Skip to content

docs(agents): the contract-review carrier is the seat's to hang; --pair PR-NUMBER is the only spelling - #18250

Merged
os-zhuang merged 4 commits into
mainfrom
claude/issue-18181-carrier-is-the-seats-to-hang
Sep 15, 2026
Merged

os-zhuang merged 4 commits into
mainfrom
claude/issue-18181-carrier-is-the-seats-to-hang

Conversation

@claude

@claude claude Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Fixes #18181

What changed

Three lines across two governed rules-layer files; line counts unchanged (os-dev.md 403/403, SKILL.md 812/812), every edited line at or under the 120-byte cap, no re-wrap anywhere, and the decision-frame block SKILL.md :734–:755 untouched (md5 3327d02c56f8a0eca88569dad2270f32 before and after).

.claude/agents/os-dev.md :287 — the line the card names, re-derived on b3b43b6 (the card body's :288 had drifted; the filer's correction comment 5664488072 gives :287):

-- 认领写 `Clause-②: yes` ⇒ 开 PR 同笔挂 `needs:contract-review`,报告附 `--pair N` 退出码。
+- `needs:contract-review` 归席位,⛔ 不挂不摘不等;报 PR 上有无与 `--pair PR-NUMBER` 退出码作读数。

The dev no longer hangs the carrier. It never hangs, removes or waits for needs:contract-review; it reports whether the label is present on the PR and the --pair PR-NUMBER exit code — as a reading, not as a gate it must clear.

.claude/agents/os-dev.md :301 — the neighbouring skip-changeset label-write rule (mechanism assumption A2, same file surface, same class — an additive label write the container may refuse):

-- 被拒 ⇒ 停下报 `blocked` 点名端点与状态码,⛔ 不换 MCP 写道;写后必做对比式读回。
+- 被拒 ⇒ 报端点与状态码、席位代挂,⛔ 不报 `blocked`、不走 MCP;写后必做对比式读回。

One rule now covers both carriers: a refused additive label write is reported with endpoint and status and the seat hangs the label; the dev never reports blocked for it and never switches to an MCP write.

.claude/skills/pm-dispatch/SKILL.md :646 — the one --pair N token (REGION claim: this line only):

-- `Clause-②: yes` 认领同笔在卡上挂标;PR 开出即读 `check-clause2-carriers --pair N` 为 0 再请审。
+- `Clause-②: yes` 认领同笔卡上挂标;PR 开出读 `check-clause2-carriers --pair PR-NUMBER` 为 0 再请审。

--pair PR-NUMBER is now the only spelling in the three governed files (contract-review.md :42 already spelled it so).

Why

Direction A of the card's grading (comment 5673619664), executed as ruled: the needs:contract-review carrier is the PM seat's to hang — on the card at the claim and on the PR when the PR appears — which is what every seat already does; the dev never blocks on a label write; --pair PR-NUMBER becomes the only spelling. Option B (granting the dev container the label write) is a permissions widening and was ruled not this card.

The two defects the card and its correction measured: a dev that obeyed :287 literally was refused the additive label write by its container's write classifier on two independent objectui runs, while an objectstack dev could write it — per container, unknowable in advance; and --pair N bound N to the nearest referent, the card, while the script takes a PR number and answers a card number with exit 2 (UNJUDGED), which a naive capture reads as a red gate.

