gsd-pi 2.78.1-dev.b0759e59b → 2.78.1-dev.d8826a445

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 (300) hide show
  1. package/README.md +8 -5
  2. package/dist/headless-recover.d.ts +23 -0
  3. package/dist/headless-recover.js +93 -0
  4. package/dist/headless.js +9 -0
  5. package/dist/help-text.js +1 -0
  6. package/dist/resources/.managed-resources-content-hash +1 -1
  7. package/dist/resources/extensions/browser-tools/tools/intent.js +8 -1
  8. package/dist/resources/extensions/gsd/auto/phases.js +7 -2
  9. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  10. package/dist/resources/extensions/gsd/auto-dispatch.js +7 -58
  11. package/dist/resources/extensions/gsd/auto-post-unit.js +14 -28
  12. package/dist/resources/extensions/gsd/auto-start.js +1 -8
  13. package/dist/resources/extensions/gsd/auto-worktree.js +244 -216
  14. package/dist/resources/extensions/gsd/auto.js +86 -7
  15. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +1 -1
  16. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +9 -77
  17. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +17 -16
  18. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +67 -55
  19. package/dist/resources/extensions/gsd/commands-codebase.js +2 -2
  20. package/dist/resources/extensions/gsd/commands-handlers.js +5 -5
  21. package/dist/resources/extensions/gsd/commands-logs.js +2 -2
  22. package/dist/resources/extensions/gsd/commands-scan.js +2 -2
  23. package/dist/resources/extensions/gsd/commands-ship.js +2 -2
  24. package/dist/resources/extensions/gsd/commands-workflow-templates.js +5 -5
  25. package/dist/resources/extensions/gsd/db-writer.js +106 -95
  26. package/dist/resources/extensions/gsd/delegation-policy.js +155 -0
  27. package/dist/resources/extensions/gsd/dispatch-guard.js +6 -10
  28. package/dist/resources/extensions/gsd/doctor-engine-checks.js +2 -2
  29. package/dist/resources/extensions/gsd/gsd-db.js +268 -8
  30. package/dist/resources/extensions/gsd/guided-flow-queue.js +1 -1
  31. package/dist/resources/extensions/gsd/guided-flow.js +141 -32
  32. package/dist/resources/extensions/gsd/markdown-renderer.js +14 -51
  33. package/dist/resources/extensions/gsd/metrics.js +287 -1
  34. package/dist/resources/extensions/gsd/parallel-merge.js +14 -13
  35. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +5 -2
  36. package/dist/resources/extensions/gsd/paths.js +114 -9
  37. package/dist/resources/extensions/gsd/prompts/complete-slice.md +4 -4
  38. package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -3
  39. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +8 -1
  40. package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +22 -7
  41. package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +6 -2
  42. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +8 -1
  43. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +6 -0
  44. package/dist/resources/extensions/gsd/queue-order.js +6 -1
  45. package/dist/resources/extensions/gsd/rethink.js +2 -2
  46. package/dist/resources/extensions/gsd/state.js +91 -372
  47. package/dist/resources/extensions/gsd/templates/project.md +10 -0
  48. package/dist/resources/extensions/gsd/tools/complete-milestone.js +6 -5
  49. package/dist/resources/extensions/gsd/tools/complete-slice.js +7 -12
  50. package/dist/resources/extensions/gsd/tools/complete-task.js +19 -31
  51. package/dist/resources/extensions/gsd/tools/validate-milestone.js +7 -5
  52. package/dist/resources/extensions/gsd/workflow-manifest.js +2 -1
  53. package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +3 -21
  54. package/dist/resources/extensions/gsd/workflow-mcp.js +2 -2
  55. package/dist/resources/extensions/gsd/workflow-reconcile.js +3 -3
  56. package/dist/resources/extensions/gsd/workspace.js +59 -0
  57. package/dist/resources/extensions/gsd/worktree-command.js +4 -3
  58. package/dist/resources/extensions/gsd/worktree-resolver.js +15 -2
  59. package/dist/resources/extensions/gsd/write-intercept.js +3 -3
  60. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  61. package/dist/web/standalone/.next/BUILD_ID +1 -1
  62. package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
  63. package/dist/web/standalone/.next/build-manifest.json +2 -2
  64. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  65. package/dist/web/standalone/.next/required-server-files.json +1 -1
  66. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  67. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  68. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  69. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  70. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  71. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  72. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  73. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  74. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  75. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  76. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  77. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  78. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  79. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  80. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  81. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  82. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  83. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  84. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  85. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  86. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  87. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  88. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  89. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  90. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  91. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  92. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  93. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  94. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  95. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  96. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  97. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  98. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  99. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  100. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  101. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  102. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  103. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  104. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  105. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  106. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  107. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  108. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  109. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  110. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  111. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  112. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  113. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  114. package/dist/web/standalone/.next/server/app/index.html +1 -1
  115. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
  122. package/dist/web/standalone/.next/server/chunks/6336.js +1 -0
  123. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  124. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  126. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  127. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  128. package/dist/web/standalone/server.js +1 -1
  129. package/package.json +1 -1
  130. package/packages/mcp-server/README.md +2 -11
  131. package/packages/mcp-server/dist/remote-questions.d.ts +27 -0
  132. package/packages/mcp-server/dist/remote-questions.d.ts.map +1 -1
  133. package/packages/mcp-server/dist/remote-questions.js +28 -0
  134. package/packages/mcp-server/dist/remote-questions.js.map +1 -1
  135. package/packages/mcp-server/dist/server.d.ts +28 -0
  136. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  137. package/packages/mcp-server/dist/server.js +94 -4
  138. package/packages/mcp-server/dist/server.js.map +1 -1
  139. package/packages/mcp-server/dist/workflow-tools.d.ts +6 -0
  140. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  141. package/packages/mcp-server/dist/workflow-tools.js +56 -2
  142. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  143. package/packages/mcp-server/src/mcp-server.test.ts +226 -0
  144. package/packages/mcp-server/src/parse-workflow-args.test.ts +80 -0
  145. package/packages/mcp-server/src/remote-questions.test.ts +103 -0
  146. package/packages/mcp-server/src/remote-questions.ts +35 -0
  147. package/packages/mcp-server/src/server.ts +129 -6
  148. package/packages/mcp-server/src/workflow-tools.ts +62 -3
  149. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  150. package/src/resources/extensions/browser-tools/tools/intent.ts +13 -2
  151. package/src/resources/extensions/gsd/auto/phases.ts +8 -2
  152. package/src/resources/extensions/gsd/auto/session.ts +4 -0
  153. package/src/resources/extensions/gsd/auto-dispatch.ts +14 -62
  154. package/src/resources/extensions/gsd/auto-post-unit.ts +15 -27
  155. package/src/resources/extensions/gsd/auto-start.ts +1 -8
  156. package/src/resources/extensions/gsd/auto-worktree.ts +286 -251
  157. package/src/resources/extensions/gsd/auto.ts +102 -7
  158. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +1 -1
  159. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +9 -84
  160. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +17 -17
  161. package/src/resources/extensions/gsd/bootstrap/tests/write-gate-basepath.test.ts +103 -0
  162. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +80 -55
  163. package/src/resources/extensions/gsd/commands-codebase.ts +2 -2
  164. package/src/resources/extensions/gsd/commands-handlers.ts +5 -5
  165. package/src/resources/extensions/gsd/commands-logs.ts +2 -2
  166. package/src/resources/extensions/gsd/commands-scan.ts +2 -2
  167. package/src/resources/extensions/gsd/commands-ship.ts +2 -2
  168. package/src/resources/extensions/gsd/commands-workflow-templates.ts +5 -5
  169. package/src/resources/extensions/gsd/db-writer.ts +123 -94
  170. package/src/resources/extensions/gsd/delegation-policy.ts +197 -0
  171. package/src/resources/extensions/gsd/dispatch-guard.ts +6 -11
  172. package/src/resources/extensions/gsd/doctor-engine-checks.ts +2 -2
  173. package/src/resources/extensions/gsd/gsd-db.ts +269 -8
  174. package/src/resources/extensions/gsd/guided-flow-queue.ts +1 -1
  175. package/src/resources/extensions/gsd/guided-flow.ts +181 -32
  176. package/src/resources/extensions/gsd/markdown-renderer.ts +13 -64
  177. package/src/resources/extensions/gsd/metrics.ts +321 -1
  178. package/src/resources/extensions/gsd/parallel-merge.ts +14 -13
  179. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +5 -2
  180. package/src/resources/extensions/gsd/paths.ts +122 -9
  181. package/src/resources/extensions/gsd/prompts/complete-slice.md +4 -4
  182. package/src/resources/extensions/gsd/prompts/execute-task.md +3 -3
  183. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +8 -1
  184. package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +22 -7
  185. package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +6 -2
  186. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +8 -1
  187. package/src/resources/extensions/gsd/prompts/plan-milestone.md +6 -0
  188. package/src/resources/extensions/gsd/queue-order.ts +6 -1
  189. package/src/resources/extensions/gsd/rethink.ts +2 -2
  190. package/src/resources/extensions/gsd/state.ts +91 -389
  191. package/src/resources/extensions/gsd/templates/project.md +10 -0
  192. package/src/resources/extensions/gsd/tests/artifact-corruption-2630.test.ts +1 -0
  193. package/src/resources/extensions/gsd/tests/auto-discuss-milestone-deadlock-4973.test.ts +14 -14
  194. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +6 -0
  195. package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +21 -34
  196. package/src/resources/extensions/gsd/tests/auto-session-scope.test.ts +331 -0
  197. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +176 -0
  198. package/src/resources/extensions/gsd/tests/complete-task-rollback-evidence.test.ts +6 -7
  199. package/src/resources/extensions/gsd/tests/complete-task.test.ts +8 -6
  200. package/src/resources/extensions/gsd/tests/completed-at-reconcile.test.ts +12 -27
  201. package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +18 -5
  202. package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +4 -4
  203. package/src/resources/extensions/gsd/tests/db-writer-path-containment.test.ts +152 -0
  204. package/src/resources/extensions/gsd/tests/db-writer-root-artifact.test.ts +221 -0
  205. package/src/resources/extensions/gsd/tests/db-writer-scope.test.ts +230 -0
  206. package/src/resources/extensions/gsd/tests/db-writer.test.ts +14 -16
  207. package/src/resources/extensions/gsd/tests/delegation-policy.test.ts +151 -0
  208. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +6 -5
  209. package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +10 -38
  210. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +136 -56
  211. package/src/resources/extensions/gsd/tests/derive-state-draft.test.ts +3 -0
  212. package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +119 -61
  213. package/src/resources/extensions/gsd/tests/derive-state.test.ts +4 -0
  214. package/src/resources/extensions/gsd/tests/dispatch-backgroundable-annotation.test.ts +55 -0
  215. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +6 -20
  216. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +4 -5
  217. package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +14 -15
  218. package/src/resources/extensions/gsd/tests/draft-promotion.test.ts +3 -23
  219. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +11 -16
  220. package/src/resources/extensions/gsd/tests/escalation.test.ts +2 -1
  221. package/src/resources/extensions/gsd/tests/gate-1b-orphan-discrimination.test.ts +193 -0
  222. package/src/resources/extensions/gsd/tests/gate-1b-recovery-bound-corrections.test.ts +246 -0
  223. package/src/resources/extensions/gsd/tests/gate-1b-recovery-bound.test.ts +218 -0
  224. package/src/resources/extensions/gsd/tests/gsd-db-failed-open-restore.test.ts +117 -0
  225. package/src/resources/extensions/gsd/tests/gsd-db-workspace-scope.test.ts +226 -0
  226. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +2 -1
  227. package/src/resources/extensions/gsd/tests/gsd-root-canonical.test.ts +66 -0
  228. package/src/resources/extensions/gsd/tests/gsd-root-home-guard.test.ts +68 -5
  229. package/src/resources/extensions/gsd/tests/gsdroot-worktree-detection.test.ts +15 -36
  230. package/src/resources/extensions/gsd/tests/guided-flow-prompt-consolidation.test.ts +4 -4
  231. package/src/resources/extensions/gsd/tests/handler-worktree-write-isolation.test.ts +57 -0
  232. package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +15 -15
  233. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +15 -5
  234. package/src/resources/extensions/gsd/tests/integration/workspace-collapse-integration.test.ts +371 -0
  235. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +14 -8
  236. package/src/resources/extensions/gsd/tests/md-importer.test.ts +2 -1
  237. package/src/resources/extensions/gsd/tests/memory-store.test.ts +3 -2
  238. package/src/resources/extensions/gsd/tests/metrics-atomic-merge.test.ts +222 -0
  239. package/src/resources/extensions/gsd/tests/metrics-lock-hardening.test.ts +400 -0
  240. package/src/resources/extensions/gsd/tests/metrics-lock-not-acquired.test.ts +141 -0
  241. package/src/resources/extensions/gsd/tests/metrics-lock-retry-sleep.test.ts +287 -0
  242. package/src/resources/extensions/gsd/tests/metrics-prune-cache-invalidation.test.ts +149 -0
  243. package/src/resources/extensions/gsd/tests/metrics-scope.test.ts +378 -0
  244. package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +329 -0
  245. package/src/resources/extensions/gsd/tests/park-milestone.test.ts +2 -0
  246. package/src/resources/extensions/gsd/tests/path-cache-decoupled.test.ts +209 -0
  247. package/src/resources/extensions/gsd/tests/path-normalization-unified.test.ts +175 -0
  248. package/src/resources/extensions/gsd/tests/paths-cache.test.ts +170 -0
  249. package/src/resources/extensions/gsd/tests/pending-autostart-scope.test.ts +120 -0
  250. package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +25 -16
  251. package/src/resources/extensions/gsd/tests/projection-regression.test.ts +1 -0
  252. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +150 -7
  253. package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +184 -0
  254. package/src/resources/extensions/gsd/tests/register-hooks-compaction-checkpoint.test.ts +6 -1
  255. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +28 -16
  256. package/src/resources/extensions/gsd/tests/replan-slice.test.ts +3 -0
  257. package/src/resources/extensions/gsd/tests/resolve-ts.mjs +4 -0
  258. package/src/resources/extensions/gsd/tests/resume-missing-worktree-warning.test.ts +209 -0
  259. package/src/resources/extensions/gsd/tests/rogue-file-detection.test.ts +3 -4
  260. package/src/resources/extensions/gsd/tests/slice-disk-reconcile.test.ts +10 -56
  261. package/src/resources/extensions/gsd/tests/stale-slice-rows.test.ts +15 -16
  262. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +1 -0
  263. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +23 -27
  264. package/src/resources/extensions/gsd/tests/steer-worktree-path.test.ts +13 -14
  265. package/src/resources/extensions/gsd/tests/stop-auto-remote.test.ts +4 -3
  266. package/src/resources/extensions/gsd/tests/sync-layer-scope.test.ts +453 -0
  267. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +10 -33
  268. package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +162 -0
  269. package/src/resources/extensions/gsd/tests/teardown-cleanup-parity.test.ts +102 -0
  270. package/src/resources/extensions/gsd/tests/teardown-failure-clears-registry.test.ts +186 -0
  271. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +1 -1
  272. package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +7 -8
  273. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +9 -15
  274. package/src/resources/extensions/gsd/tests/validator-scope-parity.test.ts +239 -0
  275. package/src/resources/extensions/gsd/tests/workflow-logger-wiring.test.ts +12 -7
  276. package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +4 -4
  277. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +26 -3
  278. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +9 -15
  279. package/src/resources/extensions/gsd/tests/workspace.test.ts +190 -0
  280. package/src/resources/extensions/gsd/tests/worktree-db-same-file.test.ts +13 -0
  281. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +65 -71
  282. package/src/resources/extensions/gsd/tests/worktree-sync-tasks.test.ts +26 -151
  283. package/src/resources/extensions/gsd/tests/write-gate-predicates.test.ts +35 -35
  284. package/src/resources/extensions/gsd/tests/write-gate.test.ts +67 -52
  285. package/src/resources/extensions/gsd/tests/write-intercept.test.ts +1 -1
  286. package/src/resources/extensions/gsd/tools/complete-milestone.ts +7 -5
  287. package/src/resources/extensions/gsd/tools/complete-slice.ts +7 -14
  288. package/src/resources/extensions/gsd/tools/complete-task.ts +19 -34
  289. package/src/resources/extensions/gsd/tools/validate-milestone.ts +7 -5
  290. package/src/resources/extensions/gsd/workflow-manifest.ts +4 -1
  291. package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +2 -18
  292. package/src/resources/extensions/gsd/workflow-mcp.ts +2 -2
  293. package/src/resources/extensions/gsd/workflow-reconcile.ts +3 -3
  294. package/src/resources/extensions/gsd/workspace.ts +95 -0
  295. package/src/resources/extensions/gsd/worktree-command.ts +4 -3
  296. package/src/resources/extensions/gsd/worktree-resolver.ts +16 -2
  297. package/src/resources/extensions/gsd/write-intercept.ts +3 -3
  298. package/dist/web/standalone/.next/server/chunks/8527.js +0 -1
  299. /package/dist/web/standalone/.next/static/{rk1EN3FQTE6Z1yalkW_GE → AT5qi39nKXkdmQIOIoh0f}/_buildManifest.js +0 -0
  300. /package/dist/web/standalone/.next/static/{rk1EN3FQTE6Z1yalkW_GE → AT5qi39nKXkdmQIOIoh0f}/_ssgManifest.js +0 -0
