agentic-orchestrator 0.1.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 (439) hide show
  1. package/.dockerignore +24 -0
  2. package/.github/workflows/mcp-contract-validation.yml +38 -0
  3. package/Agentic-Orchestrator.iml +9 -0
  4. package/LICENSE +21 -0
  5. package/README.md +679 -0
  6. package/agentic/orchestrator/agents.yaml +14 -0
  7. package/agentic/orchestrator/gates.yaml +31 -0
  8. package/agentic/orchestrator/policy.yaml +145 -0
  9. package/agentic/orchestrator/prompts/builder.system.md +1 -0
  10. package/agentic/orchestrator/prompts/planner.system.md +15 -0
  11. package/agentic/orchestrator/prompts/qa.system.md +1 -0
  12. package/agentic/orchestrator/schemas/agents.schema.json +49 -0
  13. package/agentic/orchestrator/schemas/gates.schema.json +65 -0
  14. package/agentic/orchestrator/schemas/index.schema.json +108 -0
  15. package/agentic/orchestrator/schemas/plan.schema.json +127 -0
  16. package/agentic/orchestrator/schemas/policy.schema.json +227 -0
  17. package/agentic/orchestrator/schemas/qa_test_index.schema.json +53 -0
  18. package/agentic/orchestrator/schemas/state.schema.json +92 -0
  19. package/agentic/orchestrator/tools/catalog.json +399 -0
  20. package/agentic/orchestrator/tools/errors.schema.json +21 -0
  21. package/agentic/orchestrator/tools/protocol.json +8 -0
  22. package/agentic/orchestrator/tools/schemas/input/collisions.scan.input.schema.json +7 -0
  23. package/agentic/orchestrator/tools/schemas/input/evidence.latest.input.schema.json +15 -0
  24. package/agentic/orchestrator/tools/schemas/input/feature.delete.input.schema.json +42 -0
  25. package/agentic/orchestrator/tools/schemas/input/feature.discover_specs.input.schema.json +7 -0
  26. package/agentic/orchestrator/tools/schemas/input/feature.get_context.input.schema.json +15 -0
  27. package/agentic/orchestrator/tools/schemas/input/feature.init.input.schema.json +21 -0
  28. package/agentic/orchestrator/tools/schemas/input/feature.log_append.input.schema.json +26 -0
  29. package/agentic/orchestrator/tools/schemas/input/feature.ready_to_merge.input.schema.json +34 -0
  30. package/agentic/orchestrator/tools/schemas/input/feature.state_get.input.schema.json +15 -0
  31. package/agentic/orchestrator/tools/schemas/input/feature.state_patch.input.schema.json +28 -0
  32. package/agentic/orchestrator/tools/schemas/input/gates.list.input.schema.json +11 -0
  33. package/agentic/orchestrator/tools/schemas/input/gates.run.input.schema.json +29 -0
  34. package/agentic/orchestrator/tools/schemas/input/locks.acquire.input.schema.json +29 -0
  35. package/agentic/orchestrator/tools/schemas/input/locks.release.input.schema.json +26 -0
  36. package/agentic/orchestrator/tools/schemas/input/mutating.schema.json +14 -0
  37. package/agentic/orchestrator/tools/schemas/input/plan.get.input.schema.json +15 -0
  38. package/agentic/orchestrator/tools/schemas/input/plan.submit.input.schema.json +28 -0
  39. package/agentic/orchestrator/tools/schemas/input/plan.update.input.schema.json +29 -0
  40. package/agentic/orchestrator/tools/schemas/input/qa.test_index_get.input.schema.json +15 -0
  41. package/agentic/orchestrator/tools/schemas/input/qa.test_index_update.input.schema.json +38 -0
  42. package/agentic/orchestrator/tools/schemas/input/read.schema.json +6 -0
  43. package/agentic/orchestrator/tools/schemas/input/repo.apply_patch.input.schema.json +25 -0
  44. package/agentic/orchestrator/tools/schemas/input/repo.diff.input.schema.json +21 -0
  45. package/agentic/orchestrator/tools/schemas/input/repo.diff_bundle.input.schema.json +15 -0
  46. package/agentic/orchestrator/tools/schemas/input/repo.ensure_worktree.input.schema.json +21 -0
  47. package/agentic/orchestrator/tools/schemas/input/repo.read_file.input.schema.json +20 -0
  48. package/agentic/orchestrator/tools/schemas/input/repo.search.input.schema.json +20 -0
  49. package/agentic/orchestrator/tools/schemas/input/repo.status.input.schema.json +15 -0
  50. package/agentic/orchestrator/tools/schemas/input/report.dashboard.input.schema.json +7 -0
  51. package/agentic/orchestrator/tools/schemas/input/report.feature_summary.input.schema.json +15 -0
  52. package/agentic/orchestrator/tools/schemas/output/collisions.scan.output.schema.json +17 -0
  53. package/agentic/orchestrator/tools/schemas/output/evidence.latest.output.schema.json +20 -0
  54. package/agentic/orchestrator/tools/schemas/output/feature.delete.output.schema.json +224 -0
  55. package/agentic/orchestrator/tools/schemas/output/feature.discover_specs.output.schema.json +32 -0
  56. package/agentic/orchestrator/tools/schemas/output/feature.get_context.output.schema.json +40 -0
  57. package/agentic/orchestrator/tools/schemas/output/feature.init.output.schema.json +24 -0
  58. package/agentic/orchestrator/tools/schemas/output/feature.log_append.output.schema.json +24 -0
  59. package/agentic/orchestrator/tools/schemas/output/feature.ready_to_merge.output.schema.json +30 -0
  60. package/agentic/orchestrator/tools/schemas/output/feature.state_get.output.schema.json +18 -0
  61. package/agentic/orchestrator/tools/schemas/output/feature.state_patch.output.schema.json +24 -0
  62. package/agentic/orchestrator/tools/schemas/output/gates.list.output.schema.json +42 -0
  63. package/agentic/orchestrator/tools/schemas/output/gates.run.output.schema.json +37 -0
  64. package/agentic/orchestrator/tools/schemas/output/locks.acquire.output.schema.json +34 -0
  65. package/agentic/orchestrator/tools/schemas/output/locks.release.output.schema.json +24 -0
  66. package/agentic/orchestrator/tools/schemas/output/plan.get.output.schema.json +26 -0
  67. package/agentic/orchestrator/tools/schemas/output/plan.submit.output.schema.json +23 -0
  68. package/agentic/orchestrator/tools/schemas/output/plan.update.output.schema.json +23 -0
  69. package/agentic/orchestrator/tools/schemas/output/qa.test_index_get.output.schema.json +22 -0
  70. package/agentic/orchestrator/tools/schemas/output/qa.test_index_update.output.schema.json +19 -0
  71. package/agentic/orchestrator/tools/schemas/output/repo.apply_patch.output.schema.json +33 -0
  72. package/agentic/orchestrator/tools/schemas/output/repo.diff.output.schema.json +19 -0
  73. package/agentic/orchestrator/tools/schemas/output/repo.diff_bundle.output.schema.json +32 -0
  74. package/agentic/orchestrator/tools/schemas/output/repo.ensure_worktree.output.schema.json +29 -0
  75. package/agentic/orchestrator/tools/schemas/output/repo.read_file.output.schema.json +24 -0
  76. package/agentic/orchestrator/tools/schemas/output/repo.search.output.schema.json +26 -0
  77. package/agentic/orchestrator/tools/schemas/output/repo.status.output.schema.json +27 -0
  78. package/agentic/orchestrator/tools/schemas/output/report.dashboard.output.schema.json +21 -0
  79. package/agentic/orchestrator/tools/schemas/output/report.feature_summary.output.schema.json +36 -0
  80. package/agentic/orchestrator/tools/schemas/output/standard_success.schema.json +6 -0
  81. package/agentic/orchestrator/tools.md +32 -0
  82. package/apps/control-plane/project.json +39 -0
  83. package/apps/control-plane/scripts/validate-architecture-rules.mjs +170 -0
  84. package/apps/control-plane/scripts/validate-docker-mcp-contract.mjs +84 -0
  85. package/apps/control-plane/scripts/validate-mcp-contracts.ts +61 -0
  86. package/apps/control-plane/src/application/services/collision-queue-service.ts +227 -0
  87. package/apps/control-plane/src/application/services/feature-deletion-service.ts +459 -0
  88. package/apps/control-plane/src/application/services/feature-lifecycle-service.ts +177 -0
  89. package/apps/control-plane/src/application/services/feature-state-service.ts +125 -0
  90. package/apps/control-plane/src/application/services/gate-service.ts +232 -0
  91. package/apps/control-plane/src/application/services/lock-service.ts +298 -0
  92. package/apps/control-plane/src/application/services/merge-service.ts +246 -0
  93. package/apps/control-plane/src/application/services/patch-service.ts +259 -0
  94. package/apps/control-plane/src/application/services/plan-service.ts +302 -0
  95. package/apps/control-plane/src/application/services/qa-index-service.ts +98 -0
  96. package/apps/control-plane/src/application/services/reporting-service.ts +120 -0
  97. package/apps/control-plane/src/application/services/run-lease-service.ts +340 -0
  98. package/apps/control-plane/src/application/tools/tool-metadata.ts +56 -0
  99. package/apps/control-plane/src/application/tools/tool-router.ts +43 -0
  100. package/apps/control-plane/src/cli/aop.ts +31 -0
  101. package/apps/control-plane/src/cli/cli-argument-parser.ts +116 -0
  102. package/apps/control-plane/src/cli/delete-command-handler.ts +90 -0
  103. package/apps/control-plane/src/cli/io.ts +14 -0
  104. package/apps/control-plane/src/cli/resume-command-handler.ts +228 -0
  105. package/apps/control-plane/src/cli/run-command-handler.ts +57 -0
  106. package/apps/control-plane/src/cli/spec-ingestion-service.ts +88 -0
  107. package/apps/control-plane/src/cli/spec-input-resolver.ts +95 -0
  108. package/apps/control-plane/src/cli/spec-utils.ts +40 -0
  109. package/apps/control-plane/src/cli/status-command-handler.ts +17 -0
  110. package/apps/control-plane/src/cli/stop-command-handler.ts +5 -0
  111. package/apps/control-plane/src/cli/tooling.ts +36 -0
  112. package/apps/control-plane/src/cli/types.ts +34 -0
  113. package/apps/control-plane/src/core/collisions.ts +121 -0
  114. package/apps/control-plane/src/core/constants.ts +72 -0
  115. package/apps/control-plane/src/core/error-codes.ts +54 -0
  116. package/apps/control-plane/src/core/frontmatter.ts +42 -0
  117. package/apps/control-plane/src/core/fs.ts +173 -0
  118. package/apps/control-plane/src/core/gates.ts +361 -0
  119. package/apps/control-plane/src/core/git.ts +115 -0
  120. package/apps/control-plane/src/core/kernel.ts +1077 -0
  121. package/apps/control-plane/src/core/patch.ts +152 -0
  122. package/apps/control-plane/src/core/path-layout.ts +113 -0
  123. package/apps/control-plane/src/core/path-rules.ts +71 -0
  124. package/apps/control-plane/src/core/qa-index.ts +179 -0
  125. package/apps/control-plane/src/core/response.ts +62 -0
  126. package/apps/control-plane/src/core/runtime-sessions.ts +20 -0
  127. package/apps/control-plane/src/core/schemas.ts +125 -0
  128. package/apps/control-plane/src/index.ts +21 -0
  129. package/apps/control-plane/src/interfaces/cli/bootstrap.ts +100 -0
  130. package/apps/control-plane/src/mcp/kernel-tool-executor.ts +39 -0
  131. package/apps/control-plane/src/mcp/mcp-server-adapter.ts +74 -0
  132. package/apps/control-plane/src/mcp/operation-ledger.ts +108 -0
  133. package/apps/control-plane/src/mcp/protocol-contract.ts +9 -0
  134. package/apps/control-plane/src/mcp/runtime-factory.ts +105 -0
  135. package/apps/control-plane/src/mcp/runtime-types.ts +44 -0
  136. package/apps/control-plane/src/mcp/token-auth-verifier.ts +63 -0
  137. package/apps/control-plane/src/mcp/token-claims-validator.ts +72 -0
  138. package/apps/control-plane/src/mcp/token-codec.ts +62 -0
  139. package/apps/control-plane/src/mcp/tool-authorizer.ts +43 -0
  140. package/apps/control-plane/src/mcp/tool-client.ts +78 -0
  141. package/apps/control-plane/src/mcp/tool-contract-validator.ts +83 -0
  142. package/apps/control-plane/src/mcp/tool-registry-loader.ts +135 -0
  143. package/apps/control-plane/src/mcp/tool-runtime.ts +336 -0
  144. package/apps/control-plane/src/mcp/tools-markdown-generator.ts +26 -0
  145. package/apps/control-plane/src/mcp/transport-types.ts +16 -0
  146. package/apps/control-plane/src/mcp/types.ts +2 -0
  147. package/apps/control-plane/src/providers/providers.ts +177 -0
  148. package/apps/control-plane/src/supervisor/build-wave-executor.ts +55 -0
  149. package/apps/control-plane/src/supervisor/lease-heartbeat-service.ts +22 -0
  150. package/apps/control-plane/src/supervisor/planning-wave-executor.ts +316 -0
  151. package/apps/control-plane/src/supervisor/prompt-bundle-loader.ts +62 -0
  152. package/apps/control-plane/src/supervisor/qa-wave-executor.ts +99 -0
  153. package/apps/control-plane/src/supervisor/run-coordinator.ts +224 -0
  154. package/apps/control-plane/src/supervisor/runtime.ts +347 -0
  155. package/apps/control-plane/src/supervisor/session-orchestrator.ts +268 -0
  156. package/apps/control-plane/src/supervisor/types.ts +149 -0
  157. package/apps/control-plane/src/supervisor/worker-decision-loop.ts +299 -0
  158. package/apps/control-plane/test/aop.spec.ts +101 -0
  159. package/apps/control-plane/test/cli-helpers.spec.ts +102 -0
  160. package/apps/control-plane/test/cli.spec.ts +12 -0
  161. package/apps/control-plane/test/cli.unit.spec.ts +609 -0
  162. package/apps/control-plane/test/collision-queue.spec.ts +158 -0
  163. package/apps/control-plane/test/collisions.spec.ts +138 -0
  164. package/apps/control-plane/test/core-utils.spec.ts +102 -0
  165. package/apps/control-plane/test/delete-command-handler.spec.ts +202 -0
  166. package/apps/control-plane/test/epoch-tracking.spec.ts +121 -0
  167. package/apps/control-plane/test/gates.spec.ts +452 -0
  168. package/apps/control-plane/test/helpers.ts +68 -0
  169. package/apps/control-plane/test/index.spec.ts +18 -0
  170. package/apps/control-plane/test/kernel-collision-replay.spec.ts +222 -0
  171. package/apps/control-plane/test/kernel.branches.spec.ts +321 -0
  172. package/apps/control-plane/test/kernel.coverage.spec.ts +408 -0
  173. package/apps/control-plane/test/kernel.spec.ts +369 -0
  174. package/apps/control-plane/test/mcp-helpers.spec.ts +195 -0
  175. package/apps/control-plane/test/mcp.spec.ts +776 -0
  176. package/apps/control-plane/test/merge-service.spec.ts +357 -0
  177. package/apps/control-plane/test/plan-service.spec.ts +195 -0
  178. package/apps/control-plane/test/planning-wave-executor.spec.ts +229 -0
  179. package/apps/control-plane/test/providers.spec.ts +168 -0
  180. package/apps/control-plane/test/qa-index-service.spec.ts +187 -0
  181. package/apps/control-plane/test/qa-index.spec.ts +317 -0
  182. package/apps/control-plane/test/response.spec.ts +55 -0
  183. package/apps/control-plane/test/run-coordinator.spec.ts +334 -0
  184. package/apps/control-plane/test/schema-date-time.spec.ts +170 -0
  185. package/apps/control-plane/test/service-retry-paths.spec.ts +305 -0
  186. package/apps/control-plane/test/services.spec.ts +693 -0
  187. package/apps/control-plane/test/spec-input-resolver.spec.ts +76 -0
  188. package/apps/control-plane/test/supervisor-collaborators.spec.ts +201 -0
  189. package/apps/control-plane/test/supervisor.calltool.spec.ts +120 -0
  190. package/apps/control-plane/test/supervisor.spec.ts +415 -0
  191. package/apps/control-plane/test/supervisor.unit.spec.ts +522 -0
  192. package/apps/control-plane/test/token-auth-verifier.spec.ts +111 -0
  193. package/apps/control-plane/test/tool-registry-loader.spec.ts +268 -0
  194. package/apps/control-plane/test/tool-runtime.spec.ts +294 -0
  195. package/apps/control-plane/test/worker-decision-loop.spec.ts +587 -0
  196. package/apps/control-plane/tsconfig.build.json +17 -0
  197. package/apps/control-plane/tsconfig.json +11 -0
  198. package/apps/control-plane/vitest.config.ts +28 -0
  199. package/dist/apps/control-plane/application/services/collision-queue-service.d.ts +69 -0
  200. package/dist/apps/control-plane/application/services/collision-queue-service.js +158 -0
  201. package/dist/apps/control-plane/application/services/collision-queue-service.js.map +1 -0
  202. package/dist/apps/control-plane/application/services/feature-deletion-service.d.ts +79 -0
  203. package/dist/apps/control-plane/application/services/feature-deletion-service.js +336 -0
  204. package/dist/apps/control-plane/application/services/feature-deletion-service.js.map +1 -0
  205. package/dist/apps/control-plane/application/services/feature-lifecycle-service.d.ts +81 -0
  206. package/dist/apps/control-plane/application/services/feature-lifecycle-service.js +117 -0
  207. package/dist/apps/control-plane/application/services/feature-lifecycle-service.js.map +1 -0
  208. package/dist/apps/control-plane/application/services/feature-state-service.d.ts +34 -0
  209. package/dist/apps/control-plane/application/services/feature-state-service.js +90 -0
  210. package/dist/apps/control-plane/application/services/feature-state-service.js.map +1 -0
  211. package/dist/apps/control-plane/application/services/gate-service.d.ts +46 -0
  212. package/dist/apps/control-plane/application/services/gate-service.js +160 -0
  213. package/dist/apps/control-plane/application/services/gate-service.js.map +1 -0
  214. package/dist/apps/control-plane/application/services/lock-service.d.ts +56 -0
  215. package/dist/apps/control-plane/application/services/lock-service.js +242 -0
  216. package/dist/apps/control-plane/application/services/lock-service.js.map +1 -0
  217. package/dist/apps/control-plane/application/services/merge-service.d.ts +33 -0
  218. package/dist/apps/control-plane/application/services/merge-service.js +194 -0
  219. package/dist/apps/control-plane/application/services/merge-service.js.map +1 -0
  220. package/dist/apps/control-plane/application/services/patch-service.d.ts +39 -0
  221. package/dist/apps/control-plane/application/services/patch-service.js +189 -0
  222. package/dist/apps/control-plane/application/services/patch-service.js.map +1 -0
  223. package/dist/apps/control-plane/application/services/plan-service.d.ts +60 -0
  224. package/dist/apps/control-plane/application/services/plan-service.js +234 -0
  225. package/dist/apps/control-plane/application/services/plan-service.js.map +1 -0
  226. package/dist/apps/control-plane/application/services/qa-index-service.d.ts +26 -0
  227. package/dist/apps/control-plane/application/services/qa-index-service.js +66 -0
  228. package/dist/apps/control-plane/application/services/qa-index-service.js.map +1 -0
  229. package/dist/apps/control-plane/application/services/reporting-service.d.ts +47 -0
  230. package/dist/apps/control-plane/application/services/reporting-service.js +90 -0
  231. package/dist/apps/control-plane/application/services/reporting-service.js.map +1 -0
  232. package/dist/apps/control-plane/application/services/run-lease-service.d.ts +74 -0
  233. package/dist/apps/control-plane/application/services/run-lease-service.js +263 -0
  234. package/dist/apps/control-plane/application/services/run-lease-service.js.map +1 -0
  235. package/dist/apps/control-plane/application/tools/tool-metadata.d.ts +8 -0
  236. package/dist/apps/control-plane/application/tools/tool-metadata.js +37 -0
  237. package/dist/apps/control-plane/application/tools/tool-metadata.js.map +1 -0
  238. package/dist/apps/control-plane/application/tools/tool-router.d.ts +16 -0
  239. package/dist/apps/control-plane/application/tools/tool-router.js +25 -0
  240. package/dist/apps/control-plane/application/tools/tool-router.js.map +1 -0
  241. package/dist/apps/control-plane/cli/aop.d.ts +5 -0
  242. package/dist/apps/control-plane/cli/aop.js +19 -0
  243. package/dist/apps/control-plane/cli/aop.js.map +1 -0
  244. package/dist/apps/control-plane/cli/cli-argument-parser.d.ts +5 -0
  245. package/dist/apps/control-plane/cli/cli-argument-parser.js +109 -0
  246. package/dist/apps/control-plane/cli/cli-argument-parser.js.map +1 -0
  247. package/dist/apps/control-plane/cli/delete-command-handler.d.ts +8 -0
  248. package/dist/apps/control-plane/cli/delete-command-handler.js +77 -0
  249. package/dist/apps/control-plane/cli/delete-command-handler.js.map +1 -0
  250. package/dist/apps/control-plane/cli/io.d.ts +2 -0
  251. package/dist/apps/control-plane/cli/io.js +14 -0
  252. package/dist/apps/control-plane/cli/io.js.map +1 -0
  253. package/dist/apps/control-plane/cli/resume-command-handler.d.ts +17 -0
  254. package/dist/apps/control-plane/cli/resume-command-handler.js +178 -0
  255. package/dist/apps/control-plane/cli/resume-command-handler.js.map +1 -0
  256. package/dist/apps/control-plane/cli/run-command-handler.d.ts +15 -0
  257. package/dist/apps/control-plane/cli/run-command-handler.js +39 -0
  258. package/dist/apps/control-plane/cli/run-command-handler.js.map +1 -0
  259. package/dist/apps/control-plane/cli/spec-ingestion-service.d.ts +8 -0
  260. package/dist/apps/control-plane/cli/spec-ingestion-service.js +77 -0
  261. package/dist/apps/control-plane/cli/spec-ingestion-service.js.map +1 -0
  262. package/dist/apps/control-plane/cli/spec-input-resolver.d.ts +9 -0
  263. package/dist/apps/control-plane/cli/spec-input-resolver.js +81 -0
  264. package/dist/apps/control-plane/cli/spec-input-resolver.js.map +1 -0
  265. package/dist/apps/control-plane/cli/spec-utils.d.ts +3 -0
  266. package/dist/apps/control-plane/cli/spec-utils.js +36 -0
  267. package/dist/apps/control-plane/cli/spec-utils.js.map +1 -0
  268. package/dist/apps/control-plane/cli/status-command-handler.d.ts +7 -0
  269. package/dist/apps/control-plane/cli/status-command-handler.js +14 -0
  270. package/dist/apps/control-plane/cli/status-command-handler.js.map +1 -0
  271. package/dist/apps/control-plane/cli/stop-command-handler.d.ts +3 -0
  272. package/dist/apps/control-plane/cli/stop-command-handler.js +6 -0
  273. package/dist/apps/control-plane/cli/stop-command-handler.js.map +1 -0
  274. package/dist/apps/control-plane/cli/tooling.d.ts +4 -0
  275. package/dist/apps/control-plane/cli/tooling.js +24 -0
  276. package/dist/apps/control-plane/cli/tooling.js.map +1 -0
  277. package/dist/apps/control-plane/cli/types.d.ts +31 -0
  278. package/dist/apps/control-plane/cli/types.js +2 -0
  279. package/dist/apps/control-plane/cli/types.js.map +1 -0
  280. package/dist/apps/control-plane/core/collisions.d.ts +39 -0
  281. package/dist/apps/control-plane/core/collisions.js +78 -0
  282. package/dist/apps/control-plane/core/collisions.js.map +1 -0
  283. package/dist/apps/control-plane/core/constants.d.ts +64 -0
  284. package/dist/apps/control-plane/core/constants.js +64 -0
  285. package/dist/apps/control-plane/core/constants.js.map +1 -0
  286. package/dist/apps/control-plane/core/error-codes.d.ts +50 -0
  287. package/dist/apps/control-plane/core/error-codes.js +52 -0
  288. package/dist/apps/control-plane/core/error-codes.js.map +1 -0
  289. package/dist/apps/control-plane/core/frontmatter.d.ts +11 -0
  290. package/dist/apps/control-plane/core/frontmatter.js +30 -0
  291. package/dist/apps/control-plane/core/frontmatter.js.map +1 -0
  292. package/dist/apps/control-plane/core/fs.d.ts +33 -0
  293. package/dist/apps/control-plane/core/fs.js +134 -0
  294. package/dist/apps/control-plane/core/fs.js.map +1 -0
  295. package/dist/apps/control-plane/core/gates.d.ts +88 -0
  296. package/dist/apps/control-plane/core/gates.js +229 -0
  297. package/dist/apps/control-plane/core/gates.js.map +1 -0
  298. package/dist/apps/control-plane/core/git.d.ts +31 -0
  299. package/dist/apps/control-plane/core/git.js +79 -0
  300. package/dist/apps/control-plane/core/git.js.map +1 -0
  301. package/dist/apps/control-plane/core/kernel.d.ts +445 -0
  302. package/dist/apps/control-plane/core/kernel.js +805 -0
  303. package/dist/apps/control-plane/core/kernel.js.map +1 -0
  304. package/dist/apps/control-plane/core/patch.d.ts +23 -0
  305. package/dist/apps/control-plane/core/patch.js +118 -0
  306. package/dist/apps/control-plane/core/patch.js.map +1 -0
  307. package/dist/apps/control-plane/core/path-layout.d.ts +23 -0
  308. package/dist/apps/control-plane/core/path-layout.js +90 -0
  309. package/dist/apps/control-plane/core/path-layout.js.map +1 -0
  310. package/dist/apps/control-plane/core/path-rules.d.ts +13 -0
  311. package/dist/apps/control-plane/core/path-rules.js +52 -0
  312. package/dist/apps/control-plane/core/path-rules.js.map +1 -0
  313. package/dist/apps/control-plane/core/qa-index.d.ts +53 -0
  314. package/dist/apps/control-plane/core/qa-index.js +112 -0
  315. package/dist/apps/control-plane/core/qa-index.js.map +1 -0
  316. package/dist/apps/control-plane/core/response.d.ts +19 -0
  317. package/dist/apps/control-plane/core/response.js +34 -0
  318. package/dist/apps/control-plane/core/response.js.map +1 -0
  319. package/dist/apps/control-plane/core/runtime-sessions.d.ts +19 -0
  320. package/dist/apps/control-plane/core/runtime-sessions.js +2 -0
  321. package/dist/apps/control-plane/core/runtime-sessions.js.map +1 -0
  322. package/dist/apps/control-plane/core/schemas.d.ts +23 -0
  323. package/dist/apps/control-plane/core/schemas.js +80 -0
  324. package/dist/apps/control-plane/core/schemas.js.map +1 -0
  325. package/dist/apps/control-plane/index.d.ts +11 -0
  326. package/dist/apps/control-plane/index.js +9 -0
  327. package/dist/apps/control-plane/index.js.map +1 -0
  328. package/dist/apps/control-plane/interfaces/cli/bootstrap.d.ts +2 -0
  329. package/dist/apps/control-plane/interfaces/cli/bootstrap.js +86 -0
  330. package/dist/apps/control-plane/interfaces/cli/bootstrap.js.map +1 -0
  331. package/dist/apps/control-plane/mcp/kernel-tool-executor.d.ts +14 -0
  332. package/dist/apps/control-plane/mcp/kernel-tool-executor.js +26 -0
  333. package/dist/apps/control-plane/mcp/kernel-tool-executor.js.map +1 -0
  334. package/dist/apps/control-plane/mcp/mcp-server-adapter.d.ts +19 -0
  335. package/dist/apps/control-plane/mcp/mcp-server-adapter.js +55 -0
  336. package/dist/apps/control-plane/mcp/mcp-server-adapter.js.map +1 -0
  337. package/dist/apps/control-plane/mcp/operation-ledger.d.ts +21 -0
  338. package/dist/apps/control-plane/mcp/operation-ledger.js +75 -0
  339. package/dist/apps/control-plane/mcp/operation-ledger.js.map +1 -0
  340. package/dist/apps/control-plane/mcp/protocol-contract.d.ts +8 -0
  341. package/dist/apps/control-plane/mcp/protocol-contract.js +9 -0
  342. package/dist/apps/control-plane/mcp/protocol-contract.js.map +1 -0
  343. package/dist/apps/control-plane/mcp/runtime-factory.d.ts +38 -0
  344. package/dist/apps/control-plane/mcp/runtime-factory.js +71 -0
  345. package/dist/apps/control-plane/mcp/runtime-factory.js.map +1 -0
  346. package/dist/apps/control-plane/mcp/runtime-types.d.ts +40 -0
  347. package/dist/apps/control-plane/mcp/runtime-types.js +2 -0
  348. package/dist/apps/control-plane/mcp/runtime-types.js.map +1 -0
  349. package/dist/apps/control-plane/mcp/token-auth-verifier.d.ts +24 -0
  350. package/dist/apps/control-plane/mcp/token-auth-verifier.js +45 -0
  351. package/dist/apps/control-plane/mcp/token-auth-verifier.js.map +1 -0
  352. package/dist/apps/control-plane/mcp/token-claims-validator.d.ts +9 -0
  353. package/dist/apps/control-plane/mcp/token-claims-validator.js +62 -0
  354. package/dist/apps/control-plane/mcp/token-claims-validator.js.map +1 -0
  355. package/dist/apps/control-plane/mcp/token-codec.d.ts +11 -0
  356. package/dist/apps/control-plane/mcp/token-codec.js +46 -0
  357. package/dist/apps/control-plane/mcp/token-codec.js.map +1 -0
  358. package/dist/apps/control-plane/mcp/tool-authorizer.d.ts +8 -0
  359. package/dist/apps/control-plane/mcp/tool-authorizer.js +36 -0
  360. package/dist/apps/control-plane/mcp/tool-authorizer.js.map +1 -0
  361. package/dist/apps/control-plane/mcp/tool-client.d.ts +30 -0
  362. package/dist/apps/control-plane/mcp/tool-client.js +50 -0
  363. package/dist/apps/control-plane/mcp/tool-client.js.map +1 -0
  364. package/dist/apps/control-plane/mcp/tool-contract-validator.d.ts +29 -0
  365. package/dist/apps/control-plane/mcp/tool-contract-validator.js +61 -0
  366. package/dist/apps/control-plane/mcp/tool-contract-validator.js.map +1 -0
  367. package/dist/apps/control-plane/mcp/tool-registry-loader.d.ts +15 -0
  368. package/dist/apps/control-plane/mcp/tool-registry-loader.js +109 -0
  369. package/dist/apps/control-plane/mcp/tool-registry-loader.js.map +1 -0
  370. package/dist/apps/control-plane/mcp/tool-runtime.d.ts +34 -0
  371. package/dist/apps/control-plane/mcp/tool-runtime.js +252 -0
  372. package/dist/apps/control-plane/mcp/tool-runtime.js.map +1 -0
  373. package/dist/apps/control-plane/mcp/tools-markdown-generator.d.ts +7 -0
  374. package/dist/apps/control-plane/mcp/tools-markdown-generator.js +22 -0
  375. package/dist/apps/control-plane/mcp/tools-markdown-generator.js.map +1 -0
  376. package/dist/apps/control-plane/mcp/transport-types.d.ts +14 -0
  377. package/dist/apps/control-plane/mcp/transport-types.js +2 -0
  378. package/dist/apps/control-plane/mcp/transport-types.js.map +1 -0
  379. package/dist/apps/control-plane/mcp/types.d.ts +2 -0
  380. package/dist/apps/control-plane/mcp/types.js +3 -0
  381. package/dist/apps/control-plane/mcp/types.js.map +1 -0
  382. package/dist/apps/control-plane/providers/providers.d.ts +72 -0
  383. package/dist/apps/control-plane/providers/providers.js +94 -0
  384. package/dist/apps/control-plane/providers/providers.js.map +1 -0
  385. package/dist/apps/control-plane/supervisor/build-wave-executor.d.ts +13 -0
  386. package/dist/apps/control-plane/supervisor/build-wave-executor.js +40 -0
  387. package/dist/apps/control-plane/supervisor/build-wave-executor.js.map +1 -0
  388. package/dist/apps/control-plane/supervisor/lease-heartbeat-service.d.ts +12 -0
  389. package/dist/apps/control-plane/supervisor/lease-heartbeat-service.js +14 -0
  390. package/dist/apps/control-plane/supervisor/lease-heartbeat-service.js.map +1 -0
  391. package/dist/apps/control-plane/supervisor/planning-wave-executor.d.ts +19 -0
  392. package/dist/apps/control-plane/supervisor/planning-wave-executor.js +249 -0
  393. package/dist/apps/control-plane/supervisor/planning-wave-executor.js.map +1 -0
  394. package/dist/apps/control-plane/supervisor/prompt-bundle-loader.d.ts +9 -0
  395. package/dist/apps/control-plane/supervisor/prompt-bundle-loader.js +53 -0
  396. package/dist/apps/control-plane/supervisor/prompt-bundle-loader.js.map +1 -0
  397. package/dist/apps/control-plane/supervisor/qa-wave-executor.d.ts +24 -0
  398. package/dist/apps/control-plane/supervisor/qa-wave-executor.js +70 -0
  399. package/dist/apps/control-plane/supervisor/qa-wave-executor.js.map +1 -0
  400. package/dist/apps/control-plane/supervisor/run-coordinator.d.ts +49 -0
  401. package/dist/apps/control-plane/supervisor/run-coordinator.js +162 -0
  402. package/dist/apps/control-plane/supervisor/run-coordinator.js.map +1 -0
  403. package/dist/apps/control-plane/supervisor/runtime.d.ts +58 -0
  404. package/dist/apps/control-plane/supervisor/runtime.js +270 -0
  405. package/dist/apps/control-plane/supervisor/runtime.js.map +1 -0
  406. package/dist/apps/control-plane/supervisor/session-orchestrator.d.ts +29 -0
  407. package/dist/apps/control-plane/supervisor/session-orchestrator.js +211 -0
  408. package/dist/apps/control-plane/supervisor/session-orchestrator.js.map +1 -0
  409. package/dist/apps/control-plane/supervisor/types.d.ts +148 -0
  410. package/dist/apps/control-plane/supervisor/types.js +2 -0
  411. package/dist/apps/control-plane/supervisor/types.js.map +1 -0
  412. package/dist/apps/control-plane/supervisor/worker-decision-loop.d.ts +37 -0
  413. package/dist/apps/control-plane/supervisor/worker-decision-loop.js +236 -0
  414. package/dist/apps/control-plane/supervisor/worker-decision-loop.js.map +1 -0
  415. package/docker/mcp.Dockerfile +14 -0
  416. package/docker/mcp.compose.yaml +15 -0
  417. package/docker/mcp.entrypoint.sh +17 -0
  418. package/eslint.config.mjs +93 -0
  419. package/example-configurations/README.md +26 -0
  420. package/example-configurations/java/agents.yaml +14 -0
  421. package/example-configurations/java/gates.yaml +29 -0
  422. package/example-configurations/java/policy.yaml +148 -0
  423. package/example-configurations/node/agents.yaml +14 -0
  424. package/example-configurations/node/gates.yaml +32 -0
  425. package/example-configurations/node/policy.yaml +143 -0
  426. package/nx.json +16 -0
  427. package/package.json +39 -0
  428. package/prompts/vitest-testing-standards.instructions.md +204 -0
  429. package/scripts/dev-shell-env.sh +7 -0
  430. package/scripts/nx-safe.mjs +33 -0
  431. package/spec-files/agentic_orchestrator_cli_delete_command_spec.md +310 -0
  432. package/spec-files/agentic_orchestrator_dot_aop_generated_artifacts_spec.md +211 -0
  433. package/spec-files/agentic_orchestrator_mcp_formalization_spec.md +379 -0
  434. package/spec-files/agentic_orchestrator_oop_refactor_spec.md +415 -0
  435. package/spec-files/agentic_orchestrator_single_global_orchestrator_spec.md +265 -0
  436. package/spec-files/agentic_orchestrator_spec.md +1334 -0
  437. package/spec-files/progress.md +452 -0
  438. package/tsconfig.base.json +15 -0
  439. package/tsconfig.json +11 -0
