Skip to content

pm-dispatch(p0): a lane's p0 is dispatched in the same round past every cap and lower-priority work pauses; finder stops the bleed, then escalation, then triage stop-bleed; main red and deterministic queue red are p0 at first touch; full-run card filed p0 - #27266

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-27047-p0-dispatch-at-once
Oct 28, 2026

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #27047
Clause-②: no
Metadata-protocol: none

维护者速读

What changes

Item by item against the card's Wanted 1–6 (the ruled text; nothing beyond it, no new gate). Line numbers below are post-change unless marked origin/main.

  1. p0 dispatches at once, in its own lane. references/execution-duties.md 〈候选与批次〉 L51 (new): on every round and every wake the lane seat's first read is its open priority:p0; an unclaimed one is claimed and dispatched in that same round, never the next.
  2. No concurrency cap holds a p0. SKILL.md priority:p0 row (L119) rewritten in place: same-round dispatch past batch, the depth wait (LOCK_DEPTH_HOLD) and every concurrency cap; the row's ⛔ loses 深度等待 and keeps 同文件串行与认领协议. execution-duties.md L25: p0 crosses the depth wait too (the old text forbade exactly that).
  3. When there is no room, other development pauses. execution-duties.md L26–27 (new): no slot, or a lower-priority in-flight card holding the same files ⇒ pause the lowest-priority in-flight dev that frees the room — stop its session, hold the PR draft, claim untouched; the card gets a Paused-for: line naming the p0; nothing discarded, reverted or force-pushed; when the p0 lands the dev is revived on the same claim and branch (the 〈派发〉 revive rule: SendMessage first, takeover protocol only if unreachable). The SKILL.md row says this in five characters (无槽即暂停…腾位) and points at execution-duties for the mechanics. The card's ⚠️ reading ("pause" = stop the session and hold the draft) is what the text says.
  4. An unclaimed p0 escalates. references/landing-operations.md 约定③ (L82): one triage round (~60 min) unclaimed ⇒ triage and the director name the card and the owning lane in that round's report.
  5. Main red and merge-queue red are p0 at first touch. references/triage-duties.md L30 (new): a full red on main and a deterministic merge-queue red are graded p0 at first touch — the anchor, the root-cause card and the generated full-run card; a flake anchor becomes p0 only once read as deterministic (the card's ⚠️: a queue-flake-anchor is a name, not a diagnosis). Generator: scripts/ci/scheduled-full-run.mjs cardIdentity().labels priority:p1 → priority:p0. That constant is the live filing path (createIssue({ labels: identity.labels }), called through scheduled-full-run-card.mjs fileCardStep, which .github/workflows/scheduled-full-run-card.yml runs). Its pin, scheduled-full-run-card.mjs L217 (the self-test's expected issues.create params), follows; so does the self-test board fixture CARD_LABELS (scheduled-full-run.mjs L1699), which lint.yml executes through --self-test and whose battery asserts only that a refresh never touches the grade labels.
  6. Finder stops the bleed → escalation → triage stop-bleed. landing-operations.md: 约定① (L76) gains its non-mechanical branch (L80, 6a — the finder names the owning lane on the anchor and rings its mailbox with Request: main-red; the root-cause card stays with that lane; the mechanical branches — revert, or a verified-root-cause fix — were already L78–79); 约定③ (L82–84, 6b–c): still unclaimed by the round after the escalation ⇒ triage posts the standard claim line and dispatches ONE os-dev for the stop-bleed only; one per round, triage does not become a development lane; the stop-bleed PR's review is the lane seat's or the director's, never triage's; Tier H still waits on the governed approver; a lane seat arriving takes the card back through the claim line (the one-writer protocol). triage-duties.md L31 (new) carries the triage-side duty and points at 约定③. SKILL.md 红线 L35 (new): the line 「⛔ 分诊席永不认领、派发或写码」 gains its one exception (an unclaimed p0 anchor: round report after one round, triage stop-bleed only after another; one per round; review not triage's) — without it SKILL.md 〈优先级〉 (红线 outrank 细则, and two conflicting rules resolve to the stricter one) would make item 6c dead text. This is the card's own 「amends the earlier 『你只处理分诊』 for this one case only」, written where that rule lives.

Acceptance line of the card: a reader of SKILL.md alone now learns that a p0 is dispatched in the same round, past batch, the depth wait and every concurrency cap, and that lower-priority dev work pauses to make room (L119), and that triage's only claim/dispatch is the unclaimed-p0 stop-bleed (L35).

Line budget — every edited line, bytes, and the home of every deleted line

Ceilings (scripts/pm/check-skill-line-ratchet.mjs CEILINGS): SKILL.md 319, execution-duties 188, landing-operations 101, triage-duties 102 — every one at headroom 0 on origin/main 9ff8154. The order read triage-duties' ceiling as 103 with one line of headroom; the ledger says it was lowered 103 → 102 when the whole-card cloud route merged, so that file paid for both of its new lines. Every new line is paid by deleting a line whose content has a home elsewhere (named per line); no re-wrap is used as currency; every prose line is ≤120 bytes (wc -c without the newline); the one edited table row is metered by SKILL.md's widest-table-row pin (341 B, still L160), which is the rule for table rows (classifyLine exempts them from the 120-byte line rule). Line numbers in this section are origin/main's.

.claude/skills/pm-dispatch/SKILL.md — 319 → 319

  • after L34 inserted (111 B): - 唯一例外:无主 p0 锚卡一轮即轮报、再一轮分诊只代派止血:每轮一张,复核非分诊。
  • L118 rewritten in place (124 B → 239 B; a table row — the file's widest row stays L160 at 341 B = the pin). Cell before: 插队:可超 \batch`、破轮次立即派发;⛔ 不豁免同文件串行、深度等待与认领协议. Cell after: 插队:同轮立即派发,越过 `batch`、深度等待(`LOCK_DEPTH_HOLD`)与一切并发上限;无槽即暂停低级在飞 dev 腾位(机制 `references/execution-duties.md`);⛔ 不豁免同文件串行与认领协议`.
  • L126 deleted (107 B): - hold 放行须双查:只放最近一次转换评论的条件,其后卡上有更新的 merged PR 即拒。 — home: references/state-machine.md L19 (the same rule, verbatim: 「放行双查皆机械:只放最近一次 hold/blocked 转换评论的条件;其后卡上有新 merged PR 即拒」); SKILL.md L125 already points there for hold/blocked detail.

references/execution-duties.md — 188 → 188

  • L25 rewritten in place (118 B → 117 B): tail \priority:p0` 可超 `batch`,⛔ 不越过深度等待。→p0 越过 `batch`、深度等待与一切并发上限。` (head unchanged).
  • after L25 inserted (117 B): - p0 无槽或低级在飞同文件挡住 ⇒ 暂停腾位的最低级 dev:停会话、PR 留 draft、认领不动。
  • after L25 inserted (119 B): - 卡记 \Paused-for: #P0`,⛔ 不丢弃、不回退、不 force-push;p0 落地即复活该 dev,同认领同分支。— the file spells the placeholder the way the corpus spells#` placeholders (angle brackets around p0); it is rendered here without them so this body survives the platform's sanitizer.
  • after L48 inserted (112 B): - 每轮每次唤醒首读本车道开着的 \priority:p0`,无人认领即同轮认领派发,⛔ 不等下轮。`
  • L69 deleted (113 B): - \Metadata-protocol:` 四值与定级表住 AGENTS.md「Post-Task Checklist」③:定级只随元数据协议。— home: SKILL.md 〈模板与表〉Metadata-protocol:` template line (L313, "the level table is AGENTS.md's Post-Task Checklist step 3") and AGENTS.md Post-Task Checklist ③ ("The level follows the kind alone").
  • L74 deleted (119 B): - 档位引 \dispatch-gates --tier --repo 仓`⛔ 不凭记忆;天花板拼常量名并同行引据,⛔ 不抄模型 id— home: SKILL.md 〈模板与表〉Container & model:template line (L311: 引当次--tier输出;天花板拼CONTRACT_REVIEW_TIER`,同行引其 MANDATORY 路径行或 reason;⛔ 不抄模型 id).
  • L138 deleted (116 B): - 派发令写明 dev ⛔ 不另留认领:PM 那条即身份;核对最新一条点名本分支,不符停手回报。 — home: AGENTS.md 〈Claim the issue BEFORE you write any code〉 ("A dispatched executor … verifies that the newest Claim: names its branch (on a mismatch it stops and reports), posts no second claim") and .claude/agents/os-dev.md 规则 2 (身份位是认领评论里的分支); the line also contradicted L125 of the same file (standard clauses already in os-dev.md are not copied into dispatch orders).

references/landing-operations.md — 101 → 101

  • L7 deleted (108 B): - fork PR = 提案,席位永不放行;采纳 diff 内部落地,见 \references/external-contributions.md`。— home: AGENTS.md Prime Directive 14 ("A fork PR … is a proposal, never a delivery … the owning seat adopts the diff onto an internal branch and lands that") andreferences/external-contributions.md` (its title and ③).
  • L8 deleted (105 B): - \pm:mailbox` 信箱 PR 不欠 CI、永不入队;落地台账与孤儿 PR 查询一律排除该标签。— home:references/project-forms.md` 〈信箱 PR〉 L38 (the same rule, verbatim).
  • L51 deleted (119 B): - 直敲 \node scripts/pm/fleet-write/dispatch.mjs --repo OWNER/NAME --actions-file F`,⛔ 套壳:许可逐字匹配。— home:references/rest-channel.mdL49 (the spelling of the relay call) and L13 (prefixes and wrappers fall to the classifier); L50 of this file still sends the reader torest-channel.md` for the spelling.
  • L74 deleted (111 B): - 会话席窗口内 PR 须在挂 \subscribe_pr_activity`,缺即补;⛔ 不早于报告,Routine 座位轮询。— home:references/execution-duties.md` 〈收集〉 L156 (subscribe the moment the report names the PR; relay-opened PRs are not auto-attached, so the seat adds it) and L157–158 (Routine seats poll on their patrol interval).
  • after L83 inserted (109 B): - 止血非机械 ⇒ 锚卡点名归属车道、敲其信箱 \Request: main-red`;根因卡恒归该车道。`
  • after L84 inserted (113 B): - 约定③:锚卡一轮分诊(~60 分钟)无人认领 ⇒ 分诊与总监当轮轮报点名卡与归属车道。
  • after L84 inserted (119 B): - 再一轮无人认领 ⇒ 分诊贴标准认领行、派一个 os-dev 只做止血;每轮一张,分诊不成车道。
  • after L84 inserted (113 B): - 止血 PR 复核归车道席或总监,⛔ 非分诊;Tier H 仍等审批人;车道席到场经认领行交回。

references/triage-duties.md — 102 → 102

  • L5 deleted (119 B): - 发版板、pin 链归总监席摘要,细则见 director.md;活性复查同归,细则留本文;⛔ 无代裁通道。 — home: references/lanes/director.md 职责四 L71–75 (daily summary, release board, and L74 names the liveness re-check as part of it, pointing back here for the detail) and L80–81 (the cross-repo platform-version bump cards, i.e. the pin chain); SKILL.md 红线 L30 (⛔ 无代裁通道) and the director row of 〈入口与角色〉 (三职与章程见 director.md).
  • after L30 inserted (119 B): - 主干全量红与确定性队列红首触定 p0(锚卡、根因卡、full-run 卡);flake 锚卡判确定性才升。
  • after L30 inserted (114 B): - 无主 p0 锚卡一轮即轮报,再一轮本席贴认领行只代派止血(\landing-operations.md` 约定③)。`
  • L78 deleted (100 B): - retriage 的异议判据认内容(有评论写明所求)⛔ 不认形状(有一条异议评论)。 — home: references/state-machine.md L39–40 (pm:retriage: the objection comment carries evidence plus the answer sought and a bare label is illegal; triage answers what is sought before removing the label).

scripts/ci/ — the label constant and its pins (no line count change)

  • scheduled-full-run.mjs L366 labels: ['bug', 'domain:devx', 'priority:p1'] → 'priority:p0' inside cardIdentity() — the live filing path (createIssue({ … labels: identity.labels }) at L488; fileCardStep in scheduled-full-run-card.mjs calls it; scheduled-full-run-card.yml runs that step).
  • scheduled-full-run.mjs L1699 const CARD_LABELS = ['bug', 'priority:p1', 'domain:devx'] → 'priority:p0' — the self-test's board fixture for the "card refresh: a stale pm:blocked" battery, executed by --self-test (lint.yml), not by the workflow. Its assertions are grade-agnostic (a refresh never writes the grade labels); the fixture now models a card as the generator files it.
  • scheduled-full-run-card.mjs L217 labels: ['bug', 'domain:devx', 'priority:p1'] → 'priority:p0' — the expected issues.create params in that module's self-test, i.e. the pin of L366 (it went red with L366 alone, green with both).

Tests

Derived union (node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, no paths, change set from the merge base 9ff8154 of origin/main and HEAD 7b401bf): 43 commands, each run in the foreground on the final head with its exit code captured before any pipe (cmd > log 2>&1; ec=$?); 1 non-zero. Reconciliation: dispatch-gates --ran exit 0 — 43 derived families accounted for: 42 run, 1 NOT-MEASURED (derived from the recorded exit 3), 0 UNRUN. The NOT-MEASURED one is pnpm --filter @objectstack/lint run check:doc-formula-expressions: PREREQUISITE NOT MET — @objectstack/formula and @objectstack/lint are not built in this worktree (its fix line pnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lint would build spec, sdui-parser, formula and lint, a closure this docs-and-constant diff does not owe); nothing was measured by it locally, and CI's Lint & Repo Gates runs it on a built tree.

Every command, exit code and its own verdict line
  • node scripts/check-closing-keyword-parity.mjs — exit 0 — • ui/packages/app-shell/CHANGELOG.md -- 2962537 bytes exceeds the sweep's 2097152-byte cutoff for UNREGISTERED files
  • node scripts/check-closing-keyword-parity.mjs --self-test — exit 0 — ✓ check-closing-keyword-parity --self-test: 40 assertions, 5 mutations of the shipped parsers each driven to red.
  • node scripts/check-comment-mask-corpus.mjs — exit 0 — ✓ comment-mask corpus sweep [scripts/js-comment-mask.mjs]: 18783 files, 0 disagree, 0 unparseable, 156.6s (comparator self-test: 26 cases pass).
  • node scripts/check-declaration-mirrors.mjs — exit 0 — (Parameter and return TYPES are not asserted — see this file's header.)
  • node scripts/check-declaration-mirrors.mjs --self-test — exit 0 — All 29 self-test cases passed.
  • node scripts/check-self-test-wired.mjs — exit 0 — scope: 313 file(s) under scripts/, 259 carrying '--self-test' in code (comments masked, 0 of them package-local gate(s) CI names by path); 242 of those are run by 30 workflow(s) and 3 composite action(s); 239 have thei
  • node scripts/check-self-test-wired.mjs --self-test — exit 0 — check-self-test-wired --self-test: 3 live ledger row(s) verified, plus the comment mask, the right boundary, alias resolution, the declared-alias population and both audit directions — 12 declared batteries, 96 cases reg
  • node scripts/check-self-test-workflow-commands.mjs — exit 0 — scope: 242 script(s) CI runs ship a '--self-test' (0 of them package-local gate(s) CI names by path, present because this population is the one check-self-test-wired.mjs exports rather than a second walk taken here); 3
  • node scripts/check-self-test-workflow-commands.mjs --self-test — exit 0 — check-self-test-workflow-commands --self-test: both measured parse rules pinned (legacy form anywhere in a line, current form only at line start), the innocent-output and Perl-namespace cases, the comment mask in both di
  • node scripts/check-whole-set-label-write.mjs — exit 0 — ⚠️ The EXECUTABLE population is empty: all 10 mention(s) are comments, in
  • node scripts/check-whole-set-label-write.mjs --self-test — exit 0 — ✓ check-whole-set-label-write --self-test: all cases pass (24 fixture trees + 5 refusals + 1 allowlist hatch)
  • node scripts/ci/plan-test-core-shards.mjs --self-test — exit 0 — ✓ plan-test-core-shards self-test: 23 case(s) across 5 batteries.
  • node scripts/ci/scheduled-full-run-card.mjs --self-test — exit 0 — ✓ scheduled-full-run-card --self-test: 7 cases over the card step's API plumbing.
  • node scripts/ci/scheduled-full-run.mjs --self-test — exit 0 — scheduled-full-run: self-test OK
  • node scripts/pm/bare-root-worklist.mjs --self-test — exit 0 — OK self-test: 75 live row(s), 52 unreachable as spelled, 41 recorded verdict(s) — none stale, none missing, none contradicted (12 row(s) whose gate carries the dispatch-gates wide-population declaration, the deliberate-
  • node scripts/pm/check-governed-queue-guard.mjs --self-test — exit 0 — ✓ check-governed-queue-guard self-test: 401 cases pass (register-driven verdicts, the queue/PR event split, latest-decisive approval reduction, the 2026-09-04 authorized-approval-on-ANY-commit predicate on the queue leg
  • node scripts/pm/check-harness-current.mjs --self-test — exit 0 — check-harness-current --self-test: all 26 cases passed.
  • pnpm --filter @objectstack/lint run check:doc-formula-expressions — exit 3 —  ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL  @objectstack/lint@18.2.0 check:doc-formula-expressions: 'node scripts/check-doc-formula-expressions.mjs --self-test && node scripts/check-doc-formula-expressions.mjs'
  • pnpm check:agent-test-spelling — exit 0 — turbo dogfood shard; those are the cleared ones. Non-vacuity is carried by --self-test,
  • pnpm check:bash32-floor — exit 0 — ✓ check-bash32-floor: 31 tracked shell file(s) under scripts/, .claude/hooks/, .githooks/** name no bash 4+ construct outside a comment, a guarded ${VAR:-} read, or a non-command position.
  • pnpm check:ci-filter-parity — exit 0 — ✓ check-ci-filter-parity --self-test: 120 assertions — both coverage limbs and the extglob bound, the same-root-different-file case observed failing and then covered by naming the file, a glob covered by 'core', one cove
  • pnpm check:cli-command-ids — exit 0 — ✓ check-cli-command-ids: 73 module(s) under packages/cli/src/commands examined, all of them default-export a class whose inheritance chain reaches oclif's 'Command' (0 declared exemption(s)).
  • pnpm check:cross-package-test-inputs — exit 0 — All 261 self-test cases passed.
  • pnpm check:doc-authoring — exit 0 — ✓ doc authoring guard: sibling-package prose ids hold the baseline — 0 pinned site(s) across 0 file(s), 112487 string(s) read in 1564 parsed source(s) (seen floor 40000 strings / 600 sources), no growth, no burn-down unr
  • pnpm check:driver-memory-census — exit 0 — OK self-test: classifies every module-binding form (import / export-from / dynamic import / import-type / require / vi.mock) as a DECLARATION and every other string occurrence as a MENTION (a bundler externals entry, a
  • pnpm check:entry-guard — exit 0 — ✓ check:entry-guard: 284 scripts/ file(s) — every entry guard goes through invoked-as.mjs; 233 export bindings, 233 of them inert on import (0 known-unsafe, ⛔ SHRINK-ONLY).
  • pnpm check:gitlink-declared — exit 0 — ✓ check-gitlink-declared --self-test: 36 assertions over throwaway git repos (real scan() path)
  • pnpm check:nul-bytes — exit 0 — ✓ check-nul-bytes --self-test: 75 assertions over a temp git repo (real scan() path)
  • pnpm check:parse-guard — exit 0 — ✓ check:parse-guard: 283 scripts/ file(s) — every TypeScript parse goes through ts-parse.mjs.
  • pnpm check:pm-dispatch-gates — exit 0 — ✓ dispatch-gates self-test (fast tier): 1935 cases pass; 7 slow section(s) deferred.
  • pnpm check:pm-expected-skips — exit 0 — ✓ check-expected-skips self-test: 206 cases pass (the exit register; the gate recogniser — top-level splitting, each term kind read and every near-miss spelling refused; the derivation on a frozen fixture tree, admitting
  • pnpm check:pm-governed-merges — exit 0 — ✓ check-governed-merges --self-test: 537 assertions (the unified governed predicate + near misses, subject→PR spellings, window parsing, the finding(check-governed-merges): the merge queue's build-to-land skew can put a governed landing BELOW a round's --since boundary, where it is silently absent from the audit list #12633 landing window — the QS-7 regression pin in both directions, the topolog
  • pnpm check:pm-governed-prose — exit 0 — ✓ check-governed-prose: 2 instruction surface(s) name all 13 registered governed surfaces that govern objectstack (docs/adr/** · .claude/** · skills/** · AGENTS.md · CLAUDE.md · docs/NORTH-STAR.md · .github/workflows/**
  • pnpm check:pm-half-states — exit 0 — ✓ check-half-states self-test: 5034 cases pass. Batteries: H66 released queue card 182/172, H19 judged-set founding 37/34, H65 tier declaration spelling 46/42, H67 queued merged-delivery reading 152/142, H2/H47/H66 decor
  • pnpm check:pm-label-write — exit 0 — ✓ label-write self-test: 134 cases pass across 11 batteries — the union/difference arithmetic, the ONE-OF refusal, the idempotent DELETE, the stripped-underneath re-add-and-report, the mismatch exit, the rate-limit non-f
  • pnpm check:pm-skill-id-lint — exit 0 — ✓ check-skill-id-lint: 104 file(s) clean (pattern /#[0-9]{3,}/g).
  • pnpm check:pm-skill-ratchet — exit 0 — ✓ check-skill-line-ratchet: declared cross-file moves: 3, total ceilings down 494 lines.
  • pnpm check:pnpm-filter-targets — exit 0 — ✓ check:pnpm-filter-targets: 212/287 '--filter' occurrence(s) across 43 file(s) resolve against 129 workspace package(s); 75 not judged (11 foreign, 32 interpolated, 32 path); 52 more in comments or step labels and 59 in
  • pnpm check:pnpm-flag-spellings — exit 0 — ✓ check-pnpm-flag-spellings: no rejected pnpm flag spelling in 623 tracked file(s).
  • pnpm check:refd-timer-probe — exit 0 — ✓ check-refd-timer-probe self-test: 11 cases pass, negative controls included.
  • pnpm check:scripts-symbol-anchors — exit 0 — ✅ check-scripts-symbol-anchors --self-test: every finding class provoked, comment-prose projection wired, declined shapes counted not missed, allowance rows exact both ways, population live (4043 live anchors)
  • pnpm check:skill-frame-sync — exit 0 — ✓ check-skill-frame-sync: the one declared copy of the decision frame is internally coherent (.claude/skills/pm-dispatch/SKILL.md; no second copy to compare — the cross-copy comparison is discharged until a second COPIES
  • pnpm check:watch-hint-literal — exit 0 — ✓ check-watch-hint-literal: 74 declaration(s) across 4 rostered name(s) -- ROOT_DIR_WATCH_HINTS 49, ROOT_FILE_WATCH_HINTS 13, ROOT_WATCH_HINTS 3, DECLARED_WATCH_HINTS 9 -- every one an array of quoted literals inside its

Run before the union, on the same tree (also captured before any pipe): pnpm check:pm-skill-ratchet exit 0 (SKILL.md 319/319 · execution-duties 188/188 · landing-operations 101/101 · triage-duties 102/102 · SKILL.md widest table row 341 B = pin); pnpm check:pm-skill-id-lint exit 0 (104 files clean); pnpm check:pm-governed-prose exit 0; pnpm check:skill-frame-sync exit 0; pnpm check:skill-frame-freshness exit 0 (local-only family; the frame is current with origin/main); node scripts/ci/scheduled-full-run.mjs --self-test exit 0; node scripts/ci/scheduled-full-run.mjs --check-concurrency exit 0; node scripts/ci/scheduled-full-run-card.mjs --self-test exit 0 (7 cases); pnpm check:pm-half-states exit 0 (5034 cases); pnpm check:pm-dispatch-gates exit 0 (1935 cases, 346 s).

Reverse verification of the label pin (a one-off, not kept; mutation and restore scripted under a restore trap): scheduled-full-run-card.mjs L217 mutated back to priority:p1 on disk (grep: p0 1 → 0, p1 0 → 1) with scheduled-full-run.mjs L366 at priority:p0 ⇒ node scripts/ci/scheduled-full-run-card.mjs --self-test exit 1, 5 failures, each an expected-vs-actual mismatch on the issues.create params; restored with git checkout HEAD -- scripts/ci/scheduled-full-run-card.mjs, git diff HEAD empty and the file's blob hash equal to HEAD's (25f07fee…); with both at p0 the self-test is green (7 cases) — L217 is the pin of L366. The line ratchet turned red at triage-duties 103/102 after the first draft of that file and green once the second paid line was deleted — the ceiling is enforced where the order expected headroom.

Not run locally, by the role file's scope: no package build or test (no package touched); pnpm lint and the full check:* farm belong to CI (Lint & Repo Gates on this PR). Ablation: none owed — no tested behaviour changed; the only code change is a label constant whose self-test pin is cited above.

Acceptance notes

  • scripts/pm/ensure-pm-labels.sh creates priority:p0 with the description "Queue-jump: outranks batch and breaks the round — never exempts claiming or same-file serial" — still true (it never mentioned the depth wait); not touched, out of this card's file surface.
  • scripts/pm/check-half-states.mjs H10 already patrols a stale unclaimed p0 (report-only, threshold-based). Item 4/6b now names the ~60-minute triage round in the protocol; no patrol row is added or changed (the order's hypothesis 2: report-only patrols are a separate decision). Paused-for: is likewise not a patrol-recognised line.
  • The card's "Contributing cause" names scheduled-full-run.mjs:1699 as a site that files the card; it is the self-test's fixture, not a filing site. The live site is cardIdentity() at L366. Both changed (above), so the correction has no effect on the fix.
  • scheduled-full-run.mjs L1713 quotes a triage comment verbatim ("The card keeps its p1 …"); it is a historical record inside a fixture and is left exactly as measured.
  • Order hypotheses, measured: (1) the SKILL.md row is a table row and is metered by the widest-row pin (341 B), not the 120-byte rule — the rewrite is 239 B; landing-operations needed four new lines for 6a–c (not two or three) and paid four; triage-duties had no headroom (ceiling 102) and paid two. (2) state-machine.md's Restart-when: is bound to pm:on-hold (two legal spellings, H9), and Blocked-by: moves the six-state and releases the assignee on unlock — neither fits a paused pm:dispatched card whose claim must hold, so the resume line is Paused-for: on the card, as the hypothesis's fallback says. (3) L366 is on the workflow path and L1699 on the self-test path; both execute, both changed, L217 pins L366. (4) confirmed as written. (5) the derived union is in Tests.
  • Two edits sit beyond the order's named lines but inside the card's items: the SKILL.md 红线 exception line (item 6c's amendment of 「你只处理分诊」, needed so 〈优先级〉's stricter-rule resolution does not void 6c) and the triage-duties pointer line (item 6c's triage-side duty; triage-duties.md declares itself the triage seat's complete duties). Both paid in place.
  • Queued behind this PR on shared files per the claim: the two PRs the claim names touch other lines of these files and will need a rebase after this lands; nothing here depends on them.

Verification

  • Branch claude/issue-27047-p0-dispatch-at-once, head 7b401bf on origin/main 9ff8154; one commit; no changeset (.claude/** and scripts/ci/** publish nothing — skip-changeset declared at pr_create).
  • Local verification scope per the role file: no package is touched, so no build closure (①) and no package test (②) is owed; ③ is the derived union below, every exit code captured before any pipe, reconciled with dispatch-gates --ran; ④ CI families are read from this PR's check-runs by the seat (Lint & Repo Gates carries every check:* family here), not re-run locally.
  • Tier: .claude/** is Tier S — the owning seat runs the contract review at CONTRACT_REVIEW_TIER and lands it; this PR stays draft until that record exists. No workflow was run or dispatched; the two scripts/ci modules were exercised only through their offline --self-test.

Generated by Claude Code

…ry cap; finder stops the bleed, escalation, triage stop-bleed; main red is p0 at first touch

SKILL.md: the `priority:p0` state-table row now says same-round dispatch past
`batch`, the depth wait (`LOCK_DEPTH_HOLD`) and every concurrency cap, with
lower-priority in-flight dev work paused to make room; the triage red line
gains its one exception (an unclaimed p0 anchor's stop-bleed, one per round,
review not triage's). Paid by the hold double-check line, which is state-
machine.md's verbatim rule.

execution-duties.md: p0 crosses the depth wait too; the pause mechanics
(stop the dev session, hold the PR draft, claim untouched, `Paused-for:` line,
restart when the p0 lands); the lane's first read on every round and wake is
its open p0. Paid by three lines restated in SKILL.md's claim template,
AGENTS.md and os-dev.md.

landing-operations.md: main-red 约定① gains the non-mechanical branch (name the
owning lane on the anchor, ring its mailbox); 约定③ = one round unclaimed →
round report; another round → triage dispatches the stop-bleed only, with the
one-writer, independence and one-per-round limits. Paid by four lines restated
in AGENTS.md, project-forms.md, rest-channel.md and execution-duties.md.

triage-duties.md: a full red on main and a deterministic merge-queue red are
graded p0 at first touch (anchor, root-cause card, the generated full-run
card); a flake anchor becomes p0 only once read as deterministic; the triage
stop-bleed duty points at 约定③. Paid by the director routing pointer and the
retriage objection line (state-machine.md).

scripts/ci: the generated main-red card is filed `priority:p0`
(scheduled-full-run.mjs cardIdentity, its self-test fixture, and the card
step's expected-call pin).

Claude-Session: https://claude.ai/code/session_01QSeKYmhU5KEj1nukYhp1Tg
Co-authored-by: Claude <noreply@anthropic.com>
…nding-operations fork-PR line this branch removed

The paid deletion of landing-operations.md's fork-PR line left
external-contributions.md L3 pointing at a line that no longer exists.
Rewritten in place (22 lines kept, 115 bytes): the rule's surviving home is
AGENTS.md Prime Directive #14, and this file is the four-step procedure.

Claude-Session: https://claude.ai/code/session_01QSeKYmhU5KEj1nukYhp1Tg
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: d29c4e0815cb28982a87de55b9e0446b1c253e04
Local-runs: probe — the seat ran, in a detached read-only worktree of the head (no edit, no network): node scripts/pm/check-skill-line-ratchet.mjs → ✓ (SKILL.md 319/319, execution-duties 188/188, landing-operations 101/101, triage-duties 102/102, external-contributions 22/22), node scripts/pm/check-skill-id-lint.mjs → ✓ 104 files clean, node scripts/check-skill-frame-sync.mjs → ✓, node scripts/ci/scheduled-full-run-card.mjs --self-test → ✓ 7 cases, node scripts/ci/scheduled-full-run.mjs --self-test → OK (all on 7b401bfc; the ratchet, id-lint and frame-sync re-run on d29c4e08)
Scope: .claude/skills/pm-dispatch/SKILL.md (L34 红线 exception, L118 priority:p0 row, L126 paid), references/execution-duties.md, references/landing-operations.md, references/triage-duties.md, references/external-contributions.md (L3, the seat's finding), scripts/ci/scheduled-full-run.mjs + scheduled-full-run-card.mjs (the label constant and its pin) + card #27047's 「Wanted」 1–6 and ruling record 6462070130

Read at 2026-10-28T13:47Z by the domain:skills#2 seat on the fetched head (merge-base 9ff8154c): seven files, +16/−16, 32 changed lines ≤ 3000 (check-governed-merges --pr 27266: five .claude paths, Tier S). The claim's tier was the ceiling tier by path mandate (SKILL.md); this review is served at CONTRACT_REVIEW_TIER. The head is the dev's amendment over 7b401bfc on the seat's finding (one dangling pointer, below); the six other files are byte-identical to 7b401bfc.

① Derived judgments

  • The maintainer's words land where a reader looks for them. SKILL.md L118 (239 B, under the 341 B table-row pin): 「插队:同轮立即派发,越过 batch、深度等待(LOCK_DEPTH_HOLD)与一切并发上限;无槽即暂停低级在飞 dev 腾位(机制 references/execution-duties.md);⛔ 不豁免同文件串行与认领协议」 — items 1–3 in one row, the ⛔ keeps 同文件串行与认领协议 and drops 深度等待 (now crossed). Holds against 「不受并发限制,或者宁可其他开发暂停」.
  • execution-duties: L25 tail 「p0 越过 batch、深度等待与一切并发上限」; two new lines carry the pause mechanics exactly as the card's ⚠️ reading has them (stop the session, PR stays draft, claim untouched; Paused-for: #<p0> on the card; ⛔ no discard / revert / force-push; revived on the p0's landing, same claim, same branch); one new line after L48 makes the lane's open priority:p0 the first read of every round and wake, claimed and dispatched in the same round. Holds (items 1–3).
  • landing-operations: 约定①'s non-mechanical branch (6a: name the owning lane on the anchor, ring its mailbox with Request: main-red — the key PR pm-dispatch(mailbox): one mailbox PR per seat with a closed doorbell vocabulary; seat-online/offline notices; alternate pick for multi-seat lanes #27143 landed this shift; the root-cause card stays with the lane), 约定③ (6b: one triage round ~60 min unclaimed → triage and director name card and lane in that round's report; 6c: another round → triage posts the standard claim line and dispatches ONE os-dev for the stop-bleed only, one per round, triage never a development lane; the stop-bleed PR's review is the lane seat's or the director's, Tier H still waits on the approver, the lane seat takes the card back through the claim line). Faithful to 「同意,补到 pm-dispatch(p0): a lane's p0 card is dispatched at once — no batch, depth-wait or concurrency cap holds it, and lower-priority dev work pauses to make room; main or merge-queue red is graded p0 at first touch #27047」 / 「同意乙,一起写进 pm-dispatch(p0): a lane's p0 card is dispatched at once — no batch, depth-wait or concurrency cap holds it, and lower-priority dev work pauses to make room; main or merge-queue red is graded p0 at first touch #27047」. Holds.
  • triage-duties: item 5 (a full red on main and a deterministic queue red graded p0 at first touch — anchor, root-cause card, generated full-run card; a flake anchor only once read deterministic) and a one-line pointer to 约定③ — the file declares itself the triage seat's complete duties (L3), so the pointer is owed, not extra. Holds.
  • SKILL.md 红线 L34 「唯一例外:无主 p0 锚卡一轮即轮报、再一轮分诊只代派止血:每轮一张,复核非分诊。」 — beyond the order's named lines but required by the card's own 6c (「this amends the maintainer's earlier 『你只处理分诊』 for this one case only」): without it 〈优先级〉's stricter-rule resolution would void 6c against 「⛔ 分诊席永不认领、派发或写码」. The seat read it as the card's text, not the dev's. Holds.
  • scripts/ci: scheduled-full-run.mjs L366 (the live filing path through fileCardStep) and L1699 (the self-test fixture) priority:p1 → priority:p0; scheduled-full-run-card.mjs L217 is the pin of L366 — the dev's reverse check (L217 at p1 → 5 failures, exit 1; restored → green) shows the pin bites. Holds (item 5's generator half).
  • Line budget: every new prose line ≤120 B (the seat measured all 15 on 7b401bfc and the one on d29c4e08); every paid deletion names a home the seat spot-read on the head: state-machine L19 (hold 双查) and L39–40 (retriage 判据), project-forms L38 (mailbox owes no CI), rest-channel L13/L49 (the bare dispatch command), execution-duties L156–158 (subscribe), SKILL.md 〈模板与表〉 L311/L313 (tier and Metadata-protocol template lines), director.md 职责四 L71–75, AGENTS.md PD 14 + external-contributions.md (fork PR). The fork-PR deletion's named home pointed back at the deleted line — the seat's finding — fixed in place on d29c4e08 (L3 → 「fork PR = 提案(AGENTS.md Prime Directive feat: Comprehensive CRM example demonstrating all ObjectStack protocol features #14);本文是 fork PR(head 仓 ≠ base 仓)进场到落地的四步。」, 115 B; git grep 'fork PR 行' -- .claude → 0). No re-wrap as currency. Holds.

② Semver level

  • None owed: protocol text and CI-owned scripts; no package touched. Clause-②: no, Metadata-protocol: none on the PR body match the claim; no Skills-docs: line owed; skip-changeset correct.

③ Boundary flags

  • Order hypothesis 1 corrected by the dev: triage-duties' ceiling is 102 (the seat's order said 103 — a stale reading of the CEILINGS ledger), so that file paid two lines; landing-operations needed four new lines, paid four. The order's line count for the file (619 vs 622 on another card) is the same class of stale reading — the seat notes it as its own.
  • PR body: the dev did not PATCH it after pr_create (role file: the dev writes the body once; the seat writes later corrections in its record). The body's 「Line budget」 row for landing-operations L7 therefore still reads its home as external-contributions.md without the rewrite; the correct row is: home = AGENTS.md Prime Directive feat: Comprehensive CRM example demonstrating all ObjectStack protocol features #14, with references/external-contributions.md L3 rewritten in place (commit d29c4e08, 115 B, 22/22) so it no longer points back at the deleted line. This record is the correction.
  • check:doc-formula-expressions NOT MEASURED locally (prerequisite packages unbuilt; no package touched); CI's Lint lane carries it — read off the head's check-runs in the ACCEPT.
  • The PR title was shortened to the relay's 255-byte cap (the order's title was over it); content unchanged.
  • Two observations left unfiled, agreed: ensure-pm-labels.sh's priority:p0 description stays true (it never named the depth wait); check-half-states.mjs H10 already patrols a stale unclaimed p0 report-only — no patrol row added for 6b's ~60-minute round (protocol text only).
  • Author objectstack-fleet[bot] through the relay; mcp_calls: 0; draft, no flip by anyone.

④ Design judgment

  • Against the maintainer's scenario (a main-red p0 sat four hours as a p1 in a lane queue; a deterministic queue red graded p1 twice): the lane reads its p0s first and starts them in the same round past every cap, pausing lesser work rather than waiting; the finder stops the bleed when mechanical; an unclaimed p0 reaches the maintainer within a round and gets a stop-bleed dispatch within two; the generator files red cards at p0. No new gate; the one 红线 exception is the maintainer's own ruling, bounded to one stop-bleed per round with the review kept out of triage's hands. Holds. Residual: 「暂停」 is protocol text with no tooling behind it yet (a seat stops a subagent by hand) — fine for now, and the Paused-for: line makes the state readable on the card.

Implemented-by: claude/issue-27047-p0-dispatch-at-once
Reviewed-by: session_01QSeKYmhU5KEj1nukYhp1Tg

VERDICT: PASS

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

维护者速读 — 席位终稿 · PR #27266 · head d29c4e08 · domain:skills#2 · 2026-10-28T13:59Z

  • 改了什么:本车道的 p0 卡当轮立即派发,不受 batch、深度等待(LOCK_DEPTH_HOLD)与任何并发上限约束;没槽就暂停最低优先级的在飞 dev 腾位(分支与 PR 原样、卡记 Paused-for:、p0 落地即复活);主干全量红与确定性队列红首触即 p0,四小时 full-run 生成的红卡改为 p0 立卡;发现红的席位先止血,一轮无人认领即轮报点名,再一轮分诊只代派止血(每轮一张、复核不归分诊 —— SKILL.md 红线加的唯一例外,即你的「同意乙」)。四份协议文件 319/188/101/102 行,均在上限;付掉的 11 行各有家;dev 按席位复核发现补改了 external-contributions.md 一行悬空指针。
  • 为什么改:你的原话「main 红为什么不是 p0?」「skills 规则应该要求对应车道 p0 的卡立刻派发」「不受并发限制,或者宁可其他开发暂停」「你需要立卡更新技能」,以及第 6 项「同意,补到 pm-dispatch(p0): a lane's p0 card is dispatched at once — no batch, depth-wait or concurrency cap holds it, and lower-priority dev work pauses to make room; main or merge-queue red is graded p0 at first touch #27047」「同意乙,一起写进 pm-dispatch(p0): a lane's p0 card is dispatched at once — no batch, depth-wait or concurrency cap holds it, and lower-priority dev work pauses to make room; main or merge-queue red is graded p0 at first touch #27047」。
  • 风险与回滚:只改协议文本与一个 CI 脚本的标签常量(含其 pin),不碰产品代码;回滚 = revert。唯一放宽的是分诊红线那一条例外,边界写死(每轮一张、止血不碰根因、复核归车道或总监)。
  • 先看:SKILL.md L35(红线例外)与 L119(priority:p0 行);landing-operations.md 约定①非机械分支与约定③(6a–c);execution-duties.md 暂停机制三行。
  • 两分钟验证:pnpm check:pm-skill-ratchet && pnpm check:pm-skill-id-lint && node scripts/ci/scheduled-full-run-card.mjs --self-test 预期全绿。
  • 需要你做的:无 —— Tier S,契约复核 PASS(6470738460)后席位按你今天的落地授权落地。
  • 席位意见:ACCEPT。15 行新文本逐行 ≤120 B、四维框架块 md5 未变、付行之家逐一抽读在;席位发现的悬空指针(fork PR 行)已在 d29c4e08 原地修正;dev 推翻了我「triage-duties 有 1 行余量」的读数(上限 102,非 103),属实。

席位核对 — ACCEPT · domain:skills#2 · session_01QSeKYmhU5KEj1nukYhp1Tg · 2026-10-28T13:59Z

  1. 形态:draft → main,首行 Fixes #27047,Clause-②: no、Metadata-protocol: none 行首在;七个文件 +16/−16(32 行 ≤ 3000);assignee os-justin;skip-changeset 正确;两个 commit(7b401bfc + 补改 d29c4e08);PR 标题按中继 255 字节上限缩短。
  2. 前提实测:席位在取回的 head(merge-base 9ff8154c)上核 —— SKILL.md L118 行 239 B ≤ 表行 pin 341;四份文件行数在上限;git grep 'fork PR 行' -- .claude 0 命中;四维框架块 md5 abff5f85… 与 main 相同;scripts/ci 三处常量 p1→p0 且 pin 自测 7/7;付行之家:state-machine L19/L39–40、project-forms L38、rest-channel L13/L49、execution-duties L156–158、SKILL.md L311/L313、director.md L71–75、AGENTS.md PD 14。
  3. 门禁 check-runs(head d29c4e08,本笔读数 2026-10-28T13:59Z):41 check-runs,25 success · 16 skipped · 0 in progress · 0 failure(mergeable_state: clean, draft)。dev 本地派生 43 族:42 exit 0、1 NOT-MEASURED(check:doc-formula-expressions 前置未建,CI 跑)钉 7b401bfc;补改 head 上 ratchet/id-lint/governed-prose 三项 exit 0(报告 6470650514);席位在 detached worktree 复跑 ratchet、id-lint、frame-sync、两份 ci 自测皆绿。
  4. 接受的偏差:① 席位派发令的 triage-duties 上限读数错(103→实为 102),该文件付两行;② 红线例外行与 triage-duties 指针行越出派发令点名的行,但在卡第 6c 项之内,正文已申报;③ PR 正文「Line budget」的 landing-operations L7 行之家未随补改更新(角色文件禁 dev PATCH 正文)—— 以契约复核 6470738460 ③ 为更正:家 = AGENTS.md PD 14,external-contributions.md L3 于 d29c4e08 原地改写(115 B,22/22);④ check:doc-formula-expressions 本地 NOT MEASURED。
  5. 范围外去向:none filed;Acceptance notes:ensure-pm-labels.sh 的 priority:p0 描述仍真;check-half-states.mjs H10 已巡查无主 p0(report-only),6b 的 ~60 分钟轮不加巡查行。Skills-docs: 不欠(kind none)。
  6. 落地条款:Tier S;契约复核 PASS 评论 6470738460(head d29c4e08);全绿即席位经中继 pr_ready + automerge_enable 落地(本班维护者授权在案);MERGED 后关卡摘 pm:dispatched,SKILL.md 热文件队列放开 → pm-dispatch(triage): a lane seat may self-triage (p1/p2) a card that blocks its own in-flight work on clear evidence, then ask the triage seat to review #27061、pm-dispatch(contract-review): the lane reviews its own PRs; triage takes only a review nobody is doing, and one claim line per head keeps two reviewers off the same head #27062、pm-dispatch(batch): a slot is a RUNNING subagent or card thread — PRs awaiting approval, the queue, CI or a ruling occupy none; the round report counts running and un-landed separately; a soft ceiling on accepted Tier H PRs awaiting a human #27117。

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 28, 2026 14:01
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 28, 2026
Merged via the queue into main with commit 3af6022 Oct 28, 2026
42 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-27047-p0-dispatch-at-once branch October 28, 2026 14:17
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