@opengsd/gsd-pi 1.1.1-dev.b2556262 → 1.2.0-dev.0b870afa

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 (934) hide show
  1. package/dist/cli-style.d.ts +17 -0
  2. package/dist/cli-style.js +28 -0
  3. package/dist/cli-web-branch.d.ts +2 -0
  4. package/dist/cli-web-branch.js +9 -2
  5. package/dist/cli.js +1 -1
  6. package/dist/headless-events.d.ts +4 -2
  7. package/dist/headless-events.js +14 -34
  8. package/dist/help-text.js +5 -0
  9. package/dist/mcp-server.js +2 -1
  10. package/dist/models-resolver.d.ts +3 -13
  11. package/dist/models-resolver.js +3 -22
  12. package/dist/project-sessions.js +4 -2
  13. package/dist/resource-loader.js +2 -14
  14. package/dist/resources/.managed-resources-content-hash +1 -1
  15. package/dist/resources/GSD-WORKFLOW.md +5 -4
  16. package/dist/resources/extensions/ask-user-questions.js +78 -23
  17. package/dist/resources/extensions/async-jobs/async-bash-tool.js +30 -64
  18. package/dist/resources/extensions/async-jobs/await-tool.js +80 -12
  19. package/dist/resources/extensions/async-jobs/index.js +65 -0
  20. package/dist/resources/extensions/async-jobs/job-manager.js +12 -1
  21. package/dist/resources/extensions/bg-shell/bg-shell-command.js +6 -6
  22. package/dist/resources/extensions/bg-shell/bg-shell-tool.js +10 -7
  23. package/dist/resources/extensions/bg-shell/overlay.js +9 -6
  24. package/dist/resources/extensions/bg-shell/process-manager.js +54 -25
  25. package/dist/resources/extensions/bg-shell/readiness-detector.js +11 -0
  26. package/dist/resources/extensions/bg-shell/utilities.js +5 -2
  27. package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +209 -88
  28. package/dist/resources/extensions/browser-tools/engine/selection.js +73 -5
  29. package/dist/resources/extensions/browser-tools/index.js +69 -12
  30. package/dist/resources/extensions/claude-code-cli/models.js +9 -0
  31. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +139 -243
  32. package/dist/resources/extensions/claude-code-cli/turn-assembler.js +224 -0
  33. package/dist/resources/extensions/github-sync/templates.js +3 -3
  34. package/dist/resources/extensions/gsd/artifact-projection.js +14 -0
  35. package/dist/resources/extensions/gsd/auto/contracts.js +8 -1
  36. package/dist/resources/extensions/gsd/auto/custom-verify-retry-store.js +17 -2
  37. package/dist/resources/extensions/gsd/auto/detect-stuck.js +33 -13
  38. package/dist/resources/extensions/gsd/auto/dispatch-history.js +105 -0
  39. package/dist/resources/extensions/gsd/auto/dispatch-key.js +37 -0
  40. package/dist/resources/extensions/gsd/auto/loop.js +77 -56
  41. package/dist/resources/extensions/gsd/auto/orchestrator.js +860 -96
  42. package/dist/resources/extensions/gsd/auto/phases.js +81 -8
  43. package/dist/resources/extensions/gsd/auto/run-unit.js +2 -1
  44. package/dist/resources/extensions/gsd/auto/session.js +6 -0
  45. package/dist/resources/extensions/gsd/auto-dashboard.js +16 -4
  46. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +11 -34
  47. package/dist/resources/extensions/gsd/auto-dispatch.js +56 -63
  48. package/dist/resources/extensions/gsd/auto-model-selection.js +44 -13
  49. package/dist/resources/extensions/gsd/auto-post-unit.js +47 -17
  50. package/dist/resources/extensions/gsd/auto-prompts.js +271 -27
  51. package/dist/resources/extensions/gsd/auto-recovery.js +48 -49
  52. package/dist/resources/extensions/gsd/auto-runtime-state.js +17 -0
  53. package/dist/resources/extensions/gsd/auto-start.js +36 -49
  54. package/dist/resources/extensions/gsd/auto-timers.js +16 -2
  55. package/dist/resources/extensions/gsd/auto-tool-tracking.js +55 -0
  56. package/dist/resources/extensions/gsd/auto-unit-closeout.js +45 -21
  57. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +33 -37
  58. package/dist/resources/extensions/gsd/auto-verification.js +30 -37
  59. package/dist/resources/extensions/gsd/auto-worktree-repair.js +10 -2
  60. package/dist/resources/extensions/gsd/auto-worktree.js +67 -375
  61. package/dist/resources/extensions/gsd/auto.js +112 -486
  62. package/dist/resources/extensions/gsd/blocked-models.js +28 -0
  63. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +29 -8
  64. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +28 -37
  65. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +43 -49
  66. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -2
  67. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
  68. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +19 -0
  69. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +319 -161
  70. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +365 -58
  71. package/dist/resources/extensions/gsd/branch-patterns.js +2 -0
  72. package/dist/resources/extensions/gsd/browser-daemon-auto-prep.js +83 -0
  73. package/dist/resources/extensions/gsd/browser-evidence.js +8 -2
  74. package/dist/resources/extensions/gsd/captures.js +5 -15
  75. package/dist/resources/extensions/gsd/closeout-consistency-gate.js +21 -4
  76. package/dist/resources/extensions/gsd/closeout-recovery.js +3 -2
  77. package/dist/resources/extensions/gsd/closeout-wizard.js +92 -0
  78. package/dist/resources/extensions/gsd/codebase-generator.js +8 -4
  79. package/dist/resources/extensions/gsd/commands/catalog.js +6 -62
  80. package/dist/resources/extensions/gsd/commands/context.js +16 -2
  81. package/dist/resources/extensions/gsd/commands/handlers/auto.js +3 -0
  82. package/dist/resources/extensions/gsd/commands-handlers.js +66 -3
  83. package/dist/resources/extensions/gsd/commands-inspect.js +4 -8
  84. package/dist/resources/extensions/gsd/commands-maintenance.js +61 -41
  85. package/dist/resources/extensions/gsd/commands-ship.js +2 -2
  86. package/dist/resources/extensions/gsd/commands-verdict.js +12 -2
  87. package/dist/resources/extensions/gsd/consent-question.js +353 -0
  88. package/dist/resources/extensions/gsd/consent-verdict.js +63 -0
  89. package/dist/resources/extensions/gsd/constants.js +0 -2
  90. package/dist/resources/extensions/gsd/crash-recovery.js +12 -15
  91. package/dist/resources/extensions/gsd/db/engine.js +755 -0
  92. package/dist/resources/extensions/gsd/db/queries.js +398 -0
  93. package/dist/resources/extensions/gsd/db/sql-constants.js +11 -0
  94. package/dist/resources/extensions/gsd/db/writers/cascades.js +194 -0
  95. package/dist/resources/extensions/gsd/db/writers/import-restore.js +182 -0
  96. package/dist/resources/extensions/gsd/db/writers/memory.js +149 -0
  97. package/dist/resources/extensions/gsd/db/writers/reconcile.js +458 -0
  98. package/dist/resources/extensions/gsd/db/writers/status.js +70 -0
  99. package/dist/resources/extensions/gsd/db-workspace.js +103 -0
  100. package/dist/resources/extensions/gsd/debug-logger.js +10 -0
  101. package/dist/resources/extensions/gsd/delegation-policy.js +2 -10
  102. package/dist/resources/extensions/gsd/discussion-handoff.js +218 -0
  103. package/dist/resources/extensions/gsd/dispatch-guard.js +10 -35
  104. package/dist/resources/extensions/gsd/docs/preferences-reference.md +9 -0
  105. package/dist/resources/extensions/gsd/doctor-engine-checks.js +5 -5
  106. package/dist/resources/extensions/gsd/doctor-environment.js +5 -11
  107. package/dist/resources/extensions/gsd/doctor-format.js +9 -6
  108. package/dist/resources/extensions/gsd/doctor-git-checks.js +6 -21
  109. package/dist/resources/extensions/gsd/doctor-proactive.js +7 -2
  110. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +21 -16
  111. package/dist/resources/extensions/gsd/doctor.js +16 -9
  112. package/dist/resources/extensions/gsd/engine-hook-contract.js +70 -0
  113. package/dist/resources/extensions/gsd/error-classifier.js +10 -1
  114. package/dist/resources/extensions/gsd/exec-sandbox.js +30 -10
  115. package/dist/resources/extensions/gsd/files.js +33 -19
  116. package/dist/resources/extensions/gsd/git-conflict-state.js +16 -1
  117. package/dist/resources/extensions/gsd/git-service.js +1 -0
  118. package/dist/resources/extensions/gsd/gitignore.js +3 -0
  119. package/dist/resources/extensions/gsd/gsd-command-home.js +22 -12
  120. package/dist/resources/extensions/gsd/gsd-db.js +184 -2048
  121. package/dist/resources/extensions/gsd/guidance.js +158 -0
  122. package/dist/resources/extensions/gsd/guided-flow.js +91 -476
  123. package/dist/resources/extensions/gsd/guided-unit-completion.js +225 -0
  124. package/dist/resources/extensions/gsd/markdown-renderer.js +43 -33
  125. package/dist/resources/extensions/gsd/mcp-filter.js +10 -20
  126. package/dist/resources/extensions/gsd/mcp-tool-name.js +18 -0
  127. package/dist/resources/extensions/gsd/md-importer.js +4 -3
  128. package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +1 -1
  129. package/dist/resources/extensions/gsd/migrate/safety.js +22 -11
  130. package/dist/resources/extensions/gsd/migration-auto-check.js +27 -5
  131. package/dist/resources/extensions/gsd/milestone-closeout-proof.js +72 -0
  132. package/dist/resources/extensions/gsd/milestone-closeout.js +97 -28
  133. package/dist/resources/extensions/gsd/milestone-merge-transaction.js +10 -0
  134. package/dist/resources/extensions/gsd/milestone-planning-persistence.js +156 -0
  135. package/dist/resources/extensions/gsd/milestone-readiness.js +77 -0
  136. package/dist/resources/extensions/gsd/milestone-reopen-events.js +3 -5
  137. package/dist/resources/extensions/gsd/milestone-settlement.js +50 -0
  138. package/dist/resources/extensions/gsd/milestone-validation-evidence.js +73 -0
  139. package/dist/resources/extensions/gsd/milestone-validation-verdict.js +57 -0
  140. package/dist/resources/extensions/gsd/model-cost-table.js +1 -0
  141. package/dist/resources/extensions/gsd/model-router.js +3 -0
  142. package/dist/resources/extensions/gsd/native-git-bridge.js +45 -0
  143. package/dist/resources/extensions/gsd/notification-store.js +11 -4
  144. package/dist/resources/extensions/gsd/parallel-eligibility.js +3 -6
  145. package/dist/resources/extensions/gsd/parallel-merge.js +14 -11
  146. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +11 -7
  147. package/dist/resources/extensions/gsd/parallel-orchestrator.js +3 -2
  148. package/dist/resources/extensions/gsd/parsers-legacy.js +16 -4
  149. package/dist/resources/extensions/gsd/paths.js +37 -24
  150. package/dist/resources/extensions/gsd/pre-execution-checks.js +91 -3
  151. package/dist/resources/extensions/gsd/preferences-diagnostics.js +67 -0
  152. package/dist/resources/extensions/gsd/preferences-models.js +14 -48
  153. package/dist/resources/extensions/gsd/preferences.js +161 -29
  154. package/dist/resources/extensions/gsd/projection-flush.js +7 -0
  155. package/dist/resources/extensions/gsd/prompts/complete-slice.md +4 -3
  156. package/dist/resources/extensions/gsd/prompts/discuss.md +6 -7
  157. package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -1
  158. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +5 -7
  159. package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +6 -6
  160. package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +1 -2
  161. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -6
  162. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
  163. package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -3
  164. package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -1
  165. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  166. package/dist/resources/extensions/gsd/prompts/refine-slice.md +3 -2
  167. package/dist/resources/extensions/gsd/prompts/replan-slice.md +2 -2
  168. package/dist/resources/extensions/gsd/prompts/research-milestone.md +3 -3
  169. package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
  170. package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  171. package/dist/resources/extensions/gsd/prompts/run-uat.md +7 -5
  172. package/dist/resources/extensions/gsd/prompts/system.md +6 -3
  173. package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -1
  174. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +6 -4
  175. package/dist/resources/extensions/gsd/provider-error-guidance.js +1 -5
  176. package/dist/resources/extensions/gsd/provider-payload-policy.js +83 -0
  177. package/dist/resources/extensions/gsd/provider-switch-observer.js +1 -1
  178. package/dist/resources/extensions/gsd/publication.js +87 -0
  179. package/dist/resources/extensions/gsd/pull-request-process.js +13 -0
  180. package/dist/resources/extensions/gsd/quality-gate-closure.js +109 -0
  181. package/dist/resources/extensions/gsd/question-transport.js +86 -0
  182. package/dist/resources/extensions/gsd/reactive-graph.js +8 -1
  183. package/dist/resources/extensions/gsd/recovery-classification.js +41 -87
  184. package/dist/resources/extensions/gsd/roadmap-slices.js +33 -5
  185. package/dist/resources/extensions/gsd/safety/destructive-confirmation.js +108 -0
  186. package/dist/resources/extensions/gsd/safety/evidence-collector.js +37 -4
  187. package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +7 -2
  188. package/dist/resources/extensions/gsd/safety/file-change-validator.js +10 -0
  189. package/dist/resources/extensions/gsd/schemas/parsers.js +6 -1
  190. package/dist/resources/extensions/gsd/session-lock.js +1 -1
  191. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +3 -2
  192. package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +21 -1
  193. package/dist/resources/extensions/gsd/state-transition-matrix.js +38 -0
  194. package/dist/resources/extensions/gsd/state.js +19 -25
  195. package/dist/resources/extensions/gsd/status-guards.js +56 -8
  196. package/dist/resources/extensions/gsd/stop-notice.js +57 -0
  197. package/dist/resources/extensions/gsd/templates/plan.md +7 -0
  198. package/dist/resources/extensions/gsd/templates/project.md +1 -0
  199. package/dist/resources/extensions/gsd/templates/roadmap.md +1 -1
  200. package/dist/resources/extensions/gsd/templates/uat.md +5 -1
  201. package/dist/resources/extensions/gsd/tool-contract.js +66 -11
  202. package/dist/resources/extensions/gsd/tool-presentation-plan.js +17 -36
  203. package/dist/resources/extensions/gsd/tool-surface-readiness.js +56 -0
  204. package/dist/resources/extensions/gsd/tool-surface-snapshot.js +17 -0
  205. package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -2
  206. package/dist/resources/extensions/gsd/tools/complete-slice.js +46 -55
  207. package/dist/resources/extensions/gsd/tools/complete-task.js +3 -2
  208. package/dist/resources/extensions/gsd/tools/exec-tool.js +10 -8
  209. package/dist/resources/extensions/gsd/tools/plan-milestone.js +15 -143
  210. package/dist/resources/extensions/gsd/tools/plan-slice.js +14 -8
  211. package/dist/resources/extensions/gsd/tools/plan-task.js +2 -2
  212. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +41 -2
  213. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +13 -31
  214. package/dist/resources/extensions/gsd/tools/reopen-slice.js +16 -35
  215. package/dist/resources/extensions/gsd/tools/reopen-task.js +2 -2
  216. package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -2
  217. package/dist/resources/extensions/gsd/tools/skip-slice.js +18 -36
  218. package/dist/resources/extensions/gsd/tools/validate-milestone.js +15 -78
  219. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +236 -22
  220. package/dist/resources/extensions/gsd/uat-policy.js +57 -25
  221. package/dist/resources/extensions/gsd/uat-run.js +9 -14
  222. package/dist/resources/extensions/gsd/undo.js +8 -7
  223. package/dist/resources/extensions/gsd/unit-closeout.js +138 -0
  224. package/dist/resources/extensions/gsd/unit-context-composer.js +114 -21
  225. package/dist/resources/extensions/gsd/unit-context-manifest.js +4 -27
  226. package/dist/resources/extensions/gsd/unit-registry.js +337 -0
  227. package/dist/resources/extensions/gsd/unit-runtime.js +3 -2
  228. package/dist/resources/extensions/gsd/unit-tool-contracts.js +9 -181
  229. package/dist/resources/extensions/gsd/validation-block-guard.js +2 -0
  230. package/dist/resources/extensions/gsd/verdict-parser.js +1 -1
  231. package/dist/resources/extensions/gsd/verification-verdict.js +2 -1
  232. package/dist/resources/extensions/gsd/web-app-uat.js +117 -0
  233. package/dist/resources/extensions/gsd/workflow-event-ledger.js +91 -0
  234. package/dist/resources/extensions/gsd/workflow-event-vocabulary.js +46 -0
  235. package/dist/resources/extensions/gsd/workflow-events.js +6 -18
  236. package/dist/resources/extensions/gsd/workflow-mcp.js +15 -102
  237. package/dist/resources/extensions/gsd/workflow-reconcile.js +25 -59
  238. package/dist/resources/extensions/gsd/workflow-tool-surface.js +46 -0
  239. package/dist/resources/extensions/gsd/workspace-git-guard.js +2 -0
  240. package/dist/resources/extensions/gsd/worktree-git-recovery.js +293 -0
  241. package/dist/resources/extensions/gsd/worktree-lifecycle.js +12 -3
  242. package/dist/resources/extensions/gsd/worktree-manager.js +45 -28
  243. package/dist/resources/extensions/gsd/worktree-placement.js +59 -0
  244. package/dist/resources/extensions/gsd/worktree-reentry.js +12 -8
  245. package/dist/resources/extensions/gsd/worktree-root.js +28 -6
  246. package/dist/resources/extensions/gsd/worktree-safety.js +8 -5
  247. package/dist/resources/extensions/gsd/worktree-session-state.js +12 -11
  248. package/dist/resources/extensions/gsd/worktree-state-projection.js +33 -4
  249. package/dist/resources/extensions/gsd/worktree-telemetry.js +12 -0
  250. package/dist/resources/extensions/search-the-web/native-search.js +5 -3
  251. package/dist/resources/extensions/shared/browser-contract.js +59 -0
  252. package/dist/resources/extensions/shared/gsd-browser-cli.js +116 -6
  253. package/dist/resources/extensions/shared/interview-ui.js +2 -2
  254. package/dist/resources/shared/claude-runtime-floor.js +182 -0
  255. package/dist/resources/shared/gsd-browser-path-sync.js +214 -0
  256. package/dist/resources/shared/package-manager-detection.js +1 -1
  257. package/dist/resources/shared/package.json +3 -0
  258. package/dist/resources/skills/create-skill/references/executable-code.md +1 -1
  259. package/dist/resources/skills/create-skill/workflows/add-reference.md +8 -3
  260. package/dist/resources/skills/create-skill/workflows/add-script.md +4 -2
  261. package/dist/resources/skills/create-skill/workflows/add-template.md +3 -1
  262. package/dist/resources/skills/create-skill/workflows/add-workflow.md +8 -3
  263. package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
  264. package/dist/resources/skills/create-skill/workflows/verify-skill.md +9 -4
  265. package/dist/resources/skills/gsd-browser/SKILL.md +1 -1
  266. package/dist/resources/skills/spike-wrap-up/SKILL.md +9 -9
  267. package/dist/tsconfig.extensions.tsbuildinfo +1 -0
  268. package/dist/update-check.d.ts +2 -0
  269. package/dist/update-check.js +24 -1
  270. package/dist/update-cmd.js +40 -3
  271. package/dist/web/standalone/.next/BUILD_ID +1 -1
  272. package/dist/web/standalone/.next/app-path-routes-manifest.json +5 -5
  273. package/dist/web/standalone/.next/build-manifest.json +3 -3
  274. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  275. package/dist/web/standalone/.next/react-loadable-manifest.json +8 -8
  276. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  277. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  278. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  279. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  280. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  281. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  282. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  283. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  284. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  285. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  286. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  287. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  288. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  289. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  290. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  291. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  292. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  293. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  294. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  295. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  296. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  297. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  298. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  299. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  300. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  301. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  302. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  303. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  304. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  305. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  306. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  307. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  308. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  309. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
  310. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  311. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  312. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  313. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  314. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  315. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  316. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  317. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  318. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  319. package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
  320. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  321. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  322. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  323. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  324. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  325. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  326. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  327. package/dist/web/standalone/.next/server/app/api/update/route.js.nft.json +1 -1
  328. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  329. package/dist/web/standalone/.next/server/app/index.html +1 -1
  330. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  331. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  332. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  333. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  334. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  335. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  336. package/dist/web/standalone/.next/server/app-paths-manifest.json +5 -5
  337. package/dist/web/standalone/.next/server/chunks/5124.js +1 -0
  338. package/dist/web/standalone/.next/server/chunks/5942.js +2 -0
  339. package/dist/web/standalone/.next/server/chunks/8357.js +3 -3
  340. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  341. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  342. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  343. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  344. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  345. package/dist/web/standalone/.next/static/chunks/2659.b7b129ee6a769448.js +1 -0
  346. package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +1 -0
  347. package/dist/web/standalone/.next/static/chunks/{3616.4113d484a994e411.js → 3616.3c60753b8ffcbd2e.js} +1 -1
  348. package/dist/web/standalone/.next/static/chunks/4283.e4873b058df143a1.js +2 -0
  349. package/dist/web/standalone/.next/static/chunks/5826.a46ecdd1cfe8dabc.js +1 -0
  350. package/dist/web/standalone/.next/static/chunks/796.e0bdc932325d7e03.js +10 -0
  351. package/dist/web/standalone/.next/static/chunks/8785.2e5a118797fb2dd2.js +1 -0
  352. package/dist/web/standalone/.next/static/chunks/{webpack-dda80a1ef5587410.js → webpack-f0285ce91d4ec9ef.js} +1 -1
  353. package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
  354. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  355. package/dist/web/standalone/node_modules/postcss/lib/container.js +26 -18
  356. package/dist/web/standalone/node_modules/postcss/lib/css-syntax-error.js +47 -14
  357. package/dist/web/standalone/node_modules/postcss/lib/declaration.js +4 -4
  358. package/dist/web/standalone/node_modules/postcss/lib/fromJSON.js +3 -3
  359. package/dist/web/standalone/node_modules/postcss/lib/input.js +54 -29
  360. package/dist/web/standalone/node_modules/postcss/lib/lazy-result.js +47 -37
  361. package/dist/web/standalone/node_modules/postcss/lib/map-generator.js +26 -9
  362. package/dist/web/standalone/node_modules/postcss/lib/no-work-result.js +57 -55
  363. package/dist/web/standalone/node_modules/postcss/lib/node.js +99 -31
  364. package/dist/web/standalone/node_modules/postcss/lib/parse.js +1 -1
  365. package/dist/web/standalone/node_modules/postcss/lib/parser.js +10 -9
  366. package/dist/web/standalone/node_modules/postcss/lib/postcss.js +12 -12
  367. package/dist/web/standalone/node_modules/postcss/lib/previous-map.js +30 -11
  368. package/dist/web/standalone/node_modules/postcss/lib/processor.js +7 -7
  369. package/dist/web/standalone/node_modules/postcss/lib/result.js +5 -5
  370. package/dist/web/standalone/node_modules/postcss/lib/rule.js +6 -6
  371. package/dist/web/standalone/node_modules/postcss/lib/stringifier.js +69 -28
  372. package/dist/web/standalone/node_modules/postcss/lib/tokenize.js +6 -2
  373. package/dist/web/standalone/node_modules/postcss/package.json +48 -48
  374. package/dist/web/standalone/package.json +1 -1
  375. package/dist/web-mode.d.ts +2 -0
  376. package/dist/web-mode.js +20 -8
  377. package/dist/worktree-cli.js +3 -6
  378. package/dist/worktree-status-banner.js +7 -11
  379. package/package.json +17 -11
  380. package/packages/cloud-mcp-gateway/package.json +2 -2
  381. package/packages/contracts/dist/rpc.d.ts +1 -0
  382. package/packages/contracts/dist/rpc.d.ts.map +1 -1
  383. package/packages/contracts/dist/rpc.js.map +1 -1
  384. package/packages/contracts/dist/workflow.d.ts +4 -0
  385. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  386. package/packages/contracts/dist/workflow.js.map +1 -1
  387. package/packages/contracts/package.json +1 -1
  388. package/packages/daemon/package.json +4 -4
  389. package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts +2 -0
  390. package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts.map +1 -1
  391. package/packages/gsd-agent-core/dist/session/agent-session-extensions.js +14 -0
  392. package/packages/gsd-agent-core/dist/session/agent-session-extensions.js.map +1 -1
  393. package/packages/gsd-agent-core/package.json +5 -5
  394. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +5 -0
  395. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  396. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +8 -0
  397. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  398. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +1 -1
  399. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
  400. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  401. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +113 -40
  402. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  403. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  404. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +8 -1
  405. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  406. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.d.ts.map +1 -1
  407. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js +11 -1
  408. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js.map +1 -1
  409. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.d.ts.map +1 -1
  410. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.js +6 -0
  411. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.js.map +1 -1
  412. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
  413. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +4 -4
  414. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
  415. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  416. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +3 -1
  417. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
  418. package/packages/gsd-agent-modes/package.json +7 -7
  419. package/packages/mcp-server/dist/cli.js +9 -1
  420. package/packages/mcp-server/dist/cli.js.map +1 -1
  421. package/packages/mcp-server/dist/moonshot-tool-schema.d.ts +29 -0
  422. package/packages/mcp-server/dist/moonshot-tool-schema.d.ts.map +1 -0
  423. package/packages/mcp-server/dist/moonshot-tool-schema.js +50 -0
  424. package/packages/mcp-server/dist/moonshot-tool-schema.js.map +1 -0
  425. package/packages/mcp-server/dist/server.d.ts +10 -0
  426. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  427. package/packages/mcp-server/dist/server.js +12 -0
  428. package/packages/mcp-server/dist/server.js.map +1 -1
  429. package/packages/mcp-server/dist/workflow-tools.d.ts +49 -0
  430. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  431. package/packages/mcp-server/dist/workflow-tools.js +147 -60
  432. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  433. package/packages/mcp-server/package.json +5 -4
  434. package/packages/native/package.json +1 -1
  435. package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts +1 -0
  436. package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts.map +1 -1
  437. package/packages/pi-agent-core/dist/harness/env/nodejs.js +34 -3
  438. package/packages/pi-agent-core/dist/harness/env/nodejs.js.map +1 -1
  439. package/packages/pi-agent-core/dist/index.d.ts +1 -0
  440. package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
  441. package/packages/pi-agent-core/dist/index.js +3 -0
  442. package/packages/pi-agent-core/dist/index.js.map +1 -1
  443. package/packages/pi-agent-core/package.json +1 -1
  444. package/packages/pi-ai/README.md +1 -0
  445. package/packages/pi-ai/dist/index.d.ts +2 -0
  446. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  447. package/packages/pi-ai/dist/index.js +2 -0
  448. package/packages/pi-ai/dist/index.js.map +1 -1
  449. package/packages/pi-ai/dist/models.generated.d.ts +183 -110
  450. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  451. package/packages/pi-ai/dist/models.generated.js +205 -158
  452. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  453. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  454. package/packages/pi-ai/dist/providers/anthropic.js +12 -7
  455. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  456. package/packages/pi-ai/dist/providers/google-shared.d.ts +5 -0
  457. package/packages/pi-ai/dist/providers/google-shared.d.ts.map +1 -1
  458. package/packages/pi-ai/dist/providers/google-shared.js +12 -3
  459. package/packages/pi-ai/dist/providers/google-shared.js.map +1 -1
  460. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  461. package/packages/pi-ai/dist/providers/openai-completions.js +7 -3
  462. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  463. package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts +9 -0
  464. package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts.map +1 -0
  465. package/packages/pi-ai/dist/utils/moonshot-tool-schema.js +34 -0
  466. package/packages/pi-ai/dist/utils/moonshot-tool-schema.js.map +1 -0
  467. package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
  468. package/packages/pi-ai/dist/utils/oauth/github-copilot.js +6 -2
  469. package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
  470. package/packages/pi-ai/package.json +3 -2
  471. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +2 -2
  472. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  473. package/packages/pi-coding-agent/dist/core/auth-storage.js +29 -15
  474. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  475. package/packages/pi-coding-agent/dist/core/capability-patches.d.ts.map +1 -1
  476. package/packages/pi-coding-agent/dist/core/capability-patches.js +3 -1
  477. package/packages/pi-coding-agent/dist/core/capability-patches.js.map +1 -1
  478. package/packages/pi-coding-agent/dist/core/provider-readiness.d.ts.map +1 -1
  479. package/packages/pi-coding-agent/dist/core/provider-readiness.js +13 -6
  480. package/packages/pi-coding-agent/dist/core/provider-readiness.js.map +1 -1
  481. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts +11 -0
  482. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
  483. package/packages/pi-coding-agent/dist/core/tools/bash.js +53 -11
  484. package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
  485. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  486. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  487. package/packages/pi-coding-agent/dist/index.js +1 -1
  488. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  489. package/packages/pi-coding-agent/dist/utils/shell.d.ts +28 -2
  490. package/packages/pi-coding-agent/dist/utils/shell.d.ts.map +1 -1
  491. package/packages/pi-coding-agent/dist/utils/shell.js +56 -10
  492. package/packages/pi-coding-agent/dist/utils/shell.js.map +1 -1
  493. package/packages/pi-coding-agent/package.json +7 -7
  494. package/packages/pi-tui/dist/components/input.js +1 -1
  495. package/packages/pi-tui/dist/components/input.js.map +1 -1
  496. package/packages/pi-tui/dist/keys.d.ts.map +1 -1
  497. package/packages/pi-tui/dist/keys.js +39 -30
  498. package/packages/pi-tui/dist/keys.js.map +1 -1
  499. package/packages/pi-tui/dist/stdin-buffer.d.ts.map +1 -1
  500. package/packages/pi-tui/dist/stdin-buffer.js +22 -0
  501. package/packages/pi-tui/dist/stdin-buffer.js.map +1 -1
  502. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  503. package/packages/pi-tui/dist/tui.js +9 -0
  504. package/packages/pi-tui/dist/tui.js.map +1 -1
  505. package/packages/pi-tui/package.json +2 -2
  506. package/packages/rpc-client/package.json +2 -2
  507. package/pkg/package.json +1 -1
  508. package/scripts/install/deps.js +10 -0
  509. package/scripts/link-workspace-packages.cjs +7 -40
  510. package/src/resources/GSD-WORKFLOW.md +5 -4
  511. package/src/resources/extensions/ask-user-questions.ts +87 -24
  512. package/src/resources/extensions/async-jobs/async-bash-cancel.test.ts +360 -0
  513. package/src/resources/extensions/async-jobs/async-bash-tool.ts +33 -56
  514. package/src/resources/extensions/async-jobs/await-tool.test.ts +139 -0
  515. package/src/resources/extensions/async-jobs/await-tool.ts +82 -12
  516. package/src/resources/extensions/async-jobs/index.ts +79 -0
  517. package/src/resources/extensions/async-jobs/job-manager.ts +21 -1
  518. package/src/resources/extensions/bg-shell/bg-shell-command.ts +6 -6
  519. package/src/resources/extensions/bg-shell/bg-shell-tool.ts +10 -6
  520. package/src/resources/extensions/bg-shell/overlay.ts +9 -5
  521. package/src/resources/extensions/bg-shell/process-manager.ts +50 -25
  522. package/src/resources/extensions/bg-shell/readiness-detector.ts +12 -0
  523. package/src/resources/extensions/bg-shell/tests/lifecycle-and-utilities.test.ts +48 -1
  524. package/src/resources/extensions/bg-shell/utilities.ts +5 -2
  525. package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +265 -98
  526. package/src/resources/extensions/browser-tools/engine/selection.ts +90 -4
  527. package/src/resources/extensions/browser-tools/index.ts +71 -13
  528. package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +83 -13
  529. package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +40 -1
  530. package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +136 -0
  531. package/src/resources/extensions/claude-code-cli/models.ts +9 -0
  532. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +166 -293
  533. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +270 -2
  534. package/src/resources/extensions/claude-code-cli/turn-assembler.ts +287 -0
  535. package/src/resources/extensions/github-sync/templates.ts +3 -3
  536. package/src/resources/extensions/github-sync/tests/templates.test.ts +2 -2
  537. package/src/resources/extensions/gsd/artifact-projection.ts +31 -0
  538. package/src/resources/extensions/gsd/auto/contracts.ts +40 -121
  539. package/src/resources/extensions/gsd/auto/custom-verify-retry-store.ts +21 -3
  540. package/src/resources/extensions/gsd/auto/detect-stuck.ts +32 -9
  541. package/src/resources/extensions/gsd/auto/dispatch-history.ts +152 -0
  542. package/src/resources/extensions/gsd/auto/dispatch-key.ts +39 -0
  543. package/src/resources/extensions/gsd/auto/loop-deps.ts +3 -1
  544. package/src/resources/extensions/gsd/auto/loop.ts +86 -61
  545. package/src/resources/extensions/gsd/auto/orchestrator.ts +1023 -98
  546. package/src/resources/extensions/gsd/auto/phases.ts +108 -28
  547. package/src/resources/extensions/gsd/auto/run-unit.ts +2 -1
  548. package/src/resources/extensions/gsd/auto/session.ts +7 -0
  549. package/src/resources/extensions/gsd/auto-dashboard.ts +18 -4
  550. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +18 -48
  551. package/src/resources/extensions/gsd/auto-dispatch.ts +68 -68
  552. package/src/resources/extensions/gsd/auto-model-selection.ts +49 -12
  553. package/src/resources/extensions/gsd/auto-post-unit.ts +56 -16
  554. package/src/resources/extensions/gsd/auto-prompts.ts +338 -44
  555. package/src/resources/extensions/gsd/auto-recovery.ts +50 -50
  556. package/src/resources/extensions/gsd/auto-runtime-state.ts +30 -0
  557. package/src/resources/extensions/gsd/auto-start.ts +41 -49
  558. package/src/resources/extensions/gsd/auto-timers.ts +16 -2
  559. package/src/resources/extensions/gsd/auto-tool-tracking.ts +59 -0
  560. package/src/resources/extensions/gsd/auto-unit-closeout.ts +83 -28
  561. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +43 -38
  562. package/src/resources/extensions/gsd/auto-verification.ts +33 -36
  563. package/src/resources/extensions/gsd/auto-worktree-repair.ts +13 -2
  564. package/src/resources/extensions/gsd/auto-worktree.ts +83 -391
  565. package/src/resources/extensions/gsd/auto.ts +151 -524
  566. package/src/resources/extensions/gsd/blocked-models.ts +49 -0
  567. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +37 -10
  568. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +29 -37
  569. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +43 -49
  570. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -2
  571. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
  572. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +24 -0
  573. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +379 -177
  574. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +452 -58
  575. package/src/resources/extensions/gsd/branch-patterns.ts +3 -0
  576. package/src/resources/extensions/gsd/browser-daemon-auto-prep.ts +108 -0
  577. package/src/resources/extensions/gsd/browser-evidence.ts +18 -2
  578. package/src/resources/extensions/gsd/captures.ts +5 -16
  579. package/src/resources/extensions/gsd/closeout-consistency-gate.ts +27 -5
  580. package/src/resources/extensions/gsd/closeout-recovery.ts +2 -1
  581. package/src/resources/extensions/gsd/closeout-wizard.ts +102 -0
  582. package/src/resources/extensions/gsd/codebase-generator.ts +9 -5
  583. package/src/resources/extensions/gsd/commands/catalog.ts +6 -68
  584. package/src/resources/extensions/gsd/commands/context.ts +16 -2
  585. package/src/resources/extensions/gsd/commands/handlers/auto.ts +3 -0
  586. package/src/resources/extensions/gsd/commands-handlers.ts +64 -3
  587. package/src/resources/extensions/gsd/commands-inspect.ts +7 -8
  588. package/src/resources/extensions/gsd/commands-maintenance.ts +74 -40
  589. package/src/resources/extensions/gsd/commands-ship.ts +2 -2
  590. package/src/resources/extensions/gsd/commands-verdict.ts +19 -2
  591. package/src/resources/extensions/gsd/consent-question.ts +431 -0
  592. package/src/resources/extensions/gsd/consent-verdict.ts +86 -0
  593. package/src/resources/extensions/gsd/constants.ts +0 -3
  594. package/src/resources/extensions/gsd/crash-recovery.ts +13 -11
  595. package/src/resources/extensions/gsd/db/engine.ts +809 -0
  596. package/src/resources/extensions/gsd/db/queries.ts +490 -0
  597. package/src/resources/extensions/gsd/db/sql-constants.ts +12 -0
  598. package/src/resources/extensions/gsd/db/writers/cascades.ts +237 -0
  599. package/src/resources/extensions/gsd/db/writers/import-restore.ts +310 -0
  600. package/src/resources/extensions/gsd/db/writers/memory.ts +220 -0
  601. package/src/resources/extensions/gsd/db/writers/reconcile.ts +500 -0
  602. package/src/resources/extensions/gsd/db/writers/status.ts +88 -0
  603. package/src/resources/extensions/gsd/db-workspace.ts +170 -0
  604. package/src/resources/extensions/gsd/debug-logger.ts +11 -0
  605. package/src/resources/extensions/gsd/delegation-policy.ts +3 -11
  606. package/src/resources/extensions/gsd/discussion-handoff.ts +276 -0
  607. package/src/resources/extensions/gsd/dispatch-guard.ts +8 -31
  608. package/src/resources/extensions/gsd/docs/preferences-reference.md +9 -0
  609. package/src/resources/extensions/gsd/doctor-engine-checks.ts +5 -4
  610. package/src/resources/extensions/gsd/doctor-environment.ts +5 -13
  611. package/src/resources/extensions/gsd/doctor-format.ts +12 -7
  612. package/src/resources/extensions/gsd/doctor-git-checks.ts +5 -22
  613. package/src/resources/extensions/gsd/doctor-proactive.ts +8 -2
  614. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +22 -17
  615. package/src/resources/extensions/gsd/doctor.ts +15 -5
  616. package/src/resources/extensions/gsd/engine-hook-contract.ts +79 -0
  617. package/src/resources/extensions/gsd/error-classifier.ts +12 -1
  618. package/src/resources/extensions/gsd/exec-sandbox.ts +49 -9
  619. package/src/resources/extensions/gsd/files.ts +33 -12
  620. package/src/resources/extensions/gsd/git-conflict-state.ts +17 -1
  621. package/src/resources/extensions/gsd/git-service.ts +1 -0
  622. package/src/resources/extensions/gsd/gitignore.ts +3 -0
  623. package/src/resources/extensions/gsd/gsd-command-home.ts +13 -3
  624. package/src/resources/extensions/gsd/gsd-db.ts +188 -2375
  625. package/src/resources/extensions/gsd/guidance.ts +217 -0
  626. package/src/resources/extensions/gsd/guided-flow.ts +118 -589
  627. package/src/resources/extensions/gsd/guided-unit-completion.ts +275 -0
  628. package/src/resources/extensions/gsd/markdown-renderer.ts +51 -20
  629. package/src/resources/extensions/gsd/mcp-filter.ts +11 -24
  630. package/src/resources/extensions/gsd/mcp-tool-name.ts +30 -0
  631. package/src/resources/extensions/gsd/md-importer.ts +3 -3
  632. package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +1 -1
  633. package/src/resources/extensions/gsd/migrate/safety.ts +20 -9
  634. package/src/resources/extensions/gsd/migration-auto-check.ts +30 -5
  635. package/src/resources/extensions/gsd/milestone-closeout-proof.ts +131 -0
  636. package/src/resources/extensions/gsd/milestone-closeout.ts +121 -28
  637. package/src/resources/extensions/gsd/milestone-merge-transaction.ts +47 -0
  638. package/src/resources/extensions/gsd/milestone-planning-persistence.ts +224 -0
  639. package/src/resources/extensions/gsd/milestone-readiness.ts +125 -0
  640. package/src/resources/extensions/gsd/milestone-reopen-events.ts +3 -6
  641. package/src/resources/extensions/gsd/milestone-settlement.ts +81 -0
  642. package/src/resources/extensions/gsd/milestone-validation-evidence.ts +95 -0
  643. package/src/resources/extensions/gsd/milestone-validation-verdict.ts +80 -0
  644. package/src/resources/extensions/gsd/model-cost-table.ts +1 -0
  645. package/src/resources/extensions/gsd/model-router.ts +3 -0
  646. package/src/resources/extensions/gsd/native-git-bridge.ts +48 -0
  647. package/src/resources/extensions/gsd/notification-store.ts +26 -3
  648. package/src/resources/extensions/gsd/parallel-eligibility.ts +4 -5
  649. package/src/resources/extensions/gsd/parallel-merge.ts +12 -9
  650. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +10 -7
  651. package/src/resources/extensions/gsd/parallel-orchestrator.ts +6 -2
  652. package/src/resources/extensions/gsd/parsers-legacy.ts +16 -4
  653. package/src/resources/extensions/gsd/paths.ts +42 -22
  654. package/src/resources/extensions/gsd/pre-execution-checks.ts +109 -3
  655. package/src/resources/extensions/gsd/preferences-diagnostics.ts +98 -0
  656. package/src/resources/extensions/gsd/preferences-models.ts +12 -47
  657. package/src/resources/extensions/gsd/preferences-types.ts +16 -0
  658. package/src/resources/extensions/gsd/preferences.ts +191 -28
  659. package/src/resources/extensions/gsd/projection-flush.ts +20 -0
  660. package/src/resources/extensions/gsd/prompts/complete-slice.md +4 -3
  661. package/src/resources/extensions/gsd/prompts/discuss.md +6 -7
  662. package/src/resources/extensions/gsd/prompts/execute-task.md +3 -1
  663. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +5 -7
  664. package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +6 -6
  665. package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +1 -2
  666. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -6
  667. package/src/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
  668. package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -3
  669. package/src/resources/extensions/gsd/prompts/quick-task.md +1 -1
  670. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  671. package/src/resources/extensions/gsd/prompts/refine-slice.md +3 -2
  672. package/src/resources/extensions/gsd/prompts/replan-slice.md +2 -2
  673. package/src/resources/extensions/gsd/prompts/research-milestone.md +3 -3
  674. package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
  675. package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  676. package/src/resources/extensions/gsd/prompts/run-uat.md +7 -5
  677. package/src/resources/extensions/gsd/prompts/system.md +6 -3
  678. package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -1
  679. package/src/resources/extensions/gsd/prompts/validate-milestone.md +6 -4
  680. package/src/resources/extensions/gsd/provider-error-guidance.ts +4 -9
  681. package/src/resources/extensions/gsd/provider-payload-policy.ts +140 -0
  682. package/src/resources/extensions/gsd/provider-switch-observer.ts +1 -1
  683. package/src/resources/extensions/gsd/publication.ts +122 -0
  684. package/src/resources/extensions/gsd/pull-request-process.ts +41 -0
  685. package/src/resources/extensions/gsd/quality-gate-closure.ts +140 -0
  686. package/src/resources/extensions/gsd/question-transport.ts +138 -0
  687. package/src/resources/extensions/gsd/reactive-graph.ts +11 -1
  688. package/src/resources/extensions/gsd/recovery-classification.ts +47 -88
  689. package/src/resources/extensions/gsd/roadmap-slices.ts +36 -5
  690. package/src/resources/extensions/gsd/safety/destructive-confirmation.ts +134 -0
  691. package/src/resources/extensions/gsd/safety/evidence-collector.ts +36 -4
  692. package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +7 -2
  693. package/src/resources/extensions/gsd/safety/file-change-validator.ts +14 -0
  694. package/src/resources/extensions/gsd/schemas/parsers.ts +6 -1
  695. package/src/resources/extensions/gsd/session-lock.ts +1 -1
  696. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +6 -2
  697. package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +31 -10
  698. package/src/resources/extensions/gsd/state-transition-matrix.ts +42 -0
  699. package/src/resources/extensions/gsd/state.ts +24 -26
  700. package/src/resources/extensions/gsd/status-guards.ts +59 -8
  701. package/src/resources/extensions/gsd/stop-notice.ts +75 -0
  702. package/src/resources/extensions/gsd/templates/plan.md +7 -0
  703. package/src/resources/extensions/gsd/templates/project.md +1 -0
  704. package/src/resources/extensions/gsd/templates/roadmap.md +1 -1
  705. package/src/resources/extensions/gsd/templates/uat.md +5 -1
  706. package/src/resources/extensions/gsd/tests/artifact-db-drift-memo.test.ts +66 -0
  707. package/src/resources/extensions/gsd/tests/ask-user-questions-render.test.ts +92 -0
  708. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +29 -1
  709. package/src/resources/extensions/gsd/tests/auto-dispatch-baseline-harness.test.ts +53 -0
  710. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +444 -5
  711. package/src/resources/extensions/gsd/tests/auto-milestone-target.test.ts +23 -0
  712. package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +18 -0
  713. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +91 -0
  714. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +894 -858
  715. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +41 -11
  716. package/src/resources/extensions/gsd/tests/auto-post-unit-evidence-crossref-4909.test.ts +46 -0
  717. package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +65 -3
  718. package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +34 -0
  719. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +2 -2
  720. package/src/resources/extensions/gsd/tests/auto-worktree-repair.test.ts +4 -2
  721. package/src/resources/extensions/gsd/tests/blocked-models.test.ts +19 -0
  722. package/src/resources/extensions/gsd/tests/browser-automation-contract-fixture.ts +39 -0
  723. package/src/resources/extensions/gsd/tests/browser-contract.test.ts +44 -0
  724. package/src/resources/extensions/gsd/tests/browser-daemon-auto-prep.test.ts +144 -0
  725. package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +20 -0
  726. package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +66 -1
  727. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +44 -0
  728. package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +22 -0
  729. package/src/resources/extensions/gsd/tests/commands-dispatcher-workspace-git.test.ts +11 -0
  730. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +46 -8
  731. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
  732. package/src/resources/extensions/gsd/tests/consent-question.test.ts +351 -0
  733. package/src/resources/extensions/gsd/tests/custom-verify-retry-store.test.ts +67 -0
  734. package/src/resources/extensions/gsd/tests/debug-logger.test.ts +15 -0
  735. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +10 -10
  736. package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +303 -0
  737. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +34 -3
  738. package/src/resources/extensions/gsd/tests/dispatch-history.test.ts +273 -0
  739. package/src/resources/extensions/gsd/tests/dispatch-run-uat-browser-tools.test.ts +89 -0
  740. package/src/resources/extensions/gsd/tests/doctor-git-checks-terminal.test.ts +73 -0
  741. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +18 -0
  742. package/src/resources/extensions/gsd/tests/dynamic-bash-no-cap.test.ts +132 -0
  743. package/src/resources/extensions/gsd/tests/engine-hook-contract.test.ts +148 -0
  744. package/src/resources/extensions/gsd/tests/evidence-xref-gsd-exec.test.ts +157 -0
  745. package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +193 -0
  746. package/src/resources/extensions/gsd/tests/exec-tool.test.ts +29 -1
  747. package/src/resources/extensions/gsd/tests/execute-summary-save-empty-project.test.ts +64 -1
  748. package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +1 -0
  749. package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +35 -1
  750. package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +33 -1
  751. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-no-blockers.md +1 -5
  752. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-with-blockers.md +1 -5
  753. package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +48 -1
  754. package/src/resources/extensions/gsd/tests/gsd-command-home.test.ts +120 -0
  755. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +27 -0
  756. package/src/resources/extensions/gsd/tests/guidance.test.ts +148 -0
  757. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +2 -6
  758. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +58 -15
  759. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +74 -59
  760. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +3 -2
  761. package/src/resources/extensions/gsd/tests/integration/gsd-integration-fixture.ts +80 -0
  762. package/src/resources/extensions/gsd/tests/integration/merge-strategy-regular.test.ts +157 -0
  763. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +199 -0
  764. package/src/resources/extensions/gsd/tests/markdown-renderer-parse-cache.test.ts +75 -0
  765. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +3 -1
  766. package/src/resources/extensions/gsd/tests/mcp-tool-name.test.ts +34 -0
  767. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +143 -1
  768. package/src/resources/extensions/gsd/tests/milestone-closeout-proof.test.ts +99 -0
  769. package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +120 -4
  770. package/src/resources/extensions/gsd/tests/milestone-merge-transaction.test.ts +46 -0
  771. package/src/resources/extensions/gsd/tests/milestone-readiness.test.ts +65 -0
  772. package/src/resources/extensions/gsd/tests/milestone-validation-evidence.test.ts +41 -0
  773. package/src/resources/extensions/gsd/tests/milestone-validation-verdict.test.ts +55 -0
  774. package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +32 -1
  775. package/src/resources/extensions/gsd/tests/native-merge-regular.test.ts +139 -0
  776. package/src/resources/extensions/gsd/tests/notification-store.test.ts +32 -0
  777. package/src/resources/extensions/gsd/tests/oauth-api-model-routing.test.ts +167 -0
  778. package/src/resources/extensions/gsd/tests/orchestrator-legacy-parity.test.ts +127 -0
  779. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +18 -0
  780. package/src/resources/extensions/gsd/tests/parse-project-milestone-bridge.test.ts +77 -0
  781. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +138 -0
  782. package/src/resources/extensions/gsd/tests/phases-terminal-complete-idempotent.test.ts +242 -0
  783. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +45 -0
  784. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +6 -2
  785. package/src/resources/extensions/gsd/tests/planning-crossval.test.ts +45 -0
  786. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +63 -2
  787. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +193 -1
  788. package/src/resources/extensions/gsd/tests/preferences-diagnostics.test.ts +67 -0
  789. package/src/resources/extensions/gsd/tests/preferences.test.ts +183 -0
  790. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +75 -2
  791. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +124 -6
  792. package/src/resources/extensions/gsd/tests/provider-error-guidance.test.ts +3 -3
  793. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +9 -0
  794. package/src/resources/extensions/gsd/tests/provider-payload-policy.test.ts +165 -0
  795. package/src/resources/extensions/gsd/tests/publication.test.ts +120 -0
  796. package/src/resources/extensions/gsd/tests/pull-request-process.test.ts +47 -0
  797. package/src/resources/extensions/gsd/tests/recovery-classification-illegal-transition.test.ts +30 -0
  798. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +342 -1
  799. package/src/resources/extensions/gsd/tests/research-milestone-composer.test.ts +65 -0
  800. package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +40 -0
  801. package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +68 -0
  802. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +44 -1
  803. package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +38 -0
  804. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +80 -0
  805. package/src/resources/extensions/gsd/tests/session-switch-clears-pending-autostart.test.ts +108 -0
  806. package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +144 -7
  807. package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +27 -0
  808. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +21 -6
  809. package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +36 -0
  810. package/src/resources/extensions/gsd/tests/status-guards.test.ts +38 -0
  811. package/src/resources/extensions/gsd/tests/stop-notice.test.ts +70 -0
  812. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +114 -0
  813. package/src/resources/extensions/gsd/tests/tool-availability-audit.test.ts +35 -0
  814. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +8 -0
  815. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +35 -42
  816. package/src/resources/extensions/gsd/tests/tool-surface-readiness.test.ts +155 -0
  817. package/src/resources/extensions/gsd/tests/tool-unavailable-retry.test.ts +33 -0
  818. package/src/resources/extensions/gsd/tests/transport-gate-double-complete.test.ts +139 -0
  819. package/src/resources/extensions/gsd/tests/uat-policy.test.ts +112 -6
  820. package/src/resources/extensions/gsd/tests/unit-closeout.test.ts +209 -0
  821. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +114 -2
  822. package/src/resources/extensions/gsd/tests/unit-registry.test.ts +163 -0
  823. package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +8 -0
  824. package/src/resources/extensions/gsd/tests/validate-milestone-stuck-guard.test.ts +39 -0
  825. package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +2 -0
  826. package/src/resources/extensions/gsd/tests/web-app-uat.test.ts +193 -0
  827. package/src/resources/extensions/gsd/tests/workflow-events.test.ts +19 -0
  828. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +128 -11
  829. package/src/resources/extensions/gsd/tests/workflow-reconcile.test.ts +20 -0
  830. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +275 -40
  831. package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +15 -0
  832. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +41 -4
  833. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +43 -1
  834. package/src/resources/extensions/gsd/tests/worktree-placement.test.ts +113 -0
  835. package/src/resources/extensions/gsd/tests/worktree-projection-writers.test.ts +1 -1
  836. package/src/resources/extensions/gsd/tests/worktree-reentry.test.ts +1 -1
  837. package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +27 -1
  838. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +12 -6
  839. package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +2 -2
  840. package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +22 -0
  841. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +15 -3
  842. package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +358 -0
  843. package/src/resources/extensions/gsd/tests/write-gate.test.ts +188 -1
  844. package/src/resources/extensions/gsd/tool-contract.ts +124 -11
  845. package/src/resources/extensions/gsd/tool-presentation-plan.ts +18 -35
  846. package/src/resources/extensions/gsd/tool-surface-readiness.ts +76 -0
  847. package/src/resources/extensions/gsd/tool-surface-snapshot.ts +47 -0
  848. package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
  849. package/src/resources/extensions/gsd/tools/complete-slice.ts +45 -70
  850. package/src/resources/extensions/gsd/tools/complete-task.ts +3 -2
  851. package/src/resources/extensions/gsd/tools/exec-tool.ts +9 -8
  852. package/src/resources/extensions/gsd/tools/plan-milestone.ts +19 -160
  853. package/src/resources/extensions/gsd/tools/plan-slice.ts +14 -8
  854. package/src/resources/extensions/gsd/tools/plan-task.ts +2 -2
  855. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +45 -2
  856. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +13 -40
  857. package/src/resources/extensions/gsd/tools/reopen-slice.ts +16 -44
  858. package/src/resources/extensions/gsd/tools/reopen-task.ts +2 -2
  859. package/src/resources/extensions/gsd/tools/replan-slice.ts +2 -2
  860. package/src/resources/extensions/gsd/tools/skip-slice.ts +18 -44
  861. package/src/resources/extensions/gsd/tools/validate-milestone.ts +25 -84
  862. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +264 -23
  863. package/src/resources/extensions/gsd/uat-policy.ts +80 -25
  864. package/src/resources/extensions/gsd/uat-run.ts +10 -14
  865. package/src/resources/extensions/gsd/undo.ts +9 -8
  866. package/src/resources/extensions/gsd/unit-closeout.ts +201 -0
  867. package/src/resources/extensions/gsd/unit-context-composer.ts +196 -21
  868. package/src/resources/extensions/gsd/unit-context-manifest.ts +4 -28
  869. package/src/resources/extensions/gsd/unit-registry.ts +412 -0
  870. package/src/resources/extensions/gsd/unit-runtime.ts +3 -2
  871. package/src/resources/extensions/gsd/unit-tool-contracts.ts +27 -191
  872. package/src/resources/extensions/gsd/validation-block-guard.ts +2 -0
  873. package/src/resources/extensions/gsd/verdict-parser.ts +1 -1
  874. package/src/resources/extensions/gsd/verification-verdict.ts +4 -2
  875. package/src/resources/extensions/gsd/web-app-uat.ts +144 -0
  876. package/src/resources/extensions/gsd/workflow-event-ledger.ts +131 -0
  877. package/src/resources/extensions/gsd/workflow-event-vocabulary.ts +59 -0
  878. package/src/resources/extensions/gsd/workflow-events.ts +12 -20
  879. package/src/resources/extensions/gsd/workflow-mcp.ts +22 -110
  880. package/src/resources/extensions/gsd/workflow-reconcile.ts +32 -65
  881. package/src/resources/extensions/gsd/workflow-tool-surface.ts +76 -0
  882. package/src/resources/extensions/gsd/workspace-git-guard.ts +1 -0
  883. package/src/resources/extensions/gsd/worktree-git-recovery.ts +314 -0
  884. package/src/resources/extensions/gsd/worktree-lifecycle.ts +20 -25
  885. package/src/resources/extensions/gsd/worktree-manager.ts +47 -28
  886. package/src/resources/extensions/gsd/worktree-placement.ts +63 -0
  887. package/src/resources/extensions/gsd/worktree-reentry.ts +10 -7
  888. package/src/resources/extensions/gsd/worktree-root.ts +29 -6
  889. package/src/resources/extensions/gsd/worktree-safety.ts +8 -5
  890. package/src/resources/extensions/gsd/worktree-session-state.ts +11 -11
  891. package/src/resources/extensions/gsd/worktree-state-projection.ts +55 -7
  892. package/src/resources/extensions/gsd/worktree-telemetry.ts +16 -0
  893. package/src/resources/extensions/search-the-web/native-search.ts +5 -3
  894. package/src/resources/extensions/shared/browser-contract.ts +66 -0
  895. package/src/resources/extensions/shared/gsd-browser-cli.ts +141 -6
  896. package/src/resources/extensions/shared/interview-ui.ts +15 -2
  897. package/src/resources/shared/claude-runtime-floor.ts +248 -0
  898. package/src/resources/shared/gsd-browser-path-sync.ts +273 -0
  899. package/src/resources/shared/package-manager-detection.ts +1 -1
  900. package/src/resources/shared/package.json +3 -0
  901. package/src/resources/skills/create-skill/references/executable-code.md +1 -1
  902. package/src/resources/skills/create-skill/workflows/add-reference.md +8 -3
  903. package/src/resources/skills/create-skill/workflows/add-script.md +4 -2
  904. package/src/resources/skills/create-skill/workflows/add-template.md +3 -1
  905. package/src/resources/skills/create-skill/workflows/add-workflow.md +8 -3
  906. package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
  907. package/src/resources/skills/create-skill/workflows/verify-skill.md +9 -4
  908. package/src/resources/skills/gsd-browser/SKILL.md +1 -1
  909. package/src/resources/skills/spike-wrap-up/SKILL.md +9 -9
  910. package/dist/resources/extensions/gsd/user-input-boundary.js +0 -157
  911. package/dist/web/standalone/.next/server/chunks/678.js +0 -2
  912. package/dist/web/standalone/.next/static/chunks/2659.feb6499ca863ebfc.js +0 -1
  913. package/dist/web/standalone/.next/static/chunks/2772.151789db0edea835.js +0 -1
  914. package/dist/web/standalone/.next/static/chunks/4283.10a065467b5340d8.js +0 -2
  915. package/dist/web/standalone/.next/static/chunks/5826.960dc4634cc9b0d3.js +0 -1
  916. package/dist/web/standalone/.next/static/chunks/796.46f811c0fac23aab.js +0 -10
  917. package/dist/web/standalone/.next/static/chunks/8785.d32f7a61f55c1600.js +0 -1
  918. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts +0 -21
  919. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts.map +0 -1
  920. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js +0 -213
  921. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js.map +0 -1
  922. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-density-prototype.d.ts +0 -28
  923. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-density-prototype.d.ts.map +0 -1
  924. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-density-prototype.js +0 -249
  925. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-density-prototype.js.map +0 -1
  926. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-design-prototype.d.ts +0 -19
  927. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-design-prototype.d.ts.map +0 -1
  928. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-design-prototype.js +0 -797
  929. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-design-prototype.js.map +0 -1
  930. package/scripts/ensure-workspace-builds.cjs +0 -129
  931. package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +0 -26
  932. package/src/resources/extensions/gsd/user-input-boundary.ts +0 -166
  933. /package/dist/web/standalone/.next/static/{tJOKQbQRO-9MiFDO8DIDS → T-LTxEw5wir5Lm5T3qEVd}/_buildManifest.js +0 -0
  934. /package/dist/web/standalone/.next/static/{tJOKQbQRO-9MiFDO8DIDS → T-LTxEw5wir5Lm5T3qEVd}/_ssgManifest.js +0 -0
