@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
@@ -40,6 +40,7 @@ import {
40
40
  composeContextModeInstructions,
41
41
  composeContractedUnitContext,
42
42
  composeInlinedContext,
43
+ composeToolSurfaceInstructions,
43
44
  composeUnitContext,
44
45
  type ArtifactResolver,
45
46
  type ComposedUnitContextBlock,
@@ -292,10 +293,12 @@ function prependContextModeToBlock(
292
293
  block: string,
293
294
  renderMode: ContextModeRenderMode = "standalone",
294
295
  ): string {
296
+ const toolSurface = composeToolSurfaceInstructions(unitType, { renderMode });
295
297
  const contextMode = renderContextModeBlockForPrompt(unitType, base, renderMode);
296
- if (!contextMode) return block;
297
- if (!block.trim()) return contextMode;
298
- return `${contextMode}\n\n${block}`;
298
+ const guidance = [toolSurface, contextMode].filter(Boolean).join("\n\n");
299
+ if (!guidance) return block;
300
+ if (!block.trim()) return guidance;
301
+ return `${guidance}\n\n${block}`;
299
302
  }
300
303
 
301
304
  function requireUnitPromptContextContract(unitType: string): UnitPromptContextContract {
@@ -2470,6 +2473,9 @@ export async function buildPlanSlicePrompt(
2470
2473
  `Either (a) add an earlier task that creates X on disk before the task that needs it, ` +
2471
2474
  `or (b) if this task IS the one that creates X, move X from inputs to expected_output. ` +
2472
2475
  `Do NOT put X in a task's expected_output if that task only reads or verifies X — only tasks that actually write X to disk should list it in expected_output.\n` +
2476
+ `- **"[file] X: ... GSD planning artifacts are projections preloaded as context / written by workflow tools"**: ` +
2477
+ `Remove X from the task's inputs, files, and expectedOutput entirely. Planning artifacts (anything under .gsd/, .planning/, or .audits/, or names like M001-CONTEXT.md / S01-PLAN.md) are preloaded as context and written by workflow tools — ` +
2478
+ `do NOT add a task that creates X and do NOT move X to expectedOutput.\n` +
2473
2479
  `- **"[file] X: Task T_early reads X but it's created by task T_late (sequence violation)"**: ` +
2474
2480
  `Either (a) reorder tasks so T_late (the creator) runs before T_early (the reader), ` +
2475
2481
  `or (b) if T_late doesn't actually create X (it only reads/tests it), remove X from T_late's expected_output entirely.\n` +
@@ -3847,18 +3853,22 @@ export async function buildReactiveExecutePrompt(
3847
3853
  const inlinedTemplates = inlineTemplate("task-summary", "Task Summary");
3848
3854
  trackPromptContext(contextTelemetry, "templates", "inline", inlinedTemplates);
3849
3855
 
3850
- const prompt = loadPrompt("reactive-execute", {
3851
- workingDirectory: base,
3852
- milestoneId: mid,
3853
- milestoneTitle: midTitle,
3854
- sliceId: sid,
3855
- sliceTitle: sTitle,
3856
- graphContext: prependContextModeToBlock("reactive-execute", base, graphContext),
3857
- readyTaskCount: String(readyTaskIds.length),
3858
- readyTaskList: readyTaskListLines.join("\n"),
3859
- subagentPrompts: subagentSections.join("\n\n---\n\n"),
3860
- inlinedTemplates,
3861
- });
3856
+ const prompt = prependContextModeToBlock(
3857
+ "reactive-execute",
3858
+ base,
3859
+ loadPrompt("reactive-execute", {
3860
+ workingDirectory: base,
3861
+ milestoneId: mid,
3862
+ milestoneTitle: midTitle,
3863
+ sliceId: sid,
3864
+ sliceTitle: sTitle,
3865
+ graphContext,
3866
+ readyTaskCount: String(readyTaskIds.length),
3867
+ readyTaskList: readyTaskListLines.join("\n"),
3868
+ subagentPrompts: subagentSections.join("\n\n---\n\n"),
3869
+ inlinedTemplates,
3870
+ }),
3871
+ );
3862
3872
  emitPromptContextTelemetry("reactive-execute", contextTelemetry, prompt);
3863
3873
  return prompt;
3864
3874
  }
@@ -4037,17 +4047,21 @@ export async function buildGateEvaluatePrompt(
4037
4047
  ].join("\n"));
4038
4048
  }
4039
4049
 
4040
- return loadPrompt("gate-evaluate", {
4041
- workingDirectory: base,
4042
- milestoneId: mid,
4043
- milestoneTitle: midTitle,
4044
- sliceId: sid,
4045
- sliceTitle: sTitle,
4046
- slicePlanContent: prependContextModeToBlock("gate-evaluate", base, planContent),
4047
- gateCount: String(pending.length),
4048
- gateList: gateListLines.join("\n"),
4049
- subagentPrompts: subagentSections.join("\n\n---\n\n"),
4050
- });
4050
+ return prependContextModeToBlock(
4051
+ "gate-evaluate",
4052
+ base,
4053
+ loadPrompt("gate-evaluate", {
4054
+ workingDirectory: base,
4055
+ milestoneId: mid,
4056
+ milestoneTitle: midTitle,
4057
+ sliceId: sid,
4058
+ sliceTitle: sTitle,
4059
+ slicePlanContent: planContent,
4060
+ gateCount: String(pending.length),
4061
+ gateList: gateListLines.join("\n"),
4062
+ subagentPrompts: subagentSections.join("\n\n---\n\n"),
4063
+ }),
4064
+ );
4051
4065
  }
