From 356d54431e895418f49b125ffa0c86aa9709db98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=82CHES?= Date: Mon, 23 Mar 2026 10:37:08 -0600 Subject: [PATCH] =?UTF-8?q?test(S03/T03):=20Register=20gsd=5Freplan=5Fslic?= =?UTF-8?q?e=20and=20gsd=5Freassess=5Froadmap=20tools=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - src/resources/extensions/gsd/bootstrap/db-tools.ts - src/resources/extensions/gsd/prompts/replan-slice.md - src/resources/extensions/gsd/prompts/reassess-roadmap.md - src/resources/extensions/gsd/tests/prompt-contracts.test.ts --- .gsd/milestones/M001/slices/S03/S03-PLAN.md | 2 +- .../M001/slices/S03/tasks/T02-VERIFY.json | 18 ++ .../M001/slices/S03/tasks/T03-SUMMARY.md | 74 ++++++++ .../extensions/gsd/bootstrap/db-tools.ts | 168 ++++++++++++++++++ .../gsd/prompts/reassess-roadmap.md | 11 +- .../extensions/gsd/prompts/replan-slice.md | 9 +- .../gsd/tests/prompt-contracts.test.ts | 16 ++ 7 files changed, 288 insertions(+), 10 deletions(-) create mode 100644 .gsd/milestones/M001/slices/S03/tasks/T02-VERIFY.json create mode 100644 .gsd/milestones/M001/slices/S03/tasks/T03-SUMMARY.md diff --git a/.gsd/milestones/M001/slices/S03/S03-PLAN.md b/.gsd/milestones/M001/slices/S03/S03-PLAN.md index 514fb6e68..b67657668 100644 --- a/.gsd/milestones/M001/slices/S03/S03-PLAN.md +++ b/.gsd/milestones/M001/slices/S03/S03-PLAN.md @@ -70,7 +70,7 @@ grep -c "structured error payloads" src/resources/extensions/gsd/tests/replan-ha - Verify: `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/reassess-handler.test.ts` - Done when: All reassess handler tests pass, including structural rejection of completed-slice mutations and successful reassess with DB persistence and rendered artifacts. -- [ ] **T03: Register tools in db-tools.ts + update prompts + prompt contract tests** `est:30m` +- [x] **T03: Register tools in db-tools.ts + update prompts + prompt contract tests** `est:30m` - Why: Connects the handlers to the tool system so auto-mode dispatch can invoke them, and updates prompts to name the tools as canonical write paths. Extends prompt contract tests to catch regressions. - Files: `src/resources/extensions/gsd/bootstrap/db-tools.ts`, `src/resources/extensions/gsd/prompts/replan-slice.md`, `src/resources/extensions/gsd/prompts/reassess-roadmap.md`, `src/resources/extensions/gsd/tests/prompt-contracts.test.ts` - Do: (1) Register `gsd_replan_slice` in `db-tools.ts` following the exact pattern of `gsd_plan_slice` — ensureDbOpen check, dynamic import of `../tools/replan-slice.js`, call `handleReplanSlice(params, process.cwd())`, return structured content/details. TypeBox schema matches handler params. Register alias `gsd_slice_replan`. (2) Register `gsd_reassess_roadmap` with alias `gsd_roadmap_reassess` — same pattern, dynamic import of `../tools/reassess-roadmap.js`, call `handleReassessRoadmap(params, process.cwd())`. (3) Update `replan-slice.md` prompt: add a step before the existing file-write instructions that says to use `gsd_replan_slice` tool as the canonical write path when DB-backed tools are available. Position the existing file-write instructions as degraded fallback. Name the specific tool and its parameters. (4) Update `reassess-roadmap.md` prompt: similarly add `gsd_reassess_roadmap` as canonical path. The prompt already has "Do not bypass state with manual roadmap-only edits" — strengthen by naming the specific tool. (5) Add prompt contract tests in `prompt-contracts.test.ts`: assert `replan-slice.md` contains `gsd_replan_slice`, assert `reassess-roadmap.md` contains `gsd_reassess_roadmap`. diff --git a/.gsd/milestones/M001/slices/S03/tasks/T02-VERIFY.json b/.gsd/milestones/M001/slices/S03/tasks/T02-VERIFY.json new file mode 100644 index 000000000..18ea99964 --- /dev/null +++ b/.gsd/milestones/M001/slices/S03/tasks/T02-VERIFY.json @@ -0,0 +1,18 @@ +{ + "schemaVersion": 1, + "taskId": "T02", + "unitId": "M001/S03/T02", + "timestamp": 1774283594680, + "passed": false, + "discoverySource": "package-json", + "checks": [ + { + "command": "npm run test", + "exitCode": 1, + "durationMs": 39663, + "verdict": "fail" + } + ], + "retryAttempt": 1, + "maxRetries": 2 +} diff --git a/.gsd/milestones/M001/slices/S03/tasks/T03-SUMMARY.md b/.gsd/milestones/M001/slices/S03/tasks/T03-SUMMARY.md new file mode 100644 index 000000000..1441a0dd1 --- /dev/null +++ b/.gsd/milestones/M001/slices/S03/tasks/T03-SUMMARY.md @@ -0,0 +1,74 @@ +--- +id: T03 +parent: S03 +milestone: M001 +key_files: + - src/resources/extensions/gsd/bootstrap/db-tools.ts + - src/resources/extensions/gsd/prompts/replan-slice.md + - src/resources/extensions/gsd/prompts/reassess-roadmap.md + - src/resources/extensions/gsd/tests/prompt-contracts.test.ts +key_decisions: + - Prompt updates position the DB-backed tool as canonical write path with direct file writes as degraded fallback — consistent with the pattern established for plan-slice and plan-milestone prompts +duration: "" +verification_result: passed +completed_at: 2026-03-23T16:36:49.549Z +blocker_discovered: false +--- + +# T03: Register gsd_replan_slice and gsd_reassess_roadmap tools in db-tools.ts, update prompts to name canonical tools, add prompt contract tests + +**Register gsd_replan_slice and gsd_reassess_roadmap tools in db-tools.ts, update prompts to name canonical tools, add prompt contract tests** + +## What Happened + +Wired the two new handlers into the tool system and updated prompts to direct auto-mode dispatch through the canonical tool paths. + +**Step 1 — Register `gsd_replan_slice` in `db-tools.ts`:** Added the full tool registration following the exact pattern of `gsd_plan_slice` — `ensureDbOpen()` guard, dynamic `import("../tools/replan-slice.js")`, call `handleReplanSlice(params, process.cwd())`, check for `error` in result, return structured `content`/`details` with `operation: "replan_slice"`. TypeBox schema mirrors `ReplanSliceParams` with all required fields including `updatedTasks` as `Type.Array(Type.Object({...}))` and `removedTaskIds` as `Type.Array(Type.String())`. Registered alias `gsd_slice_replan` → `gsd_replan_slice`. Description mentions structural enforcement of completed tasks. `promptGuidelines` describe the canonical name, alias, parameter list, and enforcement behavior. + +**Step 2 — Register `gsd_reassess_roadmap` in `db-tools.ts`:** Same pattern. Dynamic import of `../tools/reassess-roadmap.js`, call `handleReassessRoadmap(params, process.cwd())`. TypeBox schema mirrors `ReassessRoadmapParams` with `sliceChanges` as a nested `Type.Object` containing `modified`, `added`, and `removed` arrays. Registered alias `gsd_roadmap_reassess` → `gsd_reassess_roadmap`. + +**Step 3 — Update `replan-slice.md` prompt:** Added step 3 "Canonical write path — use `gsd_replan_slice`" before the existing file-write instructions, naming the tool and all its parameters, and explaining it as the canonical write path with structural enforcement. Repositioned existing file-write steps (4–5) as "Degraded fallback — direct file writes" with the condition "If the `gsd_replan_slice` tool is not available". Renumbered all subsequent steps. All existing hard constraints about completed tasks preserved. + +**Step 4 — Update `reassess-roadmap.md` prompt:** Added `gsd_reassess_roadmap` as the canonical write path in both the "roadmap is still good" and "changes are needed" sections. Step 1 under changes needed is now "Canonical write path — use `gsd_reassess_roadmap`" with full parameter documentation. Step 2 is the degraded fallback, augmented with "when `gsd_reassess_roadmap` is available" on the bypass prohibition. + +**Step 5 — Extend `prompt-contracts.test.ts`:** Added two new tests: "replan-slice prompt names gsd_replan_slice as canonical tool" asserts both the tool name and "canonical write path" text; "reassess-roadmap prompt names gsd_reassess_roadmap as canonical tool" does the same. Both tests pass alongside the existing 26 prompt contract tests (28 total). + +## Verification + +All slice-level verification checks pass: +- Prompt contract tests: 28/28 pass (including 2 new tool name assertions) +- Replan handler tests: 9/9 pass (no regressions from db-tools.ts changes) +- Reassess handler tests: 9/9 pass (no regressions) +- Full regression suite (plan-milestone, plan-slice, plan-task, markdown-renderer, rogue-file-detection): 25/25 pass +- Diagnostic grep: Both test files contain structured error payload assertions (1 each) +- grep -q checks: All 4 pass (gsd_replan_slice in prompt and db-tools, gsd_reassess_roadmap in prompt and db-tools) + +## Verification Evidence + +| # | Command | Exit Code | Verdict | Duration | +|---|---------|-----------|---------|----------| +| 1 | `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/prompt-contracts.test.ts` | 0 | ✅ pass | 123ms | +| 2 | `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/replan-handler.test.ts` | 0 | ✅ pass | 324ms | +| 3 | `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/reassess-handler.test.ts` | 0 | ✅ pass | 314ms | +| 4 | `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/plan-milestone.test.ts src/resources/extensions/gsd/tests/plan-slice.test.ts src/resources/extensions/gsd/tests/plan-task.test.ts src/resources/extensions/gsd/tests/markdown-renderer.test.ts src/resources/extensions/gsd/tests/rogue-file-detection.test.ts` | 0 | ✅ pass | 676ms | +| 5 | `grep -c 'structured error payloads' src/resources/extensions/gsd/tests/replan-handler.test.ts src/resources/extensions/gsd/tests/reassess-handler.test.ts` | 0 | ✅ pass | 10ms | +| 6 | `grep -q 'gsd_replan_slice' src/resources/extensions/gsd/prompts/replan-slice.md` | 0 | ✅ pass | 5ms | +| 7 | `grep -q 'gsd_reassess_roadmap' src/resources/extensions/gsd/prompts/reassess-roadmap.md` | 0 | ✅ pass | 5ms | +| 8 | `grep -q 'gsd_replan_slice' src/resources/extensions/gsd/bootstrap/db-tools.ts` | 0 | ✅ pass | 5ms | +| 9 | `grep -q 'gsd_reassess_roadmap' src/resources/extensions/gsd/bootstrap/db-tools.ts` | 0 | ✅ pass | 5ms | + + +## Deviations + +None. + +## Known Issues + +None. + +## Files Created/Modified + +- `src/resources/extensions/gsd/bootstrap/db-tools.ts` +- `src/resources/extensions/gsd/prompts/replan-slice.md` +- `src/resources/extensions/gsd/prompts/reassess-roadmap.md` +- `src/resources/extensions/gsd/tests/prompt-contracts.test.ts` diff --git a/src/resources/extensions/gsd/bootstrap/db-tools.ts b/src/resources/extensions/gsd/bootstrap/db-tools.ts index 4a1d73779..4afe85d95 100644 --- a/src/resources/extensions/gsd/bootstrap/db-tools.ts +++ b/src/resources/extensions/gsd/bootstrap/db-tools.ts @@ -723,4 +723,172 @@ export function registerDbTools(pi: ExtensionAPI): void { pi.registerTool(sliceCompleteTool); registerAlias(pi, sliceCompleteTool, "gsd_complete_slice", "gsd_slice_complete"); + + // ─── gsd_replan_slice (gsd_slice_replan alias) ───────────────────────── + + const replanSliceExecute = async (_toolCallId: any, params: any, _signal: any, _onUpdate: any, _ctx: any) => { + const dbAvailable = await ensureDbOpen(); + if (!dbAvailable) { + return { + content: [{ type: "text" as const, text: "Error: GSD database is not available. Cannot replan slice." }], + details: { operation: "replan_slice", error: "db_unavailable" } as any, + }; + } + try { + const { handleReplanSlice } = await import("../tools/replan-slice.js"); + const result = await handleReplanSlice(params, process.cwd()); + if ("error" in result) { + return { + content: [{ type: "text" as const, text: `Error replanning slice: ${result.error}` }], + details: { operation: "replan_slice", error: result.error } as any, + }; + } + return { + content: [{ type: "text" as const, text: `Replanned slice ${result.sliceId} (${result.milestoneId})` }], + details: { + operation: "replan_slice", + milestoneId: result.milestoneId, + sliceId: result.sliceId, + replanPath: result.replanPath, + planPath: result.planPath, + } as any, + }; + } catch (err) { + const msg = err instanceof Error ? err.message : String(err); + process.stderr.write(`gsd-db: replan_slice tool failed: ${msg}\n`); + return { + content: [{ type: "text" as const, text: `Error replanning slice: ${msg}` }], + details: { operation: "replan_slice", error: msg } as any, + }; + } + }; + + const replanSliceTool = { + name: "gsd_replan_slice", + label: "Replan Slice", + description: + "Replan a slice after a blocker is discovered. Structurally enforces preservation of completed tasks — " + + "mutations to completed task IDs are rejected with actionable error payloads. Writes replan history to DB, " + + "applies task mutations, re-renders PLAN.md, and renders REPLAN.md.", + promptSnippet: "Replan a GSD slice with structural enforcement of completed tasks", + promptGuidelines: [ + "Use gsd_replan_slice (canonical) or gsd_slice_replan (alias) when a blocker is discovered and the slice plan needs rewriting.", + "The tool structurally enforces that completed tasks cannot be updated or removed — violations return specific error payloads naming the blocked task ID.", + "Parameters: milestoneId, sliceId, blockerTaskId, blockerDescription, whatChanged, updatedTasks (array), removedTaskIds (array).", + "updatedTasks items: taskId, title, description, estimate, files, verify, inputs, expectedOutput.", + ], + parameters: Type.Object({ + milestoneId: Type.String({ description: "Milestone ID (e.g. M001)" }), + sliceId: Type.String({ description: "Slice ID (e.g. S01)" }), + blockerTaskId: Type.String({ description: "Task ID that discovered the blocker" }), + blockerDescription: Type.String({ description: "Description of the blocker" }), + whatChanged: Type.String({ description: "Summary of what changed in the plan" }), + updatedTasks: Type.Array( + Type.Object({ + taskId: Type.String({ description: "Task ID (e.g. T01)" }), + title: Type.String({ description: "Task title" }), + description: Type.String({ description: "Task description / steps block" }), + estimate: Type.String({ description: "Task estimate string" }), + files: Type.Array(Type.String(), { description: "Files likely touched" }), + verify: Type.String({ description: "Verification command or block" }), + inputs: Type.Array(Type.String(), { description: "Input files or references" }), + expectedOutput: Type.Array(Type.String(), { description: "Expected output files or artifacts" }), + }), + { description: "Tasks to upsert (update existing or insert new)" }, + ), + removedTaskIds: Type.Array(Type.String(), { description: "Task IDs to remove from the slice" }), + }), + execute: replanSliceExecute, + }; + + pi.registerTool(replanSliceTool); + registerAlias(pi, replanSliceTool, "gsd_slice_replan", "gsd_replan_slice"); + + // ─── gsd_reassess_roadmap (gsd_roadmap_reassess alias) ───────────────── + + const reassessRoadmapExecute = async (_toolCallId: any, params: any, _signal: any, _onUpdate: any, _ctx: any) => { + const dbAvailable = await ensureDbOpen(); + if (!dbAvailable) { + return { + content: [{ type: "text" as const, text: "Error: GSD database is not available. Cannot reassess roadmap." }], + details: { operation: "reassess_roadmap", error: "db_unavailable" } as any, + }; + } + try { + const { handleReassessRoadmap } = await import("../tools/reassess-roadmap.js"); + const result = await handleReassessRoadmap(params, process.cwd()); + if ("error" in result) { + return { + content: [{ type: "text" as const, text: `Error reassessing roadmap: ${result.error}` }], + details: { operation: "reassess_roadmap", error: result.error } as any, + }; + } + return { + content: [{ type: "text" as const, text: `Reassessed roadmap for milestone ${result.milestoneId} after ${result.completedSliceId}` }], + details: { + operation: "reassess_roadmap", + milestoneId: result.milestoneId, + completedSliceId: result.completedSliceId, + assessmentPath: result.assessmentPath, + roadmapPath: result.roadmapPath, + } as any, + }; + } catch (err) { + const msg = err instanceof Error ? err.message : String(err); + process.stderr.write(`gsd-db: reassess_roadmap tool failed: ${msg}\n`); + return { + content: [{ type: "text" as const, text: `Error reassessing roadmap: ${msg}` }], + details: { operation: "reassess_roadmap", error: msg } as any, + }; + } + }; + + const reassessRoadmapTool = { + name: "gsd_reassess_roadmap", + label: "Reassess Roadmap", + description: + "Reassess the milestone roadmap after a slice completes. Structurally enforces preservation of completed slices — " + + "mutations to completed slice IDs are rejected with actionable error payloads. Writes assessment to DB, " + + "applies slice mutations, re-renders ROADMAP.md, and renders ASSESSMENT.md.", + promptSnippet: "Reassess a GSD roadmap with structural enforcement of completed slices", + promptGuidelines: [ + "Use gsd_reassess_roadmap (canonical) or gsd_roadmap_reassess (alias) after a slice completes to reassess the roadmap.", + "The tool structurally enforces that completed slices cannot be modified or removed — violations return specific error payloads naming the blocked slice ID.", + "Parameters: milestoneId, completedSliceId, verdict, assessment, sliceChanges (object with modified, added, removed arrays).", + "sliceChanges.modified items: sliceId, title, risk (optional), depends (optional), demo (optional).", + ], + parameters: Type.Object({ + milestoneId: Type.String({ description: "Milestone ID (e.g. M001)" }), + completedSliceId: Type.String({ description: "Slice ID that just completed" }), + verdict: Type.String({ description: "Assessment verdict (e.g. 'roadmap-confirmed', 'roadmap-adjusted')" }), + assessment: Type.String({ description: "Assessment text explaining the decision" }), + sliceChanges: Type.Object({ + modified: Type.Array( + Type.Object({ + sliceId: Type.String({ description: "Slice ID to modify" }), + title: Type.String({ description: "Updated slice title" }), + risk: Type.Optional(Type.String({ description: "Updated risk level" })), + depends: Type.Optional(Type.Array(Type.String(), { description: "Updated dependencies" })), + demo: Type.Optional(Type.String({ description: "Updated demo text" })), + }), + { description: "Slices to modify" }, + ), + added: Type.Array( + Type.Object({ + sliceId: Type.String({ description: "New slice ID" }), + title: Type.String({ description: "New slice title" }), + risk: Type.Optional(Type.String({ description: "Risk level" })), + depends: Type.Optional(Type.Array(Type.String(), { description: "Dependencies" })), + demo: Type.Optional(Type.String({ description: "Demo text" })), + }), + { description: "New slices to add" }, + ), + removed: Type.Array(Type.String(), { description: "Slice IDs to remove" }), + }, { description: "Slice changes to apply" }), + }), + execute: reassessRoadmapExecute, + }; + + pi.registerTool(reassessRoadmapTool); + registerAlias(pi, reassessRoadmapTool, "gsd_roadmap_reassess", "gsd_reassess_roadmap"); } diff --git a/src/resources/extensions/gsd/prompts/reassess-roadmap.md b/src/resources/extensions/gsd/prompts/reassess-roadmap.md index 0af21a2e7..b56e58aa1 100644 --- a/src/resources/extensions/gsd/prompts/reassess-roadmap.md +++ b/src/resources/extensions/gsd/prompts/reassess-roadmap.md @@ -50,14 +50,15 @@ If all criteria have at least one remaining owning slice, the coverage check pas **If the roadmap is still good:** -Write `{{assessmentPath}}` with a brief confirmation that roadmap coverage still holds after {{completedSliceId}}. If requirements exist, explicitly note whether requirement coverage remains sound. +Write `{{assessmentPath}}` with a brief confirmation that roadmap coverage still holds after {{completedSliceId}}. If requirements exist, explicitly note whether requirement coverage remains sound. If `gsd_reassess_roadmap` is available, use it with `verdict: "roadmap-confirmed"`, an empty `sliceChanges` object, and the assessment text — the tool writes the assessment to the DB and renders ASSESSMENT.md. **If changes are needed:** -1. Rewrite the remaining (unchecked) slices in `{{roadmapPath}}` only through the DB-backed planning path when that tool is available. Do **not** bypass state with manual roadmap-only edits. Keep completed slices exactly as they are (`[x]`). Update the boundary map for changed slices. Update the proof strategy if risks changed. Update requirement coverage if ownership or scope changed. -2. Write `{{assessmentPath}}` explaining what changed and why — keep it brief and concrete. -3. If `.gsd/REQUIREMENTS.md` exists and requirement ownership or status changed, update it. -4. {{commitInstruction}} +1. **Canonical write path — use `gsd_reassess_roadmap`:** If the `gsd_reassess_roadmap` tool is available, use it to persist the assessment and apply roadmap changes. Pass: `milestoneId`, `completedSliceId`, `verdict` (e.g. "roadmap-adjusted"), `assessment` (text explaining the decision), and `sliceChanges` with `modified` (array of sliceId, title, risk, depends, demo), `added` (same shape), `removed` (array of slice ID strings). The tool structurally enforces preservation of completed slices, writes the assessment to the DB, re-renders ROADMAP.md, and renders ASSESSMENT.md. Skip step 2 if this tool succeeds. +2. **Degraded fallback — direct file writes:** If the `gsd_reassess_roadmap` tool is not available, rewrite the remaining (unchecked) slices in `{{roadmapPath}}` directly. Do **not** bypass state with manual roadmap-only edits when `gsd_reassess_roadmap` is available. Keep completed slices exactly as they are (`[x]`). Update the boundary map for changed slices. Update the proof strategy if risks changed. Update requirement coverage if ownership or scope changed. +3. Write `{{assessmentPath}}` explaining what changed and why — keep it brief and concrete. +4. If `.gsd/REQUIREMENTS.md` exists and requirement ownership or status changed, update it. +5. {{commitInstruction}} **You MUST write the file `{{assessmentPath}}` before finishing.** diff --git a/src/resources/extensions/gsd/prompts/replan-slice.md b/src/resources/extensions/gsd/prompts/replan-slice.md index 50b2c8d44..47e8de7ff 100644 --- a/src/resources/extensions/gsd/prompts/replan-slice.md +++ b/src/resources/extensions/gsd/prompts/replan-slice.md @@ -32,19 +32,20 @@ Consider these captures when rewriting the remaining tasks — they represent th 1. Read the blocker task summary carefully. Understand exactly what was discovered and why it blocks the current plan. 2. Analyze the remaining `[ ]` tasks in the slice plan. Determine which are still valid, which need modification, and which should be replaced. -3. Write `{{replanPath}}` documenting: +3. **Canonical write path — use `gsd_replan_slice`:** If the `gsd_replan_slice` tool is available, use it with the following parameters: `milestoneId`, `sliceId`, `blockerTaskId`, `blockerDescription`, `whatChanged`, `updatedTasks` (array of task objects with taskId, title, description, estimate, files, verify, inputs, expectedOutput), `removedTaskIds` (array of task ID strings). This is the canonical write path — it structurally enforces preservation of completed tasks, writes replan history to the DB, re-renders PLAN.md, and renders REPLAN.md. Skip steps 4–5 if this tool succeeds. +4. **Degraded fallback — direct file writes:** If the `gsd_replan_slice` tool is not available, fall back to writing files directly. Write `{{replanPath}}` documenting: - What blocker was discovered and in which task - What changed in the plan and why - Which incomplete tasks were modified, added, or removed - Any new risks or considerations introduced by the replan -4. Rewrite `{{planPath}}` with the updated slice plan: +5. If using the degraded fallback, rewrite `{{planPath}}` with the updated slice plan: - Keep all `[x]` tasks exactly as they were (same IDs, same descriptions, same checkmarks) - Update the `[ ]` tasks to address the blocker - Ensure the slice Goal and Demo sections are still achievable with the new tasks, or update them if the blocker fundamentally changes what the slice can deliver - Update the Files Likely Touched section if the replan changes which files are affected - If a DB-backed planning tool exists for this phase, use it as the source of truth and make any rewritten `PLAN.md` reflect that persisted state rather than bypassing it -5. If any incomplete task had a `T0x-PLAN.md`, remove or rewrite it to match the new task description. -6. Do not commit manually — the system auto-commits your changes after this unit completes. +6. If any incomplete task had a `T0x-PLAN.md`, remove or rewrite it to match the new task description. +7. Do not commit manually — the system auto-commits your changes after this unit completes. **You MUST write `{{replanPath}}` and the updated slice plan before finishing.** diff --git a/src/resources/extensions/gsd/tests/prompt-contracts.test.ts b/src/resources/extensions/gsd/tests/prompt-contracts.test.ts index f3e738056..bb14adfdb 100644 --- a/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +++ b/src/resources/extensions/gsd/tests/prompt-contracts.test.ts @@ -176,3 +176,19 @@ test("reassess-roadmap prompt forbids roadmap-only manual edits when tool path e const prompt = readPrompt("reassess-roadmap"); assert.match(prompt, /Do \*\*not\*\* bypass state with manual roadmap-only edits/i); }); + +// ─── Prompt migration: replan-slice → gsd_replan_slice ──────────────── + +test("replan-slice prompt names gsd_replan_slice as canonical tool", () => { + const prompt = readPrompt("replan-slice"); + assert.match(prompt, /gsd_replan_slice/); + assert.match(prompt, /canonical write path/i); +}); + +// ─── Prompt migration: reassess-roadmap → gsd_reassess_roadmap ─────── + +test("reassess-roadmap prompt names gsd_reassess_roadmap as canonical tool", () => { + const prompt = readPrompt("reassess-roadmap"); + assert.match(prompt, /gsd_reassess_roadmap/); + assert.match(prompt, /canonical write path/i); +});