@@ -1,51 +1,700 @@
1
1
  // Project/App: gsd-pi
2
2
  // File Purpose: Auto Orchestration module implementation and ADR-015 invariant pipeline owner.
3
+ //
4
+ // Phase 2 of #442 collapsed the nine single-implementation adapter seams
5
+ // (DispatchAdapter, RecoveryAdapter, StateReconciliationAdapter,
6
+ // ToolContractAdapter, WorktreeAdapter, HealthAdapter, UokGateAdapter,
7
+ // RuntimePersistenceAdapter, NotificationAdapter) into this class. The
8
+ // orchestrator now constructs from the concrete extension context and calls
9
+ // the real collaborators (state-reconciliation, doctor-proactive,
10
+ // auto-dispatch, recovery-classification, tool-contract, worktree-safety,
11
+ // uok/gate-runner, journal, session-lock, ctx.ui.notify) directly.
12
+ import { debugCount, debugLog, debugTime } from "../debug-logger.js";
13
+ import { reconcileBeforeDispatch } from "../state-reconciliation.js";
14
+ import { isLegalEdge, IllegalPhaseTransitionError } from "../state-transition-matrix.js";
15
+ import { hasPendingDeepStage, resolveDispatch } from "../auto-dispatch.js";
16
+ import { classifyFailure } from "../recovery-classification.js";
17
+ import { verifyExpectedArtifact, refreshRecoveryDbForArtifact } from "../auto-recovery.js";
18
+ import { invalidateAllCaches } from "../cache.js";
19
+ import { compileUnitToolContract } from "../tool-contract.js";
20
+ import { createWorktreeSafetyModule } from "../worktree-safety.js";
21
+ import { repairAutoWorktreeSafetyFailure } from "../auto-worktree-repair.js";
22
+ import { resolveManifest } from "../unit-context-manifest.js";
23
+ import { preDispatchHealthGate, recordHealthSnapshot, } from "../doctor-proactive.js";
24
+ import { checkResourcesStale, autoWorktreeBranch, mergeMilestoneToMain } from "../auto-worktree.js";
25
+ import { getSessionLockStatus } from "../session-lock.js";
26
+ import { resolveUokFlags } from "../uok/flags.js";
27
+ import { emitJournalEvent as _emitJournalEvent } from "../journal.js";
28
+ import { loadEffectiveGSDPreferences, getIsolationMode, resolveEffectiveUnitIsolationMode } from "../preferences.js";
29
+ import { detectWorktreeName, getMainBranch, resolveProjectRoot, resolveWorktreeProjectRoot, } from "../worktree.js";
30
+ import { getPriorSliceCompletionBlocker } from "../dispatch-guard.js";
31
+ import { GitServiceImpl } from "../git-service.js";
32
+ import { WorktreeStateProjection } from "../worktree-state-projection.js";
33
+ import { WorktreeLifecycle } from "../worktree-lifecycle.js";
34
+ import { createMilestoneMergeTransaction } from "../milestone-merge-transaction.js";
35
+ import { createWorkspace, scopeMilestone } from "../workspace.js";
36
+ import { supportsStructuredQuestions } from "../workflow-mcp.js";
37
+ import { getRegisteredToolSnapshot, getToolBaselineSnapshot } from "../auto-model-selection.js";
38
+ import { deriveState } from "../state.js";
39
+ import { parseUnitId } from "../unit-id.js";
40
+ import { isClosedStatus } from "../status-guards.js";
41
+ import { isDbAvailable, getSlice, getTask, } from "../gsd-db.js";
42
+ import { refreshWorkflowDatabaseFromDisk } from "../db-workspace.js";
43
+ import { getErrorMessage } from "../error-utils.js";
44
+ import { logWarning } from "../workflow-logger.js";
45
+ import { normalizeRealPath } from "../paths.js";
46
+ import { buildDispatchKey, createDispatchHistory, STUCK_WINDOW_SIZE, } from "./dispatch-history.js";
47
+ import { existsSync, readFileSync } from "node:fs";
48
+ import { join } from "node:path";
49
+ import { evaluateAllCompleteSettlement } from "../milestone-settlement.js";
3
50
  function now() {
4
51
  return Date.now();
5
52
  }
