@opengsd/gsd-pi 1.2.0-dev.84c56d87 → 1.2.0-dev.9ad8ae33

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 (460) hide show
  1. package/dist/headless-events.js +7 -5
  2. package/dist/mcp-server.js +2 -1
  3. package/dist/resource-loader.d.ts +10 -5
  4. package/dist/resource-loader.js +121 -6
  5. package/dist/resources/.managed-resources-content-hash +1 -1
  6. package/dist/resources/GSD-WORKFLOW.md +5 -4
  7. package/dist/resources/extensions/async-jobs/async-bash-tool.js +30 -64
  8. package/dist/resources/extensions/async-jobs/await-tool.js +80 -12
  9. package/dist/resources/extensions/async-jobs/index.js +65 -0
  10. package/dist/resources/extensions/async-jobs/job-manager.js +12 -1
  11. package/dist/resources/extensions/bg-shell/bg-shell-command.js +6 -6
  12. package/dist/resources/extensions/bg-shell/bg-shell-tool.js +10 -7
  13. package/dist/resources/extensions/bg-shell/overlay.js +9 -6
  14. package/dist/resources/extensions/bg-shell/process-manager.js +54 -25
  15. package/dist/resources/extensions/bg-shell/readiness-detector.js +11 -0
  16. package/dist/resources/extensions/gsd/auto/custom-verify-retry-store.js +17 -2
  17. package/dist/resources/extensions/gsd/auto/detect-stuck.js +33 -13
  18. package/dist/resources/extensions/gsd/auto/dispatch-history.js +105 -0
  19. package/dist/resources/extensions/gsd/auto/dispatch-key.js +37 -0
  20. package/dist/resources/extensions/gsd/auto/loop.js +4 -1
  21. package/dist/resources/extensions/gsd/auto/orchestrator.js +89 -54
  22. package/dist/resources/extensions/gsd/auto/phases.js +49 -6
  23. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  24. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +11 -34
  25. package/dist/resources/extensions/gsd/auto-dispatch.js +50 -58
  26. package/dist/resources/extensions/gsd/auto-model-selection.js +36 -13
  27. package/dist/resources/extensions/gsd/auto-post-unit.js +30 -12
  28. package/dist/resources/extensions/gsd/auto-prompts.js +78 -19
  29. package/dist/resources/extensions/gsd/auto-start.js +35 -15
  30. package/dist/resources/extensions/gsd/auto-unit-closeout.js +45 -21
  31. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +5 -4
  32. package/dist/resources/extensions/gsd/auto-verification.js +23 -30
  33. package/dist/resources/extensions/gsd/auto-worktree.js +14 -1
  34. package/dist/resources/extensions/gsd/auto.js +37 -1
  35. package/dist/resources/extensions/gsd/blocked-models.js +28 -0
  36. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +26 -6
  37. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +23 -6
  38. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -2
  39. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +145 -50
  40. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +302 -80
  41. package/dist/resources/extensions/gsd/browser-daemon-auto-prep.js +83 -0
  42. package/dist/resources/extensions/gsd/closeout-wizard.js +92 -0
  43. package/dist/resources/extensions/gsd/commands/context.js +16 -2
  44. package/dist/resources/extensions/gsd/commands-handlers.js +46 -3
  45. package/dist/resources/extensions/gsd/consent-question.js +353 -0
  46. package/dist/resources/extensions/gsd/consent-verdict.js +63 -0
  47. package/dist/resources/extensions/gsd/constants.js +0 -2
  48. package/dist/resources/extensions/gsd/crash-recovery.js +8 -3
  49. package/dist/resources/extensions/gsd/db/queries.js +26 -0
  50. package/dist/resources/extensions/gsd/db-writer.js +8 -17
  51. package/dist/resources/extensions/gsd/dispatch-guard.js +10 -35
  52. package/dist/resources/extensions/gsd/doctor-engine-checks.js +5 -5
  53. package/dist/resources/extensions/gsd/doctor-git-checks.js +2 -18
  54. package/dist/resources/extensions/gsd/engine-hook-contract.js +70 -0
  55. package/dist/resources/extensions/gsd/exec-sandbox.js +30 -10
  56. package/dist/resources/extensions/gsd/files.js +33 -19
  57. package/dist/resources/extensions/gsd/gsd-command-home.js +22 -12
  58. package/dist/resources/extensions/gsd/gsd-db.js +2 -1
  59. package/dist/resources/extensions/gsd/guidance.js +60 -0
  60. package/dist/resources/extensions/gsd/guided-flow.js +6 -3
  61. package/dist/resources/extensions/gsd/markdown-renderer.js +10 -0
  62. package/dist/resources/extensions/gsd/milestone-closeout.js +85 -24
  63. package/dist/resources/extensions/gsd/milestone-planning-persistence.js +2 -2
  64. package/dist/resources/extensions/gsd/milestone-reopen-events.js +3 -5
  65. package/dist/resources/extensions/gsd/parsers-legacy.js +16 -4
  66. package/dist/resources/extensions/gsd/preferences-models.js +2 -2
  67. package/dist/resources/extensions/gsd/projection-flush.js +7 -0
  68. package/dist/resources/extensions/gsd/prompts/complete-slice.md +3 -3
  69. package/dist/resources/extensions/gsd/prompts/execute-task.md +1 -1
  70. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  71. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  72. package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -1
  73. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  74. package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  75. package/dist/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  76. package/dist/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  77. package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
  78. package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  79. package/dist/resources/extensions/gsd/prompts/run-uat.md +7 -5
  80. package/dist/resources/extensions/gsd/prompts/system.md +5 -2
  81. package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -1
  82. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
  83. package/dist/resources/extensions/gsd/reactive-graph.js +8 -1
  84. package/dist/resources/extensions/gsd/roadmap-slices.js +25 -3
  85. package/dist/resources/extensions/gsd/safety/destructive-confirmation.js +108 -0
  86. package/dist/resources/extensions/gsd/session-lock.js +1 -1
  87. package/dist/resources/extensions/gsd/state.js +5 -0
  88. package/dist/resources/extensions/gsd/tool-contract.js +14 -3
  89. package/dist/resources/extensions/gsd/tool-presentation-plan.js +4 -4
  90. package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -2
  91. package/dist/resources/extensions/gsd/tools/complete-slice.js +22 -12
  92. package/dist/resources/extensions/gsd/tools/complete-task.js +3 -2
  93. package/dist/resources/extensions/gsd/tools/exec-tool.js +5 -0
  94. package/dist/resources/extensions/gsd/tools/plan-slice.js +2 -2
  95. package/dist/resources/extensions/gsd/tools/plan-task.js +2 -2
  96. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +2 -2
  97. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +2 -2
  98. package/dist/resources/extensions/gsd/tools/reopen-slice.js +2 -2
  99. package/dist/resources/extensions/gsd/tools/reopen-task.js +2 -2
  100. package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -2
  101. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +67 -2
  102. package/dist/resources/extensions/gsd/uat-policy.js +40 -15
  103. package/dist/resources/extensions/gsd/unit-context-composer.js +65 -0
  104. package/dist/resources/extensions/gsd/verdict-parser.js +1 -1
  105. package/dist/resources/extensions/gsd/verification-verdict.js +2 -1
  106. package/dist/resources/extensions/gsd/workflow-event-ledger.js +91 -0
  107. package/dist/resources/extensions/gsd/workflow-event-vocabulary.js +46 -0
  108. package/dist/resources/extensions/gsd/workflow-events.js +6 -18
  109. package/dist/resources/extensions/gsd/workflow-reconcile.js +21 -56
  110. package/dist/resources/extensions/gsd/worktree-lifecycle.js +3 -2
  111. package/dist/resources/extensions/gsd/worktree-manager.js +7 -1
  112. package/dist/resources/extensions/gsd/worktree.js +8 -1
  113. package/dist/resources/extensions/shared/gsd-browser-cli.js +45 -3
  114. package/dist/resources/shared/gsd-browser-path-sync.js +214 -0
  115. package/dist/resources/shared/package-manager-detection.js +1 -1
  116. package/dist/resources/shared/package.json +3 -0
  117. package/dist/resources/skills/create-skill/SKILL.md +3 -0
  118. package/dist/resources/skills/create-skill/references/skill-structure.md +1 -0
  119. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  120. package/dist/update-check.d.ts +2 -0
  121. package/dist/update-check.js +24 -1
  122. package/dist/update-cmd.js +20 -3
  123. package/dist/web/standalone/.next/BUILD_ID +1 -1
  124. package/dist/web/standalone/.next/app-path-routes-manifest.json +6 -6
  125. package/dist/web/standalone/.next/build-manifest.json +3 -3
  126. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  127. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  128. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  129. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  131. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  132. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  133. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  134. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  135. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  136. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  137. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  138. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  139. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  140. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  141. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  142. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  143. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  144. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/update/route.js.nft.json +1 -1
  146. package/dist/web/standalone/.next/server/app/index.html +1 -1
  147. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  148. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  149. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  150. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  151. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  152. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  153. package/dist/web/standalone/.next/server/app-paths-manifest.json +6 -6
  154. package/dist/web/standalone/.next/server/chunks/8357.js +2 -2
  155. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  156. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  158. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  159. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  160. package/dist/web/standalone/.next/static/chunks/{796.cf859a427a2cb2ac.js → 796.e0bdc932325d7e03.js} +1 -1
  161. package/dist/web/standalone/.next/static/chunks/{webpack-fbea77b5f9953368.js → webpack-f0285ce91d4ec9ef.js} +1 -1
  162. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  163. package/dist/web/standalone/node_modules/postcss/lib/container.js +26 -18
  164. package/dist/web/standalone/node_modules/postcss/lib/css-syntax-error.js +47 -14
  165. package/dist/web/standalone/node_modules/postcss/lib/declaration.js +4 -4
  166. package/dist/web/standalone/node_modules/postcss/lib/fromJSON.js +3 -3
  167. package/dist/web/standalone/node_modules/postcss/lib/input.js +54 -29
  168. package/dist/web/standalone/node_modules/postcss/lib/lazy-result.js +47 -37
  169. package/dist/web/standalone/node_modules/postcss/lib/map-generator.js +26 -9
  170. package/dist/web/standalone/node_modules/postcss/lib/no-work-result.js +57 -55
  171. package/dist/web/standalone/node_modules/postcss/lib/node.js +99 -31
  172. package/dist/web/standalone/node_modules/postcss/lib/parse.js +1 -1
  173. package/dist/web/standalone/node_modules/postcss/lib/parser.js +10 -9
  174. package/dist/web/standalone/node_modules/postcss/lib/postcss.js +12 -12
  175. package/dist/web/standalone/node_modules/postcss/lib/previous-map.js +30 -11
  176. package/dist/web/standalone/node_modules/postcss/lib/processor.js +7 -7
  177. package/dist/web/standalone/node_modules/postcss/lib/result.js +5 -5
  178. package/dist/web/standalone/node_modules/postcss/lib/rule.js +6 -6
  179. package/dist/web/standalone/node_modules/postcss/lib/stringifier.js +69 -28
  180. package/dist/web/standalone/node_modules/postcss/lib/tokenize.js +6 -2
  181. package/dist/web/standalone/node_modules/postcss/package.json +48 -48
  182. package/package.json +2 -2
  183. package/packages/cloud-mcp-gateway/package.json +2 -2
  184. package/packages/contracts/dist/rpc.d.ts +1 -0
  185. package/packages/contracts/dist/rpc.d.ts.map +1 -1
  186. package/packages/contracts/dist/rpc.js.map +1 -1
  187. package/packages/contracts/package.json +1 -1
  188. package/packages/daemon/package.json +4 -4
  189. package/packages/gsd-agent-core/package.json +5 -5
  190. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +5 -0
  191. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  192. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +5 -0
  193. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  194. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  195. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +7 -0
  196. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  197. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  198. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +8 -1
  199. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  200. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.d.ts.map +1 -1
  201. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js +11 -1
  202. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js.map +1 -1
  203. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
  204. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +4 -4
  205. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
  206. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  207. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +3 -1
  208. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
  209. package/packages/gsd-agent-modes/package.json +7 -7
  210. package/packages/mcp-server/dist/cli.js +10 -5
  211. package/packages/mcp-server/dist/cli.js.map +1 -1
  212. package/packages/mcp-server/dist/moonshot-tool-schema.d.ts +29 -0
  213. package/packages/mcp-server/dist/moonshot-tool-schema.d.ts.map +1 -0
  214. package/packages/mcp-server/dist/moonshot-tool-schema.js +50 -0
  215. package/packages/mcp-server/dist/moonshot-tool-schema.js.map +1 -0
  216. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  217. package/packages/mcp-server/dist/server.js +4 -0
  218. package/packages/mcp-server/dist/server.js.map +1 -1
  219. package/packages/mcp-server/dist/workflow-tools.d.ts +18 -18
  220. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  221. package/packages/mcp-server/dist/workflow-tools.js +99 -38
  222. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  223. package/packages/mcp-server/package.json +5 -4
  224. package/packages/native/package.json +1 -1
  225. package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts +1 -0
  226. package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts.map +1 -1
  227. package/packages/pi-agent-core/dist/harness/env/nodejs.js +34 -3
  228. package/packages/pi-agent-core/dist/harness/env/nodejs.js.map +1 -1
  229. package/packages/pi-agent-core/dist/index.d.ts +1 -0
  230. package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
  231. package/packages/pi-agent-core/dist/index.js +3 -0
  232. package/packages/pi-agent-core/dist/index.js.map +1 -1
  233. package/packages/pi-agent-core/package.json +1 -1
  234. package/packages/pi-ai/README.md +1 -0
  235. package/packages/pi-ai/dist/image-models.generated.d.ts +2 -2
  236. package/packages/pi-ai/dist/image-models.generated.js +6 -6
  237. package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
  238. package/packages/pi-ai/dist/index.d.ts +2 -0
  239. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  240. package/packages/pi-ai/dist/index.js +2 -0
  241. package/packages/pi-ai/dist/index.js.map +1 -1
  242. package/packages/pi-ai/dist/models.generated.d.ts +419 -221
  243. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  244. package/packages/pi-ai/dist/models.generated.js +460 -261
  245. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  246. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  247. package/packages/pi-ai/dist/providers/anthropic.js +12 -7
  248. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  249. package/packages/pi-ai/dist/providers/google-shared.d.ts +5 -0
  250. package/packages/pi-ai/dist/providers/google-shared.d.ts.map +1 -1
  251. package/packages/pi-ai/dist/providers/google-shared.js +12 -3
  252. package/packages/pi-ai/dist/providers/google-shared.js.map +1 -1
  253. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  254. package/packages/pi-ai/dist/providers/openai-completions.js +7 -3
  255. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  256. package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts +9 -0
  257. package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts.map +1 -0
  258. package/packages/pi-ai/dist/utils/moonshot-tool-schema.js +34 -0
  259. package/packages/pi-ai/dist/utils/moonshot-tool-schema.js.map +1 -0
  260. package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
  261. package/packages/pi-ai/dist/utils/oauth/github-copilot.js +6 -2
  262. package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
  263. package/packages/pi-ai/package.json +3 -2
  264. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +2 -2
  265. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  266. package/packages/pi-coding-agent/dist/core/auth-storage.js +19 -13
  267. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  268. package/packages/pi-coding-agent/dist/core/provider-readiness.d.ts.map +1 -1
  269. package/packages/pi-coding-agent/dist/core/provider-readiness.js +13 -6
  270. package/packages/pi-coding-agent/dist/core/provider-readiness.js.map +1 -1
  271. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts +11 -0
  272. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
  273. package/packages/pi-coding-agent/dist/core/tools/bash.js +53 -11
  274. package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
  275. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  276. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  277. package/packages/pi-coding-agent/dist/index.js +1 -1
  278. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  279. package/packages/pi-coding-agent/dist/utils/shell.d.ts +28 -2
  280. package/packages/pi-coding-agent/dist/utils/shell.d.ts.map +1 -1
  281. package/packages/pi-coding-agent/dist/utils/shell.js +56 -10
  282. package/packages/pi-coding-agent/dist/utils/shell.js.map +1 -1
  283. package/packages/pi-coding-agent/package.json +7 -7
  284. package/packages/pi-tui/package.json +2 -2
  285. package/packages/rpc-client/package.json +2 -2
  286. package/pkg/package.json +1 -1
  287. package/src/resources/GSD-WORKFLOW.md +5 -4
  288. package/src/resources/extensions/async-jobs/async-bash-cancel.test.ts +360 -0
  289. package/src/resources/extensions/async-jobs/async-bash-tool.ts +33 -56
  290. package/src/resources/extensions/async-jobs/await-tool.test.ts +139 -0
  291. package/src/resources/extensions/async-jobs/await-tool.ts +82 -12
  292. package/src/resources/extensions/async-jobs/index.ts +79 -0
  293. package/src/resources/extensions/async-jobs/job-manager.ts +21 -1
  294. package/src/resources/extensions/bg-shell/bg-shell-command.ts +6 -6
  295. package/src/resources/extensions/bg-shell/bg-shell-tool.ts +10 -6
  296. package/src/resources/extensions/bg-shell/overlay.ts +9 -5
  297. package/src/resources/extensions/bg-shell/process-manager.ts +50 -25
  298. package/src/resources/extensions/bg-shell/readiness-detector.ts +12 -0
  299. package/src/resources/extensions/bg-shell/tests/lifecycle-and-utilities.test.ts +48 -1
  300. package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +40 -1
  301. package/src/resources/extensions/gsd/auto/custom-verify-retry-store.ts +21 -3
  302. package/src/resources/extensions/gsd/auto/detect-stuck.ts +32 -9
  303. package/src/resources/extensions/gsd/auto/dispatch-history.ts +152 -0
  304. package/src/resources/extensions/gsd/auto/dispatch-key.ts +39 -0
  305. package/src/resources/extensions/gsd/auto/loop.ts +4 -1
  306. package/src/resources/extensions/gsd/auto/orchestrator.ts +98 -56
  307. package/src/resources/extensions/gsd/auto/phases.ts +65 -26
  308. package/src/resources/extensions/gsd/auto/session.ts +3 -0
  309. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +18 -48
  310. package/src/resources/extensions/gsd/auto-dispatch.ts +48 -61
  311. package/src/resources/extensions/gsd/auto-model-selection.ts +41 -12
  312. package/src/resources/extensions/gsd/auto-post-unit.ts +33 -12
  313. package/src/resources/extensions/gsd/auto-prompts.ts +115 -35
  314. package/src/resources/extensions/gsd/auto-start.ts +36 -18
  315. package/src/resources/extensions/gsd/auto-unit-closeout.ts +83 -28
  316. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +4 -4
  317. package/src/resources/extensions/gsd/auto-verification.ts +26 -28
  318. package/src/resources/extensions/gsd/auto-worktree.ts +14 -1
  319. package/src/resources/extensions/gsd/auto.ts +44 -1
  320. package/src/resources/extensions/gsd/blocked-models.ts +49 -0
  321. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +34 -5
  322. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +23 -6
  323. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -2
  324. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +163 -55
  325. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +350 -86
  326. package/src/resources/extensions/gsd/browser-daemon-auto-prep.ts +108 -0
  327. package/src/resources/extensions/gsd/closeout-wizard.ts +102 -0
  328. package/src/resources/extensions/gsd/commands/context.ts +16 -2
  329. package/src/resources/extensions/gsd/commands-handlers.ts +46 -3
  330. package/src/resources/extensions/gsd/consent-question.ts +431 -0
  331. package/src/resources/extensions/gsd/consent-verdict.ts +86 -0
  332. package/src/resources/extensions/gsd/constants.ts +0 -3
  333. package/src/resources/extensions/gsd/crash-recovery.ts +10 -2
  334. package/src/resources/extensions/gsd/db/queries.ts +37 -0
  335. package/src/resources/extensions/gsd/db-writer.ts +11 -19
  336. package/src/resources/extensions/gsd/dispatch-guard.ts +8 -31
  337. package/src/resources/extensions/gsd/doctor-engine-checks.ts +5 -4
  338. package/src/resources/extensions/gsd/doctor-git-checks.ts +2 -19
  339. package/src/resources/extensions/gsd/engine-hook-contract.ts +79 -0
  340. package/src/resources/extensions/gsd/exec-sandbox.ts +49 -9
  341. package/src/resources/extensions/gsd/files.ts +33 -12
  342. package/src/resources/extensions/gsd/gsd-command-home.ts +13 -3
  343. package/src/resources/extensions/gsd/gsd-db.ts +4 -3
  344. package/src/resources/extensions/gsd/guidance.ts +78 -0
  345. package/src/resources/extensions/gsd/guided-flow.ts +21 -26
  346. package/src/resources/extensions/gsd/markdown-renderer.ts +11 -0
  347. package/src/resources/extensions/gsd/milestone-closeout.ts +109 -24
  348. package/src/resources/extensions/gsd/milestone-planning-persistence.ts +2 -2
  349. package/src/resources/extensions/gsd/milestone-reopen-events.ts +3 -6
  350. package/src/resources/extensions/gsd/parsers-legacy.ts +16 -4
  351. package/src/resources/extensions/gsd/preferences-models.ts +2 -1
  352. package/src/resources/extensions/gsd/projection-flush.ts +20 -0
  353. package/src/resources/extensions/gsd/prompts/complete-slice.md +3 -3
  354. package/src/resources/extensions/gsd/prompts/execute-task.md +1 -1
  355. package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  356. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  357. package/src/resources/extensions/gsd/prompts/quick-task.md +1 -1
  358. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  359. package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  360. package/src/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  361. package/src/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  362. package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
  363. package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  364. package/src/resources/extensions/gsd/prompts/run-uat.md +7 -5
  365. package/src/resources/extensions/gsd/prompts/system.md +5 -2
  366. package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -1
  367. package/src/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
  368. package/src/resources/extensions/gsd/reactive-graph.ts +11 -1
  369. package/src/resources/extensions/gsd/roadmap-slices.ts +28 -3
  370. package/src/resources/extensions/gsd/safety/destructive-confirmation.ts +134 -0
  371. package/src/resources/extensions/gsd/session-lock.ts +1 -1
  372. package/src/resources/extensions/gsd/state.ts +5 -0
  373. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +97 -1
  374. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +198 -26
  375. package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +65 -3
  376. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +236 -0
  377. package/src/resources/extensions/gsd/tests/blocked-models.test.ts +19 -0
  378. package/src/resources/extensions/gsd/tests/browser-daemon-auto-prep.test.ts +144 -0
  379. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
  380. package/src/resources/extensions/gsd/tests/consent-question.test.ts +351 -0
  381. package/src/resources/extensions/gsd/tests/custom-verify-retry-store.test.ts +67 -0
  382. package/src/resources/extensions/gsd/tests/db-writer.test.ts +15 -4
  383. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +10 -10
  384. package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +303 -0
  385. package/src/resources/extensions/gsd/tests/discuss-routing-fixes.test.ts +12 -2
  386. package/src/resources/extensions/gsd/tests/dispatch-history.test.ts +273 -0
  387. package/src/resources/extensions/gsd/tests/doctor-git-checks-terminal.test.ts +73 -0
  388. package/src/resources/extensions/gsd/tests/dynamic-bash-no-cap.test.ts +132 -0
  389. package/src/resources/extensions/gsd/tests/engine-hook-contract.test.ts +148 -0
  390. package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +193 -0
  391. package/src/resources/extensions/gsd/tests/exec-tool.test.ts +29 -1
  392. package/src/resources/extensions/gsd/tests/gsd-command-home.test.ts +120 -0
  393. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +27 -0
  394. package/src/resources/extensions/gsd/tests/guidance.test.ts +23 -0
  395. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +2 -6
  396. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +199 -0
  397. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +3 -1
  398. package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +95 -4
  399. package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +32 -1
  400. package/src/resources/extensions/gsd/tests/oauth-api-model-routing.test.ts +167 -0
  401. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +18 -0
  402. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +138 -0
  403. package/src/resources/extensions/gsd/tests/phases-terminal-complete-idempotent.test.ts +242 -0
  404. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +63 -2
  405. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +124 -6
  406. package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +68 -0
  407. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +19 -1
  408. package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +17 -0
  409. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +41 -0
  410. package/src/resources/extensions/gsd/tests/tool-unavailable-retry.test.ts +33 -0
  411. package/src/resources/extensions/gsd/tests/transport-gate-double-complete.test.ts +139 -0
  412. package/src/resources/extensions/gsd/tests/uat-policy.test.ts +88 -0
  413. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +44 -0
  414. package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +8 -0
  415. package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +2 -0
  416. package/src/resources/extensions/gsd/tests/workflow-events.test.ts +19 -0
  417. package/src/resources/extensions/gsd/tests/workflow-reconcile.test.ts +20 -0
  418. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +273 -38
  419. package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +22 -0
  420. package/src/resources/extensions/gsd/tests/worktree.test.ts +18 -0
  421. package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +358 -0
  422. package/src/resources/extensions/gsd/tests/write-gate.test.ts +67 -1
  423. package/src/resources/extensions/gsd/tool-contract.ts +38 -3
  424. package/src/resources/extensions/gsd/tool-presentation-plan.ts +4 -4
  425. package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
  426. package/src/resources/extensions/gsd/tools/complete-slice.ts +22 -12
  427. package/src/resources/extensions/gsd/tools/complete-task.ts +3 -2
  428. package/src/resources/extensions/gsd/tools/exec-tool.ts +4 -0
  429. package/src/resources/extensions/gsd/tools/plan-slice.ts +2 -2
  430. package/src/resources/extensions/gsd/tools/plan-task.ts +2 -2
  431. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +2 -2
  432. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +2 -2
  433. package/src/resources/extensions/gsd/tools/reopen-slice.ts +2 -2
  434. package/src/resources/extensions/gsd/tools/reopen-task.ts +2 -2
  435. package/src/resources/extensions/gsd/tools/replan-slice.ts +2 -2
  436. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +81 -2
  437. package/src/resources/extensions/gsd/uat-policy.ts +60 -15
  438. package/src/resources/extensions/gsd/unit-context-composer.ts +99 -0
  439. package/src/resources/extensions/gsd/verdict-parser.ts +1 -1
  440. package/src/resources/extensions/gsd/verification-verdict.ts +4 -2
  441. package/src/resources/extensions/gsd/workflow-event-ledger.ts +131 -0
  442. package/src/resources/extensions/gsd/workflow-event-vocabulary.ts +59 -0
  443. package/src/resources/extensions/gsd/workflow-events.ts +12 -20
  444. package/src/resources/extensions/gsd/workflow-reconcile.ts +29 -62
  445. package/src/resources/extensions/gsd/worktree-lifecycle.ts +3 -8
  446. package/src/resources/extensions/gsd/worktree-manager.ts +6 -1
  447. package/src/resources/extensions/gsd/worktree.ts +7 -1
  448. package/src/resources/extensions/shared/gsd-browser-cli.ts +54 -3
  449. package/src/resources/shared/gsd-browser-path-sync.ts +273 -0
  450. package/src/resources/shared/package-manager-detection.ts +1 -1
  451. package/src/resources/shared/package.json +3 -0
  452. package/src/resources/skills/create-skill/SKILL.md +3 -0
  453. package/src/resources/skills/create-skill/references/skill-structure.md +1 -0
  454. package/dist/resources/extensions/gsd/user-input-boundary.js +0 -218
  455. package/dist/resources/skills/gsd-browser/SKILL.md +0 -41
  456. package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +0 -173
  457. package/src/resources/extensions/gsd/user-input-boundary.ts +0 -216
  458. package/src/resources/skills/gsd-browser/SKILL.md +0 -41
  459. /package/dist/web/standalone/.next/static/{AOpDeK_gJHU8OZjRo31gQ → FBNo5cT_chy7YNoAQsU3o}/_buildManifest.js +0 -0
  460. /package/dist/web/standalone/.next/static/{AOpDeK_gJHU8OZjRo31gQ → FBNo5cT_chy7YNoAQsU3o}/_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,
@@ -57,7 +58,11 @@ import { debugLog } from "./debug-logger.js";
57
58
  import { buildSkillActivationBlock, buildSkillDiscoveryVars } from "./skill-activation.js";
58
59
  import { findMilestoneIds } from "./milestone-ids.js";
59
60
  import { buildRunUatPresentationForType, RUN_UAT_TOOL_PRESENTATION_PLAN_ID } from "./tool-presentation-plan.js";
60
- import { resolveEffectiveUatType, shouldDispatchUatForContent, type UatType } from "./uat-policy.js";
61
+ import {
62
+ classifyUatContentForRun,
63
+ shouldDispatchUatForContent,
64
+ type UatType,
65
+ } from "./uat-policy.js";
61
66
  import { buildWebAppUatGuidanceBlock } from "./web-app-uat.js";
62
67
 
63
68
  export { buildSkillActivationBlock, buildSkillDiscoveryVars };
@@ -292,10 +297,12 @@ function prependContextModeToBlock(
292
297
  block: string,
293
298
  renderMode: ContextModeRenderMode = "standalone",
294
299
  ): string {
300
+ const toolSurface = composeToolSurfaceInstructions(unitType, { renderMode });
295
301
  const contextMode = renderContextModeBlockForPrompt(unitType, base, renderMode);
296
- if (!contextMode) return block;
297
- if (!block.trim()) return contextMode;
298
- return `${contextMode}\n\n${block}`;
302
+ const guidance = [toolSurface, contextMode].filter(Boolean).join("\n\n");
303
+ if (!guidance) return block;
304
+ if (!block.trim()) return guidance;
305
+ return `${guidance}\n\n${block}`;
299
306
  }
300
307
 
301
308
  function requireUnitPromptContextContract(unitType: string): UnitPromptContextContract {
@@ -969,7 +976,7 @@ export async function inlineDecisionsFromDb(
969
976
 
970
977
  /**
971
978
  * Inline requirements with optional milestone and slice scoping from the DB.
972
- * Falls back to filesystem via inlineGsdRootFile when DB unavailable or empty.
979
+ * Falls back to filesystem via inlineGsdRootFile only when DB is unavailable.
973
980
  */
974
981
  export async function inlineRequirementsFromDb(
975
982
  base: string, milestoneId?: string, sliceId?: string, level?: InlineLevel,
@@ -979,14 +986,28 @@ export async function inlineRequirementsFromDb(
979
986
  const { isDbAvailable } = await import("./gsd-db.js");
980
987
  if (isDbAvailable()) {
981
988
  const { queryRequirements, formatRequirementsForPrompt } = await import("./context-store.js");
982
- const requirements = queryRequirements({ milestoneId, sliceId });
989
+ let requirements = queryRequirements({ milestoneId, sliceId });
990
+ let broadenedScope = false;
991
+ if (requirements.length === 0 && sliceId) {
992
+ requirements = queryRequirements({ milestoneId });
993
+ broadenedScope = true;
994
+ }
995
+ if (requirements.length === 0 && milestoneId) {
996
+ requirements = queryRequirements({ status: "active" });
997
+ broadenedScope = true;
998
+ }
983
999
  if (requirements.length > 0) {
984
- // Use compact format for non-full levels to save ~40% tokens
985
- const formatted = inlineLevel !== "full"
1000
+ // Use compact format for non-full levels, milestone-scoped calls, and
1001
+ // any cascade stage that broadened past the originally requested scope —
1002
+ // a slice-scoped "full" call that fell through to the project-wide
1003
+ // active fallback must not format those rows as full requirements.
1004
+ const useCompact = inlineLevel !== "full" || !sliceId || broadenedScope;
1005
+ const formatted = useCompact
986
1006
  ? formatRequirementsCompact(requirements)
987
1007
  : formatRequirementsForPrompt(requirements);
988
1008
  return `### Requirements\nSource: \`.gsd/REQUIREMENTS.md\`\n\n${formatted}`;
989
1009
  }
1010
+ return null;
990
1011
  }
991
1012
  } catch (err) {
992
1013
  logWarning("prompt", `inlineRequirementsFromDb failed: ${err instanceof Error ? err.message : String(err)}`);
@@ -1442,6 +1463,40 @@ export async function checkNeedsReassessment(
1442
1463
  * - No UAT file exists for the slice
1443
1464
  * - UAT result file already exists (idempotent — already ran)
1444
1465
  */
1466
+ /**
1467
+ * Resolve the effective UAT mode for the dispatch gate the same way
1468
+ * `buildRunUatPrompt` does: classify the UAT body with the slice's SUMMARY as
1469
+ * supplemental context, so a `browser-executable` UAT whose slice references a
1470
+ * self-contained harness (`npm run test:uat`, `search-uat.mjs`, `npx
1471
+ * playwright test`) is promoted to `runtime-executable` for the gate too.
1472
+ *
1473
+ * Without this, `checkNeedsRunUat` returns `browser-executable` while the
1474
+ * prompt instructs runtime-only execution, causing the dispatch gate to
1475
+ * require browser tools / warm up the browser daemon (or stop dispatch when
1476
+ * browser MCP is unavailable) for UAT runs that never touch the browser. See
1477
+ * cursor[bot] review on PR #696 for the M007/S01 regression.
1478
+ */
1479
+ async function resolveRunUatEffectiveType(
1480
+ base: string,
1481
+ mid: string,
1482
+ sliceId: string,
1483
+ uatContent: string,
1484
+ ): Promise<UatType> {
1485
+ let summaryContent = "";
1486
+ try {
1487
+ const summaryPath = resolveSliceFile(base, mid, sliceId, "SUMMARY");
1488
+ if (summaryPath) {
1489
+ summaryContent = (await loadFile(summaryPath)) ?? "";
1490
+ }
1491
+ } catch (err) {
1492
+ logWarning(
1493
+ "prompt",
1494
+ `resolveRunUatEffectiveType SUMMARY load failed: ${err instanceof Error ? err.message : String(err)}`,
1495
+ );
1496
+ }
1497
+ return classifyUatContentForRun(uatContent, summaryContent).effectiveType;
1498
+ }
1499
+
1445
1500
  export async function checkNeedsRunUat(
1446
1501
  base: string, mid: string, state: GSDState, prefs: GSDPreferences | undefined,
1447
1502
  ): Promise<{ sliceId: string; uatType: UatType } | null> {
@@ -1470,7 +1525,8 @@ export async function checkNeedsRunUat(
1470
1525
  if (assessmentContent && hasVerdict(assessmentContent)) continue;
1471
1526
  }
1472
1527
  if (!shouldDispatchUatForContent(uatContent, prefs)) continue;
1473
- return { sliceId: sid, uatType: resolveEffectiveUatType(uatContent) };
1528
+ const uatType = await resolveRunUatEffectiveType(base, mid, sid, uatContent);
1529
+ return { sliceId: sid, uatType };
1474
1530
  }
1475
1531
  return null;
1476
1532
  }
@@ -1503,7 +1559,8 @@ export async function checkNeedsRunUat(
1503
1559
  if (assessmentContentFb && hasVerdict(assessmentContentFb)) continue;
1504
1560
  }
1505
1561
  if (!shouldDispatchUatForContent(uatContentFb, prefs)) continue;
1506
- return { sliceId: uatSid, uatType: resolveEffectiveUatType(uatContentFb) };
1562
+ const uatType = await resolveRunUatEffectiveType(base, mid, uatSid, uatContentFb);
1563
+ return { sliceId: uatSid, uatType };
1507
1564
  }
1508
1565
  return null;
1509
1566
  }
@@ -3557,15 +3614,30 @@ export async function buildRunUatPrompt(
3557
3614
  null,
3558
3615
  cappedInlinedContext.length < rawInlinedContext.length ? `dropped ${rawInlinedContext.length - cappedInlinedContext.length} chars` : "within budget",
3559
3616
  );
3617
+ const uatPolicy = classifyUatContentForRun(uatContent, cappedInlinedContext);
3618
+ const uatType = uatPolicy.effectiveType;
3619
+ const runtimeHarnessOverride = uatPolicy.declaredType === "browser-executable" && uatType === "runtime-executable"
3620
+ ? [
3621
+ "## Runtime harness override",
3622
+ "",
3623
+ "This UAT declares `browser-executable` but the slice references a self-contained verification command (`npm run test:uat`, `search-uat.mjs`, or similar).",
3624
+ "Run **only** that command via `gsd_uat_exec` with `uat-runtime-check` intent.",
3625
+ "Do **not** call `uat-service-start`, do **not** run `npm run start`, `npm run test:server`, or any separate server command.",
3626
+ "Do **not** use `browser_navigate` or other `browser_*` tools — the harness already exercises the browser.",
3627
+ "When the harness exits 0, save **PASS** with `uatType: \"runtime-executable\"` (the effective mode above, not the UAT file header) and **runtime** check modes only.",
3628
+ "",
3629
+ ].join("\n")
3630
+ : "";
3560
3631
  const inlinedContext = prependContextModeToBlock(
3561
3632
  "run-uat",
3562
3633
  base,
3563
- cappedInlinedContext,
3634
+ runtimeHarnessOverride
3635
+ ? `${runtimeHarnessOverride}\n${cappedInlinedContext}`
3636
+ : cappedInlinedContext,
3564
3637
  );
3565
3638
  emitPromptContextTelemetry("run-uat", contextTelemetry, inlinedContext);
3566
3639
 
3567
3640
  const uatResultPath = join(base, relSliceFile(base, mid, sliceId, "ASSESSMENT"));
3568
- const uatType = resolveEffectiveUatType(uatContent);
3569
3641
  const canonicalPresentation = JSON.stringify(buildRunUatPresentationForType(uatType), null, 2);
3570
3642
 
3571
3643
  return loadPrompt("run-uat", {
@@ -3850,18 +3922,22 @@ export async function buildReactiveExecutePrompt(
3850
3922
  const inlinedTemplates = inlineTemplate("task-summary", "Task Summary");
3851
3923
  trackPromptContext(contextTelemetry, "templates", "inline", inlinedTemplates);
3852
3924
 
3853
- const prompt = loadPrompt("reactive-execute", {
3854
- workingDirectory: base,
3855
- milestoneId: mid,
3856
- milestoneTitle: midTitle,
3857
- sliceId: sid,
3858
- sliceTitle: sTitle,
3859
- graphContext: prependContextModeToBlock("reactive-execute", base, graphContext),
3860
- readyTaskCount: String(readyTaskIds.length),
3861
- readyTaskList: readyTaskListLines.join("\n"),
3862
- subagentPrompts: subagentSections.join("\n\n---\n\n"),
3863
- inlinedTemplates,
3864
- });
3925
+ const prompt = prependContextModeToBlock(
3926
+ "reactive-execute",
3927
+ base,
3928
+ loadPrompt("reactive-execute", {
3929
+ workingDirectory: base,
3930
+ milestoneId: mid,
3931
+ milestoneTitle: midTitle,
3932
+ sliceId: sid,
3933
+ sliceTitle: sTitle,
3934
+ graphContext,
3935
+ readyTaskCount: String(readyTaskIds.length),
3936
+ readyTaskList: readyTaskListLines.join("\n"),
3937
+ subagentPrompts: subagentSections.join("\n\n---\n\n"),
3938
+ inlinedTemplates,
3939
+ }),
3940
+ );
3865
3941
  emitPromptContextTelemetry("reactive-execute", contextTelemetry, prompt);
3866
3942
  return prompt;
3867
3943
  }
@@ -4040,17 +4116,21 @@ export async function buildGateEvaluatePrompt(
4040
4116
  ].join("\n"));
4041
4117
  }
4042
4118
 
4043
- return loadPrompt("gate-evaluate", {
4044
- workingDirectory: base,
4045
- milestoneId: mid,
4046
- milestoneTitle: midTitle,
4047
- sliceId: sid,
4048
- sliceTitle: sTitle,
4049
- slicePlanContent: prependContextModeToBlock("gate-evaluate", base, planContent),
4050
- gateCount: String(pending.length),
4051
- gateList: gateListLines.join("\n"),
4052
- subagentPrompts: subagentSections.join("\n\n---\n\n"),
4053
- });
4119
+ return prependContextModeToBlock(
4120
+ "gate-evaluate",
4121
+ base,
4122
+ loadPrompt("gate-evaluate", {
4123
+ workingDirectory: base,
4124
+ milestoneId: mid,
4125
+ milestoneTitle: midTitle,
4126
+ sliceId: sid,
4127
+ sliceTitle: sTitle,
4128
+ slicePlanContent: planContent,
4129
+ gateCount: String(pending.length),
4130
+ gateList: gateListLines.join("\n"),
4131
+ subagentPrompts: subagentSections.join("\n\n---\n\n"),
4132
+ }),
4133
+ );
4054
4134
  }
4055
4135
 
4056
4136
  export async function buildRewriteDocsPrompt(
@@ -28,6 +28,7 @@ import { ensureGsdSymlink, isInheritedRepo, validateProjectId } from "./repo-ide
28
28
  import { migrateToExternalState, recoverFailedMigration } from "./migrate-external.js";
29
29
  import { collectSecretsFromManifest } from "../get-secrets-from-user.js";
30
30
  import { gsdRoot, resolveMilestoneFile } from "./paths.js";
31
+ import { milestoneEntryBlockedGuidance } from "./guidance.js";
31
32
  import { invalidateAllCaches } from "./cache.js";
32
33
  import { writeLock, clearLock, readCrashLock, isLockProcessAlive } from "./crash-recovery.js";
33
34
  import {
@@ -994,12 +995,14 @@ export async function bootstrapAutoSession(
994
995
  // phase-specific planning model for a discuss turn (#2829).
995
996
  //
996
997
  // Precedence:
997
- // 1) Explicit session override via /gsd model (this session)
998
- // 2) Current session model from settings/session restore (if provider ready)
999
- // 3) GSD model preferences from PREFERENCES.md (validated against live auth)
998
+ // 1) Explicit session override via /gsd model or /gsd auto --model (this session)
999
+ // 2) GSD model preferences from PREFERENCES.md (validated against live auth)
1000
+ // 3) Current session model from settings/session restore (if provider ready)
1000
1001
  //
1001
- // This preserves #3517 defaults while honoring explicit runtime model
1002
- // selection for subsequent /gsd runs in the same session.
1002
+ // PREFERENCES.md wins over the ambient session default (#3517) so /gsd auto
1003
+ // does not stick on claude-code/claude-sonnet-4-6 when the user configured
1004
+ // models via /gsd workflow-preferences or PREFERENCES.md. Custom providers
1005
+ // still skip PREFERENCES.md entirely (#4122).
1003
1006
  //
1004
1007
  // Exception (#4122): when the session provider is a custom provider declared
1005
1008
  // in ~/.gsd/agent/models.json (Ollama, vLLM, OpenAI-compatible proxy, etc.),
@@ -1011,7 +1014,7 @@ export async function bootstrapAutoSession(
1011
1014
  const sessionProviderIsCustom = isCustomProvider(ctx.model?.provider);
1012
1015
  const preferredModel = sessionProviderIsCustom
1013
1016
  ? null
1014
- : resolveDefaultSessionModel(ctx.model?.provider);
1017
+ : resolveDefaultSessionModel(ctx.model?.provider, base);
1015
1018
  // Validate the preferred model against the live registry + provider auth so
1016
1019
  // an unconfigured PREFERENCES.md entry (no API key / OAuth) can't become the
1017
1020
  // start-model snapshot. Without this, every subsequent unit would try to
@@ -1041,8 +1044,8 @@ export async function bootstrapAutoSession(
1041
1044
  : null;
1042
1045
  const startThinkingSnapshot = pi.getThinkingLevel();
1043
1046
  const startModelSnapshot = manualSessionOverride
1044
- ?? currentSessionModel
1045
1047
  ?? validatedPreferredModel
1048
+ ?? currentSessionModel
1046
1049
  ?? null;
1047
1050
 
1048
1051
  try {
@@ -1268,11 +1271,29 @@ export async function bootstrapAutoSession(
1268
1271
  }
1269
1272
  }
1270
1273
 
1271
- const blockingStrandedRecoveryAction = state.activeMilestone
1272
- ? strandedRecoveryActions.find(
1274
+ const requestedMilestoneLock = process.env.GSD_MILESTONE_LOCK?.trim() || null;
1275
+ const lockedActiveMilestone =
1276
+ requestedMilestoneLock && state.activeMilestone?.id === requestedMilestoneLock;
1277
+ let blockingStrandedRecoveryAction: OrphanAuditAction | null;
1278
+ if (lockedActiveMilestone) {
1279
+ // Parallel worker or explicit `/gsd auto Mxxx`: sibling milestones'
1280
+ // stranded work must not block this milestone's resumption, and the
1281
+ // downstream `strandedRecoveryAction` (used for currentMilestoneId,
1282
+ // setActiveMilestoneId, and adoptStrandedMilestone) must be scoped to
1283
+ // the locked milestone only. Falling back to the first sibling action
1284
+ // would mis-target adoption (#742).
1285
+ const lockMatch = strandedRecoveryActions.find(
1286
+ (action) => action.milestoneId === requestedMilestoneLock,
1287
+ ) ?? null;
1288
+ blockingStrandedRecoveryAction = lockMatch;
1289
+ strandedRecoveryAction = lockMatch;
1290
+ } else if (state.activeMilestone) {
1291
+ blockingStrandedRecoveryAction = strandedRecoveryActions.find(
1273
1292
  (action) => action.milestoneId !== state.activeMilestone?.id,
1274
- ) ?? strandedRecoveryAction
1275
- : strandedRecoveryAction;
1293
+ ) ?? strandedRecoveryAction;
1294
+ } else {
1295
+ blockingStrandedRecoveryAction = strandedRecoveryAction;
1296
+ }
1276
1297
 
1277
1298
  if (blockingStrandedRecoveryAction) {
1278
1299
  if (!state.activeMilestone) {
@@ -1294,6 +1315,8 @@ export async function bootstrapAutoSession(
1294
1315
  formatStrandedWorkRecoveryMessage(strandedRecoveryAction),
1295
1316
  "info",
1296
1317
  );
1318
+ } else if (lockedActiveMilestone) {
1319
+ strandedRecoveryAction = null;
1297
1320
  }
1298
1321
 
1299
1322
  if (
@@ -1643,14 +1666,9 @@ export async function bootstrapAutoSession(
1643
1666
  `Cannot enter milestone ${s.currentMilestoneId}: lease is held by another worker.`,
1644
1667
  "error",
1645
1668
  );
1646
- } else if (enterResult.reason === "creation-failed") {
1647
- ctx.ui.notify(
1648
- `Cannot enter milestone ${s.currentMilestoneId}: worktree/branch creation failed. Isolation is degraded.`,
1649
- "error",
1650
- );
1651
- } else if (enterResult.reason === "isolation-degraded") {
1669
+ } else if (enterResult.reason === "creation-failed" || enterResult.reason === "isolation-degraded") {
1652
1670
  ctx.ui.notify(
1653
- `Cannot enter milestone ${s.currentMilestoneId}: isolation is degraded from a prior worktree failure. Close processes locking the worktree and retry, or run /gsd doctor fix.`,
1671
+ milestoneEntryBlockedGuidance(s.currentMilestoneId, enterResult.reason),
1654
1672
  "error",
1655
1673
  );
1656
1674
  } else if (enterResult.reason === "invalid-milestone-id") {
@@ -33,6 +33,24 @@ export interface UnitActivitySnapshot {
33
33
  assistantMessages: number;
34
34
  }
35
35
 
36
+ export interface AutoUnitCloseoutRequest {
37
+ ctx: ExtensionContext;
38
+ basePath: string;
39
+ unitType: string;
40
+ unitId: string;
41
+ startedAt: number;
42
+ opts?: CloseoutOptions;
43
+ }
44
+
45
+ export interface AutoUnitCloseoutResult {
46
+ activityFile?: string;
47
+ gitTransactionRecorded: boolean;
48
+ }
49
+
50
+ type GitTransactionCloseoutOptions =
51
+ Required<Pick<CloseoutOptions, "traceId" | "turnId" | "gitAction" | "gitStatus">>
52
+ & Pick<CloseoutOptions, "gitPush" | "gitError">;
53
+
36
54
  export const GHOST_COMPLETION_MAX_ELAPSED_MS = 500;
37
55
 
38
56
  export function snapshotUnitActivity(
@@ -76,25 +94,27 @@ export function isSuspiciousGhostCompletion(
76
94
  }
77
95
 
78
96
  /**
79
- * Snapshot metrics, save activity log, and fire-and-forget memory extraction
80
- * for a completed unit. Returns the activity log file path (if any).
97
+ * Snapshot metrics, save activity log, extract memories, and record the git
98
+ * transaction for a completed auto-mode unit.
81
99
  */
82
- export async function closeoutUnit(
83
- ctx: ExtensionContext,
84
- basePath: string,
85
- unitType: string,
86
- unitId: string,
87
- startedAt: number,
88
- opts?: CloseoutOptions,
89
- ): Promise<string | undefined> {
90
- const modelId = ctx.model?.id ?? "unknown";
91
- snapshotUnitMetrics(ctx, unitType, unitId, startedAt, modelId, opts);
92
- const activityFile = saveActivityLog(ctx, basePath, unitType, unitId);
100
+ export async function closeoutAutoUnit(
101
+ request: AutoUnitCloseoutRequest,
102
+ ): Promise<AutoUnitCloseoutResult> {
103
+ const modelId = request.ctx.model?.id ?? "unknown";
104
+ snapshotUnitMetrics(
105
+ request.ctx,
106
+ request.unitType,
107
+ request.unitId,
108
+ request.startedAt,
109
+ modelId,
110
+ request.opts,
111
+ );
112
+ const activityFile = saveActivityLog(request.ctx, request.basePath, request.unitType, request.unitId);
93
113
 
94
114
  if (activityFile) {
95
115
  try {
96
- const { buildMemoryLLMCall, extractMemoriesFromUnit } = await import('./memory-extractor.js');
97
- const llmCallFn = buildMemoryLLMCall(ctx);
116
+ const { buildMemoryLLMCall, extractMemoriesFromUnit } = await import("./memory-extractor.js");
117
+ const llmCallFn = buildMemoryLLMCall(request.ctx);
98
118
  if (llmCallFn) {
99
119
  // Awaited: a fire-and-forget here lets memory-extractor writes land in
100
120
  // .gsd/ after closeoutUnit returns but before the milestone merge
@@ -103,11 +123,11 @@ export async function closeoutUnit(
103
123
  // bounded by the extractor's LLM call, which is the acceptable price
104
124
  // for not racing the merge boundary.
105
125
  try {
106
- await extractMemoriesFromUnit(activityFile, unitType, unitId, llmCallFn);
126
+ await extractMemoriesFromUnit(activityFile, request.unitType, request.unitId, llmCallFn);
107
127
  } catch (err) {
108
128
  logWarning(
109
129
  "engine",
110
- `memory extraction failed for ${unitType}/${unitId}: ${(err as Error).message}`,
130
+ `memory extraction failed for ${request.unitType}/${request.unitId}: ${(err as Error).message}`,
111
131
  );
112
132
  }
113
133
  }
@@ -116,23 +136,58 @@ export async function closeoutUnit(
116
136
  }
117
137
  }
118
138
 
119
- if (opts?.traceId && opts.turnId && opts.gitAction && opts.gitStatus) {
139
+ const gitTransaction = resolveGitTransactionOptions(request.opts);
140
+
141
+ if (gitTransaction) {
120
142
  writeTurnGitTransaction({
121
- basePath,
122
- traceId: opts.traceId,
123
- turnId: opts.turnId,
124
- unitType,
125
- unitId,
143
+ basePath: request.basePath,
144
+ traceId: gitTransaction.traceId,
145
+ turnId: gitTransaction.turnId,
146
+ unitType: request.unitType,
147
+ unitId: request.unitId,
126
148
  stage: "record",
127
- action: opts.gitAction,
128
- push: opts.gitPush === true,
129
- status: opts.gitStatus,
130
- error: opts.gitError,
149
+ action: gitTransaction.gitAction,
150
+ push: gitTransaction.gitPush === true,
151
+ status: gitTransaction.gitStatus,
152
+ error: gitTransaction.gitError,
131
153
  metadata: {
132
154
  activityFile,
133
155
  },
134
156
  });
135
157
  }
136
158
 
137
- return activityFile ?? undefined;
159
+ return {
160
+ ...(activityFile ? { activityFile } : {}),
161
+ gitTransactionRecorded: Boolean(gitTransaction),
162
+ };
163
+ }
164
+
165
+ function resolveGitTransactionOptions(
166
+ opts: CloseoutOptions | undefined,
167
+ ): GitTransactionCloseoutOptions | null {
168
+ if (!opts?.traceId || !opts.turnId || !opts.gitAction || !opts.gitStatus) return null;
169
+ return {
170
+ traceId: opts.traceId,
171
+ turnId: opts.turnId,
172
+ gitAction: opts.gitAction,
173
+ gitStatus: opts.gitStatus,
174
+ gitPush: opts.gitPush,
175
+ gitError: opts.gitError,
176
+ };
177
+ }
178
+
179
+ /**
180
+ * Compatibility wrapper for existing auto-loop callers. New code should prefer
181
+ * closeoutAutoUnit so the closeout request and result stay explicit.
182
+ */
183
+ export async function closeoutUnit(
184
+ ctx: ExtensionContext,
185
+ basePath: string,
186
+ unitType: string,
187
+ unitId: string,
188
+ startedAt: number,
189
+ opts?: CloseoutOptions,
190
+ ): Promise<string | undefined> {
191
+ const result = await closeoutAutoUnit({ ctx, basePath, unitType, unitId, startedAt, opts });
192
+ return result.activityFile;
138
193
  }
@@ -5,10 +5,10 @@ import {
5
5
  } from "./unit-tool-contracts.js";
6
6
  import {
7
7
  WORKFLOW_TOOL_ALIAS_PAIRS,
8
- canonicalWorkflowSurfaceToolName,
9
8
  isWorkflowSurfaceAliasTool,
10
9
  stripMcpToolPrefix,
11
10
  } from "./workflow-tool-surface.js";
11
+ import { canonicalWorkflowToolName } from "./engine-hook-contract.js";
12
12
 
13
13
  export {
14
14
  AUTO_UNIT_SCOPED_TOOLS,
@@ -51,9 +51,9 @@ type AutoUnitToolScopeResult = {
51
51
  displayReason?: string;
52
52
  };
53
53
 
54
- export function canonicalWorkflowToolName(toolName: string): string {
55
- return canonicalWorkflowSurfaceToolName(toolName);
56
- }
54
+ // Normalizer seam lives in engine-hook-contract.ts; re-exported here for
55
+ // existing scope importers.
56
+ export { canonicalWorkflowToolName };
57
57
 
58
58
  export function isWorkflowAliasTool(toolName: string): boolean {
59
59
  return isWorkflowSurfaceAliasTool(toolName);
@@ -15,7 +15,7 @@
15
15
 
16
16
  import type { ExtensionContext, ExtensionAPI } from "@gsd/pi-coding-agent";
17
17
  import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
18
- import { gsdProjectionRoot, resolveSliceFile, resolveSlicePath, resolveMilestoneFile } from "./paths.js";
18
+ import { gsdProjectionRoot, resolveSliceFile, resolveSlicePath } from "./paths.js";
19
19
  import { resolveMilestoneValidationVerdict } from "./milestone-validation-verdict.js";
20
20
  import { resolveCanonicalMilestoneRoot } from "./worktree-manager.js";
21
21
  import { parseUnitId } from "./unit-id.js";
@@ -25,8 +25,6 @@ import { loadEffectiveGSDPreferences } from "./preferences.js";
25
25
  import type { GSDPreferences } from "./preferences-types.js";
26
26
  import { isClosedStatus } from "./status-guards.js";
27
27
  import { loadFile } from "./files.js";
28
- import { parseRoadmap } from "./parsers-legacy.js";
29
- import { isMilestoneComplete } from "./state.js";
30
28
  import {
31
29
  runVerificationGate,
32
30
  runVerificationGateForTargets,
@@ -52,6 +50,7 @@ import { getSlice } from "./gsd-db.js";
52
50
  import { getLedger } from "./metrics.js";
53
51
  import { getUnitCostSpikeAction, resolveUnitCostSpikeMultiplier } from "./auto-budget.js";
54
52
  import { formatPostUnitStatusCard } from "./auto-status-message.js";
53
+ import { detectWebApp } from "./web-app-uat.js";
55
54
 
56
55
  export interface VerificationContext {
57
56
  s: AutoSession;
@@ -373,29 +372,13 @@ async function runValidateMilestonePostCheck(
373
372
  * DB-backed projects are authoritative (#4094 peer review); falls back to
374
373
  * roadmap parsing only when the DB is unavailable.
375
374
  */
376
- async function countIncompleteSlices(basePath: string, milestoneId: string): Promise<number> {
377
- if (isDbAvailable()) {
378
- const slices = getMilestoneSlices(milestoneId);
379
- if (slices.length === 0) {
380
- // No DB rows — treat as "unknown", do not pause.
381
- return 1;
382
- }
383
- return slices.filter((slice) => !isClosedStatus(slice.status)).length;
384
- }
385
-
386
- // Filesystem fallback: parse the roadmap markdown.
387
- try {
388
- const roadmapFile = resolveMilestoneFile(basePath, milestoneId, "ROADMAP");
389
- if (!roadmapFile) return 1;
390
- const roadmapContent = await loadFile(roadmapFile);
391
- if (!roadmapContent) return 1;
392
- const roadmap = parseRoadmap(roadmapContent);
393
- if (roadmap.slices.length === 0) return 1;
394
- return isMilestoneComplete(roadmap) ? 0 : 1;
395
- } catch {
396
- // Parsing failures should not cause false-positive pauses.
397
- return 1;
398
- }
375
+ async function countIncompleteSlices(_basePath: string, milestoneId: string): Promise<number> {
376
+ // DB-authoritative (ADR-017): no markdown fallback. DB unavailable or no
377
+ // rows means "unknown" — do not pause.
378
+ if (!isDbAvailable()) return 1;
379
+ const slices = getMilestoneSlices(milestoneId);
380
+ if (slices.length === 0) return 1;
381
+ return slices.filter((slice) => !isClosedStatus(slice.status)).length;
399
382
  }
400
383
 
401
384
  /**
@@ -805,17 +788,32 @@ export async function runPostUnitVerification(
805
788
  s.verificationRetryFailureHashes.delete(retryKey);
806
789
  s.pendingVerificationRetry = null;
807
790
  return "continue";
791
+ } else if (
792
+ verdict.reason === "no-host-checks" &&
793
+ taskAlreadyComplete &&
794
+ detectWebApp(s.basePath) &&
795
+ !result.runtimeErrors?.some((e) => e.blocking)
796
+ ) {
797
+ s.verificationRetryCount.delete(retryKey);
798
+ s.verificationRetryFailureHashes.delete(retryKey);
799
+ s.pendingVerificationRetry = null;
800
+ ctx.ui.notify(
801
+ "No task-level host verification command was found for a completed browser-facing task; continuing so slice UAT can verify the UI with browser tools.",
802
+ "warning",
803
+ );
804
+ return "continue";
808
805
  } else if (verdict.reason === "no-host-checks") {
809
806
  s.verificationRetryCount.delete(retryKey);
810
807
  s.verificationRetryFailureHashes.delete(retryKey);
811
808
  s.pendingVerificationRetry = null;
809
+ const pauseMessage = `Verification failed: ${verdict.failureContext}`;
812
810
  ctx.ui.notify(
813
- "Verification gate FAILED — no runnable host-owned verification checks were discovered. Pausing for human review.",
811
+ `Verification gate FAILED — ${verdict.failureContext}`,
814
812
  "error",
815
813
  );
816
814
  process.stderr.write(`verification-gate: ${verdict.failureContext}\n`);
817
815
  await pauseAuto(ctx, pi, {
818
- message: "Verification failed: no runnable host-owned verification checks were discovered.",
816
+ message: pauseMessage,
819
817
  category: "unknown",
820
818
  });
821
819
  return "pause";
@@ -972,6 +972,14 @@ function _resolveIntegrationBranchForReuse(
972
972
  }
973
973
  }
974
974
 
975
+ function safeCwd(fallback: string): string {
976
+ try {
977
+ return process.cwd();
978
+ } catch {
979
+ return fallback;
980
+ }
981
+ }
982
+
975
983
  /**
976
984
  * When reusing an existing milestone branch, fast-forward it onto the
977
985
  * integration branch when that's safe (branch is a strict ancestor of
@@ -1155,7 +1163,7 @@ export function teardownAutoWorktree(
1155
1163
 
1156
1164
  const branch = autoWorktreeBranch(milestoneId);
1157
1165
  const { preserveBranch = false, preserveWorktree = false } = opts;
1158
- const previousCwd = process.cwd();
1166
+ const previousCwd = safeCwd(originalBasePath);
1159
1167
 
1160
1168
  // Wrap the entire teardown body in a single try/finally so activeWorkspace
1161
1169
  // is ALWAYS cleared — even if process.chdir throws (e.g. originalBasePath
@@ -2229,6 +2237,11 @@ export function mergeMilestoneToMain(
2229
2237
  process.chdir(originalBasePath_);
2230
2238
  } catch (err) {
2231
2239
  logWarning("worktree", `chdir to project root after merge failed: ${err instanceof Error ? err.message : String(err)}`);
2240
+ debugLog("mergeMilestoneToMain", {
2241
+ phase: "post-merge-chdir-failed",
2242
+ target: originalBasePath_,
2243
+ error: err instanceof Error ? err.message : String(err),
2244
+ });
2232
2245
  }
2233
2246
  };
2234
2247