Two things v0.7.0 left open.
Coverage: the checks had no tests
A trace showed 17 of validate_plugin.py's 35 functions were never entered by any test — main(), check_manifests, check_crossrefs, check_i18n, and every cross-file sub-check among them. All of them could have been reduced to no-ops with CI still printing OK. The shipped repository passing is evidence that the repository is clean, not that a check works.
tools/tests/test_checks.py now runs all seven check groups against a synthetic repository and mutates it once per rule — 7 clean + 40 rejection cases, each rejection pinning its expected diagnostic so an unrelated failure cannot green a dead check. Coverage is 35/35. It runs in CI as a fifth step.
Writing it found three defects the shipped repository could not surface:
- Deleting every command wrapper passed the wrapper-parity check.
check_commandsreturned early onnot files, so N=0 — the most complete way to violate the rule — was the one case that passed. _check_command_flagsignored its argument. Writtendef f(repo: Path = REPO), the module global was captured at def time, so the check always scanned the real repository. That is also why it was the one cross-ref sub-check that could not be pointed at a fixture, and therefore the one that could not be tested.- v0.7.0's own zero-count tripwire was too strict. It required at least one anchored link; zero anchored links is a legitimate state, and it rejected the validator's own fixture repository. Narrowed to the single count that cannot legitimately be zero — proving each sub-check still fires is a test's job, and now is one.
Documentation: full-corpus audit
Five dimensions, every finding put through an independent refuting pass: 14 confirmed, 26 rejected. Among the rejected was one the maintainer had called confirmed — presets/design.md's (F = 0) is an appositive gloss on "violated hard constraint", so the gate was never inverted.
Confirmed and fixed:
- Following
CONTRIBUTING.md's field-profile recipe broke CI. Field profiles are registered indocs/languages.jsonone path at a time whilepresets/andcommands/use globs, so a new profile was an unregistered canonical document. Reproduced, fixed in both the contributor guide andfield-profiles/README.md, and re-verified by following the corrected recipe end to end. - The chaining handoff contract called deliverables "line-per-item" and told
tree-chainto take "the first K lines". They are ranked## <id>sections carrying several lines of fields each, so a head-N over lines would slice an item's body in half. Now defined as entries, split on level-2 headings. - ENGINE §4's slot table named fields no preset declares —
falsifiabilityattributed todesign,cost_of_changeto nothing at all — and had no row for the external-check field §3.X mandates. Every example is now a field a shipped preset really declares. - §F7 listed
--max-branchesas a cap with a cap-trip status that §6.1, §6.2 and §7.4 never define. It raises a per-node ceiling whose floor §3 fixes at 12 and never terminates a run. - README double-nested the run directory (an explicit
--outis the run directory), miscountedCONTRIBUTING.md, and claimed CI runs on every push whenci.ymlrestricts push tomain. - Two physically wrong worked examples in
framings.md: relaxing a 5σ cut to 3σ cannot make detections drop out (it triples the sample), and 10¹¹ M_sun is a Milky-Way-scale halo, not the galaxy-cluster regime.
Every Chinese parallel was co-edited and its source digest refreshed.
No interface changes: every flag, preset, command, and output filename is unchanged from v0.7.0.
Full detail: CHANGELOG.md