Commit 22ca89f
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)
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
`9f87053` on `origin/main` `8e368dc` (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
| | 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 #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 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 #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 #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
#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 #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.
## 四维分析 — 语法槽序与每处措辞的取舍
- **实际业务需求** — 每一槽都对应本班实测到的失效:分诊席在 #19143
上以五个清单区的词频命中作为「清单上的能力断了」的论据、未点名任何清单项(评论 5748750091);本席自己今天的 `Path:`
行(#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 (#19343, #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 #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>1 parent 3d6f0aa commit 22ca89f
1 file changed
Lines changed: 3 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
360 | 360 | | |
361 | 361 | | |
362 | 362 | | |
363 | | - | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
364 | 366 | | |
365 | 367 | | |
366 | 368 | | |
| |||
585 | 587 | | |
586 | 588 | | |
587 | 589 | | |
588 | | - | |
589 | 590 | | |
590 | 591 | | |
591 | 592 | | |
| |||
695 | 696 | | |
696 | 697 | | |
697 | 698 | | |
698 | | - | |
699 | 699 | | |
700 | 700 | | |
701 | 701 | | |
| |||
0 commit comments