@opengsd/gsd-pi 1.2.0 → 1.3.0-dev.eed73bea

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 (1703) hide show
  1. package/README.md +13 -7
  2. package/dist/cli-model-override.d.ts +15 -0
  3. package/dist/cli-model-override.js +21 -0
  4. package/dist/cli-style.d.ts +17 -0
  5. package/dist/cli-style.js +28 -0
  6. package/dist/cli-web-branch.d.ts +2 -0
  7. package/dist/cli-web-branch.js +9 -2
  8. package/dist/cli.js +30 -20
  9. package/dist/headless-context.js +0 -1
  10. package/dist/headless-events.d.ts +20 -3
  11. package/dist/headless-events.js +33 -36
  12. package/dist/headless.js +8 -1
  13. package/dist/help-text.js +34 -0
  14. package/dist/hermes-integration-install.d.ts +17 -0
  15. package/dist/hermes-integration-install.js +199 -0
  16. package/dist/jiti-workspace-aliases.d.ts +11 -2
  17. package/dist/jiti-workspace-aliases.js +19 -3
  18. package/dist/loader.js +6 -4
  19. package/dist/mcp-server.js +2 -1
  20. package/dist/models-resolver.d.ts +3 -13
  21. package/dist/models-resolver.js +3 -22
  22. package/dist/onboarding.js +9 -4
  23. package/dist/provider-migrations.d.ts +23 -0
  24. package/dist/provider-migrations.js +41 -0
  25. package/dist/read-cli.d.ts +23 -0
  26. package/dist/read-cli.js +90 -0
  27. package/dist/register-agent-bundles.d.ts +11 -2
  28. package/dist/register-agent-bundles.js +18 -4
  29. package/dist/resource-loader.d.ts +10 -5
  30. package/dist/resource-loader.js +121 -27
  31. package/dist/resources/.managed-resources-content-hash +1 -1
  32. package/dist/resources/GSD-WORKFLOW.md +27 -26
  33. package/dist/resources/extensions/ask-user-questions.js +81 -25
  34. package/dist/resources/extensions/async-jobs/async-bash-tool.js +30 -64
  35. package/dist/resources/extensions/async-jobs/await-tool.js +80 -12
  36. package/dist/resources/extensions/async-jobs/index.js +65 -0
  37. package/dist/resources/extensions/async-jobs/job-manager.js +12 -1
  38. package/dist/resources/extensions/bg-shell/bg-shell-command.js +6 -6
  39. package/dist/resources/extensions/bg-shell/bg-shell-tool.js +10 -7
  40. package/dist/resources/extensions/bg-shell/overlay.js +9 -6
  41. package/dist/resources/extensions/bg-shell/process-manager.js +54 -25
  42. package/dist/resources/extensions/bg-shell/readiness-detector.js +11 -0
  43. package/dist/resources/extensions/bg-shell/utilities.js +5 -2
  44. package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +209 -88
  45. package/dist/resources/extensions/browser-tools/engine/selection.js +73 -5
  46. package/dist/resources/extensions/browser-tools/index.js +69 -12
  47. package/dist/resources/extensions/claude-code-cli/index.js +7 -1
  48. package/dist/resources/extensions/claude-code-cli/models.js +9 -0
  49. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +622 -440
  50. package/dist/resources/extensions/claude-code-cli/turn-assembler.js +256 -0
  51. package/dist/resources/extensions/github-sync/templates.js +3 -3
  52. package/dist/resources/extensions/google-cli/stream-adapter.js +98 -16
  53. package/dist/resources/extensions/gsd/artifact-projection.js +14 -0
  54. package/dist/resources/extensions/gsd/auto/closeout.js +215 -0
  55. package/dist/resources/extensions/gsd/auto/custom-verify-retry-store.js +17 -2
  56. package/dist/resources/extensions/gsd/auto/detect-stuck.js +33 -13
  57. package/dist/resources/extensions/gsd/auto/dispatch-history.js +125 -0
  58. package/dist/resources/extensions/gsd/auto/dispatch-key.js +37 -0
  59. package/dist/resources/extensions/gsd/auto/dispatch.js +365 -0
  60. package/dist/resources/extensions/gsd/auto/finalize.js +347 -0
  61. package/dist/resources/extensions/gsd/auto/loop.js +147 -58
  62. package/dist/resources/extensions/gsd/auto/milestone-lease-reclaim.js +56 -0
  63. package/dist/resources/extensions/gsd/auto/orchestrator.js +361 -80
  64. package/dist/resources/extensions/gsd/auto/phase-helpers.js +146 -0
  65. package/dist/resources/extensions/gsd/auto/phases.js +17 -2299
  66. package/dist/resources/extensions/gsd/auto/pre-dispatch.js +542 -0
  67. package/dist/resources/extensions/gsd/auto/run-unit.js +2 -1
  68. package/dist/resources/extensions/gsd/auto/session.js +6 -0
  69. package/dist/resources/extensions/gsd/auto/unit-phase.js +694 -0
  70. package/dist/resources/extensions/gsd/auto/workflow-kernel.js +15 -1
  71. package/dist/resources/extensions/gsd/auto/workflow-unit-dispatch.js +1 -1
  72. package/dist/resources/extensions/gsd/auto/worktree-safety-phase.js +125 -0
  73. package/dist/resources/extensions/gsd/auto-artifact-paths.js +81 -19
  74. package/dist/resources/extensions/gsd/auto-closeout-messaging.js +90 -0
  75. package/dist/resources/extensions/gsd/auto-dashboard.js +271 -435
  76. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +26 -37
  77. package/dist/resources/extensions/gsd/auto-dispatch.js +119 -84
  78. package/dist/resources/extensions/gsd/auto-model-selection.js +56 -19
  79. package/dist/resources/extensions/gsd/auto-post-unit.js +85 -45
  80. package/dist/resources/extensions/gsd/auto-prompts.js +238 -58
  81. package/dist/resources/extensions/gsd/auto-recovery.js +173 -89
  82. package/dist/resources/extensions/gsd/auto-runtime-state.js +27 -0
  83. package/dist/resources/extensions/gsd/auto-start.js +116 -82
  84. package/dist/resources/extensions/gsd/auto-timers.js +16 -2
  85. package/dist/resources/extensions/gsd/auto-tool-tracking.js +50 -0
  86. package/dist/resources/extensions/gsd/auto-unit-closeout.js +45 -21
  87. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +14 -47
  88. package/dist/resources/extensions/gsd/auto-verification.js +34 -38
  89. package/dist/resources/extensions/gsd/auto-worktree-repair.js +10 -2
  90. package/dist/resources/extensions/gsd/auto-worktree.js +230 -467
  91. package/dist/resources/extensions/gsd/auto.js +158 -50
  92. package/dist/resources/extensions/gsd/blocked-models.js +28 -0
  93. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +161 -62
  94. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +34 -38
  95. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +74 -50
  96. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +4 -2
  97. package/dist/resources/extensions/gsd/bootstrap/fallback-continuation.js +25 -0
  98. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
  99. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +42 -1
  100. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +429 -170
  101. package/dist/resources/extensions/gsd/bootstrap/system-context.js +190 -43
  102. package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +75 -1
  103. package/dist/resources/extensions/gsd/bootstrap/tool-search-shim.js +22 -3
  104. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +476 -83
  105. package/dist/resources/extensions/gsd/branch-patterns.js +2 -0
  106. package/dist/resources/extensions/gsd/browser-daemon-auto-prep.js +83 -0
  107. package/dist/resources/extensions/gsd/browser-evidence.js +8 -2
  108. package/dist/resources/extensions/gsd/captures.js +5 -15
  109. package/dist/resources/extensions/gsd/closeout-consistency-gate.js +110 -5
  110. package/dist/resources/extensions/gsd/closeout-recovery.js +3 -2
  111. package/dist/resources/extensions/gsd/closeout-wizard.js +97 -0
  112. package/dist/resources/extensions/gsd/codebase-generator.js +1 -0
  113. package/dist/resources/extensions/gsd/commands/catalog.js +12 -62
  114. package/dist/resources/extensions/gsd/commands/context.js +16 -2
  115. package/dist/resources/extensions/gsd/commands/dispatcher.js +3 -0
  116. package/dist/resources/extensions/gsd/commands/gsd-core-aliases-handler.js +39 -0
  117. package/dist/resources/extensions/gsd/commands/gsd-core-aliases.js +44 -0
  118. package/dist/resources/extensions/gsd/commands/handlers/auto.js +3 -0
  119. package/dist/resources/extensions/gsd/commands/handlers/core.js +52 -8
  120. package/dist/resources/extensions/gsd/commands/handlers/ops.js +227 -3
  121. package/dist/resources/extensions/gsd/commands-cmux.js +3 -1
  122. package/dist/resources/extensions/gsd/commands-context.js +19 -1
  123. package/dist/resources/extensions/gsd/commands-gsd-core.js +868 -0
  124. package/dist/resources/extensions/gsd/commands-handlers.js +133 -4
  125. package/dist/resources/extensions/gsd/commands-inspect.js +4 -8
  126. package/dist/resources/extensions/gsd/commands-maintenance.js +140 -43
  127. package/dist/resources/extensions/gsd/commands-mcp-status.js +2 -2
  128. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +30 -11
  129. package/dist/resources/extensions/gsd/commands-ship.js +2 -2
  130. package/dist/resources/extensions/gsd/commands-verdict.js +21 -5
  131. package/dist/resources/extensions/gsd/commands-workflow-templates.js +9 -2
  132. package/dist/resources/extensions/gsd/commands-worktree.js +12 -10
  133. package/dist/resources/extensions/gsd/compat/compat-marker.js +172 -0
  134. package/dist/resources/extensions/gsd/compat/index.js +3 -0
  135. package/dist/resources/extensions/gsd/compat/planning-compat.js +142 -0
  136. package/dist/resources/extensions/gsd/config-overlay.js +11 -8
  137. package/dist/resources/extensions/gsd/consent-question.js +365 -0
  138. package/dist/resources/extensions/gsd/consent-verdict.js +73 -0
  139. package/dist/resources/extensions/gsd/constants.js +0 -2
  140. package/dist/resources/extensions/gsd/crash-recovery.js +12 -15
  141. package/dist/resources/extensions/gsd/dashboard-overlay.js +71 -6
  142. package/dist/resources/extensions/gsd/db/engine.js +800 -0
  143. package/dist/resources/extensions/gsd/db/queries.js +542 -0
  144. package/dist/resources/extensions/gsd/db/sql-constants.js +11 -0
  145. package/dist/resources/extensions/gsd/db/unit-dispatches.js +22 -1
  146. package/dist/resources/extensions/gsd/db/writers/cascades.js +194 -0
  147. package/dist/resources/extensions/gsd/db/writers/import-restore.js +182 -0
  148. package/dist/resources/extensions/gsd/db/writers/memory.js +149 -0
  149. package/dist/resources/extensions/gsd/db/writers/reconcile.js +476 -0
  150. package/dist/resources/extensions/gsd/db/writers/status.js +70 -0
  151. package/dist/resources/extensions/gsd/db-migration-backup.js +51 -8
  152. package/dist/resources/extensions/gsd/db-transaction.js +27 -23
  153. package/dist/resources/extensions/gsd/db-workspace.js +115 -0
  154. package/dist/resources/extensions/gsd/db-writer.js +8 -17
  155. package/dist/resources/extensions/gsd/delegation-policy.js +2 -10
  156. package/dist/resources/extensions/gsd/discussion-handoff.js +222 -0
  157. package/dist/resources/extensions/gsd/dispatch-guard.js +10 -35
  158. package/dist/resources/extensions/gsd/docs/preferences-reference.md +9 -0
  159. package/dist/resources/extensions/gsd/doctor-engine-checks.js +5 -5
  160. package/dist/resources/extensions/gsd/doctor-environment.js +261 -136
  161. package/dist/resources/extensions/gsd/doctor-format.js +9 -6
  162. package/dist/resources/extensions/gsd/doctor-git-checks.js +36 -25
  163. package/dist/resources/extensions/gsd/doctor-providers.js +93 -9
  164. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +34 -40
  165. package/dist/resources/extensions/gsd/doctor.js +43 -15
  166. package/dist/resources/extensions/gsd/engine-hook-contract.js +70 -0
  167. package/dist/resources/extensions/gsd/error-classifier.js +22 -1
  168. package/dist/resources/extensions/gsd/escalation.js +11 -4
  169. package/dist/resources/extensions/gsd/exec-sandbox.js +75 -19
  170. package/dist/resources/extensions/gsd/export-html.js +10 -3
  171. package/dist/resources/extensions/gsd/export.js +73 -0
  172. package/dist/resources/extensions/gsd/file-lock.js +1 -1
  173. package/dist/resources/extensions/gsd/files.js +33 -19
  174. package/dist/resources/extensions/gsd/flat-phase-migration.js +176 -0
  175. package/dist/resources/extensions/gsd/forensics.js +4 -33
  176. package/dist/resources/extensions/gsd/git-conflict-state.js +16 -1
  177. package/dist/resources/extensions/gsd/git-service.js +12 -8
  178. package/dist/resources/extensions/gsd/gitignore.js +9 -2
  179. package/dist/resources/extensions/gsd/gsd-command-home.js +22 -12
  180. package/dist/resources/extensions/gsd/gsd-db.js +185 -2054
  181. package/dist/resources/extensions/gsd/guidance.js +158 -0
  182. package/dist/resources/extensions/gsd/guided-flow-queue.js +59 -5
  183. package/dist/resources/extensions/gsd/guided-flow.js +184 -478
  184. package/dist/resources/extensions/gsd/guided-unit-completion.js +225 -0
  185. package/dist/resources/extensions/gsd/health-widget.js +117 -32
  186. package/dist/resources/extensions/gsd/layout-policy.js +75 -0
  187. package/dist/resources/extensions/gsd/markdown-renderer.js +408 -118
  188. package/dist/resources/extensions/gsd/mcp-bridge.js +10 -0
  189. package/dist/resources/extensions/gsd/mcp-filter.js +48 -30
  190. package/dist/resources/extensions/gsd/mcp-tool-name.js +18 -0
  191. package/dist/resources/extensions/gsd/md-importer.js +157 -54
  192. package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +45 -22
  193. package/dist/resources/extensions/gsd/memory-relations.js +1 -1
  194. package/dist/resources/extensions/gsd/metrics.js +19 -11
  195. package/dist/resources/extensions/gsd/migrate/layout-detect.js +32 -0
  196. package/dist/resources/extensions/gsd/migrate/planning-writer.js +203 -0
  197. package/dist/resources/extensions/gsd/migrate/safety.js +22 -11
  198. package/dist/resources/extensions/gsd/migrate-external.js +51 -6
  199. package/dist/resources/extensions/gsd/migration-auto-check.js +32 -19
  200. package/dist/resources/extensions/gsd/milestone-actions.js +5 -3
  201. package/dist/resources/extensions/gsd/milestone-closeout-proof.js +72 -0
  202. package/dist/resources/extensions/gsd/milestone-closeout.js +108 -29
  203. package/dist/resources/extensions/gsd/milestone-ids.js +50 -19
  204. package/dist/resources/extensions/gsd/milestone-implementation-evidence.js +26 -20
  205. package/dist/resources/extensions/gsd/milestone-merge-transaction.js +10 -0
  206. package/dist/resources/extensions/gsd/milestone-planning-persistence.js +164 -0
  207. package/dist/resources/extensions/gsd/milestone-readiness.js +77 -0
  208. package/dist/resources/extensions/gsd/milestone-reopen-events.js +3 -5
  209. package/dist/resources/extensions/gsd/milestone-settlement.js +50 -0
  210. package/dist/resources/extensions/gsd/milestone-validation-evidence.js +73 -0
  211. package/dist/resources/extensions/gsd/milestone-validation-verdict.js +60 -0
  212. package/dist/resources/extensions/gsd/model-cost-table.js +1 -0
  213. package/dist/resources/extensions/gsd/model-router.js +82 -20
  214. package/dist/resources/extensions/gsd/native-git-bridge.js +36 -0
  215. package/dist/resources/extensions/gsd/notification-store.js +33 -33
  216. package/dist/resources/extensions/gsd/notifications.js +48 -14
  217. package/dist/resources/extensions/gsd/observability-validator.js +12 -4
  218. package/dist/resources/extensions/gsd/parallel-eligibility.js +3 -6
  219. package/dist/resources/extensions/gsd/parallel-merge.js +14 -11
  220. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +144 -42
  221. package/dist/resources/extensions/gsd/parallel-orchestrator.js +3 -2
  222. package/dist/resources/extensions/gsd/parsers-legacy.js +56 -18
  223. package/dist/resources/extensions/gsd/paths.js +393 -68
  224. package/dist/resources/extensions/gsd/planning-depth.js +2 -1
  225. package/dist/resources/extensions/gsd/post-execution-checks.js +26 -3
  226. package/dist/resources/extensions/gsd/pre-execution-checks.js +91 -3
  227. package/dist/resources/extensions/gsd/preferences-diagnostics.js +67 -0
  228. package/dist/resources/extensions/gsd/preferences-models.js +46 -60
  229. package/dist/resources/extensions/gsd/preferences.js +302 -35
  230. package/dist/resources/extensions/gsd/projection-flush.js +7 -0
  231. package/dist/resources/extensions/gsd/prompts/ai-integration-phase.md +28 -0
  232. package/dist/resources/extensions/gsd/prompts/audit-fix.md +39 -0
  233. package/dist/resources/extensions/gsd/prompts/audit-milestone.md +26 -0
  234. package/dist/resources/extensions/gsd/prompts/audit-uat.md +24 -0
  235. package/dist/resources/extensions/gsd/prompts/autonomous.md +31 -0
  236. package/dist/resources/extensions/gsd/prompts/code-review.md +37 -0
  237. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +8 -2
  238. package/dist/resources/extensions/gsd/prompts/complete-slice.md +25 -15
  239. package/dist/resources/extensions/gsd/prompts/discuss-phase.md +31 -0
  240. package/dist/resources/extensions/gsd/prompts/docs-update.md +13 -0
  241. package/dist/resources/extensions/gsd/prompts/execute-phase.md +33 -0
  242. package/dist/resources/extensions/gsd/prompts/execute-task.md +9 -2
  243. package/dist/resources/extensions/gsd/prompts/explore.md +58 -0
  244. package/dist/resources/extensions/gsd/prompts/graphify.md +27 -0
  245. package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +3 -1
  246. package/dist/resources/extensions/gsd/prompts/health.md +37 -0
  247. package/dist/resources/extensions/gsd/prompts/import.md +30 -0
  248. package/dist/resources/extensions/gsd/prompts/inbox.md +27 -0
  249. package/dist/resources/extensions/gsd/prompts/ingest-docs.md +30 -0
  250. package/dist/resources/extensions/gsd/prompts/manager.md +21 -0
  251. package/dist/resources/extensions/gsd/prompts/map-codebase.md +42 -0
  252. package/dist/resources/extensions/gsd/prompts/milestone-summary.md +27 -0
  253. package/dist/resources/extensions/gsd/prompts/mvp-phase.md +23 -0
  254. package/dist/resources/extensions/gsd/prompts/pause-work.md +24 -0
  255. package/dist/resources/extensions/gsd/prompts/phase.md +22 -0
  256. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
  257. package/dist/resources/extensions/gsd/prompts/plan-phase.md +34 -0
  258. package/dist/resources/extensions/gsd/prompts/plan-review-convergence.md +34 -0
  259. package/dist/resources/extensions/gsd/prompts/plan-slice.md +3 -2
  260. package/dist/resources/extensions/gsd/prompts/profile-user.md +28 -0
  261. package/dist/resources/extensions/gsd/prompts/progress.md +30 -0
  262. package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -1
  263. package/dist/resources/extensions/gsd/prompts/reactive-execute.md +2 -2
  264. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  265. package/dist/resources/extensions/gsd/prompts/refine-slice.md +3 -2
  266. package/dist/resources/extensions/gsd/prompts/replan-slice.md +2 -2
  267. package/dist/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  268. package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
  269. package/dist/resources/extensions/gsd/prompts/resume-work.md +20 -0
  270. package/dist/resources/extensions/gsd/prompts/review-backlog.md +21 -0
  271. package/dist/resources/extensions/gsd/prompts/review.md +27 -0
  272. package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  273. package/dist/resources/extensions/gsd/prompts/run-uat.md +13 -5
  274. package/dist/resources/extensions/gsd/prompts/secure-phase.md +24 -0
  275. package/dist/resources/extensions/gsd/prompts/settings.md +24 -0
  276. package/dist/resources/extensions/gsd/prompts/sketch.md +59 -0
  277. package/dist/resources/extensions/gsd/prompts/spec-phase.md +29 -0
  278. package/dist/resources/extensions/gsd/prompts/spike.md +59 -0
  279. package/dist/resources/extensions/gsd/prompts/stats.md +43 -0
  280. package/dist/resources/extensions/gsd/prompts/surface.md +25 -0
  281. package/dist/resources/extensions/gsd/prompts/system.md +6 -3
  282. package/dist/resources/extensions/gsd/prompts/thread.md +24 -0
  283. package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -1
  284. package/dist/resources/extensions/gsd/prompts/ui-phase.md +29 -0
  285. package/dist/resources/extensions/gsd/prompts/ui-review.md +29 -0
  286. package/dist/resources/extensions/gsd/prompts/ultraplan-phase.md +24 -0
  287. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
  288. package/dist/resources/extensions/gsd/prompts/validate-phase.md +26 -0
  289. package/dist/resources/extensions/gsd/prompts/verify-work.md +24 -0
  290. package/dist/resources/extensions/gsd/prompts/workflow-start.md +2 -1
  291. package/dist/resources/extensions/gsd/prompts/workspace.md +22 -0
  292. package/dist/resources/extensions/gsd/prompts/workstreams.md +24 -0
  293. package/dist/resources/extensions/gsd/provider-error-guidance.js +25 -5
  294. package/dist/resources/extensions/gsd/provider-payload-policy.js +83 -0
  295. package/dist/resources/extensions/gsd/provider-switch-observer.js +1 -1
  296. package/dist/resources/extensions/gsd/publication.js +87 -0
  297. package/dist/resources/extensions/gsd/pull-request-process.js +13 -0
  298. package/dist/resources/extensions/gsd/quality-gate-closure.js +109 -0
  299. package/dist/resources/extensions/gsd/question-transport.js +86 -0
  300. package/dist/resources/extensions/gsd/queue-order.js +3 -2
  301. package/dist/resources/extensions/gsd/quick.js +45 -2
  302. package/dist/resources/extensions/gsd/reactive-graph.js +8 -1
  303. package/dist/resources/extensions/gsd/recovery-classification.js +49 -87
  304. package/dist/resources/extensions/gsd/roadmap-slices.js +34 -6
  305. package/dist/resources/extensions/gsd/safety/content-validator.js +2 -1
  306. package/dist/resources/extensions/gsd/safety/destructive-confirmation.js +108 -0
  307. package/dist/resources/extensions/gsd/safety/evidence-collector.js +37 -4
  308. package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +50 -3
  309. package/dist/resources/extensions/gsd/safety/file-change-validator.js +10 -0
  310. package/dist/resources/extensions/gsd/service-tier.js +2 -1
  311. package/dist/resources/extensions/gsd/session-forensics.js +11 -1
  312. package/dist/resources/extensions/gsd/session-lock.js +12 -10
  313. package/dist/resources/extensions/gsd/skill-activation.js +3 -6
  314. package/dist/resources/extensions/gsd/skills/gsd-headless/SKILL.md +3 -0
  315. package/dist/resources/extensions/gsd/skills/gsd-headless/references/commands.md +51 -0
  316. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +3 -2
  317. package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +51 -10
  318. package/dist/resources/extensions/gsd/state-reconciliation/drift/completion.js +24 -3
  319. package/dist/resources/extensions/gsd/state-reconciliation/drift/external-markdown-edit.js +82 -0
  320. package/dist/resources/extensions/gsd/state-reconciliation/drift/external-planning-edit.js +142 -0
  321. package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +19 -6
  322. package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +2 -2
  323. package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +143 -18
  324. package/dist/resources/extensions/gsd/state-reconciliation/index.js +36 -3
  325. package/dist/resources/extensions/gsd/state-reconciliation/registry.js +12 -0
  326. package/dist/resources/extensions/gsd/state-transition-matrix.js +38 -0
  327. package/dist/resources/extensions/gsd/state.js +70 -41
  328. package/dist/resources/extensions/gsd/status-guards.js +56 -8
  329. package/dist/resources/extensions/gsd/stop-notice.js +57 -0
  330. package/dist/resources/extensions/gsd/sync-lock.js +11 -18
  331. package/dist/resources/extensions/gsd/templates/plan.md +7 -0
  332. package/dist/resources/extensions/gsd/templates/project.md +1 -0
  333. package/dist/resources/extensions/gsd/templates/roadmap.md +1 -1
  334. package/dist/resources/extensions/gsd/templates/uat.md +5 -1
  335. package/dist/resources/extensions/gsd/tool-contract.js +66 -11
  336. package/dist/resources/extensions/gsd/tool-presentation-plan.js +17 -36
  337. package/dist/resources/extensions/gsd/tool-surface-readiness.js +297 -0
  338. package/dist/resources/extensions/gsd/tool-surface-snapshot.js +17 -0
  339. package/dist/resources/extensions/gsd/tools/complete-milestone.js +7 -4
  340. package/dist/resources/extensions/gsd/tools/complete-slice.js +90 -58
  341. package/dist/resources/extensions/gsd/tools/complete-task.js +153 -14
  342. package/dist/resources/extensions/gsd/tools/exec-tool.js +14 -114
  343. package/dist/resources/extensions/gsd/tools/plan-milestone.js +15 -143
  344. package/dist/resources/extensions/gsd/tools/plan-slice.js +13 -9
  345. package/dist/resources/extensions/gsd/tools/plan-task.js +18 -3
  346. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +50 -5
  347. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +13 -31
  348. package/dist/resources/extensions/gsd/tools/reopen-slice.js +16 -35
  349. package/dist/resources/extensions/gsd/tools/reopen-task.js +2 -2
  350. package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -2
  351. package/dist/resources/extensions/gsd/tools/skip-slice.js +18 -36
  352. package/dist/resources/extensions/gsd/tools/validate-milestone.js +21 -79
  353. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +110 -6
  354. package/dist/resources/extensions/gsd/triage-resolution.js +14 -7
  355. package/dist/resources/extensions/gsd/tui/render-kit.js +38 -13
  356. package/dist/resources/extensions/gsd/uat-policy.js +57 -25
  357. package/dist/resources/extensions/gsd/uat-run.js +9 -14
  358. package/dist/resources/extensions/gsd/undo.js +16 -16
  359. package/dist/resources/extensions/gsd/unit-closeout.js +138 -0
  360. package/dist/resources/extensions/gsd/unit-context-composer.js +130 -21
  361. package/dist/resources/extensions/gsd/unit-context-manifest.js +4 -27
  362. package/dist/resources/extensions/gsd/unit-registry.js +413 -0
  363. package/dist/resources/extensions/gsd/unit-runtime.js +3 -2
  364. package/dist/resources/extensions/gsd/unit-tool-contracts.js +9 -181
  365. package/dist/resources/extensions/gsd/unmerged-milestone-guard.js +91 -5
  366. package/dist/resources/extensions/gsd/validation-block-guard.js +55 -3
  367. package/dist/resources/extensions/gsd/verdict-parser.js +1 -1
  368. package/dist/resources/extensions/gsd/verification-verdict.js +2 -1
  369. package/dist/resources/extensions/gsd/visualizer-data.js +35 -0
  370. package/dist/resources/extensions/gsd/visualizer-views.js +21 -2
  371. package/dist/resources/extensions/gsd/web-app-uat.js +117 -0
  372. package/dist/resources/extensions/gsd/workflow-event-ledger.js +91 -0
  373. package/dist/resources/extensions/gsd/workflow-event-vocabulary.js +46 -0
  374. package/dist/resources/extensions/gsd/workflow-events.js +6 -18
  375. package/dist/resources/extensions/gsd/workflow-logger.js +4 -0
  376. package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +2 -0
  377. package/dist/resources/extensions/gsd/workflow-mcp-readiness-cache.js +105 -0
  378. package/dist/resources/extensions/gsd/workflow-mcp.js +24 -103
  379. package/dist/resources/extensions/gsd/workflow-projections.js +25 -4
  380. package/dist/resources/extensions/gsd/workflow-reconcile.js +25 -59
  381. package/dist/resources/extensions/gsd/workflow-tool-surface.js +46 -0
  382. package/dist/resources/extensions/gsd/workspace-git-guard.js +2 -0
  383. package/dist/resources/extensions/gsd/workspace-git-preflight.js +30 -1
  384. package/dist/resources/extensions/gsd/worktree-command.js +6 -6
  385. package/dist/resources/extensions/gsd/worktree-git-recovery.js +293 -0
  386. package/dist/resources/extensions/gsd/worktree-health.js +6 -3
  387. package/dist/resources/extensions/gsd/worktree-lifecycle.js +12 -3
  388. package/dist/resources/extensions/gsd/worktree-manager.js +161 -45
  389. package/dist/resources/extensions/gsd/worktree-placement.js +59 -0
  390. package/dist/resources/extensions/gsd/worktree-reentry.js +12 -8
  391. package/dist/resources/extensions/gsd/worktree-root.js +28 -6
  392. package/dist/resources/extensions/gsd/worktree-safety.js +48 -34
  393. package/dist/resources/extensions/gsd/worktree-session-state.js +12 -11
  394. package/dist/resources/extensions/gsd/worktree-shell-guard.js +113 -0
  395. package/dist/resources/extensions/gsd/worktree-state-projection.js +33 -4
  396. package/dist/resources/extensions/gsd/worktree-telemetry.js +12 -0
  397. package/dist/resources/extensions/gsd/worktree.js +8 -1
  398. package/dist/resources/extensions/mcp-client/manager.js +9 -4
  399. package/dist/resources/extensions/search-the-web/index.js +41 -9
  400. package/dist/resources/extensions/search-the-web/native-search.js +23 -7
  401. package/dist/resources/extensions/shared/browser-contract.js +59 -0
  402. package/dist/resources/extensions/shared/gsd-browser-cli.js +156 -8
  403. package/dist/resources/extensions/shared/interview-ui.js +2 -2
  404. package/dist/resources/extensions/subagent/index.js +20 -15
  405. package/dist/resources/extensions/subagent/worktree-cwd.js +31 -0
  406. package/dist/resources/shared/claude-runtime-floor.js +182 -0
  407. package/dist/resources/shared/gsd-browser-path-sync.js +214 -0
  408. package/dist/resources/shared/package-manager-detection.js +1 -1
  409. package/dist/resources/shared/package.json +3 -0
  410. package/dist/resources/skills/create-skill/SKILL.md +3 -0
  411. package/dist/resources/skills/create-skill/references/executable-code.md +1 -1
  412. package/dist/resources/skills/create-skill/references/skill-structure.md +1 -0
  413. package/dist/resources/skills/create-skill/workflows/add-reference.md +8 -3
  414. package/dist/resources/skills/create-skill/workflows/add-script.md +4 -2
  415. package/dist/resources/skills/create-skill/workflows/add-template.md +3 -1
  416. package/dist/resources/skills/create-skill/workflows/add-workflow.md +8 -3
  417. package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
  418. package/dist/resources/skills/create-skill/workflows/verify-skill.md +9 -4
  419. package/dist/resources/skills/spike-wrap-up/SKILL.md +9 -9
  420. package/dist/runtime-checks.d.ts +10 -0
  421. package/dist/runtime-checks.js +27 -0
  422. package/dist/tsconfig.extensions.tsbuildinfo +1 -0
  423. package/dist/update-check.d.ts +2 -0
  424. package/dist/update-check.js +39 -5
  425. package/dist/update-cmd.js +40 -3
  426. package/dist/web/standalone/.next/BUILD_ID +1 -1
  427. package/dist/web/standalone/.next/app-path-routes-manifest.json +14 -14
  428. package/dist/web/standalone/.next/build-manifest.json +4 -4
  429. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  430. package/dist/web/standalone/.next/react-loadable-manifest.json +8 -8
  431. package/dist/web/standalone/.next/required-server-files.json +3 -3
  432. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  433. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  434. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  435. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  436. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  437. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  438. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  439. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  440. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  441. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  442. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  443. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  444. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  445. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  446. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  447. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  448. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  449. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  450. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  451. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  452. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  453. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  454. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  455. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  456. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  457. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  458. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  459. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  460. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  461. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  462. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  463. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  464. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  465. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  466. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  467. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  468. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  469. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  470. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  471. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  472. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  473. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  474. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  475. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  476. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  477. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  478. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  479. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  480. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  481. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  482. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  483. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  484. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  485. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  486. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  487. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  488. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  489. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  490. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  491. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  492. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  493. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  494. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  495. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  496. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  497. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  498. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  499. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  500. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  501. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  502. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  503. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  504. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  505. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  506. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js +1 -1
  507. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
  508. package/dist/web/standalone/.next/server/app/api/mcp-connections/route_client-reference-manifest.js +1 -1
  509. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  510. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  511. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  512. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  513. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  514. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  515. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  516. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  517. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  518. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  519. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  520. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  521. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  522. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  523. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  524. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  525. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  526. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  527. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  528. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  529. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  530. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  531. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  532. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  533. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  534. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  535. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  536. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  537. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  538. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  539. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  540. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  541. package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
  542. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  543. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  544. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  545. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  546. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  547. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  548. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  549. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  550. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  551. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  552. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  553. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  554. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  555. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  556. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  557. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  558. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  559. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  560. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  561. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  562. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  563. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  564. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  565. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  566. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  567. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  568. package/dist/web/standalone/.next/server/app/api/update/route.js.nft.json +1 -1
  569. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  570. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  571. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  572. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  573. package/dist/web/standalone/.next/server/app/index.html +1 -1
  574. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  575. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  576. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  577. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  578. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  579. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  580. package/dist/web/standalone/.next/server/app/page.js +2 -2
  581. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  582. package/dist/web/standalone/.next/server/app-paths-manifest.json +14 -14
  583. package/dist/web/standalone/.next/server/chunks/1128.js +2 -0
  584. package/dist/web/standalone/.next/server/chunks/2842.js +4 -4
  585. package/dist/web/standalone/.next/server/chunks/5124.js +1 -1
  586. package/dist/web/standalone/.next/server/chunks/8357.js +3 -3
  587. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  588. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  589. package/dist/web/standalone/.next/server/middleware.js +3 -3
  590. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  591. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  592. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  593. package/dist/web/standalone/.next/static/chunks/2659.b7b129ee6a769448.js +1 -0
  594. package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +1 -0
  595. package/dist/web/standalone/.next/static/chunks/{3616.4113d484a994e411.js → 3616.3c60753b8ffcbd2e.js} +1 -1
  596. package/dist/web/standalone/.next/static/chunks/4283.8e446784528ed9dc.js +2 -0
  597. package/dist/web/standalone/.next/static/chunks/5826.a46ecdd1cfe8dabc.js +1 -0
  598. package/dist/web/standalone/.next/static/chunks/796.3976108148518f7d.js +10 -0
  599. package/dist/web/standalone/.next/static/chunks/8785.481aa5869991b760.js +1 -0
  600. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-a6fb1847f67f167c.js +1 -0
  601. package/dist/web/standalone/.next/static/chunks/app/{layout-b35cbfff38aaf4cf.js → layout-4ae2d68984392bbf.js} +1 -1
  602. package/dist/web/standalone/.next/static/chunks/app/page-6644fc6ee8ca1247.js +1 -0
  603. package/dist/web/standalone/.next/static/chunks/{main-app-590a74400e35f685.js → main-app-90d1d8d5e5d2dc6b.js} +1 -1
  604. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-1115d46ac61b9823.js +1 -0
  605. package/dist/web/standalone/.next/static/chunks/{webpack-dda80a1ef5587410.js → webpack-7c1d97e39be2da11.js} +1 -1
  606. package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
  607. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  608. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  609. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  610. package/dist/web/standalone/node_modules/postcss/lib/container.js +26 -18
  611. package/dist/web/standalone/node_modules/postcss/lib/css-syntax-error.js +47 -14
  612. package/dist/web/standalone/node_modules/postcss/lib/declaration.js +4 -4
  613. package/dist/web/standalone/node_modules/postcss/lib/fromJSON.js +3 -3
  614. package/dist/web/standalone/node_modules/postcss/lib/input.js +54 -29
  615. package/dist/web/standalone/node_modules/postcss/lib/lazy-result.js +47 -37
  616. package/dist/web/standalone/node_modules/postcss/lib/map-generator.js +26 -9
  617. package/dist/web/standalone/node_modules/postcss/lib/no-work-result.js +57 -55
  618. package/dist/web/standalone/node_modules/postcss/lib/node.js +99 -31
  619. package/dist/web/standalone/node_modules/postcss/lib/parse.js +1 -1
  620. package/dist/web/standalone/node_modules/postcss/lib/parser.js +10 -9
  621. package/dist/web/standalone/node_modules/postcss/lib/postcss.js +12 -12
  622. package/dist/web/standalone/node_modules/postcss/lib/previous-map.js +30 -11
  623. package/dist/web/standalone/node_modules/postcss/lib/processor.js +7 -7
  624. package/dist/web/standalone/node_modules/postcss/lib/result.js +5 -5
  625. package/dist/web/standalone/node_modules/postcss/lib/rule.js +6 -6
  626. package/dist/web/standalone/node_modules/postcss/lib/stringifier.js +69 -28
  627. package/dist/web/standalone/node_modules/postcss/lib/tokenize.js +6 -2
  628. package/dist/web/standalone/node_modules/postcss/package.json +48 -48
  629. package/dist/web/standalone/package.json +1 -1
  630. package/dist/web/standalone/server.js +1 -1
  631. package/dist/web-mode.d.ts +5 -1
  632. package/dist/web-mode.js +27 -13
  633. package/dist/worktree-cli.js +3 -6
  634. package/dist/worktree-status-banner.js +7 -11
  635. package/integrations/hermes/README.md +48 -0
  636. package/integrations/hermes/docs/setup.md +272 -0
  637. package/integrations/hermes/docs/upstream-hermes-pr.md +40 -0
  638. package/integrations/hermes/open_gsd_hermes/__init__.py +105 -0
  639. package/integrations/hermes/open_gsd_hermes/binding.py +107 -0
  640. package/integrations/hermes/open_gsd_hermes/commands.py +186 -0
  641. package/integrations/hermes/open_gsd_hermes/config.py +59 -0
  642. package/integrations/hermes/open_gsd_hermes/credentials.py +51 -0
  643. package/integrations/hermes/open_gsd_hermes/cron.py +85 -0
  644. package/integrations/hermes/open_gsd_hermes/formatting.py +13 -0
  645. package/integrations/hermes/open_gsd_hermes/gsd_client.py +269 -0
  646. package/integrations/hermes/open_gsd_hermes/inject.py +31 -0
  647. package/integrations/hermes/open_gsd_hermes/memory.py +66 -0
  648. package/integrations/hermes/open_gsd_hermes/notifications.py +71 -0
  649. package/integrations/hermes/open_gsd_hermes/snapshot.py +42 -0
  650. package/integrations/hermes/open_gsd_hermes/supervisor.py +180 -0
  651. package/integrations/hermes/open_gsd_hermes/types.py +100 -0
  652. package/integrations/hermes/plugin.yaml +38 -0
  653. package/integrations/hermes/pyproject.toml +32 -0
  654. package/integrations/hermes/scripts/preflight.sh +92 -0
  655. package/integrations/hermes/tests/fixtures/minimal-project/.gsd/STATE.md +17 -0
  656. package/integrations/hermes/tests/golden/memory_prefetch.txt +5 -0
  657. package/integrations/hermes/tests/golden/snapshot.txt +8 -0
  658. package/integrations/hermes/tests/test_binding.py +103 -0
  659. package/integrations/hermes/tests/test_config.py +36 -0
  660. package/integrations/hermes/tests/test_cron.py +34 -0
  661. package/integrations/hermes/tests/test_gsd_client_cache.py +120 -0
  662. package/integrations/hermes/tests/test_memory.py +59 -0
  663. package/integrations/hermes/tests/test_read_cli_contract.py +50 -0
  664. package/integrations/hermes/tests/test_register.py +56 -0
  665. package/integrations/hermes/tests/test_snapshot.py +53 -0
  666. package/integrations/hermes/tests/test_supervisor_fsm.py +581 -0
  667. package/package.json +19 -14
  668. package/packages/cloud-mcp-gateway/dist/runtime-registry.d.ts +8 -0
  669. package/packages/cloud-mcp-gateway/dist/runtime-registry.d.ts.map +1 -1
  670. package/packages/cloud-mcp-gateway/dist/runtime-registry.js +19 -2
  671. package/packages/cloud-mcp-gateway/dist/runtime-registry.js.map +1 -1
  672. package/packages/cloud-mcp-gateway/dist/runtime-registry.test.js +71 -2
  673. package/packages/cloud-mcp-gateway/dist/runtime-registry.test.js.map +1 -1
  674. package/packages/cloud-mcp-gateway/package.json +2 -2
  675. package/packages/contracts/dist/rpc.d.ts +1 -0
  676. package/packages/contracts/dist/rpc.d.ts.map +1 -1
  677. package/packages/contracts/dist/rpc.js.map +1 -1
  678. package/packages/contracts/dist/workflow.d.ts +5 -0
  679. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  680. package/packages/contracts/dist/workflow.js +2 -0
  681. package/packages/contracts/dist/workflow.js.map +1 -1
  682. package/packages/contracts/package.json +1 -1
  683. package/packages/daemon/package.json +4 -4
  684. package/packages/gsd-agent-core/dist/sdk.d.ts.map +1 -1
  685. package/packages/gsd-agent-core/dist/sdk.js +12 -6
  686. package/packages/gsd-agent-core/dist/sdk.js.map +1 -1
  687. package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts +2 -0
  688. package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts.map +1 -1
  689. package/packages/gsd-agent-core/dist/session/agent-session-extensions.js +14 -0
  690. package/packages/gsd-agent-core/dist/session/agent-session-extensions.js.map +1 -1
  691. package/packages/gsd-agent-core/package.json +5 -5
  692. package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.d.ts +5 -5
  693. package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  694. package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.js +12 -24
  695. package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.js.map +1 -1
  696. package/packages/gsd-agent-modes/dist/modes/interactive/components/bash-execution.js +5 -5
  697. package/packages/gsd-agent-modes/dist/modes/interactive/components/bash-execution.js.map +1 -1
  698. package/packages/gsd-agent-modes/dist/modes/interactive/components/branch-summary-message.d.ts +3 -3
  699. package/packages/gsd-agent-modes/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  700. package/packages/gsd-agent-modes/dist/modes/interactive/components/branch-summary-message.js +20 -11
  701. package/packages/gsd-agent-modes/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  702. package/packages/gsd-agent-modes/dist/modes/interactive/components/chat-turn-connect.d.ts +4 -3
  703. package/packages/gsd-agent-modes/dist/modes/interactive/components/chat-turn-connect.d.ts.map +1 -1
  704. package/packages/gsd-agent-modes/dist/modes/interactive/components/chat-turn-connect.js +5 -54
  705. package/packages/gsd-agent-modes/dist/modes/interactive/components/chat-turn-connect.js.map +1 -1
  706. package/packages/gsd-agent-modes/dist/modes/interactive/components/compaction-summary-message.d.ts +2 -4
  707. package/packages/gsd-agent-modes/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  708. package/packages/gsd-agent-modes/dist/modes/interactive/components/compaction-summary-message.js +2 -4
  709. package/packages/gsd-agent-modes/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  710. package/packages/gsd-agent-modes/dist/modes/interactive/components/custom-editor.d.ts +2 -0
  711. package/packages/gsd-agent-modes/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  712. package/packages/gsd-agent-modes/dist/modes/interactive/components/custom-editor.js +4 -0
  713. package/packages/gsd-agent-modes/dist/modes/interactive/components/custom-editor.js.map +1 -1
  714. package/packages/gsd-agent-modes/dist/modes/interactive/components/footer.d.ts +9 -12
  715. package/packages/gsd-agent-modes/dist/modes/interactive/components/footer.d.ts.map +1 -1
  716. package/packages/gsd-agent-modes/dist/modes/interactive/components/footer.js +100 -166
  717. package/packages/gsd-agent-modes/dist/modes/interactive/components/footer.js.map +1 -1
  718. package/packages/gsd-agent-modes/dist/modes/interactive/components/gsd-progress-state.d.ts +2 -0
  719. package/packages/gsd-agent-modes/dist/modes/interactive/components/gsd-progress-state.d.ts.map +1 -0
  720. package/packages/gsd-agent-modes/dist/modes/interactive/components/gsd-progress-state.js +4 -0
  721. package/packages/gsd-agent-modes/dist/modes/interactive/components/gsd-progress-state.js.map +1 -0
  722. package/packages/gsd-agent-modes/dist/modes/interactive/components/gsd-status-widget.d.ts +23 -0
  723. package/packages/gsd-agent-modes/dist/modes/interactive/components/gsd-status-widget.d.ts.map +1 -0
  724. package/packages/gsd-agent-modes/dist/modes/interactive/components/gsd-status-widget.js +178 -0
  725. package/packages/gsd-agent-modes/dist/modes/interactive/components/gsd-status-widget.js.map +1 -0
  726. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts +8 -0
  727. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  728. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js +21 -9
  729. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js.map +1 -1
  730. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  731. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  732. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js +10 -0
  733. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js.map +1 -1
  734. package/packages/gsd-agent-modes/dist/modes/interactive/components/skill-invocation-message.d.ts +2 -3
  735. package/packages/gsd-agent-modes/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  736. package/packages/gsd-agent-modes/dist/modes/interactive/components/skill-invocation-message.js +2 -3
  737. package/packages/gsd-agent-modes/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  738. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +16 -0
  739. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  740. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +93 -19
  741. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  742. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts +71 -3
  743. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
  744. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +257 -37
  745. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
  746. package/packages/gsd-agent-modes/dist/modes/interactive/components/user-message.d.ts +3 -3
  747. package/packages/gsd-agent-modes/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  748. package/packages/gsd-agent-modes/dist/modes/interactive/components/user-message.js +19 -19
  749. package/packages/gsd-agent-modes/dist/modes/interactive/components/user-message.js.map +1 -1
  750. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts +3 -0
  751. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  752. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +157 -56
  753. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  754. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/extension-ui-controller.d.ts.map +1 -1
  755. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/extension-ui-controller.js +12 -1
  756. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/extension-ui-controller.js.map +1 -1
  757. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  758. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +13 -1
  759. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  760. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-autocomplete.d.ts.map +1 -1
  761. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-autocomplete.js +3 -1
  762. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-autocomplete.js.map +1 -1
  763. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.d.ts.map +1 -1
  764. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js +14 -6
  765. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js.map +1 -1
  766. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-dialogs.js +2 -2
  767. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-dialogs.js.map +1 -1
  768. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.d.ts +1 -0
  769. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.d.ts.map +1 -1
  770. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.js +31 -0
  771. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.js.map +1 -1
  772. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-key-handlers.d.ts.map +1 -1
  773. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-key-handlers.js +1 -0
  774. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-key-handlers.js.map +1 -1
  775. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-init.d.ts +1 -0
  776. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-init.d.ts.map +1 -1
  777. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-init.js +20 -49
  778. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-init.js.map +1 -1
  779. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts +4 -0
  780. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  781. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  782. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts +10 -2
  783. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  784. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +48 -6
  785. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
  786. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
  787. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +4 -4
  788. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
  789. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.d.ts.map +1 -1
  790. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js +4 -0
  791. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js.map +1 -1
  792. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-ui-messaging.d.ts.map +1 -1
  793. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-ui-messaging.js +0 -1
  794. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-ui-messaging.js.map +1 -1
  795. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  796. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +6 -1
  797. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
  798. package/packages/gsd-agent-modes/package.json +7 -7
  799. package/packages/mcp-server/README.md +23 -4
  800. package/packages/mcp-server/dist/cli-errors.d.ts +11 -0
  801. package/packages/mcp-server/dist/cli-errors.d.ts.map +1 -1
  802. package/packages/mcp-server/dist/cli-errors.js +12 -0
  803. package/packages/mcp-server/dist/cli-errors.js.map +1 -1
  804. package/packages/mcp-server/dist/cli-runner.d.ts +40 -0
  805. package/packages/mcp-server/dist/cli-runner.d.ts.map +1 -0
  806. package/packages/mcp-server/dist/cli-runner.js +170 -0
  807. package/packages/mcp-server/dist/cli-runner.js.map +1 -0
  808. package/packages/mcp-server/dist/cli.d.ts +1 -0
  809. package/packages/mcp-server/dist/cli.d.ts.map +1 -1
  810. package/packages/mcp-server/dist/cli.js +3 -50
  811. package/packages/mcp-server/dist/cli.js.map +1 -1
  812. package/packages/mcp-server/dist/moonshot-tool-schema.d.ts +29 -0
  813. package/packages/mcp-server/dist/moonshot-tool-schema.d.ts.map +1 -0
  814. package/packages/mcp-server/dist/moonshot-tool-schema.js +50 -0
  815. package/packages/mcp-server/dist/moonshot-tool-schema.js.map +1 -0
  816. package/packages/mcp-server/dist/pid-registry.d.ts +46 -0
  817. package/packages/mcp-server/dist/pid-registry.d.ts.map +1 -0
  818. package/packages/mcp-server/dist/pid-registry.js +459 -0
  819. package/packages/mcp-server/dist/pid-registry.js.map +1 -0
  820. package/packages/mcp-server/dist/probe-mode.d.ts +4 -0
  821. package/packages/mcp-server/dist/probe-mode.d.ts.map +1 -0
  822. package/packages/mcp-server/dist/probe-mode.js +10 -0
  823. package/packages/mcp-server/dist/probe-mode.js.map +1 -0
  824. package/packages/mcp-server/dist/server.d.ts +40 -1
  825. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  826. package/packages/mcp-server/dist/server.js +97 -6
  827. package/packages/mcp-server/dist/server.js.map +1 -1
  828. package/packages/mcp-server/dist/stdio-watchdog.d.ts +8 -0
  829. package/packages/mcp-server/dist/stdio-watchdog.d.ts.map +1 -0
  830. package/packages/mcp-server/dist/stdio-watchdog.js +40 -0
  831. package/packages/mcp-server/dist/stdio-watchdog.js.map +1 -0
  832. package/packages/mcp-server/dist/workflow-tools.d.ts +62 -1
  833. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  834. package/packages/mcp-server/dist/workflow-tools.js +243 -123
  835. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  836. package/packages/mcp-server/package.json +21 -4
  837. package/packages/native/package.json +1 -1
  838. package/packages/pi-agent-core/dist/agent-loop.js +52 -2
  839. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  840. package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts +1 -0
  841. package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts.map +1 -1
  842. package/packages/pi-agent-core/dist/harness/env/nodejs.js +34 -3
  843. package/packages/pi-agent-core/dist/harness/env/nodejs.js.map +1 -1
  844. package/packages/pi-agent-core/dist/index.d.ts +1 -0
  845. package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
  846. package/packages/pi-agent-core/dist/index.js +3 -0
  847. package/packages/pi-agent-core/dist/index.js.map +1 -1
  848. package/packages/pi-agent-core/package.json +1 -1
  849. package/packages/pi-ai/README.md +1 -0
  850. package/packages/pi-ai/dist/index.d.ts +2 -0
  851. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  852. package/packages/pi-ai/dist/index.js +2 -0
  853. package/packages/pi-ai/dist/index.js.map +1 -1
  854. package/packages/pi-ai/dist/models.generated.d.ts +183 -76
  855. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  856. package/packages/pi-ai/dist/models.generated.js +205 -124
  857. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  858. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  859. package/packages/pi-ai/dist/providers/anthropic.js +12 -7
  860. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  861. package/packages/pi-ai/dist/providers/google-shared.d.ts +5 -0
  862. package/packages/pi-ai/dist/providers/google-shared.d.ts.map +1 -1
  863. package/packages/pi-ai/dist/providers/google-shared.js +12 -3
  864. package/packages/pi-ai/dist/providers/google-shared.js.map +1 -1
  865. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  866. package/packages/pi-ai/dist/providers/openai-completions.js +7 -3
  867. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  868. package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts +9 -0
  869. package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts.map +1 -0
  870. package/packages/pi-ai/dist/utils/moonshot-tool-schema.js +34 -0
  871. package/packages/pi-ai/dist/utils/moonshot-tool-schema.js.map +1 -0
  872. package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
  873. package/packages/pi-ai/dist/utils/oauth/github-copilot.js +6 -2
  874. package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
  875. package/packages/pi-ai/package.json +3 -2
  876. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +2 -2
  877. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  878. package/packages/pi-coding-agent/dist/core/auth-storage.js +19 -13
  879. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  880. package/packages/pi-coding-agent/dist/core/capability-patches.d.ts.map +1 -1
  881. package/packages/pi-coding-agent/dist/core/capability-patches.js +3 -1
  882. package/packages/pi-coding-agent/dist/core/capability-patches.js.map +1 -1
  883. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts +28 -2
  884. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts.map +1 -1
  885. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.js.map +1 -1
  886. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +1 -1
  887. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
  888. package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
  889. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +5 -1
  890. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  891. package/packages/pi-coding-agent/dist/core/extensions/runner.js +3 -1
  892. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  893. package/packages/pi-coding-agent/dist/core/provider-readiness.d.ts.map +1 -1
  894. package/packages/pi-coding-agent/dist/core/provider-readiness.js +13 -6
  895. package/packages/pi-coding-agent/dist/core/provider-readiness.js.map +1 -1
  896. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
  897. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  898. package/packages/pi-coding-agent/dist/core/settings-manager.js +11 -0
  899. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  900. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts +11 -0
  901. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
  902. package/packages/pi-coding-agent/dist/core/tools/bash.js +53 -11
  903. package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
  904. package/packages/pi-coding-agent/dist/index.d.ts +2 -2
  905. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  906. package/packages/pi-coding-agent/dist/index.js +1 -1
  907. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  908. package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
  909. package/packages/pi-coding-agent/dist/theme/theme.js +45 -17
  910. package/packages/pi-coding-agent/dist/theme/theme.js.map +1 -1
  911. package/packages/pi-coding-agent/dist/utils/shell.d.ts +28 -2
  912. package/packages/pi-coding-agent/dist/utils/shell.d.ts.map +1 -1
  913. package/packages/pi-coding-agent/dist/utils/shell.js +56 -10
  914. package/packages/pi-coding-agent/dist/utils/shell.js.map +1 -1
  915. package/packages/pi-coding-agent/package.json +8 -8
  916. package/packages/pi-tui/README.md +15 -0
  917. package/packages/pi-tui/dist/autocomplete.d.ts.map +1 -1
  918. package/packages/pi-tui/dist/autocomplete.js +6 -1
  919. package/packages/pi-tui/dist/autocomplete.js.map +1 -1
  920. package/packages/pi-tui/dist/components/input.js +2 -2
  921. package/packages/pi-tui/dist/components/input.js.map +1 -1
  922. package/packages/pi-tui/dist/components/loader.d.ts.map +1 -1
  923. package/packages/pi-tui/dist/components/loader.js +1 -0
  924. package/packages/pi-tui/dist/components/loader.js.map +1 -1
  925. package/packages/pi-tui/dist/components/select-list.d.ts.map +1 -1
  926. package/packages/pi-tui/dist/components/select-list.js +8 -2
  927. package/packages/pi-tui/dist/components/select-list.js.map +1 -1
  928. package/packages/pi-tui/dist/index.d.ts +2 -2
  929. package/packages/pi-tui/dist/index.d.ts.map +1 -1
  930. package/packages/pi-tui/dist/index.js +2 -2
  931. package/packages/pi-tui/dist/index.js.map +1 -1
  932. package/packages/pi-tui/dist/keys.d.ts.map +1 -1
  933. package/packages/pi-tui/dist/keys.js +39 -30
  934. package/packages/pi-tui/dist/keys.js.map +1 -1
  935. package/packages/pi-tui/dist/stdin-buffer.d.ts.map +1 -1
  936. package/packages/pi-tui/dist/stdin-buffer.js +22 -0
  937. package/packages/pi-tui/dist/stdin-buffer.js.map +1 -1
  938. package/packages/pi-tui/dist/terminal-image.d.ts +33 -0
  939. package/packages/pi-tui/dist/terminal-image.d.ts.map +1 -1
  940. package/packages/pi-tui/dist/terminal-image.js +54 -2
  941. package/packages/pi-tui/dist/terminal-image.js.map +1 -1
  942. package/packages/pi-tui/dist/terminal.d.ts +12 -0
  943. package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
  944. package/packages/pi-tui/dist/terminal.js +70 -25
  945. package/packages/pi-tui/dist/terminal.js.map +1 -1
  946. package/packages/pi-tui/dist/tui.d.ts +15 -0
  947. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  948. package/packages/pi-tui/dist/tui.js +115 -21
  949. package/packages/pi-tui/dist/tui.js.map +1 -1
  950. package/packages/pi-tui/dist/utils.d.ts.map +1 -1
  951. package/packages/pi-tui/dist/utils.js +110 -36
  952. package/packages/pi-tui/dist/utils.js.map +1 -1
  953. package/packages/pi-tui/package.json +2 -2
  954. package/packages/rpc-client/package.json +2 -2
  955. package/pkg/dist/theme/theme.d.ts.map +1 -1
  956. package/pkg/dist/theme/theme.js +45 -17
  957. package/pkg/dist/theme/theme.js.map +1 -1
  958. package/pkg/package.json +1 -1
  959. package/scripts/install/deps.js +10 -0
  960. package/scripts/link-workspace-packages.cjs +7 -40
  961. package/src/resources/GSD-WORKFLOW.md +27 -26
  962. package/src/resources/extensions/ask-user-questions.ts +94 -26
  963. package/src/resources/extensions/async-jobs/async-bash-cancel.test.ts +360 -0
  964. package/src/resources/extensions/async-jobs/async-bash-tool.ts +33 -56
  965. package/src/resources/extensions/async-jobs/await-tool.test.ts +139 -0
  966. package/src/resources/extensions/async-jobs/await-tool.ts +82 -12
  967. package/src/resources/extensions/async-jobs/index.ts +79 -0
  968. package/src/resources/extensions/async-jobs/job-manager.ts +21 -1
  969. package/src/resources/extensions/bg-shell/bg-shell-command.ts +6 -6
  970. package/src/resources/extensions/bg-shell/bg-shell-tool.ts +10 -6
  971. package/src/resources/extensions/bg-shell/overlay.ts +9 -5
  972. package/src/resources/extensions/bg-shell/process-manager.ts +50 -25
  973. package/src/resources/extensions/bg-shell/readiness-detector.ts +12 -0
  974. package/src/resources/extensions/bg-shell/tests/lifecycle-and-utilities.test.ts +48 -1
  975. package/src/resources/extensions/bg-shell/utilities.ts +5 -2
  976. package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +265 -98
  977. package/src/resources/extensions/browser-tools/engine/selection.ts +90 -4
  978. package/src/resources/extensions/browser-tools/index.ts +71 -13
  979. package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +83 -13
  980. package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +120 -1
  981. package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +136 -0
  982. package/src/resources/extensions/claude-code-cli/index.ts +8 -1
  983. package/src/resources/extensions/claude-code-cli/models.ts +9 -0
  984. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +744 -495
  985. package/src/resources/extensions/claude-code-cli/tests/index.test.ts +47 -0
  986. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +1192 -7
  987. package/src/resources/extensions/claude-code-cli/turn-assembler.ts +324 -0
  988. package/src/resources/extensions/github-sync/templates.ts +3 -3
  989. package/src/resources/extensions/github-sync/tests/templates.test.ts +2 -2
  990. package/src/resources/extensions/google-cli/stream-adapter.ts +128 -20
  991. package/src/resources/extensions/gsd/artifact-projection.ts +31 -0
  992. package/src/resources/extensions/gsd/auto/closeout.ts +309 -0
  993. package/src/resources/extensions/gsd/auto/contracts.ts +32 -2
  994. package/src/resources/extensions/gsd/auto/custom-verify-retry-store.ts +21 -3
  995. package/src/resources/extensions/gsd/auto/detect-stuck.ts +32 -9
  996. package/src/resources/extensions/gsd/auto/dispatch-history.ts +186 -0
  997. package/src/resources/extensions/gsd/auto/dispatch-key.ts +39 -0
  998. package/src/resources/extensions/gsd/auto/dispatch.ts +449 -0
  999. package/src/resources/extensions/gsd/auto/finalize.ts +445 -0
  1000. package/src/resources/extensions/gsd/auto/loop-deps.ts +3 -1
  1001. package/src/resources/extensions/gsd/auto/loop.ts +158 -63
  1002. package/src/resources/extensions/gsd/auto/milestone-lease-reclaim.ts +74 -0
  1003. package/src/resources/extensions/gsd/auto/orchestrator.ts +418 -82
  1004. package/src/resources/extensions/gsd/auto/phase-helpers.ts +199 -0
  1005. package/src/resources/extensions/gsd/auto/phases.ts +58 -2981
  1006. package/src/resources/extensions/gsd/auto/pre-dispatch.ts +716 -0
  1007. package/src/resources/extensions/gsd/auto/run-unit.ts +2 -1
  1008. package/src/resources/extensions/gsd/auto/session.ts +7 -0
  1009. package/src/resources/extensions/gsd/auto/unit-phase.ts +910 -0
  1010. package/src/resources/extensions/gsd/auto/workflow-kernel.ts +25 -3
  1011. package/src/resources/extensions/gsd/auto/workflow-unit-dispatch.ts +1 -1
  1012. package/src/resources/extensions/gsd/auto/worktree-safety-phase.ts +149 -0
  1013. package/src/resources/extensions/gsd/auto-artifact-paths.ts +83 -20
  1014. package/src/resources/extensions/gsd/auto-closeout-messaging.ts +90 -0
  1015. package/src/resources/extensions/gsd/auto-dashboard.ts +328 -458
  1016. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +33 -50
  1017. package/src/resources/extensions/gsd/auto-dispatch.ts +144 -98
  1018. package/src/resources/extensions/gsd/auto-model-selection.ts +74 -15
  1019. package/src/resources/extensions/gsd/auto-post-unit.ts +107 -46
  1020. package/src/resources/extensions/gsd/auto-prompts.ts +314 -76
  1021. package/src/resources/extensions/gsd/auto-recovery.ts +183 -87
  1022. package/src/resources/extensions/gsd/auto-runtime-state.ts +39 -0
  1023. package/src/resources/extensions/gsd/auto-start.ts +146 -88
  1024. package/src/resources/extensions/gsd/auto-timers.ts +16 -2
  1025. package/src/resources/extensions/gsd/auto-tool-tracking.ts +54 -0
  1026. package/src/resources/extensions/gsd/auto-unit-closeout.ts +83 -28
  1027. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +21 -49
  1028. package/src/resources/extensions/gsd/auto-verification.ts +37 -42
  1029. package/src/resources/extensions/gsd/auto-worktree-repair.ts +13 -2
  1030. package/src/resources/extensions/gsd/auto-worktree.ts +180 -407
  1031. package/src/resources/extensions/gsd/auto.ts +220 -54
  1032. package/src/resources/extensions/gsd/blocked-models.ts +49 -0
  1033. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +194 -70
  1034. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +35 -38
  1035. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +93 -49
  1036. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +4 -2
  1037. package/src/resources/extensions/gsd/bootstrap/fallback-continuation.ts +31 -0
  1038. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
  1039. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +46 -1
  1040. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +504 -186
  1041. package/src/resources/extensions/gsd/bootstrap/system-context.ts +219 -46
  1042. package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +82 -1
  1043. package/src/resources/extensions/gsd/bootstrap/tool-search-shim.ts +21 -3
  1044. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +586 -83
  1045. package/src/resources/extensions/gsd/branch-patterns.ts +3 -0
  1046. package/src/resources/extensions/gsd/browser-daemon-auto-prep.ts +108 -0
  1047. package/src/resources/extensions/gsd/browser-evidence.ts +18 -2
  1048. package/src/resources/extensions/gsd/captures.ts +5 -16
  1049. package/src/resources/extensions/gsd/closeout-consistency-gate.ts +132 -6
  1050. package/src/resources/extensions/gsd/closeout-recovery.ts +2 -1
  1051. package/src/resources/extensions/gsd/closeout-wizard.ts +111 -0
  1052. package/src/resources/extensions/gsd/codebase-generator.ts +1 -0
  1053. package/src/resources/extensions/gsd/commands/catalog.ts +12 -68
  1054. package/src/resources/extensions/gsd/commands/context.ts +16 -2
  1055. package/src/resources/extensions/gsd/commands/dispatcher.ts +3 -0
  1056. package/src/resources/extensions/gsd/commands/gsd-core-aliases-handler.ts +48 -0
  1057. package/src/resources/extensions/gsd/commands/gsd-core-aliases.ts +63 -0
  1058. package/src/resources/extensions/gsd/commands/handlers/auto.ts +3 -0
  1059. package/src/resources/extensions/gsd/commands/handlers/core.ts +58 -8
  1060. package/src/resources/extensions/gsd/commands/handlers/ops.ts +230 -3
  1061. package/src/resources/extensions/gsd/commands-cmux.ts +3 -0
  1062. package/src/resources/extensions/gsd/commands-context.ts +18 -1
  1063. package/src/resources/extensions/gsd/commands-gsd-core.ts +1142 -0
  1064. package/src/resources/extensions/gsd/commands-handlers.ts +140 -4
  1065. package/src/resources/extensions/gsd/commands-inspect.ts +7 -8
  1066. package/src/resources/extensions/gsd/commands-maintenance.ts +172 -42
  1067. package/src/resources/extensions/gsd/commands-mcp-status.ts +2 -2
  1068. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +27 -9
  1069. package/src/resources/extensions/gsd/commands-ship.ts +2 -2
  1070. package/src/resources/extensions/gsd/commands-verdict.ts +22 -4
  1071. package/src/resources/extensions/gsd/commands-workflow-templates.ts +11 -4
  1072. package/src/resources/extensions/gsd/commands-worktree.ts +12 -10
  1073. package/src/resources/extensions/gsd/compat/compat-marker.ts +210 -0
  1074. package/src/resources/extensions/gsd/compat/index.ts +12 -0
  1075. package/src/resources/extensions/gsd/compat/planning-compat.ts +168 -0
  1076. package/src/resources/extensions/gsd/config-overlay.ts +24 -9
  1077. package/src/resources/extensions/gsd/consent-question.ts +441 -0
  1078. package/src/resources/extensions/gsd/consent-verdict.ts +115 -0
  1079. package/src/resources/extensions/gsd/constants.ts +0 -3
  1080. package/src/resources/extensions/gsd/crash-recovery.ts +13 -11
  1081. package/src/resources/extensions/gsd/dashboard-overlay.ts +73 -7
  1082. package/src/resources/extensions/gsd/db/engine.ts +855 -0
  1083. package/src/resources/extensions/gsd/db/queries.ts +676 -0
  1084. package/src/resources/extensions/gsd/db/sql-constants.ts +12 -0
  1085. package/src/resources/extensions/gsd/db/unit-dispatches.ts +24 -0
  1086. package/src/resources/extensions/gsd/db/writers/cascades.ts +237 -0
  1087. package/src/resources/extensions/gsd/db/writers/import-restore.ts +310 -0
  1088. package/src/resources/extensions/gsd/db/writers/memory.ts +220 -0
  1089. package/src/resources/extensions/gsd/db/writers/reconcile.ts +523 -0
  1090. package/src/resources/extensions/gsd/db/writers/status.ts +88 -0
  1091. package/src/resources/extensions/gsd/db-migration-backup.ts +56 -7
  1092. package/src/resources/extensions/gsd/db-transaction.ts +37 -20
  1093. package/src/resources/extensions/gsd/db-workspace.ts +185 -0
  1094. package/src/resources/extensions/gsd/db-writer.ts +11 -19
  1095. package/src/resources/extensions/gsd/delegation-policy.ts +3 -11
  1096. package/src/resources/extensions/gsd/discussion-handoff.ts +280 -0
  1097. package/src/resources/extensions/gsd/dispatch-guard.ts +8 -31
  1098. package/src/resources/extensions/gsd/docs/preferences-reference.md +9 -0
  1099. package/src/resources/extensions/gsd/doctor-engine-checks.ts +5 -4
  1100. package/src/resources/extensions/gsd/doctor-environment.ts +272 -155
  1101. package/src/resources/extensions/gsd/doctor-format.ts +12 -7
  1102. package/src/resources/extensions/gsd/doctor-git-checks.ts +33 -25
  1103. package/src/resources/extensions/gsd/doctor-providers.ts +104 -10
  1104. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +34 -42
  1105. package/src/resources/extensions/gsd/doctor-types.ts +1 -0
  1106. package/src/resources/extensions/gsd/doctor.ts +45 -12
  1107. package/src/resources/extensions/gsd/engine-hook-contract.ts +79 -0
  1108. package/src/resources/extensions/gsd/error-classifier.ts +25 -1
  1109. package/src/resources/extensions/gsd/escalation.ts +9 -4
  1110. package/src/resources/extensions/gsd/exec-sandbox.ts +98 -18
  1111. package/src/resources/extensions/gsd/export-html.ts +11 -4
  1112. package/src/resources/extensions/gsd/export.ts +88 -1
  1113. package/src/resources/extensions/gsd/file-lock.ts +1 -1
  1114. package/src/resources/extensions/gsd/files.ts +33 -12
  1115. package/src/resources/extensions/gsd/flat-phase-migration.ts +205 -0
  1116. package/src/resources/extensions/gsd/forensics.ts +4 -34
  1117. package/src/resources/extensions/gsd/git-conflict-state.ts +17 -1
  1118. package/src/resources/extensions/gsd/git-constants.ts +1 -1
  1119. package/src/resources/extensions/gsd/git-service.ts +13 -7
  1120. package/src/resources/extensions/gsd/gitignore.ts +10 -3
  1121. package/src/resources/extensions/gsd/gsd-command-home.ts +13 -3
  1122. package/src/resources/extensions/gsd/gsd-db.ts +189 -2380
  1123. package/src/resources/extensions/gsd/guidance.ts +217 -0
  1124. package/src/resources/extensions/gsd/guided-flow-queue.ts +82 -4
  1125. package/src/resources/extensions/gsd/guided-flow.ts +250 -590
  1126. package/src/resources/extensions/gsd/guided-unit-completion.ts +275 -0
  1127. package/src/resources/extensions/gsd/health-widget.ts +133 -32
  1128. package/src/resources/extensions/gsd/layout-policy.ts +85 -0
  1129. package/src/resources/extensions/gsd/markdown-renderer.ts +423 -106
  1130. package/src/resources/extensions/gsd/mcp-bridge.ts +39 -0
  1131. package/src/resources/extensions/gsd/mcp-filter.ts +63 -34
  1132. package/src/resources/extensions/gsd/mcp-tool-name.ts +30 -0
  1133. package/src/resources/extensions/gsd/md-importer.ts +218 -68
  1134. package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +52 -20
  1135. package/src/resources/extensions/gsd/memory-relations.ts +1 -1
  1136. package/src/resources/extensions/gsd/metrics.ts +23 -10
  1137. package/src/resources/extensions/gsd/migrate/layout-detect.ts +38 -0
  1138. package/src/resources/extensions/gsd/migrate/planning-writer.ts +259 -0
  1139. package/src/resources/extensions/gsd/migrate/safety.ts +20 -9
  1140. package/src/resources/extensions/gsd/migrate-external.ts +49 -6
  1141. package/src/resources/extensions/gsd/migration-auto-check.ts +34 -18
  1142. package/src/resources/extensions/gsd/milestone-actions.ts +5 -2
  1143. package/src/resources/extensions/gsd/milestone-closeout-proof.ts +131 -0
  1144. package/src/resources/extensions/gsd/milestone-closeout.ts +133 -29
  1145. package/src/resources/extensions/gsd/milestone-ids.ts +49 -19
  1146. package/src/resources/extensions/gsd/milestone-implementation-evidence.ts +35 -21
  1147. package/src/resources/extensions/gsd/milestone-merge-transaction.ts +47 -0
  1148. package/src/resources/extensions/gsd/milestone-planning-persistence.ts +232 -0
  1149. package/src/resources/extensions/gsd/milestone-readiness.ts +125 -0
  1150. package/src/resources/extensions/gsd/milestone-reopen-events.ts +3 -6
  1151. package/src/resources/extensions/gsd/milestone-settlement.ts +81 -0
  1152. package/src/resources/extensions/gsd/milestone-validation-evidence.ts +95 -0
  1153. package/src/resources/extensions/gsd/milestone-validation-verdict.ts +78 -0
  1154. package/src/resources/extensions/gsd/model-cost-table.ts +1 -0
  1155. package/src/resources/extensions/gsd/model-router.ts +101 -18
  1156. package/src/resources/extensions/gsd/native-git-bridge.ts +39 -0
  1157. package/src/resources/extensions/gsd/notification-store.ts +43 -31
  1158. package/src/resources/extensions/gsd/notifications.ts +50 -12
  1159. package/src/resources/extensions/gsd/observability-validator.ts +12 -4
  1160. package/src/resources/extensions/gsd/parallel-eligibility.ts +4 -5
  1161. package/src/resources/extensions/gsd/parallel-merge.ts +12 -9
  1162. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +161 -38
  1163. package/src/resources/extensions/gsd/parallel-orchestrator.ts +6 -2
  1164. package/src/resources/extensions/gsd/parsers-legacy.ts +58 -19
  1165. package/src/resources/extensions/gsd/paths.ts +390 -61
  1166. package/src/resources/extensions/gsd/planning-depth.ts +2 -1
  1167. package/src/resources/extensions/gsd/post-execution-checks.ts +43 -3
  1168. package/src/resources/extensions/gsd/pre-execution-checks.ts +109 -3
  1169. package/src/resources/extensions/gsd/preferences-diagnostics.ts +98 -0
  1170. package/src/resources/extensions/gsd/preferences-models.ts +58 -59
  1171. package/src/resources/extensions/gsd/preferences-types.ts +16 -0
  1172. package/src/resources/extensions/gsd/preferences.ts +372 -35
  1173. package/src/resources/extensions/gsd/projection-flush.ts +20 -0
  1174. package/src/resources/extensions/gsd/prompts/ai-integration-phase.md +28 -0
  1175. package/src/resources/extensions/gsd/prompts/audit-fix.md +39 -0
  1176. package/src/resources/extensions/gsd/prompts/audit-milestone.md +26 -0
  1177. package/src/resources/extensions/gsd/prompts/audit-uat.md +24 -0
  1178. package/src/resources/extensions/gsd/prompts/autonomous.md +31 -0
  1179. package/src/resources/extensions/gsd/prompts/code-review.md +37 -0
  1180. package/src/resources/extensions/gsd/prompts/complete-milestone.md +8 -2
  1181. package/src/resources/extensions/gsd/prompts/complete-slice.md +25 -15
  1182. package/src/resources/extensions/gsd/prompts/discuss-phase.md +31 -0
  1183. package/src/resources/extensions/gsd/prompts/docs-update.md +13 -0
  1184. package/src/resources/extensions/gsd/prompts/execute-phase.md +33 -0
  1185. package/src/resources/extensions/gsd/prompts/execute-task.md +9 -2
  1186. package/src/resources/extensions/gsd/prompts/explore.md +58 -0
  1187. package/src/resources/extensions/gsd/prompts/graphify.md +27 -0
  1188. package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +3 -1
  1189. package/src/resources/extensions/gsd/prompts/health.md +37 -0
  1190. package/src/resources/extensions/gsd/prompts/import.md +30 -0
  1191. package/src/resources/extensions/gsd/prompts/inbox.md +27 -0
  1192. package/src/resources/extensions/gsd/prompts/ingest-docs.md +30 -0
  1193. package/src/resources/extensions/gsd/prompts/manager.md +21 -0
  1194. package/src/resources/extensions/gsd/prompts/map-codebase.md +42 -0
  1195. package/src/resources/extensions/gsd/prompts/milestone-summary.md +27 -0
  1196. package/src/resources/extensions/gsd/prompts/mvp-phase.md +23 -0
  1197. package/src/resources/extensions/gsd/prompts/pause-work.md +24 -0
  1198. package/src/resources/extensions/gsd/prompts/phase.md +22 -0
  1199. package/src/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
  1200. package/src/resources/extensions/gsd/prompts/plan-phase.md +34 -0
  1201. package/src/resources/extensions/gsd/prompts/plan-review-convergence.md +34 -0
  1202. package/src/resources/extensions/gsd/prompts/plan-slice.md +3 -2
  1203. package/src/resources/extensions/gsd/prompts/profile-user.md +28 -0
  1204. package/src/resources/extensions/gsd/prompts/progress.md +30 -0
  1205. package/src/resources/extensions/gsd/prompts/quick-task.md +1 -1
  1206. package/src/resources/extensions/gsd/prompts/reactive-execute.md +2 -2
  1207. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  1208. package/src/resources/extensions/gsd/prompts/refine-slice.md +3 -2
  1209. package/src/resources/extensions/gsd/prompts/replan-slice.md +2 -2
  1210. package/src/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  1211. package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
  1212. package/src/resources/extensions/gsd/prompts/resume-work.md +20 -0
  1213. package/src/resources/extensions/gsd/prompts/review-backlog.md +21 -0
  1214. package/src/resources/extensions/gsd/prompts/review.md +27 -0
  1215. package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  1216. package/src/resources/extensions/gsd/prompts/run-uat.md +13 -5
  1217. package/src/resources/extensions/gsd/prompts/secure-phase.md +24 -0
  1218. package/src/resources/extensions/gsd/prompts/settings.md +24 -0
  1219. package/src/resources/extensions/gsd/prompts/sketch.md +59 -0
  1220. package/src/resources/extensions/gsd/prompts/spec-phase.md +29 -0
  1221. package/src/resources/extensions/gsd/prompts/spike.md +59 -0
  1222. package/src/resources/extensions/gsd/prompts/stats.md +43 -0
  1223. package/src/resources/extensions/gsd/prompts/surface.md +25 -0
  1224. package/src/resources/extensions/gsd/prompts/system.md +6 -3
  1225. package/src/resources/extensions/gsd/prompts/thread.md +24 -0
  1226. package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -1
  1227. package/src/resources/extensions/gsd/prompts/ui-phase.md +29 -0
  1228. package/src/resources/extensions/gsd/prompts/ui-review.md +29 -0
  1229. package/src/resources/extensions/gsd/prompts/ultraplan-phase.md +24 -0
  1230. package/src/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
  1231. package/src/resources/extensions/gsd/prompts/validate-phase.md +26 -0
  1232. package/src/resources/extensions/gsd/prompts/verify-work.md +24 -0
  1233. package/src/resources/extensions/gsd/prompts/workflow-start.md +2 -1
  1234. package/src/resources/extensions/gsd/prompts/workspace.md +22 -0
  1235. package/src/resources/extensions/gsd/prompts/workstreams.md +24 -0
  1236. package/src/resources/extensions/gsd/provider-error-guidance.ts +36 -9
  1237. package/src/resources/extensions/gsd/provider-payload-policy.ts +140 -0
  1238. package/src/resources/extensions/gsd/provider-switch-observer.ts +1 -1
  1239. package/src/resources/extensions/gsd/publication.ts +122 -0
  1240. package/src/resources/extensions/gsd/pull-request-process.ts +41 -0
  1241. package/src/resources/extensions/gsd/quality-gate-closure.ts +140 -0
  1242. package/src/resources/extensions/gsd/question-transport.ts +138 -0
  1243. package/src/resources/extensions/gsd/queue-order.ts +3 -2
  1244. package/src/resources/extensions/gsd/quick.ts +43 -2
  1245. package/src/resources/extensions/gsd/reactive-graph.ts +11 -1
  1246. package/src/resources/extensions/gsd/recovery-classification.ts +54 -88
  1247. package/src/resources/extensions/gsd/roadmap-slices.ts +37 -6
  1248. package/src/resources/extensions/gsd/safety/content-validator.ts +2 -1
  1249. package/src/resources/extensions/gsd/safety/destructive-confirmation.ts +134 -0
  1250. package/src/resources/extensions/gsd/safety/evidence-collector.ts +36 -4
  1251. package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +52 -3
  1252. package/src/resources/extensions/gsd/safety/file-change-validator.ts +14 -0
  1253. package/src/resources/extensions/gsd/service-tier.ts +2 -0
  1254. package/src/resources/extensions/gsd/session-forensics.ts +11 -1
  1255. package/src/resources/extensions/gsd/session-lock.ts +16 -14
  1256. package/src/resources/extensions/gsd/skill-activation.ts +3 -6
  1257. package/src/resources/extensions/gsd/skills/gsd-headless/SKILL.md +3 -0
  1258. package/src/resources/extensions/gsd/skills/gsd-headless/references/commands.md +51 -0
  1259. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +6 -2
  1260. package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +58 -14
  1261. package/src/resources/extensions/gsd/state-reconciliation/drift/completion.ts +22 -2
  1262. package/src/resources/extensions/gsd/state-reconciliation/drift/external-markdown-edit.ts +105 -0
  1263. package/src/resources/extensions/gsd/state-reconciliation/drift/external-planning-edit.ts +180 -0
  1264. package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +19 -6
  1265. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +2 -2
  1266. package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +169 -29
  1267. package/src/resources/extensions/gsd/state-reconciliation/index.ts +36 -3
  1268. package/src/resources/extensions/gsd/state-reconciliation/registry.ts +12 -0
  1269. package/src/resources/extensions/gsd/state-reconciliation/types.ts +19 -0
  1270. package/src/resources/extensions/gsd/state-transition-matrix.ts +42 -0
  1271. package/src/resources/extensions/gsd/state.ts +87 -41
  1272. package/src/resources/extensions/gsd/status-guards.ts +59 -8
  1273. package/src/resources/extensions/gsd/stop-notice.ts +75 -0
  1274. package/src/resources/extensions/gsd/sync-lock.ts +11 -20
  1275. package/src/resources/extensions/gsd/templates/plan.md +7 -0
  1276. package/src/resources/extensions/gsd/templates/project.md +1 -0
  1277. package/src/resources/extensions/gsd/templates/roadmap.md +1 -1
  1278. package/src/resources/extensions/gsd/templates/uat.md +5 -1
  1279. package/src/resources/extensions/gsd/tests/__fixtures__/flat-phase/.gsd/phases/01-foundation/01-01-PLAN.md +13 -0
  1280. package/src/resources/extensions/gsd/tests/__fixtures__/flat-phase/.gsd/phases/01-foundation/01-ROADMAP.md +8 -0
  1281. package/src/resources/extensions/gsd/tests/__fixtures__/round-trip/m001-basic/.gsd/milestones/M001/M001-ROADMAP.md +13 -0
  1282. package/src/resources/extensions/gsd/tests/__fixtures__/round-trip/m001-basic/.gsd/milestones/M001/slices/S01/S01-PLAN.md +5 -0
  1283. package/src/resources/extensions/gsd/tests/__fixtures__/round-trip/planning-flat-phases/.planning/PROJECT.md +1 -0
  1284. package/src/resources/extensions/gsd/tests/__fixtures__/round-trip/planning-flat-phases/.planning/ROADMAP.md +5 -0
  1285. package/src/resources/extensions/gsd/tests/__fixtures__/round-trip/planning-flat-phases/.planning/STATE.md +10 -0
  1286. package/src/resources/extensions/gsd/tests/__fixtures__/round-trip/planning-flat-phases/.planning/phases/01-foundation/01-01-PLAN.md +13 -0
  1287. package/src/resources/extensions/gsd/tests/ask-user-questions-render.test.ts +92 -0
  1288. package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +1 -1
  1289. package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +322 -1
  1290. package/src/resources/extensions/gsd/tests/auto-blocked-remediation-message.test.ts +1 -1
  1291. package/src/resources/extensions/gsd/tests/auto-closeout-messaging.test.ts +71 -0
  1292. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +97 -117
  1293. package/src/resources/extensions/gsd/tests/auto-direct-dispatch-parse.test.ts +33 -0
  1294. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +753 -26
  1295. package/src/resources/extensions/gsd/tests/auto-migrating-recovery.test.ts +32 -1
  1296. package/src/resources/extensions/gsd/tests/auto-milestone-target.test.ts +23 -0
  1297. package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +25 -2
  1298. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +107 -1
  1299. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +409 -38
  1300. package/src/resources/extensions/gsd/tests/auto-pause-double-entry-guard.test.ts +1 -1
  1301. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +11 -2
  1302. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +100 -5
  1303. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +2 -1
  1304. package/src/resources/extensions/gsd/tests/auto-post-unit-evidence-crossref-4909.test.ts +46 -0
  1305. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +111 -1
  1306. package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +65 -3
  1307. package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +34 -0
  1308. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +236 -0
  1309. package/src/resources/extensions/gsd/tests/auto-unit-closeout.test.ts +169 -1
  1310. package/src/resources/extensions/gsd/tests/auto-verification.test.ts +36 -0
  1311. package/src/resources/extensions/gsd/tests/auto-worktree-auto-resolve.test.ts +17 -0
  1312. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +2 -2
  1313. package/src/resources/extensions/gsd/tests/auto-worktree-repair.test.ts +4 -2
  1314. package/src/resources/extensions/gsd/tests/blocked-models.test.ts +19 -0
  1315. package/src/resources/extensions/gsd/tests/blocker-placeholder-logs.test.ts +218 -0
  1316. package/src/resources/extensions/gsd/tests/browser-automation-contract-fixture.ts +39 -0
  1317. package/src/resources/extensions/gsd/tests/browser-contract.test.ts +44 -0
  1318. package/src/resources/extensions/gsd/tests/browser-daemon-auto-prep.test.ts +144 -0
  1319. package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +20 -0
  1320. package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +66 -1
  1321. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +44 -0
  1322. package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +26 -0
  1323. package/src/resources/extensions/gsd/tests/commands-context.test.ts +26 -0
  1324. package/src/resources/extensions/gsd/tests/commands-dispatcher-unmerged-milestone.test.ts +89 -0
  1325. package/src/resources/extensions/gsd/tests/commands-dispatcher-validation-block.test.ts +37 -1
  1326. package/src/resources/extensions/gsd/tests/commands-dispatcher-workspace-git.test.ts +11 -0
  1327. package/src/resources/extensions/gsd/tests/commands-eval-review.test.ts +31 -30
  1328. package/src/resources/extensions/gsd/tests/commands-gsd-core.test.ts +862 -0
  1329. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +47 -9
  1330. package/src/resources/extensions/gsd/tests/commands-worktree-clean.test.ts +80 -0
  1331. package/src/resources/extensions/gsd/tests/compat-health-line.test.ts +102 -0
  1332. package/src/resources/extensions/gsd/tests/compat-marker-invalidation.test.ts +51 -0
  1333. package/src/resources/extensions/gsd/tests/compat-marker.test.ts +105 -0
  1334. package/src/resources/extensions/gsd/tests/complete-milestone-prompt-rendering.test.ts +6 -2
  1335. package/src/resources/extensions/gsd/tests/complete-slice-reopen-handoff.test.ts +82 -0
  1336. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
  1337. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +18 -7
  1338. package/src/resources/extensions/gsd/tests/complete-task-rollback-evidence.test.ts +48 -8
  1339. package/src/resources/extensions/gsd/tests/complete-task.test.ts +223 -12
  1340. package/src/resources/extensions/gsd/tests/consent-question.test.ts +396 -0
  1341. package/src/resources/extensions/gsd/tests/core-overlay-fallback.test.ts +1 -0
  1342. package/src/resources/extensions/gsd/tests/custom-verify-retry-store.test.ts +67 -0
  1343. package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +90 -0
  1344. package/src/resources/extensions/gsd/tests/db-authority-regression.test.ts +1 -1
  1345. package/src/resources/extensions/gsd/tests/db-engine-logs.test.ts +207 -0
  1346. package/src/resources/extensions/gsd/tests/db-migration-backup.test.ts +68 -19
  1347. package/src/resources/extensions/gsd/tests/db-transaction.test.ts +59 -0
  1348. package/src/resources/extensions/gsd/tests/db-writer.test.ts +15 -4
  1349. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +12 -11
  1350. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +63 -1
  1351. package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +111 -5
  1352. package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +303 -0
  1353. package/src/resources/extensions/gsd/tests/discuss-cold-start-db-open.test.ts +10 -27
  1354. package/src/resources/extensions/gsd/tests/discuss-routing-fixes.test.ts +12 -2
  1355. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +54 -4
  1356. package/src/resources/extensions/gsd/tests/dispatch-db-degradation-logs.test.ts +98 -0
  1357. package/src/resources/extensions/gsd/tests/dispatch-history.test.ts +430 -0
  1358. package/src/resources/extensions/gsd/tests/dispatch-logs.test.ts +103 -0
  1359. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +38 -49
  1360. package/src/resources/extensions/gsd/tests/dispatch-reactive-logs.test.ts +98 -0
  1361. package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +26 -1
  1362. package/src/resources/extensions/gsd/tests/dispatch-run-uat-browser-tools.test.ts +89 -0
  1363. package/src/resources/extensions/gsd/tests/dist-redirect.mjs +15 -0
  1364. package/src/resources/extensions/gsd/tests/doctor-forensics-db-open-regression.test.ts +70 -2
  1365. package/src/resources/extensions/gsd/tests/doctor-git-checks-autoresolve.test.ts +149 -0
  1366. package/src/resources/extensions/gsd/tests/doctor-git-checks-terminal.test.ts +73 -0
  1367. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +113 -4
  1368. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +18 -0
  1369. package/src/resources/extensions/gsd/tests/dynamic-bash-no-cap.test.ts +132 -0
  1370. package/src/resources/extensions/gsd/tests/engine-hook-contract.test.ts +148 -0
  1371. package/src/resources/extensions/gsd/tests/engine-interfaces-contract.test.ts +117 -91
  1372. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +113 -0
  1373. package/src/resources/extensions/gsd/tests/ensure-preconditions-guard-4996.test.ts +17 -10
  1374. package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +95 -0
  1375. package/src/resources/extensions/gsd/tests/evidence-xref-gsd-exec.test.ts +157 -0
  1376. package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +231 -0
  1377. package/src/resources/extensions/gsd/tests/exec-tool.test.ts +74 -2
  1378. package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +1 -0
  1379. package/src/resources/extensions/gsd/tests/export-html-enhancements.test.ts +25 -0
  1380. package/src/resources/extensions/gsd/tests/export-memory.test.ts +179 -0
  1381. package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +88 -1
  1382. package/src/resources/extensions/gsd/tests/external-markdown-edit.test.ts +137 -0
  1383. package/src/resources/extensions/gsd/tests/external-planning-edit.test.ts +199 -0
  1384. package/src/resources/extensions/gsd/tests/fallback-continuation.test.ts +36 -0
  1385. package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +33 -1
  1386. package/src/resources/extensions/gsd/tests/file-lock.test.ts +43 -0
  1387. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-no-blockers.md +1 -5
  1388. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-with-blockers.md +1 -5
  1389. package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +114 -0
  1390. package/src/resources/extensions/gsd/tests/flat-phase-renderer.test.ts +83 -0
  1391. package/src/resources/extensions/gsd/tests/flat-phase-round-trip.test.ts +72 -0
  1392. package/src/resources/extensions/gsd/tests/flat-phase-validation-integration.test.ts +120 -0
  1393. package/src/resources/extensions/gsd/tests/flat-phase-validation-path.test.ts +74 -0
  1394. package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +2 -1
  1395. package/src/resources/extensions/gsd/tests/forensics-error-filter.test.ts +88 -0
  1396. package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +48 -1
  1397. package/src/resources/extensions/gsd/tests/gsd-command-home.test.ts +154 -1
  1398. package/src/resources/extensions/gsd/tests/gsd-core-parity-routing.test.ts +183 -0
  1399. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +46 -0
  1400. package/src/resources/extensions/gsd/tests/guidance.test.ts +173 -0
  1401. package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +42 -0
  1402. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +18 -6
  1403. package/src/resources/extensions/gsd/tests/health-widget.test.ts +268 -3
  1404. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +19 -11
  1405. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +133 -15
  1406. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +89 -59
  1407. package/src/resources/extensions/gsd/tests/integration/commands-eval-review.integration.test.ts +6 -2
  1408. package/src/resources/extensions/gsd/tests/integration/doctor-environment-async.test.ts +104 -0
  1409. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +122 -3
  1410. package/src/resources/extensions/gsd/tests/integration/gitignore-tracked-gsd.test.ts +55 -0
  1411. package/src/resources/extensions/gsd/tests/integration/gsd-integration-fixture.ts +80 -0
  1412. package/src/resources/extensions/gsd/tests/integration/idle-recovery.test.ts +4 -3
  1413. package/src/resources/extensions/gsd/tests/integration/integration-proof.test.ts +11 -7
  1414. package/src/resources/extensions/gsd/tests/integration/merge-strategy-regular.test.ts +157 -0
  1415. package/src/resources/extensions/gsd/tests/integration/queue-active-milestone-context-budget.test.ts +93 -0
  1416. package/src/resources/extensions/gsd/tests/integration/quick-branch-lifecycle.test.ts +56 -9
  1417. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +217 -0
  1418. package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +1 -0
  1419. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +47 -16
  1420. package/src/resources/extensions/gsd/tests/knowledge-cold-start.test.ts +386 -0
  1421. package/src/resources/extensions/gsd/tests/layout-policy.test.ts +59 -0
  1422. package/src/resources/extensions/gsd/tests/loop.test.ts +60 -0
  1423. package/src/resources/extensions/gsd/tests/markdown-renderer-parse-cache.test.ts +1 -1
  1424. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +214 -82
  1425. package/src/resources/extensions/gsd/tests/mcp-filter.test.ts +74 -1
  1426. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +3 -1
  1427. package/src/resources/extensions/gsd/tests/mcp-readiness-preflight.test.ts +205 -0
  1428. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +6 -5
  1429. package/src/resources/extensions/gsd/tests/mcp-tool-name.test.ts +34 -0
  1430. package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +78 -0
  1431. package/src/resources/extensions/gsd/tests/metrics-ledger-cap.test.ts +239 -0
  1432. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +143 -1
  1433. package/src/resources/extensions/gsd/tests/milestone-closeout-proof.test.ts +99 -0
  1434. package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +125 -4
  1435. package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +1 -1
  1436. package/src/resources/extensions/gsd/tests/milestone-merge-transaction.test.ts +46 -0
  1437. package/src/resources/extensions/gsd/tests/milestone-readiness.test.ts +65 -0
  1438. package/src/resources/extensions/gsd/tests/milestone-report-path.test.ts +1 -1
  1439. package/src/resources/extensions/gsd/tests/milestone-settlement.test.ts +97 -0
  1440. package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +1 -1
  1441. package/src/resources/extensions/gsd/tests/milestone-validation-evidence.test.ts +41 -0
  1442. package/src/resources/extensions/gsd/tests/milestone-validation-verdict.test.ts +55 -0
  1443. package/src/resources/extensions/gsd/tests/model-router.test.ts +343 -7
  1444. package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +32 -1
  1445. package/src/resources/extensions/gsd/tests/native-merge-regular.test.ts +139 -0
  1446. package/src/resources/extensions/gsd/tests/notification-store.test.ts +55 -0
  1447. package/src/resources/extensions/gsd/tests/notifications.test.ts +97 -9
  1448. package/src/resources/extensions/gsd/tests/oauth-api-model-routing.test.ts +179 -0
  1449. package/src/resources/extensions/gsd/tests/observability-validator-boundary.test.ts +194 -0
  1450. package/src/resources/extensions/gsd/tests/orchestrator-legacy-parity.test.ts +1 -1
  1451. package/src/resources/extensions/gsd/tests/orchestrator-logs.test.ts +381 -0
  1452. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +52 -1
  1453. package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +91 -0
  1454. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +44 -0
  1455. package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +2 -2
  1456. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +143 -0
  1457. package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +1 -1
  1458. package/src/resources/extensions/gsd/tests/phases-terminal-complete-idempotent.test.ts +242 -0
  1459. package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +1 -1
  1460. package/src/resources/extensions/gsd/tests/plan-gate-failed-doctor-heal-hint.test.ts +3 -3
  1461. package/src/resources/extensions/gsd/tests/plan-milestone-boundary-map-preservation.test.ts +7 -2
  1462. package/src/resources/extensions/gsd/tests/plan-milestone-sketch-render.test.ts +7 -2
  1463. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +54 -6
  1464. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +2 -0
  1465. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +58 -23
  1466. package/src/resources/extensions/gsd/tests/plan-task.test.ts +4 -4
  1467. package/src/resources/extensions/gsd/tests/planning-crossval.test.ts +64 -0
  1468. package/src/resources/extensions/gsd/tests/planning-layout-detect.test.ts +84 -0
  1469. package/src/resources/extensions/gsd/tests/planning-marker.test.ts +107 -0
  1470. package/src/resources/extensions/gsd/tests/planning-projection-hook.test.ts +123 -0
  1471. package/src/resources/extensions/gsd/tests/planning-round-trip-property.test.ts +164 -0
  1472. package/src/resources/extensions/gsd/tests/planning-writer.test.ts +82 -0
  1473. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +63 -2
  1474. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +48 -1
  1475. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +193 -1
  1476. package/src/resources/extensions/gsd/tests/preferences-diagnostics.test.ts +67 -0
  1477. package/src/resources/extensions/gsd/tests/preferences.test.ts +230 -1
  1478. package/src/resources/extensions/gsd/tests/prefs-missing-models-crash.test.ts +35 -4
  1479. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +54 -1
  1480. package/src/resources/extensions/gsd/tests/progress-strip-test-helpers.ts +79 -0
  1481. package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +2 -0
  1482. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +72 -2
  1483. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +124 -6
  1484. package/src/resources/extensions/gsd/tests/provider-error-guidance.test.ts +18 -3
  1485. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +312 -4
  1486. package/src/resources/extensions/gsd/tests/provider-payload-policy.test.ts +165 -0
  1487. package/src/resources/extensions/gsd/tests/publication.test.ts +120 -0
  1488. package/src/resources/extensions/gsd/tests/pull-request-process.test.ts +47 -0
  1489. package/src/resources/extensions/gsd/tests/read-uat-gate-verdict.test.ts +185 -0
  1490. package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +22 -13
  1491. package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +9 -8
  1492. package/src/resources/extensions/gsd/tests/reconcile-logs.test.ts +244 -0
  1493. package/src/resources/extensions/gsd/tests/recovery-classification-illegal-transition.test.ts +30 -0
  1494. package/src/resources/extensions/gsd/tests/recovery-finalize-logs.test.ts +119 -0
  1495. package/src/resources/extensions/gsd/tests/recovery-verify-logs.test.ts +428 -0
  1496. package/src/resources/extensions/gsd/tests/register-extension-guard.test.ts +25 -0
  1497. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +508 -5
  1498. package/src/resources/extensions/gsd/tests/remote-notification-from-desktop.test.ts +31 -81
  1499. package/src/resources/extensions/gsd/tests/replan-handler.test.ts +4 -4
  1500. package/src/resources/extensions/gsd/tests/resume-missing-worktree-warning.test.ts +5 -5
  1501. package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +40 -0
  1502. package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +68 -0
  1503. package/src/resources/extensions/gsd/tests/round-trip-property.test.ts +137 -0
  1504. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +51 -2
  1505. package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +38 -0
  1506. package/src/resources/extensions/gsd/tests/session-lock-transient-read.test.ts +28 -2
  1507. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +148 -0
  1508. package/src/resources/extensions/gsd/tests/session-switch-clears-pending-autostart.test.ts +108 -0
  1509. package/src/resources/extensions/gsd/tests/show-config-command.test.ts +3 -0
  1510. package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +301 -41
  1511. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +20 -17
  1512. package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +7 -1
  1513. package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +27 -0
  1514. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +9 -4
  1515. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +231 -58
  1516. package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +36 -0
  1517. package/src/resources/extensions/gsd/tests/status-guards.test.ts +38 -0
  1518. package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +1 -1
  1519. package/src/resources/extensions/gsd/tests/stop-backtrack.test.ts +6 -2
  1520. package/src/resources/extensions/gsd/tests/stop-notice.test.ts +70 -0
  1521. package/src/resources/extensions/gsd/tests/stuck-state-via-db.test.ts +85 -0
  1522. package/src/resources/extensions/gsd/tests/sync-lock.test.ts +23 -0
  1523. package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +29 -1
  1524. package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +17 -0
  1525. package/src/resources/extensions/gsd/tests/terminal-tool-surface-classification.test.ts +80 -0
  1526. package/src/resources/extensions/gsd/tests/thinking-level-resolution.test.ts +1 -1
  1527. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +80 -2
  1528. package/src/resources/extensions/gsd/tests/tool-availability-audit.test.ts +35 -0
  1529. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +68 -0
  1530. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +8 -0
  1531. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +35 -42
  1532. package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +26 -0
  1533. package/src/resources/extensions/gsd/tests/tool-schema-model-fallback.test.ts +64 -0
  1534. package/src/resources/extensions/gsd/tests/tool-search-shim.test.ts +71 -0
  1535. package/src/resources/extensions/gsd/tests/tool-surface-readiness.test.ts +348 -0
  1536. package/src/resources/extensions/gsd/tests/tool-unavailable-retry.test.ts +56 -0
  1537. package/src/resources/extensions/gsd/tests/transport-gate-double-complete.test.ts +139 -0
  1538. package/src/resources/extensions/gsd/tests/tui-header-lifecycle.test.ts +40 -86
  1539. package/src/resources/extensions/gsd/tests/tui-render-kit.test.ts +44 -6
  1540. package/src/resources/extensions/gsd/tests/uat-policy.test.ts +112 -6
  1541. package/src/resources/extensions/gsd/tests/undo.test.ts +39 -37
  1542. package/src/resources/extensions/gsd/tests/unit-closeout.test.ts +209 -0
  1543. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +319 -6
  1544. package/src/resources/extensions/gsd/tests/unit-registry.test.ts +163 -0
  1545. package/src/resources/extensions/gsd/tests/unmerged-milestone-guard.test.ts +87 -0
  1546. package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +8 -0
  1547. package/src/resources/extensions/gsd/tests/uok-audit.test.ts +194 -0
  1548. package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +72 -1
  1549. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +1 -1
  1550. package/src/resources/extensions/gsd/tests/validate-milestone-stuck-guard.test.ts +39 -0
  1551. package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +9 -1
  1552. package/src/resources/extensions/gsd/tests/validation-block-guard.test.ts +130 -0
  1553. package/src/resources/extensions/gsd/tests/validation-gate-patterns.test.ts +34 -6
  1554. package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +2 -0
  1555. package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +156 -0
  1556. package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +87 -0
  1557. package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +27 -0
  1558. package/src/resources/extensions/gsd/tests/web-app-uat.test.ts +193 -0
  1559. package/src/resources/extensions/gsd/tests/workflow-events.test.ts +19 -0
  1560. package/src/resources/extensions/gsd/tests/workflow-kernel.test.ts +51 -0
  1561. package/src/resources/extensions/gsd/tests/workflow-mcp-preflight.test.ts +133 -0
  1562. package/src/resources/extensions/gsd/tests/workflow-mcp-readiness-cache.test.ts +119 -0
  1563. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +227 -21
  1564. package/src/resources/extensions/gsd/tests/workflow-phase-contract-matrix.test.ts +332 -0
  1565. package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +3 -4
  1566. package/src/resources/extensions/gsd/tests/workflow-reconcile.test.ts +20 -0
  1567. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +92 -0
  1568. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +339 -48
  1569. package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +166 -2
  1570. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +1 -1
  1571. package/src/resources/extensions/gsd/tests/worktree-health.test.ts +43 -3
  1572. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +41 -4
  1573. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +105 -1
  1574. package/src/resources/extensions/gsd/tests/worktree-placement.test.ts +113 -0
  1575. package/src/resources/extensions/gsd/tests/worktree-project-root-degrade.test.ts +1 -1
  1576. package/src/resources/extensions/gsd/tests/worktree-projection-writers.test.ts +1 -1
  1577. package/src/resources/extensions/gsd/tests/worktree-reentry.test.ts +1 -1
  1578. package/src/resources/extensions/gsd/tests/worktree-safety-phase.test.ts +100 -0
  1579. package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +114 -19
  1580. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +12 -6
  1581. package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +24 -2
  1582. package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +22 -0
  1583. package/src/resources/extensions/gsd/tests/worktree-write-gate.test.ts +75 -3
  1584. package/src/resources/extensions/gsd/tests/worktree.test.ts +18 -0
  1585. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +4 -1
  1586. package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +358 -0
  1587. package/src/resources/extensions/gsd/tests/write-gate.test.ts +291 -1
  1588. package/src/resources/extensions/gsd/tool-contract.ts +124 -11
  1589. package/src/resources/extensions/gsd/tool-presentation-plan.ts +18 -35
  1590. package/src/resources/extensions/gsd/tool-surface-readiness.ts +393 -0
  1591. package/src/resources/extensions/gsd/tool-surface-snapshot.ts +47 -0
  1592. package/src/resources/extensions/gsd/tools/complete-milestone.ts +7 -9
  1593. package/src/resources/extensions/gsd/tools/complete-slice.ts +85 -80
  1594. package/src/resources/extensions/gsd/tools/complete-task.ts +186 -14
  1595. package/src/resources/extensions/gsd/tools/exec-tool.ts +13 -124
  1596. package/src/resources/extensions/gsd/tools/plan-milestone.ts +19 -160
  1597. package/src/resources/extensions/gsd/tools/plan-slice.ts +13 -9
  1598. package/src/resources/extensions/gsd/tools/plan-task.ts +19 -3
  1599. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +54 -12
  1600. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +13 -40
  1601. package/src/resources/extensions/gsd/tools/reopen-slice.ts +16 -44
  1602. package/src/resources/extensions/gsd/tools/reopen-task.ts +2 -2
  1603. package/src/resources/extensions/gsd/tools/replan-slice.ts +2 -2
  1604. package/src/resources/extensions/gsd/tools/skip-slice.ts +18 -44
  1605. package/src/resources/extensions/gsd/tools/validate-milestone.ts +26 -90
  1606. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +123 -5
  1607. package/src/resources/extensions/gsd/triage-resolution.ts +14 -7
  1608. package/src/resources/extensions/gsd/tui/render-kit.ts +56 -13
  1609. package/src/resources/extensions/gsd/uat-policy.ts +80 -25
  1610. package/src/resources/extensions/gsd/uat-run.ts +10 -14
  1611. package/src/resources/extensions/gsd/undo.ts +17 -17
  1612. package/src/resources/extensions/gsd/unit-closeout.ts +201 -0
  1613. package/src/resources/extensions/gsd/unit-context-composer.ts +222 -21
  1614. package/src/resources/extensions/gsd/unit-context-manifest.ts +4 -28
  1615. package/src/resources/extensions/gsd/unit-registry.ts +488 -0
  1616. package/src/resources/extensions/gsd/unit-runtime.ts +3 -2
  1617. package/src/resources/extensions/gsd/unit-tool-contracts.ts +27 -191
  1618. package/src/resources/extensions/gsd/unmerged-milestone-guard.ts +101 -6
  1619. package/src/resources/extensions/gsd/validation-block-guard.ts +60 -6
  1620. package/src/resources/extensions/gsd/verdict-parser.ts +1 -1
  1621. package/src/resources/extensions/gsd/verification-verdict.ts +4 -2
  1622. package/src/resources/extensions/gsd/visualizer-data.ts +55 -0
  1623. package/src/resources/extensions/gsd/visualizer-views.ts +27 -2
  1624. package/src/resources/extensions/gsd/web-app-uat.ts +144 -0
  1625. package/src/resources/extensions/gsd/workflow-event-ledger.ts +131 -0
  1626. package/src/resources/extensions/gsd/workflow-event-vocabulary.ts +59 -0
  1627. package/src/resources/extensions/gsd/workflow-events.ts +12 -20
  1628. package/src/resources/extensions/gsd/workflow-logger.ts +5 -0
  1629. package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +2 -0
  1630. package/src/resources/extensions/gsd/workflow-mcp-readiness-cache.ts +150 -0
  1631. package/src/resources/extensions/gsd/workflow-mcp.ts +34 -111
  1632. package/src/resources/extensions/gsd/workflow-projections.ts +24 -4
  1633. package/src/resources/extensions/gsd/workflow-reconcile.ts +32 -65
  1634. package/src/resources/extensions/gsd/workflow-tool-surface.ts +76 -0
  1635. package/src/resources/extensions/gsd/workspace-git-guard.ts +1 -0
  1636. package/src/resources/extensions/gsd/workspace-git-preflight.ts +31 -0
  1637. package/src/resources/extensions/gsd/worktree-command.ts +6 -6
  1638. package/src/resources/extensions/gsd/worktree-git-recovery.ts +314 -0
  1639. package/src/resources/extensions/gsd/worktree-health.ts +6 -3
  1640. package/src/resources/extensions/gsd/worktree-lifecycle.ts +20 -25
  1641. package/src/resources/extensions/gsd/worktree-manager.ts +175 -45
  1642. package/src/resources/extensions/gsd/worktree-placement.ts +63 -0
  1643. package/src/resources/extensions/gsd/worktree-reentry.ts +10 -7
  1644. package/src/resources/extensions/gsd/worktree-root.ts +29 -6
  1645. package/src/resources/extensions/gsd/worktree-safety.ts +73 -48
  1646. package/src/resources/extensions/gsd/worktree-session-state.ts +11 -11
  1647. package/src/resources/extensions/gsd/worktree-shell-guard.ts +123 -0
  1648. package/src/resources/extensions/gsd/worktree-state-projection.ts +55 -7
  1649. package/src/resources/extensions/gsd/worktree-telemetry.ts +16 -0
  1650. package/src/resources/extensions/gsd/worktree.ts +7 -1
  1651. package/src/resources/extensions/mcp-client/manager.ts +10 -4
  1652. package/src/resources/extensions/search-the-web/index.ts +45 -9
  1653. package/src/resources/extensions/search-the-web/native-search.ts +21 -7
  1654. package/src/resources/extensions/shared/browser-contract.ts +66 -0
  1655. package/src/resources/extensions/shared/gsd-browser-cli.ts +182 -8
  1656. package/src/resources/extensions/shared/interview-ui.ts +15 -2
  1657. package/src/resources/extensions/subagent/index.ts +20 -15
  1658. package/src/resources/extensions/subagent/tests/worktree-cwd.test.ts +57 -0
  1659. package/src/resources/extensions/subagent/worktree-cwd.ts +35 -0
  1660. package/src/resources/shared/claude-runtime-floor.ts +248 -0
  1661. package/src/resources/shared/gsd-browser-path-sync.ts +273 -0
  1662. package/src/resources/shared/package-manager-detection.ts +1 -1
  1663. package/src/resources/shared/package.json +3 -0
  1664. package/src/resources/skills/create-skill/SKILL.md +3 -0
  1665. package/src/resources/skills/create-skill/references/executable-code.md +1 -1
  1666. package/src/resources/skills/create-skill/references/skill-structure.md +1 -0
  1667. package/src/resources/skills/create-skill/workflows/add-reference.md +8 -3
  1668. package/src/resources/skills/create-skill/workflows/add-script.md +4 -2
  1669. package/src/resources/skills/create-skill/workflows/add-template.md +3 -1
  1670. package/src/resources/skills/create-skill/workflows/add-workflow.md +8 -3
  1671. package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
  1672. package/src/resources/skills/create-skill/workflows/verify-skill.md +9 -4
  1673. package/src/resources/skills/spike-wrap-up/SKILL.md +9 -9
  1674. package/dist/resources/extensions/gsd/user-input-boundary.js +0 -195
  1675. package/dist/resources/skills/gsd-browser/SKILL.md +0 -41
  1676. package/dist/web/standalone/.next/server/chunks/5047.js +0 -2
  1677. package/dist/web/standalone/.next/static/chunks/2659.feb6499ca863ebfc.js +0 -1
  1678. package/dist/web/standalone/.next/static/chunks/2772.151789db0edea835.js +0 -1
  1679. package/dist/web/standalone/.next/static/chunks/4283.10a065467b5340d8.js +0 -2
  1680. package/dist/web/standalone/.next/static/chunks/5826.960dc4634cc9b0d3.js +0 -1
  1681. package/dist/web/standalone/.next/static/chunks/796.46f811c0fac23aab.js +0 -10
  1682. package/dist/web/standalone/.next/static/chunks/8785.d32f7a61f55c1600.js +0 -1
  1683. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-49f565245e1e4afe.js +0 -1
  1684. package/dist/web/standalone/.next/static/chunks/app/page-a48b7c48333b31c8.js +0 -1
  1685. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ec3eaffc9785ba48.js +0 -1
  1686. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts +0 -21
  1687. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts.map +0 -1
  1688. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js +0 -213
  1689. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js.map +0 -1
  1690. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-density-prototype.d.ts +0 -28
  1691. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-density-prototype.d.ts.map +0 -1
  1692. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-density-prototype.js +0 -249
  1693. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-density-prototype.js.map +0 -1
  1694. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-design-prototype.d.ts +0 -19
  1695. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-design-prototype.d.ts.map +0 -1
  1696. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-design-prototype.js +0 -797
  1697. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-design-prototype.js.map +0 -1
  1698. package/scripts/ensure-workspace-builds.cjs +0 -129
  1699. package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +0 -88
  1700. package/src/resources/extensions/gsd/user-input-boundary.ts +0 -198
  1701. package/src/resources/skills/gsd-browser/SKILL.md +0 -41
  1702. /package/dist/web/standalone/.next/static/{TA5o9SHAnCdK6Umm1MYxb → SzEuqWX37DR9MEpEuQjP1}/_buildManifest.js +0 -0
  1703. /package/dist/web/standalone/.next/static/{TA5o9SHAnCdK6Umm1MYxb → SzEuqWX37DR9MEpEuQjP1}/_ssgManifest.js +0 -0
