@humwick/server 0.130.1 → 0.130.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (811) hide show
  1. package/README.md +5 -0
  2. package/bundled/prompts/manifest.json +1 -0
  3. package/bundled/prompts/task.hydration.md +1 -1
  4. package/bundled/roles/builder.md +1 -1
  5. package/docs/guides/sub-coordinators.md +12 -5
  6. package/docs/guides/tools-administration.md +4 -0
  7. package/docs/guides/tools-coordination.md +2 -0
  8. package/docs/guides/tools-tasks.md +8 -0
  9. package/docs/guides/workflows.md +74 -0
  10. package/docs/openapi.json +486 -4
  11. package/package.json +10 -18
  12. package/public/assets/{MessageBubble-BWpoBjl4.js → MessageBubble-Bq9kr21N.js} +2 -2
  13. package/public/assets/{PlanGraphPanel-C0auck3n.js → PlanGraphPanel-Dqiroy06.js} +2 -2
  14. package/public/assets/{TraceView-DBnOx7AQ.js → TraceView-DYU962-H.js} +2 -2
  15. package/public/assets/{VaultDecisionCard-0kp2oNBC.js → VaultDecisionCard-DhPfzioE.js} +2 -2
  16. package/public/assets/{activity-yLztXEBt.js → activity-DzCcQTee.js} +2 -2
  17. package/public/assets/{agent-lineage-BbJDR1dW.js → agent-lineage-SgDt9i3T.js} +2 -2
  18. package/public/assets/agent-liveness-Bq-s73jW.js +2 -0
  19. package/public/assets/{agent-name-CTZBrSD9.js → agent-name-CcY3Aijy.js} +2 -2
  20. package/public/assets/agent-profiles-cxtRBn6O.js +2 -0
  21. package/public/assets/{agent-project-badge-9TqzUUYE.js → agent-project-badge-DGYbIhaI.js} +2 -2
  22. package/public/assets/{agent-tools-D4n40pn8.js → agent-tools-DHbftV0N.js} +2 -2
  23. package/public/assets/{agent-type-icon-D6FUarOf.js → agent-type-icon-CY113sp-.js} +2 -2
  24. package/public/assets/{agents-BYDslkJc.js → agents-BPzY7IlQ.js} +2 -2
  25. package/public/assets/{analytics-B-XSbEMC.js → analytics-DENFPv_a.js} +2 -2
  26. package/public/assets/{artifact-viewer-DdWIfV6M.js → artifact-viewer-KRvSc7sl.js} +2 -2
  27. package/public/assets/{artifacts-DPN1q4pA.js → artifacts-C9gSmL3s.js} +2 -2
  28. package/public/assets/{artifacts-oBOqks-2.js → artifacts-DT-HkI5O.js} +2 -2
  29. package/public/assets/{automation-4KcRFXEu.js → automation-BsmjQhKD.js} +2 -2
  30. package/public/assets/{backlog-Cw9xPTCF.js → backlog-8NYH_62t.js} +2 -2
  31. package/public/assets/{busy-health-CTu32MZt.js → busy-health-D3hwvYb4.js} +2 -2
  32. package/public/assets/{channels-BiXzg1G9.js → channels-DCJ5WL7O.js} +2 -2
  33. package/public/assets/{chat-Ctk2qwvA.js → chat-DAIl357U.js} +3 -3
  34. package/public/assets/{code-preview-Bm1wWqAp.js → code-preview-CzrZfr9U.js} +2 -2
  35. package/public/assets/{connectors-C36ax4Vw.js → connectors-xTxtlyou.js} +2 -2
  36. package/public/assets/{cosmos-Jj9LK2Wf.js → cosmos-BpebFLK2.js} +2 -2
  37. package/public/assets/{crate-agent-H6S7-B9T.js → crate-agent-BHvI5wXC.js} +2 -2
  38. package/public/assets/{dependency-graph-Cd1E23wa.js → dependency-graph-DGT0o3wJ.js} +2 -2
  39. package/public/assets/{deploys-Bwfq146q.js → deploys-hqWOHSHE.js} +2 -2
  40. package/public/assets/{display-CfO7rTuF.js → display-CDeH4I8T.js} +2 -2
  41. package/public/assets/{files-DhhZI2Ih.js → files-BTeGVmTg.js} +2 -2
  42. package/public/assets/{fleet-B_rFEbnL.js → fleet-DgXtNgCa.js} +2 -2
  43. package/public/assets/{fleet-metrics-BkHP-P3R.js → fleet-metrics-BHEt5yc_.js} +2 -2
  44. package/public/assets/{formatted-body-Cm1RrzmN.js → formatted-body-MLtodyPp.js} +3 -3
  45. package/public/assets/{formatted-body-impl-DQiOuOD1.js → formatted-body-impl-CAe664Z8.js} +2 -2
  46. package/public/assets/{host-providers-dialog-CHqwXTov.js → host-providers-dialog-mapF4Fj9.js} +2 -2
  47. package/public/assets/index-CqqgOI5R.js +15 -0
  48. package/public/assets/index-MYAIwYTX.css +2 -0
  49. package/public/assets/{insights-fH1EL-qZ.js → insights-DNyf7IzF.js} +2 -2
  50. package/public/assets/{integrations-C5Oix6ng.js → integrations-DlYOHq7T.js} +2 -2
  51. package/public/assets/{issue-ref-chip-ODyondIa.js → issue-ref-chip-CeWBNWn7.js} +2 -2
  52. package/public/assets/{log-viewer-Cvfy6PW7.js → log-viewer-Cib8nqdE.js} +2 -2
  53. package/public/assets/{maintenance-D8CDH5wZ.js → maintenance-DSn1cPm7.js} +2 -2
  54. package/public/assets/{managed-agents-egllbpij.js → managed-agents-C3CkM81m.js} +2 -2
  55. package/public/assets/{markdown-preview-CYSFgVgK.js → markdown-preview-W4VQQPAv.js} +3 -3
  56. package/public/assets/{markdown-preview-impl-BteVIjX4.js → markdown-preview-impl-CMsTdhjq.js} +2 -2
  57. package/public/assets/{memory-C8WmXsyr.js → memory-BV17qtO4.js} +2 -2
  58. package/public/assets/{messages-BzQdqlO6.js → messages-Bm_1AqSA.js} +2 -2
  59. package/public/assets/{orchestrators-B1HxzkNw.js → orchestrators-Dg-vfP09.js} +2 -2
  60. package/public/assets/{overview-DCUnI4Z7.js → overview-DcYCrvlr.js} +2 -2
  61. package/public/assets/{pairs-ftCd2XcD.js → pairs-8o9nuG3V.js} +2 -2
  62. package/public/assets/{profile-icon-B2zH8DMH.js → profile-icon-BsRyBMea.js} +2 -2
  63. package/public/assets/project-profile-instructions-DETKFn_E.js +2 -0
  64. package/public/assets/projects-M_m6AHws.js +2 -0
  65. package/public/assets/{prompt-settings-Bftq9czX.js → prompt-settings-C_mNCgeL.js} +2 -2
  66. package/public/assets/provider-display-BEeLXC_D.js +2 -0
  67. package/public/assets/{registry-DWCU5c8q.js → registry-DDHHHE5N.js} +2 -2
  68. package/public/assets/run-card-Dt4I4jaP.js +2 -0
  69. package/public/assets/scroll-text-BKXS1ahr.js +2 -0
  70. package/public/assets/{secrets-C7GIUATz.js → secrets-BkVwxI5O.js} +2 -2
  71. package/public/assets/{service-access-settings-C3aujqTG.js → service-access-settings-Crq-6a-B.js} +2 -2
  72. package/public/assets/{settings-C6sZ9eBa.js → settings-CYcavMFu.js} +2 -2
  73. package/public/assets/shipping-H6gzEeZB.js +2 -0
  74. package/public/assets/{stats-V9Z-GxUd.js → stats-BJVeWkpV.js} +2 -2
  75. package/public/assets/{status-dot-CVv0iGHL.js → status-dot-BcHyw1Vw.js} +2 -2
  76. package/public/assets/store-DKPDIZBe.js +9 -0
  77. package/public/assets/{tasks-CXU75HRF.js → tasks-qJjlQPpx.js} +2 -2
  78. package/public/assets/{teams-BPf976zb.js → teams-Cd5Sk1uX.js} +2 -2
  79. package/public/assets/{terminal-viewer-DE9BOe-8.js → terminal-viewer-CpY5_m7W.js} +3 -3
  80. package/public/assets/{terminal-viewer-impl-D04pjmGh.js → terminal-viewer-impl-DI_2llFR.js} +2 -2
  81. package/public/assets/token-estimate-Co-Jdphh.js +2 -0
  82. package/public/assets/{use-agent-terminal-B1yR456R.js → use-agent-terminal-0yJA_buM.js} +2 -2
  83. package/public/assets/{use-decisions-D-S4tpDf.js → use-decisions-uJXHf34W.js} +2 -2
  84. package/public/assets/use-project-list-CpWl6eHQ.js +2 -0
  85. package/public/assets/{use-selectors-CnrAk2YP.js → use-selectors-BdxBW8mL.js} +2 -2
  86. package/public/assets/{user-avatar-nBFIcR4M.js → user-avatar-3IndfpOc.js} +2 -2
  87. package/public/assets/versioned-prompt-editor-CIVg7XB1.js +8 -0
  88. package/public/assets/{work-queue-TCjJxeT-.js → work-queue-B9rnLwHZ.js} +2 -2
  89. package/public/assets/{workflow-marker-Cf3Hf2fN.js → workflow-marker-X8wxyhzC.js} +2 -2
  90. package/public/assets/{workflows-CXQX20Qj.js → workflows-o5YyMFW7.js} +2 -2
  91. package/public/assets/{workspaces-qSYzKYMA.js → workspaces-CzEGoAng.js} +2 -2
  92. package/public/cosmos.html +4 -4
  93. package/public/index.html +31 -29
  94. package/runner/plugins/claude/.claude-plugin/plugin.json +1 -1
  95. package/runner/plugins/claude/hooks/gate-run-guard.provisioned.mjs +31 -1
  96. package/runner/src/adapters/claude-effort.ts +2 -4
  97. package/runner/src/adapters/claude-headless.ts +1 -1
  98. package/runner/src/adapters/claude-launch-exit.ts +26 -0
  99. package/runner/src/adapters/claude-session-probe.ts +1 -1
  100. package/runner/src/adapters/claude-tmux.ts +38 -10
  101. package/runner/src/adapters/claude.ts +28 -75
  102. package/runner/src/adapters/codex-launch-config.ts +4 -5
  103. package/runner/src/adapters/codex.ts +1 -1
  104. package/runner/src/adapters/opencode-provider.ts +7 -22
  105. package/runner/src/adapters/opencode.ts +4 -4
  106. package/runner/src/adapters/provider-quota-harvest.ts +20 -71
  107. package/runner/src/agent-runner/credentials.ts +42 -12
  108. package/runner/src/agent-runner/inbox.ts +27 -0
  109. package/runner/src/agent-runner/lifecycle-milestones.ts +2 -4
  110. package/runner/src/agent-runner/liveness-exchange.ts +104 -0
  111. package/runner/src/bin/claude.ts +4 -0
  112. package/runner/src/bin/codex.ts +4 -0
  113. package/runner/src/bin/opencode.ts +4 -0
  114. package/runner/src/claude-system-prompt.ts +49 -0
  115. package/runner/src/index.ts +5 -2
  116. package/runner/src/launch-assembly.ts +14 -10
  117. package/runner/src/profile-home.ts +1 -1
  118. package/runner/src/project-instructions.ts +2 -2
  119. package/runner/src/provider-command.ts +18 -0
  120. package/runner/src/provider-setup.ts +35 -0
  121. package/runner/src/providers.ts +2 -1
  122. package/runner/src/runner-core.ts +32 -38
  123. package/runner/src/runner-helpers.ts +0 -8
  124. package/runner/src/session-scratch.ts +6 -2
  125. package/runner/src/spawn-input.ts +2 -1
  126. package/runner/src/test-run-dedup.ts +59 -56
  127. package/runner/test-support/provisioning-context.ts +4 -2
  128. package/runner/test-support/runner-harness.ts +2 -1
  129. package/scripts/cd-config.ts +8 -0
  130. package/scripts/gate-run-lease.ts +10 -7
  131. package/scripts/gate.sh +5 -1
  132. package/scripts/steward-policy-cleanup.ts +2 -2
  133. package/src/agent-authz.ts +2 -2
  134. package/src/agent-drive-arbiter.ts +3 -8
  135. package/src/agent-exit-cleanup-async.ts +2 -2
  136. package/src/agent-exit-cleanup.ts +23 -19
  137. package/src/agent-lifecycle-events.ts +112 -85
  138. package/src/agent-ref.ts +3 -2
  139. package/src/agent-status-events.ts +43 -14
  140. package/src/auth/password.ts +4 -3
  141. package/src/auth/session-refresh.ts +1 -1
  142. package/src/auth/session.test-fixture.ts +2 -2
  143. package/src/auth/session.ts +7 -7
  144. package/src/automations/crud.ts +8 -81
  145. package/src/automations/dispatch.ts +33 -58
  146. package/src/automations/index.ts +1 -1
  147. package/src/automations/persistence.ts +65 -0
  148. package/src/automations/precheck.ts +18 -16
  149. package/src/automations/read-async.ts +11 -0
  150. package/src/automations/reconcile.ts +30 -39
  151. package/src/automations/storage.ts +33 -10
  152. package/src/automations/write-async.ts +33 -0
  153. package/src/branch-land-notice.ts +93 -0
  154. package/src/branch-landed.ts +31 -98
  155. package/src/bus.ts +40 -39
  156. package/src/cd-deploy-notify.ts +32 -4
  157. package/src/cd-host-lag-notify.ts +7 -6
  158. package/src/ci/incidents.ts +2 -2
  159. package/src/ci/monitor.ts +5 -8
  160. package/src/ci/notifications.ts +4 -4
  161. package/src/ci/root-missing.ts +4 -9
  162. package/src/ci/transition-notify.ts +12 -44
  163. package/src/claude-app/oauth-http.ts +3 -3
  164. package/src/cli/cd-pauses.ts +19 -0
  165. package/src/cli/orchestrator.ts +1 -1
  166. package/src/cli/state.ts +2 -19
  167. package/src/cli/task-edit.ts +22 -0
  168. package/src/cli/task.ts +3 -1
  169. package/src/cli/workflow.ts +19 -4
  170. package/src/commands-db.ts +7 -7
  171. package/src/commands-write.ts +8 -0
  172. package/src/compaction-watch.ts +10 -8
  173. package/src/config-store-write.ts +13 -1
  174. package/src/config-store.ts +25 -14
  175. package/src/config.ts +4 -11
  176. package/src/connectors.ts +10 -8
  177. package/src/context-advisory.ts +22 -21
  178. package/src/db/activity-async.ts +6 -1
  179. package/src/db/activity-write-ops.ts +12 -1
  180. package/src/db/activity.ts +1 -14
  181. package/src/db/agent-action-write.ts +36 -0
  182. package/src/db/agent-control-async.ts +9 -0
  183. package/src/db/agent-control-write.ts +49 -0
  184. package/src/db/agent-effort-observe.ts +22 -0
  185. package/src/db/agent-meta.ts +14 -3
  186. package/src/db/agent-search.ts +1 -15
  187. package/src/db/agents-async.ts +59 -9
  188. package/src/db/agents-write-ops.ts +12 -3
  189. package/src/db/agents.ts +95 -65
  190. package/src/db/auth-identities.ts +2 -2
  191. package/src/db/automation-read-ops.ts +11 -0
  192. package/src/db/automation-write-ops.ts +46 -0
  193. package/src/db/blackboard.ts +2 -2
  194. package/src/db/browser-session-write.ts +32 -0
  195. package/src/db/bus-outbox-write-ops.ts +3 -1
  196. package/src/db/checkout-refresh-schema.ts +47 -0
  197. package/src/db/checkout-refresh.ts +5 -5
  198. package/src/db/ci-incidents-async.ts +5 -5
  199. package/src/db/ci-incidents-write-ops.ts +2 -2
  200. package/src/db/command-agent-profile-backfill.ts +39 -0
  201. package/src/db/command-agent-profiles.ts +5 -1
  202. package/src/db/command-retention.ts +126 -0
  203. package/src/db/command-row.ts +10 -2
  204. package/src/db/commands-list-query.ts +2 -0
  205. package/src/db/commands-planner-stats.test-fixture.ts +8 -0
  206. package/src/db/commands-read-ops.ts +16 -0
  207. package/src/db/commands-spawn-read.ts +1 -1
  208. package/src/db/config-store-write-ops.ts +7 -2
  209. package/src/db/connection.ts +1 -182
  210. package/src/db/context-carry-write.ts +74 -0
  211. package/src/db/continuation-archives-async.ts +5 -0
  212. package/src/db/continuation-archives-write-ops.ts +7 -0
  213. package/src/db/continuations.ts +6 -6
  214. package/src/db/db-error-registry.ts +12 -0
  215. package/src/db/db-writer-worker.ts +8 -1
  216. package/src/db/deploy-events-async.ts +1 -0
  217. package/src/db/deploy-events-read-ops.ts +2 -1
  218. package/src/db/deploy-events.ts +35 -4
  219. package/src/db/gateway.ts +26 -133
  220. package/src/db/history-retention-ops.ts +13 -0
  221. package/src/db/hosts-registration.ts +10 -2
  222. package/src/db/hosts.ts +9 -6
  223. package/src/db/inbox-async.ts +2 -2
  224. package/src/db/inbox-read-ops.ts +1 -1
  225. package/src/db/inbox.ts +9 -17
  226. package/src/db/index.ts +2 -0
  227. package/src/db/integrations-async.ts +8 -0
  228. package/src/db/integrations-ops.ts +15 -0
  229. package/src/db/integrations.ts +15 -21
  230. package/src/db/issue-associations.ts +2 -2
  231. package/src/db/issue-lifecycle.ts +3 -4
  232. package/src/db/issue-refs-async.ts +23 -0
  233. package/src/db/issue-refs-read-ops.ts +6 -0
  234. package/src/db/issue-refs-write-ops.ts +29 -0
  235. package/src/db/issue-refs.ts +15 -16
  236. package/src/db/kernel-event-log-schema.ts +2 -0
  237. package/src/db/land-boundaries.ts +51 -5
  238. package/src/db/land-gate-attestations.ts +2 -2
  239. package/src/db/landing-receipts.ts +2 -2
  240. package/src/db/lifecycle-context-write.ts +5 -0
  241. package/src/db/lifecycle-tail-async.ts +76 -0
  242. package/src/db/lifecycle-tail-write-ops.ts +62 -0
  243. package/src/db/lifecycle-write-window.ts +2 -1
  244. package/src/db/lineage-pair-dedupe-sql.ts +3 -3
  245. package/src/db/long-running-work.ts +2 -2
  246. package/src/db/main-connection-mode.ts +11 -0
  247. package/src/db/main-connection-writes.ts +41 -2
  248. package/src/db/maintenance-job-reconcile.ts +61 -0
  249. package/src/db/maintenance-job-runs-async.ts +14 -0
  250. package/src/db/maintenance-job-write-ops.ts +9 -0
  251. package/src/db/maintenance-pauses.ts +2 -2
  252. package/src/db/mappers.ts +2 -14
  253. package/src/db/merge-lease.ts +1 -15
  254. package/src/db/message-send.ts +4 -0
  255. package/src/db/messages.ts +31 -25
  256. package/src/db/migrations.ts +25 -16
  257. package/src/db/notification-write-ops.ts +19 -0
  258. package/src/db/operator-answer-write.ts +19 -0
  259. package/src/db/orchestrators.ts +14 -76
  260. package/src/db/pairs-async.ts +22 -1
  261. package/src/db/pairs-write-ops.ts +8 -3
  262. package/src/db/pairs.ts +42 -61
  263. package/src/db/plan-dispatch-schema.ts +5 -1
  264. package/src/db/plan-ready-notices.ts +43 -0
  265. package/src/db/plan-tools-include-migration.ts +36 -0
  266. package/src/db/plans-write-ops.ts +2 -0
  267. package/src/db/presence-buffer.ts +5 -0
  268. package/src/db/presence-loop.ts +18 -23
  269. package/src/db/presence-write.ts +0 -6
  270. package/src/db/project-entries-async.ts +14 -0
  271. package/src/db/project-entries-read-ops.ts +5 -1
  272. package/src/db/project-entries-write-ops.ts +8 -0
  273. package/src/db/project-entries.ts +15 -12
  274. package/src/db/project-journal.ts +2 -2
  275. package/src/db/project-profile-instructions.ts +50 -0
  276. package/src/db/project-trust-approvals.ts +2 -2
  277. package/src/db/prompt-templates.ts +4 -4
  278. package/src/db/prompt-versions.ts +9 -2
  279. package/src/db/provider-config-history.ts +8 -3
  280. package/src/db/provider-model-seed.ts +34 -0
  281. package/src/db/read-op-marshaling-fixtures.ts +23 -0
  282. package/src/db/read-ops.ts +8 -0
  283. package/src/db/retention.ts +13 -2
  284. package/src/db/review-publish-write.ts +8 -0
  285. package/src/db/routing-policy.ts +2 -3
  286. package/src/db/runtime-admin-async.ts +19 -0
  287. package/src/db/runtime-admin-write-ops.ts +36 -0
  288. package/src/db/runtime-tail-async.ts +288 -0
  289. package/src/db/runtime-tail-write-ops.ts +97 -0
  290. package/src/db/schema.ts +13 -4
  291. package/src/db/spawn-budget.ts +5 -0
  292. package/src/db/spawn-delegation-state.ts +11 -4
  293. package/src/db/spawn-delegation.ts +1 -11
  294. package/src/db/sql-audit-indexes.ts +3 -0
  295. package/src/db/stats-async.ts +9 -6
  296. package/src/db/task-entity.ts +28 -6
  297. package/src/db/task-list.ts +3 -1
  298. package/src/db/tasks.ts +1 -17
  299. package/src/db/team-claim-policy.ts +60 -0
  300. package/src/db/teams-async.ts +4 -0
  301. package/src/db/teams-write-ops.ts +4 -0
  302. package/src/db/terminal-events.ts +15 -0
  303. package/src/db/timer-cutover-bodies.ts +292 -0
  304. package/src/db/timer-cutover-core.ts +37 -278
  305. package/src/db/timer-cutover-state.ts +40 -0
  306. package/src/db/timer-cutover-write-ops.ts +1 -40
  307. package/src/db/timer-ingress.ts +7 -1
  308. package/src/db/token-db-write-ops.ts +19 -0
  309. package/src/db/token-standing-async.ts +12 -0
  310. package/src/db/token-standing.ts +21 -20
  311. package/src/db/token-usage-retention.ts +33 -0
  312. package/src/db/token-usage-write-ops.ts +1 -1
  313. package/src/db/token-usage.ts +4 -1
  314. package/src/db/user-invites-async.ts +13 -0
  315. package/src/db/user-invites.ts +3 -3
  316. package/src/db/users.ts +14 -6
  317. package/src/db/workflow-contact.ts +1 -1
  318. package/src/db/workflow-task-read-ops.ts +30 -0
  319. package/src/db/workspaces.ts +8 -5
  320. package/src/db/write-ops.ts +37 -12
  321. package/src/db/writer-fault-seam.ts +2 -9
  322. package/src/db/writer-fault-test-ops.ts +18 -0
  323. package/src/db/writer-gateway.ts +58 -56
  324. package/src/dev.ts +8 -3
  325. package/src/dispatch-availability.ts +10 -6
  326. package/src/ephemeral/{landing-ingress-proof-worker.ts → landing-ingress-proof.test-fixture.ts} +4 -2
  327. package/src/event-loop-lag.ts +4 -2
  328. package/src/event-loop-yield.ts +2 -2
  329. package/src/events.ts +10 -8
  330. package/src/host/disk-alert.ts +121 -0
  331. package/src/host-provider-store.ts +5 -4
  332. package/src/hub-metrics-report.ts +5 -1
  333. package/src/hub-metrics.ts +38 -18
  334. package/src/injection-sweep-pacing.ts +6 -8
  335. package/src/land-gate-notifications.ts +11 -10
  336. package/src/land-gate-queue-progress.ts +3 -3
  337. package/src/land-settle-dispatch.ts +52 -92
  338. package/src/lifecycle-context-pressure.ts +11 -10
  339. package/src/lifecycle-manager.ts +107 -100
  340. package/src/maintenance/breaker.ts +18 -16
  341. package/src/maintenance/cd-watcher.ts +3 -3
  342. package/src/maintenance/checkout-refresh.ts +18 -1
  343. package/src/maintenance/critical-job-watchdog.ts +19 -20
  344. package/src/maintenance/events.ts +3 -3
  345. package/src/maintenance/history-retention-job.ts +30 -0
  346. package/src/maintenance/index.ts +1 -0
  347. package/src/maintenance/jobs.ts +32 -69
  348. package/src/maintenance/long-running-work.ts +3 -1
  349. package/src/maintenance/offline-agent-prune-job.ts +28 -0
  350. package/src/maintenance/orphaned-sessions.ts +5 -4
  351. package/src/maintenance/pauses.ts +4 -10
  352. package/src/maintenance/plan-ready-notice-job.ts +71 -0
  353. package/src/maintenance/scheduler.ts +98 -137
  354. package/src/maintenance/stalled-delivery-pager.ts +10 -9
  355. package/src/maintenance/teams.ts +19 -30
  356. package/src/maintenance/workspaces.ts +18 -28
  357. package/src/managed-policy-escalation.ts +7 -7
  358. package/src/managed-policy.ts +32 -28
  359. package/src/managed-provider-gate.ts +5 -4
  360. package/src/managed-spawn-reservation.ts +5 -4
  361. package/src/mcp/index.ts +12 -9
  362. package/src/mcp/output-descriptions.ts +8 -8
  363. package/src/mcp/presentation.ts +6 -5
  364. package/src/mcp/project-profile-instructions.ts +32 -0
  365. package/src/mcp/runtime-output.ts +6 -1
  366. package/src/mcp/self-care-visibility.ts +2 -2
  367. package/src/mcp/spawn-targets-matrix.ts +10 -1
  368. package/src/mcp/tool-groups.ts +4 -3
  369. package/src/mcp/tool-roles.ts +81 -0
  370. package/src/mcp/tools-spawn.ts +4 -3
  371. package/src/mcp/tools-workspace.ts +1 -1
  372. package/src/mcp-agent-action.ts +1 -2
  373. package/src/mcp-blackboard-tools.ts +6 -5
  374. package/src/mcp-decision-tools.ts +7 -7
  375. package/src/mcp-egress-tools.ts +10 -9
  376. package/src/mcp-issue-activity-tools.ts +2 -2
  377. package/src/mcp-issue-association-tools.ts +4 -4
  378. package/src/mcp-issue-ref-tools.ts +13 -12
  379. package/src/mcp-maintenance-tools.ts +2 -2
  380. package/src/mcp-merge-tools.ts +5 -5
  381. package/src/mcp-notification-subscription-tools.ts +14 -15
  382. package/src/mcp-output-levels.test-fixture.ts +1 -1
  383. package/src/mcp-profile-trust-tools.ts +5 -5
  384. package/src/mcp-project-journal-tools.ts +4 -12
  385. package/src/mcp-project-tools.ts +17 -18
  386. package/src/mcp-provider-catalog.ts +2 -2
  387. package/src/mcp-routing-policy-tools.ts +3 -2
  388. package/src/mcp-task-tools.ts +11 -5
  389. package/src/mcp-team-template-tools.ts +3 -3
  390. package/src/mcp-team-tools.ts +6 -6
  391. package/src/mcp-workflow-tools.ts +13 -4
  392. package/src/memory-area-injection.ts +13 -12
  393. package/src/memory-boundary-capture.ts +6 -6
  394. package/src/memory-injection.ts +45 -43
  395. package/src/merge-pause-maintenance.ts +5 -4
  396. package/src/notification-router.ts +44 -17
  397. package/src/notification-types.ts +2 -1
  398. package/src/notify.ts +5 -5
  399. package/src/observed-reset-refresh.ts +4 -4
  400. package/src/operator-alarm.ts +23 -11
  401. package/src/project-ingest.ts +6 -6
  402. package/src/project-instructions.ts +12 -1
  403. package/src/project-profile-instruction-text.ts +6 -0
  404. package/src/project-profile-instructions.ts +20 -0
  405. package/src/project-trust.ts +12 -11
  406. package/src/prompt-resolver.ts +3 -3
  407. package/src/provider-catalog-store.ts +3 -49
  408. package/src/provider-config-store.ts +12 -11
  409. package/src/provider-model-seed.ts +1 -18
  410. package/src/provider-quota-async.ts +5 -7
  411. package/src/provider-quota-config-store.ts +5 -4
  412. package/src/provider-secrets.test-fixture.ts +3 -3
  413. package/src/provider-timeline-event.ts +4 -7
  414. package/src/quota-band-delivery.ts +2 -2
  415. package/src/recipe-runner.ts +6 -5
  416. package/src/repo-config-source.ts +10 -4
  417. package/src/retention-config-store.ts +4 -3
  418. package/src/reviewer-pipeline.ts +11 -10
  419. package/src/routes/_route.ts +4 -4
  420. package/src/routes/_shared.ts +13 -12
  421. package/src/routes/agent-effort.ts +5 -5
  422. package/src/routes/agent-heartbeat-quota.ts +23 -0
  423. package/src/routes/agent-keep.ts +1 -1
  424. package/src/routes/agent-profiles.ts +6 -6
  425. package/src/routes/agent-reporting.ts +1 -1
  426. package/src/routes/agent-self-effort.ts +5 -5
  427. package/src/routes/agent-sessions.ts +24 -24
  428. package/src/routes/agents-spawn.ts +2 -2
  429. package/src/routes/agents.ts +19 -121
  430. package/src/routes/auth.ts +14 -15
  431. package/src/routes/authority-audit.ts +2 -2
  432. package/src/routes/automations.ts +6 -5
  433. package/src/routes/channel-binding-delete.ts +1 -1
  434. package/src/routes/channel-output.ts +3 -3
  435. package/src/routes/claude-api-budget.ts +5 -5
  436. package/src/routes/commands-listing.ts +5 -1
  437. package/src/routes/commands.ts +31 -29
  438. package/src/routes/context-resets.ts +2 -2
  439. package/src/routes/continuation-archives.ts +2 -2
  440. package/src/routes/coordinator-teams.ts +1 -1
  441. package/src/routes/decisions.ts +2 -2
  442. package/src/routes/host-secret-files.ts +1 -1
  443. package/src/routes/hosts.ts +11 -11
  444. package/src/routes/inbox.ts +3 -2
  445. package/src/routes/index.ts +12 -2
  446. package/src/routes/integrations.ts +32 -56
  447. package/src/routes/issue-activity.ts +2 -2
  448. package/src/routes/issue-associations.ts +4 -4
  449. package/src/routes/issue-refs.ts +9 -9
  450. package/src/routes/kernel-timers-operator.ts +1 -1
  451. package/src/routes/memory.ts +1 -1
  452. package/src/routes/merges.ts +11 -11
  453. package/src/routes/messages.ts +23 -17
  454. package/src/routes/orchestrator-bootstrap.ts +2 -2
  455. package/src/routes/orchestrator-host-registration.ts +4 -2
  456. package/src/routes/orchestrator-host-utilization.ts +5 -3
  457. package/src/routes/orchestrator-proxy.ts +4 -4
  458. package/src/routes/orchestrator.ts +28 -19
  459. package/src/routes/pairs.ts +8 -8
  460. package/src/routes/project-profile-instructions.ts +27 -0
  461. package/src/routes/project-trust.ts +3 -3
  462. package/src/routes/projects.ts +16 -16
  463. package/src/routes/prompt-templates.ts +12 -12
  464. package/src/routes/provider-config.ts +6 -6
  465. package/src/routes/provider-quota-config.ts +2 -2
  466. package/src/routes/provider-quotas.ts +10 -10
  467. package/src/routes/run-command.ts +1 -1
  468. package/src/routes/secrets-backup.ts +2 -2
  469. package/src/routes/secrets-import.ts +1 -1
  470. package/src/routes/secrets-vault.ts +7 -7
  471. package/src/routes/settings.ts +6 -6
  472. package/src/routes/shipping.ts +9 -1
  473. package/src/routes/spawn-policy.ts +8 -7
  474. package/src/routes/sse.ts +2 -2
  475. package/src/routes/stats.ts +6 -6
  476. package/src/routes/task-http.ts +15 -1
  477. package/src/routes/task-issues.ts +11 -26
  478. package/src/routes/tasks.ts +22 -53
  479. package/src/routes/team-templates.ts +12 -12
  480. package/src/routes/teams-config.ts +2 -2
  481. package/src/routes/teams.ts +10 -10
  482. package/src/routes/tokens.ts +30 -22
  483. package/src/routes/users.ts +24 -24
  484. package/src/routes/viewer-read.ts +3 -3
  485. package/src/routes/web-tool-calls.ts +4 -4
  486. package/src/routes/workflows.ts +22 -7
  487. package/src/routes/workspaces.ts +17 -16
  488. package/src/routing-policy-normalize.ts +1 -2
  489. package/src/routing-policy-push.ts +6 -6
  490. package/src/routing-step-defaults.ts +0 -2
  491. package/src/runner-token-mint-limit.ts +63 -0
  492. package/src/runtime-grant.ts +21 -13
  493. package/src/runtime-tokens.ts +59 -35
  494. package/src/secrets-broker/config.ts +1 -1
  495. package/src/secrets-broker/service.ts +2 -2
  496. package/src/security.ts +16 -21
  497. package/src/self-resume-carry.ts +21 -110
  498. package/src/self-resume-supersede.ts +4 -3
  499. package/src/self-resume.ts +54 -66
  500. package/src/server-background.ts +2 -2
  501. package/src/server.ts +26 -24
  502. package/src/services/agent-action.ts +12 -31
  503. package/src/services/agent-effort.ts +7 -32
  504. package/src/services/agent-hang-watchdog-job.ts +2 -2
  505. package/src/services/agent-heartbeat.ts +166 -0
  506. package/src/services/agent-reporting.ts +1 -1
  507. package/src/services/browser-inventory.ts +3 -3
  508. package/src/services/browser-session-state.ts +3 -2
  509. package/src/services/browser-session.ts +21 -27
  510. package/src/services/bus-command-update.ts +9 -9
  511. package/src/services/checkout-refresh-state.ts +1 -0
  512. package/src/services/checkout-refresh.test-fixture.ts +3 -2
  513. package/src/services/command-host.ts +7 -2
  514. package/src/services/coordinator-digest.ts +3 -2
  515. package/src/services/dispatch-command.ts +12 -13
  516. package/src/services/effective-launch-driver.ts +14 -9
  517. package/src/services/host-changed-paths.test-fixture.ts +5 -6
  518. package/src/services/host-project-readiness.ts +2 -2
  519. package/src/services/host-providers.ts +1 -1
  520. package/src/services/host-utilization.ts +27 -4
  521. package/src/services/idle-agent-digest.ts +17 -12
  522. package/src/services/idle-epics.ts +9 -10
  523. package/src/services/interrupt-agent.ts +12 -9
  524. package/src/services/issue-activity.ts +3 -3
  525. package/src/services/issue-associations.ts +15 -18
  526. package/src/services/issue-lifecycle-comments.ts +3 -2
  527. package/src/services/issue-lifecycle.ts +69 -72
  528. package/src/services/issue-refs.ts +10 -15
  529. package/src/services/kernel-timers-cutover-chaos-worker.ts +11 -8
  530. package/src/services/kernel-timers-ingress-chaos-worker.ts +6 -1
  531. package/src/services/kernel-timers-ingress.ts +4 -4
  532. package/src/services/kernel-timers-message-authority-chaos-worker.ts +3 -10
  533. package/src/services/kernel-timers-operator-chaos-worker.ts +3 -2
  534. package/src/services/kernel-timers-outbox.ts +1 -1
  535. package/src/services/kernel-timers-stage10-operator.ts +1 -1
  536. package/src/services/kernel-timers.ts +4 -3
  537. package/src/services/land-gate-placement.ts +11 -2
  538. package/src/services/land-issue-relations.ts +5 -4
  539. package/src/services/land-restart-retry.ts +7 -6
  540. package/src/services/landed-ancestry.ts +25 -8
  541. package/src/services/legacy-landing-host.ts +4 -1
  542. package/src/services/legacy-landing-recovery.ts +8 -6
  543. package/src/services/managed-running.ts +17 -17
  544. package/src/services/memory-areas.ts +17 -53
  545. package/src/services/merge-pause.ts +9 -15
  546. package/src/services/operator-decisions.ts +37 -41
  547. package/src/services/orchestrator-registration-recovery.ts +6 -2
  548. package/src/services/orchestrator-upgrade.ts +14 -12
  549. package/src/services/permission-decision.ts +4 -3
  550. package/src/services/plan-ci-notice.ts +57 -0
  551. package/src/services/plan-ci-recovery.ts +2 -55
  552. package/src/services/plan-conformance.ts +4 -4
  553. package/src/services/plan-dispatch-policy.ts +10 -3
  554. package/src/services/plan-dispatch.ts +35 -14
  555. package/src/services/plan-graph.ts +39 -261
  556. package/src/services/plan-import.ts +1 -1
  557. package/src/services/plan-live-bindings.ts +8 -37
  558. package/src/services/plan-task-create.ts +1 -1
  559. package/src/services/plan-terminal-refs.ts +2 -12
  560. package/src/services/plan-wake-digest.ts +9 -3
  561. package/src/services/profile-trust.ts +6 -5
  562. package/src/services/project-config-read.ts +70 -0
  563. package/src/services/project-profile-instructions.ts +54 -0
  564. package/src/services/project.ts +11 -10
  565. package/src/services/prompt-templates.ts +6 -5
  566. package/src/services/provider-hold-nudge.ts +9 -9
  567. package/src/services/provider-hold-record.ts +13 -12
  568. package/src/services/provider-state-audit.ts +19 -18
  569. package/src/services/provisioning-harness/budget-baseline.json +4 -4
  570. package/src/services/provisioning-harness/driver.ts +1 -1
  571. package/src/services/provisioning-harness/fixture-matrix.ts +3 -3
  572. package/src/services/provisioning-harness/lifecycle.ts +24 -22
  573. package/src/services/provisioning-harness/prepare.ts +16 -17
  574. package/src/services/rate-limit-resume.ts +10 -9
  575. package/src/services/red-main-auto-revert.ts +7 -5
  576. package/src/services/red-main-controller-deps.ts +20 -3
  577. package/src/services/red-main-incident.ts +3 -1
  578. package/src/services/red-main-quarantine.ts +2 -3
  579. package/src/services/register-agent.ts +22 -22
  580. package/src/services/restart-project-role.ts +1 -1
  581. package/src/services/restart-spawn.ts +74 -61
  582. package/src/services/review-publish.ts +7 -24
  583. package/src/services/review-ref-reconcile.ts +29 -38
  584. package/src/services/runtime-dependency-alert.ts +27 -0
  585. package/src/services/scheduler-command.ts +11 -9
  586. package/src/services/scheduler.ts +5 -5
  587. package/src/services/self-care-state.ts +2 -1
  588. package/src/services/self-effort-grant.ts +5 -25
  589. package/src/services/self-effort.ts +5 -5
  590. package/src/services/send-message.ts +21 -34
  591. package/src/services/shutdown-agent.ts +17 -14
  592. package/src/services/spawn-agent.ts +25 -43
  593. package/src/services/spawn-chain-inspector.ts +7 -14
  594. package/src/services/spawn-cwd-placement.ts +21 -5
  595. package/src/services/spawn-issue-activity.ts +8 -6
  596. package/src/services/spawn-launch.ts +17 -1
  597. package/src/services/spawn-loss-escalation.ts +1 -1
  598. package/src/services/spawn-policy.ts +68 -0
  599. package/src/services/spawn-registration-watchdog.ts +2 -2
  600. package/src/services/spawn-repo-probe.ts +7 -5
  601. package/src/services/spawn-tree-cleanup.ts +8 -9
  602. package/src/services/steward-reaper.ts +4 -4
  603. package/src/services/task-context-hydration.ts +25 -1
  604. package/src/services/task-delivery.ts +20 -34
  605. package/src/services/task-dispatch.ts +3 -0
  606. package/src/services/task-entity.ts +40 -203
  607. package/src/services/task-issue-link.ts +13 -20
  608. package/src/services/task-issue-weave.ts +12 -11
  609. package/src/services/task-lifecycle.ts +27 -31
  610. package/src/services/task-repo-cwd.ts +37 -0
  611. package/src/services/task-review-hold.ts +4 -17
  612. package/src/services/task-semantic-events.ts +13 -11
  613. package/src/services/task-state-reconcile.ts +8 -17
  614. package/src/services/task-validation.ts +2 -2
  615. package/src/services/team-templates.ts +12 -11
  616. package/src/services/team.ts +31 -98
  617. package/src/services/terminal-provider-exit.ts +6 -5
  618. package/src/services/timer-message-fire-chaos-worker.ts +7 -3
  619. package/src/services/timer-message-fire-outbox.ts +1 -1
  620. package/src/services/transient-agent-reaper.ts +25 -20
  621. package/src/services/turn-reconcile-audit.ts +9 -9
  622. package/src/services/user-onboarding.ts +8 -6
  623. package/src/services/user-profile.ts +6 -9
  624. package/src/services/work-finality.ts +16 -4
  625. package/src/services/workflow-auto-start.ts +26 -13
  626. package/src/services/workflow-caller.ts +61 -4
  627. package/src/services/workflow-child-proof-worker.ts +1 -1
  628. package/src/services/workflow-ci-main.ts +1 -1
  629. package/src/services/workflow-control-proof-worker.ts +1 -1
  630. package/src/services/workflow-coordinator.ts +8 -2
  631. package/src/services/workflow-decisions.ts +5 -5
  632. package/src/services/workflow-deferred-cleanup.ts +5 -3
  633. package/src/services/workflow-effect-driver.ts +42 -17
  634. package/src/services/workflow-effects.ts +58 -37
  635. package/src/services/workflow-land-notice.ts +10 -0
  636. package/src/services/workflow-pause-text.ts +43 -0
  637. package/src/services/workflow-pins.ts +7 -4
  638. package/src/services/workflow-reconcile.ts +14 -11
  639. package/src/services/workflow-resume-pins.ts +3 -3
  640. package/src/services/workflow-routing-defaults.ts +18 -0
  641. package/src/services/workflow-run-view.ts +6 -3
  642. package/src/services/workflow-run.test-fixture.ts +1 -1
  643. package/src/services/workflow-runs.ts +61 -33
  644. package/src/services/workflow-supervisor-state.ts +26 -1
  645. package/src/services/workflow-supervisor.ts +11 -6
  646. package/src/services/workspace-recovery.ts +4 -3
  647. package/src/settings/registry.ts +1 -2
  648. package/src/spawn-admission.ts +10 -2
  649. package/src/spawn-command.ts +4 -4
  650. package/src/spawn-models.ts +10 -12
  651. package/src/spawn-placement.ts +28 -10
  652. package/src/spawn-targets.ts +9 -9
  653. package/src/sse-agent-status.ts +15 -6
  654. package/src/sse.ts +49 -24
  655. package/src/startup-context-injection.ts +62 -57
  656. package/src/state-adoption/cd-cutover.ts +53 -7
  657. package/src/state-adoption/fleet-cutover.ts +35 -0
  658. package/src/state-adoption/fleet-plan.ts +36 -0
  659. package/src/state-adoption/index.ts +2 -2
  660. package/src/state-adoption/linux-plan.ts +2 -2
  661. package/src/state-adoption/linux.ts +2 -2
  662. package/src/state-adoption/macos-plan.ts +2 -2
  663. package/src/state-adoption/macos.ts +1 -1
  664. package/src/steward-handoff.ts +4 -3
  665. package/src/steward-policy-cleanup.ts +9 -8
  666. package/src/steward.ts +9 -8
  667. package/src/task-dispatch-live.ts +6 -3
  668. package/src/task-dispatcher.ts +3 -3
  669. package/src/teams-config-store.ts +4 -3
  670. package/src/token-db-write.ts +10 -0
  671. package/src/token-db.ts +2 -2
  672. package/src/token-usage-async.ts +2 -4
  673. package/src/user-awaiting-reply.ts +5 -5
  674. package/src/workspace-actions.ts +24 -29
  675. package/src/workspace-auto-merge.ts +14 -12
  676. package/src/workspace-changed-paths-client.ts +16 -5
  677. package/src/workspace-cleanup-stale.ts +30 -7
  678. package/src/workspace-command-settle.ts +26 -17
  679. package/src/workspace-config.ts +1 -1
  680. package/src/workspace-conflict-resolver.ts +9 -7
  681. package/src/workspace-dead-owner-recovery.ts +5 -4
  682. package/src/workspace-escalation.ts +12 -11
  683. package/src/workspace-human-escalation.ts +3 -3
  684. package/src/workspace-land-gate-watchdog.ts +3 -3
  685. package/src/workspace-land-refusal.ts +20 -0
  686. package/src/workspace-land-stopped.ts +1 -0
  687. package/src/workspace-merge.ts +10 -26
  688. package/src/workspace-nothing-to-land-notice.ts +2 -2
  689. package/src/workspace-orphans.ts +18 -37
  690. package/src/workspace-pr-completion.ts +10 -8
  691. package/src/workspace-rekey.ts +3 -3
  692. package/src/workspace-steward-failure.ts +2 -2
  693. package/src/workspace-steward-wake.ts +4 -4
  694. package/node_modules/@humwick/kernel/LICENSE +0 -167
  695. package/node_modules/@humwick/kernel/async-entity-persistence.ts +0 -344
  696. package/node_modules/@humwick/kernel/async-event-log.ts +0 -107
  697. package/node_modules/@humwick/kernel/automations.pilot.ts +0 -147
  698. package/node_modules/@humwick/kernel/config.ts +0 -111
  699. package/node_modules/@humwick/kernel/contract.ts +0 -572
  700. package/node_modules/@humwick/kernel/control-authz.ts +0 -281
  701. package/node_modules/@humwick/kernel/control.ts +0 -645
  702. package/node_modules/@humwick/kernel/effects.ts +0 -493
  703. package/node_modules/@humwick/kernel/event-log.ts +0 -319
  704. package/node_modules/@humwick/kernel/http-transport.ts +0 -384
  705. package/node_modules/@humwick/kernel/identity-grammar.ts +0 -20
  706. package/node_modules/@humwick/kernel/identity.ts +0 -248
  707. package/node_modules/@humwick/kernel/index.ts +0 -28
  708. package/node_modules/@humwick/kernel/kernel-persistence.ts +0 -181
  709. package/node_modules/@humwick/kernel/landing-incident.ts +0 -306
  710. package/node_modules/@humwick/kernel/landing.ts +0 -953
  711. package/node_modules/@humwick/kernel/manifest-validation.ts +0 -460
  712. package/node_modules/@humwick/kernel/mcp-transport.ts +0 -109
  713. package/node_modules/@humwick/kernel/message-authority-chaos-worker.ts +0 -200
  714. package/node_modules/@humwick/kernel/message-authority.ts +0 -281
  715. package/node_modules/@humwick/kernel/module-host.ts +0 -722
  716. package/node_modules/@humwick/kernel/openapi-init.ts +0 -14
  717. package/node_modules/@humwick/kernel/package.json +0 -39
  718. package/node_modules/@humwick/kernel/persistence-schema.ts +0 -248
  719. package/node_modules/@humwick/kernel/persistence.ts +0 -510
  720. package/node_modules/@humwick/kernel/registry.ts +0 -60
  721. package/node_modules/@humwick/kernel/sqlite-kernel-persistence.ts +0 -499
  722. package/node_modules/@humwick/kernel/sqlite-module-host.ts +0 -87
  723. package/node_modules/@humwick/kernel/timers-chaos-worker.ts +0 -186
  724. package/node_modules/@humwick/kernel/timers.pilot.ts +0 -1411
  725. package/node_modules/@humwick/kernel/workflow-activation.ts +0 -25
  726. package/node_modules/@humwick/kernel/workflow-backstop.ts +0 -40
  727. package/node_modules/@humwick/kernel/workflow-cancel-tree.ts +0 -20
  728. package/node_modules/@humwick/kernel/workflow-chaos-worker.ts +0 -213
  729. package/node_modules/@humwick/kernel/workflow-composition.ts +0 -231
  730. package/node_modules/@humwick/kernel/workflow-container.ts +0 -72
  731. package/node_modules/@humwick/kernel/workflow-control.test-fixture.ts +0 -42
  732. package/node_modules/@humwick/kernel/workflow-control.ts +0 -178
  733. package/node_modules/@humwick/kernel/workflow-definition.ts +0 -507
  734. package/node_modules/@humwick/kernel/workflow-dispatch.ts +0 -60
  735. package/node_modules/@humwick/kernel/workflow-foreach.ts +0 -167
  736. package/node_modules/@humwick/kernel/workflow-journal-codec.ts +0 -339
  737. package/node_modules/@humwick/kernel/workflow-journal.ts +0 -922
  738. package/node_modules/@humwick/kernel/workflow-lane.ts +0 -48
  739. package/node_modules/@humwick/kernel/workflow-lease-owner.ts +0 -60
  740. package/node_modules/@humwick/kernel/workflow-recovery.test-fixture.ts +0 -19
  741. package/node_modules/@humwick/kernel/workflow-runtime.ts +0 -938
  742. package/node_modules/@humwick/kernel/workflow-script.ts +0 -11
  743. package/node_modules/@humwick/kernel/workflow-state.ts +0 -299
  744. package/node_modules/@humwick/kernel/workflow-step-commit.ts +0 -195
  745. package/node_modules/@humwick/kernel/workflow-transitions.ts +0 -317
  746. package/node_modules/@humwick/kernel/workflow-values.ts +0 -153
  747. package/node_modules/@humwick/kernel/workflow.pilot.ts +0 -376
  748. package/node_modules/@humwick/offload/LICENSE +0 -167
  749. package/node_modules/@humwick/offload/README.md +0 -57
  750. package/node_modules/@humwick/offload/dist/async-runner.d.ts +0 -18
  751. package/node_modules/@humwick/offload/dist/async-runner.d.ts.map +0 -1
  752. package/node_modules/@humwick/offload/dist/async-runner.js +0 -158
  753. package/node_modules/@humwick/offload/dist/async-runner.js.map +0 -1
  754. package/node_modules/@humwick/offload/dist/envelope.d.ts +0 -25
  755. package/node_modules/@humwick/offload/dist/envelope.d.ts.map +0 -1
  756. package/node_modules/@humwick/offload/dist/envelope.js +0 -80
  757. package/node_modules/@humwick/offload/dist/envelope.js.map +0 -1
  758. package/node_modules/@humwick/offload/dist/fixtures/worker-task.d.ts +0 -10
  759. package/node_modules/@humwick/offload/dist/fixtures/worker-task.d.ts.map +0 -1
  760. package/node_modules/@humwick/offload/dist/fixtures/worker-task.js +0 -59
  761. package/node_modules/@humwick/offload/dist/fixtures/worker-task.js.map +0 -1
  762. package/node_modules/@humwick/offload/dist/index.d.ts +0 -5
  763. package/node_modules/@humwick/offload/dist/index.d.ts.map +0 -1
  764. package/node_modules/@humwick/offload/dist/index.js +0 -5
  765. package/node_modules/@humwick/offload/dist/index.js.map +0 -1
  766. package/node_modules/@humwick/offload/dist/subprocess-runner.d.ts +0 -62
  767. package/node_modules/@humwick/offload/dist/subprocess-runner.d.ts.map +0 -1
  768. package/node_modules/@humwick/offload/dist/subprocess-runner.js +0 -295
  769. package/node_modules/@humwick/offload/dist/subprocess-runner.js.map +0 -1
  770. package/node_modules/@humwick/offload/dist/types.d.ts +0 -111
  771. package/node_modules/@humwick/offload/dist/types.d.ts.map +0 -1
  772. package/node_modules/@humwick/offload/dist/types.js +0 -176
  773. package/node_modules/@humwick/offload/dist/types.js.map +0 -1
  774. package/node_modules/@humwick/offload/dist/worker-pool.d.ts +0 -23
  775. package/node_modules/@humwick/offload/dist/worker-pool.d.ts.map +0 -1
  776. package/node_modules/@humwick/offload/dist/worker-pool.js +0 -435
  777. package/node_modules/@humwick/offload/dist/worker-pool.js.map +0 -1
  778. package/node_modules/@humwick/offload/dist/worker-runtime.d.ts +0 -2
  779. package/node_modules/@humwick/offload/dist/worker-runtime.d.ts.map +0 -1
  780. package/node_modules/@humwick/offload/dist/worker-runtime.js +0 -27
  781. package/node_modules/@humwick/offload/dist/worker-runtime.js.map +0 -1
  782. package/node_modules/@humwick/offload/dist/worker.d.ts +0 -5
  783. package/node_modules/@humwick/offload/dist/worker.d.ts.map +0 -1
  784. package/node_modules/@humwick/offload/dist/worker.js +0 -1
  785. package/node_modules/@humwick/offload/dist/worker.js.map +0 -1
  786. package/node_modules/@humwick/offload/package.json +0 -42
  787. package/node_modules/@humwick/offload/src/async-runner.ts +0 -170
  788. package/node_modules/@humwick/offload/src/envelope.ts +0 -92
  789. package/node_modules/@humwick/offload/src/fixtures/worker-task.ts +0 -49
  790. package/node_modules/@humwick/offload/src/index.ts +0 -4
  791. package/node_modules/@humwick/offload/src/subprocess-runner.ts +0 -334
  792. package/node_modules/@humwick/offload/src/types.ts +0 -235
  793. package/node_modules/@humwick/offload/src/worker-pool.ts +0 -463
  794. package/node_modules/@humwick/offload/src/worker-runtime.ts +0 -32
  795. package/node_modules/@humwick/offload/src/worker.ts +0 -5
  796. package/public/assets/agent-liveness-DyqxfB-t.js +0 -2
  797. package/public/assets/agent-profiles-BpI_jTxq.js +0 -2
  798. package/public/assets/index-B7ZerHLY.css +0 -2
  799. package/public/assets/index-BU3uWo2t.js +0 -15
  800. package/public/assets/projects-B_lmcqfO.js +0 -2
  801. package/public/assets/provider-display-DbLWpP3j.js +0 -2
  802. package/public/assets/run-card-CO_bguQf.js +0 -2
  803. package/public/assets/shipping-Bu8p1gEw.js +0 -2
  804. package/public/assets/store-BvtFdlGX.js +0 -9
  805. package/public/assets/use-project-list-B-T2Bnnn.js +0 -2
  806. package/public/assets/versioned-prompt-editor-Diu8BIaM.js +0 -8
  807. package/runner/src/agent-runner/http-liveness.ts +0 -85
  808. package/runner/src/gate-run-lease-probe.ts +0 -38
  809. package/src/db/claude-catalog-reconcile.ts +0 -27
  810. package/src/db/on-loop-write-transaction.ts +0 -34
  811. package/src/routing-model-aliases.ts +0 -21
