docs(pm): the clause-② contract review is tier-bound — the dispatching seat reviews in-seat at CONTRACT_REVIEW_TIER, no seat list - #18363
Conversation
…g seat reviews in-seat at CONTRACT_REVIEW_TIER, no seat list Re-keys the three lines that bound the clause-② contract review to a SEAT so the condition is the served TIER instead: SKILL.md :513 and :523 (in place, 812 / 812), contract-review.md :26 (in place, 60 / 60), and ONE new platform-readings.md row recording that the harness classifier refuses a content write by content (a PASS on a PR the same session dispatched), with the same-channel control. The SELF-REVIEW machine reading and the independence pair are untouched. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HZfg2AwVX191qCizp88gQr
…e-key — the fuse covers every seat that issues a clause-② verdict Patch round on the seat's answer A: four in-place re-keys, no new line. SKILL.md :641 (119 → 117 B) drops 「spec 席达档,余席默认档」 for 「达档审,未达档默认档」; contract-review.md :41 (119 → 116 B) reads 「档位按实测」 in place of 「档位按逐车道」; :51 (116 → 105 B) makes the fuse's population every seat that issues a clause-② verdict instead of the spec and skills seats; :52 (113 → 89 B) drops the default-tier 「余席条款②复核」 class, which no longer exists under the tier condition, and keeps the director seat's exemption verbatim. SKILL.md :610 is untouched — it is clause-① routing for the published skills face, not the clause-② seat list. 812 / 812 and 60 / 60 hold. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HZfg2AwVX191qCizp88gQr
Contract reviewServed-tier: Reviewing seat: ① Derived judgments
② Semver levelNot applicable — nothing published moves; ③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
维护者速读(终稿)— PR #18363 / #18349改了什么:把你 2026-09-16 的裁决(「同意」:条款②复核 = 派发席在契约复审档席内做,记录写档位读数;不再有「只在 spec 席」)落成文本。原先三处把条款②复核绑在席位上(SKILL.md :513「契约复审档复核只在 spec 席」、:523「契约复审档留给 skills 席与 spec 席…其余席位 ⛔ 永不起该档子代理」、contract-review :26「逐车道:spec 席达档审…余席默认档自审」),现在绑在档位上::513「达档复核归派发席席内」;:523「条款②复核只在实测达档的席内做,记录写读数;未达档席 ⛔ 不审、不起该档子代理」;:26「按档位:达档席内审契约增量;未达档默认档自审加门禁、挂标」。补丁轮又把四处残留一并改掉(SKILL.md :641、contract-review :41/:51/:52):保险丝从「只管 spec 席与 skills 席」改为「管每个出条款②裁决的席」,总监席照旧豁免。platform-readings 新增一行记 harness 分类器按内容拒写(同会话派发 PR 上的 PASS 被拒作 验证:本席在 head 要你做的:审 PR #18363,同意即 APPROVE(只能请 hotlong;os-zhuang 是 PR 作者)。 Generated by Claude Code |
|
Ruling-C landing provenance — skills seat (signed off, 留守 on this PR), session Generated by Claude Code |
…e ccr routes are counted (objectstack-ai#18396) Fixes objectstack-ai#18361 `references/platform-readings.md` only, in place at **466 / 466 lines** (ratchet ceiling, headroom 0). **Four** rows re-keyed by judgment; no row added, none removed, no re-wrap, every rewritten line under the gate's 120-byte cap. Three rows landed in the first commit (`b0c55121`). The fourth arrived with the seat's review (comment 5694684277 on objectstack-ai#18361), which widened this claim's file surface by one row: a fact table does not carry a row whose job is to say the row above it is false, so the row above is re-keyed in place instead — second commit `a7026a35`, no force-push, no rebase. Rows are located by CONTENT, not by the card's line numbers: the card was filed against `1411cf2c` and the file has landed twice since (`b57671ed` objectstack-ai#18359 at 04:18Z, `05f1cdd6` objectstack-ai#18363 at 06:40Z), so :134 / :143 / :57 have drifted. ## Row 1 — the GraphQL-only membership row (line 134 on this branch) Landing point: the row directly under 「GraphQL 池 5000/时,只留给没有 REST 对应物的几件。」 before (verbatim, 113 B): ``` - 那几件 = draft 翻转、auto-merge 挂载、语义 `/search/*`、Projects field_values、`issue transfer`。 ``` after (verbatim, 118 B): ``` - 那几件 = `rest-channel.md`〈不可迁移〉那三件;draft 翻转与 auto-merge 挂载有 ccr 路、不在内。 ``` ## Row 2 — the queue-repo landing row (line 142), widened into scope by the seat's review Landing point: the row directly under 「红窗调度:守候只给上面那几件 GraphQL-only 的,⛔ 其余一切不为配额空等。」 before (verbatim, 107 B): ``` - 走队列的仓落地必经 auto-merge ⇒ 红窗里无退路;直合仓有,合并本身有 REST 端点。 ``` after (verbatim, 118 B): ``` - 走队列的仓落地仍必经 auto-merge,红窗里照样走 ccr REST 挂载;直合仓合并本身有 REST 端点。 ``` The row's premise — that arming is GraphQL-only — is the same one the card retires, so the row is retired with it. What survives is what is still true: a queue repo's landing still goes through auto-merge (the queue is not bypassed), the mount in a red window rides the ccr REST route, and the direct-merge half keeps its REST endpoint. ## Row 3 — the red-window stand-down row (line 143) Landing point: the row directly under row 2. before (verbatim, 70 B): ``` - MCP 侧限流下,draft 翻转与 auto-merge 挂载整窗不可得。 ``` after (verbatim, 89 B): ``` - 红窗里 draft 翻转与 auto-merge 挂载照常走 ccr REST,⛔ 不为它们守候。 ``` The first commit ended this row with 「⇒ 上条无退路不成立」, a clause whose only job was to void the row above. The review rejected that shape — correctly: a reader of a fact table should not have to hold two rows in mind to get one fact. With row 2 re-keyed, the clause has nothing to do and is gone. ## Row 4 — the echo row (line 57), carrying comment 5693336603's mechanism Landing point: the row directly under 「squash 的 committer date 是入队时刻,快进不改 ⇒ 落地时刻读 merged_at/merged,不读 git log。」 before (verbatim, 114 B): ``` - 回显两向不可靠,空回显不等于未挂上 ⇒ ⛔ 不拿它当任何方向的证据、不为它空转。 ``` after (verbatim, 115 B): ``` - 回显两向不可靠:全绿加 `clean` 即吞进队列不存记录 ⇒ 空回显是成功常态,⛔ 不空转。 ``` The byte WAS there, so the note is carried here rather than left on the card: the mechanism (all checks green plus `mergeable_state: clean` is consumed straight into the queue and stores no record, so an empty echo is the normal echo of SUCCESS) replaces two clauses the row no longer has to spend bytes on. `空回显不等于未挂上` is subsumed by the stronger `空回显是成功常态`, and `⛔ 不拿它当任何方向的证据` follows from `回显两向不可靠` in the same sentence. The note's third half — never re-arm on a NULL alone — is NOT restated: the file already carries it at 「⛔ 永不据它判没挂上而重挂 —— 重挂踢队重排。」, and a second copy is what this card exists to remove. ## The card's question: mirror rest-channel's 「不可迁移 —— 只有这三件」, or point at it **Point at it.** Three reasons, in descending authority: 1. A maintainer ruling already assigns ownership. The 2026-09-01 batch (总监批 objectstack-ai#22, quoted in `scripts/pm/check-skill-line-ratchet.mjs`'s ceiling comment for `rest-channel.md`) reads, verbatim and untranslated: 「**C 同批**:退役 L58 对红窗常设规则的复述 —— 内容归属裁定:**红窗规则由 `platform-readings.md` 配额段独家持有**,`rest-channel.md` 只留指路」. The split it draws is symmetric: red-window POLICY is this file's, per-operation CHANNEL MAPPING is rest-channel's. Which operations have no REST twin is channel mapping. 2. This file already says so in its own voice, one row below the one being re-keyed: 「逐操作通道归属、写侧配方与队列路由三读法见 rest-channel.md,⛔ 不在本表复述。」 The row this PR re-keys was the one row in breach of its own neighbour. 3. The drift is the evidence. rest-channel's list stayed correct across lock 1; the mirror here went stale and stood a seat down for two operations that had a route the whole time. A mirror re-opens exactly that channel. rest-channel's heading already carries the return pointer (「红窗守候规则住 platform-readings.md 配额段」), so after this PR each fact has exactly one home and each home points at the other. What is NOT delegated is the JUDGMENT the card asked for: the two operations that left the list are named here, in the negative, because a seat that remembers the old list needs the deletion stated, not merely absent. The three that stay are not re-listed. ⛔ `rest-channel.md` is not touched by this PR. Its rows 46 and 50 are already correct. ## Acceptance notes - Adjacent rows read and left standing because they stay TRUE under the re-key: 「红窗调度:守候只给上面那几件 GraphQL-only 的…」 (line 141) becomes automatically correct once line 134 points at the three; and 「被挡住的翻转是在等窗口,不是关于该 PR 的信号…」 (line 144) survives, because a flip can still be blocked by the session gate (`GitHub access is not enabled for this session`) or by REST core, so its prohibition still has a referent. - noted, not filed: 「走队列的仓落地仍必经 auto-merge」 still reads as if arming were the only landing path. It is, on this repo, under Prime Directive 14's governed-surface carve-out and the queue rules — but the row does not say which of those makes it so. 承接者: none; recorded here so the next author of this block knows it was read and judged, not missed. - Out-of-scope finding reported to the seat (class b, contract violation): the spec seat's 2026-09-16T06:19Z measurement (seat post objectstack-ai#6017, comment 5692971090) — no `enqueued` event on this repo's `/issues/N/timeline`, the queue ref answering BUILD rather than membership, and `auto_merge` cleared on enqueue — conflicts with rows 10–12 of this same file, which make the timeline event the decisive membership reading. Out of this card's scope, untouched here. Row 4's rewrite was written to be consistent with it (a consumed request stores no record), not against it. ## Gates Targeted set for a `.claude/skills/**` docs-only diff, re-derived from the actual change at the new head with `node scripts/pm/dispatch-gates.mjs --commands` (no paths) and reconciled with `--ran`: 16 derived / 16 run / 0 NOT-MEASURED / 0 UNRUN, the same 16 as the first round. Exit codes captured to a file before reading, never across a pipe. Ratchet at the new head: 466 lines, ceiling 466, headroom 0. Per-command results are in the report comments on objectstack-ai#18361. `skip-changeset`: nothing published moves — `.claude/**` is not in any package's `files[]`, it is the fast track, not a measurement. ## 维护者速读(草稿) **改了什么** —— 只动 `references/platform-readings.md` 四行,行数 466 → 466。一是 GraphQL-only 清单那行:不再自己列五件,改成指向 `rest-channel.md`〈不可迁移〉的三件,并写明 draft 翻转与 auto-merge 挂载有 ccr 路、不在其内。二是「走队列的仓落地必经 auto-merge ⇒ 红窗里无退路」那行:改成落地仍必经 auto-merge、红窗里照样走 ccr REST 挂载,直合仓那半保留。三是红窗那行:两件在限流窗里照常走 ccr REST,别为它们守候。四是回显那行:补进「全绿加 clean 即被吞进队列、不存记录,所以空回显是成功的常态」这条机制。 **为什么改** —— 锁 1 之后 ccr 路是这两件操作的唯一通道,而清单还把它们记作没有 REST 对应物。后果不是措辞问题:读到红窗那几行的席位会白等一个根本不用等的窗口。清单归属有 2026-09-01 的裁定在先(红窗规则归本表独家,通道归属归 `rest-channel.md`),所以这次是把重复的那份退役成指路,不是再抄一遍。第二行是席位复核时扩进来的:原先我只在下一行写「上条无退路不成立」,事实表不该有一行专门宣布上一行为假,现在把上一行本身改对了。 **风险与代价(含回滚)** —— 风险有两处。① 席位要判某个操作是不是 GraphQL-only 时,多读一个文件(`rest-channel.md`,82 行、零配额);换来的是清单只有一份、不会再各自漂移。② 这四行都在同一段里,措辞收紧后相邻行的语气略有重叠(红窗里走 ccr REST 这件事在两行都出现一次),是刻意的:一行讲落地路径,一行讲要不要守候。回滚代价极低:四行就地改写,两个提交都可 `git revert`,棘轮读数不变。 **席位意见** —— **你要做的** —— 若同意「指路而不镜像」这一判断,按 references 档在席复核后落地即可;若更希望本表继续自列三件(以红窗里少读一个文件换一份可能再漂的副本),请在此说明,我改回列举形。 --- _Generated by [Claude Code](https://claude.ai/code)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
…ning an at-tier subagent (ruling C) (objectstack-ai#18511) Fixes objectstack-ai#18434 Governed rules-layer re-key carrying the maintainer's ruling 「18434 C」 (director record 5699124096 on the card; the maintainer's confirmation on the ui seat's channel, record 5701005814: 「改规则:允许未达档席起达档子代理」). Three prose files (the third, `references/core-rules.md`, added in the patch round — D9 below), no code, no script edits, every touched file line-neutral against its ratchet ceiling. Landing is not the author's: this PR stays draft; the skills seat hangs the four-piece and the maintainer's approval lands it. ## What changed ### `.claude/skills/pm-dispatch/SKILL.md` — 812 / 812 (two lines re-keyed in place) | line | before | after | |:--|:--|:--| | :522 (114 B → 118 B) | 「- 条款②复核只在实测达档的席内做,记录写读数;未达档席 ⛔ 不审、不起该档子代理。」 | 「- 条款②复核按实测档:达档席内审;未达档席 ⛔ 不自审,起隔离达档子代理转录核档采信。」 | | :640 (117 B → 117 B) | 「- 交付后复核由派发席席内完成:达档审,未达档默认档加门禁;记录 = 同形评论落 PR 或卡。」 | 「- 交付后复核归派发席:达档席内审,未达档循保险丝起子代理;记录 = 同形评论落 PR 或卡。」 | :522 is the ruling's line — meaning fixed by the ruling, wording the dev's, 118 B under the 120 B cap. 「记录写读数」 was dropped from it because the record requirement lives in `contract-review.md` (「复核记录 = 一条评论落 PR 或卡」, 「同形含首行 `Served-tier:`」). ### `.claude/skills/pm-dispatch/references/contract-review.md` — 60 / 60 | line (new numbering) | before | after | |:--|:--|:--| | :26 (119 B → 116 B) | 「- 按档位:达档席内审契约增量;未达档默认档自审加门禁、挂标;豁免仅独立性件与保险丝。」 | 「- 按档位:达档席内审契约增量;未达档 ⛔ 不自审,走保险丝路;豁免仅独立性件与保险丝。」 | | old :39 deleted (97 B — the payment) | 「- 随后按 `landing-operations.md` 走落地前检 → 转 ready → 挂 auto-merge 或入队。」 | — (the same sequence is SKILL.md :617 「席位落地 = 过落地前检、清标、ready、auto-merge」 and :641; the three-step pre-landing check that follows at :40–:46 is untouched) | | :50, was :51 (105 B → 120 B) | 「- 保险丝管每个出条款②裁决的席,每场前必读服役档,读法见 `platform-readings.md`。」 | 「- 保险丝管每个出条款②裁决的席:每场前必读服役档(`platform-readings.md`),未达档 ⛔ 不自审。」 | | :53, was :54 (108 B → 114 B) | 「- 读数不达档 ⇒ 改走转录核验的复核子代理;标签原样留置,队列外等待是安全态。」 | 「- 读数不达档 ⇒ 改走转录核验的达档复核子代理;标签原样留置,队列外等待是安全态。」 | | :54, was :55 (108 B → 118 B) | 「- 保险丝只测座位自会话:`mode:subagent` 里 `get_session` 量的是派发会话,⛔ 不作互证。」 | 「- 子代理档只取其转录 harness 逐请求 `model` 盖章;`get_session` 量的是派发会话,⛔ 不作互证。」 | | :59 (new, 110 B) | — | 「- PASS、FAIL 与作废都落 PR 或卡;同 head 再起子代理须引前次作废因,⛔ 不重起求 PASS。」 | ### `.claude/skills/pm-dispatch/references/core-rules.md` — 151 / 151 (one line re-keyed in place, patch round) | line | before | after | |:--|:--|:--| | :112 (119 B → 119 B) | 「- 一单一次派发,档位逐卡显式传参;语义面卡恒契约复审档施工,契约卡达档复核归 spec 席。」 | 「- 一单一次派发,档位逐卡显式传参;语义面卡恒契约复审档施工,契约卡达档复核归派发席。」 | The twin probe `git grep -n '达档\|子代理' origin/main -- .claude/skills/pm-dispatch/references/core-rules.md` returns :51 :112 :113 :122, none of which states the spawn bar — but :112 still named the pre-tier-bound owner (spec seat) of the clause-② at-tier review, while SKILL.md :512 reads 「达档复核归派发席席内」 and contract-review.md :25 「归属该卡派发席」. 「席内」 is not spelled at :112 because the line would be 125 B against the 120 B cap; it is carried by SKILL.md :512. ### The three guards, where each now lives 1. Tier verified from the transcript, not the request — :52 「⛔ 自述档位与传参皆非读数」 (unchanged); :54 (the subagent's tier is taken only from the harness per-request `model` stamps in its own transcript; `get_session` measures the dispatching session and is no cross-proof); :57 「产出裁决的每轮都须读到契约复审档位,见回退证据 ⇒ 裁决整体作废」 (unchanged); :60, the quota-exemption bar (unchanged). Before this PR the file said 「转录核验」 but named no source for the subagent's tier — `platform-readings.md` :384 covers the seat's OWN session transcript, and the old :55 said `get_session` cannot see the subagent — so the source is added, not merely re-worded (PM assumption A2: substance present, source absent). 2. Adversarial brief, no contamination — :32–:33 unchanged. 3. Verbatim or void, every time on the record — :58 unchanged (verbatim adoption or whole voiding for 核验失败 / 越范围 / 格式不完整); the NEW :59 adds the half that was absent: every verdict, PASS, FAIL or voided, is posted on the PR or card, and a second spawn on the same head cites the first's void reason. Independence pair (:35–:37), `--pair` (:41–:42, :55) and `Served-tier:` (:29) are unchanged. No script is edited (PM assumption A3 holds: `check-clause2-carriers.mjs --pair` already reads `Served-tier:`; guard 1 is a reading rule). ## Deviation, declared: :640 and :26 are in the diff PM assumption A1 (「line 522 is the only SKILL.md line stating the old bar」) holds for the spawn bar — `不起该档子代理` is only at :522 — and is falsified for the in-person bar. PR objectstack-ai#18363 (`05f1cdd6`) wrote the rule in three places at once (its own file patch: SKILL.md :512 / :522 / :640 and contract-review.md :26 / :41 / :51 / :52), and :640 「未达档默认档加门禁」 and :26 「未达档默认档自审加门禁、挂标」 still described an off-tier seat reviewing IN PERSON at default tier — the half of the bar that ruling C keeps (the ui seat's record: 「the bar on reviewing in person stands; the bar on spawning does not」). Leaving them would re-create the two-texts-disagree shape this card reports, so both are re-keyed in place under the bounded in-place-fix exemption: same defect class; mechanical, with the meaning pinned by the ruling; no other claim holds either file (objectstack-ai#18489 is instructed not to touch :523 and targets the triage block, objectstack-ai#18469 targets :91–92, and the file lists of all 15 open PRs read at PR time touch neither file); same gate family. If the seat prefers the narrow diff, reverting those two lines is a two-line change and every gate below stays green. Answered by the coordinator in the patch round: **A — keep**. ### D9 — patch round: core-rules.md :112 rides this PR The out-of-scope finding (b) from the first report was verified by the coordinator on `origin/main` `8cf527f` and ruled to ride this PR under the same bounded in-place-fix exemption (same class as D1 — text still naming the pre-tier-bound owner; mechanical; no other claim holds `core-rules.md` — objectstack-ai#18489 is `pm:blocked`, objectstack-ai#18469 does not touch it; same gate family) instead of a fourth governed four-piece. Executed: `origin/main` merged first (`acc1943`, one docs commit touching `content/docs/data-modeling/seed-data.mdx` only, no regeneration owed); :112 re-keyed in place (`af846cf`). Probes with controls on `core-rules.md`: `归 spec 席` 1 → 0, `归派发席` 0 → 1, control `契约复审档` 1 → 1; every other core-rules line byte-identical (`git diff -U0` shows the single line). ## Verification — round 2 on `af846cf` (round 1 on `3088a1c` read identically) - Gate list derived with no paths, off the merge base with `origin/main`: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` → 17 families (identical to the PM's lead). All 17 run in the foreground, each exit code captured by redirect then `$?`, every one `0`. Reconciliation `--ran` with `COMMAND :: exit CODE` lines: 「✓ dispatch-gates --ran: 17 derived famil(ies) accounted for — 17 run, 0 NOT-MEASURED (a DERIVED zero — all 17 recorded an exit code and none of them is 3)」. - Ratchet: 「✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/SKILL.md is 812 lines (ceiling 812; headroom 0)」 · 「…contract-review.md is 60 lines (ceiling 60; headroom 0)」 · 「…core-rules.md is 151 lines (ceiling 151; headroom 0)」; widest introduced line 120 B (:50 of contract-review.md); core-rules :112 is 119 B. - `check:pm-skill-id-lint` 「27 file(s) clean」 · `check:skill-frame-sync` 「the one declared copy of the decision frame is internally coherent」 · `check:nul-bytes` 「OK (scanned 8738 text file(s) … no raw ASCII control bytes)」. - `check:doc-formula-expressions` needed `@objectstack/formula` and `@objectstack/lint` built: built under `scripts/pm/os-verify-lock.sh` (「VERDICT command-exit 0 · held the lock 141s · waited 0s」), then 「✓ check:doc-formula-expressions: 22 record-scoped formula example(s) across 438 files / 1377 TS blocks judged clean」. - Probes, `origin/main` `fed4a15` → this head: `不起该档子代理` 1 → 0; `起隔离达档子代理` 0 → 1; control `达档` 6 lines → 6; `默认档加门禁|自审加门禁` 1 + 1 → 0 + 0; core-rules.md `归 spec 席` 1 → 0, `归派发席` 0 → 1, control `契约复审档` 1 → 1. - No reverse-verification or ablation leg: a prose rule with no runtime or dist; the probe flip above is the before/after measurement. ## Acceptance notes - Finding (b) from the first report — `references/core-rules.md` :112 「契约卡达档复核归 spec 席」 naming the pre-objectstack-ai#18363 owner — is no longer to file: it rides this PR (patch round, D9 above) by the coordinator's ruling. - noted, not filed: SKILL.md :673 「报告席记条款②默认档 FAIL 率入复审清单」 reads consistently under C when 「默认档」 is the construction tier (:512), so no change; handler: none. ## 维护者速读(草稿) **改了什么**:把条款②契约复核的路线改成你 16 日下午定的 C:达档的席自己审;未达档的席不自己审,起一个隔离的达档复核子代理,按子代理转录里逐请求的档位盖章采信其裁决。`SKILL.md` 两行、`contract-review.md` 六行(删一行付账、新增一行记「每份裁决都落 PR 或卡,同 head 再起须引上次作废因」)、`core-rules.md` 一行(:112 把契约卡达档复核的归属从 spec 席改为派发席,与 `SKILL.md` :512 一致),行数与上限一致(812 / 812、60 / 60、151 / 151)。 **为什么改**:今天早上落地的 :523 把「不自审」和「不起子代理」绑在一起,默认档车道的 `Clause-②: yes` 卡就没有任何合法路径拿到裁决——objectui 三张 PR 停在安全态,第四张(objectui#8167,你批过的 p2)干脆没派出去。你的裁决 C 只放开「谁可以起复核」,不放开「什么算复核」:`Served-tier:` 首行、子代理必须真的跑在契约复审档、实现者与复核者同会话仍算自审,三条都不变。 **风险与代价(含回滚)**:零代码、零脚本、零发布物,17 个派生门禁全绿。剩下的风险在执行面:平台是否会把父会话逐字转贴的子代理裁决也拒为 `[Self-Approval]` 尚未实测(裁决记录已写明首次使用时测量并记入 `platform-readings.md`)。回滚 = revert 本 PR 的一个 commit,文本回到 :523 的旧句,车道回到安全态停靠。 **席位意见**:(留空,席位定稿) **你要做的**:按四件套流程批准本 PR(规则层,等你的字);合并后 `domain:ui` 席直接按新规则处理停靠的三张 PR,不需要你再动。 --- _Generated by [Claude Code](https://claude.ai/code/session_01Gqi43smmqjJ5sUrhfoPeKu)_ --- _Generated by [Claude Code](https://claude.ai/code)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
Fixes #18349
Clause-②: no
What changed
The maintainer ruled (2026-09-16, recorded verbatim on the card) that the clause-② contract review is done in-seat by the dispatching seat at the contract-review tier, and that there is no longer a 「只在 spec 席」:
Sentence 2 needs no text change (SKILL.md :527–:528 and contract-review.md :25 already say it). Sentence 1 re-keys the three lines that bound the review to a SEAT so that the served TIER is the condition — in place, no new line:
Plus ONE new platform-readings.md row (:429, 113 B, in 「读数陷阱」 beside the other harness readings): 「harness 按内容拒写:同会话派发 PR 上 PASS 拒为
[Self-Approval];同通道建卡、ACCEPT 照过。」 — measured 2026-09-16 on objectui PR #9578: the harness auto-mode classifier refused aVERDICT: PASSrecord on a PR the same session had dispatched as[Self-Approval], while a card create and an ACCEPT on the same channel were served seconds later; this seat's five same-shape PASS records of 2026-09-15 throughpost-stamped.mjswere not refused — so the reading is the channel-and-content pair, not the endpoint.Untouched: the SELF-REVIEW machine reading (contract-review.md :37 —
Implemented-by:is the branch for a subagent dev) and the independence pair (:35–:36).Note: the card body and the ruling comment cite the 「逐车道」 line as contract-review.md :25 (read at
500c1b56); onorigin/main1411cf2cit is :26 (:25 is the 「归属该卡派发席」 line) — the edit went to the line by content, not by number.The one design choice — how the tier condition is spelled
The question was how to spell the condition so a seat NOT at the tier cannot read itself as eligible. Options: (A) 「达档」 alone — a seat could read its configured tier as eligibility; (B) 「实测达档」 plus 「记录写读数」 — eligibility is the measured reading and the record must carry it (contract-review.md :29 already makes a record without
Served-tier:no verdict; :53 already says a self-declared tier is not a reading), with the ⛔ half 「未达档席 ⛔ 不审、不起该档子代理」 closing the escape of spawning the tier subagent; (C) naming theget_sessionfields inline — over the 120-byte budget and already recorded at platform-readings :378 and contract-review :55. Chosen: B. On the four axes — 实际业务需求: the live case is real (objectui PR #9578, aClause-②: yescard held in the safe state) and every PM seat today measures at the tier, so in-seat review removes a handoff that had no executable spelling; 项目长远合理性: a tier condition is machine-checkable (--pairreadsServed-tier:), a seat list is not; 防 AI 犯错: 实测 binds eligibility to a reading rather than a declaration, and the ⛔ half keeps the prohibition greppable; 创业阶段不扩散: no new mechanism, label, handoff artefact or line — three in-place re-keys and one fact row.Reverse verification
BEFORE (
1411cf2c): the three lines quoted above with their byte counts; sweepgrep -n '只在 spec 席\|其余席位 ⛔ 永不起该档\|spec 席达档审'over SKILL.md and references = 3 hits (:513, :523, contract-review :26);grep -c CONTRACT_REVIEW_TIER SKILL.md= 1; SKILL.md 812 lines, contract-review.md 60, platform-readings.md 463; frame block :734–:755 md53327d02c56f8a0eca88569dad2270f32.AFTER (
55b467b0): sweep = 0; constant count = 1 (unchanged); 812 / 812, 60 / 60, platform-readings 464 (ceiling 466; PR #18359, open on other regions of the same file, nets +2, so 466 once both land and no 467th); frame md5 unchanged3327d02c56f8a0eca88569dad2270f32;git diff --stat= the three files and nothing else; zero raw control bytes in the touched files; every touched line ≤ 120 B (the ratchet'sMAX_LINE_BYTES).Gates (run on
55b467b0)node scripts/pm/dispatch-gates.mjs --commandsover the three paths derived 18 commands; all 18 run;--ranreconciliation: 「18 derived, 18 run, 0 NOT-MEASURED, 0 UNRUN」. Green:check:pm-skill-ratchet,check:pm-skill-id-lint,check:skill-frame-sync,check:nul-bytes,check:pm-governed-prose,check:pm-governed-merges,check:pm-half-states,check:required-contexts,check:doc-authoring,check:agent-test-spelling,check:watch-hint-literal,check:refd-timer-probe,check:driver-memory-census,check-closing-keyword-parity(and its--self-test),check-comment-mask-corpus,check-governed-queue-guard --self-test, and@objectstack/lint check:doc-formula-expressions(first run exit 3 PREREQUISITE NOT MET — the formula and lint dist were not built; both built under the verify lock, re-run exit 0). Path face:check-governed-merges.mjs --test SKILL.md= GOVERNED (exit 3 is that verdict). Thecheck:pm-dispatch-gatesbattery was not derived for these paths.check-clause2-carriers.mjs --pairon this PR: reading in the report comment on the card.Acceptance notes
origin/main..claude/**is shipped by no package'sfiles[]), soskip-changeset.lanes/spec.mdandlanes/skills.md: no seat-bound restatement (spec.md :19, :20, :33 and skills.md :20 are trigger and gate lines only).dispatch-gates.mjs --tierprints the tier's model literal rather than the constant name; this PR names onlyCONTRACT_REVIEW_TIER.维护者速读(草稿)
改了什么:把「条款②契约复核只在 spec 席做」改成「由派发席在契约复审档席内做,记录写档位读数;未达档的席不审、不起该档子代理」—— SKILL.md 两行、contract-review.md 一行原位改写,platform-readings.md 新增一行事实(harness 按内容拒写 PASS 裁决)。行数 812 / 812、60 / 60、464 / 466。
为什么改:您 2026-09-16 裁「同意」的两句里第一句要求去掉「只在 spec 席」;objectui 那张 Clause-② 卡在没有交接拼写的情况下被卡在安全态,席内达档复核是零延迟的路。第二句(新 spec 工作仍归 spec 席)现行文本已写,无需改。
风险与代价(含回滚):三行改写全在
.claude/**,不发布、不动代码;回滚 = revert 本 PR 的一个 commit。残留:SKILL.md :641 与 contract-review.md :51–:52 仍按旧席位表述,本 PR 未动(超出派发面),需席位补一轮。席位意见:(留空,席位定稿)
你要做的:确认本 PR 的三行改写是否如实落了裁决第一句;确认后由席位走四件套 + 授权批准落地;顺带定 :641 / :51–:52 是并入本 PR 补丁轮还是另立卡。
Generated by Claude Code