docs(pm-dispatch): grading reads the checklist ITEM, not the area — the Path: line carries 定义项 | 清单项 id/缺项 | 路步, the card inherits the item's priority, and 「有人在等」 is not a grading test - #19459
Conversation
…he Path: line carries 定义项 | 清单项 id/缺项 | P路步, the card inherits the item's priority, and 「有人在等」 is not a grading test The grading line named an AREA (`<清单区>`) as the checklist test, so a card that merely touched an area read as 「清单上的能力断了」, and no line said that 「有人在等」 is not a test. Three lines now carry the two-layer test in place: - the `Path:` grammar becomes `<定义项> | <清单项 id/缺项> | P<路步> | none` (definition item first, then the ledger item that would FAIL or 缺项, then the path step; `none` is a written answer, not a triage gap); - the definition item is taken from the North Star's 「做出来的是什么」 (an instrument card's is the fleet decision that would differ); none ⇒ close; - only a checklist item that would fail counts as broken, the card inherits that item's `priority`; a missing item authors the ledger entry first; 「有人在等」 is not a grading criterion. Net 0 on the 813-line ceiling, every touched line ≤ 120 bytes: the two added lines are paid by retiring two second pointers — the 4th pointer to `references/dispatch-runbook.md` (the 收集 section keeps the 梯度 / 身份 / 验收兜底 rules themselves) and the 3rd pointer to `references/platform-readings.md` (the standing fact-table pointer remains, and that file's 断粮 section carries the same title as the section here). Claude-Session: https://claude.ai/code/session_017ETYWqMQD4qMtZzAGovWNi Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewServed-tier: ① Derived judgments
② Semver levelNone — nothing published; ③ Boundary flagsTwo Implemented-by: VERDICT: PASS 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>
…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>
Fixes #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
9f87053onorigin/main8e368dc(which carries PR #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
origin/main8e368dc)9f87053)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 「清单上的能力断了」Path: DEFN | ITEM-ID/缺项 | P-STEP | none」 — definition item, then the checklist ITEM that would fail (itsarea.slugid) or 缺项, then the path stepnone非分诊缺口」priority, what a missing item does, or that 「有人在等」 is not a test (0 occurrences on main)priority;缺项先补账本;⛔「有人在等」不是定级判据」Path:轮报记分诊缺口」noneslot is a written answer, not that gapThe 「有人在等」 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
SKILL.mdline numbers in this table are on8e368dc)references/dispatch-runbook.md」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 :729references/platform-readings.md」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 inSKILL.mdto 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 thenone-is-an-answer clause, so the delta is three lines and the payment is two retirements, both of the pattern PR #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#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 bydomain: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 arenoneas written answers, and the grade follows from rule 2 (no item fails, no step breaks), not from the area hit. The triage seat's #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/main8e368dc, reading on head9f87053)Path:Ceilings before / after (
node scripts/pm/check-skill-line-ratchet.mjs, green before and after).claude/skills/pm-dispatch/SKILL.mdNo ceiling raised, no cross-file move. Twins:
references/core-rules.mdcarries noPath:grammar line andreferences/lanes/triage.md(7 lines) carries no grading line — measured by grep over the wholepm-dispatch/tree andos-dev.md(Path:· 清单区 · 定级 · 有人在等 · 清单项): every 定级 hit outsideSKILL.mdis a lane-charter sentence about WHO grades, none about the test — so no twin changes.Mechanism assumptions — each verified
清单区, 「有人在等」 0× on main — verified on8e368dc(counts above).origin/main—merged: true,merge_commit_sha be488ce,git merge-base --is-ancestor be488ce origin/mainexit 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) 「自在飞派发升级出的卡首行一句:…」.check:pm-skill-ratchet,check:pm-skill-id-lint,check:pm-governed-proseall in the 21-command union below, exit 0; the 813 ceiling is untouched.check-governed-merges.mjs --pr N→ GOVERNED (exit 3), Tier S — runs after this PR opens; its reading is in the report comment on skills(pm-dispatch): grading reads the checklist ITEM, not the area —Path:carries the item id, the card inherits the item's P, and 「有人在等」 is not a test #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 shapearea.slug(264 / 264), field namepriorityon every item (P0 = 20, P1 = 153, P2 = 91), every itemstatus: 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 base8e368dc, 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)」.check:doc-formula-expressionsfirst exited 3 (PREREQUISITE NOT MET —@objectstack/formulaunbuilt in the fresh worktree; not a measurement);@objectstack/lint...(lint plus its upstream closure,specincluded) was built underbash 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-syncandcheck: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 #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.四维分析 — 语法槽序与每处措辞的取舍
datasetreaches ZERO author-time rules — the type declaresallowRuntimeCreate: truewhile nothing declares it inruntimeTypesandTYPE_TO_STACK_KEYhas no row #19143 上以五个清单区的词频命中作为「清单上的能力断了」的论据、未点名任何清单项(评论 5748750091);本席自己今天的Path:行(removed_from_merge_queuefires on a SUCCESSFUL merge too — 3 of 5 on this board today were merges, so the event is not a failure signal #19343、本卡)第二槽填的是文件/区域描述。账本实测:264 项、每项一个area.slugid 与自己的priority(P0 20 / P1 153 / P2 91),第二槽有真实总体可填;全部 264 项status: active、没有 planned 态,所以定义项必须排在账本前 —— 先查账本会把每张能力缺口卡关掉(立卡者更正的原话)。「有人在等」写成否定规则,是维护者原句的操作形式。docs/qa/platform-checklist/);章程不复制账本、不带数字(北极星:本页不带任何数字),级直接继承账本项的priority字段而不是再推导一遍。已在北极星里的句子(能跑但出错 ⇒ P2;不在路上不在清单上 ⇒ p3 或不做)不重抄,指针指向即可。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
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.Path:lines written this shift under the area shape (removed_from_merge_queuefires on a SUCCESSFUL merge too — 3 of 5 on this board today were merges, so the event is not a failure signal #19343, skills(pm-dispatch): grading reads the checklist ITEM, not the area —Path:carries the item id, the card inherits the item's P, and 「有人在等」 is not a test #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.dispatch-gates.mjsrefuses--commandstogether with--ran(「--ran renders a verdict on stdout; --commands and --json render the derivation. Pass one.」) — correct behaviour, butos-dev.md:137–:138 reads as if the--ranreconciliation is the same invocation with a file added; one word (「单独」) would save a dev a refused call. 承接者:无 (no PR heads foros-dev.md:137).os-dev.md:48 keeps 「未演练漂移」 whileSKILL.md:351 says 「休眠」; unchanged here. 承接者:无.Generated by Claude Code