@opengsd/gsd-pi 1.2.0-dev.b1abb545 → 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 (551) 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 +5 -2
  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/models.js +9 -0
  25. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +38 -6
  26. package/dist/resources/extensions/gsd/auto/custom-verify-retry-store.js +17 -2
  27. package/dist/resources/extensions/gsd/auto/detect-stuck.js +33 -13
  28. package/dist/resources/extensions/gsd/auto/dispatch-history.js +105 -0
  29. package/dist/resources/extensions/gsd/auto/dispatch-key.js +37 -0
  30. package/dist/resources/extensions/gsd/auto/loop.js +4 -1
  31. package/dist/resources/extensions/gsd/auto/orchestrator.js +94 -48
  32. package/dist/resources/extensions/gsd/auto/phases.js +8 -3
  33. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +8 -32
  34. package/dist/resources/extensions/gsd/auto-dispatch.js +40 -57
  35. package/dist/resources/extensions/gsd/auto-model-selection.js +25 -6
  36. package/dist/resources/extensions/gsd/auto-post-unit.js +31 -14
  37. package/dist/resources/extensions/gsd/auto-prompts.js +81 -19
  38. package/dist/resources/extensions/gsd/auto-start.js +24 -26
  39. package/dist/resources/extensions/gsd/auto-tool-tracking.js +18 -0
  40. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +12 -20
  41. package/dist/resources/extensions/gsd/auto-verification.js +9 -28
  42. package/dist/resources/extensions/gsd/auto-worktree-repair.js +10 -2
  43. package/dist/resources/extensions/gsd/auto-worktree.js +35 -352
  44. package/dist/resources/extensions/gsd/auto.js +8 -20
  45. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +3 -2
  46. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +32 -12
  47. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +19 -0
  48. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +229 -36
  49. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +319 -71
  50. package/dist/resources/extensions/gsd/branch-patterns.js +2 -0
  51. package/dist/resources/extensions/gsd/browser-daemon-auto-prep.js +83 -0
  52. package/dist/resources/extensions/gsd/browser-evidence.js +8 -2
  53. package/dist/resources/extensions/gsd/captures.js +5 -15
  54. package/dist/resources/extensions/gsd/closeout-recovery.js +3 -2
  55. package/dist/resources/extensions/gsd/commands/catalog.js +6 -62
  56. package/dist/resources/extensions/gsd/consent-question.js +337 -0
  57. package/dist/resources/extensions/gsd/consent-verdict.js +63 -0
  58. package/dist/resources/extensions/gsd/constants.js +0 -2
  59. package/dist/resources/extensions/gsd/crash-recovery.js +4 -12
  60. package/dist/resources/extensions/gsd/db/engine.js +755 -0
  61. package/dist/resources/extensions/gsd/db/queries.js +398 -0
  62. package/dist/resources/extensions/gsd/db/sql-constants.js +11 -0
  63. package/dist/resources/extensions/gsd/db/writers/cascades.js +194 -0
  64. package/dist/resources/extensions/gsd/db/writers/import-restore.js +182 -0
  65. package/dist/resources/extensions/gsd/db/writers/memory.js +149 -0
  66. package/dist/resources/extensions/gsd/db/writers/reconcile.js +458 -0
  67. package/dist/resources/extensions/gsd/db/writers/status.js +70 -0
  68. package/dist/resources/extensions/gsd/dispatch-guard.js +10 -35
  69. package/dist/resources/extensions/gsd/doctor-environment.js +5 -11
  70. package/dist/resources/extensions/gsd/doctor-format.js +9 -6
  71. package/dist/resources/extensions/gsd/doctor-git-checks.js +4 -3
  72. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +21 -16
  73. package/dist/resources/extensions/gsd/engine-hook-contract.js +70 -0
  74. package/dist/resources/extensions/gsd/error-classifier.js +9 -0
  75. package/dist/resources/extensions/gsd/exec-sandbox.js +30 -10
  76. package/dist/resources/extensions/gsd/files.js +33 -19
  77. package/dist/resources/extensions/gsd/git-service.js +1 -0
  78. package/dist/resources/extensions/gsd/gitignore.js +3 -0
  79. package/dist/resources/extensions/gsd/gsd-db.js +171 -2048
  80. package/dist/resources/extensions/gsd/guidance.js +158 -0
  81. package/dist/resources/extensions/gsd/guided-flow.js +51 -5
  82. package/dist/resources/extensions/gsd/markdown-renderer.js +10 -0
  83. package/dist/resources/extensions/gsd/mcp-filter.js +2 -19
  84. package/dist/resources/extensions/gsd/mcp-tool-name.js +5 -13
  85. package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +1 -1
  86. package/dist/resources/extensions/gsd/migrate/safety.js +20 -9
  87. package/dist/resources/extensions/gsd/migration-auto-check.js +24 -3
  88. package/dist/resources/extensions/gsd/milestone-closeout.js +13 -23
  89. package/dist/resources/extensions/gsd/model-cost-table.js +1 -0
  90. package/dist/resources/extensions/gsd/model-router.js +3 -0
  91. package/dist/resources/extensions/gsd/notification-store.js +11 -4
  92. package/dist/resources/extensions/gsd/parallel-merge.js +14 -11
  93. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +11 -7
  94. package/dist/resources/extensions/gsd/parsers-legacy.js +16 -4
  95. package/dist/resources/extensions/gsd/paths.js +37 -24
  96. package/dist/resources/extensions/gsd/pre-execution-checks.js +91 -3
  97. package/dist/resources/extensions/gsd/preferences-models.js +14 -48
  98. package/dist/resources/extensions/gsd/preferences.js +14 -0
  99. package/dist/resources/extensions/gsd/prompts/complete-slice.md +2 -2
  100. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  101. package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  102. package/dist/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  103. package/dist/resources/extensions/gsd/prompts/run-uat.md +6 -4
  104. package/dist/resources/extensions/gsd/prompts/system.md +5 -2
  105. package/dist/resources/extensions/gsd/provider-error-guidance.js +1 -5
  106. package/dist/resources/extensions/gsd/provider-switch-observer.js +1 -1
  107. package/dist/resources/extensions/gsd/publication.js +87 -0
  108. package/dist/resources/extensions/gsd/reactive-graph.js +8 -1
  109. package/dist/resources/extensions/gsd/recovery-classification.js +41 -87
  110. package/dist/resources/extensions/gsd/safety/destructive-confirmation.js +108 -0
  111. package/dist/resources/extensions/gsd/safety/evidence-collector.js +37 -4
  112. package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +7 -2
  113. package/dist/resources/extensions/gsd/safety/file-change-validator.js +10 -0
  114. package/dist/resources/extensions/gsd/state-transition-matrix.js +38 -0
  115. package/dist/resources/extensions/gsd/state.js +6 -20
  116. package/dist/resources/extensions/gsd/status-guards.js +56 -8
  117. package/dist/resources/extensions/gsd/stop-notice.js +57 -0
  118. package/dist/resources/extensions/gsd/tool-presentation-plan.js +4 -4
  119. package/dist/resources/extensions/gsd/tool-surface-readiness.js +56 -0
  120. package/dist/resources/extensions/gsd/tools/complete-slice.js +44 -53
  121. package/dist/resources/extensions/gsd/tools/exec-tool.js +10 -8
  122. package/dist/resources/extensions/gsd/tools/plan-slice.js +12 -6
  123. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +11 -29
  124. package/dist/resources/extensions/gsd/tools/reopen-slice.js +14 -33
  125. package/dist/resources/extensions/gsd/tools/skip-slice.js +18 -36
  126. package/dist/resources/extensions/gsd/uat-policy.js +42 -16
  127. package/dist/resources/extensions/gsd/undo.js +8 -7
  128. package/dist/resources/extensions/gsd/unit-closeout.js +138 -0
  129. package/dist/resources/extensions/gsd/unit-context-composer.js +74 -1
  130. package/dist/resources/extensions/gsd/unit-context-manifest.js +4 -27
  131. package/dist/resources/extensions/gsd/unit-registry.js +337 -0
  132. package/dist/resources/extensions/gsd/unit-tool-contracts.js +9 -182
  133. package/dist/resources/extensions/gsd/verdict-parser.js +1 -1
  134. package/dist/resources/extensions/gsd/web-app-uat.js +45 -8
  135. package/dist/resources/extensions/gsd/workflow-tool-surface.js +1 -1
  136. package/dist/resources/extensions/gsd/worktree-git-recovery.js +293 -0
  137. package/dist/resources/extensions/gsd/worktree-lifecycle.js +12 -3
  138. package/dist/resources/extensions/gsd/worktree-manager.js +45 -28
  139. package/dist/resources/extensions/gsd/worktree-placement.js +59 -0
  140. package/dist/resources/extensions/gsd/worktree-reentry.js +12 -8
  141. package/dist/resources/extensions/gsd/worktree-root.js +28 -6
  142. package/dist/resources/extensions/gsd/worktree-safety.js +8 -5
  143. package/dist/resources/extensions/gsd/worktree-session-state.js +12 -11
  144. package/dist/resources/extensions/search-the-web/native-search.js +5 -3
  145. package/dist/resources/extensions/shared/browser-contract.js +59 -0
  146. package/dist/resources/extensions/shared/gsd-browser-cli.js +96 -5
  147. package/dist/resources/shared/package.json +3 -0
  148. package/dist/resources/skills/create-skill/references/executable-code.md +1 -1
  149. package/dist/resources/skills/create-skill/workflows/add-reference.md +8 -3
  150. package/dist/resources/skills/create-skill/workflows/add-script.md +4 -2
  151. package/dist/resources/skills/create-skill/workflows/add-template.md +3 -1
  152. package/dist/resources/skills/create-skill/workflows/add-workflow.md +8 -3
  153. package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
  154. package/dist/resources/skills/create-skill/workflows/verify-skill.md +9 -4
  155. package/dist/resources/skills/gsd-browser/SKILL.md +1 -1
  156. package/dist/resources/skills/spike-wrap-up/SKILL.md +9 -9
  157. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  158. package/dist/web/standalone/.next/BUILD_ID +1 -1
  159. package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
  160. package/dist/web/standalone/.next/build-manifest.json +3 -3
  161. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  162. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  163. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  164. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  165. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  166. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  167. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  168. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  169. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  170. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  171. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  172. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  173. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  174. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  175. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  176. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  177. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  178. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  179. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  180. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  181. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  182. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  183. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  184. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  185. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  186. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  187. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  188. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  189. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  190. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  191. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  192. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  193. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  194. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  195. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
  196. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  197. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  198. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  199. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  200. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  201. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  202. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  203. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  204. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  205. package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
  206. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  207. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  208. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  209. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  210. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  211. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  212. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  213. package/dist/web/standalone/.next/server/app/api/update/route.js.nft.json +1 -1
  214. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  215. package/dist/web/standalone/.next/server/app/index.html +1 -1
  216. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  217. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  218. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  219. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  220. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  221. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  222. package/dist/web/standalone/.next/server/app-paths-manifest.json +8 -8
  223. package/dist/web/standalone/.next/server/chunks/5124.js +1 -1
  224. package/dist/web/standalone/.next/server/chunks/{5047.js → 5942.js} +2 -2
  225. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  226. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  227. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  228. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  229. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  230. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  231. package/dist/web/standalone/.next/static/chunks/{796.cf859a427a2cb2ac.js → 796.e0bdc932325d7e03.js} +1 -1
  232. package/dist/web/standalone/.next/static/chunks/{webpack-fbea77b5f9953368.js → webpack-f0285ce91d4ec9ef.js} +1 -1
  233. package/dist/web/standalone/package.json +1 -1
  234. package/dist/worktree-cli.js +3 -6
  235. package/dist/worktree-status-banner.js +7 -11
  236. package/package.json +1 -1
  237. package/packages/cloud-mcp-gateway/package.json +2 -2
  238. package/packages/contracts/dist/rpc.d.ts +1 -0
  239. package/packages/contracts/dist/rpc.d.ts.map +1 -1
  240. package/packages/contracts/dist/rpc.js.map +1 -1
  241. package/packages/contracts/dist/workflow.d.ts +4 -0
  242. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  243. package/packages/contracts/dist/workflow.js.map +1 -1
  244. package/packages/contracts/package.json +1 -1
  245. package/packages/daemon/package.json +4 -4
  246. package/packages/gsd-agent-core/package.json +5 -5
  247. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +5 -0
  248. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  249. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +8 -0
  250. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  251. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  252. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +7 -0
  253. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  254. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  255. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +8 -1
  256. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  257. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.d.ts.map +1 -1
  258. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js +11 -1
  259. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js.map +1 -1
  260. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
  261. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +4 -4
  262. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
  263. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  264. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +3 -1
  265. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
  266. package/packages/gsd-agent-modes/package.json +7 -7
  267. package/packages/mcp-server/dist/cli.js +6 -3
  268. package/packages/mcp-server/dist/cli.js.map +1 -1
  269. package/packages/mcp-server/dist/workflow-tools.d.ts +8 -0
  270. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  271. package/packages/mcp-server/dist/workflow-tools.js +46 -21
  272. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  273. package/packages/mcp-server/package.json +3 -3
  274. package/packages/native/package.json +1 -1
  275. package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts +1 -0
  276. package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts.map +1 -1
  277. package/packages/pi-agent-core/dist/harness/env/nodejs.js +34 -3
  278. package/packages/pi-agent-core/dist/harness/env/nodejs.js.map +1 -1
  279. package/packages/pi-agent-core/dist/index.d.ts +1 -0
  280. package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
  281. package/packages/pi-agent-core/dist/index.js +3 -0
  282. package/packages/pi-agent-core/dist/index.js.map +1 -1
  283. package/packages/pi-agent-core/package.json +1 -1
  284. package/packages/pi-ai/README.md +1 -0
  285. package/packages/pi-ai/dist/models.generated.d.ts +192 -0
  286. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  287. package/packages/pi-ai/dist/models.generated.js +166 -0
  288. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  289. package/packages/pi-ai/package.json +3 -2
  290. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +2 -2
  291. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  292. package/packages/pi-coding-agent/dist/core/auth-storage.js +19 -13
  293. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  294. package/packages/pi-coding-agent/dist/core/capability-patches.d.ts.map +1 -1
  295. package/packages/pi-coding-agent/dist/core/capability-patches.js +3 -1
  296. package/packages/pi-coding-agent/dist/core/capability-patches.js.map +1 -1
  297. package/packages/pi-coding-agent/dist/core/provider-readiness.d.ts.map +1 -1
  298. package/packages/pi-coding-agent/dist/core/provider-readiness.js +13 -6
  299. package/packages/pi-coding-agent/dist/core/provider-readiness.js.map +1 -1
  300. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts +11 -0
  301. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
  302. package/packages/pi-coding-agent/dist/core/tools/bash.js +53 -11
  303. package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
  304. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  305. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  306. package/packages/pi-coding-agent/dist/index.js +1 -1
  307. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  308. package/packages/pi-coding-agent/dist/utils/shell.d.ts +28 -2
  309. package/packages/pi-coding-agent/dist/utils/shell.d.ts.map +1 -1
  310. package/packages/pi-coding-agent/dist/utils/shell.js +56 -10
  311. package/packages/pi-coding-agent/dist/utils/shell.js.map +1 -1
  312. package/packages/pi-coding-agent/package.json +7 -7
  313. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  314. package/packages/pi-tui/dist/tui.js +9 -0
  315. package/packages/pi-tui/dist/tui.js.map +1 -1
  316. package/packages/pi-tui/package.json +2 -2
  317. package/packages/rpc-client/package.json +2 -2
  318. package/pkg/package.json +1 -1
  319. package/src/resources/GSD-WORKFLOW.md +5 -4
  320. package/src/resources/extensions/async-jobs/async-bash-cancel.test.ts +360 -0
  321. package/src/resources/extensions/async-jobs/async-bash-tool.ts +33 -56
  322. package/src/resources/extensions/async-jobs/await-tool.test.ts +139 -0
  323. package/src/resources/extensions/async-jobs/await-tool.ts +82 -12
  324. package/src/resources/extensions/async-jobs/index.ts +79 -0
  325. package/src/resources/extensions/async-jobs/job-manager.ts +21 -1
  326. package/src/resources/extensions/bg-shell/bg-shell-command.ts +6 -6
  327. package/src/resources/extensions/bg-shell/bg-shell-tool.ts +10 -6
  328. package/src/resources/extensions/bg-shell/overlay.ts +9 -5
  329. package/src/resources/extensions/bg-shell/process-manager.ts +50 -25
  330. package/src/resources/extensions/bg-shell/readiness-detector.ts +12 -0
  331. package/src/resources/extensions/bg-shell/tests/lifecycle-and-utilities.test.ts +48 -1
  332. package/src/resources/extensions/bg-shell/utilities.ts +5 -2
  333. package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +265 -98
  334. package/src/resources/extensions/browser-tools/engine/selection.ts +90 -4
  335. package/src/resources/extensions/browser-tools/index.ts +71 -13
  336. package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +83 -13
  337. package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +29 -1
  338. package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +136 -0
  339. package/src/resources/extensions/claude-code-cli/models.ts +9 -0
  340. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +40 -4
  341. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +28 -0
  342. package/src/resources/extensions/gsd/auto/custom-verify-retry-store.ts +21 -3
  343. package/src/resources/extensions/gsd/auto/detect-stuck.ts +32 -9
  344. package/src/resources/extensions/gsd/auto/dispatch-history.ts +152 -0
  345. package/src/resources/extensions/gsd/auto/dispatch-key.ts +39 -0
  346. package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -1
  347. package/src/resources/extensions/gsd/auto/loop.ts +4 -1
  348. package/src/resources/extensions/gsd/auto/orchestrator.ts +109 -51
  349. package/src/resources/extensions/gsd/auto/phases.ts +12 -3
  350. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +8 -32
  351. package/src/resources/extensions/gsd/auto-dispatch.ts +38 -52
  352. package/src/resources/extensions/gsd/auto-model-selection.ts +25 -5
  353. package/src/resources/extensions/gsd/auto-post-unit.ts +37 -13
  354. package/src/resources/extensions/gsd/auto-prompts.ts +118 -35
  355. package/src/resources/extensions/gsd/auto-start.ts +24 -29
  356. package/src/resources/extensions/gsd/auto-tool-tracking.ts +19 -0
  357. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +14 -21
  358. package/src/resources/extensions/gsd/auto-verification.ts +8 -26
  359. package/src/resources/extensions/gsd/auto-worktree-repair.ts +13 -2
  360. package/src/resources/extensions/gsd/auto-worktree.ts +41 -364
  361. package/src/resources/extensions/gsd/auto.ts +20 -24
  362. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +3 -5
  363. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +33 -12
  364. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +24 -0
  365. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +270 -37
  366. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +368 -78
  367. package/src/resources/extensions/gsd/branch-patterns.ts +3 -0
  368. package/src/resources/extensions/gsd/browser-daemon-auto-prep.ts +108 -0
  369. package/src/resources/extensions/gsd/browser-evidence.ts +18 -2
  370. package/src/resources/extensions/gsd/captures.ts +5 -16
  371. package/src/resources/extensions/gsd/closeout-recovery.ts +2 -1
  372. package/src/resources/extensions/gsd/commands/catalog.ts +6 -68
  373. package/src/resources/extensions/gsd/consent-question.ts +416 -0
  374. package/src/resources/extensions/gsd/consent-verdict.ts +86 -0
  375. package/src/resources/extensions/gsd/constants.ts +0 -3
  376. package/src/resources/extensions/gsd/crash-recovery.ts +3 -9
  377. package/src/resources/extensions/gsd/db/engine.ts +809 -0
  378. package/src/resources/extensions/gsd/db/queries.ts +490 -0
  379. package/src/resources/extensions/gsd/db/sql-constants.ts +12 -0
  380. package/src/resources/extensions/gsd/db/writers/cascades.ts +237 -0
  381. package/src/resources/extensions/gsd/db/writers/import-restore.ts +310 -0
  382. package/src/resources/extensions/gsd/db/writers/memory.ts +220 -0
  383. package/src/resources/extensions/gsd/db/writers/reconcile.ts +500 -0
  384. package/src/resources/extensions/gsd/db/writers/status.ts +88 -0
  385. package/src/resources/extensions/gsd/dispatch-guard.ts +8 -31
  386. package/src/resources/extensions/gsd/doctor-environment.ts +5 -13
  387. package/src/resources/extensions/gsd/doctor-format.ts +12 -7
  388. package/src/resources/extensions/gsd/doctor-git-checks.ts +3 -3
  389. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +22 -17
  390. package/src/resources/extensions/gsd/engine-hook-contract.ts +79 -0
  391. package/src/resources/extensions/gsd/error-classifier.ts +11 -0
  392. package/src/resources/extensions/gsd/exec-sandbox.ts +49 -9
  393. package/src/resources/extensions/gsd/files.ts +33 -12
  394. package/src/resources/extensions/gsd/git-service.ts +1 -0
  395. package/src/resources/extensions/gsd/gitignore.ts +3 -0
  396. package/src/resources/extensions/gsd/gsd-db.ts +173 -2373
  397. package/src/resources/extensions/gsd/guidance.ts +217 -0
  398. package/src/resources/extensions/gsd/guided-flow.ts +50 -5
  399. package/src/resources/extensions/gsd/markdown-renderer.ts +11 -0
  400. package/src/resources/extensions/gsd/mcp-filter.ts +2 -23
  401. package/src/resources/extensions/gsd/mcp-tool-name.ts +6 -11
  402. package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +1 -1
  403. package/src/resources/extensions/gsd/migrate/safety.ts +18 -7
  404. package/src/resources/extensions/gsd/migration-auto-check.ts +28 -3
  405. package/src/resources/extensions/gsd/milestone-closeout.ts +13 -23
  406. package/src/resources/extensions/gsd/model-cost-table.ts +1 -0
  407. package/src/resources/extensions/gsd/model-router.ts +3 -0
  408. package/src/resources/extensions/gsd/notification-store.ts +26 -3
  409. package/src/resources/extensions/gsd/parallel-merge.ts +12 -9
  410. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +10 -7
  411. package/src/resources/extensions/gsd/parsers-legacy.ts +16 -4
  412. package/src/resources/extensions/gsd/paths.ts +42 -22
  413. package/src/resources/extensions/gsd/pre-execution-checks.ts +109 -3
  414. package/src/resources/extensions/gsd/preferences-models.ts +12 -47
  415. package/src/resources/extensions/gsd/preferences.ts +18 -0
  416. package/src/resources/extensions/gsd/prompts/complete-slice.md +2 -2
  417. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  418. package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  419. package/src/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  420. package/src/resources/extensions/gsd/prompts/run-uat.md +6 -4
  421. package/src/resources/extensions/gsd/prompts/system.md +5 -2
  422. package/src/resources/extensions/gsd/provider-error-guidance.ts +4 -9
  423. package/src/resources/extensions/gsd/provider-switch-observer.ts +1 -1
  424. package/src/resources/extensions/gsd/publication.ts +122 -0
  425. package/src/resources/extensions/gsd/reactive-graph.ts +11 -1
  426. package/src/resources/extensions/gsd/recovery-classification.ts +47 -88
  427. package/src/resources/extensions/gsd/safety/destructive-confirmation.ts +134 -0
  428. package/src/resources/extensions/gsd/safety/evidence-collector.ts +36 -4
  429. package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +7 -2
  430. package/src/resources/extensions/gsd/safety/file-change-validator.ts +14 -0
  431. package/src/resources/extensions/gsd/state-transition-matrix.ts +42 -0
  432. package/src/resources/extensions/gsd/state.ts +9 -21
  433. package/src/resources/extensions/gsd/status-guards.ts +59 -8
  434. package/src/resources/extensions/gsd/stop-notice.ts +75 -0
  435. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +123 -0
  436. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +22 -0
  437. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +101 -26
  438. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +3 -1
  439. package/src/resources/extensions/gsd/tests/auto-post-unit-evidence-crossref-4909.test.ts +46 -0
  440. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +2 -2
  441. package/src/resources/extensions/gsd/tests/auto-worktree-repair.test.ts +4 -2
  442. package/src/resources/extensions/gsd/tests/browser-automation-contract-fixture.ts +39 -0
  443. package/src/resources/extensions/gsd/tests/browser-contract.test.ts +44 -0
  444. package/src/resources/extensions/gsd/tests/browser-daemon-auto-prep.test.ts +144 -0
  445. package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +66 -1
  446. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +44 -0
  447. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +8 -7
  448. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
  449. package/src/resources/extensions/gsd/tests/consent-question.test.ts +336 -0
  450. package/src/resources/extensions/gsd/tests/custom-verify-retry-store.test.ts +67 -0
  451. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +10 -10
  452. package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +303 -0
  453. package/src/resources/extensions/gsd/tests/dispatch-history.test.ts +273 -0
  454. package/src/resources/extensions/gsd/tests/dispatch-run-uat-browser-tools.test.ts +2 -1
  455. package/src/resources/extensions/gsd/tests/dynamic-bash-no-cap.test.ts +132 -0
  456. package/src/resources/extensions/gsd/tests/engine-hook-contract.test.ts +148 -0
  457. package/src/resources/extensions/gsd/tests/evidence-xref-gsd-exec.test.ts +157 -0
  458. package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +193 -0
  459. package/src/resources/extensions/gsd/tests/exec-tool.test.ts +29 -1
  460. package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +35 -1
  461. package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +33 -1
  462. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +27 -0
  463. package/src/resources/extensions/gsd/tests/guidance.test.ts +148 -0
  464. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +58 -15
  465. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +74 -59
  466. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +3 -2
  467. package/src/resources/extensions/gsd/tests/integration/gsd-integration-fixture.ts +80 -0
  468. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +199 -0
  469. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +3 -1
  470. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +85 -1
  471. package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +32 -1
  472. package/src/resources/extensions/gsd/tests/notification-store.test.ts +32 -0
  473. package/src/resources/extensions/gsd/tests/oauth-api-model-routing.test.ts +167 -0
  474. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +18 -0
  475. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +139 -0
  476. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +193 -1
  477. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +124 -6
  478. package/src/resources/extensions/gsd/tests/provider-error-guidance.test.ts +3 -3
  479. package/src/resources/extensions/gsd/tests/publication.test.ts +120 -0
  480. package/src/resources/extensions/gsd/tests/recovery-classification-illegal-transition.test.ts +30 -0
  481. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +248 -1
  482. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +1 -0
  483. package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +38 -0
  484. package/src/resources/extensions/gsd/tests/session-switch-clears-pending-autostart.test.ts +108 -0
  485. package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +43 -6
  486. package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +36 -0
  487. package/src/resources/extensions/gsd/tests/status-guards.test.ts +38 -0
  488. package/src/resources/extensions/gsd/tests/stop-notice.test.ts +70 -0
  489. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +76 -0
  490. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +8 -0
  491. package/src/resources/extensions/gsd/tests/tool-surface-readiness.test.ts +155 -0
  492. package/src/resources/extensions/gsd/tests/uat-policy.test.ts +112 -29
  493. package/src/resources/extensions/gsd/tests/unit-closeout.test.ts +209 -0
  494. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +67 -2
  495. package/src/resources/extensions/gsd/tests/unit-registry.test.ts +163 -0
  496. package/src/resources/extensions/gsd/tests/web-app-uat.test.ts +44 -1
  497. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -2
  498. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +2 -2
  499. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +41 -4
  500. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +22 -1
  501. package/src/resources/extensions/gsd/tests/worktree-placement.test.ts +113 -0
  502. package/src/resources/extensions/gsd/tests/worktree-reentry.test.ts +1 -1
  503. package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +3 -1
  504. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +12 -6
  505. package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +2 -2
  506. package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +358 -0
  507. package/src/resources/extensions/gsd/tests/write-gate.test.ts +109 -1
  508. package/src/resources/extensions/gsd/tool-presentation-plan.ts +4 -4
  509. package/src/resources/extensions/gsd/tool-surface-readiness.ts +76 -0
  510. package/src/resources/extensions/gsd/tools/complete-slice.ts +43 -68
  511. package/src/resources/extensions/gsd/tools/exec-tool.ts +9 -8
  512. package/src/resources/extensions/gsd/tools/plan-slice.ts +12 -6
  513. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +11 -38
  514. package/src/resources/extensions/gsd/tools/reopen-slice.ts +14 -42
  515. package/src/resources/extensions/gsd/tools/skip-slice.ts +18 -44
  516. package/src/resources/extensions/gsd/uat-policy.ts +62 -16
  517. package/src/resources/extensions/gsd/undo.ts +9 -8
  518. package/src/resources/extensions/gsd/unit-closeout.ts +201 -0
  519. package/src/resources/extensions/gsd/unit-context-composer.ts +111 -1
  520. package/src/resources/extensions/gsd/unit-context-manifest.ts +4 -28
  521. package/src/resources/extensions/gsd/unit-registry.ts +412 -0
  522. package/src/resources/extensions/gsd/unit-tool-contracts.ts +27 -192
  523. package/src/resources/extensions/gsd/verdict-parser.ts +1 -1
  524. package/src/resources/extensions/gsd/web-app-uat.ts +51 -8
  525. package/src/resources/extensions/gsd/workflow-tool-surface.ts +4 -1
  526. package/src/resources/extensions/gsd/worktree-git-recovery.ts +314 -0
  527. package/src/resources/extensions/gsd/worktree-lifecycle.ts +13 -9
  528. package/src/resources/extensions/gsd/worktree-manager.ts +47 -28
  529. package/src/resources/extensions/gsd/worktree-placement.ts +63 -0
  530. package/src/resources/extensions/gsd/worktree-reentry.ts +10 -7
  531. package/src/resources/extensions/gsd/worktree-root.ts +29 -6
  532. package/src/resources/extensions/gsd/worktree-safety.ts +8 -5
  533. package/src/resources/extensions/gsd/worktree-session-state.ts +11 -11
  534. package/src/resources/extensions/search-the-web/native-search.ts +5 -3
  535. package/src/resources/extensions/shared/browser-contract.ts +66 -0
  536. package/src/resources/extensions/shared/gsd-browser-cli.ts +119 -5
  537. package/src/resources/shared/package.json +3 -0
  538. package/src/resources/skills/create-skill/references/executable-code.md +1 -1
  539. package/src/resources/skills/create-skill/workflows/add-reference.md +8 -3
  540. package/src/resources/skills/create-skill/workflows/add-script.md +4 -2
  541. package/src/resources/skills/create-skill/workflows/add-template.md +3 -1
  542. package/src/resources/skills/create-skill/workflows/add-workflow.md +8 -3
  543. package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
  544. package/src/resources/skills/create-skill/workflows/verify-skill.md +9 -4
  545. package/src/resources/skills/gsd-browser/SKILL.md +1 -1
  546. package/src/resources/skills/spike-wrap-up/SKILL.md +9 -9
  547. package/dist/resources/extensions/gsd/user-input-boundary.js +0 -218
  548. package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +0 -173
  549. package/src/resources/extensions/gsd/user-input-boundary.ts +0 -216
  550. /package/dist/web/standalone/.next/static/{3PtrU9qGPEXwNLWkIyiqk → jmTLg6xZmAuq_LIqKOxrH}/_buildManifest.js +0 -0
  551. /package/dist/web/standalone/.next/static/{3PtrU9qGPEXwNLWkIyiqk → jmTLg6xZmAuq_LIqKOxrH}/_ssgManifest.js +0 -0
