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:`);
+ });
+ }
+});