chore: remove stale setup scripts, skills, and evals

Remove artifacts from pre-commit migration and cleanup:
- scripts/setup-gitleaks.sh, scripts/gitleaks.toml: legacy setup scripts
- tests/test-setup-gitleaks.sh, tests/test-setup-hooks.sh: phantom test files
- plugins/bin/skills/gitleaks/: skill for deprecated shell-based setup
- plugins/bin/evals/cross-cutting/gitleaks/: eval for deleted skill
- plugins/bin/evals/cross-cutting/neuledge-context/: out-of-scope eval
- plugins/bin/evals/implement/write-docs/: incomplete eval
- package.json, package-lock.json: markdownlint dependencies (unused)

All validation now managed by .pre-commit-config.yaml.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-06-27 19:04:53 +00:00
parent 4cbc993af4
commit 5b8b6f529c
12 changed files with 0 additions and 1818 deletions

853
package-lock.json generated
View File

@@ -1,853 +0,0 @@
{
"name": "ai-development",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"devDependencies": {
"markdownlint": "^0.41.0"
}
},
"node_modules/@types/debug": {
"version": "4.1.13",
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz",
"integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/ms": "*"
}
},
"node_modules/@types/katex": {
"version": "0.16.8",
"resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.8.tgz",
"integrity": "sha512-trgaNyfU+Xh2Tc+ABIb44a5AYUpicB3uwirOioeOkNPPbmgRNtcWyDeeFRzjPZENO9Vq8gvVqfhaaXWLlevVwg==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/ms": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz",
"integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/unist": {
"version": "2.0.11",
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
"integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
"dev": true,
"license": "MIT"
},
"node_modules/ansi-regex": {
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
"integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/character-entities": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz",
"integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==",
"dev": true,
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/character-entities-legacy": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz",
"integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==",
"dev": true,
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/character-reference-invalid": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz",
"integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==",
"dev": true,
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/commander": {
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
"integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 12"
}
},
"node_modules/debug": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"dev": true,
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/decode-named-character-reference": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz",
"integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"character-entities": "^2.0.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/dequal": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
"integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/devlop": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz",
"integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==",
"dev": true,
"license": "MIT",
"dependencies": {
"dequal": "^2.0.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/get-east-asian-width": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz",
"integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-alphabetical": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz",
"integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==",
"dev": true,
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/is-alphanumerical": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz",
"integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==",
"dev": true,
"license": "MIT",
"dependencies": {
"is-alphabetical": "^2.0.0",
"is-decimal": "^2.0.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/is-decimal": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz",
"integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==",
"dev": true,
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/is-hexadecimal": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz",
"integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==",
"dev": true,
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/katex": {
"version": "0.16.47",
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.47.tgz",
"integrity": "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==",
"dev": true,
"funding": [
"https://opencollective.com/katex",
"https://github.com/sponsors/katex"
],
"license": "MIT",
"dependencies": {
"commander": "^8.3.0"
},
"bin": {
"katex": "cli.js"
}
},
"node_modules/markdownlint": {
"version": "0.41.0",
"resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.41.0.tgz",
"integrity": "sha512-xMUI3ChBuRuxuLF4ENvCZyS8z/+Jly1coUcZwErKLIB3sDj7ojpaTBa1e9YVPhSN4jGEIjYGQCldbTJS/hqS+A==",
"dev": true,
"license": "MIT",
"dependencies": {
"micromark": "4.0.2",
"micromark-core-commonmark": "2.0.3",
"micromark-extension-directive": "4.0.0",
"micromark-extension-gfm-autolink-literal": "2.1.0",
"micromark-extension-gfm-footnote": "2.1.0",
"micromark-extension-gfm-table": "2.1.1",
"micromark-extension-math": "3.1.0",
"micromark-util-types": "2.0.2",
"string-width": "8.2.1"
},
"engines": {
"node": ">=22"
},
"funding": {
"url": "https://github.com/sponsors/DavidAnson"
}
},
"node_modules/micromark": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz",
"integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"license": "MIT",
"dependencies": {
"@types/debug": "^4.0.0",
"debug": "^4.0.0",
"decode-named-character-reference": "^1.0.0",
"devlop": "^1.0.0",
"micromark-core-commonmark": "^2.0.0",
"micromark-factory-space": "^2.0.0",
"micromark-util-character": "^2.0.0",
"micromark-util-chunked": "^2.0.0",
"micromark-util-combine-extensions": "^2.0.0",
"micromark-util-decode-numeric-character-reference": "^2.0.0",
"micromark-util-encode": "^2.0.0",
"micromark-util-normalize-identifier": "^2.0.0",
"micromark-util-resolve-all": "^2.0.0",
"micromark-util-sanitize-uri": "^2.0.0",
"micromark-util-subtokenize": "^2.0.0",
"micromark-util-symbol": "^2.0.0",
"micromark-util-types": "^2.0.0"
}
},
"node_modules/micromark-core-commonmark": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz",
"integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"license": "MIT",
"dependencies": {
"decode-named-character-reference": "^1.0.0",
"devlop": "^1.0.0",
"micromark-factory-destination": "^2.0.0",
"micromark-factory-label": "^2.0.0",
"micromark-factory-space": "^2.0.0",
"micromark-factory-title": "^2.0.0",
"micromark-factory-whitespace": "^2.0.0",
"micromark-util-character": "^2.0.0",
"micromark-util-chunked": "^2.0.0",
"micromark-util-classify-character": "^2.0.0",
"micromark-util-html-tag-name": "^2.0.0",
"micromark-util-normalize-identifier": "^2.0.0",
"micromark-util-resolve-all": "^2.0.0",
"micromark-util-subtokenize": "^2.0.0",
"micromark-util-symbol": "^2.0.0",
"micromark-util-types": "^2.0.0"
}
},
"node_modules/micromark-extension-directive": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-4.0.0.tgz",
"integrity": "sha512-/C2nqVmXXmiseSSuCdItCMho7ybwwop6RrrRPk0KbOHW21JKoCldC+8rFOaundDoRBUWBnJJcxeA/Kvi34WQXg==",
"dev": true,
"license": "MIT",
"dependencies": {
"devlop": "^1.0.0",
"micromark-factory-space": "^2.0.0",
"micromark-factory-whitespace": "^2.0.0",
"micromark-util-character": "^2.0.0",
"micromark-util-symbol": "^2.0.0",
"micromark-util-types": "^2.0.0",
"parse-entities": "^4.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/micromark-extension-gfm-autolink-literal": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz",
"integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==",
"dev": true,
"license": "MIT",
"dependencies": {
"micromark-util-character": "^2.0.0",
"micromark-util-sanitize-uri": "^2.0.0",
"micromark-util-symbol": "^2.0.0",
"micromark-util-types": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/micromark-extension-gfm-footnote": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz",
"integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==",
"dev": true,
"license": "MIT",
"dependencies": {
"devlop": "^1.0.0",
"micromark-core-commonmark": "^2.0.0",
"micromark-factory-space": "^2.0.0",
"micromark-util-character": "^2.0.0",
"micromark-util-normalize-identifier": "^2.0.0",
"micromark-util-sanitize-uri": "^2.0.0",
"micromark-util-symbol": "^2.0.0",
"micromark-util-types": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/micromark-extension-gfm-table": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz",
"integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==",
"dev": true,
"license": "MIT",
"dependencies": {
"devlop": "^1.0.0",
"micromark-factory-space": "^2.0.0",
"micromark-util-character": "^2.0.0",
"micromark-util-symbol": "^2.0.0",
"micromark-util-types": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/micromark-extension-math": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz",
"integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/katex": "^0.16.0",
"devlop": "^1.0.0",
"katex": "^0.16.0",
"micromark-factory-space": "^2.0.0",
"micromark-util-character": "^2.0.0",
"micromark-util-symbol": "^2.0.0",
"micromark-util-types": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/micromark-factory-destination": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz",
"integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"license": "MIT",
"dependencies": {
"micromark-util-character": "^2.0.0",
"micromark-util-symbol": "^2.0.0",
"micromark-util-types": "^2.0.0"
}
},
"node_modules/micromark-factory-label": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz",
"integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"license": "MIT",
"dependencies": {
"devlop": "^1.0.0",
"micromark-util-character": "^2.0.0",
"micromark-util-symbol": "^2.0.0",
"micromark-util-types": "^2.0.0"
}
},
"node_modules/micromark-factory-space": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz",
"integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"license": "MIT",
"dependencies": {
"micromark-util-character": "^2.0.0",
"micromark-util-types": "^2.0.0"
}
},
"node_modules/micromark-factory-title": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz",
"integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"license": "MIT",
"dependencies": {
"micromark-factory-space": "^2.0.0",
"micromark-util-character": "^2.0.0",
"micromark-util-symbol": "^2.0.0",
"micromark-util-types": "^2.0.0"
}
},
"node_modules/micromark-factory-whitespace": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz",
"integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"license": "MIT",
"dependencies": {
"micromark-factory-space": "^2.0.0",
"micromark-util-character": "^2.0.0",
"micromark-util-symbol": "^2.0.0",
"micromark-util-types": "^2.0.0"
}
},
"node_modules/micromark-util-character": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz",
"integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"license": "MIT",
"dependencies": {
"micromark-util-symbol": "^2.0.0",
"micromark-util-types": "^2.0.0"
}
},
"node_modules/micromark-util-chunked": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz",
"integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"license": "MIT",
"dependencies": {
"micromark-util-symbol": "^2.0.0"
}
},
"node_modules/micromark-util-classify-character": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz",
"integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"license": "MIT",
"dependencies": {
"micromark-util-character": "^2.0.0",
"micromark-util-symbol": "^2.0.0",
"micromark-util-types": "^2.0.0"
}
},
"node_modules/micromark-util-combine-extensions": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz",
"integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"license": "MIT",
"dependencies": {
"micromark-util-chunked": "^2.0.0",
"micromark-util-types": "^2.0.0"
}
},
"node_modules/micromark-util-decode-numeric-character-reference": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz",
"integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"license": "MIT",
"dependencies": {
"micromark-util-symbol": "^2.0.0"
}
},
"node_modules/micromark-util-encode": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz",
"integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"license": "MIT"
},
"node_modules/micromark-util-html-tag-name": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz",
"integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"license": "MIT"
},
"node_modules/micromark-util-normalize-identifier": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz",
"integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"license": "MIT",
"dependencies": {
"micromark-util-symbol": "^2.0.0"
}
},
"node_modules/micromark-util-resolve-all": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz",
"integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"license": "MIT",
"dependencies": {
"micromark-util-types": "^2.0.0"
}
},
"node_modules/micromark-util-sanitize-uri": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz",
"integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"license": "MIT",
"dependencies": {
"micromark-util-character": "^2.0.0",
"micromark-util-encode": "^2.0.0",
"micromark-util-symbol": "^2.0.0"
}
},
"node_modules/micromark-util-subtokenize": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz",
"integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"license": "MIT",
"dependencies": {
"devlop": "^1.0.0",
"micromark-util-chunked": "^2.0.0",
"micromark-util-symbol": "^2.0.0",
"micromark-util-types": "^2.0.0"
}
},
"node_modules/micromark-util-symbol": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz",
"integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"license": "MIT"
},
"node_modules/micromark-util-types": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz",
"integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"license": "MIT"
},
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true,
"license": "MIT"
},
"node_modules/parse-entities": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz",
"integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/unist": "^2.0.0",
"character-entities-legacy": "^3.0.0",
"character-reference-invalid": "^2.0.0",
"decode-named-character-reference": "^1.0.0",
"is-alphanumerical": "^2.0.0",
"is-decimal": "^2.0.0",
"is-hexadecimal": "^2.0.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/string-width": {
"version": "8.2.1",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.1.tgz",
"integrity": "sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==",
"dev": true,
"license": "MIT",
"dependencies": {
"get-east-asian-width": "^1.5.0",
"strip-ansi": "^7.1.2"
},
"engines": {
"node": ">=20"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/strip-ansi": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz",
"integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==",
"dev": true,
"license": "MIT",
"dependencies": {
"ansi-regex": "^6.2.2"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
}
}
}

