@opengsd/gsd-pi 1.2.0-dev.0b870afa → 1.2.0-dev.23d85b63

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 (579) hide show
  1. package/dist/cli-model-override.d.ts +15 -0
  2. package/dist/cli-model-override.js +21 -0
  3. package/dist/cli.js +14 -19
  4. package/dist/headless-events.d.ts +16 -1
  5. package/dist/headless-events.js +19 -2
  6. package/dist/headless.js +8 -1
  7. package/dist/loader.js +6 -4
  8. package/dist/onboarding.js +9 -4
  9. package/dist/provider-migrations.d.ts +23 -0
  10. package/dist/provider-migrations.js +41 -0
  11. package/dist/register-agent-bundles.d.ts +11 -2
  12. package/dist/register-agent-bundles.js +18 -4
  13. package/dist/resource-loader.d.ts +10 -5
  14. package/dist/resource-loader.js +121 -6
  15. package/dist/resources/.managed-resources-content-hash +1 -1
  16. package/dist/resources/extensions/ask-user-questions.js +3 -2
  17. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +447 -215
  18. package/dist/resources/extensions/claude-code-cli/turn-assembler.js +33 -1
  19. package/dist/resources/extensions/google-cli/stream-adapter.js +16 -1
  20. package/dist/resources/extensions/gsd/auto/closeout.js +215 -0
  21. package/dist/resources/extensions/gsd/auto/dispatch-history.js +21 -6
  22. package/dist/resources/extensions/gsd/auto/dispatch.js +365 -0
  23. package/dist/resources/extensions/gsd/auto/finalize.js +347 -0
  24. package/dist/resources/extensions/gsd/auto/loop.js +4 -1
  25. package/dist/resources/extensions/gsd/auto/milestone-lease-reclaim.js +56 -0
  26. package/dist/resources/extensions/gsd/auto/orchestrator.js +119 -18
  27. package/dist/resources/extensions/gsd/auto/phase-helpers.js +146 -0
  28. package/dist/resources/extensions/gsd/auto/phases.js +17 -2372
  29. package/dist/resources/extensions/gsd/auto/pre-dispatch.js +542 -0
  30. package/dist/resources/extensions/gsd/auto/unit-phase.js +694 -0
  31. package/dist/resources/extensions/gsd/auto/workflow-unit-dispatch.js +1 -1
  32. package/dist/resources/extensions/gsd/auto/worktree-safety-phase.js +125 -0
  33. package/dist/resources/extensions/gsd/auto-closeout-messaging.js +90 -0
  34. package/dist/resources/extensions/gsd/auto-dashboard.js +255 -431
  35. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +15 -3
  36. package/dist/resources/extensions/gsd/auto-dispatch.js +19 -1
  37. package/dist/resources/extensions/gsd/auto-model-selection.js +9 -6
  38. package/dist/resources/extensions/gsd/auto-post-unit.js +12 -8
  39. package/dist/resources/extensions/gsd/auto-prompts.js +5 -1
  40. package/dist/resources/extensions/gsd/auto-recovery.js +52 -6
  41. package/dist/resources/extensions/gsd/auto-start.js +28 -7
  42. package/dist/resources/extensions/gsd/auto-worktree.js +48 -3
  43. package/dist/resources/extensions/gsd/auto.js +83 -19
  44. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +4 -2
  45. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +37 -7
  46. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +3 -1
  47. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +32 -3
  48. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +56 -16
  49. package/dist/resources/extensions/gsd/closeout-wizard.js +8 -3
  50. package/dist/resources/extensions/gsd/commands/handlers/core.js +22 -8
  51. package/dist/resources/extensions/gsd/commands/handlers/ops.js +2 -2
  52. package/dist/resources/extensions/gsd/commands-mcp-status.js +2 -2
  53. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +8 -0
  54. package/dist/resources/extensions/gsd/commands-workflow-templates.js +9 -2
  55. package/dist/resources/extensions/gsd/config-overlay.js +11 -8
  56. package/dist/resources/extensions/gsd/db/engine.js +24 -6
  57. package/dist/resources/extensions/gsd/db/queries.js +30 -0
  58. package/dist/resources/extensions/gsd/db/writers/reconcile.js +19 -1
  59. package/dist/resources/extensions/gsd/db-migration-backup.js +51 -8
  60. package/dist/resources/extensions/gsd/db-transaction.js +27 -23
  61. package/dist/resources/extensions/gsd/db-writer.js +8 -17
  62. package/dist/resources/extensions/gsd/doctor-environment.js +256 -125
  63. package/dist/resources/extensions/gsd/doctor-git-checks.js +5 -1
  64. package/dist/resources/extensions/gsd/doctor-providers.js +1 -1
  65. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +11 -9
  66. package/dist/resources/extensions/gsd/gsd-db.js +15 -20
  67. package/dist/resources/extensions/gsd/guided-flow.js +88 -2
  68. package/dist/resources/extensions/gsd/health-widget.js +87 -28
  69. package/dist/resources/extensions/gsd/mcp-bridge.js +10 -0
  70. package/dist/resources/extensions/gsd/memory-relations.js +1 -1
  71. package/dist/resources/extensions/gsd/milestone-settlement.js +2 -2
  72. package/dist/resources/extensions/gsd/notifications.js +12 -7
  73. package/dist/resources/extensions/gsd/preferences-models.js +17 -9
  74. package/dist/resources/extensions/gsd/preferences.js +91 -5
  75. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +8 -2
  76. package/dist/resources/extensions/gsd/prompts/complete-slice.md +6 -2
  77. package/dist/resources/extensions/gsd/prompts/execute-task.md +7 -2
  78. package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -1
  79. package/dist/resources/extensions/gsd/prompts/reactive-execute.md +2 -2
  80. package/dist/resources/extensions/gsd/prompts/run-uat.md +7 -1
  81. package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -1
  82. package/dist/resources/extensions/gsd/prompts/workflow-start.md +2 -1
  83. package/dist/resources/extensions/gsd/provider-error-guidance.js +24 -0
  84. package/dist/resources/extensions/gsd/session-lock.js +4 -3
  85. package/dist/resources/extensions/gsd/skill-activation.js +3 -6
  86. package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +13 -6
  87. package/dist/resources/extensions/gsd/state.js +6 -2
  88. package/dist/resources/extensions/gsd/tool-surface-readiness.js +83 -31
  89. package/dist/resources/extensions/gsd/tools/complete-task.js +62 -0
  90. package/dist/resources/extensions/gsd/tools/exec-tool.js +2 -109
  91. package/dist/resources/extensions/gsd/tui/render-kit.js +38 -13
  92. package/dist/resources/extensions/gsd/unit-context-composer.js +1 -1
  93. package/dist/resources/extensions/gsd/unit-registry.js +34 -4
  94. package/dist/resources/extensions/gsd/workflow-logger.js +4 -0
  95. package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +2 -0
  96. package/dist/resources/extensions/gsd/workflow-mcp-readiness-cache.js +105 -0
  97. package/dist/resources/extensions/gsd/worktree-manager.js +101 -2
  98. package/dist/resources/extensions/gsd/worktree-safety.js +28 -26
  99. package/dist/resources/extensions/gsd/worktree-shell-guard.js +113 -0
  100. package/dist/resources/extensions/gsd/worktree.js +8 -1
  101. package/dist/resources/extensions/mcp-client/manager.js +6 -1
  102. package/dist/resources/extensions/search-the-web/index.js +41 -9
  103. package/dist/resources/extensions/search-the-web/native-search.js +18 -4
  104. package/dist/resources/extensions/shared/gsd-browser-cli.js +40 -2
  105. package/dist/resources/extensions/subagent/index.js +20 -15
  106. package/dist/resources/extensions/subagent/worktree-cwd.js +31 -0
  107. package/dist/resources/skills/create-skill/SKILL.md +3 -0
  108. package/dist/resources/skills/create-skill/references/skill-structure.md +1 -0
  109. package/dist/runtime-checks.d.ts +10 -0
  110. package/dist/runtime-checks.js +27 -0
  111. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  112. package/dist/web/standalone/.next/BUILD_ID +1 -1
  113. package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
  114. package/dist/web/standalone/.next/build-manifest.json +2 -2
  115. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  116. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  117. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  125. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  128. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  131. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  132. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  133. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  134. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  135. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  136. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  137. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  138. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  139. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  140. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  141. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  142. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  143. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  144. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  145. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  146. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  147. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  148. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
  149. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  150. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  151. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  152. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  153. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  154. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  155. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  156. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  157. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  158. package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
  159. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  160. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  161. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  162. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  163. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  164. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  165. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  166. package/dist/web/standalone/.next/server/app/index.html +1 -1
  167. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  168. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  169. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  170. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  171. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  172. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  173. package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
  174. package/dist/web/standalone/.next/server/chunks/{5942.js → 1128.js} +1 -1
  175. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  176. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  178. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  179. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  180. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  181. package/package.json +4 -4
  182. package/packages/cloud-mcp-gateway/package.json +2 -2
  183. package/packages/contracts/package.json +1 -1
  184. package/packages/daemon/package.json +4 -4
  185. package/packages/gsd-agent-core/dist/sdk.d.ts.map +1 -1
  186. package/packages/gsd-agent-core/dist/sdk.js +12 -6
  187. package/packages/gsd-agent-core/dist/sdk.js.map +1 -1
  188. package/packages/gsd-agent-core/package.json +5 -5
  189. package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.d.ts +5 -5
  190. package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  191. package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.js +12 -24
  192. package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.js.map +1 -1
  193. package/packages/gsd-agent-modes/dist/modes/interactive/components/bash-execution.js +5 -5
  194. package/packages/gsd-agent-modes/dist/modes/interactive/components/bash-execution.js.map +1 -1
  195. package/packages/gsd-agent-modes/dist/modes/interactive/components/branch-summary-message.d.ts +3 -3
  196. package/packages/gsd-agent-modes/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  197. package/packages/gsd-agent-modes/dist/modes/interactive/components/branch-summary-message.js +20 -11
  198. package/packages/gsd-agent-modes/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  199. package/packages/gsd-agent-modes/dist/modes/interactive/components/chat-turn-connect.d.ts +4 -3
  200. package/packages/gsd-agent-modes/dist/modes/interactive/components/chat-turn-connect.d.ts.map +1 -1
  201. package/packages/gsd-agent-modes/dist/modes/interactive/components/chat-turn-connect.js +5 -54
  202. package/packages/gsd-agent-modes/dist/modes/interactive/components/chat-turn-connect.js.map +1 -1
  203. package/packages/gsd-agent-modes/dist/modes/interactive/components/compaction-summary-message.d.ts +2 -4
  204. package/packages/gsd-agent-modes/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  205. package/packages/gsd-agent-modes/dist/modes/interactive/components/compaction-summary-message.js +2 -4
  206. package/packages/gsd-agent-modes/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  207. package/packages/gsd-agent-modes/dist/modes/interactive/components/custom-editor.d.ts +2 -0
  208. package/packages/gsd-agent-modes/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  209. package/packages/gsd-agent-modes/dist/modes/interactive/components/custom-editor.js +4 -0
  210. package/packages/gsd-agent-modes/dist/modes/interactive/components/custom-editor.js.map +1 -1
  211. package/packages/gsd-agent-modes/dist/modes/interactive/components/footer.d.ts +9 -12
  212. package/packages/gsd-agent-modes/dist/modes/interactive/components/footer.d.ts.map +1 -1
  213. package/packages/gsd-agent-modes/dist/modes/interactive/components/footer.js +100 -166
  214. package/packages/gsd-agent-modes/dist/modes/interactive/components/footer.js.map +1 -1
  215. package/packages/gsd-agent-modes/dist/modes/interactive/components/gsd-progress-state.d.ts +2 -0
  216. package/packages/gsd-agent-modes/dist/modes/interactive/components/gsd-progress-state.d.ts.map +1 -0
  217. package/packages/gsd-agent-modes/dist/modes/interactive/components/gsd-progress-state.js +4 -0
  218. package/packages/gsd-agent-modes/dist/modes/interactive/components/gsd-progress-state.js.map +1 -0
  219. package/packages/gsd-agent-modes/dist/modes/interactive/components/gsd-status-widget.d.ts +23 -0
  220. package/packages/gsd-agent-modes/dist/modes/interactive/components/gsd-status-widget.d.ts.map +1 -0
  221. package/packages/gsd-agent-modes/dist/modes/interactive/components/gsd-status-widget.js +178 -0
  222. package/packages/gsd-agent-modes/dist/modes/interactive/components/gsd-status-widget.js.map +1 -0
  223. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts +8 -0
  224. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  225. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js +21 -9
  226. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js.map +1 -1
  227. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  228. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  229. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js +10 -0
  230. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js.map +1 -1
  231. package/packages/gsd-agent-modes/dist/modes/interactive/components/skill-invocation-message.d.ts +2 -3
  232. package/packages/gsd-agent-modes/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  233. package/packages/gsd-agent-modes/dist/modes/interactive/components/skill-invocation-message.js +2 -3
  234. package/packages/gsd-agent-modes/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  235. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +11 -0
  236. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  237. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +85 -19
  238. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  239. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts +71 -3
  240. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
  241. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +257 -37
  242. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
  243. package/packages/gsd-agent-modes/dist/modes/interactive/components/user-message.d.ts +3 -3
  244. package/packages/gsd-agent-modes/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  245. package/packages/gsd-agent-modes/dist/modes/interactive/components/user-message.js +19 -19
  246. package/packages/gsd-agent-modes/dist/modes/interactive/components/user-message.js.map +1 -1
  247. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts +3 -0
  248. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  249. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +26 -10
  250. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  251. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/extension-ui-controller.d.ts.map +1 -1
  252. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/extension-ui-controller.js +12 -1
  253. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/extension-ui-controller.js.map +1 -1
  254. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  255. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +5 -0
  256. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  257. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-autocomplete.d.ts.map +1 -1
  258. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-autocomplete.js +3 -1
  259. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-autocomplete.js.map +1 -1
  260. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.d.ts.map +1 -1
  261. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js +3 -5
  262. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js.map +1 -1
  263. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-dialogs.js +2 -2
  264. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-dialogs.js.map +1 -1
  265. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.d.ts +1 -0
  266. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.d.ts.map +1 -1
  267. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.js +25 -0
  268. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.js.map +1 -1
  269. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-key-handlers.d.ts.map +1 -1
  270. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-key-handlers.js +1 -0
  271. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-key-handlers.js.map +1 -1
  272. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-init.d.ts +1 -0
  273. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-init.d.ts.map +1 -1
  274. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-init.js +20 -49
  275. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-init.js.map +1 -1
  276. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts +4 -0
  277. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  278. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  279. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts +10 -2
  280. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  281. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +48 -6
  282. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
  283. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.d.ts.map +1 -1
  284. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js +4 -0
  285. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js.map +1 -1
  286. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-ui-messaging.d.ts.map +1 -1
  287. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-ui-messaging.js +0 -1
  288. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-ui-messaging.js.map +1 -1
  289. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  290. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +3 -0
  291. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
  292. package/packages/gsd-agent-modes/package.json +7 -7
  293. package/packages/mcp-server/README.md +12 -3
  294. package/packages/mcp-server/dist/cli-runner.d.ts +40 -0
  295. package/packages/mcp-server/dist/cli-runner.d.ts.map +1 -0
  296. package/packages/mcp-server/dist/cli-runner.js +137 -0
  297. package/packages/mcp-server/dist/cli-runner.js.map +1 -0
  298. package/packages/mcp-server/dist/cli.js +2 -58
  299. package/packages/mcp-server/dist/cli.js.map +1 -1
  300. package/packages/mcp-server/dist/pid-registry.d.ts +46 -0
  301. package/packages/mcp-server/dist/pid-registry.d.ts.map +1 -0
  302. package/packages/mcp-server/dist/pid-registry.js +459 -0
  303. package/packages/mcp-server/dist/pid-registry.js.map +1 -0
  304. package/packages/mcp-server/dist/probe-mode.d.ts +4 -0
  305. package/packages/mcp-server/dist/probe-mode.d.ts.map +1 -0
  306. package/packages/mcp-server/dist/probe-mode.js +10 -0
  307. package/packages/mcp-server/dist/probe-mode.js.map +1 -0
  308. package/packages/mcp-server/dist/stdio-watchdog.d.ts +8 -0
  309. package/packages/mcp-server/dist/stdio-watchdog.d.ts.map +1 -0
  310. package/packages/mcp-server/dist/stdio-watchdog.js +40 -0
  311. package/packages/mcp-server/dist/stdio-watchdog.js.map +1 -0
  312. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  313. package/packages/mcp-server/dist/workflow-tools.js +62 -43
  314. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  315. package/packages/mcp-server/package.json +5 -5
  316. package/packages/native/package.json +1 -1
  317. package/packages/pi-agent-core/dist/agent-loop.js +52 -2
  318. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  319. package/packages/pi-agent-core/package.json +1 -1
  320. package/packages/pi-ai/package.json +1 -1
  321. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts +28 -2
  322. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts.map +1 -1
  323. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.js.map +1 -1
  324. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +1 -1
  325. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
  326. package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
  327. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +5 -1
  328. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  329. package/packages/pi-coding-agent/dist/core/extensions/runner.js +3 -1
  330. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  331. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
  332. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  333. package/packages/pi-coding-agent/dist/core/settings-manager.js +11 -0
  334. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  335. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  336. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  337. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  338. package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
  339. package/packages/pi-coding-agent/dist/theme/theme.js +45 -17
  340. package/packages/pi-coding-agent/dist/theme/theme.js.map +1 -1
  341. package/packages/pi-coding-agent/package.json +8 -8
  342. package/packages/pi-tui/README.md +15 -0
  343. package/packages/pi-tui/dist/autocomplete.d.ts.map +1 -1
  344. package/packages/pi-tui/dist/autocomplete.js +6 -1
  345. package/packages/pi-tui/dist/autocomplete.js.map +1 -1
  346. package/packages/pi-tui/dist/components/input.js +1 -1
  347. package/packages/pi-tui/dist/components/input.js.map +1 -1
  348. package/packages/pi-tui/dist/components/loader.d.ts.map +1 -1
  349. package/packages/pi-tui/dist/components/loader.js +1 -0
  350. package/packages/pi-tui/dist/components/loader.js.map +1 -1
  351. package/packages/pi-tui/dist/components/select-list.d.ts.map +1 -1
  352. package/packages/pi-tui/dist/components/select-list.js +8 -2
  353. package/packages/pi-tui/dist/components/select-list.js.map +1 -1
  354. package/packages/pi-tui/dist/index.d.ts +2 -2
  355. package/packages/pi-tui/dist/index.d.ts.map +1 -1
  356. package/packages/pi-tui/dist/index.js +2 -2
  357. package/packages/pi-tui/dist/index.js.map +1 -1
  358. package/packages/pi-tui/dist/terminal-image.d.ts +33 -0
  359. package/packages/pi-tui/dist/terminal-image.d.ts.map +1 -1
  360. package/packages/pi-tui/dist/terminal-image.js +54 -2
  361. package/packages/pi-tui/dist/terminal-image.js.map +1 -1
  362. package/packages/pi-tui/dist/terminal.d.ts +12 -0
  363. package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
  364. package/packages/pi-tui/dist/terminal.js +70 -25
  365. package/packages/pi-tui/dist/terminal.js.map +1 -1
  366. package/packages/pi-tui/dist/tui.d.ts +15 -0
  367. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  368. package/packages/pi-tui/dist/tui.js +106 -21
  369. package/packages/pi-tui/dist/tui.js.map +1 -1
  370. package/packages/pi-tui/dist/utils.d.ts.map +1 -1
  371. package/packages/pi-tui/dist/utils.js +110 -36
  372. package/packages/pi-tui/dist/utils.js.map +1 -1
  373. package/packages/pi-tui/package.json +2 -2
  374. package/packages/rpc-client/package.json +2 -2
  375. package/pkg/dist/theme/theme.d.ts.map +1 -1
  376. package/pkg/dist/theme/theme.js +45 -17
  377. package/pkg/dist/theme/theme.js.map +1 -1
  378. package/pkg/package.json +1 -1
  379. package/src/resources/extensions/ask-user-questions.ts +7 -2
  380. package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +80 -0
  381. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +531 -226
  382. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +672 -7
  383. package/src/resources/extensions/claude-code-cli/turn-assembler.ts +38 -1
  384. package/src/resources/extensions/google-cli/stream-adapter.ts +22 -1
  385. package/src/resources/extensions/gsd/auto/closeout.ts +309 -0
  386. package/src/resources/extensions/gsd/auto/dispatch-history.ts +22 -6
  387. package/src/resources/extensions/gsd/auto/dispatch.ts +449 -0
  388. package/src/resources/extensions/gsd/auto/finalize.ts +445 -0
  389. package/src/resources/extensions/gsd/auto/loop.ts +4 -1
  390. package/src/resources/extensions/gsd/auto/milestone-lease-reclaim.ts +74 -0
  391. package/src/resources/extensions/gsd/auto/orchestrator.ts +140 -18
  392. package/src/resources/extensions/gsd/auto/phase-helpers.ts +199 -0
  393. package/src/resources/extensions/gsd/auto/phases.ts +58 -3061
  394. package/src/resources/extensions/gsd/auto/pre-dispatch.ts +716 -0
  395. package/src/resources/extensions/gsd/auto/unit-phase.ts +910 -0
  396. package/src/resources/extensions/gsd/auto/workflow-unit-dispatch.ts +1 -1
  397. package/src/resources/extensions/gsd/auto/worktree-safety-phase.ts +149 -0
  398. package/src/resources/extensions/gsd/auto-closeout-messaging.ts +90 -0
  399. package/src/resources/extensions/gsd/auto-dashboard.ts +310 -454
  400. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +15 -2
  401. package/src/resources/extensions/gsd/auto-dispatch.ts +24 -2
  402. package/src/resources/extensions/gsd/auto-model-selection.ts +20 -5
  403. package/src/resources/extensions/gsd/auto-post-unit.ts +16 -9
  404. package/src/resources/extensions/gsd/auto-prompts.ts +5 -1
  405. package/src/resources/extensions/gsd/auto-recovery.ts +62 -8
  406. package/src/resources/extensions/gsd/auto-start.ts +44 -7
  407. package/src/resources/extensions/gsd/auto-worktree.ts +51 -3
  408. package/src/resources/extensions/gsd/auto.ts +118 -18
  409. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +6 -2
  410. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +56 -6
  411. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +2 -1
  412. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +36 -3
  413. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +69 -16
  414. package/src/resources/extensions/gsd/closeout-wizard.ts +11 -2
  415. package/src/resources/extensions/gsd/commands/handlers/core.ts +27 -8
  416. package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -2
  417. package/src/resources/extensions/gsd/commands-mcp-status.ts +2 -2
  418. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +7 -0
  419. package/src/resources/extensions/gsd/commands-workflow-templates.ts +11 -4
  420. package/src/resources/extensions/gsd/config-overlay.ts +22 -9
  421. package/src/resources/extensions/gsd/db/engine.ts +26 -6
  422. package/src/resources/extensions/gsd/db/queries.ts +29 -0
  423. package/src/resources/extensions/gsd/db/writers/reconcile.ts +24 -1
  424. package/src/resources/extensions/gsd/db-migration-backup.ts +56 -7
  425. package/src/resources/extensions/gsd/db-transaction.ts +37 -20
  426. package/src/resources/extensions/gsd/db-writer.ts +11 -19
  427. package/src/resources/extensions/gsd/doctor-environment.ts +267 -142
  428. package/src/resources/extensions/gsd/doctor-git-checks.ts +4 -1
  429. package/src/resources/extensions/gsd/doctor-providers.ts +1 -1
  430. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +10 -10
  431. package/src/resources/extensions/gsd/gsd-db.ts +15 -19
  432. package/src/resources/extensions/gsd/guided-flow.ts +128 -2
  433. package/src/resources/extensions/gsd/health-widget.ts +91 -27
  434. package/src/resources/extensions/gsd/mcp-bridge.ts +39 -0
  435. package/src/resources/extensions/gsd/memory-relations.ts +1 -1
  436. package/src/resources/extensions/gsd/milestone-settlement.ts +2 -2
  437. package/src/resources/extensions/gsd/notifications.ts +13 -6
  438. package/src/resources/extensions/gsd/preferences-models.ts +26 -8
  439. package/src/resources/extensions/gsd/preferences.ts +111 -5
  440. package/src/resources/extensions/gsd/prompts/complete-milestone.md +8 -2
  441. package/src/resources/extensions/gsd/prompts/complete-slice.md +6 -2
  442. package/src/resources/extensions/gsd/prompts/execute-task.md +7 -2
  443. package/src/resources/extensions/gsd/prompts/quick-task.md +1 -1
  444. package/src/resources/extensions/gsd/prompts/reactive-execute.md +2 -2
  445. package/src/resources/extensions/gsd/prompts/run-uat.md +7 -1
  446. package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -1
  447. package/src/resources/extensions/gsd/prompts/workflow-start.md +2 -1
  448. package/src/resources/extensions/gsd/provider-error-guidance.ts +32 -0
  449. package/src/resources/extensions/gsd/session-lock.ts +8 -7
  450. package/src/resources/extensions/gsd/skill-activation.ts +3 -6
  451. package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +23 -10
  452. package/src/resources/extensions/gsd/state.ts +7 -1
  453. package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +1 -1
  454. package/src/resources/extensions/gsd/tests/auto-blocked-remediation-message.test.ts +1 -1
  455. package/src/resources/extensions/gsd/tests/auto-closeout-messaging.test.ts +71 -0
  456. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +68 -116
  457. package/src/resources/extensions/gsd/tests/auto-direct-dispatch-parse.test.ts +33 -0
  458. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +206 -22
  459. package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +7 -2
  460. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +16 -1
  461. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +89 -22
  462. package/src/resources/extensions/gsd/tests/auto-pause-double-entry-guard.test.ts +1 -1
  463. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +97 -4
  464. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +2 -1
  465. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +236 -0
  466. package/src/resources/extensions/gsd/tests/auto-unit-closeout.test.ts +169 -1
  467. package/src/resources/extensions/gsd/tests/auto-verification.test.ts +36 -0
  468. package/src/resources/extensions/gsd/tests/blocker-placeholder-logs.test.ts +218 -0
  469. package/src/resources/extensions/gsd/tests/complete-milestone-prompt-rendering.test.ts +6 -2
  470. package/src/resources/extensions/gsd/tests/complete-task.test.ts +141 -5
  471. package/src/resources/extensions/gsd/tests/core-overlay-fallback.test.ts +1 -0
  472. package/src/resources/extensions/gsd/tests/db-engine-logs.test.ts +207 -0
  473. package/src/resources/extensions/gsd/tests/db-migration-backup.test.ts +68 -19
  474. package/src/resources/extensions/gsd/tests/db-transaction.test.ts +59 -0
  475. package/src/resources/extensions/gsd/tests/db-writer.test.ts +15 -4
  476. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +2 -1
  477. package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +62 -0
  478. package/src/resources/extensions/gsd/tests/discuss-routing-fixes.test.ts +12 -2
  479. package/src/resources/extensions/gsd/tests/dispatch-db-degradation-logs.test.ts +98 -0
  480. package/src/resources/extensions/gsd/tests/dispatch-history.test.ts +55 -0
  481. package/src/resources/extensions/gsd/tests/dispatch-logs.test.ts +103 -0
  482. package/src/resources/extensions/gsd/tests/dispatch-reactive-logs.test.ts +98 -0
  483. package/src/resources/extensions/gsd/tests/dist-redirect.mjs +8 -0
  484. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +6 -4
  485. package/src/resources/extensions/gsd/tests/engine-interfaces-contract.test.ts +117 -91
  486. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +113 -0
  487. package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +2 -1
  488. package/src/resources/extensions/gsd/tests/gsd-command-home.test.ts +40 -7
  489. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +19 -0
  490. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +16 -0
  491. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +75 -0
  492. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +15 -0
  493. package/src/resources/extensions/gsd/tests/integration/doctor-environment-async.test.ts +104 -0
  494. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +18 -0
  495. package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +1 -0
  496. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +47 -16
  497. package/src/resources/extensions/gsd/tests/loop.test.ts +60 -0
  498. package/src/resources/extensions/gsd/tests/mcp-readiness-preflight.test.ts +205 -0
  499. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +6 -5
  500. package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +1 -1
  501. package/src/resources/extensions/gsd/tests/milestone-report-path.test.ts +1 -1
  502. package/src/resources/extensions/gsd/tests/milestone-settlement.test.ts +92 -0
  503. package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +1 -1
  504. package/src/resources/extensions/gsd/tests/model-router.test.ts +139 -0
  505. package/src/resources/extensions/gsd/tests/notifications.test.ts +64 -9
  506. package/src/resources/extensions/gsd/tests/oauth-api-model-routing.test.ts +13 -1
  507. package/src/resources/extensions/gsd/tests/orchestrator-legacy-parity.test.ts +1 -1
  508. package/src/resources/extensions/gsd/tests/orchestrator-logs.test.ts +335 -0
  509. package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +2 -2
  510. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +5 -0
  511. package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +1 -1
  512. package/src/resources/extensions/gsd/tests/phases-terminal-complete-idempotent.test.ts +1 -1
  513. package/src/resources/extensions/gsd/tests/plan-gate-failed-doctor-heal-hint.test.ts +3 -3
  514. package/src/resources/extensions/gsd/tests/prefs-missing-models-crash.test.ts +35 -4
  515. package/src/resources/extensions/gsd/tests/progress-strip-test-helpers.ts +79 -0
  516. package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +2 -0
  517. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +11 -2
  518. package/src/resources/extensions/gsd/tests/provider-error-guidance.test.ts +15 -0
  519. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +2 -4
  520. package/src/resources/extensions/gsd/tests/reconcile-logs.test.ts +244 -0
  521. package/src/resources/extensions/gsd/tests/recovery-finalize-logs.test.ts +119 -0
  522. package/src/resources/extensions/gsd/tests/recovery-verify-logs.test.ts +428 -0
  523. package/src/resources/extensions/gsd/tests/register-extension-guard.test.ts +25 -0
  524. package/src/resources/extensions/gsd/tests/remote-notification-from-desktop.test.ts +31 -81
  525. package/src/resources/extensions/gsd/tests/resume-missing-worktree-warning.test.ts +5 -5
  526. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +7 -1
  527. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +68 -0
  528. package/src/resources/extensions/gsd/tests/show-config-command.test.ts +3 -0
  529. package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +170 -48
  530. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +20 -17
  531. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +7 -3
  532. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +17 -1
  533. package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +1 -1
  534. package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +17 -0
  535. package/src/resources/extensions/gsd/tests/thinking-level-resolution.test.ts +1 -1
  536. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +4 -2
  537. package/src/resources/extensions/gsd/tests/tool-surface-readiness.test.ts +184 -10
  538. package/src/resources/extensions/gsd/tests/tui-header-lifecycle.test.ts +40 -86
  539. package/src/resources/extensions/gsd/tests/tui-render-kit.test.ts +44 -6
  540. package/src/resources/extensions/gsd/tests/uok-audit.test.ts +194 -0
  541. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +1 -1
  542. package/src/resources/extensions/gsd/tests/workflow-mcp-readiness-cache.test.ts +119 -0
  543. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +65 -2
  544. package/src/resources/extensions/gsd/tests/workflow-phase-contract-matrix.test.ts +332 -0
  545. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +92 -0
  546. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +1 -1
  547. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +36 -0
  548. package/src/resources/extensions/gsd/tests/worktree-project-root-degrade.test.ts +1 -1
  549. package/src/resources/extensions/gsd/tests/worktree-safety-phase.test.ts +100 -0
  550. package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +72 -0
  551. package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +22 -0
  552. package/src/resources/extensions/gsd/tests/worktree-write-gate.test.ts +75 -3
  553. package/src/resources/extensions/gsd/tests/worktree.test.ts +18 -0
  554. package/src/resources/extensions/gsd/tool-surface-readiness.ts +126 -19
  555. package/src/resources/extensions/gsd/tools/complete-task.ts +87 -0
  556. package/src/resources/extensions/gsd/tools/exec-tool.ts +2 -118
  557. package/src/resources/extensions/gsd/tui/render-kit.ts +56 -13
  558. package/src/resources/extensions/gsd/unit-context-composer.ts +1 -1
  559. package/src/resources/extensions/gsd/unit-registry.ts +34 -4
  560. package/src/resources/extensions/gsd/workflow-logger.ts +5 -0
  561. package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +2 -0
  562. package/src/resources/extensions/gsd/workflow-mcp-readiness-cache.ts +150 -0
  563. package/src/resources/extensions/gsd/worktree-manager.ts +97 -2
  564. package/src/resources/extensions/gsd/worktree-safety.ts +41 -39
  565. package/src/resources/extensions/gsd/worktree-shell-guard.ts +123 -0
  566. package/src/resources/extensions/gsd/worktree.ts +7 -1
  567. package/src/resources/extensions/mcp-client/manager.ts +7 -1
  568. package/src/resources/extensions/search-the-web/index.ts +45 -9
  569. package/src/resources/extensions/search-the-web/native-search.ts +16 -4
  570. package/src/resources/extensions/shared/gsd-browser-cli.ts +41 -2
  571. package/src/resources/extensions/subagent/index.ts +20 -15
  572. package/src/resources/extensions/subagent/tests/worktree-cwd.test.ts +57 -0
  573. package/src/resources/extensions/subagent/worktree-cwd.ts +35 -0
  574. package/src/resources/skills/create-skill/SKILL.md +3 -0
  575. package/src/resources/skills/create-skill/references/skill-structure.md +1 -0
  576. package/dist/resources/skills/gsd-browser/SKILL.md +0 -41
  577. package/src/resources/skills/gsd-browser/SKILL.md +0 -41
  578. /package/dist/web/standalone/.next/static/{T-LTxEw5wir5Lm5T3qEVd → Wn9u2NYq0cyUigB_3Z0_N}/_buildManifest.js +0 -0
  579. /package/dist/web/standalone/.next/static/{T-LTxEw5wir5Lm5T3qEVd → Wn9u2NYq0cyUigB_3Z0_N}/_ssgManifest.js +0 -0
