@humwick/server 0.130.1 → 0.130.3

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 (811) hide show
  1. package/README.md +5 -0
  2. package/bundled/prompts/manifest.json +1 -0
  3. package/bundled/prompts/task.hydration.md +1 -1
  4. package/bundled/roles/builder.md +1 -1
  5. package/docs/guides/sub-coordinators.md +12 -5
  6. package/docs/guides/tools-administration.md +4 -0
  7. package/docs/guides/tools-coordination.md +2 -0
  8. package/docs/guides/tools-tasks.md +8 -0
  9. package/docs/guides/workflows.md +74 -0
  10. package/docs/openapi.json +486 -4
  11. package/package.json +10 -18
  12. package/public/assets/{MessageBubble-BWpoBjl4.js → MessageBubble-Bq9kr21N.js} +2 -2
  13. package/public/assets/{PlanGraphPanel-C0auck3n.js → PlanGraphPanel-Dqiroy06.js} +2 -2
  14. package/public/assets/{TraceView-DBnOx7AQ.js → TraceView-DYU962-H.js} +2 -2
  15. package/public/assets/{VaultDecisionCard-0kp2oNBC.js → VaultDecisionCard-DhPfzioE.js} +2 -2
  16. package/public/assets/{activity-yLztXEBt.js → activity-DzCcQTee.js} +2 -2
  17. package/public/assets/{agent-lineage-BbJDR1dW.js → agent-lineage-SgDt9i3T.js} +2 -2
  18. package/public/assets/agent-liveness-Bq-s73jW.js +2 -0
  19. package/public/assets/{agent-name-CTZBrSD9.js → agent-name-CcY3Aijy.js} +2 -2
  20. package/public/assets/agent-profiles-cxtRBn6O.js +2 -0
  21. package/public/assets/{agent-project-badge-9TqzUUYE.js → agent-project-badge-DGYbIhaI.js} +2 -2
  22. package/public/assets/{agent-tools-D4n40pn8.js → agent-tools-DHbftV0N.js} +2 -2
  23. package/public/assets/{agent-type-icon-D6FUarOf.js → agent-type-icon-CY113sp-.js} +2 -2
  24. package/public/assets/{agents-BYDslkJc.js → agents-BPzY7IlQ.js} +2 -2
  25. package/public/assets/{analytics-B-XSbEMC.js → analytics-DENFPv_a.js} +2 -2
  26. package/public/assets/{artifact-viewer-DdWIfV6M.js → artifact-viewer-KRvSc7sl.js} +2 -2
  27. package/public/assets/{artifacts-DPN1q4pA.js → artifacts-C9gSmL3s.js} +2 -2
  28. package/public/assets/{artifacts-oBOqks-2.js → artifacts-DT-HkI5O.js} +2 -2
  29. package/public/assets/{automation-4KcRFXEu.js → automation-BsmjQhKD.js} +2 -2
  30. package/public/assets/{backlog-Cw9xPTCF.js → backlog-8NYH_62t.js} +2 -2
  31. package/public/assets/{busy-health-CTu32MZt.js → busy-health-D3hwvYb4.js} +2 -2
  32. package/public/assets/{channels-BiXzg1G9.js → channels-DCJ5WL7O.js} +2 -2
  33. package/public/assets/{chat-Ctk2qwvA.js → chat-DAIl357U.js} +3 -3
  34. package/public/assets/{code-preview-Bm1wWqAp.js → code-preview-CzrZfr9U.js} +2 -2
  35. package/public/assets/{connectors-C36ax4Vw.js → connectors-xTxtlyou.js} +2 -2
  36. package/public/assets/{cosmos-Jj9LK2Wf.js → cosmos-BpebFLK2.js} +2 -2
  37. package/public/assets/{crate-agent-H6S7-B9T.js → crate-agent-BHvI5wXC.js} +2 -2
  38. package/public/assets/{dependency-graph-Cd1E23wa.js → dependency-graph-DGT0o3wJ.js} +2 -2
  39. package/public/assets/{deploys-Bwfq146q.js → deploys-hqWOHSHE.js} +2 -2
  40. package/public/assets/{display-CfO7rTuF.js → display-CDeH4I8T.js} +2 -2
  41. package/public/assets/{files-DhhZI2Ih.js → files-BTeGVmTg.js} +2 -2
  42. package/public/assets/{fleet-B_rFEbnL.js → fleet-DgXtNgCa.js} +2 -2
  43. package/public/assets/{fleet-metrics-BkHP-P3R.js → fleet-metrics-BHEt5yc_.js} +2 -2
  44. package/public/assets/{formatted-body-Cm1RrzmN.js → formatted-body-MLtodyPp.js} +3 -3
  45. package/public/assets/{formatted-body-impl-DQiOuOD1.js → formatted-body-impl-CAe664Z8.js} +2 -2
  46. package/public/assets/{host-providers-dialog-CHqwXTov.js → host-providers-dialog-mapF4Fj9.js} +2 -2
  47. package/public/assets/index-CqqgOI5R.js +15 -0
  48. package/public/assets/index-MYAIwYTX.css +2 -0
  49. package/public/assets/{insights-fH1EL-qZ.js → insights-DNyf7IzF.js} +2 -2
  50. package/public/assets/{integrations-C5Oix6ng.js → integrations-DlYOHq7T.js} +2 -2
  51. package/public/assets/{issue-ref-chip-ODyondIa.js → issue-ref-chip-CeWBNWn7.js} +2 -2
  52. package/public/assets/{log-viewer-Cvfy6PW7.js → log-viewer-Cib8nqdE.js} +2 -2
  53. package/public/assets/{maintenance-D8CDH5wZ.js → maintenance-DSn1cPm7.js} +2 -2
  54. package/public/assets/{managed-agents-egllbpij.js → managed-agents-C3CkM81m.js} +2 -2
  55. package/public/assets/{markdown-preview-CYSFgVgK.js → markdown-preview-W4VQQPAv.js} +3 -3
  56. package/public/assets/{markdown-preview-impl-BteVIjX4.js → markdown-preview-impl-CMsTdhjq.js} +2 -2
  57. package/public/assets/{memory-C8WmXsyr.js → memory-BV17qtO4.js} +2 -2
  58. package/public/assets/{messages-BzQdqlO6.js → messages-Bm_1AqSA.js} +2 -2
  59. package/public/assets/{orchestrators-B1HxzkNw.js → orchestrators-Dg-vfP09.js} +2 -2
  60. package/public/assets/{overview-DCUnI4Z7.js → overview-DcYCrvlr.js} +2 -2
  61. package/public/assets/{pairs-ftCd2XcD.js → pairs-8o9nuG3V.js} +2 -2
  62. package/public/assets/{profile-icon-B2zH8DMH.js → profile-icon-BsRyBMea.js} +2 -2
  63. package/public/assets/project-profile-instructions-DETKFn_E.js +2 -0
  64. package/public/assets/projects-M_m6AHws.js +2 -0
  65. package/public/assets/{prompt-settings-Bftq9czX.js → prompt-settings-C_mNCgeL.js} +2 -2
  66. package/public/assets/provider-display-BEeLXC_D.js +2 -0
  67. package/public/assets/{registry-DWCU5c8q.js → registry-DDHHHE5N.js} +2 -2
  68. package/public/assets/run-card-Dt4I4jaP.js +2 -0
  69. package/public/assets/scroll-text-BKXS1ahr.js +2 -0
  70. package/public/assets/{secrets-C7GIUATz.js → secrets-BkVwxI5O.js} +2 -2
  71. package/public/assets/{service-access-settings-C3aujqTG.js → service-access-settings-Crq-6a-B.js} +2 -2
  72. package/public/assets/{settings-C6sZ9eBa.js → settings-CYcavMFu.js} +2 -2
  73. package/public/assets/shipping-H6gzEeZB.js +2 -0
  74. package/public/assets/{stats-V9Z-GxUd.js → stats-BJVeWkpV.js} +2 -2
  75. package/public/assets/{status-dot-CVv0iGHL.js → status-dot-BcHyw1Vw.js} +2 -2
  76. package/public/assets/store-DKPDIZBe.js +9 -0
  77. package/public/assets/{tasks-CXU75HRF.js → tasks-qJjlQPpx.js} +2 -2
  78. package/public/assets/{teams-BPf976zb.js → teams-Cd5Sk1uX.js} +2 -2
  79. package/public/assets/{terminal-viewer-DE9BOe-8.js → terminal-viewer-CpY5_m7W.js} +3 -3
  80. package/public/assets/{terminal-viewer-impl-D04pjmGh.js → terminal-viewer-impl-DI_2llFR.js} +2 -2
  81. package/public/assets/token-estimate-Co-Jdphh.js +2 -0
  82. package/public/assets/{use-agent-terminal-B1yR456R.js → use-agent-terminal-0yJA_buM.js} +2 -2
  83. package/public/assets/{use-decisions-D-S4tpDf.js → use-decisions-uJXHf34W.js} +2 -2
  84. package/public/assets/use-project-list-CpWl6eHQ.js +2 -0
  85. package/public/assets/{use-selectors-CnrAk2YP.js → use-selectors-BdxBW8mL.js} +2 -2
  86. package/public/assets/{user-avatar-nBFIcR4M.js → user-avatar-3IndfpOc.js} +2 -2
  87. package/public/assets/versioned-prompt-editor-CIVg7XB1.js +8 -0
  88. package/public/assets/{work-queue-TCjJxeT-.js → work-queue-B9rnLwHZ.js} +2 -2
  89. package/public/assets/{workflow-marker-Cf3Hf2fN.js → workflow-marker-X8wxyhzC.js} +2 -2
  90. package/public/assets/{workflows-CXQX20Qj.js → workflows-o5YyMFW7.js} +2 -2
  91. package/public/assets/{workspaces-qSYzKYMA.js → workspaces-CzEGoAng.js} +2 -2
  92. package/public/cosmos.html +4 -4
  93. package/public/index.html +31 -29
  94. package/runner/plugins/claude/.claude-plugin/plugin.json +1 -1
  95. package/runner/plugins/claude/hooks/gate-run-guard.provisioned.mjs +31 -1
  96. package/runner/src/adapters/claude-effort.ts +2 -4
  97. package/runner/src/adapters/claude-headless.ts +1 -1
  98. package/runner/src/adapters/claude-launch-exit.ts +26 -0
  99. package/runner/src/adapters/claude-session-probe.ts +1 -1
  100. package/runner/src/adapters/claude-tmux.ts +38 -10
  101. package/runner/src/adapters/claude.ts +28 -75
  102. package/runner/src/adapters/codex-launch-config.ts +4 -5
  103. package/runner/src/adapters/codex.ts +1 -1
  104. package/runner/src/adapters/opencode-provider.ts +7 -22
  105. package/runner/src/adapters/opencode.ts +4 -4
  106. package/runner/src/adapters/provider-quota-harvest.ts +20 -71
  107. package/runner/src/agent-runner/credentials.ts +42 -12
  108. package/runner/src/agent-runner/inbox.ts +27 -0
  109. package/runner/src/agent-runner/lifecycle-milestones.ts +2 -4
  110. package/runner/src/agent-runner/liveness-exchange.ts +104 -0
  111. package/runner/src/bin/claude.ts +4 -0
  112. package/runner/src/bin/codex.ts +4 -0
  113. package/runner/src/bin/opencode.ts +4 -0
  114. package/runner/src/claude-system-prompt.ts +49 -0
  115. package/runner/src/index.ts +5 -2
  116. package/runner/src/launch-assembly.ts +14 -10
  117. package/runner/src/profile-home.ts +1 -1
  118. package/runner/src/project-instructions.ts +2 -2
  119. package/runner/src/provider-command.ts +18 -0
  120. package/runner/src/provider-setup.ts +35 -0
  121. package/runner/src/providers.ts +2 -1
  122. package/runner/src/runner-core.ts +32 -38
  123. package/runner/src/runner-helpers.ts +0 -8
  124. package/runner/src/session-scratch.ts +6 -2
  125. package/runner/src/spawn-input.ts +2 -1
  126. package/runner/src/test-run-dedup.ts +59 -56
  127. package/runner/test-support/provisioning-context.ts +4 -2
  128. package/runner/test-support/runner-harness.ts +2 -1
  129. package/scripts/cd-config.ts +8 -0
  130. package/scripts/gate-run-lease.ts +10 -7
  131. package/scripts/gate.sh +5 -1
  132. package/scripts/steward-policy-cleanup.ts +2 -2
  133. package/src/agent-authz.ts +2 -2
  134. package/src/agent-drive-arbiter.ts +3 -8
  135. package/src/agent-exit-cleanup-async.ts +2 -2
  136. package/src/agent-exit-cleanup.ts +23 -19
  137. package/src/agent-lifecycle-events.ts +112 -85
  138. package/src/agent-ref.ts +3 -2
  139. package/src/agent-status-events.ts +43 -14
  140. package/src/auth/password.ts +4 -3
  141. package/src/auth/session-refresh.ts +1 -1
  142. package/src/auth/session.test-fixture.ts +2 -2
  143. package/src/auth/session.ts +7 -7
  144. package/src/automations/crud.ts +8 -81
  145. package/src/automations/dispatch.ts +33 -58
  146. package/src/automations/index.ts +1 -1
  147. package/src/automations/persistence.ts +65 -0
  148. package/src/automations/precheck.ts +18 -16
  149. package/src/automations/read-async.ts +11 -0
  150. package/src/automations/reconcile.ts +30 -39
  151. package/src/automations/storage.ts +33 -10
  152. package/src/automations/write-async.ts +33 -0
  153. package/src/branch-land-notice.ts +93 -0
  154. package/src/branch-landed.ts +31 -98
  155. package/src/bus.ts +40 -39
  156. package/src/cd-deploy-notify.ts +32 -4
  157. package/src/cd-host-lag-notify.ts +7 -6
  158. package/src/ci/incidents.ts +2 -2
  159. package/src/ci/monitor.ts +5 -8
  160. package/src/ci/notifications.ts +4 -4
  161. package/src/ci/root-missing.ts +4 -9
  162. package/src/ci/transition-notify.ts +12 -44
  163. package/src/claude-app/oauth-http.ts +3 -3
  164. package/src/cli/cd-pauses.ts +19 -0
  165. package/src/cli/orchestrator.ts +1 -1
  166. package/src/cli/state.ts +2 -19
  167. package/src/cli/task-edit.ts +22 -0
  168. package/src/cli/task.ts +3 -1
  169. package/src/cli/workflow.ts +19 -4
  170. package/src/commands-db.ts +7 -7
  171. package/src/commands-write.ts +8 -0
  172. package/src/compaction-watch.ts +10 -8
  173. package/src/config-store-write.ts +13 -1
  174. package/src/config-store.ts +25 -14
  175. package/src/config.ts +4 -11
  176. package/src/connectors.ts +10 -8
  177. package/src/context-advisory.ts +22 -21
  178. package/src/db/activity-async.ts +6 -1
  179. package/src/db/activity-write-ops.ts +12 -1
  180. package/src/db/activity.ts +1 -14
  181. package/src/db/agent-action-write.ts +36 -0
  182. package/src/db/agent-control-async.ts +9 -0
  183. package/src/db/agent-control-write.ts +49 -0
  184. package/src/db/agent-effort-observe.ts +22 -0
  185. package/src/db/agent-meta.ts +14 -3
  186. package/src/db/agent-search.ts +1 -15
  187. package/src/db/agents-async.ts +59 -9
  188. package/src/db/agents-write-ops.ts +12 -3
  189. package/src/db/agents.ts +95 -65
  190. package/src/db/auth-identities.ts +2 -2
  191. package/src/db/automation-read-ops.ts +11 -0
  192. package/src/db/automation-write-ops.ts +46 -0
  193. package/src/db/blackboard.ts +2 -2
  194. package/src/db/browser-session-write.ts +32 -0
  195. package/src/db/bus-outbox-write-ops.ts +3 -1
  196. package/src/db/checkout-refresh-schema.ts +47 -0
  197. package/src/db/checkout-refresh.ts +5 -5
  198. package/src/db/ci-incidents-async.ts +5 -5
  199. package/src/db/ci-incidents-write-ops.ts +2 -2
  200. package/src/db/command-agent-profile-backfill.ts +39 -0
  201. package/src/db/command-agent-profiles.ts +5 -1
  202. package/src/db/command-retention.ts +126 -0
  203. package/src/db/command-row.ts +10 -2
  204. package/src/db/commands-list-query.ts +2 -0
  205. package/src/db/commands-planner-stats.test-fixture.ts +8 -0
  206. package/src/db/commands-read-ops.ts +16 -0
  207. package/src/db/commands-spawn-read.ts +1 -1
  208. package/src/db/config-store-write-ops.ts +7 -2
  209. package/src/db/connection.ts +1 -182
  210. package/src/db/context-carry-write.ts +74 -0
  211. package/src/db/continuation-archives-async.ts +5 -0
  212. package/src/db/continuation-archives-write-ops.ts +7 -0
  213. package/src/db/continuations.ts +6 -6
  214. package/src/db/db-error-registry.ts +12 -0
  215. package/src/db/db-writer-worker.ts +8 -1
  216. package/src/db/deploy-events-async.ts +1 -0
  217. package/src/db/deploy-events-read-ops.ts +2 -1
  218. package/src/db/deploy-events.ts +35 -4
  219. package/src/db/gateway.ts +26 -133
  220. package/src/db/history-retention-ops.ts +13 -0
  221. package/src/db/hosts-registration.ts +10 -2
  222. package/src/db/hosts.ts +9 -6
  223. package/src/db/inbox-async.ts +2 -2
  224. package/src/db/inbox-read-ops.ts +1 -1
  225. package/src/db/inbox.ts +9 -17
  226. package/src/db/index.ts +2 -0
  227. package/src/db/integrations-async.ts +8 -0
  228. package/src/db/integrations-ops.ts +15 -0
  229. package/src/db/integrations.ts +15 -21
  230. package/src/db/issue-associations.ts +2 -2
  231. package/src/db/issue-lifecycle.ts +3 -4
  232. package/src/db/issue-refs-async.ts +23 -0
  233. package/src/db/issue-refs-read-ops.ts +6 -0
  234. package/src/db/issue-refs-write-ops.ts +29 -0
  235. package/src/db/issue-refs.ts +15 -16
  236. package/src/db/kernel-event-log-schema.ts +2 -0
  237. package/src/db/land-boundaries.ts +51 -5
  238. package/src/db/land-gate-attestations.ts +2 -2
  239. package/src/db/landing-receipts.ts +2 -2
  240. package/src/db/lifecycle-context-write.ts +5 -0
  241. package/src/db/lifecycle-tail-async.ts +76 -0
  242. package/src/db/lifecycle-tail-write-ops.ts +62 -0
  243. package/src/db/lifecycle-write-window.ts +2 -1
  244. package/src/db/lineage-pair-dedupe-sql.ts +3 -3
  245. package/src/db/long-running-work.ts +2 -2
  246. package/src/db/main-connection-mode.ts +11 -0
  247. package/src/db/main-connection-writes.ts +41 -2
  248. package/src/db/maintenance-job-reconcile.ts +61 -0
  249. package/src/db/maintenance-job-runs-async.ts +14 -0
  250. package/src/db/maintenance-job-write-ops.ts +9 -0
  251. package/src/db/maintenance-pauses.ts +2 -2
  252. package/src/db/mappers.ts +2 -14
  253. package/src/db/merge-lease.ts +1 -15
  254. package/src/db/message-send.ts +4 -0
  255. package/src/db/messages.ts +31 -25
  256. package/src/db/migrations.ts +25 -16
  257. package/src/db/notification-write-ops.ts +19 -0
  258. package/src/db/operator-answer-write.ts +19 -0
  259. package/src/db/orchestrators.ts +14 -76
  260. package/src/db/pairs-async.ts +22 -1
  261. package/src/db/pairs-write-ops.ts +8 -3
  262. package/src/db/pairs.ts +42 -61
  263. package/src/db/plan-dispatch-schema.ts +5 -1
  264. package/src/db/plan-ready-notices.ts +43 -0
  265. package/src/db/plan-tools-include-migration.ts +36 -0
  266. package/src/db/plans-write-ops.ts +2 -0
  267. package/src/db/presence-buffer.ts +5 -0
  268. package/src/db/presence-loop.ts +18 -23
  269. package/src/db/presence-write.ts +0 -6
  270. package/src/db/project-entries-async.ts +14 -0
  271. package/src/db/project-entries-read-ops.ts +5 -1
  272. package/src/db/project-entries-write-ops.ts +8 -0
  273. package/src/db/project-entries.ts +15 -12
  274. package/src/db/project-journal.ts +2 -2
  275. package/src/db/project-profile-instructions.ts +50 -0
  276. package/src/db/project-trust-approvals.ts +2 -2
  277. package/src/db/prompt-templates.ts +4 -4
  278. package/src/db/prompt-versions.ts +9 -2
  279. package/src/db/provider-config-history.ts +8 -3
  280. package/src/db/provider-model-seed.ts +34 -0
  281. package/src/db/read-op-marshaling-fixtures.ts +23 -0
  282. package/src/db/read-ops.ts +8 -0
  283. package/src/db/retention.ts +13 -2
  284. package/src/db/review-publish-write.ts +8 -0
  285. package/src/db/routing-policy.ts +2 -3
  286. package/src/db/runtime-admin-async.ts +19 -0
  287. package/src/db/runtime-admin-write-ops.ts +36 -0
  288. package/src/db/runtime-tail-async.ts +288 -0
  289. package/src/db/runtime-tail-write-ops.ts +97 -0
  290. package/src/db/schema.ts +13 -4
  291. package/src/db/spawn-budget.ts +5 -0
  292. package/src/db/spawn-delegation-state.ts +11 -4
  293. package/src/db/spawn-delegation.ts +1 -11
  294. package/src/db/sql-audit-indexes.ts +3 -0
  295. package/src/db/stats-async.ts +9 -6
  296. package/src/db/task-entity.ts +28 -6
  297. package/src/db/task-list.ts +3 -1
  298. package/src/db/tasks.ts +1 -17
  299. package/src/db/team-claim-policy.ts +60 -0
  300. package/src/db/teams-async.ts +4 -0
  301. package/src/db/teams-write-ops.ts +4 -0
  302. package/src/db/terminal-events.ts +15 -0
  303. package/src/db/timer-cutover-bodies.ts +292 -0
  304. package/src/db/timer-cutover-core.ts +37 -278
  305. package/src/db/timer-cutover-state.ts +40 -0
  306. package/src/db/timer-cutover-write-ops.ts +1 -40
  307. package/src/db/timer-ingress.ts +7 -1
  308. package/src/db/token-db-write-ops.ts +19 -0
  309. package/src/db/token-standing-async.ts +12 -0
  310. package/src/db/token-standing.ts +21 -20
  311. package/src/db/token-usage-retention.ts +33 -0
  312. package/src/db/token-usage-write-ops.ts +1 -1
  313. package/src/db/token-usage.ts +4 -1
  314. package/src/db/user-invites-async.ts +13 -0
  315. package/src/db/user-invites.ts +3 -3
  316. package/src/db/users.ts +14 -6
  317. package/src/db/workflow-contact.ts +1 -1
  318. package/src/db/workflow-task-read-ops.ts +30 -0
  319. package/src/db/workspaces.ts +8 -5
  320. package/src/db/write-ops.ts +37 -12
  321. package/src/db/writer-fault-seam.ts +2 -9
  322. package/src/db/writer-fault-test-ops.ts +18 -0
  323. package/src/db/writer-gateway.ts +58 -56
  324. package/src/dev.ts +8 -3
  325. package/src/dispatch-availability.ts +10 -6
  326. package/src/ephemeral/{landing-ingress-proof-worker.ts → landing-ingress-proof.test-fixture.ts} +4 -2
  327. package/src/event-loop-lag.ts +4 -2
  328. package/src/event-loop-yield.ts +2 -2
  329. package/src/events.ts +10 -8
  330. package/src/host/disk-alert.ts +121 -0
  331. package/src/host-provider-store.ts +5 -4
  332. package/src/hub-metrics-report.ts +5 -1
  333. package/src/hub-metrics.ts +38 -18
  334. package/src/injection-sweep-pacing.ts +6 -8
  335. package/src/land-gate-notifications.ts +11 -10
  336. package/src/land-gate-queue-progress.ts +3 -3
  337. package/src/land-settle-dispatch.ts +52 -92
  338. package/src/lifecycle-context-pressure.ts +11 -10
  339. package/src/lifecycle-manager.ts +107 -100
  340. package/src/maintenance/breaker.ts +18 -16
  341. package/src/maintenance/cd-watcher.ts +3 -3
  342. package/src/maintenance/checkout-refresh.ts +18 -1
  343. package/src/maintenance/critical-job-watchdog.ts +19 -20
  344. package/src/maintenance/events.ts +3 -3
  345. package/src/maintenance/history-retention-job.ts +30 -0
  346. package/src/maintenance/index.ts +1 -0
  347. package/src/maintenance/jobs.ts +32 -69
  348. package/src/maintenance/long-running-work.ts +3 -1
  349. package/src/maintenance/offline-agent-prune-job.ts +28 -0
  350. package/src/maintenance/orphaned-sessions.ts +5 -4
  351. package/src/maintenance/pauses.ts +4 -10
  352. package/src/maintenance/plan-ready-notice-job.ts +71 -0
  353. package/src/maintenance/scheduler.ts +98 -137
  354. package/src/maintenance/stalled-delivery-pager.ts +10 -9
  355. package/src/maintenance/teams.ts +19 -30
  356. package/src/maintenance/workspaces.ts +18 -28
  357. package/src/managed-policy-escalation.ts +7 -7
  358. package/src/managed-policy.ts +32 -28
  359. package/src/managed-provider-gate.ts +5 -4
  360. package/src/managed-spawn-reservation.ts +5 -4
  361. package/src/mcp/index.ts +12 -9
  362. package/src/mcp/output-descriptions.ts +8 -8
  363. package/src/mcp/presentation.ts +6 -5
  364. package/src/mcp/project-profile-instructions.ts +32 -0
  365. package/src/mcp/runtime-output.ts +6 -1
  366. package/src/mcp/self-care-visibility.ts +2 -2
  367. package/src/mcp/spawn-targets-matrix.ts +10 -1
  368. package/src/mcp/tool-groups.ts +4 -3
  369. package/src/mcp/tool-roles.ts +81 -0
  370. package/src/mcp/tools-spawn.ts +4 -3
  371. package/src/mcp/tools-workspace.ts +1 -1
  372. package/src/mcp-agent-action.ts +1 -2
  373. package/src/mcp-blackboard-tools.ts +6 -5
  374. package/src/mcp-decision-tools.ts +7 -7
  375. package/src/mcp-egress-tools.ts +10 -9
  376. package/src/mcp-issue-activity-tools.ts +2 -2
  377. package/src/mcp-issue-association-tools.ts +4 -4
  378. package/src/mcp-issue-ref-tools.ts +13 -12
  379. package/src/mcp-maintenance-tools.ts +2 -2
  380. package/src/mcp-merge-tools.ts +5 -5
  381. package/src/mcp-notification-subscription-tools.ts +14 -15
  382. package/src/mcp-output-levels.test-fixture.ts +1 -1
  383. package/src/mcp-profile-trust-tools.ts +5 -5
  384. package/src/mcp-project-journal-tools.ts +4 -12
  385. package/src/mcp-project-tools.ts +17 -18
  386. package/src/mcp-provider-catalog.ts +2 -2
  387. package/src/mcp-routing-policy-tools.ts +3 -2
  388. package/src/mcp-task-tools.ts +11 -5
  389. package/src/mcp-team-template-tools.ts +3 -3
  390. package/src/mcp-team-tools.ts +6 -6
  391. package/src/mcp-workflow-tools.ts +13 -4
  392. package/src/memory-area-injection.ts +13 -12
  393. package/src/memory-boundary-capture.ts +6 -6
  394. package/src/memory-injection.ts +45 -43
  395. package/src/merge-pause-maintenance.ts +5 -4
  396. package/src/notification-router.ts +44 -17
  397. package/src/notification-types.ts +2 -1
  398. package/src/notify.ts +5 -5
  399. package/src/observed-reset-refresh.ts +4 -4
  400. package/src/operator-alarm.ts +23 -11
  401. package/src/project-ingest.ts +6 -6
  402. package/src/project-instructions.ts +12 -1
  403. package/src/project-profile-instruction-text.ts +6 -0
  404. package/src/project-profile-instructions.ts +20 -0
  405. package/src/project-trust.ts +12 -11
  406. package/src/prompt-resolver.ts +3 -3
  407. package/src/provider-catalog-store.ts +3 -49
  408. package/src/provider-config-store.ts +12 -11
  409. package/src/provider-model-seed.ts +1 -18
  410. package/src/provider-quota-async.ts +5 -7
  411. package/src/provider-quota-config-store.ts +5 -4
  412. package/src/provider-secrets.test-fixture.ts +3 -3
  413. package/src/provider-timeline-event.ts +4 -7
  414. package/src/quota-band-delivery.ts +2 -2
  415. package/src/recipe-runner.ts +6 -5
  416. package/src/repo-config-source.ts +10 -4
  417. package/src/retention-config-store.ts +4 -3
  418. package/src/reviewer-pipeline.ts +11 -10
  419. package/src/routes/_route.ts +4 -4
  420. package/src/routes/_shared.ts +13 -12
  421. package/src/routes/agent-effort.ts +5 -5
  422. package/src/routes/agent-heartbeat-quota.ts +23 -0
  423. package/src/routes/agent-keep.ts +1 -1
  424. package/src/routes/agent-profiles.ts +6 -6
  425. package/src/routes/agent-reporting.ts +1 -1
  426. package/src/routes/agent-self-effort.ts +5 -5
  427. package/src/routes/agent-sessions.ts +24 -24
  428. package/src/routes/agents-spawn.ts +2 -2
  429. package/src/routes/agents.ts +19 -121
  430. package/src/routes/auth.ts +14 -15
  431. package/src/routes/authority-audit.ts +2 -2
  432. package/src/routes/automations.ts +6 -5
  433. package/src/routes/channel-binding-delete.ts +1 -1
  434. package/src/routes/channel-output.ts +3 -3
  435. package/src/routes/claude-api-budget.ts +5 -5
  436. package/src/routes/commands-listing.ts +5 -1
  437. package/src/routes/commands.ts +31 -29
  438. package/src/routes/context-resets.ts +2 -2
  439. package/src/routes/continuation-archives.ts +2 -2
  440. package/src/routes/coordinator-teams.ts +1 -1
  441. package/src/routes/decisions.ts +2 -2
  442. package/src/routes/host-secret-files.ts +1 -1
  443. package/src/routes/hosts.ts +11 -11
  444. package/src/routes/inbox.ts +3 -2
  445. package/src/routes/index.ts +12 -2
  446. package/src/routes/integrations.ts +32 -56
  447. package/src/routes/issue-activity.ts +2 -2
  448. package/src/routes/issue-associations.ts +4 -4
  449. package/src/routes/issue-refs.ts +9 -9
  450. package/src/routes/kernel-timers-operator.ts +1 -1
  451. package/src/routes/memory.ts +1 -1
  452. package/src/routes/merges.ts +11 -11
  453. package/src/routes/messages.ts +23 -17
  454. package/src/routes/orchestrator-bootstrap.ts +2 -2
  455. package/src/routes/orchestrator-host-registration.ts +4 -2
  456. package/src/routes/orchestrator-host-utilization.ts +5 -3
  457. package/src/routes/orchestrator-proxy.ts +4 -4
  458. package/src/routes/orchestrator.ts +28 -19
  459. package/src/routes/pairs.ts +8 -8
  460. package/src/routes/project-profile-instructions.ts +27 -0
  461. package/src/routes/project-trust.ts +3 -3
  462. package/src/routes/projects.ts +16 -16
  463. package/src/routes/prompt-templates.ts +12 -12
  464. package/src/routes/provider-config.ts +6 -6
  465. package/src/routes/provider-quota-config.ts +2 -2
  466. package/src/routes/provider-quotas.ts +10 -10
  467. package/src/routes/run-command.ts +1 -1
  468. package/src/routes/secrets-backup.ts +2 -2
  469. package/src/routes/secrets-import.ts +1 -1
  470. package/src/routes/secrets-vault.ts +7 -7
  471. package/src/routes/settings.ts +6 -6
  472. package/src/routes/shipping.ts +9 -1
  473. package/src/routes/spawn-policy.ts +8 -7
  474. package/src/routes/sse.ts +2 -2
  475. package/src/routes/stats.ts +6 -6
  476. package/src/routes/task-http.ts +15 -1
  477. package/src/routes/task-issues.ts +11 -26
  478. package/src/routes/tasks.ts +22 -53
  479. package/src/routes/team-templates.ts +12 -12
  480. package/src/routes/teams-config.ts +2 -2
  481. package/src/routes/teams.ts +10 -10
  482. package/src/routes/tokens.ts +30 -22
  483. package/src/routes/users.ts +24 -24
  484. package/src/routes/viewer-read.ts +3 -3
  485. package/src/routes/web-tool-calls.ts +4 -4
  486. package/src/routes/workflows.ts +22 -7
  487. package/src/routes/workspaces.ts +17 -16
  488. package/src/routing-policy-normalize.ts +1 -2
  489. package/src/routing-policy-push.ts +6 -6
  490. package/src/routing-step-defaults.ts +0 -2
  491. package/src/runner-token-mint-limit.ts +63 -0
  492. package/src/runtime-grant.ts +21 -13
  493. package/src/runtime-tokens.ts +59 -35
  494. package/src/secrets-broker/config.ts +1 -1
  495. package/src/secrets-broker/service.ts +2 -2
  496. package/src/security.ts +16 -21
  497. package/src/self-resume-carry.ts +21 -110
  498. package/src/self-resume-supersede.ts +4 -3
  499. package/src/self-resume.ts +54 -66
  500. package/src/server-background.ts +2 -2
  501. package/src/server.ts +26 -24
  502. package/src/services/agent-action.ts +12 -31
  503. package/src/services/agent-effort.ts +7 -32
  504. package/src/services/agent-hang-watchdog-job.ts +2 -2
  505. package/src/services/agent-heartbeat.ts +166 -0
  506. package/src/services/agent-reporting.ts +1 -1
  507. package/src/services/browser-inventory.ts +3 -3
  508. package/src/services/browser-session-state.ts +3 -2
  509. package/src/services/browser-session.ts +21 -27
  510. package/src/services/bus-command-update.ts +9 -9
  511. package/src/services/checkout-refresh-state.ts +1 -0
  512. package/src/services/checkout-refresh.test-fixture.ts +3 -2
  513. package/src/services/command-host.ts +7 -2
  514. package/src/services/coordinator-digest.ts +3 -2
  515. package/src/services/dispatch-command.ts +12 -13
  516. package/src/services/effective-launch-driver.ts +14 -9
  517. package/src/services/host-changed-paths.test-fixture.ts +5 -6
  518. package/src/services/host-project-readiness.ts +2 -2
  519. package/src/services/host-providers.ts +1 -1
  520. package/src/services/host-utilization.ts +27 -4
  521. package/src/services/idle-agent-digest.ts +17 -12
  522. package/src/services/idle-epics.ts +9 -10
  523. package/src/services/interrupt-agent.ts +12 -9
  524. package/src/services/issue-activity.ts +3 -3
  525. package/src/services/issue-associations.ts +15 -18
  526. package/src/services/issue-lifecycle-comments.ts +3 -2
  527. package/src/services/issue-lifecycle.ts +69 -72
  528. package/src/services/issue-refs.ts +10 -15
  529. package/src/services/kernel-timers-cutover-chaos-worker.ts +11 -8
  530. package/src/services/kernel-timers-ingress-chaos-worker.ts +6 -1
  531. package/src/services/kernel-timers-ingress.ts +4 -4
  532. package/src/services/kernel-timers-message-authority-chaos-worker.ts +3 -10
  533. package/src/services/kernel-timers-operator-chaos-worker.ts +3 -2
  534. package/src/services/kernel-timers-outbox.ts +1 -1
  535. package/src/services/kernel-timers-stage10-operator.ts +1 -1
  536. package/src/services/kernel-timers.ts +4 -3
  537. package/src/services/land-gate-placement.ts +11 -2
  538. package/src/services/land-issue-relations.ts +5 -4
  539. package/src/services/land-restart-retry.ts +7 -6
  540. package/src/services/landed-ancestry.ts +25 -8
  541. package/src/services/legacy-landing-host.ts +4 -1
  542. package/src/services/legacy-landing-recovery.ts +8 -6
  543. package/src/services/managed-running.ts +17 -17
  544. package/src/services/memory-areas.ts +17 -53
  545. package/src/services/merge-pause.ts +9 -15
  546. package/src/services/operator-decisions.ts +37 -41
  547. package/src/services/orchestrator-registration-recovery.ts +6 -2
  548. package/src/services/orchestrator-upgrade.ts +14 -12
  549. package/src/services/permission-decision.ts +4 -3
  550. package/src/services/plan-ci-notice.ts +57 -0
  551. package/src/services/plan-ci-recovery.ts +2 -55
  552. package/src/services/plan-conformance.ts +4 -4
  553. package/src/services/plan-dispatch-policy.ts +10 -3
  554. package/src/services/plan-dispatch.ts +35 -14
  555. package/src/services/plan-graph.ts +39 -261
  556. package/src/services/plan-import.ts +1 -1
  557. package/src/services/plan-live-bindings.ts +8 -37
  558. package/src/services/plan-task-create.ts +1 -1
  559. package/src/services/plan-terminal-refs.ts +2 -12
  560. package/src/services/plan-wake-digest.ts +9 -3
  561. package/src/services/profile-trust.ts +6 -5
  562. package/src/services/project-config-read.ts +70 -0
  563. package/src/services/project-profile-instructions.ts +54 -0
  564. package/src/services/project.ts +11 -10
  565. package/src/services/prompt-templates.ts +6 -5
  566. package/src/services/provider-hold-nudge.ts +9 -9
  567. package/src/services/provider-hold-record.ts +13 -12
  568. package/src/services/provider-state-audit.ts +19 -18
  569. package/src/services/provisioning-harness/budget-baseline.json +4 -4
  570. package/src/services/provisioning-harness/driver.ts +1 -1
  571. package/src/services/provisioning-harness/fixture-matrix.ts +3 -3
  572. package/src/services/provisioning-harness/lifecycle.ts +24 -22
  573. package/src/services/provisioning-harness/prepare.ts +16 -17
  574. package/src/services/rate-limit-resume.ts +10 -9
  575. package/src/services/red-main-auto-revert.ts +7 -5
  576. package/src/services/red-main-controller-deps.ts +20 -3
  577. package/src/services/red-main-incident.ts +3 -1
  578. package/src/services/red-main-quarantine.ts +2 -3
  579. package/src/services/register-agent.ts +22 -22
  580. package/src/services/restart-project-role.ts +1 -1
  581. package/src/services/restart-spawn.ts +74 -61
  582. package/src/services/review-publish.ts +7 -24
  583. package/src/services/review-ref-reconcile.ts +29 -38
  584. package/src/services/runtime-dependency-alert.ts +27 -0
  585. package/src/services/scheduler-command.ts +11 -9
  586. package/src/services/scheduler.ts +5 -5
  587. package/src/services/self-care-state.ts +2 -1
  588. package/src/services/self-effort-grant.ts +5 -25
  589. package/src/services/self-effort.ts +5 -5
  590. package/src/services/send-message.ts +21 -34
  591. package/src/services/shutdown-agent.ts +17 -14
  592. package/src/services/spawn-agent.ts +25 -43
  593. package/src/services/spawn-chain-inspector.ts +7 -14
  594. package/src/services/spawn-cwd-placement.ts +21 -5
  595. package/src/services/spawn-issue-activity.ts +8 -6
  596. package/src/services/spawn-launch.ts +17 -1
  597. package/src/services/spawn-loss-escalation.ts +1 -1
  598. package/src/services/spawn-policy.ts +68 -0
  599. package/src/services/spawn-registration-watchdog.ts +2 -2
  600. package/src/services/spawn-repo-probe.ts +7 -5
  601. package/src/services/spawn-tree-cleanup.ts +8 -9
  602. package/src/services/steward-reaper.ts +4 -4
  603. package/src/services/task-context-hydration.ts +25 -1
  604. package/src/services/task-delivery.ts +20 -34
  605. package/src/services/task-dispatch.ts +3 -0
  606. package/src/services/task-entity.ts +40 -203
  607. package/src/services/task-issue-link.ts +13 -20
  608. package/src/services/task-issue-weave.ts +12 -11
  609. package/src/services/task-lifecycle.ts +27 -31
  610. package/src/services/task-repo-cwd.ts +37 -0
  611. package/src/services/task-review-hold.ts +4 -17
  612. package/src/services/task-semantic-events.ts +13 -11
  613. package/src/services/task-state-reconcile.ts +8 -17
  614. package/src/services/task-validation.ts +2 -2
  615. package/src/services/team-templates.ts +12 -11
  616. package/src/services/team.ts +31 -98
  617. package/src/services/terminal-provider-exit.ts +6 -5
  618. package/src/services/timer-message-fire-chaos-worker.ts +7 -3
  619. package/src/services/timer-message-fire-outbox.ts +1 -1
  620. package/src/services/transient-agent-reaper.ts +25 -20
  621. package/src/services/turn-reconcile-audit.ts +9 -9
  622. package/src/services/user-onboarding.ts +8 -6
  623. package/src/services/user-profile.ts +6 -9
  624. package/src/services/work-finality.ts +16 -4
  625. package/src/services/workflow-auto-start.ts +26 -13
  626. package/src/services/workflow-caller.ts +61 -4
  627. package/src/services/workflow-child-proof-worker.ts +1 -1
  628. package/src/services/workflow-ci-main.ts +1 -1
  629. package/src/services/workflow-control-proof-worker.ts +1 -1
  630. package/src/services/workflow-coordinator.ts +8 -2
  631. package/src/services/workflow-decisions.ts +5 -5
  632. package/src/services/workflow-deferred-cleanup.ts +5 -3
  633. package/src/services/workflow-effect-driver.ts +42 -17
  634. package/src/services/workflow-effects.ts +58 -37
  635. package/src/services/workflow-land-notice.ts +10 -0
  636. package/src/services/workflow-pause-text.ts +43 -0
  637. package/src/services/workflow-pins.ts +7 -4
  638. package/src/services/workflow-reconcile.ts +14 -11
  639. package/src/services/workflow-resume-pins.ts +3 -3
  640. package/src/services/workflow-routing-defaults.ts +18 -0
  641. package/src/services/workflow-run-view.ts +6 -3
  642. package/src/services/workflow-run.test-fixture.ts +1 -1
  643. package/src/services/workflow-runs.ts +61 -33
  644. package/src/services/workflow-supervisor-state.ts +26 -1
  645. package/src/services/workflow-supervisor.ts +11 -6
  646. package/src/services/workspace-recovery.ts +4 -3
  647. package/src/settings/registry.ts +1 -2
  648. package/src/spawn-admission.ts +10 -2
  649. package/src/spawn-command.ts +4 -4
  650. package/src/spawn-models.ts +10 -12
  651. package/src/spawn-placement.ts +28 -10
  652. package/src/spawn-targets.ts +9 -9
  653. package/src/sse-agent-status.ts +15 -6
  654. package/src/sse.ts +49 -24
  655. package/src/startup-context-injection.ts +62 -57
  656. package/src/state-adoption/cd-cutover.ts +53 -7
  657. package/src/state-adoption/fleet-cutover.ts +35 -0
  658. package/src/state-adoption/fleet-plan.ts +36 -0
  659. package/src/state-adoption/index.ts +2 -2
  660. package/src/state-adoption/linux-plan.ts +2 -2
  661. package/src/state-adoption/linux.ts +2 -2
  662. package/src/state-adoption/macos-plan.ts +2 -2
  663. package/src/state-adoption/macos.ts +1 -1
  664. package/src/steward-handoff.ts +4 -3
  665. package/src/steward-policy-cleanup.ts +9 -8
  666. package/src/steward.ts +9 -8
  667. package/src/task-dispatch-live.ts +6 -3
  668. package/src/task-dispatcher.ts +3 -3
  669. package/src/teams-config-store.ts +4 -3
  670. package/src/token-db-write.ts +10 -0
  671. package/src/token-db.ts +2 -2
  672. package/src/token-usage-async.ts +2 -4
  673. package/src/user-awaiting-reply.ts +5 -5
  674. package/src/workspace-actions.ts +24 -29
  675. package/src/workspace-auto-merge.ts +14 -12
  676. package/src/workspace-changed-paths-client.ts +16 -5
  677. package/src/workspace-cleanup-stale.ts +30 -7
  678. package/src/workspace-command-settle.ts +26 -17
  679. package/src/workspace-config.ts +1 -1
  680. package/src/workspace-conflict-resolver.ts +9 -7
  681. package/src/workspace-dead-owner-recovery.ts +5 -4
  682. package/src/workspace-escalation.ts +12 -11
  683. package/src/workspace-human-escalation.ts +3 -3
  684. package/src/workspace-land-gate-watchdog.ts +3 -3
  685. package/src/workspace-land-refusal.ts +20 -0
  686. package/src/workspace-land-stopped.ts +1 -0
  687. package/src/workspace-merge.ts +10 -26
  688. package/src/workspace-nothing-to-land-notice.ts +2 -2
  689. package/src/workspace-orphans.ts +18 -37
  690. package/src/workspace-pr-completion.ts +10 -8
  691. package/src/workspace-rekey.ts +3 -3
  692. package/src/workspace-steward-failure.ts +2 -2
  693. package/src/workspace-steward-wake.ts +4 -4
  694. package/node_modules/@humwick/kernel/LICENSE +0 -167
  695. package/node_modules/@humwick/kernel/async-entity-persistence.ts +0 -344
  696. package/node_modules/@humwick/kernel/async-event-log.ts +0 -107
  697. package/node_modules/@humwick/kernel/automations.pilot.ts +0 -147
  698. package/node_modules/@humwick/kernel/config.ts +0 -111
  699. package/node_modules/@humwick/kernel/contract.ts +0 -572
  700. package/node_modules/@humwick/kernel/control-authz.ts +0 -281
  701. package/node_modules/@humwick/kernel/control.ts +0 -645
  702. package/node_modules/@humwick/kernel/effects.ts +0 -493
  703. package/node_modules/@humwick/kernel/event-log.ts +0 -319
  704. package/node_modules/@humwick/kernel/http-transport.ts +0 -384
  705. package/node_modules/@humwick/kernel/identity-grammar.ts +0 -20
  706. package/node_modules/@humwick/kernel/identity.ts +0 -248
  707. package/node_modules/@humwick/kernel/index.ts +0 -28
  708. package/node_modules/@humwick/kernel/kernel-persistence.ts +0 -181
  709. package/node_modules/@humwick/kernel/landing-incident.ts +0 -306
  710. package/node_modules/@humwick/kernel/landing.ts +0 -953
  711. package/node_modules/@humwick/kernel/manifest-validation.ts +0 -460
  712. package/node_modules/@humwick/kernel/mcp-transport.ts +0 -109
  713. package/node_modules/@humwick/kernel/message-authority-chaos-worker.ts +0 -200
  714. package/node_modules/@humwick/kernel/message-authority.ts +0 -281
  715. package/node_modules/@humwick/kernel/module-host.ts +0 -722
  716. package/node_modules/@humwick/kernel/openapi-init.ts +0 -14
  717. package/node_modules/@humwick/kernel/package.json +0 -39
  718. package/node_modules/@humwick/kernel/persistence-schema.ts +0 -248
  719. package/node_modules/@humwick/kernel/persistence.ts +0 -510
  720. package/node_modules/@humwick/kernel/registry.ts +0 -60
  721. package/node_modules/@humwick/kernel/sqlite-kernel-persistence.ts +0 -499
  722. package/node_modules/@humwick/kernel/sqlite-module-host.ts +0 -87
  723. package/node_modules/@humwick/kernel/timers-chaos-worker.ts +0 -186
  724. package/node_modules/@humwick/kernel/timers.pilot.ts +0 -1411
  725. package/node_modules/@humwick/kernel/workflow-activation.ts +0 -25
  726. package/node_modules/@humwick/kernel/workflow-backstop.ts +0 -40
  727. package/node_modules/@humwick/kernel/workflow-cancel-tree.ts +0 -20
  728. package/node_modules/@humwick/kernel/workflow-chaos-worker.ts +0 -213
  729. package/node_modules/@humwick/kernel/workflow-composition.ts +0 -231
  730. package/node_modules/@humwick/kernel/workflow-container.ts +0 -72
  731. package/node_modules/@humwick/kernel/workflow-control.test-fixture.ts +0 -42
  732. package/node_modules/@humwick/kernel/workflow-control.ts +0 -178
  733. package/node_modules/@humwick/kernel/workflow-definition.ts +0 -507
  734. package/node_modules/@humwick/kernel/workflow-dispatch.ts +0 -60
  735. package/node_modules/@humwick/kernel/workflow-foreach.ts +0 -167
  736. package/node_modules/@humwick/kernel/workflow-journal-codec.ts +0 -339
  737. package/node_modules/@humwick/kernel/workflow-journal.ts +0 -922
  738. package/node_modules/@humwick/kernel/workflow-lane.ts +0 -48
  739. package/node_modules/@humwick/kernel/workflow-lease-owner.ts +0 -60
  740. package/node_modules/@humwick/kernel/workflow-recovery.test-fixture.ts +0 -19
  741. package/node_modules/@humwick/kernel/workflow-runtime.ts +0 -938
  742. package/node_modules/@humwick/kernel/workflow-script.ts +0 -11
  743. package/node_modules/@humwick/kernel/workflow-state.ts +0 -299
  744. package/node_modules/@humwick/kernel/workflow-step-commit.ts +0 -195
  745. package/node_modules/@humwick/kernel/workflow-transitions.ts +0 -317
  746. package/node_modules/@humwick/kernel/workflow-values.ts +0 -153
  747. package/node_modules/@humwick/kernel/workflow.pilot.ts +0 -376
  748. package/node_modules/@humwick/offload/LICENSE +0 -167
  749. package/node_modules/@humwick/offload/README.md +0 -57
  750. package/node_modules/@humwick/offload/dist/async-runner.d.ts +0 -18
  751. package/node_modules/@humwick/offload/dist/async-runner.d.ts.map +0 -1
  752. package/node_modules/@humwick/offload/dist/async-runner.js +0 -158
  753. package/node_modules/@humwick/offload/dist/async-runner.js.map +0 -1
  754. package/node_modules/@humwick/offload/dist/envelope.d.ts +0 -25
  755. package/node_modules/@humwick/offload/dist/envelope.d.ts.map +0 -1
  756. package/node_modules/@humwick/offload/dist/envelope.js +0 -80
  757. package/node_modules/@humwick/offload/dist/envelope.js.map +0 -1
  758. package/node_modules/@humwick/offload/dist/fixtures/worker-task.d.ts +0 -10
  759. package/node_modules/@humwick/offload/dist/fixtures/worker-task.d.ts.map +0 -1
  760. package/node_modules/@humwick/offload/dist/fixtures/worker-task.js +0 -59
  761. package/node_modules/@humwick/offload/dist/fixtures/worker-task.js.map +0 -1
  762. package/node_modules/@humwick/offload/dist/index.d.ts +0 -5
  763. package/node_modules/@humwick/offload/dist/index.d.ts.map +0 -1
  764. package/node_modules/@humwick/offload/dist/index.js +0 -5
  765. package/node_modules/@humwick/offload/dist/index.js.map +0 -1
  766. package/node_modules/@humwick/offload/dist/subprocess-runner.d.ts +0 -62
  767. package/node_modules/@humwick/offload/dist/subprocess-runner.d.ts.map +0 -1
  768. package/node_modules/@humwick/offload/dist/subprocess-runner.js +0 -295
  769. package/node_modules/@humwick/offload/dist/subprocess-runner.js.map +0 -1
  770. package/node_modules/@humwick/offload/dist/types.d.ts +0 -111
  771. package/node_modules/@humwick/offload/dist/types.d.ts.map +0 -1
  772. package/node_modules/@humwick/offload/dist/types.js +0 -176
  773. package/node_modules/@humwick/offload/dist/types.js.map +0 -1
  774. package/node_modules/@humwick/offload/dist/worker-pool.d.ts +0 -23
  775. package/node_modules/@humwick/offload/dist/worker-pool.d.ts.map +0 -1
  776. package/node_modules/@humwick/offload/dist/worker-pool.js +0 -435
  777. package/node_modules/@humwick/offload/dist/worker-pool.js.map +0 -1
  778. package/node_modules/@humwick/offload/dist/worker-runtime.d.ts +0 -2
  779. package/node_modules/@humwick/offload/dist/worker-runtime.d.ts.map +0 -1
  780. package/node_modules/@humwick/offload/dist/worker-runtime.js +0 -27
  781. package/node_modules/@humwick/offload/dist/worker-runtime.js.map +0 -1
  782. package/node_modules/@humwick/offload/dist/worker.d.ts +0 -5
  783. package/node_modules/@humwick/offload/dist/worker.d.ts.map +0 -1
  784. package/node_modules/@humwick/offload/dist/worker.js +0 -1
  785. package/node_modules/@humwick/offload/dist/worker.js.map +0 -1
  786. package/node_modules/@humwick/offload/package.json +0 -42
  787. package/node_modules/@humwick/offload/src/async-runner.ts +0 -170
  788. package/node_modules/@humwick/offload/src/envelope.ts +0 -92
  789. package/node_modules/@humwick/offload/src/fixtures/worker-task.ts +0 -49
  790. package/node_modules/@humwick/offload/src/index.ts +0 -4
  791. package/node_modules/@humwick/offload/src/subprocess-runner.ts +0 -334
  792. package/node_modules/@humwick/offload/src/types.ts +0 -235
  793. package/node_modules/@humwick/offload/src/worker-pool.ts +0 -463
  794. package/node_modules/@humwick/offload/src/worker-runtime.ts +0 -32
  795. package/node_modules/@humwick/offload/src/worker.ts +0 -5
  796. package/public/assets/agent-liveness-DyqxfB-t.js +0 -2
  797. package/public/assets/agent-profiles-BpI_jTxq.js +0 -2
  798. package/public/assets/index-B7ZerHLY.css +0 -2
  799. package/public/assets/index-BU3uWo2t.js +0 -15
  800. package/public/assets/projects-B_lmcqfO.js +0 -2
  801. package/public/assets/provider-display-DbLWpP3j.js +0 -2
  802. package/public/assets/run-card-CO_bguQf.js +0 -2
  803. package/public/assets/shipping-Bu8p1gEw.js +0 -2
  804. package/public/assets/store-BvtFdlGX.js +0 -9
  805. package/public/assets/use-project-list-B-T2Bnnn.js +0 -2
  806. package/public/assets/versioned-prompt-editor-Diu8BIaM.js +0 -8
  807. package/runner/src/agent-runner/http-liveness.ts +0 -85
  808. package/runner/src/gate-run-lease-probe.ts +0 -38
  809. package/src/db/claude-catalog-reconcile.ts +0 -27
  810. package/src/db/on-loop-write-transaction.ts +0 -34
  811. package/src/routing-model-aliases.ts +0 -21
