@desplega.ai/agent-swarm 1.20.0 → 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 (810) hide show
  1. package/.claude/settings.json +84 -0
  2. package/.claude/settings.local.json +3 -1
  3. package/.entire/settings.json +4 -0
  4. package/.env.docker.example +40 -23
  5. package/.env.example +39 -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 +20 -5
  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-setup.ts +103 -34
  17. package/CHANGELOG.md +447 -0
  18. package/CLAUDE.md +422 -5
  19. package/CONTRIBUTING.md +46 -1
  20. package/DEPLOYMENT.md +26 -9
  21. package/Dockerfile +15 -7
  22. package/Dockerfile.worker +99 -67
  23. package/MCP.md +452 -17
  24. package/README.md +271 -169
  25. package/api-entrypoint.sh +56 -0
  26. package/depot.json +1 -0
  27. package/docker-compose.example.yml +194 -3
  28. package/docker-compose.local.yml +119 -0
  29. package/docker-entrypoint.sh +393 -113
  30. package/docs-site/app/api/search/route.ts +4 -0
  31. package/docs-site/app/docs/[[...slug]]/page.tsx +87 -0
  32. package/docs-site/app/docs/layout.tsx +12 -0
  33. package/docs-site/app/globals.css +24 -0
  34. package/docs-site/app/layout.config.tsx +34 -0
  35. package/docs-site/app/layout.tsx +119 -0
  36. package/docs-site/app/llms-full.txt/route.ts +11 -0
  37. package/docs-site/app/llms.mdx/docs/[[...slug]]/route.ts +24 -0
  38. package/docs-site/app/llms.txt/route.ts +8 -0
  39. package/docs-site/app/page.tsx +5 -0
  40. package/docs-site/app/robots.ts +13 -0
  41. package/docs-site/app/sitemap.ts +37 -0
  42. package/docs-site/components/api-page.client.tsx +4 -0
  43. package/docs-site/components/api-page.tsx +7 -0
  44. package/docs-site/components/mdx/mermaid.tsx +55 -0
  45. package/docs-site/content/docs/(documentation)/architecture/agents.mdx +117 -0
  46. package/docs-site/content/docs/(documentation)/architecture/hooks.mdx +77 -0
  47. package/docs-site/content/docs/(documentation)/architecture/memory.mdx +96 -0
  48. package/docs-site/content/docs/(documentation)/architecture/meta.json +4 -0
  49. package/docs-site/content/docs/(documentation)/architecture/overview.mdx +172 -0
  50. package/docs-site/content/docs/(documentation)/concepts/epics.mdx +98 -0
  51. package/docs-site/content/docs/(documentation)/concepts/meta.json +4 -0
  52. package/docs-site/content/docs/(documentation)/concepts/scheduling.mdx +136 -0
  53. package/docs-site/content/docs/(documentation)/concepts/services.mdx +104 -0
  54. package/docs-site/content/docs/(documentation)/concepts/task-lifecycle.mdx +148 -0
  55. package/docs-site/content/docs/(documentation)/concepts/workflows.mdx +209 -0
  56. package/docs-site/content/docs/(documentation)/contributing.mdx +158 -0
  57. package/docs-site/content/docs/(documentation)/getting-started.mdx +157 -0
  58. package/docs-site/content/docs/(documentation)/guides/agentmail-integration.mdx +79 -0
  59. package/docs-site/content/docs/(documentation)/guides/deployment.mdx +171 -0
  60. package/docs-site/content/docs/(documentation)/guides/github-integration.mdx +81 -0
  61. package/docs-site/content/docs/(documentation)/guides/gitlab-integration.mdx +93 -0
  62. package/docs-site/content/docs/(documentation)/guides/linear-integration.mdx +98 -0
  63. package/docs-site/content/docs/(documentation)/guides/meta.json +13 -0
  64. package/docs-site/content/docs/(documentation)/guides/sentry-integration.mdx +52 -0
  65. package/docs-site/content/docs/(documentation)/guides/slack-integration.mdx +179 -0
  66. package/docs-site/content/docs/(documentation)/guides/x402-payments.mdx +154 -0
  67. package/docs-site/content/docs/(documentation)/index.mdx +65 -0
  68. package/docs-site/content/docs/(documentation)/meta.json +19 -0
  69. package/docs-site/content/docs/(documentation)/reference/cli.mdx +241 -0
  70. package/docs-site/content/docs/(documentation)/reference/environment-variables.mdx +205 -0
  71. package/docs-site/content/docs/(documentation)/reference/mcp-tools.mdx +449 -0
  72. package/docs-site/content/docs/(documentation)/reference/meta.json +4 -0
  73. package/docs-site/content/docs/api-reference/active-sessions.mdx +9 -0
  74. package/docs-site/content/docs/api-reference/agents.mdx +9 -0
  75. package/docs-site/content/docs/api-reference/channels.mdx +9 -0
  76. package/docs-site/content/docs/api-reference/config.mdx +9 -0
  77. package/docs-site/content/docs/api-reference/debug.mdx +9 -0
  78. package/docs-site/content/docs/api-reference/ecosystem.mdx +9 -0
  79. package/docs-site/content/docs/api-reference/epics.mdx +9 -0
  80. package/docs-site/content/docs/api-reference/index.mdx +32 -0
  81. package/docs-site/content/docs/api-reference/memory.mdx +9 -0
  82. package/docs-site/content/docs/api-reference/meta.json +25 -0
  83. package/docs-site/content/docs/api-reference/poll.mdx +9 -0
  84. package/docs-site/content/docs/api-reference/repos.mdx +9 -0
  85. package/docs-site/content/docs/api-reference/schedules.mdx +9 -0
  86. package/docs-site/content/docs/api-reference/session-data.mdx +9 -0
  87. package/docs-site/content/docs/api-reference/stats.mdx +9 -0
  88. package/docs-site/content/docs/api-reference/tasks.mdx +9 -0
  89. package/docs-site/content/docs/api-reference/trackers.mdx +9 -0
  90. package/docs-site/content/docs/api-reference/webhooks.mdx +9 -0
  91. package/docs-site/content/docs/api-reference/workflows.mdx +9 -0
  92. package/docs-site/content/docs/meta.json +3 -0
  93. package/docs-site/lib/get-llm-text.ts +10 -0
  94. package/docs-site/lib/openapi.ts +23 -0
  95. package/docs-site/lib/source.ts +8 -0
  96. package/docs-site/mdx-components.tsx +13 -0
  97. package/docs-site/next.config.mjs +29 -0
  98. package/docs-site/package.json +35 -0
  99. package/docs-site/pnpm-lock.yaml +5407 -0
  100. package/docs-site/postcss.config.mjs +8 -0
  101. package/docs-site/scripts/generate-docs.ts +171 -0
  102. package/docs-site/source.config.ts +17 -0
  103. package/docs-site/tsconfig.json +46 -0
  104. package/ecosystem.config.cjs +4 -4
  105. package/landing/next.config.ts +14 -0
  106. package/landing/package.json +31 -0
  107. package/landing/pnpm-lock.yaml +1091 -0
  108. package/landing/postcss.config.mjs +8 -0
  109. package/landing/public/apple-touch-icon.png +0 -0
  110. package/landing/public/favicon.ico +0 -0
  111. package/landing/public/logo.png +0 -0
  112. package/landing/public/og-image.png +0 -0
  113. package/landing/public/omghost-desplega.svg +30 -0
  114. package/landing/public/omghost-openfort.svg +9 -0
  115. package/landing/src/app/actions/waitlist.ts +25 -0
  116. package/landing/src/app/blog/openfort-hackathon/page.tsx +863 -0
  117. package/landing/src/app/blog/page.tsx +162 -0
  118. package/landing/src/app/blog/swarm-metrics/page.tsx +685 -0
  119. package/landing/src/app/examples/page.tsx +174 -0
  120. package/landing/src/app/examples/x402/page.tsx +456 -0
  121. package/landing/src/app/globals.css +122 -0
  122. package/landing/src/app/layout.tsx +134 -0
  123. package/landing/src/app/page.tsx +27 -0
  124. package/landing/src/app/robots.ts +13 -0
  125. package/landing/src/app/sitemap.ts +44 -0
  126. package/landing/src/components/architecture.tsx +163 -0
  127. package/landing/src/components/cta.tsx +52 -0
  128. package/landing/src/components/features.tsx +160 -0
  129. package/landing/src/components/footer.tsx +100 -0
  130. package/landing/src/components/hero.tsx +217 -0
  131. package/landing/src/components/how-it-works.tsx +165 -0
  132. package/landing/src/components/navbar.tsx +147 -0
  133. package/landing/src/components/waitlist.tsx +110 -0
  134. package/landing/src/components/why-choose.tsx +149 -0
  135. package/landing/src/components/workshops.tsx +328 -0
  136. package/landing/src/lib/utils.ts +6 -0
  137. package/landing/tsconfig.json +41 -0
  138. package/misc/transcripts/2026-03-09-pi-mono-e2e-verification.md +154 -0
  139. package/new-ui/CLAUDE.md +92 -0
  140. package/new-ui/README.md +73 -0
  141. package/new-ui/biome.json +42 -0
  142. package/new-ui/components.json +21 -0
  143. package/new-ui/index.html +25 -0
  144. package/new-ui/package.json +49 -0
  145. package/new-ui/pnpm-lock.yaml +4845 -0
  146. package/new-ui/public/logo.png +0 -0
  147. package/new-ui/src/api/client.ts +814 -0
  148. package/new-ui/src/api/hooks/index.ts +64 -0
  149. package/new-ui/src/api/hooks/use-agents.ts +58 -0
  150. package/new-ui/src/api/hooks/use-channels.ts +115 -0
  151. package/new-ui/src/api/hooks/use-config-api.ts +46 -0
  152. package/new-ui/src/api/hooks/use-costs.ts +122 -0
  153. package/new-ui/src/api/hooks/use-db-query.ts +29 -0
  154. package/new-ui/src/api/hooks/use-epics.ts +75 -0
  155. package/new-ui/src/api/hooks/use-repos.ts +61 -0
  156. package/new-ui/src/api/hooks/use-schedules.ts +81 -0
  157. package/new-ui/src/api/hooks/use-services.ts +16 -0
  158. package/new-ui/src/api/hooks/use-stats.ts +27 -0
  159. package/new-ui/src/api/hooks/use-tasks.ts +89 -0
  160. package/new-ui/src/api/hooks/use-workflows.ts +109 -0
  161. package/{ui/src/types/api.ts → new-ui/src/api/types.ts} +236 -10
  162. package/new-ui/src/app/App.tsx +13 -0
  163. package/new-ui/src/app/providers.tsx +32 -0
  164. package/new-ui/src/app/router.tsx +52 -0
  165. package/new-ui/src/components/layout/app-header.tsx +47 -0
  166. package/new-ui/src/components/layout/app-sidebar.tsx +128 -0
  167. package/new-ui/src/components/layout/breadcrumbs.tsx +57 -0
  168. package/new-ui/src/components/layout/config-guard.tsx +22 -0
  169. package/new-ui/src/components/layout/root-layout.tsx +40 -0
  170. package/new-ui/src/components/layout/swarm-switcher.tsx +85 -0
  171. package/new-ui/src/components/shared/command-menu.tsx +131 -0
  172. package/new-ui/src/components/shared/data-grid.tsx +141 -0
  173. package/new-ui/src/components/shared/empty-state.tsx +24 -0
  174. package/new-ui/src/components/shared/error-boundary.tsx +72 -0
  175. package/new-ui/src/components/shared/json-viewer.tsx +47 -0
  176. package/new-ui/src/components/shared/name-connection-modal.tsx +99 -0
  177. package/new-ui/src/components/shared/page-skeleton.tsx +16 -0
  178. package/new-ui/src/components/shared/session-log-viewer.tsx +364 -0
  179. package/new-ui/src/components/shared/stats-bar.tsx +132 -0
  180. package/new-ui/src/components/shared/status-badge.tsx +131 -0
  181. package/new-ui/src/components/shared/usage-summary.tsx +179 -0
  182. package/new-ui/src/components/ui/alert-dialog.tsx +176 -0
  183. package/new-ui/src/components/ui/alert.tsx +60 -0
  184. package/new-ui/src/components/ui/avatar.tsx +96 -0
  185. package/new-ui/src/components/ui/badge.tsx +46 -0
  186. package/new-ui/src/components/ui/button.tsx +62 -0
  187. package/new-ui/src/components/ui/card.tsx +75 -0
  188. package/new-ui/src/components/ui/command.tsx +160 -0
  189. package/new-ui/src/components/ui/dialog.tsx +143 -0
  190. package/new-ui/src/components/ui/dropdown-menu.tsx +226 -0
  191. package/new-ui/src/components/ui/input.tsx +21 -0
  192. package/new-ui/src/components/ui/label.tsx +19 -0
  193. package/new-ui/src/components/ui/progress.tsx +26 -0
  194. package/new-ui/src/components/ui/scroll-area.tsx +54 -0
  195. package/new-ui/src/components/ui/select.tsx +175 -0
  196. package/new-ui/src/components/ui/separator.tsx +28 -0
  197. package/new-ui/src/components/ui/sheet.tsx +132 -0
  198. package/new-ui/src/components/ui/sidebar.tsx +691 -0
  199. package/new-ui/src/components/ui/skeleton.tsx +13 -0
  200. package/new-ui/src/components/ui/sonner.tsx +35 -0
  201. package/new-ui/src/components/ui/switch.tsx +33 -0
  202. package/new-ui/src/components/ui/table.tsx +92 -0
  203. package/new-ui/src/components/ui/tabs.tsx +79 -0
  204. package/new-ui/src/components/ui/textarea.tsx +18 -0
  205. package/new-ui/src/components/ui/tooltip.tsx +51 -0
  206. package/new-ui/src/components/workflows/action-node.tsx +53 -0
  207. package/new-ui/src/components/workflows/condition-node.tsx +50 -0
  208. package/new-ui/src/components/workflows/graph-utils.ts +124 -0
  209. package/new-ui/src/components/workflows/json-tree.tsx +189 -0
  210. package/new-ui/src/components/workflows/node-styles.ts +10 -0
  211. package/new-ui/src/components/workflows/step-detail-sheet.tsx +87 -0
  212. package/new-ui/src/components/workflows/trigger-node.tsx +41 -0
  213. package/new-ui/src/components/workflows/workflow-graph.tsx +65 -0
  214. package/{ui/src/hooks/useAutoScroll.ts → new-ui/src/hooks/use-auto-scroll.ts} +0 -1
  215. package/new-ui/src/hooks/use-config.ts +203 -0
  216. package/new-ui/src/hooks/use-keyboard-shortcuts.ts +41 -0
  217. package/new-ui/src/hooks/use-mobile.ts +19 -0
  218. package/new-ui/src/hooks/use-theme.ts +60 -0
  219. package/new-ui/src/lib/config.ts +188 -0
  220. package/new-ui/src/lib/slugs.ts +71 -0
  221. package/{ui → new-ui}/src/lib/utils.ts +32 -0
  222. package/new-ui/src/main.tsx +11 -0
  223. package/new-ui/src/pages/agents/[id]/page.tsx +492 -0
  224. package/new-ui/src/pages/agents/page.tsx +134 -0
  225. package/new-ui/src/pages/chat/page.tsx +674 -0
  226. package/new-ui/src/pages/config/page.tsx +1109 -0
  227. package/new-ui/src/pages/dashboard/page.tsx +454 -0
  228. package/new-ui/src/pages/debug/page.tsx +275 -0
  229. package/new-ui/src/pages/epics/[id]/page.tsx +809 -0
  230. package/new-ui/src/pages/epics/page.tsx +321 -0
  231. package/new-ui/src/pages/not-found/page.tsx +18 -0
  232. package/new-ui/src/pages/repos/page.tsx +369 -0
  233. package/new-ui/src/pages/schedules/[id]/page.tsx +664 -0
  234. package/new-ui/src/pages/schedules/page.tsx +477 -0
  235. package/new-ui/src/pages/services/page.tsx +128 -0
  236. package/new-ui/src/pages/tasks/[id]/page.tsx +670 -0
  237. package/new-ui/src/pages/tasks/page.tsx +592 -0
  238. package/new-ui/src/pages/usage/page.tsx +195 -0
  239. package/new-ui/src/pages/workflow-runs/[id]/page.tsx +363 -0
  240. package/new-ui/src/pages/workflows/[id]/page.tsx +417 -0
  241. package/new-ui/src/pages/workflows/page.tsx +266 -0
  242. package/new-ui/src/styles/ag-grid.css +36 -0
  243. package/new-ui/src/styles/globals.css +213 -0
  244. package/new-ui/test-results/.last-run.json +4 -0
  245. package/{ui/tsconfig.json → new-ui/tsconfig.app.json} +7 -4
  246. package/new-ui/tsconfig.json +4 -0
  247. package/new-ui/tsconfig.node.json +26 -0
  248. package/new-ui/vercel.json +4 -0
  249. package/new-ui/vite.config.ts +28 -0
  250. package/openapi.json +4436 -0
  251. package/package.json +31 -7
  252. package/plugin/build-pi-skills.ts +233 -0
  253. package/plugin/commands/close-issue.md +7 -3
  254. package/plugin/commands/create-pr.md +18 -12
  255. package/plugin/commands/implement-issue.md +7 -3
  256. package/plugin/commands/respond-github.md +8 -4
  257. package/plugin/commands/review-pr.md +44 -10
  258. package/plugin/commands/start-leader.md +1 -3
  259. package/plugin/commands/start-worker.md +1 -3
  260. package/plugin/commands/work-on-task.md +22 -3
  261. package/plugin/pi-skills/close-issue/SKILL.md +90 -0
  262. package/plugin/pi-skills/create-pr/SKILL.md +99 -0
  263. package/plugin/pi-skills/implement-issue/SKILL.md +135 -0
  264. package/plugin/pi-skills/investigate-sentry-issue/SKILL.md +138 -0
  265. package/plugin/pi-skills/respond-github/SKILL.md +98 -0
  266. package/plugin/pi-skills/review-offered-task/SKILL.md +45 -0
  267. package/plugin/pi-skills/review-pr/SKILL.md +261 -0
  268. package/plugin/pi-skills/start-leader/SKILL.md +121 -0
  269. package/plugin/pi-skills/start-worker/SKILL.md +60 -0
  270. package/plugin/pi-skills/swarm-chat/SKILL.md +82 -0
  271. package/plugin/pi-skills/todos/SKILL.md +66 -0
  272. package/plugin/pi-skills/work-on-task/SKILL.md +65 -0
  273. package/plugin/skills/artifacts/examples/approval-flow.ts +34 -0
  274. package/plugin/skills/artifacts/examples/hono-dashboard.ts +31 -0
  275. package/plugin/skills/artifacts/examples/multi-artifact.ts +20 -0
  276. package/plugin/skills/artifacts/examples/static-report.sh +17 -0
  277. package/plugin/skills/artifacts/skill.md +71 -0
  278. package/prek.toml +75 -0
  279. package/scripts/check-db-boundary.sh +60 -0
  280. package/scripts/e2e-docker-provider.ts +820 -0
  281. package/scripts/e2e-io-schemas-test.ts +807 -0
  282. package/scripts/e2e-provider-test.ts +220 -0
  283. package/scripts/e2e-workflow-redesign.sh +229 -0
  284. package/scripts/e2e-workflow-test.sh +285 -0
  285. package/scripts/e2e-workflow-test.ts +857 -0
  286. package/scripts/generate-openapi.ts +26 -0
  287. package/scripts/measure-tool-tokens.ts +118 -0
  288. package/scripts/x402-e2e-test.ts +195 -0
  289. package/scripts/x402-test-server.ts +236 -0
  290. package/scripts/x402-testnet-e2e.ts +668 -0
  291. package/slack-manifest.json +17 -0
  292. package/src/agentmail/app.ts +65 -0
  293. package/src/agentmail/handlers.ts +207 -0
  294. package/src/agentmail/index.ts +9 -0
  295. package/src/agentmail/types.ts +51 -0
  296. package/src/artifact-sdk/browser-sdk.ts +30 -0
  297. package/src/artifact-sdk/index.ts +2 -0
  298. package/src/artifact-sdk/localtunnel.d.ts +20 -0
  299. package/src/artifact-sdk/port.ts +12 -0
  300. package/src/artifact-sdk/server.ts +156 -0
  301. package/src/artifact-sdk/tunnel.ts +19 -0
  302. package/src/be/chunking.ts +193 -0
  303. package/src/be/db-queries/oauth.ts +90 -0
  304. package/src/be/db-queries/tracker.ts +182 -0
  305. package/src/be/db.ts +2729 -770
  306. package/src/be/embedding.ts +80 -0
  307. package/src/be/migrations/001_initial.sql +409 -0
  308. package/src/be/migrations/002_one_time_schedules.sql +59 -0
  309. package/src/be/migrations/003_workflows.sql +51 -0
  310. package/src/be/migrations/004_workflow_source.sql +81 -0
  311. package/src/be/migrations/005_epic_next_steps.sql +2 -0
  312. package/src/be/migrations/006_vcs_provider.sql +94 -0
  313. package/src/be/migrations/007_task_dir.sql +2 -0
  314. package/src/be/migrations/008_workflow_redesign.sql +85 -0
  315. package/src/be/migrations/009_tracker_integration.sql +144 -0
  316. package/src/be/migrations/010_step_diagnostics.sql +1 -0
  317. package/src/be/migrations/011_step_next_port.sql +1 -0
  318. package/src/be/migrations/012_trigger_schema.sql +1 -0
  319. package/src/be/migrations/013_task_output_schema.sql +2 -0
  320. package/src/be/migrations/runner.ts +188 -0
  321. package/src/cli.tsx +231 -299
  322. package/src/commands/artifact.ts +241 -0
  323. package/src/commands/onboard/compose-generator.ts +169 -0
  324. package/src/commands/onboard/env-generator.ts +79 -0
  325. package/src/commands/onboard/manifest.ts +37 -0
  326. package/src/commands/onboard/presets.ts +85 -0
  327. package/src/commands/onboard/service-names.ts +47 -0
  328. package/src/commands/onboard/steps/core-credentials.tsx +111 -0
  329. package/src/commands/onboard/steps/custom-templates.tsx +168 -0
  330. package/src/commands/onboard/steps/generate.tsx +154 -0
  331. package/src/commands/onboard/steps/harness-credentials.tsx +195 -0
  332. package/src/commands/onboard/steps/harness.tsx +21 -0
  333. package/src/commands/onboard/steps/health-check.tsx +171 -0
  334. package/src/commands/onboard/steps/integration-github.tsx +105 -0
  335. package/src/commands/onboard/steps/integration-gitlab.tsx +79 -0
  336. package/src/commands/onboard/steps/integration-menu.tsx +58 -0
  337. package/src/commands/onboard/steps/integration-sentry.tsx +79 -0
  338. package/src/commands/onboard/steps/integration-slack.tsx +165 -0
  339. package/src/commands/onboard/steps/post-connect.tsx +145 -0
  340. package/src/commands/onboard/steps/post-dashboard.tsx +34 -0
  341. package/src/commands/onboard/steps/post-task.tsx +103 -0
  342. package/src/commands/onboard/steps/prereq-check.tsx +178 -0
  343. package/src/commands/onboard/steps/review.tsx +82 -0
  344. package/src/commands/onboard/steps/start.tsx +97 -0
  345. package/src/commands/onboard/templates.ts +34 -0
  346. package/src/commands/onboard/types.ts +259 -0
  347. package/src/commands/onboard.tsx +425 -0
  348. package/src/commands/runner.ts +1376 -559
  349. package/src/commands/setup.tsx +23 -38
  350. package/src/commands/shared/client-config.ts +41 -0
  351. package/src/github/app.ts +8 -0
  352. package/src/github/handlers.ts +93 -75
  353. package/src/github/index.ts +1 -0
  354. package/src/github/types.ts +1 -0
  355. package/src/gitlab/auth.ts +63 -0
  356. package/src/gitlab/handlers.ts +327 -0
  357. package/src/gitlab/index.ts +19 -0
  358. package/src/gitlab/reactions.ts +104 -0
  359. package/src/gitlab/types.ts +130 -0
  360. package/src/heartbeat/heartbeat.ts +425 -0
  361. package/src/heartbeat/index.ts +1 -0
  362. package/src/hooks/hook.ts +555 -4
  363. package/src/hooks/tool-loop-detection.test.ts +158 -0
  364. package/src/hooks/tool-loop-detection.ts +167 -0
  365. package/src/http/active-sessions.ts +172 -0
  366. package/src/http/agents.ts +328 -0
  367. package/src/http/config.ts +191 -0
  368. package/src/http/core.ts +309 -0
  369. package/src/http/db-query.ts +91 -0
  370. package/src/http/ecosystem.ts +63 -0
  371. package/src/http/epics.ts +460 -0
  372. package/src/http/index.ts +213 -0
  373. package/src/http/mcp.ts +77 -0
  374. package/src/http/memory.ts +168 -0
  375. package/src/http/openapi.ts +109 -0
  376. package/src/http/poll.ts +178 -0
  377. package/src/http/repos.ts +195 -0
  378. package/src/http/route-def.ts +123 -0
  379. package/src/http/schedules.ts +391 -0
  380. package/src/http/session-data.ts +241 -0
  381. package/src/http/stats.ts +174 -0
  382. package/src/http/tasks.ts +468 -0
  383. package/src/http/trackers/index.ts +10 -0
  384. package/src/http/trackers/linear.ts +187 -0
  385. package/src/http/types.ts +12 -0
  386. package/src/http/utils.ts +87 -0
  387. package/src/http/webhooks.ts +432 -0
  388. package/src/http/workflows.ts +522 -0
  389. package/src/http.ts +1 -1890
  390. package/src/linear/README.md +65 -0
  391. package/src/linear/app.ts +48 -0
  392. package/src/linear/client.ts +18 -0
  393. package/src/linear/index.ts +1 -0
  394. package/src/linear/oauth.ts +35 -0
  395. package/src/linear/outbound.ts +212 -0
  396. package/src/linear/sync.ts +543 -0
  397. package/src/linear/types.ts +7 -0
  398. package/src/linear/webhook.ts +104 -0
  399. package/src/oauth/README.md +66 -0
  400. package/src/oauth/index.ts +6 -0
  401. package/src/oauth/wrapper.ts +204 -0
  402. package/src/prompts/base-prompt.ts +366 -24
  403. package/src/prompts/defaults.ts +196 -0
  404. package/src/providers/claude-adapter.ts +429 -0
  405. package/src/providers/index.ts +24 -0
  406. package/src/providers/pi-mono-adapter.ts +442 -0
  407. package/src/providers/pi-mono-extension.ts +620 -0
  408. package/src/providers/pi-mono-mcp-client.ts +124 -0
  409. package/src/providers/types.ts +75 -0
  410. package/src/scheduler/scheduler.test.ts +2 -0
  411. package/src/scheduler/scheduler.ts +186 -29
  412. package/src/server.ts +82 -6
  413. package/src/slack/HEURISTICS.md +105 -0
  414. package/src/slack/actions.ts +133 -0
  415. package/src/slack/app.ts +7 -0
  416. package/src/slack/assistant.ts +115 -0
  417. package/src/slack/blocks.ts +233 -0
  418. package/src/slack/commands.ts +31 -17
  419. package/src/slack/files.ts +1 -1
  420. package/src/slack/handlers.test.ts +114 -1
  421. package/src/slack/handlers.ts +212 -52
  422. package/src/slack/responses.ts +120 -67
  423. package/src/slack/router.ts +17 -99
  424. package/src/slack/thread-buffer.ts +213 -0
  425. package/src/slack/watcher.ts +119 -4
  426. package/src/tests/agent-activity.test.ts +247 -0
  427. package/src/tests/agentmail-filters.test.ts +97 -0
  428. package/src/tests/artifact-sdk.test.ts +800 -0
  429. package/src/tests/base-prompt.test.ts +264 -0
  430. package/src/tests/build-pi-skills.test.ts +127 -0
  431. package/src/tests/claude-adapter.test.ts +126 -0
  432. package/src/tests/context-versioning.test.ts +425 -0
  433. package/src/tests/db-queries-oauth.test.ts +197 -0
  434. package/src/tests/db-queries-tracker.test.ts +230 -0
  435. package/src/tests/epics.test.ts +3 -3
  436. package/src/tests/error-tracker.test.ts +368 -0
  437. package/src/tests/fetch-resolved-env.test.ts +167 -0
  438. package/src/tests/generate-default-claude-md.test.ts +9 -1
  439. package/src/tests/generate-identity-templates.test.ts +124 -0
  440. package/src/tests/gitlab-auth.test.ts +109 -0
  441. package/src/tests/gitlab-handlers.test.ts +691 -0
  442. package/src/tests/gitlab-vcs-db.test.ts +177 -0
  443. package/src/tests/heartbeat.test.ts +363 -0
  444. package/src/tests/http-api-integration.test.ts +1698 -0
  445. package/src/tests/linear-outbound-sync.test.ts +200 -0
  446. package/src/tests/linear-webhook.test.ts +402 -0
  447. package/src/tests/match-route.test.ts +187 -0
  448. package/src/tests/memory.test.ts +737 -0
  449. package/src/tests/migration-runner-regressions.test.ts +86 -0
  450. package/src/tests/model-control.test.ts +338 -0
  451. package/src/tests/oauth-wrapper.test.ts +147 -0
  452. package/src/tests/onboard-compose.test.ts +138 -0
  453. package/src/tests/onboard-env.test.ts +174 -0
  454. package/src/tests/onboard-manifest.test.ts +137 -0
  455. package/src/tests/pi-mono-adapter.test.ts +234 -0
  456. package/src/tests/progress-dedup.test.ts +98 -0
  457. package/src/tests/provider-adapter.test.ts +122 -0
  458. package/src/tests/provider-command-format.test.ts +98 -0
  459. package/src/tests/reload-config.test.ts +170 -0
  460. package/src/tests/runner-polling-api.test.ts +25 -20
  461. package/src/tests/scheduled-tasks.test.ts +104 -0
  462. package/src/tests/scheduler-backoff.test.ts +166 -0
  463. package/src/tests/self-improvement.test.ts +540 -0
  464. package/src/tests/session-attach.test.ts +536 -0
  465. package/src/tests/session-costs.test.ts +267 -1
  466. package/src/tests/slack-actions.test.ts +133 -0
  467. package/src/tests/slack-assistant.test.ts +136 -0
  468. package/src/tests/slack-blocks.test.ts +246 -0
  469. package/src/tests/slack-metadata-inheritance.test.ts +243 -0
  470. package/src/tests/slack-queue-offline.test.ts +174 -0
  471. package/src/tests/slack-router.test.ts +181 -0
  472. package/src/tests/slack-thread-buffer.test.ts +305 -0
  473. package/src/tests/slack-thread-followups.test.ts +298 -0
  474. package/src/tests/slack-watcher.test.ts +101 -0
  475. package/src/tests/structured-output.test.ts +311 -0
  476. package/src/tests/swarm-repos.test.ts +198 -0
  477. package/src/tests/task-cancellation.test.ts +6 -4
  478. package/src/tests/task-working-dir.test.ts +176 -0
  479. package/src/tests/template-fetch.test.ts +490 -0
  480. package/src/tests/tool-annotations.test.ts +371 -0
  481. package/src/tests/tracker-tools.test.ts +184 -0
  482. package/src/tests/update-profile-api.test.ts +143 -3
  483. package/src/tests/validation-adapters.test.ts +86 -0
  484. package/src/tests/vcs-provider.test.ts +27 -0
  485. package/src/tests/workflow-agent-task.test.ts +196 -0
  486. package/src/tests/workflow-async-v2.test.ts +386 -0
  487. package/src/tests/workflow-convergence.test.ts +541 -0
  488. package/src/tests/workflow-definition-validation.test.ts +290 -0
  489. package/src/tests/workflow-engine-v2.test.ts +691 -0
  490. package/src/tests/workflow-executors.test.ts +736 -0
  491. package/src/tests/workflow-http-v2.test.ts +599 -0
  492. package/src/tests/workflow-integration-io.test.ts +902 -0
  493. package/src/tests/workflow-io-schemas.test.ts +624 -0
  494. package/src/tests/workflow-registry.test.ts +592 -0
  495. package/src/tests/workflow-retry-v2.test.ts +401 -0
  496. package/src/tests/workflow-retry-validation.test.ts +282 -0
  497. package/src/tests/workflow-template.test.ts +288 -0
  498. package/src/tests/workflow-trigger-schema.test.ts +359 -0
  499. package/src/tests/workflow-triggers-v2.test.ts +264 -0
  500. package/src/tests/workflow-versions.test.ts +208 -0
  501. package/src/tests/x402-client.test.ts +117 -0
  502. package/src/tests/x402-config.test.ts +182 -0
  503. package/src/tests/x402-spending-tracker.test.ts +185 -0
  504. package/src/tools/cancel-task.ts +2 -0
  505. package/src/tools/context-diff.ts +171 -0
  506. package/src/tools/context-history.ts +138 -0
  507. package/src/tools/create-channel.ts +1 -0
  508. package/src/tools/db-query.ts +78 -0
  509. package/src/tools/delete-channel.ts +132 -0
  510. package/src/tools/epics/assign-task-to-epic.ts +1 -0
  511. package/src/tools/epics/create-epic.ts +3 -2
  512. package/src/tools/epics/delete-epic.ts +2 -0
  513. package/src/tools/epics/get-epic-details.ts +2 -0
  514. package/src/tools/epics/list-epics.ts +2 -0
  515. package/src/tools/epics/unassign-task-from-epic.ts +1 -0
  516. package/src/tools/epics/update-epic.ts +7 -4
  517. package/src/tools/get-swarm.ts +2 -0
  518. package/src/tools/get-task-details.ts +2 -0
  519. package/src/tools/get-tasks.ts +27 -1
  520. package/src/tools/inject-learning.ts +106 -0
  521. package/src/tools/join-swarm.ts +17 -7
  522. package/src/tools/list-channels.ts +2 -0
  523. package/src/tools/list-services.ts +2 -0
  524. package/src/tools/memory-get.ts +56 -0
  525. package/src/tools/memory-search.ts +131 -0
  526. package/src/tools/my-agent-info.ts +2 -0
  527. package/src/tools/poll-task.ts +2 -20
  528. package/src/tools/post-message.ts +1 -0
  529. package/src/tools/read-messages.ts +2 -0
  530. package/src/tools/register-agentmail-inbox.ts +166 -0
  531. package/src/tools/register-service.ts +2 -0
  532. package/src/tools/schedules/create-schedule.ts +134 -24
  533. package/src/tools/schedules/delete-schedule.ts +2 -0
  534. package/src/tools/schedules/list-schedules.ts +20 -4
  535. package/src/tools/schedules/run-schedule-now.ts +1 -0
  536. package/src/tools/schedules/update-schedule.ts +49 -17
  537. package/src/tools/send-task.ts +132 -10
  538. package/src/tools/slack-download-file.ts +4 -2
  539. package/src/tools/slack-list-channels.ts +2 -0
  540. package/src/tools/slack-post.ts +2 -0
  541. package/src/tools/slack-read.ts +2 -0
  542. package/src/tools/slack-reply.ts +2 -0
  543. package/src/tools/slack-upload-file.ts +2 -0
  544. package/src/tools/store-progress.ts +187 -4
  545. package/src/tools/swarm-config/delete-config.ts +87 -0
  546. package/src/tools/swarm-config/get-config.ts +108 -0
  547. package/src/tools/swarm-config/index.ts +4 -0
  548. package/src/tools/swarm-config/list-config.ts +99 -0
  549. package/src/tools/swarm-config/set-config.ts +118 -0
  550. package/src/tools/task-action.ts +30 -5
  551. package/src/tools/task-dedup.ts +97 -0
  552. package/src/tools/tool-config.ts +117 -0
  553. package/src/tools/tracker/index.ts +6 -0
  554. package/src/tools/tracker/tracker-link-epic.ts +64 -0
  555. package/src/tools/tracker/tracker-link-task.ts +64 -0
  556. package/src/tools/tracker/tracker-map-agent.ts +57 -0
  557. package/src/tools/tracker/tracker-status.ts +56 -0
  558. package/src/tools/tracker/tracker-sync-status.ts +42 -0
  559. package/src/tools/tracker/tracker-unlink.ts +41 -0
  560. package/src/tools/unregister-service.ts +2 -0
  561. package/src/tools/update-profile.ts +93 -10
  562. package/src/tools/update-service-status.ts +2 -0
  563. package/src/tools/utils.ts +10 -1
  564. package/src/tools/workflows/create-workflow.ts +111 -0
  565. package/src/tools/workflows/delete-workflow.ts +42 -0
  566. package/src/tools/workflows/get-workflow-run.ts +59 -0
  567. package/src/tools/workflows/get-workflow.ts +53 -0
  568. package/src/tools/workflows/index.ts +9 -0
  569. package/src/tools/workflows/list-workflow-runs.ts +48 -0
  570. package/src/tools/workflows/list-workflows.ts +42 -0
  571. package/src/tools/workflows/retry-workflow-run.ts +40 -0
  572. package/src/tools/workflows/trigger-workflow.ts +96 -0
  573. package/src/tools/workflows/update-workflow.ts +118 -0
  574. package/src/tracker/types.ts +51 -0
  575. package/src/types.ts +477 -14
  576. package/src/utils/credentials.test.ts +156 -0
  577. package/src/utils/credentials.ts +50 -0
  578. package/src/utils/error-tracker.ts +190 -0
  579. package/src/vcs/index.ts +15 -0
  580. package/src/vcs/types.ts +5 -0
  581. package/src/workflows/checkpoint.ts +121 -0
  582. package/src/workflows/cooldown.ts +28 -0
  583. package/src/workflows/definition.ts +217 -0
  584. package/src/workflows/engine.ts +554 -0
  585. package/src/workflows/event-bus.ts +29 -0
  586. package/src/workflows/executors/agent-task.ts +92 -0
  587. package/src/workflows/executors/base.ts +86 -0
  588. package/src/workflows/executors/code-match.ts +88 -0
  589. package/src/workflows/executors/index.ts +16 -0
  590. package/src/workflows/executors/notify.ts +93 -0
  591. package/src/workflows/executors/property-match.ts +104 -0
  592. package/src/workflows/executors/raw-llm.ts +83 -0
  593. package/src/workflows/executors/registry.ts +76 -0
  594. package/src/workflows/executors/script.ts +103 -0
  595. package/src/workflows/executors/validate.ts +215 -0
  596. package/src/workflows/executors/vcs.ts +58 -0
  597. package/src/workflows/index.ts +61 -0
  598. package/src/workflows/input.ts +46 -0
  599. package/src/workflows/json-schema-validator.ts +118 -0
  600. package/src/workflows/recovery.ts +139 -0
  601. package/src/workflows/resume.ts +143 -0
  602. package/src/workflows/retry-poller.ts +216 -0
  603. package/src/workflows/template.ts +74 -0
  604. package/src/workflows/templates.ts +86 -0
  605. package/src/workflows/triggers.ts +95 -0
  606. package/src/workflows/validation.ts +104 -0
  607. package/src/workflows/version.ts +42 -0
  608. package/src/x402/cli.ts +140 -0
  609. package/src/x402/client.ts +192 -0
  610. package/src/x402/config.ts +131 -0
  611. package/src/x402/index.ts +37 -0
  612. package/src/x402/openfort-signer.ts +83 -0
  613. package/src/x402/spending-tracker.ts +109 -0
  614. package/templates/community/.gitkeep +0 -0
  615. package/templates/official/coder/CLAUDE.md +49 -0
  616. package/templates/official/coder/IDENTITY.md +28 -0
  617. package/templates/official/coder/SOUL.md +43 -0
  618. package/templates/official/coder/TOOLS.md +40 -0
  619. package/templates/official/coder/config.json +23 -0
  620. package/templates/official/coder/start-up.sh +23 -0
  621. package/templates/official/content-reviewer/CLAUDE.md +68 -0
  622. package/templates/official/content-reviewer/IDENTITY.md +28 -0
  623. package/templates/official/content-reviewer/SOUL.md +44 -0
  624. package/templates/official/content-reviewer/TOOLS.md +37 -0
  625. package/templates/official/content-reviewer/config.json +23 -0
  626. package/templates/official/content-reviewer/start-up.sh +23 -0
  627. package/templates/official/content-strategist/CLAUDE.md +63 -0
  628. package/templates/official/content-strategist/IDENTITY.md +33 -0
  629. package/templates/official/content-strategist/SOUL.md +48 -0
  630. package/templates/official/content-strategist/TOOLS.md +47 -0
  631. package/templates/official/content-strategist/config.json +23 -0
  632. package/templates/official/content-strategist/start-up.sh +23 -0
  633. package/templates/official/content-writer/CLAUDE.md +72 -0
  634. package/templates/official/content-writer/IDENTITY.md +30 -0
  635. package/templates/official/content-writer/SOUL.md +46 -0
  636. package/templates/official/content-writer/TOOLS.md +44 -0
  637. package/templates/official/content-writer/config.json +23 -0
  638. package/templates/official/content-writer/start-up.sh +23 -0
  639. package/templates/official/forward-deployed-engineer/CLAUDE.md +54 -0
  640. package/templates/official/forward-deployed-engineer/IDENTITY.md +37 -0
  641. package/templates/official/forward-deployed-engineer/SOUL.md +55 -0
  642. package/templates/official/forward-deployed-engineer/config.json +21 -0
  643. package/templates/official/lead/CLAUDE.md +33 -0
  644. package/templates/official/lead/IDENTITY.md +36 -0
  645. package/templates/official/lead/SOUL.md +51 -0
  646. package/templates/official/lead/config.json +22 -0
  647. package/templates/official/researcher/CLAUDE.md +46 -0
  648. package/templates/official/researcher/IDENTITY.md +28 -0
  649. package/templates/official/researcher/SOUL.md +43 -0
  650. package/templates/official/researcher/config.json +21 -0
  651. package/templates/official/reviewer/CLAUDE.md +63 -0
  652. package/templates/official/reviewer/IDENTITY.md +28 -0
  653. package/templates/official/reviewer/SOUL.md +45 -0
  654. package/templates/official/reviewer/config.json +21 -0
  655. package/templates/official/tester/CLAUDE.md +53 -0
  656. package/templates/official/tester/IDENTITY.md +28 -0
  657. package/templates/official/tester/SOUL.md +55 -0
  658. package/templates/official/tester/config.json +21 -0
  659. package/templates/schema.ts +35 -0
  660. package/templates-ui/README.md +46 -0
  661. package/templates-ui/components.json +17 -0
  662. package/templates-ui/eslint.config.mjs +18 -0
  663. package/templates-ui/next.config.ts +7 -0
  664. package/templates-ui/package.json +35 -0
  665. package/templates-ui/pnpm-lock.yaml +4571 -0
  666. package/templates-ui/postcss.config.mjs +7 -0
  667. package/templates-ui/public/file.svg +1 -0
  668. package/templates-ui/public/globe.svg +1 -0
  669. package/templates-ui/public/logo.png +0 -0
  670. package/templates-ui/public/next.svg +1 -0
  671. package/templates-ui/public/vercel.svg +1 -0
  672. package/templates-ui/public/window.svg +1 -0
  673. package/templates-ui/src/app/[category]/[name]/page.tsx +89 -0
  674. package/templates-ui/src/app/api/templates/[...slug]/route.ts +52 -0
  675. package/templates-ui/src/app/api/templates/route.ts +18 -0
  676. package/templates-ui/src/app/builder/page.tsx +37 -0
  677. package/templates-ui/src/app/globals.css +94 -0
  678. package/templates-ui/src/app/layout.tsx +79 -0
  679. package/templates-ui/src/app/page.tsx +38 -0
  680. package/templates-ui/src/app/robots.ts +11 -0
  681. package/templates-ui/src/app/sitemap.ts +31 -0
  682. package/templates-ui/src/components/compose-builder.tsx +442 -0
  683. package/templates-ui/src/components/compose-preview.tsx +117 -0
  684. package/templates-ui/src/components/file-preview.tsx +77 -0
  685. package/templates-ui/src/components/footer.tsx +40 -0
  686. package/templates-ui/src/components/header.tsx +41 -0
  687. package/templates-ui/src/components/template-card.tsx +87 -0
  688. package/templates-ui/src/components/template-detail.tsx +125 -0
  689. package/templates-ui/src/components/template-gallery.tsx +263 -0
  690. package/templates-ui/src/components/ui/badge.tsx +36 -0
  691. package/templates-ui/src/components/ui/button.tsx +57 -0
  692. package/templates-ui/src/components/ui/card.tsx +76 -0
  693. package/templates-ui/src/components/ui/separator.tsx +31 -0
  694. package/templates-ui/src/components/ui/tooltip.tsx +32 -0
  695. package/templates-ui/src/lib/compose-generator.ts +241 -0
  696. package/templates-ui/src/lib/templates.ts +137 -0
  697. package/templates-ui/src/lib/utils.ts +6 -0
  698. package/templates-ui/tsconfig.json +34 -0
  699. package/thoughts/research/2026-02-28-openfort-viem-x402-research.md +679 -0
  700. package/thoughts/research/2026-02-28-x402-payments-research.md +686 -0
  701. package/thoughts/researcher/plans/2026-02-20-agent-self-improvement-plan.md +282 -0
  702. package/thoughts/researcher/research/2026-02-20-agent-self-improvement.md +492 -0
  703. package/thoughts/shared/plans/2026-02-26-mcp-tool-context-reduction.md +282 -0
  704. package/thoughts/shared/plans/2026-03-02-claude-context-mode-integration.md +328 -0
  705. package/thoughts/shared/plans/2026-03-02-code-level-heartbeat.md +224 -0
  706. package/thoughts/shared/research/2026-02-26-cliffy-mcp-tools.md +159 -0
  707. package/thoughts/shared/research/2026-03-03-database-migration-system-refactor.md +337 -0
  708. package/thoughts/swarm-researcher/plans/2026-02-23-openclaw-improvements-plan.md +778 -0
  709. package/thoughts/swarm-researcher/plans/2026-02-26-artifacts-localtunnel-plan.md +1269 -0
  710. package/thoughts/swarm-researcher/research/2026-02-23-openclaw-vs-agent-swarm-comparison.md +411 -0
  711. package/thoughts/swarm-researcher/research/2026-02-26-artifacts-localtunnel.md +724 -0
  712. package/thoughts/taras/brainstorms/2026-03-20-prompt-template-registry.md +443 -0
  713. package/thoughts/taras/brainstorms/2026-03-20-setup-cli-onboarding.md +307 -0
  714. package/thoughts/taras/plans/2026-02-20-auto-improvement.md +803 -0
  715. package/thoughts/taras/plans/2026-02-20-env-management.md +538 -0
  716. package/thoughts/taras/plans/2026-02-20-memory-system.md +882 -0
  717. package/thoughts/taras/plans/2026-02-20-repos-knowledge.md +806 -0
  718. package/thoughts/taras/plans/2026-02-20-session-attach.md +647 -0
  719. package/thoughts/taras/plans/2026-02-20-worker-identity.md +820 -0
  720. package/thoughts/taras/plans/2026-02-25-feat-new-ui-visual-redesign-plan.md +768 -0
  721. package/thoughts/taras/plans/2026-03-04-fix-buildSystemPrompt-missing-fields.md +77 -0
  722. package/thoughts/taras/plans/2026-03-04-new-ui-missing-actions.md +543 -0
  723. package/thoughts/taras/plans/2026-03-06-one-time-scheduled-tasks.md +373 -0
  724. package/thoughts/taras/plans/2026-03-08-memory-self-improvement-enhancements.md +512 -0
  725. package/thoughts/taras/plans/2026-03-08-pi-mono-provider-implementation.md +919 -0
  726. package/thoughts/taras/plans/2026-03-09-templates-registry.md +723 -0
  727. package/thoughts/taras/plans/2026-03-10-task-working-directory.md +371 -0
  728. package/thoughts/taras/plans/2026-03-11-archil-per-agent-write-strategy.md +621 -0
  729. package/thoughts/taras/plans/2026-03-12-eliminate-inbox-route-to-tasks.md +61 -0
  730. package/thoughts/taras/plans/2026-03-12-slack-thread-followup-additive.md +488 -0
  731. package/thoughts/taras/plans/2026-03-13-slack-ai-improvements.md +644 -0
  732. package/thoughts/taras/plans/2026-03-16-route-wrapper-openapi.md +636 -0
  733. package/thoughts/taras/plans/2026-03-17-multi-api-config.md +444 -0
  734. package/thoughts/taras/plans/2026-03-18-agent-fs-integration.md +591 -0
  735. package/thoughts/taras/plans/2026-03-18-debug-db-explorer.md +446 -0
  736. package/thoughts/taras/plans/2026-03-18-workflow-redesign.md +987 -0
  737. package/thoughts/taras/plans/2026-03-19-compound-learnings.md +403 -0
  738. package/thoughts/taras/plans/2026-03-19-ticket-tracker-linear-integration.md +860 -0
  739. package/thoughts/taras/plans/2026-03-19-workflow-io-schemas-and-bugs.md +899 -0
  740. package/thoughts/taras/plans/2026-03-20-setup-cli-onboarding.md +874 -0
  741. package/thoughts/taras/plans/2026-03-20-workflow-structured-output-validation-workspace.md +723 -0
  742. package/thoughts/taras/research/2026-02-19-agent-native-swarm-architecture.md +390 -0
  743. package/thoughts/taras/research/2026-02-19-swarm-gaps-implementation.md +594 -0
  744. package/thoughts/taras/research/2026-02-25-dashboard-ui-design-best-practices.md +825 -0
  745. package/thoughts/taras/research/2026-02-26-task-detail-page-redesign.md +393 -0
  746. package/thoughts/taras/research/2026-03-03-new-ui-missing-actions.md +168 -0
  747. package/thoughts/taras/research/2026-03-05-pi-mono-provider-research.md +230 -0
  748. package/thoughts/taras/research/2026-03-06-workflow-engine-design.md +445 -0
  749. package/thoughts/taras/research/2026-03-08-drive-loop-concept.md +375 -0
  750. package/thoughts/taras/research/2026-03-08-pi-mono-deep-dive.md +869 -0
  751. package/thoughts/taras/research/2026-03-09-templates-registry.md +373 -0
  752. package/thoughts/taras/research/2026-03-10-agent-working-directory.md +223 -0
  753. package/thoughts/taras/research/2026-03-10-configurable-event-prompts.md +339 -0
  754. package/thoughts/taras/research/2026-03-11-archil-production-setup.md +181 -0
  755. package/thoughts/taras/research/2026-03-11-archil-shared-disk-write-strategies.md +437 -0
  756. package/thoughts/taras/research/2026-03-13-slack-ai-features.md +258 -0
  757. package/thoughts/taras/research/2026-03-16-openapi-docs-generation.md +335 -0
  758. package/thoughts/taras/research/2026-03-16-route-wrapper-openapi.md +670 -0
  759. package/thoughts/taras/research/2026-03-16-slack-thread-followups-e2e.md +54 -0
  760. package/thoughts/taras/research/2026-03-18-agent-fs-integration.md +558 -0
  761. package/thoughts/taras/research/2026-03-18-linear-integration-finalization.md +526 -0
  762. package/thoughts/taras/research/2026-03-18-workflow-redesign.md +797 -0
  763. package/thoughts/taras/research/2026-03-19-workflow-node-io-schemas-and-bugs.md +563 -0
  764. package/thoughts/taras/research/2026-03-19-workflow-structured-output-validation-workspace.md +486 -0
  765. package/thoughts/taras/research/2026-03-20-prompt-template-registry.md +469 -0
  766. package/tsconfig.json +1 -1
  767. package/FAQ.md +0 -19
  768. package/src/tests/get-inbox-message.test.ts +0 -145
  769. package/src/tools/get-inbox-message.ts +0 -89
  770. package/src/tools/inbox-delegate.ts +0 -113
  771. package/ui/CLAUDE.md +0 -49
  772. package/ui/bun.lock +0 -771
  773. package/ui/index.html +0 -22
  774. package/ui/package-lock.json +0 -5290
  775. package/ui/package.json +0 -33
  776. package/ui/pnpm-lock.yaml +0 -3341
  777. package/ui/postcss.config.js +0 -6
  778. package/ui/src/App.tsx +0 -63
  779. package/ui/src/components/ActivityFeed.tsx +0 -440
  780. package/ui/src/components/AgentDetailPanel.tsx +0 -733
  781. package/ui/src/components/AgentsPanel.tsx +0 -815
  782. package/ui/src/components/ChatPanel.tsx +0 -1920
  783. package/ui/src/components/ConfigModal.tsx +0 -253
  784. package/ui/src/components/Dashboard.tsx +0 -832
  785. package/ui/src/components/EditAgentProfileModal.tsx +0 -433
  786. package/ui/src/components/EpicDetailPage.tsx +0 -741
  787. package/ui/src/components/EpicsPanel.tsx +0 -566
  788. package/ui/src/components/Header.tsx +0 -160
  789. package/ui/src/components/JsonViewer.tsx +0 -171
  790. package/ui/src/components/ScheduledTaskDetailPanel.tsx +0 -517
  791. package/ui/src/components/ScheduledTasksPanel.tsx +0 -639
  792. package/ui/src/components/ServicesPanel.tsx +0 -622
  793. package/ui/src/components/SessionLogPanel.tsx +0 -1219
  794. package/ui/src/components/StatsBar.tsx +0 -321
  795. package/ui/src/components/StatusBadge.tsx +0 -168
  796. package/ui/src/components/TaskDetailPanel.tsx +0 -903
  797. package/ui/src/components/TasksPanel.tsx +0 -614
  798. package/ui/src/components/UsageCharts.tsx +0 -216
  799. package/ui/src/components/UsageTab.tsx +0 -394
  800. package/ui/src/hooks/queries.ts +0 -353
  801. package/ui/src/index.css +0 -257
  802. package/ui/src/lib/api.ts +0 -268
  803. package/ui/src/lib/config.ts +0 -35
  804. package/ui/src/lib/contentPreview.ts +0 -208
  805. package/ui/src/lib/theme.ts +0 -214
  806. package/ui/src/main.tsx +0 -28
  807. package/ui/src/vite-env.d.ts +0 -1
  808. package/ui/tailwind.config.js +0 -37
  809. package/ui/vite.config.ts +0 -35
  810. /package/{ui → docs-site}/public/logo.png +0 -0