@@ -1,13 +1,23 @@
1
1
  // Project/App: gsd-pi
2
2
  // File Purpose: Regression tests for auto-unit closeout activity classification.
3
3
 
4
- import test from "node:test";
4
+ import { mkdtempSync, writeFileSync, rmSync } from "node:fs";
5
+ import { tmpdir } from "node:os";
6
+ import { execSync } from "node:child_process";
7
+ import { join } from "node:path";
8
+ import test, { type TestContext } from "node:test";
5
9
  import assert from "node:assert/strict";
6
10
 
7
11
  import {
8
12
  isSuspiciousGhostCompletion,
9
13
  snapshotUnitActivity,
10
14
  } from "../auto-unit-closeout.ts";
15
+ import {
16
+ closeUnit,
17
+ type UnitCloseoutRequest,
18
+ type UnitCloseoutDeps,
19
+ } from "../unit-closeout.ts";
20
+ import type { NotifySeverity } from "../notification-store.js";
11
21
 
12
22
  function makeCtx(entries: unknown[]) {
13
23
  return {
@@ -17,6 +27,38 @@ function makeCtx(entries: unknown[]) {
17
27
  } as any;
18
28
  }
19
29
 
30
+ function createTempGitRepo(t: TestContext): string {
31
+ const dir = mkdtempSync(join(tmpdir(), "closeout-test-"));
32
+ t.after(() => rmSync(dir, { recursive: true, force: true }));
33
+ execSync("git init", { cwd: dir });
34
+ execSync("git config user.email test@test.com", { cwd: dir });
35
+ execSync("git config user.name Test", { cwd: dir });
36
+ return dir;
37
+ }
38
+
39
+ function makeMockDeps(overrides: Partial<UnitCloseoutDeps> = {}): UnitCloseoutDeps & { notifications: Array<{ message: string; severity: NotifySeverity }> } {
40
+ const notifications: Array<{ message: string; severity: NotifySeverity }> = [];
41
+ return {
42
+ isolationMode: () => "none",
43
+ currentBranch: () => "main",
44
+ commit: () => null,
45
+ notify: (message, severity) => notifications.push({ message, severity }),
46
+ notifications,
47
+ ...overrides,
48
+ };
49
+ }
50
+
51
+ function baseRequest(overrides: Partial<UnitCloseoutRequest> = {}): UnitCloseoutRequest {
52
+ return {
53
+ basePath: "/tmp/ignored",
54
+ unitType: "complete-milestone",
55
+ unitId: "M001",
56
+ boundary: "milestone",
57
+ outcome: "complete",
58
+ ...overrides,
59
+ };
60
+ }
61
+
20
62
  test("isSuspiciousGhostCompletion rejects fast completions with no assistant output or tools", () => {
21
63
  const startedAt = Date.now();
22
64
  const ctx = makeCtx([]);
@@ -66,3 +108,129 @@ test("snapshotUnitActivity counts assistant messages and tool calls", () => {
66
108
  assistantMessages: 1,
67
109
  });
68
110
  });
111
+
112
+ test("closeUnit: nothing-to-commit / isolation none", (t) => {
113
+ const dir = createTempGitRepo(t);
114
+ const deps = makeMockDeps({
115
+ isolationMode: () => "none",
116
+ commit: () => null,
117
+ });
118
+
119
+ const result = closeUnit(baseRequest({ basePath: dir, boundary: "milestone" }), deps);
120
+
121
+ assert.equal(result.gitVerdict, "nothing-to-commit");
122
+ assert.equal(result.commitMessage, null);
123
+ assert.equal(result.notice, undefined);
124
+ assert.equal(deps.notifications.length, 0);
125
+ });
126
+
127
+ test("closeUnit: committed / isolation none", (t) => {
128
+ const dir = createTempGitRepo(t);
129
+ writeFileSync(join(dir, "file.txt"), "hello");
130
+ execSync("git add file.txt", { cwd: dir });
131
+
132
+ const deps = makeMockDeps({
133
+ isolationMode: () => "none",
134
+ commit: () => "Add file.txt",
135
+ });
136
+
137
+ const result = closeUnit(baseRequest({ basePath: dir, boundary: "milestone" }), deps);
138
+
139
+ assert.equal(result.gitVerdict, "committed");
140
+ assert.equal(result.commitMessage, "Add file.txt");
141
+ assert.equal(result.notice, undefined);
142
+ assert.equal(deps.notifications.length, 0);
143
+ });
144
+
145
+ test("closeUnit: milestone-branch / worktree isolation", (t) => {
146
+ const dir = createTempGitRepo(t);
147
+ const deps = makeMockDeps({
148
+ isolationMode: () => "worktree",
149
+ currentBranch: () => "milestone/M001",
150
+ commit: () => "Complete M001",
151
+ });
152
+
153
+ const result = closeUnit(baseRequest({ basePath: dir, boundary: "milestone" }), deps);
154
+
155
+ assert.equal(result.gitVerdict, "milestone-branch");
156
+ assert.equal(result.commitMessage, "Complete M001");
157
+ assert.ok(result.notice);
158
+ assert.equal(deps.notifications.length, 1);
159
+ assert.equal(deps.notifications[0].severity, "info");
160
+ assert.match(deps.notifications[0].message, /Merge it to the integration branch/);
161
+ });
162
+
163
+ test("closeUnit: isolation-bypassed / worktree isolation", (t) => {
164
+ const dir = createTempGitRepo(t);
165
+ const deps = makeMockDeps({
166
+ isolationMode: () => "worktree",
167
+ currentBranch: () => "main",
168
+ commit: () => "Complete M001",
169
+ });
170
+
171
+ const result = closeUnit(baseRequest({ basePath: dir, boundary: "milestone" }), deps);
172
+
173
+ assert.equal(result.gitVerdict, "isolation-bypassed");
174
+ assert.equal(result.commitMessage, "Complete M001");
175
+ assert.ok(result.notice);
176
+ assert.equal(deps.notifications.length, 1);
177
+ assert.equal(deps.notifications[0].severity, "warning");
178
+ assert.match(deps.notifications[0].message, /completed outside a milestone worktree\/branch/);
179
+ });
180
+
181
+ test("closeUnit: isolation-bypassed / branch isolation", (t) => {
182
+ const dir = createTempGitRepo(t);
183
+ const deps = makeMockDeps({
184
+ isolationMode: () => "branch",
185
+ currentBranch: () => "main",
186
+ commit: () => "Complete M001",
187
+ });
188
+
189
+ const result = closeUnit(baseRequest({ basePath: dir, boundary: "milestone" }), deps);
190
+
191
+ assert.equal(result.gitVerdict, "isolation-bypassed");
192
+ assert.equal(result.commitMessage, "Complete M001");
193
+ assert.ok(result.notice);
194
+ assert.equal(deps.notifications.length, 1);
195
+ assert.equal(deps.notifications[0].severity, "warning");
196
+ assert.match(deps.notifications[0].message, /completed outside a milestone worktree\/branch/);
197
+ });
198
+
199
+ test("closeUnit: commit-failed", (t) => {
200
+ const dir = createTempGitRepo(t);
201
+ const deps = makeMockDeps({
202
+ isolationMode: () => "none",
203
+ commit: () => {
204
+ throw new Error("simulated commit failure");
205
+ },
206
+ });
207
+
208
+ const result = closeUnit(baseRequest({ basePath: dir, boundary: "milestone" }), deps);
209
+
210
+ assert.equal(result.gitVerdict, "commit-failed");
211
+ assert.equal(result.commitMessage, null);
212
+ assert.ok(result.notice);
213
+ assert.match(result.notice!, /simulated commit failure/);
214
+ assert.equal(deps.notifications.length, 1);
215
+ assert.equal(deps.notifications[0].severity, "error");
216
+ });
217
+
218
+ test("closeUnit: task boundary ignores isolation verdict", (t) => {
219
+ const dir = createTempGitRepo(t);
220
+ const deps = makeMockDeps({
221
+ isolationMode: () => "worktree",
222
+ currentBranch: () => "main",
223
+ commit: () => "Complete task",
224
+ });
225
+
226
+ const result = closeUnit(
227
+ baseRequest({ basePath: dir, boundary: "task", unitType: "execute-task", unitId: "M001/S01/T01" }),
228
+ deps,
229
+ );
230
+
231
+ assert.equal(result.gitVerdict, "committed");
232
+ assert.equal(result.commitMessage, "Complete task");
233
+ assert.equal(result.notice, undefined);
234
+ assert.equal(deps.notifications.length, 0);
235
+ });
236
+
@@ -0,0 +1,36 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+ import { runPostUnitVerification } from "../auto-verification.ts";
4
+
5
+ function createVerificationContext(currentUnit: { type: string; id: string } | null) {
6
+ return {
7
+ s: {
8
+ currentUnit,
9
+ },
10
+ ctx: {
11
+ ui: {
12
+ notify() {
13
+ throw new Error("notify should not be called for pass-through units");
14
+ },
15
+ },
16
+ },
17
+ pi: {},
18
+ };
19
+ }
20
+
21
+ test("post-unit verification continues when no host-owned verification is needed", async () => {
22
+ let paused = false;
23
+ const pauseAuto = async () => {
24
+ paused = true;
25
+ };
26
+
27
+ assert.equal(await runPostUnitVerification(createVerificationContext(null) as never, pauseAuto), "continue");
28
+ assert.equal(
29
+ await runPostUnitVerification(
30
+ createVerificationContext({ type: "plan-slice", id: "M001-S001" }) as never,
31
+ pauseAuto,
32
+ ),
33
+ "continue",
34
+ );
35
+ assert.equal(paused, false);
36
+ });
@@ -0,0 +1,218 @@
1
+ // gsd-pi — Blocker-placeholder recovery log coverage.
2
+ //
3
+ // writeBlockerPlaceholder (auto-recovery.ts:782) writes a placeholder artifact
4
+ // so the pipeline can advance past a stuck unit, then marks the task/slice
5
+ // complete in the DB and appends a workflow event so reconciliation can replay
6
+ // the recovery. Each of those side-effects is individually best-effort and logs
7
+ // a recovery warning on failure (auto-recovery.ts:837/840/843/844/853/854). No
8
+ // test asserted any of them. We trigger each by breaking the specific sink
9
+ // (drop the relevant DB table, or block the events-file append) and assert the
10
+ // warning lands.
11
+
12
+ import { test } from "node:test";
13
+ import assert from "node:assert/strict";
14
+ import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
15
+ import { join } from "node:path";
16
+ import { tmpdir } from "node:os";
17
+
18
+ import { writeBlockerPlaceholder } from "../auto-recovery.ts";
19
+ import { writeReactiveExecuteBlocker } from "../auto-recovery.ts";
20
+ import {
21
+ closeDatabase,
22
+ insertMilestone,
23
+ insertSlice,
24
+ insertTask,
25
+ openDatabase,
26
+ _getAdapter,
27
+ } from "../gsd-db.ts";
28
+ import {
29
+ drainLogs,
30
+ setStderrLoggingEnabled,
31
+ _resetLogs,
32
+ type LogEntry,
33
+ } from "../workflow-logger.ts";
34
+
35
+ function makeBase(prefix = "gsd-blocker-logs-"): string {
36
+ const base = mkdtempSync(join(tmpdir(), prefix));
37
+ // Slice projection dirs so the placeholder path resolves.
38
+ mkdirSync(join(base, ".gsd", "milestones", "M001", "slices", "S01", "tasks"), { recursive: true });
39
+ return base;
40
+ }
41
+
42
+ function captureLogs<T>(fn: () => T): { result: T; logs: LogEntry[] } {
43
+ const previous = setStderrLoggingEnabled(false);
44
+ _resetLogs();
45
+ try {
46
+ const result = fn();
47
+ return { result, logs: drainLogs() };
48
+ } finally {
49
+ _resetLogs();
50
+ setStderrLoggingEnabled(previous);
51
+ }
52
+ }
53
+
54
+ function recoveryWarnings(logs: readonly LogEntry[]): LogEntry[] {
55
+ return logs.filter((e) => e.component === "recovery" && e.severity === "warn");
56
+ }
57
+
58
+ test("writeBlockerPlaceholder logs a recovery warning when updateTaskStatus throws (auto-recovery.ts:837)", () => {
59
+ const base = makeBase();
60
+ try {
61
+ openDatabase(join(base, ".gsd", "gsd.db"));
62
+ // Drop tasks so updateTaskStatus throws inside the execute-task DB block.
63
+ _getAdapter()!.exec("DROP TABLE tasks");
64
+
65
+ const { logs } = captureLogs(() =>
66
+ writeBlockerPlaceholder("execute-task", "M001/S01/T01", base, "exhausted retries"),
67
+ );
68
+
69
+ const warn = recoveryWarnings(logs).find((w) => /updateTaskStatus failed during context exhaustion/u.test(w.message));
70
+ assert.ok(warn, "a recovery warning must be logged when updateTaskStatus throws");
71
+ } finally {
72
+ closeDatabase();
73
+ rmSync(base, { recursive: true, force: true });
74
+ }
75
+ });
76
+
77
+ test("writeBlockerPlaceholder logs a recovery warning when updateSliceStatus throws (auto-recovery.ts:843)", () => {
78
+ const base = makeBase();
79
+ try {
80
+ openDatabase(join(base, ".gsd", "gsd.db"));
81
+ // Drop slices so updateSliceStatus throws inside the complete-slice DB block.
82
+ _getAdapter()!.exec("DROP TABLE slices");
83
+
84
+ const { logs } = captureLogs(() =>
85
+ writeBlockerPlaceholder("complete-slice", "M001/S01", base, "exhausted retries"),
86
+ );
87
+
88
+ const warn = recoveryWarnings(logs).find((w) => /updateSliceStatus failed during context exhaustion/u.test(w.message));
89
+ assert.ok(warn, "a recovery warning must be logged when updateSliceStatus throws");
90
+ } finally {
91
+ closeDatabase();
92
+ rmSync(base, { recursive: true, force: true });
93
+ }
94
+ });
95
+
96
+ test("writeBlockerPlaceholder logs a recovery warning when the plan-milestone insertSlice throws (auto-recovery.ts:853)", () => {
97
+ const base = makeBase();
98
+ try {
99
+ openDatabase(join(base, ".gsd", "gsd.db"));
100
+ // Drop slices so the S00-blocker insertSlice throws inside the
101
+ // plan-milestone placeholder branch.
102
+ _getAdapter()!.exec("DROP TABLE slices");
103
+
104
+ const { logs } = captureLogs(() =>
105
+ writeBlockerPlaceholder("plan-milestone", "M001", base, "exhausted retries"),
106
+ );
107
+
108
+ const warn = recoveryWarnings(logs).find((w) =>
109
+ /insertSlice placeholder failed for plan-milestone recovery/u.test(w.message),
110
+ );
111
+ assert.ok(warn, "a recovery warning must be logged when the blocker slice insert throws");
112
+ } finally {
113
+ closeDatabase();
114
+ rmSync(base, { recursive: true, force: true });
115
+ }
116
+ });
117
+
118
+ test("writeBlockerPlaceholder logs a recovery warning when the workflow-event append throws (auto-recovery.ts:840)", () => {
119
+ const base = makeBase();
120
+ try {
121
+ openDatabase(join(base, ".gsd", "gsd.db"));
122
+ // Block the workflow-events append by turning its target into a directory
123
+ // (appendFileSync on a directory throws EISDIR). The placeholder write still
124
+ // succeeds because it targets a different path under milestones/.
125
+ mkdirSync(join(base, ".gsd", "event-log.jsonl"), { recursive: true });
126
+
127
+ const { logs } = captureLogs(() =>
128
+ writeBlockerPlaceholder("execute-task", "M001/S01/T01", base, "exhausted retries"),
129
+ );
130
+
131
+ const warn = recoveryWarnings(logs).find((w) => /appendEvent failed for task recovery/u.test(w.message));
132
+ assert.ok(warn, "a recovery warning must be logged when the recovery event append fails");
133
+ } finally {
134
+ closeDatabase();
135
+ rmSync(base, { recursive: true, force: true });
136
+ }
137
+ });
138
+
139
+ test("writeBlockerPlaceholder logs a recovery warning when the complete-slice appendEvent throws (auto-recovery.ts:898)", () => {
140
+ const base = makeBase("gsd-blocker-logs-cs-");
141
+ try {
142
+ openDatabase(join(base, ".gsd", "gsd.db"));
143
+ // Slices table intact so updateSliceStatus (:897) succeeds; block the
144
+ // workflow-event append so the complete-slice appendEvent (:898) throws.
145
+ mkdirSync(join(base, ".gsd", "event-log.jsonl"), { recursive: true });
146
+
147
+ const { logs } = captureLogs(() =>
148
+ writeBlockerPlaceholder("complete-slice", "M001/S01", base, "exhausted retries"),
149
+ );
150
+
151
+ const warn = recoveryWarnings(logs).find((w) => /appendEvent failed for slice recovery/u.test(w.message));
152
+ assert.ok(warn, "a recovery warning must be logged when the complete-slice appendEvent throws");
153
+ } finally {
154
+ closeDatabase();
155
+ rmSync(base, { recursive: true, force: true });
156
+ }
157
+ });
158
+
159
+ test("writeBlockerPlaceholder logs a recovery warning when the plan-milestone appendEvent throws (auto-recovery.ts:908)", () => {
160
+ const base = mkdtempSync(join(tmpdir(), "gsd-blocker-logs-pm-"));
161
+ mkdirSync(join(base, ".gsd", "milestones", "M001"), { recursive: true });
162
+ try {
163
+ openDatabase(join(base, ".gsd", "gsd.db"));
164
+ // Slices table intact so the S00-blocker insertSlice (:907) succeeds;
165
+ // block the workflow-event append so the plan-milestone appendEvent (:908) throws.
166
+ mkdirSync(join(base, ".gsd", "event-log.jsonl"), { recursive: true });
167
+
168
+ const { logs } = captureLogs(() =>
169
+ writeBlockerPlaceholder("plan-milestone", "M001", base, "exhausted retries"),
170
+ );
171
+
172
+ const warn = recoveryWarnings(logs).find((w) => /appendEvent failed for plan-milestone recovery/u.test(w.message));
173
+ assert.ok(warn, "a recovery warning must be logged when the plan-milestone appendEvent throws");
174
+ } finally {
175
+ closeDatabase();
176
+ rmSync(base, { recursive: true, force: true });
177
+ }
178
+ });
179
+
180
+ // ── writeReactiveExecuteBlocker append-event warnings (:755 / :768) ────────
181
+ // These fire after the reactive batch recovery transaction commits, when the
182
+ // per-task workflow-event append throws. We seed a real slice with two tasks,
183
+ // plant the event-log target as a directory (appendFileSync → EISDIR), and call
184
+ // writeReactiveExecuteBlocker; both the complete-task and skip-task appends fail.
185
+
186
+ test("writeReactiveExecuteBlocker logs recovery warnings when the post-recovery event appends throw (auto-recovery.ts:755/:768)", () => {
187
+ const base = mkdtempSync(join(tmpdir(), "gsd-blocker-logs-reactive-"));
188
+ mkdirSync(join(base, ".gsd", "milestones", "M001", "slices", "S01", "tasks"), { recursive: true });
189
+ try {
190
+ openDatabase(join(base, ".gsd", "gsd.db"));
191
+ insertMilestone({ id: "M001", title: "M", status: "active" });
192
+ insertSlice({ id: "S01", milestoneId: "M001", title: "S", status: "active", risk: "low", depends: [], demo: "", sequence: 1 });
193
+ insertTask({ id: "T01", sliceId: "S01", milestoneId: "M001", title: "T1", status: "active" });
194
+ insertTask({ id: "T02", sliceId: "S01", milestoneId: "M001", title: "T2", status: "active" });
195
+ // T01 has a summary (→ complete recovery path → :755), T02 does not
196
+ // (→ skip recovery path → :768).
197
+ writeFileSync(join(base, ".gsd", "milestones", "M001", "slices", "S01", "tasks", "T01-SUMMARY.md"), "# T01\n", "utf-8");
198
+ // Block the workflow-event append (event-log.jsonl is the real ledger file).
199
+ mkdirSync(join(base, ".gsd", "event-log.jsonl"), { recursive: true });
200
+
201
+ const { logs } = captureLogs(() =>
202
+ writeReactiveExecuteBlocker("M001/S01/reactive+T01,T02", base, "batch exhausted"),
203
+ );
204
+
205
+ const warnings = recoveryWarnings(logs).map((w) => w.message);
206
+ assert.ok(
207
+ warnings.some((m) => /appendEvent failed for reactive complete recovery/u.test(m)),
208
+ "the complete-task append warning must be logged (:755)",
209
+ );
210
+ assert.ok(
211
+ warnings.some((m) => /appendEvent failed for reactive skip recovery/u.test(m)),
212
+ "the skip-task append warning must be logged (:768)",
213
+ );
214
+ } finally {
215
+ closeDatabase();
216
+ rmSync(base, { recursive: true, force: true });
217
+ }
218
+ });
@@ -42,7 +42,11 @@ test("complete milestone prompt renders compact verification and completion guid
42
42
  assert.match(prompt, /Decision Re-evaluation/);
43
43
  assert.match(prompt, /self-diff/i);
44
44
  assert.match(prompt, /GSD-(?:Task|Unit)/);
45
- assert.match(prompt, /Milestone M001 complete/);
46
- assert.match(prompt, /Do not add a second final-status block/);
45
+ assert.match(prompt, /Closeout messaging \(auto-mode\)/);
46
+ assert.match(prompt, /Never say "Milestone M001 is complete"/);
47
+ assert.match(prompt, /Milestone M001 closeout submitted/);
48
+ assert.match(prompt, /Do not say the milestone is complete/);
49
+ assert.match(prompt, /VERIFICATION FAILED/);
50
+ assert.doesNotMatch(prompt, /emit only one closeout line: "Milestone M001 complete\."/);
47
51
  assert.doesNotMatch(prompt, /\{\{[a-zA-Z][a-zA-Z0-9_]*\}\}/);
48
52
  });
