chore(M001/S03): auto-commit after complete-slice

This commit is contained in:
TÂCHES 2026-03-23 10:41:21 -06:00
parent 356d54431e
commit 50cc29f93b
7 changed files with 252 additions and 1 deletions

View file

@ -58,7 +58,7 @@ This milestone is complete only when all are true:
- [x] **S02: plan_slice + plan_task tools + PLAN/task-plan renderers** `risk:high` `depends:[S01]`
> After this: gsd_plan_slice and gsd_plan_task tools accept structured params, write to DB, render S##-PLAN.md and T##-PLAN.md from DB. Task plan files pass existence checks. Prompt migration for plan-slice.md complete.
- [ ] **S03: replan_slice + reassess_roadmap with structural enforcement** `risk:medium` `depends:[S01,S02]`
- [x] **S03: replan_slice + reassess_roadmap with structural enforcement** `risk:medium` `depends:[S01,S02]`
> After this: gsd_replan_slice rejects mutations to completed tasks, gsd_reassess_roadmap rejects mutations to completed slices. replan_history and assessments tables populated. REPLAN.md and ASSESSMENT.md rendered from DB.
- [ ] **S04: Hot-path caller migration + cross-validation tests** `risk:medium` `depends:[S01,S02]`

View file

@ -0,0 +1,131 @@
---
id: S03
parent: M001
milestone: M001
provides:
- handleReplanSlice() — structural enforcement of completed tasks during replanning
- handleReassessRoadmap() — structural enforcement of completed slices during reassessment
- replan_history table populated with actual replan events
- assessments table populated with actual assessments
- REPLAN.md and ASSESSMENT.md rendered from DB (flag file equivalents for S05)
- gsd_replan_slice and gsd_reassess_roadmap registered in db-tools.ts with aliases
- DB helpers: insertReplanHistory(), insertAssessment(), deleteTask(), deleteSlice(), updateSliceFields(), getReplanHistory(), getAssessment()
- Renderers: renderReplanFromDb(), renderAssessmentFromDb()
requires:
- slice: S01
provides: Schema v8 tables (replan_history, assessments), tool handler pattern from plan-milestone.ts, renderRoadmapFromDb()
- slice: S02
provides: getSliceTasks(), getTask(), upsertTaskPlanning(), insertTask(), insertSlice(), renderPlanFromDb(), renderTaskPlanFromDb()
affects:
- S05
key_files:
- src/resources/extensions/gsd/tools/replan-slice.ts
- src/resources/extensions/gsd/tools/reassess-roadmap.ts
- src/resources/extensions/gsd/gsd-db.ts
- src/resources/extensions/gsd/markdown-renderer.ts
- 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/replan-handler.test.ts
- src/resources/extensions/gsd/tests/reassess-handler.test.ts
- src/resources/extensions/gsd/tests/prompt-contracts.test.ts
key_decisions:
- deleteTask() cascades through verification_evidence before task row (no ON DELETE CASCADE in schema) — manual FK-aware deletion pattern
- updateSliceFields() added separately from upsertSlicePlanning() to keep planning-level vs metadata-level DB APIs distinct
- Structural enforcement checks both 'complete' and 'done' statuses as completed indicators — covers both status variants
patterns_established:
- Structural enforcement pattern: query completed items → build Set → reject before transaction if any mutation targets completed items → return { error } naming specific ID
- Handler error payloads include the specific entity ID that blocked the mutation — actionable diagnostics, not generic messages
- Manual cascade deletion pattern for FK-constrained tables (evidence → tasks → slice) since schema lacks ON DELETE CASCADE
observability_surfaces:
- replan_history DB table — queryable via getReplanHistory(db, milestoneId, sliceId)
- assessments DB table — queryable via getAssessment(db, path)
- REPLAN.md on disk — rendered at slices/S##/REPLAN.md with blocker description and mutation details
- ASSESSMENT.md on disk — rendered at slices/S##/ASSESSMENT.md with verdict and assessment text
- Handler error payloads — { error: string } naming the specific completed task/slice ID that blocked a mutation
drill_down_paths:
- .gsd/milestones/M001/slices/S03/tasks/T01-SUMMARY.md
- .gsd/milestones/M001/slices/S03/tasks/T02-SUMMARY.md
- .gsd/milestones/M001/slices/S03/tasks/T03-SUMMARY.md
duration: ""
verification_result: passed
completed_at: 2026-03-23T16:40:55.867Z
blocker_discovered: false
---
# S03: replan_slice + reassess_roadmap with structural enforcement
**Delivered gsd_replan_slice and gsd_reassess_roadmap tools with structural enforcement that prevents mutations to completed tasks/slices, backed by DB persistence (replan_history, assessments tables) and rendered REPLAN.md/ASSESSMENT.md artifacts.**
## What Happened
S03 built the final two planning tools that complete the structural enforcement layer for the planning state machine.
**T01 — replan_slice handler:** Implemented `handleReplanSlice()` with the validate → enforce → transaction → render → invalidate pattern. Added four DB helpers to `gsd-db.ts`: `insertReplanHistory()`, `insertAssessment()`, `deleteTask()` (with FK-aware cascade through verification_evidence), and `deleteSlice()` (cascade: evidence → tasks → slice). Added `renderReplanFromDb()` and `renderAssessmentFromDb()` to `markdown-renderer.ts` using the `writeAndStore()` pattern. The handler queries `getSliceTasks()`, builds a Set of completed task IDs (status 'complete' or 'done'), and returns a structured `{ error }` naming the specific task ID if any mutation targets a completed task. On success: writes replan_history row, applies task upserts/inserts/deletes in a transaction, then re-renders PLAN.md and writes REPLAN.md. 9 tests cover validation, structural rejection (both update and remove), success path with DB persistence, cache invalidation, idempotency, missing parent, "done" alias, and structured error payloads.
**T02 — reassess_roadmap handler:** Implemented `handleReassessRoadmap()` with the same pattern at the milestone/slice level. Added `updateSliceFields()` to `gsd-db.ts` for title/risk/depends/demo updates (distinct from `upsertSlicePlanning()` which handles planning-level fields). Added `getAssessment()` query helper. The handler queries `getMilestoneSlices()` for completed slices and rejects modifications or removals to them. On success: writes assessments row, applies slice modifications/additions/deletions in a transaction, then re-renders ROADMAP.md and writes ASSESSMENT.md. 9 matching tests.
**T03 — Tool registration + prompts:** Registered `gsd_replan_slice` (alias `gsd_slice_replan`) and `gsd_reassess_roadmap` (alias `gsd_roadmap_reassess`) in `db-tools.ts` with TypeBox schemas matching handler params. Updated `replan-slice.md` and `reassess-roadmap.md` prompts to position the DB-backed tools as canonical write paths with direct file writes as degraded fallback. Extended `prompt-contracts.test.ts` to 28 tests including 2 new tool-name assertions.
All verification passed: 9/9 replan tests, 9/9 reassess tests, 28/28 prompt contract tests, 25/25 regression tests.
## Verification
All slice-level verification checks from the plan passed:
1. **Replan handler tests** (9/9 pass, ~337ms): validation failures, structural rejection of completed task update, structural rejection of completed task removal, successful replan with DB persistence, cache invalidation, idempotency, missing parent slice, "done" status alias, structured error payloads.
2. **Reassess handler tests** (9/9 pass, ~322ms): validation failures, missing milestone, structural rejection of completed slice modification, structural rejection of completed slice removal, successful reassess with DB persistence, cache invalidation, idempotency, "done" status alias, structured error payloads.
3. **Prompt contract tests** (28/28 pass, ~205ms): includes 2 new assertions that replan-slice.md contains `gsd_replan_slice` and reassess-roadmap.md contains `gsd_reassess_roadmap`.
4. **Full regression suite** (25/25 pass, ~723ms): plan-milestone, plan-slice, plan-task, markdown-renderer, rogue-file-detection — no regressions from gsd-db.ts/markdown-renderer.ts changes.
5. **Diagnostic grep**: Both test files contain structured error payload assertions (1 each).
## Requirements Advanced
None.
## Requirements Validated
- R005 — replan-handler.test.ts: 9 tests prove structural rejection of completed task updates/removals, DB persistence of replan_history, re-rendered PLAN.md + REPLAN.md, cache invalidation
- R006 — reassess-handler.test.ts: 9 tests prove structural rejection of completed slice modifications/removals, DB persistence of assessments, re-rendered ROADMAP.md + ASSESSMENT.md, cache invalidation
- R013 — prompt-contracts.test.ts: replan-slice.md contains gsd_replan_slice, reassess-roadmap.md contains gsd_reassess_roadmap — extends existing R013 validation from S01
- R015 — Both handlers call invalidateStateCache() and clearParseCache() after success — tested via cache invalidation tests in replan-handler.test.ts and reassess-handler.test.ts
## New Requirements Surfaced
None.
## Requirements Invalidated or Re-scoped
None.
## Deviations
Minor additive deviations only — all strengthened the implementation:
- Added `getReplanHistory()` and `getAssessment()` query helpers to gsd-db.ts (not in plan) — needed for test DB persistence assertions.
- Added `updateSliceFields()` to gsd-db.ts — needed because `upsertSlicePlanning()` only handles planning-level fields, not basic slice metadata the reassess handler modifies.
- 3 extra tests per handler beyond the minimum specified in the plan (missing parent, "done" alias, structured error payloads).
## Known Limitations
None.
## Follow-ups
None.
## Files Created/Modified
- `src/resources/extensions/gsd/gsd-db.ts` — Added insertReplanHistory(), insertAssessment(), deleteTask(), deleteSlice(), getReplanHistory(), getAssessment(), updateSliceFields() DB helper functions
- `src/resources/extensions/gsd/markdown-renderer.ts` — Added renderReplanFromDb() and renderAssessmentFromDb() using writeAndStore() pattern
- `src/resources/extensions/gsd/tools/replan-slice.ts` — New file — handleReplanSlice() with structural enforcement of completed tasks
- `src/resources/extensions/gsd/tools/reassess-roadmap.ts` — New file — handleReassessRoadmap() with structural enforcement of completed slices
- `src/resources/extensions/gsd/bootstrap/db-tools.ts` — Registered gsd_replan_slice (alias gsd_slice_replan) and gsd_reassess_roadmap (alias gsd_roadmap_reassess) with TypeBox schemas
- `src/resources/extensions/gsd/prompts/replan-slice.md` — Added gsd_replan_slice as canonical write path, repositioned direct file writes as degraded fallback
- `src/resources/extensions/gsd/prompts/reassess-roadmap.md` — Added gsd_reassess_roadmap as canonical write path with full parameter documentation
- `src/resources/extensions/gsd/tests/replan-handler.test.ts` — New file — 9 tests for handleReplanSlice covering validation, structural enforcement, DB persistence, rendering, cache invalidation, idempotency
- `src/resources/extensions/gsd/tests/reassess-handler.test.ts` — New file — 9 tests for handleReassessRoadmap covering validation, structural enforcement, DB persistence, rendering, cache invalidation, idempotency
- `src/resources/extensions/gsd/tests/prompt-contracts.test.ts` — Added 2 new tests asserting replan-slice.md and reassess-roadmap.md name their canonical tools

