@desplega.ai/agent-swarm 1.10.8 → 1.49.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 (846) hide show
  1. package/.claude/settings.json +84 -0
  2. package/.claude/settings.local.json +17 -2
  3. package/.entire/settings.json +4 -0
  4. package/.env.docker.example +44 -21
  5. package/.env.example +53 -1
  6. package/.github/ISSUE_TEMPLATE/bug_report.yml +78 -0
  7. package/.github/ISSUE_TEMPLATE/community-template.yml +77 -0
  8. package/.github/ISSUE_TEMPLATE/config.yml +8 -0
  9. package/.github/ISSUE_TEMPLATE/feature_request.yml +60 -0
  10. package/.github/PULL_REQUEST_TEMPLATE/community-template.md +29 -0
  11. package/.github/workflows/ci.yml +3 -27
  12. package/.github/workflows/docker-and-deploy.yml +42 -27
  13. package/.github/workflows/merge-gate.yml +233 -0
  14. package/.opencode/plugins/entire.ts +133 -0
  15. package/.superset/config.json +6 -0
  16. package/.wts-config.json +4 -0
  17. package/.wts-setup.ts +171 -0
  18. package/CHANGELOG.md +447 -0
  19. package/CLAUDE.md +493 -83
  20. package/CONTRIBUTING.md +46 -1
  21. package/DEPLOYMENT.md +249 -18
  22. package/Dockerfile +15 -7
  23. package/Dockerfile.worker +99 -50
  24. package/MCP.md +594 -2
  25. package/README.md +288 -111
  26. package/api-entrypoint.sh +56 -0
  27. package/depot.json +1 -0
  28. package/docker-compose.example.yml +219 -5
  29. package/docker-compose.local.yml +119 -0
  30. package/docker-entrypoint.sh +407 -56
  31. package/docs-site/app/api/search/route.ts +4 -0
  32. package/docs-site/app/docs/[[...slug]]/page.tsx +87 -0
  33. package/docs-site/app/docs/layout.tsx +12 -0
  34. package/docs-site/app/globals.css +24 -0
  35. package/docs-site/app/layout.config.tsx +34 -0
  36. package/docs-site/app/layout.tsx +119 -0
  37. package/docs-site/app/llms-full.txt/route.ts +11 -0
  38. package/docs-site/app/llms.mdx/docs/[[...slug]]/route.ts +24 -0
  39. package/docs-site/app/llms.txt/route.ts +8 -0
  40. package/docs-site/app/page.tsx +5 -0
  41. package/docs-site/app/robots.ts +13 -0
  42. package/docs-site/app/sitemap.ts +37 -0
  43. package/docs-site/components/api-page.client.tsx +4 -0
  44. package/docs-site/components/api-page.tsx +7 -0
  45. package/docs-site/components/mdx/mermaid.tsx +55 -0
  46. package/docs-site/content/docs/(documentation)/architecture/agents.mdx +117 -0
  47. package/docs-site/content/docs/(documentation)/architecture/hooks.mdx +77 -0
  48. package/docs-site/content/docs/(documentation)/architecture/memory.mdx +96 -0
  49. package/docs-site/content/docs/(documentation)/architecture/meta.json +4 -0
  50. package/docs-site/content/docs/(documentation)/architecture/overview.mdx +172 -0
  51. package/docs-site/content/docs/(documentation)/concepts/epics.mdx +98 -0
  52. package/docs-site/content/docs/(documentation)/concepts/meta.json +4 -0
  53. package/docs-site/content/docs/(documentation)/concepts/scheduling.mdx +136 -0
  54. package/docs-site/content/docs/(documentation)/concepts/services.mdx +104 -0
  55. package/docs-site/content/docs/(documentation)/concepts/task-lifecycle.mdx +148 -0
  56. package/docs-site/content/docs/(documentation)/concepts/workflows.mdx +209 -0
  57. package/docs-site/content/docs/(documentation)/contributing.mdx +158 -0
  58. package/docs-site/content/docs/(documentation)/getting-started.mdx +157 -0
  59. package/docs-site/content/docs/(documentation)/guides/agentmail-integration.mdx +79 -0
  60. package/docs-site/content/docs/(documentation)/guides/deployment.mdx +171 -0
  61. package/docs-site/content/docs/(documentation)/guides/github-integration.mdx +81 -0
  62. package/docs-site/content/docs/(documentation)/guides/gitlab-integration.mdx +93 -0
  63. package/docs-site/content/docs/(documentation)/guides/linear-integration.mdx +98 -0
  64. package/docs-site/content/docs/(documentation)/guides/meta.json +13 -0
  65. package/docs-site/content/docs/(documentation)/guides/sentry-integration.mdx +52 -0
  66. package/docs-site/content/docs/(documentation)/guides/slack-integration.mdx +179 -0
  67. package/docs-site/content/docs/(documentation)/guides/x402-payments.mdx +154 -0
  68. package/docs-site/content/docs/(documentation)/index.mdx +65 -0
  69. package/docs-site/content/docs/(documentation)/meta.json +19 -0
  70. package/docs-site/content/docs/(documentation)/reference/cli.mdx +241 -0
  71. package/docs-site/content/docs/(documentation)/reference/environment-variables.mdx +205 -0
  72. package/docs-site/content/docs/(documentation)/reference/mcp-tools.mdx +449 -0
  73. package/docs-site/content/docs/(documentation)/reference/meta.json +4 -0
  74. package/docs-site/content/docs/api-reference/active-sessions.mdx +9 -0
  75. package/docs-site/content/docs/api-reference/agents.mdx +9 -0
  76. package/docs-site/content/docs/api-reference/channels.mdx +9 -0
  77. package/docs-site/content/docs/api-reference/config.mdx +9 -0
  78. package/docs-site/content/docs/api-reference/debug.mdx +9 -0
  79. package/docs-site/content/docs/api-reference/ecosystem.mdx +9 -0
  80. package/docs-site/content/docs/api-reference/epics.mdx +9 -0
  81. package/docs-site/content/docs/api-reference/index.mdx +32 -0
  82. package/docs-site/content/docs/api-reference/memory.mdx +9 -0
  83. package/docs-site/content/docs/api-reference/meta.json +25 -0
  84. package/docs-site/content/docs/api-reference/poll.mdx +9 -0
  85. package/docs-site/content/docs/api-reference/repos.mdx +9 -0
  86. package/docs-site/content/docs/api-reference/schedules.mdx +9 -0
  87. package/docs-site/content/docs/api-reference/session-data.mdx +9 -0
  88. package/docs-site/content/docs/api-reference/stats.mdx +9 -0
  89. package/docs-site/content/docs/api-reference/tasks.mdx +9 -0
  90. package/docs-site/content/docs/api-reference/trackers.mdx +9 -0
  91. package/docs-site/content/docs/api-reference/webhooks.mdx +9 -0
  92. package/docs-site/content/docs/api-reference/workflows.mdx +9 -0
  93. package/docs-site/content/docs/meta.json +3 -0
  94. package/docs-site/lib/get-llm-text.ts +10 -0
  95. package/docs-site/lib/openapi.ts +23 -0
  96. package/docs-site/lib/source.ts +8 -0
  97. package/docs-site/mdx-components.tsx +13 -0
  98. package/docs-site/next.config.mjs +29 -0
  99. package/docs-site/package.json +35 -0
  100. package/docs-site/pnpm-lock.yaml +5407 -0
  101. package/docs-site/postcss.config.mjs +8 -0
  102. package/docs-site/scripts/generate-docs.ts +171 -0
  103. package/docs-site/source.config.ts +17 -0
  104. package/docs-site/tsconfig.json +46 -0
  105. package/ecosystem.config.cjs +66 -0
  106. package/landing/next.config.ts +14 -0
  107. package/landing/package.json +31 -0
  108. package/landing/pnpm-lock.yaml +1091 -0
  109. package/landing/postcss.config.mjs +8 -0
  110. package/landing/public/apple-touch-icon.png +0 -0
  111. package/landing/public/favicon.ico +0 -0
  112. package/landing/public/logo.png +0 -0
  113. package/landing/public/og-image.png +0 -0
  114. package/landing/public/omghost-desplega.svg +30 -0
  115. package/landing/public/omghost-openfort.svg +9 -0
  116. package/landing/src/app/actions/waitlist.ts +25 -0
  117. package/landing/src/app/blog/openfort-hackathon/page.tsx +863 -0
  118. package/landing/src/app/blog/page.tsx +162 -0
  119. package/landing/src/app/blog/swarm-metrics/page.tsx +685 -0
  120. package/landing/src/app/examples/page.tsx +174 -0
  121. package/landing/src/app/examples/x402/page.tsx +456 -0
  122. package/landing/src/app/globals.css +122 -0
  123. package/landing/src/app/layout.tsx +134 -0
  124. package/landing/src/app/page.tsx +27 -0
  125. package/landing/src/app/robots.ts +13 -0
  126. package/landing/src/app/sitemap.ts +44 -0
  127. package/landing/src/components/architecture.tsx +163 -0
  128. package/landing/src/components/cta.tsx +52 -0
  129. package/landing/src/components/features.tsx +160 -0
  130. package/landing/src/components/footer.tsx +100 -0
  131. package/landing/src/components/hero.tsx +217 -0
  132. package/landing/src/components/how-it-works.tsx +165 -0
  133. package/landing/src/components/navbar.tsx +147 -0
  134. package/landing/src/components/waitlist.tsx +110 -0
  135. package/landing/src/components/why-choose.tsx +149 -0
  136. package/landing/src/components/workshops.tsx +328 -0
  137. package/landing/src/lib/utils.ts +6 -0
  138. package/landing/tsconfig.json +41 -0
  139. package/misc/transcripts/2026-03-09-pi-mono-e2e-verification.md +154 -0
  140. package/new-ui/CLAUDE.md +92 -0
  141. package/new-ui/README.md +73 -0
  142. package/new-ui/biome.json +42 -0
  143. package/new-ui/components.json +21 -0
  144. package/new-ui/index.html +25 -0
  145. package/new-ui/package.json +49 -0
  146. package/new-ui/pnpm-lock.yaml +4845 -0
  147. package/new-ui/public/logo.png +0 -0
  148. package/new-ui/src/api/client.ts +814 -0
  149. package/new-ui/src/api/hooks/index.ts +64 -0
  150. package/new-ui/src/api/hooks/use-agents.ts +58 -0
  151. package/new-ui/src/api/hooks/use-channels.ts +115 -0
  152. package/new-ui/src/api/hooks/use-config-api.ts +46 -0
  153. package/new-ui/src/api/hooks/use-costs.ts +122 -0
  154. package/new-ui/src/api/hooks/use-db-query.ts +29 -0
  155. package/new-ui/src/api/hooks/use-epics.ts +75 -0
  156. package/new-ui/src/api/hooks/use-repos.ts +61 -0
  157. package/new-ui/src/api/hooks/use-schedules.ts +81 -0
  158. package/new-ui/src/api/hooks/use-services.ts +16 -0
  159. package/new-ui/src/api/hooks/use-stats.ts +27 -0
  160. package/new-ui/src/api/hooks/use-tasks.ts +89 -0
  161. package/new-ui/src/api/hooks/use-workflows.ts +109 -0
  162. package/new-ui/src/api/types.ts +549 -0
  163. package/new-ui/src/app/App.tsx +13 -0
  164. package/new-ui/src/app/providers.tsx +32 -0
  165. package/new-ui/src/app/router.tsx +52 -0
  166. package/new-ui/src/components/layout/app-header.tsx +47 -0
  167. package/new-ui/src/components/layout/app-sidebar.tsx +128 -0
  168. package/new-ui/src/components/layout/breadcrumbs.tsx +57 -0
  169. package/new-ui/src/components/layout/config-guard.tsx +22 -0
  170. package/new-ui/src/components/layout/root-layout.tsx +40 -0
  171. package/new-ui/src/components/layout/swarm-switcher.tsx +85 -0
  172. package/new-ui/src/components/shared/command-menu.tsx +131 -0
  173. package/new-ui/src/components/shared/data-grid.tsx +141 -0
  174. package/new-ui/src/components/shared/empty-state.tsx +24 -0
  175. package/new-ui/src/components/shared/error-boundary.tsx +72 -0
  176. package/new-ui/src/components/shared/json-viewer.tsx +47 -0
  177. package/new-ui/src/components/shared/name-connection-modal.tsx +99 -0
  178. package/new-ui/src/components/shared/page-skeleton.tsx +16 -0
  179. package/new-ui/src/components/shared/session-log-viewer.tsx +364 -0
  180. package/new-ui/src/components/shared/stats-bar.tsx +132 -0
  181. package/new-ui/src/components/shared/status-badge.tsx +131 -0
  182. package/new-ui/src/components/shared/usage-summary.tsx +179 -0
  183. package/new-ui/src/components/ui/alert-dialog.tsx +176 -0
  184. package/new-ui/src/components/ui/alert.tsx +60 -0
  185. package/new-ui/src/components/ui/avatar.tsx +96 -0
  186. package/new-ui/src/components/ui/badge.tsx +46 -0
  187. package/new-ui/src/components/ui/button.tsx +62 -0
  188. package/new-ui/src/components/ui/card.tsx +75 -0
  189. package/new-ui/src/components/ui/command.tsx +160 -0
  190. package/new-ui/src/components/ui/dialog.tsx +143 -0
  191. package/new-ui/src/components/ui/dropdown-menu.tsx +226 -0
  192. package/new-ui/src/components/ui/input.tsx +21 -0
  193. package/new-ui/src/components/ui/label.tsx +19 -0
  194. package/new-ui/src/components/ui/progress.tsx +26 -0
  195. package/new-ui/src/components/ui/scroll-area.tsx +54 -0
  196. package/new-ui/src/components/ui/select.tsx +175 -0
  197. package/new-ui/src/components/ui/separator.tsx +28 -0
  198. package/new-ui/src/components/ui/sheet.tsx +132 -0
  199. package/new-ui/src/components/ui/sidebar.tsx +691 -0
  200. package/new-ui/src/components/ui/skeleton.tsx +13 -0
  201. package/new-ui/src/components/ui/sonner.tsx +35 -0
  202. package/new-ui/src/components/ui/switch.tsx +33 -0
  203. package/new-ui/src/components/ui/table.tsx +92 -0
  204. package/new-ui/src/components/ui/tabs.tsx +79 -0
  205. package/new-ui/src/components/ui/textarea.tsx +18 -0
  206. package/new-ui/src/components/ui/tooltip.tsx +51 -0
  207. package/new-ui/src/components/workflows/action-node.tsx +53 -0
  208. package/new-ui/src/components/workflows/condition-node.tsx +50 -0
  209. package/new-ui/src/components/workflows/graph-utils.ts +124 -0
  210. package/new-ui/src/components/workflows/json-tree.tsx +189 -0
  211. package/new-ui/src/components/workflows/node-styles.ts +10 -0
  212. package/new-ui/src/components/workflows/step-detail-sheet.tsx +87 -0
  213. package/new-ui/src/components/workflows/trigger-node.tsx +41 -0
  214. package/new-ui/src/components/workflows/workflow-graph.tsx +65 -0
  215. package/{ui/src/hooks/useAutoScroll.ts → new-ui/src/hooks/use-auto-scroll.ts} +37 -10
  216. package/new-ui/src/hooks/use-config.ts +203 -0
  217. package/new-ui/src/hooks/use-keyboard-shortcuts.ts +41 -0
  218. package/new-ui/src/hooks/use-mobile.ts +19 -0
  219. package/new-ui/src/hooks/use-theme.ts +60 -0
  220. package/new-ui/src/lib/config.ts +188 -0
  221. package/new-ui/src/lib/slugs.ts +71 -0
  222. package/new-ui/src/lib/utils.ts +120 -0
  223. package/new-ui/src/main.tsx +11 -0
  224. package/new-ui/src/pages/agents/[id]/page.tsx +492 -0
  225. package/new-ui/src/pages/agents/page.tsx +134 -0
  226. package/new-ui/src/pages/chat/page.tsx +674 -0
  227. package/new-ui/src/pages/config/page.tsx +1109 -0
  228. package/new-ui/src/pages/dashboard/page.tsx +454 -0
  229. package/new-ui/src/pages/debug/page.tsx +275 -0
  230. package/new-ui/src/pages/epics/[id]/page.tsx +809 -0
  231. package/new-ui/src/pages/epics/page.tsx +321 -0
  232. package/new-ui/src/pages/not-found/page.tsx +18 -0
  233. package/new-ui/src/pages/repos/page.tsx +369 -0
  234. package/new-ui/src/pages/schedules/[id]/page.tsx +664 -0
  235. package/new-ui/src/pages/schedules/page.tsx +477 -0
  236. package/new-ui/src/pages/services/page.tsx +128 -0
  237. package/new-ui/src/pages/tasks/[id]/page.tsx +670 -0
  238. package/new-ui/src/pages/tasks/page.tsx +592 -0
  239. package/new-ui/src/pages/usage/page.tsx +195 -0
  240. package/new-ui/src/pages/workflow-runs/[id]/page.tsx +363 -0
  241. package/new-ui/src/pages/workflows/[id]/page.tsx +417 -0
  242. package/new-ui/src/pages/workflows/page.tsx +266 -0
  243. package/new-ui/src/styles/ag-grid.css +36 -0
  244. package/new-ui/src/styles/globals.css +213 -0
  245. package/new-ui/test-results/.last-run.json +4 -0
  246. package/{ui/tsconfig.json → new-ui/tsconfig.app.json} +7 -4
  247. package/new-ui/tsconfig.json +4 -0
  248. package/new-ui/tsconfig.node.json +26 -0
  249. package/new-ui/vercel.json +4 -0
  250. package/new-ui/vite.config.ts +28 -0
  251. package/openapi.json +4436 -0
  252. package/package.json +41 -8
  253. package/plugin/build-pi-skills.ts +233 -0
  254. package/plugin/commands/close-issue.md +90 -0
  255. package/plugin/commands/create-pr.md +99 -0
  256. package/plugin/commands/implement-issue.md +135 -0
  257. package/plugin/commands/investigate-sentry-issue.md +138 -0
  258. package/plugin/commands/respond-github.md +98 -0
  259. package/plugin/commands/review-pr.md +261 -0
  260. package/plugin/commands/start-leader.md +33 -15
  261. package/plugin/commands/start-worker.md +1 -3
  262. package/plugin/commands/swarm-chat.md +4 -0
  263. package/plugin/commands/work-on-task.md +34 -6
  264. package/plugin/pi-skills/close-issue/SKILL.md +90 -0
  265. package/plugin/pi-skills/create-pr/SKILL.md +99 -0
  266. package/plugin/pi-skills/implement-issue/SKILL.md +135 -0
  267. package/plugin/pi-skills/investigate-sentry-issue/SKILL.md +138 -0
  268. package/plugin/pi-skills/respond-github/SKILL.md +98 -0
  269. package/plugin/pi-skills/review-offered-task/SKILL.md +45 -0
  270. package/plugin/pi-skills/review-pr/SKILL.md +261 -0
  271. package/plugin/pi-skills/start-leader/SKILL.md +121 -0
  272. package/plugin/pi-skills/start-worker/SKILL.md +60 -0
  273. package/plugin/pi-skills/swarm-chat/SKILL.md +82 -0
  274. package/plugin/pi-skills/todos/SKILL.md +66 -0
  275. package/plugin/pi-skills/work-on-task/SKILL.md +65 -0
  276. package/plugin/skills/artifacts/examples/approval-flow.ts +34 -0
  277. package/plugin/skills/artifacts/examples/hono-dashboard.ts +31 -0
  278. package/plugin/skills/artifacts/examples/multi-artifact.ts +20 -0
  279. package/plugin/skills/artifacts/examples/static-report.sh +17 -0
  280. package/plugin/skills/artifacts/skill.md +71 -0
  281. package/prek.toml +75 -0
  282. package/scripts/check-db-boundary.sh +60 -0
  283. package/scripts/e2e-docker-provider.ts +820 -0
  284. package/scripts/e2e-io-schemas-test.ts +807 -0
  285. package/scripts/e2e-provider-test.ts +220 -0
  286. package/scripts/e2e-workflow-redesign.sh +229 -0
  287. package/scripts/e2e-workflow-test.sh +285 -0
  288. package/scripts/e2e-workflow-test.ts +857 -0
  289. package/scripts/generate-mcp-docs.ts +4 -4
  290. package/scripts/generate-openapi.ts +26 -0
  291. package/scripts/measure-tool-tokens.ts +118 -0
  292. package/scripts/x402-e2e-test.ts +195 -0
  293. package/scripts/x402-test-server.ts +236 -0
  294. package/scripts/x402-testnet-e2e.ts +668 -0
  295. package/slack-manifest.json +19 -0
  296. package/src/agentmail/app.ts +65 -0
  297. package/src/agentmail/handlers.ts +207 -0
  298. package/src/agentmail/index.ts +9 -0
  299. package/src/agentmail/types.ts +51 -0
  300. package/src/artifact-sdk/browser-sdk.ts +30 -0
  301. package/src/artifact-sdk/index.ts +2 -0
  302. package/src/artifact-sdk/localtunnel.d.ts +20 -0
  303. package/src/artifact-sdk/port.ts +12 -0
  304. package/src/artifact-sdk/server.ts +156 -0
  305. package/src/artifact-sdk/tunnel.ts +19 -0
  306. package/src/be/chunking.ts +193 -0
  307. package/src/be/db-queries/oauth.ts +90 -0
  308. package/src/be/db-queries/tracker.ts +182 -0
  309. package/src/be/db.ts +4469 -381
  310. package/src/be/embedding.ts +80 -0
  311. package/src/be/migrations/001_initial.sql +409 -0
  312. package/src/be/migrations/002_one_time_schedules.sql +59 -0
  313. package/src/be/migrations/003_workflows.sql +51 -0
  314. package/src/be/migrations/004_workflow_source.sql +81 -0
  315. package/src/be/migrations/005_epic_next_steps.sql +2 -0
  316. package/src/be/migrations/006_vcs_provider.sql +94 -0
  317. package/src/be/migrations/007_task_dir.sql +2 -0
  318. package/src/be/migrations/008_workflow_redesign.sql +85 -0
  319. package/src/be/migrations/009_tracker_integration.sql +144 -0
  320. package/src/be/migrations/010_step_diagnostics.sql +1 -0
  321. package/src/be/migrations/011_step_next_port.sql +1 -0
  322. package/src/be/migrations/012_trigger_schema.sql +1 -0
  323. package/src/be/migrations/013_task_output_schema.sql +2 -0
  324. package/src/be/migrations/runner.ts +188 -0
  325. package/src/cli.tsx +231 -299
  326. package/src/commands/artifact.ts +241 -0
  327. package/src/commands/onboard/compose-generator.ts +169 -0
  328. package/src/commands/onboard/env-generator.ts +79 -0
  329. package/src/commands/onboard/manifest.ts +37 -0
  330. package/src/commands/onboard/presets.ts +85 -0
  331. package/src/commands/onboard/service-names.ts +47 -0
  332. package/src/commands/onboard/steps/core-credentials.tsx +111 -0
  333. package/src/commands/onboard/steps/custom-templates.tsx +168 -0
  334. package/src/commands/onboard/steps/generate.tsx +154 -0
  335. package/src/commands/onboard/steps/harness-credentials.tsx +195 -0
  336. package/src/commands/onboard/steps/harness.tsx +21 -0
  337. package/src/commands/onboard/steps/health-check.tsx +171 -0
  338. package/src/commands/onboard/steps/integration-github.tsx +105 -0
  339. package/src/commands/onboard/steps/integration-gitlab.tsx +79 -0
  340. package/src/commands/onboard/steps/integration-menu.tsx +58 -0
  341. package/src/commands/onboard/steps/integration-sentry.tsx +79 -0
  342. package/src/commands/onboard/steps/integration-slack.tsx +165 -0
  343. package/src/commands/onboard/steps/post-connect.tsx +145 -0
  344. package/src/commands/onboard/steps/post-dashboard.tsx +34 -0
  345. package/src/commands/onboard/steps/post-task.tsx +103 -0
  346. package/src/commands/onboard/steps/prereq-check.tsx +178 -0
  347. package/src/commands/onboard/steps/review.tsx +82 -0
  348. package/src/commands/onboard/steps/start.tsx +97 -0
  349. package/src/commands/onboard/templates.ts +34 -0
  350. package/src/commands/onboard/types.ts +259 -0
  351. package/src/commands/onboard.tsx +425 -0
  352. package/src/commands/runner.ts +2023 -278
  353. package/src/commands/setup.tsx +23 -38
  354. package/src/commands/shared/client-config.ts +41 -0
  355. package/src/github/app.ts +239 -0
  356. package/src/github/handlers.ts +936 -0
  357. package/src/github/index.ts +32 -0
  358. package/src/github/mentions.test.ts +104 -0
  359. package/src/github/mentions.ts +30 -0
  360. package/src/github/reactions.ts +153 -0
  361. package/src/github/types.ts +157 -0
  362. package/src/gitlab/auth.ts +63 -0
  363. package/src/gitlab/handlers.ts +327 -0
  364. package/src/gitlab/index.ts +19 -0
  365. package/src/gitlab/reactions.ts +104 -0
  366. package/src/gitlab/types.ts +130 -0
  367. package/src/heartbeat/heartbeat.ts +425 -0
  368. package/src/heartbeat/index.ts +1 -0
  369. package/src/hooks/hook.ts +867 -7
  370. package/src/hooks/tool-loop-detection.test.ts +158 -0
  371. package/src/hooks/tool-loop-detection.ts +167 -0
  372. package/src/http/active-sessions.ts +172 -0
  373. package/src/http/agents.ts +328 -0
  374. package/src/http/config.ts +191 -0
  375. package/src/http/core.ts +309 -0
  376. package/src/http/db-query.ts +91 -0
  377. package/src/http/ecosystem.ts +63 -0
  378. package/src/http/epics.ts +460 -0
  379. package/src/http/index.ts +213 -0
  380. package/src/http/mcp.ts +77 -0
  381. package/src/http/memory.ts +168 -0
  382. package/src/http/openapi.ts +109 -0
  383. package/src/http/poll.ts +178 -0
  384. package/src/http/repos.ts +195 -0
  385. package/src/http/route-def.ts +123 -0
  386. package/src/http/schedules.ts +391 -0
  387. package/src/http/session-data.ts +241 -0
  388. package/src/http/stats.ts +174 -0
  389. package/src/http/tasks.ts +468 -0
  390. package/src/http/trackers/index.ts +10 -0
  391. package/src/http/trackers/linear.ts +187 -0
  392. package/src/http/types.ts +12 -0
  393. package/src/http/utils.ts +87 -0
  394. package/src/http/webhooks.ts +432 -0
  395. package/src/http/workflows.ts +522 -0
  396. package/src/http.ts +1 -908
  397. package/src/linear/README.md +65 -0
  398. package/src/linear/app.ts +48 -0
  399. package/src/linear/client.ts +18 -0
  400. package/src/linear/index.ts +1 -0
  401. package/src/linear/oauth.ts +35 -0
  402. package/src/linear/outbound.ts +212 -0
  403. package/src/linear/sync.ts +543 -0
  404. package/src/linear/types.ts +7 -0
  405. package/src/linear/webhook.ts +104 -0
  406. package/src/oauth/README.md +66 -0
  407. package/src/oauth/index.ts +6 -0
  408. package/src/oauth/wrapper.ts +204 -0
  409. package/src/prompts/base-prompt.ts +521 -28
  410. package/src/prompts/defaults.ts +196 -0
  411. package/src/providers/claude-adapter.ts +429 -0
  412. package/src/providers/index.ts +24 -0
  413. package/src/providers/pi-mono-adapter.ts +442 -0
  414. package/src/providers/pi-mono-extension.ts +620 -0
  415. package/src/providers/pi-mono-mcp-client.ts +124 -0
  416. package/src/providers/types.ts +75 -0
  417. package/src/scheduler/index.ts +1 -0
  418. package/src/scheduler/scheduler.test.ts +151 -0
  419. package/src/scheduler/scheduler.ts +321 -0
  420. package/src/server.ts +136 -1
  421. package/src/slack/HEURISTICS.md +105 -0
  422. package/src/slack/actions.ts +133 -0
  423. package/src/slack/app.ts +7 -0
  424. package/src/slack/assistant.ts +115 -0
  425. package/src/slack/blocks.ts +233 -0
  426. package/src/slack/commands.ts +31 -17
  427. package/src/slack/files.ts +302 -0
  428. package/src/slack/handlers.test.ts +278 -0
  429. package/src/slack/handlers.ts +360 -46
  430. package/src/slack/index.ts +15 -0
  431. package/src/slack/responses.ts +120 -59
  432. package/src/slack/router.ts +17 -99
  433. package/src/slack/thread-buffer.ts +213 -0
  434. package/src/slack/watcher.ts +119 -4
  435. package/src/tests/agent-activity.test.ts +247 -0
  436. package/src/tests/agentmail-filters.test.ts +97 -0
  437. package/src/tests/artifact-sdk.test.ts +800 -0
  438. package/src/tests/base-prompt.test.ts +264 -0
  439. package/src/tests/build-pi-skills.test.ts +127 -0
  440. package/src/tests/claude-adapter.test.ts +126 -0
  441. package/src/tests/concurrency.test.ts +213 -0
  442. package/src/tests/context-versioning.test.ts +425 -0
  443. package/src/tests/db-capacity.test.ts +212 -0
  444. package/src/tests/db-queries-oauth.test.ts +197 -0
  445. package/src/tests/db-queries-tracker.test.ts +230 -0
  446. package/src/tests/epics.test.ts +370 -0
  447. package/src/tests/error-tracker.test.ts +368 -0
  448. package/src/tests/fetch-resolved-env.test.ts +167 -0
  449. package/src/tests/generate-default-claude-md.test.ts +98 -0
  450. package/src/tests/generate-identity-templates.test.ts +124 -0
  451. package/src/tests/gitlab-auth.test.ts +109 -0
  452. package/src/tests/gitlab-handlers.test.ts +691 -0
  453. package/src/tests/gitlab-vcs-db.test.ts +177 -0
  454. package/src/tests/heartbeat.test.ts +363 -0
  455. package/src/tests/http-api-integration.test.ts +1698 -0
  456. package/src/tests/linear-outbound-sync.test.ts +200 -0
  457. package/src/tests/linear-webhook.test.ts +402 -0
  458. package/src/tests/match-route.test.ts +187 -0
  459. package/src/tests/memory.test.ts +737 -0
  460. package/src/tests/migration-runner-regressions.test.ts +86 -0
  461. package/src/tests/model-control.test.ts +338 -0
  462. package/src/tests/oauth-wrapper.test.ts +147 -0
  463. package/src/tests/onboard-compose.test.ts +138 -0
  464. package/src/tests/onboard-env.test.ts +174 -0
  465. package/src/tests/onboard-manifest.test.ts +137 -0
  466. package/src/tests/pi-mono-adapter.test.ts +234 -0
  467. package/src/tests/progress-dedup.test.ts +98 -0
  468. package/src/tests/provider-adapter.test.ts +122 -0
  469. package/src/tests/provider-command-format.test.ts +98 -0
  470. package/src/tests/reload-config.test.ts +170 -0
  471. package/src/tests/rest-api.test.ts +91 -13
  472. package/src/tests/runner-polling-api.test.ts +108 -31
  473. package/src/tests/scheduled-tasks-api.test.ts +352 -0
  474. package/src/tests/scheduled-tasks.test.ts +605 -0
  475. package/src/tests/scheduler-backoff.test.ts +166 -0
  476. package/src/tests/self-improvement.test.ts +540 -0
  477. package/src/tests/session-attach.test.ts +536 -0
  478. package/src/tests/session-costs.test.ts +991 -0
  479. package/src/tests/slack-actions.test.ts +133 -0
  480. package/src/tests/slack-assistant.test.ts +136 -0
  481. package/src/tests/slack-blocks.test.ts +246 -0
  482. package/src/tests/slack-metadata-inheritance.test.ts +243 -0
  483. package/src/tests/slack-queue-offline.test.ts +174 -0
  484. package/src/tests/slack-router.test.ts +181 -0
  485. package/src/tests/slack-thread-buffer.test.ts +305 -0
  486. package/src/tests/slack-thread-followups.test.ts +298 -0
  487. package/src/tests/slack-watcher.test.ts +101 -0
  488. package/src/tests/store-progress-cost.test.ts +209 -0
  489. package/src/tests/structured-output.test.ts +311 -0
  490. package/src/tests/swarm-repos.test.ts +198 -0
  491. package/src/tests/task-cancellation.test.ts +513 -0
  492. package/src/tests/task-pause-resume.test.ts +737 -0
  493. package/src/tests/task-working-dir.test.ts +176 -0
  494. package/src/tests/template-fetch.test.ts +490 -0
  495. package/src/tests/tool-annotations.test.ts +371 -0
  496. package/src/tests/tracker-tools.test.ts +184 -0
  497. package/src/tests/trigger-claiming.test.ts +631 -0
  498. package/src/tests/update-profile-api.test.ts +701 -0
  499. package/src/tests/validation-adapters.test.ts +86 -0
  500. package/src/tests/vcs-provider.test.ts +27 -0
  501. package/src/tests/workflow-agent-task.test.ts +196 -0
  502. package/src/tests/workflow-async-v2.test.ts +386 -0
  503. package/src/tests/workflow-convergence.test.ts +541 -0
  504. package/src/tests/workflow-definition-validation.test.ts +290 -0
  505. package/src/tests/workflow-engine-v2.test.ts +691 -0
  506. package/src/tests/workflow-executors.test.ts +736 -0
  507. package/src/tests/workflow-http-v2.test.ts +599 -0
  508. package/src/tests/workflow-integration-io.test.ts +902 -0
  509. package/src/tests/workflow-io-schemas.test.ts +624 -0
  510. package/src/tests/workflow-registry.test.ts +592 -0
  511. package/src/tests/workflow-retry-v2.test.ts +401 -0
  512. package/src/tests/workflow-retry-validation.test.ts +282 -0
  513. package/src/tests/workflow-template.test.ts +288 -0
  514. package/src/tests/workflow-trigger-schema.test.ts +359 -0
  515. package/src/tests/workflow-triggers-v2.test.ts +264 -0
  516. package/src/tests/workflow-versions.test.ts +208 -0
  517. package/src/tests/x402-client.test.ts +117 -0
  518. package/src/tests/x402-config.test.ts +182 -0
  519. package/src/tests/x402-spending-tracker.test.ts +185 -0
  520. package/src/tools/cancel-task.ts +113 -0
  521. package/src/tools/context-diff.ts +171 -0
  522. package/src/tools/context-history.ts +138 -0
  523. package/src/tools/create-channel.ts +2 -0
  524. package/src/tools/db-query.ts +78 -0
  525. package/src/tools/delete-channel.ts +132 -0
  526. package/src/tools/epics/assign-task-to-epic.ts +129 -0
  527. package/src/tools/epics/create-epic.ts +112 -0
  528. package/src/tools/epics/delete-epic.ts +121 -0
  529. package/src/tools/epics/get-epic-details.ts +92 -0
  530. package/src/tools/epics/index.ts +7 -0
  531. package/src/tools/epics/list-epics.ts +85 -0
  532. package/src/tools/epics/unassign-task-from-epic.ts +109 -0
  533. package/src/tools/epics/update-epic.ts +174 -0
  534. package/src/tools/get-swarm.ts +3 -0
  535. package/src/tools/get-task-details.ts +3 -0
  536. package/src/tools/get-tasks.ts +36 -1
  537. package/src/tools/inject-learning.ts +106 -0
  538. package/src/tools/join-swarm.ts +33 -10
  539. package/src/tools/list-channels.ts +3 -0
  540. package/src/tools/list-services.ts +3 -0
  541. package/src/tools/memory-get.ts +56 -0
  542. package/src/tools/memory-search.ts +131 -0
  543. package/src/tools/my-agent-info.ts +5 -0
  544. package/src/tools/poll-task.ts +24 -2
  545. package/src/tools/post-message.ts +2 -0
  546. package/src/tools/read-messages.ts +6 -0
  547. package/src/tools/register-agentmail-inbox.ts +166 -0
  548. package/src/tools/register-service.ts +3 -0
  549. package/src/tools/schedules/create-schedule.ts +336 -0
  550. package/src/tools/schedules/delete-schedule.ts +127 -0
  551. package/src/tools/schedules/index.ts +5 -0
  552. package/src/tools/schedules/list-schedules.ts +120 -0
  553. package/src/tools/schedules/run-schedule-now.ts +124 -0
  554. package/src/tools/schedules/update-schedule.ts +275 -0
  555. package/src/tools/send-task.ts +167 -14
  556. package/src/tools/slack-download-file.ts +176 -0
  557. package/src/tools/slack-list-channels.ts +170 -0
  558. package/src/tools/slack-post.ts +105 -0
  559. package/src/tools/slack-read.ts +387 -0
  560. package/src/tools/slack-reply.ts +144 -0
  561. package/src/tools/slack-upload-file.ts +378 -0
  562. package/src/tools/store-progress.ts +231 -10
  563. package/src/tools/swarm-config/delete-config.ts +87 -0
  564. package/src/tools/swarm-config/get-config.ts +108 -0
  565. package/src/tools/swarm-config/index.ts +4 -0
  566. package/src/tools/swarm-config/list-config.ts +99 -0
  567. package/src/tools/swarm-config/set-config.ts +118 -0
  568. package/src/tools/task-action.ts +122 -7
  569. package/src/tools/task-dedup.ts +97 -0
  570. package/src/tools/tool-config.ts +117 -0
  571. package/src/tools/tracker/index.ts +6 -0
  572. package/src/tools/tracker/tracker-link-epic.ts +64 -0
  573. package/src/tools/tracker/tracker-link-task.ts +64 -0
  574. package/src/tools/tracker/tracker-map-agent.ts +57 -0
  575. package/src/tools/tracker/tracker-status.ts +56 -0
  576. package/src/tools/tracker/tracker-sync-status.ts +42 -0
  577. package/src/tools/tracker/tracker-unlink.ts +41 -0
  578. package/src/tools/unregister-service.ts +3 -0
  579. package/src/tools/update-profile.ts +132 -12
  580. package/src/tools/update-service-status.ts +3 -0
  581. package/src/tools/utils.ts +10 -1
  582. package/src/tools/workflows/create-workflow.ts +111 -0
  583. package/src/tools/workflows/delete-workflow.ts +42 -0
  584. package/src/tools/workflows/get-workflow-run.ts +59 -0
  585. package/src/tools/workflows/get-workflow.ts +53 -0
  586. package/src/tools/workflows/index.ts +9 -0
  587. package/src/tools/workflows/list-workflow-runs.ts +48 -0
  588. package/src/tools/workflows/list-workflows.ts +42 -0
  589. package/src/tools/workflows/retry-workflow-run.ts +40 -0
  590. package/src/tools/workflows/trigger-workflow.ts +96 -0
  591. package/src/tools/workflows/update-workflow.ts +118 -0
  592. package/src/tracker/types.ts +51 -0
  593. package/src/types.ts +632 -1
  594. package/src/utils/credentials.test.ts +156 -0
  595. package/src/utils/credentials.ts +50 -0
  596. package/src/utils/error-tracker.ts +190 -0
  597. package/src/vcs/index.ts +15 -0
  598. package/src/vcs/types.ts +5 -0
  599. package/src/workflows/checkpoint.ts +121 -0
  600. package/src/workflows/cooldown.ts +28 -0
  601. package/src/workflows/definition.ts +217 -0
  602. package/src/workflows/engine.ts +554 -0
  603. package/src/workflows/event-bus.ts +29 -0
  604. package/src/workflows/executors/agent-task.ts +92 -0
  605. package/src/workflows/executors/base.ts +86 -0
  606. package/src/workflows/executors/code-match.ts +88 -0
  607. package/src/workflows/executors/index.ts +16 -0
  608. package/src/workflows/executors/notify.ts +93 -0
  609. package/src/workflows/executors/property-match.ts +104 -0
  610. package/src/workflows/executors/raw-llm.ts +83 -0
  611. package/src/workflows/executors/registry.ts +76 -0
  612. package/src/workflows/executors/script.ts +103 -0
  613. package/src/workflows/executors/validate.ts +215 -0
  614. package/src/workflows/executors/vcs.ts +58 -0
  615. package/src/workflows/index.ts +61 -0
  616. package/src/workflows/input.ts +46 -0
  617. package/src/workflows/json-schema-validator.ts +118 -0
  618. package/src/workflows/recovery.ts +139 -0
  619. package/src/workflows/resume.ts +143 -0
  620. package/src/workflows/retry-poller.ts +216 -0
  621. package/src/workflows/template.ts +74 -0
  622. package/src/workflows/templates.ts +86 -0
  623. package/src/workflows/triggers.ts +95 -0
  624. package/src/workflows/validation.ts +104 -0
  625. package/src/workflows/version.ts +42 -0
  626. package/src/x402/cli.ts +140 -0
  627. package/src/x402/client.ts +192 -0
  628. package/src/x402/config.ts +131 -0
  629. package/src/x402/index.ts +37 -0
  630. package/src/x402/openfort-signer.ts +83 -0
  631. package/src/x402/spending-tracker.ts +109 -0
  632. package/templates/community/.gitkeep +0 -0
  633. package/templates/official/coder/CLAUDE.md +49 -0
  634. package/templates/official/coder/IDENTITY.md +28 -0
  635. package/templates/official/coder/SOUL.md +43 -0
  636. package/templates/official/coder/TOOLS.md +40 -0
  637. package/templates/official/coder/config.json +23 -0
  638. package/templates/official/coder/start-up.sh +23 -0
  639. package/templates/official/content-reviewer/CLAUDE.md +68 -0
  640. package/templates/official/content-reviewer/IDENTITY.md +28 -0
  641. package/templates/official/content-reviewer/SOUL.md +44 -0
  642. package/templates/official/content-reviewer/TOOLS.md +37 -0
  643. package/templates/official/content-reviewer/config.json +23 -0
  644. package/templates/official/content-reviewer/start-up.sh +23 -0
  645. package/templates/official/content-strategist/CLAUDE.md +63 -0
  646. package/templates/official/content-strategist/IDENTITY.md +33 -0
  647. package/templates/official/content-strategist/SOUL.md +48 -0
  648. package/templates/official/content-strategist/TOOLS.md +47 -0
  649. package/templates/official/content-strategist/config.json +23 -0
  650. package/templates/official/content-strategist/start-up.sh +23 -0
  651. package/templates/official/content-writer/CLAUDE.md +72 -0
  652. package/templates/official/content-writer/IDENTITY.md +30 -0
  653. package/templates/official/content-writer/SOUL.md +46 -0
  654. package/templates/official/content-writer/TOOLS.md +44 -0
  655. package/templates/official/content-writer/config.json +23 -0
  656. package/templates/official/content-writer/start-up.sh +23 -0
  657. package/templates/official/forward-deployed-engineer/CLAUDE.md +54 -0
  658. package/templates/official/forward-deployed-engineer/IDENTITY.md +37 -0
  659. package/templates/official/forward-deployed-engineer/SOUL.md +55 -0
  660. package/templates/official/forward-deployed-engineer/config.json +21 -0
  661. package/templates/official/lead/CLAUDE.md +33 -0
  662. package/templates/official/lead/IDENTITY.md +36 -0
  663. package/templates/official/lead/SOUL.md +51 -0
  664. package/templates/official/lead/config.json +22 -0
  665. package/templates/official/researcher/CLAUDE.md +46 -0
  666. package/templates/official/researcher/IDENTITY.md +28 -0
  667. package/templates/official/researcher/SOUL.md +43 -0
  668. package/templates/official/researcher/config.json +21 -0
  669. package/templates/official/reviewer/CLAUDE.md +63 -0
  670. package/templates/official/reviewer/IDENTITY.md +28 -0
  671. package/templates/official/reviewer/SOUL.md +45 -0
  672. package/templates/official/reviewer/config.json +21 -0
  673. package/templates/official/tester/CLAUDE.md +53 -0
  674. package/templates/official/tester/IDENTITY.md +28 -0
  675. package/templates/official/tester/SOUL.md +55 -0
  676. package/templates/official/tester/config.json +21 -0
  677. package/templates/schema.ts +35 -0
  678. package/templates-ui/README.md +46 -0
  679. package/templates-ui/components.json +17 -0
  680. package/templates-ui/eslint.config.mjs +18 -0
  681. package/templates-ui/next.config.ts +7 -0
  682. package/templates-ui/package.json +35 -0
  683. package/templates-ui/pnpm-lock.yaml +4571 -0
  684. package/templates-ui/postcss.config.mjs +7 -0
  685. package/templates-ui/public/file.svg +1 -0
  686. package/templates-ui/public/globe.svg +1 -0
  687. package/templates-ui/public/logo.png +0 -0
  688. package/templates-ui/public/next.svg +1 -0
  689. package/templates-ui/public/vercel.svg +1 -0
  690. package/templates-ui/public/window.svg +1 -0
  691. package/templates-ui/src/app/[category]/[name]/page.tsx +89 -0
  692. package/templates-ui/src/app/api/templates/[...slug]/route.ts +52 -0
  693. package/templates-ui/src/app/api/templates/route.ts +18 -0
  694. package/templates-ui/src/app/builder/page.tsx +37 -0
  695. package/templates-ui/src/app/globals.css +94 -0
  696. package/templates-ui/src/app/layout.tsx +79 -0
  697. package/templates-ui/src/app/page.tsx +38 -0
  698. package/templates-ui/src/app/robots.ts +11 -0
  699. package/templates-ui/src/app/sitemap.ts +31 -0
  700. package/templates-ui/src/components/compose-builder.tsx +442 -0
  701. package/templates-ui/src/components/compose-preview.tsx +117 -0
  702. package/templates-ui/src/components/file-preview.tsx +77 -0
  703. package/templates-ui/src/components/footer.tsx +40 -0
  704. package/templates-ui/src/components/header.tsx +41 -0
  705. package/templates-ui/src/components/template-card.tsx +87 -0
  706. package/templates-ui/src/components/template-detail.tsx +125 -0
  707. package/templates-ui/src/components/template-gallery.tsx +263 -0
  708. package/templates-ui/src/components/ui/badge.tsx +36 -0
  709. package/templates-ui/src/components/ui/button.tsx +57 -0
  710. package/templates-ui/src/components/ui/card.tsx +76 -0
  711. package/templates-ui/src/components/ui/separator.tsx +31 -0
  712. package/templates-ui/src/components/ui/tooltip.tsx +32 -0
  713. package/templates-ui/src/lib/compose-generator.ts +241 -0
  714. package/templates-ui/src/lib/templates.ts +137 -0
  715. package/templates-ui/src/lib/utils.ts +6 -0
  716. package/templates-ui/tsconfig.json +34 -0
  717. package/thoughts/research/2026-02-28-openfort-viem-x402-research.md +679 -0
  718. package/thoughts/research/2026-02-28-x402-payments-research.md +686 -0
  719. package/thoughts/researcher/plans/2026-02-20-agent-self-improvement-plan.md +282 -0
  720. package/thoughts/researcher/research/2026-02-20-agent-self-improvement.md +492 -0
  721. package/thoughts/shared/plans/{2025-12-18-inverse-teleport.md → 2026-01-09-inverse-teleport.md} +562 -188
  722. package/thoughts/shared/plans/2026-01-12-agent-rename-pm2-control.md +1133 -0
  723. package/thoughts/shared/plans/2026-01-12-github-app-integration.md +380 -0
  724. package/thoughts/shared/plans/2026-01-12-lead-inbox-model.md +876 -0
  725. package/thoughts/shared/plans/2026-01-12-ralph-wiggum-integration.md +463 -0
  726. package/thoughts/shared/plans/2026-01-13-agent-concurrency.md +691 -0
  727. package/thoughts/shared/plans/2026-01-13-github-assignment-handling.md +690 -0
  728. package/thoughts/shared/plans/2026-01-13-prevent-duplicate-trigger-processing.md +1071 -0
  729. package/thoughts/shared/plans/2026-01-14-fix-slack-thread-context.md +507 -0
  730. package/thoughts/shared/plans/2026-01-15-scheduled-tasks-implementation.md +565 -0
  731. package/thoughts/shared/plans/2026-01-15-usage-cost-tracking-ui.md +1479 -0
  732. package/thoughts/shared/plans/2026-01-16-epics-feature-implementation.md +1230 -0
  733. package/thoughts/shared/plans/2026-02-26-mcp-tool-context-reduction.md +282 -0
  734. package/thoughts/shared/plans/2026-03-02-claude-context-mode-integration.md +328 -0
  735. package/thoughts/shared/plans/2026-03-02-code-level-heartbeat.md +224 -0
  736. package/thoughts/shared/research/2025-01-09-inverse-teleport-plan-review.md +420 -0
  737. package/thoughts/shared/research/2026-01-13-lead-duplicate-trigger-processing.md +223 -0
  738. package/thoughts/shared/research/2026-01-14-lead-slack-thread-context.md +277 -0
  739. package/thoughts/shared/research/2026-01-15-ai-tracker-agent-swarm-integration.md +376 -0
  740. package/thoughts/shared/research/2026-01-15-auto-starting-processes-in-worker-containers.md +787 -0
  741. package/thoughts/shared/research/2026-01-15-scheduled-tasks.md +390 -0
  742. package/thoughts/shared/research/2026-01-16-epics-feature-research.md +437 -0
  743. package/thoughts/shared/research/2026-02-26-cliffy-mcp-tools.md +159 -0
  744. package/thoughts/shared/research/2026-03-03-database-migration-system-refactor.md +337 -0
  745. package/thoughts/swarm-researcher/plans/2026-02-23-openclaw-improvements-plan.md +778 -0
  746. package/thoughts/swarm-researcher/plans/2026-02-26-artifacts-localtunnel-plan.md +1269 -0
  747. package/thoughts/swarm-researcher/research/2026-02-23-openclaw-vs-agent-swarm-comparison.md +411 -0
  748. package/thoughts/swarm-researcher/research/2026-02-26-artifacts-localtunnel.md +724 -0
  749. package/thoughts/taras/brainstorms/2026-03-20-prompt-template-registry.md +443 -0
  750. package/thoughts/taras/brainstorms/2026-03-20-setup-cli-onboarding.md +307 -0
  751. package/thoughts/taras/plans/2026-01-22-agent-swarm-schemas.md +98 -0
  752. package/thoughts/taras/plans/2026-01-28-per-worker-claude-md.md +617 -0
  753. package/thoughts/taras/plans/2026-01-28-sentry-cli-integration.md +214 -0
  754. package/thoughts/taras/plans/2026-02-20-auto-improvement.md +803 -0
  755. package/thoughts/taras/plans/2026-02-20-env-management.md +538 -0
  756. package/thoughts/taras/plans/2026-02-20-memory-system.md +882 -0
  757. package/thoughts/taras/plans/2026-02-20-repos-knowledge.md +806 -0
  758. package/thoughts/taras/plans/2026-02-20-session-attach.md +647 -0
  759. package/thoughts/taras/plans/2026-02-20-worker-identity.md +820 -0
  760. package/thoughts/taras/plans/2026-02-25-feat-new-ui-visual-redesign-plan.md +768 -0
  761. package/thoughts/taras/plans/2026-03-04-fix-buildSystemPrompt-missing-fields.md +77 -0
  762. package/thoughts/taras/plans/2026-03-04-new-ui-missing-actions.md +543 -0
  763. package/thoughts/taras/plans/2026-03-06-one-time-scheduled-tasks.md +373 -0
  764. package/thoughts/taras/plans/2026-03-08-memory-self-improvement-enhancements.md +512 -0
  765. package/thoughts/taras/plans/2026-03-08-pi-mono-provider-implementation.md +919 -0
  766. package/thoughts/taras/plans/2026-03-09-templates-registry.md +723 -0
  767. package/thoughts/taras/plans/2026-03-10-task-working-directory.md +371 -0
  768. package/thoughts/taras/plans/2026-03-11-archil-per-agent-write-strategy.md +621 -0
  769. package/thoughts/taras/plans/2026-03-12-eliminate-inbox-route-to-tasks.md +61 -0
  770. package/thoughts/taras/plans/2026-03-12-slack-thread-followup-additive.md +488 -0
  771. package/thoughts/taras/plans/2026-03-13-slack-ai-improvements.md +644 -0
  772. package/thoughts/taras/plans/2026-03-16-route-wrapper-openapi.md +636 -0
  773. package/thoughts/taras/plans/2026-03-17-multi-api-config.md +444 -0
  774. package/thoughts/taras/plans/2026-03-18-agent-fs-integration.md +591 -0
  775. package/thoughts/taras/plans/2026-03-18-debug-db-explorer.md +446 -0
  776. package/thoughts/taras/plans/2026-03-18-workflow-redesign.md +987 -0
  777. package/thoughts/taras/plans/2026-03-19-compound-learnings.md +403 -0
  778. package/thoughts/taras/plans/2026-03-19-ticket-tracker-linear-integration.md +860 -0
  779. package/thoughts/taras/plans/2026-03-19-workflow-io-schemas-and-bugs.md +899 -0
  780. package/thoughts/taras/plans/2026-03-20-setup-cli-onboarding.md +874 -0
  781. package/thoughts/taras/plans/2026-03-20-workflow-structured-output-validation-workspace.md +723 -0
  782. package/thoughts/taras/research/2026-01-22-vercel-cli-integration.md +287 -0
  783. package/thoughts/taras/research/2026-01-27-excessive-polling-issue.md +311 -0
  784. package/thoughts/taras/research/2026-01-28-per-worker-claude-md.md +383 -0
  785. package/thoughts/taras/research/2026-01-28-sentry-cli-integration.md +240 -0
  786. package/thoughts/taras/research/2026-02-19-agent-native-swarm-architecture.md +390 -0
  787. package/thoughts/taras/research/2026-02-19-swarm-gaps-implementation.md +594 -0
  788. package/thoughts/taras/research/2026-02-25-dashboard-ui-design-best-practices.md +825 -0
  789. package/thoughts/taras/research/2026-02-26-task-detail-page-redesign.md +393 -0
  790. package/thoughts/taras/research/2026-03-03-new-ui-missing-actions.md +168 -0
  791. package/thoughts/taras/research/2026-03-05-pi-mono-provider-research.md +230 -0
  792. package/thoughts/taras/research/2026-03-06-workflow-engine-design.md +445 -0
  793. package/thoughts/taras/research/2026-03-08-drive-loop-concept.md +375 -0
  794. package/thoughts/taras/research/2026-03-08-pi-mono-deep-dive.md +869 -0
  795. package/thoughts/taras/research/2026-03-09-templates-registry.md +373 -0
  796. package/thoughts/taras/research/2026-03-10-agent-working-directory.md +223 -0
  797. package/thoughts/taras/research/2026-03-10-configurable-event-prompts.md +339 -0
  798. package/thoughts/taras/research/2026-03-11-archil-production-setup.md +181 -0
  799. package/thoughts/taras/research/2026-03-11-archil-shared-disk-write-strategies.md +437 -0
  800. package/thoughts/taras/research/2026-03-13-slack-ai-features.md +258 -0
  801. package/thoughts/taras/research/2026-03-16-openapi-docs-generation.md +335 -0
  802. package/thoughts/taras/research/2026-03-16-route-wrapper-openapi.md +670 -0
  803. package/thoughts/taras/research/2026-03-16-slack-thread-followups-e2e.md +54 -0
  804. package/thoughts/taras/research/2026-03-18-agent-fs-integration.md +558 -0
  805. package/thoughts/taras/research/2026-03-18-linear-integration-finalization.md +526 -0
  806. package/thoughts/taras/research/2026-03-18-workflow-redesign.md +797 -0
  807. package/thoughts/taras/research/2026-03-19-workflow-node-io-schemas-and-bugs.md +563 -0
  808. package/thoughts/taras/research/2026-03-19-workflow-structured-output-validation-workspace.md +486 -0
  809. package/thoughts/taras/research/2026-03-20-prompt-template-registry.md +469 -0
  810. package/tsconfig.json +1 -1
  811. package/FAQ.md +0 -19
  812. package/plugin/.claude-plugin/plugin.json +0 -13
  813. package/plugin/commands/create-plan.md +0 -415
  814. package/plugin/commands/implement-plan.md +0 -89
  815. package/plugin/commands/research.md +0 -200
  816. package/ui/bun.lock +0 -692
  817. package/ui/index.html +0 -22
  818. package/ui/package.json +0 -32
  819. package/ui/pnpm-lock.yaml +0 -3034
  820. package/ui/postcss.config.js +0 -6
  821. package/ui/src/App.tsx +0 -43
  822. package/ui/src/components/ActivityFeed.tsx +0 -415
  823. package/ui/src/components/AgentDetailPanel.tsx +0 -534
  824. package/ui/src/components/AgentsPanel.tsx +0 -549
  825. package/ui/src/components/ChatPanel.tsx +0 -1820
  826. package/ui/src/components/ConfigModal.tsx +0 -232
  827. package/ui/src/components/Dashboard.tsx +0 -534
  828. package/ui/src/components/Header.tsx +0 -168
  829. package/ui/src/components/ServicesPanel.tsx +0 -612
  830. package/ui/src/components/SessionLogPanel.tsx +0 -433
  831. package/ui/src/components/StatsBar.tsx +0 -288
  832. package/ui/src/components/StatusBadge.tsx +0 -124
  833. package/ui/src/components/TaskDetailPanel.tsx +0 -827
  834. package/ui/src/components/TasksPanel.tsx +0 -575
  835. package/ui/src/hooks/queries.ts +0 -179
  836. package/ui/src/index.css +0 -235
  837. package/ui/src/lib/api.ts +0 -171
  838. package/ui/src/lib/config.ts +0 -35
  839. package/ui/src/lib/theme.ts +0 -214
  840. package/ui/src/lib/utils.ts +0 -48
  841. package/ui/src/main.tsx +0 -32
  842. package/ui/src/types/api.ts +0 -179
  843. package/ui/src/vite-env.d.ts +0 -1
  844. package/ui/tailwind.config.js +0 -35
  845. package/ui/vite.config.ts +0 -22
  846. /package/{ui → docs-site}/public/logo.png +0 -0
