Skip to content

Commit 2502b8a

Browse files
os-warrenclaude
andauthored
fix(pm): the clause-② correction remedy names THIS card's claim comment, never a specimen from another card (#18448)
Fixes #17919 Clause-②: no A CLI gate script exports no published symbol; the two new exports (`commentCardNumber`, `correctionTarget`) live in `scripts/pm/`, which no package's `files[]` ships. The seat declared this on the card (claim comment `5696260545`) and the diff did not move it. ## The finding, and what it actually was `check-clause2-carriers --pair` reported the clause-② declaration MISPLACED and, inside that message, named claim comment `5642248126` — a `Claim:` on card **#17366**, unrelated to the card under test. **The card reads that as the script's *selection*. It is not.** Part (3) of the C2 remedy was a module-level constant that carried the id as a **literal**: ``` '(3) Post ONE new comment on this card whose FIRST line is `Clause-②-correction: 5642248126` — ' ``` That is the #17366 specimen, hard-coded into the sentence every C2 row prints. Nothing selected it, so no guard over a selection could have fired — a constant makes no selection. The id printed on **every card**, in **every C2 state that carries the remedy**, and had done so since the constant was written. Verified on the exact blob the 2026-09-13 readings were taken from — `git cat-file -p aecbb2d | grep -n 5642248126` → line 1445, inside `CORRECTION_REMEDY`. Same literal, same sentence. ### Reproduced deterministically, offline, on a card of its own `--pair-json` judges a pre-fetched pair with no network, so the reading is exactly reproducible. A synthetic card #99002 whose whole thread is comments `900000001` and `900000002`, judged by the `origin/main` copy of the script: ``` $ node scripts/pm/check-clause2-carriers.mjs --pair 99001 --pair-json misplaced-pair.json exit=4 … whose FIRST line is `Clause-②-correction: 5642248126` … ``` An id that is on neither comment of the thread it just read, printed inside the verdict about that thread. ⇒ the class is **re-observable today**, on any card, without reproducing the non-determinism the evidence upgrade measured. ## The cut, and why it is here rather than where the card offered it The card offers a guard that the selected comment's `issue_url` matches the card under test, explicitly as a shape. Measurement moved it one level up: the only ids this file may **print** are ids it **read from the pool the reading was built from**, and each is checked against the card under test before it is printed. - `commentCardNumber(row)` — the issue a row *says* it belongs to, read off `issue_url`; this is the card's own control, mechanised. - `correctionTarget(pool, card)` — resolves the printable id from the SAME pool `cardDeclaration` built its readings from. A positive disagreement drops the id and **says so**; ⛔ absence of `issue_url` is not read as a mismatch (an offline document and this file's own fixtures carry rows without it, and a row that states nothing contradicts nothing); a reading with no card number names no id at all — fail-closed. - `CORRECTION_REMEDY` is a function of the card under test. When no id survives, part (3) names the key and no digits, plus the reason. ⛔ Nothing here resolves a state, a row or an exit code. ## Both directions, judged — this is a gate other PRs must pass **Does the guard suppress a message that was correct?** No. Word-diff of the whole output, same input, `origin/main` copy vs this one: ``` … whose FIRST line is `Clause-②-correction: [-5642248126`-]{+900000001`+} — the numeric id of the claim comment it corrects, digits [-only-]{+only, read from card #99002's own thread+} — followed by … ``` That is the entire delta. The MISPLACED verdict, its sentence, its remedy and `exit=4` are byte-identical. A self-test case asserts each of the five remedy- carrying states still renders a non-empty row, so the controls cannot pass vacuously. **Does any exit code move on a pair judged correctly?** No. All 16 open PRs, both copies run back to back, 2026-09-16T11:03–11:04Z: | exit | PRs | |:--|:--| | 0 | 18444 18438 18437 18436 18433 18430 18429 18428 18427 18414 18403 18389 18319 | | 2 | 18420, 17076 | | 4 | 18131 | Identical on both copies, 16/16, including all three non-zero verdicts. ## Population — previously unmeasured, now partly measured - **Which paths**: the remedy is printed by 5 of the 6 C2 branches — `misplaced`, `malformed`, and all three `missing` variants. `absent` does not print it (no claim comment exists to correct). Enumerated mechanically: the ablation's own failure detail names all five. - **How often**: on the live board at 2026-09-16T10:56Z, sweep over 15 pairs derived from 16 open PRs — `0` with NO CLAIM COMMENT, `0` with a claim comment but NO DECLARATION LINE ⇒ **0 pairs on the printing path today**. The class is a failure-path constant, not a standing one. - ⛔ Still unmeasured: how often the board has historically been on that path. ## Tests `--self-test`, the safety net, on `2620cb2b3d`: **715 cases pass, exit 0** (689 before; +26). New battery `#17919: the correction remedy names THIS card's claim comment, never another card's`, floor raised by exactly one. **Ablation** — the guard removed, part (3) restored to the pre-fix literal, on a committed tree, mutation proved on disk before the run and the restore proved by `git diff HEAD` and a blob-hash comparison: ``` HEAD blob fe6601d on-disk: injected marker count=1 (want 1); removed-text count=0 (want 0) mutated blob 847524b84e71639d317c6e9e9e373cb877c5c672 VERDICT ablation-mutated self-test exit=1 ← 9 cases red ✗ ⭐ …and NOT ONE of them carries a comment id from another card ["misplaced","malformed","missing","missing/describing","missing/inline-key"] restored blob fe6601d (= HEAD) git diff HEAD --name-only: [] VERDICT ablation-restored self-test exit=0 ``` Direction predicted before the run and observed: **turns red**. The module is run directly from source by `node scripts/pm/…` — there is no build and no `dist/` between the edit and the run, so the on-disk proof is the whole preflight. **Gates**: all 36 commands derived by `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` run at `2620cb2b3d`, exit 0 — including `pnpm check:pm-clause2-carriers`, `pnpm check:nul-bytes` and `pnpm check:pm-dispatch-gates` (496.6s; a first run capped at 240s read `exit=124`, NOT MEASURED, and was re-run to completion). Reconciled: `dispatch-gates --ran` ⇒ *36 derived, 36 run, 0 NOT-MEASURED, 0 UNRUN*. No changeset: the root package is private and `scripts/pm/` sits outside every workspace package, so no `files[]` can ship it. ## Acceptance notes Out of scope, noted and ⛔ not filed: - The `misplaced` sentence says "NOT in the card's claim comment" on threads that have **no** claim comment at all (`misplaced` and `malformed` are both reachable from the thread-wide scan with an empty claim pool). Prose imprecision on a reachable path, not a wrong verdict; the remedy now degrades correctly there. Carrier: whoever next edits `c2Sentence`. - The file header's illustration of the correction shape (line 367) also spells the #17366 specimen id. It is a doc comment inside a paragraph that is explicitly about #17366, never printed, and left as written. --- _Generated by [Claude Code](https://claude.ai/code/session_01KB5PFtxuy1x3dcR5gxudx6)_ Co-authored-by: claude[bot] <noreply@anthropic.com>
1 parent 3ab1508 commit 2502b8a

1 file changed

Lines changed: 257 additions & 18 deletions

File tree

0 commit comments

Comments
 (0)