@humwick/server 0.130.2 → 0.130.4

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 (587) 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 +175 -4
  8. package/package.json +8 -7
  9. package/public/assets/{MessageBubble-BWLqMGKG.js → MessageBubble-BOkmEvgZ.js} +2 -2
  10. package/public/assets/{PlanGraphPanel-3TlIQpjk.js → PlanGraphPanel-BkaDJp0r.js} +2 -2
  11. package/public/assets/{TraceView-Wimm0Czv.js → TraceView-B99Uu2yT.js} +2 -2
  12. package/public/assets/{VaultDecisionCard-Bau_vNax.js → VaultDecisionCard-DUIfTTFF.js} +2 -2
  13. package/public/assets/{activity-CrSurn-r.js → activity-ZIX0N1El.js} +2 -2
  14. package/public/assets/{agent-lineage-CknAJKcb.js → agent-lineage-kq9TPYFw.js} +2 -2
  15. package/public/assets/agent-liveness-DSQY1Aa_.js +2 -0
  16. package/public/assets/{agent-name-DKbiIhBo.js → agent-name-C_7F4DFR.js} +2 -2
  17. package/public/assets/{agent-profiles-DwF6EQ4R.js → agent-profiles-BNOcrGcY.js} +2 -2
  18. package/public/assets/{agent-project-badge-Diz4Sjjb.js → agent-project-badge-B6yAh70a.js} +2 -2
  19. package/public/assets/{agent-tools-CRhpRQza.js → agent-tools-CcrhmOzF.js} +2 -2
  20. package/public/assets/{agent-type-icon-LrUEU3lB.js → agent-type-icon-CXSLrKiq.js} +2 -2
  21. package/public/assets/{agents-B-v66C-4.js → agents-DIZG97_X.js} +2 -2
  22. package/public/assets/{analytics-BqCb-LKi.js → analytics-rasmoPjR.js} +2 -2
  23. package/public/assets/{artifact-viewer-kf4pGuAR.js → artifact-viewer-tBpTrEPb.js} +2 -2
  24. package/public/assets/{artifacts-DJevXcvg.js → artifacts-BNkrynP1.js} +2 -2
  25. package/public/assets/{artifacts-D32zyw4Y.js → artifacts-Bjq-ZyBA.js} +2 -2
  26. package/public/assets/{automation-BpRajx_5.js → automation-Cx422L3L.js} +2 -2
  27. package/public/assets/{backlog-D_UjTdzX.js → backlog-RuFQ8PUu.js} +2 -2
  28. package/public/assets/{busy-health-N3VEh4ao.js → busy-health-BvNQ9g5x.js} +2 -2
  29. package/public/assets/{channels-9jopungq.js → channels-DNbKAS0I.js} +2 -2
  30. package/public/assets/{chat-CSXrTB3C.js → chat-Bp3Fx73h.js} +3 -3
  31. package/public/assets/{code-preview-p1NnmqK0.js → code-preview-KIRZA6cz.js} +2 -2
  32. package/public/assets/{connectors-CZdqlDNL.js → connectors-k7vO4vvc.js} +2 -2
  33. package/public/assets/{cosmos-BgdsE4dG.js → cosmos-BuVoq1aw.js} +2 -2
  34. package/public/assets/{crate-agent-30aXTKva.js → crate-agent-irqlt4NH.js} +2 -2
  35. package/public/assets/{dependency-graph-B_jvw2GE.js → dependency-graph-D_rurNBz.js} +2 -2
  36. package/public/assets/{deploys-DoN6bAb5.js → deploys-yzZqIpxE.js} +2 -2
  37. package/public/assets/{display-BrKWFGJz.js → display-BemJG1f_.js} +2 -2
  38. package/public/assets/{files-D6XEu8Ng.js → files-DXWcrxOz.js} +2 -2
  39. package/public/assets/{fleet-C7jQWbw2.js → fleet-TEuOCZXE.js} +2 -2
  40. package/public/assets/{fleet-metrics-BiDs3MLx.js → fleet-metrics-BGoDAFI-.js} +2 -2
  41. package/public/assets/{formatted-body-impl-DyG0WsQS.js → formatted-body-impl-BB9eq9nN.js} +2 -2
  42. package/public/assets/{formatted-body-CQBwc1fb.js → formatted-body-qy2nTD_1.js} +3 -3
  43. package/public/assets/{host-providers-dialog-DKaW31dN.js → host-providers-dialog-BGPHxuwT.js} +2 -2
  44. package/public/assets/{index-CRHep3M9.js → index-BC5XZc0z.js} +5 -5
  45. package/public/assets/{index-MYAIwYTX.css → index-D8Rp9pz2.css} +1 -1
  46. package/public/assets/{insights-CzrtkpOE.js → insights-C-KQG0h-.js} +2 -2
  47. package/public/assets/{integrations-aVsUmigt.js → integrations-ClPRPyKU.js} +2 -2
  48. package/public/assets/{issue-ref-chip-BnSlM_95.js → issue-ref-chip-DbH8J9Ak.js} +2 -2
  49. package/public/assets/{log-viewer-qe7Ee47Z.js → log-viewer-PH4zVn24.js} +2 -2
  50. package/public/assets/{maintenance-NfjqFZAk.js → maintenance-5lV43uTL.js} +2 -2
  51. package/public/assets/{managed-agents-BiH0HgaE.js → managed-agents-BdgU35aX.js} +2 -2
  52. package/public/assets/{markdown-preview-BixaT3Xr.js → markdown-preview-DNT4OUwQ.js} +3 -3
  53. package/public/assets/{markdown-preview-impl-DNGlWIS3.js → markdown-preview-impl-CnCcPy0A.js} +2 -2
  54. package/public/assets/{memory-DNsCl6UX.js → memory--GgWH1gH.js} +2 -2
  55. package/public/assets/{messages-DopU1L1X.js → messages-CzFl_97O.js} +2 -2
  56. package/public/assets/{orchestrators-Cq7ckLQT.js → orchestrators-CVvJVkzv.js} +2 -2
  57. package/public/assets/overview-DsrZvE86.js +2 -0
  58. package/public/assets/{pairs-DE_m6rrE.js → pairs-D2d0d2py.js} +2 -2
  59. package/public/assets/{profile-icon-B3rfh77F.js → profile-icon-_SMuSbYF.js} +2 -2
  60. package/public/assets/{project-profile-instructions-DQWZE0kA.js → project-profile-instructions-Apn15y43.js} +2 -2
  61. package/public/assets/{projects-Br2Bd2h1.js → projects-D3B6kto5.js} +2 -2
  62. package/public/assets/{prompt-settings-BKvFsvGD.js → prompt-settings-DnPB6Ez6.js} +2 -2
  63. package/public/assets/provider-display-bWwiuedV.js +2 -0
  64. package/public/assets/{registry-Cw38_6gW.js → registry-D790cIhN.js} +2 -2
  65. package/public/assets/run-card-BCro-Odj.js +2 -0
  66. package/public/assets/{secrets-DxI-vzSq.js → secrets-CVXvfvbU.js} +2 -2
  67. package/public/assets/{service-access-settings-D9s_VJbd.js → service-access-settings-D3Xxqb9w.js} +2 -2
  68. package/public/assets/{settings-CKZTVGIx.js → settings-CoUC7Jci.js} +2 -2
  69. package/public/assets/shipping-D_Lp9n_J.js +2 -0
  70. package/public/assets/{stats-DyUBKyWI.js → stats-CXiNjB9S.js} +2 -2
  71. package/public/assets/{status-dot-DYqlEUhJ.js → status-dot-C703YIy1.js} +2 -2
  72. package/public/assets/store-BgDALGIX.js +9 -0
  73. package/public/assets/{tasks-Bh7Chr4-.js → tasks-DO0WpJCx.js} +2 -2
  74. package/public/assets/{teams-bowI7qVY.js → teams-FGkdi_tL.js} +2 -2
  75. package/public/assets/{terminal-viewer-BgVLHdsU.js → terminal-viewer-Dh8dSC7e.js} +3 -3
  76. package/public/assets/{terminal-viewer-impl-Dz22UPy6.js → terminal-viewer-impl-B5Zriip3.js} +2 -2
  77. package/public/assets/{use-agent-terminal-DSQQ-iY7.js → use-agent-terminal-CRUVDvLC.js} +2 -2
  78. package/public/assets/{use-decisions-samMQhQf.js → use-decisions-CoaqRh4l.js} +2 -2
  79. package/public/assets/{use-project-list-59LheVP7.js → use-project-list-X-BgT53X.js} +2 -2
  80. package/public/assets/{use-selectors-BZa25xEB.js → use-selectors-0X_UZkk-.js} +2 -2
  81. package/public/assets/{user-avatar-DHxlvUvV.js → user-avatar-CkLhVBGu.js} +2 -2
  82. package/public/assets/{versioned-prompt-editor-BmED5DnJ.js → versioned-prompt-editor-BkTi7eim.js} +2 -2
  83. package/public/assets/{work-queue-CSvpuNLz.js → work-queue-DDOLEyKo.js} +2 -2
  84. package/public/assets/{workflow-marker-DAZcj5qt.js → workflow-marker-CzOsB8BM.js} +2 -2
  85. package/public/assets/{workflows-DdmxRSyg.js → workflows-DJilvmRM.js} +2 -2
  86. package/public/assets/{workspaces-BxeKfVuF.js → workspaces-CHcfbLR3.js} +2 -2
  87. package/public/cosmos.html +4 -4
  88. package/public/index.html +29 -29
  89. package/runner/plugins/claude/.claude-plugin/plugin.json +1 -1
  90. package/runner/src/adapters/claude-api.ts +1 -1
  91. package/runner/src/adapters/claude-headless.ts +1 -1
  92. package/runner/src/adapters/claude-launch-exit.ts +26 -0
  93. package/runner/src/adapters/claude-session-probe.ts +1 -1
  94. package/runner/src/adapters/claude-tmux.ts +38 -10
  95. package/runner/src/adapters/claude.ts +28 -75
  96. package/runner/src/adapters/provider-quota-harvest.ts +20 -71
  97. package/runner/src/agent-runner/lifecycle-milestones.ts +2 -2
  98. package/runner/src/agent-runner/liveness-exchange.ts +104 -0
  99. package/runner/src/claude-system-prompt.ts +49 -0
  100. package/runner/src/launch-assembly.ts +14 -10
  101. package/runner/src/profile-home.ts +1 -1
  102. package/runner/src/project-instructions.ts +2 -2
  103. package/runner/src/provider-command.ts +18 -0
  104. package/runner/src/provider-setup.ts +3 -2
  105. package/runner/src/runner-core.ts +14 -15
  106. package/runner/src/runner-helpers.ts +0 -8
  107. package/runner/src/session-scratch.ts +6 -2
  108. package/runner/test-support/provisioning-context.ts +4 -2
  109. package/runner/test-support/runner-harness.ts +2 -1
  110. package/scripts/steward-policy-cleanup.ts +2 -2
  111. package/src/agent-authz.ts +2 -2
  112. package/src/agent-drive-arbiter.ts +3 -8
  113. package/src/agent-exit-cleanup-async.ts +2 -2
  114. package/src/agent-exit-cleanup.ts +23 -19
  115. package/src/agent-lifecycle-events.ts +112 -85
  116. package/src/agent-ref.ts +3 -2
  117. package/src/agent-status-events.ts +43 -14
  118. package/src/auth/login-link.ts +35 -0
  119. package/src/auth/password.ts +4 -3
  120. package/src/auth/session-refresh.ts +1 -1
  121. package/src/auth/session.test-fixture.ts +2 -2
  122. package/src/auth/session.ts +7 -7
  123. package/src/automations/crud.ts +8 -81
  124. package/src/automations/dispatch.ts +33 -58
  125. package/src/automations/index.ts +1 -1
  126. package/src/automations/persistence.ts +65 -0
  127. package/src/automations/precheck.ts +18 -16
  128. package/src/automations/read-async.ts +11 -0
  129. package/src/automations/reconcile.ts +30 -39
  130. package/src/automations/storage.ts +33 -10
  131. package/src/automations/write-async.ts +33 -0
  132. package/src/branch-land-notice.ts +3 -3
  133. package/src/branch-landed.ts +25 -23
  134. package/src/bus.ts +21 -19
  135. package/src/cd-deploy-notify.ts +2 -2
  136. package/src/ci/notifications.ts +4 -4
  137. package/src/ci/root-missing.ts +3 -3
  138. package/src/ci/transition-notify.ts +5 -5
  139. package/src/claude-app/oauth-http.ts +3 -3
  140. package/src/cli/index.ts +7 -1
  141. package/src/cli/init.ts +53 -0
  142. package/src/cli/orchestrator.ts +1 -7
  143. package/src/cli/setup.ts +6 -4
  144. package/src/cli/workflow.ts +12 -3
  145. package/src/commands-db.ts +4 -4
  146. package/src/commands-write.ts +8 -0
  147. package/src/compaction-watch.ts +10 -8
  148. package/src/config-store-write.ts +2 -2
  149. package/src/config.ts +4 -11
  150. package/src/connectors.ts +10 -8
  151. package/src/context-advisory.ts +22 -21
  152. package/src/db/agent-action-write.ts +36 -0
  153. package/src/db/agent-control-async.ts +9 -0
  154. package/src/db/agent-control-write.ts +49 -0
  155. package/src/db/agent-effort-observe.ts +22 -0
  156. package/src/db/agent-meta.ts +14 -3
  157. package/src/db/agents-async.ts +8 -5
  158. package/src/db/agents.ts +15 -12
  159. package/src/db/auth-identities.ts +2 -2
  160. package/src/db/automation-read-ops.ts +11 -0
  161. package/src/db/automation-write-ops.ts +46 -0
  162. package/src/db/blackboard.ts +2 -2
  163. package/src/db/browser-session-write.ts +32 -0
  164. package/src/db/bus-outbox-write-ops.ts +3 -1
  165. package/src/db/checkout-refresh-schema.ts +47 -0
  166. package/src/db/checkout-refresh.ts +5 -5
  167. package/src/db/command-agent-profile-backfill.ts +39 -0
  168. package/src/db/command-agent-profiles.ts +5 -1
  169. package/src/db/command-retention.ts +126 -0
  170. package/src/db/commands-planner-stats.test-fixture.ts +8 -0
  171. package/src/db/commands-read-ops.ts +16 -0
  172. package/src/db/connection.ts +1 -182
  173. package/src/db/context-carry-write.ts +74 -0
  174. package/src/db/continuations.ts +4 -4
  175. package/src/db/db-error-registry.ts +12 -0
  176. package/src/db/gateway.ts +26 -133
  177. package/src/db/history-retention-ops.ts +13 -0
  178. package/src/db/inbox-async.ts +2 -2
  179. package/src/db/inbox-read-ops.ts +1 -1
  180. package/src/db/inbox.ts +9 -3
  181. package/src/db/issue-associations.ts +2 -2
  182. package/src/db/issue-refs-async.ts +4 -1
  183. package/src/db/issue-refs-read-ops.ts +6 -0
  184. package/src/db/issue-refs.ts +8 -8
  185. package/src/db/kernel-event-log-schema.ts +2 -0
  186. package/src/db/land-boundaries.ts +51 -5
  187. package/src/db/land-gate-attestations.ts +2 -2
  188. package/src/db/landing-receipts.ts +2 -2
  189. package/src/db/lifecycle-context-write.ts +5 -0
  190. package/src/db/lifecycle-tail-async.ts +76 -0
  191. package/src/db/lifecycle-tail-write-ops.ts +62 -0
  192. package/src/db/lifecycle-write-window.ts +2 -1
  193. package/src/db/lineage-pair-dedupe-sql.ts +3 -3
  194. package/src/db/main-connection-mode.ts +11 -0
  195. package/src/db/main-connection-writes.ts +20 -2
  196. package/src/db/maintenance-job-runs-async.ts +2 -2
  197. package/src/db/maintenance-job-write-ops.ts +1 -1
  198. package/src/db/maintenance-pauses.ts +2 -2
  199. package/src/db/message-send.ts +4 -0
  200. package/src/db/messages.ts +31 -25
  201. package/src/db/migrations.ts +18 -1
  202. package/src/db/notification-write-ops.ts +19 -0
  203. package/src/db/operator-answer-write.ts +19 -0
  204. package/src/db/orchestrators.ts +10 -4
  205. package/src/db/pairs-async.ts +22 -1
  206. package/src/db/pairs-write-ops.ts +8 -3
  207. package/src/db/pairs.ts +41 -48
  208. package/src/db/plan-dispatch-schema.ts +5 -1
  209. package/src/db/plan-ready-notices.ts +43 -0
  210. package/src/db/plan-tools-include-migration.ts +36 -0
  211. package/src/db/plans-write-ops.ts +2 -0
  212. package/src/db/presence-buffer.ts +5 -0
  213. package/src/db/presence-loop.ts +18 -23
  214. package/src/db/presence-write.ts +0 -6
  215. package/src/db/project-entries-async.ts +14 -0
  216. package/src/db/project-entries-read-ops.ts +5 -1
  217. package/src/db/project-entries-write-ops.ts +8 -0
  218. package/src/db/project-entries.ts +15 -12
  219. package/src/db/project-journal.ts +2 -2
  220. package/src/db/project-trust-approvals.ts +2 -2
  221. package/src/db/prompt-templates.ts +4 -4
  222. package/src/db/read-op-marshaling-fixtures.ts +18 -0
  223. package/src/db/read-ops.ts +4 -0
  224. package/src/db/retention.ts +13 -2
  225. package/src/db/review-publish-write.ts +8 -0
  226. package/src/db/runtime-admin-async.ts +19 -0
  227. package/src/db/runtime-admin-write-ops.ts +36 -0
  228. package/src/db/runtime-tail-async.ts +288 -0
  229. package/src/db/runtime-tail-write-ops.ts +97 -0
  230. package/src/db/schema.ts +4 -1
  231. package/src/db/spawn-budget.ts +5 -0
  232. package/src/db/spawn-delegation.ts +3 -12
  233. package/src/db/sql-audit-indexes.ts +3 -0
  234. package/src/db/stats-async.ts +5 -3
  235. package/src/db/task-entity.ts +5 -4
  236. package/src/db/team-claim-policy.ts +60 -0
  237. package/src/db/teams-async.ts +4 -0
  238. package/src/db/teams-write-ops.ts +4 -0
  239. package/src/db/terminal-events.ts +15 -0
  240. package/src/db/timer-cutover-bodies.ts +292 -0
  241. package/src/db/timer-cutover-core.ts +37 -278
  242. package/src/db/timer-cutover-state.ts +40 -0
  243. package/src/db/timer-cutover-write-ops.ts +1 -40
  244. package/src/db/token-db-write-ops.ts +2 -0
  245. package/src/db/token-standing-async.ts +12 -0
  246. package/src/db/token-standing.ts +6 -9
  247. package/src/db/token-usage-retention.ts +33 -0
  248. package/src/db/token-usage-write-ops.ts +1 -1
  249. package/src/db/token-usage.ts +4 -1
  250. package/src/db/user-invites-async.ts +13 -0
  251. package/src/db/user-invites.ts +3 -3
  252. package/src/db/users.ts +14 -6
  253. package/src/db/workflow-execution.ts +3 -3
  254. package/src/db/workspaces.ts +8 -5
  255. package/src/db/write-ops.ts +31 -12
  256. package/src/db/writer-fault-seam.ts +2 -9
  257. package/src/db/writer-fault-test-ops.ts +18 -0
  258. package/src/db/writer-gateway.ts +42 -46
  259. package/src/dev.ts +12 -16
  260. package/src/event-loop-lag.ts +4 -2
  261. package/src/event-loop-yield.ts +2 -2
  262. package/src/events.ts +10 -8
  263. package/src/host-provider-store.ts +5 -4
  264. package/src/hub-metrics-report.ts +5 -1
  265. package/src/hub-metrics.ts +38 -18
  266. package/src/init.ts +299 -0
  267. package/src/injection-sweep-pacing.ts +6 -8
  268. package/src/invite-link.ts +16 -9
  269. package/src/land-gate-notifications.ts +11 -10
  270. package/src/land-gate-queue-progress.ts +3 -3
  271. package/src/land-settle-dispatch.ts +52 -92
  272. package/src/lifecycle-context-pressure.ts +11 -10
  273. package/src/lifecycle-manager.ts +104 -98
  274. package/src/maintenance/breaker.ts +18 -16
  275. package/src/maintenance/checkout-refresh.ts +18 -1
  276. package/src/maintenance/critical-job-watchdog.ts +3 -3
  277. package/src/maintenance/events.ts +3 -3
  278. package/src/maintenance/history-retention-job.ts +30 -0
  279. package/src/maintenance/jobs.ts +29 -67
  280. package/src/maintenance/long-running-work.ts +3 -1
  281. package/src/maintenance/offline-agent-prune-job.ts +28 -0
  282. package/src/maintenance/orphaned-sessions.ts +5 -4
  283. package/src/maintenance/pauses.ts +4 -10
  284. package/src/maintenance/plan-ready-notice-job.ts +71 -0
  285. package/src/maintenance/scheduler.ts +18 -13
  286. package/src/maintenance/stalled-delivery-pager.ts +4 -4
  287. package/src/maintenance/teams.ts +19 -30
  288. package/src/maintenance/workspaces.ts +17 -27
  289. package/src/managed-policy-escalation.ts +7 -7
  290. package/src/managed-policy.ts +3 -3
  291. package/src/managed-provider-gate.ts +5 -4
  292. package/src/managed-spawn-reservation.ts +5 -4
  293. package/src/mcp/index.ts +8 -8
  294. package/src/mcp/output-descriptions.ts +1 -1
  295. package/src/mcp/presentation.ts +2 -1
  296. package/src/mcp/runtime-output.ts +6 -1
  297. package/src/mcp/self-care-visibility.ts +2 -2
  298. package/src/mcp/spawn-targets-matrix.ts +10 -1
  299. package/src/mcp/tool-groups.ts +3 -2
  300. package/src/mcp/tool-roles.ts +81 -0
  301. package/src/mcp/tools-workspace.ts +1 -1
  302. package/src/mcp-blackboard-tools.ts +6 -5
  303. package/src/mcp-decision-tools.ts +7 -7
  304. package/src/mcp-egress-tools.ts +10 -9
  305. package/src/mcp-issue-activity-tools.ts +2 -2
  306. package/src/mcp-issue-association-tools.ts +4 -4
  307. package/src/mcp-issue-ref-tools.ts +3 -3
  308. package/src/mcp-merge-tools.ts +5 -5
  309. package/src/mcp-notification-subscription-tools.ts +14 -15
  310. package/src/mcp-output-levels.test-fixture.ts +1 -1
  311. package/src/mcp-profile-trust-tools.ts +1 -1
  312. package/src/mcp-project-journal-tools.ts +4 -12
  313. package/src/mcp-project-tools.ts +17 -18
  314. package/src/mcp-routing-policy-tools.ts +3 -2
  315. package/src/mcp-team-tools.ts +6 -6
  316. package/src/mcp-workflow-tools.ts +5 -3
  317. package/src/memory-area-injection.ts +13 -12
  318. package/src/memory-boundary-capture.ts +6 -6
  319. package/src/memory-injection.ts +45 -43
  320. package/src/merge-pause-maintenance.ts +5 -4
  321. package/src/notification-router.ts +44 -17
  322. package/src/notify.ts +5 -5
  323. package/src/observed-reset-refresh.ts +4 -4
  324. package/src/operator-alarm.ts +2 -5
  325. package/src/project-ingest.ts +6 -6
  326. package/src/project-instructions.ts +8 -1
  327. package/src/project-trust.ts +12 -11
  328. package/src/prompt-resolver.ts +3 -3
  329. package/src/provider-quota-async.ts +5 -7
  330. package/src/provider-timeline-event.ts +4 -7
  331. package/src/quota-band-delivery.ts +2 -2
  332. package/src/recipe-runner.ts +4 -3
  333. package/src/retention-config-store.ts +4 -3
  334. package/src/reviewer-pipeline.ts +11 -10
  335. package/src/routes/_route.ts +4 -4
  336. package/src/routes/_shared.ts +13 -12
  337. package/src/routes/agent-effort.ts +5 -5
  338. package/src/routes/agent-heartbeat-quota.ts +23 -0
  339. package/src/routes/agent-keep.ts +1 -1
  340. package/src/routes/agent-reporting.ts +1 -1
  341. package/src/routes/agent-self-effort.ts +5 -5
  342. package/src/routes/agent-sessions.ts +24 -24
  343. package/src/routes/agents-spawn.ts +1 -1
  344. package/src/routes/agents.ts +17 -119
  345. package/src/routes/auth.ts +44 -17
  346. package/src/routes/authority-audit.ts +2 -2
  347. package/src/routes/automations.ts +6 -5
  348. package/src/routes/channel-binding-delete.ts +1 -1
  349. package/src/routes/channel-output.ts +3 -3
  350. package/src/routes/claude-api-budget.ts +5 -5
  351. package/src/routes/commands-listing.ts +1 -1
  352. package/src/routes/commands.ts +29 -27
  353. package/src/routes/context-resets.ts +2 -2
  354. package/src/routes/coordinator-teams.ts +1 -1
  355. package/src/routes/decisions.ts +2 -2
  356. package/src/routes/host-providers.ts +18 -0
  357. package/src/routes/host-secret-files.ts +1 -1
  358. package/src/routes/hosts.ts +11 -11
  359. package/src/routes/inbox.ts +3 -2
  360. package/src/routes/index.ts +7 -3
  361. package/src/routes/integrations.ts +9 -7
  362. package/src/routes/issue-activity.ts +2 -2
  363. package/src/routes/issue-associations.ts +4 -4
  364. package/src/routes/issue-refs.ts +3 -3
  365. package/src/routes/kernel-timers-operator.ts +1 -1
  366. package/src/routes/memory.ts +1 -1
  367. package/src/routes/merges.ts +11 -11
  368. package/src/routes/messages.ts +23 -17
  369. package/src/routes/orchestrator-bootstrap.ts +3 -1
  370. package/src/routes/orchestrator-host-registration.ts +2 -0
  371. package/src/routes/orchestrator-host-utilization.ts +2 -2
  372. package/src/routes/orchestrator-proxy.ts +2 -2
  373. package/src/routes/orchestrator.ts +27 -18
  374. package/src/routes/pairs.ts +8 -8
  375. package/src/routes/project-profile-instructions.ts +1 -1
  376. package/src/routes/project-trust.ts +1 -1
  377. package/src/routes/projects.ts +16 -16
  378. package/src/routes/prompt-templates.ts +12 -12
  379. package/src/routes/provider-quotas.ts +10 -10
  380. package/src/routes/run-command.ts +1 -1
  381. package/src/routes/secrets-backup.ts +4 -5
  382. package/src/routes/secrets-import.ts +3 -4
  383. package/src/routes/secrets-vault.ts +12 -14
  384. package/src/routes/settings.ts +1 -1
  385. package/src/routes/shipping.ts +9 -1
  386. package/src/routes/spawn-policy.ts +8 -7
  387. package/src/routes/sse.ts +2 -2
  388. package/src/routes/team-templates.ts +7 -7
  389. package/src/routes/teams.ts +10 -10
  390. package/src/routes/tokens.ts +18 -17
  391. package/src/routes/users.ts +24 -24
  392. package/src/routes/viewer-read.ts +3 -3
  393. package/src/routes/web-tool-calls.ts +4 -4
  394. package/src/routes/workflows.ts +2 -2
  395. package/src/routes/workspaces.ts +17 -16
  396. package/src/routing-policy-push.ts +6 -6
  397. package/src/runtime-grant.ts +17 -11
  398. package/src/runtime-install.ts +30 -0
  399. package/src/runtime-tokens.ts +20 -28
  400. package/src/secrets-broker/config.ts +1 -1
  401. package/src/secrets-broker/service.ts +2 -2
  402. package/src/security.ts +3 -1
  403. package/src/self-resume-carry.ts +21 -110
  404. package/src/self-resume-supersede.ts +4 -3
  405. package/src/self-resume.ts +54 -66
  406. package/src/server-background.ts +1 -1
  407. package/src/server.ts +25 -26
  408. package/src/services/agent-action.ts +12 -31
  409. package/src/services/agent-effort.ts +7 -32
  410. package/src/services/agent-hang-watchdog-job.ts +2 -2
  411. package/src/services/agent-heartbeat.ts +166 -0
  412. package/src/services/agent-reporting.ts +1 -1
  413. package/src/services/auth-context.ts +6 -0
  414. package/src/services/browser-inventory.ts +3 -3
  415. package/src/services/browser-session-state.ts +3 -2
  416. package/src/services/browser-session.ts +21 -27
  417. package/src/services/bus-command-update.ts +9 -9
  418. package/src/services/checkout-refresh-state.ts +1 -0
  419. package/src/services/checkout-refresh.test-fixture.ts +3 -2
  420. package/src/services/command-host.ts +7 -2
  421. package/src/services/coordinator-digest.ts +3 -2
  422. package/src/services/dispatch-command.ts +12 -13
  423. package/src/services/effective-launch-driver.ts +14 -9
  424. package/src/services/host-changed-paths.test-fixture.ts +5 -6
  425. package/src/services/host-project-readiness.ts +2 -2
  426. package/src/services/host-providers.ts +1 -1
  427. package/src/services/host-utilization.ts +9 -9
  428. package/src/services/idle-agent-digest.ts +17 -12
  429. package/src/services/idle-epics.ts +4 -4
  430. package/src/services/interrupt-agent.ts +12 -9
  431. package/src/services/issue-activity.ts +3 -3
  432. package/src/services/issue-associations.ts +15 -18
  433. package/src/services/issue-lifecycle-comments.ts +3 -2
  434. package/src/services/issue-lifecycle.ts +14 -13
  435. package/src/services/issue-refs.ts +4 -5
  436. package/src/services/kernel-timers-cutover-chaos-worker.ts +1 -1
  437. package/src/services/kernel-timers-ingress-chaos-worker.ts +6 -1
  438. package/src/services/kernel-timers-ingress.ts +3 -3
  439. package/src/services/kernel-timers-message-authority-chaos-worker.ts +3 -10
  440. package/src/services/kernel-timers-operator-chaos-worker.ts +3 -2
  441. package/src/services/kernel-timers-outbox.ts +1 -1
  442. package/src/services/kernel-timers-stage10-operator.ts +1 -1
  443. package/src/services/kernel-timers.ts +4 -3
  444. package/src/services/land-gate-placement.ts +11 -2
  445. package/src/services/land-issue-relations.ts +5 -4
  446. package/src/services/land-restart-retry.ts +7 -6
  447. package/src/services/landed-ancestry.ts +6 -5
  448. package/src/services/legacy-landing-host.ts +4 -1
  449. package/src/services/legacy-landing-recovery.ts +8 -6
  450. package/src/services/managed-running.ts +17 -17
  451. package/src/services/memory-areas.ts +3 -3
  452. package/src/services/merge-pause.ts +9 -15
  453. package/src/services/operator-decisions.ts +37 -41
  454. package/src/services/orchestrator-registration-recovery.ts +6 -2
  455. package/src/services/orchestrator-upgrade.ts +14 -12
  456. package/src/services/permission-decision.ts +4 -3
  457. package/src/services/plan-ci-notice.ts +1 -1
  458. package/src/services/plan-conformance.ts +4 -4
  459. package/src/services/plan-dispatch-policy.ts +10 -3
  460. package/src/services/plan-dispatch.ts +35 -14
  461. package/src/services/plan-graph.ts +39 -261
  462. package/src/services/plan-import.ts +1 -1
  463. package/src/services/plan-live-bindings.ts +8 -37
  464. package/src/services/plan-task-create.ts +1 -1
  465. package/src/services/plan-terminal-refs.ts +2 -12
  466. package/src/services/plan-wake-digest.ts +8 -3
  467. package/src/services/profile-trust.ts +2 -2
  468. package/src/services/project.ts +11 -10
  469. package/src/services/prompt-templates.ts +6 -5
  470. package/src/services/provider-api-key.ts +73 -0
  471. package/src/services/provider-hold-nudge.ts +9 -9
  472. package/src/services/provider-hold-record.ts +13 -12
  473. package/src/services/provider-state-audit.ts +19 -18
  474. package/src/services/provisioning-harness/driver.ts +1 -1
  475. package/src/services/provisioning-harness/fixture-matrix.ts +3 -3
  476. package/src/services/provisioning-harness/lifecycle.ts +24 -22
  477. package/src/services/provisioning-harness/prepare.ts +16 -17
  478. package/src/services/rate-limit-resume.ts +10 -9
  479. package/src/services/red-main-auto-revert.ts +7 -5
  480. package/src/services/red-main-controller-deps.ts +20 -3
  481. package/src/services/red-main-incident.ts +3 -1
  482. package/src/services/red-main-quarantine.ts +2 -3
  483. package/src/services/register-agent.ts +22 -22
  484. package/src/services/restart-project-role.ts +1 -1
  485. package/src/services/restart-spawn.ts +17 -16
  486. package/src/services/review-publish.ts +7 -24
  487. package/src/services/review-ref-reconcile.ts +29 -38
  488. package/src/services/runtime-dependency-alert.ts +27 -0
  489. package/src/services/scheduler-command.ts +11 -9
  490. package/src/services/scheduler.ts +5 -5
  491. package/src/services/self-effort-grant.ts +5 -25
  492. package/src/services/send-message.ts +16 -33
  493. package/src/services/shutdown-agent.ts +17 -14
  494. package/src/services/spawn-agent.ts +12 -41
  495. package/src/services/spawn-chain-inspector.ts +1 -1
  496. package/src/services/spawn-cwd-placement.ts +21 -5
  497. package/src/services/spawn-issue-activity.ts +8 -6
  498. package/src/services/spawn-launch.ts +17 -1
  499. package/src/services/spawn-loss-escalation.ts +1 -1
  500. package/src/services/spawn-registration-watchdog.ts +2 -2
  501. package/src/services/spawn-repo-probe.ts +7 -5
  502. package/src/services/spawn-tree-cleanup.ts +7 -8
  503. package/src/services/steward-reaper.ts +4 -4
  504. package/src/services/task-context-hydration.ts +25 -1
  505. package/src/services/task-delivery.ts +20 -34
  506. package/src/services/task-entity.ts +40 -203
  507. package/src/services/task-issue-link.ts +13 -20
  508. package/src/services/task-issue-weave.ts +12 -11
  509. package/src/services/task-lifecycle.ts +27 -31
  510. package/src/services/task-repo-cwd.ts +37 -0
  511. package/src/services/task-review-hold.ts +4 -17
  512. package/src/services/task-semantic-events.ts +13 -11
  513. package/src/services/task-state-reconcile.ts +3 -4
  514. package/src/services/task-validation.ts +2 -2
  515. package/src/services/team-templates.ts +5 -5
  516. package/src/services/team.ts +31 -98
  517. package/src/services/terminal-provider-exit.ts +6 -5
  518. package/src/services/timer-message-fire-chaos-worker.ts +7 -3
  519. package/src/services/timer-message-fire-outbox.ts +1 -1
  520. package/src/services/transient-agent-reaper.ts +22 -19
  521. package/src/services/turn-reconcile-audit.ts +9 -9
  522. package/src/services/user-onboarding.ts +8 -6
  523. package/src/services/user-profile.ts +6 -9
  524. package/src/services/work-finality.ts +16 -4
  525. package/src/services/workflow-auto-start.ts +2 -1
  526. package/src/services/workflow-caller.ts +61 -4
  527. package/src/services/workflow-child-proof-worker.ts +1 -1
  528. package/src/services/workflow-control-proof-worker.ts +1 -1
  529. package/src/services/workflow-coordinator.ts +8 -2
  530. package/src/services/workflow-decisions.ts +5 -5
  531. package/src/services/workflow-deferred-cleanup.ts +1 -1
  532. package/src/services/workflow-effect-driver.ts +42 -19
  533. package/src/services/workflow-effects.ts +41 -27
  534. package/src/services/workflow-pins.ts +7 -4
  535. package/src/services/workflow-reconcile.ts +1 -0
  536. package/src/services/workflow-resume-pins.ts +3 -3
  537. package/src/services/workflow-routing-defaults.ts +18 -0
  538. package/src/services/workflow-run-view.ts +4 -3
  539. package/src/services/workflow-run.test-fixture.ts +1 -1
  540. package/src/services/workflow-runs.ts +34 -22
  541. package/src/services/workflow-supervisor-state.ts +21 -1
  542. package/src/services/workflow-supervisor.ts +4 -3
  543. package/src/services/workspace-recovery.ts +4 -3
  544. package/src/setup.ts +47 -8
  545. package/src/spawn-admission.ts +10 -2
  546. package/src/spawn-placement.ts +27 -9
  547. package/src/spawn-targets.ts +8 -8
  548. package/src/sse-agent-status.ts +15 -6
  549. package/src/sse.ts +49 -24
  550. package/src/startup-context-injection.ts +61 -57
  551. package/src/steward-handoff.ts +4 -3
  552. package/src/steward-policy-cleanup.ts +9 -8
  553. package/src/steward.ts +2 -2
  554. package/src/task-dispatch-live.ts +5 -2
  555. package/src/task-dispatcher.ts +2 -2
  556. package/src/token-db.ts +2 -2
  557. package/src/token-usage-async.ts +2 -4
  558. package/src/user-awaiting-reply.ts +5 -5
  559. package/src/utils.ts +7 -0
  560. package/src/workspace-actions.ts +24 -29
  561. package/src/workspace-auto-merge.ts +14 -12
  562. package/src/workspace-changed-paths-client.ts +16 -5
  563. package/src/workspace-cleanup-stale.ts +30 -7
  564. package/src/workspace-command-settle.ts +24 -16
  565. package/src/workspace-config.ts +1 -1
  566. package/src/workspace-conflict-resolver.ts +9 -7
  567. package/src/workspace-dead-owner-recovery.ts +5 -4
  568. package/src/workspace-escalation.ts +12 -11
  569. package/src/workspace-human-escalation.ts +3 -3
  570. package/src/workspace-land-gate-watchdog.ts +3 -3
  571. package/src/workspace-land-refusal.ts +20 -0
  572. package/src/workspace-land-stopped.ts +1 -0
  573. package/src/workspace-merge.ts +10 -26
  574. package/src/workspace-nothing-to-land-notice.ts +2 -2
  575. package/src/workspace-orphans.ts +18 -37
  576. package/src/workspace-pr-completion.ts +10 -8
  577. package/src/workspace-rekey.ts +3 -3
  578. package/src/workspace-steward-failure.ts +2 -2
  579. package/src/workspace-steward-wake.ts +2 -2
  580. package/public/assets/agent-liveness-CaNwK0Zf.js +0 -2
  581. package/public/assets/overview-C1DCTzzV.js +0 -2
  582. package/public/assets/provider-display-DsuWMvVL.js +0 -2
  583. package/public/assets/run-card-CpKqRbhg.js +0 -2
  584. package/public/assets/shipping-B9YtnwtG.js +0 -2
  585. package/public/assets/store-DcClXLH0.js +0 -9
  586. package/runner/src/agent-runner/http-liveness.ts +0 -85
  587. package/src/db/on-loop-write-transaction.ts +0 -34