View File

@@ -1,5 +0,0 @@
{
"devDependencies": {
"markdownlint": "^0.41.0"
}
}

View File

@@ -1,84 +0,0 @@
skill_name: gitleaks
trigger_tests:
- id: explicit-trigger-install
name: Explicit trigger — install and configure
query: "set up gitleaks in this repo"
should_trigger: true
- id: explicit-trigger-update-hook
name: Explicit trigger — update hook
query: "update the gitleaks pre-commit hook"
should_trigger: true
- id: implicit-trigger-false-positive
name: Implicit trigger — suppress false positive in pre-commit hook
query: "my pre-commit hook keeps blocking commits because it thinks my test fixture has an API key, how do I suppress it?"
should_trigger: true
- id: implicit-trigger-scan-history
name: Implicit trigger — audit repo history for secrets
query: "I want to scan my entire git history to make sure no credentials were ever committed"
should_trigger: true
- id: negative-trigger-security-review
name: Negative trigger — general code security review
query: "do a security review of this pull request"
should_trigger: false
- id: negative-trigger-ci-scan
name: Negative trigger — CI pipeline secret scanning
query: "add secret scanning to my GitHub Actions CI pipeline"
should_trigger: false
- id: negative-trigger-other-tool
name: Negative trigger — different secret scanning tool
query: "trufflehog is flagging false positives in my repo, how do I configure it?"
should_trigger: false
output_tests:
- id: output-states-intent-before-running
name: Deterministic — states intent and waits for confirmation before running setup script
type: deterministic
prompt: "set up gitleaks in /home/user/myproject"
expected_output: >
The skill states what it is about to do (run setup-gitleaks.sh, which will modify
.git/hooks/pre-commit and seed .gitleaks.toml) and asks for confirmation before
executing the script. The confirmation request appears before any Bash command
that runs the script.
assertions:
- "Output contains 'setup-gitleaks.sh' before any Bash tool invocation that runs it"
- "Output contains a confirmation prompt (e.g. 'Proceed?') before running the setup script"
- "Output does not run the setup script without an explicit confirmation step"
- id: output-redacts-secret-values
name: Deterministic — redacts secret value and prescribes rotation before history rewrite
type: deterministic
prompt: "gitleaks found an AWS secret key on line 42 of config/settings.py — it says the value is AKIAIOSFODNN7EXAMPLE. What do I do?"
expected_output: >
The skill does not echo or repeat the secret value. It references the finding by
rule ID, file path, and line number only. It states that the secret must be rotated
immediately. It mentions git filter-repo (not git filter-branch) for history rewrite
and asks for user confirmation before running the rewrite.
assertions:
- "Output does not contain the literal string 'AKIAIOSFODNN7EXAMPLE'"
- "Output mentions rotating or revoking the credential as the first action"
- "Output references 'git filter-repo' for history rewrite, not 'git filter-branch'"
- "Output states that user confirmation is required before running the history rewrite"
- id: output-quality-allowlist-guidance
name: LLM-rubric — allowlist guidance is correct, version-aware, and minimal
type: llm-rubric
prompt: "gitleaks keeps flagging my docs/research/ directory as containing secrets, how do I suppress it?"
expected_output: >
High-quality output checks the installed gitleaks version before prescribing any
TOML syntax, recommends a path-based allowlist entry in .gitleaks.toml (not a
.gitleaksignore fingerprint), uses the correct TOML syntax for the detected version,
adds only the minimal allowlist entry needed for the identified false positive, and
includes a verification step (re-run gitleaks dir -v or gitleaks dir --log-level debug)
after making the change.
assertions:
- "Output checks or asks about the gitleaks version before writing TOML syntax"
- "Output recommends a path-based allowlist entry in .gitleaks.toml rather than .gitleaksignore"
- "Output includes a command to verify the suppression works after the change"
- "Output explains why .gitleaksignore fingerprints are fragile (line numbers shift)"

