fix(#2771): advisor mode spawns registered gsd-advisor-researcher subagent instead of general-purpose (#2884)
* test(#2771): advisor mode must spawn gsd-advisor-researcher, not general-purpose * fix(#2771): spawn registered gsd-advisor-researcher subagent instead of general-purpose in advisor mode universal-anti-patterns rule 10 (injected into discuss-phase via <required_reading>) says NEVER use non-GSD agent types. The advisor mode spawned general-purpose and manually told the agent to read the def — but gsd-advisor-researcher IS registered, so spawning by type auto-loads it. Drop the manual-read prompt line (re-specifying the def is a drift risk) and use the registered type. * chore(#2771): changeset fragment (mentions follow-up #2883) * test(#2771): widen manual-read-line regex to deny phrasing variants (review minor) /read\s+@.*gsd-advisor-researcher\.md/i (case-insensitive, any 'read @' lead-in) so a drift variant like 'Read @' or 'Load @' can't sneak the manual-def-read back in. * chore(#2771): backfill changeset PR number (2884) --------- Co-authored-by: Test <test@example.com>
This commit is contained in:
5
.changeset/curious-pumas-wake.md
Normal file
5
.changeset/curious-pumas-wake.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
type: Fixed
|
||||
pr: 2886
|
||||
---
|
||||
**Discuss-phase advisor mode now spawns the registered `gsd-advisor-researcher` subagent instead of `general-purpose`** — resolving a contradiction with the universal-anti-patterns rule (injected into the same context) that forbids non-GSD agent types. The manual "read the agent def" prompt line is dropped (spawning by type auto-loads it). (#2771; the sibling assumptions-site needs a design decision — filed as #2883)
|
||||
@@ -92,16 +92,14 @@ research agents.
|
||||
|
||||
```
|
||||
Agent(
|
||||
prompt="First, read @~/.claude/agents/gsd-advisor-researcher.md for your role and instructions.
|
||||
|
||||
<gray_area>{area_name}: {area_description from gray area identification}</gray_area>
|
||||
prompt="<gray_area>{area_name}: {area_description from gray area identification}</gray_area>
|
||||
<phase_context>{phase_goal and description from ROADMAP.md}</phase_context>
|
||||
<project_context>{project name and brief description from PROJECT.md}</project_context>
|
||||
<calibration_tier>{resolved calibration tier: full_maturity | standard | minimal_decisive}</calibration_tier>
|
||||
|
||||
Research this gray area and return a structured comparison table with rationale.
|
||||
${AGENT_SKILLS_ADVISOR}",
|
||||
subagent_type="general-purpose",
|
||||
subagent_type="gsd-advisor-researcher",
|
||||
model="{ADVISOR_MODEL}",
|
||||
description="Research: {area_name}"
|
||||
)
|
||||
|
||||
43
tests/issue-2771-advisor-subagent-type.test.cjs
Normal file
43
tests/issue-2771-advisor-subagent-type.test.cjs
Normal file
@@ -0,0 +1,43 @@
|
||||
// allow-test-rule: structural-implementation-guard (#2771)
|
||||
'use strict';
|
||||
|
||||
// Regression guard for #2771: the discuss-phase advisor mode must spawn the REGISTERED
|
||||
// `gsd-advisor-researcher` subagent (auto-loads the agent def), not `general-purpose` —
|
||||
// which contradicts universal-anti-patterns rule 10 (injected into discuss-phase via
|
||||
// <required_reading>): "NEVER use non-GSD agent types — ALWAYS use gsd-{agent}".
|
||||
// Spawning general-purpose + a manual "read the agent def" prompt re-specifies what the
|
||||
// def already owns (a drift risk; the same shape assumptions's answer_validation hit).
|
||||
|
||||
const { test } = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const ADVISOR_MD = path.join(
|
||||
__dirname, '..', 'gsd-core', 'workflows', 'discuss-phase', 'modes', 'advisor.md'
|
||||
);
|
||||
|
||||
test('advisor mode spawns the registered gsd-advisor-researcher subagent, not general-purpose (#2771)', () => {
|
||||
const src = fs.readFileSync(ADVISOR_MD, 'utf8');
|
||||
|
||||
// Locate the Agent() block that researches gray areas.
|
||||
const agentIdx = src.indexOf('subagent_type=');
|
||||
assert.ok(agentIdx !== -1, 'advisor.md must contain an Agent() subagent_type declaration');
|
||||
|
||||
assert.ok(
|
||||
src.includes('subagent_type="gsd-advisor-researcher"'),
|
||||
'advisor mode must spawn subagent_type="gsd-advisor-researcher" (the registered agent def auto-loads) — not general-purpose (#2771, universal-anti-patterns rule 10)'
|
||||
);
|
||||
assert.ok(
|
||||
!src.includes('subagent_type="general-purpose"'),
|
||||
'advisor mode must NOT spawn subagent_type="general-purpose" (contradicts universal-anti-patterns rule 10, injected into the same context) (#2771)'
|
||||
);
|
||||
// The manual "read @.../gsd-advisor-researcher.md" prompt line must be gone —
|
||||
// spawning by type auto-loads the def; re-specifying it is a drift risk. Deny the
|
||||
// full class (any "read @" lead-in, case-insensitive) so a phrasing variant can't
|
||||
// sneak the drift back in.
|
||||
assert.ok(
|
||||
!/read\s+@.*gsd-advisor-researcher\.md/i.test(src),
|
||||
'advisor mode must not manually instruct reading the agent def — spawning by type auto-loads it (#2771)'
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user