@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
@@ -0,0 +1,428 @@
1
+ // gsd-pi — Recovery artifact-verification log coverage.
2
+ //
3
+ // `verifyExpectedArtifact` is the gate that prevents an LLM from advancing the
4
+ // pipeline with a stub or incomplete artifact. Each verify-fail branch emits a
5
+ // `recovery` warning (or error) describing the exact reason — these logs are
6
+ // the operator's signal during stuck-loop diagnosis, so regressions that change
7
+ // or drop them must surface. The existing artifact-verification tests assert
8
+ // only the boolean return value; this file pins the log output for each
9
+ // important gate:
10
+ // - plan-milestone roadmap has zero slices (auto-recovery.ts:511)
11
+ // - run-uat assessment missing a verdict (auto-recovery.ts:502)
12
+ // - validate-milestone validation not terminal (auto-recovery.ts:494)
13
+ // - generic verify-fail: artifact file missing (auto-recovery.ts:487)
14
+
15
+ import { test } from "node:test";
16
+ import assert from "node:assert/strict";
17
+ import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
18
+ import { join } from "node:path";
19
+ import { tmpdir } from "node:os";
20
+
21
+ import { verifyExpectedArtifact, _setRoadmapParserFnForTests } from "../auto-recovery.ts";
22
+ import { closeDatabase, openDatabase, _getAdapter } from "../gsd-db.ts";
23
+ import {
24
+ drainLogs,
25
+ peekLogs,
26
+ setStderrLoggingEnabled,
27
+ _resetLogs,
28
+ type LogEntry,
29
+ } from "../workflow-logger.ts";
30
+
31
+ function createFixtureBase(prefix = "gsd-recovery-logs-"): string {
32
+ const base = mkdtempSync(join(tmpdir(), prefix));
33
+ mkdirSync(join(base, ".gsd", "milestones"), { recursive: true });
34
+ return base;
35
+ }
36
+
37
+ function milestoneDir(base: string, mid: string): string {
38
+ const dir = join(base, ".gsd", "milestones", mid);
39
+ mkdirSync(dir, { recursive: true });
40
+ return dir;
41
+ }
42
+
43
+ function sliceDir(base: string, mid: string, sid: string): string {
44
+ const dir = join(base, ".gsd", "milestones", mid, "slices", sid);
45
+ mkdirSync(dir, { recursive: true });
46
+ return dir;
47
+ }
48
+
49
+ /**
50
+ * Run `verifyExpectedArtifact` with stderr suppressed and capture both the
51
+ * return value and the log entries emitted by the call. The log buffer is
52
+ * reset before the call (so no bleed from prior tests) and drained inside the
53
+ * capture scope (before the finally clears it) so callers can assert on logs
54
+ * after the helper returns.
55
+ *
56
+ * NOTE: the workflow-logger `_buffer` is a process-wide singleton shared with
57
+ * the code under test, so we must drain inside this scope — reading it after
58
+ * the finally would see an already-cleared buffer.
59
+ */
60
+ function verifyAndCaptureLogs(
61
+ unitType: string,
62
+ unitId: string,
63
+ base: string,
64
+ ): { result: boolean; logs: LogEntry[] } {
65
+ const previous = setStderrLoggingEnabled(false);
66
+ _resetLogs();
67
+ try {
68
+ const result = verifyExpectedArtifact(unitType, unitId, base);
69
+ return { result, logs: drainLogs() };
70
+ } finally {
71
+ _resetLogs();
72
+ setStderrLoggingEnabled(previous);
73
+ }
74
+ }
75
+
76
+ function findRecovery(logs: readonly LogEntry[]): LogEntry | undefined {
77
+ return logs.find((e) => e.component === "recovery");
78
+ }
79
+
80
+ test("plan-milestone verify-fail logs a recovery warning naming the zero-slice roadmap", () => {
81
+ const base = createFixtureBase();
82
+ try {
83
+ const dir = milestoneDir(base, "M001");
84
+ writeFileSync(join(dir, "M001-ROADMAP.md"), "# M001: Stub\n\n## Slices\n\n_TBD_\n", "utf-8");
85
+
86
+ const { result, logs } = verifyAndCaptureLogs("plan-milestone", "M001", base);
87
+
88
+ assert.equal(result, false, "zero-slice roadmap must fail verification");
89
+ const recovery = findRecovery(logs);
90
+ assert.ok(recovery, "a recovery warning must be logged");
91
+ assert.equal(recovery!.severity, "warn");
92
+ assert.match(recovery!.message, /verify-fail plan-milestone M001: roadmap has zero slices/u);
93
+ } finally {
94
+ rmSync(base, { recursive: true, force: true });
95
+ }
96
+ });
97
+
98
+ test("run-uat verify-fail logs a recovery warning when the assessment has no verdict", () => {
99
+ const base = createFixtureBase();
100
+ try {
101
+ const dir = sliceDir(base, "M001", "S01");
102
+ // No `verdict:` frontmatter → hasVerdict() returns false → warning fires.
103
+ writeFileSync(join(dir, "S01-ASSESSMENT.md"), "# UAT\n\nNo verdict yet.\n", "utf-8");
104
+
105
+ const { result, logs } = verifyAndCaptureLogs("run-uat", "M001/S01", base);
106
+
107
+ assert.equal(result, false, "verdict-less assessment must fail verification");
108
+ const recovery = findRecovery(logs);
109
+ assert.ok(recovery, "a recovery entry must be logged");
110
+ assert.equal(recovery!.severity, "warn");
111
+ assert.match(recovery!.message, /verify-fail run-uat M001\/S01: assessment missing verdict/u);
112
+ } finally {
113
+ rmSync(base, { recursive: true, force: true });
114
+ }
115
+ });
116
+
117
+ test("validate-milestone verify-fail logs a recovery warning when the validation is not terminal", () => {
118
+ const base = createFixtureBase();
119
+ try {
120
+ const dir = milestoneDir(base, "M001");
121
+ // No `verdict:` → isValidationTerminal() returns false → warning fires.
122
+ writeFileSync(join(dir, "M001-VALIDATION.md"), "# Validation\n\nStill in progress.\n", "utf-8");
123
+
124
+ const { result, logs } = verifyAndCaptureLogs("validate-milestone", "M001", base);
125
+
126
+ assert.equal(result, false, "non-terminal validation must fail verification");
127
+ const recovery = findRecovery(logs);
128
+ assert.ok(recovery, "a recovery warning must be logged");
129
+ assert.equal(recovery!.severity, "warn");
130
+ assert.match(recovery!.message, /verify-fail validate-milestone M001: validation not terminal/u);
131
+ } finally {
132
+ rmSync(base, { recursive: true, force: true });
133
+ }
134
+ });
135
+
136
+ test("verify-fail logs a recovery warning when an expected artifact file is absent", () => {
137
+ const base = createFixtureBase();
138
+ try {
139
+ // complete-slice resolves a SUMMARY path under the milestone dir, but we
140
+ // never write the file → existsSync is false → the generic verify-fail path
141
+ // logs and returns false.
142
+ sliceDir(base, "M001", "S01");
143
+
144
+ const { result, logs } = verifyAndCaptureLogs("complete-slice", "M001/S01", base);
145
+
146
+ assert.equal(result, false, "missing artifact must fail verification");
147
+ const recovery = findRecovery(logs);
148
+ assert.ok(recovery, "a recovery warning must be logged");
149
+ assert.equal(recovery!.severity, "warn");
150
+ assert.match(recovery!.message, /verify-fail complete-slice M001\/S01: existsSync false/u);
151
+ } finally {
152
+ rmSync(base, { recursive: true, force: true });
153
+ }
154
+ });
155
+
156
+ test("a passing verification produces no recovery warnings", () => {
157
+ const base = createFixtureBase();
158
+ try {
159
+ const dir = milestoneDir(base, "M001");
160
+ writeFileSync(
161
+ join(dir, "M001-ROADMAP.md"),
162
+ ["# M001: Real roadmap", "", "## Slices", "", "- [ ] **S01: First slice** `risk:low` `depends:[]`", ""].join("\n"),
163
+ "utf-8",
164
+ );
165
+
166
+ const { result, logs } = verifyAndCaptureLogs("plan-milestone", "M001", base);
167
+
168
+ assert.equal(result, true, "a real roadmap must pass verification");
169
+ assert.equal(
170
+ findRecovery(logs),
171
+ undefined,
172
+ "no recovery warning should be logged on success",
173
+ );
174
+ } finally {
175
+ rmSync(base, { recursive: true, force: true });
176
+ }
177
+ });
178
+
179
+ // ─── plan-slice verification gates (legacy path, no DB) ────────────────────
180
+ // These run the filesystem fallback when isDbAvailable() is false. Each verify-
181
+ // fail branch logs a recovery warning naming the exact missing artifact, so a
182
+ // regression that drops the reason would hide why a slice refused to advance.
183
+
184
+ test("plan-slice verify-fail logs a recovery warning when the plan has no task entries", () => {
185
+ const base = createFixtureBase("gsd-recovery-logs-plan-");
186
+ try {
187
+ const dir = sliceDir(base, "M001", "S01");
188
+ // A PLAN with neither a `- [ ] **T0x:**` checkbox nor a `## T0x --` heading.
189
+ writeFileSync(join(dir, "S01-PLAN.md"), "# S01: Stub\n\n## Tasks\n\n_TBD_\n", "utf-8");
190
+
191
+ const { result, logs } = verifyAndCaptureLogs("plan-slice", "M001/S01", base);
192
+
193
+ assert.equal(result, false, "a task-less plan must fail verification");
194
+ const recovery = findRecovery(logs);
195
+ assert.ok(recovery, "a recovery warning must be logged");
196
+ assert.match(
197
+ recovery!.message,
198
+ /verify-fail plan-slice M001\/S01: plan has no task checkbox\/heading/u,
199
+ );
200
+ } finally {
201
+ rmSync(base, { recursive: true, force: true });
202
+ }
203
+ });
204
+
205
+ test("plan-slice verify-fail logs a recovery warning when the tasks dir is missing", () => {
206
+ const base = createFixtureBase("gsd-recovery-logs-tasksdir-");
207
+ try {
208
+ const dir = sliceDir(base, "M001", "S01");
209
+ // Valid checkbox task, but we deliberately do NOT create the tasks/ dir.
210
+ writeFileSync(
211
+ join(dir, "S01-PLAN.md"),
212
+ "# S01: Has task\n\n## Tasks\n\n- [ ] **T01: A** `est:15m`\n",
213
+ "utf-8",
214
+ );
215
+
216
+ const { result, logs } = verifyAndCaptureLogs("plan-slice", "M001/S01", base);
217
+
218
+ assert.equal(result, false, "a plan without its tasks dir must fail verification");
219
+ const recovery = findRecovery(logs);
220
+ assert.ok(recovery, "a recovery warning must be logged");
221
+ assert.match(
222
+ recovery!.message,
223
+ /verify-fail plan-slice M001\/S01: tasks dir missing/u,
224
+ );
225
+ } finally {
226
+ rmSync(base, { recursive: true, force: true });
227
+ }
228
+ });
229
+
230
+ test("plan-slice verify-fail logs a recovery warning when an individual task plan file is missing", () => {
231
+ const base = createFixtureBase("gsd-recovery-logs-taskplan-");
232
+ try {
233
+ const dir = sliceDir(base, "M001", "S01");
234
+ writeFileSync(
235
+ join(dir, "S01-PLAN.md"),
236
+ "# S01: Has task\n\n## Tasks\n\n- [ ] **T01: A** `est:15m`\n",
237
+ "utf-8",
238
+ );
239
+ // Create the tasks dir but NOT the T01-PLAN.md file inside it.
240
+ mkdirSync(join(dir, "tasks"), { recursive: true });
241
+
242
+ const { result, logs } = verifyAndCaptureLogs("plan-slice", "M001/S01", base);
243
+
244
+ assert.equal(result, false, "a missing task plan file must fail verification");
245
+ const recovery = findRecovery(logs);
246
+ assert.ok(recovery, "a recovery warning must be logged");
247
+ assert.match(
248
+ recovery!.message,
249
+ /verify-fail plan-slice M001\/S01: task plan missing .*T01-PLAN\.md/u,
250
+ );
251
+ } finally {
252
+ rmSync(base, { recursive: true, force: true });
253
+ }
254
+ });
255
+
256
+ // ─── parallel-research sentinel verification gates ─────────────────────────
257
+ // The "{mid}/parallel-research" sentinel fans research across multiple slices.
258
+ // verifyExpectedArtifact checks every research-ready slice has a RESEARCH file;
259
+ // each failure logs a recovery warning naming the exact gap.
260
+
261
+ test("parallel-research verify-fail logs a recovery warning when the roadmap is missing", () => {
262
+ const base = createFixtureBase("gsd-recovery-logs-prr-");
263
+ try {
264
+ // No roadmap file present → resolveExpectedArtifactPath("plan-milestone")
265
+ // returns null/missing → :445 warning.
266
+ const { result, logs } = verifyAndCaptureLogs("research-slice", "M001/parallel-research", base);
267
+
268
+ assert.equal(result, false, "missing roadmap must fail parallel-research verification");
269
+ const recovery = findRecovery(logs);
270
+ assert.ok(recovery, "a recovery warning must be logged");
271
+ assert.match(
272
+ recovery!.message,
273
+ /verify-fail research-slice M001\/parallel-research: roadmap missing/u,
274
+ );
275
+ } finally {
276
+ rmSync(base, { recursive: true, force: true });
277
+ }
278
+ });
279
+
280
+ test("parallel-research verify-fail logs a recovery warning when a research-ready slice lacks RESEARCH", () => {
281
+ const base = createFixtureBase("gsd-recovery-logs-prrs-");
282
+ try {
283
+ const dir = milestoneDir(base, "M001");
284
+ // A roadmap with one not-done slice (S01) and no milestone-level RESEARCH.
285
+ // S01 is research-ready (no deps, not done) and has no RESEARCH file → :462.
286
+ writeFileSync(
287
+ join(dir, "M001-ROADMAP.md"),
288
+ ["# M001: Roadmap", "", "## Slices", "", "- [ ] **S01: First** `risk:low` `depends:[]`", ""].join("\n"),
289
+ "utf-8",
290
+ );
291
+
292
+ const { result, logs } = verifyAndCaptureLogs("research-slice", "M001/parallel-research", base);
293
+
294
+ assert.equal(result, false, "a research-ready slice without RESEARCH must fail verification");
295
+ const recovery = findRecovery(logs);
296
+ assert.ok(recovery, "a recovery warning must be logged");
297
+ assert.match(
298
+ recovery!.message,
299
+ /verify-fail research-slice M001\/parallel-research: slice S01 missing RESEARCH/u,
300
+ );
301
+ } finally {
302
+ rmSync(base, { recursive: true, force: true });
303
+ }
304
+ });
305
+
306
+ // ─── gate-evaluate DB-degradation gate ─────────────────────────────────────
307
+ // gate-evaluate verifies dispatched gates are no longer pending via a DB query.
308
+ // When the DB is available but the query throws (e.g. quality_gates table
309
+ // missing), the catch (auto-recovery.ts:411) logs a recovery warning and treats
310
+ // the unit as verified to avoid blocking. This pins that degradation log.
311
+
312
+ test("gate-evaluate verify logs a recovery warning when the pending-gates DB query throws", () => {
313
+ const base = mkdtempSync(join(tmpdir(), "gsd-recovery-logs-gate-"));
314
+ mkdirSync(join(base, ".gsd"), { recursive: true });
315
+ try {
316
+ // Open a DB then drop quality_gates so getPendingGatesForTurn throws inside
317
+ // the gate-evaluate DB branch → :411 warning. (getGateIdsForTurn returns
318
+ // default gate-evaluate ids, so the query path is reached.)
319
+ openDatabase(join(base, ".gsd", "gsd.db"));
320
+ _getAdapter()!.exec("DROP TABLE quality_gates");
321
+
322
+ const previous = setStderrLoggingEnabled(false);
323
+ _resetLogs();
324
+ let result: boolean;
325
+ try {
326
+ // Batch unitId "M001/S01/gates+Q3" encodes one dispatched gate.
327
+ result = verifyExpectedArtifact("gate-evaluate", "M001/S01/gates+Q3", base);
328
+ const logs = drainLogs();
329
+ const recovery = logs.find((e) => e.component === "recovery" && /gate-evaluate DB check failed/u.test(e.message));
330
+ assert.ok(recovery, "a recovery warning must be logged when the gate DB check throws");
331
+ assert.match(recovery!.message, /gate-evaluate DB check failed/u);
332
+ } finally {
333
+ _resetLogs();
334
+ setStderrLoggingEnabled(previous);
335
+ }
336
+ // Per :411 comment, a DB failure is treated as verified (return true) to
337
+ // avoid blocking the loop — pin that resilience contract too.
338
+ assert.equal(result, true, "a gate-evaluate DB failure must not block verification");
339
+ } finally {
340
+ closeDatabase();
341
+ rmSync(base, { recursive: true, force: true });
342
+ }
343
+ });
344
+
345
+ // ─── roadmap-parse-threw catches (:515 plan-milestone, :622 complete-slice) ─
346
+ // parseLegacyRoadmap is internally defensive against every malformed input, so
347
+ // these catches are unreachable without the _setRoadmapParserFnForTests seam.
348
+ // We inject a throwing parser to pin both best-effort failure logs.
349
+
350
+ test("plan-milestone verify logs a recovery warning when the roadmap parser throws (auto-recovery.ts:515)", () => {
351
+ const base = createFixtureBase("gsd-recovery-logs-parse-");
352
+ const restore = _setRoadmapParserFnForTests(() => {
353
+ throw new Error("forced roadmap parse failure");
354
+ });
355
+ try {
356
+ const dir = milestoneDir(base, "M001");
357
+ // A real ROADMAP file must exist so verification reaches the parser.
358
+ writeFileSync(join(dir, "M001-ROADMAP.md"), "# M001: x\n\n## Slices\n\n- [ ] **S01: A**\n", "utf-8");
359
+
360
+ const { result, logs } = verifyAndCaptureLogs("plan-milestone", "M001", base);
361
+
362
+ assert.equal(result, false, "a parser failure must fail plan-milestone verification");
363
+ const recovery = findRecovery(logs);
364
+ assert.ok(recovery, "a recovery warning must be logged");
365
+ assert.match(recovery!.message, /plan-milestone roadmap verification failed/u);
366
+ assert.match(recovery!.message, /forced roadmap parse failure/u);
367
+ } finally {
368
+ restore();
369
+ rmSync(base, { recursive: true, force: true });
370
+ }
371
+ });
372
+
373
+ test("complete-slice verify logs a recovery warning when the legacy roadmap parse fails (auto-recovery.ts:622)", () => {
374
+ const base = createFixtureBase("gsd-recovery-logs-cs-parse-");
375
+ const restore = _setRoadmapParserFnForTests(() => {
376
+ throw new Error("forced legacy roadmap parse failure");
377
+ });
378
+ try {
379
+ const dir = sliceDir(base, "M001", "S01");
380
+ // complete-slice verification: SUMMARY + UAT present, DB unavailable →
381
+ // legacy roadmap checkbox fallback → parser throws → :622 warning.
382
+ writeFileSync(join(dir, "S01-SUMMARY.md"), "# S01 done\n", "utf-8");
383
+ // UAT file required so the complete-slice guard (auto-recovery.ts:655) does
384
+ // not return false before reaching the legacy roadmap fallback.
385
+ writeFileSync(join(dir, "S01-UAT.md"), "# UAT\n", "utf-8");
386
+ // Legacy ROADMAP.md (unprefixed) under the milestone dir.
387
+ writeFileSync(join(base, ".gsd", "milestones", "M001", "ROADMAP.md"), "# M001\n\n## Slices\n\n- [ ] **S01: A**\n", "utf-8");
388
+
389
+ const { result, logs } = verifyAndCaptureLogs("complete-slice", "M001/S01", base);
390
+
391
+ assert.equal(result, false, "a parser failure must fail complete-slice verification");
392
+ const recovery = logs.find((e) => e.component === "recovery" && /roadmap parse failed/u.test(e.message));
393
+ assert.ok(recovery, "a recovery warning must be logged");
394
+ assert.match(recovery!.message, /roadmap parse failed/u);
395
+ assert.match(recovery!.message, /forced legacy roadmap parse failure/u);
396
+ } finally {
397
+ restore();
398
+ rmSync(base, { recursive: true, force: true });
399
+ }
400
+ });
401
+
402
+ test("parallel-research verify logs a recovery warning when the roadmap parse throws (auto-recovery.ts:522)", () => {
403
+ const base = createFixtureBase("gsd-recovery-logs-prr-throw-");
404
+ const restore = _setRoadmapParserFnForTests(() => {
405
+ throw new Error("forced parallel-research parse failure");
406
+ });
407
+ try {
408
+ const dir = milestoneDir(base, "M001");
409
+ // A real ROADMAP with a research-ready slice so verification reaches the
410
+ // parser loop; the seam makes parseRoadmapForRecovery throw → :522 catch.
411
+ writeFileSync(
412
+ join(dir, "M001-ROADMAP.md"),
413
+ ["# M001: Roadmap", "", "## Slices", "", "- [ ] **S01: First** `risk:low` `depends:[]`", ""].join("\n"),
414
+ "utf-8",
415
+ );
416
+
417
+ const { result, logs } = verifyAndCaptureLogs("research-slice", "M001/parallel-research", base);
418
+
419
+ assert.equal(result, false, "a parser failure must fail parallel-research verification");
420
+ const recovery = logs.find((e) => e.component === "recovery" && /parallel-research verification failed/u.test(e.message));
421
+ assert.ok(recovery, "a recovery warning must be logged");
422
+ assert.match(recovery!.message, /parallel-research verification failed/u);
423
+ assert.match(recovery!.message, /forced parallel-research parse failure/u);
424
+ } finally {
425
+ restore();
426
+ rmSync(base, { recursive: true, force: true });
427
+ }
428
+ });
@@ -52,6 +52,31 @@ test("handleRecoverableExtensionProcessError swallows uv_cwd ENOENT", () => {
52
52
  }
53
53
  });
