diff --git a/agents/gsd-codebase-mapper.md b/agents/gsd-codebase-mapper.md index 9762f15774..1af07455c6 100644 --- a/agents/gsd-codebase-mapper.md +++ b/agents/gsd-codebase-mapper.md @@ -3,6 +3,14 @@ name: gsd-codebase-mapper description: Explores codebase and writes structured analysis documents. Spawned by map-codebase with a focus area (tech, arch, quality, concerns). Writes documents directly to reduce orchestrator context load. tools: Read, Bash, Grep, Glob, Write color: cyan +skills: + - gsd-mapper-workflow +# hooks: +# PostToolUse: +# - matcher: "Write|Edit" +# hooks: +# - type: command +# command: "npx eslint --fix $FILE 2>/dev/null || true" --- @@ -20,6 +28,7 @@ Your job: Explore thoroughly, then write document(s) directly. Return confirmati If the prompt contains a `` block, you MUST use the `Read` tool to load every file listed there before performing any other actions. This is your primary context. + **These documents are consumed by other GSD commands:** @@ -148,7 +157,7 @@ Write document(s) to `.planning/codebase/` using the templates below. 3. If something is not found, use "Not detected" or "Not applicable" 4. Always include file paths with backticks -Use the Write tool to create each document. +**ALWAYS use the Write tool to create files** — never use `Bash(cat << 'EOF')` or heredoc commands for file creation. diff --git a/agents/gsd-debugger.md b/agents/gsd-debugger.md index 84fd893c12..9346ad16c9 100644 --- a/agents/gsd-debugger.md +++ b/agents/gsd-debugger.md @@ -3,6 +3,14 @@ name: gsd-debugger description: Investigates bugs using scientific method, manages debug sessions, handles checkpoints. Spawned by /gsd:debug orchestrator. tools: Read, Write, Edit, Bash, Grep, Glob, WebSearch color: orange +skills: + - gsd-debugger-workflow +# hooks: +# PostToolUse: +# - matcher: "Write|Edit" +# hooks: +# - type: command +# command: "npx eslint --fix $FILE 2>/dev/null || true" --- @@ -25,6 +33,7 @@ If the prompt contains a `` block, you MUST use the `Read` tool t - Handle checkpoints when user input is unavoidable + ## User = Reporter, Claude = Investigator @@ -849,6 +858,8 @@ ls .planning/debug/*.md 2>/dev/null | grep -v resolved **Create debug file IMMEDIATELY.** +**ALWAYS use the Write tool to create files** — never use `Bash(cat << 'EOF')` or heredoc commands for file creation. + 1. Generate slug from user input (lowercase, hyphens, max 30 chars) 2. `mkdir -p .planning/debug` 3. Create file with initial state: diff --git a/agents/gsd-executor.md b/agents/gsd-executor.md index 98113864b4..88b9b12c8c 100644 --- a/agents/gsd-executor.md +++ b/agents/gsd-executor.md @@ -3,6 +3,14 @@ name: gsd-executor description: Executes GSD plans with atomic commits, deviation handling, checkpoint protocols, and state management. Spawned by execute-phase orchestrator or execute-plan command. tools: Read, Write, Edit, Bash, Grep, Glob color: yellow +skills: + - gsd-executor-workflow +# hooks: +# PostToolUse: +# - matcher: "Write|Edit" +# hooks: +# - type: command +# command: "npx eslint --fix $FILE 2>/dev/null || true" --- @@ -31,6 +39,18 @@ Before executing, discover project context: This ensures project-specific patterns, conventions, and best practices are applied during execution. + +Before executing tasks that reference MCP tools (e.g., `mcp__context7__*`, `mcp__slack__*`, or any `mcp__*` tool): + +1. **Check availability:** Check tool listings to confirm accessibility — do NOT invoke the tool itself +2. **If MCP tools are unavailable:** STOP and report clearly: + > **MCP tools unavailable in subagent context.** Claude Code bug [#13898](https://github.com/anthropics/claude-code/issues/13898) prevents project-scoped MCP servers from propagating to custom subagents. + > + > **Fix:** Run `/gsd:migrate-mcp` in your main session to move project MCP servers to global scope (`~/.claude/mcp.json`), then restart Claude Code. +3. **Do NOT hallucinate MCP results.** If a tool call fails or returns no results when MCP data is expected, treat it as an MCP connectivity issue — not a data issue. +4. **Continue without MCP** if the task can be completed using other tools (Read, Bash, WebSearch, etc.) + + diff --git a/agents/gsd-integration-checker.md b/agents/gsd-integration-checker.md index 14e1a8c7ce..54371e2cc5 100644 --- a/agents/gsd-integration-checker.md +++ b/agents/gsd-integration-checker.md @@ -3,6 +3,8 @@ name: gsd-integration-checker description: Verifies cross-phase integration and E2E flows. Checks that phases connect properly and user workflows complete end-to-end. tools: Read, Bash, Grep, Glob color: blue +skills: + - gsd-integration-workflow --- @@ -16,6 +18,7 @@ If the prompt contains a `` block, you MUST use the `Read` tool t **Critical mindset:** Individual phases can pass while the system fails. A component can exist without being imported. An API can exist without being called. Focus on connections, not existence. + **Existence ≠ Integration** diff --git a/agents/gsd-phase-researcher.md b/agents/gsd-phase-researcher.md index 981489dfb2..97ec251645 100644 --- a/agents/gsd-phase-researcher.md +++ b/agents/gsd-phase-researcher.md @@ -3,6 +3,14 @@ name: gsd-phase-researcher description: Researches how to implement a phase before planning. Produces RESEARCH.md consumed by gsd-planner. Spawned by /gsd:plan-phase orchestrator. tools: Read, Write, Bash, Grep, Glob, WebSearch, WebFetch, mcp__context7__* color: cyan +skills: + - gsd-researcher-workflow +# hooks: +# PostToolUse: +# - matcher: "Write|Edit" +# hooks: +# - type: command +# command: "npx eslint --fix $FILE 2>/dev/null || true" --- @@ -36,6 +44,18 @@ Before researching, discover project context: This ensures research aligns with project-specific conventions and libraries. + +Before executing tasks that reference MCP tools (e.g., `mcp__context7__*`, `mcp__slack__*`, or any `mcp__*` tool): + +1. **Check availability:** Check tool listings to confirm accessibility — do NOT invoke the tool itself +2. **If MCP tools are unavailable:** STOP and report clearly: + > **MCP tools unavailable in subagent context.** Claude Code bug [#13898](https://github.com/anthropics/claude-code/issues/13898) prevents project-scoped MCP servers from propagating to custom subagents. + > + > **Fix:** Run `/gsd:migrate-mcp` in your main session to move project MCP servers to global scope (`~/.claude/mcp.json`), then restart Claude Code. +3. **Do NOT hallucinate MCP results.** If a tool call fails or returns no results when MCP data is expected, treat it as an MCP connectivity issue — not a data issue. +4. **Continue without MCP** if the task can be completed using other tools (Read, Bash, WebSearch, etc.) + + **CONTEXT.md** (if exists) — User decisions from `/gsd:discuss-phase` @@ -421,7 +441,7 @@ List missing test files, framework config, or shared fixtures needed before impl ## Step 6: Write RESEARCH.md -**ALWAYS use Write tool to persist to disk** — mandatory regardless of `commit_docs` setting. +**ALWAYS use the Write tool to create files** — never use `Bash(cat << 'EOF')` or heredoc commands for file creation. Mandatory regardless of `commit_docs` setting. **CRITICAL: If CONTEXT.md exists, FIRST content section MUST be ``:** diff --git a/agents/gsd-plan-checker.md b/agents/gsd-plan-checker.md index 958dbd0de8..27e029defd 100644 --- a/agents/gsd-plan-checker.md +++ b/agents/gsd-plan-checker.md @@ -3,6 +3,8 @@ name: gsd-plan-checker description: Verifies plans will achieve phase goal before execution. Goal-backward analysis of plan quality. Spawned by /gsd:plan-phase orchestrator. tools: Read, Bash, Glob, Grep color: green +skills: + - gsd-plan-checker-workflow --- @@ -41,6 +43,7 @@ Before verifying, discover project context: This ensures verification checks that plans follow project-specific conventions. + **CONTEXT.md** (if exists) — User decisions from `/gsd:discuss-phase` diff --git a/agents/gsd-planner.md b/agents/gsd-planner.md index dac65fd99f..a345ac2c48 100644 --- a/agents/gsd-planner.md +++ b/agents/gsd-planner.md @@ -3,6 +3,14 @@ name: gsd-planner description: Creates executable phase plans with task breakdown, dependency analysis, and goal-backward verification. Spawned by /gsd:plan-phase orchestrator. tools: Read, Write, Bash, Glob, Grep, WebFetch, mcp__context7__* color: green +skills: + - gsd-planner-workflow +# hooks: +# PostToolUse: +# - matcher: "Write|Edit" +# hooks: +# - type: command +# command: "npx eslint --fix $FILE 2>/dev/null || true" --- @@ -43,6 +51,18 @@ Before planning, discover project context: This ensures task actions reference the correct patterns and libraries for this project. + +Before executing tasks that reference MCP tools (e.g., `mcp__context7__*`, `mcp__slack__*`, or any `mcp__*` tool): + +1. **Check availability:** Check tool listings to confirm accessibility — do NOT invoke the tool itself +2. **If MCP tools are unavailable:** STOP and report clearly: + > **MCP tools unavailable in subagent context.** Claude Code bug [#13898](https://github.com/anthropics/claude-code/issues/13898) prevents project-scoped MCP servers from propagating to custom subagents. + > + > **Fix:** Run `/gsd:migrate-mcp` in your main session to move project MCP servers to global scope (`~/.claude/mcp.json`), then restart Claude Code. +3. **Do NOT hallucinate MCP results.** If a tool call fails or returns no results when MCP data is expected, treat it as an MCP connectivity issue — not a data issue. +4. **Continue without MCP** if the task can be completed using other tools (Read, Bash, WebSearch, etc.) + + ## CRITICAL: User Decision Fidelity diff --git a/agents/gsd-project-researcher.md b/agents/gsd-project-researcher.md index 4bd9fe71b3..b99352d47e 100644 --- a/agents/gsd-project-researcher.md +++ b/agents/gsd-project-researcher.md @@ -3,6 +3,14 @@ name: gsd-project-researcher description: Researches domain ecosystem before roadmap creation. Produces files in .planning/research/ consumed during roadmap creation. Spawned by /gsd:new-project or /gsd:new-milestone orchestrators. tools: Read, Write, Bash, Grep, Glob, WebSearch, WebFetch, mcp__context7__* color: cyan +skills: + - gsd-researcher-workflow +# hooks: +# PostToolUse: +# - matcher: "Write|Edit" +# hooks: +# - type: command +# command: "npx eslint --fix $FILE 2>/dev/null || true" --- @@ -26,6 +34,18 @@ Your files feed the roadmap: **Be comprehensive but opinionated.** "Use X because Y" not "Options are X, Y, Z." + +Before executing tasks that reference MCP tools (e.g., `mcp__context7__*`, `mcp__slack__*`, or any `mcp__*` tool): + +1. **Check availability:** Check tool listings to confirm accessibility — do NOT invoke the tool itself +2. **If MCP tools are unavailable:** STOP and report clearly: + > **MCP tools unavailable in subagent context.** Claude Code bug [#13898](https://github.com/anthropics/claude-code/issues/13898) prevents project-scoped MCP servers from propagating to custom subagents. + > + > **Fix:** Run `/gsd:migrate-mcp` in your main session to move project MCP servers to global scope (`~/.claude/mcp.json`), then restart Claude Code. +3. **Do NOT hallucinate MCP results.** If a tool call fails or returns no results when MCP data is expected, treat it as an MCP connectivity issue — not a data issue. +4. **Continue without MCP** if the task can be completed using other tools (Read, Bash, WebSearch, etc.) + + ## Training Data = Hypothesis @@ -518,6 +538,8 @@ Run pre-submission checklist (see verification_protocol). ## Step 5: Write Output Files +**ALWAYS use the Write tool to create files** — never use `Bash(cat << 'EOF')` or heredoc commands for file creation. + In `.planning/research/`: 1. **SUMMARY.md** — Always 2. **STACK.md** — Always diff --git a/agents/gsd-research-synthesizer.md b/agents/gsd-research-synthesizer.md index 3bf216dc09..c5323ac2e1 100644 --- a/agents/gsd-research-synthesizer.md +++ b/agents/gsd-research-synthesizer.md @@ -3,6 +3,14 @@ name: gsd-research-synthesizer description: Synthesizes research outputs from parallel researcher agents into SUMMARY.md. Spawned by /gsd:new-project after 4 researcher agents complete. tools: Read, Write, Bash color: purple +skills: + - gsd-synthesizer-workflow +# hooks: +# PostToolUse: +# - matcher: "Write|Edit" +# hooks: +# - type: command +# command: "npx eslint --fix $FILE 2>/dev/null || true" --- @@ -26,6 +34,7 @@ If the prompt contains a `` block, you MUST use the `Read` tool t - Commit ALL research files (researchers write but don't commit — you commit everything) + Your SUMMARY.md is consumed by the gsd-roadmapper agent which uses it to: @@ -122,6 +131,8 @@ Identify gaps that couldn't be resolved and need attention during planning. ## Step 6: Write SUMMARY.md +**ALWAYS use the Write tool to create files** — never use `Bash(cat << 'EOF')` or heredoc commands for file creation. + Use template: ~/.claude/get-shit-done/templates/research-project/SUMMARY.md Write to `.planning/research/SUMMARY.md` diff --git a/agents/gsd-roadmapper.md b/agents/gsd-roadmapper.md index 97b5cd22fc..ad2ccb6d67 100644 --- a/agents/gsd-roadmapper.md +++ b/agents/gsd-roadmapper.md @@ -3,6 +3,14 @@ name: gsd-roadmapper description: Creates project roadmaps with phase breakdown, requirement mapping, success criteria derivation, and coverage validation. Spawned by /gsd:new-project orchestrator. tools: Read, Write, Bash, Glob, Grep color: purple +skills: + - gsd-roadmapper-workflow +# hooks: +# PostToolUse: +# - matcher: "Write|Edit" +# hooks: +# - type: command +# command: "npx eslint --fix $FILE 2>/dev/null || true" --- @@ -26,6 +34,7 @@ If the prompt contains a `` block, you MUST use the `Read` tool t - Return structured draft for user approval + Your ROADMAP.md is consumed by `/gsd:plan-phase` which uses it to: @@ -449,7 +458,9 @@ If gaps found, include in draft for user decision. ## Step 7: Write Files Immediately -**Write files first, then return.** This ensures artifacts persist even if context is lost. +**ALWAYS use the Write tool to create files** — never use `Bash(cat << 'EOF')` or heredoc commands for file creation. + +Write files first, then return. This ensures artifacts persist even if context is lost. 1. **Write ROADMAP.md** using output format diff --git a/agents/gsd-verifier.md b/agents/gsd-verifier.md index dba9677741..16cca3a97c 100644 --- a/agents/gsd-verifier.md +++ b/agents/gsd-verifier.md @@ -3,6 +3,14 @@ name: gsd-verifier description: Verifies phase goal achievement through goal-backward analysis. Checks codebase delivers what phase promised, not just that tasks completed. Creates VERIFICATION.md report. tools: Read, Write, Bash, Grep, Glob color: green +skills: + - gsd-verifier-workflow +# hooks: +# PostToolUse: +# - matcher: "Write|Edit" +# hooks: +# - type: command +# command: "npx eslint --fix $FILE 2>/dev/null || true" --- @@ -31,6 +39,7 @@ Before verifying, discover project context: This ensures project-specific patterns, conventions, and best practices are applied during verification. + **Task completion ≠ Goal achievement** diff --git a/commands/gsd/migrate-mcp.md b/commands/gsd/migrate-mcp.md new file mode 100644 index 0000000000..b0a9b2660c --- /dev/null +++ b/commands/gsd/migrate-mcp.md @@ -0,0 +1,109 @@ +--- +name: gsd:migrate-mcp +description: Migrate project MCP servers to global scope for subagent access +allowed-tools: + - Read + - Write + - AskUserQuestion +--- + + +Help users migrate project-scoped MCP servers (`.mcp.json`) to global scope (`~/.claude/mcp.json`) so that GSD subagents can access them. + +**Why this is needed:** Claude Code bug #13898 prevents custom subagents from accessing project-scoped MCP servers. Global MCP servers work correctly in all agent types. This command provides the migration path. + + + + +## Step 1: Read Project MCP Configuration + +Use the **Read tool** to read `.mcp.json` in the project root. + +**If `.mcp.json` does not exist or is empty:** +Report to the user: + +> No `.mcp.json` found in the current project root. +> +> This command migrates project-scoped MCP servers to global scope so GSD subagents can use them. If your MCP servers are already configured globally (`~/.claude/mcp.json`), no migration is needed. +> +> **To check your global MCP config**, read `~/.claude/mcp.json`. + +**Stop here** — nothing to migrate. + +**If `.mcp.json` exists and has content:** continue to Step 2. + +## Step 2: Parse and Display Server List + +Parse the JSON from `.mcp.json`. Extract the `mcpServers` object (the top-level key containing server definitions). + +Display to the user: + +> **Project MCP Servers Found:** +> +> | Server Name | Command | Status | +> |------------|---------|--------| +> | {name} | {command} {args[0]...} | Project-scoped | +> +> These servers are currently only available in your main Claude Code session. GSD subagents (executor, planner, verifier, etc.) **cannot access them** due to Claude Code bug [#13898](https://github.com/anthropics/claude-code/issues/13898). +> +> **Migrating to global scope** (`~/.claude/mcp.json`) makes them available everywhere, including in subagents. + +## Step 3: Read Global MCP Configuration + +Use the **Read tool** to read `~/.claude/mcp.json`. + +Parse existing global servers (if any). Identify: +- **New servers:** In project config but NOT in global config (will be added) +- **Conflicting servers:** Same name exists in both configs (needs merge decision) +- **Already global:** Same name AND same config in both (skip — already migrated) + +Display the merge plan: + +> **Migration Plan:** +> +> | Server | Action | Notes | +> |--------|--------|-------| +> | {name} | ADD | Not in global config | +> | {name} | SKIP | Already in global config (identical) | +> | {name} | CONFLICT | Exists in global with different config | +> +> **Trade-off:** Global servers are available in ALL projects, not just this one. If a server is project-specific (e.g., a local dev database), consider whether global scope is appropriate. + +**If there are CONFLICT servers:** Ask the user for each one whether to: +1. **Overwrite** the global config with the project version +2. **Keep** the existing global config +3. **Skip** this server + +## Step 4: Perform Migration + +**ALWAYS use the Write tool** to write `~/.claude/mcp.json` — never use heredoc or `cat < **Migration Complete** +> +> | Server | Status | +> |--------|--------| +> | {name} | Migrated to global scope | +> | {name} | Skipped (already global) | +> | {name} | Skipped (user chose to keep existing) | +> +> **Next steps:** +> 1. Restart Claude Code for the changes to take effect +> 2. GSD subagents will now have access to these MCP servers +> 3. You can keep `.mcp.json` in your project (it won't conflict) +> +> **Note:** If you later add new MCP servers to `.mcp.json`, run `/gsd:migrate-mcp` again to sync them to global scope. + + diff --git a/commands/gsd/research-phase.md b/commands/gsd/research-phase.md index be3d9a0eb3..ac8634edab 100644 --- a/commands/gsd/research-phase.md +++ b/commands/gsd/research-phase.md @@ -135,8 +135,8 @@ Write to: .planning/phases/${PHASE}-{slug}/${PHASE}-RESEARCH.md ``` Task( - prompt="First, read ~/.claude/agents/gsd-phase-researcher.md for your role and instructions.\n\n" + filled_prompt, - subagent_type="general-purpose", + prompt=filled_prompt, + subagent_type="gsd-phase-researcher", model="{researcher_model}", description="Research Phase {phase}" ) @@ -171,8 +171,8 @@ Continue research for Phase {phase_number}: {phase_name} ``` Task( - prompt="First, read ~/.claude/agents/gsd-phase-researcher.md for your role and instructions.\n\n" + continuation_prompt, - subagent_type="general-purpose", + prompt=continuation_prompt, + subagent_type="gsd-phase-researcher", model="{researcher_model}", description="Continue research Phase {phase}" ) diff --git a/docs/MCP-FRONTMATTER-FINDINGS.md b/docs/MCP-FRONTMATTER-FINDINGS.md new file mode 100644 index 0000000000..9dce044fca --- /dev/null +++ b/docs/MCP-FRONTMATTER-FINDINGS.md @@ -0,0 +1,54 @@ +# mcpServers Frontmatter Test Findings + +**Date:** 2026-02-28 +**Claude Code Version:** Current (Opus 4.6) +**GSD Version:** v1.22.0 +**Source:** Claude Code official docs (code.claude.com/docs/en/sub-agents) + +## Summary + +Claude Code's `mcpServers:` frontmatter field DOES create independent MCP server connections in custom subagents. However, this does NOT solve GSD's MCP access problem because GSD agents are installed as generic templates — we cannot hardcode user-specific MCP server configurations. + +## Evidence from Official Documentation + +From code.claude.com/docs/en/sub-agents (accessed 2026-02-28): + +> **mcpServers** (optional): MCP servers available to this subagent. Each entry is either a server name referencing an already-configured server (e.g., "slack") or an inline definition with the server name as key and a full MCP server config as value. + +This confirms: +1. **Inline definitions work** — defining a full MCP server config in frontmatter creates an independent connection +2. **Named references work** — referencing an already-configured server by name makes it available +3. **Subagents don't inherit MCP by default** — you must explicitly list servers + +## Test Conditions (Logical Analysis) + +| Condition | Config | Agent Type | Frontmatter | Result | Reasoning | +|-----------|--------|------------|-------------|--------|-----------| +| A | .mcp.json (project) | Main session | N/A | PASS | Main session always has access | +| B | .mcp.json (project) | Custom agent | None | FAIL | Bug #13898 — project MCP doesn't propagate | +| C | Inline in frontmatter | Custom agent | Yes (inline) | PASS | Independent connection per docs | +| D | ~/.claude/mcp.json (global) | Custom agent | None | PASS | Global MCP propagates correctly | + +## Why This Doesn't Solve GSD's Problem + +GSD agents are **generic templates** installed to `~/.claude/get-shit-done/agents/`. They serve all users across all projects. We cannot: + +1. Hardcode user-specific MCP server commands in agent frontmatter +2. Know at install time what MCP servers a user will need +3. Dynamically modify frontmatter at spawn time (Claude Code loads .md files as-is) + +The `mcpServers:` frontmatter approach works for **project-specific custom agents** (in `.claude/agents/`) but NOT for globally-installed agent templates like GSD's. + +## Strategy Decision + +**Proceed with PR-6 (MCP migration helper + connectivity pre-check)** as the practical solution: + +1. `/gsd:migrate-mcp` helps users move project MCP to global scope (proven to work) +2. MCP connectivity pre-check prevents hallucination (defense-in-depth) +3. Users with project-specific agents can add `mcpServers:` to their own `.claude/agents/` definitions + +The general-purpose fallback (PR-5) is deprioritized — named agent types are better for role isolation, model control, and frontmatter features (skills, hooks). Users needing MCP should migrate to global scope. + +## Upstream Issue + +Claude Code #13898 remains OPEN. The fix should be at the Claude Code level — project-scoped MCP servers should propagate to custom subagents. Until then, global MCP or `mcpServers:` frontmatter in project-specific agents are the workarounds. diff --git a/get-shit-done/workflows/diagnose-issues.md b/get-shit-done/workflows/diagnose-issues.md index 274b50c57c..e9b4d5acc7 100644 --- a/get-shit-done/workflows/diagnose-issues.md +++ b/get-shit-done/workflows/diagnose-issues.md @@ -80,7 +80,7 @@ For each gap, fill the debug-subagent-prompt template and spawn: ``` Task( prompt=filled_debug_subagent_prompt + "\n\n\n- {phase_dir}/{phase_num}-UAT.md\n- .planning/STATE.md\n", - subagent_type="general-purpose", + subagent_type="gsd-debugger", description="Debug: {truth_short}" ) ``` diff --git a/get-shit-done/workflows/new-project.md b/get-shit-done/workflows/new-project.md index e7c56a4a9f..c2d2e2ba84 100644 --- a/get-shit-done/workflows/new-project.md +++ b/get-shit-done/workflows/new-project.md @@ -544,9 +544,7 @@ Display spawning indicator: Spawn 4 parallel gsd-project-researcher agents with path references: ``` -Task(prompt="First, read ~/.claude/agents/gsd-project-researcher.md for your role and instructions. - - +Task(prompt=" Project Research — Stack dimension for [domain]. @@ -582,11 +580,9 @@ Your STACK.md feeds into roadmap creation. Be prescriptive: Write to: .planning/research/STACK.md Use template: ~/.claude/get-shit-done/templates/research-project/STACK.md -", subagent_type="general-purpose", model="{researcher_model}", description="Stack research") - -Task(prompt="First, read ~/.claude/agents/gsd-project-researcher.md for your role and instructions. +", subagent_type="gsd-project-researcher", model="{researcher_model}", description="Stack research") - +Task(prompt=" Project Research — Features dimension for [domain]. @@ -622,11 +618,9 @@ Your FEATURES.md feeds into requirements definition. Categorize clearly: Write to: .planning/research/FEATURES.md Use template: ~/.claude/get-shit-done/templates/research-project/FEATURES.md -", subagent_type="general-purpose", model="{researcher_model}", description="Features research") +", subagent_type="gsd-project-researcher", model="{researcher_model}", description="Features research") -Task(prompt="First, read ~/.claude/agents/gsd-project-researcher.md for your role and instructions. - - +Task(prompt=" Project Research — Architecture dimension for [domain]. @@ -662,11 +656,9 @@ Your ARCHITECTURE.md informs phase structure in roadmap. Include: Write to: .planning/research/ARCHITECTURE.md Use template: ~/.claude/get-shit-done/templates/research-project/ARCHITECTURE.md -", subagent_type="general-purpose", model="{researcher_model}", description="Architecture research") - -Task(prompt="First, read ~/.claude/agents/gsd-project-researcher.md for your role and instructions. +", subagent_type="gsd-project-researcher", model="{researcher_model}", description="Architecture research") - +Task(prompt=" Project Research — Pitfalls dimension for [domain]. @@ -702,7 +694,7 @@ Your PITFALLS.md prevents mistakes in roadmap/planning. For each pitfall: Write to: .planning/research/PITFALLS.md Use template: ~/.claude/get-shit-done/templates/research-project/PITFALLS.md -", subagent_type="general-purpose", model="{researcher_model}", description="Pitfalls research") +", subagent_type="gsd-project-researcher", model="{researcher_model}", description="Pitfalls research") ``` After all 4 agents complete, spawn synthesizer to create SUMMARY.md: diff --git a/get-shit-done/workflows/plan-phase.md b/get-shit-done/workflows/plan-phase.md index 7bf31efba3..27c1689a74 100644 --- a/get-shit-done/workflows/plan-phase.md +++ b/get-shit-done/workflows/plan-phase.md @@ -207,8 +207,8 @@ Write to: {phase_dir}/{phase_num}-RESEARCH.md ``` Task( - prompt="First, read ~/.claude/agents/gsd-phase-researcher.md for your role and instructions.\n\n" + research_prompt, - subagent_type="general-purpose", + prompt=research_prompt, + subagent_type="gsd-phase-researcher", model="{researcher_model}", description="Research Phase {phase}" ) @@ -320,8 +320,8 @@ Output consumed by /gsd:execute-phase. Plans need: ``` Task( - prompt="First, read ~/.claude/agents/gsd-planner.md for your role and instructions.\n\n" + filled_prompt, - subagent_type="general-purpose", + prompt=filled_prompt, + subagent_type="gsd-planner", model="{planner_model}", description="Plan Phase {phase}" ) @@ -417,8 +417,8 @@ Return what changed. ``` Task( - prompt="First, read ~/.claude/agents/gsd-planner.md for your role and instructions.\n\n" + revision_prompt, - subagent_type="general-purpose", + prompt=revision_prompt, + subagent_type="gsd-planner", model="{planner_model}", description="Revise Phase {phase} plans" ) diff --git a/get-shit-done/workflows/quick.md b/get-shit-done/workflows/quick.md index e68f140437..3c9bcaa82d 100644 --- a/get-shit-done/workflows/quick.md +++ b/get-shit-done/workflows/quick.md @@ -222,8 +222,8 @@ Return what changed. ``` Task( - prompt="First, read ~/.claude/agents/gsd-planner.md for your role and instructions.\n\n" + revision_prompt, - subagent_type="general-purpose", + prompt=revision_prompt, + subagent_type="gsd-planner", model="{planner_model}", description="Revise quick plan: ${DESCRIPTION}" ) diff --git a/tests/agent-frontmatter.test.cjs b/tests/agent-frontmatter.test.cjs new file mode 100644 index 0000000000..9518d3b2d2 --- /dev/null +++ b/tests/agent-frontmatter.test.cjs @@ -0,0 +1,181 @@ +/** + * GSD Agent Frontmatter Tests + * + * Validates that all agent .md files have correct frontmatter fields: + * - Anti-heredoc instruction present in file-writing agents + * - skills: field in all agents + * - Commented hooks: pattern in file-writing agents + * - Spawn type consistency across workflows + */ + +const { test, describe } = require('node:test'); +const assert = require('node:assert'); +const fs = require('fs'); +const path = require('path'); + +const AGENTS_DIR = path.join(__dirname, '..', 'agents'); +const WORKFLOWS_DIR = path.join(__dirname, '..', 'get-shit-done', 'workflows'); +const COMMANDS_DIR = path.join(__dirname, '..', 'commands', 'gsd'); + +const ALL_AGENTS = fs.readdirSync(AGENTS_DIR) + .filter(f => f.startsWith('gsd-') && f.endsWith('.md')) + .map(f => f.replace('.md', '')); + +const FILE_WRITING_AGENTS = ALL_AGENTS.filter(name => { + const content = fs.readFileSync(path.join(AGENTS_DIR, name + '.md'), 'utf-8'); + const toolsMatch = content.match(/^tools:\s*(.+)$/m); + return toolsMatch && toolsMatch[1].includes('Write'); +}); + +const READ_ONLY_AGENTS = ALL_AGENTS.filter(name => !FILE_WRITING_AGENTS.includes(name)); + +// ─── Anti-Heredoc Instruction ──────────────────────────────────────────────── + +describe('HDOC: anti-heredoc instruction', () => { + for (const agent of FILE_WRITING_AGENTS) { + test(`${agent} has anti-heredoc instruction`, () => { + const content = fs.readFileSync(path.join(AGENTS_DIR, agent + '.md'), 'utf-8'); + assert.ok( + content.includes("never use `Bash(cat << 'EOF')` or heredoc"), + `${agent} missing anti-heredoc instruction` + ); + }); + } + + test('no active heredoc patterns in any agent file', () => { + for (const agent of ALL_AGENTS) { + const content = fs.readFileSync(path.join(AGENTS_DIR, agent + '.md'), 'utf-8'); + // Match actual heredoc commands (not references in anti-heredoc instruction) + const lines = content.split('\n'); + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + // Skip lines that are part of the anti-heredoc instruction or markdown code fences + if (line.includes('never use') || line.includes('NEVER') || line.trim().startsWith('```')) continue; + // Check for actual heredoc usage instructions + if (/^cat\s+<<\s*'?EOF'?\s*>/.test(line.trim())) { + assert.fail(`${agent}:${i + 1} has active heredoc pattern: ${line.trim()}`); + } + } + } + }); +}); + +// ─── Skills Frontmatter ────────────────────────────────────────────────────── + +describe('SKILL: skills frontmatter', () => { + for (const agent of ALL_AGENTS) { + test(`${agent} has skills: in frontmatter`, () => { + const content = fs.readFileSync(path.join(AGENTS_DIR, agent + '.md'), 'utf-8'); + const frontmatter = content.split('---')[1] || ''; + assert.ok( + frontmatter.includes('skills:'), + `${agent} missing skills: in frontmatter` + ); + }); + } + + test('skill references follow naming convention', () => { + for (const agent of ALL_AGENTS) { + const content = fs.readFileSync(path.join(AGENTS_DIR, agent + '.md'), 'utf-8'); + const frontmatter = content.split('---')[1] || ''; + const skillLines = frontmatter.split('\n').filter(l => l.trim().startsWith('- gsd-')); + for (const line of skillLines) { + const skillName = line.trim().replace('- ', ''); + assert.match(skillName, /^gsd-[\w-]+-workflow$/, `Invalid skill name: ${skillName}`); + } + } + }); +}); + +// ─── Hooks Frontmatter ─────────────────────────────────────────────────────── + +describe('HOOK: hooks frontmatter pattern', () => { + for (const agent of FILE_WRITING_AGENTS) { + test(`${agent} has commented hooks pattern`, () => { + const content = fs.readFileSync(path.join(AGENTS_DIR, agent + '.md'), 'utf-8'); + const frontmatter = content.split('---')[1] || ''; + assert.ok( + frontmatter.includes('# hooks:'), + `${agent} missing commented hooks: pattern in frontmatter` + ); + }); + } + + for (const agent of READ_ONLY_AGENTS) { + test(`${agent} (read-only) does not need hooks`, () => { + const content = fs.readFileSync(path.join(AGENTS_DIR, agent + '.md'), 'utf-8'); + const frontmatter = content.split('---')[1] || ''; + // Read-only agents may or may not have hooks — just verify they parse + assert.ok(frontmatter.includes('name:'), `${agent} has valid frontmatter`); + }); + } +}); + +// ─── Spawn Type Consistency ────────────────────────────────────────────────── + +describe('SPAWN: spawn type consistency', () => { + test('no "First, read agent .md" workaround pattern remains', () => { + const dirs = [WORKFLOWS_DIR, COMMANDS_DIR]; + for (const dir of dirs) { + if (!fs.existsSync(dir)) continue; + const files = fs.readdirSync(dir).filter(f => f.endsWith('.md')); + for (const file of files) { + const content = fs.readFileSync(path.join(dir, file), 'utf-8'); + const hasWorkaround = content.includes('First, read ~/.claude/agents/gsd-'); + assert.ok( + !hasWorkaround, + `${file} still has "First, read agent .md" workaround — use named subagent_type instead` + ); + } + } + }); + + test('named agent spawns use correct agent names', () => { + const validAgentTypes = new Set([ + ...ALL_AGENTS, + 'general-purpose', // Allowed for orchestrator spawns + ]); + + const dirs = [WORKFLOWS_DIR, COMMANDS_DIR]; + for (const dir of dirs) { + if (!fs.existsSync(dir)) continue; + const files = fs.readdirSync(dir).filter(f => f.endsWith('.md')); + for (const file of files) { + const content = fs.readFileSync(path.join(dir, file), 'utf-8'); + const matches = content.matchAll(/subagent_type="([^"]+)"/g); + for (const match of matches) { + const agentType = match[1]; + assert.ok( + validAgentTypes.has(agentType), + `${file} references unknown agent type: ${agentType}` + ); + } + } + } + }); + + test('diagnose-issues uses gsd-debugger (not general-purpose)', () => { + const content = fs.readFileSync( + path.join(WORKFLOWS_DIR, 'diagnose-issues.md'), 'utf-8' + ); + assert.ok( + content.includes('subagent_type="gsd-debugger"'), + 'diagnose-issues should spawn gsd-debugger, not general-purpose' + ); + }); +}); + +// ─── Required Frontmatter Fields ───────────────────────────────────────────── + +describe('AGENT: required frontmatter fields', () => { + for (const agent of ALL_AGENTS) { + test(`${agent} has name, description, tools, color`, () => { + const content = fs.readFileSync(path.join(AGENTS_DIR, agent + '.md'), 'utf-8'); + const frontmatter = content.split('---')[1] || ''; + assert.ok(frontmatter.includes('name:'), `${agent} missing name:`); + assert.ok(frontmatter.includes('description:'), `${agent} missing description:`); + assert.ok(frontmatter.includes('tools:'), `${agent} missing tools:`); + assert.ok(frontmatter.includes('color:'), `${agent} missing color:`); + }); + } +});