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
@@ -1,10 +1,13 @@
1
1
  /**
2
- * GSD2 — regression test for #5187: gsdRoot() must refuse to use the global
3
- * GSD home (~/.gsd) as a project .gsd directory when basePath resolves to
4
- * $HOME. Paths under ~/.gsd/projects/<hash>/ remain valid.
2
+ * GSD2 — regression tests for #5187 and git-root anchor guard:
5
3
  *
6
- * Before the fix, gsdRoot(homedir()) returned ~/.gsd silently and downstream
7
- * writes polluted the user's global state directory. After the fix, it throws.
4
+ * #5187: gsdRoot() must refuse to use the global GSD home (~/.gsd) as a
5
+ * project .gsd directory when basePath resolves to $HOME. Paths under
6
+ * ~/.gsd/projects/<hash>/ remain valid.
7
+ *
8
+ * git-root anchor guard: when $HOME is itself a git repo and ~/.gsd exists,
9
+ * gsdRoot() must NOT return ~/.gsd for a subdir basePath like ~/projects/foo.
10
+ * It should fall through to step 4 (creation fallback) instead.
8
11
  */
9
12
 
10
13
  import { describe, test, beforeEach, afterEach } from 'node:test';
@@ -12,6 +15,7 @@ import assert from 'node:assert/strict';
12
15
  import { mkdtempSync, mkdirSync, rmSync, realpathSync } from 'node:fs';
13
16
  import { tmpdir } from 'node:os';
14
17
  import { join } from 'node:path';
18
+ import { spawnSync } from 'node:child_process';
15
19
 
16
20
  import { gsdRoot, _clearGsdRootCache } from '../paths.ts';
17
21
 
@@ -84,3 +88,62 @@ describe('gsdRoot() refuses ~/.gsd as project state when basePath is $HOME (#518
84
88
  }
85
89
  });
86
90
  });
