Skip to content

docs(pm-dispatch): land the maintainer's filing/merging directive — items 1 2 3 4 5 8 — as in-place charter deltas, net 0 per ratcheted file - #19449

Merged
os-steve merged 1 commit into
mainfrom
claude/issue-19340-filing-directive-items-1-5-8
Sep 20, 2026
Merged

os-steve merged 1 commit into
mainfrom
claude/issue-19340-filing-directive-items-1-5-8

Conversation

@os-steve

Copy link
Copy Markdown
Collaborator

Fixes #19340
Clause-②: no

Lands the DELTA between the six adopted items of the director's record (comment 5750077963 on #19340 — the maintainer's verbatim answer 「1 2 3 4 5 6 8」, 2026-09-20T13:24Z, items 1 2 3 4 5 6 8 adopted, 7 and 9 not) and the charter as it stood on origin/main 23f1de0. Item 6 is carried by #19344 (out of scope here; #19344 remains open). Items 7 and 9 were not adopted and nothing here re-proposes them.

Every ratcheted file lands at net 0 — each new rule is paid by retiring a second pointer to the same reference file or a line restated verbatim in a sibling (the pointer-retirement pattern of the last two director-charter PRs) — and every landed line is at or under 120 bytes (widest: 120 B). state-machine.md is untouched (reasons below). Diff: 4 files, +24 / −24.

Per item — the line that stood, the line that lands, what was already in place