View file

@ -0,0 +1,70 @@
# S03: replan_slice + reassess_roadmap with structural enforcement — UAT
**Milestone:** M001
**Written:** 2026-03-23T16:40:55.867Z
## UAT: S03 — replan_slice + reassess_roadmap with structural enforcement
### Preconditions
- Node.js available with `--experimental-strip-types` support
- Working directory is the gsd-2 project root
- No prior test artifacts from previous runs
### Test Case 1: Replan structural enforcement rejects completed task mutation
**Steps:**
1. Run `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/replan-handler.test.ts`
2. Verify "rejects structural violation: updating a completed task" passes
3. Verify "rejects structural violation: removing a completed task" passes
4. Verify "rejects task with status 'done' (alias for complete)" passes
**Expected:** All 3 structural rejection tests pass. Error payloads name the specific task ID.
### Test Case 2: Replan success path with DB persistence
**Steps:**
1. In the same test run, verify "succeeds when modifying only incomplete tasks" passes
2. Verify test confirms replan_history row exists in DB after success
3. Verify test confirms PLAN.md and REPLAN.md artifacts exist on disk
4. Verify "cache invalidation: re-parsing PLAN.md reflects mutations" passes
**Expected:** Successful replan writes DB row, renders both artifacts, and invalidates caches so re-parsing shows updated state.
### Test Case 3: Reassess structural enforcement rejects completed slice mutation
**Steps:**
1. Run `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/reassess-handler.test.ts`
2. Verify "rejects structural violation: modifying a completed slice" passes
3. Verify "rejects structural violation: removing a completed slice" passes
4. Verify "rejects slice with status 'done' (alias for complete)" passes
**Expected:** All 3 structural rejection tests pass. Error payloads name the specific slice ID.
### Test Case 4: Reassess success path with DB persistence
**Steps:**
1. In the same test run, verify "succeeds when modifying only pending slices" passes
2. Verify test confirms assessments row exists in DB after success
3. Verify test confirms ROADMAP.md and ASSESSMENT.md artifacts exist on disk
4. Verify "cache invalidation: getMilestoneSlices reflects mutations" passes
**Expected:** Successful reassess writes DB row, renders both artifacts, and invalidates caches.
### Test Case 5: Tool registration and prompt wiring
**Steps:**
1. Run `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/prompt-contracts.test.ts`
2. Verify "replan-slice prompt names gsd_replan_slice as canonical tool" passes
3. Verify "reassess-roadmap prompt names gsd_reassess_roadmap as canonical tool" passes
4. Run `grep -q 'gsd_replan_slice' src/resources/extensions/gsd/bootstrap/db-tools.ts && echo PASS`
5. Run `grep -q 'gsd_reassess_roadmap' src/resources/extensions/gsd/bootstrap/db-tools.ts && echo PASS`
**Expected:** Both prompt contract tests pass. Both grep checks output PASS.
### Test Case 6: Full regression — no breakage from S03 changes
**Steps:**
1. Run `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`
2. Verify all 25 regression tests pass
**Expected:** 25/25 pass, 0 failures. S03 changes to gsd-db.ts and markdown-renderer.ts introduced no regressions.
### Edge Cases
- Idempotency: calling replan/reassess twice with same params succeeds both times (covered by idempotency tests)
- Missing parent: replan with nonexistent slice returns clear error (covered by "missing parent slice" test)
- Missing milestone: reassess with nonexistent milestone returns clear error (covered by "missing milestone" test)
- Structured error payloads: error messages name specific task/slice IDs, not generic messages (covered by structured error payload tests)

