fix(#973): add Edit to gsd-planner tools and forbid whole-file Write of ROADMAP.md (#989)

* fix(#973): add Edit to gsd-planner tools and forbid whole-file Write of ROADMAP.md

gsd-planner shipped Write but not Edit — the same writer-agent gap fixed for six
agents in #571/#581. Without Edit, an in-place ROADMAP update fell back to a
whole-file Write that truncated committed milestone history (292→16 lines in a
real incident).

Changes:
- agents/gsd-planner.md: add Edit to tools: frontmatter (adjacent to Write)
- agents/gsd-planner.md: update_roadmap step now directs Edit (scoped), with an
  explicit blocking prohibition on whole-file Write of ROADMAP.md or any existing
  curated .planning/ file
- agents/gsd-planner.md: Write contract section clarifies Write is authorized only
  for net-new PLAN.md creation; existing files must use Edit
- tests/agent-frontmatter.test.cjs: extend SECTION_WRITER_AGENTS list (#581 test)
  to cover gsd-planner — fails before fix, passes after
- .changeset/973-gsd-planner-edit-tool.md: Fixed changeset, pr:0

Closes #973

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore(#973): backfill changeset pr number (989)

* fix(#973): trim gsd-planner.md prose under agent size cap (keep Edit + scoped-Edit-for-ROADMAP rule)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Tom Boucher
2026-06-10 10:44:20 -04:00
committed by GitHub
parent 22bb82e205
commit 2981983bae
4 changed files with 14 additions and 4 deletions

View File

@@ -0,0 +1,5 @@
---
type: Fixed
pr: 989
---
**`gsd-planner` now ships the `Edit` tool, so it can no longer destroy `ROADMAP.md` via a whole-file `Write`** — the planner had `Write` but not `Edit` (the #571/#581 writer-agent gap), so an in-place ROADMAP edit fell back to a full overwrite that truncated committed milestone history. The `update_roadmap` step now directs scoped `Edit` calls and explicitly forbids passing the full file to `Write`. (#973)

View File

@@ -1,7 +1,7 @@
---
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__*
tools: Read, Write, Edit, Bash, Glob, Grep, WebFetch, mcp__context7__*
color: green
# hooks:
# PostToolUse:
@@ -998,6 +998,8 @@ Use template structure for each PLAN.md.
These PLAN.md files are the canonical output of this agent. The orchestrator reads each `.planning/phases/{padded_phase}-{slug}/{padded_phase}-{NN}-PLAN.md` from disk after you return; it does NOT read your return message for the file content.
**Write is for net-new PLAN.md only.** For any existing file (`ROADMAP.md`, `.planning/` files) use `Edit` (scoped replacement), never `Write`. See `update_roadmap`.
1. **Default: write each PLAN.md in a single `Write` call.** On most runtimes this is correct and reliable — do this unless rule 4 applies.
2. **Do NOT return the PLAN.md content in your response.** Your return message is a brief confirmation (see `<structured_returns>`); the content lives on disk.
3. **Do NOT use `Bash(cat << 'EOF')` or heredoc** for file creation. Use the `Write` tool.
@@ -1062,9 +1064,11 @@ Returns JSON: `{ valid, errors, warnings, task_count, tasks }`
<step name="update_roadmap">
Update ROADMAP.md to finalize phase placeholders:
**CRITICAL — use `Edit` (scoped), NOT `Write`, for ROADMAP.md.** A whole-file `Write` destroys all phase entries outside your diff window. Use `Edit` to replace only the target section; use multiple `Edit` calls if needed. NEVER pass the entire ROADMAP.md content to `Write`.
1. Read `.planning/ROADMAP.md`
2. Find phase entry (`### Phase {N}:`)
3. Update placeholders:
3. Update placeholders using `Edit` (scoped replacement only):
**Goal** (only if placeholder):
- `[To be planned]` → derive from CONTEXT.md > RESEARCH.md > phase description
@@ -1080,7 +1084,7 @@ Plans:
- [ ] {phase}-02-PLAN.md — {brief objective}
```
4. Write updated ROADMAP.md
4. Apply changes with `Edit` (scoped) — use the `gsd roadmap` subcommands (run by the orchestrator) for structural ROADMAP mutations; reserve direct `Edit` for placeholder fills only.
</step>
<step name="git_commit">

View File

@@ -161,7 +161,7 @@ GSD uses a multi-agent architecture where thin orchestrators (workflow files) sp
|----------|-------|
| **Spawned by** | `/gsd-plan-phase`, `/gsd-quick` |
| **Parallelism** | Single instance |
| **Tools** | Read, Write, Bash, Glob, Grep, WebFetch, mcp (context7) |
| **Tools** | Read, Write, Edit, Bash, Glob, Grep, WebFetch, mcp (context7) |
| **Model (balanced)** | Opus |
| **Color** | Green |
| **Produces** | `{phase}-{N}-PLAN.md` files |

View File

@@ -435,6 +435,7 @@ describe('EDITWRITE: section-writer agents must have both Write and Edit in tool
'gsd-phase-researcher',
'gsd-ui-researcher',
'gsd-debug-session-manager',
'gsd-planner', // #973: planner lacked Edit; whole-file Write truncated ROADMAP.md
];
for (const agent of SECTION_WRITER_AGENTS) {