53
+ function noRemainingUnitsOutcome(stateSnapshot) {
54
+ if (stateSnapshot.phase === "complete") {
55
+ return {
56
+ code: "all-complete",
57
+ displayReason: "All milestones complete",
58
+ allMilestonesComplete: true,
59
+ };
60
+ }
61
+ return {
62
+ code: "no-remaining-units",
63
+ displayReason: "No remaining units",
64
+ allMilestonesComplete: false,
65
+ };
66
+ }
67
+ function getAlreadyClosedDispatchReason(unitType, unitId) {
68
+ if (!isDbAvailable())
69
+ return null;
70
+ refreshWorkflowDatabaseFromDisk();
71
+ const { milestone, slice, task } = parseUnitId(unitId);
72
+ if (unitType === "execute-task" && milestone && slice && task) {
73
+ const row = getTask(milestone, slice, task);
74
+ return row && isClosedStatus(row.status)
75
+ ? `execute-task ${unitId} is already ${row.status}`
76
+ : null;
77
+ }
78
+ if (unitType === "complete-slice" && milestone && slice) {
79
+ const row = getSlice(milestone, slice);
80
+ return row && isClosedStatus(row.status)
81
+ ? `complete-slice ${unitId} is already ${row.status}`
82
+ : null;
83
+ }
84
+ return null;
85
+ }
86
+ function shouldAdoptActiveMilestone(state, activeSession, activeDispatchBasePath) {
87
+ const activeMilestoneId = state.activeMilestone?.id;
88
+ const currentMilestoneId = activeSession?.currentMilestoneId;
89
+ if (!activeSession || !activeMilestoneId || !currentMilestoneId || activeMilestoneId === currentMilestoneId) {
90
+ return false;
91
+ }
92
+ const scopedWorktreeMilestone = (activeSession.basePath ? detectWorktreeName(activeSession.basePath) : null) ??
93
+ detectWorktreeName(activeDispatchBasePath);
94
+ if (scopedWorktreeMilestone && scopedWorktreeMilestone !== activeMilestoneId) {
95
+ return false;
96
+ }
97
+ const currentMilestone = state.registry.find((milestone) => milestone.id === currentMilestoneId);
98
+ return !!currentMilestone && isClosedStatus(currentMilestone.status);
99
+ }
6
100
  /**
7
- * Size of the dispatch-decision ring buffer used by the Auto Orchestration
8
- * module's stuck-loop detector. When the same `${unitType}:${unitId}` key
9
- * fills the window, advance() blocks with `action: "stop"`.
101
+ * Pure dispatch-decision function formerly `createWiredDispatchAdapter`'s
102
+ * `decideNextUnit`. Folded out of the closure so the orchestrator can call it
103
+ * directly and tests can drive the exact dispatch decision logic against real
104
+ * fixtures without re-introducing an adapter seam.
10
105
  *
11
- * Mirrors the legacy `STUCK_WINDOW_SIZE` in auto/phases.ts so behaviour is
12
- * preserved across the eventual cutover (issue #5791).
106
+ * Derives session-derived dispatch inputs the same way phases.ts:runDispatch
107
+ * does (#5789): prefers caller-supplied values when present so test harnesses
108
+ * and alternative wirings can inject deterministic snapshots; otherwise pulls
109
+ * from the captured pi/ctx references.
13
110
  */