View file

@ -12,6 +12,10 @@ key_decisions:
- deleteTask() deletes verification_evidence before task row to avoid FK constraint violations — cascade-style manual deletion pattern
- Structural enforcement checks both 'complete' and 'done' statuses as completed-task indicators
- Error payloads include the specific task ID that blocked the mutation for actionable diagnostics
observability_surfaces:
- "replan_history DB table — query with getReplanHistory(db, milestoneId, sliceId) to inspect replan events"
- "REPLAN.md artifact on disk — rendered at slices/S##/REPLAN.md with blocker description and what changed"
- "Handler error payloads — { error: string } naming the specific completed task ID that blocked the mutation"
duration: ""
verification_result: passed
completed_at: 2026-03-23T16:28:29.943Z
@ -57,6 +61,13 @@ Added `getReplanHistory()` query helper to `gsd-db.ts` (not in plan) — needed
None.
## Diagnostics
- **Inspect replan history:** `getReplanHistory(db, milestoneId, sliceId)` returns all replan events for a slice including blocker description, what changed, and timestamps.
- **Verify structural enforcement:** Run `replan-handler.test.ts` — tests "rejects structural violation: updating a completed task" and "removing a completed task" prove the enforcement gate.
- **Check rendered artifacts:** After a successful replan, `REPLAN.md` exists at `slices/S##/REPLAN.md` and PLAN.md is re-rendered with updated tasks.
- **Error payloads:** Handler returns `{ error: "Cannot update/remove completed task T##..." }` with the specific task ID.
## Files Created/Modified
- `src/resources/extensions/gsd/gsd-db.ts`