@@ -1,757 +1,46 @@
1
1
  // Project/App: gsd-pi
2
- // File Purpose: GSD database facade, schema, migrations, and single-writer write API.
3
- // GSD Database Abstraction Layer
4
- // Provides a SQLite database with provider fallback chain:
5
- // node:sqlite (built-in) → better-sqlite3 (npm) → null (unavailable)
6
- //
7
- // Exposes a unified sync API for decisions and requirements storage.
8
- // Schema is initialized on first open with WAL mode for file-backed DBs.
2
+ // File Purpose: GSD single-writer barrel + write/read wrappers.
9
3
  //
10
4
  // ─── Single-writer invariant ─────────────────────────────────────────────
11
- // This file is the ONLY place in the codebase that issues write SQL
12
- // (INSERT / UPDATE / DELETE / REPLACE / BEGIN-COMMIT transactions) against
13
- // the engine database at `.gsd/gsd.db`. All other modules must call the
14
- // typed wrappers exported here. The structural test
15
- // `tests/single-writer-invariant.test.ts` fails CI if a new bypass appears.
5
+ // Every write-SQL statement against `.gsd/gsd.db` lives behind a typed
6
+ // wrapper in the explicit writer allowlist: this compatibility barrel,
7
+ // db/writers/*, typed coordination/runtime writers, schema/migration helpers,
8
+ // and ADR backfill helpers. Connection ownership, lifecycle, schema/migrations,
9
+ // and transaction primitives live in db/engine.ts and are re-exported here for
10
+ // backward compatibility, so callers keep importing from "./gsd-db.js".
16
11
  //
