@humwick/server 0.130.1 → 0.130.2

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 (437) hide show
  1. package/README.md +5 -0
  2. package/docs/guides/tools-administration.md +4 -0
  3. package/docs/guides/tools-coordination.md +1 -0
  4. package/docs/guides/tools-tasks.md +8 -0
  5. package/docs/guides/workflows.md +58 -0
  6. package/docs/openapi.json +414 -1
  7. package/package.json +8 -17
  8. package/public/assets/{MessageBubble-BWpoBjl4.js → MessageBubble-BWLqMGKG.js} +2 -2
  9. package/public/assets/{PlanGraphPanel-C0auck3n.js → PlanGraphPanel-3TlIQpjk.js} +2 -2
  10. package/public/assets/{TraceView-DBnOx7AQ.js → TraceView-Wimm0Czv.js} +2 -2
  11. package/public/assets/{VaultDecisionCard-0kp2oNBC.js → VaultDecisionCard-Bau_vNax.js} +2 -2
  12. package/public/assets/{activity-yLztXEBt.js → activity-CrSurn-r.js} +2 -2
  13. package/public/assets/{agent-lineage-BbJDR1dW.js → agent-lineage-CknAJKcb.js} +2 -2
  14. package/public/assets/agent-liveness-CaNwK0Zf.js +2 -0
  15. package/public/assets/{agent-name-CTZBrSD9.js → agent-name-DKbiIhBo.js} +2 -2
  16. package/public/assets/agent-profiles-DwF6EQ4R.js +2 -0
  17. package/public/assets/{agent-project-badge-9TqzUUYE.js → agent-project-badge-Diz4Sjjb.js} +2 -2
  18. package/public/assets/{agent-tools-D4n40pn8.js → agent-tools-CRhpRQza.js} +2 -2
  19. package/public/assets/{agent-type-icon-D6FUarOf.js → agent-type-icon-LrUEU3lB.js} +2 -2
  20. package/public/assets/{agents-BYDslkJc.js → agents-B-v66C-4.js} +2 -2
  21. package/public/assets/{analytics-B-XSbEMC.js → analytics-BqCb-LKi.js} +2 -2
  22. package/public/assets/{artifact-viewer-DdWIfV6M.js → artifact-viewer-kf4pGuAR.js} +2 -2
  23. package/public/assets/{artifacts-oBOqks-2.js → artifacts-D32zyw4Y.js} +2 -2
  24. package/public/assets/{artifacts-DPN1q4pA.js → artifacts-DJevXcvg.js} +2 -2
  25. package/public/assets/{automation-4KcRFXEu.js → automation-BpRajx_5.js} +2 -2
  26. package/public/assets/{backlog-Cw9xPTCF.js → backlog-D_UjTdzX.js} +2 -2
  27. package/public/assets/{busy-health-CTu32MZt.js → busy-health-N3VEh4ao.js} +2 -2
  28. package/public/assets/{channels-BiXzg1G9.js → channels-9jopungq.js} +2 -2
  29. package/public/assets/{chat-Ctk2qwvA.js → chat-CSXrTB3C.js} +2 -2
  30. package/public/assets/{code-preview-Bm1wWqAp.js → code-preview-p1NnmqK0.js} +2 -2
  31. package/public/assets/{connectors-C36ax4Vw.js → connectors-CZdqlDNL.js} +2 -2
  32. package/public/assets/{cosmos-Jj9LK2Wf.js → cosmos-BgdsE4dG.js} +2 -2
  33. package/public/assets/{crate-agent-H6S7-B9T.js → crate-agent-30aXTKva.js} +2 -2
  34. package/public/assets/{dependency-graph-Cd1E23wa.js → dependency-graph-B_jvw2GE.js} +2 -2
  35. package/public/assets/{deploys-Bwfq146q.js → deploys-DoN6bAb5.js} +2 -2
  36. package/public/assets/{display-CfO7rTuF.js → display-BrKWFGJz.js} +2 -2
  37. package/public/assets/{files-DhhZI2Ih.js → files-D6XEu8Ng.js} +2 -2
  38. package/public/assets/{fleet-B_rFEbnL.js → fleet-C7jQWbw2.js} +2 -2
  39. package/public/assets/{fleet-metrics-BkHP-P3R.js → fleet-metrics-BiDs3MLx.js} +2 -2
  40. package/public/assets/{formatted-body-Cm1RrzmN.js → formatted-body-CQBwc1fb.js} +3 -3
  41. package/public/assets/{formatted-body-impl-DQiOuOD1.js → formatted-body-impl-DyG0WsQS.js} +2 -2
  42. package/public/assets/{host-providers-dialog-CHqwXTov.js → host-providers-dialog-DKaW31dN.js} +2 -2
  43. package/public/assets/index-CRHep3M9.js +15 -0
  44. package/public/assets/index-MYAIwYTX.css +2 -0
  45. package/public/assets/{insights-fH1EL-qZ.js → insights-CzrtkpOE.js} +2 -2
  46. package/public/assets/{integrations-C5Oix6ng.js → integrations-aVsUmigt.js} +2 -2
  47. package/public/assets/{issue-ref-chip-ODyondIa.js → issue-ref-chip-BnSlM_95.js} +2 -2
  48. package/public/assets/{log-viewer-Cvfy6PW7.js → log-viewer-qe7Ee47Z.js} +2 -2
  49. package/public/assets/{maintenance-D8CDH5wZ.js → maintenance-NfjqFZAk.js} +2 -2
  50. package/public/assets/{managed-agents-egllbpij.js → managed-agents-BiH0HgaE.js} +2 -2
  51. package/public/assets/{markdown-preview-CYSFgVgK.js → markdown-preview-BixaT3Xr.js} +3 -3
  52. package/public/assets/{markdown-preview-impl-BteVIjX4.js → markdown-preview-impl-DNGlWIS3.js} +2 -2
  53. package/public/assets/{memory-C8WmXsyr.js → memory-DNsCl6UX.js} +2 -2
  54. package/public/assets/{messages-BzQdqlO6.js → messages-DopU1L1X.js} +2 -2
  55. package/public/assets/{orchestrators-B1HxzkNw.js → orchestrators-Cq7ckLQT.js} +2 -2
  56. package/public/assets/{overview-DCUnI4Z7.js → overview-C1DCTzzV.js} +2 -2
  57. package/public/assets/{pairs-ftCd2XcD.js → pairs-DE_m6rrE.js} +2 -2
  58. package/public/assets/{profile-icon-B2zH8DMH.js → profile-icon-B3rfh77F.js} +2 -2
  59. package/public/assets/project-profile-instructions-DQWZE0kA.js +2 -0
  60. package/public/assets/projects-Br2Bd2h1.js +2 -0
  61. package/public/assets/{prompt-settings-Bftq9czX.js → prompt-settings-BKvFsvGD.js} +2 -2
  62. package/public/assets/provider-display-DsuWMvVL.js +2 -0
  63. package/public/assets/{registry-DWCU5c8q.js → registry-Cw38_6gW.js} +2 -2
  64. package/public/assets/run-card-CpKqRbhg.js +2 -0
  65. package/public/assets/scroll-text-BKXS1ahr.js +2 -0
  66. package/public/assets/{secrets-C7GIUATz.js → secrets-DxI-vzSq.js} +2 -2
  67. package/public/assets/{service-access-settings-C3aujqTG.js → service-access-settings-D9s_VJbd.js} +2 -2
  68. package/public/assets/{settings-C6sZ9eBa.js → settings-CKZTVGIx.js} +2 -2
  69. package/public/assets/{shipping-Bu8p1gEw.js → shipping-B9YtnwtG.js} +2 -2
  70. package/public/assets/{stats-V9Z-GxUd.js → stats-DyUBKyWI.js} +2 -2
  71. package/public/assets/{status-dot-CVv0iGHL.js → status-dot-DYqlEUhJ.js} +2 -2
  72. package/public/assets/{store-BvtFdlGX.js → store-DcClXLH0.js} +3 -3
  73. package/public/assets/{tasks-CXU75HRF.js → tasks-Bh7Chr4-.js} +2 -2
  74. package/public/assets/{teams-BPf976zb.js → teams-bowI7qVY.js} +2 -2
  75. package/public/assets/{terminal-viewer-DE9BOe-8.js → terminal-viewer-BgVLHdsU.js} +3 -3
  76. package/public/assets/{terminal-viewer-impl-D04pjmGh.js → terminal-viewer-impl-Dz22UPy6.js} +2 -2
  77. package/public/assets/token-estimate-Co-Jdphh.js +2 -0
  78. package/public/assets/{use-agent-terminal-B1yR456R.js → use-agent-terminal-DSQQ-iY7.js} +2 -2
  79. package/public/assets/{use-decisions-D-S4tpDf.js → use-decisions-samMQhQf.js} +2 -2
  80. package/public/assets/use-project-list-59LheVP7.js +2 -0
  81. package/public/assets/{use-selectors-CnrAk2YP.js → use-selectors-BZa25xEB.js} +2 -2
  82. package/public/assets/{user-avatar-nBFIcR4M.js → user-avatar-DHxlvUvV.js} +2 -2
  83. package/public/assets/versioned-prompt-editor-BmED5DnJ.js +8 -0
  84. package/public/assets/{work-queue-TCjJxeT-.js → work-queue-CSvpuNLz.js} +2 -2
  85. package/public/assets/{workflow-marker-Cf3Hf2fN.js → workflow-marker-DAZcj5qt.js} +2 -2
  86. package/public/assets/{workflows-CXQX20Qj.js → workflows-DdmxRSyg.js} +2 -2
  87. package/public/assets/{workspaces-qSYzKYMA.js → workspaces-BxeKfVuF.js} +2 -2
  88. package/public/cosmos.html +4 -4
  89. package/public/index.html +31 -29
  90. package/runner/plugins/claude/.claude-plugin/plugin.json +1 -1
  91. package/runner/plugins/claude/hooks/gate-run-guard.provisioned.mjs +31 -1
  92. package/runner/src/adapters/claude-effort.ts +2 -4
  93. package/runner/src/adapters/codex-launch-config.ts +4 -5
  94. package/runner/src/adapters/codex.ts +1 -1
  95. package/runner/src/adapters/opencode-provider.ts +7 -22
  96. package/runner/src/adapters/opencode.ts +4 -4
  97. package/runner/src/agent-runner/credentials.ts +42 -12
  98. package/runner/src/agent-runner/inbox.ts +27 -0
  99. package/runner/src/agent-runner/lifecycle-milestones.ts +0 -2
  100. package/runner/src/bin/claude.ts +4 -0
  101. package/runner/src/bin/codex.ts +4 -0
  102. package/runner/src/bin/opencode.ts +4 -0
  103. package/runner/src/index.ts +5 -2
  104. package/runner/src/provider-setup.ts +34 -0
  105. package/runner/src/providers.ts +2 -1
  106. package/runner/src/runner-core.ts +18 -23
  107. package/runner/src/spawn-input.ts +2 -1
  108. package/runner/src/test-run-dedup.ts +59 -56
  109. package/scripts/cd-config.ts +8 -0
  110. package/scripts/gate-run-lease.ts +10 -7
  111. package/scripts/gate.sh +5 -1
  112. package/src/branch-land-notice.ts +93 -0
  113. package/src/branch-landed.ts +7 -76
  114. package/src/bus.ts +19 -20
  115. package/src/cd-deploy-notify.ts +30 -2
  116. package/src/cd-host-lag-notify.ts +7 -6
  117. package/src/ci/incidents.ts +2 -2
  118. package/src/ci/monitor.ts +5 -8
  119. package/src/ci/root-missing.ts +2 -7
  120. package/src/ci/transition-notify.ts +7 -39
  121. package/src/cli/cd-pauses.ts +19 -0
  122. package/src/cli/orchestrator.ts +1 -1
  123. package/src/cli/state.ts +2 -19
  124. package/src/cli/task-edit.ts +22 -0
  125. package/src/cli/task.ts +3 -1
  126. package/src/cli/workflow.ts +8 -2
  127. package/src/commands-db.ts +3 -3
  128. package/src/config-store-write.ts +13 -1
  129. package/src/config-store.ts +25 -14
  130. package/src/db/activity-async.ts +6 -1
  131. package/src/db/activity-write-ops.ts +12 -1
  132. package/src/db/activity.ts +1 -14
  133. package/src/db/agent-search.ts +1 -15
  134. package/src/db/agents-async.ts +52 -5
  135. package/src/db/agents-write-ops.ts +12 -3
  136. package/src/db/agents.ts +81 -54
  137. package/src/db/ci-incidents-async.ts +5 -5
  138. package/src/db/ci-incidents-write-ops.ts +2 -2
  139. package/src/db/command-row.ts +10 -2
  140. package/src/db/commands-list-query.ts +2 -0
  141. package/src/db/commands-spawn-read.ts +1 -1
  142. package/src/db/config-store-write-ops.ts +7 -2
  143. package/src/db/continuation-archives-async.ts +5 -0
  144. package/src/db/continuation-archives-write-ops.ts +7 -0
  145. package/src/db/continuations.ts +2 -2
  146. package/src/db/db-writer-worker.ts +8 -1
  147. package/src/db/deploy-events-async.ts +1 -0
  148. package/src/db/deploy-events-read-ops.ts +2 -1
  149. package/src/db/deploy-events.ts +35 -4
  150. package/src/db/hosts-registration.ts +10 -2
  151. package/src/db/hosts.ts +9 -6
  152. package/src/db/inbox.ts +0 -14
  153. package/src/db/index.ts +2 -0
  154. package/src/db/integrations-async.ts +8 -0
  155. package/src/db/integrations-ops.ts +15 -0
  156. package/src/db/integrations.ts +15 -21
  157. package/src/db/issue-lifecycle.ts +3 -4
  158. package/src/db/issue-refs-async.ts +20 -0
  159. package/src/db/issue-refs-write-ops.ts +29 -0
  160. package/src/db/issue-refs.ts +7 -8
  161. package/src/db/long-running-work.ts +2 -2
  162. package/src/db/main-connection-writes.ts +23 -2
  163. package/src/db/maintenance-job-reconcile.ts +61 -0
  164. package/src/db/maintenance-job-runs-async.ts +14 -0
  165. package/src/db/maintenance-job-write-ops.ts +9 -0
  166. package/src/db/mappers.ts +2 -14
  167. package/src/db/merge-lease.ts +1 -15
  168. package/src/db/migrations.ts +7 -15
  169. package/src/db/orchestrators.ts +4 -72
  170. package/src/db/pairs.ts +1 -13
  171. package/src/db/project-profile-instructions.ts +50 -0
  172. package/src/db/prompt-versions.ts +9 -2
  173. package/src/db/provider-config-history.ts +8 -3
  174. package/src/db/provider-model-seed.ts +34 -0
  175. package/src/db/read-op-marshaling-fixtures.ts +5 -0
  176. package/src/db/read-ops.ts +4 -0
  177. package/src/db/routing-policy.ts +2 -3
  178. package/src/db/schema.ts +9 -3
  179. package/src/db/spawn-delegation-state.ts +11 -4
  180. package/src/db/stats-async.ts +4 -3
  181. package/src/db/task-entity.ts +23 -2
  182. package/src/db/task-list.ts +3 -1
  183. package/src/db/tasks.ts +1 -17
  184. package/src/db/timer-ingress.ts +7 -1
  185. package/src/db/token-db-write-ops.ts +17 -0
  186. package/src/db/token-standing.ts +15 -11
  187. package/src/db/workflow-contact.ts +1 -1
  188. package/src/db/workflow-task-read-ops.ts +30 -0
  189. package/src/db/write-ops.ts +6 -0
  190. package/src/db/writer-gateway.ts +17 -11
  191. package/src/dispatch-availability.ts +10 -6
  192. package/src/ephemeral/{landing-ingress-proof-worker.ts → landing-ingress-proof.test-fixture.ts} +4 -2
  193. package/src/host/disk-alert.ts +121 -0
  194. package/src/lifecycle-manager.ts +3 -2
  195. package/src/maintenance/cd-watcher.ts +3 -3
  196. package/src/maintenance/critical-job-watchdog.ts +16 -17
  197. package/src/maintenance/index.ts +1 -0
  198. package/src/maintenance/jobs.ts +3 -2
  199. package/src/maintenance/scheduler.ts +84 -128
  200. package/src/maintenance/stalled-delivery-pager.ts +6 -5
  201. package/src/maintenance/workspaces.ts +1 -1
  202. package/src/managed-policy.ts +31 -27
  203. package/src/mcp/index.ts +5 -2
  204. package/src/mcp/output-descriptions.ts +8 -8
  205. package/src/mcp/presentation.ts +4 -4
  206. package/src/mcp/project-profile-instructions.ts +32 -0
  207. package/src/mcp/tool-groups.ts +1 -1
  208. package/src/mcp/tools-spawn.ts +4 -3
  209. package/src/mcp-agent-action.ts +1 -2
  210. package/src/mcp-issue-ref-tools.ts +12 -11
  211. package/src/mcp-maintenance-tools.ts +2 -2
  212. package/src/mcp-profile-trust-tools.ts +4 -4
  213. package/src/mcp-provider-catalog.ts +2 -2
  214. package/src/mcp-task-tools.ts +11 -5
  215. package/src/mcp-team-template-tools.ts +3 -3
  216. package/src/mcp-workflow-tools.ts +10 -3
  217. package/src/notification-types.ts +2 -1
  218. package/src/operator-alarm.ts +26 -11
  219. package/src/project-instructions.ts +4 -0
  220. package/src/project-profile-instruction-text.ts +6 -0
  221. package/src/project-profile-instructions.ts +20 -0
  222. package/src/provider-catalog-store.ts +3 -49
  223. package/src/provider-config-store.ts +12 -11
  224. package/src/provider-model-seed.ts +1 -18
  225. package/src/provider-quota-config-store.ts +5 -4
  226. package/src/provider-secrets.test-fixture.ts +3 -3
  227. package/src/recipe-runner.ts +2 -2
  228. package/src/repo-config-source.ts +10 -4
  229. package/src/routes/agent-profiles.ts +6 -6
  230. package/src/routes/agents-spawn.ts +1 -1
  231. package/src/routes/agents.ts +6 -6
  232. package/src/routes/commands-listing.ts +4 -0
  233. package/src/routes/commands.ts +2 -2
  234. package/src/routes/continuation-archives.ts +2 -2
  235. package/src/routes/index.ts +10 -1
  236. package/src/routes/integrations.ts +24 -50
  237. package/src/routes/issue-refs.ts +7 -7
  238. package/src/routes/orchestrator-bootstrap.ts +1 -1
  239. package/src/routes/orchestrator-host-registration.ts +2 -2
  240. package/src/routes/orchestrator-host-utilization.ts +3 -1
  241. package/src/routes/orchestrator-proxy.ts +2 -2
  242. package/src/routes/orchestrator.ts +2 -2
  243. package/src/routes/project-profile-instructions.ts +27 -0
  244. package/src/routes/project-trust.ts +2 -2
  245. package/src/routes/provider-config.ts +6 -6
  246. package/src/routes/provider-quota-config.ts +2 -2
  247. package/src/routes/settings.ts +5 -5
  248. package/src/routes/stats.ts +6 -6
  249. package/src/routes/task-http.ts +15 -1
  250. package/src/routes/task-issues.ts +11 -26
  251. package/src/routes/tasks.ts +22 -53
  252. package/src/routes/team-templates.ts +5 -5
  253. package/src/routes/teams-config.ts +2 -2
  254. package/src/routes/tokens.ts +12 -5
  255. package/src/routes/workflows.ts +20 -5
  256. package/src/routing-policy-normalize.ts +1 -2
  257. package/src/routing-step-defaults.ts +0 -2
  258. package/src/runner-token-mint-limit.ts +63 -0
  259. package/src/runtime-grant.ts +4 -2
  260. package/src/runtime-tokens.ts +39 -7
  261. package/src/security.ts +13 -20
  262. package/src/server-background.ts +1 -1
  263. package/src/server.ts +5 -2
  264. package/src/services/host-utilization.ts +23 -0
  265. package/src/services/idle-epics.ts +5 -6
  266. package/src/services/issue-lifecycle.ts +57 -61
  267. package/src/services/issue-refs.ts +9 -13
  268. package/src/services/kernel-timers-cutover-chaos-worker.ts +10 -7
  269. package/src/services/kernel-timers-ingress.ts +1 -1
  270. package/src/services/landed-ancestry.ts +19 -3
  271. package/src/services/memory-areas.ts +15 -51
  272. package/src/services/plan-ci-notice.ts +57 -0
  273. package/src/services/plan-ci-recovery.ts +2 -55
  274. package/src/services/plan-wake-digest.ts +1 -0
  275. package/src/services/profile-trust.ts +4 -3
  276. package/src/services/project-config-read.ts +70 -0
  277. package/src/services/project-profile-instructions.ts +54 -0
  278. package/src/services/provisioning-harness/budget-baseline.json +4 -4
  279. package/src/services/restart-spawn.ts +61 -49
  280. package/src/services/self-care-state.ts +2 -1
  281. package/src/services/self-effort.ts +5 -5
  282. package/src/services/send-message.ts +5 -1
  283. package/src/services/spawn-agent.ts +13 -2
  284. package/src/services/spawn-chain-inspector.ts +6 -13
  285. package/src/services/spawn-policy.ts +68 -0
  286. package/src/services/spawn-tree-cleanup.ts +2 -2
  287. package/src/services/task-dispatch.ts +3 -0
  288. package/src/services/task-state-reconcile.ts +6 -14
  289. package/src/services/team-templates.ts +9 -8
  290. package/src/services/transient-agent-reaper.ts +3 -1
  291. package/src/services/workflow-auto-start.ts +25 -13
  292. package/src/services/workflow-ci-main.ts +1 -1
  293. package/src/services/workflow-deferred-cleanup.ts +4 -2
  294. package/src/services/workflow-effect-driver.ts +2 -0
  295. package/src/services/workflow-effects.ts +18 -11
  296. package/src/services/workflow-land-notice.ts +10 -0
  297. package/src/services/workflow-pause-text.ts +43 -0
  298. package/src/services/workflow-reconcile.ts +13 -11
  299. package/src/services/workflow-run-view.ts +2 -0
  300. package/src/services/workflow-runs.ts +29 -13
  301. package/src/services/workflow-supervisor-state.ts +5 -0
  302. package/src/services/workflow-supervisor.ts +7 -3
  303. package/src/settings/registry.ts +1 -2
  304. package/src/spawn-command.ts +4 -4
  305. package/src/spawn-models.ts +10 -12
  306. package/src/spawn-placement.ts +1 -1
  307. package/src/spawn-targets.ts +1 -1
  308. package/src/startup-context-injection.ts +1 -0
  309. package/src/state-adoption/cd-cutover.ts +53 -7
  310. package/src/state-adoption/fleet-cutover.ts +35 -0
  311. package/src/state-adoption/fleet-plan.ts +36 -0
  312. package/src/state-adoption/index.ts +2 -2
  313. package/src/state-adoption/linux-plan.ts +2 -2
  314. package/src/state-adoption/linux.ts +2 -2
  315. package/src/state-adoption/macos-plan.ts +2 -2
  316. package/src/state-adoption/macos.ts +1 -1
  317. package/src/steward.ts +7 -6
  318. package/src/task-dispatch-live.ts +1 -1
  319. package/src/task-dispatcher.ts +1 -1
  320. package/src/teams-config-store.ts +4 -3
  321. package/src/token-db-write.ts +10 -0
  322. package/src/workspace-command-settle.ts +2 -1
  323. package/src/workspace-steward-wake.ts +2 -2
  324. package/node_modules/@humwick/kernel/LICENSE +0 -167
  325. package/node_modules/@humwick/kernel/async-entity-persistence.ts +0 -344
  326. package/node_modules/@humwick/kernel/async-event-log.ts +0 -107
  327. package/node_modules/@humwick/kernel/automations.pilot.ts +0 -147
  328. package/node_modules/@humwick/kernel/config.ts +0 -111
  329. package/node_modules/@humwick/kernel/contract.ts +0 -572
  330. package/node_modules/@humwick/kernel/control-authz.ts +0 -281
  331. package/node_modules/@humwick/kernel/control.ts +0 -645
  332. package/node_modules/@humwick/kernel/effects.ts +0 -493
  333. package/node_modules/@humwick/kernel/event-log.ts +0 -319
  334. package/node_modules/@humwick/kernel/http-transport.ts +0 -384
  335. package/node_modules/@humwick/kernel/identity-grammar.ts +0 -20
  336. package/node_modules/@humwick/kernel/identity.ts +0 -248
  337. package/node_modules/@humwick/kernel/index.ts +0 -28
  338. package/node_modules/@humwick/kernel/kernel-persistence.ts +0 -181
  339. package/node_modules/@humwick/kernel/landing-incident.ts +0 -306
  340. package/node_modules/@humwick/kernel/landing.ts +0 -953
  341. package/node_modules/@humwick/kernel/manifest-validation.ts +0 -460
  342. package/node_modules/@humwick/kernel/mcp-transport.ts +0 -109
  343. package/node_modules/@humwick/kernel/message-authority-chaos-worker.ts +0 -200
  344. package/node_modules/@humwick/kernel/message-authority.ts +0 -281
  345. package/node_modules/@humwick/kernel/module-host.ts +0 -722
  346. package/node_modules/@humwick/kernel/openapi-init.ts +0 -14
  347. package/node_modules/@humwick/kernel/package.json +0 -39
  348. package/node_modules/@humwick/kernel/persistence-schema.ts +0 -248
  349. package/node_modules/@humwick/kernel/persistence.ts +0 -510
  350. package/node_modules/@humwick/kernel/registry.ts +0 -60
  351. package/node_modules/@humwick/kernel/sqlite-kernel-persistence.ts +0 -499
  352. package/node_modules/@humwick/kernel/sqlite-module-host.ts +0 -87
  353. package/node_modules/@humwick/kernel/timers-chaos-worker.ts +0 -186
  354. package/node_modules/@humwick/kernel/timers.pilot.ts +0 -1411
  355. package/node_modules/@humwick/kernel/workflow-activation.ts +0 -25
  356. package/node_modules/@humwick/kernel/workflow-backstop.ts +0 -40
  357. package/node_modules/@humwick/kernel/workflow-cancel-tree.ts +0 -20
  358. package/node_modules/@humwick/kernel/workflow-chaos-worker.ts +0 -213
  359. package/node_modules/@humwick/kernel/workflow-composition.ts +0 -231
  360. package/node_modules/@humwick/kernel/workflow-container.ts +0 -72
  361. package/node_modules/@humwick/kernel/workflow-control.test-fixture.ts +0 -42
  362. package/node_modules/@humwick/kernel/workflow-control.ts +0 -178
  363. package/node_modules/@humwick/kernel/workflow-definition.ts +0 -507
  364. package/node_modules/@humwick/kernel/workflow-dispatch.ts +0 -60
  365. package/node_modules/@humwick/kernel/workflow-foreach.ts +0 -167
  366. package/node_modules/@humwick/kernel/workflow-journal-codec.ts +0 -339
  367. package/node_modules/@humwick/kernel/workflow-journal.ts +0 -922
  368. package/node_modules/@humwick/kernel/workflow-lane.ts +0 -48
  369. package/node_modules/@humwick/kernel/workflow-lease-owner.ts +0 -60
  370. package/node_modules/@humwick/kernel/workflow-recovery.test-fixture.ts +0 -19
  371. package/node_modules/@humwick/kernel/workflow-runtime.ts +0 -938
  372. package/node_modules/@humwick/kernel/workflow-script.ts +0 -11
  373. package/node_modules/@humwick/kernel/workflow-state.ts +0 -299
  374. package/node_modules/@humwick/kernel/workflow-step-commit.ts +0 -195
  375. package/node_modules/@humwick/kernel/workflow-transitions.ts +0 -317
  376. package/node_modules/@humwick/kernel/workflow-values.ts +0 -153
  377. package/node_modules/@humwick/kernel/workflow.pilot.ts +0 -376
  378. package/node_modules/@humwick/offload/LICENSE +0 -167
  379. package/node_modules/@humwick/offload/README.md +0 -57
  380. package/node_modules/@humwick/offload/dist/async-runner.d.ts +0 -18
  381. package/node_modules/@humwick/offload/dist/async-runner.d.ts.map +0 -1
  382. package/node_modules/@humwick/offload/dist/async-runner.js +0 -158
  383. package/node_modules/@humwick/offload/dist/async-runner.js.map +0 -1
  384. package/node_modules/@humwick/offload/dist/envelope.d.ts +0 -25
  385. package/node_modules/@humwick/offload/dist/envelope.d.ts.map +0 -1
  386. package/node_modules/@humwick/offload/dist/envelope.js +0 -80
  387. package/node_modules/@humwick/offload/dist/envelope.js.map +0 -1
  388. package/node_modules/@humwick/offload/dist/fixtures/worker-task.d.ts +0 -10
  389. package/node_modules/@humwick/offload/dist/fixtures/worker-task.d.ts.map +0 -1
  390. package/node_modules/@humwick/offload/dist/fixtures/worker-task.js +0 -59
  391. package/node_modules/@humwick/offload/dist/fixtures/worker-task.js.map +0 -1
  392. package/node_modules/@humwick/offload/dist/index.d.ts +0 -5
  393. package/node_modules/@humwick/offload/dist/index.d.ts.map +0 -1
  394. package/node_modules/@humwick/offload/dist/index.js +0 -5
  395. package/node_modules/@humwick/offload/dist/index.js.map +0 -1
  396. package/node_modules/@humwick/offload/dist/subprocess-runner.d.ts +0 -62
  397. package/node_modules/@humwick/offload/dist/subprocess-runner.d.ts.map +0 -1
  398. package/node_modules/@humwick/offload/dist/subprocess-runner.js +0 -295
  399. package/node_modules/@humwick/offload/dist/subprocess-runner.js.map +0 -1
  400. package/node_modules/@humwick/offload/dist/types.d.ts +0 -111
  401. package/node_modules/@humwick/offload/dist/types.d.ts.map +0 -1
  402. package/node_modules/@humwick/offload/dist/types.js +0 -176
  403. package/node_modules/@humwick/offload/dist/types.js.map +0 -1
  404. package/node_modules/@humwick/offload/dist/worker-pool.d.ts +0 -23
  405. package/node_modules/@humwick/offload/dist/worker-pool.d.ts.map +0 -1
  406. package/node_modules/@humwick/offload/dist/worker-pool.js +0 -435
  407. package/node_modules/@humwick/offload/dist/worker-pool.js.map +0 -1
  408. package/node_modules/@humwick/offload/dist/worker-runtime.d.ts +0 -2
  409. package/node_modules/@humwick/offload/dist/worker-runtime.d.ts.map +0 -1
  410. package/node_modules/@humwick/offload/dist/worker-runtime.js +0 -27
  411. package/node_modules/@humwick/offload/dist/worker-runtime.js.map +0 -1
  412. package/node_modules/@humwick/offload/dist/worker.d.ts +0 -5
  413. package/node_modules/@humwick/offload/dist/worker.d.ts.map +0 -1
  414. package/node_modules/@humwick/offload/dist/worker.js +0 -1
  415. package/node_modules/@humwick/offload/dist/worker.js.map +0 -1
  416. package/node_modules/@humwick/offload/package.json +0 -42
  417. package/node_modules/@humwick/offload/src/async-runner.ts +0 -170
  418. package/node_modules/@humwick/offload/src/envelope.ts +0 -92
  419. package/node_modules/@humwick/offload/src/fixtures/worker-task.ts +0 -49
  420. package/node_modules/@humwick/offload/src/index.ts +0 -4
  421. package/node_modules/@humwick/offload/src/subprocess-runner.ts +0 -334
  422. package/node_modules/@humwick/offload/src/types.ts +0 -235
  423. package/node_modules/@humwick/offload/src/worker-pool.ts +0 -463
  424. package/node_modules/@humwick/offload/src/worker-runtime.ts +0 -32
  425. package/node_modules/@humwick/offload/src/worker.ts +0 -5
  426. package/public/assets/agent-liveness-DyqxfB-t.js +0 -2
  427. package/public/assets/agent-profiles-BpI_jTxq.js +0 -2
  428. package/public/assets/index-B7ZerHLY.css +0 -2
  429. package/public/assets/index-BU3uWo2t.js +0 -15
  430. package/public/assets/projects-B_lmcqfO.js +0 -2
  431. package/public/assets/provider-display-DbLWpP3j.js +0 -2
  432. package/public/assets/run-card-CO_bguQf.js +0 -2
  433. package/public/assets/use-project-list-B-T2Bnnn.js +0 -2
  434. package/public/assets/versioned-prompt-editor-Diu8BIaM.js +0 -8
  435. package/runner/src/gate-run-lease-probe.ts +0 -38
  436. package/src/db/claude-catalog-reconcile.ts +0 -27
  437. package/src/routing-model-aliases.ts +0 -21