91
+
92
+ describe('git-root anchor guard: subdir basePath must not resolve to ~/.gsd', () => {
93
+ let fakeHome: string;
94
+ let subDir: string;
95
+ let savedHome: string | undefined;
96
+ let savedUserProfile: string | undefined;
97
+ let savedGsdHome: string | undefined;
98
+
99
+ beforeEach(() => {
100
+ // Create a tmpdir that will act as both $HOME and a git repo root.
101
+ fakeHome = realpathSync(mkdtempSync(join(tmpdir(), 'gsd-anchor-guard-')));
102
+ // Init a bare-minimum git repo so git rev-parse --show-toplevel returns fakeHome.
103
+ spawnSync('git', ['init', fakeHome], { encoding: 'utf-8' });
104
+ // Create ~/.gsd (the global home that must NOT be used for project subdirs).
105
+ mkdirSync(join(fakeHome, '.gsd'), { recursive: true });
106
+ // Create a subdir inside the git repo — this is the project basePath.
107
+ subDir = join(fakeHome, 'projects', 'foo');
108
+ mkdirSync(subDir, { recursive: true });
109
+
110
+ savedHome = process.env.HOME;
111
+ savedUserProfile = process.env.USERPROFILE;
112
+ savedGsdHome = process.env.GSD_HOME;
113
+
114
+ process.env.HOME = fakeHome;
115
+ process.env.USERPROFILE = fakeHome;
116
+ delete process.env.GSD_HOME;
117
+
118
+ _clearGsdRootCache();
119
+ });
120
+
121
+ afterEach(() => {
122
+ if (savedHome === undefined) delete process.env.HOME;
123
+ else process.env.HOME = savedHome;
124
+ if (savedUserProfile === undefined) delete process.env.USERPROFILE;
125
+ else process.env.USERPROFILE = savedUserProfile;
126
+ if (savedGsdHome === undefined) delete process.env.GSD_HOME;
127
+ else process.env.GSD_HOME = savedGsdHome;
128
+
129
+ _clearGsdRootCache();
130
+ rmSync(fakeHome, { recursive: true, force: true });
131
+ });
132
+
133
+ test('does NOT return ~/.gsd when $HOME is a git repo and basePath is a subdir', () => {
134
+ // fakeHome IS the git root AND $HOME, so git rev-parse returns fakeHome,
135
+ // and ~/.gsd (fakeHome/.gsd) exists. The guard must skip that candidate
136
+ // and fall through to the creation fallback: subDir/.gsd.
137
+ const result = gsdRoot(subDir);
138
+ assert.notEqual(
139
+ result,
140
+ join(fakeHome, '.gsd'),
141
+ 'gsdRoot must not return ~/.gsd for a subdir basePath',
142
+ );
143
+ assert.equal(
144
+ result,
145
+ join(subDir, '.gsd'),
146
+ 'gsdRoot should fall through to the creation fallback for a subdir',
147
+ );
148
+ });
149
+ });
@@ -1,9 +1,10 @@
1
1
  /**
2
2
  * gsdroot-worktree-detection.test.ts — Regression test for #2594.
3
3
  *
4
- * gsdRoot() must return the worktree's own .gsd directory when the basePath
5
- * is inside a .gsd/worktrees/<name>/ structure, not walk up to the project
6
- * root's .gsd via the git-root probe.
4
+ * gsdRoot() must return the canonical project .gsd directory when basePath
5
+ * is inside a .gsd/worktrees/<name>/ structure. Worktree-local .gsd folders
6
+ * are legacy projection roots only; runtime state is DB-authoritative at the
7
+ * project .gsd.
7
8
  *
8
9
  * The bug: when a git worktree lives at /project/.gsd/worktrees/M008/,
9
10
  * probeGsdRoot() runs `git rev-parse --show-toplevel` which can return the
@@ -20,7 +21,7 @@ import { mkdtempSync, realpathSync } from "node:fs";
20
21
  import { tmpdir } from "node:os";
21
22
  import { spawnSync } from "node:child_process";
22
23
 
23
- import { gsdRoot, _clearGsdRootCache } from "../paths.ts";
24
+ import { gsdRoot, resolveGsdPathContract, _clearGsdRootCache } from "../paths.ts";
24
25
 
25
26
  describe("gsdRoot() worktree detection (#2594)", () => {
26
27
  let projectRoot: string;
@@ -61,7 +62,7 @@ describe("gsdRoot() worktree detection (#2594)", () => {
61
62
  rmSync(projectRoot, { recursive: true, force: true });
62
63
  });
63
64
 
64
- test("returns worktree .gsd when basePath is a worktree with its own .gsd (fast path)", () => {
65
+ test("returns project .gsd when basePath is a worktree with its own .gsd", () => {
65
66
  // Simulates a worktree that already had copyPlanningArtifacts() run,
66
67
  // so it has its own .gsd/ directory.
67
68
  const worktreeBase = join(projectGsd, "worktrees", "M008");
@@ -71,41 +72,26 @@ describe("gsdRoot() worktree detection (#2594)", () => {
71
72
  const result = gsdRoot(worktreeBase);
72
73
  assert.equal(
73
74
  result,
74
- worktreeGsd,
75
- `Expected worktree .gsd (${worktreeGsd}), got ${result}. ` +
76
- "gsdRoot() should use the fast path for an existing worktree .gsd.",
75
+ projectGsd,
76
+ `Expected canonical project .gsd (${projectGsd}), got ${result}.`,
77
77
  );
78
+ assert.equal(resolveGsdPathContract(worktreeBase).worktreeGsd, worktreeGsd);
78
79
  });
79
80
 
80
- test("returns worktree .gsd path (not project root .gsd) when worktree .gsd does not exist yet", () => {
81
- // This is the core #2594 bug: the worktree directory exists but its .gsd
82
- // subdirectory hasn't been created yet. Without the fix, probeGsdRoot()
83
- // walks up from the worktree path, finds /project/.gsd, and returns it.
84
- // With the fix, it detects the .gsd/worktrees/<name>/ pattern and returns
85
- // the worktree-local .gsd path as the creation fallback.
81
+ test("returns project .gsd when worktree .gsd does not exist yet", () => {
86
82
  const worktreeBase = join(projectGsd, "worktrees", "M008");
87
83
  mkdirSync(worktreeBase, { recursive: true });
88
84
  // NOTE: no .gsd/ inside worktreeBase
89
85
 
90
86
  const result = gsdRoot(worktreeBase);
91
- const expected = join(worktreeBase, ".gsd");
92
-
93
- // Without the fix, this returns projectGsd (/project/.gsd) because the
94
- // walk-up from worktreeBase finds it. With the fix, it returns the
95
- // worktree-local path.
96
- assert.notEqual(
97
- result,
98
- projectGsd,
99
- "gsdRoot() must NOT return the project root .gsd when basePath is inside .gsd/worktrees/",
100
- );
101
87
  assert.equal(
102
88
  result,
103
- expected,
104
- `Expected worktree-local .gsd (${expected}), got ${result}.`,
89
+ projectGsd,
90
+ `Expected canonical project .gsd (${projectGsd}), got ${result}.`,
105
91
  );
106
92
  });
107
93
 
108
- test("returns worktree .gsd when basePath is a real git worktree inside .gsd/worktrees/", () => {
94
+ test("returns project .gsd when basePath is a real git worktree inside .gsd/worktrees/", () => {
109
95
  // Create a real git worktree at .gsd/worktrees/M010
110
96
  const worktreeName = "M010";
111
97
  const worktreeBase = join(projectGsd, "worktrees", worktreeName);
@@ -125,17 +111,10 @@ describe("gsdRoot() worktree detection (#2594)", () => {
125
111
 
126
112
  // The real git worktree exists at worktreeBase but has NO .gsd/ subdir yet
127
113
  const gsdResult = gsdRoot(worktreeBase);
128
- const expected = join(worktreeBase, ".gsd");
129
-
130
- assert.notEqual(
131
- gsdResult,
132
- projectGsd,
133
- "gsdRoot() must NOT escape to project root .gsd from inside a git worktree",
134
- );
135
114
  assert.equal(
136
115
  gsdResult,
137
- expected,
138
- `Expected worktree-local .gsd (${expected}), got ${gsdResult}`,
116
+ projectGsd,
117
+ `Expected canonical project .gsd (${projectGsd}), got ${gsdResult}`,
139
118
  );
140
119
 
141
120
  // Cleanup worktree
@@ -86,8 +86,8 @@ describe("guided-flow → auto-prompts consolidation (#5183)", () => {
86
86
  assert.ok(prompt.includes(TID), "must mention task id");
87
87
  assert.ok(prompt.includes(T_TITLE), "must mention task title");
88
88
  assert.ok(
89
- prompt.includes("gsd_complete_task"),
90
- "must instruct calling the canonical gsd_complete_task tool",
89
+ prompt.includes("gsd_task_complete"),
90
+ "must instruct calling the canonical gsd_task_complete tool",
91
91
  );
92
92
  assert.ok(
93
93
  prompt.includes(base),
@@ -110,8 +110,8 @@ describe("guided-flow → auto-prompts consolidation (#5183)", () => {
110
110
  assert.ok(prompt.includes(SID), "must mention slice id");
111
111
  assert.ok(prompt.includes(S_TITLE), "must mention slice title");
112
112
  assert.ok(
113
- prompt.includes("gsd_complete_slice"),
114
- "must instruct calling gsd_complete_slice (was in guided-complete-slice.md)",
113
+ prompt.includes("gsd_slice_complete"),
114
+ "must instruct calling gsd_slice_complete (was in guided-complete-slice.md)",
115
115
  );
116
116
  assert.ok(
117
117
  prompt.includes(base),
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Regression: when /gsd handlers run with cwd inside a worktree, writes must
3
+ * land in the worktree's .gsd/, not the parent project's .gsd/.
4
+ *
5
+ * The fix in 01464a97 replaced `process.cwd()` with `projectRoot()` to block
6
+ * $HOME pollution, but `projectRoot()` walks UP from a worktree path to the
7
+ * outer project root — breaking the worktree isolation invariant agents rely
8
+ * on. The corrected pattern: handlers use `currentDirectoryRoot()`, which
9
+ * preserves the active cwd (worktree or project) and still throws when cwd
10
+ * is $HOME.
11
+ */
12
+ import { describe, test, beforeEach, afterEach } from "node:test";
13
+ import assert from "node:assert/strict";
14
+ import { mkdtempSync, mkdirSync, rmSync, realpathSync } from "node:fs";
15
+ import { tmpdir, homedir } from "node:os";
16
+ import { join } from "node:path";
17
+
18
+ import { currentDirectoryRoot, projectRoot, withCommandCwd, GSDNoProjectError } from "../commands/context.ts";
19
+
20
+ describe("handlers preserve worktree cwd via currentDirectoryRoot()", () => {
21
+ let project: string;
22
+ let worktree: string;
23
+
24
+ beforeEach(() => {
25
+ project = realpathSync(mkdtempSync(join(tmpdir(), "gsd-wt-iso-")));
26
+ mkdirSync(join(project, ".gsd"), { recursive: true });
27
+ mkdirSync(join(project, ".git"), { recursive: true });
28
+ worktree = join(project, ".gsd", "worktrees", "M001");
29
+ mkdirSync(join(worktree, ".gsd"), { recursive: true });
30
+ });
31
+
32
+ afterEach(() => {
33
+ rmSync(project, { recursive: true, force: true });
34
+ });
35
+
36
+ test("currentDirectoryRoot() returns the worktree path when cwd is the worktree", async () => {
37
+ const resolved = await withCommandCwd(worktree, async () => currentDirectoryRoot());
38
+ assert.equal(resolved, worktree, "must keep worktree path so writes isolate");
39
+ });
40
+
41
+ test("projectRoot() walks UP from worktree to the project root (legacy semantics)", async () => {
42
+ const resolved = await withCommandCwd(worktree, async () => projectRoot());
43
+ assert.equal(resolved, project, "projectRoot intentionally returns project, not worktree");
44
+ });
45
+
46
+ test("currentDirectoryRoot() throws GSDNoProjectError when cwd is $HOME", async () => {
47
+ await assert.rejects(
48
+ withCommandCwd(homedir(), async () => currentDirectoryRoot()),
49
+ (err: unknown) => err instanceof GSDNoProjectError,
50
+ );
51
+ });
52
+
53
+ test("currentDirectoryRoot() returns project root when cwd is project root", async () => {
54
+ const resolved = await withCommandCwd(project, async () => currentDirectoryRoot());
55
+ assert.equal(resolved, project);
56
+ });
57
+ });
@@ -473,26 +473,26 @@ test("mergeAllCompleted — by-completion order respects startedAt", async () =>
473
473
  });
