@opengsd/gsd-pi 1.2.0-dev.955e4da0 → 1.2.0-dev.fb12b103

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 (378) hide show
  1. package/dist/cli-style.d.ts +17 -0
  2. package/dist/cli-style.js +28 -0
  3. package/dist/cli.js +1 -1
  4. package/dist/headless-events.d.ts +4 -2
  5. package/dist/headless-events.js +7 -29
  6. package/dist/models-resolver.d.ts +3 -13
  7. package/dist/models-resolver.js +3 -22
  8. package/dist/resource-loader.js +2 -14
  9. package/dist/resources/.managed-resources-content-hash +1 -1
  10. package/dist/resources/extensions/async-jobs/async-bash-tool.js +30 -64
  11. package/dist/resources/extensions/async-jobs/await-tool.js +80 -12
  12. package/dist/resources/extensions/async-jobs/index.js +65 -0
  13. package/dist/resources/extensions/async-jobs/job-manager.js +12 -1
  14. package/dist/resources/extensions/bg-shell/bg-shell-command.js +6 -6
  15. package/dist/resources/extensions/bg-shell/bg-shell-tool.js +10 -7
  16. package/dist/resources/extensions/bg-shell/overlay.js +9 -6
  17. package/dist/resources/extensions/bg-shell/process-manager.js +54 -25
  18. package/dist/resources/extensions/bg-shell/readiness-detector.js +11 -0
  19. package/dist/resources/extensions/bg-shell/utilities.js +3 -0
  20. package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +209 -88
  21. package/dist/resources/extensions/browser-tools/engine/selection.js +73 -5
  22. package/dist/resources/extensions/browser-tools/index.js +69 -12
  23. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +30 -4
  24. package/dist/resources/extensions/gsd/auto/orchestrator.js +7 -5
  25. package/dist/resources/extensions/gsd/auto-dispatch.js +12 -1
  26. package/dist/resources/extensions/gsd/auto-model-selection.js +25 -6
  27. package/dist/resources/extensions/gsd/auto-post-unit.js +11 -2
  28. package/dist/resources/extensions/gsd/auto-prompts.js +15 -10
  29. package/dist/resources/extensions/gsd/auto-start.js +15 -10
  30. package/dist/resources/extensions/gsd/auto-tool-tracking.js +18 -0
  31. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +7 -16
  32. package/dist/resources/extensions/gsd/auto-worktree.js +30 -90
  33. package/dist/resources/extensions/gsd/auto.js +4 -13
  34. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +3 -2
  35. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +23 -6
  36. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +19 -0
  37. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +122 -20
  38. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +6 -2
  39. package/dist/resources/extensions/gsd/branch-patterns.js +2 -0
  40. package/dist/resources/extensions/gsd/browser-daemon-auto-prep.js +83 -0
  41. package/dist/resources/extensions/gsd/browser-evidence.js +8 -2
  42. package/dist/resources/extensions/gsd/captures.js +4 -6
  43. package/dist/resources/extensions/gsd/constants.js +0 -2
  44. package/dist/resources/extensions/gsd/crash-recovery.js +4 -12
  45. package/dist/resources/extensions/gsd/doctor-environment.js +2 -6
  46. package/dist/resources/extensions/gsd/doctor-format.js +9 -6
  47. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +13 -15
  48. package/dist/resources/extensions/gsd/error-classifier.js +9 -0
  49. package/dist/resources/extensions/gsd/exec-sandbox.js +30 -10
  50. package/dist/resources/extensions/gsd/guidance.js +98 -0
  51. package/dist/resources/extensions/gsd/guided-flow.js +17 -2
  52. package/dist/resources/extensions/gsd/mcp-filter.js +2 -19
  53. package/dist/resources/extensions/gsd/mcp-tool-name.js +5 -13
  54. package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +1 -1
  55. package/dist/resources/extensions/gsd/migrate/safety.js +4 -1
  56. package/dist/resources/extensions/gsd/notification-store.js +11 -4
  57. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +6 -4
  58. package/dist/resources/extensions/gsd/paths.js +27 -0
  59. package/dist/resources/extensions/gsd/pre-execution-checks.js +91 -3
  60. package/dist/resources/extensions/gsd/preferences-models.js +14 -48
  61. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  62. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  63. package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  64. package/dist/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  65. package/dist/resources/extensions/gsd/prompts/run-uat.md +1 -1
  66. package/dist/resources/extensions/gsd/prompts/system.md +5 -2
  67. package/dist/resources/extensions/gsd/provider-error-guidance.js +1 -5
  68. package/dist/resources/extensions/gsd/provider-switch-observer.js +1 -1
  69. package/dist/resources/extensions/gsd/publication.js +87 -0
  70. package/dist/resources/extensions/gsd/recovery-classification.js +37 -94
  71. package/dist/resources/extensions/gsd/safety/destructive-confirmation.js +108 -0
  72. package/dist/resources/extensions/gsd/state.js +1 -20
  73. package/dist/resources/extensions/gsd/stop-notice.js +57 -0
  74. package/dist/resources/extensions/gsd/tool-surface-readiness.js +56 -0
  75. package/dist/resources/extensions/gsd/tools/exec-tool.js +9 -7
  76. package/dist/resources/extensions/gsd/tools/plan-slice.js +12 -6
  77. package/dist/resources/extensions/gsd/uat-policy.js +2 -1
  78. package/dist/resources/extensions/gsd/unit-closeout.js +138 -0
  79. package/dist/resources/extensions/gsd/unit-context-composer.js +74 -1
  80. package/dist/resources/extensions/gsd/unit-context-manifest.js +4 -27
  81. package/dist/resources/extensions/gsd/unit-registry.js +337 -0
  82. package/dist/resources/extensions/gsd/unit-tool-contracts.js +9 -182
  83. package/dist/resources/extensions/gsd/web-app-uat.js +45 -8
  84. package/dist/resources/extensions/gsd/workflow-tool-surface.js +1 -1
  85. package/dist/resources/extensions/gsd/worktree-git-recovery.js +15 -9
  86. package/dist/resources/extensions/gsd/worktree-root.js +11 -0
  87. package/dist/resources/extensions/gsd/worktree-session-state.js +4 -5
  88. package/dist/resources/extensions/search-the-web/native-search.js +5 -3
  89. package/dist/resources/extensions/shared/browser-contract.js +59 -0
  90. package/dist/resources/extensions/shared/gsd-browser-cli.js +96 -5
  91. package/dist/resources/shared/package.json +3 -0
  92. package/dist/resources/skills/create-skill/references/executable-code.md +1 -1
  93. package/dist/resources/skills/create-skill/workflows/add-reference.md +8 -3
  94. package/dist/resources/skills/create-skill/workflows/add-script.md +4 -2
  95. package/dist/resources/skills/create-skill/workflows/add-template.md +3 -1
  96. package/dist/resources/skills/create-skill/workflows/add-workflow.md +8 -3
  97. package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
  98. package/dist/resources/skills/create-skill/workflows/verify-skill.md +9 -4
  99. package/dist/resources/skills/spike-wrap-up/SKILL.md +9 -9
  100. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  101. package/dist/web/standalone/.next/BUILD_ID +1 -1
  102. package/dist/web/standalone/.next/app-path-routes-manifest.json +13 -13
  103. package/dist/web/standalone/.next/build-manifest.json +3 -3
  104. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  105. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  106. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  107. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  115. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/update/route.js.nft.json +1 -1
  124. package/dist/web/standalone/.next/server/app/index.html +1 -1
  125. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  128. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  131. package/dist/web/standalone/.next/server/app-paths-manifest.json +13 -13
  132. package/dist/web/standalone/.next/server/chunks/5124.js +1 -1
  133. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  134. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  136. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  137. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  138. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  139. package/dist/web/standalone/.next/static/chunks/{796.cf859a427a2cb2ac.js → 796.e0bdc932325d7e03.js} +1 -1
  140. package/dist/web/standalone/.next/static/chunks/{webpack-fbea77b5f9953368.js → webpack-f0285ce91d4ec9ef.js} +1 -1
  141. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  142. package/dist/web/standalone/node_modules/postcss/lib/container.js +18 -26
  143. package/dist/web/standalone/node_modules/postcss/lib/css-syntax-error.js +14 -47
  144. package/dist/web/standalone/node_modules/postcss/lib/declaration.js +4 -4
  145. package/dist/web/standalone/node_modules/postcss/lib/fromJSON.js +3 -3
  146. package/dist/web/standalone/node_modules/postcss/lib/input.js +29 -54
  147. package/dist/web/standalone/node_modules/postcss/lib/lazy-result.js +37 -47
  148. package/dist/web/standalone/node_modules/postcss/lib/map-generator.js +9 -26
  149. package/dist/web/standalone/node_modules/postcss/lib/no-work-result.js +55 -57
  150. package/dist/web/standalone/node_modules/postcss/lib/node.js +31 -99
  151. package/dist/web/standalone/node_modules/postcss/lib/parse.js +1 -1
  152. package/dist/web/standalone/node_modules/postcss/lib/parser.js +9 -10
  153. package/dist/web/standalone/node_modules/postcss/lib/postcss.js +12 -12
  154. package/dist/web/standalone/node_modules/postcss/lib/previous-map.js +11 -30
  155. package/dist/web/standalone/node_modules/postcss/lib/processor.js +7 -7
  156. package/dist/web/standalone/node_modules/postcss/lib/result.js +5 -5
  157. package/dist/web/standalone/node_modules/postcss/lib/rule.js +6 -6
  158. package/dist/web/standalone/node_modules/postcss/lib/stringifier.js +28 -69
  159. package/dist/web/standalone/node_modules/postcss/lib/tokenize.js +2 -6
  160. package/dist/web/standalone/node_modules/postcss/package.json +48 -48
  161. package/dist/web/standalone/package.json +1 -1
  162. package/dist/worktree-cli.js +3 -6
  163. package/dist/worktree-status-banner.js +7 -15
  164. package/package.json +1 -1
  165. package/packages/cloud-mcp-gateway/package.json +2 -2
  166. package/packages/contracts/dist/rpc.d.ts +1 -0
  167. package/packages/contracts/dist/rpc.d.ts.map +1 -1
  168. package/packages/contracts/dist/rpc.js.map +1 -1
  169. package/packages/contracts/dist/workflow.d.ts +4 -0
  170. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  171. package/packages/contracts/dist/workflow.js.map +1 -1
  172. package/packages/contracts/package.json +1 -1
  173. package/packages/daemon/package.json +4 -4
  174. package/packages/gsd-agent-core/package.json +5 -5
  175. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +5 -0
  176. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  177. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +5 -0
  178. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  179. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  180. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +7 -0
  181. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  182. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  183. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +8 -1
  184. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  185. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.d.ts.map +1 -1
  186. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js +11 -1
  187. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js.map +1 -1
  188. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
  189. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +4 -4
  190. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
  191. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  192. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +3 -1
  193. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
  194. package/packages/gsd-agent-modes/package.json +7 -7
  195. package/packages/mcp-server/dist/cli.js +6 -3
  196. package/packages/mcp-server/dist/cli.js.map +1 -1
  197. package/packages/mcp-server/dist/workflow-tools.d.ts +8 -0
  198. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  199. package/packages/mcp-server/dist/workflow-tools.js +17 -1
  200. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  201. package/packages/mcp-server/package.json +3 -3
  202. package/packages/native/package.json +1 -1
  203. package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts +1 -0
  204. package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts.map +1 -1
  205. package/packages/pi-agent-core/dist/harness/env/nodejs.js +34 -3
  206. package/packages/pi-agent-core/dist/harness/env/nodejs.js.map +1 -1
  207. package/packages/pi-agent-core/dist/index.d.ts +1 -0
  208. package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
  209. package/packages/pi-agent-core/dist/index.js +3 -0
  210. package/packages/pi-agent-core/dist/index.js.map +1 -1
  211. package/packages/pi-agent-core/package.json +1 -1
  212. package/packages/pi-ai/dist/models.generated.d.ts +94 -382
  213. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  214. package/packages/pi-ai/dist/models.generated.js +149 -422
  215. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  216. package/packages/pi-ai/package.json +1 -1
  217. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +2 -2
  218. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  219. package/packages/pi-coding-agent/dist/core/auth-storage.js +19 -13
  220. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  221. package/packages/pi-coding-agent/dist/core/provider-readiness.d.ts.map +1 -1
  222. package/packages/pi-coding-agent/dist/core/provider-readiness.js +13 -6
  223. package/packages/pi-coding-agent/dist/core/provider-readiness.js.map +1 -1
  224. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts +11 -0
  225. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
  226. package/packages/pi-coding-agent/dist/core/tools/bash.js +53 -11
  227. package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
  228. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  229. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  230. package/packages/pi-coding-agent/dist/index.js +1 -1
  231. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  232. package/packages/pi-coding-agent/dist/utils/shell.d.ts +28 -2
  233. package/packages/pi-coding-agent/dist/utils/shell.d.ts.map +1 -1
  234. package/packages/pi-coding-agent/dist/utils/shell.js +56 -10
  235. package/packages/pi-coding-agent/dist/utils/shell.js.map +1 -1
  236. package/packages/pi-coding-agent/package.json +7 -7
  237. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  238. package/packages/pi-tui/dist/tui.js +9 -0
  239. package/packages/pi-tui/dist/tui.js.map +1 -1
  240. package/packages/pi-tui/package.json +2 -2
  241. package/packages/rpc-client/package.json +2 -2
  242. package/pkg/package.json +1 -1
  243. package/src/resources/extensions/async-jobs/async-bash-cancel.test.ts +360 -0
  244. package/src/resources/extensions/async-jobs/async-bash-tool.ts +33 -56
  245. package/src/resources/extensions/async-jobs/await-tool.test.ts +139 -0
  246. package/src/resources/extensions/async-jobs/await-tool.ts +82 -12
  247. package/src/resources/extensions/async-jobs/index.ts +79 -0
  248. package/src/resources/extensions/async-jobs/job-manager.ts +21 -1
  249. package/src/resources/extensions/bg-shell/bg-shell-command.ts +6 -6
  250. package/src/resources/extensions/bg-shell/bg-shell-tool.ts +10 -6
  251. package/src/resources/extensions/bg-shell/overlay.ts +9 -5
  252. package/src/resources/extensions/bg-shell/process-manager.ts +50 -25
  253. package/src/resources/extensions/bg-shell/readiness-detector.ts +12 -0
  254. package/src/resources/extensions/bg-shell/tests/lifecycle-and-utilities.test.ts +48 -1
  255. package/src/resources/extensions/bg-shell/utilities.ts +3 -0
  256. package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +265 -98
  257. package/src/resources/extensions/browser-tools/engine/selection.ts +90 -4
  258. package/src/resources/extensions/browser-tools/index.ts +71 -13
  259. package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +83 -13
  260. package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +29 -1
  261. package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +136 -0
  262. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +34 -4
  263. package/src/resources/extensions/gsd/auto/orchestrator.ts +7 -5
  264. package/src/resources/extensions/gsd/auto-dispatch.ts +12 -0
  265. package/src/resources/extensions/gsd/auto-model-selection.ts +25 -5
  266. package/src/resources/extensions/gsd/auto-post-unit.ts +13 -2
  267. package/src/resources/extensions/gsd/auto-prompts.ts +40 -26
  268. package/src/resources/extensions/gsd/auto-start.ts +15 -10
  269. package/src/resources/extensions/gsd/auto-tool-tracking.ts +19 -0
  270. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +10 -17
  271. package/src/resources/extensions/gsd/auto-worktree.ts +30 -93
  272. package/src/resources/extensions/gsd/auto.ts +8 -15
  273. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +3 -5
  274. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +23 -6
  275. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +24 -0
  276. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +151 -15
  277. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +6 -2
  278. package/src/resources/extensions/gsd/branch-patterns.ts +3 -0
  279. package/src/resources/extensions/gsd/browser-daemon-auto-prep.ts +108 -0
  280. package/src/resources/extensions/gsd/browser-evidence.ts +18 -2
  281. package/src/resources/extensions/gsd/captures.ts +4 -6
  282. package/src/resources/extensions/gsd/constants.ts +0 -3
  283. package/src/resources/extensions/gsd/crash-recovery.ts +3 -9
  284. package/src/resources/extensions/gsd/doctor-environment.ts +2 -7
  285. package/src/resources/extensions/gsd/doctor-format.ts +12 -7
  286. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +13 -15
  287. package/src/resources/extensions/gsd/error-classifier.ts +11 -0
  288. package/src/resources/extensions/gsd/exec-sandbox.ts +49 -9
  289. package/src/resources/extensions/gsd/guidance.ts +139 -0
  290. package/src/resources/extensions/gsd/guided-flow.ts +16 -2
  291. package/src/resources/extensions/gsd/mcp-filter.ts +2 -23
  292. package/src/resources/extensions/gsd/mcp-tool-name.ts +6 -11
  293. package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +1 -1
  294. package/src/resources/extensions/gsd/migrate/safety.ts +4 -1
  295. package/src/resources/extensions/gsd/notification-store.ts +26 -3
  296. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +6 -4
  297. package/src/resources/extensions/gsd/paths.ts +33 -0
  298. package/src/resources/extensions/gsd/pre-execution-checks.ts +109 -3
  299. package/src/resources/extensions/gsd/preferences-models.ts +12 -47
  300. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  301. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  302. package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  303. package/src/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  304. package/src/resources/extensions/gsd/prompts/run-uat.md +1 -1
  305. package/src/resources/extensions/gsd/prompts/system.md +5 -2
  306. package/src/resources/extensions/gsd/provider-error-guidance.ts +4 -9
  307. package/src/resources/extensions/gsd/provider-switch-observer.ts +1 -1
  308. package/src/resources/extensions/gsd/publication.ts +122 -0
  309. package/src/resources/extensions/gsd/recovery-classification.ts +42 -96
  310. package/src/resources/extensions/gsd/safety/destructive-confirmation.ts +134 -0
  311. package/src/resources/extensions/gsd/state.ts +4 -21
  312. package/src/resources/extensions/gsd/stop-notice.ts +75 -0
  313. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +22 -0
  314. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +16 -19
  315. package/src/resources/extensions/gsd/tests/browser-automation-contract-fixture.ts +39 -0
  316. package/src/resources/extensions/gsd/tests/browser-contract.test.ts +44 -0
  317. package/src/resources/extensions/gsd/tests/browser-daemon-auto-prep.test.ts +144 -0
  318. package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +66 -1
  319. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +22 -0
  320. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +8 -7
  321. package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +303 -0
  322. package/src/resources/extensions/gsd/tests/dispatch-run-uat-browser-tools.test.ts +2 -1
  323. package/src/resources/extensions/gsd/tests/dynamic-bash-no-cap.test.ts +132 -0
  324. package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +193 -0
  325. package/src/resources/extensions/gsd/tests/exec-tool.test.ts +29 -1
  326. package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +35 -1
  327. package/src/resources/extensions/gsd/tests/guidance.test.ts +125 -0
  328. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +53 -11
  329. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +73 -58
  330. package/src/resources/extensions/gsd/tests/integration/gsd-integration-fixture.ts +80 -0
  331. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +3 -1
  332. package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +32 -1
  333. package/src/resources/extensions/gsd/tests/notification-store.test.ts +32 -0
  334. package/src/resources/extensions/gsd/tests/oauth-api-model-routing.test.ts +167 -0
  335. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +193 -1
  336. package/src/resources/extensions/gsd/tests/provider-error-guidance.test.ts +3 -3
  337. package/src/resources/extensions/gsd/tests/publication.test.ts +120 -0
  338. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +157 -0
  339. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +1 -0
  340. package/src/resources/extensions/gsd/tests/stop-notice.test.ts +70 -0
  341. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +76 -0
  342. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +8 -0
  343. package/src/resources/extensions/gsd/tests/tool-surface-readiness.test.ts +155 -0
  344. package/src/resources/extensions/gsd/tests/uat-policy.test.ts +24 -29
  345. package/src/resources/extensions/gsd/tests/unit-closeout.test.ts +209 -0
  346. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +67 -2
  347. package/src/resources/extensions/gsd/tests/unit-registry.test.ts +163 -0
  348. package/src/resources/extensions/gsd/tests/web-app-uat.test.ts +44 -1
  349. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -2
  350. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +2 -2
  351. package/src/resources/extensions/gsd/tool-surface-readiness.ts +76 -0
  352. package/src/resources/extensions/gsd/tools/exec-tool.ts +8 -7
  353. package/src/resources/extensions/gsd/tools/plan-slice.ts +12 -6
  354. package/src/resources/extensions/gsd/uat-policy.ts +2 -1
  355. package/src/resources/extensions/gsd/unit-closeout.ts +201 -0
  356. package/src/resources/extensions/gsd/unit-context-composer.ts +111 -1
  357. package/src/resources/extensions/gsd/unit-context-manifest.ts +4 -28
  358. package/src/resources/extensions/gsd/unit-registry.ts +412 -0
  359. package/src/resources/extensions/gsd/unit-tool-contracts.ts +27 -192
  360. package/src/resources/extensions/gsd/web-app-uat.ts +51 -8
  361. package/src/resources/extensions/gsd/workflow-tool-surface.ts +4 -1
  362. package/src/resources/extensions/gsd/worktree-git-recovery.ts +15 -9
  363. package/src/resources/extensions/gsd/worktree-root.ts +12 -0
  364. package/src/resources/extensions/gsd/worktree-session-state.ts +3 -5
  365. package/src/resources/extensions/search-the-web/native-search.ts +5 -3
  366. package/src/resources/extensions/shared/browser-contract.ts +66 -0
  367. package/src/resources/extensions/shared/gsd-browser-cli.ts +119 -5
  368. package/src/resources/shared/package.json +3 -0
  369. package/src/resources/skills/create-skill/references/executable-code.md +1 -1
  370. package/src/resources/skills/create-skill/workflows/add-reference.md +8 -3
  371. package/src/resources/skills/create-skill/workflows/add-script.md +4 -2
  372. package/src/resources/skills/create-skill/workflows/add-template.md +3 -1
  373. package/src/resources/skills/create-skill/workflows/add-workflow.md +8 -3
  374. package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
  375. package/src/resources/skills/create-skill/workflows/verify-skill.md +9 -4
  376. package/src/resources/skills/spike-wrap-up/SKILL.md +9 -9
  377. /package/dist/web/standalone/.next/static/{C24pqUd-aru-l0Dp0gLZP → mU4QIDlpVHDdjDpeEKh5W}/_buildManifest.js +0 -0
  378. /package/dist/web/standalone/.next/static/{C24pqUd-aru-l0Dp0gLZP → mU4QIDlpVHDdjDpeEKh5W}/_ssgManifest.js +0 -0
