@humwick/server 0.130.0 → 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 (486) hide show
  1. package/README.md +5 -0
  2. package/docs/guides/tools-administration.md +6 -1
  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-C7jQWbw2.js +2 -0
  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 +24 -3
  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 +10 -6
  128. package/src/commands-write.ts +8 -0
  129. package/src/config-store-write.ts +13 -1
  130. package/src/config-store.ts +25 -14
  131. package/src/db/activity-async.ts +6 -1
  132. package/src/db/activity-write-ops.ts +13 -1
  133. package/src/db/activity.ts +1 -14
  134. package/src/db/agent-lifecycle-write-ops.ts +1 -0
  135. package/src/db/agent-meta.ts +2 -2
  136. package/src/db/agent-ownership-write-ops.ts +4 -0
  137. package/src/db/agent-search.ts +1 -15
  138. package/src/db/agents-async.ts +58 -7
  139. package/src/db/agents-write-ops.ts +28 -5
  140. package/src/db/agents.ts +81 -54
  141. package/src/db/artifacts-write-ops.ts +8 -3
  142. package/src/db/bus-outbox-write-ops.ts +1 -0
  143. package/src/db/channels-write-ops.ts +4 -0
  144. package/src/db/ci-incidents-async.ts +5 -5
  145. package/src/db/ci-incidents-write-ops.ts +2 -2
  146. package/src/db/claude-api-budget-ops.ts +5 -5
  147. package/src/db/claude-app-oauth.ts +4 -4
  148. package/src/db/codex-reset-consumes-write-ops.ts +3 -0
  149. package/src/db/command-row.ts +10 -2
  150. package/src/db/commands-list-query.ts +2 -0
  151. package/src/db/commands-spawn-read.ts +1 -1
  152. package/src/db/commands-write-ops.ts +21 -0
  153. package/src/db/config-store-write-ops.ts +9 -2
  154. package/src/db/continuation-archives-async.ts +5 -0
  155. package/src/db/continuation-archives-write-ops.ts +9 -0
  156. package/src/db/continuations.ts +2 -2
  157. package/src/db/db-writer-worker.ts +8 -1
  158. package/src/db/delivery-write-ops.ts +5 -0
  159. package/src/db/deploy-events-async.ts +1 -0
  160. package/src/db/deploy-events-read-ops.ts +2 -1
  161. package/src/db/deploy-events.ts +35 -4
  162. package/src/db/hosts-registration.ts +10 -2
  163. package/src/db/hosts-write-ops.ts +14 -0
  164. package/src/db/hosts.ts +9 -6
  165. package/src/db/inbox-write-ops.ts +4 -0
  166. package/src/db/inbox.ts +0 -14
  167. package/src/db/index.ts +2 -0
  168. package/src/db/insights-write-ops.ts +1 -0
  169. package/src/db/integrations-async.ts +8 -0
  170. package/src/db/integrations-ops.ts +15 -0
  171. package/src/db/integrations.ts +15 -21
  172. package/src/db/issue-lifecycle.ts +3 -4
  173. package/src/db/issue-refs-async.ts +20 -0
  174. package/src/db/issue-refs-write-ops.ts +29 -0
  175. package/src/db/issue-refs.ts +7 -8
  176. package/src/db/long-running-work.ts +2 -2
  177. package/src/db/macos-privacy.ts +1 -1
  178. package/src/db/main-connection-writes.ts +23 -2
  179. package/src/db/maintenance-job-reconcile.ts +61 -0
  180. package/src/db/maintenance-job-runs-async.ts +14 -0
  181. package/src/db/maintenance-job-write-ops.ts +9 -0
  182. package/src/db/mappers.ts +2 -14
  183. package/src/db/merge-lease.ts +1 -15
  184. package/src/db/message-reads-write-ops.ts +3 -0
  185. package/src/db/message-write-ops.ts +4 -0
  186. package/src/db/migrations.ts +7 -15
  187. package/src/db/orchestrators-async.ts +7 -3
  188. package/src/db/orchestrators-write-ops.ts +7 -1
  189. package/src/db/orchestrators.ts +21 -77
  190. package/src/db/pairs.ts +1 -13
  191. package/src/db/project-profile-instructions.ts +50 -0
  192. package/src/db/prompt-versions-ops.ts +1 -0
  193. package/src/db/prompt-versions.ts +9 -2
  194. package/src/db/provider-catalog-write-ops.ts +4 -4
  195. package/src/db/provider-config-history.ts +8 -3
  196. package/src/db/provider-flap-messages-write-ops.ts +1 -0
  197. package/src/db/provider-model-seed.ts +34 -0
  198. package/src/db/provider-quota-lease-write-ops.ts +1 -0
  199. package/src/db/provider-quota-write-ops.ts +2 -0
  200. package/src/db/provisioning-write-ops.ts +9 -8
  201. package/src/db/read-op-marshaling-fixtures.ts +5 -0
  202. package/src/db/read-ops.ts +4 -0
  203. package/src/db/routing-policy.ts +3 -4
  204. package/src/db/schema.ts +9 -3
  205. package/src/db/secrets-broker-write-ops.ts +5 -5
  206. package/src/db/secrets-vault-write.ts +7 -7
  207. package/src/db/services-write-ops.ts +3 -0
  208. package/src/db/spawn-delegation-state.ts +11 -4
  209. package/src/db/spawn-tree-cleanup.ts +3 -0
  210. package/src/db/stats-async.ts +4 -3
  211. package/src/db/task-entity.ts +23 -2
  212. package/src/db/task-list.ts +3 -1
  213. package/src/db/tasks.ts +1 -17
  214. package/src/db/team-spawn-delegation.ts +1 -1
  215. package/src/db/teams-write-ops.ts +4 -4
  216. package/src/db/timer-cutover-write-ops.ts +7 -0
  217. package/src/db/timer-ingress-write-ops.ts +9 -0
  218. package/src/db/timer-ingress.ts +7 -1
  219. package/src/db/timer-operator-write-ops.ts +14 -0
  220. package/src/db/timer-transfer-write-ops.ts +4 -0
  221. package/src/db/timer-write-ops.ts +14 -0
  222. package/src/db/token-db-write-ops.ts +21 -0
  223. package/src/db/token-standing.ts +15 -11
  224. package/src/db/user-settings-write-ops.ts +1 -0
  225. package/src/db/vault-backup.ts +2 -2
  226. package/src/db/vault-expiry.ts +2 -2
  227. package/src/db/vault-health.ts +3 -3
  228. package/src/db/vault-token-ops.ts +8 -8
  229. package/src/db/web-tool-call-ops.ts +3 -3
  230. package/src/db/workflow-contact.ts +1 -1
  231. package/src/db/workflow-task-read-ops.ts +30 -0
  232. package/src/db/write-ops.ts +15 -1
  233. package/src/db/writer-fault-seam.ts +5 -2
  234. package/src/db/writer-gateway.ts +21 -12
  235. package/src/dispatch-availability.ts +10 -6
  236. package/src/ephemeral/{landing-ingress-proof-worker.ts → landing-ingress-proof.test-fixture.ts} +4 -2
  237. package/src/host/disk-alert.ts +121 -0
  238. package/src/lifecycle-manager.ts +3 -2
  239. package/src/maintenance/cd-watcher.ts +3 -3
  240. package/src/maintenance/critical-job-watchdog.ts +16 -17
  241. package/src/maintenance/index.ts +1 -0
  242. package/src/maintenance/jobs.ts +3 -2
  243. package/src/maintenance/scheduler.ts +84 -128
  244. package/src/maintenance/stalled-delivery-pager.ts +6 -5
  245. package/src/maintenance/workspaces.ts +1 -1
  246. package/src/managed-policy.ts +31 -27
  247. package/src/mcp/index.ts +5 -2
  248. package/src/mcp/output-descriptions.ts +8 -8
  249. package/src/mcp/presentation.ts +4 -4
  250. package/src/mcp/project-profile-instructions.ts +32 -0
  251. package/src/mcp/tool-groups.ts +1 -1
  252. package/src/mcp/tools-spawn.ts +4 -3
  253. package/src/mcp-agent-action.ts +1 -2
  254. package/src/mcp-host-tools.ts +1 -1
  255. package/src/mcp-issue-ref-tools.ts +12 -11
  256. package/src/mcp-maintenance-tools.ts +2 -2
  257. package/src/mcp-profile-trust-tools.ts +4 -4
  258. package/src/mcp-provider-catalog.ts +2 -2
  259. package/src/mcp-task-tools.ts +11 -5
  260. package/src/mcp-team-template-tools.ts +3 -3
  261. package/src/mcp-workflow-tools.ts +10 -3
  262. package/src/notification-types.ts +2 -1
  263. package/src/operator-alarm.ts +26 -11
  264. package/src/package-pack.ts +42 -39
  265. package/src/project-instructions.ts +4 -0
  266. package/src/project-profile-instruction-text.ts +6 -0
  267. package/src/project-profile-instructions.ts +20 -0
  268. package/src/provider-catalog-store.ts +3 -49
  269. package/src/provider-config-store.ts +12 -11
  270. package/src/provider-model-seed.ts +1 -18
  271. package/src/provider-quota-config-store.ts +5 -4
  272. package/src/provider-secrets.test-fixture.ts +3 -3
  273. package/src/recipe-runner.ts +2 -2
  274. package/src/repo-config-source.ts +10 -4
  275. package/src/routes/agent-profiles.ts +6 -6
  276. package/src/routes/agents-spawn.ts +1 -1
  277. package/src/routes/agents.ts +6 -6
  278. package/src/routes/commands-listing.ts +4 -0
  279. package/src/routes/commands.ts +2 -2
  280. package/src/routes/continuation-archives.ts +2 -2
  281. package/src/routes/host-resource-control.ts +4 -1
  282. package/src/routes/index.ts +10 -1
  283. package/src/routes/integrations.ts +24 -50
  284. package/src/routes/issue-refs.ts +7 -7
  285. package/src/routes/orchestrator-bootstrap.ts +3 -3
  286. package/src/routes/orchestrator-host-registration.ts +2 -2
  287. package/src/routes/orchestrator-host-utilization.ts +3 -1
  288. package/src/routes/orchestrator-proxy.ts +2 -2
  289. package/src/routes/orchestrator.ts +4 -4
  290. package/src/routes/project-profile-instructions.ts +27 -0
  291. package/src/routes/project-trust.ts +2 -2
  292. package/src/routes/provider-config.ts +9 -8
  293. package/src/routes/provider-quota-config.ts +2 -2
  294. package/src/routes/settings.ts +5 -5
  295. package/src/routes/stats.ts +6 -6
  296. package/src/routes/task-http.ts +15 -1
  297. package/src/routes/task-issues.ts +11 -26
  298. package/src/routes/tasks.ts +22 -53
  299. package/src/routes/team-templates.ts +5 -5
  300. package/src/routes/teams-config.ts +2 -2
  301. package/src/routes/tokens.ts +12 -5
  302. package/src/routes/workflows.ts +20 -5
  303. package/src/routing-policy-normalize.ts +1 -2
  304. package/src/routing-step-defaults.ts +0 -2
  305. package/src/runner-token-mint-limit.ts +63 -0
  306. package/src/runtime-grant.ts +4 -2
  307. package/src/runtime-tokens.ts +50 -9
  308. package/src/security.ts +13 -20
  309. package/src/server-background.ts +1 -1
  310. package/src/server.ts +5 -2
  311. package/src/services/host-utilization.ts +23 -0
  312. package/src/services/idle-epics.ts +5 -6
  313. package/src/services/issue-lifecycle.ts +57 -61
  314. package/src/services/issue-refs.ts +9 -13
  315. package/src/services/kernel-timers-cutover-chaos-worker.ts +12 -7
  316. package/src/services/kernel-timers-ingress.ts +1 -1
  317. package/src/services/kernel-timers-request-key-migration-chaos-worker.ts +4 -1
  318. package/src/services/landed-ancestry.ts +19 -3
  319. package/src/services/memory-areas.ts +15 -51
  320. package/src/services/plan-ci-notice.ts +57 -0
  321. package/src/services/plan-ci-recovery.ts +2 -55
  322. package/src/services/plan-wake-digest.ts +1 -0
  323. package/src/services/profile-trust.ts +4 -3
  324. package/src/services/project-config-read.ts +70 -0
  325. package/src/services/project-profile-instructions.ts +54 -0
  326. package/src/services/provisioning-harness/budget-baseline.json +4 -4
  327. package/src/services/restart-spawn.ts +61 -49
  328. package/src/services/self-care-state.ts +2 -1
  329. package/src/services/self-effort.ts +5 -5
  330. package/src/services/send-message.ts +5 -1
  331. package/src/services/spawn-agent.ts +13 -2
  332. package/src/services/spawn-chain-inspector.ts +6 -13
  333. package/src/services/spawn-policy.ts +68 -0
  334. package/src/services/spawn-tree-cleanup.ts +2 -2
  335. package/src/services/task-dispatch.ts +3 -0
  336. package/src/services/task-state-reconcile.ts +6 -14
  337. package/src/services/team-templates.ts +9 -8
  338. package/src/services/transient-agent-reaper.ts +3 -1
  339. package/src/services/workflow-auto-start.ts +25 -13
  340. package/src/services/workflow-ci-main.ts +1 -1
  341. package/src/services/workflow-deferred-cleanup.ts +4 -2
  342. package/src/services/workflow-effect-driver.ts +2 -0
  343. package/src/services/workflow-effects.ts +18 -11
  344. package/src/services/workflow-land-notice.ts +10 -0
  345. package/src/services/workflow-pause-text.ts +43 -0
  346. package/src/services/workflow-reconcile.ts +13 -11
  347. package/src/services/workflow-run-view.ts +2 -0
  348. package/src/services/workflow-runs.ts +29 -13
  349. package/src/services/workflow-supervisor-state.ts +5 -0
  350. package/src/services/workflow-supervisor.ts +7 -3
  351. package/src/settings/registry.ts +1 -2
  352. package/src/spawn-command.ts +4 -4
  353. package/src/spawn-models.ts +10 -12
  354. package/src/spawn-placement.ts +1 -1
  355. package/src/spawn-targets.ts +1 -1
  356. package/src/startup-context-injection.ts +1 -0
  357. package/src/state-adoption/cd-cutover.ts +53 -7
  358. package/src/state-adoption/fleet-cutover.ts +35 -0
  359. package/src/state-adoption/fleet-plan.ts +36 -0
  360. package/src/state-adoption/index.ts +2 -2
  361. package/src/state-adoption/linux-plan.ts +2 -2
  362. package/src/state-adoption/linux.ts +2 -2
  363. package/src/state-adoption/macos-plan.ts +2 -2
  364. package/src/state-adoption/macos.ts +1 -1
  365. package/src/steward.ts +7 -6
  366. package/src/task-dispatch-live.ts +1 -1
  367. package/src/task-dispatcher.ts +1 -1
  368. package/src/teams-config-store.ts +4 -3
  369. package/src/token-db-write.ts +10 -0
  370. package/src/workspace-command-settle.ts +2 -1
  371. package/src/workspace-steward-wake.ts +2 -2
  372. package/node_modules/@humwick/kernel/LICENSE +0 -167
  373. package/node_modules/@humwick/kernel/async-entity-persistence.ts +0 -344
  374. package/node_modules/@humwick/kernel/async-event-log.ts +0 -107
  375. package/node_modules/@humwick/kernel/automations.pilot.ts +0 -147
  376. package/node_modules/@humwick/kernel/config.ts +0 -111
  377. package/node_modules/@humwick/kernel/contract.ts +0 -572
  378. package/node_modules/@humwick/kernel/control-authz.ts +0 -281
  379. package/node_modules/@humwick/kernel/control.ts +0 -645
  380. package/node_modules/@humwick/kernel/effects.ts +0 -493
  381. package/node_modules/@humwick/kernel/event-log.ts +0 -319
  382. package/node_modules/@humwick/kernel/http-transport.ts +0 -384
  383. package/node_modules/@humwick/kernel/identity-grammar.ts +0 -20
  384. package/node_modules/@humwick/kernel/identity.ts +0 -248
  385. package/node_modules/@humwick/kernel/index.ts +0 -28
  386. package/node_modules/@humwick/kernel/kernel-persistence.ts +0 -181
  387. package/node_modules/@humwick/kernel/landing-incident.ts +0 -306
  388. package/node_modules/@humwick/kernel/landing.ts +0 -953
  389. package/node_modules/@humwick/kernel/manifest-validation.ts +0 -460
  390. package/node_modules/@humwick/kernel/mcp-transport.ts +0 -109
  391. package/node_modules/@humwick/kernel/message-authority-chaos-worker.ts +0 -200
  392. package/node_modules/@humwick/kernel/message-authority.ts +0 -281
  393. package/node_modules/@humwick/kernel/module-host.ts +0 -722
  394. package/node_modules/@humwick/kernel/openapi-init.ts +0 -14
  395. package/node_modules/@humwick/kernel/package.json +0 -47
  396. package/node_modules/@humwick/kernel/persistence-schema.ts +0 -248
  397. package/node_modules/@humwick/kernel/persistence.ts +0 -510
  398. package/node_modules/@humwick/kernel/registry.ts +0 -60
  399. package/node_modules/@humwick/kernel/sqlite-kernel-persistence.ts +0 -499
  400. package/node_modules/@humwick/kernel/sqlite-module-host.ts +0 -87
  401. package/node_modules/@humwick/kernel/timers-chaos-worker.ts +0 -186
  402. package/node_modules/@humwick/kernel/timers.pilot.ts +0 -1411
  403. package/node_modules/@humwick/kernel/workflow-activation.ts +0 -25
  404. package/node_modules/@humwick/kernel/workflow-backstop.ts +0 -40
  405. package/node_modules/@humwick/kernel/workflow-cancel-tree.ts +0 -20
  406. package/node_modules/@humwick/kernel/workflow-chaos-worker.ts +0 -213
  407. package/node_modules/@humwick/kernel/workflow-composition.ts +0 -231
  408. package/node_modules/@humwick/kernel/workflow-container.ts +0 -72
  409. package/node_modules/@humwick/kernel/workflow-control.test-fixture.ts +0 -42
  410. package/node_modules/@humwick/kernel/workflow-control.ts +0 -178
  411. package/node_modules/@humwick/kernel/workflow-definition.ts +0 -507
  412. package/node_modules/@humwick/kernel/workflow-dispatch.ts +0 -60
  413. package/node_modules/@humwick/kernel/workflow-foreach.ts +0 -167
  414. package/node_modules/@humwick/kernel/workflow-journal-codec.ts +0 -339
  415. package/node_modules/@humwick/kernel/workflow-journal.ts +0 -922
  416. package/node_modules/@humwick/kernel/workflow-lane.ts +0 -48
  417. package/node_modules/@humwick/kernel/workflow-lease-owner.ts +0 -60
  418. package/node_modules/@humwick/kernel/workflow-recovery.test-fixture.ts +0 -19
  419. package/node_modules/@humwick/kernel/workflow-runtime.ts +0 -938
  420. package/node_modules/@humwick/kernel/workflow-script.ts +0 -11
  421. package/node_modules/@humwick/kernel/workflow-state.ts +0 -299
  422. package/node_modules/@humwick/kernel/workflow-step-commit.ts +0 -195
  423. package/node_modules/@humwick/kernel/workflow-transitions.ts +0 -317
  424. package/node_modules/@humwick/kernel/workflow-values.ts +0 -153
  425. package/node_modules/@humwick/kernel/workflow.pilot.ts +0 -376
  426. package/node_modules/@humwick/offload/LICENSE +0 -167
  427. package/node_modules/@humwick/offload/README.md +0 -57
  428. package/node_modules/@humwick/offload/dist/async-runner.d.ts +0 -18
  429. package/node_modules/@humwick/offload/dist/async-runner.d.ts.map +0 -1
  430. package/node_modules/@humwick/offload/dist/async-runner.js +0 -158
  431. package/node_modules/@humwick/offload/dist/async-runner.js.map +0 -1
  432. package/node_modules/@humwick/offload/dist/envelope.d.ts +0 -25
  433. package/node_modules/@humwick/offload/dist/envelope.d.ts.map +0 -1
  434. package/node_modules/@humwick/offload/dist/envelope.js +0 -80
  435. package/node_modules/@humwick/offload/dist/envelope.js.map +0 -1
  436. package/node_modules/@humwick/offload/dist/fixtures/worker-task.d.ts +0 -10
  437. package/node_modules/@humwick/offload/dist/fixtures/worker-task.d.ts.map +0 -1
  438. package/node_modules/@humwick/offload/dist/fixtures/worker-task.js +0 -59
  439. package/node_modules/@humwick/offload/dist/fixtures/worker-task.js.map +0 -1
  440. package/node_modules/@humwick/offload/dist/index.d.ts +0 -5
  441. package/node_modules/@humwick/offload/dist/index.d.ts.map +0 -1
  442. package/node_modules/@humwick/offload/dist/index.js +0 -5
  443. package/node_modules/@humwick/offload/dist/index.js.map +0 -1
  444. package/node_modules/@humwick/offload/dist/subprocess-runner.d.ts +0 -62
  445. package/node_modules/@humwick/offload/dist/subprocess-runner.d.ts.map +0 -1
  446. package/node_modules/@humwick/offload/dist/subprocess-runner.js +0 -295
  447. package/node_modules/@humwick/offload/dist/subprocess-runner.js.map +0 -1
  448. package/node_modules/@humwick/offload/dist/types.d.ts +0 -111
  449. package/node_modules/@humwick/offload/dist/types.d.ts.map +0 -1
  450. package/node_modules/@humwick/offload/dist/types.js +0 -176
  451. package/node_modules/@humwick/offload/dist/types.js.map +0 -1
  452. package/node_modules/@humwick/offload/dist/worker-pool.d.ts +0 -23
  453. package/node_modules/@humwick/offload/dist/worker-pool.d.ts.map +0 -1
  454. package/node_modules/@humwick/offload/dist/worker-pool.js +0 -435
  455. package/node_modules/@humwick/offload/dist/worker-pool.js.map +0 -1
  456. package/node_modules/@humwick/offload/dist/worker-runtime.d.ts +0 -2
  457. package/node_modules/@humwick/offload/dist/worker-runtime.d.ts.map +0 -1
  458. package/node_modules/@humwick/offload/dist/worker-runtime.js +0 -27
  459. package/node_modules/@humwick/offload/dist/worker-runtime.js.map +0 -1
  460. package/node_modules/@humwick/offload/dist/worker.d.ts +0 -5
  461. package/node_modules/@humwick/offload/dist/worker.d.ts.map +0 -1
  462. package/node_modules/@humwick/offload/dist/worker.js +0 -1
  463. package/node_modules/@humwick/offload/dist/worker.js.map +0 -1
  464. package/node_modules/@humwick/offload/package.json +0 -46
  465. package/node_modules/@humwick/offload/src/async-runner.ts +0 -170
  466. package/node_modules/@humwick/offload/src/envelope.ts +0 -92
  467. package/node_modules/@humwick/offload/src/fixtures/worker-task.ts +0 -49
  468. package/node_modules/@humwick/offload/src/index.ts +0 -4
  469. package/node_modules/@humwick/offload/src/subprocess-runner.ts +0 -334
  470. package/node_modules/@humwick/offload/src/types.ts +0 -235
  471. package/node_modules/@humwick/offload/src/worker-pool.ts +0 -463
  472. package/node_modules/@humwick/offload/src/worker-runtime.ts +0 -32
  473. package/node_modules/@humwick/offload/src/worker.ts +0 -5
  474. package/public/assets/agent-liveness-DyqxfB-t.js +0 -2
  475. package/public/assets/agent-profiles-BpI_jTxq.js +0 -2
  476. package/public/assets/fleet-BL4UXS_k.js +0 -2
  477. package/public/assets/index-B7ZerHLY.css +0 -2
  478. package/public/assets/index-BK0WV6hF.js +0 -15
  479. package/public/assets/projects-B_lmcqfO.js +0 -2
  480. package/public/assets/provider-display-DbLWpP3j.js +0 -2
  481. package/public/assets/run-card-CO_bguQf.js +0 -2
  482. package/public/assets/use-project-list-B-T2Bnnn.js +0 -2
  483. package/public/assets/versioned-prompt-editor-Diu8BIaM.js +0 -8
  484. package/runner/src/gate-run-lease-probe.ts +0 -38
  485. package/src/db/claude-catalog-reconcile.ts +0 -27
  486. package/src/routing-model-aliases.ts +0 -21