@@ -44,7 +44,7 @@ const USAGE = [
44
44
  " --db <path> target DB (default: $DB_PATH, else <stateDir>/agent-relay.db)",
45
45
  ].join("\n");
46
46
 
47
- function main(): void {
47
+ async function main(): Promise<void> {
48
48
  const args = parseCleanupArgs(process.argv.slice(2));
49
49
  if (args.help) {
50
50
  console.log(USAGE);
@@ -58,7 +58,7 @@ function main(): void {
58
58
  console.log(`[steward-policy-cleanup] db=${dbPath} mode=${dryRun ? "DRY RUN" : "APPLY"}`);
59
59
  console.log(`[steward-policy-cleanup] scanned ${plan.scanned} steward polic${plan.scanned === 1 ? "y" : "ies"}`);
60
60
 
61
- const result = applyStewardPolicyCleanup(plan, { dryRun });
61
+ const result = (await applyStewardPolicyCleanup(plan, { dryRun }));
62
62
  for (const line of result.log) console.log(` ${line}`);
63
63
  if (result.log.length === 0) console.log(" (nothing to change — already canonical)");
64
64
 
@@ -189,9 +189,9 @@ export function sessionControlsOwnAgentsOnly(ctx: AuthContext): boolean {
189
189
  * operator on agents they are principal of, viewer never. Agent: coordinator authority and, with
190
190
  * several users, the target's principal (or an admin principal). Full-reach callers: always.
191
191
  * Single-user installs keep today's behavior: only the agent coordinator rule applies. */
192
- export function authorizeAgentControl(ctx: AuthContext, target: Pick<AgentCard, "id" | "spawnedBy" | "teamId">, action = "control"): AgentControlDenial | null {
192
+ export async function authorizeAgentControl(ctx: AuthContext, target: Pick<AgentCard, "id" | "spawnedBy" | "teamId">, action = "control"): Promise<AgentControlDenial | null> {
193
193
  const denied = agentControlDecision(ctx, target);
194
- if (denied) recordAuthorityDenial(ctx, target.id, action, denied.reason);
194
+ if (denied) (await recordAuthorityDenial(ctx, target.id, action, denied.reason));
195
195
  return denied;
196
196
  }
197
197
 
@@ -1,3 +1,4 @@
1
+ import { releaseDriveLeaseAsync } from "./db/runtime-tail-async";
1
2
  // Concurrency arbitration — "two humans driving one agent safely" (#388 users wave 5, #394).
2
3
  //
3
4
  // THE single decision home for "may this user drive this agent right now?". It composes three
@@ -18,13 +19,7 @@ import { canonicalHumanAgentId, userSinkId } from "@humwick/sdk";
18
19
  import { isMultiUserWorldAsync } from "./db/agent-ownership-async.ts";
19
20
  import { resolveViewer } from "./agent-authz.ts";
20
21
  import { getUser } from "./db/users.ts";
21
- import {
22
- acquireDriveLease,
23
- getDriveLease,
24
- releaseDriveLease,
25
- takeOverDriveLease,
26
- type DriveLeaseRecord,
27
- } from "./db/drive-leases.ts";
22
+ import { acquireDriveLease, getDriveLease, takeOverDriveLease, type DriveLeaseRecord } from "./db/drive-leases.ts";
28
23
 
29
24
  /** Who holds (or held) the wheel, resolved for human-readable "X is driving" messaging. */
30
25
  interface DriveHolder {
@@ -100,7 +95,7 @@ export async function releaseDrive(userId: string, agentId: string, opts: { forc
100
95
  if (!(await isMultiUserWorldAsync())) return { released: false };
101
96
  const current = getDriveLease(agentId);
102
97
  const isAdmin = resolveViewer(userId)?.role === "admin";
103
- const released = releaseDriveLease(opts.force && isAdmin ? { agentId } : { agentId, userId });
98
+ const released = (await releaseDriveLeaseAsync(opts.force && isAdmin ? { agentId } : { agentId, userId }));
104
99
  return released && current ? { released, previousHolder: driveHolder(current.holderUserId) } : { released };
105
100
  }
106
101
 
@@ -51,11 +51,11 @@ export async function settleAgentExitCleanupAsync(command: Command): Promise<boo
51
51
  const settled = await getGateway().write("commands.settleAgentCleanupSlice", { command: { ...command,
52
52
  result: { owners: [{ ...owner, workspaceIds: ids.slice(at, at + 8) }] } } }) as unknown as AgentCleanupSettlement;
53
53
  for (const workspace of settled.changed) emitWorkspaceChange(workspace);
54
- for (const alert of settled.alerts) alertCleanup(command, alert.agentId, alert.detail, owner);
54
+ for (const alert of settled.alerts) await alertCleanup(command, alert.agentId, alert.detail, owner);
55
55
  await Bun.sleep(5);
56
56
  }
57
57
  if (typeof owner.agentId === "string" && typeof owner.error === "string") {
58
- alertCleanup(command, owner.agentId, owner.error, owner);
58
+ await alertCleanup(command, owner.agentId, owner.error, owner);
59
59
  await Bun.sleep(5);
60
60
  }
61
61
  }
@@ -1,10 +1,14 @@
1
+ import { deleteWorkspaceAsync } from "./db/lifecycle-tail-async";
2
+ import { getGateway } from "./db/gateway";
3
+ import type { AgentCleanupSettlement } from "./db/agent-exit-cleanup";
4
+ import { createCommandAsync } from "./commands-write";
1
5
  import { subscribeRelayEvents } from "./events";
2
6
  import { createHash } from "node:crypto";
3
7
  import { isHumanAgentId, isRecord } from "@humwick/sdk";
4
- import { createCommand } from "./commands-db";
5
- import { hasActiveAgentCleanup, settleAgentCleanupWorkspaces } from "./db/agent-exit-cleanup";
8
+
9
+ import { hasActiveAgentCleanup } from "./db/agent-exit-cleanup";
6
10
  import { emitCommandEvent } from "./command-events";
7
- import { deleteWorkspace, emitWorkspaceChange, getAgent, listOrchestrators, listWorkspaces, getWorkspace } from "./db";
11
+ import { emitWorkspaceChange, getAgent, listOrchestrators, listWorkspaces, getWorkspace } from "./db";
8
12
  import { workspaceOwnerOrchestrator } from "./workspace-host";
9
13
  import { raiseOperatorAlarm } from "./operator-alarm";
10
14
  import { routeNotification } from "./notification-router";
@@ -14,17 +18,17 @@ import { exitCleanupCondition } from "./agent-exit-alarm";
14
18
  import { reapAgentBrowserSessions } from "./services/browser-session";
15
19
 
16
20
  // #3489 — HTTP, bus self-exit, host reports and reapers share the persisted status event.
17
- subscribeRelayEvents((event) => {
18
- if (event.type === "agent.status" && event.data.status === "offline" && event.subject) reapAgentBrowserSessions(event.subject);
21
+ subscribeRelayEvents(async (event) => {
22
+ if (event.type === "agent.status" && event.data.status === "offline" && event.subject) (await reapAgentBrowserSessions(event.subject));
19
23
  });
20
24
 
21
- export function requestAgentExitCleanup(agentId?: string): number {
25
+ export async function requestAgentExitCleanup(agentId?: string): Promise<number> {
22
26
  if (agentId === "system" || isHumanAgentId(agentId)) return 0;
23
27
  const agent = agentId ? getAgent(agentId) : null;
24
28
  if (agent && agent.status !== "offline") return 0;
25
- if (agentId) reapAgentBrowserSessions(agentId); // #3489 — a browser never outlives its agent
29
+ if (agentId) (await reapAgentBrowserSessions(agentId)); // #3489 — a browser never outlives its agent
26
30
  if (agentId) for (const ws of listWorkspaces({ ownerAgentId: agentId })) {
27
- if (ws.mode === "shared") deleteWorkspace(ws.id);
31
+ if (ws.mode === "shared") (await deleteWorkspaceAsync(ws.id));
28
32
  }
29
33
  const hosts = listOrchestrators().filter((host) => host.status === "online");
30
34
  const owned = agentId ? listWorkspaces({ ownerAgentId: agentId }) : [];
@@ -34,8 +38,8 @@ export function requestAgentExitCleanup(agentId?: string): number {
34
38
  for (const host of hosts) {
35
39
  if (agentId && hostIds.size && !hostIds.has(host.id)) continue;
36
40
  if (hasActiveAgentCleanup(host.agentId, agentId)) continue;
37
- const command = createCommand({ type: "agent.cleanup", source: "system", target: host.agentId, ttlMs: 10 * 60_000,
38
- params: { ...(agentId ? { agentId } : { sweep: true }), requestedBy: "agent-exit-cleanup" } });
41
+ const command = (await createCommandAsync({ type: "agent.cleanup", source: "system", target: host.agentId, ttlMs: 10 * 60_000,
42
+ params: { ...(agentId ? { agentId } : { sweep: true }), requestedBy: "agent-exit-cleanup" } }));
39
43
  emitCommandEvent(command, "command.requested");
40
44
  dispatched++;
41
45
  }
@@ -53,25 +57,25 @@ export async function settleAgentExitCleanup(command: Command): Promise<boolean>
53
57
  const error = command.error ?? "No cleanup inventory owner found; cleanup retained";
54
58
  await settleWorkspaceCleanupCommand({ ...command, status: "failed", error,
55
59
  result: { ...result, workspaceId: typeof command.params.workspaceId === "string" ? command.params.workspaceId : command.correlationId } });
56
- if (command.status === "succeeded") alertCleanup(command, undefined, error);
60
+ if (command.status === "succeeded") await alertCleanup(command, undefined, error);
57
61
  }
58
- const settled = settleAgentCleanupWorkspaces(command);
62
+ const settled = await getGateway().write("commands.settleAgentCleanupSlice", { command }) as unknown as AgentCleanupSettlement;
59
63
  for (const workspace of settled.changed) emitWorkspaceChange(workspace);
60
- for (const alert of settled.alerts) alertCleanup(command, alert.agentId, alert.detail);
64
+ for (const alert of settled.alerts) await alertCleanup(command, alert.agentId, alert.detail);
61
65
  for (const owner of owners) {
62
66
  if (typeof owner.agentId !== "string") continue;
63
- if (typeof owner.error === "string") alertCleanup(command, owner.agentId, owner.error, owner);
67
+ if (typeof owner.error === "string") await alertCleanup(command, owner.agentId, owner.error, owner);
64
68
  }
65
69
  if (command.status !== "succeeded" && !owners.some((owner) => typeof owner.error === "string")) {
66
70
  console.warn(`[agent-exit-cleanup] host ${command.target} agent ${command.params.agentId ?? "host sweep"}: ${command.error ?? "host cleanup failed"}`);
67
71
  }
68
72
  if (Array.isArray(result?.unattributed) && result.unattributed.length) {
69
- alertCleanup(command, undefined, `Host artifacts retained because ownership is unavailable: ${result.unattributed.join(", ")}`, { artifactPaths: result.unattributed });
73
+ await alertCleanup(command, undefined, `Host artifacts retained because ownership is unavailable: ${result.unattributed.join(", ")}`, { artifactPaths: result.unattributed });
70
74
  }
71
75
  return true;
72
76
  }
73
77
 
74
- export function alertCleanup(command: Command, agentId: string | undefined, detail: string, artifacts?: Record<string, unknown>): void {
78
+ export async function alertCleanup(command: Command, agentId: string | undefined, detail: string, artifacts?: Record<string, unknown>): Promise<void> {
75
79
  const owner = artifacts ?? (Array.isArray(command.result?.owners) ? command.result.owners.filter(isRecord)
76
80
  .find((owner) => owner.agentId === agentId) : undefined);
77
81
  if (owner?.inventoryFailed === true) return;
@@ -91,9 +95,9 @@ export function alertCleanup(command: Command, agentId: string | undefined, deta
91
95
  const host = listOrchestrators().find((host) => host.agentId === command.target);
92
96
  const body = `Agent ${agent?.label ?? agent?.name ?? "unknown"} (${identity ?? "unknown"}) on host ${host ? `${host.hostname} (${host.id})` : command.target}\nPaths: ${paths.join(", ")}\n${detail}`;
93
97
  const digest = createHash("sha256").update(`${command.target}:${identity}:${exitCleanupCondition(detail)}:${JSON.stringify(paths)}`).digest("hex").slice(0, 24);
94
- if (!raiseOperatorAlarm({ clientId: `exit-cleanup:${digest}`, source: "agent-exit-cleanup", subject: "Agent exit cleanup retained files", detail: body, dedupeEvent: true,
95
- metadata: { agentId, commandId: command.id, orchestrator: command.target, paths } })) return;
98
+ if (!(await raiseOperatorAlarm({ clientId: `exit-cleanup:${digest}`, source: "agent-exit-cleanup", subject: "Agent exit cleanup retained files", detail: body, dedupeEvent: true,
99
+ metadata: { agentId, commandId: command.id, orchestrator: command.target, paths } }))) return;
96
100
  const parent = agent?.spawnedBy;
97
- if (parent) routeNotification({ type: "agent.cleanup_failed", scope: { agentId, parent }, recipients: [parent], forceDelivery: true,
101
+ if (parent) await routeNotification({ type: "agent.cleanup_failed", scope: { agentId, parent }, recipients: [parent], forceDelivery: true,
98
102
  message: { subject: "Agent exit cleanup retained files", body, replyExpected: false, idempotencyKey: `exit-cleanup:${digest}`, payload: { kind: "agent.cleanup_failed", agentId, commandId: command.id } } });
99
103
  }
@@ -1,9 +1,10 @@
1
- import { clearAgentNotice, hasAgentExitNotice, recordAgentNoticeOnce, recordAgentReadyNoticeOnce } from "./db/terminal-events";
1
+ import { clearAgentNoticeAsync, recordCrashReportAsync, recordTerminalEventAsync } from "./db/lifecycle-tail-async";
2
+ import { hasAgentExitNotice } from "./db/terminal-events";
2
3
  import { requestAgentExitCleanup } from "./agent-exit-cleanup";
3
4
  import { emitRelayEvent } from "./events";
4
- import { routeNotification } from "./notification-router";
5
+ import { routeAgentNotice, routeNotification } from "./notification-router";
5
6
  import { LIFECYCLE_STATE_WORKING, childSignalKey, stampLifecycleSignal, taskSignalKey } from "./lifecycle-signal-registry";
6
- import { currentCoordinatorOf, deliverableTaskIdsBySpawnRequestId, getAgent, markAgentReadyNotified, recordCrashReport, recordTerminalEvent, workflowRunIdOf } from "./db";
7
+ import { currentCoordinatorOf, deliverableTaskIdsBySpawnRequestId, getAgent, markAgentReadyNotifiedAsync, workflowRunIdOf } from "./db";
7
8
  import { crashReportFor } from "./agent-death-diagnosis";
8
9
  import { renderTemplate } from "./prompt-resolver";
9
10
  import { markAgentWorkFinal } from "./services/work-finality";
@@ -57,6 +58,19 @@ function diagnosisSuffix(diagnosis?: AgentDeathDiagnosis): string {
57
58
  // it guards is same-moment, so a relay restart between the two is not a concern.
58
59
  type SpawnTerminal = "agent.ready" | "agent.spawn_failed";
59
60
  const spawnTerminalBySpawnRequest = new Map<string, SpawnTerminal>();
61
+ const pendingSpawnNotices = new Map<string, Promise<void>>();
62
+ function spawnQueueKey(agentId: string): string {
63
+ const child = getAgent(agentId);
64
+ return (child && spawnRequestIdOf(child)) || agentId;
65
+ }
66
+ // #1870 — terminal guards advance only after commit; serialize one generation across writer awaits.
67
+ function serializeSpawnNotice(key: string, work: () => Promise<void>): Promise<void> {
68
+ const prior = pendingSpawnNotices.get(key);
69
+ const result = prior ? prior.catch(() => {}).then(work) : work();
70
+ pendingSpawnNotices.set(key, result);
71
+ void result.finally(() => { if (pendingSpawnNotices.get(key) === result) pendingSpawnNotices.delete(key); }).catch(() => {});
72
+ return result;
73
+ }
60
74
 
61
75
  // #1513 — spawns we've already told the spawner are queued-for-host-memory, keyed by spawnRequestId
62
76
  // (falling back to the parent id when a request has no id). The orchestrator re-reports the whole
@@ -76,13 +90,6 @@ function recordSpawnTerminal(spawnRequestId: string | undefined, outcome: SpawnT
76
90
  spawnTerminalBySpawnRequest.set(spawnRequestId, outcome);
77
91
  }
78
92
 
79
- function tryRecordSpawnFailed(spawnRequestId: string | undefined): boolean {
80
- if (spawnRequestId === undefined) return true;
81
- if (spawnTerminalBySpawnRequest.has(spawnRequestId)) return false;
82
- spawnTerminalBySpawnRequest.set(spawnRequestId, "agent.spawn_failed");
83
- return true;
84
- }
85
-
86
93
  /** A child counts as "had become ready" once its durable readiness stamp exists. */
87
94
  function everReady(child: AgentCard): boolean {
88
95
  return typeof child.meta?.readyNotifiedAt === "number";
@@ -128,50 +135,49 @@ function stampChildLifecycleSignal(parent: string, child: AgentCard): void {
128
135
  * `spawned_by` parent a one-shot notice so it can stop block-polling. No-op for non-spawned agents
129
136
  * and for a child whose ready was already announced (reconnect / heartbeat re-registration).
130
137
  */
131
- export function notifyAgentReady(childId: string): void {
138
+ export async function notifyAgentReady(childId: string): Promise<void> {
139
+ return serializeSpawnNotice(spawnQueueKey(childId), () => notifyAgentReadyBody(childId));
140
+ }
141
+
142
+ async function notifyAgentReadyBody(childId: string): Promise<void> {
132
143
  const child = getAgent(childId);
133
144
  const parent = child?.spawnedBy;
134
145
  // A workflow step agent with no spawner (a run a dashboard user started) still records its ready edge on its run (#3160).
135
146
  if (!child || (!parent && !workflowRunIdOf(child))) return;
136
147
  if (isSpawnIntentCanceled(child.meta?.spawnRequestId)) return;
137
148
  // Idempotent — only stamped on first ready; classifies a later offline edge as exited.
138
- markAgentReadyNotified(childId);
149
+ await markAgentReadyNotifiedAsync(childId);
139
150
  // #2899 — a self-compact flips ready again; the generation slot keeps the push one-shot.
140
- recordAgentReadyNoticeOnce(child, () => announceReady(child, parent));
151
+ await announceReady(child, parent);
141
152
  }
142
153
 
143
- function announceReady(child: AgentCard, spawner: string | undefined): void {
154
+ async function announceReady(child: AgentCard, spawner: string | undefined): Promise<void> {
144
155
  const childId = child.id;
145
156
  const spawnRequestId = spawnRequestIdOf(child);
146
157
  // #648 — if a spawn_failed was already emitted for this request, this ready RETRACTS it: the agent
147
158
  // actually came up, so the earlier failure was a false negative. Emit a corrective recovery instead
148
159
  // of a plain ready notice so a coordinator that acted on the failure can reconcile.
149
160
  const recovered = spawnTerminalOf(spawnRequestId) === "agent.spawn_failed";
150
- recordSpawnTerminal(spawnRequestId, "agent.ready");
151
161
 
152
162
  const workflowRunId = workflowRunIdOf(child);
153
- emitRelayEvent({
154
- type: "agent.ready",
155
- source: "server",
156
- subject: childId,
157
- data: { agentId: childId, parent: spawner, provider: providerOf(child), label: child.label, spawnRequestId, ...(workflowRunId ? { workflowRunId } : {}) },
158
- });
159
- if (!spawner) return;
160
- const parent = noticeRecipient(child, spawner);
161
-
162
- if (recovered) {
163
- emitRelayEvent({
164
- type: "agent.spawn_recovered",
165
- source: "server",
166
- subject: childId,
167
- data: { agentId: childId, parent: spawner, provider: providerOf(child), label: child.label, spawnRequestId, supersedes: "agent.spawn_failed" },
168
- });
163
+ const readyEvent = () => {
164
+ emitRelayEvent({ type: "agent.ready", source: "server", subject: childId,
165
+ data: { agentId: childId, parent: spawner, provider: providerOf(child), label: child.label, spawnRequestId, ...(workflowRunId ? { workflowRunId } : {}) } });
166
+ if (recovered && spawner) emitRelayEvent({ type: "agent.spawn_recovered", source: "server", subject: childId,
167
+ data: { agentId: childId, parent: spawner, provider: providerOf(child), label: child.label, spawnRequestId, supersedes: "agent.spawn_failed" } });
168
+ };
169
+ const slot = { child, kind: "agent.ready" };
170
+ if (!spawner) {
171
+ const created = await routeAgentNotice(slot);
172
+ recordSpawnTerminal(spawnRequestId, "agent.ready");
173
+ if (created) readyEvent();
174
+ return;
169
175
  }
170
-
176
+ const parent = noticeRecipient(child, spawner);
171
177
  if (recovered) {
172
178
  // A correction must always reach a parent that got the (false) failure — gate only on the global
173
179
  // switch, NOT the agentReady sub-toggle, so the retraction lands even if ready pushes are off.
174
- routeNotification({
180
+ const created = await routeAgentNotice(slot, {
175
181
  type: "agent.spawn_recovered",
176
182
  scope: { agentId: childId, parent },
177
183
  recipients: [parent],
@@ -186,9 +192,11 @@ function announceReady(child: AgentCard, spawner: string | undefined): void {
186
192
  replyExpected: false,
187
193
  },
188
194
  });
195
+ recordSpawnTerminal(spawnRequestId, "agent.ready");
196
+ if (created) readyEvent();
189
197
  return;
190
198
  }
191
- routeNotification({
199
+ const created = await routeAgentNotice(slot, {
192
200
  type: "agent.ready",
193
201
  scope: { agentId: childId, parent },
194
202
  recipients: [parent],
@@ -199,7 +207,8 @@ function announceReady(child: AgentCard, spawner: string | undefined): void {
199
207
  replyExpected: false,
200
208
  },
201
209
  });
202
- stampChildLifecycleSignal(parent, child);
210
+ recordSpawnTerminal(spawnRequestId, "agent.ready");
211
+ if (created) { readyEvent(); stampChildLifecycleSignal(parent, child); }
203
212
  }
204
213
 
205
214
  /**
@@ -209,16 +218,20 @@ function announceReady(child: AgentCard, spawner: string | undefined): void {
209
218
  * No-op for non-spawned agents.
210
219
  * `reason` is the offline cause (e.g. "heartbeat lost", "shutdown").
211
220
  */
212
- export function notifyAgentOffline(childId: string, reason: string, diagnosis?: AgentDeathDiagnosis): void {
213
- requestAgentExitCleanup(childId);
221
+ export async function notifyAgentOffline(childId: string, reason: string, diagnosis?: AgentDeathDiagnosis): Promise<void> {
222
+ return serializeSpawnNotice(spawnQueueKey(childId), () => notifyAgentOfflineBody(childId, reason, diagnosis));
223
+ }
224
+
225
+ async function notifyAgentOfflineBody(childId: string, reason: string, diagnosis?: AgentDeathDiagnosis): Promise<void> {
226
+ (await requestAgentExitCleanup(childId));
214
227
  const child = getAgent(childId);
215
228
  const parent = child?.spawnedBy;
216
229
  if (!child) return;
217
230
  if (!parent) {
218
231
  // A workflow step agent with no spawner records its exit on its run (#3160); nobody else is told.
219
232
  if (workflowRunIdOf(child) && everReady(child)) {
220
- clearAgentNotice(child, "agent.ready");
221
- notifyAgentExit(child, reason, diagnosis);
233
+ await clearAgentNoticeAsync(child, "agent.ready");
234
+ await notifyAgentExit(child, reason, diagnosis);
222
235
  }
223
236
  return;
224
237
  }
@@ -228,38 +241,32 @@ export function notifyAgentOffline(childId: string, reason: string, diagnosis?:
228
241
  // later signal (relay_workspace_ready, task→done) is coming from a process that no longer exists.
229
242
  // Idempotent (flushWorkFinalReports no-ops once the ring is empty), so a redundant call from a
230
243
  // second offline classification of the same agent is harmless.
231
- markAgentWorkFinal(childId, "edge-fallback");
244
+ (await markAgentWorkFinal(childId, "edge-fallback"));
232
245
  // Classify from the durable readiness stamp; re-arm this generation's ready push for a return.
233
246
  const wasReady = everReady(child);
234
- clearAgentNotice(child, "agent.ready");
247
+ await clearAgentNoticeAsync(child, "agent.ready");
235
248
  // #636 — persist the post-mortem keyed by agentId so the WHY survives the reaper, regardless of
236
249
  // whether the parent push is enabled. Recorded once per terminal-event emission.
237
- if (diagnosis) recordCrashReport(crashReportFor(child, reason, diagnosis));
250
+ if (diagnosis) await recordCrashReportAsync(crashReportFor(child, reason, diagnosis));
238
251
  if (hasAgentExitNotice(child)) return;
239
252
 
240
253
  // #645 — persist a terminal marker for ANY offline terminus (clean exit or spawn-fail) keyed by
241
254
  // agentId so it outlives the reaper. The #634 watchdog reads this to skip a benign shutdown; it
242
255
  // must fire ONLY on a genuine silent death that emitted no terminal event at all.
243
- recordTerminalEvent({ agentId: childId, reason, kind: wasReady ? "agent.exited" : "agent.spawn_failed", epoch: child.epoch, createdAt: Date.now() });
256
+ await recordTerminalEventAsync({ agentId: childId, reason, kind: wasReady ? "agent.exited" : "agent.spawn_failed", epoch: child.epoch, createdAt: Date.now() });
244
257
 
245
258
  if (wasReady) {
246
- notifyAgentExit(child, reason, diagnosis);
259
+ await notifyAgentExit(child, reason, diagnosis);
247
260
  return;
248
261
  }
249
262
 
250
- recordAgentNoticeOnce(child, () => {
263
+
251
264
  const recipient = noticeRecipient(child, parent);
252
265
  // #648 — record the terminal outcome so a (defensive) later ready for the same request is detected
253
266
  // as a recovery and corrected, keeping the one-terminal-per-spawn invariant across both fail paths.
254
267
  const spawnRequestId = spawnRequestIdOf(child);
255
- if (!tryRecordSpawnFailed(spawnRequestId)) return;
256
- emitRelayEvent({
257
- type: "agent.spawn_failed",
258
- source: "server",
259
- subject: childId,
260
- data: { agentId: childId, parent, reason, provider: providerOf(child), spawnRequestId, neverReady: true, ...(diagnosis ? { diagnosis } : {}) },
261
- });
262
- routeNotification({
268
+ if (spawnTerminalOf(spawnRequestId)) return;
269
+ const created = await routeAgentNotice({ child, kind: "agent.spawn_failed" }, {
263
270
  type: "agent.spawn_failed",
264
271
  scope: { agentId: childId, parent: recipient },
265
272
  recipients: [recipient],
@@ -274,7 +281,15 @@ export function notifyAgentOffline(childId: string, reason: string, diagnosis?:
274
281
  replyExpected: false,
275
282
  },
276
283
  });
277
- }, "agent.spawn_failed");
284
+ recordSpawnTerminal(spawnRequestId, "agent.spawn_failed");
285
+ if (created) {
286
+ emitRelayEvent({
287
+ type: "agent.spawn_failed",
288
+ source: "server",
289
+ subject: childId,
290
+ data: { agentId: childId, parent, reason, provider: providerOf(child), spawnRequestId, neverReady: true, ...(diagnosis ? { diagnosis } : {}) },
291
+ });
292
+ }
278
293
  }
279
294
 
280
295
  /**
@@ -286,21 +301,19 @@ export function notifyAgentOffline(childId: string, reason: string, diagnosis?:
286
301
  * the subsequent agent.ready / agent.spawn_failed — no separate "admitted" event needed. Non-terminal:
287
302
  * it deliberately does NOT touch the one-terminal-per-spawn guard.
288
303
  */
289
- export function notifyAgentSpawnQueued(input: { parent: string; spawnRequestId?: string; provider?: string; reason: string }): void {
304
+ export async function notifyAgentSpawnQueued(input: { parent: string; spawnRequestId?: string; provider?: string; reason: string }): Promise<void> {
305
+ return serializeSpawnNotice(input.spawnRequestId ?? `parent:${input.parent}`, () => notifyAgentSpawnQueuedBody(input));
306
+ }
307
+
308
+ async function notifyAgentSpawnQueuedBody(input: { parent: string; spawnRequestId?: string; provider?: string; reason: string }): Promise<void> {
290
309
  const dedupeKey = input.spawnRequestId ?? `parent:${input.parent}`;
291
310
  if (spawnQueuedNotified.has(dedupeKey)) return;
292
311
  // A queued spawn whose terminal outcome already landed (a fast admit→ready, or a fail) must not now
293
312
  // emit a stale "queued" notice out of order. Ready/failed is authoritative; suppress a late queue.
294
313
  if (spawnTerminalOf(input.spawnRequestId)) return;
295
- spawnQueuedNotified.add(dedupeKey);
296
- emitRelayEvent({
297
- type: "agent.spawn_queued",
298
- source: "server",
299
- subject: input.spawnRequestId ?? input.parent,
300
- data: { parent: input.parent, spawnRequestId: input.spawnRequestId, provider: input.provider, reason: input.reason },
301
- });
314
+
302
315
  const recipient = spawnerRecipient(input.parent, input.spawnRequestId);
303
- routeNotification({
316
+ await routeNotification({
304
317
  type: "agent.spawn_queued",
305
318
  scope: { parent: recipient },
306
319
  recipients: [recipient],
@@ -314,6 +327,13 @@ export function notifyAgentSpawnQueued(input: { parent: string; spawnRequestId?:
314
327
  replyExpected: false,
315
328
  },
316
329
  });
330
+ spawnQueuedNotified.add(dedupeKey);
331
+ emitRelayEvent({
332
+ type: "agent.spawn_queued",
333
+ source: "server",
334
+ subject: input.spawnRequestId ?? input.parent,
335
+ data: { parent: input.parent, spawnRequestId: input.spawnRequestId, provider: input.provider, reason: input.reason },
336
+ });
317
337
  }
318
338
 
319
339
  /**
@@ -321,18 +341,17 @@ export function notifyAgentSpawnQueued(input: { parent: string; spawnRequestId?:
321
341
  * (provider unavailable, bad cwd, launch error) before any child agent registered. Routes directly
322
342
  * to the spawning parent threaded on the command, since there is no child agent record to resolve.
323
343
  */
324
- export function notifyAgentSpawnFailed(input: { parent: string; spawnRequestId?: string; provider?: string; reason: string }): void {
344
+ export async function notifyAgentSpawnFailed(input: { parent: string; spawnRequestId?: string; provider?: string; reason: string }): Promise<void> {
345
+ return serializeSpawnNotice(input.spawnRequestId ?? `parent:${input.parent}`, () => notifyAgentSpawnFailedBody(input));
346
+ }
347
+
348
+ async function notifyAgentSpawnFailedBody(input: { parent: string; spawnRequestId?: string; provider?: string; reason: string }): Promise<void> {
325
349
  // #648/#864 — if the spawn already reached any terminal outcome, a later command-failure report
326
350
  // for the same request is stale or duplicate. Ready is authoritative; failed is already reported.
327
- if (!tryRecordSpawnFailed(input.spawnRequestId)) return;
328
- emitRelayEvent({
329
- type: "agent.spawn_failed",
330
- source: "server",
331
- subject: input.spawnRequestId ?? input.parent,
332
- data: { parent: input.parent, spawnRequestId: input.spawnRequestId, provider: input.provider, reason: input.reason },
333
- });
351
+ if (spawnTerminalOf(input.spawnRequestId)) return;
352
+
334
353
  const recipient = spawnerRecipient(input.parent, input.spawnRequestId);
335
- routeNotification({
354
+ await routeNotification({
336
355
  type: "agent.spawn_failed",
337
356
  scope: { parent: recipient },
338
357
  recipients: [recipient],
@@ -346,6 +365,13 @@ export function notifyAgentSpawnFailed(input: { parent: string; spawnRequestId?:
346
365
  replyExpected: false,
347
366
  },
348
367
  });
368
+ recordSpawnTerminal(input.spawnRequestId, "agent.spawn_failed");
369
+ emitRelayEvent({
370
+ type: "agent.spawn_failed",
371
+ source: "server",
372
+ subject: input.spawnRequestId ?? input.parent,
373
+ data: { parent: input.parent, spawnRequestId: input.spawnRequestId, provider: input.provider, reason: input.reason },
374
+ });
349
375
  }
350
376
 
351
377
  /**
@@ -353,7 +379,7 @@ export function notifyAgentSpawnFailed(input: { parent: string; spawnRequestId?:
353
379
  * deliberately non-terminal: the runner can still register after the watchdog fires, so callers
354
380
  * must not retry or infer that a new spawn is safe.
355
381
  */
356
- export function notifyAgentSpawnUnconfirmed(input: { parent: string; spawnRequestId: string; provider?: string; reason: string; phase: "dispatch_unacknowledged" | "registration_unconfirmed" }): void {
382
+ export async function notifyAgentSpawnUnconfirmed(input: { parent: string; spawnRequestId: string; provider?: string; reason: string; phase: "dispatch_unacknowledged" | "registration_unconfirmed" }): Promise<void> {
357
383
  emitRelayEvent({
358
384
  type: "agent.spawn_unconfirmed",
359
385
  source: "server",
@@ -361,7 +387,7 @@ export function notifyAgentSpawnUnconfirmed(input: { parent: string; spawnReques
361
387
  data: input,
362
388
  });
363
389
  const recipient = spawnerRecipient(input.parent, input.spawnRequestId);
364
- routeNotification({
390
+ await routeNotification({
365
391
  type: "agent.spawn_unconfirmed",
366
392
  scope: { parent: recipient },
367
393
  recipients: [recipient],
@@ -392,24 +418,18 @@ export function notifyAgentRegistered(agent: AgentCard): void {
392
418
  }
393
419
 
394
420
  /** Emit one parent exit notice per generation, including automatic reaps before the offline report. */
395
- export function notifyAgentExit(child: AgentCard, reason: string, diagnosis?: AgentDeathDiagnosis, context: { workspaceId?: string; workspaceStatus?: string } = {}): void {
421
+ export async function notifyAgentExit(child: AgentCard, reason: string, diagnosis?: AgentDeathDiagnosis, context: { workspaceId?: string; workspaceStatus?: string } = {}): Promise<void> {
396
422
  const parent = child.spawnedBy;
397
423
  const workflowRunId = workflowRunIdOf(child);
398
- recordAgentNoticeOnce(child, () => {
399
- emitRelayEvent({
400
- type: "agent.exited",
401
- source: "server",
402
- subject: child.id,
403
- data: { ...context, agentId: child.id, parent, reason, provider: providerOf(child), spawnRequestId: spawnRequestIdOf(child), ...(workflowRunId ? { workflowRunId } : {}), ...(diagnosis ? { diagnosis } : {}) },
404
- });
424
+
405
425
  // The parent already got a shutdown command receipt for requesting this exit, so the
406
426
  // exit itself is expected — including a non-zero code from a force-reap kill. Keep the
407
427
  // terminal event for timeline consumers; only skip the parent wake-up. An exit nobody
408
428
  // requested (no shutdown command from the parent) still wakes: crashes and spawn failures
409
429
  // keep their notice.
410
- if (parent && parentRequestedShutdown(child.id, spawnRequestIdOf(child) ?? "", parent, Date.now() - 5 * 60_000)) return;
430
+ const suppressed = parent && parentRequestedShutdown(child.id, spawnRequestIdOf(child) ?? "", parent, Date.now() - 5 * 60_000);
411
431
  const recipient = parent ? noticeRecipient(child, parent) : undefined;
412
- routeNotification({
432
+ const created = await routeAgentNotice({ child, kind: "agent.exited" }, suppressed ? undefined : {
413
433
  type: "agent.exited",
414
434
  scope: { agentId: child.id, parent: recipient },
415
435
  recipients: [recipient],
@@ -424,5 +444,12 @@ export function notifyAgentExit(child: AgentCard, reason: string, diagnosis?: Ag
424
444
  replyExpected: false,
425
445
  },
426
446
  });
427
- });
447
+ if (created) {
448
+ emitRelayEvent({
449
+ type: "agent.exited",
450
+ source: "server",
451
+ subject: child.id,
452
+ data: { ...context, agentId: child.id, parent, reason, provider: providerOf(child), spawnRequestId: spawnRequestIdOf(child), ...(workflowRunId ? { workflowRunId } : {}), ...(diagnosis ? { diagnosis } : {}) },
453
+ });
454
+ }
428
455
  }
package/src/agent-ref.ts CHANGED
@@ -160,8 +160,9 @@ export function resolveAgentRef(ref: string, agents: AgentCard[], opts: ResolveO
160
160
  return { status: "not_found", offlineMatches: matches };
161
161
  }
162
162
 
163
- export function targetMatchesAgent(target: string, agentId: string, agent?: AgentCard | null): boolean {
164
- if (!agent) return false;
163
+ export function targetMatchesAgent(target: string | null | undefined, agentId: string, agent?: AgentCard | null): boolean {
164
+ // Untargeted task events have no agent recipient, on live streams or replay (#3801).
165
+ if (!agent || typeof target !== "string" || !target) return false;
165
166
  if (target.startsWith("coordinator:")) return resolveTeamCoordinatorAgentId(target.slice(12)) === agentId;
166
167
  return targetMatchesAgentIdentity(target, {
167
168
  id: agentId,
@@ -1,18 +1,41 @@
1
- // The ONE agent.status emitter (#3606): every seam lands here, so "unchanged card → no event" holds on all.
2
- // A card equal to the last one emitted, ignoring lastSeen and statusSeq, is dropped before persistence:
3
- // liveness ticks only moved those two (39% of prod agent.status events), the dashboard reads heartbeat
4
- // age from its 5–15 s roster poll, and no consumer orders by statusSeq.
1
+ // The ONE agent.status emitter (#3606): every seam lands here. A card unchanged but for lastSeen and
2
+ // statusSeq is dropped (the dashboard reads heartbeat age from its roster poll; nothing orders by
3
+ // statusSeq). #3614 — a change only in liveness telemetry (timestamps, ages, gauges the next tick
4
+ // supersedes) goes out live-only, with no outbox row; replay keeps every real state change.
5
5
 
6
6
  import { getAgentRuntimeAsync } from "./db";
7
7
  import { projectAgentStatusData } from "./agent-card-projection";
8
- import { emitRelayEvent } from "./events";
8
+ import { emitEphemeralRelayEvent, emitRelayEvent } from "./events";
9
9
  import { emitNotificationCreated, notificationForAgentStatus } from "./dashboard-notifications";
10
10
 
11
- const lastEmitted = new Map<string, number | bigint>();
11
+ type Fingerprint = number | bigint;
12
12
 
13
- function cardFingerprint(data: Record<string, unknown>): number | bigint {
14
- const { lastSeen: _lastSeen, statusSeq: _statusSeq, ...card } = data;
15
- return Bun.hash(JSON.stringify(card));
13
+ const UNEMITTED_KEYS = [["lastSeen"], ["statusSeq"]] as const;
14
+ const LIVENESS_KEYS = [
15
+ ...UNEMITTED_KEYS,
16
+ ["context", "lastUpdatedAt"], ["context", "tokensUsed"], ["context", "utilization"],
17
+ ["meta", "unreportedTokenUsage"], ["meta", "lastProviderEventAt"],
18
+ ["meta", "transport", "lastServerFrameAt"], ["meta", "transport", "lastHeartbeatAckAt"],
19
+ ["meta", "liveness", "transportLiveAt"], ["meta", "liveness", "lastProgressAt"],
20
+ ["meta", "busyHealth", "activeWorkAgeMs"], ["meta", "busyHealth", "staleForMs"], ["meta", "busyHealth", "lastProgressAt"],
21
+ ["meta", "busyHealth", "transportLiveAt"], ["meta", "busyHealth", "transportStaleForMs"],
22
+ ] as const;
23
+
24
+ const lastEmitted = new Map<string, { card: Fingerprint; durable: Fingerprint }>();
25
+
26
+ /** Hash of the card without `paths`; copies only the objects on a stripped path. */
27
+ function fingerprint(data: Record<string, unknown>, paths: ReadonlyArray<readonly string[]>): Fingerprint {
28
+ const root = { ...data };
29
+ for (const path of paths) {
30
+ let parent: Record<string, unknown> = root;
31
+ for (const key of path.slice(0, -1)) {
32
+ const child = parent[key];
33
+ if (!child || typeof child !== "object" || Array.isArray(child)) { parent = {}; break; }
34
+ parent = parent[key] = { ...child as Record<string, unknown> };
35
+ }
36
+ delete parent[path[path.length - 1]!];
37
+ }
38
+ return Bun.hash(JSON.stringify(root));
16
39
  }
17
40
 
18
41
  export async function emitAgentStatus(agentId: string): Promise<void> {
@@ -20,15 +43,21 @@ export async function emitAgentStatus(agentId: string): Promise<void> {
20
43
  // Enrich with the branch-state badge fields (#236) and the resolved issueRepo (#533) so
21
44
  // the dashboard's live agent updates carry the same projection as GET /api/agents (#560).
22
45
  const data = await projectAgentStatusData(agentId, agent) as unknown as Record<string, unknown>;
23
- const fingerprint = cardFingerprint(data);
24
- if (lastEmitted.get(agentId) === fingerprint) return;
25
- lastEmitted.set(agentId, fingerprint);
46
+ const next = { card: fingerprint(data, UNEMITTED_KEYS), durable: fingerprint(data, LIVENESS_KEYS) };
47
+ const previous = lastEmitted.get(agentId);
48
+ if (previous?.card === next.card) return;
49
+ lastEmitted.set(agentId, next);
50
+ const event = { type: "agent.status", source: "server", subject: agentId, data };
51
+ if (previous?.durable === next.durable) {
52
+ emitEphemeralRelayEvent(event);
53
+ return;
54
+ }
26
55
  try {
27
56
  // Awaited: a bus registration must not install its socket before its own status event is durable.
28
- await emitRelayEvent({ type: "agent.status", source: "server", subject: agentId, data });
57
+ await emitRelayEvent(event);
29
58
  } catch (error) {
30
59
  // Never let an append that did not happen suppress the next identical card.
31
- if (lastEmitted.get(agentId) === fingerprint) lastEmitted.delete(agentId);
60
+ if (lastEmitted.get(agentId) === next) lastEmitted.delete(agentId);
32
61
  throw error;
33
62
  }
34
63
  const notification = agent ? notificationForAgentStatus(agent) : undefined;