@@ -0,0 +1,807 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * E2E Workflow I/O Schemas Test
4
+ *
5
+ * Spins up the full API server with a clean DB, then exercises:
6
+ * 1. triggerSchema validation (missing, wrong type, valid)
7
+ * 2. Node inputs mapping + data flow between nodes
8
+ * 3. inputSchema validation
9
+ * 4. Unresolved token diagnostics
10
+ * 5. Static data flow validation (non-existent/downstream references)
11
+ * 6. Deep interpolation (nested objects, arrays)
12
+ * 7. Convergence with conditional branches
13
+ * 8. Backward compatibility (no schemas)
14
+ * 9. outputSchema validation
15
+ *
16
+ * Usage:
17
+ * bun scripts/e2e-io-schemas-test.ts
18
+ * E2E_PORT=13098 bun scripts/e2e-io-schemas-test.ts
19
+ */
20
+ import { $, type Subprocess } from "bun";
21
+
22
+ // ─── Config ─────────────────────────────────────────────────────────────────
23
+ const PORT = process.env.E2E_PORT || "13098";
24
+ const API_KEY = process.env.API_KEY || "123123";
25
+ const BASE_URL = `http://localhost:${PORT}`;
26
+ const DB_PATH = `/tmp/e2e-io-schemas-${Date.now()}.sqlite`;
27
+ const AGENT_ID = crypto.randomUUID();
28
+
29
+ // ─── State ──────────────────────────────────────────────────────────────────
30
+ let apiProc: Subprocess | null = null;
31
+ let pass = 0;
32
+ let fail = 0;
33
+ let cleaningUp = false;
34
+
35
+ // ─── Helpers ────────────────────────────────────────────────────────────────
36
+ function log(msg: string) {
37
+ console.log(`\x1b[1;34m[E2E]\x1b[0m ${msg}`);
38
+ }
39
+ function logPass(name: string) {
40
+ console.log(`\x1b[1;32m PASS\x1b[0m ${name}`);
41
+ pass++;
42
+ }
43
+ function logFail(name: string, detail: string) {
44
+ console.log(`\x1b[1;31m FAIL\x1b[0m ${name}: ${detail}`);
45
+ fail++;
46
+ }
47
+
48
+ function assert(condition: boolean, name: string, detail = "") {
49
+ if (condition) logPass(name);
50
+ else logFail(name, detail || "assertion failed");
51
+ }
52
+
53
+ function assertEq(actual: unknown, expected: unknown, name: string) {
54
+ if (actual === expected) logPass(name);
55
+ else logFail(name, `expected '${expected}', got '${actual}'`);
56
+ }
57
+
58
+ async function api<T = unknown>(
59
+ method: string,
60
+ path: string,
61
+ body?: unknown,
62
+ ): Promise<{ status: number; data: T }> {
63
+ const opts: RequestInit = {
64
+ method,
65
+ headers: {
66
+ "Content-Type": "application/json",
67
+ Authorization: `Bearer ${API_KEY}`,
68
+ "X-Agent-ID": AGENT_ID,
69
+ },
70
+ };
71
+ if (body !== undefined) opts.body = JSON.stringify(body);
72
+ const res = await fetch(`${BASE_URL}${path}`, opts);
73
+ let data: T;
74
+ try {
75
+ data = (await res.json()) as T;
76
+ } catch {
77
+ data = null as T;
78
+ }
79
+ return { status: res.status, data };
80
+ }
81
+
82
+ async function waitForServer(url: string, timeoutMs = 30_000): Promise<void> {
83
+ const start = Date.now();
84
+ while (Date.now() - start < timeoutMs) {
85
+ try {
86
+ const res = await fetch(`${url}/api/agents`, {
87
+ headers: { Authorization: `Bearer ${API_KEY}` },
88
+ });
89
+ if (res.ok) return;
90
+ } catch {
91
+ // not ready yet
92
+ }
93
+ await Bun.sleep(500);
94
+ }
95
+ throw new Error(`Server at ${url} did not start within ${timeoutMs}ms`);
96
+ }
97
+
98
+ // ─── Cleanup ────────────────────────────────────────────────────────────────
99
+ async function cleanup() {
100
+ if (cleaningUp) return;
101
+ cleaningUp = true;
102
+ log("Cleaning up...");
103
+
104
+ if (apiProc) {
105
+ try {
106
+ apiProc.kill("SIGTERM");
107
+ await Bun.sleep(1000);
108
+ if (apiProc.exitCode === null) apiProc.kill("SIGKILL");
109
+ } catch {
110
+ // already dead
111
+ }
112
+ apiProc = null;
113
+ }
114
+
115
+ for (const suffix of ["", "-wal", "-shm"]) {
116
+ try {
117
+ await $`rm -f ${DB_PATH}${suffix}`.quiet();
118
+ } catch {
119
+ // fine
120
+ }
121
+ }
122
+
123
+ log("Cleanup complete.");
124
+ }
125
+
126
+ process.on("SIGINT", async () => {
127
+ await cleanup();
128
+ process.exit(fail > 0 ? 1 : 0);
129
+ });
130
+ process.on("SIGTERM", async () => {
131
+ await cleanup();
132
+ process.exit(fail > 0 ? 1 : 0);
133
+ });
134
+
135
+ // ─── Start API ──────────────────────────────────────────────────────────────
136
+ async function startApi() {
137
+ log(`Starting API server on port ${PORT} with DB at ${DB_PATH}...`);
138
+ apiProc = Bun.spawn(["bun", "src/http.ts"], {
139
+ cwd: `${import.meta.dir}/..`,
140
+ env: {
141
+ ...process.env,
142
+ PORT,
143
+ API_KEY,
144
+ DATABASE_PATH: DB_PATH,
145
+ SLACK_DISABLE: "true",
146
+ GITHUB_DISABLE: "true",
147
+ HEARTBEAT_DISABLE: "true",
148
+ AGENTMAIL_DISABLE: "true",
149
+ },
150
+ stdout: "pipe",
151
+ stderr: "pipe",
152
+ });
153
+
154
+ const decoder = new TextDecoder();
155
+ const pipeOutput = async (stream: ReadableStream<Uint8Array>, prefix: string) => {
156
+ const reader = stream.getReader();
157
+ let buffer = "";
158
+ try {
159
+ while (true) {
160
+ const { done, value } = await reader.read();
161
+ if (done) break;
162
+ buffer += decoder.decode(value, { stream: true });
163
+ const lines = buffer.split("\n");
164
+ buffer = lines.pop() || "";
165
+ for (const line of lines) {
166
+ if (line.trim()) console.log(` \x1b[90m${prefix}\x1b[0m ${line}`);
167
+ }
168
+ }
169
+ } catch {
170
+ // stream closed
171
+ }
172
+ };
173
+ pipeOutput(apiProc.stdout, "[API]");
174
+ pipeOutput(apiProc.stderr, "[API]");
175
+
176
+ await waitForServer(BASE_URL);
177
+ log("API server is up.");
178
+ }
179
+
180
+ // ─── Response Types ─────────────────────────────────────────────────────────
181
+ interface WfJson {
182
+ id: string;
183
+ name: string;
184
+ enabled: boolean;
185
+ }
186
+ interface TriggerJson {
187
+ runId: string;
188
+ }
189
+ interface RunJson {
190
+ run: {
191
+ id: string;
192
+ status: string;
193
+ error?: string;
194
+ };
195
+ steps: Array<{
196
+ id: string;
197
+ nodeId: string;
198
+ status: string;
199
+ error?: string;
200
+ output?: unknown;
201
+ diagnostics?: string;
202
+ }>;
203
+ }
204
+
205
+ // ─── Helper: create, trigger, wait, fetch run ───────────────────────────────
206
+ async function createAndTrigger(
207
+ name: string,
208
+ definition: unknown,
209
+ triggerData: unknown,
210
+ extra: Record<string, unknown> = {},
211
+ ): Promise<{ wfId: string; runId: string; run: RunJson }> {
212
+ const { data: wf } = await api<WfJson>("POST", "/api/workflows", {
213
+ name,
214
+ definition,
215
+ ...extra,
216
+ });
217
+ const { status, data: triggerResult } = await api<TriggerJson>(
218
+ "POST",
219
+ `/api/workflows/${wf.id}/trigger`,
220
+ triggerData,
221
+ );
222
+ if (status !== 201) {
223
+ return {
224
+ wfId: wf.id,
225
+ runId: "",
226
+ run: { run: { id: "", status: "trigger_failed", error: `status ${status}` }, steps: [] },
227
+ };
228
+ }
229
+ // Wait for async execution
230
+ await Bun.sleep(2000);
231
+ const { data: run } = await api<RunJson>("GET", `/api/workflow-runs/${triggerResult.runId}`);
232
+ return { wfId: wf.id, runId: triggerResult.runId, run };
233
+ }
234
+
235
+ // ─── Test 1: triggerSchema ──────────────────────────────────────────────────
236
+
237
+ async function testTriggerSchema() {
238
+ log("Test 1: triggerSchema validation");
239
+
240
+ const triggerSchema = {
241
+ type: "object",
242
+ properties: {
243
+ repo: { type: "string" },
244
+ priority: { type: "number" },
245
+ },
246
+ required: ["repo"],
247
+ };
248
+
249
+ const definition = {
250
+ nodes: [
251
+ {
252
+ id: "echo",
253
+ type: "script",
254
+ inputs: { repo: "trigger.repo" },
255
+ config: { runtime: "bash", script: "echo {{repo}}" },
256
+ },
257
+ ],
258
+ };
259
+
260
+ // Create workflow with triggerSchema
261
+ const { data: wf } = await api<WfJson>("POST", "/api/workflows", {
262
+ name: "e2e-trigger-schema",
263
+ definition,
264
+ triggerSchema,
265
+ });
266
+ assert(!!wf.id, "1a. Created workflow with triggerSchema");
267
+
268
+ // Trigger with missing required field "repo" -> 400
269
+ const { status: s1 } = await api("POST", `/api/workflows/${wf.id}/trigger`, {
270
+ priority: 5,
271
+ });
272
+ assertEq(s1, 400, "1b. Trigger with missing repo returns 400");
273
+
274
+ // Trigger with wrong type repo: 123 (number instead of string) -> 400
275
+ const { status: s2 } = await api("POST", `/api/workflows/${wf.id}/trigger`, {
276
+ repo: 123,
277
+ });
278
+ assertEq(s2, 400, "1c. Trigger with repo=123 (wrong type) returns 400");
279
+
280
+ // Trigger with valid payload -> 201
281
+ const { status: s3, data: trigResult } = await api<TriggerJson>(
282
+ "POST",
283
+ `/api/workflows/${wf.id}/trigger`,
284
+ { repo: "my-repo", priority: 3 },
285
+ );
286
+ assertEq(s3, 201, "1d. Trigger with valid payload returns 201");
287
+ assert(typeof trigResult.runId === "string" && trigResult.runId.length > 0, "1e. Got runId");
288
+
289
+ // Wait and verify run executed
290
+ await Bun.sleep(2000);
291
+ const { data: run } = await api<RunJson>("GET", `/api/workflow-runs/${trigResult.runId}`);
292
+ assertEq(run.run.status, "completed", "1f. Valid trigger run completed");
293
+
294
+ // Verify the script output contains the repo value
295
+ const echoStep = run.steps.find((s) => s.nodeId === "echo");
296
+ const echoOutput = echoStep?.output as { stdout?: string } | undefined;
297
+ assert(
298
+ echoOutput?.stdout?.includes("my-repo") ?? false,
299
+ "1g. Script output contains repo value",
300
+ `got stdout: ${echoOutput?.stdout}`,
301
+ );
302
+
303
+ // Cleanup
304
+ await api("DELETE", `/api/workflows/${wf.id}`);
305
+ }
306
+
307
+ // ─── Test 2: Node inputs mapping + data flow ────────────────────────────────
308
+
309
+ async function testInputsMappingDataFlow() {
310
+ log("Test 2: Node inputs mapping + data flow");
311
+
312
+ const definition = {
313
+ nodes: [
314
+ {
315
+ id: "fetch",
316
+ type: "script",
317
+ inputs: { repo: "trigger.repo" },
318
+ config: { runtime: "bash", script: "echo {{repo}}" },
319
+ next: "process",
320
+ },
321
+ {
322
+ id: "process",
323
+ type: "script",
324
+ inputs: { code: "fetch.stdout" },
325
+ config: { runtime: "bash", script: "echo processed: {{code}}" },
326
+ },
327
+ ],
328
+ };
329
+
330
+ const { run, wfId } = await createAndTrigger("e2e-inputs-flow", definition, {
331
+ repo: "agent-swarm",
332
+ });
333
+
334
+ assertEq(run.run.status, "completed", "2a. Data flow run completed");
335
+ assert(run.steps.length >= 2, "2b. Both steps executed");
336
+
337
+ // Check fetch step
338
+ const fetchStep = run.steps.find((s) => s.nodeId === "fetch");
339
+ const fetchOutput = fetchStep?.output as { stdout?: string } | undefined;
340
+ assert(
341
+ fetchOutput?.stdout?.includes("agent-swarm") ?? false,
342
+ "2c. Fetch step output contains trigger value",
343
+ `got stdout: ${fetchOutput?.stdout}`,
344
+ );
345
+
346
+ // Check process step - should contain the fetch output passed through
347
+ const processStep = run.steps.find((s) => s.nodeId === "process");
348
+ const processOutput = processStep?.output as { stdout?: string } | undefined;
349
+ assert(
350
+ processOutput?.stdout?.includes("agent-swarm") ?? false,
351
+ "2d. Process step output contains trigger value passed through fetch",
352
+ `got stdout: ${processOutput?.stdout}`,
353
+ );
354
+ assert(
355
+ processOutput?.stdout?.includes("processed:") ?? false,
356
+ "2e. Process step output has 'processed:' prefix",
357
+ `got stdout: ${processOutput?.stdout}`,
358
+ );
359
+
360
+ await api("DELETE", `/api/workflows/${wfId}`);
361
+ }
362
+
363
+ // ─── Test 3: inputSchema validation ─────────────────────────────────────────
364
+
365
+ async function testInputSchemaValidation() {
366
+ log("Test 3: inputSchema validation");
367
+
368
+ const definition = {
369
+ nodes: [
370
+ {
371
+ id: "greet",
372
+ type: "script",
373
+ inputs: { msg: "trigger.msg" },
374
+ inputSchema: {
375
+ type: "object",
376
+ properties: { msg: { type: "string" } },
377
+ required: ["msg"],
378
+ },
379
+ config: { runtime: "bash", script: "echo {{msg}}" },
380
+ },
381
+ ],
382
+ };
383
+
384
+ // 3a. Trigger with valid input { msg: "hello" } -> success
385
+ const { run: run1, wfId: wfId1 } = await createAndTrigger("e2e-input-schema-valid", definition, {
386
+ msg: "hello",
387
+ });
388
+ assertEq(run1.run.status, "completed", "3a. Valid inputSchema run completed");
389
+ const greetStep1 = run1.steps.find((s) => s.nodeId === "greet");
390
+ const greetOutput1 = greetStep1?.output as { stdout?: string } | undefined;
391
+ assert(
392
+ greetOutput1?.stdout?.includes("hello") ?? false,
393
+ "3b. Valid input produces correct output",
394
+ `got stdout: ${greetOutput1?.stdout}`,
395
+ );
396
+ await api("DELETE", `/api/workflows/${wfId1}`);
397
+
398
+ // 3c. Trigger with wrong type { msg: 123 } -> step should fail
399
+ // The inputSchema checks the interpolation context which includes trigger.msg
400
+ // Since the node has inputs: { msg: "trigger.msg" }, the resolved value will
401
+ // be number 123, and the inputSchema requires msg to be string
402
+ const definitionStrict = {
403
+ nodes: [
404
+ {
405
+ id: "greet",
406
+ type: "script",
407
+ inputs: { msg: "trigger.msg" },
408
+ inputSchema: {
409
+ type: "object",
410
+ properties: { msg: { type: "string" } },
411
+ required: ["msg"],
412
+ },
413
+ config: { runtime: "bash", script: "echo {{msg}}" },
414
+ },
415
+ ],
416
+ };
417
+
418
+ const { run: run2, wfId: wfId2 } = await createAndTrigger(
419
+ "e2e-input-schema-invalid",
420
+ definitionStrict,
421
+ { msg: 123 },
422
+ );
423
+ assertEq(run2.run.status, "failed", "3c. Invalid inputSchema run failed");
424
+ const greetStep2 = run2.steps.find((s) => s.nodeId === "greet");
425
+ assert(
426
+ greetStep2?.status === "failed",
427
+ "3d. Greet step failed on inputSchema violation",
428
+ `got status: ${greetStep2?.status}`,
429
+ );
430
+ assert(
431
+ greetStep2?.error?.includes("Input schema validation failed") ?? false,
432
+ "3e. Error message mentions input schema validation",
433
+ `got error: ${greetStep2?.error}`,
434
+ );
435
+ await api("DELETE", `/api/workflows/${wfId2}`);
436
+ }
437
+
438
+ // ─── Test 4: Unresolved token diagnostics ───────────────────────────────────
439
+
440
+ async function testUnresolvedTokenDiagnostics() {
441
+ log("Test 4: Unresolved token diagnostics");
442
+
443
+ const definition = {
444
+ nodes: [
445
+ {
446
+ id: "echo",
447
+ type: "script",
448
+ inputs: { missing: "trigger.nonexistent" },
449
+ config: { runtime: "bash", script: "echo val={{missing}}" },
450
+ },
451
+ ],
452
+ };
453
+
454
+ const { run, wfId } = await createAndTrigger("e2e-unresolved-tokens", definition, {
455
+ existing: "yes",
456
+ });
457
+
458
+ // The step should still complete (unresolved tokens are warnings, not errors)
459
+ assertEq(run.run.status, "completed", "4a. Run completes despite unresolved tokens");
460
+
461
+ const echoStep = run.steps.find((s) => s.nodeId === "echo");
462
+ assert(echoStep !== undefined, "4b. Echo step exists");
463
+
464
+ // Check diagnostics field contains unresolvedTokens
465
+ if (echoStep?.diagnostics) {
466
+ const diag = JSON.parse(echoStep.diagnostics);
467
+ assert(
468
+ Array.isArray(diag.unresolvedTokens) && diag.unresolvedTokens.length > 0,
469
+ "4c. Diagnostics contains unresolvedTokens",
470
+ `got diagnostics: ${echoStep.diagnostics}`,
471
+ );
472
+ } else {
473
+ // The token "missing" resolves to undefined (trigger.nonexistent doesn't exist),
474
+ // so {{missing}} in the script template would be unresolved
475
+ logFail("4c. Diagnostics contains unresolvedTokens", "diagnostics field is empty/null");
476
+ }
477
+
478
+ await api("DELETE", `/api/workflows/${wfId}`);
479
+ }
480
+
481
+ // ─── Test 5: Static data flow validation ────────────────────────────────────
482
+
483
+ async function testStaticDataFlowValidation() {
484
+ log("Test 5: Static data flow validation");
485
+
486
+ // 5a. Reference a non-existent node -> 400
487
+ const { status: s1, data: d1 } = await api<{ error?: string }>("POST", "/api/workflows", {
488
+ name: "e2e-bad-ref-nonexistent",
489
+ definition: {
490
+ nodes: [
491
+ {
492
+ id: "step1",
493
+ type: "script",
494
+ inputs: { data: "nonexistent_node.output" },
495
+ config: { runtime: "bash", script: "echo {{data}}" },
496
+ },
497
+ ],
498
+ },
499
+ });
500
+ assertEq(s1, 400, "5a. Non-existent node reference returns 400");
501
+ assert(
502
+ typeof d1?.error === "string" && d1.error.includes("non-existent node"),
503
+ "5b. Error message mentions non-existent node",
504
+ `got error: ${d1?.error}`,
505
+ );
506
+
507
+ // 5c. Reference a downstream node (not upstream) -> 400
508
+ // step1 -> step2, but step2 tries to reference step1's sibling "step3"
509
+ // which is a parallel node (not upstream)
510
+ const { status: s2, data: d2 } = await api<{ error?: string }>("POST", "/api/workflows", {
511
+ name: "e2e-bad-ref-downstream",
512
+ definition: {
513
+ nodes: [
514
+ {
515
+ id: "step1",
516
+ type: "script",
517
+ inputs: { data: "step2.stdout" },
518
+ config: { runtime: "bash", script: "echo {{data}}" },
519
+ next: "step2",
520
+ },
521
+ {
522
+ id: "step2",
523
+ type: "script",
524
+ config: { runtime: "bash", script: "echo done" },
525
+ },
526
+ ],
527
+ },
528
+ });
529
+ assertEq(s2, 400, "5c. Downstream node reference returns 400");
530
+ assert(
531
+ typeof d2?.error === "string" && d2.error.includes("not upstream"),
532
+ "5d. Error message mentions not upstream",
533
+ `got error: ${d2?.error}`,
534
+ );
535
+
536
+ // 5e. Valid upstream reference -> 201
537
+ const { status: s3 } = await api<WfJson>("POST", "/api/workflows", {
538
+ name: "e2e-valid-upstream-ref",
539
+ definition: {
540
+ nodes: [
541
+ {
542
+ id: "step1",
543
+ type: "script",
544
+ config: { runtime: "bash", script: "echo hello" },
545
+ next: "step2",
546
+ },
547
+ {
548
+ id: "step2",
549
+ type: "script",
550
+ inputs: { data: "step1.stdout" },
551
+ config: { runtime: "bash", script: "echo {{data}}" },
552
+ },
553
+ ],
554
+ },
555
+ });
556
+ assertEq(s3, 201, "5e. Valid upstream reference returns 201");
557
+ }
558
+
559
+ // ─── Test 6: Deep interpolation ─────────────────────────────────────────────
560
+
561
+ async function testDeepInterpolation() {
562
+ log("Test 6: Deep interpolation (nested objects + arrays in config)");
563
+
564
+ // The script executor only looks at config.script, config.runtime, etc.
565
+ // But the deep interpolation happens on the entire config object.
566
+ // We'll verify by using a script that echoes something based on the config,
567
+ // and also verify the step completes (meaning interpolation didn't break).
568
+ //
569
+ // We can test deep interpolation by passing nested values through inputs
570
+ // and interpolating them in the script.
571
+ const definition = {
572
+ nodes: [
573
+ {
574
+ id: "echo",
575
+ type: "script",
576
+ inputs: { name: "trigger.name", tag: "trigger.tag" },
577
+ config: {
578
+ runtime: "bash",
579
+ script: "echo name={{name}} tag={{tag}}",
580
+ // These nested fields are not used by the script executor but
581
+ // they will be deep-interpolated by the engine
582
+ nested: { val: "{{name}}" },
583
+ list: ["{{tag}}", "fixed"],
584
+ },
585
+ },
586
+ ],
587
+ };
588
+
589
+ const { run, wfId } = await createAndTrigger("e2e-deep-interpolation", definition, {
590
+ name: "TestName",
591
+ tag: "v1.0",
592
+ });
593
+
594
+ assertEq(run.run.status, "completed", "6a. Deep interpolation run completed");
595
+
596
+ const echoStep = run.steps.find((s) => s.nodeId === "echo");
597
+ const echoOutput = echoStep?.output as { stdout?: string } | undefined;
598
+ assert(
599
+ echoOutput?.stdout?.includes("name=TestName") ?? false,
600
+ "6b. Script output contains interpolated name",
601
+ `got stdout: ${echoOutput?.stdout}`,
602
+ );
603
+ assert(
604
+ echoOutput?.stdout?.includes("tag=v1.0") ?? false,
605
+ "6c. Script output contains interpolated tag",
606
+ `got stdout: ${echoOutput?.stdout}`,
607
+ );
608
+
609
+ await api("DELETE", `/api/workflows/${wfId}`);
610
+ }
611
+
612
+ // ─── Test 7: Convergence with conditional branches ──────────────────────────
613
+
614
+ async function testConvergenceConditionalBranches() {
615
+ log("Test 7: Convergence with conditional branches");
616
+
617
+ // Workflow: A (code-match, branches true/false) ->
618
+ // true: B (script) -> C (script)
619
+ // false: C (script)
620
+ // C converges from both paths.
621
+
622
+ const definition = {
623
+ nodes: [
624
+ {
625
+ id: "A",
626
+ type: "code-match",
627
+ config: {
628
+ code: "(input) => input.trigger && input.trigger.match === true",
629
+ outputPorts: ["true", "false"],
630
+ },
631
+ next: { true: "B", false: "C" },
632
+ },
633
+ {
634
+ id: "B",
635
+ type: "script",
636
+ config: { runtime: "bash", script: "echo branch-B" },
637
+ next: "C",
638
+ },
639
+ {
640
+ id: "C",
641
+ type: "script",
642
+ config: { runtime: "bash", script: "echo final-C" },
643
+ },
644
+ ],
645
+ };
646
+
647
+ // 7a. Trigger with match=true -> A, B, C all execute
648
+ const { run: run1, wfId: wfId1 } = await createAndTrigger("e2e-convergence-true", definition, {
649
+ match: true,
650
+ });
651
+ assertEq(run1.run.status, "completed", "7a. Convergence (true path) run completed");
652
+ const stepIds1 = run1.steps.map((s) => s.nodeId);
653
+ assert(stepIds1.includes("A"), "7b. Node A executed (true path)");
654
+ assert(stepIds1.includes("B"), "7c. Node B executed (true path)");
655
+ assert(stepIds1.includes("C"), "7d. Node C executed (true path)");
656
+ await api("DELETE", `/api/workflows/${wfId1}`);
657
+
658
+ // 7e. Trigger with match=false -> A, C execute (B skipped)
659
+ const { run: run2, wfId: wfId2 } = await createAndTrigger("e2e-convergence-false", definition, {
660
+ match: false,
661
+ });
662
+ assertEq(run2.run.status, "completed", "7e. Convergence (false path) run completed");
663
+ const stepIds2 = run2.steps.map((s) => s.nodeId);
664
+ assert(stepIds2.includes("A"), "7f. Node A executed (false path)");
665
+ assert(!stepIds2.includes("B"), "7g. Node B NOT executed (false path, skipped)");
666
+ assert(stepIds2.includes("C"), "7h. Node C executed (false path, converged)");
667
+ await api("DELETE", `/api/workflows/${wfId2}`);
668
+ }
669
+
670
+ // ─── Test 8: Backward compatibility ─────────────────────────────────────────
671
+
672
+ async function testBackwardCompatibility() {
673
+ log("Test 8: Backward compatibility (no triggerSchema, no inputs, no inputSchema)");
674
+
675
+ const definition = {
676
+ nodes: [
677
+ {
678
+ id: "echo",
679
+ type: "script",
680
+ // No inputs, no inputSchema, no outputSchema
681
+ config: { runtime: "bash", script: "echo hello-compat" },
682
+ },
683
+ ],
684
+ };
685
+
686
+ // No triggerSchema -> any payload accepted
687
+ const { run, wfId } = await createAndTrigger("e2e-backward-compat", definition, {
688
+ anything: "goes",
689
+ nested: { value: 42 },
690
+ });
691
+
692
+ assertEq(run.run.status, "completed", "8a. Backward-compat run completed");
693
+ const echoStep = run.steps.find((s) => s.nodeId === "echo");
694
+ const echoOutput = echoStep?.output as { stdout?: string } | undefined;
695
+ assertEq(echoOutput?.stdout, "hello-compat", "8b. Script executed correctly");
696
+
697
+ await api("DELETE", `/api/workflows/${wfId}`);
698
+ }
699
+
700
+ // ─── Test 9: outputSchema validation ────────────────────────────────────────
701
+
702
+ async function testOutputSchemaValidation() {
703
+ log("Test 9: outputSchema validation");
704
+
705
+ // Script executor outputs { exitCode: number, stdout: string, stderr: string }
706
+ // We'll define an outputSchema that matches this shape -> should succeed
707
+
708
+ const definition = {
709
+ nodes: [
710
+ {
711
+ id: "echo",
712
+ type: "script",
713
+ outputSchema: {
714
+ type: "object",
715
+ properties: {
716
+ exitCode: { type: "number" },
717
+ },
718
+ required: ["exitCode"],
719
+ },
720
+ config: { runtime: "bash", script: "echo ok" },
721
+ },
722
+ ],
723
+ };
724
+
725
+ const { run: run1, wfId: wfId1 } = await createAndTrigger(
726
+ "e2e-output-schema-valid",
727
+ definition,
728
+ {},
729
+ );
730
+ assertEq(run1.run.status, "completed", "9a. OutputSchema (valid) run completed");
731
+ const echoStep = run1.steps.find((s) => s.nodeId === "echo");
732
+ assertEq(echoStep?.status, "completed", "9b. Echo step completed with matching outputSchema");
733
+ await api("DELETE", `/api/workflows/${wfId1}`);
734
+
735
+ // 9c. Define an outputSchema that expects a string where there's a number
736
+ // Script executor returns exitCode as number, but we require it to be string -> should fail
737
+ const definitionBad = {
738
+ nodes: [
739
+ {
740
+ id: "echo",
741
+ type: "script",
742
+ outputSchema: {
743
+ type: "object",
744
+ properties: {
745
+ exitCode: { type: "string" },
746
+ },
747
+ required: ["exitCode"],
748
+ },
749
+ config: { runtime: "bash", script: "echo ok" },
750
+ },
751
+ ],
752
+ };
753
+
754
+ const { run: run2, wfId: wfId2 } = await createAndTrigger(
755
+ "e2e-output-schema-invalid",
756
+ definitionBad,
757
+ {},
758
+ );
759
+ assertEq(run2.run.status, "failed", "9c. OutputSchema (invalid) run failed");
760
+ const echoStep2 = run2.steps.find((s) => s.nodeId === "echo");
761
+ assert(
762
+ echoStep2?.status === "failed",
763
+ "9d. Echo step failed on outputSchema violation",
764
+ `got status: ${echoStep2?.status}`,
765
+ );
766
+ assert(
767
+ echoStep2?.error?.includes("Output schema validation failed") ?? false,
768
+ "9e. Error message mentions output schema validation",
769
+ `got error: ${echoStep2?.error}`,
770
+ );
771
+ await api("DELETE", `/api/workflows/${wfId2}`);
772
+ }
773
+
774
+ // ─── Main ───────────────────────────────────────────────────────────────────
775
+ async function main() {
776
+ log("=== E2E Workflow I/O Schemas Test ===");
777
+ log(`PORT=${PORT} DB=${DB_PATH}`);
778
+
779
+ try {
780
+ await startApi();
781
+
782
+ await testTriggerSchema();
783
+ await testInputsMappingDataFlow();
784
+ await testInputSchemaValidation();
785
+ await testUnresolvedTokenDiagnostics();
786
+ await testStaticDataFlowValidation();
787
+ await testDeepInterpolation();
788
+ await testConvergenceConditionalBranches();
789
+ await testBackwardCompatibility();
790
+ await testOutputSchemaValidation();
791
+ } catch (err) {
792
+ logFail("UNEXPECTED ERROR", String(err));
793
+ console.error(err);
794
+ } finally {
795
+ await cleanup();
796
+ }
797
+
798
+ // Summary
799
+ console.log("");
800
+ log("=========================================");
801
+ log(`Results: ${pass} passed, ${fail} failed`);
802
+ log("=========================================");
803
+
804
+ process.exit(fail > 0 ? 1 : 0);
805
+ }
806
+
807
+ main();