@desplega.ai/agent-swarm 1.49.0 → 1.52.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 (547) hide show
  1. package/README.md +1 -1
  2. package/openapi.json +2070 -728
  3. package/package.json +10 -1
  4. package/src/agentmail/handlers.ts +65 -10
  5. package/src/agentmail/templates.ts +111 -0
  6. package/src/be/db.ts +1233 -7
  7. package/src/be/migrations/014_prompt_templates.sql +33 -0
  8. package/src/be/migrations/015_workflow_workspace.sql +3 -0
  9. package/src/be/migrations/016_active_session_runner_session.sql +4 -0
  10. package/src/be/migrations/017_channel_activity_cursors.sql +6 -0
  11. package/src/be/migrations/018_fix_seed_double_version.sql +30 -0
  12. package/src/be/migrations/019_skills.sql +65 -0
  13. package/src/be/migrations/020_approval_requests.sql +41 -0
  14. package/src/be/seed.ts +62 -0
  15. package/src/be/skill-parser.ts +70 -0
  16. package/src/be/skill-sync.ts +106 -0
  17. package/src/commands/runner.ts +320 -132
  18. package/src/commands/templates.ts +172 -0
  19. package/src/github/handlers.ts +292 -77
  20. package/src/github/mentions-aliases.test.ts +73 -0
  21. package/src/github/mentions.test.ts +3 -3
  22. package/src/github/mentions.ts +32 -6
  23. package/src/github/templates.ts +398 -0
  24. package/src/gitlab/handlers.ts +63 -22
  25. package/src/gitlab/templates.ts +140 -0
  26. package/src/heartbeat/heartbeat.ts +19 -10
  27. package/src/heartbeat/templates.ts +30 -0
  28. package/src/http/active-sessions.ts +27 -0
  29. package/src/http/approval-requests.ts +247 -0
  30. package/src/http/config.ts +3 -3
  31. package/src/http/index.ts +9 -2
  32. package/src/http/poll.ts +135 -14
  33. package/src/http/prompt-templates.ts +412 -0
  34. package/src/http/schedules.ts +35 -0
  35. package/src/http/skills.ts +479 -0
  36. package/src/http/workflows.ts +8 -0
  37. package/src/linear/sync.ts +28 -4
  38. package/src/linear/templates.ts +47 -0
  39. package/src/prompts/base-prompt.ts +41 -490
  40. package/src/prompts/registry.ts +57 -0
  41. package/src/prompts/resolver.ts +296 -0
  42. package/src/prompts/session-templates.ts +604 -0
  43. package/src/providers/claude-adapter.ts +15 -2
  44. package/src/providers/pi-mono-extension.ts +5 -1
  45. package/src/scheduler/scheduler.ts +125 -91
  46. package/src/server.ts +44 -0
  47. package/src/slack/assistant.ts +7 -4
  48. package/src/slack/channel-activity.ts +177 -0
  49. package/src/slack/handlers.ts +21 -6
  50. package/src/slack/templates.ts +55 -0
  51. package/src/tests/approval-requests.test.ts +735 -0
  52. package/src/tests/artifact-sdk.test.ts +12 -12
  53. package/src/tests/base-prompt.test.ts +49 -49
  54. package/src/tests/channel-activity.test.ts +363 -0
  55. package/src/tests/heartbeat.test.ts +1 -0
  56. package/src/tests/linear-webhook.test.ts +7 -3
  57. package/src/tests/pool-session-logs.test.ts +199 -0
  58. package/src/tests/prompt-template-github.test.ts +682 -0
  59. package/src/tests/prompt-template-remaining.test.ts +504 -0
  60. package/src/tests/prompt-template-resolver.test.ts +621 -0
  61. package/src/tests/prompt-template-session.test.ts +363 -0
  62. package/src/tests/prompt-templates-db.test.ts +616 -0
  63. package/src/tests/self-improvement.test.ts +8 -7
  64. package/src/tests/skill-parser.test.ts +178 -0
  65. package/src/tests/skill-sync.test.ts +171 -0
  66. package/src/tests/slack-metadata-inheritance.test.ts +1 -1
  67. package/src/tests/slack-thread-followups.test.ts +1 -1
  68. package/src/tests/structured-output.test.ts +0 -4
  69. package/src/tests/tool-annotations.test.ts +2 -1
  70. package/src/tests/update-profile-agentid.test.ts +248 -0
  71. package/src/tests/update-profile-auth.test.ts +195 -0
  72. package/src/tests/workflow-async-v2.test.ts +126 -4
  73. package/src/tests/workflow-definition-validation.test.ts +76 -0
  74. package/src/tests/workflow-executors.test.ts +4 -2
  75. package/src/tests/workflow-retry-v2.test.ts +1 -1
  76. package/src/tests/workflow-schedule-trigger.test.ts +104 -0
  77. package/src/tests/workflow-workspace.test.ts +272 -0
  78. package/src/tools/prompt-templates/delete.ts +86 -0
  79. package/src/tools/prompt-templates/get.ts +89 -0
  80. package/src/tools/prompt-templates/index.ts +5 -0
  81. package/src/tools/prompt-templates/list.ts +95 -0
  82. package/src/tools/prompt-templates/preview.ts +84 -0
  83. package/src/tools/prompt-templates/set.ts +117 -0
  84. package/src/tools/request-human-input.ts +106 -0
  85. package/src/tools/skills/index.ts +11 -0
  86. package/src/tools/skills/skill-create.ts +105 -0
  87. package/src/tools/skills/skill-delete.ts +67 -0
  88. package/src/tools/skills/skill-get.ts +75 -0
  89. package/src/tools/skills/skill-install-remote.ts +152 -0
  90. package/src/tools/skills/skill-install.ts +101 -0
  91. package/src/tools/skills/skill-list.ts +77 -0
  92. package/src/tools/skills/skill-publish.ts +123 -0
  93. package/src/tools/skills/skill-search.ts +43 -0
  94. package/src/tools/skills/skill-sync-remote.ts +128 -0
  95. package/src/tools/skills/skill-uninstall.ts +60 -0
  96. package/src/tools/skills/skill-update.ts +128 -0
  97. package/src/tools/store-progress.ts +22 -4
  98. package/src/tools/task-action.ts +20 -0
  99. package/src/tools/templates.ts +53 -0
  100. package/src/tools/tool-config.ts +23 -0
  101. package/src/tools/update-profile.ts +106 -34
  102. package/src/tools/workflows/create-workflow.ts +19 -1
  103. package/src/tools/workflows/update-workflow.ts +16 -1
  104. package/src/types.ts +109 -2
  105. package/src/workflows/definition.ts +30 -12
  106. package/src/workflows/engine.ts +40 -14
  107. package/src/workflows/executors/agent-task.ts +14 -3
  108. package/src/workflows/executors/human-in-the-loop.ts +160 -0
  109. package/src/workflows/executors/registry.ts +2 -0
  110. package/src/workflows/index.ts +1 -1
  111. package/src/workflows/recovery.ts +72 -0
  112. package/src/workflows/resume.ts +162 -12
  113. package/src/workflows/triggers.ts +31 -2
  114. package/src/workflows/version.ts +2 -0
  115. package/.claude/settings.json +0 -84
  116. package/.claude/settings.local.json +0 -117
  117. package/.dockerignore +0 -61
  118. package/.editorconfig +0 -15
  119. package/.entire/settings.json +0 -4
  120. package/.env.docker.example +0 -56
  121. package/.env.example +0 -78
  122. package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -78
  123. package/.github/ISSUE_TEMPLATE/community-template.yml +0 -77
  124. package/.github/ISSUE_TEMPLATE/config.yml +0 -8
  125. package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -60
  126. package/.github/PULL_REQUEST_TEMPLATE/community-template.md +0 -29
  127. package/.github/workflows/ci.yml +0 -52
  128. package/.github/workflows/docker-and-deploy.yml +0 -132
  129. package/.github/workflows/merge-gate.yml +0 -233
  130. package/.opencode/plugins/entire.ts +0 -133
  131. package/.superset/config.json +0 -6
  132. package/.wts-config.json +0 -4
  133. package/.wts-setup.ts +0 -171
  134. package/CHANGELOG.md +0 -447
  135. package/CLAUDE.md +0 -521
  136. package/CONTRIBUTING.md +0 -315
  137. package/DEPLOYMENT.md +0 -622
  138. package/Dockerfile +0 -65
  139. package/Dockerfile.worker +0 -189
  140. package/MCP.md +0 -841
  141. package/UI.md +0 -40
  142. package/api-entrypoint.sh +0 -56
  143. package/assets/agent-swarm-logo-orange.png +0 -0
  144. package/assets/agent-swarm-logo.png +0 -0
  145. package/assets/agent-swarm.mp4 +0 -0
  146. package/assets/agent-swarm.png +0 -0
  147. package/biome.json +0 -39
  148. package/deploy/DEPLOY.md +0 -60
  149. package/deploy/agent-swarm.service +0 -17
  150. package/deploy/docker-push.ts +0 -30
  151. package/deploy/install.ts +0 -85
  152. package/deploy/prod-db.ts +0 -42
  153. package/deploy/uninstall.ts +0 -12
  154. package/deploy/update.ts +0 -21
  155. package/depot.json +0 -1
  156. package/docker-compose.example.yml +0 -350
  157. package/docker-compose.local.yml +0 -119
  158. package/docker-entrypoint.sh +0 -632
  159. package/docs-site/app/api/search/route.ts +0 -4
  160. package/docs-site/app/docs/[[...slug]]/page.tsx +0 -87
  161. package/docs-site/app/docs/layout.tsx +0 -12
  162. package/docs-site/app/globals.css +0 -24
  163. package/docs-site/app/layout.config.tsx +0 -34
  164. package/docs-site/app/layout.tsx +0 -119
  165. package/docs-site/app/llms-full.txt/route.ts +0 -11
  166. package/docs-site/app/llms.mdx/docs/[[...slug]]/route.ts +0 -24
  167. package/docs-site/app/llms.txt/route.ts +0 -8
  168. package/docs-site/app/page.tsx +0 -5
  169. package/docs-site/app/robots.ts +0 -13
  170. package/docs-site/app/sitemap.ts +0 -37
  171. package/docs-site/components/api-page.client.tsx +0 -4
  172. package/docs-site/components/api-page.tsx +0 -7
  173. package/docs-site/components/mdx/mermaid.tsx +0 -55
  174. package/docs-site/content/docs/(documentation)/architecture/agents.mdx +0 -117
  175. package/docs-site/content/docs/(documentation)/architecture/hooks.mdx +0 -77
  176. package/docs-site/content/docs/(documentation)/architecture/memory.mdx +0 -96
  177. package/docs-site/content/docs/(documentation)/architecture/meta.json +0 -4
  178. package/docs-site/content/docs/(documentation)/architecture/overview.mdx +0 -172
  179. package/docs-site/content/docs/(documentation)/concepts/epics.mdx +0 -98
  180. package/docs-site/content/docs/(documentation)/concepts/meta.json +0 -4
  181. package/docs-site/content/docs/(documentation)/concepts/scheduling.mdx +0 -136
  182. package/docs-site/content/docs/(documentation)/concepts/services.mdx +0 -104
  183. package/docs-site/content/docs/(documentation)/concepts/task-lifecycle.mdx +0 -148
  184. package/docs-site/content/docs/(documentation)/concepts/workflows.mdx +0 -209
  185. package/docs-site/content/docs/(documentation)/contributing.mdx +0 -158
  186. package/docs-site/content/docs/(documentation)/getting-started.mdx +0 -157
  187. package/docs-site/content/docs/(documentation)/guides/agentmail-integration.mdx +0 -79
  188. package/docs-site/content/docs/(documentation)/guides/deployment.mdx +0 -171
  189. package/docs-site/content/docs/(documentation)/guides/github-integration.mdx +0 -81
  190. package/docs-site/content/docs/(documentation)/guides/gitlab-integration.mdx +0 -93
  191. package/docs-site/content/docs/(documentation)/guides/linear-integration.mdx +0 -98
  192. package/docs-site/content/docs/(documentation)/guides/meta.json +0 -13
  193. package/docs-site/content/docs/(documentation)/guides/sentry-integration.mdx +0 -52
  194. package/docs-site/content/docs/(documentation)/guides/slack-integration.mdx +0 -179
  195. package/docs-site/content/docs/(documentation)/guides/x402-payments.mdx +0 -154
  196. package/docs-site/content/docs/(documentation)/index.mdx +0 -65
  197. package/docs-site/content/docs/(documentation)/meta.json +0 -19
  198. package/docs-site/content/docs/(documentation)/reference/cli.mdx +0 -241
  199. package/docs-site/content/docs/(documentation)/reference/environment-variables.mdx +0 -205
  200. package/docs-site/content/docs/(documentation)/reference/mcp-tools.mdx +0 -449
  201. package/docs-site/content/docs/(documentation)/reference/meta.json +0 -4
  202. package/docs-site/content/docs/api-reference/active-sessions.mdx +0 -9
  203. package/docs-site/content/docs/api-reference/agents.mdx +0 -9
  204. package/docs-site/content/docs/api-reference/channels.mdx +0 -9
  205. package/docs-site/content/docs/api-reference/config.mdx +0 -9
  206. package/docs-site/content/docs/api-reference/debug.mdx +0 -9
  207. package/docs-site/content/docs/api-reference/ecosystem.mdx +0 -9
  208. package/docs-site/content/docs/api-reference/epics.mdx +0 -9
  209. package/docs-site/content/docs/api-reference/index.mdx +0 -32
  210. package/docs-site/content/docs/api-reference/memory.mdx +0 -9
  211. package/docs-site/content/docs/api-reference/meta.json +0 -25
  212. package/docs-site/content/docs/api-reference/poll.mdx +0 -9
  213. package/docs-site/content/docs/api-reference/repos.mdx +0 -9
  214. package/docs-site/content/docs/api-reference/schedules.mdx +0 -9
  215. package/docs-site/content/docs/api-reference/session-data.mdx +0 -9
  216. package/docs-site/content/docs/api-reference/stats.mdx +0 -9
  217. package/docs-site/content/docs/api-reference/tasks.mdx +0 -9
  218. package/docs-site/content/docs/api-reference/trackers.mdx +0 -9
  219. package/docs-site/content/docs/api-reference/webhooks.mdx +0 -9
  220. package/docs-site/content/docs/api-reference/workflows.mdx +0 -9
  221. package/docs-site/content/docs/meta.json +0 -3
  222. package/docs-site/lib/get-llm-text.ts +0 -10
  223. package/docs-site/lib/openapi.ts +0 -23
  224. package/docs-site/lib/source.ts +0 -8
  225. package/docs-site/mdx-components.tsx +0 -13
  226. package/docs-site/next.config.mjs +0 -29
  227. package/docs-site/package.json +0 -35
  228. package/docs-site/pnpm-lock.yaml +0 -5407
  229. package/docs-site/postcss.config.mjs +0 -8
  230. package/docs-site/public/logo.png +0 -0
  231. package/docs-site/scripts/generate-docs.ts +0 -171
  232. package/docs-site/source.config.ts +0 -17
  233. package/docs-site/tsconfig.json +0 -46
  234. package/ecosystem.config.cjs +0 -66
  235. package/landing/next.config.ts +0 -14
  236. package/landing/package.json +0 -31
  237. package/landing/pnpm-lock.yaml +0 -1091
  238. package/landing/postcss.config.mjs +0 -8
  239. package/landing/public/apple-touch-icon.png +0 -0
  240. package/landing/public/favicon.ico +0 -0
  241. package/landing/public/logo.png +0 -0
  242. package/landing/public/og-image.png +0 -0
  243. package/landing/public/omghost-desplega.svg +0 -30
  244. package/landing/public/omghost-openfort.svg +0 -9
  245. package/landing/src/app/actions/waitlist.ts +0 -25
  246. package/landing/src/app/blog/openfort-hackathon/page.tsx +0 -863
  247. package/landing/src/app/blog/page.tsx +0 -162
  248. package/landing/src/app/blog/swarm-metrics/page.tsx +0 -685
  249. package/landing/src/app/examples/page.tsx +0 -174
  250. package/landing/src/app/examples/x402/page.tsx +0 -456
  251. package/landing/src/app/globals.css +0 -122
  252. package/landing/src/app/layout.tsx +0 -134
  253. package/landing/src/app/page.tsx +0 -27
  254. package/landing/src/app/robots.ts +0 -13
  255. package/landing/src/app/sitemap.ts +0 -44
  256. package/landing/src/components/architecture.tsx +0 -163
  257. package/landing/src/components/cta.tsx +0 -52
  258. package/landing/src/components/features.tsx +0 -160
  259. package/landing/src/components/footer.tsx +0 -100
  260. package/landing/src/components/hero.tsx +0 -217
  261. package/landing/src/components/how-it-works.tsx +0 -165
  262. package/landing/src/components/navbar.tsx +0 -147
  263. package/landing/src/components/waitlist.tsx +0 -110
  264. package/landing/src/components/why-choose.tsx +0 -149
  265. package/landing/src/components/workshops.tsx +0 -328
  266. package/landing/src/lib/utils.ts +0 -6
  267. package/landing/tsconfig.json +0 -41
  268. package/misc/transcripts/2026-03-09-pi-mono-e2e-verification.md +0 -154
  269. package/new-ui/CLAUDE.md +0 -92
  270. package/new-ui/README.md +0 -73
  271. package/new-ui/biome.json +0 -42
  272. package/new-ui/components.json +0 -21
  273. package/new-ui/index.html +0 -25
  274. package/new-ui/package.json +0 -49
  275. package/new-ui/pnpm-lock.yaml +0 -4845
  276. package/new-ui/public/logo.png +0 -0
  277. package/new-ui/src/api/client.ts +0 -814
  278. package/new-ui/src/api/hooks/index.ts +0 -64
  279. package/new-ui/src/api/hooks/use-agents.ts +0 -58
  280. package/new-ui/src/api/hooks/use-channels.ts +0 -115
  281. package/new-ui/src/api/hooks/use-config-api.ts +0 -46
  282. package/new-ui/src/api/hooks/use-costs.ts +0 -122
  283. package/new-ui/src/api/hooks/use-db-query.ts +0 -29
  284. package/new-ui/src/api/hooks/use-epics.ts +0 -75
  285. package/new-ui/src/api/hooks/use-repos.ts +0 -61
  286. package/new-ui/src/api/hooks/use-schedules.ts +0 -81
  287. package/new-ui/src/api/hooks/use-services.ts +0 -16
  288. package/new-ui/src/api/hooks/use-stats.ts +0 -27
  289. package/new-ui/src/api/hooks/use-tasks.ts +0 -89
  290. package/new-ui/src/api/hooks/use-workflows.ts +0 -109
  291. package/new-ui/src/api/types.ts +0 -549
  292. package/new-ui/src/app/App.tsx +0 -13
  293. package/new-ui/src/app/providers.tsx +0 -32
  294. package/new-ui/src/app/router.tsx +0 -52
  295. package/new-ui/src/components/layout/app-header.tsx +0 -47
  296. package/new-ui/src/components/layout/app-sidebar.tsx +0 -128
  297. package/new-ui/src/components/layout/breadcrumbs.tsx +0 -57
  298. package/new-ui/src/components/layout/config-guard.tsx +0 -22
  299. package/new-ui/src/components/layout/root-layout.tsx +0 -40
  300. package/new-ui/src/components/layout/swarm-switcher.tsx +0 -85
  301. package/new-ui/src/components/shared/command-menu.tsx +0 -131
  302. package/new-ui/src/components/shared/data-grid.tsx +0 -141
  303. package/new-ui/src/components/shared/empty-state.tsx +0 -24
  304. package/new-ui/src/components/shared/error-boundary.tsx +0 -72
  305. package/new-ui/src/components/shared/json-viewer.tsx +0 -47
  306. package/new-ui/src/components/shared/name-connection-modal.tsx +0 -99
  307. package/new-ui/src/components/shared/page-skeleton.tsx +0 -16
  308. package/new-ui/src/components/shared/session-log-viewer.tsx +0 -364
  309. package/new-ui/src/components/shared/stats-bar.tsx +0 -132
  310. package/new-ui/src/components/shared/status-badge.tsx +0 -131
  311. package/new-ui/src/components/shared/usage-summary.tsx +0 -179
  312. package/new-ui/src/components/ui/alert-dialog.tsx +0 -176
  313. package/new-ui/src/components/ui/alert.tsx +0 -60
  314. package/new-ui/src/components/ui/avatar.tsx +0 -96
  315. package/new-ui/src/components/ui/badge.tsx +0 -46
  316. package/new-ui/src/components/ui/button.tsx +0 -62
  317. package/new-ui/src/components/ui/card.tsx +0 -75
  318. package/new-ui/src/components/ui/command.tsx +0 -160
  319. package/new-ui/src/components/ui/dialog.tsx +0 -143
  320. package/new-ui/src/components/ui/dropdown-menu.tsx +0 -226
  321. package/new-ui/src/components/ui/input.tsx +0 -21
  322. package/new-ui/src/components/ui/label.tsx +0 -19
  323. package/new-ui/src/components/ui/progress.tsx +0 -26
  324. package/new-ui/src/components/ui/scroll-area.tsx +0 -54
  325. package/new-ui/src/components/ui/select.tsx +0 -175
  326. package/new-ui/src/components/ui/separator.tsx +0 -28
  327. package/new-ui/src/components/ui/sheet.tsx +0 -132
  328. package/new-ui/src/components/ui/sidebar.tsx +0 -691
  329. package/new-ui/src/components/ui/skeleton.tsx +0 -13
  330. package/new-ui/src/components/ui/sonner.tsx +0 -35
  331. package/new-ui/src/components/ui/switch.tsx +0 -33
  332. package/new-ui/src/components/ui/table.tsx +0 -92
  333. package/new-ui/src/components/ui/tabs.tsx +0 -79
  334. package/new-ui/src/components/ui/textarea.tsx +0 -18
  335. package/new-ui/src/components/ui/tooltip.tsx +0 -51
  336. package/new-ui/src/components/workflows/action-node.tsx +0 -53
  337. package/new-ui/src/components/workflows/condition-node.tsx +0 -50
  338. package/new-ui/src/components/workflows/graph-utils.ts +0 -124
  339. package/new-ui/src/components/workflows/json-tree.tsx +0 -189
  340. package/new-ui/src/components/workflows/node-styles.ts +0 -10
  341. package/new-ui/src/components/workflows/step-detail-sheet.tsx +0 -87
  342. package/new-ui/src/components/workflows/trigger-node.tsx +0 -41
  343. package/new-ui/src/components/workflows/workflow-graph.tsx +0 -65
  344. package/new-ui/src/hooks/use-auto-scroll.ts +0 -82
  345. package/new-ui/src/hooks/use-config.ts +0 -203
  346. package/new-ui/src/hooks/use-keyboard-shortcuts.ts +0 -41
  347. package/new-ui/src/hooks/use-mobile.ts +0 -19
  348. package/new-ui/src/hooks/use-theme.ts +0 -60
  349. package/new-ui/src/lib/config.ts +0 -188
  350. package/new-ui/src/lib/slugs.ts +0 -71
  351. package/new-ui/src/lib/utils.ts +0 -120
  352. package/new-ui/src/main.tsx +0 -11
  353. package/new-ui/src/pages/agents/[id]/page.tsx +0 -492
  354. package/new-ui/src/pages/agents/page.tsx +0 -134
  355. package/new-ui/src/pages/chat/page.tsx +0 -674
  356. package/new-ui/src/pages/config/page.tsx +0 -1109
  357. package/new-ui/src/pages/dashboard/page.tsx +0 -454
  358. package/new-ui/src/pages/debug/page.tsx +0 -275
  359. package/new-ui/src/pages/epics/[id]/page.tsx +0 -809
  360. package/new-ui/src/pages/epics/page.tsx +0 -321
  361. package/new-ui/src/pages/not-found/page.tsx +0 -18
  362. package/new-ui/src/pages/repos/page.tsx +0 -369
  363. package/new-ui/src/pages/schedules/[id]/page.tsx +0 -664
  364. package/new-ui/src/pages/schedules/page.tsx +0 -477
  365. package/new-ui/src/pages/services/page.tsx +0 -128
  366. package/new-ui/src/pages/tasks/[id]/page.tsx +0 -670
  367. package/new-ui/src/pages/tasks/page.tsx +0 -592
  368. package/new-ui/src/pages/usage/page.tsx +0 -195
  369. package/new-ui/src/pages/workflow-runs/[id]/page.tsx +0 -363
  370. package/new-ui/src/pages/workflows/[id]/page.tsx +0 -417
  371. package/new-ui/src/pages/workflows/page.tsx +0 -266
  372. package/new-ui/src/styles/ag-grid.css +0 -36
  373. package/new-ui/src/styles/globals.css +0 -213
  374. package/new-ui/test-results/.last-run.json +0 -4
  375. package/new-ui/tsconfig.app.json +0 -34
  376. package/new-ui/tsconfig.json +0 -4
  377. package/new-ui/tsconfig.node.json +0 -26
  378. package/new-ui/vercel.json +0 -4
  379. package/new-ui/vite.config.ts +0 -28
  380. package/plugin/README.md +0 -1
  381. package/plugin/build-pi-skills.ts +0 -233
  382. package/plugin/hooks/hooks.json +0 -71
  383. package/prek.toml +0 -75
  384. package/pyproject.toml +0 -9
  385. package/scripts/check-db-boundary.sh +0 -60
  386. package/scripts/e2e-docker-provider.ts +0 -820
  387. package/scripts/e2e-io-schemas-test.ts +0 -807
  388. package/scripts/e2e-provider-test.ts +0 -220
  389. package/scripts/e2e-workflow-redesign.sh +0 -229
  390. package/scripts/e2e-workflow-test.sh +0 -285
  391. package/scripts/e2e-workflow-test.ts +0 -857
  392. package/scripts/generate-mcp-docs.ts +0 -415
  393. package/scripts/generate-openapi.ts +0 -26
  394. package/scripts/measure-tool-tokens.ts +0 -118
  395. package/scripts/x402-e2e-test.ts +0 -195
  396. package/scripts/x402-test-server.ts +0 -236
  397. package/scripts/x402-testnet-e2e.ts +0 -668
  398. package/slack-manifest.json +0 -88
  399. package/templates-ui/README.md +0 -46
  400. package/templates-ui/components.json +0 -17
  401. package/templates-ui/eslint.config.mjs +0 -18
  402. package/templates-ui/next.config.ts +0 -7
  403. package/templates-ui/package.json +0 -35
  404. package/templates-ui/pnpm-lock.yaml +0 -4571
  405. package/templates-ui/postcss.config.mjs +0 -7
  406. package/templates-ui/public/file.svg +0 -1
  407. package/templates-ui/public/globe.svg +0 -1
  408. package/templates-ui/public/logo.png +0 -0
  409. package/templates-ui/public/next.svg +0 -1
  410. package/templates-ui/public/vercel.svg +0 -1
  411. package/templates-ui/public/window.svg +0 -1
  412. package/templates-ui/src/app/[category]/[name]/page.tsx +0 -89
  413. package/templates-ui/src/app/api/templates/[...slug]/route.ts +0 -52
  414. package/templates-ui/src/app/api/templates/route.ts +0 -18
  415. package/templates-ui/src/app/builder/page.tsx +0 -37
  416. package/templates-ui/src/app/globals.css +0 -94
  417. package/templates-ui/src/app/layout.tsx +0 -79
  418. package/templates-ui/src/app/page.tsx +0 -38
  419. package/templates-ui/src/app/robots.ts +0 -11
  420. package/templates-ui/src/app/sitemap.ts +0 -31
  421. package/templates-ui/src/components/compose-builder.tsx +0 -442
  422. package/templates-ui/src/components/compose-preview.tsx +0 -117
  423. package/templates-ui/src/components/file-preview.tsx +0 -77
  424. package/templates-ui/src/components/footer.tsx +0 -40
  425. package/templates-ui/src/components/header.tsx +0 -41
  426. package/templates-ui/src/components/template-card.tsx +0 -87
  427. package/templates-ui/src/components/template-detail.tsx +0 -125
  428. package/templates-ui/src/components/template-gallery.tsx +0 -263
  429. package/templates-ui/src/components/ui/badge.tsx +0 -36
  430. package/templates-ui/src/components/ui/button.tsx +0 -57
  431. package/templates-ui/src/components/ui/card.tsx +0 -76
  432. package/templates-ui/src/components/ui/separator.tsx +0 -31
  433. package/templates-ui/src/components/ui/tooltip.tsx +0 -32
  434. package/templates-ui/src/lib/compose-generator.ts +0 -241
  435. package/templates-ui/src/lib/templates.ts +0 -137
  436. package/templates-ui/src/lib/utils.ts +0 -6
  437. package/templates-ui/tsconfig.json +0 -34
  438. package/thoughts/research/2026-02-28-openfort-viem-x402-research.md +0 -679
  439. package/thoughts/research/2026-02-28-x402-payments-research.md +0 -686
  440. package/thoughts/researcher/plans/2026-02-20-agent-self-improvement-plan.md +0 -282
  441. package/thoughts/researcher/research/2026-02-20-agent-self-improvement.md +0 -492
  442. package/thoughts/shared/plans/.gitkeep +0 -0
  443. package/thoughts/shared/plans/2025-12-18-slack-integration.md +0 -1195
  444. package/thoughts/shared/plans/2025-12-19-agent-log-streaming.md +0 -732
  445. package/thoughts/shared/plans/2025-12-19-role-based-swarm-plugin.md +0 -361
  446. package/thoughts/shared/plans/2025-12-20-mobile-responsive-ui.md +0 -501
  447. package/thoughts/shared/plans/2025-12-20-startup-team-swarm.md +0 -560
  448. package/thoughts/shared/plans/2025-12-23-runner-level-polling.md +0 -934
  449. package/thoughts/shared/plans/2025-12-23-runner-session-logs.md +0 -1000
  450. package/thoughts/shared/plans/2025-12-23-worker-lead-spawn-triggers.md +0 -568
  451. package/thoughts/shared/plans/2026-01-09-inverse-teleport.md +0 -1516
  452. package/thoughts/shared/plans/2026-01-12-agent-rename-pm2-control.md +0 -1133
  453. package/thoughts/shared/plans/2026-01-12-github-app-integration.md +0 -380
  454. package/thoughts/shared/plans/2026-01-12-lead-inbox-model.md +0 -876
  455. package/thoughts/shared/plans/2026-01-12-ralph-wiggum-integration.md +0 -463
  456. package/thoughts/shared/plans/2026-01-13-agent-concurrency.md +0 -691
  457. package/thoughts/shared/plans/2026-01-13-github-assignment-handling.md +0 -690
  458. package/thoughts/shared/plans/2026-01-13-prevent-duplicate-trigger-processing.md +0 -1071
  459. package/thoughts/shared/plans/2026-01-14-fix-slack-thread-context.md +0 -507
  460. package/thoughts/shared/plans/2026-01-15-scheduled-tasks-implementation.md +0 -565
  461. package/thoughts/shared/plans/2026-01-15-usage-cost-tracking-ui.md +0 -1479
  462. package/thoughts/shared/plans/2026-01-16-epics-feature-implementation.md +0 -1230
  463. package/thoughts/shared/plans/2026-02-26-mcp-tool-context-reduction.md +0 -282
  464. package/thoughts/shared/plans/2026-03-02-claude-context-mode-integration.md +0 -328
  465. package/thoughts/shared/plans/2026-03-02-code-level-heartbeat.md +0 -224
  466. package/thoughts/shared/research/.gitkeep +0 -0
  467. package/thoughts/shared/research/2025-01-09-inverse-teleport-plan-review.md +0 -420
  468. package/thoughts/shared/research/2025-12-18-slack-integration.md +0 -442
  469. package/thoughts/shared/research/2025-12-19-agent-log-streaming.md +0 -339
  470. package/thoughts/shared/research/2025-12-19-agent-secrets-cli-research.md +0 -390
  471. package/thoughts/shared/research/2025-12-21-gemini-cli-integration.md +0 -376
  472. package/thoughts/shared/research/2025-12-22-runner-loop-architecture.md +0 -582
  473. package/thoughts/shared/research/2025-12-22-setup-experience-improvements.md +0 -264
  474. package/thoughts/shared/research/2026-01-13-lead-duplicate-trigger-processing.md +0 -223
  475. package/thoughts/shared/research/2026-01-14-lead-slack-thread-context.md +0 -277
  476. package/thoughts/shared/research/2026-01-15-ai-tracker-agent-swarm-integration.md +0 -376
  477. package/thoughts/shared/research/2026-01-15-auto-starting-processes-in-worker-containers.md +0 -787
  478. package/thoughts/shared/research/2026-01-15-scheduled-tasks.md +0 -390
  479. package/thoughts/shared/research/2026-01-16-epics-feature-research.md +0 -437
  480. package/thoughts/shared/research/2026-02-26-cliffy-mcp-tools.md +0 -159
  481. package/thoughts/shared/research/2026-03-03-database-migration-system-refactor.md +0 -337
  482. package/thoughts/swarm-researcher/plans/2026-02-23-openclaw-improvements-plan.md +0 -778
  483. package/thoughts/swarm-researcher/plans/2026-02-26-artifacts-localtunnel-plan.md +0 -1269
  484. package/thoughts/swarm-researcher/research/2026-02-23-openclaw-vs-agent-swarm-comparison.md +0 -411
  485. package/thoughts/swarm-researcher/research/2026-02-26-artifacts-localtunnel.md +0 -724
  486. package/thoughts/taras/brainstorms/2026-03-20-prompt-template-registry.md +0 -443
  487. package/thoughts/taras/brainstorms/2026-03-20-setup-cli-onboarding.md +0 -307
  488. package/thoughts/taras/plans/2026-01-22-agent-swarm-schemas.md +0 -98
  489. package/thoughts/taras/plans/2026-01-28-per-worker-claude-md.md +0 -617
  490. package/thoughts/taras/plans/2026-01-28-sentry-cli-integration.md +0 -214
  491. package/thoughts/taras/plans/2026-02-20-auto-improvement.md +0 -803
  492. package/thoughts/taras/plans/2026-02-20-env-management.md +0 -538
  493. package/thoughts/taras/plans/2026-02-20-memory-system.md +0 -882
  494. package/thoughts/taras/plans/2026-02-20-repos-knowledge.md +0 -806
  495. package/thoughts/taras/plans/2026-02-20-session-attach.md +0 -647
  496. package/thoughts/taras/plans/2026-02-20-worker-identity.md +0 -820
  497. package/thoughts/taras/plans/2026-02-25-feat-new-ui-visual-redesign-plan.md +0 -768
  498. package/thoughts/taras/plans/2026-03-04-fix-buildSystemPrompt-missing-fields.md +0 -77
  499. package/thoughts/taras/plans/2026-03-04-new-ui-missing-actions.md +0 -543
  500. package/thoughts/taras/plans/2026-03-06-one-time-scheduled-tasks.md +0 -373
  501. package/thoughts/taras/plans/2026-03-08-memory-self-improvement-enhancements.md +0 -512
  502. package/thoughts/taras/plans/2026-03-08-pi-mono-provider-implementation.md +0 -919
  503. package/thoughts/taras/plans/2026-03-09-templates-registry.md +0 -723
  504. package/thoughts/taras/plans/2026-03-10-task-working-directory.md +0 -371
  505. package/thoughts/taras/plans/2026-03-11-archil-per-agent-write-strategy.md +0 -621
  506. package/thoughts/taras/plans/2026-03-12-eliminate-inbox-route-to-tasks.md +0 -61
  507. package/thoughts/taras/plans/2026-03-12-slack-thread-followup-additive.md +0 -488
  508. package/thoughts/taras/plans/2026-03-13-slack-ai-improvements.md +0 -644
  509. package/thoughts/taras/plans/2026-03-16-route-wrapper-openapi.md +0 -636
  510. package/thoughts/taras/plans/2026-03-17-multi-api-config.md +0 -444
  511. package/thoughts/taras/plans/2026-03-18-agent-fs-integration.md +0 -591
  512. package/thoughts/taras/plans/2026-03-18-debug-db-explorer.md +0 -446
  513. package/thoughts/taras/plans/2026-03-18-workflow-redesign.md +0 -987
  514. package/thoughts/taras/plans/2026-03-19-compound-learnings.md +0 -403
  515. package/thoughts/taras/plans/2026-03-19-ticket-tracker-linear-integration.md +0 -860
  516. package/thoughts/taras/plans/2026-03-19-workflow-io-schemas-and-bugs.md +0 -899
  517. package/thoughts/taras/plans/2026-03-20-setup-cli-onboarding.md +0 -874
  518. package/thoughts/taras/plans/2026-03-20-workflow-structured-output-validation-workspace.md +0 -723
  519. package/thoughts/taras/research/2026-01-22-vercel-cli-integration.md +0 -287
  520. package/thoughts/taras/research/2026-01-27-excessive-polling-issue.md +0 -311
  521. package/thoughts/taras/research/2026-01-28-per-worker-claude-md.md +0 -383
  522. package/thoughts/taras/research/2026-01-28-sentry-cli-integration.md +0 -240
  523. package/thoughts/taras/research/2026-02-19-agent-native-swarm-architecture.md +0 -390
  524. package/thoughts/taras/research/2026-02-19-swarm-gaps-implementation.md +0 -594
  525. package/thoughts/taras/research/2026-02-25-dashboard-ui-design-best-practices.md +0 -825
  526. package/thoughts/taras/research/2026-02-26-task-detail-page-redesign.md +0 -393
  527. package/thoughts/taras/research/2026-03-03-new-ui-missing-actions.md +0 -168
  528. package/thoughts/taras/research/2026-03-05-pi-mono-provider-research.md +0 -230
  529. package/thoughts/taras/research/2026-03-06-workflow-engine-design.md +0 -445
  530. package/thoughts/taras/research/2026-03-08-drive-loop-concept.md +0 -375
  531. package/thoughts/taras/research/2026-03-08-pi-mono-deep-dive.md +0 -869
  532. package/thoughts/taras/research/2026-03-09-templates-registry.md +0 -373
  533. package/thoughts/taras/research/2026-03-10-agent-working-directory.md +0 -223
  534. package/thoughts/taras/research/2026-03-10-configurable-event-prompts.md +0 -339
  535. package/thoughts/taras/research/2026-03-11-archil-production-setup.md +0 -181
  536. package/thoughts/taras/research/2026-03-11-archil-shared-disk-write-strategies.md +0 -437
  537. package/thoughts/taras/research/2026-03-13-slack-ai-features.md +0 -258
  538. package/thoughts/taras/research/2026-03-16-openapi-docs-generation.md +0 -335
  539. package/thoughts/taras/research/2026-03-16-route-wrapper-openapi.md +0 -670
  540. package/thoughts/taras/research/2026-03-16-slack-thread-followups-e2e.md +0 -54
  541. package/thoughts/taras/research/2026-03-18-agent-fs-integration.md +0 -558
  542. package/thoughts/taras/research/2026-03-18-linear-integration-finalization.md +0 -526
  543. package/thoughts/taras/research/2026-03-18-workflow-redesign.md +0 -797
  544. package/thoughts/taras/research/2026-03-19-workflow-node-io-schemas-and-bugs.md +0 -563
  545. package/thoughts/taras/research/2026-03-19-workflow-structured-output-validation-workspace.md +0 -486
  546. package/thoughts/taras/research/2026-03-20-prompt-template-registry.md +0 -469
  547. package/tsconfig.json +0 -37
