{"_id":"@descent-vtt/spec-guard","_rev":"29-bd066da24c2f37470a8eb9f7bec332ab","name":"@descent-vtt/spec-guard","dist-tags":{"latest":"0.18.1"},"versions":{"0.1.0":{"name":"@descent-vtt/spec-guard","version":"0.1.0","keywords":["adr","architecture","documentation","drift","lint","markdown","ripgrep","spec"],"license":"MIT","_id":"@descent-vtt/spec-guard@0.1.0","maintainers":[{"name":"descent-vtt","email":"dev@descentvtt.com"}],"homepage":"https://github.com/DescentVTT/spec-guard#readme","bugs":{"url":"https://github.com/DescentVTT/spec-guard/issues"},"bin":{"spec-guard":"bin/spec-guard.js"},"dist":{"shasum":"6f4a187b547427243d52a47048ea12e4fe23fe12","tarball":"https://registry.npmjs.org/@descent-vtt/spec-guard/-/spec-guard-0.1.0.tgz","fileCount":36,"integrity":"sha512-u8Y9VtcGGO43ksZwfhHuXYuNksmtJxXPZp14AePOwMlRLOqH5ZElcVf8ner21+9ZN6LoKvJqe5b3DPhLiWvxLQ==","signatures":[{"sig":"MEQCIH9lVm8j/ig/aYbcD4EsAfzl2W1EVEYVfu8SvPUBeBm3AiBF5KCl6ulsKmKs2+WXuuy1rkTTIg84Rd6jVLUiBX9h1A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":191087},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"22d29b4dfa0d31bb44b721dd6e3f17cdc360c7eb","scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"","selfcheck":"node ./bin/spec-guard.js \"docs/**/*.md\" \"README.md\" --verbose","test:watch":"vitest","test:coverage":"vitest run --coverage","test:mutation":"stryker run","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"descent-vtt","email":"dev@descentvtt.com"},"overrides":{"qs":"^6.16.0"},"repository":{"url":"git+https://github.com/DescentVTT/spec-guard.git","type":"git"},"_npmVersion":"11.16.0","description":"Executable architecture assertions for Markdown specs & ADRs.","directories":{},"_nodeVersion":"24.18.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.11","typescript":"^7.0.2","@types/node":"^26.4.1","@vscode/ripgrep":"^1.18.0","@vitest/coverage-v8":"^4.1.11","@stryker-mutator/core":"^10.0.0","@stryker-mutator/vitest-runner":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/spec-guard_0.1.0_1788713590822_0.9927875513310007","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@descent-vtt/spec-guard","version":"0.2.0","keywords":["adr","architecture","documentation","drift","lint","markdown","ripgrep","spec"],"license":"MIT","_id":"@descent-vtt/spec-guard@0.2.0","maintainers":[{"name":"descent-vtt","email":"dev@descentvtt.com"}],"homepage":"https://github.com/DescentVTT/spec-guard#readme","bugs":{"url":"https://github.com/DescentVTT/spec-guard/issues"},"bin":{"spec-guard":"bin/spec-guard.js"},"dist":{"shasum":"bdd4fa66cf0216601a8305f482ad24aa0b8c4af3","tarball":"https://registry.npmjs.org/@descent-vtt/spec-guard/-/spec-guard-0.2.0.tgz","fileCount":36,"integrity":"sha512-bsZ4ZvO6gd5dOXjcUB0KDR/6fv7pY0UP0ybezeoO3MwzWc31lO5+DA2zwiKzM3yFnU20vPKNhhqB8WDS9JwKGg==","signatures":[{"sig":"MEUCIQDcBwGEeIK9z3uUaeprJF8sd+l1DNcR4ubP4jyh6oRI5wIgNdOQabtKD8Ow6OYIGQX6B+OnpjGDC9Df8a4ihZfVG2c=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":205820},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"4c7445a54ecd7db72f4f1ab11cd49b9c4b18e546","scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"","selfcheck":"node ./bin/spec-guard.js \"docs/**/*.md\" \"README.md\" --verbose","test:watch":"vitest","test:coverage":"vitest run --coverage","test:mutation":"stryker run","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"descent-vtt","email":"dev@descentvtt.com"},"overrides":{"qs":"^6.16.0"},"repository":{"url":"git+https://github.com/DescentVTT/spec-guard.git","type":"git"},"_npmVersion":"11.16.0","description":"Executable architecture assertions for Markdown specs & ADRs.","directories":{},"_nodeVersion":"24.18.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.11","typescript":"^7.0.2","@types/node":"^26.4.1","@vscode/ripgrep":"^1.18.0","@vitest/coverage-v8":"^4.1.11","@stryker-mutator/core":"^10.0.0","@stryker-mutator/vitest-runner":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/spec-guard_0.2.0_1788740117768_0.04021616695585295","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@descent-vtt/spec-guard","version":"0.3.0","keywords":["adr","architecture","documentation","drift","lint","markdown","ripgrep","spec"],"license":"MIT","_id":"@descent-vtt/spec-guard@0.3.0","maintainers":[{"name":"descent-vtt","email":"dev@descentvtt.com"}],"homepage":"https://github.com/DescentVTT/spec-guard#readme","bugs":{"url":"https://github.com/DescentVTT/spec-guard/issues"},"bin":{"spec-guard":"bin/spec-guard.js"},"dist":{"shasum":"54fee18ca8425371bc18d83281e58f450f2e6f9e","tarball":"https://registry.npmjs.org/@descent-vtt/spec-guard/-/spec-guard-0.3.0.tgz","fileCount":45,"integrity":"sha512-rGQJ8BMFhh2bGbkfprU//v6uQk7OR6IudNcFyRGqC5e8uXPaVx92jYBYAbiodpYXTPtGQA5xPcT0i+W+xcw+eQ==","signatures":[{"sig":"MEQCIEgEf7ZGjA/5xLuQS7I0314EQjgpE+M+mGa1t59ow8mKAiAl48+TQgf7zEZxgu+YY0cyP4gpGWUBEYDhMWvzoYb3bg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":312787},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"5271213c3098eff049d6dd74120f32fdae6b67e3","scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"","selfcheck":"node ./bin/spec-guard.js \"docs/**/*.md\" \"README.md\" --verbose","test:watch":"vitest","test:coverage":"vitest run --coverage","test:mutation":"stryker run","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"descent-vtt","email":"dev@descentvtt.com"},"overrides":{"qs":"^6.16.0"},"repository":{"url":"git+https://github.com/DescentVTT/spec-guard.git","type":"git"},"_npmVersion":"11.16.0","description":"Executable architecture assertions for Markdown specs & ADRs.","directories":{},"_nodeVersion":"24.18.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.11","typescript":"^7.0.2","@types/node":"^26.4.1","@vscode/ripgrep":"^1.18.0","@vitest/coverage-v8":"^4.1.11","@stryker-mutator/core":"^10.0.0","@stryker-mutator/vitest-runner":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/spec-guard_0.3.0_1788786778099_0.5617343769336767","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@descent-vtt/spec-guard","version":"0.4.0","keywords":["adr","architecture","documentation","drift","lint","markdown","ripgrep","spec"],"license":"MIT","_id":"@descent-vtt/spec-guard@0.4.0","maintainers":[{"name":"descent-vtt","email":"dev@descentvtt.com"}],"homepage":"https://github.com/DescentVTT/spec-guard#readme","bugs":{"url":"https://github.com/DescentVTT/spec-guard/issues"},"bin":{"spec-guard":"bin/spec-guard.js"},"dist":{"shasum":"f0b6a27f0b9445ba8d3a1b20947d1561d250b110","tarball":"https://registry.npmjs.org/@descent-vtt/spec-guard/-/spec-guard-0.4.0.tgz","fileCount":49,"integrity":"sha512-BQaBWaGQxlnUZEAF9rC0zobKrgw08Js+NzSxlv6sotHoFUc0XfoOuzdp2N3vuKRzd8Ik5XHhdLLz2za0OooOaA==","signatures":[{"sig":"MEQCIFNUU5pIchtiNyvdtCSRt6uz0euygzmCfSC/9e8IBVo+AiAUbKU8EalZR18Cg1kfrcUr0iS6QJfwCrpaAOC9qfpwEg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":333265},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"91e1cc9968db5fa0d89c271ffaa3f4fa953abdb3","scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"","selfcheck":"node ./bin/spec-guard.js \"docs/**/*.md\" \"README.md\" --verbose","test:watch":"vitest","test:coverage":"vitest run --coverage","test:mutation":"stryker run","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"descent-vtt","email":"dev@descentvtt.com"},"overrides":{"qs":"^6.16.0"},"repository":{"url":"git+https://github.com/DescentVTT/spec-guard.git","type":"git"},"_npmVersion":"11.16.0","description":"Executable architecture assertions for Markdown specs & ADRs.","directories":{},"_nodeVersion":"24.18.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.11","typescript":"^7.0.2","@types/node":"^26.4.1","@vscode/ripgrep":"^1.18.0","@vitest/coverage-v8":"^4.1.11","@stryker-mutator/core":"^10.0.0","@stryker-mutator/vitest-runner":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/spec-guard_0.4.0_1788798087972_0.7708994408949779","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"@descent-vtt/spec-guard","version":"0.5.0","keywords":["adr","architecture","documentation","drift","lint","markdown","ripgrep","spec"],"license":"MIT","_id":"@descent-vtt/spec-guard@0.5.0","maintainers":[{"name":"descent-vtt","email":"dev@descentvtt.com"}],"homepage":"https://github.com/DescentVTT/spec-guard#readme","bugs":{"url":"https://github.com/DescentVTT/spec-guard/issues"},"bin":{"spec-guard":"bin/spec-guard.js"},"dist":{"shasum":"2f8db83c16ffecf459832d4aa89ea9a877b9d32b","tarball":"https://registry.npmjs.org/@descent-vtt/spec-guard/-/spec-guard-0.5.0.tgz","fileCount":57,"integrity":"sha512-QL88Ri+d90lFJA2ZCOsGjr9lF6O/znoQzW4ZALQ58/pJzolzd5WYldF/HCIz68RaQvYm0NjOFrY+icPZO6r5MA==","signatures":[{"sig":"MEQCIF+s14ehIbX74ohF7MkKhGH+j2osmcc4x4EoA5M6RPAeAiAMHAxZiEZrd3blzbWkRxs14oLN2ODa8WG/HeavSFRU3w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":449640},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"cdeb48d27522656427d1ef4be655781bd21a53cd","scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"","selfcheck":"node ./bin/spec-guard.js \"docs/**/*.md\" \"README.md\" --verbose","test:watch":"vitest","test:coverage":"vitest run --coverage","test:mutation":"stryker run","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"descent-vtt","email":"dev@descentvtt.com"},"overrides":{"qs":"^6.16.0"},"repository":{"url":"git+https://github.com/DescentVTT/spec-guard.git","type":"git"},"_npmVersion":"11.16.0","description":"Executable architecture assertions for Markdown specs & ADRs.","directories":{},"_nodeVersion":"24.18.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.11","typescript":"^7.0.2","@types/node":"^26.4.1","@vscode/ripgrep":"^1.18.0","@vitest/coverage-v8":"^4.1.11","@stryker-mutator/core":"^10.0.0","@stryker-mutator/vitest-runner":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/spec-guard_0.5.0_1788998367986_0.118352912745884","host":"s3://npm-registry-packages-npm-production"}},"0.5.1":{"name":"@descent-vtt/spec-guard","version":"0.5.1","keywords":["adr","architecture","documentation","drift","lint","markdown","ripgrep","spec"],"license":"MIT","_id":"@descent-vtt/spec-guard@0.5.1","maintainers":[{"name":"descent-vtt","email":"dev@descentvtt.com"}],"homepage":"https://github.com/DescentVTT/spec-guard#readme","bugs":{"url":"https://github.com/DescentVTT/spec-guard/issues"},"bin":{"spec-guard":"bin/spec-guard.js"},"dist":{"shasum":"b58e8df922a83c31ccbe7c02d2605631c60a323e","tarball":"https://registry.npmjs.org/@descent-vtt/spec-guard/-/spec-guard-0.5.1.tgz","fileCount":57,"integrity":"sha512-K71OI5xURlfn1AvdTZck73/h8qE1ycsa3XzCKjkgPuIYyDQAibIsxDtt3HShxGse+t2V9rk9WtfWegHu/arRGg==","signatures":[{"sig":"MEUCIQCU85+NdQv+eMJ1mTYWKKbVDRguIPGP2aVLSVISHOU0mgIgGcQy5/PYsHV36Y2La6Xo/7Onz5JAXyCHn2rpWhxujOM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":480540},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"50bd282100a18918ef3d5001b8306485e12bbcb0","scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"","selfcheck":"node ./bin/spec-guard.js \"docs/**/*.md\" \"README.md\" --verbose","test:watch":"vitest","test:coverage":"vitest run --coverage","test:mutation":"stryker run","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"descent-vtt","email":"dev@descentvtt.com"},"overrides":{"qs":"^6.16.0"},"repository":{"url":"git+https://github.com/DescentVTT/spec-guard.git","type":"git"},"_npmVersion":"11.16.0","description":"Executable architecture assertions for Markdown specs & ADRs.","directories":{},"_nodeVersion":"24.18.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.11","typescript":"^7.0.2","@types/node":"^26.4.1","@vscode/ripgrep":"^1.18.0","@vitest/coverage-v8":"^4.1.11","@stryker-mutator/core":"^10.0.0","@stryker-mutator/vitest-runner":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/spec-guard_0.5.1_1789213929469_0.21993573908975783","host":"s3://npm-registry-packages-npm-production"}},"0.6.0":{"name":"@descent-vtt/spec-guard","version":"0.6.0","keywords":["adr","architecture","documentation","drift","lint","markdown","ripgrep","spec"],"license":"MIT","_id":"@descent-vtt/spec-guard@0.6.0","maintainers":[{"name":"descent-vtt","email":"dev@descentvtt.com"}],"homepage":"https://github.com/DescentVTT/spec-guard#readme","bugs":{"url":"https://github.com/DescentVTT/spec-guard/issues"},"bin":{"spec-guard":"bin/spec-guard.js"},"dist":{"shasum":"42398556c93519fc6a1597dd3875259dcc4062fa","tarball":"https://registry.npmjs.org/@descent-vtt/spec-guard/-/spec-guard-0.6.0.tgz","fileCount":65,"integrity":"sha512-+GSMYN7h3cxVYifnIvh6of0+E80ly1lZUJbLjy+BlIeLDaUzUL4c/18G8Qd6SxHF8OceIzVORZMBdbVmJxd7OA==","signatures":[{"sig":"MEQCIDlnNQjZOdS4HmbuZHSs2qB9VFxMAWmR4MamClXeo4fTAiBut2iXIdh3NCECYONR9k4gITi+3FkZICG+PhBX2MeKOg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":572601},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"0b47d2e2694efcb9e0c669cc33fc6cc9f71fcefd","scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"","selfcheck":"node ./bin/spec-guard.js \"docs/**/*.md\" \"README.md\" --verbose","test:watch":"vitest","test:coverage":"vitest run --coverage","test:mutation":"stryker run","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"descent-vtt","email":"dev@descentvtt.com"},"overrides":{"qs":"^6.16.0"},"repository":{"url":"git+https://github.com/DescentVTT/spec-guard.git","type":"git"},"_npmVersion":"11.16.0","description":"Executable architecture assertions for Markdown specs & ADRs.","directories":{},"_nodeVersion":"24.18.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.11","typescript":"^7.0.2","@types/node":"^26.4.1","@vscode/ripgrep":"^1.18.0","@vitest/coverage-v8":"^4.1.11","@stryker-mutator/core":"^10.0.0","@stryker-mutator/vitest-runner":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/spec-guard_0.6.0_1789269548983_0.20680023533901104","host":"s3://npm-registry-packages-npm-production"}},"0.7.0":{"name":"@descent-vtt/spec-guard","version":"0.7.0","keywords":["adr","architecture","documentation","drift","lint","markdown","ripgrep","spec"],"license":"MIT","_id":"@descent-vtt/spec-guard@0.7.0","maintainers":[{"name":"descent-vtt","email":"dev@descentvtt.com"}],"homepage":"https://github.com/DescentVTT/spec-guard#readme","bugs":{"url":"https://github.com/DescentVTT/spec-guard/issues"},"bin":{"spec-guard":"bin/spec-guard.js"},"dist":{"shasum":"61d3bb738ad6e77ba2c97861f94d144aae6e28ce","tarball":"https://registry.npmjs.org/@descent-vtt/spec-guard/-/spec-guard-0.7.0.tgz","fileCount":81,"integrity":"sha512-jYuqBQtxn4owqo2pn3SKHIrEjzZIF4wRW6rPbpnl14icWl1jRKkLC06nIOMO0nz8ykAUyItW6j3FWah1oTHfag==","signatures":[{"sig":"MEUCIQCuXdrzO1taxBD0eP/gZXLz1pKBf+hnkmAh5qUwx1t3tQIgQBjivSu8pqXDmTpvq5XwWsbSxXOjxeHZ1LcPCCXYe6g=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":707732},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"8c7d73d21959157912289e1c51525ef200ccfd48","scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"","selfcheck":"node ./bin/spec-guard.js \"docs/**/*.md\" \"README.md\" --verbose","test:watch":"vitest","test:coverage":"vitest run --coverage","test:mutation":"stryker run","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"descent-vtt","email":"dev@descentvtt.com"},"overrides":{"qs":"^6.16.0"},"repository":{"url":"git+https://github.com/DescentVTT/spec-guard.git","type":"git"},"_npmVersion":"11.16.0","description":"Executable architecture assertions for Markdown specs & ADRs.","directories":{},"_nodeVersion":"24.18.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.11","typescript":"^7.0.2","@types/node":"^26.4.1","@vscode/ripgrep":"^1.18.0","@vitest/coverage-v8":"^4.1.11","@stryker-mutator/core":"^10.0.0","@stryker-mutator/vitest-runner":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/spec-guard_0.7.0_1789305917472_0.5957967834455014","host":"s3://npm-registry-packages-npm-production"}},"0.8.0":{"name":"@descent-vtt/spec-guard","version":"0.8.0","keywords":["adr","architecture","documentation","drift","lint","markdown","ripgrep","spec"],"license":"MIT","_id":"@descent-vtt/spec-guard@0.8.0","maintainers":[{"name":"descent-vtt","email":"dev@descentvtt.com"}],"homepage":"https://github.com/DescentVTT/spec-guard#readme","bugs":{"url":"https://github.com/DescentVTT/spec-guard/issues"},"bin":{"spec-guard":"bin/spec-guard.js"},"dist":{"shasum":"53eb562ea355b03f0197f5fc39276406ebedb3c3","tarball":"https://registry.npmjs.org/@descent-vtt/spec-guard/-/spec-guard-0.8.0.tgz","fileCount":85,"integrity":"sha512-y7fhzThAmzTH3leXAj5p1COM0sOqsgQPxH3vVc4A1u/03LidxQTpbKhxp31xAIwlVdp1ewo5RSnU7K5PyhqTyw==","signatures":[{"sig":"MEUCIQDZcSFwGunrQttqCPiD1/AYRmFkOUK/v0AqVceyHOw2IAIgc405+u0lp//RfuIZz/d30JqdA3TS8Emkhpuiv7S6FiA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":771788},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"9f6219241c5ebc39db8384ad534e738a115e871f","scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"","selfcheck":"node ./bin/spec-guard.js \"docs/**/*.md\" \"README.md\" --verbose","test:watch":"vitest","test:coverage":"vitest run --coverage","test:mutation":"stryker run","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"descent-vtt","email":"dev@descentvtt.com"},"overrides":{"qs":"^6.16.0"},"repository":{"url":"git+https://github.com/DescentVTT/spec-guard.git","type":"git"},"_npmVersion":"11.16.0","description":"Executable architecture assertions for Markdown specs & ADRs.","directories":{},"_nodeVersion":"24.18.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.11","typescript":"^7.0.2","@types/node":"^26.4.1","@vscode/ripgrep":"^1.18.0","@vitest/coverage-v8":"^4.1.11","@stryker-mutator/core":"^10.0.0","@stryker-mutator/vitest-runner":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/spec-guard_0.8.0_1789319533475_0.44910795890393573","host":"s3://npm-registry-packages-npm-production"}},"0.9.0":{"name":"@descent-vtt/spec-guard","version":"0.9.0","keywords":["adr","architecture","documentation","drift","lint","markdown","ripgrep","spec"],"license":"MIT","_id":"@descent-vtt/spec-guard@0.9.0","maintainers":[{"name":"descent-vtt","email":"dev@descentvtt.com"}],"homepage":"https://github.com/DescentVTT/spec-guard#readme","bugs":{"url":"https://github.com/DescentVTT/spec-guard/issues"},"bin":{"spec-guard":"bin/spec-guard.js"},"dist":{"shasum":"b6c7c831640e2b58175f12a78f15523a2dc4143a","tarball":"https://registry.npmjs.org/@descent-vtt/spec-guard/-/spec-guard-0.9.0.tgz","fileCount":105,"integrity":"sha512-FUSZuLLmRc2qDpm9xkVHl39gp6aaSyxGh0h5nQB7je1V+N5s2tYs+kH4f2yQ/Lvpkr7MWSVMmvGVfKvmiEnS6g==","signatures":[{"sig":"MEQCIDv7jv8fnbImY3QXMpSJ2R/F+pwARsKyJEyI7jmWTwY7AiAv3Eon0OmpLGkeOa0aEkaPrNsnnaIYG5AlOneyDhcvrA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":901448},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"b84e010e9840720f23322d320e9ad94e66ec42ce","scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"","selfcheck":"node ./bin/spec-guard.js --verbose","test:watch":"vitest","test:coverage":"vitest run --coverage","test:mutation":"stryker run","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"descent-vtt","email":"dev@descentvtt.com"},"overrides":{"qs":"^6.16.0"},"specGuard":{"specs":["docs/**/*.md","README.md"]},"repository":{"url":"git+https://github.com/DescentVTT/spec-guard.git","type":"git"},"_npmVersion":"11.16.0","description":"Executable architecture assertions for Markdown specs & ADRs.","directories":{},"_nodeVersion":"24.18.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.11","typescript":"^7.0.2","@types/node":"^26.4.1","@vscode/ripgrep":"^1.18.0","@vitest/coverage-v8":"^4.1.11","@stryker-mutator/core":"^10.0.0","@stryker-mutator/vitest-runner":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/spec-guard_0.9.0_1789381694911_0.8683860099196299","host":"s3://npm-registry-packages-npm-production"}},"0.9.1":{"name":"@descent-vtt/spec-guard","version":"0.9.1","keywords":["adr","architecture","documentation","drift","lint","markdown","ripgrep","spec"],"license":"MIT","_id":"@descent-vtt/spec-guard@0.9.1","maintainers":[{"name":"descent-vtt","email":"dev@descentvtt.com"}],"homepage":"https://github.com/DescentVTT/spec-guard#readme","bugs":{"url":"https://github.com/DescentVTT/spec-guard/issues"},"bin":{"spec-guard":"bin/spec-guard.js"},"dist":{"shasum":"64869992bd4812a57be7ebb0eeef69f2651f6722","tarball":"https://registry.npmjs.org/@descent-vtt/spec-guard/-/spec-guard-0.9.1.tgz","fileCount":105,"integrity":"sha512-dKaFLW6/rffJC6UPTyzwPHddL+1pgmHQkfcuqhww/iiwyhkIdNPM90lQFs+gO9uYYBeSUS33aCY1Pw9y2LGugA==","signatures":[{"sig":"MEUCIGqHQE9o/bKFBqrY9qNEhDjECrbxlNFgqHVLyHdxPzwnAiEAtraujt+bu58NfL+TR4aSNH99TzpfXojIKHoRI3kqj+4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":902758},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"32399eb3623b8baa0161ea2d94d29a74ef2633c9","scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"","selfcheck":"node ./bin/spec-guard.js --verbose","test:watch":"vitest","test:coverage":"vitest run --coverage","test:mutation":"stryker run","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"descent-vtt","email":"dev@descentvtt.com"},"overrides":{"qs":"^6.16.0"},"specGuard":{"specs":["docs/**/*.md","README.md"]},"repository":{"url":"git+https://github.com/DescentVTT/spec-guard.git","type":"git"},"_npmVersion":"11.16.0","description":"Executable architecture assertions for Markdown specs & ADRs.","directories":{},"_nodeVersion":"24.18.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.11","typescript":"^7.0.2","@types/node":"^26.4.1","@vscode/ripgrep":"^1.18.0","@vitest/coverage-v8":"^4.1.11","@stryker-mutator/core":"^10.0.0","@stryker-mutator/vitest-runner":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/spec-guard_0.9.1_1789388999637_0.9525145187531308","host":"s3://npm-registry-packages-npm-production"}},"0.9.2":{"name":"@descent-vtt/spec-guard","version":"0.9.2","keywords":["adr","architecture","documentation","drift","lint","markdown","ripgrep","spec"],"license":"MIT","_id":"@descent-vtt/spec-guard@0.9.2","maintainers":[{"name":"descent-vtt","email":"dev@descentvtt.com"}],"homepage":"https://github.com/DescentVTT/spec-guard#readme","bugs":{"url":"https://github.com/DescentVTT/spec-guard/issues"},"bin":{"spec-guard":"bin/spec-guard.js"},"dist":{"shasum":"fadf077a8afcbb6fe61189cfe9a44209b8c651d1","tarball":"https://registry.npmjs.org/@descent-vtt/spec-guard/-/spec-guard-0.9.2.tgz","fileCount":105,"integrity":"sha512-T9Yuu1zOeBf7oRDNKbTKcIZVsCCDJ3igAdhCuVBJpiaoSyz+gl+/Fr6AzEF26ZztHq1rkxa5hFBvCGVCx8N2Eg==","signatures":[{"sig":"MEUCIBBKJkfVNbNL91RrwhIfggQBcpaDrAPLvjhKQoGr7UcoAiEA2epqebM7Pj/6QgFFsUw2ezvUydwLHlmFZxvRBYtb9yg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":905702},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"d6c4cb332b8a1bb91abf52f3c506801af814728f","scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"","selfcheck":"node ./bin/spec-guard.js --verbose","test:watch":"vitest","test:coverage":"vitest run --coverage","test:mutation":"stryker run","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"descent-vtt","email":"dev@descentvtt.com"},"overrides":{"qs":"^6.16.0"},"specGuard":{"specs":["docs/**/*.md","README.md"]},"repository":{"url":"git+https://github.com/DescentVTT/spec-guard.git","type":"git"},"_npmVersion":"11.16.0","description":"Executable architecture assertions for Markdown specs & ADRs.","directories":{},"_nodeVersion":"24.18.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.11","typescript":"^7.0.2","@types/node":"^26.4.1","@vscode/ripgrep":"^1.18.0","@vitest/coverage-v8":"^4.1.11","@stryker-mutator/core":"^10.0.0","@stryker-mutator/vitest-runner":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/spec-guard_0.9.2_1789392679337_0.6901318330971566","host":"s3://npm-registry-packages-npm-production"}},"0.10.0":{"name":"@descent-vtt/spec-guard","version":"0.10.0","keywords":["adr","architecture","documentation","drift","lint","markdown","ripgrep","spec"],"license":"MIT","_id":"@descent-vtt/spec-guard@0.10.0","maintainers":[{"name":"descent-vtt","email":"dev@descentvtt.com"}],"homepage":"https://github.com/DescentVTT/spec-guard#readme","bugs":{"url":"https://github.com/DescentVTT/spec-guard/issues"},"bin":{"spec-guard":"bin/spec-guard.js"},"dist":{"shasum":"7583cbbefdff0795c7c4ee377c0ee42e6d69523c","tarball":"https://registry.npmjs.org/@descent-vtt/spec-guard/-/spec-guard-0.10.0.tgz","fileCount":105,"integrity":"sha512-qGLQluBdVQUxrdOZOaFZdY5io1dF/12JZACg9oNf1j92Z6rU92DO6vFUxqIMVSMzBbxTexqYjn2JtVrRQP6IbQ==","signatures":[{"sig":"MEUCIHha9Salbygbqx4snB208TIaI4YacSLPZ9BdX78Opj8DAiEA0xjsOopi9g+NQ+IdVEc2tQTn8Xg9QYc3hdhgFUrRPdo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":923589},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"a2e9c4514cfe63705ef0f1cb78f56f06606388e0","scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"","selfcheck":"node ./bin/spec-guard.js --verbose","test:watch":"vitest","test:coverage":"vitest run --coverage","test:mutation":"stryker run","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"descent-vtt","email":"dev@descentvtt.com"},"overrides":{"qs":"^6.16.0"},"specGuard":{"specs":["docs/**/*.md","README.md"]},"repository":{"url":"git+https://github.com/DescentVTT/spec-guard.git","type":"git"},"_npmVersion":"11.16.0","description":"Executable architecture assertions for Markdown specs & ADRs.","directories":{},"_nodeVersion":"24.18.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.11","typescript":"^7.0.2","@types/node":"^26.4.1","@vscode/ripgrep":"^1.18.0","@vitest/coverage-v8":"^4.1.11","@stryker-mutator/core":"^10.0.0","@stryker-mutator/vitest-runner":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/spec-guard_0.10.0_1789401024368_0.9525065521144569","host":"s3://npm-registry-packages-npm-production"}},"0.10.1":{"name":"@descent-vtt/spec-guard","version":"0.10.1","keywords":["adr","architecture","documentation","drift","lint","markdown","ripgrep","spec"],"license":"MIT","_id":"@descent-vtt/spec-guard@0.10.1","maintainers":[{"name":"descent-vtt","email":"dev@descentvtt.com"}],"homepage":"https://github.com/DescentVTT/spec-guard#readme","bugs":{"url":"https://github.com/DescentVTT/spec-guard/issues"},"bin":{"spec-guard":"bin/spec-guard.js"},"dist":{"shasum":"0130df69adb9c378832a8bec84d7e463655a2b09","tarball":"https://registry.npmjs.org/@descent-vtt/spec-guard/-/spec-guard-0.10.1.tgz","fileCount":105,"integrity":"sha512-NtRLIg8BGz5qWEFsjTVpG2Pc5LKAiEc0QDQLabRPyTHExlMLqhvKznjYFjbTkW/Mojka5jdFt8KSzom9ed/zUw==","signatures":[{"sig":"MEYCIQCVZ06LJ/OnLTJPIMCBsMOReRtAKhIgsYHiSuFk59BiEwIhAJWjMub7waqIt0HYaA86IXqUOFVtJdUUQBBxB+Yj96tK","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":951604},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"850f20200d19cf8fed7b8911dedff8f5d2058e3a","scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"","selfcheck":"node ./bin/spec-guard.js --verbose","test:watch":"vitest","test:coverage":"vitest run --coverage","test:mutation":"stryker run","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"descent-vtt","email":"dev@descentvtt.com"},"overrides":{"qs":"^6.16.0"},"specGuard":{"specs":["docs/**/*.md","README.md"]},"repository":{"url":"git+https://github.com/DescentVTT/spec-guard.git","type":"git"},"_npmVersion":"11.16.0","description":"Executable architecture assertions for Markdown specs & ADRs.","directories":{},"_nodeVersion":"24.18.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.11","typescript":"^7.0.2","@types/node":"^26.4.1","@vscode/ripgrep":"^1.18.0","@vitest/coverage-v8":"^4.1.11","@stryker-mutator/core":"^10.0.0","@stryker-mutator/vitest-runner":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/spec-guard_0.10.1_1789430985649_0.15334163810051704","host":"s3://npm-registry-packages-npm-production"}},"0.10.2":{"name":"@descent-vtt/spec-guard","version":"0.10.2","keywords":["adr","architecture","documentation","drift","lint","markdown","ripgrep","spec"],"license":"MIT","_id":"@descent-vtt/spec-guard@0.10.2","maintainers":[{"name":"descent-vtt","email":"dev@descentvtt.com"}],"homepage":"https://github.com/DescentVTT/spec-guard#readme","bugs":{"url":"https://github.com/DescentVTT/spec-guard/issues"},"bin":{"spec-guard":"bin/spec-guard.js"},"dist":{"shasum":"2d80e59e4c9cc3714df080e9905a3e0ae63e5730","tarball":"https://registry.npmjs.org/@descent-vtt/spec-guard/-/spec-guard-0.10.2.tgz","fileCount":105,"integrity":"sha512-tMSfxh83rWUy51oM4O61EClbpblR+yEOLa0km/VKspzVSY8Osui9YyOBsF1glY1Hm1Cqm5LbIsu4YJ1vkTE9XA==","signatures":[{"sig":"MEUCIEzKo/LbRRvxnSr8AWQBsx6l0yIcs0eQd9YIiDZodDKjAiEAqI3jYjaTa0WGhTcuPZiECx2OGyJmtXgMRG4rbdnafKo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":980723},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"d91dd3983a2d027e53674094b22256eae88020f6","scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"","selfcheck":"node ./bin/spec-guard.js --verbose","test:watch":"vitest","test:coverage":"vitest run --coverage","test:mutation":"stryker run","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"descent-vtt","email":"dev@descentvtt.com"},"overrides":{"qs":"^6.16.0"},"specGuard":{"specs":["docs/**/*.md","README.md"]},"repository":{"url":"git+https://github.com/DescentVTT/spec-guard.git","type":"git"},"_npmVersion":"11.16.0","description":"Executable architecture assertions for Markdown specs & ADRs.","directories":{},"_nodeVersion":"24.18.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.11","typescript":"^7.0.2","@types/node":"^26.4.1","@vscode/ripgrep":"^1.18.0","@vitest/coverage-v8":"^4.1.11","@stryker-mutator/core":"^10.0.0","@stryker-mutator/vitest-runner":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/spec-guard_0.10.2_1789483854863_0.4394601604659687","host":"s3://npm-registry-packages-npm-production"}},"0.10.3":{"name":"@descent-vtt/spec-guard","version":"0.10.3","keywords":["adr","architecture","documentation","drift","lint","markdown","ripgrep","spec"],"license":"MIT","_id":"@descent-vtt/spec-guard@0.10.3","maintainers":[{"name":"descent-vtt","email":"dev@descentvtt.com"}],"homepage":"https://github.com/DescentVTT/spec-guard#readme","bugs":{"url":"https://github.com/DescentVTT/spec-guard/issues"},"bin":{"spec-guard":"bin/spec-guard.js"},"dist":{"shasum":"dcd3a68525b300d926df75910ad4f02b60cb8462","tarball":"https://registry.npmjs.org/@descent-vtt/spec-guard/-/spec-guard-0.10.3.tgz","fileCount":105,"integrity":"sha512-trRMda44vuF1hoseBi5/4FT4j5NIOW57tKKcMKfc9cdiMSise/p6UEPPhr1CxVIGlMp1RkjllW8lLLNix2No5A==","signatures":[{"sig":"MEQCIB2WsBibN8k/6drfAELeXu3QT1Z/TFwbKkqaiRvMHmhfAiBYt6FPJ5Y4jT7PAPjoACSjddHVQiHpvgBRSNtLtvUuTQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":993820},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"8a64c8e09cd9036bcd17d34d33a0ccca8ef9bf72","scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"","selfcheck":"node ./bin/spec-guard.js --verbose","test:watch":"vitest","test:coverage":"vitest run --coverage","test:mutation":"stryker run","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"descent-vtt","email":"dev@descentvtt.com"},"overrides":{"qs":"^6.16.0"},"specGuard":{"specs":["docs/**/*.md","README.md"]},"repository":{"url":"git+https://github.com/DescentVTT/spec-guard.git","type":"git"},"_npmVersion":"11.16.0","description":"Executable architecture assertions for Markdown specs & ADRs.","directories":{},"_nodeVersion":"24.18.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.11","typescript":"^7.0.2","@types/node":"^26.4.1","@vscode/ripgrep":"^1.18.0","@vitest/coverage-v8":"^4.1.11","@stryker-mutator/core":"^10.0.0","@stryker-mutator/vitest-runner":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/spec-guard_0.10.3_1789517198262_0.8192108588177884","host":"s3://npm-registry-packages-npm-production"}},"0.11.0":{"name":"@descent-vtt/spec-guard","version":"0.11.0","keywords":["adr","architecture","documentation","drift","lint","markdown","ripgrep","spec"],"license":"MIT","_id":"@descent-vtt/spec-guard@0.11.0","maintainers":[{"name":"descent-vtt","email":"dev@descentvtt.com"}],"homepage":"https://github.com/DescentVTT/spec-guard#readme","bugs":{"url":"https://github.com/DescentVTT/spec-guard/issues"},"bin":{"spec-guard":"bin/spec-guard.js"},"dist":{"shasum":"8251c54020440390a49ca025445c6d837788c786","tarball":"https://registry.npmjs.org/@descent-vtt/spec-guard/-/spec-guard-0.11.0.tgz","fileCount":105,"integrity":"sha512-gGP72TG9Ypn2H8dwi1pwLhRRxlY5IF2/84uV6tlDpMFZE66itMjehnFj0uq/jqoszJaXngEGoj+f2o4JpefO+Q==","signatures":[{"sig":"MEQCIGNO1X4e+dTOlab/0l5wF6EKOAtsSwmGoHauNei12hovAiA18c2mTRl1OEiQ+yPKFskiPOd4hc12Wo63rP+x6mC7Jw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1016388},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"3963ce23d9ff35bb1376505e873fbe0eabc10c83","scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"","selfcheck":"node ./bin/spec-guard.js --verbose","test:watch":"vitest","test:coverage":"vitest run --coverage","test:mutation":"stryker run","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"descent-vtt","email":"dev@descentvtt.com"},"overrides":{"qs":"^6.16.0"},"specGuard":{"specs":["docs/**/*.md","README.md"]},"repository":{"url":"git+https://github.com/DescentVTT/spec-guard.git","type":"git"},"_npmVersion":"11.16.0","description":"Executable architecture assertions for Markdown specs & ADRs.","directories":{},"_nodeVersion":"24.18.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.11","typescript":"^7.0.2","@types/node":"^26.4.1","@vscode/ripgrep":"^1.18.0","@vitest/coverage-v8":"^4.1.11","@stryker-mutator/core":"^10.0.0","@stryker-mutator/vitest-runner":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/spec-guard_0.11.0_1789560075293_0.9377569816660534","host":"s3://npm-registry-packages-npm-production"}},"0.12.0":{"name":"@descent-vtt/spec-guard","version":"0.12.0","keywords":["adr","architecture","documentation","drift","lint","markdown","ripgrep","spec"],"license":"MIT","_id":"@descent-vtt/spec-guard@0.12.0","maintainers":[{"name":"descent-vtt","email":"dev@descentvtt.com"}],"homepage":"https://github.com/DescentVTT/spec-guard#readme","bugs":{"url":"https://github.com/DescentVTT/spec-guard/issues"},"bin":{"spec-guard":"bin/spec-guard.js"},"dist":{"shasum":"457c6d0f0c3f44799e203e5454ed4e858c0c38ae","tarball":"https://registry.npmjs.org/@descent-vtt/spec-guard/-/spec-guard-0.12.0.tgz","fileCount":207,"integrity":"sha512-M7twHtshDQysZkAuEX8in8KzLch3jfumRrD+5NCtaBpD/9HauwP/iG5Z4u58FKg5I4VzN2pGrtD8U08yHUW+mA==","signatures":[{"sig":"MEUCIQDxRq/0kY5EqyM0pd4CTbBVmlMwb5HXF8ooonvd7Ne27QIgWSuSEIZineOBaWWAMNZ9SVkypp1gQuXRRAieH4HPrkY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@descent-vtt%2fspec-guard@0.12.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1789500},"main":"./dist/index.js","type":"module","_from":"file:npm-package/descent-vtt-spec-guard-0.12.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"","selfcheck":"node ./bin/spec-guard.js --verbose","test:watch":"vitest","test:coverage":"vitest run --coverage","test:mutation":"stryker run","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","approver":{"name":"descent-vtt","email":"dev@descentvtt.com"},"trustedPublisher":{"id":"github","oidcConfigId":"oidc:d1dc65c8-1e19-4067-bd1e-f20a8ed70c82"}},"_resolved":"/home/runner/work/spec-guard/spec-guard/npm-package/descent-vtt-spec-guard-0.12.0.tgz","overrides":{"qs":"^6.16.0"},"specGuard":{"specs":["docs/**/*.md","README.md"],"exclude":["dist","coverage","reports","tests/fixtures"]},"_integrity":"sha512-M7twHtshDQysZkAuEX8in8KzLch3jfumRrD+5NCtaBpD/9HauwP/iG5Z4u58FKg5I4VzN2pGrtD8U08yHUW+mA==","repository":{"url":"git+https://github.com/DescentVTT/spec-guard.git","type":"git"},"_npmVersion":"11.20.0","description":"Executable architecture assertions for Markdown specs & ADRs.","directories":{},"_nodeVersion":"24.21.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.11","typescript":"^7.0.2","@types/node":"^26.4.1","@vscode/ripgrep":"^1.18.0","@vitest/coverage-v8":"^4.1.11","@stryker-mutator/core":"^10.0.0","@stryker-mutator/vitest-runner":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/spec-guard_0.12.0_1790413241859_0.7421344001994423","host":"s3://npm-registry-packages-npm-production"}},"0.12.1":{"name":"@descent-vtt/spec-guard","version":"0.12.1","keywords":["adr","architecture","documentation","drift","lint","markdown","ripgrep","spec"],"license":"MIT","_id":"@descent-vtt/spec-guard@0.12.1","maintainers":[{"name":"descent-vtt","email":"dev@descentvtt.com"}],"homepage":"https://github.com/DescentVTT/spec-guard#readme","bugs":{"url":"https://github.com/DescentVTT/spec-guard/issues"},"bin":{"spec-guard":"bin/spec-guard.js"},"dist":{"shasum":"b203924c8441e48c428e139a63b277cc482787cf","tarball":"https://registry.npmjs.org/@descent-vtt/spec-guard/-/spec-guard-0.12.1.tgz","fileCount":207,"integrity":"sha512-aVuveVt9dd/5xZLyV32JG41yx/7JNjOD8HskqbGM40MvTp3AGt6dEokyXY1ClwXZRiWt23TEbTtxwz7Mivr2pw==","signatures":[{"sig":"MEUCIQDXTjNgyebw37v81AeA2OpF1iNmxuWquop0+9kGW1m0bQIgBMt89VjM85AGZhftgpZ4ikA7l4Gbb+JcfxR9BtlyCIU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@descent-vtt%2fspec-guard@0.12.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1806308},"main":"./dist/index.js","type":"module","_from":"file:npm-package/descent-vtt-spec-guard-0.12.1.tgz","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"","selfcheck":"node ./bin/spec-guard.js --verbose","test:watch":"vitest","test:coverage":"vitest run --coverage","test:mutation":"stryker run","prepublishOnly":"node -e \"if (process.env.GITHUB_ACTIONS !== 'true') { console.error('npm publish is refused outside GitHub Actions: a release is a v* tag, staged by CI with provenance.'); process.exit(1) }\" && npm run clean && npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","approver":{"name":"descent-vtt","email":"dev@descentvtt.com"},"trustedPublisher":{"id":"github","oidcConfigId":"oidc:d1dc65c8-1e19-4067-bd1e-f20a8ed70c82"}},"_resolved":"/home/runner/work/spec-guard/spec-guard/npm-package/descent-vtt-spec-guard-0.12.1.tgz","overrides":{"qs":"^6.16.0"},"specGuard":{"specs":["docs/**/*.md","README.md"],"exclude":["dist","coverage","reports","tests/fixtures"]},"_integrity":"sha512-aVuveVt9dd/5xZLyV32JG41yx/7JNjOD8HskqbGM40MvTp3AGt6dEokyXY1ClwXZRiWt23TEbTtxwz7Mivr2pw==","repository":{"url":"git+https://github.com/DescentVTT/spec-guard.git","type":"git"},"_npmVersion":"11.20.0","description":"Executable architecture assertions for Markdown specs & ADRs.","directories":{},"_nodeVersion":"24.21.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.11","typescript":"^7.0.2","@types/node":"^26.4.1","@vscode/ripgrep":"^1.18.0","@vitest/coverage-v8":"^4.1.11","@stryker-mutator/core":"^10.0.0","@stryker-mutator/vitest-runner":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/spec-guard_0.12.1_1790444872053_0.901719926003778","host":"s3://npm-registry-packages-npm-production"}},"0.12.2":{"name":"@descent-vtt/spec-guard","version":"0.12.2","keywords":["adr","architecture","documentation","drift","lint","markdown","ripgrep","spec"],"license":"MIT","_id":"@descent-vtt/spec-guard@0.12.2","maintainers":[{"name":"descent-vtt","email":"dev@descentvtt.com"}],"homepage":"https://github.com/DescentVTT/spec-guard#readme","bugs":{"url":"https://github.com/DescentVTT/spec-guard/issues"},"bin":{"spec-guard":"bin/spec-guard.js"},"dist":{"shasum":"96a78eea78ecfbbf0a0fe9ec1ffa477202766661","tarball":"https://registry.npmjs.org/@descent-vtt/spec-guard/-/spec-guard-0.12.2.tgz","fileCount":206,"integrity":"sha512-JTrI/9+0T3eMd0aK8opkHjp0WNGPSuKqs2ZO5Oi4Nx7Ur5ojPEU3OL0ggc29ZzAIA88I6eez1noOL7hDO45ubA==","signatures":[{"sig":"MEQCIAUjwAsoshG0bqKatNfTbaFoAYpM0MkxvB+fo4fcGM4iAiBrTGTMNrqQNvt2htyHKNyR/G5SuzTwiDJBN2XQIjNttQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@descent-vtt%2fspec-guard@0.12.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1806215},"main":"./dist/index.js","type":"module","_from":"file:npm-package/descent-vtt-spec-guard-0.12.2.tgz","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"","selfcheck":"node ./bin/spec-guard.js --verbose","test:watch":"vitest","test:coverage":"vitest run --coverage","test:mutation":"stryker run","prepublishOnly":"node -e \"if (process.env.GITHUB_ACTIONS !== 'true') { console.error('npm publish is refused outside GitHub Actions: a release is a v* tag, staged by CI with provenance.'); process.exit(1) }\" && npm run clean && npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","approver":{"name":"descent-vtt","email":"dev@descentvtt.com"},"trustedPublisher":{"id":"github","oidcConfigId":"oidc:d1dc65c8-1e19-4067-bd1e-f20a8ed70c82"}},"_resolved":"/home/runner/work/spec-guard/spec-guard/npm-package/descent-vtt-spec-guard-0.12.2.tgz","overrides":{"qs":"^6.16.0"},"specGuard":{"specs":["docs/**/*.md","README.md"],"exclude":["dist","coverage","reports","tests/fixtures"]},"_integrity":"sha512-JTrI/9+0T3eMd0aK8opkHjp0WNGPSuKqs2ZO5Oi4Nx7Ur5ojPEU3OL0ggc29ZzAIA88I6eez1noOL7hDO45ubA==","repository":{"url":"git+https://github.com/DescentVTT/spec-guard.git","type":"git"},"_npmVersion":"11.20.0","description":"Executable architecture assertions for Markdown specs & ADRs.","directories":{},"_nodeVersion":"24.21.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.11","typescript":"^7.0.2","@types/node":"^26.4.1","@vscode/ripgrep":"^1.18.0","@vitest/coverage-v8":"^4.1.11","@stryker-mutator/core":"^10.0.0","@stryker-mutator/vitest-runner":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/spec-guard_0.12.2_1790449766025_0.3039836436059822","host":"s3://npm-registry-packages-npm-production"}},"0.12.3":{"name":"@descent-vtt/spec-guard","version":"0.12.3","keywords":["adr","architecture","documentation","drift","lint","markdown","ripgrep","spec"],"license":"MIT","_id":"@descent-vtt/spec-guard@0.12.3","maintainers":[{"name":"descent-vtt","email":"dev@descentvtt.com"}],"homepage":"https://github.com/DescentVTT/spec-guard#readme","bugs":{"url":"https://github.com/DescentVTT/spec-guard/issues"},"bin":{"spec-guard":"bin/spec-guard.js"},"dist":{"shasum":"5500e1df9eb3711764d381867c5e8a2a99510d02","tarball":"https://registry.npmjs.org/@descent-vtt/spec-guard/-/spec-guard-0.12.3.tgz","fileCount":206,"integrity":"sha512-QminAUknOpyMc5Ub2u7NWWzHaCCT/2R7qRnIM3SGnU818ief4mnh4PuoajKU1LPDJbCZ6Knpng0APUNRfpvUVA==","signatures":[{"sig":"MEQCIDOd0lq2VeVYXcmS11T2YUZSrB4GakqC0PlAdQGjjWhIAiBWvAh4XbrrAdgv2neGmLY7ymkbEsJSWZD6eDQxTxAViw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@descent-vtt%2fspec-guard@0.12.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1827539},"main":"./dist/index.js","type":"module","_from":"file:npm-package/descent-vtt-spec-guard-0.12.3.tgz","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"","selfcheck":"node ./bin/spec-guard.js --verbose","test:watch":"vitest","test:coverage":"vitest run --coverage","test:mutation":"stryker run","prepublishOnly":"node -e \"if (process.env.GITHUB_ACTIONS !== 'true') { console.error('npm publish is refused outside GitHub Actions: a release is a v* tag, staged by CI with provenance.'); process.exit(1) }\" && npm run clean && npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","approver":{"name":"descent-vtt","email":"dev@descentvtt.com"},"trustedPublisher":{"id":"github","oidcConfigId":"oidc:d1dc65c8-1e19-4067-bd1e-f20a8ed70c82"}},"_resolved":"/home/runner/work/spec-guard/spec-guard/npm-package/descent-vtt-spec-guard-0.12.3.tgz","overrides":{"qs":"^6.16.0"},"specGuard":{"specs":["docs/**/*.md","README.md"],"exclude":["dist","coverage","reports","tests/fixtures"]},"_integrity":"sha512-QminAUknOpyMc5Ub2u7NWWzHaCCT/2R7qRnIM3SGnU818ief4mnh4PuoajKU1LPDJbCZ6Knpng0APUNRfpvUVA==","repository":{"url":"git+https://github.com/DescentVTT/spec-guard.git","type":"git"},"_npmVersion":"11.20.0","description":"Executable architecture assertions for Markdown specs & ADRs.","directories":{},"_nodeVersion":"24.21.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.11","typescript":"^7.0.2","@types/node":"^26.4.1","@vscode/ripgrep":"^1.18.0","@vitest/coverage-v8":"^4.1.11","@stryker-mutator/core":"^10.0.0","@stryker-mutator/vitest-runner":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/spec-guard_0.12.3_1790525653299_0.6042610454810746","host":"s3://npm-registry-packages-npm-production"}},"0.13.0":{"name":"@descent-vtt/spec-guard","version":"0.13.0","keywords":["adr","architecture","documentation","drift","lint","markdown","ripgrep","spec"],"license":"MIT","_id":"@descent-vtt/spec-guard@0.13.0","maintainers":[{"name":"descent-vtt","email":"dev@descentvtt.com"}],"homepage":"https://github.com/DescentVTT/spec-guard#readme","bugs":{"url":"https://github.com/DescentVTT/spec-guard/issues"},"bin":{"spec-guard":"bin/spec-guard.js"},"dist":{"shasum":"dae90a84ddeede0acd84fb87147deccdac9913c7","tarball":"https://registry.npmjs.org/@descent-vtt/spec-guard/-/spec-guard-0.13.0.tgz","fileCount":206,"integrity":"sha512-+qyZ2aDXN7exiSLTJjKzNbKhluBGCgjsnW3//8UfYJjZEvJDIp5wsiROFyfhv/h6neVT2cWBbEnQII3ywZNkQA==","signatures":[{"sig":"MEQCIG5QI3jn3jfKjMKgZqFtkpCu1cKbAoJt9/VuXqWwbXH7AiBZ0HXuHQ0j7Wq3FqjfK3/LWrq+yIcdsg/4SFeQwAEKlQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@descent-vtt%2fspec-guard@0.13.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1837117},"main":"./dist/index.js","type":"module","_from":"file:npm-package/descent-vtt-spec-guard-0.13.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"","selfcheck":"node ./bin/spec-guard.js --verbose","test:watch":"vitest","test:coverage":"vitest run --coverage","test:mutation":"stryker run","prepublishOnly":"node -e \"if (process.env.GITHUB_ACTIONS !== 'true') { console.error('npm publish is refused outside GitHub Actions: a release is a v* tag, staged by CI with provenance.'); process.exit(1) }\" && npm run clean && npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","approver":{"name":"descent-vtt","email":"dev@descentvtt.com"},"trustedPublisher":{"id":"github","oidcConfigId":"oidc:d1dc65c8-1e19-4067-bd1e-f20a8ed70c82"}},"_resolved":"/home/runner/work/spec-guard/spec-guard/npm-package/descent-vtt-spec-guard-0.13.0.tgz","overrides":{"qs":"^6.16.0"},"specGuard":{"specs":["docs/**/*.md","README.md"],"exclude":["dist","coverage","reports","tests/fixtures"]},"_integrity":"sha512-+qyZ2aDXN7exiSLTJjKzNbKhluBGCgjsnW3//8UfYJjZEvJDIp5wsiROFyfhv/h6neVT2cWBbEnQII3ywZNkQA==","repository":{"url":"git+https://github.com/DescentVTT/spec-guard.git","type":"git"},"_npmVersion":"11.20.0","description":"Executable architecture assertions for Markdown specs & ADRs.","directories":{},"_nodeVersion":"24.21.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.11","typescript":"^7.0.2","@types/node":"^26.4.1","@vscode/ripgrep":"^1.18.0","@vitest/coverage-v8":"^4.1.11","@stryker-mutator/core":"^10.0.0","@stryker-mutator/vitest-runner":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/spec-guard_0.13.0_1790563599508_0.9611201390374358","host":"s3://npm-registry-packages-npm-production"}},"0.13.1":{"name":"@descent-vtt/spec-guard","version":"0.13.1","keywords":["adr","architecture","documentation","drift","lint","markdown","ripgrep","spec"],"license":"MIT","_id":"@descent-vtt/spec-guard@0.13.1","maintainers":[{"name":"descent-vtt","email":"dev@descentvtt.com"}],"homepage":"https://github.com/DescentVTT/spec-guard#readme","bugs":{"url":"https://github.com/DescentVTT/spec-guard/issues"},"bin":{"spec-guard":"bin/spec-guard.js"},"dist":{"shasum":"92f7848a2d58b80a8f814db4720582c9ae2aebbf","tarball":"https://registry.npmjs.org/@descent-vtt/spec-guard/-/spec-guard-0.13.1.tgz","fileCount":206,"integrity":"sha512-U59r8Kx0iVezaxD7pwUX2iKpi2xCMNqjik/dJICDtAxJDKJQy4vazPKpXF04JUyNrz/MyQbp252t4V+53Kv6zg==","signatures":[{"sig":"MEUCIQCgKFhTzTW80mZqntCpOK4FqSsJHN1578/z+exNYt1/awIgFGe/pJKTciEFgqAj2CzRIUmzt4fVeNjY3/VBtLx4l00=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@descent-vtt%2fspec-guard@0.13.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1856420},"main":"./dist/index.js","type":"module","_from":"file:npm-package/descent-vtt-spec-guard-0.13.1.tgz","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"","selfcheck":"node ./bin/spec-guard.js --verbose","test:watch":"vitest","test:coverage":"vitest run --coverage","test:mutation":"stryker run","prepublishOnly":"node -e \"if (process.env.GITHUB_ACTIONS !== 'true') { console.error('npm publish is refused outside GitHub Actions: a release is a v* tag, staged by CI with provenance.'); process.exit(1) }\" && npm run clean && npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","approver":{"name":"descent-vtt","email":"dev@descentvtt.com"},"trustedPublisher":{"id":"github","oidcConfigId":"oidc:d1dc65c8-1e19-4067-bd1e-f20a8ed70c82"}},"_resolved":"/home/runner/work/spec-guard/spec-guard/npm-package/descent-vtt-spec-guard-0.13.1.tgz","overrides":{"qs":"^6.16.0"},"specGuard":{"specs":["docs/**/*.md","README.md"],"exclude":["dist","coverage","reports","tests/fixtures"]},"_integrity":"sha512-U59r8Kx0iVezaxD7pwUX2iKpi2xCMNqjik/dJICDtAxJDKJQy4vazPKpXF04JUyNrz/MyQbp252t4V+53Kv6zg==","repository":{"url":"git+https://github.com/DescentVTT/spec-guard.git","type":"git"},"_npmVersion":"11.20.0","description":"Executable architecture assertions for Markdown specs & ADRs.","directories":{},"_nodeVersion":"24.21.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.11","typescript":"^7.0.2","@types/node":"^26.4.1","@vscode/ripgrep":"^1.18.0","@vitest/coverage-v8":"^4.1.11","@stryker-mutator/core":"^10.0.0","@stryker-mutator/vitest-runner":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/spec-guard_0.13.1_1790617325037_0.9564820042092996","host":"s3://npm-registry-packages-npm-production"}},"0.14.0":{"name":"@descent-vtt/spec-guard","version":"0.14.0","keywords":["adr","architecture","documentation","drift","lint","markdown","ripgrep","spec"],"license":"MIT","_id":"@descent-vtt/spec-guard@0.14.0","maintainers":[{"name":"descent-vtt","email":"dev@descentvtt.com"}],"homepage":"https://github.com/DescentVTT/spec-guard#readme","bugs":{"url":"https://github.com/DescentVTT/spec-guard/issues"},"bin":{"spec-guard":"bin/spec-guard.js"},"dist":{"shasum":"529f8058db96580685d87c35c610f98208f30f09","tarball":"https://registry.npmjs.org/@descent-vtt/spec-guard/-/spec-guard-0.14.0.tgz","fileCount":206,"integrity":"sha512-UQpCYaO/xKAKiEeOLEUEn0E7p3pt7X9X+08knGOobN1Cw6y+IqcX2g9zNPWBOgj0MRIHxx+AIZ7ipwcfPCD3NA==","signatures":[{"sig":"MEUCIQDGAnzp043xbhOXEsXtA6Yhmak8aiPj7m/Jf3h+S3sbigIgLDy2OvfTPwObQ+bvOpJ5qo+PJrDv4KxJFw3FRSzbwnw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@descent-vtt%2fspec-guard@0.14.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1870332},"main":"./dist/index.js","type":"module","_from":"file:npm-package/descent-vtt-spec-guard-0.14.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"","selfcheck":"node ./bin/spec-guard.js --verbose","test:watch":"vitest","test:coverage":"vitest run --coverage","test:mutation":"stryker run","prepublishOnly":"node -e \"if (process.env.GITHUB_ACTIONS !== 'true') { console.error('npm publish is refused outside GitHub Actions: a release is a v* tag, staged by CI with provenance.'); process.exit(1) }\" && npm run clean && npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","approver":{"name":"descent-vtt","email":"dev@descentvtt.com"},"trustedPublisher":{"id":"github","oidcConfigId":"d1dc65c8-1e19-4067-bd1e-f20a8ed70c82"}},"_resolved":"/home/runner/work/spec-guard/spec-guard/npm-package/descent-vtt-spec-guard-0.14.0.tgz","overrides":{"qs":"^6.16.0"},"specGuard":{"specs":["docs/**/*.md","README.md"],"exclude":["dist","coverage","reports","tests/fixtures"]},"_integrity":"sha512-UQpCYaO/xKAKiEeOLEUEn0E7p3pt7X9X+08knGOobN1Cw6y+IqcX2g9zNPWBOgj0MRIHxx+AIZ7ipwcfPCD3NA==","repository":{"url":"git+https://github.com/DescentVTT/spec-guard.git","type":"git"},"_npmVersion":"11.20.0","description":"Executable architecture assertions for Markdown specs & ADRs.","directories":{},"_nodeVersion":"24.21.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.11","typescript":"^7.0.2","@types/node":"^26.4.1","@vscode/ripgrep":"^1.18.0","@vitest/coverage-v8":"^4.1.11","@stryker-mutator/core":"^10.0.0","@stryker-mutator/vitest-runner":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/spec-guard_0.14.0_1790640183683_0.07875144006342949","host":"s3://npm-registry-packages-npm-production"}},"0.15.0":{"name":"@descent-vtt/spec-guard","version":"0.15.0","keywords":["adr","architecture","documentation","drift","lint","markdown","ripgrep","spec"],"license":"MIT","_id":"@descent-vtt/spec-guard@0.15.0","maintainers":[{"name":"descent-vtt","email":"dev@descentvtt.com"}],"homepage":"https://github.com/DescentVTT/spec-guard#readme","bugs":{"url":"https://github.com/DescentVTT/spec-guard/issues"},"bin":{"spec-guard":"bin/spec-guard.js"},"dist":{"shasum":"238e2716cb8757e54baa08a3e6f2a12bbdfb0d8c","tarball":"https://registry.npmjs.org/@descent-vtt/spec-guard/-/spec-guard-0.15.0.tgz","fileCount":206,"integrity":"sha512-HPI6FefL7CxJoaFmaRawz75GMmSjxJRfjWAesqxj906l2pMLmqAWlfNX6fr6uCXpCAhOzbz13Jf9tBCXY9vz0Q==","signatures":[{"sig":"MEQCIFqyFoGpQ2n6ZUUOQ3+MP/QZK5XWz10rtV0l0AGHLOs9AiAUZLEBo+3Pc7ukenCguM0wlsdkChw3VlZ57iX2R23eFQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@descent-vtt%2fspec-guard@0.15.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1890712},"main":"./dist/index.js","type":"module","_from":"file:npm-package/descent-vtt-spec-guard-0.15.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"","selfcheck":"node ./bin/spec-guard.js --verbose","test:watch":"vitest","test:coverage":"vitest run --coverage","test:mutation":"stryker run","prepublishOnly":"node -e \"if (process.env.GITHUB_ACTIONS !== 'true') { console.error('npm publish is refused outside GitHub Actions: a release is a v* tag, staged by CI with provenance.'); process.exit(1) }\" && npm run clean && npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","approver":{"name":"descent-vtt","email":"dev@descentvtt.com"},"trustedPublisher":{"id":"github","oidcConfigId":"d1dc65c8-1e19-4067-bd1e-f20a8ed70c82"}},"_resolved":"/home/runner/work/spec-guard/spec-guard/npm-package/descent-vtt-spec-guard-0.15.0.tgz","overrides":{"qs":"^6.16.0"},"specGuard":{"specs":["docs/**/*.md","README.md"],"exclude":["dist","coverage","reports","tests/fixtures"]},"_integrity":"sha512-HPI6FefL7CxJoaFmaRawz75GMmSjxJRfjWAesqxj906l2pMLmqAWlfNX6fr6uCXpCAhOzbz13Jf9tBCXY9vz0Q==","repository":{"url":"git+https://github.com/DescentVTT/spec-guard.git","type":"git"},"_npmVersion":"11.20.0","description":"Executable architecture assertions for Markdown specs & ADRs.","directories":{},"_nodeVersion":"24.21.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.11","typescript":"^7.0.2","@types/node":"^26.4.1","@vscode/ripgrep":"^1.18.0","@vitest/coverage-v8":"^4.1.11","@stryker-mutator/core":"^10.0.0","@stryker-mutator/vitest-runner":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/spec-guard_0.15.0_1790647199903_0.5427426904335741","host":"s3://npm-registry-packages-npm-production"}},"0.16.0":{"name":"@descent-vtt/spec-guard","version":"0.16.0","keywords":["adr","architecture","documentation","drift","lint","markdown","ripgrep","spec"],"license":"MIT","_id":"@descent-vtt/spec-guard@0.16.0","maintainers":[{"name":"descent-vtt","email":"dev@descentvtt.com"}],"homepage":"https://github.com/DescentVTT/spec-guard#readme","bugs":{"url":"https://github.com/DescentVTT/spec-guard/issues"},"bin":{"spec-guard":"bin/spec-guard.js"},"dist":{"shasum":"2e7afcecc496fef3524e63067541682972652424","tarball":"https://registry.npmjs.org/@descent-vtt/spec-guard/-/spec-guard-0.16.0.tgz","fileCount":206,"integrity":"sha512-cz71Qpnm+aql9fpX4wQXID2mfhQzur5Mo3OzCuZ4RMMbRkvumsDEDZgWB4wpD+yRZAmPcZMrQyV5dik81GlZ9A==","signatures":[{"sig":"MEQCIEv/3AhC7ppxUYXGMIIXGhvTF5gcyuuJDNS6RJKAgoJ+AiAD41J+4HtIeHQAwBTsau087SqYN+o6t2/2LgfIiEOJVw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@descent-vtt%2fspec-guard@0.16.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1900871},"main":"./dist/index.js","type":"module","_from":"file:npm-package/descent-vtt-spec-guard-0.16.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"","selfcheck":"node ./bin/spec-guard.js --verbose","test:watch":"vitest","test:coverage":"vitest run --coverage","test:mutation":"stryker run","prepublishOnly":"node -e \"if (process.env.GITHUB_ACTIONS !== 'true') { console.error('npm publish is refused outside GitHub Actions: a release is a v* tag, staged by CI with provenance.'); process.exit(1) }\" && npm run clean && npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","approver":{"name":"descent-vtt","email":"dev@descentvtt.com"},"trustedPublisher":{"id":"github","oidcConfigId":"d1dc65c8-1e19-4067-bd1e-f20a8ed70c82"}},"_resolved":"/home/runner/work/spec-guard/spec-guard/npm-package/descent-vtt-spec-guard-0.16.0.tgz","overrides":{"qs":"^6.16.0"},"specGuard":{"specs":["docs/**/*.md","README.md"],"exclude":["dist","coverage","reports","tests/fixtures"]},"_integrity":"sha512-cz71Qpnm+aql9fpX4wQXID2mfhQzur5Mo3OzCuZ4RMMbRkvumsDEDZgWB4wpD+yRZAmPcZMrQyV5dik81GlZ9A==","repository":{"url":"git+https://github.com/DescentVTT/spec-guard.git","type":"git"},"_npmVersion":"11.20.0","description":"Executable architecture assertions for Markdown specs & ADRs.","directories":{},"_nodeVersion":"24.21.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.11","typescript":"^7.0.2","@types/node":"^26.4.1","@vscode/ripgrep":"^1.18.0","@vitest/coverage-v8":"^4.1.11","@stryker-mutator/core":"^10.0.0","@stryker-mutator/vitest-runner":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/spec-guard_0.16.0_1790698662733_0.9612092263480372","host":"s3://npm-registry-packages-npm-production"}},"0.17.0":{"name":"@descent-vtt/spec-guard","version":"0.17.0","keywords":["adr","architecture","documentation","drift","lint","markdown","ripgrep","spec"],"license":"MIT","_id":"@descent-vtt/spec-guard@0.17.0","maintainers":[{"name":"descent-vtt","email":"dev@descentvtt.com"}],"homepage":"https://github.com/DescentVTT/spec-guard#readme","bugs":{"url":"https://github.com/DescentVTT/spec-guard/issues"},"bin":{"spec-guard":"bin/spec-guard.js"},"dist":{"shasum":"c7b3058f6518145831d1d79ac8e3fc51a12df952","tarball":"https://registry.npmjs.org/@descent-vtt/spec-guard/-/spec-guard-0.17.0.tgz","fileCount":210,"integrity":"sha512-/B342jUIKU9IhEvUj7woUT0pefH03D9Zpem2zk9VwIrBrBjYChB2GPcmmBZiOXeX8vaMvCkJ+0/RxSIcnor/7Q==","signatures":[{"sig":"MEUCIB+c9xJytnhnu2YPyaGG7T6FVTGQ3EZDLY6wD/+AWectAiEA4ojoG8v2FJplDYvniVfnByv241eBT9/E879TPh+qLAk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@descent-vtt%2fspec-guard@0.17.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1972120},"main":"./dist/index.js","type":"module","_from":"file:npm-package/descent-vtt-spec-guard-0.17.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"","selfcheck":"node ./bin/spec-guard.js --verbose","test:watch":"vitest","test:coverage":"vitest run --coverage","test:mutation":"stryker run","prepublishOnly":"node -e \"if (process.env.GITHUB_ACTIONS !== 'true') { console.error('npm publish is refused outside GitHub Actions: a release is a v* tag, staged by CI with provenance.'); process.exit(1) }\" && npm run clean && npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","approver":{"name":"descent-vtt","email":"dev@descentvtt.com"},"trustedPublisher":{"id":"github","oidcConfigId":"d1dc65c8-1e19-4067-bd1e-f20a8ed70c82"}},"_resolved":"/home/runner/work/spec-guard/spec-guard/npm-package/descent-vtt-spec-guard-0.17.0.tgz","overrides":{"qs":"^6.16.0"},"specGuard":{"specs":["docs/**/*.md","README.md"],"exclude":["dist","coverage","reports","tests/fixtures"]},"_integrity":"sha512-/B342jUIKU9IhEvUj7woUT0pefH03D9Zpem2zk9VwIrBrBjYChB2GPcmmBZiOXeX8vaMvCkJ+0/RxSIcnor/7Q==","repository":{"url":"git+https://github.com/DescentVTT/spec-guard.git","type":"git"},"_npmVersion":"11.20.0","description":"Executable architecture assertions for Markdown specs & ADRs.","directories":{},"_nodeVersion":"24.21.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.11","typescript":"^7.0.2","@types/node":"^26.4.1","@vscode/ripgrep":"^1.18.0","@vitest/coverage-v8":"^4.1.11","@stryker-mutator/core":"^10.0.0","@stryker-mutator/vitest-runner":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/spec-guard_0.17.0_1790737508610_0.5563714365855827","host":"s3://npm-registry-packages-npm-production"}},"0.18.0":{"name":"@descent-vtt/spec-guard","version":"0.18.0","keywords":["adr","architecture","documentation","drift","lint","markdown","ripgrep","spec"],"license":"MIT","_id":"@descent-vtt/spec-guard@0.18.0","maintainers":[{"name":"descent-vtt","email":"dev@descentvtt.com"}],"homepage":"https://github.com/DescentVTT/spec-guard#readme","bugs":{"url":"https://github.com/DescentVTT/spec-guard/issues"},"bin":{"spec-guard":"bin/spec-guard.js"},"dist":{"shasum":"44925791c1918fe8f4eca48619f8660ce904cbb9","tarball":"https://registry.npmjs.org/@descent-vtt/spec-guard/-/spec-guard-0.18.0.tgz","fileCount":210,"integrity":"sha512-iQJH7rvcMHonZDiGBDFrOKTJO0OUOEsyrw9bR04vA5HTx5bpXVLCGyoLmgWmciILS4qkJxLQswhlXMZH/lHaTw==","signatures":[{"sig":"MEUCID1009GicZSecrujCDwg55UGaiHh1LTH0/UkzFKBFGo0AiEAhXVqjtnixGkNhZ1CFcEtCYUgKSn4mYBzJPvbaBt1QTQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@descent-vtt%2fspec-guard@0.18.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1960698},"main":"./dist/index.js","type":"module","_from":"file:npm-package/descent-vtt-spec-guard-0.18.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"","selfcheck":"node ./bin/spec-guard.js --verbose","test:watch":"vitest","test:coverage":"vitest run --coverage","test:mutation":"stryker run","prepublishOnly":"node -e \"if (process.env.GITHUB_ACTIONS !== 'true') { console.error('npm publish is refused outside GitHub Actions: a release is a v* tag, staged by CI with provenance.'); process.exit(1) }\" && npm run clean && npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","approver":{"name":"descent-vtt","email":"dev@descentvtt.com"},"trustedPublisher":{"id":"github","oidcConfigId":"d1dc65c8-1e19-4067-bd1e-f20a8ed70c82"}},"_resolved":"/home/runner/work/spec-guard/spec-guard/npm-package/descent-vtt-spec-guard-0.18.0.tgz","overrides":{"qs":"^6.16.0"},"specGuard":{"specs":["docs/**/*.md","README.md"],"exclude":["dist","coverage","reports","tests/fixtures"]},"_integrity":"sha512-iQJH7rvcMHonZDiGBDFrOKTJO0OUOEsyrw9bR04vA5HTx5bpXVLCGyoLmgWmciILS4qkJxLQswhlXMZH/lHaTw==","repository":{"url":"git+https://github.com/DescentVTT/spec-guard.git","type":"git"},"_npmVersion":"11.20.0","description":"Executable architecture assertions for Markdown specs & ADRs.","directories":{},"_nodeVersion":"24.21.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.11","typescript":"^7.0.2","@types/node":"^26.4.1","@vscode/ripgrep":"^1.18.0","@vitest/coverage-v8":"^4.1.11","@stryker-mutator/core":"^10.0.0","@stryker-mutator/vitest-runner":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/spec-guard_0.18.0_1790760686515_0.8552112010511483","host":"s3://npm-registry-packages-npm-production"}},"0.18.1":{"_id":"@descent-vtt/spec-guard@0.18.1","bin":{"spec-guard":"bin/spec-guard.js"},"bugs":{"url":"https://github.com/DescentVTT/spec-guard/issues"},"dist":{"shasum":"30e588b1b985989dba91f543919df349dc57d9af","tarball":"https://registry.npmjs.org/@descent-vtt/spec-guard/-/spec-guard-0.18.1.tgz","integrity":"sha512-4YlIDDcrcd+8XfwAkuj3olqpcfW0O501ckXkjTkx3vYd0ee0zwagw8wF6ed6TSSkB/XI6we69p7sQZgKzl2UQg==","fileCount":210,"unpackedSize":1970010,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@descent-vtt%2fspec-guard@0.18.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCICLOrMiyU1GN39o/omSPvIIl9Q5mwUCy7iboPjJMhXqoAiBJR2BTxb1ycMiov1O88GQQ25clhTbuJ4eUC12oCx2Jlg=="}]},"main":"./dist/index.js","name":"@descent-vtt/spec-guard","type":"module","_from":"file:npm-package/descent-vtt-spec-guard-0.18.1.tgz","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"license":"MIT","scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"","selfcheck":"node ./bin/spec-guard.js --verbose","test:watch":"vitest","test:coverage":"vitest run --coverage","test:mutation":"stryker run","prepublishOnly":"node -e \"if (process.env.GITHUB_ACTIONS !== 'true') { console.error('npm publish is refused outside GitHub Actions: a release is a v* tag, staged by CI with provenance.'); process.exit(1) }\" && npm run clean && npm run build"},"version":"0.18.1","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"d1dc65c8-1e19-4067-bd1e-f20a8ed70c82"},"approver":{"name":"descent-vtt","email":"dev@descentvtt.com"}},"homepage":"https://github.com/DescentVTT/spec-guard#readme","keywords":["adr","architecture","documentation","drift","lint","markdown","ripgrep","spec"],"_resolved":"/home/runner/work/spec-guard/spec-guard/npm-package/descent-vtt-spec-guard-0.18.1.tgz","overrides":{"qs":"^6.16.0"},"specGuard":{"specs":["docs/**/*.md","README.md"],"exclude":["dist","coverage","reports","tests/fixtures"]},"_integrity":"sha512-4YlIDDcrcd+8XfwAkuj3olqpcfW0O501ckXkjTkx3vYd0ee0zwagw8wF6ed6TSSkB/XI6we69p7sQZgKzl2UQg==","repository":{"url":"git+https://github.com/DescentVTT/spec-guard.git","type":"git"},"_npmVersion":"11.20.0","description":"Executable architecture assertions for Markdown specs & ADRs.","directories":{},"maintainers":[{"name":"descent-vtt","email":"dev@descentvtt.com"}],"_nodeVersion":"24.21.0","publishConfig":{"access":"public"},"devDependencies":{"vitest":"^4.1.11","typescript":"^7.0.2","@types/node":"^26.4.1","@vscode/ripgrep":"^1.18.0","@vitest/coverage-v8":"^4.1.11","@stryker-mutator/core":"^10.0.0","@stryker-mutator/vitest-runner":"^10.0.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/spec-guard_0.18.1_1790788494502_0.9176581851703958"},"_hasShrinkwrap":false}},"time":{"created":"2026-09-06T16:53:10.670Z","modified":"2026-09-30T17:14:54.865Z","0.1.0":"2026-09-06T16:53:10.965Z","0.2.0":"2026-09-07T00:15:17.916Z","0.3.0":"2026-09-07T13:12:58.252Z","0.4.0":"2026-09-07T16:21:28.118Z","0.5.0":"2026-09-09T23:59:28.126Z","0.5.1":"2026-09-12T11:52:09.629Z","0.6.0":"2026-09-13T03:19:09.156Z","0.7.0":"2026-09-13T13:25:17.651Z","0.8.0":"2026-09-13T17:12:13.611Z","0.9.0":"2026-09-14T10:28:15.071Z","0.9.1":"2026-09-14T12:29:59.787Z","0.9.2":"2026-09-14T13:31:19.483Z","0.10.0":"2026-09-14T15:50:24.511Z","0.10.1":"2026-09-15T00:09:45.822Z","0.10.2":"2026-09-15T14:50:55.014Z","0.10.3":"2026-09-16T00:06:38.434Z","0.11.0":"2026-09-16T12:01:15.437Z","0.12.0":"2026-09-26T09:00:41.958Z","0.12.1":"2026-09-26T17:47:52.152Z","0.12.2":"2026-09-26T19:09:26.132Z","0.12.3":"2026-09-27T16:14:13.410Z","0.13.0":"2026-09-28T02:46:39.601Z","0.13.1":"2026-09-28T17:42:05.141Z","0.14.0":"2026-09-29T00:03:03.788Z","0.15.0":"2026-09-29T02:00:00.315Z","0.16.0":"2026-09-29T16:17:42.843Z","0.17.0":"2026-09-30T03:05:08.709Z","0.18.0":"2026-09-30T09:31:26.658Z","0.18.1":"2026-09-30T17:14:54.590Z"},"bugs":{"url":"https://github.com/DescentVTT/spec-guard/issues"},"license":"MIT","homepage":"https://github.com/DescentVTT/spec-guard#readme","keywords":["adr","architecture","documentation","drift","lint","markdown","ripgrep","spec"],"repository":{"url":"git+https://github.com/DescentVTT/spec-guard.git","type":"git"},"description":"Executable architecture assertions for Markdown specs & ADRs.","maintainers":[{"name":"descent-vtt","email":"dev@descentvtt.com"}],"readme":"# spec-guard\n\n**Executable architecture assertions for Markdown specs & ADRs.**\n\nTurn the claims your design documents make about your codebase into assertions\nthat run in CI, in milliseconds, with no runtime dependencies.\n\n```md\nThe retired payment gateway is gone from the service layer.\n\n<!-- @assert-absence target=\"src/services\" symbol=\"LegacyPaymentGateway\" -->\n```\n\nIf someone reintroduces `LegacyPaymentGateway`, CI fails and points at the line\nof the ADR that promised it was gone.\n\nThe words the spec-* tools share are defined in\n[concepts](https://github.com/DescentVTT/spec-core/blob/main/docs/concepts.md),\nand the [tutorial](https://github.com/DescentVTT/spec-core/blob/main/docs/tutorial.md)\nruns spec-guard beside its siblings through one round of work on a small\nrepository.\n\n---\n\n## Why this exists\n\nArchitecture Decision Records, RFCs and technical briefs are full of hard claims\nabout a repository:\n\n- *\"`LegacyPaymentGateway` no longer exists anywhere in the service layer.\"*\n- *\"There is exactly one `UserSessionManager`.\"*\n- *\"No secret is ever read from `process.env` outside `src/config`.\"*\n\nEvery one of those claims is true on the day it is written and unverified from\nthe day after. Prose does not fail a build. Six months later the document is\nstill confidently asserting something the code stopped doing in March.\n\nThat has always been an annoyance. It became a defect multiplier the moment\ncoding agents started reading these documents as ground truth. An agent that\nreads *\"module X does not exist yet\"* will happily build a second X. A reviewer\nwho trusts *\"this symbol occurs zero times\"* skips the grep. Stale documentation\nis now executable in the worst sense: it executes inside someone's head, or\ninside a model's context window, and produces work that has to be thrown away.\n\nspec-guard makes the claims executable in the good sense. It reads directives\nwritten as ordinary HTML comments - invisible in every Markdown renderer - and\nchecks them against the real tree with ripgrep. A stale claim becomes a failing\nbuild with a line number, not a landmine.\n\n## Quickstart\n\n```bash\nnpm install --save-dev @descent-vtt/spec-guard\nnpx spec-guard \"docs/**/*.md\"\n```\n\n**The package is scoped; the command is not.** Once installed, the binary is\nplain `spec-guard`, so `npx spec-guard`, `npm scripts` and a global install all\nuse that name:\n\n```bash\nnpm install -g @descent-vtt/spec-guard   # then: spec-guard \"docs/**/*.md\"\n```\n\nWithout a local install, `npx` needs the full package name - `npx spec-guard`\non its own would resolve to a different package on the registry:\n\n```bash\nnpx @descent-vtt/spec-guard \"docs/**/*.md\"\n```\n\nAdd a directive to any Markdown file, directly under the sentence it makes\nexecutable:\n\n```md\n## Decision\n\nSession state has exactly one owner.\n\n<!-- @assert-count target=\"src/\" symbol=\"UserSessionManager\" expected=\"1\" -->\n```\n\nRun it:\n\n```bash\nnpx spec-guard \"docs/**/*.md\" --verbose\n```\n\n```text\nspec-guard 1 spec · 1 assertion · ripgrep\n\n✔ docs/adr/0007-sessions.md:5  @assert-count \"UserSessionManager\" (1 match) in src\n\n1 passed · 7ms\n✔ every spec assertion holds\n```\n\nAnd when it drifts:\n\n```text\n✖ docs/adr/0007-sessions.md:5  @assert-count\n    \"UserSessionManager\" must appear exactly 1 time in src\n    expected exactly 1 match, found 3\n      src/auth/UserSessionManager.ts:12:14   export class UserSessionManager {\n      src/legacy/sessions.ts:4:22            import { UserSessionManager } from '../auth';\n      src/workers/refresh.ts:9:10            const manager = new UserSessionManager();\n\n0 passed · 1 failed · 9ms\n```\n\nExit code 1. The ADR is now a test.\n\n## Directives\n\nEvery directive is an HTML comment. It may span multiple lines. Attribute values\nmay use double or single quotes, and a bare attribute means `=\"true\"`. Inside a\nvalue, `\\\"`, `\\'` and `\\\\` are escapes and any other backslash is kept, so a\nregular expression is written as it reads: `symbol=\"\\bTODO\\b\" regex=\"true\"`.\n\nThere are eight kinds, and each makes one claim about the tree:\n\n| Directive | Claim |\n| --- | --- |\n| `@assert-absence` | this text is gone, or occurs at most N times |\n| `@assert-count` | this text occurs exactly, at least or at most N times |\n| `@assert-import-absence` | no file in scope depends on this module |\n| `@assert-import-count` | exactly, at least or at most N files depend on it |\n| `@assert-layers` | dependencies point one way through these layers |\n| `@assert-import-cycle` | no file depends on itself |\n| `@assert-structure` | files are named by a pattern, directories hold their entries, files have their partners |\n| `@assert-present` | these paths exist |\n\nA directive is read only where a renderer shows Markdown. In code - fenced and\nindented blocks, code spans, `<script>`, `<pre>`, `<style>` and `<textarea>` -\nand in front matter it is text, so documentation that shows the syntax, like\nthis README, never executes it.\n\n- **What is code is what CommonMark says it is**, decided by the Markdown\n  scanner every spec-* tool shares. Comments and code spans are resolved left\n  to right in one pass, so a backtick inside a comment is a character and\n  `<!--` inside a code span is code. A code span ends with its paragraph, so a\n  stray backtick cannot hide the directives after it, and a fence may be\n  indented with the list item it sits in.\n  [ADR-0002](https://github.com/DescentVTT/spec-guard/blob/main/docs/adr/0002-directive-format.md)'s\n  amendment lists where this differs from 0.11.0.\n- **What is masked is still counted.** A comment shaped like a directive -\n  `<!-- @assert-...` - in code, raw HTML or front matter is not run, and the\n  report says how many there were and where, on one line (every one under\n  `--verbose`, and in `maskedDirectives` in JSON), so text read as code by\n  accident is not a rule gone quiet without a word.\n- **A block that never closes is a warning** on its opening line: a code fence\n  or raw-text block, which makes the rest of its document code, and front\n  matter that opens on the first line and never closes. None of that front\n  matter is read as front matter, its status is unrecognised and the document\n  stays in force, and the warning, on line 1, says so and says to close it\n  with `---`, or `+++` for TOML, on a line of its own. Neither fails a run,\n  under `--strict` either.\n- **Line numbers stay exact.** Masking preserves every offset and line\n  terminator.\n\n### `@assert-absence` - this symbol is gone\n\n```md\n<!-- @assert-absence target=\"src/controllers,src/services\" symbol=\"LegacyPaymentGateway\" -->\n<!-- @assert-absence target=\"src/\" symbol=\"STRIPE_SECRET_KEY\" expected=\"0\" -->\n<!-- @assert-absence target=\"src/\" symbol=\"TODO\" expected=\"5\" reason=\"burn down the backlog\" -->\n```\n\nFails when the symbol occurs more than `expected` times (default `0`).\n`max=\"...\"` is accepted as a synonym for `expected`. A bound turns the rule into\na budget: \"at most 5 TODOs\" is an absence claim, and burning a budget down is a\nreal workflow. A lower bound, `min`, is `@assert-count`'s.\n\n### `@assert-count` - this symbol occurs exactly / at least / at most N times\n\n```md\n<!-- @assert-count target=\"src/\" symbol=\"UserSessionManager\" expected=\"1\" -->\n<!-- @assert-count target=\"src/ui/\" symbol=\"PrimaryButton\" min=\"1\" -->\n<!-- @assert-count target=\"src/core/\" symbol=\"DeprecatedHelper\" max=\"3\" -->\n<!-- @assert-count target=\"src/\" symbol=\"Repository\" min=\"2\" max=\"10\" -->\n```\n\nRequires `expected`, or `min` and/or `max`. `expected` cannot be combined with\n`min`/`max`.\n\nAn exact count is the most brittle assertion in the set: a test that merely\nmentions the symbol will break it. spec-guard does not silently skip test files\nfor you - an assertion that quietly ignores part of the tree is the failure mode\nthis tool exists to prevent - so say what you mean:\n\n```md\n<!-- @assert-count target=\"src\" symbol=\"UserSessionManager\" expected=\"1\" exclude=\"*.test.ts *.spec.ts\" -->\n```\n\n`min=\"1\"` is often the better rule anyway: it says \"this exists\" without\nbreaking every time someone writes a second test.\n\n### `@assert-import-absence` / `@assert-import-count` - dependencies, not text\n\nThe rules architecture documents actually contain are usually about\ndependencies, and a text search answers those badly in both directions - it\nmatches a mention in a comment, and it misses `export * from '../db'`.\n\n```md\n<!-- @assert-import-absence target=\"src/ui\" module=\"src/db\" reason=\"the UI talks to services, not storage\" -->\n<!-- @assert-import-count target=\"src\" module=\"axios\" max=\"1\" -->\n```\n\nThese read the dependency rather than the text, in **five languages**:\n\n| Language | Extensions | Reads |\n| --- | --- | --- |\n| JavaScript / TypeScript | `.js .mjs .cjs .jsx .ts .mts .cts .tsx` | `import`, `export ... from`, `require()`, `import()` |\n| Python | `.py .pyi` | `import a.b`, `from .rel import x`, `importlib.import_module(\"x\")` |\n| Go | `.go` | `import \"x\"` and grouped `import ( ... )`, including aliases and `_` |\n| Rust | `.rs` | `use a::{b, c}` with nested groups, `pub use`, `extern crate` |\n| C# | `.cs .csx` | `using`, `using static`, `global using`, `using X = A.B`, `global::` and extern-alias qualifiers, and a using relative to its namespace |\n\nNo parser and no new dependency. JavaScript gets a full tokenizer because a\nmodule reference can appear anywhere in an expression; the other four are read\nby masking comments and string literals with the classifier from\n[ADR-0006](https://github.com/DescentVTT/spec-guard/blob/main/docs/adr/0006-comment-classification.md) and then reading statements\noff what is left. Tree-sitter would have cost 94 MB unpacked against this\npackage's 0.33 MB - [ADR-0008](https://github.com/DescentVTT/spec-guard/blob/main/docs/adr/0008-polyglot-imports.md) has the\nmeasurements, and the list of things a real parser would genuinely see that\nthis does not.\n\nModule patterns are matched against the resolved `/`-separated path *and*\nagainst the specifier as written, so `module=\"System.Text.Json\"` and\n`module=\"System/Text/Json\"` both work. Either form covers what sits beneath it,\nas `module=\"lodash\"` covers `lodash/fp`: `module=\"Shop.Application\"` matches\n`using Shop.Application.Catalog;` and not `using Shop.ApplicationServices;`,\n`module=\"app.db\"` matches `import app.db.client`, and `module=\"crate::db\"`\nmatches `use crate::db::pool`. Matching is case-sensitive, so a rule spanning C#\nand Go needs both conventions: `module=\"app/db/** App/Db/**\"`.\n\nThe unit counted is **files** that depend on the module. For JavaScript and\nTypeScript it understands:\n\n| Form | Counted |\n| --- | --- |\n| `import { A } from 'x'`, `import 'x'`, `import * as ns from 'x'` | yes |\n| `import type { A } from 'x'` | yes, unless `types=\"ignore\"` |\n| `export * from 'x'`, `export { A } from 'x'` | yes - a re-export is a dependency, and a barrel file is how layering rules usually get broken |\n| `require('x')` | yes, with a literal argument |\n| `import('x')` | yes, with a literal argument |\n| `import(name)`, `require(expr)` | **no - reported, see below** |\n\nRelative specifiers are resolved by path arithmetic, so `module=\"src/db\"`\nmatches `../db/client.js` seen from `src/ui/`, and Python's `from ..core import\nx` resolves against the importing file the same way. There is deliberately no\nfilesystem resolution: tsconfig `paths` aliases and package `exports` maps are\nnot followed, so an alias is written out as itself (`module=\"@app/db\"`).\n\n**It tells you what it could not see.** Roughly 1% of module references in real\ncode are dynamic, and about 0.09% of files defeat the tokenizer outright. Both\nare reported rather than counted as clean:\n\n```text\n⚠ docs/adr.md:1  1 module reference could not be resolved statically\n⚠ docs/adr.md:1    src/core/plugin.ts:1 import(name)\n\n1 passed · 9ms\n✔ every spec assertion holds\n```\n\nThe count is still true of everything that could be seen; the warning is what\nstops it being mistaken for a complete answer.\n- **A passing rule prints it** without `--verbose` too, since a green run is\n  when it would otherwise go unread.\n- **`--strict` turns those warnings into failures.**\n- **Files in scope in a language whose imports spec-guard cannot read are\n  counted and reported**, so a rule pointed at the wrong tree says \"analysed 2\n  of 3 files; 1 is in a language whose imports spec-guard cannot read (.razor)\"\n  rather than quietly passing - and if *none* of them can be read, the\n  assertion fails rather than passing on an empty analysis.\n\n[ADR-0005](https://github.com/DescentVTT/spec-guard/blob/main/docs/adr/0005-import-assertions.md) has the measurements and the\nreasoning behind each boundary.\n\n### `@assert-layers` - dependencies point one way\n\n\"Domain must not depend on infrastructure\" across three layers is three\nimport rules, and across five it is ten - a triangle nobody writes down, and\nthe row somebody forgets when a layer is added. One directive states the order:\n\n```md\n<!-- @assert-layers target=\"src\" order=\"src/domain, src/application, src/infrastructure\" -->\n```\n\n**Order runs from the layer everything may depend on to the layer that may\ndepend on everything.** A file may import from its own layer and from any layer\nlisted before it; importing from a layer listed after it is a violation, and\nthe report says which way it went:\n\n```text\n✖ docs/architecture.md:12  @assert-layers\n    src must keep its layers in order, src/domain < src/application < src/infrastructure\n    expected no violating files, found 1\n      src/domain/user.ts:3:1  src/domain -> src/infrastructure: import ../infrastructure/db.js\n```\n\nA layer is a pattern in the same language as `module=` and `exclude`, which is\nwhy this works in all five languages above: `src/domain` is anchored at the\nroot, and a bare `domain` matches that segment anywhere - in `src/domain/user.ts`,\nin Python's `app.domain.user`, in Rust's `crate::domain::user`. A layer may also\nbe a single file; `order=\"src/parser.ts, src/cli.ts\"` understands that\n`./parser.js` is `src/parser.ts`. C# is layered by namespace, and has\n[a section of its own](#c-and-net-solutions).\n\nThe unit is files, and `max`, `types`, `exclude` and `baseline` mean what they\nmean on `@assert-import-absence`. Five things fail rather than pass, because\neach is a rule that would otherwise check less than it says:\n\n- a layer that matches no file (`order=\"domain, aplication\"`);\n- a file two layers both claim;\n- a target that does not exist;\n- a layer no C# `using` can reach, because it matches none of the namespaces its\n  own files declare - `src/Shop.Application` rather than `Shop.Application`;\n- a scope in which no import reaches a layer other than its own file's, since\n  that rule passes whatever order its layers are listed in:\n\n```text\n✖ docs/architecture.md:12  @assert-layers\n    src must keep its layers in order, src/domain < src/application < src/infrastructure\n    no import in scope reaches a layer other than its own file's, so these layers would pass in any order (add allow-empty=\"true\" if that is expected)\n```\n\n`allow-empty=\"true\"` turns the first and the last two into warnings. Files that\nno layer claims are left alone and counted, so a directory nobody assigned shows\nup as a number rather than as silence.\n\n### C# and .NET solutions\n\nA .NET project has three names: its folder, its project file and its root\nnamespace. `dotnet new` gives all three the same one, and that is what lets a\nsingle pattern do both halves of a layer rule - hold the files under\n`src/Shop.Domain`, and reach `using Shop.Domain.Orders;` from anywhere else:\n\n```md\n<!-- @assert-layers target=\"src\" order=\"Shop.Domain, Shop.Application, Shop.Infrastructure, Shop.Web\" reason=\"dependencies point inward\" -->\n<!-- @assert-import-absence target=\"src/Shop.Application\" module=\"Microsoft.EntityFrameworkCore\" reason=\"persistence is infrastructure's\" -->\n```\n\n- **Name a C# layer by its namespace.** `Shop.Domain` matches the folder as a\n  path segment, and the namespace with everything under it - `Shop.Domain.Orders`,\n  but not `Shop.DomainEvents`. A folder path such as `src/Shop.Domain` holds the\n  right files, but a using names a namespace, never a path, so nothing can reach\n  it: such a rule fails, and names a namespace the layer's files declare. Where\n  folders and namespaces differ, as when `src/Domain` holds\n  `Acme.Clean.Domain.Entities`, the name they share - `Domain` - does both.\n- **`module=` is a namespace too**, as above: `module=\"Shop.Infrastructure\"`\n  covers `using Shop.Infrastructure.Persistence;`.\n- **What is read**: `using`, `global using`, `using static` and aliases, with\n  any `global::` or extern-alias qualifier left off the name. A using inside a\n  namespace may be relative to it, so `using Application.Orders;` inside\n  `namespace Shop.Domain` also counts as `Shop.Application.Orders`. Nothing in a\n  comment, a verbatim string or a raw string literal is read.\n\nWhat it cannot see, and the text rule that covers each - a text rule reads a\nname wherever it is written:\n\n| Not seen by an import rule | Held by |\n| --- | --- |\n| A fully qualified name with no using: `new Shop.Infrastructure.Db()` | `@assert-absence target=\"src/Shop.Domain\" glob=\"*.cs\" symbol=\"Shop.Infrastructure\" word=\"true\"` |\n| A `<ProjectReference>`, or a `<Using Include>` in a project file | the same rule with `glob=\"*.csproj,*.props\"` |\n| `@using` in `.razor` and `.cshtml`, which import rules count as files they could not read | the same rule with `glob=\"*.razor,*.cshtml\"` |\n| Code a source generator writes | nothing: it is not in the tree |\n\nIn a solution of projects, the project references are the layering the\ncompiler enforces - a using of a project that is not referenced does not build -\nso a rule over the project files is worth having beside the layer rule:\n\n```md\n<!-- @assert-absence target=\"src/Shop.Domain\" glob=\"*.csproj\" regex=\"true\" symbol=\"Shop\\.(Application|Infrastructure|Web)\\b\" reason=\"the domain references no outer project\" -->\n```\n\nKeep build output out of every rule in `.spec-guard.json`:\n\n```json\n{\n  \"specs\": [\"docs/**/*.md\"],\n  \"exclude\": [\"bin\", \"obj\", \"artifacts\", \"TestResults\", \".vs\"]\n}\n```\n\n`bin` and `obj` are MSBuild's output, `artifacts` is where the output goes with\n`UseArtifactsOutput` (.NET 8 and later), `TestResults` is where `dotnet test`\nwrites, and `.vs` holds Visual Studio's caches. A front end in the same tree\nadds its own, such as Nuxt's `.output`; `node_modules` is skipped already.\n\n### `@assert-import-cycle` - no file depends on itself\n\n```md\n<!-- @assert-import-cycle target=\"src\" types=\"ignore\" -->\n```\n\nA cycle is reported as one concrete loop, with the line of every import on it:\n\n```text\n✖ docs/architecture.md:20  @assert-import-cycle\n    src must have no import cycles (type-only imports ignored)\n    expected no import cycles, found 1\n      src/orders/cart.ts:4:1  src/orders/cart.ts:4 -> src/billing/invoice.ts:2 -> src/orders/cart.ts\n```\n\nThe count is **knots, not loops**: a set of files each reachable from the others\ncounts once however many routes run around it, so adding an import inside a\ntangle that already exists does not move the number. `max=\"2\"` adopts the rule\non a codebase that already has two, and fails on the third.\n\n`types=\"ignore\"` asks the runtime question - erased imports create no load-order\ncycle - and the default asks the coupling one. This repository needs both: its\n`src/` has exactly one cycle, and it is type-only.\n\n`dynamic=\"ignore\"` asks it about `import()` too. A plugin that `configuration.ts`\nloads with `import('./tier-boot.ts')` can import `configuration.ts` back without\nany module waiting on another to load, so a loop closed only by `import()` is\nleft out. A static import between the same two files keeps the loop. The one\ncase this lets through is a **top-level `await import()`**, which does run while\nits module loads and can deadlock a cycle. It looks the same to a tokenizer as\nan `await import()` inside a function, so ignoring dynamic imports ignores both.\n`require()` always counts: whether it runs at load depends on where it is\ncalled.\n\n**Cycles are JavaScript and TypeScript only**, because a cycle needs to know that\n`./b.js` *is* `src/b.ts`, and in the other four languages an import names a\nmodule, package or namespace rather than a file. A scope with no JavaScript or\nTypeScript in it fails instead of reporting no cycles. The resolver is a short,\nfixed table - the TypeScript source of an emitted `.js`, the path as written,\nthe path with each extension, the directory's `index` - checked against files\nthe walk already found, never against the disk.\n\nIt says what it could not follow. An import that should have become an edge and\ndid not - a relative path matching no file, or an alias like `@/db` or\n`#internal/db` that cannot be a package - is reported, and fails the run under\n`--strict`. An alias spelled like a real package, `@app/db` through `tsconfig`\npaths, is the one thing it cannot see and cannot report: that would mean\nreading `tsconfig.json`, which is the resolver\n[ADR-0011](https://github.com/DescentVTT/spec-guard/blob/main/docs/adr/0011-layers-and-cycles.md) declines to become, for the\nreasons it gives.\n\n### `@assert-structure` - what files are called, and what comes with them\n\nArchitecture documents state conventions over sets of files rather than naming\nfiles one by one. Each directive makes exactly one of three claims:\n\n```md\n<!-- @assert-structure target=\"src/domain\" exclude=\"*.test.ts\" pattern=\"*.entity.ts, index.ts\" -->\n<!-- @assert-structure target=\"packages\" dirs=\"*\" required=\"package.json, README.md\" -->\n<!-- @assert-structure target=\"src/handlers\" exclude=\"*.test.ts\" partner=\"[name].test.ts\" -->\n```\n\n- **`pattern`** - every file in scope is named by one of the patterns. They are\n  globs, read like `glob=`: without a `/` against the file name, with one\n  against the path from the root.\n- **`required`** - every directory holds every entry. Without `dirs` the\n  directories are the targets; `dirs=\"*\"` means their immediate children and\n  `dirs=\"**\"` every directory below them. `dirs` names directories, so a\n  trailing `/` there changes nothing, on the whole of it or on an alternative\n  of its braces: `dirs=\"{api/,web}\"` is `api` and `web`, where a spec\n  pattern reads `api/` there as what `api` holds. An entry may be a path\n  (`src/index.ts`), may end in a glob (`*.csproj`), and must be a directory\n  when it ends in `/`.\n- **`partner`** - every file has a partner, named by a template.\n\nEach failure names the file or directory, since there is no line to point at:\n\n```text\n✖ docs/architecture.md:3  @assert-structure\n    files in src/domain must be named *.entity.ts or index.ts (excluding *.test.ts)\n    expected no misnamed files, found 1\n      src/domain/helpers.ts  matches none of *.entity.ts, index.ts\n\n✖ docs/architecture.md:4  @assert-structure\n    directories matching * under packages must contain package.json, README.md\n    expected no directories missing an entry, found 2\n      packages/billing  missing README.md\n      packages/web  missing package.json, README.md\n\n✖ docs/architecture.md:5  @assert-structure\n    files in src/handlers must each have a partner [name].test.ts (excluding *.test.ts)\n    expected no files without a partner, found 1\n      src/handlers/refund.ts  has no partner src/handlers/refund.test.ts\n```\n\nA partner template has three placeholders and nothing else - no regular\nexpressions, no conditionals - so a reader can expand one by eye:\n\n| Placeholder | For `src/api/user.handler.ts`, `target=\"src\"` |\n| --- | --- |\n| `[name]` | `user.handler` - the file name up to its last dot |\n| `[ext]` | `ts` - what follows that dot |\n| `[dir]` | `api` - the file's directory below the target, empty at the top |\n\nA template without a `/` names a file beside it. One with a `/` is a path from\nthe root, which is how a mirrored test tree is written:\n`partner=\"tests/[dir]/test_[name].py\"`. A comma-separated list gives\nalternatives, any one of which will do.\n\nThe partners themselves are in scope unless `exclude` says otherwise. Forgetting\nto exclude them is loud rather than silent, and says what probably happened:\n\n```text\n      src/handlers/order.test.ts  has no partner src/handlers/order.test.test.ts (it is the partner of src/handlers/order.ts - exclude it?)\n```\n\nSome things fail rather than pass, because each is a rule that would otherwise\ncheck nothing:\n- a scope holding no files, or selecting no directories (`allow-empty` as\n  everywhere else);\n- a template that names the file itself (`partner=\"[name].[ext]\"`);\n- a `required` target that is a file.\n\n**Names are compared exactly, on every platform.** Whether `README.md` exists is\ndecided by reading its directory, never by asking the filesystem for the path.\nThat lookup finds `Readme.md` on Windows and macOS and does not find it on Linux,\nand the same rule would pass on a laptop and fail in CI.\n\nA structure rule reads names, never contents. It walks with the run's usual\nskips, follows no symbolic link, and counts the spec files - which every other\nrule leaves out, and which a naming rule about `docs/adr` is about. `max`,\n`baseline` and `ratchet` work as they do on `@assert-absence`, and a baseline\nlists files or directories. `spec-guard query` shows what a rule asks of a file\nthat does not exist yet:\n\n```text\nsrc/handlers/invoice.ts (does not exist yet)\n  1 rule from 1 document\n\n  Architecture  (docs/architecture.md)\n    :5 @assert-structure  files in src/handlers must each have a partner [name].test.ts (excluding *.test.ts)\n      partner: src/handlers/invoice.test.ts\n```\n\n[ADR-0013](https://github.com/DescentVTT/spec-guard/blob/main/docs/adr/0013-structure-assertions.md) has the design and what it\ncosts.\n\n### `@assert-present` - this file exists\n\n```md\n<!-- @assert-present file=\"SECURITY.md\" -->\n<!-- @assert-present file=\"config/production.json,config/staging.json\" -->\n```\n\nPasses when every listed path exists relative to `--root`. Directories count.\n\n### Attributes\n\n| Attribute | Applies to | Meaning |\n| --- | --- | --- |\n| `target` | all but present | Comma-separated paths, relative to `--root`. Default `.` |\n| `symbol` | absence, count | The literal string to search for (or a regex with `regex=\"true\"`) |\n| `file` | present | Comma-separated paths that must exist |\n| `expected` | all but present | Exact count for count; an upper bound everywhere else |\n| `min` / `max` | count (`max` on all but present) | Inclusive bounds |\n| `glob` | absence, count, structure | Include-only file filters, e.g. `*.ts,*.tsx` (ripgrep `-g` semantics) |\n| `exclude` | all but present | Paths to leave out, gitignore-style: `src/config/**`, `tests`, `*.test.ts` |\n| `regex` | absence, count | Treat `symbol` as a regular expression |\n| `word` | absence, count | Require word boundaries, so `Primary` does not match `PrimaryButton` |\n| `ignore-case` | absence, count | Case-insensitive matching |\n| `comments` | absence, count | `ignore` (default) or `include` for matches inside comments |\n| `module` | import-absence, import-count | Which dependency, matched like `exclude` |\n| `order` | layers | The layers, from the one everything may depend on to the one that may depend on everything |\n| `pattern` | structure | The names every file in scope must match one of |\n| `required` | structure | The entries every chosen directory must hold; a trailing `/` means a directory |\n| `dirs` | structure, with `required` | Which directories below each target: `*` for children, `**` for all; a trailing `/` changes nothing, in braces or out |\n| `partner` | structure | Partner templates, any one of which must exist: `[name].test.[ext]` |\n| `types` | import assertions, layers, cycles | `include` (default) or `ignore` for `import type` |\n| `dynamic` | cycles | `include` (default) or `ignore` for `import('x')` |\n| `allow-empty` | all but present | Tolerate a scope that holds no files, a layer that matches none, a layer no C# using can reach, layers no import crosses between, or no chosen directories. Off by default - see below |\n| `baseline` | absence, import-absence, layers, structure | Known violations that do not count: `path` or `path:count` |\n| `ratchet` | absence, import-absence, layers, structure | `two-sided` (default) or `one-way` - see below |\n| `reason` | all | Human-readable justification, printed on failure |\n\nUnknown attributes are an error, not a shrug: `expct=\"1\"` fails the run instead\nof silently asserting nothing. A spec tool whose typos assert nothing is worse\nthan no spec tool.\n\n### `exclude` - everywhere except\n\nMost real rules are \"nowhere except one place\", not \"not here\":\n\n```md\n<!-- @assert-absence target=\"src\" symbol=\"process.env\" exclude=\"src/config/**\" -->\n```\n\nThat is the rule this README opens with - *no secret is ever read from\n`process.env` outside `src/config`* - written as one assertion instead of a\nhand-maintained list of every directory that is not `src/config`.\n\n`exclude` follows gitignore rules, which are **not** the same as `glob`'s:\n\n| Pattern | Excludes |\n| --- | --- |\n| `tests` | any directory or file named `tests`, at any depth, and everything under it |\n| `/tests` | only the `tests` at the root, and everything under it |\n| `src/config` | that directory and everything under it |\n| `src/config/**` | the same, written explicitly |\n| `*.test.ts` | any file with that name shape, at any depth |\n\nThe difference is deliberate. `glob=\"*.ts\"` filters files, so basename matching\nis what you want; `exclude=\"tests\"` means the directory, because that is what\npeople mean when they write it - and it is what `rg -g '!tests'` does. Both\nengines implement the same rule, and a parity matrix asserts they agree on it.\n\nA leading `./`, with the slashes after it, and a trailing `/` are dropped, so\n`./tests`, `.//tests` and `tests/` are `tests`, and a backslash is a separator. Four shapes are refused, because they\ncan never exclude anything:\n- **`!`**, which in `.gitignore` re-includes a path. Pasted from one, it was\n  silently dropped and the exclusion left wider than it read.\n- **`..`**, since nothing outside the root is searched.\n- **a drive path** such as `C:/repo/dist`.\n- **`.` or `/`**, the root itself.\n\nSo is any pattern the glob engine cannot read - an unclosed `[` or `{`, an\nextended glob such as `+(a|b)`, a range that runs backwards, `**` inside a\nname, one too large to compile - rather than being read as a literal that\nexcludes nothing. The same goes for `glob`, `module`, `order` and the\nstructure rules' patterns, and for a spec pattern.\n\n`**` means any number of directories only as a whole segment. `docs/**.md` is\nrefused, with the two ways to say what was meant, written from the pattern:\n`docs/**/*.md` for any depth, `docs/*.md` for one level. For any depth the\nstars become a segment of their own, with a star kept on each side where the\nname went on; for one level they become one star: `src/a**` is told\n`src/a*/**` or `src/a*`. The tools it could have come from read it three ways,\nand a spec pattern read the narrow way drops every nested document without a\nword.\n\nIn a directive a refused pattern is an invalid directive, whether or not its\ndocument is in force; in the configuration's `specs` or `exclude`, a spec\npattern on the command line or `--spec`, or `--exclude`, it is exit 2.\n\nList attributes accept commas or whitespace, so both of these work:\n\n```md\n<!-- @assert-absence target=\"src\" symbol=\"TODO\" exclude=\"src/legacy/** tests\" -->\n<!-- @assert-absence target=\"src\" symbol=\"TODO\" exclude=\"src/legacy/**,tests\" -->\n```\n\nTwo things therefore cannot be written in an attribute:\n- **A path containing a space**: there is no quoting inside an attribute value.\n- **A brace group with a comma in it**: `glob=\"*.{ts,tsx}\"` is the two patterns\n  `*.{ts` and `tsx}`, and is refused with a message that says so. Write\n  `glob=\"*.ts, *.tsx\"`.\n\nA configuration's `exclude` and `specs` are JSON arrays, where a brace group\nkeeps its commas. Inside one, an alternative reads as it would written alone:\n- **A trailing `/`** means what it means on a whole pattern: `{build/,dist}` in\n  `exclude` is both directories and what they hold, and `{docs/,README.md}` in\n  `specs` is everything under `docs`, and the README.\n- **A leading `/`** anchors it at the root, as it anchors a whole pattern:\n  `{/build,dist}` in `exclude` is the `build` at the root, and every `dist`.\n  After a `./` it anchors nothing, as in `.//build`: `./{/build,dist}` is\n  every `build`.\n- **An alternative that names no path is refused**: `{./,docs}` in `specs` is\n  exit 2, `the braces expand to \"./\", which names no path`.\n\n### `comments` - the note about a deletion is not the deletion\n\nYou delete a symbol and leave the explanation where the next person will look:\n\n```ts\n// LegacyThing was removed in ADR-398; do not reintroduce it.\n```\n\nA plain text search reads that comment as an occurrence, so the assertion that\nkeeps the symbol deleted fails on the sentence proving it was deleted. Both\nfixes are bad: delete the note and lose the reason, or delete the rule.\n\nSo matches inside comments do not count:\n\n```md\n<!-- comments are ignored by default -->\n<!-- @assert-absence target=\"src\" symbol=\"LegacyThing\" -->\n\n<!-- ...unless you ask for them -->\n<!-- @assert-absence target=\"src\" symbol=\"Copyright\" comments=\"include\" -->\n```\n\n`comments=\"include\"` is right for assertions that really are about text — a\nlicence header, or a name that must appear nowhere in the repository at all.\n\nBecause this is the one thing that can turn a failing run green without anyone\ntouching code, a run that passed this way says so:\n\n```\n⚠ 1 match inside comments was not counted; add comments=\"include\" to count it\n\n1 passed · 7ms\n✔ every spec assertion holds\n```\n\nComment syntax is known for around 68 extensions across 11 families (JS/TS, C,\nC#, Rust, Go, Python-style `#`, shell `#`, YAML, SQL-style `--`, markup -\nMSBuild project files included - and formats with no comments at all). What\nwould hide real code if misread is tracked too:\n- **Strings**, because `//` inside a URL is not a comment.\n- **JavaScript's regular expressions**, because the quote in `/[\"']/` is not a\n  quote.\n- **What only looks like either**: a Rust lifetime (`&'static str`), a C++ digit\n  separator (`100'000`), a `#` inside a shell word (`${#items[@]}`), an\n  apostrophe in a YAML value (`name: it's fine`) and a `/*` in JSX text\n  (`<div>/*</div>`) all open nothing.\n\nWhere spec-guard is unsure — an unknown extension, an unterminated literal — the\ntext counts as code, and the report says which files it could not classify. A\nmatch wrongly kept is a visible failure you can argue with; a match wrongly\ndropped is a lie.\n\n### `allow-empty` - an assertion that covers nothing is a failure\n\n```md\n<!-- @assert-absence target=\"services\" symbol=\"Legacy\" glob=\"*.ts\" -->\n```\n\nIf `services/` holds no `.ts` file, that rule passes every time, forever,\nwithout inspecting anything - and in the report it is indistinguishable from a\nrule that inspected a thousand files and found nothing. So it fails instead:\n\n```text\n✖ docs/adr.md:3  @assert-absence\n    \"Legacy\" must not appear in services\n    no files were inspected, so this assertion verified nothing\n    (add allow-empty=\"true\" if that is expected)\n```\n\nThe usual causes are a `glob` matching no extension in the tree, an `exclude`\nthat swallowed the target, or a directory somebody emptied. Where covering\nnothing yet is the honest state of the world - a rule written before the code\nit guards - `allow-empty=\"true\"` says so, and `--allow-empty-scope` says it for\na whole run.\n\nA `target` that does not exist fails the run too: an assertion pointed at a\nrenamed directory would otherwise search nothing, find nothing and report\nsuccess. `--allow-missing-targets` makes it a warning, for a repository where a\npath is legitimately optional.\n\n### `baseline` - adopting a rule the codebase already breaks\n\nA strict rule introduced into a mature codebase lands on violations that already\nexist. `exclude` turns those into a permanent blind spot, and `expected=\"5\"`\ncannot tell \"one fixed, one added\" from \"nothing happened\". A baseline names\nthem:\n\n```md\n<!-- @assert-absence target=\"src\" symbol=\"LegacyGateway\"\n     baseline=\"src/legacy/gateway.ts:2\n               src/legacy/adapter.ts\" -->\n```\n\nThe rule now holds when no file outside the list matches and no file inside it\nmatches more than it declares. A bare path means one match.\n\n**It ratchets in both directions.** New debt fails, obviously. So does debt that\nhas been *paid* and left on the list, because an entry the code no longer\nsupports is a spec asserting something untrue:\n\n```text\n    expected no matches, found 0; the baseline is out of date and must be\n    pruned: src/legacy/adapter.ts (no longer matches)\n```\n\nThe fix is deleting the line the message names. `ratchet=\"one-way\"` relaxes that\nhalf to a report-only note. Every run says how many matches the baseline\nexcluded, because a pass bought by an exemption is never silent.\n\nTo adopt a rule on a codebase that already violates it:\n\n```bash\nspec-guard docs/adr.md --print-baseline\n```\n\nprints the attribute that would exempt exactly today's violations, for you to\npaste in. It prints; it does not edit. [ADR-0009](https://github.com/DescentVTT/spec-guard/blob/main/docs/adr/0009-debt-baselines.md)\nexplains why that distinction is the whole design, and why there is no `--fix`\nfor architecture rules.\n\n## What gets searched\n\nAn assertion is worth exactly as much as the set of files behind it, so\nspec-guard is explicit about that set and never quietly narrows it.\n\n**Four directory names are skipped**, and nothing else:\n\n| Skipped | Why |\n| --- | --- |\n| `.git`, `.hg`, `.svn` | version-control stores hold compressed copies of code you deleted on purpose |\n| `node_modules` | code you did not write, which your architecture rules are not about |\n\nEverything else is searched. That includes **hidden directories** - `.github`,\n`.husky`, `.claude-rules`, `.agents` - because that is where CI, hooks and agent\nrules live, and a rule that cannot see your workflow files is not enforcing much.\nIt also includes `dist`, `build`, `out` and `coverage`, because spec-guard\ncannot tell build output from a directory of build scripts, and guessing wrong\nmeans a rule silently stops covering anything.\n\n`.gitignore` is not consulted. It describes what git should carry, not what a\nrule covers - and ripgrep applies it only inside a git repository, so honouring\nit made the same tree answer differently depending on whether a `.git` directory\nhappened to exist above it.\n\nTo narrow scope, say so in the assertion:\n\n```md\n<!-- @assert-absence target=\"src\" symbol=\"TODO\" exclude=\"dist coverage\" -->\n```\n\n`--no-default-skips` removes even those four, for a run that has to be certain.\n\n### Spec files are left out of their own searches\n\nAn ADR that says \"`LegacyGateway` must not appear\" contains the string\n`LegacyGateway`, so without this every absence rule would fail on the document\nasserting it - the single most confusing possible first-run experience.\n- **`--include-specs`** restores the naive behaviour, and counts the prose of\n  your specs.\n- **The directives themselves stay uncounted** even then: a directive is an\n  HTML comment, and a rule whose own text trips it can never be satisfied.\n  `comments=\"include\"` counts even those.\n- **`@assert-structure`**, which reads names rather than text, is the one rule\n  that counts the spec files.\n\n### Nothing is skipped quietly\n\nA file spec-guard could not read, or one whose bytes are not text but which\ncontained the symbol anyway, is a gap in the answer rather than a detail of it.\nThose are reported, and `--strict` fails on them:\n\n```text\n✖ docs/adr.md:3  @assert-absence\n    \"ApiKey\" must not appear in .\n    expected no matches, found 0, and 1 file could not be inspected\n    ⚠ 1 match in 1 binary file not counted: build/app.bin\n```\n\nThe counts are in `--json` too, as `skipped` on each result.\n\n## Document status - drafts and superseded ADRs\n\nAn ADR has a life. It is `Proposed` before anyone agrees to it, and `Superseded`\nlong before anyone deletes it - because deleting it deletes the reason a\ndecision was made.\n\nspec-guard reads that status from the document and honours it. A document whose\nstatus is `draft`, `proposed`, `rejected`, `deprecated`, `superseded` or\n`archived` is parsed, validated, reported - and not executed. `archived` is what\n`spec-brief` writes when it closes a task brief's round: the brief is kept as\nthe record, and its directives, which stated the round's premises and goals,\nare history.\n\nFour spellings are recognised, because four are in use:\n\n<!-- Shown fenced on purpose: spec-guard masks code before reading a status. -->\n\n```md\n---\nstatus: proposed\n---\n```\n\n```md\n## Status\n\nAccepted (0.3.0).\n```\n\n```md\n| Status | Accepted |\n| ------ | -------- |\n```\n\n```md\n**Status:** accepted\n```\n\nFront-matter wins, then the `## Status` section, then a table, then the bold\nlabel, and the first of them that is there decides:\n\n- **Front matter** is YAML between `---` lines or TOML between `+++` lines. Of\n  TOML, only the top-level `status` key is read, and only as a string on one\n  line: `status = \"accepted\"` or `status = 'accepted'`. Front matter without a\n  `status` key, YAML or TOML, hands over to the section, the table and the\n  label.\n- **A section's value** is its first line of prose before the next heading.\n  Headings are read as CommonMark reads them, so an underlined `Status` is the\n  section and a `## Status` kept in a comment is not.\n- **The table and the label** are only read above the first section heading.\n  A table is read when it has exactly two columns and one of its rows, the\n  header row or another, names the status in its left cell - `Status` or\n  `State`, in any case, bold or not - and gives it in the right. A table of\n  more columns, or one further down, is a register or a legend of other\n  documents and is never read for this one's status.\n- **A status that cannot be read still decides**: the document stays in force,\n  the report warns on its line with the reason, and nothing ranked below it is\n  read in its place. In front matter that is a value such as\n  `status: \"accepted\" (2024-05-01)`, text after a closing quote, or in TOML a\n  multi-line string, an array, a table or a value that is not a string; in a\n  section, a table or a label, an empty section or a line that begins with no\n  word.\n- **Front matter that opens on the first line and never closes** is read the\n  same way: none of it can be read, so the status is unrecognised, the document\n  stays in force, the section and the label are not read in its place, and the\n  report warns on line 1 and says how to close it.\n- **Anything else** - `Provisional`, `In review`, a misspelled `Supersedded`, or\n  no status at all - keeps enforcing.\n\nThat asymmetry is deliberate: an unanticipated word that keeps enforcing is a\nvisible failure with an obvious fix, while one that stops enforcing is a green\nbuild over a rule nobody is checking.\n\nThe status is read in English. A document may be written in any language, and\nits status is written in English under an English key - `status: superseded`,\nor `## Status` over `Superseded by ADR-0007` - which every spec-* tool reads.\nA word in another language under that key, `status: 已取代`, is a status that\ncannot be read: the document stays in force, and the report warns and says to\nwrite the status as an English word. A key in another language, `## 狀態` or\n`| 狀態 | 已取代 |`, names no status, and the document stays in force.\n\nWithholding is never quiet:\n\n```text\n○ docs/adr/0011-queues.md is Proposed. - 2 assertions not executed\n\n12 passed · 2 not in force · 48ms\n```\n\nBy name, not by count - the same fact reaches `--format json` as `inactiveSpecs`\nand `--format sarif` as a note-level execution notification. A withheld\ndirective is still checked for typos and bad attributes, so a draft's mistake is\nfound on the day it is written rather than on the day it is accepted.\n`--ignore-status` runs everything, which is how you ask whether a draft would\npass if you accepted it today.\n\nA run in which nothing is in force executes no assertion, and says so rather\nthan that every assertion holds: `no assertion was executed, so nothing was\nverified`. Under `--strict`, or `\"strict\": true`, that run fails, exit 1, as\nthe family contract has a check that measured nothing do: JSON says\n`\"ok\": false` and `\"nothingVerified\": true`, and SARIF, GitHub and GitLab carry\na `nothing-verified` finding. One rule in force is enough to pass, whatever else\nis withheld; and the MCP server's check of paths that no rule governs verified\nwhat it was asked to, and passes.\n\n[ADR-0010](https://github.com/DescentVTT/spec-guard/blob/main/docs/adr/0010-spec-status.md) has the full reasoning, including why\nthere is no per-directive `if-status` attribute.\n\n## Asking before writing - `query` and the MCP server\n\nA run tells you, after the fact, that code broke a rule. `spec-guard query`\ntells you which rules a file is under before you touch it:\n\n```bash\nspec-guard query src/domain/user.ts --spec \"docs/**/*.md\"\n```\n\n```text\nsrc/domain/user.ts\n  3 rules from 2 documents\n\n  ADR-0004: No legacy client  (docs/adr/0004-legacy.md, accepted)\n    :12 @assert-absence  \"LegacyClient\" must not appear in src\n\n  ADR-0011: Layering constraints  (docs/adr/0011-layers.md, accepted)\n    :40 @assert-layers  src must keep its layers in order, src/domain < src/application < src/infrastructure\n      layer: src/domain (1 of 3)\n      may import: src/domain\n      must not import: src/application, src/infrastructure\n      reason: the domain depends on nothing\n    :41 @assert-import-absence  src/domain must not import \"pg\"\n\n  1 more rule would govern this path if docs/adr/0014-clocks.md (proposed) were in force; --ignore-status lists it\n\n14 spec files read in 6.1ms\n```\n\nIt answers from the specs alone, without reading the codebase, so it works for\na file that does not exist yet. A directory lists every rule that could reach a\nfile under it. `--json` is the same answer for a script. Rules in documents that\nare not in force are counted and named, never silently left out.\n\nA path that no rule governs because something excluded it says so, since\n\"nobody wrote a rule\" and \"somebody set this aside\" call for different things:\n\n```text\ntarget/debug/build.rs\n  no rules in force govern this path: the project's exclude leaves it out (target)\n\nsrc/legacy/generated/api.ts\n  no rules in force govern this path: exclude=\"...\" leaves it out of 1 rule\n\n  left out by exclude=\"...\":\n    docs/adr/0004-legacy.md:12 @assert-absence  \"LegacyClient\" must not appear in src (excluding src/legacy)\n```\n\nIn JSON, each path carries `excluded.project`, the project patterns that match\nit, and `excluded.rules`, the rules whose own `exclude` leaves it out where the\nproject's does not.\n\nThe arithmetic that decides whether a rule governs a path is tested against the\nwalk a real run makes, file for file, under both engines and on randomly\ngenerated trees. [ADR-0012](https://github.com/DescentVTT/spec-guard/blob/main/docs/adr/0012-query-and-mcp.md) lists the three\nthings it cannot see: file content (binary, oversized, unreadable), symbolic\nlinks, and letter case on case-insensitive filesystems.\n\n### The MCP server\n\n`spec-guard mcp` serves the same answer to an AI agent over the\n[Model Context Protocol](https://modelcontextprotocol.io) on stdio, with no\ndependency on the MCP SDK. Register it with your client as a stdio server; the\nusual `mcpServers` entry is:\n\n```json\n{\n  \"mcpServers\": {\n    \"spec-guard\": {\n      \"command\": \"npx\",\n      \"args\": [\"spec-guard\", \"mcp\", \"--spec\", \"docs/**/*.md\"]\n    }\n  }\n}\n```\n\nThe root defaults to the directory the client starts the server in; pass\n`--root` if yours starts servers somewhere else. On Windows, `npx` is a `.cmd`\nscript that a client spawning without a shell cannot launch; point `command` at\n`node` and the first argument at\n`node_modules/@descent-vtt/spec-guard/bin/spec-guard.js` instead. Run flags such\nas `--engine`, `--strict`, `--ignore-status` and `--allow-missing-targets` apply\nto its checks.\n\n| Tool | What it does |\n| --- | --- |\n| `get_architectural_rules(path, include_inactive?)` | The query above, as text and as structured content |\n| `check_architecture(paths?)` | A run. Given paths, only the rules that govern them, each over its whole scope, with every violation marked as in those paths or not |\n| `get_dependents(paths, depth?, include_inactive?)` | [`impact`](#who-depends-on-this---impact): the files that import each path, however far away, with the import that leads there, the imports that could not be followed, and the rules in play. The structured content is the document `impact --json` writes |\n\nAll three are marked read-only, idempotent and closed-world. The server's\ninstructions tell an agent when to call each: the rules before creating or\nchanging a file, the dependents before changing a file others import, and the\ncheck after changing files.\n\n| Resource | What it holds |\n| --- | --- |\n| `spec://rules` | Every rule in force, as JSON |\n| `spec://doc/{+path}` | Any spec document, in force or not |\n\nBoth protocol eras are served: clients that open with `initialize` (revisions\n2024-10-07 to 2025-11-25), and clients on 2026-07-28 that put the protocol\nversion on every request and probe with `server/discover`. Every spec is read\nagain on every request, so an ADR edited mid-session is read as edited, and a\nrequest takes longer the more specs there are: a warm `get_architectural_rules`\ntook about 7 ms over this repository's 19 and about a third of a second over\n1,300 copies of them, on the machine ADR-0012 was measured on.\n`scripts/bench-query.mjs`, in the repository, measures yours. ADR-0012 has the\nshapes, the sources they follow, and what is deliberately not implemented.\n\n## Can each rule fail? - `prove`\n\nA passing rule says one of two things, and the report cannot tell which: the\ncode holds, or the rule cannot see the code. A `glob=\"*.js\"` over a codebase\nwritten in TypeScript passes, and would pass whatever the code did.\n\n```bash\nspec-guard prove\n```\n\n`prove` shows each rule in force a violation of itself and runs the rule over\nit: a file holding the forbidden text beside the files the rule reads, a file\nimporting the forbidden module, two files importing each other, a file in a\nlower layer importing a higher one, a misnamed file, a required entry or a\npartner taken away, a file the rule requires removed. The violation is made **in\nmemory**, through the same door every read goes through. Nothing is written to\ndisk, and nothing touches git.\n\n```text\nspec-guard prove 3 specs · 12 rules\n\n✖ docs/adr/0004-legacy.md:12  @assert-absence  passed with a violation in place\n    \"LegacyClient\" must not appear in src\n    maximum: added src/spec-guard-prove.ts holding \"LegacyClient\", beside the code under src, none of which the rule reads, and it still passed: expected no matches, found 0\n\n○ docs/adr/0009-queue.md:8  @assert-absence  no violation could be made\n    \"enqueueRaw\" must not appear in src/queue\n    it fails on the tree as it stands (expected no matches, found 1), so no change can be shown to be what fails it\n\n10 seen to fail · 1 survived · 1 unprovable · 1.10s\n✖ 1 rule passed with a violation of itself in place\n```\n\nEach rule is **killed** (it failed on the violation), **survived** (it still\npassed, and the violation is shown), or **unprovable** (no violation could be\nmade, and the reason is given). Both bounds of a count are probed. `prove`\nexits 1 when a rule survived, and under `--strict` when one is unprovable. It\ntakes the run's `--root`, `--spec`, `--exclude`, `--ignore-status`, `--json`\nand `--format sarif|github|gitlab`, and the configuration's specs, exclusions\nand strictness.\n\nA kill means the rule can fail, not that it catches the way the code is\nwritten: `module=\"src/db.ts\"` is killed by `import 'src/db.ts'` though every\nfile imports `./db.js`. [ADR-0016](https://github.com/DescentVTT/spec-guard/blob/main/docs/adr/0016-rules-seen-to-fail.md) has the\nviolations for each kind of rule, and what `unprovable` means.\n\n## Do the comments cite decisions in force? - `cites`\n\nCode comments cite decisions - `// ADR-0011: the domain imports no\ninfrastructure`, `# see ADR-7`, `/* Q-172 */` - and the claim goes stale the\nway code does: the document was never written, or it has since been superseded.\n`spec-guard cites` reads the comment text of every source file for the ids a\nproject names, and reports each citation of a document that does not exist or\nis no longer in force:\n\n```bash\nspec-guard cites\n```\n\n```text\nspec-guard cites ADR-{n} (10 documents matching docs/adr/{n}-*.md); RFC-{n} (2 documents matching docs/rfcs/rfc-{n}.md)\n\n⚠ crates/ledger/src/journal.rs:1 cites ADR-0007, which is superseded - cite ADR-0009 instead  stale-citation\n    hint: docs/adr/0007-async-journal.md says \"superseded by ADR-0009\"\n✖ crates/ledger/src/lib.rs:28 cites ADR-0011, which no document defines  ghost-citation\n    hint: no document matching docs/adr/{n}-*.md has the number 11; the nearest is ADR-0010\n\n3 citations in 2 files · 1 ghost · 1 stale · 22ms\n✖ 1 citation names a document that does not exist\n```\n\nThe families of documents are named in the configuration, one entry each - an\nid with `{n}` for the number, and a path glob naming the documents with `{n}`\nin the file name:\n\n```json\n{\n  \"cites\": [\n    { \"id\": \"ADR-{n}\", \"files\": \"docs/adr/{n}-*.md\" },\n    { \"id\": \"RFC-{n}\", \"files\": \"docs/rfcs/rfc-{n}.md\" }\n  ]\n}\n```\n\n- **The number is a number**: `ADR-7`, `ADR-007` and `docs/adr/0007-x.md` are\n  one document. An id has a word boundary on each side, so `XADR-1` and\n  `ADR-12a` are not citations, and one id on one line is one finding however\n  often it is written there.\n- **Without `cites`**, a directory of specs whose names begin with a number, and\n  whose titles all begin with one id and that number (`# ADR-0007: ...` in\n  `0007-x.md`), is read as a family. Anything less is not guessed at: the\n  command exits 0 with a note saying to name the documents.\n- **Comment text only**, as the comment classifier reads it: an id in a string,\n  a raw string or a YAML value is not a citation. Markdown is spec-graph's and\n  is not read, nor are the spec files, the project's `exclude`, and the default\n  skips. Files in a language whose comments spec-guard does not know are\n  counted by extension, and a file read in part - binary, unreadable, or a scan\n  that lost its place - is named.\n- **Another project's ids are not checked**: `spec-core's ADR-0005`,\n  `spec-graph ADR-0017` or `its ADR-12` name a document in another repository,\n  and are counted instead.\n- **Stale** is `superseded`, `deprecated`, `rejected` or `archived`; a draft or\n  proposal cited from the code implementing it is not. The successor is read\n  from the document's status line - `Superseded by ADR-0014` - and followed to\n  the one in force.\n\n| Found | Exit |\n| --- | --- |\n| a ghost citation | 1 |\n| a stale citation | 0, as a warning; 1 under `--strict` |\n| a file read in part | 0; 1 under `--strict` |\n| a check that looked for nothing or read no source file | 0; 1 under `--strict`, and every format then places it as a `nothing-read` finding, an error, with what to do |\n| a family whose files match no document | 2 |\n\n`--json` (versioned by `formatVersion`), `--format sarif`, `--format github`\nand `--format gitlab` carry the same findings; `spec-guard cites src lib/a.ts`\nreads only those paths.\n[ADR-0017](https://github.com/DescentVTT/spec-guard/blob/main/docs/adr/0017-citations-in-comments.md) has the design, and what is\nout of scope: links to symbols, which need a parser the family does not ship.\n\n## Who depends on this? - `impact`\n\nBefore changing a file, the question after \"which rules govern it\" is \"what\nelse does it reach\". `spec-guard impact` reads the import graph backwards: for\neach path, the files that import it, and the files that import those, with how\nfar each is and the import that takes it one step closer; then the rules in\nforce that govern the path or any of them:\n\n```bash\nspec-guard impact src/db/client.ts --depth 3\n```\n\n```text\nsrc/db/client.ts\n  4 files depend on it, 2 directly, up to 3 imports away\n    1  src/app/service.ts  imports src/db/client.ts (line 2)\n    1  src/db/index.ts     imports src/db/client.ts (line 1)\n    2  src/app/cache.ts    imports src/app/service.ts (line 1)\n    3  src/ui/view.tsx     imports src/app/cache.ts (line 1)\n\n3 rules govern these files, from 1 document\n\n  ADR-0001: Layers  (docs/adr/0001-layers.md)\n    :3 @assert-layers  src must keep its layers in order, src/db < src/app < src/ui\n      governs: src/db/client.ts, src/app/service.ts, src/db/index.ts, src/app/cache.ts, src/ui/view.tsx\n    ...\n\n3 imports could not be resolved, and may depend on these paths:\n  src/ui/view.tsx:3  ./gone.js (names no file)\n  src/ui/view.tsx:4  @/db (names no file)\n  src/ui/view.tsx:7  import(name)\n```\n\n- **Followed**: relative JavaScript and TypeScript imports, by the table the\n  cycle rule uses ([ADR-0011](https://github.com/DescentVTT/spec-guard/blob/main/docs/adr/0011-layers-and-cycles.md)), and relative\n  Python imports, which name a module beside the importing file.\n- **Counted, not followed**: Go imports, Rust `use`s, C# `using`s and absolute\n  Python imports name modules, and which file a module is depends on `go.mod`,\n  the crate's module tree, the compiler or `sys.path`. A path in one of those\n  languages says its dependents are not computed, rather than showing an empty\n  list.\n- **Listed, never guessed**: an import naming no file, an alias such as `@/db`,\n  a dynamic `import(name)`. Any of them may depend on the path.\n\n- **A directory** asks about every file under it.\n- **`--depth <n>`** stops `n` imports away; cycles are safe.\n- **`--ignore-status`** lists rules from documents not in force, which are\n  otherwise counted, as `query` does.\n- **`--json`** is versioned by `formatVersion`.\n- **Exit 2** for a path that does not exist, and for a run of `impact` in which\n  no spec matched, as `query` does: the dependents are still written, but \"no\n  rules\" over no specs is nothing measured. `--allow-empty` asks for the\n  dependents alone, and exits 0.\n- **The MCP server** answers the same question as `get_dependents`, with the\n  same document.\n[ADR-0018](https://github.com/DescentVTT/spec-guard/blob/main/docs/adr/0018-impact.md) has the table and what it leaves out.\n\n## CLI\n\n```bash\nspec-guard [patterns...] [options]     # execute the directives\nspec-guard --watch [patterns...]       # execute them again whenever the tree changes\nspec-guard query <paths...> [options]  # the rules in force for files or directories\nspec-guard mcp [options]               # serve the rules over MCP on stdio\nspec-guard prove [patterns...]         # show each rule a violation of itself, in memory\nspec-guard cites [paths...]            # check each spec a code comment cites exists and is in force\nspec-guard impact <paths...>           # the files that depend on each path, and the rules in play there\n```\n\n| Option | Description |\n| --- | --- |\n| `-r, --root <path>` | Codebase root that assertions resolve against (default: cwd) |\n| `--spec <pattern>` | A spec glob or path, repeatable. `query` and `mcp` take their specs only from here |\n| `-v, --verbose` | Print passing assertions too |\n| `--watch` | Report, then report again as the tree changes, until Ctrl+C |\n| `--fail-fast` | Stop at the first failing assertion |\n| `--json` | Machine-readable report on stdout (same as `--format json`), versioned by `formatVersion` |\n| `--format <human\\|json\\|sarif\\|github\\|gitlab>` | Output format. `sarif` uploads to GitHub code scanning, `github` annotates a pull request from the job's log, `gitlab` is a GitLab Code Quality report |\n| `--engine <auto\\|rg\\|js>` | Search engine (default `auto`: scanner for small trees, ripgrep for big ones) |\n| `--strict` / `--no-strict` | Treat analysis that could not be completed as a failure, and a run that executed no assertion: its specs matched and state no rule in force |\n| `--allow-missing-targets` / `--no-allow-missing-targets` | Warn instead of failing when a `target` path does not exist |\n| `--allow-empty-scope` / `--no-allow-empty-scope` | Warn instead of failing when an assertion inspects no files |\n| `--print-baseline` | Print the `baseline=\"...\"` that would exempt today's violations, and exit |\n| `--no-default-skips` / `--default-skips` | Search `.git`, `.hg`, `.svn` and `node_modules` too |\n| `--exclude <globs>` | Paths no assertion looks at, beside each directive's own `exclude`. Repeatable; replaces the configuration's list, and `--exclude=` clears it |\n| `--ignore-status` / `--no-ignore-status` | Execute directives in documents not in force too: draft, proposed, rejected, deprecated, superseded or archived |\n| `--include-specs` / `--no-include-specs` | Also count matches inside the spec files themselves |\n| `--max-snippets <n>` | Failure snippets per assertion (default 5) |\n| `--concurrency <n>` | Search passes in flight at once (default 8) |\n| `--depth <n>` | `impact` only: follow dependents at most `n` imports away (default: all) |\n| `--allow-empty` | Exit 0 when no spec file matched the patterns, for a run, `prove` or `impact` (about the run, not an assertion) |\n| `--color` / `--no-color` | Force colour on or off (`NO_COLOR` honoured) |\n\nPatterns are expanded by spec-guard itself, so quoted globs behave identically\non Windows, macOS and Linux. A directory expands to the Markdown files in it.\nThe second form of each on/off option exists to override a configuration.\n\nAn option that means nothing to a command is refused rather than ignored, so\n`spec-guard query --strict` does not look like a strict query. `query` does take\n`--no-color`: its output never has colour, and scripts pass the flag to every\ncommand they run.\n\n### Configuration\n\nThe options that are a project's policy can live in `package.json`, under\n`\"specGuard\"`, so CI, a pre-commit hook and the MCP server an agent starts all\nhold the same rules the same way:\n\n```json\n{\n  \"specGuard\": {\n    \"specs\": [\"docs/**/*.md\", \"README.md\"],\n    \"strict\": true\n  }\n}\n```\n\nA root with no `package.json` - a Rust, Go or .NET repository, say - keeps the\nsame options, at the top level, in `.spec-guard.json`:\n\n```json\n{\n  \"specs\": [\"docs/**/*.md\"],\n  \"exclude\": [\"target\", \"bin\", \"obj\"]\n}\n```\n\n| Key | Command line | Value |\n| --- | --- | --- |\n| `specs` | patterns, `--spec` | a non-empty array of globs |\n| `exclude` | `--exclude` | an array of paths, gitignore-style, left out of every assertion that takes `exclude`; no `!`, `..`, drive path or root |\n| `engine` | `--engine` | `\"auto\"`, `\"rg\"` or `\"js\"` |\n| `strict`, `allowMissingTargets`, `allowEmptyScope`, `ignoreStatus`, `includeSpecs`, `defaultSkips` | the flag of that name | `true` or `false` |\n| `maxSnippets` | `--max-snippets` | an integer, 0 or more |\n| `concurrency` | `--concurrency` | an integer, 1 or more |\n| `cites` | none; `spec-guard cites` reads it | a non-empty array of `{ \"id\": \"ADR-{n}\", \"files\": \"docs/adr/{n}-*.md\" }`, and no other key |\n\n- **Only the root's files** are read: the `--root` directory, or the working\n  directory. Nothing is inherited from a parent directory.\n- **One of the two, not both.** Options in `package.json` and in\n  `.spec-guard.json` are exit 2, since whichever lost would be options somebody\n  wrote and nothing reads. A `package.json` with no `\"specGuard\"` is fine beside\n  a `.spec-guard.json`.\n- **The command line wins, both ways.** Patterns replace `specs`, `--exclude`\n  replaces `exclude`, and `--no-strict` beats `\"strict\": true`.\n- **`exclude` is for what no rule should read**, such as build output, which can\n  turn a scan of 3,000 files into one of 37,000. It is added to each directive's\n  own `exclude`, and applies to a query as it does to a run. `@assert-present`\n  names its files and is unaffected. A rule's description names only its own\n  exclusions; the project's appear in the options line below.\n- **A malformed configuration is exit 2, before anything runs**, naming the file\n  and the key: an unknown key, `\"true\"` where `true` goes, an option that\n  belongs to one invocation, such as `format` or `verbose`, or an exclude\n  pattern that can never exclude anything:\n\n  ```text\n  spec-guard: .spec-guard.json: \"exclude\" has an invalid exclude pattern \"!build/generated/needed.ts\": negation patterns are not supported in exclude.\n  ```\n- **Every report says what it took from the file**: a line above the summary\n  such as `options from .spec-guard.json: specs, exclude (target, bin, obj)`,\n  and a `config` field in JSON. `exclude` is named with its patterns, and\n  exclusions given only on the command line get a line of their own,\n  `exclude from the command line: dist`. JSON always carries the patterns in\n  force as `exclude`, an empty list when there are none. An option nobody can see\n  should never decide a result.\n- `query` applies what a query reads, and the MCP server reads the file again\n  for every request. Both tools' answers carry the options line, and their\n  structured content carries `exclude` and `config`.\n\n### Watch mode\n\n```bash\nspec-guard --watch\n```\n\nPrints the report, then prints it again whenever something under the root\nchanges, until Ctrl+C. Saves are batched: a batch starts after 50 ms without a\nnew change, or 500 ms after its first. On a terminal the screen is redrawn;\notherwise each report is appended under the time. A change that no rule reads\nupdates t","readmeFilename":"README.md"}