@opengsd/gsd-pi 1.2.0-dev.4c756166 → 1.2.0-dev.822c9439

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 (688) 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/mcp-server.js +2 -1
  7. package/dist/models-resolver.d.ts +3 -13
  8. package/dist/models-resolver.js +3 -22
  9. package/dist/resource-loader.d.ts +9 -5
  10. package/dist/resource-loader.js +116 -20
  11. package/dist/resources/.managed-resources-content-hash +1 -1
  12. package/dist/resources/GSD-WORKFLOW.md +5 -4
  13. package/dist/resources/extensions/async-jobs/async-bash-tool.js +30 -64
  14. package/dist/resources/extensions/async-jobs/await-tool.js +80 -12
  15. package/dist/resources/extensions/async-jobs/index.js +65 -0
  16. package/dist/resources/extensions/async-jobs/job-manager.js +12 -1
  17. package/dist/resources/extensions/bg-shell/bg-shell-command.js +6 -6
  18. package/dist/resources/extensions/bg-shell/bg-shell-tool.js +10 -7
  19. package/dist/resources/extensions/bg-shell/overlay.js +9 -6
  20. package/dist/resources/extensions/bg-shell/process-manager.js +54 -25
  21. package/dist/resources/extensions/bg-shell/readiness-detector.js +11 -0
  22. package/dist/resources/extensions/bg-shell/utilities.js +5 -2
  23. package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +209 -88
  24. package/dist/resources/extensions/browser-tools/engine/selection.js +73 -5
  25. package/dist/resources/extensions/browser-tools/index.js +69 -12
  26. package/dist/resources/extensions/claude-code-cli/models.js +9 -0
  27. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +38 -6
  28. package/dist/resources/extensions/gsd/auto/custom-verify-retry-store.js +17 -2
  29. package/dist/resources/extensions/gsd/auto/detect-stuck.js +33 -13
  30. package/dist/resources/extensions/gsd/auto/dispatch-history.js +105 -0
  31. package/dist/resources/extensions/gsd/auto/dispatch-key.js +37 -0
  32. package/dist/resources/extensions/gsd/auto/loop.js +4 -1
  33. package/dist/resources/extensions/gsd/auto/orchestrator.js +122 -58
  34. package/dist/resources/extensions/gsd/auto/phases.js +54 -6
  35. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  36. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +11 -34
  37. package/dist/resources/extensions/gsd/auto-dispatch.js +50 -58
  38. package/dist/resources/extensions/gsd/auto-model-selection.js +36 -13
  39. package/dist/resources/extensions/gsd/auto-post-unit.js +43 -14
  40. package/dist/resources/extensions/gsd/auto-prompts.js +81 -19
  41. package/dist/resources/extensions/gsd/auto-start.js +24 -26
  42. package/dist/resources/extensions/gsd/auto-tool-tracking.js +18 -0
  43. package/dist/resources/extensions/gsd/auto-unit-closeout.js +45 -21
  44. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +12 -20
  45. package/dist/resources/extensions/gsd/auto-verification.js +23 -30
  46. package/dist/resources/extensions/gsd/auto-worktree-repair.js +10 -2
  47. package/dist/resources/extensions/gsd/auto-worktree.js +49 -353
  48. package/dist/resources/extensions/gsd/auto.js +45 -21
  49. package/dist/resources/extensions/gsd/blocked-models.js +28 -0
  50. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +29 -8
  51. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +32 -12
  52. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -2
  53. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +19 -0
  54. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +229 -36
  55. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +319 -71
  56. package/dist/resources/extensions/gsd/branch-patterns.js +2 -0
  57. package/dist/resources/extensions/gsd/browser-daemon-auto-prep.js +83 -0
  58. package/dist/resources/extensions/gsd/browser-evidence.js +8 -2
  59. package/dist/resources/extensions/gsd/captures.js +5 -15
  60. package/dist/resources/extensions/gsd/closeout-recovery.js +3 -2
  61. package/dist/resources/extensions/gsd/closeout-wizard.js +92 -0
  62. package/dist/resources/extensions/gsd/commands/catalog.js +6 -62
  63. package/dist/resources/extensions/gsd/commands/context.js +16 -2
  64. package/dist/resources/extensions/gsd/commands-handlers.js +46 -3
  65. package/dist/resources/extensions/gsd/consent-question.js +353 -0
  66. package/dist/resources/extensions/gsd/consent-verdict.js +63 -0
  67. package/dist/resources/extensions/gsd/constants.js +0 -2
  68. package/dist/resources/extensions/gsd/crash-recovery.js +12 -15
  69. package/dist/resources/extensions/gsd/db/engine.js +755 -0
  70. package/dist/resources/extensions/gsd/db/queries.js +398 -0
  71. package/dist/resources/extensions/gsd/db/sql-constants.js +11 -0
  72. package/dist/resources/extensions/gsd/db/writers/cascades.js +194 -0
  73. package/dist/resources/extensions/gsd/db/writers/import-restore.js +182 -0
  74. package/dist/resources/extensions/gsd/db/writers/memory.js +149 -0
  75. package/dist/resources/extensions/gsd/db/writers/reconcile.js +458 -0
  76. package/dist/resources/extensions/gsd/db/writers/status.js +70 -0
  77. package/dist/resources/extensions/gsd/dispatch-guard.js +10 -35
  78. package/dist/resources/extensions/gsd/doctor-engine-checks.js +5 -5
  79. package/dist/resources/extensions/gsd/doctor-environment.js +5 -11
  80. package/dist/resources/extensions/gsd/doctor-format.js +9 -6
  81. package/dist/resources/extensions/gsd/doctor-git-checks.js +6 -21
  82. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +21 -16
  83. package/dist/resources/extensions/gsd/engine-hook-contract.js +70 -0
  84. package/dist/resources/extensions/gsd/error-classifier.js +9 -0
  85. package/dist/resources/extensions/gsd/exec-sandbox.js +30 -10
  86. package/dist/resources/extensions/gsd/files.js +33 -19
  87. package/dist/resources/extensions/gsd/git-service.js +1 -0
  88. package/dist/resources/extensions/gsd/gitignore.js +3 -0
  89. package/dist/resources/extensions/gsd/gsd-command-home.js +22 -12
  90. package/dist/resources/extensions/gsd/gsd-db.js +172 -2048
  91. package/dist/resources/extensions/gsd/guidance.js +158 -0
  92. package/dist/resources/extensions/gsd/guided-flow.js +57 -8
  93. package/dist/resources/extensions/gsd/markdown-renderer.js +10 -0
  94. package/dist/resources/extensions/gsd/mcp-filter.js +2 -19
  95. package/dist/resources/extensions/gsd/mcp-tool-name.js +5 -13
  96. package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +1 -1
  97. package/dist/resources/extensions/gsd/migrate/safety.js +20 -9
  98. package/dist/resources/extensions/gsd/migration-auto-check.js +24 -3
  99. package/dist/resources/extensions/gsd/milestone-closeout.js +85 -24
  100. package/dist/resources/extensions/gsd/milestone-planning-persistence.js +2 -2
  101. package/dist/resources/extensions/gsd/milestone-reopen-events.js +3 -5
  102. package/dist/resources/extensions/gsd/model-cost-table.js +1 -0
  103. package/dist/resources/extensions/gsd/model-router.js +3 -0
  104. package/dist/resources/extensions/gsd/notification-store.js +11 -4
  105. package/dist/resources/extensions/gsd/parallel-merge.js +14 -11
  106. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +11 -7
  107. package/dist/resources/extensions/gsd/parsers-legacy.js +16 -4
  108. package/dist/resources/extensions/gsd/paths.js +37 -24
  109. package/dist/resources/extensions/gsd/pre-execution-checks.js +91 -3
  110. package/dist/resources/extensions/gsd/preferences-models.js +14 -48
  111. package/dist/resources/extensions/gsd/preferences.js +14 -0
  112. package/dist/resources/extensions/gsd/projection-flush.js +7 -0
  113. package/dist/resources/extensions/gsd/prompts/complete-slice.md +3 -3
  114. package/dist/resources/extensions/gsd/prompts/execute-task.md +1 -1
  115. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  116. package/dist/resources/extensions/gsd/prompts/plan-slice.md +2 -2
  117. package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -1
  118. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  119. package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  120. package/dist/resources/extensions/gsd/prompts/replan-slice.md +2 -2
  121. package/dist/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  122. package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
  123. package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  124. package/dist/resources/extensions/gsd/prompts/run-uat.md +7 -5
  125. package/dist/resources/extensions/gsd/prompts/system.md +5 -2
  126. package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -1
  127. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
  128. package/dist/resources/extensions/gsd/provider-error-guidance.js +1 -5
  129. package/dist/resources/extensions/gsd/provider-switch-observer.js +1 -1
  130. package/dist/resources/extensions/gsd/publication.js +87 -0
  131. package/dist/resources/extensions/gsd/reactive-graph.js +8 -1
  132. package/dist/resources/extensions/gsd/recovery-classification.js +41 -87
  133. package/dist/resources/extensions/gsd/roadmap-slices.js +25 -3
  134. package/dist/resources/extensions/gsd/safety/destructive-confirmation.js +108 -0
  135. package/dist/resources/extensions/gsd/safety/evidence-collector.js +37 -4
  136. package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +7 -2
  137. package/dist/resources/extensions/gsd/safety/file-change-validator.js +10 -0
  138. package/dist/resources/extensions/gsd/session-lock.js +1 -1
  139. package/dist/resources/extensions/gsd/state-transition-matrix.js +38 -0
  140. package/dist/resources/extensions/gsd/state.js +6 -20
  141. package/dist/resources/extensions/gsd/status-guards.js +56 -8
  142. package/dist/resources/extensions/gsd/stop-notice.js +57 -0
  143. package/dist/resources/extensions/gsd/tool-contract.js +14 -3
  144. package/dist/resources/extensions/gsd/tool-presentation-plan.js +4 -4
  145. package/dist/resources/extensions/gsd/tool-surface-readiness.js +56 -0
  146. package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -2
  147. package/dist/resources/extensions/gsd/tools/complete-slice.js +46 -55
  148. package/dist/resources/extensions/gsd/tools/complete-task.js +3 -2
  149. package/dist/resources/extensions/gsd/tools/exec-tool.js +10 -8
  150. package/dist/resources/extensions/gsd/tools/plan-slice.js +14 -8
  151. package/dist/resources/extensions/gsd/tools/plan-task.js +2 -2
  152. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +2 -2
  153. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +13 -31
  154. package/dist/resources/extensions/gsd/tools/reopen-slice.js +16 -35
  155. package/dist/resources/extensions/gsd/tools/reopen-task.js +2 -2
  156. package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -2
  157. package/dist/resources/extensions/gsd/tools/skip-slice.js +18 -36
  158. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +67 -2
  159. package/dist/resources/extensions/gsd/uat-policy.js +42 -16
  160. package/dist/resources/extensions/gsd/undo.js +8 -7
  161. package/dist/resources/extensions/gsd/unit-closeout.js +138 -0
  162. package/dist/resources/extensions/gsd/unit-context-composer.js +74 -1
  163. package/dist/resources/extensions/gsd/unit-context-manifest.js +4 -27
  164. package/dist/resources/extensions/gsd/unit-registry.js +337 -0
  165. package/dist/resources/extensions/gsd/unit-tool-contracts.js +9 -182
  166. package/dist/resources/extensions/gsd/verdict-parser.js +1 -1
  167. package/dist/resources/extensions/gsd/verification-verdict.js +2 -1
  168. package/dist/resources/extensions/gsd/web-app-uat.js +45 -8
  169. package/dist/resources/extensions/gsd/workflow-event-ledger.js +91 -0
  170. package/dist/resources/extensions/gsd/workflow-event-vocabulary.js +46 -0
  171. package/dist/resources/extensions/gsd/workflow-events.js +6 -18
  172. package/dist/resources/extensions/gsd/workflow-reconcile.js +21 -56
  173. package/dist/resources/extensions/gsd/workflow-tool-surface.js +1 -1
  174. package/dist/resources/extensions/gsd/worktree-git-recovery.js +293 -0
  175. package/dist/resources/extensions/gsd/worktree-lifecycle.js +12 -3
  176. package/dist/resources/extensions/gsd/worktree-manager.js +52 -29
  177. package/dist/resources/extensions/gsd/worktree-placement.js +59 -0
  178. package/dist/resources/extensions/gsd/worktree-reentry.js +12 -8
  179. package/dist/resources/extensions/gsd/worktree-root.js +28 -6
  180. package/dist/resources/extensions/gsd/worktree-safety.js +8 -5
  181. package/dist/resources/extensions/gsd/worktree-session-state.js +12 -11
  182. package/dist/resources/extensions/gsd/worktree.js +8 -1
  183. package/dist/resources/extensions/search-the-web/native-search.js +5 -3
  184. package/dist/resources/extensions/shared/browser-contract.js +59 -0
  185. package/dist/resources/extensions/shared/gsd-browser-cli.js +116 -6
  186. package/dist/resources/shared/gsd-browser-path-sync.js +214 -0
  187. package/dist/resources/shared/package-manager-detection.js +1 -1
  188. package/dist/resources/shared/package.json +3 -0
  189. package/dist/resources/skills/create-skill/SKILL.md +3 -0
  190. package/dist/resources/skills/create-skill/references/executable-code.md +1 -1
  191. package/dist/resources/skills/create-skill/references/skill-structure.md +1 -0
  192. package/dist/resources/skills/create-skill/workflows/add-reference.md +8 -3
  193. package/dist/resources/skills/create-skill/workflows/add-script.md +4 -2
  194. package/dist/resources/skills/create-skill/workflows/add-template.md +3 -1
  195. package/dist/resources/skills/create-skill/workflows/add-workflow.md +8 -3
  196. package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
  197. package/dist/resources/skills/create-skill/workflows/verify-skill.md +9 -4
  198. package/dist/resources/skills/spike-wrap-up/SKILL.md +9 -9
  199. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  200. package/dist/update-check.d.ts +2 -0
  201. package/dist/update-check.js +24 -1
  202. package/dist/update-cmd.js +20 -3
  203. package/dist/web/standalone/.next/BUILD_ID +1 -1
  204. package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
  205. package/dist/web/standalone/.next/build-manifest.json +3 -3
  206. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  207. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  208. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  209. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  210. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  211. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  212. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  213. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  214. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  215. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  216. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  217. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  218. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  219. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  220. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  221. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  222. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  223. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  224. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  225. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  226. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  227. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  228. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  229. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  230. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  231. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  232. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  233. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  234. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  235. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  236. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  237. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  238. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  239. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  240. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
  241. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  242. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  243. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  244. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  245. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  246. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  247. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  248. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  249. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  250. package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
  251. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  252. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  253. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  254. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  255. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  256. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  257. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  258. package/dist/web/standalone/.next/server/app/api/update/route.js.nft.json +1 -1
  259. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  260. package/dist/web/standalone/.next/server/app/index.html +1 -1
  261. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  262. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  263. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  264. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  265. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  266. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  267. package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
  268. package/dist/web/standalone/.next/server/chunks/5124.js +1 -1
  269. package/dist/web/standalone/.next/server/chunks/{5047.js → 5942.js} +2 -2
  270. package/dist/web/standalone/.next/server/chunks/8357.js +2 -2
  271. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  272. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  273. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  274. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  275. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  276. package/dist/web/standalone/.next/static/chunks/{796.cf859a427a2cb2ac.js → 796.e0bdc932325d7e03.js} +1 -1
  277. package/dist/web/standalone/.next/static/chunks/{webpack-fbea77b5f9953368.js → webpack-f0285ce91d4ec9ef.js} +1 -1
  278. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  279. package/dist/web/standalone/package.json +1 -1
  280. package/dist/worktree-cli.js +3 -6
  281. package/dist/worktree-status-banner.js +7 -11
  282. package/package.json +1 -1
  283. package/packages/cloud-mcp-gateway/package.json +2 -2
  284. package/packages/contracts/dist/rpc.d.ts +1 -0
  285. package/packages/contracts/dist/rpc.d.ts.map +1 -1
  286. package/packages/contracts/dist/rpc.js.map +1 -1
  287. package/packages/contracts/dist/workflow.d.ts +4 -0
  288. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  289. package/packages/contracts/dist/workflow.js.map +1 -1
  290. package/packages/contracts/package.json +1 -1
  291. package/packages/daemon/package.json +4 -4
  292. package/packages/gsd-agent-core/package.json +5 -5
  293. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +5 -0
  294. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  295. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +5 -0
  296. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  297. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  298. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +7 -0
  299. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  300. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  301. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +8 -1
  302. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  303. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.d.ts.map +1 -1
  304. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js +11 -1
  305. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js.map +1 -1
  306. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
  307. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +4 -4
  308. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
  309. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  310. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +3 -1
  311. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
  312. package/packages/gsd-agent-modes/package.json +7 -7
  313. package/packages/mcp-server/dist/cli.js +9 -1
  314. package/packages/mcp-server/dist/cli.js.map +1 -1
  315. package/packages/mcp-server/dist/moonshot-tool-schema.d.ts +29 -0
  316. package/packages/mcp-server/dist/moonshot-tool-schema.d.ts.map +1 -0
  317. package/packages/mcp-server/dist/moonshot-tool-schema.js +50 -0
  318. package/packages/mcp-server/dist/moonshot-tool-schema.js.map +1 -0
  319. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  320. package/packages/mcp-server/dist/server.js +4 -0
  321. package/packages/mcp-server/dist/server.js.map +1 -1
  322. package/packages/mcp-server/dist/workflow-tools.d.ts +26 -18
  323. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  324. package/packages/mcp-server/dist/workflow-tools.js +145 -59
  325. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  326. package/packages/mcp-server/package.json +5 -4
  327. package/packages/native/package.json +1 -1
  328. package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts +1 -0
  329. package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts.map +1 -1
  330. package/packages/pi-agent-core/dist/harness/env/nodejs.js +34 -3
  331. package/packages/pi-agent-core/dist/harness/env/nodejs.js.map +1 -1
  332. package/packages/pi-agent-core/dist/index.d.ts +1 -0
  333. package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
  334. package/packages/pi-agent-core/dist/index.js +3 -0
  335. package/packages/pi-agent-core/dist/index.js.map +1 -1
  336. package/packages/pi-agent-core/package.json +1 -1
  337. package/packages/pi-ai/README.md +1 -0
  338. package/packages/pi-ai/dist/image-models.generated.d.ts +2 -2
  339. package/packages/pi-ai/dist/image-models.generated.js +6 -6
  340. package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
  341. package/packages/pi-ai/dist/index.d.ts +2 -0
  342. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  343. package/packages/pi-ai/dist/index.js +2 -0
  344. package/packages/pi-ai/dist/index.js.map +1 -1
  345. package/packages/pi-ai/dist/models.generated.d.ts +158 -17
  346. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  347. package/packages/pi-ai/dist/models.generated.js +132 -17
  348. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  349. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  350. package/packages/pi-ai/dist/providers/anthropic.js +12 -7
  351. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  352. package/packages/pi-ai/dist/providers/google-shared.d.ts +5 -0
  353. package/packages/pi-ai/dist/providers/google-shared.d.ts.map +1 -1
  354. package/packages/pi-ai/dist/providers/google-shared.js +12 -3
  355. package/packages/pi-ai/dist/providers/google-shared.js.map +1 -1
  356. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  357. package/packages/pi-ai/dist/providers/openai-completions.js +7 -3
  358. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  359. package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts +9 -0
  360. package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts.map +1 -0
  361. package/packages/pi-ai/dist/utils/moonshot-tool-schema.js +34 -0
  362. package/packages/pi-ai/dist/utils/moonshot-tool-schema.js.map +1 -0
  363. package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
  364. package/packages/pi-ai/dist/utils/oauth/github-copilot.js +6 -2
  365. package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
  366. package/packages/pi-ai/package.json +3 -2
  367. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +2 -2
  368. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  369. package/packages/pi-coding-agent/dist/core/auth-storage.js +19 -13
  370. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  371. package/packages/pi-coding-agent/dist/core/capability-patches.d.ts.map +1 -1
  372. package/packages/pi-coding-agent/dist/core/capability-patches.js +3 -1
  373. package/packages/pi-coding-agent/dist/core/capability-patches.js.map +1 -1
  374. package/packages/pi-coding-agent/dist/core/provider-readiness.d.ts.map +1 -1
  375. package/packages/pi-coding-agent/dist/core/provider-readiness.js +13 -6
  376. package/packages/pi-coding-agent/dist/core/provider-readiness.js.map +1 -1
  377. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts +11 -0
  378. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
  379. package/packages/pi-coding-agent/dist/core/tools/bash.js +53 -11
  380. package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
  381. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  382. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  383. package/packages/pi-coding-agent/dist/index.js +1 -1
  384. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  385. package/packages/pi-coding-agent/dist/utils/shell.d.ts +28 -2
  386. package/packages/pi-coding-agent/dist/utils/shell.d.ts.map +1 -1
  387. package/packages/pi-coding-agent/dist/utils/shell.js +56 -10
  388. package/packages/pi-coding-agent/dist/utils/shell.js.map +1 -1
  389. package/packages/pi-coding-agent/package.json +7 -7
  390. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  391. package/packages/pi-tui/dist/tui.js +9 -0
  392. package/packages/pi-tui/dist/tui.js.map +1 -1
  393. package/packages/pi-tui/package.json +2 -2
  394. package/packages/rpc-client/package.json +2 -2
  395. package/pkg/package.json +1 -1
  396. package/src/resources/GSD-WORKFLOW.md +5 -4
  397. package/src/resources/extensions/async-jobs/async-bash-cancel.test.ts +360 -0
  398. package/src/resources/extensions/async-jobs/async-bash-tool.ts +33 -56
  399. package/src/resources/extensions/async-jobs/await-tool.test.ts +139 -0
  400. package/src/resources/extensions/async-jobs/await-tool.ts +82 -12
  401. package/src/resources/extensions/async-jobs/index.ts +79 -0
  402. package/src/resources/extensions/async-jobs/job-manager.ts +21 -1
  403. package/src/resources/extensions/bg-shell/bg-shell-command.ts +6 -6
  404. package/src/resources/extensions/bg-shell/bg-shell-tool.ts +10 -6
  405. package/src/resources/extensions/bg-shell/overlay.ts +9 -5
  406. package/src/resources/extensions/bg-shell/process-manager.ts +50 -25
  407. package/src/resources/extensions/bg-shell/readiness-detector.ts +12 -0
  408. package/src/resources/extensions/bg-shell/tests/lifecycle-and-utilities.test.ts +48 -1
  409. package/src/resources/extensions/bg-shell/utilities.ts +5 -2
  410. package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +265 -98
  411. package/src/resources/extensions/browser-tools/engine/selection.ts +90 -4
  412. package/src/resources/extensions/browser-tools/index.ts +71 -13
  413. package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +83 -13
  414. package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +40 -1
  415. package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +136 -0
  416. package/src/resources/extensions/claude-code-cli/models.ts +9 -0
  417. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +40 -4
  418. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +28 -0
  419. package/src/resources/extensions/gsd/auto/custom-verify-retry-store.ts +21 -3
  420. package/src/resources/extensions/gsd/auto/detect-stuck.ts +32 -9
  421. package/src/resources/extensions/gsd/auto/dispatch-history.ts +152 -0
  422. package/src/resources/extensions/gsd/auto/dispatch-key.ts +39 -0
  423. package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -1
  424. package/src/resources/extensions/gsd/auto/loop.ts +4 -1
  425. package/src/resources/extensions/gsd/auto/orchestrator.ts +137 -61
  426. package/src/resources/extensions/gsd/auto/phases.ts +74 -26
  427. package/src/resources/extensions/gsd/auto/session.ts +3 -0
  428. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +18 -48
  429. package/src/resources/extensions/gsd/auto-dispatch.ts +48 -61
  430. package/src/resources/extensions/gsd/auto-model-selection.ts +41 -12
  431. package/src/resources/extensions/gsd/auto-post-unit.ts +52 -13
  432. package/src/resources/extensions/gsd/auto-prompts.ts +118 -35
  433. package/src/resources/extensions/gsd/auto-start.ts +24 -29
  434. package/src/resources/extensions/gsd/auto-tool-tracking.ts +19 -0
  435. package/src/resources/extensions/gsd/auto-unit-closeout.ts +83 -28
  436. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +14 -21
  437. package/src/resources/extensions/gsd/auto-verification.ts +26 -28
  438. package/src/resources/extensions/gsd/auto-worktree-repair.ts +13 -2
  439. package/src/resources/extensions/gsd/auto-worktree.ts +55 -365
  440. package/src/resources/extensions/gsd/auto.ts +64 -25
  441. package/src/resources/extensions/gsd/blocked-models.ts +49 -0
  442. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +37 -10
  443. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +33 -12
  444. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -2
  445. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +24 -0
  446. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +270 -37
  447. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +368 -78
  448. package/src/resources/extensions/gsd/branch-patterns.ts +3 -0
  449. package/src/resources/extensions/gsd/browser-daemon-auto-prep.ts +108 -0
  450. package/src/resources/extensions/gsd/browser-evidence.ts +18 -2
  451. package/src/resources/extensions/gsd/captures.ts +5 -16
  452. package/src/resources/extensions/gsd/closeout-recovery.ts +2 -1
  453. package/src/resources/extensions/gsd/closeout-wizard.ts +102 -0
  454. package/src/resources/extensions/gsd/commands/catalog.ts +6 -68
  455. package/src/resources/extensions/gsd/commands/context.ts +16 -2
  456. package/src/resources/extensions/gsd/commands-handlers.ts +46 -3
  457. package/src/resources/extensions/gsd/consent-question.ts +431 -0
  458. package/src/resources/extensions/gsd/consent-verdict.ts +86 -0
  459. package/src/resources/extensions/gsd/constants.ts +0 -3
  460. package/src/resources/extensions/gsd/crash-recovery.ts +13 -11
  461. package/src/resources/extensions/gsd/db/engine.ts +809 -0
  462. package/src/resources/extensions/gsd/db/queries.ts +490 -0
  463. package/src/resources/extensions/gsd/db/sql-constants.ts +12 -0
  464. package/src/resources/extensions/gsd/db/writers/cascades.ts +237 -0
  465. package/src/resources/extensions/gsd/db/writers/import-restore.ts +310 -0
  466. package/src/resources/extensions/gsd/db/writers/memory.ts +220 -0
  467. package/src/resources/extensions/gsd/db/writers/reconcile.ts +500 -0
  468. package/src/resources/extensions/gsd/db/writers/status.ts +88 -0
  469. package/src/resources/extensions/gsd/dispatch-guard.ts +8 -31
  470. package/src/resources/extensions/gsd/doctor-engine-checks.ts +5 -4
  471. package/src/resources/extensions/gsd/doctor-environment.ts +5 -13
  472. package/src/resources/extensions/gsd/doctor-format.ts +12 -7
  473. package/src/resources/extensions/gsd/doctor-git-checks.ts +5 -22
  474. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +22 -17
  475. package/src/resources/extensions/gsd/engine-hook-contract.ts +79 -0
  476. package/src/resources/extensions/gsd/error-classifier.ts +11 -0
  477. package/src/resources/extensions/gsd/exec-sandbox.ts +49 -9
  478. package/src/resources/extensions/gsd/files.ts +33 -12
  479. package/src/resources/extensions/gsd/git-service.ts +1 -0
  480. package/src/resources/extensions/gsd/gitignore.ts +3 -0
  481. package/src/resources/extensions/gsd/gsd-command-home.ts +13 -3
  482. package/src/resources/extensions/gsd/gsd-db.ts +176 -2375
  483. package/src/resources/extensions/gsd/guidance.ts +217 -0
  484. package/src/resources/extensions/gsd/guided-flow.ts +71 -31
  485. package/src/resources/extensions/gsd/markdown-renderer.ts +11 -0
  486. package/src/resources/extensions/gsd/mcp-filter.ts +2 -23
  487. package/src/resources/extensions/gsd/mcp-tool-name.ts +6 -11
  488. package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +1 -1
  489. package/src/resources/extensions/gsd/migrate/safety.ts +18 -7
  490. package/src/resources/extensions/gsd/migration-auto-check.ts +28 -3
  491. package/src/resources/extensions/gsd/milestone-closeout.ts +109 -24
  492. package/src/resources/extensions/gsd/milestone-planning-persistence.ts +2 -2
  493. package/src/resources/extensions/gsd/milestone-reopen-events.ts +3 -6
  494. package/src/resources/extensions/gsd/model-cost-table.ts +1 -0
  495. package/src/resources/extensions/gsd/model-router.ts +3 -0
  496. package/src/resources/extensions/gsd/notification-store.ts +26 -3
  497. package/src/resources/extensions/gsd/parallel-merge.ts +12 -9
  498. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +10 -7
  499. package/src/resources/extensions/gsd/parsers-legacy.ts +16 -4
  500. package/src/resources/extensions/gsd/paths.ts +42 -22
  501. package/src/resources/extensions/gsd/pre-execution-checks.ts +109 -3
  502. package/src/resources/extensions/gsd/preferences-models.ts +12 -47
  503. package/src/resources/extensions/gsd/preferences.ts +18 -0
  504. package/src/resources/extensions/gsd/projection-flush.ts +20 -0
  505. package/src/resources/extensions/gsd/prompts/complete-slice.md +3 -3
  506. package/src/resources/extensions/gsd/prompts/execute-task.md +1 -1
  507. package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  508. package/src/resources/extensions/gsd/prompts/plan-slice.md +2 -2
  509. package/src/resources/extensions/gsd/prompts/quick-task.md +1 -1
  510. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  511. package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  512. package/src/resources/extensions/gsd/prompts/replan-slice.md +2 -2
  513. package/src/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  514. package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
  515. package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  516. package/src/resources/extensions/gsd/prompts/run-uat.md +7 -5
  517. package/src/resources/extensions/gsd/prompts/system.md +5 -2
  518. package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -1
  519. package/src/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
  520. package/src/resources/extensions/gsd/provider-error-guidance.ts +4 -9
  521. package/src/resources/extensions/gsd/provider-switch-observer.ts +1 -1
  522. package/src/resources/extensions/gsd/publication.ts +122 -0
  523. package/src/resources/extensions/gsd/reactive-graph.ts +11 -1
  524. package/src/resources/extensions/gsd/recovery-classification.ts +47 -88
  525. package/src/resources/extensions/gsd/roadmap-slices.ts +28 -3
  526. package/src/resources/extensions/gsd/safety/destructive-confirmation.ts +134 -0
  527. package/src/resources/extensions/gsd/safety/evidence-collector.ts +36 -4
  528. package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +7 -2
  529. package/src/resources/extensions/gsd/safety/file-change-validator.ts +14 -0
  530. package/src/resources/extensions/gsd/session-lock.ts +1 -1
  531. package/src/resources/extensions/gsd/state-transition-matrix.ts +42 -0
  532. package/src/resources/extensions/gsd/state.ts +9 -21
  533. package/src/resources/extensions/gsd/status-guards.ts +59 -8
  534. package/src/resources/extensions/gsd/stop-notice.ts +75 -0
  535. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +123 -0
  536. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +97 -1
  537. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +198 -26
  538. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +3 -1
  539. package/src/resources/extensions/gsd/tests/auto-post-unit-evidence-crossref-4909.test.ts +46 -0
  540. package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +65 -3
  541. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +2 -2
  542. package/src/resources/extensions/gsd/tests/auto-worktree-repair.test.ts +4 -2
  543. package/src/resources/extensions/gsd/tests/blocked-models.test.ts +19 -0
  544. package/src/resources/extensions/gsd/tests/browser-automation-contract-fixture.ts +39 -0
  545. package/src/resources/extensions/gsd/tests/browser-contract.test.ts +44 -0
  546. package/src/resources/extensions/gsd/tests/browser-daemon-auto-prep.test.ts +144 -0
  547. package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +66 -1
  548. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +44 -0
  549. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +8 -7
  550. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
  551. package/src/resources/extensions/gsd/tests/consent-question.test.ts +351 -0
  552. package/src/resources/extensions/gsd/tests/custom-verify-retry-store.test.ts +67 -0
  553. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +10 -10
  554. package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +303 -0
  555. package/src/resources/extensions/gsd/tests/discuss-routing-fixes.test.ts +12 -2
  556. package/src/resources/extensions/gsd/tests/dispatch-history.test.ts +273 -0
  557. package/src/resources/extensions/gsd/tests/dispatch-run-uat-browser-tools.test.ts +2 -1
  558. package/src/resources/extensions/gsd/tests/doctor-git-checks-terminal.test.ts +73 -0
  559. package/src/resources/extensions/gsd/tests/dynamic-bash-no-cap.test.ts +132 -0
  560. package/src/resources/extensions/gsd/tests/engine-hook-contract.test.ts +148 -0
  561. package/src/resources/extensions/gsd/tests/evidence-xref-gsd-exec.test.ts +157 -0
  562. package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +193 -0
  563. package/src/resources/extensions/gsd/tests/exec-tool.test.ts +29 -1
  564. package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +35 -1
  565. package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +33 -1
  566. package/src/resources/extensions/gsd/tests/gsd-command-home.test.ts +120 -0
  567. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +27 -0
  568. package/src/resources/extensions/gsd/tests/guidance.test.ts +148 -0
  569. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +2 -6
  570. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +58 -15
  571. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +74 -59
  572. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +3 -2
  573. package/src/resources/extensions/gsd/tests/integration/gsd-integration-fixture.ts +80 -0
  574. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +199 -0
  575. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +3 -1
  576. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +85 -1
  577. package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +95 -4
  578. package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +32 -1
  579. package/src/resources/extensions/gsd/tests/notification-store.test.ts +32 -0
  580. package/src/resources/extensions/gsd/tests/oauth-api-model-routing.test.ts +167 -0
  581. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +18 -0
  582. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +138 -0
  583. package/src/resources/extensions/gsd/tests/phases-terminal-complete-idempotent.test.ts +242 -0
  584. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +63 -2
  585. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +193 -1
  586. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +124 -6
  587. package/src/resources/extensions/gsd/tests/provider-error-guidance.test.ts +3 -3
  588. package/src/resources/extensions/gsd/tests/publication.test.ts +120 -0
  589. package/src/resources/extensions/gsd/tests/recovery-classification-illegal-transition.test.ts +30 -0
  590. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +248 -1
  591. package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +68 -0
  592. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +20 -1
  593. package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +38 -0
  594. package/src/resources/extensions/gsd/tests/session-switch-clears-pending-autostart.test.ts +108 -0
  595. package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +43 -6
  596. package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +36 -0
  597. package/src/resources/extensions/gsd/tests/status-guards.test.ts +38 -0
  598. package/src/resources/extensions/gsd/tests/stop-notice.test.ts +70 -0
  599. package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +17 -0
  600. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +76 -0
  601. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +8 -0
  602. package/src/resources/extensions/gsd/tests/tool-surface-readiness.test.ts +155 -0
  603. package/src/resources/extensions/gsd/tests/tool-unavailable-retry.test.ts +33 -0
  604. package/src/resources/extensions/gsd/tests/transport-gate-double-complete.test.ts +139 -0
  605. package/src/resources/extensions/gsd/tests/uat-policy.test.ts +112 -29
  606. package/src/resources/extensions/gsd/tests/unit-closeout.test.ts +209 -0
  607. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +67 -2
  608. package/src/resources/extensions/gsd/tests/unit-registry.test.ts +163 -0
  609. package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +8 -0
  610. package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +2 -0
  611. package/src/resources/extensions/gsd/tests/web-app-uat.test.ts +44 -1
  612. package/src/resources/extensions/gsd/tests/workflow-events.test.ts +19 -0
  613. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -2
  614. package/src/resources/extensions/gsd/tests/workflow-reconcile.test.ts +20 -0
  615. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +275 -40
  616. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +41 -4
  617. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +22 -1
  618. package/src/resources/extensions/gsd/tests/worktree-placement.test.ts +113 -0
  619. package/src/resources/extensions/gsd/tests/worktree-reentry.test.ts +1 -1
  620. package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +3 -1
  621. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +12 -6
  622. package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +24 -2
  623. package/src/resources/extensions/gsd/tests/worktree.test.ts +18 -0
  624. package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +358 -0
  625. package/src/resources/extensions/gsd/tests/write-gate.test.ts +109 -1
  626. package/src/resources/extensions/gsd/tool-contract.ts +38 -3
  627. package/src/resources/extensions/gsd/tool-presentation-plan.ts +4 -4
  628. package/src/resources/extensions/gsd/tool-surface-readiness.ts +76 -0
  629. package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
  630. package/src/resources/extensions/gsd/tools/complete-slice.ts +45 -70
  631. package/src/resources/extensions/gsd/tools/complete-task.ts +3 -2
  632. package/src/resources/extensions/gsd/tools/exec-tool.ts +9 -8
  633. package/src/resources/extensions/gsd/tools/plan-slice.ts +14 -8
  634. package/src/resources/extensions/gsd/tools/plan-task.ts +2 -2
  635. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +2 -2
  636. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +13 -40
  637. package/src/resources/extensions/gsd/tools/reopen-slice.ts +16 -44
  638. package/src/resources/extensions/gsd/tools/reopen-task.ts +2 -2
  639. package/src/resources/extensions/gsd/tools/replan-slice.ts +2 -2
  640. package/src/resources/extensions/gsd/tools/skip-slice.ts +18 -44
  641. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +81 -2
  642. package/src/resources/extensions/gsd/uat-policy.ts +62 -16
  643. package/src/resources/extensions/gsd/undo.ts +9 -8
  644. package/src/resources/extensions/gsd/unit-closeout.ts +201 -0
  645. package/src/resources/extensions/gsd/unit-context-composer.ts +111 -1
  646. package/src/resources/extensions/gsd/unit-context-manifest.ts +4 -28
  647. package/src/resources/extensions/gsd/unit-registry.ts +412 -0
  648. package/src/resources/extensions/gsd/unit-tool-contracts.ts +27 -192
  649. package/src/resources/extensions/gsd/verdict-parser.ts +1 -1
  650. package/src/resources/extensions/gsd/verification-verdict.ts +4 -2
  651. package/src/resources/extensions/gsd/web-app-uat.ts +51 -8
  652. package/src/resources/extensions/gsd/workflow-event-ledger.ts +131 -0
  653. package/src/resources/extensions/gsd/workflow-event-vocabulary.ts +59 -0
  654. package/src/resources/extensions/gsd/workflow-events.ts +12 -20
  655. package/src/resources/extensions/gsd/workflow-reconcile.ts +29 -62
  656. package/src/resources/extensions/gsd/workflow-tool-surface.ts +4 -1
  657. package/src/resources/extensions/gsd/worktree-git-recovery.ts +314 -0
  658. package/src/resources/extensions/gsd/worktree-lifecycle.ts +13 -9
  659. package/src/resources/extensions/gsd/worktree-manager.ts +53 -29
  660. package/src/resources/extensions/gsd/worktree-placement.ts +63 -0
  661. package/src/resources/extensions/gsd/worktree-reentry.ts +10 -7
  662. package/src/resources/extensions/gsd/worktree-root.ts +29 -6
  663. package/src/resources/extensions/gsd/worktree-safety.ts +8 -5
  664. package/src/resources/extensions/gsd/worktree-session-state.ts +11 -11
  665. package/src/resources/extensions/gsd/worktree.ts +7 -1
  666. package/src/resources/extensions/search-the-web/native-search.ts +5 -3
  667. package/src/resources/extensions/shared/browser-contract.ts +66 -0
  668. package/src/resources/extensions/shared/gsd-browser-cli.ts +141 -6
  669. package/src/resources/shared/gsd-browser-path-sync.ts +273 -0
  670. package/src/resources/shared/package-manager-detection.ts +1 -1
  671. package/src/resources/shared/package.json +3 -0
  672. package/src/resources/skills/create-skill/SKILL.md +3 -0
  673. package/src/resources/skills/create-skill/references/executable-code.md +1 -1
  674. package/src/resources/skills/create-skill/references/skill-structure.md +1 -0
  675. package/src/resources/skills/create-skill/workflows/add-reference.md +8 -3
  676. package/src/resources/skills/create-skill/workflows/add-script.md +4 -2
  677. package/src/resources/skills/create-skill/workflows/add-template.md +3 -1
  678. package/src/resources/skills/create-skill/workflows/add-workflow.md +8 -3
  679. package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
  680. package/src/resources/skills/create-skill/workflows/verify-skill.md +9 -4
  681. package/src/resources/skills/spike-wrap-up/SKILL.md +9 -9
  682. package/dist/resources/extensions/gsd/user-input-boundary.js +0 -218
  683. package/dist/resources/skills/gsd-browser/SKILL.md +0 -41
  684. package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +0 -173
  685. package/src/resources/extensions/gsd/user-input-boundary.ts +0 -216
  686. package/src/resources/skills/gsd-browser/SKILL.md +0 -41
  687. /package/dist/web/standalone/.next/static/{DUFWcMFRH3iXh7d2fbrOF → yWwBo-w09Y_W-nmeeWFRp}/_buildManifest.js +0 -0
  688. /package/dist/web/standalone/.next/static/{DUFWcMFRH3iXh7d2fbrOF → yWwBo-w09Y_W-nmeeWFRp}/_ssgManifest.js +0 -0