@@ -1,723 +0,0 @@
1
- ---
2
- date: 2026-03-20
3
- topic: "Workflow: Structured Output, Validation Fixes, Workspace Scoping"
4
- status: verified
5
- author: taras+claude
6
- autonomy: critical
7
- commit-per-phase: true
8
- ---
9
-
10
- # Workflow: Structured Output, Validation Fixes, Workspace Scoping
11
-
12
- ## Overview
13
-
14
- Four features to close gaps in the workflow engine: workspace scoping for agent-tasks, a validation retry bug fix, structured output extraction from agent-tasks, and validation executor adapter normalization. These are ordered by complexity (lowest first) to deliver value incrementally.
15
-
16
- **Cross-node validation nodes** (backward edges, cycle detection, step invalidation) are explicitly deferred to a separate plan.
17
-
18
- ## Current State Analysis
19
-
20
- **Workspace scoping**: `AgentTaskConfigSchema` (agent-task.ts:8-14) only exposes `template`, `agentId`, `tags`, `priority`, `offerMode`. The DB layer's `CreateTaskOptions` (db.ts:1707-1740) already supports `dir`, `vcsRepo`, `model`, `parentTaskId`. The runner already resolves cwd from `task.dir` > `vcsRepo clonePath` > `process.cwd()` (runner.ts:2150-2172). The gap is simply that the workflow executor doesn't forward these fields.
21
-
22
- **Validation bug**: The retry poller (retry-poller.ts:77-128) re-runs executors after a validation-triggered retry but never calls `runStepValidation()` on the result. Validation only runs in `executeStep()` (engine.ts:447-475). This means a retried step's output is never re-validated.
23
-
24
- **Structured output**: Task output is always `z.string().optional()` (types.ts:98). `store-progress` (store-progress.ts:124) stores raw strings. There's no way to extract structured data from agent output. The `raw-llm` executor already uses `generateObject()` with AI SDK (raw-llm.ts:47-53), so the extraction pattern exists.
25
-
26
- **Validation executor adapters**: The pass/fail contract is hardcoded at validation.ts:53-56 (`result.output.pass === true`). Only the `validate` executor produces `{ pass: boolean }`. Other executors (`script`, `property-match`, `raw-llm`) have different output shapes and always "fail" the check.
27
-
28
- ### Key Discoveries:
29
- - Runner cwd resolution is robust: validates `existsSync()` + `statSync()`, falls back gracefully (runner.ts:2154-2167)
30
- - `deepInterpolate()` already handles `{{token}}` replacement in all config fields (engine.ts:356), so new fields like `dir: "{{repo_path}}"` work automatically
31
- - Retry poller uses `setTimeout` chaining (not `setInterval`) to prevent overlap (retry-poller.ts:135)
32
- - `store-progress` runs memory indexing AFTER task completion (store-progress.ts:178-232) — structured output should be validated BEFORE `completeTask()` call
33
- - The `validate` executor already uses AI SDK's `generateObject()` with OpenRouter (validate.ts:114-141)
34
-
35
- ## Desired End State
36
-
37
- 1. **Workspace scoping**: Workflow `agent-task` nodes can set `dir`, `vcsRepo`, `model`, `parentTaskId` in their config. These flow through to the created task and the runner resolves the working directory accordingly.
38
-
39
- 2. **Validation bug fixed**: After a validation-triggered retry succeeds, the retry poller re-runs `runStepValidation()` before checkpointing success.
40
-
41
- 3. **Structured output**: Tasks can declare an `outputSchema` (JSON Schema). When set:
42
- - The agent's prompt includes the schema so it knows what structure to produce
43
- - `store-progress` validates output against the schema; invalid output fails the tool call (not the task), giving the agent a chance to retry
44
- - Claude adapter: if session ends without structured output, a fallback extraction call (`claude -p --json-schema`) produces structured data
45
- - Pi-mono adapter: no fallback — task fails if no valid structured output
46
- - Workflow `agent-task` nodes can set `outputSchema` in config, forwarded to the task
47
-
48
- 4. **Validation executor adapters**: Any executor can be used as a validator. The validation system normalizes output to `{ pass }` using an adapter layer: `script.exitCode === 0 → pass`, `property-match.passed → pass`, etc.
49
-
50
- ## Quick Verification Reference
51
-
52
- Common commands:
53
- - `bun run tsc:check` — TypeScript type check
54
- - `bun run lint:fix` — Biome lint + format
55
- - `bun test` — All unit tests
56
- - `bun test src/tests/<file>.test.ts` — Specific test
57
-
58
- Key files:
59
- - `src/workflows/executors/agent-task.ts` — Agent-task executor (config schema + task creation)
60
- - `src/workflows/validation.ts` — Validation orchestrator (pass/fail contract)
61
- - `src/workflows/retry-poller.ts` — Retry loop
62
- - `src/tools/store-progress.ts` — MCP tool for task completion
63
- - `src/types.ts` — All Zod schemas
64
- - `src/commands/runner.ts` — Task runner (prompt building, cwd resolution)
65
-
66
- ## What We're NOT Doing
67
-
68
- - **Cross-node validation nodes**: No backward edges, cycle detection, or step invalidation. Deferred to a separate plan.
69
- - **UI changes**: No dashboard changes for structured output display or validation status.
70
- - **New dependencies**: AI SDK is already present. No new packages.
71
- - **Full JSON Schema support**: The existing `validateJsonSchema()` is a minimal validator (supports `type`, `required`, `properties` only). We will extend it to also support `enum` and `const`, but advanced features like `pattern`, `anyOf`/`oneOf`, `$ref`, `additionalProperties` are out of scope for this plan.
72
-
73
- ## Implementation Approach
74
-
75
- Ordered by complexity (lowest first). Each phase is independently testable and committable.
76
-
77
- 1. **Workspace scoping** — Pure config passthrough, no new logic
78
- 2. **Validation bug fix** — Small, targeted fix in retry poller
79
- 3. **Structured output** — Largest feature, builds on existing AI SDK patterns
80
- 4. **Validation executor adapters** — Normalize pass/fail contract
81
-
82
- ---
83
-
84
- ## Phase 1: Workspace Scoping for Agent-Tasks
85
-
86
- ### Overview
87
- Extend `AgentTaskConfigSchema` to expose `dir`, `vcsRepo`, `model`, and `parentTaskId` fields, and forward them to `createTaskExtended()`. The runner and DB layer already handle these fields — the workflow executor just doesn't pass them through.
88
-
89
- ### Changes Required:
90
-
91
- #### 1. Extend AgentTaskConfigSchema
92
- **File**: `src/workflows/executors/agent-task.ts`
93
- **Changes**:
94
- - Add optional fields to `AgentTaskConfigSchema` (after line 14):
95
- ```typescript
96
- dir: z.string().min(1).optional(),
97
- vcsRepo: z.string().min(1).optional(),
98
- model: z.string().min(1).optional(),
99
- parentTaskId: z.string().uuid().optional(),
100
- ```
101
- - Note: `dir` does NOT enforce `.startsWith("/")` here because the value may come from interpolation (e.g., `"{{repo_path}}"`) and the runner already validates the path at runtime (runner.ts:2154-2167).
102
-
103
- #### 2. Forward fields to createTaskExtended
104
- **File**: `src/workflows/executors/agent-task.ts`
105
- **Changes**:
106
- - In the `execute()` method's `createTaskExtended()` call (lines 64-72), add the new fields:
107
- ```typescript
108
- dir: config.dir,
109
- vcsRepo: config.vcsRepo,
110
- model: config.model,
111
- parentTaskId: config.parentTaskId,
112
- ```
113
-
114
- #### 3. Unit test
115
- **File**: `src/tests/workflow-agent-task.test.ts` (new file)
116
- **Changes**:
117
- - Test that `AgentTaskConfigSchema` parses configs with new fields
118
- - Test that `execute()` creates tasks with `dir`, `vcsRepo`, `model`, `parentTaskId` set
119
- - Use isolated SQLite DB (pattern from existing tests)
120
-
121
- ### Success Criteria:
122
-
123
- #### Automated Verification:
124
- - [x] Types pass: `bun run tsc:check` ✓
125
- - [x] Lint passes: `bun run lint:fix` ✓
126
- - [x] New test passes: `bun test src/tests/workflow-agent-task.test.ts` (6/6) ✓
127
- - [x] All tests pass: `bun test` (1657/1657) ✓
128
-
129
- #### Manual Verification:
130
- - [x] Create a workflow with `agent-task` node that includes `dir: "/workspace/repos/agent-swarm"` and verify the created task has `dir` set via `GET /api/tasks` ✓ (task created with `dir: "/workspace/repos/agent-swarm"`, `source: "workflow"`)
131
- - [x] Create a workflow with interpolated `dir: "{{trigger.repo_path}}"` and trigger with `{ "repo_path": "/workspace/repos/test" }` — verify interpolation works ✓ (task created with `dir: "/workspace/repos/test"`, `task: "List files in /workspace/repos/test"`)
132
-
133
- **Note**: Interpolation path must use `{{trigger.repo_path}}` (not `{{repo_path}}`) since trigger data is stored under `ctx.trigger`.
134
-
135
- **Committed**: `405d679` — `feat(workflow): add workspace scoping to agent-task executor`
136
-
137
- ---
138
-
139
- ## Phase 2: Validation Retry Bug Fix
140
-
141
- ### Overview
142
- Fix the retry poller to re-run `runStepValidation()` after successfully re-executing a step that was retried due to validation failure. Currently, the poller bypasses validation on retry, meaning a step's output is only validated on its first execution.
143
-
144
- ### Changes Required:
145
-
146
- #### 1. Add validation re-check in retry poller
147
- **File**: `src/workflows/retry-poller.ts`
148
- **Changes**:
149
- - After the executor succeeds (around line 96), before calling `checkpointStep()`:
150
- 1. Check if the node has a `validation` config
151
- 2. If yes, call `runStepValidation()` with the result output
152
- 3. If validation returns `"retry"`: call `checkpointStepFailure()` again (same as lines 84-95) to schedule another retry, and `continue` to the next step
153
- 4. If validation returns `"halt"`: mark step and run as failed
154
- 5. If validation returns `"pass"`: proceed to `checkpointStep()` as before
155
- - Import `runStepValidation` from `./validation`
156
-
157
- #### 2. Unit test
158
- **File**: `src/tests/workflow-retry-validation.test.ts` (new file)
159
- **Changes**:
160
- - Test: step with validation + retry → first execution fails validation → retry poller re-executes → poller re-validates the result
161
- - Test: retry succeeds but validation still fails → another retry is scheduled (not infinite — respects maxRetries)
162
- - Test: retry succeeds and validation passes → step checkpointed, graph continues
163
-
164
- ### Success Criteria:
165
-
166
- #### Automated Verification:
167
- - [x] Types pass: `bun run tsc:check` ✓
168
- - [x] Lint passes: `bun run lint:fix` ✓
169
- - [x] New test passes: `bun test src/tests/workflow-retry-validation.test.ts` (3/3) ✓
170
- - [x] All tests pass: `bun test` (1660/1660) ✓
171
-
172
- #### Manual Verification:
173
- - [x] Create a workflow with `raw-llm` node + LLM-based validation (`mustPass: true`, `retry: { maxRetries: 3 }`). Validation required number > 95 (5% pass rate). ✓ Verified: LLM generated numbers ≤ 95 on all attempts → validation failed on each retry → retryCount incremented to 3 → run correctly marked `"failed"`. Also found and fixed a pre-existing bug: `checkpointStepFailure` wasn't clearing `nextRetryAt` on terminal failure, causing infinite retry loops (commit `ccc5162`).
174
-
175
- **Committed**: `2e91344` — `fix(workflow): re-run validation after retry poller re-executes a step`
176
- **Bonus fix**: `ccc5162` — `fix(workflow): clear nextRetryAt when retries are exhausted`
177
-
178
- ---
179
-
180
- ## Phase 3: Structured Output Extraction for Agent-Tasks
181
-
182
- ### Overview
183
- Add `outputSchema` support to tasks. When set, the agent is prompted to produce structured output, `store-progress` validates it inline (failing the tool call, not the task, on mismatch), and the Claude adapter provides a fallback extraction if the session ends without valid structured output.
184
-
185
- ### Changes Required:
186
-
187
- #### 1. Add outputSchema to AgentTaskSchema
188
- **File**: `src/types.ts`
189
- **Changes**:
190
- - Add to `AgentTaskSchema` (near line 98):
191
- ```typescript
192
- outputSchema: z.record(z.string(), z.unknown()).optional(),
193
- ```
194
- - This represents a JSON Schema object that the task output must conform to.
195
-
196
- #### 2. Store outputSchema in DB
197
- **File**: `src/be/db.ts`
198
- **Changes**:
199
- - Add `outputSchema` to `CreateTaskOptions` interface (near line 1733):
200
- ```typescript
201
- outputSchema?: Record<string, unknown>;
202
- ```
203
- - In `createTaskExtended()` SQL INSERT (lines 1822-1871): store `outputSchema` as a JSON-stringified column. If the column doesn't exist yet, add a migration.
204
- - Check: does `agent_tasks` table already have an `outputSchema` column? If not, create migration `NNN_add_output_schema.sql`:
205
- ```sql
206
- ALTER TABLE agent_tasks ADD COLUMN outputSchema TEXT;
207
- ```
208
-
209
- #### 3. Validate structured output in store-progress
210
- **File**: `src/tools/store-progress.ts`
211
- **Changes**:
212
- - After the terminal state guard (line 106) and before `completeTask()` call (line 124):
213
- 1. Load the task's `outputSchema` (already have the task object from line 95)
214
- 2. If `outputSchema` is set and `status === "completed"` and `output` is provided:
215
- a. Try `JSON.parse(output)`
216
- b. If not valid JSON: return a tool error (NOT task failure) with message explaining the output must be valid JSON matching the schema. Include the schema in the error.
217
- c. If valid JSON: validate against `outputSchema` using `validateJsonSchema()` (from `src/workflows/json-schema-validator.ts`)
218
- d. If validation fails: return a tool error with the validation errors, asking the agent to retry
219
- e. If validation passes: proceed to `completeTask()` as normal
220
- - This gives the agent multiple chances to produce correct output within the same session.
221
- - **Validator limitation**: `validateJsonSchema()` currently only supports `type`, `required`, `properties`. Before using it here, extend it to also support `enum` and `const` (common in task output schemas). Add these checks in `json-schema-validator.ts` alongside the existing `type`/`required`/`properties` handling. Other advanced JSON Schema features (`pattern`, `anyOf`, `$ref`, etc.) are out of scope.
222
-
223
- #### 4. Prompt injection for outputSchema
224
- **File**: `src/commands/runner.ts`
225
- **Changes**:
226
- - In `buildPromptForTrigger()` (around line 892-903), after building the task_assigned prompt:
227
- 1. Check if `trigger.task.outputSchema` exists
228
- 2. If yes, append a section to the prompt:
229
- ```
230
- **Required Output Format**: When completing this task, you MUST call store-progress with output that is valid JSON conforming to this schema:
231
- ```json
232
- <JSON.stringify(outputSchema, null, 2)>
233
- ```
234
- Call store-progress with status "completed" and your JSON output. If your output doesn't match the schema, the tool call will fail and you should fix and retry.
235
- ```
236
-
237
- #### 5. Structured output fallback in runner completion path
238
- **File**: `src/commands/runner.ts`
239
- **Changes**:
240
-
241
- The existing `ensureTaskFinished()` is a simple safety net (POST status based on exit code). Rather than expanding it, extract the structured output logic into a new helper function:
242
-
243
- - Add `async function handleStructuredOutputFallback(config: ApiConfig, taskId: string, adapterType: "claude" | "pi-mono"): Promise<string | null>`:
244
- 1. Fetch the task via `GET /api/tasks/${taskId}` (returns task + logs)
245
- 2. If no `outputSchema` on the task: return `null` (no-op)
246
- 3. If the task already has `output` stored (agent called `store-progress` successfully): return `null` (already handled)
247
- 4. **Adapter branching**:
248
- - **Claude adapter**: Build an extraction prompt and run fallback:
249
- - Build prompt from task description + progress history (filter `task.logs` for `eventType === "task_progress"`, sort chronologically, format as numbered entries) + output schema
250
- - The prompt structure:
251
- ```
252
- Extract structured data from this task's execution history.
253
-
254
- ## Task Description
255
- ${task.description}
256
-
257
- ## Progress Updates (chronological)
258
- ${progressEntries.map((log, i) => `${i+1}. [${log.createdAt}] ${log.newValue}`).join("\n")}
259
-
260
- ## Required Output Schema
261
- ${JSON.stringify(task.outputSchema, null, 2)}
262
-
263
- Extract the structured data from the progress updates above. Return ONLY valid JSON matching the schema.
264
- ```
265
- - Run extraction:
266
- ```typescript
267
- const result = await Bun.$`claude -p ${extractionPrompt} --json-schema ${JSON.stringify(schema)} --output-format json --model sonnet`.json();
268
- ```
269
- - Return `result.structured_output` as stringified JSON, or `null` on failure
270
- - **Pi-mono adapter**: Return a special sentinel (e.g., throw or return error string) that signals "fail the task" with reason: `"Structured output required by outputSchema but not provided via store-progress"`
271
-
272
- - Modify `ensureTaskFinished()` to call the helper before POST:
273
- 1. If `exitCode === 0`: call `handleStructuredOutputFallback(config, taskId, adapterType)`
274
- 2. If it returns structured output: use it as the `output` in the finish POST
275
- 3. If it signals failure (Pi-mono): change status to `"failed"` with the structured output failure reason
276
- 4. If it returns `null`: proceed with existing behavior (raw fallback output)
277
-
278
- - The `adapterType` is available in the runner's process state (`state.activeTasks` tracks which adapter spawned each process). Pass it to `ensureTaskFinished()` as a new parameter.
279
-
280
- #### 6. JSON-parse structured output in workflow resume
281
- **File**: `src/workflows/resume.ts`
282
- **Changes**:
283
- - In `resumeFromTaskCompletion()` (line 77), where `stepOutput` is built:
284
- ```typescript
285
- // Before:
286
- const stepOutput = { taskId: event.taskId, taskOutput: event.output };
287
- // After:
288
- let taskOutput: unknown = event.output;
289
- if (event.output) {
290
- try {
291
- const parsed = JSON.parse(event.output);
292
- if (typeof parsed === "object" && parsed !== null) {
293
- taskOutput = parsed;
294
- }
295
- } catch {
296
- // Not JSON — keep as string (non-structured output tasks)
297
- }
298
- }
299
- const stepOutput = { taskId: event.taskId, taskOutput };
300
- ```
301
- - This ensures that when a task with `outputSchema` completes, the structured JSON is stored as a parsed object in the workflow context. Downstream nodes can then access nested fields via `{{task1.taskOutput.fileCount}}` through the `interpolate()` dot-path walker (template.ts:18-24).
302
- - For non-structured tasks that produce plain text, the `JSON.parse()` will either fail (caught, keeps string) or parse to a non-object (keeps string). No behavioral change for existing workflows.
303
-
304
- #### 8. Forward outputSchema from workflow config
305
- **File**: `src/workflows/executors/agent-task.ts`
306
- **Changes**:
307
- - Add to `AgentTaskConfigSchema`:
308
- ```typescript
309
- outputSchema: z.record(z.string(), z.unknown()).optional(),
310
- ```
311
- - Forward in `createTaskExtended()` call:
312
- ```typescript
313
- outputSchema: config.outputSchema,
314
- ```
315
-
316
- #### 9. Unit tests
317
- **File**: `src/tests/structured-output.test.ts` (new file)
318
- **Changes**:
319
- - Test: store-progress with valid JSON matching schema → task completes successfully
320
- - Test: store-progress with invalid JSON → tool call fails with error message, task stays in_progress
321
- - Test: store-progress with valid JSON not matching schema → tool call fails with validation errors
322
- - Test: store-progress without outputSchema → no validation, behaves as before
323
- - Test: AgentTaskConfigSchema parses outputSchema
324
- - Test: createTaskExtended stores outputSchema
325
- - Test: resume.ts JSON-parses structured output → downstream context has parsed object
326
- - Test: resume.ts non-JSON output → downstream context keeps string (backward compat)
327
- - Test: `validateJsonSchema()` handles `enum` and `const` constraints correctly
328
-
329
- ### Success Criteria:
330
-
331
- #### Automated Verification:
332
- - [x] Types pass: `bun run tsc:check` ✓
333
- - [x] Lint passes: `bun run lint:fix` ✓
334
- - [x] New test passes: `bun test src/tests/structured-output.test.ts` (18/18) ✓
335
- - [x] All tests pass: `bun test` (1678/1678) ✓
336
- - [x] Migration applies cleanly on fresh DB ✓ (outputSchema stored and retrieved correctly)
337
-
338
- #### Manual Verification:
339
- - [x] Create a task with `outputSchema` via API ✓ (POST /api/tasks returns outputSchema in response, stored correctly)
340
- - [x] Assign to a worker, verify the agent sees the schema in its prompt ✓ (Docker worker picked up task, produced `{"greeting":"Hello!","agentName":"worker-5cd53523"}` matching schema — agent clearly saw and followed the schema instructions)
341
- - [x] Verify store-progress rejects malformed output ✓ (non-JSON rejected, schema mismatch rejected with "missing required property")
342
- - [x] Verify store-progress accepts valid structured output ✓ (worker's store-progress call with valid JSON succeeded, task completed)
343
- - [x] Verify downstream node receives structured data (not raw string) ✓ (JSON-parsed to object, `{{t1.taskOutput.fileCount}}` interpolation works)
344
- - [ ] Verify Claude adapter fallback: kill agent session before it calls store-progress (skipped — agent completed too fast for manual kill; fallback path is unit-tested)
345
-
346
- **Committed**: `9107205` — `feat(workflow): add structured output support for agent-tasks`
347
-
348
- ---
349
-
350
- ## Phase 4: Validation Executor Adapters
351
-
352
- ### Overview
353
- Normalize the pass/fail contract so any executor type can be used as a validator. Add an adapter layer in the validation system that maps each executor's output shape to `{ pass: boolean }`.
354
-
355
- ### Changes Required:
356
-
357
- #### 1. Add pass/fail adapter mapping
358
- **File**: `src/workflows/validation.ts`
359
- **Changes**:
360
- - Add a function `extractPassResult(executorType: string, output: unknown): boolean` that normalizes executor outputs:
361
- ```typescript
362
- function extractPassResult(executorType: string, output: unknown): boolean {
363
- if (!output || typeof output !== "object") return false;
364
- const o = output as Record<string, unknown>;
365
-
366
- switch (executorType) {
367
- case "validate":
368
- return o.pass === true;
369
- case "script":
370
- return o.exitCode === 0;
371
- case "property-match":
372
- return o.passed === true;
373
- case "raw-llm":
374
- // For raw-llm used as validator, check if the LLM output
375
- // contains a structured pass result
376
- if (typeof o.result === "object" && o.result !== null) {
377
- return (o.result as Record<string, unknown>).pass === true;
378
- }
379
- return false;
380
- default:
381
- // Generic fallback: check for common pass indicators
382
- return o.pass === true || o.passed === true || o.exitCode === 0;
383
- }
384
- }
385
- ```
386
- - Replace the hardcoded check at line 53-56:
387
- ```typescript
388
- // Before:
389
- const passed = result.output && (result.output as { pass?: boolean }).pass === true;
390
- // After:
391
- const passed = extractPassResult(executorType, result.output);
392
- ```
393
- Where `executorType` is the resolved executor type from `validation.executor` (already available at line 30).
394
-
395
- #### 2. Unit tests
396
- **File**: `src/tests/validation-adapters.test.ts` (new file)
397
- **Changes**:
398
- - Test: `validate` executor output `{ pass: true }` → passes
399
- - Test: `validate` executor output `{ pass: false }` → fails
400
- - Test: `script` executor output `{ exitCode: 0 }` → passes
401
- - Test: `script` executor output `{ exitCode: 1 }` → fails
402
- - Test: `property-match` executor output `{ passed: true }` → passes
403
- - Test: `property-match` executor output `{ passed: false }` → fails
404
- - Test: unknown executor with `{ pass: true }` → passes (generic fallback)
405
- - Test: null/undefined output → fails
406
-
407
- ### Success Criteria:
408
-
409
- #### Automated Verification:
410
- - [x] Types pass: `bun run tsc:check` ✓
411
- - [x] Lint passes: `bun run lint:fix` ✓
412
- - [x] New test passes: `bun test src/tests/validation-adapters.test.ts` (19/19) ✓
413
- - [x] All tests pass: `bun test` (1697/1697) ✓
414
-
415
- #### Manual Verification:
416
- - [x] Script executor adapter: `exitCode: 0 → pass`, `exitCode: 1 → fail` ✓ (tested via `extractPassResult()` with real output shapes)
417
- - [x] Property-match adapter: `passed: true → pass`, `passed: false → fail` ✓
418
- - [x] Backward compat: validate executor `.pass` still works ✓
419
- - [x] Raw-LLM adapter: `.result.pass` mapping works ✓
420
- - [x] Edge cases: null/undefined → fail, generic fallback → checks common indicators ✓
421
-
422
- **Committed**: `39bebf3` — `feat(workflow): normalize validation pass/fail across all executor types`
423
-
424
- ---
425
-
426
- ## Testing Strategy
427
-
428
- **Unit tests**: Each phase adds its own test file. Tests use isolated SQLite DBs with `initDb()`/`closeDb()` lifecycle.
429
-
430
- **Integration tests**: Manual E2E via API + Docker workers (see research doc's E2E scenarios). Not automated in CI — these require Docker workers.
431
-
432
- **Regression**: `bun test` runs all existing tests to catch regressions.
433
-
434
- ## Manual E2E Verification
435
-
436
- After all phases are complete, run the full E2E scenario from the research doc:
437
-
438
- ```bash
439
- # Setup
440
- rm -f agent-swarm-db.sqlite*
441
- bun run start:http &
442
- bun run docker:build:worker
443
-
444
- docker run --rm -d --name e2e-lead \
445
- --env-file .env.docker-lead -e AGENT_ROLE=lead \
446
- -e MAX_CONCURRENT_TASKS=1 -p 3201:3000 agent-swarm-worker:latest
447
-
448
- docker run --rm -d --name e2e-worker \
449
- --env-file .env.docker \
450
- -e MAX_CONCURRENT_TASKS=1 -p 3203:3000 agent-swarm-worker:latest
451
-
452
- sleep 15
453
-
454
- # 1. Workspace scoping: task with dir
455
- curl -s -X POST http://localhost:3013/api/workflows \
456
- -H "Authorization: Bearer 123123" -H "Content-Type: application/json" \
457
- -d '{
458
- "name": "e2e-workspace-test",
459
- "nodes": [{"id": "t1", "type": "agent-task", "config": {"template": "List files in current dir", "dir": "/workspace/repos/agent-swarm"}}],
460
- "trigger": {"type": "manual"}
461
- }'
462
- # Trigger and verify task.dir is set
463
-
464
- # 2. Structured output: task with outputSchema
465
- curl -s -X POST http://localhost:3013/api/tasks \
466
- -H "Authorization: Bearer 123123" -H "Content-Type: application/json" \
467
- -d '{
468
- "description": "Count files in /tmp. Report as JSON.",
469
- "outputSchema": {"type": "object", "properties": {"fileCount": {"type": "number"}}, "required": ["fileCount"]}
470
- }'
471
- # Verify agent sees schema in prompt, output is structured JSON
472
-
473
- # 3. Validation retry: node with mustPass + retry
474
- curl -s -X POST http://localhost:3013/api/workflows \
475
- -H "Authorization: Bearer 123123" -H "Content-Type: application/json" \
476
- -d '{
477
- "name": "e2e-validation-retry",
478
- "nodes": [{"id": "llm1", "type": "raw-llm", "config": {"prompt": "Generate a random number 1-100", "model": "google/gemini-3-flash-preview"}, "validation": {"executor": "validate", "config": {"prompt": "Is the number > 50?"}, "mustPass": true, "retry": {"maxRetries": 3, "strategy": "static", "baseDelayMs": 1000}}}],
479
- "trigger": {"type": "manual"}
480
- }'
481
- # Verify validation runs on each retry
482
-
483
- # Cleanup
484
- docker stop e2e-lead e2e-worker
485
- kill $(lsof -ti :3013)
486
- ```
487
-
488
- ## References
489
-
490
- - Research: `thoughts/taras/research/2026-03-19-workflow-structured-output-validation-workspace.md`
491
- - Prior research: `thoughts/taras/research/2026-03-19-workflow-node-io-schemas-and-bugs.md`
492
- - Prior plan: `thoughts/taras/plans/2026-03-18-workflow-redesign.md`
493
- - Prior plan: `thoughts/taras/plans/2026-03-19-workflow-io-schemas-and-bugs.md`
494
-
495
- ---
496
-
497
- ## Review Errata
498
-
499
- _Reviewed: 2026-03-20 by claude_
500
-
501
- All findings have been addressed in the plan above.
502
-
503
- ### Resolved
504
-
505
- - [x] **Contradiction about migration** — Removed incorrect "no migration needed" claim from "What We're NOT Doing". Phase 3 step 2 correctly adds migration.
506
- - [x] **Structured output flows as string in workflow context** — Added Phase 3 step 6: JSON-parse structured output in `resume.ts` before storing in workflow context. Ensures `{{task1.taskOutput.fileCount}}` interpolation works.
507
- - [x] **`validateJsonSchema()` is minimal** — Added note to "What We're NOT Doing" about scope. Phase 3 step 3 now includes extending the validator to support `enum` and `const`. Added unit test for validator extensions.
508
- - [x] **Pi-mono adapter failure path unspecified** — Phase 3 step 5 now specifies adapter branching: Claude runs fallback extraction, Pi-mono fails with descriptive reason.
509
- - [x] **`ensureTaskFinished()` refactoring scope** — Restructured Phase 3 step 5 to extract logic into `handleStructuredOutputFallback()` helper, keeping `ensureTaskFinished()` simple with a single call to the helper.
510
- - [x] **Phase 4 script executor test example** — Replaced misleading `echo` command with `test` command that uses actual process exit code.
511
-
512
- ---
513
-
514
- ## Appendix: E2E Test Outcomes
515
-
516
- _Tested: 2026-03-20_
517
-
518
- ### Phase 1: Workspace Scoping
519
-
520
- **E2E-1: Task with `dir`** — PASS
521
- ```
522
- POST /api/workflows → workflow created
523
- POST /api/workflows/:id/trigger → run started
524
- GET /api/tasks?source=workflow →
525
- { task: "List files", dir: "/workspace/repos/agent-swarm", source: "workflow" }
526
- ```
527
-
528
- **E2E-2: Interpolated `dir`** — PASS
529
- ```
530
- Workflow config: dir: "{{trigger.repo_path}}"
531
- Trigger data: { "repo_path": "/workspace/repos/test" }
532
- Created task: { task: "List files in /workspace/repos/test", dir: "/workspace/repos/test" }
533
- ```
534
- Note: interpolation path must use `{{trigger.repo_path}}` since trigger data is stored at `ctx.trigger`.
535
-
536
- ### Phase 2: Validation Retry
537
-
538
- **E2E-3: Validation retry with raw-llm + LLM validation** — PASS
539
- ```
540
- Workflow: raw-llm generates random number 1-100
541
- Validation: LLM checks if number > 95 (mustPass: true, maxRetries: 3)
542
- Server logs:
543
- [workflows] Retrying step llm1 (attempt 1)
544
- [workflows] Retrying step llm1 (attempt 2)
545
- [workflows] Retrying step llm1 (attempt 3)
546
- Final state:
547
- step: { status: "failed", retryCount: 3, nextRetryAt: null, finishedAt: "2026-03-20T20:03:51Z" }
548
- run: { status: "failed", error: "Step failed: Validation failed, retrying" }
549
- ```
550
- Bonus discovery: found and fixed pre-existing bug where `checkpointStepFailure` didn't clear `nextRetryAt` on terminal failure, causing infinite retry loops (commit `ccc5162`).
551
-
552
- ### Phase 3: Structured Output
553
-
554
- **E2E-4: Agent sees outputSchema in prompt** — PASS (Docker worker)
555
- ```
556
- Task: "Say hello and report your name as JSON"
557
- outputSchema: { type: "object", properties: { greeting: { type: "string" }, agentName: { type: "string" } }, required: [...] }
558
- Worker output: {"greeting": "Hello!", "agentName": "worker-5cd53523"}
559
- ```
560
- Agent clearly saw and followed the schema instructions, produced valid JSON via store-progress.
561
-
562
- **E2E-5: store-progress validation** — PASS
563
- ```
564
- Non-JSON input: → rejected ("Task output must be valid JSON")
565
- Schema mismatch: → rejected ("missing required property 'count'")
566
- Valid JSON output: → accepted, task completed
567
- ```
568
-
569
- **E2E-6: Downstream receives parsed structured data** — PASS
570
- ```
571
- JSON output stored as string in DB: '{"fileCount":42,"path":"/tmp"}'
572
- resume.ts JSON-parses → object in workflow context
573
- Interpolation {{t1.taskOutput.fileCount}} → 42
574
- Plain text output stays as string (backward compat)
575
- ```
576
-
577
- **E2E-7: Validation adapters** — PASS
578
- ```
579
- extractPassResult("script", { exitCode: 0 }) → true
580
- extractPassResult("script", { exitCode: 1 }) → false
581
- extractPassResult("property-match", { passed: true }) → true
582
- extractPassResult("property-match", { passed: false }) → false
583
- extractPassResult("validate", { pass: true }) → true
584
- extractPassResult("raw-llm", { result: { pass: true } }) → true
585
- extractPassResult("custom", { pass: true }) → true (generic fallback)
586
- extractPassResult("validate", null) → false (edge case)
587
- ```
588
-
589
- ### DB Record: Structured Output Task (Docker Worker)
590
-
591
- ```json
592
- {
593
- "id": "ae75f674",
594
- "task": "Say hello and report your name as JSON. This is a trivial test task.",
595
- "status": "completed",
596
- "source": "api",
597
- "output": {
598
- "greeting": "Hello!",
599
- "agentName": "worker-5cd53523"
600
- },
601
- "outputSchema": {
602
- "type": "object",
603
- "properties": {
604
- "greeting": { "type": "string" },
605
- "agentName": { "type": "string" }
606
- },
607
- "required": ["greeting", "agentName"]
608
- }
609
- }
610
- ```
611
-
612
- ---
613
-
614
- ## Post-Implementation Verification
615
-
616
- _Verified: 2026-03-20 by claude_
617
-
618
- **Verdict: PASS** — All 4 phases correctly implemented, no discrepancies.
619
-
620
- ### Automated Checks
621
-
622
- | Check | Result |
623
- |-------|--------|
624
- | `bun run tsc:check` | Pass (no errors) |
625
- | `bun run lint:fix` | Pass (warnings only) |
626
- | `bun test` | 1697/1697 pass, 0 fail |
627
-
628
- ### Phase-by-Phase Code Verification
629
-
630
- - **Phase 1 (Workspace Scoping)**: `AgentTaskConfigSchema` has all 4 new fields, `execute()` forwards them, 6 unit tests pass. Commit `405d679`.
631
- - **Phase 2 (Validation Retry)**: `retry-poller.ts` calls `runStepValidation()` after retry, handles halt/retry/pass. `checkpoint.ts` clears `nextRetryAt` on exhaustion. 3 unit tests pass. Commits `2e91344`, `ccc5162`.
632
- - **Phase 3 (Structured Output)**: All 10 sub-checks verified — types, DB, migration, store-progress validation, prompt injection, fallback extraction, resume JSON-parsing, agent-task forwarding, json-schema-validator enum/const, 18 unit tests. Commit `9107205`.
633
- - **Phase 4 (Validation Adapters)**: `extractPassResult()` with 5 executor adapters + generic fallback. Hardcoded check replaced. 19 unit tests pass. Commit `39bebf3`.
634
-
635
- ### Open Items
636
-
637
- - Claude adapter fallback E2E (Phase 3): Skipped — agent completed too fast for manual kill. Fallback path is unit-tested. Acceptable trade-off.
638
-
639
- ---
640
-
641
- ## E2E Verification: Structured I/O with Docker Worker
642
-
643
- _Verified: 2026-03-20 by taras+claude_
644
-
645
- **Verdict: PASS** — Full workflow with structured input/output, context propagation, and two sequential agent-task nodes completed successfully with a single Docker worker.
646
-
647
- ### What was tested
648
-
649
- A 2-node sequential workflow exercising the structured I/O pipeline end-to-end:
650
-
651
- 1. **Node `generate-city`** (agent-task): Asks agent to produce a JSON object with `city`, `country`, `population`. Has `config.outputSchema` for schema validation.
652
- 2. **Node `summarize-city`** (agent-task): Uses `inputs` mapping to pull step 1's output into interpolation context. Template references `{{cityData.taskOutput.city}}` etc. Also has `config.outputSchema`.
653
-
654
- ### Verification checklist
655
-
656
- | Check | Result |
657
- |-------|--------|
658
- | `config.outputSchema` flows from workflow node → task creation | ✅ Task has `outputSchema` field set |
659
- | Agent produces structured JSON validated against schema | ✅ `{"city":"Lisbon","country":"Portugal","population":545000}` |
660
- | `resume.ts` JSON-parses task output into run context | ✅ Context has parsed object, not string |
661
- | `inputs` mapping scopes upstream data for interpolation | ✅ `"cityData": "generate-city"` resolved correctly |
662
- | Template interpolation resolves nested paths | ✅ `{{cityData.taskOutput.city}}` → `"Lisbon"` |
663
- | Second node receives interpolated values | ✅ Task prompt: "The city is Lisbon in Portugal with population 545000" |
664
- | Second node produces its own structured output | ✅ `{"summary":"Lisbon is a city in Portugal with a population of 545000"}` |
665
- | Workflow completes with both outputs in final context | ✅ Both steps in `run.context` |
666
-
667
- ### Workflow definition (copy-paste to recreate)
668
-
669
- ```json
670
- {
671
- "name": "structured-io-e2e",
672
- "definition": {
673
- "nodes": [
674
- {
675
- "id": "generate-city",
676
- "type": "agent-task",
677
- "label": "Generate city data",
678
- "config": {
679
- "template": "Respond with ONLY a valid JSON object (no markdown, no explanation, no code fences) describing a real city. Use exactly this format: {\"city\": \"Tokyo\", \"country\": \"Japan\", \"population\": 14000000}. Pick any real city you like. Output ONLY the JSON object, nothing else.",
680
- "outputSchema": {
681
- "type": "object",
682
- "required": ["city", "country", "population"],
683
- "properties": {
684
- "city": { "type": "string" },
685
- "country": { "type": "string" },
686
- "population": { "type": "number" }
687
- }
688
- }
689
- },
690
- "next": "summarize-city"
691
- },
692
- {
693
- "id": "summarize-city",
694
- "type": "agent-task",
695
- "label": "Summarize city data",
696
- "inputs": { "cityData": "generate-city" },
697
- "config": {
698
- "template": "You received city data from a previous step. The city is {{cityData.taskOutput.city}} in {{cityData.taskOutput.country}} with population {{cityData.taskOutput.population}}. Respond with ONLY a valid JSON object (no markdown, no explanation, no code fences) in this exact format: {\"summary\": \"<city> is a city in <country> with a population of <population>\"}. Output ONLY the JSON object, nothing else.",
699
- "outputSchema": {
700
- "type": "object",
701
- "required": ["summary"],
702
- "properties": { "summary": { "type": "string" } }
703
- }
704
- }
705
- }
706
- ]
707
- }
708
- }
709
- ```
710
-
711
- ### Learnings & roadblocks
712
-
713
- 1. **`inputs` mapping is REQUIRED for cross-node data access** (gotcha): Without an explicit `inputs` mapping on a node, the interpolation context only includes `trigger` and `input` (workflow-level inputs) — upstream step outputs are NOT available. This is by design (engine.ts:316-340) for encapsulation, but it's a non-obvious foot-gun for workflow authors. The first test run failed with `unresolvedTokens` diagnostics until `"inputs": {"cityData": "generate-city"}` was added. This should be prominently documented in workflow authoring guides.
714
-
715
- 2. **`outputSchema` placement matters**: Node-level `outputSchema` (on the WorkflowNode) validates the executor's return value (e.g. `{taskId, taskOutput}`). The `config.outputSchema` on agent-task nodes is what gets forwarded to the created task and validates the agent's raw output. These are different schemas at different layers. For structured agent output, the schema goes in `config.outputSchema`.
716
-
717
- 3. **Stale `in_progress` tasks block worker pickup**: When a worker's Claude session claims a task but exits before completing it, the task remains `in_progress` with `assignedTo=none`. The worker polls for `unassigned` tasks only, so it never sees the stranded task. Restarting the worker doesn't help — the task is permanently stuck. This happened during testing when the first session claimed the second task within the same session but exited after completing only the first. A stale-task recovery mechanism (timeout → reset to `unassigned`) would prevent this.
718
-
719
- 4. **Lead vs worker for workflow tasks**: The lead agent's polling mechanism didn't pick up workflow-created tasks during testing (it polled but never triggered). The worker agent did. For workflow E2E testing, use a worker container, not a lead.
720
-
721
- 5. **Clean DB between test runs is critical**: Old stale tasks (`in_progress` from previous runs) persist across API restarts and block subsequent runs. Always `rm -f agent-swarm-db.sqlite*` before a clean E2E test, and ensure the API server is fully stopped before deleting (WAL replay can resurrect data).
722
-
723
- 6. **Docker env files need port adjustment per worktree**: `.env.docker` and `.env.docker-lead` hardcode `MCP_BASE_URL=http://host.docker.internal:3013`. Worktrees on alternate ports (e.g. 3014) need manual update.