17
- // `_getAdapter()` is retained for read-only SELECTs in query modules
18
- // (context-store, memory-store queries, doctor checks, projections).
19
- // Do NOT use it for writes — add a wrapper here instead.
12
+ // `_getAdapter()` (re-exported from the engine) is retained for read-only
13
+ // SELECTs in query modules. Do NOT use it for writes — add or call a typed
14
+ // wrapper in the explicit writer layer.
20
15
  //
21
- // The separate `.gsd/unit-claims.db` managed by `unit-ownership.ts` is an
22
- // intentionally independent store for cross-worktree claim races and is
23
- // excluded from this invariant.
24
- import { createRequire } from "node:module";
16
+ // The separate `.gsd/unit-claims.db` (unit-ownership.ts) is an intentionally
17
+ // independent store and is excluded from this invariant.
25
18
  import { createHash } from "node:crypto";
26
- import { existsSync, copyFileSync, mkdirSync, realpathSync } from "node:fs";
27
- import { dirname, join } from "node:path";
28
19
  import { GSDError, GSD_STALE_STATE } from "./errors.js";
29
20
  import { getGateIdsForTurn } from "./gate-registry.js";
30
- import { logError, logWarning } from "./workflow-logger.js";
31
- import { createDbAdapter } from "./db-adapter.js";
32
- import { createBaseSchemaObjects } from "./db-base-schema.js";
33
- import { createCoordinationTablesV24 } from "./db-coordination-schema.js";
34
- import { createDbConnectionCache } from "./db-connection-cache.js";
35
- import { emptyTaskStatusCounts, rowToActiveTaskSummary, rowToIdStatusSummary, rowToTaskStatusCounts, rowsToStringColumn, } from "./db-lightweight-query-rows.js";
36
- import { rowToActiveDecision, rowToActiveRequirement, rowToDecision, rowToRequirement, rowsToRequirementCounts, } from "./db-decision-requirement-rows.js";
37
- import { rowToGate } from "./db-gate-rows.js";
38
- import { rowToArtifact, rowToMilestone } from "./db-milestone-artifact-rows.js";
39
- import { backupDatabaseBeforeMigration } from "./db-migration-backup.js";
21
+ import { logWarning } from "./workflow-logger.js";
40
22
  import { isClosedStatus } from "./status-guards.js";
