chore(M001/S05): auto-commit after plan-slice
This commit is contained in:
parent
4f829131f6
commit
b8aaded95e
5 changed files with 506 additions and 0 deletions
93
.gsd/milestones/M001/slices/S05/S05-PLAN.md
Normal file
93
.gsd/milestones/M001/slices/S05/S05-PLAN.md
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
# S05: Warm/cold callers + flag files + pre-M002 migration
|
||||
|
||||
**Goal:** All non-hot-path parseRoadmap/parsePlan callers migrated to DB queries with lazy parser fallback. REPLAN.md and REPLAN-TRIGGER.md flag-file detection in deriveStateFromDb() replaced with DB table/column queries. migrateHierarchyToDb() populates v8 planning columns from parsed markdown.
|
||||
**Demo:** `grep -rn 'import.*parseRoadmap\|import.*parsePlan' src/resources/extensions/gsd/*.ts | grep -v '/tests/' | grep -v 'md-importer' | grep -v 'files.ts'` returns only lazy `createRequire` references and markdown-renderer.ts lazy imports. Flag-file phase detection works without disk files when DB is seeded.
|
||||
|
||||
## Must-Haves
|
||||
|
||||
- Schema v10 adds `replan_triggered_at TEXT` column to slices table (both CREATE TABLE DDL and migration block)
|
||||
- `deriveStateFromDb()` uses `getReplanHistory()` for REPLAN detection and `replan_triggered_at` column for REPLAN-TRIGGER detection instead of `resolveSliceFile()` disk checks
|
||||
- `triage-resolution.ts` `executeReplan()` writes `replan_triggered_at` column in addition to disk file
|
||||
- `migrateHierarchyToDb()` passes `planning: { vision, successCriteria, boundaryMapMarkdown }` to `insertMilestone()`, `planning: { goal }` to `insertSlice()`, and `files`/`verify` to `insertTask()`
|
||||
- All 13 warm/cold caller files have module-level `parseRoadmap`/`parsePlan` imports replaced with `isDbAvailable()` gate + lazy `createRequire` fallback (or dynamic import for async callers)
|
||||
- `markdown-renderer.ts` validation moves parser import from module-level to lazy `createRequire` (keeps parser calls — they're intentional disk-vs-DB comparison)
|
||||
- CONTINUE.md and CONTEXT-DRAFT.md migration NOT touched per D003 (locked, non-revisable)
|
||||
- All existing tests pass (no regressions)
|
||||
|
||||
## Proof Level
|
||||
|
||||
- This slice proves: integration (DB queries replace parser calls across 13+ files)
|
||||
- Real runtime required: no (unit tests with seeded DBs prove behavior)
|
||||
- Human/UAT required: no
|
||||
|
||||
## Verification
|
||||
|
||||
- `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/flag-file-db.test.ts` — flag-file DB migration tests pass
|
||||
- `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/gsd-recover.test.ts` — extended recovery tests pass (v8 column population)
|
||||
- `grep -rn 'import.*parseRoadmap\|import.*parsePlan\|import.*parseRoadmapSlices' src/resources/extensions/gsd/*.ts | grep -v '/tests/' | grep -v 'md-importer' | grep -v 'files.ts'` — returns zero module-level imports (only lazy createRequire references)
|
||||
- Regression suites: doctor.test.ts, auto-recovery.test.ts, auto-dashboard.test.ts, derive-state-db.test.ts, derive-state-crossval.test.ts, planning-crossval.test.ts, markdown-renderer.test.ts all pass
|
||||
|
||||
## Observability / Diagnostics
|
||||
|
||||
- Runtime signals: `replan_triggered_at` column on slices table records when triage writes a replan trigger; `replan_history` table rows indicate completed replans — both queryable via SQL
|
||||
- Inspection surfaces: `SELECT id, replan_triggered_at FROM slices WHERE milestone_id = :mid` shows trigger state; `SELECT * FROM replan_history WHERE milestone_id = :mid AND slice_id = :sid` shows replan completion
|
||||
- Failure visibility: `isDbAvailable()` gate in all migrated callers writes to stderr when falling back to parser — detectable in logs
|
||||
- Redaction constraints: none
|
||||
|
||||
## Integration Closure
|
||||
|
||||
- Upstream surfaces consumed: `getReplanHistory()` from S03, `getMilestoneSlices()`/`getSliceTasks()`/`getTask()` from S01/S02, `isDbAvailable()` + lazy `createRequire` pattern from S04
|
||||
- New wiring introduced: `replan_triggered_at` column writer in `triage-resolution.ts`, v8 column population in `migrateHierarchyToDb()`
|
||||
- What remains before the milestone is truly usable end-to-end: S06 (parser deprecation + cleanup — removes dead parser code from hot paths)
|
||||
|
||||
## Tasks
|
||||
|
||||
- [ ] **T01: Schema v10 + flag-file DB migration in deriveStateFromDb** `est:45m`
|
||||
- Why: The architecturally novel piece — REPLAN.md and REPLAN-TRIGGER.md detection in `deriveStateFromDb()` must use DB queries instead of disk-file checks. Schema v10 adds the `replan_triggered_at` column. Triage-resolution must also write the column.
|
||||
- Files: `src/resources/extensions/gsd/gsd-db.ts`, `src/resources/extensions/gsd/state.ts`, `src/resources/extensions/gsd/triage-resolution.ts`, `src/resources/extensions/gsd/tests/flag-file-db.test.ts`
|
||||
- Do: (1) Bump SCHEMA_VERSION to 10, add `replan_triggered_at TEXT DEFAULT NULL` to slices CREATE TABLE DDL and v10 migration block. (2) Update `SliceRow` interface and `rowToSlice()`. (3) In `deriveStateFromDb()`, replace `resolveSliceFile(... "REPLAN")` with `getReplanHistory(mid, sid).length > 0` check, replace `resolveSliceFile(... "REPLAN-TRIGGER")` with checking `getSlice(mid, sid)?.replan_triggered_at`. (4) In `triage-resolution.ts` `executeReplan()`, after writing the disk file, also write the `replan_triggered_at` column via `UPDATE slices SET replan_triggered_at = :ts`. (5) Write `flag-file-db.test.ts` testing: blocker→replan detection via DB (no disk file), REPLAN-TRIGGER via DB column (no disk file), loop protection (replan_history exists = no replanning phase).
|
||||
- Verify: `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/flag-file-db.test.ts`
|
||||
- Done when: deriveStateFromDb returns phase='replanning-slice' from DB-only data (no REPLAN.md or REPLAN-TRIGGER.md on disk) and returns phase='executing' when replan_history exists (loop protection). SCHEMA_VERSION=10.
|
||||
|
||||
- [ ] **T02: Extend migrateHierarchyToDb with v8 column population** `est:30m`
|
||||
- Why: Existing projects migrating to the DB need their parsed ROADMAP/PLAN data written into the v8 planning columns so DB queries return meaningful data. The `gsd recover` test must verify this.
|
||||
- Files: `src/resources/extensions/gsd/md-importer.ts`, `src/resources/extensions/gsd/tests/gsd-recover.test.ts`
|
||||
- Do: (1) In `migrateHierarchyToDb()`, extend the `insertMilestone()` call to pass `planning: { vision: roadmap.vision, successCriteria: roadmap.successCriteria, boundaryMapMarkdown: boundaryMapSection }` where `boundaryMapMarkdown` is the raw "## Boundary Map" section extracted from the roadmap content. (2) Extend `insertSlice()` calls to pass `planning: { goal: plan.goal }` from the parsed plan (when plan exists). (3) Extend `insertTask()` calls to pass `planning: { files: task.files, verify: task.verify }` from TaskPlanEntry. (4) Extend `gsd-recover.test.ts` to assert: after recover, milestone has non-empty `vision`; slice has non-empty `goal`; task has populated `files` array and `verify` string.
|
||||
- Verify: `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/gsd-recover.test.ts`
|
||||
- Done when: migrateHierarchyToDb populates vision, successCriteria, boundaryMapMarkdown on milestones; goal on slices; files and verify on tasks. Recovery test proves it.
|
||||
|
||||
- [ ] **T03: Migrate warm/cold callers batch 1 — doctor, visualizer, workspace, dashboard, guided-flow** `est:40m`
|
||||
- Why: Seven files with straightforward parseRoadmap/parsePlan usage need the S04 isDbAvailable + lazy createRequire pattern applied.
|
||||
- Files: `src/resources/extensions/gsd/doctor.ts`, `src/resources/extensions/gsd/doctor-checks.ts`, `src/resources/extensions/gsd/visualizer-data.ts`, `src/resources/extensions/gsd/workspace-index.ts`, `src/resources/extensions/gsd/dashboard-overlay.ts`, `src/resources/extensions/gsd/auto-dashboard.ts`, `src/resources/extensions/gsd/guided-flow.ts`
|
||||
- Do: For each file: (1) Remove module-level `parseRoadmap`/`parsePlan` from the import statement. (2) At each call site, add `isDbAvailable()` gate calling `getMilestoneSlices()`/`getSliceTasks()` for the DB path. (3) Add lazy `createRequire`-based fallback loading the parser for non-DB path. (4) For `parsePlan().filesLikelyTouched` aggregation in callers: collect `.files` arrays from `getSliceTasks()` results. (5) Keep other non-parser imports (loadFile, parseSummary, etc.) as module-level. Note: these files are async or synchronous — check each. For async callers, dynamic `import()` is also acceptable. Follow the exact pattern from `dispatch-guard.ts` (S04).
|
||||
- Verify: `grep -n 'import.*parseRoadmap\|import.*parsePlan' src/resources/extensions/gsd/doctor.ts src/resources/extensions/gsd/doctor-checks.ts src/resources/extensions/gsd/visualizer-data.ts src/resources/extensions/gsd/workspace-index.ts src/resources/extensions/gsd/dashboard-overlay.ts src/resources/extensions/gsd/auto-dashboard.ts src/resources/extensions/gsd/guided-flow.ts` returns zero results. Existing test suites pass.
|
||||
- Done when: Zero module-level parseRoadmap/parsePlan imports in these 7 files. All existing tests for these files pass.
|
||||
|
||||
- [ ] **T04: Migrate warm/cold callers batch 2 — auto-prompts, auto-recovery, auto-direct-dispatch, auto-worktree, reactive-graph, markdown-renderer + final verification** `est:50m`
|
||||
- Why: The remaining 6 files include auto-prompts.ts (6 parser calls, 1649 lines, highest complexity) and markdown-renderer.ts (intentional parser usage → lazy import only). Final grep verification confirms zero module-level parser imports remain.
|
||||
- Files: `src/resources/extensions/gsd/auto-prompts.ts`, `src/resources/extensions/gsd/auto-recovery.ts`, `src/resources/extensions/gsd/auto-direct-dispatch.ts`, `src/resources/extensions/gsd/auto-worktree.ts`, `src/resources/extensions/gsd/reactive-graph.ts`, `src/resources/extensions/gsd/markdown-renderer.ts`
|
||||
- Do: (1) **auto-prompts.ts** — all functions are async, so use dynamic `import("./gsd-db.js")` pattern (already used in this file for decisions/requirements). For `inlineDependencySummaries`: replace `parseRoadmap(roadmapContent).slices.find(s => s.id === sid)?.depends` with `getSlice(mid, sid)?.depends`. For `checkNeedsReassessment`/`checkNeedsRunUat`: replace `parseRoadmap().slices` with `getMilestoneSlices(mid)`, map `s.done` to `s.status === 'complete'`. For `buildCompleteMilestonePrompt`/`buildValidateMilestonePrompt`: replace slice iteration with `getMilestoneSlices()`. For `buildResumeContextListing` parsePlan: replace with `getSliceTasks()` to find incomplete tasks. Keep `parseSummary`, `parseContinue`, `loadFile`, `parseTaskPlanFile` imports — those aren't in scope. (2) **auto-recovery.ts** — the `parsePlan` at line 370 replaces with `getSliceTasks()` to check task plan files exist. The `parseRoadmap` at line 407 is already inside an `!isDbAvailable()` block — leave it, just move to lazy import. (3) **auto-direct-dispatch.ts** — replace 2 `parseRoadmap` calls with `getMilestoneSlices()` behind `isDbAvailable()` gate. (4) **auto-worktree.ts** — replace 1 `parseRoadmap` call with `getMilestoneSlices()`. (5) **reactive-graph.ts** — replace 1 `parsePlan` call with `getSliceTasks()`. Also uses `parseTaskPlanIO` — keep that as-is (not a planning parser). (6) **markdown-renderer.ts** — move `parseRoadmap`/`parsePlan` from module-level import to lazy `createRequire` (the parser calls are intentional disk-vs-DB comparison in `findStaleArtifacts()`). (7) Run final grep to confirm zero module-level parser imports remain across all non-test, non-md-importer, non-files.ts source files.
|
||||
- Verify: `grep -rn 'import.*parseRoadmap\|import.*parsePlan\|import.*parseRoadmapSlices' src/resources/extensions/gsd/*.ts | grep -v '/tests/' | grep -v 'md-importer' | grep -v 'files.ts'` returns zero results. `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/auto-recovery.test.ts` passes.
|
||||
- Done when: Zero module-level parseRoadmap/parsePlan/parseRoadmapSlices imports in any non-test, non-md-importer, non-files.ts source file. All existing test suites pass.
|
||||
|
||||
## Files Likely Touched
|
||||
|
||||
- `src/resources/extensions/gsd/gsd-db.ts`
|
||||
- `src/resources/extensions/gsd/state.ts`
|
||||
- `src/resources/extensions/gsd/triage-resolution.ts`
|
||||
- `src/resources/extensions/gsd/md-importer.ts`
|
||||
- `src/resources/extensions/gsd/doctor.ts`
|
||||
- `src/resources/extensions/gsd/doctor-checks.ts`
|
||||
- `src/resources/extensions/gsd/visualizer-data.ts`
|
||||
- `src/resources/extensions/gsd/workspace-index.ts`
|
||||
- `src/resources/extensions/gsd/dashboard-overlay.ts`
|
||||
- `src/resources/extensions/gsd/auto-dashboard.ts`
|
||||
- `src/resources/extensions/gsd/guided-flow.ts`
|
||||
- `src/resources/extensions/gsd/reactive-graph.ts`
|
||||
- `src/resources/extensions/gsd/auto-direct-dispatch.ts`
|
||||
- `src/resources/extensions/gsd/auto-worktree.ts`
|
||||
- `src/resources/extensions/gsd/auto-recovery.ts`
|
||||
- `src/resources/extensions/gsd/auto-prompts.ts`
|
||||
- `src/resources/extensions/gsd/markdown-renderer.ts`
|
||||
- `src/resources/extensions/gsd/tests/flag-file-db.test.ts`
|
||||
- `src/resources/extensions/gsd/tests/gsd-recover.test.ts`
|
||||
98
.gsd/milestones/M001/slices/S05/tasks/T01-PLAN.md
Normal file
98
.gsd/milestones/M001/slices/S05/tasks/T01-PLAN.md
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
---
|
||||
estimated_steps: 5
|
||||
estimated_files: 4
|
||||
skills_used: []
|
||||
---
|
||||
|
||||
# T01: Schema v10 + flag-file DB migration in deriveStateFromDb
|
||||
|
||||
**Slice:** S05 — Warm/cold callers + flag files + pre-M002 migration
|
||||
**Milestone:** M001
|
||||
|
||||
## Description
|
||||
|
||||
Add `replan_triggered_at TEXT DEFAULT NULL` column to the slices table (schema v10), then replace the disk-based REPLAN.md and REPLAN-TRIGGER.md detection in `deriveStateFromDb()` with DB queries. Update `triage-resolution.ts` to write the new column when creating a replan trigger. Write a test file proving flag-file phase detection works from DB-only data.
|
||||
|
||||
**Critical semantic note:** In `deriveStateFromDb()`, REPLAN.md detection is **loop protection** — if a replan has already been done (REPLAN.md exists / replan_history has entries), the system should NOT re-enter replanning phase. REPLAN-TRIGGER.md detection triggers replanning when triage creates it. These are distinct checks with different semantics:
|
||||
- `resolveSliceFile(... "REPLAN")` → checks if replan was already completed → DB equivalent: `getReplanHistory(mid, sid).length > 0`
|
||||
- `resolveSliceFile(... "REPLAN-TRIGGER")` → checks if triage triggered a replan → DB equivalent: `getSlice(mid, sid)?.replan_triggered_at` is non-null
|
||||
|
||||
**D003 constraint:** Do NOT touch CONTINUE.md detection. It stays as disk-based per locked decision D003.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Schema v10 migration + DDL update in `gsd-db.ts`:**
|
||||
- Bump `SCHEMA_VERSION` from 9 to 10
|
||||
- Add `replan_triggered_at TEXT DEFAULT NULL` to the CREATE TABLE DDL for `slices` (after the `sequence` column)
|
||||
- Add a `if (currentVersion < 10)` migration block using `ensureColumn()` to add the column to existing DBs
|
||||
- Update `SliceRow` interface to include `replan_triggered_at: string | null`
|
||||
- Update `rowToSlice()` to read the column: `replan_triggered_at: (row["replan_triggered_at"] as string) ?? null`
|
||||
|
||||
2. **Update `deriveStateFromDb()` in `state.ts`:**
|
||||
- The blocker detection block (around line 640) checks `resolveSliceFile(basePath, activeMilestone.id, activeSlice.id, "REPLAN")` for loop protection. Replace with: import and call `getReplanHistory` from `gsd-db.js`, check if `getReplanHistory(activeMilestone.id, activeSlice.id).length > 0`. If replan history exists, it means replan was already done — don't return `replanning-slice`.
|
||||
- The REPLAN-TRIGGER detection block (around line 659) checks `resolveSliceFile(basePath, activeMilestone.id, activeSlice.id, "REPLAN-TRIGGER")`. Replace with: import `getSlice` from `gsd-db.js`, check if `getSlice(activeMilestone.id, activeSlice.id)?.replan_triggered_at` is non-null. If set, check loop protection (replan_history) before returning `replanning-slice`.
|
||||
- Do NOT touch the `_deriveStateImpl()` fallback path (line ~1266+) — that's the disk-based fallback and stays as-is.
|
||||
- Do NOT touch CONTINUE.md detection (line ~679) — per D003.
|
||||
|
||||
3. **Update `triage-resolution.ts` `executeReplan()`:**
|
||||
- After writing the disk file (keep the disk write for `_deriveStateImpl()` fallback), also write the DB column:
|
||||
```typescript
|
||||
try {
|
||||
const { isDbAvailable, _getAdapter } = await import("./gsd-db.js");
|
||||
// ... or use a synchronous approach since executeReplan is sync
|
||||
}
|
||||
```
|
||||
- Since `executeReplan` is synchronous and `gsd-db.ts` exports are module-level, use a direct import if possible, or use `createRequire` for lazy loading. Check if `gsd-db.ts` is already imported in the file. If not, use the lazy pattern. Write: `UPDATE slices SET replan_triggered_at = :ts WHERE milestone_id = :mid AND id = :sid`
|
||||
- Note: `_getAdapter()` returns the raw adapter. Or use `isDbAvailable()` check + direct SQL. Follow the pattern used by other callers.
|
||||
|
||||
4. **Write `flag-file-db.test.ts`:**
|
||||
Test cases:
|
||||
- "blocker_discovered + no replan_history → phase is replanning-slice" — seed DB with a completed task that has `blocker_discovered=1`, no replan_history entries. Confirm `deriveStateFromDb()` returns `phase: 'replanning-slice'`.
|
||||
- "blocker_discovered + replan_history exists → loop protection, phase is executing" — seed DB with blocker task AND a replan_history entry for that slice. Confirm `deriveStateFromDb()` returns `phase: 'executing'` (loop protection).
|
||||
- "replan_triggered_at set + no replan_history → phase is replanning-slice" — seed DB with `replan_triggered_at` on the active slice, no replan_history. Confirm replanning phase.
|
||||
- "replan_triggered_at set + replan_history exists → loop protection" — seed with both. Confirm executing phase.
|
||||
- "no blocker, no trigger → phase is executing" — baseline test confirming normal execution.
|
||||
- Use the test harness pattern from `derive-state-db.test.ts` — create temp dirs, seed DB, call `deriveStateFromDb()`.
|
||||
|
||||
5. **Run verification:**
|
||||
- Run `flag-file-db.test.ts`
|
||||
- Run `derive-state-db.test.ts` and `derive-state-crossval.test.ts` for regressions
|
||||
- Run `schema-v9-sequence.test.ts` (now schema v10 — confirm v9 migration still works)
|
||||
|
||||
## Must-Haves
|
||||
|
||||
- [ ] SCHEMA_VERSION bumped to 10
|
||||
- [ ] `replan_triggered_at` column in both CREATE TABLE DDL and v10 migration block
|
||||
- [ ] `SliceRow` interface and `rowToSlice()` updated
|
||||
- [ ] `deriveStateFromDb()` uses `getReplanHistory()` for REPLAN loop protection
|
||||
- [ ] `deriveStateFromDb()` uses `getSlice().replan_triggered_at` for REPLAN-TRIGGER detection
|
||||
- [ ] `triage-resolution.ts` `executeReplan()` writes `replan_triggered_at` column
|
||||
- [ ] CONTINUE.md detection untouched per D003
|
||||
- [ ] `_deriveStateImpl()` fallback path untouched
|
||||
- [ ] `flag-file-db.test.ts` with 5 test cases passing
|
||||
|
||||
## Verification
|
||||
|
||||
- `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/flag-file-db.test.ts` — all 5 tests pass
|
||||
- `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/derive-state-db.test.ts` — no regressions
|
||||
- `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/derive-state-crossval.test.ts` — no regressions
|
||||
|
||||
## Observability Impact
|
||||
|
||||
- Signals added: `replan_triggered_at` column on slices — queryable indicator of triage-initiated replan triggers
|
||||
- How a future agent inspects this: `SELECT id, replan_triggered_at FROM slices WHERE milestone_id = :mid`
|
||||
- Failure state exposed: If `deriveStateFromDb()` returns wrong phase, inspect `replan_history` table and `replan_triggered_at` column to diagnose
|
||||
|
||||
## Inputs
|
||||
|
||||
- `src/resources/extensions/gsd/gsd-db.ts` — schema, SliceRow interface, getReplanHistory(), getSlice(), _getAdapter()
|
||||
- `src/resources/extensions/gsd/state.ts` — deriveStateFromDb() with existing REPLAN/REPLAN-TRIGGER disk checks
|
||||
- `src/resources/extensions/gsd/triage-resolution.ts` — executeReplan() that writes REPLAN-TRIGGER.md
|
||||
- `src/resources/extensions/gsd/tests/derive-state-db.test.ts` — test pattern reference for DB-seeded state tests
|
||||
|
||||
## Expected Output
|
||||
|
||||
- `src/resources/extensions/gsd/gsd-db.ts` — schema v10, updated SliceRow, rowToSlice
|
||||
- `src/resources/extensions/gsd/state.ts` — deriveStateFromDb() using DB queries for flag-file detection
|
||||
- `src/resources/extensions/gsd/triage-resolution.ts` — executeReplan() also writing replan_triggered_at column
|
||||
- `src/resources/extensions/gsd/tests/flag-file-db.test.ts` — new test file with 5 flag-file DB migration tests
|
||||
67
.gsd/milestones/M001/slices/S05/tasks/T02-PLAN.md
Normal file
67
.gsd/milestones/M001/slices/S05/tasks/T02-PLAN.md
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
---
|
||||
estimated_steps: 4
|
||||
estimated_files: 2
|
||||
skills_used: []
|
||||
---
|
||||
|
||||
# T02: Extend migrateHierarchyToDb with v8 column population
|
||||
|
||||
**Slice:** S05 — Warm/cold callers + flag files + pre-M002 migration
|
||||
**Milestone:** M001
|
||||
|
||||
## Description
|
||||
|
||||
Extend `migrateHierarchyToDb()` in `md-importer.ts` to populate v8 planning columns from parsed ROADMAP and PLAN files. This ensures pre-M002 projects get meaningful data in the DB planning columns when migrating. Per D004, tool-only fields (risks, requirementCoverage, proofLevel) are not populated — only fields the parsers can extract. Extend `gsd-recover.test.ts` to verify the v8 columns are populated after recovery.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Extend milestone insertion in `migrateHierarchyToDb()`:**
|
||||
- The `parseRoadmap(roadmapContent)` call already returns `{ title, vision, successCriteria, slices, boundaryMap }`.
|
||||
- The `insertMilestone()` call (around line 558) currently passes only `id`, `title`, `status`, `depends_on`.
|
||||
- Add `planning: { vision: roadmap.vision, successCriteria: roadmap.successCriteria, boundaryMapMarkdown: boundaryMapSection }`.
|
||||
- For `boundaryMapMarkdown`: extract the raw `## Boundary Map` section from `roadmapContent` using string operations (find `## Boundary Map` heading, take content until next `##` or EOF). The `extractSection()` function from `files.ts` can do this but is not exported — use a simple inline extraction: `const bmIdx = roadmapContent.indexOf('## Boundary Map'); const bmSection = bmIdx >= 0 ? roadmapContent.slice(bmIdx) ... : ''`.
|
||||
- Note: `successCriteria` from `parseRoadmap()` is already a `string[]` — `insertMilestone()` expects it as `string[]` in the planning object and `JSON.stringify`s it internally. Verify this matches the `MilestonePlanningRecord.successCriteria` type.
|
||||
|
||||
2. **Extend slice insertion:**
|
||||
- The `insertSlice()` call (around line 574) currently passes `id`, `milestoneId`, `title`, `status`, `risk`, `depends`, `demo`.
|
||||
- Parse the plan content (which already happens at line ~592: `parsePlan(planContent)`) and add `planning: { goal: plan.goal }` to the `insertSlice()` call.
|
||||
- The plan parsing happens AFTER slice insertion currently. Restructure: read and parse the plan file BEFORE `insertSlice()`, so the goal is available. Or call `upsertSlicePlanning()` after parsing. The simpler approach: move the plan parse earlier, pass goal into insertSlice. If no plan exists, goal stays empty (the default).
|
||||
|
||||
3. **Extend task insertion:**
|
||||
- The `insertTask()` call (around line 612) currently passes `id`, `sliceId`, `milestoneId`, `title`, `status`.
|
||||
- Add `planning: { files: taskEntry.files ?? [], verify: taskEntry.verify ?? '' }`.
|
||||
- `TaskPlanEntry` from `parsePlan()` has optional `files?: string[]` and `verify?: string` fields. These are populated when the plan markdown has `- Files:` and `- Verify:` lines in task entries.
|
||||
|
||||
4. **Extend `gsd-recover.test.ts`:**
|
||||
- The existing test writes a ROADMAP.md and PLAN.md, runs `migrateHierarchyToDb()`, then checks counts and status.
|
||||
- Add assertions after recovery:
|
||||
- `getMilestonePlanning(mid)` returns non-empty `vision` matching what was in the fixture ROADMAP
|
||||
- Slice row has non-empty `goal` matching what was in the fixture PLAN
|
||||
- Task row has populated `files` array and non-empty `verify` string matching fixture data
|
||||
- The fixture ROADMAP.md must include a `**Vision:**` field and `## Success Criteria` section for this to work. Check the existing fixture — if it doesn't have these, add them.
|
||||
- The fixture PLAN.md must include `- Files:` and `- Verify:` in task entries. Check and extend if needed.
|
||||
|
||||
## Must-Haves
|
||||
|
||||
- [ ] `insertMilestone()` call in migrateHierarchyToDb passes `planning: { vision, successCriteria, boundaryMapMarkdown }`
|
||||
- [ ] `insertSlice()` call passes `planning: { goal }` from parsed plan
|
||||
- [ ] `insertTask()` call passes `planning: { files, verify }` from TaskPlanEntry
|
||||
- [ ] `gsd-recover.test.ts` asserts v8 columns are populated after recovery
|
||||
- [ ] Tool-only fields (risks, requirementCoverage, proofLevel) left empty per D004
|
||||
|
||||
## Verification
|
||||
|
||||
- `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/gsd-recover.test.ts` — all tests pass including new v8 column assertions
|
||||
- No regressions in other tests that use migrateHierarchyToDb (check `integration-mixed-milestones.test.ts`)
|
||||
|
||||
## Inputs
|
||||
|
||||
- `src/resources/extensions/gsd/md-importer.ts` — migrateHierarchyToDb() with existing insertMilestone/insertSlice/insertTask calls
|
||||
- `src/resources/extensions/gsd/gsd-db.ts` — insertMilestone(planning), insertSlice(planning), insertTask(planning) signatures, getMilestonePlanning(), SliceRow, TaskRow interfaces
|
||||
- `src/resources/extensions/gsd/tests/gsd-recover.test.ts` — existing recovery test to extend
|
||||
- `src/resources/extensions/gsd/files.ts` — parseRoadmap() return type (vision, successCriteria, boundaryMap), parsePlan() return type (goal, tasks with files/verify)
|
||||
|
||||
## Expected Output
|
||||
|
||||
- `src/resources/extensions/gsd/md-importer.ts` — migrateHierarchyToDb() populates v8 planning columns
|
||||
- `src/resources/extensions/gsd/tests/gsd-recover.test.ts` — extended with v8 column population assertions
|
||||
123
.gsd/milestones/M001/slices/S05/tasks/T03-PLAN.md
Normal file
123
.gsd/milestones/M001/slices/S05/tasks/T03-PLAN.md
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
---
|
||||
estimated_steps: 4
|
||||
estimated_files: 7
|
||||
skills_used: []
|
||||
---
|
||||
|
||||
# T03: Migrate warm/cold callers batch 1 — doctor, visualizer, workspace, dashboard, guided-flow
|
||||
|
||||
**Slice:** S05 — Warm/cold callers + flag files + pre-M002 migration
|
||||
**Milestone:** M001
|
||||
|
||||
## Description
|
||||
|
||||
Apply the established S04 migration pattern (`isDbAvailable()` gate + lazy `createRequire` fallback) to 7 warm/cold caller files: `doctor.ts`, `doctor-checks.ts`, `visualizer-data.ts`, `workspace-index.ts`, `dashboard-overlay.ts`, `auto-dashboard.ts`, `guided-flow.ts`. These files have straightforward parseRoadmap/parsePlan usage that can be mechanically replaced with DB queries.
|
||||
|
||||
**Pattern reference (from S04 dispatch-guard.ts):**
|
||||
```typescript
|
||||
// Remove from module-level import:
|
||||
// import { parseRoadmap } from "./files.js";
|
||||
|
||||
// Add to module-level import:
|
||||
import { isDbAvailable, getMilestoneSlices } from "./gsd-db.js";
|
||||
|
||||
// At each call site, replace:
|
||||
// const roadmap = parseRoadmap(content);
|
||||
// for (const slice of roadmap.slices) { ... }
|
||||
// With:
|
||||
if (isDbAvailable()) {
|
||||
const slices = getMilestoneSlices(mid);
|
||||
// use slices directly — SliceRow has .id, .title, .status, .risk, .depends, .demo
|
||||
// .done equivalent: slice.status === 'complete'
|
||||
} else {
|
||||
// Lazy fallback
|
||||
const { createRequire } = await import("node:module");
|
||||
const _require = createRequire(import.meta.url);
|
||||
let parseRoadmap: (c: string) => { slices: Array<{ id: string; done: boolean; title: string; risk: string; depends: string[]; demo: string }> };
|
||||
try {
|
||||
parseRoadmap = _require("./files.ts").parseRoadmap;
|
||||
} catch {
|
||||
parseRoadmap = _require("./files.js").parseRoadmap;
|
||||
}
|
||||
const roadmap = parseRoadmap(content);
|
||||
// ... use roadmap.slices
|
||||
}
|
||||
```
|
||||
|
||||
**Key mapping from parsed types to DB types:**
|
||||
- `roadmap.slices[].done` → `slice.status === 'complete'`
|
||||
- `roadmap.slices[].id/title/risk/depends/demo` → same field names on `SliceRow`
|
||||
- `plan.tasks[].done` → `task.status === 'complete' || task.status === 'done'`
|
||||
- `plan.tasks[].id/title` → same on `TaskRow`
|
||||
- `plan.tasks[].files` → `task.files` (already parsed as `string[]` by `rowToTask()`)
|
||||
- `plan.tasks[].verify` → `task.verify`
|
||||
- `plan.filesLikelyTouched` → aggregate: `sliceTasks.flatMap(t => t.files)`
|
||||
|
||||
**Important:** Some of these files have async functions (doctor.ts, visualizer-data.ts, workspace-index.ts, dashboard-overlay.ts, auto-dashboard.ts). For async callers, `await import("./gsd-db.js")` is cleaner than `createRequire`. For synchronous callers, use `createRequire`. Check each file.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **doctor.ts** (3 parseRoadmap + 1 parsePlan):
|
||||
- Remove `parseRoadmap`, `parsePlan` from the module-level import from `./files.js`. Keep `loadFile`, `parseSummary`, `saveFile`, `parseTaskPlanMustHaves`, `countMustHavesMentionedInSummary`.
|
||||
- Add `import { isDbAvailable, getMilestoneSlices, getSliceTasks } from "./gsd-db.js";`
|
||||
- At line ~216: replace `parseRoadmap(roadmapContent).slices` with `isDbAvailable() ? getMilestoneSlices(mid) : lazyParseRoadmap(roadmapContent).slices`. Map `.done` to `.status === 'complete'`.
|
||||
- At line ~463: same pattern.
|
||||
- At line ~582: replace `parsePlan(planContent)` with `isDbAvailable() ? { tasks: getSliceTasks(mid, sid) } : lazyParsePlan(planContent)`. Map task fields accordingly.
|
||||
- Create a local lazy-parser helper function at the top of the file to avoid repeating the createRequire boilerplate.
|
||||
|
||||
2. **doctor-checks.ts** (2 parseRoadmap):
|
||||
- Remove `parseRoadmap` from import. Keep `loadFile`.
|
||||
- Add DB imports. Replace 2 call sites with `getMilestoneSlices()` + fallback.
|
||||
|
||||
3. **visualizer-data.ts** (1 parseRoadmap + 1 parsePlan):
|
||||
- Remove parser imports. Add DB imports. Replace call sites.
|
||||
|
||||
4. **workspace-index.ts** (2 parseRoadmap + 1 parsePlan):
|
||||
- Remove parser imports. Add DB imports. Replace 3 call sites.
|
||||
|
||||
5. **dashboard-overlay.ts** (1 parseRoadmap + 1 parsePlan):
|
||||
- Remove parser imports. Add DB imports. Replace call sites.
|
||||
|
||||
6. **auto-dashboard.ts** (1 parseRoadmap + 1 parsePlan):
|
||||
- Remove parser imports. Add DB imports. Replace call sites.
|
||||
|
||||
7. **guided-flow.ts** (2 parseRoadmap):
|
||||
- Remove `parseRoadmap` from import. Keep `loadFile`. Add DB imports. Replace 2 call sites.
|
||||
|
||||
After all changes, run verification grep and existing test suites.
|
||||
|
||||
## Must-Haves
|
||||
|
||||
- [ ] Zero module-level `parseRoadmap`/`parsePlan` imports in all 7 files
|
||||
- [ ] Each file uses `isDbAvailable()` gate with DB query as primary path
|
||||
- [ ] Each file has lazy `createRequire` (or dynamic import for async) fallback for parser
|
||||
- [ ] `SliceRow.status === 'complete'` used instead of `.done` for all DB-path code
|
||||
- [ ] Existing tests pass for all modified files
|
||||
|
||||
## Verification
|
||||
|
||||
- `grep -n 'import.*parseRoadmap\|import.*parsePlan' src/resources/extensions/gsd/doctor.ts src/resources/extensions/gsd/doctor-checks.ts src/resources/extensions/gsd/visualizer-data.ts src/resources/extensions/gsd/workspace-index.ts src/resources/extensions/gsd/dashboard-overlay.ts src/resources/extensions/gsd/auto-dashboard.ts src/resources/extensions/gsd/guided-flow.ts` — returns zero results
|
||||
- Run available test suites: `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/doctor.test.ts`
|
||||
- Run `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/auto-dashboard.test.ts` (if exists)
|
||||
|
||||
## Inputs
|
||||
|
||||
- `src/resources/extensions/gsd/doctor.ts` — 3 parseRoadmap + 1 parsePlan calls to migrate
|
||||
- `src/resources/extensions/gsd/doctor-checks.ts` — 2 parseRoadmap calls
|
||||
- `src/resources/extensions/gsd/visualizer-data.ts` — 1 parseRoadmap + 1 parsePlan
|
||||
- `src/resources/extensions/gsd/workspace-index.ts` — 2 parseRoadmap + 1 parsePlan
|
||||
- `src/resources/extensions/gsd/dashboard-overlay.ts` — 1 parseRoadmap + 1 parsePlan
|
||||
- `src/resources/extensions/gsd/auto-dashboard.ts` — 1 parseRoadmap + 1 parsePlan
|
||||
- `src/resources/extensions/gsd/guided-flow.ts` — 2 parseRoadmap
|
||||
- `src/resources/extensions/gsd/gsd-db.ts` — isDbAvailable(), getMilestoneSlices(), getSliceTasks(), SliceRow, TaskRow interfaces
|
||||
- `src/resources/extensions/gsd/dispatch-guard.ts` — reference implementation of the migration pattern from S04
|
||||
|
||||
## Expected Output
|
||||
|
||||
- `src/resources/extensions/gsd/doctor.ts` — module-level parser imports removed, DB queries + lazy fallback
|
||||
- `src/resources/extensions/gsd/doctor-checks.ts` — same migration
|
||||
- `src/resources/extensions/gsd/visualizer-data.ts` — same migration
|
||||
- `src/resources/extensions/gsd/workspace-index.ts` — same migration
|
||||
- `src/resources/extensions/gsd/dashboard-overlay.ts` — same migration
|
||||
- `src/resources/extensions/gsd/auto-dashboard.ts` — same migration
|
||||
- `src/resources/extensions/gsd/guided-flow.ts` — same migration
|
||||
125
.gsd/milestones/M001/slices/S05/tasks/T04-PLAN.md
Normal file
125
.gsd/milestones/M001/slices/S05/tasks/T04-PLAN.md
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
---
|
||||
estimated_steps: 4
|
||||
estimated_files: 6
|
||||
skills_used: []
|
||||
---
|
||||
|
||||
# T04: Migrate warm/cold callers batch 2 — auto-prompts, auto-recovery, auto-direct-dispatch, auto-worktree, reactive-graph, markdown-renderer + final verification
|
||||
|
||||
**Slice:** S05 — Warm/cold callers + flag files + pre-M002 migration
|
||||
**Milestone:** M001
|
||||
|
||||
## Description
|
||||
|
||||
Migrate the remaining 6 files with parseRoadmap/parsePlan imports. `auto-prompts.ts` is the most complex (6 parser calls across 1649 lines, all async functions — use dynamic `import()` pattern already established in that file). `markdown-renderer.ts` is special: its parser calls are intentional disk-vs-DB comparisons in `findStaleArtifacts()` — only move the import from module-level to lazy `createRequire`, don't replace parser usage. Final step: run the comprehensive grep to confirm zero module-level parser imports remain anywhere in the codebase (excluding tests, md-importer, files.ts).
|
||||
|
||||
**Pattern for async callers (already used in auto-prompts.ts for decisions/requirements):**
|
||||
```typescript
|
||||
try {
|
||||
const { isDbAvailable, getMilestoneSlices } = await import("./gsd-db.js");
|
||||
if (isDbAvailable()) {
|
||||
const slices = getMilestoneSlices(mid);
|
||||
// ... use DB data
|
||||
return result;
|
||||
}
|
||||
} catch { /* fall through */ }
|
||||
// Filesystem fallback
|
||||
const roadmapContent = await loadFile(roadmapFile);
|
||||
if (!roadmapContent) return null;
|
||||
// lazy-load parser
|
||||
const { createRequire } = await import("node:module");
|
||||
const _require = createRequire(import.meta.url);
|
||||
let parseRoadmap: Function;
|
||||
try { parseRoadmap = _require("./files.ts").parseRoadmap; }
|
||||
catch { parseRoadmap = _require("./files.js").parseRoadmap; }
|
||||
const roadmap = parseRoadmap(roadmapContent);
|
||||
```
|
||||
|
||||
**Key field mappings:**
|
||||
- `roadmap.slices[].done` → `slice.status === 'complete'`
|
||||
- `plan.tasks[].done` → `task.status === 'complete' || task.status === 'done'`
|
||||
- `plan.tasks[].files` → `task.files` (already parsed `string[]` per KNOWLEDGE.md)
|
||||
- `plan.filesLikelyTouched` → `tasks.flatMap(t => t.files)`
|
||||
- Slice `depends` field: same on `SliceRow` (already parsed as `string[]`)
|
||||
|
||||
## Steps
|
||||
|
||||
1. **auto-prompts.ts** (5 parseRoadmap + 1 parsePlan — all in async functions):
|
||||
- Remove `parsePlan`, `parseRoadmap` from the module-level import on line 9. Keep `loadFile`, `parseContinue`, `parseSummary`, `extractUatType`, `loadActiveOverrides`, `formatOverridesSection`, `parseTaskPlanFile`.
|
||||
- **`inlineDependencySummaries()` (line ~184):** Uses `parseRoadmap(roadmapContent).slices.find(s => s.id === sid)?.depends`. Replace with DB: `const { isDbAvailable, getSlice } = await import("./gsd-db.js"); if (isDbAvailable()) { const slice = getSlice(mid, sid); if (!slice || slice.depends.length === 0) return "- (no dependencies)"; /* use slice.depends */ }`. Fallback: lazy-load parseRoadmap.
|
||||
- **`checkNeedsReassessment()` (line ~691):** Uses `parseRoadmap().slices` to find completed/incomplete slices. Replace with: `getMilestoneSlices(mid)`, filter by `s.status === 'complete'` vs not.
|
||||
- **`checkNeedsRunUat()` (line ~732):** Same pattern as checkNeedsReassessment — replace with `getMilestoneSlices(mid)`.
|
||||
- **`buildCompleteMilestonePrompt()` (line ~1221):** Iterates `roadmap.slices` to inline slice summaries. Replace with `getMilestoneSlices(mid)` to get slice IDs.
|
||||
- **`buildValidateMilestonePrompt()` (line ~1277):** Same as buildCompleteMilestonePrompt — iterate `getMilestoneSlices(mid)` for slice summary inlining.
|
||||
- **`buildResumeContextListing()` (line ~1603):** Uses `parsePlan(planContent).tasks` to find incomplete tasks for listing. Replace with `getSliceTasks(mid, sid)`, filter by `task.status !== 'complete' && task.status !== 'done'`.
|
||||
- Create a local helper `async function lazyParseRoadmap(content: string)` and `async function lazyParsePlan(content: string)` at top of file to centralize the createRequire fallback pattern.
|
||||
|
||||
2. **auto-recovery.ts** (1 parsePlan at line 370, 1 parseRoadmap at line 407):
|
||||
- Remove `parseRoadmap`, `parsePlan` from module-level import on line 14. Keep `clearParseCache`.
|
||||
- Line 370 `parsePlan`: Used in plan-slice completion check — gets task list to verify task plan files exist. Replace with `getSliceTasks(mid, sid)` to get task IDs, then check if task plan files exist on disk. Fallback: lazy-load parsePlan.
|
||||
- Line 407 `parseRoadmap`: Already inside `!isDbAvailable()` block — this IS the fallback path. Just move the import from module-level to lazy `createRequire` at that call site.
|
||||
- Add `import { isDbAvailable, getSliceTasks } from "./gsd-db.js";` to module-level imports.
|
||||
|
||||
3. **auto-direct-dispatch.ts, auto-worktree.ts, reactive-graph.ts:**
|
||||
- **auto-direct-dispatch.ts** (2 parseRoadmap at lines 160, 185): Remove `parseRoadmap` from import (keep `loadFile`). Add `isDbAvailable, getMilestoneSlices`. Replace both call sites with `getMilestoneSlices()` + fallback.
|
||||
- **auto-worktree.ts** (1 parseRoadmap at line 1002): Remove `parseRoadmap` from import. Add DB imports. Replace call site.
|
||||
- **reactive-graph.ts** (1 parsePlan at line 191): Remove `parsePlan` from import (keep `loadFile`, `parseTaskPlanIO`). Add `isDbAvailable, getSliceTasks`. Replace with `getSliceTasks()` + fallback. Note: `parseTaskPlanIO` is NOT a planning parser — it parses Inputs/Expected Output from task plan files for dependency graphing. Keep it as module-level import.
|
||||
|
||||
4. **markdown-renderer.ts** (2 parseRoadmap + 2 parsePlan in `findStaleArtifacts()`):
|
||||
- These parser calls are **intentional** — they compare disk content against DB state to detect staleness. Do NOT replace parser usage with DB queries.
|
||||
- Move `parseRoadmap`, `parsePlan` from module-level import (line 33) to lazy `createRequire` inside `findStaleArtifacts()`. Keep `saveFile`, `clearParseCache` as module-level.
|
||||
- At the top of `findStaleArtifacts()` (around line 775), add lazy loading:
|
||||
```typescript
|
||||
const { createRequire } = await import("node:module");
|
||||
const _require = createRequire(import.meta.url);
|
||||
let parseRoadmap: Function, parsePlan: Function;
|
||||
try {
|
||||
const m = _require("./files.ts");
|
||||
parseRoadmap = m.parseRoadmap; parsePlan = m.parsePlan;
|
||||
} catch {
|
||||
const m = _require("./files.js");
|
||||
parseRoadmap = m.parseRoadmap; parsePlan = m.parsePlan;
|
||||
}
|
||||
```
|
||||
- Note: `findStaleArtifacts()` is async, so dynamic import works too. Use whichever is simpler.
|
||||
|
||||
5. **Final verification grep:**
|
||||
- `grep -rn 'import.*parseRoadmap\|import.*parsePlan\|import.*parseRoadmapSlices' src/resources/extensions/gsd/*.ts | grep -v '/tests/' | grep -v 'md-importer' | grep -v 'files.ts'`
|
||||
- Expected: ZERO results. No module-level parser imports remain.
|
||||
- Run `auto-recovery.test.ts` and any other available test suites for modified files.
|
||||
|
||||
## Must-Haves
|
||||
|
||||
- [ ] Zero module-level `parseRoadmap`/`parsePlan` imports in all 6 files
|
||||
- [ ] `auto-prompts.ts` uses DB queries as primary path for all 6 parser call sites
|
||||
- [ ] `auto-recovery.ts` parsePlan at line 370 replaced with getSliceTasks() + fallback
|
||||
- [ ] `markdown-renderer.ts` parser imports moved to lazy loading (parser usage kept)
|
||||
- [ ] Final grep returns zero module-level parser imports across all non-test source files
|
||||
- [ ] All existing test suites pass
|
||||
|
||||
## Verification
|
||||
|
||||
- `grep -rn 'import.*parseRoadmap\|import.*parsePlan\|import.*parseRoadmapSlices' src/resources/extensions/gsd/*.ts | grep -v '/tests/' | grep -v 'md-importer' | grep -v 'files.ts'` — returns zero results
|
||||
- `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/auto-recovery.test.ts` — passes
|
||||
- `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/markdown-renderer.test.ts` — passes
|
||||
- `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/planning-crossval.test.ts` — passes
|
||||
|
||||
## Inputs
|
||||
|
||||
- `src/resources/extensions/gsd/auto-prompts.ts` — 5 parseRoadmap + 1 parsePlan calls to migrate (all async functions)
|
||||
- `src/resources/extensions/gsd/auto-recovery.ts` — 1 parsePlan + 1 parseRoadmap (latter already in !isDbAvailable block)
|
||||
- `src/resources/extensions/gsd/auto-direct-dispatch.ts` — 2 parseRoadmap calls
|
||||
- `src/resources/extensions/gsd/auto-worktree.ts` — 1 parseRoadmap call
|
||||
- `src/resources/extensions/gsd/reactive-graph.ts` — 1 parsePlan call
|
||||
- `src/resources/extensions/gsd/markdown-renderer.ts` — 2 parseRoadmap + 2 parsePlan (intentional disk-vs-DB comparison)
|
||||
- `src/resources/extensions/gsd/gsd-db.ts` — isDbAvailable(), getMilestoneSlices(), getSliceTasks(), getSlice(), getTask()
|
||||
- `src/resources/extensions/gsd/dispatch-guard.ts` — reference for lazy createRequire pattern
|
||||
|
||||
## Expected Output
|
||||
|
||||
- `src/resources/extensions/gsd/auto-prompts.ts` — module-level parser imports removed, 6 call sites use DB queries with lazy fallback
|
||||
- `src/resources/extensions/gsd/auto-recovery.ts` — module-level parser imports removed, DB + lazy fallback
|
||||
- `src/resources/extensions/gsd/auto-direct-dispatch.ts` — module-level parseRoadmap removed, DB + fallback
|
||||
- `src/resources/extensions/gsd/auto-worktree.ts` — module-level parseRoadmap removed, DB + fallback
|
||||
- `src/resources/extensions/gsd/reactive-graph.ts` — module-level parsePlan removed, DB + fallback
|
||||
- `src/resources/extensions/gsd/markdown-renderer.ts` — module-level parser imports moved to lazy loading inside findStaleArtifacts()
|
||||
Loading…
Add table
Reference in a new issue