@humwick/server 0.130.2 → 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 (570) hide show
  1. package/bundled/prompts/manifest.json +1 -0
  2. package/bundled/prompts/task.hydration.md +1 -1
  3. package/bundled/roles/builder.md +1 -1
  4. package/docs/guides/sub-coordinators.md +12 -5
  5. package/docs/guides/tools-coordination.md +1 -0
  6. package/docs/guides/workflows.md +16 -0
  7. package/docs/openapi.json +73 -4
  8. package/package.json +8 -7
  9. package/public/assets/{MessageBubble-BWLqMGKG.js → MessageBubble-Bq9kr21N.js} +2 -2
  10. package/public/assets/{PlanGraphPanel-3TlIQpjk.js → PlanGraphPanel-Dqiroy06.js} +2 -2
  11. package/public/assets/{TraceView-Wimm0Czv.js → TraceView-DYU962-H.js} +2 -2
  12. package/public/assets/{VaultDecisionCard-Bau_vNax.js → VaultDecisionCard-DhPfzioE.js} +2 -2
  13. package/public/assets/{activity-CrSurn-r.js → activity-DzCcQTee.js} +2 -2
  14. package/public/assets/{agent-lineage-CknAJKcb.js → agent-lineage-SgDt9i3T.js} +2 -2
  15. package/public/assets/agent-liveness-Bq-s73jW.js +2 -0
  16. package/public/assets/{agent-name-DKbiIhBo.js → agent-name-CcY3Aijy.js} +2 -2
  17. package/public/assets/{agent-profiles-DwF6EQ4R.js → agent-profiles-cxtRBn6O.js} +2 -2
  18. package/public/assets/{agent-project-badge-Diz4Sjjb.js → agent-project-badge-DGYbIhaI.js} +2 -2
  19. package/public/assets/{agent-tools-CRhpRQza.js → agent-tools-DHbftV0N.js} +2 -2
  20. package/public/assets/{agent-type-icon-LrUEU3lB.js → agent-type-icon-CY113sp-.js} +2 -2
  21. package/public/assets/{agents-B-v66C-4.js → agents-BPzY7IlQ.js} +2 -2
  22. package/public/assets/{analytics-BqCb-LKi.js → analytics-DENFPv_a.js} +2 -2
  23. package/public/assets/{artifact-viewer-kf4pGuAR.js → artifact-viewer-KRvSc7sl.js} +2 -2
  24. package/public/assets/{artifacts-DJevXcvg.js → artifacts-C9gSmL3s.js} +2 -2
  25. package/public/assets/{artifacts-D32zyw4Y.js → artifacts-DT-HkI5O.js} +2 -2
  26. package/public/assets/{automation-BpRajx_5.js → automation-BsmjQhKD.js} +2 -2
  27. package/public/assets/{backlog-D_UjTdzX.js → backlog-8NYH_62t.js} +2 -2
  28. package/public/assets/{busy-health-N3VEh4ao.js → busy-health-D3hwvYb4.js} +2 -2
  29. package/public/assets/{channels-9jopungq.js → channels-DCJ5WL7O.js} +2 -2
  30. package/public/assets/{chat-CSXrTB3C.js → chat-DAIl357U.js} +3 -3
  31. package/public/assets/{code-preview-p1NnmqK0.js → code-preview-CzrZfr9U.js} +2 -2
  32. package/public/assets/{connectors-CZdqlDNL.js → connectors-xTxtlyou.js} +2 -2
  33. package/public/assets/{cosmos-BgdsE4dG.js → cosmos-BpebFLK2.js} +2 -2
  34. package/public/assets/{crate-agent-30aXTKva.js → crate-agent-BHvI5wXC.js} +2 -2
  35. package/public/assets/{dependency-graph-B_jvw2GE.js → dependency-graph-DGT0o3wJ.js} +2 -2
  36. package/public/assets/{deploys-DoN6bAb5.js → deploys-hqWOHSHE.js} +2 -2
  37. package/public/assets/{display-BrKWFGJz.js → display-CDeH4I8T.js} +2 -2
  38. package/public/assets/{files-D6XEu8Ng.js → files-BTeGVmTg.js} +2 -2
  39. package/public/assets/{fleet-C7jQWbw2.js → fleet-DgXtNgCa.js} +2 -2
  40. package/public/assets/{fleet-metrics-BiDs3MLx.js → fleet-metrics-BHEt5yc_.js} +2 -2
  41. package/public/assets/{formatted-body-CQBwc1fb.js → formatted-body-MLtodyPp.js} +3 -3
  42. package/public/assets/{formatted-body-impl-DyG0WsQS.js → formatted-body-impl-CAe664Z8.js} +2 -2
  43. package/public/assets/{host-providers-dialog-DKaW31dN.js → host-providers-dialog-mapF4Fj9.js} +2 -2
  44. package/public/assets/{index-CRHep3M9.js → index-CqqgOI5R.js} +5 -5
  45. package/public/assets/{insights-CzrtkpOE.js → insights-DNyf7IzF.js} +2 -2
  46. package/public/assets/{integrations-aVsUmigt.js → integrations-DlYOHq7T.js} +2 -2
  47. package/public/assets/{issue-ref-chip-BnSlM_95.js → issue-ref-chip-CeWBNWn7.js} +2 -2
  48. package/public/assets/{log-viewer-qe7Ee47Z.js → log-viewer-Cib8nqdE.js} +2 -2
  49. package/public/assets/{maintenance-NfjqFZAk.js → maintenance-DSn1cPm7.js} +2 -2
  50. package/public/assets/{managed-agents-BiH0HgaE.js → managed-agents-C3CkM81m.js} +2 -2
  51. package/public/assets/{markdown-preview-BixaT3Xr.js → markdown-preview-W4VQQPAv.js} +3 -3
  52. package/public/assets/{markdown-preview-impl-DNGlWIS3.js → markdown-preview-impl-CMsTdhjq.js} +2 -2
  53. package/public/assets/{memory-DNsCl6UX.js → memory-BV17qtO4.js} +2 -2
  54. package/public/assets/{messages-DopU1L1X.js → messages-Bm_1AqSA.js} +2 -2
  55. package/public/assets/{orchestrators-Cq7ckLQT.js → orchestrators-Dg-vfP09.js} +2 -2
  56. package/public/assets/{overview-C1DCTzzV.js → overview-DcYCrvlr.js} +2 -2
  57. package/public/assets/{pairs-DE_m6rrE.js → pairs-8o9nuG3V.js} +2 -2
  58. package/public/assets/{profile-icon-B3rfh77F.js → profile-icon-BsRyBMea.js} +2 -2
  59. package/public/assets/{project-profile-instructions-DQWZE0kA.js → project-profile-instructions-DETKFn_E.js} +2 -2
  60. package/public/assets/{projects-Br2Bd2h1.js → projects-M_m6AHws.js} +2 -2
  61. package/public/assets/{prompt-settings-BKvFsvGD.js → prompt-settings-C_mNCgeL.js} +2 -2
  62. package/public/assets/provider-display-BEeLXC_D.js +2 -0
  63. package/public/assets/{registry-Cw38_6gW.js → registry-DDHHHE5N.js} +2 -2
  64. package/public/assets/run-card-Dt4I4jaP.js +2 -0
  65. package/public/assets/{secrets-DxI-vzSq.js → secrets-BkVwxI5O.js} +2 -2
  66. package/public/assets/{service-access-settings-D9s_VJbd.js → service-access-settings-Crq-6a-B.js} +2 -2
  67. package/public/assets/{settings-CKZTVGIx.js → settings-CYcavMFu.js} +2 -2
  68. package/public/assets/shipping-H6gzEeZB.js +2 -0
  69. package/public/assets/{stats-DyUBKyWI.js → stats-BJVeWkpV.js} +2 -2
  70. package/public/assets/{status-dot-DYqlEUhJ.js → status-dot-BcHyw1Vw.js} +2 -2
  71. package/public/assets/store-DKPDIZBe.js +9 -0
  72. package/public/assets/{tasks-Bh7Chr4-.js → tasks-qJjlQPpx.js} +2 -2
  73. package/public/assets/{teams-bowI7qVY.js → teams-Cd5Sk1uX.js} +2 -2
  74. package/public/assets/{terminal-viewer-BgVLHdsU.js → terminal-viewer-CpY5_m7W.js} +3 -3
  75. package/public/assets/{terminal-viewer-impl-Dz22UPy6.js → terminal-viewer-impl-DI_2llFR.js} +2 -2
  76. package/public/assets/{use-agent-terminal-DSQQ-iY7.js → use-agent-terminal-0yJA_buM.js} +2 -2
  77. package/public/assets/{use-decisions-samMQhQf.js → use-decisions-uJXHf34W.js} +2 -2
  78. package/public/assets/{use-project-list-59LheVP7.js → use-project-list-CpWl6eHQ.js} +2 -2
  79. package/public/assets/{use-selectors-BZa25xEB.js → use-selectors-BdxBW8mL.js} +2 -2
  80. package/public/assets/{user-avatar-DHxlvUvV.js → user-avatar-3IndfpOc.js} +2 -2
  81. package/public/assets/{versioned-prompt-editor-BmED5DnJ.js → versioned-prompt-editor-CIVg7XB1.js} +2 -2
  82. package/public/assets/{work-queue-CSvpuNLz.js → work-queue-B9rnLwHZ.js} +2 -2
  83. package/public/assets/{workflow-marker-DAZcj5qt.js → workflow-marker-X8wxyhzC.js} +2 -2
  84. package/public/assets/{workflows-DdmxRSyg.js → workflows-o5YyMFW7.js} +2 -2
  85. package/public/assets/{workspaces-BxeKfVuF.js → workspaces-CzEGoAng.js} +2 -2
  86. package/public/cosmos.html +4 -4
  87. package/public/index.html +28 -28
  88. package/runner/plugins/claude/.claude-plugin/plugin.json +1 -1
  89. package/runner/src/adapters/claude-headless.ts +1 -1
  90. package/runner/src/adapters/claude-launch-exit.ts +26 -0
  91. package/runner/src/adapters/claude-session-probe.ts +1 -1
  92. package/runner/src/adapters/claude-tmux.ts +38 -10
  93. package/runner/src/adapters/claude.ts +28 -75
  94. package/runner/src/adapters/provider-quota-harvest.ts +20 -71
  95. package/runner/src/agent-runner/lifecycle-milestones.ts +2 -2
  96. package/runner/src/agent-runner/liveness-exchange.ts +104 -0
  97. package/runner/src/claude-system-prompt.ts +49 -0
  98. package/runner/src/launch-assembly.ts +14 -10
  99. package/runner/src/profile-home.ts +1 -1
  100. package/runner/src/project-instructions.ts +2 -2
  101. package/runner/src/provider-command.ts +18 -0
  102. package/runner/src/provider-setup.ts +2 -1
  103. package/runner/src/runner-core.ts +14 -15
  104. package/runner/src/runner-helpers.ts +0 -8
  105. package/runner/src/session-scratch.ts +6 -2
  106. package/runner/test-support/provisioning-context.ts +4 -2
  107. package/runner/test-support/runner-harness.ts +2 -1
  108. package/scripts/steward-policy-cleanup.ts +2 -2
  109. package/src/agent-authz.ts +2 -2
  110. package/src/agent-drive-arbiter.ts +3 -8
  111. package/src/agent-exit-cleanup-async.ts +2 -2
  112. package/src/agent-exit-cleanup.ts +23 -19
  113. package/src/agent-lifecycle-events.ts +112 -85
  114. package/src/agent-ref.ts +3 -2
  115. package/src/agent-status-events.ts +43 -14
  116. package/src/auth/password.ts +4 -3
  117. package/src/auth/session-refresh.ts +1 -1
  118. package/src/auth/session.test-fixture.ts +2 -2
  119. package/src/auth/session.ts +7 -7
  120. package/src/automations/crud.ts +8 -81
  121. package/src/automations/dispatch.ts +33 -58
  122. package/src/automations/index.ts +1 -1
  123. package/src/automations/persistence.ts +65 -0
  124. package/src/automations/precheck.ts +18 -16
  125. package/src/automations/read-async.ts +11 -0
  126. package/src/automations/reconcile.ts +30 -39
  127. package/src/automations/storage.ts +33 -10
  128. package/src/automations/write-async.ts +33 -0
  129. package/src/branch-land-notice.ts +3 -3
  130. package/src/branch-landed.ts +25 -23
  131. package/src/bus.ts +21 -19
  132. package/src/cd-deploy-notify.ts +2 -2
  133. package/src/ci/notifications.ts +4 -4
  134. package/src/ci/root-missing.ts +3 -3
  135. package/src/ci/transition-notify.ts +5 -5
  136. package/src/claude-app/oauth-http.ts +3 -3
  137. package/src/cli/workflow.ts +12 -3
  138. package/src/commands-db.ts +4 -4
  139. package/src/commands-write.ts +8 -0
  140. package/src/compaction-watch.ts +10 -8
  141. package/src/config-store-write.ts +2 -2
  142. package/src/config.ts +4 -11
  143. package/src/connectors.ts +10 -8
  144. package/src/context-advisory.ts +22 -21
  145. package/src/db/agent-action-write.ts +36 -0
  146. package/src/db/agent-control-async.ts +9 -0
  147. package/src/db/agent-control-write.ts +49 -0
  148. package/src/db/agent-effort-observe.ts +22 -0
  149. package/src/db/agent-meta.ts +14 -3
  150. package/src/db/agents-async.ts +8 -5
  151. package/src/db/agents.ts +15 -12
  152. package/src/db/auth-identities.ts +2 -2
  153. package/src/db/automation-read-ops.ts +11 -0
  154. package/src/db/automation-write-ops.ts +46 -0
  155. package/src/db/blackboard.ts +2 -2
  156. package/src/db/browser-session-write.ts +32 -0
  157. package/src/db/bus-outbox-write-ops.ts +3 -1
  158. package/src/db/checkout-refresh-schema.ts +47 -0
  159. package/src/db/checkout-refresh.ts +5 -5
  160. package/src/db/command-agent-profile-backfill.ts +39 -0
  161. package/src/db/command-agent-profiles.ts +5 -1
  162. package/src/db/command-retention.ts +126 -0
  163. package/src/db/commands-planner-stats.test-fixture.ts +8 -0
  164. package/src/db/commands-read-ops.ts +16 -0
  165. package/src/db/connection.ts +1 -182
  166. package/src/db/context-carry-write.ts +74 -0
  167. package/src/db/continuations.ts +4 -4
  168. package/src/db/db-error-registry.ts +12 -0
  169. package/src/db/gateway.ts +26 -133
  170. package/src/db/history-retention-ops.ts +13 -0
  171. package/src/db/inbox-async.ts +2 -2
  172. package/src/db/inbox-read-ops.ts +1 -1
  173. package/src/db/inbox.ts +9 -3
  174. package/src/db/issue-associations.ts +2 -2
  175. package/src/db/issue-refs-async.ts +4 -1
  176. package/src/db/issue-refs-read-ops.ts +6 -0
  177. package/src/db/issue-refs.ts +8 -8
  178. package/src/db/kernel-event-log-schema.ts +2 -0
  179. package/src/db/land-boundaries.ts +51 -5
  180. package/src/db/land-gate-attestations.ts +2 -2
  181. package/src/db/landing-receipts.ts +2 -2
  182. package/src/db/lifecycle-context-write.ts +5 -0
  183. package/src/db/lifecycle-tail-async.ts +76 -0
  184. package/src/db/lifecycle-tail-write-ops.ts +62 -0
  185. package/src/db/lifecycle-write-window.ts +2 -1
  186. package/src/db/lineage-pair-dedupe-sql.ts +3 -3
  187. package/src/db/main-connection-mode.ts +11 -0
  188. package/src/db/main-connection-writes.ts +20 -2
  189. package/src/db/maintenance-job-runs-async.ts +2 -2
  190. package/src/db/maintenance-job-write-ops.ts +1 -1
  191. package/src/db/maintenance-pauses.ts +2 -2
  192. package/src/db/message-send.ts +4 -0
  193. package/src/db/messages.ts +31 -25
  194. package/src/db/migrations.ts +18 -1
  195. package/src/db/notification-write-ops.ts +19 -0
  196. package/src/db/operator-answer-write.ts +19 -0
  197. package/src/db/orchestrators.ts +10 -4
  198. package/src/db/pairs-async.ts +22 -1
  199. package/src/db/pairs-write-ops.ts +8 -3
  200. package/src/db/pairs.ts +41 -48
  201. package/src/db/plan-dispatch-schema.ts +5 -1
  202. package/src/db/plan-ready-notices.ts +43 -0
  203. package/src/db/plan-tools-include-migration.ts +36 -0
  204. package/src/db/plans-write-ops.ts +2 -0
  205. package/src/db/presence-buffer.ts +5 -0
  206. package/src/db/presence-loop.ts +18 -23
  207. package/src/db/presence-write.ts +0 -6
  208. package/src/db/project-entries-async.ts +14 -0
  209. package/src/db/project-entries-read-ops.ts +5 -1
  210. package/src/db/project-entries-write-ops.ts +8 -0
  211. package/src/db/project-entries.ts +15 -12
  212. package/src/db/project-journal.ts +2 -2
  213. package/src/db/project-trust-approvals.ts +2 -2
  214. package/src/db/prompt-templates.ts +4 -4
  215. package/src/db/read-op-marshaling-fixtures.ts +18 -0
  216. package/src/db/read-ops.ts +4 -0
  217. package/src/db/retention.ts +13 -2
  218. package/src/db/review-publish-write.ts +8 -0
  219. package/src/db/runtime-admin-async.ts +19 -0
  220. package/src/db/runtime-admin-write-ops.ts +36 -0
  221. package/src/db/runtime-tail-async.ts +288 -0
  222. package/src/db/runtime-tail-write-ops.ts +97 -0
  223. package/src/db/schema.ts +4 -1
  224. package/src/db/spawn-budget.ts +5 -0
  225. package/src/db/spawn-delegation.ts +1 -11
  226. package/src/db/sql-audit-indexes.ts +3 -0
  227. package/src/db/stats-async.ts +5 -3
  228. package/src/db/task-entity.ts +5 -4
  229. package/src/db/team-claim-policy.ts +60 -0
  230. package/src/db/teams-async.ts +4 -0
  231. package/src/db/teams-write-ops.ts +4 -0
  232. package/src/db/terminal-events.ts +15 -0
  233. package/src/db/timer-cutover-bodies.ts +292 -0
  234. package/src/db/timer-cutover-core.ts +37 -278
  235. package/src/db/timer-cutover-state.ts +40 -0
  236. package/src/db/timer-cutover-write-ops.ts +1 -40
  237. package/src/db/token-db-write-ops.ts +2 -0
  238. package/src/db/token-standing-async.ts +12 -0
  239. package/src/db/token-standing.ts +6 -9
  240. package/src/db/token-usage-retention.ts +33 -0
  241. package/src/db/token-usage-write-ops.ts +1 -1
  242. package/src/db/token-usage.ts +4 -1
  243. package/src/db/user-invites-async.ts +13 -0
  244. package/src/db/user-invites.ts +3 -3
  245. package/src/db/users.ts +14 -6
  246. package/src/db/workspaces.ts +8 -5
  247. package/src/db/write-ops.ts +31 -12
  248. package/src/db/writer-fault-seam.ts +2 -9
  249. package/src/db/writer-fault-test-ops.ts +18 -0
  250. package/src/db/writer-gateway.ts +42 -46
  251. package/src/dev.ts +8 -3
  252. package/src/event-loop-lag.ts +4 -2
  253. package/src/event-loop-yield.ts +2 -2
  254. package/src/events.ts +10 -8
  255. package/src/host-provider-store.ts +5 -4
  256. package/src/hub-metrics-report.ts +5 -1
  257. package/src/hub-metrics.ts +38 -18
  258. package/src/injection-sweep-pacing.ts +6 -8
  259. package/src/land-gate-notifications.ts +11 -10
  260. package/src/land-gate-queue-progress.ts +3 -3
  261. package/src/land-settle-dispatch.ts +52 -92
  262. package/src/lifecycle-context-pressure.ts +11 -10
  263. package/src/lifecycle-manager.ts +104 -98
  264. package/src/maintenance/breaker.ts +18 -16
  265. package/src/maintenance/checkout-refresh.ts +18 -1
  266. package/src/maintenance/critical-job-watchdog.ts +3 -3
  267. package/src/maintenance/events.ts +3 -3
  268. package/src/maintenance/history-retention-job.ts +30 -0
  269. package/src/maintenance/jobs.ts +29 -67
  270. package/src/maintenance/long-running-work.ts +3 -1
  271. package/src/maintenance/offline-agent-prune-job.ts +28 -0
  272. package/src/maintenance/orphaned-sessions.ts +5 -4
  273. package/src/maintenance/pauses.ts +4 -10
  274. package/src/maintenance/plan-ready-notice-job.ts +71 -0
  275. package/src/maintenance/scheduler.ts +18 -13
  276. package/src/maintenance/stalled-delivery-pager.ts +4 -4
  277. package/src/maintenance/teams.ts +19 -30
  278. package/src/maintenance/workspaces.ts +17 -27
  279. package/src/managed-policy-escalation.ts +7 -7
  280. package/src/managed-policy.ts +3 -3
  281. package/src/managed-provider-gate.ts +5 -4
  282. package/src/managed-spawn-reservation.ts +5 -4
  283. package/src/mcp/index.ts +8 -8
  284. package/src/mcp/output-descriptions.ts +1 -1
  285. package/src/mcp/presentation.ts +2 -1
  286. package/src/mcp/runtime-output.ts +6 -1
  287. package/src/mcp/self-care-visibility.ts +2 -2
  288. package/src/mcp/spawn-targets-matrix.ts +10 -1
  289. package/src/mcp/tool-groups.ts +3 -2
  290. package/src/mcp/tool-roles.ts +81 -0
  291. package/src/mcp/tools-workspace.ts +1 -1
  292. package/src/mcp-blackboard-tools.ts +6 -5
  293. package/src/mcp-decision-tools.ts +7 -7
  294. package/src/mcp-egress-tools.ts +10 -9
  295. package/src/mcp-issue-activity-tools.ts +2 -2
  296. package/src/mcp-issue-association-tools.ts +4 -4
  297. package/src/mcp-issue-ref-tools.ts +3 -3
  298. package/src/mcp-merge-tools.ts +5 -5
  299. package/src/mcp-notification-subscription-tools.ts +14 -15
  300. package/src/mcp-output-levels.test-fixture.ts +1 -1
  301. package/src/mcp-profile-trust-tools.ts +1 -1
  302. package/src/mcp-project-journal-tools.ts +4 -12
  303. package/src/mcp-project-tools.ts +17 -18
  304. package/src/mcp-routing-policy-tools.ts +3 -2
  305. package/src/mcp-team-tools.ts +6 -6
  306. package/src/mcp-workflow-tools.ts +5 -3
  307. package/src/memory-area-injection.ts +13 -12
  308. package/src/memory-boundary-capture.ts +6 -6
  309. package/src/memory-injection.ts +45 -43
  310. package/src/merge-pause-maintenance.ts +5 -4
  311. package/src/notification-router.ts +44 -17
  312. package/src/notify.ts +5 -5
  313. package/src/observed-reset-refresh.ts +4 -4
  314. package/src/operator-alarm.ts +2 -5
  315. package/src/project-ingest.ts +6 -6
  316. package/src/project-instructions.ts +8 -1
  317. package/src/project-trust.ts +12 -11
  318. package/src/prompt-resolver.ts +3 -3
  319. package/src/provider-quota-async.ts +5 -7
  320. package/src/provider-timeline-event.ts +4 -7
  321. package/src/quota-band-delivery.ts +2 -2
  322. package/src/recipe-runner.ts +4 -3
  323. package/src/retention-config-store.ts +4 -3
  324. package/src/reviewer-pipeline.ts +11 -10
  325. package/src/routes/_route.ts +4 -4
  326. package/src/routes/_shared.ts +13 -12
  327. package/src/routes/agent-effort.ts +5 -5
  328. package/src/routes/agent-heartbeat-quota.ts +23 -0
  329. package/src/routes/agent-keep.ts +1 -1
  330. package/src/routes/agent-reporting.ts +1 -1
  331. package/src/routes/agent-self-effort.ts +5 -5
  332. package/src/routes/agent-sessions.ts +24 -24
  333. package/src/routes/agents-spawn.ts +1 -1
  334. package/src/routes/agents.ts +17 -119
  335. package/src/routes/auth.ts +14 -15
  336. package/src/routes/authority-audit.ts +2 -2
  337. package/src/routes/automations.ts +6 -5
  338. package/src/routes/channel-binding-delete.ts +1 -1
  339. package/src/routes/channel-output.ts +3 -3
  340. package/src/routes/claude-api-budget.ts +5 -5
  341. package/src/routes/commands-listing.ts +1 -1
  342. package/src/routes/commands.ts +29 -27
  343. package/src/routes/context-resets.ts +2 -2
  344. package/src/routes/coordinator-teams.ts +1 -1
  345. package/src/routes/decisions.ts +2 -2
  346. package/src/routes/host-secret-files.ts +1 -1
  347. package/src/routes/hosts.ts +11 -11
  348. package/src/routes/inbox.ts +3 -2
  349. package/src/routes/index.ts +2 -1
  350. package/src/routes/integrations.ts +9 -7
  351. package/src/routes/issue-activity.ts +2 -2
  352. package/src/routes/issue-associations.ts +4 -4
  353. package/src/routes/issue-refs.ts +3 -3
  354. package/src/routes/kernel-timers-operator.ts +1 -1
  355. package/src/routes/memory.ts +1 -1
  356. package/src/routes/merges.ts +11 -11
  357. package/src/routes/messages.ts +23 -17
  358. package/src/routes/orchestrator-bootstrap.ts +1 -1
  359. package/src/routes/orchestrator-host-registration.ts +2 -0
  360. package/src/routes/orchestrator-host-utilization.ts +2 -2
  361. package/src/routes/orchestrator-proxy.ts +2 -2
  362. package/src/routes/orchestrator.ts +27 -18
  363. package/src/routes/pairs.ts +8 -8
  364. package/src/routes/project-profile-instructions.ts +1 -1
  365. package/src/routes/project-trust.ts +1 -1
  366. package/src/routes/projects.ts +16 -16
  367. package/src/routes/prompt-templates.ts +12 -12
  368. package/src/routes/provider-quotas.ts +10 -10
  369. package/src/routes/run-command.ts +1 -1
  370. package/src/routes/secrets-backup.ts +2 -2
  371. package/src/routes/secrets-import.ts +1 -1
  372. package/src/routes/secrets-vault.ts +7 -7
  373. package/src/routes/settings.ts +1 -1
  374. package/src/routes/shipping.ts +9 -1
  375. package/src/routes/spawn-policy.ts +8 -7
  376. package/src/routes/sse.ts +2 -2
  377. package/src/routes/team-templates.ts +7 -7
  378. package/src/routes/teams.ts +10 -10
  379. package/src/routes/tokens.ts +18 -17
  380. package/src/routes/users.ts +24 -24
  381. package/src/routes/viewer-read.ts +3 -3
  382. package/src/routes/web-tool-calls.ts +4 -4
  383. package/src/routes/workflows.ts +2 -2
  384. package/src/routes/workspaces.ts +17 -16
  385. package/src/routing-policy-push.ts +6 -6
  386. package/src/runtime-grant.ts +17 -11
  387. package/src/runtime-tokens.ts +20 -28
  388. package/src/secrets-broker/config.ts +1 -1
  389. package/src/secrets-broker/service.ts +2 -2
  390. package/src/security.ts +3 -1
  391. package/src/self-resume-carry.ts +21 -110
  392. package/src/self-resume-supersede.ts +4 -3
  393. package/src/self-resume.ts +54 -66
  394. package/src/server-background.ts +1 -1
  395. package/src/server.ts +21 -22
  396. package/src/services/agent-action.ts +12 -31
  397. package/src/services/agent-effort.ts +7 -32
  398. package/src/services/agent-hang-watchdog-job.ts +2 -2
  399. package/src/services/agent-heartbeat.ts +166 -0
  400. package/src/services/agent-reporting.ts +1 -1
  401. package/src/services/browser-inventory.ts +3 -3
  402. package/src/services/browser-session-state.ts +3 -2
  403. package/src/services/browser-session.ts +21 -27
  404. package/src/services/bus-command-update.ts +9 -9
  405. package/src/services/checkout-refresh-state.ts +1 -0
  406. package/src/services/checkout-refresh.test-fixture.ts +3 -2
  407. package/src/services/command-host.ts +7 -2
  408. package/src/services/coordinator-digest.ts +3 -2
  409. package/src/services/dispatch-command.ts +12 -13
  410. package/src/services/effective-launch-driver.ts +14 -9
  411. package/src/services/host-changed-paths.test-fixture.ts +5 -6
  412. package/src/services/host-project-readiness.ts +2 -2
  413. package/src/services/host-providers.ts +1 -1
  414. package/src/services/host-utilization.ts +9 -9
  415. package/src/services/idle-agent-digest.ts +17 -12
  416. package/src/services/idle-epics.ts +4 -4
  417. package/src/services/interrupt-agent.ts +12 -9
  418. package/src/services/issue-activity.ts +3 -3
  419. package/src/services/issue-associations.ts +15 -18
  420. package/src/services/issue-lifecycle-comments.ts +3 -2
  421. package/src/services/issue-lifecycle.ts +14 -13
  422. package/src/services/issue-refs.ts +4 -5
  423. package/src/services/kernel-timers-cutover-chaos-worker.ts +1 -1
  424. package/src/services/kernel-timers-ingress-chaos-worker.ts +6 -1
  425. package/src/services/kernel-timers-ingress.ts +3 -3
  426. package/src/services/kernel-timers-message-authority-chaos-worker.ts +3 -10
  427. package/src/services/kernel-timers-operator-chaos-worker.ts +3 -2
  428. package/src/services/kernel-timers-outbox.ts +1 -1
  429. package/src/services/kernel-timers-stage10-operator.ts +1 -1
  430. package/src/services/kernel-timers.ts +4 -3
  431. package/src/services/land-gate-placement.ts +11 -2
  432. package/src/services/land-issue-relations.ts +5 -4
  433. package/src/services/land-restart-retry.ts +7 -6
  434. package/src/services/landed-ancestry.ts +6 -5
  435. package/src/services/legacy-landing-host.ts +4 -1
  436. package/src/services/legacy-landing-recovery.ts +8 -6
  437. package/src/services/managed-running.ts +17 -17
  438. package/src/services/memory-areas.ts +3 -3
  439. package/src/services/merge-pause.ts +9 -15
  440. package/src/services/operator-decisions.ts +37 -41
  441. package/src/services/orchestrator-registration-recovery.ts +6 -2
  442. package/src/services/orchestrator-upgrade.ts +14 -12
  443. package/src/services/permission-decision.ts +4 -3
  444. package/src/services/plan-ci-notice.ts +1 -1
  445. package/src/services/plan-conformance.ts +4 -4
  446. package/src/services/plan-dispatch-policy.ts +10 -3
  447. package/src/services/plan-dispatch.ts +35 -14
  448. package/src/services/plan-graph.ts +39 -261
  449. package/src/services/plan-import.ts +1 -1
  450. package/src/services/plan-live-bindings.ts +8 -37
  451. package/src/services/plan-task-create.ts +1 -1
  452. package/src/services/plan-terminal-refs.ts +2 -12
  453. package/src/services/plan-wake-digest.ts +8 -3
  454. package/src/services/profile-trust.ts +2 -2
  455. package/src/services/project.ts +11 -10
  456. package/src/services/prompt-templates.ts +6 -5
  457. package/src/services/provider-hold-nudge.ts +9 -9
  458. package/src/services/provider-hold-record.ts +13 -12
  459. package/src/services/provider-state-audit.ts +19 -18
  460. package/src/services/provisioning-harness/driver.ts +1 -1
  461. package/src/services/provisioning-harness/fixture-matrix.ts +3 -3
  462. package/src/services/provisioning-harness/lifecycle.ts +24 -22
  463. package/src/services/provisioning-harness/prepare.ts +16 -17
  464. package/src/services/rate-limit-resume.ts +10 -9
  465. package/src/services/red-main-auto-revert.ts +7 -5
  466. package/src/services/red-main-controller-deps.ts +20 -3
  467. package/src/services/red-main-incident.ts +3 -1
  468. package/src/services/red-main-quarantine.ts +2 -3
  469. package/src/services/register-agent.ts +22 -22
  470. package/src/services/restart-project-role.ts +1 -1
  471. package/src/services/restart-spawn.ts +17 -16
  472. package/src/services/review-publish.ts +7 -24
  473. package/src/services/review-ref-reconcile.ts +29 -38
  474. package/src/services/runtime-dependency-alert.ts +27 -0
  475. package/src/services/scheduler-command.ts +11 -9
  476. package/src/services/scheduler.ts +5 -5
  477. package/src/services/self-effort-grant.ts +5 -25
  478. package/src/services/send-message.ts +16 -33
  479. package/src/services/shutdown-agent.ts +17 -14
  480. package/src/services/spawn-agent.ts +12 -41
  481. package/src/services/spawn-chain-inspector.ts +1 -1
  482. package/src/services/spawn-cwd-placement.ts +21 -5
  483. package/src/services/spawn-issue-activity.ts +8 -6
  484. package/src/services/spawn-launch.ts +17 -1
  485. package/src/services/spawn-loss-escalation.ts +1 -1
  486. package/src/services/spawn-registration-watchdog.ts +2 -2
  487. package/src/services/spawn-repo-probe.ts +7 -5
  488. package/src/services/spawn-tree-cleanup.ts +7 -8
  489. package/src/services/steward-reaper.ts +4 -4
  490. package/src/services/task-context-hydration.ts +25 -1
  491. package/src/services/task-delivery.ts +20 -34
  492. package/src/services/task-entity.ts +40 -203
  493. package/src/services/task-issue-link.ts +13 -20
  494. package/src/services/task-issue-weave.ts +12 -11
  495. package/src/services/task-lifecycle.ts +27 -31
  496. package/src/services/task-repo-cwd.ts +37 -0
  497. package/src/services/task-review-hold.ts +4 -17
  498. package/src/services/task-semantic-events.ts +13 -11
  499. package/src/services/task-state-reconcile.ts +3 -4
  500. package/src/services/task-validation.ts +2 -2
  501. package/src/services/team-templates.ts +5 -5
  502. package/src/services/team.ts +31 -98
  503. package/src/services/terminal-provider-exit.ts +6 -5
  504. package/src/services/timer-message-fire-chaos-worker.ts +7 -3
  505. package/src/services/timer-message-fire-outbox.ts +1 -1
  506. package/src/services/transient-agent-reaper.ts +22 -19
  507. package/src/services/turn-reconcile-audit.ts +9 -9
  508. package/src/services/user-onboarding.ts +8 -6
  509. package/src/services/user-profile.ts +6 -9
  510. package/src/services/work-finality.ts +16 -4
  511. package/src/services/workflow-auto-start.ts +2 -1
  512. package/src/services/workflow-caller.ts +61 -4
  513. package/src/services/workflow-child-proof-worker.ts +1 -1
  514. package/src/services/workflow-control-proof-worker.ts +1 -1
  515. package/src/services/workflow-coordinator.ts +8 -2
  516. package/src/services/workflow-decisions.ts +5 -5
  517. package/src/services/workflow-deferred-cleanup.ts +1 -1
  518. package/src/services/workflow-effect-driver.ts +42 -19
  519. package/src/services/workflow-effects.ts +41 -27
  520. package/src/services/workflow-pins.ts +7 -4
  521. package/src/services/workflow-reconcile.ts +1 -0
  522. package/src/services/workflow-resume-pins.ts +3 -3
  523. package/src/services/workflow-routing-defaults.ts +18 -0
  524. package/src/services/workflow-run-view.ts +4 -3
  525. package/src/services/workflow-run.test-fixture.ts +1 -1
  526. package/src/services/workflow-runs.ts +34 -22
  527. package/src/services/workflow-supervisor-state.ts +21 -1
  528. package/src/services/workflow-supervisor.ts +4 -3
  529. package/src/services/workspace-recovery.ts +4 -3
  530. package/src/spawn-admission.ts +10 -2
  531. package/src/spawn-placement.ts +27 -9
  532. package/src/spawn-targets.ts +8 -8
  533. package/src/sse-agent-status.ts +15 -6
  534. package/src/sse.ts +49 -24
  535. package/src/startup-context-injection.ts +61 -57
  536. package/src/steward-handoff.ts +4 -3
  537. package/src/steward-policy-cleanup.ts +9 -8
  538. package/src/steward.ts +2 -2
  539. package/src/task-dispatch-live.ts +5 -2
  540. package/src/task-dispatcher.ts +2 -2
  541. package/src/token-db.ts +2 -2
  542. package/src/token-usage-async.ts +2 -4
  543. package/src/user-awaiting-reply.ts +5 -5
  544. package/src/workspace-actions.ts +24 -29
  545. package/src/workspace-auto-merge.ts +14 -12
  546. package/src/workspace-changed-paths-client.ts +16 -5
  547. package/src/workspace-cleanup-stale.ts +30 -7
  548. package/src/workspace-command-settle.ts +24 -16
  549. package/src/workspace-config.ts +1 -1
  550. package/src/workspace-conflict-resolver.ts +9 -7
  551. package/src/workspace-dead-owner-recovery.ts +5 -4
  552. package/src/workspace-escalation.ts +12 -11
  553. package/src/workspace-human-escalation.ts +3 -3
  554. package/src/workspace-land-gate-watchdog.ts +3 -3
  555. package/src/workspace-land-refusal.ts +20 -0
  556. package/src/workspace-land-stopped.ts +1 -0
  557. package/src/workspace-merge.ts +10 -26
  558. package/src/workspace-nothing-to-land-notice.ts +2 -2
  559. package/src/workspace-orphans.ts +18 -37
  560. package/src/workspace-pr-completion.ts +10 -8
  561. package/src/workspace-rekey.ts +3 -3
  562. package/src/workspace-steward-failure.ts +2 -2
  563. package/src/workspace-steward-wake.ts +2 -2
  564. package/public/assets/agent-liveness-CaNwK0Zf.js +0 -2
  565. package/public/assets/provider-display-DsuWMvVL.js +0 -2
  566. package/public/assets/run-card-CpKqRbhg.js +0 -2
  567. package/public/assets/shipping-B9YtnwtG.js +0 -2
  568. package/public/assets/store-DcClXLH0.js +0 -9
  569. package/runner/src/agent-runner/http-liveness.ts +0 -85
  570. package/src/db/on-loop-write-transaction.ts +0 -34