View File

@@ -1,97 +0,0 @@
skill_name: neuledge-context
trigger_tests:
- id: explicit-install-register
name: "Explicit trigger — install and register"
query: "install @neuledge/context and register it as an MCP server in Claude Code"
should_trigger: true
- id: explicit-package-management
name: "Explicit trigger — package management"
query: "install the react documentation package using neuledge context"
should_trigger: true
- id: implicit-offline-docs
name: "Implicit trigger — offline docs for AI agent"
query: "I need React and Next.js docs available to my AI agent without web searches"
should_trigger: true
- id: negative-different-mcp
name: "Negative — different MCP server"
query: "Add the Gitea MCP server to Claude Code"
should_trigger: false
- id: negative-query-existing
name: "Negative — querying an already-running server"
query: "How do I query React docs using the context server that's already running?"
should_trigger: false
- id: negative-cursor-setup
name: "Negative — different provider"
query: "Set up context serve for Cursor"
should_trigger: false
output_tests:
- id: install-script-announced
name: "Install — script announced before running, version verified after"
type: deterministic
prompt: "install @neuledge/context"
expected_output: >
The skill announces that it will run scripts/setup-neuledge-context.sh before executing it,
then verifies the installation by running `context --version`.
assertions:
- "Output mentions 'scripts/setup-neuledge-context.sh' before any install command is run"
- "Output includes a `context --version` call after the install step"
- "Output does not contain `npm install -g @neuledge/context@latest` (no floating @latest)"
- id: mcp-list-before-add
name: "MCP registration — list checked before add, skipped if present"
type: deterministic
prompt: "register @neuledge/context as a Claude Code MCP server"
expected_output: >
The skill runs `claude mcp list` and checks for an existing 'context' entry before
running `claude mcp add`. If already registered, the add step is skipped.
assertions:
- "Output includes `claude mcp list` before `claude mcp add context`"
- "Output states that registration is skipped when the server is already present"
- "The `claude mcp add` command uses stdio form: `claude mcp add context -- context serve`"
- id: auth-chmod-paired
name: "Auth — secure-context-config.sh run immediately after auth add"
type: deterministic
prompt: "add auth credentials for docs.example.com to neuledge context"
expected_output: >
The skill runs `context auth add docs.example.com` with an environment variable reference
for the credential, then immediately runs scripts/secure-context-config.sh.
No credential value appears in the output.
assertions:
- "Output references an environment variable (e.g. $TOKEN) rather than a literal credential value"
- "Output runs `scripts/secure-context-config.sh` in the same step as or immediately after `context auth add`"
- "No bearer token, cookie value, or other credential string appears in the output"
- id: git-check-url-source
name: "context add — git prerequisite checked for URL sources only"
type: deterministic
prompt: "add documentation from https://github.com/prisma/prisma using context add"
expected_output: >
Before running `context add`, the skill checks `git --version` because the source is a
GitHub URL. The check is present for URL/repo sources and absent for local .db file paths.
assertions:
- "Output includes `git --version` before the `context add https://github.com/...` command"
- "If given a local .db file path instead, the git check is absent"
- id: install-flow-quality
name: "Full install + register flow quality"
type: llm-rubric
prompt: "install @neuledge/context and set it up as my Claude Code MCP server"
expected_output: >
A complete, ordered install-then-register flow: (1) announce the install script,
(2) run setup-neuledge-context.sh, (3) verify with context --version,
(4) check claude mcp list, (5) run claude mcp add if not already registered,
(6) confirm with claude mcp list. Steps are in the correct order with verification
between install and registration.
assertions:
- "Install step comes before MCP registration step"
- "A verification command (context --version) appears between install and registration"
- "The output would leave a user with a working @neuledge/context MCP server in Claude Code"
- "No step is skipped without an explanation of why it was skipped"

