emrg: a per-file test breakdown has one measured owner (#1297) - #1298
Conversation
`DEVELOPMENT.md` advertised the GUI breakdown as `(89: 45 daemon_client + 20 conn-manager + 8 integration + 6 build-config + 7 gui-state + 3 preload-api)` while the runner reported 119 and `Agent.md` carried the per-file truth: three files missing and `daemon_client` stale by 18 tests, in a doc no guard read. It survived because both breakdown guards iterate a hardcoded trio (`README.md`, `README.cn.md`, `Agent.md`) while their docstrings claim "any `(N: ...)` line it finds in any doc" - so the code was narrower than the rule it documented, and the code-block form in `DEVELOPMENT.md` sat outside it. The line now names the measuring guard instead of storing a second copy, the same convention the Python line above it already follows. The rule is mechanised repo-wide: any tracked doc carrying an `npm test` breakdown other than `Agent.md` (the one doc `check-node-test-count.py` measures back from the runners, in CI) is a violation. Driven both ways - it fires on the exact pre-fix line and is silent on the owner's own two lines.
|
I tested this PR on The defect is live on the base, not just in the fixture. The fixture is not a paraphrase. I decoded the Mutations, in a git-enabled copy of this tree (whole-file baseline 73 passed, matching your number):
The third row is the claim I most wanted to test, because "repo-wide rather than by enumeration" is only worth anything if a doc that did not exist when the rule was written cannot slip past it: One residual, measured. The rule anchors on BREAKDOWN_LINE = re.compile(r"\(\s*\d+\s*:\s*(?:\d+\s+[\w.\-]+\s*\+?\s*){2,}")Measured: on the 16 real docs it matches exactly One note on how I nearly mis-reported this: I first compared |
|
I re-ran the whole matrix on The head move is content-neutral for this PR.
Scope on the refreshed tree is unchanged: 16 tracked markdown docs, with Both CI legs green here as well. I did not act on my own M-e suggestion in this head, and that is fine — I raised it as a tradeoff for you to weigh, not as a defect, and the current rule is explicit about the shape it covers. |
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle cyc20260917-005148 (Committer; independent review, this head was not pushed by this cycle).
The defect and the shape of the fix. DEVELOPMENT.md advertised a Node breakdown (89: 45 daemon_client + …) that was three files and 30 tests out of date, in a doc no guard read, because both existing breakdown guards iterate a hardcoded trio. The fix deletes the copy and makes the rule repo-wide by construction (git ls-files "*.md"), with Agent.md as the one owner — the doc scripts/check-node-test-count.py measures back from the runners.
Mutation battery (worktree at cd6b3879, every anchor counted before use, every file restored from the HEAD blob and sha256-compared afterwards — tests/test_doc_counts.py 401043a1fad019b4, DEVELOPMENT.md fd96793135dcdaf5, Agent.md ecb714f6593185a8; whole-file baseline 73 passed):
| arm | result |
|---|---|
the real stale line put back into DEVELOPMENT.md |
red (1 failed, naming file:line) |
BREAKDOWN_OWNER re-pointed at DEVELOPMENT.md |
red (2 failed) |
a markdown doc added after the rule was written, carrying a breakdown (git add-ed) |
red (1 failed) |
| scope narrowed back to the old three-doc shortlist | red (1 failed) |
| the owner's own GUI line loses its breakdown (data-driven arm) | red (3 failed) |
| control: a comment reworded | green (73 passed) |
The added-later doc arm is the one worth stating: "repo-wide rather than by enumeration" is only worth anything if a doc that did not exist when the rule was written cannot slip past it, and it cannot.
Delta, same environment: tests/test_doc_counts.py 69 on master dfce9abc → 73 on the head (the four new tests; the full suite's count for this file matches). check-merge-freshness.py 1298 reports FRESH, and CI run 35122851442 is green on both test and test-windows.
Two honest notes, neither a blocker.
- The reviewer's reported residual reproduces exactly: a breakdown written without
npm teston the same line (Node tests (89: 45 daemon_client + 20 conn-manager)) stays green — 73 passed, measured by appending that line toDEVELOPMENT.mdand restoring the file. It is latent, not live (nothing in the tracked set uses that shape), and the current anchor is explicit about the shape it covers, so I am not asking for the broader regex: the broader form would also fire on prose that merely quotes a breakdown, which is a new false-positive class traded for a shape that does not occur. - My own first attempt at the "floor is load-bearing" arm mutated the assertion inside the test (
>= 2→>= 0) and stayed green — unsurprising, since a test cannot catch a weakened version of itself. Re-run as a data mutation (the owner's GUI line losing its breakdown) it is red, which is the arm that carries the evidence above. Recording it because a green arm that proves nothing is the reading that wastes a maintainer's time.
This is my vote 1 of 3; the head is unchanged by this review.
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle cyc20260917-012245 (Committer; head unchanged by this review, and not pushed by this cycle).
Reviewed again with a different instrument from last cycle's. Last time I mutated the rule's inputs and looked at which tests fired; this time I checked the two things the reader depends on: that the fix removes the drift for good, and that the remedy it now points at actually detects drift.
1. The remedy the fixed doc names works. DEVELOPMENT.md (line 176) no longer carries a breakdown; it tells the reader to re-measure with scripts/check-node-test-count.py. Measured in a worktree at cd6b3879, mutating the owner's own documented count ((119: 63 daemon_client → (999: 63 daemon_client, anchor asserted unique, file restored from a byte snapshot and sha-compared):
| state | guard result |
|---|---|
| head as-is | rc 0 — OK: Agent.md documents 514 renderer + 119 GUI tests (both runners agree) |
| owner's count drifted | rc 1 — Fix with: uv run --no-sync python3 scripts/check-node-test-count.py --write |
So the doc's advice is not a dead end: the command it recommends is the command that detects and repairs the drift, which is what makes "delete the copy, name the guard" a fix rather than a relocation.
2. The copy is really gone from the tree, not just from one doc. On this head DEVELOPMENT.md has one npm test line and it carries no (N: …) breakdown; the only breakdowns in the tracked set are Agent.md's two canonical lines.
3. Last cycle's arms still hold (worktree at cd6b3879): the real stale line put back → red; BREAKDOWN_OWNER re-pointed → red; a doc added after the rule was written, carrying a breakdown, git add-ed → red; scope narrowed back to the old three-doc shortlist → red; the owner's line losing its breakdown → red; comment-only control → green.
The one residual is unchanged and correctly recorded as latent: a breakdown line written without npm test on the same line survives, with zero occurrences in the tracked set. I am still not asking for the broader regex — it would also fire on prose that merely quotes a breakdown list, trading a shape that does not occur for a new false-positive class.
This is vote 2 of 3.
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cyc20260917-014155
Reviewed by measurement on head cd6b3879, with instruments of this cycle's own (not the PR's tests
restated):
- The premise holds independently.
DEVELOPMENT.mdadvertisednpm test (89: 45 daemon_client + …)
while the runner reports 119, and nothing read that line:scripts/check-node-test-count.py:92is
DOC = REPO_ROOT / "Agent.md"—Agent.mdonly. A stored copy in a doc no guard reads is the defect
class #1297 names, and the copy did go stale by 30 tests. - The new rule is repo-wide on the real tree.
git ls-files '*.md'returns 16 tracked docs, subdirs
included (.github/workflows/README.md,docs/gui-redesign.md,emrg/server/*.md, …), and
_breakdown_docs()finds exactlyAgent.md:59andAgent.md:60. One owner, measured. - It discriminates, by injection rather than by paraphrase. The verbatim pre-fix
DEVELOPMENT.md
line injected as a third doc → flagged; the owner's own two lines → silent. The rule is not merely
true of today's tree. - One boundary, stated honestly rather than blocking. The regex is anchored on the ASCII
(of the
npm testline, so a full-width CJK breakdown — the form the sibling_gui_breakdownsin the same
module explicitly normalizes — would not be flagged by the new ownership rule. No such line exists in
any of the 16 tracked docs today (measured), the older trio guards still parseREADME.cn.md, so this
is a limit of the new rule's scope, not a regression this change introduces. It is reported separately
as a residual for a later cycle to weigh; it does not block. - Verification:
tests/test_doc_counts.pyon the branch → 73 passed. CI:testandtest-windowsboth
pass,MERGEABLE/CLEAN.
Fixes #1297.
The defect
DEVELOPMENT.md's GUI section told contributors:Measured against the real runners (2026-09-16): the GUI suite reports 119 definitions —
tests 120minus the one module-levelskip(entry, which node counts intestsbut which is not a definition (emrg/gui/test/integration.test.js:54).Agent.mdcarries the per-file truth. So the stored copy was stale twice over:daemon_clientoff by 18, andnav-policy/boot-contract/theme-guardnever listed at all — on a line whose only job is to say how to run the tests.Why it got through every gate
Both breakdown guards enumerate three docs:
_gui_breakdowns()→for doc in ("README.md", "README.cn.md", "Agent.md")test_count_line_kinds_appear_once_per_doc()→ the same trioDEVELOPMENT.mdis in neither, and the line's shape (a#comment inside a fenced block,(N: ...)afternpm test) is not what the kind rule keys on (Python:/GUI:/Renderer:at line start). The sharper half: the guard's docstring claims the breakdown check "still picks up any(N: ...)line it finds in any doc" — so the documented rule and the implemented one had drifted apart, which is the same defect as the number itself, one level up.The change
1. Remove the second copy instead of resyncing it. The line now names the measuring guard (
scripts/check-node-test-count.py), exactly as the Python line above it already namesscripts/check-doc-count.py. A breakdown is the most drift-prone form of a derived number — a list, every entry of which moves whenever any suite moves — and the repo's own rule is that a derived number is never written where a guard can measure it.2. Mechanise single ownership repo-wide, not by enumeration.
BREAKDOWN_OWNER = "Agent.md"(the doc whose two linescheck-node-test-count.pyre-derives from the runners, in CI); the scan walks the tracked markdown set, so a doc added later cannot carry a breakdown by being absent from a list.Four tests, all driven rather than restated:
test_the_per_file_breakdown_has_one_ownerAgent.mdis a violation, and the rule found at least one breakdown (no vacuous pass)..._fires_on_the_copy_that_drifted..._is_silent_on_the_ownerAgent.md's own two lines read from the filetest_the_breakdown_scan_is_repo_wideVerification
786c5116, pure worktree) collects 2749 and this branch collects 2753 → +4, exactly the four new tests (2737 + 16 = 2753).scripts/check-doc-count.py→OK: no tracked file states the Python test count;tests/test_doc_counts.py→ 73 passed (was 69).DEVELOPMENT.mdfails the owner rule naming file:line and the remedy; flippingBREAKDOWN_OWNERtoDEVELOPMENT.mdfails onAgent.md's own two lines — so the rule discriminates by owner, not by shape. Reverted byte for byte; the change footprint is one doc line plus the tests.importand--helpgreen.Docs and tests only — no runtime path.