agentic-orchestrator 0.1.27 → 0.2.0

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 (837) hide show
  1. package/.claude/settings.local.json +46 -1
  2. package/.cortexrc +28 -0
  3. package/.github/agents/copilot-instructions.md +29 -0
  4. package/.github/copilot-instructions.md +93 -0
  5. package/.vscode/settings.json +13 -0
  6. package/.vscode/tms.code-snippets +223 -0
  7. package/AGENTS.md +72 -1
  8. package/Agentic-Orchestrator.iml +12 -11
  9. package/CLAUDE.md +72 -1
  10. package/CONSTITUTION.md +504 -0
  11. package/FUTURE-ENHANCEMENTS.md +85 -0
  12. package/NEXT-TASKS.md +25 -0
  13. package/PROMPTS.md +161 -0
  14. package/README.md +126 -29
  15. package/agentic/orchestrator/agents.yaml +4 -3
  16. package/agentic/orchestrator/defaults/policy.defaults.yaml +39 -3
  17. package/agentic/orchestrator/gates.yaml +15 -3
  18. package/agentic/orchestrator/policy.yaml +47 -3
  19. package/agentic/orchestrator/prompts/builder.system.md +69 -20
  20. package/agentic/orchestrator/prompts/planner-intake.system.md +149 -0
  21. package/agentic/orchestrator/prompts/planner.system.md +113 -40
  22. package/agentic/orchestrator/prompts/qa.system.md +73 -18
  23. package/agentic/orchestrator/prompts/reconciler.system.md +119 -0
  24. package/agentic/orchestrator/schemas/agents.schema.json +89 -1
  25. package/agentic/orchestrator/schemas/execution-control.schema.json +242 -0
  26. package/agentic/orchestrator/schemas/index.schema.json +234 -0
  27. package/agentic/orchestrator/schemas/intake.review.schema.json +82 -0
  28. package/agentic/orchestrator/schemas/organizer-ordering-artifact.schema.json +75 -0
  29. package/agentic/orchestrator/schemas/plan.schema.json +44 -0
  30. package/agentic/orchestrator/schemas/policy.schema.json +238 -9
  31. package/agentic/orchestrator/schemas/policy.user.schema.json +129 -1
  32. package/agentic/orchestrator/schemas/spec.manifest.bootstrap.schema.json +101 -0
  33. package/agentic/orchestrator/schemas/spec.manifest.verified.schema.json +80 -0
  34. package/agentic/orchestrator/schemas/state.schema.json +298 -3
  35. package/agentic/orchestrator/tools/catalog.json +145 -15
  36. package/agentic/orchestrator/tools/schemas/input/doctor.run.input.schema.json +18 -0
  37. package/agentic/orchestrator/tools/schemas/input/evidence.latest.input.schema.json +4 -0
  38. package/agentic/orchestrator/tools/schemas/input/evidence.verify_chain.input.schema.json +13 -0
  39. package/agentic/orchestrator/tools/schemas/input/feature.intake_submit.input.schema.json +11 -0
  40. package/agentic/orchestrator/tools/schemas/input/feature.question_answer.input.schema.json +15 -0
  41. package/agentic/orchestrator/tools/schemas/input/feature.question_create.input.schema.json +21 -0
  42. package/agentic/orchestrator/tools/schemas/input/feature.question_list.input.schema.json +13 -0
  43. package/agentic/orchestrator/tools/schemas/input/feature.ready_to_merge.input.schema.json +5 -0
  44. package/agentic/orchestrator/tools/schemas/input/feature.send_message.input.schema.json +1 -1
  45. package/agentic/orchestrator/tools/schemas/input/replay.timeline_get.input.schema.json +32 -0
  46. package/agentic/orchestrator/tools/schemas/input/repo.conflict_abort.input.schema.json +16 -0
  47. package/agentic/orchestrator/tools/schemas/input/repo.conflict_files.input.schema.json +16 -0
  48. package/agentic/orchestrator/tools/schemas/input/repo.reconcile_mainline.input.schema.json +37 -0
  49. package/agentic/orchestrator/tools/schemas/input/repo.resolve_conflict.input.schema.json +40 -0
  50. package/agentic/orchestrator/tools/schemas/input/runtime.execution_request_list.input.schema.json +7 -0
  51. package/agentic/orchestrator/tools/schemas/input/runtime.execution_request_submit.input.schema.json +25 -0
  52. package/agentic/orchestrator/tools/schemas/output/doctor.run.output.schema.json +34 -0
  53. package/agentic/orchestrator/tools/schemas/output/evidence.verify_chain.output.schema.json +23 -0
  54. package/agentic/orchestrator/tools/schemas/output/feature.get_context.output.schema.json +62 -2
  55. package/agentic/orchestrator/tools/schemas/output/feature.intake_submit.output.schema.json +24 -0
  56. package/agentic/orchestrator/tools/schemas/output/feature.question_answer.output.schema.json +21 -0
  57. package/agentic/orchestrator/tools/schemas/output/feature.question_create.output.schema.json +12 -0
  58. package/agentic/orchestrator/tools/schemas/output/feature.question_list.output.schema.json +14 -0
  59. package/agentic/orchestrator/tools/schemas/output/feature.ready_to_merge.output.schema.json +31 -0
  60. package/agentic/orchestrator/tools/schemas/output/feature.send_message.output.schema.json +8 -18
  61. package/agentic/orchestrator/tools/schemas/output/replay.timeline_get.output.schema.json +64 -0
  62. package/agentic/orchestrator/tools/schemas/output/repo.conflict_abort.output.schema.json +16 -0
  63. package/agentic/orchestrator/tools/schemas/output/repo.conflict_files.output.schema.json +22 -0
  64. package/agentic/orchestrator/tools/schemas/output/repo.reconcile_mainline.output.schema.json +61 -0
  65. package/agentic/orchestrator/tools/schemas/output/repo.resolve_conflict.output.schema.json +19 -0
  66. package/agentic/orchestrator/tools/schemas/output/report.dashboard.output.schema.json +26 -0
  67. package/agentic/orchestrator/tools/schemas/output/runtime.execution_request_list.output.schema.json +17 -0
  68. package/agentic/orchestrator/tools/schemas/output/runtime.execution_request_submit.output.schema.json +24 -0
  69. package/agentic/orchestrator/tools.md +13 -0
  70. package/apps/control-plane/scripts/validate-mcp-contracts.ts +1 -1
  71. package/apps/control-plane/src/application/kernel-tool-wiring.ts +140 -2
  72. package/apps/control-plane/src/application/services/activity-monitor-service.ts +44 -1
  73. package/apps/control-plane/src/application/services/bootstrap-manifest-generator-service.ts +251 -0
  74. package/apps/control-plane/src/application/services/checkpoint-service.ts +87 -27
  75. package/apps/control-plane/src/application/services/collision-override-service.ts +906 -0
  76. package/apps/control-plane/src/application/services/collision-queue-service.ts +129 -38
  77. package/apps/control-plane/src/application/services/cost-tracking-service.ts +94 -0
  78. package/apps/control-plane/src/application/services/execution-control-service.ts +599 -0
  79. package/apps/control-plane/src/application/services/feature-deletion-service.ts +37 -1
  80. package/apps/control-plane/src/application/services/feature-lifecycle-service.ts +182 -4
  81. package/apps/control-plane/src/application/services/feature-send-message-service.ts +17 -8
  82. package/apps/control-plane/src/application/services/feature-state-service.ts +191 -6
  83. package/apps/control-plane/src/application/services/gate-service.ts +121 -2
  84. package/apps/control-plane/src/application/services/git-reconciliation-service.ts +1591 -0
  85. package/apps/control-plane/src/application/services/intake-service.ts +1468 -0
  86. package/apps/control-plane/src/application/services/merge-service.ts +308 -17
  87. package/apps/control-plane/src/application/services/notifier-service.ts +3 -1
  88. package/apps/control-plane/src/application/services/performance-analytics-service.ts +75 -0
  89. package/apps/control-plane/src/application/services/plan-service.ts +336 -20
  90. package/apps/control-plane/src/application/services/question-service.ts +693 -0
  91. package/apps/control-plane/src/application/services/reactions-service.ts +73 -17
  92. package/apps/control-plane/src/application/services/replay-timeline-service.ts +295 -0
  93. package/apps/control-plane/src/application/services/reporting-service.ts +194 -10
  94. package/apps/control-plane/src/application/services/run-lease-service.ts +121 -5
  95. package/apps/control-plane/src/application/services/worktree-watchdog-service.ts +95 -8
  96. package/apps/control-plane/src/application/tools/tool-metadata.ts +7 -0
  97. package/apps/control-plane/src/application/usage-types.ts +138 -0
  98. package/apps/control-plane/src/cli/add-command-handler.ts +162 -0
  99. package/apps/control-plane/src/cli/answer-command-handler.ts +113 -0
  100. package/apps/control-plane/src/cli/attach-command-handler.ts +12 -3
  101. package/apps/control-plane/src/cli/cli-argument-parser.ts +133 -11
  102. package/apps/control-plane/src/cli/collision-command-handler.ts +113 -0
  103. package/apps/control-plane/src/cli/command-catalog.ts +479 -0
  104. package/apps/control-plane/src/cli/complete-command-handler.ts +23 -0
  105. package/apps/control-plane/src/cli/completion-command-handler.ts +25 -0
  106. package/apps/control-plane/src/cli/completion-resolver.ts +319 -0
  107. package/apps/control-plane/src/cli/completion-shell-renderer.ts +58 -0
  108. package/apps/control-plane/src/cli/dashboard-command-handler.ts +110 -1
  109. package/apps/control-plane/src/cli/dashboard-runtime-runner.ts +1036 -0
  110. package/apps/control-plane/src/cli/dashboard-runtime.ts +31 -0
  111. package/apps/control-plane/src/cli/help-command-handler.ts +17 -185
  112. package/apps/control-plane/src/cli/init-command-handler.ts +51 -6
  113. package/apps/control-plane/src/cli/merge-command-handler.ts +200 -0
  114. package/apps/control-plane/src/cli/questions-command-handler.ts +70 -0
  115. package/apps/control-plane/src/cli/replay-command-handler.ts +98 -0
  116. package/apps/control-plane/src/cli/resume-command-handler.ts +252 -18
  117. package/apps/control-plane/src/cli/retry-command-handler.ts +229 -17
  118. package/apps/control-plane/src/cli/retry-resume-decision.ts +75 -0
  119. package/apps/control-plane/src/cli/rollback-command-handler.ts +4 -2
  120. package/apps/control-plane/src/cli/run-command-handler.ts +35 -1
  121. package/apps/control-plane/src/cli/spec-ingestion-service.ts +45 -55
  122. package/apps/control-plane/src/cli/spec-preparation.ts +114 -0
  123. package/apps/control-plane/src/cli/spec-utils.ts +90 -11
  124. package/apps/control-plane/src/cli/status-command-handler.ts +122 -0
  125. package/apps/control-plane/src/cli/types.ts +41 -3
  126. package/apps/control-plane/src/core/collisions.ts +150 -31
  127. package/apps/control-plane/src/core/constants.ts +18 -1
  128. package/apps/control-plane/src/core/error-codes.ts +39 -0
  129. package/apps/control-plane/src/core/execution-control.ts +56 -0
  130. package/apps/control-plane/src/core/feature-resume-phase.ts +118 -0
  131. package/apps/control-plane/src/core/gate-freshness.ts +359 -0
  132. package/apps/control-plane/src/core/gate-log-extractor.ts +97 -0
  133. package/apps/control-plane/src/core/gates.ts +90 -1
  134. package/apps/control-plane/src/core/intake-artifacts.ts +295 -0
  135. package/apps/control-plane/src/core/kernel-types.ts +11 -0
  136. package/apps/control-plane/src/core/kernel.ts +604 -16
  137. package/apps/control-plane/src/core/mainline-conflict.ts +22 -0
  138. package/apps/control-plane/src/core/merge-repair.ts +149 -0
  139. package/apps/control-plane/src/core/path-layout.ts +46 -2
  140. package/apps/control-plane/src/core/path-rules.ts +11 -3
  141. package/apps/control-plane/src/core/plan-submit-recovery.ts +130 -0
  142. package/apps/control-plane/src/core/questions.ts +49 -0
  143. package/apps/control-plane/src/core/runtime-sessions.ts +4 -0
  144. package/apps/control-plane/src/core/schemas.ts +40 -1
  145. package/apps/control-plane/src/core/tool-caller.ts +25 -1
  146. package/apps/control-plane/src/core/utils/index-normalizer.ts +25 -4
  147. package/apps/control-plane/src/core/worktree-diff.ts +66 -0
  148. package/apps/control-plane/src/index.ts +29 -1
  149. package/apps/control-plane/src/interfaces/cli/bootstrap.ts +300 -6
  150. package/apps/control-plane/src/mcp/kernel-tool-executor.ts +17 -0
  151. package/apps/control-plane/src/mcp/tool-runtime.ts +63 -4
  152. package/apps/control-plane/src/providers/api-worker-provider.ts +62 -15
  153. package/apps/control-plane/src/providers/cli-worker-provider.ts +1037 -61
  154. package/apps/control-plane/src/providers/output-parsers/generic-output-parser.ts +99 -1
  155. package/apps/control-plane/src/providers/output-parsers/types.ts +2 -0
  156. package/apps/control-plane/src/providers/provider-defaults.ts +116 -7
  157. package/apps/control-plane/src/providers/providers.ts +225 -21
  158. package/apps/control-plane/src/providers/worker-provider-factory.ts +26 -2
  159. package/apps/control-plane/src/supervisor/artifact-stager.ts +52 -0
  160. package/apps/control-plane/src/supervisor/build-wave-executor.ts +477 -166
  161. package/apps/control-plane/src/supervisor/execution-enrollment-service.ts +408 -0
  162. package/apps/control-plane/src/supervisor/organizer-enrollment-scheduler.ts +117 -0
  163. package/apps/control-plane/src/supervisor/organizer-sidecar-service.ts +394 -0
  164. package/apps/control-plane/src/supervisor/plan-conformance-scorer.ts +2 -5
  165. package/apps/control-plane/src/supervisor/planner-phase.ts +85 -0
  166. package/apps/control-plane/src/supervisor/planning-wave-executor.ts +993 -64
  167. package/apps/control-plane/src/supervisor/prompt-bundle-loader.ts +20 -1
  168. package/apps/control-plane/src/supervisor/qa-wave-executor.ts +384 -177
  169. package/apps/control-plane/src/supervisor/run-coordinator.ts +801 -43
  170. package/apps/control-plane/src/supervisor/runtime.ts +485 -9
  171. package/apps/control-plane/src/supervisor/session-orchestrator.ts +220 -1
  172. package/apps/control-plane/src/supervisor/types.ts +152 -1
  173. package/apps/control-plane/src/supervisor/worker-decision-loop.ts +1030 -92
  174. package/apps/control-plane/test/activity-monitor.spec.ts +76 -0
  175. package/apps/control-plane/test/add-command-handler.spec.ts +189 -0
  176. package/apps/control-plane/test/application/services/feature-state-service.spec.ts +208 -0
  177. package/apps/control-plane/test/artifact-stager.spec.ts +93 -0
  178. package/apps/control-plane/test/batch-operations.spec.ts +58 -0
  179. package/apps/control-plane/test/bootstrap-edge-cases.spec.ts +50 -2
  180. package/apps/control-plane/test/bootstrap-manifest-generator-service.spec.ts +99 -0
  181. package/apps/control-plane/test/bootstrap.spec.ts +177 -4
  182. package/apps/control-plane/test/checkpoint-service.spec.ts +977 -29
  183. package/apps/control-plane/test/cli-argument-parser.spec.ts +119 -0
  184. package/apps/control-plane/test/cli-helpers.spec.ts +1202 -12
  185. package/apps/control-plane/test/cli.unit.spec.ts +797 -16
  186. package/apps/control-plane/test/collision-command-handler.spec.ts +182 -0
  187. package/apps/control-plane/test/collision-override-service.spec.ts +878 -0
  188. package/apps/control-plane/test/collision-queue.spec.ts +430 -2
  189. package/apps/control-plane/test/collisions.spec.ts +209 -1
  190. package/apps/control-plane/test/core-utils.spec.ts +61 -0
  191. package/apps/control-plane/test/cost-tracking.spec.ts +224 -0
  192. package/apps/control-plane/test/dashboard-api.integration.spec.ts +185 -5
  193. package/apps/control-plane/test/dashboard-client.spec.ts +948 -0
  194. package/apps/control-plane/test/dashboard-command.spec.ts +138 -6
  195. package/apps/control-plane/test/dashboard-runtime-runner.spec.ts +1550 -0
  196. package/apps/control-plane/test/dashboard-runtime.spec.ts +138 -0
  197. package/apps/control-plane/test/dashboard-ui-utils.spec.ts +56 -12
  198. package/apps/control-plane/test/dependency-scheduler.spec.ts +7 -1
  199. package/apps/control-plane/test/env-file.spec.ts +76 -0
  200. package/apps/control-plane/test/execution-control-service.spec.ts +535 -0
  201. package/apps/control-plane/test/execution-enrollment-service.spec.ts +648 -0
  202. package/apps/control-plane/test/feature-lifecycle.spec.ts +126 -0
  203. package/apps/control-plane/test/feature-resume-phase.spec.ts +164 -0
  204. package/apps/control-plane/test/feature-send-message-service.spec.ts +161 -0
  205. package/apps/control-plane/test/feature-state-service.spec.ts +295 -0
  206. package/apps/control-plane/test/fs.spec.ts +80 -0
  207. package/apps/control-plane/test/gate-freshness.spec.ts +590 -0
  208. package/apps/control-plane/test/gate-log-extractor.spec.ts +170 -0
  209. package/apps/control-plane/test/gates.spec.ts +108 -0
  210. package/apps/control-plane/test/git-reconciliation-service.spec.ts +2307 -0
  211. package/apps/control-plane/test/helpers.ts +65 -0
  212. package/apps/control-plane/test/incremental-gates.spec.ts +271 -0
  213. package/apps/control-plane/test/index-normalizer.spec.ts +98 -0
  214. package/apps/control-plane/test/init-wizard.spec.ts +17 -0
  215. package/apps/control-plane/test/intake-artifacts.spec.ts +203 -0
  216. package/apps/control-plane/test/intake-service.spec.ts +3176 -0
  217. package/apps/control-plane/test/kernel-collision-replay.spec.ts +3 -2
  218. package/apps/control-plane/test/kernel-tool-executor.spec.ts +77 -0
  219. package/apps/control-plane/test/kernel-tool-wiring.spec.ts +279 -0
  220. package/apps/control-plane/test/kernel.branches.spec.ts +15 -2
  221. package/apps/control-plane/test/kernel.coverage.spec.ts +7 -3
  222. package/apps/control-plane/test/kernel.coverage2.spec.ts +731 -2
  223. package/apps/control-plane/test/kernel.spec.ts +464 -2
  224. package/apps/control-plane/test/mainline-conflict.spec.ts +66 -0
  225. package/apps/control-plane/test/mcp-helpers.spec.ts +79 -0
  226. package/apps/control-plane/test/mcp.spec.ts +177 -13
  227. package/apps/control-plane/test/merge-command-handler.spec.ts +531 -0
  228. package/apps/control-plane/test/merge-service.spec.ts +570 -4
  229. package/apps/control-plane/test/notifier-service.spec.ts +26 -0
  230. package/apps/control-plane/test/organizer-enrollment-scheduler.spec.ts +340 -0
  231. package/apps/control-plane/test/organizer-ordering-artifact.spec.ts +95 -0
  232. package/apps/control-plane/test/organizer-sidecar-service.spec.ts +468 -0
  233. package/apps/control-plane/test/output-loop-detector.spec.ts +6 -0
  234. package/apps/control-plane/test/path-layout.spec.ts +70 -0
  235. package/apps/control-plane/test/path-normalizers.spec.ts +41 -0
  236. package/apps/control-plane/test/performance-analytics.spec.ts +124 -0
  237. package/apps/control-plane/test/plan-conformance-scorer.spec.ts +53 -0
  238. package/apps/control-plane/test/plan-service.spec.ts +686 -4
  239. package/apps/control-plane/test/planning-wave-executor.spec.ts +3272 -86
  240. package/apps/control-plane/test/policy-loader-service.spec.ts +5 -0
  241. package/apps/control-plane/test/prompt-overlay.spec.ts +65 -0
  242. package/apps/control-plane/test/provider-command-runner-epipe.spec.ts +64 -0
  243. package/apps/control-plane/test/providers/api-worker-provider.spec.ts +129 -0
  244. package/apps/control-plane/test/providers/cli-worker-provider.spec.ts +148 -0
  245. package/apps/control-plane/test/providers/usage-types.spec.ts +98 -0
  246. package/apps/control-plane/test/providers.spec.ts +293 -16
  247. package/apps/control-plane/test/question-command-handlers.spec.ts +156 -0
  248. package/apps/control-plane/test/question-service.spec.ts +1119 -0
  249. package/apps/control-plane/test/reactions.spec.ts +114 -0
  250. package/apps/control-plane/test/replay-command-handler.spec.ts +144 -0
  251. package/apps/control-plane/test/replay-timeline-service.spec.ts +459 -0
  252. package/apps/control-plane/test/response.spec.ts +31 -0
  253. package/apps/control-plane/test/resume-command.spec.ts +786 -9
  254. package/apps/control-plane/test/retry-resume-decision.spec.ts +133 -0
  255. package/apps/control-plane/test/rollback-command-handler.spec.ts +334 -0
  256. package/apps/control-plane/test/rollback-command.spec.ts +120 -0
  257. package/apps/control-plane/test/run-coordinator.spec.ts +3141 -364
  258. package/apps/control-plane/test/schemas/state.schema.spec.ts +71 -0
  259. package/apps/control-plane/test/service-retry-paths.spec.ts +112 -0
  260. package/apps/control-plane/test/services.spec.ts +472 -2
  261. package/apps/control-plane/test/session-management.spec.ts +346 -1
  262. package/apps/control-plane/test/spec-ingestion.spec.ts +102 -28
  263. package/apps/control-plane/test/spec-preparation.spec.ts +182 -0
  264. package/apps/control-plane/test/supervisor-collaborators.spec.ts +191 -3
  265. package/apps/control-plane/test/supervisor.calltool.spec.ts +198 -0
  266. package/apps/control-plane/test/supervisor.spec.ts +95 -16
  267. package/apps/control-plane/test/supervisor.unit.spec.ts +385 -18
  268. package/apps/control-plane/test/tool-runtime.spec.ts +122 -0
  269. package/apps/control-plane/test/worker-decision-loop.spec.ts +3479 -476
  270. package/apps/control-plane/test/worker-execution-policy.spec.ts +1416 -6
  271. package/apps/control-plane/test/worker-provider-adapters.spec.ts +1894 -37
  272. package/apps/control-plane/test/worker-provider-factory.spec.ts +81 -0
  273. package/apps/control-plane/test/worktree-watchdog-service.spec.ts +125 -0
  274. package/apps/control-plane/vitest.config.ts +5 -0
  275. package/config/agentic/orchestrator/agents.yaml +23 -2
  276. package/config/agentic/orchestrator/gates.yaml +24 -7
  277. package/config/agentic/orchestrator/policy.yaml +23 -1
  278. package/config/agentic/orchestrator/prompts/builder.system.md +69 -20
  279. package/config/agentic/orchestrator/prompts/organizer.system.md +85 -0
  280. package/config/agentic/orchestrator/prompts/overrides/builder.claude.md +28 -0
  281. package/config/agentic/orchestrator/prompts/overrides/builder.codex.md +28 -0
  282. package/config/agentic/orchestrator/prompts/overrides/planner.claude.md +20 -0
  283. package/config/agentic/orchestrator/prompts/overrides/planner.codex.md +20 -0
  284. package/config/agentic/orchestrator/prompts/planner-intake.system.md +149 -0
  285. package/config/agentic/orchestrator/prompts/planner.system.md +113 -40
  286. package/config/agentic/orchestrator/prompts/qa.system.md +75 -18
  287. package/config/agentic/orchestrator/prompts/reconciler.system.md +119 -0
  288. package/dist/apps/control-plane/application/kernel-tool-wiring.d.ts +26 -2
  289. package/dist/apps/control-plane/application/kernel-tool-wiring.js +40 -2
  290. package/dist/apps/control-plane/application/kernel-tool-wiring.js.map +1 -1
  291. package/dist/apps/control-plane/application/services/activity-monitor-service.js +37 -1
  292. package/dist/apps/control-plane/application/services/activity-monitor-service.js.map +1 -1
  293. package/dist/apps/control-plane/application/services/bootstrap-manifest-generator-service.d.ts +4 -0
  294. package/dist/apps/control-plane/application/services/bootstrap-manifest-generator-service.js +188 -0
  295. package/dist/apps/control-plane/application/services/bootstrap-manifest-generator-service.js.map +1 -0
  296. package/dist/apps/control-plane/application/services/checkpoint-service.d.ts +5 -0
  297. package/dist/apps/control-plane/application/services/checkpoint-service.js +69 -24
  298. package/dist/apps/control-plane/application/services/checkpoint-service.js.map +1 -1
  299. package/dist/apps/control-plane/application/services/collision-override-service.d.ts +139 -0
  300. package/dist/apps/control-plane/application/services/collision-override-service.js +568 -0
  301. package/dist/apps/control-plane/application/services/collision-override-service.js.map +1 -0
  302. package/dist/apps/control-plane/application/services/collision-queue-service.d.ts +15 -0
  303. package/dist/apps/control-plane/application/services/collision-queue-service.js +92 -33
  304. package/dist/apps/control-plane/application/services/collision-queue-service.js.map +1 -1
  305. package/dist/apps/control-plane/application/services/cost-tracking-service.d.ts +11 -0
  306. package/dist/apps/control-plane/application/services/cost-tracking-service.js +75 -0
  307. package/dist/apps/control-plane/application/services/cost-tracking-service.js.map +1 -1
  308. package/dist/apps/control-plane/application/services/execution-control-service.d.ts +75 -0
  309. package/dist/apps/control-plane/application/services/execution-control-service.js +421 -0
  310. package/dist/apps/control-plane/application/services/execution-control-service.js.map +1 -0
  311. package/dist/apps/control-plane/application/services/feature-deletion-service.d.ts +1 -0
  312. package/dist/apps/control-plane/application/services/feature-deletion-service.js +23 -1
  313. package/dist/apps/control-plane/application/services/feature-deletion-service.js.map +1 -1
  314. package/dist/apps/control-plane/application/services/feature-lifecycle-service.d.ts +24 -1
  315. package/dist/apps/control-plane/application/services/feature-lifecycle-service.js +132 -3
  316. package/dist/apps/control-plane/application/services/feature-lifecycle-service.js.map +1 -1
  317. package/dist/apps/control-plane/application/services/feature-send-message-service.js +16 -8
  318. package/dist/apps/control-plane/application/services/feature-send-message-service.js.map +1 -1
  319. package/dist/apps/control-plane/application/services/feature-state-service.d.ts +36 -0
  320. package/dist/apps/control-plane/application/services/feature-state-service.js +163 -6
  321. package/dist/apps/control-plane/application/services/feature-state-service.js.map +1 -1
  322. package/dist/apps/control-plane/application/services/gate-service.d.ts +2 -1
  323. package/dist/apps/control-plane/application/services/gate-service.js +95 -5
  324. package/dist/apps/control-plane/application/services/gate-service.js.map +1 -1
  325. package/dist/apps/control-plane/application/services/git-reconciliation-service.d.ts +92 -0
  326. package/dist/apps/control-plane/application/services/git-reconciliation-service.js +1097 -0
  327. package/dist/apps/control-plane/application/services/git-reconciliation-service.js.map +1 -0
  328. package/dist/apps/control-plane/application/services/intake-service.d.ts +63 -0
  329. package/dist/apps/control-plane/application/services/intake-service.js +1050 -0
  330. package/dist/apps/control-plane/application/services/intake-service.js.map +1 -0
  331. package/dist/apps/control-plane/application/services/merge-service.d.ts +5 -1
  332. package/dist/apps/control-plane/application/services/merge-service.js +233 -18
  333. package/dist/apps/control-plane/application/services/merge-service.js.map +1 -1
  334. package/dist/apps/control-plane/application/services/notifier-service.d.ts +1 -1
  335. package/dist/apps/control-plane/application/services/notifier-service.js +1 -0
  336. package/dist/apps/control-plane/application/services/notifier-service.js.map +1 -1
  337. package/dist/apps/control-plane/application/services/performance-analytics-service.d.ts +11 -0
  338. package/dist/apps/control-plane/application/services/performance-analytics-service.js +59 -0
  339. package/dist/apps/control-plane/application/services/performance-analytics-service.js.map +1 -1
  340. package/dist/apps/control-plane/application/services/plan-service.d.ts +5 -0
  341. package/dist/apps/control-plane/application/services/plan-service.js +254 -15
  342. package/dist/apps/control-plane/application/services/plan-service.js.map +1 -1
  343. package/dist/apps/control-plane/application/services/question-service.d.ts +72 -0
  344. package/dist/apps/control-plane/application/services/question-service.js +507 -0
  345. package/dist/apps/control-plane/application/services/question-service.js.map +1 -0
  346. package/dist/apps/control-plane/application/services/reactions-service.d.ts +2 -0
  347. package/dist/apps/control-plane/application/services/reactions-service.js +60 -17
  348. package/dist/apps/control-plane/application/services/reactions-service.js.map +1 -1
  349. package/dist/apps/control-plane/application/services/replay-timeline-service.d.ts +39 -0
  350. package/dist/apps/control-plane/application/services/replay-timeline-service.js +205 -0
  351. package/dist/apps/control-plane/application/services/replay-timeline-service.js.map +1 -0
  352. package/dist/apps/control-plane/application/services/reporting-service.d.ts +59 -0
  353. package/dist/apps/control-plane/application/services/reporting-service.js +121 -9
  354. package/dist/apps/control-plane/application/services/reporting-service.js.map +1 -1
  355. package/dist/apps/control-plane/application/services/run-lease-service.d.ts +20 -0
  356. package/dist/apps/control-plane/application/services/run-lease-service.js +81 -4
  357. package/dist/apps/control-plane/application/services/run-lease-service.js.map +1 -1
  358. package/dist/apps/control-plane/application/services/worktree-watchdog-service.d.ts +10 -0
  359. package/dist/apps/control-plane/application/services/worktree-watchdog-service.js +65 -8
  360. package/dist/apps/control-plane/application/services/worktree-watchdog-service.js.map +1 -1
  361. package/dist/apps/control-plane/application/tools/tool-metadata.js +7 -0
  362. package/dist/apps/control-plane/application/tools/tool-metadata.js.map +1 -1
  363. package/dist/apps/control-plane/application/usage-types.d.ts +65 -0
  364. package/dist/apps/control-plane/application/usage-types.js +75 -0
  365. package/dist/apps/control-plane/application/usage-types.js.map +1 -0
  366. package/dist/apps/control-plane/cli/add-command-handler.d.ts +18 -0
  367. package/dist/apps/control-plane/cli/add-command-handler.js +110 -0
  368. package/dist/apps/control-plane/cli/add-command-handler.js.map +1 -0
  369. package/dist/apps/control-plane/cli/answer-command-handler.d.ts +8 -0
  370. package/dist/apps/control-plane/cli/answer-command-handler.js +96 -0
  371. package/dist/apps/control-plane/cli/answer-command-handler.js.map +1 -0
  372. package/dist/apps/control-plane/cli/attach-command-handler.js +8 -3
  373. package/dist/apps/control-plane/cli/attach-command-handler.js.map +1 -1
  374. package/dist/apps/control-plane/cli/cli-argument-parser.js +131 -11
  375. package/dist/apps/control-plane/cli/cli-argument-parser.js.map +1 -1
  376. package/dist/apps/control-plane/cli/collision-command-handler.d.ts +8 -0
  377. package/dist/apps/control-plane/cli/collision-command-handler.js +90 -0
  378. package/dist/apps/control-plane/cli/collision-command-handler.js.map +1 -0
  379. package/dist/apps/control-plane/cli/command-catalog.d.ts +21 -0
  380. package/dist/apps/control-plane/cli/command-catalog.js +416 -0
  381. package/dist/apps/control-plane/cli/command-catalog.js.map +1 -0
  382. package/dist/apps/control-plane/cli/complete-command-handler.d.ts +15 -0
  383. package/dist/apps/control-plane/cli/complete-command-handler.js +26 -0
  384. package/dist/apps/control-plane/cli/complete-command-handler.js.map +1 -0
  385. package/dist/apps/control-plane/cli/completion-command-handler.d.ts +8 -0
  386. package/dist/apps/control-plane/cli/completion-command-handler.js +20 -0
  387. package/dist/apps/control-plane/cli/completion-command-handler.js.map +1 -0
  388. package/dist/apps/control-plane/cli/completion-resolver.d.ts +1 -0
  389. package/dist/apps/control-plane/cli/completion-resolver.js +250 -0
  390. package/dist/apps/control-plane/cli/completion-resolver.js.map +1 -0
  391. package/dist/apps/control-plane/cli/completion-shell-renderer.d.ts +3 -0
  392. package/dist/apps/control-plane/cli/completion-shell-renderer.js +53 -0
  393. package/dist/apps/control-plane/cli/completion-shell-renderer.js.map +1 -0
  394. package/dist/apps/control-plane/cli/dashboard-command-handler.d.ts +1 -0
  395. package/dist/apps/control-plane/cli/dashboard-command-handler.js +83 -1
  396. package/dist/apps/control-plane/cli/dashboard-command-handler.js.map +1 -1
  397. package/dist/apps/control-plane/cli/dashboard-runtime-runner.d.ts +81 -0
  398. package/dist/apps/control-plane/cli/dashboard-runtime-runner.js +724 -0
  399. package/dist/apps/control-plane/cli/dashboard-runtime-runner.js.map +1 -0
  400. package/dist/apps/control-plane/cli/dashboard-runtime.d.ts +1 -0
  401. package/dist/apps/control-plane/cli/dashboard-runtime.js +26 -0
  402. package/dist/apps/control-plane/cli/dashboard-runtime.js.map +1 -0
  403. package/dist/apps/control-plane/cli/help-command-handler.js +13 -172
  404. package/dist/apps/control-plane/cli/help-command-handler.js.map +1 -1
  405. package/dist/apps/control-plane/cli/init-command-handler.js +51 -6
  406. package/dist/apps/control-plane/cli/init-command-handler.js.map +1 -1
  407. package/dist/apps/control-plane/cli/merge-command-handler.d.ts +8 -0
  408. package/dist/apps/control-plane/cli/merge-command-handler.js +139 -0
  409. package/dist/apps/control-plane/cli/merge-command-handler.js.map +1 -0
  410. package/dist/apps/control-plane/cli/questions-command-handler.d.ts +8 -0
  411. package/dist/apps/control-plane/cli/questions-command-handler.js +59 -0
  412. package/dist/apps/control-plane/cli/questions-command-handler.js.map +1 -0
  413. package/dist/apps/control-plane/cli/replay-command-handler.d.ts +15 -0
  414. package/dist/apps/control-plane/cli/replay-command-handler.js +55 -0
  415. package/dist/apps/control-plane/cli/replay-command-handler.js.map +1 -0
  416. package/dist/apps/control-plane/cli/resume-command-handler.d.ts +2 -0
  417. package/dist/apps/control-plane/cli/resume-command-handler.js +196 -19
  418. package/dist/apps/control-plane/cli/resume-command-handler.js.map +1 -1
  419. package/dist/apps/control-plane/cli/retry-command-handler.js +202 -16
  420. package/dist/apps/control-plane/cli/retry-command-handler.js.map +1 -1
  421. package/dist/apps/control-plane/cli/retry-resume-decision.d.ts +26 -0
  422. package/dist/apps/control-plane/cli/retry-resume-decision.js +61 -0
  423. package/dist/apps/control-plane/cli/retry-resume-decision.js.map +1 -0
  424. package/dist/apps/control-plane/cli/rollback-command-handler.js +3 -2
  425. package/dist/apps/control-plane/cli/rollback-command-handler.js.map +1 -1
  426. package/dist/apps/control-plane/cli/run-command-handler.js +26 -2
  427. package/dist/apps/control-plane/cli/run-command-handler.js.map +1 -1
  428. package/dist/apps/control-plane/cli/spec-ingestion-service.d.ts +2 -0
  429. package/dist/apps/control-plane/cli/spec-ingestion-service.js +37 -48
  430. package/dist/apps/control-plane/cli/spec-ingestion-service.js.map +1 -1
  431. package/dist/apps/control-plane/cli/spec-preparation.d.ts +14 -0
  432. package/dist/apps/control-plane/cli/spec-preparation.js +81 -0
  433. package/dist/apps/control-plane/cli/spec-preparation.js.map +1 -0
  434. package/dist/apps/control-plane/cli/spec-utils.d.ts +4 -0
  435. package/dist/apps/control-plane/cli/spec-utils.js +70 -11
  436. package/dist/apps/control-plane/cli/spec-utils.js.map +1 -1
  437. package/dist/apps/control-plane/cli/status-command-handler.js +69 -0
  438. package/dist/apps/control-plane/cli/status-command-handler.js.map +1 -1
  439. package/dist/apps/control-plane/cli/types.d.ts +41 -4
  440. package/dist/apps/control-plane/cli/types.js +9 -1
  441. package/dist/apps/control-plane/cli/types.js.map +1 -1
  442. package/dist/apps/control-plane/core/collisions.d.ts +37 -19
  443. package/dist/apps/control-plane/core/collisions.js +87 -12
  444. package/dist/apps/control-plane/core/collisions.js.map +1 -1
  445. package/dist/apps/control-plane/core/constants.d.ts +17 -1
  446. package/dist/apps/control-plane/core/constants.js +18 -1
  447. package/dist/apps/control-plane/core/constants.js.map +1 -1
  448. package/dist/apps/control-plane/core/error-codes.d.ts +39 -0
  449. package/dist/apps/control-plane/core/error-codes.js +39 -0
  450. package/dist/apps/control-plane/core/error-codes.js.map +1 -1
  451. package/dist/apps/control-plane/core/execution-control.d.ts +45 -0
  452. package/dist/apps/control-plane/core/execution-control.js +2 -0
  453. package/dist/apps/control-plane/core/execution-control.js.map +1 -0
  454. package/dist/apps/control-plane/core/feature-resume-phase.d.ts +3 -0
  455. package/dist/apps/control-plane/core/feature-resume-phase.js +88 -0
  456. package/dist/apps/control-plane/core/feature-resume-phase.js.map +1 -0
  457. package/dist/apps/control-plane/core/gate-freshness.d.ts +48 -0
  458. package/dist/apps/control-plane/core/gate-freshness.js +267 -0
  459. package/dist/apps/control-plane/core/gate-freshness.js.map +1 -0
  460. package/dist/apps/control-plane/core/gate-log-extractor.d.ts +22 -0
  461. package/dist/apps/control-plane/core/gate-log-extractor.js +66 -0
  462. package/dist/apps/control-plane/core/gate-log-extractor.js.map +1 -0
  463. package/dist/apps/control-plane/core/gates.d.ts +11 -2
  464. package/dist/apps/control-plane/core/gates.js +67 -3
  465. package/dist/apps/control-plane/core/gates.js.map +1 -1
  466. package/dist/apps/control-plane/core/intake-artifacts.d.ts +109 -0
  467. package/dist/apps/control-plane/core/intake-artifacts.js +143 -0
  468. package/dist/apps/control-plane/core/intake-artifacts.js.map +1 -0
  469. package/dist/apps/control-plane/core/kernel-types.d.ts +8 -0
  470. package/dist/apps/control-plane/core/kernel.d.ts +256 -8
  471. package/dist/apps/control-plane/core/kernel.js +400 -14
  472. package/dist/apps/control-plane/core/kernel.js.map +1 -1
  473. package/dist/apps/control-plane/core/mainline-conflict.d.ts +7 -0
  474. package/dist/apps/control-plane/core/mainline-conflict.js +20 -0
  475. package/dist/apps/control-plane/core/mainline-conflict.js.map +1 -0
  476. package/dist/apps/control-plane/core/merge-repair.d.ts +35 -0
  477. package/dist/apps/control-plane/core/merge-repair.js +99 -0
  478. package/dist/apps/control-plane/core/merge-repair.js.map +1 -0
  479. package/dist/apps/control-plane/core/path-layout.d.ts +10 -0
  480. package/dist/apps/control-plane/core/path-layout.js +32 -2
  481. package/dist/apps/control-plane/core/path-layout.js.map +1 -1
  482. package/dist/apps/control-plane/core/path-rules.js +9 -3
  483. package/dist/apps/control-plane/core/path-rules.js.map +1 -1
  484. package/dist/apps/control-plane/core/plan-submit-recovery.d.ts +22 -0
  485. package/dist/apps/control-plane/core/plan-submit-recovery.js +78 -0
  486. package/dist/apps/control-plane/core/plan-submit-recovery.js.map +1 -0
  487. package/dist/apps/control-plane/core/questions.d.ts +40 -0
  488. package/dist/apps/control-plane/core/questions.js +2 -0
  489. package/dist/apps/control-plane/core/questions.js.map +1 -0
  490. package/dist/apps/control-plane/core/runtime-sessions.d.ts +4 -0
  491. package/dist/apps/control-plane/core/schemas.d.ts +2 -0
  492. package/dist/apps/control-plane/core/schemas.js +31 -1
  493. package/dist/apps/control-plane/core/schemas.js.map +1 -1
  494. package/dist/apps/control-plane/core/tool-caller.d.ts +18 -1
  495. package/dist/apps/control-plane/core/utils/index-normalizer.js +17 -4
  496. package/dist/apps/control-plane/core/utils/index-normalizer.js.map +1 -1
  497. package/dist/apps/control-plane/core/worktree-diff.d.ts +4 -0
  498. package/dist/apps/control-plane/core/worktree-diff.js +52 -0
  499. package/dist/apps/control-plane/core/worktree-diff.js.map +1 -0
  500. package/dist/apps/control-plane/index.d.ts +10 -2
  501. package/dist/apps/control-plane/index.js +9 -2
  502. package/dist/apps/control-plane/index.js.map +1 -1
  503. package/dist/apps/control-plane/interfaces/cli/bootstrap.js +236 -6
  504. package/dist/apps/control-plane/interfaces/cli/bootstrap.js.map +1 -1
  505. package/dist/apps/control-plane/mcp/kernel-tool-executor.js +16 -0
  506. package/dist/apps/control-plane/mcp/kernel-tool-executor.js.map +1 -1
  507. package/dist/apps/control-plane/mcp/tool-runtime.d.ts +5 -0
  508. package/dist/apps/control-plane/mcp/tool-runtime.js +40 -5
  509. package/dist/apps/control-plane/mcp/tool-runtime.js.map +1 -1
  510. package/dist/apps/control-plane/providers/api-worker-provider.d.ts +2 -2
  511. package/dist/apps/control-plane/providers/api-worker-provider.js +40 -9
  512. package/dist/apps/control-plane/providers/api-worker-provider.js.map +1 -1
  513. package/dist/apps/control-plane/providers/cli-worker-provider.d.ts +59 -3
  514. package/dist/apps/control-plane/providers/cli-worker-provider.js +758 -46
  515. package/dist/apps/control-plane/providers/cli-worker-provider.js.map +1 -1
  516. package/dist/apps/control-plane/providers/output-parsers/generic-output-parser.js +91 -1
  517. package/dist/apps/control-plane/providers/output-parsers/generic-output-parser.js.map +1 -1
  518. package/dist/apps/control-plane/providers/output-parsers/types.d.ts +2 -0
  519. package/dist/apps/control-plane/providers/provider-defaults.d.ts +12 -0
  520. package/dist/apps/control-plane/providers/provider-defaults.js +103 -7
  521. package/dist/apps/control-plane/providers/provider-defaults.js.map +1 -1
  522. package/dist/apps/control-plane/providers/providers.d.ts +50 -4
  523. package/dist/apps/control-plane/providers/providers.js +145 -14
  524. package/dist/apps/control-plane/providers/providers.js.map +1 -1
  525. package/dist/apps/control-plane/providers/worker-provider-factory.d.ts +2 -0
  526. package/dist/apps/control-plane/providers/worker-provider-factory.js +8 -1
  527. package/dist/apps/control-plane/providers/worker-provider-factory.js.map +1 -1
  528. package/dist/apps/control-plane/supervisor/artifact-stager.d.ts +5 -0
  529. package/dist/apps/control-plane/supervisor/artifact-stager.js +45 -0
  530. package/dist/apps/control-plane/supervisor/artifact-stager.js.map +1 -0
  531. package/dist/apps/control-plane/supervisor/build-wave-executor.d.ts +24 -1
  532. package/dist/apps/control-plane/supervisor/build-wave-executor.js +362 -150
  533. package/dist/apps/control-plane/supervisor/build-wave-executor.js.map +1 -1
  534. package/dist/apps/control-plane/supervisor/execution-enrollment-service.d.ts +41 -0
  535. package/dist/apps/control-plane/supervisor/execution-enrollment-service.js +311 -0
  536. package/dist/apps/control-plane/supervisor/execution-enrollment-service.js.map +1 -0
  537. package/dist/apps/control-plane/supervisor/organizer-enrollment-scheduler.d.ts +15 -0
  538. package/dist/apps/control-plane/supervisor/organizer-enrollment-scheduler.js +93 -0
  539. package/dist/apps/control-plane/supervisor/organizer-enrollment-scheduler.js.map +1 -0
  540. package/dist/apps/control-plane/supervisor/organizer-sidecar-service.d.ts +44 -0
  541. package/dist/apps/control-plane/supervisor/organizer-sidecar-service.js +311 -0
  542. package/dist/apps/control-plane/supervisor/organizer-sidecar-service.js.map +1 -0
  543. package/dist/apps/control-plane/supervisor/plan-conformance-scorer.js +2 -5
  544. package/dist/apps/control-plane/supervisor/plan-conformance-scorer.js.map +1 -1
  545. package/dist/apps/control-plane/supervisor/planner-phase.d.ts +3 -0
  546. package/dist/apps/control-plane/supervisor/planner-phase.js +70 -0
  547. package/dist/apps/control-plane/supervisor/planner-phase.js.map +1 -0
  548. package/dist/apps/control-plane/supervisor/planning-wave-executor.d.ts +42 -0
  549. package/dist/apps/control-plane/supervisor/planning-wave-executor.js +753 -55
  550. package/dist/apps/control-plane/supervisor/planning-wave-executor.js.map +1 -1
  551. package/dist/apps/control-plane/supervisor/prompt-bundle-loader.js +19 -1
  552. package/dist/apps/control-plane/supervisor/prompt-bundle-loader.js.map +1 -1
  553. package/dist/apps/control-plane/supervisor/qa-wave-executor.d.ts +21 -0
  554. package/dist/apps/control-plane/supervisor/qa-wave-executor.js +287 -156
  555. package/dist/apps/control-plane/supervisor/qa-wave-executor.js.map +1 -1
  556. package/dist/apps/control-plane/supervisor/run-coordinator.d.ts +33 -1
  557. package/dist/apps/control-plane/supervisor/run-coordinator.js +631 -39
  558. package/dist/apps/control-plane/supervisor/run-coordinator.js.map +1 -1
  559. package/dist/apps/control-plane/supervisor/runtime.d.ts +84 -0
  560. package/dist/apps/control-plane/supervisor/runtime.js +393 -3
  561. package/dist/apps/control-plane/supervisor/runtime.js.map +1 -1
  562. package/dist/apps/control-plane/supervisor/session-orchestrator.d.ts +54 -0
  563. package/dist/apps/control-plane/supervisor/session-orchestrator.js +176 -1
  564. package/dist/apps/control-plane/supervisor/session-orchestrator.js.map +1 -1
  565. package/dist/apps/control-plane/supervisor/types.d.ts +142 -1
  566. package/dist/apps/control-plane/supervisor/types.js.map +1 -1
  567. package/dist/apps/control-plane/supervisor/worker-decision-loop.d.ts +68 -2
  568. package/dist/apps/control-plane/supervisor/worker-decision-loop.js +723 -89
  569. package/dist/apps/control-plane/supervisor/worker-decision-loop.js.map +1 -1
  570. package/docs/core/ARCHITECTURE.md +227 -0
  571. package/docs/core/DECISIONS.md +94 -0
  572. package/docs/core/DOMAIN-LOGIC.md +60 -0
  573. package/docs/core/PATTERNS.md +201 -0
  574. package/docs/core/TROUBLESHOOTING.md +347 -0
  575. package/docs/core/intentgraph-dependencies.json +39860 -0
  576. package/docs/core/intentgraph.index.json +46580 -0
  577. package/docs/plans/2026-03-10-gate-failure-targeted-repair-design.md +224 -0
  578. package/docs/plans/2026-03-10-gate-failure-targeted-repair.md +1032 -0
  579. package/docs/superpowers/plans/2026-03-16-provider-cli-config.md +743 -0
  580. package/docs/superpowers/plans/2026-03-23-reconcile-divergence-fix.md +777 -0
  581. package/docs/superpowers/plans/2026-03-28-ordering-agent-implementation.md +1754 -0
  582. package/docs/superpowers/plans/2026-03-29-drop-zone-and-provider-optimization.md +1108 -0
  583. package/docs/superpowers/plans/2026-03-29-merge-target-feature-branch.md +685 -0
  584. package/docs/superpowers/plans/2026-03-29-organizer-sidecar-runtime-loop.md +1289 -0
  585. package/docs/superpowers/specs/2026-03-23-reconcile-divergence-fix-design.md +118 -0
  586. package/docs/superpowers/specs/2026-03-28-ordering-agent-spec-audit-design.md +50 -0
  587. package/docs/superpowers/specs/2026-03-29-drop-zone-and-provider-optimization-design.md +254 -0
  588. package/docs/superpowers/specs/2026-03-29-merge-target-feature-branch-design.md +152 -0
  589. package/docs/superpowers/specs/2026-03-29-organizer-sidecar-runtime-loop-design.md +225 -0
  590. package/package.json +3 -2
  591. package/packages/web-dashboard/package.json +2 -1
  592. package/packages/web-dashboard/src/app/analytics/page.tsx +36 -2
  593. package/packages/web-dashboard/src/app/api/actions/route.ts +274 -63
  594. package/packages/web-dashboard/src/app/api/actions/status/route.ts +35 -0
  595. package/packages/web-dashboard/src/app/api/analytics/provider/route.ts +18 -0
  596. package/packages/web-dashboard/src/app/api/collisions/approve/route.ts +58 -0
  597. package/packages/web-dashboard/src/app/api/features/[id]/checkpoint-diff/route.ts +36 -0
  598. package/packages/web-dashboard/src/app/api/features/[id]/checkpoints/route.ts +29 -0
  599. package/packages/web-dashboard/src/app/api/features/[id]/conflicts/abort/route.ts +29 -0
  600. package/packages/web-dashboard/src/app/api/features/[id]/conflicts/files/route.ts +30 -0
  601. package/packages/web-dashboard/src/app/api/features/[id]/conflicts/resolve/route.ts +51 -0
  602. package/packages/web-dashboard/src/app/api/features/[id]/conflicts/route.ts +75 -0
  603. package/packages/web-dashboard/src/app/api/features/[id]/diff/route.ts +16 -2
  604. package/packages/web-dashboard/src/app/api/features/[id]/files/route.ts +26 -0
  605. package/packages/web-dashboard/src/app/api/features/[id]/gate-history/route.ts +27 -0
  606. package/packages/web-dashboard/src/app/api/features/[id]/genealogy/route.ts +26 -0
  607. package/packages/web-dashboard/src/app/api/features/[id]/history/run/[runId]/route.ts +20 -0
  608. package/packages/web-dashboard/src/app/api/features/[id]/history/runs/route.ts +34 -0
  609. package/packages/web-dashboard/src/app/api/features/[id]/intake-workspace/route.ts +20 -0
  610. package/packages/web-dashboard/src/app/api/features/[id]/live-output/route.ts +74 -0
  611. package/packages/web-dashboard/src/app/api/features/[id]/plan/amend/route.ts +21 -0
  612. package/packages/web-dashboard/src/app/api/features/[id]/plan-progress/route.ts +20 -0
  613. package/packages/web-dashboard/src/app/api/features/[id]/planner-artifacts/[artifact]/route.ts +78 -0
  614. package/packages/web-dashboard/src/app/api/features/[id]/planner-lifecycle/route.ts +20 -0
  615. package/packages/web-dashboard/src/app/api/features/[id]/planning-workspace/route.ts +20 -0
  616. package/packages/web-dashboard/src/app/api/features/[id]/questions/[questionId]/answer/route.ts +27 -0
  617. package/packages/web-dashboard/src/app/api/features/[id]/questions/route.ts +18 -0
  618. package/packages/web-dashboard/src/app/api/features/[id]/review/route.ts +14 -7
  619. package/packages/web-dashboard/src/app/api/features/[id]/route.ts +57 -2
  620. package/packages/web-dashboard/src/app/api/features/[id]/spec/route.ts +30 -0
  621. package/packages/web-dashboard/src/app/api/features/[id]/triage/route.ts +83 -0
  622. package/packages/web-dashboard/src/app/api/features/[id]/worker-events/route.ts +40 -0
  623. package/packages/web-dashboard/src/app/api/launch/preview/route.ts +86 -0
  624. package/packages/web-dashboard/src/app/api/launch/submit/route.ts +180 -0
  625. package/packages/web-dashboard/src/app/api/mainline/status/route.ts +74 -0
  626. package/packages/web-dashboard/src/app/api/merge-queue/route.ts +13 -0
  627. package/packages/web-dashboard/src/app/api/policy/budget/route.ts +14 -0
  628. package/packages/web-dashboard/src/app/api/projects/route.ts +11 -7
  629. package/packages/web-dashboard/src/app/api/reconciler/queue/route.ts +47 -0
  630. package/packages/web-dashboard/src/app/api/run/route.ts +26 -2
  631. package/packages/web-dashboard/src/app/api/runtime/events/route.ts +227 -0
  632. package/packages/web-dashboard/src/app/api/runtime/operations/route.ts +269 -0
  633. package/packages/web-dashboard/src/app/api/runtime/questions/route.ts +11 -0
  634. package/packages/web-dashboard/src/app/api/runtime/runs/route.ts +80 -0
  635. package/packages/web-dashboard/src/app/api/status/route.ts +4 -2
  636. package/packages/web-dashboard/src/app/feature/[id]/page.tsx +32 -42
  637. package/packages/web-dashboard/src/app/globals.css +34 -3
  638. package/packages/web-dashboard/src/app/launch/page.tsx +357 -0
  639. package/packages/web-dashboard/src/app/layout.tsx +23 -1
  640. package/packages/web-dashboard/src/app/page.tsx +263 -272
  641. package/packages/web-dashboard/src/components/dashboard/attention-strip.tsx +52 -0
  642. package/packages/web-dashboard/src/components/dashboard/collision-approval-drawer.tsx +185 -0
  643. package/packages/web-dashboard/src/components/dashboard/command-center-header.tsx +102 -0
  644. package/packages/web-dashboard/src/components/dashboard/mainline-status-banner.tsx +84 -0
  645. package/packages/web-dashboard/src/components/dashboard/merged-archive.tsx +36 -0
  646. package/packages/web-dashboard/src/components/dashboard/prioritized-queues.tsx +98 -0
  647. package/packages/web-dashboard/src/components/dashboard/reconciler-queue-card.tsx +115 -0
  648. package/packages/web-dashboard/src/components/dashboard/secondary-diagnostics-rail.tsx +48 -0
  649. package/packages/web-dashboard/src/components/dashboard/task-filter-bar.tsx +74 -0
  650. package/packages/web-dashboard/src/components/dashboard/triage-drawer.tsx +455 -0
  651. package/packages/web-dashboard/src/components/diff-viewer.tsx +19 -3
  652. package/packages/web-dashboard/src/components/evidence-viewer.tsx +65 -51
  653. package/packages/web-dashboard/src/components/feature-card.tsx +90 -7
  654. package/packages/web-dashboard/src/components/feature-cost-panel.tsx +112 -11
  655. package/packages/web-dashboard/src/components/feature-list-view.tsx +25 -4
  656. package/packages/web-dashboard/src/components/features/runtime-inspector/EventsTimelineView.tsx +260 -0
  657. package/packages/web-dashboard/src/components/features/runtime-inspector/OperationsListView.tsx +172 -0
  658. package/packages/web-dashboard/src/components/features/runtime-inspector/RuntimeInspectorPanel.tsx +896 -0
  659. package/packages/web-dashboard/src/components/filter-bar.tsx +7 -39
  660. package/packages/web-dashboard/src/components/focus/ActionableRiskList.tsx +46 -0
  661. package/packages/web-dashboard/src/components/focus/AgentRolePerformanceCard.tsx +200 -0
  662. package/packages/web-dashboard/src/components/focus/BlockedGuidanceBanner.tsx +149 -0
  663. package/packages/web-dashboard/src/components/focus/CheckpointInspector.tsx +123 -0
  664. package/packages/web-dashboard/src/components/focus/CheckpointRail.tsx +118 -0
  665. package/packages/web-dashboard/src/components/focus/CheckpointScrubber.tsx +249 -0
  666. package/packages/web-dashboard/src/components/focus/CollisionApprovalBanner.tsx +192 -0
  667. package/packages/web-dashboard/src/components/focus/CollisionRadar.tsx +136 -0
  668. package/packages/web-dashboard/src/components/focus/ConflictStatusCard.tsx +52 -0
  669. package/packages/web-dashboard/src/components/focus/ContextSidebar.tsx +108 -0
  670. package/packages/web-dashboard/src/components/focus/DiagnosisPanel.tsx +68 -0
  671. package/packages/web-dashboard/src/components/focus/FeatureDecisionBanner.tsx +68 -0
  672. package/packages/web-dashboard/src/components/focus/FeatureQuestionAnswerPanel.tsx +167 -0
  673. package/packages/web-dashboard/src/components/focus/FocusHeader.tsx +54 -0
  674. package/packages/web-dashboard/src/components/focus/FocusLayout.tsx +283 -0
  675. package/packages/web-dashboard/src/components/focus/GateFlakinessSummary.tsx +144 -0
  676. package/packages/web-dashboard/src/components/focus/GenealogyTree.tsx +34 -0
  677. package/packages/web-dashboard/src/components/focus/HeroBlock.tsx +67 -0
  678. package/packages/web-dashboard/src/components/focus/LiveAgentConsole.tsx +277 -0
  679. package/packages/web-dashboard/src/components/focus/MergeQueueCard.tsx +78 -0
  680. package/packages/web-dashboard/src/components/focus/OperationalSummaryCard.tsx +227 -0
  681. package/packages/web-dashboard/src/components/focus/PinnedActions.tsx +96 -0
  682. package/packages/web-dashboard/src/components/focus/PlanAmendmentPanel.tsx +250 -0
  683. package/packages/web-dashboard/src/components/focus/PlanProgressPanel.tsx +133 -0
  684. package/packages/web-dashboard/src/components/focus/PlannerArtifactViewer.tsx +158 -0
  685. package/packages/web-dashboard/src/components/focus/PlannerLifecycleHeader.tsx +141 -0
  686. package/packages/web-dashboard/src/components/focus/ProgressSnapshotCard.tsx +113 -0
  687. package/packages/web-dashboard/src/components/focus/RecentMaterialChanges.tsx +69 -0
  688. package/packages/web-dashboard/src/components/focus/RoleLogViewer.tsx +436 -0
  689. package/packages/web-dashboard/src/components/focus/RunHistoryBrowser.tsx +62 -0
  690. package/packages/web-dashboard/src/components/focus/SpecViewer.tsx +172 -0
  691. package/packages/web-dashboard/src/components/focus/TabBar.tsx +33 -0
  692. package/packages/web-dashboard/src/components/focus/UsageBurnChart.tsx +212 -0
  693. package/packages/web-dashboard/src/components/focus/VerificationSummaryCard.tsx +122 -0
  694. package/packages/web-dashboard/src/components/focus/tabs/ChangesTab.tsx +325 -0
  695. package/packages/web-dashboard/src/components/focus/tabs/ConflictsTab.tsx +395 -0
  696. package/packages/web-dashboard/src/components/focus/tabs/GatesQaTab.tsx +38 -0
  697. package/packages/web-dashboard/src/components/focus/tabs/HistoryTab.tsx +213 -0
  698. package/packages/web-dashboard/src/components/focus/tabs/IntakeTab.tsx +429 -0
  699. package/packages/web-dashboard/src/components/focus/tabs/OverviewTab.tsx +217 -0
  700. package/packages/web-dashboard/src/components/focus/tabs/PlanningTab.tsx +390 -0
  701. package/packages/web-dashboard/src/components/focus/tabs/ReviewTab.tsx +497 -0
  702. package/packages/web-dashboard/src/components/focus/tabs/RuntimeTab.tsx +213 -0
  703. package/packages/web-dashboard/src/components/focus/tabs/TranscriptTab.tsx +315 -0
  704. package/packages/web-dashboard/src/components/gate-results.tsx +2 -2
  705. package/packages/web-dashboard/src/components/human-input-panel.tsx +33 -57
  706. package/packages/web-dashboard/src/components/kanban-board.tsx +4 -0
  707. package/packages/web-dashboard/src/components/launch/launch-draft-card.tsx +131 -0
  708. package/packages/web-dashboard/src/components/plan-viewer.tsx +147 -69
  709. package/packages/web-dashboard/src/components/quick-launch-panel.tsx +20 -47
  710. package/packages/web-dashboard/src/components/summary-bar.tsx +30 -76
  711. package/packages/web-dashboard/src/lib/aop-client.ts +2484 -36
  712. package/packages/web-dashboard/src/lib/blocked-state-guidance.ts +475 -0
  713. package/packages/web-dashboard/src/lib/collision-radar.ts +136 -0
  714. package/packages/web-dashboard/src/lib/dashboard-action-states.ts +204 -0
  715. package/packages/web-dashboard/src/lib/dashboard-runtime-client.ts +439 -0
  716. package/packages/web-dashboard/src/lib/dashboard-utils.ts +179 -18
  717. package/packages/web-dashboard/src/lib/drop-zone-utils.ts +92 -0
  718. package/packages/web-dashboard/src/lib/focus-detail-derivations.ts +958 -0
  719. package/packages/web-dashboard/src/lib/focus-view.ts +300 -0
  720. package/packages/web-dashboard/src/lib/health-diagnosis.ts +356 -0
  721. package/packages/web-dashboard/src/lib/launch-contracts.ts +77 -0
  722. package/packages/web-dashboard/src/lib/launch-markdown.ts +107 -0
  723. package/packages/web-dashboard/src/lib/launch-page-preview.ts +89 -0
  724. package/packages/web-dashboard/src/lib/live-feed.ts +1 -1
  725. package/packages/web-dashboard/src/lib/multi-project-config.ts +33 -0
  726. package/packages/web-dashboard/src/lib/orchestrator-tools.ts +845 -59
  727. package/packages/web-dashboard/src/lib/planner-workspace.ts +1285 -0
  728. package/packages/web-dashboard/src/lib/review-contracts.ts +5 -3
  729. package/packages/web-dashboard/src/lib/runtime-files.ts +285 -0
  730. package/packages/web-dashboard/src/lib/tool-catalog.ts +51 -0
  731. package/packages/web-dashboard/src/lib/types.ts +731 -3
  732. package/packages/web-dashboard/src/lib/usage-burn.ts +175 -0
  733. package/packages/web-dashboard/src/lib/worktree-diff.ts +128 -0
  734. package/packages/web-dashboard/src/styles/dashboard.module.css +1742 -459
  735. package/packages/web-dashboard/test/api/actions/route.spec.ts +675 -0
  736. package/packages/web-dashboard/test/api/features/diff.route.spec.ts +57 -0
  737. package/packages/web-dashboard/test/api/features/feature.route.spec.ts +99 -0
  738. package/packages/web-dashboard/test/api/features/live-output.route.spec.ts +123 -0
  739. package/packages/web-dashboard/test/api/features/plan-amend.route.spec.ts +95 -0
  740. package/packages/web-dashboard/test/api/features/planner-workspaces.route.spec.ts +162 -0
  741. package/packages/web-dashboard/test/api/features/question-answer.route.spec.ts +99 -0
  742. package/packages/web-dashboard/test/api/features/triage.route.spec.ts +195 -0
  743. package/packages/web-dashboard/test/api/launch/preview.route.spec.ts +149 -0
  744. package/packages/web-dashboard/test/api/launch/submit.route.spec.ts +382 -0
  745. package/packages/web-dashboard/test/api/runtime/events/route.spec.ts +164 -0
  746. package/packages/web-dashboard/test/api/runtime/operations/route.spec.ts +156 -0
  747. package/packages/web-dashboard/test/api/runtime/runs/route.spec.ts +112 -0
  748. package/packages/web-dashboard/test/components/changes-tab.spec.tsx +76 -0
  749. package/packages/web-dashboard/test/components/command-center-root.spec.tsx +87 -0
  750. package/packages/web-dashboard/test/components/diagnosis-panel.spec.tsx +59 -0
  751. package/packages/web-dashboard/test/components/feature-card.spec.tsx +45 -0
  752. package/packages/web-dashboard/test/components/focus-layout.spec.tsx +299 -0
  753. package/packages/web-dashboard/test/components/gate-results.spec.tsx +39 -0
  754. package/packages/web-dashboard/test/components/gates-qa-tab.spec.tsx +118 -0
  755. package/packages/web-dashboard/test/components/human-input-panel.spec.tsx +54 -0
  756. package/packages/web-dashboard/test/components/intake-tab.spec.tsx +210 -0
  757. package/packages/web-dashboard/test/components/kanban-board.spec.tsx +35 -0
  758. package/packages/web-dashboard/test/components/launch-draft-card.spec.tsx +54 -0
  759. package/packages/web-dashboard/test/components/launch-page.spec.tsx +79 -0
  760. package/packages/web-dashboard/test/components/overview-tab.spec.tsx +236 -0
  761. package/packages/web-dashboard/test/components/planning-tab.spec.tsx +202 -0
  762. package/packages/web-dashboard/test/components/review-tab.spec.tsx +169 -0
  763. package/packages/web-dashboard/test/components/role-log-viewer.spec.ts +42 -0
  764. package/packages/web-dashboard/test/components/runtime-inspector.spec.tsx +22 -0
  765. package/packages/web-dashboard/test/components/runtime-tab.spec.tsx +133 -0
  766. package/packages/web-dashboard/test/components/transcript-tab.spec.tsx +46 -0
  767. package/packages/web-dashboard/test/components/triage-drawer.spec.tsx +159 -0
  768. package/packages/web-dashboard/test/lib/aop-client.spec.ts +235 -0
  769. package/packages/web-dashboard/test/lib/dashboard-runtime-client.spec.ts +144 -0
  770. package/packages/web-dashboard/test/lib/focus-detail-derivations.spec.ts +314 -0
  771. package/packages/web-dashboard/test/lib/focus-view.spec.ts +248 -0
  772. package/packages/web-dashboard/test/lib/health-diagnosis.spec.ts +277 -0
  773. package/packages/web-dashboard/test/lib/launch-markdown.spec.ts +36 -0
  774. package/packages/web-dashboard/test/lib/multi-project-config.spec.ts +54 -0
  775. package/packages/web-dashboard/test/lib/orchestrator-tools.spec.ts +352 -0
  776. package/packages/web-dashboard/test/lib/planner-workspace.spec.ts +289 -0
  777. package/packages/web-dashboard/test/lib/worktree-diff.spec.ts +119 -0
  778. package/packages/web-dashboard/vitest.config.ts +2 -0
  779. package/spec-files/completed/agentic_orchestrator_add_feature_to_active_execution_spec.md +557 -0
  780. package/spec-files/completed/agentic_orchestrator_dashboard_command_center_redesign_spec.md +1147 -0
  781. package/spec-files/completed/agentic_orchestrator_execution_mode_spec.md +18 -16
  782. package/spec-files/completed/agentic_orchestrator_feature_focus_view_track_a_spec.md +672 -0
  783. package/spec-files/completed/agentic_orchestrator_feature_focus_view_track_b_spec.md +794 -0
  784. package/spec-files/completed/agentic_orchestrator_feature_focus_view_track_c_decision_centric_remediation_spec.md +1037 -0
  785. package/spec-files/completed/agentic_orchestrator_feature_focus_view_ux_redesign_spec.md +1432 -0
  786. package/spec-files/completed/agentic_orchestrator_focus_plan_tab_intake_planning_workspace_spec.md +921 -0
  787. package/spec-files/completed/agentic_orchestrator_intentional_collision_override_spec.md +584 -0
  788. package/spec-files/completed/agentic_orchestrator_interactive_planning_intake_and_requirements_verification_spec.md +1185 -0
  789. package/spec-files/completed/agentic_orchestrator_reactive_execution_enrollment_spec.md +864 -0
  790. package/spec-files/{outstanding → completed}/agentic_orchestrator_runtime_inspection_spec.md +92 -19
  791. package/spec-files/completed/agentic_orchestrator_scope_aware_run_lease_spec.md +408 -0
  792. package/spec-files/completed/git-reconciliation-engine.md +827 -0
  793. package/spec-files/outstanding/agentic_orchestrator_dashboard_quick_launch_and_control_surface_spec.md +331 -0
  794. package/spec-files/outstanding/agentic_orchestrator_enterprise_governance_dashboard_spec.md +16 -6
  795. package/spec-files/outstanding/agentic_orchestrator_evidence_integrity_doctor_spec.md +60 -9
  796. package/spec-files/outstanding/agentic_orchestrator_focus_plan_tab_execution_contract_workspace_spec.md +616 -0
  797. package/spec-files/outstanding/agentic_orchestrator_headless_standby_dashboard_runtime_spec.md +310 -0
  798. package/spec-files/outstanding/agentic_orchestrator_human_input_interaction_protocol_spec.md +175 -72
  799. package/spec-files/outstanding/agentic_orchestrator_interactive_rename_cleanup_spec.md +197 -0
  800. package/spec-files/outstanding/agentic_orchestrator_interactive_resume_and_reconciliation_disposition_spec.md +412 -0
  801. package/spec-files/outstanding/agentic_orchestrator_knowledge_canary_spec.md +166 -137
  802. package/spec-files/outstanding/agentic_orchestrator_observability_replay_spec.md +3 -3
  803. package/spec-files/outstanding/agentic_orchestrator_phase_specific_agent_profiles_and_token_telemetry_spec.md +303 -0
  804. package/spec-files/outstanding/agentic_orchestrator_planning_review_quality_spec.md +18 -5
  805. package/spec-files/outstanding/agentic_orchestrator_policy_stratification_spec.md +225 -0
  806. package/spec-files/outstanding/agentic_orchestrator_quality_adoption_execution_spec.md +77 -50
  807. package/spec-files/outstanding/agentic_orchestrator_ready_to_merge_branch_handoff_spec.md +724 -0
  808. package/spec-files/outstanding/agentic_orchestrator_remove_deterministic_mode_spec.md +263 -0
  809. package/spec-files/outstanding/agentic_orchestrator_request_more_context_and_dashboard_human_input_spec.md +456 -0
  810. package/spec-files/outstanding/agentic_orchestrator_spec_coverage_and_reconciliation_enforcement_spec.md +1411 -0
  811. package/spec-files/outstanding/agentic_orchestrator_spec_ordering_agent_spec.md +370 -0
  812. package/spec-files/outstanding/shadow_workspace_implementation_spec.md +1 -1
  813. package/spec-files/progress.md +2045 -87
  814. package/specs/001-runtime-inspection/checklists/requirements.md +35 -0
  815. package/specs/001-runtime-inspection/design.md +338 -0
  816. package/specs/001-runtime-inspection/spec.md +95 -0
  817. package/specs/002-scope-aware-lease/checklists/requirements.md +35 -0
  818. package/specs/002-scope-aware-lease/contracts/lease-registry.schema.json +101 -0
  819. package/specs/002-scope-aware-lease/data-model.md +236 -0
  820. package/specs/002-scope-aware-lease/plan.md +766 -0
  821. package/specs/002-scope-aware-lease/quickstart.md +150 -0
  822. package/specs/002-scope-aware-lease/research.md +135 -0
  823. package/specs/002-scope-aware-lease/spec.md +128 -0
  824. package/specs/002-scope-aware-lease/tasks.md +767 -0
  825. package/tsconfig.json +1 -1
  826. package/vitest.config.ts +28 -0
  827. package/ARCHITECTURE_ADHERENCE_ANALYSIS.md +0 -871
  828. package/packages/web-dashboard/next-env.d.ts +0 -6
  829. package/packages/web-dashboard/src/components/detail-panel.tsx +0 -1124
  830. package/packages/web-dashboard/src/components/review-workspace.tsx +0 -1162
  831. /package/spec-files/{outstanding → completed}/agentic_orchestrator_artifact_database_publishing_spec.md +0 -0
  832. /package/spec-files/{outstanding → completed}/agentic_orchestrator_cli_shell_tab_completion_spec.md +0 -0
  833. /package/spec-files/{outstanding → completed}/agentic_orchestrator_dashboard_diff_and_agent_console_spec.md +0 -0
  834. /package/spec-files/{outstanding → completed}/agentic_orchestrator_performance_improvements_spec.md +0 -0
  835. /package/spec-files/{outstanding → completed}/agentic_orchestrator_persistent_worker_runtime_spec.md +0 -0
  836. /package/spec-files/{outstanding → completed}/agentic_orchestrator_provider_auth_bootstrap_spec.md +0 -0
  837. /package/spec-files/{outstanding → completed}/agentic_orchestrator_real_worker_provider_execution_spec.md +0 -0