@@ -1,8 +1,9 @@
1
+ import { upsertProjectTrustApprovalAsync } from "./db/runtime-tail-async";
1
2
  import { createHash } from "node:crypto";
2
3
  import { resolve } from "node:path";
3
4
  import { shellEscape, ValidationError, type AgentProfile, type ProfileAssetCell, type ProfileProjectCells, type ProfileProjectGate, type ProfileProjectReviewMode, type ProfileProjectTrustScope, type Project } from "@humwick/sdk";
4
5
  import { rootsForProject, resolveProjectForCwd } from "./db/projects";
5
- import { getProjectTrustApproval, upsertProjectTrustApproval, type ProjectTrustApproval, type ProjectTrustCapability } from "./db/project-trust-approvals";
6
+ import { getProjectTrustApproval, type ProjectTrustApproval, type ProjectTrustCapability } from "./db/project-trust-approvals";
6
7
  import { observeCapabilityReview } from "./project-trust-fingerprint";
7
8
  import { canonicalRoot } from "./services/canonical-root";
8
9
  import { isPathWithinBase } from "./utils";
@@ -35,26 +36,26 @@ function repoKeyFor(cwd: string): string {
35
36
  /** Records `approvedValue` (a `sha256:<hex>` or `commit:<sha>`, matching `mode`) as trusted for
36
37
  * this (profile, repo, capability) — the dashboard/API one-click approve action. Format-validated
37
38
  * here so a malformed value can never be written through the trust store's only public writer. */
38
- export function approveProjectCapabilityReview(input: {
39
+ export async function approveProjectCapabilityReview(input: {
39
40
  profileName: string;
40
41
  repoKey: string;
41
42
  capability: ProjectCapability;
42
43
  mode: "fingerprint" | "commit";
43
44
  approvedValue: string;
44
45
  approvedBy: string;
45
- }): ProjectTrustApproval {
46
+ }): Promise<ProjectTrustApproval> {
46
47
  const prefix = input.mode === "commit" ? "commit:" : "sha256:";
47
48
  if (!input.approvedValue.startsWith(prefix)) {
48
49
  throw new ValidationError(`approved value must be prefixed "${prefix}" for ${input.mode} review`);
49
50
  }
50
- return upsertProjectTrustApproval({
51
+ return (await upsertProjectTrustApprovalAsync({
51
52
  profileName: input.profileName,
52
53
  repoKey: input.repoKey,
53
54
  capability: input.capability,
54
55
  reviewMode: input.mode,
55
56
  approvedValue: input.approvedValue,
56
57
  approvedBy: input.approvedBy,
57
- });
58
+ }));
58
59
  }
59
60
 
60
61
  /** Stable JSON is intentionally local to this small trust seam. The hash is an
@@ -142,13 +143,13 @@ export interface ProjectCapabilityGateOpts {
142
143
  pinnedMcpCommit?: string;
143
144
  }
144
145
 
145
- export function projectCapabilityGate(
146
+ export async function projectCapabilityGate(
146
147
  profile: AgentProfile,
147
148
  capability: ProjectCapability,
148
149
  cwd: string,
149
150
  registeredProject?: Project | null,
150
151
  opts?: ProjectCapabilityGateOpts,
151
- ): ProfileProjectGate {
152
+ ): Promise<ProfileProjectGate> {
152
153
  const project = profile.sources?.project;
153
154
  const cell = capabilityCell(profile, capability);
154
155
  if (!project || !cell?.enabled) {
@@ -238,7 +239,7 @@ export function projectCapabilityGate(
238
239
  // approved instead of failing closed, so shipping G3 does not instantly regress every
239
240
  // already-trusted profile. Only a SUBSEQUENT change (a different observed value) fails
240
241
  // closed from here on.
241
- upsertProjectTrustApproval({ profileName: profile.name, repoKey, capability, reviewMode: mode, approvedValue: observed, approvedBy: "system:grandfathered" });
242
+ (await upsertProjectTrustApprovalAsync({ profileName: profile.name, repoKey, capability, reviewMode: mode, approvedValue: observed, approvedBy: "system:grandfathered" }));
242
243
  return { allowed: true, reason: "allowed", detail: gateDetail(capability, `${scopeDetail} (grandfathered ${observed})`), observed, repoKey, reviewMode: mode };
243
244
  }
244
245
  // `commit` review has no grandfather: it is the stricter opt-in mode, so first encounter
@@ -254,9 +255,9 @@ export function projectCapabilityGate(
254
255
  /** Stamp the server's per-spawn decisions onto a cloned profile. The source cells
255
256
  * remain visible for truthful projection; the runner consumes only these decisions
256
257
  * for filesystem materialization. */
257
- export function applyProjectCapabilityGates(profile: AgentProfile, cwd: string, registeredProject?: Project | null, opts?: ProjectCapabilityGateOpts): AgentProfile {
258
+ export async function applyProjectCapabilityGates(profile: AgentProfile, cwd: string, registeredProject?: Project | null, opts?: ProjectCapabilityGateOpts): Promise<AgentProfile> {
258
259
  if (!profile.sources?.project) return profile;
259
- const hooks = projectCapabilityGate(profile, "hooks", cwd, registeredProject, opts);
260
- const mcp = projectCapabilityGate(profile, "mcp", cwd, registeredProject, opts);
260
+ const hooks = (await projectCapabilityGate(profile, "hooks", cwd, registeredProject, opts));
261
+ const mcp = (await projectCapabilityGate(profile, "mcp", cwd, registeredProject, opts));
261
262
  return { ...profile, projectGates: { hooks, mcp } };
262
263
  }
@@ -250,7 +250,7 @@ const DEFAULT_PROMPT_TEMPLATES = [
250
250
  "{{context}}",
251
251
  "Acceptance — done when:",
252
252
  "{{doneWhen}}",
253
- "",
253
+ "{{afterLand}}",
254
254
  "Linked issue spec (resolved server-side once — do NOT re-read GitHub):",
255
255
  "{{issues}}",
256
256
  "",
@@ -275,7 +275,7 @@ const DEFAULT_PROMPT_TEMPLATES = [
275
275
  "{{context}}",
276
276
  "Acceptance — done when:",
277
277
  "{{doneWhen}}",
278
- "",
278
+ "{{afterLand}}",
279
279
  "Linked issue spec (resolved server-side once — do NOT re-read GitHub):",
280
280
  "{{issues}}",
281
281
  "",
@@ -288,7 +288,7 @@ const DEFAULT_PROMPT_TEMPLATES = [
288
288
  "Latest steer (act on this now):",
289
289
  "{{steer}}",
290
290
  ),
291
- variables: ["taskId", "title", "status", "stage", "owner", "intent", "context", "doneWhen", "issues", "decisions", "history", "memory", "steer"],
291
+ variables: ["taskId", "title", "status", "stage", "owner", "intent", "context", "doneWhen", "afterLand", "issues", "decisions", "history", "memory", "steer"],
292
292
  },
293
293
  {
294
294
  slug: "context.advisory.warn",
@@ -51,27 +51,25 @@ export async function upsertProviderQuotaAsync(
51
51
  * Synchronous in-process compatibility wrapper for direct callers and existing tests. Runs the writer
52
52
  * body directly (no gateway hop) and fires the returned effects synchronously.
53
53
  */
54
- export function upsertProviderQuota(input: ProviderQuotaUpdateInput, now = Date.now()): ProviderQuotaRecord {
55
- const result = upsertProviderQuotaInTx(input, now);
56
- invalidateProviderQuotaMatrixCache();
54
+ export async function upsertProviderQuota(input: ProviderQuotaUpdateInput, now = Date.now()): Promise<ProviderQuotaRecord> {
55
+ const result = await upsertProviderQuotaAsync(input, { now });
57
56
  if (result.outcome.kind !== "stored") throw new Error("provider quota lease not held");
58
- deliverProviderQuotaEffects(result, { isolate: false });
59
57
  return result.outcome.record;
60
58
  }
61
59
 
62
60
  /** Fire each event+notification pair in production order; `isolate` logs (not throws) per-pair faults. */
63
- function deliverProviderQuotaEffects(result: ProviderQuotaUpsertOpResult, options: { isolate: boolean }): void {
61
+ async function deliverProviderQuotaEffects(result: ProviderQuotaUpsertOpResult, options: { isolate: boolean }): Promise<void> {
64
62
  for (const effect of result.advisory?.effects ?? []) {
65
63
  if (options.isolate) {
66
64
  try {
67
65
  emitRelayEvent(effect.event);
68
- if (effect.notification) routeNotification(effect.notification);
66
+ if (effect.notification) await routeNotification(effect.notification);
69
67
  } catch (error) {
70
68
  console.error("provider quota post-commit effect failed", error);
71
69
  }
72
70
  } else {
73
71
  emitRelayEvent(effect.event);
74
- if (effect.notification) routeNotification(effect.notification);
72
+ if (effect.notification) await routeNotification(effect.notification);
75
73
  }
76
74
  }
77
75
  }
@@ -1,5 +1,5 @@
1
1
  import { isRecord, stringValue } from "@humwick/sdk";
2
- import { createActivityEventWithResult } from "./db";
2
+ import { createActivityEventByClientIdAsync } from "./db/activity-async";
3
3
  import { emitRelayEvent } from "./events";
4
4
 
5
5
  interface HasMeta {
@@ -28,7 +28,7 @@ function numberValue(value: unknown): number | undefined {
28
28
  return typeof value === "number" && Number.isFinite(value) ? value : undefined;
29
29
  }
30
30
 
31
- export function auditRunnerTimelineEvent(agentId: string, timelineEvent: ProviderTimelineEvent | null): void {
31
+ export async function auditRunnerTimelineEvent(agentId: string, timelineEvent: ProviderTimelineEvent | null): Promise<void> {
32
32
  if (!timelineEvent) return;
33
33
  const metadata = isRecord(timelineEvent.metadata) ? timelineEvent.metadata : {};
34
34
  if (metadata.source !== "runner") return;
@@ -41,10 +41,7 @@ export function auditRunnerTimelineEvent(agentId: string, timelineEvent: Provide
41
41
  const body = stringValue(timelineEvent.body);
42
42
  const icon = stringValue(timelineEvent.icon) ?? "ti-activity";
43
43
  try {
44
- // #1912 §4 retained: this runs inside the synchronous bus status-frame callback. Turning this
45
- // into an unawaited gateway write would reorder/drop the audit relative to the frame; moving
46
- // the whole hot status ingress is the later owner.
47
- const result = createActivityEventWithResult({
44
+ const result = (await createActivityEventByClientIdAsync({
48
45
  clientId: `runner-timeline-${agentId}-${id}`,
49
46
  kind: "state",
50
47
  title,
@@ -60,7 +57,7 @@ export function auditRunnerTimelineEvent(agentId: string, timelineEvent: Provide
60
57
  timelineId: id,
61
58
  timelineTimestamp: timestamp,
62
59
  },
63
- });
60
+ }));
64
61
  // A repeated frame may still carry the same event during reconnect/retry. The durable activity
65
62
  // clientId dedup is authoritative; only a newly inserted row owns an activity.created edge.
66
63
  if (!result.created) return;
@@ -6,8 +6,8 @@ import { getSpawnCapableAgentIds } from "./routing-policy-push";
6
6
  import { renderBandTransition } from "./quota-band-transition";
7
7
  import type { ProviderBandWindow, QuotaBand } from "./quota-band-projection";
8
8
 
9
- export function deliverBandTransition(input: { provider: string; window: ProviderBandWindow; previousBand: QuotaBand; recommendedAction: string; now: number }): void {
9
+ export async function deliverBandTransition(input: { provider: string; window: ProviderBandWindow; previousBand: QuotaBand; recommendedAction: string; now: number }): Promise<void> {
10
10
  const effect = renderBandTransition(input, getSpawnCapableAgentIds());
11
11
  emitRelayEvent(effect.event);
12
- if (effect.notification) routeNotification(effect.notification);
12
+ if (effect.notification) await routeNotification(effect.notification);
13
13
  }
@@ -1,6 +1,7 @@
1
+ import { createCommandAsync } from "./commands-write";
1
2
  import { writeChildEnv } from "@humwick/sdk/env";
2
3
  import { randomUUID } from "node:crypto";
3
- import { createCommand, type CreateCommandWriteArgs } from "./commands-db";
4
+ import { type CreateCommandWriteArgs } from "./commands-db";
4
5
  import { effectiveProviderCatalogListAsync, listOrchestrators } from "./db";
5
6
  import { resolveProviderSelection } from "@humwick/sdk/provider-catalog";
6
7
  import { getRecipeAsync } from "./recipe-loader";
@@ -148,13 +149,13 @@ export async function stopRecipe(instanceId: string, stoppedBy = "cli"): Promise
148
149
  // canceled by beginStop; a claimed one is already ordered before this stop and cannot be
149
150
  // targeted with an agent.shutdown command until its spawn result supplies a real agent id.
150
151
  if (agent.agentId.startsWith("pending:")) continue;
151
- const command = createCommand({
152
+ const command = (await createCommandAsync({
152
153
  type: "agent.shutdown",
153
154
  source: stoppedBy,
154
155
  target: agent.agentId,
155
156
  params: { recipeInstanceId: instance.id, role: agent.role },
156
157
  ttlMs: 30_000,
157
- });
158
+ }));
158
159
  commands.push(command);
159
160
  await updateRecipeAgentInstanceAsync(instance.id, agent.agentId, "stopping");
160
161
  }
@@ -1,4 +1,5 @@
1
- import { getConfig, setConfig } from "./config-store";
1
+ import { setConfigAsync } from "./config-store-write";
2
+ import { getConfig } from "./config-store";
2
3
  import {
3
4
  RETENTION_CONFIG_DEFAULTS,
4
5
  RETENTION_KEY,
@@ -27,6 +28,6 @@ export function getRetentionConfigEntry(): ConfigEntry<RetentionConfig> {
27
28
  };
28
29
  }
29
30
 
30
- export function setRetentionConfig(value: unknown, updatedBy?: string): ConfigEntry<RetentionConfig> {
31
- return setConfig(RETENTION_NAMESPACE, RETENTION_KEY, value as RetentionConfig, updatedBy);
31
+ export async function setRetentionConfig(value: unknown, updatedBy?: string): Promise<ConfigEntry<RetentionConfig>> {
32
+ return (await setConfigAsync(RETENTION_NAMESPACE, RETENTION_KEY, value as RetentionConfig, updatedBy));
32
33
  }
@@ -1,6 +1,7 @@
1
+ import { createCommandAsync } from "./commands-write";
1
2
  import { isRecord } from "@humwick/sdk";
2
3
  import { planSend } from "./agent-ref";
3
- import { createCommand } from "./commands-db";
4
+
4
5
  import { getSpawnPolicy } from "./config-store";
5
6
  import { deferLandSettleSideEffect } from "./land-settle-dispatch";
6
7
  import { getLifecycleManager } from "./lifecycle-manager";
@@ -68,7 +69,7 @@ export async function handleReviewerMergeResult(command: Command, result: Record
68
69
  // it must reach the reviewer even if they're offline a while — not a bystander notice. So, like the
69
70
  // landing receipt, it is written SYNCHRONOUSLY on the settle path; only the bystander announcement
70
71
  // ping and the eager spawn defer off the hot path below.
71
- routeNotification({
72
+ await routeNotification({
72
73
  type: "workspace.review_request",
73
74
  scope: { workspaceId: workspace.id, repoRoot: workspace.repoRoot },
74
75
  recipients: [target],
@@ -102,8 +103,8 @@ export async function handleReviewerMergeResult(command: Command, result: Record
102
103
  // (`handleReviewerMergeResult` runs inside `settleWorkspaceMergeCommand`). They defer off the hot
103
104
  // path; the spawn self-heals via `reconcilePolicy` even if a deferred dispatch is missed, and the
104
105
  // review-request obligation it consumes is already durably queued synchronously above.
105
- deferLandSettleSideEffect("reviewer-review-request", () => {
106
- emitWorkspaceTaskSemanticNotifications({
106
+ deferLandSettleSideEffect("reviewer-review-request", async () => {
107
+ await emitWorkspaceTaskSemanticNotifications({
107
108
  workspace: reviewWorkspace,
108
109
  transition: "review-requested",
109
110
  actor: "reviewer-pipeline",
@@ -144,7 +145,7 @@ export async function handleReviewerPipelineScan(
144
145
 
145
146
  if (decision === "APPROVED") {
146
147
  if (!prNumber && !prUrl) return { skipped: "missing-pr" };
147
- const command = createCommand({
148
+ const command = (await createCommandAsync({
148
149
  type: "workspace.pr-arm-auto-merge",
149
150
  source: "system",
150
151
  target: orchestratorAgentId,
@@ -161,7 +162,7 @@ export async function handleReviewerPipelineScan(
161
162
  requestedBy: "reviewer-pipeline",
162
163
  requestedAt: now,
163
164
  },
164
- });
165
+ }));
165
166
  await patchWorkspaceMetadataAsync(workspace.id, {
166
167
  autoMergeArmed: true,
167
168
  autoMergeArmCommandId: command.id,
@@ -176,7 +177,7 @@ export async function handleReviewerPipelineScan(
176
177
  const last = text(workspace.metadata.lastReviewDecision);
177
178
  if (last === "CHANGES_REQUESTED") return { skipped: "changes-requested-already-notified" };
178
179
  const notifiedOwner = workspace.ownerAgentId
179
- ? notifyReviewChangesRequested(workspace, preview, prUrl, prNumber)
180
+ ? await notifyReviewChangesRequested(workspace, preview, prUrl, prNumber)
180
181
  : undefined;
181
182
  await patchWorkspaceMetadataAsync(workspace.id, {
182
183
  lastReviewDecision: decision,
@@ -198,17 +199,17 @@ function workspaceActiveArm(workspace: WorkspaceRecord): boolean {
198
199
  return workspace.metadata.autoMergeArmed === true || typeof workspace.metadata.autoMergeArmCommandId === "string";
199
200
  }
200
201
 
201
- function notifyReviewChangesRequested(
202
+ async function notifyReviewChangesRequested(
202
203
  workspace: WorkspaceRecord,
203
204
  preview: WorkspaceMergePreview,
204
205
  prUrl: string | undefined,
205
206
  prNumber: number | undefined,
206
- ): string | undefined {
207
+ ): Promise<string | undefined> {
207
208
  const target = workspace.ownerAgentId;
208
209
  if (!target) return undefined;
209
210
  // Durable (ttl null): the owner must learn changes were requested on THEIR workspace even after
210
211
  // being offline — store-ahead, not a freshness-gated bystander notice.
211
- routeNotification({
212
+ await routeNotification({
212
213
  type: "workspace.review_changes_requested",
213
214
  scope: { workspaceId: workspace.id, repoRoot: workspace.repoRoot, author: target },
214
215
  recipients: [target],
@@ -1,7 +1,7 @@
1
1
  import { scopeResourceReads } from "./viewer-read";
2
- import { captureSyncFrame, runWithLoopCallsite } from "../loop-block-attribution";
2
+ import { captureSyncFrame } from "../loop-block-attribution";
3
3
  import { withRelayEventDrain } from "../relay-event-drain";
4
- import { trackCaller } from "../hub-metrics";
4
+ import { runInFrame } from "../hub-metrics";
5
5
  import { error, type Handler } from "./_shared";
6
6
  import type { LoopCallsiteContext } from "../loop-block-attribution";
7
7
 
@@ -42,8 +42,8 @@ export function runMatchedRoute(
42
42
  req: Request,
43
43
  finish: (response: Response) => Promise<Response>,
44
44
  ): Promise<Response> {
45
- return runWithLoopCallsite(matched.loop.scope, () => trackCaller(matched.loop.scope.callsite, () => withRelayEventDrain(async () =>
46
- finish(await captureSyncFrame(matched.loop.frame, () => matched.handler(req, matched.params))))));
45
+ return runInFrame(matched.loop.scope, () => withRelayEventDrain(async () =>
46
+ finish(await captureSyncFrame(matched.loop.frame, () => matched.handler(req, matched.params)))));
47
47
  }
48
48
 
49
49
  export function matchRoutes(
@@ -1,9 +1,10 @@
1
+ import { sendMessageWithResultAsync } from "../db/message-send";
1
2
  import { hasPresentedCredential, relayHeader, canonicalHumanAgentId, DEFAULT_USER_ID, errMessage, fireAndForget, isHumanAgentId, isRecord, userIdFromAddress, userSinkId } from "@humwick/sdk";
2
3
  import { authorityDenied } from "../authority-audit";
3
4
  // Auto-split from routes.ts (#299). Domain: _shared.
4
5
  import { agentVisibleTo, visibleAgentIds, viewerScope, type ViewerScope } from "../db/viewer-scope";
5
6
  import { MAX_BODY_BYTES, getIntegrationTokens } from "../config";
6
- import { ValidationError, createActivityEventAsync, createCallbackDeliveryAsync, finishCallbackDeliveryAsync, getAgent, getTaskAsync, normalizeReactionEmoji, sendMessageWithResult } from "../db";
7
+ import { ValidationError, createActivityEventAsync, createCallbackDeliveryAsync, finishCallbackDeliveryAsync, getAgent, getTaskAsync, normalizeReactionEmoji } from "../db";
7
8
  import { cleanEpoch, cleanString, optionalEnum } from "../validation";
8
9
  import { emitActivityEvent, emitMessageQueued, emitNewMessage } from "../sse";
9
10
  import { authorizeAgentForUser, type AgentAction } from "../agent-authz";
@@ -25,19 +26,19 @@ export const json = (data: unknown, status = 200) =>
25
26
  export const error = (msg: string, status = 400) =>
26
27
  json({ error: msg }, status);
27
28
 
28
- export function authorizeRoute(req: Request, check: Parameters<typeof isRequestAuthorizedFor>[1]): Response | null {
29
+ export async function authorizeRoute(req: Request, check: Parameters<typeof isRequestAuthorizedFor>[1]): Promise<Response | null> {
29
30
  if (!hasPresentedCredential(req)) return null;
30
- return isRequestAuthorizedFor(req, check) ? null : authorityDenied(req, "forbidden");
31
+ return isRequestAuthorizedFor(req, check) ? null : (await authorityDenied(req, "forbidden"));
31
32
  }
32
33
 
33
34
  /** A write about agent `agentId` by that agent's own credential: the agent, its agent:write check and the parsed body. */
34
35
  export async function agentWriteRequest(req: Request, agentId: string): Promise<{ agent: NonNullable<ReturnType<typeof getAgent>>; body: Record<string, unknown> } | Response> {
35
36
  const agent = getAgent(agentId);
36
37
  if (!agent) return error("agent not found", 404);
37
- const denied = authorizeRoute(req, {
38
+ const denied = (await authorizeRoute(req, {
38
39
  scope: "agent:write",
39
40
  resource: { agentId: agent.id, policyName: metaString(agent.meta, "policyName"), spawnRequestId: metaString(agent.meta, "spawnRequestId") },
40
- });
41
+ }));
41
42
  if (denied) return denied;
42
43
  const parsed = await parseBody<Record<string, unknown>>(req);
43
44
  if (!parsed.ok) return error(parsed.error, parsed.status);
@@ -49,9 +50,9 @@ export async function agentWriteRequest(req: Request, agentId: string): Promise<
49
50
  // `command:fleet`-scoped token is authorized here without the sandbox constraint; every other
50
51
  // caller falls back to the normal constrained `command:write` check. Use ONLY at those three call
51
52
  // sites — everywhere else must keep going through `authorizeRoute`.
52
- export function authorizeFleetRoute(req: Request, resource?: Parameters<typeof isFleetActionAuthorized>[1]): Response | null {
53
+ export async function authorizeFleetRoute(req: Request, resource?: Parameters<typeof isFleetActionAuthorized>[1]): Promise<Response | null> {
53
54
  if (!hasPresentedCredential(req)) return null;
54
- return isFleetActionAuthorized(req, resource) ? null : authorityDenied(req, "forbidden");
55
+ return isFleetActionAuthorized(req, resource) ? null : (await authorityDenied(req, "forbidden"));
55
56
  }
56
57
 
57
58
  export function authAuditMetadata(req: Request): Record<string, unknown> {
@@ -181,8 +182,8 @@ export function requestUserAddress(req: Request): string {
181
182
  * Single-user worlds fail-open inside {@link authorizeAgentForUser}, so existing routes are
182
183
  * unchanged until #389 upgrades {@link requestUserId} to the real session user.
183
184
  */
184
- export function authorizeAgentRoute(req: Request, agentId: string, action: AgentAction, auditAction: string = action): Response | null {
185
- return authorizeAgentForUser(requestUserId(req), agentId, action) ? null : authorityDenied(req, "agent visibility or role", 403, agentId, auditAction);
185
+ export async function authorizeAgentRoute(req: Request, agentId: string, action: AgentAction, auditAction: string = action): Promise<Response | null> {
186
+ return authorizeAgentForUser(requestUserId(req), agentId, action) ? null : (await authorityDenied(req, "agent visibility or role", 403, agentId, auditAction));
186
187
  }
187
188
 
188
189
  /** Machine callers retain their existing reach; user sessions share one read scope. */
@@ -468,7 +469,7 @@ function reactionNotificationSender(parent: Message, actorId: string): string {
468
469
  return parent.channel && getAgent(parent.channel) ? parent.channel : "user";
469
470
  }
470
471
 
471
- export function sendReactionNotificationToAuthor(parent: Message, actorId: string, emoji: string, action: "add" | "remove"): void {
472
+ export async function sendReactionNotificationToAuthor(parent: Message, actorId: string, emoji: string, action: "add" | "remove"): Promise<void> {
472
473
  if (isHumanAgentId(parent.from) || parent.from === "system") return;
473
474
  const targetAgent = getAgent(parent.from);
474
475
  if (!targetAgent || targetAgent.kind === "channel") return;
@@ -477,7 +478,7 @@ export function sendReactionNotificationToAuthor(parent: Message, actorId: strin
477
478
  const now = Date.now();
478
479
  const actor = reactionActorView(actorId);
479
480
  const verb = action === "remove" ? "removed reaction" : "reacted";
480
- const result = sendMessageWithResult({
481
+ const result = (await sendMessageWithResultAsync({
481
482
  from,
482
483
  to: parent.from,
483
484
  kind: "system",
@@ -505,7 +506,7 @@ export function sendReactionNotificationToAuthor(parent: Message, actorId: strin
505
506
  },
506
507
  },
507
508
  },
508
- });
509
+ }));
509
510
  if (result.created) {
510
511
  if (result.message.deliveryStatus === "queued") emitMessageQueued(result.message);
511
512
  else emitNewMessage(result.message);
@@ -13,12 +13,12 @@ import { agentWriteRequest, authAuditMetadata, authorizeAgentRoute, authorizeRou
13
13
  export async function postAgentEffortAction(req: Request, agentId: string, body: Record<string, unknown>): Promise<Response> {
14
14
  const agent = getAgent(agentId);
15
15
  if (!agent) return error("agent not found", 404);
16
- const driveDenied = authorizeAgentRoute(req, agent.id, "drive", "effort");
16
+ const driveDenied = (await authorizeAgentRoute(req, agent.id, "drive", "effort"));
17
17
  if (driveDenied) return driveDenied;
18
- const denied = authorizeRoute(req, {
18
+ const denied = (await authorizeRoute(req, {
19
19
  scope: "agent:write",
20
20
  resource: { agentId: agent.id, policyName: metaString(agent.meta, "policyName"), spawnRequestId: metaString(agent.meta, "spawnRequestId") },
21
- });
21
+ }));
22
22
  if (denied) return denied;
23
23
  try {
24
24
  const result = await dispatchAgentAction({
@@ -54,12 +54,12 @@ export const postAgentEffortObservedRoute: Handler = async (req, params) => {
54
54
  try {
55
55
  const version = body.version;
56
56
  if (typeof version !== "number" || !Number.isSafeInteger(version) || version < 1) throw new ValidationError("version must be a positive integer");
57
- const observed = reportEffortObserved(agent.id, {
57
+ const observed = (await reportEffortObserved(agent.id, {
58
58
  instanceId: cleanString(body.instanceId, "instanceId", { required: true, max: 200 })!,
59
59
  version,
60
60
  effort: cleanString(body.effort, "effort", { required: true, max: 32 })!,
61
61
  previousEffort: cleanString(body.previousEffort, "previousEffort", { max: 32 }) ?? null,
62
- });
62
+ }));
63
63
  return json(observed);
64
64
  } catch (e) {
65
65
  if (e instanceof ValidationError || e instanceof EffortReportRejected) return error(e.message, 400);
@@ -0,0 +1,23 @@
1
+ import type { HeartbeatResult, ProviderQuotaUpdateInput } from "@humwick/sdk";
2
+ import { acquireProviderQuotaLeaseAsync } from "../db";
3
+ import { getProviderQuotaConfig } from "../provider-quota-config-store";
4
+ import { upsertProviderQuotaAsync } from "../provider-quota-async";
5
+ import { emitRelayEvent } from "../events";
6
+
7
+ /** Same lease and writer as standalone quota reports, with config resolved on the hub (#3608). */
8
+ export async function publishHeartbeatQuota(input: ProviderQuotaUpdateInput, leaseToken?: string): Promise<NonNullable<HeartbeatResult["providerQuota"]>> {
9
+ const config = getProviderQuotaConfig(input.provider);
10
+ if (!config.enabled) return { reported: false, retryAfterMs: 60_000 };
11
+ const holder = `runner:${input.sourceAgentId}`;
12
+ const lease = await acquireProviderQuotaLeaseAsync({
13
+ provider: input.provider, accountKey: input.accountKey, orchestratorId: holder, leaseToken,
14
+ ttlMs: Math.min(10 * 60_000, config.pollIntervalMs + 60_000),
15
+ });
16
+ if (!lease.acquired || !lease.lease) return { reported: false, retryAfterMs: Math.min(lease.retryAfterMs ?? config.pollIntervalMs, config.pollIntervalMs) };
17
+ const result = await upsertProviderQuotaAsync(input, { requiredLeaseHolder: holder });
18
+ if (result.outcome.kind === "stored") {
19
+ const record = result.outcome.record;
20
+ emitRelayEvent({ type: "provider-quota.updated", source: "server", subject: `${record.provider}:${record.accountKey}`, data: {} });
21
+ }
22
+ return { reported: result.outcome.kind === "stored", retryAfterMs: config.pollIntervalMs, leaseToken: lease.lease.leaseToken };
23
+ }
@@ -9,7 +9,7 @@ export const putAgentKeep: Handler = async (req, params) => {
9
9
  const parsed = await parseBody<unknown>(req);
10
10
  if (!parsed.ok) return error(parsed.error, parsed.status);
11
11
  if (!isRecord(parsed.body)) return error("keep required");
12
- const denied = authorizeRoute(req, { scope: "agent:write" });
12
+ const denied = (await authorizeRoute(req, { scope: "agent:write" }));
13
13
  if (denied) return denied;
14
14
  try {
15
15
  const result = await setAgentKeep({
@@ -6,7 +6,7 @@ import { cleanString } from "../validation";
6
6
  import { authorizeAgentRoute, authorizeRoute, error, json } from "./_shared";
7
7
 
8
8
  export async function postAgentReportingAction(req: Request, agentId: string, body: Record<string, unknown>): Promise<Response> {
9
- const denied = authorizeAgentRoute(req, agentId, "drive") ?? authorizeRoute(req, { scope: "agent:write", resource: { agentId } });
9
+ const denied = (await authorizeAgentRoute(req, agentId, "drive")) ?? (await authorizeRoute(req, { scope: "agent:write", resource: { agentId } }));
10
10
  if (denied) return denied;
11
11
  try {
12
12
  return json({ ok: true, ...await setAgentReportVerbosity({ agentId, reportVerbosity: body.reportVerbosity, reason: cleanString(body.reason, "reason", { max: 500 }), requestedVia: "http" }, authContextFromRequest(req)) });
@@ -9,10 +9,10 @@ import { ShutdownAuthError, ShutdownTargetError } from "../services/shutdown-age
9
9
  import { authAuditMetadata, authorizeAgentRoute, authorizeRoute, dashboardAttribution, error, json, metaString, parseBody, requestUserAddress, type Handler } from "./_shared";
10
10
  import { isRecord } from "../types";
11
11
 
12
- export const getAgentSelfEffort: Handler = (req, params) => {
12
+ export const getAgentSelfEffort: Handler = async (req, params) => {
13
13
  const agent = getAgent(params.id!);
14
14
  if (!agent) return error("agent not found", 404);
15
- const denied = authorizeAgentRoute(req, agent.id, "view");
15
+ const denied = (await authorizeAgentRoute(req, agent.id, "view"));
16
16
  if (denied) return denied;
17
17
  return json({ agentId: agent.id, selfEffort: spawnSelfEffortPolicy(agent) ?? null });
18
18
  };
@@ -24,12 +24,12 @@ export const putAgentSelfEffort: Handler = async (req, params) => {
24
24
  const body = parsed.body;
25
25
  const agent = getAgent(params.id!);
26
26
  if (!agent) return error("agent not found", 404);
27
- const driveDenied = authorizeAgentRoute(req, agent.id, "drive");
27
+ const driveDenied = (await authorizeAgentRoute(req, agent.id, "drive"));
28
28
  if (driveDenied) return driveDenied;
29
- const denied = authorizeRoute(req, {
29
+ const denied = (await authorizeRoute(req, {
30
30
  scope: "agent:write",
31
31
  resource: { agentId: agent.id, policyName: metaString(agent.meta, "policyName"), spawnRequestId: metaString(agent.meta, "spawnRequestId") },
32
- });
32
+ }));
33
33
  if (denied) return denied;
34
34
  try {
35
35
  const result = await grantSelfEffort({