@@ -80,6 +80,20 @@ function createTempProject(): { basePath: string; planPath: string } {
80
80
  return { basePath, planPath };
81
81
  }
82
82
 
83
+ function writeProjectPreferences(basePath: string, yaml: string): void {
84
+ fs.writeFileSync(path.join(basePath, '.gsd', 'PREFERENCES.md'), `---\n${yaml}---\n`);
85
+ }
86
+
87
+ async function withWorkingDirectory<T>(cwd: string, action: () => Promise<T>): Promise<T> {
88
+ const previousCwd = process.cwd();
89
+ process.chdir(cwd);
90
+ try {
91
+ return await action();
92
+ } finally {
93
+ process.chdir(previousCwd);
94
+ }
95
+ }
96
+
83
97
  function makeValidParams() {
84
98
  return {
85
99
  taskId: 'T01',
@@ -104,6 +118,13 @@ function makeValidParams() {
104
118
  };
105
119
  }
106
120
 
121
+ function makeEscalationOptions() {
122
+ return [
123
+ { id: 'continue', label: 'Continue', tradeoffs: 'Keeps execution moving with the default path.' },
124
+ { id: 'pause', label: 'Pause', tradeoffs: 'Stops execution until the blocker is reviewed.' },
125
+ ];
126
+ }
127
+
107
128
  // ═══════════════════════════════════════════════════════════════════════════
108
129
  // complete-task: Fresh DB is migrated to the current schema version
109
130
  // ═══════════════════════════════════════════════════════════════════════════
@@ -359,6 +380,105 @@ console.log('\n=== complete-task: handler happy path ===');
359
380
  cleanup(dbPath);
360
381
  }
