feat(standards): generate each Verify block from check.sh, assert the skeleton

Every SKILL.md restated its own assertions in prose sitting next to the script that makes them, and each standard had picked its own heading for that section: ## What is checked in three, ## Asserted against the API in one, and a <details> block called "What the check enforces" in five more, plus two near-variants. Prose beside a script is free to drift from it, and it had. Two of those restatements said a failing project "fails the pipeline reference-check in cutover mode", present tense, about a component that exists at no catalog tag.

This makes the section derived instead. DESCRIBE=1 (new "Describe mode" header in _lib.sh) turns every primitive into an enumerator: it prints the assertion it would make, tab-separated, and returns without touching the filesystem, the network, or the counters. applies_when_file reports its precondition rather than exiting, so the enumeration does not truncate at the first gate on a machine whose tree happens not to match the glob. It is one line per primitive, and no primitive gains a second code path.

scripts/skill-shape.py reads that and owns the ## Verify section end to end. just sync regenerates it, just validate-skills asserts it, and the generator and the checker are the same code path called twice, so they cannot disagree. 76 assertions across 20 standards. The block carries the just check-one invocation, the severity tier, the precondition, and every assertion with its output id, so a reader can map a FAIL line back to the bullet that predicted it.

The one hand-maintained field is front matter unasserted:, a single sentence naming what the standard deliberately does not assert. Seven standards carry one, each harvested from the real gap its deleted restatement had been holding. It lives in front matter rather than in the block so regenerating cannot silently drop it, and it is quoted, because an unquoted colon-space starts a nested mapping.

The heading skeleton is now asserted as a subsequence (The rule, Why <specific>, Verify, optional Details, References or See also, Template(s)), so a standard carrying structure of its own keeps it. Eight deviated: four named the rule something else, one had no rule heading, two stated no rationale, and four cited no sources at all. Details stays optional deliberately, since a 28-line standard should not grow a deep-dive to satisfy a checker, and Template is asserted if and only if the standard ships files under templates/.

The primitive count is also derived now rather than restated. just guard reports the size of its own allowlist. Seven prose sites claimed "nine" while the set has been ten since check_xml_wellformed landed, and two files contradicted themselves within a single screen.

Three smaller corrections found along the way: presentation linked ../naming, a standard it had itself absorbed; just check-one's usage comment named a standard deleted on 2026-08-04; and project-settings's description: claimed it asserts branch protection and force-push when it asserts neither, which is the copy a reader meets first on the site card.

Verification

Guard, validate (7 of 7, including the new validate-skills), check (20 of 20), build, agent surface, and vale project-mode all green, in both the main checkout and the worktree.

The validator is verified able to fail three ways, each restoring clean: an assertion added to a check.sh without regenerating, a renamed rule heading, and a deleted References section.

Vale caught the generated fence language sh, which `gitlab_base.CodeblockFences` rejects in favour of shell; that would otherwise have failed CI on all twenty files at once.

Merge request reports

Loading