pm-dispatch: reserve the contract-review tier for the skills seat and the spec seat’s clause-② review; default tier elsewhere; the director’s tier is the maintainer’s per-summon choice - #17294
Conversation
…or skills seat, spec clause-② review; director tier is the maintainer's choice INCOMPLETE AND UNREVIEWED: skill-file half only; dispatch-gates.mjs half follows. Claude-Session: https://claude.ai/code/session_01MoTv7pn338AZ71owsp19gQ Co-authored-by: Claude <noreply@anthropic.com>
…-line exit; docblock and self-test follow the 2026-09-10 rulings INCOMPLETE AND UNREVIEWED: self-test not yet run on this tree. Claude-Session: https://claude.ai/code/session_01MoTv7pn338AZ71owsp19gQ Co-authored-by: Claude <noreply@anthropic.com>
维护者速读改了什么 —— 把「谁用契约复审档」从「所有车道都派、没有就等复审」收窄到两处:skills 席(三个协议文件加对外发布的 为什么改 —— 你今天的六条指示(PR 正文顶部逐字引用)。旧文本把 fable 当默认施工档和默认裁决档,各车道等复核等到饥饿(cli 席量到 8 张卡在等档位);实际风险集中在两个对外契约面( 风险与代价(含回滚) —— 代价:spec 席以外的条款②卡不再有契约复审档复核,靠该席默认档自审加 席位意见 —— 本席按契约复审档自审通过:diff 与卡上六条裁决逐行对得上;四个技能文件全在棘轮天花板上净零(812 / 151 / 60 / 72),决策框架块 md5 未动; 你要做的 —— 人工合并本 draft PR(受管面 Generated by Claude Code |
Fixes #17285
Model-tier policy after this PR: the contract-review tier is reserved for the skills seat (the three clause-① protocol files plus the published
skills/**catalogs) and for the spec seat's clause-② review; the triage seat and every other execution seat run the default tier and spawn no contract-review-tier subagent; adjudication (decision inbox, 代裁, 一类自裁) belongs to the maintainer-summoned director seat alone, at whatever tier the maintainer summons it — no tier hard gate. The seat's own prose uses the tier names the skill text already uses (契约复审档 =CONTRACT_REVIEW_TIER, 默认判断档 =TIER_DEFAULT); no model name enters any skill file, andscripts/pm/dispatch-gates.mjsstays the single value site of the constant (self-test pinned).裁决 — the maintainer's words, verbatim and untranslated (chat, 2026-09-10)
What the rule text says after this PR
skills/**catalogs; default tier forreferences/**and other governed one-liners as todaySeat reading recorded for veto: 「分诊席现在也是opus」 is read as covering the whole triage seat including its emergency-triage subagent (SKILL.md :332 below). If the maintainer meant the direct session only, that one line reverts.
Every changed line, before → after, next to the ruling it implements
Line numbers are on
origin/mainatebf9a489; identical to the card'sd64bcb63on this surface (git log d64bcb63..ebf9a489over the five files is empty). Every rewritten line was measured at ≤120 bytes, the ratchet's line cap..claude/skills/pm-dispatch/SKILL.md— 812 → 812 (ceiling 812)model的契约复审档子代理。」model的契约复审档子代理(逐份过转录核验),或达档总监席。」SKILL.md主文件、决策框架拷贝所在文件与.claude/agents/os-dev.md。」SKILL.md、决策框架拷贝所在文件、.claude/agents/os-dev.md与skills/**。」skills/**整根随npx skills add发运,⛔ 无一行级豁免,逐行判机械不作数。」--tier嫌疑行是提示非裁定;双肢命中任一 ⇒ 无席内契约复审档 PASS 在案 ⛔ 禁止入队。」--tier嫌疑行是提示非裁定;双肢命中任一 ⇒ 无席内条款②复核 PASS 在案 ⛔ 禁止入队。」/pm-dispatch director;⛔ 无 Routine 无 cron。」/pm-dispatch director;⛔ 无 Routine 无 cron。」CONTRACT_REVIEW_TIER,不达档只做免档整理并停放四职。」22f2339f0acb64cdb50c7adc9db681c3before and after..claude/skills/pm-dispatch/references/core-rules.md— 151 → 151 (ceiling 151), twins of the above per SKILL.md :44.claude/skills/pm-dispatch/references/contract-review.md— 60 → 60 (ceiling 60)Clause-②: yes | no按设计临时:只定是否必过契约复审档复核的保守方向,⛔ 非终审。」Clause-②: yes | no按设计临时:只定是否必过席内契约复核的保守方向,⛔ 非终审。」yes,锁契约复审档复核。」yes,锁席内契约复核。」yes挂标走契约复审档复核;⛔ 不建全量分类学与 claim 时决策程序。」yes挂标走席内契约复核;⛔ 不建全量分类学与 claim 时决策程序。」platform-readings.md。」platform-readings.md。」.claude/skills/pm-dispatch/references/lanes/director.md— 72 → 72 (ceiling 72)CONTRACT_REVIEW_TIER,dispatch-gates 常量单源,⛔ 本文不写模型名。」../contract-review.md。」../platform-readings.md;⛔ 不因档位拒裁停四职。」scripts/pm/dispatch-gates.mjs— tier constants, their docblock, the tier rendering, the self-testMANDATORY_TIER_GLOBSgains{ glob: 'skills/**', tier: CONTRACT_REVIEW_TIER, why: 'clause ① (2026-09-10 ruling, verbatim 「必须 fable的还包括对外发布的skills」): the published catalog ships verbatim to third parties by npx skills add objectstack-ai/objectstack/skills and npm create objectstack, so a wrong edit is installed elsewhere before anyone here reads it — and no one-line exemption applies under this root', oneLineExit: false }— ruling 2.oneLineExit: falseis the one path-shaped exit the ruling closes (a closed enumeration beats a per-line "is this mechanical" call); every other entry carries no flag (self-test pinned as an opt-out).skills/**catalog (ruling 2); the clause-② paragraph says default-tier build, contract-review-tier REVIEW in the spec seat only, other lanes' review = own default-tier review plus gates, triage and director spawn no contract-review-tier subagent (rulings 1, 3, 4, 6); the sanctioned-exits paragraph states the encodedskills/**exception; the measured-side-effect paragraph adds the re-measured count (47 tracked files underskills/onebf9a489, one already covered); the authority paragraph cites the 2026-09-10 widening.deriveTiercopiesoneLineExitonto each hit;tierLinesrenders the exits line without the one-line-class exit when any hit carriesoneLineExit: false(「⛔ NOT available for this surface … carries no one-line exemption」), and otherwise exactly as before. The two clause-② sentences of the rendering now say 「owes a contract-review-tier REVIEW too (spec seat; default-tier build)」 instead of 「is fable-mandatory too」 — the stale wording would have restated the superseded review scope in every claim comment.skills/objectstack-data/SKILL.md,skills/objectstack-ai/SKILL.md, a generatedreferences/_index.mdunder a published skill, the published PM skill covered by two entries at ONE tier,skills/**not reaching.claude/skills/**, the flag as data, the rendering with and without the exit, a mixed surface losing the exit for the whole card) and the CLI end to end (--tier skills/objectstack-data/SKILL.mdand--tier skills/objectstack-ai/SKILL.mdprint the mandate naming'skills/**'and refuse the exit;--tier .claude/skills/pm-dispatch/references/core-rules.mdprints no mandate).SUSPECT_TIER_GLOBS,TIER_FLOOR/TIER_DEFAULT, the constant's value.维护者速读(草稿)
改了什么
把「谁用契约复审档」从「所有车道都派、没有就等复审」收窄为两处:skills 席(三个协议文件加对外发布的
skills/**,施工与复核都用)与 spec 席的条款②复核。分诊席、engine/services/cli/devx/ui/hotcrm 执行席全部默认判断档,不再起契约复审档子代理。裁决(决策箱、代裁、一类自裁)只由您召唤的总监席出,档位由您逐场按项目定,不设档位硬门、不再有「不达档只整理不裁」的状态;分诊席不再有每 fire 代裁通道,置信门由五条改四条。dispatch-gates.mjs的--tier推导把skills/**整根列入强制档,并明确对它没有一行级豁免。为什么改
您 2026-09-10 的六条指示(正文顶部逐字引用):fable 只留给 spec 与 skills 车道,对外发布的 skills 必须 fable,分诊席用 opus,裁决由您以总监身份人工召唤且不需要 fable、简单元数据项目 opus 即可。现行规则文本与这六条冲突的每一行都在本 PR 一并改掉,主文件与核心条款、章程、细则四处同改,无一处留旧口径。
风险与代价(含回滚)
check-clause2-carriers/check-widening-tells门禁兜底;错误码新码等「恒 yes」的机械地板不变。git revert一次即回到旧口径;无发布物、无数据迁移。席位意见
(留空,由席位定稿时填写)
你要做的
人工合并本 draft PR(受管面:
.claude/**与scripts/pm/**,席位不翻 ready、不入队、不批准);若对 :332 的读法有异议,在 PR 上说一句,本席回滚该行后再合。Acceptance notes
.claude/**andscripts/pm/**are governed ⇒ draft only; no seat flips it ready, queues it, arms auto-merge or approves it. Changeset: none — neither.claude/**norscripts/pm/**is in any package's publishedfiles[](fast-track class per the os-dev clause); the PM appliesskip-changeset.skills/**no-exemption row after :510, the 唯一裁决者 row after :769) = 812/812; core-rules.md 151/151, all in place; contract-review.md −1 (:19 merged into :20) +1 (the fuse-population row after :50) = 60/60; director.md 72/72, all in place. No ceiling raised, none lowered. Every rewritten line measured ≤120 bytes (max seen 119 B) — the capcheck-skill-line-ratchetenforces on these files..md(check:pm-skill-id-lintgreen; the corpus convention — AGENTS.md header and the id-lint header — is that rules carry no ruling dates, so the 2026-09-10 date lives in the dispatch-gates docblock andwhystrings and in this PR, not in the rule lines; the dispatch's suggested wordings carried none either).grep -n -i "tier|contract-review|model|契约复审|达档|档位" skills/objectstack-pm-dispatch/SKILL.mdhits only the heading 「State model」 at :132;check:skill-frame-syncgreen (「binding sentence present in all 2; 4 count mention(s) agree; 76 markdown files scanned」). C holds —MANDATORY_TIER_GLOBSalready goes throughhintCovers, which collapses a final-segment**glob the same waySUSPECT_TIER_GLOBS'spackages/spec/src/**is matched; no second matcher, no helper change;skills/**measured not to reach.claude/skills/**(CLI and pure cases). D — dispatch-gates: STAGE-THEN-RUN reaches a program by an edge neither follow traverses — check:objectui-changeset inherits nothing from scripts/bump-objectui.sh #14290 (pm:on-hold, devx,Restart-touch: scripts/pm/dispatch-gates.mjs, STAGE-THEN-RUN resolution) is the declared intersection: this diff is a constant entry, a docblock, the tier rendering and self-test cases; literal/base resolution is untouched, and dispatch-gates: STAGE-THEN-RUN reaches a program by an edge neither follow traverses — check:objectui-changeset inherits nothing from scripts/bump-objectui.sh #14290 is not addressed here. E measured true —node scripts/pm/dispatch-gates.mjs --self-testoutlived the 600 s foreground cap and finished detached: verdict line 「✓ dispatch-gates self-test: 1639 cases pass.」 (exit 0, treeec15afa1);pnpm check:pm-dispatch-gateswas then run detached per its own header, verdict quoted below. F — every count re-derived: 置信门 五 → 四 at SKILL.md :397 and core-rules :98 (the only two places that count them;grep -rn 置信门五条is now empty); 四职 unchanged; 一类自裁门 三判据 unchanged; the clause-① file set is stated by enumeration, not by count.dispatch-gates.mjs,tierLinesis edited beyond the exits line: the two clause-② sentences, for the reason given above. (3) The dispatch's gate spellingscheck:skill-line-ratchet,check:doc-links,check:control-bytesandcheck:doc-fence-languagesdo not exist inpackage.json; the ratchet ischeck:pm-skill-ratchet, the control-byte gate ischeck:nul-bytes, and the doc gates in the derived list arecheck:doc-authoringand the@objectstack/lintcheck:doc-formula-expressions. The derived 39-command list was run instead. (4)node scripts/pm/check-governed-queue-guard.mjs --testdoes not exist — that script readsGITHUB_EVENT_PATHand exits 1 「could not read」 without it; the seat-side predicate is the siblingcheck-governed-merges.mjs --test, verdict quoted below.--tieracceptance (stdout, exit 0 each):skills/objectstack-data/SKILL.mdandskills/objectstack-ai/SKILL.md→ 「Model tier — MANDATORY: … - PATH ⇢ 'skills/' — clause ① (2026-09-10 ruling …」 with the exits line 「the one-line-class mechanical-edit downgrade is ⛔ NOT available for this surface — 'skills/' carries no one-line exemption …」;.claude/skills/pm-dispatch/references/core-rules.md→ 「Model tier — no path-derived mandate: the surface hits none of the 4 declared glob(s)」;skills/objectstack-pm-dispatch/SKILL.md→ two hits (its own entry andskills/**) at one tier, no ambiguity refusal;.claude/skills/pm-dispatch/SKILL.md→ the exits line unchanged from before (one-line-class exit still offered).ec15afa1(list derived withnode scripts/pm/dispatch-gates.mjs --commandsfrom the merge-base change set, 39 commands, identical to the pre-edit derivation over the five paths); verdict lines quoted from each gate's own output, exit codes captured before any pipe:pnpm -s check:pm-skill-ratchetexit 0 — 「✓ check-skill-line-ratchet: declared cross-file moves: 1, total ceilings down 9 lines.」pnpm -s check:skill-frame-syncexit 0 — 「binding sentence present in all 2; 4 count mention(s) agree; 76 markdown files scanned for undeclared copies.」pnpm -s check:skill-compatibilityexit 0 — 「✓ check-skill-compatibility-version: 11 SKILL.md file(s) reconciled against 80 workspace packages」pnpm -s check:pm-skill-id-lintexit 0 — 「✓ check-skill-id-lint: 27 file(s) clean (pattern /#[0-9]{3,}/g).」pnpm -s check:nul-bytesexit 0 — 「check-nul-bytes: OK (scanned 8132 text file(s) … no raw ASCII control bytes).」pnpm -s check:pm-governed-proseexit 0 — 「✓ check-governed-prose: 2 instruction surface(s) name all 5 registered governed surfaces」pnpm -s check:pm-governed-mergesexit 0;pnpm -s check:doc-authoringexit 0;pnpm -s check:agent-test-spellingexit 0;pnpm -s check:bash32-floorexit 0;pnpm -s check:cli-command-idsexit 0;pnpm -s check:declared-population-liveexit 0 — 「241 of 291 famil(ies) declare a path population, and every one of them reaches this tree's 8139 tracked files」;pnpm -s check:entry-guardexit 0;pnpm -s check:parse-guardexit 0;pnpm -s check:watch-hint-literalexit 0 — 「69 declaration(s) across 4 rostered name(s)」;pnpm -s check:ratchet-remedy-authorityexit 0;pnpm -s check:refd-timer-probeexit 0;pnpm -s check:pnpm-filter-targetsexit 0;pnpm -s check:cross-package-test-inputsexit 0;pnpm -s check:driver-memory-censusexit 0.check-ci-filter-parity,check-closing-keyword-parity(+--self-test, 「24 assertions, 5 mutations … driven to red」),check-comment-mask-corpus(「6466 files, 0 disagree, 0 unparseable」),check-declaration-mirrors(+ self-test),check-scripts-symbol-anchors(+ self-test),check-self-test-wired(+ self-test, 「every one of the 199 script(s) CI runs that ship a --self-test has that self-test run by CI」),check-self-test-workflow-commands(+ self-test),check-whole-set-label-write(+ self-test),scripts/pm/check-governed-queue-guard.mjs --self-test(「144 cases pass」),report-test-timings.mjs --self-test(「61 cases across 4 batteries」),packages/lint/scripts/check-reference-carrier-shape.mjs(+ self-test, 「6466 file(s) scanned, 649 reference site(s)」).node scripts/pm/dispatch-gates.mjs --self-testexit 0 — 「✓ dispatch-gates self-test: 1639 cases pass.」 (detached; includes the 15 new cases, each found as ✓ by name in the log).pnpm check:pm-dispatch-gates— run detached per its own header (PID recorded, waited on withtail --pid, 03:47Z → 04:00Z); its log ends 「✓ dispatch-gates self-test: 1639 cases pass.」 and carries neither of the wrapper’s failure prints (「✗ check:pm-dispatch-gates: … was killed by …」 / 「could not run …」) — the wrapper prints nothing of its own on success and exits with the battery’s status; the detached process’s exit code itself was not captured.pnpm --filter @objectstack/lint run check:doc-formula-expressions— first run exit 3 「PREREQUISITE NOT MET — the workspace package @objectstack/formula is not built」 (nothing measured); afterpnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lint --concurrency=2throughscripts/pm/os-verify-lock.sh(「os-verify-lock: VERDICT command-exit 0 · held the lock 191s (3m11s) · waited 0s」, turbo 「Tasks: 4 successful, 4 total」): exit 0 — 「✓ check:doc-formula-expressions: 22 record-scoped formula example(s) across 440 files / 1374 TS blocks judged clean by @objectstack/formula.」, plus the spec-TSDoc line (「9 @example(s) judged clean across 1317 packages/spec/src files」) and the field-level line (「14 predicate(s) … judged clean; 6 skipped as undeterminable」), all ✓.node scripts/pm/check-governed-merges.mjs --testover the five files — exit 3 — 「governed-surface predicate: 4 of 5 path(s) hit the register (5 surfaces, repo-agnostic). ⛔ GOVERNED — a human merge is the review record for this PR」; hits.claude/** ×4;scripts/pm/dispatch-gates.mjsis not on the register but the PR is governed whole on the four hits.node scripts/pm/dispatch-gates.mjs --ranreconciliation — exit 0 — 「✓ dispatch-gates --ran: 39 derived famil(ies) accounted for — 39 run, 0 NOT-MEASURED.」 (the record is spelled as the derivation prints it; the runs usedpnpm -s, which only silences pnpm’s banner — a first reconciliation with the-sspelling reported those 19 rows UNRUN, which is the record’s spelling, not a missing run).origin/mainadvanced toa256f189during this run (the skills seat’s other PR, onskills/objectstack-ai/SKILL.md— disjoint from this diff;git diff --name-only ebf9a489 origin/mainover this surface names only that file). The branch stays onebf9a489; nothing to merge.pnpm lint/pnpm test(CI's; no package source is touched, so no build closure and no package tests are owed); the two CI-only families and the Test Core job steps the derivation lists as NOT MEASURED..claude/agents/os-dev.md;skills/objectstack-pm-dispatch/SKILL.md(assumption B held);references/lanes/triage.md;references/lanes/spec.md(:25 stays a pointer to SKILL.md 模型分档); the decision frame block; anything indispatch-gates.mjsbeyond the tier constants, their docblock, the tier rendering and the self-test.references/lanes/skills.md:20(「pm-dispatch 根恒契约复审档」) andreferences/lanes/cli.md:18stay true but do not mention theskills/**widening — both defer to--tier, which now carries it.Session: https://claude.ai/code/session_01MoTv7pn338AZ71owsp19gQ
Generated by Claude Code
Generated by Claude Code