361
382
 
383
+ // ═══════════════════════════════════════════════════════════════════════════
384
+ // complete-task: hard-blocker escalation with mid-execution escalation disabled
385
+ // ═══════════════════════════════════════════════════════════════════════════
386
+
387
+ console.log('\n=== complete-task: disabled hard-blocker escalation rolls back completion ===');
388
+ {
389
+ const dbPath = tempDbPath();
390
+ openDatabase(dbPath);
391
+
392
+ const { basePath } = createTempProject();
393
+ writeProjectPreferences(basePath, 'phases:\n mid_execution_escalation: false\n');
394
+
395
+ insertMilestone({ id: 'M001', title: 'Test Milestone' });
396
+ insertSlice({ id: 'S01', milestoneId: 'M001', title: 'Test Slice' });
397
+
398
+ const params = {
399
+ ...makeValidParams(),
400
+ blockerDiscovered: true,
401
+ escalation: {
402
+ question: 'Should execution pause for the hard blocker?',
403
+ options: makeEscalationOptions(),
404
+ recommendation: 'pause',
405
+ recommendationRationale: 'The blocker should not be silently advanced.',
406
+ continueWithDefault: false,
407
+ },
408
+ };
409
+
410
+ const result = await withWorkingDirectory(basePath, () => handleCompleteTask(params, basePath));
411
+
412
+ assertTrue('error' in result, 'hard-blocker escalation should fail when escalation handling is disabled');
413
+ if ('error' in result) {
414
+ assertMatch(result.error, /hard-blocker escalation/, 'error should mention hard-blocker escalation');
415
+ assertMatch(result.error, /mid_execution_escalation is disabled/, 'error should mention disabled preference');
416
+ }
417
+
418
+ const task = getTask('M001', 'S01', 'T01');
419
+ assertTrue(task !== null, 'task row should remain after rollback');
420
+ assertEq(task!.status, 'pending', 'task status should be rolled back to pending');
421
+ assertEq(task!.blocker_discovered, true, 'blocker flag should remain recorded for visibility');
422
+ assertEq(task!.escalation_pending, 0, 'disabled preference should not create a pending escalation flag');
423
+ assertEq(task!.escalation_awaiting_review, 0, 'disabled preference should not create an awaiting-review flag');
424
+
425
+ const adapter = _getAdapter()!;
426
+ const evRows = adapter.prepare(
427
+ "SELECT * FROM verification_evidence WHERE task_id = 'T01' AND slice_id = 'S01' AND milestone_id = 'M001'"
428
+ ).all();
429
+ assertEq(evRows.length, 0, 'verification evidence should be deleted when completion rolls back');
430
+
431
+ cleanupDir(basePath);
432
+ cleanup(dbPath);
433
+ }
434
+
435
+ // ═══════════════════════════════════════════════════════════════════════════
436
+ // complete-task: soft escalation with mid-execution escalation disabled
437
+ // ═══════════════════════════════════════════════════════════════════════════
438
+
439
+ console.log('\n=== complete-task: disabled soft escalation still completes ===');
440
+ {
441
+ const dbPath = tempDbPath();
442
+ openDatabase(dbPath);
443
+
444
+ const { basePath } = createTempProject();
445
+ writeProjectPreferences(basePath, 'phases:\n mid_execution_escalation: false\n');
446
+
447
+ insertMilestone({ id: 'M001', title: 'Test Milestone' });
448
+ insertSlice({ id: 'S01', milestoneId: 'M001', title: 'Test Slice' });
449
+
450
+ const params = {
451
+ ...makeValidParams(),
452
+ escalation: {
453
+ question: 'Should execution continue with the default?',
454
+ options: makeEscalationOptions(),
455
+ recommendation: 'continue',
456
+ recommendationRationale: 'The default path is safe enough to continue.',
457
+ continueWithDefault: true,
458
+ },
459
+ };
460
+
461
+ const result = await withWorkingDirectory(basePath, () => handleCompleteTask(params, basePath));
462
+
463
+ assertTrue(!('error' in result), 'soft escalation should still complete when escalation handling is disabled');
464
+ if (!('error' in result)) {
465
+ assertTrue(!result.escalation, 'disabled preference should not return escalation metadata');
466
+ }
467
+
468
+ const task = getTask('M001', 'S01', 'T01');
469
+ assertTrue(task !== null, 'task row should exist');
470
+ assertEq(task!.status, 'complete', 'soft escalation should leave task complete');
471
+
472
+ const adapter = _getAdapter()!;
473
+ const evRows = adapter.prepare(
474
+ "SELECT * FROM verification_evidence WHERE task_id = 'T01' AND slice_id = 'S01' AND milestone_id = 'M001'"
475
+ ).all();
476
+ assertEq(evRows.length, 1, 'verification evidence should remain for soft escalation completion');
477
+
478
+ cleanupDir(basePath);
479
+ cleanup(dbPath);
480
+ }
481
+
362
482
  // ═══════════════════════════════════════════════════════════════════════════