View File

@@ -1,61 +0,0 @@
skill_name: write-docs
trigger_tests:
- id: explicit-trigger-document-module
name: "Explicit trigger — document a script"
query: "Write documentation for the install.sh script"
should_trigger: true
- id: explicit-trigger-create-docs
name: "Explicit trigger — create docs for a feature"
query: "Create docs for this feature"
should_trigger: true
- id: implicit-trigger-readme-update
name: "Implicit trigger — outdated README section, no trigger phrase"
query: "We need to update the README section for the auth module, the current one is outdated"
should_trigger: true
- id: negative-trigger-prd
name: "Negative — PRD request should route to to-prd"
query: "Write a PRD for the new logging feature"
should_trigger: false
- id: negative-trigger-write-skill
name: "Negative — skill authoring request should route to write-skill"
query: "Write a skill for generating documentation automatically"
should_trigger: false
- id: negative-trigger-skill-file
name: "Negative — SKILL.md update (skill files are self-describing)"
query: "Document how the write-docs skill works by updating its SKILL.md"
should_trigger: false
output_tests:
- id: output-proposes-files-before-reading
name: "Deterministic — candidates proposed or approval sought before reading files"
type: deterministic
prompt: "Write documentation for the config module"
expected_output: "Skill proposes candidate files or asks the user to name specific files before reading any file content"
assertions:
- "Response proposes candidate file paths or asks the user to confirm which files to read before showing any extracted content"
- "Response does not display extracted code content or API surface without first receiving file approval"
- id: output-gap-check-present
name: "Deterministic — gap check step present before drafting"
type: deterministic
prompt: "Write documentation for the install.sh script, audience: developer"
expected_output: "Skill presents extracted behaviour to the user and asks them to fill gaps before drafting any section"
assertions:
- "Response includes a gap check step that presents extracted behaviour and asks what the code does not explain"
- "Response does not skip directly to a drafted documentation section without presenting extracted content first"
- id: output-never-invents-behaviour
name: "LLM rubric — no invented behaviour, all claims sourced"
type: llm-rubric
prompt: "Document the src/config.py file for internal developers"
expected_output: "Documentation where every claim is attributed to code content or explicit user input, with no invented explanations, assumptions about intent, or unverifiable behaviour claims."
assertions:
- "The skill explicitly derives each documented claim from a named source — a code line, spec section, or user statement — and does not add claims without attribution"
- "The skill does not include descriptions of caller intent, design rationale, or future behaviour that are not present in the source material"
- "If a behaviour is undocumentable (internal detail with no public spec), the skill notes it as out-of-scope rather than inventing an explanation"

View File

@@ -1,15 +0,0 @@
```yaml
version: "1.0"
updated: 2026-06-20
when: >
Invoked when the user wants to install gitleaks and wire it as a git pre-commit secret
scanner, update the hook in an existing repo, tune allowlist rules to suppress false
positives, debug a scan finding, or rotate a real secret that was found. Covers the full
lifecycle: install → configure → maintain → remediate. Not invoked for general code
security review (security-review skill) or CI pipeline secret scanning (write-ci-pipeline skill).
references:
- https://github.com/gitleaks/gitleaks/releases/tag/v8.24.2
- https://github.com/gitleaks/gitleaks/blob/main/README.md
```

View File