@@ -1,317 +0,0 @@
1
- import { enterActivation, settleActivation, valueContext } from "./workflow-composition";
2
- import { expandItems } from "./workflow-container";
3
- import { validateWorkflowValue, workflowValue, workflowCondition, WorkflowValueError } from "./workflow-values";
4
- import { z } from "zod";
5
- import { type ModuleCtx, type StepResult } from "./contract";
6
- import { workflowBackstop, workflowStepChange } from "./workflow-backstop";
7
- import { workflowScriptResultSchema } from "./workflow-script";
8
- import { CI_MAIN_STEP, isLoopBack, routeOutcome, stepOutcome, stepReap, waitTimeoutMs, WORKFLOW_EXITED_OUTCOME, workflowStepPin, type RouteDecision } from "./workflow-definition";
9
- import { stores, requireRun, writeEffect, SIGNAL_TOPIC, ciVerdictSchema, type WorkflowRunRecord, type Awaiting } from "./workflow-state";
10
- export type RunState = { runId: string };
11
- type RunStep = StepResult<RunState>;
12
-
13
- function routeChange(run: WorkflowRunRecord, decision: RouteDecision, now: number) {
14
- return { ...workflowStepChange(run, decision.target, now), counters: decision.counters, round: isLoopBack(run.definition, run.step, decision.target) ? run.round + 1 : run.round };
15
- }
16
-
17
- export function landIntent(run: WorkflowRunRecord, override = run.resuming !== undefined): Record<string, unknown> {
18
- const resume = run.resumes?.at(-1);
19
- const entry = run.rounds.at(-1)?.steps.at(-1);
20
- const source = override ? { at: resume?.at, by: resume?.by, step: resume?.step, escalation: resume?.escalation }
21
- : { at: entry?.at, taskId: entry?.taskId, step: entry?.step, outcome: entry?.outcome };
22
- return { taskId: run.taskId, eventId: run.cursor, workspaceId: run.deliveryWorkspaceId, head: run.head,
23
- approval: { kind: override ? "override" : "go", source } };
24
- }
25
-
26
- /** Enter `run.step`: write its effect and park until the src supervisor signals the wait. */
27
- export async function enter(ctx: ModuleCtx, state: RunState): Promise<RunStep> {
28
- const run = await requireRun(ctx, state.runId);
29
- if (run.cancel) return finish(ctx, run, {}, { status: "cancelled", reason: run.cancel.reason });
30
- const seq = run.waitSeq + 1;
31
- const key = `${run.id}:${seq}`;
32
- const now = ctx.clock.now();
33
- const resume = run.resuming ? { resume: run.resuming } : {};
34
- // The dispatch carries the pin it applies, so a retried effect spawns what this entry decided.
35
- const applied = workflowStepPin(run.definition, run.pins, run.step, run.routingDefaults);
36
- const pin = applied ? { pin: applied } : {};
37
- const declared = run.definition.steps[run.step];
38
- try {
39
- if (declared?.condition !== undefined && !workflowCondition(declared.condition, valueContext(run))) {
40
- await enterActivation(ctx, run, key, now, true);
41
- const current = await requireRun(ctx, run.id);
42
- const patch = await settleActivation(ctx, current, "skipped", {});
43
- const decision = routeOutcome(run.definition, run.step, "skipped", run.counters, valueContext({ ...current, ...patch }));
44
- const update = { ...patch, waitSeq: seq, counters: decision.counters };
45
- if (decision.target === "done") return finish(ctx, current, update, { status: "done" });
46
- if (decision.target === "fail" || decision.target === "escalate") return finish(ctx, current, update, { status: decision.target === "fail" ? "failed" : "escalated", reason: "skipped step route" });
47
- await stores(ctx).run.update(run.id, { ...update, ...routeChange(run, decision, now) });
48
- return { state, next: "enter" };
49
- }
50
- } catch (error) { return finish(ctx, await requireRun(ctx, run.id), {}, { status: "failed", reason: String(error) }); }
51
- const decisionWait = run.definition.steps[run.step]?.decision;
52
- const activationDeadline = decisionWait ? (decisionWait.deadlineMs === undefined ? undefined : now + decisionWait.deadlineMs) : now + waitTimeoutMs(run.definition, run.step);
53
- let data: Record<string, unknown> = {};
54
- try { data = await enterActivation(ctx, run, key, activationDeadline); }
55
- catch (error) { return finish(ctx, run, {}, { status: "escalated", reason: String(error) }); }
56
- let awaiting: Awaiting;
57
- let landOperationId: string | undefined;
58
- if (run.step === "close") {
59
- const id = await writeEffect(ctx, run, seq, "close", {}, key);
60
- awaiting = { key, kind: "closed", effectId: id, afterEventId: run.cursor, since: now };
61
- } else if (run.step === "land") {
62
- landOperationId = await writeEffect(ctx, run, seq, "clear-hold", landIntent(run), key);
63
- awaiting = { key, kind: "landed", taskId: run.taskId, afterEventId: run.cursor, since: now };
64
- } else if (run.step === CI_MAIN_STEP) {
65
- // The work landed: no step agent has anything left to do while CI runs.
66
- await writeEffect(ctx, run, seq, "reap", { scope: "run" });
67
- awaiting = { key, kind: "ci", taskId: run.taskId, sha: run.landed!.sha, afterEventId: run.cursor, since: now };
68
- } else {
69
- const step = run.definition.steps[run.step]!;
70
- if (step.forEach) {
71
- try { await expandItems(ctx, await requireRun(ctx, run.id)); }
72
- catch (error) { return finish(ctx, await requireRun(ctx, run.id), {}, { status: "escalated", reason: String(error) }); }
73
- awaiting = { key, kind: "for-each", afterEventId: 0, since: now };
74
- } else if (step.decision) {
75
- const id = await writeEffect(ctx, run, seq, "decision", { step: run.step, ...data }, key);
76
- awaiting = { key, kind: "decision", effectId: id, afterEventId: 0, since: now, ...(step.decision.deadlineMs !== undefined ? { deadline: now + step.decision.deadlineMs } : {}) };
77
- } else if (step.workflow) {
78
- const id = await writeEffect(ctx, run, seq, "child", { step: run.step, ...data }, key);
79
- awaiting = { key, kind: "child", effectId: id, afterEventId: 0, since: now };
80
- } else if (step.script) {
81
- const poll = run.scriptPoll ?? { step: run.step, attempt: 1, deadline: now + step.script.timeoutMs, nextAt: now };
82
- const id = await writeEffect(ctx, run, seq, "script", { ...poll, ...data }, key);
83
- awaiting = { key, kind: "script", effectId: id, afterEventId: run.cursor, since: now, deadline: poll.deadline };
84
- await stores(ctx).run.update(run.id, { scriptPoll: poll });
85
- } else if (step.task === "input") {
86
- // #3660 — a gated input step (a single-agent audit) links its Task with the gate, so its delivery is a verdict.
87
- const inputGate = step.gate ? { gate: step.gate } : {};
88
- if (run.resuming) {
89
- // The src effect hands the note to the warm builder, or dispatches a fresh one when it is gone.
90
- await writeEffect(ctx, run, seq, "dispatch", { step: run.step, role: step.role, taskId: run.taskId, round: run.round, hold: true, ...inputGate, ...resume, ...pin, ...data }, key);
91
- } else if (run.entered.includes(run.step)) {
92
- await writeEffect(ctx, run, seq, "findings", { taskId: run.taskId, round: run.round, ...run.feedback }, key);
93
- } else {
94
- await writeEffect(ctx, run, seq, "dispatch", { step: run.step, role: step.role, taskId: run.taskId, hold: true, ...inputGate, ...pin, ...data }, key);
95
- }
96
- awaiting = { key, kind: "delivery", taskId: run.taskId, afterEventId: run.cursor, since: now };
97
- } else {
98
- const id = await writeEffect(ctx, run, seq, "dispatch", {
99
- step: run.step, role: step.role, round: run.round, parentTaskId: run.taskId,
100
- ...(run.head ? { head: run.head } : {}), ...(step.gate ? { gate: step.gate } : {}), ...resume, ...pin, ...data,
101
- }, key);
102
- awaiting = { key, kind: "delivery", effectId: id, afterEventId: 0, since: now };
103
- }
104
- }
105
- if (awaiting.kind !== "decision") awaiting.deadline ??= now + waitTimeoutMs(run.definition, run.step);
106
- const entered = run.step === "land" || run.entered.includes(run.step) ? run.entered : [...run.entered, run.step];
107
- const backstop = run.scriptPoll && run.overdueAt !== undefined ? {} : workflowBackstop(run, now, awaiting.deadline);
108
- await stores(ctx).run.update(run.id, { ...backstop, waitSeq: seq, awaiting, entered, resuming: undefined, ...(landOperationId ? { landOperationId } : {}), updatedAt: now });
109
- return { state, next: "route", waitFor: { kind: "event", topic: SIGNAL_TOPIC, correlationId: key } };
110
- }
111
-
112
- type RunEnd = { status: "escalated" | "cancelled" | "failed"; reason: string } | { status: "done"; landedSha?: string; nothingToLand?: boolean; ci?: z.output<typeof ciVerdictSchema> };
113
-
114
- async function finish(ctx: ModuleCtx, run: WorkflowRunRecord, patch: Partial<WorkflowRunRecord>, end: RunEnd, cleanupSettled = false): Promise<RunStep> {
115
- const now = ctx.clock.now();
116
- const final = { ...run, ...patch, status: end.status, ...(end.status === "done" && end.landedSha ? { landed: { ...run.landed, sha: end.landedSha, at: run.landed?.at ?? now } } : {}) };
117
- let returned: Record<string, unknown> | undefined;
118
- if (end.status === "done" && run.definition.version === 2) {
119
- try {
120
- returned = (cleanupSettled ? run.finalizing : workflowValue(run.definition.returns ?? {}, valueContext(final))) as Record<string, unknown>;
121
- validateWorkflowValue(run.definition.outputs, returned, "OUTPUT_INVALID");
122
- } catch (error) { return finish(ctx, run, patch, { status: "failed", reason: String(error) }); }
123
- }
124
- // The end consumes its seq, so a resumed run's next step and end never reuse these effect ids.
125
- const seq = run.waitSeq + 1;
126
- if (run.awaiting?.kind === "decision") await writeEffect(ctx, run, seq, "withdraw-decision", { effectId: run.awaiting.effectId });
127
- if (run.activationId) {
128
- const activation = await stores(ctx).activation.get(run.activationId);
129
- if (activation && activation.state === "waiting") await stores(ctx).activation.update(activation.id, { state: end.status === "done" ? "succeeded" : end.status === "cancelled" ? "cancelled" : "paused", outcome: end.status, updatedAt: now });
130
- }
131
- if (end.status === "done" && !cleanupSettled) {
132
- const ci = end.ci ?? final.landed?.ci;
133
- const output = (cleanupSettled ? run.finalizing : undefined) ?? returned ?? { landedSha: end.landedSha, rounds: final.round, ...(end.nothingToLand ? { nothingToLand: true } : {}), ...(ci ? { ci } : {}) };
134
- const key = `${run.id}:${seq}`;
135
- const id = await writeEffect(ctx, final, seq, "reap", { scope: "run" }, key);
136
- await stores(ctx).run.update(run.id, { ...patch, waitSeq: seq, ...(final.landed ? { landed: final.landed } : {}), finalizing: output, cleanup: { status: "pending", deadline: now + 300000 }, awaiting: { kind: "cleanup", key, effectId: id, afterEventId: run.cursor, since: now, deadline: now + 300000 }, updatedAt: now });
137
- return { state: { runId: run.id }, next: "route", waitFor: { kind: "event", topic: SIGNAL_TOPIC, correlationId: key } };
138
- }
139
- if (!cleanupSettled) await writeEffect(ctx, final, seq, "reap", { scope: "run" });
140
- if (end.status !== "done") {
141
- // A cancel is the coordinator's own act (cancel, abandon): nothing to tell it.
142
- const escalation = end.status === "escalated" || end.status === "failed" ? { escalation: { id: await writeEffect(ctx, final, seq, "escalate", { reason: end.reason }), at: now } } : {};
143
- await stores(ctx).run.update(run.id, { ...patch, ...escalation, ...(end.status === "cancelled" ? { cleanup: run.cleanup ?? { status: "pending" as const, deadline: now + 300000 } } : {}), waitSeq: seq, status: end.status, reason: end.reason, awaiting: null, resuming: undefined, updatedAt: now });
144
- } else {
145
- const ci = end.ci ?? final.landed?.ci;
146
- const output = (cleanupSettled ? run.finalizing : undefined) ?? returned ?? { landedSha: end.landedSha, rounds: final.round, ...(end.nothingToLand || final.landed?.nothingToLand ? { nothingToLand: true } : {}), ...(ci ? { ci } : {}) };
147
- await writeEffect(ctx, final, seq, "result", output);
148
- await stores(ctx).run.update(run.id, { ...patch, waitSeq: seq, status: "done", finalizing: undefined, cleanup: { status: "complete", deadline: run.cleanup?.deadline ?? now }, output, ...(run.rootRunId ? { outputs: output } : {}), awaiting: null, resuming: undefined, updatedAt: now });
149
- }
150
- await ctx.events.emit("workflow.finished", { runId: run.id, status: end.status });
151
- return { state: { runId: run.id }, next: "done", output: end };
152
- }
153
-
154
- function textField(value: unknown): string | undefined {
155
- return typeof value === "string" && value.trim() ? value : undefined;
156
- }
157
-
158
- /** Consume the signal of the current wait and decide the next step. */
159
- export async function route(ctx: ModuleCtx, state: RunState): Promise<RunStep> {
160
- try { return await routeSignal(ctx, state); }
161
- catch (error) {
162
- if (!(error instanceof WorkflowValueError)) throw error;
163
- return finish(ctx, await requireRun(ctx, state.runId), {}, { status: "failed", reason: error.message });
164
- }
165
- }
166
-
167
- async function routeSignal(ctx: ModuleCtx, state: RunState): Promise<RunStep> {
168
- const run = await requireRun(ctx, state.runId);
169
- // A cancel wins over whatever woke the wait, including a result that arrived first.
170
- if (run.cancel) return finish(ctx, run, {}, { status: "cancelled", reason: run.cancel.reason });
171
- const key = run.awaiting?.key;
172
- const signal = key ? await stores(ctx).signal.get(key) : undefined;
173
- if (!signal) throw new Error(`workflow run '${run.id}' woke without the signal for its wait`);
174
- // The resume op already set the run up; a run leaving its land wait takes its step now the Task is held.
175
- if (signal.kind === "resume") {
176
- const to = run.resuming?.to;
177
- if (to) await stores(ctx).run.update(run.id, { ...workflowStepChange(run, to, ctx.clock.now()), resuming: run.resuming?.note ? { note: run.resuming.note } : {} });
178
- return { state, next: "enter" };
179
- }
180
- const payload = signal.payload;
181
- if (run.awaiting?.kind === "cleanup" && signal.kind === "cleanup") return finish(ctx, run, {}, { status: "done" }, true);
182
- if (signal.kind === "effect-failed") {
183
- const message = `${String(payload.effect)} failed: ${String(payload.error)}`;
184
- const patch = await settleActivation(ctx, run, "blocked", {}, { code: String(payload.error).split(":")[0], message, effectId: run.awaiting?.effectId });
185
- return finish(ctx, run, patch, { status: "escalated", reason: message });
186
- }
187
- if (signal.kind === "land-withdrawn") {
188
- // #3603 — a withdrawn land parks the run at the step that delivered it: same run, builder and worktree.
189
- const delivering = run.rounds.flatMap((round) => round.steps).reverse().find((entry) => entry.taskId === run.taskId && run.definition.steps[entry.step]?.task === "input")?.step;
190
- if (!delivering) return finish(ctx, run, {}, { status: "cancelled", reason: String(payload.reason) });
191
- const note = `The armed land of ${run.head ?? "your delivered head"} was withdrawn: ${String(payload.reason)}. The run is parked here; your worktree and commits are kept.`;
192
- await stores(ctx).run.update(run.id, { ...workflowStepChange(run, delivering, ctx.clock.now()), round: run.round + 1, feedback: null, resuming: { note } });
193
- return { state, next: "enter" };
194
- }
195
- if (signal.kind === "land-cancelled" || signal.kind === "start-refused") return finish(ctx, run, {}, { status: "cancelled", reason: String(payload.reason) });
196
- if (run.step === "close") return finish(ctx, run, {}, { status: "done", landedSha: String(payload.landedSha ?? run.landed?.sha) });
197
- if (run.step === CI_MAIN_STEP) {
198
- const ci = ciVerdictSchema.parse(payload);
199
- if (run.definition.land?.then) {
200
- if (ci.status !== "pass") return finish(ctx, run, {}, { status: "escalated", reason: `CI on main: ${ci.status}; verification did not run` });
201
- await stores(ctx).run.update(run.id, { ...workflowStepChange(run, run.definition.land.then, ctx.clock.now()), landed: { ...run.landed!, ci } });
202
- return { state, next: "enter" };
203
- }
204
- return finish(ctx, run, {}, { status: "done", landedSha: run.landed!.sha, ci });
205
- }
206
- if (run.step === "land") {
207
- if (run.definition.land?.then) {
208
- const landed = { sha: String(payload.sha), at: ctx.clock.now(), ...(payload.nothingToLand === true ? { nothingToLand: true } : {}) };
209
- const next = run.definition.ciMain && !landed.nothingToLand ? CI_MAIN_STEP : run.definition.land.then;
210
- await stores(ctx).run.update(run.id, { ...workflowStepChange(run, next, ctx.clock.now()), landed });
211
- return { state, next: "enter" };
212
- }
213
- // Nothing landed, so CI on main has no land of this run's to judge.
214
- if (payload.nothingToLand === true) return finish(ctx, run, {}, { status: "done", landedSha: String(payload.sha), nothingToLand: true });
215
- if (!run.definition.ciMain) return finish(ctx, run, {}, { status: "done", landedSha: String(payload.sha) });
216
- await stores(ctx).run.update(run.id, { ...workflowStepChange(run, CI_MAIN_STEP, ctx.clock.now()), landed: { sha: String(payload.sha), at: ctx.clock.now() } });
217
- return { state, next: "enter" };
218
- }
219
-
220
- const step = run.definition.steps[run.step]!;
221
- if (step.decision || step.workflow || step.forEach) {
222
- const outputs = (payload.outputs ?? {}) as Record<string, unknown>;
223
- const outcome = String(payload.outcome);
224
- let patch: Partial<WorkflowRunRecord>;
225
- try {
226
- if (outcome === "complete" && step.outputSchema) validateWorkflowValue(step.outputSchema, outputs, "OUTPUT_INVALID");
227
- patch = await settleActivation(ctx, run, outcome, outputs, payload.error as Record<string, unknown> | undefined);
228
- } catch (error) {
229
- patch = await settleActivation(ctx, run, "failed", {}, { code: "OUTPUT_INVALID", message: String(error), childRunId: payload.childRunId });
230
- return finish(ctx, run, patch, { status: "failed", reason: String(error) });
231
- }
232
- const decision = routeOutcome(run.definition, run.step, outcome, run.counters, valueContext({ ...run, ...patch }));
233
- patch.counters = decision.counters;
234
- if (decision.target === "done") return finish(ctx, run, patch, { status: "done" });
235
- if (decision.target === "fail" || decision.target === "escalate") return finish(ctx, run, patch, { status: decision.target === "fail" ? "failed" : "escalated", reason: String(payload.error ?? decision.reason ?? `child ${outcome}`) });
236
- await stores(ctx).run.update(run.id, { ...patch, ...routeChange(run, decision, ctx.clock.now()) });
237
- return { state, next: "enter" };
238
- }
239
- if (step.script) {
240
- const result = workflowScriptResultSchema.parse(payload);
241
- const outcome = result.timedOut ? "timeout" : String(result.exitCode ?? "unknown");
242
- const decision = routeOutcome(run.definition, run.step, outcome, run.counters, valueContext({ ...run, results: { ...run.results, [run.step]: { status: result.exitCode === 0 ? "succeeded" : "failed", outputs: result.output ?? {} } } }));
243
- await stores(ctx).scriptAttempt.create({ id: signal.id, runId: run.id, ...result });
244
- const scriptOutputs = { ...run.scriptOutputs, ...(result.output ? { [run.step]: result.output } : {}) };
245
- if (decision.target === "wait") {
246
- await stores(ctx).run.update(run.id, { scriptOutputs, scriptPoll: { ...run.scriptPoll!, attempt: result.attempt + 1, nextAt: ctx.clock.now() + step.script.everyMs! }, updatedAt: ctx.clock.now() });
247
- return { state, next: "enter" };
248
- }
249
- const entry = { step: run.step, taskId: run.taskId, outcome, startedAt: run.awaiting!.since, at: ctx.clock.now() };
250
- const rounds = run.rounds.some((r) => r.round === run.round)
251
- ? run.rounds.map((r) => r.round === run.round ? { ...r, steps: [...r.steps, entry] } : r)
252
- : [...run.rounds, { round: run.round, steps: [entry] }];
253
- let activationPatch: Partial<WorkflowRunRecord> = {};
254
- if (run.rootRunId) {
255
- try {
256
- if (result.error) throw new Error(String(result.error.message));
257
- if (step.outputSchema) validateWorkflowValue(step.outputSchema, result.output ?? {}, "OUTPUT_INVALID");
258
- activationPatch = await settleActivation(ctx, run, decision.outcome ?? (decision.target === "escalate" ? "blocked" : decision.target === "fail" ? "failed" : "complete"), result.output ?? {});
259
- } catch (error) {
260
- activationPatch = await settleActivation(ctx, run, "failed", {}, { code: "OUTPUT_INVALID", message: String(error), artifactId: result.logArtifactId });
261
- return finish(ctx, run, { ...activationPatch, scriptPoll: undefined, rounds }, { status: "failed", reason: `OUTPUT_INVALID: ${String(error)}` });
262
- }
263
- }
264
- const patch = { scriptOutputs, scriptPoll: undefined, rounds, ...activationPatch, counters: decision.counters };
265
- if (decision.target === "escalate" || decision.target === "fail") return finish(ctx, run, patch, { status: decision.target === "fail" ? "failed" : "escalated", reason: decision.reason! });
266
- if (decision.target === "done") return finish(ctx, run, patch, { status: "done", landedSha: run.landed?.sha ?? "" });
267
- await stores(ctx).run.update(run.id, { ...patch, ...routeChange(run, decision, ctx.clock.now()) });
268
- return { state, next: "enter" };
269
- }
270
- const exited = signal.kind === "agent-exited";
271
- const outcome = exited ? WORKFLOW_EXITED_OUTCOME : stepOutcome(step, { disposition: String(payload.disposition), gateStatus: textField(payload.gateStatus) });
272
- const input = step.task === "input";
273
- const head = input ? textField(payload.head) ?? run.head : run.head;
274
- const entry = {
275
- step: run.step,
276
- taskId: Number(payload.taskId),
277
- outcome,
278
- ...(head ? { head } : {}),
279
- ...(textField(payload.summary) ? { summary: textField(payload.summary) } : {}),
280
- ...(textField(payload.findings) ? { findings: textField(payload.findings) } : {}),
281
- ...(run.awaiting ? { startedAt: run.awaiting.since } : {}),
282
- at: ctx.clock.now(),
283
- };
284
- const rounds = run.rounds.some((r) => r.round === run.round)
285
- ? run.rounds.map((r) => (r.round === run.round ? { ...r, steps: [...r.steps, entry] } : r))
286
- : [...run.rounds, { round: run.round, steps: [entry] }];
287
- if (stepReap(step) === "on-step-done") await writeEffect(ctx, run, run.waitSeq, "reap", { scope: "step", step: run.step });
288
- const decision = routeOutcome(run.definition, run.step, outcome, run.counters, valueContext({ ...run, results: { ...run.results, [run.step]: { status: outcome === "complete" || outcome === "pass" ? "succeeded" : "failed", outcome, outputs: payload.outputs ?? {} } } }));
289
- // An exit consumed no delivery, so the next wait still counts from the last one.
290
- let activationPatch: Partial<WorkflowRunRecord> = {};
291
- if (run.rootRunId) {
292
- const outputs = payload.outputs as Record<string, unknown> | undefined ?? {};
293
- try {
294
- if (step.outputSchema) validateWorkflowValue(step.outputSchema, outputs, "OUTPUT_INVALID");
295
- activationPatch = await settleActivation(ctx, run, outcome, outputs);
296
- } catch (error) {
297
- activationPatch = await settleActivation(ctx, run, "failed", {}, { code: "OUTPUT_INVALID", message: String(error), deliveryEventId: payload.eventId });
298
- return finish(ctx, run, activationPatch, { status: "failed", reason: String(error) });
299
- }
300
- }
301
- const patch: Partial<WorkflowRunRecord> = { ...activationPatch, rounds, counters: decision.counters, scriptOutputs: { ...run.scriptOutputs, [run.step]: payload }, ...(input && !exited ? { cursor: Number(payload.eventId), deliveryWorkspaceId: textField(payload.workspaceId) } : {}), ...(head ? { head } : {}) };
302
- await ctx.events.emit("workflow.routed", { runId: run.id, step: run.step, outcome, target: decision.target });
303
- if (decision.target === "done") return finish(ctx, run, patch, { status: "done" });
304
- if (decision.target === "fail") return finish(ctx, run, patch, { status: "failed", reason: `step ${run.step} returned ${outcome}` });
305
- if (decision.target === "escalate") {
306
- // An exit the workflow does not route escalates with its own account.
307
- const reason = exited && !run.definition.routes[run.step]?.[outcome] ? String(payload.summary) : decision.reason ?? `step ${run.step} returned ${outcome}`;
308
- return finish(ctx, run, patch, { status: "escalated", reason });
309
- }
310
-
311
- const loop = isLoopBack(run.definition, run.step, decision.target);
312
- const feedback = loop && run.definition.steps[decision.target]?.task === "input"
313
- ? { ...(head ? { head } : {}), findings: entry.findings ?? entry.summary ?? outcome, taskId: entry.taskId, step: run.step }
314
- : null;
315
- await stores(ctx).run.update(run.id, { ...patch, ...routeChange(run, decision, ctx.clock.now()), feedback });
316
- return { state, next: "enter" };
317
- }
@@ -1,153 +0,0 @@
1
- import jsep from "jsep";
2
- import Ajv, { type ValidateFunction } from "ajv";
3
- import { z } from "zod";
4
-
5
- export const workflowObject = z.record(z.string(), z.unknown());
6
- export const emptyBoundary = { type: "object", additionalProperties: false, properties: {} };
7
- const ajv = new Ajv({ strict: true, allErrors: true, coerceTypes: false, useDefaults: false, removeAdditional: false });
8
- const compiled = new Map<string, ValidateFunction>();
9
- function schemaKey(schema: Record<string, unknown>): string { return JSON.stringify(schema); }
10
- const keywords = new Set(["type", "properties", "required", "additionalProperties", "items", "enum", "const", "nullable", "minimum", "maximum", "exclusiveMinimum", "exclusiveMaximum", "multipleOf", "minLength", "maxLength", "minItems", "maxItems", "uniqueItems", "minProperties", "maxProperties", "$defs", "$ref", "description", "title"]);
11
-
12
- export class WorkflowValueError extends Error {
13
- constructor(readonly code: string, message: string) { super(`${code}: ${message}`); }
14
- }
15
-
16
- export function validateWorkflowSchema(schema: Record<string, unknown>, boundary = false): void {
17
- if (boundary && (schema.type !== "object" || schema.additionalProperties !== false)) throw new WorkflowValueError("SCHEMA_INVALID", "boundary must declare type: object and additionalProperties: false");
18
- let nodes = 0;
19
- function visit(value: unknown, depth: number): void {
20
- if (++nodes > 1000 || depth > 32) throw new WorkflowValueError("SCHEMA_INVALID", "schema exceeds depth/node limit");
21
- if (!value || typeof value !== "object" || Array.isArray(value)) throw new WorkflowValueError("SCHEMA_INVALID", "schema must be an object");
22
- for (const [key, child] of Object.entries(value)) {
23
- if (!keywords.has(key)) throw new WorkflowValueError("SCHEMA_INVALID", `unsupported keyword ${key}`);
24
- if (key === "$ref" && (typeof child !== "string" || !child.startsWith("#/$defs/"))) throw new WorkflowValueError("SCHEMA_INVALID", "only local $defs references are supported");
25
- if (key === "properties" || key === "$defs") {
26
- if (!child || typeof child !== "object" || Array.isArray(child)) throw new WorkflowValueError("SCHEMA_INVALID", `${key} must be an object`);
27
- for (const nested of Object.values(child)) visit(nested, depth + 1);
28
- } else if (key === "items" || (key === "additionalProperties" && typeof child === "object")) visit(child, depth + 1);
29
- }
30
- }
31
- visit(schema, 0);
32
- const key = schemaKey(schema);
33
- if (!compiled.has(key)) {
34
- if (compiled.size >= 512) compiled.delete(compiled.keys().next().value!);
35
- compiled.set(key, ajv.compile(schema));
36
- }
37
- }
38
-
39
- export function validateWorkflowValue(schema: Record<string, unknown> | undefined, data: Record<string, unknown>, code: string): void {
40
- if (new TextEncoder().encode(JSON.stringify(data)).length > 65536) throw new WorkflowValueError(code, "object exceeds 64 KiB");
41
- const definition = schema ?? emptyBoundary;
42
- if (!compiled.has(schemaKey(definition))) validateWorkflowSchema(definition);
43
- const check = compiled.get(schemaKey(definition))!;
44
- if (!check(data)) throw new WorkflowValueError(code, ajv.errorsText(check.errors));
45
- }
46
-
47
- const expressions = new Map<string, jsep.Expression>();
48
- const binary = ["&&", "||", "==", "!=", "<", "<=", ">", ">="];
49
- class MissingPath extends WorkflowValueError {}
50
- function children(node: jsep.Expression): jsep.Expression[] {
51
- if (node.type === "MemberExpression") return [(node as jsep.MemberExpression).object];
52
- if (node.type === "UnaryExpression") return [(node as jsep.UnaryExpression).argument];
53
- if (node.type === "BinaryExpression") return [(node as jsep.BinaryExpression).left, (node as jsep.BinaryExpression).right];
54
- if (node.type === "CallExpression") return (node as jsep.CallExpression).arguments;
55
- return [];
56
- }
57
- function expression(text: string): jsep.Expression {
58
- const source = /^\$\{\{([\s\S]*)\}\}$/.exec(text)?.[1];
59
- if (source === undefined || source.length > 4096) throw new WorkflowValueError("EXPRESSION_INVALID", "expected a whole expression");
60
- const cached = expressions.get(source);
61
- if (cached) return cached;
62
- let parsed: jsep.Expression;
63
- try { parsed = jsep(source); } catch (error) { throw new WorkflowValueError("EXPRESSION_INVALID", String(error)); }
64
- let nodes = 0;
65
- function check(node: jsep.Expression, depth: number): void {
66
- if (++nodes > 256 || depth > 32) throw new WorkflowValueError("EXPRESSION_INVALID", "expression exceeds depth/node limit");
67
- let valid = false;
68
- if (node.type === "Identifier") valid = ["inputs", "steps", "run", "item", "index"].includes((node as jsep.Identifier).name);
69
- if (node.type === "Literal") valid = (node as jsep.Literal).value === null || ["string", "boolean", "number"].includes(typeof (node as jsep.Literal).value);
70
- if (node.type === "MemberExpression") {
71
- const member = node as jsep.MemberExpression;
72
- const property = member.computed ? (member.property as jsep.Literal).value : (member.property as jsep.Identifier).name;
73
- valid = (!member.computed || member.property.type === "Literal") && (typeof property === "string" || typeof property === "number" && Number.isSafeInteger(property) && property >= 0) && !["__proto__", "prototype", "constructor"].includes(String(property));
74
- }
75
- if (node.type === "UnaryExpression") valid = (node as jsep.UnaryExpression).operator === "!" || (node as jsep.UnaryExpression).operator === "-" && (node as jsep.UnaryExpression).argument.type === "Literal" && typeof ((node as jsep.UnaryExpression).argument as jsep.Literal).value === "number";
76
- if (node.type === "BinaryExpression") valid = binary.includes((node as jsep.BinaryExpression).operator);
77
- if (node.type === "CallExpression") {
78
- const call = node as jsep.CallExpression;
79
- valid = call.callee.type === "Identifier" && (call.callee as jsep.Identifier).name === "has" && call.arguments.length === 1 && ["MemberExpression", "Identifier"].includes(call.arguments[0]!.type);
80
- }
81
- if (!valid) throw new WorkflowValueError("EXPRESSION_INVALID", `unsupported ${node.type}`);
82
- for (const child of children(node)) check(child, depth + 1);
83
- }
84
- check(parsed, 0);
85
- if (expressions.size >= 1024) expressions.delete(expressions.keys().next().value!);
86
- expressions.set(source, parsed);
87
- return parsed;
88
- }
89
-
90
- export function validateWorkflowExpressions(value: unknown, steps: readonly string[]): void {
91
- if (typeof value === "string" && value.startsWith("${{")) {
92
- function names(part: jsep.Expression): void {
93
- if (part.type === "MemberExpression") {
94
- const member = part as jsep.MemberExpression;
95
- if (member.object.type === "Identifier" && (member.object as jsep.Identifier).name === "steps") {
96
- const name = member.computed ? (member.property as jsep.Literal).value : (member.property as jsep.Identifier).name;
97
- if (!steps.includes(String(name))) throw new WorkflowValueError("EXPRESSION_INVALID", `unknown step ${String(name)}`);
98
- }
99
- }
100
- for (const child of children(part)) names(child);
101
- }
102
- names(expression(value));
103
- } else if (value && typeof value === "object") for (const item of Object.values(value)) validateWorkflowExpressions(item, steps);
104
- }
105
-
106
- function boolean(value: unknown): boolean {
107
- if (typeof value !== "boolean") throw new WorkflowValueError("EXPRESSION_INVALID", "condition requires a boolean");
108
- return value;
109
- }
110
- export function workflowCondition(value: unknown, context: Record<string, unknown>): boolean { return boolean(workflowValue(value, context)); }
111
-
112
- export function workflowValue(value: unknown, context: Record<string, unknown>): unknown {
113
- if (typeof value === "string" && value.startsWith("${{")) {
114
- function evaluate(node: jsep.Expression): unknown {
115
- if (node.type === "Literal") return (node as jsep.Literal).value;
116
- if (node.type === "Identifier") {
117
- const name = (node as jsep.Identifier).name;
118
- if (!Object.hasOwn(context, name)) throw new MissingPath("EXPRESSION_INVALID", `missing context ${name}`);
119
- return context[name];
120
- }
121
- if (node.type === "CallExpression") {
122
- try { evaluate((node as jsep.CallExpression).arguments[0]!); return true; }
123
- catch (error) { if (error instanceof MissingPath) return false; throw error; }
124
- }
125
- if (node.type === "UnaryExpression") {
126
- const unary = node as jsep.UnaryExpression;
127
- return unary.operator === "!" ? !boolean(evaluate(unary.argument)) : -Number((unary.argument as jsep.Literal).value);
128
- }
129
- if (node.type === "BinaryExpression") {
130
- const { operator, left, right } = node as jsep.BinaryExpression;
131
- const a = evaluate(left);
132
- if (operator === "&&") return boolean(a) && boolean(evaluate(right));
133
- if (operator === "||") return boolean(a) || boolean(evaluate(right));
134
- const b = evaluate(right);
135
- if ((a !== null && typeof a === "object") || (b !== null && typeof b === "object") || typeof a !== typeof b) throw new WorkflowValueError("EXPRESSION_INVALID", "comparison requires matching scalar types");
136
- if (operator === "==") return a === b;
137
- if (operator === "!=") return a !== b;
138
- if (typeof a === "number" && typeof b === "number") return operator === "<" ? a < b : operator === "<=" ? a <= b : operator === ">" ? a > b : a >= b;
139
- if (typeof a === "string" && typeof b === "string") return operator === "<" ? a < b : operator === "<=" ? a <= b : operator === ">" ? a > b : a >= b;
140
- throw new WorkflowValueError("EXPRESSION_INVALID", "ordering requires numbers or strings");
141
- }
142
- const member = node as jsep.MemberExpression;
143
- const target = evaluate(member.object);
144
- const key = member.computed ? (member.property as jsep.Literal).value : (member.property as jsep.Identifier).name;
145
- if (!target || typeof target !== "object" || !Object.hasOwn(target, String(key))) throw new MissingPath("EXPRESSION_INVALID", `missing property ${String(key)}`);
146
- return (target as Record<string, unknown>)[String(key)];
147
- }
148
- return evaluate(expression(value));
149
- }
150
- if (Array.isArray(value)) return value.map(item => workflowValue(item, context));
151
- if (value && typeof value === "object") return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, workflowValue(item, context)]));
152
- return value;
153
- }