@@ -14,13 +14,14 @@ import type { ExtensionAPI, ExtensionContext } from "@gsd/pi-coding-agent";
14
14
 
15
15
  import type { AutoAdvanceResult, AutoOrchestrationModule, AutoSessionContext, AutoStatus, AutoTerminalOutcome } from "./contracts.js";
16
16
  import type { AutoSession, PendingOrchestrationDispatch } from "./session.js";
17
- import type { GSDState } from "../types.js";
17
+ import type { GSDState, Phase } from "../types.js";
18
18
  import type { MinimalModelRegistry } from "../context-budget.js";
19
19
 
20
20
  type BlockedAdvanceResult = Extract<AutoAdvanceResult, { kind: "blocked" }>;
21
21
 
22
- import { debugCount, debugTime } from "../debug-logger.js";
22
+ import { debugCount, debugLog, debugTime } from "../debug-logger.js";
23
23
  import { reconcileBeforeDispatch } from "../state-reconciliation.js";
24
+ import { isLegalEdge, IllegalPhaseTransitionError } from "../state-transition-matrix.js";
24
25
  import { resolveDispatch } from "../auto-dispatch.js";
25
26
  import { classifyFailure } from "../recovery-classification.js";
26
27
  import { verifyExpectedArtifact, refreshRecoveryDbForArtifact } from "../auto-recovery.js";