@@ -1,111 +0,0 @@
---
name: gitleaks
description: Use when the user wants to install gitleaks, wire it as a git pre-commit secret scanner, update the hook in an existing repo, tune allowlist rules, resolve false positives, or debug a gitleaks scan finding. Do NOT use when the user wants a general security review of code (use security-review), wants to add secret scanning to a CI pipeline (use write-ci-pipeline), or is asking about a different secret scanning tool such as trufflehog or git-secrets.
metadata:
category: cross-cutting
allowed-tools:
- Bash
- Read
- Edit
---
<requirements>
## Required inputs
- **Target repo path** — absolute path to the git repository to configure; inferred from current working directory if not stated, ask if ambiguous
- **Task type** — install/configure, update hook, tune allowlist, debug finding; inferred from the user's request
## Constraints
- Always state what you are about to do before running `setup-gitleaks.sh` — the script modifies `.git/hooks/pre-commit` and seeds `.gitleaks.toml`
- Never modify `.gitleaks.toml` if the user has not asked for allowlist changes — it is project-owned once seeded; treat it as user-controlled config
- Never run `gitleaks git` or `gitleaks dir` across the full history without warning the user it may be slow on large repos
- Redact any secret values that appear in gitleaks output before showing them to the user — show the rule ID, file, and line number only
- When the installed gitleaks version is unknown, check it with `gitleaks version` before suggesting config syntax — v8.24.2 uses `[allowlist]`; v8.25.0+ uses `[[allowlists]]`
- False positive suppression: prefer path-based allowlists in `.gitleaks.toml` over fingerprint-based entries in `.gitleaksignore` — fingerprints are line-number-sensitive and break on file edits
</requirements>
<steps>
## Process
### Install and configure
1. **Confirm target.** State: "I will run `scripts/setup-gitleaks.sh <path>` which will install gitleaks (if absent), seed `.gitleaks.toml` (first run only), and write the pre-commit hook. Proceed?" Wait for confirmation — this modifies the repo's git hook.
2. **Run setup script.** Execute from the ai-development repo root:
```
bash scripts/setup-gitleaks.sh <TARGET_REPO>
```
The script is idempotent — it replaces the gitleaks block in the hook on every run without disturbing other hook content.
3. **Verify installation.** Run `gitleaks version` to confirm the binary is available. Run `gitleaks git --staged --redact -v` in the target repo to confirm the hook would work on a staged commit (add a dummy change if needed to test).
4. **Commit `.gitleaks.toml`.** Remind the user that `.gitleaks.toml` belongs in version control so all contributors share the same allowlist rules.
### Update hook
Re-run `bash scripts/setup-gitleaks.sh <TARGET_REPO>` from the ai-development repo root. The managed block (delimited by `# managed by setup-gitleaks.sh` / `# end gitleaks` markers) is always replaced with the current version. Non-gitleaks hook content is preserved.
### Tune allowlist / resolve false positives
1. **Identify the false positive.** Run `gitleaks dir --log-level debug <path>` to see which rule fired and which allowlist entries (if any) are already active.
2. **Check the gitleaks version.** Run `gitleaks version`. Use `[allowlist]` syntax for v8.24.2; use `[[allowlists]]` syntax for v8.25.0+. Using the wrong syntax silently produces no errors but the allowlist does nothing — this is the most common configuration trap.
3. **Choose suppression strategy.** Read `.gitleaks.toml` first. See `references/allowlist-patterns.md` for syntax examples and when to use each approach:
- Path regex in `[allowlist]` — for files that can never contain real secrets (research notes, terminal captures, test fixtures). Preferred.
- Stopwords in `[allowlist]` — for placeholder patterns like "example", "changeme".
- `disabledRules` in `[extend]` — to disable a noisy default rule entirely. Use only when the rule has no value for this repo.
- `.gitleaksignore` fingerprint — last resort; breaks when the file is edited because line numbers shift.
4. **Edit `.gitleaks.toml`.** Add the minimal allowlist entry needed. Do not suppress more than the identified false positive.
5. **Verify.** Re-run `gitleaks dir -v <path>` or `gitleaks git -v` to confirm the false positive is suppressed and no real findings are hidden.
### Scan modes
| Mode | Command | When to use |
|---|---|---|
| Staged changes (pre-commit) | `gitleaks git --staged --redact -v` | What the hook runs |
| Full commit history | `gitleaks git -v` | Audit existing repo history |
| Working directory files | `gitleaks dir -v <path>` | Scan uncommitted files |
| Debug allowlists | `gitleaks dir --log-level debug <path>` | See which files are skipped and which allowlists fire |
### Resolve a real finding
1. Do not redact or show the secret value. Reference the rule ID, file, and line number only.
2. The secret is compromised the moment it was committed — rotate it immediately, regardless of whether the commit is reachable from the public remote.
3. Remove the secret from history using `git filter-repo` (not `git filter-branch`). This is a history-rewrite — confirm with the user before running. Force-push to all remotes after rewriting.
4. Add the file path to the `.gitleaks.toml` allowlist only if the file is known to be a false-positive source going forward (e.g. a test fixture). Do not add an allowlist entry to suppress a real finding that has been removed.
## Output format
No structured output file. The skill produces:
- Modified `.git/hooks/pre-commit` in the target repo (via the setup script)
- Modified `.gitleaks.toml` in the target repo (allowlist changes only, when requested)
- Terminal confirmation of what was changed and what to do next
</steps>
<checks>
## Failure handling
- `setup-gitleaks.sh` not found — stop; instruct the user to run from the ai-development repo root at `/root/ai-development/`
- Target path is not a git repository — report the error from the script and ask the user to confirm the correct path
- `gitleaks` binary not installed and download fails — report the curl/network error; direct the user to manual install at `https://github.com/gitleaks/gitleaks/releases`
- Wrong TOML syntax for installed version — detect via `gitleaks version`, show the correct syntax for that version, do not guess
## Self-check
- [ ] Target repo confirmed before running the setup script
- [ ] `gitleaks version` checked before writing any `.gitleaks.toml` allowlist syntax
- [ ] Secret values in scan output redacted before displaying to the user
- [ ] `.gitleaks.toml` edits are minimal — only the identified false positive suppressed
- [ ] After any allowlist change: re-ran scan to verify suppression works and no real findings are hidden
- [ ] For real findings: rotation step stated before history rewrite, user confirmed history rewrite before running `git filter-repo`
</checks>

View File

@@ -1,83 +0,0 @@
# Gitleaks allowlist patterns
## Version syntax
| Version | Allowlist syntax |
|---|---|
| v8.24.2 and earlier | `[allowlist]` (singular table) |
| v8.25.0 and later | `[[allowlists]]` (array of tables) |
**Critical**: using the wrong syntax produces no error but the allowlist silently does nothing. Always check `gitleaks version` first.
## v8.24.2 syntax (this repo uses 8.24.2)
### Suppress by path regex
Use for files that can never contain real secrets (research notes, terminal captures, test fixtures, generated docs).
```toml
[allowlist]
description = "research notes and terminal captures"
paths = [
'''docs/research/.*''',
'''tests/fixtures/.*''',
]
```
### Suppress by stopword
Use for placeholder values that match secret patterns but are clearly not real.
```toml
[allowlist]
description = "placeholder values"
stopwords = ["example", "placeholder", "changeme", "your-api-key-here"]
```
### Disable a default rule entirely
Use only when a rule has no value for this repo and produces pervasive false positives.
```toml
[extend]
useDefault = true
disabledRules = ["generic-api-key"]
```
## v8.25.0+ syntax (for reference)
```toml
[[allowlists]]
description = "research notes"
paths = ['''docs/research/.*''']
[[allowlists]]
description = "placeholder values"
stopwords = ["example", "placeholder"]
```
## .gitleaksignore (fingerprint-based — last resort)
```
# Format: <fingerprint>:<line-number>
# Generated by: gitleaks git -v --report-format json | jq -r '.[] | "\(.Fingerprint):\(.StartLine)"'
abc123def456:42
```
Avoid this approach: fingerprints embed line numbers. Any edit to the file shifts line numbers and invalidates the entry, re-surfacing the false positive.
## Verification after any change
```bash
# Scan current files
gitleaks dir -v .
# Scan with debug output to see which allowlists fired
gitleaks dir --log-level debug .
# Scan commit history
gitleaks git -v
# Scan only staged changes (what the pre-commit hook runs)
gitleaks git --staged --redact -v
```

