swarm-engine 1.0.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 (431) hide show
  1. package/AGENTS.md +72 -0
  2. package/CLAUDE.md +89 -0
  3. package/LICENSE +21 -0
  4. package/README.md +235 -0
  5. package/agents/accessibility-reviewer.md +118 -0
  6. package/agents/api-contract-reviewer.md +99 -0
  7. package/agents/concurrency-reviewer.md +111 -0
  8. package/agents/data-integrity-reviewer.md +103 -0
  9. package/agents/debugger.md +99 -0
  10. package/agents/dependency-reviewer.md +115 -0
  11. package/agents/devils-advocate.md +94 -0
  12. package/agents/documentation-reviewer.md +114 -0
  13. package/agents/documenter.md +78 -0
  14. package/agents/error-handling-reviewer.md +113 -0
  15. package/agents/grounding.md +99 -0
  16. package/agents/guardian.md +87 -0
  17. package/agents/implementer.md +141 -0
  18. package/agents/integrator.md +95 -0
  19. package/agents/judge.md +79 -0
  20. package/agents/librarian.md +90 -0
  21. package/agents/orchestrator.md +331 -0
  22. package/agents/performance-reviewer.md +93 -0
  23. package/agents/planner.md +106 -0
  24. package/agents/refactorer.md +92 -0
  25. package/agents/researcher.md +97 -0
  26. package/agents/reviewer.md +117 -0
  27. package/agents/security-reviewer.md +107 -0
  28. package/agents/sentinel.md +92 -0
  29. package/agents/tester.md +93 -0
  30. package/agents/testing-reviewer.md +112 -0
  31. package/commands/diff-review.md +64 -0
  32. package/commands/fix-pr.md +78 -0
  33. package/commands/red-team.md +82 -0
  34. package/commands/research.md +59 -0
  35. package/commands/resume.md +80 -0
  36. package/commands/review-cycle.md +123 -0
  37. package/commands/swarm-setup.md +28 -0
  38. package/commands/swarm.md +126 -0
  39. package/commands/tdd.md +91 -0
  40. package/dist/cli/bin.d.ts +3 -0
  41. package/dist/cli/bin.d.ts.map +1 -0
  42. package/dist/cli/bin.js +3 -0
  43. package/dist/cli/bin.js.map +1 -0
  44. package/dist/cli/commands/acp.d.ts +3 -0
  45. package/dist/cli/commands/acp.d.ts.map +1 -0
  46. package/dist/cli/commands/acp.js +29 -0
  47. package/dist/cli/commands/acp.js.map +1 -0
  48. package/dist/cli/commands/agents.d.ts +3 -0
  49. package/dist/cli/commands/agents.d.ts.map +1 -0
  50. package/dist/cli/commands/agents.js +344 -0
  51. package/dist/cli/commands/agents.js.map +1 -0
  52. package/dist/cli/commands/backends.d.ts +3 -0
  53. package/dist/cli/commands/backends.d.ts.map +1 -0
  54. package/dist/cli/commands/backends.js +22 -0
  55. package/dist/cli/commands/backends.js.map +1 -0
  56. package/dist/cli/commands/completions.d.ts +3 -0
  57. package/dist/cli/commands/completions.d.ts.map +1 -0
  58. package/dist/cli/commands/completions.js +85 -0
  59. package/dist/cli/commands/completions.js.map +1 -0
  60. package/dist/cli/commands/compound.d.ts +3 -0
  61. package/dist/cli/commands/compound.d.ts.map +1 -0
  62. package/dist/cli/commands/compound.js +119 -0
  63. package/dist/cli/commands/compound.js.map +1 -0
  64. package/dist/cli/commands/configure.d.ts +3 -0
  65. package/dist/cli/commands/configure.d.ts.map +1 -0
  66. package/dist/cli/commands/configure.js +151 -0
  67. package/dist/cli/commands/configure.js.map +1 -0
  68. package/dist/cli/commands/convert.d.ts +15 -0
  69. package/dist/cli/commands/convert.d.ts.map +1 -0
  70. package/dist/cli/commands/convert.js +218 -0
  71. package/dist/cli/commands/convert.js.map +1 -0
  72. package/dist/cli/commands/doctor.d.ts +3 -0
  73. package/dist/cli/commands/doctor.d.ts.map +1 -0
  74. package/dist/cli/commands/doctor.js +96 -0
  75. package/dist/cli/commands/doctor.js.map +1 -0
  76. package/dist/cli/commands/init.d.ts +3 -0
  77. package/dist/cli/commands/init.d.ts.map +1 -0
  78. package/dist/cli/commands/init.js +154 -0
  79. package/dist/cli/commands/init.js.map +1 -0
  80. package/dist/cli/commands/learn.d.ts +3 -0
  81. package/dist/cli/commands/learn.d.ts.map +1 -0
  82. package/dist/cli/commands/learn.js +163 -0
  83. package/dist/cli/commands/learn.js.map +1 -0
  84. package/dist/cli/commands/mcp.d.ts +3 -0
  85. package/dist/cli/commands/mcp.d.ts.map +1 -0
  86. package/dist/cli/commands/mcp.js +89 -0
  87. package/dist/cli/commands/mcp.js.map +1 -0
  88. package/dist/cli/commands/memory.d.ts +3 -0
  89. package/dist/cli/commands/memory.d.ts.map +1 -0
  90. package/dist/cli/commands/memory.js +134 -0
  91. package/dist/cli/commands/memory.js.map +1 -0
  92. package/dist/cli/commands/orchestrate.d.ts +3 -0
  93. package/dist/cli/commands/orchestrate.d.ts.map +1 -0
  94. package/dist/cli/commands/orchestrate.js +237 -0
  95. package/dist/cli/commands/orchestrate.js.map +1 -0
  96. package/dist/cli/commands/patterns.d.ts +3 -0
  97. package/dist/cli/commands/patterns.d.ts.map +1 -0
  98. package/dist/cli/commands/patterns.js +25 -0
  99. package/dist/cli/commands/patterns.js.map +1 -0
  100. package/dist/cli/commands/plan.d.ts +3 -0
  101. package/dist/cli/commands/plan.d.ts.map +1 -0
  102. package/dist/cli/commands/plan.js +77 -0
  103. package/dist/cli/commands/plan.js.map +1 -0
  104. package/dist/cli/commands/plugin.d.ts +3 -0
  105. package/dist/cli/commands/plugin.d.ts.map +1 -0
  106. package/dist/cli/commands/plugin.js +124 -0
  107. package/dist/cli/commands/plugin.js.map +1 -0
  108. package/dist/cli/commands/resume.d.ts +3 -0
  109. package/dist/cli/commands/resume.d.ts.map +1 -0
  110. package/dist/cli/commands/resume.js +55 -0
  111. package/dist/cli/commands/resume.js.map +1 -0
  112. package/dist/cli/commands/run.d.ts +3 -0
  113. package/dist/cli/commands/run.d.ts.map +1 -0
  114. package/dist/cli/commands/run.js +78 -0
  115. package/dist/cli/commands/run.js.map +1 -0
  116. package/dist/cli/commands/share.d.ts +3 -0
  117. package/dist/cli/commands/share.d.ts.map +1 -0
  118. package/dist/cli/commands/share.js +34 -0
  119. package/dist/cli/commands/share.js.map +1 -0
  120. package/dist/cli/commands/status.d.ts +3 -0
  121. package/dist/cli/commands/status.d.ts.map +1 -0
  122. package/dist/cli/commands/status.js +148 -0
  123. package/dist/cli/commands/status.js.map +1 -0
  124. package/dist/cli/commands/template.d.ts +3 -0
  125. package/dist/cli/commands/template.d.ts.map +1 -0
  126. package/dist/cli/commands/template.js +213 -0
  127. package/dist/cli/commands/template.js.map +1 -0
  128. package/dist/cli/commands/vault.d.ts +3 -0
  129. package/dist/cli/commands/vault.d.ts.map +1 -0
  130. package/dist/cli/commands/vault.js +402 -0
  131. package/dist/cli/commands/vault.js.map +1 -0
  132. package/dist/cli/commands/verify.d.ts +3 -0
  133. package/dist/cli/commands/verify.d.ts.map +1 -0
  134. package/dist/cli/commands/verify.js +38 -0
  135. package/dist/cli/commands/verify.js.map +1 -0
  136. package/dist/cli/commands/version.d.ts +3 -0
  137. package/dist/cli/commands/version.d.ts.map +1 -0
  138. package/dist/cli/commands/version.js +19 -0
  139. package/dist/cli/commands/version.js.map +1 -0
  140. package/dist/cli/commands/watch.d.ts +3 -0
  141. package/dist/cli/commands/watch.d.ts.map +1 -0
  142. package/dist/cli/commands/watch.js +179 -0
  143. package/dist/cli/commands/watch.js.map +1 -0
  144. package/dist/cli/index.d.ts +3 -0
  145. package/dist/cli/index.d.ts.map +1 -0
  146. package/dist/cli/index.js +118 -0
  147. package/dist/cli/index.js.map +1 -0
  148. package/dist/core/checkpoint.d.ts +35 -0
  149. package/dist/core/checkpoint.d.ts.map +1 -0
  150. package/dist/core/checkpoint.js +80 -0
  151. package/dist/core/checkpoint.js.map +1 -0
  152. package/dist/core/event-bus.d.ts +41 -0
  153. package/dist/core/event-bus.d.ts.map +1 -0
  154. package/dist/core/event-bus.js +115 -0
  155. package/dist/core/event-bus.js.map +1 -0
  156. package/dist/core/lifecycle.d.ts +30 -0
  157. package/dist/core/lifecycle.d.ts.map +1 -0
  158. package/dist/core/lifecycle.js +72 -0
  159. package/dist/core/lifecycle.js.map +1 -0
  160. package/dist/core/patterns.d.ts +43 -0
  161. package/dist/core/patterns.d.ts.map +1 -0
  162. package/dist/core/patterns.js +372 -0
  163. package/dist/core/patterns.js.map +1 -0
  164. package/dist/core/permissions.d.ts +40 -0
  165. package/dist/core/permissions.d.ts.map +1 -0
  166. package/dist/core/permissions.js +113 -0
  167. package/dist/core/permissions.js.map +1 -0
  168. package/dist/core/registry.d.ts +80 -0
  169. package/dist/core/registry.d.ts.map +1 -0
  170. package/dist/core/registry.js +308 -0
  171. package/dist/core/registry.js.map +1 -0
  172. package/dist/core/snapshots.d.ts +20 -0
  173. package/dist/core/snapshots.d.ts.map +1 -0
  174. package/dist/core/snapshots.js +73 -0
  175. package/dist/core/snapshots.js.map +1 -0
  176. package/dist/core/types.d.ts +168 -0
  177. package/dist/core/types.d.ts.map +1 -0
  178. package/dist/core/types.js +33 -0
  179. package/dist/core/types.js.map +1 -0
  180. package/dist/hooks/cli.d.ts +11 -0
  181. package/dist/hooks/cli.d.ts.map +1 -0
  182. package/dist/hooks/cli.js +32 -0
  183. package/dist/hooks/cli.js.map +1 -0
  184. package/dist/hooks/index.d.ts +23 -0
  185. package/dist/hooks/index.d.ts.map +1 -0
  186. package/dist/hooks/index.js +58 -0
  187. package/dist/hooks/index.js.map +1 -0
  188. package/dist/index.d.ts +82 -0
  189. package/dist/index.d.ts.map +1 -0
  190. package/dist/index.js +49 -0
  191. package/dist/index.js.map +1 -0
  192. package/dist/memory/index.d.ts +105 -0
  193. package/dist/memory/index.d.ts.map +1 -0
  194. package/dist/memory/index.js +298 -0
  195. package/dist/memory/index.js.map +1 -0
  196. package/dist/memory/schema.d.ts +6 -0
  197. package/dist/memory/schema.d.ts.map +1 -0
  198. package/dist/memory/schema.js +71 -0
  199. package/dist/memory/schema.js.map +1 -0
  200. package/dist/plugin/index.d.ts +6 -0
  201. package/dist/plugin/index.d.ts.map +1 -0
  202. package/dist/plugin/index.js +182 -0
  203. package/dist/plugin/index.js.map +1 -0
  204. package/dist/runtime/acp.d.ts +41 -0
  205. package/dist/runtime/acp.d.ts.map +1 -0
  206. package/dist/runtime/acp.js +137 -0
  207. package/dist/runtime/acp.js.map +1 -0
  208. package/dist/runtime/adaptive.d.ts +34 -0
  209. package/dist/runtime/adaptive.d.ts.map +1 -0
  210. package/dist/runtime/adaptive.js +229 -0
  211. package/dist/runtime/adaptive.js.map +1 -0
  212. package/dist/runtime/autonomy.d.ts +21 -0
  213. package/dist/runtime/autonomy.d.ts.map +1 -0
  214. package/dist/runtime/autonomy.js +74 -0
  215. package/dist/runtime/autonomy.js.map +1 -0
  216. package/dist/runtime/backends/claude.d.ts +9 -0
  217. package/dist/runtime/backends/claude.d.ts.map +1 -0
  218. package/dist/runtime/backends/claude.js +134 -0
  219. package/dist/runtime/backends/claude.js.map +1 -0
  220. package/dist/runtime/backends/codex.d.ts +9 -0
  221. package/dist/runtime/backends/codex.d.ts.map +1 -0
  222. package/dist/runtime/backends/codex.js +132 -0
  223. package/dist/runtime/backends/codex.js.map +1 -0
  224. package/dist/runtime/backends/gemini.d.ts +9 -0
  225. package/dist/runtime/backends/gemini.d.ts.map +1 -0
  226. package/dist/runtime/backends/gemini.js +103 -0
  227. package/dist/runtime/backends/gemini.js.map +1 -0
  228. package/dist/runtime/backends/index.d.ts +17 -0
  229. package/dist/runtime/backends/index.d.ts.map +1 -0
  230. package/dist/runtime/backends/index.js +39 -0
  231. package/dist/runtime/backends/index.js.map +1 -0
  232. package/dist/runtime/backends/mock.d.ts +21 -0
  233. package/dist/runtime/backends/mock.d.ts.map +1 -0
  234. package/dist/runtime/backends/mock.js +46 -0
  235. package/dist/runtime/backends/mock.js.map +1 -0
  236. package/dist/runtime/backends/types.d.ts +34 -0
  237. package/dist/runtime/backends/types.d.ts.map +1 -0
  238. package/dist/runtime/backends/types.js +2 -0
  239. package/dist/runtime/backends/types.js.map +1 -0
  240. package/dist/runtime/backends/vercel-ai.d.ts +14 -0
  241. package/dist/runtime/backends/vercel-ai.d.ts.map +1 -0
  242. package/dist/runtime/backends/vercel-ai.js +137 -0
  243. package/dist/runtime/backends/vercel-ai.js.map +1 -0
  244. package/dist/runtime/cache-optimizer.d.ts +37 -0
  245. package/dist/runtime/cache-optimizer.d.ts.map +1 -0
  246. package/dist/runtime/cache-optimizer.js +54 -0
  247. package/dist/runtime/cache-optimizer.js.map +1 -0
  248. package/dist/runtime/cascade.d.ts +26 -0
  249. package/dist/runtime/cascade.d.ts.map +1 -0
  250. package/dist/runtime/cascade.js +54 -0
  251. package/dist/runtime/cascade.js.map +1 -0
  252. package/dist/runtime/chunker.d.ts +36 -0
  253. package/dist/runtime/chunker.d.ts.map +1 -0
  254. package/dist/runtime/chunker.js +210 -0
  255. package/dist/runtime/chunker.js.map +1 -0
  256. package/dist/runtime/compaction.d.ts +22 -0
  257. package/dist/runtime/compaction.d.ts.map +1 -0
  258. package/dist/runtime/compaction.js +36 -0
  259. package/dist/runtime/compaction.js.map +1 -0
  260. package/dist/runtime/compounder.d.ts +66 -0
  261. package/dist/runtime/compounder.d.ts.map +1 -0
  262. package/dist/runtime/compounder.js +276 -0
  263. package/dist/runtime/compounder.js.map +1 -0
  264. package/dist/runtime/cost-model.d.ts +24 -0
  265. package/dist/runtime/cost-model.d.ts.map +1 -0
  266. package/dist/runtime/cost-model.js +120 -0
  267. package/dist/runtime/cost-model.js.map +1 -0
  268. package/dist/runtime/distiller.d.ts +21 -0
  269. package/dist/runtime/distiller.d.ts.map +1 -0
  270. package/dist/runtime/distiller.js +70 -0
  271. package/dist/runtime/distiller.js.map +1 -0
  272. package/dist/runtime/engine.d.ts +123 -0
  273. package/dist/runtime/engine.d.ts.map +1 -0
  274. package/dist/runtime/engine.js +969 -0
  275. package/dist/runtime/engine.js.map +1 -0
  276. package/dist/runtime/executor.d.ts +71 -0
  277. package/dist/runtime/executor.d.ts.map +1 -0
  278. package/dist/runtime/executor.js +283 -0
  279. package/dist/runtime/executor.js.map +1 -0
  280. package/dist/runtime/heuristics.d.ts +33 -0
  281. package/dist/runtime/heuristics.d.ts.map +1 -0
  282. package/dist/runtime/heuristics.js +188 -0
  283. package/dist/runtime/heuristics.js.map +1 -0
  284. package/dist/runtime/living-spec.d.ts +34 -0
  285. package/dist/runtime/living-spec.d.ts.map +1 -0
  286. package/dist/runtime/living-spec.js +91 -0
  287. package/dist/runtime/living-spec.js.map +1 -0
  288. package/dist/runtime/lsp.d.ts +50 -0
  289. package/dist/runtime/lsp.d.ts.map +1 -0
  290. package/dist/runtime/lsp.js +110 -0
  291. package/dist/runtime/lsp.js.map +1 -0
  292. package/dist/runtime/mcp.d.ts +27 -0
  293. package/dist/runtime/mcp.d.ts.map +1 -0
  294. package/dist/runtime/mcp.js +154 -0
  295. package/dist/runtime/mcp.js.map +1 -0
  296. package/dist/runtime/model-router.d.ts +22 -0
  297. package/dist/runtime/model-router.d.ts.map +1 -0
  298. package/dist/runtime/model-router.js +94 -0
  299. package/dist/runtime/model-router.js.map +1 -0
  300. package/dist/runtime/panes.d.ts +76 -0
  301. package/dist/runtime/panes.d.ts.map +1 -0
  302. package/dist/runtime/panes.js +279 -0
  303. package/dist/runtime/panes.js.map +1 -0
  304. package/dist/runtime/plan-search.d.ts +41 -0
  305. package/dist/runtime/plan-search.d.ts.map +1 -0
  306. package/dist/runtime/plan-search.js +140 -0
  307. package/dist/runtime/plan-search.js.map +1 -0
  308. package/dist/runtime/plugins.d.ts +59 -0
  309. package/dist/runtime/plugins.d.ts.map +1 -0
  310. package/dist/runtime/plugins.js +121 -0
  311. package/dist/runtime/plugins.js.map +1 -0
  312. package/dist/runtime/reflexion.d.ts +22 -0
  313. package/dist/runtime/reflexion.d.ts.map +1 -0
  314. package/dist/runtime/reflexion.js +85 -0
  315. package/dist/runtime/reflexion.js.map +1 -0
  316. package/dist/runtime/review-schema.d.ts +75 -0
  317. package/dist/runtime/review-schema.d.ts.map +1 -0
  318. package/dist/runtime/review-schema.js +223 -0
  319. package/dist/runtime/review-schema.js.map +1 -0
  320. package/dist/runtime/rewriter.d.ts +8 -0
  321. package/dist/runtime/rewriter.d.ts.map +1 -0
  322. package/dist/runtime/rewriter.js +81 -0
  323. package/dist/runtime/rewriter.js.map +1 -0
  324. package/dist/runtime/sharing.d.ts +15 -0
  325. package/dist/runtime/sharing.d.ts.map +1 -0
  326. package/dist/runtime/sharing.js +48 -0
  327. package/dist/runtime/sharing.js.map +1 -0
  328. package/dist/runtime/stats.d.ts +53 -0
  329. package/dist/runtime/stats.d.ts.map +1 -0
  330. package/dist/runtime/stats.js +160 -0
  331. package/dist/runtime/stats.js.map +1 -0
  332. package/dist/runtime/templates.d.ts +77 -0
  333. package/dist/runtime/templates.d.ts.map +1 -0
  334. package/dist/runtime/templates.js +221 -0
  335. package/dist/runtime/templates.js.map +1 -0
  336. package/dist/runtime/traces.d.ts +60 -0
  337. package/dist/runtime/traces.d.ts.map +1 -0
  338. package/dist/runtime/traces.js +166 -0
  339. package/dist/runtime/traces.js.map +1 -0
  340. package/dist/runtime/verifier.d.ts +54 -0
  341. package/dist/runtime/verifier.d.ts.map +1 -0
  342. package/dist/runtime/verifier.js +172 -0
  343. package/dist/runtime/verifier.js.map +1 -0
  344. package/dist/runtime/worktree.d.ts +24 -0
  345. package/dist/runtime/worktree.d.ts.map +1 -0
  346. package/dist/runtime/worktree.js +82 -0
  347. package/dist/runtime/worktree.js.map +1 -0
  348. package/dist/tui/dashboard.d.ts +65 -0
  349. package/dist/tui/dashboard.d.ts.map +1 -0
  350. package/dist/tui/dashboard.js +496 -0
  351. package/dist/tui/dashboard.js.map +1 -0
  352. package/dist/tui/progress.d.ts +32 -0
  353. package/dist/tui/progress.d.ts.map +1 -0
  354. package/dist/tui/progress.js +257 -0
  355. package/dist/tui/progress.js.map +1 -0
  356. package/dist/tui/renderer.d.ts +72 -0
  357. package/dist/tui/renderer.d.ts.map +1 -0
  358. package/dist/tui/renderer.js +205 -0
  359. package/dist/tui/renderer.js.map +1 -0
  360. package/dist/utils/compact-format.d.ts +35 -0
  361. package/dist/utils/compact-format.d.ts.map +1 -0
  362. package/dist/utils/compact-format.js +106 -0
  363. package/dist/utils/compact-format.js.map +1 -0
  364. package/dist/utils/config.d.ts +73 -0
  365. package/dist/utils/config.d.ts.map +1 -0
  366. package/dist/utils/config.js +70 -0
  367. package/dist/utils/config.js.map +1 -0
  368. package/dist/utils/env.d.ts +6 -0
  369. package/dist/utils/env.d.ts.map +1 -0
  370. package/dist/utils/env.js +28 -0
  371. package/dist/utils/env.js.map +1 -0
  372. package/dist/utils/errors.d.ts +14 -0
  373. package/dist/utils/errors.d.ts.map +1 -0
  374. package/dist/utils/errors.js +120 -0
  375. package/dist/utils/errors.js.map +1 -0
  376. package/dist/utils/logger.d.ts +14 -0
  377. package/dist/utils/logger.d.ts.map +1 -0
  378. package/dist/utils/logger.js +56 -0
  379. package/dist/utils/logger.js.map +1 -0
  380. package/dist/utils/output.d.ts +10 -0
  381. package/dist/utils/output.d.ts.map +1 -0
  382. package/dist/utils/output.js +26 -0
  383. package/dist/utils/output.js.map +1 -0
  384. package/dist/utils/paths.d.ts +7 -0
  385. package/dist/utils/paths.d.ts.map +1 -0
  386. package/dist/utils/paths.js +16 -0
  387. package/dist/utils/paths.js.map +1 -0
  388. package/dist/utils/project-config.d.ts +18 -0
  389. package/dist/utils/project-config.d.ts.map +1 -0
  390. package/dist/utils/project-config.js +46 -0
  391. package/dist/utils/project-config.js.map +1 -0
  392. package/dist/utils/redact.d.ts +5 -0
  393. package/dist/utils/redact.d.ts.map +1 -0
  394. package/dist/utils/redact.js +25 -0
  395. package/dist/utils/redact.js.map +1 -0
  396. package/dist/utils/schemas.d.ts +109 -0
  397. package/dist/utils/schemas.d.ts.map +1 -0
  398. package/dist/utils/schemas.js +63 -0
  399. package/dist/utils/schemas.js.map +1 -0
  400. package/dist/utils/terminal.d.ts +33 -0
  401. package/dist/utils/terminal.d.ts.map +1 -0
  402. package/dist/utils/terminal.js +82 -0
  403. package/dist/utils/terminal.js.map +1 -0
  404. package/dist/utils/tokens.d.ts +9 -0
  405. package/dist/utils/tokens.d.ts.map +1 -0
  406. package/dist/utils/tokens.js +11 -0
  407. package/dist/utils/tokens.js.map +1 -0
  408. package/package.json +71 -0
  409. package/skills/design-system/SKILL.md +195 -0
  410. package/skills/orchestration-patterns/SKILL.md +81 -0
  411. package/skills/orchestration-patterns/examples/example-workflows.md +290 -0
  412. package/skills/orchestration-patterns/references/adversarial.md +51 -0
  413. package/skills/orchestration-patterns/references/batch.md +63 -0
  414. package/skills/orchestration-patterns/references/chaos.md +43 -0
  415. package/skills/orchestration-patterns/references/competitive.md +84 -0
  416. package/skills/orchestration-patterns/references/debate.md +44 -0
  417. package/skills/orchestration-patterns/references/emergence.md +50 -0
  418. package/skills/orchestration-patterns/references/fan-out-fan-in.md +74 -0
  419. package/skills/orchestration-patterns/references/iterative.md +99 -0
  420. package/skills/orchestration-patterns/references/pipeline.md +72 -0
  421. package/skills/swarm-output-style/SKILL.md +85 -0
  422. package/templates/add-endpoint.yml +44 -0
  423. package/templates/add-feature.yml +30 -0
  424. package/templates/agent-template.md +73 -0
  425. package/templates/bug-fix.yml +31 -0
  426. package/templates/explore.yml +21 -0
  427. package/templates/fix-pr.yml +30 -0
  428. package/templates/migration.yml +36 -0
  429. package/templates/refactor.yml +35 -0
  430. package/templates/security-audit.yml +27 -0
  431. package/templates/workflow-template.md +63 -0
