Repository navigation
fix(pm): the clause-2 correction note READS the claim comment's two stamps instead of vouching it was never edited - #19298
Conversation
…ers — RED against the current message The `--pair` green line and the C2-CORRECTION note under it both testify that the claim comment 「is NOT edited and still reads as it was written」, with no instrument behind either sentence. This commit lands the pin ALONE, so the red run is on the record before the fix exists (#18892's filing discipline: a pin that was never shown to fail is not evidence). Measured specimen replayed as the fixture: objectui#9764's claim 5724909959, `created_at` 2026-09-18T03:54:37Z vs `updated_at` 2026-09-18T04:23:23Z. `node scripts/pm/check-clause2-carriers.mjs --self-test` → exit 1, 9 of 1071 cases fail. Claude-Session: https://claude.ai/code/session_017ETYWqMQD4qMtZzAGovWNi Co-authored-by: Claude <noreply@anthropic.com>
…tamps instead of vouching that it was never edited `applicableCorrection`'s note ended with an integrity assertion the gate had no instrument for — 「which is NOT edited and still reads as it was written」 — printed unconditionally under every correction. `created_at` and `updated_at` both arrive on the `/issues/comments` row the reader already holds, so the reading cost no request; it simply was not taken. `claimEditReading` takes it, in three readings and never two: EDITED names the instant so a reader can open the comment's edit history, equal stamps are a measured UNEDITED, and a row carrying neither stamp is NOT READ — never reported as unedited. Report-only, per the #18892 ruling: the exit register does not move, because an edit is a legitimate act and the silence was the defect. The `--pair` green line's parenthetical follows the note it points at, and now names the stream that note prints on. `node scripts/pm/check-clause2-carriers.mjs --self-test` → exit 0, 1071 cases. Net +39 lines against the card's +40 ceiling. Claude-Session: https://claude.ai/code/session_017ETYWqMQD4qMtZzAGovWNi Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewServed-tier: ① Derived judgments
② Semver levelNone — ③ Boundary flagsDev flags: Implemented-by: VERDICT: PASS Generated by Claude Code |
Fixes #18892
Clause-②: no
The
--pairgreen line and theC2-CORRECTIONnote under it both testified that the claim comment 「is NOT edited and still reads as it was written」. Nothing in this file had ever read an edit.created_atandupdated_atboth arrive on the/issues/commentsrowapplicableCorrectionalready holds, so the reading cost no request — it simply was not taken.Triage's grading (5725446014) chose option A over the card's B and C: read the two fields, say it in the message, ⛔ never fail on it.
What changed —
scripts/pm/check-clause2-carriers.mjsonlyclaimEditReading(row)— module-local, ⛔ no newexportand no registration (Clause-② declaredno). It turns the claim comment's own two stamps into three readings, never two:updated_atdiffers fromcreated_at⇒ WAS EDITED, naming the instant so a reader can open that comment's edit history;declaredat the seat's own value. An edit is a legitimate act; the silence was the defect.The pin was proven red BEFORE the fix existed
Two commits, in that order, exactly as the card required (「⛔ 先让 pin 红」).
0d29892— the pin alone, against the unfixed message:0128cbb— the reader:The unedited control and the three report-only cases pass on both commits, so the battery is not a one-sided pin. The source-scan negative and its control are assembled at runtime (the #16770 idiom), because a literal would have made the scan hit itself — the first draft did exactly that and passed vacuously; it is fixed and the control now proves the read reaches the file.
Measured on the specimen the card names — offline, via
--pair-jsonobjectui's claim
5724909959on card #9764:created_at2026-09-18T03:54:37Z,updated_at2026-09-18T04:23:23Z. Replayed with the real API payloads, thread truncated to the instant the card measured:Before (
adf4b18):After (
0128cbb):And the sharper half — two
--pair-jsondocuments differing only inupdated_at, both reaching exit 0:NOT editedWAS EDITED at …NOT editedreads UNEDITED — … both …Before this PR the two runs were byte-identical on every stream. That identity is now impossible, and the exit register did not move in either row.
Acceptance notes
renderPair'srows.length === 0branch prints every note (ℹ️ C2-CORRECTION — …) immediately above the green line. So 「the reading above」 resolves today and was ⛔ not dropped. What is true is that the note goes to stderr while the green line goes to stdout, so a seat capturing stdout alone holds the pointer without its referent — which is the likeliest reading of the card's 「只打三行」. The parenthetical now names the stream, which is the cheapest thing that makes the pointer executable. No reading was deleted.--pair-jsondocument that omitsupdated_atchanges reading, from a silent "unedited" to an explicit NOT READ. That is the intended direction (absence must be loud) and affects hand-written fixture documents only; the live/issues/commentsrows always carry both fields, unprojected —readCardCommentshands the raw rows through.git rev-parse --is-shallow-repository⇒true, 116 commits; this file reads as+9132insertions at the boundary commit) makesgit log -Sunable to answer whether the pass path ever failed to print its notes. Stated rather than answered; nothing in this PR rests on it.scripts/pm/**publishes nothing, henceskip-changeset.scripts/pm/**is not a governed path, so no 维护者速读 section is owed.Gates
Derived from the worktree after the last commit, no paths passed:
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackat0128cbb⇒ 34 commands, matching the dispatch-time derivation. Each is run with its exit code captured before any pipe; the full table, its--ranreconciliation and the head sha it was taken on are in this card'sos-dev-reportcomment, which is the machine-read record.Generated by Claude Code