@@ -25,6 +25,7 @@ import { existsSync, copyFileSync, mkdirSync, realpathSync } from "node:fs";
25
25
  import { dirname } from "node:path";
26
26
  import type { Decision, Requirement, GateRow, GateId, GateScope, GateStatus, GateVerdict } from "./types.js";
27
27
  import { GSDError, GSD_STALE_STATE } from "./errors.js";
28
+ import type { GsdWorkspace, MilestoneScope } from "./workspace.js";
28
29
  import { getGateIdsForTurn, type OwnerTurn } from "./gate-registry.js";
29
30
  import { logError, logWarning } from "./workflow-logger.js";
30
31
  // Type-only import to avoid a circular runtime dep. The runtime side of
@@ -181,7 +182,7 @@ function openRawDb(path: string): unknown {
181
182
  return new Database(path);
182
183
  }
183
184
 
184
- export const SCHEMA_VERSION = 22;
185
+ export const SCHEMA_VERSION = 23;
185
186
 
186
187
  function indexExists(db: DbAdapter, name: string): boolean {
187
188
  return !!db.prepare(
@@ -354,7 +355,8 @@ function initSchema(db: DbAdapter, fileBacked: boolean): void {
354
355
  verification_uat TEXT NOT NULL DEFAULT '',
355
356
  definition_of_done TEXT NOT NULL DEFAULT '[]',
356
357
  requirement_coverage TEXT NOT NULL DEFAULT '',
357
- boundary_map_markdown TEXT NOT NULL DEFAULT ''
358
+ boundary_map_markdown TEXT NOT NULL DEFAULT '',
359
+ sequence INTEGER DEFAULT 0
358
360
  )
359
361
  `);
360
362
 
@@ -1233,6 +1235,17 @@ function migrateSchema(db: DbAdapter): void {
1233
1235
  });
1234
1236
  }
1235
1237
 
1238
+ if (currentVersion < 23) {
1239
+ // v23: milestone queue ordering moves into the canonical DB. The
1240
+ // historical QUEUE-ORDER.json file remains a projection, but runtime
1241
+ // derivation must not read it as authoritative state.
1242
+ ensureColumn(db, "milestones", "sequence", "ALTER TABLE milestones ADD COLUMN sequence INTEGER DEFAULT 0");
1243
+ db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
1244
+ ":version": 23,
1245
+ ":applied_at": new Date().toISOString(),
1246
+ });
1247
+ }
1248
+
1236
1249
  db.exec("COMMIT");
1237
1250
  } catch (err) {
1238
1251
  db.exec("ROLLBACK");
@@ -1247,6 +1260,182 @@ let _exitHandlerRegistered = false;
1247
1260
  let _dbOpenAttempted = false;
1248
1261
  let _lastDbError: Error | null = null;
1249
1262
  let _lastDbPhase: "open" | "initSchema" | "vacuum-recovery" | null = null;
1263
+ /**
1264
+ * Identity key of the workspace whose connection is currently active
1265
+ * (currentDb). Set by openDatabaseByWorkspace(); null when the active
1266
+ * connection was opened via the legacy openDatabase(path) path.
1267
+ */
1268
+ let _currentIdentityKey: string | null = null;
1269
+
1270
+ /**
1271
+ * Workspace-scoped connection cache.
1272
+ * Key: GsdWorkspace.identityKey (realpath-normalized project root).
1273
+ * Value: the DB path and open adapter for that workspace.
1274
+ *
1275
+ * Sibling worktrees of the same project share the same identityKey (set by
1276
+ * createWorkspace) and therefore reuse the same cached connection, preserving
1277
+ * shared-WAL semantics. Different projects get distinct cache entries.
1278
+ *
1279
+ * NOTE: Only one connection is "active" at a time (currentDb/currentPath).
1280
+ * The cache allows fast re-activation of a previously opened connection when
1281
+ * callers switch between known workspaces via openDatabaseByWorkspace().
1282
+ */
1283
+ const _dbCache = new Map<string, { dbPath: string; db: DbAdapter }>();
1284
+
1285
+ /** Test helper: expose the internal cache for inspection. Not for production use. */
1286
+ export function _getDbCache(): ReadonlyMap<string, { dbPath: string; db: DbAdapter }> {
1287
+ return _dbCache;
1288
+ }
1289
+
1290
+ /**
1291
+ * Close and evict every entry in the workspace connection cache, then call
1292
+ * closeDatabase() to close the active connection.
1293
+ *
1294
+ * Use this for test teardown or process-shutdown paths where every open
1295
+ * connection must be flushed. Normal callers should use closeDatabase() or
1296
+ * closeDatabaseByWorkspace() instead.
1297
+ */
1298
+ export function closeAllDatabases(): void {
1299
+ // Close all non-active cached connections first.
1300
+ for (const [key, entry] of _dbCache) {
1301
+ if (entry.db === currentDb) continue; // handled by closeDatabase() below
1302
+ _dbCache.delete(key);
1303
+ try { entry.db.exec("PRAGMA wal_checkpoint(TRUNCATE)"); } catch { /* best-effort */ }
1304
+ try { entry.db.exec("PRAGMA incremental_vacuum(64)"); } catch { /* best-effort */ }
1305
+ try { entry.db.close(); } catch { /* best-effort */ }
1306
+ }
1307
+ closeDatabase();
1308
+ }
1309
+
1310
+ /**
1311
+ * Open (or reuse) the database connection scoped to the given workspace.
1312
+ *
1313
+ * Uses workspace.identityKey as the cache key, so sibling worktrees of the
1314
+ * same project resolve to the same connection. On a cache hit the existing
1315
+ * adapter is reactivated as the current connection without re-opening the
1316
+ * file. On a cache miss, delegates to openDatabase() for the full
1317
+ * open + schema-init + migration flow, then caches the result.
1318
+ *
1319
+ * When switching to a different workspace, the previously active connection
1320
+ * is preserved in the cache (not closed), so callers can switch back to it
1321
+ * cheaply via a subsequent openDatabaseByWorkspace() call.
1322
+ *
1323
+ * @param workspace A GsdWorkspace created by createWorkspace().
1324
+ * @returns true if the connection is open and ready, false otherwise.
1325
+ */
1326
+ export function openDatabaseByWorkspace(workspace: GsdWorkspace): boolean {
1327
+ const key = workspace.identityKey;
1328
+ const dbPath = workspace.contract.projectDb;
1329
+
1330
+ const cached = _dbCache.get(key);
1331
+ if (cached) {
1332
+ // Reactivate the cached connection as the current singleton.
1333
+ currentDb = cached.db;
1334
+ currentPath = cached.dbPath;
1335
+ currentPid = process.pid;
1336
+ _dbOpenAttempted = true;
1337
+ _currentIdentityKey = key;
1338
+ return true;
1339
+ }
1340
+
1341
+ // Cache miss — need to open a new connection.
1342
+ //
1343
+ // If there is a currently active workspace connection, stash it in the
1344
+ // cache under its identity key before calling openDatabase(), because
1345
+ // openDatabase() will call closeDatabase() when the path changes (which
1346
+ // would destroy the existing adapter). By nulling out currentDb first,
1347
+ // we prevent openDatabase() from closing the live adapter.
1348
+ let oldDb: typeof currentDb = null;
1349
+ let oldPath: typeof currentPath = null;
1350
+ let oldPid: typeof currentPid = 0;
1351
+ let oldKey: typeof _currentIdentityKey = null;
1352
+
1353
+ if (currentDb !== null && _currentIdentityKey !== null) {
1354
+ // Snapshot the old globals so we can restore them on failure.
1355
+ oldDb = currentDb;
1356
+ oldPath = currentPath;
1357
+ oldPid = currentPid;
1358
+ oldKey = _currentIdentityKey;
1359
+ // Save the current connection so it stays alive in the cache.
1360
+ _dbCache.set(_currentIdentityKey, {
1361
+ dbPath: currentPath!,
1362
+ db: currentDb,
1363
+ });
1364
+ // Detach from globals so openDatabase() opens fresh without closing it.
1365
+ currentDb = null;
1366
+ currentPath = null;
1367
+ currentPid = 0;
1368
+ _currentIdentityKey = null;
1369
+ }
1370
+
1371
+ // Run the full open/schema/migration flow for the new workspace.
1372
+ // openDatabase() can throw on corrupt DB or permission error — catch so we
1373
+ // can restore the previous connection rather than leaving globals null.
1374
+ let opened: boolean;
1375
+ try {
1376
+ opened = openDatabase(dbPath);
1377
+ } catch (err) {
1378
+ // Failed to open the new DB. Restore the previous workspace connection so
1379
+ // the caller's workspace remains active (it is still safe in _dbCache).
1380
+ if (oldDb !== null) {
1381
+ currentDb = oldDb;
1382
+ currentPath = oldPath;
1383
+ currentPid = oldPid;
1384
+ _currentIdentityKey = oldKey;
1385
+ }
1386
+ throw err;
1387
+ }
1388
+ if (opened && currentDb) {
1389
+ _dbCache.set(key, { dbPath, db: currentDb });
1390
+ _currentIdentityKey = key;
1391
+ } else if (!opened && oldDb !== null) {
1392
+ // Restore the previous connection so the caller's workspace remains active.
1393
+ // The failed attempt left no live adapter, so the globals stayed null.
1394
+ currentDb = oldDb;
1395
+ currentPath = oldPath;
1396
+ currentPid = oldPid;
1397
+ _currentIdentityKey = oldKey;
1398
+ }
1399
+ return opened;
1400
+ }
1401
+
1402
+ /**
1403
+ * Open (or reuse) the database connection scoped to the workspace in a
1404
+ * MilestoneScope. Thin delegation to openDatabaseByWorkspace().
1405
+ */
1406
+ export function openDatabaseByScope(scope: MilestoneScope): boolean {
1407
+ return openDatabaseByWorkspace(scope.workspace);
1408
+ }
1409
+
1410
+ /**
1411
+ * Close the database connection for the given workspace and remove it from
1412
+ * the cache. If the workspace's connection is currently active (currentDb),
1413
+ * performs a full closeDatabase() including WAL checkpoint. Otherwise only
1414
+ * removes the cache entry (the adapter was already replaced by a later open).
1415
+ */
1416
+ export function closeDatabaseByWorkspace(workspace: GsdWorkspace): void {
1417
+ const key = workspace.identityKey;
1418
+ const cached = _dbCache.get(key);
1419
+ if (!cached) return;
1420
+
1421
+ _dbCache.delete(key);
1422
+
1423
+ if (currentDb === cached.db) {
1424
+ // This workspace's connection is the active one — full close.
1425
+ closeDatabase();
1426
+ } else {
1427
+ // Connection was displaced by a later open; close the adapter directly.
1428
+ try {
1429
+ cached.db.exec("PRAGMA wal_checkpoint(TRUNCATE)");
1430
+ } catch (e) { logWarning("db", `WAL checkpoint (byWorkspace) failed: ${(e as Error).message}`); }
1431
+ try {
1432
+ cached.db.exec("PRAGMA incremental_vacuum(64)");
1433
+ } catch (e) { logWarning("db", `incremental vacuum (byWorkspace) failed: ${(e as Error).message}`); }
1434
+ try {
1435
+ cached.db.close();
1436
+ } catch (e) { logWarning("db", `database close (byWorkspace) failed: ${(e as Error).message}`); }
1437
+ }
1438
+ }
1250
1439
 
1251
1440
  export function getDbProvider(): ProviderName | null {
1252
1441
  loadProvider();
@@ -1377,6 +1566,13 @@ export function closeDatabase(): void {
1377
1566
  try {
1378
1567
  currentDb.close();
1379
1568
  } catch (e) { logWarning("db", `database close failed: ${(e as Error).message}`); }
1569
+ // If this connection was workspace-tracked, evict it from the cache so
1570
+ // subsequent openDatabaseByWorkspace() calls re-open rather than reactivate
1571
+ // a closed adapter.
1572
+ if (_currentIdentityKey !== null) {
1573
+ _dbCache.delete(_currentIdentityKey);
1574
+ _currentIdentityKey = null;
1575
+ }
1380
1576
  currentDb = null;
1381
1577
  currentPath = null;
1382
1578
  currentPid = 0;
@@ -1602,6 +1798,34 @@ export function getActiveRequirements(): Requirement[] {
1602
1798
  }));
1603
1799
  }
1604
1800
 
1801
+ export function getRequirementCounts(): {
1802
+ active: number;
1803
+ validated: number;
1804
+ deferred: number;
1805
+ outOfScope: number;
1806
+ blocked: number;
1807
+ total: number;
1808
+ } {
1809
+ if (!currentDb) {
1810
+ return { active: 0, validated: 0, deferred: 0, outOfScope: 0, blocked: 0, total: 0 };
1811
+ }
1812
+ const rows = currentDb
1813
+ .prepare("SELECT lower(status) as status, COUNT(*) as count FROM requirements GROUP BY lower(status)")
1814
+ .all();
1815
+ const counts = { active: 0, validated: 0, deferred: 0, outOfScope: 0, blocked: 0, total: 0 };
1816
+ for (const row of rows) {
1817
+ const status = String(row["status"] ?? "");
1818
+ const count = Number(row["count"] ?? 0);
1819
+ counts.total += count;
1820
+ if (status === "active") counts.active += count;
1821
+ else if (status === "validated") counts.validated += count;
1822
+ else if (status === "deferred") counts.deferred += count;
1823
+ else if (status === "out-of-scope" || status === "out_of_scope") counts.outOfScope += count;
1824
+ else if (status === "blocked") counts.blocked += count;
1825
+ }
1826
+ return counts;
1827
+ }
1828
+
1605
1829
  export function getDbOwnerPid(): number {
1606
1830
  return currentPid;
1607
1831
  }
@@ -2469,6 +2693,7 @@ export interface MilestoneRow {
2469
2693
  definition_of_done: string[];
2470
2694
  requirement_coverage: string;
2471
2695
  boundary_map_markdown: string;
2696
+ sequence: number;
2472
2697
  }
2473
2698
 
2474
2699
  function rowToMilestone(row: Record<string, unknown>): MilestoneRow {
@@ -2490,6 +2715,7 @@ function rowToMilestone(row: Record<string, unknown>): MilestoneRow {
2490
2715
  definition_of_done: JSON.parse((row["definition_of_done"] as string) || "[]"),
2491
2716
  requirement_coverage: (row["requirement_coverage"] as string) ?? "",
2492
2717
  boundary_map_markdown: (row["boundary_map_markdown"] as string) ?? "",
2718
+ sequence: Number(row["sequence"] ?? 0),
2493
2719
  };
2494
2720
  }
2495
2721
 
@@ -2517,7 +2743,9 @@ function rowToArtifact(row: Record<string, unknown>): ArtifactRow {
2517
2743
 
2518
2744
  export function getAllMilestones(): MilestoneRow[] {
2519
2745
  if (!currentDb) return [];
2520
- const rows = currentDb.prepare("SELECT * FROM milestones ORDER BY id").all();
2746
+ const rows = currentDb.prepare(
2747
+ "SELECT * FROM milestones ORDER BY CASE WHEN sequence > 0 THEN 0 ELSE 1 END, sequence, id",
2748
+ ).all();
2521
2749
  return rows.map(rowToMilestone);
2522
2750
  }
2523
2751
 
@@ -2528,6 +2756,22 @@ export function getMilestone(id: string): MilestoneRow | null {
2528
2756
  return rowToMilestone(row);
2529
2757
  }
2530
2758
 
2759
+ export function setMilestoneQueueOrder(order: string[]): void {
2760
+ if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2761
+ currentDb.exec("BEGIN IMMEDIATE");
2762
+ try {
2763
+ currentDb.prepare("UPDATE milestones SET sequence = 0").run();
2764
+ const stmt = currentDb.prepare("UPDATE milestones SET sequence = :sequence WHERE id = :id");
2765
+ order.forEach((id, index) => {
2766
+ stmt.run({ ":id": id, ":sequence": index + 1 });
2767
+ });
2768
+ currentDb.exec("COMMIT");
2769
+ } catch (err) {
2770
+ currentDb.exec("ROLLBACK");
2771
+ throw err;
2772
+ }
2773
+ }
2774
+
2531
2775
  /**
2532
2776
  * Update a milestone's status in the database.
2533
2777
  * Used by park/unpark to keep the DB in sync with the filesystem marker.
@@ -2723,6 +2967,8 @@ export function reconcileWorktreeDb(
2723
2967
  // fall through to the main DB's existing value (not a literal default)
2724
2968
  // so reconcile never silently clears state the main tree has recorded.
2725
2969
  const hasDecisionSource = wtInfo.some((col) => col["name"] === "source");
2970
+ const wtMilestoneInfo = adapter.prepare("PRAGMA wt.table_info('milestones')").all();
2971
+ const hasMilestoneSequence = wtMilestoneInfo.some((col) => col["name"] === "sequence");
2726
2972
  const wtSliceInfo = adapter.prepare("PRAGMA wt.table_info('slices')").all();
2727
2973
  const hasIsSketch = wtSliceInfo.some((col) => col["name"] === "is_sketch");
2728
2974
  const hasSketchScope = wtSliceInfo.some((col) => col["name"] === "sketch_scope");
@@ -2796,7 +3042,7 @@ export function reconcileWorktreeDb(
2796
3042
  id, title, status, depends_on, created_at, completed_at,
2797
3043
  vision, success_criteria, key_risks, proof_strategy,
2798
3044
  verification_contract, verification_integration, verification_operational, verification_uat,
2799
- definition_of_done, requirement_coverage, boundary_map_markdown
3045
+ definition_of_done, requirement_coverage, boundary_map_markdown, sequence
2800
3046
  )
2801
3047
  SELECT w.id, w.title,
2802
3048
  CASE
@@ -2814,7 +3060,8 @@ export function reconcileWorktreeDb(
2814
3060
  END,
2815
3061
  w.vision, w.success_criteria, w.key_risks, w.proof_strategy,
2816
3062
  w.verification_contract, w.verification_integration, w.verification_operational, w.verification_uat,
2817
- w.definition_of_done, w.requirement_coverage, w.boundary_map_markdown
3063
+ w.definition_of_done, w.requirement_coverage, w.boundary_map_markdown,
3064
+ ${hasMilestoneSequence ? "COALESCE(w.sequence, 0)" : "COALESCE(m.sequence, 0)"}
2818
3065
  FROM wt.milestones w
2819
3066
  LEFT JOIN milestones m ON m.id = w.id
2820
3067
  `).run());