@@ -9,9 +9,10 @@
9
9
  // the real collaborators (state-reconciliation, doctor-proactive,
10
10
  // auto-dispatch, recovery-classification, tool-contract, worktree-safety,
11
11
  // uok/gate-runner, journal, session-lock, ctx.ui.notify) directly.
12
- import { debugCount, debugTime } from "../debug-logger.js";
12
+ import { debugCount, debugLog, debugTime } from "../debug-logger.js";
13
13
  import { reconcileBeforeDispatch } from "../state-reconciliation.js";
14
- import { resolveDispatch } from "../auto-dispatch.js";
14
+ import { isLegalEdge, IllegalPhaseTransitionError } from "../state-transition-matrix.js";
15
+ import { hasPendingDeepStage, resolveDispatch } from "../auto-dispatch.js";
15
16
  import { classifyFailure } from "../recovery-classification.js";
16
17
  import { verifyExpectedArtifact, refreshRecoveryDbForArtifact } from "../auto-recovery.js";
17
18
  import { invalidateAllCaches } from "../cache.js";
@@ -24,7 +25,7 @@ import { checkResourcesStale, autoWorktreeBranch, mergeMilestoneToMain } from ".
24
25
  import { getSessionLockStatus } from "../session-lock.js";
25
26
  import { resolveUokFlags } from "../uok/flags.js";