4052
4066
 
4053
4067
  export async function buildRewriteDocsPrompt(
@@ -57,7 +57,8 @@ import {
57
57
  detectWorktreeName,
58
58
  setActiveMilestoneId,
59
59
  } from "./worktree.js";
60
- import { getAutoWorktreePath, isInAutoWorktree, checkoutBranchWithStashGuard } from "./auto-worktree.js";
60
+ import { getAutoWorktreePath, isInAutoWorktree } from "./auto-worktree.js";
61
+ import { checkoutBranchWithStashGuard } from "./worktree-git-recovery.js";
61
62
  import { readResourceVersion, cleanStaleRuntimeUnits } from "./auto-worktree.js";
62
63
  import { worktreePath as getWorktreeDir, isInsideWorktreesDir } from "./worktree-manager.js";
63
64
  import { emitWorktreeOrphaned } from "./worktree-telemetry.js";
@@ -993,12 +994,14 @@ export async function bootstrapAutoSession(
993
994
  // phase-specific planning model for a discuss turn (#2829).
994
995
  //
995
996
  // Precedence:
996
- // 1) Explicit session override via /gsd model (this session)
997
- // 2) Current session model from settings/session restore (if provider ready)
998
- // 3) GSD model preferences from PREFERENCES.md (validated against live auth)
997
+ // 1) Explicit session override via /gsd model or /gsd auto --model (this session)
998
+ // 2) GSD model preferences from PREFERENCES.md (validated against live auth)
999
+ // 3) Current session model from settings/session restore (if provider ready)
999
1000
  //
1000
- // This preserves #3517 defaults while honoring explicit runtime model
1001
- // selection for subsequent /gsd runs in the same session.
1001
+ // PREFERENCES.md wins over the ambient session default (#3517) so /gsd auto
1002
+ // does not stick on claude-code/claude-sonnet-4-6 when the user configured
1003
+ // models via /gsd workflow-preferences or PREFERENCES.md. Custom providers
1004
+ // still skip PREFERENCES.md entirely (#4122).
1002
1005
  //
1003
1006
  // Exception (#4122): when the session provider is a custom provider declared
1004
1007
  // in ~/.gsd/agent/models.json (Ollama, vLLM, OpenAI-compatible proxy, etc.),
@@ -1010,7 +1013,7 @@ export async function bootstrapAutoSession(
1010
1013
  const sessionProviderIsCustom = isCustomProvider(ctx.model?.provider);
1011
1014
  const preferredModel = sessionProviderIsCustom
1012
1015
  ? null
1013
- : resolveDefaultSessionModel(ctx.model?.provider);
1016
+ : resolveDefaultSessionModel(ctx.model?.provider, base);
1014
1017
  // Validate the preferred model against the live registry + provider auth so
1015
1018
  // an unconfigured PREFERENCES.md entry (no API key / OAuth) can't become the
1016
1019
  // start-model snapshot. Without this, every subsequent unit would try to
@@ -1040,8 +1043,8 @@ export async function bootstrapAutoSession(
1040
1043
  : null;
1041
1044
  const startThinkingSnapshot = pi.getThinkingLevel();
1042
1045
  const startModelSnapshot = manualSessionOverride
1043
- ?? currentSessionModel
1044
1046
  ?? validatedPreferredModel
1047
+ ?? currentSessionModel
1045
1048
  ?? null;
1046
1049
 
1047
1050
  try {
@@ -1612,8 +1615,10 @@ export async function bootstrapAutoSession(
1612
1615
  const isUnderGsdWorktrees = (p: string): boolean => {
1613
1616
  const normalized = p.replaceAll("\\", "/");
1614
1617
  if (findWorktreeSegment(normalized) !== null) return true;
1615
- // The container directory itself (no trailing worktree name).
1616
- return normalized.endsWith("/.gsd/worktrees") || normalized.endsWith("/.gsd-worktrees");
1618
+ // The container directory itself (no trailing worktree name), in any layout.
1619
+ return normalized.endsWith("/.gsd/worktrees")
1620
+ || normalized.endsWith("/.gsd-worktrees")
1621
+ || /\/\.gsd\/projects\/[^/]+\/worktrees$/.test(normalized);
1617
1622
  };
1618
1623
 
1619
1624
  if (
@@ -5,6 +5,7 @@
5
5
  */
6
6
 
7
7
  import { stripMcpToolPrefix } from "@gsd/pi-ai";
8
+ import { TOOL_SURFACE_NOT_READY } from "./tool-surface-readiness.js";
8
9
 
9
10
  interface InFlightTool {
10
11
  startedAt: number;
@@ -132,6 +133,15 @@ export function clearInFlightTools(): void {
132
133
  const TOOL_INVOCATION_ERROR_RE = /Validation failed for tool|Input validation error|Invalid arguments for tool|MCP error -32602|No such tool available|Expected ',' or '\}'(?: after property value)?(?: in JSON)?|Unexpected end of JSON|Unexpected token.*in JSON|does not provide an export named|Named export .* not found|Cannot find module|ERR_MODULE_NOT_FOUND|ERR_MODULE_NOT_EXPORTED|ERR_PACKAGE_PATH_NOT_EXPORTED/i;
133
134
  const DETERMINISTIC_POLICY_ERROR_RE = /(?:^|\b)(?:HARD BLOCK:|Blocked: \/gsd queue is a planning tool|Direct writes to \.gsd\/STATE\.md and \.gsd\/gsd\.db are blocked|This is a mechanical gate)/i;
134
135
 
136
+ /**
137
+ * Matches the runtime's "tool not registered" error. Unlike the deterministic
138
+ * invocation failures above, this one is usually transient: the workflow MCP
139
+ * server registers its tool surface asynchronously after session start, so a
140
+ * Unit's first tool call can race the registration. Callers should retry
141
+ * (bounded) instead of breaking the loop.
142
+ */
143
+ const TOOL_UNAVAILABLE_ERROR_RE = new RegExp(`No such tool available|${TOOL_SURFACE_NOT_READY}`, "i");
144
+
135
145
  /**
136
146
  * Returns true if the error message indicates a deterministic invocation or
137
147
  * policy failure (as opposed to a normal tool execution error).
@@ -141,6 +151,15 @@ export function isToolInvocationError(errorMsg: string): boolean {
141
151
  return TOOL_INVOCATION_ERROR_RE.test(errorMsg) || isDeterministicPolicyError(errorMsg);
142
152
  }
143
153
 
154
+ /**
155
+ * Returns true if the error message indicates the called tool was not on the
156
+ * session's tool surface (MCP startup race — see TOOL_UNAVAILABLE_ERROR_RE).
157
+ */
158
+ export function isToolUnavailableError(errorMsg: string): boolean {
159
+ if (!errorMsg) return false;
160
+ return TOOL_UNAVAILABLE_ERROR_RE.test(errorMsg);
161
+ }
162
+
144
163
  /**
145
164
  * Returns true if the error message indicates the tool was skipped because
146
165
  * a queued user message interrupted the turn (#3595). Retrying will produce
@@ -15,22 +15,15 @@ export {
15
15
  RUN_UAT_BROWSER_TOOL_NAMES,
16
16
  } from "./unit-tool-contracts.js";
17
17
 
18
- const EXECUTE_TASK_UNIT_TYPES = new Set([
19
- "execute-task",
20
- "execute-task-simple",
21
- "reactive-execute",
22
- ]);
23
-
24
- // These units own quality gates, but their completion handlers persist verdicts
25
- // from artifact sections. gsd_save_gate_result belongs to gate-evaluate, so keep
26
- // blocking it here with a calm redirect to the section-write path.
27
- const SECTION_CLOSE_GATE_UNIT_TYPES = new Set([
28
- "execute-task",
29
- "execute-task-simple",
30
- "reactive-execute",
31
- "complete-slice",
32
- "validate-milestone",
33
- ]);
18
+ // Scope-class membership is declared per unit in the Unit Registry (ADR-033).
19
+ // EXECUTE_TASK_UNIT_TYPES = scopeClass "execute-task"; the section-close gate
20
+ // Set additionally includes scopeClass "section-close" — units whose completion
21
+ // handlers persist gate verdicts from artifact sections (gsd_save_gate_result
22
+ // belongs to gate-evaluate, so it is soft-blocked with a redirect below).
23
+ import {
24
+ EXECUTE_TASK_UNIT_TYPES,
25
+ SECTION_CLOSE_GATE_UNIT_TYPES,
26
+ } from "./unit-registry.js";
34
27
 
35
28
  const EXTRA_SCOPED_GSD_LIFECYCLE_TOOLS = [
36
29
  "gsd_skip_slice",
@@ -110,7 +103,7 @@ function isNativeWorkflowTool(toolName: string): boolean {
110
103
  return stripMcpToolPrefix(toolName) === "Workflow";
111
104
  }
112
105
 
113
- function readStringField(input: unknown, camel: string, snake: string): string | undefined {
106
+ export function readStringField(input: unknown, camel: string, snake: string): string | undefined {
114
107
  if (!input || typeof input !== "object") return undefined;
115
108
  const record = input as Record<string, unknown>;
116
109
  const value = record[camel] ?? record[snake];
@@ -44,23 +44,21 @@ import {
44
44
  worktreePath,
45
45
  isInsideWorktreesDir,
46
46
  } from "./worktree-manager.js";
47
+ import { worktreePathFor } from "./worktree-placement.js";
47
48
  import {
48
49
  detectWorktreeName,
49
50
  resolveGitHeadPath,
50
51
  nudgeGitBranchCache,
51
52
  } from "./worktree.js";
52
53
  import {
53
- findWorktreeSegment,
54
54
  isGsdWorktreePath,
55
+ projectRootFromWorktreePath,
55
56
  normalizeWorktreePathForCompare,
56
57
  resolveWorktreeProjectRoot,
57
58
  } from "./worktree-root.js";
58
59
  import { autoResolveSafeConflictPaths } from "./git-conflict-resolve.js";
59
60
  import { MergeConflictError, readIntegrationBranch, resolveMilestoneIntegrationBranch, RUNTIME_EXCLUSION_PATHS } from "./git-service.js";
60
- import {
61
- buildPullRequestEvidence,
62
- createDraftPullRequestFromEvidence,
63
- } from "./pull-request-process.js";
61
+ import { publishMilestone } from "./publication.js";
64
62
  import { debugLog } from "./debug-logger.js";
65
63
  import { logWarning, logError } from "./workflow-logger.js";
66
64
  import {
@@ -73,9 +71,6 @@ import {
73
71
  stashAlreadyExistsFilesFromError,
74
72
  stashRefFromError,
75
73
  } from "./worktree-git-recovery.js";
76
-
77
- // Re-export for existing callers/tests (auto-start.ts, checkout-branch-stash-guard.test.ts).
78
- export { checkoutBranchWithStashGuard } from "./worktree-git-recovery.js";
79
74
  import { loadEffectiveGSDPreferences } from "./preferences.js";
80
75
  import { MILESTONE_ID_RE } from "./milestone-ids.js";
81
76
  import { runWorktreePostCreateHook } from "./worktree-post-create-hook.js";
@@ -290,19 +285,6 @@ export function _gitPathspecForWorktreePath(basePath: string, targetPath: string
290
285
  return gitPathspecForWorktreePath(basePath, targetPath);
291
286
  }
292
287
 
293
- function gitRemoteExists(basePath: string, remote: string): boolean {
294
- try {
295
- execFileSync("git", ["remote", "get-url", remote], {
296
- cwd: basePath,
297
- stdio: ["ignore", "pipe", "pipe"],
298
- encoding: "utf-8",
299
- });
300
- return true;
301
- } catch {
302
- return false;
303
- }
304
- }
305
-
306
288
  function findRegularMergeChangedPaths(basePath: string, milestoneBranch: string, mainBranch: string): Set<string> {
307
289
  const changedPaths = new Set<string>();
308
290
  let mergeLog = "";
@@ -520,12 +502,8 @@ export function checkResourcesStale(
520
502
  * Returns the corrected base path.
521
503
  */
522
504
  export function escapeStaleWorktree(base: string): string {
523
- const segment = findWorktreeSegment(base.replaceAll("\\", "/"));
524
- if (!segment) return base;
525
-
526
- // base is inside .gsd/worktrees/<something> — extract the project root.
527
- // Normalization is 1:1 on characters, so the segment index is valid in `base`.
528
- const projectRoot = base.slice(0, segment.gsdIdx);
505
+ const projectRoot = projectRootFromWorktreePath(base);
506
+ if (projectRoot === null) return base;
529
507
 
530
508
  // Guard: If the candidate project root's .gsd IS the user-level ~/.gsd,
531
509
  // the string-slice heuristic matched the wrong /.gsd/ boundary. This happens
@@ -1307,7 +1285,9 @@ export function getAutoWorktreePath(
1307
1285
  ): string | null {
1308
1286
  basePath = resolveWorktreeProjectRoot(basePath);
1309
1287
 
1310
- const p = worktreePath(basePath, milestoneId);
1288
+ // basePath is already the resolved project root — go straight to placement
1289
+ // instead of worktreePath(), which would re-resolve the root.
1290
+ const p = worktreePathFor(basePath, milestoneId);
1311
1291
  if (!existsSync(p)) return null;
1312
1292
 
1313
1293
  // Validate this is a real git worktree, not a stray directory.
@@ -2049,8 +2029,6 @@ export function mergeMilestoneToMain(
2049
2029
  const isUntrackedRestoreFailure = stashPopMessage.includes("could not restore untracked files from stash");
2050
2030
  const gsdContentConflicts: string[] = [];
2051
2031
  const alreadyExists = stashAlreadyExistsFilesFromError(e);
2052
- const gsdAlreadyExists = alreadyExists.filter((f) => f.startsWith(".gsd/"));
2053
- const nonGsdAlreadyExists = alreadyExists.filter((f) => !f.startsWith(".gsd/"));
2054
2032
 
2055
2033
  // Untracked-file restore failures can leave marker conflicts in tracked
2056
2034
  // .gsd JSONL files without producing `U` status entries.
@@ -2114,11 +2092,12 @@ export function mergeMilestoneToMain(
2114
2092
  } else if (
2115
2093
  gsdUU.length === 0 &&
2116
2094
  nonGsdUU.length === 0 &&
2117
- gsdAlreadyExists.length > 0 &&
2118
- nonGsdAlreadyExists.length === 0
2095
+ alreadyExists.length > 0
2119
2096
  ) {
2120
- // Untracked-file restore failure from stash pop where all collided
2121
- // paths are .gsd/ artifacts that already exist after merge.
2097
+ // Untracked-file restore failure from stash pop where all collided paths
2098
+ // already exist after merge (committed on target). Safe to drop the stash
2099
+ // for the full alreadyExists set — they were untracked on source by
2100
+ // definition of the "already exists, no checkout" failure.
2122
2101
  if (stashRefForDrop) {
2123
2102
  try {
2124
2103
  execFileSync("git", ["stash", "drop", stashRefForDrop], {
@@ -2137,10 +2116,6 @@ export function mergeMilestoneToMain(
2137
2116
  logWarning("reconcile", "Stash pop conflict on non-.gsd files after merge", {
2138
2117
  files: nonGsdUU.join(", "),
2139
2118
  });
2140
- } else if (nonGsdAlreadyExists.length > 0) {
2141
- logWarning("reconcile", "Stash pop restore collision on non-.gsd files after merge", {
2142
- files: nonGsdAlreadyExists.join(", "),
2143
- });
2144
2119
  } else {
2145
2120
  logWarning(
2146
2121
  "worktree",
@@ -2258,62 +2233,24 @@ export function mergeMilestoneToMain(
2258
2233
  };
2259
2234
 
2260
2235
  let shouldCleanup = false;
2261
- let pushed = false;
2262
- let prCreated = false;
2263
2236
  try {
2264
- // 10. Auto-push if enabled
2265
- if (prefs.auto_push === true && prefs.auto_pr !== true && !nothingToCommit) {
2266
- const remote = prefs.remote ?? "origin";
2267
- if (gitRemoteExists(originalBasePath_, remote)) {
2268
- try {
2269
- execFileSync("git", ["push", remote, mainBranch], {
2270
- cwd: originalBasePath_,
2271
- stdio: ["ignore", "pipe", "pipe"],
2272
- encoding: "utf-8",
2273
- });
2274
- pushed = true;
2275
- } catch (err) {
2276
- // Push failure is non-fatal
2277
- logWarning("worktree", `git push failed: ${err instanceof Error ? err.message : String(err)}`);
2278
- }
2279
- }
2280
- }
2281
-
2282
- // 9b. Auto-create PR if enabled (#2302: no longer gated on pushed/auto_push)
2283
- if (prefs.auto_pr === true && !nothingToCommit) {
2284
- const remote = prefs.remote ?? "origin";
2285
- const prTarget = prefs.pr_target_branch ?? mainBranch;
2286
- if (gitRemoteExists(originalBasePath_, remote)) {
2287
- try {
2288
- // Push the milestone branch to remote first
2289
- execFileSync("git", ["push", remote, milestoneBranch], {
2290
- cwd: originalBasePath_,
2291
- stdio: ["ignore", "pipe", "pipe"],
2292
- encoding: "utf-8",
2293
- });
2294
- const prEvidence = buildPullRequestEvidence({
2295
- milestoneId,
2296
- milestoneTitle,
2297
- changeType: "feat",
2298
- summaries: completedSlices.map((slice) => `### ${slice.id}\n${slice.title}`),
2299
- testsRun: ["Auto-created after milestone merge. Run `npm run verify:merge` before marking this draft ready."],
2300
- rollbackNotes: ["Close the draft PR or revert the merge commit if review finds a behavior regression."],
2301
- how: "Generated by git.auto_pr after the milestone branch was pushed and merged locally.",
2302
- });
2303
- const prUrl = createDraftPullRequestFromEvidence(originalBasePath_, milestoneId, prEvidence, {
2304
- head: milestoneBranch,
2305
- base: prTarget,
2306
- });
2307
- if (!prUrl) {
2308
- throw new Error("gh pr create returned no URL");
2309
- }
2310
- prCreated = true;
2311
- } catch (err) {
2312
- // PR creation failure is non-fatal — gh may not be installed or authenticated
2313
- logWarning("worktree", `PR creation failed: ${err instanceof Error ? err.message : String(err)}`);
2314
- }
2315
- }
2316
- }
2237
+ // 10/9b. Publication (auto-push / draft PR) — Publication module seam (ADR-034).
2238
+ const publication = publishMilestone({
2239
+ basePath: originalBasePath_,
2240
+ milestoneId,
2241
+ milestoneTitle,
2242
+ integrationBranch: mainBranch,
2243
+ milestoneBranch,
2244
+ sliceSummaries: completedSlices.map((slice) => `### ${slice.id}\n${slice.title}`),
2245
+ nothingToCommit,
2246
+ prefs: {
2247
+ autoPush: prefs.auto_push === true,
2248
+ autoPr: prefs.auto_pr === true,
2249
+ remote: prefs.remote,
2250
+ prTargetBranch: prefs.pr_target_branch,
2251
+ },
2252
+ });
2253
+ const { pushed, prCreated } = publication;
2317
2254
 
2318
2255
  // 11. Guard removed — step 9b (#1792) now handles this with a smarter check:
2319
2256
  // throws only when the milestone has unanchored code changes, passes
@@ -331,6 +331,11 @@ import {
331
331
  } from "./db/auto-workers.js";
332
332
  import { releaseMilestoneLease } from "./db/milestone-leases.js";
333
333
  import { normalizeRealPath } from "./paths.js";
334
+ import {
335
+ formatStopNoticePrefix,
336
+ isBlockedStopReason,
337
+ stopNoticeDisplayReason,
338
+ } from "./stop-notice.js";
334
339
 
335
340
  // ── ENCAPSULATION INVARIANT ─────────────────────────────────────────────────
336
341
  // ALL mutable auto-mode state lives in the AutoSession class (auto/session.ts).
@@ -355,19 +360,7 @@ export function formatAutoStopNotification(prefix: string, totals: { cost: numbe
355
360
  ].join("\n");
356
361
  }
357
362
 
358
- function isBlockedStopReason(reason?: string | null): boolean {
359
- return /^Blocked:\s*/i.test(reason ?? "");
360
- }
361
-
362
- function formatAutoStopDisplayReason(reason?: string | null): string {
363
- return (reason ?? "").replace(/^Blocked:\s*/i, "").trim();
364
- }
365
-
366
- export function formatAutoStopNotificationPrefix(reason?: string | null): string {
367
- const displayReason = formatAutoStopDisplayReason(reason);
368
- const prefix = isBlockedStopReason(reason) ? "Auto-mode blocked" : "Auto-mode stopped";
369
- return displayReason ? `${prefix} — ${displayReason}` : prefix;
370
- }
363
+ export { formatStopNoticePrefix as formatAutoStopNotificationPrefix } from "./stop-notice.js";
371
364
 
372
365
  function clearSessionModelOverrideForCommandSession(ctx?: ExtensionContext | null): void {
373
366
  const sessionId =
@@ -1465,8 +1458,8 @@ export async function stopAuto(
1465
1458
  ): Promise<void> {
1466
1459
  if (!s.active && !s.paused) return;
1467
1460
  const loadedPreferences = loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences;
1468
- const stopNotificationPrefix = formatAutoStopNotificationPrefix(reason);
1469
- const displayReason = formatAutoStopDisplayReason(reason);
1461
+ const stopNotificationPrefix = formatStopNoticePrefix(reason);
1462
+ const displayReason = stopNoticeDisplayReason(reason);
1470
1463
  const isHeadlessStop = process.env.GSD_HEADLESS === "1";
1471
1464
  const completionStopRequested = Boolean(options.completionWidget);
1472
1465
  const preserveCloseoutTranscript = !isHeadlessStop && (
@@ -43,10 +43,8 @@ import {
43
43
  } from "../error-classifier.js";
44
44
  import { blockModel, isModelBlocked } from "../blocked-models.js";
45
45
  import { getProjectGSDPreferencesPath } from "../preferences.js";
46
- import {
47
- formatProviderErrorGuidance,
48
- resolveProviderErrorGuidance,
49
- } from "../provider-error-guidance.js";
46
+ import { resolveProviderErrorGuidance } from "../provider-error-guidance.js";
47
+ import { formatGuidance } from "../guidance.js";
50
48
 
51
49
  const retryState = createRetryState();
52
50
  const MAX_NETWORK_RETRIES = 2;
@@ -627,7 +625,7 @@ export async function handleAgentEnd(
627
625
  preferencesPath: dash.basePath ? getProjectGSDPreferencesPath(dash.basePath) : undefined,
628
626
  hasConfiguredFallbacks: (modelConfig?.fallbacks.length ?? 0) > 0,
629
627
  });
630
- const guidanceText = formatProviderErrorGuidance(guidance);
628
+ const guidanceText = formatGuidance(guidance);
631
629
 
632
630
  await pauseForProviderModelRejection(ctx, pi, {
633
631
  errorDetail,
@@ -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);
@@ -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
  }