agentic-orchestrator 0.1.28 → 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 (836) 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 +231 -16
  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 +723 -20
  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/performance-analytics.spec.ts +124 -0
  236. package/apps/control-plane/test/plan-conformance-scorer.spec.ts +53 -0
  237. package/apps/control-plane/test/plan-service.spec.ts +686 -4
  238. package/apps/control-plane/test/planning-wave-executor.spec.ts +3272 -86
  239. package/apps/control-plane/test/policy-loader-service.spec.ts +5 -0
  240. package/apps/control-plane/test/prompt-overlay.spec.ts +65 -0
  241. package/apps/control-plane/test/provider-command-runner-epipe.spec.ts +64 -0
  242. package/apps/control-plane/test/providers/api-worker-provider.spec.ts +129 -0
  243. package/apps/control-plane/test/providers/cli-worker-provider.spec.ts +148 -0
  244. package/apps/control-plane/test/providers/usage-types.spec.ts +98 -0
  245. package/apps/control-plane/test/providers.spec.ts +293 -16
  246. package/apps/control-plane/test/question-command-handlers.spec.ts +156 -0
  247. package/apps/control-plane/test/question-service.spec.ts +1119 -0
  248. package/apps/control-plane/test/reactions.spec.ts +114 -0
  249. package/apps/control-plane/test/replay-command-handler.spec.ts +144 -0
  250. package/apps/control-plane/test/replay-timeline-service.spec.ts +459 -0
  251. package/apps/control-plane/test/response.spec.ts +31 -0
  252. package/apps/control-plane/test/resume-command.spec.ts +757 -9
  253. package/apps/control-plane/test/retry-resume-decision.spec.ts +133 -0
  254. package/apps/control-plane/test/rollback-command-handler.spec.ts +334 -0
  255. package/apps/control-plane/test/rollback-command.spec.ts +120 -0
  256. package/apps/control-plane/test/run-coordinator.spec.ts +3062 -404
  257. package/apps/control-plane/test/schemas/state.schema.spec.ts +71 -0
  258. package/apps/control-plane/test/service-retry-paths.spec.ts +112 -0
  259. package/apps/control-plane/test/services.spec.ts +472 -2
  260. package/apps/control-plane/test/session-management.spec.ts +346 -1
  261. package/apps/control-plane/test/spec-ingestion.spec.ts +102 -28
  262. package/apps/control-plane/test/spec-preparation.spec.ts +182 -0
  263. package/apps/control-plane/test/supervisor-collaborators.spec.ts +191 -3
  264. package/apps/control-plane/test/supervisor.calltool.spec.ts +198 -0
  265. package/apps/control-plane/test/supervisor.spec.ts +95 -16
  266. package/apps/control-plane/test/supervisor.unit.spec.ts +385 -18
  267. package/apps/control-plane/test/tool-runtime.spec.ts +122 -0
  268. package/apps/control-plane/test/worker-decision-loop.spec.ts +3479 -476
  269. package/apps/control-plane/test/worker-execution-policy.spec.ts +1416 -6
  270. package/apps/control-plane/test/worker-provider-adapters.spec.ts +1894 -37
  271. package/apps/control-plane/test/worker-provider-factory.spec.ts +81 -0
  272. package/apps/control-plane/test/worktree-watchdog-service.spec.ts +125 -0
  273. package/apps/control-plane/vitest.config.ts +5 -0
  274. package/config/agentic/orchestrator/agents.yaml +22 -1
  275. package/config/agentic/orchestrator/gates.yaml +24 -7
  276. package/config/agentic/orchestrator/policy.yaml +23 -1
  277. package/config/agentic/orchestrator/prompts/builder.system.md +69 -20
  278. package/config/agentic/orchestrator/prompts/organizer.system.md +85 -0
  279. package/config/agentic/orchestrator/prompts/overrides/builder.claude.md +28 -0
  280. package/config/agentic/orchestrator/prompts/overrides/builder.codex.md +28 -0
  281. package/config/agentic/orchestrator/prompts/overrides/planner.claude.md +20 -0
  282. package/config/agentic/orchestrator/prompts/overrides/planner.codex.md +20 -0
  283. package/config/agentic/orchestrator/prompts/planner-intake.system.md +149 -0
  284. package/config/agentic/orchestrator/prompts/planner.system.md +113 -40
  285. package/config/agentic/orchestrator/prompts/qa.system.md +75 -18
  286. package/config/agentic/orchestrator/prompts/reconciler.system.md +119 -0
  287. package/dist/apps/control-plane/application/kernel-tool-wiring.d.ts +26 -2
  288. package/dist/apps/control-plane/application/kernel-tool-wiring.js +40 -2
  289. package/dist/apps/control-plane/application/kernel-tool-wiring.js.map +1 -1
  290. package/dist/apps/control-plane/application/services/activity-monitor-service.js +37 -1
  291. package/dist/apps/control-plane/application/services/activity-monitor-service.js.map +1 -1
  292. package/dist/apps/control-plane/application/services/bootstrap-manifest-generator-service.d.ts +4 -0
  293. package/dist/apps/control-plane/application/services/bootstrap-manifest-generator-service.js +188 -0
  294. package/dist/apps/control-plane/application/services/bootstrap-manifest-generator-service.js.map +1 -0
  295. package/dist/apps/control-plane/application/services/checkpoint-service.d.ts +5 -0
  296. package/dist/apps/control-plane/application/services/checkpoint-service.js +69 -24
  297. package/dist/apps/control-plane/application/services/checkpoint-service.js.map +1 -1
  298. package/dist/apps/control-plane/application/services/collision-override-service.d.ts +139 -0
  299. package/dist/apps/control-plane/application/services/collision-override-service.js +568 -0
  300. package/dist/apps/control-plane/application/services/collision-override-service.js.map +1 -0
  301. package/dist/apps/control-plane/application/services/collision-queue-service.d.ts +15 -0
  302. package/dist/apps/control-plane/application/services/collision-queue-service.js +92 -33
  303. package/dist/apps/control-plane/application/services/collision-queue-service.js.map +1 -1
  304. package/dist/apps/control-plane/application/services/cost-tracking-service.d.ts +11 -0
  305. package/dist/apps/control-plane/application/services/cost-tracking-service.js +75 -0
  306. package/dist/apps/control-plane/application/services/cost-tracking-service.js.map +1 -1
  307. package/dist/apps/control-plane/application/services/execution-control-service.d.ts +75 -0
  308. package/dist/apps/control-plane/application/services/execution-control-service.js +421 -0
  309. package/dist/apps/control-plane/application/services/execution-control-service.js.map +1 -0
  310. package/dist/apps/control-plane/application/services/feature-deletion-service.d.ts +1 -0
  311. package/dist/apps/control-plane/application/services/feature-deletion-service.js +23 -1
  312. package/dist/apps/control-plane/application/services/feature-deletion-service.js.map +1 -1
  313. package/dist/apps/control-plane/application/services/feature-lifecycle-service.d.ts +24 -1
  314. package/dist/apps/control-plane/application/services/feature-lifecycle-service.js +132 -3
  315. package/dist/apps/control-plane/application/services/feature-lifecycle-service.js.map +1 -1
  316. package/dist/apps/control-plane/application/services/feature-send-message-service.js +16 -8
  317. package/dist/apps/control-plane/application/services/feature-send-message-service.js.map +1 -1
  318. package/dist/apps/control-plane/application/services/feature-state-service.d.ts +36 -0
  319. package/dist/apps/control-plane/application/services/feature-state-service.js +163 -6
  320. package/dist/apps/control-plane/application/services/feature-state-service.js.map +1 -1
  321. package/dist/apps/control-plane/application/services/gate-service.d.ts +2 -1
  322. package/dist/apps/control-plane/application/services/gate-service.js +95 -5
  323. package/dist/apps/control-plane/application/services/gate-service.js.map +1 -1
  324. package/dist/apps/control-plane/application/services/git-reconciliation-service.d.ts +92 -0
  325. package/dist/apps/control-plane/application/services/git-reconciliation-service.js +1097 -0
  326. package/dist/apps/control-plane/application/services/git-reconciliation-service.js.map +1 -0
  327. package/dist/apps/control-plane/application/services/intake-service.d.ts +63 -0
  328. package/dist/apps/control-plane/application/services/intake-service.js +1050 -0
  329. package/dist/apps/control-plane/application/services/intake-service.js.map +1 -0
  330. package/dist/apps/control-plane/application/services/merge-service.d.ts +5 -1
  331. package/dist/apps/control-plane/application/services/merge-service.js +233 -18
  332. package/dist/apps/control-plane/application/services/merge-service.js.map +1 -1
  333. package/dist/apps/control-plane/application/services/notifier-service.d.ts +1 -1
  334. package/dist/apps/control-plane/application/services/notifier-service.js +1 -0
  335. package/dist/apps/control-plane/application/services/notifier-service.js.map +1 -1
  336. package/dist/apps/control-plane/application/services/performance-analytics-service.d.ts +11 -0
  337. package/dist/apps/control-plane/application/services/performance-analytics-service.js +59 -0
  338. package/dist/apps/control-plane/application/services/performance-analytics-service.js.map +1 -1
  339. package/dist/apps/control-plane/application/services/plan-service.d.ts +5 -0
  340. package/dist/apps/control-plane/application/services/plan-service.js +254 -15
  341. package/dist/apps/control-plane/application/services/plan-service.js.map +1 -1
  342. package/dist/apps/control-plane/application/services/question-service.d.ts +72 -0
  343. package/dist/apps/control-plane/application/services/question-service.js +507 -0
  344. package/dist/apps/control-plane/application/services/question-service.js.map +1 -0
  345. package/dist/apps/control-plane/application/services/reactions-service.d.ts +2 -0
  346. package/dist/apps/control-plane/application/services/reactions-service.js +60 -17
  347. package/dist/apps/control-plane/application/services/reactions-service.js.map +1 -1
  348. package/dist/apps/control-plane/application/services/replay-timeline-service.d.ts +39 -0
  349. package/dist/apps/control-plane/application/services/replay-timeline-service.js +205 -0
  350. package/dist/apps/control-plane/application/services/replay-timeline-service.js.map +1 -0
  351. package/dist/apps/control-plane/application/services/reporting-service.d.ts +59 -0
  352. package/dist/apps/control-plane/application/services/reporting-service.js +121 -9
  353. package/dist/apps/control-plane/application/services/reporting-service.js.map +1 -1
  354. package/dist/apps/control-plane/application/services/run-lease-service.d.ts +20 -0
  355. package/dist/apps/control-plane/application/services/run-lease-service.js +81 -4
  356. package/dist/apps/control-plane/application/services/run-lease-service.js.map +1 -1
  357. package/dist/apps/control-plane/application/services/worktree-watchdog-service.d.ts +10 -0
  358. package/dist/apps/control-plane/application/services/worktree-watchdog-service.js +65 -8
  359. package/dist/apps/control-plane/application/services/worktree-watchdog-service.js.map +1 -1
  360. package/dist/apps/control-plane/application/tools/tool-metadata.js +7 -0
  361. package/dist/apps/control-plane/application/tools/tool-metadata.js.map +1 -1
  362. package/dist/apps/control-plane/application/usage-types.d.ts +65 -0
  363. package/dist/apps/control-plane/application/usage-types.js +75 -0
  364. package/dist/apps/control-plane/application/usage-types.js.map +1 -0
  365. package/dist/apps/control-plane/cli/add-command-handler.d.ts +18 -0
  366. package/dist/apps/control-plane/cli/add-command-handler.js +110 -0
  367. package/dist/apps/control-plane/cli/add-command-handler.js.map +1 -0
  368. package/dist/apps/control-plane/cli/answer-command-handler.d.ts +8 -0
  369. package/dist/apps/control-plane/cli/answer-command-handler.js +96 -0
  370. package/dist/apps/control-plane/cli/answer-command-handler.js.map +1 -0
  371. package/dist/apps/control-plane/cli/attach-command-handler.js +8 -3
  372. package/dist/apps/control-plane/cli/attach-command-handler.js.map +1 -1
  373. package/dist/apps/control-plane/cli/cli-argument-parser.js +131 -11
  374. package/dist/apps/control-plane/cli/cli-argument-parser.js.map +1 -1
  375. package/dist/apps/control-plane/cli/collision-command-handler.d.ts +8 -0
  376. package/dist/apps/control-plane/cli/collision-command-handler.js +90 -0
  377. package/dist/apps/control-plane/cli/collision-command-handler.js.map +1 -0
  378. package/dist/apps/control-plane/cli/command-catalog.d.ts +21 -0
  379. package/dist/apps/control-plane/cli/command-catalog.js +416 -0
  380. package/dist/apps/control-plane/cli/command-catalog.js.map +1 -0
  381. package/dist/apps/control-plane/cli/complete-command-handler.d.ts +15 -0
  382. package/dist/apps/control-plane/cli/complete-command-handler.js +26 -0
  383. package/dist/apps/control-plane/cli/complete-command-handler.js.map +1 -0
  384. package/dist/apps/control-plane/cli/completion-command-handler.d.ts +8 -0
  385. package/dist/apps/control-plane/cli/completion-command-handler.js +20 -0
  386. package/dist/apps/control-plane/cli/completion-command-handler.js.map +1 -0
  387. package/dist/apps/control-plane/cli/completion-resolver.d.ts +1 -0
  388. package/dist/apps/control-plane/cli/completion-resolver.js +250 -0
  389. package/dist/apps/control-plane/cli/completion-resolver.js.map +1 -0
  390. package/dist/apps/control-plane/cli/completion-shell-renderer.d.ts +3 -0
  391. package/dist/apps/control-plane/cli/completion-shell-renderer.js +53 -0
  392. package/dist/apps/control-plane/cli/completion-shell-renderer.js.map +1 -0
  393. package/dist/apps/control-plane/cli/dashboard-command-handler.d.ts +1 -0
  394. package/dist/apps/control-plane/cli/dashboard-command-handler.js +83 -1
  395. package/dist/apps/control-plane/cli/dashboard-command-handler.js.map +1 -1
  396. package/dist/apps/control-plane/cli/dashboard-runtime-runner.d.ts +81 -0
  397. package/dist/apps/control-plane/cli/dashboard-runtime-runner.js +724 -0
  398. package/dist/apps/control-plane/cli/dashboard-runtime-runner.js.map +1 -0
  399. package/dist/apps/control-plane/cli/dashboard-runtime.d.ts +1 -0
  400. package/dist/apps/control-plane/cli/dashboard-runtime.js +26 -0
  401. package/dist/apps/control-plane/cli/dashboard-runtime.js.map +1 -0
  402. package/dist/apps/control-plane/cli/help-command-handler.js +13 -172
  403. package/dist/apps/control-plane/cli/help-command-handler.js.map +1 -1
  404. package/dist/apps/control-plane/cli/init-command-handler.js +51 -6
  405. package/dist/apps/control-plane/cli/init-command-handler.js.map +1 -1
  406. package/dist/apps/control-plane/cli/merge-command-handler.d.ts +8 -0
  407. package/dist/apps/control-plane/cli/merge-command-handler.js +139 -0
  408. package/dist/apps/control-plane/cli/merge-command-handler.js.map +1 -0
  409. package/dist/apps/control-plane/cli/questions-command-handler.d.ts +8 -0
  410. package/dist/apps/control-plane/cli/questions-command-handler.js +59 -0
  411. package/dist/apps/control-plane/cli/questions-command-handler.js.map +1 -0
  412. package/dist/apps/control-plane/cli/replay-command-handler.d.ts +15 -0
  413. package/dist/apps/control-plane/cli/replay-command-handler.js +55 -0
  414. package/dist/apps/control-plane/cli/replay-command-handler.js.map +1 -0
  415. package/dist/apps/control-plane/cli/resume-command-handler.d.ts +2 -0
  416. package/dist/apps/control-plane/cli/resume-command-handler.js +180 -17
  417. package/dist/apps/control-plane/cli/resume-command-handler.js.map +1 -1
  418. package/dist/apps/control-plane/cli/retry-command-handler.js +202 -16
  419. package/dist/apps/control-plane/cli/retry-command-handler.js.map +1 -1
  420. package/dist/apps/control-plane/cli/retry-resume-decision.d.ts +26 -0
  421. package/dist/apps/control-plane/cli/retry-resume-decision.js +61 -0
  422. package/dist/apps/control-plane/cli/retry-resume-decision.js.map +1 -0
  423. package/dist/apps/control-plane/cli/rollback-command-handler.js +3 -2
  424. package/dist/apps/control-plane/cli/rollback-command-handler.js.map +1 -1
  425. package/dist/apps/control-plane/cli/run-command-handler.js +26 -2
  426. package/dist/apps/control-plane/cli/run-command-handler.js.map +1 -1
  427. package/dist/apps/control-plane/cli/spec-ingestion-service.d.ts +2 -0
  428. package/dist/apps/control-plane/cli/spec-ingestion-service.js +37 -48
  429. package/dist/apps/control-plane/cli/spec-ingestion-service.js.map +1 -1
  430. package/dist/apps/control-plane/cli/spec-preparation.d.ts +14 -0
  431. package/dist/apps/control-plane/cli/spec-preparation.js +81 -0
  432. package/dist/apps/control-plane/cli/spec-preparation.js.map +1 -0
  433. package/dist/apps/control-plane/cli/spec-utils.d.ts +4 -0
  434. package/dist/apps/control-plane/cli/spec-utils.js +70 -11
  435. package/dist/apps/control-plane/cli/spec-utils.js.map +1 -1
  436. package/dist/apps/control-plane/cli/status-command-handler.js +69 -0
  437. package/dist/apps/control-plane/cli/status-command-handler.js.map +1 -1
  438. package/dist/apps/control-plane/cli/types.d.ts +41 -4
  439. package/dist/apps/control-plane/cli/types.js +9 -1
  440. package/dist/apps/control-plane/cli/types.js.map +1 -1
  441. package/dist/apps/control-plane/core/collisions.d.ts +37 -19
  442. package/dist/apps/control-plane/core/collisions.js +87 -12
  443. package/dist/apps/control-plane/core/collisions.js.map +1 -1
  444. package/dist/apps/control-plane/core/constants.d.ts +17 -1
  445. package/dist/apps/control-plane/core/constants.js +18 -1
  446. package/dist/apps/control-plane/core/constants.js.map +1 -1
  447. package/dist/apps/control-plane/core/error-codes.d.ts +39 -0
  448. package/dist/apps/control-plane/core/error-codes.js +39 -0
  449. package/dist/apps/control-plane/core/error-codes.js.map +1 -1
  450. package/dist/apps/control-plane/core/execution-control.d.ts +45 -0
  451. package/dist/apps/control-plane/core/execution-control.js +2 -0
  452. package/dist/apps/control-plane/core/execution-control.js.map +1 -0
  453. package/dist/apps/control-plane/core/feature-resume-phase.d.ts +3 -0
  454. package/dist/apps/control-plane/core/feature-resume-phase.js +88 -0
  455. package/dist/apps/control-plane/core/feature-resume-phase.js.map +1 -0
  456. package/dist/apps/control-plane/core/gate-freshness.d.ts +48 -0
  457. package/dist/apps/control-plane/core/gate-freshness.js +267 -0
  458. package/dist/apps/control-plane/core/gate-freshness.js.map +1 -0
  459. package/dist/apps/control-plane/core/gate-log-extractor.d.ts +22 -0
  460. package/dist/apps/control-plane/core/gate-log-extractor.js +66 -0
  461. package/dist/apps/control-plane/core/gate-log-extractor.js.map +1 -0
  462. package/dist/apps/control-plane/core/gates.d.ts +11 -2
  463. package/dist/apps/control-plane/core/gates.js +67 -3
  464. package/dist/apps/control-plane/core/gates.js.map +1 -1
  465. package/dist/apps/control-plane/core/intake-artifacts.d.ts +109 -0
  466. package/dist/apps/control-plane/core/intake-artifacts.js +143 -0
  467. package/dist/apps/control-plane/core/intake-artifacts.js.map +1 -0
  468. package/dist/apps/control-plane/core/kernel-types.d.ts +8 -0
  469. package/dist/apps/control-plane/core/kernel.d.ts +256 -8
  470. package/dist/apps/control-plane/core/kernel.js +400 -14
  471. package/dist/apps/control-plane/core/kernel.js.map +1 -1
  472. package/dist/apps/control-plane/core/mainline-conflict.d.ts +7 -0
  473. package/dist/apps/control-plane/core/mainline-conflict.js +20 -0
  474. package/dist/apps/control-plane/core/mainline-conflict.js.map +1 -0
  475. package/dist/apps/control-plane/core/merge-repair.d.ts +35 -0
  476. package/dist/apps/control-plane/core/merge-repair.js +99 -0
  477. package/dist/apps/control-plane/core/merge-repair.js.map +1 -0
  478. package/dist/apps/control-plane/core/path-layout.d.ts +10 -0
  479. package/dist/apps/control-plane/core/path-layout.js +32 -2
  480. package/dist/apps/control-plane/core/path-layout.js.map +1 -1
  481. package/dist/apps/control-plane/core/path-rules.js +9 -3
  482. package/dist/apps/control-plane/core/path-rules.js.map +1 -1
  483. package/dist/apps/control-plane/core/plan-submit-recovery.d.ts +22 -0
  484. package/dist/apps/control-plane/core/plan-submit-recovery.js +78 -0
  485. package/dist/apps/control-plane/core/plan-submit-recovery.js.map +1 -0
  486. package/dist/apps/control-plane/core/questions.d.ts +40 -0
  487. package/dist/apps/control-plane/core/questions.js +2 -0
  488. package/dist/apps/control-plane/core/questions.js.map +1 -0
  489. package/dist/apps/control-plane/core/runtime-sessions.d.ts +4 -0
  490. package/dist/apps/control-plane/core/schemas.d.ts +2 -0
  491. package/dist/apps/control-plane/core/schemas.js +31 -1
  492. package/dist/apps/control-plane/core/schemas.js.map +1 -1
  493. package/dist/apps/control-plane/core/tool-caller.d.ts +18 -1
  494. package/dist/apps/control-plane/core/utils/index-normalizer.js +17 -4
  495. package/dist/apps/control-plane/core/utils/index-normalizer.js.map +1 -1
  496. package/dist/apps/control-plane/core/worktree-diff.d.ts +4 -0
  497. package/dist/apps/control-plane/core/worktree-diff.js +52 -0
  498. package/dist/apps/control-plane/core/worktree-diff.js.map +1 -0
  499. package/dist/apps/control-plane/index.d.ts +10 -2
  500. package/dist/apps/control-plane/index.js +9 -2
  501. package/dist/apps/control-plane/index.js.map +1 -1
  502. package/dist/apps/control-plane/interfaces/cli/bootstrap.js +236 -6
  503. package/dist/apps/control-plane/interfaces/cli/bootstrap.js.map +1 -1
  504. package/dist/apps/control-plane/mcp/kernel-tool-executor.js +16 -0
  505. package/dist/apps/control-plane/mcp/kernel-tool-executor.js.map +1 -1
  506. package/dist/apps/control-plane/mcp/tool-runtime.d.ts +5 -0
  507. package/dist/apps/control-plane/mcp/tool-runtime.js +40 -5
  508. package/dist/apps/control-plane/mcp/tool-runtime.js.map +1 -1
  509. package/dist/apps/control-plane/providers/api-worker-provider.d.ts +2 -2
  510. package/dist/apps/control-plane/providers/api-worker-provider.js +40 -9
  511. package/dist/apps/control-plane/providers/api-worker-provider.js.map +1 -1
  512. package/dist/apps/control-plane/providers/cli-worker-provider.d.ts +59 -3
  513. package/dist/apps/control-plane/providers/cli-worker-provider.js +758 -46
  514. package/dist/apps/control-plane/providers/cli-worker-provider.js.map +1 -1
  515. package/dist/apps/control-plane/providers/output-parsers/generic-output-parser.js +91 -1
  516. package/dist/apps/control-plane/providers/output-parsers/generic-output-parser.js.map +1 -1
  517. package/dist/apps/control-plane/providers/output-parsers/types.d.ts +2 -0
  518. package/dist/apps/control-plane/providers/provider-defaults.d.ts +12 -0
  519. package/dist/apps/control-plane/providers/provider-defaults.js +103 -7
  520. package/dist/apps/control-plane/providers/provider-defaults.js.map +1 -1
  521. package/dist/apps/control-plane/providers/providers.d.ts +50 -4
  522. package/dist/apps/control-plane/providers/providers.js +145 -14
  523. package/dist/apps/control-plane/providers/providers.js.map +1 -1
  524. package/dist/apps/control-plane/providers/worker-provider-factory.d.ts +2 -0
  525. package/dist/apps/control-plane/providers/worker-provider-factory.js +8 -1
  526. package/dist/apps/control-plane/providers/worker-provider-factory.js.map +1 -1
  527. package/dist/apps/control-plane/supervisor/artifact-stager.d.ts +5 -0
  528. package/dist/apps/control-plane/supervisor/artifact-stager.js +45 -0
  529. package/dist/apps/control-plane/supervisor/artifact-stager.js.map +1 -0
  530. package/dist/apps/control-plane/supervisor/build-wave-executor.d.ts +24 -1
  531. package/dist/apps/control-plane/supervisor/build-wave-executor.js +362 -150
  532. package/dist/apps/control-plane/supervisor/build-wave-executor.js.map +1 -1
  533. package/dist/apps/control-plane/supervisor/execution-enrollment-service.d.ts +41 -0
  534. package/dist/apps/control-plane/supervisor/execution-enrollment-service.js +311 -0
  535. package/dist/apps/control-plane/supervisor/execution-enrollment-service.js.map +1 -0
  536. package/dist/apps/control-plane/supervisor/organizer-enrollment-scheduler.d.ts +15 -0
  537. package/dist/apps/control-plane/supervisor/organizer-enrollment-scheduler.js +93 -0
  538. package/dist/apps/control-plane/supervisor/organizer-enrollment-scheduler.js.map +1 -0
  539. package/dist/apps/control-plane/supervisor/organizer-sidecar-service.d.ts +44 -0
  540. package/dist/apps/control-plane/supervisor/organizer-sidecar-service.js +311 -0
  541. package/dist/apps/control-plane/supervisor/organizer-sidecar-service.js.map +1 -0
  542. package/dist/apps/control-plane/supervisor/plan-conformance-scorer.js +2 -5
  543. package/dist/apps/control-plane/supervisor/plan-conformance-scorer.js.map +1 -1
  544. package/dist/apps/control-plane/supervisor/planner-phase.d.ts +3 -0
  545. package/dist/apps/control-plane/supervisor/planner-phase.js +70 -0
  546. package/dist/apps/control-plane/supervisor/planner-phase.js.map +1 -0
  547. package/dist/apps/control-plane/supervisor/planning-wave-executor.d.ts +42 -0
  548. package/dist/apps/control-plane/supervisor/planning-wave-executor.js +753 -55
  549. package/dist/apps/control-plane/supervisor/planning-wave-executor.js.map +1 -1
  550. package/dist/apps/control-plane/supervisor/prompt-bundle-loader.js +19 -1
  551. package/dist/apps/control-plane/supervisor/prompt-bundle-loader.js.map +1 -1
  552. package/dist/apps/control-plane/supervisor/qa-wave-executor.d.ts +21 -0
  553. package/dist/apps/control-plane/supervisor/qa-wave-executor.js +287 -156
  554. package/dist/apps/control-plane/supervisor/qa-wave-executor.js.map +1 -1
  555. package/dist/apps/control-plane/supervisor/run-coordinator.d.ts +30 -1
  556. package/dist/apps/control-plane/supervisor/run-coordinator.js +561 -17
  557. package/dist/apps/control-plane/supervisor/run-coordinator.js.map +1 -1
  558. package/dist/apps/control-plane/supervisor/runtime.d.ts +84 -0
  559. package/dist/apps/control-plane/supervisor/runtime.js +393 -3
  560. package/dist/apps/control-plane/supervisor/runtime.js.map +1 -1
  561. package/dist/apps/control-plane/supervisor/session-orchestrator.d.ts +54 -0
  562. package/dist/apps/control-plane/supervisor/session-orchestrator.js +176 -1
  563. package/dist/apps/control-plane/supervisor/session-orchestrator.js.map +1 -1
  564. package/dist/apps/control-plane/supervisor/types.d.ts +142 -1
  565. package/dist/apps/control-plane/supervisor/types.js.map +1 -1
  566. package/dist/apps/control-plane/supervisor/worker-decision-loop.d.ts +68 -2
  567. package/dist/apps/control-plane/supervisor/worker-decision-loop.js +723 -89
  568. package/dist/apps/control-plane/supervisor/worker-decision-loop.js.map +1 -1
  569. package/docs/core/ARCHITECTURE.md +227 -0
  570. package/docs/core/DECISIONS.md +94 -0
  571. package/docs/core/DOMAIN-LOGIC.md +60 -0
  572. package/docs/core/PATTERNS.md +201 -0
  573. package/docs/core/TROUBLESHOOTING.md +347 -0
  574. package/docs/core/intentgraph-dependencies.json +39860 -0
  575. package/docs/core/intentgraph.index.json +46580 -0
  576. package/docs/plans/2026-03-10-gate-failure-targeted-repair-design.md +224 -0
  577. package/docs/plans/2026-03-10-gate-failure-targeted-repair.md +1032 -0
  578. package/docs/superpowers/plans/2026-03-16-provider-cli-config.md +743 -0
  579. package/docs/superpowers/plans/2026-03-23-reconcile-divergence-fix.md +777 -0
  580. package/docs/superpowers/plans/2026-03-28-ordering-agent-implementation.md +1754 -0
  581. package/docs/superpowers/plans/2026-03-29-drop-zone-and-provider-optimization.md +1108 -0
  582. package/docs/superpowers/plans/2026-03-29-merge-target-feature-branch.md +685 -0
  583. package/docs/superpowers/plans/2026-03-29-organizer-sidecar-runtime-loop.md +1289 -0
  584. package/docs/superpowers/specs/2026-03-23-reconcile-divergence-fix-design.md +118 -0
  585. package/docs/superpowers/specs/2026-03-28-ordering-agent-spec-audit-design.md +50 -0
  586. package/docs/superpowers/specs/2026-03-29-drop-zone-and-provider-optimization-design.md +254 -0
  587. package/docs/superpowers/specs/2026-03-29-merge-target-feature-branch-design.md +152 -0
  588. package/docs/superpowers/specs/2026-03-29-organizer-sidecar-runtime-loop-design.md +225 -0
  589. package/package.json +3 -2
  590. package/packages/web-dashboard/package.json +2 -1
  591. package/packages/web-dashboard/src/app/analytics/page.tsx +36 -2
  592. package/packages/web-dashboard/src/app/api/actions/route.ts +274 -63
  593. package/packages/web-dashboard/src/app/api/actions/status/route.ts +35 -0
  594. package/packages/web-dashboard/src/app/api/analytics/provider/route.ts +18 -0
  595. package/packages/web-dashboard/src/app/api/collisions/approve/route.ts +58 -0
  596. package/packages/web-dashboard/src/app/api/features/[id]/checkpoint-diff/route.ts +36 -0
  597. package/packages/web-dashboard/src/app/api/features/[id]/checkpoints/route.ts +29 -0
  598. package/packages/web-dashboard/src/app/api/features/[id]/conflicts/abort/route.ts +29 -0
  599. package/packages/web-dashboard/src/app/api/features/[id]/conflicts/files/route.ts +30 -0
  600. package/packages/web-dashboard/src/app/api/features/[id]/conflicts/resolve/route.ts +51 -0
  601. package/packages/web-dashboard/src/app/api/features/[id]/conflicts/route.ts +75 -0
  602. package/packages/web-dashboard/src/app/api/features/[id]/diff/route.ts +16 -2
  603. package/packages/web-dashboard/src/app/api/features/[id]/files/route.ts +26 -0
  604. package/packages/web-dashboard/src/app/api/features/[id]/gate-history/route.ts +27 -0
  605. package/packages/web-dashboard/src/app/api/features/[id]/genealogy/route.ts +26 -0
  606. package/packages/web-dashboard/src/app/api/features/[id]/history/run/[runId]/route.ts +20 -0
  607. package/packages/web-dashboard/src/app/api/features/[id]/history/runs/route.ts +34 -0
  608. package/packages/web-dashboard/src/app/api/features/[id]/intake-workspace/route.ts +20 -0
  609. package/packages/web-dashboard/src/app/api/features/[id]/live-output/route.ts +74 -0
  610. package/packages/web-dashboard/src/app/api/features/[id]/plan/amend/route.ts +21 -0
  611. package/packages/web-dashboard/src/app/api/features/[id]/plan-progress/route.ts +20 -0
  612. package/packages/web-dashboard/src/app/api/features/[id]/planner-artifacts/[artifact]/route.ts +78 -0
  613. package/packages/web-dashboard/src/app/api/features/[id]/planner-lifecycle/route.ts +20 -0
  614. package/packages/web-dashboard/src/app/api/features/[id]/planning-workspace/route.ts +20 -0
  615. package/packages/web-dashboard/src/app/api/features/[id]/questions/[questionId]/answer/route.ts +27 -0
  616. package/packages/web-dashboard/src/app/api/features/[id]/questions/route.ts +18 -0
  617. package/packages/web-dashboard/src/app/api/features/[id]/review/route.ts +14 -7
  618. package/packages/web-dashboard/src/app/api/features/[id]/route.ts +57 -2
  619. package/packages/web-dashboard/src/app/api/features/[id]/spec/route.ts +30 -0
  620. package/packages/web-dashboard/src/app/api/features/[id]/triage/route.ts +83 -0
  621. package/packages/web-dashboard/src/app/api/features/[id]/worker-events/route.ts +40 -0
  622. package/packages/web-dashboard/src/app/api/launch/preview/route.ts +86 -0
  623. package/packages/web-dashboard/src/app/api/launch/submit/route.ts +180 -0
  624. package/packages/web-dashboard/src/app/api/mainline/status/route.ts +74 -0
  625. package/packages/web-dashboard/src/app/api/merge-queue/route.ts +13 -0
  626. package/packages/web-dashboard/src/app/api/policy/budget/route.ts +14 -0
  627. package/packages/web-dashboard/src/app/api/projects/route.ts +11 -7
  628. package/packages/web-dashboard/src/app/api/reconciler/queue/route.ts +47 -0
  629. package/packages/web-dashboard/src/app/api/run/route.ts +26 -2
  630. package/packages/web-dashboard/src/app/api/runtime/events/route.ts +227 -0
  631. package/packages/web-dashboard/src/app/api/runtime/operations/route.ts +269 -0
  632. package/packages/web-dashboard/src/app/api/runtime/questions/route.ts +11 -0
  633. package/packages/web-dashboard/src/app/api/runtime/runs/route.ts +80 -0
  634. package/packages/web-dashboard/src/app/api/status/route.ts +4 -2
  635. package/packages/web-dashboard/src/app/feature/[id]/page.tsx +32 -42
  636. package/packages/web-dashboard/src/app/globals.css +34 -3
  637. package/packages/web-dashboard/src/app/launch/page.tsx +357 -0
  638. package/packages/web-dashboard/src/app/layout.tsx +23 -1
  639. package/packages/web-dashboard/src/app/page.tsx +263 -272
  640. package/packages/web-dashboard/src/components/dashboard/attention-strip.tsx +52 -0
  641. package/packages/web-dashboard/src/components/dashboard/collision-approval-drawer.tsx +185 -0
  642. package/packages/web-dashboard/src/components/dashboard/command-center-header.tsx +102 -0
  643. package/packages/web-dashboard/src/components/dashboard/mainline-status-banner.tsx +84 -0
  644. package/packages/web-dashboard/src/components/dashboard/merged-archive.tsx +36 -0
  645. package/packages/web-dashboard/src/components/dashboard/prioritized-queues.tsx +98 -0
  646. package/packages/web-dashboard/src/components/dashboard/reconciler-queue-card.tsx +115 -0
  647. package/packages/web-dashboard/src/components/dashboard/secondary-diagnostics-rail.tsx +48 -0
  648. package/packages/web-dashboard/src/components/dashboard/task-filter-bar.tsx +74 -0
  649. package/packages/web-dashboard/src/components/dashboard/triage-drawer.tsx +455 -0
  650. package/packages/web-dashboard/src/components/diff-viewer.tsx +19 -3
  651. package/packages/web-dashboard/src/components/evidence-viewer.tsx +65 -51
  652. package/packages/web-dashboard/src/components/feature-card.tsx +90 -7
  653. package/packages/web-dashboard/src/components/feature-cost-panel.tsx +112 -11
  654. package/packages/web-dashboard/src/components/feature-list-view.tsx +25 -4
  655. package/packages/web-dashboard/src/components/features/runtime-inspector/EventsTimelineView.tsx +260 -0
  656. package/packages/web-dashboard/src/components/features/runtime-inspector/OperationsListView.tsx +172 -0
  657. package/packages/web-dashboard/src/components/features/runtime-inspector/RuntimeInspectorPanel.tsx +896 -0
  658. package/packages/web-dashboard/src/components/filter-bar.tsx +7 -39
  659. package/packages/web-dashboard/src/components/focus/ActionableRiskList.tsx +46 -0
  660. package/packages/web-dashboard/src/components/focus/AgentRolePerformanceCard.tsx +200 -0
  661. package/packages/web-dashboard/src/components/focus/BlockedGuidanceBanner.tsx +149 -0
  662. package/packages/web-dashboard/src/components/focus/CheckpointInspector.tsx +123 -0
  663. package/packages/web-dashboard/src/components/focus/CheckpointRail.tsx +118 -0
  664. package/packages/web-dashboard/src/components/focus/CheckpointScrubber.tsx +249 -0
  665. package/packages/web-dashboard/src/components/focus/CollisionApprovalBanner.tsx +192 -0
  666. package/packages/web-dashboard/src/components/focus/CollisionRadar.tsx +136 -0
  667. package/packages/web-dashboard/src/components/focus/ConflictStatusCard.tsx +52 -0
  668. package/packages/web-dashboard/src/components/focus/ContextSidebar.tsx +108 -0
  669. package/packages/web-dashboard/src/components/focus/DiagnosisPanel.tsx +68 -0
  670. package/packages/web-dashboard/src/components/focus/FeatureDecisionBanner.tsx +68 -0
  671. package/packages/web-dashboard/src/components/focus/FeatureQuestionAnswerPanel.tsx +167 -0
  672. package/packages/web-dashboard/src/components/focus/FocusHeader.tsx +54 -0
  673. package/packages/web-dashboard/src/components/focus/FocusLayout.tsx +283 -0
  674. package/packages/web-dashboard/src/components/focus/GateFlakinessSummary.tsx +144 -0
  675. package/packages/web-dashboard/src/components/focus/GenealogyTree.tsx +34 -0
  676. package/packages/web-dashboard/src/components/focus/HeroBlock.tsx +67 -0
  677. package/packages/web-dashboard/src/components/focus/LiveAgentConsole.tsx +277 -0
  678. package/packages/web-dashboard/src/components/focus/MergeQueueCard.tsx +78 -0
  679. package/packages/web-dashboard/src/components/focus/OperationalSummaryCard.tsx +227 -0
  680. package/packages/web-dashboard/src/components/focus/PinnedActions.tsx +96 -0
  681. package/packages/web-dashboard/src/components/focus/PlanAmendmentPanel.tsx +250 -0
  682. package/packages/web-dashboard/src/components/focus/PlanProgressPanel.tsx +133 -0
  683. package/packages/web-dashboard/src/components/focus/PlannerArtifactViewer.tsx +158 -0
  684. package/packages/web-dashboard/src/components/focus/PlannerLifecycleHeader.tsx +141 -0
  685. package/packages/web-dashboard/src/components/focus/ProgressSnapshotCard.tsx +113 -0
  686. package/packages/web-dashboard/src/components/focus/RecentMaterialChanges.tsx +69 -0
  687. package/packages/web-dashboard/src/components/focus/RoleLogViewer.tsx +436 -0
  688. package/packages/web-dashboard/src/components/focus/RunHistoryBrowser.tsx +62 -0
  689. package/packages/web-dashboard/src/components/focus/SpecViewer.tsx +172 -0
  690. package/packages/web-dashboard/src/components/focus/TabBar.tsx +33 -0
  691. package/packages/web-dashboard/src/components/focus/UsageBurnChart.tsx +212 -0
  692. package/packages/web-dashboard/src/components/focus/VerificationSummaryCard.tsx +122 -0
  693. package/packages/web-dashboard/src/components/focus/tabs/ChangesTab.tsx +325 -0
  694. package/packages/web-dashboard/src/components/focus/tabs/ConflictsTab.tsx +395 -0
  695. package/packages/web-dashboard/src/components/focus/tabs/GatesQaTab.tsx +38 -0
  696. package/packages/web-dashboard/src/components/focus/tabs/HistoryTab.tsx +213 -0
  697. package/packages/web-dashboard/src/components/focus/tabs/IntakeTab.tsx +429 -0
  698. package/packages/web-dashboard/src/components/focus/tabs/OverviewTab.tsx +217 -0
  699. package/packages/web-dashboard/src/components/focus/tabs/PlanningTab.tsx +390 -0
  700. package/packages/web-dashboard/src/components/focus/tabs/ReviewTab.tsx +497 -0
  701. package/packages/web-dashboard/src/components/focus/tabs/RuntimeTab.tsx +213 -0
  702. package/packages/web-dashboard/src/components/focus/tabs/TranscriptTab.tsx +315 -0
  703. package/packages/web-dashboard/src/components/gate-results.tsx +2 -2
  704. package/packages/web-dashboard/src/components/human-input-panel.tsx +33 -57
  705. package/packages/web-dashboard/src/components/kanban-board.tsx +4 -0
  706. package/packages/web-dashboard/src/components/launch/launch-draft-card.tsx +131 -0
  707. package/packages/web-dashboard/src/components/plan-viewer.tsx +147 -69
  708. package/packages/web-dashboard/src/components/quick-launch-panel.tsx +20 -47
  709. package/packages/web-dashboard/src/components/summary-bar.tsx +30 -76
  710. package/packages/web-dashboard/src/lib/aop-client.ts +2484 -36
  711. package/packages/web-dashboard/src/lib/blocked-state-guidance.ts +475 -0
  712. package/packages/web-dashboard/src/lib/collision-radar.ts +136 -0
  713. package/packages/web-dashboard/src/lib/dashboard-action-states.ts +204 -0
  714. package/packages/web-dashboard/src/lib/dashboard-runtime-client.ts +439 -0
  715. package/packages/web-dashboard/src/lib/dashboard-utils.ts +179 -18
  716. package/packages/web-dashboard/src/lib/drop-zone-utils.ts +92 -0
  717. package/packages/web-dashboard/src/lib/focus-detail-derivations.ts +958 -0
  718. package/packages/web-dashboard/src/lib/focus-view.ts +300 -0
  719. package/packages/web-dashboard/src/lib/health-diagnosis.ts +356 -0
  720. package/packages/web-dashboard/src/lib/launch-contracts.ts +77 -0
  721. package/packages/web-dashboard/src/lib/launch-markdown.ts +107 -0
  722. package/packages/web-dashboard/src/lib/launch-page-preview.ts +89 -0
  723. package/packages/web-dashboard/src/lib/live-feed.ts +1 -1
  724. package/packages/web-dashboard/src/lib/multi-project-config.ts +33 -0
  725. package/packages/web-dashboard/src/lib/orchestrator-tools.ts +845 -59
  726. package/packages/web-dashboard/src/lib/planner-workspace.ts +1285 -0
  727. package/packages/web-dashboard/src/lib/review-contracts.ts +5 -3
  728. package/packages/web-dashboard/src/lib/runtime-files.ts +285 -0
  729. package/packages/web-dashboard/src/lib/tool-catalog.ts +51 -0
  730. package/packages/web-dashboard/src/lib/types.ts +731 -3
  731. package/packages/web-dashboard/src/lib/usage-burn.ts +175 -0
  732. package/packages/web-dashboard/src/lib/worktree-diff.ts +128 -0
  733. package/packages/web-dashboard/src/styles/dashboard.module.css +1742 -459
  734. package/packages/web-dashboard/test/api/actions/route.spec.ts +675 -0
  735. package/packages/web-dashboard/test/api/features/diff.route.spec.ts +57 -0
  736. package/packages/web-dashboard/test/api/features/feature.route.spec.ts +99 -0
  737. package/packages/web-dashboard/test/api/features/live-output.route.spec.ts +123 -0
  738. package/packages/web-dashboard/test/api/features/plan-amend.route.spec.ts +95 -0
  739. package/packages/web-dashboard/test/api/features/planner-workspaces.route.spec.ts +162 -0
  740. package/packages/web-dashboard/test/api/features/question-answer.route.spec.ts +99 -0
  741. package/packages/web-dashboard/test/api/features/triage.route.spec.ts +195 -0
  742. package/packages/web-dashboard/test/api/launch/preview.route.spec.ts +149 -0
  743. package/packages/web-dashboard/test/api/launch/submit.route.spec.ts +382 -0
  744. package/packages/web-dashboard/test/api/runtime/events/route.spec.ts +164 -0
  745. package/packages/web-dashboard/test/api/runtime/operations/route.spec.ts +156 -0
  746. package/packages/web-dashboard/test/api/runtime/runs/route.spec.ts +112 -0
  747. package/packages/web-dashboard/test/components/changes-tab.spec.tsx +76 -0
  748. package/packages/web-dashboard/test/components/command-center-root.spec.tsx +87 -0
  749. package/packages/web-dashboard/test/components/diagnosis-panel.spec.tsx +59 -0
  750. package/packages/web-dashboard/test/components/feature-card.spec.tsx +45 -0
  751. package/packages/web-dashboard/test/components/focus-layout.spec.tsx +299 -0
  752. package/packages/web-dashboard/test/components/gate-results.spec.tsx +39 -0
  753. package/packages/web-dashboard/test/components/gates-qa-tab.spec.tsx +118 -0
  754. package/packages/web-dashboard/test/components/human-input-panel.spec.tsx +54 -0
  755. package/packages/web-dashboard/test/components/intake-tab.spec.tsx +210 -0
  756. package/packages/web-dashboard/test/components/kanban-board.spec.tsx +35 -0
  757. package/packages/web-dashboard/test/components/launch-draft-card.spec.tsx +54 -0
  758. package/packages/web-dashboard/test/components/launch-page.spec.tsx +79 -0
  759. package/packages/web-dashboard/test/components/overview-tab.spec.tsx +236 -0
  760. package/packages/web-dashboard/test/components/planning-tab.spec.tsx +202 -0
  761. package/packages/web-dashboard/test/components/review-tab.spec.tsx +169 -0
  762. package/packages/web-dashboard/test/components/role-log-viewer.spec.ts +42 -0
  763. package/packages/web-dashboard/test/components/runtime-inspector.spec.tsx +22 -0
  764. package/packages/web-dashboard/test/components/runtime-tab.spec.tsx +133 -0
  765. package/packages/web-dashboard/test/components/transcript-tab.spec.tsx +46 -0
  766. package/packages/web-dashboard/test/components/triage-drawer.spec.tsx +159 -0
  767. package/packages/web-dashboard/test/lib/aop-client.spec.ts +235 -0
  768. package/packages/web-dashboard/test/lib/dashboard-runtime-client.spec.ts +144 -0
  769. package/packages/web-dashboard/test/lib/focus-detail-derivations.spec.ts +314 -0
  770. package/packages/web-dashboard/test/lib/focus-view.spec.ts +248 -0
  771. package/packages/web-dashboard/test/lib/health-diagnosis.spec.ts +277 -0
  772. package/packages/web-dashboard/test/lib/launch-markdown.spec.ts +36 -0
  773. package/packages/web-dashboard/test/lib/multi-project-config.spec.ts +54 -0
  774. package/packages/web-dashboard/test/lib/orchestrator-tools.spec.ts +352 -0
  775. package/packages/web-dashboard/test/lib/planner-workspace.spec.ts +289 -0
  776. package/packages/web-dashboard/test/lib/worktree-diff.spec.ts +119 -0
  777. package/packages/web-dashboard/vitest.config.ts +2 -0
  778. package/spec-files/completed/agentic_orchestrator_add_feature_to_active_execution_spec.md +557 -0
  779. package/spec-files/completed/agentic_orchestrator_dashboard_command_center_redesign_spec.md +1147 -0
  780. package/spec-files/completed/agentic_orchestrator_execution_mode_spec.md +18 -16
  781. package/spec-files/completed/agentic_orchestrator_feature_focus_view_track_a_spec.md +672 -0
  782. package/spec-files/completed/agentic_orchestrator_feature_focus_view_track_b_spec.md +794 -0
  783. package/spec-files/completed/agentic_orchestrator_feature_focus_view_track_c_decision_centric_remediation_spec.md +1037 -0
  784. package/spec-files/completed/agentic_orchestrator_feature_focus_view_ux_redesign_spec.md +1432 -0
  785. package/spec-files/completed/agentic_orchestrator_focus_plan_tab_intake_planning_workspace_spec.md +921 -0
  786. package/spec-files/completed/agentic_orchestrator_intentional_collision_override_spec.md +584 -0
  787. package/spec-files/completed/agentic_orchestrator_interactive_planning_intake_and_requirements_verification_spec.md +1185 -0
  788. package/spec-files/completed/agentic_orchestrator_reactive_execution_enrollment_spec.md +864 -0
  789. package/spec-files/{outstanding → completed}/agentic_orchestrator_runtime_inspection_spec.md +92 -19
  790. package/spec-files/completed/agentic_orchestrator_scope_aware_run_lease_spec.md +408 -0
  791. package/spec-files/completed/git-reconciliation-engine.md +827 -0
  792. package/spec-files/outstanding/agentic_orchestrator_dashboard_quick_launch_and_control_surface_spec.md +331 -0
  793. package/spec-files/outstanding/agentic_orchestrator_enterprise_governance_dashboard_spec.md +16 -6
  794. package/spec-files/outstanding/agentic_orchestrator_evidence_integrity_doctor_spec.md +60 -9
  795. package/spec-files/outstanding/agentic_orchestrator_focus_plan_tab_execution_contract_workspace_spec.md +616 -0
  796. package/spec-files/outstanding/agentic_orchestrator_headless_standby_dashboard_runtime_spec.md +310 -0
  797. package/spec-files/outstanding/agentic_orchestrator_human_input_interaction_protocol_spec.md +175 -72
  798. package/spec-files/outstanding/agentic_orchestrator_interactive_rename_cleanup_spec.md +197 -0
  799. package/spec-files/outstanding/agentic_orchestrator_interactive_resume_and_reconciliation_disposition_spec.md +412 -0
  800. package/spec-files/outstanding/agentic_orchestrator_knowledge_canary_spec.md +166 -137
  801. package/spec-files/outstanding/agentic_orchestrator_observability_replay_spec.md +3 -3
  802. package/spec-files/outstanding/agentic_orchestrator_phase_specific_agent_profiles_and_token_telemetry_spec.md +303 -0
  803. package/spec-files/outstanding/agentic_orchestrator_planning_review_quality_spec.md +18 -5
  804. package/spec-files/outstanding/agentic_orchestrator_policy_stratification_spec.md +225 -0
  805. package/spec-files/outstanding/agentic_orchestrator_quality_adoption_execution_spec.md +77 -50
  806. package/spec-files/outstanding/agentic_orchestrator_ready_to_merge_branch_handoff_spec.md +724 -0
  807. package/spec-files/outstanding/agentic_orchestrator_remove_deterministic_mode_spec.md +263 -0
  808. package/spec-files/outstanding/agentic_orchestrator_request_more_context_and_dashboard_human_input_spec.md +456 -0
  809. package/spec-files/outstanding/agentic_orchestrator_spec_coverage_and_reconciliation_enforcement_spec.md +1411 -0
  810. package/spec-files/outstanding/agentic_orchestrator_spec_ordering_agent_spec.md +370 -0
  811. package/spec-files/outstanding/shadow_workspace_implementation_spec.md +1 -1
  812. package/spec-files/progress.md +2026 -120
  813. package/specs/001-runtime-inspection/checklists/requirements.md +35 -0
  814. package/specs/001-runtime-inspection/design.md +338 -0
  815. package/specs/001-runtime-inspection/spec.md +95 -0
  816. package/specs/002-scope-aware-lease/checklists/requirements.md +35 -0
  817. package/specs/002-scope-aware-lease/contracts/lease-registry.schema.json +101 -0
  818. package/specs/002-scope-aware-lease/data-model.md +236 -0
  819. package/specs/002-scope-aware-lease/plan.md +766 -0
  820. package/specs/002-scope-aware-lease/quickstart.md +150 -0
  821. package/specs/002-scope-aware-lease/research.md +135 -0
  822. package/specs/002-scope-aware-lease/spec.md +128 -0
  823. package/specs/002-scope-aware-lease/tasks.md +767 -0
  824. package/tsconfig.json +1 -1
  825. package/vitest.config.ts +28 -0
  826. package/ARCHITECTURE_ADHERENCE_ANALYSIS.md +0 -871
  827. package/packages/web-dashboard/next-env.d.ts +0 -6
  828. package/packages/web-dashboard/src/components/detail-panel.tsx +0 -1124
  829. package/packages/web-dashboard/src/components/review-workspace.tsx +0 -1162
  830. /package/spec-files/{outstanding → completed}/agentic_orchestrator_artifact_database_publishing_spec.md +0 -0
  831. /package/spec-files/{outstanding → completed}/agentic_orchestrator_cli_shell_tab_completion_spec.md +0 -0
  832. /package/spec-files/{outstanding → completed}/agentic_orchestrator_dashboard_diff_and_agent_console_spec.md +0 -0
  833. /package/spec-files/{outstanding → completed}/agentic_orchestrator_performance_improvements_spec.md +0 -0
  834. /package/spec-files/{outstanding → completed}/agentic_orchestrator_persistent_worker_runtime_spec.md +0 -0
  835. /package/spec-files/{outstanding → completed}/agentic_orchestrator_provider_auth_bootstrap_spec.md +0 -0
  836. /package/spec-files/{outstanding → completed}/agentic_orchestrator_real_worker_provider_execution_spec.md +0 -0
