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
@@ -63,20 +63,42 @@ const QUEUE_SAFE_TOOLS = new Set([
63
63
  */
64
64
  const BASH_READ_ONLY_RE = /^\s*(cat|head|tail|less|more|wc|file|stat|du|df|which|type|echo|printf|ls|find|grep|rg|awk|sed\b(?!.*-i)|sort|uniq|diff|comm|tr|cut|tee\s+-a\s+\/dev\/null|git\s+(log|show|diff|status|branch|tag|remote|rev-parse|ls-files|blame|shortlog|describe|stash\s+list|config\s+--get|cat-file)|gh\s+(issue|pr|api|repo|release)\s+(view|list|diff|status|checks)|mkdir\s+-p\s+\.gsd|rtk\s|npm\s+run\s+(test|test:\w+|lint|lint:\w+|typecheck|type-check|type-check:\w+|check|verify|audit|outdated|format:check|ci|validate)\b|npm\s+(ls|list|info|view|show|outdated|audit|explain|doctor|ping|--version|-v)\b|npx\s|tsx\s|node\s+(--print|--version|-v\b)|python[23]?\s+(-c\s+'[^']*'|--version|-V\b|-m\s+(pip\s+show|pip\s+list|site))|pip[23]?\s+(show|list|freeze|check|index\s+versions)\b|jq\s|yq\s|curl\s+(-s\b|--silent\b)(?!\s+[^|>]*\s-[oO]\b)(?!\s+[^|>]*\s--output\b)[^|>]*$|openssl\s+(version|x509|s_client)|env\b|printenv\b|true\b|false\b)/;
65
65
 
66
- const verifiedDepthMilestones = new Set<string>();
67
- const verifiedApprovalGates = new Set<string>();
68
- let activeQueuePhase = false;
66
+ interface InMemoryWriteGateState {
67
+ verifiedDepthMilestones: Set<string>;
68
+ verifiedApprovalGates: Set<string>;
69
+ activeQueuePhase: boolean;
70
+ pendingGateId: string | null;
71
+ }
72
+
73
+ function createEmptyWriteGateState(): InMemoryWriteGateState {
74
+ return {
75
+ verifiedDepthMilestones: new Set<string>(),
76
+ verifiedApprovalGates: new Set<string>(),
77
+ activeQueuePhase: false,
78
+ pendingGateId: null,
79
+ };
80
+ }
81
+
82
+ const writeGateStatesByBasePath = new Map<string, InMemoryWriteGateState>();
83
+
84
+ function writeGateStateKey(basePath: string): string {
85
+ return resolve(basePath);
86
+ }
87
+
88
+ function getWriteGateState(basePath: string = process.cwd()): InMemoryWriteGateState {
89
+ const key = writeGateStateKey(basePath);
90
+ let state = writeGateStatesByBasePath.get(key);
91
+ if (!state) {
92
+ state = createEmptyWriteGateState();
93
+ writeGateStatesByBasePath.set(key, state);
94
+ }
95
+ return state;
96
+ }
69
97
 
70
98
  /**
71
- * Discussion gate enforcement state.
72
- *
73
- * When ask_user_questions is called with a recognized gate question ID,
74
- * we track the pending gate. Until the gate is confirmed (user selects the
75
- * first/recommended option), all non-read-only tool calls are blocked.
76
- * This mechanically prevents the model from rationalizing past failed or
77
- * cancelled gate questions.
99
+ * Discussion gate enforcement state is scoped per basePath so multiple
100
+ * workspaces can coexist in the same process without sharing gate state.
78
101
  */
79
- let pendingGateId: string | null = null;
80
102
 
81
103
  /**
82
104
  * Recognized gate question ID patterns.
@@ -119,25 +141,26 @@ function shouldPersistWriteGateSnapshot(env: NodeJS.ProcessEnv = process.env): b
119
141
  return v !== "0" && v !== "false";
120
142
  }
121
143
 
122
- function writeGateSnapshotPath(basePath: string = process.cwd()): string {
144
+ function writeGateSnapshotPath(basePath: string): string {
123
145
  return join(basePath, ".gsd", "runtime", "write-gate-state.json");
124
146
  }
125
147
 
126
- function currentWriteGateSnapshot(): WriteGateSnapshot {
148
+ function currentWriteGateSnapshot(basePath: string = process.cwd()): WriteGateSnapshot {
149
+ const state = getWriteGateState(basePath);
127
150
  return {
128
- verifiedDepthMilestones: [...verifiedDepthMilestones].sort(),
129
- verifiedApprovalGates: [...verifiedApprovalGates].sort(),
130
- activeQueuePhase,
131
- pendingGateId,
151
+ verifiedDepthMilestones: [...state.verifiedDepthMilestones].sort(),
152
+ verifiedApprovalGates: [...state.verifiedApprovalGates].sort(),
153
+ activeQueuePhase: state.activeQueuePhase,
154
+ pendingGateId: state.pendingGateId,
132
155
  };
133
156
  }
134
157
 
135
- function persistWriteGateSnapshot(basePath: string = process.cwd()): void {
158
+ function persistWriteGateSnapshot(basePath: string): void {
136
159
  if (!shouldPersistWriteGateSnapshot()) return;
137
160
  const path = writeGateSnapshotPath(basePath);
138
161
  mkdirSync(join(basePath, ".gsd", "runtime"), { recursive: true });
139
162
  const tempPath = `${path}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`;
140
- writeFileSync(tempPath, JSON.stringify(currentWriteGateSnapshot(), null, 2), "utf-8");
163
+ writeFileSync(tempPath, JSON.stringify(currentWriteGateSnapshot(basePath), null, 2), "utf-8");
141
164
  try {
142
165
  renameSync(tempPath, path);
143
166
  } catch (err: unknown) {
@@ -152,7 +175,7 @@ function persistWriteGateSnapshot(basePath: string = process.cwd()): void {
152
175
  }
153
176
  }
154
177
 
155
- function clearPersistedWriteGateSnapshot(basePath: string = process.cwd()): void {
178
+ function clearPersistedWriteGateSnapshot(basePath: string): void {
156
179
  if (!shouldPersistWriteGateSnapshot()) return;
157
180
  const path = writeGateSnapshotPath(basePath);
158
181
  try {
@@ -185,32 +208,35 @@ const EMPTY_SNAPSHOT: WriteGateSnapshot = {
185
208
  pendingGateId: null,
186
209
  };
187
210
 
188
- export function loadWriteGateSnapshot(basePath: string = process.cwd()): WriteGateSnapshot {
211
+ export function loadWriteGateSnapshot(basePath: string): WriteGateSnapshot {
189
212
  const path = writeGateSnapshotPath(basePath);
190
213
  if (!existsSync(path)) {
191
214
  // When persist mode is active and the file has been deleted, treat it as a
192
215
  // full state reset so deleting the file clears the HARD BLOCK gate.
193
216
  // In non-persist mode the file is never written, so fall back to in-memory.
194
217
  if (shouldPersistWriteGateSnapshot()) return EMPTY_SNAPSHOT;
195
- return currentWriteGateSnapshot();
218
+ return currentWriteGateSnapshot(basePath);
196
219
  }
197
220
  try {
198
221
  return normalizeWriteGateSnapshot(JSON.parse(readFileSync(path, "utf-8")));
199
222
  } catch {
200
- return currentWriteGateSnapshot();
223
+ return currentWriteGateSnapshot(basePath);
201
224
  }
202
225
  }
203
226
 
204
- export function isDepthVerified(): boolean {
205
- return verifiedDepthMilestones.size > 0;
227
+ export function isDepthVerified(basePath: string = process.cwd()): boolean {
228
+ return getWriteGateState(basePath).verifiedDepthMilestones.size > 0;
206
229
  }
207
230
 
208
231
  /**
209
232
  * Check whether a specific milestone has passed depth verification.
210
233
  */
211
- export function isMilestoneDepthVerified(milestoneId: string | null | undefined): boolean {
234
+ export function isMilestoneDepthVerified(
235
+ milestoneId: string | null | undefined,
236
+ basePath: string = process.cwd(),
237
+ ): boolean {
212
238
  if (!milestoneId) return false;
213
- return verifiedDepthMilestones.has(milestoneId);
239
+ return getWriteGateState(basePath).verifiedDepthMilestones.has(milestoneId);
214
240
  }
215
241
 
216
242
  export function isMilestoneDepthVerifiedInSnapshot(
@@ -221,39 +247,37 @@ export function isMilestoneDepthVerifiedInSnapshot(
221
247
  return snapshot.verifiedDepthMilestones.includes(milestoneId);
222
248
  }
223
249
 
224
- export function isQueuePhaseActive(): boolean {
225
- return activeQueuePhase;
250
+ export function isQueuePhaseActive(basePath: string = process.cwd()): boolean {
251
+ return getWriteGateState(basePath).activeQueuePhase;
226
252
  }
227
253
 
228
- export function setQueuePhaseActive(active: boolean): void {
229
- activeQueuePhase = active;
230
- persistWriteGateSnapshot();
254
+ export function setQueuePhaseActive(active: boolean, basePath: string): void {
255
+ getWriteGateState(basePath).activeQueuePhase = active;
256
+ persistWriteGateSnapshot(basePath);
231
257
  }
232
258
 
233
- export function resetWriteGateState(): void {
234
- verifiedDepthMilestones.clear();
235
- verifiedApprovalGates.clear();
236
- pendingGateId = null;
237
- persistWriteGateSnapshot();
259
+ export function resetWriteGateState(basePath: string): void {
260
+ const state = getWriteGateState(basePath);
261
+ state.verifiedDepthMilestones.clear();
262
+ state.verifiedApprovalGates.clear();
263
+ state.pendingGateId = null;
264
+ persistWriteGateSnapshot(basePath);
238
265
  }
239
266
 
240
- export function clearDiscussionFlowState(): void {
241
- verifiedDepthMilestones.clear();
242
- verifiedApprovalGates.clear();
243
- activeQueuePhase = false;
244
- pendingGateId = null;
245
- clearPersistedWriteGateSnapshot();
267
+ export function clearDiscussionFlowState(basePath: string): void {
268
+ writeGateStatesByBasePath.delete(writeGateStateKey(basePath));
269
+ clearPersistedWriteGateSnapshot(basePath);
246
270
  }
247
271
 
248
272
  export function markDepthVerified(milestoneId?: string | null, basePath: string = process.cwd()): void {
249
273
  if (!milestoneId) return;
250
- verifiedDepthMilestones.add(milestoneId);
274
+ getWriteGateState(basePath).verifiedDepthMilestones.add(milestoneId);
251
275
  persistWriteGateSnapshot(basePath);
252
276
  }
253
277
 
254
278
  export function markApprovalGateVerified(gateId?: string | null, basePath: string = process.cwd()): void {
255
279
  if (!gateId) return;
256
- verifiedApprovalGates.add(gateId);
280
+ getWriteGateState(basePath).verifiedApprovalGates.add(gateId);
257
281
  persistWriteGateSnapshot(basePath);
258
282
  }
259
283
 
@@ -292,27 +316,28 @@ function extractContextMilestoneId(inputPath: string): string | null {
292
316
  /**
293
317
  * Mark a gate as pending (called when ask_user_questions is invoked with a gate ID).
294
318
  */
295
- export function setPendingGate(gateId: string): void {
296
- pendingGateId = gateId;
297
- verifiedApprovalGates.delete(gateId);
319
+ export function setPendingGate(gateId: string, basePath: string): void {
320
+ const state = getWriteGateState(basePath);
321
+ state.pendingGateId = gateId;
322
+ state.verifiedApprovalGates.delete(gateId);
298
323
  const milestoneId = extractDepthVerificationMilestoneId(gateId);
299
- if (milestoneId) verifiedDepthMilestones.delete(milestoneId);
300
- persistWriteGateSnapshot();
324
+ if (milestoneId) state.verifiedDepthMilestones.delete(milestoneId);
325
+ persistWriteGateSnapshot(basePath);
301
326
  }
302
327
 
303
328
  /**
304
329
  * Clear the pending gate (called when the user confirms).
305
330
  */
306
- export function clearPendingGate(): void {
307
- pendingGateId = null;
308
- persistWriteGateSnapshot();
331
+ export function clearPendingGate(basePath: string): void {
332
+ getWriteGateState(basePath).pendingGateId = null;
333
+ persistWriteGateSnapshot(basePath);
309
334
  }
310
335
 
311
336
  /**
312
337
  * Get the currently pending gate, if any.
313
338
  */
314
- export function getPendingGate(): string | null {
315
- return pendingGateId;
339
+ export function getPendingGate(basePath: string = process.cwd()): string | null {
340
+ return getWriteGateState(basePath).pendingGateId;
316
341
  }
317
342
 
318
343
  /**
@@ -16,7 +16,7 @@ import {
16
16
  } from "./codebase-generator.js";
17
17
  import { loadEffectiveGSDPreferences } from "./preferences.js";
18
18
  import type { CodebaseMapOptions } from "./codebase-generator.js";
19
- import { projectRoot } from "./commands/context.js";
19
+ import { currentDirectoryRoot } from "./commands/context.js";
20
20
 
21
21
  const USAGE =
22
22
  "Usage: /gsd codebase [generate|update|stats]\n\n" +
@@ -37,7 +37,7 @@ export async function handleCodebase(
37
37
  ctx: ExtensionCommandContext,
38
38
  _pi: ExtensionAPI,
39
39
  ): Promise<void> {
40
- const basePath = projectRoot();
40
+ const basePath = currentDirectoryRoot();
41
41
  const parts = args.trim().split(/\s+/);
42
42
  const sub = parts[0] ?? "";
43
43
 
@@ -24,7 +24,7 @@ import {
24
24
  } from "./doctor.js";
25
25
  import { isAutoActive, checkRemoteAutoSession } from "./auto.js";
26
26
  import { getAutoWorktreePath } from "./auto-worktree.js";
27
- import { projectRoot } from "./commands/context.js";
27
+ import { currentDirectoryRoot, projectRoot } from "./commands/context.js";
28
28
  import { loadPrompt } from "./prompt-loader.js";
29
29
 
30
30
  const UPDATE_REGISTRY_URL = "https://registry.npmjs.org/gsd-pi/latest";
@@ -203,7 +203,7 @@ export async function handleCapture(args: string, ctx: ExtensionCommandContext):
203
203
  return;
204
204
  }
205
205
 
206
- const basePath = projectRoot();
206
+ const basePath = currentDirectoryRoot();
207
207
 
208
208
  // Ensure .gsd/ exists — capture should work even without a milestone
209
209
  const gsdDir = gsdRoot(basePath);
@@ -270,7 +270,7 @@ export async function handleTriage(ctx: ExtensionCommandContext, pi: ExtensionAP
270
270
  }
271
271
 
272
272
  export async function handleSteer(change: string, ctx: ExtensionCommandContext, pi: ExtensionAPI): Promise<void> {
273
- const basePath = projectRoot();
273
+ const basePath = currentDirectoryRoot();
274
274
  const state = await deriveState(basePath);
275
275
  const mid = state.activeMilestone?.id ?? "none";
276
276
  const sid = state.activeSlice?.id ?? "none";
@@ -343,7 +343,7 @@ export async function handleKnowledge(args: string, ctx: ExtensionCommandContext
343
343
  }
344
344
 
345
345
  const type = typeArg as "rule" | "pattern" | "lesson";
346
- const basePath = projectRoot();
346
+ const basePath = currentDirectoryRoot();
347
347
  const state = await deriveState(basePath);
348
348
  const scope = state.activeMilestone?.id
349
349
  ? `${state.activeMilestone.id}${state.activeSlice ? `/${state.activeSlice.id}` : ""}`
@@ -372,7 +372,7 @@ Examples:
372
372
  }
373
373
 
374
374
  const [hookName, unitType, unitId] = parts;
375
- const basePath = projectRoot();
375
+ const basePath = currentDirectoryRoot();
376
376
 
377
377
  // Import the hook trigger function
378
378
  const { triggerHookManually, formatHookStatus, getHookStatus } = await import("./post-unit-hooks.js");
@@ -15,7 +15,7 @@ import { existsSync, readdirSync, readFileSync, statSync, unlinkSync } from "nod
15
15
  import { join } from "node:path";
16
16
  import { gsdRoot } from "./paths.js";
17
17
  import { loadJsonFileOrNull } from "./json-persistence.js";
18
- import { projectRoot } from "./commands/context.js";
18
+ import { currentDirectoryRoot } from "./commands/context.js";
19
19
 
20
20
  // ─── Types ──────────────────────────────────────────────────────────────────
21
21
 
@@ -244,7 +244,7 @@ function summarizeDebugLog(filePath: string): {
244
244
  // ─── Main Handler ───────────────────────────────────────────────────────────
245
245
 
246
246
  export async function handleLogs(args: string, ctx: ExtensionCommandContext): Promise<void> {
247
- const basePath = projectRoot();
247
+ const basePath = currentDirectoryRoot();
248
248
  const parts = args.trim().split(/\s+/).filter(Boolean);
249
249
  const subCmd = parts[0] ?? "";
250
250
 
@@ -20,7 +20,7 @@ import { existsSync, mkdirSync } from "node:fs";
20
20
  import { join, relative } from "node:path";
21
21
 
22
22
  import { loadPrompt } from "./prompt-loader.js";
23
- import { projectRoot } from "./commands/context.js";
23
+ import { currentDirectoryRoot } from "./commands/context.js";
24
24
 
25
25
  // ─── Constants ────────────────────────────────────────────────────────────────
26
26
 
@@ -87,7 +87,7 @@ export async function handleScan(
87
87
  ctx: ExtensionCommandContext,
88
88
  pi: ExtensionAPI,
89
89
  ): Promise<void> {
90
- const basePath = projectRoot();
90
+ const basePath = currentDirectoryRoot();
91
91
  const { focus } = parseScanArgs(args);
92
92
  const outputDir = join(basePath, ".gsd", "codebase");
93
93
  const outputPaths = buildScanOutputPaths(focus, basePath);
@@ -17,7 +17,7 @@ import { getLedger, getProjectTotals, aggregateByModel, formatCost, formatTokenC
17
17
  import { nativeGetCurrentBranch, nativeDetectMainBranch } from "./native-git-bridge.js";
18
18
  import { formatDuration } from "../shared/format-utils.js";
19
19
  import { parseEvalReviewFrontmatter, type Verdict } from "./eval-review-schema.js";
20
- import { projectRoot } from "./commands/context.js";
20
+ import { currentDirectoryRoot } from "./commands/context.js";
21
21
 
22
22
  function git(basePath: string, args: readonly string[]): string {
23
23
  return execFileSync("git", args, { cwd: basePath, encoding: "utf-8" }).trim();
@@ -223,7 +223,7 @@ export async function handleShip(
223
223
  ctx: ExtensionCommandContext,
224
224
  _pi: ExtensionAPI,
225
225
  ): Promise<void> {
226
- const basePath = projectRoot();
226
+ const basePath = currentDirectoryRoot();
227
227
  const dryRun = args.includes("--dry-run");
228
228
  const draft = args.includes("--draft");
229
229
  const force = args.includes("--force");
@@ -23,7 +23,7 @@ import { createGitService, runGit } from "./git-service.js";
23
23
  import { isAutoActive, isAutoPaused } from "./auto.js";
24
24
  import { getErrorMessage } from "./error-utils.js";
25
25
  import { resolvePlugin, type WorkflowPlugin } from "./workflow-plugins.js";
26
- import { projectRoot } from "./commands/context.js";
26
+ import { currentDirectoryRoot } from "./commands/context.js";
27
27
 
28
28
  // ─── Helpers ─────────────────────────────────────────────────────────────────
29
29
 
@@ -197,7 +197,7 @@ export async function handleStart(
197
197
  // ─── Resume detection ───────────────────────────────────────────────────
198
198
  // /gsd start --resume or /gsd start resume → resume in-progress workflow
199
199
  if (trimmed === "--resume" || trimmed === "resume") {
200
- const basePath = projectRoot();
200
+ const basePath = currentDirectoryRoot();
201
201
  const inProgress = findInProgressWorkflows(basePath);
202
202
  if (inProgress.length === 0) {
203
203
  ctx.ui.notify("No in-progress workflows found.", "info");
@@ -248,7 +248,7 @@ export async function handleStart(
248
248
 
249
249
  // Show in-progress workflows when /gsd start is called with no args
250
250
  if (!trimmed) {
251
- const basePath = projectRoot();
251
+ const basePath = currentDirectoryRoot();
252
252
  const inProgress = findInProgressWorkflows(basePath);
253
253
  if (inProgress.length > 0) {
254
254
  const wf = inProgress[0];
@@ -347,7 +347,7 @@ export async function handleStart(
347
347
 
348
348
  const templateId = match.id;
349
349
  const template = match.template;
350
- const basePath = projectRoot();
350
+ const basePath = currentDirectoryRoot();
351
351
  const date = new Date().toISOString().split("T")[0];
352
352
 
353
353
  // Load the workflow template content — prefer a project/global plugin
@@ -582,7 +582,7 @@ export function dispatchMarkdownPhasePlugin(
582
582
  }
583
583
 
584
584
  const templateId = plugin.name;
585
- const basePath = projectRoot();
585
+ const basePath = currentDirectoryRoot();
586
586
  const date = new Date().toISOString().split("T")[0];
587
587
  let workflowContent: string;
588
588
  try {