@opengsd/gsd-pi 1.2.0-dev.5457a158 → 1.2.0-dev.822c9439

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 (489) hide show
  1. package/dist/headless-events.js +7 -5
  2. package/dist/mcp-server.js +2 -1
  3. package/dist/resource-loader.d.ts +9 -5
  4. package/dist/resource-loader.js +114 -6
  5. package/dist/resources/.managed-resources-content-hash +1 -1
  6. package/dist/resources/GSD-WORKFLOW.md +5 -4
  7. package/dist/resources/extensions/async-jobs/async-bash-tool.js +30 -64
  8. package/dist/resources/extensions/async-jobs/await-tool.js +80 -12
  9. package/dist/resources/extensions/async-jobs/index.js +65 -0
  10. package/dist/resources/extensions/async-jobs/job-manager.js +12 -1
  11. package/dist/resources/extensions/bg-shell/bg-shell-command.js +6 -6
  12. package/dist/resources/extensions/bg-shell/bg-shell-tool.js +10 -7
  13. package/dist/resources/extensions/bg-shell/overlay.js +9 -6
  14. package/dist/resources/extensions/bg-shell/process-manager.js +54 -25
  15. package/dist/resources/extensions/bg-shell/readiness-detector.js +11 -0
  16. package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +209 -88
  17. package/dist/resources/extensions/browser-tools/engine/selection.js +73 -5
  18. package/dist/resources/extensions/browser-tools/index.js +69 -12
  19. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +3 -2
  20. package/dist/resources/extensions/gsd/auto/custom-verify-retry-store.js +17 -2
  21. package/dist/resources/extensions/gsd/auto/detect-stuck.js +33 -13
  22. package/dist/resources/extensions/gsd/auto/dispatch-history.js +105 -0
  23. package/dist/resources/extensions/gsd/auto/dispatch-key.js +37 -0
  24. package/dist/resources/extensions/gsd/auto/loop.js +4 -1
  25. package/dist/resources/extensions/gsd/auto/orchestrator.js +89 -54
  26. package/dist/resources/extensions/gsd/auto/phases.js +49 -6
  27. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  28. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +11 -34
  29. package/dist/resources/extensions/gsd/auto-dispatch.js +50 -58
  30. package/dist/resources/extensions/gsd/auto-model-selection.js +36 -13
  31. package/dist/resources/extensions/gsd/auto-post-unit.js +30 -12
  32. package/dist/resources/extensions/gsd/auto-prompts.js +78 -19
  33. package/dist/resources/extensions/gsd/auto-start.js +12 -12
  34. package/dist/resources/extensions/gsd/auto-unit-closeout.js +45 -21
  35. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +5 -4
  36. package/dist/resources/extensions/gsd/auto-verification.js +23 -30
  37. package/dist/resources/extensions/gsd/auto-worktree.js +14 -1
  38. package/dist/resources/extensions/gsd/auto.js +37 -1
  39. package/dist/resources/extensions/gsd/blocked-models.js +28 -0
  40. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +26 -6
  41. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +23 -6
  42. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -2
  43. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +19 -0
  44. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +172 -59
  45. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +302 -80
  46. package/dist/resources/extensions/gsd/browser-daemon-auto-prep.js +83 -0
  47. package/dist/resources/extensions/gsd/browser-evidence.js +8 -2
  48. package/dist/resources/extensions/gsd/closeout-wizard.js +92 -0
  49. package/dist/resources/extensions/gsd/commands/context.js +16 -2
  50. package/dist/resources/extensions/gsd/commands-handlers.js +46 -3
  51. package/dist/resources/extensions/gsd/consent-question.js +353 -0
  52. package/dist/resources/extensions/gsd/consent-verdict.js +63 -0
  53. package/dist/resources/extensions/gsd/constants.js +0 -2
  54. package/dist/resources/extensions/gsd/crash-recovery.js +8 -3
  55. package/dist/resources/extensions/gsd/db/queries.js +26 -0
  56. package/dist/resources/extensions/gsd/dispatch-guard.js +10 -35
  57. package/dist/resources/extensions/gsd/doctor-engine-checks.js +5 -5
  58. package/dist/resources/extensions/gsd/doctor-git-checks.js +2 -18
  59. package/dist/resources/extensions/gsd/engine-hook-contract.js +70 -0
  60. package/dist/resources/extensions/gsd/exec-sandbox.js +30 -10
  61. package/dist/resources/extensions/gsd/files.js +33 -19
  62. package/dist/resources/extensions/gsd/gsd-command-home.js +22 -12
  63. package/dist/resources/extensions/gsd/gsd-db.js +2 -1
  64. package/dist/resources/extensions/gsd/guidance.js +60 -0
  65. package/dist/resources/extensions/gsd/guided-flow.js +6 -3
  66. package/dist/resources/extensions/gsd/markdown-renderer.js +10 -0
  67. package/dist/resources/extensions/gsd/mcp-filter.js +2 -19
  68. package/dist/resources/extensions/gsd/milestone-closeout.js +85 -24
  69. package/dist/resources/extensions/gsd/milestone-planning-persistence.js +2 -2
  70. package/dist/resources/extensions/gsd/milestone-reopen-events.js +3 -5
  71. package/dist/resources/extensions/gsd/parsers-legacy.js +16 -4
  72. package/dist/resources/extensions/gsd/preferences-models.js +2 -2
  73. package/dist/resources/extensions/gsd/projection-flush.js +7 -0
  74. package/dist/resources/extensions/gsd/prompts/complete-slice.md +3 -3
  75. package/dist/resources/extensions/gsd/prompts/execute-task.md +1 -1
  76. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  77. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  78. package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -1
  79. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  80. package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  81. package/dist/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  82. package/dist/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  83. package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
  84. package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  85. package/dist/resources/extensions/gsd/prompts/run-uat.md +7 -5
  86. package/dist/resources/extensions/gsd/prompts/system.md +5 -2
  87. package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -1
  88. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
  89. package/dist/resources/extensions/gsd/reactive-graph.js +8 -1
  90. package/dist/resources/extensions/gsd/roadmap-slices.js +25 -3
  91. package/dist/resources/extensions/gsd/safety/destructive-confirmation.js +108 -0
  92. package/dist/resources/extensions/gsd/session-lock.js +1 -1
  93. package/dist/resources/extensions/gsd/state.js +5 -0
  94. package/dist/resources/extensions/gsd/tool-contract.js +14 -3
  95. package/dist/resources/extensions/gsd/tool-presentation-plan.js +4 -4
  96. package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -2
  97. package/dist/resources/extensions/gsd/tools/complete-slice.js +22 -12
  98. package/dist/resources/extensions/gsd/tools/complete-task.js +3 -2
  99. package/dist/resources/extensions/gsd/tools/exec-tool.js +5 -0
  100. package/dist/resources/extensions/gsd/tools/plan-slice.js +2 -2
  101. package/dist/resources/extensions/gsd/tools/plan-task.js +2 -2
  102. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +2 -2
  103. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +2 -2
  104. package/dist/resources/extensions/gsd/tools/reopen-slice.js +2 -2
  105. package/dist/resources/extensions/gsd/tools/reopen-task.js +2 -2
  106. package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -2
  107. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +67 -2
  108. package/dist/resources/extensions/gsd/uat-policy.js +42 -16
  109. package/dist/resources/extensions/gsd/unit-context-composer.js +65 -0
  110. package/dist/resources/extensions/gsd/unit-registry.js +7 -20
  111. package/dist/resources/extensions/gsd/verdict-parser.js +1 -1
  112. package/dist/resources/extensions/gsd/verification-verdict.js +2 -1
  113. package/dist/resources/extensions/gsd/web-app-uat.js +45 -8
  114. package/dist/resources/extensions/gsd/workflow-event-ledger.js +91 -0
  115. package/dist/resources/extensions/gsd/workflow-event-vocabulary.js +46 -0
  116. package/dist/resources/extensions/gsd/workflow-events.js +6 -18
  117. package/dist/resources/extensions/gsd/workflow-reconcile.js +21 -56
  118. package/dist/resources/extensions/gsd/worktree-lifecycle.js +3 -2
  119. package/dist/resources/extensions/gsd/worktree-manager.js +7 -1
  120. package/dist/resources/extensions/gsd/worktree.js +8 -1
  121. package/dist/resources/extensions/search-the-web/native-search.js +5 -3
  122. package/dist/resources/extensions/shared/browser-contract.js +59 -0
  123. package/dist/resources/extensions/shared/gsd-browser-cli.js +116 -6
  124. package/dist/resources/shared/gsd-browser-path-sync.js +214 -0
  125. package/dist/resources/shared/package-manager-detection.js +1 -1
  126. package/dist/resources/shared/package.json +3 -0
  127. package/dist/resources/skills/create-skill/SKILL.md +3 -0
  128. package/dist/resources/skills/create-skill/references/executable-code.md +1 -1
  129. package/dist/resources/skills/create-skill/references/skill-structure.md +1 -0
  130. package/dist/resources/skills/create-skill/workflows/add-reference.md +8 -3
  131. package/dist/resources/skills/create-skill/workflows/add-script.md +4 -2
  132. package/dist/resources/skills/create-skill/workflows/add-template.md +3 -1
  133. package/dist/resources/skills/create-skill/workflows/add-workflow.md +8 -3
  134. package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
  135. package/dist/resources/skills/create-skill/workflows/verify-skill.md +9 -4
  136. package/dist/resources/skills/spike-wrap-up/SKILL.md +9 -9
  137. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  138. package/dist/update-check.d.ts +2 -0
  139. package/dist/update-check.js +24 -1
  140. package/dist/update-cmd.js +20 -3
  141. package/dist/web/standalone/.next/BUILD_ID +1 -1
  142. package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
  143. package/dist/web/standalone/.next/build-manifest.json +3 -3
  144. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  145. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  146. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  147. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  148. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  149. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  150. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  151. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  152. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  153. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  154. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  155. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  156. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  157. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  158. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  159. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  160. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  161. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  162. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/update/route.js.nft.json +1 -1
  164. package/dist/web/standalone/.next/server/app/index.html +1 -1
  165. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  166. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  167. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  168. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  169. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  170. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  171. package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
  172. package/dist/web/standalone/.next/server/chunks/8357.js +2 -2
  173. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  174. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  176. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  177. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  178. package/dist/web/standalone/.next/static/chunks/{796.cf859a427a2cb2ac.js → 796.e0bdc932325d7e03.js} +1 -1
  179. package/dist/web/standalone/.next/static/chunks/{webpack-fbea77b5f9953368.js → webpack-f0285ce91d4ec9ef.js} +1 -1
  180. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  181. package/dist/web/standalone/package.json +1 -1
  182. package/package.json +1 -1
  183. package/packages/cloud-mcp-gateway/package.json +2 -2
  184. package/packages/contracts/dist/rpc.d.ts +1 -0
  185. package/packages/contracts/dist/rpc.d.ts.map +1 -1
  186. package/packages/contracts/dist/rpc.js.map +1 -1
  187. package/packages/contracts/package.json +1 -1
  188. package/packages/daemon/package.json +4 -4
  189. package/packages/gsd-agent-core/package.json +5 -5
  190. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +5 -0
  191. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  192. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +5 -0
  193. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  194. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  195. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +7 -0
  196. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  197. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  198. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +8 -1
  199. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  200. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.d.ts.map +1 -1
  201. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js +11 -1
  202. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js.map +1 -1
  203. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
  204. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +4 -4
  205. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
  206. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  207. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +3 -1
  208. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
  209. package/packages/gsd-agent-modes/package.json +7 -7
  210. package/packages/mcp-server/dist/cli.js +10 -5
  211. package/packages/mcp-server/dist/cli.js.map +1 -1
  212. package/packages/mcp-server/dist/moonshot-tool-schema.d.ts +29 -0
  213. package/packages/mcp-server/dist/moonshot-tool-schema.d.ts.map +1 -0
  214. package/packages/mcp-server/dist/moonshot-tool-schema.js +50 -0
  215. package/packages/mcp-server/dist/moonshot-tool-schema.js.map +1 -0
  216. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  217. package/packages/mcp-server/dist/server.js +4 -0
  218. package/packages/mcp-server/dist/server.js.map +1 -1
  219. package/packages/mcp-server/dist/workflow-tools.d.ts +18 -18
  220. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  221. package/packages/mcp-server/dist/workflow-tools.js +99 -38
  222. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  223. package/packages/mcp-server/package.json +5 -4
  224. package/packages/native/package.json +1 -1
  225. package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts +1 -0
  226. package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts.map +1 -1
  227. package/packages/pi-agent-core/dist/harness/env/nodejs.js +34 -3
  228. package/packages/pi-agent-core/dist/harness/env/nodejs.js.map +1 -1
  229. package/packages/pi-agent-core/dist/index.d.ts +1 -0
  230. package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
  231. package/packages/pi-agent-core/dist/index.js +3 -0
  232. package/packages/pi-agent-core/dist/index.js.map +1 -1
  233. package/packages/pi-agent-core/package.json +1 -1
  234. package/packages/pi-ai/README.md +1 -0
  235. package/packages/pi-ai/dist/image-models.generated.d.ts +2 -2
  236. package/packages/pi-ai/dist/image-models.generated.js +6 -6
  237. package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
  238. package/packages/pi-ai/dist/index.d.ts +2 -0
  239. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  240. package/packages/pi-ai/dist/index.js +2 -0
  241. package/packages/pi-ai/dist/index.js.map +1 -1
  242. package/packages/pi-ai/dist/models.generated.d.ts +239 -153
  243. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  244. package/packages/pi-ai/dist/models.generated.js +256 -145
  245. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  246. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  247. package/packages/pi-ai/dist/providers/anthropic.js +12 -7
  248. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  249. package/packages/pi-ai/dist/providers/google-shared.d.ts +5 -0
  250. package/packages/pi-ai/dist/providers/google-shared.d.ts.map +1 -1
  251. package/packages/pi-ai/dist/providers/google-shared.js +12 -3
  252. package/packages/pi-ai/dist/providers/google-shared.js.map +1 -1
  253. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  254. package/packages/pi-ai/dist/providers/openai-completions.js +7 -3
  255. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  256. package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts +9 -0
  257. package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts.map +1 -0
  258. package/packages/pi-ai/dist/utils/moonshot-tool-schema.js +34 -0
  259. package/packages/pi-ai/dist/utils/moonshot-tool-schema.js.map +1 -0
  260. package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
  261. package/packages/pi-ai/dist/utils/oauth/github-copilot.js +6 -2
  262. package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
  263. package/packages/pi-ai/package.json +3 -2
  264. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +2 -2
  265. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  266. package/packages/pi-coding-agent/dist/core/auth-storage.js +19 -13
  267. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  268. package/packages/pi-coding-agent/dist/core/provider-readiness.d.ts.map +1 -1
  269. package/packages/pi-coding-agent/dist/core/provider-readiness.js +13 -6
  270. package/packages/pi-coding-agent/dist/core/provider-readiness.js.map +1 -1
  271. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts +11 -0
  272. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
  273. package/packages/pi-coding-agent/dist/core/tools/bash.js +53 -11
  274. package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
  275. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  276. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  277. package/packages/pi-coding-agent/dist/index.js +1 -1
  278. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  279. package/packages/pi-coding-agent/dist/utils/shell.d.ts +28 -2
  280. package/packages/pi-coding-agent/dist/utils/shell.d.ts.map +1 -1
  281. package/packages/pi-coding-agent/dist/utils/shell.js +56 -10
  282. package/packages/pi-coding-agent/dist/utils/shell.js.map +1 -1
  283. package/packages/pi-coding-agent/package.json +7 -7
  284. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  285. package/packages/pi-tui/dist/tui.js +9 -0
  286. package/packages/pi-tui/dist/tui.js.map +1 -1
  287. package/packages/pi-tui/package.json +2 -2
  288. package/packages/rpc-client/package.json +2 -2
  289. package/pkg/package.json +1 -1
  290. package/src/resources/GSD-WORKFLOW.md +5 -4
  291. package/src/resources/extensions/async-jobs/async-bash-cancel.test.ts +360 -0
  292. package/src/resources/extensions/async-jobs/async-bash-tool.ts +33 -56
  293. package/src/resources/extensions/async-jobs/await-tool.test.ts +139 -0
  294. package/src/resources/extensions/async-jobs/await-tool.ts +82 -12
  295. package/src/resources/extensions/async-jobs/index.ts +79 -0
  296. package/src/resources/extensions/async-jobs/job-manager.ts +21 -1
  297. package/src/resources/extensions/bg-shell/bg-shell-command.ts +6 -6
  298. package/src/resources/extensions/bg-shell/bg-shell-tool.ts +10 -6
  299. package/src/resources/extensions/bg-shell/overlay.ts +9 -5
  300. package/src/resources/extensions/bg-shell/process-manager.ts +50 -25
  301. package/src/resources/extensions/bg-shell/readiness-detector.ts +12 -0
  302. package/src/resources/extensions/bg-shell/tests/lifecycle-and-utilities.test.ts +48 -1
  303. package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +265 -98
  304. package/src/resources/extensions/browser-tools/engine/selection.ts +90 -4
  305. package/src/resources/extensions/browser-tools/index.ts +71 -13
  306. package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +83 -13
  307. package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +40 -1
  308. package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +136 -0
  309. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +3 -2
  310. package/src/resources/extensions/gsd/auto/custom-verify-retry-store.ts +21 -3
  311. package/src/resources/extensions/gsd/auto/detect-stuck.ts +32 -9
  312. package/src/resources/extensions/gsd/auto/dispatch-history.ts +152 -0
  313. package/src/resources/extensions/gsd/auto/dispatch-key.ts +39 -0
  314. package/src/resources/extensions/gsd/auto/loop.ts +4 -1
  315. package/src/resources/extensions/gsd/auto/orchestrator.ts +98 -56
  316. package/src/resources/extensions/gsd/auto/phases.ts +65 -26
  317. package/src/resources/extensions/gsd/auto/session.ts +3 -0
  318. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +18 -48
  319. package/src/resources/extensions/gsd/auto-dispatch.ts +48 -61
  320. package/src/resources/extensions/gsd/auto-model-selection.ts +41 -12
  321. package/src/resources/extensions/gsd/auto-post-unit.ts +33 -12
  322. package/src/resources/extensions/gsd/auto-prompts.ts +115 -35
  323. package/src/resources/extensions/gsd/auto-start.ts +12 -14
  324. package/src/resources/extensions/gsd/auto-unit-closeout.ts +83 -28
  325. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +4 -4
  326. package/src/resources/extensions/gsd/auto-verification.ts +26 -28
  327. package/src/resources/extensions/gsd/auto-worktree.ts +14 -1
  328. package/src/resources/extensions/gsd/auto.ts +44 -1
  329. package/src/resources/extensions/gsd/blocked-models.ts +49 -0
  330. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +34 -5
  331. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +23 -6
  332. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -2
  333. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +24 -0
  334. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +211 -59
  335. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +350 -86
  336. package/src/resources/extensions/gsd/browser-daemon-auto-prep.ts +108 -0
  337. package/src/resources/extensions/gsd/browser-evidence.ts +18 -2
  338. package/src/resources/extensions/gsd/closeout-wizard.ts +102 -0
  339. package/src/resources/extensions/gsd/commands/context.ts +16 -2
  340. package/src/resources/extensions/gsd/commands-handlers.ts +46 -3
  341. package/src/resources/extensions/gsd/consent-question.ts +431 -0
  342. package/src/resources/extensions/gsd/consent-verdict.ts +86 -0
  343. package/src/resources/extensions/gsd/constants.ts +0 -3
  344. package/src/resources/extensions/gsd/crash-recovery.ts +10 -2
  345. package/src/resources/extensions/gsd/db/queries.ts +37 -0
  346. package/src/resources/extensions/gsd/dispatch-guard.ts +8 -31
  347. package/src/resources/extensions/gsd/doctor-engine-checks.ts +5 -4
  348. package/src/resources/extensions/gsd/doctor-git-checks.ts +2 -19
  349. package/src/resources/extensions/gsd/engine-hook-contract.ts +79 -0
  350. package/src/resources/extensions/gsd/exec-sandbox.ts +49 -9
  351. package/src/resources/extensions/gsd/files.ts +33 -12
  352. package/src/resources/extensions/gsd/gsd-command-home.ts +13 -3
  353. package/src/resources/extensions/gsd/gsd-db.ts +4 -3
  354. package/src/resources/extensions/gsd/guidance.ts +78 -0
  355. package/src/resources/extensions/gsd/guided-flow.ts +21 -26
  356. package/src/resources/extensions/gsd/markdown-renderer.ts +11 -0
  357. package/src/resources/extensions/gsd/mcp-filter.ts +2 -23
  358. package/src/resources/extensions/gsd/milestone-closeout.ts +109 -24
  359. package/src/resources/extensions/gsd/milestone-planning-persistence.ts +2 -2
  360. package/src/resources/extensions/gsd/milestone-reopen-events.ts +3 -6
  361. package/src/resources/extensions/gsd/parsers-legacy.ts +16 -4
  362. package/src/resources/extensions/gsd/preferences-models.ts +2 -1
  363. package/src/resources/extensions/gsd/projection-flush.ts +20 -0
  364. package/src/resources/extensions/gsd/prompts/complete-slice.md +3 -3
  365. package/src/resources/extensions/gsd/prompts/execute-task.md +1 -1
  366. package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  367. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  368. package/src/resources/extensions/gsd/prompts/quick-task.md +1 -1
  369. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  370. package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  371. package/src/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  372. package/src/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  373. package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
  374. package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  375. package/src/resources/extensions/gsd/prompts/run-uat.md +7 -5
  376. package/src/resources/extensions/gsd/prompts/system.md +5 -2
  377. package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -1
  378. package/src/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
  379. package/src/resources/extensions/gsd/reactive-graph.ts +11 -1
  380. package/src/resources/extensions/gsd/roadmap-slices.ts +28 -3
  381. package/src/resources/extensions/gsd/safety/destructive-confirmation.ts +134 -0
  382. package/src/resources/extensions/gsd/session-lock.ts +1 -1
  383. package/src/resources/extensions/gsd/state.ts +5 -0
  384. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +97 -1
  385. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +198 -26
  386. package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +65 -3
  387. package/src/resources/extensions/gsd/tests/blocked-models.test.ts +19 -0
  388. package/src/resources/extensions/gsd/tests/browser-automation-contract-fixture.ts +39 -0
  389. package/src/resources/extensions/gsd/tests/browser-contract.test.ts +44 -0
  390. package/src/resources/extensions/gsd/tests/browser-daemon-auto-prep.test.ts +144 -0
  391. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
  392. package/src/resources/extensions/gsd/tests/consent-question.test.ts +351 -0
  393. package/src/resources/extensions/gsd/tests/custom-verify-retry-store.test.ts +67 -0
  394. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +10 -10
  395. package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +303 -0
  396. package/src/resources/extensions/gsd/tests/discuss-routing-fixes.test.ts +12 -2
  397. package/src/resources/extensions/gsd/tests/dispatch-history.test.ts +273 -0
  398. package/src/resources/extensions/gsd/tests/dispatch-run-uat-browser-tools.test.ts +2 -1
  399. package/src/resources/extensions/gsd/tests/doctor-git-checks-terminal.test.ts +73 -0
  400. package/src/resources/extensions/gsd/tests/dynamic-bash-no-cap.test.ts +132 -0
  401. package/src/resources/extensions/gsd/tests/engine-hook-contract.test.ts +148 -0
  402. package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +193 -0
  403. package/src/resources/extensions/gsd/tests/exec-tool.test.ts +29 -1
  404. package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +35 -1
  405. package/src/resources/extensions/gsd/tests/gsd-command-home.test.ts +120 -0
  406. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +27 -0
  407. package/src/resources/extensions/gsd/tests/guidance.test.ts +23 -0
  408. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +2 -6
  409. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +7 -11
  410. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +20 -58
  411. package/src/resources/extensions/gsd/tests/integration/gsd-integration-fixture.ts +80 -0
  412. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +199 -0
  413. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +3 -1
  414. package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +95 -4
  415. package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +32 -1
  416. package/src/resources/extensions/gsd/tests/oauth-api-model-routing.test.ts +167 -0
  417. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +18 -0
  418. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +138 -0
  419. package/src/resources/extensions/gsd/tests/phases-terminal-complete-idempotent.test.ts +242 -0
  420. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +63 -2
  421. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +124 -6
  422. package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +68 -0
  423. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +19 -1
  424. package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +17 -0
  425. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +76 -0
  426. package/src/resources/extensions/gsd/tests/tool-unavailable-retry.test.ts +33 -0
  427. package/src/resources/extensions/gsd/tests/transport-gate-double-complete.test.ts +139 -0
  428. package/src/resources/extensions/gsd/tests/uat-policy.test.ts +112 -29
  429. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +44 -0
  430. package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +8 -0
  431. package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +2 -0
  432. package/src/resources/extensions/gsd/tests/web-app-uat.test.ts +44 -1
  433. package/src/resources/extensions/gsd/tests/workflow-events.test.ts +19 -0
  434. package/src/resources/extensions/gsd/tests/workflow-reconcile.test.ts +20 -0
  435. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +273 -38
  436. package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +22 -0
  437. package/src/resources/extensions/gsd/tests/worktree.test.ts +18 -0
  438. package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +358 -0
  439. package/src/resources/extensions/gsd/tests/write-gate.test.ts +67 -1
  440. package/src/resources/extensions/gsd/tool-contract.ts +38 -3
  441. package/src/resources/extensions/gsd/tool-presentation-plan.ts +4 -4
  442. package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
  443. package/src/resources/extensions/gsd/tools/complete-slice.ts +22 -12
  444. package/src/resources/extensions/gsd/tools/complete-task.ts +3 -2
  445. package/src/resources/extensions/gsd/tools/exec-tool.ts +4 -0
  446. package/src/resources/extensions/gsd/tools/plan-slice.ts +2 -2
  447. package/src/resources/extensions/gsd/tools/plan-task.ts +2 -2
  448. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +2 -2
  449. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +2 -2
  450. package/src/resources/extensions/gsd/tools/reopen-slice.ts +2 -2
  451. package/src/resources/extensions/gsd/tools/reopen-task.ts +2 -2
  452. package/src/resources/extensions/gsd/tools/replan-slice.ts +2 -2
  453. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +81 -2
  454. package/src/resources/extensions/gsd/uat-policy.ts +62 -16
  455. package/src/resources/extensions/gsd/unit-context-composer.ts +99 -0
  456. package/src/resources/extensions/gsd/unit-registry.ts +7 -20
  457. package/src/resources/extensions/gsd/verdict-parser.ts +1 -1
  458. package/src/resources/extensions/gsd/verification-verdict.ts +4 -2
  459. package/src/resources/extensions/gsd/web-app-uat.ts +51 -8
  460. package/src/resources/extensions/gsd/workflow-event-ledger.ts +131 -0
  461. package/src/resources/extensions/gsd/workflow-event-vocabulary.ts +59 -0
  462. package/src/resources/extensions/gsd/workflow-events.ts +12 -20
  463. package/src/resources/extensions/gsd/workflow-reconcile.ts +29 -62
  464. package/src/resources/extensions/gsd/worktree-lifecycle.ts +3 -8
  465. package/src/resources/extensions/gsd/worktree-manager.ts +6 -1
  466. package/src/resources/extensions/gsd/worktree.ts +7 -1
  467. package/src/resources/extensions/search-the-web/native-search.ts +5 -3
  468. package/src/resources/extensions/shared/browser-contract.ts +66 -0
  469. package/src/resources/extensions/shared/gsd-browser-cli.ts +141 -6
  470. package/src/resources/shared/gsd-browser-path-sync.ts +273 -0
  471. package/src/resources/shared/package-manager-detection.ts +1 -1
  472. package/src/resources/shared/package.json +3 -0
  473. package/src/resources/skills/create-skill/SKILL.md +3 -0
  474. package/src/resources/skills/create-skill/references/executable-code.md +1 -1
  475. package/src/resources/skills/create-skill/references/skill-structure.md +1 -0
  476. package/src/resources/skills/create-skill/workflows/add-reference.md +8 -3
  477. package/src/resources/skills/create-skill/workflows/add-script.md +4 -2
  478. package/src/resources/skills/create-skill/workflows/add-template.md +3 -1
  479. package/src/resources/skills/create-skill/workflows/add-workflow.md +8 -3
  480. package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
  481. package/src/resources/skills/create-skill/workflows/verify-skill.md +9 -4
  482. package/src/resources/skills/spike-wrap-up/SKILL.md +9 -9
  483. package/dist/resources/extensions/gsd/user-input-boundary.js +0 -218
  484. package/dist/resources/skills/gsd-browser/SKILL.md +0 -41
  485. package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +0 -173
  486. package/src/resources/extensions/gsd/user-input-boundary.ts +0 -216
  487. package/src/resources/skills/gsd-browser/SKILL.md +0 -41
  488. /package/dist/web/standalone/.next/static/{2p9Rv9pQflAxCBbGVI2vb → yWwBo-w09Y_W-nmeeWFRp}/_buildManifest.js +0 -0
  489. /package/dist/web/standalone/.next/static/{2p9Rv9pQflAxCBbGVI2vb → yWwBo-w09Y_W-nmeeWFRp}/_ssgManifest.js +0 -0
