gsd-pi 2.79.0-dev.ece5fd8ba → 2.80.0-dev.b62439b9f

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 (607) hide show
  1. package/dist/{cli-web-branch.d.ts → cli/cli-web-branch.d.ts} +1 -1
  2. package/dist/{cli-web-branch.js → cli/cli-web-branch.js} +3 -3
  3. package/dist/{cli.js → cli/cli.js} +25 -25
  4. package/dist/{web-mode.js → cli/web-mode.js} +3 -3
  5. package/dist/{extension-registry.js → extension-runtime/extension-registry.js} +1 -1
  6. package/dist/{headless-query.d.ts → headless/headless-query.d.ts} +1 -1
  7. package/dist/{headless-query.js → headless/headless-query.js} +3 -2
  8. package/dist/{headless-recover.js → headless/headless-recover.js} +3 -2
  9. package/dist/{headless.js → headless/headless.js} +3 -3
  10. package/dist/loader.js +10 -10
  11. package/dist/{onboarding.js → onboarding/onboarding.js} +8 -8
  12. package/dist/{welcome-screen.js → onboarding/welcome-screen.js} +1 -1
  13. package/dist/{models-resolver.js → providers/models-resolver.js} +1 -1
  14. package/dist/{remote-questions-config.js → providers/remote-questions-config.js} +1 -1
  15. package/dist/{resource-loader.d.ts → resource-runtime/resource-loader.d.ts} +1 -1
  16. package/dist/{resource-loader.js → resource-runtime/resource-loader.js} +6 -6
  17. package/dist/resources/.managed-resources-content-hash +1 -1
  18. package/dist/resources/extensions/github-sync/templates.js +55 -70
  19. package/dist/resources/extensions/gsd/auto/contracts.js +1 -0
  20. package/dist/resources/extensions/gsd/auto/custom-verify-retry-store.js +53 -0
  21. package/dist/resources/extensions/gsd/auto/loop.js +362 -523
  22. package/dist/resources/extensions/gsd/auto/orchestrator.js +146 -0
  23. package/dist/resources/extensions/gsd/auto/phases.js +55 -6
  24. package/dist/resources/extensions/gsd/auto/session.js +8 -0
  25. package/dist/resources/extensions/gsd/auto/workflow-custom-engine-dispatch-outcome.js +12 -0
  26. package/dist/resources/extensions/gsd/auto/workflow-custom-engine-iteration.js +24 -0
  27. package/dist/resources/extensions/gsd/auto/workflow-custom-engine-reconcile-outcome.js +33 -0
  28. package/dist/resources/extensions/gsd/auto/workflow-custom-engine-reconcile.js +26 -0
  29. package/dist/resources/extensions/gsd/auto/workflow-custom-engine-retry.js +49 -0
  30. package/dist/resources/extensions/gsd/auto/workflow-custom-engine-verify-outcome.js +25 -0
  31. package/dist/resources/extensions/gsd/auto/workflow-dispatch-claim.js +48 -0
  32. package/dist/resources/extensions/gsd/auto/workflow-dispatch-ledger.js +26 -0
  33. package/dist/resources/extensions/gsd/auto/workflow-iteration-completion.js +10 -0
  34. package/dist/resources/extensions/gsd/auto/workflow-journal-reporter.js +16 -0
  35. package/dist/resources/extensions/gsd/auto/workflow-kernel.js +263 -0
  36. package/dist/resources/extensions/gsd/auto/workflow-memory-pressure.js +36 -0
  37. package/dist/resources/extensions/gsd/auto/workflow-phase-reporter.js +9 -0
  38. package/dist/resources/extensions/gsd/auto/workflow-session-lock.js +35 -0
  39. package/dist/resources/extensions/gsd/auto/workflow-sidecar-iteration.js +24 -0
  40. package/dist/resources/extensions/gsd/auto/workflow-sidecar-queue.js +26 -0
  41. package/dist/resources/extensions/gsd/auto/workflow-turn-reporter.js +36 -0
  42. package/dist/resources/extensions/gsd/auto/workflow-unit-dispatch.js +44 -0
  43. package/dist/resources/extensions/gsd/auto/workflow-worker-heartbeat.js +15 -0
  44. package/dist/resources/extensions/gsd/auto-dashboard.js +3 -0
  45. package/dist/resources/extensions/gsd/auto-prompts.js +168 -3
  46. package/dist/resources/extensions/gsd/auto-recovery.js +45 -52
  47. package/dist/resources/extensions/gsd/auto-runtime-state.js +4 -0
  48. package/dist/resources/extensions/gsd/auto-verification.js +2 -11
  49. package/dist/resources/extensions/gsd/auto-worktree.js +85 -38
  50. package/dist/resources/extensions/gsd/auto.js +162 -5
  51. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +9 -1
  52. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +10 -0
  53. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +11 -5
  54. package/dist/resources/extensions/gsd/commands-ship.js +23 -46
  55. package/dist/resources/extensions/gsd/commands-workflow-templates.js +12 -7
  56. package/dist/resources/extensions/gsd/component-loader.js +5 -11
  57. package/dist/resources/extensions/gsd/custom-workflow-engine.js +25 -1
  58. package/dist/resources/extensions/gsd/db-adapter.js +47 -0
  59. package/dist/resources/extensions/gsd/db-base-schema.js +337 -0
  60. package/dist/resources/extensions/gsd/db-connection-cache.js +31 -0
  61. package/dist/resources/extensions/gsd/db-coordination-schema.js +104 -0
  62. package/dist/resources/extensions/gsd/db-decision-requirement-rows.js +71 -0
  63. package/dist/resources/extensions/gsd/db-gate-rows.js +16 -0
  64. package/dist/resources/extensions/gsd/db-lightweight-query-rows.js +29 -0
  65. package/dist/resources/extensions/gsd/db-memory-fts-schema.js +56 -0
  66. package/dist/resources/extensions/gsd/db-migration-backup.js +22 -0
  67. package/dist/resources/extensions/gsd/db-migration-steps.js +394 -0
  68. package/dist/resources/extensions/gsd/db-milestone-artifact-rows.js +35 -0
  69. package/dist/resources/extensions/gsd/db-open-state.js +32 -0
  70. package/dist/resources/extensions/gsd/db-provider.js +108 -0
  71. package/dist/resources/extensions/gsd/db-runtime-kv-schema.js +27 -0
  72. package/dist/resources/extensions/gsd/db-schema-metadata.js +23 -0
  73. package/dist/resources/extensions/gsd/db-task-slice-rows.js +86 -0
  74. package/dist/resources/extensions/gsd/db-transaction.js +63 -0
  75. package/dist/resources/extensions/gsd/db-verification-evidence-rows.js +3 -0
  76. package/dist/resources/extensions/gsd/db-verification-evidence-schema.js +19 -0
  77. package/dist/resources/extensions/gsd/escalation.js +2 -0
  78. package/dist/resources/extensions/gsd/graph.js +9 -3
  79. package/dist/resources/extensions/gsd/gsd-db.js +215 -1519
  80. package/dist/resources/extensions/gsd/legacy-telemetry.js +70 -0
  81. package/dist/resources/extensions/gsd/markdown-renderer.js +2 -0
  82. package/dist/resources/extensions/gsd/model-router.js +9 -6
  83. package/dist/resources/extensions/gsd/notification-widget.js +21 -3
  84. package/dist/resources/extensions/gsd/post-execution-checks.js +27 -6
  85. package/dist/resources/extensions/gsd/pr-evidence.js +76 -0
  86. package/dist/resources/extensions/gsd/pre-execution-checks.js +2 -0
  87. package/dist/resources/extensions/gsd/process-task-path.js +61 -0
  88. package/dist/resources/extensions/gsd/prompt-loader.js +9 -5
  89. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +32 -30
  90. package/dist/resources/extensions/gsd/prompts/complete-slice.md +23 -34
  91. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +50 -96
  92. package/dist/resources/extensions/gsd/prompts/discuss.md +81 -181
  93. package/dist/resources/extensions/gsd/prompts/execute-task.md +40 -67
  94. package/dist/resources/extensions/gsd/prompts/forensics.md +41 -84
  95. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +29 -39
  96. package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +30 -65
  97. package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +25 -52
  98. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +36 -36
  99. package/dist/resources/extensions/gsd/prompts/guided-research-project.md +20 -38
  100. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +45 -59
  101. package/dist/resources/extensions/gsd/prompts/plan-slice.md +25 -87
  102. package/dist/resources/extensions/gsd/prompts/queue.md +46 -53
  103. package/dist/resources/extensions/gsd/prompts/refine-slice.md +23 -23
  104. package/dist/resources/extensions/gsd/prompts/research-slice.md +23 -23
  105. package/dist/resources/extensions/gsd/prompts/rethink.md +10 -10
  106. package/dist/resources/extensions/gsd/prompts/system.md +65 -107
  107. package/dist/resources/extensions/gsd/prompts/triage-captures.md +15 -15
  108. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +24 -24
  109. package/dist/resources/extensions/gsd/prompts/worktree-merge.md +35 -35
  110. package/dist/resources/extensions/gsd/state.js +4 -0
  111. package/dist/resources/extensions/gsd/tools/complete-milestone.js +14 -9
  112. package/dist/resources/extensions/gsd/tools/complete-task.js +2 -0
  113. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +6 -1
  114. package/dist/resources/extensions/gsd/unit-context-composer.js +1 -1
  115. package/dist/resources/extensions/gsd/uok/kernel.js +8 -3
  116. package/dist/resources/extensions/gsd/uok/plan-v2.js +2 -0
  117. package/dist/resources/extensions/gsd/workflow-logger.js +13 -13
  118. package/dist/resources/extensions/gsd/workflow-manifest.js +2 -0
  119. package/dist/resources/extensions/gsd/workflow-projections.js +2 -0
  120. package/dist/resources/extensions/gsd/workflow-templates.js +9 -0
  121. package/dist/resources/extensions/shared/interview-ui.js +15 -4
  122. package/dist/{security-overrides.js → security/security-overrides.js} +1 -1
  123. package/dist/{startup-model-validation.js → startup/startup-model-validation.js} +1 -1
  124. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  125. package/dist/{update-check.js → update/update-check.js} +1 -1
  126. package/dist/web/standalone/.next/BUILD_ID +1 -1
  127. package/dist/web/standalone/.next/app-path-routes-manifest.json +16 -16
  128. package/dist/web/standalone/.next/build-manifest.json +2 -2
  129. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  130. package/dist/web/standalone/.next/required-server-files.json +1 -1
  131. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  132. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  133. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  134. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  135. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  136. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  137. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  138. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  139. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  140. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  141. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  142. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  143. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  144. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  145. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  146. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  147. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  149. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  151. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  153. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  154. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  155. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  157. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  159. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  161. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  163. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  165. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  167. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  169. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  171. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  173. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  175. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  177. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  179. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  180. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  181. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  183. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  186. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  188. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  190. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  192. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  193. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  194. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  196. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  198. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  199. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  200. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  201. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  202. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  203. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  204. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  205. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  206. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  207. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  208. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +3 -3
  209. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  210. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  211. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  212. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  213. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  214. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  215. package/dist/web/standalone/.next/server/app/index.html +1 -1
  216. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  217. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  218. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  219. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  220. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  221. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  222. package/dist/web/standalone/.next/server/app-paths-manifest.json +16 -16
  223. package/dist/web/standalone/.next/server/chunks/167.js +2 -0
  224. package/dist/web/standalone/.next/server/chunks/7020.js +12 -0
  225. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  226. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  227. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  228. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  229. package/dist/web/standalone/package.json +1 -0
  230. package/dist/web/standalone/server.js +1 -1
  231. package/dist/{worktree-cli.js → worktrees/worktree-cli.js} +3 -2
  232. package/package.json +12 -5
  233. package/packages/contracts/dist/index.d.ts +3 -0
  234. package/packages/contracts/dist/index.d.ts.map +1 -0
  235. package/packages/contracts/dist/index.js +5 -0
  236. package/packages/contracts/dist/index.js.map +1 -0
  237. package/packages/contracts/dist/rpc.d.ts +549 -0
  238. package/packages/contracts/dist/rpc.d.ts.map +1 -0
  239. package/packages/contracts/dist/rpc.js +53 -0
  240. package/packages/contracts/dist/rpc.js.map +1 -0
  241. package/packages/contracts/dist/rpc.test.d.ts +2 -0
  242. package/packages/contracts/dist/rpc.test.d.ts.map +1 -0
  243. package/packages/contracts/dist/rpc.test.js +47 -0
  244. package/packages/contracts/dist/rpc.test.js.map +1 -0
  245. package/packages/contracts/dist/workflow.d.ts +180 -0
  246. package/packages/contracts/dist/workflow.d.ts.map +1 -0
  247. package/packages/contracts/dist/workflow.js +201 -0
  248. package/packages/contracts/dist/workflow.js.map +1 -0
  249. package/packages/contracts/package.json +39 -0
  250. package/packages/contracts/src/index.ts +5 -0
  251. package/packages/contracts/src/rpc.test.ts +72 -0
  252. package/packages/contracts/src/rpc.ts +286 -0
  253. package/packages/contracts/src/workflow.ts +213 -0
  254. package/packages/contracts/tsconfig.json +25 -0
  255. package/packages/daemon/package.json +3 -2
  256. package/packages/daemon/src/event-bridge.test.ts +2 -1
  257. package/packages/daemon/src/event-bridge.ts +1 -1
  258. package/packages/daemon/src/event-formatter.test.ts +1 -2
  259. package/packages/daemon/src/event-formatter.ts +1 -2
  260. package/packages/daemon/src/session-manager.ts +2 -2
  261. package/packages/daemon/src/types.ts +3 -18
  262. package/packages/mcp-server/dist/server.d.ts +13 -0
  263. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  264. package/packages/mcp-server/dist/server.js +77 -0
  265. package/packages/mcp-server/dist/server.js.map +1 -1
  266. package/packages/mcp-server/dist/session-manager.js +1 -1
  267. package/packages/mcp-server/dist/session-manager.js.map +1 -1
  268. package/packages/mcp-server/dist/types.d.ts +3 -11
  269. package/packages/mcp-server/dist/types.d.ts.map +1 -1
  270. package/packages/mcp-server/dist/types.js.map +1 -1
  271. package/packages/mcp-server/dist/workflow-tools.d.ts +1 -1
  272. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  273. package/packages/mcp-server/dist/workflow-tools.js +2 -40
  274. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  275. package/packages/mcp-server/package.json +3 -2
  276. package/packages/mcp-server/src/mcp-server.test.ts +138 -0
  277. package/packages/mcp-server/src/server.ts +99 -1
  278. package/packages/mcp-server/src/session-manager.ts +2 -2
  279. package/packages/mcp-server/src/types.ts +7 -18
  280. package/packages/mcp-server/src/workflow-tools.ts +2 -40
  281. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  282. package/packages/native/package.json +1 -1
  283. package/packages/pi-agent-core/package.json +1 -1
  284. package/packages/pi-ai/package.json +1 -1
  285. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +14 -0
  286. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  287. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +20 -0
  288. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -1
  289. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  290. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +6 -1
  291. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  292. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +9 -1
  293. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  294. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +31 -10
  295. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  296. package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts +1 -512
  297. package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  298. package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.js +3 -7
  299. package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.js.map +1 -1
  300. package/packages/pi-coding-agent/package.json +2 -1
  301. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +23 -2
  302. package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +31 -0
  303. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +6 -1
  304. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +50 -9
  305. package/packages/pi-coding-agent/src/modes/rpc/rpc-types.ts +3 -336
  306. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  307. package/packages/pi-tui/dist/__tests__/tui.test.js +25 -3
  308. package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
  309. package/packages/pi-tui/dist/tui.d.ts +3 -1
  310. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  311. package/packages/pi-tui/dist/tui.js +3 -1
  312. package/packages/pi-tui/dist/tui.js.map +1 -1
  313. package/packages/pi-tui/package.json +1 -1
  314. package/packages/pi-tui/src/__tests__/tui.test.ts +30 -3
  315. package/packages/pi-tui/src/tui.ts +3 -1
  316. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  317. package/packages/rpc-client/README.md +3 -3
  318. package/packages/rpc-client/dist/index.d.ts +1 -1
  319. package/packages/rpc-client/dist/index.d.ts.map +1 -1
  320. package/packages/rpc-client/dist/index.js.map +1 -1
  321. package/packages/rpc-client/dist/rpc-client.d.ts +2 -6
  322. package/packages/rpc-client/dist/rpc-client.d.ts.map +1 -1
  323. package/packages/rpc-client/dist/rpc-client.js.map +1 -1
  324. package/packages/rpc-client/dist/rpc-types.d.ts +1 -565
  325. package/packages/rpc-client/dist/rpc-types.d.ts.map +1 -1
  326. package/packages/rpc-client/dist/rpc-types.js +3 -11
  327. package/packages/rpc-client/dist/rpc-types.js.map +1 -1
  328. package/packages/rpc-client/package.json +4 -1
  329. package/packages/rpc-client/src/index.ts +1 -1
  330. package/packages/rpc-client/src/rpc-client.ts +3 -6
  331. package/packages/rpc-client/src/rpc-types.ts +3 -398
  332. package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
  333. package/pkg/package.json +1 -1
  334. package/src/resources/extensions/github-sync/templates.ts +59 -84
  335. package/src/resources/extensions/github-sync/tests/templates.test.ts +10 -2
  336. package/src/resources/extensions/gsd/auto/contracts.ts +87 -0
  337. package/src/resources/extensions/gsd/auto/custom-verify-retry-store.ts +72 -0
  338. package/src/resources/extensions/gsd/auto/loop-deps.ts +10 -3
  339. package/src/resources/extensions/gsd/auto/loop.ts +414 -598
  340. package/src/resources/extensions/gsd/auto/orchestrator.ts +161 -0
  341. package/src/resources/extensions/gsd/auto/phases.ts +82 -8
  342. package/src/resources/extensions/gsd/auto/session.ts +11 -0
  343. package/src/resources/extensions/gsd/auto/workflow-custom-engine-dispatch-outcome.ts +28 -0
  344. package/src/resources/extensions/gsd/auto/workflow-custom-engine-iteration.ts +52 -0
  345. package/src/resources/extensions/gsd/auto/workflow-custom-engine-reconcile-outcome.ts +58 -0
  346. package/src/resources/extensions/gsd/auto/workflow-custom-engine-reconcile.ts +71 -0
  347. package/src/resources/extensions/gsd/auto/workflow-custom-engine-retry.ts +90 -0
  348. package/src/resources/extensions/gsd/auto/workflow-custom-engine-verify-outcome.ts +50 -0
  349. package/src/resources/extensions/gsd/auto/workflow-dispatch-claim.ts +97 -0
  350. package/src/resources/extensions/gsd/auto/workflow-dispatch-ledger.ts +45 -0
  351. package/src/resources/extensions/gsd/auto/workflow-iteration-completion.ts +26 -0
  352. package/src/resources/extensions/gsd/auto/workflow-journal-reporter.ts +33 -0
  353. package/src/resources/extensions/gsd/auto/workflow-kernel.ts +520 -0
  354. package/src/resources/extensions/gsd/auto/workflow-memory-pressure.ts +58 -0
  355. package/src/resources/extensions/gsd/auto/workflow-phase-reporter.ts +22 -0
  356. package/src/resources/extensions/gsd/auto/workflow-session-lock.ts +68 -0
  357. package/src/resources/extensions/gsd/auto/workflow-sidecar-iteration.ts +46 -0
  358. package/src/resources/extensions/gsd/auto/workflow-sidecar-queue.ts +46 -0
  359. package/src/resources/extensions/gsd/auto/workflow-turn-reporter.ts +68 -0
  360. package/src/resources/extensions/gsd/auto/workflow-unit-dispatch.ts +89 -0
  361. package/src/resources/extensions/gsd/auto/workflow-worker-heartbeat.ts +38 -0
  362. package/src/resources/extensions/gsd/auto-dashboard.ts +4 -0
  363. package/src/resources/extensions/gsd/auto-prompts.ts +170 -3
  364. package/src/resources/extensions/gsd/auto-recovery.ts +42 -50
  365. package/src/resources/extensions/gsd/auto-runtime-state.ts +7 -0
  366. package/src/resources/extensions/gsd/auto-verification.ts +5 -1
  367. package/src/resources/extensions/gsd/auto-worktree.ts +83 -36
  368. package/src/resources/extensions/gsd/auto.ts +170 -4
  369. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +14 -1
  370. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +11 -0
  371. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +13 -5
  372. package/src/resources/extensions/gsd/commands-ship.ts +24 -51
  373. package/src/resources/extensions/gsd/commands-workflow-templates.ts +13 -0
  374. package/src/resources/extensions/gsd/component-loader.ts +5 -11
  375. package/src/resources/extensions/gsd/custom-workflow-engine.ts +29 -0
  376. package/src/resources/extensions/gsd/db-adapter.ts +75 -0
  377. package/src/resources/extensions/gsd/db-base-schema.ts +368 -0
  378. package/src/resources/extensions/gsd/db-connection-cache.ts +45 -0
  379. package/src/resources/extensions/gsd/db-coordination-schema.ts +109 -0
  380. package/src/resources/extensions/gsd/db-decision-requirement-rows.ts +77 -0
  381. package/src/resources/extensions/gsd/db-gate-rows.ts +19 -0
  382. package/src/resources/extensions/gsd/db-lightweight-query-rows.ts +50 -0
  383. package/src/resources/extensions/gsd/db-memory-fts-schema.ts +66 -0
  384. package/src/resources/extensions/gsd/db-migration-backup.ts +34 -0
  385. package/src/resources/extensions/gsd/db-migration-steps.ts +434 -0
  386. package/src/resources/extensions/gsd/db-milestone-artifact-rows.ts +70 -0
  387. package/src/resources/extensions/gsd/db-open-state.ts +47 -0
  388. package/src/resources/extensions/gsd/db-provider.ts +148 -0
  389. package/src/resources/extensions/gsd/db-runtime-kv-schema.ts +30 -0
  390. package/src/resources/extensions/gsd/db-schema-metadata.ts +33 -0
  391. package/src/resources/extensions/gsd/db-task-slice-rows.ts +146 -0
  392. package/src/resources/extensions/gsd/db-transaction.ts +76 -0
  393. package/src/resources/extensions/gsd/db-verification-evidence-rows.ts +14 -0
  394. package/src/resources/extensions/gsd/db-verification-evidence-schema.ts +22 -0
  395. package/src/resources/extensions/gsd/escalation.ts +3 -1
  396. package/src/resources/extensions/gsd/graph.ts +12 -5
  397. package/src/resources/extensions/gsd/gsd-db.ts +260 -1659
  398. package/src/resources/extensions/gsd/interrupted-session.ts +1 -0
  399. package/src/resources/extensions/gsd/legacy-telemetry.ts +99 -0
  400. package/src/resources/extensions/gsd/markdown-renderer.ts +4 -1
  401. package/src/resources/extensions/gsd/model-router.ts +10 -6
  402. package/src/resources/extensions/gsd/notification-widget.ts +25 -4
  403. package/src/resources/extensions/gsd/post-execution-checks.ts +35 -7
  404. package/src/resources/extensions/gsd/pr-evidence.ts +124 -0
  405. package/src/resources/extensions/gsd/pre-execution-checks.ts +4 -1
  406. package/src/resources/extensions/gsd/process-task-path.ts +81 -0
  407. package/src/resources/extensions/gsd/prompt-loader.ts +9 -5
  408. package/src/resources/extensions/gsd/prompts/complete-milestone.md +32 -30
  409. package/src/resources/extensions/gsd/prompts/complete-slice.md +23 -34
  410. package/src/resources/extensions/gsd/prompts/discuss-headless.md +50 -96
  411. package/src/resources/extensions/gsd/prompts/discuss.md +81 -181
  412. package/src/resources/extensions/gsd/prompts/execute-task.md +40 -67
  413. package/src/resources/extensions/gsd/prompts/forensics.md +41 -84
  414. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +29 -39
  415. package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +30 -65
  416. package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +25 -52
  417. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +36 -36
  418. package/src/resources/extensions/gsd/prompts/guided-research-project.md +20 -38
  419. package/src/resources/extensions/gsd/prompts/plan-milestone.md +45 -59
  420. package/src/resources/extensions/gsd/prompts/plan-slice.md +25 -87
  421. package/src/resources/extensions/gsd/prompts/queue.md +46 -53
  422. package/src/resources/extensions/gsd/prompts/refine-slice.md +23 -23
  423. package/src/resources/extensions/gsd/prompts/research-slice.md +23 -23
  424. package/src/resources/extensions/gsd/prompts/rethink.md +10 -10
  425. package/src/resources/extensions/gsd/prompts/system.md +65 -107
  426. package/src/resources/extensions/gsd/prompts/triage-captures.md +15 -15
  427. package/src/resources/extensions/gsd/prompts/validate-milestone.md +24 -24
  428. package/src/resources/extensions/gsd/prompts/worktree-merge.md +35 -35
  429. package/src/resources/extensions/gsd/state.ts +6 -3
  430. package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +32 -0
  431. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +65 -0
  432. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +38 -0
  433. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +353 -0
  434. package/src/resources/extensions/gsd/tests/auto-pr-bugs.test.ts +19 -0
  435. package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +39 -0
  436. package/src/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +3 -0
  437. package/src/resources/extensions/gsd/tests/commands-eval-review.test.ts +2 -2
  438. package/src/resources/extensions/gsd/tests/commands-ship-eval-warn.test.ts +3 -2
  439. package/src/resources/extensions/gsd/tests/complete-milestone-prompt-rendering.test.ts +47 -0
  440. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +19 -5
  441. package/src/resources/extensions/gsd/tests/component-loader.test.ts +2 -9
  442. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +144 -0
  443. package/src/resources/extensions/gsd/tests/custom-verify-retry-store.test.ts +139 -0
  444. package/src/resources/extensions/gsd/tests/custom-workflow-engine.test.ts +50 -0
  445. package/src/resources/extensions/gsd/tests/dashboard-custom-engine.test.ts +3 -3
  446. package/src/resources/extensions/gsd/tests/db-adapter.test.ts +82 -0
  447. package/src/resources/extensions/gsd/tests/db-base-schema.test.ts +62 -0
  448. package/src/resources/extensions/gsd/tests/db-connection-cache.test.ts +60 -0
  449. package/src/resources/extensions/gsd/tests/db-coordination-schema.test.ts +39 -0
  450. package/src/resources/extensions/gsd/tests/db-decision-requirement-rows.test.ts +135 -0
  451. package/src/resources/extensions/gsd/tests/db-gate-rows.test.ts +53 -0
  452. package/src/resources/extensions/gsd/tests/db-lightweight-query-rows.test.ts +45 -0
  453. package/src/resources/extensions/gsd/tests/db-memory-fts-schema.test.ts +86 -0
  454. package/src/resources/extensions/gsd/tests/db-migration-backup.test.ts +105 -0
  455. package/src/resources/extensions/gsd/tests/db-migration-steps.test.ts +159 -0
  456. package/src/resources/extensions/gsd/tests/db-milestone-artifact-rows.test.ts +53 -0
  457. package/src/resources/extensions/gsd/tests/db-open-state.test.ts +56 -0
  458. package/src/resources/extensions/gsd/tests/db-provider.test.ts +105 -0
  459. package/src/resources/extensions/gsd/tests/db-runtime-kv-schema.test.ts +37 -0
  460. package/src/resources/extensions/gsd/tests/db-schema-metadata.test.ts +115 -0
  461. package/src/resources/extensions/gsd/tests/db-task-slice-rows.test.ts +128 -0
  462. package/src/resources/extensions/gsd/tests/db-transaction.test.ts +110 -0
  463. package/src/resources/extensions/gsd/tests/db-verification-evidence-schema.test.ts +76 -0
  464. package/src/resources/extensions/gsd/tests/discuss-headless-rendering.test.ts +37 -0
  465. package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +59 -0
  466. package/src/resources/extensions/gsd/tests/forensics-prompt-rendering.test.ts +36 -0
  467. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +10 -0
  468. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +95 -0
  469. package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +43 -0
  470. package/src/resources/extensions/gsd/tests/guided-discuss-project-prompt-rendering.test.ts +41 -0
  471. package/src/resources/extensions/gsd/tests/guided-discuss-requirements-prompt-rendering.test.ts +45 -0
  472. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +1 -1
  473. package/src/resources/extensions/gsd/tests/headless-query.test.ts +2 -2
  474. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +79 -0
  475. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +37 -0
  476. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +5 -3
  477. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +134 -0
  478. package/src/resources/extensions/gsd/tests/legacy-component-format-telemetry.test.ts +62 -0
  479. package/src/resources/extensions/gsd/tests/legacy-telemetry.test.ts +144 -0
  480. package/src/resources/extensions/gsd/tests/memory-pressure-stuck-state.test.ts +40 -16
  481. package/src/resources/extensions/gsd/tests/model-router.test.ts +33 -12
  482. package/src/resources/extensions/gsd/tests/notification-store.test.ts +8 -0
  483. package/src/resources/extensions/gsd/tests/notification-widget.test.ts +40 -1
  484. package/src/resources/extensions/gsd/tests/paused-session-via-db.test.ts +2 -0
  485. package/src/resources/extensions/gsd/tests/plan-milestone-rendering.test.ts +45 -0
  486. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +65 -16
  487. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +27 -0
  488. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +46 -0
  489. package/src/resources/extensions/gsd/tests/pr-evidence.test.ts +79 -0
  490. package/src/resources/extensions/gsd/tests/process-task-path.test.ts +51 -0
  491. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +16 -1
  492. package/src/resources/extensions/gsd/tests/queue-prompt-rendering.test.ts +37 -0
  493. package/src/resources/extensions/gsd/tests/resource-loader-import-path.test.ts +1 -1
  494. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +32 -9
  495. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +6 -6
  496. package/src/resources/extensions/gsd/tests/uok-kernel-path.test.ts +12 -0
  497. package/src/resources/extensions/gsd/tests/workflow-custom-engine-dispatch-outcome.test.ts +55 -0
  498. package/src/resources/extensions/gsd/tests/workflow-custom-engine-iteration.test.ts +93 -0
  499. package/src/resources/extensions/gsd/tests/workflow-custom-engine-reconcile-outcome.test.ts +108 -0
  500. package/src/resources/extensions/gsd/tests/workflow-custom-engine-reconcile.test.ts +146 -0
  501. package/src/resources/extensions/gsd/tests/workflow-custom-engine-retry.test.ts +136 -0
  502. package/src/resources/extensions/gsd/tests/workflow-custom-engine-verify-outcome.test.ts +95 -0
  503. package/src/resources/extensions/gsd/tests/workflow-dispatch-claim.test.ts +158 -0
  504. package/src/resources/extensions/gsd/tests/workflow-dispatch-ledger.test.ts +82 -0
  505. package/src/resources/extensions/gsd/tests/workflow-iteration-completion.test.ts +44 -0
  506. package/src/resources/extensions/gsd/tests/workflow-journal-reporter.test.ts +49 -0
  507. package/src/resources/extensions/gsd/tests/workflow-kernel.test.ts +607 -0
  508. package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +20 -4
  509. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +8 -7
  510. package/src/resources/extensions/gsd/tests/workflow-memory-pressure.test.ts +71 -0
  511. package/src/resources/extensions/gsd/tests/workflow-phase-reporter.test.ts +40 -0
  512. package/src/resources/extensions/gsd/tests/workflow-session-lock.test.ts +135 -0
  513. package/src/resources/extensions/gsd/tests/workflow-sidecar-iteration.test.ts +110 -0
  514. package/src/resources/extensions/gsd/tests/workflow-sidecar-queue.test.ts +116 -0
  515. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +21 -0
  516. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +32 -0
  517. package/src/resources/extensions/gsd/tests/workflow-turn-reporter.test.ts +87 -0
  518. package/src/resources/extensions/gsd/tests/workflow-unit-dispatch.test.ts +160 -0
  519. package/src/resources/extensions/gsd/tests/workflow-worker-heartbeat.test.ts +123 -0
  520. package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +18 -34
  521. package/src/resources/extensions/gsd/tools/complete-milestone.ts +15 -9
  522. package/src/resources/extensions/gsd/tools/complete-task.ts +4 -1
  523. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +6 -1
  524. package/src/resources/extensions/gsd/unit-context-composer.ts +1 -1
  525. package/src/resources/extensions/gsd/uok/kernel.ts +10 -3
  526. package/src/resources/extensions/gsd/uok/plan-v2.ts +5 -1
  527. package/src/resources/extensions/gsd/workflow-logger.ts +13 -13
  528. package/src/resources/extensions/gsd/workflow-manifest.ts +6 -15
  529. package/src/resources/extensions/gsd/workflow-projections.ts +5 -1
  530. package/src/resources/extensions/gsd/workflow-templates.ts +11 -0
  531. package/src/resources/extensions/shared/interview-ui.ts +18 -5
  532. package/src/resources/extensions/shared/tests/interview-notes-loop.test.ts +41 -0
  533. package/dist/web/standalone/.next/server/chunks/6336.js +0 -1
  534. package/dist/web/standalone/.next/server/chunks/6897.js +0 -12
  535. /package/dist/{app-paths.d.ts → app/app-paths.d.ts} +0 -0
  536. /package/dist/{app-paths.js → app/app-paths.js} +0 -0
  537. /package/dist/{project-sessions.d.ts → app/project-sessions.d.ts} +0 -0
  538. /package/dist/{project-sessions.js → app/project-sessions.js} +0 -0
  539. /package/dist/{tool-bootstrap.d.ts → app/tool-bootstrap.d.ts} +0 -0
  540. /package/dist/{tool-bootstrap.js → app/tool-bootstrap.js} +0 -0
  541. /package/dist/{cli-auto-routing.d.ts → cli/cli-auto-routing.d.ts} +0 -0
  542. /package/dist/{cli-auto-routing.js → cli/cli-auto-routing.js} +0 -0
  543. /package/dist/{cli-policy.d.ts → cli/cli-policy.d.ts} +0 -0
  544. /package/dist/{cli-policy.js → cli/cli-policy.js} +0 -0
  545. /package/dist/{cli.d.ts → cli/cli.d.ts} +0 -0
  546. /package/dist/{help-text.d.ts → cli/help-text.d.ts} +0 -0
  547. /package/dist/{help-text.js → cli/help-text.js} +0 -0
  548. /package/dist/{logo.d.ts → cli/logo.d.ts} +0 -0
  549. /package/dist/{logo.js → cli/logo.js} +0 -0
  550. /package/dist/{web-mode.d.ts → cli/web-mode.d.ts} +0 -0
  551. /package/dist/{bundled-extension-paths.d.ts → extension-runtime/bundled-extension-paths.d.ts} +0 -0
  552. /package/dist/{bundled-extension-paths.js → extension-runtime/bundled-extension-paths.js} +0 -0
  553. /package/dist/{bundled-resource-path.d.ts → extension-runtime/bundled-resource-path.d.ts} +0 -0
  554. /package/dist/{bundled-resource-path.js → extension-runtime/bundled-resource-path.js} +0 -0
  555. /package/dist/{extension-discovery.d.ts → extension-runtime/extension-discovery.d.ts} +0 -0
  556. /package/dist/{extension-discovery.js → extension-runtime/extension-discovery.js} +0 -0
  557. /package/dist/{extension-registry.d.ts → extension-runtime/extension-registry.d.ts} +0 -0
  558. /package/dist/{extension-sort.d.ts → extension-runtime/extension-sort.d.ts} +0 -0
  559. /package/dist/{extension-sort.js → extension-runtime/extension-sort.js} +0 -0
  560. /package/dist/{extension-validator.d.ts → extension-runtime/extension-validator.d.ts} +0 -0
  561. /package/dist/{extension-validator.js → extension-runtime/extension-validator.js} +0 -0
  562. /package/dist/{headless-answers.d.ts → headless/headless-answers.d.ts} +0 -0
  563. /package/dist/{headless-answers.js → headless/headless-answers.js} +0 -0
  564. /package/dist/{headless-context.d.ts → headless/headless-context.d.ts} +0 -0
  565. /package/dist/{headless-context.js → headless/headless-context.js} +0 -0
  566. /package/dist/{headless-events.d.ts → headless/headless-events.d.ts} +0 -0
  567. /package/dist/{headless-events.js → headless/headless-events.js} +0 -0
  568. /package/dist/{headless-recover.d.ts → headless/headless-recover.d.ts} +0 -0
  569. /package/dist/{headless-types.d.ts → headless/headless-types.d.ts} +0 -0
  570. /package/dist/{headless-types.js → headless/headless-types.js} +0 -0
  571. /package/dist/{headless-ui.d.ts → headless/headless-ui.d.ts} +0 -0
  572. /package/dist/{headless-ui.js → headless/headless-ui.js} +0 -0
  573. /package/dist/{headless.d.ts → headless/headless.d.ts} +0 -0
  574. /package/dist/{mcp-server.d.ts → mcp/mcp-server.d.ts} +0 -0
  575. /package/dist/{mcp-server.js → mcp/mcp-server.js} +0 -0
  576. /package/dist/{onboarding.d.ts → onboarding/onboarding.d.ts} +0 -0
  577. /package/dist/{welcome-screen.d.ts → onboarding/welcome-screen.d.ts} +0 -0
  578. /package/dist/{wizard.d.ts → onboarding/wizard.d.ts} +0 -0
  579. /package/dist/{wizard.js → onboarding/wizard.js} +0 -0
  580. /package/dist/{models-resolver.d.ts → providers/models-resolver.d.ts} +0 -0
  581. /package/dist/{pi-migration.d.ts → providers/pi-migration.d.ts} +0 -0
  582. /package/dist/{pi-migration.js → providers/pi-migration.js} +0 -0
  583. /package/dist/{provider-migrations.d.ts → providers/provider-migrations.d.ts} +0 -0
  584. /package/dist/{provider-migrations.js → providers/provider-migrations.js} +0 -0
  585. /package/dist/{remote-questions-config.d.ts → providers/remote-questions-config.d.ts} +0 -0
  586. /package/dist/{rtk-shared.d.ts → rtk/rtk-shared.d.ts} +0 -0
  587. /package/dist/{rtk-shared.js → rtk/rtk-shared.js} +0 -0
  588. /package/dist/{rtk.d.ts → rtk/rtk.d.ts} +0 -0
  589. /package/dist/{rtk.js → rtk/rtk.js} +0 -0
  590. /package/dist/{security-overrides.d.ts → security/security-overrides.d.ts} +0 -0
  591. /package/dist/{claude-cli-check.d.ts → startup/claude-cli-check.d.ts} +0 -0
  592. /package/dist/{claude-cli-check.js → startup/claude-cli-check.js} +0 -0
  593. /package/dist/{runtime-checks.d.ts → startup/runtime-checks.d.ts} +0 -0
  594. /package/dist/{runtime-checks.js → startup/runtime-checks.js} +0 -0
  595. /package/dist/{startup-model-validation.d.ts → startup/startup-model-validation.d.ts} +0 -0
  596. /package/dist/{startup-timings.d.ts → startup/startup-timings.d.ts} +0 -0
  597. /package/dist/{startup-timings.js → startup/startup-timings.js} +0 -0
  598. /package/dist/{update-check.d.ts → update/update-check.d.ts} +0 -0
  599. /package/dist/{update-cmd.d.ts → update/update-cmd.d.ts} +0 -0
  600. /package/dist/{update-cmd.js → update/update-cmd.js} +0 -0
  601. /package/dist/web/standalone/.next/static/{TzEVJ1Lh8vbez4n4Q9TqQ → -WDXZiiJHGZDbYH75Mu6f}/_buildManifest.js +0 -0
  602. /package/dist/web/standalone/.next/static/{TzEVJ1Lh8vbez4n4Q9TqQ → -WDXZiiJHGZDbYH75Mu6f}/_ssgManifest.js +0 -0
  603. /package/dist/{worktree-cli.d.ts → worktrees/worktree-cli.d.ts} +0 -0
  604. /package/dist/{worktree-name-gen.d.ts → worktrees/worktree-name-gen.d.ts} +0 -0
  605. /package/dist/{worktree-name-gen.js → worktrees/worktree-name-gen.js} +0 -0
  606. /package/dist/{worktree-status-banner.d.ts → worktrees/worktree-status-banner.d.ts} +0 -0
  607. /package/dist/{worktree-status-banner.js → worktrees/worktree-status-banner.js} +0 -0
