fix(port): check-citations was red, and its selftest BROKEN, on a clean tree #66

Merged
fabi merged 1 commits from fix/citations-generated-tree into main 2026-09-21 16:33:53 +00:00
Owner

Same shape as #65, found the same way — by running the gates on main instead of assuming they were green. Two independent defects, both reporting a correct checkout as wrong. Neither is new; both were invisible because nobody ran this here.

1. A citation of generated output is not a dangling citation

export/ is the exporter's output and is gitignored (.gitignore/export*/). A checkout where nobody has run the exporter has no export/ at all, so four citations landed in resolve NOWHERE and the check exited 1:

export/manifest.json                 <- DECISIONS.md
export/screens/title/extras.json     <- DECISIONS.md
export/screens/title/main_menu.json  <- DECISIONS.md
export/screens/title/press_start.json <- BLOCKED.md

Red for a state no edit can fix — the exact shape its own docstring says it exists to avoid. check-capture-citations already learned this for docs/re/captures/, so the rule is borrowed rather than invented: absent because unbuilt is reported; absent while the tree IS built still fails.

Verified both directions — mkdir export and the same four go straight back to failing (exit 1). The leniency is scoped to "the tree was never built", not to export/ as a prefix.

2. The selftest was asserting against a file that became ordinary

Its peer-branch fixture cited docs/re/f5-a-press-snaps-the-plate.md — which the consolidation made an ordinary local file. The fixture stopped testing the scanner and started reporting it broken. PEER_REFS also still named origin/auto/frame-blend-draw-path, a branch that no longer exists.

So --selftest prints 🔴 BROKEN on main today, for itself, not for the code under test.

It now finds a peer-only path at runtime; where none exists — the normal case on a clean checkout, measured: zero — it says the class is empty here rather than claiming a failure. The class itself stays: the next topic branch that lands a finding recreates the condition exactly.

Measured

before after
check-citations exit 1 0
resolve here 119 119
unbuilt generated 4 (reported)
resolve nowhere 4 0
--selftest 🔴 BROKEN ok

The new generated-tree selftest case was confirmed to FAIL against the unfixed function before the fix went in.

What to look at

Pass: tools/port/check-citations exits 0 and lists the four under not built in this checkout; --selftest ends -> ok.
Fail: either still reports resolve NOWHERE, or mkdir export && tools/port/check-citations exits 0 — that would mean the leniency is too wide.

Not in scope

tools/port/check-all, check-claims and check-modding cd /work and only run inside the container; contract-check needs an export. audit-kinds exits 1 on 9 dangling kind citations in authored/ — that is port content, not a tooling defect, and belongs to whoever picks up the F-series work.

🤖 Generated with Claude Code

Same shape as #65, found the same way — by running the gates on `main` instead of assuming they were green. Two independent defects, both reporting a correct checkout as wrong. Neither is new; both were invisible because nobody ran this here. ### 1. A citation of generated output is not a dangling citation `export/` is the exporter's **output** and is gitignored (`.gitignore` → `/export*/`). A checkout where nobody has run the exporter has no `export/` at all, so four citations landed in **resolve NOWHERE** and the check exited 1: ``` export/manifest.json <- DECISIONS.md export/screens/title/extras.json <- DECISIONS.md export/screens/title/main_menu.json <- DECISIONS.md export/screens/title/press_start.json <- BLOCKED.md ``` Red for a state no edit can fix — the exact shape [its own docstring](tools/port/check-citations) says it exists to avoid. `check-capture-citations` already learned this for `docs/re/captures/`, so the rule is borrowed rather than invented: **absent because unbuilt is reported; absent while the tree IS built still fails.** Verified both directions — `mkdir export` and the same four go straight back to failing (exit 1). The leniency is scoped to "the tree was never built", not to `export/` as a prefix. ### 2. The selftest was asserting against a file that became ordinary Its peer-branch fixture cited `docs/re/f5-a-press-snaps-the-plate.md` — which **the consolidation made an ordinary local file**. The fixture stopped testing the scanner and started reporting it broken. `PEER_REFS` also still named `origin/auto/frame-blend-draw-path`, a branch that **no longer exists**. So `--selftest` prints 🔴 BROKEN on `main` today, for itself, not for the code under test. It now **finds** a peer-only path at runtime; where none exists — the normal case on a clean checkout, measured: **zero** — it says the class is *empty here* rather than claiming a failure. The class itself stays: the next topic branch that lands a finding recreates the condition exactly. ### Measured | | before | after | |---|---|---| | `check-citations` exit | **1** | **0** | | resolve here | 119 | 119 | | unbuilt generated | — | 4 (reported) | | resolve nowhere | **4** | **0** | | `--selftest` | **🔴 BROKEN** | ok | The new generated-tree selftest case was confirmed to **FAIL** against the unfixed function before the fix went in. ### What to look at **Pass:** `tools/port/check-citations` exits 0 and lists the four under *not built in this checkout*; `--selftest` ends `-> ok`. **Fail:** either still reports `resolve NOWHERE`, or `mkdir export && tools/port/check-citations` exits 0 — that would mean the leniency is too wide. ### Not in scope `tools/port/check-all`, `check-claims` and `check-modding` `cd /work` and only run inside the container; `contract-check` needs an export. `audit-kinds` exits 1 on **9 dangling** `kind` citations in `authored/` — that is port content, not a tooling defect, and belongs to whoever picks up the F-series work. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fabi added 1 commit 2026-09-21 16:17:35 +00:00
fix(port): check-citations was red, and its selftest BROKEN, on a clean tree
Some checks failed
CI / Native — linux (pull_request) Failing after 1h3m26s
CI / WASM — Web (pull_request) Successful in 25m21s
CI / Formatting (pull_request) Successful in 28s
7907c8d286
Two independent defects, both making the script report a correct checkout as
wrong. Neither is new; both were invisible because nobody ran it here.

1. `export/` is the exporter's OUTPUT and is gitignored (`/export*/`). A
   checkout where nobody has run the exporter has no `export/` at all, so the
   four `DECISIONS.md`/`BLOCKED.md` citations of `export/manifest.json` and
   `export/screens/...` landed in "resolve NOWHERE" and the check exited 1 --
   red for a state no edit can fix, which is the exact shape its own docstring
   says it exists to avoid. `check-capture-citations` learned this for
   `docs/re/captures/`; same rule now: absent BECAUSE UNBUILT is reported,
   absent while the tree IS built still fails. Verified both ways -- `mkdir
   export` and the same four go back to failing.

2. The selftest's peer-branch fixture cited
   `docs/re/f5-a-press-snaps-the-plate.md`, which the consolidation made an
   ordinary local file. The fixture stopped testing the scanner and started
   reporting it broken; `PEER_REFS` also still named
   `origin/auto/frame-blend-draw-path`, a branch that no longer exists. The
   selftest now FINDS a peer-only path at runtime, and where none exists -- the
   normal case on a clean checkout, measured: zero -- it says the class is empty
   here rather than claiming a failure. The class itself stays: the next topic
   branch that lands a finding recreates the condition exactly.

Measured: check 123 citations, 119 resolve, 4 unbuilt, 0 nowhere, exit 0 (was
exit 1). Selftest ok (was 🔴 BROKEN, on `main` too). The new generated-tree case
was confirmed to FAIL against the unfixed function first.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
fabi merged commit bfe590c6bc into main 2026-09-21 16:33:53 +00:00
Sign in to join this conversation.