26
27
  import { emitJournalEvent as _emitJournalEvent } from "../journal.js";
27
- import { loadEffectiveGSDPreferences, getIsolationMode } from "../preferences.js";
28
+ import { loadEffectiveGSDPreferences, getIsolationMode, resolveEffectiveUnitIsolationMode } from "../preferences.js";
28
29
  import { detectWorktreeName, getMainBranch, resolveProjectRoot, resolveWorktreeProjectRoot, } from "../worktree.js";
29
30
  import { getPriorSliceCompletionBlocker } from "../dispatch-guard.js";
30
31
  import { GitServiceImpl } from "../git-service.js";
@@ -41,21 +42,14 @@ import { isDbAvailable, getSlice, getTask, } from "../gsd-db.js";
41
42
  import { refreshWorkflowDatabaseFromDisk } from "../db-workspace.js";
42
43
  import { getErrorMessage } from "../error-utils.js";
43
44
  import { logWarning } from "../workflow-logger.js";
45
+ import { normalizeRealPath } from "../paths.js";
46
+ import { buildDispatchKey, createDispatchHistory, STUCK_WINDOW_SIZE, } from "./dispatch-history.js";
44
47
  import { existsSync, readFileSync } from "node:fs";
45
48
  import { join } from "node:path";
46
49
  import { evaluateAllCompleteSettlement } from "../milestone-settlement.js";