@@ -1,6 +1,22 @@
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 {
6
+ normalizeManifestConfidence,
7
+ obligationsMeetConfidenceThreshold,
8
+ validatePlanTraceAgainstObligationIds,
9
+ type PlanTraceContractValidation,
10
+ } from '../core/intake-artifacts.js';
11
+ import type { FeatureStatePayload } from '../core/tool-caller.js';
12
+ import {
13
+ assessGateFreshness,
14
+ readCheckpointValidity,
15
+ readGateEvidenceByMode,
16
+ } from '../core/gate-freshness.js';
17
+ import { extractGateLog, type GateLogExtraction } from '../core/gate-log-extractor.js';
3
18
  import type { FeatureContextPayload, InitialPlanGenerator, SupervisorToolCaller } from './types.js';
19
+ import { resolvePlannerPhaseFromContext } from './planner-phase.js';
4
20
  import {
5
21
  NOOP_WORKER_DECISION_RUNNER,
6
22
  type WorkerDecisionResult,
@@ -21,6 +37,9 @@ type AnyRecord = Record<string, unknown>;
21
37
  interface PlanningWaveExecutorDependencies {
22
38
  toolCaller: SupervisorToolCaller;
23
39
  planGenerator: InitialPlanGenerator;
40
+ plannerSessionSync?: {
41
+ syncPlannerSessions(featureIds: string[]): Promise<void>;
42
+ };
24
43
  workerDecisionRunner?: WorkerDecisionRunner;
25
44
  providerMode?: WorkerProviderMode;
26
45
  outputLoopDetector?: OutputLoopDetector;
@@ -35,10 +54,22 @@ interface PlanningWaveExecutorDependencies {
35
54
  runId?: string | (() => string);
36
55
  providerName?: string;
37
56
  modelName?: string;
57
+ safeCheckpointHook?: () => Promise<void>;
58
+ getPolicySnapshot?: () => Record<string, unknown>;
38
59
  }
39
60
 
40
61
  interface ReconciliationDecision {
41
- action: 'update' | 'no_update';
62
+ planDecision: 'update_required' | 'unchanged';
63
+ executionDisposition:
64
+ | 'converged'
65
+ | 'retry_build'
66
+ | 'retry_qa'
67
+ | 'rerun_fast_gate'
68
+ | 'rerun_full_gate'
69
+ | 'blocked_checkpoint_invalid'
70
+ | 'blocked_provider_failure'
71
+ | 'blocked_stale_evidence'
72
+ | 'blocked_other';
42
73
  reasons: string[];
43
74
  acceptanceCriteriaAdditions: string[];
44
75
  edgeCaseChecklist: string[];
@@ -48,6 +79,10 @@ interface ReconciliationDecision {
48
79
  running: number;
49
80
  };
50
81
  latestGateOverall: string | null;
82
+ gateEvidenceFreshness: string;
83
+ checkpointValidity: string;
84
+ gateFailureContext: Record<string, unknown> | null;
85
+ planTraceContract: PlanTraceContractValidation | null;
51
86
  }
52
87
 
53
88
  function asRecord(value: unknown): AnyRecord {
@@ -85,6 +120,14 @@ function normalizeList(values: string[]): string[] {
85
120
  return normalized;
86
121
  }
87
122
 
123
+ function asString(value: unknown): string | null {
124
+ return typeof value === 'string' && value.length > 0 ? value : null;
125
+ }
126
+
127
+ function asNumber(value: unknown): number | null {
128
+ return typeof value === 'number' && Number.isFinite(value) ? value : null;
129
+ }
130
+
88
131
  function readCount(summary: AnyRecord, key: string): number {
89
132
  const raw = summary[key];
90
133
  if (typeof raw !== 'number' || !Number.isFinite(raw) || raw < 0) {
@@ -97,6 +140,53 @@ function readStatus(value: unknown): string {
97
140
  return typeof value === 'string' ? value : 'unknown';
98
141
  }
99
142
 
143
+ function readVerifiedManifestObligations(context: FeatureContextPayload): AnyRecord[] {
144
+ const intake = asRecord(context.intake);
145
+ const verifiedManifest = asRecord(intake.verified_manifest);
146
+ return Array.isArray(verifiedManifest.obligations)
147
+ ? verifiedManifest.obligations.map((item) => asRecord(item))
148
+ : [];
149
+ }
150
+
151
+ function readVerifiedManifestObligationIds(context: FeatureContextPayload): string[] {
152
+ const obligations = readVerifiedManifestObligations(context);
153
+ return normalizeList(
154
+ obligations
155
+ .map((item) => asString(item.obligation_id))
156
+ .filter((item): item is string => item !== null),
157
+ );
158
+ }
159
+
160
+ function readPlanTraceContractValidation(
161
+ context: FeatureContextPayload,
162
+ plan: AnyRecord,
163
+ ): PlanTraceContractValidation | null {
164
+ const verifiedObligationIds = readVerifiedManifestObligationIds(context);
165
+ if (verifiedObligationIds.length === 0) {
166
+ return null;
167
+ }
168
+ return validatePlanTraceAgainstObligationIds(plan, verifiedObligationIds);
169
+ }
170
+
171
+ function hasInvalidPlanTraceContract(
172
+ validation: PlanTraceContractValidation | null,
173
+ ): validation is PlanTraceContractValidation {
174
+ return validation !== null && !validation.valid;
175
+ }
176
+
177
+ interface IntakeRecoveryAmbiguity {
178
+ id: string;
179
+ summary: string;
180
+ obligationIds: string[];
181
+ }
182
+
183
+ interface IntakeRecoveryAnswer {
184
+ questionId: string;
185
+ ambiguityIds: string[];
186
+ answer: string;
187
+ answeredAt: string | null;
188
+ }
189
+
100
190
  function deriveEdgeCaseChecklist(specText: string): string[] {
101
191
  const checklist = [
102
192
  'Edge-case: boundary values and size limits are covered.',
@@ -121,6 +211,39 @@ function deriveEdgeCaseChecklist(specText: string): string[] {
121
211
  return normalizeList(checklist);
122
212
  }
123
213
 
214
+ function deriveEdgeCaseChecklistFromVerifiedManifest(obligations: AnyRecord[]): string[] {
215
+ const checklist: string[] = [];
216
+ const kinds = new Set(
217
+ obligations
218
+ .map((obligation) => asString(obligation.kind))
219
+ .filter((item): item is string => item !== null),
220
+ );
221
+ const verificationHints = new Set(
222
+ obligations
223
+ .map((obligation) => asString(obligation.verification_hint))
224
+ .filter((item): item is string => item !== null),
225
+ );
226
+
227
+ if (kinds.has('artifact') || kinds.has('workflow') || kinds.has('behavior')) {
228
+ checklist.push(
229
+ 'Verified workflow and artifact obligations cover boundary values and phase transitions.',
230
+ );
231
+ }
232
+ if (kinds.has('endpoint') || kinds.has('contract')) {
233
+ checklist.push(
234
+ 'Verified endpoint and contract obligations cover payload validation and negative-path handling.',
235
+ );
236
+ }
237
+ if (kinds.has('integration')) {
238
+ checklist.push('Verified integration obligations cover dependency failure and retry behavior.');
239
+ }
240
+ if (verificationHints.has('required') || kinds.has('verification')) {
241
+ checklist.push('Required verified-manifest obligations have explicit verification coverage.');
242
+ }
243
+
244
+ return normalizeList(checklist);
245
+ }
246
+
124
247
  function readPlanVersion(plan: AnyRecord): number | null {
125
248
  const raw = plan.plan_version;
126
249
  if (typeof raw !== 'number' || !Number.isFinite(raw) || raw < 1) {
@@ -129,6 +252,14 @@ function readPlanVersion(plan: AnyRecord): number | null {
129
252
  return Math.floor(raw);
130
253
  }
131
254
 
255
+ function readStateVersion(frontMatter: AnyRecord): number | null {
256
+ const raw = frontMatter.version;
257
+ if (typeof raw !== 'number' || !Number.isFinite(raw) || raw < 1) {
258
+ return null;
259
+ }
260
+ return Math.floor(raw);
261
+ }
262
+
132
263
  function isPostQaStatus(status: string): boolean {
133
264
  return status === STATUS.QA || status === STATUS.READY_TO_MERGE || status === STATUS.BLOCKED;
134
265
  }
@@ -143,9 +274,19 @@ const TIMEOUT_RUNTIME_ERROR_CODES = new Set<string>([
143
274
  * @fileoverview Planning phase wave executor.
144
275
  */
145
276
 
277
+ /**
278
+ * Executes the planning phase for one supervisor iteration wave.
279
+ * Handles intake verification, plan generation, worker decision dispatch,
280
+ * and post-QA reconciliation of accepted plans.
281
+ */
146
282
  export class PlanningWaveExecutor {
147
283
  private readonly toolCaller: SupervisorToolCaller;
148
284
  private readonly planGenerator: InitialPlanGenerator;
285
+ private readonly plannerSessionSync:
286
+ | {
287
+ syncPlannerSessions(featureIds: string[]): Promise<void>;
288
+ }
289
+ | undefined;
149
290
  private readonly workerDecisionRunner: WorkerDecisionRunner;
150
291
  private readonly providerMode: WorkerProviderMode;
151
292
  private readonly outputLoopDetector: OutputLoopDetector | undefined;
@@ -160,12 +301,15 @@ export class PlanningWaveExecutor {
160
301
  private readonly runId: string | (() => string) | null;
161
302
  private readonly providerName: string;
162
303
  private readonly modelName: string;
304
+ private readonly safeCheckpointHook: (() => Promise<void>) | undefined;
305
+ private readonly getPolicySnapshot: (() => Record<string, unknown>) | undefined;
163
306
  private readonly noProgressByFeature = new Map<string, number>();
164
307
  private readonly lastStatusByFeature = new Map<string, string>();
165
308
 
166
309
  constructor(dependencies: PlanningWaveExecutorDependencies) {
167
310
  this.toolCaller = dependencies.toolCaller;
168
311
  this.planGenerator = dependencies.planGenerator;
312
+ this.plannerSessionSync = dependencies.plannerSessionSync;
169
313
  this.workerDecisionRunner = dependencies.workerDecisionRunner ?? NOOP_WORKER_DECISION_RUNNER;
170
314
  this.providerMode = dependencies.providerMode ?? 'stub';
171
315
  this.outputLoopDetector = dependencies.outputLoopDetector;
@@ -183,78 +327,262 @@ export class PlanningWaveExecutor {
183
327
  this.runId = dependencies.runId ?? null;
184
328
  this.providerName = dependencies.providerName ?? 'unknown';
185
329
  this.modelName = dependencies.modelName ?? 'unknown';
330
+ this.safeCheckpointHook = dependencies.safeCheckpointHook;
331
+ this.getPolicySnapshot = dependencies.getPolicySnapshot;
186
332
  }
187
333
 
334
+ /**
335
+ * Runs a single planning wave: resolves planner phase (intake vs. planning), invokes workers,
336
+ * normalizes accepted plan state, and falls back to stub plan generation when not in live mode.
337
+ * @param featureIds Feature IDs eligible for planning in this wave.
338
+ */
188
339
  async run(featureIds: string[]): Promise<void> {
340
+ await this.plannerSessionSync?.syncPlannerSessions(featureIds);
189
341
  for (const featureId of featureIds) {
190
- const context = await this.toolCaller.callTool<FeatureContextPayload>(
191
- 'planner',
192
- TOOLS.FEATURE_GET_CONTEXT,
193
- {
194
- feature_id: featureId,
195
- },
196
- );
342
+ try {
343
+ const context = await this.toolCaller.callTool<FeatureContextPayload>(
344
+ 'planner',
345
+ TOOLS.FEATURE_GET_CONTEXT,
346
+ {
347
+ feature_id: featureId,
348
+ },
349
+ );
197
350
 
198
- const state = context.data.state.front_matter;
199
- const previousStatus = this.lastStatusByFeature.get(featureId);
200
- if (previousStatus === STATUS.BLOCKED && state.status === STATUS.PLANNING) {
201
- this.noProgressByFeature.delete(featureId);
202
- this.outputLoopDetector?.reset(featureId);
203
- }
204
- this.lastStatusByFeature.set(featureId, state.status);
205
- if (state.status !== STATUS.PLANNING && state.status !== STATUS.BLOCKED) {
206
- continue;
207
- }
351
+ const state = context.data.state.front_matter;
352
+ const plannerPhase = resolvePlannerPhaseFromContext(context.data);
353
+ const previousStatus = this.lastStatusByFeature.get(featureId);
354
+ if (previousStatus === STATUS.BLOCKED && state.status === STATUS.PLANNING) {
355
+ this.noProgressByFeature.delete(featureId);
356
+ this.outputLoopDetector?.reset(featureId);
357
+ }
358
+ this.lastStatusByFeature.set(featureId, state.status);
359
+ if (
360
+ state.status !== STATUS.INTAKE &&
361
+ state.status !== STATUS.PLANNING &&
362
+ state.status !== STATUS.BLOCKED
363
+ ) {
364
+ continue;
365
+ }
208
366
 
209
- const existingPlan = context.data.plan;
210
- let decision: WorkerDecisionResult;
211
- try {
212
- decision = await this.workerDecisionRunner.execute({
213
- role: 'planner',
214
- featureId,
215
- contextBundle: asRecord(context.data),
216
- instructions:
217
- 'Review feature context and emit PLAN_SUBMISSION/REQUEST/NOTE outputs to advance planning deterministically.',
218
- });
219
- } catch (error) {
220
- const handledRuntimeFailure = await this.handleRuntimeFailure(error, featureId);
221
- if (handledRuntimeFailure) {
367
+ const existingPlan = asRecord(context.data.plan);
368
+ const planTraceContract = readPlanTraceContractValidation(context.data, existingPlan);
369
+ if (
370
+ await this.normalizeAcceptedPlanState(
371
+ featureId,
372
+ asRecord(state),
373
+ existingPlan,
374
+ planTraceContract,
375
+ )
376
+ ) {
222
377
  continue;
223
378
  }
224
- throw error;
225
- }
379
+ if (
380
+ state.status === STATUS.BLOCKED &&
381
+ plannerPhase === 'planning' &&
382
+ readPlanVersion(existingPlan) !== null &&
383
+ !hasInvalidPlanTraceContract(planTraceContract)
384
+ ) {
385
+ continue;
386
+ }
387
+ let decision: WorkerDecisionResult;
388
+ try {
389
+ decision = await this.workerDecisionRunner.execute({
390
+ role: 'planner',
391
+ featureId,
392
+ contextBundle: asRecord(context.data),
393
+ instructions: this.instructionsForPlannerState(asRecord(context.data)),
394
+ });
395
+ } catch (error) {
396
+ const handledRuntimeFailure = await this.handleRuntimeFailure(error, featureId);
397
+ if (handledRuntimeFailure) {
398
+ continue;
399
+ }
400
+ throw error;
401
+ }
226
402
 
227
- const loopStalled = await this.enforceOutputLoopPolicy(featureId, decision);
228
- if (loopStalled) {
229
- continue;
230
- }
403
+ const loopStalled = await this.enforceOutputLoopPolicy(featureId, decision);
404
+ if (loopStalled) {
405
+ continue;
406
+ }
231
407
 
232
- const shouldSkip = await this.enforceWorkerExecutionPolicy(featureId, decision);
233
- if (shouldSkip) {
234
- continue;
235
- }
408
+ if (decision.questionRequested) {
409
+ this.noProgressByFeature.delete(featureId);
410
+ continue;
411
+ }
412
+ if (decision.intakeSubmission) {
413
+ this.noProgressByFeature.delete(featureId);
414
+ continue;
415
+ }
236
416
 
237
- if (decision.planSubmission || existingPlan) {
238
- continue;
239
- }
417
+ const shouldSkip = await this.enforceWorkerExecutionPolicy(featureId, decision);
418
+ if (shouldSkip) {
419
+ continue;
420
+ }
240
421
 
241
- if (this.providerMode === 'stub') {
242
- const plan = await this.planGenerator.generateInitialPlan(featureId);
243
- await this.toolCaller.callTool('planner', TOOLS.PLAN_SUBMIT, {
244
- feature_id: featureId,
245
- plan_json: plan,
246
- });
422
+ if (
423
+ decision.planSubmission ||
424
+ (readPlanVersion(existingPlan) !== null &&
425
+ !hasInvalidPlanTraceContract(planTraceContract))
426
+ ) {
427
+ continue;
428
+ }
429
+
430
+ if (this.providerMode === 'stub') {
431
+ if (plannerPhase === 'intake') {
432
+ const intake = asRecord(asRecord(context.data).intake);
433
+ const verifiedManifest = asRecord(intake.verified_manifest);
434
+ const bootstrapManifest = asRecord(intake.bootstrap_manifest);
435
+ if (
436
+ Object.keys(verifiedManifest).length === 0 &&
437
+ this.policyAllowsStubAutoPromotion(bootstrapManifest)
438
+ ) {
439
+ await this.toolCaller.callTool('planner', TOOLS.FEATURE_INTAKE_SUBMIT, {
440
+ feature_id: featureId,
441
+ intake_submission: {
442
+ verified_manifest: {
443
+ ...bootstrapManifest,
444
+ artifact_type: 'verified',
445
+ verification_basis: 'policy_approved_auto_promotion',
446
+ verified_at: new Date().toISOString(),
447
+ source_bootstrap_version:
448
+ typeof bootstrapManifest.manifest_version === 'number'
449
+ ? bootstrapManifest.manifest_version
450
+ : null,
451
+ },
452
+ open_ambiguities: [],
453
+ resolved_ambiguities: [],
454
+ requires_user_input: false,
455
+ },
456
+ });
457
+ continue;
458
+ }
459
+ if (Object.keys(verifiedManifest).length === 0) {
460
+ continue;
461
+ }
462
+ }
463
+ const plan = await this.planGenerator.generateInitialPlan(featureId);
464
+ await this.toolCaller.callTool('planner', TOOLS.PLAN_SUBMIT, {
465
+ feature_id: featureId,
466
+ plan_json: plan,
467
+ });
468
+ }
469
+ } finally {
470
+ if (this.safeCheckpointHook) {
471
+ await this.safeCheckpointHook();
472
+ }
247
473
  }
248
474
  }
249
475
  }
250
476
 
477
+ /**
478
+ * Clears all per-feature tracking state (progress counters, status cache, loop detector).
479
+ * Called when a feature is removed from the active execution set.
480
+ * @param featureId The feature whose tracking data should be purged.
481
+ */
251
482
  clearFeatureTracking(featureId: string): void {
252
483
  this.noProgressByFeature.delete(featureId);
253
484
  this.lastStatusByFeature.delete(featureId);
254
485
  this.outputLoopDetector?.delete(featureId);
255
486
  }
256
487
 
488
+ private instructionsForPlannerState(contextBundle: AnyRecord): string {
489
+ if (resolvePlannerPhaseFromContext(contextBundle) === 'intake') {
490
+ return [
491
+ 'Review spec.md, the bootstrap manifest, verified manifest state, and intake review artifacts.',
492
+ 'In intake mode, form or verify the requirements contract before execution planning begins.',
493
+ 'Emit INTAKE_SUBMISSION when the verified manifest is ready.',
494
+ 'Emit REQUEST action=ask_user_input only for blocking requirement clarification.',
495
+ 'If you emit ask_user_input, stop there for the turn and wait for the persisted human answer before promoting intake.',
496
+ 'Do not emit PLAN_SUBMISSION while the feature remains in intake.',
497
+ ].join(' ');
498
+ }
499
+ 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.';
500
+ }
501
+
502
+ private policyAllowsStubAutoPromotion(bootstrapManifest: AnyRecord): boolean {
503
+ if (Object.keys(bootstrapManifest).length === 0) {
504
+ return false;
505
+ }
506
+ const planning = asRecord(this.getPolicySnapshot?.().planning);
507
+ const intake = asRecord(planning.intake);
508
+ if (intake.allow_auto_promotion !== true) {
509
+ return false;
510
+ }
511
+ const ambiguities = Array.isArray(bootstrapManifest.ambiguities)
512
+ ? bootstrapManifest.ambiguities
513
+ : [];
514
+ if (ambiguities.length > 0) {
515
+ return false;
516
+ }
517
+ const minimumConfidence =
518
+ normalizeManifestConfidence(intake.auto_promotion_min_confidence) ?? 'high';
519
+ const obligations = Array.isArray(bootstrapManifest.obligations)
520
+ ? bootstrapManifest.obligations.map((item) => asRecord(item))
521
+ : [];
522
+ return obligationsMeetConfidenceThreshold(
523
+ obligations
524
+ .map((obligation) => normalizeManifestConfidence(obligation.confidence))
525
+ .filter((confidence): confidence is 'high' | 'medium' | 'low' => confidence !== null)
526
+ .map((confidence) => ({ confidence })),
527
+ minimumConfidence,
528
+ );
529
+ }
530
+
531
+ private async normalizeAcceptedPlanState(
532
+ featureId: string,
533
+ frontMatter: AnyRecord,
534
+ plan: AnyRecord,
535
+ planTraceContract: PlanTraceContractValidation | null = null,
536
+ ): Promise<boolean> {
537
+ const planVersion = readPlanVersion(plan);
538
+ if (planVersion == null || hasInvalidPlanTraceContract(planTraceContract)) {
539
+ return false;
540
+ }
541
+
542
+ const status = readStatus(frontMatter.status);
543
+ const gates = asRecord(frontMatter.gates);
544
+ const needsStatusHeal = status === STATUS.PLANNING;
545
+ const needsPlanGateHeal = gates.plan !== 'pass';
546
+ if (!needsStatusHeal && !needsPlanGateHeal) {
547
+ return false;
548
+ }
549
+
550
+ const expectedVersion = readStateVersion(frontMatter);
551
+ if (expectedVersion == null) {
552
+ return false;
553
+ }
554
+
555
+ const nextFrontMatter: AnyRecord = {
556
+ gates: {
557
+ ...gates,
558
+ plan: 'pass',
559
+ },
560
+ };
561
+ if (needsStatusHeal) {
562
+ nextFrontMatter.status = STATUS.BUILDING;
563
+ }
564
+
565
+ await this.toolCaller.callTool('orchestrator', TOOLS.FEATURE_STATE_PATCH, {
566
+ feature_id: featureId,
567
+ expected_version: expectedVersion,
568
+ patch: {
569
+ front_matter: nextFrontMatter,
570
+ },
571
+ });
572
+
573
+ this.lastStatusByFeature.set(featureId, needsStatusHeal ? STATUS.BUILDING : status);
574
+ return true;
575
+ }
576
+
577
+ /**
578
+ * Reconciles accepted plans against QA/gate findings after the QA wave completes.
579
+ * Evaluates gate freshness, plan-trace contract validity, and QA test summaries,
580
+ * then emits plan updates or invokes the planner worker for revisions when needed.
581
+ * @param featureIds Feature IDs in post-QA status to reconcile.
582
+ * @param iteration Current supervisor iteration number (used for decision logging).
583
+ */
257
584
  async runPostQaReconciliation(featureIds: string[], iteration: number): Promise<void> {
585
+ await this.plannerSessionSync?.syncPlannerSessions(featureIds);
258
586
  for (const featureId of featureIds) {
259
587
  const context = await this.toolCaller.callTool<FeatureContextPayload>(
260
588
  'planner',
@@ -269,13 +597,17 @@ export class PlanningWaveExecutor {
269
597
  if (!isPostQaStatus(status)) {
270
598
  continue;
271
599
  }
600
+ if (status === STATUS.BLOCKED && resolvePlannerPhaseFromContext(context.data) === 'intake') {
601
+ continue;
602
+ }
272
603
 
273
604
  const existingPlan = asRecord(context.data.plan);
274
605
  if (Object.keys(existingPlan).length === 0) {
275
606
  await this.appendDecisionLog(featureId, {
276
607
  phase: 'post_qa_reconciliation',
277
608
  iteration,
278
- decision: 'no_update',
609
+ plan_decision: 'unchanged',
610
+ execution_disposition: 'blocked_other',
279
611
  reasons: ['missing_plan'],
280
612
  status,
281
613
  });
@@ -287,24 +619,118 @@ export class PlanningWaveExecutor {
287
619
  await this.appendDecisionLog(featureId, {
288
620
  phase: 'post_qa_reconciliation',
289
621
  iteration,
290
- decision: 'no_update',
622
+ plan_decision: 'unchanged',
623
+ execution_disposition: 'blocked_other',
291
624
  reasons: ['existing_plan_version_invalid'],
292
625
  status,
293
626
  });
294
627
  continue;
295
628
  }
296
629
 
297
- const decision = this.evaluateReconciliationDecision(context.data, existingPlan, status);
298
- if (decision.action === 'no_update') {
630
+ const decision = await this.evaluateReconciliationDecision(
631
+ context.data,
632
+ existingPlan,
633
+ status,
634
+ );
635
+ if (this.shouldInvokePlannerForPlanTraceContract(decision)) {
636
+ const plannerDecision = await this.workerDecisionRunner.execute({
637
+ role: 'planner',
638
+ featureId,
639
+ contextBundle: {
640
+ ...asRecord(context.data),
641
+ plan_trace_contract: structuredClone(decision.planTraceContract),
642
+ },
643
+ instructions:
644
+ '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.',
645
+ });
646
+
647
+ await this.appendDecisionLog(featureId, {
648
+ phase: 'post_qa_reconciliation',
649
+ iteration,
650
+ plan_decision:
651
+ plannerDecision.planSubmission || plannerDecision.requestHandled
652
+ ? 'update_required'
653
+ : 'unchanged',
654
+ execution_disposition:
655
+ plannerDecision.planSubmission || plannerDecision.requestHandled
656
+ ? 'retry_build'
657
+ : decision.executionDisposition,
658
+ status,
659
+ reasons:
660
+ plannerDecision.planSubmission || plannerDecision.requestHandled
661
+ ? normalizeList([
662
+ ...decision.reasons,
663
+ 'planner_verified_manifest_trace_revision_requested',
664
+ ])
665
+ : decision.reasons,
666
+ qa_summary: decision.qaSummary,
667
+ latest_gate_overall: decision.latestGateOverall,
668
+ gate_evidence_freshness: decision.gateEvidenceFreshness,
669
+ checkpoint_validity: decision.checkpointValidity,
670
+ gate_failure_context: decision.gateFailureContext,
671
+ edge_case_checklist: decision.edgeCaseChecklist,
672
+ plan_trace_contract: decision.planTraceContract,
673
+ });
674
+
675
+ continue;
676
+ }
677
+ if (this.shouldInvokePlannerForGateFailure(decision)) {
678
+ const plannerDecision = await this.workerDecisionRunner.execute({
679
+ role: 'planner',
680
+ featureId,
681
+ contextBundle: {
682
+ ...asRecord(context.data),
683
+ gate_failure_context: structuredClone(decision.gateFailureContext),
684
+ },
685
+ instructions:
686
+ '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.',
687
+ });
688
+
299
689
  await this.appendDecisionLog(featureId, {
300
690
  phase: 'post_qa_reconciliation',
301
691
  iteration,
302
- decision: 'no_update',
692
+ plan_decision:
693
+ plannerDecision.planSubmission || plannerDecision.requestHandled
694
+ ? 'update_required'
695
+ : 'unchanged',
696
+ execution_disposition:
697
+ plannerDecision.planSubmission || plannerDecision.requestHandled
698
+ ? 'retry_build'
699
+ : decision.executionDisposition,
700
+ status,
701
+ reasons:
702
+ plannerDecision.planSubmission || plannerDecision.requestHandled
703
+ ? normalizeList([...decision.reasons, 'planner_gate_failure_revision_requested'])
704
+ : decision.reasons,
705
+ qa_summary: decision.qaSummary,
706
+ latest_gate_overall: decision.latestGateOverall,
707
+ gate_evidence_freshness: decision.gateEvidenceFreshness,
708
+ checkpoint_validity: decision.checkpointValidity,
709
+ gate_failure_context: decision.gateFailureContext,
710
+ edge_case_checklist: decision.edgeCaseChecklist,
711
+ plan_trace_contract: decision.planTraceContract,
712
+ });
713
+
714
+ if (plannerDecision.planSubmission || plannerDecision.requestHandled) {
715
+ continue;
716
+ }
717
+ }
718
+
719
+ if (decision.planDecision === 'unchanged') {
720
+ await this.appendDecisionLog(featureId, {
721
+ phase: 'post_qa_reconciliation',
722
+ iteration,
723
+ plan_decision: decision.planDecision,
724
+ execution_disposition: decision.executionDisposition,
303
725
  status,
304
726
  reasons: decision.reasons,
305
727
  qa_summary: decision.qaSummary,
306
728
  latest_gate_overall: decision.latestGateOverall,
729
+ gate_evidence_freshness: decision.gateEvidenceFreshness,
730
+ checkpoint_validity: decision.checkpointValidity,
731
+ gate_failure_context: decision.gateFailureContext,
307
732
  edge_case_checklist: decision.edgeCaseChecklist,
733
+ plan_trace_contract: decision.planTraceContract,
308
734
  });
309
735
  continue;
310
736
  }
@@ -319,7 +745,8 @@ export class PlanningWaveExecutor {
319
745
  await this.appendDecisionLog(featureId, {
320
746
  phase: 'post_qa_reconciliation',
321
747
  iteration,
322
- decision: 'plan_update',
748
+ plan_decision: decision.planDecision,
749
+ execution_disposition: decision.executionDisposition,
323
750
  status,
324
751
  expected_plan_version: planVersion,
325
752
  next_plan_version: nextPlan.plan_version,
@@ -327,20 +754,29 @@ export class PlanningWaveExecutor {
327
754
  reasons: decision.reasons,
328
755
  qa_summary: decision.qaSummary,
329
756
  latest_gate_overall: decision.latestGateOverall,
757
+ gate_evidence_freshness: decision.gateEvidenceFreshness,
758
+ checkpoint_validity: decision.checkpointValidity,
759
+ gate_failure_context: decision.gateFailureContext,
330
760
  edge_case_checklist: decision.edgeCaseChecklist,
761
+ plan_trace_contract: decision.planTraceContract,
331
762
  });
332
763
  }
333
764
  }
334
765
 
335
- private evaluateReconciliationDecision(
766
+ private async evaluateReconciliationDecision(
336
767
  context: FeatureContextPayload,
337
768
  plan: AnyRecord,
338
769
  status: string,
339
- ): ReconciliationDecision {
770
+ ): Promise<ReconciliationDecision> {
340
771
  const acceptanceCriteria = asStringArray(plan.acceptance_criteria);
341
772
  const riskItems = asStringArray(plan.risk);
773
+ const verifiedObligations = readVerifiedManifestObligations(context);
774
+ const planTraceContract = readPlanTraceContractValidation(context, plan);
342
775
  const specText = typeof context.spec === 'string' ? context.spec : '';
343
- const edgeCaseChecklist = deriveEdgeCaseChecklist(specText);
776
+ const edgeCaseChecklist =
777
+ verifiedObligations.length > 0
778
+ ? deriveEdgeCaseChecklistFromVerifiedManifest(verifiedObligations)
779
+ : deriveEdgeCaseChecklist(specText);
344
780
  const qaSummary = asRecord(asRecord(context.qa_test_index).summary);
345
781
  const pending = readCount(qaSummary, 'pending');
346
782
  const failed = readCount(qaSummary, 'failed');
@@ -349,32 +785,146 @@ export class PlanningWaveExecutor {
349
785
  typeof asRecord(context.latest_evidence).overall === 'string'
350
786
  ? String(asRecord(context.latest_evidence).overall)
351
787
  : null;
788
+ const frontMatter = asRecord(asRecord(context.state).front_matter);
789
+ const statusReason =
790
+ typeof frontMatter.status_reason === 'string' ? frontMatter.status_reason : '';
791
+ const lastGateMode =
792
+ typeof asRecord(frontMatter.evidence).last_gate_mode === 'string'
793
+ ? String(asRecord(frontMatter.evidence).last_gate_mode)
794
+ : null;
795
+ const fastFreshness = assessGateFreshness({
796
+ frontMatter,
797
+ mode: 'fast',
798
+ gateEvidenceByMode: readGateEvidenceByMode(context),
799
+ latestEvidence: context.latest_evidence,
800
+ });
801
+ const fullFreshness = assessGateFreshness({
802
+ frontMatter,
803
+ mode: 'full',
804
+ gateEvidenceByMode: readGateEvidenceByMode(context),
805
+ latestEvidence: context.latest_evidence,
806
+ });
807
+ const checkpointValidity = readCheckpointValidity(frontMatter);
808
+ const gateEvidenceFreshness =
809
+ lastGateMode === 'full'
810
+ ? fullFreshness.freshness
811
+ : status === STATUS.BLOCKED || status === STATUS.BUILDING
812
+ ? fastFreshness.freshness
813
+ : fullFreshness.freshness;
814
+ let executionDisposition: ReconciliationDecision['executionDisposition'] =
815
+ status === STATUS.READY_TO_MERGE ? 'converged' : 'retry_qa';
816
+ const gateFailureContext = await this.extractGateFailureContext(context);
352
817
 
353
- const reasons: string[] = [];
818
+ const planReasons: string[] = [];
819
+ const executionReasons: string[] = [];
354
820
  const acceptanceCriteriaAdditions: string[] = [];
355
821
 
356
822
  const missingEdgeCases = edgeCaseChecklist.filter((item) => !riskItems.includes(item));
357
823
  if (missingEdgeCases.length > 0) {
358
- reasons.push(`edge_case_checklist_missing:${missingEdgeCases.length}`);
824
+ planReasons.push(`edge_case_checklist_missing:${missingEdgeCases.length}`);
359
825
  acceptanceCriteriaAdditions.push(
360
826
  'Planner edge-case checklist has been reviewed and incorporated into the execution plan.',
361
827
  );
362
828
  }
363
829
 
830
+ const planTraceRequiresRevision = hasInvalidPlanTraceContract(planTraceContract);
831
+ if (planTraceContract?.missing_obligation_ids.length) {
832
+ planReasons.push(
833
+ `verified_manifest_trace_missing:${planTraceContract.missing_obligation_ids.length}`,
834
+ );
835
+ }
836
+ if (planTraceContract?.unknown_obligation_ids.length) {
837
+ planReasons.push(
838
+ `verified_manifest_trace_unknown:${planTraceContract.unknown_obligation_ids.length}`,
839
+ );
840
+ }
841
+ if (planTraceContract?.duplicate_obligation_ids.length) {
842
+ planReasons.push(
843
+ `verified_manifest_trace_duplicate:${planTraceContract.duplicate_obligation_ids.length}`,
844
+ );
845
+ }
846
+ if (planTraceContract?.invalid_mappings.length) {
847
+ planReasons.push(
848
+ `verified_manifest_trace_invalid_mapping:${planTraceContract.invalid_mappings.length}`,
849
+ );
850
+ }
851
+ if (planTraceRequiresRevision) {
852
+ acceptanceCriteriaAdditions.push(
853
+ 'plan_trace maps every verified manifest obligation_id into planned implementation and verification work.',
854
+ );
855
+ }
856
+
364
857
  const hasQaSignals =
365
858
  status === STATUS.BLOCKED || failed > 0 || pending > 0 || latestGateOverall === 'fail';
366
859
  const qaCheckpoint = `Planner reconciliation checkpoint [status=${status};failed=${failed};pending=${pending};latest=${latestGateOverall ?? 'unknown'}]`;
367
860
  if (hasQaSignals && !acceptanceCriteria.includes(qaCheckpoint)) {
368
- reasons.push(`qa_signals_detected:${status}:failed=${failed}:pending=${pending}`);
861
+ planReasons.push(`qa_signals_detected:${status}:failed=${failed}:pending=${pending}`);
369
862
  acceptanceCriteriaAdditions.push(
370
863
  'Reconcile QA/gate findings against plan scope and apply corrective updates before merge.',
371
864
  );
372
865
  acceptanceCriteriaAdditions.push(qaCheckpoint);
373
866
  }
374
867
 
868
+ if (status === STATUS.BLOCKED) {
869
+ if (statusReason.includes(ERROR_CODES.PROVIDER_OUTPUT_INVALID)) {
870
+ executionReasons.push('provider_output_invalid');
871
+ executionDisposition = 'blocked_provider_failure';
872
+ } else if (
873
+ lastGateMode === 'full' &&
874
+ latestGateOverall === 'fail' &&
875
+ fullFreshness.freshness === 'current'
876
+ ) {
877
+ executionDisposition = 'blocked_other';
878
+ } else if (
879
+ lastGateMode === 'fast' &&
880
+ latestGateOverall === 'fail' &&
881
+ fastFreshness.freshness === 'current'
882
+ ) {
883
+ executionDisposition = 'blocked_other';
884
+ } else if (lastGateMode === 'full' && fullFreshness.shouldRerunGate) {
885
+ executionReasons.push(...fullFreshness.reasons);
886
+ executionDisposition =
887
+ latestGateOverall === 'pass' ? 'rerun_full_gate' : 'blocked_stale_evidence';
888
+ } else if (fastFreshness.shouldRerunGate) {
889
+ executionReasons.push(...fastFreshness.reasons);
890
+ executionDisposition = latestGateOverall === 'pass' ? 'retry_qa' : 'blocked_stale_evidence';
891
+ } else if (fullFreshness.shouldRerunGate) {
892
+ executionReasons.push(...fullFreshness.reasons);
893
+ executionDisposition =
894
+ latestGateOverall === 'pass' ? 'rerun_full_gate' : 'blocked_stale_evidence';
895
+ } else if (latestGateOverall === 'fail') {
896
+ executionDisposition = 'blocked_other';
897
+ }
898
+ } else if (status === STATUS.QA) {
899
+ if (fullFreshness.shouldRerunGate) {
900
+ executionReasons.push(...fullFreshness.reasons);
901
+ executionDisposition = 'rerun_full_gate';
902
+ } else if (failed > 0 || pending > 0 || running > 0) {
903
+ executionDisposition = 'retry_qa';
904
+ } else if (latestGateOverall === 'pass' && fullFreshness.freshness === 'current') {
905
+ executionDisposition = 'converged';
906
+ }
907
+ } else if (status === STATUS.READY_TO_MERGE) {
908
+ if (fullFreshness.shouldRerunGate) {
909
+ executionReasons.push(...fullFreshness.reasons);
910
+ executionDisposition = 'rerun_full_gate';
911
+ } else if (latestGateOverall !== 'pass' || fullFreshness.freshness !== 'current') {
912
+ executionReasons.push(...fullFreshness.reasons);
913
+ executionDisposition = 'blocked_stale_evidence';
914
+ } else {
915
+ executionDisposition = 'converged';
916
+ }
917
+ }
918
+
919
+ if (planTraceRequiresRevision && executionDisposition === 'converged') {
920
+ executionDisposition = 'retry_build';
921
+ }
922
+
923
+ const reasons = normalizeList([...planReasons, ...executionReasons]);
375
924
  if (reasons.length === 0) {
376
925
  return {
377
- action: 'no_update',
926
+ planDecision: 'unchanged',
927
+ executionDisposition,
378
928
  reasons: ['reconciled_no_gaps'],
379
929
  acceptanceCriteriaAdditions: [],
380
930
  edgeCaseChecklist,
@@ -384,11 +934,16 @@ export class PlanningWaveExecutor {
384
934
  running,
385
935
  },
386
936
  latestGateOverall,
937
+ gateEvidenceFreshness,
938
+ checkpointValidity,
939
+ gateFailureContext,
940
+ planTraceContract,
387
941
  };
388
942
  }
389
943
 
390
944
  return {
391
- action: 'update',
945
+ planDecision: acceptanceCriteriaAdditions.length > 0 ? 'update_required' : 'unchanged',
946
+ executionDisposition,
392
947
  reasons,
393
948
  acceptanceCriteriaAdditions: normalizeList(acceptanceCriteriaAdditions),
394
949
  edgeCaseChecklist,
@@ -398,6 +953,10 @@ export class PlanningWaveExecutor {
398
953
  running,
399
954
  },
400
955
  latestGateOverall,
956
+ gateEvidenceFreshness,
957
+ checkpointValidity,
958
+ gateFailureContext,
959
+ planTraceContract,
401
960
  };
402
961
  }
403
962
 
@@ -421,6 +980,88 @@ export class PlanningWaveExecutor {
421
980
  return nextPlan;
422
981
  }
423
982
 
983
+ private shouldInvokePlannerForGateFailure(decision: ReconciliationDecision): boolean {
984
+ return (
985
+ decision.gateFailureContext !== null &&
986
+ decision.latestGateOverall === 'fail' &&
987
+ decision.gateEvidenceFreshness === 'current' &&
988
+ decision.checkpointValidity !== 'invalid' &&
989
+ (decision.executionDisposition === 'blocked_other' ||
990
+ decision.executionDisposition === 'retry_qa')
991
+ );
992
+ }
993
+
994
+ private shouldInvokePlannerForPlanTraceContract(decision: ReconciliationDecision): boolean {
995
+ return hasInvalidPlanTraceContract(decision.planTraceContract);
996
+ }
997
+
998
+ private async extractGateFailureContext(
999
+ context: FeatureContextPayload,
1000
+ ): Promise<Record<string, unknown> | null> {
1001
+ const latestEvidence = asRecord(context.latest_evidence);
1002
+ const stepResultsRaw = Array.isArray(latestEvidence.step_results)
1003
+ ? latestEvidence.step_results
1004
+ : [];
1005
+ const stepResults = (stepResultsRaw as unknown[])
1006
+ .map((item) => asRecord(item))
1007
+ .filter((item): item is AnyRecord => Object.keys(item).length > 0);
1008
+
1009
+ const failingStep =
1010
+ stepResults.find((item) => (asNumber(item.exit_code) ?? 0) !== 0 || item.timeout === true) ??
1011
+ (typeof latestEvidence.overall === 'string' && latestEvidence.overall === 'fail'
1012
+ ? (stepResults[0] ?? null)
1013
+ : null);
1014
+
1015
+ if (!failingStep) {
1016
+ return null;
1017
+ }
1018
+
1019
+ const stepName = asString(failingStep.name) ?? 'unknown';
1020
+ const stepCmd = Array.isArray(failingStep.cmd)
1021
+ ? (failingStep.cmd as unknown[]).map((value) => String(value))
1022
+ : [];
1023
+ const exitCode = asNumber(failingStep.exit_code) ?? 1;
1024
+ const rawLogPath = asString(failingStep.log_path);
1025
+ const notes = Array.isArray(latestEvidence.notes)
1026
+ ? latestEvidence.notes.filter((item): item is string => typeof item === 'string')
1027
+ : [];
1028
+
1029
+ let failureAnalysis: GateLogExtraction | null = null;
1030
+ if (rawLogPath) {
1031
+ const logPath = path.isAbsolute(rawLogPath)
1032
+ ? rawLogPath
1033
+ : this.repoRoot
1034
+ ? path.join(this.repoRoot, rawLogPath)
1035
+ : rawLogPath;
1036
+ try {
1037
+ const logContent = await fs.readFile(logPath, 'utf8');
1038
+ failureAnalysis = extractGateLog({
1039
+ stepName,
1040
+ cmd: stepCmd,
1041
+ exitCode,
1042
+ logContent,
1043
+ });
1044
+ } catch {
1045
+ failureAnalysis = null;
1046
+ }
1047
+ }
1048
+
1049
+ return {
1050
+ gate_name: asString(latestEvidence.mode) ?? 'unknown',
1051
+ step_name: stepName,
1052
+ cmd: stepCmd,
1053
+ exit_code: exitCode,
1054
+ timeout: failingStep.timeout === true,
1055
+ affected_files: failureAnalysis?.affectedFiles ?? [],
1056
+ error_lines: failureAnalysis?.errorLines ?? [],
1057
+ summary_lines: failureAnalysis?.summaryLines ?? [],
1058
+ error_count: failureAnalysis?.errorCount ?? null,
1059
+ log_tail: failureAnalysis?.logTail ?? '',
1060
+ notes,
1061
+ evidence_overall: asString(latestEvidence.overall) ?? null,
1062
+ };
1063
+ }
1064
+
424
1065
  private async appendDecisionLog(featureId: string, note: AnyRecord): Promise<void> {
425
1066
  await this.toolCaller.callTool('orchestrator', TOOLS.FEATURE_LOG_APPEND, {
426
1067
  feature_id: featureId,
@@ -568,6 +1209,10 @@ export class PlanningWaveExecutor {
568
1209
  decision: {
569
1210
  invalidOutput: boolean;
570
1211
  noProgress: boolean;
1212
+ contextStall?: boolean;
1213
+ contextRequestCount?: number;
1214
+ lastContextRequestAt?: string | null;
1215
+ lastContextRequestRole?: string | null;
571
1216
  },
572
1217
  ): Promise<boolean> {
573
1218
  if (this.providerMode !== 'live') {
@@ -575,7 +1220,24 @@ export class PlanningWaveExecutor {
575
1220
  return false;
576
1221
  }
577
1222
 
1223
+ const context = await this.toolCaller.callTool<FeatureContextPayload>(
1224
+ 'planner',
1225
+ TOOLS.FEATURE_GET_CONTEXT,
1226
+ {
1227
+ feature_id: featureId,
1228
+ },
1229
+ );
1230
+
578
1231
  if (decision.invalidOutput) {
1232
+ if (
1233
+ await this.requestIntakeClarificationFallback(
1234
+ featureId,
1235
+ asRecord(context.data),
1236
+ ERROR_CODES.PROVIDER_OUTPUT_INVALID,
1237
+ )
1238
+ ) {
1239
+ return true;
1240
+ }
579
1241
  await this.applyWorkerPolicyAction(
580
1242
  featureId,
581
1243
  this.malformedOutputAction,
@@ -585,6 +1247,75 @@ export class PlanningWaveExecutor {
585
1247
  return true;
586
1248
  }
587
1249
 
1250
+ if (decision.contextStall) {
1251
+ if (
1252
+ await this.requestIntakeClarificationFallback(
1253
+ featureId,
1254
+ asRecord(context.data),
1255
+ ERROR_CODES.PROVIDER_CONTEXT_STALL,
1256
+ )
1257
+ ) {
1258
+ return true;
1259
+ }
1260
+ const state = await this.toolCaller.callTool<FeatureStatePayload>(
1261
+ 'orchestrator',
1262
+ TOOLS.FEATURE_STATE_GET,
1263
+ { feature_id: featureId },
1264
+ );
1265
+ const frontMatter = asRecord(state.data.front_matter);
1266
+ const expectedVersion =
1267
+ typeof frontMatter.version === 'number' && Number.isFinite(frontMatter.version)
1268
+ ? Math.floor(frontMatter.version)
1269
+ : null;
1270
+ const recovery = this.buildPlannerRecoveryFrontMatter(
1271
+ frontMatter,
1272
+ ERROR_CODES.PROVIDER_CONTEXT_STALL,
1273
+ 'planning',
1274
+ );
1275
+ await this.toolCaller.callTool('orchestrator', TOOLS.FEATURE_STATE_PATCH, {
1276
+ feature_id: featureId,
1277
+ expected_version: expectedVersion,
1278
+ patch: {
1279
+ front_matter: {
1280
+ status: STATUS.BLOCKED,
1281
+ status_reason: `${ERROR_CODES.PROVIDER_CONTEXT_STALL}: repeated context refresh with no progress`,
1282
+ recovery,
1283
+ context_request_count: decision.contextRequestCount ?? 0,
1284
+ last_context_request_at: decision.lastContextRequestAt ?? null,
1285
+ last_context_request_role: decision.lastContextRequestRole ?? 'planner',
1286
+ },
1287
+ },
1288
+ });
1289
+ this.lastStatusByFeature.set(featureId, STATUS.BLOCKED);
1290
+ await this.toolCaller.callTool('orchestrator', TOOLS.FEATURE_LOG_APPEND, {
1291
+ feature_id: featureId,
1292
+ note: JSON.stringify({
1293
+ phase: 'planning',
1294
+ decision: 'blocked',
1295
+ error_code: ERROR_CODES.PROVIDER_CONTEXT_STALL,
1296
+ reason: 'repeated context refresh with no progress',
1297
+ recovery_state: recovery.state,
1298
+ recovery_attempt: recovery.attempt,
1299
+ context_request_count: decision.contextRequestCount ?? 0,
1300
+ last_context_request_at: decision.lastContextRequestAt ?? null,
1301
+ last_context_request_role: decision.lastContextRequestRole ?? 'planner',
1302
+ }),
1303
+ });
1304
+ return true;
1305
+ }
1306
+
1307
+ if (
1308
+ decision.noProgress &&
1309
+ (await this.requestIntakeClarificationFallback(
1310
+ featureId,
1311
+ asRecord(context.data),
1312
+ ERROR_CODES.PROVIDER_NO_PROGRESS,
1313
+ ))
1314
+ ) {
1315
+ this.noProgressByFeature.delete(featureId);
1316
+ return true;
1317
+ }
1318
+
588
1319
  if (!decision.noProgress) {
589
1320
  this.noProgressByFeature.delete(featureId);
590
1321
  return false;
@@ -605,6 +1336,200 @@ export class PlanningWaveExecutor {
605
1336
  return true;
606
1337
  }
607
1338
 
1339
+ private readOpenIntakeAmbiguities(context: AnyRecord): IntakeRecoveryAmbiguity[] {
1340
+ const review = asRecord(asRecord(context.intake).review);
1341
+ const ambiguities = Array.isArray(review.ambiguities) ? review.ambiguities : [];
1342
+ return ambiguities
1343
+ .map((item) => asRecord(item))
1344
+ .filter((item) => asString(item.status) === 'open')
1345
+ .map((item) => ({
1346
+ id: asString(item.id) ?? 'AMB-UNKNOWN',
1347
+ summary: asString(item.summary) ?? 'Clarify the remaining intake ambiguity.',
1348
+ obligationIds: asStringArray(item.obligation_ids),
1349
+ }));
1350
+ }
1351
+
1352
+ private async readAnsweredIntakeAmbiguityIds(featureId: string): Promise<Set<string>> {
1353
+ const response = await this.toolCaller.callTool<{ items?: unknown[] }>(
1354
+ 'orchestrator',
1355
+ TOOLS.FEATURE_QUESTION_LIST,
1356
+ {
1357
+ feature_id: featureId,
1358
+ status: 'all',
1359
+ },
1360
+ );
1361
+ const items = Array.isArray(response.data.items) ? response.data.items : [];
1362
+ const ambiguityIds = items
1363
+ .map((item) => asRecord(item))
1364
+ .filter(
1365
+ (item) =>
1366
+ asString(item.status) === 'answered' &&
1367
+ (asString(item.resume_status) === STATUS.INTAKE ||
1368
+ asString(item.resume_phase) === STATUS.INTAKE ||
1369
+ asString(item.phase) === STATUS.INTAKE),
1370
+ )
1371
+ .flatMap((item) => {
1372
+ const details = asRecord(item.details);
1373
+ const direct = asString(details.ambiguity_id);
1374
+ const grouped = asStringArray(details.ambiguity_ids);
1375
+ return direct ? [direct, ...grouped] : grouped;
1376
+ });
1377
+ return new Set(normalizeList(ambiguityIds));
1378
+ }
1379
+
1380
+ private readAnsweredIntakeClarifications(context: AnyRecord): IntakeRecoveryAnswer[] {
1381
+ const review = asRecord(asRecord(context.intake).review);
1382
+ const answers = Array.isArray(review.clarification_answers) ? review.clarification_answers : [];
1383
+ return answers
1384
+ .map((item) => asRecord(item))
1385
+ .filter((item) => asStringArray(item.ambiguity_ids).length > 0)
1386
+ .map((item) => ({
1387
+ questionId: asString(item.question_id) ?? 'unknown',
1388
+ ambiguityIds: asStringArray(item.ambiguity_ids),
1389
+ answer:
1390
+ typeof item.answer === 'string'
1391
+ ? item.answer
1392
+ : JSON.stringify(asRecord(item.answer) ?? {}, null, 2),
1393
+ answeredAt: asString(item.answered_at),
1394
+ }));
1395
+ }
1396
+
1397
+ private buildIntakeClarificationPrompt(
1398
+ ambiguities: IntakeRecoveryAmbiguity[],
1399
+ followUpAmbiguityIds: Set<string>,
1400
+ priorAnswers: IntakeRecoveryAnswer[],
1401
+ ): string {
1402
+ const needsFollowUp = ambiguities.some((ambiguity) => followUpAmbiguityIds.has(ambiguity.id));
1403
+ const intro =
1404
+ needsFollowUp && ambiguities.length === 1
1405
+ ? 'Planning still cannot continue because this intake ambiguity remains unresolved after the previous answer:'
1406
+ : needsFollowUp
1407
+ ? 'Planning still cannot continue because these intake ambiguities remain unresolved after the previous answer:'
1408
+ : ambiguities.length === 1
1409
+ ? 'Planning cannot continue until this remaining intake ambiguity is clarified:'
1410
+ : 'Planning cannot continue until these remaining intake ambiguities are clarified:';
1411
+ const items = ambiguities.map((ambiguity) => `- ${ambiguity.id}: ${ambiguity.summary}`);
1412
+ const priorAnswerLines = ambiguities.flatMap((ambiguity) =>
1413
+ priorAnswers
1414
+ .filter((answer) => answer.ambiguityIds.includes(ambiguity.id))
1415
+ .map(
1416
+ (answer) =>
1417
+ `- ${ambiguity.id} via ${answer.questionId}${
1418
+ answer.answeredAt ? ` at ${answer.answeredAt}` : ''
1419
+ }: ${answer.answer}`,
1420
+ ),
1421
+ );
1422
+ const priorAnswersBlock =
1423
+ priorAnswerLines.length > 0
1424
+ ? `\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.`
1425
+ : '';
1426
+ return `${intro}\n${items.join('\n')}${priorAnswersBlock}\nRespond in free text and explicitly address each ambiguity ID.`;
1427
+ }
1428
+
1429
+ private async requestIntakeClarificationFallback(
1430
+ featureId: string,
1431
+ context: AnyRecord,
1432
+ recoveryReason: string,
1433
+ ): Promise<boolean> {
1434
+ if (resolvePlannerPhaseFromContext(context) !== 'intake') {
1435
+ return false;
1436
+ }
1437
+
1438
+ const intake = asRecord(context.intake);
1439
+ const verifiedManifest = asRecord(intake.verified_manifest);
1440
+ if (Object.keys(verifiedManifest).length > 0) {
1441
+ return false;
1442
+ }
1443
+
1444
+ const humanInput = asRecord(context.human_input);
1445
+ const openQuestions = Array.isArray(humanInput.open_questions) ? humanInput.open_questions : [];
1446
+ if (openQuestions.length > 0) {
1447
+ return false;
1448
+ }
1449
+
1450
+ const ambiguities = this.readOpenIntakeAmbiguities(context);
1451
+ const answeredAmbiguityIds = await this.readAnsweredIntakeAmbiguityIds(featureId);
1452
+ const priorAnswers = this.readAnsweredIntakeClarifications(context);
1453
+ if (ambiguities.length === 0) {
1454
+ return false;
1455
+ }
1456
+
1457
+ const frontMatter = asRecord(asRecord(context.state).front_matter);
1458
+ const cluster = asRecord(frontMatter.cluster);
1459
+ const question = await this.toolCaller.callTool<{ question_id?: string }>(
1460
+ 'orchestrator',
1461
+ TOOLS.FEATURE_QUESTION_CREATE,
1462
+ {
1463
+ feature_id: featureId,
1464
+ role: 'planner',
1465
+ session_id: asString(cluster.planner_session_id) ?? `planner:intake-recovery:${featureId}`,
1466
+ question_type: 'clarification',
1467
+ prompt: this.buildIntakeClarificationPrompt(
1468
+ ambiguities,
1469
+ answeredAmbiguityIds,
1470
+ priorAnswers,
1471
+ ),
1472
+ details: {
1473
+ ambiguity_ids: ambiguities.map((ambiguity) => ambiguity.id),
1474
+ obligation_ids: normalizeList(
1475
+ ambiguities.flatMap((ambiguity) => ambiguity.obligationIds),
1476
+ ),
1477
+ prior_answered_ambiguity_ids: ambiguities
1478
+ .filter((ambiguity) => answeredAmbiguityIds.has(ambiguity.id))
1479
+ .map((ambiguity) => ambiguity.id),
1480
+ recovery_reason: recoveryReason,
1481
+ recovery_source: 'planning_wave_executor',
1482
+ },
1483
+ expected_answer: {
1484
+ kind: 'free_text',
1485
+ },
1486
+ blocking: true,
1487
+ phase: STATUS.INTAKE,
1488
+ request_action: 'ask_user_input',
1489
+ resume_status: STATUS.INTAKE,
1490
+ resume_phase: STATUS.INTAKE,
1491
+ },
1492
+ );
1493
+
1494
+ this.noProgressByFeature.delete(featureId);
1495
+ this.lastStatusByFeature.set(featureId, STATUS.AWAITING_INPUT);
1496
+ await this.toolCaller.callTool('orchestrator', TOOLS.FEATURE_LOG_APPEND, {
1497
+ feature_id: featureId,
1498
+ note: JSON.stringify({
1499
+ phase: 'planning',
1500
+ action: 'ask_user_input',
1501
+ decision: 'awaiting_input',
1502
+ question_id: asRecord(question.data).question_id ?? null,
1503
+ recovery_reason: recoveryReason,
1504
+ ambiguity_ids: ambiguities.map((ambiguity) => ambiguity.id),
1505
+ }),
1506
+ });
1507
+ return true;
1508
+ }
1509
+
1510
+ private buildPlannerRecoveryFrontMatter(
1511
+ frontMatter: AnyRecord,
1512
+ errorCode: string,
1513
+ phase: 'planning',
1514
+ ): AnyRecord {
1515
+ const existingRecovery = asRecord(frontMatter.recovery);
1516
+ const nextAttempt =
1517
+ (typeof existingRecovery.attempt === 'number' && Number.isFinite(existingRecovery.attempt)
1518
+ ? Math.max(0, Math.floor(existingRecovery.attempt))
1519
+ : 0) + 1;
1520
+ const now = new Date().toISOString();
1521
+ return {
1522
+ state: 'retrying',
1523
+ cause: errorCode,
1524
+ role: 'planner',
1525
+ resume_phase: phase,
1526
+ attempt: nextAttempt,
1527
+ run_id: this.resolveRunId(),
1528
+ started_at: asString(existingRecovery.started_at) ?? now,
1529
+ last_attempt_at: now,
1530
+ };
1531
+ }
1532
+
608
1533
  private async applyWorkerPolicyAction(
609
1534
  featureId: string,
610
1535
  action:
@@ -638,6 +1563,7 @@ export class PlanningWaveExecutor {
638
1563
  typeof frontMatter.version === 'number' && Number.isFinite(frontMatter.version)
639
1564
  ? Math.floor(frontMatter.version)
640
1565
  : null;
1566
+ const recovery = this.buildPlannerRecoveryFrontMatter(frontMatter, errorCode, phase);
641
1567
  await this.toolCaller.callTool('orchestrator', TOOLS.FEATURE_STATE_PATCH, {
642
1568
  feature_id: featureId,
643
1569
  expected_version: expectedVersion,
@@ -645,6 +1571,7 @@ export class PlanningWaveExecutor {
645
1571
  front_matter: {
646
1572
  status: STATUS.BLOCKED,
647
1573
  status_reason: `${errorCode}: ${message}`,
1574
+ recovery,
648
1575
  },
649
1576
  },
650
1577
  });
@@ -656,6 +1583,8 @@ export class PlanningWaveExecutor {
656
1583
  decision: 'blocked',
657
1584
  error_code: errorCode,
658
1585
  reason: message,
1586
+ recovery_state: recovery.state,
1587
+ recovery_attempt: recovery.attempt,
659
1588
  }),
660
1589
  });
661
1590
  }