Repository navigation
skills(pm-dispatch): the contract-review PASS leaves its provenance comment on the PR, not only the card - #17856
Merged
Merged
Conversation
…omment on the PR, not only the card The 清标即落地 disposition required a provenance comment at every clear but left its CARRIER unpinned, so a clear recorded on the card side alone left the pull request exactly as blind as the measured incident found it: the gate label gone, `get_reviews` empty, and no comment on the PR thread — a legitimate un-park indistinguishable from an intruder from the PR side. Pin the comment to the PR, the carrier that gets un-parked, still citing the record id and the judged head. One line, 60 lines before and after, 119 bytes. Claude-Session: https://claude.ai/code/session_01MCLBsUgfykL74aU716rzVK Co-authored-by: Claude <noreply@anthropic.com>
Contributor
Author
维护者速读事情:契约复审 PASS 之后,座位清掉闸门标签、翻 ready,但 PR 本身没有任何痕迹——只在卡上有一行结论。8 月 31 日的 #13412 事故就是这么来的:两个 PR 被合法复审放行,旁观的席位从 PR 侧看不到任何复审记录,当成入侵重新停回去,花掉一张 p1 安全卡、两次善意回停和一次总监调查。这张卡当时因为文件行数顶格被停放,等语料审计裁完;审计 Phase 2 已裁、文件已重写,本席今天放行并派发。 改了什么: 风险:低。协议文本;门禁 14/14 绿。两处脚本注释里引用的旧原文会差一个从句,随下次动那两个脚本的 PR 顺手改。 只问一字:是否合并? Generated by Claude Code |
This was referenced Sep 12, 2026
os-zhuang
approved these changes
Sep 12, 2026
os-zhuang
marked this pull request as ready for review
September 12, 2026 15:27
os-zhuang
enabled auto-merge
September 12, 2026 15:27
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #13417
A contract-review PASS left zero trace on the PR itself: the gate label cleared on both
carriers,
get_reviewsanswering[], and the verdict living on the card only — so alegitimate un-park was indistinguishable from an intruder read from the PR side. The Phase-3
rewrite of
references/contract-review.mdalready requires a provenance comment at everyclear, and C6 of
check-clause2-carriers.mjsalready reads the review record on the PR orthe 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:38Before (119 B,
origin/main9c577c18a):After (119 B, this PR):
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'sown width and under the gate's
MAX_LINE_BYTES = 120. No ceiling raise, no second line, nodensity 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
「同意,然后执行契约复审」) — 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.
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_reviewsanswering[]therefore no longerreads 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 thisfile → 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/objectstackin the worktree (1 path, no paths passed by hand) — 14 families, all run, all exit 0,
reconciled with
--rancarrying 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)".
node scripts/check-closing-keyword-parity.mjs(and--self-test)node scripts/check-comment-mask-corpus.mjspnpm --filter @objectstack/lint run check:doc-formula-expressions@objectstack/formula+@objectstack/lintbuilt underscripts/pm/os-verify-lock.sh,VERDICT command-exit 0, then re-run)pnpm check:agent-test-spellingpnpm check:doc-authoringpnpm check:driver-memory-censuspnpm check:nul-bytespnpm check:pm-governed-mergespnpm check:pm-skill-id-lintpnpm check:pm-skill-ratchetpnpm check:refd-timer-probepnpm check:skill-frame-syncpnpm check:watch-hint-literalGate 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
b54e3954ewith 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-changesetapplied 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
:38verbatim and go stale with thisedit:
scripts/pm/check-half-states.mjs(the H61 header, quoting the whole line "verbatim anduntranslated") 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.mdwith ⛔ no script change, and touching either scriptwould 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.
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