Observation-class finding, filed unassigned from the #6863 / PR #6871 work. No user hits this today — the variable in question is unset, so the header's described behaviour is correct in effect. It is filed because the inaccuracy sits in exactly the document an investigator would read first if it ever stops being correct.
What
scripts/check-agent-model-declared.mjs's WHY-THIS-EXISTS header states:
The Agent tool resolves a subagent's model in three steps: an explicit model argument on the dispatch call → the agent definition's frontmatter → inherit from the parent session.
The real resolution has four steps. Verified 2026-08-09 against the Claude Code subagent documentation ("Claude Code resolves the subagent's model in this order"):
- the
CLAUDE_CODE_SUBAGENT_MODEL environment variable, when set
- the per-invocation
model parameter on the Agent call
- the agent definition's
model: frontmatter
- the main conversation's model
The omitted step is the one that outranks everything the repo controls.
Why it is worth a line rather than nothing
The gate's whole thesis is that a role's tier must be a property of the role, not of whoever dispatched it. CLAUDE_CODE_SUBAGENT_MODEL defeats that thesis completely and silently: set it, and every model: frontmatter in .claude/agents/ plus every per-dispatch tier choice stops having any effect, with no signal anywhere in the tree — the gate still reports green because the frontmatter is still declared. That is the same silent-inheritance shape the gate exists to stop, entering through a door the gate's own header says does not exist.
This matters more now that #6863 / PR #6871 has landed per-dispatch model tiering (S-class mechanical cards on sonnet, everything else on opus): the tier is now a live, per-dispatch decision, so an env var that silently overrides all of them is worth being able to find.
Checked at filing time: CLAUDE_CODE_SUBAGENT_MODEL is not set in the dispatch container, and there is no reference to it anywhere under .claude/.
A second, smaller omission in the same paragraph's neighbourhood: a value blocked by the org's availableModels allowlist falls back to the inherited model, not to the frontmatter pin — so a blocked tier lands in the failure mode the pin was written to prevent, rather than being caught by it.
Suggested fix (small, comment-only)
Correct the header to the four-step order and note the allowlist fallback. ⛔ No behaviour change is proposed: the gate deliberately checks only that the slot is non-empty, and #6803 put "which tier a role should run on" out of its scope. Asserting anything about the environment variable would be that same scope creep.
Why not fixed in PR #6871
Out of that card's declared file surface — #6863 scopes to .claude/skills/pm-dispatch/SKILL.md + .claude/agents/os-dev.md, and scripts/ is neither. The correct four-step order is written into .claude/agents/os-dev.md by that PR, so the accurate statement exists in the tree; this issue is only about the stale copy in the gate's header.
Dedup: searched open issues for CLAUDE_CODE_SUBAGENT_MODEL — zero hits.
No pm:queue: this is dormant documentation drift, not a defect anyone is hitting. Left for the triage seat to grade.
Observation-class finding, filed unassigned from the #6863 / PR #6871 work. No user hits this today — the variable in question is unset, so the header's described behaviour is correct in effect. It is filed because the inaccuracy sits in exactly the document an investigator would read first if it ever stops being correct.
What
scripts/check-agent-model-declared.mjs's WHY-THIS-EXISTS header states:The real resolution has four steps. Verified 2026-08-09 against the Claude Code subagent documentation ("Claude Code resolves the subagent's model in this order"):
CLAUDE_CODE_SUBAGENT_MODELenvironment variable, when setmodelparameter on the Agent callmodel:frontmatterThe omitted step is the one that outranks everything the repo controls.
Why it is worth a line rather than nothing
The gate's whole thesis is that a role's tier must be a property of the role, not of whoever dispatched it.
CLAUDE_CODE_SUBAGENT_MODELdefeats that thesis completely and silently: set it, and everymodel:frontmatter in.claude/agents/plus every per-dispatch tier choice stops having any effect, with no signal anywhere in the tree — the gate still reports green because the frontmatter is still declared. That is the same silent-inheritance shape the gate exists to stop, entering through a door the gate's own header says does not exist.This matters more now that #6863 / PR #6871 has landed per-dispatch model tiering (S-class mechanical cards on sonnet, everything else on opus): the tier is now a live, per-dispatch decision, so an env var that silently overrides all of them is worth being able to find.
Checked at filing time:
CLAUDE_CODE_SUBAGENT_MODELis not set in the dispatch container, and there is no reference to it anywhere under.claude/.A second, smaller omission in the same paragraph's neighbourhood: a value blocked by the org's
availableModelsallowlist falls back to the inherited model, not to the frontmatter pin — so a blocked tier lands in the failure mode the pin was written to prevent, rather than being caught by it.Suggested fix (small, comment-only)
Correct the header to the four-step order and note the allowlist fallback. ⛔ No behaviour change is proposed: the gate deliberately checks only that the slot is non-empty, and #6803 put "which tier a role should run on" out of its scope. Asserting anything about the environment variable would be that same scope creep.
Why not fixed in PR #6871
Out of that card's declared file surface — #6863 scopes to
.claude/skills/pm-dispatch/SKILL.md+.claude/agents/os-dev.md, andscripts/is neither. The correct four-step order is written into.claude/agents/os-dev.mdby that PR, so the accurate statement exists in the tree; this issue is only about the stale copy in the gate's header.Dedup: searched open issues for
CLAUDE_CODE_SUBAGENT_MODEL— zero hits.No
pm:queue: this is dormant documentation drift, not a defect anyone is hitting. Left for the triage seat to grade.