Skip to content

Commit 4351033

Browse files
claude[bot]claude
andauthored
skills(pm-dispatch): the contract-review PASS leaves its provenance comment on the PR, not only the card (#17856)
Fixes #13417 A contract-review PASS left **zero trace on the PR itself**: the gate label cleared on both carriers, `get_reviews` answering `[]`, and the verdict living on the card only — so a legitimate un-park was indistinguishable from an intruder read from the PR side. The Phase-3 rewrite of `references/contract-review.md` already requires a provenance comment at every clear, and C6 of `check-clause2-carriers.mjs` already reads the review record on the PR **or** the card. What was still open is exactly what the card measured: the provenance comment's **carrier was unpinned**, so a seat recording both the record and the provenance comment on the card side left the PR as blind as the incident found it. ## The change — one line, `references/contract-review.md` :38 Before (119 B, `origin/main` `9c577c18a`): > `- 清标即落地:PASS ⇒ 同席同笔剥双载体;凡清标同笔留 provenance 评论,引记录 id 与所判 head。` After (119 B, this PR): > `- 清标即落地:PASS ⇒ 同席同笔剥双载体;清标同笔落 PR provenance 评论,引记录 id 与所判 head。` The provenance comment is now pinned to the **PR** — the carrier that gets un-parked — while still citing the record id and the judged head. The card-side one-line verdict is untouched (载体纪律不动), `:28` 「复核记录 = 一条评论落 PR 或卡」 is untouched, and no script changed. **Measurements.** 60 lines before, 60 lines after (ceiling 60, headroom 0 — `scripts/pm/check-skill-line-ratchet.mjs`); the line is 119 B, one byte under the before-line's own width and under the gate's `MAX_LINE_BYTES = 120`. No ceiling raise, no second line, no density payment inside the file, and no cross-file move. **Wording adjusted from the dispatch's suggested shape, because the suggested shape does not fit.** 「清标同笔在 PR 上留 provenance 评论」 measures **126 B**, over the 120-byte rule; the cheapest spelling of that pin with 「在 … 留」 is 123 B. Two bytes-level adjustments bring it to 119 B without dropping a rule: the emphatic 「凡」 goes (its subject 「清标」 stays, so the clause still speaks about every clear, not only this PASS stroke), and the pin is spelled with the file's own verb for a comment landing on a carrier — 「落 PR」, as at `:28` 「一条评论落 PR 或卡」 — instead of 「在 PR 上留」. Every rule token survives: 同席, 同笔, 剥双载体, 清标, the PR pin, `provenance 评论`, 引记录 id, 所判 head. ## Rulings this edit stands on - The 2026-09-03 Phase-2 ruling of audit #13597 (recorded on the audit; the maintainer's word 「同意,然后执行契约复审」) — item 5 admits a same-PR cross-file line-budget move under the no-total-increase gate. **Not used**: the line fits in place at 60 → 60, so no move and no raise was needed. - The skills seat's 2026-08-31 grading of this card: the fix is the mechanical form the card proposed — the PASS disposition leaves a one-line pointer **on the PR** in the same stroke as the label clear, with the card-side verdict line unchanged (载体纪律不动). ## Acceptance reading After this text, a PASS clear that follows it leaves the PR thread carrying a comment that names the record id and the head it judged. `get_reviews` answering `[]` therefore no longer reads as "no review happened" from the PR side: the observer's own reasonable read now lands on the pointer instead of on an unexplained state change. Anchored evidence: the pointer wording is absent on `origin/main` (`git grep -n -i -E 'PASS at head|PR 上|落 PR|指针|pointer'` over this file → 0 hits, lit control `git grep -c '清标'` → 4) and present on this head (1 hit at `:38`). ## Gates Derived with `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` in the worktree (1 path, no paths passed by hand) — 14 families, all run, **all exit 0**, reconciled with `--ran` carrying each exit code: "14 derived famil(ies) accounted for — 14 run, 0 NOT-MEASURED (a DERIVED zero — all 14 recorded an exit code and none of them is 3)". | command | exit | |:---|:---| | `node scripts/check-closing-keyword-parity.mjs` (and `--self-test`) | 0 / 0 | | `node scripts/check-comment-mask-corpus.mjs` | 0 | | `pnpm --filter @objectstack/lint run check:doc-formula-expressions` | 0 (first run exit **3**, PREREQUISITE NOT MET — not a measurement; `@objectstack/formula` + `@objectstack/lint` built under `scripts/pm/os-verify-lock.sh`, `VERDICT command-exit 0`, then re-run) | | `pnpm check:agent-test-spelling` | 0 | | `pnpm check:doc-authoring` | 0 | | `pnpm check:driver-memory-census` | 0 | | `pnpm check:nul-bytes` | 0 | | `pnpm check:pm-governed-merges` | 0 | | `pnpm check:pm-skill-id-lint` | 0 | | `pnpm check:pm-skill-ratchet` | 0 | | `pnpm check:refd-timer-probe` | 0 | | `pnpm check:skill-frame-sync` | 0 | | `pnpm check:watch-hint-literal` | 0 | Gate verdict lines quoted rather than a bare `$?` (exit captured before any pipe): - `✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/references/contract-review.md is 60 lines (ceiling 60; headroom 0).` - `✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/references/contract-review.md: widest table row is 0 bytes (pin 0; headroom 0).` - `check-nul-bytes: OK (scanned 8483 text file(s) ... no raw ASCII control bytes).` - `✓ check-skill-id-lint: 27 file(s) clean (pattern for three-plus-digit card ids).` The ratchet family was re-run **after** the final commit, on `b54e3954e` with a clean worktree: exit 0, same two lines. Control reading, no script changed: `node scripts/pm/check-clause2-carriers.mjs --self-test` → exit 0, "546 cases pass". No changeset: the diff is `.claude/**` only, which publishes nothing from any released package (the fast lane in AGENTS.md's Post-Task Checklist step 3). `skip-changeset` applied on the PR. The derivation's 14 changeset-dependent families are derived against a path that does not exist and are correspondingly not in the run. ## Acceptance notes - **Two script comments now quote the OLD wording of `:38` verbatim** and go stale with this edit: `scripts/pm/check-half-states.mjs` (the H61 header, quoting the whole line "verbatim and untranslated") and `scripts/pm/check-clause2-carriers.mjs` (the C6 docblock, quoting 「凡清标同笔留 provenance 评论,引记录 id 与所判 head」). Neither is gate-enforced — no script reads this file at runtime except the ratchet, for line counts, and H61's own pin asserts only 「清标即落地」, which survives — and neither quote contradicts the new text; each is simply less specific than it (no carrier pin). Left untouched deliberately: the dispatch fences this card to `references/contract-review.md` with ⛔ no script change, and touching either script would add its own self-test surface to this PR. Successor: whoever next edits H61 or C6, or a quote-sync follow-up if the seat wants one. - Not filed as a card: prose drift in a comment is neither a reproducible defect, a declared contract violation, nor a metadata-authoring trap. ## 维护者速读(草稿) **改了什么**:`references/contract-review.md` 第 38 行一句话,把 PASS 清标时那条 provenance 评论钉到 **PR 上**(原文只要求「留一条评论」,没说落哪个载体)。60 行进、60 行出,119 字节, 不动天花板、不动别的文件、不动任何脚本。 **为什么改**:合法的契约复核 PASS 在 PR 侧不留任何痕迹 —— 标签没了、`get_reviews` 读空、结论 只在卡上。观察者做了最合理的那次阅读(看 PR),得出「没人复审过」,于是善意回停已通过复审的 PR。这一次的实测代价:一张 p1/security 卡、两次回停、一次总监调查、两个 PR 空等约 40 分钟。 文内早有读者侧缓解(「`get_reviews` 读空 ≠ 未复审」),事故照样发生 —— 所以承重的是写者侧的 这一行。 **风险与代价(含回滚)**:风险低。这是一行规则文字,不是机制:C6 已经同时读 PR 与卡两条线程, 本 PR 不动它,所以门禁语义零变化。代价是每次清标多一条 PR 评论(席位已在同一笔里写卡侧结论, 增量是一次 API 写)。回滚 = 撤销这一行,不留任何残留状态。两处脚本注释仍逐字引着旧措辞,已在 上面 Acceptance notes 里点名,未改动。 **席位意见**:(留待席位定稿) **你要做的**:这是受管面(`.claude/**`)⇒ 只能人工合并。PR 保持 draft;确认这一行的措辞(尤其 「凡」字去掉后是否仍读作「每次清标」)后由维护者手工落地。 --- _Generated by [Claude Code](https://claude.ai/code/session_01MCLBsUgfykL74aU716rzVK)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 80ef826 commit 4351033

1 file changed

Lines changed: 1 addition & 1 deletion

File tree

‎.claude/skills/pm-dispatch/references/contract-review.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
- 独立性对(机读):`Implemented-by:` 写产 diff 者身份;`mode:subagent` 记分支,`mode:remote` 记 session id。
3636
- `Reviewed-by:` 写渲染或采纳裁决的席位 session;隔离复核子代理无 session,记采纳它的席位。
3737
- 两者同 session ⇒ 报 SELF-REVIEW;值紧跟冒号,前置词即不可读;两行皆无的历史裁决恒静默。
38-
- 清标即落地:PASS ⇒ 同席同笔剥双载体;凡清标同笔留 provenance 评论,引记录 id 与所判 head。
38+
- 清标即落地:PASS ⇒ 同席同笔剥双载体;清标同笔落 PR provenance 评论,引记录 id 与所判 head。
3939
- 随后按 `landing-operations.md` 走落地前检 → 转 ready → 挂 auto-merge 或入队。
4040
- 轮次报告设复审清单专节,形状与代裁清单同为强制审计。
4141
- 落地前检三条:① 席内条款②复核 PASS 在案,即 PR 或卡上同形的复核记录(spec 席达档)。

0 commit comments

Comments
 (0)