@@ -0,0 +1,554 @@
1
+ import {
2
+ createWorkflowRun,
3
+ createWorkflowRunStep,
4
+ getCompletedStepNodeIds,
5
+ getStepByIdempotencyKey,
6
+ getWorkflowRun,
7
+ getWorkflowRunStepsByRunId,
8
+ updateWorkflowRun,
9
+ updateWorkflowRunStep,
10
+ } from "../be/db";
11
+ import type { Workflow, WorkflowDefinition, WorkflowNode } from "../types";
12
+ import { checkpointStep, checkpointStepFailure, checkpointStepWaiting } from "./checkpoint";
13
+ import { shouldSkipCooldown } from "./cooldown";
14
+ import { findEntryNodes, getSuccessors } from "./definition";
15
+ import type { AsyncExecutorResult } from "./executors/base";
16
+ import type { ExecutorRegistry } from "./executors/registry";
17
+ import { resolveInputs } from "./input";
18
+ import { validateJsonSchema } from "./json-schema-validator";
19
+ import { deepInterpolate } from "./template";
20
+ import { runStepValidation } from "./validation";
21
+
22
+ const DEFAULT_TIMEOUT_MS = 30_000;
23
+ const MAX_ITERATIONS = Number(process.env.WORKFLOW_MAX_ITERATIONS) || 100;
24
+
25
+ /**
26
+ * Error thrown when trigger data fails validation against a workflow's triggerSchema.
27
+ */
28
+ export class TriggerSchemaError extends Error {
29
+ constructor(public readonly validationErrors: string[]) {
30
+ super(`Trigger schema validation failed: ${validationErrors.join("; ")}`);
31
+ this.name = "TriggerSchemaError";
32
+ }
33
+ }
34
+
35
+ // ─── Public API ────────────────────────────────────────────
36
+
37
+ /**
38
+ * Start executing a workflow from scratch.
39
+ *
40
+ * 1. Check cooldown
41
+ * 2. Create workflow run
42
+ * 3. Resolve inputs
43
+ * 4. Find entry nodes
44
+ * 5. Walk the graph
45
+ */
46
+ export async function startWorkflowExecution(
47
+ workflow: Workflow,
48
+ triggerData: unknown,
49
+ registry: ExecutorRegistry,
50
+ ): Promise<string> {
51
+ // Validate trigger data against triggerSchema (before any DB writes)
52
+ if (workflow.triggerSchema) {
53
+ const validationErrors = validateJsonSchema(workflow.triggerSchema, triggerData);
54
+ if (validationErrors.length > 0) {
55
+ throw new TriggerSchemaError(validationErrors);
56
+ }
57
+ }
58
+
59
+ // Cooldown check
60
+ if (workflow.cooldown && shouldSkipCooldown(workflow.id, workflow.cooldown)) {
61
+ const runId = crypto.randomUUID();
62
+ createWorkflowRun({ id: runId, workflowId: workflow.id, triggerData });
63
+ updateWorkflowRun(runId, {
64
+ status: "skipped",
65
+ error: "cooldown",
66
+ finishedAt: new Date().toISOString(),
67
+ });
68
+ return runId;
69
+ }
70
+
71
+ const runId = crypto.randomUUID();
72
+ createWorkflowRun({ id: runId, workflowId: workflow.id, triggerData });
73
+
74
+ // Resolve inputs and merge into initial context
75
+ const ctx: Record<string, unknown> = { trigger: triggerData };
76
+ if (workflow.input) {
77
+ try {
78
+ const resolved = resolveInputs(workflow.input);
79
+ Object.assign(ctx, { input: resolved });
80
+ } catch (err) {
81
+ updateWorkflowRun(runId, {
82
+ status: "failed",
83
+ error: `Input resolution failed: ${err}`,
84
+ finishedAt: new Date().toISOString(),
85
+ });
86
+ return runId;
87
+ }
88
+ }
89
+
90
+ const entryNodes = findEntryNodes(workflow.definition);
91
+ await walkGraph(workflow.definition, runId, ctx, entryNodes, registry, workflow.id);
92
+ return runId;
93
+ }
94
+
95
+ // ─── Graph Walker ──────────────────────────────────────────
96
+
97
+ /**
98
+ * Step execution result — includes the successors to queue next.
99
+ */
100
+ interface StepResult {
101
+ outcome: "completed" | "waiting" | "failed";
102
+ successors: WorkflowNode[];
103
+ }
104
+
105
+ /**
106
+ * Event-loop style graph walker.
107
+ *
108
+ * Executes start nodes, collects successor nodes from each completed step's
109
+ * port-based routing, deduplicates convergence nodes (waiting for all
110
+ * predecessors), then executes the next batch. Repeats until done.
111
+ */
112
+ export async function walkGraph(
113
+ def: WorkflowDefinition,
114
+ runId: string,
115
+ ctx: Record<string, unknown>,
116
+ startNodes: WorkflowNode[],
117
+ registry: ExecutorRegistry,
118
+ workflowId?: string,
119
+ ): Promise<void> {
120
+ let nodeExecutionCount = 0;
121
+ const completedNodeIds = new Set(getCompletedStepNodeIds(runId));
122
+
123
+ // Track active edges: "sourceId→targetId" — only edges on actually-taken
124
+ // execution paths, not all structural edges in the definition.
125
+ const activeEdges = new Set<string>();
126
+
127
+ // For memoized re-walks, inject stored outputs into context and
128
+ // reconstruct active edges from completed steps' stored nextPort.
129
+ if (completedNodeIds.size > 0) {
130
+ for (const nodeId of completedNodeIds) {
131
+ const key = `${runId}:${nodeId}`;
132
+ const step = getStepByIdempotencyKey(key);
133
+ if (step?.output !== undefined) {
134
+ // Bug 5 fix: Validate stored output against executor schema on recovery
135
+ const node = def.nodes.find((n) => n.id === nodeId);
136
+ if (node && registry.has(node.type)) {
137
+ const executor = registry.get(node.type);
138
+ const parseResult = executor.outputSchema.safeParse(step.output);
139
+ if (!parseResult.success) {
140
+ console.warn(
141
+ `[workflow] Recovery: step ${nodeId} output failed validation: ${parseResult.error.message}`,
142
+ );
143
+ continue; // Skip corrupted output
144
+ }
145
+ }
146
+ ctx[nodeId] = step.output;
147
+ }
148
+ // Reconstruct active edges from the stored nextPort.
149
+ // If nextPort is set, use it for port-specific routing.
150
+ // If not set, get all successors (fan-out).
151
+ const successors = step?.nextPort
152
+ ? getSuccessors(def, nodeId, step.nextPort)
153
+ : getSuccessors(def, nodeId);
154
+ for (const succ of successors) {
155
+ activeEdges.add(`${nodeId}→${succ.id}`);
156
+ }
157
+ }
158
+ }
159
+
160
+ // Seed with start nodes that haven't been completed yet
161
+ let pendingNodes = startNodes.filter((n) => !completedNodeIds.has(n.id));
162
+
163
+ while (pendingNodes.length > 0) {
164
+ nodeExecutionCount += pendingNodes.length;
165
+ if (nodeExecutionCount > MAX_ITERATIONS) {
166
+ updateWorkflowRun(runId, {
167
+ status: "failed",
168
+ error: `Max node executions (${MAX_ITERATIONS}) exceeded — possible infinite loop`,
169
+ finishedAt: new Date().toISOString(),
170
+ });
171
+ return;
172
+ }
173
+
174
+ // Execute all pending nodes in parallel
175
+ const results = await Promise.all(
176
+ pendingNodes.map((node) =>
177
+ executeStep(def, runId, ctx, node, registry, workflowId).catch(
178
+ (_err): StepResult => ({
179
+ outcome: "failed",
180
+ successors: [],
181
+ }),
182
+ ),
183
+ ),
184
+ );
185
+
186
+ // Collect successors and check for errors/pauses
187
+ const nextBatch = new Map<string, WorkflowNode>();
188
+ let hasWaiting = false;
189
+ let hasFailed = false;
190
+
191
+ for (let i = 0; i < results.length; i++) {
192
+ const result = results[i]!;
193
+ if (result.outcome === "failed") {
194
+ hasFailed = true;
195
+ break;
196
+ }
197
+ if (result.outcome === "waiting") {
198
+ hasWaiting = true;
199
+ continue;
200
+ }
201
+ // Mark this node as completed
202
+ const sourceNodeId = pendingNodes[i]!.id;
203
+ completedNodeIds.add(sourceNodeId);
204
+ // Record active edges and queue successors
205
+ for (const succ of result.successors) {
206
+ activeEdges.add(`${sourceNodeId}→${succ.id}`);
207
+ nextBatch.set(succ.id, succ);
208
+ }
209
+ }
210
+
211
+ if (hasFailed) return; // Run already marked failed in executeStep
212
+ if (hasWaiting) return; // Run paused, will be resumed by event
213
+
214
+ // Convergence check — only wait for predecessors with active edges to
215
+ // this node, not all structural predecessors. This prevents deadlocks
216
+ // when conditional branches skip nodes.
217
+ const readyNext: WorkflowNode[] = [];
218
+ for (const [nodeId, node] of nextBatch) {
219
+ if (completedNodeIds.has(nodeId)) continue; // Already done
220
+
221
+ const allPreds = getAllPredecessors(def, nodeId);
222
+ const activePreds = allPreds.filter((predId) => activeEdges.has(`${predId}→${nodeId}`));
223
+ const allActivePredsCompleted = activePreds.every((p) => completedNodeIds.has(p));
224
+
225
+ if (allActivePredsCompleted) {
226
+ readyNext.push(node);
227
+ }
228
+ }
229
+
230
+ pendingNodes = readyNext;
231
+ }
232
+
233
+ // No more nodes to execute — check if the run should be completed.
234
+ // If any step has a pending retry (failed with nextRetryAt), the run
235
+ // should stay in "running" state for the retry poller to pick up.
236
+ const run = getWorkflowRun(runId);
237
+ if (run && run.status === "running") {
238
+ const allSteps = getWorkflowRunStepsByRunId(runId);
239
+ const hasPendingRetries = allSteps.some((s) => s.status === "failed" && s.nextRetryAt != null);
240
+
241
+ if (!hasPendingRetries) {
242
+ updateWorkflowRun(runId, {
243
+ status: "completed",
244
+ context: ctx,
245
+ finishedAt: new Date().toISOString(),
246
+ });
247
+ }
248
+ }
249
+ }
250
+
251
+ /**
252
+ * Get all predecessor node IDs for a given node.
253
+ * A predecessor is any node that references this node via its `next` field.
254
+ */
255
+ function getAllPredecessors(def: WorkflowDefinition, nodeId: string): string[] {
256
+ const preds: string[] = [];
257
+ for (const node of def.nodes) {
258
+ if (!node.next) continue;
259
+ const targets = typeof node.next === "string" ? [node.next] : Object.values(node.next);
260
+ if (targets.includes(nodeId)) {
261
+ preds.push(node.id);
262
+ }
263
+ }
264
+ return preds;
265
+ }
266
+
267
+ // ─── Step Execution ────────────────────────────────────────
268
+
269
+ /**
270
+ * Execute a single node step:
271
+ * 1. Check memoization (idempotency)
272
+ * 2. Create step record
273
+ * 3. Interpolate config
274
+ * 4. Run executor with timeout
275
+ * 5. Handle result (checkpoint, validation, or async)
276
+ *
277
+ * Returns the outcome and list of successor nodes to queue.
278
+ */
279
+ async function executeStep(
280
+ def: WorkflowDefinition,
281
+ runId: string,
282
+ ctx: Record<string, unknown>,
283
+ node: WorkflowNode,
284
+ registry: ExecutorRegistry,
285
+ workflowId?: string,
286
+ ): Promise<StepResult> {
287
+ const idempotencyKey = `${runId}:${node.id}`;
288
+
289
+ // 1. Memoization check
290
+ const existingStep = getStepByIdempotencyKey(idempotencyKey);
291
+ if (existingStep && existingStep.status === "completed") {
292
+ // Inject stored output into context
293
+ ctx[node.id] = existingStep.output;
294
+ // For memoized steps, return all successors (no port — use default)
295
+ const successors = getSuccessors(def, node.id);
296
+ return { outcome: "completed", successors };
297
+ }
298
+
299
+ // 2. Create step
300
+ const stepId = crypto.randomUUID();
301
+ createWorkflowRunStep({
302
+ id: stepId,
303
+ runId,
304
+ nodeId: node.id,
305
+ nodeType: node.type,
306
+ input: ctx,
307
+ });
308
+
309
+ // Set idempotency key
310
+ updateWorkflowRunStep(stepId, { idempotencyKey });
311
+
312
+ // 3. Get executor
313
+ const executor = registry.get(node.type);
314
+
315
+ // 3b. Build local interpolation context from explicit inputs mapping
316
+ let interpolationCtx: Record<string, unknown>;
317
+ if (node.inputs) {
318
+ interpolationCtx = {};
319
+ // Always include built-in sources
320
+ if (ctx.trigger !== undefined) interpolationCtx.trigger = ctx.trigger;
321
+ if (ctx.input !== undefined) interpolationCtx.input = ctx.input;
322
+ // Resolve declared inputs
323
+ for (const [localName, sourcePath] of Object.entries(node.inputs)) {
324
+ const keys = sourcePath.split(".");
325
+ let value: unknown = ctx;
326
+ for (const key of keys) {
327
+ if (value == null || typeof value !== "object") {
328
+ value = undefined;
329
+ break;
330
+ }
331
+ value = (value as Record<string, unknown>)[key];
332
+ }
333
+ interpolationCtx[localName] = value;
334
+ }
335
+ } else {
336
+ // No inputs declared — only built-in sources available
337
+ interpolationCtx = {};
338
+ if (ctx.trigger !== undefined) interpolationCtx.trigger = ctx.trigger;
339
+ if (ctx.input !== undefined) interpolationCtx.input = ctx.input;
340
+ }
341
+
342
+ // 3c. Validate resolved inputs against inputSchema if defined
343
+ if (node.inputSchema) {
344
+ const inputErrors = validateJsonSchema(
345
+ node.inputSchema as Record<string, unknown>,
346
+ interpolationCtx,
347
+ );
348
+ if (inputErrors.length > 0) {
349
+ const errorMsg = `Input schema validation failed: ${inputErrors.join("; ")}`;
350
+ checkpointStepFailure(runId, stepId, errorMsg, 0);
351
+ throw new Error(errorMsg);
352
+ }
353
+ }
354
+
355
+ // 4. Deep-interpolate config using local context (not global ctx)
356
+ const { value: interpolatedValue, unresolved } = deepInterpolate(node.config, interpolationCtx);
357
+ const interpolatedConfig = interpolatedValue as Record<string, unknown>;
358
+
359
+ if (unresolved.length > 0) {
360
+ console.warn(
361
+ `[workflow] Step ${node.id}: unresolved interpolation tokens: ${unresolved.join(", ")}`,
362
+ );
363
+ updateWorkflowRunStep(stepId, {
364
+ diagnostics: JSON.stringify({ unresolvedTokens: unresolved }),
365
+ });
366
+ }
367
+
368
+ // 5. Execute with timeout
369
+ const meta = {
370
+ runId,
371
+ stepId,
372
+ nodeId: node.id,
373
+ workflowId: workflowId || "",
374
+ dryRun: false,
375
+ };
376
+
377
+ const timeoutMs = DEFAULT_TIMEOUT_MS;
378
+
379
+ let result: Awaited<ReturnType<typeof executor.run>>;
380
+ try {
381
+ result = await Promise.race([
382
+ executor.run({
383
+ config: interpolatedConfig,
384
+ context: ctx,
385
+ meta,
386
+ }),
387
+ timeoutPromise(timeoutMs),
388
+ ]);
389
+ } catch (err) {
390
+ const errorMsg = err instanceof Error ? err.message : String(err);
391
+
392
+ // Apply retry policy if configured
393
+ const retryPolicy = node.retry || executor.retryPolicy;
394
+ const currentRetryCount = existingStep?.retryCount || 0;
395
+ const { shouldRetry } = checkpointStepFailure(
396
+ runId,
397
+ stepId,
398
+ errorMsg,
399
+ currentRetryCount,
400
+ retryPolicy,
401
+ );
402
+
403
+ if (!shouldRetry) {
404
+ throw err; // Will be caught by walkGraph
405
+ }
406
+ // Retry will be handled by the retry poller
407
+ return { outcome: "completed", successors: [] };
408
+ }
409
+
410
+ // 6. Handle result
411
+ if (result.status === "failed") {
412
+ const retryPolicy = node.retry || executor.retryPolicy;
413
+ const currentRetryCount = existingStep?.retryCount || 0;
414
+ const { shouldRetry } = checkpointStepFailure(
415
+ runId,
416
+ stepId,
417
+ result.error || "Executor returned failed status",
418
+ currentRetryCount,
419
+ retryPolicy,
420
+ );
421
+
422
+ if (!shouldRetry) {
423
+ throw new Error(result.error || "Step execution failed");
424
+ }
425
+ return { outcome: "completed", successors: [] }; // Retry handled by poller
426
+ }
427
+
428
+ // Check for async result
429
+ if ("async" in result && (result as AsyncExecutorResult).async) {
430
+ checkpointStepWaiting(runId, stepId, ctx);
431
+ return { outcome: "waiting", successors: [] };
432
+ }
433
+
434
+ // 6b. Validate output against node-level outputSchema if defined
435
+ if (node.outputSchema && result.status === "success") {
436
+ const outputErrors = validateJsonSchema(
437
+ node.outputSchema as Record<string, unknown>,
438
+ result.output,
439
+ );
440
+ if (outputErrors.length > 0) {
441
+ const errorMsg = `Output schema validation failed: ${outputErrors.join("; ")}`;
442
+ checkpointStepFailure(runId, stepId, errorMsg, 0);
443
+ throw new Error(errorMsg);
444
+ }
445
+ }
446
+
447
+ // 7. Run validation if configured
448
+ if (node.validation) {
449
+ const validationResult = await runStepValidation(registry, node, result.output, ctx, meta);
450
+
451
+ if (validationResult.outcome === "halt") {
452
+ const errorMsg = "Validation failed (mustPass)";
453
+ checkpointStepFailure(runId, stepId, errorMsg, 0);
454
+ throw new Error(errorMsg);
455
+ }
456
+
457
+ if (validationResult.outcome === "retry") {
458
+ // Bug 7 fix: Append validation context to history array instead of overwriting
459
+ if (validationResult.retryContext) {
460
+ const historyKey = `${node.id}_validations`;
461
+ const existing = (ctx[historyKey] as unknown[]) || [];
462
+ ctx[historyKey] = [...existing, validationResult.retryContext];
463
+ }
464
+ const retryPolicy = node.validation.retry || node.retry;
465
+ const currentRetryCount = existingStep?.retryCount || 0;
466
+ checkpointStepFailure(
467
+ runId,
468
+ stepId,
469
+ "Validation failed, retrying",
470
+ currentRetryCount,
471
+ retryPolicy,
472
+ );
473
+ return { outcome: "completed", successors: [] }; // Retry handled by poller
474
+ }
475
+ }
476
+
477
+ // 8. Checkpoint success
478
+ checkpointStep(runId, stepId, node.id, result, ctx);
479
+
480
+ // 9. Determine successors based on nextPort
481
+ // If executor returned a specific port, use it. Otherwise, get all successors
482
+ // (fan-out behavior for non-branching nodes with record-based `next`).
483
+ const successors = result.nextPort
484
+ ? getSuccessors(def, node.id, result.nextPort)
485
+ : getSuccessors(def, node.id);
486
+ return { outcome: "completed", successors };
487
+ }
488
+
489
+ // ─── Ready Node Detection ──────────────────────────────────
490
+
491
+ /**
492
+ * Find nodes that are ready to execute (used for recovery/resume).
493
+ * A node is ready when all its predecessors (nodes that reference it via `next`)
494
+ * have been completed.
495
+ *
496
+ * When `activeEdges` is provided, only predecessors with an active edge to the
497
+ * node are considered (prevents deadlocks on conditional branches where some
498
+ * predecessors were never executed).
499
+ */
500
+ export function findReadyNodes(
501
+ def: WorkflowDefinition,
502
+ completedNodeIds: Set<string>,
503
+ activeEdges?: Set<string>,
504
+ ): WorkflowNode[] {
505
+ // Build predecessor map: nodeId -> set of nodes that must complete before it
506
+ const predecessors = new Map<string, Set<string>>();
507
+ for (const node of def.nodes) {
508
+ if (!predecessors.has(node.id)) {
509
+ predecessors.set(node.id, new Set());
510
+ }
511
+ }
512
+
513
+ for (const node of def.nodes) {
514
+ if (!node.next) continue;
515
+ const targets = typeof node.next === "string" ? [node.next] : Object.values(node.next);
516
+ for (const target of targets) {
517
+ if (!predecessors.has(target)) {
518
+ predecessors.set(target, new Set());
519
+ }
520
+ predecessors.get(target)!.add(node.id);
521
+ }
522
+ }
523
+
524
+ // A node is ready if:
525
+ // 1. It hasn't been completed yet
526
+ // 2. All its relevant predecessors are completed
527
+ return def.nodes.filter((node) => {
528
+ if (completedNodeIds.has(node.id)) return false;
529
+ const preds = predecessors.get(node.id);
530
+ if (!preds || preds.size === 0) return true; // Entry node
531
+
532
+ if (activeEdges) {
533
+ // Only consider predecessors with active edges to this node
534
+ const activePreds = [...preds].filter((predId) => activeEdges.has(`${predId}→${node.id}`));
535
+ // If no active edges point here, the node is not reachable yet
536
+ if (activePreds.length === 0) return false;
537
+ return activePreds.every((pred) => completedNodeIds.has(pred));
538
+ }
539
+
540
+ // Fallback: structural predecessors (backward compat)
541
+ for (const pred of preds) {
542
+ if (!completedNodeIds.has(pred)) return false;
543
+ }
544
+ return true;
545
+ });
546
+ }
547
+
548
+ // ─── Helpers ───────────────────────────────────────────────
549
+
550
+ function timeoutPromise(ms: number): Promise<never> {
551
+ return new Promise((_, reject) => {
552
+ setTimeout(() => reject(new Error(`Step timed out after ${ms}ms`)), ms);
553
+ });
554
+ }
@@ -0,0 +1,29 @@
1
+ import { EventEmitter } from "node:events";
2
+
3
+ export interface WorkflowEventBus {
4
+ emit(event: string, data: unknown): void;
5
+ on(event: string, handler: (data: unknown) => void): void;
6
+ off(event: string, handler: (data: unknown) => void): void;
7
+ }
8
+
9
+ export class InProcessEventBus implements WorkflowEventBus {
10
+ private emitter = new EventEmitter();
11
+
12
+ constructor() {
13
+ this.emitter.setMaxListeners(100);
14
+ }
15
+
16
+ emit(event: string, data: unknown): void {
17
+ this.emitter.emit(event, data);
18
+ }
19
+
20
+ on(event: string, handler: (data: unknown) => void): void {
21
+ this.emitter.on(event, handler);
22
+ }
23
+
24
+ off(event: string, handler: (data: unknown) => void): void {
25
+ this.emitter.off(event, handler);
26
+ }
27
+ }
28
+
29
+ export const workflowEventBus: WorkflowEventBus = new InProcessEventBus();
@@ -0,0 +1,92 @@
1
+ import { z } from "zod";
2
+ import type { ExecutorMeta } from "../../types";
3
+ import type { ExecutorResult } from "./base";
4
+ import { BaseExecutor } from "./base";
5
+
6
+ // ─── Config / Output Schemas ────────────────────────────────
7
+
8
+ const AgentTaskConfigSchema = z.object({
9
+ template: z.string(),
10
+ agentId: z.string().uuid().optional(),
11
+ tags: z.array(z.string()).optional(),
12
+ priority: z.number().int().min(0).max(100).optional(),
13
+ offerMode: z.boolean().optional(),
14
+ dir: z.string().min(1).optional(),
15
+ vcsRepo: z.string().min(1).optional(),
16
+ model: z.string().min(1).optional(),
17
+ parentTaskId: z.string().uuid().optional(),
18
+ outputSchema: z.record(z.string(), z.unknown()).optional(),
19
+ });
20
+
21
+ const AgentTaskOutputSchema = z.object({
22
+ taskId: z.string().uuid(),
23
+ taskOutput: z.unknown(),
24
+ });
25
+
26
+ type AgentTaskOutput = z.infer<typeof AgentTaskOutputSchema>;
27
+
28
+ // ─── Executor ───────────────────────────────────────────────
29
+
30
+ export class AgentTaskExecutor extends BaseExecutor<
31
+ typeof AgentTaskConfigSchema,
32
+ typeof AgentTaskOutputSchema
33
+ > {
34
+ readonly type = "agent-task";
35
+ readonly mode = "async" as const;
36
+ readonly configSchema = AgentTaskConfigSchema;
37
+ readonly outputSchema = AgentTaskOutputSchema;
38
+
39
+ protected async execute(
40
+ config: z.infer<typeof AgentTaskConfigSchema>,
41
+ _context: Readonly<Record<string, unknown>>,
42
+ meta: ExecutorMeta,
43
+ ): Promise<ExecutorResult<AgentTaskOutput>> {
44
+ const { db } = this.deps;
45
+
46
+ // 1. Idempotency: check if a task was already created for this step
47
+ const existingTask = db.getTaskByWorkflowRunStepId(meta.stepId);
48
+ if (existingTask) {
49
+ if (existingTask.status === "completed") {
50
+ return {
51
+ status: "success",
52
+ output: {
53
+ taskId: existingTask.id,
54
+ taskOutput: existingTask.output,
55
+ },
56
+ };
57
+ }
58
+ // Task exists but not yet completed — return async marker to keep waiting.
59
+ // The engine detects async results via `"async" in result`.
60
+ return {
61
+ status: "success",
62
+ async: true,
63
+ waitFor: "task.completed",
64
+ correlationId: existingTask.id,
65
+ } as unknown as ExecutorResult<AgentTaskOutput>;
66
+ }
67
+
68
+ // 2. Create the task (config is already deep-interpolated by the engine)
69
+ const task = db.createTaskExtended(config.template, {
70
+ agentId: config.agentId ?? null,
71
+ source: "workflow",
72
+ tags: config.tags,
73
+ priority: config.priority,
74
+ offeredTo: config.offerMode ? config.agentId : undefined,
75
+ workflowRunId: meta.runId,
76
+ workflowRunStepId: meta.stepId,
77
+ dir: config.dir,
78
+ vcsRepo: config.vcsRepo,
79
+ model: config.model,
80
+ parentTaskId: config.parentTaskId,
81
+ outputSchema: config.outputSchema,
82
+ });
83
+
84
+ // 4. Return async result — engine will pause the workflow
85
+ return {
86
+ status: "success",
87
+ async: true,
88
+ waitFor: "task.completed",
89
+ correlationId: task.id,
90
+ } as unknown as ExecutorResult<AgentTaskOutput>;
91
+ }
92
+ }