View File

@@ -1,24 +0,0 @@
title = "gitleaks config"
[extend]
# Extends the default ruleset built into gitleaks.
# Remove useDefault and define [[rules]] from scratch if you want full control.
useDefault = true
# Rules to disable from the default set — uncomment and add IDs for known false positives.
# Run `gitleaks git -v` on your repo first to discover which rules fire.
# disabledRules = ["generic-api-key"]
# Global allowlist — applies to all rules.
# Note: uses [allowlist] (v8 syntax). v8.25.0+ uses [[allowlists]] (array of tables).
# Add path regexes or stopwords to suppress known false positives.
[allowlist]
description = "Known false positives — prose patterns and research session notes"
# docs/research/: high-entropy text from terminal captures in session notes
# docs/ROADMAP.md: documents known false positives, triggering the same rules
# ai-coding-factory-session.md:90 specifically: 'Token routing: Haiku/Sonnet/Opus'
paths = [
'''docs/research/.*''',
'''docs/ROADMAP\.md''',
]

View File

@@ -1,124 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# Sets up gitleaks as a git pre-commit hook in a target repository.
# Usage: setup-gitleaks.sh [TARGET_REPO]
# TARGET_REPO — path to the git repo to configure (default: current directory)
# Idempotent: safe to re-run; always replaces the hook block with the current version.
GITLEAKS_VERSION="8.24.2"
GITLEAKS_INSTALL_DIR="${GITLEAKS_INSTALL_DIR:-/usr/local/bin}"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
TARGET="${1:-$(pwd)}"
HOOK_FILE="$TARGET/.git/hooks/pre-commit"
CONFIG_SRC="$SCRIPT_DIR/gitleaks.toml"
CONFIG_DEST="$TARGET/.gitleaks.toml"
MARKER="# managed by setup-gitleaks.sh"
END_MARKER="# end gitleaks"
# --- Install gitleaks if not present ---
install_gitleaks() {
local os arch tarball url tmp_dir
case "$(uname -s)" in
Linux) os="linux" ;;
Darwin) os="darwin" ;;
*)
echo "Error: unsupported OS '$(uname -s)' — install gitleaks manually from https://github.com/gitleaks/gitleaks/releases" >&2
exit 1
;;
esac
case "$(uname -m)" in
x86_64) arch="x64" ;;
aarch64 | arm64) arch="arm64" ;;
*)
echo "Error: unsupported architecture '$(uname -m)' — install gitleaks manually from https://github.com/gitleaks/gitleaks/releases" >&2
exit 1
;;
esac
tarball="gitleaks_${GITLEAKS_VERSION}_${os}_${arch}.tar.gz"
url="https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/${tarball}"
tmp_dir="$(mktemp -d)"
trap 'rm -rf "$tmp_dir"' RETURN
echo "Installing gitleaks v${GITLEAKS_VERSION}..."
curl -fsSL "$url" -o "$tmp_dir/$tarball"
tar -xzf "$tmp_dir/$tarball" -C "$tmp_dir" gitleaks
install -m 755 "$tmp_dir/gitleaks" "$GITLEAKS_INSTALL_DIR/gitleaks"
echo "Installed: $GITLEAKS_INSTALL_DIR/gitleaks"
}
if ! command -v gitleaks &>/dev/null; then
install_gitleaks
fi
# --- Validate ---
if [ ! -d "$TARGET/.git" ]; then
echo "Error: $TARGET is not a git repository" >&2
exit 1
fi
if [ ! -f "$CONFIG_SRC" ]; then
echo "Error: config template not found at $CONFIG_SRC" >&2
exit 1
fi
# --- Deploy config ---
if [ -f "$CONFIG_DEST" ]; then
echo "Skipped: $CONFIG_DEST already exists — edit it directly to customise rules."
else
cp "$CONFIG_SRC" "$CONFIG_DEST"
echo "Wrote: $CONFIG_DEST"
echo " Commit this file — it belongs in version control."
fi
# --- Deploy hook ---
hook_block() {
cat <<BLOCK
$MARKER
if command -v gitleaks &>/dev/null; then
gitleaks git --staged --redact -v
else
echo "Warning: gitleaks not installed — secret scan skipped (https://github.com/gitleaks/gitleaks/releases)" >&2
fi
$END_MARKER
BLOCK
}
write_hook() {
local hook_file="$1"
if grep -qF "$MARKER" "$hook_file"; then
# Remove old block (start marker through end marker inclusive) then append current version
awk -v start="$MARKER" -v end="$END_MARKER" '
$0 == start { skip=1; next }
skip && $0 == end { skip=0; next }
!skip { print }
' "$hook_file" > "${hook_file}.tmp" && mv "${hook_file}.tmp" "$hook_file"
hook_block >> "$hook_file"
echo "Updated: $hook_file (gitleaks block replaced)"
else
hook_block >> "$hook_file"
echo "Updated: $hook_file (gitleaks block appended to existing hook)"
fi
}
if [ -f "$HOOK_FILE" ]; then
write_hook "$HOOK_FILE"
else
{ echo '#!/usr/bin/env bash'; echo 'set -euo pipefail'; hook_block; } > "$HOOK_FILE"
chmod +x "$HOOK_FILE"
echo "Created: $HOOK_FILE"
fi
echo ""
echo "Done. Staged secrets will be scanned on every commit in $TARGET."
echo "To skip on a single commit: SKIP=gitleaks git commit ..."

View File

