spec citations: five named sections their SPECs do not have, and a check so they cannot return #238
2026-10-13
ci: a citation to a section that does not exist is now a failure
All checks were successful
standards workspaces build + test / jouleclaw-rs (pull_request) Successful in 2m15s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 1m22s
standards workspaces build + test / aac-rs (pull_request) Successful in 2m31s
standards workspaces build + test / joulecontract-rs (pull_request) Successful in 54s
standards workspaces build + test / map-rs (pull_request) Successful in 55s
standards workspaces build + test / mesh-rs (pull_request) Successful in 55s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 56s
standards workspaces build + test / openpay (pull_request) Successful in 3m4s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 4m36s
lockfiles / every Cargo.lock is current (pull_request) Successful in 40s
spec citations resolve / Code cites no section its SPEC lacks (pull_request) Successful in 4s
standards workspaces build + test / arl-rs (pull_request) Successful in 1m10s
standards workspaces build + test / eoc-rs (pull_request) Successful in 2m0s
standards workspaces build + test / joule-ui-rs (pull_request) Successful in 1m12s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m31s
standards workspaces build + test / joulehook-rs (pull_request) Successful in 1m11s
standards workspaces build + test / proof-rs (pull_request) Successful in 1m19s
standards workspaces build + test / sense-rs (pull_request) Successful in 1m12s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m22s
workflow hygiene / every workflow supersedes its own queue (pull_request) Successful in 4s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 3m46s
The commit before this fixed five of them. They were written long before anyone read them, and the one in #190 — `jcp-runtime` citing `SPEC §4.10` in six places, with no §4.10 — survived a gate-enforcing, tested mechanism for months. Reading the tree once finds these; reading it every time is a check. `scripts/check-spec-refs.py` resolves every `SPEC §N` in a standard's `*.rs` against the numbered headings of the `SPEC.md` beside it. 1454 citations across 15 standards resolve today. Three decisions worth stating, because each is a way the check could have been written to find nothing: - Parents are not synthesised. A cited `§4` needs its own `§4` heading; a `§4.10` heading does not satisfy it. Otherwise a standard citing a section it never wrote is excused by a child it happens to have. - A citation resolves against the SPEC.md of its own directory. Every cross-standard citation in the tree today is a self-reference that names its standard for the reader ("JouleClaw SPEC §1.3", inside jouleclaw/), so this is right for all of them; the header says what to do instead if that ever stops being true, rather than loosening the check. - Sections of a `spec/*.md` subfile are not sections of `SPEC.md`. The self-test asserts the check can fail, in the four ways that matter: an unresolvable citation fails, both heading spellings (`## 4.` and `## §4`) are accepted, a child heading does not satisfy its parent, and one standard's section does not excuse another's citation. A regex that quietly stops matching would otherwise find nothing and exit 0 — the failure mode this repo has already met in gated and skipped tests. The workflow carries no `paths:` filter, deliberately. The check is a second of Python with no toolchain, and a correct filter would have to name every standard's `**/*.rs` and every `SPEC.md`; `standards-build.yml` records that `**`-prefixed globs do not match on this forge and that a gate which quietly fails to fire is worse than none, since it reports nothing and that reads as green. This is `check-wai-section-refs.py`'s complement, not a duplicate: that one checks WAI markdown against WAI markdown, this one checks every standard's code against its spec. Co-Authored-By: Claude Opus 5 <[email protected]>
aac, sandbox: five citations named sections their SPECs do not have
Code cites normative text to say which rule it enforces. These five cited
sections that do not exist, so the citation read as authority it did not have.
None of the rules was missing — every one is written down, just not where the
code said:
aac §3.3 (3 sites) the rule is §3 item 3 ("rendering its cell as visually
inactive **in place**") and §3.1 item 3 ("MUST keep its
position and MUST be rendered as visually inactive and
not selectable"). aac/SPEC.md has §3 and §3.1 and no
§3.2 or §3.3, and the SPEC's own cross-references
already use the form this commit adopts — line 54 reads
"(§3 item 3, §3.1)".
sandbox §6.5 the receipt's storage line is `spec/receipts.md`:
"Storage activity is its own line … it does **not** enter
the per-device-class energy sum of §6.2". §6 has 6.1-6.4.
sandbox §12.1 the deterministic-first cascade is `spec/build.md`, under
"## Deterministic-first (the cascade)". §12 exists and
records the tier in the build receipt, but has no
subsections.
So each citation now points where the rule actually is. Sections of a
`spec/*.md` subfile are not sections of `SPEC.md`, and are cited by file name.
Found by checking every `SPEC §N` in the tree against the headings of the
SPEC.md beside it — 1454 citations across 15 standards, and these five were
the only ones that did not resolve. The commit after this one makes that a
check, because all three were written long before anyone read them. The same
family as #190, where `jcp-runtime` cited `SPEC §4.10` in six places and
§4.10 did not exist.
Both workspaces check clean with `--all-targets`.
Co-Authored-By: Claude Opus 5 <[email protected]>