@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,10 +1,9 @@
1
- import {
2
- addProjectRoot,
3
- ensureProject,
4
- upsertOrchestrator,
5
- writeProjectEntry,
6
- } from "../../db";
7
- import { setAgentProfile } from "../../config-store";
1
+ import { setAgentProfileAsync } from "../../config-store-write";
2
+ import { writeProjectEntryAsync } from "../../db/project-entries-async";
3
+ import { ensureProjectAsync, addProjectRootAsync } from "../../db/projects-async";
4
+ import { upsertOrchestratorAsync } from "../../db/orchestrators-async";
5
+
6
+
8
7
  import { upsertHostFromRegistrationInternal } from "../../db/hosts-registration";
9
8
  import { parseMemorySeam } from "../../memory-seam";
10
9
  import type { AgentProfile, Command } from "../../types";
@@ -17,8 +16,8 @@ import type { MemoryFixture, ProvisioningDriverRequest } from "./types";
17
16
  export const HARNESS_ORCHESTRATOR_ID = "provisioning-harness";
18
17
  export const HARNESS_HOST = "harness-host";
19
18
 
20
- export function seedHarnessHost(cwd: string): void {
21
- upsertOrchestrator({ id: HARNESS_ORCHESTRATOR_ID, hostname: HARNESS_HOST, providers: ["claude", "codex"], baseDir: cwd });
19
+ export async function seedHarnessHost(cwd: string): Promise<void> {
20
+ (await upsertOrchestratorAsync({ id: HARNESS_ORCHESTRATOR_ID, hostname: HARNESS_HOST, providers: ["claude", "codex"], baseDir: cwd }));
22
21
  upsertHostFromRegistrationInternal({ orchestratorId: HARNESS_ORCHESTRATOR_ID, hostname: HARNESS_HOST,
23
22
  hardware: { platform: "linux", arch: "x64", cpuThreads: 8, totalMemMb: 16384 } }, 1_700_000_000_000);
24
23
  }
@@ -33,13 +32,13 @@ function defaults(profile: string): MemoryFixture[] {
33
32
  ];
34
33
  }
35
34
 