14
- export const STUCK_WINDOW_SIZE = 6;
15
- function noRemainingUnitsReason(stateSnapshot) {
16
- if (stateSnapshot.phase === "complete") {
17
- return "all milestones complete";
111
+ export async function decideOrchestratorDispatch(ctx, pi, dispatchBasePath, session, input) {
112
+ const state = input.stateSnapshot;
113
+ const active = state.activeMilestone;
114
+ const activeSession = input.session ?? session;
115
+ const activeDispatchBasePath = activeSession?.basePath || dispatchBasePath;
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)) {
129
+ activeSession.currentMilestoneId = active.id;
18
130
  }
19
- return "no remaining units";
131
+ const dispatchMid = active?.id ?? activeSession?.currentMilestoneId ?? "";
132
+ const dispatchMidTitle = active?.title ?? "";
133
+ // Derive session-derived dispatch inputs the same way phases.ts:runDispatch does
134
+ // (#5789). Prefer caller-supplied values when present so test harnesses and
135
+ // alternative wirings can inject deterministic snapshots; otherwise pull from
136
+ // the captured pi/ctx references.
137
+ const sessionProvider = input.sessionProvider ?? ctx.model?.provider;
138
+ const sessionContextWindow = input.sessionContextWindow ?? ctx.model?.contextWindow;
139
+ const modelRegistry = input.modelRegistry ?? ctx.modelRegistry;
140
+ const authMode = sessionProvider && typeof ctx.modelRegistry?.getProviderAuthMode === "function"
141
+ ? ctx.modelRegistry.getProviderAuthMode(sessionProvider)
142
+ : undefined;
143
+ // Use baseline snapshot — same reason as phases.ts:runDispatch: the live
144
+ // active set may be narrowed by the prior unit before selectAndApplyModel
145
+ // restores it, causing false transport-preflight failures (#477 follow-up).
146
+ const activeTools = getToolBaselineSnapshot(pi);
147
+ const registeredTools = getRegisteredToolSnapshot(pi);
148
+ // Mirrors runDispatch: deep-planning keeps approval gates in plain chat
149
+ // because structured questions can be cancelled outside the chat turn on
150
+ // some transports.
151
+ const structuredQuestionsAvailable = input.structuredQuestionsAvailable ??
152
+ (prefs?.planning_depth === "deep"
153
+ ? "false"
154
+ : supportsStructuredQuestions(activeTools, {
155
+ authMode,
156
+ baseUrl: ctx.model?.baseUrl,
157
+ })
158
+ ? "true"
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`.
167
+ const pendingRetry = session?.pendingVerificationRetryDispatch;
168
+ if (session && pendingRetry && active) {
169
+ session.pendingVerificationRetryDispatch = null;
170
+ const alreadyClosedReason = getAlreadyClosedDispatchReason(pendingRetry.unitType, pendingRetry.unitId);
171
+ if (alreadyClosedReason) {
172
+ session.pendingOrchestrationDispatch = null;
173
+ session.pendingVerificationRetry = null;
174
+ return { kind: "skipped", reason: alreadyClosedReason };
175
+ }
176
+ session.pendingOrchestrationDispatch = pendingRetry;
177
+ return {
178
+ unitType: pendingRetry.unitType,
179
+ unitId: pendingRetry.unitId,
180
+ reason: "verification-retry",
181
+ preconditions: [],
182
+ };
183
+ }
184
+ const action = await resolveDispatch({
185
+ basePath: activeDispatchBasePath,
186
+ mid: dispatchMid,
187
+ midTitle: dispatchMidTitle,
188
+ state,
189
+ prefs,
190
+ session: activeSession,
191
+ structuredQuestionsAvailable,
192
+ sessionContextWindow,
193
+ sessionProvider,
194
+ modelRegistry,
195
+ activeTools,
196
+ registeredTools,
197
+ sessionAuthMode: authMode,
198
+ sessionBaseUrl: ctx.model?.baseUrl,
199
+ });
200
+ if (action.action === "stop") {
201
+ if (session)
202
+ session.pendingOrchestrationDispatch = null;
203
+ return {
204
+ kind: "blocked",
205
+ reason: action.reason,
206
+ action: action.level === "warning" ? "pause" : "stop",
207
+ };
208
+ }
209
+ if (action.action !== "dispatch") {
210
+ if (session)
211
+ session.pendingOrchestrationDispatch = null;
212
+ return {
213
+ kind: "skipped",
214
+ reason: action.matchedRule ?? "dispatch-skip",
215
+ };
216
+ }
217
+ const alreadyClosedReason = getAlreadyClosedDispatchReason(action.unitType, action.unitId);
218
+ if (alreadyClosedReason) {
219
+ if (session) {
220
+ session.pendingOrchestrationDispatch = null;
221
+ session.pendingVerificationRetry = null;
222
+ }
223
+ return { kind: "skipped", reason: alreadyClosedReason };
224
+ }
225
+ if (session) {
226
+ const pending = {
227
+ unitType: action.unitType,
228
+ unitId: action.unitId,
229
+ prompt: action.prompt,
230
+ pauseAfterUatDispatch: action.pauseAfterDispatch ?? false,
231
+ state,
232
+ mid: dispatchMid,
233
+ midTitle: dispatchMidTitle,
234
+ };
235
+ session.pendingOrchestrationDispatch = pending;
236
+ }
237
+ return {
238
+ unitType: action.unitType,
239
+ unitId: action.unitId,
240
+ reason: action.matchedRule ?? "dispatch",
241
+ preconditions: [],
242
+ };
20
243
  }
21
244
  export class AutoOrchestrator {
22
245
  status = {
23
246
  phase: "idle",
24
247
  transitionCount: 0,
25
248
  };
26
- deps;
249
+ ctx;
250
+ pi;
251
+ dispatchBasePath;
252
+ runtimeBasePath;
253
+ s;
254
+ flowId;
255
+ seq = 0;
27
256
  lastAdvanceKey = null;
28
257
  lastFinalizedUnitKey = null;
29
- dispatchKeyWindow = [];
30
- constructor(deps) {
31
- this.deps = deps;
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;
265
+ // #442: the unit key we last attempted graduated stuck-recovery for. Bounds
266
+ // recovery to one attempt per stuck episode per run (reset on start/resume/
267
+ // stop), mirroring the legacy Level-1-then-Level-2 escalation in phases.ts.
268
+ lastStuckRecoveryKey = null;
269
+ constructor(context) {
270
+ this.ctx = context.ctx;
271
+ this.pi = context.pi;
272
+ this.dispatchBasePath = context.dispatchBasePath;
273
+ this.runtimeBasePath = context.runtimeBasePath;
274
+ this.s = context.session;
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
+ });
283
+ }
284
+ // ── Live base-path resolution (was the wiring factory's getLiveDispatchBasePath) ──
285
+ getLiveDispatchBasePath() {
286
+ return resolveLiveOrchestratorBasePath({
287
+ capturedBasePath: this.dispatchBasePath,
288
+ runtimeBasePath: this.runtimeBasePath,
289
+ sessionBasePath: this.s.basePath,
290
+ originalBasePath: this.s.originalBasePath,
291
+ });
292
+ }
293
+ // ── RuntimePersistenceAdapter (folded) ───────────────────────────────────
294
+ ensureLockOwnership() {
295
+ const status = getSessionLockStatus(this.runtimeBasePath);
296
+ if (!status.valid || status.failureReason === "pid-mismatch") {
297
+ throw new Error("session lock held by another process");
298
+ }
299
+ }
300
+ /**
301
+ * Map an orchestrator lifecycle event name to its journal eventType and emit
302
+ * it. The name→eventType ternary is preserved byte-for-byte from the legacy
303
+ * wired RuntimePersistenceAdapter.journalTransition.
304
+ */
305
+ journalTransition(event) {
306
+ const eventType = event.name === "start"
307
+ ? "orchestrator-iteration-start"
308
+ : event.name === "resume"
309
+ ? "orchestrator-iteration-start"
310
+ : event.name === "advance"
311
+ ? "orchestrator-dispatch-match"
312
+ : event.name === "advance-blocked"
313
+ ? "orchestrator-guard-block"
314
+ : event.name === "advance-stopped"
315
+ ? "orchestrator-dispatch-stop"
316
+ : event.name === "advance-error"
317
+ ? "orchestrator-iteration-end"
318
+ : event.name === "advance-paused" || event.name === "advance-retry"
319
+ ? "orchestrator-guard-block"
320
+ : event.name === "stop"
321
+ ? "orchestrator-terminal"
322
+ : "orchestrator-iteration-end";
323
+ _emitJournalEvent(this.runtimeBasePath, {
324
+ ts: new Date().toISOString(),
325
+ flowId: this.flowId,
326
+ seq: ++this.seq,
327
+ eventType,
328
+ data: {
329
+ source: "auto-orchestrator",
330
+ name: event.name,
331
+ reason: event.reason,
332
+ unitType: event.unitType,
333
+ unitId: event.unitId,
334
+ },
335
+ });
336
+ }
337
+ // ── NotificationAdapter (folded) ─────────────────────────────────────────
338
+ notifyLifecycle(event) {
339
+ if (event.name === "error") {
340
+ this.ctx.ui.notify(event.detail ?? "auto orchestration error", "error");
341
+ }
342
+ }
343
+ // ── HealthAdapter (folded) ───────────────────────────────────────────────
344
+ checkResourcesStale() {
345
+ return checkResourcesStale(this.s.resourceVersionOnStart);
346
+ }
347
+ async preAdvanceGate() {
348
+ try {
349
+ const gate = await preDispatchHealthGate(this.getLiveDispatchBasePath());
350
+ if (gate.proceed) {
351
+ return {
352
+ kind: "pass",
353
+ fixesApplied: gate.fixesApplied,
354
+ };
355
+ }
356
+ return {
357
+ kind: "fail",
358
+ reason: gate.reason ?? "Pre-dispatch health check failed — run /gsd doctor for details.",
359
+ action: gate.severity ?? "pause",
360
+ };
361
+ }
362
+ catch (error) {
363
+ return { kind: "threw", error };
364
+ }
365
+ }
366
+ postAdvanceRecord(result) {
367
+ if (result.kind === "error") {
368
+ recordHealthSnapshot(1, 0, 0, [{
369
+ code: "orchestration-error",
370
+ message: result.reason ?? "orchestration error",
371
+ severity: "error",
372
+ unitId: "orchestration",
373
+ }], [], "orchestration");
374
+ }
375
+ else if (result.kind === "blocked") {
376
+ recordHealthSnapshot(0, 1, 0, [{
377
+ code: "orchestration-blocked",
378
+ message: result.reason ?? "orchestration blocked",
379
+ severity: "warning",
380
+ unitId: "orchestration",
381
+ }], [], "orchestration");
382
+ }
383
+ }
384
+ // ── UokGateAdapter (folded) ──────────────────────────────────────────────
385
+ async emitUokGate(input) {
386
+ const activeBasePath = this.getLiveDispatchBasePath();
387
+ const prefs = loadEffectiveGSDPreferences(activeBasePath)?.preferences;
388
+ const uokFlags = resolveUokFlags(prefs);
389
+ if (!uokFlags.gates)
390
+ return;
391
+ const milestoneId = input.milestoneId ?? this.s.currentMilestoneId ?? undefined;
392
+ try {
393
+ const { UokGateRunner } = await import("../uok/gate-runner.js");
394
+ const runner = new UokGateRunner();
395
+ runner.register({
396
+ id: input.gateId,
397
+ type: input.gateType,
398
+ execute: async () => ({
399
+ outcome: input.outcome,
400
+ failureClass: input.failureClass,
401
+ rationale: input.rationale,
402
+ findings: input.findings ?? "",
403
+ }),
404
+ });
405
+ await runner.run(input.gateId, {
406
+ basePath: activeBasePath,
407
+ traceId: `pre-dispatch:${this.flowId}`,
408
+ turnId: `orch-${this.seq}`,
409
+ milestoneId,
410
+ unitType: "pre-dispatch",
411
+ unitId: `orch-${this.seq}`,
412
+ });
413
+ }
414
+ catch (err) {
415
+ logWarning("engine", `uok gate emit failed: ${getErrorMessage(err)}`, {
416
+ file: "orchestrator.ts",
417
+ gateId: input.gateId,
418
+ gateType: input.gateType,
419
+ ...(milestoneId ? { milestoneId } : {}),
420
+ });
421
+ }
422
+ }
423
+ // ── StateReconciliationAdapter (folded) ──────────────────────────────────
424
+ async reconcileBeforeDispatch() {
425
+ const activeBasePath = this.getLiveDispatchBasePath();
426
+ const result = await reconcileBeforeDispatch(activeBasePath);
427
+ // Failure-path summaries written by gsd_summary_save create
428
+ // artifact-db-status-divergence blockers for tasks that are still
429
+ // pending (gsd_task_complete never ran). These tasks can still be
430
+ // dispatched and the drift self-heals once they complete successfully.
431
+ const hardBlockers = result.blockers.filter((b) => !b.includes("has SUMMARY artifact while DB status is") &&
432
+ !b.includes("has SUMMARY on disk while DB status is") &&
433
+ !b.includes("has task SUMMARY artifacts but no DB tasks"));
434
+ if (hardBlockers.length > 0) {
435
+ return {
436
+ ok: false,
437
+ reason: hardBlockers[0],
438
+ stateSnapshot: result.stateSnapshot,
439
+ };
440
+ }
441
+ const repairedKinds = result.repaired.map((d) => d.kind);
442
+ return {
443
+ ok: true,
444
+ reason: repairedKinds.length > 0
445
+ ? `repaired: ${repairedKinds.join(", ")}`
446
+ : "clean",
447
+ stateSnapshot: result.stateSnapshot,
448
+ };
449
+ }
450
+ // ── DispatchAdapter (folded) ─────────────────────────────────────────────
451
+ decideNextUnit(input) {
452
+ return decideOrchestratorDispatch(this.ctx, this.pi, this.dispatchBasePath, this.s, input);
453
+ }
454
+ evaluateNoRemainingUnitsSettlement(stateSnapshot) {
455
+ const settlement = evaluateAllCompleteSettlement({
456
+ milestoneId: this.s.currentMilestoneId ?? stateSnapshot.activeMilestone?.id,
457
+ statePhase: stateSnapshot.phase,
458
+ basePath: this.s.basePath || this.getLiveDispatchBasePath(),
459
+ originalBasePath: this.s.originalBasePath || this.runtimeBasePath,
460
+ milestoneMerged: this.s.milestoneMergedInPhases,
461
+ });
462
+ this.s.milestoneSettlement = settlement;
463
+ if (settlement.ok)
464
+ return null;
465
+ return {
466
+ kind: "blocked",
467
+ reason: settlement.message,
468
+ action: settlement.action,
469
+ stateSnapshot,
470
+ terminalOutcome: {
471
+ code: "settlement-blocked",
472
+ displayReason: settlement.message,
473
+ nextAction: settlement.nextAction,
474
+ milestoneId: settlement.milestoneId,
475
+ allMilestonesComplete: false,
476
+ },
477
+ };
478
+ }
479
+ clearPendingDispatch() {
480
+ this.s.pendingOrchestrationDispatch = null;
481
+ }
482
+ findPriorSliceCompletionBlocker(unitType, unitId) {
483
+ const guardBasePath = resolveWorktreeProjectRoot(this.getLiveDispatchBasePath(), this.s.originalBasePath);
484
+ let mainBranch = "main";
485
+ try {
486
+ mainBranch = getMainBranch(guardBasePath);
487
+ }
488
+ catch (err) {
489
+ // Preserve legacy dispatch behavior: fall back to main when branch
490
+ // discovery fails, then let the guard make the progression decision.
491
+ logWarning("engine", `branch discovery failed, falling back to main: ${getErrorMessage(err)}`, { file: "orchestrator.ts" });
492
+ }
493
+ return getPriorSliceCompletionBlocker(guardBasePath, mainBranch, unitType, unitId);
494
+ }
495
+ // ── ToolContractAdapter (folded) ─────────────────────────────────────────
496
+ compileUnitToolContract(unitType) {
497
+ const result = compileUnitToolContract(unitType);
498
+ if (!result.ok)
499
+ return { ok: false, reason: result.detail };
500
+ return { ok: true, reason: result.contract.validationRules.join(", ") };
501
+ }
502
+ // ── WorktreeAdapter (folded) ─────────────────────────────────────────────
503
+ getEffectiveUnitIsolationMode(basePath) {
504
+ return resolveEffectiveUnitIsolationMode(getIsolationMode(basePath), this.s.isolationDegraded, this.s.strandedRecoveryIsolationMode);
505
+ }
506
+ buildLifecycle() {
507
+ return new WorktreeLifecycle(this.s, {
508
+ gitServiceFactory: (basePath) => {
509
+ const gitConfig = loadEffectiveGSDPreferences()?.preferences?.git ?? {};
510
+ return new GitServiceImpl(basePath, gitConfig);
511
+ },
512
+ worktreeProjection: new WorktreeStateProjection(),
513
+ mergeMilestoneToMain: createMilestoneMergeTransaction(mergeMilestoneToMain),
514
+ });
515
+ }
516
+ rebuildScope(rawPath, milestoneId) {
517
+ if (!milestoneId) {
518
+ this.s.scope = null;
519
+ return;
520
+ }
521
+ try {
522
+ const workspace = createWorkspace(rawPath);
523
+ this.s.scope = scopeMilestone(workspace, milestoneId);
524
+ }
525
+ catch {
526
+ // Non-fatal — scope is additive. Existing readers still use basePath.
527
+ this.s.scope = null;
528
+ }
529
+ }
530
+ async prepareWorktreeForUnit(unitType, unitId) {
531
+ const isolationMode = this.getEffectiveUnitIsolationMode(this.runtimeBasePath);
532
+ const manifest = resolveManifest(unitType);
533
+ if (!manifest) {
534
+ return {
535
+ ok: false,
536
+ reason: `No Unit manifest is registered for ${unitType}`,
537
+ };
538
+ }
539
+ if (isolationMode !== "worktree") {
540
+ return { ok: true, reason: "not-required" };
541
+ }
542
+ const writeScope = manifest.tools.mode === "all" || manifest.tools.mode === "docs"
543
+ ? "source-writing"
544
+ : "planning-only";
545
+ const safety = createWorktreeSafetyModule();
546
+ const activeBasePath = this.getLiveDispatchBasePath();
547
+ const snapshot = await deriveState(activeBasePath);
548
+ const milestoneId = snapshot.activeMilestone?.id ?? null;
549
+ const expectedBranch = milestoneId ? autoWorktreeBranch(milestoneId) : null;
550
+ let result = safety.validateUnitRoot({
551
+ unitType,
552
+ unitId,
553
+ writeScope,
554
+ projectRoot: this.runtimeBasePath,
555
+ unitRoot: activeBasePath,
556
+ milestoneId,
557
+ isolationMode,
558
+ expectedBranch,
559
+ });
560
+ if (!result.ok) {
561
+ const repaired = await repairAutoWorktreeSafetyFailure({
562
+ safetyResult: result,
563
+ projectRoot: this.runtimeBasePath,
564
+ activeRoot: activeBasePath,
565
+ milestoneId,
566
+ enterMilestone: async (id) => {
567
+ this.buildLifecycle().adoptSessionRoot(this.runtimeBasePath, this.s.originalBasePath || this.runtimeBasePath);
568
+ const enterResult = this.buildLifecycle().enterMilestone(id, {
569
+ notify: this.ctx.ui.notify.bind(this.ctx.ui),
570
+ });
571
+ if (!enterResult.ok)
572
+ return { ok: false, reason: enterResult.reason };
573
+ this.rebuildScope(this.s.basePath, this.s.currentMilestoneId);
574
+ return { ok: true };
575
+ },
576
+ revalidate: () => safety.validateUnitRoot({
577
+ unitType,
578
+ unitId,
579
+ writeScope,
580
+ projectRoot: this.runtimeBasePath,
581
+ unitRoot: this.getLiveDispatchBasePath(),
582
+ milestoneId,
583
+ isolationMode: this.getEffectiveUnitIsolationMode(this.runtimeBasePath),
584
+ expectedBranch,
585
+ }),
586
+ });
587
+ result = repaired.result;
588
+ if (result.ok) {
589
+ return { ok: true, reason: repaired.repaired ? `repaired-${result.kind}` : result.kind };
590
+ }
591
+ const repairDetail = repaired.repairReason
592
+ ? ` (repair skipped: ${repaired.repairReason})`
593
+ : "";
594
+ return { ok: false, reason: `${result.kind}: ${result.reason}${repairDetail}` };
595
+ }
596
+ return { ok: true, reason: result.kind };
597
+ }
598
+ // ── RecoveryAdapter (folded) ─────────────────────────────────────────────
599
+ classifyAndRecover(input) {
600
+ const recovery = classifyFailure(input);
601
+ return { action: recovery.action, reason: recovery.reason };
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
+ }
618
+ // ── Lifecycle verbs ──────────────────────────────────────────────────────
619
+ /**
620
+ * #442: graduated stuck recovery, ported from the legacy
621
+ * auto/phases.ts:runDispatch path that Phase 3 retires. The ring-buffer
622
+ * hard-stops (stuck-loop saturation and finalized-repeat) would otherwise
623
+ * KILL a unit that actually completed on disk but whose DB row is still
624
+ * stale. Before hard-stopping, verify the expected artifact exists; if so,
625
+ * refresh the DB from it, invalidate caches and reset the dispatch ring so
626
+ * the next advance picks the correct next unit. Bounded to one attempt per
627
+ * stuck key per episode (reset on lifecycle + genuine finalize) to avoid an
628
+ * unbounded recover→re-saturate→recover loop — mirrors the legacy
629
+ * Level-1-recover-then-Level-2-hard-stop escalation.
630
+ *
631
+ * Returns true when recovery succeeded; the caller should re-loop (return a
632
+ * skipped result) instead of stopping.
633
+ */
634
+ tryStuckArtifactRecovery(unitType, unitId) {
635
+ const key = buildDispatchKey(unitType, unitId);
636
+ if (this.lastStuckRecoveryKey === key)
637
+ return false; // already tried this episode
638
+ const basePath = this.getLiveDispatchBasePath();
639
+ if (!verifyExpectedArtifact(unitType, unitId, basePath))
640
+ return false;
641
+ const refreshed = refreshRecoveryDbForArtifact(unitType, unitId, basePath);
642
+ // Fatal failures cannot be recovered — hard-stop. Non-fatal (e.g. plan-slice
643
+ // DB refresh hiccup) still fall through: invalidating caches and resetting
644
+ // the ring gives the next advance a clean slate to pick up the correct state,
645
+ // mirroring the legacy Level-1 "continue" escalation path.
646
+ if (!refreshed.ok && refreshed.fatal)
647
+ return false;
648
+ this.lastStuckRecoveryKey = key;
649
+ invalidateAllCaches();
650
+ this.dispatchHistory.clearOnRecovery();
651
+ this.lastAdvanceKey = null;
652
+ this.lastFinalizedUnitKey = null;
653
+ return true;
654
+ }
655
+ stuckRecovered(decision, stateSnapshot) {
656
+ const recovered = {
657
+ kind: "skipped",
658
+ reason: `stuck-recovery: ${decision.unitType} ${decision.unitId} artifact found on disk; DB refreshed`,
659
+ stateSnapshot,
660
+ };
661
+ this.status.phase = "running";
662
+ this.status.activeUnit = undefined;
663
+ this.bumpTransition();
664
+ this.journalTransition({
665
+ name: "advance-skipped",
666
+ reason: recovered.reason,
667
+ unitType: decision.unitType,
668
+ unitId: decision.unitId,
669
+ });
670
+ this.postAdvanceRecord(recovered);
671
+ return recovered;
32
672
  }
33
673
  async start(_sessionContext) {
34
674
  this.lastAdvanceKey = null;
35
675
  this.lastFinalizedUnitKey = null;
36
- 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();
682
+ this.lastStuckRecoveryKey = null;
683
+ this.lastDerivedPhase = null;
37
684
  this.status.phase = "running";
38
685
  this.bumpTransition();
39
- await this.deps.runtime.journalTransition({ name: "start" });
40
- await this.deps.notifications.notifyLifecycle({ name: "start" });
686
+ this.journalTransition({ name: "start" });
687
+ this.notifyLifecycle({ name: "start" });
41
688
  return { kind: "started" };
42
689
  }
43
690
  async advance() {
691
+ debugCount("dispatches");
692
+ const stopAdvanceTimer = debugTime("orchestrator-advance");
44
693
  try {
45
- await this.deps.runtime.ensureLockOwnership();
46
- const staleMsg = this.deps.health.checkResourcesStale();
694
+ this.ensureLockOwnership();
695
+ const staleMsg = this.checkResourcesStale();
47
696
  if (staleMsg) {
48
- await this.deps.uokGate.emit({
697
+ await this.emitUokGate({
49
698
  gateId: "resource-version-guard",
50
699
  gateType: "policy",
51
700
  outcome: "fail",
@@ -54,20 +703,20 @@ export class AutoOrchestrator {
54
703
  findings: staleMsg,
55
704
  });
56
705
  const blocked = { kind: "blocked", reason: staleMsg, action: "pause" };
57
- await this.deps.runtime.journalTransition({ name: "advance-blocked", reason: blocked.reason });
58
- await this.deps.health.postAdvanceRecord(blocked);
706
+ this.journalTransition({ name: "advance-blocked", reason: blocked.reason });
707
+ this.postAdvanceRecord(blocked);
59
708
  return blocked;
60
709
  }
61
- await this.deps.uokGate.emit({
710
+ await this.emitUokGate({
62
711
  gateId: "resource-version-guard",
63
712
  gateType: "policy",
64
713
  outcome: "pass",
65
714
  failureClass: "none",
66
715
  rationale: "resource version guard passed",
67
716
  });
68
- const gate = await this.deps.health.preAdvanceGate();
717
+ const gate = await this.preAdvanceGate();
69
718
  if (gate.kind === "fail") {
70
- await this.deps.uokGate.emit({
719
+ await this.emitUokGate({
71
720
  gateId: "pre-dispatch-health-gate",
72
721
  gateType: "execution",
73
722
  outcome: "manual-attention",
@@ -80,12 +729,12 @@ export class AutoOrchestrator {
80
729
  reason: gate.reason,
81
730
  action: gate.action ?? "pause",
82
731
  };
83
- await this.deps.runtime.journalTransition({ name: "advance-blocked", reason: blocked.reason });
84
- await this.deps.health.postAdvanceRecord(blocked);
732
+ this.journalTransition({ name: "advance-blocked", reason: blocked.reason });
733
+ this.postAdvanceRecord(blocked);
85
734
  return blocked;
86
735
  }
87
736
  if (gate.kind === "threw") {
88
- await this.deps.uokGate.emit({
737
+ await this.emitUokGate({
89
738
  gateId: "pre-dispatch-health-gate",
90
739
  gateType: "execution",
91
740
  outcome: "manual-attention",
@@ -96,7 +745,7 @@ export class AutoOrchestrator {
96
745
  // intentional fall-through: matches runPreDispatch behaviour
97
746
  }
98
747
  else {
99
- await this.deps.uokGate.emit({
748
+ await this.emitUokGate({
100
749
  gateId: "pre-dispatch-health-gate",
101
750
  gateType: "execution",
102
751
  outcome: "pass",
@@ -105,7 +754,7 @@ export class AutoOrchestrator {
105
754
  findings: gate.fixesApplied?.join(", ") ?? "",
106
755
  });
107
756
  }
108
- const reconciliation = await this.deps.stateReconciliation.reconcileBeforeDispatch();
757
+ const reconciliation = await this.reconcileBeforeDispatch();
109
758
  if (!reconciliation.ok || !reconciliation.stateSnapshot) {
110
759
  const blocked = {
111
760
  kind: "blocked",
@@ -113,24 +762,42 @@ export class AutoOrchestrator {
113
762
  action: "pause",
114
763
  stateSnapshot: reconciliation.stateSnapshot,
115
764
  };
116
- await this.deps.runtime.journalTransition({ name: "advance-blocked", reason: blocked.reason });
117
- await this.deps.health.postAdvanceRecord(blocked);
765
+ this.journalTransition({ name: "advance-blocked", reason: blocked.reason });
766
+ this.postAdvanceRecord(blocked);
118
767
  return blocked;
119
768
  }
120
- const decision = await this.deps.dispatch.decideNextUnit({ stateSnapshot: reconciliation.stateSnapshot });
769
+ const reconciledPhase = reconciliation.stateSnapshot.phase;
770
+ if (this.lastDerivedPhase !== null) {
771
+ this.observePhaseTransition(this.lastDerivedPhase, reconciledPhase);
772
+ }
773
+ this.lastDerivedPhase = reconciledPhase;
774
+ const decision = await this.decideNextUnit({ stateSnapshot: reconciliation.stateSnapshot });
121
775
  if (!decision) {
776
+ const settlementBlock = this.evaluateNoRemainingUnitsSettlement(reconciliation.stateSnapshot);
777
+ if (settlementBlock) {
778
+ this.status.phase = "paused";
779
+ this.status.activeUnit = undefined;
780
+ this.lastAdvanceKey = null;
781
+ this.dispatchHistory.clearOnRecovery();
782
+ this.bumpTransition();
783
+ this.journalTransition({ name: "advance-blocked", reason: settlementBlock.reason });
784
+ this.postAdvanceRecord(settlementBlock);
785
+ return settlementBlock;
786
+ }
787
+ const terminalOutcome = noRemainingUnitsOutcome(reconciliation.stateSnapshot);
122
788
  const stopped = {
123
789
  kind: "stopped",
124
- reason: noRemainingUnitsReason(reconciliation.stateSnapshot),
790
+ reason: terminalOutcome.displayReason,
125
791
  stateSnapshot: reconciliation.stateSnapshot,
792
+ terminalOutcome,
126
793
  };
127
794
  this.status.phase = "stopped";
128
795
  this.status.activeUnit = undefined;
129
796
  this.lastAdvanceKey = null;
130
- this.dispatchKeyWindow = [];
797
+ this.dispatchHistory.clearOnRecovery();
131
798
  this.bumpTransition();
132
- await this.deps.runtime.journalTransition({ name: "advance-stopped", reason: stopped.reason });
133
- await this.deps.health.postAdvanceRecord(stopped);
799
+ this.journalTransition({ name: "advance-stopped", reason: stopped.reason });
800
+ this.postAdvanceRecord(stopped);
134
801
  return stopped;
135
802
  }
136
803
  if ("kind" in decision && decision.kind === "skipped") {
@@ -142,8 +809,8 @@ export class AutoOrchestrator {
142
809
  this.status.phase = "running";
143
810
  this.status.activeUnit = undefined;
144
811
  this.bumpTransition();
145
- await this.deps.runtime.journalTransition({ name: "advance-skipped", reason: skipped.reason });
146
- await this.deps.health.postAdvanceRecord(skipped);
812
+ this.journalTransition({ name: "advance-skipped", reason: skipped.reason });
813
+ this.postAdvanceRecord(skipped);
147
814
  return skipped;
148
815
  }
149
816
  if (!("unitType" in decision)) {
@@ -153,34 +820,56 @@ export class AutoOrchestrator {
153
820
  action: decision.action,
154
821
  stateSnapshot: reconciliation.stateSnapshot,
155
822
  };
156
- await this.deps.runtime.journalTransition({ name: "advance-blocked", reason: blocked.reason });
157
- await this.deps.health.postAdvanceRecord(blocked);
823
+ this.journalTransition({ name: "advance-blocked", reason: blocked.reason });
824
+ this.postAdvanceRecord(blocked);
158
825
  return blocked;
159
826
  }
160
- const nextKey = `${decision.unitType}:${decision.unitId}`;
161
- // Record every dispatch decision in the ring buffer before pre-flight
827
+ const priorSliceBlocker = this.findPriorSliceCompletionBlocker(decision.unitType, decision.unitId);
828
+ if (priorSliceBlocker) {
829
+ this.clearPendingDispatch();
830
+ const blocked = {
831
+ kind: "blocked",
832
+ reason: priorSliceBlocker,
833
+ action: "stop",
834
+ stateSnapshot: reconciliation.stateSnapshot,
835
+ };
836
+ this.journalTransition({
837
+ name: "advance-blocked",
838
+ reason: blocked.reason,
839
+ unitType: decision.unitType,
840
+ unitId: decision.unitId,
841
+ });
842
+ this.postAdvanceRecord(blocked);
843
+ return blocked;
844
+ }
845
+ // Record every dispatch decision in the history window before pre-flight
162
846
  // checks so the stuck-loop detector observes the full decision history
163
847
  // (including decisions that idempotency would otherwise short-circuit).
164
- // The ring is capped at STUCK_WINDOW_SIZE and evicts oldest-first.
165
- this.dispatchKeyWindow.push(nextKey);
166
- if (this.dispatchKeyWindow.length > STUCK_WINDOW_SIZE) {
167
- this.dispatchKeyWindow.shift();
168
- }
169
- 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);
170
851
  if (this.lastFinalizedUnitKey === nextKey) {
852
+ // #442: the unit re-dispatched immediately after finalizing may have
853
+ // actually completed on disk with a stale DB. Verify + recover before
854
+ // hard-stopping (legacy graduated stuck-recovery parity).
855
+ if (this.tryStuckArtifactRecovery(decision.unitType, decision.unitId)) {
856
+ this.clearPendingDispatch();
857
+ return this.stuckRecovered(decision, reconciliation.stateSnapshot);
858
+ }
859
+ this.clearPendingDispatch();
171
860
  const blocked = {
172
861
  kind: "blocked",
173
862
  reason: `state did not advance after finalized ${decision.unitType} ${decision.unitId}`,
174
863
  action: "stop",
175
864
  stateSnapshot: reconciliation.stateSnapshot,
176
865
  };
177
- await this.deps.runtime.journalTransition({
866
+ this.journalTransition({
178
867
  name: "advance-blocked",
179
868
  reason: blocked.reason,
180
869
  unitType: decision.unitType,
181
870
  unitId: decision.unitId,
182
871
  });
183
- await this.deps.health.postAdvanceRecord(blocked);
872
+ this.postAdvanceRecord(blocked);
184
873
  return blocked;
185
874
  }
186
875
  // Idempotency: same key as immediately previous successful advance.
@@ -190,90 +879,109 @@ export class AutoOrchestrator {
190
879
  // checks coexist: idempotency for the common immediate-repeat case,
191
880
  // stuck-loop for the saturated-window case.
192
881
  if (this.lastAdvanceKey === nextKey && matchingCount < STUCK_WINDOW_SIZE) {
193
- const blocked = { kind: "blocked", reason: "idempotent advance: unit already active", action: "pause" };
194
- await this.deps.runtime.journalTransition({
195
- name: "advance-blocked",
196
- reason: blocked.reason,
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).
884
+ this.clearPendingDispatch();
885
+ const skipped = { kind: "skipped", reason: "idempotent advance: unit already active" };
886
+ this.journalTransition({
887
+ name: "advance-skipped",
888
+ reason: skipped.reason,
197
889
  unitType: decision.unitType,
198
890
  unitId: decision.unitId,
199
891
  });
200
- await this.deps.health.postAdvanceRecord(blocked);
201
- return blocked;
892
+ this.postAdvanceRecord(skipped);
893
+ return skipped;
202
894
  }
203
- // Stuck-loop detection: when the ring is saturated with copies of
204
- // `nextKey` (count >= STUCK_WINDOW_SIZE), the orchestrator has been
205
- // picking the same unit across the whole window and must hard-stop with
206
- // a diagnosable reason.
207
- 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) {
906
+ // #442: before declaring a stuck loop, verify the unit didn't actually
907
+ // complete on disk (stale DB) and recover if so — legacy graduated
908
+ // stuck-recovery parity. Otherwise hard-stop with a diagnosable reason.
909
+ if (this.tryStuckArtifactRecovery(decision.unitType, decision.unitId)) {
910
+ this.clearPendingDispatch();
911
+ return this.stuckRecovered(decision, reconciliation.stateSnapshot);
912
+ }
913
+ this.clearPendingDispatch();
208
914
  const blocked = {
209
915
  kind: "blocked",
210
- reason: `stuck-loop: ${nextKey} picked ${matchingCount} times`,
916
+ reason: `stuck-loop: ${stuckVerdict.reason}`,
211
917
  action: "stop",
212
918
  };
213
- await this.deps.runtime.journalTransition({
919
+ this.journalTransition({
214
920
  name: "advance-blocked",
215
921
  reason: blocked.reason,
216
922
  unitType: decision.unitType,
217
923
  unitId: decision.unitId,
218
924
  });
219
- await this.deps.health.postAdvanceRecord(blocked);
925
+ this.postAdvanceRecord(blocked);
220
926
  return blocked;
221
927
  }
222
- const contract = await this.deps.toolContract.compileUnitToolContract(decision.unitType, decision.unitId);
928
+ const contract = this.compileUnitToolContract(decision.unitType);
223
929
  if (!contract.ok) {
930
+ this.clearPendingDispatch();
224
931
  const blocked = {
225
932
  kind: "blocked",
226
933
  reason: contract.reason,
227
934
  action: "pause",
228
935
  stateSnapshot: reconciliation.stateSnapshot,
229
936
  };
230
- await this.deps.runtime.journalTransition({
937
+ this.journalTransition({
231
938
  name: "advance-blocked",
232
939
  reason: blocked.reason,
233
940
  unitType: decision.unitType,
234
941
  unitId: decision.unitId,
235
942
  });
236
- await this.deps.health.postAdvanceRecord(blocked);
943
+ this.postAdvanceRecord(blocked);
237
944
  return blocked;
238
945
  }
239
- const worktree = await this.deps.worktree.prepareForUnit(decision.unitType, decision.unitId);
946
+ const worktree = await this.prepareWorktreeForUnit(decision.unitType, decision.unitId);
240
947
  if (!worktree.ok) {
948
+ this.clearPendingDispatch();
241
949
  const blocked = {
242
950
  kind: "blocked",
243
951
  reason: worktree.reason,
244
952
  action: "pause",
245
953
  stateSnapshot: reconciliation.stateSnapshot,
246
954
  };
247
- await this.deps.runtime.journalTransition({
955
+ this.journalTransition({
248
956
  name: "advance-blocked",
249
957
  reason: blocked.reason,
250
958
  unitType: decision.unitType,
251
959
  unitId: decision.unitId,
252
960
  });
253
- await this.deps.health.postAdvanceRecord(blocked);
961
+ this.postAdvanceRecord(blocked);
254
962
  return blocked;
255
963
  }
256
964
  this.status.activeUnit = { unitType: decision.unitType, unitId: decision.unitId };
257
965
  this.status.phase = "running";
258
966
  this.lastAdvanceKey = nextKey;
259
967
  this.bumpTransition();
260
- await this.deps.runtime.journalTransition({
968
+ this.journalTransition({
261
969
  name: "advance",
262
970
  reason: decision.reason,
263
971
  unitType: decision.unitType,
264
972
  unitId: decision.unitId,
265
973
  });
266
- await this.deps.worktree.syncAfterUnit(decision.unitType, decision.unitId);
974
+ // syncAfterUnit was a no-op in the wired WorktreeAdapter.
267
975
  const advanced = {
268
976
  kind: "advanced",
269
977
  unit: { unitType: decision.unitType, unitId: decision.unitId },
270
978
  stateSnapshot: reconciliation.stateSnapshot,
271
979
  };
272
- await this.deps.health.postAdvanceRecord(advanced);
980
+ this.postAdvanceRecord(advanced);
273
981
  return advanced;
274
982
  }
275
983
  catch (error) {
276
- const recovery = await this.deps.recovery.classifyAndRecover({
984
+ const recovery = this.classifyAndRecover({
277
985
  error,
278
986
  unitType: this.status.activeUnit?.unitType,
279
987
  unitId: this.status.activeUnit?.unitId,
@@ -295,7 +1003,7 @@ export class AutoOrchestrator {
295
1003
  if (result.kind === "stopped") {
296
1004
  this.lastAdvanceKey = null;
297
1005
  this.lastFinalizedUnitKey = null;
298
- this.dispatchKeyWindow = [];
1006
+ this.dispatchHistory.clearOnRecovery();
299
1007
  this.status.activeUnit = undefined;
300
1008
  }
301
1009
  this.bumpTransition();
@@ -304,69 +1012,91 @@ export class AutoOrchestrator {
304
1012
  : result.kind === "stopped"
305
1013
  ? "advance-stopped"
306
1014
  : "advance-error";
307
- await this.deps.runtime.journalTransition({ name: journalName, reason: recovery.reason });
1015
+ this.journalTransition({ name: journalName, reason: recovery.reason });
308
1016
  if (result.kind === "paused") {
309
- await this.deps.notifications.notifyLifecycle({ name: "pause", detail: recovery.reason });
1017
+ this.notifyLifecycle({ name: "pause", detail: recovery.reason });
310
1018
  }
311
1019
  else if (result.kind === "stopped") {
312
- await this.deps.notifications.notifyLifecycle({ name: "stopped", detail: recovery.reason });
1020
+ this.notifyLifecycle({ name: "stopped", detail: recovery.reason });
313
1021
  }
314
1022
  else if (result.kind === "error") {
315
- await this.deps.notifications.notifyLifecycle({ name: "error", detail: recovery.reason });
1023
+ this.notifyLifecycle({ name: "error", detail: recovery.reason });
316
1024
  }
317
- await this.deps.health.postAdvanceRecord(result);
1025
+ this.postAdvanceRecord(result);
318
1026
  return result;
319
1027
  }
1028
+ finally {
1029
+ stopAdvanceTimer();
1030
+ }
320
1031
  }
321
1032
  async resume() {
322
1033
  this.lastAdvanceKey = null;
323
1034
  this.lastFinalizedUnitKey = null;
324
- this.dispatchKeyWindow = [];
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
+ }
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;
325
1047
  this.status.phase = "running";
326
1048
  this.bumpTransition();
327
- await this.deps.runtime.journalTransition({ name: "resume" });
328
- await this.deps.notifications.notifyLifecycle({ name: "resume" });
1049
+ this.journalTransition({ name: "resume" });
1050
+ this.notifyLifecycle({ name: "resume" });
329
1051
  return { kind: "resumed" };
330
1052
  }
331
1053
  async stop(reason) {
332
1054
  if (this.status.phase === "stopped") {
333
1055
  return { kind: "stopped", reason };
334
1056
  }
335
- await this.deps.worktree.cleanupOnStop(reason);
1057
+ // cleanupOnStop was a no-op in the wired WorktreeAdapter.
336
1058
  this.status.phase = "stopped";
337
1059
  this.status.activeUnit = undefined;
338
1060
  this.lastAdvanceKey = null;
339
1061
  this.lastFinalizedUnitKey = null;
340
- this.dispatchKeyWindow = [];
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.
1065
+ if (reason !== "pause") {
1066
+ this.dispatchHistory.clearOnRecovery();
1067
+ }
1068
+ this.lastStuckRecoveryKey = null;
341
1069
  this.bumpTransition();
342
- await this.deps.runtime.journalTransition({ name: "stop", reason });
343
- await this.deps.notifications.notifyLifecycle({ name: "stop", detail: reason });
1070
+ this.journalTransition({ name: "stop", reason });
1071
+ this.notifyLifecycle({ name: "stop", detail: reason });
344
1072
  return { kind: "stopped", reason };
345
1073
  }
346
1074
  getStatus() {
347
1075
  return { ...this.status, activeUnit: this.status.activeUnit ? { ...this.status.activeUnit } : undefined };
348
1076
  }
349
1077
  async completeActiveUnit(unit) {
350
- const unitKey = `${unit.unitType}:${unit.unitId}`;
1078
+ const unitKey = buildDispatchKey(unit.unitType, unit.unitId);
351
1079
  const activeUnitKey = this.status.activeUnit
352
- ? `${this.status.activeUnit.unitType}:${this.status.activeUnit.unitId}`
1080
+ ? buildDispatchKey(this.status.activeUnit.unitType, this.status.activeUnit.unitId)
353
1081
  : null;
354
1082
  if (activeUnitKey !== unitKey)
355
1083
  return;
356
1084
  this.status.activeUnit = undefined;
357
1085
  this.lastAdvanceKey = null;
358
1086
  this.lastFinalizedUnitKey = unitKey;
1087
+ // Genuine progress — re-enable graduated stuck recovery for future episodes.
1088
+ this.lastStuckRecoveryKey = null;
359
1089
  this.bumpTransition();
360
- await this.deps.runtime.journalTransition({
1090
+ this.journalTransition({
361
1091
  name: "unit-finalized",
362
1092
  unitType: unit.unitType,
363
1093
  unitId: unit.unitId,
364
1094
  });
365
1095
  }
366
1096
  async retryActiveUnit(unit) {
367
- const unitKey = `${unit.unitType}:${unit.unitId}`;
1097
+ const unitKey = buildDispatchKey(unit.unitType, unit.unitId);
368
1098
  const activeUnitKey = this.status.activeUnit
369
- ? `${this.status.activeUnit.unitType}:${this.status.activeUnit.unitId}`
1099
+ ? buildDispatchKey(this.status.activeUnit.unitType, this.status.activeUnit.unitId)
370
1100
  : null;
371
1101
  if (activeUnitKey !== unitKey && this.lastFinalizedUnitKey !== unitKey)
372
1102
  return;
@@ -376,7 +1106,7 @@ export class AutoOrchestrator {
376
1106
  this.lastAdvanceKey = null;
377
1107
  this.lastFinalizedUnitKey = null;
378
1108
  this.bumpTransition();
379
- await this.deps.runtime.journalTransition({
1109
+ this.journalTransition({
380
1110
  name: "unit-retry",
381
1111
  reason: "finalize-retry",
382
1112
  unitType: unit.unitType,
@@ -388,6 +1118,40 @@ export class AutoOrchestrator {
388
1118
  this.status.lastTransitionAt = now();
389
1119
  }
390
1120
  }
391
- export function createAutoOrchestrator(deps) {
392
- return new AutoOrchestrator(deps);
1121
+ function isUsableLiveOrchestratorBasePath(basePath) {
1122
+ if (!basePath || !existsSync(basePath))
1123
+ return false;
1124
+ if (!detectWorktreeName(basePath))
1125
+ return true;
1126
+ try {
1127
+ return readFileSync(join(basePath, ".git"), "utf8").trim().startsWith("gitdir: ");
1128
+ }
1129
+ catch {
1130
+ return false;
1131
+ }
1132
+ }
1133
+ /**
1134
+ * Resolve the base path the live orchestrator should dispatch from, falling
1135
+ * back to the project root when the captured worktree path has been removed
1136
+ * (e.g. after milestone-merge cleanup). Exported for the closeout-regression
1137
+ * tests and reused by the orchestrator's getLiveDispatchBasePath.
1138
+ */
1139
+ export function resolveLiveOrchestratorBasePath(input) {
1140
+ const primary = input.sessionBasePath || input.capturedBasePath;
1141
+ if (isUsableLiveOrchestratorBasePath(primary))
1142
+ return primary;
1143
+ const fallbacks = [
1144
+ input.originalBasePath,
1145
+ input.runtimeBasePath,
1146
+ resolveProjectRoot(input.capturedBasePath),
1147
+ ];
1148
+ for (const candidate of fallbacks) {
1149
+ if (candidate && isUsableLiveOrchestratorBasePath(candidate)) {
1150
+ return candidate;
1151
+ }
1152
+ }
1153
+ return input.runtimeBasePath || input.capturedBasePath;
1154
+ }
1155
+ export function createAutoOrchestrator(context) {
1156
+ return new AutoOrchestrator(context);
393
1157
  }