@@ -22,8 +22,8 @@ function actorFromRequest(req: Request): string {
22
22
  : "root";
23
23
  }
24
24
 
25
- export const getMergePauses: Handler = (req) => {
26
- const denied = authorizeRoute(req, { scope: "command:read" });
25
+ export const getMergePauses: Handler = async (req) => {
26
+ const denied = (await authorizeRoute(req, { scope: "command:read" }));
27
27
  if (denied) return denied;
28
28
  return json({ pauses: listAutoMergePauses() });
29
29
  };
@@ -37,13 +37,13 @@ export const getMergePauses: Handler = (req) => {
37
37
  * indefinitely, and #2094's fast reclaim covers whatever the interlock misses.
38
38
  */
39
39
  export const getMergeDrain: Handler = async (req) => {
40
- const denied = authorizeRoute(req, { scope: "command:read" });
40
+ const denied = (await authorizeRoute(req, { scope: "command:read" }));
41
41
  if (denied) return denied;
42
42
  return json(await workspaceMergeDrainStatusAsync());
43
43
  };
44
44
 
45
45
  export const postMergePause: Handler = async (req) => {
46
- const denied = authorizeRoute(req, { scope: "command:write" });
46
+ const denied = (await authorizeRoute(req, { scope: "command:write" }));
47
47
  if (denied) return denied;
48
48
  const parsed = await parseBody<unknown>(req);
49
49
  if (!parsed.ok) return error(parsed.error, parsed.status);
@@ -54,7 +54,7 @@ export const postMergePause: Handler = async (req) => {
54
54
  const holder = cleanString(parsed.body.holder, "holder", { max: 240 }) ?? actorFromRequest(req);
55
55
  const reason = cleanString(parsed.body.reason, "reason", { max: 500 });
56
56
  const ttlMs = cleanTtlMs(parsed.body.ttlMs);
57
- const result = pauseAutoMerge({ repoRoot, baseRef, holder, reason, ttlMs });
57
+ const result = (await pauseAutoMerge({ repoRoot, baseRef, holder, reason, ttlMs }));
58
58
  if (!result.ok) {
59
59
  return json({ error: "merge target already paused", pause: result.pause }, 409);
60
60
  }
@@ -66,7 +66,7 @@ export const postMergePause: Handler = async (req) => {
66
66
  };
67
67
 
68
68
  export const postMergePauseRenew: Handler = async (req) => {
69
- const denied = authorizeRoute(req, { scope: "command:write" });
69
+ const denied = (await authorizeRoute(req, { scope: "command:write" }));
70
70
  if (denied) return denied;
71
71
  const parsed = await parseBody<unknown>(req);
72
72
  if (!parsed.ok) return error(parsed.error, parsed.status);
@@ -74,7 +74,7 @@ export const postMergePauseRenew: Handler = async (req) => {
74
74
  if (!isRecord(parsed.body)) return error("body required");
75
75
  const id = cleanString(parsed.body.id, "id", { required: true, max: 120 })!;
76
76
  const ttlMs = cleanTtlMs(parsed.body.ttlMs);
77
- const pause = renewAutoMergePause(id, ttlMs);
77
+ const pause = (await renewAutoMergePause(id, ttlMs));
78
78
  return pause ? json({ pause }) : error("merge pause not found or expired", 404);
79
79
  } catch (e) {
80
80
  if (e instanceof ValidationError) return error(e.message, 400);
@@ -83,7 +83,7 @@ export const postMergePauseRenew: Handler = async (req) => {
83
83
  };
84
84
 
85
85
  export const postMergePauseResume: Handler = async (req) => {
86
- const denied = authorizeRoute(req, { scope: "command:write" });
86
+ const denied = (await authorizeRoute(req, { scope: "command:write" }));
87
87
  if (denied) return denied;
88
88
  const parsed = await parseBody<unknown>(req);
89
89
  if (!parsed.ok) return error(parsed.error, parsed.status);
@@ -93,7 +93,7 @@ export const postMergePauseResume: Handler = async (req) => {
93
93
  const repoRoot = cleanString(parsed.body.repoRoot, "repoRoot", { max: 1000 });
94
94
  const baseRef = cleanString(parsed.body.baseRef, "baseRef", { max: 240 });
95
95
  if (!id && !repoRoot) return error("id or repoRoot required", 400);
96
- const released = resumeAutoMerge(id ? { id } : { repoRoot: repoRoot!, baseRef: baseRef ?? "main" });
96
+ const released = (await resumeAutoMerge(id ? { id } : { repoRoot: repoRoot!, baseRef: baseRef ?? "main" }));
97
97
  return json({ released });
98
98
  } catch (e) {
99
99
  if (e instanceof ValidationError) return error(e.message, 400);
@@ -101,8 +101,8 @@ export const postMergePauseResume: Handler = async (req) => {
101
101
  }
102
102
  };
103
103
 
104
- export const getMergePauseById: Handler = (req, params) => {
105
- const denied = authorizeRoute(req, { scope: "command:read" });
104
+ export const getMergePauseById: Handler = async (req, params) => {
105
+ const denied = (await authorizeRoute(req, { scope: "command:read" }));
106
106
  if (denied) return denied;
107
107
  const pause = getAutoMergePause(params.id!);
108
108
  return pause ? json(pause) : error("merge pause not found", 404);
@@ -1,7 +1,8 @@
1
+ import { sendMessageWithResultAsync, sendMessageAsync } from "../db/message-send";
1
2
  import { authorityDenied } from "../authority-audit";
2
3
  // Auto-split from routes.ts (#299). Domain: messages.
3
4
  import { MAX_BODY_BYTES } from "../config";
4
- import { ValidationError, applyMessageDeliveryActionAsync, claimMessageAsync, deleteMessageAsync, getAgent, getLatestMessageIdAsync, getMessage, getMessageAsync, getMessageDeliveryStatusAsync, getThreadAsync, listQueuedMessagesAsync, listRecentMessagesAsync, markReadAsync, pollMessagesAsync, recordMessageDeliveryAttemptAsync, renewMessageClaimAsync, sendMessage, sendMessageWithResult, setMessageReactionAsync } from "../db";
5
+ import { ValidationError, applyMessageDeliveryActionAsync, claimMessageAsync, deleteMessageAsync, getAgent, getLatestMessageIdAsync, getMessage, getMessageAsync, getMessageDeliveryStatusAsync, getThreadAsync, listQueuedMessagesAsync, listRecentMessagesAsync, markReadAsync, pollMessagesAsync, recordMessageDeliveryAttemptAsync, renewMessageClaimAsync, setMessageReactionAsync, isChannelEgressTarget } from "../db";
5
6
  import { requestUserAddress, resolveActingUser, auditEvent, cleanAttachmentRefs, dispatchTaskCallbacksInBackground, emitCommand, error, json, normalizeAgentSessionGuard, parseBody, parseId, parseQueryInt, reactionEmoji, sendReactionNotificationToAuthor, withPayloadAttachments, type Handler } from "./_shared";
6
7
  import { cleanMeta, cleanParams, cleanPositiveId, cleanString, optionalEnum } from "../validation";
7
8
  import { emitMessageClaimed, emitMessageDeleted, emitMessageDeliveryUpdated, emitMessageQueued, emitMessageReactionUpdated, emitNewMessage, emitTaskChanged } from "../sse";
@@ -12,12 +13,11 @@ import { authContextFromRequest } from "../services/auth-context";
12
13
  import { sendMessagesBatchService, sendMessageServiceAsync } from "../services/send-message";
13
14
  import { recordFanoutSuppression } from "../services/channel-suppression-receipt";
14
15
  import { fanOutToAgent } from "../services/agent-message-fanout";
15
- import { isChannelEgressTarget } from "../db";
16
16
  import { CHANNEL_SUPPRESSION_REASON, isDisallowedChannelContent } from "../db/channel-egress-allowlist.ts";
17
17
  import { settleParkedSelfResumeContinuation } from "../self-resume";
18
18
  import { AmbiguousTargetError, ServiceAuthError } from "../services/errors";
19
19
  import { reEvaluateChannelDelivery } from "../services/message-delivery-actions";
20
- import { isOtherHumanSink, messageVisibleTo } from "../message-visibility";
20
+ import { isOtherHumanSink, messageVisibleTo, type MessageViewer } from "../message-visibility";
21
21
  import { messageViewerForRequest, visibleMessages } from "./message-viewer";
22
22
  import { type AgentSessionGuard, type Message, type PollQuery, type SendMessageInput } from "../types";
23
23
 
@@ -136,7 +136,7 @@ export const postMessageDeliveryAttempt: Handler = async (req, params) => {
136
136
  }, idempotencyKey);
137
137
  if (!result.ok) return error(result.error ?? "message not found", result.error === "message not found" ? 404 : 409);
138
138
  emitMessageDeliveryUpdated(result.message!);
139
- if (status === "delivered") settleParkedSelfResumeContinuation(result.message!);
139
+ if (status === "delivered") (await settleParkedSelfResumeContinuation(result.message!));
140
140
  return json(await getMessageDeliveryStatusAsync(id), 201);
141
141
  } catch (e) {
142
142
  if (e instanceof ValidationError) return error(e.message, 400);
@@ -222,13 +222,13 @@ export const postSystemBroadcast: Handler = async (req) => {
222
222
  const body = parsed.body;
223
223
  if (!body?.body) return error("body required");
224
224
  try {
225
- const msg = sendMessage({
225
+ const msg = (await sendMessageAsync({
226
226
  from: "system",
227
227
  to: "broadcast",
228
228
  kind: "system",
229
229
  subject: body.subject ?? undefined,
230
230
  body: body.body,
231
- });
231
+ }));
232
232
  emitNewMessage(msg);
233
233
  return json(msg, 201);
234
234
  } catch (e) {
@@ -351,7 +351,7 @@ export const getMessages: Handler = async (req) => {
351
351
  const channel = url.searchParams.get("channel") ?? undefined;
352
352
  // #3567 D6 — a non-admin reads only their own human sink; another human's inbox is a 403.
353
353
  const viewer = messageViewerForRequest(req);
354
- if (forAgent && isOtherHumanSink(viewer, forAgent)) return authorityDenied(req, "you can only read your own messages", 403, forAgent, "read sink");
354
+ if (forAgent && isOtherHumanSink(viewer, forAgent)) return (await authorityDenied(req, "you can only read your own messages", 403, forAgent, "read sink"));
355
355
 
356
356
  // No agent filter — return all recent messages
357
357
  if (!forAgent) {
@@ -367,6 +367,12 @@ export const getMessages: Handler = async (req) => {
367
367
  channel,
368
368
  limit,
369
369
  };
370
+ return json(await pollAgentMessages(viewer, pollQuery));
371
+ };
372
+
373
+ /** Shared display/turn-delivery polling for GET messages and the liveness exchange (#3608). */
374
+ export async function pollAgentMessages(viewer: MessageViewer | null, pollQuery: PollQuery): Promise<Message[]> {
375
+ const forAgent = pollQuery.for;
370
376
  //
371
377
  // #2335 (P1 privacy) — a poll whose `for` resolves to a channel-egress bridge is a DELIVERY poll by
372
378
  // construction: the only thing on the other end is a bridge about to forward what it receives into a
@@ -394,18 +400,18 @@ export const getMessages: Handler = async (req) => {
394
400
  // gets the COMPLETE set: `history` is still dashboard/thread-visible by definition, and this endpoint is
395
401
  // where the dashboard reads it. Suppressing there would evict it from the view (dashboard merge REPLACEs),
396
402
  // breaking the "no data loss" invariant — so the seam gates delivery, never display.
397
- if (url.searchParams.get("delivery") !== "turn") return json(polled);
403
+ if (!pollQuery.turnDelivery) return polled;
398
404
  const delivered: Message[] = [];
399
405
  for (const msg of polled) fanOutToAgent(forAgent, msg, () => delivered.push(msg));
400
- return json(delivered);
401
- };
406
+ return delivered;
407
+ }
402
408
 
403
409
  export const getMessageById: Handler = async (req, params) => {
404
410
  const id = parseId(params.id);
405
411
  if (id === null) return error("invalid message id");
406
412
  const msg = await getMessageAsync(id);
407
413
  if (!msg) return error("message not found", 404);
408
- return messageVisibleTo(messageViewerForRequest(req), msg) ? json(msg) : authorityDenied(req, "you can only read your own messages", 403, String(id), "read message");
414
+ return messageVisibleTo(messageViewerForRequest(req), msg) ? json(msg) : (await authorityDenied(req, "you can only read your own messages", 403, String(id), "read message"));
409
415
  };
410
416
 
411
417
  export const getMessageThread: Handler = async (req, params) => {
@@ -415,7 +421,7 @@ export const getMessageThread: Handler = async (req, params) => {
415
421
  if (!thread.length) return error("message not found", 404);
416
422
  const viewer = messageViewerForRequest(req);
417
423
  const root = thread.find((message) => message.id === id);
418
- if (root && !messageVisibleTo(viewer, root)) return authorityDenied(req, "you can only read your own messages", 403, String(id), "read thread");
424
+ if (root && !messageVisibleTo(viewer, root)) return (await authorityDenied(req, "you can only read your own messages", 403, String(id), "read thread"));
419
425
  return json(visibleMessages(viewer, thread));
420
426
  };
421
427
 
@@ -537,7 +543,7 @@ function channelReactionActor(actorId: string): Record<string, unknown> {
537
543
  };
538
544
  }
539
545
 
540
- function sendOutboundChannelReaction(parent: Message, actorId: string, emoji: string): void {
546
+ async function sendOutboundChannelReaction(parent: Message, actorId: string, emoji: string): Promise<void> {
541
547
  if (!parent.channel) return;
542
548
  const target = telegramTargetFromMessage(parent);
543
549
  if (!target) return;
@@ -545,7 +551,7 @@ function sendOutboundChannelReaction(parent: Message, actorId: string, emoji: st
545
551
  const accountId = target.accountId ?? cleanString(payloadChannel.accountId, "payload.channel.accountId", { max: 200 }) ?? "default";
546
552
  const conversation = isRecord(parent.payload?.conversation) ? parent.payload.conversation : undefined;
547
553
  const now = Date.now();
548
- const result = sendMessageWithResult({
554
+ const result = (await sendMessageWithResultAsync({
549
555
  from: actorId,
550
556
  to: parent.channel,
551
557
  kind: "channel.event",
@@ -580,7 +586,7 @@ function sendOutboundChannelReaction(parent: Message, actorId: string, emoji: st
580
586
  },
581
587
  },
582
588
  },
583
- });
589
+ }));
584
590
  if (result.created) {
585
591
  if (result.message.deliveryStatus === "queued") emitMessageQueued(result.message);
586
592
  else emitNewMessage(result.message);
@@ -601,8 +607,8 @@ export const postMessageReaction: Handler = async (req, params) => {
601
607
  const result = await setMessageReactionAsync({ messageId: id, actorId, emoji, action });
602
608
  if (!result.ok) return error(result.error, result.error === "message not found" ? 404 : 400);
603
609
  emitMessageReactionUpdated(result.message);
604
- if (action === "add") sendOutboundChannelReaction(result.message, actorId, emoji);
605
- sendReactionNotificationToAuthor(result.message, actorId, emoji, action);
610
+ if (action === "add") (await sendOutboundChannelReaction(result.message, actorId, emoji));
611
+ (await sendReactionNotificationToAuthor(result.message, actorId, emoji, action));
606
612
  return json(result.message);
607
613
  } catch (e) {
608
614
  if (e instanceof ValidationError) return error(e.message, 400);
@@ -61,6 +61,8 @@ export const postOrchestratorBootstrap: Handler = async (req) => {
61
61
  version,
62
62
  pathPrefix: pathPrefix ?? [],
63
63
  token: bootstrapToken.record,
64
+ // The single-use credential itself, for a caller that runs `orchestrator install` without the shell command (`humwick init`, #2680).
65
+ bootstrapToken: bootstrapToken.token,
64
66
  expiresAt: bootstrapToken.record.expiresAt,
65
67
  }, 201);
66
68
  } catch (e) {
@@ -76,7 +78,7 @@ export const postOrchestratorBootstrapExchange: Handler = async (req) => {
76
78
  if (!isRecord(parsed.body)) return error("body required");
77
79
  const id = cleanString(parsed.body.id, "id", { required: true, max: 120 })!;
78
80
  const baseDir = cleanString(parsed.body.baseDir, "baseDir", { required: true, max: 500 })!;
79
- const denied = authorizeRoute(req, { scope: "token:write", resource: { orchestratorId: id } });
81
+ const denied = (await authorizeRoute(req, { scope: "token:write", resource: { orchestratorId: id } }));
80
82
  if (denied) return denied;
81
83
  const auth = getComponentAuth(req);
82
84
  if (!auth || auth.role !== "orchestrator-bootstrap") return error("bootstrap token required", 403);
@@ -8,6 +8,7 @@ import { conflictingHardwareFields, upsertHostFromRegistrationAsync, type HostRe
8
8
  import { auditEvent, cleanSafeNumber } from "./_shared";
9
9
  import { recordOrchestratorUtilization } from "./orchestrator-host-utilization";
10
10
  import { cleanString } from "../validation";
11
+ import { reportRuntimeDependencyFailure } from "../services/runtime-dependency-alert";
11
12
 
12
13
  // The machine fingerprint an orchestrator reports at registration (§3.5). Lenient/observability-grade
13
14
  // like `cleanQueuedSpawns`: a malformed blob yields `undefined` (treated as "no fingerprint", never a
@@ -118,6 +119,7 @@ export async function linkOrchestratorHost(orchestratorId: string, hostname: str
118
119
  const result = await upsertHostFromRegistrationAsync({ orchestratorId, hostname, hardware });
119
120
  await emitHostRegistrationEvents(result.events);
120
121
  await recordOrchestratorUtilization(orchestratorId, result.host.id, body);
122
+ await reportRuntimeDependencyFailure(result.host.id, hostname, body);
121
123
  } catch (err) {
122
124
  // Additive over the orchestrator row; log so it is visible, then let the heartbeat path retry.
123
125
  console.warn(`[relay] host registration for orchestrator ${orchestratorId} (${hostname}) failed; will self-heal on next heartbeat:`, err);
@@ -247,11 +247,11 @@ export async function recordOrchestratorUtilization(
247
247
  const sample = cleanHostUtilizationSample(raw, now);
248
248
  if (!sample) return false;
249
249
  const gateArming = cleanGateArming(isRecord(body) ? body.gateArming : undefined, now);
250
- return recordHostUtilization({
250
+ return (await recordHostUtilization({
251
251
  hostId,
252
252
  orchestratorId,
253
253
  machine: { ...toMachineSample(sample), ...(gateArming ? { gateArming } : {}) },
254
254
  daemon: toDaemonSample(sample),
255
255
  now,
256
- });
256
+ }));
257
257
  }
@@ -153,8 +153,8 @@ export const getOrchestratorSessions: Handler = (req, params) => proxyOrchestrat
153
153
 
154
154
  export const getOrchestratorVersion: Handler = (req, params) => proxyOrchestratorGet(req, params.id!, "/api/version");
155
155
 
156
- export const getOrchestratorLogs: Handler = (req, params) => {
157
- const denied = authorizeRoute(req, { scope: "logs:read", resource: { orchestratorId: params.id!, logsRead: true } });
156
+ export const getOrchestratorLogs: Handler = async (req, params) => {
157
+ const denied = (await authorizeRoute(req, { scope: "logs:read", resource: { orchestratorId: params.id!, logsRead: true } }));
158
158
  return denied ?? proxyOrchestratorGet(req, params.id!, `/api/logs/${encodeURIComponent(params.session!)}`);
159
159
  };
160
160
 
@@ -1,3 +1,4 @@
1
+ import { deleteOrchestratorAsync } from "../db/runtime-tail-async";
1
2
  import { cleanBrowserInventory, reconcileBrowserInventory } from "../services/browser-inventory";
2
3
  // Auto-split from routes.ts (#299). Domain: orchestrator.
3
4
  import { APPROVAL_MODES, SPAWN_PROVIDERS, VALID_WORKSPACE_MODES, fireAndForget, isRecord } from "@humwick/sdk";
@@ -6,7 +7,7 @@ import { CONTRACT_VERSIONS, parseRuntimeCapabilities, parseRuntimeContracts, par
6
7
  import { notifyAgentOffline, notifyAgentSpawnQueued } from "../agent-lifecycle-events";
7
8
  import { diagnoseReportedExit } from "../services/reported-exit-death";
8
9
  import { VERSION } from "../config";
9
- import { ValidationError, deleteOrchestrator, effectiveProviderCatalogListAsync, getAgent, getOrchestrator, getOrchestratorAsync, listOrchestrators, listOrchestratorsAsync, orchestratorHeartbeatAsync, recordAgentExitDiagnosticsAsync, reportOrchestratorRosterAsync, setOrchestratorUpgradeStateAsync, upsertOrchestratorAsync } from "../db";
10
+ import { ValidationError, effectiveProviderCatalogListAsync, getAgent, getOrchestrator, getOrchestratorAsync, listOrchestrators, listOrchestratorsAsync, orchestratorHeartbeatAsync, recordAgentExitDiagnosticsAsync, reportOrchestratorRosterAsync, setOrchestratorUpgradeStateAsync, upsertOrchestratorAsync } from "../db";
10
11
  import { reconcileOrchestratorSchedulerCommands } from "../services/scheduler-recovery.ts";
11
12
  import { recoverRegisteredOrchestrator } from "../services/orchestrator-registration-recovery";
12
13
  import { recoverOrchestratorLegacyLandings } from "../services/orchestrator-landing-recovery";
@@ -24,10 +25,9 @@ import { serializeCommandForRead } from "../services/dispatch-command";
24
25
  import { isOrchestratorRegistrationAuthorized } from "../security";
25
26
  import { isOrchestratorSelfReportAuthorized } from "../orchestrator-self-report-authz";
26
27
  import { getHostProviderSetting } from "../host-provider-store";
27
- import { hostDisabledFromValue } from "../host-provider-enablement";
28
+ import { hostDisabledFromValue, isHostSwitchableProvider } from "../host-provider-enablement";
28
29
  import { seedHostProviders } from "../services/host-providers";
29
- import { isHostSwitchableProvider } from "../host-provider-enablement";
30
- import { type ManagedAgent, type ManagedSessionExitDiagnostics, type OrchestratorRuntimeInput, type QueuedSpawn, type RegisterOrchestratorInput, type SpawnApprovalMode, type SpawnProvider } from "../types";
30
+ import { type ManagedAgent, type ManagedSessionExitDiagnostics, type Orchestrator, type OrchestratorRuntimeInput, type QueuedSpawn, type RegisterOrchestratorInput, type SpawnApprovalMode, type SpawnProvider } from "../types";
31
31
  import { restartSpawnParamsForAgentAsync } from "../services/restart-spawn";
32
32
  import { cleanProjectToolchain } from "../project-toolchain";
33
33
  import { cleanHostTools } from "../host-tools";
@@ -215,8 +215,17 @@ function orchestratorSelfReportDenied(req: Request, orchestratorId: string): Res
215
215
  return error("forbidden: only the orchestrator itself may report its host state", 403);
216
216
  }
217
217
 
218
+ // #2410 — the list is polled by every open dashboard and the per-host `providerCatalog` (a
219
+ // deprecated host snapshot, stored in the row and again in `meta`) was ~85% of a 515 KB response
220
+ // nothing reads: the hub owns the model catalog. It stays on the row (`GET /:id`) and in the DB.
221
+ function withoutHostCatalog(orch: Orchestrator): Orchestrator {
222
+ const { providerCatalog: _snapshot, ...row } = orch;
223
+ const { providerCatalog: _metaSnapshot, ...meta } = orch.meta;
224
+ return { ...row, meta };
225
+ }
226
+
218
227
  export const getOrchestrators: Handler = async () => {
219
- return json(await listOrchestratorsAsync());
228
+ return json((await listOrchestratorsAsync()).map(withoutHostCatalog));
220
229
  };
221
230
 
222
231
  export const getOrchestratorById: Handler = async (_req, params) => {
@@ -239,7 +248,7 @@ export const postOrchestratorHeartbeat: Handler = async (req, params) => {
239
248
  const parsed = await parseBody<unknown>(req);
240
249
  if (!parsed.ok) return error(parsed.error, parsed.status);
241
250
  try {
242
- const denied = authorizeRoute(req, { scope: "command:write", resource: { orchestratorId: params.id! } });
251
+ const denied = (await authorizeRoute(req, { scope: "command:write", resource: { orchestratorId: params.id! } }));
243
252
  if (denied) return denied;
244
253
  // #1797 round 2 (F1) — same self-report claim as the roster PATCH: this writes the host's
245
254
  // reported version/providers/capabilities, which the upgrade reconcile then acts on.
@@ -292,7 +301,7 @@ export const patchOrchestratorAgents: Handler = async (req, params) => {
292
301
  try {
293
302
  const orch = getOrchestrator(params.id!);
294
303
  if (!orch) return error("orchestrator not found", 404);
295
- const denied = authorizeRoute(req, { scope: "command:write", resource: { orchestratorId: orch.id } });
304
+ const denied = (await authorizeRoute(req, { scope: "command:write", resource: { orchestratorId: orch.id } }));
296
305
  if (denied) return denied;
297
306
  // #1797 round 2 (F1) — this roster IS the input to the managed-state reconcile; the scope +
298
307
  // resource check above cannot establish that the caller IS this orchestrator. See the helper.
@@ -344,7 +353,7 @@ export const patchOrchestratorAgents: Handler = async (req, params) => {
344
353
  if (queuedSpawns) {
345
354
  for (const queued of queuedSpawns) {
346
355
  if (!queued.spawnedBy) continue;
347
- notifyAgentSpawnQueued({
356
+ await notifyAgentSpawnQueued({
348
357
  parent: queued.spawnedBy,
349
358
  spawnRequestId: queued.spawnRequestId,
350
359
  provider: queued.provider,
@@ -357,7 +366,7 @@ export const patchOrchestratorAgents: Handler = async (req, params) => {
357
366
  // between the ack and this call, so reconciles still run in request order. Running it after
358
367
  // the exit-audit loop below (which awaits the async gateway per exited agent) let a stale,
359
368
  // superseded roster from a slow request land AFTER a newer report's reconcile and overwrite it.
360
- getLifecycleManager().onOrchestratorManagedAgentsReported(params.id!, cleaned, exitedAgents);
369
+ (await getLifecycleManager().onOrchestratorManagedAgentsReported(params.id!, cleaned, exitedAgents));
361
370
  for (const exited of exitedAgents) {
362
371
  const agent = await recordAgentExitDiagnosticsAsync(exited.agentId, exited);
363
372
  if (agent) {
@@ -370,7 +379,7 @@ export const patchOrchestratorAgents: Handler = async (req, params) => {
370
379
  // #636 — classify the death from the captured exit diagnostics + agent state and ride the
371
380
  // verdict on the terminal event (also persisted as a crash report inside notifyAgentOffline).
372
381
  // Exit diagnostics remain on replay; the shared generation ledger dedups the parent notice.
373
- notifyAgentOffline(exited.agentId, exitReason(exited), diagnoseReportedExit(agent, exitReason(exited), exited));
382
+ (await notifyAgentOffline(exited.agentId, exitReason(exited), diagnoseReportedExit(agent, exitReason(exited), exited)));
374
383
  }
375
384
  await auditEvent({
376
385
  clientId: [
@@ -550,9 +559,9 @@ export const postOrchestratorAction: Handler = async (req, params) => {
550
559
  if (action === "migrate-provider-config") {
551
560
  // #1259 — fleet-wide host action: a command:fleet-scoped token may cross its own
552
561
  // cwd/orchestrator sandbox pin for this action only.
553
- const denied = authorizeFleetRoute(req, { orchestratorId: orch.id });
562
+ const denied = (await authorizeFleetRoute(req, { orchestratorId: orch.id }));
554
563
  if (denied) return denied;
555
- const command = dispatchProviderConfigMigration(orch, "dashboard");
564
+ const command = (await dispatchProviderConfigMigration(orch, "dashboard"));
556
565
  if (!command) return error(`orchestrator ${orch.id} does not support provider-config migration; upgrade it first`, 409);
557
566
  await auditEvent({
558
567
  clientId: `server-orchestrator-migrate-provider-config-${orch.id}-${command.id}`,
@@ -570,7 +579,7 @@ export const postOrchestratorAction: Handler = async (req, params) => {
570
579
  if (action === "upgrade") {
571
580
  // #1259 — fleet-wide host action: a command:fleet-scoped token may cross its own
572
581
  // cwd/orchestrator sandbox pin for this action only.
573
- const denied = authorizeFleetRoute(req, { orchestratorId: orch.id });
582
+ const denied = (await authorizeFleetRoute(req, { orchestratorId: orch.id }));
574
583
  if (denied) return denied;
575
584
  const targetVersion = cleanString(parsed.body.targetVersion, "targetVersion", { max: 80 }) ?? VERSION;
576
585
  if (!ORCH_UPGRADE_SEMVER_RE.test(targetVersion)) return error("targetVersion must be a semver like 0.10.20");
@@ -657,8 +666,8 @@ export const postOrchestratorAction: Handler = async (req, params) => {
657
666
  // command:fleet; "shutdown" is NOT in that enumeration and stays on the constrained path.
658
667
  const resource = { orchestratorId: orch.id, agentId, policyName, spawnRequestId };
659
668
  const denied = action === "restart"
660
- ? authorizeFleetRoute(req, resource)
661
- : authorizeRoute(req, { scope: "command:write", resource });
669
+ ? (await authorizeFleetRoute(req, resource))
670
+ : (await authorizeRoute(req, { scope: "command:write", resource }));
662
671
  if (denied) return denied;
663
672
  const agent = action === "restart" && agentId ? getAgent(agentId) : undefined;
664
673
  const restartSpawn = agent ? await restartSpawnParamsForAgentAsync(agent, orch, policyName, spawnRequestId) : undefined;
@@ -690,10 +699,10 @@ export const postOrchestratorAction: Handler = async (req, params) => {
690
699
  }
691
700
  };
692
701
 
693
- export const deleteOrchestratorById: Handler = (req, params) => {
694
- const denied = authorizeRoute(req, { scope: "system:admin", resource: { orchestratorId: params.id! } });
702
+ export const deleteOrchestratorById: Handler = async (req, params) => {
703
+ const denied = (await authorizeRoute(req, { scope: "system:admin", resource: { orchestratorId: params.id! } }));
695
704
  if (denied) return denied;
696
- const deleted = deleteOrchestrator(params.id!);
705
+ const deleted = (await deleteOrchestratorAsync(params.id!));
697
706
  if (!deleted) return error("orchestrator not found", 404);
698
707
  return json({ ok: true });
699
708
  };
@@ -1,6 +1,7 @@
1
+ import { sendPairMessageAsync, rejectPairAsync, endPairAsync, createPairAsync, acceptPairAsync, getPairAsync, listPairsAsync } from "../db/pairs-async";
1
2
  // Auto-split from routes.ts (#299). Domain: pairs.
2
3
  import { MAX_BODY_BYTES } from "../config";
3
- import { ValidationError, acceptPair, createPair, endPair, getPair, listAgents, listPairs, rejectPair, sendPairMessage } from "../db";
4
+ import { ValidationError, getPair, listAgents, listPairs } from "../db";
4
5
  import { resolveCallerAgentId } from "../agent-ref";
5
6
  import { getComponentAuth, hasComponentScope } from "../security";
6
7
  import { auditEvent, authorizeRoute, error, json, parseBody, type Handler } from "./_shared";
@@ -59,7 +60,7 @@ export const postPair: Handler = async (req) => {
59
60
  const parsed = await parseBody<unknown>(req);
60
61
  if (!parsed.ok) return error(parsed.error, parsed.status);
61
62
  try {
62
- const result = createPair(normalizeCreatePairInput(parsed.body));
63
+ const result = (await createPairAsync(normalizeCreatePairInput(parsed.body)));
63
64
  if (!result.ok) return pairError(result);
64
65
  emitNewMessage(result.invite);
65
66
  await auditEvent({
@@ -96,7 +97,7 @@ export const getPairs: Handler = async (req) => {
96
97
  ? resolveCallerAgentId(component.constraints, listAgents)
97
98
  : undefined;
98
99
  if (!(agentId && callerAgentId === agentId && component && hasComponentScope(component, "agent:read"))) {
99
- const denied = authorizeRoute(req, { scope: "pairs:read" });
100
+ const denied = (await authorizeRoute(req, { scope: "pairs:read" }));
100
101
  if (denied) return denied;
101
102
  }
102
103
 
@@ -115,7 +116,7 @@ export const postAcceptPair: Handler = async (req, params) => {
115
116
  const parsed = await parseBody<unknown>(req);
116
117
  if (!parsed.ok) return error(parsed.error, parsed.status);
117
118
  try {
118
- const result = acceptPair(params.id!, normalizePairActionInput(parsed.body));
119
+ const result = (await acceptPairAsync(params.id!, normalizePairActionInput(parsed.body)));
119
120
  if (!result.ok) return pairError(result);
120
121
  for (const notice of result.notices) emitNewMessage(notice);
121
122
  await auditEvent({
@@ -140,7 +141,7 @@ export const postRejectPair: Handler = async (req, params) => {
140
141
  const parsed = await parseBody<unknown>(req);
141
142
  if (!parsed.ok) return error(parsed.error, parsed.status);
142
143
  try {
143
- const result = rejectPair(params.id!, normalizePairActionInput(parsed.body));
144
+ const result = (await rejectPairAsync(params.id!, normalizePairActionInput(parsed.body)));
144
145
  if (!result.ok) return pairError(result);
145
146
  emitNewMessage(result.notice);
146
147
  await auditEvent({
@@ -165,7 +166,7 @@ export const postHangupPair: Handler = async (req, params) => {
165
166
  const parsed = await parseBody<unknown>(req);
166
167
  if (!parsed.ok) return error(parsed.error, parsed.status);
167
168
  try {
168
- const result = endPair(params.id!, normalizePairActionInput(parsed.body));
169
+ const result = (await endPairAsync(params.id!, normalizePairActionInput(parsed.body)));
169
170
  if (!result.ok) return pairError(result);
170
171
  if (result.notice) emitNewMessage(result.notice);
171
172
  await auditEvent({
@@ -190,7 +191,7 @@ export const postPairMessage: Handler = async (req, params) => {
190
191
  const parsed = await parseBody<unknown>(req);
191
192
  if (!parsed.ok) return error(parsed.error, parsed.status);
192
193
  try {
193
- const result = sendPairMessage(params.id!, normalizePairMessageInput(parsed.body));
194
+ const result = (await sendPairMessageAsync(params.id!, normalizePairMessageInput(parsed.body)));
194
195
  if (!result.ok) return pairError(result);
195
196
  emitNewMessage(result.message);
196
197
  await auditEvent({
@@ -211,4 +212,3 @@ export const postPairMessage: Handler = async (req, params) => {
211
212
  throw e;
212
213
  }
213
214
  };
214
- import { getPairAsync, listPairsAsync } from "../db/pairs-async";
@@ -6,7 +6,7 @@ import { PromptVersionConflictError } from "../prompt-version-errors";
6
6
  import { listProjectProfileInstructions, mutateProjectProfileInstructions, projectProfileInstructionHistory, readProjectProfileInstructions } from "../services/project-profile-instructions";
7
7
 
8
8
  export const projectProfileInstructionsRoute: Handler = async (req, params) => {
9
- const denied = authorizeRoute(req, { scope: req.method === "GET" ? "agent:read" : "agent:write" });
9
+ const denied = (await authorizeRoute(req, { scope: req.method === "GET" ? "agent:read" : "agent:write" }));
10
10
  if (denied) return denied;
11
11
  try {
12
12
  const projectId = cleanString(params.id, "projectId", { max: 200 });
@@ -32,7 +32,7 @@ export const postProjectTrustApproveRoute: Handler = async (req, params) => {
32
32
  const mode = optionalEnum(body.mode, "mode", ["fingerprint", "commit"] as const);
33
33
  if (mode && !approvedValue.startsWith(mode === "commit" ? "commit:" : "sha256:")) return error(`approved value must be prefixed "${mode === "commit" ? "commit:" : "sha256:"}" for ${mode} review`, 400);
34
34
 
35
- const approval = approveProfileProjectTrust({ name, capability, repoKey, value: approvedValue, by: requestUserAddress(req) });
35
+ const approval = (await approveProfileProjectTrust({ name, capability, repoKey, value: approvedValue, by: requestUserAddress(req) }));
36
36
  await auditEvent({
37
37
  kind: "state",
38
38
  title: `Project trust approved: ${name} / ${capability}`,
@@ -1,4 +1,4 @@
1
- import { getProjectEntry, getProjectEntryChain, listProjectsAsync, resolveProjectAsync, resolveProjectEntriesAsync, retractProjectEntry, rootsForProjectAsync, searchProjectEntriesAsync, writeProjectEntry, ValidationError } from "../db";
1
+ import { getProjectEntryAsync, getProjectEntryChainAsync, listProjectsAsync, resolveProjectAsync, resolveProjectEntriesAsync, retractProjectEntryAsync, rootsForProjectAsync, searchProjectEntriesAsync, writeProjectEntryAsync, ValidationError } from "../db";
2
2
  import { resolveProjectForCanonicalCwdAsync } from "../services/project";
3
3
  import { authContextFromRequest } from "../services/auth-context";
4
4
  import { callerProfile, resolveAgentWriteInject } from "../services/memory-identity";
@@ -14,7 +14,7 @@ import { PROJECT_ENTRY_INJECT_TIERS, PROJECT_ENTRY_KINDS, type ProjectEntry, typ
14
14
  //
15
15
  // #1940 Part 2 — manual/promoted entry CRUD from the dashboard. Mutations are thin wrappers
16
16
  // around the SAME db functions the audited `relay_project_write_entry`/`relay_project_retract`
17
- // MCP tools call (writeProjectEntry/retractProjectEntry, src/db/project-entries.ts) — one
17
+ // MCP tools call (writeProjectEntryAsync/retractProjectEntryAsync, src/db/project-entries.ts) — one
18
18
  // write path for both surfaces, never a direct/duplicated DB write here. `ingested` entries
19
19
  // are refused because the CLAUDE.md ingest pipeline owns them. `steward` entries remain
20
20
  // operator-curatable: an edit adopts the replacement as `manual` input for a later sweep.
@@ -103,12 +103,12 @@ export const getProjectResolveRoute: Handler = async (req) => {
103
103
  }
104
104
  };
105
105
 
106
- export const getProjectEntryRoute: Handler = (req, params) => {
106
+ export const getProjectEntryRoute: Handler = async (req, params) => {
107
107
  try {
108
108
  const id = cleanString(params.entryId, "entryId", { required: true, max: 120 })!;
109
- const entry = getProjectEntry(id);
109
+ const entry = await getProjectEntryAsync(id);
110
110
  if (!entry) return error("project entry not found", 404);
111
- return json({ entry, chain: getProjectEntryChain(id) });
111
+ return json({ entry, chain: await getProjectEntryChainAsync(id) });
112
112
  } catch (err) {
113
113
  return error(err instanceof Error ? err.message : "projects route failed");
114
114
  }
@@ -130,8 +130,8 @@ function cleanAudience(value: unknown): ProjectEntryAudience | undefined {
130
130
 
131
131
  // Historical steward entries retain the same curation rights as manual entries (#3456).
132
132
  // Only the current active version is editable, preserving supersession and retraction.
133
- function loadEditableEntry(projectId: string, entryId: string): { entry: ProjectEntry } | { errorResponse: Response } {
134
- const entry = getProjectEntry(entryId);
133
+ async function loadEditableEntry(projectId: string, entryId: string): Promise<{ entry: ProjectEntry } | { errorResponse: Response }> {
134
+ const entry = await getProjectEntryAsync(entryId);
135
135
  if (!entry || entry.projectId !== projectId) return { errorResponse: error("project entry not found", 404) };
136
136
  if (!isEditableSource(entry.source)) {
137
137
  return { errorResponse: error(`${entry.source} entries are owned by the ingest pipeline and cannot be edited or removed here`, 409) };
@@ -170,7 +170,7 @@ export const postProjectEntryRoute: Handler = async (req, params) => {
170
170
  // Use the same caller placement as MCP writes; dashboard callers fall back to project roots.
171
171
  // Areas stay optional because the dashboard has no areas input yet.
172
172
  const areas = await resolveWriteAreas(project, areaCallerFromCtx(authContextFromRequest(req)), parsed.body.areas, { requireDeclared: false });
173
- const entry = writeProjectEntry({
173
+ const entry = await writeProjectEntryAsync({
174
174
  projectId: project.id,
175
175
  authorId: requestUserAddress(req),
176
176
  kind,
@@ -188,7 +188,7 @@ export const postProjectEntryRoute: Handler = async (req, params) => {
188
188
  agentId: entry.authorId,
189
189
  metadata: projectEntryAuditMetadata(req, "relay_project_write_entry", project.id, entry.id),
190
190
  });
191
- return json({ entry, ...(tier.note ? { injectNote: tier.note } : {}), ...areaDeliveryReport(entry) }, 201);
191
+ return json({ entry, ...(tier.note ? { injectNote: tier.note } : {}), ...await areaDeliveryReport(entry) }, 201);
192
192
  } catch (err) {
193
193
  if (err instanceof ValidationError) return error(err.message, 400);
194
194
  return error(err instanceof Error ? err.message : "projects route failed");
@@ -196,7 +196,7 @@ export const postProjectEntryRoute: Handler = async (req, params) => {
196
196
  };
197
197
 
198
198
  // PATCH /api/projects/:id/entries/:entryId — Edit (#1940 Part 2). There is no in-place UPDATE
199
- // in the ledger (writeProjectEntry only inserts); an edit is a new entry that `supersedes` the
199
+ // in the ledger (writeProjectEntryAsync only inserts); an edit is a new entry that `supersedes` the
200
200
  // old one — the exact mechanism relay_project_write_entry's `supersedes` param already gives
201
201
  // agents. Omitted fields fall back to the current entry's value (a partial patch, not a
202
202
  // full-replace); an explicit `null` for `body` clears it.
@@ -206,7 +206,7 @@ export const patchProjectEntryRoute: Handler = async (req, params) => {
206
206
  const project = await resolveProjectAsync(ref);
207
207
  if (!project) return error("project not found", 404);
208
208
  const entryId = cleanString(params.entryId, "entryId", { required: true, max: 120 })!;
209
- const loaded = loadEditableEntry(project.id, entryId);
209
+ const loaded = await loadEditableEntry(project.id, entryId);
210
210
  if ("errorResponse" in loaded) return loaded.errorResponse;
211
211
  const { entry } = loaded;
212
212
 
@@ -234,7 +234,7 @@ export const patchProjectEntryRoute: Handler = async (req, params) => {
234
234
  );
235
235
  const areas = await resolveWriteAreas(project, areaCallerFromCtx(authContextFromRequest(req)), body.areas, { prior: entry.areas, requireDeclared: false });
236
236
 
237
- const updated = writeProjectEntry({
237
+ const updated = await writeProjectEntryAsync({
238
238
  projectId: project.id,
239
239
  authorId: requestUserAddress(req),
240
240
  kind,
@@ -250,7 +250,7 @@ export const patchProjectEntryRoute: Handler = async (req, params) => {
250
250
  source: entry.source === "steward" ? "manual" : entry.source,
251
251
  originRef: entry.originRef,
252
252
  sensitivity: entry.sensitivity,
253
- // Carry a POSITIVE prior TTL only: writeProjectEntry rejects invalid epochs, so a corrupt
253
+ // Carry a POSITIVE prior TTL only: writeProjectEntryAsync rejects invalid epochs, so a corrupt
254
254
  // legacy value cannot turn a partial dashboard edit into a failed adoption.
255
255
  ...(entry.expiresAt !== undefined && entry.expiresAt > 0 ? { expiresAt: entry.expiresAt } : {}),
256
256
  });
@@ -261,7 +261,7 @@ export const patchProjectEntryRoute: Handler = async (req, params) => {
261
261
  agentId: updated.authorId,
262
262
  metadata: projectEntryAuditMetadata(req, "relay_project_write_entry", project.id, updated.id, { supersedes: entry.id }),
263
263
  });
264
- return json({ entry: updated, ...(tier.note ? { injectNote: tier.note } : {}), ...areaDeliveryReport(updated) });
264
+ return json({ entry: updated, ...(tier.note ? { injectNote: tier.note } : {}), ...await areaDeliveryReport(updated) });
265
265
  } catch (err) {
266
266
  if (err instanceof ValidationError) return error(err.message, 400);
267
267
  return error(err instanceof Error ? err.message : "projects route failed");
@@ -276,10 +276,10 @@ export const deleteProjectEntryRoute: Handler = async (req, params) => {
276
276
  const project = await resolveProjectAsync(ref);
277
277
  if (!project) return error("project not found", 404);
278
278
  const entryId = cleanString(params.entryId, "entryId", { required: true, max: 120 })!;
279
- const loaded = loadEditableEntry(project.id, entryId);
279
+ const loaded = await loadEditableEntry(project.id, entryId);
280
280
  if ("errorResponse" in loaded) return loaded.errorResponse;
281
281
 
282
- const retracted = retractProjectEntry(entryId);
282
+ const retracted = await retractProjectEntryAsync(entryId);
283
283
  if (!retracted) return error("project entry not found", 404);
284
284
  await auditEvent({
285
285
  kind: "state",