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

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 (424) 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 +14 -34
  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/GSD-WORKFLOW.md +5 -4
  11. package/dist/resources/extensions/async-jobs/async-bash-tool.js +30 -64
  12. package/dist/resources/extensions/async-jobs/await-tool.js +80 -12
  13. package/dist/resources/extensions/async-jobs/index.js +65 -0
  14. package/dist/resources/extensions/async-jobs/job-manager.js +12 -1
  15. package/dist/resources/extensions/bg-shell/bg-shell-command.js +6 -6
  16. package/dist/resources/extensions/bg-shell/bg-shell-tool.js +10 -7
  17. package/dist/resources/extensions/bg-shell/overlay.js +9 -6
  18. package/dist/resources/extensions/bg-shell/process-manager.js +54 -25
  19. package/dist/resources/extensions/bg-shell/readiness-detector.js +11 -0
  20. package/dist/resources/extensions/bg-shell/utilities.js +3 -0
  21. package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +209 -88
  22. package/dist/resources/extensions/browser-tools/engine/selection.js +73 -5
  23. package/dist/resources/extensions/browser-tools/index.js +69 -12
  24. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +30 -4
  25. package/dist/resources/extensions/gsd/auto/custom-verify-retry-store.js +17 -2
  26. package/dist/resources/extensions/gsd/auto/detect-stuck.js +33 -13
  27. package/dist/resources/extensions/gsd/auto/dispatch-history.js +105 -0
  28. package/dist/resources/extensions/gsd/auto/dispatch-key.js +37 -0
  29. package/dist/resources/extensions/gsd/auto/loop.js +4 -1
  30. package/dist/resources/extensions/gsd/auto/orchestrator.js +61 -44
  31. package/dist/resources/extensions/gsd/auto/phases.js +2 -2
  32. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +8 -32
  33. package/dist/resources/extensions/gsd/auto-dispatch.js +40 -57
  34. package/dist/resources/extensions/gsd/auto-model-selection.js +25 -6
  35. package/dist/resources/extensions/gsd/auto-post-unit.js +23 -8
  36. package/dist/resources/extensions/gsd/auto-prompts.js +81 -19
  37. package/dist/resources/extensions/gsd/auto-start.js +18 -15
  38. package/dist/resources/extensions/gsd/auto-tool-tracking.js +18 -0
  39. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +12 -20
  40. package/dist/resources/extensions/gsd/auto-verification.js +9 -28
  41. package/dist/resources/extensions/gsd/auto-worktree.js +30 -90
  42. package/dist/resources/extensions/gsd/auto.js +4 -13
  43. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +3 -2
  44. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +23 -6
  45. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +19 -0
  46. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +212 -48
  47. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +303 -77
  48. package/dist/resources/extensions/gsd/branch-patterns.js +2 -0
  49. package/dist/resources/extensions/gsd/browser-daemon-auto-prep.js +83 -0
  50. package/dist/resources/extensions/gsd/browser-evidence.js +8 -2
  51. package/dist/resources/extensions/gsd/captures.js +4 -6
  52. package/dist/resources/extensions/gsd/consent-question.js +337 -0
  53. package/dist/resources/extensions/gsd/consent-verdict.js +63 -0
  54. package/dist/resources/extensions/gsd/constants.js +0 -2
  55. package/dist/resources/extensions/gsd/crash-recovery.js +4 -12
  56. package/dist/resources/extensions/gsd/db/queries.js +26 -0
  57. package/dist/resources/extensions/gsd/dispatch-guard.js +10 -35
  58. package/dist/resources/extensions/gsd/doctor-environment.js +2 -6
  59. package/dist/resources/extensions/gsd/doctor-format.js +9 -6
  60. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +13 -15
  61. package/dist/resources/extensions/gsd/engine-hook-contract.js +70 -0
  62. package/dist/resources/extensions/gsd/error-classifier.js +9 -0
  63. package/dist/resources/extensions/gsd/exec-sandbox.js +30 -10
  64. package/dist/resources/extensions/gsd/files.js +33 -19
  65. package/dist/resources/extensions/gsd/guidance.js +158 -0
  66. package/dist/resources/extensions/gsd/guided-flow.js +17 -2
  67. package/dist/resources/extensions/gsd/markdown-renderer.js +10 -0
  68. package/dist/resources/extensions/gsd/mcp-filter.js +2 -19
  69. package/dist/resources/extensions/gsd/mcp-tool-name.js +5 -13
  70. package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +1 -1
  71. package/dist/resources/extensions/gsd/migrate/safety.js +4 -1
  72. package/dist/resources/extensions/gsd/milestone-closeout.js +13 -23
  73. package/dist/resources/extensions/gsd/notification-store.js +11 -4
  74. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +6 -4
  75. package/dist/resources/extensions/gsd/parsers-legacy.js +16 -4
  76. package/dist/resources/extensions/gsd/paths.js +27 -0
  77. package/dist/resources/extensions/gsd/pre-execution-checks.js +91 -3
  78. package/dist/resources/extensions/gsd/preferences-models.js +14 -48
  79. package/dist/resources/extensions/gsd/prompts/complete-slice.md +2 -2
  80. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  81. package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  82. package/dist/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  83. package/dist/resources/extensions/gsd/prompts/run-uat.md +6 -4
  84. package/dist/resources/extensions/gsd/prompts/system.md +5 -2
  85. package/dist/resources/extensions/gsd/provider-error-guidance.js +1 -5
  86. package/dist/resources/extensions/gsd/provider-switch-observer.js +1 -1
  87. package/dist/resources/extensions/gsd/publication.js +87 -0
  88. package/dist/resources/extensions/gsd/reactive-graph.js +8 -1
  89. package/dist/resources/extensions/gsd/recovery-classification.js +37 -94
  90. package/dist/resources/extensions/gsd/safety/destructive-confirmation.js +108 -0
  91. package/dist/resources/extensions/gsd/state.js +6 -20
  92. package/dist/resources/extensions/gsd/stop-notice.js +57 -0
  93. package/dist/resources/extensions/gsd/tool-presentation-plan.js +4 -4
  94. package/dist/resources/extensions/gsd/tool-surface-readiness.js +56 -0
  95. package/dist/resources/extensions/gsd/tools/complete-slice.js +20 -10
  96. package/dist/resources/extensions/gsd/tools/exec-tool.js +9 -7
  97. package/dist/resources/extensions/gsd/tools/plan-slice.js +12 -6
  98. package/dist/resources/extensions/gsd/uat-policy.js +42 -16
  99. package/dist/resources/extensions/gsd/unit-closeout.js +138 -0
  100. package/dist/resources/extensions/gsd/unit-context-composer.js +74 -1
  101. package/dist/resources/extensions/gsd/unit-context-manifest.js +4 -27
  102. package/dist/resources/extensions/gsd/unit-registry.js +337 -0
  103. package/dist/resources/extensions/gsd/unit-tool-contracts.js +9 -182
  104. package/dist/resources/extensions/gsd/verdict-parser.js +1 -1
  105. package/dist/resources/extensions/gsd/web-app-uat.js +45 -8
  106. package/dist/resources/extensions/gsd/workflow-tool-surface.js +1 -1
  107. package/dist/resources/extensions/gsd/worktree-git-recovery.js +15 -9
  108. package/dist/resources/extensions/gsd/worktree-lifecycle.js +3 -2
  109. package/dist/resources/extensions/gsd/worktree-root.js +11 -0
  110. package/dist/resources/extensions/gsd/worktree-session-state.js +4 -5
  111. package/dist/resources/extensions/search-the-web/native-search.js +5 -3
  112. package/dist/resources/extensions/shared/browser-contract.js +59 -0
  113. package/dist/resources/extensions/shared/gsd-browser-cli.js +96 -5
  114. package/dist/resources/shared/package.json +3 -0
  115. package/dist/resources/skills/create-skill/references/executable-code.md +1 -1
  116. package/dist/resources/skills/create-skill/workflows/add-reference.md +8 -3
  117. package/dist/resources/skills/create-skill/workflows/add-script.md +4 -2
  118. package/dist/resources/skills/create-skill/workflows/add-template.md +3 -1
  119. package/dist/resources/skills/create-skill/workflows/add-workflow.md +8 -3
  120. package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
  121. package/dist/resources/skills/create-skill/workflows/verify-skill.md +9 -4
  122. package/dist/resources/skills/spike-wrap-up/SKILL.md +9 -9
  123. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  124. package/dist/web/standalone/.next/BUILD_ID +1 -1
  125. package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
  126. package/dist/web/standalone/.next/build-manifest.json +3 -3
  127. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  128. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  129. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  130. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  131. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  132. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  133. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  134. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  135. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  136. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  137. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  138. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  139. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  140. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  141. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  142. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  143. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  144. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  145. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/update/route.js.nft.json +1 -1
  147. package/dist/web/standalone/.next/server/app/index.html +1 -1
  148. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  149. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  150. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  151. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  152. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  153. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  154. package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
  155. package/dist/web/standalone/.next/server/chunks/5124.js +1 -1
  156. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  157. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  158. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  160. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  161. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  162. package/dist/web/standalone/.next/static/chunks/{796.cf859a427a2cb2ac.js → 796.e0bdc932325d7e03.js} +1 -1
  163. package/dist/web/standalone/.next/static/chunks/{webpack-fbea77b5f9953368.js → webpack-f0285ce91d4ec9ef.js} +1 -1
  164. package/dist/web/standalone/package.json +1 -1
  165. package/dist/worktree-cli.js +3 -6
  166. package/dist/worktree-status-banner.js +7 -15
  167. package/package.json +1 -1
  168. package/packages/cloud-mcp-gateway/package.json +2 -2
  169. package/packages/contracts/dist/rpc.d.ts +1 -0
  170. package/packages/contracts/dist/rpc.d.ts.map +1 -1
  171. package/packages/contracts/dist/rpc.js.map +1 -1
  172. package/packages/contracts/dist/workflow.d.ts +4 -0
  173. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  174. package/packages/contracts/dist/workflow.js.map +1 -1
  175. package/packages/contracts/package.json +1 -1
  176. package/packages/daemon/package.json +4 -4
  177. package/packages/gsd-agent-core/package.json +5 -5
  178. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +5 -0
  179. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  180. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +5 -0
  181. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  182. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  183. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +7 -0
  184. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  185. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  186. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +8 -1
  187. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  188. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.d.ts.map +1 -1
  189. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js +11 -1
  190. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js.map +1 -1
  191. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
  192. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +4 -4
  193. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
  194. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  195. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +3 -1
  196. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
  197. package/packages/gsd-agent-modes/package.json +7 -7
  198. package/packages/mcp-server/dist/cli.js +6 -3
  199. package/packages/mcp-server/dist/cli.js.map +1 -1
  200. package/packages/mcp-server/dist/workflow-tools.d.ts +8 -0
  201. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  202. package/packages/mcp-server/dist/workflow-tools.js +17 -1
  203. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  204. package/packages/mcp-server/package.json +3 -3
  205. package/packages/native/package.json +1 -1
  206. package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts +1 -0
  207. package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts.map +1 -1
  208. package/packages/pi-agent-core/dist/harness/env/nodejs.js +34 -3
  209. package/packages/pi-agent-core/dist/harness/env/nodejs.js.map +1 -1
  210. package/packages/pi-agent-core/dist/index.d.ts +1 -0
  211. package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
  212. package/packages/pi-agent-core/dist/index.js +3 -0
  213. package/packages/pi-agent-core/dist/index.js.map +1 -1
  214. package/packages/pi-agent-core/package.json +1 -1
  215. package/packages/pi-ai/README.md +1 -0
  216. package/packages/pi-ai/dist/image-models.generated.d.ts +2 -2
  217. package/packages/pi-ai/dist/image-models.generated.js +6 -6
  218. package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
  219. package/packages/pi-ai/dist/models.generated.d.ts +35 -125
  220. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  221. package/packages/pi-ai/dist/models.generated.js +46 -120
  222. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  223. package/packages/pi-ai/package.json +3 -2
  224. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +2 -2
  225. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  226. package/packages/pi-coding-agent/dist/core/auth-storage.js +19 -13
  227. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  228. package/packages/pi-coding-agent/dist/core/provider-readiness.d.ts.map +1 -1
  229. package/packages/pi-coding-agent/dist/core/provider-readiness.js +13 -6
  230. package/packages/pi-coding-agent/dist/core/provider-readiness.js.map +1 -1
  231. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts +11 -0
  232. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
  233. package/packages/pi-coding-agent/dist/core/tools/bash.js +53 -11
  234. package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
  235. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  236. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  237. package/packages/pi-coding-agent/dist/index.js +1 -1
  238. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  239. package/packages/pi-coding-agent/dist/utils/shell.d.ts +28 -2
  240. package/packages/pi-coding-agent/dist/utils/shell.d.ts.map +1 -1
  241. package/packages/pi-coding-agent/dist/utils/shell.js +56 -10
  242. package/packages/pi-coding-agent/dist/utils/shell.js.map +1 -1
  243. package/packages/pi-coding-agent/package.json +7 -7
  244. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  245. package/packages/pi-tui/dist/tui.js +9 -0
  246. package/packages/pi-tui/dist/tui.js.map +1 -1
  247. package/packages/pi-tui/package.json +2 -2
  248. package/packages/rpc-client/package.json +2 -2
  249. package/pkg/package.json +1 -1
  250. package/src/resources/GSD-WORKFLOW.md +5 -4
  251. package/src/resources/extensions/async-jobs/async-bash-cancel.test.ts +360 -0
  252. package/src/resources/extensions/async-jobs/async-bash-tool.ts +33 -56
  253. package/src/resources/extensions/async-jobs/await-tool.test.ts +139 -0
  254. package/src/resources/extensions/async-jobs/await-tool.ts +82 -12
  255. package/src/resources/extensions/async-jobs/index.ts +79 -0
  256. package/src/resources/extensions/async-jobs/job-manager.ts +21 -1
  257. package/src/resources/extensions/bg-shell/bg-shell-command.ts +6 -6
  258. package/src/resources/extensions/bg-shell/bg-shell-tool.ts +10 -6
  259. package/src/resources/extensions/bg-shell/overlay.ts +9 -5
  260. package/src/resources/extensions/bg-shell/process-manager.ts +50 -25
  261. package/src/resources/extensions/bg-shell/readiness-detector.ts +12 -0
  262. package/src/resources/extensions/bg-shell/tests/lifecycle-and-utilities.test.ts +48 -1
  263. package/src/resources/extensions/bg-shell/utilities.ts +3 -0
  264. package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +265 -98
  265. package/src/resources/extensions/browser-tools/engine/selection.ts +90 -4
  266. package/src/resources/extensions/browser-tools/index.ts +71 -13
  267. package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +83 -13
  268. package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +29 -1
  269. package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +136 -0
  270. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +34 -4
  271. package/src/resources/extensions/gsd/auto/custom-verify-retry-store.ts +21 -3
  272. package/src/resources/extensions/gsd/auto/detect-stuck.ts +32 -9
  273. package/src/resources/extensions/gsd/auto/dispatch-history.ts +152 -0
  274. package/src/resources/extensions/gsd/auto/dispatch-key.ts +39 -0
  275. package/src/resources/extensions/gsd/auto/loop.ts +4 -1
  276. package/src/resources/extensions/gsd/auto/orchestrator.ts +70 -46
  277. package/src/resources/extensions/gsd/auto/phases.ts +2 -2
  278. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +8 -32
  279. package/src/resources/extensions/gsd/auto-dispatch.ts +38 -52
  280. package/src/resources/extensions/gsd/auto-model-selection.ts +25 -5
  281. package/src/resources/extensions/gsd/auto-post-unit.ts +25 -8
  282. package/src/resources/extensions/gsd/auto-prompts.ts +118 -35
  283. package/src/resources/extensions/gsd/auto-start.ts +18 -17
  284. package/src/resources/extensions/gsd/auto-tool-tracking.ts +19 -0
  285. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +14 -21
  286. package/src/resources/extensions/gsd/auto-verification.ts +8 -26
  287. package/src/resources/extensions/gsd/auto-worktree.ts +30 -93
  288. package/src/resources/extensions/gsd/auto.ts +8 -15
  289. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +3 -5
  290. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +23 -6
  291. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +24 -0
  292. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +251 -47
  293. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +352 -84
  294. package/src/resources/extensions/gsd/branch-patterns.ts +3 -0
  295. package/src/resources/extensions/gsd/browser-daemon-auto-prep.ts +108 -0
  296. package/src/resources/extensions/gsd/browser-evidence.ts +18 -2
  297. package/src/resources/extensions/gsd/captures.ts +4 -6
  298. package/src/resources/extensions/gsd/consent-question.ts +416 -0
  299. package/src/resources/extensions/gsd/consent-verdict.ts +86 -0
  300. package/src/resources/extensions/gsd/constants.ts +0 -3
  301. package/src/resources/extensions/gsd/crash-recovery.ts +3 -9
  302. package/src/resources/extensions/gsd/db/queries.ts +37 -0
  303. package/src/resources/extensions/gsd/dispatch-guard.ts +8 -31
  304. package/src/resources/extensions/gsd/doctor-environment.ts +2 -7
  305. package/src/resources/extensions/gsd/doctor-format.ts +12 -7
  306. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +13 -15
  307. package/src/resources/extensions/gsd/engine-hook-contract.ts +79 -0
  308. package/src/resources/extensions/gsd/error-classifier.ts +11 -0
  309. package/src/resources/extensions/gsd/exec-sandbox.ts +49 -9
  310. package/src/resources/extensions/gsd/files.ts +33 -12
  311. package/src/resources/extensions/gsd/guidance.ts +217 -0
  312. package/src/resources/extensions/gsd/guided-flow.ts +16 -2
  313. package/src/resources/extensions/gsd/markdown-renderer.ts +11 -0
  314. package/src/resources/extensions/gsd/mcp-filter.ts +2 -23
  315. package/src/resources/extensions/gsd/mcp-tool-name.ts +6 -11
  316. package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +1 -1
  317. package/src/resources/extensions/gsd/migrate/safety.ts +4 -1
  318. package/src/resources/extensions/gsd/milestone-closeout.ts +13 -23
  319. package/src/resources/extensions/gsd/notification-store.ts +26 -3
  320. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +6 -4
  321. package/src/resources/extensions/gsd/parsers-legacy.ts +16 -4
  322. package/src/resources/extensions/gsd/paths.ts +33 -0
  323. package/src/resources/extensions/gsd/pre-execution-checks.ts +109 -3
  324. package/src/resources/extensions/gsd/preferences-models.ts +12 -47
  325. package/src/resources/extensions/gsd/prompts/complete-slice.md +2 -2
  326. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  327. package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  328. package/src/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  329. package/src/resources/extensions/gsd/prompts/run-uat.md +6 -4
  330. package/src/resources/extensions/gsd/prompts/system.md +5 -2
  331. package/src/resources/extensions/gsd/provider-error-guidance.ts +4 -9
  332. package/src/resources/extensions/gsd/provider-switch-observer.ts +1 -1
  333. package/src/resources/extensions/gsd/publication.ts +122 -0
  334. package/src/resources/extensions/gsd/reactive-graph.ts +11 -1
  335. package/src/resources/extensions/gsd/recovery-classification.ts +42 -96
  336. package/src/resources/extensions/gsd/safety/destructive-confirmation.ts +134 -0
  337. package/src/resources/extensions/gsd/state.ts +9 -21
  338. package/src/resources/extensions/gsd/stop-notice.ts +75 -0
  339. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +22 -0
  340. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +101 -26
  341. package/src/resources/extensions/gsd/tests/browser-automation-contract-fixture.ts +39 -0
  342. package/src/resources/extensions/gsd/tests/browser-contract.test.ts +44 -0
  343. package/src/resources/extensions/gsd/tests/browser-daemon-auto-prep.test.ts +144 -0
  344. package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +66 -1
  345. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +22 -0
  346. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +8 -7
  347. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
  348. package/src/resources/extensions/gsd/tests/consent-question.test.ts +336 -0
  349. package/src/resources/extensions/gsd/tests/custom-verify-retry-store.test.ts +67 -0
  350. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +10 -10
  351. package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +303 -0
  352. package/src/resources/extensions/gsd/tests/dispatch-history.test.ts +273 -0
  353. package/src/resources/extensions/gsd/tests/dispatch-run-uat-browser-tools.test.ts +2 -1
  354. package/src/resources/extensions/gsd/tests/dynamic-bash-no-cap.test.ts +132 -0
  355. package/src/resources/extensions/gsd/tests/engine-hook-contract.test.ts +148 -0
  356. package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +193 -0
  357. package/src/resources/extensions/gsd/tests/exec-tool.test.ts +29 -1
  358. package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +35 -1
  359. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +27 -0
  360. package/src/resources/extensions/gsd/tests/guidance.test.ts +148 -0
  361. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +53 -11
  362. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +73 -58
  363. package/src/resources/extensions/gsd/tests/integration/gsd-integration-fixture.ts +80 -0
  364. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +199 -0
  365. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +3 -1
  366. package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +32 -1
  367. package/src/resources/extensions/gsd/tests/notification-store.test.ts +32 -0
  368. package/src/resources/extensions/gsd/tests/oauth-api-model-routing.test.ts +167 -0
  369. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +18 -0
  370. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +139 -0
  371. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +193 -1
  372. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +124 -6
  373. package/src/resources/extensions/gsd/tests/provider-error-guidance.test.ts +3 -3
  374. package/src/resources/extensions/gsd/tests/publication.test.ts +120 -0
  375. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +157 -0
  376. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +1 -0
  377. package/src/resources/extensions/gsd/tests/stop-notice.test.ts +70 -0
  378. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +76 -0
  379. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +8 -0
  380. package/src/resources/extensions/gsd/tests/tool-surface-readiness.test.ts +155 -0
  381. package/src/resources/extensions/gsd/tests/uat-policy.test.ts +112 -29
  382. package/src/resources/extensions/gsd/tests/unit-closeout.test.ts +209 -0
  383. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +67 -2
  384. package/src/resources/extensions/gsd/tests/unit-registry.test.ts +163 -0
  385. package/src/resources/extensions/gsd/tests/web-app-uat.test.ts +44 -1
  386. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -2
  387. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +2 -2
  388. package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +358 -0
  389. package/src/resources/extensions/gsd/tests/write-gate.test.ts +67 -1
  390. package/src/resources/extensions/gsd/tool-presentation-plan.ts +4 -4
  391. package/src/resources/extensions/gsd/tool-surface-readiness.ts +76 -0
  392. package/src/resources/extensions/gsd/tools/complete-slice.ts +20 -10
  393. package/src/resources/extensions/gsd/tools/exec-tool.ts +8 -7
  394. package/src/resources/extensions/gsd/tools/plan-slice.ts +12 -6
  395. package/src/resources/extensions/gsd/uat-policy.ts +62 -16
  396. package/src/resources/extensions/gsd/unit-closeout.ts +201 -0
  397. package/src/resources/extensions/gsd/unit-context-composer.ts +111 -1
  398. package/src/resources/extensions/gsd/unit-context-manifest.ts +4 -28
  399. package/src/resources/extensions/gsd/unit-registry.ts +412 -0
  400. package/src/resources/extensions/gsd/unit-tool-contracts.ts +27 -192
  401. package/src/resources/extensions/gsd/verdict-parser.ts +1 -1
  402. package/src/resources/extensions/gsd/web-app-uat.ts +51 -8
  403. package/src/resources/extensions/gsd/workflow-tool-surface.ts +4 -1
  404. package/src/resources/extensions/gsd/worktree-git-recovery.ts +15 -9
  405. package/src/resources/extensions/gsd/worktree-lifecycle.ts +3 -8
  406. package/src/resources/extensions/gsd/worktree-root.ts +12 -0
  407. package/src/resources/extensions/gsd/worktree-session-state.ts +3 -5
  408. package/src/resources/extensions/search-the-web/native-search.ts +5 -3
  409. package/src/resources/extensions/shared/browser-contract.ts +66 -0
  410. package/src/resources/extensions/shared/gsd-browser-cli.ts +119 -5
  411. package/src/resources/shared/package.json +3 -0
  412. package/src/resources/skills/create-skill/references/executable-code.md +1 -1
  413. package/src/resources/skills/create-skill/workflows/add-reference.md +8 -3
  414. package/src/resources/skills/create-skill/workflows/add-script.md +4 -2
  415. package/src/resources/skills/create-skill/workflows/add-template.md +3 -1
  416. package/src/resources/skills/create-skill/workflows/add-workflow.md +8 -3
  417. package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
  418. package/src/resources/skills/create-skill/workflows/verify-skill.md +9 -4
  419. package/src/resources/skills/spike-wrap-up/SKILL.md +9 -9
  420. package/dist/resources/extensions/gsd/user-input-boundary.js +0 -218
  421. package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +0 -173
  422. package/src/resources/extensions/gsd/user-input-boundary.ts +0 -216
  423. /package/dist/web/standalone/.next/static/{C24pqUd-aru-l0Dp0gLZP → jmTLg6xZmAuq_LIqKOxrH}/_buildManifest.js +0 -0
  424. /package/dist/web/standalone/.next/static/{C24pqUd-aru-l0Dp0gLZP → jmTLg6xZmAuq_LIqKOxrH}/_ssgManifest.js +0 -0