@@ -1,3 +1,5 @@
1
+ import { pauseMaintenanceJobAsync } from "../db/runtime-tail-async";
2
+ import { createActivityEventAsync } from "../db/activity-async";
1
3
  // #1724 stage 1 — the maintenance circuit breaker's bookkeeping and trip actions.
2
4
  //
3
5
  // The design (§5.4, §8.5) asks for a breaker that, when a job repeatedly starves the event loop (or
@@ -15,7 +17,7 @@
15
17
 
16
18
  import { errMessage } from "@humwick/sdk";
17
19
  import { MAINTENANCE_BREAKER_MAX_STRIKES } from "../config";
18
- import { AUTO_BREAKER_PAUSE_HOLDER, createActivityEvent, pauseMaintenanceJob } from "../db";
20
+ import { AUTO_BREAKER_PAUSE_HOLDER } from "../db";
19
21
 
20
22
  // Two strike counters per job, because the two failure signals want different reset semantics — and
21
23
  // getting this wrong silently defeats the breaker:
@@ -81,7 +83,7 @@ export interface BreakerStrikeResult {
81
83
  * and, on reaching MAINTENANCE_BREAKER_MAX_STRIKES, trips: a non-critical job is durably auto-paused;
82
84
  * a critical one is escalated LOUDLY but never paused. Idempotent per runId.
83
85
  */
84
- export function recordBreakerStrike(input: BreakerStrikeInput): BreakerStrikeResult {
86
+ export async function recordBreakerStrike(input: BreakerStrikeInput): Promise<BreakerStrikeResult> {
85
87
  if (!markStruck(input.runId)) {
86
88
  return { struck: false, strikes: breakerStrikeCount(input.jobId), tripped: false };
87
89
  }
@@ -92,7 +94,7 @@ export function recordBreakerStrike(input: BreakerStrikeInput): BreakerStrikeRes
92
94
  if (count < MAINTENANCE_BREAKER_MAX_STRIKES) {
93
95
  return { struck: true, strikes: breakerStrikeCount(input.jobId), tripped: false };
94
96
  }
95
- const action = trip(input.jobId, input.critical, input.reason);
97
+ const action = (await trip(input.jobId, input.critical, input.reason));
96
98
  return { struck: true, strikes: 0, tripped: true, action };
97
99
  }
98
100
 
@@ -119,34 +121,34 @@ export function isRunStruck(runId: string): boolean {
119
121
  return struckRunIds.has(runId);
120
122
  }
121
123
 
122
- function trip(jobId: string, critical: boolean, reason: string): "paused" | "escalated" | "pause-conflict" {
124
+ async function trip(jobId: string, critical: boolean, reason: string): Promise<"paused" | "escalated" | "pause-conflict"> {
123
125
  // Reset BOTH counters first: after a trip the job is either paused (won't run) or escalated; either
124
126
  // way the next strike should start a fresh count rather than instantly re-trip on every later run.
125
127
  timeoutStrikes.delete(jobId);
126
128
  lagStrikes.delete(jobId);
127
129
  if (critical) {
128
- escalateCritical(jobId, reason);
130
+ (await escalateCritical(jobId, reason));
129
131
  return "escalated";
130
132
  }
131
- return autoPause(jobId, reason);
133
+ return (await autoPause(jobId, reason));
132
134
  }
133
135
 
134
- function autoPause(jobId: string, reason: string): "paused" | "pause-conflict" {
136
+ async function autoPause(jobId: string, reason: string): Promise<"paused" | "pause-conflict"> {
135
137
  const pauseReason = `auto-paused by circuit breaker: ${reason}`;
136
138
  console.warn(`[relay] maintenance circuit breaker TRIPPED — durably auto-pausing ${jobId}: ${reason}`);
137
139
  try {
138
140
  // Indefinite on purpose: a job that was starving the loop must NOT quietly resume itself on a
139
141
  // timer. A human resumes it once it is fixed — and the `maintenance-auto-paused` health arm is
140
142
  // what makes sure a human sees it (this pause is otherwise invisible to the critical-only arm).
141
- const result = pauseMaintenanceJob({ jobId, holder: AUTO_BREAKER_PAUSE_HOLDER, reason: pauseReason, indefinite: true });
142
- auditBreakerEvent({
143
+ const result = (await pauseMaintenanceJobAsync({ jobId, holder: AUTO_BREAKER_PAUSE_HOLDER, reason: pauseReason, indefinite: true }));
144
+ (await auditBreakerEvent({
143
145
  jobId,
144
146
  clientId: `server-maintenance-breaker-pause-${jobId}-${result.pause.createdAt}`,
145
147
  title: `Maintenance circuit breaker auto-paused ${jobId}`,
146
148
  body: `${jobId} was auto-paused by the event-loop-lag circuit breaker after ${MAINTENANCE_BREAKER_MAX_STRIKES} strikes — ${reason}. It will stay paused until a human resumes it.`,
147
149
  icon: "ti-alert-octagon",
148
150
  metadata: { breaker: true, pauseId: result.pause.id, alreadyHeld: !result.ok },
149
- });
151
+ }));
150
152
  return result.ok ? "paused" : "pause-conflict";
151
153
  } catch (error) {
152
154
  console.warn(`[relay] maintenance circuit breaker could not pause ${jobId}: ${errMessage(error)}`);
@@ -154,27 +156,27 @@ function autoPause(jobId: string, reason: string): "paused" | "pause-conflict" {
154
156
  }
155
157
  }
156
158
 
157
- function escalateCritical(jobId: string, reason: string): void {
159
+ async function escalateCritical(jobId: string, reason: string): Promise<void> {
158
160
  // §8.5 — the one thing the breaker must never do is silence a critical job the way a bare
159
161
  // `enabled=0` silenced cd-watcher for nine hours. So a critical job is escalated, never paused: it
160
162
  // KEEPS running (and keeps being reported by criticalMaintenanceJobsCheck if it is genuinely
161
163
  // failing), and a loud, attributed event tells a human to intervene deliberately.
162
164
  console.warn(`[relay] maintenance circuit breaker: CRITICAL job ${jobId} repeatedly misbehaving (${reason}) — NOT auto-paused (see #1645/§8.5), escalating for a human`);
163
- auditBreakerEvent({
165
+ (await auditBreakerEvent({
164
166
  jobId,
165
167
  clientId: `server-maintenance-breaker-escalate-${jobId}-${Date.now()}`,
166
168
  title: `Maintenance circuit breaker: critical job ${jobId} needs a human`,
167
169
  body: `${jobId} repeatedly starved the event loop or overran its deadline (${reason}). Because it is CRITICAL, the breaker did NOT auto-pause it — a machine silencing a critical job is the #1645 blackout. A human must decide what to do.`,
168
170
  icon: "ti-alert-triangle",
169
171
  metadata: { breaker: true, critical: true, escalated: true },
170
- });
172
+ }));
171
173
  }
172
174
 
173
- function auditBreakerEvent(input: { jobId: string; clientId: string; title: string; body: string; icon: string; metadata: Record<string, unknown> }): void {
175
+ async function auditBreakerEvent(input: { jobId: string; clientId: string; title: string; body: string; icon: string; metadata: Record<string, unknown> }): Promise<void> {
174
176
  try {
175
177
  // #1912 S3.2: sync-retained — the lag sampler invokes recordBreakerStrike synchronously and
176
178
  // cannot await without redesigning the event-loop attribution callback contract.
177
- createActivityEvent({
179
+ (await createActivityEventAsync({
178
180
  clientId: input.clientId,
179
181
  kind: "operator",
180
182
  title: input.title,
@@ -183,7 +185,7 @@ function auditBreakerEvent(input: { jobId: string; clientId: string; title: stri
183
185
  icon: input.icon,
184
186
  view: "activity",
185
187
  metadata: { source: "server", maintenanceJobId: input.jobId, ...input.metadata },
186
- });
188
+ }));
187
189
  } catch (error) {
188
190
  // The pause/escalation itself already happened; losing the timeline entry must not throw back
189
191
  // into the scheduler's tick.
@@ -140,7 +140,7 @@ export async function runCdWatcherJob(context: MaintenanceJobContext = { signal:
140
140
  // `offThread: true` mirrors the #1725 off-thread jobs (old-message-prune, db-maintenance, …): it
141
141
  // records in the run's persisted result that the heavy work ran in a subprocess, so an operator
142
142
  // reading the last result sees the same proof the run registry acted on for breaker attribution.
143
- return { ...result, offThread: true, transition: notifyMainCiTransition(result.observation) };
143
+ return { ...result, offThread: true, transition: await notifyMainCiTransition(result.observation) };
144
144
  }
145
145
 
146
146
  /** Best-effort Cosmos deploy hero-shot: read the ledger row this deploy just
@@ -164,9 +164,9 @@ async function emitDeployHeroShot(sha: string | null): Promise<void> {
164
164
  }
165
165
 
166
166
  /** Best-effort transition alert; never throws into the deploy job. */
167
- function notifyMainCiTransition(observation: CiObservation): Record<string, unknown> {
167
+ async function notifyMainCiTransition(observation: CiObservation): Promise<Record<string, unknown>> {
168
168
  try {
169
- const { transition, incidentId, notified, messages } = notifyCiTransition(observation);
169
+ const { transition, incidentId, notified, messages } = await notifyCiTransition(observation);
170
170
  return { flip: transition, notified, messages, ...(incidentId ? { incidentId } : {}) };
171
171
  } catch (error) {
172
172
  const message = errMessage(error);
@@ -9,6 +9,7 @@ import { isRecord } from "@humwick/sdk";
9
9
  import { createHash } from "node:crypto";
10
10
  import { sendMessageServiceAsync } from "../services/send-message";
11
11
  import { checkoutRefreshEnabled } from "../config";
12
+ import { runGit } from "../services/git-process";
12
13
 
13
14
  async function notice(projectId: string, projectSlug: string, host: string, rootPath: string, reason: string): Promise<void> {
14
15
  const key = createHash("sha256").update(JSON.stringify([projectId, host, rootPath, reason])).digest("hex");
@@ -28,6 +29,7 @@ export function reconcileCheckoutRefresh(signal?: AbortSignal): Promise<Record<s
28
29
  async function reconcile(signal?: AbortSignal): Promise<Record<string, unknown>> {
29
30
  const dispatched: string[] = [];
30
31
  const skipped: string[] = [];
32
+ const remoteTips = new Map<string, Promise<string | undefined>>();
31
33
  for (const project of await listProjectsAsync()) {
32
34
  if (signal?.aborted) break;
33
35
  const roots = await rootsForProjectAsync(project.id);
@@ -55,8 +57,23 @@ async function reconcile(signal?: AbortSignal): Promise<Record<string, unknown>>
55
57
  if (prior && ["pending", "accepted", "running"].includes(prior.status)) continue;
56
58
  // The host reported once that it cannot refresh; re-asking every tick only repeats that (#3629).
57
59
  if (health === "unsupported") { skipped.push(`${project.slug}: unsupported host ${hostId} for ${root.rootPath}`); continue; }
60
+ // Completed receipts remain valid until the remote default branch moves (#3813).
61
+ if (prior?.status === "succeeded" && prior.result?.targetSha && ["current", "refreshed", "disabled"].includes(prior.result.status)) {
62
+ let tip = remoteTips.get(root.remoteUrl!);
63
+ if (!tip) {
64
+ tip = runGit(["ls-remote", "--symref", "--", root.remoteUrl!, "HEAD"], 10_000, 4096).then(result => {
65
+ if (result.exitCode !== 0 || result.unavailable || !/^ref: refs\/heads\/.+\tHEAD$/m.test(result.stdout)) return undefined;
66
+ return result.stdout.match(/^([0-9a-f]{40,64})\tHEAD$/m)?.[1];
67
+ });
68
+ remoteTips.set(root.remoteUrl!, tip);
69
+ }
70
+ const sha = await tip;
71
+ if (!sha) { skipped.push(`${project.slug}: remote default branch unavailable`); continue; }
72
+ if (sha === prior.result.targetSha) continue;
73
+ }
58
74
  // Leave one tick of backoff after terminal failure, including restart/lease recovery (#3691).
59
75
  if (prior && (["failed", "timed_out"].includes(prior.status) || prior.result?.status === "error") && Date.now() < (prior.updatedAt ?? 0) + 60_000) continue;
76
+ if (signal?.aborted) break;
60
77
  const command = await createCommandAsync({ type: "project.checkout.refresh", source: "system", target: `orchestrator-${hostId}`,
61
78
  params: { projectId: project.id, rootPath: root.rootPath, remoteUrl: root.remoteUrl, orchestratorId: hostId, enabled: true, ...(prior?.result ? { previousResult: prior.result } : {}) } });
62
79
  emitCommandEvent(command, "command.requested");
@@ -66,7 +83,7 @@ async function reconcile(signal?: AbortSignal): Promise<Record<string, unknown>>
66
83
  return { enabled: true, dispatched, skipped };
67
84
  }
68
85
 
69
- // A confirmed publish accelerates the same periodic reconciliation; external pushes converge on ticks.
86
+ // Publish hints and external pushes use the same remote-tip comparison.
70
87
  subscribeRelayEvents((event) => {
71
88
  if (!event.type.startsWith("command.") || !isRecord(event.data.command)) return;
72
89
  const command = event.data.command;
@@ -17,12 +17,13 @@
17
17
  // - the configured fleet-ops agent target, so something that can actually act is woken.
18
18
 
19
19
  import { errMessage } from "@humwick/sdk";
20
- import { getConfig, setConfig } from "../config-store";
20
+ import { getConfig } from "../config-store";
21
+ import { setConfigAsync } from "../config-store-write";
22
+ import { resetExpiredCriticalRunsAsync } from "../db/maintenance-job-runs-async";
21
23
  import { stewardFallbackTarget } from "../config";
22
24
  import {
23
25
  evaluateCriticalMaintenanceJobs,
24
26
  legacyHungCriticalMaintenanceRuns,
25
- resetExpiredCriticalMaintenanceRuns,
26
27
  type CriticalJobCondition,
27
28
  type LegacyHungCriticalMaintenanceRun,
28
29
  type ResetCriticalMaintenanceRun,
@@ -69,11 +70,11 @@ export interface CriticalJobWatchdogResult {
69
70
  suppressed?: "unchanged-within-reminder-window" | "awaiting-second-failure";
70
71
  }
71
72
 
72
- export function runCriticalJobWatchdog(now: number = Date.now()): CriticalJobWatchdogResult {
73
+ export async function runCriticalJobWatchdog(now: number = Date.now()): Promise<CriticalJobWatchdogResult> {
73
74
  // Do this before evaluating health so the durable scheduler latch is recovered even if the
74
75
  // notification path is unavailable. A normal timed-out run clears itself; this is only the
75
76
  // safety net for a row stranded in `running` after its own deadline lease elapsed.
76
- const resetRuns = resetExpiredCriticalMaintenanceRuns(now);
77
+ const resetRuns = await resetExpiredCriticalRunsAsync(now);
77
78
  const legacyHungRuns = legacyHungCriticalMaintenanceRuns(now);
78
79
  const conditions = evaluateCriticalMaintenanceJobs(now);
79
80
  const errors = conditions.filter((condition) => condition.status === "error");
@@ -86,9 +87,9 @@ export function runCriticalJobWatchdog(now: number = Date.now()): CriticalJobWat
86
87
  state.missedChecks[key] = checks;
87
88
  return checks >= 2;
88
89
  });
89
- const persist = () => {
90
+ const persist = async () => {
90
91
  if (JSON.stringify(state) !== JSON.stringify(prior)) {
91
- setConfig(STATE_NAMESPACE, STATE_KEY, state, "critical-job-watchdog");
92
+ await setConfigAsync(STATE_NAMESPACE, STATE_KEY, state, "critical-job-watchdog");
92
93
  }
93
94
  };
94
95
  const heldRestartEpoch = currentHeldRestartEpoch(now);
@@ -97,7 +98,7 @@ export function runCriticalJobWatchdog(now: number = Date.now()): CriticalJobWat
97
98
  // Recovered (or never degraded): clear the marker so the NEXT degradation notifies immediately
98
99
  // rather than being swallowed by the reminder window opened by the previous one.
99
100
  state.lastNotified = null;
100
- persist();
101
+ await persist();
101
102
  return errors.length > 0
102
103
  ? { status: "error", degradedJobIds: errors.map((condition) => condition.jobId), notified: false, recipients: [], suppressed: "awaiting-second-failure" }
103
104
  : { status: conditions.length > 0 ? "warn" : "ok", degradedJobIds: [], notified: false, recipients: [] };
@@ -115,7 +116,7 @@ export function runCriticalJobWatchdog(now: number = Date.now()): CriticalJobWat
115
116
  ...(heldRestartEpoch ? [`epoch:${heldRestartEpoch.id}:${heldRestartEpoch.blockerCode}`] : []),
116
117
  ].sort().join("|");
117
118
  if (state.lastNotified?.fingerprint === fingerprint && now - state.lastNotified.notifiedAt < DEGRADED_REMINDER_MS) {
118
- persist();
119
+ await persist();
119
120
  return {
120
121
  status: "error", degradedJobIds,
121
122
  ...(resetRuns.length > 0 ? { resetJobIds: resetRuns.map((run) => run.jobId) } : {}),
@@ -127,18 +128,18 @@ export function runCriticalJobWatchdog(now: number = Date.now()): CriticalJobWat
127
128
 
128
129
  const { subject, body, payload } = composeNotice(degraded, resetRuns, legacyHungRuns, heldRestartEpoch, now);
129
130
  const recipients: string[] = [];
130
- const human = notifyWorkspaceHumanEscalation({
131
+ const human = (await notifyWorkspaceHumanEscalation({
131
132
  subject,
132
133
  body,
133
134
  payload,
134
135
  source: "maintenance-critical-job-watchdog",
135
136
  tags: ["agent-relay", "maintenance"],
136
- });
137
+ }));
137
138
  if (human.accepted && human.channelId) recipients.push(human.channelId);
138
139
 
139
140
  const agentTarget = stewardFallbackTarget();
140
141
  if (agentTarget) {
141
- const routed = notifyTarget("maintenance.degraded", {}, agentTarget, subject, body, payload);
142
+ const routed = await notifyTarget("maintenance.degraded", {}, agentTarget, subject, body, payload);
142
143
  if (routed) recipients.push(routed);
143
144
  }
144
145
 
@@ -154,7 +155,7 @@ export function runCriticalJobWatchdog(now: number = Date.now()): CriticalJobWat
154
155
  }
155
156
 
156
157
  state.lastNotified = { fingerprint, notifiedAt: now };
157
- persist();
158
+ await persist();
158
159
  return {
159
160
  status: "error", degradedJobIds,
160
161
  ...(resetRuns.length > 0 ? { resetJobIds: resetRuns.map((run) => run.jobId) } : {}),
@@ -236,16 +237,14 @@ function composeNotice(
236
237
 
237
238
  /** Handler wrapper: a watchdog that throws must not mark itself failed-and-silent, so failures are
238
239
  * reported as a result the job record carries. */
239
- export function criticalJobWatchdogJob(context: { signal?: AbortSignal } = {}): Record<string, unknown> {
240
- // #1819 — SYNCHRONOUS and single-unit: one `evaluateCriticalMaintenanceJobs` read then one notify
241
- // fan-out that must not be split (the `lastNotified` fingerprint is stamped only after the sends,
242
- // so a half-run would re-page on the next tick). The only safe checkpoint is before it starts, and
243
- // on one thread that is also the only one that could ever fire. Its work is bounded by the number
244
- // of critical jobs (one today), so overrun is not a live risk; if that ever changes this is an
245
- // #1809 offload candidate, not a place for more checks.
240
+ export async function criticalJobWatchdogJob(context: { signal?: AbortSignal } = {}): Promise<Record<string, unknown>> {
241
+ // #1819 — single-unit: one `evaluateCriticalMaintenanceJobs` read then one notify fan-out that must not
242
+ // be split (the `lastNotified` fingerprint is stamped only after the sends, so a half-run would re-page
243
+ // on the next tick). The only safe checkpoint is before it starts. Its two writes (the lease reset and
244
+ // the state persist) are writer ops (#1870 S7).
246
245
  if (context.signal?.aborted) return { status: "ok", aborted: true, degradedJobIds: [], notified: false, recipients: [] };
247
246
  try {
248
- return { ...runCriticalJobWatchdog() };
247
+ return { ...(await runCriticalJobWatchdog()) };
249
248
  } catch (error) {
250
249
  return { status: "error", error: errMessage(error) };
251
250
  }
@@ -9,7 +9,7 @@ export function emitCommand(command: Command): void {
9
9
 
10
10
  // Route a maintenance notification, swallowing failures (a stale/missing/misconfigured
11
11
  // target must never break the sweep). Returns the target on success, null otherwise.
12
- export function notifyTarget(
12
+ export async function notifyTarget(
13
13
  type: NotificationType,
14
14
  scope: NotificationScope,
15
15
  target: string,
@@ -17,10 +17,10 @@ export function notifyTarget(
17
17
  body: string,
18
18
  payload: Record<string, unknown>,
19
19
  idempotencyKey?: string,
20
- ): string | null {
20
+ ): Promise<string | null> {
21
21
  if (!target) return null;
22
22
  try {
23
- routeNotification({ type, scope, recipients: [target], message: { subject, body, payload, idempotencyKey } });
23
+ await routeNotification({ type, scope, recipients: [target], message: { subject, body, payload, idempotencyKey } });
24
24
  return target;
25
25
  } catch {
26
26
  return null;
@@ -0,0 +1,30 @@
1
+ import { getGateway } from "../db/gateway";
2
+ import type { MaintenanceJobDefinition } from "./types";
3
+
4
+ export const HISTORY_RETENTION_JOB: MaintenanceJobDefinition = {
5
+ id: "history-retention", critical: false,
6
+ title: "Command, kernel replay and token history retention",
7
+ description: "Expire superseded checkout refresh commands after one hour, other non-spawn terminal commands and kernel replay receipts after 30 days, and raw usage after 90 days. Preserve references, expired replay keys and permanent budget spend (#3619, #3797).",
8
+ intervalMs: 60 * 60_000, backlogIntervalMs: 1_000, deadlineMs: 30_000, runOnStart: true,
9
+ async handler(context) {
10
+ const gateway = getGateway();
11
+ const result = { prunedCommands: 0, prunedKernelReceipts: 0, prunedTokenReports: 0, moreWork: false };
12
+ for (const [op, key] of [
13
+ ["historyRetention.commands", "prunedCommands"],
14
+ ["historyRetention.kernel", "prunedKernelReceipts"],
15
+ ["historyRetention.tokens", "prunedTokenReports"],
16
+ ] as const) {
17
+ if (context.signal.aborted) return { ...result, aborted: true, moreWork: true };
18
+ const start = performance.now();
19
+ let batch: { pruned: number; moreWork: boolean };
20
+ do {
21
+ if (context.signal.aborted) return { ...result, aborted: true, moreWork: true };
22
+ batch = await gateway.write(op, {}) as typeof batch;
23
+ result[key] += batch.pruned;
24
+ // Each await releases the writer for foreground work; bound the whole catch-up run (#3807).
25
+ } while (op === "historyRetention.commands" && batch.moreWork && performance.now() - start < 250);
26
+ result.moreWork ||= batch.moreWork;
27
+ }
28
+ return result;
29
+ },
30
+ };
@@ -1,6 +1,7 @@
1
1
  export {
2
2
  cancelMaintenanceRun,
3
3
  listMaintenanceJobs,
4
+ listMaintenanceJobsAsync,
4
5
  listRecentMaintenanceRuns,
5
6
  listRunningMaintenanceRuns,
6
7
  resetOrphanTrackerForTests,
@@ -1,5 +1,9 @@
1
+ import { OFFLINE_AGENT_PRUNE_JOB } from "./offline-agent-prune-job";
2
+ import { pruneOrphanedSharedWorkspacesAsync, releaseExpiredDriveLeasesAsync } from "../db/runtime-tail-async";
3
+ import { HISTORY_RETENTION_JOB } from "./history-retention-job";
1
4
  import { isHumanAgentId } from "@humwick/sdk";
2
- import { IDLE_EPICS_JOB, PENDING_ISSUE_CLOSE_JOB } from "./long-running-work";
5
+ import { REAP_INTERVAL_MS, STALE_TTL_MS } from "../config";
6
+ import { IDLE_EPICS_JOB, PENDING_ISSUE_CLOSE_JOB, PLAN_READY_NOTICE_JOB } from "./long-running-work";
3
7
  import { CHECKOUT_REFRESH_JOB } from "./checkout-refresh";
4
8
  import { CLAUDE_API_BUDGET_RECONCILE_JOB } from "./claude-api-budget-job";
5
9
  import { SERVICE_ACCESS_JOBS } from "./service-access-job";
@@ -15,27 +19,9 @@ import { deriveAgentBusyHealth } from "../agent-busy-health";
15
19
  import { expireStaleBusAgents } from "../bus";
16
20
  import { eventLoopLagGraceMs } from "../event-loop-lag";
17
21
  import { pruneOutboxAsync } from "../bus-outbox-async";
18
- import { expireCommands } from "../commands-db";
22
+ import { expireCommandsAsync } from "../db/runtime-admin-async";
19
23
  import { getRetentionConfig } from "../retention-config-store";
20
- import { OFFLINE_PRUNE_MS, REAP_INTERVAL_MS, STALE_TTL_MS } from "../config";
21
- import {
22
- createActivityEventAsync,
23
- evaluatePoolBindingsAsync,
24
- getAgent,
25
- listAgents,
26
- listStaleQueuedDirectTargetsAsync,
27
- pruneOrphanedSharedWorkspaces,
28
- pruneOfflineAgentsAsync,
29
- pruneRetentionBatchAsync,
30
- pruneProviderQuotaHistoryAsync,
31
- reapStaleOrchestratorsAsync,
32
- releaseExpiredClaimsAsync,
33
- releaseExpiredDriveLeases,
34
- releaseOrphanedTasksAsync,
35
- reapStaleAgentsAsync,
36
- revokeOrphanedRuntimeTokensAsync,
37
- runDbMaintenanceAsync,
38
- } from "../db";
24
+ import { createActivityEventAsync, evaluatePoolBindingsAsync, getAgent, listAgents, listStaleQueuedDirectTargetsAsync, pruneRetentionBatchAsync, pruneProviderQuotaHistoryAsync, reapStaleOrchestratorsAsync, releaseExpiredClaimsAsync, releaseOrphanedTasksAsync, reapStaleAgentsAsync, revokeOrphanedRuntimeTokensAsync, runDbMaintenanceAsync } from "../db";
39
25
  import { isAgentUnavailable } from "../db/agent-predicates";
40
26
  import { resolveTeamCoordinatorAgentId } from "../coordinator-authority";
41
27
  import { flushQueuedDirectMessages } from "../services/managed-running";
@@ -49,7 +35,6 @@ import { getLifecycleManager } from "../lifecycle-manager";
49
35
  import { applyCommandToRecipe } from "../recipe-runner";
50
36
  import { settleWorkspaceCommand } from "../workspace-command-settle";
51
37
  import {
52
- emitAgentRemoved,
53
38
  emitAgentStatus,
54
39
  emitMessageClaimReleased,
55
40
  emitOrchestratorStatus,
@@ -64,7 +49,6 @@ import { runIdleAgentDigest } from "../services/idle-agent-digest";
64
49
  import { runShutdownWatchdog } from "../services/shutdown-watchdog";
65
50
  import { AGENT_HANG_WATCHDOG_MAINTENANCE_JOB } from "../services/agent-hang-watchdog-job";
66
51
  import { reapIdleStewards } from "../services/steward-reaper";
67
- import { emitWorkFinalityResult } from "../services/work-finality";
68
52
  import { escalateExpiredSpawnCommands } from "../services/spawn-loss-escalation";
69
53
  import { reapUnregisteredSpawnCommands } from "../services/spawn-registration-watchdog";
70
54
  import { resumeRateLimitedAgents } from "../services/rate-limit-resume";
@@ -182,7 +166,7 @@ export async function runStuckBusyWatchdog(input: { now?: number; signal?: Abort
182
166
  },
183
167
  });
184
168
 
185
- const messages = routeNotification({
169
+ const messages = await routeNotification({
186
170
  type: "agent.stuck_busy",
187
171
  scope: { agentId: agent.id, parent: agent.spawnedBy, teamId: agent.teamId },
188
172
  message: {
@@ -300,9 +284,9 @@ export const definitions: MaintenanceJobDefinition[] = [
300
284
  runOnStart: true,
301
285
  // #1819 — SYNCHRONOUS, one atomic statement, no fan-out: nothing to split, so the pre-flight
302
286
  // check is the whole of its cooperation.
303
- handler(context) {
287
+ async handler(context) {
304
288
  if (context.signal?.aborted) return { releasedDriveLeaseAgentIds: [], aborted: true };
305
- return { releasedDriveLeaseAgentIds: releaseExpiredDriveLeases() };
289
+ return { releasedDriveLeaseAgentIds: (await releaseExpiredDriveLeasesAsync()) };
306
290
  },
307
291
  },
308
292
  {
@@ -339,7 +323,7 @@ export const definitions: MaintenanceJobDefinition[] = [
339
323
  // message belongs in the queue (this is hooked to agent availability,
340
324
  // not pool-slot reclaim).
341
325
  if (!agent || isAgentUnavailable(agent)) continue;
342
- const flushed = flushQueuedDirectMessages(agent!.id);
326
+ const flushed = await flushQueuedDirectMessages(agent!.id);
343
327
  if (flushed.length > 0) reswept[target] = flushed.length;
344
328
  }
345
329
  return { resweptTargets: reswept };
@@ -359,19 +343,14 @@ export const definitions: MaintenanceJobDefinition[] = [
359
343
  // by heartbeat and deleted on removal, so a missing/offline agent record for the
360
344
  // target means it will never poll this command again. A merely-busy (online) host is
361
345
  // left alone, preserving the #930/#953 "don't sweep before the host can claim it".
362
- const commands = expireCommands(Date.now(), {
363
- isTargetGone: (command) => {
364
- if (!command.target || command.target === "system") return false;
365
- const agent = getAgent(command.target);
366
- return !agent || agent.status === "offline";
367
- },
368
- });
346
+ const commands = await expireCommandsAsync();
347
+
369
348
  // #1819 — deliberately NOT checkpointed: `expireCommands` already moved these rows terminal
370
349
  // and nothing re-runs this settle, so bailing would strand their workspace and recipe forever.
371
350
  // Bounded by one expiry sweep.
372
351
  for (const command of commands) {
373
- notifySelfResumeNoOp(command);
374
- settleContextResetCarry(command);
352
+ await notifySelfResumeNoOp(command);
353
+ (await settleContextResetCarry(command));
375
354
  noteCompactionResult(command);
376
355
  await settleWorkspaceCommand(command, { onMergeSettled: scheduleRepoMerge });
377
356
  await applyCommandToRecipe(command);
@@ -412,7 +391,7 @@ export const definitions: MaintenanceJobDefinition[] = [
412
391
  // #1819 — deliberately NOT checkpointed, as in command-expiration: the attachment is already
413
392
  // expired, and this is the one place a parent is told its agent died.
414
393
  for (const id of expired.agentIds) {
415
- getLifecycleManager().onAgentDisappeared(id);
394
+ (await getLifecycleManager().onAgentDisappeared(id));
416
395
  // #636/#659 — only after the stale reconnect grace expires do we turn a bare
417
396
  // heartbeat gap into a terminal parent notification. A live runner that
418
397
  // reconnects before this point heals from `stale` without a false exit.
@@ -420,7 +399,7 @@ export const definitions: MaintenanceJobDefinition[] = [
420
399
  // when a succeeded agent.shutdown command explains the silence, instead of the
421
400
  // heartbeat-lost/transport-loss verdict a graceful reap used to receive.
422
401
  const { reason, diagnosis } = classifyBusExpirationDeath(id);
423
- notifyAgentOffline(id, reason, diagnosis);
402
+ (await notifyAgentOffline(id, reason, diagnosis));
424
403
  }
425
404
  for (const task of expired.orphanedTasks) emitTaskChanged(task, "task.updated");
426
405
  return {
@@ -464,26 +443,7 @@ export const definitions: MaintenanceJobDefinition[] = [
464
443
  return { reapedAgentIds };
465
444
  },
466
445
  },
467
- {
468
- id: "offline-agent-prune",
469
- critical: false,
470
- title: "Offline agent prune",
471
- description: "Delete long-offline provider agents and release their claims.",
472
- intervalMs: REAP_INTERVAL_MS,
473
- runOnStart: false,
474
- async handler(context) {
475
- if (context.signal?.aborted) return { prunedAgentIds: [], aborted: true };
476
- // #1084 crash-final-loss fix-forward — defense-in-depth: `notifyAgentOffline` is the primary
477
- // flush point when an agent first goes offline, so this is normally a no-op by the time an
478
- // agent reaches prune horizon; the async facade snapshots its held queue and performs the DB
479
- // finalization in the SAME worker transaction before deleting the agent row.
480
- const prunedAgentIds = await pruneOfflineAgentsAsync(OFFLINE_PRUNE_MS, {
481
- onFinality: emitWorkFinalityResult,
482
- });
483
- for (const id of prunedAgentIds) emitAgentRemoved(id);
484
- return { prunedAgentIds };
485
- },
486
- },
446
+ OFFLINE_AGENT_PRUNE_JOB,
487
447
  AGENT_IDENTITY_ARCHIVE_PRUNE_JOB,
488
448
  {
489
449
  id: "orphan-token-revoker",
@@ -498,8 +458,9 @@ export const definitions: MaintenanceJobDefinition[] = [
498
458
  // event loop was stalled, a live replacement's heartbeats may still be unprocessed, so the
499
459
  // grace widens by the observed lag instead of misreading the backlog as post-mortem silence.
500
460
  // #1895 (S3.2 L10, review finding 3) — routed through the async gateway facade.
501
- const revokedOrphanTokens = await revokeOrphanedRuntimeTokensAsync(STALE_TTL_MS, eventLoopLagGraceMs());
502
- return { revokedOrphanTokens };
461
+ // #3776 — paged short writes, bounded by the abort signal and a time budget.
462
+ const { revoked, complete } = await revokeOrphanedRuntimeTokensAsync(STALE_TTL_MS, eventLoopLagGraceMs(), { signal: context.signal });
463
+ return { revokedOrphanTokens: revoked, moreWork: !complete };
503
464
  },
504
465
  },
505
466
  {
@@ -509,12 +470,12 @@ export const definitions: MaintenanceJobDefinition[] = [
509
470
  description: "Stop spawned sessions whose relay agent is offline/gone but whose process the orchestrator still reports running, after a grace period for self-heal.",
510
471
  intervalMs: ORPHAN_REAPER_INTERVAL_MS,
511
472
  runOnStart: false,
512
- handler: (context) => reapOrphanedSessions({ signal: context.signal }),
473
+ handler: async (context) => (await reapOrphanedSessions({ signal: context.signal })),
513
474
  },
514
- { id: "transient-agent-reaper", critical: false, title: "Transient agent reaper", description: "Cleanly shut down transient spawned agents once they are idle and any isolated branch work has landed; also flushes a persistent agent's held work-final report once it has settled idle (#1084 HIGH fix-forward).", intervalMs: REAP_INTERVAL_MS, runOnStart: false, handler: (context) => reapTransientAgents({ signal: context.signal }) },
475
+ { id: "transient-agent-reaper", critical: false, title: "Transient agent reaper", description: "Cleanly shut down transient spawned agents once they are idle and any isolated branch work has landed; also flushes a persistent agent's held work-final report once it has settled idle (#1084 HIGH fix-forward).", intervalMs: REAP_INTERVAL_MS, runOnStart: false, handler: async (context) => (await reapTransientAgents({ signal: context.signal })) },
515
476
  { id: "idle-agent-digest", critical: false, title: "Idle-agent digest", description: "One digest per coordinator window listing idle children; stops provably safe ones when the team allows it (#3428). Off until the idle-digest setting enables it.", intervalMs: REAP_INTERVAL_MS, runOnStart: false, handler: (context) => runIdleAgentDigest({ signal: context.signal }) },
516
477
  { id: "shutdown-watchdog", critical: false, title: "Shutdown kill-switch watchdog", description: "#1746 — recover a NON-policy agent stuck `shutting-down` past its grace whose shutdown command never executed (owning host offline / command expired): re-issue exactly one forceful shutdown, then surface a terminal `kill-failed` if it is still alive a further grace window later. Policy/steward agents are excluded (the lifecycle-manager owns their retry ladder, #1761).", intervalMs: REAP_INTERVAL_MS, runOnStart: false, handler: (context) => runShutdownWatchdog({ signal: context.signal }) },
517
- { id: "steward-reaper", critical: false, title: "Orphan steward reaper", description: "Independent backstop (#1761) for the lifecycle reconcile: reap ORPHANED stewards ONLY — a live steward agent no managed policy state references (left when a respawn overwrote the state's agentId, or handed off after the lifecycle exhausted its forceful stop budget). Reaps an orphan once idle past the dashboard keepalive grace, or immediately when steward spawning is disabled. Never reaps a busy/provider-blocked/mid-land (claim-holding) steward, reaps each orphan at most once (idempotent), and never touches a still-tracked steward — that one is the lifecycle reconcile's (its keepalive idle-timeout, policy-disabled stop, and forceful stopping-wedge escalation), so the two can never race.", intervalMs: REAP_INTERVAL_MS, runOnStart: false, handler: (context) => reapIdleStewards({ signal: context.signal }) },
478
+ { id: "steward-reaper", critical: false, title: "Orphan steward reaper", description: "Independent backstop (#1761) for the lifecycle reconcile: reap ORPHANED stewards ONLY — a live steward agent no managed policy state references (left when a respawn overwrote the state's agentId, or handed off after the lifecycle exhausted its forceful stop budget). Reaps an orphan once idle past the dashboard keepalive grace, or immediately when steward spawning is disabled. Never reaps a busy/provider-blocked/mid-land (claim-holding) steward, reaps each orphan at most once (idempotent), and never touches a still-tracked steward — that one is the lifecycle reconcile's (its keepalive idle-timeout, policy-disabled stop, and forceful stopping-wedge escalation), so the two can never race.", intervalMs: REAP_INTERVAL_MS, runOnStart: false, handler: async (context) => (await reapIdleStewards({ signal: context.signal })) },
518
479
  {
519
480
  id: "restart-epoch-reconcile",
520
481
  // CRITICAL: if this stops running, an epoch opened by a deploy is never released — every
@@ -555,7 +516,7 @@ export const definitions: MaintenanceJobDefinition[] = [
555
516
  description: "Auto-resume agents held on a provider usage/rate-limit stall once their reset window has passed (#286).",
556
517
  intervalMs: REAP_INTERVAL_MS,
557
518
  runOnStart: false,
558
- handler: (context) => resumeRateLimitedAgents({ signal: context.signal }),
519
+ handler: async (context) => (await resumeRateLimitedAgents({ signal: context.signal })),
559
520
  },
560
521
  { id: "provider-still-held-nudge", critical: false, title: "Provider still-held nudge", description: "Notify a child's parent while it remains provider-blocked, and page the operator once a top-level provider block passes its threshold.", intervalMs: REAP_INTERVAL_MS, runOnStart: false, handler: async (context) => await sendStillHeldNudges(Date.now(), context.signal) },
561
522
  {
@@ -647,6 +608,7 @@ export const definitions: MaintenanceJobDefinition[] = [
647
608
  prunedMessages: result.prunedMessages,
648
609
  prunedActivityEvents: result.prunedActivityEvents,
649
610
  prunedSpawnCommands: result.prunedSpawnCommands,
611
+ slimmedSpawnProfiles: result.slimmedSpawnProfiles,
650
612
  offThread: result.offThread,
651
613
  moreWork: result.moreWork, // #1758 — bounded-progress signal; drives backlogIntervalMs reschedule.
652
614
  };
@@ -661,6 +623,7 @@ export const definitions: MaintenanceJobDefinition[] = [
661
623
  SNAPSHOT_LEDGER_PRUNE_JOB,
662
624
  PROVIDER_SECRET_SCRUB_JOB,
663
625
  WEB_TOOL_CALL_PRUNE_JOB,
626
+ HISTORY_RETENTION_JOB,
664
627
  CONTINUATION_ARCHIVE_SEARCH_SYNC_JOB,
665
628
  SHIPPING_STATS_ROLLUP_JOB,
666
629
  REPLY_OBLIGATION_PARITY_JOB,
@@ -761,9 +724,9 @@ export const definitions: MaintenanceJobDefinition[] = [
761
724
  intervalMs: REAP_INTERVAL_MS,
762
725
  runOnStart: true,
763
726
  // #1819 — SYNCHRONOUS, one atomic sweep: pre-flight check only, nothing to split.
764
- handler(context) {
727
+ async handler(context) {
765
728
  if (context.signal?.aborted) return { prunedSharedWorkspaceIds: [], aborted: true };
766
- const prunedSharedWorkspaceIds = pruneOrphanedSharedWorkspaces();
729
+ const prunedSharedWorkspaceIds = (await pruneOrphanedSharedWorkspacesAsync());
767
730
  return { prunedSharedWorkspaceIds };
768
731
  },
769
732
  },
@@ -829,7 +792,7 @@ export const definitions: MaintenanceJobDefinition[] = [
829
792
  intervalMs: WORKSPACE_IDLE_REFRESH_INTERVAL_MS,
830
793
  runOnStart: false,
831
794
  deadlineMs: 60 * 1000,
832
- handler: (context) => refreshIdleWorkspaces({ signal: context.signal }),
795
+ handler: async (context) => (await refreshIdleWorkspaces({ signal: context.signal })),
833
796
  },
834
797
  {
835
798
  id: "workspace-gc",
@@ -843,14 +806,14 @@ export const definitions: MaintenanceJobDefinition[] = [
843
806
  // otherwise never run it at all — the backstop effectively off exactly when it's needed.
844
807
  runOnStart: true,
845
808
  deadlineMs: 60 * 1000,
846
- handler: (context) => workspaceGC({ signal: context.signal }),
809
+ handler: async (context) => (await workspaceGC({ signal: context.signal })),
847
810
  },
848
811
  { id: "agent-exit-cleanup", critical: false, title: "Agent exit cleanup",
849
812
  description: "Save exited owners on origin, then remove their workspace, branch, outbox and provider home on each host (#2749).",
850
813
  intervalMs: 15 * 60_000, runOnStart: true, logRuns: true, deadlineMs: 60_000,
851
814
  handler: (context) => requestAgentExitCleanupSweep(context.signal),
852
815
  },
853
- IDLE_EPICS_JOB, PENDING_ISSUE_CLOSE_JOB,
816
+ IDLE_EPICS_JOB, PENDING_ISSUE_CLOSE_JOB, PLAN_READY_NOTICE_JOB,
854
817
  REVIEW_REF_RECONCILE_JOB,
855
818
  CHECKOUT_REFRESH_JOB,
856
819
  ARTIFACT_CHECKOUT_GC_JOB,
@@ -5,6 +5,8 @@ import { routeNotification } from "../notification-router";
5
5
  import { DAY_MS } from "./constants";
6
6
  import type { MaintenanceJobDefinition } from "./types";
7
7
 
8
+ export { PLAN_READY_NOTICE_JOB } from "./plan-ready-notice-job";
9
+
8
10
  export const PENDING_ISSUE_CLOSE_JOB: MaintenanceJobDefinition = {
9
11
  id: "pending-issue-closes", title: "Issues awaiting Task completion", critical: false,
10
12
  description: "Close landed delivery issues when their Tasks reach doneWhen and pass validation.",
@@ -23,7 +25,7 @@ export async function remindIdleEpics(signal: AbortSignal, now = Date.now()): Pr
23
25
  if (signal.aborted) break;
24
26
  const lines = [...renderTeamIdleEpics(team.id), ...teamFailures.map(failure => `- ${failure}`)];
25
27
  if (!lines.length) continue;
26
- routeNotification({
28
+ await routeNotification({
27
29
  type: "team.idle", scope: { teamId: team.id }, recipients: [`coordinator:${team.id}`],
28
30
  message: { kind: "system", from: "system", subject: "Open idle epics and Plans", body: lines.join("\n"), replyExpected: false,
29
31
  payload: { kind: "team.idle-epics", teamId: team.id }, idempotencyKey: `idle-epics:${team.id}:${Math.floor(now / DAY_MS)}` },