@@ -37,7 +38,7 @@ import { checkResourcesStale, autoWorktreeBranch, mergeMilestoneToMain } from ".
37
38
  import { getSessionLockStatus } from "../session-lock.js";
38
39
  import { resolveUokFlags } from "../uok/flags.js";
39
40
  import { emitJournalEvent as _emitJournalEvent } from "../journal.js";
40
- import { loadEffectiveGSDPreferences, getIsolationMode } from "../preferences.js";
41
+ import { loadEffectiveGSDPreferences, getIsolationMode, resolveEffectiveUnitIsolationMode } from "../preferences.js";
41
42
  import {
42
43
  detectWorktreeName,
43
44
  getMainBranch,
@@ -63,6 +64,13 @@ import {
63
64
  import { refreshWorkflowDatabaseFromDisk } from "../db-workspace.js";
64
65
  import { getErrorMessage } from "../error-utils.js";
65
66
  import { logWarning } from "../workflow-logger.js";
67
+ import { normalizeRealPath } from "../paths.js";
68
+ import {
69
+ buildDispatchKey,
70
+ createDispatchHistory,
71
+ STUCK_WINDOW_SIZE,
72
+ type DispatchHistory,
73
+ } from "./dispatch-history.js";
66
74
  import { existsSync, readFileSync } from "node:fs";
67
75
  import { join } from "node:path";
68
76
  import { evaluateAllCompleteSettlement } from "../milestone-settlement.js";
@@ -71,16 +79,6 @@ function now(): number {
71
79
  return Date.now();
72
80
  }
73
81
 
74
- /**
75
- * Size of the dispatch-decision ring buffer used by the Auto Orchestration
76
- * module's stuck-loop detector. When the same `${unitType}:${unitId}` key
77
- * fills the window, advance() blocks with `action: "stop"`.
78
- *
79
- * Mirrors the legacy `STUCK_WINDOW_SIZE` in auto/phases.ts so behaviour is
80
- * preserved across the eventual cutover (issue #5791).
81
- */
82
- export const STUCK_WINDOW_SIZE = 6;
83
-
84
82
  function noRemainingUnitsOutcome(stateSnapshot: GSDState): AutoTerminalOutcome {
85
83
  if (stateSnapshot.phase === "complete") {
86
84
  return {
@@ -329,7 +327,13 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
329
327
  private seq = 0;
330
328
  private lastAdvanceKey: string | null = null;
331
329
  private lastFinalizedUnitKey: string | null = null;
332
- private dispatchKeyWindow: string[] = [];
330
+ // Dispatch History module (#482): the dispatch-decision window with
331
+ // cross-session DB rehydration and full detect-stuck rules.
332
+ private readonly dispatchHistory: DispatchHistory;
333
+ // ADR-030 Phase Transition Invariant: the prior advance's reconciled Phase,
334
+ // the "from" endpoint of the edge check. In-memory; reset on start/resume/stop
335
+ // so the first advance of a session has no edge to assert.
336
+ private lastDerivedPhase: Phase | null = null;
333
337
  // #442: the unit key we last attempted graduated stuck-recovery for. Bounds
334
338
  // recovery to one attempt per stuck episode per run (reset on start/resume/
335
339
  // stop), mirroring the legacy Level-1-then-Level-2 escalation in phases.ts.
@@ -342,6 +346,16 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
342
346
  this.runtimeBasePath = context.runtimeBasePath;
343
347
  this.s = context.session;
344
348
  this.flowId = `auto-orchestrator-${Date.now()}`;
349
+ this.dispatchHistory = createDispatchHistory({
350
+ windowSize: STUCK_WINDOW_SIZE,
351
+ // Same stable scope the auto-loop uses for stuck-state persistence so
352
+ // rehydration reads the rows the dispatch ledger wrote for this project.
353
+ resolveScopeId: () =>
354
+ normalizeRealPath(
355
+ this.s.scope?.workspace.projectRoot ??
356
+ (this.s.originalBasePath || this.s.basePath || this.runtimeBasePath),
357
+ ) || null,
358
+ });
345
359
  }
346
360
 
347
361
  // ── Live base-path resolution (was the wiring factory's getLiveDispatchBasePath) ──
@@ -612,8 +626,11 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
612
626
  // ── WorktreeAdapter (folded) ─────────────────────────────────────────────
613
627
 
614
628
  private getEffectiveUnitIsolationMode(basePath: string): ReturnType<typeof getIsolationMode> {
615
- const configuredMode = getIsolationMode(basePath);
616
- return configuredMode === "worktree" && this.s.isolationDegraded ? "branch" : configuredMode;
629
+ return resolveEffectiveUnitIsolationMode(
630
+ getIsolationMode(basePath),
631
+ this.s.isolationDegraded,
632
+ this.s.strandedRecoveryIsolationMode,
633
+ );
617
634
  }
618
635
 
619
636
  private buildLifecycle(): WorktreeLifecycle {
@@ -724,6 +741,21 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
724
741
  return { action: recovery.action, reason: recovery.reason };
725
742
  }
726
743
 
744
+ /**
745
+ * ADR-030 Phase Transition Invariant (advisory mode). The matrix is an
746
+ * assertion, not a decision-maker — deriveState already chose the phase; we
747
+ * only observe illegal *derived* edges that survived reconciliation. The
748
+ * matrix is still a sparse hardening spec, so this is telemetry-only (no
749
+ * block) until it is expanded into a validated legal-edge graph. To enforce:
750
+ * `throw violation;` instead of logging — recovery-classification maps
751
+ * IllegalPhaseTransitionError to kind "illegal-transition" (escalate).
752
+ */
753
+ private observePhaseTransition(from: Phase, to: Phase): void {
754
+ if (isLegalEdge(from, to)) return;
755
+ const violation = new IllegalPhaseTransitionError(from, to);
756
+ debugLog("phase-transition-advisory", { from, to, message: violation.message });
757
+ }
758
+
727
759
  // ── Lifecycle verbs ──────────────────────────────────────────────────────
728
760
 
729
761
  /**
@@ -742,7 +774,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
742
774
  * skipped result) instead of stopping.
743
775
  */
744
776
  private tryStuckArtifactRecovery(unitType: string, unitId: string): boolean {
745
- const key = `${unitType}:${unitId}`;
777
+ const key = buildDispatchKey(unitType, unitId);
746
778
  if (this.lastStuckRecoveryKey === key) return false; // already tried this episode
747
779
  const basePath = this.getLiveDispatchBasePath();
748
780
  if (!verifyExpectedArtifact(unitType, unitId, basePath)) return false;
@@ -754,7 +786,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
754
786
  if (!refreshed.ok && refreshed.fatal) return false;
755
787
  this.lastStuckRecoveryKey = key;
756
788
  invalidateAllCaches();
757
- this.dispatchKeyWindow = [];
789
+ this.dispatchHistory.clearOnRecovery();
758
790
  this.lastAdvanceKey = null;
759
791
  this.lastFinalizedUnitKey = null;
760
792
  return true;
@@ -785,8 +817,14 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
785
817
  public async start(_sessionContext: AutoSessionContext): Promise<AutoAdvanceResult> {
786
818
  this.lastAdvanceKey = null;
787
819
  this.lastFinalizedUnitKey = null;
788
- this.dispatchKeyWindow = [];
820
+ // #482: the DB dispatch ledger is the source of truth across sessions.
821
+ // Discard any in-memory window and rebuild it from the ledger so a unit
822
+ // that was re-dispatched in previous sessions is detected as stuck here
823
+ // instead of silently re-dispatching forever.
824
+ this.dispatchHistory.clearOnRecovery();
825
+ this.dispatchHistory.rehydrate();
789
826
  this.lastStuckRecoveryKey = null;
827
+ this.lastDerivedPhase = null;
790
828
  this.status.phase = "running";
791
829
  this.bumpTransition();
792
830
  this.journalTransition({ name: "start" });
@@ -876,6 +914,12 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
876
914
  return blocked;
877
915
  }
878
916
 
917
+ const reconciledPhase = reconciliation.stateSnapshot.phase;
918
+ if (this.lastDerivedPhase !== null) {
919
+ this.observePhaseTransition(this.lastDerivedPhase, reconciledPhase);
920
+ }
921
+ this.lastDerivedPhase = reconciledPhase;
922
+
879
923
  const decision = await this.decideNextUnit({ stateSnapshot: reconciliation.stateSnapshot });
880
924
  if (!decision) {
881
925
  const settlementBlock = this.evaluateNoRemainingUnitsSettlement(reconciliation.stateSnapshot);
@@ -883,7 +927,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
883
927
  this.status.phase = "paused";
884
928
  this.status.activeUnit = undefined;
885
929
  this.lastAdvanceKey = null;
886
- this.dispatchKeyWindow = [];
930
+ this.dispatchHistory.clearOnRecovery();
887
931
  this.bumpTransition();
888
932
  this.journalTransition({ name: "advance-blocked", reason: settlementBlock.reason });
889
933
  this.postAdvanceRecord(settlementBlock);
@@ -899,7 +943,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
899
943
  this.status.phase = "stopped";
900
944
  this.status.activeUnit = undefined;
901
945
  this.lastAdvanceKey = null;
902
- this.dispatchKeyWindow = [];
946
+ this.dispatchHistory.clearOnRecovery();
903
947
  this.bumpTransition();
904
948
  this.journalTransition({ name: "advance-stopped", reason: stopped.reason });
905
949
  this.postAdvanceRecord(stopped);
@@ -949,18 +993,13 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
949
993
  return blocked;
950
994
  }
951
995
 
952
- const nextKey = `${decision.unitType}:${decision.unitId}`;
953
-
954
- // Record every dispatch decision in the ring buffer before pre-flight
996
+ // Record every dispatch decision in the history window before pre-flight
955
997
  // checks so the stuck-loop detector observes the full decision history
956
998
  // (including decisions that idempotency would otherwise short-circuit).
957
- // The ring is capped at STUCK_WINDOW_SIZE and evicts oldest-first.
958
- this.dispatchKeyWindow.push(nextKey);
959
- if (this.dispatchKeyWindow.length > STUCK_WINDOW_SIZE) {
960
- this.dispatchKeyWindow.shift();
961
- }
999
+ // The window is capped at STUCK_WINDOW_SIZE and evicts oldest-first.
1000
+ const nextKey = this.dispatchHistory.recordDispatch(decision.unitType, decision.unitId);
962
1001
 
963
- const matchingCount = this.dispatchKeyWindow.filter((k) => k === nextKey).length;
1002
+ const matchingCount = this.dispatchHistory.countMatching(nextKey);
964
1003
  if (this.lastFinalizedUnitKey === nextKey) {
965
1004
  // #442: the unit re-dispatched immediately after finalizing may have
966
1005
  // actually completed on disk with a stale DB. Verify + recover before
@@ -993,23 +1032,32 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
993
1032
  // checks coexist: idempotency for the common immediate-repeat case,
994
1033
  // stuck-loop for the saturated-window case.
995
1034
  if (this.lastAdvanceKey === nextKey && matchingCount < STUCK_WINDOW_SIZE) {
1035
+ // Unit already active — benign no-op. Return skipped so the loop re-polls
1036
+ // without cancelling the in-flight unit (blocked+pause would force-cancel it).
996
1037
  this.clearPendingDispatch();
997
- const blocked: AutoAdvanceResult = { kind: "blocked", reason: "idempotent advance: unit already active", action: "pause" };
1038
+ const skipped: AutoAdvanceResult = { kind: "skipped", reason: "idempotent advance: unit already active" };
998
1039
  this.journalTransition({
999
- name: "advance-blocked",
1000
- reason: blocked.reason,
1040
+ name: "advance-skipped",
1041
+ reason: skipped.reason,
1001
1042
  unitType: decision.unitType,
1002
1043
  unitId: decision.unitId,
1003
1044
  });
1004
- this.postAdvanceRecord(blocked);
1005
- return blocked;
1045
+ this.postAdvanceRecord(skipped);
1046
+ return skipped;
1006
1047
  }
1007
1048
 
1008
- // Stuck-loop detection: when the ring is saturated with copies of
1009
- // `nextKey` (count >= STUCK_WINDOW_SIZE), the orchestrator has been
1010
- // picking the same unit across the whole window and must hard-stop with
1011
- // a diagnosable reason.
1012
- if (matchingCount >= STUCK_WINDOW_SIZE) {
1049
+ // Stuck-loop detection: when the window is saturated with copies of
1050
+ // `nextKey` (count >= STUCK_WINDOW_SIZE), consult the Dispatch History
1051
+ // module's full detect-stuck rule set for the verdict instead of the old
1052
+ // bare saturation count. This keeps the saturation threshold (the window
1053
+ // deliberately records benign idempotent repeats, so earlier-firing
1054
+ // rules would false-positive on pause/resume re-advances) while gaining
1055
+ // retry-budget suppression and diagnosable rule reasons. A saturated
1056
+ // window with no verdict means the dispatch ledger says we are inside
1057
+ // the unit's retry-backoff budget — let the retry proceed.
1058
+ const stuckVerdict =
1059
+ matchingCount >= STUCK_WINDOW_SIZE ? this.dispatchHistory.detectStuck() : null;
1060
+ if (stuckVerdict) {
1013
1061
  // #442: before declaring a stuck loop, verify the unit didn't actually
1014
1062
  // complete on disk (stale DB) and recover if so — legacy graduated
1015
1063
  // stuck-recovery parity. Otherwise hard-stop with a diagnosable reason.
@@ -1020,7 +1068,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
1020
1068
  this.clearPendingDispatch();
1021
1069
  const blocked: AutoAdvanceResult = {
1022
1070
  kind: "blocked",
1023
- reason: `stuck-loop: ${nextKey} picked ${matchingCount} times`,
1071
+ reason: `stuck-loop: ${stuckVerdict.reason}`,
1024
1072
  action: "stop",
1025
1073
  };
1026
1074
  this.journalTransition({
@@ -1114,7 +1162,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
1114
1162
  if (result.kind === "stopped") {
1115
1163
  this.lastAdvanceKey = null;
1116
1164
  this.lastFinalizedUnitKey = null;
1117
- this.dispatchKeyWindow = [];
1165
+ this.dispatchHistory.clearOnRecovery();
1118
1166
  this.status.activeUnit = undefined;
1119
1167
  }
1120
1168
  this.bumpTransition();
@@ -1143,9 +1191,18 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
1143
1191
  public async resume(): Promise<AutoAdvanceResult> {
1144
1192
  this.lastAdvanceKey = null;
1145
1193
  this.lastFinalizedUnitKey = null;
1146
- // Preserve dispatchKeyWindow across resume so stuck-loop detection
1147
- // accumulates across pause/resume cycles rather than resetting each time.
1194
+ // Preserve the dispatch-history window across an in-process resume so
1195
+ // stuck-loop detection accumulates across pause/resume cycles rather than
1196
+ // resetting each time (#572 regression). When the window is empty (fresh
1197
+ // orchestrator resuming a prior session), rehydrate it from the DB
1198
+ // dispatch ledger so cross-session re-dispatch loops are detected (#482).
1199
+ if (this.dispatchHistory.getRecentWindow().length === 0) {
1200
+ this.dispatchHistory.rehydrate();
1201
+ }
1148
1202
  this.lastStuckRecoveryKey = null;
1203
+ // ADR-030: drop the prior "from" — the first advance after resume has no
1204
+ // edge to assert (avoids a false illegal-edge across the pause boundary).
1205
+ this.lastDerivedPhase = null;
1149
1206
  this.status.phase = "running";
1150
1207
  this.bumpTransition();
1151
1208
  this.journalTransition({ name: "resume" });
@@ -1162,10 +1219,11 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
1162
1219
  this.status.activeUnit = undefined;
1163
1220
  this.lastAdvanceKey = null;
1164
1221
  this.lastFinalizedUnitKey = null;
1165
- // Preserve dispatchKeyWindow on pause so stuck-loop detection accumulates
1166
- // across pause/resume cycles. Only clear on a hard stop.
1222
+ this.lastDerivedPhase = null;
1223
+ // Preserve the dispatch-history window on pause so stuck-loop detection
1224
+ // accumulates across pause/resume cycles. Only clear on a hard stop.
1167
1225
  if (reason !== "pause") {
1168
- this.dispatchKeyWindow = [];
1226
+ this.dispatchHistory.clearOnRecovery();
1169
1227
  }
1170
1228
  this.lastStuckRecoveryKey = null;
1171
1229
  this.bumpTransition();
@@ -1179,9 +1237,9 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
1179
1237
  }
1180
1238
 
1181
1239
  public async completeActiveUnit(unit: { unitType: string; unitId: string }): Promise<void> {
1182
- const unitKey = `${unit.unitType}:${unit.unitId}`;
1240
+ const unitKey = buildDispatchKey(unit.unitType, unit.unitId);
1183
1241
  const activeUnitKey = this.status.activeUnit
1184
- ? `${this.status.activeUnit.unitType}:${this.status.activeUnit.unitId}`
1242
+ ? buildDispatchKey(this.status.activeUnit.unitType, this.status.activeUnit.unitId)
1185
1243
  : null;
1186
1244
  if (activeUnitKey !== unitKey) return;
1187
1245
 
@@ -1199,9 +1257,9 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
1199
1257
  }
1200
1258
 
1201
1259
  public async retryActiveUnit(unit: { unitType: string; unitId: string }): Promise<void> {
1202
- const unitKey = `${unit.unitType}:${unit.unitId}`;
1260
+ const unitKey = buildDispatchKey(unit.unitType, unit.unitId);
1203
1261
  const activeUnitKey = this.status.activeUnit
1204
- ? `${this.status.activeUnit.unitType}:${this.status.activeUnit.unitId}`
1262
+ ? buildDispatchKey(this.status.activeUnit.unitType, this.status.activeUnit.unitId)
1205
1263
  : null;
1206
1264
  if (activeUnitKey !== unitKey && this.lastFinalizedUnitKey !== unitKey) return;
1207
1265
 
@@ -19,7 +19,8 @@ import {
19
19
  type PostUnitContext,
20
20
  type PreVerificationOpts,
21
21
  } from "../auto-post-unit.js";
22
- import { lastAssistantText } from "../user-input-boundary.js";
22
+ import { lastAssistantText } from "../consent-question.js";
23
+ import { resolveEffectiveUnitIsolationMode } from "../preferences.js";
23
24
  import type { Phase } from "../types.js";
24
25
  import {
25
26
  MAX_RECOVERY_CHARS,
@@ -32,6 +33,7 @@ import {
32
33
  type IterationData,
33
34
  } from "./types.js";
34
35
  import { detectStuck } from "./detect-stuck.js";
36
+ import { STUCK_WINDOW_SIZE } from "./dispatch-history.js";
35
37
  import { runUnit } from "./run-unit.js";
36
38
  import { debugLog } from "../debug-logger.js";
37
39
  import { resolveWorktreeProjectRoot, normalizeWorktreePathForCompare } from "../worktree-root.js";
@@ -106,7 +108,6 @@ import {
106
108
  } from "../root-write-leak-guard.js";
107
109
  import { classifyError, isTransient } from "../error-classifier.js";
108
110
 
109
- export const STUCK_WINDOW_SIZE = 6;
110
111
  const STUCK_RECOVERY_ATTEMPTS_KEY = "stuck_recovery_attempts";
111
112
  const ZERO_TOOL_PROVIDER_ERROR_PREFIX_RE =
112
113
  /^(?:api error(?::|$|\s*\()|provider error(?::|$|\s*\()|request failed\b|(?:http\s*)?(?:429|500|502|503)\b|\b(?:econnreset|etimedout|econnrefused|epipe)\b|socket hang up\b|fetch failed\b|(?:network|connection|server) error(?::|$)|connection (?:reset|refused)(?::|$|\s+by\b)|dns\b.*(?:fail|error|timeout)|unexpected eof\b|stream idle timeout\b|partial response received\b|stream_exhausted\b|terminated(?::|$)|(?:connection|stream|request)\b.{0,40}\bterminated\b|other side closed\b|rate.?limit(?:ed| exceeded| reached| error)|too many requests\b|you(?:'ve| have) (?:hit|reached) your (?:\w+ )?limit\b|.*\b(?:usage|session|weekly|daily|monthly|quota) limit\b|limit\b.{0,40}\bresets?\b|out of extra usage\b|service.?unavailable\b|internal(?: server)? error(?::|$)|internal(?:[_-]server)?[_-]error\b|server[_-]error\b|(?:provider|server|api|model|codex|claude|openai|anthropic|gemini)\b.{0,80}\boverloaded\b|overloaded\b.{0,80}\b(?:provider|server|api|model)\b|context (?:window|length) exceed|context window exceed)/i;
@@ -362,7 +363,15 @@ async function validateSourceWriteWorktreeSafety(
362
363
  if (!writesSource) return null;
363
364
 
364
365
  const projectRoot = s.canonicalProjectRoot ?? resolveWorktreeProjectRoot(s.basePath, s.originalBasePath);
365
- const isolationMode = deps.getIsolationMode(projectRoot);
366
+ // A degraded session already fell back to the milestone branch in the
367
+ // project root — validating against the canonical worktree root there
368
+ // would fail every dispatch with a false invalid-root. The same applies
369
+ // to a stranded-recovery session that adopted the milestone branch.
370
+ const isolationMode = resolveEffectiveUnitIsolationMode(
371
+ deps.getIsolationMode(projectRoot),
372
+ s.isolationDegraded,
373
+ s.strandedRecoveryIsolationMode,
374
+ );
366
375
  if (isolationMode !== "worktree") return null;
367
376
 
368
377
  const safety = createWorktreeSafetyModule();
@@ -10,10 +10,9 @@ import type {
10
10
 
11
11
  import { deriveState } from "./state.js";
12
12
  import { loadFile } from "./files.js";
13
- import { isDbAvailable, getMilestoneSlices } from "./gsd-db.js";
14
- import { parseRoadmap } from "./parsers-legacy.js";
13
+ import { isDbAvailable, getClosedSliceIds } from "./gsd-db.js";
15
14
  import {
16
- resolveMilestoneFile, resolveSliceFile, relSliceFile,
15
+ resolveSliceFile, relSliceFile,
17
16
  } from "./paths.js";
18
17
  import {
19
18
  buildResearchSlicePrompt,
@@ -182,21 +181,9 @@ export async function dispatchDirectPhase(
182
181
 
183
182
  case "reassess":
184
183
  case "reassess-roadmap": {
185
- // DB primary pathget completed slices, fall back to file parsing when DB has no data
186
- let completedSliceIds: string[] = [];
187
- if (isDbAvailable()) {
188
- completedSliceIds = getMilestoneSlices(mid).filter(s => s.status === "complete").map(s => s.id);
189
- }
190
- if (completedSliceIds.length === 0) {
191
- // File-based fallback: parse roadmap checkboxes
192
- const roadmapPath = resolveMilestoneFile(dispatchBase, mid, "ROADMAP");
193
- if (roadmapPath) {
194
- const roadmapContent = await loadFile(roadmapPath);
195
- if (roadmapContent) {
196
- completedSliceIds = parseRoadmap(roadmapContent).slices.filter(s => s.done).map(s => s.id);
197
- }
198
- }
199
- }
184
+ // DB-authoritative read (ADR-017)markdown projections are never
185
+ // consulted for dispatch decisions. No DB rows means no completed slices.
186
+ const completedSliceIds = isDbAvailable() ? getClosedSliceIds(mid) : [];
200
187
  if (completedSliceIds.length === 0) {
201
188
  ctx.ui.notify("Cannot dispatch reassess-roadmap: no completed slices.", "warning");
202
189
  return;
@@ -222,20 +209,9 @@ export async function dispatchDirectPhase(
222
209
  // incomplete) slice. After slice completion, state.activeSlice advances
223
210
  // to the next incomplete slice, so we find the last done slice from the
224
211
  // roadmap instead (#1693).
225
- let uatCompletedSliceIds: string[] = [];
226
- if (isDbAvailable()) {
227
- uatCompletedSliceIds = getMilestoneSlices(mid).filter(s => s.status === "complete").map(s => s.id);
228
- }
229
- if (uatCompletedSliceIds.length === 0) {
230
- // File-based fallback: parse roadmap checkboxes
231
- const roadmapPath = resolveMilestoneFile(dispatchBase, mid, "ROADMAP");
232
- if (roadmapPath) {
233
- const roadmapContent = await loadFile(roadmapPath);
234
- if (roadmapContent) {
235
- uatCompletedSliceIds = parseRoadmap(roadmapContent).slices.filter(s => s.done).map(s => s.id);
236
- }
237
- }
238
- }
212
+ // DB-authoritative read (ADR-017) — no markdown fallback for dispatch
213
+ // decisions.
214
+ const uatCompletedSliceIds = isDbAvailable() ? getClosedSliceIds(mid) : [];
239
215
  if (uatCompletedSliceIds.length === 0) {
240
216
  ctx.ui.notify("Cannot dispatch run-uat: no completed slices.", "warning");
241
217
  return;
@@ -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).