@@ -15,16 +15,15 @@ import { closeWorkflowDatabase, getWorkflowDatabasePath, openWorkflowDatabasePat
15
15
  import { execFileSync } from "node:child_process";
16
16
  import { gsdRoot, resolveGsdPathContract } from "./paths.js";
17
17
  import { createWorktree, removeWorktree, worktreePath, isInsideWorktreesDir, } from "./worktree-manager.js";
18
+ import { worktreePathFor } from "./worktree-placement.js";
18
19
  import { detectWorktreeName, nudgeGitBranchCache, } from "./worktree.js";
19
- import { findWorktreeSegment, isGsdWorktreePath, normalizeWorktreePathForCompare, resolveWorktreeProjectRoot, } from "./worktree-root.js";
20
+ import { isGsdWorktreePath, projectRootFromWorktreePath, normalizeWorktreePathForCompare, resolveWorktreeProjectRoot, } from "./worktree-root.js";
20
21
  import { autoResolveSafeConflictPaths } from "./git-conflict-resolve.js";
21
22
  import { MergeConflictError, readIntegrationBranch, resolveMilestoneIntegrationBranch, RUNTIME_EXCLUSION_PATHS } from "./git-service.js";
22
- import { buildPullRequestEvidence, createDraftPullRequestFromEvidence, } from "./pull-request-process.js";
23
+ import { publishMilestone } from "./publication.js";
23
24
  import { debugLog } from "./debug-logger.js";
24
25
  import { logWarning, logError } from "./workflow-logger.js";
25
26
  import { checkoutBranchWithStashGuard, cleanupConflictState, gsdJsonlFilesWithConflictMarkers, hasConflictMarkers, popStashByRef, removeMergeStateFiles, stashAlreadyExistsFilesFromError, stashRefFromError, } from "./worktree-git-recovery.js";
26
- // Re-export for existing callers/tests (auto-start.ts, checkout-branch-stash-guard.test.ts).
27
- export { checkoutBranchWithStashGuard } from "./worktree-git-recovery.js";
28
27
  import { loadEffectiveGSDPreferences } from "./preferences.js";
29
28
  import { MILESTONE_ID_RE } from "./milestone-ids.js";
30
29
  import { runWorktreePostCreateHook } from "./worktree-post-create-hook.js";
@@ -184,19 +183,6 @@ function gitPathspecForWorktreePath(basePath, targetPath) {
184
183
  export function _gitPathspecForWorktreePath(basePath, targetPath) {
185
184
  return gitPathspecForWorktreePath(basePath, targetPath);
186
185
  }
187
- function gitRemoteExists(basePath, remote) {
188
- try {
189
- execFileSync("git", ["remote", "get-url", remote], {
190
- cwd: basePath,
191
- stdio: ["ignore", "pipe", "pipe"],
192
- encoding: "utf-8",
193
- });
194
- return true;
195
- }
196
- catch {
197
- return false;
198
- }
199
- }
200
186
  function findRegularMergeChangedPaths(basePath, milestoneBranch, mainBranch) {
201
187
  const changedPaths = new Set();
202
188
  let mergeLog = "";
@@ -392,12 +378,9 @@ export function checkResourcesStale(versionOnStart) {
392
378
  * Returns the corrected base path.
393
379
  */
394
380
  export function escapeStaleWorktree(base) {
395
- const segment = findWorktreeSegment(base.replaceAll("\\", "/"));
396
- if (!segment)
381
+ const projectRoot = projectRootFromWorktreePath(base);
382
+ if (projectRoot === null)
397
383
  return base;
398
- // base is inside .gsd/worktrees/<something> — extract the project root.
399
- // Normalization is 1:1 on characters, so the segment index is valid in `base`.
400
- const projectRoot = base.slice(0, segment.gsdIdx);
401
384
  // Guard: If the candidate project root's .gsd IS the user-level ~/.gsd,
402
385
  // the string-slice heuristic matched the wrong /.gsd/ boundary. This happens
403
386
  // when .gsd is a symlink into ~/.gsd/projects/<hash> and process.cwd()
@@ -1078,7 +1061,9 @@ export function isInAutoWorktree(basePath) {
1078
1061
  */
1079
1062
  export function getAutoWorktreePath(basePath, milestoneId) {
1080
1063
  basePath = resolveWorktreeProjectRoot(basePath);
1081
- const p = worktreePath(basePath, milestoneId);
1064
+ // basePath is already the resolved project root — go straight to placement
1065
+ // instead of worktreePath(), which would re-resolve the root.
1066
+ const p = worktreePathFor(basePath, milestoneId);
1082
1067
  if (!existsSync(p))
1083
1068
  return null;
1084
1069
  // Validate this is a real git worktree, not a stray directory.
@@ -1738,8 +1723,6 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
1738
1723
  const isUntrackedRestoreFailure = stashPopMessage.includes("could not restore untracked files from stash");
1739
1724
  const gsdContentConflicts = [];
1740
1725
  const alreadyExists = stashAlreadyExistsFilesFromError(e);
1741
- const gsdAlreadyExists = alreadyExists.filter((f) => f.startsWith(".gsd/"));
1742
- const nonGsdAlreadyExists = alreadyExists.filter((f) => !f.startsWith(".gsd/"));
1743
1726
  // Untracked-file restore failures can leave marker conflicts in tracked
1744
1727
  // .gsd JSONL files without producing `U` status entries.
1745
1728
  if (isUntrackedRestoreFailure) {
@@ -1800,10 +1783,11 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
1800
1783
  }
1801
1784
  else if (gsdUU.length === 0 &&
1802
1785
  nonGsdUU.length === 0 &&
1803
- gsdAlreadyExists.length > 0 &&
1804
- nonGsdAlreadyExists.length === 0) {
1805
- // Untracked-file restore failure from stash pop where all collided
1806
- // paths are .gsd/ artifacts that already exist after merge.
1786
+ alreadyExists.length > 0) {
1787
+ // Untracked-file restore failure from stash pop where all collided paths
1788
+ // already exist after merge (committed on target). Safe to drop the stash
1789
+ // for the full alreadyExists set they were untracked on source by
1790
+ // definition of the "already exists, no checkout" failure.
1807
1791
  if (stashRefForDrop) {
1808
1792
  try {
1809
1793
  execFileSync("git", ["stash", "drop", stashRefForDrop], {
@@ -1826,11 +1810,6 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
1826
1810
  files: nonGsdUU.join(", "),
1827
1811
  });
1828
1812
  }
1829
- else if (nonGsdAlreadyExists.length > 0) {
1830
- logWarning("reconcile", "Stash pop restore collision on non-.gsd files after merge", {
1831
- files: nonGsdAlreadyExists.join(", "),
1832
- });
1833
- }
1834
1813
  else {
1835
1814
  logWarning("worktree", "git stash pop failed without resolvable conflict files; leaving stash for manual recovery");
1836
1815
  }
@@ -1925,63 +1904,24 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
1925
1904
  }
1926
1905
  };
1927
1906
  let shouldCleanup = false;
1928
- let pushed = false;
1929
- let prCreated = false;
1930
1907
  try {
1931
- // 10. Auto-push if enabled
1932
- if (prefs.auto_push === true && prefs.auto_pr !== true && !nothingToCommit) {
1933
- const remote = prefs.remote ?? "origin";
1934
- if (gitRemoteExists(originalBasePath_, remote)) {
1935
- try {
1936
- execFileSync("git", ["push", remote, mainBranch], {
1937
- cwd: originalBasePath_,
1938
- stdio: ["ignore", "pipe", "pipe"],
1939
- encoding: "utf-8",
1940
- });
1941
- pushed = true;
1942
- }
1943
- catch (err) {
1944
- // Push failure is non-fatal
1945
- logWarning("worktree", `git push failed: ${err instanceof Error ? err.message : String(err)}`);
1946
- }
1947
- }
1948
- }
1949
- // 9b. Auto-create PR if enabled (#2302: no longer gated on pushed/auto_push)
1950
- if (prefs.auto_pr === true && !nothingToCommit) {
1951
- const remote = prefs.remote ?? "origin";
1952
- const prTarget = prefs.pr_target_branch ?? mainBranch;
1953
- if (gitRemoteExists(originalBasePath_, remote)) {
1954
- try {
1955
- // Push the milestone branch to remote first
1956
- execFileSync("git", ["push", remote, milestoneBranch], {
1957
- cwd: originalBasePath_,
1958
- stdio: ["ignore", "pipe", "pipe"],
1959
- encoding: "utf-8",
1960
- });
1961
- const prEvidence = buildPullRequestEvidence({
1962
- milestoneId,
1963
- milestoneTitle,
1964
- changeType: "feat",
1965
- summaries: completedSlices.map((slice) => `### ${slice.id}\n${slice.title}`),
1966
- testsRun: ["Auto-created after milestone merge. Run `npm run verify:merge` before marking this draft ready."],
1967
- rollbackNotes: ["Close the draft PR or revert the merge commit if review finds a behavior regression."],
1968
- how: "Generated by git.auto_pr after the milestone branch was pushed and merged locally.",
1969
- });
1970
- const prUrl = createDraftPullRequestFromEvidence(originalBasePath_, milestoneId, prEvidence, {
1971
- head: milestoneBranch,
1972
- base: prTarget,
1973
- });
1974
- if (!prUrl) {
1975
- throw new Error("gh pr create returned no URL");
1976
- }
1977
- prCreated = true;
1978
- }
1979
- catch (err) {
1980
- // PR creation failure is non-fatal — gh may not be installed or authenticated
1981
- logWarning("worktree", `PR creation failed: ${err instanceof Error ? err.message : String(err)}`);
1982
- }
1983
- }
1984
- }
1908
+ // 10/9b. Publication (auto-push / draft PR) — Publication module seam (ADR-034).
1909
+ const publication = publishMilestone({
1910
+ basePath: originalBasePath_,
1911
+ milestoneId,
1912
+ milestoneTitle,
1913
+ integrationBranch: mainBranch,
1914
+ milestoneBranch,
1915
+ sliceSummaries: completedSlices.map((slice) => `### ${slice.id}\n${slice.title}`),
1916
+ nothingToCommit,
1917
+ prefs: {
1918
+ autoPush: prefs.auto_push === true,
1919
+ autoPr: prefs.auto_pr === true,
1920
+ remote: prefs.remote,
1921
+ prTargetBranch: prefs.pr_target_branch,
1922
+ },
1923
+ });
1924
+ const { pushed, prCreated } = publication;
1985
1925
  // 11. Guard removed — step 9b (#1792) now handles this with a smarter check:
1986
1926
  // throws only when the milestone has unanchored code changes, passes
1987
1927
  // through when the code is genuinely already on the integration branch.
@@ -117,6 +117,7 @@ import { createWorkspace, scopeMilestone } from "./workspace.js";
117
117
  import { registerAutoWorker, markWorkerStopping, } from "./db/auto-workers.js";
118
118
  import { releaseMilestoneLease } from "./db/milestone-leases.js";
119
119
  import { normalizeRealPath } from "./paths.js";
120
+ import { formatStopNoticePrefix, isBlockedStopReason, stopNoticeDisplayReason, } from "./stop-notice.js";
120
121
  // ── ENCAPSULATION INVARIANT ─────────────────────────────────────────────────
121
122
  // ALL mutable auto-mode state lives in the AutoSession class (auto/session.ts).
122
123
  // This file must NOT declare module-level `let` or `var` variables for state.
@@ -137,17 +138,7 @@ export function formatAutoStopNotification(prefix, totals, unitCount) {
137
138
  `Session: ${formatCost(totals.cost)} · ${formatTokenCount(totals.tokens.total)} tokens · ${unitCount} units`,
138
139
  ].join("\n");
139
140
  }
140
- function isBlockedStopReason(reason) {
141
- return /^Blocked:\s*/i.test(reason ?? "");
142
- }
143
- function formatAutoStopDisplayReason(reason) {
144
- return (reason ?? "").replace(/^Blocked:\s*/i, "").trim();
145
- }
146
- export function formatAutoStopNotificationPrefix(reason) {
147
- const displayReason = formatAutoStopDisplayReason(reason);
148
- const prefix = isBlockedStopReason(reason) ? "Auto-mode blocked" : "Auto-mode stopped";
149
- return displayReason ? `${prefix} — ${displayReason}` : prefix;
150
- }
141
+ export { formatStopNoticePrefix as formatAutoStopNotificationPrefix } from "./stop-notice.js";
151
142
  function clearSessionModelOverrideForCommandSession(ctx) {
152
143
  const sessionId = s.cmdCtx?.sessionManager?.getSessionId?.() ??
153
144
  ctx?.sessionManager?.getSessionId?.();
@@ -990,8 +981,8 @@ export async function stopAuto(ctx, pi, reason, options = {}) {
990
981
  if (!s.active && !s.paused)
991
982
  return;
992
983
  const loadedPreferences = loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences;
993
- const stopNotificationPrefix = formatAutoStopNotificationPrefix(reason);
994
- const displayReason = formatAutoStopDisplayReason(reason);
984
+ const stopNotificationPrefix = formatStopNoticePrefix(reason);
985
+ const displayReason = stopNoticeDisplayReason(reason);
995
986
  const isHeadlessStop = process.env.GSD_HEADLESS === "1";
996
987
  const completionStopRequested = Boolean(options.completionWidget);
997
988
  const preserveCloseoutTranscript = !isHeadlessStop && (options.preserveCloseoutTranscript ?? completionStopRequested);
@@ -15,7 +15,8 @@ import { resumeAutoAfterProviderDelay } from "./provider-error-resume.js";
15
15
  import { classifyError, createRetryState, resetRetryState, isTransient, } from "../error-classifier.js";
16
16
  import { blockModel, isModelBlocked } from "../blocked-models.js";
17
17
  import { getProjectGSDPreferencesPath } from "../preferences.js";
18
- import { formatProviderErrorGuidance, resolveProviderErrorGuidance, } from "../provider-error-guidance.js";
18
+ import { resolveProviderErrorGuidance } from "../provider-error-guidance.js";
19
+ import { formatGuidance } from "../guidance.js";
19
20
  const retryState = createRetryState();
20
21
  const MAX_NETWORK_RETRIES = 2;
21
22
  function isObjectRecord(value) {
@@ -486,7 +487,7 @@ export async function handleAgentEnd(pi, event, ctx) {
486
487
  preferencesPath: dash.basePath ? getProjectGSDPreferencesPath(dash.basePath) : undefined,
487
488
  hasConfiguredFallbacks: (modelConfig?.fallbacks.length ?? 0) > 0,
488
489
  });
489
- const guidanceText = formatProviderErrorGuidance(guidance);
490
+ const guidanceText = formatGuidance(guidance);
490
491
  await pauseForProviderModelRejection(ctx, pi, {
491
492
  errorDetail,
492
493
  rawErrorMsg,
@@ -4,7 +4,6 @@ import { existsSync, readdirSync } from "node:fs";
4
4
  import { homedir } from "node:os";
5
5
  import { join } from "node:path";
6
6
  import { createBashTool, createEditTool, createReadTool, createWriteTool } from "@gsd/pi-coding-agent";
7
- import { DEFAULT_BASH_TIMEOUT_SECS } from "../constants.js";
8
7
  import { logWarning } from "../workflow-logger.js";
9
8
  import { openWorkflowDatabase } from "../db-workspace.js";
10
9
  import { getAutoWorktreePath } from "../auto-worktree.js";
@@ -79,18 +78,36 @@ export function registerDynamicTools(pi) {
79
78
  const baseBash = createBashTool(fallbackRoot, {
80
79
  spawnHook: (ctx) => ctx,
81
80
  });
81
+ // The auto-mode stalled-tool watchdog only exists in GSD/auto-mode, so the
82
+ // watchdog verbiage is injected here (the GSD-registered tool) rather than in
83
+ // core bash.ts, which is reused by non-GSD embeddings that have no watchdog.
84
+ const WATCHDOG_DETAIL = "Genuine hangs are caught by the auto-mode stalled-tool watchdog (stalled: 5m / idle: 10m / soft: 20m / hard: 30m).";
85
+ const gsdBashDescription = `${baseBash.description} ${WATCHDOG_DETAIL}`;
86
+ const gsdBashParameters = (() => {
87
+ const params = baseBash.parameters;
88
+ if (!params?.properties?.timeout)
89
+ return params;
90
+ return {
91
+ ...params,
92
+ properties: {
93
+ ...params.properties,
94
+ timeout: {
95
+ ...params.properties.timeout,
96
+ description: `${params.properties.timeout.description} ${WATCHDOG_DETAIL}`,
97
+ },
98
+ },
99
+ };
100
+ })();
82
101
  const dynamicBash = {
83
102
  ...baseBash,
103
+ description: gsdBashDescription,
104
+ parameters: gsdBashParameters,
84
105
  execute: async (toolCallId, params, signal, onUpdate, ctx) => {
85
106
  const basePath = resolveCtxCwd(ctx);
86
107
  const fresh = createBashTool(basePath, {
87
108
  spawnHook: (spawnCtx) => ({ ...spawnCtx, cwd: basePath }),
88
109
  });
89
- const paramsWithTimeout = {
90
- ...params,
91
- timeout: params.timeout ?? DEFAULT_BASH_TIMEOUT_SECS,
92
- };
93
- return fresh.execute(toolCallId, paramsWithTimeout, signal, onUpdate, ctx);
110
+ return fresh.execute(toolCallId, params, signal, onUpdate, ctx);
94
111
  },
95
112
  };
96
113
  pi.registerTool(dynamicBash);
@@ -13,6 +13,7 @@ import { registerHooks } from "./register-hooks.js";
13
13
  import { registerShortcuts } from "./register-shortcuts.js";
14
14
  import { writeCrashLog } from "./crash-log.js";
15
15
  import { logWarning } from "../workflow-logger.js";
16
+ import { UNIT_TOOL_CONTRACTS } from "../unit-tool-contracts.js";
16
17
  // Static import so cmux event listeners are registered synchronously during
17
18
  // extension bootstrap. Prior implementation used `void import().then()` which
18
19
  // queued listener registration as a microtask — any CMUX_CHANNELS emit fired
@@ -30,6 +31,9 @@ const EPIPE_STORM_THRESHOLD = 100;
30
31
  const EPIPE_STORM_WINDOW_MS = 10_000;
31
32
  let epipeCount = 0;
32
33
  let epipeWindowStart = 0;
34
+ export const CRITICAL_GSD_WORKFLOW_TOOL_NAMES = [...new Set(Object.values(UNIT_TOOL_CONTRACTS)
35
+ .flatMap((contract) => contract.requiredWorkflowTools)
36
+ .filter((toolName) => toolName.startsWith("gsd_")))].sort();
33
37
  /** Write to stderr without ever re-throwing — stderr can EPIPE too, which would
34
38
  * re-enter this handler and re-loop. */
35
39
  function safeStderr(msg) {
@@ -121,6 +125,20 @@ export function installEpipeGuard() {
121
125
  process.on("unhandledRejection", _gsdRejectionGuard);
122
126
  }
123
127
  }
128
+ function assertCriticalGsdWorkflowToolsRegistered(pi) {
129
+ if (typeof pi.getAllTools !== "function")
130
+ return;
131
+ const registered = new Set(pi.getAllTools().map((tool) => tool.name));
132
+ const missing = CRITICAL_GSD_WORKFLOW_TOOL_NAMES.filter((toolName) => !registered.has(toolName));
133
+ if (missing.length === 0)
134
+ return;
135
+ const message = [
136
+ `Critical GSD workflow tool registration failed; missing required tool(s): ${missing.join(", ")}.`,
137
+ "Check earlier bootstrap warnings for the registration slot that failed.",
138
+ ].join(" ");
139
+ logWarning("bootstrap", message);
140
+ throw new Error(message);
141
+ }
124
142
  export function registerGsdExtension(pi) {
125
143
  // Note: registerGSDCommand is called by index.ts before this function,
126
144
  // so we intentionally skip it here to avoid double-registration.
@@ -186,4 +204,5 @@ export function registerGsdExtension(pi) {
186
204
  logWarning("bootstrap", `Failed to register ${name}: ${err instanceof Error ? err.message : String(err)}`);
187
205
  }
188
206
  }
207
+ assertCriticalGsdWorkflowToolsRegistered(pi);
189
208
  }
@@ -7,7 +7,7 @@ import { isToolCallEventType } from "@gsd/pi-coding-agent";
7
7
  import { ALWAYS_PRESERVED_SHIM_TOOL_NAMES } from "@gsd/pi-ai";
8
8
  import { updateSnapshot } from "../ecosystem/gsd-extension-api.js";
9
9
  import { buildMilestoneFileName, clearPathCache, milestonesDir, resolveMilestonePath, resolveSliceFile, resolveSlicePath } from "../paths.js";
10
- import { applyAskUserQuestionsGateResult, canonicalToolName, clearDiscussionFlowState, formatPendingAskUserQuestionsGateMessage, isApprovalGateVerifiedInSnapshot, isMilestoneDepthVerified, isMilestoneDepthVerifiedInSnapshot, isQueuePhaseActive, loadWriteGateSnapshot, markApprovalGateVerified, markDepthVerified, refreshWriteGateStateFromDisk, resetWriteGateState, shouldBlockContextWrite, shouldBlockPlanningUnit, shouldBlockQueueExecution, shouldBlockWorktreeWrite, isGateQuestionId, setPendingGate, clearPendingGate, getPendingGate, shouldBlockPendingGate, shouldBlockPendingGateBash, extractDepthVerificationMilestoneId } from "./write-gate.js";
10
+ import { applyAskUserQuestionsGateResult, canonicalToolName, clearDiscussionFlowState, formatPendingAskUserQuestionsGateMessage, isApprovalGateVerifiedInSnapshot, isDepthConfirmationAnswer, isMilestoneDepthVerified, isMilestoneDepthVerifiedInSnapshot, isQueuePhaseActive, markApprovalGateVerified, markDepthVerified, refreshWriteGateStateFromDisk, resetWriteGateState, shouldBlockContextWrite, shouldBlockPlanningUnit, shouldBlockQueueExecution, shouldBlockWorktreeWrite, isGateQuestionId, setPendingGate, clearPendingGate, getPendingGate, shouldBlockPendingGate, shouldBlockPendingGateBash, extractDepthVerificationMilestoneId } from "./write-gate.js";
11
11
  import { resolveManifest } from "../unit-context-manifest.js";
12
12
  import { isBlockedStateFile, isBashWriteToStateFile, BLOCKED_WRITE_ERROR } from "../write-intercept.js";
13
13
  import { loadFile, saveFile, formatContinue } from "../files.js";
@@ -19,7 +19,9 @@ import { saveActivityLog } from "../activity-log.js";
19
19
  import { recordToolCall as safetyRecordToolCall, recordToolResult as safetyRecordToolResult, saveEvidenceToDisk } from "../safety/evidence-collector.js";
20
20
  import { parseUnitId } from "../unit-id.js";
21
21
  import { classifyCommand } from "../safety/destructive-guard.js";
22
+ import { confirmDestructiveCommand, consumeDestructiveConfirmation, isDestructiveConfirmGateId, requestDestructiveConfirmation, } from "../safety/destructive-confirmation.js";
22
23
  import { logWarning as safetyLogWarning } from "../workflow-logger.js";
24
+ import { isUnitCloseoutTool, runInteractiveUnitCloseout } from "../unit-closeout.js";
23
25
  import { installNotifyInterceptor } from "./notify-interceptor.js";
24
26
  import { initNotificationStore } from "../notification-store.js";
25
27
  import { initNotificationWidget } from "../notification-widget.js";
@@ -31,11 +33,14 @@ import { applyUnitSkillVisibility, unitHasSkillManifest } from "../skill-scope.j
31
33
  import { getGuidedUnitContext } from "../guided-unit-context.js";
32
34
  import { registerPlanMilestoneSchemaRecovery } from "./plan-milestone-schema-recovery.js";
33
35
  import { AUTO_UNIT_SCOPED_TOOLS, RUN_UAT_BROWSER_TOOL_NAMES, canonicalWorkflowToolName, isWorkflowAliasTool } from "../auto-unit-tool-scope.js";
36
+ import { hasBrowserContractPrefix } from "../../shared/browser-contract.js";
34
37
  import { filterToolsForProvider } from "../model-router.js";
35
38
  import { mcpToolMatchesBaseName } from "../mcp-tool-name.js";
36
39
  import { RUN_UAT_READ_ONLY_TOOL_NAMES, RUN_UAT_WORKFLOW_TOOL_NAMES } from "../tool-presentation-plan.js";
37
40
  import { supportsSourceObservationsForUnit } from "../source-observations.js";
38
41
  import { clearPendingAutoStart } from "../pending-auto-start.js";
42
+ import { resolveWorkflowToolBasePath } from "./dynamic-tools.js";
43
+ import { getRequiredWorkflowToolsForUnit } from "../unit-tool-contracts.js";
39
44
  let approvalQuestionAbortInFlight = false;
40
45
  async function loadWelcomeScreenModule() {
41
46
  const candidates = [];
@@ -138,7 +143,7 @@ function withPreservedShimTools(toolNames) {
138
143
  }
139
144
  /** True for the browser automation tools (browser_navigate, browser_click, ...). */
140
145
  function isBrowserTool(toolName) {
141
- return canonicalToolName(toolName).startsWith("browser_");
146
+ return hasBrowserContractPrefix(canonicalToolName(toolName));
142
147
  }
143
148
  /**
144
149
  * True when any message in the request is driven by a GSD workflow command
@@ -200,7 +205,7 @@ export function buildMinimalGsdToolSet(activeToolNames) {
200
205
  const minimal = resolveScopedToolNames(activeToolNames, MINIMAL_GSD_TOOL_NAMES);
201
206
  return withPreservedShimTools([...new Set([...preserved, ...minimal])]);
202
207
  }
203
- export function buildMinimalAutoGsdToolSet(activeToolNames, unitType, registeredToolNames = activeToolNames) {
208
+ export function buildMinimalAutoGsdToolSet(activeToolNames, unitType, registeredToolNames = activeToolNames, warnOnUnresolvedRequiredTools = registeredToolNames !== activeToolNames) {
204
209
  if (unitType === "run-uat") {
205
210
  return buildRunUatGsdToolSet(activeToolNames, registeredToolNames);
206
211
  }
@@ -212,7 +217,20 @@ export function buildMinimalAutoGsdToolSet(activeToolNames, unitType, registered
212
217
  ...availableBaseTools,
213
218
  ])];
214
219
  const scoped = resolveScopedToolNames([...activeToolNames, ...registeredToolNames], [...MINIMAL_GSD_TOOL_NAMES, ...unitTools]);
215
- return withPreservedShimTools([...new Set([...preserved, ...scoped])]);
220
+ const result = withPreservedShimTools([...new Set([...preserved, ...scoped])]);
221
+ warnIfRequiredWorkflowToolsUnresolved(unitType, result, warnOnUnresolvedRequiredTools);
222
+ return result;
223
+ }
224
+ function hasResolvedWorkflowTool(resolvedToolNames, requiredToolName) {
225
+ return resolvedToolNames.some((name) => name === requiredToolName || mcpToolMatchesBaseName(name, requiredToolName));
226
+ }
227
+ function warnIfRequiredWorkflowToolsUnresolved(unitType, scopedToolNames, shouldWarn) {
228
+ if (!unitType || !shouldWarn)
229
+ return;
230
+ const unresolved = getRequiredWorkflowToolsForUnit(unitType).filter((toolName) => !hasResolvedWorkflowTool(scopedToolNames, toolName));
231
+ if (unresolved.length === 0)
232
+ return;
233
+ safetyLogWarning("bootstrap", `buildMinimalAutoGsdToolSet(${unitType}): required workflow tool(s) not in active/registered surface after scoping: ${unresolved.join(", ")}. Tool registration may have partially failed, provider filtering may have removed a required tool, or workflow MCP may be disconnected.`);
216
234
  }
217
235
  export function buildRunUatGsdToolSet(activeToolNames, registeredToolNames = activeToolNames) {
218
236
  const scoped = resolveScopedToolNames([...activeToolNames, ...registeredToolNames], [
@@ -238,7 +256,7 @@ export function buildMinimalGsdWorkflowToolSet(activeToolNames, registeredToolNa
238
256
  const scoped = resolveScopedToolNames([...activeToolNames, ...registeredToolNames], WORKFLOW_GSD_TOOL_NAMES);
239
257
  return withPreservedShimTools([...new Set([...preserved, ...scoped])]);
240
258
  }
241
- export function buildRequestScopedGsdToolSet(activeToolNames, requestCustomMessages, registeredToolNames = activeToolNames, guidedUnitType) {
259
+ export function buildRequestScopedGsdToolSet(activeToolNames, requestCustomMessages, registeredToolNames = activeToolNames, guidedUnitType, warnOnUnresolvedRequiredTools = registeredToolNames !== activeToolNames) {
242
260
  for (let index = (requestCustomMessages?.length ?? 0) - 1; index >= 0; index--) {
243
261
  const currentCustomType = requestCustomMessages?.[index]?.customType;
244
262
  if (currentCustomType === "gsd-run" ||
@@ -246,7 +264,7 @@ export function buildRequestScopedGsdToolSet(activeToolNames, requestCustomMessa
246
264
  currentCustomType === "gsd-doctor-heal" ||
247
265
  currentCustomType === "gsd-triage") {
248
266
  if (guidedUnitType) {
249
- return buildMinimalAutoGsdToolSet(activeToolNames, guidedUnitType, registeredToolNames);
267
+ return buildMinimalAutoGsdToolSet(activeToolNames, guidedUnitType, registeredToolNames, warnOnUnresolvedRequiredTools);
250
268
  }
251
269
  return buildMinimalGsdWorkflowToolSet(activeToolNames, registeredToolNames);
252
270
  }
@@ -280,8 +298,9 @@ function applyMinimalGsdToolSurface(pi) {
280
298
  const dash = getAutoRuntimeSnapshot();
281
299
  if (dash.active && dash.currentUnit) {
282
300
  const currentToolNames = pi.getActiveTools();
301
+ const hasRegisteredSurface = typeof pi.getAllTools === "function";
283
302
  const registeredToolNames = resolveRegisteredToolNames(pi, currentToolNames);
284
- const scopedToolNames = buildMinimalAutoGsdToolSet(currentToolNames, dash.currentUnit.type, registeredToolNames);
303
+ const scopedToolNames = buildMinimalAutoGsdToolSet(currentToolNames, dash.currentUnit.type, registeredToolNames, hasRegisteredSurface);
285
304
  recordAutoToolSurfaceSnapshot({
286
305
  source: "runtime-scope",
287
306
  unitType: dash.currentUnit.type,
@@ -300,9 +319,10 @@ export function scopeGsdWorkflowToolsForDispatch(pi, unitType) {
300
319
  if (isFullGsdToolSurfaceRequested())
301
320
  return null;
302
321
  const current = pi.getActiveTools();
322
+ const hasRegisteredSurface = typeof pi.getAllTools === "function";
303
323
  const registeredToolNames = resolveRegisteredToolNames(pi, current);
304
324
  const scoped = unitType
305
- ? buildMinimalAutoGsdToolSet(current, unitType, registeredToolNames)
325
+ ? buildMinimalAutoGsdToolSet(current, unitType, registeredToolNames, hasRegisteredSurface)
306
326
  : buildMinimalGsdWorkflowToolSet(current, registeredToolNames);
307
327
  recordAutoToolSurfaceSnapshot({
308
328
  source: "dispatch-scope",
@@ -447,8 +467,7 @@ function activateDeferredApprovalGate(basePath) {
447
467
  return;
448
468
  const gateId = deferredApprovalGate.gateId;
449
469
  deferredApprovalGate = null;
450
- refreshWriteGateStateFromDisk(basePath);
451
- const snapshot = loadWriteGateSnapshot(basePath);
470
+ const snapshot = refreshWriteGateStateFromDisk(basePath);
452
471
  const milestoneId = extractDepthVerificationMilestoneId(gateId);
453
472
  if (isApprovalGateVerifiedInSnapshot(snapshot, gateId))
454
473
  return;
@@ -472,6 +491,25 @@ function isContextDraftSummarySave(toolName, input) {
472
491
  return false;
473
492
  return input.artifact_type === "CONTEXT-DRAFT";
474
493
  }
494
+ /**
495
+ * External engines (claude-code-cli) deliver ask_user_questions results as
496
+ * relayed MCP tool results: the structured round payload arrives in
497
+ * `result.structuredContent`, not in pi-native `event.details`. Without this
498
+ * fallback, applyAskUserQuestionsGateResult sees no response for an answered
499
+ * gate question and lands in the "waiting" branch — leaving a re-armed gate
500
+ * permanently pending and the discuss→auto handoff blocked.
501
+ */
502
+ function resolveAskUserQuestionsGateDetails(event) {
503
+ const hasRoundShape = (value) => !!value && typeof value === "object" &&
504
+ (value.cancelled !== undefined || value.response !== undefined);
505
+ const details = event.details;
506
+ if (hasRoundShape(details))
507
+ return details;
508
+ const structured = event.result?.structuredContent;
509
+ if (hasRoundShape(structured))
510
+ return structured;
511
+ return details ?? {};
512
+ }
475
513
  function selectedAnswerLabel(selected) {
476
514
  if (Array.isArray(selected))
477
515
  return selected.map(String).join(", ");
@@ -1072,19 +1110,35 @@ export function registerHooks(pi, ecosystemHandlers) {
1072
1110
  }
1073
1111
  // Destructive command classification + hard gate in all modes.
1074
1112
  if (isToolCallEventType("bash", event)) {
1075
- const classification = classifyCommand(event.input.command);
1113
+ const command = event.input.command;
1114
+ const classification = classifyCommand(command);
1076
1115
  if (classification.destructive) {
1116
+ const guardBasePath = contextBasePath(ctx);
1117
+ // Escape hatch: if the user already confirmed this exact command via a
1118
+ // destructive_confirm gate, consume the one-shot token and let it run.
1119
+ // Without this, the block below loops forever — the model cannot satisfy
1120
+ // "confirm in the current turn" because nothing ever clears the gate.
1121
+ if (consumeDestructiveConfirmation(command, guardBasePath)) {
1122
+ safetyLogWarning("safety", `destructive command confirmed: ${classification.labels.join(", ")}`, {
1123
+ command: String(command).slice(0, 200),
1124
+ });
1125
+ return;
1126
+ }
1127
+ // Record the command as pending so an affirmative answer to a
1128
+ // destructive_confirm gate (handled in tool_result) can confirm it.
1129
+ requestDestructiveConfirmation(command, guardBasePath);
1077
1130
  const reason = [
1078
1131
  "HARD BLOCK: destructive Bash command requires explicit human confirmation.",
1079
1132
  `Detected: ${classification.labels.join(", ")}`,
1080
- "Run this via ask_user_questions, wait for the user's response,",
1081
- "then issue the command only when confirmed in the current turn.",
1133
+ "Call ask_user_questions with a question id containing \"destructive_confirm\"",
1134
+ "and a first option that affirms the action; wait for the user's response,",
1135
+ "then re-issue this exact command in the same turn to run it once.",
1082
1136
  ].join(" ");
1083
1137
  safetyLogWarning("safety", `destructive command: ${classification.labels.join(", ")}`, {
1084
- command: String(event.input.command).slice(0, 200),
1138
+ command: String(command).slice(0, 200),
1085
1139
  });
1086
1140
  if (ctx) {
1087
- await maybePauseAutoForApprovalGate(ctx, pi, isAutoActive(), "Depth confirmation is waiting for your answer — pausing auto-mode.");
1141
+ await maybePauseAutoForApprovalGate(ctx, pi, isAutoActive(), "Destructive-command confirmation is waiting for your answer — pausing auto-mode.");
1088
1142
  }
1089
1143
  return { block: true, reason };
1090
1144
  }
@@ -1121,12 +1175,27 @@ export function registerHooks(pi, ecosystemHandlers) {
1121
1175
  else if (isAutoActive()) {
1122
1176
  clearToolInvocationError();
1123
1177
  }
1178
+ // Interactive Closeout adapter (ADR-032): auto-mode owns closeout for its
1179
+ // own units; interactive completions get the durable git subset (commit +
1180
+ // Closeout Git Verdict) instead of silently bypassing git.isolation.
1181
+ if (!event.isError && !isAutoActive() && isUnitCloseoutTool(toolName)) {
1182
+ try {
1183
+ runInteractiveUnitCloseout({
1184
+ basePath: resolveWorkflowToolBasePath(ctx, event.input),
1185
+ canonicalToolName: toolName,
1186
+ input: event.input,
1187
+ });
1188
+ }
1189
+ catch (err) {
1190
+ safetyLogWarning("engine", `interactive unit closeout failed: ${err instanceof Error ? err.message : String(err)}`);
1191
+ }
1192
+ }
1124
1193
  if (toolName !== "ask_user_questions")
1125
1194
  return;
1126
1195
  const basePath = contextBasePath(ctx);
1127
1196
  const milestoneId = await getDiscussionMilestoneIdFor(basePath);
1128
- const details = event.details;
1129
- const questions = event.input?.questions ?? [];
1197
+ const details = resolveAskUserQuestionsGateDetails(event);
1198
+ const questions = event.input?.questions ?? details?.questions ?? [];
1130
1199
  const gateResult = applyAskUserQuestionsGateResult({
1131
1200
  basePath,
1132
1201
  questions,
@@ -1152,6 +1221,22 @@ export function registerHooks(pi, ecosystemHandlers) {
1152
1221
  }
1153
1222
  if (details?.cancelled || !details?.response)
1154
1223
  return;
1224
+ // Destructive-command confirmation: an affirmative answer to a
1225
+ // destructive_confirm gate promotes the pending blocked command to a
1226
+ // one-shot confirmed token, which the bash tool_call guard consumes on the
1227
+ // next attempt. Rejecting/declining leaves the command blocked.
1228
+ // (Depth-verification gate handling now lives in
1229
+ // applyAskUserQuestionsGateResult above; only the destructive-confirm gate
1230
+ // is handled inline here.)
1231
+ for (const question of questions) {
1232
+ if (isDestructiveConfirmGateId(question?.id)) {
1233
+ const answer = details.response?.answers?.[question.id];
1234
+ if (isDepthConfirmationAnswer(answer?.selected, question.options)) {
1235
+ confirmDestructiveCommand(basePath);
1236
+ }
1237
+ break;
1238
+ }
1239
+ }
1155
1240
  if (!milestoneId)
1156
1241
  return;
1157
1242
  await saveDiscussionQuestionRound(basePath, milestoneId, questions, details);
@@ -1162,7 +1247,23 @@ export function registerHooks(pi, ecosystemHandlers) {
1162
1247
  if (toolName === "ask_user_questions") {
1163
1248
  const questionId = extractGateQuestionId(event.args);
1164
1249
  if (typeof questionId === "string") {
1165
- setPendingGate(questionId, basePath);
1250
+ // External engines (claude-code-cli) ingest the SDK turn's tool blocks
1251
+ // post-hoc, so this event can fire AFTER the workflow MCP child already
1252
+ // verified this gate and allowed the CONTEXT save. setPendingGate also
1253
+ // revokes verifiedDepthMilestones/verifiedApprovalGates, so an
1254
+ // unconditional re-arm here wipes the child's verification and leaves
1255
+ // the discuss→auto handoff permanently blocked. Skip the re-arm when
1256
+ // the snapshot already records this exact gate as verified — mirrors
1257
+ // activateDeferredApprovalGate's guard. Stale verified state cannot
1258
+ // leak into a later re-discussion: a successful handoff deletes the
1259
+ // snapshot via clearDiscussionFlowState.
1260
+ const snapshot = refreshWriteGateStateFromDisk(basePath);
1261
+ const gateMilestoneId = extractDepthVerificationMilestoneId(questionId);
1262
+ const alreadyVerified = isApprovalGateVerifiedInSnapshot(snapshot, questionId) ||
1263
+ isMilestoneDepthVerifiedInSnapshot(snapshot, gateMilestoneId);
1264
+ if (!alreadyVerified) {
1265
+ setPendingGate(questionId, basePath);
1266
+ }
1166
1267
  clearDeferredApprovalGate(basePath);
1167
1268
  }
1168
1269
  }
@@ -1252,12 +1353,13 @@ export function registerHooks(pi, ecosystemHandlers) {
1252
1353
  return surfaceReduced ? { toolNames: providerCompatible } : undefined;
1253
1354
  }
1254
1355
  const registeredToolNames = resolveRegisteredToolNames(pi, event.activeToolNames);
1356
+ const hasRegisteredSurface = typeof pi.getAllTools === "function";
1255
1357
  const compatibleRegisteredToolNames = filterToolsForProvider(registeredToolNames, event.selectedModelApi, event.selectedModelProvider).compatible.filter((name) => !(dropAliases && isWorkflowAliasTool(name)));
1256
1358
  const guidedUnit = getGuidedUnitContext();
1257
1359
  const requestRegisteredToolNames = guidedUnit?.unitType === "run-uat"
1258
1360
  ? compatibleRegisteredToolNames
1259
1361
  : registeredToolNames;
1260
- const requestScoped = buildRequestScopedGsdToolSet(guidedUnit?.unitType === "run-uat" ? aliasFilteredCompatible : providerCompatible, event.requestCustomMessages, requestRegisteredToolNames, guidedUnit?.unitType);
1362
+ const requestScoped = buildRequestScopedGsdToolSet(guidedUnit?.unitType === "run-uat" ? aliasFilteredCompatible : providerCompatible, event.requestCustomMessages, requestRegisteredToolNames, guidedUnit?.unitType, hasRegisteredSurface);
1261
1363
  if (requestScoped) {
1262
1364
  recordAutoToolSurfaceSnapshot({
1263
1365
  source: "provider-adjustment",
@@ -1273,7 +1375,7 @@ export function registerHooks(pi, ecosystemHandlers) {
1273
1375
  const registeredForUnit = dash.currentUnit.type === "run-uat"
1274
1376
  ? compatibleRegisteredToolNames
1275
1377
  : resolveRegisteredToolNames(pi, event.activeToolNames);
1276
- const scopedToolNames = buildMinimalAutoGsdToolSet(dash.currentUnit.type === "run-uat" ? aliasFilteredCompatible : providerCompatible, dash.currentUnit.type, registeredForUnit);
1378
+ const scopedToolNames = buildMinimalAutoGsdToolSet(dash.currentUnit.type === "run-uat" ? aliasFilteredCompatible : providerCompatible, dash.currentUnit.type, registeredForUnit, hasRegisteredSurface);
1277
1379
  recordAutoToolSurfaceSnapshot({
1278
1380
  source: "provider-adjustment",
1279
1381
  unitType: dash.currentUnit.type,