@@ -0,0 +1,316 @@
1
+ import { STATUS, TOOLS } from '../core/constants.js';
2
+ import type {
3
+ FeatureContextPayload,
4
+ InitialPlanGenerator,
5
+ SupervisorToolCaller
6
+ } from './types.js';
7
+ import { NOOP_WORKER_DECISION_RUNNER, type WorkerDecisionRunner } from './worker-decision-loop.js';
8
+
9
+ type AnyRecord = Record<string, unknown>;
10
+
11
+ interface PlanningWaveExecutorDependencies {
12
+ toolCaller: SupervisorToolCaller;
13
+ planGenerator: InitialPlanGenerator;
14
+ workerDecisionRunner?: WorkerDecisionRunner;
15
+ }
16
+
17
+ interface ReconciliationDecision {
18
+ action: 'update' | 'no_update';
19
+ reasons: string[];
20
+ acceptanceCriteriaAdditions: string[];
21
+ edgeCaseChecklist: string[];
22
+ qaSummary: {
23
+ pending: number;
24
+ failed: number;
25
+ running: number;
26
+ };
27
+ latestGateOverall: string | null;
28
+ }
29
+
30
+ function asRecord(value: unknown): AnyRecord {
31
+ return value && typeof value === 'object' ? (value as AnyRecord) : {};
32
+ }
33
+
34
+ function asStringArray(value: unknown): string[] {
35
+ if (!Array.isArray(value)) {
36
+ return [];
37
+ }
38
+ const normalized: string[] = [];
39
+ for (const item of value) {
40
+ if (typeof item !== 'string') {
41
+ continue;
42
+ }
43
+ const trimmed = item.trim();
44
+ if (trimmed.length > 0) {
45
+ normalized.push(trimmed);
46
+ }
47
+ }
48
+ return normalized;
49
+ }
50
+
51
+ function normalizeList(values: string[]): string[] {
52
+ const seen = new Set<string>();
53
+ const normalized: string[] = [];
54
+ for (const value of values) {
55
+ const trimmed = value.trim();
56
+ if (trimmed.length === 0 || seen.has(trimmed)) {
57
+ continue;
58
+ }
59
+ seen.add(trimmed);
60
+ normalized.push(trimmed);
61
+ }
62
+ return normalized;
63
+ }
64
+
65
+ function readCount(summary: AnyRecord, key: string): number {
66
+ const raw = summary[key];
67
+ if (typeof raw !== 'number' || !Number.isFinite(raw) || raw < 0) {
68
+ return 0;
69
+ }
70
+ return Math.floor(raw);
71
+ }
72
+
73
+ function readStatus(value: unknown): string {
74
+ return typeof value === 'string' ? value : 'unknown';
75
+ }
76
+
77
+ function deriveEdgeCaseChecklist(specText: string): string[] {
78
+ const checklist = [
79
+ 'Edge-case: boundary values and size limits are covered.',
80
+ 'Edge-case: negative-path input validation and error handling are covered.',
81
+ 'Edge-case: dependency failure and retry behavior are covered.'
82
+ ];
83
+
84
+ const normalizedSpec = specText.toLowerCase();
85
+ if (/(empty|null|missing|required)/.test(normalizedSpec)) {
86
+ checklist.push('Edge-case: empty/null/missing input handling is covered.');
87
+ }
88
+ if (/(timeout|retry|backoff|latency)/.test(normalizedSpec)) {
89
+ checklist.push('Edge-case: timeout, retry, and latency behavior is covered.');
90
+ }
91
+ if (/(concurrent|race|parallel|lock)/.test(normalizedSpec)) {
92
+ checklist.push('Edge-case: concurrent access and race-condition behavior are covered.');
93
+ }
94
+ if (/(permission|auth|unauthori|forbidden|denied)/.test(normalizedSpec)) {
95
+ checklist.push('Edge-case: authorization and permission-denied behavior is covered.');
96
+ }
97
+
98
+ return normalizeList(checklist);
99
+ }
100
+
101
+ function readPlanVersion(plan: AnyRecord): number | null {
102
+ const raw = plan.plan_version;
103
+ if (typeof raw !== 'number' || !Number.isFinite(raw) || raw < 1) {
104
+ return null;
105
+ }
106
+ return Math.floor(raw);
107
+ }
108
+
109
+ function isPostQaStatus(status: string): boolean {
110
+ return status === STATUS.QA || status === STATUS.READY_TO_MERGE || status === STATUS.BLOCKED;
111
+ }
112
+
113
+ export class PlanningWaveExecutor {
114
+ private readonly toolCaller: SupervisorToolCaller;
115
+ private readonly planGenerator: InitialPlanGenerator;
116
+ private readonly workerDecisionRunner: WorkerDecisionRunner;
117
+
118
+ constructor(dependencies: PlanningWaveExecutorDependencies) {
119
+ this.toolCaller = dependencies.toolCaller;
120
+ this.planGenerator = dependencies.planGenerator;
121
+ this.workerDecisionRunner = dependencies.workerDecisionRunner ?? NOOP_WORKER_DECISION_RUNNER;
122
+ }
123
+
124
+ async run(featureIds: string[]): Promise<void> {
125
+ for (const featureId of featureIds) {
126
+ const context = await this.toolCaller.callTool<FeatureContextPayload>('planner', TOOLS.FEATURE_GET_CONTEXT, {
127
+ feature_id: featureId
128
+ });
129
+
130
+ const state = context.data.state.front_matter;
131
+ if (state.status !== STATUS.PLANNING && state.status !== STATUS.BLOCKED) {
132
+ continue;
133
+ }
134
+
135
+ const existingPlan = context.data.plan;
136
+ const decision = await this.workerDecisionRunner.execute({
137
+ role: 'planner',
138
+ featureId,
139
+ contextBundle: asRecord(context.data),
140
+ instructions:
141
+ 'Review feature context and emit PLAN_SUBMISSION/REQUEST/NOTE outputs to advance planning deterministically.'
142
+ });
143
+
144
+ if (decision.planSubmission || existingPlan) {
145
+ continue;
146
+ }
147
+
148
+ const plan = await this.planGenerator.generateInitialPlan(featureId);
149
+ await this.toolCaller.callTool('planner', TOOLS.PLAN_SUBMIT, {
150
+ feature_id: featureId,
151
+ plan_json: plan
152
+ });
153
+ }
154
+ }
155
+
156
+ async runPostQaReconciliation(featureIds: string[], iteration: number): Promise<void> {
157
+ for (const featureId of featureIds) {
158
+ const context = await this.toolCaller.callTool<FeatureContextPayload>('planner', TOOLS.FEATURE_GET_CONTEXT, {
159
+ feature_id: featureId
160
+ });
161
+
162
+ const frontMatter = asRecord(asRecord(context.data.state).front_matter);
163
+ const status = readStatus(frontMatter.status);
164
+ if (!isPostQaStatus(status)) {
165
+ continue;
166
+ }
167
+
168
+ const existingPlan = asRecord(context.data.plan);
169
+ if (Object.keys(existingPlan).length === 0) {
170
+ await this.appendDecisionLog(featureId, {
171
+ phase: 'post_qa_reconciliation',
172
+ iteration,
173
+ decision: 'no_update',
174
+ reasons: ['missing_plan'],
175
+ status
176
+ });
177
+ continue;
178
+ }
179
+
180
+ const planVersion = readPlanVersion(existingPlan);
181
+ if (planVersion == null) {
182
+ await this.appendDecisionLog(featureId, {
183
+ phase: 'post_qa_reconciliation',
184
+ iteration,
185
+ decision: 'no_update',
186
+ reasons: ['existing_plan_version_invalid'],
187
+ status
188
+ });
189
+ continue;
190
+ }
191
+
192
+ const decision = this.evaluateReconciliationDecision(context.data, existingPlan, status);
193
+ if (decision.action === 'no_update') {
194
+ await this.appendDecisionLog(featureId, {
195
+ phase: 'post_qa_reconciliation',
196
+ iteration,
197
+ decision: 'no_update',
198
+ status,
199
+ reasons: decision.reasons,
200
+ qa_summary: decision.qaSummary,
201
+ latest_gate_overall: decision.latestGateOverall,
202
+ edge_case_checklist: decision.edgeCaseChecklist
203
+ });
204
+ continue;
205
+ }
206
+
207
+ const nextPlan = this.buildUpdatedPlan(existingPlan, planVersion, decision);
208
+ await this.toolCaller.callTool('planner', TOOLS.PLAN_UPDATE, {
209
+ feature_id: featureId,
210
+ expected_plan_version: planVersion,
211
+ plan_json: nextPlan
212
+ });
213
+
214
+ await this.appendDecisionLog(featureId, {
215
+ phase: 'post_qa_reconciliation',
216
+ iteration,
217
+ decision: 'plan_update',
218
+ status,
219
+ expected_plan_version: planVersion,
220
+ next_plan_version: nextPlan.plan_version,
221
+ revision_reason: nextPlan.revision_reason,
222
+ reasons: decision.reasons,
223
+ qa_summary: decision.qaSummary,
224
+ latest_gate_overall: decision.latestGateOverall,
225
+ edge_case_checklist: decision.edgeCaseChecklist
226
+ });
227
+ }
228
+ }
229
+
230
+ private evaluateReconciliationDecision(
231
+ context: FeatureContextPayload,
232
+ plan: AnyRecord,
233
+ status: string
234
+ ): ReconciliationDecision {
235
+ const acceptanceCriteria = asStringArray(plan.acceptance_criteria);
236
+ const riskItems = asStringArray(plan.risk);
237
+ const specText = typeof context.spec === 'string' ? context.spec : '';
238
+ const edgeCaseChecklist = deriveEdgeCaseChecklist(specText);
239
+ const qaSummary = asRecord(asRecord(context.qa_test_index).summary);
240
+ const pending = readCount(qaSummary, 'pending');
241
+ const failed = readCount(qaSummary, 'failed');
242
+ const running = readCount(qaSummary, 'running');
243
+ const latestGateOverall = typeof asRecord(context.latest_evidence).overall === 'string'
244
+ ? String(asRecord(context.latest_evidence).overall)
245
+ : null;
246
+
247
+ const reasons: string[] = [];
248
+ const acceptanceCriteriaAdditions: string[] = [];
249
+
250
+ const missingEdgeCases = edgeCaseChecklist.filter((item) => !riskItems.includes(item));
251
+ if (missingEdgeCases.length > 0) {
252
+ reasons.push(`edge_case_checklist_missing:${missingEdgeCases.length}`);
253
+ acceptanceCriteriaAdditions.push(
254
+ 'Planner edge-case checklist has been reviewed and incorporated into the execution plan.'
255
+ );
256
+ }
257
+
258
+ const hasQaSignals = status === STATUS.BLOCKED || failed > 0 || pending > 0 || latestGateOverall === 'fail';
259
+ const qaCheckpoint = `Planner reconciliation checkpoint [status=${status};failed=${failed};pending=${pending};latest=${latestGateOverall ?? 'unknown'}]`;
260
+ if (hasQaSignals && !acceptanceCriteria.includes(qaCheckpoint)) {
261
+ reasons.push(`qa_signals_detected:${status}:failed=${failed}:pending=${pending}`);
262
+ acceptanceCriteriaAdditions.push(
263
+ 'Reconcile QA/gate findings against plan scope and apply corrective updates before merge.'
264
+ );
265
+ acceptanceCriteriaAdditions.push(qaCheckpoint);
266
+ }
267
+
268
+ if (reasons.length === 0) {
269
+ return {
270
+ action: 'no_update',
271
+ reasons: ['reconciled_no_gaps'],
272
+ acceptanceCriteriaAdditions: [],
273
+ edgeCaseChecklist,
274
+ qaSummary: {
275
+ pending,
276
+ failed,
277
+ running
278
+ },
279
+ latestGateOverall
280
+ };
281
+ }
282
+
283
+ return {
284
+ action: 'update',
285
+ reasons,
286
+ acceptanceCriteriaAdditions: normalizeList(acceptanceCriteriaAdditions),
287
+ edgeCaseChecklist,
288
+ qaSummary: {
289
+ pending,
290
+ failed,
291
+ running
292
+ },
293
+ latestGateOverall
294
+ };
295
+ }
296
+
297
+ private buildUpdatedPlan(plan: AnyRecord, planVersion: number, decision: ReconciliationDecision): AnyRecord {
298
+ const nextPlan = structuredClone(plan);
299
+ const acceptanceCriteria = asStringArray(nextPlan.acceptance_criteria);
300
+ const riskItems = asStringArray(nextPlan.risk);
301
+
302
+ nextPlan.plan_version = planVersion + 1;
303
+ nextPlan.revision_of = planVersion;
304
+ nextPlan.revision_reason = decision.reasons.join('; ');
305
+ nextPlan.acceptance_criteria = normalizeList([...acceptanceCriteria, ...decision.acceptanceCriteriaAdditions]);
306
+ nextPlan.risk = normalizeList([...riskItems, ...decision.edgeCaseChecklist]);
307
+ return nextPlan;
308
+ }
309
+
310
+ private async appendDecisionLog(featureId: string, note: AnyRecord): Promise<void> {
311
+ await this.toolCaller.callTool('orchestrator', TOOLS.FEATURE_LOG_APPEND, {
312
+ feature_id: featureId,
313
+ note: JSON.stringify(note)
314
+ });
315
+ }
316
+ }
@@ -0,0 +1,62 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { ERROR_CODES } from '../core/error-codes.js';
4
+ import type { AgentPromptProvider, AppError, PromptBundle, RuntimeStateReader } from './types.js';
5
+
6
+ export class PromptBundleLoader implements AgentPromptProvider {
7
+ private readonly runtimeStateReader: RuntimeStateReader;
8
+ private promptsCache: PromptBundle | null;
9
+
10
+ constructor(runtimeStateReader: RuntimeStateReader) {
11
+ this.runtimeStateReader = runtimeStateReader;
12
+ this.promptsCache = null;
13
+ }
14
+
15
+ async loadRolePrompts(): Promise<PromptBundle> {
16
+ if (this.promptsCache) {
17
+ return this.promptsCache;
18
+ }
19
+
20
+ const agentsConfig = this.runtimeStateReader.getAgentsConfig();
21
+ const roles = agentsConfig.roles ?? {};
22
+ const behavior = agentsConfig.missing_prompt_behavior ?? 'ignore';
23
+ const prompts: PromptBundle = {
24
+ planner: null,
25
+ builder: null,
26
+ qa: null
27
+ };
28
+
29
+ for (const role of ['planner', 'builder', 'qa'] as const) {
30
+ const configuredPath = roles[role]?.system_prompt_path;
31
+ if (!configuredPath) {
32
+ prompts[role] = null;
33
+ continue;
34
+ }
35
+
36
+ const absolute = path.join(this.runtimeStateReader.getRepoRoot(), configuredPath);
37
+ try {
38
+ prompts[role] = await fs.readFile(absolute, 'utf8');
39
+ } catch {
40
+ if (behavior === 'error') {
41
+ const error = new Error(ERROR_CODES.MISSING_ROLE_PROMPT) as AppError;
42
+ error.code = ERROR_CODES.MISSING_ROLE_PROMPT;
43
+ error.details = { role, configured_path: configuredPath };
44
+ throw error;
45
+ }
46
+
47
+ prompts[role] = null;
48
+ }
49
+ }
50
+
51
+ this.promptsCache = prompts;
52
+ return prompts;
53
+ }
54
+
55
+ peekCache(): PromptBundle | null {
56
+ return this.promptsCache;
57
+ }
58
+
59
+ setCache(prompts: PromptBundle | null): void {
60
+ this.promptsCache = prompts;
61
+ }
62
+ }
@@ -0,0 +1,99 @@
1
+ import { STATUS, TOOLS } from '../core/constants.js';
2
+ import type { WorkerProvider } from '../providers/providers.js';
3
+ import type {
4
+ AgentPromptProvider,
5
+ FeatureClusterPatcher,
6
+ FeatureOrchestrationPort,
7
+ FeatureStatePayload,
8
+ SupervisorRuntimeState,
9
+ SupervisorToolCaller
10
+ } from './types.js';
11
+ import { UNASSIGNED_SESSION_ID } from './types.js';
12
+ import { NOOP_WORKER_DECISION_RUNNER, type WorkerDecisionRunner } from './worker-decision-loop.js';
13
+
14
+ interface QaWaveExecutorDependencies {
15
+ kernel: FeatureOrchestrationPort;
16
+ provider: WorkerProvider;
17
+ toolCaller: SupervisorToolCaller;
18
+ promptProvider: AgentPromptProvider;
19
+ featureClusterPatcher: FeatureClusterPatcher;
20
+ state: SupervisorRuntimeState;
21
+ workerDecisionRunner?: WorkerDecisionRunner;
22
+ }
23
+
24
+ export class QaWaveExecutor {
25
+ private readonly kernel: FeatureOrchestrationPort;
26
+ private readonly provider: WorkerProvider;
27
+ private readonly toolCaller: SupervisorToolCaller;
28
+ private readonly promptProvider: AgentPromptProvider;
29
+ private readonly featureClusterPatcher: FeatureClusterPatcher;
30
+ private readonly state: SupervisorRuntimeState;
31
+ private readonly workerDecisionRunner: WorkerDecisionRunner;
32
+
33
+ constructor(dependencies: QaWaveExecutorDependencies) {
34
+ this.kernel = dependencies.kernel;
35
+ this.provider = dependencies.provider;
36
+ this.toolCaller = dependencies.toolCaller;
37
+ this.promptProvider = dependencies.promptProvider;
38
+ this.featureClusterPatcher = dependencies.featureClusterPatcher;
39
+ this.state = dependencies.state;
40
+ this.workerDecisionRunner = dependencies.workerDecisionRunner ?? NOOP_WORKER_DECISION_RUNNER;
41
+ }
42
+
43
+ async run(featureIds: string[], maxParallelGateRuns: number): Promise<void> {
44
+ const batch: string[] = [];
45
+ for (const featureId of featureIds) {
46
+ const state = await this.toolCaller.callTool<FeatureStatePayload>('qa', TOOLS.FEATURE_STATE_GET, {
47
+ feature_id: featureId
48
+ });
49
+
50
+ if (state.data.front_matter.status === STATUS.QA) {
51
+ batch.push(featureId);
52
+ }
53
+ }
54
+
55
+ for (const featureId of batch.slice(0, maxParallelGateRuns)) {
56
+ const context = await this.toolCaller.callTool('qa', TOOLS.FEATURE_GET_CONTEXT, {
57
+ feature_id: featureId
58
+ });
59
+ await this.workerDecisionRunner.execute({
60
+ role: 'qa',
61
+ featureId,
62
+ contextBundle: context.data,
63
+ instructions:
64
+ 'Emit PATCH outputs for deterministic QA remediations, NOTE outputs for findings, and REQUEST outputs for lock/context needs.'
65
+ });
66
+
67
+ await this.toolCaller.callTool('qa', TOOLS.GATES_RUN, {
68
+ feature_id: featureId,
69
+ profile: null,
70
+ mode: 'full'
71
+ });
72
+
73
+ const sessions = this.state.sessionsByFeature.get(featureId);
74
+ if (sessions?.qa) {
75
+ await this.provider.closeSession(sessions.qa);
76
+ }
77
+
78
+ const prompts = await this.promptProvider.loadRolePrompts();
79
+ const newQa = await this.provider.createSession('qa', featureId, prompts.qa);
80
+ if (sessions) {
81
+ sessions.qa = newQa.session_id;
82
+ }
83
+
84
+ await this.kernel.updateFeatureSessionAssignment({
85
+ run_id: this.state.runId,
86
+ owner_instance_id: this.state.ownerInstanceId,
87
+ feature_id: featureId,
88
+ planner_session_id: sessions?.planner ?? UNASSIGNED_SESSION_ID,
89
+ builder_session_id: sessions?.builder ?? UNASSIGNED_SESSION_ID,
90
+ qa_session_id: newQa.session_id
91
+ });
92
+
93
+ await this.featureClusterPatcher.patchFeatureCluster(featureId, {
94
+ orchestrator_session_id: this.state.orchestratorSessionId ?? 'unknown',
95
+ qa_session_id: newQa.session_id
96
+ });
97
+ }
98
+ }
99
+ }
@@ -0,0 +1,224 @@
1
+ import { STATUS, TOOLS } from '../core/constants.js';
2
+ import type { WorkerProvider } from '../providers/providers.js';
3
+ import type {
4
+ FeatureInput,
5
+ FeatureStatePayload,
6
+ FeatureOrchestrationPort,
7
+ RuntimeStateReader,
8
+ SupervisorRuntimeState,
9
+ SupervisorToolCaller
10
+ } from './types.js';
11
+ import { type SessionOrchestrator } from './session-orchestrator.js';
12
+ import { type PlanningWaveExecutor } from './planning-wave-executor.js';
13
+ import { type BuildWaveExecutor } from './build-wave-executor.js';
14
+ import { type QaWaveExecutor } from './qa-wave-executor.js';
15
+ import { type LeaseHeartbeatService } from './lease-heartbeat-service.js';
16
+ import { NOOP_WORKER_DECISION_RUNNER, type WorkerDecisionRunner } from './worker-decision-loop.js';
17
+
18
+ interface RunCoordinatorDependencies {
19
+ kernel: FeatureOrchestrationPort & RuntimeStateReader;
20
+ provider: WorkerProvider;
21
+ toolCaller: SupervisorToolCaller;
22
+ state: SupervisorRuntimeState;
23
+ sessionOrchestrator: SessionOrchestrator;
24
+ planningWaveExecutor: PlanningWaveExecutor;
25
+ buildWaveExecutor: BuildWaveExecutor;
26
+ qaWaveExecutor: QaWaveExecutor;
27
+ leaseHeartbeatService: LeaseHeartbeatService;
28
+ maxActiveFeatures: number;
29
+ maxParallelGateRuns: number;
30
+ maxIterationsPerPhase: number;
31
+ takeoverStaleRun: boolean;
32
+ providerConfigRefHash: () => string;
33
+ workerDecisionRunner?: WorkerDecisionRunner;
34
+ }
35
+
36
+ export class RunCoordinator {
37
+ private readonly kernel: FeatureOrchestrationPort & RuntimeStateReader;
38
+ private readonly provider: WorkerProvider;
39
+ private readonly toolCaller: SupervisorToolCaller;
40
+ private readonly state: SupervisorRuntimeState;
41
+ private readonly sessionOrchestrator: SessionOrchestrator;
42
+ private readonly planningWaveExecutor: PlanningWaveExecutor;
43
+ private readonly buildWaveExecutor: BuildWaveExecutor;
44
+ private readonly qaWaveExecutor: QaWaveExecutor;
45
+ private readonly leaseHeartbeatService: LeaseHeartbeatService;
46
+ private readonly maxActiveFeatures: number;
47
+ private readonly maxParallelGateRuns: number;
48
+ private readonly maxIterationsPerPhase: number;
49
+ private readonly takeoverStaleRun: boolean;
50
+ private readonly providerConfigRefHash: () => string;
51
+ private readonly workerDecisionRunner: WorkerDecisionRunner;
52
+ private static readonly TERMINAL_STATUSES = new Set<string>([STATUS.MERGED, STATUS.FAILED]);
53
+
54
+ constructor(dependencies: RunCoordinatorDependencies) {
55
+ this.kernel = dependencies.kernel;
56
+ this.provider = dependencies.provider;
57
+ this.toolCaller = dependencies.toolCaller;
58
+ this.state = dependencies.state;
59
+ this.sessionOrchestrator = dependencies.sessionOrchestrator;
60
+ this.planningWaveExecutor = dependencies.planningWaveExecutor;
61
+ this.buildWaveExecutor = dependencies.buildWaveExecutor;
62
+ this.qaWaveExecutor = dependencies.qaWaveExecutor;
63
+ this.leaseHeartbeatService = dependencies.leaseHeartbeatService;
64
+ this.maxActiveFeatures = dependencies.maxActiveFeatures;
65
+ this.maxParallelGateRuns = dependencies.maxParallelGateRuns;
66
+ this.maxIterationsPerPhase = dependencies.maxIterationsPerPhase;
67
+ this.takeoverStaleRun = dependencies.takeoverStaleRun;
68
+ this.providerConfigRefHash = dependencies.providerConfigRefHash;
69
+ this.workerDecisionRunner = dependencies.workerDecisionRunner ?? NOOP_WORKER_DECISION_RUNNER;
70
+ }
71
+
72
+ async start(features: FeatureInput[]): Promise<Record<string, unknown>> {
73
+ await this.kernel.ensureLoaded();
74
+ await this.kernel.recoverFromState();
75
+
76
+ const leaseResult = await this.kernel.acquireRunLease({
77
+ run_id: this.state.runId,
78
+ owner_instance_id: this.state.ownerInstanceId,
79
+ provider: this.provider.selection.provider,
80
+ model: this.provider.selection.model,
81
+ provider_config_ref_hash: this.providerConfigRefHash(),
82
+ takeover_stale_run: this.takeoverStaleRun
83
+ });
84
+
85
+ this.state.runMetadata.took_over_stale = Boolean(leaseResult.data.took_over_stale);
86
+
87
+ await this.sessionOrchestrator.ensureGlobalOrchestratorSession();
88
+
89
+ const sorted = [...features].sort((a, b) => a.feature_id.localeCompare(b.feature_id));
90
+ const scopedFeatureIds = sorted.map((item) => item.feature_id);
91
+ this.state.queue = sorted;
92
+ let activeFeatureIds: string[] = [];
93
+
94
+ await this.sessionOrchestrator.cleanupOrphanWorkerSessions(scopedFeatureIds);
95
+ await this.kernel.pruneFeatureSessionAssignments({
96
+ run_id: this.state.runId,
97
+ owner_instance_id: this.state.ownerInstanceId,
98
+ active_feature_ids: scopedFeatureIds
99
+ });
100
+
101
+ activeFeatureIds = await this.rebalanceActiveFeatures(activeFeatureIds);
102
+
103
+ for (let iteration = 0; iteration < this.maxIterationsPerPhase; iteration += 1) {
104
+ if (activeFeatureIds.length === 0 && this.state.queue.length === 0) {
105
+ break;
106
+ }
107
+ await this.leaseHeartbeatService.renew();
108
+ activeFeatureIds = await this.applyOrchestratorPrioritization(activeFeatureIds, iteration + 1);
109
+ await this.planningWaveExecutor.run(activeFeatureIds);
110
+ await this.buildWaveExecutor.run(activeFeatureIds, this.maxParallelGateRuns);
111
+ await this.qaWaveExecutor.run(activeFeatureIds, this.maxParallelGateRuns);
112
+ await this.planningWaveExecutor.runPostQaReconciliation(activeFeatureIds, iteration + 1);
113
+ activeFeatureIds = await this.rebalanceActiveFeatures(activeFeatureIds);
114
+ }
115
+
116
+ const dashboard = await this.toolCaller.callTool('orchestrator', TOOLS.REPORT_DASHBOARD, {});
117
+ const runtimeSessions = await this.kernel.getRuntimeSessions();
118
+
119
+ return {
120
+ status: 'running',
121
+ dashboard: dashboard.data,
122
+ queue_depth: this.state.queue.length,
123
+ run_metadata: {
124
+ ...this.state.runMetadata,
125
+ runtime_sessions: runtimeSessions
126
+ }
127
+ };
128
+ }
129
+
130
+ private async rebalanceActiveFeatures(currentActiveFeatureIds: string[]): Promise<string[]> {
131
+ const survivingActiveFeatureIds: string[] = [];
132
+ const sortedCurrent = [...currentActiveFeatureIds].sort((a, b) => a.localeCompare(b));
133
+
134
+ for (const featureId of sortedCurrent) {
135
+ const status = await this.readFeatureStatus(featureId);
136
+ if (status && RunCoordinator.TERMINAL_STATUSES.has(status)) {
137
+ await this.sessionOrchestrator.closeFeatureCluster(featureId);
138
+ continue;
139
+ }
140
+ survivingActiveFeatureIds.push(featureId);
141
+ }
142
+
143
+ while (survivingActiveFeatureIds.length < this.maxActiveFeatures && this.state.queue.length > 0) {
144
+ const nextFeature = this.state.queue.shift();
145
+ if (!nextFeature) {
146
+ break;
147
+ }
148
+
149
+ const status = await this.readFeatureStatus(nextFeature.feature_id);
150
+ if (status && RunCoordinator.TERMINAL_STATUSES.has(status)) {
151
+ await this.sessionOrchestrator.closeFeatureCluster(nextFeature.feature_id);
152
+ continue;
153
+ }
154
+
155
+ await this.sessionOrchestrator.initializeFeatureCluster(nextFeature.feature_id);
156
+ survivingActiveFeatureIds.push(nextFeature.feature_id);
157
+ }
158
+
159
+ const activeFeatureIds = [...new Set(survivingActiveFeatureIds)].sort((a, b) => a.localeCompare(b));
160
+ const scopedFeatureIds = [...activeFeatureIds, ...this.state.queue.map((item) => item.feature_id)].sort((a, b) =>
161
+ a.localeCompare(b)
162
+ );
163
+
164
+ await this.sessionOrchestrator.reconcileQueuedFeatures(this.state.queue);
165
+ await this.sessionOrchestrator.enforceActiveFeatureInvariant(activeFeatureIds);
166
+ await this.kernel.pruneFeatureSessionAssignments({
167
+ run_id: this.state.runId,
168
+ owner_instance_id: this.state.ownerInstanceId,
169
+ active_feature_ids: scopedFeatureIds
170
+ });
171
+
172
+ return activeFeatureIds;
173
+ }
174
+
175
+ private async readFeatureStatus(featureId: string): Promise<string | null> {
176
+ try {
177
+ const state = await this.toolCaller.callTool<FeatureStatePayload>('orchestrator', TOOLS.FEATURE_STATE_GET, {
178
+ feature_id: featureId
179
+ });
180
+ const status = state.data.front_matter.status;
181
+ return typeof status === 'string' ? status : null;
182
+ } catch (_error) {
183
+ return null;
184
+ }
185
+ }
186
+
187
+ private async applyOrchestratorPrioritization(
188
+ activeFeatureIds: string[],
189
+ iteration: number
190
+ ): Promise<string[]> {
191
+ if (activeFeatureIds.length < 2) {
192
+ return activeFeatureIds;
193
+ }
194
+
195
+ const decision = await this.workerDecisionRunner.execute({
196
+ role: 'orchestrator',
197
+ featureId: 'global',
198
+ contextBundle: {
199
+ iteration,
200
+ active_feature_ids: activeFeatureIds,
201
+ queued_feature_ids: this.state.queue.map((item) => item.feature_id)
202
+ },
203
+ instructions:
204
+ 'Decide per-iteration prioritization. Emit REQUEST action=prioritize with feature_order to reprioritize active features.'
205
+ });
206
+
207
+ if (decision.priorityOrder.length === 0) {
208
+ return activeFeatureIds;
209
+ }
210
+
211
+ const activeSet = new Set(activeFeatureIds);
212
+ const prioritized: string[] = [];
213
+ for (const featureId of decision.priorityOrder) {
214
+ if (!activeSet.has(featureId)) {
215
+ continue;
216
+ }
217
+ activeSet.delete(featureId);
218
+ prioritized.push(featureId);
219
+ }
220
+
221
+ const remaining = [...activeSet].sort((a, b) => a.localeCompare(b));
222
+ return [...prioritized, ...remaining];
223
+ }
224
+ }