@@ -15,7 +15,7 @@
15
15
 
16
16
  import type { ExtensionContext, ExtensionAPI } from "@gsd/pi-coding-agent";
17
17
  import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
18
- import { gsdProjectionRoot, resolveSliceFile, resolveSlicePath, resolveMilestoneFile } from "./paths.js";
18
+ import { gsdProjectionRoot, resolveSliceFile, resolveSlicePath } from "./paths.js";
19
19
  import { resolveMilestoneValidationVerdict } from "./milestone-validation-verdict.js";
20
20
  import { resolveCanonicalMilestoneRoot } from "./worktree-manager.js";
21
21
  import { parseUnitId } from "./unit-id.js";
@@ -25,8 +25,6 @@ import { loadEffectiveGSDPreferences } from "./preferences.js";
25
25
  import type { GSDPreferences } from "./preferences-types.js";
26
26
  import { isClosedStatus } from "./status-guards.js";
27
27
  import { loadFile } from "./files.js";
28
- import { parseRoadmap } from "./parsers-legacy.js";
29
- import { isMilestoneComplete } from "./state.js";
30
28
  import {
31
29
  runVerificationGate,
32
30
  runVerificationGateForTargets,
@@ -52,6 +50,7 @@ import { getSlice } from "./gsd-db.js";
52
50
  import { getLedger } from "./metrics.js";
53
51
  import { getUnitCostSpikeAction, resolveUnitCostSpikeMultiplier } from "./auto-budget.js";
54
52
  import { formatPostUnitStatusCard } from "./auto-status-message.js";
53
+ import { detectWebApp } from "./web-app-uat.js";
55
54
 
56
55
  export interface VerificationContext {
57
56
  s: AutoSession;
@@ -373,29 +372,13 @@ async function runValidateMilestonePostCheck(
373
372
  * DB-backed projects are authoritative (#4094 peer review); falls back to
374
373
  * roadmap parsing only when the DB is unavailable.
375
374
  */
376
- async function countIncompleteSlices(basePath: string, milestoneId: string): Promise<number> {
377
- if (isDbAvailable()) {
378
- const slices = getMilestoneSlices(milestoneId);
379
- if (slices.length === 0) {
380
- // No DB rows — treat as "unknown", do not pause.
381
- return 1;
382
- }
383
- return slices.filter((slice) => !isClosedStatus(slice.status)).length;
384
- }
385
-
386
- // Filesystem fallback: parse the roadmap markdown.
387
- try {
388
- const roadmapFile = resolveMilestoneFile(basePath, milestoneId, "ROADMAP");
389
- if (!roadmapFile) return 1;
390
- const roadmapContent = await loadFile(roadmapFile);
391
- if (!roadmapContent) return 1;
392
- const roadmap = parseRoadmap(roadmapContent);
393
- if (roadmap.slices.length === 0) return 1;
394
- return isMilestoneComplete(roadmap) ? 0 : 1;
395
- } catch {
396
- // Parsing failures should not cause false-positive pauses.
397
- return 1;
398
- }
375
+ async function countIncompleteSlices(_basePath: string, milestoneId: string): Promise<number> {
376
+ // DB-authoritative (ADR-017): no markdown fallback. DB unavailable or no
377
+ // rows means "unknown" — do not pause.
378
+ if (!isDbAvailable()) return 1;
379
+ const slices = getMilestoneSlices(milestoneId);
380
+ if (slices.length === 0) return 1;
381
+ return slices.filter((slice) => !isClosedStatus(slice.status)).length;
399
382
  }
400
383
 
401
384
  /**
@@ -805,17 +788,32 @@ export async function runPostUnitVerification(
805
788
  s.verificationRetryFailureHashes.delete(retryKey);
806
789
  s.pendingVerificationRetry = null;
807
790
  return "continue";
791
+ } else if (
792
+ verdict.reason === "no-host-checks" &&
793
+ taskAlreadyComplete &&
794
+ detectWebApp(s.basePath) &&
795
+ !result.runtimeErrors?.some((e) => e.blocking)
796
+ ) {
797
+ s.verificationRetryCount.delete(retryKey);
798
+ s.verificationRetryFailureHashes.delete(retryKey);
799
+ s.pendingVerificationRetry = null;
800
+ ctx.ui.notify(
801
+ "No task-level host verification command was found for a completed browser-facing task; continuing so slice UAT can verify the UI with browser tools.",
802
+ "warning",
803
+ );
804
+ return "continue";
808
805
  } else if (verdict.reason === "no-host-checks") {
809
806
  s.verificationRetryCount.delete(retryKey);
810
807
  s.verificationRetryFailureHashes.delete(retryKey);
811
808
  s.pendingVerificationRetry = null;
809
+ const pauseMessage = `Verification failed: ${verdict.failureContext}`;
812
810
  ctx.ui.notify(
813
- "Verification gate FAILED — no runnable host-owned verification checks were discovered. Pausing for human review.",
811
+ `Verification gate FAILED — ${verdict.failureContext}`,
814
812
  "error",
815
813
  );
816
814
  process.stderr.write(`verification-gate: ${verdict.failureContext}\n`);
817
815
  await pauseAuto(ctx, pi, {
818
- message: "Verification failed: no runnable host-owned verification checks were discovered.",
816
+ message: pauseMessage,
819
817
  category: "unknown",
820
818
  });
821
819
  return "pause";
@@ -972,6 +972,14 @@ function _resolveIntegrationBranchForReuse(
972
972
  }
973
973
  }
974
974
 
975
+ function safeCwd(fallback: string): string {
976
+ try {
977
+ return process.cwd();
978
+ } catch {
979
+ return fallback;
980
+ }
981
+ }
982
+
975
983
  /**
976
984
  * When reusing an existing milestone branch, fast-forward it onto the
977
985
  * integration branch when that's safe (branch is a strict ancestor of
@@ -1155,7 +1163,7 @@ export function teardownAutoWorktree(
1155
1163
 
1156
1164
  const branch = autoWorktreeBranch(milestoneId);
1157
1165
  const { preserveBranch = false, preserveWorktree = false } = opts;
1158
- const previousCwd = process.cwd();
1166
+ const previousCwd = safeCwd(originalBasePath);
1159
1167
 
1160
1168
  // Wrap the entire teardown body in a single try/finally so activeWorkspace
1161
1169
  // is ALWAYS cleared — even if process.chdir throws (e.g. originalBasePath
@@ -2229,6 +2237,11 @@ export function mergeMilestoneToMain(
2229
2237
  process.chdir(originalBasePath_);
2230
2238
  } catch (err) {
2231
2239
  logWarning("worktree", `chdir to project root after merge failed: ${err instanceof Error ? err.message : String(err)}`);
2240
+ debugLog("mergeMilestoneToMain", {
2241
+ phase: "post-merge-chdir-failed",
2242
+ target: originalBasePath_,
2243
+ error: err instanceof Error ? err.message : String(err),
2244
+ });
2232
2245
  }
2233
2246
  };
2234
2247
 
@@ -924,6 +924,14 @@ export function setCurrentDispatchedModelId(model: { provider: string; id: strin
924
924
  s.currentDispatchedModelId = model ? `${model.provider}/${model.id}` : null;
925
925
  }
926
926
 
927
+ /**
928
+ * Update the active unit model after runtime recovery switches models mid-unit.
929
+ * The next session restore path reads this field before dispatching again.
930
+ */
931
+ export function setCurrentUnitModelForRecovery(model: any | null): void {
932
+ s.currentUnitModel = model;
933
+ }
934
+
927
935
  // Tool tracking — delegates to auto-tool-tracking.ts
928
936
  export function markToolStart(toolCallId: string, toolName?: string): void {
929
937
  _markToolStart(toolCallId, s.active, toolName);
@@ -1000,6 +1008,41 @@ export function stopAutoRemote(projectRoot: string): {
1000
1008
  }
1001
1009
  }
1002
1010
 
1011
+ /**
1012
+ * Force-stop a remote auto-mode session before stealing its lock.
1013
+ * The normal stop path stays SIGTERM-only so cooperative sessions can clean up;
1014
+ * this path is only for the explicit "Force start" action.
1015
+ */
1016
+ export function forceStopAutoRemote(projectRoot: string): {
1017
+ found: boolean;
1018
+ pid?: number;
1019
+ error?: string;
1020
+ } {
1021
+ const lock = readCrashLock(projectRoot);
1022
+ if (!lock) return { found: false };
1023
+
1024
+ if (lock.pid === process.pid) {
1025
+ clearLock(projectRoot);
1026
+ return { found: false };
1027
+ }
1028
+
1029
+ if (!isLockProcessAlive(lock)) {
1030
+ clearLock(projectRoot);
1031
+ return { found: false };
1032
+ }
1033
+
1034
+ try {
1035
+ process.kill(lock.pid, "SIGTERM");
1036
+ if (isLockProcessAlive(lock)) {
1037
+ process.kill(lock.pid, "SIGKILL");
1038
+ }
1039
+ clearLock(projectRoot);
1040
+ return { found: true, pid: lock.pid };
1041
+ } catch (err) {
1042
+ return { found: false, error: (err as Error).message };
1043
+ }
1044
+ }
1045
+
1003
1046
  /**
1004
1047
  * Check if a remote auto-mode session is running (from a different process).
1005
1048
  * Reads the crash lock, checks PID liveness, and returns session details.
@@ -2400,7 +2443,7 @@ export async function startAuto(
2400
2443
  const pid = freshStartAssessment.lock?.pid;
2401
2444
  ctx.ui.notify(
2402
2445
  pid
2403
- ? `Another auto-mode session (PID ${pid}) appears to be running.\nStop it with \`kill ${pid}\` before starting a new session.`
2446
+ ? `Another auto-mode session (PID ${pid}) appears to be running.\nRun \`/gsd stop\` for graceful shutdown, or choose "Force start" from \`/gsd auto\` to terminate it.`
2404
2447
  : "Another auto-mode session appears to be running.",
2405
2448
  "error",
2406
2449
  );
@@ -23,6 +23,15 @@ interface BlockedModelsFile {
23
23
  blocked: BlockedModelEntry[];
24
24
  }
25
25
 
26
+ interface TemporaryBlockedModelEntry {
27
+ provider: string;
28
+ id: string;
29
+ reason: string;
30
+ blockedUntil: number;
31
+ }
32
+
33
+ const temporaryBlockedModels = new Map<string, TemporaryBlockedModelEntry>();
34
+
26
35
  function blockedModelsPath(basePath: string): string {
27
36
  return join(gsdRoot(basePath), "runtime", "blocked-models.json");
28
37
  }
@@ -31,6 +40,10 @@ function modelKey(provider: string, id: string): string {
31
40
  return `${provider.toLowerCase()}/${id.toLowerCase()}`;
32
41
  }
33
42
 
43
+ function temporaryModelKey(basePath: string, provider: string, id: string): string {
44
+ return `${basePath}:${modelKey(provider, id)}`;
45
+ }
46
+
34
47
  function readFileSafe(path: string): BlockedModelsFile {
35
48
  if (!existsSync(path)) return { version: 1, blocked: [] };
36
49
  try {
@@ -66,6 +79,42 @@ export function isModelBlocked(
66
79
  );
67
80
  }
68
81
 
82
+ export function blockModelUntil(
83
+ basePath: string,
84
+ provider: string,
85
+ id: string,
86
+ blockedUntil: number,
87
+ reason: string,
88
+ ): void {
89
+ const key = temporaryModelKey(basePath, provider, id);
90
+ if (blockedUntil <= Date.now()) {
91
+ temporaryBlockedModels.delete(key);
92
+ return;
93
+ }
94
+ temporaryBlockedModels.set(key, { provider, id, reason, blockedUntil });
95
+ }
96
+
97
+ export function isModelTemporarilyUnavailable(
98
+ basePath: string,
99
+ provider: string | undefined,
100
+ id: string | undefined,
101
+ now = Date.now(),
102
+ ): boolean {
103
+ if (!provider || !id) return false;
104
+ const key = temporaryModelKey(basePath, provider, id);
105
+ const entry = temporaryBlockedModels.get(key);
106
+ if (!entry) return false;
107
+ if (entry.blockedUntil <= now) {
108
+ temporaryBlockedModels.delete(key);
109
+ return false;
110
+ }
111
+ return true;
112
+ }
113
+
114
+ export function clearTemporaryModelBlocksForTest(): void {
115
+ temporaryBlockedModels.clear();
116
+ }
117
+
69
118
  export function blockModel(
70
119
  basePath: string,
71
120
  provider: string,
@@ -19,6 +19,7 @@ import {
19
19
  isAutoCompletionStopInProgress,
20
20
  pauseAuto,
21
21
  setCurrentDispatchedModelId,
22
+ setCurrentUnitModelForRecovery,
22
23
  } from "../auto.js";
23
24
  import { getNextFallbackModel, resolveModelWithFallbacksForUnit } from "../preferences.js";
24
25
  import { pauseAutoForProviderError } from "../provider-error-pause.js";
@@ -41,7 +42,7 @@ import {
41
42
  isTransient,
42
43
  type ErrorClass,
43
44
  } from "../error-classifier.js";
44
- import { blockModel, isModelBlocked } from "../blocked-models.js";
45
+ import { blockModel, blockModelUntil, isModelBlocked, isModelTemporarilyUnavailable } from "../blocked-models.js";
45
46
  import { getProjectGSDPreferencesPath } from "../preferences.js";
46
47
  import { resolveProviderErrorGuidance } from "../provider-error-guidance.js";
47
48
  import { formatGuidance } from "../guidance.js";
@@ -143,9 +144,14 @@ async function tryProviderModelFallback(params: ProviderModelFallbackParams): Pr
143
144
  const nextModelId = getNextFallbackModel(cursorModelId, modelConfig);
144
145
  if (!nextModelId) break;
145
146
  const candidate = resolveModelId(nextModelId, availableModels, rejectedProvider);
146
- if (candidate && !isModelBlocked(basePath, candidate.provider, candidate.id)) {
147
+ if (
148
+ candidate &&
149
+ !isModelBlocked(basePath, candidate.provider, candidate.id) &&
150
+ !isModelTemporarilyUnavailable(basePath, candidate.provider, candidate.id)
151
+ ) {
147
152
  const ok = await pi.setModel(candidate, { persist: false });
148
153
  if (ok) {
154
+ setCurrentUnitModelForRecovery(candidate);
149
155
  setCurrentDispatchedModelId({ provider: candidate.provider, id: candidate.id });
150
156
  switchedNotify(`${candidate.provider}/${candidate.id}`);
151
157
  pi.sendMessage(
@@ -163,7 +169,8 @@ async function tryProviderModelFallback(params: ProviderModelFallbackParams): Pr
163
169
  if (
164
170
  sessionModel &&
165
171
  !(sessionModel.provider === rejectedProvider && sessionModel.id === rejectedId) &&
166
- !isModelBlocked(basePath, sessionModel.provider, sessionModel.id)
172
+ !isModelBlocked(basePath, sessionModel.provider, sessionModel.id) &&
173
+ !isModelTemporarilyUnavailable(basePath, sessionModel.provider, sessionModel.id)
167
174
  ) {
168
175
  const startModel = availableModels.find(
169
176
  (m) => m.provider === sessionModel.provider && m.id === sessionModel.id,
@@ -171,6 +178,7 @@ async function tryProviderModelFallback(params: ProviderModelFallbackParams): Pr
171
178
  if (startModel) {
172
179
  const ok = await pi.setModel(startModel, { persist: false });
173
180
  if (ok) {
181
+ setCurrentUnitModelForRecovery(startModel);
174
182
  setCurrentDispatchedModelId({ provider: startModel.provider, id: startModel.id });
175
183
  switchedNotify(`${startModel.provider}/${startModel.id}`);
176
184
  pi.sendMessage(
@@ -676,6 +684,16 @@ export async function handleAgentEnd(
676
684
  if (currentProvider === "openai-codex" || currentProvider === "google-gemini-cli") {
677
685
  cls.retryAfterMs = Math.min(cls.retryAfterMs, 30_000);
678
686
  }
687
+ const dash = getAutoDashboardData();
688
+ if (dash.basePath && ctx.model?.provider && ctx.model?.id) {
689
+ blockModelUntil(
690
+ dash.basePath,
691
+ ctx.model.provider,
692
+ ctx.model.id,
693
+ Date.now() + cls.retryAfterMs,
694
+ rawErrorMsg || displayMsg || "rate limit",
695
+ );
696
+ }
679
697
  }
680
698
 
681
699
  // ── 2. Decide & Act ──────────────────────────────────────────────────
@@ -721,9 +739,14 @@ export async function handleAgentEnd(
721
739
  retryState.networkRetryCount = 0;
722
740
  retryState.currentRetryModelId = undefined;
723
741
  const modelToSet = resolveModelId(nextModelId, availableModels, ctx.model?.provider);
724
- if (modelToSet) {
742
+ const modelUnavailable = dash.basePath && modelToSet
743
+ ? isModelBlocked(dash.basePath, modelToSet.provider, modelToSet.id) ||
744
+ isModelTemporarilyUnavailable(dash.basePath, modelToSet.provider, modelToSet.id)
745
+ : false;
746
+ if (modelToSet && !modelUnavailable) {
725
747
  const ok = await pi.setModel(modelToSet, { persist: false });
726
748
  if (ok) {
749
+ setCurrentUnitModelForRecovery(modelToSet);
727
750
  setCurrentDispatchedModelId({ provider: modelToSet.provider, id: modelToSet.id });
728
751
  ctx.ui.notify(`Model error${errorDetail}. Switched to fallback: ${nextModelId} and resuming.`, "warning");
729
752
  pi.sendMessage({ customType: "gsd-auto-timeout-recovery", content: "Continue execution.", display: false }, { triggerTurn: true });
@@ -737,11 +760,17 @@ export async function handleAgentEnd(
737
760
  // Try restoring session model
738
761
  const sessionModel = getAutoModeStartModel();
739
762
  if (sessionModel) {
740
- if (ctx.model?.id !== sessionModel.id || ctx.model?.provider !== sessionModel.provider) {
763
+ const dash = getAutoDashboardData();
764
+ const sessionModelUnavailable = dash.basePath
765
+ ? isModelBlocked(dash.basePath, sessionModel.provider, sessionModel.id) ||
766
+ isModelTemporarilyUnavailable(dash.basePath, sessionModel.provider, sessionModel.id)
767
+ : false;
768
+ if (!sessionModelUnavailable && (ctx.model?.id !== sessionModel.id || ctx.model?.provider !== sessionModel.provider)) {
741
769
  const startModel = ctx.modelRegistry.getAvailable().find((m) => m.provider === sessionModel.provider && m.id === sessionModel.id);
742
770
  if (startModel) {
743
771
  const ok = await pi.setModel(startModel, { persist: false });
744
772
  if (ok) {
773
+ setCurrentUnitModelForRecovery(startModel);
745
774
  setCurrentDispatchedModelId({ provider: startModel.provider, id: startModel.id });
746
775
  retryState.networkRetryCount = 0;
747
776
  retryState.currentRetryModelId = undefined;
@@ -7,7 +7,6 @@ import { join } from "node:path";
7
7
  import type { ExtensionAPI } from "@gsd/pi-coding-agent";
8
8
  import { createBashTool, createEditTool, createReadTool, createWriteTool } from "@gsd/pi-coding-agent";
9
9
 
10
- import { DEFAULT_BASH_TIMEOUT_SECS } from "../constants.js";
11
10
  import { logWarning } from "../workflow-logger.js";
12
11
  import { openWorkflowDatabase } from "../db-workspace.js";
13
12
  import { getAutoWorktreePath } from "../auto-worktree.js";
@@ -87,8 +86,30 @@ export function registerDynamicTools(pi: ExtensionAPI): void {
87
86
  const baseBash = createBashTool(fallbackRoot, {
88
87
  spawnHook: (ctx) => ctx,
89
88
  });
89
+ // The auto-mode stalled-tool watchdog only exists in GSD/auto-mode, so the
90
+ // watchdog verbiage is injected here (the GSD-registered tool) rather than in
91
+ // core bash.ts, which is reused by non-GSD embeddings that have no watchdog.
92
+ const WATCHDOG_DETAIL =
93
+ "Genuine hangs are caught by the auto-mode stalled-tool watchdog (stalled: 5m / idle: 10m / soft: 20m / hard: 30m).";
94
+ const gsdBashDescription = `${(baseBash as any).description} ${WATCHDOG_DETAIL}`;
95
+ const gsdBashParameters = (() => {
96
+ const params: any = (baseBash as any).parameters;
97
+ if (!params?.properties?.timeout) return params;
98
+ return {
99
+ ...params,
100
+ properties: {
101
+ ...params.properties,
102
+ timeout: {
103
+ ...params.properties.timeout,
104
+ description: `${params.properties.timeout.description} ${WATCHDOG_DETAIL}`,
105
+ },
106
+ },
107
+ };
108
+ })();
90
109
  const dynamicBash = {
91
110
  ...baseBash,
111
+ description: gsdBashDescription,
112
+ parameters: gsdBashParameters,
92
113
  execute: async (
93
114
  toolCallId: string,
94
115
  params: { command: string; timeout?: number },
@@ -100,11 +121,7 @@ export function registerDynamicTools(pi: ExtensionAPI): void {
100
121
  const fresh = createBashTool(basePath, {
101
122
  spawnHook: (spawnCtx) => ({ ...spawnCtx, cwd: basePath }),
102
123
  });
103
- const paramsWithTimeout = {
104
- ...params,
105
- timeout: params.timeout ?? DEFAULT_BASH_TIMEOUT_SECS,
106
- };
107
- return (fresh as any).execute(toolCallId, paramsWithTimeout, signal, onUpdate, ctx);
124
+ return (fresh as any).execute(toolCallId, params, signal, onUpdate, ctx);
108
125
  },
109
126
  };
110
127
  pi.registerTool(dynamicBash as any);
@@ -137,8 +137,8 @@ export function registerExecTools(pi: ExtensionAPI): void {
137
137
  parameters: Type.Object({
138
138
  query: Type.Optional(Type.String({ description: "Substring matched against id and purpose (case-insensitive)." })),
139
139
  runtime: Type.Optional(
140
- Type.Union([Type.Literal("bash"), Type.Literal("node"), Type.Literal("python")], {
141
- description: "Restrict to one runtime.",
140
+ Type.String({
141
+ description: "Restrict to one runtime: bash, node, or python.",
142
142
  }),
143
143
  ),
144
144
  failing_only: Type.Optional(Type.Boolean({ description: "Only non-zero exit codes and timeouts." })),
@@ -17,6 +17,7 @@ import { registerHooks } from "./register-hooks.js";
17
17
  import { registerShortcuts } from "./register-shortcuts.js";
18
18
  import { writeCrashLog } from "./crash-log.js";
19
19
  import { logWarning } from "../workflow-logger.js";
20
+ import { UNIT_TOOL_CONTRACTS } from "../unit-tool-contracts.js";
20
21
  // Static import so cmux event listeners are registered synchronously during
21
22
  // extension bootstrap. Prior implementation used `void import().then()` which
22
23
  // queued listener registration as a microtask — any CMUX_CHANNELS emit fired
@@ -37,6 +38,12 @@ const EPIPE_STORM_WINDOW_MS = 10_000;
37
38
  let epipeCount = 0;
38
39
  let epipeWindowStart = 0;
39
40
 
41
+ export const CRITICAL_GSD_WORKFLOW_TOOL_NAMES = [...new Set(
42
+ Object.values(UNIT_TOOL_CONTRACTS)
43
+ .flatMap((contract) => contract.requiredWorkflowTools)
44
+ .filter((toolName) => toolName.startsWith("gsd_")),
45
+ )].sort();
46
+
40
47
  /** Write to stderr without ever re-throwing — stderr can EPIPE too, which would
41
48
  * re-enter this handler and re-loop. */
42
49
  function safeStderr(msg: string): void {
@@ -133,6 +140,21 @@ export function installEpipeGuard(): void {
133
140
  }
134
141
  }
135
142
 
143
+ function assertCriticalGsdWorkflowToolsRegistered(pi: ExtensionAPI): void {
144
+ if (typeof pi.getAllTools !== "function") return;
145
+
146
+ const registered = new Set(pi.getAllTools().map((tool) => tool.name));
147
+ const missing = CRITICAL_GSD_WORKFLOW_TOOL_NAMES.filter((toolName) => !registered.has(toolName));
148
+ if (missing.length === 0) return;
149
+
150
+ const message = [
151
+ `Critical GSD workflow tool registration failed; missing required tool(s): ${missing.join(", ")}.`,
152
+ "Check earlier bootstrap warnings for the registration slot that failed.",
153
+ ].join(" ");
154
+ logWarning("bootstrap", message);
155
+ throw new Error(message);
156
+ }
157
+
136
158
  export function registerGsdExtension(pi: ExtensionAPI): void {
137
159
  // Note: registerGSDCommand is called by index.ts before this function,
138
160
  // so we intentionally skip it here to avoid double-registration.
@@ -214,4 +236,6 @@ export function registerGsdExtension(pi: ExtensionAPI): void {
214
236
  );
215
237
  }
216
238
  }
239
+
240
+ assertCriticalGsdWorkflowToolsRegistered(pi);
217
241
  }