47
50
  function now() {
48
51
  return Date.now();
49
52
  }
50
- /**
51
- * Size of the dispatch-decision ring buffer used by the Auto Orchestration
52
- * module's stuck-loop detector. When the same `${unitType}:${unitId}` key
53
- * fills the window, advance() blocks with `action: "stop"`.
54
- *
55
- * Mirrors the legacy `STUCK_WINDOW_SIZE` in auto/phases.ts so behaviour is
56
- * preserved across the eventual cutover (issue #5791).
57
- */
58
- export const STUCK_WINDOW_SIZE = 6;
59
53
  function noRemainingUnitsOutcome(stateSnapshot) {
60
54
  if (stateSnapshot.phase === "complete") {
61
55
  return {
@@ -117,14 +111,25 @@ function shouldAdoptActiveMilestone(state, activeSession, activeDispatchBasePath
117
111
  export async function decideOrchestratorDispatch(ctx, pi, dispatchBasePath, session, input) {
118
112
  const state = input.stateSnapshot;
119
113
  const active = state.activeMilestone;
120
- if (!active)
121
- return null;
122
114
  const activeSession = input.session ?? session;
123
115
  const activeDispatchBasePath = activeSession?.basePath || dispatchBasePath;
124
- if (activeSession && shouldAdoptActiveMilestone(state, activeSession, activeDispatchBasePath)) {
116
+ const prefs = loadEffectiveGSDPreferences(activeDispatchBasePath)?.preferences;
117
+ if (!active) {
118
+ if (state.phase !== "pre-planning")
119
+ return null;
120
+ if (!hasPendingDeepStage(prefs, activeDispatchBasePath)) {
121
+ return {
122
+ kind: "blocked",
123
+ reason: state.nextAction || "No active milestone. Run /gsd unpark <id> or create a new milestone.",
124
+ action: "stop",
125
+ };
126
+ }
127
+ }
128
+ if (active && activeSession && shouldAdoptActiveMilestone(state, activeSession, activeDispatchBasePath)) {
125
129
  activeSession.currentMilestoneId = active.id;
126
130
  }
127
- const prefs = loadEffectiveGSDPreferences(activeDispatchBasePath)?.preferences;
131
+ const dispatchMid = active?.id ?? activeSession?.currentMilestoneId ?? "";
132
+ const dispatchMidTitle = active?.title ?? "";
128
133
  // Derive session-derived dispatch inputs the same way phases.ts:runDispatch does
129
134
  // (#5789). Prefer caller-supplied values when present so test harnesses and
130
135
  // alternative wirings can inject deterministic snapshots; otherwise pull from
@@ -152,8 +157,15 @@ export async function decideOrchestratorDispatch(ctx, pi, dispatchBasePath, sess
152
157
  })
153
158
  ? "true"
154
159
  : "false");
160
+ // Only replay a milestone-scoped verification retry when a milestone is
161
+ // active. Pre-PR (#712 fix), `!active` returned null before reaching this
162
+ // block, so the retry was preserved for a future tick. The new
163
+ // pre-planning + deep-pending fall-through must keep that contract:
164
+ // otherwise a stale execute-task / complete-slice / complete-milestone
165
+ // retry whose target milestone has since been parked would preempt
166
+ // project-level deep rules like `discuss-project`.
155
167
  const pendingRetry = session?.pendingVerificationRetryDispatch;
156
- if (session && pendingRetry) {
168
+ if (session && pendingRetry && active) {
157
169
  session.pendingVerificationRetryDispatch = null;
158
170
  const alreadyClosedReason = getAlreadyClosedDispatchReason(pendingRetry.unitType, pendingRetry.unitId);
159
171
  if (alreadyClosedReason) {
@@ -171,8 +183,8 @@ export async function decideOrchestratorDispatch(ctx, pi, dispatchBasePath, sess
171
183
  }
172
184
  const action = await resolveDispatch({
173
185
  basePath: activeDispatchBasePath,
174
- mid: active.id,
175
- midTitle: active.title,
186
+ mid: dispatchMid,
187
+ midTitle: dispatchMidTitle,
176
188
  state,
177
189
  prefs,
178
190
  session: activeSession,
@@ -217,8 +229,8 @@ export async function decideOrchestratorDispatch(ctx, pi, dispatchBasePath, sess
217
229
  prompt: action.prompt,
218
230
  pauseAfterUatDispatch: action.pauseAfterDispatch ?? false,
219
231
  state,
220
- mid: active.id,
221
- midTitle: active.title,
232
+ mid: dispatchMid,
233
+ midTitle: dispatchMidTitle,
222
234
  };
223
235
  session.pendingOrchestrationDispatch = pending;
224
236
  }
@@ -243,7 +255,13 @@ export class AutoOrchestrator {
243
255
  seq = 0;
244
256
  lastAdvanceKey = null;
245
257
  lastFinalizedUnitKey = null;
246
- dispatchKeyWindow = [];
258
+ // Dispatch History module (#482): the dispatch-decision window with
259
+ // cross-session DB rehydration and full detect-stuck rules.
260
+ dispatchHistory;
261
+ // ADR-030 Phase Transition Invariant: the prior advance's reconciled Phase,
262
+ // the "from" endpoint of the edge check. In-memory; reset on start/resume/stop
263
+ // so the first advance of a session has no edge to assert.
264
+ lastDerivedPhase = null;
247
265
  // #442: the unit key we last attempted graduated stuck-recovery for. Bounds
248
266
  // recovery to one attempt per stuck episode per run (reset on start/resume/
249
267
  // stop), mirroring the legacy Level-1-then-Level-2 escalation in phases.ts.
@@ -255,6 +273,13 @@ export class AutoOrchestrator {
255
273
  this.runtimeBasePath = context.runtimeBasePath;
256
274
  this.s = context.session;
257
275
  this.flowId = `auto-orchestrator-${Date.now()}`;
276
+ this.dispatchHistory = createDispatchHistory({
277
+ windowSize: STUCK_WINDOW_SIZE,
278
+ // Same stable scope the auto-loop uses for stuck-state persistence so
279
+ // rehydration reads the rows the dispatch ledger wrote for this project.
280
+ resolveScopeId: () => normalizeRealPath(this.s.scope?.workspace.projectRoot ??
281
+ (this.s.originalBasePath || this.s.basePath || this.runtimeBasePath)) || null,
282
+ });
258
283
  }
259
284
  // ── Live base-path resolution (was the wiring factory's getLiveDispatchBasePath) ──
260
285
  getLiveDispatchBasePath() {
@@ -476,8 +501,7 @@ export class AutoOrchestrator {
476
501
  }
477
502
  // ── WorktreeAdapter (folded) ─────────────────────────────────────────────
478
503
  getEffectiveUnitIsolationMode(basePath) {
479
- const configuredMode = getIsolationMode(basePath);
480
- return configuredMode === "worktree" && this.s.isolationDegraded ? "branch" : configuredMode;
504
+ return resolveEffectiveUnitIsolationMode(getIsolationMode(basePath), this.s.isolationDegraded, this.s.strandedRecoveryIsolationMode);
481
505
  }
482
506
  buildLifecycle() {
483
507
  return new WorktreeLifecycle(this.s, {
@@ -576,6 +600,21 @@ export class AutoOrchestrator {
576
600
  const recovery = classifyFailure(input);
577
601
  return { action: recovery.action, reason: recovery.reason };
578
602
  }
603
+ /**
604
+ * ADR-030 Phase Transition Invariant (advisory mode). The matrix is an
605
+ * assertion, not a decision-maker — deriveState already chose the phase; we
606
+ * only observe illegal *derived* edges that survived reconciliation. The
607
+ * matrix is still a sparse hardening spec, so this is telemetry-only (no
608
+ * block) until it is expanded into a validated legal-edge graph. To enforce:
609
+ * `throw violation;` instead of logging — recovery-classification maps
610
+ * IllegalPhaseTransitionError to kind "illegal-transition" (escalate).
611
+ */
612
+ observePhaseTransition(from, to) {
613
+ if (isLegalEdge(from, to))
614
+ return;
615
+ const violation = new IllegalPhaseTransitionError(from, to);
616
+ debugLog("phase-transition-advisory", { from, to, message: violation.message });
617
+ }
579
618
  // ── Lifecycle verbs ──────────────────────────────────────────────────────
580
619
  /**
581
620
  * #442: graduated stuck recovery, ported from the legacy
@@ -593,7 +632,7 @@ export class AutoOrchestrator {
593
632
  * skipped result) instead of stopping.
594
633
  */
595
634
  tryStuckArtifactRecovery(unitType, unitId) {
596
- const key = `${unitType}:${unitId}`;
635
+ const key = buildDispatchKey(unitType, unitId);
597
636
  if (this.lastStuckRecoveryKey === key)
598
637
  return false; // already tried this episode
599
638
  const basePath = this.getLiveDispatchBasePath();
@@ -608,7 +647,7 @@ export class AutoOrchestrator {
608
647
  return false;
609
648
  this.lastStuckRecoveryKey = key;
610
649
  invalidateAllCaches();
611
- this.dispatchKeyWindow = [];
650
+ this.dispatchHistory.clearOnRecovery();
612
651
  this.lastAdvanceKey = null;
613
652
  this.lastFinalizedUnitKey = null;
614
653
  return true;
@@ -634,8 +673,14 @@ export class AutoOrchestrator {
634
673
  async start(_sessionContext) {
635
674
  this.lastAdvanceKey = null;
636
675
  this.lastFinalizedUnitKey = null;
637
- this.dispatchKeyWindow = [];
676
+ // #482: the DB dispatch ledger is the source of truth across sessions.
677
+ // Discard any in-memory window and rebuild it from the ledger so a unit
678
+ // that was re-dispatched in previous sessions is detected as stuck here
679
+ // instead of silently re-dispatching forever.
680
+ this.dispatchHistory.clearOnRecovery();
681
+ this.dispatchHistory.rehydrate();
638
682
  this.lastStuckRecoveryKey = null;
683
+ this.lastDerivedPhase = null;
639
684
  this.status.phase = "running";
640
685
  this.bumpTransition();
641
686
  this.journalTransition({ name: "start" });
@@ -721,6 +766,11 @@ export class AutoOrchestrator {
721
766
  this.postAdvanceRecord(blocked);
722
767
  return blocked;
723
768
  }
769
+ const reconciledPhase = reconciliation.stateSnapshot.phase;
770
+ if (this.lastDerivedPhase !== null) {
771
+ this.observePhaseTransition(this.lastDerivedPhase, reconciledPhase);
772
+ }
773
+ this.lastDerivedPhase = reconciledPhase;
724
774
  const decision = await this.decideNextUnit({ stateSnapshot: reconciliation.stateSnapshot });
725
775
  if (!decision) {
726
776
  const settlementBlock = this.evaluateNoRemainingUnitsSettlement(reconciliation.stateSnapshot);
@@ -728,7 +778,7 @@ export class AutoOrchestrator {
728
778
  this.status.phase = "paused";
729
779
  this.status.activeUnit = undefined;
730
780
  this.lastAdvanceKey = null;
731
- this.dispatchKeyWindow = [];
781
+ this.dispatchHistory.clearOnRecovery();
732
782
  this.bumpTransition();
733
783
  this.journalTransition({ name: "advance-blocked", reason: settlementBlock.reason });
734
784
  this.postAdvanceRecord(settlementBlock);
@@ -744,7 +794,7 @@ export class AutoOrchestrator {
744
794
  this.status.phase = "stopped";
745
795
  this.status.activeUnit = undefined;
746
796
  this.lastAdvanceKey = null;
747
- this.dispatchKeyWindow = [];
797
+ this.dispatchHistory.clearOnRecovery();
748
798
  this.bumpTransition();
749
799
  this.journalTransition({ name: "advance-stopped", reason: stopped.reason });
750
800
  this.postAdvanceRecord(stopped);
@@ -792,16 +842,12 @@ export class AutoOrchestrator {
792
842
  this.postAdvanceRecord(blocked);
793
843
  return blocked;
794
844
  }
795
- const nextKey = `${decision.unitType}:${decision.unitId}`;
796
- // Record every dispatch decision in the ring buffer before pre-flight
845
+ // Record every dispatch decision in the history window before pre-flight
797
846
  // checks so the stuck-loop detector observes the full decision history
798
847
  // (including decisions that idempotency would otherwise short-circuit).
799
- // The ring is capped at STUCK_WINDOW_SIZE and evicts oldest-first.
800
- this.dispatchKeyWindow.push(nextKey);
801
- if (this.dispatchKeyWindow.length > STUCK_WINDOW_SIZE) {
802
- this.dispatchKeyWindow.shift();
803
- }
804
- const matchingCount = this.dispatchKeyWindow.filter((k) => k === nextKey).length;
848
+ // The window is capped at STUCK_WINDOW_SIZE and evicts oldest-first.
849
+ const nextKey = this.dispatchHistory.recordDispatch(decision.unitType, decision.unitId);
850
+ const matchingCount = this.dispatchHistory.countMatching(nextKey);
805
851
  if (this.lastFinalizedUnitKey === nextKey) {
806
852
  // #442: the unit re-dispatched immediately after finalizing may have
807
853
  // actually completed on disk with a stale DB. Verify + recover before
@@ -833,22 +879,30 @@ export class AutoOrchestrator {
833
879
  // checks coexist: idempotency for the common immediate-repeat case,
834
880
  // stuck-loop for the saturated-window case.
835
881
  if (this.lastAdvanceKey === nextKey && matchingCount < STUCK_WINDOW_SIZE) {
882
+ // Unit already active — benign no-op. Return skipped so the loop re-polls
883
+ // without cancelling the in-flight unit (blocked+pause would force-cancel it).
836
884
  this.clearPendingDispatch();
837
- const blocked = { kind: "blocked", reason: "idempotent advance: unit already active", action: "pause" };
885
+ const skipped = { kind: "skipped", reason: "idempotent advance: unit already active" };
838
886
  this.journalTransition({
839
- name: "advance-blocked",
840
- reason: blocked.reason,
887
+ name: "advance-skipped",
888
+ reason: skipped.reason,
841
889
  unitType: decision.unitType,
842
890
  unitId: decision.unitId,
843
891
  });
844
- this.postAdvanceRecord(blocked);
845
- return blocked;
892
+ this.postAdvanceRecord(skipped);
893
+ return skipped;
846
894
  }
847
- // Stuck-loop detection: when the ring is saturated with copies of
848
- // `nextKey` (count >= STUCK_WINDOW_SIZE), the orchestrator has been
849
- // picking the same unit across the whole window and must hard-stop with
850
- // a diagnosable reason.
851
- if (matchingCount >= STUCK_WINDOW_SIZE) {
895
+ // Stuck-loop detection: when the window is saturated with copies of
896
+ // `nextKey` (count >= STUCK_WINDOW_SIZE), consult the Dispatch History
897
+ // module's full detect-stuck rule set for the verdict instead of the old
898
+ // bare saturation count. This keeps the saturation threshold (the window
899
+ // deliberately records benign idempotent repeats, so earlier-firing
900
+ // rules would false-positive on pause/resume re-advances) while gaining
901
+ // retry-budget suppression and diagnosable rule reasons. A saturated
902
+ // window with no verdict means the dispatch ledger says we are inside
903
+ // the unit's retry-backoff budget — let the retry proceed.
904
+ const stuckVerdict = matchingCount >= STUCK_WINDOW_SIZE ? this.dispatchHistory.detectStuck() : null;
905
+ if (stuckVerdict) {
852
906
  // #442: before declaring a stuck loop, verify the unit didn't actually
853
907
  // complete on disk (stale DB) and recover if so — legacy graduated
854
908
  // stuck-recovery parity. Otherwise hard-stop with a diagnosable reason.
@@ -859,7 +913,7 @@ export class AutoOrchestrator {
859
913
  this.clearPendingDispatch();
860
914
  const blocked = {
861
915
  kind: "blocked",
862
- reason: `stuck-loop: ${nextKey} picked ${matchingCount} times`,
916
+ reason: `stuck-loop: ${stuckVerdict.reason}`,
863
917
  action: "stop",
864
918
  };
865
919
  this.journalTransition({
@@ -949,7 +1003,7 @@ export class AutoOrchestrator {
949
1003
  if (result.kind === "stopped") {
950
1004
  this.lastAdvanceKey = null;
951
1005
  this.lastFinalizedUnitKey = null;
952
- this.dispatchKeyWindow = [];
1006
+ this.dispatchHistory.clearOnRecovery();
953
1007
  this.status.activeUnit = undefined;
954
1008
  }
955
1009
  this.bumpTransition();
@@ -978,9 +1032,18 @@ export class AutoOrchestrator {
978
1032
  async resume() {
979
1033
  this.lastAdvanceKey = null;
980
1034
  this.lastFinalizedUnitKey = null;
981
- // Preserve dispatchKeyWindow across resume so stuck-loop detection
982
- // accumulates across pause/resume cycles rather than resetting each time.
1035
+ // Preserve the dispatch-history window across an in-process resume so
1036
+ // stuck-loop detection accumulates across pause/resume cycles rather than
1037
+ // resetting each time (#572 regression). When the window is empty (fresh
1038
+ // orchestrator resuming a prior session), rehydrate it from the DB
1039
+ // dispatch ledger so cross-session re-dispatch loops are detected (#482).
1040
+ if (this.dispatchHistory.getRecentWindow().length === 0) {
1041
+ this.dispatchHistory.rehydrate();
1042
+ }
983
1043
  this.lastStuckRecoveryKey = null;
1044
+ // ADR-030: drop the prior "from" — the first advance after resume has no
1045
+ // edge to assert (avoids a false illegal-edge across the pause boundary).
1046
+ this.lastDerivedPhase = null;
984
1047
  this.status.phase = "running";
985
1048
  this.bumpTransition();
986
1049
  this.journalTransition({ name: "resume" });
@@ -996,10 +1059,11 @@ export class AutoOrchestrator {
996
1059
  this.status.activeUnit = undefined;
997
1060
  this.lastAdvanceKey = null;
998
1061
  this.lastFinalizedUnitKey = null;
999
- // Preserve dispatchKeyWindow on pause so stuck-loop detection accumulates
1000
- // across pause/resume cycles. Only clear on a hard stop.
1062
+ this.lastDerivedPhase = null;
1063
+ // Preserve the dispatch-history window on pause so stuck-loop detection
1064
+ // accumulates across pause/resume cycles. Only clear on a hard stop.
1001
1065
  if (reason !== "pause") {
1002
- this.dispatchKeyWindow = [];
1066
+ this.dispatchHistory.clearOnRecovery();
1003
1067
  }
1004
1068
  this.lastStuckRecoveryKey = null;
1005
1069
  this.bumpTransition();
@@ -1011,9 +1075,9 @@ export class AutoOrchestrator {
1011
1075
  return { ...this.status, activeUnit: this.status.activeUnit ? { ...this.status.activeUnit } : undefined };
1012
1076
  }
1013
1077
  async completeActiveUnit(unit) {
1014
- const unitKey = `${unit.unitType}:${unit.unitId}`;
1078
+ const unitKey = buildDispatchKey(unit.unitType, unit.unitId);
1015
1079
  const activeUnitKey = this.status.activeUnit
1016
- ? `${this.status.activeUnit.unitType}:${this.status.activeUnit.unitId}`
1080
+ ? buildDispatchKey(this.status.activeUnit.unitType, this.status.activeUnit.unitId)
1017
1081
  : null;
1018
1082
  if (activeUnitKey !== unitKey)
1019
1083
  return;
@@ -1030,9 +1094,9 @@ export class AutoOrchestrator {
1030
1094
  });
1031
1095
  }
1032
1096
  async retryActiveUnit(unit) {
1033
- const unitKey = `${unit.unitType}:${unit.unitId}`;
1097
+ const unitKey = buildDispatchKey(unit.unitType, unit.unitId);
1034
1098
  const activeUnitKey = this.status.activeUnit
1035
- ? `${this.status.activeUnit.unitType}:${this.status.activeUnit.unitId}`
1099
+ ? buildDispatchKey(this.status.activeUnit.unitType, this.status.activeUnit.unitId)
1036
1100
  : null;
1037
1101
  if (activeUnitKey !== unitKey && this.lastFinalizedUnitKey !== unitKey)
1038
1102
  return;
@@ -10,9 +10,11 @@
10
10
  */
11
11
  import { importExtensionModule } from "@gsd/pi-coding-agent";
12
12
  import { USER_DRIVEN_DEEP_UNITS, isAwaitingUserInput, } from "../auto-post-unit.js";
13
- import { lastAssistantText } from "../user-input-boundary.js";
13
+ import { lastAssistantText } from "../consent-question.js";
14
+ import { resolveEffectiveUnitIsolationMode, getIsolationMode } from "../preferences.js";
14
15
  import { MAX_RECOVERY_CHARS, BUDGET_THRESHOLDS, MAX_FINALIZE_TIMEOUTS, } from "./types.js";
15
16
  import { detectStuck } from "./detect-stuck.js";
17
+ import { STUCK_WINDOW_SIZE } from "./dispatch-history.js";
16
18
  import { runUnit } from "./run-unit.js";
17
19
  import { debugLog } from "../debug-logger.js";
18
20
  import { resolveWorktreeProjectRoot, normalizeWorktreePathForCompare } from "../worktree-root.js";
@@ -33,9 +35,10 @@ import { writeUnitRuntimeRecord } from "../unit-runtime.js";
33
35
  import { withTimeout, FINALIZE_PRE_TIMEOUT_MS, FINALIZE_POST_TIMEOUT_MS } from "./finalize-timeout.js";
34
36
  import { getEligibleSlices } from "../slice-parallel-eligibility.js";
35
37
  import { isSliceParallelActive, startSliceParallel } from "../slice-parallel-orchestrator.js";
36
- import { isDbAvailable, getMilestoneSlices, getSlice, getTask } from "../gsd-db.js";
38
+ import { isDbAvailable, getMilestone, getMilestoneSlices, getSlice, getTask } from "../gsd-db.js";
37
39
  import { refreshWorkflowDatabaseFromDisk } from "../db-workspace.js";
38
40
  import { isClosedStatus } from "../status-guards.js";
41
+ import { findUnmergedCompletedMilestones } from "../unmerged-milestone-guard.js";
39
42
  import { setRuntimeKv } from "../db/runtime-kv.js";
40
43
  import { getLatestForUnit } from "../db/unit-dispatches.js";
41
44
  import { reconcileBeforeSpawn } from "../state-reconciliation.js";
@@ -48,7 +51,8 @@ import { parseUnitId } from "../unit-id.js";
48
51
  import { createCheckpoint, cleanupCheckpoint, rollbackToCheckpoint } from "../safety/git-checkpoint.js";
49
52
  import { resolveSafetyHarnessConfig } from "../safety/safety-harness.js";
50
53
  import { getContextPauseAction } from "../auto-budget.js";
51
- import { getWorkflowTransportSupportError, getRequiredWorkflowToolsForAutoUnit, supportsStructuredQuestions, } from "../workflow-mcp.js";
54
+ import { supportsStructuredQuestions } from "../workflow-mcp.js";
55
+ import { getUnitWorkflowDispatchReadinessError } from "../tool-contract.js";
52
56
  import { prepareWorkflowMcpForProject } from "../workflow-mcp-auto-prep.js";
53
57
  import { applyThinkingLevelForModel, floorThinkingLevelForUnit, getRegisteredToolSnapshot, getToolBaselineSnapshot, } from "../auto-model-selection.js";
54
58
  import { resolveManifest } from "../unit-context-manifest.js";
@@ -59,7 +63,6 @@ import { buildPhaseHandoffOutcome, setAutoActiveStatus, setAutoOutcomeWidget } f
59
63
  import { getConsecutiveDispatchBlocker } from "../dispatch-guard.js";
60
64
  import { captureRootDirtySnapshot, detectRootWriteLeak, formatRootWriteLeakMessage, } from "../root-write-leak-guard.js";
61
65
  import { classifyError, isTransient } from "../error-classifier.js";
62
- export const STUCK_WINDOW_SIZE = 6;
63
66
  const STUCK_RECOVERY_ATTEMPTS_KEY = "stuck_recovery_attempts";
64
67
  const ZERO_TOOL_PROVIDER_ERROR_PREFIX_RE = /^(?: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;
65
68
  const ZERO_TOOL_PROVIDER_ERROR_SIGNAL_RE = /(?:\b(?:http|status(?: code)?|code|error:)\s*(?:429|500|502|503)\b|\b(?:api|provider) error\s*[:(]?\s*(?:429|500|502|503)\b|\b(?:typeerror|error):\s*(?:fetch failed\b|socket hang up\b|terminated(?::|$)|connection (?:reset|refused)(?::|$|\s+by\b)|(?:network|connection|server) error(?::|$)|stream idle timeout\b|partial response received\b|unexpected eof\b)|\b(?:server_error|api_error|stream_exhausted(?:_without_result)?)\b|\b(?:econnreset|etimedout|econnrefused|epipe)\b|context (?:window|length) exceed|context window exceed)/i;
@@ -265,7 +268,11 @@ async function validateSourceWriteWorktreeSafety(ic, unitType, unitId, milestone
265
268
  if (!writesSource)
266
269
  return null;
267
270
  const projectRoot = s.canonicalProjectRoot ?? resolveWorktreeProjectRoot(s.basePath, s.originalBasePath);
268
- const isolationMode = deps.getIsolationMode(projectRoot);
271
+ // A degraded session already fell back to the milestone branch in the
272
+ // project root — validating against the canonical worktree root there
273
+ // would fail every dispatch with a false invalid-root. The same applies
274
+ // to a stranded-recovery session that adopted the milestone branch.
275
+ const isolationMode = resolveEffectiveUnitIsolationMode(deps.getIsolationMode(projectRoot), s.isolationDegraded, s.strandedRecoveryIsolationMode);
269
276
  if (isolationMode !== "worktree")
270
277
  return null;
271
278
  const safety = createWorktreeSafetyModule();
@@ -595,6 +602,36 @@ async function failClosedOnFinalizeTimeout(ic, iterData, loopState, stage, start
595
602
  drainLogs();
596
603
  return { action: "break", reason: progressKind };
597
604
  }
605
+ export async function shouldSkipTerminalMilestoneCloseout(s, state, mid) {
606
+ const closeoutMilestoneId = mid ?? s.currentMilestoneId ?? state.lastCompletedMilestone?.id;
607
+ if (s.completionStopInProgress) {
608
+ return { skip: true, milestoneId: closeoutMilestoneId };
609
+ }
610
+ if (!closeoutMilestoneId) {
611
+ return { skip: false };
612
+ }
613
+ if (isDbAvailable())
614
+ refreshWorkflowDatabaseFromDisk();
615
+ const closeoutBasePath = s.originalBasePath || s.canonicalProjectRoot || s.basePath;
616
+ let closeoutMergePending = false;
617
+ if (getIsolationMode(closeoutBasePath) !== "none") {
618
+ try {
619
+ const blockers = await findUnmergedCompletedMilestones(closeoutBasePath);
620
+ closeoutMergePending = blockers.some((blocker) => blocker.milestoneId === closeoutMilestoneId);
621
+ }
622
+ catch {
623
+ // Fail open: without git/DB inspection we cannot safely treat closeout as done.
624
+ closeoutMergePending = true;
625
+ }
626
+ }
627
+ const milestoneAlreadyClosedOut = isDbAvailable()
628
+ && isClosedStatus(getMilestone(closeoutMilestoneId)?.status ?? "")
629
+ && !closeoutMergePending;
630
+ if (milestoneAlreadyClosedOut) {
631
+ return { skip: true, milestoneId: closeoutMilestoneId };
632
+ }
633
+ return { skip: false, milestoneId: closeoutMilestoneId };
634
+ }
598
635
  // ─── runPreDispatch ───────────────────────────────────────────────────────────
599
636
  /**
600
637
  * Phase 1: Pre-dispatch — resource guard, health gate, state derivation,
@@ -957,6 +994,13 @@ export async function runPreDispatch(ic, loopState) {
957
994
  deps.setActiveMilestoneId(s.basePath, mid);
958
995
  }
959
996
  // ── Terminal conditions ──────────────────────────────────────────────
997
+ if (state.phase === "complete") {
998
+ const closeoutSkip = await shouldSkipTerminalMilestoneCloseout(s, state, mid);
999
+ if (closeoutSkip.skip) {
1000
+ debugLog("autoLoop", { phase: "complete", reason: "milestone-already-closed", milestoneId: closeoutSkip.milestoneId });
1001
+ return { action: "break", reason: "milestone-complete" };
1002
+ }
1003
+ }
960
1004
  if (!mid) {
961
1005
  if (s.currentUnit) {
962
1006
  await deps.closeoutUnit(ctx, s.basePath, s.currentUnit.type, s.currentUnit.id, s.currentUnit.startedAt, deps.buildSnapshotOpts(s.currentUnit.type, s.currentUnit.id));
@@ -1764,7 +1808,8 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
1764
1808
  s.currentDispatchedModelId = s.currentUnitModel
1765
1809
  ? `${s.currentUnitModel.provider ?? ""}/${s.currentUnitModel.id ?? ""}`
1766
1810
  : null;
1767
- const compatibilityError = getWorkflowTransportSupportError(s.currentUnitModel?.provider ?? ctx.model?.provider, getRequiredWorkflowToolsForAutoUnit(unitType), {
1811
+ const compatibilityError = getUnitWorkflowDispatchReadinessError({
1812
+ provider: s.currentUnitModel?.provider ?? ctx.model?.provider,
1768
1813
  projectRoot: s.basePath,
1769
1814
  surface: "auto-mode",
1770
1815
  unitType,
@@ -1843,6 +1888,9 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
1843
1888
  causedBy: "unit-start",
1844
1889
  });
1845
1890
  s.lastToolInvocationError = null; // #2883: clear stale error from previous unit
1891
+ if (nextDispatchCount <= 1) {
1892
+ s.toolUnavailableRetries = 0;
1893
+ }
1846
1894
  const unitStartSeq = ic.nextSeq();
1847
1895
  deps.emitJournalEvent({ ts: new Date().toISOString(), flowId: ic.flowId, seq: unitStartSeq, eventType: "unit-start", data: { unitType, unitId } });
1848
1896
  deps.captureAvailableSkills();
@@ -126,6 +126,8 @@ export class AutoSession {
126
126
  /** Set when a GSD tool execution ends with isError due to malformed/truncated
127
127
  * JSON arguments. Checked by postUnitPreVerification to break retry loops. */
128
128
  lastToolInvocationError = null;
129
+ /** Consecutive tool-unavailable retries for the current unit (MCP startup race). */
130
+ toolUnavailableRetries = 0;
129
131
  /** Agent-end messages from the just-finished unit, consumed during finalize. */
130
132
  lastUnitAgentEndMessages = null;
131
133
  /** Set when turn-level git action fails during closeout. */
@@ -306,6 +308,7 @@ export class AutoSession {
306
308
  this.lastPreExecFailure = null;
307
309
  this.preExecRetryCount.clear();
308
310
  this.lastToolInvocationError = null;
311
+ this.toolUnavailableRetries = 0;
309
312
  this.lastUnitAgentEndMessages = null;
310
313
  this.lastGitActionFailure = null;
311
314
  this.lastGitActionStatus = null;
@@ -4,14 +4,13 @@
4
4
  */
5
5
  import { deriveState } from "./state.js";
6
6
  import { loadFile } from "./files.js";
7
- import { isDbAvailable, getMilestoneSlices } from "./gsd-db.js";
8
- import { parseRoadmap } from "./parsers-legacy.js";
9
- import { resolveMilestoneFile, resolveSliceFile, relSliceFile, } from "./paths.js";
7
+ import { isDbAvailable, getClosedSliceIds } from "./gsd-db.js";
8
+ import { resolveSliceFile, relSliceFile, } from "./paths.js";
10
9
  import { buildResearchSlicePrompt, buildResearchMilestonePrompt, buildPlanSlicePrompt, buildPlanMilestonePrompt, buildExecuteTaskPrompt, buildCompleteSlicePrompt, buildCompleteMilestonePrompt, buildValidateMilestonePrompt, buildReassessRoadmapPrompt, buildRunUatPrompt, buildReplanSlicePrompt, } from "./auto-prompts.js";
11
10
  import { loadEffectiveGSDPreferences } from "./preferences.js";
12
11
  import { pauseAuto } from "./auto.js";
13
12
  import { resolveCanonicalMilestoneRoot } from "./worktree-manager.js";
14
- import { getWorkflowTransportSupportError, getRequiredWorkflowToolsForAutoUnit, } from "./workflow-mcp.js";
13
+ import { getUnitWorkflowDispatchReadinessError } from "./tool-contract.js";
15
14
  export async function dispatchDirectPhase(ctx, pi, phase, base) {
16
15
  const state = await deriveState(base);
17
16
  const mid = state.activeMilestone?.id;
@@ -135,21 +134,9 @@ export async function dispatchDirectPhase(ctx, pi, phase, base) {
135
134
  }
136
135
  case "reassess":
137
136
  case "reassess-roadmap": {
138
- // DB primary pathget completed slices, fall back to file parsing when DB has no data
139
- let completedSliceIds = [];
140
- if (isDbAvailable()) {
141
- completedSliceIds = getMilestoneSlices(mid).filter(s => s.status === "complete").map(s => s.id);
142
- }
143
- if (completedSliceIds.length === 0) {
144
- // File-based fallback: parse roadmap checkboxes
145
- const roadmapPath = resolveMilestoneFile(dispatchBase, mid, "ROADMAP");
146
- if (roadmapPath) {
147
- const roadmapContent = await loadFile(roadmapPath);
148
- if (roadmapContent) {
149
- completedSliceIds = parseRoadmap(roadmapContent).slices.filter(s => s.done).map(s => s.id);
150
- }
151
- }
152
- }
137
+ // DB-authoritative read (ADR-017)markdown projections are never
138
+ // consulted for dispatch decisions. No DB rows means no completed slices.
139
+ const completedSliceIds = isDbAvailable() ? getClosedSliceIds(mid) : [];
153
140
  if (completedSliceIds.length === 0) {
154
141
  ctx.ui.notify("Cannot dispatch reassess-roadmap: no completed slices.", "warning");
155
142
  return;
@@ -173,20 +160,9 @@ export async function dispatchDirectPhase(ctx, pi, phase, base) {
173
160
  // incomplete) slice. After slice completion, state.activeSlice advances
174
161
  // to the next incomplete slice, so we find the last done slice from the
175
162
  // roadmap instead (#1693).
176
- let uatCompletedSliceIds = [];
177
- if (isDbAvailable()) {
178
- uatCompletedSliceIds = getMilestoneSlices(mid).filter(s => s.status === "complete").map(s => s.id);
179
- }
180
- if (uatCompletedSliceIds.length === 0) {
181
- // File-based fallback: parse roadmap checkboxes
182
- const roadmapPath = resolveMilestoneFile(dispatchBase, mid, "ROADMAP");
183
- if (roadmapPath) {
184
- const roadmapContent = await loadFile(roadmapPath);
185
- if (roadmapContent) {
186
- uatCompletedSliceIds = parseRoadmap(roadmapContent).slices.filter(s => s.done).map(s => s.id);
187
- }
188
- }
189
- }
163
+ // DB-authoritative read (ADR-017) — no markdown fallback for dispatch
164
+ // decisions.
165
+ const uatCompletedSliceIds = isDbAvailable() ? getClosedSliceIds(mid) : [];
190
166
  if (uatCompletedSliceIds.length === 0) {
191
167
  ctx.ui.notify("Cannot dispatch run-uat: no completed slices.", "warning");
192
168
  return;
@@ -225,7 +201,8 @@ export async function dispatchDirectPhase(ctx, pi, phase, base) {
225
201
  ctx.ui.notify(`Unknown phase "${phase}". Valid phases: research, plan, execute, complete, validate, reassess, uat, replan.`, "warning");
226
202
  return;
227
203
  }
228
- const compatibilityError = getWorkflowTransportSupportError(ctx.model?.provider, getRequiredWorkflowToolsForAutoUnit(unitType), {
204
+ const compatibilityError = getUnitWorkflowDispatchReadinessError({
205
+ provider: ctx.model?.provider,
229
206
  projectRoot,
230
207
  surface: "direct phase dispatch",
231
208
  unitType,