@@ -3104,6 +3351,20 @@ export function getAssessment(path: string): Record<string, unknown> | null {
3104
3351
  return row ?? null;
3105
3352
  }
3106
3353
 
3354
+ export function getLatestAssessmentByScope(
3355
+ milestoneId: string,
3356
+ scope: string,
3357
+ ): Record<string, unknown> | null {
3358
+ if (!currentDb) return null;
3359
+ const row = currentDb.prepare(
3360
+ `SELECT * FROM assessments
3361
+ WHERE milestone_id = :mid AND scope = :scope
3362
+ ORDER BY created_at DESC
3363
+ LIMIT 1`,
3364
+ ).get({ ":mid": milestoneId, ":scope": scope });
3365
+ return row ?? null;
3366
+ }
3367
+
3107
3368
  // ─── Quality Gates ───────────────────────────────────────────────────────
3108
3369
 
3109
3370
  function rowToGate(row: Record<string, unknown>): GateRow {
@@ -3591,8 +3852,8 @@ export function restoreManifest(manifest: StateManifest): void {
3591
3852
  `INSERT INTO milestones (id, title, status, depends_on, created_at, completed_at,
3592
3853
  vision, success_criteria, key_risks, proof_strategy,
3593
3854
  verification_contract, verification_integration, verification_operational, verification_uat,
3594
- definition_of_done, requirement_coverage, boundary_map_markdown)
3595
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
3855
+ definition_of_done, requirement_coverage, boundary_map_markdown, sequence)
3856
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
3596
3857
  );
3597
3858
  for (const m of manifest.milestones) {
3598
3859
  msStmt.run(
@@ -3601,7 +3862,7 @@ export function restoreManifest(manifest: StateManifest): void {
3601
3862
  m.vision, JSON.stringify(m.success_criteria), JSON.stringify(m.key_risks),
3602
3863
  JSON.stringify(m.proof_strategy),
3603
3864
  m.verification_contract, m.verification_integration, m.verification_operational, m.verification_uat,
3604
- JSON.stringify(m.definition_of_done), m.requirement_coverage, m.boundary_map_markdown,
3865
+ JSON.stringify(m.definition_of_done), m.requirement_coverage, m.boundary_map_markdown, m.sequence ?? 0,
3605
3866
  );
3606
3867
  }
3607
3868
 
@@ -194,7 +194,7 @@ export async function showQueueAdd(
194
194
 
195
195
  // ── Dispatch the queue prompt ───────────────────────────────────────
196
196
  // Activate the queue phase so the write-gate applies to CONTEXT.md writes
197
- setQueuePhaseActive(true);
197
+ setQueuePhaseActive(true, basePath);
198
198
 
199
199
  const queueInlinedTemplates = inlineTemplate("context", "Context");
200
200
  const prompt = loadPrompt("queue", {