363
483
  // complete-task: Handler validation errors
364
484
  // ═══════════════════════════════════════════════════════════════════════════
@@ -414,6 +534,9 @@ console.log('\n=== complete-task: handler idempotency ===');
414
534
  // First call should succeed
415
535
  const r1 = await handleCompleteTask(params, basePath);
416
536
  assertTrue(!('error' in r1), 'first call should succeed');
537
+ if ('error' in r1) {
538
+ throw new Error(r1.error);
539
+ }
417
540
 
418
541
  // Verify complete-task did not duplicate T01. S01-PLAN.md is a projection,
419
542
  // so the remaining plan task is not imported implicitly.
@@ -421,16 +544,29 @@ console.log('\n=== complete-task: handler idempotency ===');
421
544
  assertEq(tasks.length, 1, 'should only have the completed DB task after first call');
422
545
  assertEq(tasks.filter(t => t.id === 'T01').length, 1, 'should have exactly one T01 row after first call');
423
546
 
424
- // Second call with same params state machine guard rejects (task is already complete)
547
+ // If the DB row is complete but the projection was lost, the duplicate call
548
+ // should repair the missing summary from full_summary_md instead of forcing a
549
+ // reopen/re-complete loop.
550
+ fs.unlinkSync(r1.summaryPath);
551
+ assertTrue(!fs.existsSync(r1.summaryPath), 'fixture should remove the task summary before repair');
425
552
  const r2 = await handleCompleteTask(params, basePath);