item before (origin/main 23f1de0) after (this branch, a2665ce) already in place — untouched
1 filing threshold inverted SKILL.md :347–:351 named the three classes and 「其余进 PR ## Acceptance notes,⛔ 不立卡」 but said nothing about reachability today, a named producer, dormant / zero-pull findings, digests or quotas SKILL.md :351 (new) 「(a) 须今天可达,(c) 须具名生产者;观察、休眠、零拉动 ⛔ 不立卡、不进汇总卡、无配额」 · os-dev.md :45 「(a) 须今天可达,…」, :46 「…须具名生产者…」, :48 adds 休眠、零拉动 to the not-filed list · core-rules.md :87 twin (今日可达可复现缺陷 · 具名生产者陷阱) SKILL.md :347–:350 (three classes, (a)/(c) boundaries), :352–:354 (承接者:无), :376 (三类外关 not planned); os-dev.md :41–:44, :47
2 devs do not file; report contract SKILL.md :778 「只列三类立卡与 noted, not filed;立卡附查重词、归挂、立在修复仓」 and :779 「席位在 ACCEPT 读 … 由席位补立」 named no class: / carrier: field and no per-entry disposition; os-dev.md :49–:50 spelled entries as noted, not filed: …; :60–:61 and :65 still read as the dev filing (「立成它的 sub-issue」「独立立单」「无 assignee 立单」) SKILL.md :777 (every entry class: a|b|c + evidence, or carrier: = 承接者; neither ⇒ Acceptance notes), :778 (dev 不立卡; ACCEPT disposes each entry in one line filed #N / Acceptance notes / dropped — reason; the seat files the three-class ones in the fix repo), :779 (seat reads Acceptance notes, files the true three-class ones with 归挂 + 查重词; out-of-class cards already filed are closed not planned) · os-dev.md :49–:50 (the two fields; carrier: defined; neither ⇒ Acceptance notes only), :60–:61, :65 (the REPORT names the sub-issue / Blocked-by: anchor; the seat files), :376 (report template) · core-rules.md :151 twin os-dev.md :55 「dev 不 POST /issues」 already said devs do not file; :51 (3–5 dedupe words); :53 (four-write budget)
2 the mechanical lock see Item 2's lock — measured below no file change MCP half: issue_write and sub_issue_write are in settings.json permissions.deny, pinned by check-settings-deny-roster.mjs
3 triage merges at first grading SKILL.md :367 「同文件同缺陷 = 同一发现,不分车道:证据搬到先卡,后卡关 duplicate_of,⛔ 不并排派发」 and :368 「其余在飞 ⇒ Blocked-by: 不派;open 未认领 ⇒ 先并成一个派发入口;已完成 ⇒ 卡可能过期」 — a label-pass rule with no first-touch timing, no same-family rule and no execution-seat route SKILL.md :368 「同文件同机制 = 同一发现,不分车道,首触定级即并:证据搬先卡,后卡关 duplicate_of」, :369 「同族异缺陷 ⛔ 不并:互链排同批;在飞(assignee/open PR)永不并,Blocked-by: 不派;完工查过期」, :370 「执行席 ⛔ 不并卡,疑重复挂 pm:retriage 写明哪两张同文件同机制;…」 SKILL.md :223 (分诊唯一生产 duplicate_of), :224 (执行席误标 ⇒ pm:retriage), :366 (查重先按文件/机制); core-rules.md :137 (去重并卡 = 记账不升级) — no core-rules line states the merge rule itself, so no twin
4(i) escalated card names its half nothing: SKILL.md :454–:455 (在飞卡衍生三分 / sub-issue) and :471 (Release: 行点名已落项与余项去向) never required the new card's face to say which half it carries SKILL.md :458 (new) 「自在飞派发升级出的卡首行一句:本卡承哪一半、父卡留哪一半;缺此行不入队不入箱」 SKILL.md :456–:457 (sub-issue inherits domain / priority; the one dispatch bypass), :471
4(ii) ruled card re-enters only with Prior rulings on this card: SKILL.md :357 「决策箱勤务:落卡入箱时校验/补全四棱块与速读;…」 checked the 速读 and four-facet block only; no intake refusal existed anywhere SKILL.md :357 (intake also checks the Prior rulings on this card: line), :358 (new) 「线程有 Ruling:/RULED 的卡再入箱,该行逐 id 各一句变化;缺行 ⇒ 拒入,pm:retriage 回立卡者」 SKILL.md :340 (Prior rulings read: line at classification), :733 (出决策箱须引裁决 id); decision-analysis.md :45; dispatch-runbook.md :84 (Ruling-ref:); state-machine.md :40–:41 (who hangs and who removes pm:retriage)
5 first batch after five cards director.md :40 「第一步:逐卡过一类自裁三判据;全立者录裁转工作态、只入收班追认表,⛔ 不呈批」 — read as 「screen the whole inbox, then present」 director.md :40 「首批读完前 ≤5 张同族卡即呈;一类自裁按批过,⛔ 不先扫全箱,自裁者由下一候选补位」, :41 「取下五张只用便宜扫描:标签、assignee、PR 引用、速读首行;全文只读手上五张」, :42 「判据:开场标记→首批 ≤ 读五张;全立者录裁转工作态、只入收班追认表,⛔ 不呈批」 (the old :40 tail kept verbatim) director.md :44 「一次只开一批」 (pacing, not the pre-read); :23 (每批 5 张)
8 same-holder duplicates SKILL.md :223 「分诊座位唯一生产:…duplicate_of」 with no exception anywhere SKILL.md :370 tail 「同 assignee 者自关后卡」 — the holding seat closes the later card as duplicate_of itself, no pm:retriage round trip :223 kept verbatim: no 120-byte spelling of the exception fits on it (four variants measured 125–153 B); the exception sits beside the merge rule it widens

Paid for by retiring five second pointers and two restated lines — net 0 per file

retired what it was the rule still lives at
SKILL.md :321 「since 读法与成本对价见 references/dispatch-runbook.md」 pointer, one of six to the same file dispatch-runbook.md, still pointed at from :384, :532, :588, :729
SKILL.md :560 「云卡四课与接手协议增量见 references/dispatch-runbook.md」 pointer dispatch-runbook.md :115 「## 云卡(mode:cloud)四课」, :143 「## 接手中断的 dev」; pointed at from :532
SKILL.md :650 「os-regen 的陷阱与锚点禁令见 landing-operations A」 pointer, second to the same file :637 「细则见 references/landing-operations.md」; os-dev.md :197–:198 carry the trap
SKILL.md :657 「首次入队 flip 定点、MERGED 两读数、关键 PR 订阅与退订/归档细则见 landing-operations B」 pointer, third to the same file :637
SKILL.md :771 「总监席不占 domain:*,永不认领 backlog、永不写码;章程见 references/lanes/director.md」 restated verbatim + duplicate pointer director.md :19 (the rule); SKILL.md :57 and :675 (the pointer)
director.md :42 「一行回批即全链执行,裁后四件原子执行不再请示」 restated decision-analysis.md :14 (⛔ 不为它另起请示轮), SKILL.md :728 (四件同笔); director.md :46 points at decision-analysis
director.md :51 「代裁通道的置信门与人工地板见 SKILL.md 分诊座位职责,⛔ 不另抄」 pointer SKILL.md :392–:399 (人工地板, 置信门), :770 (总监席是唯一裁决者)

Clauses compressed inside a rewritten line, and where each now lives:

clause now covered by
SKILL.md :357 「语言按不变量」「子轮」 :99 (中文只留四通道), :372 (低频子轮)
SKILL.md :367 「⛔ 不并排派发」 :368 merge at first grading + :369 「在飞 … Blocked-by: 不派」 + :370 (execution seat raises pm:retriage): two same-finding cards can no longer be dispatched side by side
SKILL.md :368 「open 未认领 ⇒ 先并成一个派发入口」 superseded by 「首触定级即并」 (:368) and 「同族异缺陷 … 互链排同批」 (:369) — item 3 moves the merge from the dispatch entry to first grading
SKILL.md :368 「已完成 ⇒ 卡可能过期」 kept as 「完工查过期」 (:369)
os-dev.md :46 「由写它的人以外的人」→「他人」 · :48 「文档 nit」→「nit」 same meaning, 21 B and 7 B shorter
os-dev.md :49 「席位 ACCEPT 读」 SKILL.md :778–:779 (the seat's ACCEPT disposition)
core-rules.md :87 「先发修复指令再跳过,不可派发」→「发修复指令不派」 SKILL.md :355 (the full rule)
core-rules.md :151 「核验对读同轮报告」→「对读同轮」 SKILL.md :780 (unchanged)

Ceilings before / after (node scripts/pm/check-skill-line-ratchet.mjs, green before and after)

file before after ceiling
.claude/skills/pm-dispatch/SKILL.md 813 813 813
.claude/agents/os-dev.md 403 403 403
.claude/skills/pm-dispatch/references/core-rules.md 151 151 151
.claude/skills/pm-dispatch/references/lanes/director.md 72 72 72
.claude/skills/pm-dispatch/references/state-machine.md 42 42 42 (untouched)

No ceiling raised, no cross-file move declared. Twin rule: a rule changed in SKILL.md that has a core-rules.md twin changed there in this PR (:87 for item 1, :151 for item 2); items 3, 4, 5, 8 have no core-rules twin line, so none was added.

Item 2's lock — measured, not written

  • .claude/settings.json permissions.deny holds 17 mcp__github__* write tools, including issue_write and sub_issue_write — the MCP half of 「devs do not file」 is already mechanical (lock 1; check-settings-deny-roster.mjs pins the roster).
  • permissions.allow pre-approves curl -sS -X POST …/issues/*/labels (labels) and no POST …/issues (create): the REST create is neither allowed nor denied — it falls to the session's permission mode, not to a rule.
  • No hook inspects a curl target: of the five PreToolUse hooks only guard-main-checkout-bash.sh mentions curl, as a write-redirection shape, not a URL.
  • references/rest-channel.md :41 declares POST …/issues a ✓ seat channel (「建卡带标签 POST .../issues」) and the seats file cards through it; a dev subagent runs inside the seat's session under the same settings.json. A Bash deny rule on POST …/issues would refuse the seat's own filing — exactly the conflict the claim anticipated — so no rule is added. The report's open_questions carries the two mechanisms that could bind the dev without the seat (an agent-scoped PreToolUse hook declared in os-dev.md frontmatter; a guard branch keyed on a subagent signal in the hook payload), both needing a measurement of what the harness hands a subagent's hook, and both on the human floor (新增必需 hook).

Why state-machine.md is untouched

The claim listed it for item 4(ii). It is 42 / 42 on the ratchet (mechanism assumption 4: the row exists), has no needs-user-decision section, and its pm:retriage section already governs the refusal's mechanics — :40 (挂标者 = 提出异议的席位, evidence + the ask in one stroke) and :41 (摘标者 = 分诊 Routine, next fire). The intake duty the card itself names (「落卡入箱时校验/补全」) lives at SKILL.md :357, so 4(ii) lands there. Nothing in state-machine.md is a second pointer or a restated line worth retiring to add a twin.

Mechanism assumptions — each verified

  1. Tier. dispatch-gates --tier --repo objectstack-ai/objectstack on the five paths → MANDATORY, path-derived from SKILL.md and os-dev.md; the register (check-governed-merges.mjs row claude-tree) puts .claude/** in Tier S. node scripts/pm/check-governed-merges.mjs --pr N runs after this PR opens; its reading is in the report comment on finding(skills/pm-dispatch): the director charter's step order reads as 「screen the whole inbox before the first batch」 — summon #25 presented batch #192 only after reading all 51 cards; and ruled cards re-enter the decision box without citing the ruling on their own thread #19340 (GOVERNED, exit 3, Tier S expected).
  2. Serial. At 2026-09-20T21:54Z the file lists of all 21 open PRs were read: none touches the five files; only chore(pm): allow the two stamped seat-write tools and the issue-state PATCH #19292 touches .claude/settings.json, which this PR does not. origin/main moved by one commit since the branch point (57ceb9d, scripts/ only, no .claude/ path) — nothing to merge.
  3. Gates. The line ratchet, the id-lint and the governed-prose pin are all in the derived union and green (below). There is no token ratchet over .claude/**: scripts/check-skills-token-ratchet.mjs prices the published skills/** only; .claude/** is priced in lines by check-skill-line-ratchet.mjs. Ceilings not raised.
  4. state-machine.md row. Present at 42 — see above.

Verification (head a2665ce)

Derived union — node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths; change set 4 paths vs merge base 23f1de0, 48 changed lines vs the 5000 threshold: under) → 23 commands, each exit captured before any pipe, reconciled with --ran: 「23 derived famil(ies) accounted for — 23 run, 0 NOT-MEASURED (a DERIVED zero — all 23 recorded an exit code and none of them is 3)」.

pnpm check:pm-skill-ratchet :: exit 0
pnpm check:pm-skill-id-lint :: exit 0
pnpm check:pm-governed-prose :: exit 0
pnpm check:pm-governed-merges :: exit 0
pnpm check:pm-expected-skips :: exit 0
pnpm check:skill-frame-sync :: exit 0
pnpm check:agent-model-declared :: exit 0
pnpm check:nul-bytes :: exit 0
pnpm check:commit-card-trailers :: exit 0
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
pnpm check:agent-test-spelling :: exit 0
pnpm check:doc-authoring :: exit 0
pnpm check:gitlink-declared :: exit 0
pnpm check:watch-hint-literal :: exit 0
pnpm check:refd-timer-probe :: exit 0
pnpm check:driver-memory-census :: exit 0
pnpm check:cross-package-test-inputs :: 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 check:pm-half-states :: exit 0
pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0

check:doc-formula-expressions first exited 3 (PREREQUISITE NOT MET — @objectstack/formula and @objectstack/lint unbuilt; not a measurement); both were built under bash scripts/pm/os-verify-lock.sh (VERDICT command-exit 0, 4 tasks, cached) and the gate re-ran to exit 0. The three named gates plus check-nul-bytes and check-agent-model-declared were also run directly via node on the working tree before the commit, exit 0 each. pnpm check:pm-dispatch-gates (not in the derived union) runs detached with its exit captured to a log; at PR open it stood at 1715 cases ✓ / 0 ✗ and still running — its final exit is in the report comment.

四维分析 — 每处措辞的取舍

  • 实际业务需求 — 每一条都对应本场总监席实测到的成本:51 张全读后才呈第一批(第 5 项);5 张已裁卡以新速读重入决策箱、每张换来一次全线程重读与一句「维持原裁」(第 4(ii) 项);16 张裸 finding 积压超过运行手册 15 张告警线(第 1、2 项)。措辞只写机制与判据,不写故事;判据可核验(开场标记→首批 ≤ 读五张;线程有 Ruling: 而卡面缺行 ⇒ 拒入)。
  • 项目长远合理性 — 全部落成在位改写与退指针,不抬棘轮上限、不加文件、不加工作流;规则住在它的自然家(入箱检在 SKILL.md :357 的决策箱勤务行,并卡规则在查重三行,总监节奏在章程 :40–:42),不另起一节。第 2 项的锁没有落:实测无规则拒 POST …/issues,而 settings.json deny 会一并锁住席位自己的立卡通道 —— 加一条会破坏立卡的规则是「workaround」,故按裁决意图只落报告契约半边,机制半边作为待决问题带四轴上报。
  • 防 AI 写错 — 报告契约从散文(noted, not filed: …)改成两个具名字段(class: a|b|c + 证据 / carrier:),缺字段的条目有确定去向(Acceptance notes),席位处置是三选一的固定拼写;入箱拒入是机械判据(线程有 Ruling:/RULED 而卡面缺行),不靠席位记得去读线程 —— 这正是本场 5 张重入卡的失效形态。
  • 创业阶段不扩散需求 — 未采纳的第 7、9 项与汇总卡、配额都没有被重新提出;第 1 项明确写「不进汇总卡、无配额」封住两条被拒的路。state-machine.md 不为一个已有归宿的规则新增一节。

维护者速读(草稿)

改了什么 — 把您 2026-09-20 对立卡与并卡流程的裁定(「1 2 3 4 5 6 8」,总监席记录 5750077963)中的六项(第 6 项由 #19344 另落)逐条落进章程:立卡门槛反转(只立三类,且缺陷须今天可达、元数据陷阱须具名生产者;观察类 / 休眠 / 零拉动 不立卡、不进汇总卡、不设配额);dev 不立卡,报告每条带 class: + 证据或 carrier:,席位在 ACCEPT 逐条一行处置;分诊首触定级即并同文件同机制的卡,同族异缺陷互链排同批、在飞永不并,执行席只挂 pm:retriage;同 assignee 的重复由持有席自关;从在飞派发升级出的卡首行写明承哪一半;线程已有裁决的卡再入决策箱必须带 Prior rulings on this card: 行,否则拒入;总监席读完前五张同族卡即呈首批,一类自裁按批过,排序只用便宜扫描。四个受棘轮文件全部净 0 行(813 / 403 / 151 / 72),每条新规则以退掉一条重复指针或一条他处已原样陈述的行付账;state-machine.md 未动。

为什么改 — 章程原文与已生效裁定相反或缺失:director.md :40 仍写「第一步:逐卡过一类自裁」(本场总监席因此读完 51 张卡才呈第一批);SKILL.md 没有「首触即并」「同持有自关」「Prior rulings on this card」任何一句;os-dev.md 的报告契约没有 class: / carrier: 字段,且三行仍把「立单」写成 dev 的动作。每个席位每次 fire 都读这些文件,错一句就整队照错。

风险与代价(含回滚) — 纯文本改动,零代码、零工作流、零 settings;派生门禁 23 / 23 绿。代价是为了净 0 而退掉的 7 行(5 条第二指针、2 条他处原样陈述的规则)与重写行里压缩掉的几个短语,每一条都在上方表格里点名了现在住在哪一行;若您认为任一条不该退,恢复它是一行 revert,但要同时退另一行才能过棘轮。第 2 项的机械锁没有落:实测今天没有任何规则拒绝 dev 会话的 REST POST /issues(MCP issue_write 已 deny;REST 建卡既不在 allow 也不在 deny),而在 settings.json 加 deny 会同时锁住席位自己的立卡通道,故作为待决问题上报而不硬加。

席位意见 —(留空,由席位定稿)

你要做的 — 本 PR 走 Tier S 席内复核落地,不需要您点击。唯一待您一字的是第 2 项机械锁的形态(报告 open_questions):A 以 os-dev.md frontmatter 的 agent 级 PreToolUse hook 只锁 dev 会话 / B 暂不加锁、只靠报告契约与 ACCEPT 处置 / C 其它。

Acceptance notes

  • noted, not filed: Prior rulings read: (tool-printed by check-prior-rulings.mjs, ids only; decision-analysis.md :45) and the ruled Prior rulings on this card: (hand-written, id + one sentence each) are now two spellings for one fact on a card face; the tool could print a stub of the second. 承接者: the skills seat (this lane), when a card asks for it — no PR heads for check-prior-rulings.mjs today.
  • noted, not filed: SKILL.md :223 still reads 「分诊座位唯一生产 … duplicate_of」 with the item-8 exception only at :370; no 120-byte spelling of the exception fits on :223 (four variants measured 125–153 B). 承接者: the next PR that touches :223.
  • noted, not filed: os-dev.md :48 keeps 「未演练漂移」 while the seat-side list (SKILL.md :351) says 「休眠」 — same class, two words. 承接者:无.
  • noted, not filed: the record's 「Tier H — the maintainer merges by hand」 for .claude/** is the superseded boundary; PR fix(pm): repair two carriers still spelling the superseded references-tier boundary #19379 repairs the two carriers still spelling it (out of scope here; fix(pm): repair two carriers still spelling the superseded references-tier boundary #19379 remains open).

Generated by Claude Code

…tems 1 2 3 4 5 8 — as in-place charter deltas

Filing threshold inverted (three classes qualified: reachable today, named
producer; observation/dormant/zero-pull findings not filed, no digest, no
quota); devs do not file — report entries carry `class: a|b|c` + evidence
or `carrier:`, the seat disposes each entry in one ACCEPT line; triage
merges at first grading (same file + same mechanism), same family is linked
and batched, in-flight never merged, execution seats raise `pm:retriage`
with the reading; same-assignee duplicates closed by the holding seat; an
escalated card names which half it carries; a ruled card re-enters the
decision box only with `Prior rulings on this card:`; the director presents
the first batch after the first five same-family cards, class-1 screening
per batch, cheap-scan ordering, verifiable criterion.

Net 0 lines in every ratcheted file: each new rule paid by retiring a
second pointer to the same reference file or a line restated verbatim in a
sibling. Every line at or under 120 bytes. state-machine.md untouched (no
`needs-user-decision` section; the intake duty's home is SKILL.md).

Claude-Session: https://claude.ai/code/session_017ETYWqMQD4qMtZzAGovWNi
Co-authored-by: Claude <noreply@anthropic.com>
@os-steve os-steve added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 20, 2026 — with Claude
@github-actions github-actions Bot added size/s documentation Improvements or additions to documentation labels Sep 20, 2026

Copy link
Copy Markdown
Collaborator Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: a2665ce1a7074c3863cb63372fe86367d1f62bbb

① Derived judgments

  • Published accept set / public surface: none moves — four Tier S charter files (.claude/skills/pm-dispatch/SKILL.md 813 / 813, .claude/agents/os-dev.md 403 / 403, references/core-rules.md 151 / 151, references/lanes/director.md 72 / 72; +24 / −24, net 0 in every ratcheted file, widest landed line 120 B), state-machine.md untouched at 42 / 42. check-governed-merges --pr 19449: GOVERNED — Tier S (.claude/** by the register), this record is the landing carrier; queue landing by the seat. Judged correct.
  • The six ruled items, each read against the record 5750077963's words and the line that lands: 1 — SKILL.md :351 「(a) 须今天可达,(c) 须具名生产者;观察、休眠、零拉动 ⛔ 不立卡、不进汇总卡、无配额」 (the two refused shapes, digests and quotas, closed by name), os-dev.md :45 / :46 / :48, core-rules.md :87 twin. 2 — SKILL.md :777–:779 (every out_of_scope_findings entry class: a|b|c + evidence or carrier:; neither ⇒ Acceptance notes; dev 不立卡; the ACCEPT disposes each entry in one line filed #N / Acceptance notes / dropped — 因; the seat files the three-class ones in the fix repo), os-dev.md :49–:50 / :60–:61 / :65 / :376 (the report template), core-rules.md :151 twin; the mechanical lock MEASURED and not written — nothing refuses REST POST …/issues today, MCP issue_write is already denied, and a settings.json deny would bind the seats' own filing channel (rest-channel.md :41) — the conflict the claim anticipated, correctly carried as an open question rather than a rule that breaks filing. 3 — :368–:370 (同文件同机制 首触定级即并; 同族异缺陷 互链排同批; 在飞永不并; 执行席 pm:retriage naming the two cards). 8 — :370 tail (同 assignee 者自关后卡). 4(i) — :458 (an escalated card's first line names its half; missing ⇒ neither queue nor box). 4(ii) — :357 + :358 (Prior rulings on this card: at intake; a ruled thread re-entering without it is refused, pm:retriage to the filer) — landed in SKILL.md's decision-box duty line rather than state-machine.md, the deviation the seat accepts: the intake duty already lives at :357 and :40–:41 of the state machine govern only who hangs and removes the label. 5 — director.md :40–:42 (首批读完前 ≤5 张同族卡即呈; 一类自裁按批过, ⛔ 不先扫全箱; 便宜扫描取下五张; 判据 开场标记→首批 ≤ 读五张), the old :40 tail kept verbatim. Items 7 and 9 re-proposed nowhere. Judged correct.
  • Paid for by seven retirements the seat re-read on this head: five second pointers in SKILL.md (:321 · :560 · :650 · :657 — each file still pointed at from a surviving line, counted: dispatch-runbook.md ×4, landing-operations ×4 after) and :771 (its rule at director.md :19 「不占 domain:* 车道 … 永不认领 backlog、永不写码」, its pointer at SKILL.md :57 and :675); two in director.md — :42 (「一行回批即全链执行」 restated at decision-analysis.md :14 「⛔ 不为它另起请示轮」 and SKILL.md :728 「四件同笔」) and :51 (a pointer to SKILL.md :392–:399). Nothing retired lost a rule. Evidence, seat-run in a detached worktree: check-skill-line-ratchet.mjs exit 0, check-skill-id-lint.mjs exit 0 (27 files), check-governed-prose.mjs exit 0; merge-tree vs origin/main 57ceb9d: 0 conflicts; CI on a2665ce: 30 check runs, 1 still running, 0 red. The dev's derived union 23 / 23 exit 0 with --ran reconciled, check:pm-dispatch-gates 1883 cases exit 0 captured.

② Semver level

None — nothing published (.claude/** is in no released package's files[]); skip-changeset on the PR is the correct declaration. Judged correct.

③ Boundary flags

Two open_questions, both for the maintainer, ⛔ not landing blockers: (1) item 2's mechanical lock — A (an agent-scoped PreToolUse hook declared in os-dev.md frontmatter, after measuring that the harness fires agent-scoped hooks for subagents) / B (no mechanical lock: the report contract landed here plus the ACCEPT's api_writes audit) / C (a subagent-keyed branch in an existing guard); the seat's reading is B now and A only after the measurement — a shared deny is the one shape refused. (2) two spellings for prior rulings on a card face (Prior rulings read: tool-printed vs Prior rulings on this card: ruled) — B, leave as landed; a stub-printing card only when pulled. Both go to the seat post's 待您 list. All four mechanism assumptions confirmed (Tier S by the register, the record's Tier H being the superseded boundary PR #19379 repairs; 0 of 21 open PRs on the five files; the three gates in the union; the state-machine.md row present at 42). Deviations read and accepted. Four noted, not filed items, each with a carrier or 「承接者:无」 — the :223 exception spelling (no 120 B fit) and the 休眠 / 未演练漂移 word pair are recorded as seat items.

Implemented-by: claude/issue-19340-filing-directive-items-1-5-8
Reviewed-by: session_017ETYWqMQD4qMtZzAGovWNi

VERDICT: PASS


Generated by Claude Code

@os-steve
os-steve marked this pull request as ready for review September 20, 2026 22:48
@os-steve
os-steve added this pull request to the merge queue Sep 20, 2026
Merged via the queue into main with commit be488ce Sep 20, 2026
32 checks passed
@os-steve
os-steve deleted the claude/issue-19340-filing-directive-items-1-5-8 branch September 20, 2026 23:12
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Sep 28, 2026
…he Path: line carries 定义项 | 清单项 id/缺项 | 路步, the card inherits the item's priority, and 「有人在等」 is not a grading test (objectstack-ai#19459)

Fixes objectstack-ai#19155
Clause-②: no

Lands the maintainer's grading ruling (quoted verbatim on the card body,
2026-09-19: 「我们是一个开发工具,应该考虑北极星有没有这个需求,有人在等吗 是个伪命题」) and the filer's
two-layer test (comment 5737998283 — the spec) into the charter's
grading line, in place, at **net 0** on the 813-line ceiling: one line
rewritten, two lines added, two second pointers retired. Every touched
line is under 120 bytes (117 / 113 / 112 B). Diff: 1 file, +3 / −3. Head
`9f87053` on `origin/main` `8e368dc` (which carries PR objectstack-ai#19449's landed
lines; its neighbours are untouched, quoted below).

Sanitizer note: the file writes each grammar slot inside angle brackets
(the same convention the old line used). This body spells them as
placeholder words — DEFN, ITEM-ID, P-STEP — because GitHub strips short
angle-bracket fragments from bodies, backticks included.

## The line that stood, the lines that land

| | before (`origin/main` `8e368dc`) | after (head `9f87053`) |
|:--|:--|:--|
| grading line `SKILL.md` :363 (110 B) | 「定级按 `docs/NORTH-STAR.md`「优先级」第
1、2 条;正文首行 `Path: P-n \| AREA \| none`」 — the second slot is an AREA
(`清单区`), so a card that merely touches an area read as 「清单上的能力断了」 | :363
(117 B) 「定级按北极星「优先级」1、2 条;首行 `Path: DEFN \| ITEM-ID/缺项 \| P-STEP \|
none`」 — definition item, then the checklist ITEM that would fail (its
`area.slug` id) or 缺项, then the path step |
| definition layer — nothing | no line said where a 定义项 comes from, what
an instrument card's is, or that a card outside the definition closes |
:364 (113 B, new) 「定义项取北极星「做出来的是什么」或仪器卡的车队决定;无则关;`none` 非分诊缺口」 |
| ledger layer + the negative rule — nothing | no line said that only an
item that would FAIL counts as broken, that the card inherits the item's
own `priority`, what a missing item does, or that 「有人在等」 is not a test
(0 occurrences on main) | :365 (112 B, new) 「清单项会 fail 才算断,继承其
`priority`;缺项先补账本;⛔「有人在等」不是定级判据」 |
| 分诊缺口 rule (:464 → :466) | 「…无级/缺 `Path:` 轮报记分诊缺口」 | unchanged — a
MISSING line is still the round-report gap; :364 says a `none` slot is a
written answer, not that gap |

The 「有人在等」 sentence is written as the negative rule (⛔ … 不是定级判据), not
quoted as narrative: the file's register is one executable sentence per
rule, and `check:pm-skill-id-lint`'s corpus rule (no ruling dates, no
quotations, no issue numbers) holds — the ruling itself stays on the
card and in this PR.

### Paid for by retiring two second pointers — net 0

| retired (all `SKILL.md` line numbers in this table are on `8e368dc`) |
what it was | the detail still lives at |
|:--|:--|:--|
| :588 「失报与停摆细则(梯度、身份三元组、验收动作)见 `references/dispatch-runbook.md`」 |
pointer, 4th of four to the same file | `dispatch-runbook.md` :164 「##
停摆复位梯度」, :173 「## 通知重放去重」, :179 「## 直接验收兜底」; the 收集 section keeps the
rules themselves at :583 (梯度 / unreliable), :584 (身份), :585–:587
(直接验收兜底's three conditions); the file stays pointed at from :384, :532
(the general 「构造细则与条款原文见」) and :729 |
| :698 「检测读数、盲区与恢复 playbook 细则见 `references/platform-readings.md`」 |
pointer, 3rd of three to the same file | `platform-readings.md` :450 「##
断粮检测与跨墙恢复(5 小时用量墙)」 — the same title as the SKILL.md section; the
section keeps its six rules (:699–:704); the file stays pointed at from
:155 and :160 (「实测事实表在 …,做对应操作的那一刻查阅」) |

Not retired: :306 「收尾四步、僵尸回收与领地防撞细则见 `references/seat-post-protocol.md`」
is the only signpost in `SKILL.md` to that file's 「Epic 车道收尾与僵尸回收」
section (僵尸 occurs nowhere else in the file), so retiring it would
orphan the detail, not a duplicate.

### Why two lines, not the claim's one — a measured correction

The claim's proposed rule sentence (「命中清单区 ≠ 能力断了;写不出会 fail 的清单项 / 断的路步
⇒ `none` ⇒ p3 或不做;定级继承该项 `priority`(断)或 P2(能跑但错);⛔「有人在等」「拉动」不是判据」)
measures **212 bytes** against the 120-byte cap, so it is not one line.
The tightest two-line spelling (grammar + one rule) dropped the
definition layer's closure (「无则关」 — the maintainer's actual sentence
「北极星有没有这个需求」) and the `none`-is-an-answer clause, so the delta is three
lines and the payment is two retirements, both of the pattern PR objectstack-ai#19449
used (a second pointer to a file that stays pointed at). Clauses NOT
restated because the pointed-at North Star already carries them: 能跑但出错 ⇒
P2 and 不在路上、不在清单上 ⇒ p3 或不做 (优先级 rule 2), and a 缺项's own grade (a path
step named ⇒ 路断了 ⇒ P0/P1; none ⇒ 不在路上 ⇒ p3 — the P-STEP slot plus rule
2).

### `Path:` specimen — a grading this shift, before and after

objectstack-ai#19343's first line (graded p3 by this seat today): 「Path: none \| fact
table (`.claude/skills/pm-dispatch/references/platform-readings.md`, 队列
section — the DEQUEUE direction) \| family: … \| graded by
`domain:skills#2`」 — the second slot holds a file / area description; no
item id could be named because none exists. Under the new grammar the
same card reads 「Path: 席位对 dequeue 事件的读法(仪器卡的车队决定) \| none \| none \|
none \| graded by …」 — slot 1 is the fleet decision (North Star
「仪器为车队服务」), slots 2–3 are `none` as written answers, and the grade
follows from rule 2 (no item fails, no step breaks), not from the area
hit. The triage seat's objectstack-ai#19143 grade (comment 5748750091 on this card)
rested on five area word-counts and named no item — the failure shape
the new slot 2 makes unwritable.

## Acceptance greps (control on `origin/main` `8e368dc`, reading on head
`9f87053`)

| word | control (main) | head | where |
|:--|--:|--:|:--|
| 清单项 | 0 | 2 | :363, :365 |
| 定义项 | 0 | 2 | :363, :364 |
| 缺项 | 0 | 2 | :363, :365 |
| 有人在等 | 0 | 1 | :365, as the negative rule |
| `Path:` | 2 | 2 | :363, :466 |
| 清单区 | 1 | 0 | — |

## Ceilings before / after (`node
scripts/pm/check-skill-line-ratchet.mjs`, green before and after)

| file | before | after | ceiling |
|:--|--:|--:|--:|
| `.claude/skills/pm-dispatch/SKILL.md` | 813 | 813 | 813 (headroom 0) |

No ceiling raised, no cross-file move. Twins: `references/core-rules.md`
carries no `Path:` grammar line and `references/lanes/triage.md` (7
lines) carries no grading line — measured by grep over the whole
`pm-dispatch/` tree and `os-dev.md` (`Path:` · 清单区 · 定级 · 有人在等 · 清单项):
every 定级 hit outside `SKILL.md` is a lane-charter sentence about WHO
grades, none about the test — so no twin changes.

## Mechanism assumptions — each verified

1. **:363 reads `清单区`, 「有人在等」 0× on main** — verified on `8e368dc`
(counts above).
2. **PR objectstack-ai#19449 MERGED and on `origin/main`** — `merged: true`,
`merge_commit_sha be488ce`, `git merge-base --is-ancestor be488ce
origin/main` exit 0 (exit 0 is self-proving on the shallow clone). Its
landed lines, before and after this edit, byte-identical: :351 「(a)
须今天可达,(c) 须具名生产者;观察、休眠、零拉动 ⛔ 不立卡、不进汇总卡、无配额」, :357 「决策箱勤务:…`Prior rulings
on this card:` 行;存量卡低频回填」, :358 「线程有 `Ruling:`/RULED
的卡再入箱,…`pm:retriage` 回立卡者」, :368–:370 (now :370–:372, the three
merge-at-first-grading lines), :458 (now :460) 「自在飞派发升级出的卡首行一句:…」.
3. **The three gates are in the derived union and green** —
`check:pm-skill-ratchet`, `check:pm-skill-id-lint`,
`check:pm-governed-prose` all in the 21-command union below, exit 0; the
813 ceiling is untouched.
4. **`check-governed-merges.mjs --pr N` → GOVERNED (exit 3), Tier S** —
runs after this PR opens; its reading is in the report comment on
objectstack-ai#19155. Tier: `dispatch-gates --tier --repo objectstack-ai/objectstack
.claude/skills/pm-dispatch/SKILL.md` → the path-derived mandate (clause
①), `MANDATORY_TIER_GLOBS`.

The checklist ledger, measured on `8e368dc`:
`docs/qa/platform-checklist/areas/*.json` — 15 files, **264 items**,
every id of the shape `area.slug` (264 / 264), field name `priority` on
every item (P0 = 20, P1 = 153, P2 = 91), every item `status: active` (no
planned state — which is why the definition layer comes first).

## Verification (head `9f87053`)

Derived union — `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` (no paths; change set 1 path vs merge base
`8e368dc`, committed 1 / working tree 0 / untracked 0) → 21 commands,
each exit captured before any pipe, reconciled with `--ran`: 「✓
dispatch-gates --ran: 21 derived famil(ies) accounted for — 21 run, 0
NOT-MEASURED (a DERIVED zero — all 21 recorded an exit code and none of
them is 3)」.

```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 check:agent-test-spelling :: exit 0
pnpm check:cross-package-test-inputs :: exit 0
pnpm check:doc-authoring :: 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:skill-frame-sync :: exit 0
pnpm check:watch-hint-literal :: exit 0
pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0
```

`check:doc-formula-expressions` first exited 3 (PREREQUISITE NOT MET —
`@objectstack/formula` unbuilt in the fresh worktree; not a
measurement); `@objectstack/lint...` (lint plus its upstream closure,
`spec` included) was built under `bash scripts/pm/os-verify-lock.sh`
(VERDICT command-exit 0, held the lock 175 s, waited 0 s) and the gate
re-ran to exit 0. The ratchet's own line: 「✓ check-skill-line-ratchet:
.claude/skills/pm-dispatch/SKILL.md is 813 lines (ceiling 813; headroom
0)」. `check:skill-frame-sync` and `check:pm-half-states` (named on the
card) are in the union above. `pnpm check:pm-dispatch-gates` (not in the
derived union) runs detached with its exit captured to a log; its final
exit is in the report comment on objectstack-ai#19155. No package is touched, so ①
(dependency closure build) and ② (package tests) are empty by the
local-verification rule; the closure build above served one gate's
prerequisite only.

## 四维分析 — 语法槽序与每处措辞的取舍

- **实际业务需求** — 每一槽都对应本班实测到的失效:分诊席在 objectstack-ai#19143
上以五个清单区的词频命中作为「清单上的能力断了」的论据、未点名任何清单项(评论 5748750091);本席自己今天的 `Path:`
行(objectstack-ai#19343、本卡)第二槽填的是文件/区域描述。账本实测:264 项、每项一个 `area.slug` id 与自己的
`priority`(P0 20 / P1 153 / P2 91),第二槽有真实总体可填;全部 264 项 `status:
active`、没有 planned 态,所以定义项必须排在账本前 ——
先查账本会把每张能力缺口卡关掉(立卡者更正的原话)。「有人在等」写成否定规则,是维护者原句的操作形式。
- **项目长远合理性** — 槽序照抄北极星自己的顺序:定义行(「做出来的是什么」)→ 那条路 →
账本(`docs/qa/platform-checklist/`);章程不复制账本、不带数字(北极星:本页不带任何数字),级直接继承账本项的
`priority` 字段而不是再推导一遍。已在北极星里的句子(能跑但出错 ⇒ P2;不在路上不在清单上 ⇒ p3
或不做)不重抄,指针指向即可。
- **防 AI 写错** — `area.slug` 形状的清单项 id 是能机械核对的 token,清单区名不是;`none`
作为每槽的书面答案,让「没答」与「不适用」可区分(缺 `Path:` 行仍是分诊缺口,:466
未动)。否定规则限定为「定级判据」:不限定的「拉动不是判据」会与 :351「零拉动 ⛔ 不立卡」(立卡门槛)和
:756「推荐序按拉动定向」(方案推荐序)直接冲突,正是 :46 禁止的两条细则冲突 ——
所以席位读法里的「拉动」二字没有落,「有人在等」即拉动之问在定级层的原话,已覆盖其实质。
- **创业阶段不扩散需求** —
不加文件、不抬上限、不加门禁、不为仪器卡另起语法:仪器卡按北极星「仪器为车队服务」原句,把会不一样的车队决定填进第一槽;缺项卡保留但先回账本补项(`checklist-author`
的输入),不按「有人在等」排程。

## 维护者速读(草稿)

**改了什么** — 把您 2026-09-19 对定级的裁定(「我们是一个开发工具,应该考虑北极星有没有这个需求,有人在等吗
是个伪命题」)落进 PM 章程的定级行:`Path:` 行从「路步 | 清单区 | none」改成「定义项 | 清单项 id 或缺项 | 路步
| none」——先问北极星「做出来的是什么」里落在哪一项(仪器卡则填它会改变的车队决定),落不到就关;再问账本里哪一个清单项会
fail(写它的 id),级继承该项自己的
`priority`,只命中某个清单区不算断;账本里没有对应项的能力缺口先回账本补项;「有人在等」不再是定级判据。`SKILL.md` 净 0
行(813 / 813),两条新行以退掉两条重复指针付账,细则文件本身未动。

**为什么改** — 章程原来的定级行把「清单区」写成判据,分诊按区命中就判「清单上的能力断了」,本班一批 8 张卡 8 张定
P0–P2、零关闭,再拿「有人在等吗」当平手裁决 —— 与您的裁定相反;两仓约 965 张卡的每一次首触定级都读这一行。

**风险与代价(含回滚)** — 纯文本改动,零代码、零工作流;派生门禁 21 / 21 绿。代价是退掉的两条指针(指向
`dispatch-runbook.md` 的第四条、指向 `platform-readings.md`
的第三条),细节仍在那两个文件里、`SKILL.md` 里各自还有其它指针;若您认为不该退,恢复是一行
revert,但要同时退另一行才过棘轮。北极星 `docs/NORTH-STAR.md` 本 PR 未动:「清单上的能力断了 = 指得出会
fail 的清单项」这一句(以及断了的 P2 项继承 P2 而不是您第 2 条写的 P0/P1)由席位在聊天里向您提出,不在本 PR 里。

**席位意见** —(留空,由席位定稿)

**你要做的** — 本 PR 走 Tier S 席内复核落地,不需要您点击。可选一字:是否同意把「清单上的能力断了 = 指得出会 fail
的清单项,级随该项的 priority」写进北极星第 2 条(A 同意,席位另开 docs PR / B 不写,章程这行足够)。

## Acceptance notes

- noted, not filed: North Star 优先级 rule 2 says 「清单上的能力断了 ⇒ P0/P1」 while
91 of the ledger's 264 items carry `priority: P2`; the charter now
inherits the item's own field, so a broken P2 item grades P2. The North
Star text is the maintainer's; the card offers him the clause in chat.
carrier: the skills seat (chat), then a docs-only PR if he says yes.
- noted, not filed: the seat's own `Path:` lines written this shift
under the area shape (objectstack-ai#19343, objectstack-ai#19155's grading comment, and the first
batch of 16) are specimens, not errors to fix here; re-reading them
under the new grammar is the seat's next grading round. carrier: the
skills seat.
- noted, not filed: `dispatch-gates.mjs` refuses `--commands` together
with `--ran` (「--ran renders a verdict on stdout; --commands and --json
render the derivation. Pass one.」) — correct behaviour, but `os-dev.md`
:137–:138 reads as if the `--ran` reconciliation is the same invocation
with a file added; one word (「单独」) would save a dev a refused call.
承接者:无 (no PR heads for `os-dev.md` :137).
- noted, not filed: PR objectstack-ai#19449's Acceptance notes already record that
`os-dev.md` :48 keeps 「未演练漂移」 while `SKILL.md` :351 says 「休眠」; unchanged
here. 承接者:无.

---
_Generated by [Claude
Code](https://claude.ai/code/session_017ETYWqMQD4qMtZzAGovWNi)_

Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Sep 28, 2026
…e at first grading, broken gates are deleted, ≤1 tooling dev in flight, tooling is a first-touch label (ruling objectstack-ai#202 B) (objectstack-ai#19462)

Fixes objectstack-ai#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
--diff` was run over this branch's full three-dot diff and exits 0.

## The ruling this PR carries

Batch objectstack-ai#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):

1. 「我随便看了几个任务,这些都是辅助类的吧,我感觉开发agent被大量的浪费在这种任务下。在北极星的标准下,这些应该开发吗?」
2. 「我们是创业项目,应该花精力处理类似的这些任务吗?」
3. 「B(荐)A + 清理存量」
4. 「p2 的 47 张转 pm:on-hold 带机器条件 有价值吗?卡片只要open就要一直被扫描。」
5. 「重点是分诊,分诊为什么没有关闭这些卡片」
6. 「你建议的规矩就三条,是否应该立卡派发」 / 「按照你的建议继续。」
7. 「对于工具卡,分诊是不是应该有一个单独的标签打上,比如 tooling」
8. 「立章程卡并把 90 张的关闭交分诊席,你会派发处理章程卡吧,然后合并之后通知分诊?」

And the ruling addendum recorded on the card as comment 5754225479,
which edit 6 below executes, verbatim and untranslated:

9. 「受管合并审计 以后不需要了,浪费时间。」

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):

10. 「205 否,天花板抬到 819」

## The five edits

All five land in `.claude/skills/pm-dispatch/SKILL.md`. The one rule
that also has a line in `references/core-rules.md` is 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:queue` definition in both files:

- SKILL.md 〈分诊座位职责〉: 「`pm:queue` = 有具名落点或复现的具体缺陷,或范围明确的工具/门禁修复,无可问之事」
becomes 「`pm:queue` = 有具名落点或复现的具体缺陷,无可问之事;⛔ 工具/门禁修复不由此进」.
- `references/core-rules.md` 〈分诊座位职责〉:
「有落点或可复现的缺陷、范围明确的工具修复与实现未被裁错的说明书脱节进 `pm:queue`」 becomes
「有落点或可复现的缺陷、实现未被裁错的说明书脱节进 `pm:queue`;工具卡另须带解锁行」.

The condition a tooling card may sit in `pm:queue` under 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
objectstack-ai#19459 landed on `main` while this branch was open:

- The grading reference now reads North Star 「优先级」1–3 条 (main had 1、2).
「1–3」 rather than 「1、2、3」 is measured, not stylistic: the latter puts
that line at 121 bytes against the ratchet's 120-byte cap.
- 「「无则关」= 首触即关 not_planned,带理由与入队两条件,⛔ 不定 p3、不 hold;下行同此」 — it hangs off
main's own 「无则关」 clause rather than restating it, and carries only what
main lacks: `not_planned`, the reason, the two reopen conditions, and
the prohibition.
- North Star rule 3 restated as a **closing** rule: 「产品仓 P0/P1
开着时,无解锁对象的 p2/p3 `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:

- 「门禁两次误报(假红、实测假绿、处方句点名不存在路径)⇒ 删肢或删门禁,PR 引两次测量」
- 「只有护产品落地或用户可见契约的门禁才立修复卡;门禁上「稳定 > 功能」= 更少零件」

**4. At most one tooling dev in flight, fleet-wide.** In 〈候选与批次〉, beside
the 并行度 rule: 「舰队至多一张 `tooling` 卡带 `pm:dispatched`,第二张等;带 `Unblocks:`
者继承产品级不计数」.

**5. `tooling` is 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.mjs` builds 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 name `tooling` at all. Measured
in objectstack while writing this, with the label live on 44 queue
cards, the object carries GitHub's default colour `ededed` and 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:
`--reconcile` aligns 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 to `priority: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-cap` is green and names
`tooling` as 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.md` loses 〈职责四:受管合并审计〉 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.
- 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 the deletion makes 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, on the test that a line about the CI gate or the
script's existence is not 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 pre-ready `--pr N`
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 — 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.md` loses 「轮报的受管合并审计清单带 `--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 surviving `check-governed-merges` references are only the CI-gate
and script-behaviour ones listed above.

## Merged `main`

`main` moved three charter commits under this branch after its merge
base: be488ce (objectstack-ai#19449), 287eb4c (objectstack-ai#19214) and 22ca89f (objectstack-ai#19459).
The last rewrites exactly the grading line this card edits, so `git
merge origin/main` produced 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

```
$ git grep -n '范围明确的工具' -- .claude/
$ echo "EXIT=$?"
EXIT=1                     # 0 hits on this branch

$ git grep -cn 'pm:queue' -- .claude/skills/pm-dispatch/SKILL.md
.claude/skills/pm-dispatch/SKILL.md:23
$ echo "EXIT=$?"
EXIT=0                     # the control is non-zero: the instrument reaches the file
```

## 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 reads `41 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-expressions`
exits **0** once `@objectstack/formula` and `@objectstack/lint` are
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-ratchet` red at 819 against 813 and
did not touch `CEILINGS`, 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:

```
✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/SKILL.md is 819 lines
  (ceiling 819; headroom 0).
```

The `CEILINGS` entry for `.claude/skills/pm-dispatch/SKILL.md` goes 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 a `CROSS_FILE_MOVES` destination so no `ruledRaises` record applies.
⛔ No other entry in that map moves.

Measured, per file, against `origin/main`:

| file | main | this branch | ceiling | verdict |
|:--|--:|--:|--:|:--|
| `.claude/skills/pm-dispatch/SKILL.md` | 813 | 819 | **819** (ruled) |
green, headroom 0 |
| `.claude/skills/pm-dispatch/references/core-rules.md` | 151 | 151 |
151 | green, headroom 0 |
| `.claude/skills/pm-dispatch/references/lanes/director.md` | 72 | 63 |
72 | green, headroom 9 |
| `.claude/skills/pm-dispatch/references/lanes/skills.md` | 33 | 32 | 33
| green, headroom 1 |
| `scripts/pm/ensure-pm-labels.sh` | — | — | — | not ceilinged |

The 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)` and `lanes/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 for `dogfood-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:queue` definition, 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]` becomes `819`, 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_SURFACES` table in
`scripts/pm/check-governed-merges.mjs`. Measured on this tree,
`governedPathsIn` answers the single row `claude-tree` (`.claude/**`)
and `governedTierFor` answers **`S`** for 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/**` and
`scripts/pm/**` only, and `scripts/pm/**` is a PM-loop tool that ships
in no tarball — so `Check Changeset` needs `skip-changeset`. The seat
applies labels; this PR does not.

Related: objectstack-ai#19340 is the sibling filing/merging directive and is **not
addressed here** (its items 1 2 3 4 5 8 landed separately as
be488ce); objectstack-ai#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](https://claude.ai/code)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

1 participant