@opengsd/gsd-pi 1.1.1-dev.616a1a1 → 1.1.1-dev.9bb7453

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 (395) 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 +44 -0
  14. package/dist/resources/extensions/gsd/auto-post-unit.js +134 -10
  15. package/dist/resources/extensions/gsd/auto-prompts.js +68 -22
  16. package/dist/resources/extensions/gsd/auto-recovery.js +4 -4
  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 +2 -1
  21. package/dist/resources/extensions/gsd/auto.js +31 -6
  22. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +83 -4
  23. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +43 -0
  24. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +39 -14
  25. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +16 -10
  26. package/dist/resources/extensions/gsd/browser-evidence.js +29 -2
  27. package/dist/resources/extensions/gsd/commands/catalog.js +6 -1
  28. package/dist/resources/extensions/gsd/commands/handlers/core.js +6 -2
  29. package/dist/resources/extensions/gsd/commands/handlers/ops.js +9 -5
  30. package/dist/resources/extensions/gsd/commands-handlers.js +76 -11
  31. package/dist/resources/extensions/gsd/commands-maintenance.js +172 -2
  32. package/dist/resources/extensions/gsd/commands-mcp-status.js +109 -60
  33. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +3 -1
  34. package/dist/resources/extensions/gsd/commands-verdict.js +1 -1
  35. package/dist/resources/extensions/gsd/config-overlay.js +2 -1
  36. package/dist/resources/extensions/gsd/dashboard-overlay.js +21 -7
  37. package/dist/resources/extensions/gsd/docs/preferences-reference.md +8 -0
  38. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +2 -2
  39. package/dist/resources/extensions/gsd/error-classifier.js +2 -1
  40. package/dist/resources/extensions/gsd/escalation.js +4 -4
  41. package/dist/resources/extensions/gsd/exec-sandbox.js +2 -0
  42. package/dist/resources/extensions/gsd/forensics.js +74 -2
  43. package/dist/resources/extensions/gsd/gsd-db.js +42 -6
  44. package/dist/resources/extensions/gsd/guided-flow.js +30 -69
  45. package/dist/resources/extensions/gsd/mcp-filter.js +3 -0
  46. package/dist/resources/extensions/gsd/mcp-project-config.js +76 -84
  47. package/dist/resources/extensions/gsd/memory-store.js +4 -1
  48. package/dist/resources/extensions/gsd/migration-auto-check.js +2 -2
  49. package/dist/resources/extensions/gsd/post-unit-hooks.js +9 -0
  50. package/dist/resources/extensions/gsd/preferences-validation.js +39 -0
  51. package/dist/resources/extensions/gsd/prompt-loader.js +7 -0
  52. package/dist/resources/extensions/gsd/prompts/forensics.md +61 -1
  53. package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +3 -1
  54. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +3 -1
  55. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  56. package/dist/resources/extensions/gsd/prompts/reactive-execute.md +3 -1
  57. package/dist/resources/extensions/gsd/prompts/run-uat.md +48 -24
  58. package/dist/resources/extensions/gsd/prompts/system.md +3 -1
  59. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +3 -3
  60. package/dist/resources/extensions/gsd/rule-registry.js +428 -52
  61. package/dist/resources/extensions/gsd/safety/destructive-guard.js +3 -0
  62. package/dist/resources/extensions/gsd/skill-activation.js +20 -3
  63. package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +4 -2
  64. package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +1 -1
  65. package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +18 -1
  66. package/dist/resources/extensions/gsd/state-reconciliation/index.js +6 -0
  67. package/dist/resources/extensions/gsd/state.js +17 -14
  68. package/dist/resources/extensions/gsd/templates/plan.md +3 -1
  69. package/dist/resources/extensions/gsd/tool-presentation-plan.js +120 -0
  70. package/dist/resources/extensions/gsd/tools/complete-slice.js +15 -1
  71. package/dist/resources/extensions/gsd/tools/complete-task.js +11 -1
  72. package/dist/resources/extensions/gsd/tools/exec-tool.js +109 -0
  73. package/dist/resources/extensions/gsd/tools/plan-slice.js +14 -9
  74. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +2 -2
  75. package/dist/resources/extensions/gsd/tools/validate-milestone.js +46 -16
  76. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +403 -3
  77. package/dist/resources/extensions/gsd/unit-context-manifest.js +8 -3
  78. package/dist/resources/extensions/gsd/validation-block-guard.js +2 -0
  79. package/dist/resources/extensions/gsd/verdict-parser.js +59 -15
  80. package/dist/resources/extensions/gsd/verification-gate.js +72 -1
  81. package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +3 -1
  82. package/dist/resources/extensions/gsd/workflow-mcp.js +5 -1
  83. package/dist/resources/extensions/gsd/worktree-lifecycle.js +24 -0
  84. package/dist/resources/extensions/mcp-client/manager.js +31 -1
  85. package/dist/resources/extensions/shared/gsd-browser-cli.js +145 -0
  86. package/dist/rtk.d.ts +7 -1
  87. package/dist/rtk.js +27 -11
  88. package/dist/update-check.d.ts +15 -1
  89. package/dist/update-check.js +87 -12
  90. package/dist/update-cmd.d.ts +1 -0
  91. package/dist/update-cmd.js +53 -2
  92. package/dist/web/standalone/.next/BUILD_ID +1 -1
  93. package/dist/web/standalone/.next/app-path-routes-manifest.json +6 -6
  94. package/dist/web/standalone/.next/build-manifest.json +2 -2
  95. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  96. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  105. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  113. package/dist/web/standalone/.next/server/app/index.html +1 -1
  114. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app-paths-manifest.json +6 -6
  121. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  122. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  124. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  125. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  126. package/package.json +5 -3
  127. package/packages/cloud-mcp-gateway/package.json +2 -2
  128. package/packages/contracts/dist/workflow.d.ts +14 -0
  129. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  130. package/packages/contracts/dist/workflow.js +16 -0
  131. package/packages/contracts/dist/workflow.js.map +1 -1
  132. package/packages/contracts/package.json +1 -1
  133. package/packages/daemon/package.json +4 -4
  134. package/packages/gsd-agent-core/dist/agent-session.d.ts +9 -0
  135. package/packages/gsd-agent-core/dist/agent-session.d.ts.map +1 -1
  136. package/packages/gsd-agent-core/dist/agent-session.js +32 -0
  137. package/packages/gsd-agent-core/dist/agent-session.js.map +1 -1
  138. package/packages/gsd-agent-core/dist/index.d.ts +1 -0
  139. package/packages/gsd-agent-core/dist/index.d.ts.map +1 -1
  140. package/packages/gsd-agent-core/dist/index.js +1 -0
  141. package/packages/gsd-agent-core/dist/index.js.map +1 -1
  142. package/packages/gsd-agent-core/dist/session/agent-session-compaction.d.ts +2 -0
  143. package/packages/gsd-agent-core/dist/session/agent-session-compaction.d.ts.map +1 -1
  144. package/packages/gsd-agent-core/dist/session/agent-session-compaction.js +8 -2
  145. package/packages/gsd-agent-core/dist/session/agent-session-compaction.js.map +1 -1
  146. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts +7 -0
  147. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts.map +1 -1
  148. package/packages/gsd-agent-core/dist/session/agent-session-host.js.map +1 -1
  149. package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts.map +1 -1
  150. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js +69 -1
  151. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js.map +1 -1
  152. package/packages/gsd-agent-core/dist/turn-latency.d.ts +47 -0
  153. package/packages/gsd-agent-core/dist/turn-latency.d.ts.map +1 -0
  154. package/packages/gsd-agent-core/dist/turn-latency.js +123 -0
  155. package/packages/gsd-agent-core/dist/turn-latency.js.map +1 -0
  156. package/packages/gsd-agent-core/package.json +6 -6
  157. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts +21 -0
  158. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts.map +1 -0
  159. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js +213 -0
  160. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js.map +1 -0
  161. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  162. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  163. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js +10 -0
  164. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js.map +1 -1
  165. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts +1 -0
  166. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  167. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +92 -31
  168. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  169. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  170. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +7 -1
  171. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  172. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.d.ts.map +1 -1
  173. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.js +6 -0
  174. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.js.map +1 -1
  175. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-dialogs.d.ts.map +1 -1
  176. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-dialogs.js +2 -0
  177. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-dialogs.js.map +1 -1
  178. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts +1 -1
  179. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts.map +1 -1
  180. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js +1 -1
  181. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js.map +1 -1
  182. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  183. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +1 -0
  184. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
  185. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.d.ts.map +1 -1
  186. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js +5 -0
  187. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js.map +1 -1
  188. package/packages/gsd-agent-modes/package.json +7 -7
  189. package/packages/mcp-server/dist/remote-questions.d.ts.map +1 -1
  190. package/packages/mcp-server/dist/remote-questions.js +23 -9
  191. package/packages/mcp-server/dist/remote-questions.js.map +1 -1
  192. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  193. package/packages/mcp-server/dist/workflow-tools.js +84 -2
  194. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  195. package/packages/mcp-server/package.json +3 -3
  196. package/packages/native/package.json +1 -1
  197. package/packages/pi-agent-core/dist/agent-loop.js +38 -0
  198. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  199. package/packages/pi-agent-core/dist/agent.d.ts +5 -1
  200. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  201. package/packages/pi-agent-core/dist/agent.js +2 -0
  202. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  203. package/packages/pi-agent-core/dist/types.d.ts +3 -0
  204. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  205. package/packages/pi-agent-core/dist/types.js.map +1 -1
  206. package/packages/pi-agent-core/package.json +1 -1
  207. package/packages/pi-ai/dist/api-registry.d.ts +2 -0
  208. package/packages/pi-ai/dist/api-registry.d.ts.map +1 -1
  209. package/packages/pi-ai/dist/api-registry.js +23 -0
  210. package/packages/pi-ai/dist/api-registry.js.map +1 -1
  211. package/packages/pi-ai/dist/image-models.generated.d.ts +15 -0
  212. package/packages/pi-ai/dist/image-models.generated.d.ts.map +1 -1
  213. package/packages/pi-ai/dist/image-models.generated.js +15 -0
  214. package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
  215. package/packages/pi-ai/dist/models.generated.d.ts +406 -17
  216. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  217. package/packages/pi-ai/dist/models.generated.js +484 -116
  218. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  219. package/packages/pi-ai/dist/stream.js +6 -6
  220. package/packages/pi-ai/dist/stream.js.map +1 -1
  221. package/packages/pi-ai/package.json +1 -1
  222. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  223. package/packages/pi-coding-agent/dist/core/model-registry.js +2 -2
  224. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  225. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
  226. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  227. package/packages/pi-coding-agent/dist/core/settings-manager.js +11 -0
  228. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  229. package/packages/pi-coding-agent/package.json +7 -7
  230. package/packages/pi-tui/dist/terminal.d.ts +1 -0
  231. package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
  232. package/packages/pi-tui/dist/terminal.js +8 -4
  233. package/packages/pi-tui/dist/terminal.js.map +1 -1
  234. package/packages/pi-tui/package.json +1 -1
  235. package/packages/rpc-client/package.json +2 -2
  236. package/pkg/package.json +1 -1
  237. package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +579 -0
  238. package/src/resources/extensions/browser-tools/engine/selection.ts +19 -0
  239. package/src/resources/extensions/browser-tools/extension-manifest.json +2 -2
  240. package/src/resources/extensions/browser-tools/index.ts +60 -9
  241. package/src/resources/extensions/browser-tools/package.json +5 -1
  242. package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +35 -0
  243. package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +33 -0
  244. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +196 -16
  245. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +239 -63
  246. package/src/resources/extensions/gsd/auto/orchestrator.ts +0 -1
  247. package/src/resources/extensions/gsd/auto/phases.ts +5 -3
  248. package/src/resources/extensions/gsd/auto-dashboard.ts +98 -18
  249. package/src/resources/extensions/gsd/auto-dispatch.ts +53 -0
  250. package/src/resources/extensions/gsd/auto-post-unit.ts +166 -9
  251. package/src/resources/extensions/gsd/auto-prompts.ts +102 -15
  252. package/src/resources/extensions/gsd/auto-recovery.ts +4 -4
  253. package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -0
  254. package/src/resources/extensions/gsd/auto-start.ts +112 -17
  255. package/src/resources/extensions/gsd/auto-tool-tracking.ts +1 -1
  256. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +2 -1
  257. package/src/resources/extensions/gsd/auto.ts +47 -5
  258. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +90 -4
  259. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +51 -0
  260. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +60 -19
  261. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +21 -10
  262. package/src/resources/extensions/gsd/browser-evidence.ts +26 -2
  263. package/src/resources/extensions/gsd/commands/catalog.ts +6 -1
  264. package/src/resources/extensions/gsd/commands/handlers/core.ts +6 -2
  265. package/src/resources/extensions/gsd/commands/handlers/ops.ts +9 -5
  266. package/src/resources/extensions/gsd/commands-handlers.ts +76 -11
  267. package/src/resources/extensions/gsd/commands-maintenance.ts +197 -2
  268. package/src/resources/extensions/gsd/commands-mcp-status.ts +136 -58
  269. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +4 -1
  270. package/src/resources/extensions/gsd/commands-verdict.ts +1 -1
  271. package/src/resources/extensions/gsd/config-overlay.ts +3 -1
  272. package/src/resources/extensions/gsd/dashboard-overlay.ts +28 -7
  273. package/src/resources/extensions/gsd/docs/preferences-reference.md +8 -0
  274. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +2 -2
  275. package/src/resources/extensions/gsd/error-classifier.ts +2 -1
  276. package/src/resources/extensions/gsd/escalation.ts +4 -4
  277. package/src/resources/extensions/gsd/exec-sandbox.ts +4 -0
  278. package/src/resources/extensions/gsd/forensics.ts +99 -5
  279. package/src/resources/extensions/gsd/gsd-db.ts +46 -8
  280. package/src/resources/extensions/gsd/guided-flow.ts +91 -83
  281. package/src/resources/extensions/gsd/mcp-filter.ts +3 -0
  282. package/src/resources/extensions/gsd/mcp-project-config.ts +105 -88
  283. package/src/resources/extensions/gsd/memory-store.ts +4 -1
  284. package/src/resources/extensions/gsd/migration-auto-check.ts +2 -2
  285. package/src/resources/extensions/gsd/post-unit-hooks.ts +14 -1
  286. package/src/resources/extensions/gsd/preferences-types.ts +1 -1
  287. package/src/resources/extensions/gsd/preferences-validation.ts +36 -0
  288. package/src/resources/extensions/gsd/prompt-loader.ts +8 -0
  289. package/src/resources/extensions/gsd/prompts/forensics.md +61 -1
  290. package/src/resources/extensions/gsd/prompts/gate-evaluate.md +3 -1
  291. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +3 -1
  292. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  293. package/src/resources/extensions/gsd/prompts/reactive-execute.md +3 -1
  294. package/src/resources/extensions/gsd/prompts/run-uat.md +48 -24
  295. package/src/resources/extensions/gsd/prompts/system.md +3 -1
  296. package/src/resources/extensions/gsd/prompts/validate-milestone.md +3 -3
  297. package/src/resources/extensions/gsd/rule-registry.ts +558 -58
  298. package/src/resources/extensions/gsd/rule-types.ts +2 -0
  299. package/src/resources/extensions/gsd/safety/destructive-guard.ts +3 -0
  300. package/src/resources/extensions/gsd/skill-activation.ts +20 -2
  301. package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +4 -2
  302. package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +1 -1
  303. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +20 -0
  304. package/src/resources/extensions/gsd/state-reconciliation/index.ts +6 -0
  305. package/src/resources/extensions/gsd/state-reconciliation/types.ts +1 -0
  306. package/src/resources/extensions/gsd/state.ts +18 -14
  307. package/src/resources/extensions/gsd/templates/plan.md +3 -1
  308. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +156 -4
  309. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +123 -0
  310. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +143 -2
  311. package/src/resources/extensions/gsd/tests/auto-start-project-milestone-reconcile.test.ts +24 -2
  312. package/src/resources/extensions/gsd/tests/browser-evidence.test.ts +142 -0
  313. package/src/resources/extensions/gsd/tests/commands-dispatcher-validation-block.test.ts +38 -3
  314. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +6 -2
  315. package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +30 -0
  316. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
  317. package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +45 -0
  318. package/src/resources/extensions/gsd/tests/deep-planning-mode-dispatch.test.ts +53 -0
  319. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +8 -0
  320. package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +50 -13
  321. package/src/resources/extensions/gsd/tests/discuss-milestone-structured-questions.test.ts +31 -0
  322. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +60 -0
  323. package/src/resources/extensions/gsd/tests/doctor-runtime-checks.test.ts +27 -0
  324. package/src/resources/extensions/gsd/tests/escalation.test.ts +16 -27
  325. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +18 -0
  326. package/src/resources/extensions/gsd/tests/exec-tool.test.ts +69 -0
  327. package/src/resources/extensions/gsd/tests/forensics-issue-routing.test.ts +20 -0
  328. package/src/resources/extensions/gsd/tests/forensics-prompt-rendering.test.ts +3 -0
  329. package/src/resources/extensions/gsd/tests/forensics-tool-scope.test.ts +69 -0
  330. package/src/resources/extensions/gsd/tests/gsd-rebuild.test.ts +199 -0
  331. package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +75 -0
  332. package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +40 -1
  333. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +86 -0
  334. package/src/resources/extensions/gsd/tests/guided-flow.test.ts +12 -9
  335. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +4 -4
  336. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +66 -10
  337. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +13 -6
  338. package/src/resources/extensions/gsd/tests/mcp-filter.test.ts +15 -0
  339. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +100 -0
  340. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +179 -0
  341. package/src/resources/extensions/gsd/tests/memory-maintenance.test.ts +39 -8
  342. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +3 -3
  343. package/src/resources/extensions/gsd/tests/new-milestone-discuss-routing.test.ts +3 -3
  344. package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +54 -7
  345. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +9 -0
  346. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +39 -1
  347. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +157 -0
  348. package/src/resources/extensions/gsd/tests/post-unit-retry-on-orchestrator-bridge.test.ts +179 -0
  349. package/src/resources/extensions/gsd/tests/preferences.test.ts +29 -0
  350. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +53 -1
  351. package/src/resources/extensions/gsd/tests/prompt-loader-extension-dir.test.ts +14 -0
  352. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +18 -1
  353. package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +7 -8
  354. package/src/resources/extensions/gsd/tests/reactive-executor.test.ts +36 -0
  355. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +35 -0
  356. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +1 -1
  357. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +75 -0
  358. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +100 -0
  359. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +55 -0
  360. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +6 -2
  361. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +191 -0
  362. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +84 -10
  363. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +19 -0
  364. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +12 -2
  365. package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +7 -1
  366. package/src/resources/extensions/gsd/tests/tui-header-lifecycle.test.ts +29 -6
  367. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +29 -6
  368. package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +6 -3
  369. package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +133 -0
  370. package/src/resources/extensions/gsd/tests/validation-block-guard.test.ts +21 -0
  371. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +51 -0
  372. package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +17 -2
  373. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +213 -0
  374. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +25 -0
  375. package/src/resources/extensions/gsd/tool-presentation-plan.ts +167 -0
  376. package/src/resources/extensions/gsd/tools/complete-slice.ts +14 -1
  377. package/src/resources/extensions/gsd/tools/complete-task.ts +20 -2
  378. package/src/resources/extensions/gsd/tools/exec-tool.ts +130 -0
  379. package/src/resources/extensions/gsd/tools/plan-slice.ts +14 -9
  380. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +2 -2
  381. package/src/resources/extensions/gsd/tools/validate-milestone.ts +46 -15
  382. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +489 -3
  383. package/src/resources/extensions/gsd/types.ts +69 -5
  384. package/src/resources/extensions/gsd/unit-context-manifest.ts +14 -5
  385. package/src/resources/extensions/gsd/validation-block-guard.ts +2 -0
  386. package/src/resources/extensions/gsd/verdict-parser.ts +54 -13
  387. package/src/resources/extensions/gsd/verification-gate.ts +87 -1
  388. package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +2 -1
  389. package/src/resources/extensions/gsd/workflow-mcp.ts +5 -1
  390. package/src/resources/extensions/gsd/worktree-lifecycle.ts +26 -0
  391. package/src/resources/extensions/mcp-client/manager.ts +33 -1
  392. package/src/resources/extensions/mcp-client/tests/manager.test.ts +35 -0
  393. package/src/resources/extensions/shared/gsd-browser-cli.ts +172 -0
  394. /package/dist/web/standalone/.next/static/{L9N5SPFi7f-Ne4u2uXzCe → jBtwT9v1u2lUA3UEOy_ZH}/_buildManifest.js +0 -0
  395. /package/dist/web/standalone/.next/static/{L9N5SPFi7f-Ne4u2uXzCe → jBtwT9v1u2lUA3UEOy_ZH}/_ssgManifest.js +0 -0
