fix(#2072): thread resolved model into routed-agent spawns (assumptions-analyzer, code-reviewer, code-fixer)
model_overrides / models.<phaseType> were silently inert for gsd-assumptions-analyzer,
gsd-code-reviewer, and gsd-code-fixer on Claude Code: resolveModelInternal honors them,
but the workflows spawned these agents with no model= param, so the resolved value
never reached the Agent tool and the agents inherited the session model — no warning.
Fix — thread each agent's resolved model at every spawn site (the established
plan-phase pattern; the architecture-consistent Claude mechanism, since 13 other
agents already thread their model):
- discuss-phase-assumptions.md: `resolve-model gsd-assumptions-analyzer --raw`
→ ANALYZER_MODEL, threaded.
- code-review.md + code-review-fix.md (re-review): `resolve-model gsd-code-reviewer --raw`
→ REVIEWER_MODEL, threaded.
- code-review-fix.md (both fixer spawns): `resolve-model gsd-code-fixer --raw`
→ FIXER_MODEL, threaded (same silently-inert bug, same file — folded in per review).
- quick.md review step: was reusing `{executor_model}` for gsd-code-reviewer (so the
reviewer's own override was ignored); init.quick now resolves `reviewer_model`
(gsd-code-reviewer) and the spawn threads it.
resolve-model --raw returns the bare model string (resolve-execution --raw would
return effort — wrong). The resolver maps these agents to phaseType discuss /
verification / execution, so models.<phaseType> apply too.
Scope: the three agents reachable from the two issue-named workflows + quick.md. The
wider systemic class (other agents in UNTOUCHED workflows with the same pattern) stays
documented on the issue for a maintainer-scoped structural decision (thread-at-source
vs embed-at-install like #2256), not widened here.
Docs: the stale "discuss — reserved, no subagent today" model-profile tables now list
gsd-assumptions-analyzer and the verification row includes gsd-code-reviewer, across
the English docs, the shipped gsd-core/references/model-profiles.md reference, and the
ja-JP / zh-CN / ko-KR / pt-BR locale mirrors.
Tests:
- tests/model-resolver.test.cjs: #2072 acceptance — model_overrides and
models.discuss/verification/execution resolve for all three agents.
- tests/model-routing-spawn-threading.test.cjs: every spawn of the three agents threads
a resolved model (fails pre-fix); a header-precise parity guard fails the suite if a
new un-threaded spawn of any of them regresses.
All 16 golden-install-parity fixtures + the workflow size baseline regenerated for the
changed shipped files (4 workflows + the reference doc); bin/lib is excluded from parity.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -120,6 +120,36 @@ describe('resolveModelInternal', () => {
|
||||
assert.ok(typeof model === 'string' && model.length > 0);
|
||||
});
|
||||
|
||||
// #2072 acceptance: these two catalog agents' config MUST resolve — the bug was
|
||||
// that the workflows never threaded the resolved value, not that the resolver
|
||||
// ignored it. These assert the value the (now-threaded) spawns receive.
|
||||
test('#2072: model_overrides applies to gsd-code-reviewer', () => {
|
||||
writeConfig(tmpDir, { model_overrides: { 'gsd-code-reviewer': 'my-custom-model' } });
|
||||
assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-code-reviewer'), 'my-custom-model');
|
||||
});
|
||||
|
||||
test('#2072: model_overrides applies to gsd-assumptions-analyzer', () => {
|
||||
writeConfig(tmpDir, { model_overrides: { 'gsd-assumptions-analyzer': 'my-custom-model' } });
|
||||
assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-assumptions-analyzer'), 'my-custom-model');
|
||||
});
|
||||
|
||||
test('#2072: models.verification tier applies to gsd-code-reviewer', () => {
|
||||
writeConfig(tmpDir, { models: { verification: 'opus' } });
|
||||
assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-code-reviewer'), 'opus');
|
||||
});
|
||||
|
||||
test('#2072: models.discuss tier applies to gsd-assumptions-analyzer', () => {
|
||||
writeConfig(tmpDir, { models: { discuss: 'opus' } });
|
||||
assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-assumptions-analyzer'), 'opus');
|
||||
});
|
||||
|
||||
test('#2072: model_overrides + models.execution apply to gsd-code-fixer', () => {
|
||||
writeConfig(tmpDir, { model_overrides: { 'gsd-code-fixer': 'my-custom-model' } });
|
||||
assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-code-fixer'), 'my-custom-model');
|
||||
writeConfig(tmpDir, { models: { execution: 'opus' } });
|
||||
assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-code-fixer'), 'opus');
|
||||
});
|
||||
|
||||
test('runtime non-claude + model_profile_overrides for runtime tier', () => {
|
||||
writeConfig(tmpDir, {
|
||||
runtime: 'codex',
|
||||
|
||||
Reference in New Issue
Block a user