gsd-pi 2.43.0 → 2.44.0-dev.0b97ffd
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -12
- package/dist/cli.js +13 -1
- package/dist/help-text.js +24 -0
- package/dist/resources/extensions/bg-shell/overlay.js +3 -0
- package/dist/resources/extensions/github-sync/sync.js +2 -1
- package/dist/resources/extensions/gsd/auto/loop.js +0 -2
- package/dist/resources/extensions/gsd/auto/phases.js +7 -12
- package/dist/resources/extensions/gsd/auto-dashboard.js +19 -18
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +34 -19
- package/dist/resources/extensions/gsd/auto-dispatch.js +36 -21
- package/dist/resources/extensions/gsd/auto-post-unit.js +128 -14
- package/dist/resources/extensions/gsd/auto-prompts.js +202 -92
- package/dist/resources/extensions/gsd/auto-recovery.js +83 -135
- package/dist/resources/extensions/gsd/auto-start.js +10 -0
- package/dist/resources/extensions/gsd/auto-supervisor.js +14 -0
- package/dist/resources/extensions/gsd/auto-timeout-recovery.js +4 -7
- package/dist/resources/extensions/gsd/auto-verification.js +5 -10
- package/dist/resources/extensions/gsd/auto-worktree.js +123 -30
- package/dist/resources/extensions/gsd/auto.js +1 -4
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +611 -0
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +28 -3
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +7 -0
- package/dist/resources/extensions/gsd/commands/catalog.js +3 -1
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +15 -1
- package/dist/resources/extensions/gsd/commands/handlers/workflow.js +5 -0
- package/dist/resources/extensions/gsd/commands-handlers.js +1 -1
- package/dist/resources/extensions/gsd/commands-maintenance.js +78 -3
- package/dist/resources/extensions/gsd/dashboard-overlay.js +32 -31
- package/dist/resources/extensions/gsd/db-writer.js +95 -4
- package/dist/resources/extensions/gsd/dispatch-guard.js +35 -30
- package/dist/resources/extensions/gsd/doctor-checks.js +28 -11
- package/dist/resources/extensions/gsd/doctor-environment.js +28 -0
- package/dist/resources/extensions/gsd/doctor-types.js +0 -15
- package/dist/resources/extensions/gsd/doctor.js +46 -282
- package/dist/resources/extensions/gsd/file-watcher.js +5 -1
- package/dist/resources/extensions/gsd/files.js +14 -198
- package/dist/resources/extensions/gsd/git-service.js +4 -0
- package/dist/resources/extensions/gsd/gitignore.js +4 -0
- package/dist/resources/extensions/gsd/gsd-db.js +819 -197
- package/dist/resources/extensions/gsd/guided-flow.js +18 -8
- package/dist/resources/extensions/gsd/markdown-renderer.js +862 -0
- package/dist/resources/extensions/gsd/md-importer.js +182 -4
- package/dist/resources/extensions/gsd/native-git-bridge.js +10 -1
- package/dist/resources/extensions/gsd/parallel-eligibility.js +14 -19
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +38 -0
- package/dist/resources/extensions/gsd/parsers-legacy.js +239 -0
- package/dist/resources/extensions/gsd/preferences-types.js +1 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +9 -0
- package/dist/resources/extensions/gsd/preferences.js +1 -0
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +22 -9
- package/dist/resources/extensions/gsd/prompts/discuss.md +2 -2
- package/dist/resources/extensions/gsd/prompts/execute-task.md +15 -5
- package/dist/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-plan-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +6 -10
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -7
- package/dist/resources/extensions/gsd/prompts/reactive-execute.md +3 -3
- package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -7
- package/dist/resources/extensions/gsd/prompts/replan-slice.md +6 -6
- package/dist/resources/extensions/gsd/reactive-graph.js +33 -3
- package/dist/resources/extensions/gsd/skill-health.js +3 -1
- package/dist/resources/extensions/gsd/state.js +484 -30
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +128 -0
- package/dist/resources/extensions/gsd/tools/complete-slice.js +244 -0
- package/dist/resources/extensions/gsd/tools/complete-task.js +204 -0
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +205 -0
- package/dist/resources/extensions/gsd/tools/plan-slice.js +155 -0
- package/dist/resources/extensions/gsd/tools/plan-task.js +94 -0
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +152 -0
- package/dist/resources/extensions/gsd/tools/replan-slice.js +146 -0
- package/dist/resources/extensions/gsd/triage-resolution.js +17 -1
- package/dist/resources/extensions/gsd/undo.js +197 -3
- package/dist/resources/extensions/gsd/visualizer-data.js +53 -16
- package/dist/resources/extensions/gsd/workspace-index.js +63 -39
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +18 -17
- package/dist/web/standalone/.next/build-manifest.json +4 -4
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
- package/dist/web/standalone/.next/required-server-files.json +4 -4
- package/dist/web/standalone/.next/routes-manifest.json +6 -0
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -4
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -0
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -0
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -0
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +5 -5
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +5 -5
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +18 -17
- package/dist/web/standalone/.next/server/chunks/229.js +3 -3
- package/dist/web/standalone/.next/server/chunks/471.js +3 -3
- package/dist/web/standalone/.next/server/functions-config-manifest.json +1 -0
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.js +2 -2
- package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +2 -2
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/alS4hoANx0TK4UVZY27da/_buildManifest.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{4024.c195dc1fdd2adbea.js → 4024.0de81b543b28b9fe.js} +2 -2
- package/dist/web/standalone/.next/static/chunks/app/_global-error/{page-d07a2c023f1aef1e.js → page-d83ba70a25a85472.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/_not-found/page-f2a7482d42a5614b.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/boot/{route-d07a2c023f1aef1e.js → route-d83ba70a25a85472.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/input/{route-d07a2c023f1aef1e.js → route-d83ba70a25a85472.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/resize/{route-d07a2c023f1aef1e.js → route-d83ba70a25a85472.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/captures/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/files/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/git/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/history/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/projects/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/steer/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/switch-root/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/undo/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/update/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/page-b9367c5ae13b99c6.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{main-app-2f2ee7b85712c2bd.js → main-app-fdab67f7802d7832.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-fa307370fcf9fb2c.js → webpack-9014b5adb127a98a.js} +1 -1
- package/dist/web/standalone/.next/static/css/8a727f372cf53002.css +1 -0
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
- package/dist/web/standalone/server.js +1 -1
- package/package.json +4 -4
- package/packages/pi-ai/dist/models.custom.d.ts +173 -0
- package/packages/pi-ai/dist/models.custom.d.ts.map +1 -0
- package/packages/pi-ai/dist/models.custom.js +170 -0
- package/packages/pi-ai/dist/models.custom.js.map +1 -0
- package/packages/pi-ai/dist/models.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.js +16 -1
- package/packages/pi-ai/dist/models.js.map +1 -1
- package/packages/pi-ai/dist/models.test.d.ts +2 -0
- package/packages/pi-ai/dist/models.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/models.test.js +67 -0
- package/packages/pi-ai/dist/models.test.js.map +1 -0
- package/packages/pi-ai/src/models.custom.ts +172 -0
- package/packages/pi-ai/src/models.test.ts +85 -0
- package/packages/pi-ai/src/models.ts +17 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts +10 -3
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +21 -34
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js +6 -8
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.d.ts +2 -2
- package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +2 -2
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +4 -4
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +6 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +80 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.test.js +63 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +24 -26
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +37 -0
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/fallback-resolver.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/fallback-resolver.js +2 -3
- package/packages/pi-coding-agent/dist/core/fallback-resolver.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/fallback-resolver.test.js +12 -2
- package/packages/pi-coding-agent/dist/core/fallback-resolver.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/fs-utils.test.js +29 -48
- package/packages/pi-coding-agent/dist/core/fs-utils.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts +38 -0
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js +192 -0
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/lsp/client.d.ts +5 -0
- package/packages/pi-coding-agent/dist/core/lsp/client.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/client.js +69 -21
- package/packages/pi-coding-agent/dist/core/lsp/client.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +255 -0
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts +15 -0
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +40 -3
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/package-commands.d.ts +25 -0
- package/packages/pi-coding-agent/dist/core/package-commands.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/package-commands.js +253 -0
- package/packages/pi-coding-agent/dist/core/package-commands.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/package-commands.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/package-commands.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/package-commands.test.js +225 -0
- package/packages/pi-coding-agent/dist/core/package-commands.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +34 -44
- package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +4 -0
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.test.js +30 -34
- package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js +10 -12
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts +3 -1
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js +1 -0
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/main.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/main.js +11 -199
- package/packages/pi-coding-agent/dist/main.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts +6 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +21 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +8 -15
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/print-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/print-mode.js +45 -34
- package/packages/pi-coding-agent/dist/modes/print-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.js +7 -2
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js +2 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js +43 -47
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/agent-session.ts +26 -37
- package/packages/pi-coding-agent/src/core/auth-storage.test.ts +7 -7
- package/packages/pi-coding-agent/src/core/compaction/branch-summarization.ts +2 -2
- package/packages/pi-coding-agent/src/core/compaction/compaction.ts +3 -3
- package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +4 -4
- package/packages/pi-coding-agent/src/core/extensions/index.ts +5 -0
- package/packages/pi-coding-agent/src/core/extensions/loader.test.ts +96 -0
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +89 -0
- package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +26 -26
- package/packages/pi-coding-agent/src/core/extensions/types.ts +44 -0
- package/packages/pi-coding-agent/src/core/fallback-resolver.test.ts +15 -2
- package/packages/pi-coding-agent/src/core/fallback-resolver.ts +2 -3
- package/packages/pi-coding-agent/src/core/fs-utils.test.ts +31 -43
- package/packages/pi-coding-agent/src/core/lifecycle-hooks.ts +274 -0
- package/packages/pi-coding-agent/src/core/lsp/client.ts +83 -21
- package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +288 -0
- package/packages/pi-coding-agent/src/core/model-registry.ts +39 -3
- package/packages/pi-coding-agent/src/core/package-commands.test.ts +240 -0
- package/packages/pi-coding-agent/src/core/package-commands.ts +310 -0
- package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +40 -45
- package/packages/pi-coding-agent/src/core/sdk.ts +4 -0
- package/packages/pi-coding-agent/src/core/session-manager.test.ts +33 -33
- package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +17 -17
- package/packages/pi-coding-agent/src/index.ts +7 -0
- package/packages/pi-coding-agent/src/main.ts +11 -232
- package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +20 -0
- package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +9 -16
- package/packages/pi-coding-agent/src/modes/print-mode.ts +42 -32
- package/packages/pi-coding-agent/src/modes/rpc/rpc-client.ts +8 -2
- package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +2 -1
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +74 -74
- package/pkg/dist/modes/interactive/theme/theme.d.ts +1 -1
- package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/pkg/dist/modes/interactive/theme/theme.js +8 -15
- package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/bg-shell/overlay.ts +4 -0
- package/src/resources/extensions/github-sync/sync.ts +2 -1
- package/src/resources/extensions/gsd/auto/loop-deps.ts +0 -8
- package/src/resources/extensions/gsd/auto/loop.ts +0 -2
- package/src/resources/extensions/gsd/auto/phases.ts +7 -20
- package/src/resources/extensions/gsd/auto/types.ts +0 -1
- package/src/resources/extensions/gsd/auto-dashboard.ts +20 -16
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +34 -19
- package/src/resources/extensions/gsd/auto-dispatch.ts +38 -21
- package/src/resources/extensions/gsd/auto-post-unit.ts +150 -15
- package/src/resources/extensions/gsd/auto-prompts.ts +186 -103
- package/src/resources/extensions/gsd/auto-recovery.ts +77 -142
- package/src/resources/extensions/gsd/auto-start.ts +14 -0
- package/src/resources/extensions/gsd/auto-supervisor.ts +14 -0
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +6 -7
- package/src/resources/extensions/gsd/auto-verification.ts +4 -9
- package/src/resources/extensions/gsd/auto-worktree.ts +126 -30
- package/src/resources/extensions/gsd/auto.ts +0 -9
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +675 -4
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +31 -3
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +7 -0
- package/src/resources/extensions/gsd/commands/catalog.ts +3 -1
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +15 -1
- package/src/resources/extensions/gsd/commands/handlers/workflow.ts +8 -0
- package/src/resources/extensions/gsd/commands-handlers.ts +1 -1
- package/src/resources/extensions/gsd/commands-maintenance.ts +86 -3
- package/src/resources/extensions/gsd/dashboard-overlay.ts +17 -13
- package/src/resources/extensions/gsd/db-writer.ts +105 -4
- package/src/resources/extensions/gsd/dispatch-guard.ts +32 -30
- package/src/resources/extensions/gsd/doctor-checks.ts +25 -11
- package/src/resources/extensions/gsd/doctor-environment.ts +31 -0
- package/src/resources/extensions/gsd/doctor-types.ts +0 -23
- package/src/resources/extensions/gsd/doctor.ts +45 -295
- package/src/resources/extensions/gsd/file-watcher.ts +4 -1
- package/src/resources/extensions/gsd/files.ts +16 -220
- package/src/resources/extensions/gsd/git-service.ts +4 -0
- package/src/resources/extensions/gsd/gitignore.ts +4 -0
- package/src/resources/extensions/gsd/gsd-db.ts +1157 -370
- package/src/resources/extensions/gsd/guided-flow.ts +20 -8
- package/src/resources/extensions/gsd/markdown-renderer.ts +1098 -0
- package/src/resources/extensions/gsd/md-importer.ts +211 -2
- package/src/resources/extensions/gsd/native-git-bridge.ts +12 -1
- package/src/resources/extensions/gsd/parallel-eligibility.ts +14 -18
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +43 -0
- package/src/resources/extensions/gsd/parsers-legacy.ts +271 -0
- package/src/resources/extensions/gsd/preferences-types.ts +3 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +9 -0
- package/src/resources/extensions/gsd/preferences.ts +1 -0
- package/src/resources/extensions/gsd/prompts/complete-slice.md +22 -9
- package/src/resources/extensions/gsd/prompts/discuss.md +2 -2
- package/src/resources/extensions/gsd/prompts/execute-task.md +15 -5
- package/src/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-plan-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +6 -10
- package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -7
- package/src/resources/extensions/gsd/prompts/reactive-execute.md +3 -3
- package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -7
- package/src/resources/extensions/gsd/prompts/replan-slice.md +6 -6
- package/src/resources/extensions/gsd/reactive-graph.ts +33 -3
- package/src/resources/extensions/gsd/skill-health.ts +2 -1
- package/src/resources/extensions/gsd/state.ts +547 -29
- package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +99 -99
- package/src/resources/extensions/gsd/tests/atomic-task-closeout.test.ts +8 -120
- package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +14 -16
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +20 -11
- package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +43 -57
- package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +11 -13
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +600 -513
- package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +73 -75
- package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +34 -56
- package/src/resources/extensions/gsd/tests/auto-stash-merge.test.ts +121 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +540 -668
- package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +165 -143
- package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +29 -52
- package/src/resources/extensions/gsd/tests/captures.test.ts +148 -176
- package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +32 -33
- package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +141 -143
- package/src/resources/extensions/gsd/tests/commands-inspect-open-db.test.ts +25 -25
- package/src/resources/extensions/gsd/tests/commands-logs.test.ts +81 -81
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +39 -60
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +375 -0
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +387 -0
- package/src/resources/extensions/gsd/tests/context-store.test.ts +354 -367
- package/src/resources/extensions/gsd/tests/continue-here.test.ts +68 -72
- package/src/resources/extensions/gsd/tests/cost-projection.test.ts +92 -106
- package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +27 -35
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +0 -2
- package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +220 -237
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +390 -420
- package/src/resources/extensions/gsd/tests/definition-loader.test.ts +76 -92
- package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +512 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +644 -84
- package/src/resources/extensions/gsd/tests/derive-state-deps.test.ts +78 -101
- package/src/resources/extensions/gsd/tests/derive-state.test.ts +192 -227
- package/src/resources/extensions/gsd/tests/detection.test.ts +232 -278
- package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +30 -34
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +192 -161
- package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +43 -49
- package/src/resources/extensions/gsd/tests/dispatch-uat-last-completed.test.ts +28 -32
- package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +30 -90
- package/src/resources/extensions/gsd/tests/doctor-delimiter-fix.test.ts +34 -38
- package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +57 -80
- package/src/resources/extensions/gsd/tests/doctor-environment-worktree.test.ts +164 -0
- package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +72 -97
- package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +55 -153
- package/src/resources/extensions/gsd/tests/doctor-git.test.ts +104 -145
- package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +84 -106
- package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +53 -97
- package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +72 -93
- package/src/resources/extensions/gsd/tests/doctor.test.ts +109 -149
- package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +123 -131
- package/src/resources/extensions/gsd/tests/exit-command.test.ts +20 -24
- package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +48 -57
- package/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts +5 -7
- package/src/resources/extensions/gsd/tests/flag-file-db.test.ts +278 -0
- package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +232 -0
- package/src/resources/extensions/gsd/tests/git-locale.test.ts +13 -27
- package/src/resources/extensions/gsd/tests/git-service.test.ts +291 -390
- package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +31 -39
- package/src/resources/extensions/gsd/tests/graph-operations.test.ts +63 -69
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +255 -264
- package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +108 -119
- package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +440 -0
- package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +229 -262
- package/src/resources/extensions/gsd/tests/headless-answers.test.ts +13 -13
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +29 -37
- package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +81 -270
- package/src/resources/extensions/gsd/tests/init-wizard.test.ts +16 -18
- package/src/resources/extensions/gsd/tests/integration-edge.test.ts +41 -46
- package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +42 -53
- package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +75 -91
- package/src/resources/extensions/gsd/tests/integration-proof.test.ts +643 -0
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +0 -3
- package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +1161 -0
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +101 -125
- package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +45 -54
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +81 -94
- package/src/resources/extensions/gsd/tests/migrate-command.test.ts +57 -66
- package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +429 -0
- package/src/resources/extensions/gsd/tests/migrate-parser.test.ts +161 -170
- package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +125 -141
- package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +107 -131
- package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +89 -97
- package/src/resources/extensions/gsd/tests/migrate-writer.test.ts +127 -164
- package/src/resources/extensions/gsd/tests/must-have-parser.test.ts +81 -94
- package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +35 -36
- package/src/resources/extensions/gsd/tests/overrides.test.ts +99 -106
- package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +40 -47
- package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +25 -28
- package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +66 -83
- package/src/resources/extensions/gsd/tests/park-edge-cases.test.ts +54 -77
- package/src/resources/extensions/gsd/tests/park-milestone.test.ts +68 -115
- package/src/resources/extensions/gsd/tests/parsers.test.ts +548 -612
- package/src/resources/extensions/gsd/tests/paths.test.ts +72 -87
- package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +176 -113
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +179 -0
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +145 -0
- package/src/resources/extensions/gsd/tests/planning-crossval.test.ts +305 -0
- package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +77 -117
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +139 -0
- package/src/resources/extensions/gsd/tests/prompt-db.test.ts +56 -56
- package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +93 -119
- package/src/resources/extensions/gsd/tests/queue-order.test.ts +70 -82
- package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +42 -55
- package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/quick-branch-lifecycle.test.ts +45 -73
- package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +325 -0
- package/src/resources/extensions/gsd/tests/reassess-prompt.test.ts +28 -38
- package/src/resources/extensions/gsd/tests/replan-handler.test.ts +410 -0
- package/src/resources/extensions/gsd/tests/replan-slice.test.ts +73 -80
- package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +71 -74
- package/src/resources/extensions/gsd/tests/requirements.test.ts +70 -75
- package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +44 -66
- package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +114 -181
- package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/rogue-file-detection.test.ts +296 -0
- package/src/resources/extensions/gsd/tests/rule-registry.test.ts +63 -65
- package/src/resources/extensions/gsd/tests/run-uat.test.ts +66 -128
- package/src/resources/extensions/gsd/tests/schema-v9-sequence.test.ts +176 -0
- package/src/resources/extensions/gsd/tests/session-lock-multipath.test.ts +18 -25
- package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +37 -44
- package/src/resources/extensions/gsd/tests/shared-wal.test.ts +209 -0
- package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +6 -8
- package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +22 -28
- package/src/resources/extensions/gsd/tests/token-cost-display.test.ts +118 -0
- package/src/resources/extensions/gsd/tests/token-savings.test.ts +54 -56
- package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +23 -25
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +19 -13
- package/src/resources/extensions/gsd/tests/undo.test.ts +321 -1
- package/src/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +66 -82
- package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +46 -47
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/verification-evidence.test.ts +0 -142
- package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -22
- package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +84 -86
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +41 -43
- package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +94 -96
- package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +11 -13
- package/src/resources/extensions/gsd/tests/worker-registry.test.ts +27 -29
- package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +50 -52
- package/src/resources/extensions/gsd/tests/worktree-bugfix.test.ts +10 -13
- package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +14 -18
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +38 -39
- package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +17 -21
- package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +12 -5
- package/src/resources/extensions/gsd/tests/worktree-health.test.ts +25 -30
- package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +30 -37
- package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +15 -22
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +59 -66
- package/src/resources/extensions/gsd/tests/worktree.test.ts +44 -50
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +176 -0
- package/src/resources/extensions/gsd/tools/complete-slice.ts +300 -0
- package/src/resources/extensions/gsd/tools/complete-task.ts +245 -0
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +249 -0
- package/src/resources/extensions/gsd/tools/plan-slice.ts +194 -0
- package/src/resources/extensions/gsd/tools/plan-task.ts +116 -0
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +203 -0
- package/src/resources/extensions/gsd/tools/replan-slice.ts +192 -0
- package/src/resources/extensions/gsd/triage-resolution.ts +20 -1
- package/src/resources/extensions/gsd/types.ts +50 -0
- package/src/resources/extensions/gsd/undo.ts +247 -3
- package/src/resources/extensions/gsd/visualizer-data.ts +54 -17
- package/src/resources/extensions/gsd/workspace-index.ts +64 -46
- package/dist/resources/extensions/gsd/auto-observability.js +0 -56
- package/dist/resources/extensions/gsd/observability-validator.js +0 -422
- package/dist/resources/extensions/gsd/roadmap-mutations.js +0 -110
- package/dist/web/standalone/.next/static/VvclDCW6TAWjEyLU-EYL1/_buildManifest.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/_not-found/page-e07acdb7dd069836.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/captures/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/files/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/git/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/history/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/projects/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/steer/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/undo/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/update/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/layout-745c6ed5fea5fb06.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/page-801b53eff6e83579.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-e6255954dccfcf0a.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/css/123c0bb039697968.css +0 -1
- package/src/resources/extensions/gsd/auto-observability.ts +0 -74
- package/src/resources/extensions/gsd/observability-validator.ts +0 -456
- package/src/resources/extensions/gsd/roadmap-mutations.ts +0 -134
- package/src/resources/extensions/gsd/tests/doctor-task-done-missing-summary-slice-loop.test.ts +0 -174
- package/src/resources/extensions/gsd/tests/plan-quality-validator.test.ts +0 -474
- /package/dist/web/standalone/.next/static/{VvclDCW6TAWjEyLU-EYL1 → alS4hoANx0TK4UVZY27da}/_ssgManifest.js +0 -0
|
@@ -8,18 +8,13 @@ import { createRequire } from "node:module";
|
|
|
8
8
|
import { existsSync, copyFileSync, mkdirSync } from "node:fs";
|
|
9
9
|
import { dirname } from "node:path";
|
|
10
10
|
import { GSDError, GSD_STALE_STATE } from "./errors.js";
|
|
11
|
-
// Create a require function for loading native modules in ESM context
|
|
12
11
|
const _require = createRequire(import.meta.url);
|
|
13
12
|
let providerName = null;
|
|
14
13
|
let providerModule = null;
|
|
15
14
|
let loadAttempted = false;
|
|
16
|
-
/**
|
|
17
|
-
* Suppress the ExperimentalWarning for SQLite from node:sqlite.
|
|
18
|
-
* Must be called before require('node:sqlite').
|
|
19
|
-
*/
|
|
20
15
|
function suppressSqliteWarning() {
|
|
21
16
|
const origEmit = process.emit;
|
|
22
|
-
// @ts-expect-error
|
|
17
|
+
// @ts-expect-error overriding process.emit for warning filter
|
|
23
18
|
process.emit = function (event, ...args) {
|
|
24
19
|
if (event === "warning" &&
|
|
25
20
|
args[0] &&
|
|
@@ -38,7 +33,6 @@ function loadProvider() {
|
|
|
38
33
|
if (loadAttempted)
|
|
39
34
|
return;
|
|
40
35
|
loadAttempted = true;
|
|
41
|
-
// Try node:sqlite first
|
|
42
36
|
try {
|
|
43
37
|
suppressSqliteWarning();
|
|
44
38
|
const mod = _require("node:sqlite");
|
|
@@ -49,9 +43,8 @@ function loadProvider() {
|
|
|
49
43
|
}
|
|
50
44
|
}
|
|
51
45
|
catch {
|
|
52
|
-
//
|
|
46
|
+
// unavailable
|
|
53
47
|
}
|
|
54
|
-
// Try better-sqlite3
|
|
55
48
|
try {
|
|
56
49
|
const mod = _require("better-sqlite3");
|
|
57
50
|
if (typeof mod === "function" || (mod && mod.default)) {
|
|
@@ -61,14 +54,10 @@ function loadProvider() {
|
|
|
61
54
|
}
|
|
62
55
|
}
|
|
63
56
|
catch {
|
|
64
|
-
//
|
|
57
|
+
// unavailable
|
|
65
58
|
}
|
|
66
59
|
process.stderr.write("gsd-db: No SQLite provider available (tried node:sqlite, better-sqlite3)\n");
|
|
67
60
|
}
|
|
68
|
-
// ─── Database Adapter ──────────────────────────────────────────────────────
|
|
69
|
-
/**
|
|
70
|
-
* Normalize a row from node:sqlite (null-prototype) to a plain object.
|
|
71
|
-
*/
|
|
72
61
|
function normalizeRow(row) {
|
|
73
62
|
if (row == null)
|
|
74
63
|
return undefined;
|
|
@@ -113,17 +102,16 @@ function openRawDb(path) {
|
|
|
113
102
|
const { DatabaseSync } = providerModule;
|
|
114
103
|
return new DatabaseSync(path);
|
|
115
104
|
}
|
|
116
|
-
// better-sqlite3
|
|
117
105
|
const Database = providerModule;
|
|
118
106
|
return new Database(path);
|
|
119
107
|
}
|
|
120
|
-
|
|
121
|
-
const SCHEMA_VERSION = 4;
|
|
108
|
+
const SCHEMA_VERSION = 10;
|
|
122
109
|
function initSchema(db, fileBacked) {
|
|
123
|
-
|
|
124
|
-
if (fileBacked) {
|
|
110
|
+
if (fileBacked)
|
|
125
111
|
db.exec("PRAGMA journal_mode=WAL");
|
|
126
|
-
|
|
112
|
+
if (fileBacked)
|
|
113
|
+
db.exec("PRAGMA busy_timeout = 5000");
|
|
114
|
+
db.exec("PRAGMA foreign_keys = ON");
|
|
127
115
|
db.exec("BEGIN");
|
|
128
116
|
try {
|
|
129
117
|
db.exec(`
|
|
@@ -194,16 +182,128 @@ function initSchema(db, fileBacked) {
|
|
|
194
182
|
activity_file TEXT,
|
|
195
183
|
processed_at TEXT NOT NULL
|
|
196
184
|
)
|
|
185
|
+
`);
|
|
186
|
+
db.exec(`
|
|
187
|
+
CREATE TABLE IF NOT EXISTS milestones (
|
|
188
|
+
id TEXT PRIMARY KEY,
|
|
189
|
+
title TEXT NOT NULL DEFAULT '',
|
|
190
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
191
|
+
depends_on TEXT NOT NULL DEFAULT '[]',
|
|
192
|
+
created_at TEXT NOT NULL DEFAULT '',
|
|
193
|
+
completed_at TEXT DEFAULT NULL,
|
|
194
|
+
vision TEXT NOT NULL DEFAULT '',
|
|
195
|
+
success_criteria TEXT NOT NULL DEFAULT '[]',
|
|
196
|
+
key_risks TEXT NOT NULL DEFAULT '[]',
|
|
197
|
+
proof_strategy TEXT NOT NULL DEFAULT '[]',
|
|
198
|
+
verification_contract TEXT NOT NULL DEFAULT '',
|
|
199
|
+
verification_integration TEXT NOT NULL DEFAULT '',
|
|
200
|
+
verification_operational TEXT NOT NULL DEFAULT '',
|
|
201
|
+
verification_uat TEXT NOT NULL DEFAULT '',
|
|
202
|
+
definition_of_done TEXT NOT NULL DEFAULT '[]',
|
|
203
|
+
requirement_coverage TEXT NOT NULL DEFAULT '',
|
|
204
|
+
boundary_map_markdown TEXT NOT NULL DEFAULT ''
|
|
205
|
+
)
|
|
206
|
+
`);
|
|
207
|
+
db.exec(`
|
|
208
|
+
CREATE TABLE IF NOT EXISTS slices (
|
|
209
|
+
milestone_id TEXT NOT NULL,
|
|
210
|
+
id TEXT NOT NULL,
|
|
211
|
+
title TEXT NOT NULL DEFAULT '',
|
|
212
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
213
|
+
risk TEXT NOT NULL DEFAULT 'medium',
|
|
214
|
+
depends TEXT NOT NULL DEFAULT '[]',
|
|
215
|
+
demo TEXT NOT NULL DEFAULT '',
|
|
216
|
+
created_at TEXT NOT NULL DEFAULT '',
|
|
217
|
+
completed_at TEXT DEFAULT NULL,
|
|
218
|
+
full_summary_md TEXT NOT NULL DEFAULT '',
|
|
219
|
+
full_uat_md TEXT NOT NULL DEFAULT '',
|
|
220
|
+
goal TEXT NOT NULL DEFAULT '',
|
|
221
|
+
success_criteria TEXT NOT NULL DEFAULT '',
|
|
222
|
+
proof_level TEXT NOT NULL DEFAULT '',
|
|
223
|
+
integration_closure TEXT NOT NULL DEFAULT '',
|
|
224
|
+
observability_impact TEXT NOT NULL DEFAULT '',
|
|
225
|
+
sequence INTEGER DEFAULT 0, -- DEAD CODE: no tool exposes sequence — always 0
|
|
226
|
+
replan_triggered_at TEXT DEFAULT NULL,
|
|
227
|
+
PRIMARY KEY (milestone_id, id),
|
|
228
|
+
FOREIGN KEY (milestone_id) REFERENCES milestones(id)
|
|
229
|
+
)
|
|
230
|
+
`);
|
|
231
|
+
db.exec(`
|
|
232
|
+
CREATE TABLE IF NOT EXISTS tasks (
|
|
233
|
+
milestone_id TEXT NOT NULL,
|
|
234
|
+
slice_id TEXT NOT NULL,
|
|
235
|
+
id TEXT NOT NULL,
|
|
236
|
+
title TEXT NOT NULL DEFAULT '',
|
|
237
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
238
|
+
one_liner TEXT NOT NULL DEFAULT '',
|
|
239
|
+
narrative TEXT NOT NULL DEFAULT '',
|
|
240
|
+
verification_result TEXT NOT NULL DEFAULT '',
|
|
241
|
+
duration TEXT NOT NULL DEFAULT '',
|
|
242
|
+
completed_at TEXT DEFAULT NULL,
|
|
243
|
+
blocker_discovered INTEGER DEFAULT 0,
|
|
244
|
+
deviations TEXT NOT NULL DEFAULT '',
|
|
245
|
+
known_issues TEXT NOT NULL DEFAULT '',
|
|
246
|
+
key_files TEXT NOT NULL DEFAULT '[]',
|
|
247
|
+
key_decisions TEXT NOT NULL DEFAULT '[]',
|
|
248
|
+
full_summary_md TEXT NOT NULL DEFAULT '',
|
|
249
|
+
description TEXT NOT NULL DEFAULT '',
|
|
250
|
+
estimate TEXT NOT NULL DEFAULT '',
|
|
251
|
+
files TEXT NOT NULL DEFAULT '[]',
|
|
252
|
+
verify TEXT NOT NULL DEFAULT '',
|
|
253
|
+
inputs TEXT NOT NULL DEFAULT '[]',
|
|
254
|
+
expected_output TEXT NOT NULL DEFAULT '[]',
|
|
255
|
+
observability_impact TEXT NOT NULL DEFAULT '',
|
|
256
|
+
sequence INTEGER DEFAULT 0, -- DEAD CODE: no tool exposes sequence — always 0
|
|
257
|
+
PRIMARY KEY (milestone_id, slice_id, id),
|
|
258
|
+
FOREIGN KEY (milestone_id, slice_id) REFERENCES slices(milestone_id, id)
|
|
259
|
+
)
|
|
260
|
+
`);
|
|
261
|
+
db.exec(`
|
|
262
|
+
CREATE TABLE IF NOT EXISTS verification_evidence (
|
|
263
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
264
|
+
task_id TEXT NOT NULL DEFAULT '',
|
|
265
|
+
slice_id TEXT NOT NULL DEFAULT '',
|
|
266
|
+
milestone_id TEXT NOT NULL DEFAULT '',
|
|
267
|
+
command TEXT NOT NULL DEFAULT '',
|
|
268
|
+
exit_code INTEGER DEFAULT 0,
|
|
269
|
+
verdict TEXT NOT NULL DEFAULT '',
|
|
270
|
+
duration_ms INTEGER DEFAULT 0,
|
|
271
|
+
created_at TEXT NOT NULL DEFAULT '',
|
|
272
|
+
FOREIGN KEY (milestone_id, slice_id, task_id) REFERENCES tasks(milestone_id, slice_id, id)
|
|
273
|
+
)
|
|
274
|
+
`);
|
|
275
|
+
db.exec(`
|
|
276
|
+
CREATE TABLE IF NOT EXISTS replan_history (
|
|
277
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
278
|
+
milestone_id TEXT NOT NULL DEFAULT '',
|
|
279
|
+
slice_id TEXT DEFAULT NULL,
|
|
280
|
+
task_id TEXT DEFAULT NULL,
|
|
281
|
+
summary TEXT NOT NULL DEFAULT '',
|
|
282
|
+
previous_artifact_path TEXT DEFAULT NULL,
|
|
283
|
+
replacement_artifact_path TEXT DEFAULT NULL,
|
|
284
|
+
created_at TEXT NOT NULL DEFAULT '',
|
|
285
|
+
FOREIGN KEY (milestone_id) REFERENCES milestones(id)
|
|
286
|
+
)
|
|
287
|
+
`);
|
|
288
|
+
db.exec(`
|
|
289
|
+
CREATE TABLE IF NOT EXISTS assessments (
|
|
290
|
+
path TEXT PRIMARY KEY,
|
|
291
|
+
milestone_id TEXT NOT NULL DEFAULT '',
|
|
292
|
+
slice_id TEXT DEFAULT NULL,
|
|
293
|
+
task_id TEXT DEFAULT NULL,
|
|
294
|
+
status TEXT NOT NULL DEFAULT '',
|
|
295
|
+
scope TEXT NOT NULL DEFAULT '',
|
|
296
|
+
full_content TEXT NOT NULL DEFAULT '',
|
|
297
|
+
created_at TEXT NOT NULL DEFAULT '',
|
|
298
|
+
FOREIGN KEY (milestone_id) REFERENCES milestones(id)
|
|
299
|
+
)
|
|
197
300
|
`);
|
|
198
301
|
db.exec("CREATE INDEX IF NOT EXISTS idx_memories_active ON memories(superseded_by)");
|
|
199
|
-
|
|
302
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_replan_history_milestone ON replan_history(milestone_id, created_at)");
|
|
200
303
|
db.exec(`CREATE VIEW IF NOT EXISTS active_decisions AS SELECT * FROM decisions WHERE superseded_by IS NULL`);
|
|
201
304
|
db.exec(`CREATE VIEW IF NOT EXISTS active_requirements AS SELECT * FROM requirements WHERE superseded_by IS NULL`);
|
|
202
305
|
db.exec(`CREATE VIEW IF NOT EXISTS active_memories AS SELECT * FROM memories WHERE superseded_by IS NULL`);
|
|
203
|
-
|
|
204
|
-
const existing = db
|
|
205
|
-
.prepare("SELECT count(*) as cnt FROM schema_version")
|
|
206
|
-
.get();
|
|
306
|
+
const existing = db.prepare("SELECT count(*) as cnt FROM schema_version").get();
|
|
207
307
|
if (existing && existing["cnt"] === 0) {
|
|
208
308
|
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
209
309
|
":version": SCHEMA_VERSION,
|
|
@@ -216,13 +316,16 @@ function initSchema(db, fileBacked) {
|
|
|
216
316
|
db.exec("ROLLBACK");
|
|
217
317
|
throw err;
|
|
218
318
|
}
|
|
219
|
-
// Run incremental migrations for existing databases
|
|
220
319
|
migrateSchema(db);
|
|
221
320
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
321
|
+
function columnExists(db, table, column) {
|
|
322
|
+
const rows = db.prepare(`PRAGMA table_info(${table})`).all();
|
|
323
|
+
return rows.some((row) => row["name"] === column);
|
|
324
|
+
}
|
|
325
|
+
function ensureColumn(db, table, column, ddl) {
|
|
326
|
+
if (!columnExists(db, table, column))
|
|
327
|
+
db.exec(ddl);
|
|
328
|
+
}
|
|
226
329
|
function migrateSchema(db) {
|
|
227
330
|
const row = db.prepare("SELECT MAX(version) as v FROM schema_version").get();
|
|
228
331
|
const currentVersion = row ? row["v"] : 0;
|
|
@@ -230,7 +333,6 @@ function migrateSchema(db) {
|
|
|
230
333
|
return;
|
|
231
334
|
db.exec("BEGIN");
|
|
232
335
|
try {
|
|
233
|
-
// v1 → v2: add artifacts table
|
|
234
336
|
if (currentVersion < 2) {
|
|
235
337
|
db.exec(`
|
|
236
338
|
CREATE TABLE IF NOT EXISTS artifacts (
|
|
@@ -243,9 +345,11 @@ function migrateSchema(db) {
|
|
|
243
345
|
imported_at TEXT NOT NULL DEFAULT ''
|
|
244
346
|
)
|
|
245
347
|
`);
|
|
246
|
-
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
348
|
+
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
349
|
+
":version": 2,
|
|
350
|
+
":applied_at": new Date().toISOString(),
|
|
351
|
+
});
|
|
247
352
|
}
|
|
248
|
-
// v2 → v3: add memories + memory_processed_units tables
|
|
249
353
|
if (currentVersion < 3) {
|
|
250
354
|
db.exec(`
|
|
251
355
|
CREATE TABLE IF NOT EXISTS memories (
|
|
@@ -272,16 +376,171 @@ function migrateSchema(db) {
|
|
|
272
376
|
db.exec("CREATE INDEX IF NOT EXISTS idx_memories_active ON memories(superseded_by)");
|
|
273
377
|
db.exec("DROP VIEW IF EXISTS active_memories");
|
|
274
378
|
db.exec("CREATE VIEW active_memories AS SELECT * FROM memories WHERE superseded_by IS NULL");
|
|
275
|
-
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
379
|
+
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
380
|
+
":version": 3,
|
|
381
|
+
":applied_at": new Date().toISOString(),
|
|
382
|
+
});
|
|
276
383
|
}
|
|
277
|
-
// v3 → v4: add made_by column to decisions table
|
|
278
384
|
if (currentVersion < 4) {
|
|
279
|
-
|
|
280
|
-
db.exec(`ALTER TABLE decisions ADD COLUMN made_by TEXT NOT NULL DEFAULT 'agent'`);
|
|
281
|
-
// Recreate views to pick up new columns (SQLite expands SELECT * at view creation time)
|
|
385
|
+
ensureColumn(db, "decisions", "made_by", `ALTER TABLE decisions ADD COLUMN made_by TEXT NOT NULL DEFAULT 'agent'`);
|
|
282
386
|
db.exec("DROP VIEW IF EXISTS active_decisions");
|
|
283
387
|
db.exec("CREATE VIEW active_decisions AS SELECT * FROM decisions WHERE superseded_by IS NULL");
|
|
284
|
-
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
388
|
+
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
389
|
+
":version": 4,
|
|
390
|
+
":applied_at": new Date().toISOString(),
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
if (currentVersion < 5) {
|
|
394
|
+
db.exec(`
|
|
395
|
+
CREATE TABLE IF NOT EXISTS milestones (
|
|
396
|
+
id TEXT PRIMARY KEY,
|
|
397
|
+
title TEXT NOT NULL DEFAULT '',
|
|
398
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
399
|
+
created_at TEXT NOT NULL,
|
|
400
|
+
completed_at TEXT DEFAULT NULL
|
|
401
|
+
)
|
|
402
|
+
`);
|
|
403
|
+
db.exec(`
|
|
404
|
+
CREATE TABLE IF NOT EXISTS slices (
|
|
405
|
+
milestone_id TEXT NOT NULL,
|
|
406
|
+
id TEXT NOT NULL,
|
|
407
|
+
title TEXT NOT NULL DEFAULT '',
|
|
408
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
409
|
+
risk TEXT NOT NULL DEFAULT 'medium',
|
|
410
|
+
created_at TEXT NOT NULL DEFAULT '',
|
|
411
|
+
completed_at TEXT DEFAULT NULL,
|
|
412
|
+
PRIMARY KEY (milestone_id, id),
|
|
413
|
+
FOREIGN KEY (milestone_id) REFERENCES milestones(id)
|
|
414
|
+
)
|
|
415
|
+
`);
|
|
416
|
+
db.exec(`
|
|
417
|
+
CREATE TABLE IF NOT EXISTS tasks (
|
|
418
|
+
milestone_id TEXT NOT NULL,
|
|
419
|
+
slice_id TEXT NOT NULL,
|
|
420
|
+
id TEXT NOT NULL,
|
|
421
|
+
title TEXT NOT NULL DEFAULT '',
|
|
422
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
423
|
+
one_liner TEXT NOT NULL DEFAULT '',
|
|
424
|
+
narrative TEXT NOT NULL DEFAULT '',
|
|
425
|
+
verification_result TEXT NOT NULL DEFAULT '',
|
|
426
|
+
duration TEXT NOT NULL DEFAULT '',
|
|
427
|
+
completed_at TEXT DEFAULT NULL,
|
|
428
|
+
blocker_discovered INTEGER DEFAULT 0,
|
|
429
|
+
deviations TEXT NOT NULL DEFAULT '',
|
|
430
|
+
known_issues TEXT NOT NULL DEFAULT '',
|
|
431
|
+
key_files TEXT NOT NULL DEFAULT '[]',
|
|
432
|
+
key_decisions TEXT NOT NULL DEFAULT '[]',
|
|
433
|
+
full_summary_md TEXT NOT NULL DEFAULT '',
|
|
434
|
+
PRIMARY KEY (milestone_id, slice_id, id),
|
|
435
|
+
FOREIGN KEY (milestone_id, slice_id) REFERENCES slices(milestone_id, id)
|
|
436
|
+
)
|
|
437
|
+
`);
|
|
438
|
+
db.exec(`
|
|
439
|
+
CREATE TABLE IF NOT EXISTS verification_evidence (
|
|
440
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
441
|
+
task_id TEXT NOT NULL DEFAULT '',
|
|
442
|
+
slice_id TEXT NOT NULL DEFAULT '',
|
|
443
|
+
milestone_id TEXT NOT NULL DEFAULT '',
|
|
444
|
+
command TEXT NOT NULL DEFAULT '',
|
|
445
|
+
exit_code INTEGER DEFAULT 0,
|
|
446
|
+
verdict TEXT NOT NULL DEFAULT '',
|
|
447
|
+
duration_ms INTEGER DEFAULT 0,
|
|
448
|
+
created_at TEXT NOT NULL DEFAULT '',
|
|
449
|
+
FOREIGN KEY (milestone_id, slice_id, task_id) REFERENCES tasks(milestone_id, slice_id, id)
|
|
450
|
+
)
|
|
451
|
+
`);
|
|
452
|
+
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
453
|
+
":version": 5,
|
|
454
|
+
":applied_at": new Date().toISOString(),
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
if (currentVersion < 6) {
|
|
458
|
+
ensureColumn(db, "slices", "full_summary_md", `ALTER TABLE slices ADD COLUMN full_summary_md TEXT NOT NULL DEFAULT ''`);
|
|
459
|
+
ensureColumn(db, "slices", "full_uat_md", `ALTER TABLE slices ADD COLUMN full_uat_md TEXT NOT NULL DEFAULT ''`);
|
|
460
|
+
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
461
|
+
":version": 6,
|
|
462
|
+
":applied_at": new Date().toISOString(),
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
if (currentVersion < 7) {
|
|
466
|
+
ensureColumn(db, "slices", "depends", `ALTER TABLE slices ADD COLUMN depends TEXT NOT NULL DEFAULT '[]'`);
|
|
467
|
+
ensureColumn(db, "slices", "demo", `ALTER TABLE slices ADD COLUMN demo TEXT NOT NULL DEFAULT ''`);
|
|
468
|
+
ensureColumn(db, "milestones", "depends_on", `ALTER TABLE milestones ADD COLUMN depends_on TEXT NOT NULL DEFAULT '[]'`);
|
|
469
|
+
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
470
|
+
":version": 7,
|
|
471
|
+
":applied_at": new Date().toISOString(),
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
if (currentVersion < 8) {
|
|
475
|
+
ensureColumn(db, "milestones", "vision", `ALTER TABLE milestones ADD COLUMN vision TEXT NOT NULL DEFAULT ''`);
|
|
476
|
+
ensureColumn(db, "milestones", "success_criteria", `ALTER TABLE milestones ADD COLUMN success_criteria TEXT NOT NULL DEFAULT '[]'`);
|
|
477
|
+
ensureColumn(db, "milestones", "key_risks", `ALTER TABLE milestones ADD COLUMN key_risks TEXT NOT NULL DEFAULT '[]'`);
|
|
478
|
+
ensureColumn(db, "milestones", "proof_strategy", `ALTER TABLE milestones ADD COLUMN proof_strategy TEXT NOT NULL DEFAULT '[]'`);
|
|
479
|
+
ensureColumn(db, "milestones", "verification_contract", `ALTER TABLE milestones ADD COLUMN verification_contract TEXT NOT NULL DEFAULT ''`);
|
|
480
|
+
ensureColumn(db, "milestones", "verification_integration", `ALTER TABLE milestones ADD COLUMN verification_integration TEXT NOT NULL DEFAULT ''`);
|
|
481
|
+
ensureColumn(db, "milestones", "verification_operational", `ALTER TABLE milestones ADD COLUMN verification_operational TEXT NOT NULL DEFAULT ''`);
|
|
482
|
+
ensureColumn(db, "milestones", "verification_uat", `ALTER TABLE milestones ADD COLUMN verification_uat TEXT NOT NULL DEFAULT ''`);
|
|
483
|
+
ensureColumn(db, "milestones", "definition_of_done", `ALTER TABLE milestones ADD COLUMN definition_of_done TEXT NOT NULL DEFAULT '[]'`);
|
|
484
|
+
ensureColumn(db, "milestones", "requirement_coverage", `ALTER TABLE milestones ADD COLUMN requirement_coverage TEXT NOT NULL DEFAULT ''`);
|
|
485
|
+
ensureColumn(db, "milestones", "boundary_map_markdown", `ALTER TABLE milestones ADD COLUMN boundary_map_markdown TEXT NOT NULL DEFAULT ''`);
|
|
486
|
+
ensureColumn(db, "slices", "goal", `ALTER TABLE slices ADD COLUMN goal TEXT NOT NULL DEFAULT ''`);
|
|
487
|
+
ensureColumn(db, "slices", "success_criteria", `ALTER TABLE slices ADD COLUMN success_criteria TEXT NOT NULL DEFAULT ''`);
|
|
488
|
+
ensureColumn(db, "slices", "proof_level", `ALTER TABLE slices ADD COLUMN proof_level TEXT NOT NULL DEFAULT ''`);
|
|
489
|
+
ensureColumn(db, "slices", "integration_closure", `ALTER TABLE slices ADD COLUMN integration_closure TEXT NOT NULL DEFAULT ''`);
|
|
490
|
+
ensureColumn(db, "slices", "observability_impact", `ALTER TABLE slices ADD COLUMN observability_impact TEXT NOT NULL DEFAULT ''`);
|
|
491
|
+
ensureColumn(db, "tasks", "description", `ALTER TABLE tasks ADD COLUMN description TEXT NOT NULL DEFAULT ''`);
|
|
492
|
+
ensureColumn(db, "tasks", "estimate", `ALTER TABLE tasks ADD COLUMN estimate TEXT NOT NULL DEFAULT ''`);
|
|
493
|
+
ensureColumn(db, "tasks", "files", `ALTER TABLE tasks ADD COLUMN files TEXT NOT NULL DEFAULT '[]'`);
|
|
494
|
+
ensureColumn(db, "tasks", "verify", `ALTER TABLE tasks ADD COLUMN verify TEXT NOT NULL DEFAULT ''`);
|
|
495
|
+
ensureColumn(db, "tasks", "inputs", `ALTER TABLE tasks ADD COLUMN inputs TEXT NOT NULL DEFAULT '[]'`);
|
|
496
|
+
ensureColumn(db, "tasks", "expected_output", `ALTER TABLE tasks ADD COLUMN expected_output TEXT NOT NULL DEFAULT '[]'`);
|
|
497
|
+
ensureColumn(db, "tasks", "observability_impact", `ALTER TABLE tasks ADD COLUMN observability_impact TEXT NOT NULL DEFAULT ''`);
|
|
498
|
+
db.exec(`
|
|
499
|
+
CREATE TABLE IF NOT EXISTS replan_history (
|
|
500
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
501
|
+
milestone_id TEXT NOT NULL DEFAULT '',
|
|
502
|
+
slice_id TEXT DEFAULT NULL,
|
|
503
|
+
task_id TEXT DEFAULT NULL,
|
|
504
|
+
summary TEXT NOT NULL DEFAULT '',
|
|
505
|
+
previous_artifact_path TEXT DEFAULT NULL,
|
|
506
|
+
replacement_artifact_path TEXT DEFAULT NULL,
|
|
507
|
+
created_at TEXT NOT NULL DEFAULT '',
|
|
508
|
+
FOREIGN KEY (milestone_id) REFERENCES milestones(id)
|
|
509
|
+
)
|
|
510
|
+
`);
|
|
511
|
+
db.exec(`
|
|
512
|
+
CREATE TABLE IF NOT EXISTS assessments (
|
|
513
|
+
path TEXT PRIMARY KEY,
|
|
514
|
+
milestone_id TEXT NOT NULL DEFAULT '',
|
|
515
|
+
slice_id TEXT DEFAULT NULL,
|
|
516
|
+
task_id TEXT DEFAULT NULL,
|
|
517
|
+
status TEXT NOT NULL DEFAULT '',
|
|
518
|
+
scope TEXT NOT NULL DEFAULT '',
|
|
519
|
+
full_content TEXT NOT NULL DEFAULT '',
|
|
520
|
+
created_at TEXT NOT NULL DEFAULT '',
|
|
521
|
+
FOREIGN KEY (milestone_id) REFERENCES milestones(id)
|
|
522
|
+
)
|
|
523
|
+
`);
|
|
524
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_replan_history_milestone ON replan_history(milestone_id, created_at)");
|
|
525
|
+
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
526
|
+
":version": 8,
|
|
527
|
+
":applied_at": new Date().toISOString(),
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
if (currentVersion < 9) {
|
|
531
|
+
ensureColumn(db, "slices", "sequence", `ALTER TABLE slices ADD COLUMN sequence INTEGER DEFAULT 0`);
|
|
532
|
+
ensureColumn(db, "tasks", "sequence", `ALTER TABLE tasks ADD COLUMN sequence INTEGER DEFAULT 0`);
|
|
533
|
+
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
534
|
+
":version": 9,
|
|
535
|
+
":applied_at": new Date().toISOString(),
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
if (currentVersion < 10) {
|
|
539
|
+
ensureColumn(db, "slices", "replan_triggered_at", `ALTER TABLE slices ADD COLUMN replan_triggered_at TEXT DEFAULT NULL`);
|
|
540
|
+
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
541
|
+
":version": 10,
|
|
542
|
+
":applied_at": new Date().toISOString(),
|
|
543
|
+
});
|
|
285
544
|
}
|
|
286
545
|
db.exec("COMMIT");
|
|
287
546
|
}
|
|
@@ -290,38 +549,22 @@ function migrateSchema(db) {
|
|
|
290
549
|
throw err;
|
|
291
550
|
}
|
|
292
551
|
}
|
|
293
|
-
// ─── Module State ──────────────────────────────────────────────────────────
|
|
294
552
|
let currentDb = null;
|
|
295
553
|
let currentPath = null;
|
|
296
|
-
/** PID that opened the current connection — used for diagnostic logging. */
|
|
297
554
|
let currentPid = 0;
|
|
298
|
-
|
|
299
|
-
/**
|
|
300
|
-
* Returns which SQLite provider is available, or null if none.
|
|
301
|
-
*/
|
|
555
|
+
let _exitHandlerRegistered = false;
|
|
302
556
|
export function getDbProvider() {
|
|
303
557
|
loadProvider();
|
|
304
558
|
return providerName;
|
|
305
559
|
}
|
|
306
|
-
/**
|
|
307
|
-
* Returns true if a database is currently open and usable.
|
|
308
|
-
*/
|
|
309
560
|
export function isDbAvailable() {
|
|
310
561
|
return currentDb !== null;
|
|
311
562
|
}
|
|
312
|
-
/**
|
|
313
|
-
* Opens (or creates) a SQLite database at the given path.
|
|
314
|
-
* Initializes schema if needed. Sets WAL mode for file-backed DBs.
|
|
315
|
-
* Returns true on success, false if no provider is available.
|
|
316
|
-
*/
|
|
317
563
|
export function openDatabase(path) {
|
|
318
|
-
|
|
319
|
-
if (currentDb && currentPath !== path) {
|
|
564
|
+
if (currentDb && currentPath !== path)
|
|
320
565
|
closeDatabase();
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
return true; // already open
|
|
324
|
-
}
|
|
566
|
+
if (currentDb && currentPath === path)
|
|
567
|
+
return true;
|
|
325
568
|
const rawDb = openRawDb(path);
|
|
326
569
|
if (!rawDb)
|
|
327
570
|
return false;
|
|
@@ -334,21 +577,27 @@ export function openDatabase(path) {
|
|
|
334
577
|
try {
|
|
335
578
|
adapter.close();
|
|
336
579
|
}
|
|
337
|
-
catch {
|
|
338
|
-
/* swallow */
|
|
339
|
-
}
|
|
580
|
+
catch { /* swallow */ }
|
|
340
581
|
throw err;
|
|
341
582
|
}
|
|
342
583
|
currentDb = adapter;
|
|
343
584
|
currentPath = path;
|
|
344
585
|
currentPid = process.pid;
|
|
586
|
+
if (!_exitHandlerRegistered) {
|
|
587
|
+
_exitHandlerRegistered = true;
|
|
588
|
+
process.on("exit", () => { try {
|
|
589
|
+
closeDatabase();
|
|
590
|
+
}
|
|
591
|
+
catch { } });
|
|
592
|
+
}
|
|
345
593
|
return true;
|
|
346
594
|
}
|
|
347
|
-
/**
|
|
348
|
-
* Closes the current database connection.
|
|
349
|
-
*/
|
|
350
595
|
export function closeDatabase() {
|
|
351
596
|
if (currentDb) {
|
|
597
|
+
try {
|
|
598
|
+
currentDb.exec('PRAGMA wal_checkpoint(TRUNCATE)');
|
|
599
|
+
}
|
|
600
|
+
catch { /* non-fatal — best effort before close */ }
|
|
352
601
|
try {
|
|
353
602
|
currentDb.close();
|
|
354
603
|
}
|
|
@@ -360,9 +609,6 @@ export function closeDatabase() {
|
|
|
360
609
|
currentPid = 0;
|
|
361
610
|
}
|
|
362
611
|
}
|
|
363
|
-
/**
|
|
364
|
-
* Runs a function inside a transaction. Rolls back on error.
|
|
365
|
-
*/
|
|
366
612
|
export function transaction(fn) {
|
|
367
613
|
if (!currentDb)
|
|
368
614
|
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
@@ -377,17 +623,11 @@ export function transaction(fn) {
|
|
|
377
623
|
throw err;
|
|
378
624
|
}
|
|
379
625
|
}
|
|
380
|
-
// ─── Decision Wrappers ────────────────────────────────────────────────────
|
|
381
|
-
/**
|
|
382
|
-
* Insert a decision. The `seq` field is auto-generated.
|
|
383
|
-
*/
|
|
384
626
|
export function insertDecision(d) {
|
|
385
627
|
if (!currentDb)
|
|
386
628
|
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
387
|
-
currentDb
|
|
388
|
-
|
|
389
|
-
VALUES (:id, :when_context, :scope, :decision, :choice, :rationale, :revisable, :made_by, :superseded_by)`)
|
|
390
|
-
.run({
|
|
629
|
+
currentDb.prepare(`INSERT INTO decisions (id, when_context, scope, decision, choice, rationale, revisable, made_by, superseded_by)
|
|
630
|
+
VALUES (:id, :when_context, :scope, :decision, :choice, :rationale, :revisable, :made_by, :superseded_by)`).run({
|
|
391
631
|
":id": d.id,
|
|
392
632
|
":when_context": d.when_context,
|
|
393
633
|
":scope": d.scope,
|
|
@@ -399,9 +639,6 @@ export function insertDecision(d) {
|
|
|
399
639
|
":superseded_by": d.superseded_by,
|
|
400
640
|
});
|
|
401
641
|
}
|
|
402
|
-
/**
|
|
403
|
-
* Get a decision by its ID (e.g. "D001"). Returns null if not found.
|
|
404
|
-
*/
|
|
405
642
|
export function getDecisionById(id) {
|
|
406
643
|
if (!currentDb)
|
|
407
644
|
return null;
|
|
@@ -421,9 +658,6 @@ export function getDecisionById(id) {
|
|
|
421
658
|
superseded_by: row["superseded_by"] ?? null,
|
|
422
659
|
};
|
|
423
660
|
}
|
|
424
|
-
/**
|
|
425
|
-
* Get all active (non-superseded) decisions.
|
|
426
|
-
*/
|
|
427
661
|
export function getActiveDecisions() {
|
|
428
662
|
if (!currentDb)
|
|
429
663
|
return [];
|
|
@@ -441,17 +675,11 @@ export function getActiveDecisions() {
|
|
|
441
675
|
superseded_by: null,
|
|
442
676
|
}));
|
|
443
677
|
}
|
|
444
|
-
// ─── Requirement Wrappers ─────────────────────────────────────────────────
|
|
445
|
-
/**
|
|
446
|
-
* Insert a requirement.
|
|
447
|
-
*/
|
|
448
678
|
export function insertRequirement(r) {
|
|
449
679
|
if (!currentDb)
|
|
450
680
|
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
451
|
-
currentDb
|
|
452
|
-
|
|
453
|
-
VALUES (:id, :class, :status, :description, :why, :source, :primary_owner, :supporting_slices, :validation, :notes, :full_content, :superseded_by)`)
|
|
454
|
-
.run({
|
|
681
|
+
currentDb.prepare(`INSERT INTO requirements (id, class, status, description, why, source, primary_owner, supporting_slices, validation, notes, full_content, superseded_by)
|
|
682
|
+
VALUES (:id, :class, :status, :description, :why, :source, :primary_owner, :supporting_slices, :validation, :notes, :full_content, :superseded_by)`).run({
|
|
455
683
|
":id": r.id,
|
|
456
684
|
":class": r.class,
|
|
457
685
|
":status": r.status,
|
|
@@ -466,15 +694,10 @@ export function insertRequirement(r) {
|
|
|
466
694
|
":superseded_by": r.superseded_by,
|
|
467
695
|
});
|
|
468
696
|
}
|
|
469
|
-
/**
|
|
470
|
-
* Get a requirement by its ID (e.g. "R001"). Returns null if not found.
|
|
471
|
-
*/
|
|
472
697
|
export function getRequirementById(id) {
|
|
473
698
|
if (!currentDb)
|
|
474
699
|
return null;
|
|
475
|
-
const row = currentDb
|
|
476
|
-
.prepare("SELECT * FROM requirements WHERE id = ?")
|
|
477
|
-
.get(id);
|
|
700
|
+
const row = currentDb.prepare("SELECT * FROM requirements WHERE id = ?").get(id);
|
|
478
701
|
if (!row)
|
|
479
702
|
return null;
|
|
480
703
|
return {
|
|
@@ -492,9 +715,6 @@ export function getRequirementById(id) {
|
|
|
492
715
|
superseded_by: row["superseded_by"] ?? null,
|
|
493
716
|
};
|
|
494
717
|
}
|
|
495
|
-
/**
|
|
496
|
-
* Get all active (non-superseded) requirements.
|
|
497
|
-
*/
|
|
498
718
|
export function getActiveRequirements() {
|
|
499
719
|
if (!currentDb)
|
|
500
720
|
return [];
|
|
@@ -514,45 +734,25 @@ export function getActiveRequirements() {
|
|
|
514
734
|
superseded_by: null,
|
|
515
735
|
}));
|
|
516
736
|
}
|
|
517
|
-
/**
|
|
518
|
-
* Returns the PID of the process that opened the current DB connection.
|
|
519
|
-
* Returns 0 if no connection is open.
|
|
520
|
-
*/
|
|
521
737
|
export function getDbOwnerPid() {
|
|
522
738
|
return currentPid;
|
|
523
739
|
}
|
|
524
|
-
/**
|
|
525
|
-
* Returns the path of the currently open database, or null if none.
|
|
526
|
-
*/
|
|
527
740
|
export function getDbPath() {
|
|
528
741
|
return currentPath;
|
|
529
742
|
}
|
|
530
|
-
// ─── Internal Access (for testing) ─────────────────────────────────────────
|
|
531
|
-
/**
|
|
532
|
-
* Get the raw adapter for direct queries (testing only).
|
|
533
|
-
*/
|
|
534
743
|
export function _getAdapter() {
|
|
535
744
|
return currentDb;
|
|
536
745
|
}
|
|
537
|
-
/**
|
|
538
|
-
* Reset provider state (testing only — allows re-detection).
|
|
539
|
-
*/
|
|
540
746
|
export function _resetProvider() {
|
|
541
747
|
loadAttempted = false;
|
|
542
748
|
providerModule = null;
|
|
543
749
|
providerName = null;
|
|
544
750
|
}
|
|
545
|
-
// ─── Upsert Wrappers (for idempotent import) ─────────────────────────────
|
|
546
|
-
/**
|
|
547
|
-
* Insert or replace a decision. Uses the `id` UNIQUE constraint for idempotency.
|
|
548
|
-
*/
|
|
549
751
|
export function upsertDecision(d) {
|
|
550
752
|
if (!currentDb)
|
|
551
753
|
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
552
|
-
currentDb
|
|
553
|
-
|
|
554
|
-
VALUES (:id, :when_context, :scope, :decision, :choice, :rationale, :revisable, :made_by, :superseded_by)`)
|
|
555
|
-
.run({
|
|
754
|
+
currentDb.prepare(`INSERT OR REPLACE INTO decisions (id, when_context, scope, decision, choice, rationale, revisable, made_by, superseded_by)
|
|
755
|
+
VALUES (:id, :when_context, :scope, :decision, :choice, :rationale, :revisable, :made_by, :superseded_by)`).run({
|
|
556
756
|
":id": d.id,
|
|
557
757
|
":when_context": d.when_context,
|
|
558
758
|
":scope": d.scope,
|
|
@@ -564,16 +764,11 @@ export function upsertDecision(d) {
|
|
|
564
764
|
":superseded_by": d.superseded_by ?? null,
|
|
565
765
|
});
|
|
566
766
|
}
|
|
567
|
-
/**
|
|
568
|
-
* Insert or replace a requirement. Uses the `id` PK for idempotency.
|
|
569
|
-
*/
|
|
570
767
|
export function upsertRequirement(r) {
|
|
571
768
|
if (!currentDb)
|
|
572
769
|
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
573
|
-
currentDb
|
|
574
|
-
|
|
575
|
-
VALUES (:id, :class, :status, :description, :why, :source, :primary_owner, :supporting_slices, :validation, :notes, :full_content, :superseded_by)`)
|
|
576
|
-
.run({
|
|
770
|
+
currentDb.prepare(`INSERT OR REPLACE INTO requirements (id, class, status, description, why, source, primary_owner, supporting_slices, validation, notes, full_content, superseded_by)
|
|
771
|
+
VALUES (:id, :class, :status, :description, :why, :source, :primary_owner, :supporting_slices, :validation, :notes, :full_content, :superseded_by)`).run({
|
|
577
772
|
":id": r.id,
|
|
578
773
|
":class": r.class,
|
|
579
774
|
":status": r.status,
|
|
@@ -588,32 +783,19 @@ export function upsertRequirement(r) {
|
|
|
588
783
|
":superseded_by": r.superseded_by ?? null,
|
|
589
784
|
});
|
|
590
785
|
}
|
|
591
|
-
/**
|
|
592
|
-
* Insert or replace an artifact. Uses the `path` PK for idempotency.
|
|
593
|
-
*/
|
|
594
|
-
/**
|
|
595
|
-
* Delete all rows from the artifacts table.
|
|
596
|
-
* The artifacts table is a read cache — clearing it forces the next
|
|
597
|
-
* deriveState() to fall through to disk reads (native Rust batch parse).
|
|
598
|
-
* Safe to call when no database is open (no-op).
|
|
599
|
-
*/
|
|
600
786
|
export function clearArtifacts() {
|
|
601
787
|
if (!currentDb)
|
|
602
788
|
return;
|
|
603
789
|
try {
|
|
604
790
|
currentDb.exec("DELETE FROM artifacts");
|
|
605
791
|
}
|
|
606
|
-
catch {
|
|
607
|
-
// Clearing a cache should never be fatal
|
|
608
|
-
}
|
|
792
|
+
catch { /* cache clear is best effort */ }
|
|
609
793
|
}
|
|
610
794
|
export function insertArtifact(a) {
|
|
611
795
|
if (!currentDb)
|
|
612
796
|
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
613
|
-
currentDb
|
|
614
|
-
|
|
615
|
-
VALUES (:path, :artifact_type, :milestone_id, :slice_id, :task_id, :full_content, :imported_at)`)
|
|
616
|
-
.run({
|
|
797
|
+
currentDb.prepare(`INSERT OR REPLACE INTO artifacts (path, artifact_type, milestone_id, slice_id, task_id, full_content, imported_at)
|
|
798
|
+
VALUES (:path, :artifact_type, :milestone_id, :slice_id, :task_id, :full_content, :imported_at)`).run({
|
|
617
799
|
":path": a.path,
|
|
618
800
|
":artifact_type": a.artifact_type,
|
|
619
801
|
":milestone_id": a.milestone_id,
|
|
@@ -623,6 +805,403 @@ export function insertArtifact(a) {
|
|
|
623
805
|
":imported_at": new Date().toISOString(),
|
|
624
806
|
});
|
|
625
807
|
}
|
|
808
|
+
export function insertMilestone(m) {
|
|
809
|
+
if (!currentDb)
|
|
810
|
+
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
811
|
+
currentDb.prepare(`INSERT OR IGNORE INTO milestones (
|
|
812
|
+
id, title, status, depends_on, created_at,
|
|
813
|
+
vision, success_criteria, key_risks, proof_strategy,
|
|
814
|
+
verification_contract, verification_integration, verification_operational, verification_uat,
|
|
815
|
+
definition_of_done, requirement_coverage, boundary_map_markdown
|
|
816
|
+
) VALUES (
|
|
817
|
+
:id, :title, :status, :depends_on, :created_at,
|
|
818
|
+
:vision, :success_criteria, :key_risks, :proof_strategy,
|
|
819
|
+
:verification_contract, :verification_integration, :verification_operational, :verification_uat,
|
|
820
|
+
:definition_of_done, :requirement_coverage, :boundary_map_markdown
|
|
821
|
+
)`).run({
|
|
822
|
+
":id": m.id,
|
|
823
|
+
":title": m.title ?? "",
|
|
824
|
+
":status": m.status ?? "active",
|
|
825
|
+
":depends_on": JSON.stringify(m.depends_on ?? []),
|
|
826
|
+
":created_at": new Date().toISOString(),
|
|
827
|
+
":vision": m.planning?.vision ?? "",
|
|
828
|
+
":success_criteria": JSON.stringify(m.planning?.successCriteria ?? []),
|
|
829
|
+
":key_risks": JSON.stringify(m.planning?.keyRisks ?? []),
|
|
830
|
+
":proof_strategy": JSON.stringify(m.planning?.proofStrategy ?? []),
|
|
831
|
+
":verification_contract": m.planning?.verificationContract ?? "",
|
|
832
|
+
":verification_integration": m.planning?.verificationIntegration ?? "",
|
|
833
|
+
":verification_operational": m.planning?.verificationOperational ?? "",
|
|
834
|
+
":verification_uat": m.planning?.verificationUat ?? "",
|
|
835
|
+
":definition_of_done": JSON.stringify(m.planning?.definitionOfDone ?? []),
|
|
836
|
+
":requirement_coverage": m.planning?.requirementCoverage ?? "",
|
|
837
|
+
":boundary_map_markdown": m.planning?.boundaryMapMarkdown ?? "",
|
|
838
|
+
});
|
|
839
|
+
}
|
|
840
|
+
export function upsertMilestonePlanning(milestoneId, planning) {
|
|
841
|
+
if (!currentDb)
|
|
842
|
+
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
843
|
+
currentDb.prepare(`UPDATE milestones SET
|
|
844
|
+
vision = COALESCE(:vision, vision),
|
|
845
|
+
success_criteria = COALESCE(:success_criteria, success_criteria),
|
|
846
|
+
key_risks = COALESCE(:key_risks, key_risks),
|
|
847
|
+
proof_strategy = COALESCE(:proof_strategy, proof_strategy),
|
|
848
|
+
verification_contract = COALESCE(:verification_contract, verification_contract),
|
|
849
|
+
verification_integration = COALESCE(:verification_integration, verification_integration),
|
|
850
|
+
verification_operational = COALESCE(:verification_operational, verification_operational),
|
|
851
|
+
verification_uat = COALESCE(:verification_uat, verification_uat),
|
|
852
|
+
definition_of_done = COALESCE(:definition_of_done, definition_of_done),
|
|
853
|
+
requirement_coverage = COALESCE(:requirement_coverage, requirement_coverage),
|
|
854
|
+
boundary_map_markdown = COALESCE(:boundary_map_markdown, boundary_map_markdown)
|
|
855
|
+
WHERE id = :id`).run({
|
|
856
|
+
":id": milestoneId,
|
|
857
|
+
":vision": planning.vision ?? null,
|
|
858
|
+
":success_criteria": planning.successCriteria ? JSON.stringify(planning.successCriteria) : null,
|
|
859
|
+
":key_risks": planning.keyRisks ? JSON.stringify(planning.keyRisks) : null,
|
|
860
|
+
":proof_strategy": planning.proofStrategy ? JSON.stringify(planning.proofStrategy) : null,
|
|
861
|
+
":verification_contract": planning.verificationContract ?? null,
|
|
862
|
+
":verification_integration": planning.verificationIntegration ?? null,
|
|
863
|
+
":verification_operational": planning.verificationOperational ?? null,
|
|
864
|
+
":verification_uat": planning.verificationUat ?? null,
|
|
865
|
+
":definition_of_done": planning.definitionOfDone ? JSON.stringify(planning.definitionOfDone) : null,
|
|
866
|
+
":requirement_coverage": planning.requirementCoverage ?? null,
|
|
867
|
+
":boundary_map_markdown": planning.boundaryMapMarkdown ?? null,
|
|
868
|
+
});
|
|
869
|
+
}
|
|
870
|
+
export function insertSlice(s) {
|
|
871
|
+
if (!currentDb)
|
|
872
|
+
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
873
|
+
currentDb.prepare(`INSERT OR IGNORE INTO slices (
|
|
874
|
+
milestone_id, id, title, status, risk, depends, demo, created_at,
|
|
875
|
+
goal, success_criteria, proof_level, integration_closure, observability_impact, sequence
|
|
876
|
+
) VALUES (
|
|
877
|
+
:milestone_id, :id, :title, :status, :risk, :depends, :demo, :created_at,
|
|
878
|
+
:goal, :success_criteria, :proof_level, :integration_closure, :observability_impact, :sequence
|
|
879
|
+
)`).run({
|
|
880
|
+
":milestone_id": s.milestoneId,
|
|
881
|
+
":id": s.id,
|
|
882
|
+
":title": s.title ?? "",
|
|
883
|
+
":status": s.status ?? "pending",
|
|
884
|
+
":risk": s.risk ?? "medium",
|
|
885
|
+
":depends": JSON.stringify(s.depends ?? []),
|
|
886
|
+
":demo": s.demo ?? "",
|
|
887
|
+
":created_at": new Date().toISOString(),
|
|
888
|
+
":goal": s.planning?.goal ?? "",
|
|
889
|
+
":success_criteria": s.planning?.successCriteria ?? "",
|
|
890
|
+
":proof_level": s.planning?.proofLevel ?? "",
|
|
891
|
+
":integration_closure": s.planning?.integrationClosure ?? "",
|
|
892
|
+
":observability_impact": s.planning?.observabilityImpact ?? "",
|
|
893
|
+
":sequence": s.sequence ?? 0,
|
|
894
|
+
});
|
|
895
|
+
}
|
|
896
|
+
export function upsertSlicePlanning(milestoneId, sliceId, planning) {
|
|
897
|
+
if (!currentDb)
|
|
898
|
+
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
899
|
+
currentDb.prepare(`UPDATE slices SET
|
|
900
|
+
goal = COALESCE(:goal, goal),
|
|
901
|
+
success_criteria = COALESCE(:success_criteria, success_criteria),
|
|
902
|
+
proof_level = COALESCE(:proof_level, proof_level),
|
|
903
|
+
integration_closure = COALESCE(:integration_closure, integration_closure),
|
|
904
|
+
observability_impact = COALESCE(:observability_impact, observability_impact)
|
|
905
|
+
WHERE milestone_id = :milestone_id AND id = :id`).run({
|
|
906
|
+
":milestone_id": milestoneId,
|
|
907
|
+
":id": sliceId,
|
|
908
|
+
":goal": planning.goal ?? null,
|
|
909
|
+
":success_criteria": planning.successCriteria ?? null,
|
|
910
|
+
":proof_level": planning.proofLevel ?? null,
|
|
911
|
+
":integration_closure": planning.integrationClosure ?? null,
|
|
912
|
+
":observability_impact": planning.observabilityImpact ?? null,
|
|
913
|
+
});
|
|
914
|
+
}
|
|
915
|
+
export function insertTask(t) {
|
|
916
|
+
if (!currentDb)
|
|
917
|
+
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
918
|
+
currentDb.prepare(`INSERT INTO tasks (
|
|
919
|
+
milestone_id, slice_id, id, title, status, one_liner, narrative,
|
|
920
|
+
verification_result, duration, completed_at, blocker_discovered,
|
|
921
|
+
deviations, known_issues, key_files, key_decisions, full_summary_md,
|
|
922
|
+
description, estimate, files, verify, inputs, expected_output, observability_impact, sequence
|
|
923
|
+
) VALUES (
|
|
924
|
+
:milestone_id, :slice_id, :id, :title, :status, :one_liner, :narrative,
|
|
925
|
+
:verification_result, :duration, :completed_at, :blocker_discovered,
|
|
926
|
+
:deviations, :known_issues, :key_files, :key_decisions, :full_summary_md,
|
|
927
|
+
:description, :estimate, :files, :verify, :inputs, :expected_output, :observability_impact, :sequence
|
|
928
|
+
)
|
|
929
|
+
ON CONFLICT(milestone_id, slice_id, id) DO UPDATE SET
|
|
930
|
+
title = CASE WHEN NULLIF(:title, '') IS NOT NULL THEN :title ELSE tasks.title END,
|
|
931
|
+
status = :status,
|
|
932
|
+
one_liner = :one_liner,
|
|
933
|
+
narrative = :narrative,
|
|
934
|
+
verification_result = :verification_result,
|
|
935
|
+
duration = :duration,
|
|
936
|
+
completed_at = :completed_at,
|
|
937
|
+
blocker_discovered = :blocker_discovered,
|
|
938
|
+
deviations = :deviations,
|
|
939
|
+
known_issues = :known_issues,
|
|
940
|
+
key_files = :key_files,
|
|
941
|
+
key_decisions = :key_decisions,
|
|
942
|
+
full_summary_md = :full_summary_md,
|
|
943
|
+
description = CASE WHEN NULLIF(:description, '') IS NOT NULL THEN :description ELSE tasks.description END,
|
|
944
|
+
estimate = CASE WHEN NULLIF(:estimate, '') IS NOT NULL THEN :estimate ELSE tasks.estimate END,
|
|
945
|
+
files = CASE WHEN NULLIF(:files, '[]') IS NOT NULL THEN :files ELSE tasks.files END,
|
|
946
|
+
verify = CASE WHEN NULLIF(:verify, '') IS NOT NULL THEN :verify ELSE tasks.verify END,
|
|
947
|
+
inputs = CASE WHEN NULLIF(:inputs, '[]') IS NOT NULL THEN :inputs ELSE tasks.inputs END,
|
|
948
|
+
expected_output = CASE WHEN NULLIF(:expected_output, '[]') IS NOT NULL THEN :expected_output ELSE tasks.expected_output END,
|
|
949
|
+
observability_impact = CASE WHEN NULLIF(:observability_impact, '') IS NOT NULL THEN :observability_impact ELSE tasks.observability_impact END,
|
|
950
|
+
sequence = :sequence`).run({
|
|
951
|
+
":milestone_id": t.milestoneId,
|
|
952
|
+
":slice_id": t.sliceId,
|
|
953
|
+
":id": t.id,
|
|
954
|
+
":title": t.title ?? "",
|
|
955
|
+
":status": t.status ?? "pending",
|
|
956
|
+
":one_liner": t.oneLiner ?? "",
|
|
957
|
+
":narrative": t.narrative ?? "",
|
|
958
|
+
":verification_result": t.verificationResult ?? "",
|
|
959
|
+
":duration": t.duration ?? "",
|
|
960
|
+
":completed_at": t.status === "done" || t.status === "complete" ? new Date().toISOString() : null,
|
|
961
|
+
":blocker_discovered": t.blockerDiscovered ? 1 : 0,
|
|
962
|
+
":deviations": t.deviations ?? "",
|
|
963
|
+
":known_issues": t.knownIssues ?? "",
|
|
964
|
+
":key_files": JSON.stringify(t.keyFiles ?? []),
|
|
965
|
+
":key_decisions": JSON.stringify(t.keyDecisions ?? []),
|
|
966
|
+
":full_summary_md": t.fullSummaryMd ?? "",
|
|
967
|
+
":description": t.planning?.description ?? "",
|
|
968
|
+
":estimate": t.planning?.estimate ?? "",
|
|
969
|
+
":files": JSON.stringify(t.planning?.files ?? []),
|
|
970
|
+
":verify": t.planning?.verify ?? "",
|
|
971
|
+
":inputs": JSON.stringify(t.planning?.inputs ?? []),
|
|
972
|
+
":expected_output": JSON.stringify(t.planning?.expectedOutput ?? []),
|
|
973
|
+
":observability_impact": t.planning?.observabilityImpact ?? "",
|
|
974
|
+
":sequence": t.sequence ?? 0,
|
|
975
|
+
});
|
|
976
|
+
}
|
|
977
|
+
export function updateTaskStatus(milestoneId, sliceId, taskId, status, completedAt) {
|
|
978
|
+
if (!currentDb)
|
|
979
|
+
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
980
|
+
currentDb.prepare(`UPDATE tasks SET status = :status, completed_at = :completed_at
|
|
981
|
+
WHERE milestone_id = :milestone_id AND slice_id = :slice_id AND id = :id`).run({
|
|
982
|
+
":status": status,
|
|
983
|
+
":completed_at": completedAt ?? null,
|
|
984
|
+
":milestone_id": milestoneId,
|
|
985
|
+
":slice_id": sliceId,
|
|
986
|
+
":id": taskId,
|
|
987
|
+
});
|
|
988
|
+
}
|
|
989
|
+
export function upsertTaskPlanning(milestoneId, sliceId, taskId, planning) {
|
|
990
|
+
if (!currentDb)
|
|
991
|
+
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
992
|
+
currentDb.prepare(`UPDATE tasks SET
|
|
993
|
+
title = COALESCE(:title, title),
|
|
994
|
+
description = COALESCE(:description, description),
|
|
995
|
+
estimate = COALESCE(:estimate, estimate),
|
|
996
|
+
files = COALESCE(:files, files),
|
|
997
|
+
verify = COALESCE(:verify, verify),
|
|
998
|
+
inputs = COALESCE(:inputs, inputs),
|
|
999
|
+
expected_output = COALESCE(:expected_output, expected_output),
|
|
1000
|
+
observability_impact = COALESCE(:observability_impact, observability_impact)
|
|
1001
|
+
WHERE milestone_id = :milestone_id AND slice_id = :slice_id AND id = :id`).run({
|
|
1002
|
+
":milestone_id": milestoneId,
|
|
1003
|
+
":slice_id": sliceId,
|
|
1004
|
+
":id": taskId,
|
|
1005
|
+
":title": planning.title ?? null,
|
|
1006
|
+
":description": planning.description ?? null,
|
|
1007
|
+
":estimate": planning.estimate ?? null,
|
|
1008
|
+
":files": planning.files ? JSON.stringify(planning.files) : null,
|
|
1009
|
+
":verify": planning.verify ?? null,
|
|
1010
|
+
":inputs": planning.inputs ? JSON.stringify(planning.inputs) : null,
|
|
1011
|
+
":expected_output": planning.expectedOutput ? JSON.stringify(planning.expectedOutput) : null,
|
|
1012
|
+
":observability_impact": planning.observabilityImpact ?? null,
|
|
1013
|
+
});
|
|
1014
|
+
}
|
|
1015
|
+
function rowToSlice(row) {
|
|
1016
|
+
return {
|
|
1017
|
+
milestone_id: row["milestone_id"],
|
|
1018
|
+
id: row["id"],
|
|
1019
|
+
title: row["title"],
|
|
1020
|
+
status: row["status"],
|
|
1021
|
+
risk: row["risk"],
|
|
1022
|
+
depends: JSON.parse(row["depends"] || "[]"),
|
|
1023
|
+
demo: row["demo"] ?? "",
|
|
1024
|
+
created_at: row["created_at"],
|
|
1025
|
+
completed_at: row["completed_at"] ?? null,
|
|
1026
|
+
full_summary_md: row["full_summary_md"] ?? "",
|
|
1027
|
+
full_uat_md: row["full_uat_md"] ?? "",
|
|
1028
|
+
goal: row["goal"] ?? "",
|
|
1029
|
+
success_criteria: row["success_criteria"] ?? "",
|
|
1030
|
+
proof_level: row["proof_level"] ?? "",
|
|
1031
|
+
integration_closure: row["integration_closure"] ?? "",
|
|
1032
|
+
observability_impact: row["observability_impact"] ?? "",
|
|
1033
|
+
sequence: row["sequence"] ?? 0,
|
|
1034
|
+
replan_triggered_at: row["replan_triggered_at"] ?? null,
|
|
1035
|
+
};
|
|
1036
|
+
}
|
|
1037
|
+
export function getSlice(milestoneId, sliceId) {
|
|
1038
|
+
if (!currentDb)
|
|
1039
|
+
return null;
|
|
1040
|
+
const row = currentDb.prepare("SELECT * FROM slices WHERE milestone_id = :mid AND id = :sid").get({ ":mid": milestoneId, ":sid": sliceId });
|
|
1041
|
+
if (!row)
|
|
1042
|
+
return null;
|
|
1043
|
+
return rowToSlice(row);
|
|
1044
|
+
}
|
|
1045
|
+
export function updateSliceStatus(milestoneId, sliceId, status, completedAt) {
|
|
1046
|
+
if (!currentDb)
|
|
1047
|
+
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
1048
|
+
currentDb.prepare(`UPDATE slices SET status = :status, completed_at = :completed_at
|
|
1049
|
+
WHERE milestone_id = :milestone_id AND id = :id`).run({
|
|
1050
|
+
":status": status,
|
|
1051
|
+
":completed_at": completedAt ?? null,
|
|
1052
|
+
":milestone_id": milestoneId,
|
|
1053
|
+
":id": sliceId,
|
|
1054
|
+
});
|
|
1055
|
+
}
|
|
1056
|
+
function rowToTask(row) {
|
|
1057
|
+
return {
|
|
1058
|
+
milestone_id: row["milestone_id"],
|
|
1059
|
+
slice_id: row["slice_id"],
|
|
1060
|
+
id: row["id"],
|
|
1061
|
+
title: row["title"],
|
|
1062
|
+
status: row["status"],
|
|
1063
|
+
one_liner: row["one_liner"],
|
|
1064
|
+
narrative: row["narrative"],
|
|
1065
|
+
verification_result: row["verification_result"],
|
|
1066
|
+
duration: row["duration"],
|
|
1067
|
+
completed_at: row["completed_at"] ?? null,
|
|
1068
|
+
blocker_discovered: row["blocker_discovered"] === 1,
|
|
1069
|
+
deviations: row["deviations"],
|
|
1070
|
+
known_issues: row["known_issues"],
|
|
1071
|
+
key_files: JSON.parse(row["key_files"] || "[]"),
|
|
1072
|
+
key_decisions: JSON.parse(row["key_decisions"] || "[]"),
|
|
1073
|
+
full_summary_md: row["full_summary_md"],
|
|
1074
|
+
description: row["description"] ?? "",
|
|
1075
|
+
estimate: row["estimate"] ?? "",
|
|
1076
|
+
files: JSON.parse(row["files"] || "[]"),
|
|
1077
|
+
verify: row["verify"] ?? "",
|
|
1078
|
+
inputs: JSON.parse(row["inputs"] || "[]"),
|
|
1079
|
+
expected_output: JSON.parse(row["expected_output"] || "[]"),
|
|
1080
|
+
observability_impact: row["observability_impact"] ?? "",
|
|
1081
|
+
sequence: row["sequence"] ?? 0,
|
|
1082
|
+
};
|
|
1083
|
+
}
|
|
1084
|
+
export function getTask(milestoneId, sliceId, taskId) {
|
|
1085
|
+
if (!currentDb)
|
|
1086
|
+
return null;
|
|
1087
|
+
const row = currentDb.prepare("SELECT * FROM tasks WHERE milestone_id = :mid AND slice_id = :sid AND id = :tid").get({ ":mid": milestoneId, ":sid": sliceId, ":tid": taskId });
|
|
1088
|
+
if (!row)
|
|
1089
|
+
return null;
|
|
1090
|
+
return rowToTask(row);
|
|
1091
|
+
}
|
|
1092
|
+
export function getSliceTasks(milestoneId, sliceId) {
|
|
1093
|
+
if (!currentDb)
|
|
1094
|
+
return [];
|
|
1095
|
+
const rows = currentDb.prepare("SELECT * FROM tasks WHERE milestone_id = :mid AND slice_id = :sid ORDER BY sequence, id").all({ ":mid": milestoneId, ":sid": sliceId });
|
|
1096
|
+
return rows.map(rowToTask);
|
|
1097
|
+
}
|
|
1098
|
+
export function insertVerificationEvidence(e) {
|
|
1099
|
+
if (!currentDb)
|
|
1100
|
+
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
1101
|
+
currentDb.prepare(`INSERT INTO verification_evidence (task_id, slice_id, milestone_id, command, exit_code, verdict, duration_ms, created_at)
|
|
1102
|
+
VALUES (:task_id, :slice_id, :milestone_id, :command, :exit_code, :verdict, :duration_ms, :created_at)`).run({
|
|
1103
|
+
":task_id": e.taskId,
|
|
1104
|
+
":slice_id": e.sliceId,
|
|
1105
|
+
":milestone_id": e.milestoneId,
|
|
1106
|
+
":command": e.command,
|
|
1107
|
+
":exit_code": e.exitCode,
|
|
1108
|
+
":verdict": e.verdict,
|
|
1109
|
+
":duration_ms": e.durationMs,
|
|
1110
|
+
":created_at": new Date().toISOString(),
|
|
1111
|
+
});
|
|
1112
|
+
}
|
|
1113
|
+
function rowToMilestone(row) {
|
|
1114
|
+
return {
|
|
1115
|
+
id: row["id"],
|
|
1116
|
+
title: row["title"],
|
|
1117
|
+
status: row["status"],
|
|
1118
|
+
depends_on: JSON.parse(row["depends_on"] || "[]"),
|
|
1119
|
+
created_at: row["created_at"],
|
|
1120
|
+
completed_at: row["completed_at"] ?? null,
|
|
1121
|
+
vision: row["vision"] ?? "",
|
|
1122
|
+
success_criteria: JSON.parse(row["success_criteria"] || "[]"),
|
|
1123
|
+
key_risks: JSON.parse(row["key_risks"] || "[]"),
|
|
1124
|
+
proof_strategy: JSON.parse(row["proof_strategy"] || "[]"),
|
|
1125
|
+
verification_contract: row["verification_contract"] ?? "",
|
|
1126
|
+
verification_integration: row["verification_integration"] ?? "",
|
|
1127
|
+
verification_operational: row["verification_operational"] ?? "",
|
|
1128
|
+
verification_uat: row["verification_uat"] ?? "",
|
|
1129
|
+
definition_of_done: JSON.parse(row["definition_of_done"] || "[]"),
|
|
1130
|
+
requirement_coverage: row["requirement_coverage"] ?? "",
|
|
1131
|
+
boundary_map_markdown: row["boundary_map_markdown"] ?? "",
|
|
1132
|
+
};
|
|
1133
|
+
}
|
|
1134
|
+
function rowToArtifact(row) {
|
|
1135
|
+
return {
|
|
1136
|
+
path: row["path"],
|
|
1137
|
+
artifact_type: row["artifact_type"],
|
|
1138
|
+
milestone_id: row["milestone_id"] ?? null,
|
|
1139
|
+
slice_id: row["slice_id"] ?? null,
|
|
1140
|
+
task_id: row["task_id"] ?? null,
|
|
1141
|
+
full_content: row["full_content"],
|
|
1142
|
+
imported_at: row["imported_at"],
|
|
1143
|
+
};
|
|
1144
|
+
}
|
|
1145
|
+
export function getAllMilestones() {
|
|
1146
|
+
if (!currentDb)
|
|
1147
|
+
return [];
|
|
1148
|
+
const rows = currentDb.prepare("SELECT * FROM milestones ORDER BY id").all();
|
|
1149
|
+
return rows.map(rowToMilestone);
|
|
1150
|
+
}
|
|
1151
|
+
export function getMilestone(id) {
|
|
1152
|
+
if (!currentDb)
|
|
1153
|
+
return null;
|
|
1154
|
+
const row = currentDb.prepare("SELECT * FROM milestones WHERE id = :id").get({ ":id": id });
|
|
1155
|
+
if (!row)
|
|
1156
|
+
return null;
|
|
1157
|
+
return rowToMilestone(row);
|
|
1158
|
+
}
|
|
1159
|
+
export function getActiveMilestoneFromDb() {
|
|
1160
|
+
if (!currentDb)
|
|
1161
|
+
return null;
|
|
1162
|
+
const row = currentDb.prepare("SELECT * FROM milestones WHERE status NOT IN ('complete', 'parked') ORDER BY id LIMIT 1").get();
|
|
1163
|
+
if (!row)
|
|
1164
|
+
return null;
|
|
1165
|
+
return rowToMilestone(row);
|
|
1166
|
+
}
|
|
1167
|
+
export function getActiveSliceFromDb(milestoneId) {
|
|
1168
|
+
if (!currentDb)
|
|
1169
|
+
return null;
|
|
1170
|
+
const rows = currentDb.prepare("SELECT * FROM slices WHERE milestone_id = :mid AND status NOT IN ('complete', 'done') ORDER BY sequence, id").all({ ":mid": milestoneId });
|
|
1171
|
+
if (rows.length === 0)
|
|
1172
|
+
return null;
|
|
1173
|
+
const completedRows = currentDb.prepare("SELECT id FROM slices WHERE milestone_id = :mid AND status IN ('complete', 'done')").all({ ":mid": milestoneId });
|
|
1174
|
+
const completedIds = new Set(completedRows.map((r) => r["id"]));
|
|
1175
|
+
for (const row of rows) {
|
|
1176
|
+
const slice = rowToSlice(row);
|
|
1177
|
+
if (slice.depends.length === 0 || slice.depends.every((d) => completedIds.has(d))) {
|
|
1178
|
+
return slice;
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
return null;
|
|
1182
|
+
}
|
|
1183
|
+
export function getActiveTaskFromDb(milestoneId, sliceId) {
|
|
1184
|
+
if (!currentDb)
|
|
1185
|
+
return null;
|
|
1186
|
+
const row = currentDb.prepare("SELECT * FROM tasks WHERE milestone_id = :mid AND slice_id = :sid AND status NOT IN ('complete', 'done') ORDER BY sequence, id LIMIT 1").get({ ":mid": milestoneId, ":sid": sliceId });
|
|
1187
|
+
if (!row)
|
|
1188
|
+
return null;
|
|
1189
|
+
return rowToTask(row);
|
|
1190
|
+
}
|
|
1191
|
+
export function getMilestoneSlices(milestoneId) {
|
|
1192
|
+
if (!currentDb)
|
|
1193
|
+
return [];
|
|
1194
|
+
const rows = currentDb.prepare("SELECT * FROM slices WHERE milestone_id = :mid ORDER BY sequence, id").all({ ":mid": milestoneId });
|
|
1195
|
+
return rows.map(rowToSlice);
|
|
1196
|
+
}
|
|
1197
|
+
export function getArtifact(path) {
|
|
1198
|
+
if (!currentDb)
|
|
1199
|
+
return null;
|
|
1200
|
+
const row = currentDb.prepare("SELECT * FROM artifacts WHERE path = :path").get({ ":path": path });
|
|
1201
|
+
if (!row)
|
|
1202
|
+
return null;
|
|
1203
|
+
return rowToArtifact(row);
|
|
1204
|
+
}
|
|
626
1205
|
// ─── Worktree DB Helpers ──────────────────────────────────────────────────
|
|
627
1206
|
export function copyWorktreeDb(srcDbPath, destDbPath) {
|
|
628
1207
|
try {
|
|
@@ -639,22 +1218,17 @@ export function copyWorktreeDb(srcDbPath, destDbPath) {
|
|
|
639
1218
|
}
|
|
640
1219
|
}
|
|
641
1220
|
export function reconcileWorktreeDb(mainDbPath, worktreeDbPath) {
|
|
642
|
-
const zero = {
|
|
643
|
-
decisions: 0,
|
|
644
|
-
requirements: 0,
|
|
645
|
-
artifacts: 0,
|
|
646
|
-
conflicts: [],
|
|
647
|
-
};
|
|
1221
|
+
const zero = { decisions: 0, requirements: 0, artifacts: 0, conflicts: [] };
|
|
648
1222
|
if (!existsSync(worktreeDbPath))
|
|
649
1223
|
return zero;
|
|
650
1224
|
if (worktreeDbPath.includes("'")) {
|
|
651
|
-
process.stderr.write(
|
|
1225
|
+
process.stderr.write("gsd-db: worktree DB reconciliation failed: path contains unsafe characters\n");
|
|
652
1226
|
return zero;
|
|
653
1227
|
}
|
|
654
1228
|
if (!currentDb) {
|
|
655
1229
|
const opened = openDatabase(mainDbPath);
|
|
656
1230
|
if (!opened) {
|
|
657
|
-
process.stderr.write(
|
|
1231
|
+
process.stderr.write("gsd-db: worktree DB reconciliation failed: cannot open main DB\n");
|
|
658
1232
|
return zero;
|
|
659
1233
|
}
|
|
660
1234
|
}
|
|
@@ -663,75 +1237,49 @@ export function reconcileWorktreeDb(mainDbPath, worktreeDbPath) {
|
|
|
663
1237
|
try {
|
|
664
1238
|
adapter.exec(`ATTACH DATABASE '${worktreeDbPath}' AS wt`);
|
|
665
1239
|
try {
|
|
666
|
-
// Check if attached wt database has the made_by column (legacy v3 worktrees won't)
|
|
667
1240
|
const wtInfo = adapter.prepare("PRAGMA wt.table_info('decisions')").all();
|
|
668
1241
|
const hasMadeBy = wtInfo.some((col) => col["name"] === "made_by");
|
|
669
|
-
const decConf = adapter
|
|
670
|
-
.prepare(`SELECT m.id FROM decisions m INNER JOIN wt.decisions w ON m.id = w.id WHERE m.decision != w.decision OR m.choice != w.choice OR m.rationale != w.rationale OR ${hasMadeBy ? "m.made_by != w.made_by" : "'agent' != 'agent'"} OR m.superseded_by IS NOT w.superseded_by`)
|
|
671
|
-
.all();
|
|
1242
|
+
const decConf = adapter.prepare(`SELECT m.id FROM decisions m INNER JOIN wt.decisions w ON m.id = w.id WHERE m.decision != w.decision OR m.choice != w.choice OR m.rationale != w.rationale OR ${hasMadeBy ? "m.made_by != w.made_by" : "'agent' != 'agent'"} OR m.superseded_by IS NOT w.superseded_by`).all();
|
|
672
1243
|
for (const row of decConf)
|
|
673
1244
|
conflicts.push(`decision ${row["id"]}: modified in both`);
|
|
674
|
-
const reqConf = adapter
|
|
675
|
-
.prepare(`SELECT m.id FROM requirements m INNER JOIN wt.requirements w ON m.id = w.id WHERE m.description != w.description OR m.status != w.status OR m.notes != w.notes OR m.superseded_by IS NOT w.superseded_by`)
|
|
676
|
-
.all();
|
|
1245
|
+
const reqConf = adapter.prepare(`SELECT m.id FROM requirements m INNER JOIN wt.requirements w ON m.id = w.id WHERE m.description != w.description OR m.status != w.status OR m.notes != w.notes OR m.superseded_by IS NOT w.superseded_by`).all();
|
|
677
1246
|
for (const row of reqConf)
|
|
678
1247
|
conflicts.push(`requirement ${row["id"]}: modified in both`);
|
|
679
1248
|
const merged = { decisions: 0, requirements: 0, artifacts: 0 };
|
|
680
1249
|
adapter.exec("BEGIN");
|
|
681
1250
|
try {
|
|
682
|
-
const dR = adapter
|
|
683
|
-
.prepare(`
|
|
1251
|
+
const dR = adapter.prepare(`
|
|
684
1252
|
INSERT OR REPLACE INTO decisions (
|
|
685
1253
|
id, when_context, scope, decision, choice, rationale, revisable, made_by, superseded_by
|
|
686
1254
|
)
|
|
687
|
-
SELECT
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
.run();
|
|
692
|
-
merged.decisions =
|
|
693
|
-
typeof dR === "object" && dR !== null
|
|
694
|
-
? (dR.changes ?? 0)
|
|
695
|
-
: 0;
|
|
696
|
-
const rR = adapter
|
|
697
|
-
.prepare(`
|
|
1255
|
+
SELECT id, when_context, scope, decision, choice, rationale, revisable, ${hasMadeBy ? "made_by" : "'agent'"}, superseded_by FROM wt.decisions
|
|
1256
|
+
`).run();
|
|
1257
|
+
merged.decisions = typeof dR === "object" && dR !== null ? (dR.changes ?? 0) : 0;
|
|
1258
|
+
const rR = adapter.prepare(`
|
|
698
1259
|
INSERT OR REPLACE INTO requirements (
|
|
699
1260
|
id, class, status, description, why, source, primary_owner,
|
|
700
1261
|
supporting_slices, validation, notes, full_content, superseded_by
|
|
701
1262
|
)
|
|
702
|
-
SELECT
|
|
703
|
-
|
|
704
|
-
supporting_slices, validation, notes, full_content, superseded_by
|
|
1263
|
+
SELECT id, class, status, description, why, source, primary_owner,
|
|
1264
|
+
supporting_slices, validation, notes, full_content, superseded_by
|
|
705
1265
|
FROM wt.requirements
|
|
706
|
-
`)
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
typeof rR === "object" && rR !== null
|
|
710
|
-
? (rR.changes ?? 0)
|
|
711
|
-
: 0;
|
|
712
|
-
const aR = adapter
|
|
713
|
-
.prepare(`
|
|
1266
|
+
`).run();
|
|
1267
|
+
merged.requirements = typeof rR === "object" && rR !== null ? (rR.changes ?? 0) : 0;
|
|
1268
|
+
const aR = adapter.prepare(`
|
|
714
1269
|
INSERT OR REPLACE INTO artifacts (
|
|
715
1270
|
path, artifact_type, milestone_id, slice_id, task_id, full_content, imported_at
|
|
716
1271
|
)
|
|
717
|
-
SELECT
|
|
718
|
-
path, artifact_type, milestone_id, slice_id, task_id, full_content, imported_at
|
|
1272
|
+
SELECT path, artifact_type, milestone_id, slice_id, task_id, full_content, imported_at
|
|
719
1273
|
FROM wt.artifacts
|
|
720
|
-
`)
|
|
721
|
-
|
|
722
|
-
merged.artifacts =
|
|
723
|
-
typeof aR === "object" && aR !== null
|
|
724
|
-
? (aR.changes ?? 0)
|
|
725
|
-
: 0;
|
|
1274
|
+
`).run();
|
|
1275
|
+
merged.artifacts = typeof aR === "object" && aR !== null ? (aR.changes ?? 0) : 0;
|
|
726
1276
|
adapter.exec("COMMIT");
|
|
727
1277
|
}
|
|
728
1278
|
catch (txErr) {
|
|
729
1279
|
try {
|
|
730
1280
|
adapter.exec("ROLLBACK");
|
|
731
1281
|
}
|
|
732
|
-
catch {
|
|
733
|
-
/* best-effort */
|
|
734
|
-
}
|
|
1282
|
+
catch { /* best effort */ }
|
|
735
1283
|
throw txErr;
|
|
736
1284
|
}
|
|
737
1285
|
return { ...merged, conflicts };
|
|
@@ -740,9 +1288,7 @@ export function reconcileWorktreeDb(mainDbPath, worktreeDbPath) {
|
|
|
740
1288
|
try {
|
|
741
1289
|
adapter.exec("DETACH DATABASE wt");
|
|
742
1290
|
}
|
|
743
|
-
catch {
|
|
744
|
-
/* best-effort */
|
|
745
|
-
}
|
|
1291
|
+
catch { /* best effort */ }
|
|
746
1292
|
}
|
|
747
1293
|
}
|
|
748
1294
|
catch (err) {
|
|
@@ -750,3 +1296,79 @@ export function reconcileWorktreeDb(mainDbPath, worktreeDbPath) {
|
|
|
750
1296
|
return { ...zero, conflicts };
|
|
751
1297
|
}
|
|
752
1298
|
}
|
|
1299
|
+
// ─── Replan & Assessment Helpers ──────────────────────────────────────────
|
|
1300
|
+
export function insertReplanHistory(entry) {
|
|
1301
|
+
if (!currentDb)
|
|
1302
|
+
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
1303
|
+
currentDb.prepare(`INSERT INTO replan_history (milestone_id, slice_id, task_id, summary, previous_artifact_path, replacement_artifact_path, created_at)
|
|
1304
|
+
VALUES (:milestone_id, :slice_id, :task_id, :summary, :previous_artifact_path, :replacement_artifact_path, :created_at)`).run({
|
|
1305
|
+
":milestone_id": entry.milestoneId,
|
|
1306
|
+
":slice_id": entry.sliceId ?? null,
|
|
1307
|
+
":task_id": entry.taskId ?? null,
|
|
1308
|
+
":summary": entry.summary,
|
|
1309
|
+
":previous_artifact_path": entry.previousArtifactPath ?? null,
|
|
1310
|
+
":replacement_artifact_path": entry.replacementArtifactPath ?? null,
|
|
1311
|
+
":created_at": new Date().toISOString(),
|
|
1312
|
+
});
|
|
1313
|
+
}
|
|
1314
|
+
export function insertAssessment(entry) {
|
|
1315
|
+
if (!currentDb)
|
|
1316
|
+
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
1317
|
+
currentDb.prepare(`INSERT OR REPLACE INTO assessments (path, milestone_id, slice_id, task_id, status, scope, full_content, created_at)
|
|
1318
|
+
VALUES (:path, :milestone_id, :slice_id, :task_id, :status, :scope, :full_content, :created_at)`).run({
|
|
1319
|
+
":path": entry.path,
|
|
1320
|
+
":milestone_id": entry.milestoneId,
|
|
1321
|
+
":slice_id": entry.sliceId ?? null,
|
|
1322
|
+
":task_id": entry.taskId ?? null,
|
|
1323
|
+
":status": entry.status,
|
|
1324
|
+
":scope": entry.scope,
|
|
1325
|
+
":full_content": entry.fullContent,
|
|
1326
|
+
":created_at": new Date().toISOString(),
|
|
1327
|
+
});
|
|
1328
|
+
}
|
|
1329
|
+
export function deleteTask(milestoneId, sliceId, taskId) {
|
|
1330
|
+
if (!currentDb)
|
|
1331
|
+
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
1332
|
+
// Must delete verification_evidence first (FK constraint)
|
|
1333
|
+
currentDb.prepare(`DELETE FROM verification_evidence WHERE milestone_id = :mid AND slice_id = :sid AND task_id = :tid`).run({ ":mid": milestoneId, ":sid": sliceId, ":tid": taskId });
|
|
1334
|
+
currentDb.prepare(`DELETE FROM tasks WHERE milestone_id = :mid AND slice_id = :sid AND id = :tid`).run({ ":mid": milestoneId, ":sid": sliceId, ":tid": taskId });
|
|
1335
|
+
}
|
|
1336
|
+
export function deleteSlice(milestoneId, sliceId) {
|
|
1337
|
+
if (!currentDb)
|
|
1338
|
+
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
1339
|
+
// Cascade-style manual deletion: evidence → tasks → slice
|
|
1340
|
+
currentDb.prepare(`DELETE FROM verification_evidence WHERE milestone_id = :mid AND slice_id = :sid`).run({ ":mid": milestoneId, ":sid": sliceId });
|
|
1341
|
+
currentDb.prepare(`DELETE FROM tasks WHERE milestone_id = :mid AND slice_id = :sid`).run({ ":mid": milestoneId, ":sid": sliceId });
|
|
1342
|
+
currentDb.prepare(`DELETE FROM slices WHERE milestone_id = :mid AND id = :sid`).run({ ":mid": milestoneId, ":sid": sliceId });
|
|
1343
|
+
}
|
|
1344
|
+
export function updateSliceFields(milestoneId, sliceId, fields) {
|
|
1345
|
+
if (!currentDb)
|
|
1346
|
+
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
1347
|
+
currentDb.prepare(`UPDATE slices SET
|
|
1348
|
+
title = COALESCE(:title, title),
|
|
1349
|
+
risk = COALESCE(:risk, risk),
|
|
1350
|
+
depends = COALESCE(:depends, depends),
|
|
1351
|
+
demo = COALESCE(:demo, demo)
|
|
1352
|
+
WHERE milestone_id = :milestone_id AND id = :id`).run({
|
|
1353
|
+
":milestone_id": milestoneId,
|
|
1354
|
+
":id": sliceId,
|
|
1355
|
+
":title": fields.title ?? null,
|
|
1356
|
+
":risk": fields.risk ?? null,
|
|
1357
|
+
":depends": fields.depends ? JSON.stringify(fields.depends) : null,
|
|
1358
|
+
":demo": fields.demo ?? null,
|
|
1359
|
+
});
|
|
1360
|
+
}
|
|
1361
|
+
export function getReplanHistory(milestoneId, sliceId) {
|
|
1362
|
+
if (!currentDb)
|
|
1363
|
+
return [];
|
|
1364
|
+
if (sliceId) {
|
|
1365
|
+
return currentDb.prepare(`SELECT * FROM replan_history WHERE milestone_id = :mid AND slice_id = :sid ORDER BY created_at DESC`).all({ ":mid": milestoneId, ":sid": sliceId });
|
|
1366
|
+
}
|
|
1367
|
+
return currentDb.prepare(`SELECT * FROM replan_history WHERE milestone_id = :mid ORDER BY created_at DESC`).all({ ":mid": milestoneId });
|
|
1368
|
+
}
|
|
1369
|
+
export function getAssessment(path) {
|
|
1370
|
+
if (!currentDb)
|
|
1371
|
+
return null;
|
|
1372
|
+
const row = currentDb.prepare(`SELECT * FROM assessments WHERE path = :path`).get({ ":path": path });
|
|
1373
|
+
return row ?? null;
|
|
1374
|
+
}
|