@@ -22,6 +22,20 @@ test("resolveExtensionDirFromCandidates prefers user-local dir when both trees a
22
22
  assert.equal(resolved, agentDir);
23
23
  });
24
24
 
25
+ test("resolveExtensionDirFromCandidates prefers source checkout dir when both trees are valid", () => {
26
+ const moduleDir = "/repo/src/resources/extensions/gsd";
27
+ const agentDir = "/home/user/.gsd/agent/extensions/gsd";
28
+ const paths = new Set<string>([
29
+ join(moduleDir, "prompts"),
30
+ join(moduleDir, "templates", "task-summary.md"),
31
+ join(agentDir, "prompts"),
32
+ join(agentDir, "templates", "task-summary.md"),
33
+ ]);
34
+
35
+ const resolved = resolveExtensionDirFromCandidates(moduleDir, agentDir, makeExists(paths));
36
+ assert.equal(resolved, moduleDir);
37
+ });
38
+
25
39
  test("resolveExtensionDirFromCandidates rejects module dir missing task-summary template", () => {
26
40
  const moduleDir = "/npm/global/gsd";
27
41
  const agentDir = "/home/user/.gsd/agent/extensions/gsd";
@@ -17,7 +17,10 @@ import {
17
17
  shouldDeferTransientErrorToCoreRetry,
18
18
  suppressTerminalDeletedWorktreeMessageEnd,
19
19
  } from "../bootstrap/agent-end-recovery.ts";
20
- import { _buildCancelledUnitStopReason } from "../auto/phases.ts";
20
+ import {
21
+ _buildCancelledUnitStopReason,
22
+ _classifyZeroToolProviderMessageForTest,
23
+ } from "../auto/phases.ts";
21
24
  import { autoSession } from "../auto-runtime-state.ts";
22
25
  import { getNextFallbackModel } from "../preferences.ts";
23
26
  // Zero-import module — imported by path rather than through the package
@@ -53,6 +56,20 @@ test("classifyError treats usage-limit phrasing as transient rate-limit (#4373)"
53
56
  assert.equal(result.kind, "rate-limit");
54
57
  });
55
58
 
59
+ test("zero-tool provider classifier treats Claude session-limit wording as transient rate-limit (#371)", () => {
60
+ const result = _classifyZeroToolProviderMessageForTest("Claude Code session limit reached. Limit resets at 5 PM.");
61
+ assert.ok(result, "session-limit wording should be recognized");
62
+ assert.ok(isTransient(result));
63
+ assert.equal(result.kind, "rate-limit");
64
+ });
65
+
66
+ test("zero-tool provider classifier treats weekly limit wording as transient rate-limit (#371)", () => {
67
+ const result = _classifyZeroToolProviderMessageForTest("You've reached your weekly limit. Try again later.");
68
+ assert.ok(result, "weekly limit wording should be recognized");
69
+ assert.ok(isTransient(result));
70
+ assert.equal(result.kind, "rate-limit");
71
+ });
72
+
56
73
  test("classifyError treats extra-usage phrasing as transient rate-limit (#4397)", () => {
57
74
  const result = classifyError("You are out of extra usage. Please wait before retrying.");
58
75
  assert.ok(isTransient(result));
@@ -24,25 +24,24 @@ describe("queued-discuss-fast-path", () => {
24
24
  );
25
25
  });
26
26
 
27
- test("2. dispatchDiscussForMilestone computes fastPathInstruction and passes it to loadPrompt", () => {
27
+ test("2. dispatchDiscussForMilestone computes fastPathInstruction and passes it to buildDiscussMilestonePrompt", () => {
28
28
  const source = guidedFlowSrc();
29
29
  const fnStart = source.indexOf("async function dispatchDiscussForMilestone(");
30
30
  assert.ok(fnStart > 0, "dispatchDiscussForMilestone must exist");
31
- const fnEnd = source.indexOf("\nasync function ", fnStart + 1);
32
31
  const fnBody = extractSourceRegion(source, "async function dispatchDiscussForMilestone(");
33
32
  assert.ok(
34
33
  fnBody.includes("fastPathInstruction"),
35
34
  "dispatchDiscussForMilestone must compute fastPathInstruction",
36
35
  );
37
36
  assert.ok(
38
- fnBody.includes("loadPrompt("),
39
- "dispatchDiscussForMilestone must call loadPrompt",
37
+ fnBody.includes("buildDiscussMilestonePrompt("),
38
+ "dispatchDiscussForMilestone must call buildDiscussMilestonePrompt",
40
39
  );
41
- const loadPromptIdx = fnBody.indexOf("loadPrompt(");
42
- const fastPathIdx = fnBody.indexOf("fastPathInstruction", loadPromptIdx);
40
+ const buildPromptIdx = fnBody.indexOf("buildDiscussMilestonePrompt(");
41
+ const fastPathIdx = fnBody.indexOf("fastPathInstruction", buildPromptIdx);
43
42
  assert.ok(
44
- fastPathIdx > loadPromptIdx,
45
- "fastPathInstruction must be passed to loadPrompt in dispatchDiscussForMilestone",
43
+ fastPathIdx > buildPromptIdx,
44
+ "fastPathInstruction must be passed to buildDiscussMilestonePrompt in dispatchDiscussForMilestone",
46
45
  );
47
46
  });
48
47
 
@@ -17,6 +17,10 @@ import { validatePreferences } from "../preferences-validation.ts";
17
17
  import type { ReactiveExecutionState } from "../types.ts";
18
18
  import { parseUnitId } from "../unit-id.ts";
19
19
  import { resolveDispatch } from "../auto-dispatch.ts";
20
+ import {
21
+ _getPlannedKeyFilesForTest,
22
+ _parseReactiveBatchTaskIdsForTest,
23
+ } from "../auto-post-unit.ts";
20
24
 
21
25
  // ─── Preference Validation ────────────────────────────────────────────────
22
26
 
@@ -71,6 +75,38 @@ test("reactive_execution validation warns on unknown keys", () => {
71
75
  assert.ok(result.warnings.some((w) => w.includes("unknown_thing")));
72
76
  });
73
77
 
78
+ test("reactive batch unit ids are parsed and deduped for commit context", () => {
79
+ assert.deepEqual(
80
+ _parseReactiveBatchTaskIdsForTest("M001/S01/reactive+T01,t02,T01"),
81
+ ["T01", "T02"],
82
+ );
83
+ assert.deepEqual(_parseReactiveBatchTaskIdsForTest("M001/S01/T01"), []);
84
+ });
85
+
86
+ test("reactive commit context key files include planned output, files, and key_files once", () => {
87
+ const result = _getPlannedKeyFilesForTest([
88
+ {
89
+ expected_output: ["src/new.ts", "src/shared.ts"],
90
+ files: ["src/input.ts", "src/shared.ts"],
91
+ key_files: ["src/key.ts"],
92
+ },
93
+ {
94
+ expected_output: ["src/new.ts"],
95
+ files: ["src/other.ts"],
96
+ key_files: ["src/key.ts", "src/final.ts"],
97
+ },
98
+ ]);
99
+
100
+ assert.deepEqual(result, [
101
+ "src/new.ts",
102
+ "src/shared.ts",
103
+ "src/input.ts",
104
+ "src/key.ts",
105
+ "src/other.ts",
106
+ "src/final.ts",
107
+ ]);
108
+ });
109
+
74
110
  // ─── Dispatch Rule Matching Logic ─────────────────────────────────────────
75
111
 
76
112
  test("reactive dispatch requires enabled config and multiple ready tasks", async () => {
@@ -10,6 +10,7 @@ import {
10
10
  resetWriteGateState,
11
11
  shouldBlockContextArtifactSave,
12
12
  } from "../bootstrap/write-gate.ts";
13
+ import { classifyCommand } from "../safety/destructive-guard.ts";
13
14
  import { toRoundResultResponse } from "../../remote-questions/manager.ts";
14
15
 
15
16
  function makeTempDir(prefix: string): string {
@@ -35,6 +36,40 @@ async function armDepthGate(
35
36
  }
36
37
  }
37
38
 
39
+ test("destructive guard classifies infrastructure mutation commands", () => {
40
+ assert.deepEqual(classifyCommand("terraform destroy -auto-approve").labels, ["IaC apply/destroy"]);
41
+ assert.deepEqual(classifyCommand("terragrunt apply").labels, ["IaC apply/destroy"]);
42
+ assert.deepEqual(classifyCommand("aws s3 delete-bucket --bucket example").labels, ["AWS mutation"]);
43
+ assert.deepEqual(classifyCommand("kubectl delete namespace prod").labels, ["kubectl mutation"]);
44
+ });
45
+
46
+ test("register-hooks hard-blocks destructive bash commands outside auto-mode", async () => {
47
+ const handlers = new Map<string, Array<(event: any, ctx?: any) => Promise<any> | any>>();
48
+ const pi = {
49
+ on(event: string, handler: (event: any, ctx?: any) => Promise<any> | any) {
50
+ const existing = handlers.get(event) ?? [];
51
+ existing.push(handler);
52
+ handlers.set(event, existing);
53
+ },
54
+ } as any;
55
+
56
+ registerHooks(pi, []);
57
+
58
+ let block: any;
59
+ for (const handler of handlers.get("tool_call") ?? []) {
60
+ const result = await handler({
61
+ toolCallId: "call-1",
62
+ toolName: "bash",
63
+ input: { command: "terraform apply -auto-approve" },
64
+ });
65
+ if (result?.block) block = result;
66
+ }
67
+
68
+ assert.equal(block?.block, true);
69
+ assert.match(block?.reason ?? "", /HARD BLOCK: destructive Bash command requires explicit human confirmation/);
70
+ assert.match(block?.reason ?? "", /IaC apply\/destroy/);
71
+ });
72
+
38
73
  test("register-hooks unlocks milestone depth verification from question id without guided-flow state (#4047)", async (t) => {
39
74
  const dir = makeTempDir("manual");
40
75
  const originalCwd = process.cwd();
@@ -51,7 +51,7 @@ test("discuss workflow scopes tools for the queued turn and restores the full to
51
51
  // discuss allowlist: gsd_summary_save and gsd_plan_milestone (the latter
52
52
  // is needed for the discuss.md output phase — see DISCUSS_TOOLS_ALLOWLIST).
53
53
  // gsd_task_complete and the broad shell_exec tool are scoped out.
54
- assert.deepEqual(sentTools, ["gsd_summary_save", "gsd_plan_milestone", "ToolSearch"]);
54
+ assert.deepEqual(sentTools, ["gsd_plan_milestone", "gsd_summary_save", "ToolSearch"]);
55
55
  assert.deepEqual(activeTools, originalTools);
56
56
  assert.equal(triggerTurn, true);
57
57
  } finally {
@@ -8,6 +8,7 @@ import { test, describe, beforeEach } from "node:test";
8
8
  import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
9
9
  import { tmpdir } from "node:os";
10
10
  import { join } from "node:path";
11
+ import { emitJournalEvent } from "../journal.ts";
11
12
  import {
12
13
  RuleRegistry,
13
14
  getRegistry,
@@ -16,6 +17,7 @@ import {
16
17
  resetRegistry,
17
18
  convertDispatchRules,
18
19
  getOrCreateRegistry,
20
+ resolveHookArtifactPath,
19
21
  } from "../rule-registry.ts";
20
22
  import type { UnifiedRule } from "../rule-types.ts";
21
23
  import type { DispatchAction, DispatchContext } from "../auto-dispatch.ts";
@@ -443,6 +445,79 @@ describe("RuleRegistry", () => {
443
445
  }
444
446
  });
445
447
 
448
+ test("failed hook completion with an artifact does not dequeue the next hook", () => {
449
+ const originalGsdHome = process.env.GSD_HOME;
450
+ const projectRoot = mkdtempSync(join(tmpdir(), "gsd-hook-failed-"));
451
+ const tempGsdHome = mkdtempSync(join(tmpdir(), "gsd-hook-home-"));
452
+ const unitId = "M001/S01/T01";
453
+
454
+ try {
455
+ mkdirSync(join(projectRoot, ".gsd", "milestones", "M001", "slices", "S01", "tasks"), { recursive: true });
456
+ writeFileSync(
457
+ join(projectRoot, ".gsd", "PREFERENCES.md"),
458
+ [
459
+ "---",
460
+ "version: 1",
461
+ "post_unit_hooks:",
462
+ " - name: review-arbiter",
463
+ " after: [execute-task]",
464
+ " prompt: Review {taskId}",
465
+ " artifact: REVIEW.md",
466
+ " max_cycles: 1",
467
+ " - name: follow-up-review",
468
+ " after: [execute-task]",
469
+ " prompt: Follow-up review {taskId}",
470
+ "---",
471
+ ].join("\n"),
472
+ "utf-8",
473
+ );
474
+ process.env.GSD_HOME = tempGsdHome;
475
+
476
+ const registry = new RuleRegistry([]);
477
+ const firstHook = registry.evaluatePostUnit("execute-task", unitId, projectRoot);
478
+ assert.equal(firstHook?.hookName, "review-arbiter");
479
+
480
+ writeFileSync(
481
+ resolveHookArtifactPath(projectRoot, unitId, "REVIEW.md"),
482
+ "partial review output",
483
+ "utf-8",
484
+ );
485
+ emitJournalEvent(projectRoot, {
486
+ ts: "2026-06-03T12:00:00.000Z",
487
+ flowId: "flow-hook-failed",
488
+ seq: 3,
489
+ eventType: "unit-end",
490
+ data: {
491
+ unitType: "hook/review-arbiter",
492
+ unitId,
493
+ status: "cancelled",
494
+ artifactVerified: false,
495
+ errorContext: {
496
+ message: "Provider error: Stream ended without finish_reason",
497
+ category: "provider",
498
+ },
499
+ },
500
+ });
501
+
502
+ const nextHook = registry.evaluatePostUnit("hook/review-arbiter", unitId, projectRoot);
503
+ assert.equal(nextHook, null, "failed hook must not allow follow-up hook dispatch");
504
+ const failure = registry.consumeHookFailure();
505
+ assert.equal(failure?.hookName, "review-arbiter");
506
+ assert.match(failure?.reason ?? "", /status cancelled/);
507
+
508
+ const resumedRegistry = new RuleRegistry([]);
509
+ resumedRegistry.restoreState(projectRoot);
510
+ const resumedHook = resumedRegistry.evaluatePostUnit("execute-task", unitId, projectRoot);
511
+ assert.equal(resumedHook, null, "resumed hook evaluation must not skip failed hook artifact");
512
+ assert.equal(resumedRegistry.consumeHookFailure()?.hookName, "review-arbiter");
513
+ } finally {
514
+ if (originalGsdHome === undefined) delete process.env.GSD_HOME;
515
+ else process.env.GSD_HOME = originalGsdHome;
516
+ rmSync(projectRoot, { recursive: true, force: true });
517
+ rmSync(tempGsdHome, { recursive: true, force: true });
518
+ }
519
+ });
520
+
446
521
  // ── matchedRule provenance (S02 journal support) ───────────────────
447
522
 
448
523
  test("evaluateDispatch result includes matchedRule on dispatch match", async () => {
@@ -298,6 +298,106 @@ test("session_start installs the welcome screen as the TUI header", async (t) =>
298
298
  assert.deepEqual(header.render(123), ["welcome 9.9.9-test none 123"]);
299
299
  });
300
300
 
301
+ test("session hooks preserve closeout-boundary UI during completion reroot", async (t) => {
302
+ const dir = join(
303
+ tmpdir(),
304
+ `gsd-closeout-session-hooks-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
305
+ );
306
+ mkdirSync(join(dir, ".gsd"), { recursive: true });
307
+ mkdirSync(join(dir, "dist"), { recursive: true });
308
+ const tempGsdHome = join(dir, "home");
309
+ mkdirSync(tempGsdHome, { recursive: true });
310
+ writeFileSync(
311
+ join(dir, "dist", "welcome-screen.js"),
312
+ "export function buildWelcomeScreenLines() { return ['welcome header']; }\n",
313
+ "utf-8",
314
+ );
315
+
316
+ const originalCwd = process.cwd();
317
+ const originalGsdHome = process.env.GSD_HOME;
318
+ const originalGsdPkgRoot = process.env.GSD_PKG_ROOT;
319
+ process.chdir(dir);
320
+ process.env.GSD_HOME = tempGsdHome;
321
+ process.env.GSD_PKG_ROOT = dir;
322
+ autoSession.reset();
323
+ autoSession.completionStopInProgress = true;
324
+ t.after(() => {
325
+ autoSession.reset();
326
+ process.chdir(originalCwd);
327
+ if (originalGsdHome === undefined) delete process.env.GSD_HOME;
328
+ else process.env.GSD_HOME = originalGsdHome;
329
+ if (originalGsdPkgRoot === undefined) delete process.env.GSD_PKG_ROOT;
330
+ else process.env.GSD_PKG_ROOT = originalGsdPkgRoot;
331
+ try { rmSync(dir, { recursive: true, force: true }); } catch { /* best-effort */ }
332
+ });
333
+
334
+ const handlers = new Map<string, (event: unknown, ctx: any) => Promise<void> | void>();
335
+ const pi = {
336
+ on(event: string, handler: (event: unknown, ctx: any) => Promise<void> | void) {
337
+ handlers.set(event, handler);
338
+ },
339
+ } as any;
340
+
341
+ registerHooks(pi, []);
342
+
343
+ const sessionStart = handlers.get("session_start");
344
+ const sessionSwitch = handlers.get("session_switch");
345
+ assert.ok(sessionStart, "session_start handler must be registered");
346
+ assert.ok(sessionSwitch, "session_switch handler must be registered");
347
+
348
+ const widgetCalls: Array<{ key: string; value: unknown }> = [];
349
+ let headerInstallCount = 0;
350
+ const ctx = {
351
+ hasUI: true,
352
+ ui: {
353
+ notify: () => {},
354
+ setStatus: () => {},
355
+ setFooter: () => {},
356
+ setHeader: () => {
357
+ headerInstallCount++;
358
+ },
359
+ setWorkingMessage: () => {},
360
+ onTerminalInput: () => () => {},
361
+ setWidget: (key: string, value: unknown) => {
362
+ widgetCalls.push({ key, value });
363
+ },
364
+ },
365
+ sessionManager: { getSessionId: () => null },
366
+ model: null,
367
+ setCompactionThresholdOverride: () => {},
368
+ modelRegistry: {
369
+ setDisabledModelProviders: () => {},
370
+ getProviderAuthMode: () => undefined,
371
+ isProviderRequestReady: () => false,
372
+ },
373
+ };
374
+
375
+ await sessionStart!({}, ctx);
376
+ assert.equal(
377
+ headerInstallCount,
378
+ 0,
379
+ "completion reroot session_start must not reinstall the welcome/project-console header",
380
+ );
381
+ assert.ok(
382
+ widgetCalls.some((call) => call.key === "gsd-health" && call.value === undefined),
383
+ "completion reroot session_start should hide the ambient health widget",
384
+ );
385
+
386
+ widgetCalls.length = 0;
387
+ await sessionSwitch!({ reason: "reroot" }, ctx);
388
+ assert.deepEqual(
389
+ widgetCalls
390
+ .filter((call) => call.key === "gsd-progress" || call.key === "gsd-outcome")
391
+ .map((call) => [call.key, call.value]),
392
+ [],
393
+ "completion reroot session_switch must not clear the preserved closeout surface",
394
+ );
395
+ assert.ok(
396
+ widgetCalls.some((call) => call.key === "gsd-health" && call.value === undefined),
397
+ "completion reroot session_switch should keep the ambient health widget hidden",
398
+ );
399
+ });
400
+
301
401
  test("session_start and session_switch apply disabled model provider policy from current preferences", async (t) => {
302
402
  const dir = join(
303
403
  tmpdir(),
@@ -5,6 +5,7 @@ import { join } from "node:path";
5
5
  import { tmpdir } from "node:os";
6
6
  import { loadSkills } from "@gsd/pi-coding-agent";
7
7
  import {
8
+ buildCompleteSlicePrompt,
8
9
  buildPlanMilestonePrompt,
9
10
  buildResearchMilestonePrompt,
10
11
  buildSkillActivationBlock,
@@ -143,6 +144,29 @@ test("buildSkillActivationBlock includes skill_rules matches and task-plan skill
143
144
  }
144
145
  });
145
146
 
147
+ test("buildSkillActivationBlock matches skill_rules against exact unit type context", () => {
148
+ const base = makeTempBase();
149
+ try {
150
+ writeSkill(base, "complete-slice-policies", "Use for complete-slice closeout policy checks.");
151
+ writeSkill(base, "slice-broad", "Use for broad slice work.");
152
+ loadOnlyTestSkills(base);
153
+
154
+ const result = buildBlock(base, {
155
+ unitType: "complete-slice",
156
+ }, {
157
+ skill_rules: [
158
+ { when: "complete-slice", use: ["complete-slice-policies"] },
159
+ { when: "slice", use: ["slice-broad"] },
160
+ ],
161
+ });
162
+
163
+ assert.match(result, /Call Skill\(\{ skill: 'complete-slice-policies' \}\)/);
164
+ assert.doesNotMatch(result, /slice-broad/);
165
+ } finally {
166
+ cleanup(base);
167
+ }
168
+ });
169
+
146
170
  test("buildSkillActivationBlock honors avoid_skills against always_use_skills", () => {
147
171
  const base = makeTempBase();
148
172
  try {
@@ -328,6 +352,37 @@ test("milestone prompt builders propagate always_use_skills through buildSkillAc
328
352
  }
329
353
  });
330
354
 
355
+ test("complete-slice prompt propagates always_use_skills through buildSkillActivationBlock", async () => {
356
+ const base = makeTempBase();
357
+ try {
358
+ writeSkill(base, "write-docs", "Use when writing docs or RFCs.");
359
+ writeProjectPreferences(base, "always_use_skills:\n - write-docs\n");
360
+ loadOnlyTestSkills(base);
361
+
362
+ const milestoneDir = join(base, ".gsd", "milestones", "M001");
363
+ const sliceDir = join(milestoneDir, "slices", "S01");
364
+ mkdirSync(sliceDir, { recursive: true });
365
+ writeFileSync(
366
+ join(milestoneDir, "M001-ROADMAP.md"),
367
+ [
368
+ "# M001: Test",
369
+ "",
370
+ "## Slices",
371
+ "",
372
+ "- [ ] **S01: Slice** `risk:low` `depends:[]`",
373
+ "",
374
+ ].join("\n"),
375
+ );
376
+ writeFileSync(join(sliceDir, "S01-PLAN.md"), "# S01: Slice\n\n## Tasks\n\n- [x] **T01: Done**\n");
377
+
378
+ const prompt = await buildCompleteSlicePrompt("M001", "Test", "S01", "Slice", base);
379
+
380
+ assert.match(prompt, /Call Skill\(\{ skill: 'write-docs' \}\)/);
381
+ } finally {
382
+ cleanup(base);
383
+ }
384
+ });
385
+
331
386
  test("skill manifest strict warnings require GSD_SKILL_MANIFEST_STRICT=1", (t) => {
332
387
  const previousStrict = process.env.GSD_SKILL_MANIFEST_STRICT;
333
388
  const previousStderr = setStderrLoggingEnabled(false);
@@ -148,6 +148,7 @@ test("fresh start registers the auto worker before bootstrap enters worktree flo
148
148
  const freshStartSectionIdx = startAutoBody.indexOf("// ── Fresh start path — delegated to auto-start.ts ──");
149
149
  const resumeBody = startAutoBody.slice(resumeSectionIdx, freshStartSectionIdx);
150
150
  const resumeDbOpenIdx = resumeBody.indexOf("await openProjectDbIfPresent(base);");
151
+ const resumeMergeReconcileIdx = resumeBody.indexOf("reconcileMergedMilestonesFromJournal(base);");
151
152
  const resumeRegisterIdx = resumeBody.indexOf("registerAutoWorkerForSession(s, base);");
152
153
  const resumeEnterMilestoneIdx = resumeBody.indexOf("buildLifecycle().enterMilestone");
153
154
  const dbOpenIdx = bootstrapBody.indexOf("await openProjectDbIfPresent(base);");
@@ -164,6 +165,7 @@ test("fresh start registers the auto worker before bootstrap enters worktree flo
164
165
  assert.ok(resumeSectionIdx > -1, "startAuto should have resume milestone entry flow");
165
166
  assert.ok(freshStartSectionIdx > resumeSectionIdx, "resume assertions should be scoped before fresh start");
166
167
  assert.ok(resumeDbOpenIdx > -1, "resume should open DB before milestone entry");
168
+ assert.ok(resumeMergeReconcileIdx > -1, "resume should reconcile merged milestones before deriving dispatch state");
167
169
  assert.ok(resumeRegisterIdx > -1, "resume should register worker before milestone entry");
168
170
  assert.ok(resumeEnterMilestoneIdx > -1, "resume should enter milestones through lifecycle");
169
171
  assert.ok(bootstrapIdx > -1, "bootstrapAutoSession should exist");
@@ -179,8 +181,10 @@ test("fresh start registers the auto worker before bootstrap enters worktree flo
179
181
  "bootstrap must open DB and register worker before first enterMilestone",
180
182
  );
181
183
  assert.ok(
182
- resumeDbOpenIdx < resumeRegisterIdx && resumeRegisterIdx < resumeEnterMilestoneIdx,
183
- "resume must open DB and register worker before first enterMilestone",
184
+ resumeDbOpenIdx < resumeMergeReconcileIdx &&
185
+ resumeMergeReconcileIdx < resumeRegisterIdx &&
186
+ resumeRegisterIdx < resumeEnterMilestoneIdx,
187
+ "resume must open DB, reconcile merged milestones, and register worker before first enterMilestone",
184
188
  );
185
189
  });
186
190