View file

@ -9,6 +9,10 @@ key_files:
key_decisions:
- Added updateSliceFields() to gsd-db.ts for title/risk/depends/demo updates because upsertSlicePlanning() only handles planning-level fields (goal, success_criteria, etc.) — keeps DB API consistent rather than using raw SQL in the handler
- Added getAssessment() query helper to gsd-db.ts for test verification of assessments DB persistence — follows the same pattern as getReplanHistory() added in T01
observability_surfaces:
- "assessments DB table — query with getAssessment(db, path) to inspect assessment events"
- "ASSESSMENT.md artifact on disk — rendered at slices/S##/ASSESSMENT.md with verdict and assessment text"
- "Handler error payloads — { error: string } naming the specific completed slice ID that blocked the mutation"
duration: ""
verification_result: passed
completed_at: 2026-03-23T16:32:59.273Z
@ -52,6 +56,13 @@ Added `updateSliceFields()` to `gsd-db.ts` (not in task plan's expected output)
None.
## Diagnostics
- **Inspect assessments:** `getAssessment(db, path)` returns the assessment row for a given artifact path.
- **Verify structural enforcement:** Run `reassess-handler.test.ts` — tests "rejects structural violation: modifying a completed slice" and "removing a completed slice" prove the enforcement gate.
- **Check rendered artifacts:** After a successful reassess, `ASSESSMENT.md` exists at `slices/S##/ASSESSMENT.md` and ROADMAP.md is re-rendered.
- **Error payloads:** Handler returns `{ error: "Cannot modify/remove completed slice S##..." }` with the specific slice ID.
## Files Created/Modified
- `src/resources/extensions/gsd/tools/reassess-roadmap.ts`

View file

@ -9,6 +9,10 @@ key_files:
- 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
observability_surfaces:
- "db-tools.ts tool registrations — grep for gsd_replan_slice and gsd_reassess_roadmap to verify wiring"
- "Prompt contract tests — prompt-contracts.test.ts asserts tool names appear in prompts as regression guard"
- "Prompt files — replan-slice.md and reassess-roadmap.md contain canonical write path instructions"
duration: ""
verification_result: passed
completed_at: 2026-03-23T16:36:49.549Z
@ -66,6 +70,12 @@ None.
None.
## Diagnostics
- **Verify tool registration:** `grep -q 'gsd_replan_slice' src/resources/extensions/gsd/bootstrap/db-tools.ts && grep -q 'gsd_reassess_roadmap' src/resources/extensions/gsd/bootstrap/db-tools.ts` — both must succeed.
- **Verify prompt wiring:** `grep -q 'gsd_replan_slice' src/resources/extensions/gsd/prompts/replan-slice.md && grep -q 'gsd_reassess_roadmap' src/resources/extensions/gsd/prompts/reassess-roadmap.md` — both must succeed.
- **Prompt contract regression guard:** Run `prompt-contracts.test.ts` — 28 tests including the 2 new tool-name assertions catch regressions if someone removes the canonical tool references from prompts.
## Files Created/Modified
- `src/resources/extensions/gsd/bootstrap/db-tools.ts`

View file

@ -0,0 +1,18 @@
{
"schemaVersion": 1,
"taskId": "T03",
"unitId": "M001/S03/T03",
"timestamp": 1774283829836,
"passed": false,
"discoverySource": "package-json",
"checks": [
{
"command": "npm run test",
"exitCode": 1,
"durationMs": 41263,
"verdict": "fail"
}
],
"retryAttempt": 1,
"maxRetries": 2
}