@@ -10,11 +10,10 @@
10
10
  import type { ExtensionAPI, ExtensionContext } from "@gsd/pi-coding-agent";
11
11
 
12
12
  import { randomUUID } from "node:crypto";
13
- import type { AutoSession, SidecarItem } from "./session.js";
13
+ import type { AutoSession } from "./session.js";
14
14
  import type { LoopDeps } from "./loop-deps.js";
15
15
  import {
16
16
  MAX_LOOP_ITERATIONS,
17
- type PhaseResult,
18
17
  type LoopState,
19
18
  type IterationContext,
20
19
  type IterationData,
@@ -24,7 +23,6 @@ import {
24
23
  runPreDispatch,
25
24
  runDispatch,
26
25
  runGuards,
27
- runUnitPhase,
28
26
  runFinalize,
29
27
  } from "./phases.js";
30
28
  import { debugLog } from "../debug-logger.js";
@@ -32,27 +30,68 @@ import { isInfrastructureError, isTransientCooldownError, getCooldownRetryAfterM
32
30
  import { ModelPolicyDispatchBlockedError } from "../auto-model-selection.js";
33
31
  import { resolveEngine } from "../engine-resolver.js";
34
32
  import { logWarning } from "../workflow-logger.js";
35
- import { gsdRoot } from "../paths.js";
36
- import { heartbeatAutoWorker } from "../db/auto-workers.js";
37
33
  import {
38
34
  recordDispatchClaim,
39
35
  markRunning as markDispatchRunning,
40
36
  markCompleted as markDispatchCompleted,
41
37
  markFailed as markDispatchFailed,
42
- markStuck as markDispatchStuck,
43
38
  getRecentForUnit as getRecentDispatchesForUnit,
44
39
  getRecentUnitKeysForProjectRoot,
45
40
  } from "../db/unit-dispatches.js";
46
41
  import { refreshMilestoneLease } from "../db/milestone-leases.js";
42
+ import { heartbeatAutoWorker } from "../db/auto-workers.js";
47
43
  import { getRuntimeKv, setRuntimeKv } from "../db/runtime-kv.js";
48
- import { atomicWriteSync } from "../atomic-write.js";
49
44
  import { resolveUokFlags } from "../uok/flags.js";
50
45
  import { scheduleSidecarQueue } from "../uok/execution-graph.js";
51
- import { ExecutionGraphScheduler } from "../uok/execution-graph.js";
52
- import type { UokGraphNode } from "../uok/contracts.js";
53
- import { readFileSync, writeFileSync, mkdirSync, unlinkSync } from "node:fs";
54
- import { join } from "node:path";
55
46
  import { normalizeRealPath } from "../paths.js";
47
+ import {
48
+ decideCooldownRecovery,
49
+ decideDispatchClaim,
50
+ decideEngineDispatch,
51
+ decideFinalizeResult,
52
+ decideInfrastructureError,
53
+ decideIterationErrorRecovery,
54
+ decideMemoryPressure,
55
+ decideModelPolicyBlocked,
56
+ decideMinRequestInterval,
57
+ decideWorkflowLoop,
58
+ formatDispatchExceptionSummary,
59
+ formatUnhandledDispatchErrorSummary,
60
+ resolveUnitRequestTimestamp,
61
+ shouldUseCustomEnginePath,
62
+ } from "./workflow-kernel.js";
63
+ import {
64
+ hydrateCustomVerifyRetryCounts,
65
+ saveCustomVerifyRetryCounts,
66
+ } from "./custom-verify-retry-store.js";
67
+ import {
68
+ settleDispatchCompleted,
69
+ settleDispatchFailed,
70
+ } from "./workflow-dispatch-ledger.js";
71
+ import { openDispatchClaim } from "./workflow-dispatch-claim.js";
72
+ import { completeWorkflowIteration } from "./workflow-iteration-completion.js";
73
+ import { createWorkflowJournalReporter } from "./workflow-journal-reporter.js";
74
+ import { createWorkflowPhaseReporter } from "./workflow-phase-reporter.js";
75
+ import { createWorkflowTurnReporter } from "./workflow-turn-reporter.js";
76
+ import { validateWorkflowSessionLock } from "./workflow-session-lock.js";
77
+ import { dequeueSidecarItem } from "./workflow-sidecar-queue.js";
78
+ import { maintainWorkerHeartbeat } from "./workflow-worker-heartbeat.js";
79
+ import { measureMemoryPressure } from "./workflow-memory-pressure.js";
80
+ import { buildSidecarIterationData } from "./workflow-sidecar-iteration.js";
81
+ import {
82
+ createExecutionGraphUnitDispatchDeps,
83
+ runUnitPhaseViaContract,
84
+ type DispatchContract,
85
+ } from "./workflow-unit-dispatch.js";
86
+ import { handleCustomEngineDispatchOutcome } from "./workflow-custom-engine-dispatch-outcome.js";
87
+ import { buildCustomEngineIterationData } from "./workflow-custom-engine-iteration.js";
88
+ import { handleCustomEngineVerifyRetry } from "./workflow-custom-engine-retry.js";
89
+ import {
90
+ handleCustomEngineVerifyPause,
91
+ handleCustomEngineVerifyRetryOutcome,
92
+ } from "./workflow-custom-engine-verify-outcome.js";
93
+ import { handleCustomEngineReconcile } from "./workflow-custom-engine-reconcile.js";
94
+ import { handleCustomEngineReconcileOutcome } from "./workflow-custom-engine-reconcile-outcome.js";
56
95
 
57
96
  // ── Stuck detection persistence (#3704) ──────────────────────────────────
58
97
  // Phase C migration: stuck-state.json deleted in favor of DB-backed
@@ -98,132 +137,44 @@ function saveStuckState(s: AutoSession, state: LoopState): void {
98
137
  }
99
138
  }
100
139
 
101
- // ── Custom workflow verification retry persistence ───────────────────────
102
- // Custom workflows can request verification retries after a step runs. The
103
- // retry budget must survive an auto-mode restart or a failing verifier can
104
- // consume a fresh retry budget every session.
105
- function customVerifyRetryStateDir(s: Pick<AutoSession, "activeRunDir" | "basePath">): string {
106
- return s.activeRunDir ? join(s.activeRunDir, "runtime") : join(gsdRoot(s.basePath), "runtime");
140
+ function logDispatchLedgerWriteFailure(err: unknown): void {
141
+ debugLog("autoLoop", {
142
+ phase: "dispatch-ledger-write-failed",
143
+ error: err instanceof Error ? err.message : String(err),
144
+ });
107
145
  }
108
146
 
109
- function customVerifyRetryStatePath(s: Pick<AutoSession, "activeRunDir" | "basePath">): string {
110
- return join(customVerifyRetryStateDir(s), "custom-verify-retries.json");
147
+ function logDispatchClaimRejected(details: {
148
+ unitId: string;
149
+ reason: string;
150
+ existingId?: number;
151
+ existingWorker?: string;
152
+ }): void {
153
+ debugLog("autoLoop", {
154
+ phase: "dispatch-claim-rejected",
155
+ ...details,
156
+ });
111
157
  }
112
158
 
113
- function hydrateCustomVerifyRetryCounts(s: AutoSession): Map<string, number> {
114
- if (s.verificationRetryCount.size > 0) {
115
- return s.verificationRetryCount;
116
- }
117
-
118
- try {
119
- const raw = JSON.parse(readFileSync(customVerifyRetryStatePath(s), "utf-8"));
120
- const counts = raw && typeof raw === "object" && raw.counts && typeof raw.counts === "object"
121
- ? raw.counts as Record<string, unknown>
122
- : {};
123
- for (const [key, value] of Object.entries(counts)) {
124
- if (typeof value === "number" && Number.isFinite(value) && value > 0) {
125
- s.verificationRetryCount.set(key, Math.floor(value));
126
- }
127
- }
128
- } catch (err) {
129
- debugLog("autoLoop", { phase: "load-custom-verify-retries-failed", error: err instanceof Error ? err.message : String(err) });
130
- }
131
-
132
- return s.verificationRetryCount;
159
+ function logDispatchClaimFailed(err: unknown): void {
160
+ debugLog("autoLoop", {
161
+ phase: "dispatch-claim-failed",
162
+ error: err instanceof Error ? err.message : String(err),
163
+ });
133
164
  }
134
165
 
135
- function saveCustomVerifyRetryCounts(s: AutoSession): void {
136
- const retryCounts = s.verificationRetryCount;
137
- const filePath = customVerifyRetryStatePath(s);
138
-
139
- try {
140
- if (!retryCounts || retryCounts.size === 0) {
141
- unlinkSync(filePath);
142
- return;
143
- }
144
- mkdirSync(customVerifyRetryStateDir(s), { recursive: true });
145
- atomicWriteSync(filePath, JSON.stringify({
146
- counts: Object.fromEntries(retryCounts),
147
- updatedAt: new Date().toISOString(),
148
- }) + "\n");
149
- } catch (err) {
150
- const code = err && typeof err === "object" && "code" in err ? (err as { code?: string }).code : undefined;
151
- if (code !== "ENOENT") {
152
- debugLog("autoLoop", { phase: "save-custom-verify-retries-failed", error: err instanceof Error ? err.message : String(err) });
153
- }
154
- }
166
+ function logCustomVerifyRetryLoadFailure(err: unknown): void {
167
+ debugLog("autoLoop", {
168
+ phase: "load-custom-verify-retries-failed",
169
+ error: err instanceof Error ? err.message : String(err),
170
+ });
155
171
  }
156
172
 
157
- /**
158
- * Phase B helper: open a unit_dispatches row in 'claimed' state and
159
- * immediately transition it to 'running'. Returns a tri-state result so
160
- * callers can distinguish between a degraded ledger write and an explicit
161
- * already-active rejection from the partial unique index.
162
- *
163
- * Single-worker compatibility: this function is best-effort and never
164
- * throws. The auto-loop must continue to behave identically when the
165
- * ledger is degraded.
166
- */
167
- type DispatchClaimOutcome =
168
- | { kind: "opened"; dispatchId: number }
169
- | { kind: "skip"; reason: "already-active" | "stale-lease"; existingId?: number; existingWorker?: string }
170
- | { kind: "degraded" };
171
-
172
- function openDispatchClaim(
173
- s: AutoSession,
174
- flowId: string,
175
- turnId: string,
176
- iterData: IterationData,
177
- ): DispatchClaimOutcome {
178
- if (!s.workerId || s.milestoneLeaseToken === null) return { kind: "degraded" };
179
- const mid = iterData.mid;
180
- if (!mid) return { kind: "degraded" };
181
-
182
- const recent = getRecentDispatchesForUnit(iterData.unitId, 1);
183
- const attemptN = (recent[0]?.attempt_n ?? 0) + 1;
184
-
185
- let claim: ReturnType<typeof recordDispatchClaim>;
186
- try {
187
- claim = recordDispatchClaim({
188
- traceId: flowId,
189
- turnId,
190
- workerId: s.workerId,
191
- milestoneLeaseToken: s.milestoneLeaseToken,
192
- milestoneId: mid,
193
- sliceId: iterData.state.activeSlice?.id ?? null,
194
- taskId: iterData.state.activeTask?.id ?? null,
195
- unitType: iterData.unitType,
196
- unitId: iterData.unitId,
197
- attemptN,
198
- });
199
- if (!claim.ok) {
200
- debugLog("autoLoop", {
201
- phase: "dispatch-claim-rejected",
202
- unitId: iterData.unitId,
203
- reason: claim.error,
204
- existingId: "existingId" in claim ? claim.existingId : undefined,
205
- existingWorker: "existingWorker" in claim ? claim.existingWorker : undefined,
206
- });
207
- if (claim.error === "already_active") {
208
- return {
209
- kind: "skip",
210
- reason: "already-active",
211
- existingId: claim.existingId,
212
- existingWorker: claim.existingWorker,
213
- };
214
- }
215
- return { kind: "skip", reason: "stale-lease" };
216
- }
217
- markDispatchRunning(claim.dispatchId);
218
- return { kind: "opened", dispatchId: claim.dispatchId };
219
- } catch (err) {
220
- debugLog("autoLoop", {
221
- phase: "dispatch-claim-failed",
222
- error: err instanceof Error ? err.message : String(err),
223
- });
224
- return { kind: "degraded" };
225
- }
226
-
173
+ function logCustomVerifyRetrySaveFailure(err: unknown): void {
174
+ debugLog("autoLoop", {
175
+ phase: "save-custom-verify-retries-failed",
176
+ error: err instanceof Error ? err.message : String(err),
177
+ });
227
178
  }
228
179
 
229
180
  // ── Memory pressure monitoring (#3331) ──────────────────────────────────
@@ -231,110 +182,25 @@ function openDispatchClaim(
231
182
  // the OS OOM killer sends SIGKILL. The threshold is 90% of the V8 heap
232
183
  // limit (--max-old-space-size or default ~1.5-4GB depending on platform).
233
184
  const MEMORY_CHECK_INTERVAL = 5; // check every 5 iterations
234
- const MEMORY_PRESSURE_THRESHOLD = 0.85; // 85% of heap limit
235
185
  const MAX_CUSTOM_ENGINE_VERIFY_RETRIES = 3;
236
186
 
237
- type DispatchContract = "legacy-direct" | "uok-scheduler";
238
-
239
187
  interface AutoLoopOptions {
240
188
  dispatchContract?: DispatchContract;
241
189
  }
242
190
 
243
- function checkMemoryPressure(): { pressured: boolean; heapMB: number; limitMB: number; pct: number } {
244
- const mem = process.memoryUsage();
245
- // v8.getHeapStatistics() gives heap_size_limit but requires import
246
- // Use a conservative estimate: RSS > 3GB is danger zone on most systems
247
- const heapMB = Math.round(mem.heapUsed / 1024 / 1024);
248
- const rssMB = Math.round(mem.rss / 1024 / 1024);
249
- // Try to get the actual V8 heap limit
250
- let limitMB = 4096; // conservative default
251
- try {
252
- const v8 = require("node:v8");
253
- const stats = v8.getHeapStatistics();
254
- limitMB = Math.round(stats.heap_size_limit / 1024 / 1024);
255
- } catch { limitMB = 4096; /* v8 stats unavailable — use conservative default */ }
256
- const pct = heapMB / limitMB;
257
- return { pressured: pct > MEMORY_PRESSURE_THRESHOLD, heapMB, limitMB, pct };
258
- }
259
-
260
- function resolveDispatchNodeKind(
261
- unitType: string,
262
- sidecarItem?: SidecarItem,
263
- ): UokGraphNode["kind"] {
264
- if (sidecarItem?.kind === "hook") return "hook";
265
- if (sidecarItem?.kind === "triage") return "verification";
266
- if (sidecarItem?.kind === "quick-task") return "team-worker";
267
-
268
- if (unitType.startsWith("hook/")) return "hook";
269
- if (unitType === "reactive-execute") return "subagent";
270
- if (
271
- unitType === "gate-evaluate"
272
- || unitType === "validate-milestone"
273
- || unitType === "run-uat"
274
- || unitType === "complete-slice"
275
- ) {
276
- return "verification";
277
- }
278
- if (unitType === "replan-slice" || unitType === "reassess-roadmap") {
279
- return "reprocess";
280
- }
281
- return "unit";
282
- }
283
-
284
191
  async function enforceMinRequestInterval(s: AutoSession, prefs: IterationContext["prefs"]): Promise<void> {
285
192
  const minInterval = prefs?.min_request_interval_ms ?? 0;
286
- if (minInterval > 0 && s.lastRequestTimestamp > 0) {
287
- const elapsed = Date.now() - s.lastRequestTimestamp;
288
- if (elapsed < minInterval) {
289
- const waitMs = minInterval - elapsed;
290
- debugLog("autoLoop", { phase: "rate-limit-wait", waitMs });
291
- await new Promise<void>(r => setTimeout(r, waitMs));
292
- }
193
+ const decision = decideMinRequestInterval({
194
+ minIntervalMs: minInterval,
195
+ lastRequestTimestamp: s.lastRequestTimestamp,
196
+ nowMs: Date.now(),
197
+ });
198
+ if (decision.action === "wait") {
199
+ debugLog("autoLoop", { phase: "rate-limit-wait", waitMs: decision.waitMs });
200
+ await new Promise<void>(r => setTimeout(r, decision.waitMs));
293
201
  }
294
202
  }
295
203
 
296
- async function runUnitPhaseViaContract(
297
- dispatchContract: DispatchContract,
298
- ic: IterationContext,
299
- iterData: IterationData,
300
- loopState: LoopState,
301
- sidecarItem?: SidecarItem,
302
- ): Promise<PhaseResult<{ unitStartedAt?: number; requestDispatchedAt?: number }>> {
303
- if (dispatchContract === "legacy-direct") {
304
- return runUnitPhase(ic, iterData, loopState, sidecarItem);
305
- }
306
-
307
- const scheduler = new ExecutionGraphScheduler();
308
- let outcome: PhaseResult<{ unitStartedAt?: number; requestDispatchedAt?: number }> | null = null;
309
- const executeNode = async (): Promise<void> => {
310
- outcome = await runUnitPhase(ic, iterData, loopState, sidecarItem);
311
- };
312
- const kinds: UokGraphNode["kind"][] = [
313
- "unit",
314
- "hook",
315
- "subagent",
316
- "team-worker",
317
- "verification",
318
- "reprocess",
319
- ];
320
- for (const kind of kinds) scheduler.registerHandler(kind, executeNode);
321
-
322
- const nodeId = `dispatch:${ic.iteration}:${iterData.unitType}:${iterData.unitId}`;
323
- await scheduler.run([
324
- {
325
- id: nodeId,
326
- kind: resolveDispatchNodeKind(iterData.unitType, sidecarItem),
327
- dependsOn: [],
328
- metadata: {
329
- unitType: iterData.unitType,
330
- unitId: iterData.unitId,
331
- },
332
- },
333
- ], { parallel: false, maxWorkers: 1 });
334
-
335
- return outcome ?? { action: "break", reason: "scheduler-dispatch-missing-result" };
336
- }
337
-
338
204
  /**
339
205
  * Main auto-mode execution loop. Iterates: derive → dispatch → guards →
340
206
  * runUnit → finalize → repeat. Exits when s.active becomes false or a
@@ -353,6 +219,7 @@ export async function autoLoop(
353
219
  debugLog("autoLoop", { phase: "enter" });
354
220
  let iteration = 0;
355
221
  const dispatchContract = options?.dispatchContract ?? "legacy-direct";
222
+ const unitDispatchDeps = createExecutionGraphUnitDispatchDeps();
356
223
  // Load persisted stuck state so counters survive session restarts (#3704)
357
224
  const persisted = loadStuckState(s);
358
225
  const loopState: LoopState = {
@@ -368,69 +235,71 @@ export async function autoLoop(
368
235
  iteration++;
369
236
  debugLog("autoLoop", { phase: "loop-top", iteration });
370
237
 
371
- // Phase B: heartbeat the worker registry + active milestone lease so
372
- // janitors and concurrent workers see a live process. Best-effort —
373
- // DB unavailability or stale state must not stop the loop.
374
- if (s.workerId) {
375
- try {
376
- heartbeatAutoWorker(s.workerId);
377
- if (s.currentMilestoneId && s.milestoneLeaseToken) {
378
- refreshMilestoneLease(s.workerId, s.currentMilestoneId, s.milestoneLeaseToken);
379
- }
380
- } catch (err) {
381
- debugLog("autoLoop", {
382
- phase: "heartbeat-failed",
383
- error: err instanceof Error ? err.message : String(err),
384
- });
385
- }
386
- }
238
+ maintainWorkerHeartbeat(s, {
239
+ heartbeatAutoWorker,
240
+ refreshMilestoneLease,
241
+ logHeartbeatFailure: err => debugLog("autoLoop", {
242
+ phase: "heartbeat-failed",
243
+ error: err instanceof Error ? err.message : String(err),
244
+ }),
245
+ });
387
246
 
388
247
  // ── Journal: per-iteration flow grouping ──
389
248
  const flowId = randomUUID();
390
249
  let seqCounter = 0;
391
250
  const nextSeq = () => ++seqCounter;
251
+ const journalReporter = createWorkflowJournalReporter({
252
+ emitJournalEvent: deps.emitJournalEvent,
253
+ flowId,
254
+ nextSeq,
255
+ });
392
256
  const turnId = randomUUID();
393
257
  s.currentTraceId = flowId;
394
258
  s.currentTurnId = turnId;
395
259
  const turnStartedAt = new Date().toISOString();
396
260
  let observedUnitType: string | undefined;
397
261
  let observedUnitId: string | undefined;
398
- let turnFinished = false;
262
+ const phaseReporter = createWorkflowPhaseReporter({
263
+ observer: deps.uokObserver,
264
+ });
265
+ const turnReporter = createWorkflowTurnReporter({
266
+ observer: deps.uokObserver,
267
+ traceId: flowId,
268
+ turnId,
269
+ iteration,
270
+ basePath: s.basePath,
271
+ startedAt: turnStartedAt,
272
+ clearCurrentTurn: () => {
273
+ s.currentTraceId = null;
274
+ s.currentTurnId = null;
275
+ },
276
+ });
399
277
  const finishTurn = (
400
278
  status: "completed" | "failed" | "paused" | "stopped" | "skipped" | "retry",
401
279
  failureClass: "none" | "unknown" | "manual-attention" | "timeout" | "execution" | "closeout" | "git" = "none",
402
280
  error?: string,
403
281
  ): void => {
404
- if (turnFinished) return;
405
- turnFinished = true;
406
- deps.uokObserver?.onTurnResult({
407
- traceId: flowId,
408
- turnId,
409
- iteration,
282
+ turnReporter.finish({
410
283
  unitType: observedUnitType,
411
284
  unitId: observedUnitId,
412
285
  status,
413
286
  failureClass,
414
- phaseResults: [],
415
287
  error,
416
- startedAt: turnStartedAt,
417
- finishedAt: new Date().toISOString(),
418
288
  });
419
- s.currentTraceId = null;
420
- s.currentTurnId = null;
421
289
  };
422
- deps.uokObserver?.onTurnStart({
423
- traceId: flowId,
424
- turnId,
290
+ turnReporter.start();
291
+
292
+ const iterationDecision = decideWorkflowLoop({
293
+ active: s.active,
425
294
  iteration,
426
- basePath: s.basePath,
427
- startedAt: turnStartedAt,
295
+ maxIterations: MAX_LOOP_ITERATIONS,
296
+ hasCommandContext: true,
297
+ sessionLockValid: true,
428
298
  });
429
-
430
- if (iteration > MAX_LOOP_ITERATIONS) {
299
+ if (iterationDecision.action === "stop" && iterationDecision.reason === "max-iterations") {
431
300
  debugLog("autoLoop", {
432
301
  phase: "exit",
433
- reason: "max-iterations",
302
+ reason: iterationDecision.reason,
434
303
  iteration,
435
304
  });
436
305
  await deps.stopAuto(
@@ -445,78 +314,86 @@ export async function autoLoop(
445
314
  // ── Memory pressure check (#3331) ──
446
315
  // Graceful shutdown before OOM killer sends SIGKILL.
447
316
  if (iteration % MEMORY_CHECK_INTERVAL === 0) {
448
- const mem = checkMemoryPressure();
317
+ const mem = measureMemoryPressure();
449
318
  debugLog("autoLoop", { phase: "memory-check", ...mem });
450
- if (mem.pressured) {
451
- logWarning("dispatch", `Memory pressure: ${mem.heapMB}MB / ${mem.limitMB}MB (${Math.round(mem.pct * 100)}%) — stopping auto-mode to prevent OOM kill`);
452
- await deps.stopAuto(
453
- ctx,
454
- pi,
455
- `Memory pressure: heap at ${mem.heapMB}MB / ${mem.limitMB}MB (${Math.round(mem.pct * 100)}%). ` +
456
- `Stopping gracefully to prevent OOM kill after ${iteration} iterations. ` +
457
- `Resume with /gsd auto to continue from where you left off.`,
458
- );
459
- finishTurn("stopped", "timeout", "memory-pressure");
319
+ const memoryDecision = decideMemoryPressure({ ...mem, iteration });
320
+ if (memoryDecision.action === "stop") {
321
+ logWarning("dispatch", memoryDecision.warningMessage);
322
+ await deps.stopAuto(ctx, pi, memoryDecision.stopMessage);
323
+ finishTurn("stopped", "timeout", memoryDecision.turnError);
460
324
  break;
461
325
  }
462
326
  }
463
327
 
464
- if (!s.cmdCtx) {
328
+ const commandContextDecision = decideWorkflowLoop({
329
+ active: s.active,
330
+ iteration,
331
+ maxIterations: MAX_LOOP_ITERATIONS,
332
+ hasCommandContext: Boolean(s.cmdCtx),
333
+ sessionLockValid: true,
334
+ });
335
+ if (commandContextDecision.action === "stop" && commandContextDecision.reason === "missing-command-context") {
465
336
  debugLog("autoLoop", { phase: "exit", reason: "no-cmdCtx" });
466
- finishTurn("stopped", "manual-attention", "missing-command-context");
337
+ finishTurn("stopped", "manual-attention", commandContextDecision.reason);
467
338
  break;
468
339
  }
469
340
 
470
341
  let dispatchId: number | null = null;
471
342
  let dispatchSettled = false;
343
+ const completeIteration = (): void => {
344
+ completeWorkflowIteration({
345
+ get consecutiveErrors() { return consecutiveErrors; },
346
+ set consecutiveErrors(value) { consecutiveErrors = value; },
347
+ get consecutiveCooldowns() { return consecutiveCooldowns; },
348
+ set consecutiveCooldowns(value) { consecutiveCooldowns = value; },
349
+ recentErrorMessages,
350
+ }, {
351
+ emitIterationEnd: () => journalReporter.emit("iteration-end", { iteration }),
352
+ saveStuckState: () => saveStuckState(s, loopState),
353
+ logIterationComplete: () => debugLog("autoLoop", { phase: "iteration-complete", iteration }),
354
+ });
355
+ };
472
356
 
473
357
  try {
474
358
  // ── Blanket try/catch: one bad iteration must not kill the session
475
359
  const prefs = deps.loadEffectiveGSDPreferences()?.preferences;
476
360
  const uokFlags = resolveUokFlags(prefs);
477
361
 
478
- // ── Check sidecar queue before deriveState ──
479
- let sidecarItem: SidecarItem | undefined;
480
- if (s.sidecarQueue.length > 0) {
481
- if (uokFlags.executionGraph && s.sidecarQueue.length > 1) {
482
- try {
483
- s.sidecarQueue = await scheduleSidecarQueue(s.sidecarQueue);
484
- } catch (err) {
485
- logWarning("dispatch", `sidecar queue scheduling failed: ${err instanceof Error ? err.message : String(err)}`);
486
- }
487
- }
488
- sidecarItem = s.sidecarQueue.shift()!;
489
- debugLog("autoLoop", {
490
- phase: "sidecar-dequeue",
491
- kind: sidecarItem.kind,
492
- unitType: sidecarItem.unitType,
493
- unitId: sidecarItem.unitId,
494
- });
495
- deps.emitJournalEvent({ ts: new Date().toISOString(), flowId, seq: nextSeq(), eventType: "sidecar-dequeue", data: { kind: sidecarItem.kind, unitType: sidecarItem.unitType, unitId: sidecarItem.unitId } });
496
- }
497
-
498
- const sessionLockBase = deps.lockBase();
499
- if (sessionLockBase) {
500
- const lockStatus = deps.validateSessionLock(sessionLockBase);
501
- if (!lockStatus.valid) {
502
- debugLog("autoLoop", {
362
+ const sessionLockOutcome = validateWorkflowSessionLock({
363
+ active: s.active,
364
+ iteration,
365
+ maxIterations: MAX_LOOP_ITERATIONS,
366
+ deps: {
367
+ lockBase: deps.lockBase,
368
+ validateSessionLock: deps.validateSessionLock,
369
+ handleLostSessionLock: lockStatus => deps.handleLostSessionLock(ctx, lockStatus),
370
+ logInvalidSessionLock: details => debugLog("autoLoop", {
503
371
  phase: "session-lock-invalid",
504
- reason: lockStatus.failureReason ?? "unknown",
505
- existingPid: lockStatus.existingPid,
506
- expectedPid: lockStatus.expectedPid,
507
- });
508
- deps.handleLostSessionLock(ctx, lockStatus);
509
- debugLog("autoLoop", {
372
+ ...details,
373
+ }),
374
+ logSessionLockExit: details => debugLog("autoLoop", {
510
375
  phase: "exit",
511
- reason: "session-lock-lost",
512
- detail: lockStatus.failureReason ?? "unknown",
513
- });
514
- break;
515
- }
376
+ ...details,
377
+ }),
378
+ },
379
+ });
380
+ if (sessionLockOutcome.action === "stop" && sessionLockOutcome.reason === "session-lock-lost") {
381
+ finishTurn("stopped", "manual-attention", sessionLockOutcome.reason);
382
+ break;
516
383
  }
517
384
 
385
+ // ── Check sidecar queue before deriveState ──
386
+ const sidecarItem = await dequeueSidecarItem({
387
+ queue: s.sidecarQueue,
388
+ executionGraphEnabled: uokFlags.executionGraph,
389
+ scheduleQueue: scheduleSidecarQueue,
390
+ warnSchedulingFailure: message => logWarning("dispatch", `sidecar queue scheduling failed: ${message}`),
391
+ logDequeue: payload => debugLog("autoLoop", { phase: "sidecar-dequeue", ...payload }),
392
+ emitDequeue: payload => journalReporter.emit("sidecar-dequeue", payload),
393
+ });
394
+
518
395
  const ic: IterationContext = { ctx, pi, s, deps, prefs, iteration, flowId, nextSeq };
519
- deps.emitJournalEvent({ ts: new Date().toISOString(), flowId, seq: nextSeq(), eventType: "iteration-start", data: { iteration } });
396
+ journalReporter.emit("iteration-start", { iteration });
520
397
  let iterData: IterationData;
521
398
 
522
399
  // ── Custom engine path ──────────────────────────────────────────────
@@ -527,7 +404,11 @@ export async function autoLoop(
527
404
  //
528
405
  // GSD_ENGINE_BYPASS=1 skips the engine layer entirely — falls through
529
406
  // to the dev path below.
530
- if (s.activeEngineId != null && s.activeEngineId !== "dev" && !sidecarItem && process.env.GSD_ENGINE_BYPASS !== "1") {
407
+ if (shouldUseCustomEnginePath({
408
+ activeEngineId: s.activeEngineId,
409
+ hasSidecarItem: Boolean(sidecarItem),
410
+ engineBypass: process.env.GSD_ENGINE_BYPASS === "1",
411
+ })) {
531
412
  debugLog("autoLoop", { phase: "custom-engine-derive", iteration, engineId: s.activeEngineId });
532
413
 
533
414
  const { engine, policy } = resolveEngine({
@@ -547,45 +428,48 @@ export async function autoLoop(
547
428
  isComplete: engineState.isComplete,
548
429
  });
549
430
  if (engineState.isComplete) {
431
+ finishTurn("completed");
550
432
  await deps.stopAuto(ctx, pi, "Workflow complete");
551
433
  break;
552
434
  }
553
435
 
554
436
  debugLog("autoLoop", { phase: "custom-engine-dispatch", iteration });
555
437
  const dispatch = await engine.resolveDispatch(engineState, { basePath: s.basePath });
556
-
557
- if (dispatch.action === "stop") {
558
- await deps.stopAuto(ctx, pi, dispatch.reason ?? "Engine stopped");
438
+ const engineDispatchDecision = decideEngineDispatch(dispatch.action === "stop"
439
+ ? { action: "stop", reason: dispatch.reason }
440
+ : { action: dispatch.action });
441
+ const dispatchFlow = await handleCustomEngineDispatchOutcome({
442
+ decision: engineDispatchDecision,
443
+ deps: {
444
+ stopAuto: reason => deps.stopAuto(ctx, pi, reason),
445
+ },
446
+ });
447
+ if (dispatchFlow.action === "break") {
448
+ finishTurn("stopped", "manual-attention", "custom-engine-dispatch-stop");
559
449
  break;
560
450
  }
561
- if (dispatch.action === "skip") {
451
+ if (dispatchFlow.action === "continue") {
452
+ finishTurn("skipped");
562
453
  continue;
563
454
  }
564
455
 
565
456
  // dispatch.action === "dispatch"
566
- const step = dispatch.step!;
567
- const gsdState = await deps.deriveState(s.canonicalProjectRoot);
568
- debugLog("autoLoop", {
569
- phase: "post-derive",
570
- site: "custom-engine-gsd-state",
457
+ if (dispatch.action !== "dispatch") {
458
+ finishTurn("skipped");
459
+ continue;
460
+ }
461
+ const step = dispatch.step;
462
+ iterData = await buildCustomEngineIterationData({
463
+ step,
571
464
  basePath: s.basePath,
572
465
  canonicalProjectRoot: s.canonicalProjectRoot,
573
- derivedPhase: gsdState.phase,
574
- activeUnit: gsdState.activeTask?.id ?? gsdState.activeSlice?.id ?? gsdState.activeMilestone?.id,
466
+ currentMilestoneId: s.currentMilestoneId,
467
+ deriveState: deps.deriveState,
468
+ logPostDerive: details => debugLog("autoLoop", {
469
+ phase: "post-derive",
470
+ ...details,
471
+ }),
575
472
  });
576
-
577
- iterData = {
578
- unitType: step.unitType,
579
- unitId: step.unitId,
580
- prompt: step.prompt,
581
- finalPrompt: step.prompt,
582
- pauseAfterUatDispatch: false,
583
- state: gsdState,
584
- mid: s.currentMilestoneId ?? "workflow",
585
- midTitle: "Workflow",
586
- isRetry: false,
587
- previousTier: undefined,
588
- };
589
473
  observedUnitType = iterData.unitType;
590
474
  observedUnitId = iterData.unitId;
591
475
 
@@ -594,7 +478,7 @@ export async function autoLoop(
594
478
 
595
479
  // ── Guards (shared with dev path) ──
596
480
  const guardsResult = await runGuards(ic, s.currentMilestoneId ?? "workflow");
597
- deps.uokObserver?.onPhaseResult("guard", guardsResult.action, {
481
+ phaseReporter.report("guard", guardsResult.action, {
598
482
  unitType: iterData.unitType,
599
483
  unitId: iterData.unitId,
600
484
  });
@@ -610,12 +494,14 @@ export async function autoLoop(
610
494
  ic,
611
495
  iterData,
612
496
  loopState,
497
+ undefined,
498
+ unitDispatchDeps,
613
499
  );
614
500
  if (unitPhaseResult.action === "next") {
615
- const requestTimestamp = unitPhaseResult.data.requestDispatchedAt ?? unitPhaseResult.data.unitStartedAt;
616
- if (typeof requestTimestamp === "number") s.lastRequestTimestamp = requestTimestamp;
501
+ const requestTimestamp = resolveUnitRequestTimestamp(unitPhaseResult.data);
502
+ if (requestTimestamp !== undefined) s.lastRequestTimestamp = requestTimestamp;
617
503
  }
618
- deps.uokObserver?.onPhaseResult("unit", unitPhaseResult.action, {
504
+ phaseReporter.report("unit", unitPhaseResult.action, {
619
505
  unitType: iterData.unitType,
620
506
  unitId: iterData.unitId,
621
507
  });
@@ -628,116 +514,93 @@ export async function autoLoop(
628
514
  debugLog("autoLoop", { phase: "custom-engine-verify", iteration, unitId: iterData.unitId });
629
515
  const verifyResult = await policy.verify(iterData.unitType, iterData.unitId, { basePath: s.basePath });
630
516
  if (verifyResult === "pause") {
631
- await deps.pauseAuto(ctx, pi);
632
- deps.uokObserver?.onPhaseResult("custom-engine", "pause", {
517
+ const verifyFlow = await handleCustomEngineVerifyPause({
633
518
  unitType: iterData.unitType,
634
519
  unitId: iterData.unitId,
520
+ deps: {
521
+ pauseAuto: () => deps.pauseAuto(ctx, pi),
522
+ stopAuto: reason => deps.stopAuto(ctx, pi, reason),
523
+ reportPause: details => phaseReporter.report("custom-engine", "pause", details),
524
+ finishTurn,
525
+ },
635
526
  });
636
- finishTurn("paused", "manual-attention", "custom-engine-verify-pause");
637
- break;
527
+ if (verifyFlow.action === "break") break;
638
528
  }
639
529
  if (verifyResult === "retry") {
640
- const recoveryKey = `${iterData.unitType}/${iterData.unitId}`;
641
- const retryCounts = hydrateCustomVerifyRetryCounts(s);
642
- const attempts = (retryCounts.get(recoveryKey) ?? 0) + 1;
643
- retryCounts.set(recoveryKey, attempts);
644
- saveCustomVerifyRetryCounts(s);
645
- debugLog("autoLoop", { phase: "custom-engine-verify-retry", iteration, unitId: iterData.unitId, attempts });
646
- deps.uokObserver?.onPhaseResult("custom-engine", "retry", {
530
+ const retryOutcome = await handleCustomEngineVerifyRetry({
531
+ session: s,
647
532
  unitType: iterData.unitType,
648
533
  unitId: iterData.unitId,
649
- attempts,
534
+ basePath: s.basePath,
535
+ iteration,
536
+ maxRetries: MAX_CUSTOM_ENGINE_VERIFY_RETRIES,
537
+ deps: {
538
+ hydrateRetryCounts: () => hydrateCustomVerifyRetryCounts(s, {
539
+ logFailure: logCustomVerifyRetryLoadFailure,
540
+ }),
541
+ saveRetryCounts: () => saveCustomVerifyRetryCounts(s, {
542
+ logFailure: logCustomVerifyRetrySaveFailure,
543
+ }),
544
+ recover: (unitType, unitId, options) => policy.recover(unitType, unitId, options),
545
+ logRetry: details => debugLog("autoLoop", {
546
+ phase: "custom-engine-verify-retry",
547
+ ...details,
548
+ }),
549
+ reportRetry: details => phaseReporter.report("custom-engine", "retry", details),
550
+ },
650
551
  });
651
- if (attempts > MAX_CUSTOM_ENGINE_VERIFY_RETRIES) {
652
- const recovery = await policy.recover(iterData.unitType, iterData.unitId, { basePath: s.basePath });
653
- if (recovery.outcome === "pause") {
654
- await deps.pauseAuto(ctx, pi);
655
- finishTurn("paused", "manual-attention", recovery.reason ?? "custom-engine-verify-retry-exhausted");
656
- break;
657
- }
658
- if (recovery.outcome === "skip") {
659
- await deps.stopAuto(
660
- ctx,
661
- pi,
662
- recovery.reason ??
663
- `Custom workflow verification for ${iterData.unitId} requested skip after retry exhaustion, but the custom engine cannot reconcile skipped steps.`,
664
- );
665
- finishTurn("stopped", "manual-attention", "custom-engine-verify-retry-exhausted");
666
- break;
667
- }
668
- const exhaustedReason =
669
- `Custom workflow verification for ${iterData.unitId} requested retry ${attempts} times without passing.`;
670
- await deps.stopAuto(
671
- ctx,
672
- pi,
673
- recovery.outcome === "stop" && recovery.reason ? recovery.reason : exhaustedReason,
674
- );
675
- finishTurn("stopped", "manual-attention", "custom-engine-verify-retry-exhausted");
676
- break;
677
- }
678
- finishTurn("retry");
552
+ const retryFlow = await handleCustomEngineVerifyRetryOutcome({
553
+ outcome: retryOutcome,
554
+ deps: {
555
+ pauseAuto: () => deps.pauseAuto(ctx, pi),
556
+ stopAuto: reason => deps.stopAuto(ctx, pi, reason),
557
+ reportPause: details => phaseReporter.report("custom-engine", "pause", details),
558
+ finishTurn,
559
+ },
560
+ });
561
+ if (retryFlow.action === "break") break;
679
562
  continue;
680
563
  }
681
564
 
682
565
  // Verification passed — mark step complete
683
- s.verificationRetryCount?.delete(`${iterData.unitType}/${iterData.unitId}`);
684
- saveCustomVerifyRetryCounts(s);
685
- debugLog("autoLoop", { phase: "custom-engine-reconcile", iteration, unitId: iterData.unitId });
686
- const reconcileResult = await engine.reconcile(engineState, {
687
- unitType: iterData.unitType,
688
- unitId: iterData.unitId,
689
- startedAt: s.currentUnit?.startedAt ?? Date.now(),
690
- finishedAt: Date.now(),
566
+ const reconcileOutcome = await handleCustomEngineReconcile({
567
+ session: s,
568
+ engineState,
569
+ iterData,
570
+ iteration,
571
+ deps: {
572
+ saveRetryCounts: () => saveCustomVerifyRetryCounts(s, {
573
+ logFailure: logCustomVerifyRetrySaveFailure,
574
+ }),
575
+ logReconcile: details => debugLog("autoLoop", {
576
+ phase: "custom-engine-reconcile",
577
+ ...details,
578
+ }),
579
+ reconcile: (state, completedStep) => engine.reconcile(state, completedStep),
580
+ now: () => Date.now(),
581
+ clearUnitTimeout: deps.clearUnitTimeout,
582
+ completeIteration,
583
+ },
691
584
  });
692
-
693
- deps.clearUnitTimeout();
694
- consecutiveErrors = 0;
695
- consecutiveCooldowns = 0;
696
- recentErrorMessages.length = 0;
697
- deps.emitJournalEvent({ ts: new Date().toISOString(), flowId, seq: nextSeq(), eventType: "iteration-end", data: { iteration } });
698
- saveStuckState(s, loopState); // persist across session restarts (#3704)
699
- debugLog("autoLoop", { phase: "iteration-complete", iteration });
700
-
701
- if (reconcileResult.outcome === "milestone-complete") {
702
- await deps.stopAuto(ctx, pi, "Workflow complete");
703
- deps.uokObserver?.onPhaseResult("custom-engine", "milestone-complete", {
704
- unitType: iterData.unitType,
705
- unitId: iterData.unitId,
706
- });
707
- finishTurn("completed");
708
- break;
709
- }
710
- if (reconcileResult.outcome === "pause") {
711
- await deps.pauseAuto(ctx, pi);
712
- deps.uokObserver?.onPhaseResult("custom-engine", "pause", {
713
- unitType: iterData.unitType,
714
- unitId: iterData.unitId,
715
- });
716
- finishTurn("paused", "manual-attention");
717
- break;
718
- }
719
- if (reconcileResult.outcome === "stop") {
720
- await deps.stopAuto(ctx, pi, reconcileResult.reason ?? "Engine stopped");
721
- deps.uokObserver?.onPhaseResult("custom-engine", "stop", {
722
- unitType: iterData.unitType,
723
- unitId: iterData.unitId,
724
- reason: reconcileResult.reason,
725
- });
726
- finishTurn("stopped", "manual-attention", reconcileResult.reason);
727
- break;
728
- }
729
- deps.uokObserver?.onPhaseResult("custom-engine", "continue", {
585
+ const reconcileFlow = await handleCustomEngineReconcileOutcome({
586
+ outcome: reconcileOutcome,
730
587
  unitType: iterData.unitType,
731
588
  unitId: iterData.unitId,
589
+ deps: {
590
+ stopAuto: reason => deps.stopAuto(ctx, pi, reason),
591
+ pauseAuto: () => deps.pauseAuto(ctx, pi),
592
+ report: (action, details) => phaseReporter.report("custom-engine", action, details),
593
+ finishTurn,
594
+ },
732
595
  });
733
- finishTurn("completed");
596
+ if (reconcileFlow.action === "break") break;
734
597
  continue;
735
598
  }
736
599
 
737
600
  if (!sidecarItem) {
738
601
  // ── Phase 1: Pre-dispatch ─────────────────────────────────────────
739
602
  const preDispatchResult = await runPreDispatch(ic, loopState);
740
- deps.uokObserver?.onPhaseResult("pre-dispatch", preDispatchResult.action);
603
+ phaseReporter.report("pre-dispatch", preDispatchResult.action);
741
604
  if (preDispatchResult.action === "break") {
742
605
  finishTurn("stopped", "manual-attention", "pre-dispatch-break");
743
606
  break;
@@ -751,7 +614,7 @@ export async function autoLoop(
751
614
 
752
615
  // ── Phase 2: Guards ───────────────────────────────────────────────
753
616
  const guardsResult = await runGuards(ic, preData.mid);
754
- deps.uokObserver?.onPhaseResult("guard", guardsResult.action);
617
+ phaseReporter.report("guard", guardsResult.action);
755
618
  if (guardsResult.action === "break") {
756
619
  finishTurn("stopped", "manual-attention", "guard-break");
757
620
  break;
@@ -759,7 +622,7 @@ export async function autoLoop(
759
622
 
760
623
  // ── Phase 3: Dispatch ─────────────────────────────────────────────
761
624
  const dispatchResult = await runDispatch(ic, preData, loopState);
762
- deps.uokObserver?.onPhaseResult("dispatch", dispatchResult.action);
625
+ phaseReporter.report("dispatch", dispatchResult.action);
763
626
  if (dispatchResult.action === "break") {
764
627
  finishTurn("stopped", "manual-attention", "dispatch-break");
765
628
  break;
@@ -772,30 +635,19 @@ export async function autoLoop(
772
635
  observedUnitType = iterData.unitType;
773
636
  observedUnitId = iterData.unitId;
774
637
  } else {
775
- // ── Sidecar path: use values from the sidecar item directly ──
776
- const sidecarState = await deps.deriveState(s.canonicalProjectRoot);
777
- debugLog("autoLoop", {
778
- phase: "post-derive",
779
- site: "sidecar",
638
+ iterData = await buildSidecarIterationData({
639
+ sidecarItem,
780
640
  basePath: s.basePath,
781
641
  canonicalProjectRoot: s.canonicalProjectRoot,
782
- derivedPhase: sidecarState.phase,
783
- activeUnit: sidecarState.activeTask?.id ?? sidecarState.activeSlice?.id ?? sidecarState.activeMilestone?.id,
642
+ deriveState: deps.deriveState,
643
+ logPostDerive: details => debugLog("autoLoop", {
644
+ phase: "post-derive",
645
+ ...details,
646
+ }),
784
647
  });
785
- iterData = {
786
- unitType: sidecarItem.unitType,
787
- unitId: sidecarItem.unitId,
788
- prompt: sidecarItem.prompt,
789
- finalPrompt: sidecarItem.prompt,
790
- pauseAfterUatDispatch: false,
791
- state: sidecarState,
792
- mid: sidecarState.activeMilestone?.id,
793
- midTitle: sidecarState.activeMilestone?.title,
794
- isRetry: false, previousTier: undefined,
795
- };
796
648
  observedUnitType = iterData.unitType;
797
649
  observedUnitId = iterData.unitId;
798
- deps.uokObserver?.onPhaseResult("dispatch", "sidecar", {
650
+ phaseReporter.report("dispatch", "sidecar", {
799
651
  unitType: iterData.unitType,
800
652
  unitId: iterData.unitId,
801
653
  sidecarKind: sidecarItem.kind,
@@ -810,12 +662,25 @@ export async function autoLoop(
810
662
  // null when DB unavailable, no worker registered, or no active lease
811
663
  // — those degraded paths fall through to the existing single-worker
812
664
  // semantics with no ledger entry, preserving back-compat.
813
- const dispatchClaim = openDispatchClaim(s, flowId, turnId, iterData);
814
- if (dispatchClaim.kind === "skip") {
815
- finishTurn("skipped", "execution", dispatchClaim.reason);
665
+ const dispatchClaim = openDispatchClaim(s, flowId, turnId, iterData, {
666
+ getRecentDispatchesForUnit,
667
+ recordDispatchClaim,
668
+ markDispatchRunning,
669
+ logClaimRejected: logDispatchClaimRejected,
670
+ logClaimFailed: logDispatchClaimFailed,
671
+ });
672
+ const dispatchDecision = decideDispatchClaim(
673
+ dispatchClaim.kind === "opened"
674
+ ? { kind: "opened", dispatchId: dispatchClaim.dispatchId }
675
+ : dispatchClaim.kind === "skip"
676
+ ? { kind: "skip", reason: dispatchClaim.reason }
677
+ : { kind: "degraded" },
678
+ );
679
+ if (dispatchDecision.action === "skip") {
680
+ finishTurn("skipped", "execution", dispatchDecision.reason);
816
681
  continue;
817
682
  }
818
- dispatchId = dispatchClaim.kind === "opened" ? dispatchClaim.dispatchId : null;
683
+ dispatchId = dispatchDecision.dispatchId;
819
684
 
820
685
  let unitPhaseResult: Awaited<ReturnType<typeof runUnitPhaseViaContract>>;
821
686
  try {
@@ -825,40 +690,35 @@ export async function autoLoop(
825
690
  iterData,
826
691
  loopState,
827
692
  sidecarItem,
693
+ unitDispatchDeps,
828
694
  );
829
695
  } catch (err) {
830
696
  if (err instanceof ModelPolicyDispatchBlockedError) {
831
697
  throw err;
832
698
  }
833
- if (dispatchId !== null) {
834
- try {
835
- markDispatchFailed(dispatchId, {
836
- errorSummary: `exception:${err instanceof Error ? err.message : String(err)}`,
837
- });
838
- dispatchSettled = true;
839
- } catch (ledgerErr) {
840
- debugLog("autoLoop", { phase: "dispatch-ledger-write-failed", error: ledgerErr instanceof Error ? ledgerErr.message : String(ledgerErr) });
841
- }
842
- }
699
+ dispatchSettled = settleDispatchFailed(
700
+ dispatchId,
701
+ formatDispatchExceptionSummary({ error: err }),
702
+ {
703
+ markFailed: markDispatchFailed,
704
+ logWriteFailure: logDispatchLedgerWriteFailure,
705
+ },
706
+ ) || dispatchSettled;
843
707
  throw err;
844
708
  }
845
709
  if (unitPhaseResult.action === "next") {
846
- const requestTimestamp = unitPhaseResult.data.requestDispatchedAt ?? unitPhaseResult.data.unitStartedAt;
847
- if (typeof requestTimestamp === "number") s.lastRequestTimestamp = requestTimestamp;
710
+ const requestTimestamp = resolveUnitRequestTimestamp(unitPhaseResult.data);
711
+ if (requestTimestamp !== undefined) s.lastRequestTimestamp = requestTimestamp;
848
712
  }
849
- deps.uokObserver?.onPhaseResult("unit", unitPhaseResult.action, {
713
+ phaseReporter.report("unit", unitPhaseResult.action, {
850
714
  unitType: iterData.unitType,
851
715
  unitId: iterData.unitId,
852
716
  });
853
717
  if (unitPhaseResult.action === "break") {
854
- if (dispatchId !== null) {
855
- try {
856
- markDispatchFailed(dispatchId, { errorSummary: "unit-break" });
857
- dispatchSettled = true;
858
- } catch (err) {
859
- debugLog("autoLoop", { phase: "dispatch-ledger-write-failed", error: err instanceof Error ? err.message : String(err) });
860
- }
861
- }
718
+ dispatchSettled = settleDispatchFailed(dispatchId, "unit-break", {
719
+ markFailed: markDispatchFailed,
720
+ logWriteFailure: logDispatchLedgerWriteFailure,
721
+ }) || dispatchSettled;
862
722
  finishTurn("stopped", "execution", "unit-break");
863
723
  break;
864
724
  }
@@ -869,84 +729,68 @@ export async function autoLoop(
869
729
  try {
870
730
  finalizeResult = await runFinalize(ic, iterData, loopState, sidecarItem);
871
731
  } catch (err) {
872
- if (dispatchId !== null) {
873
- try {
874
- markDispatchFailed(dispatchId, {
875
- errorSummary: `exception:${err instanceof Error ? err.message : String(err)}`,
876
- });
877
- dispatchSettled = true;
878
- } catch (ledgerErr) {
879
- debugLog("autoLoop", { phase: "dispatch-ledger-write-failed", error: ledgerErr instanceof Error ? ledgerErr.message : String(ledgerErr) });
880
- }
881
- }
732
+ dispatchSettled = settleDispatchFailed(
733
+ dispatchId,
734
+ formatDispatchExceptionSummary({ error: err }),
735
+ {
736
+ markFailed: markDispatchFailed,
737
+ logWriteFailure: logDispatchLedgerWriteFailure,
738
+ },
739
+ ) || dispatchSettled;
882
740
  throw err;
883
741
  }
884
- deps.uokObserver?.onPhaseResult("finalize", finalizeResult.action, {
742
+ phaseReporter.report("finalize", finalizeResult.action, {
885
743
  unitType: iterData.unitType,
886
744
  unitId: iterData.unitId,
887
745
  });
888
- if (finalizeResult.action === "break") {
889
- const finalizeFailureClass = finalizeResult.reason === "git-closeout-failure"
890
- ? "git"
891
- : "closeout";
892
- if (dispatchId !== null) {
893
- try {
894
- markDispatchFailed(dispatchId, { errorSummary: `finalize-break:${finalizeResult.reason ?? "unknown"}` });
895
- dispatchSettled = true;
896
- } catch (err) {
897
- debugLog("autoLoop", { phase: "dispatch-ledger-write-failed", error: err instanceof Error ? err.message : String(err) });
898
- }
899
- }
900
- finishTurn("stopped", finalizeFailureClass, "finalize-break");
746
+ const finalizeDecision = decideFinalizeResult(
747
+ finalizeResult.action === "break"
748
+ ? { action: "break", reason: finalizeResult.reason }
749
+ : finalizeResult.action === "continue"
750
+ ? { action: "continue" }
751
+ : { action: "next" },
752
+ );
753
+ if (finalizeDecision.action === "stop") {
754
+ dispatchSettled = settleDispatchFailed(dispatchId, finalizeDecision.ledgerErrorSummary, {
755
+ markFailed: markDispatchFailed,
756
+ logWriteFailure: logDispatchLedgerWriteFailure,
757
+ }) || dispatchSettled;
758
+ finishTurn("stopped", finalizeDecision.failureClass, finalizeDecision.turnError);
901
759
  break;
902
760
  }
903
- if (finalizeResult.action === "continue") {
904
- if (dispatchId !== null) {
905
- try {
906
- markDispatchFailed(dispatchId, { errorSummary: "finalize-retry" });
907
- dispatchSettled = true;
908
- } catch (err) {
909
- debugLog("autoLoop", { phase: "dispatch-ledger-write-failed", error: err instanceof Error ? err.message : String(err) });
910
- }
911
- }
761
+ if (finalizeDecision.action === "retry") {
762
+ dispatchSettled = settleDispatchFailed(dispatchId, finalizeDecision.ledgerErrorSummary, {
763
+ markFailed: markDispatchFailed,
764
+ logWriteFailure: logDispatchLedgerWriteFailure,
765
+ }) || dispatchSettled;
912
766
  finishTurn("retry");
913
767
  continue;
914
768
  }
915
769
 
916
- if (dispatchId !== null) {
917
- try {
918
- markDispatchCompleted(dispatchId);
919
- dispatchSettled = true;
920
- } catch (err) {
921
- debugLog("autoLoop", { phase: "dispatch-ledger-write-failed", error: err instanceof Error ? err.message : String(err) });
922
- }
923
- }
924
- consecutiveErrors = 0; // Iteration completed successfully
925
- consecutiveCooldowns = 0;
926
- recentErrorMessages.length = 0;
927
- deps.emitJournalEvent({ ts: new Date().toISOString(), flowId, seq: nextSeq(), eventType: "iteration-end", data: { iteration } });
928
- saveStuckState(s, loopState); // persist across session restarts (#4382)
929
- debugLog("autoLoop", { phase: "iteration-complete", iteration });
770
+ dispatchSettled = settleDispatchCompleted(dispatchId, {
771
+ markCompleted: markDispatchCompleted,
772
+ logWriteFailure: logDispatchLedgerWriteFailure,
773
+ }) || dispatchSettled;
774
+ completeIteration();
930
775
  finishTurn("completed");
931
776
  } catch (loopErr) {
932
777
  // ── Blanket catch: absorb unexpected exceptions, apply graduated recovery ──
933
778
  const msg = loopErr instanceof Error ? loopErr.message : String(loopErr);
934
779
  if (dispatchId !== null && !dispatchSettled && !(loopErr instanceof ModelPolicyDispatchBlockedError)) {
935
- try {
936
- markDispatchFailed(dispatchId, { errorSummary: `unhandled-error:${msg.slice(0, 200)}` });
937
- dispatchSettled = true;
938
- } catch (err) {
939
- debugLog("autoLoop", {
940
- phase: "dispatch-ledger-write-failed",
941
- error: err instanceof Error ? err.message : String(err),
942
- });
943
- }
780
+ dispatchSettled = settleDispatchFailed(
781
+ dispatchId,
782
+ formatUnhandledDispatchErrorSummary({ error: loopErr }),
783
+ {
784
+ markFailed: markDispatchFailed,
785
+ logWriteFailure: logDispatchLedgerWriteFailure,
786
+ },
787
+ ) || dispatchSettled;
944
788
  }
945
789
 
946
790
  // Always emit iteration-end on error so the journal records iteration
947
791
  // completion even on failure (#2344). Without this, errors in
948
792
  // runFinalize leave the journal incomplete, making diagnosis harder.
949
- deps.emitJournalEvent({ ts: new Date().toISOString(), flowId, seq: nextSeq(), eventType: "iteration-end", data: { iteration, error: msg } });
793
+ journalReporter.emit("iteration-end", { iteration, error: msg });
950
794
 
951
795
  // ── Pre-send model-policy block: not a retryable error (#4959 / #4850) ──
952
796
  // The model-policy gate runs before the prompt is sent. When every
@@ -957,6 +801,12 @@ export async function autoLoop(
957
801
  // instead, with the per-model deny reasons surfaced from the typed
958
802
  // error.
959
803
  if (loopErr instanceof ModelPolicyDispatchBlockedError) {
804
+ const policyDecision = decideModelPolicyBlocked({
805
+ unitType: loopErr.unitType,
806
+ unitId: loopErr.unitId,
807
+ errorMessage: msg,
808
+ reasons: loopErr.reasons,
809
+ });
960
810
  debugLog("autoLoop", {
961
811
  phase: "model-policy-blocked",
962
812
  iteration,
@@ -964,23 +814,8 @@ export async function autoLoop(
964
814
  unitId: loopErr.unitId,
965
815
  reasons: loopErr.reasons,
966
816
  });
967
- ctx.ui.notify(
968
- `Auto-mode paused: model-policy denied dispatch for ${loopErr.unitType}/${loopErr.unitId}. ${msg}`,
969
- "error",
970
- );
971
- deps.emitJournalEvent({
972
- ts: new Date().toISOString(),
973
- flowId,
974
- seq: nextSeq(),
975
- eventType: "unit-end",
976
- data: {
977
- unitType: loopErr.unitType,
978
- unitId: loopErr.unitId,
979
- status: "blocked",
980
- reason: "model-policy-dispatch-blocked",
981
- reasons: loopErr.reasons,
982
- },
983
- });
817
+ ctx.ui.notify(policyDecision.notifyMessage, "error");
818
+ journalReporter.emit("unit-end", policyDecision.journalData);
984
819
  // Carry the blocked unit identity into the turn-result observer:
985
820
  // the throw originated inside dispatch, so observedUnitType/Id were
986
821
  // not assigned by the success path at lines 453/631/647 — but the
@@ -988,7 +823,7 @@ export async function autoLoop(
988
823
  observedUnitType = loopErr.unitType;
989
824
  observedUnitId = loopErr.unitId;
990
825
  await deps.pauseAuto(ctx, pi);
991
- finishTurn("paused", "manual-attention", msg);
826
+ finishTurn(policyDecision.turnStatus, policyDecision.failureClass, msg);
992
827
  // Do NOT increment consecutiveErrors — the failure is configuration,
993
828
  // not a transient runtime fault.
994
829
  break;
@@ -999,22 +834,19 @@ export async function autoLoop(
999
834
  // LLM budget on guaranteed failures.
1000
835
  const infraCode = isInfrastructureError(loopErr);
1001
836
  if (infraCode) {
837
+ const infraDecision = decideInfrastructureError({
838
+ code: infraCode,
839
+ errorMessage: msg,
840
+ });
1002
841
  debugLog("autoLoop", {
1003
842
  phase: "infrastructure-error",
1004
843
  iteration,
1005
844
  code: infraCode,
1006
845
  error: msg,
1007
846
  });
1008
- ctx.ui.notify(
1009
- `Auto-mode stopped: infrastructure error ${infraCode} — ${msg}`,
1010
- "error",
1011
- );
1012
- await deps.stopAuto(
1013
- ctx,
1014
- pi,
1015
- `Infrastructure error (${infraCode}): not recoverable by retry`,
1016
- );
1017
- finishTurn("failed", "execution", msg);
847
+ ctx.ui.notify(infraDecision.notifyMessage, "error");
848
+ await deps.stopAuto(ctx, pi, infraDecision.stopMessage);
849
+ finishTurn(infraDecision.turnStatus, infraDecision.failureClass, msg);
1018
850
  break;
1019
851
  }
1020
852
 
@@ -1027,6 +859,12 @@ export async function autoLoop(
1027
859
  if (isTransientCooldownError(loopErr)) {
1028
860
  consecutiveCooldowns++;
1029
861
  const retryAfterMs = getCooldownRetryAfterMs(loopErr);
862
+ const cooldownDecision = decideCooldownRecovery({
863
+ consecutiveCooldowns,
864
+ maxCooldownRetries: MAX_COOLDOWN_RETRIES,
865
+ retryAfterMs,
866
+ fallbackWaitMs: COOLDOWN_FALLBACK_WAIT_MS,
867
+ });
1030
868
  debugLog("autoLoop", {
1031
869
  phase: "cooldown-wait",
1032
870
  iteration,
@@ -1035,27 +873,15 @@ export async function autoLoop(
1035
873
  error: msg,
1036
874
  });
1037
875
 
1038
- if (consecutiveCooldowns > MAX_COOLDOWN_RETRIES) {
1039
- ctx.ui.notify(
1040
- `Auto-mode stopped: ${consecutiveCooldowns} consecutive credential cooldowns — rate limit or quota may be persistently exhausted.`,
1041
- "error",
1042
- );
1043
- await deps.stopAuto(
1044
- ctx,
1045
- pi,
1046
- `${consecutiveCooldowns} consecutive credential cooldowns exceeded retry budget`,
1047
- );
876
+ if (cooldownDecision.action === "stop") {
877
+ ctx.ui.notify(cooldownDecision.notifyMessage, "error");
878
+ finishTurn("stopped", "timeout", msg);
879
+ await deps.stopAuto(ctx, pi, cooldownDecision.stopMessage);
1048
880
  break;
1049
881
  }
1050
882
 
1051
- const waitMs = (retryAfterMs !== undefined && retryAfterMs > 0 && retryAfterMs <= 60_000)
1052
- ? retryAfterMs + 500 // Use structured hint + small buffer
1053
- : COOLDOWN_FALLBACK_WAIT_MS;
1054
- ctx.ui.notify(
1055
- `Credentials in cooldown (${consecutiveCooldowns}/${MAX_COOLDOWN_RETRIES}) — waiting ${Math.round(waitMs / 1000)}s before retrying.`,
1056
- "warning",
1057
- );
1058
- await new Promise(resolve => setTimeout(resolve, waitMs));
883
+ ctx.ui.notify(cooldownDecision.notifyMessage, "warning");
884
+ await new Promise(resolve => setTimeout(resolve, cooldownDecision.waitMs));
1059
885
  finishTurn("retry", "timeout", msg);
1060
886
  continue; // Retry iteration without incrementing consecutiveErrors
1061
887
  }
@@ -1069,34 +895,24 @@ export async function autoLoop(
1069
895
  error: msg,
1070
896
  });
1071
897
 
1072
- if (consecutiveErrors >= 3) {
1073
- // 3+ consecutive: hard stop — something is fundamentally broken
1074
- const errorHistory = recentErrorMessages
1075
- .map((m, i) => ` ${i + 1}. ${m}`)
1076
- .join("\n");
1077
- ctx.ui.notify(
1078
- `Auto-mode stopped: ${consecutiveErrors} consecutive iteration failures:\n${errorHistory}`,
1079
- "error",
1080
- );
1081
- await deps.stopAuto(
1082
- ctx,
1083
- pi,
1084
- `${consecutiveErrors} consecutive iteration failures`,
1085
- );
1086
- finishTurn("failed", "execution", msg);
898
+ const errorDecision = decideIterationErrorRecovery({
899
+ consecutiveErrors,
900
+ recentErrorMessages,
901
+ currentErrorMessage: msg,
902
+ });
903
+ if (errorDecision.action === "stop") {
904
+ ctx.ui.notify(errorDecision.notifyMessage, "error");
905
+ await deps.stopAuto(ctx, pi, errorDecision.stopMessage);
906
+ finishTurn(errorDecision.turnStatus, "execution", msg);
1087
907
  break;
1088
- } else if (consecutiveErrors === 2) {
1089
- // 2nd consecutive: try invalidating caches + re-deriving state
1090
- ctx.ui.notify(
1091
- `Iteration error (attempt ${consecutiveErrors}): ${msg}. Invalidating caches and retrying.`,
1092
- "warning",
1093
- );
908
+ }
909
+ if (errorDecision.action === "invalidate-and-retry") {
910
+ ctx.ui.notify(errorDecision.notifyMessage, "warning");
1094
911
  deps.invalidateAllCaches();
1095
912
  } else {
1096
- // 1st error: log and retry — transient failures happen
1097
- ctx.ui.notify(`Iteration error: ${msg}. Retrying.`, "warning");
913
+ ctx.ui.notify(errorDecision.notifyMessage, "warning");
1098
914
  }
1099
- finishTurn("retry", "execution", msg);
915
+ finishTurn(errorDecision.turnStatus, "execution", msg);
1100
916
  }
1101
917
  }
1102
918