@@ -20,6 +20,8 @@ import { getUatBrowserToolSupportError, type UatType } from "./uat-policy.js";
20
20
  import {
21
21
  isDbAvailable,
22
22
  getMilestoneSlices,
23
+ getMilestoneSliceSummaries,
24
+ getClosedSliceIds,
23
25
  getPendingGatesForTurn,
24
26
  markPendingGatesOmittedForTurn,
25
27
  getMilestone,
@@ -47,7 +49,6 @@ import {
47
49
  buildTaskFileName,
48
50
  gsdProjectionRoot,
49
51
  } from "./paths.js";
50
- import { parseRoadmap } from "./parsers-legacy.js";
51
52
  import { validateArtifact } from "./schemas/validate.js";
52
53
  import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync, readdirSync } from "node:fs";
53
54
  import { logWarning, logError } from "./workflow-logger.js";
@@ -84,13 +85,18 @@ import { selectReactiveDispatchBatch } from "./uok/execution-graph.js";
84
85
  import { getMilestonePipelineVariant } from "./milestone-scope-classifier.js";
85
86
  import { EXECUTION_ENTRY_PHASES, hasFinalizedMilestoneContext } from "./uok/plan-v2.js";
86
87
  import { isAutoActive } from "./auto.js";
87
- import { markDepthVerified } from "./bootstrap/write-gate.js";
88
+ // Host adapter explicitly: auto-dispatch runs in the extension host, and the
89
+ // ambient write-gate exports env-sniff the adapter per call (they are reserved
90
+ // for the workflow MCP child's dynamic-import surface).
91
+ import { hostWriteGateAdapter } from "./bootstrap/write-gate.js";
88
92
  import { ensureWorkflowPreferencesCaptured } from "./planning-depth.js";
