Repository navigation
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
Conversation
…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>
Contract reviewServed-tier: Read at 2026-10-28T13:47Z by the ① Derived judgments
② Semver level
③ Boundary flags
④ Design judgment
Implemented-by: VERDICT: PASS |
维护者速读 — 席位终稿 · PR #27266 · head
|
Fixes #27047
Clause-②: no
Metadata-protocol: none
维护者速读
batch、深度等待(LOCK_DEPTH_HOLD)与任何并发上限约束;没有槽位就暂停最低优先级的在飞开发腾位(分支与 PR 原样保留、卡上记Paused-for:行、p0 落地即复活)。主干全量红与确定性队列红首触即 p0,四小时 full-run 生成的红卡也改为 p0 立卡。发现红的席位先止血;一轮无人认领即轮报点名;再一轮分诊只代派止血(每轮一张,复核不归分诊)。SKILL.md第 35 行(红线新增的唯一例外)与第 119 行(priority:p0行);②references/landing-operations.md第 76–84 行(约定①及其非机械分支、约定③);③references/execution-duties.md第 25–27 行(暂停机制)。pnpm check:pm-skill-ratchet && pnpm check:pm-skill-id-lint && node scripts/ci/scheduled-full-run-card.mjs --self-test—— 预期全绿;ratchet 打印四份文件 319 / 188 / 101 / 102 行,各在上限、headroom 0。.claude/**)。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.references/execution-duties.md〈候选与批次〉 L51 (new): on every round and every wake the lane seat's first read is its openpriority:p0; an unclaimed one is claimed and dispatched in that same round, never the next.SKILL.mdpriority:p0row (L119) rewritten in place: same-round dispatch pastbatch, the depth wait (LOCK_DEPTH_HOLD) and every concurrency cap; the row's ⛔ loses 深度等待 and keeps 同文件串行与认领协议.execution-duties.mdL25: p0 crosses the depth wait too (the old text forbade exactly that).execution-duties.mdL26–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 aPaused-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'sreferences/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.references/triage-duties.mdL30 (new): a full red onmainand 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'squeue-flake-anchoris a name, not a diagnosis). Generator:scripts/ci/scheduled-full-run.mjscardIdentity().labelspriority:p1→priority:p0. That constant is the live filing path (createIssue({ labels: identity.labels }), called throughscheduled-full-run-card.mjsfileCardStep, which.github/workflows/scheduled-full-run-card.ymlruns). Its pin,scheduled-full-run-card.mjsL217 (the self-test's expectedissues.createparams), follows; so does the self-test board fixtureCARD_LABELS(scheduled-full-run.mjsL1699), whichlint.ymlexecutes through--self-testand whose battery asserts only that a refresh never touches the grade labels.landing-operations.md: 约定① (L76) gains its non-mechanical branch (L80, 6a — the finder names the owning lane on the anchor and rings its mailbox withRequest: 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 ONEos-devfor 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.mdL31 (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.mdalone now learns that a p0 is dispatched in the same round, pastbatch, 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.mjsCEILINGS): SKILL.md 319, execution-duties 188, landing-operations 101, triage-duties 102 — every one at headroom 0 onorigin/main9ff8154. 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 -cwithout 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 (classifyLineexempts them from the 120-byte line rule). Line numbers in this section areorigin/main's..claude/skills/pm-dispatch/SKILL.md— 319 → 319- 唯一例外:无主 p0 锚卡一轮即轮报、再一轮分诊只代派止血:每轮一张,复核非分诊。插队:可超 \batch`、破轮次立即派发;⛔ 不豁免同文件串行、深度等待与认领协议. Cell after:插队:同轮立即派发,越过 `batch`、深度等待(`LOCK_DEPTH_HOLD`)与一切并发上限;无槽即暂停低级在飞 dev 腾位(机制 `references/execution-duties.md`);⛔ 不豁免同文件串行与认领协议`.- hold 放行须双查:只放最近一次转换评论的条件,其后卡上有更新的 merged PR 即拒。— home:references/state-machine.mdL19 (the same rule, verbatim: 「放行双查皆机械:只放最近一次 hold/blocked 转换评论的条件;其后卡上有新 merged PR 即拒」); SKILL.md L125 already points there for hold/blocked detail.references/execution-duties.md— 188 → 188\priority:p0` 可超 `batch`,⛔ 不越过深度等待。→p0 越过 `batch`、深度等待与一切并发上限。` (head unchanged).- p0 无槽或低级在飞同文件挡住 ⇒ 暂停腾位的最低级 dev:停会话、PR 留 draft、认领不动。- 卡记 \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.- 每轮每次唤醒首读本车道开着的 \priority:p0`,无人认领即同轮认领派发,⛔ 不等下轮。`- \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").- 档位引 \dispatch-gates --tier --repo 仓`⛔ 不凭记忆;天花板拼常量名并同行引据,⛔ 不抄模型 id— home: SKILL.md 〈模板与表〉Container & model:template line (L311: 引当次--tier输出;天花板拼CONTRACT_REVIEW_TIER`,同行引其 MANDATORY 路径行或 reason;⛔ 不抄模型 id).- 派发令写明 dev ⛔ 不另留认领:PM 那条即身份;核对最新一条点名本分支,不符停手回报。— home: AGENTS.md 〈Claim the issue BEFORE you write any code〉 ("A dispatched executor … verifies that the newestClaim: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- 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 ③).- \pm:mailbox` 信箱 PR 不欠 CI、永不入队;落地台账与孤儿 PR 查询一律排除该标签。— home:references/project-forms.md` 〈信箱 PR〉 L38 (the same rule, verbatim).- 直敲 \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.- 会话席窗口内 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).- 止血非机械 ⇒ 锚卡点名归属车道、敲其信箱 \Request: main-red`;根因卡恒归该车道。`- 约定③:锚卡一轮分诊(~60 分钟)无人认领 ⇒ 分诊与总监当轮轮报点名卡与归属车道。- 再一轮无人认领 ⇒ 分诊贴标准认领行、派一个 os-dev 只做止血;每轮一张,分诊不成车道。- 止血 PR 复核归车道席或总监,⛔ 非分诊;Tier H 仍等审批人;车道席到场经认领行交回。references/triage-duties.md— 102 → 102- 发版板、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 thedirectorrow of 〈入口与角色〉 (三职与章程见 director.md).- 主干全量红与确定性队列红首触定 p0(锚卡、根因卡、full-run 卡);flake 锚卡判确定性才升。- 无主 p0 锚卡一轮即轮报,再一轮本席贴认领行只代派止血(\landing-operations.md` 约定③)。`- retriage 的异议判据认内容(有评论写明所求)⛔ 不认形状(有一条异议评论)。— home:references/state-machine.mdL39–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.mjsL366labels: ['bug', 'domain:devx', 'priority:p1']→'priority:p0'insidecardIdentity()— the live filing path (createIssue({ … labels: identity.labels })at L488;fileCardStepinscheduled-full-run-card.mjscalls it;scheduled-full-run-card.ymlruns that step).scheduled-full-run.mjsL1699const 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.mjsL217labels: ['bug', 'domain:devx', 'priority:p1']→'priority:p0'— the expectedissues.createparams 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 oforigin/mainand 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 --ranexit 0 — 43 derived families accounted for: 42 run, 1 NOT-MEASURED (derived from the recorded exit 3), 0 UNRUN. The NOT-MEASURED one ispnpm --filter @objectstack/lint run check:doc-formula-expressions: PREREQUISITE NOT MET —@objectstack/formulaand@objectstack/lintare not built in this worktree (its fix linepnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lintwould 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'sLint & Repo Gatesruns 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 filesnode 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 theinode 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 regnode 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); 3node 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 dinode scripts/check-whole-set-label-write.mjs— exit 0 —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 OKnode 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 legnode 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 covepnpm 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 unrpnpm 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, apnpm 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, admittingpnpm 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 topologpnpm 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 decorpnpm 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-fpnpm 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 inpnpm 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 COPIESpnpm 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 itsRun before the union, on the same tree (also captured before any pipe):
pnpm check:pm-skill-ratchetexit 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-lintexit 0 (104 files clean);pnpm check:pm-governed-proseexit 0;pnpm check:skill-frame-syncexit 0;pnpm check:skill-frame-freshnessexit 0 (local-only family; the frame is current withorigin/main);node scripts/ci/scheduled-full-run.mjs --self-testexit 0;node scripts/ci/scheduled-full-run.mjs --check-concurrencyexit 0;node scripts/ci/scheduled-full-run-card.mjs --self-testexit 0 (7 cases);pnpm check:pm-half-statesexit 0 (5034 cases);pnpm check:pm-dispatch-gatesexit 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.mjsL217 mutated back topriority:p1on disk (grep: p0 1 → 0, p1 0 → 1) withscheduled-full-run.mjsL366 atpriority:p0⇒node scripts/ci/scheduled-full-run-card.mjs --self-testexit 1, 5 failures, each an expected-vs-actual mismatch on theissues.createparams; restored withgit checkout HEAD -- scripts/ci/scheduled-full-run-card.mjs,git diff HEADempty 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 lintand the fullcheck:*farm belong to CI (Lint & Repo Gateson 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.shcreatespriority:p0with 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.mjsH10 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.scheduled-full-run.mjs:1699as a site that files the card; it is the self-test's fixture, not a filing site. The live site iscardIdentity()at L366. Both changed (above), so the correction has no effect on the fix.scheduled-full-run.mjsL1713 quotes a triage comment verbatim ("The card keeps its p1 …"); it is a historical record inside a fixture and is left exactly as measured.state-machine.md'sRestart-when:is bound topm:on-hold(two legal spellings, H9), andBlocked-by:moves the six-state and releases the assignee on unlock — neither fits a pausedpm:dispatchedcard whose claim must hold, so the resume line isPaused-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.triage-duties.mddeclares itself the triage seat's complete duties). Both paid in place.Verification
claude/issue-27047-p0-dispatch-at-once, head 7b401bf onorigin/main9ff8154; one commit; no changeset (.claude/**andscripts/ci/**publish nothing —skip-changesetdeclared atpr_create).dispatch-gates --ran; ④ CI families are read from this PR's check-runs by the seat (Lint & Repo Gatescarries everycheck:*family here), not re-run locally..claude/**is Tier S — the owning seat runs the contract review atCONTRACT_REVIEW_TIERand lands it; this PR stays draft until that record exists. No workflow was run or dispatched; the twoscripts/cimodules were exercised only through their offline--self-test.Generated by Claude Code