@@ -1,344 +0,0 @@
1
- import { Buffer } from "node:buffer";
2
- import { createHmac, randomBytes, timingSafeEqual } from "node:crypto";
3
- import type { EntityListOptions, EntityPage, EntityStore, EntityStores, ModuleDefinition, ModuleManifest, Scope } from "./contract";
4
- import type { KernelEntityMutation, KernelEntityStoredRow, KernelPersistence, KernelStoredValue } from "./kernel-persistence";
5
- import { assertValidManifest } from "./manifest-validation";
6
- import {
7
- EntityConflictError,
8
- EntityNotFoundError,
9
- EntitySessionClosedError,
10
- type EntityRawListOptions,
11
- type EntityRawPage,
12
- type EntityRawRow,
13
- } from "./persistence";
14
- import {
15
- buildModuleEntityCatalog,
16
- decodeField,
17
- encodeField,
18
- entityCatalogOf,
19
- type EntityField,
20
- type EntityTable,
21
- } from "./persistence-schema";
22
-
23
- type EntityValue = Record<string, unknown>;
24
-
25
- interface RowState {
26
- readonly table: EntityTable;
27
- readonly key: unknown;
28
- readonly expectedVersion: number | null;
29
- value?: EntityValue;
30
- deleted?: boolean;
31
- mutation?: "put" | "delete";
32
- }
33
-
34
- function keyIdentity(table: EntityTable, key: unknown): string {
35
- const encoded = encodeField(table.key, key);
36
- const parts = [table.name, typeof encoded, String(encoded)];
37
- return parts.map((part) => `${part.length}:${part}`).join("");
38
- }
39
-
40
- function decodedValue(table: EntityTable, row: KernelEntityStoredRow): EntityValue {
41
- const value: EntityValue = {};
42
- for (const field of table.fields) {
43
- const decoded = decodeField(field, row.values[field.name]);
44
- if (decoded !== undefined) value[field.name] = decoded;
45
- }
46
- return table.decl.schema.parse(value) as EntityValue;
47
- }
48
-
49
- function sign(secret: Buffer, body: string): string {
50
- return createHmac("sha256", secret).update(body).digest("base64url");
51
- }
52
-
53
- function encodeCursor(secret: Buffer, table: EntityTable, scope: Scope, key: KernelStoredValue): string {
54
- const body = Buffer.from(JSON.stringify({ v: 3, module: table.moduleId, entity: table.entityName, scope, type: typeof key, key: typeof key === "bigint" ? key.toString() : key })).toString("base64url");
55
- return `${body}.${sign(secret, body)}`;
56
- }
57
-
58
- function decodeCursor(secret: Buffer, table: EntityTable, scope: Scope, cursor: string): KernelStoredValue {
59
- try {
60
- const split = cursor.lastIndexOf(".");
61
- if (split < 0) throw new Error();
62
- const body = cursor.slice(0, split);
63
- const actual = Buffer.from(cursor.slice(split + 1));
64
- const expected = Buffer.from(sign(secret, body));
65
- if (actual.length !== expected.length || !timingSafeEqual(actual, expected)) throw new Error();
66
- const value = JSON.parse(Buffer.from(body, "base64url").toString("utf8")) as { v: number; module: string; entity: string; scope: string; type: string; key: KernelStoredValue };
67
- if (value.v !== 3 || value.module !== table.moduleId || value.entity !== table.entityName || value.scope !== scope) throw new Error();
68
- if (value.type === "bigint") return BigInt(value.key as string);
69
- if (value.type !== typeof value.key) throw new Error();
70
- return value.key;
71
- } catch {
72
- throw new TypeError(`invalid cursor for entity '${table.moduleId}.${table.entityName}'`);
73
- }
74
- }
75
-
76
- function pageSize(limit: number | undefined): number {
77
- const resolved = limit ?? 50;
78
- if (!Number.isInteger(resolved) || resolved < 1 || resolved > 200) {
79
- throw new RangeError("entity page limit must be an integer from 1 to 200");
80
- }
81
- return resolved;
82
- }
83
-
84
- function compareKeys(table: EntityTable, left: unknown, right: unknown): number {
85
- const a = encodeField(table.key, left);
86
- const b = encodeField(table.key, right);
87
- return a === b ? 0 : a! < b! ? -1 : 1;
88
- }
89
-
90
- function matchesWhere(value: EntityValue, where: ReadonlyMap<EntityField, unknown>): boolean {
91
- for (const [field, expected] of where) {
92
- if (encodeField(field, value[field.name]) !== encodeField(field, expected)) return false;
93
- }
94
- return true;
95
- }
96
-
97
- export interface AsyncEntitySession<E> {
98
- readonly entities: EntityStores<E>;
99
- readonly pendingMutations: number;
100
- seal(): void;
101
- discard(): void;
102
- mutations(): readonly KernelEntityMutation[];
103
- }
104
-
105
- class AsyncEntitySessionRuntime<E> implements AsyncEntitySession<E> {
106
- readonly entities: EntityStores<E>;
107
- readonly #states = new Map<string, RowState>();
108
- #closed = false;
109
- #finished = false;
110
-
111
- constructor(
112
- readonly port: KernelPersistence,
113
- readonly ready: Promise<void>,
114
- readonly scope: Scope,
115
- readonly cursorSecret: Buffer,
116
- tables: ReadonlyMap<string, EntityTable>,
117
- ) {
118
- this.entities = Object.freeze(Object.fromEntries(
119
- [...tables].map(([name, table]) => [name, this.#store(table)]),
120
- )) as EntityStores<E>;
121
- }
122
-
123
- get pendingMutations(): number {
124
- return [...this.#states.values()].filter((state) => state.mutation !== undefined).length;
125
- }
126
-
127
- #assertOpen(): void {
128
- if (this.#closed) throw new EntitySessionClosedError();
129
- }
130
-
131
- async #read(table: EntityTable, key: unknown): Promise<RowState> {
132
- const identity = keyIdentity(table, key);
133
- const known = this.#states.get(identity);
134
- if (known) return known;
135
- await this.ready;
136
- const row = await this.port.entityPoint({ entity: entityCatalogOf(table), scope: this.scope, key: encodeField(table.key, key) });
137
- const state: RowState = { table, key, expectedVersion: row?.version ?? null, value: row ? decodedValue(table, row) : undefined };
138
- this.#states.set(identity, state);
139
- return state;
140
- }
141
-
142
- #remember(table: EntityTable, row: KernelEntityStoredRow): RowState {
143
- const value = decodedValue(table, row);
144
- const key = value[table.key.name];
145
- const identity = keyIdentity(table, key);
146
- const known = this.#states.get(identity);
147
- if (known) return known;
148
- const state: RowState = { table, key, expectedVersion: row.version, value };
149
- this.#states.set(identity, state);
150
- return state;
151
- }
152
-
153
- #store(table: EntityTable): EntityStore {
154
- return {
155
- get: async (key) => {
156
- this.#assertOpen();
157
- const state = await this.#read(table, key);
158
- return state.deleted ? undefined : state.value;
159
- },
160
- list: async (options) => this.#list(table, options as EntityListOptions<EntityValue> | undefined),
161
- create: async (input) => {
162
- this.#assertOpen();
163
- const value = table.decl.schema.parse(input) as EntityValue;
164
- const key = value[table.key.name];
165
- const state = await this.#read(table, key);
166
- if (!state.deleted && state.value !== undefined) throw new EntityConflictError(table.moduleId, table.entityName, key);
167
- state.value = value;
168
- state.deleted = false;
169
- state.mutation = "put";
170
- return value;
171
- },
172
- update: async (key, patch) => {
173
- this.#assertOpen();
174
- const state = await this.#read(table, key);
175
- if (state.deleted || !state.value) throw new EntityNotFoundError(table.moduleId, table.entityName, key);
176
- const value = table.decl.schema.parse({ ...state.value, ...patch }) as EntityValue;
177
- if (keyIdentity(table, value[table.key.name]) !== keyIdentity(table, key)) throw new TypeError(`entity key '${table.key.name}' cannot be changed`);
178
- state.value = value;
179
- state.mutation = "put";
180
- return value;
181
- },
182
- delete: async (key) => {
183
- this.#assertOpen();
184
- const state = await this.#read(table, key);
185
- if (state.deleted || !state.value) return false;
186
- state.deleted = true;
187
- state.value = undefined;
188
- state.mutation = state.expectedVersion === null ? undefined : "delete";
189
- return true;
190
- },
191
- } as EntityStore;
192
- }
193
-
194
- async #list(table: EntityTable, options: EntityListOptions<EntityValue> | undefined): Promise<EntityPage<EntityValue>> {
195
- this.#assertOpen();
196
- await this.ready;
197
- const limit = pageSize(options?.limit);
198
- const where: Record<string, KernelStoredValue> = {};
199
- const parsedWhere = new Map<EntityField, unknown>();
200
- for (const [name, raw] of Object.entries(options?.where ?? {})) {
201
- const field = table.fieldByName.get(name);
202
- if (!field) throw new TypeError(`unknown where field '${name}' on '${table.moduleId}.${table.entityName}'`);
203
- const parsed = field.schema.parse(raw);
204
- parsedWhere.set(field, parsed);
205
- where[name] = encodeField(field, parsed);
206
- }
207
- const after = options?.cursor ? decodeCursor(this.cursorSecret, table, this.scope, options.cursor) : undefined;
208
- const stagedCount = [...this.#states.values()].filter((state) => state.table === table && state.mutation).length;
209
- const rows = await this.port.entityList({ entity: entityCatalogOf(table), scope: this.scope, where, ...(after !== undefined ? { after } : {}), limit: limit + stagedCount + 1 });
210
- const candidates = new Map<string, EntityValue>();
211
- for (const row of rows) {
212
- const state = this.#remember(table, row);
213
- if (!state.deleted && state.value && matchesWhere(state.value, parsedWhere)) candidates.set(keyIdentity(table, state.key), state.value);
214
- }
215
- for (const state of this.#states.values()) {
216
- if (state.table !== table || state.deleted || !state.value || !matchesWhere(state.value, parsedWhere)) continue;
217
- if (after !== undefined && compareKeys(table, state.key, decodeField(table.key, after)) <= 0) continue;
218
- candidates.set(keyIdentity(table, state.key), state.value);
219
- }
220
- const sorted = [...candidates.values()].sort((a, b) => compareKeys(table, a[table.key.name], b[table.key.name]));
221
- const page = sorted.slice(0, limit);
222
- const last = page.at(-1);
223
- return {
224
- items: page,
225
- ...(sorted.length > limit && last ? { cursor: encodeCursor(this.cursorSecret, table, this.scope, encodeField(table.key, last[table.key.name])) } : {}),
226
- };
227
- }
228
-
229
- seal(): void {
230
- if (this.#finished) throw new EntitySessionClosedError();
231
- this.#closed = true;
232
- }
233
-
234
- mutations(): readonly KernelEntityMutation[] {
235
- if (!this.#closed || this.#finished) throw new EntitySessionClosedError();
236
- const result: KernelEntityMutation[] = [];
237
- for (const state of this.#states.values()) {
238
- if (!state.mutation) continue;
239
- const entity = entityCatalogOf(state.table);
240
- if (state.mutation === "delete") {
241
- result.push({ kind: "delete", entity, scope: this.scope, key: encodeField(state.table.key, state.key), logicalKey: state.key as string | number | bigint | boolean, expectedVersion: state.expectedVersion });
242
- } else {
243
- const values = Object.fromEntries(state.table.fields.map((field) => [field.name, encodeField(field, state.value![field.name])]));
244
- result.push({ kind: "put", entity, scope: this.scope, key: encodeField(state.table.key, state.key), logicalKey: state.key as string | number | bigint | boolean, expectedVersion: state.expectedVersion, values });
245
- }
246
- }
247
- this.#finished = true;
248
- return Object.freeze(result);
249
- }
250
-
251
- discard(): void {
252
- if (this.#finished) throw new EntitySessionClosedError();
253
- this.#closed = true;
254
- this.#states.clear();
255
- this.#finished = true;
256
- }
257
- }
258
-
259
- export class AsyncEntityPersistence {
260
- readonly #tables = new Map<string, ReadonlyMap<string, EntityTable>>();
261
- readonly #ready = new Map<string, Promise<void>>();
262
- readonly #cursorSecret = randomBytes(32);
263
-
264
- constructor(readonly port: KernelPersistence) {}
265
-
266
- register<M extends ModuleManifest>(module: ModuleDefinition<M>): Promise<void> {
267
- assertValidManifest(module);
268
- if (this.#tables.has(module.id)) throw new Error(`module '${module.id}' entity persistence is already installed`);
269
- const { catalog, tables } = buildModuleEntityCatalog(module);
270
- this.#tables.set(module.id, tables);
271
- const ready = this.port.installModule(structuredClone(catalog));
272
- this.#ready.set(module.id, ready);
273
- return ready;
274
- }
275
-
276
- begin<M extends ModuleManifest>(module: ModuleDefinition<M>, scope: Scope): AsyncEntitySession<M["entities"]> {
277
- const tables = this.#tables.get(module.id);
278
- const ready = this.#ready.get(module.id);
279
- if (!tables || !ready) throw new Error(`module '${module.id}' entity persistence is not installed`);
280
- return new AsyncEntitySessionRuntime(this.port, ready, scope, this.#cursorSecret, tables);
281
- }
282
-
283
- ready(moduleId: string): Promise<void> {
284
- const ready = this.#ready.get(moduleId);
285
- if (!ready) throw new Error(`module '${moduleId}' entity persistence is not installed`);
286
- return ready;
287
- }
288
-
289
- #lookupTable(moduleId: string, entityName: string): EntityTable | undefined {
290
- return this.#tables.get(moduleId)?.get(entityName);
291
- }
292
-
293
- #rawRow(table: EntityTable, scope: Scope, row: KernelEntityStoredRow): EntityRawRow {
294
- const fields = decodedValue(table, row);
295
- return {
296
- module: table.moduleId,
297
- entity: table.entityName,
298
- scope,
299
- key: fields[table.key.name],
300
- version: row.version,
301
- createdAt: row.createdAt,
302
- updatedAt: row.updatedAt,
303
- fields,
304
- };
305
- }
306
-
307
- async readEntity(moduleId: string, entityName: string, scope: Scope, key: unknown): Promise<EntityRawRow | undefined> {
308
- const table = this.#lookupTable(moduleId, entityName);
309
- if (!table) return undefined;
310
- await this.ready(moduleId);
311
- const parsedKey = table.key.schema.parse(key);
312
- const row = await this.port.entityPoint({ entity: entityCatalogOf(table), scope, key: encodeField(table.key, parsedKey) });
313
- return row ? this.#rawRow(table, scope, row) : undefined;
314
- }
315
-
316
- async listEntity(moduleId: string, entityName: string, scope: Scope, options: EntityRawListOptions = {}): Promise<EntityRawPage> {
317
- const table = this.#lookupTable(moduleId, entityName);
318
- if (!table) return { items: [] };
319
- await this.ready(moduleId);
320
- const limit = pageSize(options.limit);
321
- const where: Record<string, KernelStoredValue> = {};
322
- for (const [name, raw] of Object.entries(options.where ?? {})) {
323
- const field = table.fieldByName.get(name);
324
- if (!field) throw new TypeError(`unknown where field '${name}' on '${moduleId}.${entityName}'`);
325
- where[name] = encodeField(field, field.schema.parse(raw));
326
- }
327
- const after = options.cursor ? decodeCursor(this.#cursorSecret, table, scope, options.cursor) : undefined;
328
- const rows = await this.port.entityList({
329
- entity: entityCatalogOf(table),
330
- scope,
331
- where,
332
- ...(after !== undefined ? { after } : {}),
333
- limit: limit + 1,
334
- });
335
- const items = rows.slice(0, limit).map((row) => this.#rawRow(table, scope, row));
336
- const last = items.at(-1);
337
- return {
338
- items,
339
- ...(rows.length > limit && last
340
- ? { cursor: encodeCursor(this.#cursorSecret, table, scope, encodeField(table.key, last.key)) }
341
- : {}),
342
- };
343
- }
344
- }
@@ -1,107 +0,0 @@
1
- import { isDeepStrictEqual } from "node:util";
2
- import type * as z from "zod";
3
- import type { EventWriter, ModuleDefinition, ModuleManifest, Scope } from "./contract";
4
- import { EventSessionClosedError, EventTopicMismatchError, UndeclaredEventError } from "./event-log";
5
- import type { KernelEventAppend, KernelPersistence } from "./kernel-persistence";
6
-
7
- interface PendingEvent {
8
- readonly name: string;
9
- readonly payload: string;
10
- }
11
-
12
- function normalizeJsonSafe(value: unknown): unknown {
13
- if (typeof value === "number") return Object.is(value, -0) ? 0 : value;
14
- if (Array.isArray(value)) return value.map(normalizeJsonSafe);
15
- if (value !== null && typeof value === "object" && Object.getPrototypeOf(value) === Object.prototype) {
16
- return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined).map(([key, entry]) => [key, normalizeJsonSafe(entry)]));
17
- }
18
- return value;
19
- }
20
-
21
- function encodePayload(value: unknown, name: string): string {
22
- try {
23
- const encoded = JSON.stringify(value);
24
- if (encoded === undefined || !isDeepStrictEqual(JSON.parse(encoded) as unknown, normalizeJsonSafe(value))) {
25
- throw new TypeError("value changes during JSON encoding");
26
- }
27
- return encoded;
28
- } catch (error) {
29
- throw new TypeError(`event '${name}' payload must be JSON-safe: ${error instanceof Error ? error.message : String(error)}`);
30
- }
31
- }
32
-
33
- export interface AsyncEventSession<E> {
34
- readonly events: EventWriter<E>;
35
- readonly pendingEvents: number;
36
- seal(): void;
37
- discard(): void;
38
- appends(createdAt: number): readonly KernelEventAppend[];
39
- }
40
-
41
- class AsyncEventSessionRuntime<E> implements AsyncEventSession<E> {
42
- readonly events: EventWriter<E>;
43
- readonly #buffer: PendingEvent[] = [];
44
- #closed = false;
45
- #finished = false;
46
-
47
- constructor(readonly scope: Scope, readonly moduleId: string, readonly schemas: ReadonlyMap<string, z.ZodType>) {
48
- const prefix = `${moduleId}.`;
49
- this.events = {
50
- emit: async (name: string, payload: unknown) => {
51
- if (this.#closed) throw new EventSessionClosedError();
52
- if (!name.startsWith(prefix) || name.length === prefix.length) throw new EventTopicMismatchError(moduleId, name);
53
- const schema = schemas.get(name);
54
- if (!schema) throw new UndeclaredEventError(moduleId, name);
55
- this.#buffer.push({ name, payload: encodePayload(schema.parse(payload), name) });
56
- },
57
- } as unknown as EventWriter<E>;
58
- }
59
-
60
- get pendingEvents(): number { return this.#buffer.length; }
61
-
62
- seal(): void {
63
- if (this.#finished) throw new EventSessionClosedError();
64
- this.#closed = true;
65
- }
66
-
67
- appends(createdAt: number): readonly KernelEventAppend[] {
68
- if (!this.#closed || this.#finished) throw new EventSessionClosedError();
69
- this.#finished = true;
70
- return Object.freeze(this.#buffer.map((event) => Object.freeze({
71
- scope: this.scope,
72
- moduleId: this.moduleId,
73
- name: event.name,
74
- payload: event.payload,
75
- createdAt,
76
- })));
77
- }
78
-
79
- discard(): void {
80
- if (this.#finished) throw new EventSessionClosedError();
81
- this.#closed = true;
82
- this.#buffer.length = 0;
83
- this.#finished = true;
84
- }
85
- }
86
-
87
- export class AsyncEventLogPersistence {
88
- readonly #modules = new Map<string, ReadonlyMap<string, z.ZodType>>();
89
- constructor(readonly port: KernelPersistence) {}
90
-
91
- register<M extends ModuleManifest>(module: ModuleDefinition<M>): void {
92
- if (this.#modules.has(module.id)) throw new Error(`module '${module.id}' event log is already installed`);
93
- this.#modules.set(module.id, new Map(Object.entries(module.events ?? {}) as Array<[string, z.ZodType]>));
94
- }
95
-
96
- begin<M extends ModuleManifest>(module: ModuleDefinition<M>, scope: Scope): AsyncEventSession<NonNullable<M["events"]>> {
97
- const schemas = this.#modules.get(module.id);
98
- if (!schemas) throw new Error(`module '${module.id}' event log is not installed`);
99
- return new AsyncEventSessionRuntime(scope, module.id, schemas);
100
- }
101
-
102
- replay(scope: Scope, since: number, limit: number, moduleId?: string) {
103
- return this.port.replayEvents(scope, since, limit, moduleId);
104
- }
105
-
106
- highWater(scope: Scope) { return this.port.eventHighWater(scope); }
107
- }
@@ -1,147 +0,0 @@
1
- import { z } from "zod";
2
- import { type EntityStore, type ModuleCtx, type StepResult, defineModule } from "./contract";
3
-
4
- /**
5
- * The M1 workflow-runtime pilot: an automations-shaped module whose workflows drive several steps
6
- * that mutate a kernel `run` entity, emit scoped events, and hand state from one step to the next.
7
- * It proves the forward-path executor end-to-end — memoization (each step journaled once), state
8
- * continuity (step N+1 sees exactly step N's snapshot), status projection across
9
- * running→sleeping/waiting→done, and that a `sleepUntil`/`waitFor` suspension parks the instance
10
- * without firing (durable firing is M3). Boring on purpose, like the timers pilot.
11
- */
12
-
13
- const runSchema = z.object({
14
- id: z.string(),
15
- phase: z.string(),
16
- total: z.number().int(),
17
- });
18
-
19
- /** The un-parameterized `ModuleCtx` handed to a step narrows its own `run` store here. */
20
- function runStore(ctx: ModuleCtx): EntityStore<{ schema: typeof runSchema }> {
21
- return (ctx.entities as unknown as { readonly run: EntityStore<{ schema: typeof runSchema }> }).run;
22
- }
23
-
24
- /** State threaded through the multi-step `pipeline` workflow; `log` records each step's input. */
25
- const pipelineState = z.object({
26
- id: z.string(),
27
- total: z.number().int(),
28
- log: z.array(z.string()),
29
- });
30
- type PipelineState = z.output<typeof pipelineState>;
31
-
32
- /** State for the suspending pilots (`napping`/`gated`). */
33
- const suspendState = z.object({
34
- id: z.string(),
35
- total: z.number().int(),
36
- });
37
- type SuspendState = z.output<typeof suspendState>;
38
-
39
- const startInput = z.object({ id: z.string() });
40
-
41
- export const automations = defineModule({
42
- id: "automations",
43
- title: "Automations runtime pilot",
44
- description: "Multi-step workflows proving the M1 forward-path executor (in-process only).",
45
- entities: {
46
- run: {
47
- schema: runSchema,
48
- indexes: ["phase"],
49
- },
50
- },
51
- events: {
52
- "automations.started": z.object({ id: z.string() }),
53
- "automations.progressed": z.object({ id: z.string(), phase: z.string(), total: z.number().int() }),
54
- "automations.completed": z.object({ id: z.string(), total: z.number().int() }),
55
- },
56
- workflows: {
57
- // Runs to completion with no suspension: ingest → enrich → publish(done). Each step mutates the
58
- // run entity, emits, and appends `${step}:saw=${incoming total}` so state continuity is directly
59
- // observable in the final journaled state.
60
- pipeline: {
61
- input: startInput,
62
- state: pipelineState,
63
- init: (input): PipelineState => ({ id: input.id, total: 0, log: [] }),
64
- start: "ingest",
65
- steps: {
66
- ingest: {
67
- run: async (ctx, state: PipelineState): Promise<StepResult<PipelineState>> => {
68
- const total = state.total + 1;
69
- await runStore(ctx).create({ id: state.id, phase: "ingested", total });
70
- await ctx.events.emit("automations.started", { id: state.id });
71
- await ctx.events.emit("automations.progressed", { id: state.id, phase: "ingested", total });
72
- return { state: { id: state.id, total, log: [...state.log, `ingest:saw=${state.total}`] }, next: "enrich" };
73
- },
74
- },
75
- enrich: {
76
- run: async (ctx, state: PipelineState): Promise<StepResult<PipelineState>> => {
77
- const total = state.total + 1;
78
- await runStore(ctx).update(state.id, { phase: "enriched", total });
79
- await ctx.events.emit("automations.progressed", { id: state.id, phase: "enriched", total });
80
- return { state: { id: state.id, total, log: [...state.log, `enrich:saw=${state.total}`] }, next: "publish" };
81
- },
82
- },
83
- publish: {
84
- run: async (ctx, state: PipelineState): Promise<StepResult<PipelineState>> => {
85
- const total = state.total + 1;
86
- await runStore(ctx).update(state.id, { phase: "published", total });
87
- await ctx.events.emit("automations.completed", { id: state.id, total });
88
- const log = [...state.log, `publish:saw=${state.total}`];
89
- return { state: { id: state.id, total, log }, next: "done", output: { total, log } };
90
- },
91
- },
92
- },
93
- },
94
-
95
- // Suspends on a durable timer after `warm`. M1 parks it `sleeping`; `settle` never runs until
96
- // M3's timer driver fires the sleep.
97
- napping: {
98
- input: startInput,
99
- state: suspendState,
100
- init: (input): SuspendState => ({ id: input.id, total: 0 }),
101
- start: "warm",
102
- steps: {
103
- warm: {
104
- run: async (ctx, state: SuspendState): Promise<StepResult<SuspendState>> => {
105
- await runStore(ctx).create({ id: state.id, phase: "warming", total: 1 });
106
- await ctx.events.emit("automations.started", { id: state.id });
107
- return { state: { id: state.id, total: 1 }, next: "settle", sleepUntil: ctx.clock.now() + 10_000 };
108
- },
109
- },
110
- settle: {
111
- run: async (ctx, state: SuspendState): Promise<StepResult<SuspendState>> => {
112
- await runStore(ctx).update(state.id, { phase: "settled" });
113
- return { state, next: "done" };
114
- },
115
- },
116
- },
117
- },
118
-
119
- // Suspends on an event wait after `arm`. M1 parks it `waiting`; `release` never runs until M3's
120
- // wait driver delivers the awaited event.
121
- gated: {
122
- input: startInput,
123
- state: suspendState,
124
- init: (input): SuspendState => ({ id: input.id, total: 0 }),
125
- start: "arm",
126
- steps: {
127
- arm: {
128
- run: async (ctx, state: SuspendState): Promise<StepResult<SuspendState>> => {
129
- await runStore(ctx).create({ id: state.id, phase: "armed", total: 1 });
130
- await ctx.events.emit("automations.started", { id: state.id });
131
- return {
132
- state: { id: state.id, total: 1 },
133
- next: "release",
134
- waitFor: { kind: "event", topic: "automations.progressed", correlationId: state.id },
135
- };
136
- },
137
- },
138
- release: {
139
- run: async (ctx, state: SuspendState): Promise<StepResult<SuspendState>> => {
140
- await runStore(ctx).update(state.id, { phase: "released" });
141
- return { state, next: "done" };
142
- },
143
- },
144
- },
145
- },
146
- },
147
- });