89
93
  import { MILESTONE_ID_RE } from "./milestone-ids.js";
90
94
  import {
91
95
  getWorkflowTransportSupportError,
92
96
  getRequiredWorkflowToolsForAutoUnit,
97
+ resolveWorkflowMcpProjectRoot,
93
98
  } from "./workflow-mcp.js";
99
+ import { prepareBrowserDaemonForUat } from "./browser-daemon-auto-prep.js";
94
100
  import {
95
101
  PROJECT_RESEARCH_INFLIGHT_MARKER,
96
102
  } from "./project-research-policy.js";
@@ -490,27 +496,12 @@ function persistSliceAssessmentBackfill(
490
496
  }
491
497
 
492
498
  function backfillMissingAssessmentsFromSummaries(basePath: string, mid: string): void {
493
- const completedSliceIds = new Set<string>();
494
- if (isDbAvailable()) {
495
- for (const slice of getMilestoneSlices(mid)) {
496
- if (slice.status === "complete" || slice.status === "done") {
497
- completedSliceIds.add(slice.id);
498
- }
499
- }
500
- } else {
501
- const roadmapFile = resolveMilestoneFile(basePath, mid, "ROADMAP");
502
- if (!roadmapFile) return;
503
- try {
504
- const roadmap = parseRoadmap(readFileSync(roadmapFile, "utf-8"));
505
- for (const slice of roadmap.slices) {
506
- if (slice.done) completedSliceIds.add(slice.id);
507
- }
508
- } catch {
509
- return;
510
- }
511
- }
512
-
513
- for (const sliceId of completedSliceIds) {
499
+ // DB-authoritative (ADR-017): no markdown fallback. Without DB rows there
500
+ // is nothing to backfill.
501
+ if (!isDbAvailable()) return;
502
+ // Canonical closed vocabulary (complete/done/skipped/closed) a skipped or
503
+ // closed slice with a SUMMARY gets the same assessment backfill treatment.
504
+ for (const sliceId of getClosedSliceIds(mid)) {
514
505
  const summaryPath = resolveSliceFile(basePath, mid, sliceId, "SUMMARY");
515
506
  if (!summaryPath || !existsSync(summaryPath)) continue;
516
507
 
@@ -696,7 +687,7 @@ export const DISPATCH_RULES: DispatchRule[] = [
696
687
  // deadlock. Deep planning is still user-driven even inside auto-mode,
697
688
  // so it must wait for explicit approval instead of taking this bypass.
698
689
  if (shouldBypassMilestoneDepthGateInAuto(prefs)) {
699
- markDepthVerified(mid, basePath);
690
+ hostWriteGateAdapter.markDepthVerified(mid, basePath);
700
691
  }
701
692
  return {
702
693
  action: "dispatch",
@@ -772,6 +763,16 @@ export const DISPATCH_RULES: DispatchRule[] = [
772
763
  if (browserToolError) {
773
764
  return { action: "stop" as const, reason: browserToolError, level: "warning" as const };
774
765
  }
766
+ const browserDaemonError = prepareBrowserDaemonForUat({
767
+ uatType,
768
+ sessionProvider,
769
+ sessionAuthMode,
770
+ sessionBaseUrl,
771
+ projectRoot: resolveWorkflowMcpProjectRoot(basePath),
772
+ });
773
+ if (browserDaemonError) {
774
+ return { action: "stop" as const, reason: browserDaemonError, level: "warning" as const };
775
+ }
775
776
 
776
777
  // Cap run-uat dispatch attempts to prevent infinite replay (#3624).
777
778
  // Check before incrementing so an exhausted counter cannot create a
@@ -808,23 +809,10 @@ export const DISPATCH_RULES: DispatchRule[] = [
808
809
  // Only applies when UAT dispatch is enabled
809
810
  if (!prefs?.uat_dispatch) return null;
810
811
 
811
- // DB-first: prefer closed slices from DB; fall back to ROADMAP on disk.
812
- let closedSliceIds: string[];
813
- if (isDbAvailable()) {
814
- closedSliceIds = getMilestoneSlices(mid)
815
- .filter(s => isClosedStatus(s.status))
816
- .map(s => s.id);
817
- } else {
818
- // Filesystem fallback for degraded / unmigrated projects.
819
- // `slice.done` in the parsed ROADMAP is the disk-level closed signal.
820
- const roadmapFile = resolveMilestoneFile(basePath, mid, "ROADMAP");
821
- const roadmapContent = roadmapFile ? await loadFile(roadmapFile) : null;
822
- if (!roadmapContent) return null;
823
- const roadmap = parseRoadmap(roadmapContent);
824
- closedSliceIds = roadmap.slices.filter(s => s.done).map(s => s.id);
825
- }
826
-
827
- for (const sliceId of closedSliceIds) {
812
+ // DB-authoritative (ADR-017): closed slices come from the DB only; the
813
+ // ROADMAP projection is never parsed for gate decisions.
814
+ if (!isDbAvailable()) return null;
815
+ for (const sliceId of getClosedSliceIds(mid)) {
828
816
  const result = await readUatGateVerdict(basePath, mid, sliceId);
829
817
  if (!result) continue;
830
818
  const { verdict, uatType } = result;
@@ -879,7 +867,7 @@ export const DISPATCH_RULES: DispatchRule[] = [
879
867
  // H6 fix (#4973): keep the non-deep auto-mode bypass, but do not
880
868
  // pre-verify deep planning's user-facing milestone approval gate.
881
869
  if (shouldBypassMilestoneDepthGateInAuto(prefs)) {
882
- markDepthVerified(mid, basePath);
870
+ hostWriteGateAdapter.markDepthVerified(mid, basePath);
883
871
  }
884
872
  return {
885
873
  action: "dispatch",
@@ -1050,7 +1038,7 @@ export const DISPATCH_RULES: DispatchRule[] = [
1050
1038
  // H6 fix (#4973): keep the non-deep auto-mode bypass, but do not
1051
1039
  // pre-verify deep planning's user-facing milestone approval gate.
1052
1040
  if (shouldBypassMilestoneDepthGateInAuto(prefs)) {
1053
- markDepthVerified(mid, basePath);
1041
+ hostWriteGateAdapter.markDepthVerified(mid, basePath);
1054
1042
  }
1055
1043
  return {
1056
1044
  action: "dispatch",
@@ -1128,13 +1116,11 @@ export const DISPATCH_RULES: DispatchRule[] = [
1128
1116
  // behavior.
1129
1117
  if (await getMilestonePipelineVariant(mid) === "trivial") return null;
1130
1118
 
1131
- // Load roadmap to find all slices
1132
- const roadmapFile =
1133
- resolveExistingExpectedArtifact("plan-milestone", mid, basePath) ??
1134
- resolveMilestoneFile(basePath, mid, "ROADMAP");
1135
- const roadmapContent = roadmapFile ? await loadFile(roadmapFile) : null;
1136
- if (!roadmapContent) return null;
1137
- const roadmap = parseRoadmap(roadmapContent);
1119
+ // DB-authoritative slice list (ADR-017): the ROADMAP projection is
1120
+ // never parsed for dispatch decisions. No DB / no rows → skip this rule.
1121
+ if (!isDbAvailable()) return null;
1122
+ const dbSlices = getMilestoneSliceSummaries(mid);
1123
+ if (dbSlices.length === 0) return null;
1138
1124
 
1139
1125
  // Find slices that need research (no RESEARCH file, dependencies done)
1140
1126
  const milestoneResearchFile =
@@ -1142,14 +1128,14 @@ export const DISPATCH_RULES: DispatchRule[] = [
1142
1128
  resolveMilestoneFile(basePath, mid, "RESEARCH");
1143
1129
  const researchReadySlices: Array<{ id: string; title: string }> = [];
1144
1130
 
1145
- for (const slice of roadmap.slices) {
1131
+ for (const slice of dbSlices) {
1146
1132
  if (slice.done) continue;
1147
1133
  // Skip S01 when milestone research exists
1148
1134
  if (milestoneResearchFile && slice.id === "S01") continue;
1149
1135
  // Skip if already has research
1150
1136
  if (resolveExistingExpectedArtifact("research-slice", `${mid}/${slice.id}`, basePath)) continue;
1151
1137
  // Skip if dependencies aren't done (check for SUMMARY files)
1152
- const depsComplete = (slice.depends ?? []).every((depId) =>
1138
+ const depsComplete = slice.depends.every((depId) =>
1153
1139
  !!resolveExistingExpectedArtifact("complete-slice", `${mid}/${depId}`, basePath),
1154
1140
  );
1155
1141
  if (!depsComplete) continue;
@@ -1041,16 +1041,36 @@ export function resolveModelId<T extends { id: string; provider: string }>(
1041
1041
  if (providerMatch) return providerMatch;
1042
1042
  }
1043
1043
 
1044
- // Prefer "anthropic" as the canonical provider for Anthropic models.
1045
- // Transport-specific tiebreaker (ADR-012): intentionally keys on provider,
1046
- // not api we want the plain Anthropic transport when multiple are available.
1047
- const anthropicMatch = candidates.find(m => m.provider === "anthropic");
1048
- if (anthropicMatch) return anthropicMatch;
1044
+ // Subscription/OAuth routes beat pay-per-token API when the same model ID
1045
+ // exists on multiple providers. Order matters — first match wins.
1046
+ for (const provider of BARE_ID_SUBSCRIPTION_PROVIDER_PRECEDENCE) {
1047
+ const match = candidates.find(m => m.provider === provider);
1048
+ if (match) return match;
1049
+ }
1049
1050
 
1050
1051
  // Fall back to first non-extension candidate, or any candidate
1051
1052
  return candidates.find(m => !EXTENSION_PROVIDERS.has(m.provider)) ?? candidates[0];
1052
1053
  }
1053
1054
 
1055
+ /**
1056
+ * When a bare model ID exists on multiple providers, prefer subscription/OAuth
1057
+ * routes over pay-per-token API keys. Matches PROVIDER_ROUTES in doctor-providers
1058
+ * but applies when *both* sides are authenticated.
1059
+ *
1060
+ * Order rationale:
1061
+ * - openai-codex before github-copilot: ChatGPT-native for shared GPT IDs
1062
+ * - google-gemini-cli before github-copilot: first-party Gemini CLI
1063
+ * - anthropic before github-copilot: first-party Claude API/OAuth over Copilot
1064
+ * - github-copilot before openai/google: Copilot OAuth over platform API keys
1065
+ */
1066
+ export const BARE_ID_SUBSCRIPTION_PROVIDER_PRECEDENCE = [
1067
+ "openai-codex",
1068
+ "google-gemini-cli",
1069
+ "anthropic",
1070
+ "github-copilot",
1071
+ "google-antigravity",
1072
+ ] as const;
1073
+
1054
1074
  /**
1055
1075
  * Flat-rate providers charge the same per request regardless of model.
1056
1076
  * Dynamic routing provides no cost benefit — it only degrades quality (#3453).
@@ -18,7 +18,7 @@ import { deriveState } from "./state.js";
18
18
  import { logWarning, logError } from "./workflow-logger.js";
19
19
  import { loadFile, parseSummary, resolveAllOverrides } from "./files.js";
20
20
  import { loadPrompt } from "./prompt-loader.js";
21
- import { isAwaitingUserInput } from "./user-input-boundary.js";
21
+ import { isAwaitingUserInput } from "./consent-question.js";
22
22
  import {
23
23
  resolveMilestonePath,
24
24
  resolveSliceFile,
@@ -51,8 +51,7 @@ import { createWorkspace, scopeMilestone } from "./workspace.js";
51
51
  import { normalizeWorktreePathForCompare } from "./worktree-root.js";
52
52
  import { isDbAvailable, getTask, getSlice, getMilestone, getMilestoneSlices, updateTaskStatus, _getAdapter, getVerificationEvidence } from "./gsd-db.js";
53
53
  import { getWorkflowDatabasePath, refreshWorkflowDatabaseFromDisk } from "./db-workspace.js";
54
- import { renderPlanCheckboxes, renderRoadmapFromDb } from "./markdown-renderer.js";
55
- import { parseRoadmap as parseLegacyRoadmap } from "./parsers-legacy.js";
54
+ import { renderPlanCheckboxes, renderRoadmapFromDb, roadmapRenderMarksSliceDone } from "./markdown-renderer.js";
56
55
  import { consumeSignal } from "./session-status-io.js";
57
56
  import {
58
57
  checkPostUnitHooks,
@@ -88,7 +87,7 @@ import { writeTurnGitTransaction } from "./uok/gitops.js";
88
87
  import { isClosedStatus } from "./status-guards.js";
89
88
  import { detectAbandonMilestone } from "./abandon-detect.js";
90
89
  import { getPendingGate } from "./bootstrap/write-gate.js";
91
- import { isDeterministicPolicyError } from "./auto-tool-tracking.js";
90
+ import { isDeterministicPolicyError, isToolUnavailableError } from "./auto-tool-tracking.js";
92
91
  import { formatConnectedStepStack, formatPostUnitStatusCard } from "./auto-status-message.js";
93
92
  import {
94
93
  clearProjectResearchInflightMarker,
@@ -96,6 +95,7 @@ import {
96
95
  } from "./project-research-policy.js";
97
96
  import { validateArtifact } from "./schemas/validate.js";
98
97
  import { verificationRetryKey } from "./auto/verification-retry-policy.js";
98
+ import { saveCustomVerifyRetryCounts } from "./auto/custom-verify-retry-store.js";
99
99
  import { getLedger } from "./metrics.js";
100
100
  import { getUnitCostSpikeAction, resolveUnitCostSpikeMultiplier } from "./auto-budget.js";
101
101
  import { resolveCanonicalMilestoneRoot } from "./worktree-manager.js";
@@ -901,7 +901,7 @@ export const USER_DRIVEN_DEEP_UNITS = new Set([
901
901
  "discuss-milestone",
902
902
  "research-decision",
903
903
  ]);
904
- export { isAwaitingUserInput } from "./user-input-boundary.js";
904
+ export { isAwaitingUserInput } from "./consent-question.js";
905
905
 
906
906
  function artifactValidationKind(unitType: string): "project" | "requirements" | null {
907
907
  if (unitType === "discuss-project") return "project";
@@ -990,11 +990,13 @@ async function repairCompleteSliceRoadmapProjection(
990
990
  return false;
991
991
  }
992
992
 
993
+ // Stale-render detection (ADR-017): the DB already says the slice is closed;
994
+ // this only checks whether the rendered ROADMAP projection reflects it, to
995
+ // decide whether a repair re-render is needed.
993
996
  const roadmapPath = resolveMilestoneFile(artifactBase, mid, "ROADMAP");
994
997
  if (roadmapPath && existsSync(roadmapPath)) {
995
998
  try {
996
- const roadmap = parseLegacyRoadmap(readFileSync(roadmapPath, "utf-8"));
997
- if (roadmap.slices.find((roadmapSlice) => roadmapSlice.id === sid)?.done) {
999
+ if (roadmapRenderMarksSliceDone(readFileSync(roadmapPath, "utf-8"), sid)) {
998
1000
  return false;
999
1001
  }
1000
1002
  } catch (err) {
@@ -2022,7 +2024,18 @@ export async function postUnitPreVerification(pctx: PostUnitContext, opts?: PreV
2022
2024
  "error",
2023
2025
  );
2024
2026
  } else if (!triggerArtifactVerified) {
2025
- if (s.lastToolInvocationError) {
2027
+ if (s.lastToolInvocationError && isToolUnavailableError(s.lastToolInvocationError)) {
2028
+ // Tool-unavailable is the one transient invocation error: the
2029
+ // workflow MCP server registers its surface asynchronously, so a
2030
+ // Unit's first call can race the registration. Fall through to the
2031
+ // bounded verification retry instead of pausing.
2032
+ debugLog("postUnit", { phase: "tool-unavailable-retry", unitType: s.currentUnit.type, unitId: s.currentUnit.id, error: s.lastToolInvocationError });
2033
+ ctx.ui.notify(
2034
+ `Tool unavailable for ${s.currentUnit.type}: ${s.lastToolInvocationError}. The tool surface may still be registering — retrying.`,
2035
+ "warning",
2036
+ );
2037
+ s.lastToolInvocationError = null;
2038
+ } else if (s.lastToolInvocationError) {
2026
2039
  const isUserSkip = /queued user message/i.test(s.lastToolInvocationError);
2027
2040
  const errMsg = isUserSkip
2028
2041
  ? `Tool skipped for ${s.currentUnit.type}: ${s.lastToolInvocationError}. Queued user message interrupted the turn — pausing auto-mode.`
@@ -2148,6 +2161,7 @@ export async function postUnitPreVerification(pctx: PostUnitContext, opts?: PreV
2148
2161
  }
2149
2162
  }
2150
2163
  s.exhaustedVerificationUnits.add(retryKey);
2164
+ saveCustomVerifyRetryCounts(s, { logFailure: err => debugLog("postUnit", { phase: "save-verify-retries-failed", error: err instanceof Error ? err.message : String(err) }) });
2151
2165
  debugLog("postUnit", { phase: "artifact-verify-exhausted", unitType: s.currentUnit.type, unitId: s.currentUnit.id, attempt });
2152
2166
  ctx.ui.notify(
2153
2167
  `${failureDetails} Pausing auto-mode after ${MAX_ARTIFACT_VERIFICATION_RETRIES} retries.`,
@@ -2157,6 +2171,7 @@ export async function postUnitPreVerification(pctx: PostUnitContext, opts?: PreV
2157
2171
  return "dispatched";
2158
2172
  }
2159
2173
  s.verificationRetryCount.set(retryKey, attempt);
2174
+ saveCustomVerifyRetryCounts(s, { logFailure: err => debugLog("postUnit", { phase: "save-verify-retries-failed", error: err instanceof Error ? err.message : String(err) }) });
2160
2175
  s.pendingVerificationRetry = {
2161
2176
  unitId: s.currentUnit.id,
2162
2177
  failureContext: `${failureDetails} (attempt ${attempt}/${MAX_ARTIFACT_VERIFICATION_RETRIES}).`,
@@ -2180,6 +2195,8 @@ export async function postUnitPreVerification(pctx: PostUnitContext, opts?: PreV
2180
2195
  }
2181
2196
  s.verificationRetryCount.delete(retryKey);
2182
2197
  s.verificationRetryFailureHashes.delete(retryKey);
2198
+ s.exhaustedVerificationUnits.delete(retryKey);
2199
+ saveCustomVerifyRetryCounts(s, { logFailure: err => debugLog("postUnit", { phase: "save-verify-retries-failed", error: err instanceof Error ? err.message : String(err) }) });
2183
2200
 
2184
2201
  if (s.currentUnit.type === "complete-milestone") {
2185
2202
  const { milestone: mid } = parseUnitId(s.currentUnit.id);
@@ -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
  }
@@ -2470,6 +2527,9 @@ export async function buildPlanSlicePrompt(
2470
2527
  `Either (a) add an earlier task that creates X on disk before the task that needs it, ` +
2471
2528
  `or (b) if this task IS the one that creates X, move X from inputs to expected_output. ` +
2472
2529
  `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` +
2530
+ `- **"[file] X: ... GSD planning artifacts are projections preloaded as context / written by workflow tools"**: ` +
2531
+ `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 — ` +
2532
+ `do NOT add a task that creates X and do NOT move X to expectedOutput.\n` +
2473
2533
  `- **"[file] X: Task T_early reads X but it's created by task T_late (sequence violation)"**: ` +
2474
2534
  `Either (a) reorder tasks so T_late (the creator) runs before T_early (the reader), ` +
2475
2535
  `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` +
@@ -3554,15 +3614,30 @@ export async function buildRunUatPrompt(
3554
3614
  null,
3555
3615
  cappedInlinedContext.length < rawInlinedContext.length ? `dropped ${rawInlinedContext.length - cappedInlinedContext.length} chars` : "within budget",
3556
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
+ : "";
3557
3631
  const inlinedContext = prependContextModeToBlock(
3558
3632
  "run-uat",
3559
3633
  base,
3560
- cappedInlinedContext,
3634
+ runtimeHarnessOverride
3635
+ ? `${runtimeHarnessOverride}\n${cappedInlinedContext}`
3636
+ : cappedInlinedContext,
3561
3637
  );
3562
3638
  emitPromptContextTelemetry("run-uat", contextTelemetry, inlinedContext);
3563
3639
 
3564
3640
  const uatResultPath = join(base, relSliceFile(base, mid, sliceId, "ASSESSMENT"));
3565
- const uatType = resolveEffectiveUatType(uatContent);
3566
3641
  const canonicalPresentation = JSON.stringify(buildRunUatPresentationForType(uatType), null, 2);
3567
3642
 
3568
3643
  return loadPrompt("run-uat", {
@@ -3847,18 +3922,22 @@ export async function buildReactiveExecutePrompt(
3847
3922
  const inlinedTemplates = inlineTemplate("task-summary", "Task Summary");
3848
3923
  trackPromptContext(contextTelemetry, "templates", "inline", inlinedTemplates);
3849
3924
 
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
- });
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
+ );
3862
3941
  emitPromptContextTelemetry("reactive-execute", contextTelemetry, prompt);
3863
3942
  return prompt;
3864
3943
  }
@@ -4037,17 +4116,21 @@ export async function buildGateEvaluatePrompt(
4037
4116
  ].join("\n"));
4038
4117
  }
4039
4118
 
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
- });
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
+ );
4051
4134
  }
4052
4135
 
4053
4136
  export async function buildRewriteDocsPrompt(