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,11 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
1
3
  import { STATUS, TOOLS } from '../core/constants.js';
2
4
  import { ERROR_CODES } from '../core/error-codes.js';
5
+ import { normalizeManifestConfidence, obligationsMeetConfidenceThreshold, validatePlanTraceAgainstObligationIds, } from '../core/intake-artifacts.js';
6
+ import { assessGateFreshness, readCheckpointValidity, readGateEvidenceByMode, } from '../core/gate-freshness.js';
7
+ import { extractGateLog } from '../core/gate-log-extractor.js';
8
+ import { resolvePlannerPhaseFromContext } from './planner-phase.js';
3
9
  import { NOOP_WORKER_DECISION_RUNNER, } from './worker-decision-loop.js';
4
10
  import { appendWorkerRuntimeEvent } from './worker-event-journal.js';
5
11
  function asRecord(value) {
@@ -34,6 +40,12 @@ function normalizeList(values) {
34
40
  }
35
41
  return normalized;
36
42
  }
43
+ function asString(value) {
44
+ return typeof value === 'string' && value.length > 0 ? value : null;
45
+ }
46
+ function asNumber(value) {
47
+ return typeof value === 'number' && Number.isFinite(value) ? value : null;
48
+ }
37
49
  function readCount(summary, key) {
38
50
  const raw = summary[key];
39
51
  if (typeof raw !== 'number' || !Number.isFinite(raw) || raw < 0) {
@@ -44,6 +56,29 @@ function readCount(summary, key) {
44
56
  function readStatus(value) {
45
57
  return typeof value === 'string' ? value : 'unknown';
46
58
  }
59
+ function readVerifiedManifestObligations(context) {
60
+ const intake = asRecord(context.intake);
61
+ const verifiedManifest = asRecord(intake.verified_manifest);
62
+ return Array.isArray(verifiedManifest.obligations)
63
+ ? verifiedManifest.obligations.map((item) => asRecord(item))
64
+ : [];
65
+ }
66
+ function readVerifiedManifestObligationIds(context) {
67
+ const obligations = readVerifiedManifestObligations(context);
68
+ return normalizeList(obligations
69
+ .map((item) => asString(item.obligation_id))
70
+ .filter((item) => item !== null));
71
+ }
72
+ function readPlanTraceContractValidation(context, plan) {
73
+ const verifiedObligationIds = readVerifiedManifestObligationIds(context);
74
+ if (verifiedObligationIds.length === 0) {
75
+ return null;
76
+ }
77
+ return validatePlanTraceAgainstObligationIds(plan, verifiedObligationIds);
78
+ }
79
+ function hasInvalidPlanTraceContract(validation) {
80
+ return validation !== null && !validation.valid;
81
+ }
47
82
  function deriveEdgeCaseChecklist(specText) {
48
83
  const checklist = [
49
84
  'Edge-case: boundary values and size limits are covered.',
@@ -65,6 +100,28 @@ function deriveEdgeCaseChecklist(specText) {
65
100
  }
66
101
  return normalizeList(checklist);
67
102
  }
103
+ function deriveEdgeCaseChecklistFromVerifiedManifest(obligations) {
104
+ const checklist = [];
105
+ const kinds = new Set(obligations
106
+ .map((obligation) => asString(obligation.kind))
107
+ .filter((item) => item !== null));
108
+ const verificationHints = new Set(obligations
109
+ .map((obligation) => asString(obligation.verification_hint))
110
+ .filter((item) => item !== null));
111
+ if (kinds.has('artifact') || kinds.has('workflow') || kinds.has('behavior')) {
112
+ checklist.push('Verified workflow and artifact obligations cover boundary values and phase transitions.');
113
+ }
114
+ if (kinds.has('endpoint') || kinds.has('contract')) {
115
+ checklist.push('Verified endpoint and contract obligations cover payload validation and negative-path handling.');
116
+ }
117
+ if (kinds.has('integration')) {
118
+ checklist.push('Verified integration obligations cover dependency failure and retry behavior.');
119
+ }
120
+ if (verificationHints.has('required') || kinds.has('verification')) {
121
+ checklist.push('Required verified-manifest obligations have explicit verification coverage.');
122
+ }
123
+ return normalizeList(checklist);
124
+ }
68
125
  function readPlanVersion(plan) {
69
126
  const raw = plan.plan_version;
70
127
  if (typeof raw !== 'number' || !Number.isFinite(raw) || raw < 1) {
@@ -72,6 +129,13 @@ function readPlanVersion(plan) {
72
129
  }
73
130
  return Math.floor(raw);
74
131
  }
132
+ function readStateVersion(frontMatter) {
133
+ const raw = frontMatter.version;
134
+ if (typeof raw !== 'number' || !Number.isFinite(raw) || raw < 1) {
135
+ return null;
136
+ }
137
+ return Math.floor(raw);
138
+ }
75
139
  function isPostQaStatus(status) {
76
140
  return status === STATUS.QA || status === STATUS.READY_TO_MERGE || status === STATUS.BLOCKED;
77
141
  }
@@ -83,9 +147,15 @@ const TIMEOUT_RUNTIME_ERROR_CODES = new Set([
83
147
  /**
84
148
  * @fileoverview Planning phase wave executor.
85
149
  */
150
+ /**
151
+ * Executes the planning phase for one supervisor iteration wave.
152
+ * Handles intake verification, plan generation, worker decision dispatch,
153
+ * and post-QA reconciliation of accepted plans.
154
+ */
86
155
  export class PlanningWaveExecutor {
87
156
  toolCaller;
88
157
  planGenerator;
158
+ plannerSessionSync;
89
159
  workerDecisionRunner;
90
160
  providerMode;
91
161
  outputLoopDetector;
@@ -100,11 +170,14 @@ export class PlanningWaveExecutor {
100
170
  runId;
101
171
  providerName;
102
172
  modelName;
173
+ safeCheckpointHook;
174
+ getPolicySnapshot;
103
175
  noProgressByFeature = new Map();
104
176
  lastStatusByFeature = new Map();
105
177
  constructor(dependencies) {
106
178
  this.toolCaller = dependencies.toolCaller;
107
179
  this.planGenerator = dependencies.planGenerator;
180
+ this.plannerSessionSync = dependencies.plannerSessionSync;
108
181
  this.workerDecisionRunner = dependencies.workerDecisionRunner ?? NOOP_WORKER_DECISION_RUNNER;
109
182
  this.providerMode = dependencies.providerMode ?? 'stub';
110
183
  this.outputLoopDetector = dependencies.outputLoopDetector;
@@ -122,65 +195,217 @@ export class PlanningWaveExecutor {
122
195
  this.runId = dependencies.runId ?? null;
123
196
  this.providerName = dependencies.providerName ?? 'unknown';
124
197
  this.modelName = dependencies.modelName ?? 'unknown';
198
+ this.safeCheckpointHook = dependencies.safeCheckpointHook;
199
+ this.getPolicySnapshot = dependencies.getPolicySnapshot;
125
200
  }
201
+ /**
202
+ * Runs a single planning wave: resolves planner phase (intake vs. planning), invokes workers,
203
+ * normalizes accepted plan state, and falls back to stub plan generation when not in live mode.
204
+ * @param featureIds Feature IDs eligible for planning in this wave.
205
+ */
126
206
  async run(featureIds) {
207
+ await this.plannerSessionSync?.syncPlannerSessions(featureIds);
127
208
  for (const featureId of featureIds) {
128
- const context = await this.toolCaller.callTool('planner', TOOLS.FEATURE_GET_CONTEXT, {
129
- feature_id: featureId,
130
- });
131
- const state = context.data.state.front_matter;
132
- const previousStatus = this.lastStatusByFeature.get(featureId);
133
- if (previousStatus === STATUS.BLOCKED && state.status === STATUS.PLANNING) {
134
- this.noProgressByFeature.delete(featureId);
135
- this.outputLoopDetector?.reset(featureId);
136
- }
137
- this.lastStatusByFeature.set(featureId, state.status);
138
- if (state.status !== STATUS.PLANNING && state.status !== STATUS.BLOCKED) {
139
- continue;
140
- }
141
- const existingPlan = context.data.plan;
142
- let decision;
143
209
  try {
144
- decision = await this.workerDecisionRunner.execute({
145
- role: 'planner',
146
- featureId,
147
- contextBundle: asRecord(context.data),
148
- instructions: 'Review feature context and emit PLAN_SUBMISSION/REQUEST/NOTE outputs to advance planning deterministically.',
210
+ const context = await this.toolCaller.callTool('planner', TOOLS.FEATURE_GET_CONTEXT, {
211
+ feature_id: featureId,
149
212
  });
150
- }
151
- catch (error) {
152
- const handledRuntimeFailure = await this.handleRuntimeFailure(error, featureId);
153
- if (handledRuntimeFailure) {
213
+ const state = context.data.state.front_matter;
214
+ const plannerPhase = resolvePlannerPhaseFromContext(context.data);
215
+ const previousStatus = this.lastStatusByFeature.get(featureId);
216
+ if (previousStatus === STATUS.BLOCKED && state.status === STATUS.PLANNING) {
217
+ this.noProgressByFeature.delete(featureId);
218
+ this.outputLoopDetector?.reset(featureId);
219
+ }
220
+ this.lastStatusByFeature.set(featureId, state.status);
221
+ if (state.status !== STATUS.INTAKE &&
222
+ state.status !== STATUS.PLANNING &&
223
+ state.status !== STATUS.BLOCKED) {
154
224
  continue;
155
225
  }
156
- throw error;
157
- }
158
- const loopStalled = await this.enforceOutputLoopPolicy(featureId, decision);
159
- if (loopStalled) {
160
- continue;
161
- }
162
- const shouldSkip = await this.enforceWorkerExecutionPolicy(featureId, decision);
163
- if (shouldSkip) {
164
- continue;
165
- }
166
- if (decision.planSubmission || existingPlan) {
167
- continue;
226
+ const existingPlan = asRecord(context.data.plan);
227
+ const planTraceContract = readPlanTraceContractValidation(context.data, existingPlan);
228
+ if (await this.normalizeAcceptedPlanState(featureId, asRecord(state), existingPlan, planTraceContract)) {
229
+ continue;
230
+ }
231
+ if (state.status === STATUS.BLOCKED &&
232
+ plannerPhase === 'planning' &&
233
+ readPlanVersion(existingPlan) !== null &&
234
+ !hasInvalidPlanTraceContract(planTraceContract)) {
235
+ continue;
236
+ }
237
+ let decision;
238
+ try {
239
+ decision = await this.workerDecisionRunner.execute({
240
+ role: 'planner',
241
+ featureId,
242
+ contextBundle: asRecord(context.data),
243
+ instructions: this.instructionsForPlannerState(asRecord(context.data)),
244
+ });
245
+ }
246
+ catch (error) {
247
+ const handledRuntimeFailure = await this.handleRuntimeFailure(error, featureId);
248
+ if (handledRuntimeFailure) {
249
+ continue;
250
+ }
251
+ throw error;
252
+ }
253
+ const loopStalled = await this.enforceOutputLoopPolicy(featureId, decision);
254
+ if (loopStalled) {
255
+ continue;
256
+ }
257
+ if (decision.questionRequested) {
258
+ this.noProgressByFeature.delete(featureId);
259
+ continue;
260
+ }
261
+ if (decision.intakeSubmission) {
262
+ this.noProgressByFeature.delete(featureId);
263
+ continue;
264
+ }
265
+ const shouldSkip = await this.enforceWorkerExecutionPolicy(featureId, decision);
266
+ if (shouldSkip) {
267
+ continue;
268
+ }
269
+ if (decision.planSubmission ||
270
+ (readPlanVersion(existingPlan) !== null &&
271
+ !hasInvalidPlanTraceContract(planTraceContract))) {
272
+ continue;
273
+ }
274
+ if (this.providerMode === 'stub') {
275
+ if (plannerPhase === 'intake') {
276
+ const intake = asRecord(asRecord(context.data).intake);
277
+ const verifiedManifest = asRecord(intake.verified_manifest);
278
+ const bootstrapManifest = asRecord(intake.bootstrap_manifest);
279
+ if (Object.keys(verifiedManifest).length === 0 &&
280
+ this.policyAllowsStubAutoPromotion(bootstrapManifest)) {
281
+ await this.toolCaller.callTool('planner', TOOLS.FEATURE_INTAKE_SUBMIT, {
282
+ feature_id: featureId,
283
+ intake_submission: {
284
+ verified_manifest: {
285
+ ...bootstrapManifest,
286
+ artifact_type: 'verified',
287
+ verification_basis: 'policy_approved_auto_promotion',
288
+ verified_at: new Date().toISOString(),
289
+ source_bootstrap_version: typeof bootstrapManifest.manifest_version === 'number'
290
+ ? bootstrapManifest.manifest_version
291
+ : null,
292
+ },
293
+ open_ambiguities: [],
294
+ resolved_ambiguities: [],
295
+ requires_user_input: false,
296
+ },
297
+ });
298
+ continue;
299
+ }
300
+ if (Object.keys(verifiedManifest).length === 0) {
301
+ continue;
302
+ }
303
+ }
304
+ const plan = await this.planGenerator.generateInitialPlan(featureId);
305
+ await this.toolCaller.callTool('planner', TOOLS.PLAN_SUBMIT, {
306
+ feature_id: featureId,
307
+ plan_json: plan,
308
+ });
309
+ }
168
310
  }
169
- if (this.providerMode === 'stub') {
170
- const plan = await this.planGenerator.generateInitialPlan(featureId);
171
- await this.toolCaller.callTool('planner', TOOLS.PLAN_SUBMIT, {
172
- feature_id: featureId,
173
- plan_json: plan,
174
- });
311
+ finally {
312
+ if (this.safeCheckpointHook) {
313
+ await this.safeCheckpointHook();
314
+ }
175
315
  }
176
316
  }
177
317
  }
318
+ /**
319
+ * Clears all per-feature tracking state (progress counters, status cache, loop detector).
320
+ * Called when a feature is removed from the active execution set.
321
+ * @param featureId The feature whose tracking data should be purged.
322
+ */
178
323
  clearFeatureTracking(featureId) {
179
324
  this.noProgressByFeature.delete(featureId);
180
325
  this.lastStatusByFeature.delete(featureId);
181
326
  this.outputLoopDetector?.delete(featureId);
182
327
  }
328
+ instructionsForPlannerState(contextBundle) {
329
+ if (resolvePlannerPhaseFromContext(contextBundle) === 'intake') {
330
+ return [
331
+ 'Review spec.md, the bootstrap manifest, verified manifest state, and intake review artifacts.',
332
+ 'In intake mode, form or verify the requirements contract before execution planning begins.',
333
+ 'Emit INTAKE_SUBMISSION when the verified manifest is ready.',
334
+ 'Emit REQUEST action=ask_user_input only for blocking requirement clarification.',
335
+ 'If you emit ask_user_input, stop there for the turn and wait for the persisted human answer before promoting intake.',
336
+ 'Do not emit PLAN_SUBMISSION while the feature remains in intake.',
337
+ ].join(' ');
338
+ }
339
+ return 'Review the feature artifacts on disk, update plan.md so it reflects the current planning state and step-by-step implementation plan, and emit PLAN_SUBMISSION/REQUEST/NOTE outputs to advance planning.';
340
+ }
341
+ policyAllowsStubAutoPromotion(bootstrapManifest) {
342
+ if (Object.keys(bootstrapManifest).length === 0) {
343
+ return false;
344
+ }
345
+ const planning = asRecord(this.getPolicySnapshot?.().planning);
346
+ const intake = asRecord(planning.intake);
347
+ if (intake.allow_auto_promotion !== true) {
348
+ return false;
349
+ }
350
+ const ambiguities = Array.isArray(bootstrapManifest.ambiguities)
351
+ ? bootstrapManifest.ambiguities
352
+ : [];
353
+ if (ambiguities.length > 0) {
354
+ return false;
355
+ }
356
+ const minimumConfidence = normalizeManifestConfidence(intake.auto_promotion_min_confidence) ?? 'high';
357
+ const obligations = Array.isArray(bootstrapManifest.obligations)
358
+ ? bootstrapManifest.obligations.map((item) => asRecord(item))
359
+ : [];
360
+ return obligationsMeetConfidenceThreshold(obligations
361
+ .map((obligation) => normalizeManifestConfidence(obligation.confidence))
362
+ .filter((confidence) => confidence !== null)
363
+ .map((confidence) => ({ confidence })), minimumConfidence);
364
+ }
365
+ async normalizeAcceptedPlanState(featureId, frontMatter, plan, planTraceContract = null) {
366
+ const planVersion = readPlanVersion(plan);
367
+ if (planVersion == null || hasInvalidPlanTraceContract(planTraceContract)) {
368
+ return false;
369
+ }
370
+ const status = readStatus(frontMatter.status);
371
+ const gates = asRecord(frontMatter.gates);
372
+ const needsStatusHeal = status === STATUS.PLANNING;
373
+ const needsPlanGateHeal = gates.plan !== 'pass';
374
+ if (!needsStatusHeal && !needsPlanGateHeal) {
375
+ return false;
376
+ }
377
+ const expectedVersion = readStateVersion(frontMatter);
378
+ if (expectedVersion == null) {
379
+ return false;
380
+ }
381
+ const nextFrontMatter = {
382
+ gates: {
383
+ ...gates,
384
+ plan: 'pass',
385
+ },
386
+ };
387
+ if (needsStatusHeal) {
388
+ nextFrontMatter.status = STATUS.BUILDING;
389
+ }
390
+ await this.toolCaller.callTool('orchestrator', TOOLS.FEATURE_STATE_PATCH, {
391
+ feature_id: featureId,
392
+ expected_version: expectedVersion,
393
+ patch: {
394
+ front_matter: nextFrontMatter,
395
+ },
396
+ });
397
+ this.lastStatusByFeature.set(featureId, needsStatusHeal ? STATUS.BUILDING : status);
398
+ return true;
399
+ }
400
+ /**
401
+ * Reconciles accepted plans against QA/gate findings after the QA wave completes.
402
+ * Evaluates gate freshness, plan-trace contract validity, and QA test summaries,
403
+ * then emits plan updates or invokes the planner worker for revisions when needed.
404
+ * @param featureIds Feature IDs in post-QA status to reconcile.
405
+ * @param iteration Current supervisor iteration number (used for decision logging).
406
+ */
183
407
  async runPostQaReconciliation(featureIds, iteration) {
408
+ await this.plannerSessionSync?.syncPlannerSessions(featureIds);
184
409
  for (const featureId of featureIds) {
185
410
  const context = await this.toolCaller.callTool('planner', TOOLS.FEATURE_GET_CONTEXT, {
186
411
  feature_id: featureId,
@@ -190,12 +415,16 @@ export class PlanningWaveExecutor {
190
415
  if (!isPostQaStatus(status)) {
191
416
  continue;
192
417
  }
418
+ if (status === STATUS.BLOCKED && resolvePlannerPhaseFromContext(context.data) === 'intake') {
419
+ continue;
420
+ }
193
421
  const existingPlan = asRecord(context.data.plan);
194
422
  if (Object.keys(existingPlan).length === 0) {
195
423
  await this.appendDecisionLog(featureId, {
196
424
  phase: 'post_qa_reconciliation',
197
425
  iteration,
198
- decision: 'no_update',
426
+ plan_decision: 'unchanged',
427
+ execution_disposition: 'blocked_other',
199
428
  reasons: ['missing_plan'],
200
429
  status,
201
430
  });
@@ -206,23 +435,100 @@ export class PlanningWaveExecutor {
206
435
  await this.appendDecisionLog(featureId, {
207
436
  phase: 'post_qa_reconciliation',
208
437
  iteration,
209
- decision: 'no_update',
438
+ plan_decision: 'unchanged',
439
+ execution_disposition: 'blocked_other',
210
440
  reasons: ['existing_plan_version_invalid'],
211
441
  status,
212
442
  });
213
443
  continue;
214
444
  }
215
- const decision = this.evaluateReconciliationDecision(context.data, existingPlan, status);
216
- if (decision.action === 'no_update') {
445
+ const decision = await this.evaluateReconciliationDecision(context.data, existingPlan, status);
446
+ if (this.shouldInvokePlannerForPlanTraceContract(decision)) {
447
+ const plannerDecision = await this.workerDecisionRunner.execute({
448
+ role: 'planner',
449
+ featureId,
450
+ contextBundle: {
451
+ ...asRecord(context.data),
452
+ plan_trace_contract: structuredClone(decision.planTraceContract),
453
+ },
454
+ instructions: 'The accepted plan_trace no longer matches the verified manifest contract. Review plan_trace_contract, revise the accepted plan so every verified manifest obligation is correctly traced, remove obsolete obligation mappings, and emit PLAN_SUBMISSION or REQUEST.action=amend_plan. Do not leave the stale plan_trace unchanged.',
455
+ });
217
456
  await this.appendDecisionLog(featureId, {
218
457
  phase: 'post_qa_reconciliation',
219
458
  iteration,
220
- decision: 'no_update',
459
+ plan_decision: plannerDecision.planSubmission || plannerDecision.requestHandled
460
+ ? 'update_required'
461
+ : 'unchanged',
462
+ execution_disposition: plannerDecision.planSubmission || plannerDecision.requestHandled
463
+ ? 'retry_build'
464
+ : decision.executionDisposition,
465
+ status,
466
+ reasons: plannerDecision.planSubmission || plannerDecision.requestHandled
467
+ ? normalizeList([
468
+ ...decision.reasons,
469
+ 'planner_verified_manifest_trace_revision_requested',
470
+ ])
471
+ : decision.reasons,
472
+ qa_summary: decision.qaSummary,
473
+ latest_gate_overall: decision.latestGateOverall,
474
+ gate_evidence_freshness: decision.gateEvidenceFreshness,
475
+ checkpoint_validity: decision.checkpointValidity,
476
+ gate_failure_context: decision.gateFailureContext,
477
+ edge_case_checklist: decision.edgeCaseChecklist,
478
+ plan_trace_contract: decision.planTraceContract,
479
+ });
480
+ continue;
481
+ }
482
+ if (this.shouldInvokePlannerForGateFailure(decision)) {
483
+ const plannerDecision = await this.workerDecisionRunner.execute({
484
+ role: 'planner',
485
+ featureId,
486
+ contextBundle: {
487
+ ...asRecord(context.data),
488
+ gate_failure_context: structuredClone(decision.gateFailureContext),
489
+ },
490
+ instructions: 'A required gate is currently failing with fresh evidence. Review gate_failure_context, revise the accepted plan as needed so the builder can legally investigate and fix the failure, and emit PLAN_SUBMISSION or REQUEST.action=amend_plan when a plan revision is required.',
491
+ });
492
+ await this.appendDecisionLog(featureId, {
493
+ phase: 'post_qa_reconciliation',
494
+ iteration,
495
+ plan_decision: plannerDecision.planSubmission || plannerDecision.requestHandled
496
+ ? 'update_required'
497
+ : 'unchanged',
498
+ execution_disposition: plannerDecision.planSubmission || plannerDecision.requestHandled
499
+ ? 'retry_build'
500
+ : decision.executionDisposition,
501
+ status,
502
+ reasons: plannerDecision.planSubmission || plannerDecision.requestHandled
503
+ ? normalizeList([...decision.reasons, 'planner_gate_failure_revision_requested'])
504
+ : decision.reasons,
505
+ qa_summary: decision.qaSummary,
506
+ latest_gate_overall: decision.latestGateOverall,
507
+ gate_evidence_freshness: decision.gateEvidenceFreshness,
508
+ checkpoint_validity: decision.checkpointValidity,
509
+ gate_failure_context: decision.gateFailureContext,
510
+ edge_case_checklist: decision.edgeCaseChecklist,
511
+ plan_trace_contract: decision.planTraceContract,
512
+ });
513
+ if (plannerDecision.planSubmission || plannerDecision.requestHandled) {
514
+ continue;
515
+ }
516
+ }
517
+ if (decision.planDecision === 'unchanged') {
518
+ await this.appendDecisionLog(featureId, {
519
+ phase: 'post_qa_reconciliation',
520
+ iteration,
521
+ plan_decision: decision.planDecision,
522
+ execution_disposition: decision.executionDisposition,
221
523
  status,
222
524
  reasons: decision.reasons,
223
525
  qa_summary: decision.qaSummary,
224
526
  latest_gate_overall: decision.latestGateOverall,
527
+ gate_evidence_freshness: decision.gateEvidenceFreshness,
528
+ checkpoint_validity: decision.checkpointValidity,
529
+ gate_failure_context: decision.gateFailureContext,
225
530
  edge_case_checklist: decision.edgeCaseChecklist,
531
+ plan_trace_contract: decision.planTraceContract,
226
532
  });
227
533
  continue;
228
534
  }
@@ -235,7 +541,8 @@ export class PlanningWaveExecutor {
235
541
  await this.appendDecisionLog(featureId, {
236
542
  phase: 'post_qa_reconciliation',
237
543
  iteration,
238
- decision: 'plan_update',
544
+ plan_decision: decision.planDecision,
545
+ execution_disposition: decision.executionDisposition,
239
546
  status,
240
547
  expected_plan_version: planVersion,
241
548
  next_plan_version: nextPlan.plan_version,
@@ -243,15 +550,23 @@ export class PlanningWaveExecutor {
243
550
  reasons: decision.reasons,
244
551
  qa_summary: decision.qaSummary,
245
552
  latest_gate_overall: decision.latestGateOverall,
553
+ gate_evidence_freshness: decision.gateEvidenceFreshness,
554
+ checkpoint_validity: decision.checkpointValidity,
555
+ gate_failure_context: decision.gateFailureContext,
246
556
  edge_case_checklist: decision.edgeCaseChecklist,
557
+ plan_trace_contract: decision.planTraceContract,
247
558
  });
248
559
  }
249
560
  }
250
- evaluateReconciliationDecision(context, plan, status) {
561
+ async evaluateReconciliationDecision(context, plan, status) {
251
562
  const acceptanceCriteria = asStringArray(plan.acceptance_criteria);
252
563
  const riskItems = asStringArray(plan.risk);
564
+ const verifiedObligations = readVerifiedManifestObligations(context);
565
+ const planTraceContract = readPlanTraceContractValidation(context, plan);
253
566
  const specText = typeof context.spec === 'string' ? context.spec : '';
254
- const edgeCaseChecklist = deriveEdgeCaseChecklist(specText);
567
+ const edgeCaseChecklist = verifiedObligations.length > 0
568
+ ? deriveEdgeCaseChecklistFromVerifiedManifest(verifiedObligations)
569
+ : deriveEdgeCaseChecklist(specText);
255
570
  const qaSummary = asRecord(asRecord(context.qa_test_index).summary);
256
571
  const pending = readCount(qaSummary, 'pending');
257
572
  const failed = readCount(qaSummary, 'failed');
@@ -259,23 +574,128 @@ export class PlanningWaveExecutor {
259
574
  const latestGateOverall = typeof asRecord(context.latest_evidence).overall === 'string'
260
575
  ? String(asRecord(context.latest_evidence).overall)
261
576
  : null;
262
- const reasons = [];
577
+ const frontMatter = asRecord(asRecord(context.state).front_matter);
578
+ const statusReason = typeof frontMatter.status_reason === 'string' ? frontMatter.status_reason : '';
579
+ const lastGateMode = typeof asRecord(frontMatter.evidence).last_gate_mode === 'string'
580
+ ? String(asRecord(frontMatter.evidence).last_gate_mode)
581
+ : null;
582
+ const fastFreshness = assessGateFreshness({
583
+ frontMatter,
584
+ mode: 'fast',
585
+ gateEvidenceByMode: readGateEvidenceByMode(context),
586
+ latestEvidence: context.latest_evidence,
587
+ });
588
+ const fullFreshness = assessGateFreshness({
589
+ frontMatter,
590
+ mode: 'full',
591
+ gateEvidenceByMode: readGateEvidenceByMode(context),
592
+ latestEvidence: context.latest_evidence,
593
+ });
594
+ const checkpointValidity = readCheckpointValidity(frontMatter);
595
+ const gateEvidenceFreshness = lastGateMode === 'full'
596
+ ? fullFreshness.freshness
597
+ : status === STATUS.BLOCKED || status === STATUS.BUILDING
598
+ ? fastFreshness.freshness
599
+ : fullFreshness.freshness;
600
+ let executionDisposition = status === STATUS.READY_TO_MERGE ? 'converged' : 'retry_qa';
601
+ const gateFailureContext = await this.extractGateFailureContext(context);
602
+ const planReasons = [];
603
+ const executionReasons = [];
263
604
  const acceptanceCriteriaAdditions = [];
264
605
  const missingEdgeCases = edgeCaseChecklist.filter((item) => !riskItems.includes(item));
265
606
  if (missingEdgeCases.length > 0) {
266
- reasons.push(`edge_case_checklist_missing:${missingEdgeCases.length}`);
607
+ planReasons.push(`edge_case_checklist_missing:${missingEdgeCases.length}`);
267
608
  acceptanceCriteriaAdditions.push('Planner edge-case checklist has been reviewed and incorporated into the execution plan.');
268
609
  }
610
+ const planTraceRequiresRevision = hasInvalidPlanTraceContract(planTraceContract);
611
+ if (planTraceContract?.missing_obligation_ids.length) {
612
+ planReasons.push(`verified_manifest_trace_missing:${planTraceContract.missing_obligation_ids.length}`);
613
+ }
614
+ if (planTraceContract?.unknown_obligation_ids.length) {
615
+ planReasons.push(`verified_manifest_trace_unknown:${planTraceContract.unknown_obligation_ids.length}`);
616
+ }
617
+ if (planTraceContract?.duplicate_obligation_ids.length) {
618
+ planReasons.push(`verified_manifest_trace_duplicate:${planTraceContract.duplicate_obligation_ids.length}`);
619
+ }
620
+ if (planTraceContract?.invalid_mappings.length) {
621
+ planReasons.push(`verified_manifest_trace_invalid_mapping:${planTraceContract.invalid_mappings.length}`);
622
+ }
623
+ if (planTraceRequiresRevision) {
624
+ acceptanceCriteriaAdditions.push('plan_trace maps every verified manifest obligation_id into planned implementation and verification work.');
625
+ }
269
626
  const hasQaSignals = status === STATUS.BLOCKED || failed > 0 || pending > 0 || latestGateOverall === 'fail';
270
627
  const qaCheckpoint = `Planner reconciliation checkpoint [status=${status};failed=${failed};pending=${pending};latest=${latestGateOverall ?? 'unknown'}]`;
271
628
  if (hasQaSignals && !acceptanceCriteria.includes(qaCheckpoint)) {
272
- reasons.push(`qa_signals_detected:${status}:failed=${failed}:pending=${pending}`);
629
+ planReasons.push(`qa_signals_detected:${status}:failed=${failed}:pending=${pending}`);
273
630
  acceptanceCriteriaAdditions.push('Reconcile QA/gate findings against plan scope and apply corrective updates before merge.');
274
631
  acceptanceCriteriaAdditions.push(qaCheckpoint);
275
632
  }
633
+ if (status === STATUS.BLOCKED) {
634
+ if (statusReason.includes(ERROR_CODES.PROVIDER_OUTPUT_INVALID)) {
635
+ executionReasons.push('provider_output_invalid');
636
+ executionDisposition = 'blocked_provider_failure';
637
+ }
638
+ else if (lastGateMode === 'full' &&
639
+ latestGateOverall === 'fail' &&
640
+ fullFreshness.freshness === 'current') {
641
+ executionDisposition = 'blocked_other';
642
+ }
643
+ else if (lastGateMode === 'fast' &&
644
+ latestGateOverall === 'fail' &&
645
+ fastFreshness.freshness === 'current') {
646
+ executionDisposition = 'blocked_other';
647
+ }
648
+ else if (lastGateMode === 'full' && fullFreshness.shouldRerunGate) {
649
+ executionReasons.push(...fullFreshness.reasons);
650
+ executionDisposition =
651
+ latestGateOverall === 'pass' ? 'rerun_full_gate' : 'blocked_stale_evidence';
652
+ }
653
+ else if (fastFreshness.shouldRerunGate) {
654
+ executionReasons.push(...fastFreshness.reasons);
655
+ executionDisposition = latestGateOverall === 'pass' ? 'retry_qa' : 'blocked_stale_evidence';
656
+ }
657
+ else if (fullFreshness.shouldRerunGate) {
658
+ executionReasons.push(...fullFreshness.reasons);
659
+ executionDisposition =
660
+ latestGateOverall === 'pass' ? 'rerun_full_gate' : 'blocked_stale_evidence';
661
+ }
662
+ else if (latestGateOverall === 'fail') {
663
+ executionDisposition = 'blocked_other';
664
+ }
665
+ }
666
+ else if (status === STATUS.QA) {
667
+ if (fullFreshness.shouldRerunGate) {
668
+ executionReasons.push(...fullFreshness.reasons);
669
+ executionDisposition = 'rerun_full_gate';
670
+ }
671
+ else if (failed > 0 || pending > 0 || running > 0) {
672
+ executionDisposition = 'retry_qa';
673
+ }
674
+ else if (latestGateOverall === 'pass' && fullFreshness.freshness === 'current') {
675
+ executionDisposition = 'converged';
676
+ }
677
+ }
678
+ else if (status === STATUS.READY_TO_MERGE) {
679
+ if (fullFreshness.shouldRerunGate) {
680
+ executionReasons.push(...fullFreshness.reasons);
681
+ executionDisposition = 'rerun_full_gate';
682
+ }
683
+ else if (latestGateOverall !== 'pass' || fullFreshness.freshness !== 'current') {
684
+ executionReasons.push(...fullFreshness.reasons);
685
+ executionDisposition = 'blocked_stale_evidence';
686
+ }
687
+ else {
688
+ executionDisposition = 'converged';
689
+ }
690
+ }
691
+ if (planTraceRequiresRevision && executionDisposition === 'converged') {
692
+ executionDisposition = 'retry_build';
693
+ }
694
+ const reasons = normalizeList([...planReasons, ...executionReasons]);
276
695
  if (reasons.length === 0) {
277
696
  return {
278
- action: 'no_update',
697
+ planDecision: 'unchanged',
698
+ executionDisposition,
279
699
  reasons: ['reconciled_no_gaps'],
280
700
  acceptanceCriteriaAdditions: [],
281
701
  edgeCaseChecklist,
@@ -285,10 +705,15 @@ export class PlanningWaveExecutor {
285
705
  running,
286
706
  },
287
707
  latestGateOverall,
708
+ gateEvidenceFreshness,
709
+ checkpointValidity,
710
+ gateFailureContext,
711
+ planTraceContract,
288
712
  };
289
713
  }
290
714
  return {
291
- action: 'update',
715
+ planDecision: acceptanceCriteriaAdditions.length > 0 ? 'update_required' : 'unchanged',
716
+ executionDisposition,
292
717
  reasons,
293
718
  acceptanceCriteriaAdditions: normalizeList(acceptanceCriteriaAdditions),
294
719
  edgeCaseChecklist,
@@ -298,6 +723,10 @@ export class PlanningWaveExecutor {
298
723
  running,
299
724
  },
300
725
  latestGateOverall,
726
+ gateEvidenceFreshness,
727
+ checkpointValidity,
728
+ gateFailureContext,
729
+ planTraceContract,
301
730
  };
302
731
  }
303
732
  buildUpdatedPlan(plan, planVersion, decision) {
@@ -314,6 +743,76 @@ export class PlanningWaveExecutor {
314
743
  nextPlan.risk = normalizeList([...riskItems, ...decision.edgeCaseChecklist]);
315
744
  return nextPlan;
316
745
  }
746
+ shouldInvokePlannerForGateFailure(decision) {
747
+ return (decision.gateFailureContext !== null &&
748
+ decision.latestGateOverall === 'fail' &&
749
+ decision.gateEvidenceFreshness === 'current' &&
750
+ decision.checkpointValidity !== 'invalid' &&
751
+ (decision.executionDisposition === 'blocked_other' ||
752
+ decision.executionDisposition === 'retry_qa'));
753
+ }
754
+ shouldInvokePlannerForPlanTraceContract(decision) {
755
+ return hasInvalidPlanTraceContract(decision.planTraceContract);
756
+ }
757
+ async extractGateFailureContext(context) {
758
+ const latestEvidence = asRecord(context.latest_evidence);
759
+ const stepResultsRaw = Array.isArray(latestEvidence.step_results)
760
+ ? latestEvidence.step_results
761
+ : [];
762
+ const stepResults = stepResultsRaw
763
+ .map((item) => asRecord(item))
764
+ .filter((item) => Object.keys(item).length > 0);
765
+ const failingStep = stepResults.find((item) => (asNumber(item.exit_code) ?? 0) !== 0 || item.timeout === true) ??
766
+ (typeof latestEvidence.overall === 'string' && latestEvidence.overall === 'fail'
767
+ ? (stepResults[0] ?? null)
768
+ : null);
769
+ if (!failingStep) {
770
+ return null;
771
+ }
772
+ const stepName = asString(failingStep.name) ?? 'unknown';
773
+ const stepCmd = Array.isArray(failingStep.cmd)
774
+ ? failingStep.cmd.map((value) => String(value))
775
+ : [];
776
+ const exitCode = asNumber(failingStep.exit_code) ?? 1;
777
+ const rawLogPath = asString(failingStep.log_path);
778
+ const notes = Array.isArray(latestEvidence.notes)
779
+ ? latestEvidence.notes.filter((item) => typeof item === 'string')
780
+ : [];
781
+ let failureAnalysis = null;
782
+ if (rawLogPath) {
783
+ const logPath = path.isAbsolute(rawLogPath)
784
+ ? rawLogPath
785
+ : this.repoRoot
786
+ ? path.join(this.repoRoot, rawLogPath)
787
+ : rawLogPath;
788
+ try {
789
+ const logContent = await fs.readFile(logPath, 'utf8');
790
+ failureAnalysis = extractGateLog({
791
+ stepName,
792
+ cmd: stepCmd,
793
+ exitCode,
794
+ logContent,
795
+ });
796
+ }
797
+ catch {
798
+ failureAnalysis = null;
799
+ }
800
+ }
801
+ return {
802
+ gate_name: asString(latestEvidence.mode) ?? 'unknown',
803
+ step_name: stepName,
804
+ cmd: stepCmd,
805
+ exit_code: exitCode,
806
+ timeout: failingStep.timeout === true,
807
+ affected_files: failureAnalysis?.affectedFiles ?? [],
808
+ error_lines: failureAnalysis?.errorLines ?? [],
809
+ summary_lines: failureAnalysis?.summaryLines ?? [],
810
+ error_count: failureAnalysis?.errorCount ?? null,
811
+ log_tail: failureAnalysis?.logTail ?? '',
812
+ notes,
813
+ evidence_overall: asString(latestEvidence.overall) ?? null,
814
+ };
815
+ }
317
816
  async appendDecisionLog(featureId, note) {
318
817
  await this.toolCaller.callTool('orchestrator', TOOLS.FEATURE_LOG_APPEND, {
319
818
  feature_id: featureId,
@@ -433,10 +932,62 @@ export class PlanningWaveExecutor {
433
932
  this.noProgressByFeature.delete(featureId);
434
933
  return false;
435
934
  }
935
+ const context = await this.toolCaller.callTool('planner', TOOLS.FEATURE_GET_CONTEXT, {
936
+ feature_id: featureId,
937
+ });
436
938
  if (decision.invalidOutput) {
939
+ if (await this.requestIntakeClarificationFallback(featureId, asRecord(context.data), ERROR_CODES.PROVIDER_OUTPUT_INVALID)) {
940
+ return true;
941
+ }
437
942
  await this.applyWorkerPolicyAction(featureId, this.malformedOutputAction, ERROR_CODES.PROVIDER_OUTPUT_INVALID, 'Planner emitted malformed worker outputs');
438
943
  return true;
439
944
  }
945
+ if (decision.contextStall) {
946
+ if (await this.requestIntakeClarificationFallback(featureId, asRecord(context.data), ERROR_CODES.PROVIDER_CONTEXT_STALL)) {
947
+ return true;
948
+ }
949
+ const state = await this.toolCaller.callTool('orchestrator', TOOLS.FEATURE_STATE_GET, { feature_id: featureId });
950
+ const frontMatter = asRecord(state.data.front_matter);
951
+ const expectedVersion = typeof frontMatter.version === 'number' && Number.isFinite(frontMatter.version)
952
+ ? Math.floor(frontMatter.version)
953
+ : null;
954
+ const recovery = this.buildPlannerRecoveryFrontMatter(frontMatter, ERROR_CODES.PROVIDER_CONTEXT_STALL, 'planning');
955
+ await this.toolCaller.callTool('orchestrator', TOOLS.FEATURE_STATE_PATCH, {
956
+ feature_id: featureId,
957
+ expected_version: expectedVersion,
958
+ patch: {
959
+ front_matter: {
960
+ status: STATUS.BLOCKED,
961
+ status_reason: `${ERROR_CODES.PROVIDER_CONTEXT_STALL}: repeated context refresh with no progress`,
962
+ recovery,
963
+ context_request_count: decision.contextRequestCount ?? 0,
964
+ last_context_request_at: decision.lastContextRequestAt ?? null,
965
+ last_context_request_role: decision.lastContextRequestRole ?? 'planner',
966
+ },
967
+ },
968
+ });
969
+ this.lastStatusByFeature.set(featureId, STATUS.BLOCKED);
970
+ await this.toolCaller.callTool('orchestrator', TOOLS.FEATURE_LOG_APPEND, {
971
+ feature_id: featureId,
972
+ note: JSON.stringify({
973
+ phase: 'planning',
974
+ decision: 'blocked',
975
+ error_code: ERROR_CODES.PROVIDER_CONTEXT_STALL,
976
+ reason: 'repeated context refresh with no progress',
977
+ recovery_state: recovery.state,
978
+ recovery_attempt: recovery.attempt,
979
+ context_request_count: decision.contextRequestCount ?? 0,
980
+ last_context_request_at: decision.lastContextRequestAt ?? null,
981
+ last_context_request_role: decision.lastContextRequestRole ?? 'planner',
982
+ }),
983
+ });
984
+ return true;
985
+ }
986
+ if (decision.noProgress &&
987
+ (await this.requestIntakeClarificationFallback(featureId, asRecord(context.data), ERROR_CODES.PROVIDER_NO_PROGRESS))) {
988
+ this.noProgressByFeature.delete(featureId);
989
+ return true;
990
+ }
440
991
  if (!decision.noProgress) {
441
992
  this.noProgressByFeature.delete(featureId);
442
993
  return false;
@@ -449,6 +1000,149 @@ export class PlanningWaveExecutor {
449
1000
  await this.applyWorkerPolicyAction(featureId, this.noProgressAction, ERROR_CODES.PROVIDER_NO_PROGRESS, `Planner made no actionable progress in ${currentCount} consecutive iterations`);
450
1001
  return true;
451
1002
  }
1003
+ readOpenIntakeAmbiguities(context) {
1004
+ const review = asRecord(asRecord(context.intake).review);
1005
+ const ambiguities = Array.isArray(review.ambiguities) ? review.ambiguities : [];
1006
+ return ambiguities
1007
+ .map((item) => asRecord(item))
1008
+ .filter((item) => asString(item.status) === 'open')
1009
+ .map((item) => ({
1010
+ id: asString(item.id) ?? 'AMB-UNKNOWN',
1011
+ summary: asString(item.summary) ?? 'Clarify the remaining intake ambiguity.',
1012
+ obligationIds: asStringArray(item.obligation_ids),
1013
+ }));
1014
+ }
1015
+ async readAnsweredIntakeAmbiguityIds(featureId) {
1016
+ const response = await this.toolCaller.callTool('orchestrator', TOOLS.FEATURE_QUESTION_LIST, {
1017
+ feature_id: featureId,
1018
+ status: 'all',
1019
+ });
1020
+ const items = Array.isArray(response.data.items) ? response.data.items : [];
1021
+ const ambiguityIds = items
1022
+ .map((item) => asRecord(item))
1023
+ .filter((item) => asString(item.status) === 'answered' &&
1024
+ (asString(item.resume_status) === STATUS.INTAKE ||
1025
+ asString(item.resume_phase) === STATUS.INTAKE ||
1026
+ asString(item.phase) === STATUS.INTAKE))
1027
+ .flatMap((item) => {
1028
+ const details = asRecord(item.details);
1029
+ const direct = asString(details.ambiguity_id);
1030
+ const grouped = asStringArray(details.ambiguity_ids);
1031
+ return direct ? [direct, ...grouped] : grouped;
1032
+ });
1033
+ return new Set(normalizeList(ambiguityIds));
1034
+ }
1035
+ readAnsweredIntakeClarifications(context) {
1036
+ const review = asRecord(asRecord(context.intake).review);
1037
+ const answers = Array.isArray(review.clarification_answers) ? review.clarification_answers : [];
1038
+ return answers
1039
+ .map((item) => asRecord(item))
1040
+ .filter((item) => asStringArray(item.ambiguity_ids).length > 0)
1041
+ .map((item) => ({
1042
+ questionId: asString(item.question_id) ?? 'unknown',
1043
+ ambiguityIds: asStringArray(item.ambiguity_ids),
1044
+ answer: typeof item.answer === 'string'
1045
+ ? item.answer
1046
+ : JSON.stringify(asRecord(item.answer) ?? {}, null, 2),
1047
+ answeredAt: asString(item.answered_at),
1048
+ }));
1049
+ }
1050
+ buildIntakeClarificationPrompt(ambiguities, followUpAmbiguityIds, priorAnswers) {
1051
+ const needsFollowUp = ambiguities.some((ambiguity) => followUpAmbiguityIds.has(ambiguity.id));
1052
+ const intro = needsFollowUp && ambiguities.length === 1
1053
+ ? 'Planning still cannot continue because this intake ambiguity remains unresolved after the previous answer:'
1054
+ : needsFollowUp
1055
+ ? 'Planning still cannot continue because these intake ambiguities remain unresolved after the previous answer:'
1056
+ : ambiguities.length === 1
1057
+ ? 'Planning cannot continue until this remaining intake ambiguity is clarified:'
1058
+ : 'Planning cannot continue until these remaining intake ambiguities are clarified:';
1059
+ const items = ambiguities.map((ambiguity) => `- ${ambiguity.id}: ${ambiguity.summary}`);
1060
+ const priorAnswerLines = ambiguities.flatMap((ambiguity) => priorAnswers
1061
+ .filter((answer) => answer.ambiguityIds.includes(ambiguity.id))
1062
+ .map((answer) => `- ${ambiguity.id} via ${answer.questionId}${answer.answeredAt ? ` at ${answer.answeredAt}` : ''}: ${answer.answer}`));
1063
+ const priorAnswersBlock = priorAnswerLines.length > 0
1064
+ ? `\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.`
1065
+ : '';
1066
+ return `${intro}\n${items.join('\n')}${priorAnswersBlock}\nRespond in free text and explicitly address each ambiguity ID.`;
1067
+ }
1068
+ async requestIntakeClarificationFallback(featureId, context, recoveryReason) {
1069
+ if (resolvePlannerPhaseFromContext(context) !== 'intake') {
1070
+ return false;
1071
+ }
1072
+ const intake = asRecord(context.intake);
1073
+ const verifiedManifest = asRecord(intake.verified_manifest);
1074
+ if (Object.keys(verifiedManifest).length > 0) {
1075
+ return false;
1076
+ }
1077
+ const humanInput = asRecord(context.human_input);
1078
+ const openQuestions = Array.isArray(humanInput.open_questions) ? humanInput.open_questions : [];
1079
+ if (openQuestions.length > 0) {
1080
+ return false;
1081
+ }
1082
+ const ambiguities = this.readOpenIntakeAmbiguities(context);
1083
+ const answeredAmbiguityIds = await this.readAnsweredIntakeAmbiguityIds(featureId);
1084
+ const priorAnswers = this.readAnsweredIntakeClarifications(context);
1085
+ if (ambiguities.length === 0) {
1086
+ return false;
1087
+ }
1088
+ const frontMatter = asRecord(asRecord(context.state).front_matter);
1089
+ const cluster = asRecord(frontMatter.cluster);
1090
+ const question = await this.toolCaller.callTool('orchestrator', TOOLS.FEATURE_QUESTION_CREATE, {
1091
+ feature_id: featureId,
1092
+ role: 'planner',
1093
+ session_id: asString(cluster.planner_session_id) ?? `planner:intake-recovery:${featureId}`,
1094
+ question_type: 'clarification',
1095
+ prompt: this.buildIntakeClarificationPrompt(ambiguities, answeredAmbiguityIds, priorAnswers),
1096
+ details: {
1097
+ ambiguity_ids: ambiguities.map((ambiguity) => ambiguity.id),
1098
+ obligation_ids: normalizeList(ambiguities.flatMap((ambiguity) => ambiguity.obligationIds)),
1099
+ prior_answered_ambiguity_ids: ambiguities
1100
+ .filter((ambiguity) => answeredAmbiguityIds.has(ambiguity.id))
1101
+ .map((ambiguity) => ambiguity.id),
1102
+ recovery_reason: recoveryReason,
1103
+ recovery_source: 'planning_wave_executor',
1104
+ },
1105
+ expected_answer: {
1106
+ kind: 'free_text',
1107
+ },
1108
+ blocking: true,
1109
+ phase: STATUS.INTAKE,
1110
+ request_action: 'ask_user_input',
1111
+ resume_status: STATUS.INTAKE,
1112
+ resume_phase: STATUS.INTAKE,
1113
+ });
1114
+ this.noProgressByFeature.delete(featureId);
1115
+ this.lastStatusByFeature.set(featureId, STATUS.AWAITING_INPUT);
1116
+ await this.toolCaller.callTool('orchestrator', TOOLS.FEATURE_LOG_APPEND, {
1117
+ feature_id: featureId,
1118
+ note: JSON.stringify({
1119
+ phase: 'planning',
1120
+ action: 'ask_user_input',
1121
+ decision: 'awaiting_input',
1122
+ question_id: asRecord(question.data).question_id ?? null,
1123
+ recovery_reason: recoveryReason,
1124
+ ambiguity_ids: ambiguities.map((ambiguity) => ambiguity.id),
1125
+ }),
1126
+ });
1127
+ return true;
1128
+ }
1129
+ buildPlannerRecoveryFrontMatter(frontMatter, errorCode, phase) {
1130
+ const existingRecovery = asRecord(frontMatter.recovery);
1131
+ const nextAttempt = (typeof existingRecovery.attempt === 'number' && Number.isFinite(existingRecovery.attempt)
1132
+ ? Math.max(0, Math.floor(existingRecovery.attempt))
1133
+ : 0) + 1;
1134
+ const now = new Date().toISOString();
1135
+ return {
1136
+ state: 'retrying',
1137
+ cause: errorCode,
1138
+ role: 'planner',
1139
+ resume_phase: phase,
1140
+ attempt: nextAttempt,
1141
+ run_id: this.resolveRunId(),
1142
+ started_at: asString(existingRecovery.started_at) ?? now,
1143
+ last_attempt_at: now,
1144
+ };
1145
+ }
452
1146
  async applyWorkerPolicyAction(featureId, action, errorCode, message, phase = 'planning') {
453
1147
  if (action === 'fail_run') {
454
1148
  const error = new Error(message);
@@ -467,6 +1161,7 @@ export class PlanningWaveExecutor {
467
1161
  const expectedVersion = typeof frontMatter.version === 'number' && Number.isFinite(frontMatter.version)
468
1162
  ? Math.floor(frontMatter.version)
469
1163
  : null;
1164
+ const recovery = this.buildPlannerRecoveryFrontMatter(frontMatter, errorCode, phase);
470
1165
  await this.toolCaller.callTool('orchestrator', TOOLS.FEATURE_STATE_PATCH, {
471
1166
  feature_id: featureId,
472
1167
  expected_version: expectedVersion,
@@ -474,6 +1169,7 @@ export class PlanningWaveExecutor {
474
1169
  front_matter: {
475
1170
  status: STATUS.BLOCKED,
476
1171
  status_reason: `${errorCode}: ${message}`,
1172
+ recovery,
477
1173
  },
478
1174
  },
479
1175
  });
@@ -485,6 +1181,8 @@ export class PlanningWaveExecutor {
485
1181
  decision: 'blocked',
486
1182
  error_code: errorCode,
487
1183
  reason: message,
1184
+ recovery_state: recovery.state,
1185
+ recovery_attempt: recovery.attempt,
488
1186
  }),
489
1187
  });
490
1188
  }