@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,40 +1,27 @@
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
-
25
- 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.
26
18
  import { createHash } from "node:crypto";
27
- import { existsSync, copyFileSync, mkdirSync, realpathSync } from "node:fs";
28
- import { dirname, join } from "node:path";
19
+ import { join } from "node:path";
29
20
  import type { Decision, Requirement, GateRow, GateId, GateScope, GateStatus, GateVerdict } from "./types.js";
30
21
  import { GSDError, GSD_STALE_STATE } from "./errors.js";
31
- import type { GsdWorkspace, MilestoneScope } from "./workspace.js";
32
22
  import { getGateIdsForTurn, type OwnerTurn } from "./gate-registry.js";
33
23
  import { logError, logWarning } from "./workflow-logger.js";
34
- import { createDbAdapter, type DbAdapter } from "./db-adapter.js";
35
- import { createBaseSchemaObjects } from "./db-base-schema.js";
36
- import { createCoordinationTablesV24 } from "./db-coordination-schema.js";
37
- import { createDbConnectionCache, type DbConnectionCacheEntry } from "./db-connection-cache.js";
24
+ import { type DbAdapter } from "./db-adapter.js";
38
25
  import {
39
26
  emptyTaskStatusCounts,
40
27
  rowToActiveTaskSummary,
@@ -54,783 +41,36 @@ import {
54
41
  } from "./db-decision-requirement-rows.js";
55
42
  import { rowToGate } from "./db-gate-rows.js";
56
43
  import { rowToArtifact, rowToMilestone, type ArtifactRow, type MilestoneRow } from "./db-milestone-artifact-rows.js";
57
- import { backupDatabaseBeforeMigration } from "./db-migration-backup.js";
58
44
  import { isClosedStatus } from "./status-guards.js";
59
- import {
60
- applyMigrationV2Artifacts,
61
- applyMigrationV3Memories,
62
- applyMigrationV4DecisionMadeBy,
63
- applyMigrationV5HierarchyTables,
64
- applyMigrationV6SliceSummaries,
65
- applyMigrationV7Dependencies,
66
- applyMigrationV8PlanningFields,
67
- applyMigrationV9Ordering,
68
- applyMigrationV10ReplanTrigger,
69
- applyMigrationV11TaskPlanning,
70
- applyMigrationV12QualityGates,
71
- applyMigrationV13HotPathIndexes,
72
- applyMigrationV14SliceDependencies,
73
- applyMigrationV15AuditTables,
74
- applyMigrationV16EscalationSource,
75
- applyMigrationV17TaskEscalation,
76
- applyMigrationV18MemorySources,
77
- applyMigrationV19MemoryFts,
78
- applyMigrationV20MemoryRelations,
79
- applyMigrationV21StructuredMemories,
80
- applyMigrationV22QualityGateRepair,
81
- applyMigrationV23MilestoneQueue,
82
- applyMigrationV26MilestoneCommitAttributions,
83
- applyMigrationV27ArtifactHash,
84
- applyMigrationV28MemoryLastHitAt,
85
- applyMigrationV29RepositoryTargets,
86
- } from "./db-migration-steps.js";
87
- import { isMemoriesFtsAvailableSchema, tryCreateMemoriesFtsSchema } from "./db-memory-fts-schema.js";
88
- import { createDbOpenState, type DbOpenPhase } from "./db-open-state.js";
89
- import { createRuntimeKvTableV25 } from "./db-runtime-kv-schema.js";
90
- import { ensureColumn, getCurrentSchemaVersion, recordSchemaVersion } from "./db-schema-metadata.js";
91
45
  import { rowToSlice, rowToTask, type SliceRow, type TaskRow } from "./db-task-slice-rows.js";
92
- import { createDbTransactionRunner } from "./db-transaction.js";
93
- import { ensureVerificationEvidenceDedupIndex } from "./db-verification-evidence-schema.js";
94
- import {
95
- BETTER_SQLITE3_PACKAGE,
96
- createSqliteProviderLoader,
97
- suppressSqliteWarning,
98
- type DbProviderName,
99
- type SqliteFallbackOpen,
100
- } from "./db-provider.js";
101
- // Type-only import to avoid a circular runtime dep. The runtime side of
102
- // workflow-manifest.ts depends on this file, but the StateManifest type is
103
- // pure structure with no runtime coupling.
104
- import type { StateManifest } from "./workflow-manifest.js";
105
-
106
- let _gsdRequire: ReturnType<typeof createRequire> | null | undefined;
107
-
108
- function getGsdRequire(): ReturnType<typeof createRequire> | null {
109
- if (_gsdRequire !== undefined) return _gsdRequire;
110
- try {
111
- _gsdRequire = createRequire(import.meta.url);
112
- } catch {
113
- _gsdRequire = null;
114
- }
115
- return _gsdRequire;
116
- }
117
46
 
118
- type ProviderName = DbProviderName;
47
+ // Connection ownership, lifecycle, schema/migrations and transaction
48
+ // primitives now live in the engine; re-export the full public surface so
49
+ // existing `from "./gsd-db.js"` imports keep working.
50
+ export * from "./db/engine.js";
51
+ import { immediateTransaction, transaction, getDb, getDbOrNull } from "./db/engine.js";
52
+
53
+ // ─── Single Writer Layer re-exports ──────────────────────────────────────
54
+ // Domain write subsystems live in db/writers/*; re-exported here so callers
55
+ // keep importing from "./gsd-db.js".
56
+ export * from "./db/writers/memory.js";
57
+ export * from "./db/writers/reconcile.js";
58
+ export * from "./db/writers/import-restore.js";
59
+ // Query Module (read-only seam) — extracted from the single-writer file.
60
+ export * from "./db/queries.js";
61
+ // Domain Write Operations (Hierarchy Status Cascades).
62
+ export * from "./db/writers/cascades.js";
119
63
 
120
64
  export type { ArtifactRow, MilestoneRow } from "./db-milestone-artifact-rows.js";
121
65
  export type { ActiveTaskSummary, IdStatusSummary, TaskStatusCounts } from "./db-lightweight-query-rows.js";
122
66
  export type { SliceRow, TaskRow } from "./db-task-slice-rows.js";
123
67
 
124
- const providerLoader = createSqliteProviderLoader({
125
- tryRequireNodeSqlite: () => {
126
- const req = getGsdRequire();
127
- if (!req) throw new Error("unavailable");
128
- return req("node:sqlite");
129
- },
130
- tryRequireBetterSqlite3: () => {
131
- const req = getGsdRequire();
132
- if (!req) throw new Error("unavailable");
133
- return req(BETTER_SQLITE3_PACKAGE);
134
- },
135
- suppressSqliteWarning,
136
- nodeVersion: process.versions.node,
137
- writeStderr: (message: string) => process.stderr.write(message),
138
- });
139
-
140
- export const SCHEMA_VERSION = 29;
141
- const TERMINAL_STATUS_SQL = "'complete', 'done', 'skipped', 'closed'";
142
-
143
- function initSchema(db: DbAdapter, fileBacked: boolean, dbPath: string | null): void {
144
- const conservativeFilePragmas = fileBacked && _isLikelyWslDrvFsPathForTest(dbPath);
145
- if (fileBacked) db.exec(conservativeFilePragmas ? "PRAGMA journal_mode=DELETE" : "PRAGMA journal_mode=WAL");
146
- if (fileBacked) db.exec("PRAGMA busy_timeout = 5000");
147
- if (fileBacked) db.exec(conservativeFilePragmas ? "PRAGMA synchronous = FULL" : "PRAGMA synchronous = NORMAL");
148
- if (fileBacked) db.exec("PRAGMA auto_vacuum = INCREMENTAL");
149
- if (fileBacked) db.exec("PRAGMA cache_size = -8000"); // 8 MB page cache
150
- if (fileBacked && !conservativeFilePragmas && process.platform !== "darwin") db.exec("PRAGMA mmap_size = 67108864"); // 64 MB mmap
151
- db.exec("PRAGMA temp_store = MEMORY");
152
- db.exec("PRAGMA foreign_keys = ON");
153
-
154
- db.exec("BEGIN");
155
- try {
156
- createBaseSchemaObjects(db, {
157
- tryCreateMemoriesFts,
158
- ensureVerificationEvidenceDedupIndex,
159
- });
160
-
161
- const existing = db.prepare("SELECT count(*) as cnt FROM schema_version").get();
162
- if (existing && (existing["cnt"] as number) === 0) {
163
- createCoordinationTablesV24(db);
164
- createRuntimeKvTableV25(db);
165
-
166
- // Fresh install — all tables are created above with the full current schema,
167
- // so it is safe to create all migration-specific indexes here. For existing
168
- // databases these indexes are created inside the individual migration guards
169
- // in migrateSchema() after the corresponding columns have been added.
170
- db.exec("CREATE INDEX IF NOT EXISTS idx_tasks_escalation_pending ON tasks(milestone_id, slice_id, escalation_pending)");
171
- db.exec("CREATE INDEX IF NOT EXISTS idx_memories_scope ON memories(scope)");
172
- db.exec("CREATE INDEX IF NOT EXISTS idx_memory_sources_kind ON memory_sources(kind)");
173
- db.exec("CREATE INDEX IF NOT EXISTS idx_memory_sources_scope ON memory_sources(scope)");
174
- db.exec("CREATE INDEX IF NOT EXISTS idx_memory_relations_from ON memory_relations(from_id)");
175
- db.exec("CREATE INDEX IF NOT EXISTS idx_memory_relations_to ON memory_relations(to_id)");
176
-
177
- recordSchemaVersion(db, SCHEMA_VERSION);
178
- }
179
-
180
- db.exec("COMMIT");
181
- } catch (err) {
182
- db.exec("ROLLBACK");
183
- throw err;
184
- }
185
-
186
- migrateSchema(db);
187
- }
188
-
189
- export function _isLikelyWslDrvFsPathForTest(dbPath: string | null): boolean {
190
- if (!dbPath || process.platform !== "linux") return false;
191
- const drvFsPathPattern = /^\/mnt\/[a-z](?:\/|$)/i;
192
- if (drvFsPathPattern.test(dbPath)) return true;
193
- try {
194
- return drvFsPathPattern.test(realpathSync(dbPath));
195
- } catch {
196
- return false;
197
- }
198
- }
199
-
200
- /**
201
- * Create the FTS5 virtual table for memories plus the triggers that keep it
202
- * in sync with the base table. FTS5 may be unavailable on stripped-down
203
- * SQLite builds — callers should treat failure as non-fatal and fall back
204
- * to LIKE-based scans in `memory-store.queryMemoriesRanked`.
205
- */
206
- export function tryCreateMemoriesFts(db: DbAdapter): boolean {
207
- return tryCreateMemoriesFtsSchema(db, {
208
- onUnavailable: (message) => logWarning("db", message),
209
- });
210
- }
211
-
212
- export function isMemoriesFtsAvailable(db: DbAdapter): boolean {
213
- return isMemoriesFtsAvailableSchema(db);
214
- }
215
-
216
- function backfillMemoriesFts(db: DbAdapter): void {
217
- db.exec(`INSERT INTO memories_fts(rowid, content) SELECT seq, content FROM memories`);
218
- }
219
-
220
- function copyQualityGateRowsToRepairedTable(db: DbAdapter): void {
221
- db.exec(`
222
- INSERT OR IGNORE INTO quality_gates_new
223
- (milestone_id, slice_id, gate_id, scope, task_id, status, verdict, rationale, findings, evaluated_at)
224
- SELECT milestone_id, slice_id, gate_id, scope, COALESCE(task_id, ''), status, verdict, rationale, findings, evaluated_at
225
- FROM quality_gates
226
- `);
227
- }
228
-
229
- function migrateSchema(db: DbAdapter): void {
230
- const currentVersion = getCurrentSchemaVersion(db);
231
- if (currentVersion >= SCHEMA_VERSION) return;
232
-
233
- backupDatabaseBeforeMigration(db, currentPath, currentVersion, {
234
- existsSync,
235
- copyFileSync,
236
- logWarning,
237
- });
238
-
239
- db.exec("BEGIN");
240
- try {
241
- if (currentVersion < 2) {
242
- applyMigrationV2Artifacts(db);
243
- recordSchemaVersion(db, 2);
244
- }
245
-
246
- if (currentVersion < 3) {
247
- applyMigrationV3Memories(db);
248
- recordSchemaVersion(db, 3);
249
- }
250
-
251
- if (currentVersion < 4) {
252
- applyMigrationV4DecisionMadeBy(db);
253
- recordSchemaVersion(db, 4);
254
- }
255
-
256
- if (currentVersion < 5) {
257
- applyMigrationV5HierarchyTables(db);
258
- recordSchemaVersion(db, 5);
259
- }
260
-
261
- if (currentVersion < 6) {
262
- applyMigrationV6SliceSummaries(db);
263
- recordSchemaVersion(db, 6);
264
- }
265
-
266
- if (currentVersion < 7) {
267
- applyMigrationV7Dependencies(db);
268
- recordSchemaVersion(db, 7);
269
- }
270
-
271
- if (currentVersion < 8) {
272
- applyMigrationV8PlanningFields(db);
273
- recordSchemaVersion(db, 8);
274
- }
275
-
276
- if (currentVersion < 9) {
277
- applyMigrationV9Ordering(db);
278
- recordSchemaVersion(db, 9);
279
- }
280
-
281
- if (currentVersion < 10) {
282
- applyMigrationV10ReplanTrigger(db);
283
- recordSchemaVersion(db, 10);
284
- }
285
-
286
- if (currentVersion < 11) {
287
- applyMigrationV11TaskPlanning(db);
288
- recordSchemaVersion(db, 11);
289
- }
290
-
291
- if (currentVersion < 12) {
292
- // NOTE: The original DDL used COALESCE(task_id, '') in the PRIMARY KEY
293
- // expression, which is invalid SQLite syntax and causes startup errors on
294
- // DBs that migrate through v12. The corrected DDL uses
295
- // task_id TEXT NOT NULL DEFAULT '' with a plain column list PK. DBs that
296
- // were created with the broken DDL are repaired by the v22 migration below.
297
- applyMigrationV12QualityGates(db);
298
- recordSchemaVersion(db, 12);
299
- }
300
-
301
- if (currentVersion < 13) {
302
- applyMigrationV13HotPathIndexes(db, ensureVerificationEvidenceDedupIndex);
303
- recordSchemaVersion(db, 13);
304
- }
305
-
306
- if (currentVersion < 14) {
307
- applyMigrationV14SliceDependencies(db);
308
- recordSchemaVersion(db, 14);
309
- }
310
-
311
- if (currentVersion < 15) {
312
- applyMigrationV15AuditTables(db);
313
- recordSchemaVersion(db, 15);
314
- }
315
-
316
- if (currentVersion < 16) {
317
- applyMigrationV16EscalationSource(db);
318
- recordSchemaVersion(db, 16);
319
- }
320
-
321
- if (currentVersion < 17) {
322
- applyMigrationV17TaskEscalation(db);
323
- recordSchemaVersion(db, 17);
324
- }
325
-
326
- if (currentVersion < 18) {
327
- applyMigrationV18MemorySources(db);
328
- recordSchemaVersion(db, 18);
329
- }
330
-
331
- if (currentVersion < 19) {
332
- applyMigrationV19MemoryFts(db, {
333
- tryCreateMemoriesFts,
334
- isMemoriesFtsAvailable,
335
- backfillMemoriesFts,
336
- logWarning,
337
- });
338
- recordSchemaVersion(db, 19);
339
- }
340
-
341
- if (currentVersion < 20) {
342
- applyMigrationV20MemoryRelations(db);
343
- recordSchemaVersion(db, 20);
344
- }
345
-
346
- if (currentVersion < 21) {
347
- applyMigrationV21StructuredMemories(db);
348
- recordSchemaVersion(db, 21);
349
- }
350
-
351
- if (currentVersion < 22) {
352
- applyMigrationV22QualityGateRepair(db, { copyQualityGateRowsToRepairedTable });
353
- recordSchemaVersion(db, 22);
354
- }
355
-
356
- if (currentVersion < 23) {
357
- applyMigrationV23MilestoneQueue(db);
358
- recordSchemaVersion(db, 23);
359
- }
360
-
361
- if (currentVersion < 24) {
362
- // v24: auto-mode coordination tables. See createCoordinationTablesV24
363
- // for full schema + invariants. No-op for fresh installs (the same
364
- // helper runs in the fresh-install path); for upgraded DBs this is
365
- // the only place these tables get created.
366
- createCoordinationTablesV24(db);
367
- recordSchemaVersion(db, 24);
368
- }
369
-
370
- if (currentVersion < 25) {
371
- // v25: runtime_kv non-correctness-critical key-value storage. See
372
- // createRuntimeKvTableV25 for the full schema + invariants.
373
- createRuntimeKvTableV25(db);
374
- recordSchemaVersion(db, 25);
375
- }
376
-
377
- if (currentVersion < 26) {
378
- applyMigrationV26MilestoneCommitAttributions(db);
379
- recordSchemaVersion(db, 26);
380
- }
381
-
382
- if (currentVersion < 27) {
383
- applyMigrationV27ArtifactHash(db);
384
- recordSchemaVersion(db, 27);
385
- }
386
-
387
- if (currentVersion < 28) {
388
- applyMigrationV28MemoryLastHitAt(db);
389
- recordSchemaVersion(db, 28);
390
- }
391
-
392
- if (currentVersion < 29) {
393
- applyMigrationV29RepositoryTargets(db);
394
- recordSchemaVersion(db, 29);
395
- }
396
-
397
- db.exec("COMMIT");
398
- } catch (err) {
399
- db.exec("ROLLBACK");
400
- throw err;
401
- }
402
- }
403
-
404
- let currentDb: DbAdapter | null = null;
405
- let currentPath: string | null = null;
406
- let currentPid: number = 0;
407
- let _exitHandlerRegistered = false;
408
- const _dbOpenState = createDbOpenState();
409
- /**
410
- * Identity key of the workspace whose connection is currently active
411
- * (currentDb). Set by openDatabaseByWorkspace(); null when the active
412
- * connection was opened via the legacy openDatabase(path) path.
413
- */
414
- let _currentIdentityKey: string | null = null;
415
-
416
- /**
417
- * Workspace-scoped connection cache.
418
- * Key: GsdWorkspace.identityKey (realpath-normalized project root).
419
- * Value: the DB path and open adapter for that workspace.
420
- *
421
- * Sibling worktrees of the same project share the same identityKey (set by
422
- * createWorkspace) and therefore reuse the same cached connection, preserving
423
- * shared-WAL semantics. Different projects get distinct cache entries.
424
- *
425
- * NOTE: Only one connection is "active" at a time (currentDb/currentPath).
426
- * The cache allows fast re-activation of a previously opened connection when
427
- * callers switch between known workspaces via openDatabaseByWorkspace().
428
- */
429
- const _dbCache = createDbConnectionCache();
430
-
431
- /** Test helper: expose the internal cache for inspection. Not for production use. */
432
- export function _getDbCache(): ReadonlyMap<string, DbConnectionCacheEntry> {
433
- return _dbCache.asReadonlyMap();
434
- }
435
-
436
- function closeCachedConnection(entry: DbConnectionCacheEntry, source: "all" | "workspace"): void {
437
- try {
438
- entry.db.exec("PRAGMA wal_checkpoint(TRUNCATE)");
439
- } catch (e) {
440
- if (source === "workspace") logWarning("db", `WAL checkpoint (byWorkspace) failed: ${(e as Error).message}`);
441
- }
442
- try {
443
- entry.db.exec("PRAGMA incremental_vacuum(64)");
444
- } catch (e) {
445
- if (source === "workspace") logWarning("db", `incremental vacuum (byWorkspace) failed: ${(e as Error).message}`);
446
- }
447
- try {
448
- entry.db.close();
449
- } catch (e) {
450
- if (source === "workspace") logWarning("db", `database close (byWorkspace) failed: ${(e as Error).message}`);
451
- }
452
- }
453
-
454
- /**
455
- * Close and evict every entry in the workspace connection cache, then call
456
- * closeDatabase() to close the active connection.
457
- *
458
- * Use this for test teardown or process-shutdown paths where every open
459
- * connection must be flushed. Normal callers should use closeDatabase() or
460
- * closeDatabaseByWorkspace() instead.
461
- */
462
- export function closeAllDatabases(): void {
463
- // Close all non-active cached connections first.
464
- _dbCache.closeNonActive(currentDb, (entry) => closeCachedConnection(entry, "all"));
465
- closeDatabase();
466
- }
467
-
468
- /**
469
- * Open (or reuse) the database connection scoped to the given workspace.
470
- *
471
- * Uses workspace.identityKey as the cache key, so sibling worktrees of the
472
- * same project resolve to the same connection. On a cache hit the existing
473
- * adapter is reactivated as the current connection without re-opening the
474
- * file. On a cache miss, delegates to openDatabase() for the full
475
- * open + schema-init + migration flow, then caches the result.
476
- *
477
- * When switching to a different workspace, the previously active connection
478
- * is preserved in the cache (not closed), so callers can switch back to it
479
- * cheaply via a subsequent openDatabaseByWorkspace() call.
480
- *
481
- * @param workspace A GsdWorkspace created by createWorkspace().
482
- * @returns true if the connection is open and ready, false otherwise.
483
- */
484
- export function openDatabaseByWorkspace(workspace: GsdWorkspace): boolean {
485
- const key = workspace.identityKey;
486
- const dbPath = workspace.contract.projectDb;
487
-
488
- const cached = _dbCache.get(key);
489
- if (cached) {
490
- // Reactivate the cached connection as the current singleton.
491
- currentDb = cached.db;
492
- currentPath = cached.dbPath;
493
- currentPid = process.pid;
494
- _dbOpenState.markAttempted();
495
- _currentIdentityKey = key;
496
- return true;
497
- }
498
-
499
- // Cache miss — need to open a new connection.
500
- //
501
- // If there is a currently active workspace connection, stash it in the
502
- // cache under its identity key before calling openDatabase(), because
503
- // openDatabase() will call closeDatabase() when the path changes (which
504
- // would destroy the existing adapter). By nulling out currentDb first,
505
- // we prevent openDatabase() from closing the live adapter.
506
- let oldDb: typeof currentDb = null;
507
- let oldPath: typeof currentPath = null;
508
- let oldPid: typeof currentPid = 0;
509
- let oldKey: typeof _currentIdentityKey = null;
510
-
511
- if (currentDb !== null && _currentIdentityKey !== null) {
512
- // Snapshot the old globals so we can restore them on failure.
513
- oldDb = currentDb;
514
- oldPath = currentPath;
515
- oldPid = currentPid;
516
- oldKey = _currentIdentityKey;
517
- // Save the current connection so it stays alive in the cache.
518
- _dbCache.set(_currentIdentityKey, {
519
- dbPath: currentPath!,
520
- db: currentDb,
521
- });
522
- // Detach from globals so openDatabase() opens fresh without closing it.
523
- currentDb = null;
524
- currentPath = null;
525
- currentPid = 0;
526
- _currentIdentityKey = null;
527
- }
528
-
529
- // Run the full open/schema/migration flow for the new workspace.
530
- // openDatabase() can throw on corrupt DB or permission error — catch so we
531
- // can restore the previous connection rather than leaving globals null.
532
- let opened: boolean;
533
- try {
534
- opened = openDatabase(dbPath);
535
- } catch (err) {
536
- // Failed to open the new DB. Restore the previous workspace connection so
537
- // the caller's workspace remains active (it is still safe in _dbCache).
538
- if (oldDb !== null) {
539
- currentDb = oldDb;
540
- currentPath = oldPath;
541
- currentPid = oldPid;
542
- _currentIdentityKey = oldKey;
543
- }
544
- throw err;
545
- }
546
- if (opened && currentDb) {
547
- _dbCache.set(key, { dbPath, db: currentDb });
548
- _currentIdentityKey = key;
549
- } else if (!opened && oldDb !== null) {
550
- // Restore the previous connection so the caller's workspace remains active.
551
- // The failed attempt left no live adapter, so the globals stayed null.
552
- currentDb = oldDb;
553
- currentPath = oldPath;
554
- currentPid = oldPid;
555
- _currentIdentityKey = oldKey;
556
- }
557
- return opened;
558
- }
559
-
560
- /**
561
- * Open (or reuse) the database connection scoped to the workspace in a
562
- * MilestoneScope. Thin delegation to openDatabaseByWorkspace().
563
- */
564
- export function openDatabaseByScope(scope: MilestoneScope): boolean {
565
- return openDatabaseByWorkspace(scope.workspace);
566
- }
567
-
568
- /**
569
- * Close the database connection for the given workspace and remove it from
570
- * the cache. If the workspace's connection is currently active (currentDb),
571
- * performs a full closeDatabase() including WAL checkpoint. Otherwise only
572
- * removes the cache entry (the adapter was already replaced by a later open).
573
- */
574
- export function closeDatabaseByWorkspace(workspace: GsdWorkspace): void {
575
- const key = workspace.identityKey;
576
- const cached = _dbCache.get(key);
577
- if (!cached) return;
578
-
579
- _dbCache.delete(key);
580
-
581
- if (currentDb === cached.db) {
582
- // This workspace's connection is the active one — full close.
583
- closeDatabase();
584
- } else {
585
- // Connection was displaced by a later open; close the adapter directly.
586
- closeCachedConnection(cached, "workspace");
587
- }
588
- }
589
-
590
- export function getDbProvider(): ProviderName | null {
591
- providerLoader.load();
592
- return providerLoader.getProviderName();
593
- }
594
-
595
- export function isDbAvailable(): boolean {
596
- return currentDb !== null;
597
- }
598
-
599
- /**
600
- * Returns true if openDatabase() has been called at least once this session.
601
- * Used to distinguish "DB not yet initialized" from "DB genuinely unavailable"
602
- * so that early callers (e.g. before_agent_start context injection) don't
603
- * trigger a false degraded-mode warning.
604
- */
605
- export function wasDbOpenAttempted(): boolean {
606
- return _dbOpenState.snapshot().attempted;
607
- }
608
-
609
- export function getDbStatus(): {
610
- available: boolean;
611
- provider: ProviderName | null;
612
- attempted: boolean;
613
- lastError: Error | null;
614
- lastPhase: DbOpenPhase | null;
615
- } {
616
- providerLoader.load();
617
- const openState = _dbOpenState.snapshot();
618
- return {
619
- available: currentDb !== null,
620
- provider: providerLoader.getProviderName(),
621
- attempted: openState.attempted,
622
- lastError: openState.lastError,
623
- lastPhase: openState.lastPhase,
624
- };
625
- }
626
-
627
- export function openDatabase(path: string): boolean {
628
- _dbOpenState.markAttempted();
629
- if (currentDb && currentPath !== path) closeDatabase();
630
- if (currentDb && currentPath === path) return true;
631
-
632
- // Reset error state only when a new open attempt is actually going to run.
633
- _dbOpenState.clearError();
634
-
635
- let rawDb: unknown;
636
- let fallbackOpen: SqliteFallbackOpen | null = null;
637
- try {
638
- rawDb = providerLoader.openRaw(path);
639
- } catch (primaryErr) {
640
- _dbOpenState.recordError("open", primaryErr);
641
- // node:sqlite loaded but failed to open this file — try better-sqlite3 as fallback.
642
- fallbackOpen = providerLoader.tryOpenBetterSqliteFallback(path);
643
- if (fallbackOpen) {
644
- rawDb = fallbackOpen.rawDb;
645
- _dbOpenState.clearError();
646
- }
647
- if (!rawDb) throw primaryErr;
648
- }
649
- if (!rawDb) return false;
650
-
651
- const adapter = createDbAdapter(rawDb);
652
- const fileBacked = path !== ":memory:";
653
- try {
654
- initSchema(adapter, fileBacked, path);
655
- } catch (err) {
656
- // Corrupt freelist: DDL fails with "malformed" but VACUUM can rebuild.
657
- // Attempt VACUUM recovery before giving up (see #2519).
658
- if (fileBacked && err instanceof Error && err.message?.includes("malformed")) {
659
- try {
660
- adapter.exec("VACUUM");
661
- initSchema(adapter, fileBacked, path);
662
- process.stderr.write("gsd-db: recovered corrupt database via VACUUM\n");
663
- } catch (retryErr) {
664
- _dbOpenState.recordError("vacuum-recovery", retryErr);
665
- try { adapter.close(); } catch (e) { logWarning("db", `close after VACUUM failed: ${(e as Error).message}`); }
666
- throw retryErr;
667
- }
668
- } else {
669
- _dbOpenState.recordError("initSchema", err);
670
- try { adapter.close(); } catch (e) { logWarning("db", `close after initSchema failed: ${(e as Error).message}`); }
671
- throw err;
672
- }
673
- }
674
-
675
- // Commit fallback provider switch only after open + schema both succeeded.
676
- if (fallbackOpen) providerLoader.commitFallback(fallbackOpen);
677
-
678
- currentDb = adapter;
679
- currentPath = path;
680
- currentPid = process.pid;
681
-
682
- if (!_exitHandlerRegistered) {
683
- _exitHandlerRegistered = true;
684
- process.on("exit", () => { try { closeDatabase(); } catch (e) { logWarning("db", `exit handler close failed: ${(e as Error).message}`); } });
685
- }
686
-
687
- return true;
688
- }
689
-
690
- export function closeDatabase(): void {
691
- if (currentDb) {
692
- try {
693
- currentDb.exec('PRAGMA wal_checkpoint(TRUNCATE)');
694
- } catch (e) { logWarning("db", `WAL checkpoint failed: ${(e as Error).message}`); }
695
- try {
696
- // Incremental vacuum to reclaim space without blocking
697
- currentDb.exec('PRAGMA incremental_vacuum(64)');
698
- } catch (e) { logWarning("db", `incremental vacuum failed: ${(e as Error).message}`); }
699
- try {
700
- currentDb.close();
701
- } catch (e) { logWarning("db", `database close failed: ${(e as Error).message}`); }
702
- // If this connection was workspace-tracked, evict it from the cache so
703
- // subsequent openDatabaseByWorkspace() calls re-open rather than reactivate
704
- // a closed adapter.
705
- if (_currentIdentityKey !== null) {
706
- _dbCache.delete(_currentIdentityKey);
707
- _currentIdentityKey = null;
708
- }
709
- currentDb = null;
710
- currentPath = null;
711
- currentPid = 0;
712
- }
713
- // Reset session-scoped state unconditionally so stale error info from a
714
- // failed open doesn't persist into the next open attempt or status check.
715
- _dbOpenState.reset();
716
- }
717
-
718
- /**
719
- * Re-open the active database connection from disk.
720
- *
721
- * Auto-mode can observe artifacts written by a workflow server running in a
722
- * different process before its long-lived singleton has re-synchronized. The
723
- * recovery path uses this to force the next state derivation to read from the
724
- * current on-disk database instead of continuing with a possibly stale handle.
725
- */
726
- export function refreshOpenDatabaseFromDisk(): boolean {
727
- if (!currentDb || !currentPath) return false;
728
- if (currentPath === ":memory:") return false;
729
-
730
- const dbPath = currentPath;
731
- const identityKey = _currentIdentityKey;
732
-
733
- try {
734
- closeDatabase();
735
- const opened = openDatabase(dbPath);
736
- if (opened && identityKey && currentDb) {
737
- _dbCache.set(identityKey, { dbPath, db: currentDb });
738
- _currentIdentityKey = identityKey;
739
- }
740
- return opened;
741
- } catch (e) {
742
- logWarning("db", `database refresh failed: ${(e as Error).message}`);
743
- return false;
744
- }
745
- }
746
-
747
- /** Run a full VACUUM — call sparingly (e.g. after milestone completion). */
748
- export function vacuumDatabase(): void {
749
- if (!currentDb) return;
750
- try {
751
- currentDb.exec('VACUUM');
752
- } catch (e) { logWarning("db", `VACUUM failed: ${(e as Error).message}`); }
753
- }
754
-
755
- /** Flush WAL into gsd.db so `git add .gsd/gsd.db` stages current state — safe while DB is open. */
756
- export function checkpointDatabase(): void {
757
- if (!currentDb) return;
758
- try {
759
- currentDb.exec('PRAGMA wal_checkpoint(TRUNCATE)');
760
- } catch (e) { logWarning("db", `WAL checkpoint failed: ${(e as Error).message}`); }
761
- }
762
-
763
- /**
764
- * Copy the live database file to `.gsd/backups/<label>-<timestamp>.db` so a
765
- * destructive operation (e.g. recover, which clears the hierarchy tables) is
766
- * reversible. Checkpoints the WAL first so the snapshot is complete. Returns
767
- * the backup path, or null if no DB is open or the copy failed.
768
- */
769
- export function backupDatabaseSnapshot(label: string): string | null {
770
- if (!currentPath) return null;
771
- try {
772
- checkpointDatabase();
773
- const backupsDir = join(dirname(currentPath), "backups");
774
- mkdirSync(backupsDir, { recursive: true });
775
- const stamp = new Date().toISOString().replace(/[:.]/g, "-");
776
- const dest = join(backupsDir, `${label}-${stamp}.db`);
777
- copyFileSync(currentPath, dest);
778
- return dest;
779
- } catch (e) {
780
- logWarning("db", `database snapshot failed: ${(e as Error).message}`);
781
- return null;
782
- }
783
- }
784
-
785
- const _transactionRunner = createDbTransactionRunner();
786
-
787
- function createTransactionControls(db: DbAdapter) {
788
- return {
789
- begin: () => db.exec("BEGIN"),
790
- beginRead: () => db.exec("BEGIN DEFERRED"),
791
- commit: () => db.exec("COMMIT"),
792
- rollback: () => db.exec("ROLLBACK"),
793
- };
794
- }
795
-
796
- /**
797
- * Whether the current call is running inside an active SQLite transaction.
798
- * Statement-time recovery paths (e.g. VACUUM retry on a malformed memory
799
- * store) MUST gate on this — SQLite refuses VACUUM inside a transaction
800
- * and would mask the original error with a secondary "cannot VACUUM" throw.
801
- */
802
- export function isInTransaction(): boolean {
803
- return _transactionRunner.isInTransaction();
804
- }
805
-
806
- export function transaction<T>(fn: () => T): T {
807
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
808
- return _transactionRunner.transaction(createTransactionControls(currentDb), fn);
809
- }
810
-
811
- /**
812
- * Wrap a block of reads in a DEFERRED transaction so that all SELECTs observe
813
- * a consistent snapshot of the DB even if a concurrent writer commits between
814
- * them. Use this for multi-query read flows (e.g. tool executors that query
815
- * milestone + slices + counts and want one snapshot). Re-entrant — if already
816
- * inside a transaction, runs fn() without starting a nested one.
817
- */
818
- export function readTransaction<T>(fn: () => T): T {
819
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
820
-
821
- return _transactionRunner.readTransaction(createTransactionControls(currentDb), fn, (rollbackErr) => {
822
- // A failed ROLLBACK after a failed read is a split-brain signal —
823
- // the transaction is in an indeterminate state. Surface it via the
824
- // logger instead of swallowing it.
825
- logError("db", "snapshotState ROLLBACK failed", {
826
- error: rollbackErr.message,
827
- });
828
- });
829
- }
68
+ import { TERMINAL_STATUS_SQL } from "./db/sql-constants.js";
69
+ import { applyStatusTransition } from "./db/writers/status.js";
830
70
 
831
71
  export function insertDecision(d: Omit<Decision, "seq">): void {
832
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
833
- currentDb.prepare(
72
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
73
+ getDbOrNull()!.prepare(
834
74
  `INSERT INTO decisions (id, when_context, scope, decision, choice, rationale, revisable, made_by, source, superseded_by)
835
75
  VALUES (:id, :when_context, :scope, :decision, :choice, :rationale, :revisable, :made_by, :source, :superseded_by)`,
836
76
  ).run({
@@ -847,22 +87,11 @@ export function insertDecision(d: Omit<Decision, "seq">): void {
847
87
  });
848
88
  }
849
89
 
850
- export function getDecisionById(id: string): Decision | null {
851
- if (!currentDb) return null;
852
- const row = currentDb.prepare("SELECT * FROM decisions WHERE id = ?").get(id);
853
- if (!row) return null;
854
- return rowToDecision(row);
855
- }
856
90
 
857
- export function getActiveDecisions(): Decision[] {
858
- if (!currentDb) return [];
859
- const rows = currentDb.prepare("SELECT * FROM active_decisions").all();
860
- return rows.map(rowToActiveDecision);
861
- }
862
91
 
863
92
  export function insertRequirement(r: Requirement): void {
864
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
865
- currentDb.prepare(
93
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
94
+ getDbOrNull()!.prepare(
866
95
  `INSERT INTO requirements (id, class, status, description, why, source, primary_owner, supporting_slices, validation, notes, full_content, superseded_by)
867
96
  VALUES (:id, :class, :status, :description, :why, :source, :primary_owner, :supporting_slices, :validation, :notes, :full_content, :superseded_by)`,
868
97
  ).run({
@@ -881,58 +110,15 @@ export function insertRequirement(r: Requirement): void {
881
110
  });
882
111
  }
883
112
 
884
- export function getRequirementById(id: string): Requirement | null {
885
- if (!currentDb) return null;
886
- const row = currentDb.prepare("SELECT * FROM requirements WHERE id = ?").get(id);
887
- if (!row) return null;
888
- return rowToRequirement(row);
889
- }
890
-
891
- export function getActiveRequirements(): Requirement[] {
892
- if (!currentDb) return [];
893
- const rows = currentDb.prepare("SELECT * FROM active_requirements").all();
894
- return rows.map(rowToActiveRequirement);
895
- }
896
-
897
- export function getRequirementCounts(): {
898
- active: number;
899
- validated: number;
900
- deferred: number;
901
- outOfScope: number;
902
- blocked: number;
903
- total: number;
904
- } {
905
- if (!currentDb) {
906
- return { active: 0, validated: 0, deferred: 0, outOfScope: 0, blocked: 0, total: 0 };
907
- }
908
- const rows = currentDb
909
- .prepare("SELECT lower(status) as status, COUNT(*) as count FROM requirements GROUP BY lower(status)")
910
- .all();
911
- return rowsToRequirementCounts(rows);
912
- }
913
-
914
- export function getDbOwnerPid(): number {
915
- return currentPid;
916
- }
917
-
918
- export function getDbPath(): string | null {
919
- return currentPath;
920
- }
921
113
 
922
- export function _getAdapter(): DbAdapter | null {
923
- return currentDb;
924
- }
925
114
 
926
- export function _resetProvider(): void {
927
- providerLoader.reset();
928
- }
929
115
 
930
116
  export function upsertDecision(d: Omit<Decision, "seq">): void {
931
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
117
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
932
118
  // Use ON CONFLICT DO UPDATE instead of INSERT OR REPLACE to preserve the
933
119
  // seq column. INSERT OR REPLACE deletes then reinserts, resetting seq and
934
120
  // corrupting decision ordering in DECISIONS.md after reconcile replay.
935
- currentDb.prepare(
121
+ getDbOrNull()!.prepare(
936
122
  `INSERT INTO decisions (id, when_context, scope, decision, choice, rationale, revisable, made_by, source, superseded_by)
937
123
  VALUES (:id, :when_context, :scope, :decision, :choice, :rationale, :revisable, :made_by, :source, :superseded_by)
938
124
  ON CONFLICT(id) DO UPDATE SET
@@ -960,8 +146,8 @@ export function upsertDecision(d: Omit<Decision, "seq">): void {
960
146
  }
961
147
 
962
148
  export function upsertRequirement(r: Requirement): void {
963
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
964
- currentDb.prepare(
149
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
150
+ getDbOrNull()!.prepare(
965
151
  `INSERT OR REPLACE INTO requirements (id, class, status, description, why, source, primary_owner, supporting_slices, validation, notes, full_content, superseded_by)
966
152
  VALUES (:id, :class, :status, :description, :why, :source, :primary_owner, :supporting_slices, :validation, :notes, :full_content, :superseded_by)`,
967
153
  ).run({
@@ -981,18 +167,18 @@ export function upsertRequirement(r: Requirement): void {
981
167
  }
982
168
 
983
169
  export function clearArtifacts(): void {
984
- if (!currentDb) return;
985
- try { currentDb.exec("DELETE FROM artifacts"); } catch (e) { logWarning("db", `clearArtifacts failed: ${(e as Error).message}`); }
170
+ if (!getDbOrNull()!) return;
171
+ try { getDbOrNull()!.exec("DELETE FROM artifacts"); } catch (e) { logWarning("db", `clearArtifacts failed: ${(e as Error).message}`); }
986
172
  }
987
173
 
988
174
  export function clearDecisions(): void {
989
- if (!currentDb) return;
990
- try { currentDb.exec("DELETE FROM decisions"); } catch (e) { logWarning("db", `clearDecisions failed: ${(e as Error).message}`); }
175
+ if (!getDbOrNull()!) return;
176
+ try { getDbOrNull()!.exec("DELETE FROM decisions"); } catch (e) { logWarning("db", `clearDecisions failed: ${(e as Error).message}`); }
991
177
  }
992
178
 
993
179
  export function clearRequirements(): void {
994
- if (!currentDb) return;
995
- try { currentDb.exec("DELETE FROM requirements"); } catch (e) { logWarning("db", `clearRequirements failed: ${(e as Error).message}`); }
180
+ if (!getDbOrNull()!) return;
181
+ try { getDbOrNull()!.exec("DELETE FROM requirements"); } catch (e) { logWarning("db", `clearRequirements failed: ${(e as Error).message}`); }
996
182
  }
997
183
 
998
184
  export function insertArtifact(a: {
@@ -1003,9 +189,9 @@ export function insertArtifact(a: {
1003
189
  task_id: string | null;
1004
190
  full_content: string;
1005
191
  }): void {
1006
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
192
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1007
193
  const contentHash = createHash("sha256").update(a.full_content).digest("hex");
1008
- currentDb.prepare(
194
+ getDbOrNull()!.prepare(
1009
195
  `INSERT OR REPLACE INTO artifacts (path, artifact_type, milestone_id, slice_id, task_id, full_content, imported_at, content_hash)
1010
196
  VALUES (:path, :artifact_type, :milestone_id, :slice_id, :task_id, :full_content, :imported_at, :content_hash)`,
1011
197
  ).run({
@@ -1062,9 +248,9 @@ export function insertMilestone(m: {
1062
248
  status?: string;
1063
249
  depends_on?: string[];
1064
250
  planning?: Partial<MilestonePlanningRecord>;
1065
- }): void {
1066
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1067
- currentDb.prepare(
251
+ }): boolean {
252
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
253
+ const result = getDbOrNull()!.prepare(
1068
254
  `INSERT OR IGNORE INTO milestones (
1069
255
  id, title, status, depends_on, created_at,
1070
256
  vision, success_criteria, key_risks, proof_strategy,
@@ -1095,12 +281,13 @@ export function insertMilestone(m: {
1095
281
  ":definition_of_done": JSON.stringify(m.planning?.definitionOfDone ?? []),
1096
282
  ":requirement_coverage": m.planning?.requirementCoverage ?? "",
1097
283
  ":boundary_map_markdown": m.planning?.boundaryMapMarkdown ?? "",
1098
- });
284
+ }) as { changes?: number };
285
+ return (result.changes ?? 0) > 0;
1099
286
  }
1100
287
 
1101
288
  export function upsertMilestonePlanning(milestoneId: string, planning: Partial<MilestonePlanningRecord> & { title?: string; status?: string; depends_on?: string[] }): void {
1102
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1103
- currentDb.prepare(
289
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
290
+ getDbOrNull()!.prepare(
1104
291
  `UPDATE milestones SET
1105
292
  title = COALESCE(NULLIF(:title, ''), title),
1106
293
  status = COALESCE(NULLIF(:status, ''), status),
@@ -1149,8 +336,13 @@ export function insertSlice(s: {
1149
336
  sketchScope?: string;
1150
337
  planning?: Partial<SlicePlanningRecord>;
1151
338
  }): void {
1152
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1153
- currentDb.prepare(
339
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
340
+ const SLICE_ID_RE = /^[A-Za-z0-9][A-Za-z0-9-]*$/;
341
+ const invalidDep = (s.depends ?? []).find(d => !SLICE_ID_RE.test(d));
342
+ if (invalidDep !== undefined) {
343
+ throw new GSDError(GSD_STALE_STATE, `insertSlice: depends element "${invalidDep}" is not a valid slice ID`);
344
+ }
345
+ getDbOrNull()!.prepare(
1154
346
  `INSERT INTO slices (
1155
347
  milestone_id, id, title, status, risk, depends, demo, created_at,
1156
348
  goal, success_criteria, proof_level, integration_closure, observability_impact, target_repositories, sequence,
@@ -1214,29 +406,16 @@ export function insertSlice(s: {
1214
406
 
1215
407
  // ADR-011: sketch-then-refine helpers
1216
408
  export function setSliceSketchFlag(milestoneId: string, sliceId: string, isSketch: boolean): void {
1217
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1218
- currentDb.prepare(
409
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
410
+ getDbOrNull()!.prepare(
1219
411
  `UPDATE slices SET is_sketch = :is_sketch WHERE milestone_id = :mid AND id = :sid`,
1220
412
  ).run({ ":is_sketch": isSketch ? 1 : 0, ":mid": milestoneId, ":sid": sliceId });
1221
413
  }
1222
414
 
1223
- /**
1224
- * ADR-017 raw primitive: returns slice IDs in a milestone whose is_sketch flag
1225
- * is still 1. The stale-sketch-flag drift handler at
1226
- * `state-reconciliation/drift/sketch-flag.ts` composes this with PLAN.md
1227
- * existence checks to detect drift, then writes via `setSliceSketchFlag`.
1228
- */
1229
- export function getSketchedSliceIds(milestoneId: string): string[] {
1230
- if (!currentDb) return [];
1231
- const rows = currentDb.prepare(
1232
- `SELECT id FROM slices WHERE milestone_id = :mid AND is_sketch = 1`,
1233
- ).all({ ":mid": milestoneId }) as Array<{ id: string }>;
1234
- return rows.map((r) => r.id);
1235
- }
1236
415
 
1237
416
  export function upsertSlicePlanning(milestoneId: string, sliceId: string, planning: Partial<SlicePlanningRecord>): void {
1238
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1239
- currentDb.prepare(
417
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
418
+ getDbOrNull()!.prepare(
1240
419
  `UPDATE slices SET
1241
420
  goal = COALESCE(:goal, goal),
1242
421
  success_criteria = COALESCE(:success_criteria, success_criteria),
@@ -1276,8 +455,8 @@ export function insertTask(t: {
1276
455
  sequence?: number;
1277
456
  planning?: Partial<TaskPlanningRecord>;
1278
457
  }): void {
1279
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1280
- currentDb.prepare(
458
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
459
+ getDbOrNull()!.prepare(
1281
460
  `INSERT INTO tasks (
1282
461
  milestone_id, slice_id, id, title, status, one_liner, narrative,
1283
462
  verification_result, duration, completed_at, blocker_discovered,
@@ -1353,29 +532,19 @@ export function insertTask(t: {
1353
532
  }
1354
533
 
1355
534
  export function updateTaskStatus(milestoneId: string, sliceId: string, taskId: string, status: string, completedAt?: string): void {
1356
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1357
- currentDb.prepare(
1358
- `UPDATE tasks SET status = :status, completed_at = :completed_at
1359
- WHERE milestone_id = :milestone_id AND slice_id = :slice_id AND id = :id`,
1360
- ).run({
1361
- ":status": status,
1362
- ":completed_at": completedAt ?? null,
1363
- ":milestone_id": milestoneId,
1364
- ":slice_id": sliceId,
1365
- ":id": taskId,
1366
- });
535
+ applyStatusTransition({ entity: "task", milestoneId, sliceId, taskId, status, completedAt });
1367
536
  }
1368
537
 
1369
538
  export function setTaskBlockerDiscovered(milestoneId: string, sliceId: string, taskId: string, discovered: boolean): void {
1370
- if (!currentDb) return;
1371
- currentDb.prepare(
539
+ if (!getDbOrNull()!) return;
540
+ getDbOrNull()!.prepare(
1372
541
  `UPDATE tasks SET blocker_discovered = :discovered WHERE milestone_id = :mid AND slice_id = :sid AND id = :tid`,
1373
542
  ).run({ ":discovered": discovered ? 1 : 0, ":mid": milestoneId, ":sid": sliceId, ":tid": taskId });
1374
543
  }
1375
544
 
1376
545
  export function upsertTaskPlanning(milestoneId: string, sliceId: string, taskId: string, planning: Partial<TaskPlanningRecord>): void {
1377
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1378
- currentDb.prepare(
546
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
547
+ getDbOrNull()!.prepare(
1379
548
  `UPDATE tasks SET
1380
549
  title = COALESCE(:title, title),
1381
550
  description = COALESCE(:description, description),
@@ -1405,95 +574,28 @@ export function upsertTaskPlanning(milestoneId: string, sliceId: string, taskId:
1405
574
  });
1406
575
  }
1407
576
 
1408
- export function getSlice(milestoneId: string, sliceId: string): SliceRow | null {
1409
- if (!currentDb) return null;
1410
- const row = currentDb.prepare("SELECT * FROM slices WHERE milestone_id = :mid AND id = :sid").get({ ":mid": milestoneId, ":sid": sliceId });
1411
- if (!row) return null;
1412
- return rowToSlice(row);
1413
- }
1414
577
 
1415
578
  export function updateSliceStatus(milestoneId: string, sliceId: string, status: string, completedAt?: string): void {
1416
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1417
- currentDb.prepare(
1418
- `UPDATE slices SET status = :status, completed_at = :completed_at
1419
- WHERE milestone_id = :milestone_id AND id = :id`,
1420
- ).run({
1421
- ":status": status,
1422
- ":completed_at": completedAt ?? null,
1423
- ":milestone_id": milestoneId,
1424
- ":id": sliceId,
1425
- });
579
+ applyStatusTransition({ entity: "slice", milestoneId, sliceId, status, completedAt });
1426
580
  }
1427
581
 
1428
582
  export function setTaskSummaryMd(milestoneId: string, sliceId: string, taskId: string, md: string): void {
1429
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1430
- currentDb.prepare(
583
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
584
+ getDbOrNull()!.prepare(
1431
585
  `UPDATE tasks SET full_summary_md = :md WHERE milestone_id = :mid AND slice_id = :sid AND id = :tid`,
1432
586
  ).run({ ":mid": milestoneId, ":sid": sliceId, ":tid": taskId, ":md": md });
1433
587
  }
1434
588
 
1435
589
  export function setSliceSummaryMd(milestoneId: string, sliceId: string, summaryMd: string, uatMd: string): void {
1436
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1437
- currentDb.prepare(
590
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
591
+ getDbOrNull()!.prepare(
1438
592
  `UPDATE slices SET full_summary_md = :summary_md, full_uat_md = :uat_md WHERE milestone_id = :mid AND id = :sid`,
1439
593
  ).run({ ":mid": milestoneId, ":sid": sliceId, ":summary_md": summaryMd, ":uat_md": uatMd });
1440
594
  }
1441
595
 
1442
- export function getTask(milestoneId: string, sliceId: string, taskId: string): TaskRow | null {
1443
- if (!currentDb) return null;
1444
- const row = currentDb.prepare(
1445
- "SELECT * FROM tasks WHERE milestone_id = :mid AND slice_id = :sid AND id = :tid",
1446
- ).get({ ":mid": milestoneId, ":sid": sliceId, ":tid": taskId });
1447
- if (!row) return null;
1448
- return rowToTask(row);
1449
- }
1450
596
 
1451
- export function getSliceTasks(milestoneId: string, sliceId: string): TaskRow[] {
1452
- if (!currentDb) return [];
1453
- const rows = currentDb.prepare(
1454
- "SELECT * FROM tasks WHERE milestone_id = :mid AND slice_id = :sid ORDER BY sequence, id",
1455
- ).all({ ":mid": milestoneId, ":sid": sliceId });
1456
- return rows.map(rowToTask);
1457
- }
1458
-
1459
- export function getCompletedMilestoneTaskFileHints(milestoneId: string): string[] {
1460
- if (!currentDb) return [];
1461
- const rows = currentDb.prepare(
1462
- `SELECT files, key_files
1463
- FROM tasks
1464
- WHERE milestone_id = :mid AND status IN ('complete', 'done')`,
1465
- ).all({ ":mid": milestoneId }) as Array<Record<string, unknown>>;
1466
-
1467
- const hints = new Set<string>();
1468
- for (const row of rows) {
1469
- for (const raw of [row["files"], row["key_files"]]) {
1470
- for (const file of parseStringArrayColumn(raw)) {
1471
- const normalized = normalizeRepoPath(file);
1472
- if (normalized) hints.add(normalized);
1473
- }
1474
- }
1475
- }
1476
- return [...hints];
1477
- }
1478
597
 
1479
- function parseStringArrayColumn(raw: unknown): string[] {
1480
- if (Array.isArray(raw)) return raw.filter((entry): entry is string => typeof entry === "string");
1481
- if (typeof raw !== "string") return [];
1482
- const trimmed = raw.trim();
1483
- if (!trimmed) return [];
1484
- try {
1485
- const parsed = JSON.parse(trimmed);
1486
- if (Array.isArray(parsed)) return parsed.filter((entry): entry is string => typeof entry === "string");
1487
- if (typeof parsed === "string") return [parsed];
1488
- } catch {
1489
- return trimmed.split(",");
1490
- }
1491
- return [];
1492
- }
1493
598
 
1494
- function normalizeRepoPath(file: string): string {
1495
- return file.trim().replace(/\\/g, "/").replace(/^\.\/+/, "");
1496
- }
1497
599
 
1498
600
  // ─── ADR-011 Phase 2 escalation helpers ──────────────────────────────────
1499
601
 
@@ -1502,8 +604,8 @@ export function setTaskEscalationPending(
1502
604
  milestoneId: string, sliceId: string, taskId: string,
1503
605
  artifactPath: string,
1504
606
  ): void {
1505
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1506
- currentDb.prepare(
607
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
608
+ getDbOrNull()!.prepare(
1507
609
  `UPDATE tasks
1508
610
  SET escalation_pending = 1,
1509
611
  escalation_awaiting_review = 0,
@@ -1517,8 +619,8 @@ export function setTaskEscalationAwaitingReview(
1517
619
  milestoneId: string, sliceId: string, taskId: string,
1518
620
  artifactPath: string,
1519
621
  ): void {
1520
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1521
- currentDb.prepare(
622
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
623
+ getDbOrNull()!.prepare(
1522
624
  `UPDATE tasks
1523
625
  SET escalation_awaiting_review = 1,
1524
626
  escalation_pending = 0,
@@ -1531,8 +633,8 @@ export function setTaskEscalationAwaitingReview(
1531
633
  export function clearTaskEscalationFlags(
1532
634
  milestoneId: string, sliceId: string, taskId: string,
1533
635
  ): void {
1534
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1535
- currentDb.prepare(
636
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
637
+ getDbOrNull()!.prepare(
1536
638
  `UPDATE tasks
1537
639
  SET escalation_pending = 0,
1538
640
  escalation_awaiting_review = 0
@@ -1548,9 +650,9 @@ export function clearTaskEscalationFlags(
1548
650
  export function claimEscalationOverride(
1549
651
  milestoneId: string, sliceId: string, sourceTaskId: string,
1550
652
  ): boolean {
1551
- if (!currentDb) return false;
653
+ if (!getDbOrNull()!) return false;
1552
654
  const now = new Date().toISOString();
1553
- const result = currentDb.prepare(
655
+ const result = getDbOrNull()!.prepare(
1554
656
  `UPDATE tasks
1555
657
  SET escalation_override_applied_at = :now
1556
658
  WHERE milestone_id = :mid AND slice_id = :sid AND id = :tid
@@ -1562,39 +664,13 @@ export function claimEscalationOverride(
1562
664
  return changes > 0;
1563
665
  }
1564
666
 
1565
- /** Find the most recent resolved-but-unapplied escalation override in a slice. */
1566
- export function findUnappliedEscalationOverride(
1567
- milestoneId: string, sliceId: string,
1568
- ): { taskId: string; artifactPath: string } | null {
1569
- if (!currentDb) return null;
1570
- // Filter BOTH flags: escalation_pending=0 AND escalation_awaiting_review=0
1571
- // ensures we only claim overrides the user has explicitly resolved.
1572
- // Without the awaiting_review filter, continueWithDefault=true artifacts
1573
- // (not yet responded to) would be prematurely claimed, causing the override
1574
- // to be lost when the user later resolves (#ADR-011 Phase 2 peer-review Bug 2).
1575
- const row = currentDb.prepare(
1576
- `SELECT id, escalation_artifact_path AS path
1577
- FROM tasks
1578
- WHERE milestone_id = :mid AND slice_id = :sid
1579
- AND escalation_artifact_path IS NOT NULL
1580
- AND escalation_override_applied_at IS NULL
1581
- AND escalation_pending = 0
1582
- AND escalation_awaiting_review = 0
1583
- ORDER BY sequence DESC, id DESC
1584
- LIMIT 1`,
1585
- ).get({ ":mid": milestoneId, ":sid": sliceId }) as
1586
- | { id: string; path: string | null }
1587
- | undefined;
1588
- if (!row || !row.path) return null;
1589
- return { taskId: row.id, artifactPath: row.path };
1590
- }
1591
667
 
1592
668
  /** Set the blocker_source provenance field (used when rejecting an escalation). */
1593
669
  export function setTaskBlockerSource(
1594
670
  milestoneId: string, sliceId: string, taskId: string, source: string,
1595
671
  ): void {
1596
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1597
- currentDb.prepare(
672
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
673
+ getDbOrNull()!.prepare(
1598
674
  `UPDATE tasks
1599
675
  SET blocker_discovered = 1,
1600
676
  blocker_source = :src
@@ -1602,17 +678,6 @@ export function setTaskBlockerSource(
1602
678
  ).run({ ":src": source, ":mid": milestoneId, ":sid": sliceId, ":tid": taskId });
1603
679
  }
1604
680
 
1605
- /** List tasks with active escalation artifacts across a milestone (for /gsd escalate list). */
1606
- export function listEscalationArtifacts(milestoneId: string, includeResolved: boolean = false): TaskRow[] {
1607
- if (!currentDb) return [];
1608
- const filter = includeResolved
1609
- ? "escalation_artifact_path IS NOT NULL"
1610
- : "(escalation_pending = 1 OR escalation_awaiting_review = 1) AND escalation_artifact_path IS NOT NULL";
1611
- const rows = currentDb.prepare(
1612
- `SELECT * FROM tasks WHERE milestone_id = :mid AND ${filter} ORDER BY slice_id, sequence, id`,
1613
- ).all({ ":mid": milestoneId });
1614
- return rows.map(rowToTask);
1615
- }
1616
681
 
1617
682
  export function insertVerificationEvidence(e: {
1618
683
  taskId: string;
@@ -1623,8 +688,8 @@ export function insertVerificationEvidence(e: {
1623
688
  verdict: string;
1624
689
  durationMs: number;
1625
690
  }): void {
1626
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1627
- currentDb.prepare(
691
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
692
+ getDbOrNull()!.prepare(
1628
693
  `INSERT OR IGNORE INTO verification_evidence (task_id, slice_id, milestone_id, command, exit_code, verdict, duration_ms, created_at)
1629
694
  VALUES (:task_id, :slice_id, :milestone_id, :command, :exit_code, :verdict, :duration_ms, :created_at)`,
1630
695
  ).run({
@@ -1639,66 +704,30 @@ export function insertVerificationEvidence(e: {
1639
704
  });
1640
705
  }
1641
706
 
1642
- export interface VerificationEvidenceRow {
1643
- id: number;
1644
- task_id: string;
1645
- slice_id: string;
1646
- milestone_id: string;
1647
- command: string;
1648
- exit_code: number;
1649
- verdict: string;
1650
- duration_ms: number;
1651
- created_at: string;
1652
- }
1653
707
 
1654
- export function getVerificationEvidence(milestoneId: string, sliceId: string, taskId: string): VerificationEvidenceRow[] {
1655
- if (!currentDb) return [];
1656
- const rows = currentDb.prepare(
1657
- "SELECT * FROM verification_evidence WHERE milestone_id = :mid AND slice_id = :sid AND task_id = :tid ORDER BY id",
1658
- ).all({ ":mid": milestoneId, ":sid": sliceId, ":tid": taskId });
1659
- return rows as unknown as VerificationEvidenceRow[];
1660
- }
1661
708
 
1662
- export function getAllMilestones(): MilestoneRow[] {
1663
- if (!currentDb) return [];
1664
- const rows = currentDb.prepare(
1665
- "SELECT * FROM milestones ORDER BY CASE WHEN sequence > 0 THEN 0 ELSE 1 END, sequence, id",
1666
- ).all();
1667
- return rows.map(rowToMilestone);
1668
- }
1669
709
 
1670
- export function getMilestone(id: string): MilestoneRow | null {
1671
- if (!currentDb) return null;
1672
- const row = currentDb.prepare("SELECT * FROM milestones WHERE id = :id").get({ ":id": id });
1673
- if (!row) return null;
1674
- return rowToMilestone(row);
1675
- }
1676
710
 
1677
711
  export function setMilestoneQueueOrder(order: string[]): void {
1678
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1679
- currentDb.exec("BEGIN IMMEDIATE");
1680
- try {
1681
- currentDb.prepare("UPDATE milestones SET sequence = 0").run();
1682
- const stmt = currentDb.prepare("UPDATE milestones SET sequence = :sequence WHERE id = :id");
712
+ const db = getDb();
713
+ immediateTransaction(() => {
714
+ db.prepare("UPDATE milestones SET sequence = 0").run();
715
+ const stmt = db.prepare("UPDATE milestones SET sequence = :sequence WHERE id = :id");
1683
716
  order.forEach((id, index) => {
1684
717
  stmt.run({ ":id": id, ":sequence": index + 1 });
1685
718
  });
1686
- currentDb.exec("COMMIT");
1687
- } catch (err) {
1688
- currentDb.exec("ROLLBACK");
1689
- throw err;
1690
- }
719
+ });
1691
720
  }
1692
721
 
1693
722
  function getMilestoneStatusForUpdate(milestoneId: string): string | null {
1694
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1695
- const row = currentDb.prepare("SELECT status FROM milestones WHERE id = :id").get({ ":id": milestoneId });
723
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
724
+ const row = getDbOrNull()!.prepare("SELECT status FROM milestones WHERE id = :id").get({ ":id": milestoneId });
1696
725
  return typeof row?.["status"] === "string" ? row["status"] : null;
1697
726
  }
1698
727
 
1699
728
  function writeMilestoneStatus(milestoneId: string, status: string, completedAt?: string | null): void {
1700
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1701
- currentDb.prepare(
729
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
730
+ getDbOrNull()!.prepare(
1702
731
  `UPDATE milestones SET status = :status, completed_at = :completed_at WHERE id = :id`,
1703
732
  ).run({ ":status": status, ":completed_at": completedAt ?? null, ":id": milestoneId });
1704
733
  }
@@ -1711,21 +740,14 @@ function writeMilestoneStatus(milestoneId: string, status: string, completedAt?:
1711
740
  * must use reopenMilestoneStatus(), which is reserved for gsd_milestone_reopen.
1712
741
  */
1713
742
  export function updateMilestoneStatus(milestoneId: string, status: string, completedAt?: string | null): void {
1714
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1715
- const currentStatus = getMilestoneStatusForUpdate(milestoneId);
1716
- if (currentStatus && isClosedStatus(currentStatus) && !isClosedStatus(status)) {
1717
- throw new Error(
1718
- `Cannot update closed milestone ${milestoneId} from ${currentStatus} to ${status}; use gsd_milestone_reopen for an explicit reopen.`,
1719
- );
1720
- }
1721
- writeMilestoneStatus(milestoneId, status, completedAt);
743
+ applyStatusTransition({ entity: "milestone", milestoneId, status, completedAt });
1722
744
  }
1723
745
 
1724
746
  /**
1725
747
  * Explicit closed -> active transition for gsd_milestone_reopen only.
1726
748
  */
1727
749
  export function reopenMilestoneStatus(milestoneId: string): void {
1728
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
750
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1729
751
  const currentStatus = getMilestoneStatusForUpdate(milestoneId);
1730
752
  if (!currentStatus) {
1731
753
  throw new Error(`Cannot reopen missing milestone ${milestoneId}`);
@@ -1736,615 +758,35 @@ export function reopenMilestoneStatus(milestoneId: string): void {
1736
758
  writeMilestoneStatus(milestoneId, "active", null);
1737
759
  }
1738
760
 
1739
- export function getActiveMilestoneFromDb(): MilestoneRow | null {
1740
- if (!currentDb) return null;
1741
- const row = currentDb.prepare(
1742
- "SELECT * FROM milestones WHERE status NOT IN ('complete', 'done', 'skipped', 'closed', 'parked') ORDER BY id LIMIT 1",
1743
- ).get();
1744
- if (!row) return null;
1745
- return rowToMilestone(row);
1746
- }
1747
761
 
1748
- export function getActiveSliceFromDb(milestoneId: string): SliceRow | null {
1749
- if (!currentDb) return null;
1750
-
1751
- // Single query: find the first non-complete slice whose dependencies are all satisfied.
1752
- // Uses json_each() to expand the JSON depends array and checks each dep is complete.
1753
- const row = currentDb.prepare(
1754
- `SELECT s.* FROM slices s
1755
- WHERE s.milestone_id = :mid
1756
- AND s.status NOT IN ('complete', 'done', 'skipped')
1757
- AND NOT EXISTS (
1758
- SELECT 1 FROM json_each(s.depends) AS dep
1759
- WHERE dep.value NOT IN (
1760
- SELECT id FROM slices WHERE milestone_id = :mid AND status IN ('complete', 'done', 'skipped')
1761
- )
1762
- )
1763
- ORDER BY s.sequence, s.id
1764
- LIMIT 1`,
1765
- ).get({ ":mid": milestoneId });
1766
- if (!row) return null;
1767
- return rowToSlice(row);
1768
- }
1769
762
 
1770
- export function getActiveTaskFromDb(milestoneId: string, sliceId: string): TaskRow | null {
1771
- if (!currentDb) return null;
1772
- const row = currentDb.prepare(
1773
- "SELECT * FROM tasks WHERE milestone_id = :mid AND slice_id = :sid AND status NOT IN ('complete', 'done') ORDER BY sequence, id LIMIT 1",
1774
- ).get({ ":mid": milestoneId, ":sid": sliceId });
1775
- if (!row) return null;
1776
- return rowToTask(row);
1777
- }
1778
763
 
1779
- export function getMilestoneSlices(milestoneId: string): SliceRow[] {
1780
- if (!currentDb) return [];
1781
- const rows = currentDb.prepare("SELECT * FROM slices WHERE milestone_id = :mid ORDER BY sequence, id").all({ ":mid": milestoneId });
1782
- return rows.map(rowToSlice);
1783
- }
1784
764
 
1785
- export function getArtifact(path: string): ArtifactRow | null {
1786
- if (!currentDb) return null;
1787
- const row = currentDb.prepare("SELECT * FROM artifacts WHERE path = :path").get({ ":path": path });
1788
- if (!row) return null;
1789
- return rowToArtifact(row);
1790
- }
1791
765
 
1792
766
  // ─── Lightweight Query Variants (hot-path optimized) ─────────────────────
1793
767
 
1794
- /** Fast milestone status check — avoids deserializing JSON planning fields. */
1795
- export function getActiveMilestoneIdFromDb(): IdStatusSummary | null {
1796
- if (!currentDb) return null;
1797
- const row = currentDb.prepare(
1798
- "SELECT id, status FROM milestones WHERE status NOT IN ('complete', 'done', 'skipped', 'closed', 'parked') ORDER BY id LIMIT 1",
1799
- ).get();
1800
- if (!row) return null;
1801
- return rowToIdStatusSummary(row);
1802
- }
1803
768
 
1804
- /** Fast slice status check — avoids deserializing JSON depends/planning fields. */
1805
- export function getSliceStatusSummary(milestoneId: string): IdStatusSummary[] {
1806
- if (!currentDb) return [];
1807
- return currentDb.prepare(
1808
- "SELECT id, status FROM slices WHERE milestone_id = :mid ORDER BY sequence, id",
1809
- ).all({ ":mid": milestoneId }).map(rowToIdStatusSummary);
1810
- }
1811
769
 
1812
- /** Fast task status check — avoids deserializing JSON arrays and large text fields. */
1813
- export function getActiveTaskIdFromDb(milestoneId: string, sliceId: string): ActiveTaskSummary | null {
1814
- if (!currentDb) return null;
1815
- const row = currentDb.prepare(
1816
- "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",
1817
- ).get({ ":mid": milestoneId, ":sid": sliceId });
1818
- if (!row) return null;
1819
- return rowToActiveTaskSummary(row);
1820
- }
1821
770
 
1822
- /** Count tasks by status for a slice — useful for progress reporting without full row load. */
1823
- export function getSliceTaskCounts(milestoneId: string, sliceId: string): TaskStatusCounts {
1824
- if (!currentDb) return emptyTaskStatusCounts();
1825
- const row = currentDb.prepare(
1826
- `SELECT
1827
- COUNT(*) as total,
1828
- SUM(CASE WHEN status IN ('complete', 'done') THEN 1 ELSE 0 END) as done,
1829
- SUM(CASE WHEN status NOT IN ('complete', 'done') THEN 1 ELSE 0 END) as pending
1830
- FROM tasks WHERE milestone_id = :mid AND slice_id = :sid`,
1831
- ).get({ ":mid": milestoneId, ":sid": sliceId });
1832
- return rowToTaskStatusCounts(row);
1833
- }
1834
771
 
1835
772
  // ─── Slice Dependencies (junction table) ─────────────────────────────────
1836
773
 
1837
774
  /** Sync the slice_dependencies junction table from a slice's JSON depends array. */
1838
775
  export function syncSliceDependencies(milestoneId: string, sliceId: string, depends: string[]): void {
1839
- if (!currentDb) return;
1840
- currentDb.prepare(
776
+ if (!getDbOrNull()!) return;
777
+ getDbOrNull()!.prepare(
1841
778
  "DELETE FROM slice_dependencies WHERE milestone_id = :mid AND slice_id = :sid",
1842
779
  ).run({ ":mid": milestoneId, ":sid": sliceId });
1843
780
  for (const dep of depends) {
1844
- currentDb.prepare(
781
+ getDbOrNull()!.prepare(
1845
782
  "INSERT OR IGNORE INTO slice_dependencies (milestone_id, slice_id, depends_on_slice_id) VALUES (:mid, :sid, :dep)",
1846
783
  ).run({ ":mid": milestoneId, ":sid": sliceId, ":dep": dep });
1847
784
  }
1848
785
  }
1849
786
 
1850
- /** Get all slices that depend on a given slice. */
1851
- export function getDependentSlices(milestoneId: string, sliceId: string): string[] {
1852
- if (!currentDb) return [];
1853
- const rows = currentDb.prepare(
1854
- "SELECT slice_id FROM slice_dependencies WHERE milestone_id = :mid AND depends_on_slice_id = :sid",
1855
- ).all({ ":mid": milestoneId, ":sid": sliceId });
1856
- return rowsToStringColumn(rows, "slice_id");
1857
- }
1858
787
 
1859
788
  // ─── Worktree DB Helpers ──────────────────────────────────────────────────
1860
789
 
1861
- export function copyWorktreeDb(srcDbPath: string, destDbPath: string): boolean {
1862
- try {
1863
- if (!existsSync(srcDbPath)) return false;
1864
- const destDir = dirname(destDbPath);
1865
- mkdirSync(destDir, { recursive: true });
1866
- copyFileSync(srcDbPath, destDbPath);
1867
- return true;
1868
- } catch (err) {
1869
- logError("db", "failed to copy DB to worktree", { error: (err as Error).message });
1870
- return false;
1871
- }
1872
- }
1873
-
1874
- export interface ReconcileResult {
1875
- decisions: number;
1876
- requirements: number;
1877
- artifacts: number;
1878
- milestones: number;
1879
- slices: number;
1880
- tasks: number;
1881
- memories: number;
1882
- replan_history: number;
1883
- assessments: number;
1884
- quality_gates: number;
1885
- slice_dependencies: number;
1886
- verification_evidence: number;
1887
- gate_runs: number;
1888
- milestone_commit_attributions: number;
1889
- conflicts: string[];
1890
- }
1891
-
1892
- export function reconcileWorktreeDb(
1893
- mainDbPath: string,
1894
- worktreeDbPath: string,
1895
- ): ReconcileResult {
1896
- const zero: ReconcileResult = {
1897
- decisions: 0,
1898
- requirements: 0,
1899
- artifacts: 0,
1900
- milestones: 0,
1901
- slices: 0,
1902
- tasks: 0,
1903
- memories: 0,
1904
- replan_history: 0,
1905
- assessments: 0,
1906
- quality_gates: 0,
1907
- slice_dependencies: 0,
1908
- verification_evidence: 0,
1909
- gate_runs: 0,
1910
- milestone_commit_attributions: 0,
1911
- conflicts: [],
1912
- };
1913
- if (!existsSync(worktreeDbPath)) return zero;
1914
- // Guard: bail when both paths resolve to the same physical file.
1915
- // ATTACHing a WAL-mode DB to itself corrupts the WAL (#2823).
1916
- try {
1917
- if (realpathSync(mainDbPath) === realpathSync(worktreeDbPath)) return zero;
1918
- } catch (e) { logWarning("db", `realpathSync failed: ${(e as Error).message}`); }
1919
- // Sanitize path: reject any characters that could break ATTACH syntax.
1920
- // ATTACH DATABASE doesn't support parameterized paths in all providers,
1921
- // so we use strict allowlist validation instead.
1922
- if (/['";\x00]/.test(worktreeDbPath)) {
1923
- logError("db", "worktree DB reconciliation failed: path contains unsafe characters");
1924
- return zero;
1925
- }
1926
- if (!currentDb) {
1927
- const opened = openDatabase(mainDbPath);
1928
- if (!opened) {
1929
- logError("db", "worktree DB reconciliation failed: cannot open main DB");
1930
- return zero;
1931
- }
1932
- }
1933
- const adapter = currentDb!;
1934
- const conflicts: string[] = [];
1935
- try {
1936
- adapter.exec(`ATTACH DATABASE '${worktreeDbPath}' AS wt`);
1937
- try {
1938
- function countChanges(result: unknown): number {
1939
- return typeof result === "object" && result !== null ? ((result as { changes?: number }).changes ?? 0) : 0;
1940
- }
1941
-
1942
- function wtTableInfo(tableName: string): Array<Record<string, unknown>> {
1943
- return adapter.prepare(`PRAGMA wt.table_info('${tableName}')`).all() as Array<Record<string, unknown>>;
1944
- }
1945
-
1946
- const wtInfo = wtTableInfo("decisions");
1947
- const hasWtDecisions = wtInfo.length > 0;
1948
- const hasMadeBy = wtInfo.some((col) => col["name"] === "made_by");
1949
- // ADR-011: worktree may predate schema v16/v17. For missing columns we
1950
- // fall through to the main DB's existing value (not a literal default)
1951
- // so reconcile never silently clears state the main tree has recorded.
1952
- const hasDecisionSource = wtInfo.some((col) => col["name"] === "source");
1953
- const wtRequirementInfo = wtTableInfo("requirements");
1954
- const hasWtRequirements = wtRequirementInfo.length > 0;
1955
- const wtMilestoneInfo = wtTableInfo("milestones");
1956
- const hasWtMilestones = wtMilestoneInfo.length > 0;
1957
- const hasMilestoneSequence = wtMilestoneInfo.some((col) => col["name"] === "sequence");
1958
- const wtSliceInfo = wtTableInfo("slices");
1959
- const hasWtSlices = wtSliceInfo.length > 0;
1960
- const hasIsSketch = wtSliceInfo.some((col) => col["name"] === "is_sketch");
1961
- const hasSketchScope = wtSliceInfo.some((col) => col["name"] === "sketch_scope");
1962
- const hasSliceTargetRepositories = wtSliceInfo.some((col) => col["name"] === "target_repositories");
1963
- const wtTaskInfo = wtTableInfo("tasks");
1964
- const hasWtTasks = wtTaskInfo.length > 0;
1965
- const hasTaskTargetRepositories = wtTaskInfo.some((col) => col["name"] === "target_repositories");
1966
- const hasBlockerSource = wtTaskInfo.some((col) => col["name"] === "blocker_source");
1967
- const hasEscalationPending = wtTaskInfo.some((col) => col["name"] === "escalation_pending");
1968
- const hasEscalationAwaiting = wtTaskInfo.some((col) => col["name"] === "escalation_awaiting_review");
1969
- const hasEscalationArtifact = wtTaskInfo.some((col) => col["name"] === "escalation_artifact_path");
1970
- const hasEscalationOverride = wtTaskInfo.some((col) => col["name"] === "escalation_override_applied_at");
1971
- const wtArtifactInfo = wtTableInfo("artifacts");
1972
- const hasWtArtifacts = wtArtifactInfo.length > 0;
1973
- const wtMemoryInfo = wtTableInfo("memories");
1974
- const hasWtMemories = wtMemoryInfo.length > 0;
1975
- const hasMemoryScope = wtMemoryInfo.some((col) => col["name"] === "scope");
1976
- const hasMemoryTags = wtMemoryInfo.some((col) => col["name"] === "tags");
1977
- const hasMemoryStructuredFields = wtMemoryInfo.some((col) => col["name"] === "structured_fields");
1978
- const hasMemoryLastHitAt = wtMemoryInfo.some((col) => col["name"] === "last_hit_at");
1979
- const hasWtReplanHistory = wtTableInfo("replan_history").length > 0;
1980
- const hasWtAssessments = wtTableInfo("assessments").length > 0;
1981
- const hasWtQualityGates = wtTableInfo("quality_gates").length > 0;
1982
- const hasWtSliceDependencies = wtTableInfo("slice_dependencies").length > 0;
1983
- const hasWtVerificationEvidence = wtTableInfo("verification_evidence").length > 0;
1984
- const hasWtGateRuns = wtTableInfo("gate_runs").length > 0;
1985
- const hasWtMilestoneCommitAttributions = wtTableInfo("milestone_commit_attributions").length > 0;
1986
-
1987
- if (hasWtDecisions) {
1988
- const decConf = adapter.prepare(
1989
- `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 ${
1990
- hasMadeBy ? "m.made_by != w.made_by" : "'agent' != 'agent'"
1991
- } OR m.superseded_by IS NOT w.superseded_by`,
1992
- ).all();
1993
- for (const row of decConf) conflicts.push(`decision ${(row as Record<string, unknown>)["id"]}: modified in both`);
1994
- }
1995
-
1996
- if (hasWtRequirements) {
1997
- const reqConf = adapter.prepare(
1998
- `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`,
1999
- ).all();
2000
- for (const row of reqConf) conflicts.push(`requirement ${(row as Record<string, unknown>)["id"]}: modified in both`);
2001
- }
2002
-
2003
- const merged: Omit<ReconcileResult, "conflicts"> = {
2004
- decisions: 0,
2005
- requirements: 0,
2006
- artifacts: 0,
2007
- milestones: 0,
2008
- slices: 0,
2009
- tasks: 0,
2010
- memories: 0,
2011
- replan_history: 0,
2012
- assessments: 0,
2013
- quality_gates: 0,
2014
- slice_dependencies: 0,
2015
- verification_evidence: 0,
2016
- gate_runs: 0,
2017
- milestone_commit_attributions: 0,
2018
- };
2019
- const sliceTargetRepositoriesSql = hasSliceTargetRepositories
2020
- ? `CASE
2021
- WHEN w.target_repositories = '[]' AND COALESCE(m.target_repositories, '[]') <> '[]'
2022
- THEN m.target_repositories
2023
- ELSE COALESCE(w.target_repositories, m.target_repositories, '[]')
2024
- END`
2025
- : "COALESCE(m.target_repositories, '[]')";
2026
- const taskTargetRepositoriesSql = hasTaskTargetRepositories
2027
- ? `CASE
2028
- WHEN w.target_repositories = '[]' AND COALESCE(m.target_repositories, '[]') <> '[]'
2029
- THEN m.target_repositories
2030
- ELSE COALESCE(w.target_repositories, m.target_repositories, '[]')
2031
- END`
2032
- : "COALESCE(m.target_repositories, '[]')";
2033
-
2034
- adapter.exec("BEGIN");
2035
- try {
2036
- // Join the target decisions so we can prefer an existing main.source
2037
- // when the worktree predates v16 — otherwise a write-through reconcile
2038
- // would clobber 'escalation'-sourced decisions with the literal default.
2039
- if (hasWtDecisions) {
2040
- merged.decisions = countChanges(adapter.prepare(`
2041
- INSERT INTO decisions (
2042
- id, when_context, scope, decision, choice, rationale, revisable, made_by, source, superseded_by
2043
- )
2044
- SELECT w.id, w.when_context, w.scope, w.decision, w.choice, w.rationale, w.revisable, ${
2045
- hasMadeBy ? "w.made_by" : "COALESCE(m.made_by, 'agent')"
2046
- }, ${
2047
- hasDecisionSource ? "w.source" : "COALESCE(m.source, 'discussion')"
2048
- }, w.superseded_by
2049
- FROM wt.decisions w
2050
- LEFT JOIN decisions m ON m.id = w.id
2051
- WHERE true
2052
- ON CONFLICT(id) DO UPDATE SET
2053
- when_context = excluded.when_context,
2054
- scope = excluded.scope,
2055
- decision = excluded.decision,
2056
- choice = excluded.choice,
2057
- rationale = excluded.rationale,
2058
- revisable = excluded.revisable,
2059
- made_by = excluded.made_by,
2060
- source = excluded.source,
2061
- superseded_by = excluded.superseded_by
2062
- `).run());
2063
- }
2064
-
2065
- if (hasWtRequirements) {
2066
- merged.requirements = countChanges(adapter.prepare(`
2067
- INSERT OR REPLACE INTO requirements (
2068
- id, class, status, description, why, source, primary_owner,
2069
- supporting_slices, validation, notes, full_content, superseded_by
2070
- )
2071
- SELECT id, class, status, description, why, source, primary_owner,
2072
- supporting_slices, validation, notes, full_content, superseded_by
2073
- FROM wt.requirements
2074
- `).run());
2075
- }
2076
-
2077
- // Always recompute artifact hashes from the content being merged. Older
2078
- // worktree DBs may not have content_hash at all, and migrated old DBs can
2079
- // carry stale default/null hashes after their content changed.
2080
- if (hasWtArtifacts) {
2081
- const artifactRows = adapter.prepare(`
2082
- SELECT path, artifact_type, milestone_id, slice_id, task_id, full_content, imported_at
2083
- FROM wt.artifacts
2084
- `).all() as Array<Record<string, unknown>>;
2085
- const artifactStmt = adapter.prepare(`
2086
- INSERT OR REPLACE INTO artifacts (
2087
- path, artifact_type, milestone_id, slice_id, task_id, full_content, imported_at, content_hash
2088
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
2089
- `);
2090
- for (const row of artifactRows) {
2091
- const fullContent = String(row["full_content"] ?? "");
2092
- merged.artifacts += countChanges(artifactStmt.run(
2093
- row["path"],
2094
- row["artifact_type"],
2095
- row["milestone_id"] ?? null,
2096
- row["slice_id"] ?? null,
2097
- row["task_id"] ?? null,
2098
- fullContent,
2099
- row["imported_at"],
2100
- createHash("sha256").update(fullContent).digest("hex"),
2101
- ));
2102
- }
2103
- }
2104
-
2105
- // Merge milestones — worktree may have updated status/planning fields.
2106
- // Never downgrade status: complete > active > pre-planning (#4372).
2107
- // A stale worktree may carry an older 'active' status for a milestone
2108
- // that the main DB has already marked 'complete'; preserve the higher status.
2109
- if (hasWtMilestones) {
2110
- merged.milestones = countChanges(adapter.prepare(`
2111
- INSERT OR REPLACE INTO milestones (
2112
- id, title, status, depends_on, created_at, completed_at,
2113
- vision, success_criteria, key_risks, proof_strategy,
2114
- verification_contract, verification_integration, verification_operational, verification_uat,
2115
- definition_of_done, requirement_coverage, boundary_map_markdown, sequence
2116
- )
2117
- SELECT w.id, w.title,
2118
- CASE
2119
- WHEN m.status IN (${TERMINAL_STATUS_SQL}) AND w.status NOT IN (${TERMINAL_STATUS_SQL})
2120
- THEN m.status ELSE w.status
2121
- END,
2122
- w.depends_on,
2123
- CASE
2124
- WHEN m.status IN (${TERMINAL_STATUS_SQL}) AND w.status NOT IN (${TERMINAL_STATUS_SQL})
2125
- THEN m.created_at ELSE w.created_at
2126
- END,
2127
- CASE
2128
- WHEN m.status IN (${TERMINAL_STATUS_SQL}) AND w.status NOT IN (${TERMINAL_STATUS_SQL})
2129
- THEN m.completed_at ELSE w.completed_at
2130
- END,
2131
- w.vision, w.success_criteria, w.key_risks, w.proof_strategy,
2132
- w.verification_contract, w.verification_integration, w.verification_operational, w.verification_uat,
2133
- w.definition_of_done, w.requirement_coverage, w.boundary_map_markdown,
2134
- ${hasMilestoneSequence ? "COALESCE(w.sequence, 0)" : "COALESCE(m.sequence, 0)"}
2135
- FROM wt.milestones w
2136
- LEFT JOIN milestones m ON m.id = w.id
2137
- `).run());
2138
- }
2139
-
2140
- // Merge slices — preserve worktree progress but never downgrade completed status (#2558).
2141
- // ADR-011 Phase 1: carry is_sketch + sketch_scope so reconcile doesn't
2142
- // silently clear sketch metadata. When the worktree predates v16,
2143
- // fall back to the main DB's existing value rather than a literal 0/''.
2144
- if (hasWtSlices) {
2145
- merged.slices = countChanges(adapter.prepare(`
2146
- INSERT OR REPLACE INTO slices (
2147
- milestone_id, id, title, status, risk, depends, demo, created_at, completed_at,
2148
- full_summary_md, full_uat_md, goal, success_criteria, proof_level,
2149
- integration_closure, observability_impact, target_repositories, sequence, replan_triggered_at,
2150
- is_sketch, sketch_scope
2151
- )
2152
- SELECT w.milestone_id, w.id, w.title,
2153
- CASE
2154
- WHEN m.status IN (${TERMINAL_STATUS_SQL}) AND w.status NOT IN (${TERMINAL_STATUS_SQL})
2155
- THEN m.status ELSE w.status
2156
- END,
2157
- w.risk, w.depends, w.demo, w.created_at,
2158
- CASE
2159
- WHEN m.status IN (${TERMINAL_STATUS_SQL}) AND w.status NOT IN (${TERMINAL_STATUS_SQL})
2160
- THEN m.completed_at ELSE w.completed_at
2161
- END,
2162
- w.full_summary_md, w.full_uat_md, w.goal, w.success_criteria, w.proof_level,
2163
- w.integration_closure, w.observability_impact,
2164
- ${sliceTargetRepositoriesSql},
2165
- w.sequence, w.replan_triggered_at,
2166
- ${hasIsSketch ? "w.is_sketch" : "COALESCE(m.is_sketch, 0)"},
2167
- ${hasSketchScope ? "w.sketch_scope" : "COALESCE(m.sketch_scope, '')"}
2168
- FROM wt.slices w
2169
- LEFT JOIN slices m ON m.milestone_id = w.milestone_id AND m.id = w.id
2170
- `).run());
2171
- }
2172
-
2173
- // Merge tasks — preserve execution results, never downgrade completed status (#2558).
2174
- // ADR-011 P2: carry blocker_source + escalation_* columns so worktree reconcile
2175
- // doesn't silently clear escalation state back to defaults.
2176
- if (hasWtTasks) {
2177
- merged.tasks = countChanges(adapter.prepare(`
2178
- INSERT OR REPLACE INTO tasks (
2179
- milestone_id, slice_id, id, title, status, one_liner, narrative,
2180
- verification_result, duration, completed_at, blocker_discovered,
2181
- deviations, known_issues, key_files, key_decisions, full_summary_md,
2182
- description, estimate, files, verify, inputs, expected_output,
2183
- observability_impact, full_plan_md, target_repositories, sequence,
2184
- blocker_source, escalation_pending, escalation_awaiting_review,
2185
- escalation_artifact_path, escalation_override_applied_at
2186
- )
2187
- SELECT w.milestone_id, w.slice_id, w.id, w.title,
2188
- CASE
2189
- WHEN m.status IN (${TERMINAL_STATUS_SQL}) AND w.status NOT IN (${TERMINAL_STATUS_SQL})
2190
- THEN m.status ELSE w.status
2191
- END,
2192
- w.one_liner, w.narrative,
2193
- w.verification_result, w.duration,
2194
- CASE
2195
- WHEN m.status IN (${TERMINAL_STATUS_SQL}) AND w.status NOT IN (${TERMINAL_STATUS_SQL})
2196
- THEN m.completed_at ELSE w.completed_at
2197
- END,
2198
- w.blocker_discovered,
2199
- w.deviations, w.known_issues, w.key_files, w.key_decisions, w.full_summary_md,
2200
- w.description, w.estimate, w.files, w.verify, w.inputs, w.expected_output,
2201
- w.observability_impact, w.full_plan_md,
2202
- ${taskTargetRepositoriesSql},
2203
- w.sequence,
2204
- ${hasBlockerSource ? "w.blocker_source" : "COALESCE(m.blocker_source, '')"},
2205
- ${hasEscalationPending ? "w.escalation_pending" : "COALESCE(m.escalation_pending, 0)"},
2206
- ${hasEscalationAwaiting ? "w.escalation_awaiting_review" : "COALESCE(m.escalation_awaiting_review, 0)"},
2207
- ${hasEscalationArtifact ? "w.escalation_artifact_path" : "m.escalation_artifact_path"},
2208
- ${hasEscalationOverride ? "w.escalation_override_applied_at" : "m.escalation_override_applied_at"}
2209
- FROM wt.tasks w
2210
- LEFT JOIN tasks m ON m.milestone_id = w.milestone_id AND m.slice_id = w.slice_id AND m.id = w.id
2211
- `).run());
2212
- }
2213
-
2214
- // Merge memories — keep worktree-learned insights.
2215
- // V18 (scope, tags), V21 (structured_fields), V28 (last_hit_at): for each
2216
- // column the wt may not yet have (older worktree DB), fall back to the
2217
- // main DB's existing value via LEFT JOIN so reconcile never silently
2218
- // resets these fields to defaults on rows that already had them.
2219
- if (hasWtMemories) {
2220
- merged.memories = countChanges(adapter.prepare(`
2221
- INSERT OR REPLACE INTO memories (
2222
- seq, id, category, content, confidence, source_unit_type, source_unit_id,
2223
- created_at, updated_at, superseded_by, hit_count,
2224
- scope, tags, structured_fields, last_hit_at
2225
- )
2226
- SELECT w.seq, w.id, w.category, w.content, w.confidence, w.source_unit_type, w.source_unit_id,
2227
- w.created_at, w.updated_at, w.superseded_by, w.hit_count,
2228
- ${hasMemoryScope ? "w.scope" : "COALESCE(m.scope, 'project')"},
2229
- ${hasMemoryTags ? "w.tags" : "COALESCE(m.tags, '[]')"},
2230
- ${hasMemoryStructuredFields ? "w.structured_fields" : "m.structured_fields"},
2231
- ${hasMemoryLastHitAt ? "w.last_hit_at" : "m.last_hit_at"}
2232
- FROM wt.memories w
2233
- LEFT JOIN memories m ON m.id = w.id
2234
- `).run());
2235
- }
2236
-
2237
- if (hasWtReplanHistory) {
2238
- merged.replan_history = countChanges(adapter.prepare(`
2239
- INSERT INTO replan_history (
2240
- milestone_id, slice_id, task_id, summary, previous_artifact_path, replacement_artifact_path, created_at
2241
- )
2242
- SELECT w.milestone_id, w.slice_id, w.task_id, w.summary, w.previous_artifact_path, w.replacement_artifact_path, w.created_at
2243
- FROM wt.replan_history w
2244
- WHERE EXISTS (SELECT 1 FROM milestones m WHERE m.id = w.milestone_id)
2245
- AND NOT EXISTS (
2246
- SELECT 1 FROM replan_history m
2247
- WHERE m.milestone_id = w.milestone_id
2248
- AND m.slice_id IS w.slice_id
2249
- AND m.task_id IS w.task_id
2250
- AND m.summary = w.summary
2251
- AND m.previous_artifact_path IS w.previous_artifact_path
2252
- AND m.replacement_artifact_path IS w.replacement_artifact_path
2253
- )
2254
- `).run());
2255
- }
2256
-
2257
- if (hasWtAssessments) {
2258
- merged.assessments = countChanges(adapter.prepare(`
2259
- INSERT OR REPLACE INTO assessments (
2260
- path, milestone_id, slice_id, task_id, status, scope, full_content, created_at
2261
- )
2262
- SELECT w.path, w.milestone_id, w.slice_id, w.task_id, w.status, w.scope, w.full_content, w.created_at
2263
- FROM wt.assessments w
2264
- WHERE EXISTS (SELECT 1 FROM milestones m WHERE m.id = w.milestone_id)
2265
- `).run());
2266
- }
2267
-
2268
- if (hasWtQualityGates) {
2269
- merged.quality_gates = countChanges(adapter.prepare(`
2270
- INSERT OR REPLACE INTO quality_gates (
2271
- milestone_id, slice_id, gate_id, scope, task_id, status, verdict, rationale, findings, evaluated_at
2272
- )
2273
- 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
2274
- FROM wt.quality_gates w
2275
- WHERE EXISTS (SELECT 1 FROM slices s WHERE s.milestone_id = w.milestone_id AND s.id = w.slice_id)
2276
- `).run());
2277
- }
2278
-
2279
- if (hasWtSliceDependencies) {
2280
- merged.slice_dependencies = countChanges(adapter.prepare(`
2281
- INSERT OR IGNORE INTO slice_dependencies (milestone_id, slice_id, depends_on_slice_id)
2282
- SELECT w.milestone_id, w.slice_id, w.depends_on_slice_id
2283
- FROM wt.slice_dependencies w
2284
- WHERE EXISTS (SELECT 1 FROM slices s WHERE s.milestone_id = w.milestone_id AND s.id = w.slice_id)
2285
- AND EXISTS (SELECT 1 FROM slices d WHERE d.milestone_id = w.milestone_id AND d.id = w.depends_on_slice_id)
2286
- `).run());
2287
- }
2288
-
2289
- // Merge verification evidence — append-only, use INSERT OR IGNORE to avoid duplicates
2290
- if (hasWtVerificationEvidence) {
2291
- merged.verification_evidence = countChanges(adapter.prepare(`
2292
- INSERT OR IGNORE INTO verification_evidence (
2293
- task_id, slice_id, milestone_id, command, exit_code, verdict, duration_ms, created_at
2294
- )
2295
- SELECT task_id, slice_id, milestone_id, command, exit_code, verdict, duration_ms, created_at
2296
- FROM wt.verification_evidence
2297
- `).run());
2298
- }
2299
-
2300
- if (hasWtGateRuns) {
2301
- merged.gate_runs = countChanges(adapter.prepare(`
2302
- INSERT INTO gate_runs (
2303
- trace_id, turn_id, gate_id, gate_type, unit_type, unit_id, milestone_id, slice_id, task_id,
2304
- outcome, failure_class, rationale, findings, attempt, max_attempts, retryable, evaluated_at
2305
- )
2306
- 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,
2307
- w.outcome, w.failure_class, w.rationale, w.findings, w.attempt, w.max_attempts, w.retryable, w.evaluated_at
2308
- FROM wt.gate_runs w
2309
- WHERE NOT EXISTS (
2310
- SELECT 1 FROM gate_runs m
2311
- WHERE m.trace_id = w.trace_id
2312
- AND m.turn_id = w.turn_id
2313
- AND m.gate_id = w.gate_id
2314
- AND m.attempt = w.attempt
2315
- AND m.evaluated_at = w.evaluated_at
2316
- )
2317
- `).run());
2318
- }
2319
-
2320
- if (hasWtMilestoneCommitAttributions) {
2321
- merged.milestone_commit_attributions = countChanges(adapter.prepare(`
2322
- INSERT OR REPLACE INTO milestone_commit_attributions (
2323
- commit_sha, milestone_id, slice_id, task_id, source, confidence, files_json, created_at
2324
- )
2325
- SELECT w.commit_sha, w.milestone_id, w.slice_id, w.task_id, w.source, w.confidence, w.files_json, w.created_at
2326
- FROM wt.milestone_commit_attributions w
2327
- WHERE EXISTS (SELECT 1 FROM milestones m WHERE m.id = w.milestone_id)
2328
- `).run());
2329
- }
2330
-
2331
- adapter.exec("COMMIT");
2332
- } catch (txErr) {
2333
- try { adapter.exec("ROLLBACK"); } catch (e) { logWarning("db", `rollback failed: ${(e as Error).message}`); }
2334
- throw txErr;
2335
- }
2336
- return { ...merged, conflicts };
2337
- } finally {
2338
- try { adapter.exec("DETACH DATABASE wt"); } catch (e) { logWarning("db", `detach worktree DB failed: ${(e as Error).message}`); }
2339
- }
2340
- } catch (err) {
2341
- logError("db", "worktree DB reconciliation failed", { error: (err as Error).message });
2342
- return { ...zero, conflicts };
2343
- }
2344
- }
2345
-
2346
- // ─── Replan & Assessment Helpers ──────────────────────────────────────────
2347
-
2348
790
  export function insertReplanHistory(entry: {
2349
791
  milestoneId: string;
2350
792
  sliceId?: string | null;
@@ -2353,10 +795,10 @@ export function insertReplanHistory(entry: {
2353
795
  previousArtifactPath?: string | null;
2354
796
  replacementArtifactPath?: string | null;
2355
797
  }): void {
2356
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
798
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2357
799
  // INSERT OR REPLACE: idempotent on (milestone_id, slice_id, task_id) via schema v11 unique index.
2358
800
  // Retrying the same replan silently updates summary instead of accumulating duplicate rows.
2359
- currentDb.prepare(
801
+ getDbOrNull()!.prepare(
2360
802
  `INSERT OR REPLACE INTO replan_history (milestone_id, slice_id, task_id, summary, previous_artifact_path, replacement_artifact_path, created_at)
2361
803
  VALUES (:milestone_id, :slice_id, :task_id, :summary, :previous_artifact_path, :replacement_artifact_path, :created_at)`,
2362
804
  ).run({
@@ -2379,11 +821,11 @@ export function insertAssessment(entry: {
2379
821
  scope: string;
2380
822
  fullContent: string;
2381
823
  }): void {
2382
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
824
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2383
825
  // Idempotent: PRIMARY KEY is `path`, which is deterministic given (milestone_id, scope) per
2384
826
  // the artifact-path resolver. Retrying the same reassess-roadmap silently overwrites the row
2385
827
  // instead of accumulating duplicates.
2386
- currentDb.prepare(
828
+ getDbOrNull()!.prepare(
2387
829
  `INSERT OR REPLACE INTO assessments (path, milestone_id, slice_id, task_id, status, scope, full_content, created_at)
2388
830
  VALUES (:path, :milestone_id, :slice_id, :task_id, :status, :scope, :full_content, :created_at)`,
2389
831
  ).run({
@@ -2399,94 +841,94 @@ export function insertAssessment(entry: {
2399
841
  }
2400
842
 
2401
843
  export function deleteAssessmentByScope(milestoneId: string, scope: string): void {
2402
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2403
- currentDb.prepare(
844
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
845
+ getDbOrNull()!.prepare(
2404
846
  `DELETE FROM assessments WHERE milestone_id = :mid AND scope = :scope`,
2405
847
  ).run({ ":mid": milestoneId, ":scope": scope });
2406
848
  }
2407
849
 
2408
850
  export function deleteVerificationEvidence(milestoneId: string, sliceId: string, taskId: string): void {
2409
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2410
- currentDb.prepare(
851
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
852
+ getDbOrNull()!.prepare(
2411
853
  `DELETE FROM verification_evidence WHERE milestone_id = :mid AND slice_id = :sid AND task_id = :tid`,
2412
854
  ).run({ ":mid": milestoneId, ":sid": sliceId, ":tid": taskId });
2413
855
  }
2414
856
 
2415
857
  export function deleteTask(milestoneId: string, sliceId: string, taskId: string): void {
2416
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
858
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2417
859
  transaction(() => {
2418
860
  // Must delete verification_evidence first (FK constraint)
2419
- currentDb!.prepare(
861
+ getDbOrNull()!!.prepare(
2420
862
  `DELETE FROM verification_evidence WHERE milestone_id = :mid AND slice_id = :sid AND task_id = :tid`,
2421
863
  ).run({ ":mid": milestoneId, ":sid": sliceId, ":tid": taskId });
2422
- currentDb!.prepare(
864
+ getDbOrNull()!!.prepare(
2423
865
  `DELETE FROM quality_gates WHERE milestone_id = :mid AND slice_id = :sid AND task_id = :tid`,
2424
866
  ).run({ ":mid": milestoneId, ":sid": sliceId, ":tid": taskId });
2425
- currentDb!.prepare(
867
+ getDbOrNull()!!.prepare(
2426
868
  `DELETE FROM tasks WHERE milestone_id = :mid AND slice_id = :sid AND id = :tid`,
2427
869
  ).run({ ":mid": milestoneId, ":sid": sliceId, ":tid": taskId });
2428
870
  });
2429
871
  }
2430
872
 
2431
873
  export function deleteSlice(milestoneId: string, sliceId: string): void {
2432
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
874
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2433
875
  transaction(() => {
2434
876
  // Cascade-style manual deletion: evidence → tasks → dependencies → slice
2435
- currentDb!.prepare(
877
+ getDbOrNull()!!.prepare(
2436
878
  `DELETE FROM verification_evidence WHERE milestone_id = :mid AND slice_id = :sid`,
2437
879
  ).run({ ":mid": milestoneId, ":sid": sliceId });
2438
- currentDb!.prepare(
880
+ getDbOrNull()!!.prepare(
2439
881
  `DELETE FROM tasks WHERE milestone_id = :mid AND slice_id = :sid`,
2440
882
  ).run({ ":mid": milestoneId, ":sid": sliceId });
2441
- currentDb!.prepare(
883
+ getDbOrNull()!!.prepare(
2442
884
  `DELETE FROM slice_dependencies WHERE milestone_id = :mid AND slice_id = :sid`,
2443
885
  ).run({ ":mid": milestoneId, ":sid": sliceId });
2444
- currentDb!.prepare(
886
+ getDbOrNull()!!.prepare(
2445
887
  `DELETE FROM slice_dependencies WHERE milestone_id = :mid AND depends_on_slice_id = :sid`,
2446
888
  ).run({ ":mid": milestoneId, ":sid": sliceId });
2447
- currentDb!.prepare(
889
+ getDbOrNull()!!.prepare(
2448
890
  `DELETE FROM slices WHERE milestone_id = :mid AND id = :sid`,
2449
891
  ).run({ ":mid": milestoneId, ":sid": sliceId });
2450
892
  });
2451
893
  }
2452
894
 
2453
895
  export function deleteMilestone(milestoneId: string): void {
2454
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
896
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2455
897
  transaction(() => {
2456
- currentDb!.prepare(
898
+ getDbOrNull()!!.prepare(
2457
899
  `DELETE FROM verification_evidence WHERE milestone_id = :mid`,
2458
900
  ).run({ ":mid": milestoneId });
2459
- currentDb!.prepare(
901
+ getDbOrNull()!!.prepare(
2460
902
  `DELETE FROM quality_gates WHERE milestone_id = :mid`,
2461
903
  ).run({ ":mid": milestoneId });
2462
- currentDb!.prepare(
904
+ getDbOrNull()!!.prepare(
2463
905
  `DELETE FROM gate_runs WHERE milestone_id = :mid`,
2464
906
  ).run({ ":mid": milestoneId });
2465
- currentDb!.prepare(
907
+ getDbOrNull()!!.prepare(
2466
908
  `DELETE FROM tasks WHERE milestone_id = :mid`,
2467
909
  ).run({ ":mid": milestoneId });
2468
- currentDb!.prepare(
910
+ getDbOrNull()!!.prepare(
2469
911
  `DELETE FROM slice_dependencies WHERE milestone_id = :mid`,
2470
912
  ).run({ ":mid": milestoneId });
2471
- currentDb!.prepare(
913
+ getDbOrNull()!!.prepare(
2472
914
  `DELETE FROM slices WHERE milestone_id = :mid`,
2473
915
  ).run({ ":mid": milestoneId });
2474
- currentDb!.prepare(
916
+ getDbOrNull()!!.prepare(
2475
917
  `DELETE FROM replan_history WHERE milestone_id = :mid`,
2476
918
  ).run({ ":mid": milestoneId });
2477
- currentDb!.prepare(
919
+ getDbOrNull()!!.prepare(
2478
920
  `DELETE FROM assessments WHERE milestone_id = :mid`,
2479
921
  ).run({ ":mid": milestoneId });
2480
- currentDb!.prepare(
922
+ getDbOrNull()!!.prepare(
2481
923
  `DELETE FROM artifacts WHERE milestone_id = :mid`,
2482
924
  ).run({ ":mid": milestoneId });
2483
- currentDb!.prepare(
925
+ getDbOrNull()!!.prepare(
2484
926
  `DELETE FROM milestone_commit_attributions WHERE milestone_id = :mid`,
2485
927
  ).run({ ":mid": milestoneId });
2486
- currentDb!.prepare(
928
+ getDbOrNull()!!.prepare(
2487
929
  `DELETE FROM milestone_leases WHERE milestone_id = :mid`,
2488
930
  ).run({ ":mid": milestoneId });
2489
- currentDb!.prepare(
931
+ getDbOrNull()!!.prepare(
2490
932
  `DELETE FROM milestones WHERE id = :mid`,
2491
933
  ).run({ ":mid": milestoneId });
2492
934
  });
@@ -2498,8 +940,15 @@ export function updateSliceFields(milestoneId: string, sliceId: string, fields:
2498
940
  depends?: string[];
2499
941
  demo?: string;
2500
942
  }): void {
2501
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2502
- currentDb.prepare(
943
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
944
+ const SLICE_ID_RE = /^[A-Za-z0-9][A-Za-z0-9-]*$/;
945
+ if (fields.depends !== undefined) {
946
+ const invalidDep = fields.depends.find(d => !SLICE_ID_RE.test(d));
947
+ if (invalidDep !== undefined) {
948
+ throw new GSDError(GSD_STALE_STATE, `updateSliceFields: depends element "${invalidDep}" is not a valid slice ID`);
949
+ }
950
+ }
951
+ getDbOrNull()!.prepare(
2503
952
  `UPDATE slices SET
2504
953
  title = COALESCE(:title, title),
2505
954
  risk = COALESCE(:risk, risk),
@@ -2516,39 +965,8 @@ export function updateSliceFields(milestoneId: string, sliceId: string, fields:
2516
965
  });
2517
966
  }
2518
967
 
2519
- export function getReplanHistory(milestoneId: string, sliceId?: string): Array<Record<string, unknown>> {
2520
- if (!currentDb) return [];
2521
- if (sliceId) {
2522
- return currentDb.prepare(
2523
- `SELECT * FROM replan_history WHERE milestone_id = :mid AND slice_id = :sid ORDER BY created_at DESC`,
2524
- ).all({ ":mid": milestoneId, ":sid": sliceId });
2525
- }
2526
- return currentDb.prepare(
2527
- `SELECT * FROM replan_history WHERE milestone_id = :mid ORDER BY created_at DESC`,
2528
- ).all({ ":mid": milestoneId });
2529
- }
2530
968
 
2531
- export function getAssessment(path: string): Record<string, unknown> | null {
2532
- if (!currentDb) return null;
2533
- const row = currentDb.prepare(
2534
- `SELECT * FROM assessments WHERE path = :path`,
2535
- ).get({ ":path": path });
2536
- return row ?? null;
2537
- }
2538
969
 
2539
- export function getLatestAssessmentByScope(
2540
- milestoneId: string,
2541
- scope: string,
2542
- ): Record<string, unknown> | null {
2543
- if (!currentDb) return null;
2544
- const row = currentDb.prepare(
2545
- `SELECT * FROM assessments
2546
- WHERE milestone_id = :mid AND scope = :scope
2547
- ORDER BY created_at DESC
2548
- LIMIT 1`,
2549
- ).get({ ":mid": milestoneId, ":scope": scope });
2550
- return row ?? null;
2551
- }
2552
970
 
2553
971
  // ─── Quality Gates ───────────────────────────────────────────────────────
2554
972
 
@@ -2560,8 +978,8 @@ export function insertGateRow(g: {
2560
978
  taskId?: string | null;
2561
979
  status?: GateStatus;
2562
980
  }): void {
2563
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2564
- currentDb.prepare(
981
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
982
+ getDbOrNull()!.prepare(
2565
983
  `INSERT OR IGNORE INTO quality_gates (milestone_id, slice_id, gate_id, scope, task_id, status)
2566
984
  VALUES (:mid, :sid, :gid, :scope, :tid, :status)`,
2567
985
  ).run({
@@ -2583,9 +1001,9 @@ export function saveGateResult(g: {
2583
1001
  rationale: string;
2584
1002
  findings: string;
2585
1003
  }): void {
2586
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1004
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2587
1005
  const evaluatedAt = new Date().toISOString();
2588
- const result = currentDb.prepare(
1006
+ const result = getDbOrNull()!.prepare(
2589
1007
  `UPDATE quality_gates
2590
1008
  SET status = 'complete', verdict = :verdict, rationale = :rationale,
2591
1009
  findings = :findings, evaluated_at = :evaluated_at
@@ -2634,29 +1052,11 @@ export function saveGateResult(g: {
2634
1052
  });
2635
1053
  }
2636
1054
 
2637
- export function getPendingGates(milestoneId: string, sliceId: string, scope?: GateScope): GateRow[] {
2638
- if (!currentDb) return [];
2639
- const sql = scope
2640
- ? `SELECT * FROM quality_gates WHERE milestone_id = :mid AND slice_id = :sid AND scope = :scope AND status = 'pending'`
2641
- : `SELECT * FROM quality_gates WHERE milestone_id = :mid AND slice_id = :sid AND status = 'pending'`;
2642
- const params: Record<string, unknown> = { ":mid": milestoneId, ":sid": sliceId };
2643
- if (scope) params[":scope"] = scope;
2644
- return currentDb.prepare(sql).all(params).map(rowToGate);
2645
- }
2646
1055
 
2647
- export function getGateResults(milestoneId: string, sliceId: string, scope?: GateScope): GateRow[] {
2648
- if (!currentDb) return [];
2649
- const sql = scope
2650
- ? `SELECT * FROM quality_gates WHERE milestone_id = :mid AND slice_id = :sid AND scope = :scope`
2651
- : `SELECT * FROM quality_gates WHERE milestone_id = :mid AND slice_id = :sid`;
2652
- const params: Record<string, unknown> = { ":mid": milestoneId, ":sid": sliceId };
2653
- if (scope) params[":scope"] = scope;
2654
- return currentDb.prepare(sql).all(params).map(rowToGate);
2655
- }
2656
1056
 
2657
1057
  export function markAllGatesOmitted(milestoneId: string, sliceId: string): void {
2658
- if (!currentDb) return;
2659
- currentDb.prepare(
1058
+ if (!getDbOrNull()!) return;
1059
+ getDbOrNull()!.prepare(
2660
1060
  `UPDATE quality_gates SET status = 'complete', verdict = 'omitted', evaluated_at = :now
2661
1061
  WHERE milestone_id = :mid AND slice_id = :sid AND status = 'pending'`,
2662
1062
  ).run({
@@ -2671,7 +1071,7 @@ export function markPendingGatesOmittedForTurn(
2671
1071
  sliceId: string,
2672
1072
  turn: OwnerTurn,
2673
1073
  ): void {
2674
- if (!currentDb) return;
1074
+ if (!getDbOrNull()!) return;
2675
1075
  const gateIds = [...getGateIdsForTurn(turn)];
2676
1076
  if (gateIds.length === 0) return;
2677
1077
  const placeholders = gateIds.map((_, i) => `:gid${i}`).join(",");
@@ -2683,71 +1083,15 @@ export function markPendingGatesOmittedForTurn(
2683
1083
  gateIds.forEach((id, index) => {
2684
1084
  params[`:gid${index}`] = id;
2685
1085
  });
2686
- currentDb.prepare(
1086
+ getDbOrNull()!.prepare(
2687
1087
  `UPDATE quality_gates SET status = 'complete', verdict = 'omitted', evaluated_at = :now
2688
1088
  WHERE milestone_id = :mid AND slice_id = :sid AND status = 'pending'
2689
1089
  AND gate_id IN (${placeholders})`,
2690
1090
  ).run(params);
2691
1091
  }
2692
1092
 
2693
- export function getPendingSliceGateCount(milestoneId: string, sliceId: string): number {
2694
- if (!currentDb) return 0;
2695
- const row = currentDb.prepare(
2696
- `SELECT COUNT(*) as cnt FROM quality_gates
2697
- WHERE milestone_id = :mid AND slice_id = :sid AND scope = 'slice' AND status = 'pending'`,
2698
- ).get({ ":mid": milestoneId, ":sid": sliceId });
2699
- return row ? (row["cnt"] as number) : 0;
2700
- }
2701
1093
 
2702
- /**
2703
- * Return pending gate rows owned by a specific workflow turn.
2704
- *
2705
- * Unlike `getPendingGates(..., scope)`, this filters by the registry's
2706
- * `ownerTurn` metadata so callers can distinguish Q3/Q4 (owned by
2707
- * gate-evaluate) from Q8 (owned by complete-slice) even though both are
2708
- * scope:"slice". Pass `taskId` to narrow task-scoped results to one task.
2709
- */
2710
- export function getPendingGatesForTurn(
2711
- milestoneId: string,
2712
- sliceId: string,
2713
- turn: OwnerTurn,
2714
- taskId?: string,
2715
- ): GateRow[] {
2716
- if (!currentDb) return [];
2717
- const ids = getGateIdsForTurn(turn);
2718
- if (ids.size === 0) return [];
2719
- const idList = [...ids];
2720
- const placeholders = idList.map((_, i) => `:gid${i}`).join(",");
2721
- const params: Record<string, unknown> = {
2722
- ":mid": milestoneId,
2723
- ":sid": sliceId,
2724
- };
2725
- idList.forEach((id, i) => {
2726
- params[`:gid${i}`] = id;
2727
- });
2728
- let sql =
2729
- `SELECT * FROM quality_gates
2730
- WHERE milestone_id = :mid AND slice_id = :sid
2731
- AND status = 'pending'
2732
- AND gate_id IN (${placeholders})`;
2733
- if (taskId !== undefined) {
2734
- sql += ` AND task_id = :tid`;
2735
- params[":tid"] = taskId;
2736
- }
2737
- return currentDb.prepare(sql).all(params).map(rowToGate);
2738
- }
2739
1094
 
2740
- /**
2741
- * Count pending gates for a turn. Convenience wrapper used by state
2742
- * derivation to decide whether a phase transition should pause.
2743
- */
2744
- export function getPendingGateCountForTurn(
2745
- milestoneId: string,
2746
- sliceId: string,
2747
- turn: OwnerTurn,
2748
- ): number {
2749
- return getPendingGatesForTurn(milestoneId, sliceId, turn).length;
2750
- }
2751
1095
 
2752
1096
  export function insertGateRun(entry: {
2753
1097
  traceId: string;
@@ -2768,8 +1112,8 @@ export function insertGateRun(entry: {
2768
1112
  retryable: boolean;
2769
1113
  evaluatedAt: string;
2770
1114
  }): void {
2771
- if (!currentDb) return;
2772
- currentDb.prepare(
1115
+ if (!getDbOrNull()!) return;
1116
+ getDbOrNull()!.prepare(
2773
1117
  `INSERT INTO gate_runs (
2774
1118
  trace_id, turn_id, gate_id, gate_type, unit_type, unit_id, milestone_id, slice_id, task_id,
2775
1119
  outcome, failure_class, rationale, findings, attempt, max_attempts, retryable, evaluated_at
@@ -2811,8 +1155,8 @@ export function upsertTurnGitTransaction(entry: {
2811
1155
  metadata?: Record<string, unknown>;
2812
1156
  updatedAt: string;
2813
1157
  }): void {
2814
- if (!currentDb) return;
2815
- currentDb.prepare(
1158
+ if (!getDbOrNull()!) return;
1159
+ getDbOrNull()!.prepare(
2816
1160
  `INSERT OR REPLACE INTO turn_git_transactions (
2817
1161
  trace_id, turn_id, unit_type, unit_id, stage, action, push, status, error, metadata_json, updated_at
2818
1162
  ) VALUES (
@@ -2833,18 +1177,6 @@ export function upsertTurnGitTransaction(entry: {
2833
1177
  });
2834
1178
  }
2835
1179
 
2836
- export function getMilestoneCommitAttributionShas(milestoneId: string): string[] {
2837
- if (!currentDb) return [];
2838
- const rows = currentDb.prepare(
2839
- `SELECT commit_sha
2840
- FROM milestone_commit_attributions
2841
- WHERE milestone_id = :mid
2842
- ORDER BY created_at, commit_sha`,
2843
- ).all({ ":mid": milestoneId }) as Array<Record<string, unknown>>;
2844
- return rows
2845
- .map((row) => typeof row["commit_sha"] === "string" ? row["commit_sha"] : "")
2846
- .filter(Boolean);
2847
- }
2848
1180
 
2849
1181
  export function recordMilestoneCommitAttribution(entry: {
2850
1182
  commitSha: string;
@@ -2856,9 +1188,9 @@ export function recordMilestoneCommitAttribution(entry: {
2856
1188
  files: string[];
2857
1189
  createdAt: string;
2858
1190
  }): void {
2859
- if (!currentDb) return;
1191
+ if (!getDbOrNull()!) return;
2860
1192
  transaction(() => {
2861
- currentDb!.prepare(
1193
+ getDbOrNull()!!.prepare(
2862
1194
  `INSERT OR REPLACE INTO milestone_commit_attributions (
2863
1195
  commit_sha, milestone_id, slice_id, task_id, source, confidence, files_json, created_at
2864
1196
  ) VALUES (
@@ -2875,7 +1207,7 @@ export function recordMilestoneCommitAttribution(entry: {
2875
1207
  ":created_at": entry.createdAt,
2876
1208
  });
2877
1209
 
2878
- currentDb!.prepare(
1210
+ getDbOrNull()!!.prepare(
2879
1211
  `INSERT OR IGNORE INTO audit_events (
2880
1212
  event_id, trace_id, turn_id, caused_by, category, type, ts, payload_json
2881
1213
  ) VALUES (
@@ -2912,9 +1244,9 @@ export function insertAuditEvent(entry: {
2912
1244
  ts: string;
2913
1245
  payload: Record<string, unknown>;
2914
1246
  }): void {
2915
- if (!currentDb) return;
1247
+ if (!getDbOrNull()!) return;
2916
1248
  transaction(() => {
2917
- currentDb!.prepare(
1249
+ getDbOrNull()!!.prepare(
2918
1250
  `INSERT OR IGNORE INTO audit_events (
2919
1251
  event_id, trace_id, turn_id, caused_by, category, type, ts, payload_json
2920
1252
  ) VALUES (
@@ -2932,7 +1264,7 @@ export function insertAuditEvent(entry: {
2932
1264
  });
2933
1265
 
2934
1266
  if (entry.turnId) {
2935
- const row = currentDb!.prepare(
1267
+ const row = getDbOrNull()!!.prepare(
2936
1268
  `SELECT event_count, first_ts, last_ts
2937
1269
  FROM audit_turn_index
2938
1270
  WHERE trace_id = :trace_id AND turn_id = :turn_id`,
@@ -2941,7 +1273,7 @@ export function insertAuditEvent(entry: {
2941
1273
  ":turn_id": entry.turnId,
2942
1274
  });
2943
1275
  if (row) {
2944
- currentDb!.prepare(
1276
+ getDbOrNull()!!.prepare(
2945
1277
  `UPDATE audit_turn_index
2946
1278
  SET first_ts = CASE WHEN :ts < first_ts THEN :ts ELSE first_ts END,
2947
1279
  last_ts = CASE WHEN :ts > last_ts THEN :ts ELSE last_ts END,
@@ -2953,7 +1285,7 @@ export function insertAuditEvent(entry: {
2953
1285
  ":ts": entry.ts,
2954
1286
  });
2955
1287
  } else {
2956
- currentDb!.prepare(
1288
+ getDbOrNull()!!.prepare(
2957
1289
  `INSERT INTO audit_turn_index (trace_id, turn_id, first_ts, last_ts, event_count)
2958
1290
  VALUES (:trace_id, :turn_id, :first_ts, :last_ts, :event_count)`,
2959
1291
  ).run({
@@ -2977,20 +1309,20 @@ export function insertAuditEvent(entry: {
2977
1309
 
2978
1310
  /** Delete a decision row by id. Used by db-writer.ts rollback on disk-write failure. */
2979
1311
  export function deleteDecisionById(id: string): void {
2980
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2981
- currentDb.prepare("DELETE FROM decisions WHERE id = :id").run({ ":id": id });
1312
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1313
+ getDbOrNull()!.prepare("DELETE FROM decisions WHERE id = :id").run({ ":id": id });
2982
1314
  }
2983
1315
 
2984
1316
  /** Delete a requirement row by id. Used by db-writer.ts rollback on disk-write failure. */
2985
1317
  export function deleteRequirementById(id: string): void {
2986
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2987
- currentDb.prepare("DELETE FROM requirements WHERE id = :id").run({ ":id": id });
1318
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1319
+ getDbOrNull()!.prepare("DELETE FROM requirements WHERE id = :id").run({ ":id": id });
2988
1320
  }
2989
1321
 
2990
1322
  /** Delete an artifact row by path. Used by db-writer.ts rollback on disk-write failure. */
2991
1323
  export function deleteArtifactByPath(path: string): void {
2992
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2993
- currentDb.prepare("DELETE FROM artifacts WHERE path = :path").run({ ":path": path });
1324
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1325
+ getDbOrNull()!.prepare("DELETE FROM artifacts WHERE path = :path").run({ ":path": path });
2994
1326
  }
2995
1327
 
2996
1328
  /**
@@ -2998,18 +1330,18 @@ export function deleteArtifactByPath(path: string): void {
2998
1330
  * `gsd recover --confirm` to rebuild engine state from markdown.
2999
1331
  */
3000
1332
  export function clearEngineHierarchy(): void {
3001
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1333
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
3002
1334
  transaction(() => {
3003
- currentDb!.exec("DELETE FROM verification_evidence");
3004
- currentDb!.exec("DELETE FROM quality_gates");
3005
- currentDb!.exec("DELETE FROM slice_dependencies");
3006
- currentDb!.exec("DELETE FROM assessments");
3007
- currentDb!.exec("DELETE FROM replan_history");
3008
- currentDb!.exec("DELETE FROM milestone_commit_attributions");
3009
- currentDb!.exec("DELETE FROM tasks");
3010
- currentDb!.exec("DELETE FROM slices");
3011
- currentDb!.exec("DELETE FROM milestone_leases");
3012
- currentDb!.exec("DELETE FROM milestones");
1335
+ getDbOrNull()!!.exec("DELETE FROM verification_evidence");
1336
+ getDbOrNull()!!.exec("DELETE FROM quality_gates");
1337
+ getDbOrNull()!!.exec("DELETE FROM slice_dependencies");
1338
+ getDbOrNull()!!.exec("DELETE FROM assessments");
1339
+ getDbOrNull()!!.exec("DELETE FROM replan_history");
1340
+ getDbOrNull()!!.exec("DELETE FROM milestone_commit_attributions");
1341
+ getDbOrNull()!!.exec("DELETE FROM tasks");
1342
+ getDbOrNull()!!.exec("DELETE FROM slices");
1343
+ getDbOrNull()!!.exec("DELETE FROM milestone_leases");
1344
+ getDbOrNull()!!.exec("DELETE FROM milestones");
3013
1345
  });
3014
1346
  }
3015
1347
 
@@ -3025,8 +1357,8 @@ export function insertOrIgnoreSlice(args: {
3025
1357
  title: string;
3026
1358
  createdAt: string;
3027
1359
  }): void {
3028
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
3029
- currentDb.prepare(
1360
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1361
+ getDbOrNull()!.prepare(
3030
1362
  `INSERT OR IGNORE INTO slices (milestone_id, id, title, status, created_at)
3031
1363
  VALUES (:mid, :sid, :title, 'pending', :ts)`,
3032
1364
  ).run({
@@ -3048,8 +1380,8 @@ export function insertOrIgnoreTask(args: {
3048
1380
  title: string;
3049
1381
  createdAt: string;
3050
1382
  }): void {
3051
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
3052
- currentDb.prepare(
1383
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1384
+ getDbOrNull()!.prepare(
3053
1385
  `INSERT OR IGNORE INTO tasks (milestone_id, slice_id, id, title, status, created_at)
3054
1386
  VALUES (:mid, :sid, :tid, :title, 'pending', :ts)`,
3055
1387
  ).run({
@@ -3067,8 +1399,8 @@ export function insertOrIgnoreTask(args: {
3067
1399
  * trigger via DB in addition to the on-disk REPLAN-TRIGGER.md marker.
3068
1400
  */
3069
1401
  export function setSliceReplanTriggeredAt(milestoneId: string, sliceId: string, ts: string): void {
3070
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
3071
- currentDb.prepare(
1402
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1403
+ getDbOrNull()!.prepare(
3072
1404
  "UPDATE slices SET replan_triggered_at = :ts WHERE milestone_id = :mid AND id = :sid",
3073
1405
  ).run({ ":ts": ts, ":mid": milestoneId, ":sid": sliceId });
3074
1406
  }
@@ -3089,8 +1421,8 @@ export function upsertQualityGate(g: {
3089
1421
  findings: string;
3090
1422
  evaluatedAt: string;
3091
1423
  }): void {
3092
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
3093
- currentDb.prepare(
1424
+ if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1425
+ getDbOrNull()!.prepare(
3094
1426
  `INSERT OR REPLACE INTO quality_gates
3095
1427
  (milestone_id, slice_id, gate_id, scope, task_id, status, verdict, rationale, findings, evaluated_at)
3096
1428
  VALUES (:mid, :sid, :gid, :scope, :tid, :status, :verdict, :rationale, :findings, :evaluated_at)`,
@@ -3107,526 +1439,3 @@ export function upsertQualityGate(g: {
3107
1439
  ":evaluated_at": g.evaluatedAt,
3108
1440
  });
3109
1441
  }
3110
-
3111
- /**
3112
- * Atomically replace all workflow state from a manifest. Lifted verbatim from
3113
- * workflow-manifest.ts so the single-writer invariant holds. Restores
3114
- * correctness-bearing workflow tables; runtime soft state and append-only audit
3115
- * streams stay outside this recovery path.
3116
- */
3117
- export function restoreManifest(manifest: StateManifest): void {
3118
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
3119
- const db = currentDb;
3120
-
3121
- transaction(() => {
3122
- const restoredMilestoneIds = new Set(manifest.milestones.map((m) => m.id));
3123
- const restoredSliceKeys = new Set(manifest.slices.map((s) => JSON.stringify([s.milestone_id, s.id])));
3124
- const preservedReplanHistory = manifest.replan_history === undefined
3125
- ? db.prepare("SELECT * FROM replan_history ORDER BY id").all() as unknown as NonNullable<StateManifest["replan_history"]>
3126
- : [];
3127
- const preservedAssessments = manifest.assessments === undefined
3128
- ? db.prepare("SELECT * FROM assessments ORDER BY path").all() as unknown as NonNullable<StateManifest["assessments"]>
3129
- : [];
3130
- const preservedQualityGates = manifest.quality_gates === undefined
3131
- ? db.prepare("SELECT * FROM quality_gates ORDER BY milestone_id, slice_id, gate_id, task_id").all() as unknown as NonNullable<StateManifest["quality_gates"]>
3132
- : [];
3133
- const preservedCommitAttributions = manifest.milestone_commit_attributions === undefined
3134
- ? db.prepare("SELECT * FROM milestone_commit_attributions ORDER BY milestone_id, commit_sha").all() as unknown as NonNullable<StateManifest["milestone_commit_attributions"]>
3135
- : [];
3136
-
3137
- // Clear workflow tables in dependency order.
3138
- db.exec("DELETE FROM verification_evidence");
3139
- db.exec("DELETE FROM quality_gates");
3140
- db.exec("DELETE FROM slice_dependencies");
3141
- db.exec("DELETE FROM assessments");
3142
- db.exec("DELETE FROM replan_history");
3143
- db.exec("DELETE FROM milestone_commit_attributions");
3144
- db.exec("DELETE FROM tasks");
3145
- db.exec("DELETE FROM slices");
3146
- db.exec("DELETE FROM milestone_leases");
3147
- db.exec("DELETE FROM milestones");
3148
- db.exec("DELETE FROM decisions WHERE 1=1");
3149
- db.exec(`DELETE FROM memories WHERE category = 'architecture' AND structured_fields LIKE '%"sourceDecisionId":"%'`);
3150
- if (manifest.artifacts !== undefined) db.exec("DELETE FROM artifacts");
3151
- if (manifest.requirements !== undefined) db.exec("DELETE FROM requirements");
3152
-
3153
- if (manifest.requirements !== undefined) {
3154
- const reqStmt = db.prepare(
3155
- `INSERT INTO requirements (
3156
- id, class, status, description, why, source, primary_owner,
3157
- supporting_slices, validation, notes, full_content, superseded_by
3158
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
3159
- );
3160
- for (const r of manifest.requirements) {
3161
- reqStmt.run(
3162
- r.id, r.class, r.status, r.description, r.why, r.source, r.primary_owner,
3163
- r.supporting_slices, r.validation, r.notes, r.full_content, r.superseded_by,
3164
- );
3165
- }
3166
- }
3167
-
3168
- if (manifest.artifacts !== undefined) {
3169
- const artStmt = db.prepare(
3170
- `INSERT INTO artifacts (
3171
- path, artifact_type, milestone_id, slice_id, task_id, full_content, imported_at, content_hash
3172
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
3173
- );
3174
- for (const a of manifest.artifacts) {
3175
- const fullContent = a.full_content ?? "";
3176
- artStmt.run(
3177
- a.path, a.artifact_type, a.milestone_id, a.slice_id, a.task_id,
3178
- fullContent, a.imported_at, a.content_hash ?? createHash("sha256").update(fullContent).digest("hex"),
3179
- );
3180
- }
3181
- }
3182
-
3183
- // Restore milestones
3184
- const msStmt = db.prepare(
3185
- `INSERT INTO milestones (id, title, status, depends_on, created_at, completed_at,
3186
- vision, success_criteria, key_risks, proof_strategy,
3187
- verification_contract, verification_integration, verification_operational, verification_uat,
3188
- definition_of_done, requirement_coverage, boundary_map_markdown, sequence)
3189
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
3190
- );
3191
- for (const m of manifest.milestones) {
3192
- msStmt.run(
3193
- m.id, m.title, m.status,
3194
- JSON.stringify(m.depends_on), m.created_at, m.completed_at,
3195
- m.vision, JSON.stringify(m.success_criteria), JSON.stringify(m.key_risks),
3196
- JSON.stringify(m.proof_strategy),
3197
- m.verification_contract, m.verification_integration, m.verification_operational, m.verification_uat,
3198
- JSON.stringify(m.definition_of_done), m.requirement_coverage, m.boundary_map_markdown, m.sequence ?? 0,
3199
- );
3200
- }
3201
-
3202
- // Restore slices (ADR-011 Phase 1: includes is_sketch + sketch_scope)
3203
- const slStmt = db.prepare(
3204
- `INSERT INTO slices (milestone_id, id, title, status, risk, depends, demo,
3205
- created_at, completed_at, full_summary_md, full_uat_md,
3206
- goal, success_criteria, proof_level, integration_closure, observability_impact,
3207
- target_repositories, sequence, replan_triggered_at, is_sketch, sketch_scope)
3208
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
3209
- );
3210
- for (const s of manifest.slices) {
3211
- slStmt.run(
3212
- s.milestone_id, s.id, s.title, s.status, s.risk,
3213
- JSON.stringify(s.depends), s.demo,
3214
- s.created_at, s.completed_at, s.full_summary_md, s.full_uat_md,
3215
- s.goal, s.success_criteria, s.proof_level, s.integration_closure, s.observability_impact,
3216
- JSON.stringify(s.target_repositories ?? []),
3217
- s.sequence, s.replan_triggered_at,
3218
- s.is_sketch ?? 0,
3219
- s.sketch_scope ?? "",
3220
- );
3221
- }
3222
-
3223
- const depStmt = db.prepare(
3224
- "INSERT OR IGNORE INTO slice_dependencies (milestone_id, slice_id, depends_on_slice_id) VALUES (?, ?, ?)",
3225
- );
3226
- for (const s of manifest.slices) {
3227
- for (const dep of s.depends ?? []) {
3228
- depStmt.run(s.milestone_id, s.id, dep);
3229
- }
3230
- }
3231
-
3232
- // Restore tasks (ADR-011 P2: includes blocker_source + escalation_* columns)
3233
- const tkStmt = db.prepare(
3234
- `INSERT INTO tasks (milestone_id, slice_id, id, title, status,
3235
- one_liner, narrative, verification_result, duration, completed_at,
3236
- blocker_discovered, deviations, known_issues, key_files, key_decisions,
3237
- full_summary_md, description, estimate, files, verify,
3238
- inputs, expected_output, observability_impact, full_plan_md, target_repositories, sequence,
3239
- blocker_source, escalation_pending, escalation_awaiting_review,
3240
- escalation_artifact_path, escalation_override_applied_at)
3241
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
3242
- );
3243
- for (const t of manifest.tasks) {
3244
- tkStmt.run(
3245
- t.milestone_id, t.slice_id, t.id, t.title, t.status,
3246
- t.one_liner, t.narrative, t.verification_result, t.duration, t.completed_at,
3247
- t.blocker_discovered ? 1 : 0, t.deviations, t.known_issues,
3248
- JSON.stringify(t.key_files), JSON.stringify(t.key_decisions),
3249
- t.full_summary_md, t.description, t.estimate, JSON.stringify(t.files), t.verify,
3250
- JSON.stringify(t.inputs), JSON.stringify(t.expected_output),
3251
- t.observability_impact, t.full_plan_md ?? "", JSON.stringify(t.target_repositories ?? []), t.sequence,
3252
- t.blocker_source ?? "",
3253
- t.escalation_pending ?? 0,
3254
- t.escalation_awaiting_review ?? 0,
3255
- t.escalation_artifact_path ?? null,
3256
- t.escalation_override_applied_at ?? null,
3257
- );
3258
- }
3259
-
3260
- // Restore decisions (ADR-011 P2: include source so escalation decisions survive)
3261
- const dcStmt = db.prepare(
3262
- `INSERT INTO decisions (seq, id, when_context, scope, decision, choice, rationale, revisable, made_by, source, superseded_by)
3263
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
3264
- );
3265
- for (const d of manifest.decisions) {
3266
- 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);
3267
- }
3268
-
3269
- const replanHistoryRows = manifest.replan_history ?? preservedReplanHistory.filter((r) => restoredMilestoneIds.has(r.milestone_id));
3270
- if (replanHistoryRows.length > 0) {
3271
- const replStmt = db.prepare(
3272
- `INSERT INTO replan_history (
3273
- id, milestone_id, slice_id, task_id, summary, previous_artifact_path, replacement_artifact_path, created_at
3274
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
3275
- );
3276
- for (const r of replanHistoryRows) {
3277
- replStmt.run(
3278
- r.id, r.milestone_id, r.slice_id, r.task_id, r.summary,
3279
- r.previous_artifact_path, r.replacement_artifact_path, r.created_at,
3280
- );
3281
- }
3282
- }
3283
-
3284
- const assessmentRows = manifest.assessments ?? preservedAssessments.filter((a) => restoredMilestoneIds.has(a.milestone_id));
3285
- if (assessmentRows.length > 0) {
3286
- const assessStmt = db.prepare(
3287
- `INSERT INTO assessments (
3288
- path, milestone_id, slice_id, task_id, status, scope, full_content, created_at
3289
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
3290
- );
3291
- for (const a of assessmentRows) {
3292
- assessStmt.run(
3293
- a.path, a.milestone_id, a.slice_id, a.task_id,
3294
- a.status, a.scope, a.full_content, a.created_at,
3295
- );
3296
- }
3297
- }
3298
-
3299
- const qualityGateRows = manifest.quality_gates ?? preservedQualityGates.filter((g) => (
3300
- restoredSliceKeys.has(JSON.stringify([g.milestone_id, g.slice_id]))
3301
- ));
3302
- if (qualityGateRows.length > 0) {
3303
- const gateStmt = db.prepare(
3304
- `INSERT INTO quality_gates (
3305
- milestone_id, slice_id, gate_id, scope, task_id, status, verdict, rationale, findings, evaluated_at
3306
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
3307
- );
3308
- for (const g of qualityGateRows) {
3309
- gateStmt.run(
3310
- g.milestone_id, g.slice_id, g.gate_id, g.scope, g.task_id,
3311
- g.status, g.verdict ?? "", g.rationale, g.findings, g.evaluated_at,
3312
- );
3313
- }
3314
- }
3315
-
3316
- const commitAttributionRows = manifest.milestone_commit_attributions ??
3317
- preservedCommitAttributions.filter((a) => restoredMilestoneIds.has(a.milestone_id));
3318
- if (commitAttributionRows.length > 0) {
3319
- const attrStmt = db.prepare(
3320
- `INSERT OR REPLACE INTO milestone_commit_attributions (
3321
- commit_sha, milestone_id, slice_id, task_id, source, confidence, files_json, created_at
3322
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
3323
- );
3324
- for (const a of commitAttributionRows) {
3325
- attrStmt.run(
3326
- a.commit_sha, a.milestone_id, a.slice_id, a.task_id,
3327
- a.source, a.confidence, a.files_json, a.created_at,
3328
- );
3329
- }
3330
- }
3331
-
3332
- // Restore verification evidence
3333
- const evStmt = db.prepare(
3334
- `INSERT INTO verification_evidence (task_id, slice_id, milestone_id, command, exit_code, verdict, duration_ms, created_at)
3335
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
3336
- );
3337
- for (const e of manifest.verification_evidence) {
3338
- evStmt.run(e.task_id, e.slice_id, e.milestone_id, e.command, e.exit_code, e.verdict, e.duration_ms, e.created_at);
3339
- }
3340
- });
3341
- }
3342
-
3343
- // ─── Legacy markdown → DB bulk migration ─────────────────────────────────
3344
-
3345
- export interface LegacyMilestoneInsert {
3346
- id: string;
3347
- title: string;
3348
- status: string;
3349
- }
3350
-
3351
- export interface LegacySliceInsert {
3352
- id: string;
3353
- milestoneId: string;
3354
- title: string;
3355
- status: string;
3356
- risk: string;
3357
- sequence: number;
3358
- }
3359
-
3360
- export interface LegacyTaskInsert {
3361
- id: string;
3362
- sliceId: string;
3363
- milestoneId: string;
3364
- title: string;
3365
- status: string;
3366
- sequence: number;
3367
- }
3368
-
3369
- /**
3370
- * Bulk delete + insert a legacy milestone hierarchy for markdown → DB migration.
3371
- * Used by workflow-migration.ts to populate engine tables from parsed ROADMAP/PLAN
3372
- * files. All operations run inside a single transaction.
3373
- */
3374
- export function bulkInsertLegacyHierarchy(payload: {
3375
- milestones: LegacyMilestoneInsert[];
3376
- slices: LegacySliceInsert[];
3377
- tasks: LegacyTaskInsert[];
3378
- clearMilestoneIds: string[];
3379
- createdAt: string;
3380
- }): void {
3381
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
3382
- const db = currentDb;
3383
- const { milestones, slices, tasks, clearMilestoneIds, createdAt } = payload;
3384
-
3385
- if (clearMilestoneIds.length === 0) return;
3386
- const placeholders = clearMilestoneIds.map(() => "?").join(",");
3387
-
3388
- transaction(() => {
3389
- db.prepare(`DELETE FROM tasks WHERE milestone_id IN (${placeholders})`).run(...clearMilestoneIds);
3390
- db.prepare(`DELETE FROM slices WHERE milestone_id IN (${placeholders})`).run(...clearMilestoneIds);
3391
- db.prepare(`DELETE FROM milestone_leases WHERE milestone_id IN (${placeholders})`).run(...clearMilestoneIds);
3392
- db.prepare(`DELETE FROM milestones WHERE id IN (${placeholders})`).run(...clearMilestoneIds);
3393
-
3394
- const insertMilestone = db.prepare(
3395
- "INSERT INTO milestones (id, title, status, created_at) VALUES (?, ?, ?, ?)",
3396
- );
3397
- for (const m of milestones) {
3398
- insertMilestone.run(m.id, m.title, m.status, createdAt);
3399
- }
3400
-
3401
- const insertSliceStmt = db.prepare(
3402
- "INSERT INTO slices (id, milestone_id, title, status, risk, depends, sequence, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
3403
- );
3404
- for (const s of slices) {
3405
- insertSliceStmt.run(s.id, s.milestoneId, s.title, s.status, s.risk, "[]", s.sequence, createdAt);
3406
- }
3407
-
3408
- const insertTaskStmt = db.prepare(
3409
- "INSERT INTO tasks (id, slice_id, milestone_id, title, description, status, estimate, files, sequence) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
3410
- );
3411
- for (const t of tasks) {
3412
- insertTaskStmt.run(t.id, t.sliceId, t.milestoneId, t.title, "", t.status, "", "[]", t.sequence);
3413
- }
3414
- });
3415
- }
3416
-
3417
- // ─── Memory store writers ────────────────────────────────────────────────
3418
- // All memory writes go through gsd-db.ts so the single-writer invariant
3419
- // holds. These are direct pass-throughs to the SQL previously in
3420
- // memory-store.ts — same bindings, same behavior.
3421
-
3422
- export function insertMemoryRow(args: {
3423
- id: string;
3424
- category: string;
3425
- content: string;
3426
- confidence: number;
3427
- sourceUnitType: string | null;
3428
- sourceUnitId: string | null;
3429
- createdAt: string;
3430
- updatedAt: string;
3431
- scope?: string;
3432
- tags?: string[];
3433
- /**
3434
- * ADR-013 Step 2: optional structured payload preserved alongside the flat
3435
- * `content` field. Used to retain gsd_save_decision-style fields (scope,
3436
- * decision, choice, rationale, made_by, revisable) on architecture-category
3437
- * memories so the cutover in Step 6 is lossless. Schema is intentionally
3438
- * open inside the JSON; documented per category in ADR-013.
3439
- */
3440
- structuredFields?: Record<string, unknown> | null;
3441
- }): void {
3442
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
3443
- currentDb.prepare(
3444
- `INSERT INTO memories (id, category, content, confidence, source_unit_type, source_unit_id, created_at, updated_at, scope, tags, structured_fields)
3445
- VALUES (:id, :category, :content, :confidence, :source_unit_type, :source_unit_id, :created_at, :updated_at, :scope, :tags, :structured_fields)`,
3446
- ).run({
3447
- ":id": args.id,
3448
- ":category": args.category,
3449
- ":content": args.content,
3450
- ":confidence": args.confidence,
3451
- ":source_unit_type": args.sourceUnitType,
3452
- ":source_unit_id": args.sourceUnitId,
3453
- ":created_at": args.createdAt,
3454
- ":updated_at": args.updatedAt,
3455
- ":scope": args.scope ?? "project",
3456
- ":tags": JSON.stringify(args.tags ?? []),
3457
- ":structured_fields": args.structuredFields == null ? null : JSON.stringify(args.structuredFields),
3458
- });
3459
- }
3460
-
3461
- export function insertMemorySourceRow(args: {
3462
- id: string;
3463
- kind: string;
3464
- uri: string | null;
3465
- title: string | null;
3466
- content: string;
3467
- contentHash: string;
3468
- importedAt: string;
3469
- scope?: string;
3470
- tags?: string[];
3471
- }): void {
3472
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
3473
- currentDb.prepare(
3474
- `INSERT OR IGNORE INTO memory_sources (id, kind, uri, title, content, content_hash, imported_at, scope, tags)
3475
- VALUES (:id, :kind, :uri, :title, :content, :content_hash, :imported_at, :scope, :tags)`,
3476
- ).run({
3477
- ":id": args.id,
3478
- ":kind": args.kind,
3479
- ":uri": args.uri,
3480
- ":title": args.title,
3481
- ":content": args.content,
3482
- ":content_hash": args.contentHash,
3483
- ":imported_at": args.importedAt,
3484
- ":scope": args.scope ?? "project",
3485
- ":tags": JSON.stringify(args.tags ?? []),
3486
- });
3487
- }
3488
-
3489
- export function deleteMemorySourceRow(id: string): boolean {
3490
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
3491
- const res = currentDb
3492
- .prepare("DELETE FROM memory_sources WHERE id = :id")
3493
- .run({ ":id": id }) as { changes?: number };
3494
- return (res?.changes ?? 0) > 0;
3495
- }
3496
-
3497
- export function upsertMemoryEmbedding(args: {
3498
- memoryId: string;
3499
- model: string;
3500
- dim: number;
3501
- vector: Uint8Array;
3502
- updatedAt: string;
3503
- }): void {
3504
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
3505
- currentDb.prepare(
3506
- `INSERT INTO memory_embeddings (memory_id, model, dim, vector, updated_at)
3507
- VALUES (:memory_id, :model, :dim, :vector, :updated_at)
3508
- ON CONFLICT(memory_id) DO UPDATE SET
3509
- model = excluded.model,
3510
- dim = excluded.dim,
3511
- vector = excluded.vector,
3512
- updated_at = excluded.updated_at`,
3513
- ).run({
3514
- ":memory_id": args.memoryId,
3515
- ":model": args.model,
3516
- ":dim": args.dim,
3517
- ":vector": args.vector,
3518
- ":updated_at": args.updatedAt,
3519
- });
3520
- }
3521
-
3522
- export function deleteMemoryEmbedding(memoryId: string): boolean {
3523
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
3524
- const res = currentDb
3525
- .prepare("DELETE FROM memory_embeddings WHERE memory_id = :id")
3526
- .run({ ":id": memoryId }) as { changes?: number };
3527
- return (res?.changes ?? 0) > 0;
3528
- }
3529
-
3530
- export function insertMemoryRelationRow(args: {
3531
- fromId: string;
3532
- toId: string;
3533
- rel: string;
3534
- confidence: number;
3535
- createdAt: string;
3536
- }): void {
3537
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
3538
- currentDb.prepare(
3539
- `INSERT OR REPLACE INTO memory_relations (from_id, to_id, rel, confidence, created_at)
3540
- VALUES (:from_id, :to_id, :rel, :confidence, :created_at)`,
3541
- ).run({
3542
- ":from_id": args.fromId,
3543
- ":to_id": args.toId,
3544
- ":rel": args.rel,
3545
- ":confidence": args.confidence,
3546
- ":created_at": args.createdAt,
3547
- });
3548
- }
3549
-
3550
- export function deleteMemoryRelationsFor(memoryId: string): void {
3551
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
3552
- currentDb
3553
- .prepare("DELETE FROM memory_relations WHERE from_id = :id OR to_id = :id")
3554
- .run({ ":id": memoryId });
3555
- }
3556
-
3557
- export function rewriteMemoryId(placeholderId: string, realId: string): void {
3558
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
3559
- currentDb.prepare("UPDATE memories SET id = :real_id WHERE id = :placeholder").run({
3560
- ":real_id": realId,
3561
- ":placeholder": placeholderId,
3562
- });
3563
- }
3564
-
3565
- export function updateMemoryContentRow(
3566
- id: string,
3567
- content: string,
3568
- confidence: number | undefined,
3569
- updatedAt: string,
3570
- ): void {
3571
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
3572
- if (confidence != null) {
3573
- currentDb.prepare(
3574
- "UPDATE memories SET content = :content, confidence = :confidence, updated_at = :updated_at WHERE id = :id",
3575
- ).run({ ":content": content, ":confidence": confidence, ":updated_at": updatedAt, ":id": id });
3576
- } else {
3577
- currentDb.prepare(
3578
- "UPDATE memories SET content = :content, updated_at = :updated_at WHERE id = :id",
3579
- ).run({ ":content": content, ":updated_at": updatedAt, ":id": id });
3580
- }
3581
- }
3582
-
3583
- export function incrementMemoryHitCount(id: string, updatedAt: string): void {
3584
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
3585
- currentDb.prepare(
3586
- "UPDATE memories SET hit_count = hit_count + 1, updated_at = :updated_at, last_hit_at = :last_hit_at WHERE id = :id",
3587
- ).run({ ":updated_at": updatedAt, ":last_hit_at": updatedAt, ":id": id });
3588
- }
3589
-
3590
- export function supersedeMemoryRow(oldId: string, newId: string, updatedAt: string): void {
3591
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
3592
- currentDb.prepare(
3593
- "UPDATE memories SET superseded_by = :new_id, updated_at = :updated_at WHERE id = :old_id",
3594
- ).run({ ":new_id": newId, ":updated_at": updatedAt, ":old_id": oldId });
3595
- }
3596
-
3597
- export function markMemoryUnitProcessed(
3598
- unitKey: string,
3599
- activityFile: string,
3600
- processedAt: string,
3601
- ): void {
3602
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
3603
- currentDb.prepare(
3604
- `INSERT OR IGNORE INTO memory_processed_units (unit_key, activity_file, processed_at)
3605
- VALUES (:key, :file, :at)`,
3606
- ).run({ ":key": unitKey, ":file": activityFile, ":at": processedAt });
3607
- }
3608
-
3609
- export function decayMemoriesBefore(cutoffTs: string, now: string): void {
3610
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
3611
- currentDb.prepare(
3612
- `UPDATE memories
3613
- SET confidence = MAX(0.1, confidence - 0.1), updated_at = :now
3614
- WHERE superseded_by IS NULL
3615
- AND updated_at < :cutoff
3616
- AND confidence > 0.1
3617
- AND (structured_fields IS NULL OR structured_fields NOT LIKE '%"sourceDecisionId"%')`,
3618
- ).run({ ":now": now, ":cutoff": cutoffTs });
3619
- }
3620
-
3621
- export function supersedeLowestRankedMemories(limit: number, now: string): void {
3622
- if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
3623
- currentDb.prepare(
3624
- `UPDATE memories SET superseded_by = 'CAP_EXCEEDED', updated_at = :now
3625
- WHERE id IN (
3626
- SELECT id FROM memories
3627
- WHERE superseded_by IS NULL
3628
- ORDER BY (confidence * (1.0 + hit_count * 0.1)) ASC
3629
- LIMIT :limit
3630
- )`,
3631
- ).run({ ":now": now, ":limit": limit });
3632
- }