docs(pm-dispatch): dispatch token economics — sonnet tier for S-class cards, scoped local gates, slimmed prompts (#6863) - #6871
Merged
Conversation
… cards, scoped local gates, slimmed prompts (#6863) Three coupled changes to the dispatch machinery, maintainer-approved 2026-08-09 (「全部同意,先开任务」). 1. Model tiering. Step 5's absolute "pass model: opus on every dev dispatch" is replaced by a tiered policy: S-class mechanical cards dispatch on sonnet, everything with design judgment stays on opus. The old absolute is named and retired in place so a reader cannot come away with both. The claim comment's container-assessment line now carries the tier too. 2. Local gate scoping. The "enumerate every check:* from lint.yml and run all 55+ locally" rule is replaced by build closure + affected-package suites + the gate families touching the card's surface. The CI-convergence wait is restated as the load-bearing safety half, in os-dev.md and again in the PM's step-7 reconciliation. 3. Slimmed dispatch prompts. The template no longer pastes the issue body; the dev reads it on GitHub and must verify completeness (notes-12 truncation risk moves with the read). The unconditional non-negotiables sink into .claude/agents/os-dev.md once; prompts carry only deltas. Conditional standard clauses (those with 适用判据) stay in the SKILL, pasted per card. Every line PR #6799 added is present verbatim; zero hunk overlap. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F8q5J1MQyocgtNspb15fSn
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
hotlong
marked this pull request as ready for review
August 9, 2026 06:34
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #6863
Three coupled changes to the dispatch machinery, all in
.claude/. Nothing ships tousers; this PR releases nothing and writes no changeset.
Maintainer authorization
Per the Guardrails exception for
.claude/internal tooling PRs (#5925-6, precedents#5597 / #5872 / #6650), the authorization is quoted here verbatim and untranslated.
Maintainer, in-session, 2026-08-09:
Approving the
domain:specseat's token-economics assessment (sessionsession_011sGk4SKHqGRgmmqUok1P8M). Review stays with another seat or a maintainerwalkthrough — this PR is a draft, auto-merge is not armed, and the seat that
implemented it will not merge it.
Item 1 — model tiering, and the precedence finding the card asked for
The finding first, because the card flagged it as the one thing that could make item 1
inert: it does not. The per-dispatch argument wins.
Claude Code resolves a subagent's model in four steps, verified 2026-08-09 against the
subagent documentation rather than inferred from the repo's own prose:
CLAUDE_CODE_SUBAGENT_MODELenvironment variable, when setmodelparameter on the Agent callmodel:frontmatterSo
.claude/agents/os-dev.md's frontmattermodel: opus(#6688, guarded by #6836'scheck:agent-model-declared) does not defeat a dispatch that passesmodel: "sonnet"— step 2 outranks step 3. The pin governs only the case where thedispatcher passes nothing, which is exactly the #6686 incident it was written for. Item 1
takes effect as written.
Two adjacent traps are recorded next to it, because both are silent:
CLAUDE_CODE_SUBAGENT_MODELoutranks both the argument and the frontmatter. It isnot set in the dispatch container (checked 2026-08-09), but if it ever is, it
overrides every tier decision the PM makes and nothing in this repo would show it.
availableModelsallowlist does not fall back to thefrontmatter pin — it falls back to the inherited model, i.e. straight back into the
silent-inheritance failure the pin exists to stop.
On the contradiction the card named. The old rule existed in two places: step 5's
「Model split (maintainer policy): pass
model: "opus"on every dev dispatch」 and the08-08 handover's 「所有派发至少 opus」. The second is a handover note, not a file — grep
finds no copy of it in the tree — so only the first was editable. Rather than quietly
swapping the sentence, the new §5 names the old wording, quotes it, and declares it
废止, and instructs the reader to override any 「一律/至少 opus」 they meet elsewhere
(old handover notes, seat stickers, second-hand retellings). A reader cannot come away
holding both.
Tiering itself: S-class mechanical cards go to sonnet, where the criterion is "the
gate farm decides correctness mechanically", not "the diff is small"; M/L, ruling
implementations, multi-face semantic cards and anything with design judgment stay on
opus; ties round up.
modelis passed explicitly on every dispatch rather thanleaning on the pin, so the tier is a property of the dispatch and not of a file's current
state. The claim comment's container-assessment line now carries the tier beside the
size, since both come from one reading — with an explicit warning that "S-class" does not
imply sonnet on its own.
Item 2 — local gate scoping, with the safety half kept mandatory
os-dev.mdgains a Local verification scope section: build closure, the affectedpackages' suites, and the gate families touching the card's surface — instead of
enumerating all 55+
check:*steps out oflint.yml. The dispatch template now namesthe relevant families per card.
The card accepts an occasional extra push-fix lap as the cost, so the rule states that
cost and then pins the half that makes it safe. Written into
os-dev.mdverbatim:And reconciled on the PM side at step 7: the CI-convergence check moves from "the second
of two safety nets" to the only one, so a non-obvious gate reddening in CI is now the
expected shape rather than an anomaly, the extra lap is a price already paid rather
than grounds for REWORK, and "local green" in a report covers a smaller surface than it
used to. Kept intact per the card: build-first, prefix-direction consumer sweep, reverse
verification, and CI convergence before reporting.
Item 3 — slimmed prompts, boilerplate sunk to the producer
body and all comments on GitHub, which premise-first already forced. It still
pastes what GitHub reading cannot supply: ruling quotes verbatim (Chinese
untranslated), the 裁决 / PM-机制假设 partition, card-specific clauses and same-day
churn.
transfer, not a courtesy: pasting made truncation the PM's risk, self-reading makes
it the dev's, so the prompt requires a completeness self-check and a double-read on
suspicion. Precedent [移交自 objectui] ComponentPropsMap 未声明 objectui 渲染器实读的 5 个顶层 prop(page:header ×3 / page:tabs.tabStyle / page:accordion.variant)—— #5775 的清点未完 #6776 is cited.
.claude/agents/os-dev.mdonce(producer-side fix, the PD#12 instinct the SKILL itself cites): build-first ordering,
filter direction, cross-package reverse verification, the authorable-surface anchor
rules with the
gen:schemaMERGE-state ban, and theFixesvsPart ofjudgment.Worktree discipline, ADR-0112 rejection assertions, foreground posture, English policy
and the report contract were already there and were not duplicated.
conformance coverage, rejection-case
code+status, the filter compile-faceinventory) — deliberately stay in the SKILL and are still pasted per card. They are not
universal, so sinking them would attach them to cards they do not apply to.
os-dev.mdsays plainly that a prompt's silence about a standard clause is theexpected shape and never permission.
Overlap with PR #6799
#6799 is merged —
cd704cc43, 2026-08-09T01:50:17Z — so the card's premise that itis open and being held for a human merge had already expired by dispatch time. I branched
from
origin/mainwith #6799 in it rather than composing around it.Region overlap: none. Hunk ranges do not intersect at any point:
Verified by content, not by line arithmetic: every line #6799 added is still present
verbatim in the file, checked by replaying its added lines through
grep -qF(zero missing). All four of its additions are untouched — the ADR merge prohibition in
Guardrails, the step-7 ACCEPT path fork, probe-and-revive as the standing backstop, and
the replay-wake identity check. My nearest edit (the step-7 CI-convergence bullet, in the
review checklist) sits above the ACCEPT verdict section where #6799's fork lives.
Deliberately NOT done
docs/adr/**, nocontent/docs/releases/, no code, no AGENTS.md."no file change needed" — batched seat-post refreshes, terse ACCEPT comments,
thread-tail race re-reads, sweep-first S-card batching. Not written.
checks, premise-first verification, write-after-read, serial landing relay, and the
45-minute patrol cadence. The claim comment gained one line and lost nothing; the
「最后一行」 back-reference that the [skill] pm-dispatch:services 车道 08-05/06 班次交接沉淀的 10 条 SKILL 更新建议(28 PR / 两次 CI 红 / 三次前提证伪) #5885 serial-constraints sentence depends on was
preserved by inserting the new line above it, not below.
scripts/check-agent-model-declared.mjs's header describes the resolution as "threesteps" and omits
CLAUDE_CODE_SUBAGENT_MODEL. Accurate in effect today (the variableis unset) and outside this card's declared file surface, so it was not edited — filed
separately as an observation.
Verification
No package code changed, so
pnpm test/pnpm typecheckare not meaningful here —saying so beats manufacturing template-shaped evidence. What was run, serialized under
the shared verification lock with the capped heap, is every gate whose scan surface
includes
.claude/(found by greppingscripts/*.mjsfor the path rather than frommemory), plus the repo-wide prose and changeset gates. 8 gates, all green, each with
EXIT=0:check:agent-model-declared— 18 self-test cases pass;os-dev.md → opus, 0 justified inheritscheck:skill-frame-sync— 12 self-test cases; 4 copies isomorphic across 3 files, 3 axes, 42 files scannedcheck:skill-frame-freshness— 12 self-test cases; frame current withorigin/maincheck:skill-compatibility— 18 self-test cases; 11 SKILL.md reconciled against 77 packagescheck:nul-bytes— 56 assertions; 6403 tracked text files, no raw ASCII control bytescheck:doc-authoring— 373 files cleancheck:role-word— 44 baselined files, no new occurrencescheck:empty-changeset— no empty-frontmatter changeset introducedByte discipline: a manual control-byte self-scan beyond the gate's surface
(
grep -naPover the two edited files, the full0x00-0x1fplus0x7frange) returnedno matches. This PR is dogfooding its own item 2 — the gates above are the families
touching its surface, not the whole farm.
Generated by Claude Code