54
54
 
55
+ test("handleRecoverableExtensionProcessError suppresses uv_cwd stderr in TUI mode", async () => {
56
+ const { setStderrLoggingEnabled } = await import("../workflow-logger.ts");
57
+ let stderr = "";
58
+ const originalWrite = process.stderr.write.bind(process.stderr);
59
+ process.stderr.write = ((chunk: string | Uint8Array) => {
60
+ stderr += String(chunk);
61
+ return true;
62
+ }) as typeof process.stderr.write;
63
+ const previous = setStderrLoggingEnabled(false);
64
+
65
+ try {
66
+ const handled = handleRecoverableExtensionProcessError(
67
+ Object.assign(new Error("process.cwd failed"), {
68
+ code: "ENOENT",
69
+ syscall: "uv_cwd",
70
+ }),
71
+ );
72
+ assert.equal(handled, true);
73
+ assert.equal(stderr, "");
74
+ } finally {
75
+ setStderrLoggingEnabled(previous);
76
+ process.stderr.write = originalWrite;
77
+ }
78
+ });
79
+
55
80
  test("handleRecoverableExtensionProcessError swallows read EIO", () => {
56
81
  let stderr = "";
57
82
  const originalWrite = process.stderr.write.bind(process.stderr);
@@ -5,103 +5,53 @@
5
5
  * as a fire-and-forget side-effect so that Telegram/Slack/Discord channels
6
6
  * receive the same events as native desktop notifications.
7
7
  *
8
- * Testing strategy (structural analysis):
9
- * node:test does not support mock.module without --experimental-test-module-mocks,
10
- * so we use the same source-code structural approach established in this codebase
11
- * (see session-start-footer.test.ts). We read notifications.ts and assert that:
12
- * 1. It imports sendRemoteNotification from the remote-questions/notify module.
13
- * 2. The sendDesktopNotification function body calls sendRemoteNotification
14
- * with title and message as arguments.
15
- * 3. The call uses the void fire-and-forget pattern with a .catch(() => {})
16
- * suppressor so that async failures never break the synchronous caller.
8
+ * Testing strategy (behavioral):
9
+ * Import sendDesktopNotification and the swappable remoteNotificationDispatcher.
10
+ * Mock the dispatcher's send method, call sendDesktopNotification, and assert
11
+ * that the dispatcher received the same title/message and that the call is
12
+ * fire-and-forget (the function returns without awaiting).
17
13
  *
18
14
  * Relates to #4341.
19
15
  */
20
16
 
21
17
  import test from "node:test";
22
18
  import assert from "node:assert/strict";
23
- import { readFileSync } from "node:fs";
24
- import { join, dirname } from "node:path";
25
- import { fileURLToPath } from "node:url";
26
19
 
27
- const __dirname = dirname(fileURLToPath(import.meta.url));
28
- const SOURCE = readFileSync(join(__dirname, "..", "notifications.ts"), "utf-8");
20
+ import {
21
+ sendDesktopNotification,
22
+ remoteNotificationDispatcher,
23
+ } from "../notifications.js";
29
24
 
30
- test("notifications.ts imports sendRemoteNotification from remote-questions/notify", () => {
31
- const hasImport =
32
- SOURCE.includes('from "../remote-questions/notify.js"') ||
33
- SOURCE.includes("from '../remote-questions/notify.js'");
34
- assert.ok(
35
- hasImport,
36
- "notifications.ts must import from '../remote-questions/notify.js'",
37
- );
38
-
39
- const importLine = SOURCE.split("\n").find(
40
- (line) =>
41
- line.includes("sendRemoteNotification") &&
42
- (line.includes("remote-questions/notify") || line.includes("remote-questions/notify.js")),
43
- );
44
- assert.ok(
45
- importLine,
46
- "The import statement must include sendRemoteNotification from the remote-questions/notify module",
47
- );
48
- });
49
-
50
- test("sendDesktopNotification calls sendRemoteNotification(title, message)", () => {
51
- // Extract the body of sendDesktopNotification — from its opening brace to the
52
- // closing brace at the same indentation level.
53
- const fnStart = SOURCE.indexOf("export function sendDesktopNotification(");
54
- assert.ok(fnStart > -1, "sendDesktopNotification must be present in notifications.ts");
25
+ test("sendDesktopNotification calls sendRemoteNotification with title and message", async (t) => {
26
+ const sendMock = t.mock.method(remoteNotificationDispatcher, "send", async () => {});
55
27
 
56
- // Find the next exported function/const after sendDesktopNotification to bound the search.
57
- const nextExportIdx = SOURCE.indexOf("\nexport ", fnStart + 1);
58
- const fnBody = nextExportIdx > -1 ? SOURCE.slice(fnStart, nextExportIdx) : SOURCE.slice(fnStart);
59
-
60
- assert.ok(
61
- fnBody.includes("sendRemoteNotification"),
62
- "sendDesktopNotification must call sendRemoteNotification",
63
- );
28
+ sendDesktopNotification("Test Title", "Test Message");
64
29
 
65
- assert.ok(
66
- fnBody.includes("sendRemoteNotification(title") || fnBody.includes("sendRemoteNotification(title,"),
67
- "sendRemoteNotification must be called with title as first argument",
68
- );
30
+ assert.equal(sendMock.mock.callCount(), 1);
31
+ assert.deepEqual(sendMock.mock.calls[0].arguments, ["Test Title", "Test Message"]);
69
32
  });
70
33
 
71
- test("sendRemoteNotification is invoked as void fire-and-forget with .catch(() => {})", () => {
72
- const fnStart = SOURCE.indexOf("export function sendDesktopNotification(");
73
- const nextExportIdx = SOURCE.indexOf("\nexport ", fnStart + 1);
74
- const fnBody = nextExportIdx > -1 ? SOURCE.slice(fnStart, nextExportIdx) : SOURCE.slice(fnStart);
34
+ test("sendDesktopNotification does not await the remote notification", async (t) => {
35
+ const sendMock = t.mock.method(remoteNotificationDispatcher, "send", async () => {});
75
36
 
76
- assert.ok(
77
- fnBody.includes("void sendRemoteNotification("),
78
- "sendRemoteNotification must be called with void (fire-and-forget)",
79
- );
37
+ const result = sendDesktopNotification("Async Title", "Async Message");
80
38
 
81
- assert.ok(
82
- fnBody.includes(".catch("),
83
- "sendRemoteNotification call must be followed by .catch() to suppress unhandled-rejection warnings",
84
- );
39
+ assert.equal(result, undefined, "sendDesktopNotification must return void");
40
+ assert.equal(sendMock.mock.callCount(), 1);
85
41
  });
86
42
 
87
- test("sendRemoteNotification call appears before shouldSendDesktopNotification guard", () => {
88
- // Regression guard for the HIGH-severity bug where remote notifications were
89
- // gated behind the desktop-notification preference check. Users who disable
90
- // desktop notifications must still receive Telegram/Slack/Discord messages.
91
- const fnStart = SOURCE.indexOf("export function sendDesktopNotification(");
92
- assert.ok(fnStart > -1, "sendDesktopNotification must be present in notifications.ts");
93
-
94
- const nextExportIdx = SOURCE.indexOf("\nexport ", fnStart + 1);
95
- const fnBody = nextExportIdx > -1 ? SOURCE.slice(fnStart, nextExportIdx) : SOURCE.slice(fnStart);
43
+ test("sendDesktopNotification fires remote notification even when desktop notifications are disabled", async (t) => {
44
+ const sendMock = t.mock.method(remoteNotificationDispatcher, "send", async () => {});
96
45
 
97
- const remoteCallIdx = fnBody.indexOf("sendRemoteNotification(");
98
- const guardIdx = fnBody.indexOf("shouldSendDesktopNotification(");
99
-
100
- assert.ok(remoteCallIdx > -1, "sendRemoteNotification must be called inside sendDesktopNotification");
101
- assert.ok(guardIdx > -1, "shouldSendDesktopNotification guard must be present inside sendDesktopNotification");
102
-
103
- assert.ok(
104
- remoteCallIdx < guardIdx,
105
- `sendRemoteNotification (pos ${remoteCallIdx}) must appear BEFORE the shouldSendDesktopNotification guard (pos ${guardIdx}) so that remote channels fire even when desktop notifications are disabled`,
46
+ sendDesktopNotification(
47
+ "Remote Title",
48
+ "Remote Message",
49
+ "info",
50
+ "complete",
51
+ undefined,
52
+ { notifications: { enabled: false } },
106
53
  );
54
+
55
+ assert.equal(sendMock.mock.callCount(), 1);
56
+ assert.deepEqual(sendMock.mock.calls[0].arguments, ["Remote Title", "Remote Message"]);
107
57
  });
@@ -114,19 +114,19 @@ describe("resume: missing worktree warning emission", () => {
114
114
  assert.equal(peekLogs().length, 0);
115
115
  });
116
116
 
117
- test("warning message mentions project-root fallback action", () => {
117
+ test("warning message mentions project-root fallback and worktree recreation", () => {
118
118
  const missingPath = join(projectDir, ".gsd", "worktrees", "M099-deleted");
119
119
  _warnIfWorktreeMissingForTest(missingPath, "M099");
120
120
 
121
121
  const logs = peekLogs();
122
122
  assert.equal(logs.length, 1);
123
123
  assert.ok(
124
- logs[0].message.includes("project-root mode"),
125
- "warning should mention project-root mode fallback",
124
+ logs[0].message.includes("project root"),
125
+ "warning should mention project-root fallback",
126
126
  );
127
127
  assert.ok(
128
- logs[0].message.includes("gsd-debug"),
129
- "warning should suggest /gsd-debug recovery action",
128
+ logs[0].message.includes("/gsd next"),
129
+ "warning should suggest /gsd next to recreate the worktree",
130
130
  );
131
131
  });
132
132
  });
@@ -67,7 +67,13 @@ test("Tool Contract compiles known Unit prompt and tool policy", () => {
67
67
 
68
68
  assert.equal(result.ok, true);
69
69
  assert.equal(result.ok && result.contract.unitType, "execute-task");
70
- assert.deepEqual(result.ok && result.contract.requiredWorkflowTools, ["gsd_task_complete"]);
70
+ assert.deepEqual(result.ok && result.contract.requiredWorkflowTools, [
71
+ "gsd_task_complete",
72
+ "gsd_exec",
73
+ "gsd_exec_search",
74
+ "gsd_resume",
75
+ "gsd_capture_thought",
76
+ ]);
71
77
  assert.deepEqual(result.ok && result.contract.forbiddenWorkflowTools, []);
72
78
  assert.equal(result.ok && result.contract.toolsPolicy.mode, "all");
73
79
  assert.ok(result.ok && result.contract.validationRules.includes("closeout-tool-present"));