Mechanism readings

  • A1 — :287 is the line on b3b43b6 (108 B; the card's :288 is the skills/** line). Replaced as above. Under the byte cap the Clause-②: yes trigger did not fit, so the rule is now unconditional: on every PR the dev hangs nothing, removes nothing, waits for nothing, and reports carrier presence plus the --pair PR-NUMBER exit code. That superset is deliberate — --pair also carries the widening-tell row, which only fires on a Clause-②: no claim, so a reading on every PR is worth more than one on yes claims alone.
  • A2 — measured on the text: :301's 被拒 ⇒ 停下报 blocked is the same container-refusal class one line over, and nothing about skip-changeset requires the dev to block on it: CI's changeset gate reads the label, the dev's report says whether it landed, and the seat can hang it on that report. So one rule covers both carriers and :301 changed as above; :299 (the label is your step, hang it as soon as the PR opens) and :300 (additive endpoint) stay — the dev still attempts the write. The live half of the measurement is this PR's own skip-changeset write; its outcome (landed, or the endpoint and status of the refusal) is in the os-dev-report comment on the card, not here, because the PR body is written before the label write and is not re-sent.
  • A3git grep -n -- '--pair N\b' -- '.claude/**' 'scripts/pm/**': before 6 hits (os-dev.md :287, SKILL.md :646, and 4 in scripts/pm/**); after 4 hits, all outside the claimed surface: check-clause2-carriers.mjs :24 and :490 (docblocks), :4947 (a self-test title), and check-widening-tells.mjs :492 (docblock). In the three governed files the count is 0. Lit control --pair PR-NUMBER: 1 before (contract-review.md :42), 3 after (:42, os-dev.md :287, SKILL.md :646). The script docblocks bind N to a PR number in their own text (:11 spells --pair 13910 # ONE PR), so the ambiguity is not live there; noted below, not edited.
  • A4 — measured from the sibling checkout on this container: cd /home/user/objectui && PM_SWEEP_REPO=objectstack-ai/objectui node ../objectstack/scripts/pm/check-clause2-carriers.mjs --pair 9552 exits 0 with the provenance line every row below is read from objectstack-ai/objectui (source: PM_SWEEP_REPO) and the verdict PR #9552 / card #6910 — the clause-② declaration is readable in the fixed spelling and both carriers agree (token present, 3 reads served; the proxy re-exec happened by itself). A control on objectui#9495 (no longer open) exits 2 — UNJUDGED, with the board still retargeted. So the invocation works from a sibling checkout. The byte cap leaves no room on :287 for the invocation (the line stands at 119 B), so the line carries only the flag spelling; the script header (:20–:24) already spells the sibling invocation and every run prints the board it read, which is the remedy text the ruling asks to keep in the script.

Gates

Derived with node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths; change set from the merge base): 18 families on a2cbbef0, re-derived on the merged head 0c934967 (merge base 68fea8bc) — identical list. All 18 run in the foreground on 0c934967, exit codes captured by redirect before any pipe, all 0:

check-closing-keyword-parity (+ --self-test) · check-comment-mask-corpus · check-governed-queue-guard --self-test · check:doc-formula-expressions (lint pkg) · check:agent-model-declared · check:agent-test-spelling · check:commit-card-trailers · check:doc-authoring · check:driver-memory-census · check:nul-bytes · check:pm-governed-merges · check:pm-governed-prose · check:pm-skill-id-lint · check:pm-skill-ratchet · check:refd-timer-probe · check:skill-frame-sync · check:watch-hint-literal

Reconciliation on 0c934967: ✓ dispatch-gates --ran: 18 derived famil(ies) accounted for — 18 run, 0 NOT-MEASURED (a DERIVED zero — all 18 recorded an exit code and none of them is 3).

Verdict lines: ✓ check-skill-line-ratchet: .claude/agents/os-dev.md is 403 lines (ceiling 403; headroom 0) · ✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/SKILL.md is 812 lines (ceiling 812; headroom 0) · ✓ check-agent-model-declared: 1 agent definition(s) under .claude/agents/ all declare a model · ✓ check-skill-id-lint: 27 file(s) clean · ✓ check-skill-frame-sync: the one declared copy of the decision frame is internally coherent.

check:doc-formula-expressions first answered exit 3 (PREREQUISITE NOT MET — @objectstack/formula and @objectstack/lint unbuilt in a fresh worktree); prerequisite built under the verify lock (turbo run build --filter=@objectstack/formula --filter=@objectstack/lint, VERDICT command-exit 0), rebuilt again after the merge, then the gate exits 0. The exit 3 is not a measurement and is not counted as one.

Not run locally, by design: the 11 wide-population families and the whole-repo pnpm lint sweep belong to CI. Control-byte self-scan on both edited files: no hits.

Line budget

file before after ceiling edited lines (bytes)
.claude/agents/os-dev.md 403 403 403 :287 108→119 · :301 110→114
.claude/skills/pm-dispatch/SKILL.md 812 812 812 :646 116→118

Paid by density in place; no line merged or split.

Deviations, declared

  1. SKILL.md :646: the token swap alone (NPR-NUMBER, +8 B) puts the line at 124 B, over the 120-byte cap. Two characters were dropped on the same line (, ), content unchanged, landing at 118 B. Still inside the one-line REGION claim.
  2. os-dev.md :287: the Clause-②: yes trigger is gone for the byte cap; the rule is unconditional (see A1). If the seat wants the trigger back, the price is the 作读数 tail or the 不等 limb.
  3. os-dev.md :287 does not spell the objectui invocation (A4); the line names the flag, the script header names the sibling form.
  4. os-dev.md :301 edited under A2 (inside the file surface and the card's class). objectui's copy and the dispatch-order template are untouched.
  5. skip-changeset: nothing published moves — .claude/** is on the fast path (no package files[] ships it).
  6. origin/main merged at 68fea8bc (one spec commit, nothing on this surface) before opening; pm-dispatch: reconcile the quota rows with the identity-bound rate limit; merged-write rule; account-suspension recovery readings #18242 remains open on SKILL.md :172–:185 — disjoint from :646.

Acceptance notes

  • To file (class b, for the seat — dedupe words: needs:contract-review, PR 创建者, 同笔挂, SKILL.md, direction A): SKILL.md :645 still reads 「needs:contract-review(恒英文)由 PR 创建者随可复审契约增量同笔挂:draft PR,或先到的报告。」 For a dev-created PR the creator is the dev, which direction A says never hangs it. Outside this card's REGION claim (:646 only), so not edited here; it sits on the SKILL.md chain the seat owns.
  • noted, not filed: 4 --pair N spellings remain in scripts/pm/** docblocks and one self-test title (listed under A3); each is next to text that binds N to a PR number. 承接者:无.
  • noted, not filed: os-dev.md :300's 「可达性按会话探,先探后用」 is redundant with the new :301 — the write attempt is the probe. Left as is; deleting it frees bytes, not a line. 承接者:无.
  • Observed on this PR after opening: the labels present are reported in the os-dev-report comment with a read-back; under one shared identity the author field says nothing about who hung what.

维护者速读(草稿)

改了什么:改了两个受管规则文件里的三行,行数不变。开发 agent 定义(os-dev.md)一行:needs:contract-review 这个标签归席位挂,开发 agent 不挂、不摘、不等,只在报告里写 PR 上有没有它、以及 --pair PR-NUMBER 的退出码,作读数。另一行:加法写标签被容器拒绝时,报端点与状态码、由席位代挂,不再报 blocked、不走 MCP。PM 技能(SKILL.md)一个 token:--pair N 改成 --pair PR-NUMBER

为什么改:两次独立实测里,开发 agent 的容器拒绝写标签,而规则要求它开 PR 同笔挂——照做就失败、如实报告又像抗命。分诊裁定 A 向:载体由席位挂(认领时挂卡、PR 出现时挂 PR),开发 agent 只报所见。同一行的 N 让人绑到卡号,脚本要的是 PR 号,给卡号返回 exit 2(未判),会被当红灯读;PR-NUMBER 是唯一拼写。

风险与代价(含回滚):行数与上限不变,每行 ≤120 字节,决策框架块未动。风险是开发 agent 不再自己挂载体,若席位漏挂,条款② PR 的载体会缺失——但席位侧已经是现行做法,且开发 agent 报告的 --pair 读数会暴露缺失。回滚 = revert 本 PR,无其他副作用。

席位意见:

你要做的:审阅上面三行措辞(尤其 :287 去掉了 Clause-②: yes 触发词、改为对每个 PR 都成立);同意即给授权批准,由席位落地;不同意请指出要保留的措辞。


Generated by Claude Code

…air PR-NUMBER` is the only spelling

os-dev.md: the dev never hangs, removes or waits for `needs:contract-review`;
it reports the carrier state seen on the PR and the `--pair PR-NUMBER` exit
code as a reading. A refused additive label write is reported with endpoint
and status for the seat to hang — never `blocked`, never MCP.
SKILL.md: the one `--pair N` token becomes `--pair PR-NUMBER`.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HZfg2AwVX191qCizp88gQr
…e PR creator

SKILL.md :645 now says the seat hangs `needs:contract-review` in the same
stroke: on the PR as soon as it exists, on the card first when the report
arrives before the PR — the order contract-review.md already states.
Equal-line, paid by density.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HZfg2AwVX191qCizp88gQr
@claude

claude Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: d181b4f0c65d10f8bbf5d34d49bb50bd3e6d95a6

Reviewing seat: domain:skills, in-seat review at the contract-review tier (get_session at 2026-09-15T02:54Z: configured = session = last served, the constant's tier). Card #18181, claim 5674057831, reports 5674343438 (round 0) and 5674431308 (patch round 1 after REWORK 5674367642); Clause-②: no on the claim and in the PR body.

① Derived judgments

  • Accept set / public surface: none moves — .claude/agents/os-dev.md (+2/−2) and .claude/skills/pm-dispatch/SKILL.md (+2/−2) against merge-base 75237a9a; nothing published; skip-changeset on the PR (read back with size/xs, documentation).
  • The four lines, read on the head by the seat in a detached worktree at d181b4f0: os-dev.md :287 (119 B) 「needs:contract-review 归席位,⛔ 不挂不摘不等;报 PR 上有无与 --pair PR-NUMBER 退出码作读数。」; os-dev.md :301 (114 B) 「被拒 ⇒ 报端点与状态码、席位代挂,⛔ 不报 blocked、不走 MCP;写后必做对比式读回。」; SKILL.md :645 (101 B) 「needs:contract-review(恒英文)由席位同笔挂:PR 一现即挂 PR;报告先到则先挂卡。」; SKILL.md :646 (118 B) with --pair PR-NUMBER as the only spelling. Direction A holds in every carrier — the seat hangs (:645), the dev never hangs, removes or waits (:287), a refused additive label write is reported for the seat to hang, never blocked, never MCP (:301) — and contract-review.md :15–:16 keeps the ACCEPT-time PR-side catch-up. No rule is homeless.
  • Ratchets on the head, seat-run: 403/403 and 812/812 ✓, check-skill-id-lint 27 files clean ✓, check-skill-frame-sync ✓, frame block :734–:755 md5 3327d02c56f8a0eca88569dad2270f32 unchanged ✓; every edited line ≤ 119 B by the seat's own awk length.
  • A3: --pair N is gone from the three governed files (contract-review.md :42, os-dev.md :287, SKILL.md :646 all spell PR-NUMBER); the four remaining hits sit in scripts/pm/** docblocks beside text binding N to a PR number — outside the surface, recorded. A4: the sibling invocation PM_SWEEP_REPO=objectstack-ai/objectui node ../objectstack/scripts/pm/check-clause2-carriers.mjs --pair PR-NUMBER measured working from an objectui checkout (exit 0 on a live pair, exit 2 on a closed one); the byte cap keeps it off :287 and the script header names it. A2 measured: the additive label write was NOT refused on this container (200, read back), so the refusal is per container as the card said; :301 covers the refusing containers.
  • Gates 18 / 18 / 0 / 0 on the head per the patch report with exits captured by redirect (doc-formula-expressions after its prerequisite build under the verify lock); --pair 18250 exit 0 re-read by the seat on the head.

② Semver level

Not applicable — nothing published moves; skip-changeset measured (.claude/** is on the fast path).

③ Boundary flags

open_questions: none. Round-0 deviations (6) accepted on the REWORK; patch-round deviations (3) accepted: the widened region (the seat's own act), the catch-up clause kept in the reference, the worktree recreated from the pushed branch with no work redone. The REWORK's one item is discharged (the (b) finding on :645 is closed by this head). Out-of-scope notes — four --pair N docblock spellings in scripts/pm/**; os-dev.md :300 redundant with :301 — are acceptance notes, no card. Governed (both files = rules layer) ⇒ four-piece: needs-user-decision on the PR, 速读终稿 below, reviews requested; ⛔ not flipped ready by the seat before an authorized approval. Serial: PR #18242 (:172–:185) is disjoint; the second to land merges origin/main first.

Implemented-by: claude/issue-18181-carrier-is-the-seats-to-hang
Reviewed-by: session_01HZfg2AwVX191qCizp88gQr

VERDICT: PASS


Generated by Claude Code

@claude

claude Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor Author

维护者速读(终稿)

改了什么:两份席位规则文件各改两行,等行数、每行 ≤ 120 字节。① os-dev.md :287:needs:contract-review 这枚复核标签归席位——dev 不挂、不摘、不等,只在报告里写 PR 上有没有它,并附 --pair PR-NUMBER 的读数;:301:dev 的加法标签写被容器拒绝时,报端点与状态码由席位代挂,不再报 blocked、不走 MCP。② SKILL.md :645:标签由席位同笔挂(PR 一出现就挂 PR;报告先到就先挂卡);:646:--pair N 改成 --pair PR-NUMBER,三份治理文件里只剩这一种拼写。

为什么改:原文要求 dev「开 PR 同笔挂标签」,而 objectui 的两名 dev 实测被容器的写分类器拒绝——照做的 dev 失败、报告失败的 dev 看起来像抗命;同一行还把 --pair N 的 N 绑到卡号,脚本要的却是 PR 号(传卡号退 2 = 未测,天真读法当红)。席位本来就在替 dev 挂这枚标签,现在把文本改成事实。补丁轮顺手把 SKILL.md :645「由 PR 创建者挂」改掉——否则规则层落地后会自相矛盾。

风险与代价(含回滚):纯文本、不碰发布包、不改 CI;行数不变。回滚 = revert 一个 PR。放宽容器写权限(方案 B)是权限面的事,不在本 PR,由你另定。一处已知残留:scripts/pm/** 的 4 处 docblock 仍写 --pair N,旁边都有 N 绑 PR 号的说明,不动。

席位意见:建议批准。本席在 head 上亲核:四行内容与字节(119/114/101/118)、棘轮 403/403 与 812/812、frame 块 md5 不变、id-lint 与 frame-sync 绿、--pair 0;objectui 侧调用形态 dev 实测可用。CI 在新 head 上重跑中(旧 head 的 type-check 红是并发取消伪红),绿后才由本席按裁决 C 落地;与 PR #18242 同文件不同区域,后落地者先合 main。

你要做的(一个动作):approve 本 PR。approve 后本席翻 ready + 入队。


Generated by Claude Code

@os-zhuang
os-zhuang marked this pull request as ready for review September 15, 2026 06:07
@os-zhuang
os-zhuang added this pull request to the merge queue Sep 15, 2026
@claude

claude Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor Author

Ruling-C landing provenance — skills seat, session session_01HZfg2AwVX191qCizp88gQr, 2026-09-15T06:14Z. Authorized approval: os-zhuang's APPROVED reviews 5206130889 (2026-09-15T06:07Z) and 5206135851 (2026-09-15T06:07Z) on head d181b4f0c65d10f8bbf5d34d49bb50bd3e6d95a6, the same head the review of record 5674459504 (## Contract review PASS) names and the ACCEPT 5674459894 on #18181 cites; not dismissed. The approver also flipped the PR ready (2026-09-15T06:07Z) and enqueued it (added_to_merge_queue 2026-09-15T06:07Z, actor os-zhuang; queue ref gh-readonly-queue/main/pr-18250-* present on origin at 2026-09-15T06:13Z), so the seat's remaining acts under ruling C are the readings and the label: check-clause2-carriers --pair 18250 exit 0 re-read at 2026-09-15T06:13Z with the C6-RECORD note naming that record; on that head Lint & Repo Gates and TypeScript Type Check both success and every other check is success or skipped (31 runs: 18 success, 13 skipped); mergeable_state clean, no main commit touching os-dev.md or SKILL.md since the merge-base, so no branch update was made (the queue builds the merge, behind PRs #18242 and #18244); needs-user-decision cleared through label-write.mjs and read back. Serial note: PR #18242 (:172–:185) and PR #18256 (:306–:415) share SKILL.md in disjoint regions and are in the same queue; PR #18273 (#18264) holds os-dev.md :319–:398, disjoint from this PR's :287 / :301, and merges origin/main at its own landing. MERGED is confirmed later by two readings (the queue ref gone + git log origin/main carrying (#18250) with one parent), then #18181's residue is stripped.


Generated by Claude Code

Merged via the queue into main with commit 41ff021 Sep 15, 2026
35 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-18181-carrier-is-the-seats-to-hang branch September 15, 2026 06:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/xs skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants