@opengsd/gsd-pi 1.1.1-dev.616a1a1 → 1.1.1-dev.75048e7

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 (452) hide show
  1. package/dist/cli.js +3 -2
  2. package/dist/help-text.js +10 -6
  3. package/dist/resources/.managed-resources-content-hash +1 -1
  4. package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +495 -0
  5. package/dist/resources/extensions/browser-tools/engine/selection.js +16 -0
  6. package/dist/resources/extensions/browser-tools/extension-manifest.json +2 -2
  7. package/dist/resources/extensions/browser-tools/index.js +57 -9
  8. package/dist/resources/extensions/browser-tools/package.json +5 -1
  9. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +167 -16
  10. package/dist/resources/extensions/gsd/auto/orchestrator.js +0 -1
  11. package/dist/resources/extensions/gsd/auto/phases.js +4 -3
  12. package/dist/resources/extensions/gsd/auto-dashboard.js +92 -17
  13. package/dist/resources/extensions/gsd/auto-dispatch.js +55 -0
  14. package/dist/resources/extensions/gsd/auto-post-unit.js +134 -10
  15. package/dist/resources/extensions/gsd/auto-prompts.js +72 -22
  16. package/dist/resources/extensions/gsd/auto-recovery.js +7 -8
  17. package/dist/resources/extensions/gsd/auto-runtime-state.js +3 -0
  18. package/dist/resources/extensions/gsd/auto-start.js +94 -15
  19. package/dist/resources/extensions/gsd/auto-tool-tracking.js +1 -1
  20. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +18 -65
  21. package/dist/resources/extensions/gsd/auto-worktree.js +18 -5
  22. package/dist/resources/extensions/gsd/auto.js +31 -6
  23. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +89 -4
  24. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +43 -0
  25. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +56 -20
  26. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +33 -38
  27. package/dist/resources/extensions/gsd/browser-evidence.js +29 -2
  28. package/dist/resources/extensions/gsd/closeout-consistency-gate.js +61 -0
  29. package/dist/resources/extensions/gsd/commands/catalog.js +6 -1
  30. package/dist/resources/extensions/gsd/commands/handlers/core.js +6 -2
  31. package/dist/resources/extensions/gsd/commands/handlers/ops.js +9 -5
  32. package/dist/resources/extensions/gsd/commands-handlers.js +76 -11
  33. package/dist/resources/extensions/gsd/commands-maintenance.js +172 -2
  34. package/dist/resources/extensions/gsd/commands-mcp-status.js +109 -60
  35. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +3 -1
  36. package/dist/resources/extensions/gsd/commands-verdict.js +1 -1
  37. package/dist/resources/extensions/gsd/config-overlay.js +2 -1
  38. package/dist/resources/extensions/gsd/dashboard-overlay.js +21 -7
  39. package/dist/resources/extensions/gsd/docs/preferences-reference.md +8 -0
  40. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +2 -2
  41. package/dist/resources/extensions/gsd/error-classifier.js +2 -1
  42. package/dist/resources/extensions/gsd/escalation.js +4 -4
  43. package/dist/resources/extensions/gsd/exec-sandbox.js +2 -0
  44. package/dist/resources/extensions/gsd/forensics.js +74 -2
  45. package/dist/resources/extensions/gsd/gsd-db.js +42 -6
  46. package/dist/resources/extensions/gsd/guided-flow.js +119 -176
  47. package/dist/resources/extensions/gsd/mcp-filter.js +3 -0
  48. package/dist/resources/extensions/gsd/mcp-project-config.js +76 -84
  49. package/dist/resources/extensions/gsd/memory-store.js +4 -1
  50. package/dist/resources/extensions/gsd/migration-auto-check.js +2 -2
  51. package/dist/resources/extensions/gsd/milestone-closeout.js +3 -1
  52. package/dist/resources/extensions/gsd/pending-auto-start.js +0 -1
  53. package/dist/resources/extensions/gsd/post-unit-hooks.js +9 -0
  54. package/dist/resources/extensions/gsd/preferences-validation.js +39 -0
  55. package/dist/resources/extensions/gsd/prompt-loader.js +7 -0
  56. package/dist/resources/extensions/gsd/prompts/forensics.md +61 -1
  57. package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +3 -1
  58. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +3 -1
  59. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  60. package/dist/resources/extensions/gsd/prompts/reactive-execute.md +3 -1
  61. package/dist/resources/extensions/gsd/prompts/run-uat.md +33 -23
  62. package/dist/resources/extensions/gsd/prompts/system.md +3 -1
  63. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +3 -3
  64. package/dist/resources/extensions/gsd/recovery-classification.js +20 -0
  65. package/dist/resources/extensions/gsd/rule-registry.js +428 -52
  66. package/dist/resources/extensions/gsd/safety/destructive-guard.js +3 -0
  67. package/dist/resources/extensions/gsd/skill-activation.js +20 -3
  68. package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +4 -2
  69. package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +1 -1
  70. package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +18 -1
  71. package/dist/resources/extensions/gsd/state-reconciliation/index.js +6 -0
  72. package/dist/resources/extensions/gsd/state.js +17 -14
  73. package/dist/resources/extensions/gsd/templates/plan.md +3 -1
  74. package/dist/resources/extensions/gsd/tool-contract.js +5 -0
  75. package/dist/resources/extensions/gsd/tool-presentation-plan.js +143 -0
  76. package/dist/resources/extensions/gsd/tools/complete-slice.js +15 -1
  77. package/dist/resources/extensions/gsd/tools/complete-task.js +11 -1
  78. package/dist/resources/extensions/gsd/tools/exec-tool.js +109 -0
  79. package/dist/resources/extensions/gsd/tools/plan-slice.js +14 -9
  80. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +2 -2
  81. package/dist/resources/extensions/gsd/tools/validate-milestone.js +46 -16
  82. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +483 -6
  83. package/dist/resources/extensions/gsd/unit-context-manifest.js +8 -3
  84. package/dist/resources/extensions/gsd/unit-tool-contracts.js +169 -0
  85. package/dist/resources/extensions/gsd/validation-block-guard.js +2 -0
  86. package/dist/resources/extensions/gsd/verdict-parser.js +59 -15
  87. package/dist/resources/extensions/gsd/verification-gate.js +72 -1
  88. package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +3 -1
  89. package/dist/resources/extensions/gsd/workflow-mcp.js +5 -73
  90. package/dist/resources/extensions/gsd/worktree-lifecycle.js +24 -0
  91. package/dist/resources/extensions/mcp-client/manager.js +31 -1
  92. package/dist/resources/extensions/shared/gsd-browser-cli.js +145 -0
  93. package/dist/rtk.d.ts +7 -1
  94. package/dist/rtk.js +27 -11
  95. package/dist/update-check.d.ts +15 -1
  96. package/dist/update-check.js +87 -12
  97. package/dist/update-cmd.d.ts +1 -0
  98. package/dist/update-cmd.js +53 -2
  99. package/dist/web/standalone/.next/BUILD_ID +1 -1
  100. package/dist/web/standalone/.next/app-path-routes-manifest.json +5 -5
  101. package/dist/web/standalone/.next/build-manifest.json +2 -2
  102. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  103. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  104. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  112. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  120. package/dist/web/standalone/.next/server/app/index.html +1 -1
  121. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app-paths-manifest.json +5 -5
  128. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  129. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  130. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  131. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  132. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  133. package/package.json +5 -3
  134. package/packages/cloud-mcp-gateway/package.json +2 -2
  135. package/packages/contracts/dist/workflow.d.ts +14 -0
  136. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  137. package/packages/contracts/dist/workflow.js +16 -0
  138. package/packages/contracts/dist/workflow.js.map +1 -1
  139. package/packages/contracts/package.json +1 -1
  140. package/packages/daemon/package.json +4 -4
  141. package/packages/gsd-agent-core/dist/agent-session.d.ts +9 -0
  142. package/packages/gsd-agent-core/dist/agent-session.d.ts.map +1 -1
  143. package/packages/gsd-agent-core/dist/agent-session.js +32 -0
  144. package/packages/gsd-agent-core/dist/agent-session.js.map +1 -1
  145. package/packages/gsd-agent-core/dist/index.d.ts +1 -0
  146. package/packages/gsd-agent-core/dist/index.d.ts.map +1 -1
  147. package/packages/gsd-agent-core/dist/index.js +1 -0
  148. package/packages/gsd-agent-core/dist/index.js.map +1 -1
  149. package/packages/gsd-agent-core/dist/session/agent-session-compaction.d.ts +2 -0
  150. package/packages/gsd-agent-core/dist/session/agent-session-compaction.d.ts.map +1 -1
  151. package/packages/gsd-agent-core/dist/session/agent-session-compaction.js +8 -2
  152. package/packages/gsd-agent-core/dist/session/agent-session-compaction.js.map +1 -1
  153. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts +7 -0
  154. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts.map +1 -1
  155. package/packages/gsd-agent-core/dist/session/agent-session-host.js.map +1 -1
  156. package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts.map +1 -1
  157. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js +69 -1
  158. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js.map +1 -1
  159. package/packages/gsd-agent-core/dist/turn-latency.d.ts +47 -0
  160. package/packages/gsd-agent-core/dist/turn-latency.d.ts.map +1 -0
  161. package/packages/gsd-agent-core/dist/turn-latency.js +123 -0
  162. package/packages/gsd-agent-core/dist/turn-latency.js.map +1 -0
  163. package/packages/gsd-agent-core/package.json +6 -6
  164. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts +21 -0
  165. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts.map +1 -0
  166. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js +213 -0
  167. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js.map +1 -0
  168. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  169. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  170. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js +10 -0
  171. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js.map +1 -1
  172. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  173. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +5 -0
  174. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  175. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts +1 -0
  176. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  177. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +92 -31
  178. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  179. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  180. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +7 -1
  181. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  182. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.d.ts.map +1 -1
  183. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.js +6 -0
  184. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.js.map +1 -1
  185. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-dialogs.d.ts.map +1 -1
  186. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-dialogs.js +2 -0
  187. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-dialogs.js.map +1 -1
  188. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts +1 -1
  189. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts.map +1 -1
  190. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js +1 -1
  191. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js.map +1 -1
  192. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  193. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +1 -0
  194. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
  195. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.d.ts.map +1 -1
  196. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js +5 -0
  197. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js.map +1 -1
  198. package/packages/gsd-agent-modes/package.json +7 -7
  199. package/packages/mcp-server/dist/remote-questions.d.ts.map +1 -1
  200. package/packages/mcp-server/dist/remote-questions.js +23 -9
  201. package/packages/mcp-server/dist/remote-questions.js.map +1 -1
  202. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  203. package/packages/mcp-server/dist/workflow-tools.js +84 -2
  204. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  205. package/packages/mcp-server/package.json +3 -3
  206. package/packages/native/package.json +1 -1
  207. package/packages/pi-agent-core/dist/agent-loop.js +42 -3
  208. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  209. package/packages/pi-agent-core/dist/agent.d.ts +5 -1
  210. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  211. package/packages/pi-agent-core/dist/agent.js +2 -0
  212. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  213. package/packages/pi-agent-core/dist/harness/agent-harness.d.ts.map +1 -1
  214. package/packages/pi-agent-core/dist/harness/agent-harness.js +3 -1
  215. package/packages/pi-agent-core/dist/harness/agent-harness.js.map +1 -1
  216. package/packages/pi-agent-core/dist/harness/types.d.ts +1 -0
  217. package/packages/pi-agent-core/dist/harness/types.d.ts.map +1 -1
  218. package/packages/pi-agent-core/dist/harness/types.js.map +1 -1
  219. package/packages/pi-agent-core/dist/types.d.ts +6 -1
  220. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  221. package/packages/pi-agent-core/dist/types.js.map +1 -1
  222. package/packages/pi-agent-core/package.json +1 -1
  223. package/packages/pi-ai/dist/api-registry.d.ts +2 -0
  224. package/packages/pi-ai/dist/api-registry.d.ts.map +1 -1
  225. package/packages/pi-ai/dist/api-registry.js +23 -0
  226. package/packages/pi-ai/dist/api-registry.js.map +1 -1
  227. package/packages/pi-ai/dist/image-models.generated.d.ts +15 -0
  228. package/packages/pi-ai/dist/image-models.generated.d.ts.map +1 -1
  229. package/packages/pi-ai/dist/image-models.generated.js +15 -0
  230. package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
  231. package/packages/pi-ai/dist/models.generated.d.ts +411 -39
  232. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  233. package/packages/pi-ai/dist/models.generated.js +504 -153
  234. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  235. package/packages/pi-ai/dist/stream.js +6 -6
  236. package/packages/pi-ai/dist/stream.js.map +1 -1
  237. package/packages/pi-ai/package.json +1 -1
  238. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts +3 -0
  239. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts.map +1 -1
  240. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.js.map +1 -1
  241. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  242. package/packages/pi-coding-agent/dist/core/model-registry.js +2 -2
  243. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  244. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
  245. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  246. package/packages/pi-coding-agent/dist/core/settings-manager.js +11 -0
  247. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  248. package/packages/pi-coding-agent/dist/core/tools/bash.js +2 -2
  249. package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
  250. package/packages/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
  251. package/packages/pi-coding-agent/dist/core/tools/edit.js +3 -2
  252. package/packages/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
  253. package/packages/pi-coding-agent/dist/core/tools/render-utils.d.ts +1 -0
  254. package/packages/pi-coding-agent/dist/core/tools/render-utils.d.ts.map +1 -1
  255. package/packages/pi-coding-agent/dist/core/tools/render-utils.js +6 -0
  256. package/packages/pi-coding-agent/dist/core/tools/render-utils.js.map +1 -1
  257. package/packages/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
  258. package/packages/pi-coding-agent/dist/core/tools/write.js +3 -2
  259. package/packages/pi-coding-agent/dist/core/tools/write.js.map +1 -1
  260. package/packages/pi-coding-agent/package.json +7 -7
  261. package/packages/pi-tui/dist/terminal.d.ts +1 -0
  262. package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
  263. package/packages/pi-tui/dist/terminal.js +8 -4
  264. package/packages/pi-tui/dist/terminal.js.map +1 -1
  265. package/packages/pi-tui/package.json +1 -1
  266. package/packages/rpc-client/package.json +2 -2
  267. package/pkg/package.json +1 -1
  268. package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +579 -0
  269. package/src/resources/extensions/browser-tools/engine/selection.ts +19 -0
  270. package/src/resources/extensions/browser-tools/extension-manifest.json +2 -2
  271. package/src/resources/extensions/browser-tools/index.ts +60 -9
  272. package/src/resources/extensions/browser-tools/package.json +5 -1
  273. package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +35 -0
  274. package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +33 -0
  275. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +196 -16
  276. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +239 -63
  277. package/src/resources/extensions/gsd/auto/orchestrator.ts +0 -1
  278. package/src/resources/extensions/gsd/auto/phases.ts +5 -3
  279. package/src/resources/extensions/gsd/auto-dashboard.ts +98 -18
  280. package/src/resources/extensions/gsd/auto-dispatch.ts +67 -0
  281. package/src/resources/extensions/gsd/auto-post-unit.ts +166 -9
  282. package/src/resources/extensions/gsd/auto-prompts.ts +106 -15
  283. package/src/resources/extensions/gsd/auto-recovery.ts +7 -7
  284. package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -0
  285. package/src/resources/extensions/gsd/auto-start.ts +112 -17
  286. package/src/resources/extensions/gsd/auto-tool-tracking.ts +1 -1
  287. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +43 -73
  288. package/src/resources/extensions/gsd/auto-worktree.ts +23 -5
  289. package/src/resources/extensions/gsd/auto.ts +47 -5
  290. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +96 -4
  291. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +51 -0
  292. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +81 -25
  293. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +70 -63
  294. package/src/resources/extensions/gsd/browser-evidence.ts +26 -2
  295. package/src/resources/extensions/gsd/closeout-consistency-gate.ts +137 -0
  296. package/src/resources/extensions/gsd/commands/catalog.ts +6 -1
  297. package/src/resources/extensions/gsd/commands/handlers/core.ts +6 -2
  298. package/src/resources/extensions/gsd/commands/handlers/ops.ts +9 -5
  299. package/src/resources/extensions/gsd/commands-handlers.ts +76 -11
  300. package/src/resources/extensions/gsd/commands-maintenance.ts +197 -2
  301. package/src/resources/extensions/gsd/commands-mcp-status.ts +136 -58
  302. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +4 -1
  303. package/src/resources/extensions/gsd/commands-verdict.ts +1 -1
  304. package/src/resources/extensions/gsd/config-overlay.ts +3 -1
  305. package/src/resources/extensions/gsd/dashboard-overlay.ts +28 -7
  306. package/src/resources/extensions/gsd/docs/preferences-reference.md +8 -0
  307. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +2 -2
  308. package/src/resources/extensions/gsd/error-classifier.ts +2 -1
  309. package/src/resources/extensions/gsd/escalation.ts +4 -4
  310. package/src/resources/extensions/gsd/exec-sandbox.ts +4 -0
  311. package/src/resources/extensions/gsd/forensics.ts +99 -5
  312. package/src/resources/extensions/gsd/gsd-db.ts +46 -8
  313. package/src/resources/extensions/gsd/guided-flow.ts +215 -217
  314. package/src/resources/extensions/gsd/mcp-filter.ts +3 -0
  315. package/src/resources/extensions/gsd/mcp-project-config.ts +105 -88
  316. package/src/resources/extensions/gsd/memory-store.ts +4 -1
  317. package/src/resources/extensions/gsd/migration-auto-check.ts +2 -2
  318. package/src/resources/extensions/gsd/milestone-closeout.ts +3 -1
  319. package/src/resources/extensions/gsd/pending-auto-start.ts +0 -2
  320. package/src/resources/extensions/gsd/post-unit-hooks.ts +14 -1
  321. package/src/resources/extensions/gsd/preferences-types.ts +1 -1
  322. package/src/resources/extensions/gsd/preferences-validation.ts +36 -0
  323. package/src/resources/extensions/gsd/prompt-loader.ts +8 -0
  324. package/src/resources/extensions/gsd/prompts/forensics.md +61 -1
  325. package/src/resources/extensions/gsd/prompts/gate-evaluate.md +3 -1
  326. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +3 -1
  327. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  328. package/src/resources/extensions/gsd/prompts/reactive-execute.md +3 -1
  329. package/src/resources/extensions/gsd/prompts/run-uat.md +33 -23
  330. package/src/resources/extensions/gsd/prompts/system.md +3 -1
  331. package/src/resources/extensions/gsd/prompts/validate-milestone.md +3 -3
  332. package/src/resources/extensions/gsd/recovery-classification.ts +20 -0
  333. package/src/resources/extensions/gsd/rule-registry.ts +558 -58
  334. package/src/resources/extensions/gsd/rule-types.ts +2 -0
  335. package/src/resources/extensions/gsd/safety/destructive-guard.ts +3 -0
  336. package/src/resources/extensions/gsd/skill-activation.ts +20 -2
  337. package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +4 -2
  338. package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +1 -1
  339. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +20 -0
  340. package/src/resources/extensions/gsd/state-reconciliation/index.ts +6 -0
  341. package/src/resources/extensions/gsd/state-reconciliation/types.ts +1 -0
  342. package/src/resources/extensions/gsd/state.ts +18 -14
  343. package/src/resources/extensions/gsd/templates/plan.md +3 -1
  344. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +156 -4
  345. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +123 -0
  346. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +10 -2
  347. package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +4 -1
  348. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +143 -2
  349. package/src/resources/extensions/gsd/tests/auto-start-project-milestone-reconcile.test.ts +24 -2
  350. package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +12 -2
  351. package/src/resources/extensions/gsd/tests/browser-evidence.test.ts +142 -0
  352. package/src/resources/extensions/gsd/tests/check-auto-start-pending-gate.test.ts +9 -15
  353. package/src/resources/extensions/gsd/tests/check-auto-start-ready-guard.test.ts +26 -16
  354. package/src/resources/extensions/gsd/tests/commands-dispatcher-unmerged-milestone.test.ts +21 -0
  355. package/src/resources/extensions/gsd/tests/commands-dispatcher-validation-block.test.ts +38 -3
  356. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +6 -2
  357. package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +30 -0
  358. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
  359. package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +45 -0
  360. package/src/resources/extensions/gsd/tests/deep-planning-mode-dispatch.test.ts +53 -0
  361. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +8 -0
  362. package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +50 -13
  363. package/src/resources/extensions/gsd/tests/discuss-milestone-structured-questions.test.ts +31 -0
  364. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +40 -1
  365. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +60 -0
  366. package/src/resources/extensions/gsd/tests/doctor-runtime-checks.test.ts +27 -0
  367. package/src/resources/extensions/gsd/tests/escalation.test.ts +16 -27
  368. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +18 -0
  369. package/src/resources/extensions/gsd/tests/exec-tool.test.ts +69 -0
  370. package/src/resources/extensions/gsd/tests/forensics-issue-routing.test.ts +20 -0
  371. package/src/resources/extensions/gsd/tests/forensics-prompt-rendering.test.ts +3 -0
  372. package/src/resources/extensions/gsd/tests/forensics-tool-scope.test.ts +69 -0
  373. package/src/resources/extensions/gsd/tests/gate-1b-orphan-discrimination.test.ts +31 -79
  374. package/src/resources/extensions/gsd/tests/gsd-rebuild.test.ts +199 -0
  375. package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +75 -0
  376. package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +40 -1
  377. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +86 -0
  378. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +5 -3
  379. package/src/resources/extensions/gsd/tests/guided-flow-state-rebuild.test.ts +40 -4
  380. package/src/resources/extensions/gsd/tests/guided-flow.test.ts +12 -9
  381. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +4 -4
  382. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +8 -0
  383. package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +16 -0
  384. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +72 -10
  385. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +13 -6
  386. package/src/resources/extensions/gsd/tests/mcp-filter.test.ts +15 -0
  387. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +100 -0
  388. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +179 -0
  389. package/src/resources/extensions/gsd/tests/memory-maintenance.test.ts +39 -8
  390. package/src/resources/extensions/gsd/tests/merge-closeout-consistency-gate.test.ts +63 -0
  391. package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +10 -1
  392. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +3 -3
  393. package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +9 -1
  394. package/src/resources/extensions/gsd/tests/new-milestone-discuss-routing.test.ts +3 -3
  395. package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +54 -7
  396. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +9 -0
  397. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +39 -1
  398. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +157 -0
  399. package/src/resources/extensions/gsd/tests/post-unit-retry-on-orchestrator-bridge.test.ts +179 -0
  400. package/src/resources/extensions/gsd/tests/preferences.test.ts +29 -0
  401. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +83 -1
  402. package/src/resources/extensions/gsd/tests/prompt-loader-extension-dir.test.ts +14 -0
  403. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +18 -1
  404. package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +7 -8
  405. package/src/resources/extensions/gsd/tests/reactive-executor.test.ts +36 -0
  406. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +79 -0
  407. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +1 -1
  408. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +75 -0
  409. package/src/resources/extensions/gsd/tests/run-uat-composer.test.ts +4 -0
  410. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +36 -0
  411. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +100 -0
  412. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +55 -0
  413. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +6 -2
  414. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +191 -0
  415. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +84 -10
  416. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +19 -0
  417. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +12 -2
  418. package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +7 -1
  419. package/src/resources/extensions/gsd/tests/tui-header-lifecycle.test.ts +29 -6
  420. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +29 -6
  421. package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +6 -3
  422. package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +133 -0
  423. package/src/resources/extensions/gsd/tests/validation-block-guard.test.ts +21 -0
  424. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +51 -0
  425. package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +17 -2
  426. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +493 -0
  427. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +40 -0
  428. package/src/resources/extensions/gsd/tool-contract.ts +6 -0
  429. package/src/resources/extensions/gsd/tool-presentation-plan.ts +223 -0
  430. package/src/resources/extensions/gsd/tools/complete-slice.ts +14 -1
  431. package/src/resources/extensions/gsd/tools/complete-task.ts +20 -2
  432. package/src/resources/extensions/gsd/tools/exec-tool.ts +130 -0
  433. package/src/resources/extensions/gsd/tools/plan-slice.ts +14 -9
  434. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +2 -2
  435. package/src/resources/extensions/gsd/tools/validate-milestone.ts +46 -15
  436. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +589 -8
  437. package/src/resources/extensions/gsd/types.ts +69 -5
  438. package/src/resources/extensions/gsd/unit-context-manifest.ts +14 -5
  439. package/src/resources/extensions/gsd/unit-tool-contracts.ts +186 -0
  440. package/src/resources/extensions/gsd/validation-block-guard.ts +2 -0
  441. package/src/resources/extensions/gsd/verdict-parser.ts +54 -13
  442. package/src/resources/extensions/gsd/verification-gate.ts +87 -1
  443. package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +2 -1
  444. package/src/resources/extensions/gsd/workflow-mcp.ts +5 -73
  445. package/src/resources/extensions/gsd/worktree-lifecycle.ts +26 -0
  446. package/src/resources/extensions/mcp-client/manager.ts +33 -1
  447. package/src/resources/extensions/mcp-client/tests/manager.test.ts +35 -0
  448. package/src/resources/extensions/shared/gsd-browser-cli.ts +172 -0
  449. package/src/resources/extensions/gsd/tests/gate-1b-recovery-bound-corrections.test.ts +0 -246
  450. package/src/resources/extensions/gsd/tests/gate-1b-recovery-bound.test.ts +0 -218
  451. /package/dist/web/standalone/.next/static/{L9N5SPFi7f-Ne4u2uXzCe → h4TGni4xJzlZjGkxaT6uU}/_buildManifest.js +0 -0
  452. /package/dist/web/standalone/.next/static/{L9N5SPFi7f-Ne4u2uXzCe → h4TGni4xJzlZjGkxaT6uU}/_ssgManifest.js +0 -0
@@ -91,10 +91,15 @@ import { nativeHasChanges, nativeIsRepo, _resetHasChangesCache } from "./native-
91
91
  import { debugLog, isDebugEnabled } from "./debug-logger.js";
92
92
  import { resolveCanonicalMilestoneRoot } from "./worktree-manager.js";
93
93
  import { resolveWorktreeProjectRoot } from "./worktree-root.js";
94
+ import { detectWorktreeName } from "./worktree.js";
94
95
  import { probeGitConflictState } from "./git-conflict-state.js";
95
96
  import { runTurnGitAction } from "./git-service.js";
96
97
  import { parseUnitId } from "./unit-id.js";
97
98
  import { resolveExpectedArtifactPath } from "./auto-artifact-paths.js";
99
+ import {
100
+ checkCloseoutConsistencyGate,
101
+ formatCloseoutConsistencyBlock,
102
+ } from "./closeout-consistency-gate.js";
98
103
 
99
104
  // ─── Types ────────────────────────────────────────────────────────────────
100
105
 
@@ -340,6 +345,29 @@ function isRegistryMilestoneComplete(state: GSDState, mid: string): boolean {
340
345
  );
341
346
  }
342
347
 
348
+ function normalizeMilestoneScope(value: string | null | undefined): string | null {
349
+ const trimmed = value?.trim();
350
+ if (!trimmed || !MILESTONE_ID_RE.test(trimmed)) return null;
351
+ return trimmed;
352
+ }
353
+
354
+ function resolveDispatchMilestoneScope(
355
+ ctx: DispatchContext,
356
+ ): { id: string; source: string } | null {
357
+ const sessionMilestone = normalizeMilestoneScope(ctx.session?.currentMilestoneId);
358
+ if (sessionMilestone) return { id: sessionMilestone, source: "session.currentMilestoneId" };
359
+
360
+ const sessionWorktree = normalizeMilestoneScope(
361
+ ctx.session?.basePath ? detectWorktreeName(ctx.session.basePath) : null,
362
+ );
363
+ if (sessionWorktree) return { id: sessionWorktree, source: "session.basePath worktree" };
364
+
365
+ const baseWorktree = normalizeMilestoneScope(detectWorktreeName(ctx.basePath));
366
+ if (baseWorktree) return { id: baseWorktree, source: "basePath worktree" };
367
+
368
+ return null;
369
+ }
370
+
343
371
  function hasMilestonePassedDiscuss(basePath: string, mid: string): boolean {
344
372
  if (isDbAvailable()) {
345
373
  try {
@@ -598,6 +626,7 @@ export const DISPATCH_RULES: DispatchRule[] = [
598
626
  structuredQuestionsAvailable,
599
627
  { headless: !!process.env.GSD_HEADLESS },
600
628
  ),
629
+ pauseAfterDispatch: !process.env.GSD_HEADLESS,
601
630
  };
602
631
  },
603
632
  },
@@ -748,6 +777,7 @@ export const DISPATCH_RULES: DispatchRule[] = [
748
777
  structuredQuestionsAvailable,
749
778
  { headless: !!process.env.GSD_HEADLESS },
750
779
  ),
780
+ pauseAfterDispatch: !process.env.GSD_HEADLESS,
751
781
  };
752
782
  },
753
783
  },
@@ -781,6 +811,7 @@ export const DISPATCH_RULES: DispatchRule[] = [
781
811
  unitType: "discuss-project",
782
812
  unitId: "PROJECT",
783
813
  prompt: await buildDiscussProjectPrompt(basePath, structuredQuestionsAvailable),
814
+ pauseAfterDispatch: !process.env.GSD_HEADLESS,
784
815
  };
785
816
  },
786
817
  },
@@ -802,6 +833,7 @@ export const DISPATCH_RULES: DispatchRule[] = [
802
833
  unitType: "discuss-requirements",
803
834
  unitId: "REQUIREMENTS",
804
835
  prompt: await buildDiscussRequirementsPrompt(basePath, structuredQuestionsAvailable),
836
+ pauseAfterDispatch: !process.env.GSD_HEADLESS,
805
837
  };
806
838
  },
807
839
  },
@@ -916,6 +948,7 @@ export const DISPATCH_RULES: DispatchRule[] = [
916
948
  structuredQuestionsAvailable,
917
949
  { headless: !!process.env.GSD_HEADLESS },
918
950
  ),
951
+ pauseAfterDispatch: !process.env.GSD_HEADLESS,
919
952
  };
920
953
  },
921
954
  },
@@ -1606,6 +1639,16 @@ export const DISPATCH_RULES: DispatchRule[] = [
1606
1639
  prompt: await buildCompleteMilestonePrompt(mid, midTitle, basePath),
1607
1640
  };
1608
1641
  }
1642
+ if (milestone) {
1643
+ const closeoutGate = checkCloseoutConsistencyGate(mid, { refreshFromDisk: true });
1644
+ if (!closeoutGate.ok) {
1645
+ return {
1646
+ action: "stop",
1647
+ reason: formatCloseoutConsistencyBlock(closeoutGate),
1648
+ level: "warning",
1649
+ };
1650
+ }
1651
+ }
1609
1652
  }
1610
1653
  return {
1611
1654
  action: "stop",
@@ -1631,6 +1674,19 @@ import { getRegistry } from "./rule-registry.js";
1631
1674
  export async function resolveDispatch(
1632
1675
  ctx: DispatchContext,
1633
1676
  ): Promise<DispatchAction> {
1677
+ if (ctx.mid && isDbAvailable()) {
1678
+ const milestone = getMilestone(ctx.mid);
1679
+ if (milestone && isClosedStatus(milestone.status)) {
1680
+ return {
1681
+ action: "stop",
1682
+ reason:
1683
+ `Milestone ${ctx.mid} is closed (status: ${milestone.status}); auto-mode will not reopen or recover it implicitly. ` +
1684
+ "Use an explicit reopen command before planning or executing more work for this milestone.",
1685
+ level: "warning",
1686
+ };
1687
+ }
1688
+ }
1689
+
1634
1690
  const activeMid = ctx.state.activeMilestone?.id;
1635
1691
  if (activeMid && ctx.mid !== activeMid) {
1636
1692
  return {
@@ -1642,6 +1698,17 @@ export async function resolveDispatch(
1642
1698
  };
1643
1699
  }
1644
1700
 
1701
+ const scopedMilestone = resolveDispatchMilestoneScope(ctx);
1702
+ if (scopedMilestone && ctx.mid !== scopedMilestone.id) {
1703
+ return {
1704
+ action: "stop",
1705
+ reason:
1706
+ `Dispatch milestone mismatch: context mid "${ctx.mid}" does not match ${scopedMilestone.source} "${scopedMilestone.id}". ` +
1707
+ "The active worktree/session and derived project state disagree; recover, park, or discard the stranded milestone before continuing.",
1708
+ level: "warning",
1709
+ };
1710
+ }
1711
+
1645
1712
  // Delegate to registry when available
1646
1713
  try {
1647
1714
  const registry = getRegistry();
@@ -55,8 +55,10 @@ import { parseRoadmap as parseLegacyRoadmap } from "./parsers-legacy.js";
55
55
  import { consumeSignal } from "./session-status-io.js";
56
56
  import {
57
57
  checkPostUnitHooks,
58
+ consumeHookFailure,
58
59
  isRetryPending,
59
60
  consumeRetryTrigger,
61
+ consumeGateBlock,
60
62
  persistHookState,
61
63
  resolveHookArtifactPath,
62
64
  } from "./post-unit-hooks.js";
@@ -394,6 +396,50 @@ function stripKnownIdPrefix(value: string | undefined | null, id: string): strin
394
396
  return raw;
395
397
  }
396
398
 
399
+ function parseReactiveBatchTaskIds(unitId: string): string[] {
400
+ const { task: batchPart } = parseUnitId(unitId);
401
+ if (!batchPart?.startsWith("reactive+")) return [];
402
+
403
+ const rawIds = batchPart
404
+ .slice("reactive+".length)
405
+ .split(",")
406
+ .map((taskId) => taskId.trim().toUpperCase())
407
+ .filter(Boolean);
408
+
409
+ const unique = new Set<string>();
410
+ for (const taskId of rawIds) {
411
+ unique.add(taskId);
412
+ }
413
+ return [...unique];
414
+ }
415
+
416
+ function dedupePaths(values: string[]): string[] {
417
+ const seen = new Set<string>();
418
+ const result: string[] = [];
419
+ for (const value of values) {
420
+ if (!seen.has(value)) {
421
+ seen.add(value);
422
+ result.push(value);
423
+ }
424
+ }
425
+ return result;
426
+ }
427
+
428
+ function getPlannedKeyFiles(tasks: Array<
429
+ { expected_output?: string[]; files?: string[]; key_files?: string[] }
430
+ >): string[] {
431
+ return dedupePaths(
432
+ tasks.flatMap((taskRow) => [
433
+ ...(taskRow.expected_output ?? []),
434
+ ...(taskRow.files ?? []),
435
+ ...(taskRow.key_files ?? []),
436
+ ]),
437
+ );
438
+ }
439
+
440
+ export const _parseReactiveBatchTaskIdsForTest = parseReactiveBatchTaskIds;
441
+ export const _getPlannedKeyFilesForTest = getPlannedKeyFiles;
442
+
397
443
  function resolveVerificationFailureMarkerPath(
398
444
  unitType: string,
399
445
  unitId: string,
@@ -481,6 +527,40 @@ async function buildTaskCommitContextForUnit(
481
527
  };
482
528
  }
483
529
 
530
+ async function buildReactiveTaskCommitContext(
531
+ _basePath: string,
532
+ unitId: string,
533
+ ): Promise<TaskCommitContext | undefined> {
534
+ const { milestone: mid, slice: sid } = parseUnitId(unitId);
535
+ if (!mid || !sid || !isDbAvailable()) return undefined;
536
+
537
+ const batchTaskIds = parseReactiveBatchTaskIds(unitId);
538
+ if (batchTaskIds.length === 0) return undefined;
539
+
540
+ const milestone = getMilestone(mid);
541
+ const slice = getSlice(mid, sid);
542
+ const taskRows = batchTaskIds
543
+ .map((tid) => getTask(mid, sid, tid))
544
+ .filter((taskRow): taskRow is NonNullable<ReturnType<typeof getTask>> => taskRow !== null);
545
+
546
+ const keyFiles = getPlannedKeyFiles(taskRows);
547
+ if (taskRows.length === 0 || keyFiles.length === 0) return undefined;
548
+
549
+ const taskLabel = taskRows.map((row) => row.id).join(",");
550
+
551
+ return {
552
+ taskId: `${sid}/${taskLabel}`,
553
+ taskDisplayId: "reactive-batch",
554
+ taskTitle: `Reactive batch: ${taskLabel}`,
555
+ milestoneId: mid,
556
+ milestoneTitle: stripKnownIdPrefix(milestone?.title, mid),
557
+ sliceId: sid,
558
+ sliceTitle: stripKnownIdPrefix(slice?.title, sid),
559
+ oneLiner: `Reactive execute for ${taskLabel}`,
560
+ keyFiles,
561
+ };
562
+ }
563
+
484
564
  async function runPostUnitGitHubSyncIfNeeded(
485
565
  basePath: string,
486
566
  unit: NonNullable<AutoSession["currentUnit"]>,
@@ -943,6 +1023,8 @@ export async function autoCommitUnit(
943
1023
 
944
1024
  if (unitType === "execute-task") {
945
1025
  taskContext = await buildTaskCommitContextForUnit(basePath, unitId);
1026
+ } else if (unitType === "reactive-execute") {
1027
+ taskContext = await buildReactiveTaskCommitContext(basePath, unitId);
946
1028
  }
947
1029
 
948
1030
  _resetHasChangesCache();
@@ -1005,6 +1087,21 @@ async function runCloseoutGitAction(
1005
1087
  if (mid && sid && tid && isDbAvailable()) {
1006
1088
  targetRepositories = getTask(mid, sid, tid)?.target_repositories;
1007
1089
  }
1090
+ } else if (turnAction === "commit" && unit.type === "reactive-execute") {
1091
+ taskContext = await buildReactiveTaskCommitContext(s.basePath, unit.id);
1092
+ const { milestone: mid, slice: sid } = parseUnitId(unit.id);
1093
+ if (mid && sid && isDbAvailable()) {
1094
+ const repositories = new Set<string>();
1095
+ for (const tid of parseReactiveBatchTaskIds(unit.id)) {
1096
+ const taskRow = getTask(mid, sid, tid);
1097
+ for (const repoId of taskRow?.target_repositories ?? []) {
1098
+ repositories.add(repoId);
1099
+ }
1100
+ }
1101
+ if (repositories.size > 0) {
1102
+ targetRepositories = [...repositories];
1103
+ }
1104
+ }
1008
1105
  }
1009
1106
 
1010
1107
  // Invalidate the nativeHasChanges cache before auto-commit (#1853).
@@ -1436,12 +1533,24 @@ export async function postUnitPreVerification(pctx: PostUnitContext, opts?: PreV
1436
1533
  const { milestone: sMid, slice: sSid, task: sTid } = parseUnitId(s.currentUnit.id);
1437
1534
 
1438
1535
  // File change validation (execute-task only, after unit execution)
1439
- if (safetyConfig.file_change_validation && s.currentUnit.type === "execute-task" && sMid && sSid && sTid && isDbAvailable()) {
1536
+ if (safetyConfig.file_change_validation && s.currentUnit.type === "execute-task" && sMid && sSid && sTid) {
1440
1537
  try {
1441
- const taskRow = getTask(sMid, sSid, sTid);
1442
- if (taskRow) {
1443
- const expectedOutput = taskRow.expected_output ?? [];
1444
- const plannedFiles = taskRow.files ?? [];
1538
+ const sliceTaskRows = isDbAvailable()
1539
+ ? getSliceTasks(sMid, sSid).filter((t) => isClosedStatus(t.status) || t.id === sTid)
1540
+ : [];
1541
+
1542
+ if (sliceTaskRows.length > 0) {
1543
+ const expectedOutput = getPlannedKeyFiles(
1544
+ sliceTaskRows.map((taskRow) => ({
1545
+ expected_output: taskRow.expected_output,
1546
+ files: taskRow.files,
1547
+ })),
1548
+ );
1549
+ const plannedFiles = getPlannedKeyFiles(
1550
+ sliceTaskRows.map((taskRow) => ({
1551
+ files: taskRow.files,
1552
+ })),
1553
+ );
1445
1554
  const audit = validateFileChanges(s.basePath, expectedOutput, plannedFiles, safetyConfig.file_change_allowlist);
1446
1555
  if (audit && audit.violations.length > 0) {
1447
1556
  const warnings = audit.violations.filter(v => v.severity === "warning");
@@ -1455,6 +1564,30 @@ export async function postUnitPreVerification(pctx: PostUnitContext, opts?: PreV
1455
1564
  );
1456
1565
  }
1457
1566
  }
1567
+ } else {
1568
+ const taskRow = getTask(sMid, sSid, sTid);
1569
+ if (taskRow) {
1570
+ const expectedOutput = taskRow.expected_output ?? [];
1571
+ const plannedFiles = taskRow.files ?? [];
1572
+ const audit = validateFileChanges(
1573
+ s.basePath,
1574
+ expectedOutput,
1575
+ plannedFiles,
1576
+ safetyConfig.file_change_allowlist,
1577
+ );
1578
+ if (audit && audit.violations.length > 0) {
1579
+ const warnings = audit.violations.filter(v => v.severity === "warning");
1580
+ for (const v of warnings) {
1581
+ logWarning("safety", `file-change: ${v.file} — ${v.reason}`);
1582
+ }
1583
+ if (warnings.length > 0) {
1584
+ ctx.ui.notify(
1585
+ `Safety: ${warnings.length} unexpected file change(s) outside task plan`,
1586
+ "warning",
1587
+ );
1588
+ }
1589
+ }
1590
+ }
1458
1591
  }
1459
1592
  } catch (e) {
1460
1593
  debugLog("postUnit", { phase: "safety-file-change", error: String(e) });
@@ -2096,11 +2229,11 @@ export async function postUnitPostVerification(pctx: PostUnitContext): Promise<"
2096
2229
  // ── Post-unit hooks ──
2097
2230
  if (s.currentUnit && !s.stepMode) {
2098
2231
  const hookUnit = checkPostUnitHooks(s.currentUnit.type, s.currentUnit.id, s.basePath);
2232
+ persistHookState(s.basePath);
2099
2233
  if (hookUnit) {
2100
2234
  if (s.currentUnit) {
2101
2235
  await closeoutUnit(ctx, s.basePath, s.currentUnit.type, s.currentUnit.id, s.currentUnit.startedAt, buildSnapshotOpts(s.currentUnit.type, s.currentUnit.id));
2102
2236
  }
2103
- persistHookState(s.basePath);
2104
2237
 
2105
2238
  return enqueueSidecar(
2106
2239
  s, ctx,
@@ -2109,12 +2242,23 @@ export async function postUnitPostVerification(pctx: PostUnitContext): Promise<"
2109
2242
  );
2110
2243
  }
2111
2244
 
2245
+ const hookFailure = consumeHookFailure();
2246
+ if (hookFailure) {
2247
+ ctx.ui.notify(
2248
+ `Post-unit hook ${hookFailure.hookName} failed for ${hookFailure.unitId}: ${hookFailure.reason}. Pausing auto-mode.`,
2249
+ "warning",
2250
+ );
2251
+ await pauseAuto(ctx, pi);
2252
+ return "stopped";
2253
+ }
2254
+
2112
2255
  // Check if a hook requested a retry of the trigger unit
2113
2256
  if (isRetryPending()) {
2114
2257
  const trigger = consumeRetryTrigger();
2115
2258
  if (trigger) {
2259
+ persistHookState(s.basePath);
2116
2260
  ctx.ui.notify(
2117
- `Hook requested retry of ${trigger.unitType} ${trigger.unitId} — resetting task state.`,
2261
+ `Hook requested retry of ${trigger.unitType} ${trigger.unitId} — resetting trigger unit state.`,
2118
2262
  "info",
2119
2263
  );
2120
2264
 
@@ -2134,8 +2278,8 @@ export async function postUnitPostVerification(pctx: PostUnitContext): Promise<"
2134
2278
  await renderPlanCheckboxes(s.canonicalProjectRoot, mid, sid);
2135
2279
  } catch (dbErr) {
2136
2280
  // DB unavailable — fail explicitly rather than silently reverting to markdown mutation.
2137
- // Use 'gsd recover' to rebuild DB state from disk if needed.
2138
- logError("engine", `retry state-reset failed (DB unavailable): ${(dbErr as Error).message}. Run 'gsd recover' to reconcile.`);
2281
+ // Use 'gsd recover --confirm' to import markdown into the DB if needed.
2282
+ logError("engine", `retry state-reset failed (DB unavailable): ${(dbErr as Error).message}. Run 'gsd recover --confirm' to import markdown into the DB.`);
2139
2283
  }
2140
2284
  }
2141
2285
 
@@ -2168,6 +2312,19 @@ export async function postUnitPostVerification(pctx: PostUnitContext): Promise<"
2168
2312
  // Fall through to normal dispatch — deriveState will re-derive the unit
2169
2313
  }
2170
2314
  }
2315
+
2316
+ const gateBlock = consumeGateBlock();
2317
+ if (gateBlock) {
2318
+ persistHookState(s.basePath);
2319
+ const verdict = gateBlock.verdict ? ` verdict=${gateBlock.verdict};` : "";
2320
+ const artifact = gateBlock.artifact ? ` artifact=${gateBlock.artifact};` : "";
2321
+ const message =
2322
+ `Post-unit gate "${gateBlock.hookName}" blocked ${gateBlock.triggerUnitType} ${gateBlock.triggerUnitId}:` +
2323
+ `${verdict}${artifact} ${gateBlock.reason}. Run /gsd status to inspect, then /gsd auto after recovery.`;
2324
+ ctx.ui.notify(message, "warning");
2325
+ await pauseAuto(ctx, pi);
2326
+ return "stopped";
2327
+ }
2171
2328
  }
2172
2329
 
2173
2330
  // ── Fast-path stop detection (#3487) ──
@@ -45,6 +45,8 @@ import { classifyProject, type ProjectClassification } from "./detection.js";
45
45
  import { hasBrowserRequiredText } from "./browser-evidence.js";
46
46
  import { debugLog } from "./debug-logger.js";
47
47
  import { buildSkillActivationBlock, buildSkillDiscoveryVars } from "./skill-activation.js";
48
+ import { findMilestoneIds } from "./milestone-ids.js";
49
+ import { buildRunUatPresentationForType, RUN_UAT_TOOL_PRESENTATION_PLAN_ID } from "./tool-presentation-plan.js";
48
50
 
49
51
  export { buildSkillActivationBlock, buildSkillDiscoveryVars };
50
52
 
@@ -1428,7 +1430,7 @@ export async function checkNeedsRunUat(
1428
1430
  // If the UAT file already contains a verdict, UAT has been run — skip
1429
1431
  if (hasVerdict(uatContent)) continue;
1430
1432
  // Also check the ASSESSMENT file — the run-uat prompt writes the verdict
1431
- // there (via gsd_summary_save artifact_type:"ASSESSMENT"), not into the
1433
+ // there (via gsd_uat_result_save), not into the
1432
1434
  // UAT spec file. Without this check the unit re-dispatches indefinitely.
1433
1435
  const assessmentFile = resolveSliceFile(base, mid, sid, "ASSESSMENT");
1434
1436
  if (assessmentFile) {
@@ -1482,21 +1484,84 @@ export async function checkNeedsRunUat(
1482
1484
  * as a seed when present. The discussion agent interviews the user, writes
1483
1485
  * a full CONTEXT.md, and the phase transitions to pre-planning automatically.
1484
1486
  */
1487
+ export interface DiscussMilestonePromptOptions {
1488
+ headless?: boolean;
1489
+ commitInstruction?: string;
1490
+ fastPathInstruction?: string;
1491
+ includeDraftSeed?: boolean;
1492
+ includeContextMode?: boolean;
1493
+ }
1494
+
1495
+ export async function buildDiscussMilestoneInlinedContext(mid: string, base: string): Promise<string> {
1496
+ const inlined: string[] = [];
1497
+
1498
+ const roadmapInline = await inlineFileOptional(
1499
+ resolveMilestoneFile(base, mid, "ROADMAP"),
1500
+ relMilestoneFile(base, mid, "ROADMAP"),
1501
+ "Milestone Roadmap",
1502
+ );
1503
+ if (roadmapInline) inlined.push(roadmapInline);
1504
+
1505
+ const contextInline = await inlineFileOptional(
1506
+ resolveMilestoneFile(base, mid, "CONTEXT"),
1507
+ relMilestoneFile(base, mid, "CONTEXT"),
1508
+ "Milestone Context",
1509
+ );
1510
+ if (contextInline) inlined.push(contextInline);
1511
+
1512
+ const researchInline = await inlineFileOptional(
1513
+ resolveMilestoneFile(base, mid, "RESEARCH"),
1514
+ relMilestoneFile(base, mid, "RESEARCH"),
1515
+ "Milestone Research",
1516
+ );
1517
+ if (researchInline) inlined.push(researchInline);
1518
+
1519
+ const decisionsPath = resolveGsdRootFile(base, "DECISIONS");
1520
+ if (existsSync(decisionsPath)) {
1521
+ const decisionsContent = await loadFile(decisionsPath);
1522
+ if (decisionsContent) {
1523
+ inlined.push(`### Decisions Register\nSource: \`${relGsdRootFile("DECISIONS")}\`\n\n${decisionsContent.trim()}`);
1524
+ }
1525
+ }
1526
+
1527
+ const milestoneIds = findMilestoneIds(base);
1528
+ const currentIndex = milestoneIds.indexOf(mid);
1529
+ const priorMilestoneIds = currentIndex >= 0 ? milestoneIds.slice(0, currentIndex) : milestoneIds;
1530
+ for (const priorMid of priorMilestoneIds) {
1531
+ const summaryInline = await inlineFileOptional(
1532
+ resolveMilestoneFile(base, priorMid, "SUMMARY"),
1533
+ relMilestoneFile(base, priorMid, "SUMMARY"),
1534
+ `${priorMid} Prior Milestone Summary`,
1535
+ );
1536
+ if (summaryInline) inlined.push(summaryInline);
1537
+ }
1538
+
1539
+ return inlined.length > 0
1540
+ ? `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`
1541
+ : "## Inlined Context\n\n_(no milestone context files found yet — go in blind and ask broad questions)_";
1542
+ }
1543
+
1485
1544
  export async function buildDiscussMilestonePrompt(
1486
1545
  mid: string,
1487
1546
  midTitle: string,
1488
1547
  base: string,
1489
1548
  structuredQuestionsAvailable = "false",
1490
- { headless = false }: { headless?: boolean } = {},
1549
+ {
1550
+ headless = false,
1551
+ commitInstruction = "Do not commit planning artifacts — .gsd/ is managed externally.",
1552
+ fastPathInstruction = "",
1553
+ includeDraftSeed = true,
1554
+ includeContextMode = true,
1555
+ }: DiscussMilestonePromptOptions = {},
1491
1556
  ): Promise<string> {
1492
- const discussTemplates = inlineTemplate("context", "Context");
1557
+ const contextTemplate = inlineTemplate("context", "Context");
1493
1558
 
1494
1559
  if (headless) {
1495
1560
  const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
1496
1561
  const roadmapContent = roadmapPath ? await loadFile(roadmapPath) : null;
1497
1562
  return loadPrompt("discuss-headless", {
1498
1563
  seedContext: roadmapContent ?? "",
1499
- inlinedTemplates: discussTemplates,
1564
+ inlinedTemplates: contextTemplate,
1500
1565
  workingDirectory: base,
1501
1566
  milestoneId: mid,
1502
1567
  contextPath: relMilestoneFile(base, mid, "CONTEXT"),
@@ -1505,7 +1570,9 @@ export async function buildDiscussMilestonePrompt(
1505
1570
  });
1506
1571
  }
1507
1572
 
1508
- const contextModeInstructions = renderContextModeForPrompt("discuss-milestone", base);
1573
+ const rawInlinedContext = await buildDiscussMilestoneInlinedContext(mid, base);
1574
+ const cappedInlinedContext = capPreamble(rawInlinedContext);
1575
+ const discussTemplates = [cappedInlinedContext, contextTemplate].join("\n\n---\n\n");
1509
1576
 
1510
1577
  const basePrompt = loadPrompt("guided-discuss-milestone", {
1511
1578
  workingDirectory: base,
@@ -1513,20 +1580,22 @@ export async function buildDiscussMilestonePrompt(
1513
1580
  milestoneTitle: midTitle,
1514
1581
  inlinedTemplates: discussTemplates,
1515
1582
  structuredQuestionsAvailable,
1516
- commitInstruction: "Do not commit planning artifacts — .gsd/ is managed externally.",
1517
- fastPathInstruction: "",
1583
+ commitInstruction,
1584
+ fastPathInstruction,
1518
1585
  });
1519
- const promptWithContextMode = prependContextModeToBlock("discuss-milestone", base, basePrompt);
1586
+ const promptWithContextMode = includeContextMode
1587
+ ? prependContextModeToBlock("discuss-milestone", base, basePrompt)
1588
+ : basePrompt;
1520
1589
 
1521
1590
  // If a CONTEXT-DRAFT.md exists, append it as seed material
1522
1591
  const draftPath = resolveMilestoneFile(base, mid, "CONTEXT-DRAFT");
1523
1592
  const draftContent = draftPath ? await loadFile(draftPath) : null;
1524
1593
 
1525
- if (draftContent) {
1594
+ if (includeDraftSeed && draftContent) {
1526
1595
  return `${promptWithContextMode}\n\n## Prior Discussion (Draft Seed)\n\nThe following draft was captured from a prior multi-milestone discussion. Use it as seed material — the user has already provided this context. Start with a brief reflection on what the draft covers, then probe for any gaps or open questions before writing the full CONTEXT.md.\n\n${draftContent}`;
1527
1596
  }
1528
1597
 
1529
- return contextModeInstructions ? promptWithContextMode : basePrompt;
1598
+ return promptWithContextMode;
1530
1599
  }
1531
1600
 
1532
1601
  /**
@@ -2711,6 +2780,15 @@ export async function buildCompleteSlicePrompt(
2711
2780
  sliceSummaryPath,
2712
2781
  sliceUatPath,
2713
2782
  gatesToClose,
2783
+ skillActivation: buildSkillActivationBlock({
2784
+ base,
2785
+ milestoneId: mid,
2786
+ milestoneTitle: midTitle,
2787
+ sliceId: sid,
2788
+ sliceTitle: sTitle,
2789
+ extraContext: [inlinedContext],
2790
+ unitType: "complete-slice",
2791
+ }),
2714
2792
  });
2715
2793
  }
2716
2794
 
@@ -2909,13 +2987,23 @@ export async function buildValidateMilestonePrompt(
2909
2987
  if (isDbAvailable()) {
2910
2988
  const milestone = getMilestone(mid);
2911
2989
  if (milestone) {
2990
+ const escapeCell = (value: string) =>
2991
+ value.replace(/[\\|]/g, (char) => `\\${char}`).replace(/\r?\n/g, " ");
2912
2992
  const classes: string[] = [];
2913
- if (milestone.verification_contract) classes.push(`- **Contract:** ${milestone.verification_contract}`);
2914
- if (milestone.verification_integration) classes.push(`- **Integration:** ${milestone.verification_integration}`);
2915
- if (milestone.verification_operational) classes.push(`- **Operational:** ${milestone.verification_operational}`);
2916
- if (milestone.verification_uat) classes.push(`- **UAT:** ${milestone.verification_uat}`);
2993
+ if (milestone.verification_contract) classes.push(`| Contract | ${escapeCell(milestone.verification_contract)} |`);
2994
+ if (milestone.verification_integration) classes.push(`| Integration | ${escapeCell(milestone.verification_integration)} |`);
2995
+ if (milestone.verification_operational) classes.push(`| Operational | ${escapeCell(milestone.verification_operational)} |`);
2996
+ if (milestone.verification_uat) classes.push(`| UAT | ${escapeCell(milestone.verification_uat)} |`);
2917
2997
  if (classes.length > 0) {
2918
- const verificationClasses = `### Verification Classes (from planning)\n\nThese verification tiers were defined during milestone planning. Each non-empty class must be checked for evidence during validation.\n\n${classes.join("\n")}`;
2998
+ const verificationClasses = [
2999
+ "### Verification Classes (from planning)",
3000
+ "",
3001
+ "These verification tiers were defined during milestone planning. Every row in this table must appear in `verificationClasses` with the same canonical class name.",
3002
+ "",
3003
+ "| Class | Planned Check |",
3004
+ "| --- | --- |",
3005
+ ...classes,
3006
+ ].join("\n");
2919
3007
  inlined.push(verificationClasses);
2920
3008
  trackPromptContext(contextTelemetry, "verification-classes", "inline", verificationClasses);
2921
3009
  }
@@ -3297,6 +3385,7 @@ export async function buildRunUatPrompt(
3297
3385
 
3298
3386
  const uatResultPath = join(base, relSliceFile(base, mid, sliceId, "ASSESSMENT"));
3299
3387
  const uatType = resolveEffectiveUatType(uatContent);
3388
+ const canonicalPresentation = JSON.stringify(buildRunUatPresentationForType(uatType), null, 2);
3300
3389
 
3301
3390
  return loadPrompt("run-uat", {
3302
3391
  workingDirectory: base,
@@ -3305,6 +3394,8 @@ export async function buildRunUatPrompt(
3305
3394
  uatPath,
3306
3395
  uatResultPath,
3307
3396
  uatType,
3397
+ toolPresentationPlanId: RUN_UAT_TOOL_PRESENTATION_PLAN_ID,
3398
+ canonicalPresentation,
3308
3399
  inlinedContext,
3309
3400
  skillActivation: buildSkillActivationBlock({
3310
3401
  base,
@@ -54,6 +54,7 @@ import { isGsdWorktreePath } from "./worktree-root.js";
54
54
  import { resolveCanonicalMilestoneRoot } from "./worktree-manager.js";
55
55
  import { hasImplementationArtifacts } from "./milestone-implementation-evidence.js";
56
56
  import { loadAllCaptures, loadPendingCaptures } from "./captures.js";
57
+ import { checkCloseoutConsistencyGate } from "./closeout-consistency-gate.js";
57
58
 
58
59
  // Re-export so existing consumers of auto-recovery.ts keep working.
59
60
  export { resolveExpectedArtifactPath, diagnoseExpectedArtifact };
@@ -626,9 +627,8 @@ export function verifyExpectedArtifact(
626
627
  if (summaryOutcome === "failure") return false;
627
628
  const { milestone: mid } = parseUnitId(unitId);
628
629
  if (mid && isDbAvailable()) {
629
- const dbMilestone = getMilestone(mid);
630
- if (!dbMilestone) return false;
631
- if (!isClosedStatus(dbMilestone.status) && summaryOutcome !== "success") return false;
630
+ const closeoutGate = checkCloseoutConsistencyGate(mid, { refreshFromDisk: true });
631
+ if (!closeoutGate.ok) return false;
632
632
  }
633
633
  if (hasImplementationArtifacts(base, mid) === "absent") return false;
634
634
  }
@@ -867,7 +867,7 @@ export function buildLoopRemediationSteps(
867
867
  return [
868
868
  ` 1. Run \`gsd undo-task ${mid}/${sid}/${tid}\` to reset the task state`,
869
869
  ` 2. Resume auto-mode — it will re-execute the task`,
870
- ` 3. If the task keeps failing, run \`gsd recover\` to rebuild DB state from disk`,
870
+ ` 3. If the task keeps failing and markdown should repopulate the DB, run \`gsd recover --confirm\``,
871
871
  ].join("\n");
872
872
  }
873
873
  case "plan-slice":
@@ -879,7 +879,7 @@ export function buildLoopRemediationSteps(
879
879
  : relSliceFile(base, mid, sid, "RESEARCH");
880
880
  return [
881
881
  ` 1. Write ${artifactRel} manually (or with the LLM in interactive mode)`,
882
- ` 2. Run \`gsd recover\` to rebuild DB state from disk`,
882
+ ` 2. Run \`gsd recover --confirm\` to import the markdown into the DB`,
883
883
  ` 3. Resume auto-mode`,
884
884
  ].join("\n");
885
885
  }
@@ -888,7 +888,7 @@ export function buildLoopRemediationSteps(
888
888
  return [
889
889
  ` 1. Run \`gsd reset-slice ${mid}/${sid}\` to reset the slice and all its tasks`,
890
890
  ` 2. Resume auto-mode — it will re-execute incomplete tasks and re-complete the slice`,
891
- ` 3. If the slice keeps failing, run \`gsd recover\` to rebuild DB state from disk`,
891
+ ` 3. If the slice keeps failing and markdown should repopulate the DB, run \`gsd recover --confirm\``,
892
892
  ].join("\n");
893
893
  }
894
894
  case "validate-milestone": {
@@ -896,7 +896,7 @@ export function buildLoopRemediationSteps(
896
896
  const artifactRel = relMilestoneFile(base, mid, "VALIDATION");
897
897
  return [
898
898
  ` 1. Write ${artifactRel} with verdict: pass`,
899
- ` 2. Run \`gsd recover\` to rebuild DB state from disk`,
899
+ ` 2. Run \`gsd recover --confirm\` to import the markdown into the DB`,
900
900
  ` 3. Resume auto-mode`,
901
901
  ].join("\n");
902
902
  }
@@ -42,6 +42,10 @@ export function isAutoPaused(): boolean {
42
42
  return autoSession.paused;
43
43
  }
44
44
 
45
+ export function isAutoCompletionStopInProgress(): boolean {
46
+ return autoSession.completionStopInProgress;
47
+ }
48
+
45
49
  export function markToolStart(toolCallId: string, toolName?: string): void {
46
50
  markTrackedToolStart(toolCallId, autoSession.active, toolName);
47
51
  }