474
474
 
475
475
  // ═══════════════════════════════════════════════════════════════════════════════
476
- // Bug #2812 — determineMergeOrder should use worktree DB as source of truth
476
+ // Bug #2812 — determineMergeOrder should use DB state as source of truth
477
477
  // ═══════════════════════════════════════════════════════════════════════════════
478
478
 
479
- /** Set up a worktree DB with a milestone marked complete */
480
- function setupWorktreeDb(basePath: string, mid: string): void {
481
- const wtGsdDir = join(basePath, ".gsd", "worktrees", mid, ".gsd");
482
- mkdirSync(wtGsdDir, { recursive: true });
483
- const dbPath = join(wtGsdDir, "gsd.db");
479
+ /** Set up canonical DB with a milestone marked complete and a worktree marker dir */
480
+ function setupCanonicalDbWithWorktree(basePath: string, mid: string): void {
481
+ mkdirSync(join(basePath, ".gsd", "worktrees", mid), { recursive: true });
482
+ mkdirSync(join(basePath, ".gsd"), { recursive: true });
483
+ const dbPath = join(basePath, ".gsd", "gsd.db");
484
484
  openDatabase(dbPath);
485
485
  insertMilestone({ id: mid, title: `Milestone ${mid}`, status: "complete" });
486
486
  updateMilestoneStatus(mid, "complete", new Date().toISOString());
487
487
  closeDatabase();
488
488
  }
489
489
 
490
- test("determineMergeOrder — finds milestones completed in worktree DB even when worker state is 'error' (#2812)", () => {
490
+ test("determineMergeOrder — finds milestones completed in canonical DB even when worker state is 'error' (#2812)", () => {
491
491
  const base = realpathSync(mkdtempSync(join(tmpdir(), "merge-db-bug-")));
492
492
  try {
493
493
  // Simulate the bug scenario: orchestrator has stale "error" state
494
- // but the worktree DB shows milestone is actually complete.
495
- setupWorktreeDb(base, "M011");
494
+ // but the canonical DB shows milestone is actually complete.
495
+ setupCanonicalDbWithWorktree(base, "M011");
496
496
 
497
497
  const workers = [
498
498
  makeWorker({ milestoneId: "M010", state: "error" }),
@@ -502,12 +502,12 @@ test("determineMergeOrder — finds milestones completed in worktree DB even whe
502
502
 
503
503
  const order = determineMergeOrder(workers, "sequential", base);
504
504
 
505
- // M011 should be included because its worktree DB says status='complete'
505
+ // M011 should be included because the canonical DB says status='complete'
506
506
  assert.ok(
507
507
  order.includes("M011"),
508
- `Expected M011 in merge order (worktree DB says complete), got: [${order}]`,
508
+ `Expected M011 in merge order (canonical DB says complete), got: [${order}]`,
509
509
  );
510
- // M010 and M012 should NOT be included (no worktree DB with complete status)
510
+ // M010 and M012 should NOT be included (no canonical complete status)
511
511
  assert.ok(!order.includes("M010"), "M010 should not be in merge order (error, no DB)");
512
512
  assert.ok(!order.includes("M012"), "M012 should not be in merge order (running, no DB)");
513
513
  } finally {
@@ -529,7 +529,7 @@ test("determineMergeOrder — combines stopped workers and DB-complete milestone
529
529
  const base = realpathSync(mkdtempSync(join(tmpdir(), "merge-dedup-")));
530
530
  try {
531
531
  // M001 is stopped in orchestrator AND complete in worktree DB
532
- setupWorktreeDb(base, "M001");
532
+ setupCanonicalDbWithWorktree(base, "M001");
533
533
 
534
534
  const workers = [
535
535
  makeWorker({ milestoneId: "M001", state: "stopped" }),
@@ -555,8 +555,8 @@ test("mergeAllCompleted — discovers DB-complete milestones when workers show e
555
555
  ]);
556
556
  setupRoadmap(repo, "M011", "Feature System", ["S01: Feature module"]);
557
557
 
558
- // Set up worktree DB showing M011 is complete
559
- setupWorktreeDb(repo, "M011");
558
+ // Set up canonical DB showing M011 is complete
559
+ setupCanonicalDbWithWorktree(repo, "M011");
560
560
 
561
561
  // Orchestrator thinks M011 is in error (stale state)
562
562
  const workers = [
@@ -46,6 +46,7 @@ import {
46
46
  updateTaskStatus,
47
47
  updateSliceStatus,
48
48
  updateMilestoneStatus,
49
+ insertAssessment,
49
50
  insertReplanHistory,
50
51
  getReplanHistory,
51
52
  insertGateRow,
@@ -363,13 +364,13 @@ describe("state derivation failures", () => {
363
364
  const state2 = await deriveState(base);
364
365
  assert.equal(state2.phase, "executing", "cached result should still show executing");
365
366
 
366
- // After explicit invalidation, should reflect the DB mutation and reconcile
367
- // missing plan tasks instead of prematurely summarizing a partial DB row set.
367
+ // After explicit invalidation, DB rows remain authoritative; PLAN.md is a
368
+ // projection and must not import missing task rows.
368
369
  invalidateStateCache();
369
370
  const state3 = await deriveState(base);
370
- assert.equal(state3.phase, "executing", "after cache invalidation should continue with the missing plan task");
371
- assert.equal(state3.activeTask?.id, "T02", "missing plan task T02 should be imported and selected");
372
- assert.deepEqual(state3.progress?.tasks, { done: 1, total: 2 });
371
+ assert.equal(state3.phase, "summarizing", "after cache invalidation should follow DB tasks only");
372
+ assert.equal(state3.activeTask, null, "disk-only plan task T02 should not be imported");
373
+ assert.deepEqual(state3.progress?.tasks, { done: 1, total: 1 });
373
374
  });
374
375
 
375
376
  test("corrupt ROADMAP: binary content does not crash deriveState", async () => {
@@ -486,12 +487,14 @@ describe("transition boundary failures", () => {
486
487
  writeFileSync(join(mDir, "M001-CONTEXT-DRAFT.md"), "# Draft\nSome draft.\n");
487
488
 
488
489
  openDatabase(join(base, ".gsd", "gsd.db"));
490
+ insertMilestone({ id: "M001", title: "Draft", status: "needs-discussion" });
489
491
  invalidateAllCaches();
490
492
  const state1 = await deriveState(base);
491
493
  assert.equal(state1.phase, "needs-discussion");
492
494
 
493
495
  // Now write the full CONTEXT (simulates discussion completion)
494
496
  writeFileSync(join(mDir, "M001-CONTEXT.md"), "# M001: Resolved\n\n## Purpose\nDone.\n");
497
+ updateMilestoneStatus("M001", "active");
495
498
 
496
499
  invalidateAllCaches();
497
500
  const state2 = await deriveState(base);
@@ -1148,6 +1151,13 @@ describe("completion and verification failures", () => {
1148
1151
  insertTask({ id: "T01", sliceId: "S01", milestoneId: "M001", status: "complete" });
1149
1152
  insertTask({ id: "T02", sliceId: "S01", milestoneId: "M001", status: "complete" });
1150
1153
  insertTask({ id: "T01", sliceId: "S02", milestoneId: "M001", status: "complete" });
1154
+ insertAssessment({
1155
+ path: "milestones/M001/M001-VALIDATION.md",
1156
+ milestoneId: "M001",
1157
+ status: "pass",
1158
+ scope: "milestone-validation",
1159
+ fullContent: "verdict: pass",
1160
+ });
1151
1161
 
1152
1162
  invalidateAllCaches();
1153
1163
  const state = await deriveStateFromDb(base);