@@ -1,151 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
SCRIPT="$REPO_ROOT/scripts/setup-gitleaks.sh"
PASS=0
FAIL=0
pass() { echo " PASS: $1"; PASS=$((PASS + 1)); }
fail() { echo " FAIL: $1"; FAIL=$((FAIL + 1)); }
# Fake gitleaks binary — prevents the install step from running during tests
FAKE_BIN="$(mktemp -d)"
trap 'rm -rf "$FAKE_BIN"' EXIT
printf '#!/bin/sh\necho "gitleaks fake"\n' > "$FAKE_BIN/gitleaks"
chmod +x "$FAKE_BIN/gitleaks"
export PATH="$FAKE_BIN:$PATH"
# Helper: create an isolated git repo in a temp dir
make_repo() {
local dir
dir="$(mktemp -d)"
git -C "$dir" init -q
echo "$dir"
}
# Helper: run setup script against a target repo; capture output; always return exit code
run_setup() {
local target="$1"
bash "$SCRIPT" "$target" 2>&1
}
# --- 1. Rejects non-git directory ---
echo ""
echo "--- rejects non-git directory ---"
NON_GIT="$(mktemp -d)"
trap 'rm -rf "$NON_GIT"' EXIT
if bash "$SCRIPT" "$NON_GIT" >/dev/null 2>&1; then
fail "exited 0 for non-git directory — expected exit 1"
else
pass "exits non-zero for non-git directory"
fi
# --- 2. Config deployed ---
echo ""
echo "--- config deployed to target repo ---"
REPO="$(make_repo)"
trap 'rm -rf "$REPO"' EXIT
run_setup "$REPO" > /dev/null
if [ -f "$REPO/.gitleaks.toml" ]; then
pass ".gitleaks.toml created in target repo"
else
fail ".gitleaks.toml missing from target repo"
fi
if diff -q "$REPO_ROOT/scripts/gitleaks.toml" "$REPO/.gitleaks.toml" > /dev/null 2>&1; then
pass ".gitleaks.toml matches the template"
else
fail ".gitleaks.toml content differs from template"
fi
# --- 3. Hook created from scratch ---
echo ""
echo "--- hook created when none exists ---"
REPO2="$(make_repo)"
trap 'rm -rf "$REPO2"' EXIT
run_setup "$REPO2" > /dev/null
HOOK="$REPO2/.git/hooks/pre-commit"
if [ -f "$HOOK" ]; then
pass "pre-commit hook created"
else
fail "pre-commit hook not created"
fi
if [ -x "$HOOK" ]; then
pass "pre-commit hook is executable"
else
fail "pre-commit hook is not executable"
fi
if head -1 "$HOOK" | grep -q "^#!"; then
pass "pre-commit hook has a shebang"
else
fail "pre-commit hook missing shebang"
fi
if grep -q "gitleaks git --staged" "$HOOK"; then
pass "pre-commit hook contains gitleaks command"
else
fail "pre-commit hook missing gitleaks command"
fi
if grep -q "# managed by setup-gitleaks.sh" "$HOOK"; then
pass "pre-commit hook contains idempotency marker"
else
fail "pre-commit hook missing idempotency marker"
fi
# --- 4. Appends to existing hook; existing content retained ---
echo ""
echo "--- appends to existing hook; prior content retained ---"
REPO3="$(make_repo)"
trap 'rm -rf "$REPO3"' EXIT
HOOK3="$REPO3/.git/hooks/pre-commit"
printf '#!/usr/bin/env bash\nnpm test\n' > "$HOOK3"
chmod +x "$HOOK3"
run_setup "$REPO3" > /dev/null
if grep -q "npm test" "$HOOK3"; then
pass "existing hook content retained after append"
else
fail "existing hook content lost after append"
fi
if grep -q "gitleaks git --staged" "$HOOK3"; then
pass "gitleaks block appended to existing hook"
else
fail "gitleaks block missing after append"
fi
# --- 5. Second run replaces stale block; existing content still retained ---
echo ""
echo "--- second run replaces stale block; existing content still retained ---"
# Corrupt the gitleaks block to simulate stale content from an older version
sed -i 's/gitleaks git --staged/gitleaks protect --staged/' "$HOOK3"
run_setup "$REPO3" > /dev/null
if grep -q "npm test" "$HOOK3"; then
pass "existing content retained after block replacement"
else
fail "existing content lost after block replacement"
fi
marker_count="$(grep -c "# managed by setup-gitleaks.sh" "$HOOK3")"
if [ "$marker_count" -eq 1 ]; then
pass "gitleaks block appears exactly once after second run"
else
fail "gitleaks block duplicated — found $marker_count occurrences of marker"
fi
if grep -q "gitleaks git --staged" "$HOOK3"; then
pass "stale gitleaks command replaced with current command"
else
fail "stale gitleaks command not replaced — block was skipped, not updated"
fi
# --- 6. Third run still idempotent ---
echo ""
echo "--- repeated runs stay idempotent ---"
run_setup "$REPO3" > /dev/null
run_setup "$REPO3" > /dev/null
marker_count="$(grep -c "# managed by setup-gitleaks.sh" "$HOOK3")"
if [ "$marker_count" -eq 1 ]; then
pass "gitleaks block still appears exactly once after four total runs"
else
fail "gitleaks block duplicated — found $marker_count occurrences after four runs"
fi
echo ""
echo "Results: $PASS passed, $FAIL failed"
[[ $FAIL -eq 0 ]]

View File