@@ -1,5 +1,7 @@
1
- import { TOOLS } from '../core/constants.js';
1
+ import path from 'node:path';
2
+ import { STATUS, TOOLS } from '../core/constants.js';
2
3
  import { ERROR_CODES } from '../core/error-codes.js';
4
+ import { resolvePlannerPhaseFromContext } from './planner-phase.js';
3
5
  import { appendWorkerRuntimeEvent } from './worker-event-journal.js';
4
6
  const PLAN_TOP_LEVEL_KEYS = new Set([
5
7
  'feature_id',
@@ -11,6 +13,7 @@ const PLAN_TOP_LEVEL_KEYS = new Set([
11
13
  'files',
12
14
  'contracts',
13
15
  'acceptance_criteria',
16
+ 'plan_trace',
14
17
  'gate_targets',
15
18
  'risk',
16
19
  'revision_of',
@@ -20,6 +23,23 @@ const PLAN_TOP_LEVEL_KEYS = new Set([
20
23
  function asRecord(value) {
21
24
  return value && typeof value === 'object' ? value : {};
22
25
  }
26
+ function extractNonErrorMessage(value) {
27
+ if (!value || typeof value !== 'object') {
28
+ return typeof value === 'string' ? value : null;
29
+ }
30
+ const obj = value;
31
+ const normalized = obj['normalizedResponse'];
32
+ if (normalized?.['error'] && typeof normalized['error'] === 'object') {
33
+ const err = normalized['error'];
34
+ if (typeof err['message'] === 'string') {
35
+ return err['message'];
36
+ }
37
+ }
38
+ if (typeof obj['message'] === 'string') {
39
+ return obj['message'];
40
+ }
41
+ return null;
42
+ }
23
43
  function asNonEmptyString(value) {
24
44
  if (typeof value !== 'string') {
25
45
  return null;
@@ -63,23 +83,153 @@ function asOutputs(result) {
63
83
  }
64
84
  return [asRecord(result)];
65
85
  }
86
+ function readInteractiveFallbackReason(result) {
87
+ return asNonEmptyString(asRecord(result.provider_meta).parse_fallback_reason);
88
+ }
89
+ function isBlockingAskUserInputOutput(output) {
90
+ const request = asRecord(output.request ?? output);
91
+ const action = asNonEmptyString(request.action ?? request.request_type)?.toLowerCase();
92
+ const prompt = asNonEmptyString(request.prompt);
93
+ return action === 'ask_user_input' && prompt !== null;
94
+ }
66
95
  function makeEmptyResult() {
67
96
  return {
68
97
  planSubmission: false,
98
+ intakeSubmission: false,
69
99
  patchApplied: false,
70
100
  noteLogged: false,
71
101
  requestHandled: false,
102
+ questionRequested: false,
103
+ contextStall: false,
104
+ contextRequestCount: 0,
105
+ lastContextRequestAt: null,
106
+ lastContextRequestRole: null,
72
107
  invalidOutput: false,
108
+ errorCode: null,
73
109
  noProgress: false,
74
110
  outputTypes: [],
75
111
  rawOutputs: [],
76
112
  priorityOrder: [],
77
113
  toolResults: [],
114
+ interactiveOutcome: null,
115
+ checkpoint: null,
116
+ usageRecords: [],
78
117
  };
79
118
  }
119
+ /** No-op decision runner that always returns an empty result with no progress. */
80
120
  export const NOOP_WORKER_DECISION_RUNNER = {
81
121
  execute: () => Promise.resolve(makeEmptyResult()),
82
122
  };
123
+ function normalizeList(values) {
124
+ return Array.from(new Set(values.map((item) => item.trim()).filter((item) => item.length > 0)));
125
+ }
126
+ function readToolFailureDetails(error) {
127
+ if (!error || typeof error !== 'object') {
128
+ return null;
129
+ }
130
+ const direct = asRecord(error.error);
131
+ const normalized = asRecord(asRecord(error.normalizedResponse).error);
132
+ const payload = Object.keys(normalized).length > 0 ? normalized : direct;
133
+ if (Object.keys(payload).length === 0) {
134
+ return null;
135
+ }
136
+ return {
137
+ code: asNonEmptyString(payload.code),
138
+ message: asNonEmptyString(payload.message),
139
+ details: asRecord(payload.details),
140
+ };
141
+ }
142
+ function readAllIntakeAmbiguities(contextBundle) {
143
+ const intake = asRecord(contextBundle.intake);
144
+ const review = asRecord(intake.review);
145
+ const ambiguities = Array.isArray(review.ambiguities) ? review.ambiguities : [];
146
+ const results = [];
147
+ for (const item of ambiguities) {
148
+ const record = asRecord(item);
149
+ const id = asNonEmptyString(record.id);
150
+ const summary = asNonEmptyString(record.summary);
151
+ if (!id || !summary) {
152
+ continue;
153
+ }
154
+ results.push({
155
+ id,
156
+ summary,
157
+ obligationIds: asStringArray(record.obligation_ids),
158
+ });
159
+ }
160
+ return results;
161
+ }
162
+ function readOpenIntakeAmbiguities(contextBundle) {
163
+ const intake = asRecord(contextBundle.intake);
164
+ const review = asRecord(intake.review);
165
+ const openIds = new Set((Array.isArray(review.ambiguities) ? review.ambiguities : [])
166
+ .map((item) => asRecord(item))
167
+ .filter((item) => asNonEmptyString(item.status) === 'open')
168
+ .map((item) => asNonEmptyString(item.id))
169
+ .filter((item) => item !== null));
170
+ return readAllIntakeAmbiguities(contextBundle).filter((item) => openIds.has(item.id));
171
+ }
172
+ function readIntakeAmbiguitiesForRecovery(contextBundle, ambiguityIds) {
173
+ const normalizedIds = normalizeList(ambiguityIds);
174
+ if (normalizedIds.length === 0) {
175
+ return readOpenIntakeAmbiguities(contextBundle);
176
+ }
177
+ const byId = new Map(readAllIntakeAmbiguities(contextBundle).map((item) => [item.id, item]));
178
+ return normalizedIds.map((ambiguityId) => {
179
+ const existing = byId.get(ambiguityId);
180
+ if (existing) {
181
+ return existing;
182
+ }
183
+ return {
184
+ id: ambiguityId,
185
+ summary: 'Clarify this ambiguity before verifying the intake manifest.',
186
+ obligationIds: [],
187
+ };
188
+ });
189
+ }
190
+ function hasOpenIntakeQuestion(contextBundle) {
191
+ const humanInput = asRecord(contextBundle.human_input);
192
+ const openQuestions = Array.isArray(humanInput.open_questions) ? humanInput.open_questions : [];
193
+ return openQuestions.length > 0;
194
+ }
195
+ function readAnsweredIntakeClarifications(contextBundle) {
196
+ const intake = asRecord(contextBundle.intake);
197
+ const review = asRecord(intake.review);
198
+ const clarificationAnswers = Array.isArray(review.clarification_answers)
199
+ ? review.clarification_answers
200
+ : [];
201
+ return clarificationAnswers
202
+ .map((item) => asRecord(item))
203
+ .filter((item) => asStringArray(item.ambiguity_ids).length > 0)
204
+ .map((item) => ({
205
+ questionId: asNonEmptyString(item.question_id) ?? 'unknown',
206
+ ambiguityIds: asStringArray(item.ambiguity_ids),
207
+ answer: typeof item.answer === 'string'
208
+ ? item.answer
209
+ : JSON.stringify(asRecord(item.answer) ?? {}, null, 2),
210
+ answeredAt: asNonEmptyString(item.answered_at),
211
+ }));
212
+ }
213
+ function buildIntakeClarificationPrompt(ambiguities, recoveryReason, priorAnswers) {
214
+ const intro = ambiguities.length === 1
215
+ ? 'Execution planning cannot begin because this intake ambiguity is still unresolved:'
216
+ : 'Execution planning cannot begin because these intake ambiguities are still unresolved:';
217
+ const items = ambiguities.map((ambiguity) => `- ${ambiguity.id}: ${ambiguity.summary}`);
218
+ const priorAnswerLines = ambiguities.flatMap((ambiguity) => priorAnswers
219
+ .filter((answer) => answer.ambiguityIds.includes(ambiguity.id))
220
+ .map((answer) => `- ${ambiguity.id} via ${answer.questionId}${answer.answeredAt ? ` at ${answer.answeredAt}` : ''}: ${answer.answer}`));
221
+ const priorAnswersBlock = priorAnswerLines.length > 0
222
+ ? `\nPrior answered clarification evidence:\n${priorAnswerLines.join('\n')}\nUse this prior answer evidence. Only ask a narrower follow-up if it is still insufficient to resolve the ambiguity.`
223
+ : '';
224
+ return `${intro}\n${items.join('\n')}${priorAnswersBlock}\nRespond in free text and explicitly address each ambiguity ID. Recovery reason: ${recoveryReason}.`;
225
+ }
226
+ /**
227
+ * Core decision loop that drives a single agent worker turn.
228
+ *
229
+ * Invokes the provider, classifies outputs (plans, patches, notes, requests),
230
+ * dispatches tool calls, handles context-refresh retries, and supports both
231
+ * deterministic and interactive execution modes.
232
+ */
83
233
  export class WorkerDecisionLoop {
84
234
  provider;
85
235
  toolCaller;
@@ -87,6 +237,7 @@ export class WorkerDecisionLoop {
87
237
  repoRoot;
88
238
  runId;
89
239
  resolveExecutionModeOverride;
240
+ resolveRuntimeSelectionOverride;
90
241
  resolveInteractiveConfigOverride;
91
242
  watchdog;
92
243
  checkpointService;
@@ -99,17 +250,28 @@ export class WorkerDecisionLoop {
99
250
  this.repoRoot = dependencies.repoRoot ?? null;
100
251
  this.runId = dependencies.runId ?? null;
101
252
  this.resolveExecutionModeOverride = dependencies.resolveExecutionMode;
253
+ this.resolveRuntimeSelectionOverride = dependencies.resolveRuntimeSelection;
102
254
  this.resolveInteractiveConfigOverride = dependencies.resolveInteractiveConfig;
103
255
  this.watchdog = dependencies.watchdog;
104
256
  this.checkpointService = dependencies.checkpointService;
105
257
  this.resolveWorktreePath = dependencies.resolveWorktreePath;
106
258
  this.resolveRoleSessionId = dependencies.resolveRoleSessionId;
107
259
  }
260
+ /**
261
+ * Execute one decision turn: invoke the worker, process all outputs, and
262
+ * optionally retry once on a context-refresh request.
263
+ * @returns Aggregated result describing every action taken and diagnostics.
264
+ */
108
265
  async execute(input) {
109
266
  const result = makeEmptyResult();
267
+ const plannerState = {
268
+ currentPlanVersion: readPlanVersion(asRecord(input.contextBundle.plan).plan_version),
269
+ planMutationApplied: false,
270
+ };
110
271
  if (typeof this.provider.runWorker !== 'function') {
111
272
  return result;
112
273
  }
274
+ const runtimeSelection = await this.resolveRuntimeSelection(input.featureId, input.role);
113
275
  const requestedExecutionMode = await this.resolveExecutionMode(input.featureId, input.role);
114
276
  const interactiveEligible = this.isInteractiveEligible(requestedExecutionMode, input.role);
115
277
  const executionMode = requestedExecutionMode === 'interactive' && interactiveEligible
@@ -128,6 +290,7 @@ export class WorkerDecisionLoop {
128
290
  valid: true,
129
291
  errorCode: null,
130
292
  executionMode,
293
+ runtimeSelection,
131
294
  });
132
295
  }
133
296
  await this.appendWorkerEvent({
@@ -142,16 +305,95 @@ export class WorkerDecisionLoop {
142
305
  valid: true,
143
306
  errorCode: null,
144
307
  executionMode,
308
+ runtimeSelection,
145
309
  });
310
+ let finalRun = await this.runWorkerTurn(input, executionMode, runtimeSelection, interactiveEligible);
311
+ if (finalRun.usage) {
312
+ result.usageRecords.push(finalRun.usage);
313
+ }
314
+ const firstPass = await this.processOutputs({
315
+ input,
316
+ workerRun: finalRun,
317
+ result,
318
+ plannerState,
319
+ allowContextRefreshRetry: true,
320
+ });
321
+ if (firstPass.contextRefreshRequested && firstPass.refreshedContext) {
322
+ finalRun = await this.runWorkerTurn({
323
+ ...input,
324
+ contextBundle: firstPass.refreshedContext,
325
+ lastToolResults: this.buildContextRetryToolResults(input, firstPass.refreshedContext),
326
+ }, executionMode, runtimeSelection, interactiveEligible);
327
+ if (finalRun.usage) {
328
+ result.usageRecords.push(finalRun.usage);
329
+ }
330
+ const secondPass = await this.processOutputs({
331
+ input: {
332
+ ...input,
333
+ contextBundle: firstPass.refreshedContext,
334
+ lastToolResults: this.buildContextRetryToolResults(input, firstPass.refreshedContext),
335
+ },
336
+ workerRun: finalRun,
337
+ result,
338
+ plannerState,
339
+ allowContextRefreshRetry: false,
340
+ });
341
+ if (secondPass.contextRefreshRequested) {
342
+ const hasInteractiveWork = finalRun.interactiveSummary?.hasNetNewWorktreeChanges === true &&
343
+ finalRun.interactiveSummary.changedFiles.length > 0;
344
+ if (!hasInteractiveWork) {
345
+ result.contextStall = true;
346
+ result.errorCode = ERROR_CODES.PROVIDER_CONTEXT_STALL;
347
+ }
348
+ }
349
+ }
350
+ this.finalizeInteractiveOutcome(result, finalRun.interactiveSummary);
351
+ const hasProgress = result.planSubmission ||
352
+ result.intakeSubmission ||
353
+ result.patchApplied ||
354
+ result.requestHandled ||
355
+ result.questionRequested;
356
+ result.noProgress = !hasProgress;
357
+ await this.appendWorkerEvent({
358
+ eventType: 'worker_completed',
359
+ featureId: input.featureId,
360
+ role: input.role,
361
+ outputTypes: result.outputTypes,
362
+ patchCount: result.outputTypes.filter((type) => type === 'PATCH').length,
363
+ planSubmissionCount: result.outputTypes.filter((type) => type === 'PLAN_SUBMISSION' || type === 'INTAKE_SUBMISSION').length,
364
+ requestCount: result.outputTypes.filter((type) => type === 'REQUEST').length,
365
+ noteCount: result.outputTypes.filter((type) => type === 'NOTE').length,
366
+ valid: !result.invalidOutput && result.errorCode === null,
367
+ errorCode: result.errorCode,
368
+ interactiveOutcome: result.interactiveOutcome ?? null,
369
+ checkpointId: result.checkpoint?.checkpoint_id ?? null,
370
+ checkpointDiffHash: typeof result.checkpoint?.diff_hash === 'string' ? result.checkpoint.diff_hash : null,
371
+ checkpointNetNewWorktreeChange: result.checkpoint?.net_new_worktree_change ?? null,
372
+ checkpointValidationStatus: typeof result.checkpoint?.validation_status === 'string'
373
+ ? result.checkpoint.validation_status
374
+ : null,
375
+ executionMode,
376
+ runtimeSelection,
377
+ usage: finalRun.usage,
378
+ });
379
+ if (this.activityMonitor) {
380
+ await this.activityMonitor.checkAndNotifyStuck(input.featureId);
381
+ }
382
+ return result;
383
+ }
384
+ async runWorkerTurn(input, executionMode, runtimeSelection, interactiveEligible) {
146
385
  let workerOutput;
147
386
  let interactiveSummary = null;
148
387
  try {
149
388
  if (interactiveEligible) {
150
- interactiveSummary = await this.runInteractiveWorker(input);
389
+ interactiveSummary =
390
+ input.role === 'planner'
391
+ ? await this.runInteractivePlanner(input, runtimeSelection)
392
+ : await this.runInteractiveWorker(input, runtimeSelection);
151
393
  workerOutput = interactiveSummary.workerOutput;
152
394
  }
153
395
  else {
154
- workerOutput = await this.provider.runWorker(this.buildRunInput(input, executionMode, undefined));
396
+ workerOutput = await this.provider.runWorker(this.buildRunInput(input, executionMode, undefined, runtimeSelection));
155
397
  }
156
398
  }
157
399
  catch (error) {
@@ -188,86 +430,138 @@ export class WorkerDecisionLoop {
188
430
  elapsedMs: typeof typed.details?.elapsed_ms === 'number' ? typed.details.elapsed_ms : undefined,
189
431
  signal: typeof typed.details?.signal === 'string' ? typed.details.signal : null,
190
432
  exitCode: typeof typed.details?.exit_code === 'number' ? typed.details.exit_code : undefined,
433
+ stderr: typeof typed.details?.stderr === 'string' && typed.details.stderr.length > 0
434
+ ? typed.details.stderr
435
+ : undefined,
191
436
  executionMode,
437
+ runtimeSelection,
192
438
  });
193
439
  throw error;
194
440
  }
195
- const outputs = asOutputs(workerOutput);
196
- result.rawOutputs = outputs.map((output) => structuredClone(output));
197
- const allowedTypes = new Set(['PLAN_SUBMISSION', 'PATCH', 'NOTE', 'REQUEST']);
198
- let planSubmissionCount = 0;
199
- let patchCount = 0;
200
- let requestCount = 0;
201
- let noteCount = 0;
441
+ // Extract usage telemetry from provider output (if available).
442
+ const rawUsage = workerOutput.usage;
443
+ const usage = rawUsage &&
444
+ typeof rawUsage === 'object' &&
445
+ 'status' in rawUsage &&
446
+ typeof rawUsage.status === 'string'
447
+ ? rawUsage
448
+ : null;
449
+ return {
450
+ workerOutput,
451
+ interactiveSummary,
452
+ executionMode,
453
+ runtimeSelection,
454
+ usage,
455
+ };
456
+ }
457
+ buildContextRetryToolResults(input, refreshedContext) {
458
+ return [
459
+ ...(input.lastToolResults ?? []),
460
+ {
461
+ tool_name: TOOLS.FEATURE_GET_CONTEXT,
462
+ feature_id: input.featureId,
463
+ refreshed_context: structuredClone(refreshedContext),
464
+ },
465
+ ];
466
+ }
467
+ async processOutputs(input) {
468
+ const { result, plannerState, allowContextRefreshRetry } = input;
469
+ const workerInput = input.input;
470
+ const outputs = asOutputs(input.workerRun.workerOutput);
471
+ result.rawOutputs.push(...outputs.map((output) => structuredClone(output)));
472
+ const blockingQuestionOutput = outputs.find((output) => isBlockingAskUserInputOutput(output));
473
+ if (blockingQuestionOutput) {
474
+ result.outputTypes.push('REQUEST');
475
+ await this.routeRequest(workerInput, blockingQuestionOutput, result, plannerState, allowContextRefreshRetry);
476
+ return { contextRefreshRequested: false, refreshedContext: null };
477
+ }
478
+ const allowedTypes = new Set([
479
+ 'PLAN_SUBMISSION',
480
+ 'INTAKE_SUBMISSION',
481
+ 'PATCH',
482
+ 'NOTE',
483
+ 'REQUEST',
484
+ ]);
202
485
  for (const output of outputs) {
203
486
  const outputType = asNonEmptyString(output.type)?.toUpperCase();
204
487
  if (!outputType) {
205
488
  result.invalidOutput = true;
489
+ result.errorCode = ERROR_CODES.PROVIDER_OUTPUT_INVALID;
490
+ result.interactiveOutcome = input.workerRun.interactiveSummary
491
+ ? 'provider_output_invalid'
492
+ : null;
206
493
  continue;
207
494
  }
208
495
  result.outputTypes.push(outputType);
209
496
  if (!allowedTypes.has(outputType)) {
210
497
  result.invalidOutput = true;
498
+ result.errorCode = ERROR_CODES.PROVIDER_OUTPUT_INVALID;
499
+ result.interactiveOutcome = input.workerRun.interactiveSummary
500
+ ? 'provider_output_invalid'
501
+ : null;
211
502
  continue;
212
503
  }
213
504
  if (outputType === 'PLAN_SUBMISSION') {
214
- planSubmissionCount += 1;
215
- await this.routePlanSubmission(input, output, result);
505
+ await this.routePlanSubmission(workerInput, output, result, plannerState);
506
+ continue;
507
+ }
508
+ if (outputType === 'INTAKE_SUBMISSION') {
509
+ await this.routeIntakeSubmission(workerInput, output, result, plannerState);
216
510
  continue;
217
511
  }
218
512
  if (outputType === 'PATCH') {
219
- patchCount += 1;
220
- if (interactiveSummary) {
221
- const hasPatchPayload = Boolean(asNonEmptyString(output.unified_diff ?? output.diff));
222
- if (hasPatchPayload) {
223
- result.patchApplied = true;
224
- }
225
- }
226
- else {
227
- await this.routePatch(input, output, result);
513
+ if (!input.workerRun.interactiveSummary) {
514
+ await this.routePatch(workerInput, output, result);
228
515
  }
229
516
  continue;
230
517
  }
231
518
  if (outputType === 'NOTE') {
232
- noteCount += 1;
233
- await this.routeNote(input.featureId, output, result);
519
+ if (input.workerRun.interactiveSummary &&
520
+ input.workerRun.interactiveSummary.fallbackReason !== null &&
521
+ !input.workerRun.interactiveSummary.hasNetNewWorktreeChanges) {
522
+ result.invalidOutput = true;
523
+ result.errorCode = ERROR_CODES.PROVIDER_OUTPUT_INVALID;
524
+ result.interactiveOutcome = 'provider_output_invalid';
525
+ continue;
526
+ }
527
+ await this.routeNote(workerInput.featureId, output, result);
234
528
  continue;
235
529
  }
236
- if (outputType === 'REQUEST') {
237
- requestCount += 1;
238
- await this.routeRequest(input, output, result);
530
+ const requestResult = await this.routeRequest(workerInput, output, result, plannerState, allowContextRefreshRetry);
531
+ if (requestResult.contextRefreshRequested) {
532
+ return requestResult;
239
533
  }
240
534
  }
241
- if (interactiveSummary) {
535
+ return { contextRefreshRequested: false, refreshedContext: null };
536
+ }
537
+ finalizeInteractiveOutcome(result, interactiveSummary) {
538
+ if (!interactiveSummary) {
539
+ return;
540
+ }
541
+ result.checkpoint = structuredClone(interactiveSummary.finalCheckpoint);
542
+ if (interactiveSummary.finalCheckpoint) {
242
543
  result.toolResults.push({
243
544
  checkpoint: structuredClone(interactiveSummary.finalCheckpoint),
244
545
  });
245
- if (interactiveSummary.changedFiles.length > 0) {
246
- result.patchApplied = true;
247
- }
248
- if (interactiveSummary.checkpointInvalid) {
249
- result.invalidOutput = true;
250
- }
251
546
  }
252
- const hasProgress = result.planSubmission || result.patchApplied || result.requestHandled;
253
- result.noProgress = !hasProgress;
254
- await this.appendWorkerEvent({
255
- eventType: 'worker_completed',
256
- featureId: input.featureId,
257
- role: input.role,
258
- outputTypes: result.outputTypes,
259
- patchCount,
260
- planSubmissionCount,
261
- requestCount,
262
- noteCount,
263
- valid: !result.invalidOutput,
264
- errorCode: result.invalidOutput ? ERROR_CODES.PROVIDER_OUTPUT_INVALID : null,
265
- executionMode,
266
- });
267
- if (this.activityMonitor) {
268
- await this.activityMonitor.checkAndNotifyStuck(input.featureId);
547
+ if (interactiveSummary.finalCheckpoint &&
548
+ interactiveSummary.hasNetNewWorktreeChanges &&
549
+ interactiveSummary.changedFiles.length > 0) {
550
+ result.patchApplied = true;
551
+ }
552
+ if (interactiveSummary.checkpointInvalid) {
553
+ result.errorCode = ERROR_CODES.INTERACTIVE_CHECKPOINT_INVALID;
554
+ result.interactiveOutcome = 'checkpoint_invalid';
555
+ }
556
+ else if (result.invalidOutput) {
557
+ result.interactiveOutcome = 'provider_output_invalid';
558
+ }
559
+ else if (result.patchApplied) {
560
+ result.interactiveOutcome = 'progress_applied';
561
+ }
562
+ else if (!result.planSubmission && !result.requestHandled && !result.questionRequested) {
563
+ result.interactiveOutcome = 'no_new_work';
269
564
  }
270
- return result;
271
565
  }
272
566
  async resolveExecutionMode(featureId, role) {
273
567
  if (this.resolveExecutionModeOverride) {
@@ -275,21 +569,33 @@ export class WorkerDecisionLoop {
275
569
  }
276
570
  return 'deterministic';
277
571
  }
572
+ async resolveRuntimeSelection(featureId, role) {
573
+ if (this.resolveRuntimeSelectionOverride) {
574
+ return await this.resolveRuntimeSelectionOverride(featureId, role);
575
+ }
576
+ return this.provider.selection;
577
+ }
278
578
  isInteractiveEligible(executionMode, role) {
279
579
  if (executionMode !== 'interactive') {
280
580
  return false;
281
581
  }
282
- if (role !== 'builder' && role !== 'qa') {
582
+ const capabilities = this.provider.getCapabilities?.();
583
+ const supportsInteractive = !capabilities
584
+ ? true
585
+ : capabilities.supportsInteractiveMode && capabilities.supportsWorkingDirectory;
586
+ if (!supportsInteractive) {
283
587
  return false;
284
588
  }
285
- if (!this.repoRoot || !this.watchdog || !this.checkpointService || !this.resolveWorktreePath) {
589
+ if (role === 'planner') {
590
+ return Boolean(this.repoRoot);
591
+ }
592
+ if (role !== 'builder' && role !== 'qa' && role !== 'reconciler') {
286
593
  return false;
287
594
  }
288
- const capabilities = this.provider.getCapabilities?.();
289
- if (!capabilities) {
290
- return true;
595
+ if (!this.repoRoot || !this.watchdog || !this.checkpointService || !this.resolveWorktreePath) {
596
+ return false;
291
597
  }
292
- return capabilities.supportsInteractiveMode && capabilities.supportsWorkingDirectory;
598
+ return true;
293
599
  }
294
600
  resolveInteractiveConfig() {
295
601
  if (this.resolveInteractiveConfigOverride) {
@@ -304,31 +610,38 @@ export class WorkerDecisionLoop {
304
610
  violationSeverity: 'warning',
305
611
  };
306
612
  }
307
- buildRunInput(input, executionMode, workingDirectory) {
613
+ buildRunInput(input, executionMode, workingDirectory, runtimeSelection) {
308
614
  return {
309
615
  role: input.role,
310
616
  feature_id: input.featureId,
617
+ ...(input.role === 'planner'
618
+ ? { planner_phase: resolvePlannerPhaseFromContext(input.contextBundle) }
619
+ : {}),
311
620
  context_bundle: input.contextBundle,
312
- instructions: input.instructions,
621
+ instructions: this.resolvePromptInstructions(input, executionMode),
313
622
  last_tool_results: input.lastToolResults ?? [],
314
623
  runtime_selection: {
315
- provider: this.provider.selection.provider,
316
- model: this.provider.selection.model,
317
- provider_config_ref: this.provider.selection.provider_config_ref,
624
+ provider: runtimeSelection.provider,
625
+ model: runtimeSelection.model,
626
+ provider_config_env: runtimeSelection.provider_config_env ?? null,
627
+ provider_config_ref: runtimeSelection.provider_config_ref,
628
+ agent_config: runtimeSelection.agent_config ?? null,
318
629
  },
319
630
  execution_mode: executionMode,
320
631
  working_directory: workingDirectory,
321
632
  pause_resume_protocol: 'none',
322
633
  };
323
634
  }
324
- async runInteractiveWorker(input) {
635
+ async runInteractiveWorker(input, runtimeSelection) {
325
636
  if (!this.repoRoot || !this.watchdog || !this.checkpointService || !this.resolveWorktreePath) {
326
- const fallbackOutput = await this.provider.runWorker(this.buildRunInput(input, 'deterministic', undefined));
637
+ const fallbackOutput = await this.provider.runWorker(this.buildRunInput(input, 'deterministic', undefined, runtimeSelection));
327
638
  return {
328
639
  workerOutput: fallbackOutput,
329
640
  finalCheckpoint: this.createSyntheticCheckpoint(input.featureId),
330
641
  changedFiles: [],
642
+ hasNetNewWorktreeChanges: false,
331
643
  checkpointInvalid: false,
644
+ fallbackReason: readInteractiveFallbackReason(fallbackOutput),
332
645
  };
333
646
  }
334
647
  const interactiveConfig = this.resolveInteractiveConfig();
@@ -343,6 +656,7 @@ export class WorkerDecisionLoop {
343
656
  });
344
657
  let latestCheckpoint = null;
345
658
  let checkpointInvalid = false;
659
+ let lastCheckpointFailureReason = null;
346
660
  let lastCheckpointAt = 0;
347
661
  const checkpointDebounceMs = 5_000;
348
662
  let checkpointQueue = Promise.resolve();
@@ -360,11 +674,15 @@ export class WorkerDecisionLoop {
360
674
  });
361
675
  if (checkpoint) {
362
676
  latestCheckpoint = checkpoint.checkpoint;
363
- checkpointInvalid = checkpointInvalid || !checkpoint.valid || checkpoint.blockMerge;
677
+ checkpointInvalid = checkpointInvalid || checkpoint.blockMerge;
364
678
  }
365
679
  }
366
- catch {
680
+ catch (checkpointError) {
367
681
  checkpointInvalid = true;
682
+ lastCheckpointFailureReason =
683
+ checkpointError instanceof Error
684
+ ? checkpointError.message
685
+ : (extractNonErrorMessage(checkpointError) ?? 'checkpoint creation failed');
368
686
  }
369
687
  finally {
370
688
  lastCheckpointAt = Date.now();
@@ -385,14 +703,18 @@ export class WorkerDecisionLoop {
385
703
  }, interactiveConfig.checkpointIntervalMs);
386
704
  timer.unref?.();
387
705
  try {
388
- const workerOutput = await this.provider.runWorker(this.buildRunInput(input, 'interactive', worktreePath));
706
+ const workerOutput = await this.provider.runWorker(this.buildRunInput(input, 'interactive', worktreePath, runtimeSelection));
389
707
  await enqueueCheckpoint('final');
390
708
  const changedFiles = latestCheckpoint?.files_changed ?? [];
709
+ const hasNetNewWorktreeChanges = latestCheckpoint?.net_new_worktree_change === true;
391
710
  return {
392
711
  workerOutput,
393
- finalCheckpoint: latestCheckpoint ?? this.createSyntheticCheckpoint(input.featureId),
712
+ finalCheckpoint: latestCheckpoint ??
713
+ this.createSyntheticCheckpoint(input.featureId, lastCheckpointFailureReason),
394
714
  changedFiles,
715
+ hasNetNewWorktreeChanges,
395
716
  checkpointInvalid,
717
+ fallbackReason: readInteractiveFallbackReason(workerOutput),
396
718
  };
397
719
  }
398
720
  finally {
@@ -402,33 +724,119 @@ export class WorkerDecisionLoop {
402
724
  await this.watchdog.stopWatching(input.featureId);
403
725
  }
404
726
  }
405
- createSyntheticCheckpoint(featureId) {
727
+ createSyntheticCheckpoint(featureId, failureReason = null) {
406
728
  return {
407
729
  checkpoint_id: `checkpoint-synthetic-${Date.now()}`,
408
730
  timestamp: new Date().toISOString(),
409
731
  files_changed: [],
410
- validation_status: 'skipped',
411
- violations: [],
732
+ validation_status: failureReason ? 'invalid' : 'skipped',
733
+ violations: failureReason ? [failureReason] : [],
412
734
  diff_snapshot: `.aop/features/${featureId}/checkpoints/synthetic.diff`,
735
+ net_new_worktree_change: false,
736
+ };
737
+ }
738
+ async runInteractivePlanner(input, runtimeSelection) {
739
+ const workerOutput = await this.provider.runWorker(this.buildRunInput(input, 'interactive', this.resolvePlannerWorkingDirectory(input.featureId), runtimeSelection));
740
+ return {
741
+ workerOutput,
742
+ finalCheckpoint: null,
743
+ changedFiles: [],
744
+ hasNetNewWorktreeChanges: false,
745
+ checkpointInvalid: false,
746
+ fallbackReason: readInteractiveFallbackReason(workerOutput),
413
747
  };
414
748
  }
415
- async routePlanSubmission(input, output, result) {
749
+ resolvePromptInstructions(input, executionMode) {
750
+ const baseInstructions = input.instructions.trim();
751
+ if (executionMode !== 'interactive') {
752
+ return baseInstructions;
753
+ }
754
+ if (input.role === 'builder' || input.role === 'qa' || input.role === 'reconciler') {
755
+ const interactiveOverride = input.role === 'builder'
756
+ ? [
757
+ 'Interactive mode override:',
758
+ '- Edit planned files directly in the working directory.',
759
+ '- Ignore any generic instruction that asks you to emit PATCH or unified diff output.',
760
+ '- Use the accepted plan, allowed areas, planned file list, and latest evidence in the context summary below as your execution contract.',
761
+ '- Return NOTE only after making planned file changes.',
762
+ '- If the safe fix surface exceeds the accepted plan, return REQUEST.action=more_context with a concrete blocker.',
763
+ '- Use ask_user_input only for genuine human decisions, approvals, or policy exceptions you cannot resolve from the plan and repo.',
764
+ ].join('\n')
765
+ : input.role === 'qa'
766
+ ? [
767
+ 'Interactive mode override:',
768
+ '- Edit files directly in the working directory.',
769
+ '- Ignore any generic instruction that asks you to emit PATCH or unified diff output.',
770
+ '- Use the accepted plan, qa_test_index, and latest evidence in the context summary below as your verification contract.',
771
+ '- Return NOTE only after making file changes that address a reproduced failure or verification gap.',
772
+ '- Use more_context/context_refresh only when evidence is stale or the accepted plan does not authorize the safe fix surface.',
773
+ '- Use ask_user_input only for genuine operator decisions, approvals, or risk acknowledgements.',
774
+ ].join('\n')
775
+ : [
776
+ 'Interactive mode override:',
777
+ '- Edit files directly in the conflicted worktree.',
778
+ '- Ignore any generic instruction that asks you to emit PATCH or unified diff output.',
779
+ '- Use the spec, accepted plan, conflict status, approved collision context, and latest evidence in the context summary below as your reconciliation contract.',
780
+ '- Return NOTE only after resolving conflicted files and performing proportionate verification.',
781
+ '- Use more_context/context_refresh only when the conflict snapshot or surrounding repo state is stale.',
782
+ '- Use ask_user_input only when preserving mainline semantics and feature intent requires an operator choice.',
783
+ ].join('\n');
784
+ return baseInstructions.length > 0
785
+ ? `${interactiveOverride}\n\nAdditional task context:\n${baseInstructions}`
786
+ : interactiveOverride;
787
+ }
788
+ if (input.role === 'planner') {
789
+ const plannerOverride = resolvePlannerPhaseFromContext(input.contextBundle) === 'intake'
790
+ ? [
791
+ 'Interactive mode override:',
792
+ '- Read and update the intake artifacts directly on disk.',
793
+ '- Emit INTAKE_SUBMISSION when the verified manifest is ready.',
794
+ '- Emit REQUEST.action=ask_user_input only for blocking requirement clarification.',
795
+ '- If you ask for user input, stop there for the turn and wait for the persisted answer before promoting the manifest.',
796
+ '- Never self-assert human_review_confirmed without an answered manifest-review confirmation question in context.',
797
+ '- Return NOTE only when you intentionally keep intake unchanged and can justify that decision from the observed feature state.',
798
+ ].join('\n')
799
+ : [
800
+ 'Interactive mode override:',
801
+ '- Read and update the planning artifacts directly on disk.',
802
+ '- Emit PLAN_SUBMISSION or REQUEST.action=amend_plan when the accepted plan must change.',
803
+ '- Return NOTE only when you intentionally keep the accepted plan unchanged and can justify that decision from the observed feature state.',
804
+ ].join('\n');
805
+ return baseInstructions.length > 0
806
+ ? `${plannerOverride}\n\nAdditional task context:\n${baseInstructions}`
807
+ : plannerOverride;
808
+ }
809
+ return baseInstructions;
810
+ }
811
+ resolvePlannerWorkingDirectory(featureId) {
812
+ if (!this.repoRoot) {
813
+ return undefined;
814
+ }
815
+ return path.join(this.repoRoot, '.aop', 'features', featureId);
816
+ }
817
+ async routePlanSubmission(input, output, result, plannerState) {
416
818
  if (input.role !== 'planner') {
417
819
  return;
418
820
  }
821
+ if (plannerState.planMutationApplied) {
822
+ return;
823
+ }
419
824
  const planJson = sanitizePlannerPlan(asRecord(output.plan_json ?? output.plan));
420
825
  if (Object.keys(planJson).length === 0) {
421
826
  return;
422
827
  }
423
- const contextPlan = asRecord(input.contextBundle.plan);
424
- const existingVersion = readPlanVersion(contextPlan.plan_version);
828
+ if ((await this.requestIntakeClarificationForPlanMutation(input, result, ERROR_CODES.VERIFIED_MANIFEST_REQUIRED)) === true) {
829
+ return;
830
+ }
425
831
  const requestedExpectedVersion = readPlanVersion(output.expected_plan_version);
832
+ const existingVersion = plannerState.currentPlanVersion;
426
833
  if (existingVersion == null) {
427
834
  const response = await this.toolCaller.callTool('planner', TOOLS.PLAN_SUBMIT, {
428
835
  feature_id: input.featureId,
429
836
  plan_json: planJson,
430
837
  });
431
838
  result.toolResults.push(asRecord(response.data));
839
+ this.recordPlannerMutation(plannerState, response.data, planJson);
432
840
  result.planSubmission = true;
433
841
  return;
434
842
  }
@@ -439,10 +847,73 @@ export class WorkerDecisionLoop {
439
847
  plan_json: planJson,
440
848
  });
441
849
  result.toolResults.push(asRecord(response.data));
850
+ this.recordPlannerMutation(plannerState, response.data, planJson);
442
851
  result.planSubmission = true;
443
852
  }
853
+ async routeIntakeSubmission(input, output, result, plannerState) {
854
+ if (input.role !== 'planner' || plannerState.planMutationApplied) {
855
+ return;
856
+ }
857
+ const intakeSubmission = asRecord(output.intake_submission);
858
+ if (!intakeSubmission) {
859
+ return;
860
+ }
861
+ try {
862
+ const response = await this.toolCaller.callTool('planner', TOOLS.FEATURE_INTAKE_SUBMIT, {
863
+ feature_id: input.featureId,
864
+ intake_submission: intakeSubmission,
865
+ });
866
+ result.toolResults.push(asRecord(response.data));
867
+ result.intakeSubmission = true;
868
+ }
869
+ catch (error) {
870
+ const failure = readToolFailureDetails(error);
871
+ const plannerPhase = resolvePlannerPhaseFromContext(input.contextBundle);
872
+ if (failure?.code !== ERROR_CODES.INTAKE_SUBMISSION_INVALID || plannerPhase !== 'intake') {
873
+ throw error;
874
+ }
875
+ const ambiguityIds = normalizeList([
876
+ ...asStringArray(failure.details.missing_ambiguity_evidence_ids),
877
+ ...asStringArray(failure.details.open_ambiguity_ids),
878
+ ]);
879
+ if (!hasOpenIntakeQuestion(input.contextBundle)) {
880
+ const ambiguities = readIntakeAmbiguitiesForRecovery(input.contextBundle, ambiguityIds);
881
+ const priorAnswers = readAnsweredIntakeClarifications(input.contextBundle).filter((answer) => ambiguityIds.length === 0 ||
882
+ answer.ambiguityIds.some((ambiguityId) => ambiguityIds.includes(ambiguityId)));
883
+ const sessionId = this.resolveRoleSessionId?.(input.role, input.featureId) ?? `bootstrap:${input.role}`;
884
+ const response = await this.toolCaller.callTool('orchestrator', TOOLS.FEATURE_QUESTION_CREATE, {
885
+ feature_id: input.featureId,
886
+ role: 'planner',
887
+ session_id: sessionId,
888
+ question_type: 'clarification',
889
+ prompt: buildIntakeClarificationPrompt(ambiguities, failure.code ?? ERROR_CODES.INTAKE_SUBMISSION_INVALID, priorAnswers),
890
+ details: {
891
+ ambiguity_ids: ambiguities.map((ambiguity) => ambiguity.id),
892
+ obligation_ids: normalizeList(ambiguities.flatMap((ambiguity) => ambiguity.obligationIds)),
893
+ prior_answered_ambiguity_ids: ambiguities
894
+ .filter((ambiguity) => priorAnswers.some((answer) => answer.ambiguityIds.includes(ambiguity.id)))
895
+ .map((ambiguity) => ambiguity.id),
896
+ recovery_reason: failure.code ?? ERROR_CODES.INTAKE_SUBMISSION_INVALID,
897
+ recovery_source: 'intake_submission_validation',
898
+ validation_message: failure.message,
899
+ },
900
+ expected_answer: {
901
+ kind: 'free_text',
902
+ },
903
+ blocking: true,
904
+ phase: STATUS.INTAKE,
905
+ request_action: 'ask_user_input',
906
+ resume_status: STATUS.INTAKE,
907
+ resume_phase: STATUS.INTAKE,
908
+ });
909
+ result.toolResults.push(asRecord(response.data));
910
+ }
911
+ result.requestHandled = true;
912
+ result.questionRequested = true;
913
+ }
914
+ }
444
915
  async routePatch(input, output, result) {
445
- if (input.role !== 'builder' && input.role !== 'qa') {
916
+ if (input.role !== 'builder' && input.role !== 'qa' && input.role !== 'reconciler') {
446
917
  return;
447
918
  }
448
919
  const unifiedDiff = asNonEmptyString(output.unified_diff ?? output.diff);
@@ -470,11 +941,11 @@ export class WorkerDecisionLoop {
470
941
  // Global logs are best-effort for parity with prior orphan-session logging.
471
942
  }
472
943
  }
473
- async routeRequest(input, output, result) {
944
+ async routeRequest(input, output, result, plannerState, allowContextRefreshRetry) {
474
945
  const request = asRecord(output.request ?? output);
475
946
  const action = asNonEmptyString(request.action ?? request.request_type)?.toLowerCase();
476
947
  if (!action) {
477
- return;
948
+ return { contextRefreshRequested: false, refreshedContext: null };
478
949
  }
479
950
  if (action === 'prioritize') {
480
951
  const featureOrder = asStringArray(request.feature_order);
@@ -482,12 +953,12 @@ export class WorkerDecisionLoop {
482
953
  result.priorityOrder = featureOrder;
483
954
  result.requestHandled = true;
484
955
  }
485
- return;
956
+ return { contextRefreshRequested: false, refreshedContext: null };
486
957
  }
487
958
  if (action === 'lock_acquire') {
488
959
  const resources = asStringArray(request.resources);
489
960
  if (resources.length === 0) {
490
- return;
961
+ return { contextRefreshRequested: false, refreshedContext: null };
491
962
  }
492
963
  const response = await this.toolCaller.callTool('orchestrator', TOOLS.LOCKS_ACQUIRE, {
493
964
  feature_id: input.featureId,
@@ -495,12 +966,12 @@ export class WorkerDecisionLoop {
495
966
  });
496
967
  result.toolResults.push(asRecord(response.data));
497
968
  result.requestHandled = true;
498
- return;
969
+ return { contextRefreshRequested: false, refreshedContext: null };
499
970
  }
500
971
  if (action === 'lock_release') {
501
972
  const resources = asStringArray(request.resources);
502
973
  if (resources.length === 0) {
503
- return;
974
+ return { contextRefreshRequested: false, refreshedContext: null };
504
975
  }
505
976
  const response = await this.toolCaller.callTool('orchestrator', TOOLS.LOCKS_RELEASE, {
506
977
  feature_id: input.featureId,
@@ -508,33 +979,89 @@ export class WorkerDecisionLoop {
508
979
  });
509
980
  result.toolResults.push(asRecord(response.data));
510
981
  result.requestHandled = true;
511
- return;
982
+ return { contextRefreshRequested: false, refreshedContext: null };
512
983
  }
513
984
  if (action === 'more_context' || action === 'context_refresh') {
985
+ result.contextRequestCount += 1;
986
+ result.lastContextRequestAt = new Date().toISOString();
987
+ result.lastContextRequestRole = input.role;
988
+ if (!allowContextRefreshRetry) {
989
+ return { contextRefreshRequested: true, refreshedContext: null };
990
+ }
514
991
  const response = await this.toolCaller.callTool(input.role, TOOLS.FEATURE_GET_CONTEXT, {
515
992
  feature_id: input.featureId,
516
993
  });
517
994
  result.toolResults.push(asRecord(response.data));
995
+ this.refreshPlannerStateFromContext(plannerState, response.data);
996
+ return {
997
+ contextRefreshRequested: true,
998
+ refreshedContext: asRecord(response.data) ?? {},
999
+ };
1000
+ }
1001
+ if (action === 'ask_user_input') {
1002
+ const prompt = asNonEmptyString(request.prompt);
1003
+ if (!prompt) {
1004
+ return { contextRefreshRequested: false, refreshedContext: null };
1005
+ }
1006
+ const sessionId = this.resolveRoleSessionId?.(input.role, input.featureId) ?? `bootstrap:${input.role}`;
1007
+ const currentStatus = asNonEmptyString(asRecord(asRecord(input.contextBundle.state).front_matter).status);
1008
+ const plannerPhase = input.role === 'planner' ? resolvePlannerPhaseFromContext(input.contextBundle) : 'planning';
1009
+ const response = await this.toolCaller.callTool('orchestrator', TOOLS.FEATURE_QUESTION_CREATE, {
1010
+ feature_id: input.featureId,
1011
+ role: input.role,
1012
+ session_id: sessionId,
1013
+ question_type: asNonEmptyString(request.question_type) ?? 'clarification',
1014
+ prompt,
1015
+ details: asRecord(request.details) ?? {},
1016
+ expected_answer: asRecord(request.expected_answer) ?? undefined,
1017
+ blocking: request.blocking !== false,
1018
+ phase: plannerPhase === 'intake' ? STATUS.INTAKE : (currentStatus ?? input.role),
1019
+ request_action: action,
1020
+ resume_status: plannerPhase === 'intake' ? STATUS.INTAKE : undefined,
1021
+ resume_phase: plannerPhase === 'intake' ? STATUS.INTAKE : undefined,
1022
+ });
1023
+ result.toolResults.push(asRecord(response.data));
518
1024
  result.requestHandled = true;
519
- return;
1025
+ result.questionRequested = true;
1026
+ try {
1027
+ await this.toolCaller.callTool('orchestrator', TOOLS.FEATURE_LOG_APPEND, {
1028
+ feature_id: input.featureId,
1029
+ note: JSON.stringify({
1030
+ action,
1031
+ question_id: asRecord(response.data)?.question_id ?? null,
1032
+ role: input.role,
1033
+ prompt,
1034
+ }),
1035
+ });
1036
+ }
1037
+ catch (_error) {
1038
+ // Best effort log for observability.
1039
+ }
1040
+ return { contextRefreshRequested: false, refreshedContext: null };
520
1041
  }
521
1042
  if (action === 'amend_plan' && input.role === 'planner') {
1043
+ if (plannerState.planMutationApplied) {
1044
+ return { contextRefreshRequested: false, refreshedContext: null };
1045
+ }
522
1046
  const planJson = sanitizePlannerPlan(asRecord(request.plan_json));
523
1047
  if (Object.keys(planJson).length === 0) {
524
- return;
1048
+ return { contextRefreshRequested: false, refreshedContext: null };
1049
+ }
1050
+ if ((await this.requestIntakeClarificationForPlanMutation(input, result, ERROR_CODES.VERIFIED_MANIFEST_REQUIRED)) === true) {
1051
+ return { contextRefreshRequested: false, refreshedContext: null };
525
1052
  }
526
- const contextPlan = asRecord(input.contextBundle.plan);
527
- const existingVersion = readPlanVersion(contextPlan.plan_version);
528
1053
  const requestedExpectedVersion = readPlanVersion(request.expected_plan_version);
1054
+ const existingVersion = plannerState.currentPlanVersion;
529
1055
  if (existingVersion == null) {
530
1056
  const response = await this.toolCaller.callTool('planner', TOOLS.PLAN_SUBMIT, {
531
1057
  feature_id: input.featureId,
532
1058
  plan_json: planJson,
533
1059
  });
534
1060
  result.toolResults.push(asRecord(response.data));
1061
+ this.recordPlannerMutation(plannerState, response.data, planJson);
535
1062
  result.requestHandled = true;
536
1063
  result.planSubmission = true;
537
- return;
1064
+ return { contextRefreshRequested: false, refreshedContext: null };
538
1065
  }
539
1066
  const response = await this.toolCaller.callTool('planner', TOOLS.PLAN_UPDATE, {
540
1067
  feature_id: input.featureId,
@@ -542,8 +1069,100 @@ export class WorkerDecisionLoop {
542
1069
  plan_json: planJson,
543
1070
  });
544
1071
  result.toolResults.push(asRecord(response.data));
1072
+ this.recordPlannerMutation(plannerState, response.data, planJson);
545
1073
  result.requestHandled = true;
546
1074
  result.planSubmission = true;
1075
+ return { contextRefreshRequested: false, refreshedContext: null };
1076
+ }
1077
+ try {
1078
+ await this.toolCaller.callTool('orchestrator', TOOLS.FEATURE_LOG_APPEND, {
1079
+ feature_id: input.featureId,
1080
+ note: JSON.stringify({
1081
+ action: 'unknown_request_action',
1082
+ requested_action: action,
1083
+ role: input.role,
1084
+ }),
1085
+ });
1086
+ }
1087
+ catch (_error) {
1088
+ // Best effort observability for unknown actions.
1089
+ }
1090
+ return { contextRefreshRequested: false, refreshedContext: null };
1091
+ }
1092
+ async requestIntakeClarificationForPlanMutation(input, result, recoveryReason) {
1093
+ if (input.role !== 'planner' ||
1094
+ resolvePlannerPhaseFromContext(input.contextBundle) !== 'intake') {
1095
+ return false;
1096
+ }
1097
+ const verifiedManifest = asRecord(asRecord(input.contextBundle.intake).verified_manifest);
1098
+ if (Object.keys(verifiedManifest).length > 0) {
1099
+ return false;
1100
+ }
1101
+ if (hasOpenIntakeQuestion(input.contextBundle)) {
1102
+ result.requestHandled = true;
1103
+ return true;
1104
+ }
1105
+ const ambiguities = readOpenIntakeAmbiguities(input.contextBundle);
1106
+ const priorAnswers = readAnsweredIntakeClarifications(input.contextBundle);
1107
+ if (ambiguities.length === 0) {
1108
+ result.requestHandled = true;
1109
+ return true;
1110
+ }
1111
+ const sessionId = this.resolveRoleSessionId?.(input.role, input.featureId) ?? `bootstrap:${input.role}`;
1112
+ const response = await this.toolCaller.callTool('orchestrator', TOOLS.FEATURE_QUESTION_CREATE, {
1113
+ feature_id: input.featureId,
1114
+ role: input.role,
1115
+ session_id: sessionId,
1116
+ question_type: 'clarification',
1117
+ prompt: buildIntakeClarificationPrompt(ambiguities, recoveryReason, priorAnswers),
1118
+ details: {
1119
+ ambiguity_ids: ambiguities.map((ambiguity) => ambiguity.id),
1120
+ obligation_ids: ambiguities.flatMap((ambiguity) => ambiguity.obligationIds),
1121
+ recovery_reason: recoveryReason,
1122
+ recovery_source: 'worker_decision_loop',
1123
+ },
1124
+ expected_answer: {
1125
+ kind: 'free_text',
1126
+ },
1127
+ blocking: true,
1128
+ phase: STATUS.INTAKE,
1129
+ request_action: 'ask_user_input',
1130
+ resume_status: STATUS.INTAKE,
1131
+ resume_phase: STATUS.INTAKE,
1132
+ });
1133
+ result.toolResults.push(asRecord(response.data));
1134
+ result.requestHandled = true;
1135
+ result.questionRequested = true;
1136
+ try {
1137
+ await this.toolCaller.callTool('orchestrator', TOOLS.FEATURE_LOG_APPEND, {
1138
+ feature_id: input.featureId,
1139
+ note: JSON.stringify({
1140
+ action: 'ask_user_input',
1141
+ question_id: asRecord(response.data)?.question_id ?? null,
1142
+ role: input.role,
1143
+ recovery_reason: recoveryReason,
1144
+ recovery_source: 'worker_decision_loop',
1145
+ ambiguity_ids: ambiguities.map((ambiguity) => ambiguity.id),
1146
+ }),
1147
+ });
1148
+ }
1149
+ catch (_error) {
1150
+ // Best effort observability for intake rerouting.
1151
+ }
1152
+ return true;
1153
+ }
1154
+ refreshPlannerStateFromContext(plannerState, context) {
1155
+ const refreshedPlanVersion = readPlanVersion(asRecord(asRecord(context).plan).plan_version);
1156
+ if (refreshedPlanVersion != null) {
1157
+ plannerState.currentPlanVersion = refreshedPlanVersion;
1158
+ }
1159
+ }
1160
+ recordPlannerMutation(plannerState, responseData, planJson) {
1161
+ plannerState.planMutationApplied = true;
1162
+ const acceptedPlanVersion = readPlanVersion(asRecord(responseData).plan_version) ??
1163
+ readPlanVersion(planJson.plan_version);
1164
+ if (acceptedPlanVersion != null) {
1165
+ plannerState.currentPlanVersion = acceptedPlanVersion;
547
1166
  }
548
1167
  }
549
1168
  resolveRunId() {
@@ -576,8 +1195,22 @@ export class WorkerDecisionLoop {
576
1195
  note_count: event.noteCount,
577
1196
  valid: event.valid,
578
1197
  error_code: event.errorCode,
579
- provider: this.provider.selection.provider,
580
- model: this.provider.selection.model,
1198
+ interactive_outcome: event.interactiveOutcome ?? null,
1199
+ checkpoint_id: event.checkpointId ?? null,
1200
+ checkpoint_diff_hash: event.checkpointDiffHash ?? null,
1201
+ checkpoint_net_new_worktree_change: event.checkpointNetNewWorktreeChange ?? null,
1202
+ checkpoint_validation_status: event.checkpointValidationStatus ?? null,
1203
+ provider: event.runtimeSelection.provider,
1204
+ model: event.runtimeSelection.model,
1205
+ usage: event.usage
1206
+ ? {
1207
+ status: event.usage.status,
1208
+ input_tokens: event.usage.input_tokens,
1209
+ output_tokens: event.usage.output_tokens,
1210
+ total_tokens: event.usage.total_tokens,
1211
+ estimated_cost_usd: event.usage.estimated_cost_usd,
1212
+ }
1213
+ : null,
581
1214
  watchdog_reason: event.watchdogReason ?? null,
582
1215
  timeout_ms: event.timeoutMs,
583
1216
  idle_timeout_ms: event.idleTimeoutMs,
@@ -586,6 +1219,7 @@ export class WorkerDecisionLoop {
586
1219
  elapsed_ms: event.elapsedMs,
587
1220
  signal: event.signal ?? null,
588
1221
  exit_code: event.exitCode,
1222
+ stderr: event.stderr,
589
1223
  };
590
1224
  await appendWorkerRuntimeEvent({
591
1225
  repoRoot: this.repoRoot,