426
- assertTrue('error' in r2, 'second call should return error (task already complete)');
553
+ assertTrue(!('error' in r2), 'second call should repair missing summary for DB-complete task');
427
554
  if ('error' in r2) {
428
- assertMatch(r2.error, /already complete/, 'error should mention already complete');
555
+ throw new Error(r2.error);
556
+ }
557
+ assertTrue(fs.existsSync(r2.summaryPath), 'missing summary should be restored on disk');
558
+ assertEq(r2.duplicate, true, 'repair should be reported as a duplicate/no-op state mutation');
559
+
560
+ // Third call with the summary present — state machine guard rejects (task is already complete)
561
+ const r3 = await handleCompleteTask(params, basePath);
562
+ assertTrue('error' in r3, 'third call should return error (task already complete)');
563
+ if ('error' in r3) {
564
+ assertMatch(r3.error, /already complete/, 'error should mention already complete');
429
565
  }
430
566
 
431
- // Still no duplicate rows from the rejected second call.
567
+ // Still no duplicate rows from the repair or rejected third call.
432
568
  const tasksAfter = getSliceTasks('M001', 'S01');
433
- assertEq(tasksAfter.length, 1, 'should still only have T01 after rejected second call');
569
+ assertEq(tasksAfter.length, 1, 'should still only have T01 after duplicate repair and rejected third call');
434
570
  assertEq(tasksAfter.filter(t => t.id === 'T01').length, 1, 'should still have exactly one T01 row');
435
571
 
436
572
  cleanupDir(basePath);
@@ -13,6 +13,7 @@ function makeCtx(customResult: unknown) {
13
13
  const customCalls: Array<{ options: any }> = [];
14
14
  return {
15
15
  hasUI: true,
16
+ modelRegistry: { getAvailable: () => [] },
16
17
  ui: {
17
18
  custom: async (_factory: unknown, options: any) => {
18
19
  customCalls.push({ options });