docs(pm-dispatch): the dev queue is product-only — tooling cards close at first grading, broken gates are deleted, ≤1 tooling dev in flight, tooling is a first-touch label (ruling #202 B) - #19462
Conversation
…first grading Five charter edits under the maintainer's ruling batch #202 letter B: 1. `pm:queue` no longer admits a well-scoped tooling/gate fix by definition (SKILL.md and references/core-rules.md, same PR); a `tooling` card enters only with an `Unblocks: #N` open product card or a named published surface, and the execution seat's candidate query excludes the rest. 2. Triage closes at first grading: `Path: none` closes not_planned with the reason and the two reopen conditions; gate headers, self-test text and `check-*` remedy sentences are not a declared contract for class (b); North Star rule 3 restated as a closing rule. 3. A gate that misfires twice is deleted, limb or gate, in a PR citing the two measurements; a repair card is filed only for a gate that protects a product landing or a customer-visible contract. 4. At most one `pm:dispatched` tooling card fleet-wide; `Unblocks:` cards inherit the product priority and do not count. 5. `tooling` is a first-touch triage label: glossary row in the state model, four named readers under the named-reader rule. Claude-Session: https://claude.ai/code/session_012GcsUbuqFGBibkEDMRC1eE Co-authored-by: Claude <noreply@anthropic.com>
|
Director seat ( Not fixable by this seat or the dev: raising a ceiling is on the charter's manual floor and needs the maintainer's own words quoted in the PR. Asked in chat. When granted, the round updates the single Generated by Claude Code |
Resolves the one conflict, in `.claude/skills/pm-dispatch/SKILL.md`, keeping both sides. #19459 rewrote the grading line this card also edits; main's four-segment `Path:` spelling and its two new lines (定义项 / 清单项) are kept verbatim, and this card's three additions sit beside them: - the grading reference now reads North Star 「优先级」1–3 条 (main had 1、2); 「1–3」 rather than 「1、2、3」 because the latter spelling puts the line at 121 bytes against the ratchet's 120-byte cap. - the close-at-first-touch rule is folded onto main's own 「无则关」 clause instead of restating it: it carries only what main lacks — not_planned, the reason, the two reopen conditions, and ⛔ 不定 p3、不 hold. - the tooling closing rule (North Star rule 3) follows it and inherits that prohibition through 「下行同此」. Claude-Session: https://claude.ai/code/session_012GcsUbuqFGBibkEDMRC1eE Co-authored-by: Claude <noreply@anthropic.com>
…d declare the label object Two post-merge changes, both paying down what round 1 reported: - The four named readers move off their own bullet and into the `tooling` glossary row itself, which is where the card asks for them and which the ratchet exempts from the 120-byte cap (the row is 227 bytes against this file's 342-byte widest-row pin). SKILL.md is 821 lines, 8 over the 813 ceiling instead of 9. - `scripts/pm/ensure-pm-labels.sh` gains the `tooling` row. Measured today in objectstack, the live label object carries GitHub's default `ededed` and an EMPTY description on 44 queue cards, because nothing in the vocabulary script named it — the drift that file's own header describes, and one no rerun of the default mode can repair. The description is 100 characters, at the cap (`pnpm check:pm-label-desc-cap` green, and it names `tooling` as the longest). Claude-Session: https://claude.ai/code/session_012GcsUbuqFGBibkEDMRC1eE Co-authored-by: Claude <noreply@anthropic.com>
…dit 6) Maintainer directive, verbatim and untranslated: 「受管合并审计 以后不需要了,浪费时间。」 - `references/lanes/director.md` loses 〈职责四:受管合并审计〉 entire — heading and its six bullets, 9 lines including the blank — and its 四职 reference becomes 三职. The file goes 72 → 63 lines. - SKILL.md loses the two lines that RAN the audit (the `--since` invocation and the lane-early-warning / director-window split), drops the audit list from the round-report contents line, and its two duty-roster mentions become 三职. The guard-index row keeps the SCRIPT and loses only 轮报载体, which is now false. - `references/core-rules.md` drops the audit from the round-report line and from the director's duty roster, both in place, net 0 lines. Kept deliberately, because they are the CI gate and the script rather than the retired seat duty: the `domain:skills` lane row naming the script as the governance-execution file, the guard-index row itself, `landing-operations.md`'s `--pr N` pre-ready run, `lanes/skills.md`'s `--test` run, `state-machine.md`'s generator-artifact `--test` rule, and both `platform-readings.md` behaviour readings. `scripts/pm/check-governed-merges.mjs` and its CI self-test are untouched. Claude-Session: https://claude.ai/code/session_012GcsUbuqFGBibkEDMRC1eE Co-authored-by: Claude <noreply@anthropic.com>
…er's ruling Maintainer, live PM chat with the director seat, verbatim and untranslated: 「205 否,天花板抬到 819」 — the second clause is the ceiling ruling. Recorded by the director on #19457, comment 5754521737. - `scripts/pm/check-skill-line-ratchet.mjs`: the CEILINGS entry for `.claude/skills/pm-dispatch/SKILL.md` goes 813 to 819, with the sentence quoted above it in the shape of the two ORDINARY ruled raises already on that entry — what the six lines buy, why they could not be paid in place (measured across three rounds, 9 to 8 to 6), and the note that SKILL.md is not a CROSS_FILE_MOVES destination so no `ruledRaises` record applies. - `references/lanes/skills.md` loses its remaining charter bullet that ordered the retired governed-merge review duty, under the same maintainer directive that retired it: 「受管合并审计 以后不需要了,浪费时间。」 The file goes 33 to 32 lines. Nothing in `scripts/pm/check-governed-merges.mjs` or its CI self-test is touched — the script and the post-merge record it produces both stay. `pnpm check:pm-skill-ratchet` now exits 0: check-skill-line-ratchet: .claude/skills/pm-dispatch/SKILL.md is 819 lines (ceiling 819; headroom 0). Neither `lanes/skills.md` (32, ceiling 33) nor `lanes/director.md` (63, ceiling 72) has its ceiling lowered: the gate prints both green with headroom and asks for neither, the same verdict it already prints for `dogfood-verification`. Claude-Session: https://claude.ai/code/session_012GcsUbuqFGBibkEDMRC1eE Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewServed-tier: Isolated at-tier reviewer; reviewed 2026-09-21T03:03Z. Merge-base ① Derived judgments1. Fidelity to the ruling — RIGHT. Each edit's landed text against the card's edit text, no more and no less:
2. Merge with main — RIGHT. #19459's three lines are at SKILL.md:368–370: the four-segment 3. Ceiling raise — RIGHT. 4. 5. Byte hygiene and register — RIGHT. 65 added lines measured off the three-dot diff: every added prose line in 6. Merge faithfulness — RIGHT. 7. Gates and CI — RIGHT. 40 of 41 exit 0 on the first pass; the one non-zero is the prerequisite reading below, re-run to 0, so the measured standing is 41 of 41 green (
② Semver levelNone — no released package is touched (0 paths under ③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
|
Provenance — director seat, summon #25 ( Landing: the maintainer's hand (item 8 of the ruling record, 「你会派发处理章程卡吧,然后合并之后通知分诊」) — ⛔ this seat does not flip it ready, queue it or arm auto-merge. Two seat-side readings from the review, neither blocking the hand-merge: Generated by Claude Code |
…nance instead of a liveness test; the reader accepts it and C9 keeps one red (objectstack-ai#19502) Fixes objectstack-ai#19240 Clause-②: yes `Clause-②: yes` — the claim reader's accept set widens (a cross-login `Release:` carrying provenance now retracts) and C9's judged set narrows to a bare cross-login `Claim:`; a `.claude/**` surface ⇒ Tier S, the seat lands it on its `## Contract review` PASS + `--pair` 0. This PR stays draft. ## What lands — ruling 5754797404, shape A, executed as ruled **The claim HANDOVER protocol.** A card whose claimant is unreachable (token exhausted, session ended, identity retired) is taken over by a new session in ONE comment, and the claim reader accepts that comment — no liveness heuristic anywhere: the human's word, copied with provenance, is the permission. | # | Surface | Change | Net lines | |---|---|---|---| | 1 | `scripts/pm/check-clause2-carriers.mjs` | `claimRetractions` gains the HANDOVER arm; `CLAIM_RETRACTION_RULE`, `CLAIM_HANDOVER_RULE`, `CLAIM_HANDOVER_REMEDY` rewritten; C9 keeps one red and lists refused handover attempts; self-tests both sides (1075 → 1091 cases) | +174 / −54 = **+120** (the claim's budget, exactly) | | 2 | `.claude/skills/pm-dispatch/SKILL.md` | :177 · :472 · :492 aligned in place; the nine liveness-heuristic bullets (:493–:501 at base) replaced by five handover bullets | 813 → **809** (net −4; ceiling 813, headroom 4) | | 3 | `.claude/skills/pm-dispatch/references/core-rules.md` | the two twins (:110, :111) rewritten in place | 151 → **151** (net 0) | | 4 | `.claude/agents/os-dev.md` | :94 in place: every compilable step is pushed; a handover reads the remote branch's last sha | 403 → **403** (net 0) | | 5 | `scripts/pm/check-half-states.mjs` | **untouched** — measured: `grep -n 'author !== '` → 0 hits; its `Release:` readers (H47 `latestMarkedComment` / `releaseAnswersClaim`) compare comment ORDER, never authors, so it carries no copy of the retraction rule and imports nothing from the clause-② reader | 0 | Base `32b5831`, `origin/main` merged once at `d00692f` (PR objectstack-ai#19462 had not landed at 2026-09-21T04:1xZ — SKILL.md ceiling stays 813, no region overlap). Every line ≤ 120 bytes; `check:pm-skill-ratchet`, `check:pm-skill-id-lint`, `check:pm-governed-prose`, `check:agent-model-declared`, `check:nul-bytes` all exit 0 on the edited files. ## 1. The reader ### The HANDOVER arm of `claimRetractions` (the one accept-set widening) A `Release:` comment by a **different login** retracts an earlier claim when, and only when: - (a) its `Release:` **line** (the first line of the body that `markerMatches(RELEASE_COMMENT_MARKER, line)` reads — the sibling's ONE reading, applied per line, so `**Release:**` and `` `Release:` `` read and `- Release:` does not) names the retracted claim's **comment id** (digit-bounded) **and** its **session id** (token-bounded; the claim's `Session:` line first, else the first `session_…` token in the claim body — a claim with none cannot be named, fail closed); - (b) the comment carries the three provenance fields of SKILL.md's 出处三件 line 「代执行他人指令的关闭、摘标、回收认领,评论带出处三件:谁的指令、原话、在哪说。」, each with a **non-empty** value. Missing any one piece ⇒ NOT a retraction, state unchanged. ⛔ No liveness test: the earlier claimant's later comments are irrelevant (pinned). Same-login retractions: byte-for-byte the old behaviour (no id, no session, no provenance needed). **Pinned key spellings** (`HANDOVER_PROVENANCE_KEYS = ['谁的指令', '原话', '在哪说']`, exactly the :149 vocabulary — ⛔ no fourth key, ⛔ no synonym). A field is: the key · optional decoration (`*`, `_`, backticks) · an optional parenthetical `(…)` / `(…)` · a colon (ASCII `:` or fullwidth `:` — indistinguishable on the page, pinned equal) · the value = the rest of that line up to the next key, or, when that is blank, the blockquote (`>` lines) under the key. Whitespace, `>`, decoration and separator punctuation alone are an EMPTY value (pinned per key). The two live specimens, both replayed verbatim in the self-test: - 5754797404 (inline paragraph): `**出处三件** — **谁的指令**:维护者,在本席(…)会话内的三个真实用户轮次。**在哪说**:本席会话聊天,在评论 5754717208(2026-09-21T02:44Z)之后、本条之前的连续三轮。**原话**(逐字,⛔ 未翻译、未润色):` followed by the blockquoted turns. - 5754717208 (line per field): `**出处三件**——` / `**谁的指令**:维护者(本仓 maintainer,…)。` / `**在哪说**:本会话聊天内,…。` / `**原话**(逐字,⛔ 未翻译、未润色):` followed by the blockquoted turns. ### C9 keeps exactly one red `claimHandovers` is unchanged in its walk: it reads the LIVE claims through the same `claimRetractions` map, so a handover comment (① provenance `Release:` naming the holder's claim + ③ new `Claim:` with `Branch:`/`Clause-②:` in the SAME comment) leaves one author holding ⇒ no row, no note, and the new `Claim:` is the governing claim on the `--pair` path (a comment is not later than itself, so it cannot retract its own claim — pinned). The one red left: a cross-login `Claim:` with NO `Release:` at all for the earlier claim — a real claim-jump. `CROSS_AUTHOR_CLAIM_ROW_EFFECTIVE_AT` stays; its gating now applies to that narrowed red only (it is read at the same place as before). **Loud refusal, not silent red:** a cross-login `Release:` that TRIED to hand over a live claim (names its id or session id, or carries a provenance field) and did not is listed in the C9 sentence with its reason — `missing 在哪说`, `the comment id is not on its `Release:` line`, `the session id is not on its `Release:` line`, `the claim carries no session id to name`. A bare `Release:` by another login (a seat releasing its own claim) is not an attempt and is not listed — the first draft listed those and the `--pair 19373` row named os-steve's own two releases as "refused handovers" of os-bill's claim, which was noise; narrowed. **The remedy sentence** (`CLAIM_HANDOVER_REMEDY`) prescribes the four-item handover comment and prints SKILL.md's handover sentence **verbatim** (`CLAIM_HANDOVER_SENTENCE_LINES` = the five 认领 bullets, byte for byte), citing the 出处三件 line as its source. The old remedy words 「the HOLDER posts `Release:` … the TAKER posts nothing until then … ⛔ never a `Release:` on the holder's behalf」 are gone; ② (assignee swap) and ④ (the sha record) are stated as the seat's acts, unread by the reader. ### Self-tests (beside the existing retraction and C9 cases, ⛔ not at `selfTest()`'s tail; floor unchanged) Retraction battery: ⭐ a cross-login provenance `Release:` naming id + session is accepted — state `declared`, the handover's own `Claim:` governs, the record says "a DIFFERENT login … HANDOVER" · ⛔ missing any one field, or a key with an empty value ⇒ refused, one case per key each way, the missing key named · ⛔ id without session / session without id / both in prose under a bare `Release:` line / the three fields with no `Release:` line at all ⇒ refused · ⭐ NO liveness test: the earlier claimant commenting after the handover changes nothing · ⭐ both live specimens' spellings read, and a fullwidth colon reads as the ASCII one · ⛔ same-login `Release:` still needs nothing (arm untouched); a claim with no session id cannot be handed over · ⛔ item ④ absent still retracts (the seat's act, not the reader's gate) · the printed rule names both arms, the three keys, the source line and the absent liveness test. C9 battery: ⭐ the handover comment clears C9 (no row, no note) · the handover's `Claim:` is the governing claim on `--pair` (branch, declaration) and is not self-retracted · ⛔ the same comment missing any one field ⇒ still C9 JUDGED, the row names the refused release and the missing key · ⛔ the ONE red kept: a cross-login `Claim:` with no `Release:` at all · ⛔ a handover naming only one of two live claims leaves the other standing · the remedy is SKILL.md's handover sentence verbatim, with the 出处三件 source line and 让先到者 for a yield · each sentence line is one SKILL.md bullet by shape (≤ 120 bytes, no bullet, no issue id). ## 2. Before / after — every changed instruction line `.claude/skills/pm-dispatch/SKILL.md` | line (base → now) | before | after | |---|---|---| | :177 → :177 | `- dev 自己死了不等于维护者中止:子代理消失是正常死法,走死认领回收。` | `- dev 自己死了不等于维护者中止:子代理消失是正常死法,走接管(见认领节)。` | | :472 → :472 | `- 共享身份下 assignee 只答有无认领;身份只认正文 session ID,⛔ 不认作者字段。` | `- 共享身份下 assignee 只答有无认领;身份只认正文 session ID,⛔ 不认作者字段,接管同此。` | | :474 | `- 释放是显式动作:让卡离手者同笔清 assignee + `Release:` 行(会话/因/去向);下一任重新认领。` | **unchanged, deliberately** — this line is the greppable source of `RELEASE_ACT_RULE` in `check-half-states.mjs` (outside this claim's surface); the handover reuses the act's two halves (② assignee + ① `Release:` line, by the taker), stated in the new bullets | | :492 → :492 | `- dev 侧早推分支,远程分支是在飞工作最硬的证据。` | `- dev 每个可编译小步即 push:容器随会话回收,未 push 的树救不回,可交接的只有远程分支。` | | :493–:501 → :493–:497 | the nine liveness bullets (listed in §3) | `- 认领人不可达(token 耗尽/会话结束/身份退役)⇒ 接管:一条评论四件齐,⛔ 不判死活。` / `- ① 跨账号 `Release:` 点名被撤认领的 id 与 session ID,带出处三件(谁的指令/原话/在哪说)。` / `- ② assignee 同笔换人(`--unassign 旧 --assign 新`);③ 新 `Claim:`:新 session、续用分支与远程 sha。` / `- ④ 交接记录:旧分支最后已 push 的 sha + 一句状态;读者只验①③形状,缺一件即非撤销。` / `- C9 只剩一种红:无任何 `Release:` 的跨账号 `Claim:`(真抢卡);线程上每条活认领都要点名。` | | :502 → :498 | `- 误伤活席位 ⇒ 令其追加式更正,落 PR 正文不落分支历史。` | unchanged (a mis-handed live seat still appends its correction) | `.claude/skills/pm-dispatch/references/core-rules.md` | line | before | after | |---|---|---| | :110 | `- 更早的他会话认领即让行并交出已诊断的一切;认领逾一天且无合并证据即疑死。` | `- 更早的他会话认领即让行并交出已诊断的一切;认领人不可达即接管,⛔ 不判死活。` | | :111 | `- dev 自死不等于维护者中止,需显式信号;回收前先救工作树,有提交的活分支 ⛔ 永不回收。` | `- dev 自死不等于维护者中止,需显式信号;接管一条评论四件齐,只救已 push 的分支。` | `.claude/agents/os-dev.md` | line | before | after | |---|---|---| | :94 | ` - 有可展示内容即 commit、push 并开 draft PR,不等验证结束;验证结果到达即写进报告。` | ` - 每个可编译小步即 commit + push;有可展示内容即开 draft PR;接管只认远程分支最后 sha。` | The dropped tail 「验证结果到达即写进报告」 survives at os-dev.md :95 (「未读到的判决写 NOT MEASURED」) and :311 (「报告在本地验证走完时交付」). ## 3. SKILL.md deletion list — each retired line's surviving home | retired line (base :493–:501) | surviving home | |---|---| | `死认领回收:认领 >~24h ⇒ 疑死;判死主腿 = 搜引用本卡的 PR、读其 merged/merged_at。` | **retired outright** — the ruling replaces liveness judgement with the human's word (:493 「⛔ 不判死活」) | | `⛔ 判死不读 closes-list;承诺分支缺席与提交扫描失效只能支持判死、永不单独确立。` | retired outright (no liveness judgement exists to bound) | | `零引用 PR ⇒ 停下发问,⛔ 不判什么都没落地。` | retired outright; the "ask first" half is the protocol itself — the handover IS the human's answer copied with provenance (:494) | | `回收前先救工作树:向任何派发 worktree 提交前先过存活/所有权检查。` | **retired outright** — the hard fact at :492: a remote container's worktree is reclaimed with the session; there is nothing to rescue | | `或对树最新 mtime 过明确年龄阈值;⛔ 不凭 GitHub 侧静默动手。` | retired outright (same reason); 「⛔ 不凭 GitHub 侧静默动手」 survives as the provenance requirement (:494) | | `过栏后,派发 worktree 的未提交改动先 WIP commit 到派发分支并 push,sha 记进回收评论。` | :492 (every compilable step is pushed by the dev — the WIP-rescue is moved to the writer side, before the cut) + :496 ④ (the last pushed sha in the handover record) | | `WIP commit 标 INCOMPLETE AND UNREVIEWED;续派者 diff 它,⛔ 不无审续建。` | :496 ④ 「一句状态」 — the taker records the branch's state and continues from the remote sha; "diff before continuing" is the taker's ordinary care under 「读者只验①③形状」 | | `WIP 信息只写观察到的(脏路径/行数/sha),⛔ 不写席位行为的现在时断言。` | :496 ④ (sha + one status sentence) — no WIP commit is written by anyone but the dev itself | | `再评论询问,静默一窗后释放回队(`Release:` 行载因);有带提交活分支的认领永不回收。` | :494 ① (the `Release:` line, now with provenance instead of a silence window) + :497 (every live claim named) — 「有带提交活分支的认领永不回收」 is retired: a pushed branch is precisely what the handover continues (:495 ③) | ## 4. PM mechanism assumptions — verified, one refuted 1. ✓ At `5e7d83c` = `32b5831` (no diff on the surface between them): `CLAIM_RETRACTION_RULE` :1731 stated "⛔ never a DIFFERENT author's line", `claimRetractions` skipped every candidate whose author differs (:1778 `candidate.author === null || candidate.author !== claim.author`), and `claimHandovers` judged cross-login claims after `CROSS_AUTHOR_CLAIM_ROW_EFFECTIVE_AT` (:2073, `2026-09-19T03:45Z`). 2. ✓ Reproduced before the change (2026-09-21T03:5xZ, `PM_SWEEP_REPO=objectstack-ai/objectstack`): `--pair 19373` → exit 4, `✗ C9 — card objectstack-ai#17518 (delivering open PR objectstack-ai#19373) — 2 authors hold LIVE claim comments … `os-bill`'s 5646971772 at 2026-09-12T15:54:12Z is the claim that stood; `os-litant`'s 5749581295 at 2026-09-20T11:43:41Z took the card from `os-bill` (dated AFTER the effective instant 2026-09-19T03:45Z — JUDGED)`; `--pair 19335` → exit 4, `✗ C9 — card objectstack-ai#18670 (delivering open PR objectstack-ai#19335) — 3 authors … `os-litant`'s 5717305863 … stood; `os-steve`'s 5736537462 … (listed, informational); `os-bill`'s 5749165780 at 2026-09-20T10:14:08Z took the card from `os-steve` (… JUDGED)`. After the change both STILL exit 4 (same rows, the remedy now printing the four-item comment) — as predicted, until the seats post the handover comments below. 3. ✓ SKILL.md :149 reads exactly 「代执行他人指令的关闭、摘标、回收认领,评论带出处三件:谁的指令、原话、在哪说。」 (ASCII punctuation); the reader now reads exactly those three fields and quotes the line unbroken (`HANDOVER_PROVENANCE_SOURCE`). 4. Tier S — `node scripts/pm/check-governed-merges.mjs --pr N` is run once the PR number exists; the result is in the report. The PR stays draft. 5. **REFUTED — ruling item ② spelling.** `label-write --clear-assignees --assign NEW` is refused by the tool: `--clear-assignees cannot be combined with --assign/--unassign` (`scripts/pm/label-write.mjs` :417–:419). The one-write assignee swap is `node scripts/pm/label-write.mjs --repo objectstack-ai/objectstack --issue N --unassign OLD_LOGIN --assign NEW_LOGIN` (`computeAssigneeTarget`: target = current − unassign + assign, one write, read back). SKILL.md :495 and the handover comments below use that spelling. ## 5. The handover comments the seats post (verbatim — ⛔ not posted by this PR, ⛔ nothing written on objectstack-ai#17518 / objectstack-ai#18670 / PR objectstack-ai#19373 / PR objectstack-ai#19335 here) Both were **simulated offline against the live threads** (the REST rows of each card plus the drafted comment appended): C9 state `null` (clear), pool = the handover comment, governing branch = the continued branch, declaration `declared` / `yes`, C8 = 0; controls — the same comment without 在哪说 ⇒ C9 judged `true`; the same comment with the session id blanked on the `Release:` line ⇒ C9 judged `true`. Placeholders in CAPITALS are the poster's to fill (its own session id / login, the UTC stamp). The 原话 / 在哪说 values copy the maintainer's words that adopted this protocol for exactly these two PRs (5754717208 § the maintainer's turns; 5754797404 「同意」, which names PR objectstack-ai#19373 and PR objectstack-ai#19335 as the two the ruling unblocks); a fresher instruction naming the card directly is a better value, if the seat has one. ### objectstack-ai#17518 (PR objectstack-ai#19373) — posted by the `domain:spec#1` seat (`os-litant`, the taker already holding claim 5749581295) ```text Release: handover of claim 5646971772 (`session_01MkQhmuuJAVDjmeWNixwDDH`, `os-bill`, branch `claude/issue-17518-assembled-body-json-schema`) and of this seat's own claim 5749581295 (`session_01LvwGppdonww4zGLWZo5rho`) · 因: the earlier claimant is a dev subagent session that ended on 2026-09-12 and cannot post its own `Release:`; the taker has delivered the whole diff on PR objectstack-ai#19373 · 去向: the `Claim:` below — same seat, same branch 谁的指令: the maintainer (objectstack-ai#19240 — ruling 5754797404, recorded by the `domain:skills` seat 2 at 2026-09-21T02:57Z; the maintainer's words carried in 5754717208 by the `domain:spec` seat 2) 原话: 「某个 agent 开发了一半没有token了,就是需要新的 agent 重新认领,而且重新认领的时候 是不是不issue 的人员也要跟着改。」「把它从「补一种 Release: 拼写」升级成 「接管协议」」「同意」 在哪说: objectstack-ai#19240 comments 5754717208 (2026-09-21T02:44Z, the maintainer's verbatim turns in the `domain:spec` seat 2's session) and 5754797404 (2026-09-21T02:57Z, 「同意」 on shape A in the `domain:skills` seat 2's session) Assignee: `os-project-manager` → `os-litant`, in the same label write as this comment: `node scripts/pm/label-write.mjs --repo objectstack-ai/objectstack --issue 17518 --unassign os-project-manager --assign os-litant` Claim: `domain:spec` seat 1 takes over objectstack-ai#17518 under SKILL.md's handover rule (认领 section), at DATE_TIME_UTC Session: `session_01LvwGppdonww4zGLWZo5rho` Branch: `claude/issue-17518-assembled-package-body-inert-json` (continued at remote sha `aac764cc36113b4e52820c1695715f000ccbe1b4`, the head of PR objectstack-ai#19373) Clause-②: yes Handover: the released claim's branch `claude/issue-17518-assembled-body-json-schema` — last pushed sha `ed8dea17bd510100320ab42dbac6ec2a78e99deb` (read from origin at 2026-09-21); status: superseded — the whole diff was re-delivered on PR objectstack-ai#19373 at `aac764c` (checks green, `## Contract review` pending), nothing from the old branch is carried. ``` Why the seat's own 5749581295 is named too: the reader would otherwise carry TWO live `Claim:` comments by `os-litant` (C8). Named on the same `Release:` line it is retracted by the same-login arm, and the fresh `Claim:` in this comment is the only one standing. If the posting session differs from `session_01LvwGppdonww4zGLWZo5rho`, the `Session:` line carries the new one. ### objectstack-ai#18670 (PR objectstack-ai#19335) — posted by the live `domain:spec` seat (POSTER_LOGIN / POSTER_SESSION_ID; the taker of record, `session_01JbZnqu8bt6YqfJsr9vaFb3`, was retired at 2026-09-20T23:34Z) ```text Release: handover of claims 5717305863 (`session_01LvwGppdonww4zGLWZo5rho`, `os-litant`, branch `claude/issue-18670-refinement-projection-census`), 5736537462 (`session_01AmH9bKvGoLjiY86Q4Z3og2`, `os-steve`, branch `claude/issue-18670-banned-keys-projection`) and 5749165780 (`session_01JbZnqu8bt6YqfJsr9vaFb3`, `os-bill`, branch `claude/issue-18670-propertynames-not-pattern-arm`) · 因: the first two claims' work is merged (PR objectstack-ai#18729, PR objectstack-ai#19137; both branches absent on origin), and the third claim's session was retired at 2026-09-20T23:34Z with its PR objectstack-ai#19335 reviewed and green — none of the three can post its own `Release:` · 去向: the `Claim:` below 谁的指令: the maintainer (objectstack-ai#19240 — ruling 5754797404, recorded by the `domain:skills` seat 2 at 2026-09-21T02:57Z; the maintainer's words carried in 5754717208 by the `domain:spec` seat 2) 原话: 「某个 agent 开发了一半没有token了,就是需要新的 agent 重新认领,而且重新认领的时候 是不是不issue 的人员也要跟着改。」「把它从「补一种 Release: 拼写」升级成 「接管协议」」「同意」 在哪说: objectstack-ai#19240 comments 5754717208 (2026-09-21T02:44Z, the maintainer's verbatim turns in the `domain:spec` seat 2's session) and 5754797404 (2026-09-21T02:57Z, 「同意」 on shape A in the `domain:skills` seat 2's session) Assignee: `os-bill` → POSTER_LOGIN, in the same label write as this comment: `node scripts/pm/label-write.mjs --repo objectstack-ai/objectstack --issue 18670 --unassign os-bill --assign POSTER_LOGIN` (a no-op when the poster IS `os-bill`; `pm:blocked` → `pm:dispatched` in that same write once the reader has landed) Claim: `domain:spec` seat takes over objectstack-ai#18670 under SKILL.md's handover rule (认领 section), at DATE_TIME_UTC Session: `POSTER_SESSION_ID` Branch: `claude/issue-18670-propertynames-not-pattern-arm` (continued at remote sha `1dfe2f40bce77270758d9b31b01dd8d46875a290`, the head of PR objectstack-ai#19335) Clause-②: yes Handover: branch `claude/issue-18670-propertynames-not-pattern-arm` — last pushed sha `1dfe2f40bce77270758d9b31b01dd8d46875a290` (read from origin at 2026-09-21); status: `## Contract review` PASS recorded at 5749728565 on this head, both carriers stripped, checks green — nothing left to build, the landing is the only step. The two older branches are absent on origin (their work merged as PR objectstack-ai#18729 / PR objectstack-ai#19137). ``` Why all three claims are named: C9 walks every LIVE claim; naming only 5749165780 would leave `os-litant` → `os-steve` → NEW as two hand-overs, the last dated after the instant — still red. The row prints exactly the ids to name (:497 「线程上每条活认领都要点名」). ## 6. Four-axis analysis ### 「No liveness test」 (ruling; 5754717208 §4's 「点名的是活认领 ⇒ 拒」 not kept) - **实际业务需求** — measured: the three specimens (objectstack-ai#17518 / PR objectstack-ai#19373; objectstack-ai#18670 / PR objectstack-ai#19335; objectui#9370) are all cases where the human already knew the claimant was gone and the machine could not: a subagent session that ended 2026-09-12, a seat session retired at 23:34Z, a retired identity. In every one the holder's silence was total, so a liveness heuristic (>24h, later comments, PR search, mtime) would have said "dead" only by luck of thresholds, and a holder that posts one late comment would have flipped a correct takeover into a refusal. The maintainer's words: 「这种情况通常都是人类口头交代的」 — the decision is already taken by a human; the reader's job is to verify the copy, not to re-decide. - **项目长远合理性** — a reader that verifies provenance is a pure function of the thread (contract-first, no workaround); a liveness heuristic is a second, contradictable oracle beside the human's word and needs its own thresholds, exceptions and reconciliation windows (which is what :493–:501 had become: nine lines of them). Long-term cost of the chosen option: a bad handover is possible on a bad instruction — but it is auditable (谁的指令 / 原话 / 在哪说 are on the card) and repairable (:498 「误伤活席位 ⇒ 令其追加式更正」). - **防 AI 写错** — the accept set is closed and mechanical: three named keys, an id + session on ONE line, fail closed on any gap, and the refusal names the missing piece. Nothing to guess; an AI seat that half-writes the comment is told which field. A liveness test would be the opposite — a tolerance rule ("probably dead") that hides a wrong takeover behind a green. - **创业阶段不扩散需求** — the ruling's own reason: 「我们系统开发了太多无用的门禁,反而在浪费时间」. Nine heuristic lines retired, five protocol lines added, no staged transition (the heuristics are gone at once — 「短期不考虑渐进」). - Recommendation held: no liveness test, per the ruling. ### 「C9 keeps one red」 (a bare cross-login `Claim:` with no `Release:` at all) - **实际业务需求** — the red exists for the measured claim-jumps (objectstack-ai#17852's two seats eight hours apart, objectstack-ai#15811's silent assignee move); those are exactly the shape left red. The two finished PRs it blocked were handovers, not jumps — they had no channel to say so; now they have one comment. - **项目长远合理性** — one state, one row, one repair (the handover comment) — no widening of C8, no second selector; the effective instant stays as history and still gates the narrowed red only. - **防 AI 写错** — deleting C9 would let any later `Claim:` silently govern (the pre-objectstack-ai#18862 SUPERSEDED exit-0 reading); keeping the red but printing the four-item comment as the remedy makes the correct act the shortest path. A refused attempt is listed with its reason instead of a bare "2 authors hold live claims". - **创业阶段不扩散需求** — no new gate, no new label, no new tool: the remedy is a comment in the spelling the protocol already has; the only added code path is the provenance read. - Alternative weighed and refused: retiring C9 entirely (「太多无用的门禁」) — refused because the ruling itself keeps 「真正的抢卡」 red, and a jump is a real, measured, silent failure. ## 7. Tests and gates (head `7a66ffe`; every exit captured before any pipe) - `node scripts/pm/check-clause2-carriers.mjs --self-test` → exit 0, **1091 cases pass** (1075 at `origin/main`, run from a temp copy in the same tree; the roster floor unchanged; both new case groups sit inside their existing batteries). - `--pair 19373` / `--pair 19335` → exit 4 before AND after (rows quoted in §4.2); after the change each row ends with the four-item remedy (`grep -c 认领人不可达` = 1 per log). - Offline simulation of the two handover comments (§5): C9 clear, governing claim = the handover, declaration `declared/yes`; controls red. - Derived union (`node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack`, 48 commands, derived from the tree at `693afd7` after the `origin/main` merge and re-run at `7a66ffe`): all **48 of 48** commands exit 0 (run 2026-09-21T03:56Z–04:15Z, sequential, each exit captured before any pipe; the list reconciled with `--ran`); the slowest, `pnpm check:pm-dispatch-gates`, ran its full 1883-case battery green at this head. - `pnpm --filter @objectstack/lint run check:doc-formula-expressions` first answered exit 3 (PREREQUISITE NOT MET: `@objectstack/formula` / `@objectstack/lint` not built — NOT a finding); after `pnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lint` under `os-verify-lock.sh` (VERDICT command-exit 0, 203 s) it answers exit 0. - `pnpm check:pm-dispatch-gates` (845 s on this box) red once on an EARLIER draft: its governed-read census found a `readFileSync` of SKILL.md in this reader's self-test (my "same words" pin). Removed — see Deviations — and re-run green at the final head. ## Deviations (declared) 1. **The "ONE sentence" property is not a governed read.** A self-test pin that reads SKILL.md makes `check:pm-clause2-carriers` a derived family of SKILL.md and needs a `GOVERNED_READ_FLOOR` row in `scripts/pm/dispatch-gates.mjs` (outside this claim's surface; a gate-derivation change). Kept instead: `CLAIM_HANDOVER_SENTENCE_LINES` (the remedy prints the five lines verbatim) + the twin rule at review + a shape pin (each line ≤ 120 bytes, no bullet, no issue id). Open question for the seat: register the read so a SKILL.md edit that breaks the sentence reds the reader (recommended; a two-line floor row). 2. **SKILL.md ceiling not lowered** (813 → could be 809): `check-skill-line-ratchet.mjs` is outside the surface; headroom 4 is reported, the seat lowers it if wanted. 3. **:474 left byte-identical** (see §2) — the alignment the dispatch asked for is carried by the new bullets rather than by editing the line that a sibling file quotes. 4. **Ruling ② spelling corrected** (`--unassign OLD --assign NEW`), see §4.5. ## Acceptance notes (off-path; noted, not filed — ⛔ no card filed by this dev) - `scripts/pm/check-half-states.mjs` H47 leg (b) sentence still quotes 「释放回队(`Release:` 行载因)」 as "the dead-claim route" — that SKILL.md line is retired here, so the quotation is stale prose in a remedy sentence (a doc nit, not a defect; carrier: the `domain:skills` seat on its next half-states touch). - `references/platform-readings.md` :391 「处置 = 死认领回收加 worktree 抢救,⛔ 不重核前提、不升级」 names the retired route (a host-signal disposition line; outside this claim's surface — the seat's twin-rule follow-up, one line: 「处置 = 接管(认领节),⛔ 不重核前提、不升级」). - `check-clause2-carriers.mjs`'s C9 docblock still carries the objectstack-ai#18862 ruling history verbatim (「the holder posts `Release:`; the taker posts nothing until then」 as the ruling's quoted words) — kept as history, the new paragraph below it states the change; no action. - `.claude/skills/pm-dispatch/SKILL.md` :272 「维护者强制接管令 … ⛔ 不取在飞卡,由原认领者跟完」 is the seat-level forced takeover (a blanket order) and is not contradicted by a per-card handover on a named instruction; left as is. ## 维护者速读(草稿) **改了什么**:把「死认领回收」换成「接管协议」。一个 agent 做到一半没 token 了,新会话在**一条评论**里接管:① 跨账号 `Release:` 点名旧认领的评论 id 与 session ID,并带出处三件(谁的指令 / 原话 / 在哪说);② assignee 同笔换人;③ 新 `Claim:`(续用远程分支与 sha);④ 一句交接状态。认领读者(`check-clause2-carriers.mjs`)按形状接受①③,不再判死活;C9 只剩「没有任何 `Release:` 的跨账号抢卡」一种红。SKILL.md 删掉九行判死启发式,换成五行接管规则;os-dev.md 把「早推分支」提为硬要求(每个可编译小步即 push)。 **为什么改**:两张已复核完毕的成品 PR(objectstack-ai#19373、objectstack-ai#19335)今天落不了地,只因为旧认领人已经不在、没人能替它写 `Release:`;而「代执行他人指令要带出处三件」这条规矩早就在 SKILL.md 里,只是读者不读。您的原话:「这种情况通常都是人类口头交代的……我们系统开发了太多无用的门禁」。 **风险与代价(含回滚)**:风险是一条编造出处的接管评论会被读者接受——但出处三件留在卡上可审,误伤活席位按既有规则追加更正。代价是读者多一条判形状的分支(+120 行,含自测)。回滚 = revert 本 PR,一次 revert 即回到判死启发式与旧 C9。 **席位意见**:(席位填写) **你要做的**:本 PR 是受管面(`.claude/**`),由席位达档复核后落地,不需要您动手;落地后 spec 席按正文第 5 节的两条评论接管 objectstack-ai#17518 与 objectstack-ai#18670,两张 PR 即可入队。若您希望读者对「SKILL.md 与读者同句」做机械钉死(而非复核时人工核对),点一下头,席位在 `dispatch-gates.mjs` 登记一条 governed read 即可。 --- _Generated by [Claude Code](https://claude.ai/code/session_017ETYWqMQD4qMtZzAGovWNi)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
…路」 section as an ordered list of feature points, cross-layer features as parent + per-layer sub-issues, domain:* retreats to file ownership (objectstack-ai#19483) (objectstack-ai#19488) Fixes objectstack-ai#19483 Clause-②: no The feature axis lands in the three steps the card names: `area:*` as the planning axis, the North Star's road section as an ordered list of feature points, and `domain:*` retreating to file ownership. ## The maintainer's words this implements (verbatim, chat 2026-09-21) 「关于任务的车道,我觉得现在是有问题的,应该是按照功能点划分车道我更容易判断优先级和安排,而且一个功能点应该覆盖从协议开始到运行时到前端。不应该按照我们的文件夹划分。」 / 「或者是否建议再加一组label?」 / 「有了功能轴之后我应该怎么安排任务?」 / 「包括我们应该划分哪些功能轴」 / 「把北极星的「路」那一节改成可读的功能点顺序 立」. ## Tier and landing Tier H (`docs/NORTH-STAR.md` and `.claude/**` in one diff, one path hit makes the whole PR Tier H). The maintainer merges this by hand. Draft, no ready flip, no auto-merge, no labels. ✅ **The eleven-value axis list is ruled.** The maintainer confirmed it on the card with ONE amendment, verbatim (chat, 2026-09-21): 「19483 api-integration 简化成 api 其他同意。」 — recorded as the card's ruling comment 5754985448. Round 2 of this PR carries the rename: the value is `area:api` in all four places it is spelled (the label row, the `axis` in api-backend.json and integration-system.json, and the three roadmap lines), its customer capability unchanged. The other three open questions were ruled A in the same comment: platform-core stays file-level `devpath`, the label objects stay in objectstack + objectui, and the four readers keep riding in the glossary row with no ceiling raise. ## Step 1 — `area:*` - `scripts/pm/ensure-pm-labels.sh` gains eleven rows, in **two** repos (objectstack + objectui), not the five-repo loop: a feature point spans 协议 → 运行时 → 前端, which is those two. cloud is parked (北极星「现在不做」), objectos is the docs/site repo, hotcrm is the exemplar app whose platform gaps are filed upstream. The reasoning is written into the file beside the rows; widening the loop is a vocabulary decision, not a maintenance edit. `check:pm-label-desc-cap` reads 38 descriptions (was 27), longest 100 characters. - SKILL.md 〈状态模型〉 gains the `area:*` glossary row with the card's text. - The four named readers ride **in that row** rather than on their own line under 「一个标签存在当且仅当有具名读者」. That is the one deviation from the card's letter, and it is a ratchet consequence, measured below — the same fold the objectstack-ai#19457 ratchet comment records for `tooling`. The row is exempt from the 120-byte line rule and the readers are still named and greppable: `git grep -n 'area:' -- .claude/skills/pm-dispatch/SKILL.md` returns the row with all four. - All fifteen `docs/qa/platform-checklist/areas/*.json` carry a top-level `axis`, item ids untouched. **No schema extension was needed**: the gate has no unknown-top-level-key rule, and `pnpm check:platform-checklist` is green on the added key (15 areas, 264 items, exit 0). - One mapping cannot be expressed with a top-level field: the card sends platform-core's **docs-portal items** (`platform-core.docs-audience-gate`, `platform-core.docs-portal-render`, both P1) to `studio` while the rest of that area is `devpath`. The file carries `devpath`; a per-item axis is out of this card's scope. Flagged for the maintainer under Open questions on the card. ## The roadmap section, rewritten in round 3 The maintainer read the first version and said, verbatim (chat, 2026-09-21): 「19488 路上的功能点写的很奇怪,真的是平台总体的功能清单吗?怎么感觉是几个issue」. He was right: it was one card plus the checklist's currently-failing P0 items — a to-do list, not the platform's feature map. Round 3 replaces that one section; everything else in this PR is as reviewed. What it is now: six blocks, one per step of the road the North Star already measures, and inside each block one line per feature point at capability level — a customer-visible capability that runs from the protocol through the runtime to the frontend. The end-user capabilities (records, access, workflow, reports, identity, files, i18n) sit at the step where the road first needs them, which is where the app is first run and seen. The 路步 column is gone because the block position is the step, the docs-authoring feature keeps its 「清单项待写」 slot at step ①, and the page's own rules hold: no counts, no pass/fail status, no new headings, and the ledger is not copied here. **The completeness claim is mechanical, not editorial.** The feature points are derived by grouping every item in `docs/qa/platform-checklist/areas/*.json` so that each item belongs to exactly one line. The two totals: **264 items on disk, 264 mapped** — zero unmapped, zero double-mapped, zero ids the ledger does not have — across **76 feature points** in a **95-line** section. The per-item listing is on the card, in the round-3 `os-dev-report`. **Round 4** (one commit, `docs/NORTH-STAR.md` only, +4/−2): the round-3 at-tier review (5755471665, PASS) named one line as misdescribing its items and one placement as debatable; both fixed — the CEL formula pair (`formula-stdlib-matrix`, `formula-gates`) now has its own feature-point line and the REST construction line no longer claims it; `lifecycle-retention-sweep` (ADR-0057 retention) moved off the packaged-object line onto its own. Totals unchanged: 264 items, 264 mapped, 0 unmapped, 0 double-mapped; 78 feature points. **Round 5** (merge commit, no rebase): `origin/main` moved (objectstack-ai#19506 entered the maintainer's 插队 / 契约面卡 tiers into the 取卡全序; objectstack-ai#19502 the handover protocol) and conflicted with this PR's 取卡全序 edit in SKILL.md and core-rules.md. Both sides are the maintainer's rulings, so the merge composes them: 「取卡全序:维护者直派插队卡(出处三件)> 契约面卡(判据见 references/lanes/spec.md)> 标签序」 and 「标签序:priority:p0 > pm:blocking > 功能点位次 > target: 板上项 > p1 > p2 > p3 > 无级」, identical in both files; the tie-break 「同级先 Bug 再卡龄」 stays on SKILL.md's following line (the composed line would exceed the 120-byte cap) and core-rules.md's summary defers to it. Everything else takes main's side. Ratchet: SKILL.md 815/819 (main's own count; this PR net zero), core-rules 151/151. ## Step 3 — `domain:*` retreats to file ownership - 〈域车道〉 now says in one line that `domain:*` decides file ownership (anchoring, hot-file serial, single-claim paths) and is **not** a queue or a priority unit. - 〈候选与批次〉: the candidate order reads 「功能点位次」 — the parent's position in 「路上的功能点」 — ahead of the board and the priority ladder, and at most one feature point per axis is in flight unless the file surfaces are disjoint. - 〈分诊座位职责〉: a cross-layer feature point (two or more of spec / 运行时 / 前端) is filed as ONE parent carrying `area:*` + `pm:epic` + the checklist item's priority, plus per-layer sub-issues ordered by `Blocked-by:`. 〈Epic 子树车道〉 now names cross-layer feature points in its delegation line, which is what makes the existing epic mechanism the default for that case, and 多仓协调 规则 2 is aligned from 每仓一子单 to 逐层子单. - `references/core-rules.md` mirrors all four rules in place. - `references/lanes/*.md`: **zero edits, as a measured reading, not a skipped step.** No lane charter describes a per-domain queue as the order of work. Instrument reachability is shown by the control word: 「车道」 hits 31 times across those ten files, while the order vocabulary (队列/全序/取卡/候选顺序/排序/优先序/按域/逐域) produces exactly two hits, both about the **merge** queue (`lanes/cli.md` line 17, `lanes/ui.md` line 26). Since the card's instruction there is "delete or re-point, never add", the correct edit count is zero. ## The ratchet — paid in place, no ceiling raised `check:pm-skill-ratchet` is green with both files exactly at their ceilings: SKILL.md **813/813**, core-rules.md **151/151**, widest SKILL.md table row **342/342**. Three lines were added and three retired. Each retirement was checked for a surviving home rather than assumed: | retired from SKILL.md | where the content still lives | |---|---| | 「唯一例外 `packages/lint` 等与 spec 相交的 devx 面…」 (域车道) | the 域车道 table's own `domain:devx` row, plus `references/lanes/spec.md` 范围 (「同含围着 spec 契约转的工具链…」 / 「一般开发工具面留 devx」) | | 「座位在编以 `label:pm:seat` 索引为准,每车道…每席恰一张。」 (域车道) | 全体座位的不变量 (「一 PM 恰管一车道,一车道由一组座位管,一席一贴」) and 座位贴协议's first line; the label object's own description carries the fleet-board half | | 「sweep 与首触定级只对多车道仓,单车道仓机械三务自理。」 (分诊座位职责) | 多仓协调 carries both halves — 「多车道仓…中央分诊是 `domain:*`/type/定级的唯一生产者」 and 「机械三务 = 自扫 sweep、自打 `type`、自做 `finding` 首触定级」 | Two clauses moved rather than died: 「同级先 `Bug` 再卡龄」 moved from the order line to the line below it, and 「优先非豁免」 was dropped there because the 状态模型 `priority:p0` row states it (「⛔ 不豁免同文件串行、深度等待与认领协议」). **The exact count the card asks for.** One ruled line could not be paid: the reader list as its own bullet under 「一个标签存在当且仅当有具名读者」 needs **SKILL.md 814 against a ceiling of 813 — one line**. Everything payable was paid (three retirements), the length rule blocks folding it into that bullet (the bullet is 117 bytes and the shortest self-contained reader line is 114), and every other ceilinged file in the map stands at headroom 0, so no reference file can absorb it. ⛔ No ceiling was raised. The readers therefore ride in the byte-exempt glossary row; if the maintainer wants them as a separate rule line, the raise is 813 → 814. ## Verification - `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derives **37 families** on this diff; all 37 were run on the final head `c55c02e` with exit codes captured before any pipe, all exit 0, and `--ran` reconciles **37 derived / 37 run / 0 NOT-MEASURED / 0 UNRUN** with no stale-tree warning. - Named in the dispatch and green: `check:pm-skill-ratchet`, `check:pm-label-desc-cap`, `check:pm-widening-tells`, `check:pm-skill-id-lint`, `check:doc-authoring`, `check:platform-checklist`, `check:self-test-wired`, `check:nul-bytes`, `check:pm-governed-prose`, `check:pm-governed-merges`, `check:skill-frame-sync`. - `pnpm --filter @objectstack/lint run check:doc-formula-expressions` first exited **3 — PREREQUISITE NOT MET** (its two packages were unbuilt). That is not a finding; after `turbo run build --filter=@objectstack/formula --filter=@objectstack/lint` it exits 0, and the merged-head run above is the one recorded. - Beyond the derivation, the roster gates whose roster sits under a directory this diff touches were read rather than assumed: `check:pm-settings-deny-roster`, `check-published-list-mirrors.mjs`, `check-skills-token-ratchet.mjs` — all exit 0. - Repo-wide `pnpm lint` is not derived for these paths and is CI's run, not this PR's claim. - **Collision probe against the in-flight charter PR objectstack-ai#19462** (branch `claude/issue-19457-charter-product-only-queue`): `git merge-tree --write-tree` against its tip exits 0 with a tree and no conflict. That PR's SKILL.md lines were deliberately left untouched — its `tooling` row goes after `finding` while the `area:*` row goes after `priority:p0`, four rows away; its grading edits sit two lines above the cross-layer insert; its candidate-line edit is the 候选 line while this one rewrites 取卡全序. None of this repo's paths here is merge-driver managed. - `Check Changeset`: this diff publishes nothing — `.claude/**`, `docs/**` and `scripts/pm/**` are outside every package's `files[]`. It needs the **`skip-changeset`** label, which the seat applies (this dispatch writes no labels). ## Acceptance notes - Noted, not filed: `docs/qa/platform-checklist/areas/*.json` has no schema and no unknown-top-level-key rule, so `axis` is accepted by presence alone and a typo (`area:studo`) would pass every gate. A value check belongs with whichever card next touches the checklist gate; the carrier is named, so it is a note rather than a card. - Noted, not filed, 承接者:无 — `scripts/pm/ensure-pm-labels.sh` is create-if-missing by default, so the eleven new label objects only reach the two repos when someone with label-write credentials runs the script (a PM landing step, exactly as the file says for objectos and hotcrm). ## 维护者速读(草稿) **改了什么** — 加了一组新标签 `area:*`(十一个功能轴),给测试清单的十五个 area 文件各加了一个 `axis` 字段,在北极星的「那条路」下面加了一张「路上的功能点」表(第一条是文档编写那个功能,后面是清单上现在还开着的全部 P0 项,按路步排),并把 PM 章程里「按车道排队」的地方改成「按这张表排队」:`domain:*` 从此只管哪个席位能动哪些文件。 **为什么改** — 您的原话:按功能点划分更容易判断优先级和安排,一个功能点应该从协议一直覆盖到前端,不应该按文件夹划分。以前排队顺序是按文件夹(车道)来的,所以一个功能的三层会被拆到三个队列里各自排;现在顺序只有一份,就是北极星上的那张表,改表即改优先级,不用逐张卡改档位。 **风险与代价(含回滚)** — 一、十一个轴您已在卡上定了,只改了一个名(API 那一轴由长名简化为 `area:api`),本轮已在四处改齐:标签行、两个清单文件的 `axis`、路上的功能点三行。二、新标签只在 objectstack 与 objectui 两个仓建,理由写在脚本里;要不要也给 hotcrm,您随时可加。三、章程的行数棘轮是零余量,所以这次是「加三行、退三行」换来的,退掉的三行内容都在别处有家(PR 正文里逐条列了);还有一行实在付不出,已按卡上要求报了准确数字(要 814,天花板 813),没有抬天花板 —— 您也已裁定保持现状。四、回滚就是 revert 这个 PR,新标签对象留在 GitHub 上不影响任何东西。 **席位意见** — (留空,复核席填) **你要做的** — 手动合并这个 PR(Tier H);轴名已定,无需再确认。 --- _Generated by [Claude Code](https://claude.ai/code)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
… questions only; C5 and the patrol anchor stop blocking; at-tier review scoped to what ships and read from CI (objectstack-ai#19496) (objectstack-ai#19513) Fixes objectstack-ai#19496 Clause-②: no **Tier H — the maintainer merges this by hand.** The diff touches `AGENTS.md` and `.claude/**`, so one Tier H path makes the whole PR Tier H: no seat flips it ready, queues it, or arms auto-merge, and no agent account approves it. Authorization, verbatim and untranslated — maintainer, 2026-09-21 (ruling objectstack-ai#208 on objectstack-ai#19491): > 「19491 接受你的建议,并立刻派发处理相关任务。」 ## What lands — five charter edits, text only Nothing under `scripts/`, `.github/` or `packages/` is touched. The C5 code demotion, the patrol schedule and the CI self-test scoping are their own cards. **R1 — a non-zero `--pair` blocks landing only on rows that answer a definite question.** `SKILL.md` 〈入队与落地〉 and `references/contract-review.md` 落地前检三条: ```text - `Clause-②: yes` 认领同笔卡上挂标;开 PR 跑 `--pair N`:只确定性行红才挡请审,C5 只印读数。 - 0 = 确定性行全清;4 = 任一不成立,只确定性行红才挡落地;3 = 环境答不了 ⛔ 不作干净。 - 确定性行 = 记录在案、`Served-tier:`、双载体一致、认领形;C5 放宽 tell 只报告,归复核裁。 ``` `AGENTS.md` Prime Directive objectstack-ai#14 is where the conjunct lives — `git grep -n -- '--pair' AGENTS.md .claude` is the census (1 hit in `AGENTS.md`, 5 in `.claude`). Tier S now reads `reads 0 on its definite rows (⛔ never C5) and every check is green`; the paragraph was re-wrapped from that sentence onward and `AGENTS.md` stays at 1109 lines. **R2 — the rule line**, next to the tooling rules ruling objectstack-ai#202 B landed, in 〈分诊座位职责〉's filing classes: ```text - 只报告的仪器,报错不配 dev:猜意图的只印读数,误报席位一句推翻,⛔ 不立卡不派 dev。 ``` **R3 (charter half) — the patrol anchor stops being a precondition.** The two 〈执行座位职责〉 lines are deleted; one line replaces them, mirrored in `references/core-rules.md`: ```text SKILL.md - 半状态巡查按需跑(分诊席每日对账可调),H 行是读数不是前提;⛔ 不因锚行停派发。 core-rules.md - 半状态巡查按需跑,其 H 行是读数不是前提,⛔ 不因锚行停派发。 ``` **R5 — at-tier review: scope and shape**, in `references/contract-review.md` 〈复核归属与资格〉: ```text - 复核面 = 出货给用户或 agent 的:`content/docs/**`、`apps/docs/**`、CHANGELOG/`.changeset` 散文。 - 同含已发布 schema 与 governed 规则文本;三面皆不碰 ⇒ CI 加席位自读,⛔ 不起第二个 agent。 - 复核形状:只读 diff 与卡片,check 结论取 head 的 check-runs,⛔ 永不本地重跑派生门禁族。 ``` `Served-tier:` and the record shape are unchanged. `check-clause2-carriers --template` prints nothing that contradicts the shape: its ③ is the record's boundary-flag heading and it prescribes no local gate run, so no script edit was needed (checked; reported below as a reading, not a finding). **R6 — 〈仪器纪律〉** is a new reference, `references/instrument-discipline.md` (11 lines), with exactly one pointer line in SKILL.md 〈平台读数纪律〉, placed one line below the advisory-red rule: ```text - 仪器纪律(硬门禁面、只报告面、新增授权、工具位)见 `references/instrument-discipline.md`。 ``` The section itself: ```text - 硬门禁只答有确定答案的问题:受管登记表、队列守卫、CI 测试、复核记录在不在。 - 判意图的仪器(放宽 tell、半状态巡查)只印读数 ⛔ 不挡落地,误报由席位一句话推翻。 - 放宽 tell(C5)由 `scripts/pm/check-widening-tells.mjs` 印 file:line,归达档复核裁。 - 只报告的仪器不配 dev:⛔ 不立卡、不派 dev、不开 PR;它的在途工作只有删除。 - 新增门禁、巡查行或棘轮须在卡上引维护者原话,⛔ 无原话不新增;首行四件恒硬。 - 工具位只有一个,先花在删除上;`dispatch-gates.mjs` 冻结,只在它喂的 workflow 坏了时碰。 - 出处:维护者 2026-09-21 逐字「19491 接受你的建议,并立刻派发处理相关任务。」 ``` **Why a new file rather than `landing-operations.md`.** Every file an at-tier reader already opens for landing or gates stands at its ceiling with zero headroom — `landing-operations.md` 69/69, `true-green.md` 32/32, `review-checklist.md` 77/77 — and the section costs 11 lines, so hosting it in one of them means deleting live rules, which this card forbids. The pointer instead sits where the reader deciding what a gate reading means already is: 〈平台读数纪律〉, right after the two lines on a gate job's conclusion and an advisory red. The new file carries no `CEILINGS` row, because that row is an edit under `scripts/**` (out of scope here) and R6's own rule says a new ratchet needs the maintainer's sentence on its own card — reported below. ## The line ratchet — no ceiling raised, every added line paid in place `pnpm check:pm-skill-ratchet` exit 0. Per-file counts on head `fec2177089`, after merging `origin/main`: | file | lines | ceiling | headroom | net this PR | |:--|--:|--:|--:|--:| | `.claude/skills/pm-dispatch/SKILL.md` | 819 | 819 | 0 | 0 | | `.claude/skills/pm-dispatch/references/contract-review.md` | 60 | 60 | 0 | 0 | | `.claude/skills/pm-dispatch/references/core-rules.md` | 151 | 151 | 0 | 0 | | `AGENTS.md` | 1109 | 1109 | 0 | 0 | | `.claude/skills/pm-dispatch/references/instrument-discipline.md` | 11 | none | — | new file | What paid for the added lines — de-duplication only, no rule deleted, each surviving carrier named: - SKILL.md 〈复核〉's two 受管面两层 lines became one. The Tier H enumeration it dropped is the 〈复核〉 line three above it (governed 面统一定义), and 四件套 is stated at 路径面命中规则层 ⇒ ACCEPT 换终局四件套. - contract-review.md's 双载体同笔挂 line is stated in SKILL.md 〈入队与落地〉 (`needs:contract-review`(恒英文)由席位同笔挂:PR 一现即挂 PR;报告先到则先挂卡); its unique tail, ACCEPT 补齐 PR 侧, rides the next line. - contract-review.md's two `Implemented-by:` / `Reviewed-by:` spelling lines became one pointer at `--template`, which prints both fields verbatim — and the record-shape line three above already cites that template. - contract-review.md's standalone Tier H/S landing line left; the tier outcome now rides the 落地前检三条 line itself, so `references/lanes/director.md`'s pointer at this block still resolves, and SKILL.md 〈复核〉 carries the full two-tier rule. - `AGENTS.md`: 43 added bytes absorbed into the paragraph's own slack by re-wrapping from the edited sentence onward; no line was bought. ## Collision — both charter PRs merge clean - **PR objectstack-ai#19462** (`claude/issue-19457-charter-product-only-queue`, head `36ab00aa`) **merged into `main` during this round.** `git merge-tree --write-tree 36ab00a HEAD` was exit 0 with zero conflict markers before that, and this branch then merged `origin/main` (`48c39e00`) with no conflict. Its `tooling` label rules, its two gate-false-positive lines and its ratchet bump (SKILL.md 813 → 819) are all present on this head. - **PR objectstack-ai#19488** (`claude/issue-19483-feature-axis-charter`): the card named head `420bd091`; the branch tip is now `16418377`. `git merge-tree --write-tree 1641837 fec2177` → **exit 0**, tree `02a7323a2d779974bd035082ad954eaf4cd15a21`, zero conflict markers. Every line that PR touches is untouched here. ## Acceptance | grep | result | |:--|:--| | `git grep -n '0 才请审' .claude` | 0 hits (exit 1) | | control `git grep -n -- '--pair' .claude` | 5 hits (os-dev.md 1, SKILL.md 1, contract-review.md 2, platform-readings.md 1) | | `git grep -n '锚行未处置' .claude` | 0 hits (exit 1) | | control `git grep -n '半状态' .claude` | 24 hits across 8 files | | `git grep -n 'C5' …/references/contract-review.md` | 1 hit, naming it 只报告 | ## Gates Derived on this diff with `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` — 23 commands; the derivation also names 11 wide-population, 53 artifact-roster, 14 pending-changeset and 2 CI-valued families as outside that list, so this is not a complete account of CI. Every exit code was captured **before** any pipe (`cmd > log 2>&1; e=$?`). Reconciled with `--ran`: **23 derived, 23 run, 0 NOT-MEASURED, 0 UNRUN.** ```text node scripts/check-closing-keyword-parity.mjs :: exit 0 node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0 node scripts/check-comment-mask-corpus.mjs :: exit 0 node scripts/pm/check-governed-queue-guard.mjs --self-test :: exit 0 node scripts/pm/check-harness-current.mjs --self-test :: exit 0 pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0 pnpm check:agent-test-spelling :: exit 0 pnpm check:cross-package-test-inputs :: exit 0 pnpm check:doc-authoring :: exit 0 pnpm check:docs-audit-scope :: exit 0 pnpm check:driver-memory-census :: exit 0 pnpm check:gitlink-declared :: exit 0 pnpm check:nul-bytes :: exit 0 pnpm check:pm-expected-skips :: exit 0 pnpm check:pm-governed-merges :: exit 0 pnpm check:pm-governed-prose :: exit 0 pnpm check:pm-half-states :: exit 0 pnpm check:pm-skill-id-lint :: exit 0 pnpm check:pm-skill-ratchet :: exit 0 pnpm check:refd-timer-probe :: exit 0 pnpm check:required-contexts :: exit 0 pnpm check:skill-frame-sync :: exit 0 pnpm check:watch-hint-literal :: exit 0 ``` Three more, run because this card names them: ```text pnpm check:pm-widening-tells :: exit 0 (self-test only — 525 cases; checker health, not a verdict on this diff) node scripts/pm/check-widening-tells.mjs --declaration no --diff pr.diff :: exit 0 (a real verdict: no tell) pnpm check:pm-label-desc-cap :: exit 0 pnpm check:pm-settings-deny-roster :: exit 0 (its roster lives under .claude, which this diff is in) ``` Two gates first answered `exit 3` (PREREQUISITE NOT MET) in a fresh worktree and were re-run after `pnpm install`, and `check:doc-formula-expressions` after `pnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lint` under the shared verify lock (VERDICT command-exit 0). Those 3s are recorded as what they are — nothing measured, not a finding. `skip-changeset` applies: the diff is `.claude/**` plus `AGENTS.md`, nothing under `packages/**`, and no published `files[]` content moves. ## Acceptance notes — out of scope, not filed by the dev - SKILL.md 〈状态模型〉 still says 派发与折叠检查时读半状态巡查锚的 H17 触发文件索引. With the patrol's schedule retired on its own card, that index can go stale; this card's R3 scope was the two 〈执行座位职责〉 lines only. Dedupe words: 半状态巡查锚, H17, 触发文件索引, 折叠检查. - `references/instrument-discipline.md` carries no `CEILINGS` row, so it is the one un-ratcheted file on the pm-dispatch surface. Adding the row is an edit under `scripts/**`, and by R6's own rule a new ratchet needs the maintainer's sentence on its card. Dedupe words: CEILINGS, instrument-discipline, ratchet row, un-ratcheted reference. - `check-clause2-carriers --template` prints no line contradicting R5's shape (checked; no script edit). ## 维护者速读(草稿) **改了什么** — 把「仪器」这件事写成纪律:`--pair` 这类硬门禁只在能给出确定答案的行上挡落地(复核记录在不在、档位行在不在、两个标签载体一不一致、认领形对不对);猜意图的那一行(C5 放宽 tell)从此只印读数,由达档复核的人判。半状态巡查从「每轮派发的前置条件」降为「按需跑的读数」。达档复核的范围收到「会出货给用户或 agent 的东西」,形状收到「读 diff 加读 CI 的 check-runs」,不再本地重跑门禁。新增一页〈仪器纪律〉,把这几条连同「只报告的仪器不配 dev」「新增门禁要维护者一句话」「工具位先花在删除上」写在一起。 **为什么改** — 裁决 objectstack-ai#208 的实测:工具链自己占了三到四成的合并量、每个 PR 三分之二的 CI 关键路径;把 objectstack-ai#19314 挡住的那道门,本体只是两句章程话,不是 CI 门禁。一次达档复核 24 万 token、29 分钟,其中最大一块是在本地重跑 CI 已经跑过的 37 个门禁族。这三件都不是删代码能解决的,是纪律写错了地方。 **风险与代价(含回滚)** — 代价是硬门变软:C5 不再挡人,漏网要靠复核的人看见。回滚是一次 revert,因为全是文本。棘轮一行没抬,新增的行全部用去重付账,幸存载体逐条点名在上面;唯一的新面是那一页新文件,它暂时没有棘轮行。 **席位意见** — **你要做的** — 读这五处改动,同意就人工合并(Tier H,队列与 auto-merge 都不适用)。 ## Round 2 (seat's note) Head `96774e44ef`. The at-tier review (5755678024, FAIL) named three items; all fixed in one push: R5's obligation now keys on the **face**, not the lane (`references/contract-review.md` 〈复核归属与资格(按面)〉 lines 24–27, SKILL.md line 647, plus the two lane-keyed twins at SKILL.md 533 and core-rules.md 113 — 「三面」 is now 「五面」 and the published schema names its path `packages/spec/src/**` non-test); `origin/main` (`ea64bbc6e8`) merged with the SKILL.md 180/181 conflict resolved keep-both; `instrument-discipline.md` cites ruling 208 / card 19491 / comment 5755284987 with bare ids (the `#` spelling is what `check:pm-skill-id-lint` refuses). Ratchet: SKILL.md 815/819, contract-review.md 60/60, core-rules.md 151/151, AGENTS.md 1109/1109. CI: this head has zero GitHub-Actions runs — a `.claude/**` plus `AGENTS.md` diff matches no PR-level workflow paths; the merge queue's `merge_group` run supplies the required contexts, so the empty check list is the known shape and not a stall. --- _Generated by [Claude Code](https://claude.ai/code/session_012GcsUbuqFGBibkEDMRC1eE)_ --- _Generated by [Claude Code](https://claude.ai/code)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
Fixes #19457
Clause-②: no — charter text plus one label-vocabulary row. The diff adds no Zod key, no closed-set member, no exported symbol and no runtime registration.
node scripts/pm/check-widening-tells.mjs --declaration no --diffwas run over this branch's full three-dot diff and exits 0.The ruling this PR carries
Batch #202 item 1, letter B. The maintainer's authorizing words, verbatim, in order, quoted unchanged from the card (chat, 2026-09-20 between 23:18Z and 23:45Z):
And the ruling addendum recorded on the card as comment 5754225479, which edit 6 below executes, verbatim and untranslated:
And the ceiling ruling, recorded on the card as comment 5754521737, which round 4 executes (the first clause is a different card, the second is this one):
The five edits
All five land in
.claude/skills/pm-dispatch/SKILL.md. The one rule that also has a line inreferences/core-rules.mdis changed there in the same PR, per the charter's own 「一条规则在本文与核心条款一处改动,另一处同 PR 同改」.1. The dev queue is product-only. The tooling clause is deleted from the
pm:queuedefinition in both files:pm:queue= 有具名落点或复现的具体缺陷,或范围明确的工具/门禁修复,无可问之事」 becomes 「pm:queue= 有具名落点或复现的具体缺陷,无可问之事;⛔ 工具/门禁修复不由此进」.references/core-rules.md〈分诊座位职责〉: 「有落点或可复现的缺陷、范围明确的工具修复与实现未被裁错的说明书脱节进pm:queue」 becomes 「有落点或可复现的缺陷、实现未被裁错的说明书脱节进pm:queue;工具卡另须带解锁行」.The condition a tooling card may sit in
pm:queueunder is added beside it: 「tooling入pm:queue仅当首行带Unblocks: #N(open 产品卡)或点名所护的已发布面」. The execution seat's candidate query gains the exclusion in place, on the 候选 line in 〈候选与批次〉: 「⛔ 排除两行皆无的tooling卡」.2. Triage closes at first grading. In 〈分诊座位职责〉, on top of what #19459 landed on
mainwhile this branch was open:not_planned, the reason, the two reopen conditions, and the prohibition.tooling卡同样关」, inheriting the prohibition through 「下行同此」.Class (b) is narrowed beside the three filing classes: 「门禁头注、self-test 文案与
check-*处方句 ⛔ 非已声明契约;(b) 须用户或已发布包读得到」.3. A broken gate is deleted, not repaired. Seeded on the existing 「失效修法按序取:先删容许出错的构造…」 line in 〈平台读数纪律〉, two lines follow it:
4. At most one tooling dev in flight, fleet-wide. In 〈候选与批次〉, beside the 并行度 rule: 「舰队至多一张
tooling卡带pm:dispatched,第二张等;带Unblocks:者继承产品级不计数」.5.
toolingis a first-touch triage label with named readers. The authoritative label glossary is the 〈状态模型〉 table in SKILL.md, whose bullet list carries the rule 「一个标签存在当且仅当有具名读者」. Definition, first-touch application and all four readers land in the one glossary row:| tooling | 修复落在门禁/脚本/workflow/技能/席位协议/PM 工具面而非产品包;分诊首触打,与 domain:* 同笔;四具名读者 = 候选查询排除、首触即关、舰队一张在飞、普查半态行 |A table row is exempt from the 120-byte cap and metered by the file's widest-row pin instead, so carrying the readers there costs one line fewer than a separate bullet: the row is 227 bytes against this file's 342-byte pin.
Reader (iv) — the half-state row — is named only.
scripts/pm/check-half-states.mjsbuilds every H row from a per-row predicate, a message builder and a registration, so it is not the one-line addition the card made that conditional on; per the card it stays named in the glossary and is left to the next patrol edit.The label OBJECT, which rides this PR
Round 1 reported this as a finding; it is fixed here instead of filed.
scripts/pm/ensure-pm-labels.sh— the file the charter names as the authority on a label's readers — did not nametoolingat all. Measured in objectstack while writing this, with the label live on 44 queue cards, the object carries GitHub's default colouredededand a null description. That is the exact drift the script's own header describes, and the header also says why it cannot heal by itself:--reconcilealigns only the labels that file names, so no rerun in either mode ever reaches it.The row is added in the five-repo loop, beside
finding, on the rule stated next topriority:p0: a label belongs in that loop when the sweep that reads it is repo-parameterized and the duty that sets it is a five-repo triage duty. Both hold. Its description is 100 characters, at the hard cap —pnpm check:pm-label-desc-capis green and namestoolingas the longest of the 28.Edit 6 — the director's governed-merge audit is retired
Item 9 above. It is a net deletion, and the only edit in this PR that removes a duty rather than adding a rule.
references/lanes/director.mdloses 〈职责四:受管合并审计〉 entire — the heading and its six bullets, 9 lines with the blank — and the 四职 reference in its opening block becomes 三职. The file goes 72 to 63 lines.--sinceinvocation and the lane-early-warning / director-window split), drops the audit list from the round-report contents line, and its two duty-roster mentions become 三职. The guard-index row keeps the SCRIPT and loses only 轮报载体, which the deletion makes false.references/core-rules.mddrops the audit from the round-report line and from the director's duty roster, both in place, net 0 lines.Kept deliberately, on the test that a line about the CI gate or the script's existence is not the retired seat duty: the
domain:skillslane row naming the script as the governance-execution file; the guard-index row itself;landing-operations.md's pre-ready--pr Nrun;lanes/skills.md's--testrun;state-machine.md's generator-artifact--testrule; and bothplatform-readings.mdbehaviour readings.scripts/pm/check-governed-merges.mjsand its CI self-test are untouched — they are not the duty.Round 3 left one mention standing and reported it; round 4 takes it, on the seat's word and under the same directive:
references/lanes/skills.mdloses 「轮报的受管合并审计清单带--since四仓实跑,⛔ 不凭记忆汇总」, the same retired audit ordered for a different seat's round report. That file goes 33 to 32 lines. A residual scan for the duty across.claude/skills/pm-dispatch/**and.claude/agents/**— pattern 受管合并审计, governed 合并审计, 合并审计, 四职, 职责四 — now returns zero hits, and the survivingcheck-governed-mergesreferences are only the CI-gate and script-behaviour ones listed above.Merged
mainmainmoved three charter commits under this branch after its merge base: be488ce (#19449), 287eb4c (#19214) and 22ca89f (#19459). The last rewrites exactly the grading line this card edits, sogit merge origin/mainproduced one conflict, in.claude/skills/pm-dispatch/SKILL.md. It is a merge commit, not a rebase, and nothing was force-pushed.The resolution keeps both sides: main's four-segment
Path:spelling and its two new lines (定义项 / 清单项) verbatim, and this card's three additions beside them as described under edit 2. The merge commit carries only the resolution; the fold and the label row are a separate commit on top, so a reviewer can read what main brought apart from what this change produces.Verification the card asks for
Gates
Derived on this head with
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack— 41 families: 21 at first, 36 once the label row brought the shell-script families in, and 41 now that round 4 edits the ratchet script itself. Every one was run with its exit code captured before any pipe, and the reconciliation reads41 derived, 41 run, 0 NOT-MEASURED, 0 UNRUN, a derived zero rather than a claimed one because every line carries its code. All 41 are green.pnpm --filter @objectstack/lint run check:doc-formula-expressionsexits 0 once@objectstack/formulaand@objectstack/lintare built; on a torn-down worktree it exits 3, which that gate spells out as PREREQUISITE NOT MET with nothing measured — not a finding.Also run green, outside the derived set:
check:pm-widening-tells(self-test and against this diff),check:pm-settings-deny-roster,check:pm-clause2-carriers,check:pm-label-write,scripts/check-skills-token-ratchet.mjs,check:skill-identifier-liveness,check:skill-frame-freshness,check:skill-compatibility.The ceiling, now ruled
Rounds 1 to 3 left
check:pm-skill-ratchetred at 819 against 813 and did not touchCEILINGS, because raising one is on the charter's own manual floor. The maintainer has now ruled it — item 10 above — so round 4 executes it and the gate is green:The
CEILINGSentry for.claude/skills/pm-dispatch/SKILL.mdgoes 813 to 819, with the maintainer's sentence quoted above it in the shape of the two ORDINARY ruled raises already on that entry: what the six lines buy, why they could not be paid in place, and the note that SKILL.md is not aCROSS_FILE_MOVESdestination so noruledRaisesrecord applies. ⛔ No other entry in that map moves.Measured, per file, against
origin/main:.claude/skills/pm-dispatch/SKILL.md.claude/skills/pm-dispatch/references/core-rules.md.claude/skills/pm-dispatch/references/lanes/director.md.claude/skills/pm-dispatch/references/lanes/skills.mdscripts/pm/ensure-pm-labels.shThe six lines the ruling buys are what is left after three rounds of paying in place — the cost went 9 at round 1, to 8 after the merge, to 6 after edit 6: folding the four readers into the length-exempt glossary row bought one line back, and edit 6 deleting the two lines that ran the audit bought two more. The widest-table-row pin is unaffected — SKILL.md's pin is 342 bytes and the new glossary row is 227. Every new prose line is at or under the 120-byte cap.
Neither shrunk file has its ceiling lowered, and that is a measurement, not an omission. The gate prints
director.md is 63 lines (ceiling 72; headroom 9)andlanes/skills.md is 32 lines (ceiling 33; headroom 1), both with a ✓ — it asks for neither entry to be moved, exactly as it does not fordogfood-verification/SKILL.md, which stands at headroom 9 and is green. Lowering either is a legitimate ratchet-down whenever someone wants it; it is not owed here.Six lines is the measured cost of the six ruled edits after paying everything payable in place, and it is what item 10 rules. Most of the rule changes cost no line at all: the
pm:queuedefinition, the 候选 candidate query, the grading reference, the core-rules mirror, the four readers now riding the glossary row, and every one of edit 6's in-place rewrites. The remaining six are one ruled rule each and there is nothing left to merge them into: every ceilinged file in that map stands at headroom 0, so no reference file can absorb them either, and a declared cross-file move is zero-sum by construction — the destination's raise may not exceed the source's net decrease — so it cannot fund new content.Raising a ceiling is on the charter's own manual floor — 「人工地板项(发版、天花板、契约扩大)仍需明确字句」 — which is why rounds 1 to 3 carried the red rather than clearing it. Item 10 is that explicit sentence, so the raise is now an execution rather than a judgement:
['.claude/skills/pm-dispatch/SKILL.md', 813]becomes819, quoted above the entry, exactly as the two precedents already in that map were taken. A cross-file move funded by director.md's decrease was described to the seat and refused: the mechanism is a move, deletion at the source pays and restatement does not, and nothing here moves — it would have passed the gate's arithmetic while recording something that did not happen.Landing
The register of record is the
GOVERNED_SURFACEStable inscripts/pm/check-governed-merges.mjs. Measured on this tree,governedPathsInanswers the single rowclaude-tree(.claude/**) andgovernedTierForanswersSfor this diff — so by the register this is a Tier S landing, not Tier H as the card and the dispatch both describe it.scripts/pm/**is not on the register and does not change that. It changes nothing about what happens next: the maintainer's item 8 reserves this particular merge to his own hand (「你会派发处理章程卡吧,然后合并之后通知分诊?」), and the ratchet red above must be cleared first either way. No seat flips this ready, queues it or arms auto-merge.This diff publishes nothing from any released package —
.claude/**andscripts/pm/**only, andscripts/pm/**is a PM-loop tool that ships in no tarball — soCheck Changesetneedsskip-changeset. The seat applies labels; this PR does not.Related: #19340 is the sibling filing/merging directive and is not addressed here (its items 1 2 3 4 5 8 landed separately as be488ce); #19458 carries the 90-card stock closure and is not addressed here either.
维护者速读(草稿)
改了什么 —— 开发队列从此只收产品卡。工具卡(门禁、脚本、技能、席位协议)要么点名它挡住的那张产品卡,要么点名它保护的已发布面,否则分诊第一次看到就关掉,不再降级成 p3 挂着。另外三条配套:坏门禁默认删不默认修;全舰队同时最多只有一个开发 agent 在做工具卡;
tooling成为分诊首触就打的标签,有四个具名读者,并且这次把这个标签本身也在标签词表脚本里声明了(它现在在 GitHub 上是灰色、没有说明的野标签)。第六条是你说的:总监席的「受管合并审计」整职删掉,章程里所有让席位去跑这个审计的行一并删(技能席那一行也删了),脚本和 CI 自检不动。为什么改 —— 现在队列里 215 张有 111 张是工具类(52%),而产品 P0 只有 3 张、P1 有 29 张。分诊没有关掉它们不是失职,是章程写着「范围明确的工具修复」就该进队列。规矩不改,下一批 90 张还会长出来。
风险与代价(含回滚) —— 风险是误伤:真正挡住产品的仪器卡如果忘了写
Unblocks:行,会被当成工具卡关掉。对冲是两个重开条件都写在关单评论里,重开免费。回滚是一次 revert,这个 PR 只改两个 markdown 文件加一个 shell 脚本里的一行标签,没有产品代码、没有 workflow。席位意见 ——
你要做的 —— 一件:合并这个 PR(受管面,item 8 说了由你亲手合)。天花板的事已经按你那句「天花板抬到 819」执行完,棘轮现在是绿的(819/819),41 个门禁全绿。
Authored by the dispatched os-dev round of https://claude.ai/code/session_012GcsUbuqFGBibkEDMRC1eE — round 1 opened this PR; round 2 merged
main, folded the readers into the glossary row and added the label row; round 3 landed edit 6; round 4 executed the ceiling ruling and removed the last audit line. The footer under this line is the platform own block: a REST body EDIT appends one, which is why this body carries none of its own.Generated by Claude Code