@@ -0,0 +1,969 @@
1
+ import { emptyUsageStats, mergeUsageStats, generateId, } from '../core/types.js';
2
+ import { AgentExecutor } from './executor.js';
3
+ import { saveCheckpoint, loadCheckpoint } from '../core/checkpoint.js';
4
+ import { PatternRegistry } from '../core/patterns.js';
5
+ import { WorktreeManager } from './worktree.js';
6
+ import { CompactionManager } from './compaction.js';
7
+ import { ContextDistiller } from './distiller.js';
8
+ import { Verifier } from './verifier.js';
9
+ import { rewritePlan } from './rewriter.js';
10
+ import { CostModel } from './cost-model.js';
11
+ import { PlanSearcher } from './plan-search.js';
12
+ import { StatsCollector } from './stats.js';
13
+ import { AdaptiveReplanner } from './adaptive.js';
14
+ import { ReflectionEngine } from './reflexion.js';
15
+ import { TraceStore } from './traces.js';
16
+ import { HeuristicStore } from './heuristics.js';
17
+ import { KnowledgeCompounder } from './compounder.js';
18
+ import { ModelRouter } from './model-router.js';
19
+ import { AutonomyTracker } from './autonomy.js';
20
+ import { ContinuousVerifier } from './verifier.js';
21
+ import { optimizeForCache, estimateCacheSavings } from './cache-optimizer.js';
22
+ import { classifyTaskComplexity, selectStartingTier } from './cascade.js';
23
+ import { createLivingSpec, updateSpecFromPhase, formatLivingSpec } from './living-spec.js';
24
+ import { estimateTokens } from '../utils/tokens.js';
25
+ import { redactSecrets } from '../utils/redact.js';
26
+ import { join } from 'path';
27
+ import { existsSync, mkdirSync, writeFileSync, unlinkSync } from 'fs';
28
+ import { randomUUID } from 'crypto';
29
+ /**
30
+ * The Swarm Orchestration Engine.
31
+ *
32
+ * Manages the lifecycle of orchestrations — multi-phase workflows
33
+ * that dispatch parallel agents and manage dependencies between phases.
34
+ */
35
+ export class SwarmEngine {
36
+ registry;
37
+ bus;
38
+ executor;
39
+ log;
40
+ patterns;
41
+ options;
42
+ orchestrations = new Map();
43
+ phaseOutputs = new Map();
44
+ abortController = new AbortController();
45
+ worktreeManager = null;
46
+ compaction;
47
+ distiller = null;
48
+ verifier;
49
+ costModel;
50
+ replanner;
51
+ reflectionEngine;
52
+ reflections = [];
53
+ traceStore = null;
54
+ heuristicStore = null;
55
+ stats;
56
+ modelRouter = null;
57
+ autonomyTracker = null;
58
+ compounder = null;
59
+ signalHandlers = [];
60
+ sharedContextFiles = [];
61
+ livingSpec = null;
62
+ constructor(options) {
63
+ this.options = options;
64
+ this.registry = options.registry;
65
+ this.bus = options.bus;
66
+ this.executor = new AgentExecutor({
67
+ bus: this.bus,
68
+ logger: options.logger,
69
+ cwd: options.cwd,
70
+ mock: options.mock ?? false,
71
+ permissionMode: options.permissionMode ?? 'default',
72
+ defaultBackend: options.defaultBackend,
73
+ permissionProfile: options.permissionProfile,
74
+ snapshotsEnabled: options.snapshotsEnabled,
75
+ doomLoopDetection: options.doomLoopDetection,
76
+ paneManager: options.paneManager,
77
+ });
78
+ this.log = options.logger.child('engine');
79
+ this.patterns = options.patterns ?? new PatternRegistry();
80
+ this.compaction = new CompactionManager(options.compactionEnabled === false ? { enabled: false } : undefined);
81
+ this.distiller = options.distillation !== false ? new ContextDistiller() : null;
82
+ this.verifier = new Verifier(options.cwd ?? process.cwd());
83
+ this.stats = new StatsCollector();
84
+ this.stats.attachToEventBus(this.bus, undefined);
85
+ this.costModel = new CostModel(this.stats);
86
+ this.reflectionEngine = new ReflectionEngine();
87
+ try {
88
+ this.traceStore = new TraceStore();
89
+ }
90
+ catch (e) {
91
+ this.log.warn('TraceStore init failed', { error: e instanceof Error ? e.message : e });
92
+ }
93
+ this.replanner = new AdaptiveReplanner(options.logger, this.traceStore ?? undefined);
94
+ try {
95
+ this.heuristicStore = new HeuristicStore();
96
+ }
97
+ catch (e) {
98
+ this.log.warn('HeuristicStore init failed', { error: e instanceof Error ? e.message : e });
99
+ }
100
+ try {
101
+ this.modelRouter = new ModelRouter();
102
+ }
103
+ catch (e) {
104
+ this.log.warn('ModelRouter init failed', { error: e instanceof Error ? e.message : e });
105
+ }
106
+ try {
107
+ this.autonomyTracker = new AutonomyTracker();
108
+ }
109
+ catch (e) {
110
+ this.log.warn('AutonomyTracker init failed', { error: e instanceof Error ? e.message : e });
111
+ }
112
+ try {
113
+ this.compounder = new KnowledgeCompounder();
114
+ }
115
+ catch (e) {
116
+ this.log.warn('KnowledgeCompounder init failed', { error: e instanceof Error ? e.message : e });
117
+ }
118
+ if (options.worktreeEnabled) {
119
+ try {
120
+ this.worktreeManager = new WorktreeManager(options.cwd);
121
+ }
122
+ catch { /* not a git repo */ }
123
+ }
124
+ if (options.pluginLoader) {
125
+ options.pluginLoader.wireHooks(this.bus);
126
+ }
127
+ this.setupSignalHandlers();
128
+ }
129
+ /**
130
+ * Execute an orchestration from config.
131
+ */
132
+ async execute(config) {
133
+ // Re-use existing instance if present (e.g., when resuming from checkpoint)
134
+ const orchestration = this.orchestrations.get(config.id) ?? this.createInstance(config);
135
+ this.orchestrations.set(config.id, orchestration);
136
+ this.log.info(`Starting orchestration: ${config.name}`, {
137
+ pattern: config.pattern,
138
+ phases: config.phases.length,
139
+ });
140
+ this.bus.emit('orchestration:start', {
141
+ id: config.id,
142
+ name: config.name,
143
+ pattern: config.pattern,
144
+ phaseCount: config.phases.length,
145
+ }, 'engine');
146
+ orchestration.status = 'running';
147
+ orchestration.startedAt = new Date();
148
+ this.phaseOutputs = new Map();
149
+ this.reflections = [];
150
+ this.sharedContextFiles = [];
151
+ this.abortController = new AbortController();
152
+ this.livingSpec = createLivingSpec(config.description);
153
+ // Start continuous verification
154
+ let continuousVerifier = null;
155
+ if (this.verifier) {
156
+ continuousVerifier = new ContinuousVerifier(this.verifier, this.bus);
157
+ continuousVerifier.start();
158
+ }
159
+ try {
160
+ // Execute phases using work-queue approach (handles DAGs correctly)
161
+ // If resuming, seed completed phases so the DAG executor skips them
162
+ const completed = new Set();
163
+ for (const phase of orchestration.phases) {
164
+ if (phase.status === 'completed') {
165
+ completed.add(phase.config.name);
166
+ }
167
+ }
168
+ while (completed.size < orchestration.phases.length) {
169
+ // Check if abort was requested
170
+ if (this.abortController.signal.aborted) {
171
+ orchestration.status = 'cancelled';
172
+ break;
173
+ }
174
+ // Find all runnable phases (dependencies met, not yet completed)
175
+ const runnable = orchestration.phases.filter(p => {
176
+ if (completed.has(p.config.name))
177
+ return false;
178
+ if (p.status === 'failed')
179
+ return false;
180
+ const deps = p.config.dependsOn ?? [];
181
+ return deps.every(d => completed.has(d));
182
+ });
183
+ if (runnable.length === 0) {
184
+ // No runnable phases — either all done or deadlocked
185
+ const incomplete = orchestration.phases.filter(p => !completed.has(p.config.name) && p.status !== 'failed');
186
+ if (incomplete.length > 0) {
187
+ // Deadlock — blocked phases with unmet dependencies
188
+ for (const p of incomplete) {
189
+ p.status = 'blocked';
190
+ }
191
+ orchestration.status = 'failed';
192
+ this.log.error('Orchestration deadlocked: blocked phases with unmet dependencies', {
193
+ blocked: incomplete.map(p => p.config.name),
194
+ });
195
+ }
196
+ break;
197
+ }
198
+ // Execute runnable phases (could be parallel if multiple are ready)
199
+ for (const phase of runnable) {
200
+ orchestration.currentPhase = orchestration.phases.indexOf(phase);
201
+ // Check for approval gate
202
+ if (phase.config.requiresApproval) {
203
+ this.log.info(`Phase requires approval: ${phase.config.name}`);
204
+ this.bus.emit('orchestration:paused', {
205
+ orchestrationId: orchestration.config.id,
206
+ phase: phase.config.name,
207
+ agentCount: phase.config.agents.length,
208
+ }, 'engine');
209
+ // In interactive mode, wait for approval
210
+ if (!this.options.nonInteractive) {
211
+ const approved = await this.requestApproval(phase.config.name, phase.config.agents);
212
+ if (!approved) {
213
+ phase.status = 'skipped';
214
+ this.log.info(`Phase skipped (not approved): ${phase.config.name}`);
215
+ completed.add(phase.config.name);
216
+ continue;
217
+ }
218
+ }
219
+ }
220
+ const outputs = await this.executePhase(orchestration, phase);
221
+ this.phaseOutputs.set(phase.config.name, outputs);
222
+ if (phase.status === 'completed') {
223
+ completed.add(phase.config.name);
224
+ }
225
+ else if (phase.status === 'failed') {
226
+ orchestration.status = 'failed';
227
+ break;
228
+ }
229
+ }
230
+ if (orchestration.status === 'failed')
231
+ break;
232
+ // Check cost budget after each batch of phases
233
+ if (orchestration.config.costBudget) {
234
+ const spent = orchestration.phases
235
+ .filter(p => p.status === 'completed')
236
+ .reduce((sum, p) => sum + p.usage.costUsd, 0);
237
+ if (spent >= orchestration.config.costBudget) {
238
+ orchestration.status = 'failed';
239
+ this.log.warn(`Cost budget exceeded: $${spent.toFixed(2)} >= $${orchestration.config.costBudget}`, {
240
+ spent, budget: orchestration.config.costBudget,
241
+ });
242
+ this.bus.emit('system:warning', {
243
+ reason: 'budget-exceeded',
244
+ id: orchestration.config.id,
245
+ spent,
246
+ budget: orchestration.config.costBudget,
247
+ }, 'engine');
248
+ break;
249
+ }
250
+ }
251
+ }
252
+ if (orchestration.status !== 'failed') {
253
+ orchestration.status = 'completed';
254
+ }
255
+ }
256
+ catch (error) {
257
+ orchestration.status = 'failed';
258
+ this.log.error(`Orchestration failed: ${config.name}`, {
259
+ error: error instanceof Error ? error.message : String(error),
260
+ });
261
+ }
262
+ orchestration.completedAt = new Date();
263
+ continuousVerifier?.stop();
264
+ // Clean up shared context files
265
+ for (const f of this.sharedContextFiles) {
266
+ try {
267
+ unlinkSync(f);
268
+ }
269
+ catch { }
270
+ }
271
+ this.sharedContextFiles = [];
272
+ // Build phase data once for all consumers (avoids 4x redundant mapping)
273
+ const phaseData = orchestration.phases.map(p => ({
274
+ name: p.config.name,
275
+ status: p.status,
276
+ agentCount: p.agents.length,
277
+ tokens: p.usage.totalTokens,
278
+ durationMs: p.usage.durationMs,
279
+ confidence: p.agents[0]?.result?.confidence ?? 'unknown',
280
+ }));
281
+ const traceData = {
282
+ orchestrationId: config.id,
283
+ task: config.description,
284
+ pattern: config.pattern,
285
+ status: orchestration.status,
286
+ totalTokens: orchestration.usage.totalTokens,
287
+ costUsd: orchestration.usage.costUsd,
288
+ durationMs: orchestration.usage.durationMs,
289
+ phaseCount: orchestration.phases.length,
290
+ agentCount: orchestration.phases.reduce((n, p) => n + p.agents.length, 0),
291
+ phases: phaseData,
292
+ reflections: this.reflections.map(r => redactSecrets(r)),
293
+ };
294
+ // Store execution trace for learning
295
+ if (this.traceStore) {
296
+ try {
297
+ this.traceStore.store(traceData);
298
+ }
299
+ catch { /* Don't fail orchestration if trace storage fails */ }
300
+ // Extract heuristics from the trace for future learning
301
+ if (this.heuristicStore) {
302
+ try {
303
+ this.heuristicStore.extractFromTrace(traceData);
304
+ }
305
+ catch { /* Don't fail orchestration if heuristic extraction fails */ }
306
+ }
307
+ // Auto-compound knowledge from completed orchestrations
308
+ if (orchestration.status === 'completed' && this.compounder) {
309
+ try {
310
+ const doc = this.compounder.extractFromTrace({ ...traceData, status: 'completed' }, this.reflections);
311
+ if (doc)
312
+ this.compounder.store(doc);
313
+ }
314
+ catch { /* Don't fail orchestration if compounding fails */ }
315
+ }
316
+ // Auto-capture outcomes to memory
317
+ try {
318
+ const { traceToMemoryEntries } = await import('./traces.js');
319
+ const memEntries = traceToMemoryEntries(traceData);
320
+ // Store in memory if SwarmMemory is available
321
+ let memory;
322
+ try {
323
+ const { SwarmMemory } = await import('../memory/index.js');
324
+ memory = new SwarmMemory();
325
+ for (const entry of memEntries) {
326
+ memory.store({ type: entry.type, title: entry.title, content: entry.content });
327
+ }
328
+ }
329
+ catch { /* Memory not available */ }
330
+ finally {
331
+ try {
332
+ memory?.close();
333
+ }
334
+ catch { }
335
+ }
336
+ }
337
+ catch { /* Don't fail orchestration */ }
338
+ }
339
+ // Record model outcomes for routing
340
+ if (this.modelRouter) {
341
+ for (const phase of orchestration.phases) {
342
+ for (const agent of phase.agents) {
343
+ const model = agent.config.model;
344
+ if (!model)
345
+ continue;
346
+ const success = agent.status === 'shutdown' || agent.status === 'idle';
347
+ this.modelRouter.record(model, agent.config.name, success, success ? 1.0 : 0.0);
348
+ }
349
+ }
350
+ }
351
+ // Record autonomy outcome
352
+ if (this.autonomyTracker) {
353
+ const success = orchestration.status === 'completed';
354
+ const intervention = orchestration.phases.some(p => p.config.requiresApproval);
355
+ this.autonomyTracker.record(config.pattern, success, intervention);
356
+ }
357
+ // Compute total usage
358
+ orchestration.usage = orchestration.phases.reduce((total, phase) => mergeUsageStats(total, phase.usage), emptyUsageStats());
359
+ this.bus.emit(orchestration.status === 'completed' ? 'orchestration:complete' : 'orchestration:failed', {
360
+ id: config.id,
361
+ name: config.name,
362
+ status: orchestration.status,
363
+ usage: orchestration.usage,
364
+ durationMs: orchestration.completedAt.getTime() - (orchestration.startedAt?.getTime() ?? 0),
365
+ }, 'engine');
366
+ this.log.info(`Orchestration ${orchestration.status}: ${config.name}`, {
367
+ usage: orchestration.usage,
368
+ });
369
+ // Prune terminal agent instances to free memory
370
+ this.registry.pruneTerminalInstances();
371
+ return orchestration;
372
+ }
373
+ /**
374
+ * Execute a named pattern with a task description.
375
+ */
376
+ async runPattern(patternName, task, options) {
377
+ const pattern = this.patterns.get(patternName);
378
+ if (!pattern) {
379
+ throw new Error(`Unknown pattern: ${patternName}. Available: ${this.patterns.list().map(p => p.name).join(', ')}`);
380
+ }
381
+ // Inject task into all agent prompts
382
+ const config = {
383
+ id: generateId(),
384
+ name: `${patternName}: ${task.slice(0, 50)}`,
385
+ description: task,
386
+ pattern: patternName,
387
+ phases: pattern.phases.map(phase => ({
388
+ ...phase,
389
+ agents: phase.agents.map(a => ({
390
+ ...a,
391
+ prompt: `${task}\n\n${a.prompt ?? ''}`.trim(),
392
+ })),
393
+ })),
394
+ costBudget: options?.costBudget,
395
+ };
396
+ // Substitute pattern parameters into agent prompts
397
+ if (options?.params && pattern.parameters) {
398
+ for (const phase of config.phases) {
399
+ for (const agent of phase.agents) {
400
+ if (agent.prompt) {
401
+ for (const [key, value] of Object.entries(options.params)) {
402
+ // Use string replacement instead of regex to avoid ReDoS from user-controlled keys
403
+ const placeholder = '${' + key + '}';
404
+ agent.prompt = agent.prompt.split(placeholder).join(String(value));
405
+ }
406
+ }
407
+ }
408
+ }
409
+ }
410
+ return this.execute(config);
411
+ }
412
+ /**
413
+ * Generate a serializable execution plan WITHOUT executing anything.
414
+ * Useful for previewing what an orchestration will do before running it.
415
+ */
416
+ plan(patternName, task, options) {
417
+ const pattern = this.patterns.get(patternName);
418
+ if (!pattern) {
419
+ throw new Error(`Unknown pattern: ${patternName}. Available: ${this.patterns.list().map(p => p.name).join(', ')}`);
420
+ }
421
+ // Check for similar past traces to inform planning
422
+ if (this.traceStore) {
423
+ try {
424
+ const similar = this.traceStore.findSimilar(task, 3);
425
+ if (similar.length > 0) {
426
+ let traceContext = '';
427
+ const best = similar.find(t => t.status === 'completed');
428
+ if (best) {
429
+ traceContext = `Past successful orchestration for similar task used pattern "${best.pattern}" with ${best.agentCount} agents (${best.totalTokens} tokens, ${Math.round(best.durationMs / 1000)}s).`;
430
+ }
431
+ const failed = similar.find(t => t.status === 'failed');
432
+ if (failed && failed.reflections.length > 0) {
433
+ traceContext += ` Previous attempt failed. Lessons: ${failed.reflections[0]?.slice(0, 200)}`;
434
+ }
435
+ if (traceContext) {
436
+ this.log.info('Found similar past traces', { context: traceContext.slice(0, 200) });
437
+ }
438
+ }
439
+ }
440
+ catch { /* Don't fail planning if trace lookup fails */ }
441
+ }
442
+ const id = generateId();
443
+ const phases = pattern.phases.map(phase => ({
444
+ name: phase.name,
445
+ parallel: phase.parallel,
446
+ dependsOn: phase.dependsOn,
447
+ requiresApproval: phase.requiresApproval,
448
+ tokenBudget: phase.tokenBudget,
449
+ agents: phase.agents.map(a => {
450
+ const agentConfig = this.registry.getConfig(a.type);
451
+ return {
452
+ name: a.name,
453
+ type: a.type,
454
+ model: a.model ?? agentConfig?.model ?? 'sonnet',
455
+ backend: a.backend ?? agentConfig?.backend,
456
+ prompt: `${task}\n\n${a.prompt ?? agentConfig?.description ?? ''}`.trim(),
457
+ permissionProfile: agentConfig?.permissionProfile,
458
+ worktree: a.worktree,
459
+ };
460
+ }),
461
+ }));
462
+ // Substitute pattern parameters if provided
463
+ if (options?.params && pattern.parameters) {
464
+ for (const phase of phases) {
465
+ for (const agent of phase.agents) {
466
+ for (const [key, value] of Object.entries(options.params)) {
467
+ const placeholder = '${' + key + '}';
468
+ agent.prompt = agent.prompt.split(placeholder).join(String(value));
469
+ }
470
+ }
471
+ }
472
+ }
473
+ const planResult = {
474
+ id,
475
+ name: `${patternName}: ${task.slice(0, 50)}`,
476
+ task,
477
+ pattern: patternName,
478
+ phases,
479
+ costBudget: options?.costBudget,
480
+ createdAt: new Date().toISOString(),
481
+ };
482
+ // Apply plan rewriting rules
483
+ const { plan: rewrittenPlan, rewrites } = rewritePlan(planResult);
484
+ if (rewrites.length > 0) {
485
+ this.log.info('Plan rewritten', { rewrites });
486
+ }
487
+ // Retrieve relevant heuristics and inject into first phase
488
+ if (this.heuristicStore) {
489
+ try {
490
+ const heuristics = this.heuristicStore.retrieve(task);
491
+ if (heuristics.length > 0) {
492
+ const context = this.heuristicStore.formatForContext(heuristics);
493
+ for (const agent of rewrittenPlan.phases[0]?.agents ?? []) {
494
+ agent.prompt = `${context}\n\n${agent.prompt}`;
495
+ }
496
+ this.log.info('Injected heuristics into plan', { count: heuristics.length });
497
+ }
498
+ }
499
+ catch { /* Don't fail planning if heuristic retrieval fails */ }
500
+ }
501
+ // Inject relevant past solutions from knowledge compounder (singleton)
502
+ if (this.compounder) {
503
+ try {
504
+ const solutions = this.compounder.findRelevant(task, 3);
505
+ if (solutions.length > 0) {
506
+ const solutionContext = this.compounder.formatForContext(solutions);
507
+ for (const agent of rewrittenPlan.phases[0]?.agents ?? []) {
508
+ agent.prompt = `${solutionContext}\n\n${agent.prompt}`;
509
+ }
510
+ this.log.info('Injected past solutions into plan', { count: solutions.length });
511
+ }
512
+ }
513
+ catch { /* Don't fail planning if solution retrieval fails */ }
514
+ }
515
+ // Search over candidate plans to find the best one
516
+ const searcher = new PlanSearcher(this.costModel, this.traceStore ?? undefined);
517
+ const candidates = searcher.search(rewrittenPlan, {
518
+ maxCandidates: 3,
519
+ constraints: options?.costBudget ? { maxCostUsd: options.costBudget } : undefined,
520
+ });
521
+ // Use the best candidate
522
+ const bestPlan = candidates[0]?.plan ?? rewrittenPlan;
523
+ // Store search metadata
524
+ bestPlan.estimates = this.costModel.estimate(bestPlan);
525
+ bestPlan.rewrites = rewrites;
526
+ if (candidates.length > 1) {
527
+ bestPlan._alternatives = candidates.slice(1).map(c => ({
528
+ source: c.source,
529
+ costUsd: c.cost.costUsd,
530
+ quality: c.cost.qualityScore,
531
+ }));
532
+ }
533
+ return bestPlan;
534
+ }
535
+ /**
536
+ * Execute a single phase.
537
+ */
538
+ async executePhase(orchestration, phase) {
539
+ phase.status = 'running';
540
+ phase.startedAt = new Date();
541
+ // Evaluate agent dropout before executing
542
+ if (phase.config.agents.length > 1) {
543
+ const dropout = this.replanner.evaluateDropout(orchestration, phase.config);
544
+ if (dropout) {
545
+ this.log.info(`Agent dropout: ${dropout.reason}`);
546
+ phase.config.agents = phase.config.agents.filter(a => dropout.agentsToKeep.includes(a.name));
547
+ this.bus.emit('system:warning', { type: 'agent-dropout', ...dropout }, 'adaptive');
548
+ }
549
+ }
550
+ const maxRetries = phase.config.maxRetries ?? 2;
551
+ this.log.info(`Phase started: ${phase.config.name}`, {
552
+ agents: phase.config.agents.length,
553
+ parallel: phase.config.parallel,
554
+ });
555
+ this.bus.emit('orchestration:phase-start', {
556
+ orchestrationId: orchestration.config.id,
557
+ phase: phase.config.name,
558
+ agentCount: phase.config.agents.length,
559
+ parallel: phase.config.parallel,
560
+ }, 'engine');
561
+ try {
562
+ if (phase.config.parallel) {
563
+ // Run all agents in parallel (with retry)
564
+ const results = await Promise.allSettled(phase.config.agents.map(assignment => this.executeAgentWithRetry(assignment, phase, orchestration, maxRetries)));
565
+ // Log cache savings estimate for parallel phases
566
+ if (phase.config.agents.length > 1) {
567
+ const phaseContext = this.compaction.buildContextPrefix(this.phaseOutputs);
568
+ const sharedTokens = estimateTokens(`## Orchestration: ${orchestration.config.name}\nPattern: ${orchestration.config.pattern}\n\n${phaseContext}`);
569
+ if (sharedTokens > 0) {
570
+ const savings = estimateCacheSavings(sharedTokens, phase.config.agents.length, 3.0);
571
+ this.log.info(`Cache optimization: ${savings.savingsPercent}% estimated savings on shared prefix (${phase.config.agents.length} agents)`, savings);
572
+ }
573
+ }
574
+ // Check for failures
575
+ const failures = results.filter(r => r.status === 'rejected');
576
+ if (failures.length > 0) {
577
+ const failureCount = failures.length;
578
+ this.log.warn(`Phase had ${failureCount} agent failures`, {
579
+ phase: phase.config.name,
580
+ });
581
+ // If all agents failed, phase fails
582
+ if (failures.length === phase.config.agents.length) {
583
+ phase.status = 'failed';
584
+ }
585
+ else {
586
+ phase.status = 'completed'; // Partial success
587
+ }
588
+ }
589
+ else {
590
+ phase.status = 'completed';
591
+ }
592
+ }
593
+ else {
594
+ // Run agents sequentially (with retry)
595
+ for (const assignment of phase.config.agents) {
596
+ await this.executeAgentWithRetry(assignment, phase, orchestration, maxRetries);
597
+ // Check phase token budget after each agent
598
+ if (phase.config.tokenBudget) {
599
+ const phaseTokens = phase.agents.reduce((sum, a) => sum + a.usage.totalTokens, 0);
600
+ if (phaseTokens >= phase.config.tokenBudget) {
601
+ this.log.warn(`Phase token budget exceeded: ${phaseTokens} >= ${phase.config.tokenBudget}`, {
602
+ phase: phase.config.name,
603
+ });
604
+ break;
605
+ }
606
+ }
607
+ }
608
+ phase.status = 'completed';
609
+ }
610
+ }
611
+ catch (error) {
612
+ phase.status = 'failed';
613
+ throw error;
614
+ }
615
+ phase.completedAt = new Date();
616
+ phase.usage = phase.agents.reduce((total, agent) => mergeUsageStats(total, agent.usage), emptyUsageStats());
617
+ // Run verification after implementation phases
618
+ if (this.verifier && (phase.config.name.includes('implement') || phase.config.name.includes('integrate'))) {
619
+ const results = await this.verifier.verify();
620
+ const summary = Verifier.summarize(results);
621
+ this.log.info(`Verification: ${summary}`, { phase: phase.config.name });
622
+ this.bus.emit('system:warning', { verification: summary, results }, 'verifier');
623
+ }
624
+ // Adaptive replanning based on phase results
625
+ const adaptation = this.replanner.analyze(orchestration, phase);
626
+ if (adaptation) {
627
+ this.replanner.apply(orchestration, adaptation);
628
+ this.bus.emit('system:warning', {
629
+ type: 'adaptive-replan',
630
+ reason: adaptation.reason,
631
+ skipped: adaptation.skipPhases,
632
+ overrides: Object.keys(adaptation.modelOverrides).length,
633
+ }, 'replanner');
634
+ }
635
+ this.bus.emit('orchestration:phase-complete', {
636
+ orchestrationId: orchestration.config.id,
637
+ phase: phase.config.name,
638
+ status: phase.status,
639
+ usage: phase.usage,
640
+ }, 'engine');
641
+ // Save checkpoint after each phase
642
+ saveCheckpoint(orchestration);
643
+ this.log.info(`Phase ${phase.status}: ${phase.config.name}`, {
644
+ agents: phase.agents.length,
645
+ usage: phase.usage,
646
+ });
647
+ // Collect agent outputs for inter-phase context
648
+ const outputs = phase.agents
649
+ .filter(a => a.result?.output)
650
+ .map(a => `[${a.config.name}]: ${a.result.output.slice(0, 2000)}`);
651
+ // Update living spec with phase outputs
652
+ if (this.livingSpec) {
653
+ this.livingSpec = updateSpecFromPhase(this.livingSpec, phase.config.name, outputs);
654
+ }
655
+ // Generate reflection and inject into outputs for next phase
656
+ const reflection = this.reflectionEngine.reflect(phase);
657
+ const reflectionText = this.reflectionEngine.format(reflection);
658
+ this.reflections.push(reflectionText);
659
+ outputs.push(reflectionText);
660
+ // Distill outputs if they're large
661
+ if (this.distiller) {
662
+ const distilled = await this.distiller.distill(outputs, phase.config.name);
663
+ return [distilled];
664
+ }
665
+ return outputs;
666
+ }
667
+ /**
668
+ * Execute a single agent within a phase.
669
+ */
670
+ async executeAgent(assignment, phase, orchestration) {
671
+ // Spawn from registry, passing all assignment overrides
672
+ const instance = this.registry.spawn(assignment.type, {
673
+ name: assignment.name,
674
+ model: assignment.model,
675
+ backend: assignment.backend,
676
+ backendModel: assignment.backendModel,
677
+ });
678
+ phase.agents.push(instance);
679
+ // Build task prompt with cache-friendly ordering:
680
+ // Shared prefix (orchestration + phase context) comes first for API cache hits,
681
+ // agent-specific content (definition + task) comes last.
682
+ const orchestrationContext = `## Orchestration: ${orchestration.config.name}\nPattern: ${orchestration.config.pattern}`;
683
+ const phaseContext = this.compaction.buildContextPrefix(this.phaseOutputs);
684
+ const agentPrompt = instance.config.prompt;
685
+ const baseTask = assignment.prompt || `Execute task as ${assignment.type}`;
686
+ const optimized = optimizeForCache(orchestrationContext, phaseContext, agentPrompt, baseTask);
687
+ // For parallel phases with large shared prefix, use shared context file
688
+ const sharedContextPath = phase.config.parallel
689
+ ? this.writeSharedContext(optimized.sharedPrefix)
690
+ : null;
691
+ // Cascade model selection: if no explicit model override, pick starting tier by complexity
692
+ if (!assignment.model) {
693
+ const complexity = classifyTaskComplexity(baseTask);
694
+ const startTier = selectStartingTier(complexity);
695
+ if (startTier !== instance.config.model) {
696
+ instance.config.model = startTier;
697
+ }
698
+ }
699
+ // Inject living spec into task context
700
+ const specPrefix = this.livingSpec ? formatLivingSpec(this.livingSpec) + '\n\n' : '';
701
+ const task = sharedContextPath
702
+ ? `Read the shared context file at ${sharedContextPath} first, then:\n\n${specPrefix}${optimized.agentSuffix}`
703
+ : `${specPrefix}${optimized.full}`;
704
+ // Transition to running
705
+ this.registry.updateStatus(instance.id, 'running');
706
+ // Create worktree if enabled and assignment requests it
707
+ let worktreeId;
708
+ if (this.worktreeManager && assignment.worktree) {
709
+ try {
710
+ const wt = this.worktreeManager.create(instance.id, assignment.name);
711
+ worktreeId = wt.id;
712
+ this.bus.emit('worktree:created', { agentId: instance.id, worktreeId: wt.id, path: wt.path }, instance.id);
713
+ }
714
+ catch (err) {
715
+ this.log.warn(`Failed to create worktree for ${assignment.name}: ${err}`);
716
+ }
717
+ }
718
+ // Execute with timeout
719
+ const timeoutMs = (instance.config.timeout ?? 300) * 1000; // default 5 min
720
+ let timer;
721
+ const timeoutPromise = new Promise((_, reject) => {
722
+ timer = setTimeout(() => reject(new Error(`Agent timeout after ${timeoutMs / 1000}s`)), timeoutMs);
723
+ });
724
+ try {
725
+ await Promise.race([
726
+ this.executor.execute(instance, task),
727
+ timeoutPromise,
728
+ ]);
729
+ clearTimeout(timer);
730
+ // Merge worktree if created
731
+ if (worktreeId && this.worktreeManager) {
732
+ try {
733
+ this.worktreeManager.merge(worktreeId);
734
+ this.bus.emit('worktree:merged', { agentId: instance.id, worktreeId }, instance.id);
735
+ }
736
+ catch (err) {
737
+ this.log.warn(`Failed to merge worktree ${worktreeId}: ${err}`);
738
+ }
739
+ }
740
+ // Transition to idle (completed successfully)
741
+ this.registry.updateStatus(instance.id, 'idle');
742
+ // Then shutdown
743
+ this.registry.updateStatus(instance.id, 'shutdown');
744
+ return instance;
745
+ }
746
+ catch (error) {
747
+ clearTimeout(timer);
748
+ if (String(error).includes('timeout')) {
749
+ this.registry.updateStatus(instance.id, 'timeout');
750
+ }
751
+ else {
752
+ this.registry.updateStatus(instance.id, 'error');
753
+ }
754
+ instance.error = error instanceof Error ? error.message : String(error);
755
+ throw error;
756
+ }
757
+ }
758
+ async executeAgentWithRetry(assignment, phase, orchestration, maxRetries = 2) {
759
+ let lastError;
760
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
761
+ try {
762
+ return await this.executeAgent(assignment, phase, orchestration);
763
+ }
764
+ catch (error) {
765
+ lastError = error instanceof Error ? error : new Error(String(error));
766
+ // Remove the failed instance from phase agents to prevent duplicates on retry
767
+ const failedIndex = phase.agents.findIndex(a => a.config.name === assignment.name && (a.status === 'error' || a.status === 'timeout'));
768
+ if (failedIndex >= 0)
769
+ phase.agents.splice(failedIndex, 1);
770
+ if (attempt < maxRetries) {
771
+ const delayMs = Math.min(1000 * Math.pow(2, attempt) + Math.random() * 1000, 30000);
772
+ this.log.warn(`Agent failed, retrying in ${Math.round(delayMs / 1000)}s (attempt ${attempt + 1}/${maxRetries})`, {
773
+ agent: assignment.name,
774
+ error: lastError.message,
775
+ });
776
+ await new Promise(resolve => setTimeout(resolve, delayMs));
777
+ }
778
+ }
779
+ }
780
+ throw lastError;
781
+ }
782
+ // ─── Resume ────────────────────────────────────────────────────
783
+ /**
784
+ * Resume an orchestration from a checkpoint.
785
+ */
786
+ async resume(orchestrationId) {
787
+ const checkpoint = loadCheckpoint(orchestrationId);
788
+ if (!checkpoint) {
789
+ this.log.error(`No checkpoint found for: ${orchestrationId}`);
790
+ return null;
791
+ }
792
+ this.log.info(`Resuming orchestration: ${checkpoint.config.name} from phase ${checkpoint.currentPhase + 1}`);
793
+ // Reconstruct the orchestration, marking completed phases
794
+ const orchestration = this.createInstance(checkpoint.config);
795
+ orchestration.status = 'running';
796
+ orchestration.startedAt = new Date();
797
+ // Mark completed phases from checkpoint
798
+ for (let i = 0; i < checkpoint.phaseResults.length; i++) {
799
+ const saved = checkpoint.phaseResults[i];
800
+ if (saved && (saved.status === 'completed' || saved.status === 'failed')) {
801
+ orchestration.phases[i].status = saved.status;
802
+ }
803
+ }
804
+ this.orchestrations.set(checkpoint.config.id, orchestration);
805
+ this.bus.emit('orchestration:resumed', {
806
+ id: checkpoint.config.id,
807
+ name: checkpoint.config.name,
808
+ resumedFromPhase: checkpoint.currentPhase,
809
+ }, 'engine');
810
+ // Re-run execute — the DAG executor will skip completed phases
811
+ // because they're already marked and seeded into the completed set
812
+ return this.execute(checkpoint.config);
813
+ }
814
+ // ─── Approval ─────────────────────────────────────────────────
815
+ async requestApproval(phaseName, agents) {
816
+ const { createInterface } = await import('readline');
817
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
818
+ return new Promise((resolve) => {
819
+ const agentList = agents.map(a => ` ${a.name} (${a.type})`).join('\n');
820
+ rl.question(`\n⏸ Phase "${phaseName}" requires approval.\n` +
821
+ ` Agents:\n${agentList}\n` +
822
+ ` Proceed? [Y/n] `, (answer) => {
823
+ rl.close();
824
+ resolve(answer.toLowerCase() !== 'n');
825
+ });
826
+ });
827
+ }
828
+ // ─── Signal Handling ──────────────────────────────────────────
829
+ /**
830
+ * Register signal handlers for graceful shutdown.
831
+ */
832
+ setupSignalHandlers() {
833
+ // Remove any previously registered handlers to prevent accumulation
834
+ this.removeSignalHandlers();
835
+ const handler = async () => {
836
+ this.log.warn('Shutdown signal received — saving checkpoint and cleaning up');
837
+ this.abortController.abort();
838
+ // Save checkpoint for any running orchestration
839
+ for (const orchestration of this.getActiveOrchestrations()) {
840
+ try {
841
+ const path = saveCheckpoint(orchestration);
842
+ this.log.info(`Checkpoint saved: ${path}`);
843
+ }
844
+ catch {
845
+ // Best effort
846
+ }
847
+ orchestration.status = 'cancelled';
848
+ }
849
+ // Transition running agents to error
850
+ for (const instance of this.registry.getActiveInstances()) {
851
+ try {
852
+ this.registry.updateStatus(instance.id, 'error');
853
+ }
854
+ catch {
855
+ // Best effort — lifecycle may not allow transition
856
+ }
857
+ }
858
+ try {
859
+ this.stats.close();
860
+ }
861
+ catch { /* best effort */ }
862
+ try {
863
+ this.traceStore?.close();
864
+ }
865
+ catch { /* best effort */ }
866
+ try {
867
+ this.heuristicStore?.close();
868
+ }
869
+ catch { /* best effort */ }
870
+ try {
871
+ this.modelRouter?.close();
872
+ }
873
+ catch { }
874
+ try {
875
+ this.autonomyTracker?.close();
876
+ }
877
+ catch { }
878
+ this.bus.emit('system:warning', { message: 'Graceful shutdown complete' }, 'engine');
879
+ };
880
+ process.on('SIGINT', handler);
881
+ process.on('SIGTERM', handler);
882
+ this.signalHandlers.push({ signal: 'SIGINT', handler: handler });
883
+ this.signalHandlers.push({ signal: 'SIGTERM', handler: handler });
884
+ }
885
+ removeSignalHandlers() {
886
+ for (const { signal, handler } of this.signalHandlers) {
887
+ process.removeListener(signal, handler);
888
+ }
889
+ this.signalHandlers = [];
890
+ }
891
+ /** Close all resources (stats, traces, heuristics, model router, autonomy tracker). */
892
+ close() {
893
+ try {
894
+ this.stats.close();
895
+ }
896
+ catch { }
897
+ try {
898
+ this.traceStore?.close();
899
+ }
900
+ catch { }
901
+ try {
902
+ this.heuristicStore?.close();
903
+ }
904
+ catch { }
905
+ try {
906
+ this.modelRouter?.close();
907
+ }
908
+ catch { }
909
+ try {
910
+ this.autonomyTracker?.close();
911
+ }
912
+ catch { }
913
+ this.removeSignalHandlers();
914
+ }
915
+ // ─── Queries ───────────────────────────────────────────────────
916
+ /**
917
+ * Get an orchestration by ID.
918
+ */
919
+ getOrchestration(id) {
920
+ return this.orchestrations.get(id);
921
+ }
922
+ /**
923
+ * Get all orchestrations.
924
+ */
925
+ getAllOrchestrations() {
926
+ return [...this.orchestrations.values()];
927
+ }
928
+ /**
929
+ * Get active orchestrations.
930
+ */
931
+ getActiveOrchestrations() {
932
+ return [...this.orchestrations.values()].filter(o => o.status === 'running' || o.status === 'paused');
933
+ }
934
+ get patternRegistry() {
935
+ return this.patterns;
936
+ }
937
+ // ─── Shared Context ────────────────────────────────────────────
938
+ /**
939
+ * Write shared context to a file for parallel agents to read,
940
+ * avoiding duplicating large context in each agent's prompt.
941
+ */
942
+ writeSharedContext(context) {
943
+ if (!context || context.length < 2000)
944
+ return null; // Not worth sharing for small contexts
945
+ const contextDir = join(this.options.cwd ?? process.cwd(), '.swarm');
946
+ if (!existsSync(contextDir))
947
+ mkdirSync(contextDir, { recursive: true });
948
+ const contextPath = join(contextDir, `shared-context-${randomUUID().slice(0, 8)}.md`);
949
+ writeFileSync(contextPath, redactSecrets(context), { mode: 0o600 });
950
+ this.sharedContextFiles.push(contextPath);
951
+ return contextPath;
952
+ }
953
+ // ─── Factory ───────────────────────────────────────────────────
954
+ createInstance(config) {
955
+ return {
956
+ config,
957
+ status: 'pending',
958
+ phases: config.phases.map(phaseConfig => ({
959
+ config: phaseConfig,
960
+ status: 'pending',
961
+ agents: [],
962
+ usage: emptyUsageStats(),
963
+ })),
964
+ currentPhase: 0,
965
+ usage: emptyUsageStats(),
966
+ };
967
+ }
968
+ }
969
+ //# sourceMappingURL=engine.js.map