41
- import { applyMigrationV2Artifacts, applyMigrationV3Memories, applyMigrationV4DecisionMadeBy, applyMigrationV5HierarchyTables, applyMigrationV6SliceSummaries, applyMigrationV7Dependencies, applyMigrationV8PlanningFields, applyMigrationV9Ordering, applyMigrationV10ReplanTrigger, applyMigrationV11TaskPlanning, applyMigrationV12QualityGates, applyMigrationV13HotPathIndexes, applyMigrationV14SliceDependencies, applyMigrationV15AuditTables, applyMigrationV16EscalationSource, applyMigrationV17TaskEscalation, applyMigrationV18MemorySources, applyMigrationV19MemoryFts, applyMigrationV20MemoryRelations, applyMigrationV21StructuredMemories, applyMigrationV22QualityGateRepair, applyMigrationV23MilestoneQueue, applyMigrationV26MilestoneCommitAttributions, applyMigrationV27ArtifactHash, applyMigrationV28MemoryLastHitAt, applyMigrationV29RepositoryTargets, } from "./db-migration-steps.js";
42
- import { isMemoriesFtsAvailableSchema, tryCreateMemoriesFtsSchema } from "./db-memory-fts-schema.js";
43
- import { createDbOpenState } from "./db-open-state.js";
44
- import { createRuntimeKvTableV25 } from "./db-runtime-kv-schema.js";
45
- import { getCurrentSchemaVersion, recordSchemaVersion } from "./db-schema-metadata.js";
46
- import { rowToSlice, rowToTask } from "./db-task-slice-rows.js";
47
- import { createDbTransactionRunner } from "./db-transaction.js";
48
- import { ensureVerificationEvidenceDedupIndex } from "./db-verification-evidence-schema.js";
49
- import { BETTER_SQLITE3_PACKAGE, createSqliteProviderLoader, suppressSqliteWarning, } from "./db-provider.js";
50
- let _gsdRequire;
51
- function getGsdRequire() {
52
- if (_gsdRequire !== undefined)
53
- return _gsdRequire;
54
- try {
55
- _gsdRequire = createRequire(import.meta.url);
56
- }
57
- catch {
58
- _gsdRequire = null;
59
- }
60
- return _gsdRequire;
61
- }
62
- const providerLoader = createSqliteProviderLoader({
63
- tryRequireNodeSqlite: () => {
64
- const req = getGsdRequire();
65
- if (!req)
66
- throw new Error("unavailable");
67
- return req("node:sqlite");
68
- },
69
- tryRequireBetterSqlite3: () => {
70
- const req = getGsdRequire();
71
- if (!req)
72
- throw new Error("unavailable");
73
- return req(BETTER_SQLITE3_PACKAGE);
74
- },
75
- suppressSqliteWarning,
76
- nodeVersion: process.versions.node,
77
- writeStderr: (message) => process.stderr.write(message),
78
- });
79
- export const SCHEMA_VERSION = 29;
80
- const TERMINAL_STATUS_SQL = "'complete', 'done', 'skipped', 'closed'";
81
- function initSchema(db, fileBacked, dbPath) {
82
- const conservativeFilePragmas = fileBacked && _isLikelyWslDrvFsPathForTest(dbPath);
83
- if (fileBacked)
84
- db.exec(conservativeFilePragmas ? "PRAGMA journal_mode=DELETE" : "PRAGMA journal_mode=WAL");
85
- if (fileBacked)
86
- db.exec("PRAGMA busy_timeout = 5000");
87
- if (fileBacked)
88
- db.exec(conservativeFilePragmas ? "PRAGMA synchronous = FULL" : "PRAGMA synchronous = NORMAL");
89
- if (fileBacked)
90
- db.exec("PRAGMA auto_vacuum = INCREMENTAL");
91
- if (fileBacked)
92
- db.exec("PRAGMA cache_size = -8000"); // 8 MB page cache
93
- if (fileBacked && !conservativeFilePragmas && process.platform !== "darwin")
94
- db.exec("PRAGMA mmap_size = 67108864"); // 64 MB mmap
95
- db.exec("PRAGMA temp_store = MEMORY");
96
- db.exec("PRAGMA foreign_keys = ON");
97
- db.exec("BEGIN");
98
- try {
99
- createBaseSchemaObjects(db, {
100
- tryCreateMemoriesFts,
101
- ensureVerificationEvidenceDedupIndex,
102
- });
103
- const existing = db.prepare("SELECT count(*) as cnt FROM schema_version").get();
104
- if (existing && existing["cnt"] === 0) {
105
- createCoordinationTablesV24(db);
106
- createRuntimeKvTableV25(db);
107
- // Fresh install — all tables are created above with the full current schema,
108
- // so it is safe to create all migration-specific indexes here. For existing
109
- // databases these indexes are created inside the individual migration guards
110
- // in migrateSchema() after the corresponding columns have been added.
111
- db.exec("CREATE INDEX IF NOT EXISTS idx_tasks_escalation_pending ON tasks(milestone_id, slice_id, escalation_pending)");
112
- db.exec("CREATE INDEX IF NOT EXISTS idx_memories_scope ON memories(scope)");
113
- db.exec("CREATE INDEX IF NOT EXISTS idx_memory_sources_kind ON memory_sources(kind)");
114
- db.exec("CREATE INDEX IF NOT EXISTS idx_memory_sources_scope ON memory_sources(scope)");
115
- db.exec("CREATE INDEX IF NOT EXISTS idx_memory_relations_from ON memory_relations(from_id)");
116
- db.exec("CREATE INDEX IF NOT EXISTS idx_memory_relations_to ON memory_relations(to_id)");
117
- recordSchemaVersion(db, SCHEMA_VERSION);
118
- }
119
- db.exec("COMMIT");
120
- }
121
- catch (err) {
122
- db.exec("ROLLBACK");
123
- throw err;
124
- }
125
- migrateSchema(db);
126
- }
127
- export function _isLikelyWslDrvFsPathForTest(dbPath) {
128
- if (!dbPath || process.platform !== "linux")
129
- return false;
130
- const drvFsPathPattern = /^\/mnt\/[a-z](?:\/|$)/i;
131
- if (drvFsPathPattern.test(dbPath))
132
- return true;
133
- try {
134
- return drvFsPathPattern.test(realpathSync(dbPath));
135
- }
136
- catch {
137
- return false;
138
- }
139
- }
140
- /**
141
- * Create the FTS5 virtual table for memories plus the triggers that keep it
142
- * in sync with the base table. FTS5 may be unavailable on stripped-down
143
- * SQLite builds — callers should treat failure as non-fatal and fall back
144
- * to LIKE-based scans in `memory-store.queryMemoriesRanked`.
145
- */
146
- export function tryCreateMemoriesFts(db) {
147
- return tryCreateMemoriesFtsSchema(db, {
148
- onUnavailable: (message) => logWarning("db", message),
149
- });
150
- }
151
- export function isMemoriesFtsAvailable(db) {
152
- return isMemoriesFtsAvailableSchema(db);
153
- }
154
- function backfillMemoriesFts(db) {
155
- db.exec(`INSERT INTO memories_fts(rowid, content) SELECT seq, content FROM memories`);
156
- }
157
- function copyQualityGateRowsToRepairedTable(db) {
158
- db.exec(`
159
- INSERT OR IGNORE INTO quality_gates_new
160
- (milestone_id, slice_id, gate_id, scope, task_id, status, verdict, rationale, findings, evaluated_at)
161
- SELECT milestone_id, slice_id, gate_id, scope, COALESCE(task_id, ''), status, verdict, rationale, findings, evaluated_at
162
- FROM quality_gates
163
- `);
164
- }
165
- function migrateSchema(db) {
166
- const currentVersion = getCurrentSchemaVersion(db);
167
- if (currentVersion >= SCHEMA_VERSION)
168
- return;
169
- backupDatabaseBeforeMigration(db, currentPath, currentVersion, {
170
- existsSync,
171
- copyFileSync,
172
- logWarning,
173
- });
174
- db.exec("BEGIN");
175
- try {
176
- if (currentVersion < 2) {
177
- applyMigrationV2Artifacts(db);
178
- recordSchemaVersion(db, 2);
179
- }
180
- if (currentVersion < 3) {
181
- applyMigrationV3Memories(db);
182
- recordSchemaVersion(db, 3);
183
- }
184
- if (currentVersion < 4) {
185
- applyMigrationV4DecisionMadeBy(db);
186
- recordSchemaVersion(db, 4);
187
- }
188
- if (currentVersion < 5) {
189
- applyMigrationV5HierarchyTables(db);
190
- recordSchemaVersion(db, 5);
191
- }
192
- if (currentVersion < 6) {
193
- applyMigrationV6SliceSummaries(db);
194
- recordSchemaVersion(db, 6);
195
- }
196
- if (currentVersion < 7) {
197
- applyMigrationV7Dependencies(db);
198
- recordSchemaVersion(db, 7);
199
- }
200
- if (currentVersion < 8) {
201
- applyMigrationV8PlanningFields(db);
202
- recordSchemaVersion(db, 8);
203
- }
204
- if (currentVersion < 9) {
205
- applyMigrationV9Ordering(db);
206
- recordSchemaVersion(db, 9);
207
- }
208
- if (currentVersion < 10) {
209
- applyMigrationV10ReplanTrigger(db);
210
- recordSchemaVersion(db, 10);
211
- }
212
- if (currentVersion < 11) {
213
- applyMigrationV11TaskPlanning(db);
214
- recordSchemaVersion(db, 11);
215
- }
216
- if (currentVersion < 12) {
217
- // NOTE: The original DDL used COALESCE(task_id, '') in the PRIMARY KEY
218
- // expression, which is invalid SQLite syntax and causes startup errors on
219
- // DBs that migrate through v12. The corrected DDL uses
220
- // task_id TEXT NOT NULL DEFAULT '' with a plain column list PK. DBs that
221
- // were created with the broken DDL are repaired by the v22 migration below.
222
- applyMigrationV12QualityGates(db);
223
- recordSchemaVersion(db, 12);
224
- }
225
- if (currentVersion < 13) {
226
- applyMigrationV13HotPathIndexes(db, ensureVerificationEvidenceDedupIndex);
227
- recordSchemaVersion(db, 13);
228
- }
229
- if (currentVersion < 14) {
230
- applyMigrationV14SliceDependencies(db);
231
- recordSchemaVersion(db, 14);
232
- }
233
- if (currentVersion < 15) {
234
- applyMigrationV15AuditTables(db);
235
- recordSchemaVersion(db, 15);
236
- }
237
- if (currentVersion < 16) {
238
- applyMigrationV16EscalationSource(db);
239
- recordSchemaVersion(db, 16);
240
- }
241
- if (currentVersion < 17) {
242
- applyMigrationV17TaskEscalation(db);
243
- recordSchemaVersion(db, 17);
244
- }
245
- if (currentVersion < 18) {
246
- applyMigrationV18MemorySources(db);
247
- recordSchemaVersion(db, 18);
248
- }
249
- if (currentVersion < 19) {
250
- applyMigrationV19MemoryFts(db, {
251
- tryCreateMemoriesFts,
252
- isMemoriesFtsAvailable,
253
- backfillMemoriesFts,
254
- logWarning,
255
- });
256
- recordSchemaVersion(db, 19);
257
- }
258
- if (currentVersion < 20) {
259
- applyMigrationV20MemoryRelations(db);
260
- recordSchemaVersion(db, 20);
261
- }
262
- if (currentVersion < 21) {
263
- applyMigrationV21StructuredMemories(db);
264
- recordSchemaVersion(db, 21);
265
- }
266
- if (currentVersion < 22) {
267
- applyMigrationV22QualityGateRepair(db, { copyQualityGateRowsToRepairedTable });
268
- recordSchemaVersion(db, 22);
269
- }
270
- if (currentVersion < 23) {
271
- applyMigrationV23MilestoneQueue(db);
272
- recordSchemaVersion(db, 23);
273
- }
274
- if (currentVersion < 24) {
275
- // v24: auto-mode coordination tables. See createCoordinationTablesV24
276
- // for full schema + invariants. No-op for fresh installs (the same
277
- // helper runs in the fresh-install path); for upgraded DBs this is
278
- // the only place these tables get created.
279
- createCoordinationTablesV24(db);
280
- recordSchemaVersion(db, 24);
281
- }
282
- if (currentVersion < 25) {
283
- // v25: runtime_kv non-correctness-critical key-value storage. See
284
- // createRuntimeKvTableV25 for the full schema + invariants.
285
- createRuntimeKvTableV25(db);
286
- recordSchemaVersion(db, 25);
287
- }
288
- if (currentVersion < 26) {
289
- applyMigrationV26MilestoneCommitAttributions(db);
290
- recordSchemaVersion(db, 26);
291
- }
292
- if (currentVersion < 27) {
293
- applyMigrationV27ArtifactHash(db);
294
- recordSchemaVersion(db, 27);
295
- }
296
- if (currentVersion < 28) {
297
- applyMigrationV28MemoryLastHitAt(db);
298
- recordSchemaVersion(db, 28);
299
- }
300
- if (currentVersion < 29) {
301
- applyMigrationV29RepositoryTargets(db);
302
- recordSchemaVersion(db, 29);
303
- }
304
- db.exec("COMMIT");
305
- }
306
- catch (err) {
307
- db.exec("ROLLBACK");
308
- throw err;
309
- }
310
- }
311
- let currentDb = null;
312
- let currentPath = null;
313
- let currentPid = 0;
314
- let _exitHandlerRegistered = false;
315
- const _dbOpenState = createDbOpenState();
316
- /**
317
- * Identity key of the workspace whose connection is currently active
318
- * (currentDb). Set by openDatabaseByWorkspace(); null when the active
319
- * connection was opened via the legacy openDatabase(path) path.
320
- */
321
- let _currentIdentityKey = null;
322
- /**
323
- * Workspace-scoped connection cache.
324
- * Key: GsdWorkspace.identityKey (realpath-normalized project root).
325
- * Value: the DB path and open adapter for that workspace.
326
- *
327
- * Sibling worktrees of the same project share the same identityKey (set by
328
- * createWorkspace) and therefore reuse the same cached connection, preserving
329
- * shared-WAL semantics. Different projects get distinct cache entries.
330
- *
331
- * NOTE: Only one connection is "active" at a time (currentDb/currentPath).
332
- * The cache allows fast re-activation of a previously opened connection when
333
- * callers switch between known workspaces via openDatabaseByWorkspace().
334
- */
335
- const _dbCache = createDbConnectionCache();
336
- /** Test helper: expose the internal cache for inspection. Not for production use. */
337
- export function _getDbCache() {
338
- return _dbCache.asReadonlyMap();
339
- }
340
- function closeCachedConnection(entry, source) {
341
- try {
342
- entry.db.exec("PRAGMA wal_checkpoint(TRUNCATE)");
343
- }
344
- catch (e) {
345
- if (source === "workspace")
346
- logWarning("db", `WAL checkpoint (byWorkspace) failed: ${e.message}`);
347
- }
348
- try {
349
- entry.db.exec("PRAGMA incremental_vacuum(64)");
350
- }
351
- catch (e) {
352
- if (source === "workspace")
353
- logWarning("db", `incremental vacuum (byWorkspace) failed: ${e.message}`);
354
- }
355
- try {
356
- entry.db.close();
357
- }
358
- catch (e) {
359
- if (source === "workspace")
360
- logWarning("db", `database close (byWorkspace) failed: ${e.message}`);
361
- }
362
- }
363
- /**
364
- * Close and evict every entry in the workspace connection cache, then call
365
- * closeDatabase() to close the active connection.
366
- *
367
- * Use this for test teardown or process-shutdown paths where every open
368
- * connection must be flushed. Normal callers should use closeDatabase() or
369
- * closeDatabaseByWorkspace() instead.
370
- */
371
- export function closeAllDatabases() {
372
- // Close all non-active cached connections first.
373
- _dbCache.closeNonActive(currentDb, (entry) => closeCachedConnection(entry, "all"));
374
- closeDatabase();
375
- }
376
- /**
377
- * Open (or reuse) the database connection scoped to the given workspace.
378
- *
379
- * Uses workspace.identityKey as the cache key, so sibling worktrees of the
380
- * same project resolve to the same connection. On a cache hit the existing
381
- * adapter is reactivated as the current connection without re-opening the
382
- * file. On a cache miss, delegates to openDatabase() for the full
383
- * open + schema-init + migration flow, then caches the result.
384
- *
385
- * When switching to a different workspace, the previously active connection
386
- * is preserved in the cache (not closed), so callers can switch back to it
387
- * cheaply via a subsequent openDatabaseByWorkspace() call.
388
- *
389
- * @param workspace A GsdWorkspace created by createWorkspace().
390
- * @returns true if the connection is open and ready, false otherwise.
391
- */
392
- export function openDatabaseByWorkspace(workspace) {
393
- const key = workspace.identityKey;
394
- const dbPath = workspace.contract.projectDb;
395
- const cached = _dbCache.get(key);
396
- if (cached) {
397
- // Reactivate the cached connection as the current singleton.
398
- currentDb = cached.db;
399
- currentPath = cached.dbPath;
400
- currentPid = process.pid;
401
- _dbOpenState.markAttempted();
402
- _currentIdentityKey = key;
403
- return true;
404
- }
405
- // Cache miss — need to open a new connection.
406
- //
407
- // If there is a currently active workspace connection, stash it in the
408
- // cache under its identity key before calling openDatabase(), because
409
- // openDatabase() will call closeDatabase() when the path changes (which
410
- // would destroy the existing adapter). By nulling out currentDb first,
411
- // we prevent openDatabase() from closing the live adapter.
412
- let oldDb = null;
413
- let oldPath = null;
414
- let oldPid = 0;
415
- let oldKey = null;
416
- if (currentDb !== null && _currentIdentityKey !== null) {
417
- // Snapshot the old globals so we can restore them on failure.
418
- oldDb = currentDb;
419
- oldPath = currentPath;
420
- oldPid = currentPid;
421
- oldKey = _currentIdentityKey;
422
- // Save the current connection so it stays alive in the cache.
423
- _dbCache.set(_currentIdentityKey, {
424
- dbPath: currentPath,
425
- db: currentDb,
426
- });
427
- // Detach from globals so openDatabase() opens fresh without closing it.
428
- currentDb = null;
429
- currentPath = null;
430
- currentPid = 0;
431
- _currentIdentityKey = null;
432
- }
433
- // Run the full open/schema/migration flow for the new workspace.
434
- // openDatabase() can throw on corrupt DB or permission error — catch so we
435
- // can restore the previous connection rather than leaving globals null.
436
- let opened;
437
- try {
438
- opened = openDatabase(dbPath);
439
- }
440
- catch (err) {
441
- // Failed to open the new DB. Restore the previous workspace connection so
442
- // the caller's workspace remains active (it is still safe in _dbCache).
443
- if (oldDb !== null) {
444
- currentDb = oldDb;
445
- currentPath = oldPath;
446
- currentPid = oldPid;
447
- _currentIdentityKey = oldKey;
448
- }
449
- throw err;
450
- }
451
- if (opened && currentDb) {
452
- _dbCache.set(key, { dbPath, db: currentDb });
453
- _currentIdentityKey = key;
454
- }
455
- else if (!opened && oldDb !== null) {
456
- // Restore the previous connection so the caller's workspace remains active.
457
- // The failed attempt left no live adapter, so the globals stayed null.
458
- currentDb = oldDb;
459
- currentPath = oldPath;
460
- currentPid = oldPid;
461
- _currentIdentityKey = oldKey;
462
- }
463
- return opened;
464
- }
465
- /**
466
- * Open (or reuse) the database connection scoped to the workspace in a
467
- * MilestoneScope. Thin delegation to openDatabaseByWorkspace().
468
- */
469
- export function openDatabaseByScope(scope) {
470
- return openDatabaseByWorkspace(scope.workspace);
471
- }
472
- /**
473
- * Close the database connection for the given workspace and remove it from
474
- * the cache. If the workspace's connection is currently active (currentDb),
475
- * performs a full closeDatabase() including WAL checkpoint. Otherwise only
476
- * removes the cache entry (the adapter was already replaced by a later open).
477
- */
478
- export function closeDatabaseByWorkspace(workspace) {
479
- const key = workspace.identityKey;
480
- const cached = _dbCache.get(key);
481
- if (!cached)
482
- return;
483
- _dbCache.delete(key);
484
- if (currentDb === cached.db) {
485
- // This workspace's connection is the active one — full close.
486
- closeDatabase();
487
- }
488
- else {
489
- // Connection was displaced by a later open; close the adapter directly.
490
- closeCachedConnection(cached, "workspace");
491
- }
492
- }
493
- export function getDbProvider() {
494
- providerLoader.load();
495
- return providerLoader.getProviderName();
496
- }
497
- export function isDbAvailable() {
498
- return currentDb !== null;
499
- }
500
- /**
501
- * Returns true if openDatabase() has been called at least once this session.
502
- * Used to distinguish "DB not yet initialized" from "DB genuinely unavailable"
503
- * so that early callers (e.g. before_agent_start context injection) don't
504
- * trigger a false degraded-mode warning.
505
- */
506
- export function wasDbOpenAttempted() {
507
- return _dbOpenState.snapshot().attempted;
508
- }
509
- export function getDbStatus() {
510
- providerLoader.load();
511
- const openState = _dbOpenState.snapshot();
512
- return {
513
- available: currentDb !== null,
514
- provider: providerLoader.getProviderName(),
515
- attempted: openState.attempted,
516
- lastError: openState.lastError,
517
- lastPhase: openState.lastPhase,
518
- };
519
- }
520
- export function openDatabase(path) {
521
- _dbOpenState.markAttempted();
522
- if (currentDb && currentPath !== path)
523
- closeDatabase();
524
- if (currentDb && currentPath === path)
525
- return true;
526
- // Reset error state only when a new open attempt is actually going to run.
527
- _dbOpenState.clearError();
528
- let rawDb;
529
- let fallbackOpen = null;
530
- try {
531
- rawDb = providerLoader.openRaw(path);
532
- }
533
- catch (primaryErr) {
534
- _dbOpenState.recordError("open", primaryErr);
535
- // node:sqlite loaded but failed to open this file — try better-sqlite3 as fallback.
536
- fallbackOpen = providerLoader.tryOpenBetterSqliteFallback(path);
537
- if (fallbackOpen) {
538
- rawDb = fallbackOpen.rawDb;
539
- _dbOpenState.clearError();
540
- }
541
- if (!rawDb)
542
- throw primaryErr;
543
- }
544
- if (!rawDb)
545
- return false;
546
- const adapter = createDbAdapter(rawDb);
547
- const fileBacked = path !== ":memory:";
548
- try {
549
- initSchema(adapter, fileBacked, path);
550
- }
551
- catch (err) {
552
- // Corrupt freelist: DDL fails with "malformed" but VACUUM can rebuild.
553
- // Attempt VACUUM recovery before giving up (see #2519).
554
- if (fileBacked && err instanceof Error && err.message?.includes("malformed")) {
555
- try {
556
- adapter.exec("VACUUM");
557
- initSchema(adapter, fileBacked, path);
558
- process.stderr.write("gsd-db: recovered corrupt database via VACUUM\n");
559
- }
560
- catch (retryErr) {
561
- _dbOpenState.recordError("vacuum-recovery", retryErr);
562
- try {
563
- adapter.close();
564
- }
565
- catch (e) {
566
- logWarning("db", `close after VACUUM failed: ${e.message}`);
567
- }
568
- throw retryErr;
569
- }
570
- }
571
- else {
572
- _dbOpenState.recordError("initSchema", err);
573
- try {
574
- adapter.close();
575
- }
576
- catch (e) {
577
- logWarning("db", `close after initSchema failed: ${e.message}`);
578
- }
579
- throw err;
580
- }
581
- }
582
- // Commit fallback provider switch only after open + schema both succeeded.
583
- if (fallbackOpen)
584
- providerLoader.commitFallback(fallbackOpen);
585
- currentDb = adapter;
586
- currentPath = path;
587
- currentPid = process.pid;
588
- if (!_exitHandlerRegistered) {
589
- _exitHandlerRegistered = true;
590
- process.on("exit", () => { try {
591
- closeDatabase();
592
- }
593
- catch (e) {
594
- logWarning("db", `exit handler close failed: ${e.message}`);
595
- } });
596
- }
597
- return true;
598
- }
599
- export function closeDatabase() {
600
- if (currentDb) {
601
- try {
602
- currentDb.exec('PRAGMA wal_checkpoint(TRUNCATE)');
603
- }
604
- catch (e) {
605
- logWarning("db", `WAL checkpoint failed: ${e.message}`);
606
- }
607
- try {
608
- // Incremental vacuum to reclaim space without blocking
609
- currentDb.exec('PRAGMA incremental_vacuum(64)');
610
- }
611
- catch (e) {
612
- logWarning("db", `incremental vacuum failed: ${e.message}`);
613
- }
614
- try {
615
- currentDb.close();
616
- }
617
- catch (e) {
618
- logWarning("db", `database close failed: ${e.message}`);
619
- }
620
- // If this connection was workspace-tracked, evict it from the cache so
621
- // subsequent openDatabaseByWorkspace() calls re-open rather than reactivate
622
- // a closed adapter.
623
- if (_currentIdentityKey !== null) {
624
- _dbCache.delete(_currentIdentityKey);
625
- _currentIdentityKey = null;
626
- }
627
- currentDb = null;
628
- currentPath = null;
629
- currentPid = 0;
630
- }
631
- // Reset session-scoped state unconditionally so stale error info from a
632
- // failed open doesn't persist into the next open attempt or status check.
633
- _dbOpenState.reset();
634
- }
635
- /**
636
- * Re-open the active database connection from disk.
637
- *
638
- * Auto-mode can observe artifacts written by a workflow server running in a
639
- * different process before its long-lived singleton has re-synchronized. The
640
- * recovery path uses this to force the next state derivation to read from the
641
- * current on-disk database instead of continuing with a possibly stale handle.
642
- */
643
- export function refreshOpenDatabaseFromDisk() {
644
- if (!currentDb || !currentPath)
645
- return false;
646
- if (currentPath === ":memory:")
647
- return false;
648
- const dbPath = currentPath;
649
- const identityKey = _currentIdentityKey;
650
- try {
651
- closeDatabase();
652
- const opened = openDatabase(dbPath);
653
- if (opened && identityKey && currentDb) {
654
- _dbCache.set(identityKey, { dbPath, db: currentDb });
655
- _currentIdentityKey = identityKey;
656
- }
657
- return opened;
658
- }
659
- catch (e) {
660
- logWarning("db", `database refresh failed: ${e.message}`);
661
- return false;
662
- }
663
- }
664
- /** Run a full VACUUM — call sparingly (e.g. after milestone completion). */
665
- export function vacuumDatabase() {
666
- if (!currentDb)
667
- return;
668
- try {
669
- currentDb.exec('VACUUM');
670
- }
671
- catch (e) {
672
- logWarning("db", `VACUUM failed: ${e.message}`);
673
- }
674
- }
675
- /** Flush WAL into gsd.db so `git add .gsd/gsd.db` stages current state — safe while DB is open. */
676
- export function checkpointDatabase() {
677
- if (!currentDb)
678
- return;
679
- try {
680
- currentDb.exec('PRAGMA wal_checkpoint(TRUNCATE)');
681
- }
682
- catch (e) {
683
- logWarning("db", `WAL checkpoint failed: ${e.message}`);
684
- }
685
- }
686
- /**
687
- * Copy the live database file to `.gsd/backups/<label>-<timestamp>.db` so a
688
- * destructive operation (e.g. recover, which clears the hierarchy tables) is
689
- * reversible. Checkpoints the WAL first so the snapshot is complete. Returns
690
- * the backup path, or null if no DB is open or the copy failed.
691
- */
692
- export function backupDatabaseSnapshot(label) {
693
- if (!currentPath)
694
- return null;
695
- try {
696
- checkpointDatabase();
697
- const backupsDir = join(dirname(currentPath), "backups");
698
- mkdirSync(backupsDir, { recursive: true });
699
- const stamp = new Date().toISOString().replace(/[:.]/g, "-");
700
- const dest = join(backupsDir, `${label}-${stamp}.db`);
701
- copyFileSync(currentPath, dest);
702
- return dest;
703
- }
704
- catch (e) {
705
- logWarning("db", `database snapshot failed: ${e.message}`);
706
- return null;
707
- }
708
- }
709
- const _transactionRunner = createDbTransactionRunner();
710
- function createTransactionControls(db) {
711
- return {
712
- begin: () => db.exec("BEGIN"),
713
- beginRead: () => db.exec("BEGIN DEFERRED"),
714
- commit: () => db.exec("COMMIT"),
715
- rollback: () => db.exec("ROLLBACK"),
716
- };
717
- }
718
- /**
719
- * Whether the current call is running inside an active SQLite transaction.
720
- * Statement-time recovery paths (e.g. VACUUM retry on a malformed memory
721
- * store) MUST gate on this — SQLite refuses VACUUM inside a transaction
722
- * and would mask the original error with a secondary "cannot VACUUM" throw.
723
- */
724
- export function isInTransaction() {
725
- return _transactionRunner.isInTransaction();
726
- }
727
- export function transaction(fn) {
728
- if (!currentDb)
729
- throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
730
- return _transactionRunner.transaction(createTransactionControls(currentDb), fn);
731
- }
732
- /**
733
- * Wrap a block of reads in a DEFERRED transaction so that all SELECTs observe
734
- * a consistent snapshot of the DB even if a concurrent writer commits between
735
- * them. Use this for multi-query read flows (e.g. tool executors that query
736
- * milestone + slices + counts and want one snapshot). Re-entrant — if already
737
- * inside a transaction, runs fn() without starting a nested one.
738
- */
739
- export function readTransaction(fn) {
740
- if (!currentDb)
741
- throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
742
- return _transactionRunner.readTransaction(createTransactionControls(currentDb), fn, (rollbackErr) => {
743
- // A failed ROLLBACK after a failed read is a split-brain signal —
744
- // the transaction is in an indeterminate state. Surface it via the
745
- // logger instead of swallowing it.
746
- logError("db", "snapshotState ROLLBACK failed", {
747
- error: rollbackErr.message,
748
- });
749
- });
750
- }
23
+ // Connection ownership, lifecycle, schema/migrations and transaction
24
+ // primitives now live in the engine; re-export the full public surface so
25
+ // existing `from "./gsd-db.js"` imports keep working.
26
+ export * from "./db/engine.js";
27
+ import { immediateTransaction, transaction, getDb, getDbOrNull } from "./db/engine.js";
28
+ // ─── Single Writer Layer re-exports ──────────────────────────────────────
29
+ // Domain write subsystems live in db/writers/*; re-exported here so callers
30
+ // keep importing from "./gsd-db.js".
31
+ export * from "./db/writers/memory.js";
32
+ export * from "./db/writers/reconcile.js";
33
+ export * from "./db/writers/import-restore.js";
34
+ // Query Module (read-only seam) — extracted from the single-writer file.
35
+ export * from "./db/queries.js";
36
+ // Domain Write Operations (Hierarchy Status Cascades).
37
+ export * from "./db/writers/cascades.js";
38
+ import { TERMINAL_STATUS_SQL } from "./db/sql-constants.js";
39
+ import { applyStatusTransition } from "./db/writers/status.js";
751
40
  export function insertDecision(d) {
752
- if (!currentDb)
41
+ if (!getDbOrNull())
753
42
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
754
- currentDb.prepare(`INSERT INTO decisions (id, when_context, scope, decision, choice, rationale, revisable, made_by, source, superseded_by)
43
+ getDbOrNull().prepare(`INSERT INTO decisions (id, when_context, scope, decision, choice, rationale, revisable, made_by, source, superseded_by)
755
44
  VALUES (:id, :when_context, :scope, :decision, :choice, :rationale, :revisable, :made_by, :source, :superseded_by)`).run({
756
45
  ":id": d.id,
757
46
  ":when_context": d.when_context,
@@ -765,24 +54,10 @@ export function insertDecision(d) {
765
54
  ":superseded_by": d.superseded_by,
766
55
  });
767
56
  }
768
- export function getDecisionById(id) {
769
- if (!currentDb)
770
- return null;
771
- const row = currentDb.prepare("SELECT * FROM decisions WHERE id = ?").get(id);
772
- if (!row)
773
- return null;
774
- return rowToDecision(row);
775
- }
776
- export function getActiveDecisions() {
777
- if (!currentDb)
778
- return [];
779
- const rows = currentDb.prepare("SELECT * FROM active_decisions").all();
780
- return rows.map(rowToActiveDecision);
781
- }
782
57
  export function insertRequirement(r) {
783
- if (!currentDb)
58
+ if (!getDbOrNull())
784
59
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
785
- currentDb.prepare(`INSERT INTO requirements (id, class, status, description, why, source, primary_owner, supporting_slices, validation, notes, full_content, superseded_by)
60
+ getDbOrNull().prepare(`INSERT INTO requirements (id, class, status, description, why, source, primary_owner, supporting_slices, validation, notes, full_content, superseded_by)
786
61
  VALUES (:id, :class, :status, :description, :why, :source, :primary_owner, :supporting_slices, :validation, :notes, :full_content, :superseded_by)`).run({
787
62
  ":id": r.id,
788
63
  ":class": r.class,
@@ -798,48 +73,13 @@ export function insertRequirement(r) {
798
73
  ":superseded_by": r.superseded_by,
799
74
  });
800
75
  }
801
- export function getRequirementById(id) {
802
- if (!currentDb)
803
- return null;
804
- const row = currentDb.prepare("SELECT * FROM requirements WHERE id = ?").get(id);
805
- if (!row)
806
- return null;
807
- return rowToRequirement(row);
808
- }
809
- export function getActiveRequirements() {
810
- if (!currentDb)
811
- return [];
812
- const rows = currentDb.prepare("SELECT * FROM active_requirements").all();
813
- return rows.map(rowToActiveRequirement);
814
- }
815
- export function getRequirementCounts() {
816
- if (!currentDb) {
817
- return { active: 0, validated: 0, deferred: 0, outOfScope: 0, blocked: 0, total: 0 };
818
- }
819
- const rows = currentDb
820
- .prepare("SELECT lower(status) as status, COUNT(*) as count FROM requirements GROUP BY lower(status)")
821
- .all();
822
- return rowsToRequirementCounts(rows);
823
- }
824
- export function getDbOwnerPid() {
825
- return currentPid;
826
- }
827
- export function getDbPath() {
828
- return currentPath;
829
- }
830
- export function _getAdapter() {
831
- return currentDb;
832
- }
833
- export function _resetProvider() {
834
- providerLoader.reset();
835
- }
836
76
  export function upsertDecision(d) {
837
- if (!currentDb)
77
+ if (!getDbOrNull())
838
78
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
839
79
  // Use ON CONFLICT DO UPDATE instead of INSERT OR REPLACE to preserve the
840
80
  // seq column. INSERT OR REPLACE deletes then reinserts, resetting seq and
841
81
  // corrupting decision ordering in DECISIONS.md after reconcile replay.
842
- currentDb.prepare(`INSERT INTO decisions (id, when_context, scope, decision, choice, rationale, revisable, made_by, source, superseded_by)
82
+ getDbOrNull().prepare(`INSERT INTO decisions (id, when_context, scope, decision, choice, rationale, revisable, made_by, source, superseded_by)
843
83
  VALUES (:id, :when_context, :scope, :decision, :choice, :rationale, :revisable, :made_by, :source, :superseded_by)
844
84
  ON CONFLICT(id) DO UPDATE SET
845
85
  when_context = excluded.when_context,
@@ -864,9 +104,9 @@ export function upsertDecision(d) {
864
104
  });
865
105
  }
866
106
  export function upsertRequirement(r) {
867
- if (!currentDb)
107
+ if (!getDbOrNull())
868
108
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
869
- currentDb.prepare(`INSERT OR REPLACE INTO requirements (id, class, status, description, why, source, primary_owner, supporting_slices, validation, notes, full_content, superseded_by)
109
+ getDbOrNull().prepare(`INSERT OR REPLACE INTO requirements (id, class, status, description, why, source, primary_owner, supporting_slices, validation, notes, full_content, superseded_by)
870
110
  VALUES (:id, :class, :status, :description, :why, :source, :primary_owner, :supporting_slices, :validation, :notes, :full_content, :superseded_by)`).run({
871
111
  ":id": r.id,
872
112
  ":class": r.class,
@@ -883,40 +123,40 @@ export function upsertRequirement(r) {
883
123
  });
884
124
  }
885
125
  export function clearArtifacts() {
886
- if (!currentDb)
126
+ if (!getDbOrNull())
887
127
  return;
888
128
  try {
889
- currentDb.exec("DELETE FROM artifacts");
129
+ getDbOrNull().exec("DELETE FROM artifacts");
890
130
  }
891
131
  catch (e) {
892
132
  logWarning("db", `clearArtifacts failed: ${e.message}`);
893
133
  }
894
134
  }
895
135
  export function clearDecisions() {
896
- if (!currentDb)
136
+ if (!getDbOrNull())
897
137
  return;
898
138
  try {
899
- currentDb.exec("DELETE FROM decisions");
139
+ getDbOrNull().exec("DELETE FROM decisions");
900
140
  }
901
141
  catch (e) {
902
142
  logWarning("db", `clearDecisions failed: ${e.message}`);
903
143
  }
904
144
  }
905
145
  export function clearRequirements() {
906
- if (!currentDb)
146
+ if (!getDbOrNull())
907
147
  return;
908
148
  try {
909
- currentDb.exec("DELETE FROM requirements");
149
+ getDbOrNull().exec("DELETE FROM requirements");
910
150
  }
911
151
  catch (e) {
912
152
  logWarning("db", `clearRequirements failed: ${e.message}`);
913
153
  }
914
154
  }
915
155
  export function insertArtifact(a) {
916
- if (!currentDb)
156
+ if (!getDbOrNull())
917
157
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
918
158
  const contentHash = createHash("sha256").update(a.full_content).digest("hex");
919
- currentDb.prepare(`INSERT OR REPLACE INTO artifacts (path, artifact_type, milestone_id, slice_id, task_id, full_content, imported_at, content_hash)
159
+ getDbOrNull().prepare(`INSERT OR REPLACE INTO artifacts (path, artifact_type, milestone_id, slice_id, task_id, full_content, imported_at, content_hash)
920
160
  VALUES (:path, :artifact_type, :milestone_id, :slice_id, :task_id, :full_content, :imported_at, :content_hash)`).run({
921
161
  ":path": a.path,
922
162
  ":artifact_type": a.artifact_type,
@@ -929,9 +169,9 @@ export function insertArtifact(a) {
929
169
  });
930
170
  }
931
171
  export function insertMilestone(m) {
932
- if (!currentDb)
172
+ if (!getDbOrNull())
933
173
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
934
- currentDb.prepare(`INSERT OR IGNORE INTO milestones (
174
+ const result = getDbOrNull().prepare(`INSERT OR IGNORE INTO milestones (
935
175
  id, title, status, depends_on, created_at,
936
176
  vision, success_criteria, key_risks, proof_strategy,
937
177
  verification_contract, verification_integration, verification_operational, verification_uat,
@@ -961,11 +201,12 @@ export function insertMilestone(m) {
961
201
  ":requirement_coverage": m.planning?.requirementCoverage ?? "",
962
202
  ":boundary_map_markdown": m.planning?.boundaryMapMarkdown ?? "",
963
203
  });
204
+ return (result.changes ?? 0) > 0;
964
205
  }
965
206
  export function upsertMilestonePlanning(milestoneId, planning) {
966
- if (!currentDb)
207
+ if (!getDbOrNull())
967
208
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
968
- currentDb.prepare(`UPDATE milestones SET
209
+ getDbOrNull().prepare(`UPDATE milestones SET
969
210
  title = COALESCE(NULLIF(:title, ''), title),
970
211
  status = COALESCE(NULLIF(:status, ''), status),
971
212
  depends_on = COALESCE(:depends_on, depends_on),
@@ -999,9 +240,14 @@ export function upsertMilestonePlanning(milestoneId, planning) {
999
240
  });
1000
241
  }
1001
242
  export function insertSlice(s) {
1002
- if (!currentDb)
243
+ if (!getDbOrNull())
1003
244
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1004
- currentDb.prepare(`INSERT INTO slices (
245
+ const SLICE_ID_RE = /^[A-Za-z0-9][A-Za-z0-9-]*$/;
246
+ const invalidDep = (s.depends ?? []).find(d => !SLICE_ID_RE.test(d));
247
+ if (invalidDep !== undefined) {
248
+ throw new GSDError(GSD_STALE_STATE, `insertSlice: depends element "${invalidDep}" is not a valid slice ID`);
249
+ }
250
+ getDbOrNull().prepare(`INSERT INTO slices (
1005
251
  milestone_id, id, title, status, risk, depends, demo, created_at,
1006
252
  goal, success_criteria, proof_level, integration_closure, observability_impact, target_repositories, sequence,
1007
253
  is_sketch, sketch_scope
@@ -1062,26 +308,14 @@ export function insertSlice(s) {
1062
308
  }
1063
309
  // ADR-011: sketch-then-refine helpers
1064
310
  export function setSliceSketchFlag(milestoneId, sliceId, isSketch) {
1065
- if (!currentDb)
311
+ if (!getDbOrNull())
1066
312
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1067
- currentDb.prepare(`UPDATE slices SET is_sketch = :is_sketch WHERE milestone_id = :mid AND id = :sid`).run({ ":is_sketch": isSketch ? 1 : 0, ":mid": milestoneId, ":sid": sliceId });
1068
- }
1069
- /**
1070
- * ADR-017 raw primitive: returns slice IDs in a milestone whose is_sketch flag
1071
- * is still 1. The stale-sketch-flag drift handler at
1072
- * `state-reconciliation/drift/sketch-flag.ts` composes this with PLAN.md
1073
- * existence checks to detect drift, then writes via `setSliceSketchFlag`.
1074
- */
1075
- export function getSketchedSliceIds(milestoneId) {
1076
- if (!currentDb)
1077
- return [];
1078
- const rows = currentDb.prepare(`SELECT id FROM slices WHERE milestone_id = :mid AND is_sketch = 1`).all({ ":mid": milestoneId });
1079
- return rows.map((r) => r.id);
313
+ getDbOrNull().prepare(`UPDATE slices SET is_sketch = :is_sketch WHERE milestone_id = :mid AND id = :sid`).run({ ":is_sketch": isSketch ? 1 : 0, ":mid": milestoneId, ":sid": sliceId });
1080
314
  }
1081
315
  export function upsertSlicePlanning(milestoneId, sliceId, planning) {
1082
- if (!currentDb)
316
+ if (!getDbOrNull())
1083
317
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1084
- currentDb.prepare(`UPDATE slices SET
318
+ getDbOrNull().prepare(`UPDATE slices SET
1085
319
  goal = COALESCE(:goal, goal),
1086
320
  success_criteria = COALESCE(:success_criteria, success_criteria),
1087
321
  proof_level = COALESCE(:proof_level, proof_level),
@@ -1100,9 +334,9 @@ export function upsertSlicePlanning(milestoneId, sliceId, planning) {
1100
334
  });
1101
335
  }
1102
336
  export function insertTask(t) {
1103
- if (!currentDb)
337
+ if (!getDbOrNull())
1104
338
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1105
- currentDb.prepare(`INSERT INTO tasks (
339
+ getDbOrNull().prepare(`INSERT INTO tasks (
1106
340
  milestone_id, slice_id, id, title, status, one_liner, narrative,
1107
341
  verification_result, duration, completed_at, blocker_discovered,
1108
342
  deviations, known_issues, key_files, key_decisions, full_summary_md,
@@ -1174,26 +408,17 @@ export function insertTask(t) {
1174
408
  });
1175
409
  }
1176
410
  export function updateTaskStatus(milestoneId, sliceId, taskId, status, completedAt) {
1177
- if (!currentDb)
1178
- throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1179
- currentDb.prepare(`UPDATE tasks SET status = :status, completed_at = :completed_at
1180
- WHERE milestone_id = :milestone_id AND slice_id = :slice_id AND id = :id`).run({
1181
- ":status": status,
1182
- ":completed_at": completedAt ?? null,
1183
- ":milestone_id": milestoneId,
1184
- ":slice_id": sliceId,
1185
- ":id": taskId,
1186
- });
411
+ applyStatusTransition({ entity: "task", milestoneId, sliceId, taskId, status, completedAt });
1187
412
  }
1188
413
  export function setTaskBlockerDiscovered(milestoneId, sliceId, taskId, discovered) {
1189
- if (!currentDb)
414
+ if (!getDbOrNull())
1190
415
  return;
1191
- currentDb.prepare(`UPDATE tasks SET blocker_discovered = :discovered WHERE milestone_id = :mid AND slice_id = :sid AND id = :tid`).run({ ":discovered": discovered ? 1 : 0, ":mid": milestoneId, ":sid": sliceId, ":tid": taskId });
416
+ getDbOrNull().prepare(`UPDATE tasks SET blocker_discovered = :discovered WHERE milestone_id = :mid AND slice_id = :sid AND id = :tid`).run({ ":discovered": discovered ? 1 : 0, ":mid": milestoneId, ":sid": sliceId, ":tid": taskId });
1192
417
  }
1193
418
  export function upsertTaskPlanning(milestoneId, sliceId, taskId, planning) {
1194
- if (!currentDb)
419
+ if (!getDbOrNull())
1195
420
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1196
- currentDb.prepare(`UPDATE tasks SET
421
+ getDbOrNull().prepare(`UPDATE tasks SET
1197
422
  title = COALESCE(:title, title),
1198
423
  description = COALESCE(:description, description),
1199
424
  estimate = COALESCE(:estimate, estimate),
@@ -1220,96 +445,25 @@ export function upsertTaskPlanning(milestoneId, sliceId, taskId, planning) {
1220
445
  ":target_repositories": planning.targetRepositories ? JSON.stringify(planning.targetRepositories) : null,
1221
446
  });
1222
447
  }
1223
- export function getSlice(milestoneId, sliceId) {
1224
- if (!currentDb)
1225
- return null;
1226
- const row = currentDb.prepare("SELECT * FROM slices WHERE milestone_id = :mid AND id = :sid").get({ ":mid": milestoneId, ":sid": sliceId });
1227
- if (!row)
1228
- return null;
1229
- return rowToSlice(row);
1230
- }
1231
448
  export function updateSliceStatus(milestoneId, sliceId, status, completedAt) {
1232
- if (!currentDb)
1233
- throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1234
- currentDb.prepare(`UPDATE slices SET status = :status, completed_at = :completed_at
1235
- WHERE milestone_id = :milestone_id AND id = :id`).run({
1236
- ":status": status,
1237
- ":completed_at": completedAt ?? null,
1238
- ":milestone_id": milestoneId,
1239
- ":id": sliceId,
1240
- });
449
+ applyStatusTransition({ entity: "slice", milestoneId, sliceId, status, completedAt });
1241
450
  }
1242
451
  export function setTaskSummaryMd(milestoneId, sliceId, taskId, md) {
1243
- if (!currentDb)
452
+ if (!getDbOrNull())
1244
453
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1245
- currentDb.prepare(`UPDATE tasks SET full_summary_md = :md WHERE milestone_id = :mid AND slice_id = :sid AND id = :tid`).run({ ":mid": milestoneId, ":sid": sliceId, ":tid": taskId, ":md": md });
454
+ getDbOrNull().prepare(`UPDATE tasks SET full_summary_md = :md WHERE milestone_id = :mid AND slice_id = :sid AND id = :tid`).run({ ":mid": milestoneId, ":sid": sliceId, ":tid": taskId, ":md": md });
1246
455
  }
1247
456
  export function setSliceSummaryMd(milestoneId, sliceId, summaryMd, uatMd) {
1248
- if (!currentDb)
457
+ if (!getDbOrNull())
1249
458
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1250
- currentDb.prepare(`UPDATE slices SET full_summary_md = :summary_md, full_uat_md = :uat_md WHERE milestone_id = :mid AND id = :sid`).run({ ":mid": milestoneId, ":sid": sliceId, ":summary_md": summaryMd, ":uat_md": uatMd });
1251
- }
1252
- export function getTask(milestoneId, sliceId, taskId) {
1253
- if (!currentDb)
1254
- return null;
1255
- 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 });
1256
- if (!row)
1257
- return null;
1258
- return rowToTask(row);
1259
- }
1260
- export function getSliceTasks(milestoneId, sliceId) {
1261
- if (!currentDb)
1262
- return [];
1263
- const rows = currentDb.prepare("SELECT * FROM tasks WHERE milestone_id = :mid AND slice_id = :sid ORDER BY sequence, id").all({ ":mid": milestoneId, ":sid": sliceId });
1264
- return rows.map(rowToTask);
1265
- }
1266
- export function getCompletedMilestoneTaskFileHints(milestoneId) {
1267
- if (!currentDb)
1268
- return [];
1269
- const rows = currentDb.prepare(`SELECT files, key_files
1270
- FROM tasks
1271
- WHERE milestone_id = :mid AND status IN ('complete', 'done')`).all({ ":mid": milestoneId });
1272
- const hints = new Set();
1273
- for (const row of rows) {
1274
- for (const raw of [row["files"], row["key_files"]]) {
1275
- for (const file of parseStringArrayColumn(raw)) {
1276
- const normalized = normalizeRepoPath(file);
1277
- if (normalized)
1278
- hints.add(normalized);
1279
- }
1280
- }
1281
- }
1282
- return [...hints];
1283
- }
1284
- function parseStringArrayColumn(raw) {
1285
- if (Array.isArray(raw))
1286
- return raw.filter((entry) => typeof entry === "string");
1287
- if (typeof raw !== "string")
1288
- return [];
1289
- const trimmed = raw.trim();
1290
- if (!trimmed)
1291
- return [];
1292
- try {
1293
- const parsed = JSON.parse(trimmed);
1294
- if (Array.isArray(parsed))
1295
- return parsed.filter((entry) => typeof entry === "string");
1296
- if (typeof parsed === "string")
1297
- return [parsed];
1298
- }
1299
- catch {
1300
- return trimmed.split(",");
1301
- }
1302
- return [];
1303
- }
1304
- function normalizeRepoPath(file) {
1305
- return file.trim().replace(/\\/g, "/").replace(/^\.\/+/, "");
459
+ getDbOrNull().prepare(`UPDATE slices SET full_summary_md = :summary_md, full_uat_md = :uat_md WHERE milestone_id = :mid AND id = :sid`).run({ ":mid": milestoneId, ":sid": sliceId, ":summary_md": summaryMd, ":uat_md": uatMd });
1306
460
  }
1307
461
  // ─── ADR-011 Phase 2 escalation helpers ──────────────────────────────────
1308
462
  /** Set pause-on-escalation state on a completed task. Mutually exclusive with awaiting_review. */
1309
463
  export function setTaskEscalationPending(milestoneId, sliceId, taskId, artifactPath) {
1310
- if (!currentDb)
464
+ if (!getDbOrNull())
1311
465
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1312
- currentDb.prepare(`UPDATE tasks
466
+ getDbOrNull().prepare(`UPDATE tasks
1313
467
  SET escalation_pending = 1,
1314
468
  escalation_awaiting_review = 0,
1315
469
  escalation_artifact_path = :path
@@ -1317,9 +471,9 @@ export function setTaskEscalationPending(milestoneId, sliceId, taskId, artifactP
1317
471
  }
1318
472
  /** Set awaiting-review state (artifact exists and requires explicit user review). Mutually exclusive with pending. */
1319
473
  export function setTaskEscalationAwaitingReview(milestoneId, sliceId, taskId, artifactPath) {
1320
- if (!currentDb)
474
+ if (!getDbOrNull())
1321
475
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1322
- currentDb.prepare(`UPDATE tasks
476
+ getDbOrNull().prepare(`UPDATE tasks
1323
477
  SET escalation_awaiting_review = 1,
1324
478
  escalation_pending = 0,
1325
479
  escalation_artifact_path = :path
@@ -1327,9 +481,9 @@ export function setTaskEscalationAwaitingReview(milestoneId, sliceId, taskId, ar
1327
481
  }
1328
482
  /** Clear escalation-pending and awaiting-review flags once the user has resolved it. */
1329
483
  export function clearTaskEscalationFlags(milestoneId, sliceId, taskId) {
1330
- if (!currentDb)
484
+ if (!getDbOrNull())
1331
485
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1332
- currentDb.prepare(`UPDATE tasks
486
+ getDbOrNull().prepare(`UPDATE tasks
1333
487
  SET escalation_pending = 0,
1334
488
  escalation_awaiting_review = 0
1335
489
  WHERE milestone_id = :mid AND slice_id = :sid AND id = :tid`).run({ ":mid": milestoneId, ":sid": sliceId, ":tid": taskId });
@@ -1340,10 +494,10 @@ export function clearTaskEscalationFlags(milestoneId, sliceId, taskId) {
1340
494
  * another caller already claimed it (must skip).
1341
495
  */
1342
496
  export function claimEscalationOverride(milestoneId, sliceId, sourceTaskId) {
1343
- if (!currentDb)
497
+ if (!getDbOrNull())
1344
498
  return false;
1345
499
  const now = new Date().toISOString();
1346
- const result = currentDb.prepare(`UPDATE tasks
500
+ const result = getDbOrNull().prepare(`UPDATE tasks
1347
501
  SET escalation_override_applied_at = :now
1348
502
  WHERE milestone_id = :mid AND slice_id = :sid AND id = :tid
1349
503
  AND escalation_override_applied_at IS NULL
@@ -1352,51 +506,19 @@ export function claimEscalationOverride(milestoneId, sliceId, sourceTaskId) {
1352
506
  const changes = result.changes ?? 0;
1353
507
  return changes > 0;
1354
508
  }
1355
- /** Find the most recent resolved-but-unapplied escalation override in a slice. */
1356
- export function findUnappliedEscalationOverride(milestoneId, sliceId) {
1357
- if (!currentDb)
1358
- return null;
1359
- // Filter BOTH flags: escalation_pending=0 AND escalation_awaiting_review=0
1360
- // ensures we only claim overrides the user has explicitly resolved.
1361
- // Without the awaiting_review filter, continueWithDefault=true artifacts
1362
- // (not yet responded to) would be prematurely claimed, causing the override
1363
- // to be lost when the user later resolves (#ADR-011 Phase 2 peer-review Bug 2).
1364
- const row = currentDb.prepare(`SELECT id, escalation_artifact_path AS path
1365
- FROM tasks
1366
- WHERE milestone_id = :mid AND slice_id = :sid
1367
- AND escalation_artifact_path IS NOT NULL
1368
- AND escalation_override_applied_at IS NULL
1369
- AND escalation_pending = 0
1370
- AND escalation_awaiting_review = 0
1371
- ORDER BY sequence DESC, id DESC
1372
- LIMIT 1`).get({ ":mid": milestoneId, ":sid": sliceId });
1373
- if (!row || !row.path)
1374
- return null;
1375
- return { taskId: row.id, artifactPath: row.path };
1376
- }
1377
509
  /** Set the blocker_source provenance field (used when rejecting an escalation). */
1378
510
  export function setTaskBlockerSource(milestoneId, sliceId, taskId, source) {
1379
- if (!currentDb)
511
+ if (!getDbOrNull())
1380
512
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1381
- currentDb.prepare(`UPDATE tasks
513
+ getDbOrNull().prepare(`UPDATE tasks
1382
514
  SET blocker_discovered = 1,
1383
515
  blocker_source = :src
1384
516
  WHERE milestone_id = :mid AND slice_id = :sid AND id = :tid`).run({ ":src": source, ":mid": milestoneId, ":sid": sliceId, ":tid": taskId });
1385
517
  }
1386
- /** List tasks with active escalation artifacts across a milestone (for /gsd escalate list). */
1387
- export function listEscalationArtifacts(milestoneId, includeResolved = false) {
1388
- if (!currentDb)
1389
- return [];
1390
- const filter = includeResolved
1391
- ? "escalation_artifact_path IS NOT NULL"
1392
- : "(escalation_pending = 1 OR escalation_awaiting_review = 1) AND escalation_artifact_path IS NOT NULL";
1393
- const rows = currentDb.prepare(`SELECT * FROM tasks WHERE milestone_id = :mid AND ${filter} ORDER BY slice_id, sequence, id`).all({ ":mid": milestoneId });
1394
- return rows.map(rowToTask);
1395
- }
1396
518
  export function insertVerificationEvidence(e) {
1397
- if (!currentDb)
519
+ if (!getDbOrNull())
1398
520
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1399
- currentDb.prepare(`INSERT OR IGNORE INTO verification_evidence (task_id, slice_id, milestone_id, command, exit_code, verdict, duration_ms, created_at)
521
+ getDbOrNull().prepare(`INSERT OR IGNORE INTO verification_evidence (task_id, slice_id, milestone_id, command, exit_code, verdict, duration_ms, created_at)
1400
522
  VALUES (:task_id, :slice_id, :milestone_id, :command, :exit_code, :verdict, :duration_ms, :created_at)`).run({
1401
523
  ":task_id": e.taskId,
1402
524
  ":slice_id": e.sliceId,
@@ -1408,53 +530,26 @@ export function insertVerificationEvidence(e) {
1408
530
  ":created_at": new Date().toISOString(),
1409
531
  });
1410
532
  }
1411
- export function getVerificationEvidence(milestoneId, sliceId, taskId) {
1412
- if (!currentDb)
1413
- return [];
1414
- const rows = currentDb.prepare("SELECT * FROM verification_evidence WHERE milestone_id = :mid AND slice_id = :sid AND task_id = :tid ORDER BY id").all({ ":mid": milestoneId, ":sid": sliceId, ":tid": taskId });
1415
- return rows;
1416
- }
1417
- export function getAllMilestones() {
1418
- if (!currentDb)
1419
- return [];
1420
- const rows = currentDb.prepare("SELECT * FROM milestones ORDER BY CASE WHEN sequence > 0 THEN 0 ELSE 1 END, sequence, id").all();
1421
- return rows.map(rowToMilestone);
1422
- }
1423
- export function getMilestone(id) {
1424
- if (!currentDb)
1425
- return null;
1426
- const row = currentDb.prepare("SELECT * FROM milestones WHERE id = :id").get({ ":id": id });
1427
- if (!row)
1428
- return null;
1429
- return rowToMilestone(row);
1430
- }
1431
533
  export function setMilestoneQueueOrder(order) {
1432
- if (!currentDb)
1433
- throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1434
- currentDb.exec("BEGIN IMMEDIATE");
1435
- try {
1436
- currentDb.prepare("UPDATE milestones SET sequence = 0").run();
1437
- const stmt = currentDb.prepare("UPDATE milestones SET sequence = :sequence WHERE id = :id");
534
+ const db = getDb();
535
+ immediateTransaction(() => {
536
+ db.prepare("UPDATE milestones SET sequence = 0").run();
537
+ const stmt = db.prepare("UPDATE milestones SET sequence = :sequence WHERE id = :id");
1438
538
  order.forEach((id, index) => {
1439
539
  stmt.run({ ":id": id, ":sequence": index + 1 });
1440
540
  });
1441
- currentDb.exec("COMMIT");
1442
- }
1443
- catch (err) {
1444
- currentDb.exec("ROLLBACK");
1445
- throw err;
1446
- }
541
+ });
1447
542
  }
1448
543
  function getMilestoneStatusForUpdate(milestoneId) {
1449
- if (!currentDb)
544
+ if (!getDbOrNull())
1450
545
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1451
- const row = currentDb.prepare("SELECT status FROM milestones WHERE id = :id").get({ ":id": milestoneId });
546
+ const row = getDbOrNull().prepare("SELECT status FROM milestones WHERE id = :id").get({ ":id": milestoneId });
1452
547
  return typeof row?.["status"] === "string" ? row["status"] : null;
1453
548
  }
1454
549
  function writeMilestoneStatus(milestoneId, status, completedAt) {
1455
- if (!currentDb)
550
+ if (!getDbOrNull())
1456
551
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1457
- currentDb.prepare(`UPDATE milestones SET status = :status, completed_at = :completed_at WHERE id = :id`).run({ ":status": status, ":completed_at": completedAt ?? null, ":id": milestoneId });
552
+ getDbOrNull().prepare(`UPDATE milestones SET status = :status, completed_at = :completed_at WHERE id = :id`).run({ ":status": status, ":completed_at": completedAt ?? null, ":id": milestoneId });
1458
553
  }
1459
554
  /**
1460
555
  * Update a milestone's status in the database.
@@ -1464,19 +559,13 @@ function writeMilestoneStatus(milestoneId, status, completedAt) {
1464
559
  * must use reopenMilestoneStatus(), which is reserved for gsd_milestone_reopen.
1465
560
  */
1466
561
  export function updateMilestoneStatus(milestoneId, status, completedAt) {
1467
- if (!currentDb)
1468
- throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1469
- const currentStatus = getMilestoneStatusForUpdate(milestoneId);
1470
- if (currentStatus && isClosedStatus(currentStatus) && !isClosedStatus(status)) {
1471
- throw new Error(`Cannot update closed milestone ${milestoneId} from ${currentStatus} to ${status}; use gsd_milestone_reopen for an explicit reopen.`);
1472
- }
1473
- writeMilestoneStatus(milestoneId, status, completedAt);
562
+ applyStatusTransition({ entity: "milestone", milestoneId, status, completedAt });
1474
563
  }
1475
564
  /**
1476
565
  * Explicit closed -> active transition for gsd_milestone_reopen only.
1477
566
  */
1478
567
  export function reopenMilestoneStatus(milestoneId) {
1479
- if (!currentDb)
568
+ if (!getDbOrNull())
1480
569
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1481
570
  const currentStatus = getMilestoneStatusForUpdate(milestoneId);
1482
571
  if (!currentStatus) {
@@ -1487,562 +576,24 @@ export function reopenMilestoneStatus(milestoneId) {
1487
576
  }
1488
577
  writeMilestoneStatus(milestoneId, "active", null);
1489
578
  }
1490
- export function getActiveMilestoneFromDb() {
1491
- if (!currentDb)
1492
- return null;
1493
- const row = currentDb.prepare("SELECT * FROM milestones WHERE status NOT IN ('complete', 'done', 'skipped', 'closed', 'parked') ORDER BY id LIMIT 1").get();
1494
- if (!row)
1495
- return null;
1496
- return rowToMilestone(row);
1497
- }
1498
- export function getActiveSliceFromDb(milestoneId) {
1499
- if (!currentDb)
1500
- return null;
1501
- // Single query: find the first non-complete slice whose dependencies are all satisfied.
1502
- // Uses json_each() to expand the JSON depends array and checks each dep is complete.
1503
- const row = currentDb.prepare(`SELECT s.* FROM slices s
1504
- WHERE s.milestone_id = :mid
1505
- AND s.status NOT IN ('complete', 'done', 'skipped')
1506
- AND NOT EXISTS (
1507
- SELECT 1 FROM json_each(s.depends) AS dep
1508
- WHERE dep.value NOT IN (
1509
- SELECT id FROM slices WHERE milestone_id = :mid AND status IN ('complete', 'done', 'skipped')
1510
- )
1511
- )
1512
- ORDER BY s.sequence, s.id
1513
- LIMIT 1`).get({ ":mid": milestoneId });
1514
- if (!row)
1515
- return null;
1516
- return rowToSlice(row);
1517
- }
1518
- export function getActiveTaskFromDb(milestoneId, sliceId) {
1519
- if (!currentDb)
1520
- return null;
1521
- 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 });
1522
- if (!row)
1523
- return null;
1524
- return rowToTask(row);
1525
- }
1526
- export function getMilestoneSlices(milestoneId) {
1527
- if (!currentDb)
1528
- return [];
1529
- const rows = currentDb.prepare("SELECT * FROM slices WHERE milestone_id = :mid ORDER BY sequence, id").all({ ":mid": milestoneId });
1530
- return rows.map(rowToSlice);
1531
- }
1532
- export function getArtifact(path) {
1533
- if (!currentDb)
1534
- return null;
1535
- const row = currentDb.prepare("SELECT * FROM artifacts WHERE path = :path").get({ ":path": path });
1536
- if (!row)
1537
- return null;
1538
- return rowToArtifact(row);
1539
- }
1540
579
  // ─── Lightweight Query Variants (hot-path optimized) ─────────────────────
1541
- /** Fast milestone status check — avoids deserializing JSON planning fields. */
1542
- export function getActiveMilestoneIdFromDb() {
1543
- if (!currentDb)
1544
- return null;
1545
- const row = currentDb.prepare("SELECT id, status FROM milestones WHERE status NOT IN ('complete', 'done', 'skipped', 'closed', 'parked') ORDER BY id LIMIT 1").get();
1546
- if (!row)
1547
- return null;
1548
- return rowToIdStatusSummary(row);
1549
- }
1550
- /** Fast slice status check — avoids deserializing JSON depends/planning fields. */
1551
- export function getSliceStatusSummary(milestoneId) {
1552
- if (!currentDb)
1553
- return [];
1554
- return currentDb.prepare("SELECT id, status FROM slices WHERE milestone_id = :mid ORDER BY sequence, id").all({ ":mid": milestoneId }).map(rowToIdStatusSummary);
1555
- }
1556
- /** Fast task status check — avoids deserializing JSON arrays and large text fields. */
1557
- export function getActiveTaskIdFromDb(milestoneId, sliceId) {
1558
- if (!currentDb)
1559
- return null;
1560
- const row = currentDb.prepare("SELECT id, status, title 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 });
1561
- if (!row)
1562
- return null;
1563
- return rowToActiveTaskSummary(row);
1564
- }
1565
- /** Count tasks by status for a slice — useful for progress reporting without full row load. */
1566
- export function getSliceTaskCounts(milestoneId, sliceId) {
1567
- if (!currentDb)
1568
- return emptyTaskStatusCounts();
1569
- const row = currentDb.prepare(`SELECT
1570
- COUNT(*) as total,
1571
- SUM(CASE WHEN status IN ('complete', 'done') THEN 1 ELSE 0 END) as done,
1572
- SUM(CASE WHEN status NOT IN ('complete', 'done') THEN 1 ELSE 0 END) as pending
1573
- FROM tasks WHERE milestone_id = :mid AND slice_id = :sid`).get({ ":mid": milestoneId, ":sid": sliceId });
1574
- return rowToTaskStatusCounts(row);
1575
- }
1576
580
  // ─── Slice Dependencies (junction table) ─────────────────────────────────
1577
581
  /** Sync the slice_dependencies junction table from a slice's JSON depends array. */
1578
582
  export function syncSliceDependencies(milestoneId, sliceId, depends) {
1579
- if (!currentDb)
583
+ if (!getDbOrNull())
1580
584
  return;
1581
- currentDb.prepare("DELETE FROM slice_dependencies WHERE milestone_id = :mid AND slice_id = :sid").run({ ":mid": milestoneId, ":sid": sliceId });
585
+ getDbOrNull().prepare("DELETE FROM slice_dependencies WHERE milestone_id = :mid AND slice_id = :sid").run({ ":mid": milestoneId, ":sid": sliceId });
1582
586
  for (const dep of depends) {
1583
- currentDb.prepare("INSERT OR IGNORE INTO slice_dependencies (milestone_id, slice_id, depends_on_slice_id) VALUES (:mid, :sid, :dep)").run({ ":mid": milestoneId, ":sid": sliceId, ":dep": dep });
587
+ getDbOrNull().prepare("INSERT OR IGNORE INTO slice_dependencies (milestone_id, slice_id, depends_on_slice_id) VALUES (:mid, :sid, :dep)").run({ ":mid": milestoneId, ":sid": sliceId, ":dep": dep });
1584
588
  }
1585
589
  }
1586
- /** Get all slices that depend on a given slice. */
1587
- export function getDependentSlices(milestoneId, sliceId) {
1588
- if (!currentDb)
1589
- return [];
1590
- const rows = currentDb.prepare("SELECT slice_id FROM slice_dependencies WHERE milestone_id = :mid AND depends_on_slice_id = :sid").all({ ":mid": milestoneId, ":sid": sliceId });
1591
- return rowsToStringColumn(rows, "slice_id");
1592
- }
1593
590
  // ─── Worktree DB Helpers ──────────────────────────────────────────────────
1594
- export function copyWorktreeDb(srcDbPath, destDbPath) {
1595
- try {
1596
- if (!existsSync(srcDbPath))
1597
- return false;
1598
- const destDir = dirname(destDbPath);
1599
- mkdirSync(destDir, { recursive: true });
1600
- copyFileSync(srcDbPath, destDbPath);
1601
- return true;
1602
- }
1603
- catch (err) {
1604
- logError("db", "failed to copy DB to worktree", { error: err.message });
1605
- return false;
1606
- }
1607
- }
1608
- export function reconcileWorktreeDb(mainDbPath, worktreeDbPath) {
1609
- const zero = {
1610
- decisions: 0,
1611
- requirements: 0,
1612
- artifacts: 0,
1613
- milestones: 0,
1614
- slices: 0,
1615
- tasks: 0,
1616
- memories: 0,
1617
- replan_history: 0,
1618
- assessments: 0,
1619
- quality_gates: 0,
1620
- slice_dependencies: 0,
1621
- verification_evidence: 0,
1622
- gate_runs: 0,
1623
- milestone_commit_attributions: 0,
1624
- conflicts: [],
1625
- };
1626
- if (!existsSync(worktreeDbPath))
1627
- return zero;
1628
- // Guard: bail when both paths resolve to the same physical file.
1629
- // ATTACHing a WAL-mode DB to itself corrupts the WAL (#2823).
1630
- try {
1631
- if (realpathSync(mainDbPath) === realpathSync(worktreeDbPath))
1632
- return zero;
1633
- }
1634
- catch (e) {
1635
- logWarning("db", `realpathSync failed: ${e.message}`);
1636
- }
1637
- // Sanitize path: reject any characters that could break ATTACH syntax.
1638
- // ATTACH DATABASE doesn't support parameterized paths in all providers,
1639
- // so we use strict allowlist validation instead.
1640
- if (/['";\x00]/.test(worktreeDbPath)) {
1641
- logError("db", "worktree DB reconciliation failed: path contains unsafe characters");
1642
- return zero;
1643
- }
1644
- if (!currentDb) {
1645
- const opened = openDatabase(mainDbPath);
1646
- if (!opened) {
1647
- logError("db", "worktree DB reconciliation failed: cannot open main DB");
1648
- return zero;
1649
- }
1650
- }
1651
- const adapter = currentDb;
1652
- const conflicts = [];
1653
- try {
1654
- adapter.exec(`ATTACH DATABASE '${worktreeDbPath}' AS wt`);
1655
- try {
1656
- function countChanges(result) {
1657
- return typeof result === "object" && result !== null ? (result.changes ?? 0) : 0;
1658
- }
1659
- function wtTableInfo(tableName) {
1660
- return adapter.prepare(`PRAGMA wt.table_info('${tableName}')`).all();
1661
- }
1662
- const wtInfo = wtTableInfo("decisions");
1663
- const hasWtDecisions = wtInfo.length > 0;
1664
- const hasMadeBy = wtInfo.some((col) => col["name"] === "made_by");
1665
- // ADR-011: worktree may predate schema v16/v17. For missing columns we
1666
- // fall through to the main DB's existing value (not a literal default)
1667
- // so reconcile never silently clears state the main tree has recorded.
1668
- const hasDecisionSource = wtInfo.some((col) => col["name"] === "source");
1669
- const wtRequirementInfo = wtTableInfo("requirements");
1670
- const hasWtRequirements = wtRequirementInfo.length > 0;
1671
- const wtMilestoneInfo = wtTableInfo("milestones");
1672
- const hasWtMilestones = wtMilestoneInfo.length > 0;
1673
- const hasMilestoneSequence = wtMilestoneInfo.some((col) => col["name"] === "sequence");
1674
- const wtSliceInfo = wtTableInfo("slices");
1675
- const hasWtSlices = wtSliceInfo.length > 0;
1676
- const hasIsSketch = wtSliceInfo.some((col) => col["name"] === "is_sketch");
1677
- const hasSketchScope = wtSliceInfo.some((col) => col["name"] === "sketch_scope");
1678
- const hasSliceTargetRepositories = wtSliceInfo.some((col) => col["name"] === "target_repositories");
1679
- const wtTaskInfo = wtTableInfo("tasks");
1680
- const hasWtTasks = wtTaskInfo.length > 0;
1681
- const hasTaskTargetRepositories = wtTaskInfo.some((col) => col["name"] === "target_repositories");
1682
- const hasBlockerSource = wtTaskInfo.some((col) => col["name"] === "blocker_source");
1683
- const hasEscalationPending = wtTaskInfo.some((col) => col["name"] === "escalation_pending");
1684
- const hasEscalationAwaiting = wtTaskInfo.some((col) => col["name"] === "escalation_awaiting_review");
1685
- const hasEscalationArtifact = wtTaskInfo.some((col) => col["name"] === "escalation_artifact_path");
1686
- const hasEscalationOverride = wtTaskInfo.some((col) => col["name"] === "escalation_override_applied_at");
1687
- const wtArtifactInfo = wtTableInfo("artifacts");
1688
- const hasWtArtifacts = wtArtifactInfo.length > 0;
1689
- const wtMemoryInfo = wtTableInfo("memories");
1690
- const hasWtMemories = wtMemoryInfo.length > 0;
1691
- const hasMemoryScope = wtMemoryInfo.some((col) => col["name"] === "scope");
1692
- const hasMemoryTags = wtMemoryInfo.some((col) => col["name"] === "tags");
1693
- const hasMemoryStructuredFields = wtMemoryInfo.some((col) => col["name"] === "structured_fields");
1694
- const hasMemoryLastHitAt = wtMemoryInfo.some((col) => col["name"] === "last_hit_at");
1695
- const hasWtReplanHistory = wtTableInfo("replan_history").length > 0;
1696
- const hasWtAssessments = wtTableInfo("assessments").length > 0;
1697
- const hasWtQualityGates = wtTableInfo("quality_gates").length > 0;
1698
- const hasWtSliceDependencies = wtTableInfo("slice_dependencies").length > 0;
1699
- const hasWtVerificationEvidence = wtTableInfo("verification_evidence").length > 0;
1700
- const hasWtGateRuns = wtTableInfo("gate_runs").length > 0;
1701
- const hasWtMilestoneCommitAttributions = wtTableInfo("milestone_commit_attributions").length > 0;
1702
- if (hasWtDecisions) {
1703
- 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();
1704
- for (const row of decConf)
1705
- conflicts.push(`decision ${row["id"]}: modified in both`);
1706
- }
1707
- if (hasWtRequirements) {
1708
- 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();
1709
- for (const row of reqConf)
1710
- conflicts.push(`requirement ${row["id"]}: modified in both`);
1711
- }
1712
- const merged = {
1713
- decisions: 0,
1714
- requirements: 0,
1715
- artifacts: 0,
1716
- milestones: 0,
1717
- slices: 0,
1718
- tasks: 0,
1719
- memories: 0,
1720
- replan_history: 0,
1721
- assessments: 0,
1722
- quality_gates: 0,
1723
- slice_dependencies: 0,
1724
- verification_evidence: 0,
1725
- gate_runs: 0,
1726
- milestone_commit_attributions: 0,
1727
- };
1728
- const sliceTargetRepositoriesSql = hasSliceTargetRepositories
1729
- ? `CASE
1730
- WHEN w.target_repositories = '[]' AND COALESCE(m.target_repositories, '[]') <> '[]'
1731
- THEN m.target_repositories
1732
- ELSE COALESCE(w.target_repositories, m.target_repositories, '[]')
1733
- END`
1734
- : "COALESCE(m.target_repositories, '[]')";
1735
- const taskTargetRepositoriesSql = hasTaskTargetRepositories
1736
- ? `CASE
1737
- WHEN w.target_repositories = '[]' AND COALESCE(m.target_repositories, '[]') <> '[]'
1738
- THEN m.target_repositories
1739
- ELSE COALESCE(w.target_repositories, m.target_repositories, '[]')
1740
- END`
1741
- : "COALESCE(m.target_repositories, '[]')";
1742
- adapter.exec("BEGIN");
1743
- try {
1744
- // Join the target decisions so we can prefer an existing main.source
1745
- // when the worktree predates v16 — otherwise a write-through reconcile
1746
- // would clobber 'escalation'-sourced decisions with the literal default.
1747
- if (hasWtDecisions) {
1748
- merged.decisions = countChanges(adapter.prepare(`
1749
- INSERT INTO decisions (
1750
- id, when_context, scope, decision, choice, rationale, revisable, made_by, source, superseded_by
1751
- )
1752
- SELECT w.id, w.when_context, w.scope, w.decision, w.choice, w.rationale, w.revisable, ${hasMadeBy ? "w.made_by" : "COALESCE(m.made_by, 'agent')"}, ${hasDecisionSource ? "w.source" : "COALESCE(m.source, 'discussion')"}, w.superseded_by
1753
- FROM wt.decisions w
1754
- LEFT JOIN decisions m ON m.id = w.id
1755
- WHERE true
1756
- ON CONFLICT(id) DO UPDATE SET
1757
- when_context = excluded.when_context,
1758
- scope = excluded.scope,
1759
- decision = excluded.decision,
1760
- choice = excluded.choice,
1761
- rationale = excluded.rationale,
1762
- revisable = excluded.revisable,
1763
- made_by = excluded.made_by,
1764
- source = excluded.source,
1765
- superseded_by = excluded.superseded_by
1766
- `).run());
1767
- }
1768
- if (hasWtRequirements) {
1769
- merged.requirements = countChanges(adapter.prepare(`
1770
- INSERT OR REPLACE INTO requirements (
1771
- id, class, status, description, why, source, primary_owner,
1772
- supporting_slices, validation, notes, full_content, superseded_by
1773
- )
1774
- SELECT id, class, status, description, why, source, primary_owner,
1775
- supporting_slices, validation, notes, full_content, superseded_by
1776
- FROM wt.requirements
1777
- `).run());
1778
- }
1779
- // Always recompute artifact hashes from the content being merged. Older
1780
- // worktree DBs may not have content_hash at all, and migrated old DBs can
1781
- // carry stale default/null hashes after their content changed.
1782
- if (hasWtArtifacts) {
1783
- const artifactRows = adapter.prepare(`
1784
- SELECT path, artifact_type, milestone_id, slice_id, task_id, full_content, imported_at
1785
- FROM wt.artifacts
1786
- `).all();
1787
- const artifactStmt = adapter.prepare(`
1788
- INSERT OR REPLACE INTO artifacts (
1789
- path, artifact_type, milestone_id, slice_id, task_id, full_content, imported_at, content_hash
1790
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
1791
- `);
1792
- for (const row of artifactRows) {
1793
- const fullContent = String(row["full_content"] ?? "");
1794
- merged.artifacts += countChanges(artifactStmt.run(row["path"], row["artifact_type"], row["milestone_id"] ?? null, row["slice_id"] ?? null, row["task_id"] ?? null, fullContent, row["imported_at"], createHash("sha256").update(fullContent).digest("hex")));
1795
- }
1796
- }
1797
- // Merge milestones — worktree may have updated status/planning fields.
1798
- // Never downgrade status: complete > active > pre-planning (#4372).
1799
- // A stale worktree may carry an older 'active' status for a milestone
1800
- // that the main DB has already marked 'complete'; preserve the higher status.
1801
- if (hasWtMilestones) {
1802
- merged.milestones = countChanges(adapter.prepare(`
1803
- INSERT OR REPLACE INTO milestones (
1804
- id, title, status, depends_on, created_at, completed_at,
1805
- vision, success_criteria, key_risks, proof_strategy,
1806
- verification_contract, verification_integration, verification_operational, verification_uat,
1807
- definition_of_done, requirement_coverage, boundary_map_markdown, sequence
1808
- )
1809
- SELECT w.id, w.title,
1810
- CASE
1811
- WHEN m.status IN (${TERMINAL_STATUS_SQL}) AND w.status NOT IN (${TERMINAL_STATUS_SQL})
1812
- THEN m.status ELSE w.status
1813
- END,
1814
- w.depends_on,
1815
- CASE
1816
- WHEN m.status IN (${TERMINAL_STATUS_SQL}) AND w.status NOT IN (${TERMINAL_STATUS_SQL})
1817
- THEN m.created_at ELSE w.created_at
1818
- END,
1819
- CASE
1820
- WHEN m.status IN (${TERMINAL_STATUS_SQL}) AND w.status NOT IN (${TERMINAL_STATUS_SQL})
1821
- THEN m.completed_at ELSE w.completed_at
1822
- END,
1823
- w.vision, w.success_criteria, w.key_risks, w.proof_strategy,
1824
- w.verification_contract, w.verification_integration, w.verification_operational, w.verification_uat,
1825
- w.definition_of_done, w.requirement_coverage, w.boundary_map_markdown,
1826
- ${hasMilestoneSequence ? "COALESCE(w.sequence, 0)" : "COALESCE(m.sequence, 0)"}
1827
- FROM wt.milestones w
1828
- LEFT JOIN milestones m ON m.id = w.id
1829
- `).run());
1830
- }
1831
- // Merge slices — preserve worktree progress but never downgrade completed status (#2558).
1832
- // ADR-011 Phase 1: carry is_sketch + sketch_scope so reconcile doesn't
1833
- // silently clear sketch metadata. When the worktree predates v16,
1834
- // fall back to the main DB's existing value rather than a literal 0/''.
1835
- if (hasWtSlices) {
1836
- merged.slices = countChanges(adapter.prepare(`
1837
- INSERT OR REPLACE INTO slices (
1838
- milestone_id, id, title, status, risk, depends, demo, created_at, completed_at,
1839
- full_summary_md, full_uat_md, goal, success_criteria, proof_level,
1840
- integration_closure, observability_impact, target_repositories, sequence, replan_triggered_at,
1841
- is_sketch, sketch_scope
1842
- )
1843
- SELECT w.milestone_id, w.id, w.title,
1844
- CASE
1845
- WHEN m.status IN (${TERMINAL_STATUS_SQL}) AND w.status NOT IN (${TERMINAL_STATUS_SQL})
1846
- THEN m.status ELSE w.status
1847
- END,
1848
- w.risk, w.depends, w.demo, w.created_at,
1849
- CASE
1850
- WHEN m.status IN (${TERMINAL_STATUS_SQL}) AND w.status NOT IN (${TERMINAL_STATUS_SQL})
1851
- THEN m.completed_at ELSE w.completed_at
1852
- END,
1853
- w.full_summary_md, w.full_uat_md, w.goal, w.success_criteria, w.proof_level,
1854
- w.integration_closure, w.observability_impact,
1855
- ${sliceTargetRepositoriesSql},
1856
- w.sequence, w.replan_triggered_at,
1857
- ${hasIsSketch ? "w.is_sketch" : "COALESCE(m.is_sketch, 0)"},
1858
- ${hasSketchScope ? "w.sketch_scope" : "COALESCE(m.sketch_scope, '')"}
1859
- FROM wt.slices w
1860
- LEFT JOIN slices m ON m.milestone_id = w.milestone_id AND m.id = w.id
1861
- `).run());
1862
- }
1863
- // Merge tasks — preserve execution results, never downgrade completed status (#2558).
1864
- // ADR-011 P2: carry blocker_source + escalation_* columns so worktree reconcile
1865
- // doesn't silently clear escalation state back to defaults.
1866
- if (hasWtTasks) {
1867
- merged.tasks = countChanges(adapter.prepare(`
1868
- INSERT OR REPLACE INTO tasks (
1869
- milestone_id, slice_id, id, title, status, one_liner, narrative,
1870
- verification_result, duration, completed_at, blocker_discovered,
1871
- deviations, known_issues, key_files, key_decisions, full_summary_md,
1872
- description, estimate, files, verify, inputs, expected_output,
1873
- observability_impact, full_plan_md, target_repositories, sequence,
1874
- blocker_source, escalation_pending, escalation_awaiting_review,
1875
- escalation_artifact_path, escalation_override_applied_at
1876
- )
1877
- SELECT w.milestone_id, w.slice_id, w.id, w.title,
1878
- CASE
1879
- WHEN m.status IN (${TERMINAL_STATUS_SQL}) AND w.status NOT IN (${TERMINAL_STATUS_SQL})
1880
- THEN m.status ELSE w.status
1881
- END,
1882
- w.one_liner, w.narrative,
1883
- w.verification_result, w.duration,
1884
- CASE
1885
- WHEN m.status IN (${TERMINAL_STATUS_SQL}) AND w.status NOT IN (${TERMINAL_STATUS_SQL})
1886
- THEN m.completed_at ELSE w.completed_at
1887
- END,
1888
- w.blocker_discovered,
1889
- w.deviations, w.known_issues, w.key_files, w.key_decisions, w.full_summary_md,
1890
- w.description, w.estimate, w.files, w.verify, w.inputs, w.expected_output,
1891
- w.observability_impact, w.full_plan_md,
1892
- ${taskTargetRepositoriesSql},
1893
- w.sequence,
1894
- ${hasBlockerSource ? "w.blocker_source" : "COALESCE(m.blocker_source, '')"},
1895
- ${hasEscalationPending ? "w.escalation_pending" : "COALESCE(m.escalation_pending, 0)"},
1896
- ${hasEscalationAwaiting ? "w.escalation_awaiting_review" : "COALESCE(m.escalation_awaiting_review, 0)"},
1897
- ${hasEscalationArtifact ? "w.escalation_artifact_path" : "m.escalation_artifact_path"},
1898
- ${hasEscalationOverride ? "w.escalation_override_applied_at" : "m.escalation_override_applied_at"}
1899
- FROM wt.tasks w
1900
- LEFT JOIN tasks m ON m.milestone_id = w.milestone_id AND m.slice_id = w.slice_id AND m.id = w.id
1901
- `).run());
1902
- }
1903
- // Merge memories — keep worktree-learned insights.
1904
- // V18 (scope, tags), V21 (structured_fields), V28 (last_hit_at): for each
1905
- // column the wt may not yet have (older worktree DB), fall back to the
1906
- // main DB's existing value via LEFT JOIN so reconcile never silently
1907
- // resets these fields to defaults on rows that already had them.
1908
- if (hasWtMemories) {
1909
- merged.memories = countChanges(adapter.prepare(`
1910
- INSERT OR REPLACE INTO memories (
1911
- seq, id, category, content, confidence, source_unit_type, source_unit_id,
1912
- created_at, updated_at, superseded_by, hit_count,
1913
- scope, tags, structured_fields, last_hit_at
1914
- )
1915
- SELECT w.seq, w.id, w.category, w.content, w.confidence, w.source_unit_type, w.source_unit_id,
1916
- w.created_at, w.updated_at, w.superseded_by, w.hit_count,
1917
- ${hasMemoryScope ? "w.scope" : "COALESCE(m.scope, 'project')"},
1918
- ${hasMemoryTags ? "w.tags" : "COALESCE(m.tags, '[]')"},
1919
- ${hasMemoryStructuredFields ? "w.structured_fields" : "m.structured_fields"},
1920
- ${hasMemoryLastHitAt ? "w.last_hit_at" : "m.last_hit_at"}
1921
- FROM wt.memories w
1922
- LEFT JOIN memories m ON m.id = w.id
1923
- `).run());
1924
- }
1925
- if (hasWtReplanHistory) {
1926
- merged.replan_history = countChanges(adapter.prepare(`
1927
- INSERT INTO replan_history (
1928
- milestone_id, slice_id, task_id, summary, previous_artifact_path, replacement_artifact_path, created_at
1929
- )
1930
- SELECT w.milestone_id, w.slice_id, w.task_id, w.summary, w.previous_artifact_path, w.replacement_artifact_path, w.created_at
1931
- FROM wt.replan_history w
1932
- WHERE EXISTS (SELECT 1 FROM milestones m WHERE m.id = w.milestone_id)
1933
- AND NOT EXISTS (
1934
- SELECT 1 FROM replan_history m
1935
- WHERE m.milestone_id = w.milestone_id
1936
- AND m.slice_id IS w.slice_id
1937
- AND m.task_id IS w.task_id
1938
- AND m.summary = w.summary
1939
- AND m.previous_artifact_path IS w.previous_artifact_path
1940
- AND m.replacement_artifact_path IS w.replacement_artifact_path
1941
- )
1942
- `).run());
1943
- }
1944
- if (hasWtAssessments) {
1945
- merged.assessments = countChanges(adapter.prepare(`
1946
- INSERT OR REPLACE INTO assessments (
1947
- path, milestone_id, slice_id, task_id, status, scope, full_content, created_at
1948
- )
1949
- SELECT w.path, w.milestone_id, w.slice_id, w.task_id, w.status, w.scope, w.full_content, w.created_at
1950
- FROM wt.assessments w
1951
- WHERE EXISTS (SELECT 1 FROM milestones m WHERE m.id = w.milestone_id)
1952
- `).run());
1953
- }
1954
- if (hasWtQualityGates) {
1955
- merged.quality_gates = countChanges(adapter.prepare(`
1956
- INSERT OR REPLACE INTO quality_gates (
1957
- milestone_id, slice_id, gate_id, scope, task_id, status, verdict, rationale, findings, evaluated_at
1958
- )
1959
- SELECT w.milestone_id, w.slice_id, w.gate_id, w.scope, COALESCE(w.task_id, ''), w.status, w.verdict, w.rationale, w.findings, w.evaluated_at
1960
- FROM wt.quality_gates w
1961
- WHERE EXISTS (SELECT 1 FROM slices s WHERE s.milestone_id = w.milestone_id AND s.id = w.slice_id)
1962
- `).run());
1963
- }
1964
- if (hasWtSliceDependencies) {
1965
- merged.slice_dependencies = countChanges(adapter.prepare(`
1966
- INSERT OR IGNORE INTO slice_dependencies (milestone_id, slice_id, depends_on_slice_id)
1967
- SELECT w.milestone_id, w.slice_id, w.depends_on_slice_id
1968
- FROM wt.slice_dependencies w
1969
- WHERE EXISTS (SELECT 1 FROM slices s WHERE s.milestone_id = w.milestone_id AND s.id = w.slice_id)
1970
- AND EXISTS (SELECT 1 FROM slices d WHERE d.milestone_id = w.milestone_id AND d.id = w.depends_on_slice_id)
1971
- `).run());
1972
- }
1973
- // Merge verification evidence — append-only, use INSERT OR IGNORE to avoid duplicates
1974
- if (hasWtVerificationEvidence) {
1975
- merged.verification_evidence = countChanges(adapter.prepare(`
1976
- INSERT OR IGNORE INTO verification_evidence (
1977
- task_id, slice_id, milestone_id, command, exit_code, verdict, duration_ms, created_at
1978
- )
1979
- SELECT task_id, slice_id, milestone_id, command, exit_code, verdict, duration_ms, created_at
1980
- FROM wt.verification_evidence
1981
- `).run());
1982
- }
1983
- if (hasWtGateRuns) {
1984
- merged.gate_runs = countChanges(adapter.prepare(`
1985
- INSERT INTO gate_runs (
1986
- trace_id, turn_id, gate_id, gate_type, unit_type, unit_id, milestone_id, slice_id, task_id,
1987
- outcome, failure_class, rationale, findings, attempt, max_attempts, retryable, evaluated_at
1988
- )
1989
- SELECT w.trace_id, w.turn_id, w.gate_id, w.gate_type, w.unit_type, w.unit_id, w.milestone_id, w.slice_id, w.task_id,
1990
- w.outcome, w.failure_class, w.rationale, w.findings, w.attempt, w.max_attempts, w.retryable, w.evaluated_at
1991
- FROM wt.gate_runs w
1992
- WHERE NOT EXISTS (
1993
- SELECT 1 FROM gate_runs m
1994
- WHERE m.trace_id = w.trace_id
1995
- AND m.turn_id = w.turn_id
1996
- AND m.gate_id = w.gate_id
1997
- AND m.attempt = w.attempt
1998
- AND m.evaluated_at = w.evaluated_at
1999
- )
2000
- `).run());
2001
- }
2002
- if (hasWtMilestoneCommitAttributions) {
2003
- merged.milestone_commit_attributions = countChanges(adapter.prepare(`
2004
- INSERT OR REPLACE INTO milestone_commit_attributions (
2005
- commit_sha, milestone_id, slice_id, task_id, source, confidence, files_json, created_at
2006
- )
2007
- SELECT w.commit_sha, w.milestone_id, w.slice_id, w.task_id, w.source, w.confidence, w.files_json, w.created_at
2008
- FROM wt.milestone_commit_attributions w
2009
- WHERE EXISTS (SELECT 1 FROM milestones m WHERE m.id = w.milestone_id)
2010
- `).run());
2011
- }
2012
- adapter.exec("COMMIT");
2013
- }
2014
- catch (txErr) {
2015
- try {
2016
- adapter.exec("ROLLBACK");
2017
- }
2018
- catch (e) {
2019
- logWarning("db", `rollback failed: ${e.message}`);
2020
- }
2021
- throw txErr;
2022
- }
2023
- return { ...merged, conflicts };
2024
- }
2025
- finally {
2026
- try {
2027
- adapter.exec("DETACH DATABASE wt");
2028
- }
2029
- catch (e) {
2030
- logWarning("db", `detach worktree DB failed: ${e.message}`);
2031
- }
2032
- }
2033
- }
2034
- catch (err) {
2035
- logError("db", "worktree DB reconciliation failed", { error: err.message });
2036
- return { ...zero, conflicts };
2037
- }
2038
- }
2039
- // ─── Replan & Assessment Helpers ──────────────────────────────────────────
2040
591
  export function insertReplanHistory(entry) {
2041
- if (!currentDb)
592
+ if (!getDbOrNull())
2042
593
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2043
594
  // INSERT OR REPLACE: idempotent on (milestone_id, slice_id, task_id) via schema v11 unique index.
2044
595
  // Retrying the same replan silently updates summary instead of accumulating duplicate rows.
2045
- currentDb.prepare(`INSERT OR REPLACE INTO replan_history (milestone_id, slice_id, task_id, summary, previous_artifact_path, replacement_artifact_path, created_at)
596
+ getDbOrNull().prepare(`INSERT OR REPLACE INTO replan_history (milestone_id, slice_id, task_id, summary, previous_artifact_path, replacement_artifact_path, created_at)
2046
597
  VALUES (:milestone_id, :slice_id, :task_id, :summary, :previous_artifact_path, :replacement_artifact_path, :created_at)`).run({
2047
598
  ":milestone_id": entry.milestoneId,
2048
599
  ":slice_id": entry.sliceId ?? null,
@@ -2054,12 +605,12 @@ export function insertReplanHistory(entry) {
2054
605
  });
2055
606
  }
2056
607
  export function insertAssessment(entry) {
2057
- if (!currentDb)
608
+ if (!getDbOrNull())
2058
609
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2059
610
  // Idempotent: PRIMARY KEY is `path`, which is deterministic given (milestone_id, scope) per
2060
611
  // the artifact-path resolver. Retrying the same reassess-roadmap silently overwrites the row
2061
612
  // instead of accumulating duplicates.
2062
- currentDb.prepare(`INSERT OR REPLACE INTO assessments (path, milestone_id, slice_id, task_id, status, scope, full_content, created_at)
613
+ getDbOrNull().prepare(`INSERT OR REPLACE INTO assessments (path, milestone_id, slice_id, task_id, status, scope, full_content, created_at)
2063
614
  VALUES (:path, :milestone_id, :slice_id, :task_id, :status, :scope, :full_content, :created_at)`).run({
2064
615
  ":path": entry.path,
2065
616
  ":milestone_id": entry.milestoneId,
@@ -2072,59 +623,66 @@ export function insertAssessment(entry) {
2072
623
  });
2073
624
  }
2074
625
  export function deleteAssessmentByScope(milestoneId, scope) {
2075
- if (!currentDb)
626
+ if (!getDbOrNull())
2076
627
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2077
- currentDb.prepare(`DELETE FROM assessments WHERE milestone_id = :mid AND scope = :scope`).run({ ":mid": milestoneId, ":scope": scope });
628
+ getDbOrNull().prepare(`DELETE FROM assessments WHERE milestone_id = :mid AND scope = :scope`).run({ ":mid": milestoneId, ":scope": scope });
2078
629
  }
2079
630
  export function deleteVerificationEvidence(milestoneId, sliceId, taskId) {
2080
- if (!currentDb)
631
+ if (!getDbOrNull())
2081
632
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2082
- 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 });
633
+ getDbOrNull().prepare(`DELETE FROM verification_evidence WHERE milestone_id = :mid AND slice_id = :sid AND task_id = :tid`).run({ ":mid": milestoneId, ":sid": sliceId, ":tid": taskId });
2083
634
  }
2084
635
  export function deleteTask(milestoneId, sliceId, taskId) {
2085
- if (!currentDb)
636
+ if (!getDbOrNull())
2086
637
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2087
638
  transaction(() => {
2088
639
  // Must delete verification_evidence first (FK constraint)
2089
- 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 });
2090
- currentDb.prepare(`DELETE FROM quality_gates WHERE milestone_id = :mid AND slice_id = :sid AND task_id = :tid`).run({ ":mid": milestoneId, ":sid": sliceId, ":tid": taskId });
2091
- currentDb.prepare(`DELETE FROM tasks WHERE milestone_id = :mid AND slice_id = :sid AND id = :tid`).run({ ":mid": milestoneId, ":sid": sliceId, ":tid": taskId });
640
+ getDbOrNull().prepare(`DELETE FROM verification_evidence WHERE milestone_id = :mid AND slice_id = :sid AND task_id = :tid`).run({ ":mid": milestoneId, ":sid": sliceId, ":tid": taskId });
641
+ getDbOrNull().prepare(`DELETE FROM quality_gates WHERE milestone_id = :mid AND slice_id = :sid AND task_id = :tid`).run({ ":mid": milestoneId, ":sid": sliceId, ":tid": taskId });
642
+ getDbOrNull().prepare(`DELETE FROM tasks WHERE milestone_id = :mid AND slice_id = :sid AND id = :tid`).run({ ":mid": milestoneId, ":sid": sliceId, ":tid": taskId });
2092
643
  });
2093
644
  }
2094
645
  export function deleteSlice(milestoneId, sliceId) {
2095
- if (!currentDb)
646
+ if (!getDbOrNull())
2096
647
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2097
648
  transaction(() => {
2098
649
  // Cascade-style manual deletion: evidence → tasks → dependencies → slice
2099
- currentDb.prepare(`DELETE FROM verification_evidence WHERE milestone_id = :mid AND slice_id = :sid`).run({ ":mid": milestoneId, ":sid": sliceId });
2100
- currentDb.prepare(`DELETE FROM tasks WHERE milestone_id = :mid AND slice_id = :sid`).run({ ":mid": milestoneId, ":sid": sliceId });
2101
- currentDb.prepare(`DELETE FROM slice_dependencies WHERE milestone_id = :mid AND slice_id = :sid`).run({ ":mid": milestoneId, ":sid": sliceId });
2102
- currentDb.prepare(`DELETE FROM slice_dependencies WHERE milestone_id = :mid AND depends_on_slice_id = :sid`).run({ ":mid": milestoneId, ":sid": sliceId });
2103
- currentDb.prepare(`DELETE FROM slices WHERE milestone_id = :mid AND id = :sid`).run({ ":mid": milestoneId, ":sid": sliceId });
650
+ getDbOrNull().prepare(`DELETE FROM verification_evidence WHERE milestone_id = :mid AND slice_id = :sid`).run({ ":mid": milestoneId, ":sid": sliceId });
651
+ getDbOrNull().prepare(`DELETE FROM tasks WHERE milestone_id = :mid AND slice_id = :sid`).run({ ":mid": milestoneId, ":sid": sliceId });
652
+ getDbOrNull().prepare(`DELETE FROM slice_dependencies WHERE milestone_id = :mid AND slice_id = :sid`).run({ ":mid": milestoneId, ":sid": sliceId });
653
+ getDbOrNull().prepare(`DELETE FROM slice_dependencies WHERE milestone_id = :mid AND depends_on_slice_id = :sid`).run({ ":mid": milestoneId, ":sid": sliceId });
654
+ getDbOrNull().prepare(`DELETE FROM slices WHERE milestone_id = :mid AND id = :sid`).run({ ":mid": milestoneId, ":sid": sliceId });
2104
655
  });
2105
656
  }
2106
657
  export function deleteMilestone(milestoneId) {
2107
- if (!currentDb)
658
+ if (!getDbOrNull())
2108
659
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2109
660
  transaction(() => {
2110
- currentDb.prepare(`DELETE FROM verification_evidence WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
2111
- currentDb.prepare(`DELETE FROM quality_gates WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
2112
- currentDb.prepare(`DELETE FROM gate_runs WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
2113
- currentDb.prepare(`DELETE FROM tasks WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
2114
- currentDb.prepare(`DELETE FROM slice_dependencies WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
2115
- currentDb.prepare(`DELETE FROM slices WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
2116
- currentDb.prepare(`DELETE FROM replan_history WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
2117
- currentDb.prepare(`DELETE FROM assessments WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
2118
- currentDb.prepare(`DELETE FROM artifacts WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
2119
- currentDb.prepare(`DELETE FROM milestone_commit_attributions WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
2120
- currentDb.prepare(`DELETE FROM milestone_leases WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
2121
- currentDb.prepare(`DELETE FROM milestones WHERE id = :mid`).run({ ":mid": milestoneId });
661
+ getDbOrNull().prepare(`DELETE FROM verification_evidence WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
662
+ getDbOrNull().prepare(`DELETE FROM quality_gates WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
663
+ getDbOrNull().prepare(`DELETE FROM gate_runs WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
664
+ getDbOrNull().prepare(`DELETE FROM tasks WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
665
+ getDbOrNull().prepare(`DELETE FROM slice_dependencies WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
666
+ getDbOrNull().prepare(`DELETE FROM slices WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
667
+ getDbOrNull().prepare(`DELETE FROM replan_history WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
668
+ getDbOrNull().prepare(`DELETE FROM assessments WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
669
+ getDbOrNull().prepare(`DELETE FROM artifacts WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
670
+ getDbOrNull().prepare(`DELETE FROM milestone_commit_attributions WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
671
+ getDbOrNull().prepare(`DELETE FROM milestone_leases WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
672
+ getDbOrNull().prepare(`DELETE FROM milestones WHERE id = :mid`).run({ ":mid": milestoneId });
2122
673
  });
2123
674
  }
2124
675
  export function updateSliceFields(milestoneId, sliceId, fields) {
2125
- if (!currentDb)
676
+ if (!getDbOrNull())
2126
677
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2127
- currentDb.prepare(`UPDATE slices SET
678
+ const SLICE_ID_RE = /^[A-Za-z0-9][A-Za-z0-9-]*$/;
679
+ if (fields.depends !== undefined) {
680
+ const invalidDep = fields.depends.find(d => !SLICE_ID_RE.test(d));
681
+ if (invalidDep !== undefined) {
682
+ throw new GSDError(GSD_STALE_STATE, `updateSliceFields: depends element "${invalidDep}" is not a valid slice ID`);
683
+ }
684
+ }
685
+ getDbOrNull().prepare(`UPDATE slices SET
2128
686
  title = COALESCE(:title, title),
2129
687
  risk = COALESCE(:risk, risk),
2130
688
  depends = COALESCE(:depends, depends),
@@ -2138,34 +696,11 @@ export function updateSliceFields(milestoneId, sliceId, fields) {
2138
696
  ":demo": fields.demo ?? null,
2139
697
  });
2140
698
  }
2141
- export function getReplanHistory(milestoneId, sliceId) {
2142
- if (!currentDb)
2143
- return [];
2144
- if (sliceId) {
2145
- 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 });
2146
- }
2147
- return currentDb.prepare(`SELECT * FROM replan_history WHERE milestone_id = :mid ORDER BY created_at DESC`).all({ ":mid": milestoneId });
2148
- }
2149
- export function getAssessment(path) {
2150
- if (!currentDb)
2151
- return null;
2152
- const row = currentDb.prepare(`SELECT * FROM assessments WHERE path = :path`).get({ ":path": path });
2153
- return row ?? null;
2154
- }
2155
- export function getLatestAssessmentByScope(milestoneId, scope) {
2156
- if (!currentDb)
2157
- return null;
2158
- const row = currentDb.prepare(`SELECT * FROM assessments
2159
- WHERE milestone_id = :mid AND scope = :scope
2160
- ORDER BY created_at DESC
2161
- LIMIT 1`).get({ ":mid": milestoneId, ":scope": scope });
2162
- return row ?? null;
2163
- }
2164
699
  // ─── Quality Gates ───────────────────────────────────────────────────────
2165
700
  export function insertGateRow(g) {
2166
- if (!currentDb)
701
+ if (!getDbOrNull())
2167
702
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2168
- currentDb.prepare(`INSERT OR IGNORE INTO quality_gates (milestone_id, slice_id, gate_id, scope, task_id, status)
703
+ getDbOrNull().prepare(`INSERT OR IGNORE INTO quality_gates (milestone_id, slice_id, gate_id, scope, task_id, status)
2169
704
  VALUES (:mid, :sid, :gid, :scope, :tid, :status)`).run({
2170
705
  ":mid": g.milestoneId,
2171
706
  ":sid": g.sliceId,
@@ -2176,10 +711,10 @@ export function insertGateRow(g) {
2176
711
  });
2177
712
  }
2178
713
  export function saveGateResult(g) {
2179
- if (!currentDb)
714
+ if (!getDbOrNull())
2180
715
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2181
716
  const evaluatedAt = new Date().toISOString();
2182
- const result = currentDb.prepare(`UPDATE quality_gates
717
+ const result = getDbOrNull().prepare(`UPDATE quality_gates
2183
718
  SET status = 'complete', verdict = :verdict, rationale = :rationale,
2184
719
  findings = :findings, evaluated_at = :evaluated_at
2185
720
  WHERE milestone_id = :mid AND slice_id = :sid AND gate_id = :gid
@@ -2219,32 +754,10 @@ export function saveGateResult(g) {
2219
754
  evaluatedAt,
2220
755
  });
2221
756
  }
2222
- export function getPendingGates(milestoneId, sliceId, scope) {
2223
- if (!currentDb)
2224
- return [];
2225
- const sql = scope
2226
- ? `SELECT * FROM quality_gates WHERE milestone_id = :mid AND slice_id = :sid AND scope = :scope AND status = 'pending'`
2227
- : `SELECT * FROM quality_gates WHERE milestone_id = :mid AND slice_id = :sid AND status = 'pending'`;
2228
- const params = { ":mid": milestoneId, ":sid": sliceId };
2229
- if (scope)
2230
- params[":scope"] = scope;
2231
- return currentDb.prepare(sql).all(params).map(rowToGate);
2232
- }
2233
- export function getGateResults(milestoneId, sliceId, scope) {
2234
- if (!currentDb)
2235
- return [];
2236
- const sql = scope
2237
- ? `SELECT * FROM quality_gates WHERE milestone_id = :mid AND slice_id = :sid AND scope = :scope`
2238
- : `SELECT * FROM quality_gates WHERE milestone_id = :mid AND slice_id = :sid`;
2239
- const params = { ":mid": milestoneId, ":sid": sliceId };
2240
- if (scope)
2241
- params[":scope"] = scope;
2242
- return currentDb.prepare(sql).all(params).map(rowToGate);
2243
- }
2244
757
  export function markAllGatesOmitted(milestoneId, sliceId) {
2245
- if (!currentDb)
758
+ if (!getDbOrNull())
2246
759
  return;
2247
- currentDb.prepare(`UPDATE quality_gates SET status = 'complete', verdict = 'omitted', evaluated_at = :now
760
+ getDbOrNull().prepare(`UPDATE quality_gates SET status = 'complete', verdict = 'omitted', evaluated_at = :now
2248
761
  WHERE milestone_id = :mid AND slice_id = :sid AND status = 'pending'`).run({
2249
762
  ":mid": milestoneId,
2250
763
  ":sid": sliceId,
@@ -2252,7 +765,7 @@ export function markAllGatesOmitted(milestoneId, sliceId) {
2252
765
  });
2253
766
  }
2254
767
  export function markPendingGatesOmittedForTurn(milestoneId, sliceId, turn) {
2255
- if (!currentDb)
768
+ if (!getDbOrNull())
2256
769
  return;
2257
770
  const gateIds = [...getGateIdsForTurn(turn)];
2258
771
  if (gateIds.length === 0)
@@ -2266,61 +779,14 @@ export function markPendingGatesOmittedForTurn(milestoneId, sliceId, turn) {
2266
779
  gateIds.forEach((id, index) => {
2267
780
  params[`:gid${index}`] = id;
2268
781
  });
2269
- currentDb.prepare(`UPDATE quality_gates SET status = 'complete', verdict = 'omitted', evaluated_at = :now
782
+ getDbOrNull().prepare(`UPDATE quality_gates SET status = 'complete', verdict = 'omitted', evaluated_at = :now
2270
783
  WHERE milestone_id = :mid AND slice_id = :sid AND status = 'pending'
2271
784
  AND gate_id IN (${placeholders})`).run(params);
2272
785
  }
2273
- export function getPendingSliceGateCount(milestoneId, sliceId) {
2274
- if (!currentDb)
2275
- return 0;
2276
- const row = currentDb.prepare(`SELECT COUNT(*) as cnt FROM quality_gates
2277
- WHERE milestone_id = :mid AND slice_id = :sid AND scope = 'slice' AND status = 'pending'`).get({ ":mid": milestoneId, ":sid": sliceId });
2278
- return row ? row["cnt"] : 0;
2279
- }
2280
- /**
2281
- * Return pending gate rows owned by a specific workflow turn.
2282
- *
2283
- * Unlike `getPendingGates(..., scope)`, this filters by the registry's
2284
- * `ownerTurn` metadata so callers can distinguish Q3/Q4 (owned by
2285
- * gate-evaluate) from Q8 (owned by complete-slice) even though both are
2286
- * scope:"slice". Pass `taskId` to narrow task-scoped results to one task.
2287
- */
2288
- export function getPendingGatesForTurn(milestoneId, sliceId, turn, taskId) {
2289
- if (!currentDb)
2290
- return [];
2291
- const ids = getGateIdsForTurn(turn);
2292
- if (ids.size === 0)
2293
- return [];
2294
- const idList = [...ids];
2295
- const placeholders = idList.map((_, i) => `:gid${i}`).join(",");
2296
- const params = {
2297
- ":mid": milestoneId,
2298
- ":sid": sliceId,
2299
- };
2300
- idList.forEach((id, i) => {
2301
- params[`:gid${i}`] = id;
2302
- });
2303
- let sql = `SELECT * FROM quality_gates
2304
- WHERE milestone_id = :mid AND slice_id = :sid
2305
- AND status = 'pending'
2306
- AND gate_id IN (${placeholders})`;
2307
- if (taskId !== undefined) {
2308
- sql += ` AND task_id = :tid`;
2309
- params[":tid"] = taskId;
2310
- }
2311
- return currentDb.prepare(sql).all(params).map(rowToGate);
2312
- }
2313
- /**
2314
- * Count pending gates for a turn. Convenience wrapper used by state
2315
- * derivation to decide whether a phase transition should pause.
2316
- */
2317
- export function getPendingGateCountForTurn(milestoneId, sliceId, turn) {
2318
- return getPendingGatesForTurn(milestoneId, sliceId, turn).length;
2319
- }
2320
786
  export function insertGateRun(entry) {
2321
- if (!currentDb)
787
+ if (!getDbOrNull())
2322
788
  return;
2323
- currentDb.prepare(`INSERT INTO gate_runs (
789
+ getDbOrNull().prepare(`INSERT INTO gate_runs (
2324
790
  trace_id, turn_id, gate_id, gate_type, unit_type, unit_id, milestone_id, slice_id, task_id,
2325
791
  outcome, failure_class, rationale, findings, attempt, max_attempts, retryable, evaluated_at
2326
792
  ) VALUES (
@@ -2347,9 +813,9 @@ export function insertGateRun(entry) {
2347
813
  });
2348
814
  }
2349
815
  export function upsertTurnGitTransaction(entry) {
2350
- if (!currentDb)
816
+ if (!getDbOrNull())
2351
817
  return;
2352
- currentDb.prepare(`INSERT OR REPLACE INTO turn_git_transactions (
818
+ getDbOrNull().prepare(`INSERT OR REPLACE INTO turn_git_transactions (
2353
819
  trace_id, turn_id, unit_type, unit_id, stage, action, push, status, error, metadata_json, updated_at
2354
820
  ) VALUES (
2355
821
  :trace_id, :turn_id, :unit_type, :unit_id, :stage, :action, :push, :status, :error, :metadata_json, :updated_at
@@ -2367,22 +833,11 @@ export function upsertTurnGitTransaction(entry) {
2367
833
  ":updated_at": entry.updatedAt,
2368
834
  });
2369
835
  }
2370
- export function getMilestoneCommitAttributionShas(milestoneId) {
2371
- if (!currentDb)
2372
- return [];
2373
- const rows = currentDb.prepare(`SELECT commit_sha
2374
- FROM milestone_commit_attributions
2375
- WHERE milestone_id = :mid
2376
- ORDER BY created_at, commit_sha`).all({ ":mid": milestoneId });
2377
- return rows
2378
- .map((row) => typeof row["commit_sha"] === "string" ? row["commit_sha"] : "")
2379
- .filter(Boolean);
2380
- }
2381
836
  export function recordMilestoneCommitAttribution(entry) {
2382
- if (!currentDb)
837
+ if (!getDbOrNull())
2383
838
  return;
2384
839
  transaction(() => {
2385
- currentDb.prepare(`INSERT OR REPLACE INTO milestone_commit_attributions (
840
+ getDbOrNull().prepare(`INSERT OR REPLACE INTO milestone_commit_attributions (
2386
841
  commit_sha, milestone_id, slice_id, task_id, source, confidence, files_json, created_at
2387
842
  ) VALUES (
2388
843
  :commit_sha, :milestone_id, :slice_id, :task_id, :source, :confidence, :files_json, :created_at
@@ -2396,7 +851,7 @@ export function recordMilestoneCommitAttribution(entry) {
2396
851
  ":files_json": JSON.stringify(entry.files),
2397
852
  ":created_at": entry.createdAt,
2398
853
  });
2399
- currentDb.prepare(`INSERT OR IGNORE INTO audit_events (
854
+ getDbOrNull().prepare(`INSERT OR IGNORE INTO audit_events (
2400
855
  event_id, trace_id, turn_id, caused_by, category, type, ts, payload_json
2401
856
  ) VALUES (
2402
857
  :event_id, :trace_id, :turn_id, :caused_by, :category, :type, :ts, :payload_json
@@ -2421,10 +876,10 @@ export function recordMilestoneCommitAttribution(entry) {
2421
876
  });
2422
877
  }
2423
878
  export function insertAuditEvent(entry) {
2424
- if (!currentDb)
879
+ if (!getDbOrNull())
2425
880
  return;
2426
881
  transaction(() => {
2427
- currentDb.prepare(`INSERT OR IGNORE INTO audit_events (
882
+ getDbOrNull().prepare(`INSERT OR IGNORE INTO audit_events (
2428
883
  event_id, trace_id, turn_id, caused_by, category, type, ts, payload_json
2429
884
  ) VALUES (
2430
885
  :event_id, :trace_id, :turn_id, :caused_by, :category, :type, :ts, :payload_json
@@ -2439,14 +894,14 @@ export function insertAuditEvent(entry) {
2439
894
  ":payload_json": JSON.stringify(entry.payload ?? {}),
2440
895
  });
2441
896
  if (entry.turnId) {
2442
- const row = currentDb.prepare(`SELECT event_count, first_ts, last_ts
897
+ const row = getDbOrNull().prepare(`SELECT event_count, first_ts, last_ts
2443
898
  FROM audit_turn_index
2444
899
  WHERE trace_id = :trace_id AND turn_id = :turn_id`).get({
2445
900
  ":trace_id": entry.traceId,
2446
901
  ":turn_id": entry.turnId,
2447
902
  });
2448
903
  if (row) {
2449
- currentDb.prepare(`UPDATE audit_turn_index
904
+ getDbOrNull().prepare(`UPDATE audit_turn_index
2450
905
  SET first_ts = CASE WHEN :ts < first_ts THEN :ts ELSE first_ts END,
2451
906
  last_ts = CASE WHEN :ts > last_ts THEN :ts ELSE last_ts END,
2452
907
  event_count = event_count + 1
@@ -2457,7 +912,7 @@ export function insertAuditEvent(entry) {
2457
912
  });
2458
913
  }
2459
914
  else {
2460
- currentDb.prepare(`INSERT INTO audit_turn_index (trace_id, turn_id, first_ts, last_ts, event_count)
915
+ getDbOrNull().prepare(`INSERT INTO audit_turn_index (trace_id, turn_id, first_ts, last_ts, event_count)
2461
916
  VALUES (:trace_id, :turn_id, :first_ts, :last_ts, :event_count)`).run({
2462
917
  ":trace_id": entry.traceId,
2463
918
  ":turn_id": entry.turnId,
@@ -2477,40 +932,40 @@ export function insertAuditEvent(entry) {
2477
932
  // add new behavior.
2478
933
  /** Delete a decision row by id. Used by db-writer.ts rollback on disk-write failure. */
2479
934
  export function deleteDecisionById(id) {
2480
- if (!currentDb)
935
+ if (!getDbOrNull())
2481
936
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2482
- currentDb.prepare("DELETE FROM decisions WHERE id = :id").run({ ":id": id });
937
+ getDbOrNull().prepare("DELETE FROM decisions WHERE id = :id").run({ ":id": id });
2483
938
  }
2484
939
  /** Delete a requirement row by id. Used by db-writer.ts rollback on disk-write failure. */
2485
940
  export function deleteRequirementById(id) {
2486
- if (!currentDb)
941
+ if (!getDbOrNull())
2487
942
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2488
- currentDb.prepare("DELETE FROM requirements WHERE id = :id").run({ ":id": id });
943
+ getDbOrNull().prepare("DELETE FROM requirements WHERE id = :id").run({ ":id": id });
2489
944
  }
2490
945
  /** Delete an artifact row by path. Used by db-writer.ts rollback on disk-write failure. */
2491
946
  export function deleteArtifactByPath(path) {
2492
- if (!currentDb)
947
+ if (!getDbOrNull())
2493
948
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2494
- currentDb.prepare("DELETE FROM artifacts WHERE path = :path").run({ ":path": path });
949
+ getDbOrNull().prepare("DELETE FROM artifacts WHERE path = :path").run({ ":path": path });
2495
950
  }
2496
951
  /**
2497
952
  * Drop hierarchy rows in dependency order inside a transaction. Used by
2498
953
  * `gsd recover --confirm` to rebuild engine state from markdown.
2499
954
  */
2500
955
  export function clearEngineHierarchy() {
2501
- if (!currentDb)
956
+ if (!getDbOrNull())
2502
957
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2503
958
  transaction(() => {
2504
- currentDb.exec("DELETE FROM verification_evidence");
2505
- currentDb.exec("DELETE FROM quality_gates");
2506
- currentDb.exec("DELETE FROM slice_dependencies");
2507
- currentDb.exec("DELETE FROM assessments");
2508
- currentDb.exec("DELETE FROM replan_history");
2509
- currentDb.exec("DELETE FROM milestone_commit_attributions");
2510
- currentDb.exec("DELETE FROM tasks");
2511
- currentDb.exec("DELETE FROM slices");
2512
- currentDb.exec("DELETE FROM milestone_leases");
2513
- currentDb.exec("DELETE FROM milestones");
959
+ getDbOrNull().exec("DELETE FROM verification_evidence");
960
+ getDbOrNull().exec("DELETE FROM quality_gates");
961
+ getDbOrNull().exec("DELETE FROM slice_dependencies");
962
+ getDbOrNull().exec("DELETE FROM assessments");
963
+ getDbOrNull().exec("DELETE FROM replan_history");
964
+ getDbOrNull().exec("DELETE FROM milestone_commit_attributions");
965
+ getDbOrNull().exec("DELETE FROM tasks");
966
+ getDbOrNull().exec("DELETE FROM slices");
967
+ getDbOrNull().exec("DELETE FROM milestone_leases");
968
+ getDbOrNull().exec("DELETE FROM milestones");
2514
969
  });
2515
970
  }
2516
971
  /**
@@ -2520,9 +975,9 @@ export function clearEngineHierarchy() {
2520
975
  * slice back to 'pending'.
2521
976
  */
2522
977
  export function insertOrIgnoreSlice(args) {
2523
- if (!currentDb)
978
+ if (!getDbOrNull())
2524
979
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2525
- currentDb.prepare(`INSERT OR IGNORE INTO slices (milestone_id, id, title, status, created_at)
980
+ getDbOrNull().prepare(`INSERT OR IGNORE INTO slices (milestone_id, id, title, status, created_at)
2526
981
  VALUES (:mid, :sid, :title, 'pending', :ts)`).run({
2527
982
  ":mid": args.milestoneId,
2528
983
  ":sid": args.sliceId,
@@ -2535,9 +990,9 @@ export function insertOrIgnoreSlice(args) {
2535
990
  * Same rationale as `insertOrIgnoreSlice`.
2536
991
  */
2537
992
  export function insertOrIgnoreTask(args) {
2538
- if (!currentDb)
993
+ if (!getDbOrNull())
2539
994
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2540
- currentDb.prepare(`INSERT OR IGNORE INTO tasks (milestone_id, slice_id, id, title, status, created_at)
995
+ getDbOrNull().prepare(`INSERT OR IGNORE INTO tasks (milestone_id, slice_id, id, title, status, created_at)
2541
996
  VALUES (:mid, :sid, :tid, :title, 'pending', :ts)`).run({
2542
997
  ":mid": args.milestoneId,
2543
998
  ":sid": args.sliceId,
@@ -2552,18 +1007,18 @@ export function insertOrIgnoreTask(args) {
2552
1007
  * trigger via DB in addition to the on-disk REPLAN-TRIGGER.md marker.
2553
1008
  */
2554
1009
  export function setSliceReplanTriggeredAt(milestoneId, sliceId, ts) {
2555
- if (!currentDb)
1010
+ if (!getDbOrNull())
2556
1011
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2557
- currentDb.prepare("UPDATE slices SET replan_triggered_at = :ts WHERE milestone_id = :mid AND id = :sid").run({ ":ts": ts, ":mid": milestoneId, ":sid": sliceId });
1012
+ getDbOrNull().prepare("UPDATE slices SET replan_triggered_at = :ts WHERE milestone_id = :mid AND id = :sid").run({ ":ts": ts, ":mid": milestoneId, ":sid": sliceId });
2558
1013
  }
2559
1014
  /**
2560
1015
  * INSERT OR REPLACE a quality_gates row. Used by milestone-validation-gates.ts
2561
1016
  * to persist milestone-level (MV*) gate outcomes after validate-milestone runs.
2562
1017
  */
2563
1018
  export function upsertQualityGate(g) {
2564
- if (!currentDb)
1019
+ if (!getDbOrNull())
2565
1020
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2566
- currentDb.prepare(`INSERT OR REPLACE INTO quality_gates
1021
+ getDbOrNull().prepare(`INSERT OR REPLACE INTO quality_gates
2567
1022
  (milestone_id, slice_id, gate_id, scope, task_id, status, verdict, rationale, findings, evaluated_at)
2568
1023
  VALUES (:mid, :sid, :gid, :scope, :tid, :status, :verdict, :rationale, :findings, :evaluated_at)`).run({
2569
1024
  ":mid": g.milestoneId,
@@ -2578,327 +1033,3 @@ export function upsertQualityGate(g) {
2578
1033
  ":evaluated_at": g.evaluatedAt,
2579
1034
  });
2580
1035
  }
2581
- /**
2582
- * Atomically replace all workflow state from a manifest. Lifted verbatim from
2583
- * workflow-manifest.ts so the single-writer invariant holds. Restores
2584
- * correctness-bearing workflow tables; runtime soft state and append-only audit
2585
- * streams stay outside this recovery path.
2586
- */
2587
- export function restoreManifest(manifest) {
2588
- if (!currentDb)
2589
- throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2590
- const db = currentDb;
2591
- transaction(() => {
2592
- const restoredMilestoneIds = new Set(manifest.milestones.map((m) => m.id));
2593
- const restoredSliceKeys = new Set(manifest.slices.map((s) => JSON.stringify([s.milestone_id, s.id])));
2594
- const preservedReplanHistory = manifest.replan_history === undefined
2595
- ? db.prepare("SELECT * FROM replan_history ORDER BY id").all()
2596
- : [];
2597
- const preservedAssessments = manifest.assessments === undefined
2598
- ? db.prepare("SELECT * FROM assessments ORDER BY path").all()
2599
- : [];
2600
- const preservedQualityGates = manifest.quality_gates === undefined
2601
- ? db.prepare("SELECT * FROM quality_gates ORDER BY milestone_id, slice_id, gate_id, task_id").all()
2602
- : [];
2603
- const preservedCommitAttributions = manifest.milestone_commit_attributions === undefined
2604
- ? db.prepare("SELECT * FROM milestone_commit_attributions ORDER BY milestone_id, commit_sha").all()
2605
- : [];
2606
- // Clear workflow tables in dependency order.
2607
- db.exec("DELETE FROM verification_evidence");
2608
- db.exec("DELETE FROM quality_gates");
2609
- db.exec("DELETE FROM slice_dependencies");
2610
- db.exec("DELETE FROM assessments");
2611
- db.exec("DELETE FROM replan_history");
2612
- db.exec("DELETE FROM milestone_commit_attributions");
2613
- db.exec("DELETE FROM tasks");
2614
- db.exec("DELETE FROM slices");
2615
- db.exec("DELETE FROM milestone_leases");
2616
- db.exec("DELETE FROM milestones");
2617
- db.exec("DELETE FROM decisions WHERE 1=1");
2618
- db.exec(`DELETE FROM memories WHERE category = 'architecture' AND structured_fields LIKE '%"sourceDecisionId":"%'`);
2619
- if (manifest.artifacts !== undefined)
2620
- db.exec("DELETE FROM artifacts");
2621
- if (manifest.requirements !== undefined)
2622
- db.exec("DELETE FROM requirements");
2623
- if (manifest.requirements !== undefined) {
2624
- const reqStmt = db.prepare(`INSERT INTO requirements (
2625
- id, class, status, description, why, source, primary_owner,
2626
- supporting_slices, validation, notes, full_content, superseded_by
2627
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
2628
- for (const r of manifest.requirements) {
2629
- reqStmt.run(r.id, r.class, r.status, r.description, r.why, r.source, r.primary_owner, r.supporting_slices, r.validation, r.notes, r.full_content, r.superseded_by);
2630
- }
2631
- }
2632
- if (manifest.artifacts !== undefined) {
2633
- const artStmt = db.prepare(`INSERT INTO artifacts (
2634
- path, artifact_type, milestone_id, slice_id, task_id, full_content, imported_at, content_hash
2635
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);
2636
- for (const a of manifest.artifacts) {
2637
- const fullContent = a.full_content ?? "";
2638
- artStmt.run(a.path, a.artifact_type, a.milestone_id, a.slice_id, a.task_id, fullContent, a.imported_at, a.content_hash ?? createHash("sha256").update(fullContent).digest("hex"));
2639
- }
2640
- }
2641
- // Restore milestones
2642
- const msStmt = db.prepare(`INSERT INTO milestones (id, title, status, depends_on, created_at, completed_at,
2643
- vision, success_criteria, key_risks, proof_strategy,
2644
- verification_contract, verification_integration, verification_operational, verification_uat,
2645
- definition_of_done, requirement_coverage, boundary_map_markdown, sequence)
2646
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
2647
- for (const m of manifest.milestones) {
2648
- msStmt.run(m.id, m.title, m.status, JSON.stringify(m.depends_on), m.created_at, m.completed_at, m.vision, JSON.stringify(m.success_criteria), JSON.stringify(m.key_risks), JSON.stringify(m.proof_strategy), m.verification_contract, m.verification_integration, m.verification_operational, m.verification_uat, JSON.stringify(m.definition_of_done), m.requirement_coverage, m.boundary_map_markdown, m.sequence ?? 0);
2649
- }
2650
- // Restore slices (ADR-011 Phase 1: includes is_sketch + sketch_scope)
2651
- const slStmt = db.prepare(`INSERT INTO slices (milestone_id, id, title, status, risk, depends, demo,
2652
- created_at, completed_at, full_summary_md, full_uat_md,
2653
- goal, success_criteria, proof_level, integration_closure, observability_impact,
2654
- target_repositories, sequence, replan_triggered_at, is_sketch, sketch_scope)
2655
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
2656
- for (const s of manifest.slices) {
2657
- slStmt.run(s.milestone_id, s.id, s.title, s.status, s.risk, JSON.stringify(s.depends), s.demo, s.created_at, s.completed_at, s.full_summary_md, s.full_uat_md, s.goal, s.success_criteria, s.proof_level, s.integration_closure, s.observability_impact, JSON.stringify(s.target_repositories ?? []), s.sequence, s.replan_triggered_at, s.is_sketch ?? 0, s.sketch_scope ?? "");
2658
- }
2659
- const depStmt = db.prepare("INSERT OR IGNORE INTO slice_dependencies (milestone_id, slice_id, depends_on_slice_id) VALUES (?, ?, ?)");
2660
- for (const s of manifest.slices) {
2661
- for (const dep of s.depends ?? []) {
2662
- depStmt.run(s.milestone_id, s.id, dep);
2663
- }
2664
- }
2665
- // Restore tasks (ADR-011 P2: includes blocker_source + escalation_* columns)
2666
- const tkStmt = db.prepare(`INSERT INTO tasks (milestone_id, slice_id, id, title, status,
2667
- one_liner, narrative, verification_result, duration, completed_at,
2668
- blocker_discovered, deviations, known_issues, key_files, key_decisions,
2669
- full_summary_md, description, estimate, files, verify,
2670
- inputs, expected_output, observability_impact, full_plan_md, target_repositories, sequence,
2671
- blocker_source, escalation_pending, escalation_awaiting_review,
2672
- escalation_artifact_path, escalation_override_applied_at)
2673
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
2674
- for (const t of manifest.tasks) {
2675
- tkStmt.run(t.milestone_id, t.slice_id, t.id, t.title, t.status, t.one_liner, t.narrative, t.verification_result, t.duration, t.completed_at, t.blocker_discovered ? 1 : 0, t.deviations, t.known_issues, JSON.stringify(t.key_files), JSON.stringify(t.key_decisions), t.full_summary_md, t.description, t.estimate, JSON.stringify(t.files), t.verify, JSON.stringify(t.inputs), JSON.stringify(t.expected_output), t.observability_impact, t.full_plan_md ?? "", JSON.stringify(t.target_repositories ?? []), t.sequence, t.blocker_source ?? "", t.escalation_pending ?? 0, t.escalation_awaiting_review ?? 0, t.escalation_artifact_path ?? null, t.escalation_override_applied_at ?? null);
2676
- }
2677
- // Restore decisions (ADR-011 P2: include source so escalation decisions survive)
2678
- const dcStmt = db.prepare(`INSERT INTO decisions (seq, id, when_context, scope, decision, choice, rationale, revisable, made_by, source, superseded_by)
2679
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
2680
- for (const d of manifest.decisions) {
2681
- dcStmt.run(d.seq, d.id, d.when_context, d.scope, d.decision, d.choice, d.rationale, d.revisable, d.made_by, d.source ?? "discussion", d.superseded_by);
2682
- }
2683
- const replanHistoryRows = manifest.replan_history ?? preservedReplanHistory.filter((r) => restoredMilestoneIds.has(r.milestone_id));
2684
- if (replanHistoryRows.length > 0) {
2685
- const replStmt = db.prepare(`INSERT INTO replan_history (
2686
- id, milestone_id, slice_id, task_id, summary, previous_artifact_path, replacement_artifact_path, created_at
2687
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);
2688
- for (const r of replanHistoryRows) {
2689
- replStmt.run(r.id, r.milestone_id, r.slice_id, r.task_id, r.summary, r.previous_artifact_path, r.replacement_artifact_path, r.created_at);
2690
- }
2691
- }
2692
- const assessmentRows = manifest.assessments ?? preservedAssessments.filter((a) => restoredMilestoneIds.has(a.milestone_id));
2693
- if (assessmentRows.length > 0) {
2694
- const assessStmt = db.prepare(`INSERT INTO assessments (
2695
- path, milestone_id, slice_id, task_id, status, scope, full_content, created_at
2696
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);
2697
- for (const a of assessmentRows) {
2698
- assessStmt.run(a.path, a.milestone_id, a.slice_id, a.task_id, a.status, a.scope, a.full_content, a.created_at);
2699
- }
2700
- }
2701
- const qualityGateRows = manifest.quality_gates ?? preservedQualityGates.filter((g) => (restoredSliceKeys.has(JSON.stringify([g.milestone_id, g.slice_id]))));
2702
- if (qualityGateRows.length > 0) {
2703
- const gateStmt = db.prepare(`INSERT INTO quality_gates (
2704
- milestone_id, slice_id, gate_id, scope, task_id, status, verdict, rationale, findings, evaluated_at
2705
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
2706
- for (const g of qualityGateRows) {
2707
- gateStmt.run(g.milestone_id, g.slice_id, g.gate_id, g.scope, g.task_id, g.status, g.verdict ?? "", g.rationale, g.findings, g.evaluated_at);
2708
- }
2709
- }
2710
- const commitAttributionRows = manifest.milestone_commit_attributions ??
2711
- preservedCommitAttributions.filter((a) => restoredMilestoneIds.has(a.milestone_id));
2712
- if (commitAttributionRows.length > 0) {
2713
- const attrStmt = db.prepare(`INSERT OR REPLACE INTO milestone_commit_attributions (
2714
- commit_sha, milestone_id, slice_id, task_id, source, confidence, files_json, created_at
2715
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);
2716
- for (const a of commitAttributionRows) {
2717
- attrStmt.run(a.commit_sha, a.milestone_id, a.slice_id, a.task_id, a.source, a.confidence, a.files_json, a.created_at);
2718
- }
2719
- }
2720
- // Restore verification evidence
2721
- const evStmt = db.prepare(`INSERT INTO verification_evidence (task_id, slice_id, milestone_id, command, exit_code, verdict, duration_ms, created_at)
2722
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);
2723
- for (const e of manifest.verification_evidence) {
2724
- evStmt.run(e.task_id, e.slice_id, e.milestone_id, e.command, e.exit_code, e.verdict, e.duration_ms, e.created_at);
2725
- }
2726
- });
2727
- }
2728
- /**
2729
- * Bulk delete + insert a legacy milestone hierarchy for markdown → DB migration.
2730
- * Used by workflow-migration.ts to populate engine tables from parsed ROADMAP/PLAN
2731
- * files. All operations run inside a single transaction.
2732
- */
2733
- export function bulkInsertLegacyHierarchy(payload) {
2734
- if (!currentDb)
2735
- throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2736
- const db = currentDb;
2737
- const { milestones, slices, tasks, clearMilestoneIds, createdAt } = payload;
2738
- if (clearMilestoneIds.length === 0)
2739
- return;
2740
- const placeholders = clearMilestoneIds.map(() => "?").join(",");
2741
- transaction(() => {
2742
- db.prepare(`DELETE FROM tasks WHERE milestone_id IN (${placeholders})`).run(...clearMilestoneIds);
2743
- db.prepare(`DELETE FROM slices WHERE milestone_id IN (${placeholders})`).run(...clearMilestoneIds);
2744
- db.prepare(`DELETE FROM milestone_leases WHERE milestone_id IN (${placeholders})`).run(...clearMilestoneIds);
2745
- db.prepare(`DELETE FROM milestones WHERE id IN (${placeholders})`).run(...clearMilestoneIds);
2746
- const insertMilestone = db.prepare("INSERT INTO milestones (id, title, status, created_at) VALUES (?, ?, ?, ?)");
2747
- for (const m of milestones) {
2748
- insertMilestone.run(m.id, m.title, m.status, createdAt);
2749
- }
2750
- const insertSliceStmt = db.prepare("INSERT INTO slices (id, milestone_id, title, status, risk, depends, sequence, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
2751
- for (const s of slices) {
2752
- insertSliceStmt.run(s.id, s.milestoneId, s.title, s.status, s.risk, "[]", s.sequence, createdAt);
2753
- }
2754
- const insertTaskStmt = db.prepare("INSERT INTO tasks (id, slice_id, milestone_id, title, description, status, estimate, files, sequence) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
2755
- for (const t of tasks) {
2756
- insertTaskStmt.run(t.id, t.sliceId, t.milestoneId, t.title, "", t.status, "", "[]", t.sequence);
2757
- }
2758
- });
2759
- }
2760
- // ─── Memory store writers ────────────────────────────────────────────────
2761
- // All memory writes go through gsd-db.ts so the single-writer invariant
2762
- // holds. These are direct pass-throughs to the SQL previously in
2763
- // memory-store.ts — same bindings, same behavior.
2764
- export function insertMemoryRow(args) {
2765
- if (!currentDb)
2766
- throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2767
- currentDb.prepare(`INSERT INTO memories (id, category, content, confidence, source_unit_type, source_unit_id, created_at, updated_at, scope, tags, structured_fields)
2768
- VALUES (:id, :category, :content, :confidence, :source_unit_type, :source_unit_id, :created_at, :updated_at, :scope, :tags, :structured_fields)`).run({
2769
- ":id": args.id,
2770
- ":category": args.category,
2771
- ":content": args.content,
2772
- ":confidence": args.confidence,
2773
- ":source_unit_type": args.sourceUnitType,
2774
- ":source_unit_id": args.sourceUnitId,
2775
- ":created_at": args.createdAt,
2776
- ":updated_at": args.updatedAt,
2777
- ":scope": args.scope ?? "project",
2778
- ":tags": JSON.stringify(args.tags ?? []),
2779
- ":structured_fields": args.structuredFields == null ? null : JSON.stringify(args.structuredFields),
2780
- });
2781
- }
2782
- export function insertMemorySourceRow(args) {
2783
- if (!currentDb)
2784
- throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2785
- currentDb.prepare(`INSERT OR IGNORE INTO memory_sources (id, kind, uri, title, content, content_hash, imported_at, scope, tags)
2786
- VALUES (:id, :kind, :uri, :title, :content, :content_hash, :imported_at, :scope, :tags)`).run({
2787
- ":id": args.id,
2788
- ":kind": args.kind,
2789
- ":uri": args.uri,
2790
- ":title": args.title,
2791
- ":content": args.content,
2792
- ":content_hash": args.contentHash,
2793
- ":imported_at": args.importedAt,
2794
- ":scope": args.scope ?? "project",
2795
- ":tags": JSON.stringify(args.tags ?? []),
2796
- });
2797
- }
2798
- export function deleteMemorySourceRow(id) {
2799
- if (!currentDb)
2800
- throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2801
- const res = currentDb
2802
- .prepare("DELETE FROM memory_sources WHERE id = :id")
2803
- .run({ ":id": id });
2804
- return (res?.changes ?? 0) > 0;
2805
- }
2806
- export function upsertMemoryEmbedding(args) {
2807
- if (!currentDb)
2808
- throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2809
- currentDb.prepare(`INSERT INTO memory_embeddings (memory_id, model, dim, vector, updated_at)
2810
- VALUES (:memory_id, :model, :dim, :vector, :updated_at)
2811
- ON CONFLICT(memory_id) DO UPDATE SET
2812
- model = excluded.model,
2813
- dim = excluded.dim,
2814
- vector = excluded.vector,
2815
- updated_at = excluded.updated_at`).run({
2816
- ":memory_id": args.memoryId,
2817
- ":model": args.model,
2818
- ":dim": args.dim,
2819
- ":vector": args.vector,
2820
- ":updated_at": args.updatedAt,
2821
- });
2822
- }
2823
- export function deleteMemoryEmbedding(memoryId) {
2824
- if (!currentDb)
2825
- throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2826
- const res = currentDb
2827
- .prepare("DELETE FROM memory_embeddings WHERE memory_id = :id")
2828
- .run({ ":id": memoryId });
2829
- return (res?.changes ?? 0) > 0;
2830
- }
2831
- export function insertMemoryRelationRow(args) {
2832
- if (!currentDb)
2833
- throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2834
- currentDb.prepare(`INSERT OR REPLACE INTO memory_relations (from_id, to_id, rel, confidence, created_at)
2835
- VALUES (:from_id, :to_id, :rel, :confidence, :created_at)`).run({
2836
- ":from_id": args.fromId,
2837
- ":to_id": args.toId,
2838
- ":rel": args.rel,
2839
- ":confidence": args.confidence,
2840
- ":created_at": args.createdAt,
2841
- });
2842
- }
2843
- export function deleteMemoryRelationsFor(memoryId) {
2844
- if (!currentDb)
2845
- throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2846
- currentDb
2847
- .prepare("DELETE FROM memory_relations WHERE from_id = :id OR to_id = :id")
2848
- .run({ ":id": memoryId });
2849
- }
2850
- export function rewriteMemoryId(placeholderId, realId) {
2851
- if (!currentDb)
2852
- throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2853
- currentDb.prepare("UPDATE memories SET id = :real_id WHERE id = :placeholder").run({
2854
- ":real_id": realId,
2855
- ":placeholder": placeholderId,
2856
- });
2857
- }
2858
- export function updateMemoryContentRow(id, content, confidence, updatedAt) {
2859
- if (!currentDb)
2860
- throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2861
- if (confidence != null) {
2862
- currentDb.prepare("UPDATE memories SET content = :content, confidence = :confidence, updated_at = :updated_at WHERE id = :id").run({ ":content": content, ":confidence": confidence, ":updated_at": updatedAt, ":id": id });
2863
- }
2864
- else {
2865
- currentDb.prepare("UPDATE memories SET content = :content, updated_at = :updated_at WHERE id = :id").run({ ":content": content, ":updated_at": updatedAt, ":id": id });
2866
- }
2867
- }
2868
- export function incrementMemoryHitCount(id, updatedAt) {
2869
- if (!currentDb)
2870
- throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2871
- currentDb.prepare("UPDATE memories SET hit_count = hit_count + 1, updated_at = :updated_at, last_hit_at = :last_hit_at WHERE id = :id").run({ ":updated_at": updatedAt, ":last_hit_at": updatedAt, ":id": id });
2872
- }
2873
- export function supersedeMemoryRow(oldId, newId, updatedAt) {
2874
- if (!currentDb)
2875
- throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2876
- currentDb.prepare("UPDATE memories SET superseded_by = :new_id, updated_at = :updated_at WHERE id = :old_id").run({ ":new_id": newId, ":updated_at": updatedAt, ":old_id": oldId });
2877
- }
2878
- export function markMemoryUnitProcessed(unitKey, activityFile, processedAt) {
2879
- if (!currentDb)
2880
- throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2881
- currentDb.prepare(`INSERT OR IGNORE INTO memory_processed_units (unit_key, activity_file, processed_at)
2882
- VALUES (:key, :file, :at)`).run({ ":key": unitKey, ":file": activityFile, ":at": processedAt });
2883
- }
2884
- export function decayMemoriesBefore(cutoffTs, now) {
2885
- if (!currentDb)
2886
- throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2887
- currentDb.prepare(`UPDATE memories
2888
- SET confidence = MAX(0.1, confidence - 0.1), updated_at = :now
2889
- WHERE superseded_by IS NULL
2890
- AND updated_at < :cutoff
2891
- AND confidence > 0.1
2892
- AND (structured_fields IS NULL OR structured_fields NOT LIKE '%"sourceDecisionId"%')`).run({ ":now": now, ":cutoff": cutoffTs });
2893
- }
2894
- export function supersedeLowestRankedMemories(limit, now) {
2895
- if (!currentDb)
2896
- throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2897
- currentDb.prepare(`UPDATE memories SET superseded_by = 'CAP_EXCEEDED', updated_at = :now
2898
- WHERE id IN (
2899
- SELECT id FROM memories
2900
- WHERE superseded_by IS NULL
2901
- ORDER BY (confidence * (1.0 + hit_count * 0.1)) ASC
2902
- LIMIT :limit
2903
- )`).run({ ":now": now, ":limit": limit });
2904
- }