diff --git a/src/resources/extensions/gsd/prompts/complete-milestone.md b/src/resources/extensions/gsd/prompts/complete-milestone.md index 91ac07e5d..eac76640e 100644 --- a/src/resources/extensions/gsd/prompts/complete-milestone.md +++ b/src/resources/extensions/gsd/prompts/complete-milestone.md @@ -56,7 +56,7 @@ Then: - `followUps` (string) — Follow-up items for future milestones - `deviations` (string) — Deviations from the original plan 10. For each requirement whose status changed in step 8, call `gsd_requirement_update` with the requirement ID and updated `status` and `validation` fields — the tool regenerates `.gsd/REQUIREMENTS.md` automatically. -11. Update `.gsd/PROJECT.md` to reflect milestone completion and current project state. +11. Update `.gsd/PROJECT.md`: use the `write` tool with `path: ".gsd/PROJECT.md"` and `content` containing the full updated document reflecting milestone completion and current project state. Do NOT use the `edit` tool for this — PROJECT.md is a full-document refresh. 12. Review all slice summaries for cross-cutting lessons, patterns, or gotchas that emerged during this milestone. Append any non-obvious, reusable insights to `.gsd/KNOWLEDGE.md`. 13. Do not commit manually — the system auto-commits your changes after this unit completes. - Say: "Milestone {{milestoneId}} complete." diff --git a/src/resources/extensions/gsd/prompts/complete-slice.md b/src/resources/extensions/gsd/prompts/complete-slice.md index 1be3fd51d..7fc14be5f 100644 --- a/src/resources/extensions/gsd/prompts/complete-slice.md +++ b/src/resources/extensions/gsd/prompts/complete-slice.md @@ -31,7 +31,7 @@ Then: 10. Review task summaries for patterns, gotchas, or non-obvious lessons learned. If any would save future agents from repeating investigation or hitting the same issues, append them to `.gsd/KNOWLEDGE.md`. Only add entries that are genuinely useful — don't pad with obvious observations. 11. Call `gsd_complete_slice` with milestone_id, slice_id, the slice summary, and the UAT result. Do NOT manually mark the roadmap checkbox — the tool writes to the DB and renders the ROADMAP.md projection automatically. 12. Do not run git commands — the system commits your changes and handles any merge after this unit succeeds. -13. Update `.gsd/PROJECT.md` if it exists — refresh current state if needed. +13. Update `.gsd/PROJECT.md` if it exists — refresh current state if needed: use the `write` tool with `path: ".gsd/PROJECT.md"` and `content` containing the full updated document reflecting current project state. Do NOT use the `edit` tool for this — PROJECT.md is a full-document refresh. **Autonomous execution:** Do not call `ask_user_questions` or `secure_env_collect`. You are running in auto-mode — there is no human available to answer questions. Make reasonable assumptions and document them in the slice summary. If a decision genuinely requires human input, note it in the summary and proceed with the best available option. diff --git a/src/resources/extensions/gsd/tests/complete-milestone.test.ts b/src/resources/extensions/gsd/tests/complete-milestone.test.ts index 78211dc0e..c86eeb1e4 100644 --- a/src/resources/extensions/gsd/tests/complete-milestone.test.ts +++ b/src/resources/extensions/gsd/tests/complete-milestone.test.ts @@ -237,6 +237,33 @@ describe("complete-milestone", () => { } }); + test("step 11 specifies write tool for PROJECT.md update (#2946)", () => { + const prompt = loadPromptFromWorktree("complete-milestone", { + workingDirectory: "/tmp/test-project", + milestoneId: "M001", + milestoneTitle: "Tool Guidance Test", + roadmapPath: ".gsd/milestones/M001/M001-ROADMAP.md", + inlinedContext: "context", + milestoneSummaryPath: ".gsd/milestones/M001/M001-SUMMARY.md", + skillActivation: "", + }); + + // Step 11 must explicitly name the `write` tool so the LLM doesn't + // confuse it with `edit` (which requires path + oldText + newText). + // See: https://github.com/gsd-build/gsd-2/issues/2946 + assert.ok( + /PROJECT\.md.*\bwrite\b/i.test(prompt) || /\bwrite\b.*PROJECT\.md/i.test(prompt), + "step 11 must name the `write` tool when updating PROJECT.md", + ); + + // The prompt must NOT leave tool choice ambiguous for PROJECT.md + // Verify it mentions the required parameter (`content` or `path`) + assert.ok( + prompt.includes("`.gsd/PROJECT.md`") || prompt.includes('".gsd/PROJECT.md"'), + "step 11 must reference the PROJECT.md path explicitly", + ); + }); + test("deriveState completing-milestone integration", async () => { const { deriveState, isMilestoneComplete } = await import("../state.ts"); const { invalidateAllCaches: invalidateAllCachesDynamic } = await import("../cache.ts"); diff --git a/src/resources/extensions/gsd/tests/complete-slice.test.ts b/src/resources/extensions/gsd/tests/complete-slice.test.ts index 5dcc16768..ed5073ff8 100644 --- a/src/resources/extensions/gsd/tests/complete-slice.test.ts +++ b/src/resources/extensions/gsd/tests/complete-slice.test.ts @@ -406,6 +406,27 @@ console.log('\n=== complete-slice: handler with missing roadmap ==='); cleanup(dbPath); } +// ═══════════════════════════════════════════════════════════════════════════ +// complete-slice: step 13 specifies write tool for PROJECT.md (#2946) +// ═══════════════════════════════════════════════════════════════════════════ + +console.log('\n=== complete-slice: step 13 specifies write tool for PROJECT.md (#2946) ==='); +{ + const promptPath = path.join( + path.dirname(new URL(import.meta.url).pathname), + '..', 'prompts', 'complete-slice.md', + ); + const prompt = fs.readFileSync(promptPath, 'utf-8'); + + // Step 13 must explicitly name the `write` tool so the LLM doesn't + // confuse it with `edit` (which requires path + oldText + newText). + // See: https://github.com/gsd-build/gsd-2/issues/2946 + const mentionsWriteTool = + /PROJECT\.md.*\bwrite\b/i.test(prompt) || + /\bwrite\b.*PROJECT\.md/i.test(prompt); + assertTrue(mentionsWriteTool, 'step 13 must name the `write` tool when updating PROJECT.md'); +} + // ═══════════════════════════════════════════════════════════════════════════ report();