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.
Files changed (693) hide show
  1. package/README.md +30 -12
  2. package/dist/cli.js +13 -1
  3. package/dist/help-text.js +24 -0
  4. package/dist/resources/extensions/bg-shell/overlay.js +3 -0
  5. package/dist/resources/extensions/github-sync/sync.js +2 -1
  6. package/dist/resources/extensions/gsd/auto/loop.js +0 -2
  7. package/dist/resources/extensions/gsd/auto/phases.js +7 -12
  8. package/dist/resources/extensions/gsd/auto-dashboard.js +19 -18
  9. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +34 -19
  10. package/dist/resources/extensions/gsd/auto-dispatch.js +36 -21
  11. package/dist/resources/extensions/gsd/auto-post-unit.js +128 -14
  12. package/dist/resources/extensions/gsd/auto-prompts.js +202 -92
  13. package/dist/resources/extensions/gsd/auto-recovery.js +83 -135
  14. package/dist/resources/extensions/gsd/auto-start.js +10 -0
  15. package/dist/resources/extensions/gsd/auto-supervisor.js +14 -0
  16. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +4 -7
  17. package/dist/resources/extensions/gsd/auto-verification.js +5 -10
  18. package/dist/resources/extensions/gsd/auto-worktree.js +123 -30
  19. package/dist/resources/extensions/gsd/auto.js +1 -4
  20. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +611 -0
  21. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +28 -3
  22. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +7 -0
  23. package/dist/resources/extensions/gsd/commands/catalog.js +3 -1
  24. package/dist/resources/extensions/gsd/commands/handlers/ops.js +15 -1
  25. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +5 -0
  26. package/dist/resources/extensions/gsd/commands-handlers.js +1 -1
  27. package/dist/resources/extensions/gsd/commands-maintenance.js +78 -3
  28. package/dist/resources/extensions/gsd/dashboard-overlay.js +32 -31
  29. package/dist/resources/extensions/gsd/db-writer.js +95 -4
  30. package/dist/resources/extensions/gsd/dispatch-guard.js +35 -30
  31. package/dist/resources/extensions/gsd/doctor-checks.js +28 -11
  32. package/dist/resources/extensions/gsd/doctor-environment.js +28 -0
  33. package/dist/resources/extensions/gsd/doctor-types.js +0 -15
  34. package/dist/resources/extensions/gsd/doctor.js +46 -282
  35. package/dist/resources/extensions/gsd/file-watcher.js +5 -1
  36. package/dist/resources/extensions/gsd/files.js +14 -198
  37. package/dist/resources/extensions/gsd/git-service.js +4 -0
  38. package/dist/resources/extensions/gsd/gitignore.js +4 -0
  39. package/dist/resources/extensions/gsd/gsd-db.js +819 -197
  40. package/dist/resources/extensions/gsd/guided-flow.js +18 -8
  41. package/dist/resources/extensions/gsd/markdown-renderer.js +862 -0
  42. package/dist/resources/extensions/gsd/md-importer.js +182 -4
  43. package/dist/resources/extensions/gsd/native-git-bridge.js +10 -1
  44. package/dist/resources/extensions/gsd/parallel-eligibility.js +14 -19
  45. package/dist/resources/extensions/gsd/parallel-orchestrator.js +38 -0
  46. package/dist/resources/extensions/gsd/parsers-legacy.js +239 -0
  47. package/dist/resources/extensions/gsd/preferences-types.js +1 -0
  48. package/dist/resources/extensions/gsd/preferences-validation.js +9 -0
  49. package/dist/resources/extensions/gsd/preferences.js +1 -0
  50. package/dist/resources/extensions/gsd/prompts/complete-slice.md +22 -9
  51. package/dist/resources/extensions/gsd/prompts/discuss.md +2 -2
  52. package/dist/resources/extensions/gsd/prompts/execute-task.md +15 -5
  53. package/dist/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
  54. package/dist/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
  55. package/dist/resources/extensions/gsd/prompts/guided-plan-milestone.md +1 -1
  56. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +6 -10
  57. package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -7
  58. package/dist/resources/extensions/gsd/prompts/reactive-execute.md +3 -3
  59. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -7
  60. package/dist/resources/extensions/gsd/prompts/replan-slice.md +6 -6
  61. package/dist/resources/extensions/gsd/reactive-graph.js +33 -3
  62. package/dist/resources/extensions/gsd/skill-health.js +3 -1
  63. package/dist/resources/extensions/gsd/state.js +484 -30
  64. package/dist/resources/extensions/gsd/tools/complete-milestone.js +128 -0
  65. package/dist/resources/extensions/gsd/tools/complete-slice.js +244 -0
  66. package/dist/resources/extensions/gsd/tools/complete-task.js +204 -0
  67. package/dist/resources/extensions/gsd/tools/plan-milestone.js +205 -0
  68. package/dist/resources/extensions/gsd/tools/plan-slice.js +155 -0
  69. package/dist/resources/extensions/gsd/tools/plan-task.js +94 -0
  70. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +152 -0
  71. package/dist/resources/extensions/gsd/tools/replan-slice.js +146 -0
  72. package/dist/resources/extensions/gsd/triage-resolution.js +17 -1
  73. package/dist/resources/extensions/gsd/undo.js +197 -3
  74. package/dist/resources/extensions/gsd/visualizer-data.js +53 -16
  75. package/dist/resources/extensions/gsd/workspace-index.js +63 -39
  76. package/dist/web/standalone/.next/BUILD_ID +1 -1
  77. package/dist/web/standalone/.next/app-path-routes-manifest.json +18 -17
  78. package/dist/web/standalone/.next/build-manifest.json +4 -4
  79. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  80. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  81. package/dist/web/standalone/.next/required-server-files.json +4 -4
  82. package/dist/web/standalone/.next/routes-manifest.json +6 -0
  83. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  84. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  85. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  86. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  87. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  88. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  89. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  90. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  91. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  94. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  95. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  96. package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -4
  97. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
  98. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
  100. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  103. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  104. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  105. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  106. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  107. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  109. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  110. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
  148. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  154. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -0
  166. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -0
  167. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -0
  168. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  171. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  173. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  175. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  184. package/dist/web/standalone/.next/server/app/index.html +1 -1
  185. package/dist/web/standalone/.next/server/app/index.rsc +5 -5
  186. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  187. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +5 -5
  188. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  189. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -4
  190. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  191. package/dist/web/standalone/.next/server/app/page.js +2 -2
  192. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/app-paths-manifest.json +18 -17
  194. package/dist/web/standalone/.next/server/chunks/229.js +3 -3
  195. package/dist/web/standalone/.next/server/chunks/471.js +3 -3
  196. package/dist/web/standalone/.next/server/functions-config-manifest.json +1 -0
  197. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  198. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  199. package/dist/web/standalone/.next/server/middleware.js +2 -2
  200. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  201. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  202. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  203. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  204. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  205. package/dist/web/standalone/.next/static/alS4hoANx0TK4UVZY27da/_buildManifest.js +1 -0
  206. package/dist/web/standalone/.next/static/chunks/{4024.c195dc1fdd2adbea.js → 4024.0de81b543b28b9fe.js} +2 -2
  207. package/dist/web/standalone/.next/static/chunks/app/_global-error/{page-d07a2c023f1aef1e.js → page-d83ba70a25a85472.js} +1 -1
  208. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-f2a7482d42a5614b.js +1 -0
  209. package/dist/web/standalone/.next/static/chunks/app/api/boot/{route-d07a2c023f1aef1e.js → route-d83ba70a25a85472.js} +1 -1
  210. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/input/{route-d07a2c023f1aef1e.js → route-d83ba70a25a85472.js} +1 -1
  211. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/resize/{route-d07a2c023f1aef1e.js → route-d83ba70a25a85472.js} +1 -1
  212. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-d83ba70a25a85472.js +1 -0
  213. package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-d83ba70a25a85472.js +1 -0
  214. package/dist/web/standalone/.next/static/chunks/app/api/captures/route-d83ba70a25a85472.js +1 -0
  215. package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-d83ba70a25a85472.js +1 -0
  216. package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-d83ba70a25a85472.js +1 -0
  217. package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-d83ba70a25a85472.js +1 -0
  218. package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-d83ba70a25a85472.js +1 -0
  219. package/dist/web/standalone/.next/static/chunks/app/api/files/route-d83ba70a25a85472.js +1 -0
  220. package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-d83ba70a25a85472.js +1 -0
  221. package/dist/web/standalone/.next/static/chunks/app/api/git/route-d83ba70a25a85472.js +1 -0
  222. package/dist/web/standalone/.next/static/chunks/app/api/history/route-d83ba70a25a85472.js +1 -0
  223. package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-d83ba70a25a85472.js +1 -0
  224. package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-d83ba70a25a85472.js +1 -0
  225. package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-d83ba70a25a85472.js +1 -0
  226. package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-d83ba70a25a85472.js +1 -0
  227. package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-d83ba70a25a85472.js +1 -0
  228. package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-d83ba70a25a85472.js +1 -0
  229. package/dist/web/standalone/.next/static/chunks/app/api/projects/route-d83ba70a25a85472.js +1 -0
  230. package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-d83ba70a25a85472.js +1 -0
  231. package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-d83ba70a25a85472.js +1 -0
  232. package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-d83ba70a25a85472.js +1 -0
  233. package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-d83ba70a25a85472.js +1 -0
  234. package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-d83ba70a25a85472.js +1 -0
  235. package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-d83ba70a25a85472.js +1 -0
  236. package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-d83ba70a25a85472.js +1 -0
  237. package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-d83ba70a25a85472.js +1 -0
  238. package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-d83ba70a25a85472.js +1 -0
  239. package/dist/web/standalone/.next/static/chunks/app/api/steer/route-d83ba70a25a85472.js +1 -0
  240. package/dist/web/standalone/.next/static/chunks/app/api/switch-root/route-d83ba70a25a85472.js +1 -0
  241. package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-d83ba70a25a85472.js +1 -0
  242. package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-d83ba70a25a85472.js +1 -0
  243. package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-d83ba70a25a85472.js +1 -0
  244. package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-d83ba70a25a85472.js +1 -0
  245. package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-d83ba70a25a85472.js +1 -0
  246. package/dist/web/standalone/.next/static/chunks/app/api/undo/route-d83ba70a25a85472.js +1 -0
  247. package/dist/web/standalone/.next/static/chunks/app/api/update/route-d83ba70a25a85472.js +1 -0
  248. package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-d83ba70a25a85472.js +1 -0
  249. package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +1 -0
  250. package/dist/web/standalone/.next/static/chunks/app/page-b9367c5ae13b99c6.js +1 -0
  251. package/dist/web/standalone/.next/static/chunks/{main-app-2f2ee7b85712c2bd.js → main-app-fdab67f7802d7832.js} +1 -1
  252. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-d83ba70a25a85472.js +1 -0
  253. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-d83ba70a25a85472.js +1 -0
  254. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  255. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-d83ba70a25a85472.js +1 -0
  256. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-d83ba70a25a85472.js +1 -0
  257. package/dist/web/standalone/.next/static/chunks/{webpack-fa307370fcf9fb2c.js → webpack-9014b5adb127a98a.js} +1 -1
  258. package/dist/web/standalone/.next/static/css/8a727f372cf53002.css +1 -0
  259. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  260. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  261. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  262. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  263. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  264. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  265. package/dist/web/standalone/server.js +1 -1
  266. package/package.json +4 -4
  267. package/packages/pi-ai/dist/models.custom.d.ts +173 -0
  268. package/packages/pi-ai/dist/models.custom.d.ts.map +1 -0
  269. package/packages/pi-ai/dist/models.custom.js +170 -0
  270. package/packages/pi-ai/dist/models.custom.js.map +1 -0
  271. package/packages/pi-ai/dist/models.d.ts.map +1 -1
  272. package/packages/pi-ai/dist/models.js +16 -1
  273. package/packages/pi-ai/dist/models.js.map +1 -1
  274. package/packages/pi-ai/dist/models.test.d.ts +2 -0
  275. package/packages/pi-ai/dist/models.test.d.ts.map +1 -0
  276. package/packages/pi-ai/dist/models.test.js +67 -0
  277. package/packages/pi-ai/dist/models.test.js.map +1 -0
  278. package/packages/pi-ai/src/models.custom.ts +172 -0
  279. package/packages/pi-ai/src/models.test.ts +85 -0
  280. package/packages/pi-ai/src/models.ts +17 -1
  281. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +10 -3
  282. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  283. package/packages/pi-coding-agent/dist/core/agent-session.js +21 -34
  284. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  285. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +6 -8
  286. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  287. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.d.ts +2 -2
  288. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  289. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.js.map +1 -1
  290. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +2 -2
  291. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  292. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  293. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +4 -4
  294. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
  295. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +1 -1
  296. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
  297. package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
  298. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +6 -0
  299. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  300. package/packages/pi-coding-agent/dist/core/extensions/loader.js +80 -0
  301. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  302. package/packages/pi-coding-agent/dist/core/extensions/loader.test.js +63 -0
  303. package/packages/pi-coding-agent/dist/core/extensions/loader.test.js.map +1 -1
  304. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +24 -26
  305. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  306. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +37 -0
  307. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  308. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  309. package/packages/pi-coding-agent/dist/core/fallback-resolver.d.ts.map +1 -1
  310. package/packages/pi-coding-agent/dist/core/fallback-resolver.js +2 -3
  311. package/packages/pi-coding-agent/dist/core/fallback-resolver.js.map +1 -1
  312. package/packages/pi-coding-agent/dist/core/fallback-resolver.test.js +12 -2
  313. package/packages/pi-coding-agent/dist/core/fallback-resolver.test.js.map +1 -1
  314. package/packages/pi-coding-agent/dist/core/fs-utils.test.js +29 -48
  315. package/packages/pi-coding-agent/dist/core/fs-utils.test.js.map +1 -1
  316. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts +38 -0
  317. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts.map +1 -0
  318. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js +192 -0
  319. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js.map +1 -0
  320. package/packages/pi-coding-agent/dist/core/lsp/client.d.ts +5 -0
  321. package/packages/pi-coding-agent/dist/core/lsp/client.d.ts.map +1 -1
  322. package/packages/pi-coding-agent/dist/core/lsp/client.js +69 -21
  323. package/packages/pi-coding-agent/dist/core/lsp/client.js.map +1 -1
  324. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.d.ts +2 -0
  325. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.d.ts.map +1 -0
  326. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +255 -0
  327. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -0
  328. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +15 -0
  329. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  330. package/packages/pi-coding-agent/dist/core/model-registry.js +40 -3
  331. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  332. package/packages/pi-coding-agent/dist/core/package-commands.d.ts +25 -0
  333. package/packages/pi-coding-agent/dist/core/package-commands.d.ts.map +1 -0
  334. package/packages/pi-coding-agent/dist/core/package-commands.js +253 -0
  335. package/packages/pi-coding-agent/dist/core/package-commands.js.map +1 -0
  336. package/packages/pi-coding-agent/dist/core/package-commands.test.d.ts +2 -0
  337. package/packages/pi-coding-agent/dist/core/package-commands.test.d.ts.map +1 -0
  338. package/packages/pi-coding-agent/dist/core/package-commands.test.js +225 -0
  339. package/packages/pi-coding-agent/dist/core/package-commands.test.js.map +1 -0
  340. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +34 -44
  341. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -1
  342. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  343. package/packages/pi-coding-agent/dist/core/sdk.js +4 -0
  344. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  345. package/packages/pi-coding-agent/dist/core/session-manager.test.js +30 -34
  346. package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
  347. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js +10 -12
  348. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js.map +1 -1
  349. package/packages/pi-coding-agent/dist/index.d.ts +3 -1
  350. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  351. package/packages/pi-coding-agent/dist/index.js +1 -0
  352. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  353. package/packages/pi-coding-agent/dist/main.d.ts.map +1 -1
  354. package/packages/pi-coding-agent/dist/main.js +11 -199
  355. package/packages/pi-coding-agent/dist/main.js.map +1 -1
  356. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts +6 -0
  357. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  358. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +21 -0
  359. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  360. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts +1 -1
  361. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  362. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +8 -15
  363. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
  364. package/packages/pi-coding-agent/dist/modes/print-mode.d.ts.map +1 -1
  365. package/packages/pi-coding-agent/dist/modes/print-mode.js +45 -34
  366. package/packages/pi-coding-agent/dist/modes/print-mode.js.map +1 -1
  367. package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.d.ts +1 -0
  368. package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  369. package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.js +7 -2
  370. package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.js.map +1 -1
  371. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  372. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js +2 -1
  373. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
  374. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js +43 -47
  375. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js.map +1 -1
  376. package/packages/pi-coding-agent/package.json +1 -1
  377. package/packages/pi-coding-agent/src/core/agent-session.ts +26 -37
  378. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +7 -7
  379. package/packages/pi-coding-agent/src/core/compaction/branch-summarization.ts +2 -2
  380. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +3 -3
  381. package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +4 -4
  382. package/packages/pi-coding-agent/src/core/extensions/index.ts +5 -0
  383. package/packages/pi-coding-agent/src/core/extensions/loader.test.ts +96 -0
  384. package/packages/pi-coding-agent/src/core/extensions/loader.ts +89 -0
  385. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +26 -26
  386. package/packages/pi-coding-agent/src/core/extensions/types.ts +44 -0
  387. package/packages/pi-coding-agent/src/core/fallback-resolver.test.ts +15 -2
  388. package/packages/pi-coding-agent/src/core/fallback-resolver.ts +2 -3
  389. package/packages/pi-coding-agent/src/core/fs-utils.test.ts +31 -43
  390. package/packages/pi-coding-agent/src/core/lifecycle-hooks.ts +274 -0
  391. package/packages/pi-coding-agent/src/core/lsp/client.ts +83 -21
  392. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +288 -0
  393. package/packages/pi-coding-agent/src/core/model-registry.ts +39 -3
  394. package/packages/pi-coding-agent/src/core/package-commands.test.ts +240 -0
  395. package/packages/pi-coding-agent/src/core/package-commands.ts +310 -0
  396. package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +40 -45
  397. package/packages/pi-coding-agent/src/core/sdk.ts +4 -0
  398. package/packages/pi-coding-agent/src/core/session-manager.test.ts +33 -33
  399. package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +17 -17
  400. package/packages/pi-coding-agent/src/index.ts +7 -0
  401. package/packages/pi-coding-agent/src/main.ts +11 -232
  402. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +20 -0
  403. package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +9 -16
  404. package/packages/pi-coding-agent/src/modes/print-mode.ts +42 -32
  405. package/packages/pi-coding-agent/src/modes/rpc/rpc-client.ts +8 -2
  406. package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +2 -1
  407. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +74 -74
  408. package/pkg/dist/modes/interactive/theme/theme.d.ts +1 -1
  409. package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  410. package/pkg/dist/modes/interactive/theme/theme.js +8 -15
  411. package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
  412. package/pkg/package.json +1 -1
  413. package/src/resources/extensions/bg-shell/overlay.ts +4 -0
  414. package/src/resources/extensions/github-sync/sync.ts +2 -1
  415. package/src/resources/extensions/gsd/auto/loop-deps.ts +0 -8
  416. package/src/resources/extensions/gsd/auto/loop.ts +0 -2
  417. package/src/resources/extensions/gsd/auto/phases.ts +7 -20
  418. package/src/resources/extensions/gsd/auto/types.ts +0 -1
  419. package/src/resources/extensions/gsd/auto-dashboard.ts +20 -16
  420. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +34 -19
  421. package/src/resources/extensions/gsd/auto-dispatch.ts +38 -21
  422. package/src/resources/extensions/gsd/auto-post-unit.ts +150 -15
  423. package/src/resources/extensions/gsd/auto-prompts.ts +186 -103
  424. package/src/resources/extensions/gsd/auto-recovery.ts +77 -142
  425. package/src/resources/extensions/gsd/auto-start.ts +14 -0
  426. package/src/resources/extensions/gsd/auto-supervisor.ts +14 -0
  427. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +6 -7
  428. package/src/resources/extensions/gsd/auto-verification.ts +4 -9
  429. package/src/resources/extensions/gsd/auto-worktree.ts +126 -30
  430. package/src/resources/extensions/gsd/auto.ts +0 -9
  431. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +675 -4
  432. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +31 -3
  433. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +7 -0
  434. package/src/resources/extensions/gsd/commands/catalog.ts +3 -1
  435. package/src/resources/extensions/gsd/commands/handlers/ops.ts +15 -1
  436. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +8 -0
  437. package/src/resources/extensions/gsd/commands-handlers.ts +1 -1
  438. package/src/resources/extensions/gsd/commands-maintenance.ts +86 -3
  439. package/src/resources/extensions/gsd/dashboard-overlay.ts +17 -13
  440. package/src/resources/extensions/gsd/db-writer.ts +105 -4
  441. package/src/resources/extensions/gsd/dispatch-guard.ts +32 -30
  442. package/src/resources/extensions/gsd/doctor-checks.ts +25 -11
  443. package/src/resources/extensions/gsd/doctor-environment.ts +31 -0
  444. package/src/resources/extensions/gsd/doctor-types.ts +0 -23
  445. package/src/resources/extensions/gsd/doctor.ts +45 -295
  446. package/src/resources/extensions/gsd/file-watcher.ts +4 -1
  447. package/src/resources/extensions/gsd/files.ts +16 -220
  448. package/src/resources/extensions/gsd/git-service.ts +4 -0
  449. package/src/resources/extensions/gsd/gitignore.ts +4 -0
  450. package/src/resources/extensions/gsd/gsd-db.ts +1157 -370
  451. package/src/resources/extensions/gsd/guided-flow.ts +20 -8
  452. package/src/resources/extensions/gsd/markdown-renderer.ts +1098 -0
  453. package/src/resources/extensions/gsd/md-importer.ts +211 -2
  454. package/src/resources/extensions/gsd/native-git-bridge.ts +12 -1
  455. package/src/resources/extensions/gsd/parallel-eligibility.ts +14 -18
  456. package/src/resources/extensions/gsd/parallel-orchestrator.ts +43 -0
  457. package/src/resources/extensions/gsd/parsers-legacy.ts +271 -0
  458. package/src/resources/extensions/gsd/preferences-types.ts +3 -0
  459. package/src/resources/extensions/gsd/preferences-validation.ts +9 -0
  460. package/src/resources/extensions/gsd/preferences.ts +1 -0
  461. package/src/resources/extensions/gsd/prompts/complete-slice.md +22 -9
  462. package/src/resources/extensions/gsd/prompts/discuss.md +2 -2
  463. package/src/resources/extensions/gsd/prompts/execute-task.md +15 -5
  464. package/src/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
  465. package/src/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
  466. package/src/resources/extensions/gsd/prompts/guided-plan-milestone.md +1 -1
  467. package/src/resources/extensions/gsd/prompts/plan-milestone.md +6 -10
  468. package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -7
  469. package/src/resources/extensions/gsd/prompts/reactive-execute.md +3 -3
  470. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -7
  471. package/src/resources/extensions/gsd/prompts/replan-slice.md +6 -6
  472. package/src/resources/extensions/gsd/reactive-graph.ts +33 -3
  473. package/src/resources/extensions/gsd/skill-health.ts +2 -1
  474. package/src/resources/extensions/gsd/state.ts +547 -29
  475. package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +99 -99
  476. package/src/resources/extensions/gsd/tests/atomic-task-closeout.test.ts +8 -120
  477. package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +14 -16
  478. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +20 -11
  479. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +43 -57
  480. package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +11 -13
  481. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +600 -513
  482. package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +73 -75
  483. package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +34 -56
  484. package/src/resources/extensions/gsd/tests/auto-stash-merge.test.ts +121 -0
  485. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +540 -668
  486. package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +165 -143
  487. package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +29 -52
  488. package/src/resources/extensions/gsd/tests/captures.test.ts +148 -176
  489. package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +32 -33
  490. package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +141 -143
  491. package/src/resources/extensions/gsd/tests/commands-inspect-open-db.test.ts +25 -25
  492. package/src/resources/extensions/gsd/tests/commands-logs.test.ts +81 -81
  493. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +39 -60
  494. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +375 -0
  495. package/src/resources/extensions/gsd/tests/complete-task.test.ts +387 -0
  496. package/src/resources/extensions/gsd/tests/context-store.test.ts +354 -367
  497. package/src/resources/extensions/gsd/tests/continue-here.test.ts +68 -72
  498. package/src/resources/extensions/gsd/tests/cost-projection.test.ts +92 -106
  499. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +27 -35
  500. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +0 -2
  501. package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +220 -237
  502. package/src/resources/extensions/gsd/tests/db-writer.test.ts +390 -420
  503. package/src/resources/extensions/gsd/tests/definition-loader.test.ts +76 -92
  504. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +512 -0
  505. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +644 -84
  506. package/src/resources/extensions/gsd/tests/derive-state-deps.test.ts +78 -101
  507. package/src/resources/extensions/gsd/tests/derive-state.test.ts +192 -227
  508. package/src/resources/extensions/gsd/tests/detection.test.ts +232 -278
  509. package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +30 -34
  510. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +192 -161
  511. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +43 -49
  512. package/src/resources/extensions/gsd/tests/dispatch-uat-last-completed.test.ts +28 -32
  513. package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +30 -90
  514. package/src/resources/extensions/gsd/tests/doctor-delimiter-fix.test.ts +34 -38
  515. package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +57 -80
  516. package/src/resources/extensions/gsd/tests/doctor-environment-worktree.test.ts +164 -0
  517. package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +72 -97
  518. package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +55 -153
  519. package/src/resources/extensions/gsd/tests/doctor-git.test.ts +104 -145
  520. package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +84 -106
  521. package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +53 -97
  522. package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +72 -93
  523. package/src/resources/extensions/gsd/tests/doctor.test.ts +109 -149
  524. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +123 -131
  525. package/src/resources/extensions/gsd/tests/exit-command.test.ts +20 -24
  526. package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +48 -57
  527. package/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts +5 -7
  528. package/src/resources/extensions/gsd/tests/flag-file-db.test.ts +278 -0
  529. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +232 -0
  530. package/src/resources/extensions/gsd/tests/git-locale.test.ts +13 -27
  531. package/src/resources/extensions/gsd/tests/git-service.test.ts +291 -390
  532. package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +31 -39
  533. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +63 -69
  534. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +255 -264
  535. package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +108 -119
  536. package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +440 -0
  537. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +229 -262
  538. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +13 -13
  539. package/src/resources/extensions/gsd/tests/health-widget.test.ts +29 -37
  540. package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +81 -270
  541. package/src/resources/extensions/gsd/tests/init-wizard.test.ts +16 -18
  542. package/src/resources/extensions/gsd/tests/integration-edge.test.ts +41 -46
  543. package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +42 -53
  544. package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +75 -91
  545. package/src/resources/extensions/gsd/tests/integration-proof.test.ts +643 -0
  546. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +0 -3
  547. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +1161 -0
  548. package/src/resources/extensions/gsd/tests/md-importer.test.ts +101 -125
  549. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +45 -54
  550. package/src/resources/extensions/gsd/tests/memory-store.test.ts +81 -94
  551. package/src/resources/extensions/gsd/tests/migrate-command.test.ts +57 -66
  552. package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +429 -0
  553. package/src/resources/extensions/gsd/tests/migrate-parser.test.ts +161 -170
  554. package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +125 -141
  555. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +107 -131
  556. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +89 -97
  557. package/src/resources/extensions/gsd/tests/migrate-writer.test.ts +127 -164
  558. package/src/resources/extensions/gsd/tests/must-have-parser.test.ts +81 -94
  559. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +35 -36
  560. package/src/resources/extensions/gsd/tests/overrides.test.ts +99 -106
  561. package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +40 -47
  562. package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +25 -28
  563. package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +66 -83
  564. package/src/resources/extensions/gsd/tests/park-edge-cases.test.ts +54 -77
  565. package/src/resources/extensions/gsd/tests/park-milestone.test.ts +68 -115
  566. package/src/resources/extensions/gsd/tests/parsers.test.ts +548 -612
  567. package/src/resources/extensions/gsd/tests/paths.test.ts +72 -87
  568. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +176 -113
  569. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +7 -0
  570. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +179 -0
  571. package/src/resources/extensions/gsd/tests/plan-task.test.ts +145 -0
  572. package/src/resources/extensions/gsd/tests/planning-crossval.test.ts +305 -0
  573. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +77 -117
  574. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +139 -0
  575. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +56 -56
  576. package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +93 -119
  577. package/src/resources/extensions/gsd/tests/queue-order.test.ts +70 -82
  578. package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +42 -55
  579. package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +100 -0
  580. package/src/resources/extensions/gsd/tests/quick-branch-lifecycle.test.ts +45 -73
  581. package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +325 -0
  582. package/src/resources/extensions/gsd/tests/reassess-prompt.test.ts +28 -38
  583. package/src/resources/extensions/gsd/tests/replan-handler.test.ts +410 -0
  584. package/src/resources/extensions/gsd/tests/replan-slice.test.ts +73 -80
  585. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +71 -74
  586. package/src/resources/extensions/gsd/tests/requirements.test.ts +70 -75
  587. package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +44 -66
  588. package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +114 -181
  589. package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +1 -1
  590. package/src/resources/extensions/gsd/tests/rogue-file-detection.test.ts +296 -0
  591. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +63 -65
  592. package/src/resources/extensions/gsd/tests/run-uat.test.ts +66 -128
  593. package/src/resources/extensions/gsd/tests/schema-v9-sequence.test.ts +176 -0
  594. package/src/resources/extensions/gsd/tests/session-lock-multipath.test.ts +18 -25
  595. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +37 -44
  596. package/src/resources/extensions/gsd/tests/shared-wal.test.ts +209 -0
  597. package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +63 -0
  598. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +6 -8
  599. package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +22 -28
  600. package/src/resources/extensions/gsd/tests/token-cost-display.test.ts +118 -0
  601. package/src/resources/extensions/gsd/tests/token-savings.test.ts +54 -56
  602. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +23 -25
  603. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +19 -13
  604. package/src/resources/extensions/gsd/tests/undo.test.ts +321 -1
  605. package/src/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +66 -82
  606. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +46 -47
  607. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +1 -1
  608. package/src/resources/extensions/gsd/tests/verification-evidence.test.ts +0 -142
  609. package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -22
  610. package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +84 -86
  611. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +41 -43
  612. package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +94 -96
  613. package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +11 -13
  614. package/src/resources/extensions/gsd/tests/worker-registry.test.ts +27 -29
  615. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +50 -52
  616. package/src/resources/extensions/gsd/tests/worktree-bugfix.test.ts +10 -13
  617. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +14 -18
  618. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +38 -39
  619. package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +17 -21
  620. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +12 -5
  621. package/src/resources/extensions/gsd/tests/worktree-health.test.ts +25 -30
  622. package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +30 -37
  623. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +15 -22
  624. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +59 -66
  625. package/src/resources/extensions/gsd/tests/worktree.test.ts +44 -50
  626. package/src/resources/extensions/gsd/tools/complete-milestone.ts +176 -0
  627. package/src/resources/extensions/gsd/tools/complete-slice.ts +300 -0
  628. package/src/resources/extensions/gsd/tools/complete-task.ts +245 -0
  629. package/src/resources/extensions/gsd/tools/plan-milestone.ts +249 -0
  630. package/src/resources/extensions/gsd/tools/plan-slice.ts +194 -0
  631. package/src/resources/extensions/gsd/tools/plan-task.ts +116 -0
  632. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +203 -0
  633. package/src/resources/extensions/gsd/tools/replan-slice.ts +192 -0
  634. package/src/resources/extensions/gsd/triage-resolution.ts +20 -1
  635. package/src/resources/extensions/gsd/types.ts +50 -0
  636. package/src/resources/extensions/gsd/undo.ts +247 -3
  637. package/src/resources/extensions/gsd/visualizer-data.ts +54 -17
  638. package/src/resources/extensions/gsd/workspace-index.ts +64 -46
  639. package/dist/resources/extensions/gsd/auto-observability.js +0 -56
  640. package/dist/resources/extensions/gsd/observability-validator.js +0 -422
  641. package/dist/resources/extensions/gsd/roadmap-mutations.js +0 -110
  642. package/dist/web/standalone/.next/static/VvclDCW6TAWjEyLU-EYL1/_buildManifest.js +0 -1
  643. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-e07acdb7dd069836.js +0 -1
  644. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-d07a2c023f1aef1e.js +0 -1
  645. package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-d07a2c023f1aef1e.js +0 -1
  646. package/dist/web/standalone/.next/static/chunks/app/api/captures/route-d07a2c023f1aef1e.js +0 -1
  647. package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-d07a2c023f1aef1e.js +0 -1
  648. package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-d07a2c023f1aef1e.js +0 -1
  649. package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-d07a2c023f1aef1e.js +0 -1
  650. package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-d07a2c023f1aef1e.js +0 -1
  651. package/dist/web/standalone/.next/static/chunks/app/api/files/route-d07a2c023f1aef1e.js +0 -1
  652. package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-d07a2c023f1aef1e.js +0 -1
  653. package/dist/web/standalone/.next/static/chunks/app/api/git/route-d07a2c023f1aef1e.js +0 -1
  654. package/dist/web/standalone/.next/static/chunks/app/api/history/route-d07a2c023f1aef1e.js +0 -1
  655. package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-d07a2c023f1aef1e.js +0 -1
  656. package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-d07a2c023f1aef1e.js +0 -1
  657. package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-d07a2c023f1aef1e.js +0 -1
  658. package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-d07a2c023f1aef1e.js +0 -1
  659. package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-d07a2c023f1aef1e.js +0 -1
  660. package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-d07a2c023f1aef1e.js +0 -1
  661. package/dist/web/standalone/.next/static/chunks/app/api/projects/route-d07a2c023f1aef1e.js +0 -1
  662. package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-d07a2c023f1aef1e.js +0 -1
  663. package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-d07a2c023f1aef1e.js +0 -1
  664. package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-d07a2c023f1aef1e.js +0 -1
  665. package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-d07a2c023f1aef1e.js +0 -1
  666. package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-d07a2c023f1aef1e.js +0 -1
  667. package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-d07a2c023f1aef1e.js +0 -1
  668. package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-d07a2c023f1aef1e.js +0 -1
  669. package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-d07a2c023f1aef1e.js +0 -1
  670. package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-d07a2c023f1aef1e.js +0 -1
  671. package/dist/web/standalone/.next/static/chunks/app/api/steer/route-d07a2c023f1aef1e.js +0 -1
  672. package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-d07a2c023f1aef1e.js +0 -1
  673. package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-d07a2c023f1aef1e.js +0 -1
  674. package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-d07a2c023f1aef1e.js +0 -1
  675. package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-d07a2c023f1aef1e.js +0 -1
  676. package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-d07a2c023f1aef1e.js +0 -1
  677. package/dist/web/standalone/.next/static/chunks/app/api/undo/route-d07a2c023f1aef1e.js +0 -1
  678. package/dist/web/standalone/.next/static/chunks/app/api/update/route-d07a2c023f1aef1e.js +0 -1
  679. package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-d07a2c023f1aef1e.js +0 -1
  680. package/dist/web/standalone/.next/static/chunks/app/layout-745c6ed5fea5fb06.js +0 -1
  681. package/dist/web/standalone/.next/static/chunks/app/page-801b53eff6e83579.js +0 -1
  682. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-d07a2c023f1aef1e.js +0 -1
  683. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-d07a2c023f1aef1e.js +0 -1
  684. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-e6255954dccfcf0a.js +0 -1
  685. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-d07a2c023f1aef1e.js +0 -1
  686. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-d07a2c023f1aef1e.js +0 -1
  687. package/dist/web/standalone/.next/static/css/123c0bb039697968.css +0 -1
  688. package/src/resources/extensions/gsd/auto-observability.ts +0 -74
  689. package/src/resources/extensions/gsd/observability-validator.ts +0 -456
  690. package/src/resources/extensions/gsd/roadmap-mutations.ts +0 -134
  691. package/src/resources/extensions/gsd/tests/doctor-task-done-missing-summary-slice-loop.test.ts +0 -174
  692. package/src/resources/extensions/gsd/tests/plan-quality-validator.test.ts +0 -474
  693. /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 overriding process.emit with filtered version
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
- // node:sqlite not available
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
- // better-sqlite3 not available
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
- // ─── Schema ────────────────────────────────────────────────────────────────
121
- const SCHEMA_VERSION = 4;
108
+ const SCHEMA_VERSION = 10;
122
109
  function initSchema(db, fileBacked) {
123
- // WAL mode for file-backed databases (must be outside transaction)
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
- // Views — DROP + CREATE since CREATE VIEW IF NOT EXISTS doesn't update definitions
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
- // Insert schema version if not already present
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
- * Incremental schema migration. Reads current version from schema_version table
224
- * and applies DDL for each version step up to SCHEMA_VERSION.
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({ ":version": 2, ":applied_at": new Date().toISOString() });
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({ ":version": 3, ":applied_at": new Date().toISOString() });
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
- // Add made_by column default 'agent' for existing rows (pre-attribution decisions)
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({ ":version": 4, ":applied_at": new Date().toISOString() });
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
- // ─── Public API ────────────────────────────────────────────────────────────
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
- // Close existing if different path
319
- if (currentDb && currentPath !== path) {
564
+ if (currentDb && currentPath !== path)
320
565
  closeDatabase();
321
- }
322
- if (currentDb && currentPath === path) {
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
- .prepare(`INSERT INTO decisions (id, when_context, scope, decision, choice, rationale, revisable, made_by, superseded_by)
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
- .prepare(`INSERT INTO requirements (id, class, status, description, why, source, primary_owner, supporting_slices, validation, notes, full_content, superseded_by)
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
- .prepare(`INSERT OR REPLACE INTO decisions (id, when_context, scope, decision, choice, rationale, revisable, made_by, superseded_by)
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
- .prepare(`INSERT OR REPLACE INTO requirements (id, class, status, description, why, source, primary_owner, supporting_slices, validation, notes, full_content, superseded_by)
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
- .prepare(`INSERT OR REPLACE INTO artifacts (path, artifact_type, milestone_id, slice_id, task_id, full_content, imported_at)
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(`gsd-db: worktree DB reconciliation failed: path contains unsafe characters\n`);
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(`gsd-db: worktree DB reconciliation failed: cannot open main DB\n`);
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
- id, when_context, scope, decision, choice, rationale, revisable, ${hasMadeBy ? "made_by" : "'agent'"}, superseded_by
689
- FROM wt.decisions
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
- id, class, status, description, why, source, primary_owner,
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
- .run();
708
- merged.requirements =
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
- .run();
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
+ }