Skip to content

v0.17.1 — bound the doc-drift payload, close two gate blind spots

Choose a tag to compare

@Redtropig Redtropig released this 31 Jul 05:06
· 14 commits to main since this release
2d9a7e6

PATCH. Every entry repairs something that already shipped — nothing belongs in an ### Added section, which is what the versioning rule keys MINOR on.

All five findings are the same shape 0.17.0 shipped fixes for, turned on 0.17.0's own artefacts: a sensor whose silence was not coverage, and gates that had stopped covering what they claimed to.

Fixed

doc-drift-scan.sh flooded the consumer it reports to

HARD_CAP bounded the symbol set; nothing bounded the candidate rows, the unit the reader actually pays for. Measured on this repository's own v0.16.0..v0.17.0 range: 54 symbols → 4765 rows / 759 KB. The 3000-token SessionStart budget invariant is this repo's scale for what injected context may cost; 759 KB from one sensor is not in that world. Wherever the consuming tool's output limit falls, a payload that size is past it — so drift-analyst was adjudicating a list the harness had already cut, silently. The script announced PARTIAL for the one truncation it performed and was blind to the larger one it caused.

Rows are now capped per symbol (12) and in total (400), each with a PARTIAL marker, and the summary reports matched-vs-shown (K candidate(s), S shown).

doc-drift-scan.sh harvested comment prose as if it were code

Symbol extraction reads raw diff lines, comments included, so English containing word ( becomes a "symbol". Three of them — O (from O(files)), b (from the regex \b(${ALT})) and it (from prefixes it () — produced 3100 of those 4765 rows, 65% of the output, none naming any code symbol.

Tokens under three characters are no longer searched at all: matching is prefix-based and case-insensitive by design, so their rows are undecidable at any count. They are named individually on stderr — a symbol the scan chose not to look for must never read as one it looked for and found nothing about. The accepted common-word noise (read, get, check — real identifiers whose rows a reader can judge) is untouched.

Same range after: 379 rows / 70 KB (−91%), with every bound announced.

tests/windows-compat.sh stopped checking the newest hook two releases ago

Its HOOKS list was hard-coded and never learned about hooks/pre-compact (v0.15.0), so [1/5] (no bare python3), [3/5] (eol=lf) and [5/5] (portable.sh wiring) skipped it — and [1/5] has no other coverage anywhere in the suite. Hooks are now globbed, with a non-vacuity guard so an empty discovery fails loudly instead of passing every loop below it.

[3/5] also gains skills/using-harness-anchor/SKILL.md, awk-consumed by hooks/session-start and pinned eol=lf for that reason — a pin unverified since v0.14.0 added it, because this check is the only place in the repo that reads an eol attribute at all.

A hook registered in hooks.json but missing on disk was invisible to every gate

validate-anchor [1/12] names two of the five hooks; [11/12] enumerated all five by hand but only to check their wiring; hooks.json itself is validated for JSON syntax alone. [11/12] now derives its list from hooks.json and runs registry → disk. Complementary to windows-compat [5/5]'s disk → wiring; neither direction alone catches both failures.

Two troubleshooting entries gave pre-0.13.0 / pre-0.16.0 advice

The doc-align marker had sat at v0.9.0 through eight releases — two of which added entries to that very file — while its own text said "re-verify and bump this marker if they change". All 15 entries were re-checked against hooks/ and scripts/, every mechanically checkable claim run or grepped rather than read. Thirteen hold. Two did not:

  • #6 named a missing python3 as a cause of hook-contract FAILs. False since v0.13.0 — the engine chain is python3pythonpy -3node → narrow pure-bash, and an engine-less machine emits SKIP, never FAIL. It sent Windows readers, the exact people v0.13.0 was for, chasing an interpreter that cannot be the cause.
  • #5 told the reader to install a build tool on the strength of init.sh's command -v check — PATH-only, precisely the inference 0.16.0's discovery chain exists to prevent, in the guide meant to teach it.

The new marker states the scope of that verification instead of asserting a bare "verified". A scope-less positive is the same defect as a scope-less negative.

Changed

  • agents/drift-analyst.md reads the scan's stderr through a six-row state table (up from three prose states), including both cap markers and the never-searched token list. A clean doc-drift section now means "no doc claim about a changed, 3+ character, function-shaped symbol in a scanned language looks stale".
  • docs/troubleshooting.md gains entries 14 and 15, covering the two sensors 0.16.0/0.17.0 added — both built to report things that look like failures and are not.
  • tests/unit/doc-drift-scan.sh 22 → 32 assertions; tests/windows-compat.sh 19 → 24; scripts/validate-anchor.sh 157 → 158.

Verification

Run on main at 2d9a7e6 before tagging:

Gate Result
validate-anchor 158 / 0
validate-manifests 3 / 0
windows-compat 24 / 0
posix-compat 4 / 0
cpp-tool-discovery 15 / 0
doc-drift-scan 32 / 0
mandated-phrasing 9 / 0
check-coverage 28 / 0
SessionStart injection 6807 / 5153 chars, cap 12000
CI on the merged head 9 / 9 green (ubuntu, macOS, windows-latest, ShellCheck, CodeQL ×5)

Negative paths proven to fire, not assumed: empty hook discovery, missing registered hook file, unrecognised hooks.json command shape (5 declared / 4 parsed), zero parsed, and a doc-drift fixture that trips the length floor plus both caps at once — with an assertion pinning that all 40 fixture symbols survive capping, since a cap that amputated whole symbols would reintroduce the silent miss the script exists to prevent.

Full diff: v0.17.0...v0.17.1