test(S03/T03): Register gsd_replan_slice and gsd_reassess_roadmap tools…
- 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
This commit is contained in:
parent
46c5d37a8d
commit
356d54431e
7 changed files with 288 additions and 10 deletions
|
|
@ -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`.
|
||||
|
|
|
|||
18
.gsd/milestones/M001/slices/S03/tasks/T02-VERIFY.json
Normal file
18
.gsd/milestones/M001/slices/S03/tasks/T02-VERIFY.json
Normal file
|
|
@ -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
|
||||
}
|
||||
74
.gsd/milestones/M001/slices/S03/tasks/T03-SUMMARY.md
Normal file
74
.gsd/milestones/M001/slices/S03/tasks/T03-SUMMARY.md
Normal file
|
|
@ -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`
|
||||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.**
|
||||
|
||||
|
|
|
|||
|
|
@ -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.**
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue