agentic-orchestrator 0.1.3 → 0.1.4

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 (294) hide show
  1. package/.claude/settings.local.json +15 -0
  2. package/CLAUDE.md +126 -0
  3. package/README.md +166 -25
  4. package/agentic/orchestrator/adapters.yaml +3 -0
  5. package/agentic/orchestrator/gates.yaml +47 -0
  6. package/agentic/orchestrator/policy.yaml +89 -0
  7. package/agentic/orchestrator/schemas/adapters.schema.json +12 -0
  8. package/agentic/orchestrator/schemas/gates.schema.json +6 -1
  9. package/agentic/orchestrator/schemas/index.schema.json +14 -0
  10. package/agentic/orchestrator/schemas/multi-project.schema.json +41 -0
  11. package/agentic/orchestrator/schemas/policy.schema.json +449 -52
  12. package/agentic/orchestrator/schemas/state.schema.json +16 -0
  13. package/agentic/orchestrator/tools/catalog.json +68 -0
  14. package/agentic/orchestrator/tools/schemas/input/cost.get.input.schema.json +10 -0
  15. package/agentic/orchestrator/tools/schemas/input/cost.record.input.schema.json +13 -0
  16. package/agentic/orchestrator/tools/schemas/input/feature.send_message.input.schema.json +11 -0
  17. package/agentic/orchestrator/tools/schemas/input/performance.get_analytics.input.schema.json +10 -0
  18. package/agentic/orchestrator/tools/schemas/input/performance.record_outcome.input.schema.json +18 -0
  19. package/agentic/orchestrator/tools/schemas/output/cost.get.output.schema.json +13 -0
  20. package/agentic/orchestrator/tools/schemas/output/cost.record.output.schema.json +13 -0
  21. package/agentic/orchestrator/tools/schemas/output/feature.ready_to_merge.output.schema.json +7 -0
  22. package/agentic/orchestrator/tools/schemas/output/feature.send_message.output.schema.json +23 -0
  23. package/agentic/orchestrator/tools/schemas/output/performance.get_analytics.output.schema.json +46 -0
  24. package/agentic/orchestrator/tools/schemas/output/performance.record_outcome.output.schema.json +10 -0
  25. package/agentic/orchestrator/tools.md +5 -0
  26. package/apps/control-plane/scripts/validate-architecture-rules.mjs +28 -2
  27. package/apps/control-plane/scripts/validate-docker-mcp-contract.mjs +12 -0
  28. package/apps/control-plane/scripts/validate-mcp-contracts.ts +92 -0
  29. package/apps/control-plane/src/application/adapters/adapter-registry.ts +169 -0
  30. package/apps/control-plane/src/application/multi-project-loader.ts +119 -0
  31. package/apps/control-plane/src/application/services/activity-monitor-service.ts +199 -0
  32. package/apps/control-plane/src/application/services/cost-tracking-service.ts +82 -0
  33. package/apps/control-plane/src/application/services/dependency-scheduler-service.ts +86 -0
  34. package/apps/control-plane/src/application/services/feature-deletion-service.ts +7 -5
  35. package/apps/control-plane/src/application/services/gate-interpolation-service.ts +15 -0
  36. package/apps/control-plane/src/application/services/gate-service.ts +38 -2
  37. package/apps/control-plane/src/application/services/instance-isolation-service.ts +18 -0
  38. package/apps/control-plane/src/application/services/issue-tracker-service.ts +469 -0
  39. package/apps/control-plane/src/application/services/merge-service.ts +67 -3
  40. package/apps/control-plane/src/application/services/notifier-service.ts +295 -0
  41. package/apps/control-plane/src/application/services/performance-analytics-service.ts +122 -0
  42. package/apps/control-plane/src/application/services/plan-service.ts +51 -0
  43. package/apps/control-plane/src/application/services/pr-monitor-service.ts +262 -0
  44. package/apps/control-plane/src/application/services/reactions-service.ts +175 -0
  45. package/apps/control-plane/src/application/services/reporting-service.ts +17 -2
  46. package/apps/control-plane/src/application/services/run-lease-service.ts +16 -38
  47. package/apps/control-plane/src/application/tools/tool-metadata.ts +4 -1
  48. package/apps/control-plane/src/cli/attach-command-handler.ts +120 -0
  49. package/apps/control-plane/src/cli/cleanup-command-handler.ts +190 -0
  50. package/apps/control-plane/src/cli/cli-argument-parser.ts +69 -3
  51. package/apps/control-plane/src/cli/dashboard-command-handler.ts +57 -0
  52. package/apps/control-plane/src/cli/help-command-handler.ts +163 -0
  53. package/apps/control-plane/src/cli/init-command-handler.ts +609 -0
  54. package/apps/control-plane/src/cli/retry-command-handler.ts +138 -0
  55. package/apps/control-plane/src/cli/run-command-handler.ts +115 -3
  56. package/apps/control-plane/src/cli/send-command-handler.ts +65 -0
  57. package/apps/control-plane/src/cli/status-command-handler.ts +102 -2
  58. package/apps/control-plane/src/cli/types.ts +26 -1
  59. package/apps/control-plane/src/core/constants.ts +8 -2
  60. package/apps/control-plane/src/core/error-codes.ts +3 -1
  61. package/apps/control-plane/src/core/gates.ts +170 -50
  62. package/apps/control-plane/src/core/kernel.ts +280 -5
  63. package/apps/control-plane/src/core/path-layout.ts +12 -0
  64. package/apps/control-plane/src/core/tool-caller.ts +36 -0
  65. package/apps/control-plane/src/core/workspace-hooks.ts +87 -0
  66. package/apps/control-plane/src/interfaces/cli/bootstrap.ts +258 -9
  67. package/apps/control-plane/src/providers/providers.ts +235 -14
  68. package/apps/control-plane/src/supervisor/build-wave-executor.ts +129 -8
  69. package/apps/control-plane/src/supervisor/qa-wave-executor.ts +123 -5
  70. package/apps/control-plane/src/supervisor/run-coordinator.ts +143 -6
  71. package/apps/control-plane/src/supervisor/runtime.ts +135 -6
  72. package/apps/control-plane/src/supervisor/types.ts +12 -21
  73. package/apps/control-plane/src/supervisor/worker-decision-loop.ts +8 -0
  74. package/apps/control-plane/test/activity-monitor.spec.ts +294 -0
  75. package/apps/control-plane/test/adapter-registry.spec.ts +132 -0
  76. package/apps/control-plane/test/batch-operations.spec.ts +112 -0
  77. package/apps/control-plane/test/bootstrap-attach.spec.ts +102 -0
  78. package/apps/control-plane/test/bootstrap-edge-cases.spec.ts +252 -0
  79. package/apps/control-plane/test/bootstrap.spec.ts +560 -0
  80. package/apps/control-plane/test/cleanup-command.spec.ts +301 -0
  81. package/apps/control-plane/test/cli-helpers.spec.ts +404 -1
  82. package/apps/control-plane/test/cli.unit.spec.ts +182 -1
  83. package/apps/control-plane/test/collision-queue.spec.ts +104 -1
  84. package/apps/control-plane/test/core-utils.spec.ts +175 -2
  85. package/apps/control-plane/test/cost-tracking.spec.ts +143 -0
  86. package/apps/control-plane/test/dashboard-api.integration.spec.ts +247 -0
  87. package/apps/control-plane/test/dashboard-client.spec.ts +116 -0
  88. package/apps/control-plane/test/dashboard-command.spec.ts +103 -0
  89. package/apps/control-plane/test/dependency-scheduler.spec.ts +189 -0
  90. package/apps/control-plane/test/epoch-tracking.spec.ts +4 -4
  91. package/apps/control-plane/test/feature-deletion-service.spec.ts +422 -0
  92. package/apps/control-plane/test/feature-lifecycle.spec.ts +202 -0
  93. package/apps/control-plane/test/git-spawn-error.spec.ts +24 -0
  94. package/apps/control-plane/test/incremental-gates.spec.ts +137 -0
  95. package/apps/control-plane/test/init-wizard.spec.ts +506 -0
  96. package/apps/control-plane/test/instance-isolation.spec.ts +83 -0
  97. package/apps/control-plane/test/issue-tracker.spec.ts +890 -0
  98. package/apps/control-plane/test/kernel.coverage.spec.ts +3 -5
  99. package/apps/control-plane/test/kernel.coverage2.spec.ts +871 -0
  100. package/apps/control-plane/test/kernel.spec.ts +13 -11
  101. package/apps/control-plane/test/lock-service.spec.ts +508 -0
  102. package/apps/control-plane/test/mcp-helpers.spec.ts +176 -0
  103. package/apps/control-plane/test/mcp.spec.ts +50 -15
  104. package/apps/control-plane/test/merge-service.spec.ts +67 -4
  105. package/apps/control-plane/test/multi-project.spec.ts +372 -0
  106. package/apps/control-plane/test/notifier-service.spec.ts +388 -0
  107. package/apps/control-plane/test/parallel-gates.spec.ts +312 -0
  108. package/apps/control-plane/test/patch-service.spec.ts +253 -0
  109. package/apps/control-plane/test/performance-analytics.spec.ts +338 -0
  110. package/apps/control-plane/test/planning-wave-executor.spec.ts +168 -0
  111. package/apps/control-plane/test/pr-monitor.spec.ts +385 -0
  112. package/apps/control-plane/test/providers.spec.ts +344 -1
  113. package/apps/control-plane/test/reactions.spec.ts +392 -0
  114. package/apps/control-plane/test/resume-command.spec.ts +390 -0
  115. package/apps/control-plane/test/run-coordinator.spec.ts +481 -2
  116. package/apps/control-plane/test/schema-date-time.spec.ts +46 -0
  117. package/apps/control-plane/test/service-retry-paths.spec.ts +30 -0
  118. package/apps/control-plane/test/services.spec.ts +95 -2
  119. package/apps/control-plane/test/session-management.spec.ts +450 -0
  120. package/apps/control-plane/test/spec-ingestion.spec.ts +190 -0
  121. package/apps/control-plane/test/supervisor-collaborators.spec.ts +699 -2
  122. package/apps/control-plane/test/supervisor.spec.ts +36 -30
  123. package/apps/control-plane/test/supervisor.unit.spec.ts +405 -0
  124. package/apps/control-plane/test/worker-decision-loop.spec.ts +57 -0
  125. package/apps/control-plane/test/workspace-hooks.spec.ts +177 -0
  126. package/apps/control-plane/vitest.config.ts +21 -5
  127. package/dist/apps/control-plane/application/adapters/adapter-registry.d.ts +44 -0
  128. package/dist/apps/control-plane/application/adapters/adapter-registry.js +76 -0
  129. package/dist/apps/control-plane/application/adapters/adapter-registry.js.map +1 -0
  130. package/dist/apps/control-plane/application/multi-project-loader.d.ts +31 -0
  131. package/dist/apps/control-plane/application/multi-project-loader.js +82 -0
  132. package/dist/apps/control-plane/application/multi-project-loader.js.map +1 -0
  133. package/dist/apps/control-plane/application/services/activity-monitor-service.d.ts +43 -0
  134. package/dist/apps/control-plane/application/services/activity-monitor-service.js +132 -0
  135. package/dist/apps/control-plane/application/services/activity-monitor-service.js.map +1 -0
  136. package/dist/apps/control-plane/application/services/cost-tracking-service.d.ts +28 -0
  137. package/dist/apps/control-plane/application/services/cost-tracking-service.js +48 -0
  138. package/dist/apps/control-plane/application/services/cost-tracking-service.js.map +1 -0
  139. package/dist/apps/control-plane/application/services/dependency-scheduler-service.d.ts +26 -0
  140. package/dist/apps/control-plane/application/services/dependency-scheduler-service.js +75 -0
  141. package/dist/apps/control-plane/application/services/dependency-scheduler-service.js.map +1 -0
  142. package/dist/apps/control-plane/application/services/feature-deletion-service.d.ts +2 -0
  143. package/dist/apps/control-plane/application/services/feature-deletion-service.js +5 -5
  144. package/dist/apps/control-plane/application/services/feature-deletion-service.js.map +1 -1
  145. package/dist/apps/control-plane/application/services/gate-interpolation-service.d.ts +7 -0
  146. package/dist/apps/control-plane/application/services/gate-interpolation-service.js +7 -0
  147. package/dist/apps/control-plane/application/services/gate-interpolation-service.js.map +1 -0
  148. package/dist/apps/control-plane/application/services/gate-service.js +32 -2
  149. package/dist/apps/control-plane/application/services/gate-service.js.map +1 -1
  150. package/dist/apps/control-plane/application/services/instance-isolation-service.d.ts +11 -0
  151. package/dist/apps/control-plane/application/services/instance-isolation-service.js +17 -0
  152. package/dist/apps/control-plane/application/services/instance-isolation-service.js.map +1 -0
  153. package/dist/apps/control-plane/application/services/issue-tracker-service.d.ts +65 -0
  154. package/dist/apps/control-plane/application/services/issue-tracker-service.js +358 -0
  155. package/dist/apps/control-plane/application/services/issue-tracker-service.js.map +1 -0
  156. package/dist/apps/control-plane/application/services/merge-service.d.ts +4 -0
  157. package/dist/apps/control-plane/application/services/merge-service.js +44 -2
  158. package/dist/apps/control-plane/application/services/merge-service.js.map +1 -1
  159. package/dist/apps/control-plane/application/services/notifier-service.d.ts +74 -0
  160. package/dist/apps/control-plane/application/services/notifier-service.js +212 -0
  161. package/dist/apps/control-plane/application/services/notifier-service.js.map +1 -0
  162. package/dist/apps/control-plane/application/services/performance-analytics-service.d.ts +39 -0
  163. package/dist/apps/control-plane/application/services/performance-analytics-service.js +75 -0
  164. package/dist/apps/control-plane/application/services/performance-analytics-service.js.map +1 -0
  165. package/dist/apps/control-plane/application/services/plan-service.d.ts +1 -0
  166. package/dist/apps/control-plane/application/services/plan-service.js +53 -0
  167. package/dist/apps/control-plane/application/services/plan-service.js.map +1 -1
  168. package/dist/apps/control-plane/application/services/pr-monitor-service.d.ts +44 -0
  169. package/dist/apps/control-plane/application/services/pr-monitor-service.js +192 -0
  170. package/dist/apps/control-plane/application/services/pr-monitor-service.js.map +1 -0
  171. package/dist/apps/control-plane/application/services/reactions-service.d.ts +67 -0
  172. package/dist/apps/control-plane/application/services/reactions-service.js +114 -0
  173. package/dist/apps/control-plane/application/services/reactions-service.js.map +1 -0
  174. package/dist/apps/control-plane/application/services/reporting-service.d.ts +1 -0
  175. package/dist/apps/control-plane/application/services/reporting-service.js +13 -2
  176. package/dist/apps/control-plane/application/services/reporting-service.js.map +1 -1
  177. package/dist/apps/control-plane/application/services/run-lease-service.d.ts +2 -0
  178. package/dist/apps/control-plane/application/services/run-lease-service.js +14 -38
  179. package/dist/apps/control-plane/application/services/run-lease-service.js.map +1 -1
  180. package/dist/apps/control-plane/application/tools/tool-metadata.js +3 -1
  181. package/dist/apps/control-plane/application/tools/tool-metadata.js.map +1 -1
  182. package/dist/apps/control-plane/cli/attach-command-handler.d.ts +12 -0
  183. package/dist/apps/control-plane/cli/attach-command-handler.js +98 -0
  184. package/dist/apps/control-plane/cli/attach-command-handler.js.map +1 -0
  185. package/dist/apps/control-plane/cli/cleanup-command-handler.d.ts +12 -0
  186. package/dist/apps/control-plane/cli/cleanup-command-handler.js +162 -0
  187. package/dist/apps/control-plane/cli/cleanup-command-handler.js.map +1 -0
  188. package/dist/apps/control-plane/cli/cli-argument-parser.js +68 -3
  189. package/dist/apps/control-plane/cli/cli-argument-parser.js.map +1 -1
  190. package/dist/apps/control-plane/cli/dashboard-command-handler.d.ts +7 -0
  191. package/dist/apps/control-plane/cli/dashboard-command-handler.js +45 -0
  192. package/dist/apps/control-plane/cli/dashboard-command-handler.js.map +1 -0
  193. package/dist/apps/control-plane/cli/help-command-handler.d.ts +8 -0
  194. package/dist/apps/control-plane/cli/help-command-handler.js +146 -0
  195. package/dist/apps/control-plane/cli/help-command-handler.js.map +1 -0
  196. package/dist/apps/control-plane/cli/init-command-handler.d.ts +26 -0
  197. package/dist/apps/control-plane/cli/init-command-handler.js +517 -0
  198. package/dist/apps/control-plane/cli/init-command-handler.js.map +1 -0
  199. package/dist/apps/control-plane/cli/retry-command-handler.d.ts +8 -0
  200. package/dist/apps/control-plane/cli/retry-command-handler.js +111 -0
  201. package/dist/apps/control-plane/cli/retry-command-handler.js.map +1 -0
  202. package/dist/apps/control-plane/cli/run-command-handler.d.ts +5 -0
  203. package/dist/apps/control-plane/cli/run-command-handler.js +82 -3
  204. package/dist/apps/control-plane/cli/run-command-handler.js.map +1 -1
  205. package/dist/apps/control-plane/cli/send-command-handler.d.ts +8 -0
  206. package/dist/apps/control-plane/cli/send-command-handler.js +55 -0
  207. package/dist/apps/control-plane/cli/send-command-handler.js.map +1 -0
  208. package/dist/apps/control-plane/cli/status-command-handler.d.ts +12 -1
  209. package/dist/apps/control-plane/cli/status-command-handler.js +55 -2
  210. package/dist/apps/control-plane/cli/status-command-handler.js.map +1 -1
  211. package/dist/apps/control-plane/cli/types.d.ts +25 -1
  212. package/dist/apps/control-plane/cli/types.js +15 -1
  213. package/dist/apps/control-plane/cli/types.js.map +1 -1
  214. package/dist/apps/control-plane/core/constants.d.ts +6 -0
  215. package/dist/apps/control-plane/core/constants.js +8 -2
  216. package/dist/apps/control-plane/core/constants.js.map +1 -1
  217. package/dist/apps/control-plane/core/error-codes.d.ts +2 -0
  218. package/dist/apps/control-plane/core/error-codes.js +3 -1
  219. package/dist/apps/control-plane/core/error-codes.js.map +1 -1
  220. package/dist/apps/control-plane/core/gates.d.ts +4 -0
  221. package/dist/apps/control-plane/core/gates.js +140 -43
  222. package/dist/apps/control-plane/core/gates.js.map +1 -1
  223. package/dist/apps/control-plane/core/kernel.d.ts +48 -1
  224. package/dist/apps/control-plane/core/kernel.js +218 -5
  225. package/dist/apps/control-plane/core/kernel.js.map +1 -1
  226. package/dist/apps/control-plane/core/path-layout.d.ts +3 -0
  227. package/dist/apps/control-plane/core/path-layout.js +9 -0
  228. package/dist/apps/control-plane/core/path-layout.js.map +1 -1
  229. package/dist/apps/control-plane/core/tool-caller.d.ts +32 -0
  230. package/dist/apps/control-plane/core/tool-caller.js +2 -0
  231. package/dist/apps/control-plane/core/tool-caller.js.map +1 -0
  232. package/dist/apps/control-plane/core/workspace-hooks.d.ts +20 -0
  233. package/dist/apps/control-plane/core/workspace-hooks.js +69 -0
  234. package/dist/apps/control-plane/core/workspace-hooks.js.map +1 -0
  235. package/dist/apps/control-plane/interfaces/cli/bootstrap.js +245 -9
  236. package/dist/apps/control-plane/interfaces/cli/bootstrap.js.map +1 -1
  237. package/dist/apps/control-plane/providers/providers.d.ts +39 -4
  238. package/dist/apps/control-plane/providers/providers.js +160 -10
  239. package/dist/apps/control-plane/providers/providers.js.map +1 -1
  240. package/dist/apps/control-plane/supervisor/build-wave-executor.d.ts +3 -0
  241. package/dist/apps/control-plane/supervisor/build-wave-executor.js +115 -6
  242. package/dist/apps/control-plane/supervisor/build-wave-executor.js.map +1 -1
  243. package/dist/apps/control-plane/supervisor/qa-wave-executor.d.ts +3 -0
  244. package/dist/apps/control-plane/supervisor/qa-wave-executor.js +109 -5
  245. package/dist/apps/control-plane/supervisor/qa-wave-executor.js.map +1 -1
  246. package/dist/apps/control-plane/supervisor/run-coordinator.d.ts +15 -0
  247. package/dist/apps/control-plane/supervisor/run-coordinator.js +132 -6
  248. package/dist/apps/control-plane/supervisor/run-coordinator.js.map +1 -1
  249. package/dist/apps/control-plane/supervisor/runtime.d.ts +3 -0
  250. package/dist/apps/control-plane/supervisor/runtime.js +110 -6
  251. package/dist/apps/control-plane/supervisor/runtime.js.map +1 -1
  252. package/dist/apps/control-plane/supervisor/types.d.ts +9 -16
  253. package/dist/apps/control-plane/supervisor/types.js.map +1 -1
  254. package/dist/apps/control-plane/supervisor/worker-decision-loop.d.ts +3 -0
  255. package/dist/apps/control-plane/supervisor/worker-decision-loop.js +5 -0
  256. package/dist/apps/control-plane/supervisor/worker-decision-loop.js.map +1 -1
  257. package/eslint.config.mjs +2 -1
  258. package/package.json +12 -2
  259. package/packages/web-dashboard/next-env.d.ts +5 -0
  260. package/packages/web-dashboard/next.config.js +7 -0
  261. package/packages/web-dashboard/package.json +26 -0
  262. package/packages/web-dashboard/src/app/api/actions/route.ts +64 -0
  263. package/packages/web-dashboard/src/app/api/events/route.ts +51 -0
  264. package/packages/web-dashboard/src/app/api/features/[id]/checkout/route.ts +256 -0
  265. package/packages/web-dashboard/src/app/api/features/[id]/diff/route.ts +10 -0
  266. package/packages/web-dashboard/src/app/api/features/[id]/evidence/[artifact]/route.ts +25 -0
  267. package/packages/web-dashboard/src/app/api/features/[id]/review/route.ts +63 -0
  268. package/packages/web-dashboard/src/app/api/features/[id]/route.ts +16 -0
  269. package/packages/web-dashboard/src/app/api/projects/route.ts +31 -0
  270. package/packages/web-dashboard/src/app/api/status/route.ts +15 -0
  271. package/packages/web-dashboard/src/app/globals.css +2 -0
  272. package/packages/web-dashboard/src/app/layout.tsx +15 -0
  273. package/packages/web-dashboard/src/app/page.tsx +393 -0
  274. package/packages/web-dashboard/src/lib/aop-client.ts +244 -0
  275. package/packages/web-dashboard/src/lib/multi-project-config.ts +116 -0
  276. package/packages/web-dashboard/src/lib/orchestrator-tools.ts +284 -0
  277. package/packages/web-dashboard/src/lib/types.ts +58 -0
  278. package/packages/web-dashboard/tsconfig.json +40 -0
  279. package/packages/web-dashboard/vitest.config.ts +6 -0
  280. package/spec-files/completed/agentic_orchestrator_feature_gaps_closure_spec.md +1764 -0
  281. package/spec-files/outstanding/agentic_orchestrator_enterprise_governance_dashboard_spec.md +348 -0
  282. package/spec-files/outstanding/agentic_orchestrator_knowledge_canary_spec.md +344 -0
  283. package/spec-files/outstanding/agentic_orchestrator_observability_integrity_diagnostics_spec.md +374 -0
  284. package/spec-files/outstanding/agentic_orchestrator_performance_improvements_spec.md +1059 -0
  285. package/spec-files/outstanding/agentic_orchestrator_planning_review_quality_spec.md +466 -0
  286. package/spec-files/outstanding/agentic_orchestrator_quality_adoption_execution_spec.md +198 -0
  287. package/spec-files/outstanding/agentic_orchestrator_validator_hardening_spec.md +365 -0
  288. package/spec-files/progress.md +481 -52
  289. /package/spec-files/{agentic_orchestrator_cli_delete_command_spec.md → completed/agentic_orchestrator_cli_delete_command_spec.md} +0 -0
  290. /package/spec-files/{agentic_orchestrator_dot_aop_generated_artifacts_spec.md → completed/agentic_orchestrator_dot_aop_generated_artifacts_spec.md} +0 -0
  291. /package/spec-files/{agentic_orchestrator_mcp_formalization_spec.md → completed/agentic_orchestrator_mcp_formalization_spec.md} +0 -0
  292. /package/spec-files/{agentic_orchestrator_oop_refactor_spec.md → completed/agentic_orchestrator_oop_refactor_spec.md} +0 -0
  293. /package/spec-files/{agentic_orchestrator_single_global_orchestrator_spec.md → completed/agentic_orchestrator_single_global_orchestrator_spec.md} +0 -0
  294. /package/spec-files/{agentic_orchestrator_spec.md → completed/agentic_orchestrator_spec.md} +0 -0
@@ -0,0 +1,295 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { promisify } from 'node:util';
3
+
4
+ const execFileAsync = promisify(execFile);
5
+
6
+ export type NotificationPriority = 'critical' | 'warning' | 'info';
7
+ type CanonicalPriority = NotificationPriority;
8
+ export type NotificationEvent =
9
+ | 'gate_failed'
10
+ | 'collision_detected'
11
+ | 'feature_blocked'
12
+ | 'ready_to_merge'
13
+ | 'feature_merged'
14
+ | 'stale_lease'
15
+ | 'agent_stuck'
16
+ | 'changes_requested'
17
+ | 'budget_exceeded'
18
+ | 'budget_alert';
19
+
20
+ export interface NotificationPayload {
21
+ event: NotificationEvent;
22
+ priority: NotificationPriority;
23
+ feature_id?: string;
24
+ message: string;
25
+ details?: Record<string, unknown>;
26
+ timestamp: string;
27
+ }
28
+
29
+ export interface NotifierChannel {
30
+ name: string;
31
+ send(payload: NotificationPayload): Promise<void>;
32
+ }
33
+
34
+ export interface NotificationChannelConfig {
35
+ desktop?: { enabled?: boolean };
36
+ slack?: { enabled?: boolean; webhook?: string; channel?: string };
37
+ webhook?: { enabled?: boolean; url?: string };
38
+ }
39
+
40
+ export interface NotificationRoutingConfig {
41
+ critical?: string[];
42
+ warning?: string[];
43
+ info?: string[];
44
+ urgent?: string[];
45
+ action?: string[];
46
+ }
47
+
48
+ export interface NotificationConfig {
49
+ enabled: boolean;
50
+ channels?: NotificationChannelConfig;
51
+ routing?: NotificationRoutingConfig;
52
+ }
53
+
54
+ const DEFAULT_ROUTING: Record<NotificationPriority, string[]> = {
55
+ critical: ['desktop', 'slack'],
56
+ warning: ['slack', 'desktop'],
57
+ info: ['slack']
58
+ };
59
+
60
+ const EVENT_PRIORITY: Record<NotificationEvent, CanonicalPriority> = {
61
+ gate_failed: 'critical',
62
+ collision_detected: 'critical',
63
+ feature_blocked: 'warning',
64
+ ready_to_merge: 'info',
65
+ feature_merged: 'info',
66
+ stale_lease: 'warning',
67
+ agent_stuck: 'warning',
68
+ changes_requested: 'warning',
69
+ budget_exceeded: 'critical',
70
+ budget_alert: 'warning'
71
+ };
72
+
73
+ const THROTTLE_WINDOW_MS = 5 * 60 * 1000; // 5 minutes
74
+
75
+ export class DesktopNotifierChannel implements NotifierChannel {
76
+ readonly name = 'desktop';
77
+
78
+ async send(payload: NotificationPayload): Promise<void> {
79
+ const title = `AOP [${payload.priority}]`;
80
+ const body = payload.feature_id
81
+ ? `[${payload.feature_id}] ${payload.message}`
82
+ : payload.message;
83
+
84
+ const platform = process.platform;
85
+ try {
86
+ if (platform === 'linux') {
87
+ await execFileAsync('notify-send', [title, body], { timeout: 3000 });
88
+ } else if (platform === 'darwin') {
89
+ const script = `display notification "${body.replaceAll('"', '\\"')}" with title "${title.replaceAll('"', '\\"')}"`;
90
+ await execFileAsync('osascript', ['-e', script], { timeout: 3000 });
91
+ }
92
+ // Other platforms: silently skip
93
+ } catch {
94
+ // Notification tool not available — silently skip
95
+ }
96
+ }
97
+ }
98
+
99
+ export class SlackNotifierChannel implements NotifierChannel {
100
+ readonly name = 'slack';
101
+ private readonly webhookUrl: string;
102
+ private readonly channel: string;
103
+
104
+ constructor(webhookUrl: string, channel: string) {
105
+ this.webhookUrl = webhookUrl;
106
+ this.channel = channel;
107
+ }
108
+
109
+ async send(payload: NotificationPayload): Promise<void> {
110
+ const details = payload.details ?? {};
111
+ const dashboardFeatureUrl =
112
+ typeof details.dashboard_feature_url === 'string' && details.dashboard_feature_url.length > 0
113
+ ? details.dashboard_feature_url
114
+ : typeof details.dashboard_url === 'string' && details.dashboard_url.length > 0
115
+ ? details.dashboard_url
116
+ : null;
117
+ const detailsJson = JSON.stringify(details);
118
+ const detailsSuffix =
119
+ detailsJson !== '{}' ? `\nContext: \`${detailsJson.length > 800 ? `${detailsJson.slice(0, 800)}…` : detailsJson}\`` : '';
120
+ const dashboardSuffix = dashboardFeatureUrl ? `\nDashboard: ${dashboardFeatureUrl}` : '';
121
+ const text = payload.feature_id
122
+ ? `*[${payload.priority.toUpperCase()}]* \`${payload.feature_id}\`: ${payload.message}`
123
+ : `*[${payload.priority.toUpperCase()}]* ${payload.message}`;
124
+
125
+ const body = JSON.stringify({ channel: this.channel, text: `${text}${dashboardSuffix}${detailsSuffix}` });
126
+ const response = await fetch(this.webhookUrl, {
127
+ method: 'POST',
128
+ headers: { 'Content-Type': 'application/json' },
129
+ body
130
+ });
131
+ if (!response.ok) {
132
+ throw new Error(`Slack webhook returned ${response.status}`);
133
+ }
134
+ }
135
+ }
136
+
137
+ export class WebhookNotifierChannel implements NotifierChannel {
138
+ readonly name = 'webhook';
139
+ private readonly url: string;
140
+
141
+ constructor(url: string) {
142
+ this.url = url;
143
+ }
144
+
145
+ async send(payload: NotificationPayload): Promise<void> {
146
+ const response = await fetch(this.url, {
147
+ method: 'POST',
148
+ headers: { 'Content-Type': 'application/json' },
149
+ body: JSON.stringify(payload)
150
+ });
151
+ if (!response.ok) {
152
+ throw new Error(`Webhook returned ${response.status}`);
153
+ }
154
+ }
155
+ }
156
+
157
+ export class NotifierService {
158
+ private readonly config: NotificationConfig;
159
+ private readonly channels: Map<string, NotifierChannel>;
160
+ private readonly routing: Record<CanonicalPriority, string[]>;
161
+ private readonly throttleCache: Map<string, number>;
162
+ private readonly dashboardUrl: string | null;
163
+
164
+ constructor(config: NotificationConfig, dashboardUrl: string | null = null) {
165
+ this.config = config;
166
+ this.throttleCache = new Map();
167
+ this.routing = this.buildRouting(config.routing);
168
+ this.channels = this.buildChannels(config.channels);
169
+ this.dashboardUrl = dashboardUrl;
170
+ }
171
+
172
+ private buildRouting(routing: NotificationRoutingConfig | undefined): Record<CanonicalPriority, string[]> {
173
+ const critical = routing?.critical ?? routing?.urgent ?? routing?.action ?? DEFAULT_ROUTING.critical;
174
+ return {
175
+ critical,
176
+ warning: routing?.warning ?? DEFAULT_ROUTING.warning,
177
+ info: routing?.info ?? DEFAULT_ROUTING.info
178
+ };
179
+ }
180
+
181
+ private buildChannels(channelsConfig: NotificationChannelConfig | undefined): Map<string, NotifierChannel> {
182
+ const map = new Map<string, NotifierChannel>();
183
+ if (!channelsConfig) {
184
+ return map;
185
+ }
186
+
187
+ if (channelsConfig.desktop?.enabled === true) {
188
+ map.set('desktop', new DesktopNotifierChannel());
189
+ }
190
+
191
+ const slack = channelsConfig.slack;
192
+ if (slack?.enabled === true && slack.webhook) {
193
+ map.set('slack', new SlackNotifierChannel(slack.webhook, slack.channel ?? '#aop-alerts'));
194
+ }
195
+
196
+ const webhook = channelsConfig.webhook;
197
+ if (webhook?.enabled === true && webhook.url) {
198
+ map.set('webhook', new WebhookNotifierChannel(webhook.url));
199
+ }
200
+
201
+ return map;
202
+ }
203
+
204
+ private isThrottled(featureId: string | undefined, event: NotificationEvent): boolean {
205
+ const key = `${featureId ?? '__global__'}:${event}`;
206
+ const last = this.throttleCache.get(key);
207
+ const now = Date.now();
208
+ if (last !== undefined && now - last < THROTTLE_WINDOW_MS) {
209
+ return true;
210
+ }
211
+ this.throttleCache.set(key, now);
212
+ return false;
213
+ }
214
+
215
+ async notify(
216
+ event: NotificationEvent,
217
+ context: { feature_id?: string; message: string; details?: Record<string, unknown> }
218
+ ): Promise<void> {
219
+ if (!this.config.enabled) {
220
+ return;
221
+ }
222
+ if (this.isThrottled(context.feature_id, event)) {
223
+ return;
224
+ }
225
+
226
+ const priority = EVENT_PRIORITY[event];
227
+ const details: Record<string, unknown> = {
228
+ ...(context.details ?? {})
229
+ };
230
+ if (this.dashboardUrl) {
231
+ details.dashboard_url = this.dashboardUrl;
232
+ if (context.feature_id) {
233
+ details.dashboard_feature_url = `${this.dashboardUrl}?feature=${encodeURIComponent(context.feature_id)}`;
234
+ }
235
+ }
236
+ const payload: NotificationPayload = {
237
+ event,
238
+ priority,
239
+ feature_id: context.feature_id,
240
+ message: context.message,
241
+ details,
242
+ timestamp: new Date().toISOString()
243
+ };
244
+
245
+ const targetChannelNames = this.routing[priority] ?? [];
246
+
247
+ for (const channelName of targetChannelNames) {
248
+ const channel = this.channels.get(channelName);
249
+ if (!channel) {
250
+ continue;
251
+ }
252
+ try {
253
+ await channel.send(payload);
254
+ } catch (err) {
255
+ process.stderr.write(`[NotifierService] Channel "${channelName}" failed: ${String(err)}\n`);
256
+ }
257
+ }
258
+ }
259
+ }
260
+
261
+ export function createNotifierService(
262
+ policySnapshot: Record<string, unknown>,
263
+ preferredChannel: string | null = null
264
+ ): NotifierService {
265
+ const raw = policySnapshot.notifications;
266
+ if (!raw || typeof raw !== 'object') {
267
+ return new NotifierService({ enabled: false });
268
+ }
269
+ const n = raw as Record<string, unknown>;
270
+ const config: NotificationConfig = {
271
+ enabled: n.enabled === true,
272
+ channels: (n.channels as NotificationChannelConfig | undefined) ?? {},
273
+ routing: (n.routing as NotificationRoutingConfig | undefined) ?? {}
274
+ };
275
+ if (preferredChannel) {
276
+ const channels = config.channels ?? {};
277
+ const forceEnabled = { enabled: true };
278
+ config.channels = {
279
+ desktop: preferredChannel === 'desktop' ? { ...(channels.desktop ?? {}), ...forceEnabled } : { enabled: false },
280
+ slack: preferredChannel === 'slack' ? { ...(channels.slack ?? {}), ...forceEnabled } : { enabled: false },
281
+ webhook: preferredChannel === 'webhook' ? { ...(channels.webhook ?? {}), ...forceEnabled } : { enabled: false }
282
+ };
283
+ }
284
+ const dashboardRaw =
285
+ policySnapshot.dashboard && typeof policySnapshot.dashboard === 'object'
286
+ ? (policySnapshot.dashboard as Record<string, unknown>)
287
+ : {};
288
+ const dashboardPort =
289
+ typeof dashboardRaw.port === 'number' && Number.isFinite(dashboardRaw.port) ? Math.floor(dashboardRaw.port) : 3000;
290
+ const dashboardUrl =
291
+ typeof process.env.AOP_DASHBOARD_URL === 'string' && process.env.AOP_DASHBOARD_URL.trim().length > 0
292
+ ? process.env.AOP_DASHBOARD_URL.trim()
293
+ : `http://localhost:${dashboardPort}`;
294
+ return new NotifierService(config, dashboardUrl);
295
+ }
@@ -0,0 +1,122 @@
1
+ import { atomicWriteJson, ensureDir, nowIso, readJson } from '../../core/fs.js';
2
+ import path from 'node:path';
3
+
4
+ export interface FeatureOutcome {
5
+ feature_id: string;
6
+ provider: string;
7
+ model: string;
8
+ status: string;
9
+ gate_pass: boolean;
10
+ retry_count: number;
11
+ duration_ms: number;
12
+ cost_usd: number;
13
+ recorded_at: string;
14
+ }
15
+
16
+ export interface ProviderModelStats {
17
+ provider: string;
18
+ model: string;
19
+ total_features: number;
20
+ success_count: number;
21
+ success_rate: number;
22
+ avg_retry_count: number;
23
+ avg_duration_ms: number;
24
+ avg_cost_usd: number;
25
+ last_updated: string;
26
+ }
27
+
28
+ export interface AnalyticsSnapshot {
29
+ outcomes: FeatureOutcome[];
30
+ aggregates: ProviderModelStats[];
31
+ generated_at: string;
32
+ }
33
+
34
+ export interface PerformanceAnalyticsServicePort {
35
+ analyticsPath(): string;
36
+ getPolicySnapshot(): Record<string, unknown>;
37
+ }
38
+
39
+ function computeAggregates(outcomes: FeatureOutcome[]): ProviderModelStats[] {
40
+ const groups = new Map<string, FeatureOutcome[]>();
41
+ for (const o of outcomes) {
42
+ const key = `${o.provider}::${o.model}`;
43
+ const list = groups.get(key);
44
+ if (list) {
45
+ list.push(o);
46
+ } else {
47
+ groups.set(key, [o]);
48
+ }
49
+ }
50
+
51
+ const aggregates: ProviderModelStats[] = [];
52
+ for (const [, group] of groups) {
53
+ const first = group[0];
54
+ const total = group.length;
55
+ const successCount = group.filter((o) => o.gate_pass).length;
56
+ const sumRetry = group.reduce((s, o) => s + o.retry_count, 0);
57
+ const sumDuration = group.reduce((s, o) => s + o.duration_ms, 0);
58
+ const sumCost = group.reduce((s, o) => s + o.cost_usd, 0);
59
+
60
+ aggregates.push({
61
+ provider: first.provider,
62
+ model: first.model,
63
+ total_features: total,
64
+ success_count: successCount,
65
+ success_rate: total > 0 ? successCount / total : 0,
66
+ avg_retry_count: total > 0 ? sumRetry / total : 0,
67
+ avg_duration_ms: total > 0 ? sumDuration / total : 0,
68
+ avg_cost_usd: total > 0 ? sumCost / total : 0,
69
+ last_updated: nowIso()
70
+ });
71
+ }
72
+
73
+ return aggregates;
74
+ }
75
+
76
+ export class PerformanceAnalyticsService {
77
+ private readonly port: PerformanceAnalyticsServicePort;
78
+
79
+ constructor(port: PerformanceAnalyticsServicePort) {
80
+ this.port = port;
81
+ }
82
+
83
+ async recordOutcome(outcome: FeatureOutcome): Promise<AnalyticsSnapshot> {
84
+ const filePath = this.port.analyticsPath();
85
+ await ensureDir(path.dirname(filePath));
86
+
87
+ const current = await this.readSnapshot();
88
+ current.outcomes.push(outcome);
89
+ current.aggregates = computeAggregates(current.outcomes);
90
+ current.generated_at = nowIso();
91
+
92
+ await atomicWriteJson(filePath, current);
93
+ return current;
94
+ }
95
+
96
+ async getAnalytics(): Promise<AnalyticsSnapshot> {
97
+ return await this.readSnapshot();
98
+ }
99
+
100
+ async getProviderStats(provider?: string, model?: string): Promise<ProviderModelStats[]> {
101
+ const snapshot = await this.readSnapshot();
102
+ let stats = snapshot.aggregates;
103
+
104
+ if (provider) {
105
+ stats = stats.filter((s) => s.provider === provider);
106
+ }
107
+ if (model) {
108
+ stats = stats.filter((s) => s.model === model);
109
+ }
110
+
111
+ return stats;
112
+ }
113
+
114
+ private async readSnapshot(): Promise<AnalyticsSnapshot> {
115
+ const existing = await readJson<AnalyticsSnapshot>(this.port.analyticsPath(), null);
116
+ return existing ?? {
117
+ outcomes: [],
118
+ aggregates: [],
119
+ generated_at: nowIso()
120
+ };
121
+ }
122
+ }
@@ -4,6 +4,7 @@ import { sortResourcesDeterministically } from '../../core/path-rules.js';
4
4
  import { ERROR_CODES } from '../../core/error-codes.js';
5
5
  import { fail } from '../../core/response.js';
6
6
  import { GATE_RESULT, STATUS } from '../../core/constants.js';
7
+ import { getUnresolvedDeps, detectCircularDependency, addToDepBlocked } from './dependency-scheduler-service.js';
7
8
 
8
9
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
10
  type AnyRecord = Record<string, any>;
@@ -227,6 +228,53 @@ export class PlanService {
227
228
  };
228
229
  }
229
230
 
231
+ async checkDependencies(featureId: string | null): Promise<void> {
232
+ if (!featureId) {return;}
233
+ const state = await this.port.readState(featureId);
234
+ const dependsOn: string[] = Array.isArray(state.frontMatter.depends_on)
235
+ ? (state.frontMatter.depends_on as string[]).filter((d): d is string => typeof d === 'string')
236
+ : [];
237
+ if (dependsOn.length === 0) {return;}
238
+
239
+ // Circular detection: traverse the dependency chain
240
+ const depsCache = new Map<string, string[]>([[featureId, dependsOn]]);
241
+ const getDirectDeps = (id: string): string[] => {
242
+ if (depsCache.has(id)) {return depsCache.get(id);}
243
+ return [];
244
+ };
245
+ const cycle = detectCircularDependency(featureId, getDirectDeps);
246
+ if (cycle) {
247
+ throw {
248
+ normalizedResponse: fail(ERROR_CODES.DEPENDENCY_CIRCULAR, `Circular dependency detected: ${cycle}`, {
249
+ feature_id: featureId,
250
+ cycle,
251
+ retryable: false,
252
+ requires_human: true
253
+ })
254
+ };
255
+ }
256
+
257
+ const index = await this.port.readIndex();
258
+ const mergedFeatures: string[] = Array.isArray(index.merged) ? (index.merged as string[]) : [];
259
+ const unresolved = getUnresolvedDeps(dependsOn, mergedFeatures);
260
+ if (unresolved.length > 0) {
261
+ await this.port.withIndexLock(async () => {
262
+ const idx = await this.port.readIndex();
263
+ addToDepBlocked(idx, featureId, unresolved);
264
+ idx.updated_at = nowIso();
265
+ await this.port.writeIndex(idx);
266
+ });
267
+ throw {
268
+ normalizedResponse: fail(ERROR_CODES.DEPENDENCY_UNRESOLVED, 'Plan deferred: dependencies not yet merged', {
269
+ feature_id: featureId,
270
+ depends_on_unresolved: unresolved,
271
+ retryable: true,
272
+ requires_human: false
273
+ })
274
+ };
275
+ }
276
+ }
277
+
230
278
  async planSubmit(
231
279
  featureId: string | null,
232
280
  plan: AnyRecord | null,
@@ -255,6 +303,9 @@ export class PlanService {
255
303
  await this.validatePlanSchema(plan);
256
304
  await this.assertPlanLocksHeld(featureId, plan);
257
305
 
306
+ // N4: Dependency-aware scheduling — check depends_on before accepting plan
307
+ await this.checkDependencies(featureId);
308
+
258
309
  const existing = await readJson(this.port.planPath(featureId), null);
259
310
  this.validatePlanRevisionRules(existing, plan, expectedVersion);
260
311