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,121 @@
1
+ import { describe, it, expect, beforeEach } from 'vitest';
2
+ import { AopKernel } from '../src/core/kernel.js';
3
+ import { makeTempRepo } from './helpers.js';
4
+
5
+ describe('Orchestrator Epoch Tracking and Recovery', () => {
6
+ let tempDir: string;
7
+ let kernel: AopKernel;
8
+
9
+ beforeEach(async () => {
10
+ tempDir = await makeTempRepo(process.cwd());
11
+ kernel = new AopKernel(tempDir);
12
+ await kernel.ensureLoaded();
13
+ });
14
+
15
+ it('should initialize epoch to 0 on first run lease acquisition', async () => {
16
+ const result = await kernel.acquireRunLease({
17
+ run_id: 'test-run-1',
18
+ owner_instance_id: 'test-owner-1',
19
+ provider: 'custom',
20
+ model: 'test-model',
21
+ provider_config_ref_hash: 'hash123',
22
+ takeover_stale_run: false
23
+ });
24
+
25
+ expect(result.data.runtime_sessions.orchestrator_epoch).toBe(0);
26
+ expect(result.data.took_over_stale).toBe(false);
27
+ });
28
+
29
+ it('should maintain epoch on same owner lease renewal', async () => {
30
+ await kernel.acquireRunLease({
31
+ run_id: 'test-run-2',
32
+ owner_instance_id: 'test-owner-2',
33
+ provider: 'custom',
34
+ model: 'test-model',
35
+ provider_config_ref_hash: 'hash123',
36
+ takeover_stale_run: false
37
+ });
38
+
39
+ const renewResult = await kernel.renewRunLease('test-run-2', 'test-owner-2');
40
+ expect(renewResult.data.lease_expires_at).toBeDefined();
41
+
42
+ const sessions = await kernel.getRuntimeSessions();
43
+ expect(sessions.orchestrator_epoch).toBe(0);
44
+ });
45
+
46
+ it('should increment epoch when updating orchestrator session with increment flag', async () => {
47
+ await kernel.acquireRunLease({
48
+ run_id: 'test-run-3',
49
+ owner_instance_id: 'test-owner-3',
50
+ provider: 'custom',
51
+ model: 'test-model',
52
+ provider_config_ref_hash: 'hash123',
53
+ takeover_stale_run: false
54
+ });
55
+
56
+ await kernel.updateOrchestratorSession({
57
+ run_id: 'test-run-3',
58
+ owner_instance_id: 'test-owner-3',
59
+ orchestrator_session_id: 'new-orch-session-1',
60
+ increment_epoch: true
61
+ });
62
+
63
+ const sessions = await kernel.getRuntimeSessions();
64
+ expect(sessions.orchestrator_epoch).toBe(1);
65
+ });
66
+
67
+ it('should not increment epoch when updating without increment flag', async () => {
68
+ await kernel.acquireRunLease({
69
+ run_id: 'test-run-4',
70
+ owner_instance_id: 'test-owner-4',
71
+ provider: 'custom',
72
+ model: 'test-model',
73
+ provider_config_ref_hash: 'hash123',
74
+ takeover_stale_run: false
75
+ });
76
+
77
+ await kernel.updateOrchestratorSession({
78
+ run_id: 'test-run-4',
79
+ owner_instance_id: 'test-owner-4',
80
+ orchestrator_session_id: 'new-orch-session-2',
81
+ increment_epoch: false
82
+ });
83
+
84
+ const sessions = await kernel.getRuntimeSessions();
85
+ expect(sessions.orchestrator_epoch).toBe(0);
86
+ });
87
+
88
+ it('should preserve epoch on takeover', async () => {
89
+ await kernel.acquireRunLease({
90
+ run_id: 'test-run-5',
91
+ owner_instance_id: 'test-owner-5a',
92
+ provider: 'custom',
93
+ model: 'test-model',
94
+ provider_config_ref_hash: 'hash123',
95
+ takeover_stale_run: false
96
+ });
97
+
98
+ await kernel.updateOrchestratorSession({
99
+ run_id: 'test-run-5',
100
+ owner_instance_id: 'test-owner-5a',
101
+ orchestrator_session_id: 'orch-session-5',
102
+ increment_epoch: true
103
+ });
104
+
105
+ const index = await kernel.readIndex();
106
+ index.runtime_sessions.lease_expires_at = new Date(Date.now() - 60000).toISOString();
107
+ await kernel.writeIndex(index);
108
+
109
+ const takeoverResult = await kernel.acquireRunLease({
110
+ run_id: 'test-run-5-takeover',
111
+ owner_instance_id: 'test-owner-5b',
112
+ provider: 'custom',
113
+ model: 'test-model',
114
+ provider_config_ref_hash: 'hash123',
115
+ takeover_stale_run: true
116
+ });
117
+
118
+ expect(takeoverResult.data.took_over_stale).toBe(true);
119
+ expect(takeoverResult.data.runtime_sessions.orchestrator_epoch).toBe(1);
120
+ });
121
+ });
@@ -0,0 +1,452 @@
1
+ import fs from 'node:fs/promises';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
5
+
6
+ const runCommandMock = vi.hoisted(() => vi.fn());
7
+
8
+ vi.mock('../src/core/git.js', () => ({
9
+ runCommand: runCommandMock
10
+ }));
11
+
12
+ import { parseCoverage, runGateMode } from '../src/core/gates.js';
13
+
14
+ const basePolicy = {
15
+ execution: {
16
+ retry_policy: {
17
+ transient_max_retries: 1,
18
+ transient_error_codes: [124]
19
+ },
20
+ env_allowlist: ['TEST_ALLOWED_ENV'],
21
+ default_step_timeout_seconds: 1
22
+ },
23
+ testing: {
24
+ coverage: {
25
+ minimums: { line: 0.9, branch: 0.9 },
26
+ targets: { line: 1.0, branch: 1.0 }
27
+ }
28
+ }
29
+ };
30
+
31
+ describe('gates helpers', () => {
32
+ let tempRoot: string;
33
+
34
+ beforeEach(async () => {
35
+ tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'aop-gates-'));
36
+ process.env.TEST_ALLOWED_ENV = 'allowed-value';
37
+ runCommandMock.mockReset();
38
+ });
39
+
40
+ afterEach(() => {
41
+ delete process.env.TEST_ALLOWED_ENV;
42
+ vi.restoreAllMocks();
43
+ });
44
+
45
+ it('GIVEN_no_parser_or_none_parser_WHEN_parsing_coverage_THEN_returns_null', async () => {
46
+ await expect(parseCoverage(undefined, tempRoot)).resolves.toBeNull();
47
+ await expect(parseCoverage({ type: 'none' }, tempRoot)).resolves.toBeNull();
48
+ });
49
+
50
+ it('GIVEN_supported_parser_formats_WHEN_parsing_coverage_THEN_extracts_metrics', async () => {
51
+ await fs.writeFile(
52
+ path.join(tempRoot, 'lcov.info'),
53
+ ['TN:', 'SF:src/a.ts', 'LF:10', 'LH:8', 'BRF:4', 'BRH:3', 'end_of_record', ''].join('\n'),
54
+ 'utf8'
55
+ );
56
+ await fs.writeFile(
57
+ path.join(tempRoot, 'junit.xml'),
58
+ '<testsuite tests="5" failures="1" errors="1"></testsuite>',
59
+ 'utf8'
60
+ );
61
+ await fs.writeFile(
62
+ path.join(tempRoot, 'jacoco.xml'),
63
+ '<report><counter type="LINE" missed="2" covered="8"/><counter type="BRANCH" missed="3" covered="9"/></report>',
64
+ 'utf8'
65
+ );
66
+ await fs.writeFile(
67
+ path.join(tempRoot, 'cobertura.xml'),
68
+ '<coverage line-rate="0.75" branch-rate="0.5"></coverage>',
69
+ 'utf8'
70
+ );
71
+
72
+ await expect(parseCoverage({ type: 'lcov', path: 'lcov.info' }, tempRoot)).resolves.toMatchObject({
73
+ line: 0.8,
74
+ branch: 0.75,
75
+ details: { linesFound: 10, linesHit: 8, branchesFound: 4, branchesHit: 3 }
76
+ });
77
+ await expect(parseCoverage({ type: 'junit_xml', path: 'junit.xml' }, tempRoot)).resolves.toMatchObject({
78
+ line: 0.6,
79
+ branch: 0.6
80
+ });
81
+ await expect(parseCoverage({ type: 'jacoco_xml', path: 'jacoco.xml' }, tempRoot)).resolves.toMatchObject({
82
+ line: 0.8,
83
+ branch: 0.75
84
+ });
85
+ await expect(parseCoverage({ type: 'cobertura_xml', path: 'cobertura.xml' }, tempRoot)).resolves.toMatchObject({
86
+ line: 0.75,
87
+ branch: 0.5
88
+ });
89
+ });
90
+
91
+ it('GIVEN_unsupported_parser_WHEN_parsing_coverage_THEN_throws_error', async () => {
92
+ await fs.writeFile(path.join(tempRoot, 'raw.txt'), 'x', 'utf8');
93
+ await expect(parseCoverage({ type: 'custom_parser', path: 'raw.txt' }, tempRoot)).rejects.toThrow(
94
+ 'unsupported_parser:custom_parser'
95
+ );
96
+ });
97
+
98
+ it('GIVEN_missing_mode_definition_WHEN_running_gate_mode_THEN_throws_unknown_mode_error', async () => {
99
+ await expect(
100
+ runGateMode({
101
+ featureId: 'feature_a',
102
+ mode: 'fast',
103
+ profileName: 'default',
104
+ profile: { modes: {} },
105
+ policy: basePolicy as any,
106
+ worktreePath: tempRoot,
107
+ logDirectory: path.join(tempRoot, 'logs'),
108
+ evidenceDirectory: path.join(tempRoot, 'evidence')
109
+ })
110
+ ).rejects.toThrow('unknown_gate_profile_or_mode:default/fast');
111
+ });
112
+
113
+ it('GIVEN_transient_failure_then_success_WHEN_running_gate_mode_THEN_retries_and_passes', async () => {
114
+ runCommandMock
115
+ .mockResolvedValueOnce({
116
+ code: 124,
117
+ signal: null,
118
+ stdout: '',
119
+ stderr: 'timeout',
120
+ timeout: false
121
+ })
122
+ .mockResolvedValueOnce({
123
+ code: 0,
124
+ signal: null,
125
+ stdout: 'ok',
126
+ stderr: '',
127
+ timeout: false
128
+ });
129
+
130
+ const result = await runGateMode({
131
+ featureId: 'feature_a',
132
+ mode: 'fast',
133
+ profileName: 'default',
134
+ profile: {
135
+ modes: {
136
+ fast: [
137
+ {
138
+ name: 'lint',
139
+ cmd: ['npm', 'run', 'lint'],
140
+ env: { EXTRA: '1' },
141
+ timeout_seconds: 2
142
+ }
143
+ ]
144
+ },
145
+ parsers: { coverage: { type: 'none' } }
146
+ },
147
+ policy: basePolicy as any,
148
+ worktreePath: tempRoot,
149
+ logDirectory: path.join(tempRoot, 'logs'),
150
+ evidenceDirectory: path.join(tempRoot, 'evidence')
151
+ });
152
+
153
+ expect(result.overall).toBe('pass');
154
+ expect(result.coverage_status).toBe('na');
155
+ expect(result.step_results).toEqual([
156
+ expect.objectContaining({
157
+ name: 'lint',
158
+ attempts: 2,
159
+ exit_code: 0,
160
+ timeout: false
161
+ })
162
+ ]);
163
+ expect(runCommandMock).toHaveBeenCalledTimes(2);
164
+
165
+ const firstCallOptions = runCommandMock.mock.calls[0][2];
166
+ expect(firstCallOptions.timeoutMs).toBe(2000);
167
+ expect(firstCallOptions.env).toMatchObject({
168
+ TEST_ALLOWED_ENV: 'allowed-value',
169
+ EXTRA: '1'
170
+ });
171
+
172
+ await expect(fs.stat(result.evidence_path as string)).resolves.toBeTruthy();
173
+ await expect(fs.stat(result.latest_path as string)).resolves.toBeTruthy();
174
+ });
175
+
176
+ it('GIVEN_non_transient_failure_WHEN_running_gate_mode_THEN_fails_without_extra_retries', async () => {
177
+ runCommandMock.mockResolvedValue({
178
+ code: 2,
179
+ signal: null,
180
+ stdout: '',
181
+ stderr: 'bad command',
182
+ timeout: false
183
+ });
184
+
185
+ const result = await runGateMode({
186
+ featureId: 'feature_a',
187
+ mode: 'fast',
188
+ profileName: 'default',
189
+ profile: {
190
+ modes: {
191
+ fast: [{ name: 'lint', cmd: ['npm', 'run', 'lint'] }]
192
+ }
193
+ },
194
+ policy: basePolicy as any,
195
+ worktreePath: tempRoot,
196
+ logDirectory: path.join(tempRoot, 'logs'),
197
+ evidenceDirectory: path.join(tempRoot, 'evidence')
198
+ });
199
+
200
+ expect(result.overall).toBe('fail');
201
+ expect(result.step_results).toEqual([
202
+ expect.objectContaining({
203
+ attempts: 1,
204
+ exit_code: 2
205
+ })
206
+ ]);
207
+ expect(runCommandMock).toHaveBeenCalledTimes(1);
208
+ });
209
+
210
+ it('GIVEN_timeout_or_exhausted_transient_retries_WHEN_running_gate_mode_THEN_fails', async () => {
211
+ runCommandMock.mockResolvedValue({
212
+ code: 124,
213
+ signal: null,
214
+ stdout: '',
215
+ stderr: 'timeout',
216
+ timeout: true
217
+ });
218
+
219
+ const timeoutResult = await runGateMode({
220
+ featureId: 'feature_timeout',
221
+ mode: 'fast',
222
+ profileName: 'default',
223
+ profile: {
224
+ modes: {
225
+ fast: [{ name: 'lint', cmd: ['npm', 'run', 'lint'] }]
226
+ }
227
+ },
228
+ policy: basePolicy as any,
229
+ worktreePath: tempRoot,
230
+ logDirectory: path.join(tempRoot, 'logs'),
231
+ evidenceDirectory: path.join(tempRoot, 'evidence')
232
+ });
233
+
234
+ expect(timeoutResult.overall).toBe('fail');
235
+ expect(timeoutResult.step_results[0]).toMatchObject({ attempts: 1, timeout: true });
236
+
237
+ runCommandMock.mockReset();
238
+ runCommandMock
239
+ .mockResolvedValueOnce({
240
+ code: 124,
241
+ signal: null,
242
+ stdout: '',
243
+ stderr: 'timeout',
244
+ timeout: false
245
+ })
246
+ .mockResolvedValueOnce({
247
+ code: 124,
248
+ signal: null,
249
+ stdout: '',
250
+ stderr: 'timeout',
251
+ timeout: false
252
+ });
253
+
254
+ const exhaustedRetries = await runGateMode({
255
+ featureId: 'feature_retry',
256
+ mode: 'fast',
257
+ profileName: 'default',
258
+ profile: {
259
+ modes: {
260
+ fast: [{ name: 'lint', cmd: ['npm', 'run', 'lint'] }]
261
+ }
262
+ },
263
+ policy: basePolicy as any,
264
+ worktreePath: tempRoot,
265
+ logDirectory: path.join(tempRoot, 'logs'),
266
+ evidenceDirectory: path.join(tempRoot, 'evidence')
267
+ });
268
+
269
+ expect(exhaustedRetries.overall).toBe('fail');
270
+ expect(exhaustedRetries.step_results[0]).toMatchObject({ attempts: 2, exit_code: 124 });
271
+ });
272
+
273
+ it('GIVEN_missing_or_high_coverage_artifacts_WHEN_running_gate_mode_THEN_sets_expected_coverage_status', async () => {
274
+ runCommandMock.mockResolvedValue({
275
+ code: 0,
276
+ signal: null,
277
+ stdout: 'ok',
278
+ stderr: '',
279
+ timeout: false
280
+ });
281
+
282
+ const missingCoverage = await runGateMode({
283
+ featureId: 'feature_no_cov',
284
+ mode: 'full',
285
+ profileName: 'default',
286
+ profile: {
287
+ modes: {
288
+ full: [{ name: 'tests', cmd: ['npm', 'test'] }]
289
+ },
290
+ parsers: { coverage: { type: 'lcov', path: 'missing/lcov.info' } }
291
+ },
292
+ policy: basePolicy as any,
293
+ worktreePath: tempRoot,
294
+ logDirectory: path.join(tempRoot, 'logs'),
295
+ evidenceDirectory: path.join(tempRoot, 'evidence')
296
+ });
297
+ expect(missingCoverage.overall).toBe('pass');
298
+ expect(missingCoverage.coverage_status).toBe('na');
299
+
300
+ const coverageDir = path.join(tempRoot, 'coverage-pass');
301
+ await fs.mkdir(coverageDir, { recursive: true });
302
+ await fs.writeFile(
303
+ path.join(coverageDir, 'lcov.info'),
304
+ ['TN:', 'SF:src/a.ts', 'LF:20', 'LH:20', 'BRF:10', 'BRH:10', 'end_of_record', ''].join('\n'),
305
+ 'utf8'
306
+ );
307
+
308
+ const highCoverage = await runGateMode({
309
+ featureId: 'feature_cov_pass',
310
+ mode: 'full',
311
+ profileName: 'default',
312
+ profile: {
313
+ modes: {
314
+ full: [{ name: 'tests', cmd: ['npm', 'test'] }]
315
+ },
316
+ parsers: { coverage: { type: 'lcov', path: 'coverage-pass/lcov.info' } },
317
+ thresholds: {
318
+ coverage_line_min: 0.5,
319
+ coverage_branch_min: 0.5
320
+ }
321
+ },
322
+ policy: basePolicy as any,
323
+ worktreePath: tempRoot,
324
+ logDirectory: path.join(tempRoot, 'logs'),
325
+ evidenceDirectory: path.join(tempRoot, 'evidence')
326
+ });
327
+ expect(highCoverage.overall).toBe('pass');
328
+ expect(highCoverage.coverage_status).toBe('pass');
329
+ expect(highCoverage.thresholds).toMatchObject({
330
+ coverage_line_min: 0.9,
331
+ coverage_branch_min: 0.9
332
+ });
333
+ });
334
+
335
+ it('GIVEN_low_coverage_WHEN_running_gate_mode_THEN_marks_coverage_failure', async () => {
336
+ const coverageDir = path.join(tempRoot, 'coverage');
337
+ await fs.mkdir(coverageDir, { recursive: true });
338
+ await fs.writeFile(
339
+ path.join(coverageDir, 'lcov.info'),
340
+ ['TN:', 'SF:src/a.ts', 'LF:20', 'LH:10', 'BRF:10', 'BRH:3', 'end_of_record', ''].join('\n'),
341
+ 'utf8'
342
+ );
343
+
344
+ runCommandMock.mockResolvedValue({
345
+ code: 0,
346
+ signal: null,
347
+ stdout: 'ok',
348
+ stderr: '',
349
+ timeout: false
350
+ });
351
+
352
+ const result = await runGateMode({
353
+ featureId: 'feature_cov',
354
+ mode: 'full',
355
+ profileName: 'default',
356
+ profile: {
357
+ modes: {
358
+ full: [{ name: 'tests', cmd: ['npm', 'test'] }]
359
+ },
360
+ parsers: { coverage: { type: 'lcov', path: 'coverage/lcov.info' } }
361
+ },
362
+ policy: basePolicy as any,
363
+ worktreePath: tempRoot,
364
+ logDirectory: path.join(tempRoot, 'logs'),
365
+ evidenceDirectory: path.join(tempRoot, 'evidence')
366
+ });
367
+
368
+ expect(result.overall).toBe('fail');
369
+ expect(result.coverage_status).toBe('fail');
370
+ expect(result.coverage).toMatchObject({
371
+ line: 0.5,
372
+ branch: 0.3
373
+ });
374
+
375
+ const latest = JSON.parse(await fs.readFile(result.latest_path as string, 'utf8'));
376
+ expect(latest.coverage_failure).toMatchObject({
377
+ line: 0.5,
378
+ branch: 0.3,
379
+ min_line: 0.9,
380
+ min_branch: 0.9
381
+ });
382
+ });
383
+
384
+ it('GIVEN_sparse_coverage_artifacts_WHEN_parsing_THEN_uses_safe_default_metrics', async () => {
385
+ await fs.writeFile(path.join(tempRoot, 'lcov-empty.info'), 'TN:\nSF:src/a.ts\nend_of_record\n', 'utf8');
386
+ await fs.writeFile(path.join(tempRoot, 'junit-empty.xml'), '<testsuite></testsuite>', 'utf8');
387
+ await fs.writeFile(path.join(tempRoot, 'jacoco-empty.xml'), '<report></report>', 'utf8');
388
+ await fs.writeFile(path.join(tempRoot, 'cobertura-empty.xml'), '<coverage></coverage>', 'utf8');
389
+
390
+ await expect(parseCoverage({ type: 'lcov', path: 'lcov-empty.info' }, tempRoot)).resolves.toMatchObject({
391
+ line: 1,
392
+ branch: 1,
393
+ details: { linesFound: 0, linesHit: 0, branchesFound: 0, branchesHit: 0 }
394
+ });
395
+ await expect(parseCoverage({ type: 'junit_xml', path: 'junit-empty.xml' }, tempRoot)).resolves.toMatchObject({
396
+ line: 1,
397
+ branch: 1
398
+ });
399
+ await expect(parseCoverage({ type: 'jacoco_xml', path: 'jacoco-empty.xml' }, tempRoot)).resolves.toMatchObject({
400
+ line: 1,
401
+ branch: 1,
402
+ details: { lineMissed: 0, lineCovered: 0, branchMissed: 0, branchCovered: 0 }
403
+ });
404
+ await expect(parseCoverage({ type: 'cobertura_xml', path: 'cobertura-empty.xml' }, tempRoot)).resolves.toMatchObject({
405
+ line: 1,
406
+ branch: 1,
407
+ details: { lineRate: 1, branchRate: 1 }
408
+ });
409
+ });
410
+
411
+ it('GIVEN_parser_without_path_or_step_cwd_WHEN_running_parsing_or_gate_THEN_uses_defaults', async () => {
412
+ const standaloneLcov = path.join(tempRoot, 'standalone.lcov');
413
+ await fs.writeFile(
414
+ standaloneLcov,
415
+ ['TN:', 'SF:src/a.ts', 'LF:2', 'LH:1', 'BRF:2', 'BRH:1', 'end_of_record', ''].join('\n'),
416
+ 'utf8'
417
+ );
418
+ await expect(parseCoverage({ type: 'lcov' }, standaloneLcov)).resolves.toMatchObject({
419
+ line: 0.5,
420
+ branch: 0.5
421
+ });
422
+
423
+ runCommandMock.mockResolvedValue({
424
+ code: 0,
425
+ signal: null,
426
+ stdout: 'ok',
427
+ stderr: '',
428
+ timeout: false
429
+ });
430
+
431
+ const result = await runGateMode({
432
+ featureId: 'feature_cwd',
433
+ mode: 'fast',
434
+ profileName: 'default',
435
+ profile: {
436
+ modes: {
437
+ fast: [{ name: 'lint', cmd: ['npm', 'run', 'lint'], cwd: 'packages/app' }]
438
+ },
439
+ parsers: { coverage: { type: 'none' } }
440
+ },
441
+ policy: basePolicy as any,
442
+ worktreePath: tempRoot,
443
+ logDirectory: path.join(tempRoot, 'logs'),
444
+ evidenceDirectory: path.join(tempRoot, 'evidence')
445
+ });
446
+
447
+ expect(result.overall).toBe('pass');
448
+ expect(runCommandMock.mock.calls[0]?.[2]).toMatchObject({
449
+ cwd: path.join(tempRoot, 'packages/app')
450
+ });
451
+ });
452
+ });
@@ -0,0 +1,68 @@
1
+ import fs from 'node:fs/promises';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { stableHash } from '../src/core/fs.js';
5
+ import { runCommand } from '../src/core/git.js';
6
+
7
+ export async function makeTempRepo(templateRoot) {
8
+ const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'aop-test-'));
9
+ await fs.cp(path.join(templateRoot, 'agentic'), path.join(tempRoot, 'agentic'), { recursive: true });
10
+ await fs.cp(path.join(templateRoot, 'apps'), path.join(tempRoot, 'apps'), { recursive: true });
11
+ await fs.writeFile(path.join(tempRoot, 'README.md'), '# temp repo\n', 'utf8');
12
+
13
+ // Runtime artifacts are generated under .aop and should not come from the template copy.
14
+ await fs.rm(path.join(tempRoot, '.aop', 'features'), { recursive: true, force: true });
15
+ await fs.rm(path.join(tempRoot, '.aop', 'runtime'), { recursive: true, force: true });
16
+
17
+ await fs.mkdir(path.join(tempRoot, '.aop', 'features'), { recursive: true });
18
+ await fs.mkdir(path.join(tempRoot, '.aop', 'runtime', 'operation-ledger'), { recursive: true });
19
+
20
+ const indexPath = path.join(tempRoot, '.aop', 'features', 'index.json');
21
+ const now = new Date().toISOString();
22
+ await fs.writeFile(
23
+ indexPath,
24
+ `${JSON.stringify(
25
+ {
26
+ version: 1,
27
+ active: [],
28
+ blocked: [],
29
+ merged: [],
30
+ locks: {},
31
+ lock_leases: {},
32
+ blocked_queue: [],
33
+ updated_at: now,
34
+ runtime_sessions: {
35
+ run_id: 'none',
36
+ orchestrator_session_id: 'unknown',
37
+ provider: 'unknown',
38
+ model: 'unknown',
39
+ provider_config_ref_hash: stableHash('none'),
40
+ owner_instance_id: 'none',
41
+ lease_id: 'none',
42
+ started_at: now,
43
+ last_heartbeat_at: now,
44
+ lease_expires_at: now,
45
+ orchestrator_epoch: 0,
46
+ feature_sessions: {}
47
+ }
48
+ },
49
+ null,
50
+ 2
51
+ )}\n`,
52
+ 'utf8'
53
+ );
54
+
55
+ await runCommand('git', ['init', '-b', 'main'], { cwd: tempRoot });
56
+ await runCommand('git', ['config', 'user.email', 'test@example.com'], { cwd: tempRoot });
57
+ await runCommand('git', ['config', 'user.name', 'AOP Test'], { cwd: tempRoot });
58
+ await runCommand('git', ['add', '.'], { cwd: tempRoot });
59
+ await runCommand('git', ['commit', '-m', 'initial'], { cwd: tempRoot });
60
+
61
+ return tempRoot;
62
+ }
63
+
64
+ export async function writeFeatureSpec(repoRoot, featureId, content = '# Spec\n\nBuild something.\n') {
65
+ const featureDir = path.join(repoRoot, '.aop', 'features', featureId);
66
+ await fs.mkdir(featureDir, { recursive: true });
67
+ await fs.writeFile(path.join(featureDir, 'spec.md'), content, 'utf8');
68
+ }
@@ -0,0 +1,18 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import * as api from '../src/index.js';
3
+
4
+ describe('public index exports', () => {
5
+ it('GIVEN_module_import_WHEN_loaded_THEN_exposes_public_api_symbols', () => {
6
+ expect(typeof api.AopKernel).toBe('function');
7
+ expect(typeof api.SupervisorRuntime).toBe('function');
8
+ expect(typeof api.resolveProviderSelection).toBe('function');
9
+ expect(typeof api.NullWorkerProvider).toBe('function');
10
+ expect(typeof api.createToolingRuntime).toBe('function');
11
+ expect(typeof api.resolveToolClient).toBe('function');
12
+ expect(typeof api.InProcessToolClient).toBe('function');
13
+ expect(typeof api.McpToolClient).toBe('function');
14
+ expect(typeof api.createOperationId).toBe('function');
15
+ expect(typeof api.TokenAuthVerifier).toBe('function');
16
+ expect(typeof api.McpServerAdapter).toBe('function');
17
+ });
18
+ });