feat(spec): lint that spec "Locked by Test..." references resolve#90
Merged
Conversation
Part (2)-lint of the spec-prose drift cleanup. The strict-coverage gate maps tests to ACs by @spec/@ac annotation id, not by checking spec prose against the tree — so a "Locked by TestX" reference rots silently when TestX is renamed or never written, while coverage stays green. The audit found 26 such stale references across 12 specs; nothing flagged them. TestSpecTestReferencesResolve (cmd/kensa-validate, runs under `go test ./...`) closes that hole: it scans every specs/**/*.spec.yaml for Go test identifiers and FAILS on any that don't resolve to a real `func Test...`, unless tolerated by the ratcheting ledger knownStaleSpecTestRefs. It mirrors the param-contract divergence-ledger idiom: the ledger can only shrink — an entry that now resolves (or is no longer referenced) also fails (ratchet), so debt can't linger once fixed. Exact-name references require an exact test; only explicit prefix families (trailing "_") get prefix matching, so "TestFoo" can't silently match an unrelated "TestFooBar". Lands green: the 26 current stale refs are seeded in the ledger, grouped by spec with rename-vs-gap notes (11 specs are renames; agent-bootstrap holds the one genuine missing-test gap). Verified it catches NEW drift (an injected nonexistent reference fails the test). Part (2)-A will shrink the ledger to empty. No production code; test-only. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The strict-coverage gate maps tests to ACs by
@spec/@acannotation id, not by checking spec prose against the tree. So aLocked by TestXreference rots silently whenTestXis renamed or never written — coverage stays green while the spec lies. The audit found 26 such stale references across 12 specs, and nothing flagged them.What
TestSpecTestReferencesResolve(incmd/kensa-validate, runs under the existinggo test ./...CI job — no new wiring) scans everyspecs/**/*.spec.yamlfor Go test identifiers and fails on any that don't resolve to a realfunc Test…, unless tolerated by a ratcheting ledger.It mirrors the repo's existing divergence-ledger idiom (
param_contract_corpus_test.go+mechanism.HandlerParamDivergence):knownStaleSpecTestRefsseeds the 26 current stale refs, so it lands green.Matching is strict: exact-name refs require an exact test; only explicit prefix families (trailing
_) get prefix matching, soTestFoocan't silently match an unrelatedTestFooBar.Verification
Locked by TestThisDoesNotExistAtAll_Sentinelreference into a spec fails the test; removing it restores green.What's next (the ledger is the worklist)
agent-bootstrap(83%): write the one genuinely-missing test, then clear its entry.When the ledger reaches empty, this becomes a pure enforcing gate.
🤖 Generated with Claude Code