36
- export function seedMemory(cwd: string, request: ProvisioningDriverRequest): void {
35
+ export async function seedMemory(cwd: string, request: ProvisioningDriverRequest): Promise<void> {
37
36
  const { profile } = request.scenario;
38
- const project = ensureProject({ slug: "provisioning-harness", title: "Provisioning harness" });
39
- addProjectRoot(project.id, cwd);
37
+ const project = (await ensureProjectAsync({ slug: "provisioning-harness", title: "Provisioning harness" }));
38
+ (await addProjectRootAsync(project.id, cwd));
40
39
  for (const fixture of request.scenario.fixtures?.memory ?? defaults(profile)) {
41
40
  if (fixture.cell !== "project") throw new Error("Only project knowledge fixtures are supported");
42
- writeProjectEntry({
41
+ (await writeProjectEntryAsync({
43
42
  projectId: project.id,
44
43
  kind: "rule",
45
44
  title: fixture.title,
@@ -49,7 +48,7 @@ export function seedMemory(cwd: string, request: ProvisioningDriverRequest): voi
49
48
  originRef: fixture.originRef ?? `harness:${fixture.id}`,
50
49
  audience: fixture.audience ?? "all",
51
50
  inject: fixture.inject ?? "pinned",
52
- });
51
+ }));
53
52
  }
54
53
  }
55
54
 
@@ -69,10 +68,10 @@ export async function prepareProvisioningSpawn(request: ProvisioningDriverReques
69
68
  (error as Error & { code: string }).code = "PROVISIONING_SPAWN_INPUT_REJECTED";
70
69
  throw error;
71
70
  }
72
- seedHarnessHost(scenario.cwd);
73
- seedMemory(scenario.cwd, request);
71
+ (await seedHarnessHost(scenario.cwd));
72
+ (await seedMemory(scenario.cwd, request));
74
73
  if (scenario.profileOverride) {
75
- setAgentProfile({ name: scenario.profile, ...scenario.profileOverride } as AgentProfile, "provisioning-harness", { overrideBuiltIn: true });
74
+ (await setAgentProfileAsync({ name: scenario.profile, ...scenario.profileOverride } as AgentProfile, "provisioning-harness", { overrideBuiltIn: true }));
76
75
  }
77
76
  const spawnRequestId = `sp_harness_${scenario.id.replace(/[^A-Za-z0-9._-]/g, "-").slice(0, 56)}`;
78
77
  const result = await spawnAgent({
@@ -1,6 +1,7 @@
1
+ import { mergeAgentMetaAsync } from "../db/agents-async";
1
2
  import { relayEnv } from "@humwick/sdk/env";
2
3
  import { PROXY_AUTH_HOLD_KIND } from "@humwick/sdk";
3
- import { createActivityEventAsync, getAgent, mergeAgentMeta } from "../db";
4
+ import { createActivityEventAsync, getAgent } from "../db";
4
5
  import { listRateLimitHoldCandidates } from "../db/agent-card-read";
5
6
  import { withBufferedPresence } from "../db/presence-buffer";
6
7
  import { rateLimitFallbackMs } from "../config";
@@ -72,10 +73,10 @@ function nextTransientState(state: ProviderState, now: number, attempts: number)
72
73
  };
73
74
  }
74
75
 
75
- function notifyTransientExhausted(agent: { id: string; label?: string | null; spawnedBy?: string | null }, state: ProviderState, now: number): void {
76
- mergeAgentMeta(agent.id, { providerState: { ...state, exhaustedAt: now, updatedAt: now } });
76
+ async function notifyTransientExhausted(agent: { id: string; label?: string | null; spawnedBy?: string | null }, state: ProviderState, now: number): Promise<void> {
77
+ (await mergeAgentMetaAsync(agent.id, { providerState: { ...state, exhaustedAt: now, updatedAt: now } }));
77
78
  if (!agent.spawnedBy) return;
78
- routeNotification({
79
+ await routeNotification({
79
80
  type: "agent.provider_blocked",
80
81
  scope: { agentId: agent.id, parent: agent.spawnedBy },
81
82
  recipients: [agent.spawnedBy],
@@ -126,7 +127,7 @@ export async function resumeRateLimitedAgents(context: { signal?: AbortSignal }
126
127
  const persistedExhaustedAt = typeof state.exhaustedAt === "number" && Number.isFinite(state.exhaustedAt) ? state.exhaustedAt : undefined;
127
128
  const justExhausted = exhausted && !tracked.exhaustedNotified && persistedExhaustedAt === undefined;
128
129
  if (justExhausted) {
129
- notifyTransientExhausted(agent, state, now);
130
+ await notifyTransientExhausted(agent, state, now);
130
131
  resumeTracker.set(agent.id, { ...tracked, attempts, exhaustedNotified: true });
131
132
  }
132
133
  // #2619 — exhausting the fast backoff must never become a permanent, silent stop (an agent
@@ -141,7 +142,7 @@ export async function resumeRateLimitedAgents(context: { signal?: AbortSignal }
141
142
  try {
142
143
  // Short default TTL (per-type): a "limit reset, resume" push is pointless once stale — the
143
144
  // window has moved on. One recipient per iteration keeps the per-agent rollback below intact.
144
- routeNotification({
145
+ await routeNotification({
145
146
  type: "agent.rate_limit_resume",
146
147
  scope: { agentId: agent.id },
147
148
  recipients: [agent.id],
@@ -166,17 +167,17 @@ export async function resumeRateLimitedAgents(context: { signal?: AbortSignal }
166
167
  continue;
167
168
  }
168
169
 
169
- if (transient && !exhausted) mergeAgentMeta(agent.id, { providerState: nextTransientState(state, now, attempts) });
170
+ if (transient && !exhausted) (await mergeAgentMetaAsync(agent.id, { providerState: nextTransientState(state, now, attempts) }));
170
171
  // #2619 — persist every exhausted-mode probe, so a relay restart after probe N keeps the
171
172
  // clock (lastProbe reads state.lastResumeAt). Re-read: the exhaustion notice above may have
172
173
  // just persisted exhaustedAt, which must survive (never re-stamped).
173
174
  else if (exhausted) {
174
175
  const current = agentProviderState(getAgent(agent.id)) ?? state;
175
- mergeAgentMeta(agent.id, { providerState: { ...current, lastResumeAt: now, updatedAt: now } });
176
+ (await mergeAgentMetaAsync(agent.id, { providerState: { ...current, lastResumeAt: now, updatedAt: now } }));
176
177
  }
177
178
 
178
179
  // #416 — flush messages queued while the agent was rate-limited.
179
- flushQueuedDirectMessages(agent.id);
180
+ (await flushQueuedDirectMessages(agent.id));
180
181
  // The held-agent card and provider state above are the accepted resume snapshot. Persist its
181
182
  // audit before admitting the next agent, so concurrent provider updates cannot relabel it.
182
183
  await beforeRateLimitResumeAuditForTests?.(agent.id);
@@ -1,11 +1,13 @@
1
+ import { upsertWorkspaceAsync } from "../db/runtime-admin-async";
1
2
  import { relayEnv } from "@humwick/sdk/env";
2
3
  import { createHash } from "node:crypto";
3
4
  import type { LandBoundary, RedMainIncident } from "@humwick/kernel/landing-incident";
4
5
  import { errMessage, isRecord, stringValue, type Command } from "@humwick/sdk";
5
- import { findCommandByCorrelationId, findLatestCommandByCorrelation } from "../commands-db";
6
+ import { findCommandByCorrelationId } from "../commands-db";
7
+ import { findLatestCommandByCorrelationAsync } from "../commands-write";
6
8
  import { getCommandAsync } from "../commands-write";
7
9
  import { isTerminalCommandStatus } from "../db/command-terminal-status";
8
- import { getWorkspace, upsertWorkspace } from "../db/workspaces";
10
+ import { getWorkspace } from "../db/workspaces";
9
11
  import { landBoundaryById, landBoundaryForCommand, redMainIncidentById } from "../db/land-boundaries";
10
12
  import { readFailedTestFiles } from "../ci/failed-test-files";
11
13
  import type { GitHubApi } from "../issue-tracker/github";
@@ -70,13 +72,13 @@ async function advanceAutomaticRevert(incident: RedMainIncident, boundary: LandB
70
72
  /** One direct, pinned, gated land per prepared red-main workspace: the revert's or the quarantine's. */
71
73
  export async function landRedMainWorkspace(id: string, boundary: LandBoundary, prepared: Record<string, unknown>,
72
74
  metadata: Record<string, unknown>, recoveryTestFiles?: string[]): Promise<Command> {
73
- const existing = findLatestCommandByCorrelation("workspace.merge", id);
75
+ const existing = await findLatestCommandByCorrelationAsync("workspace.merge", id);
74
76
  if (existing) return existing;
75
77
  const source = getWorkspace(boundary.workspaceId)!;
76
- const workspace = getWorkspace(id) ?? upsertWorkspace({ id, repoRoot: source.repoRoot, sourceCwd: source.repoRoot,
78
+ const workspace = getWorkspace(id) ?? (await upsertWorkspaceAsync({ id, repoRoot: source.repoRoot, sourceCwd: source.repoRoot,
77
79
  worktreePath: String(prepared.worktreePath), branch: String(prepared.branch), baseRef: boundary.baseRef,
78
80
  baseSha: String(prepared.baseSha), mode: "isolated", status: "ready", orchestratorId: source.orchestratorId,
79
- metadata: { ...metadata, landStrategy: "direct" } });
81
+ metadata: { ...metadata, landStrategy: "direct" } }));
80
82
  const requested = await requestWorkspaceMerge(workspace, { requestedBy: "red-main-controller", strategy: "direct",
81
83
  expectedHeadSha: String(prepared.headSha), deleteBranch: true, ...(recoveryTestFiles ? { recoveryTestFiles } : {}) });
82
84
  if (!requested.ok) throw new Error(requested.error);
@@ -1,8 +1,8 @@
1
1
  // #3363 — the red-main controller's production deps: GitHub for CI verdicts and reruns, Tasks and
2
2
  // messages for escalation. Every CI observation uses the boundary's authoritative watch snapshot.
3
- import type { LandBoundary, RedMainIncident } from "@humwick/kernel/landing-incident";
3
+ import { MAX_INCIDENT_FAILING_TESTS, type LandBoundary, type RedMainIncident } from "@humwick/kernel/landing-incident";
4
4
  import { cleanLandGatesConfigFull } from "@humwick/sdk/land-gates";
5
- import { isRecord } from "@humwick/sdk";
5
+ import { ciRunUrl, errMessage, isRecord } from "@humwick/sdk";
6
6
  import { judgeExactSha, rerunBoundaryCi, type BoundaryCiObservation } from "../ci/land-boundary-ci.ts";
7
7
  import { type GitHubRepository } from "../ci/monitor.ts";
8
8
  import { getTaskDetailAsync } from "../db/task-entity-async.ts";
@@ -12,6 +12,8 @@ import { sendMessageServiceAsync } from "./send-message.ts";
12
12
  import { setTaskEntityStatusAsync } from "./task-entity.ts";
13
13
  import { automaticRedMainQuarantine } from "./red-main-quarantine";
14
14
  import { automaticRedMainRevert, automaticRevertOutcome } from "./red-main-auto-revert";
15
+ import { readFailedTestCases } from "../ci/failed-test-files.ts";
16
+ import { recordRedMainIncidentFailures } from "./red-main-incident.ts";
15
17
 
16
18
  /** Twice a typical main CI run: a run missing or cancelled past this leaves its boundary unverified. */
17
19
  export const RED_MAIN_GRACE_MS = 60 * 60_000;
@@ -31,6 +33,20 @@ function describe(incident: RedMainIncident, observation: BoundaryCiObservation)
31
33
  return `Red main confirmed on lane ${incident.laneKey} (incident ${incident.id}): the re-run did not produce a successful verdict.${jobs}${observation.runUrl ? ` Run: ${observation.runUrl}` : ""}`;
32
34
  }
33
35
 
36
+ /** #3362 §11: the confirmed attempt's failing cases; a rerun that never produced logs falls back to the first failure.
37
+ * Best effort, read once: unreadable logs record nothing, so delivery gates hold nothing and every failure blocks. */
38
+ export async function recordIncidentFailingTests(incident: RedMainIncident, boundary: LandBoundary, attempt: number, api: GitHubApi): Promise<void> {
39
+ let cases;
40
+ try {
41
+ cases = await readFailedTestCases(boundary, incident.ciRunId, attempt, api);
42
+ if (!cases.length && attempt > 1) cases = await readFailedTestCases(boundary, incident.ciRunId, attempt - 1, api);
43
+ } catch (error) {
44
+ console.warn(`[red-main] ${incident.id}: failing cases unreadable; none recorded: ${errMessage(error)}`);
45
+ return;
46
+ }
47
+ await recordRedMainIncidentFailures(incident.id, cases.slice(0, MAX_INCIDENT_FAILING_TESTS).map(({ file, name }) => ({ file, name })));
48
+ }
49
+
34
50
  export function createRedMainControllerDeps(api: GitHubApi = ghApi, now: () => number = Date.now): RedMainControllerDeps {
35
51
  return {
36
52
  now,
@@ -62,10 +78,11 @@ export function createRedMainControllerDeps(api: GitHubApi = ghApi, now: () => n
62
78
  if (!incident) throw new Error(`Effect ${effect.key} needs its incident`);
63
79
  if (effect.kind === "auto-revert") return incident.mainFailurePolicy === "advisory" ? undefined : automaticRedMainRevert(incident, boundary, api);
64
80
  if (effect.kind === "quarantine") return automaticRedMainQuarantine(incident, boundary, effect, api);
81
+ if (effect.kind === "record-failures") return recordIncidentFailingTests(incident, boundary, effect.attempt, api);
65
82
  const task = await getTaskDetailAsync(effect.taskId);
66
83
  if (!task) throw new Error(`Effect ${effect.key}: T${effect.taskId} is missing`);
67
84
  const observation: BoundaryCiObservation = { status: "failure", runId: incident.ciRunId,
68
- runUrl: `https://github.com/${boundary.remote}/actions/runs/${incident.ciRunId}/attempts/${incident.ciAttempt}` };
85
+ runUrl: ciRunUrl(boundary.remote, incident.ciRunId, incident.ciAttempt) };
69
86
  const advisory = incident.mainFailurePolicy === "advisory";
70
87
  const note = describe(incident, observation);
71
88
  if (effect.kind === "reopen-task") {
@@ -1,7 +1,7 @@
1
1
  // #3363 — server seam for the Kernel landing boundary and red-main incident ops
2
2
  // (kernel/landing-incident.ts). Every write goes through the singleton landing module host.
3
3
  import { landing } from "@humwick/kernel/landing";
4
- import type { IncidentEffect, IncidentState, LandBoundary, RedMainIncident } from "@humwick/kernel/landing-incident";
4
+ import type { IncidentEffect, IncidentFailingTest, IncidentState, LandBoundary, RedMainIncident } from "@humwick/kernel/landing-incident";
5
5
  import { activeLandCommandIdForWorkspace } from "../db/land-incident-eligibility.ts";
6
6
  import { startKernelLandingIngress } from "./kernel-landing-ingress.ts";
7
7
 
@@ -26,6 +26,8 @@ export const transitionRedMainIncident = (input: { id: string; from: IncidentSta
26
26
  export const settleRedMainIncidentEffect = (id: string, key: string) =>
27
27
  invoke<RedMainIncident>("settleIncidentEffect", { id, key });
28
28
  export const ensureRedMainIncidentEffects = (id: string) => invoke<RedMainIncident>("ensureIncidentEffects", { id });
29
+ export const recordRedMainIncidentFailures = (id: string, failingTests: IncidentFailingTest[]) =>
30
+ invoke<RedMainIncident>("recordIncidentFailures", { id, failingTests });
29
31
  export const failAutomaticRedMainRevert = (id: string, reason: string) => invoke<RedMainIncident>("failAutomaticRevert", { id, reason });
30
32
  export const queueBoundaryRerun = (id: string, effect: IncidentEffect) => invoke<LandBoundary>("queueBoundaryRerun", { id, effect });
31
33
  export const settleBoundaryEffect = (id: string, key: string) => invoke<LandBoundary>("settleBoundaryEffect", { id, key });
@@ -4,7 +4,7 @@
4
4
  // like any change, and the list's issue gets the audit record. Anything short of that becomes a Task.
5
5
  import { createHash } from "node:crypto";
6
6
  import type { IncidentEffect, LandBoundary, RedMainIncident } from "@humwick/kernel/landing-incident";
7
- import { isRecord, stringValue } from "@humwick/sdk";
7
+ import { ciRunUrl, isRecord, stringValue } from "@humwick/sdk";
8
8
  import { readFailedTestCases } from "../ci/failed-test-files";
9
9
  import { findCommandByCorrelationId } from "../commands-db";
10
10
  import { isTerminalCommandStatus } from "../db/command-terminal-status";
@@ -19,8 +19,7 @@ type Case = { id?: string; file: string; name: string; why?: string };
19
19
 
20
20
  export const automaticQuarantineWorkspaceId = (id: string) => `red-main-q-${createHash("sha256").update(id).digest("hex").slice(0, 24)}`;
21
21
  const prepareKey = (id: string) => `kcmd:red-main:${id}:prepare-quarantine`;
22
- const runUrl = (boundary: LandBoundary, incident: RedMainIncident, attempt?: number) =>
23
- `https://github.com/${boundary.remote}/actions/runs/${incident.ciRunId}${attempt ? `/attempts/${attempt}` : ""}`;
22
+ const runUrl = (boundary: LandBoundary, incident: RedMainIncident, attempt?: number) => ciRunUrl(boundary.remote, incident.ciRunId, attempt);
24
23
 
25
24
  function evidence(incident: RedMainIncident, boundary: LandBoundary, attempt: number): string {
26
25
  const failed = `main ${boundary.landedTipSha.slice(0, 12)} run ${incident.ciRunId} attempt ${attempt} failed`;
@@ -1,3 +1,4 @@
1
+ import { stampSpawnPrincipalAsync, markSpawnRegistrationConfirmedAsync, seedSpawnPromptMirrorAsync } from "../db/lifecycle-tail-async";
1
2
  // Transport convergence (epic #342, slice #345) — the agent-registration service.
2
3
  //
3
4
  // ONE home for "an agent registered" — previously inlined in HTTP `postAgent` and
@@ -11,14 +12,13 @@
11
12
  // the first-registration audit row.
12
13
  import { errMessage, fireAndForget, isReservedAgentId } from "@humwick/sdk";
13
14
  import { normalizeAgentSystemTags } from "../agent-system-tags";
14
- import { ValidationError, agentPrincipalUserId, stampSpawnPrincipal, createActivityEvent, deliverableTaskIdsBySpawnRequestId, getAgent, getTaskDetail, readSpawnRegistrationMeta, seedSpawnPromptMirror, seedSpawnReplyObligation, spawnRegistrationMeta, upsertAgent } from "../db";
15
+ import { ValidationError, agentPrincipalUserId, createActivityEventAsync, deliverableTaskIdsBySpawnRequestId, getAgent, getTaskDetail, readSpawnRegistrationMeta, seedSpawnReplyObligation, spawnRegistrationMeta, upsertAgentAsync } from "../db";
15
16
  import { readSpawnSystemTags } from "../commands-db";
16
17
  import { channelProviderForInput, expectedChannelAgentId } from "../db/channel-identity";
17
18
  import { emitAgentStatus, emitNewMessage } from "../sse";
18
19
  import { noteAgentTimelineEvent } from "../compaction-watch";
19
20
  import { agentProviderTimelineEvent } from "../provider-timeline-event";
20
21
  import { notifyAgentReady, notifyAgentRegistered } from "../agent-lifecycle-events";
21
- import { markSpawnRegistrationConfirmed } from "../commands-db";
22
22
  import { resolveSpawnLineage, resolveTeamLineage } from "../security";
23
23
  import { flushQueuedDirectMessages, markManagedAgentRunning } from "./managed-running";
24
24
  import { acquireTeamOnReady } from "./team";
@@ -56,7 +56,7 @@ function taskIdsForReadyAgent(agent: AgentCard): number[] {
56
56
  return [...ids].sort((a, b) => a - b);
57
57
  }
58
58
 
59
- export function bindSpawnedTaskToReadyAgent(agentId: string, actor = "agent-relay"): void {
59
+ export async function bindSpawnedTaskToReadyAgent(agentId: string, actor = "agent-relay"): Promise<void> {
60
60
  const agent = getAgent(agentId);
61
61
  if (!agent?.ready || isSpawnIntentCanceled(agent.meta?.spawnRequestId)) return;
62
62
  const taskIds = taskIdsForReadyAgent(agent);
@@ -67,9 +67,9 @@ export function bindSpawnedTaskToReadyAgent(agentId: string, actor = "agent-rela
67
67
  if (before.ownerAgentId && before.ownerAgentId !== agent.id && getAgent(before.ownerAgentId)?.status !== "offline") continue;
68
68
  const assigned = before.ownerAgentId === agent.id
69
69
  ? before
70
- : assignTaskEntityAgent(taskId, agent.id, "worker", agent.spawnedBy ?? actor);
70
+ : (await assignTaskEntityAgent(taskId, agent.id, "worker", agent.spawnedBy ?? actor));
71
71
  if (assigned.status === "open" || assigned.status === "claimed" || assigned.status === "orphaned") {
72
- setTaskEntityStatus(taskId, {
72
+ await setTaskEntityStatus(taskId, {
73
73
  status: "in_progress",
74
74
  note: `worker ${agent.id} ready`,
75
75
  actor: agent.spawnedBy ?? actor,
@@ -90,9 +90,9 @@ export function bindSpawnedTaskToReadyAgent(agentId: string, actor = "agent-rela
90
90
  * regardless of which transport carried it — a child readied only over the bus used to die
91
91
  * unstamped and get reaped as `agent.spawn_failed`.
92
92
  */
93
- export function announceSpawnedAgentReady(agentId: string, actor = "agent-relay"): void {
94
- notifyAgentReady(agentId);
95
- bindSpawnedTaskToReadyAgent(agentId, actor);
93
+ export async function announceSpawnedAgentReady(agentId: string, actor = "agent-relay"): Promise<void> {
94
+ await notifyAgentReady(agentId);
95
+ await bindSpawnedTaskToReadyAgent(agentId, actor);
96
96
  }
97
97
 
98
98
  /** The PRIVILEGED principals that bypass the registration gates — an explicit allowlist, so a
@@ -238,7 +238,7 @@ function serverRecordedApprovalMode(agentId: string, ctx: AuthContext): SpawnApp
238
238
  return undefined;
239
239
  }
240
240
 
241
- export function registerAgent(input: RegisterAgentInput, ctx: AuthContext, options: { emitStatus?: boolean } = {}): AgentCard {
241
+ export async function registerAgent(input: RegisterAgentInput, ctx: AuthContext, options: { emitStatus?: boolean } = {}): Promise<AgentCard> {
242
242
  // Reserved built-in identities — the `system` lifecycle sender and the whole `user:` human
243
243
  // namespace (legacy bare `'user'`, `user:default`, every `user:<id>`) — are mechanical sinks,
244
244
  // never registrable agents. THIS is the one external-registration boundary (HTTP `postAgent`
@@ -358,7 +358,7 @@ export function registerAgent(input: RegisterAgentInput, ctx: AuthContext, optio
358
358
  if (Object.keys(spawnMeta).length) registrationInput.meta = { ...registrationInput.meta, ...spawnMeta };
359
359
  const rawSpawnSystemTags = readSpawnSystemTags(registeringSpawnRequestId, registrationInput.id);
360
360
  const spawnSystemTags = rawSpawnSystemTags === undefined ? undefined : normalizeAgentSystemTags(rawSpawnSystemTags);
361
- const agent = upsertAgent(registrationInput, {
361
+ const agent = await upsertAgentAsync(registrationInput, {
362
362
  verifiedSpawnRequestId: ctx.constraints?.spawnRequestIds?.length === 1 ? ctx.constraints.spawnRequestIds[0] : undefined,
363
363
  ...(verifiedKeepJti ? { verifiedKeepJtis: [verifiedKeepJti] } : {}),
364
364
  ...(spawnSystemTags !== undefined ? { systemTags: spawnSystemTags } : {}),
@@ -366,20 +366,20 @@ export function registerAgent(input: RegisterAgentInput, ctx: AuthContext, optio
366
366
  // #3567 — a first registration or a new generation records its principal (a reconnect has
367
367
  // nothing new to stamp): the spawn's principal, else the registering caller's.
368
368
  if (!existing || metaStr(existing.meta, "spawnRequestId") !== registeringSpawnRequestId) {
369
- stampSpawnPrincipal(agent.id, registeringSpawnRequestId, registeringPrincipal(ctx, agent.id));
369
+ await stampSpawnPrincipalAsync(agent.id, registeringSpawnRequestId, registeringPrincipal(ctx, agent.id));
370
370
  }
371
371
  // #3398 — a new instance under this id replaced the provider process: that is a context reset.
372
372
  if (existing?.instanceId && agent.instanceId && agent.instanceId !== existing.instanceId) {
373
- recordContextReset({ agentId: agent.id, resetId: `restart:${agent.instanceId}`, kind: "restart", observedAt: Date.now(), evidence: { previousInstanceId: existing.instanceId } });
373
+ (await recordContextReset({ agentId: agent.id, resetId: `restart:${agent.instanceId}`, kind: "restart", observedAt: Date.now(), evidence: { previousInstanceId: existing.instanceId } }));
374
374
  }
375
375
  // A parked continuation is durable across runner process loss. Registration is the earliest
376
376
  // point a replacement can receive it, so replay here rather than waiting for maintenance.
377
- if (agent.ready && agent.status !== "offline") replayParkedContinuationInjections(agent.id, `registration:${agent.epoch}`);
377
+ if (agent.ready && agent.status !== "offline") (await replayParkedContinuationInjections(agent.id, `registration:${agent.epoch}`));
378
378
 
379
379
  // Managed came-up-running reconcile — no-op for non-managed agents (the guard lives
380
380
  // in markManagedAgentRunning). Clears backoff, flushes the policy queue, transitions
381
381
  // managed state to running.
382
- markManagedAgentRunning(
382
+ (await markManagedAgentRunning(
383
383
  {
384
384
  policyName: metaStr(agent.meta, "policyName"),
385
385
  spawnRequestId: metaStr(agent.meta, "spawnRequestId"),
@@ -387,7 +387,7 @@ export function registerAgent(input: RegisterAgentInput, ctx: AuthContext, optio
387
387
  tmuxSession: metaStr(agent.meta, "tmuxSession"),
388
388
  },
389
389
  ctx,
390
- );
390
+ ));
391
391
 
392
392
  // ONE status broadcast (branch-state-enriched, #236), ONE timeline note. A real
393
393
  // PreCompact/SessionStart hook arrives as a latched meta.timelineEvent — clears any
@@ -407,25 +407,25 @@ export function registerAgent(input: RegisterAgentInput, ctx: AuthContext, optio
407
407
  const generation = metaStr(agent.meta, "spawnRequestId");
408
408
  const newGeneration = generation !== undefined && generation !== metaStr(existing?.meta, "spawnRequestId");
409
409
  if (newGeneration) notifyAgentRegistered(agent);
410
- if (agent.ready && (!existing?.ready || newGeneration)) announceSpawnedAgentReady(agent.id, ctx.actor.id);
410
+ if (agent.ready && (!existing?.ready || newGeneration)) await announceSpawnedAgentReady(agent.id, ctx.actor.id);
411
411
 
412
412
  // #416 — flush queued direct messages when a re-registering agent was previously unavailable
413
413
  // (offline, stale, compacting, blocked) or a new agent becomes ready. No-op for brand-new agents
414
414
  // (no queued messages yet) and when no queued messages exist.
415
- if (agent.ready) acquireTeamOnReady(agent.id); // #3107 — a coordinator takes its project's seat before the flush
416
- if (existing && (existing.status === "offline" || isAgentUnavailable(existing)) && agent.ready) flushQueuedDirectMessages(agent.id);
415
+ if (agent.ready) await acquireTeamOnReady(agent.id); // #3107 — a coordinator takes its project's seat before the flush
416
+ if (existing && (existing.status === "offline" || isAgentUnavailable(existing)) && agent.ready) (await flushQueuedDirectMessages(agent.id));
417
417
 
418
418
  if (!existing) {
419
419
  // #413 — a spawned worker with a report-back contract gets a pending reply obligation to its
420
420
  // spawner so it can't idle with its verdict undelivered (vent #121). First-registration only.
421
421
  const spawnRequestId = metaStr(agent.meta, "spawnRequestId");
422
- if (spawnRequestId) markSpawnRegistrationConfirmed(spawnRequestId);
422
+ if (spawnRequestId) await markSpawnRegistrationConfirmedAsync(spawnRequestId);
423
423
  const provider = metaStr(agent.meta, "provider");
424
- const promptMirror = seedSpawnPromptMirror(agent.id, spawnRequestId);
424
+ const promptMirror = await seedSpawnPromptMirrorAsync(agent.id, spawnRequestId);
425
425
  if (promptMirror?.created || promptMirror?.updated) emitNewMessage(promptMirror.message);
426
426
  seedSpawnReplyObligation(agent.id, agent.spawnedBy, spawnRequestId);
427
- void fireAndForget(`[register] spawn prompt issue activity for ${agent.id}`, () => recordSpawnPromptIssueActivity(agent, spawnRequestId));
428
- createActivityEvent({
427
+ void fireAndForget(`[register] spawn prompt issue activity for ${agent.id}`, async () => (await recordSpawnPromptIssueActivity(agent, spawnRequestId)));
428
+ await createActivityEventAsync({
429
429
  clientId: `server-agent-${agent.id}-registered`,
430
430
  kind: "state",
431
431
  title: "Agent registered",
@@ -54,7 +54,7 @@ export async function restartProjectRole(input: {
54
54
  if (!base) throw new Error(`it extends unknown profile "${role.extends}"`);
55
55
  resolveProjectRoleForProvider(role, input.provider, { providerArgs: input.providerArgs }, {});
56
56
  let profile = projectRoleProfile((await withResolvedProvisioningAsync(base, input.provider))!, role);
57
- if (profile.sources?.project) profile = applyProjectCapabilityGates(profile, input.sourceCwd, undefined, { orchestratorLocal: isOrchestratorLocalToRelay(input.host), pinnedMcpCommit: role.source.sha });
57
+ if (profile.sources?.project) profile = (await applyProjectCapabilityGates(profile, input.sourceCwd, undefined, { orchestratorLocal: isOrchestratorLocalToRelay(input.host), pinnedMcpCommit: role.source.sha }));
58
58
  assertProjectRoleMcpTrusted(role, profile);
59
59
  assertProjectRoleMcpCwd(role, input.runtimeCwd);
60
60
  const defaults = projectRoleSpawnDefaults(builtInProfileSpawnDefaults(base.name), role);
@@ -1,3 +1,5 @@
1
+ import { runnerRuntimeTokenEnvAsync, SUCCESSOR_LAUNCH, type RunnerRuntimeTokenInput } from "../runtime-tokens";
2
+ import { updateManagedAgentStateAsync } from "../db/lifecycle-tail-async";
1
3
  import { createCommandAsync } from "../commands-write";
2
4
  import { restartHarnessSubagents } from "./harness-subagents";
3
5
  import { RELAY_TOKEN_HEADER, isRecord, isSpawnProvider, stringValue } from "@humwick/sdk";
@@ -5,7 +7,7 @@ import { recordedLaunchMode } from "../launch-mode";
5
7
  import type { ProviderEffort } from "@humwick/sdk/provider-catalog";
6
8
  import { listCommands } from "../commands-db";
7
9
  import { isTrustedOrchestratorApiUrl, relayToken } from "../config";
8
- import { getAgentProfile, getManagedAgentState, getSpawnPolicy, updateManagedAgentState } from "../config-store";
10
+ import { getAgentProfile, getManagedAgentState, getSpawnPolicy } from "../config-store";
9
11
  import { getMergeLease, getOrchestrator, listWorkspaces, ownedIsolatedWorkspace, ValidationError, withResolvedProvisioning, withResolvedProvisioningAsync, workflowRunIdOf } from "../db";
10
12
  import { resolveProjectForCanonicalCwd } from "./project";
11
13
  import { isProvenStewardAgent, stewardWorktreeCwdPrefixes } from "../steward-spawn-guard";
@@ -16,7 +18,6 @@ import { resolveWhoamiRole } from "../mcp/identity-projection";
16
18
  import { listManagedOrchestratorsForAgent } from "../orchestrator-lookup";
17
19
  import { applyDefaultSharedMcp } from "../shared-mcp";
18
20
  import { buildSpawnCommand, generateSpawnRequestId, resolveSpawnModelParams, resolveSpawnModelParamsAsync } from "../spawn-command";
19
- import { SUCCESSOR_LAUNCH, runnerRuntimeTokenEnv, runnerRuntimeTokenEnvAsync, type RunnerRuntimeTokenInput } from "../runtime-tokens";
20
21
  import { restartEffortState } from "./self-effort";
21
22
  // #2033 — from isolated-workspace-placement.ts, NOT ./spawn-identity: that module also exports
22
23
  // buildProspectiveSpawnIdentity, which imports mcp/identity.ts → self-resume.ts → restart-spawn.ts,
@@ -65,13 +66,13 @@ function resumeWorkspaceForRestart(agent: AgentCard): { branch: string; mode: "a
65
66
  * self-restart. The token is minted here from the CURRENT profile, never cloned from the old
66
67
  * runtime token, so changed scopes/tool groups take effect on the successor.
67
68
  */
68
- function buildRestartSpawnParamsForAgent(
69
+ async function buildRestartSpawnParamsForAgent(
69
70
  agent: AgentCard,
70
71
  orchestrator: Orchestrator | null,
71
72
  policyName?: string,
72
73
  predecessorSpawnRequestId?: string,
73
74
  opts: RestartOptions = {},
74
- ): Record<string, unknown> | undefined {
75
+ ): Promise<Record<string, unknown> | undefined> {
75
76
  if (!orchestrator) return undefined;
76
77
  refuseSyncProjectRoleRestart(agent);
77
78
  const requestId = generateSpawnRequestId();
@@ -110,14 +111,14 @@ function buildRestartSpawnParamsForAgent(
110
111
  resumeWorktreePath: restartResumeWorkspace?.worktreePath,
111
112
  });
112
113
  const params = {
113
- ...buildManagedSpawnParams(relaunchPolicy(policy.value, relaunch.effort), requestId, { createdBy: requestedBy, authority: SUCCESSOR_LAUNCH, identityAgentId: agent.id }),
114
+ ...(await buildManagedSpawnParams(relaunchPolicy(policy.value, relaunch.effort), requestId, { createdBy: requestedBy, authority: SUCCESSOR_LAUNCH, identityAgentId: agent.id })),
114
115
  ...relaunch.carried,
115
116
  agentId: agent.id,
116
117
  requestedBy,
117
118
  // Override the policy builder's normal mint so stable team/project bindings are also
118
119
  // carried by the fresh token, not merely preserved incidentally on the agent row.
119
- env: runnerRuntimeTokenEnv(managedRestartTokenInput(agent, policy.value, requestId, requestedBy, projectId,
120
- [...stewardExtraCwdPrefixes, ...isolatedExtraCwdPrefixes])),
120
+ env: (await runnerRuntimeTokenEnvAsync(managedRestartTokenInput(agent, policy.value, requestId, requestedBy, projectId,
121
+ [...stewardExtraCwdPrefixes, ...isolatedExtraCwdPrefixes]))),
121
122
  ...managedRestartOptions(opts, restartResumeWorkspace),
122
123
  };
123
124
  return opts.resumeId ? withResumeParams(params, opts.resumeId, agent.id) : params;
@@ -126,7 +127,7 @@ function buildRestartSpawnParamsForAgent(
126
127
  const provider = stringValue(agent.meta?.provider);
127
128
  if (!isSpawnProvider(provider)) return undefined;
128
129
  // #2033 review — fold in #2041: for an ISOLATED agent, `agent.meta.cwd` is caller-writable
129
- // (not an AUTHZ_META_KEY) and this `cwd` feeds `runnerRuntimeTokenEnv({cwd})` below as the
130
+ // (not an AUTHZ_META_KEY) and this `cwd` feeds `runnerRuntimeTokenEnvAsync({cwd})` below as the
130
131
  // successor token's cwdPrefixes[0] — a forged value would mint a token authorizing an arbitrary
131
132
  // path. Prefer the same unforgeable orchestrator-written DB row (`ownedIsolatedWorkspace`) G1
132
133
  // sources the resume worktree from; it's undefined for a non-isolated (shared/coordinator) agent
@@ -167,7 +168,7 @@ function buildRestartSpawnParamsForAgent(
167
168
  };
168
169
  const tokenContext = { orchestratorId: orchestrator.id, projectId, extraCwdPrefixes: stewardExtraCwdPrefixes };
169
170
  return buildRestartSpawnCommand(agent, predecessorSpawnRequestId, agentProfile, projectedInstructions, opts, options, tokenContext,
170
- runnerRuntimeTokenEnv(restartTokenInput(agent, options, tokenContext)));
171
+ (await runnerRuntimeTokenEnvAsync(restartTokenInput(agent, options, tokenContext))));
171
172
  }
172
173
 
173
174
  /** Worker-safe restart command construction used by HTTP/orchestrator/self-restart flows. */
@@ -457,11 +458,11 @@ export async function createSelfRestartCommandAsync(
457
458
  const predecessorSpawnRequestId = stringValue(agent.meta?.spawnRequestId);
458
459
  const restartSpawn = await restartSpawnParamsForAgentAsync(agent, orchestrator, policyName, predecessorSpawnRequestId, { continuation, generation, reason });
459
460
  if (!restartSpawn) throw new ValidationError("self-restart could not build a fresh successor spawn");
460
- return createCommandAsync(selfRestartInput(agent, orchestrator, restartSpawn, generation, continuation, fullContextMessageId, reason, now));
461
+ return (await createCommandAsync(selfRestartInput(agent, orchestrator, restartSpawn, generation, continuation, fullContextMessageId, reason, now)));
461
462
  }
462
463
 
463
464
  /** Settle managed runtime correlation only after the transactional orchestrator swap succeeds. */
464
- export function settleSelfRestartManagedState(command: Command): void {
465
+ export async function settleSelfRestartManagedState(command: Command): Promise<void> {
465
466
  if (command.type !== "agent.restart" || !isRecord(command.params.selfRestart)) return;
466
467
  const policyName = stringValue(command.params.policyName);
467
468
  if (!policyName || command.status !== "succeeded") return;
@@ -472,7 +473,7 @@ export function settleSelfRestartManagedState(command: Command): void {
472
473
  const spawnRequestId = stringValue(restartSpawn?.spawnRequestId) ?? state?.spawnRequestId;
473
474
  const tmuxSession = stringValue(report?.tmuxSession) ?? stringValue(report?.sessionName) ?? state?.tmuxSession;
474
475
  if (!agentId || !spawnRequestId) return;
475
- updateManagedAgentState(policyName, {
476
+ (await updateManagedAgentStateAsync(policyName, {
476
477
  status: "starting",
477
478
  agentId,
478
479
  spawnRequestId,
@@ -480,12 +481,12 @@ export function settleSelfRestartManagedState(command: Command): void {
480
481
  lastSpawnAt: command.updatedAt,
481
482
  lastStopAt: command.updatedAt,
482
483
  restartCount: (state?.restartCount ?? 0) + 1,
483
- });
484
- markManagedAgentRunning({ policyName, spawnRequestId, agentId, tmuxSession }, authContextFromSystem(), { now: () => command.updatedAt });
484
+ }));
485
+ (await markManagedAgentRunning({ policyName, spawnRequestId, agentId, tmuxSession }, authContextFromSystem(), { now: () => command.updatedAt }));
485
486
  }
486
487
 
487
- export function restartSpawnParamsForAgent(...args: Parameters<typeof buildRestartSpawnParamsForAgent>) {
488
- return buildRestartSpawnParamsForAgent(...args);
488
+ export async function restartSpawnParamsForAgent(...args: Parameters<typeof buildRestartSpawnParamsForAgent>) {
489
+ return (await buildRestartSpawnParamsForAgent(...args));
489
490
  }
490
491
  export async function restartSpawnParamsForAgentAsync(...args: Parameters<typeof buildRestartSpawnParamsForAgentAsync>) {
491
492
  return buildRestartSpawnParamsForAgentAsync(...args);
@@ -17,10 +17,10 @@ export interface ReviewPublishDispatch {
17
17
  error?: string;
18
18
  }
19
19
 
20
- export function dispatchReviewPublish(
20
+ export async function dispatchReviewPublish(
21
21
  workspace: WorkspaceRecord | undefined,
22
22
  opts: { requestedBy: string; taskId: number; sha?: string; emit: (command: Command) => void },
23
- ): ReviewPublishDispatch | undefined {
23
+ ): Promise<ReviewPublishDispatch | undefined> {
24
24
  if (!workspace || workspace.mode !== "isolated" || !workspace.worktreePath) return undefined;
25
25
  // #1452 round-6 H2b / round-7 H3 — publishing REQUIRES an immutable delivered COMMIT OID (the host
26
26
  // must pin exactly it, and settlement matches result.sha === requested sha). It must be a concrete
@@ -46,28 +46,11 @@ export function dispatchReviewPublish(
46
46
  // failing ledger insert was swallowed, leaving a POLLABLE publish command with NO cleanup ledger
47
47
  // (a crash/insert-failure orphan). The transaction makes them all-or-nothing: a ledger failure
48
48
  // rolls back the command row too, so a reviewer never sees a command with no durable cleanup path.
49
- let command: Command | undefined;
50
- let buildError: string | undefined;
51
- writeTransaction(() => {
52
- const built = buildWorkspacePublishReviewCommand(workspace, opts.requestedBy, { taskId: opts.taskId, sha, reviewRef });
53
- if (!built.ok) { buildError = built.error; return; } // nothing was persisted (owner/worktree check)
54
- // Round-9: PIN the exact ref (relay-derived, host-asserted-equal before push) so cleanup can
55
- // delete it even if the host's success-result is lost. The row also holds the branch/host/
56
- // requested-sha so cleanup survives a purge/recycle. On settlement the reconciler re-writes the
57
- // host-confirmed ref (identical to this one, since the host refuses to push a divergent ref).
58
- upsertReviewRefCleanup({
59
- id: built.command.id,
60
- ref: reviewRef,
61
- workspaceId: workspace.id,
62
- repoRoot: workspace.repoRoot,
63
- worktreePath: workspace.worktreePath,
64
- branch: workspace.branch,
65
- orchestratorId: workspace.orchestratorId,
66
- requestedSha: sha,
67
- });
68
- command = built.command;
69
- });
70
- if (!command) return { workspaceId: workspace.id, dispatched: false, error: buildError ?? "review publish not dispatched" };
49
+ const built = await buildWorkspacePublishReviewCommand(workspace, opts.requestedBy, { taskId: opts.taskId, sha, reviewRef,
50
+ cleanup: { ref: reviewRef, workspaceId: workspace.id, repoRoot: workspace.repoRoot, worktreePath: workspace.worktreePath,
51
+ branch: workspace.branch, orchestratorId: workspace.orchestratorId, requestedSha: sha } });
52
+ if (!built.ok) return { workspaceId: workspace.id, dispatched: false, error: built.error };
53
+ const command = built.command;
71
54
  opts.emit(command); // durable state (command + ledger) is committed before anyone is notified
72
55
  return { workspaceId: workspace.id, commandId: command.id, dispatched: true };
73
56
  } catch (err) {