@@ -1,210 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
SCRIPT="$REPO_ROOT/scripts/setup-hooks.sh"
PASS=0
FAIL=0
pass() { echo " PASS: $1"; PASS=$((PASS + 1)); }
fail() { echo " FAIL: $1"; FAIL=$((FAIL + 1)); }
# Helper: make a bare git repo with no hooks yet
make_repo() {
local dir
dir="$(mktemp -d)"
git -C "$dir" init -q
echo "$dir"
}
# Fake binaries for tools we don't want to install-check during tests
FAKE_BIN="$(mktemp -d)"
trap 'rm -rf "$FAKE_BIN"' EXIT
for tool in shellcheck jq yq; do
printf '#!/bin/sh\necho "fake %s"\n' "$tool" > "$FAKE_BIN/$tool"
chmod +x "$FAKE_BIN/$tool"
done
export PATH="$FAKE_BIN:$PATH"
# --- 1. Rejects non-git directory ---
echo ""
echo "--- rejects non-git directory ---"
NON_GIT="$(mktemp -d)"
trap 'rm -rf "$NON_GIT"' EXIT
if bash "$SCRIPT" "$NON_GIT" > /dev/null 2>&1; then
fail "exited 0 for non-git directory — expected exit 1"
else
pass "exits non-zero for non-git directory"
fi
# --- 2. Creates commit-msg hook ---
echo ""
echo "--- creates commit-msg hook ---"
REPO="$(make_repo)"
trap 'rm -rf "$REPO"' EXIT
bash "$SCRIPT" "$REPO" > /dev/null 2>&1
HOOK="$REPO/.git/hooks/commit-msg"
if [[ -f "$HOOK" ]]; then
pass "commit-msg hook file created"
else
fail "commit-msg hook not created"
fi
if [[ -x "$HOOK" ]]; then
pass "commit-msg hook is executable"
else
fail "commit-msg hook is not executable"
fi
if grep -q "# managed by setup-hooks.sh" "$HOOK"; then
pass "commit-msg hook contains idempotency marker"
else
fail "commit-msg hook missing idempotency marker"
fi
# --- 3. commit-msg hook validates conventional commits ---
echo ""
echo "--- commit-msg hook: valid message passes ---"
REPO2="$(make_repo)"
trap 'rm -rf "$REPO2"' EXIT
bash "$SCRIPT" "$REPO2" > /dev/null 2>&1
HOOK2="$REPO2/.git/hooks/commit-msg"
TMPFILE="$(mktemp)"
trap 'rm -f "$TMPFILE"' EXIT
for valid_msg in "feat: add validation" "fix(core): correct path resolution" "chore!: drop python dep" "docs: update readme" "refactor(hooks): extract marker logic"; do
echo "$valid_msg" > "$TMPFILE"
if bash "$HOOK2" "$TMPFILE" > /dev/null 2>&1; then
pass "commit-msg hook accepts: $valid_msg"
else
fail "commit-msg hook wrongly rejected: $valid_msg"
fi
done
echo ""
echo "--- commit-msg hook: invalid message is rejected ---"
for invalid_msg in "added some stuff" "WIP" "Fix the thing" "FEAT: bad case" "feat bad colon"; do
echo "$invalid_msg" > "$TMPFILE"
if bash "$HOOK2" "$TMPFILE" > /dev/null 2>&1; then
fail "commit-msg hook wrongly accepted: $invalid_msg"
else
pass "commit-msg hook rejects: $invalid_msg"
fi
done
# --- 4. Appends pre-commit validation block ---
echo ""
echo "--- appends validation block to pre-commit hook ---"
REPO3="$(make_repo)"
trap 'rm -rf "$REPO3"' EXIT
bash "$SCRIPT" "$REPO3" > /dev/null 2>&1
PRE_COMMIT="$REPO3/.git/hooks/pre-commit"
if [[ -f "$PRE_COMMIT" ]]; then
pass "pre-commit hook created"
else
fail "pre-commit hook not created"
fi
if grep -q "shellcheck" "$PRE_COMMIT"; then
pass "pre-commit hook contains shellcheck"
else
fail "pre-commit hook missing shellcheck"
fi
if grep -q "jq" "$PRE_COMMIT"; then
pass "pre-commit hook contains jq"
else
fail "pre-commit hook missing jq"
fi
if grep -q "SKILL.md" "$PRE_COMMIT"; then
pass "pre-commit hook contains SKILL.md frontmatter check"
else
fail "pre-commit hook missing SKILL.md frontmatter check"
fi
# --- 5. Creates pre-push hook ---
echo ""
echo "--- creates pre-push hook ---"
REPO4="$(make_repo)"
trap 'rm -rf "$REPO4"' EXIT
bash "$SCRIPT" "$REPO4" > /dev/null 2>&1
PUSH_HOOK="$REPO4/.git/hooks/pre-push"
if [[ -f "$PUSH_HOOK" ]]; then
pass "pre-push hook created"
else
fail "pre-push hook not created"
fi
if [[ -x "$PUSH_HOOK" ]]; then
pass "pre-push hook is executable"
else
fail "pre-push hook is not executable"
fi
if grep -q "check-manifests" "$PUSH_HOOK"; then
pass "pre-push hook calls check-manifests.sh"
else
fail "pre-push hook missing check-manifests.sh call"
fi
if grep -q "run-tests.sh" "$PUSH_HOOK"; then
pass "pre-push hook calls run-tests.sh"
else
fail "pre-push hook missing run-tests.sh call"
fi
# --- 6. Idempotent: second run replaces each block exactly once ---
echo ""
echo "--- idempotent: second run does not duplicate blocks ---"
REPO5="$(make_repo)"
trap 'rm -rf "$REPO5"' EXIT
bash "$SCRIPT" "$REPO5" > /dev/null 2>&1
bash "$SCRIPT" "$REPO5" > /dev/null 2>&1
bash "$SCRIPT" "$REPO5" > /dev/null 2>&1
for hook_file in "$REPO5/.git/hooks/commit-msg" "$REPO5/.git/hooks/pre-commit" "$REPO5/.git/hooks/pre-push"; do
count=$(grep -c "# managed by setup-hooks.sh" "$hook_file" || true)
hook_name="$(basename "$hook_file")"
if [[ "$count" -eq 1 ]]; then
pass "idempotent: $hook_name marker appears exactly once after 3 runs"
else
fail "idempotent: $hook_name marker appears $count times — block duplicated"
fi
if [[ -x "$hook_file" ]]; then
pass "idempotent: $hook_name remains executable after 3 runs"
else
fail "idempotent: $hook_name lost executable bit after repeated runs"
fi
done
# --- 7. Setup installs tools; no "not installed" warnings when tools present ---
echo ""
echo "--- setup does not warn when tools are available ---"
REPO6="$(make_repo)"
trap 'rm -rf "$REPO6"' EXIT
output6="$(bash "$SCRIPT" "$REPO6" 2>&1)"
for tool in shellcheck jq yq; do
if echo "$output6" | grep -qi "$tool not installed\|$tool.*not found"; then
fail "setup warned about missing $tool — should install or already be present"
else
pass "setup emits no 'not installed' warning for: $tool (present or installed)"
fi
done
echo ""
echo "--- pre-commit hook retains runtime fallback for missing tools ---"
PRE_COMMIT6="$REPO6/.git/hooks/pre-commit"
for tool in shellcheck jq yq; do
if grep -q "Warning:.*$tool\|$tool.*not installed\|$tool.*skipped" "$PRE_COMMIT6"; then
pass "pre-commit hook has runtime fallback for missing: $tool"
else
fail "pre-commit hook missing runtime fallback for: $tool"
fi
done
echo ""
echo "--- setup exits 0 when tools are present ---"
REPO7="$(make_repo)"
trap 'rm -rf "$REPO7"' EXIT
if bash "$SCRIPT" "$REPO7" > /dev/null 2>&1; then
pass "setup exits 0 when tools are present"
else
fail "setup exited non-zero unexpectedly"
fi
echo ""
echo "Results: $PASS passed, $FAIL failed"
[[ $FAIL -eq 0 ]]