@humwick/server 0.130.2 → 0.130.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (587) hide show
  1. package/bundled/prompts/manifest.json +1 -0
  2. package/bundled/prompts/task.hydration.md +1 -1
  3. package/bundled/roles/builder.md +1 -1
  4. package/docs/guides/sub-coordinators.md +12 -5
  5. package/docs/guides/tools-coordination.md +1 -0
  6. package/docs/guides/workflows.md +16 -0
  7. package/docs/openapi.json +175 -4
  8. package/package.json +8 -7
  9. package/public/assets/{MessageBubble-BWLqMGKG.js → MessageBubble-BOkmEvgZ.js} +2 -2
  10. package/public/assets/{PlanGraphPanel-3TlIQpjk.js → PlanGraphPanel-BkaDJp0r.js} +2 -2
  11. package/public/assets/{TraceView-Wimm0Czv.js → TraceView-B99Uu2yT.js} +2 -2
  12. package/public/assets/{VaultDecisionCard-Bau_vNax.js → VaultDecisionCard-DUIfTTFF.js} +2 -2
  13. package/public/assets/{activity-CrSurn-r.js → activity-ZIX0N1El.js} +2 -2
  14. package/public/assets/{agent-lineage-CknAJKcb.js → agent-lineage-kq9TPYFw.js} +2 -2
  15. package/public/assets/agent-liveness-DSQY1Aa_.js +2 -0
  16. package/public/assets/{agent-name-DKbiIhBo.js → agent-name-C_7F4DFR.js} +2 -2
  17. package/public/assets/{agent-profiles-DwF6EQ4R.js → agent-profiles-BNOcrGcY.js} +2 -2
  18. package/public/assets/{agent-project-badge-Diz4Sjjb.js → agent-project-badge-B6yAh70a.js} +2 -2
  19. package/public/assets/{agent-tools-CRhpRQza.js → agent-tools-CcrhmOzF.js} +2 -2
  20. package/public/assets/{agent-type-icon-LrUEU3lB.js → agent-type-icon-CXSLrKiq.js} +2 -2
  21. package/public/assets/{agents-B-v66C-4.js → agents-DIZG97_X.js} +2 -2
  22. package/public/assets/{analytics-BqCb-LKi.js → analytics-rasmoPjR.js} +2 -2
  23. package/public/assets/{artifact-viewer-kf4pGuAR.js → artifact-viewer-tBpTrEPb.js} +2 -2
  24. package/public/assets/{artifacts-DJevXcvg.js → artifacts-BNkrynP1.js} +2 -2
  25. package/public/assets/{artifacts-D32zyw4Y.js → artifacts-Bjq-ZyBA.js} +2 -2
  26. package/public/assets/{automation-BpRajx_5.js → automation-Cx422L3L.js} +2 -2
  27. package/public/assets/{backlog-D_UjTdzX.js → backlog-RuFQ8PUu.js} +2 -2
  28. package/public/assets/{busy-health-N3VEh4ao.js → busy-health-BvNQ9g5x.js} +2 -2
  29. package/public/assets/{channels-9jopungq.js → channels-DNbKAS0I.js} +2 -2
  30. package/public/assets/{chat-CSXrTB3C.js → chat-Bp3Fx73h.js} +3 -3
  31. package/public/assets/{code-preview-p1NnmqK0.js → code-preview-KIRZA6cz.js} +2 -2
  32. package/public/assets/{connectors-CZdqlDNL.js → connectors-k7vO4vvc.js} +2 -2
  33. package/public/assets/{cosmos-BgdsE4dG.js → cosmos-BuVoq1aw.js} +2 -2
  34. package/public/assets/{crate-agent-30aXTKva.js → crate-agent-irqlt4NH.js} +2 -2
  35. package/public/assets/{dependency-graph-B_jvw2GE.js → dependency-graph-D_rurNBz.js} +2 -2
  36. package/public/assets/{deploys-DoN6bAb5.js → deploys-yzZqIpxE.js} +2 -2
  37. package/public/assets/{display-BrKWFGJz.js → display-BemJG1f_.js} +2 -2
  38. package/public/assets/{files-D6XEu8Ng.js → files-DXWcrxOz.js} +2 -2
  39. package/public/assets/{fleet-C7jQWbw2.js → fleet-TEuOCZXE.js} +2 -2
  40. package/public/assets/{fleet-metrics-BiDs3MLx.js → fleet-metrics-BGoDAFI-.js} +2 -2
  41. package/public/assets/{formatted-body-impl-DyG0WsQS.js → formatted-body-impl-BB9eq9nN.js} +2 -2
  42. package/public/assets/{formatted-body-CQBwc1fb.js → formatted-body-qy2nTD_1.js} +3 -3
  43. package/public/assets/{host-providers-dialog-DKaW31dN.js → host-providers-dialog-BGPHxuwT.js} +2 -2
  44. package/public/assets/{index-CRHep3M9.js → index-BC5XZc0z.js} +5 -5
  45. package/public/assets/{index-MYAIwYTX.css → index-D8Rp9pz2.css} +1 -1
  46. package/public/assets/{insights-CzrtkpOE.js → insights-C-KQG0h-.js} +2 -2
  47. package/public/assets/{integrations-aVsUmigt.js → integrations-ClPRPyKU.js} +2 -2
  48. package/public/assets/{issue-ref-chip-BnSlM_95.js → issue-ref-chip-DbH8J9Ak.js} +2 -2
  49. package/public/assets/{log-viewer-qe7Ee47Z.js → log-viewer-PH4zVn24.js} +2 -2
  50. package/public/assets/{maintenance-NfjqFZAk.js → maintenance-5lV43uTL.js} +2 -2
  51. package/public/assets/{managed-agents-BiH0HgaE.js → managed-agents-BdgU35aX.js} +2 -2
  52. package/public/assets/{markdown-preview-BixaT3Xr.js → markdown-preview-DNT4OUwQ.js} +3 -3
  53. package/public/assets/{markdown-preview-impl-DNGlWIS3.js → markdown-preview-impl-CnCcPy0A.js} +2 -2
  54. package/public/assets/{memory-DNsCl6UX.js → memory--GgWH1gH.js} +2 -2
  55. package/public/assets/{messages-DopU1L1X.js → messages-CzFl_97O.js} +2 -2
  56. package/public/assets/{orchestrators-Cq7ckLQT.js → orchestrators-CVvJVkzv.js} +2 -2
  57. package/public/assets/overview-DsrZvE86.js +2 -0
  58. package/public/assets/{pairs-DE_m6rrE.js → pairs-D2d0d2py.js} +2 -2
  59. package/public/assets/{profile-icon-B3rfh77F.js → profile-icon-_SMuSbYF.js} +2 -2
  60. package/public/assets/{project-profile-instructions-DQWZE0kA.js → project-profile-instructions-Apn15y43.js} +2 -2
  61. package/public/assets/{projects-Br2Bd2h1.js → projects-D3B6kto5.js} +2 -2
  62. package/public/assets/{prompt-settings-BKvFsvGD.js → prompt-settings-DnPB6Ez6.js} +2 -2
  63. package/public/assets/provider-display-bWwiuedV.js +2 -0
  64. package/public/assets/{registry-Cw38_6gW.js → registry-D790cIhN.js} +2 -2
  65. package/public/assets/run-card-BCro-Odj.js +2 -0
  66. package/public/assets/{secrets-DxI-vzSq.js → secrets-CVXvfvbU.js} +2 -2
  67. package/public/assets/{service-access-settings-D9s_VJbd.js → service-access-settings-D3Xxqb9w.js} +2 -2
  68. package/public/assets/{settings-CKZTVGIx.js → settings-CoUC7Jci.js} +2 -2
  69. package/public/assets/shipping-D_Lp9n_J.js +2 -0
  70. package/public/assets/{stats-DyUBKyWI.js → stats-CXiNjB9S.js} +2 -2
  71. package/public/assets/{status-dot-DYqlEUhJ.js → status-dot-C703YIy1.js} +2 -2
  72. package/public/assets/store-BgDALGIX.js +9 -0
  73. package/public/assets/{tasks-Bh7Chr4-.js → tasks-DO0WpJCx.js} +2 -2
  74. package/public/assets/{teams-bowI7qVY.js → teams-FGkdi_tL.js} +2 -2
  75. package/public/assets/{terminal-viewer-BgVLHdsU.js → terminal-viewer-Dh8dSC7e.js} +3 -3
  76. package/public/assets/{terminal-viewer-impl-Dz22UPy6.js → terminal-viewer-impl-B5Zriip3.js} +2 -2
  77. package/public/assets/{use-agent-terminal-DSQQ-iY7.js → use-agent-terminal-CRUVDvLC.js} +2 -2
  78. package/public/assets/{use-decisions-samMQhQf.js → use-decisions-CoaqRh4l.js} +2 -2
  79. package/public/assets/{use-project-list-59LheVP7.js → use-project-list-X-BgT53X.js} +2 -2
  80. package/public/assets/{use-selectors-BZa25xEB.js → use-selectors-0X_UZkk-.js} +2 -2
  81. package/public/assets/{user-avatar-DHxlvUvV.js → user-avatar-CkLhVBGu.js} +2 -2
  82. package/public/assets/{versioned-prompt-editor-BmED5DnJ.js → versioned-prompt-editor-BkTi7eim.js} +2 -2
  83. package/public/assets/{work-queue-CSvpuNLz.js → work-queue-DDOLEyKo.js} +2 -2
  84. package/public/assets/{workflow-marker-DAZcj5qt.js → workflow-marker-CzOsB8BM.js} +2 -2
  85. package/public/assets/{workflows-DdmxRSyg.js → workflows-DJilvmRM.js} +2 -2
  86. package/public/assets/{workspaces-BxeKfVuF.js → workspaces-CHcfbLR3.js} +2 -2
  87. package/public/cosmos.html +4 -4
  88. package/public/index.html +29 -29
  89. package/runner/plugins/claude/.claude-plugin/plugin.json +1 -1
  90. package/runner/src/adapters/claude-api.ts +1 -1
  91. package/runner/src/adapters/claude-headless.ts +1 -1
  92. package/runner/src/adapters/claude-launch-exit.ts +26 -0
  93. package/runner/src/adapters/claude-session-probe.ts +1 -1
  94. package/runner/src/adapters/claude-tmux.ts +38 -10
  95. package/runner/src/adapters/claude.ts +28 -75
  96. package/runner/src/adapters/provider-quota-harvest.ts +20 -71
  97. package/runner/src/agent-runner/lifecycle-milestones.ts +2 -2
  98. package/runner/src/agent-runner/liveness-exchange.ts +104 -0
  99. package/runner/src/claude-system-prompt.ts +49 -0
  100. package/runner/src/launch-assembly.ts +14 -10
  101. package/runner/src/profile-home.ts +1 -1
  102. package/runner/src/project-instructions.ts +2 -2
  103. package/runner/src/provider-command.ts +18 -0
  104. package/runner/src/provider-setup.ts +3 -2
  105. package/runner/src/runner-core.ts +14 -15
  106. package/runner/src/runner-helpers.ts +0 -8
  107. package/runner/src/session-scratch.ts +6 -2
  108. package/runner/test-support/provisioning-context.ts +4 -2
  109. package/runner/test-support/runner-harness.ts +2 -1
  110. package/scripts/steward-policy-cleanup.ts +2 -2
  111. package/src/agent-authz.ts +2 -2
  112. package/src/agent-drive-arbiter.ts +3 -8
  113. package/src/agent-exit-cleanup-async.ts +2 -2
  114. package/src/agent-exit-cleanup.ts +23 -19
  115. package/src/agent-lifecycle-events.ts +112 -85
  116. package/src/agent-ref.ts +3 -2
  117. package/src/agent-status-events.ts +43 -14
  118. package/src/auth/login-link.ts +35 -0
  119. package/src/auth/password.ts +4 -3
  120. package/src/auth/session-refresh.ts +1 -1
  121. package/src/auth/session.test-fixture.ts +2 -2
  122. package/src/auth/session.ts +7 -7
  123. package/src/automations/crud.ts +8 -81
  124. package/src/automations/dispatch.ts +33 -58
  125. package/src/automations/index.ts +1 -1
  126. package/src/automations/persistence.ts +65 -0
  127. package/src/automations/precheck.ts +18 -16
  128. package/src/automations/read-async.ts +11 -0
  129. package/src/automations/reconcile.ts +30 -39
  130. package/src/automations/storage.ts +33 -10
  131. package/src/automations/write-async.ts +33 -0
  132. package/src/branch-land-notice.ts +3 -3
  133. package/src/branch-landed.ts +25 -23
  134. package/src/bus.ts +21 -19
  135. package/src/cd-deploy-notify.ts +2 -2
  136. package/src/ci/notifications.ts +4 -4
  137. package/src/ci/root-missing.ts +3 -3
  138. package/src/ci/transition-notify.ts +5 -5
  139. package/src/claude-app/oauth-http.ts +3 -3
  140. package/src/cli/index.ts +7 -1
  141. package/src/cli/init.ts +53 -0
  142. package/src/cli/orchestrator.ts +1 -7
  143. package/src/cli/setup.ts +6 -4
  144. package/src/cli/workflow.ts +12 -3
  145. package/src/commands-db.ts +4 -4
  146. package/src/commands-write.ts +8 -0
  147. package/src/compaction-watch.ts +10 -8
  148. package/src/config-store-write.ts +2 -2
  149. package/src/config.ts +4 -11
  150. package/src/connectors.ts +10 -8
  151. package/src/context-advisory.ts +22 -21
  152. package/src/db/agent-action-write.ts +36 -0
  153. package/src/db/agent-control-async.ts +9 -0
  154. package/src/db/agent-control-write.ts +49 -0
  155. package/src/db/agent-effort-observe.ts +22 -0
  156. package/src/db/agent-meta.ts +14 -3
  157. package/src/db/agents-async.ts +8 -5
  158. package/src/db/agents.ts +15 -12
  159. package/src/db/auth-identities.ts +2 -2
  160. package/src/db/automation-read-ops.ts +11 -0
  161. package/src/db/automation-write-ops.ts +46 -0
  162. package/src/db/blackboard.ts +2 -2
  163. package/src/db/browser-session-write.ts +32 -0
  164. package/src/db/bus-outbox-write-ops.ts +3 -1
  165. package/src/db/checkout-refresh-schema.ts +47 -0
  166. package/src/db/checkout-refresh.ts +5 -5
  167. package/src/db/command-agent-profile-backfill.ts +39 -0
  168. package/src/db/command-agent-profiles.ts +5 -1
  169. package/src/db/command-retention.ts +126 -0
  170. package/src/db/commands-planner-stats.test-fixture.ts +8 -0
  171. package/src/db/commands-read-ops.ts +16 -0
  172. package/src/db/connection.ts +1 -182
  173. package/src/db/context-carry-write.ts +74 -0
  174. package/src/db/continuations.ts +4 -4
  175. package/src/db/db-error-registry.ts +12 -0
  176. package/src/db/gateway.ts +26 -133
  177. package/src/db/history-retention-ops.ts +13 -0
  178. package/src/db/inbox-async.ts +2 -2
  179. package/src/db/inbox-read-ops.ts +1 -1
  180. package/src/db/inbox.ts +9 -3
  181. package/src/db/issue-associations.ts +2 -2
  182. package/src/db/issue-refs-async.ts +4 -1
  183. package/src/db/issue-refs-read-ops.ts +6 -0
  184. package/src/db/issue-refs.ts +8 -8
  185. package/src/db/kernel-event-log-schema.ts +2 -0
  186. package/src/db/land-boundaries.ts +51 -5
  187. package/src/db/land-gate-attestations.ts +2 -2
  188. package/src/db/landing-receipts.ts +2 -2
  189. package/src/db/lifecycle-context-write.ts +5 -0
  190. package/src/db/lifecycle-tail-async.ts +76 -0
  191. package/src/db/lifecycle-tail-write-ops.ts +62 -0
  192. package/src/db/lifecycle-write-window.ts +2 -1
  193. package/src/db/lineage-pair-dedupe-sql.ts +3 -3
  194. package/src/db/main-connection-mode.ts +11 -0
  195. package/src/db/main-connection-writes.ts +20 -2
  196. package/src/db/maintenance-job-runs-async.ts +2 -2
  197. package/src/db/maintenance-job-write-ops.ts +1 -1
  198. package/src/db/maintenance-pauses.ts +2 -2
  199. package/src/db/message-send.ts +4 -0
  200. package/src/db/messages.ts +31 -25
  201. package/src/db/migrations.ts +18 -1
  202. package/src/db/notification-write-ops.ts +19 -0
  203. package/src/db/operator-answer-write.ts +19 -0
  204. package/src/db/orchestrators.ts +10 -4
  205. package/src/db/pairs-async.ts +22 -1
  206. package/src/db/pairs-write-ops.ts +8 -3
  207. package/src/db/pairs.ts +41 -48
  208. package/src/db/plan-dispatch-schema.ts +5 -1
  209. package/src/db/plan-ready-notices.ts +43 -0
  210. package/src/db/plan-tools-include-migration.ts +36 -0
  211. package/src/db/plans-write-ops.ts +2 -0
  212. package/src/db/presence-buffer.ts +5 -0
  213. package/src/db/presence-loop.ts +18 -23
  214. package/src/db/presence-write.ts +0 -6
  215. package/src/db/project-entries-async.ts +14 -0
  216. package/src/db/project-entries-read-ops.ts +5 -1
  217. package/src/db/project-entries-write-ops.ts +8 -0
  218. package/src/db/project-entries.ts +15 -12
  219. package/src/db/project-journal.ts +2 -2
  220. package/src/db/project-trust-approvals.ts +2 -2
  221. package/src/db/prompt-templates.ts +4 -4
  222. package/src/db/read-op-marshaling-fixtures.ts +18 -0
  223. package/src/db/read-ops.ts +4 -0
  224. package/src/db/retention.ts +13 -2
  225. package/src/db/review-publish-write.ts +8 -0
  226. package/src/db/runtime-admin-async.ts +19 -0
  227. package/src/db/runtime-admin-write-ops.ts +36 -0
  228. package/src/db/runtime-tail-async.ts +288 -0
  229. package/src/db/runtime-tail-write-ops.ts +97 -0
  230. package/src/db/schema.ts +4 -1
  231. package/src/db/spawn-budget.ts +5 -0
  232. package/src/db/spawn-delegation.ts +3 -12
  233. package/src/db/sql-audit-indexes.ts +3 -0
  234. package/src/db/stats-async.ts +5 -3
  235. package/src/db/task-entity.ts +5 -4
  236. package/src/db/team-claim-policy.ts +60 -0
  237. package/src/db/teams-async.ts +4 -0
  238. package/src/db/teams-write-ops.ts +4 -0
  239. package/src/db/terminal-events.ts +15 -0
  240. package/src/db/timer-cutover-bodies.ts +292 -0
  241. package/src/db/timer-cutover-core.ts +37 -278
  242. package/src/db/timer-cutover-state.ts +40 -0
  243. package/src/db/timer-cutover-write-ops.ts +1 -40
  244. package/src/db/token-db-write-ops.ts +2 -0
  245. package/src/db/token-standing-async.ts +12 -0
  246. package/src/db/token-standing.ts +6 -9
  247. package/src/db/token-usage-retention.ts +33 -0
  248. package/src/db/token-usage-write-ops.ts +1 -1
  249. package/src/db/token-usage.ts +4 -1
  250. package/src/db/user-invites-async.ts +13 -0
  251. package/src/db/user-invites.ts +3 -3
  252. package/src/db/users.ts +14 -6
  253. package/src/db/workflow-execution.ts +3 -3
  254. package/src/db/workspaces.ts +8 -5
  255. package/src/db/write-ops.ts +31 -12
  256. package/src/db/writer-fault-seam.ts +2 -9
  257. package/src/db/writer-fault-test-ops.ts +18 -0
  258. package/src/db/writer-gateway.ts +42 -46
  259. package/src/dev.ts +12 -16
  260. package/src/event-loop-lag.ts +4 -2
  261. package/src/event-loop-yield.ts +2 -2
  262. package/src/events.ts +10 -8
  263. package/src/host-provider-store.ts +5 -4
  264. package/src/hub-metrics-report.ts +5 -1
  265. package/src/hub-metrics.ts +38 -18
  266. package/src/init.ts +299 -0
  267. package/src/injection-sweep-pacing.ts +6 -8
  268. package/src/invite-link.ts +16 -9
  269. package/src/land-gate-notifications.ts +11 -10
  270. package/src/land-gate-queue-progress.ts +3 -3
  271. package/src/land-settle-dispatch.ts +52 -92
  272. package/src/lifecycle-context-pressure.ts +11 -10
  273. package/src/lifecycle-manager.ts +104 -98
  274. package/src/maintenance/breaker.ts +18 -16
  275. package/src/maintenance/checkout-refresh.ts +18 -1
  276. package/src/maintenance/critical-job-watchdog.ts +3 -3
  277. package/src/maintenance/events.ts +3 -3
  278. package/src/maintenance/history-retention-job.ts +30 -0
  279. package/src/maintenance/jobs.ts +29 -67
  280. package/src/maintenance/long-running-work.ts +3 -1
  281. package/src/maintenance/offline-agent-prune-job.ts +28 -0
  282. package/src/maintenance/orphaned-sessions.ts +5 -4
  283. package/src/maintenance/pauses.ts +4 -10
  284. package/src/maintenance/plan-ready-notice-job.ts +71 -0
  285. package/src/maintenance/scheduler.ts +18 -13
  286. package/src/maintenance/stalled-delivery-pager.ts +4 -4
  287. package/src/maintenance/teams.ts +19 -30
  288. package/src/maintenance/workspaces.ts +17 -27
  289. package/src/managed-policy-escalation.ts +7 -7
  290. package/src/managed-policy.ts +3 -3
  291. package/src/managed-provider-gate.ts +5 -4
  292. package/src/managed-spawn-reservation.ts +5 -4
  293. package/src/mcp/index.ts +8 -8
  294. package/src/mcp/output-descriptions.ts +1 -1
  295. package/src/mcp/presentation.ts +2 -1
  296. package/src/mcp/runtime-output.ts +6 -1
  297. package/src/mcp/self-care-visibility.ts +2 -2
  298. package/src/mcp/spawn-targets-matrix.ts +10 -1
  299. package/src/mcp/tool-groups.ts +3 -2
  300. package/src/mcp/tool-roles.ts +81 -0
  301. package/src/mcp/tools-workspace.ts +1 -1
  302. package/src/mcp-blackboard-tools.ts +6 -5
  303. package/src/mcp-decision-tools.ts +7 -7
  304. package/src/mcp-egress-tools.ts +10 -9
  305. package/src/mcp-issue-activity-tools.ts +2 -2
  306. package/src/mcp-issue-association-tools.ts +4 -4
  307. package/src/mcp-issue-ref-tools.ts +3 -3
  308. package/src/mcp-merge-tools.ts +5 -5
  309. package/src/mcp-notification-subscription-tools.ts +14 -15
  310. package/src/mcp-output-levels.test-fixture.ts +1 -1
  311. package/src/mcp-profile-trust-tools.ts +1 -1
  312. package/src/mcp-project-journal-tools.ts +4 -12
  313. package/src/mcp-project-tools.ts +17 -18
  314. package/src/mcp-routing-policy-tools.ts +3 -2
  315. package/src/mcp-team-tools.ts +6 -6
  316. package/src/mcp-workflow-tools.ts +5 -3
  317. package/src/memory-area-injection.ts +13 -12
  318. package/src/memory-boundary-capture.ts +6 -6
  319. package/src/memory-injection.ts +45 -43
  320. package/src/merge-pause-maintenance.ts +5 -4
  321. package/src/notification-router.ts +44 -17
  322. package/src/notify.ts +5 -5
  323. package/src/observed-reset-refresh.ts +4 -4
  324. package/src/operator-alarm.ts +2 -5
  325. package/src/project-ingest.ts +6 -6
  326. package/src/project-instructions.ts +8 -1
  327. package/src/project-trust.ts +12 -11
  328. package/src/prompt-resolver.ts +3 -3
  329. package/src/provider-quota-async.ts +5 -7
  330. package/src/provider-timeline-event.ts +4 -7
  331. package/src/quota-band-delivery.ts +2 -2
  332. package/src/recipe-runner.ts +4 -3
  333. package/src/retention-config-store.ts +4 -3
  334. package/src/reviewer-pipeline.ts +11 -10
  335. package/src/routes/_route.ts +4 -4
  336. package/src/routes/_shared.ts +13 -12
  337. package/src/routes/agent-effort.ts +5 -5
  338. package/src/routes/agent-heartbeat-quota.ts +23 -0
  339. package/src/routes/agent-keep.ts +1 -1
  340. package/src/routes/agent-reporting.ts +1 -1
  341. package/src/routes/agent-self-effort.ts +5 -5
  342. package/src/routes/agent-sessions.ts +24 -24
  343. package/src/routes/agents-spawn.ts +1 -1
  344. package/src/routes/agents.ts +17 -119
  345. package/src/routes/auth.ts +44 -17
  346. package/src/routes/authority-audit.ts +2 -2
  347. package/src/routes/automations.ts +6 -5
  348. package/src/routes/channel-binding-delete.ts +1 -1
  349. package/src/routes/channel-output.ts +3 -3
  350. package/src/routes/claude-api-budget.ts +5 -5
  351. package/src/routes/commands-listing.ts +1 -1
  352. package/src/routes/commands.ts +29 -27
  353. package/src/routes/context-resets.ts +2 -2
  354. package/src/routes/coordinator-teams.ts +1 -1
  355. package/src/routes/decisions.ts +2 -2
  356. package/src/routes/host-providers.ts +18 -0
  357. package/src/routes/host-secret-files.ts +1 -1
  358. package/src/routes/hosts.ts +11 -11
  359. package/src/routes/inbox.ts +3 -2
  360. package/src/routes/index.ts +7 -3
  361. package/src/routes/integrations.ts +9 -7
  362. package/src/routes/issue-activity.ts +2 -2
  363. package/src/routes/issue-associations.ts +4 -4
  364. package/src/routes/issue-refs.ts +3 -3
  365. package/src/routes/kernel-timers-operator.ts +1 -1
  366. package/src/routes/memory.ts +1 -1
  367. package/src/routes/merges.ts +11 -11
  368. package/src/routes/messages.ts +23 -17
  369. package/src/routes/orchestrator-bootstrap.ts +3 -1
  370. package/src/routes/orchestrator-host-registration.ts +2 -0
  371. package/src/routes/orchestrator-host-utilization.ts +2 -2
  372. package/src/routes/orchestrator-proxy.ts +2 -2
  373. package/src/routes/orchestrator.ts +27 -18
  374. package/src/routes/pairs.ts +8 -8
  375. package/src/routes/project-profile-instructions.ts +1 -1
  376. package/src/routes/project-trust.ts +1 -1
  377. package/src/routes/projects.ts +16 -16
  378. package/src/routes/prompt-templates.ts +12 -12
  379. package/src/routes/provider-quotas.ts +10 -10
  380. package/src/routes/run-command.ts +1 -1
  381. package/src/routes/secrets-backup.ts +4 -5
  382. package/src/routes/secrets-import.ts +3 -4
  383. package/src/routes/secrets-vault.ts +12 -14
  384. package/src/routes/settings.ts +1 -1
  385. package/src/routes/shipping.ts +9 -1
  386. package/src/routes/spawn-policy.ts +8 -7
  387. package/src/routes/sse.ts +2 -2
  388. package/src/routes/team-templates.ts +7 -7
  389. package/src/routes/teams.ts +10 -10
  390. package/src/routes/tokens.ts +18 -17
  391. package/src/routes/users.ts +24 -24
  392. package/src/routes/viewer-read.ts +3 -3
  393. package/src/routes/web-tool-calls.ts +4 -4
  394. package/src/routes/workflows.ts +2 -2
  395. package/src/routes/workspaces.ts +17 -16
  396. package/src/routing-policy-push.ts +6 -6
  397. package/src/runtime-grant.ts +17 -11
  398. package/src/runtime-install.ts +30 -0
  399. package/src/runtime-tokens.ts +20 -28
  400. package/src/secrets-broker/config.ts +1 -1
  401. package/src/secrets-broker/service.ts +2 -2
  402. package/src/security.ts +3 -1
  403. package/src/self-resume-carry.ts +21 -110
  404. package/src/self-resume-supersede.ts +4 -3
  405. package/src/self-resume.ts +54 -66
  406. package/src/server-background.ts +1 -1
  407. package/src/server.ts +25 -26
  408. package/src/services/agent-action.ts +12 -31
  409. package/src/services/agent-effort.ts +7 -32
  410. package/src/services/agent-hang-watchdog-job.ts +2 -2
  411. package/src/services/agent-heartbeat.ts +166 -0
  412. package/src/services/agent-reporting.ts +1 -1
  413. package/src/services/auth-context.ts +6 -0
  414. package/src/services/browser-inventory.ts +3 -3
  415. package/src/services/browser-session-state.ts +3 -2
  416. package/src/services/browser-session.ts +21 -27
  417. package/src/services/bus-command-update.ts +9 -9
  418. package/src/services/checkout-refresh-state.ts +1 -0
  419. package/src/services/checkout-refresh.test-fixture.ts +3 -2
  420. package/src/services/command-host.ts +7 -2
  421. package/src/services/coordinator-digest.ts +3 -2
  422. package/src/services/dispatch-command.ts +12 -13
  423. package/src/services/effective-launch-driver.ts +14 -9
  424. package/src/services/host-changed-paths.test-fixture.ts +5 -6
  425. package/src/services/host-project-readiness.ts +2 -2
  426. package/src/services/host-providers.ts +1 -1
  427. package/src/services/host-utilization.ts +9 -9
  428. package/src/services/idle-agent-digest.ts +17 -12
  429. package/src/services/idle-epics.ts +4 -4
  430. package/src/services/interrupt-agent.ts +12 -9
  431. package/src/services/issue-activity.ts +3 -3
  432. package/src/services/issue-associations.ts +15 -18
  433. package/src/services/issue-lifecycle-comments.ts +3 -2
  434. package/src/services/issue-lifecycle.ts +14 -13
  435. package/src/services/issue-refs.ts +4 -5
  436. package/src/services/kernel-timers-cutover-chaos-worker.ts +1 -1
  437. package/src/services/kernel-timers-ingress-chaos-worker.ts +6 -1
  438. package/src/services/kernel-timers-ingress.ts +3 -3
  439. package/src/services/kernel-timers-message-authority-chaos-worker.ts +3 -10
  440. package/src/services/kernel-timers-operator-chaos-worker.ts +3 -2
  441. package/src/services/kernel-timers-outbox.ts +1 -1
  442. package/src/services/kernel-timers-stage10-operator.ts +1 -1
  443. package/src/services/kernel-timers.ts +4 -3
  444. package/src/services/land-gate-placement.ts +11 -2
  445. package/src/services/land-issue-relations.ts +5 -4
  446. package/src/services/land-restart-retry.ts +7 -6
  447. package/src/services/landed-ancestry.ts +6 -5
  448. package/src/services/legacy-landing-host.ts +4 -1
  449. package/src/services/legacy-landing-recovery.ts +8 -6
  450. package/src/services/managed-running.ts +17 -17
  451. package/src/services/memory-areas.ts +3 -3
  452. package/src/services/merge-pause.ts +9 -15
  453. package/src/services/operator-decisions.ts +37 -41
  454. package/src/services/orchestrator-registration-recovery.ts +6 -2
  455. package/src/services/orchestrator-upgrade.ts +14 -12
  456. package/src/services/permission-decision.ts +4 -3
  457. package/src/services/plan-ci-notice.ts +1 -1
  458. package/src/services/plan-conformance.ts +4 -4
  459. package/src/services/plan-dispatch-policy.ts +10 -3
  460. package/src/services/plan-dispatch.ts +35 -14
  461. package/src/services/plan-graph.ts +39 -261
  462. package/src/services/plan-import.ts +1 -1
  463. package/src/services/plan-live-bindings.ts +8 -37
  464. package/src/services/plan-task-create.ts +1 -1
  465. package/src/services/plan-terminal-refs.ts +2 -12
  466. package/src/services/plan-wake-digest.ts +8 -3
  467. package/src/services/profile-trust.ts +2 -2
  468. package/src/services/project.ts +11 -10
  469. package/src/services/prompt-templates.ts +6 -5
  470. package/src/services/provider-api-key.ts +73 -0
  471. package/src/services/provider-hold-nudge.ts +9 -9
  472. package/src/services/provider-hold-record.ts +13 -12
  473. package/src/services/provider-state-audit.ts +19 -18
  474. package/src/services/provisioning-harness/driver.ts +1 -1
  475. package/src/services/provisioning-harness/fixture-matrix.ts +3 -3
  476. package/src/services/provisioning-harness/lifecycle.ts +24 -22
  477. package/src/services/provisioning-harness/prepare.ts +16 -17
  478. package/src/services/rate-limit-resume.ts +10 -9
  479. package/src/services/red-main-auto-revert.ts +7 -5
  480. package/src/services/red-main-controller-deps.ts +20 -3
  481. package/src/services/red-main-incident.ts +3 -1
  482. package/src/services/red-main-quarantine.ts +2 -3
  483. package/src/services/register-agent.ts +22 -22
  484. package/src/services/restart-project-role.ts +1 -1
  485. package/src/services/restart-spawn.ts +17 -16
  486. package/src/services/review-publish.ts +7 -24
  487. package/src/services/review-ref-reconcile.ts +29 -38
  488. package/src/services/runtime-dependency-alert.ts +27 -0
  489. package/src/services/scheduler-command.ts +11 -9
  490. package/src/services/scheduler.ts +5 -5
  491. package/src/services/self-effort-grant.ts +5 -25
  492. package/src/services/send-message.ts +16 -33
  493. package/src/services/shutdown-agent.ts +17 -14
  494. package/src/services/spawn-agent.ts +12 -41
  495. package/src/services/spawn-chain-inspector.ts +1 -1
  496. package/src/services/spawn-cwd-placement.ts +21 -5
  497. package/src/services/spawn-issue-activity.ts +8 -6
  498. package/src/services/spawn-launch.ts +17 -1
  499. package/src/services/spawn-loss-escalation.ts +1 -1
  500. package/src/services/spawn-registration-watchdog.ts +2 -2
  501. package/src/services/spawn-repo-probe.ts +7 -5
  502. package/src/services/spawn-tree-cleanup.ts +7 -8
  503. package/src/services/steward-reaper.ts +4 -4
  504. package/src/services/task-context-hydration.ts +25 -1
  505. package/src/services/task-delivery.ts +20 -34
  506. package/src/services/task-entity.ts +40 -203
  507. package/src/services/task-issue-link.ts +13 -20
  508. package/src/services/task-issue-weave.ts +12 -11
  509. package/src/services/task-lifecycle.ts +27 -31
  510. package/src/services/task-repo-cwd.ts +37 -0
  511. package/src/services/task-review-hold.ts +4 -17
  512. package/src/services/task-semantic-events.ts +13 -11
  513. package/src/services/task-state-reconcile.ts +3 -4
  514. package/src/services/task-validation.ts +2 -2
  515. package/src/services/team-templates.ts +5 -5
  516. package/src/services/team.ts +31 -98
  517. package/src/services/terminal-provider-exit.ts +6 -5
  518. package/src/services/timer-message-fire-chaos-worker.ts +7 -3
  519. package/src/services/timer-message-fire-outbox.ts +1 -1
  520. package/src/services/transient-agent-reaper.ts +22 -19
  521. package/src/services/turn-reconcile-audit.ts +9 -9
  522. package/src/services/user-onboarding.ts +8 -6
  523. package/src/services/user-profile.ts +6 -9
  524. package/src/services/work-finality.ts +16 -4
  525. package/src/services/workflow-auto-start.ts +2 -1
  526. package/src/services/workflow-caller.ts +61 -4
  527. package/src/services/workflow-child-proof-worker.ts +1 -1
  528. package/src/services/workflow-control-proof-worker.ts +1 -1
  529. package/src/services/workflow-coordinator.ts +8 -2
  530. package/src/services/workflow-decisions.ts +5 -5
  531. package/src/services/workflow-deferred-cleanup.ts +1 -1
  532. package/src/services/workflow-effect-driver.ts +42 -19
  533. package/src/services/workflow-effects.ts +41 -27
  534. package/src/services/workflow-pins.ts +7 -4
  535. package/src/services/workflow-reconcile.ts +1 -0
  536. package/src/services/workflow-resume-pins.ts +3 -3
  537. package/src/services/workflow-routing-defaults.ts +18 -0
  538. package/src/services/workflow-run-view.ts +4 -3
  539. package/src/services/workflow-run.test-fixture.ts +1 -1
  540. package/src/services/workflow-runs.ts +34 -22
  541. package/src/services/workflow-supervisor-state.ts +21 -1
  542. package/src/services/workflow-supervisor.ts +4 -3
  543. package/src/services/workspace-recovery.ts +4 -3
  544. package/src/setup.ts +47 -8
  545. package/src/spawn-admission.ts +10 -2
  546. package/src/spawn-placement.ts +27 -9
  547. package/src/spawn-targets.ts +8 -8
  548. package/src/sse-agent-status.ts +15 -6
  549. package/src/sse.ts +49 -24
  550. package/src/startup-context-injection.ts +61 -57
  551. package/src/steward-handoff.ts +4 -3
  552. package/src/steward-policy-cleanup.ts +9 -8
  553. package/src/steward.ts +2 -2
  554. package/src/task-dispatch-live.ts +5 -2
  555. package/src/task-dispatcher.ts +2 -2
  556. package/src/token-db.ts +2 -2
  557. package/src/token-usage-async.ts +2 -4
  558. package/src/user-awaiting-reply.ts +5 -5
  559. package/src/utils.ts +7 -0
  560. package/src/workspace-actions.ts +24 -29
  561. package/src/workspace-auto-merge.ts +14 -12
  562. package/src/workspace-changed-paths-client.ts +16 -5
  563. package/src/workspace-cleanup-stale.ts +30 -7
  564. package/src/workspace-command-settle.ts +24 -16
  565. package/src/workspace-config.ts +1 -1
  566. package/src/workspace-conflict-resolver.ts +9 -7
  567. package/src/workspace-dead-owner-recovery.ts +5 -4
  568. package/src/workspace-escalation.ts +12 -11
  569. package/src/workspace-human-escalation.ts +3 -3
  570. package/src/workspace-land-gate-watchdog.ts +3 -3
  571. package/src/workspace-land-refusal.ts +20 -0
  572. package/src/workspace-land-stopped.ts +1 -0
  573. package/src/workspace-merge.ts +10 -26
  574. package/src/workspace-nothing-to-land-notice.ts +2 -2
  575. package/src/workspace-orphans.ts +18 -37
  576. package/src/workspace-pr-completion.ts +10 -8
  577. package/src/workspace-rekey.ts +3 -3
  578. package/src/workspace-steward-failure.ts +2 -2
  579. package/src/workspace-steward-wake.ts +2 -2
  580. package/public/assets/agent-liveness-CaNwK0Zf.js +0 -2
  581. package/public/assets/overview-C1DCTzzV.js +0 -2
  582. package/public/assets/provider-display-DsuWMvVL.js +0 -2
  583. package/public/assets/run-card-CpKqRbhg.js +0 -2
  584. package/public/assets/shipping-B9YtnwtG.js +0 -2
  585. package/public/assets/store-DcClXLH0.js +0 -9
  586. package/runner/src/agent-runner/http-liveness.ts +0 -85
  587. package/src/db/on-loop-write-transaction.ts +0 -34
package/src/db/gateway.ts CHANGED
@@ -37,34 +37,12 @@
37
37
  // inherits the phantom-failure guarantee ("a write may be committed even when reported as failed";
38
38
  // reconcile via the key, never blind-retry) for free by routing through this surface.
39
39
  //
40
- // TWO BACKENDS behind one interface (§3.8):
41
- // - in-process (the Phase-0 DEFAULT, §5/§7): every op runs synchronously against the ambient main
42
- // connection (`getDb()`), wrapped in a resolved Promise. Behaviorally identical to today's sync
43
- // path, so this whole module SHIPS GREEN with ZERO callsite moves. Under `bun test` the in-process
44
- // backend still round-trips args/results/errors through the SAME marshaling path as the worker
45
- // (H1 §3.8.1), so the default suite fails exactly where production would.
46
- // - worker-backed (a file DB, gated on explicitly, §7 Phase 1/2): writes to the size-1 writer pool,
47
- // reads to the reader pool. Off the loop; proven by the file-backed integration suite. Production
48
- // rollout flips per-domain in S3 (§11.5) — this module does NOT turn it on at bootstrap.
49
- //
50
- // THE TWO BACKENDS ARE SELECTED PER HALF (#1960 T1). `initGateway` takes `readerBackend` / `writerBackend`
51
- // independently (with `backend` kept as the both-halves shorthand); BOTH default to in-process, so this
52
- // change is behavior-preserving by construction. The split exists because the halves are different risk
53
- // classes, and coupling them is what blocked the rollout:
54
- // - READS are safe to offload. Under WAL a reader takes no write lock, so a worker reader cannot block
55
- // or be blocked by the writer, and no main-thread state changes. This is ADR §7 Phase 1 verbatim
56
- // ("Route reader ops through the reader pool in production; keep writes in-process on the loop
57
- // initially") — and it accounts for ~55% of measured on-loop block-ms on prod.
58
- // - WRITES are not. A worker WRITER owns the sole RW connection, so its bootstrap calls `closeDb()`
59
- // and every surviving main-thread `getDb()` callsite — ~1380 of them, `/health` included — starts
60
- // throwing. That is the S3 burn-down (#1870), not a config flip.
61
- // So a reader-only flip must leave the writer half COMPLETELY untouched: same in-process writer, same
62
- // live ambient connection, `closeDb()` never called by this module. Everything keyed off "is the main RW
63
- // connection still ours?" (`gatewayBackend()`, the writer fault seam, the writer self-heal path) is
64
- // therefore keyed off the WRITER half specifically, never off "either half is a worker".
40
+ // File databases always use the writer thread (#1870 S8). The main connection remains available
41
+ // for reads and boot migrations; the in-process writer is only for :memory:. Reader placement is
42
+ // independent and still controlled by the reader backend option.
65
43
 
66
44
  import { errMessage } from "@humwick/sdk";
67
- import { getDbPath } from "./connection.ts";
45
+ import { getDbGeneration, getDbPath } from "./connection.ts";
68
46
  // Op-timing capture source (#1882 / ADR §5). One-way dependency — loop-block-attribution imports
69
47
  // event-loop-lag + config only, never the gateway/writer stack, so this closes no cycle.
70
48
  import { withLoopFrameCapture } from "../loop-block-attribution.ts";
@@ -237,74 +215,38 @@ export interface DbGatewayStats {
237
215
  }
238
216
 
239
217
  export interface InitGatewayOptions {
240
- /** DB path; defaults to the live `getDbPath()`. Only consulted when a half runs on a worker. */
218
+ /** Defaults to the live getDbPath(). File databases default both pools to workers. */
241
219
  dbPath?: string;
242
- /**
243
- * Shorthand that sets BOTH halves at once. Defaults to `"in-process"` — the Phase-0 no-op that runs
244
- * every op synchronously against the ambient main connection (so bootstrap spawns NO worker threads
245
- * and behavior is unchanged). `"worker"` requires a file DB and stands up the writer + reader pools;
246
- * it is used by the integration suite and by the per-domain S3 rollout, never at Phase-0 bootstrap.
247
- *
248
- * `readerBackend` / `writerBackend` override this per half — see them for the split rationale.
249
- */
220
+ /** Shorthand for reader placement; file writes always run on the worker. */
250
221
  backend?: GatewayBackend;
251
- /**
252
- * The READ path's backend, overriding `backend`. Defaults to `backend ?? "in-process"`.
253
- *
254
- * THE POINT OF THE SPLIT (#1960 T1 / ADR §7 Phase 1). Reads are the safe half to offload: under WAL a
255
- * reader takes no write lock and cannot block or be blocked by the writer, so a worker-backed reader
256
- * changes NOTHING about write behavior. The writer half is a different risk class entirely — the
257
- * worker writer owns the sole RW connection, so its bootstrap calls `closeDb()` and every surviving
258
- * main-thread `getDb()` callsite (incl. `/health`) starts throwing. Keeping the writer in-process
259
- * while the reader moves off-loop is therefore the only landable first step, and before this split it
260
- * was not even expressible: one `backend` flag flipped both halves together.
261
- */
262
222
  readerBackend?: GatewayBackend;
263
- /**
264
- * The WRITE path's backend, overriding `backend`. Defaults to `backend ?? "in-process"`.
265
- *
266
- * CAUTION: a worker writer takes ownership of the sole RW connection — its callers are expected to
267
- * `closeDb()` first (see the module header and `initWriter`). Leave this `"in-process"` unless you
268
- * are deliberately doing that; a reader-only flip must NOT touch it.
269
- */
223
+ /** Legacy preference; a file database always resolves to worker. */
270
224
  writerBackend?: GatewayBackend;
271
- /** Writer-pool tuning (queue high-water, hard cap, writer-job deadline) — see `InitWriterOptions`. */
272
225
  writer?: Omit<InitWriterOptions, "path">;
273
- /** Reader-pool tuning (size, queue high-water, per-job timeout). */
274
226
  reader?: { size?: number; queueHighWater?: number; timeoutMs?: number };
275
227
  }
276
228
 
277
- /** The resolved per-half backend selection — what `initGateway` actually stands up. */
278
229
  export interface ResolvedGatewayBackends {
279
230
  reader: GatewayBackend;
280
231
  writer: GatewayBackend;
281
232
  }
282
233
 
283
- /**
284
- * Resolve the per-half backends from the options: the specific `readerBackend`/`writerBackend` wins,
285
- * then the `backend` shorthand, then the in-process default. Pure, so the selection matrix is testable
286
- * without standing up pools or spawning threads (mirrors `resolveReaderBackend` in reader-pool.ts).
287
- */
288
234
  export function resolveGatewayBackends(options: InitGatewayOptions = {}): ResolvedGatewayBackends {
289
- const both = options.backend ?? "in-process";
290
- return { reader: options.readerBackend ?? both, writer: options.writerBackend ?? both };
235
+ const path = options.dbPath ?? getDbPath();
236
+ return {
237
+ reader: options.readerBackend ?? options.backend ?? (path && path !== ":memory:" ? "worker" : "in-process"),
238
+ writer: path && path !== ":memory:" ? "worker" : options.writerBackend ?? options.backend ?? "in-process",
239
+ };
291
240
  }
292
241
 
293
242
  // ── Backend state ───────────────────────────────────────────────────────────────────────────────
294
243
 
295
244
  let reader: ReaderGateway | undefined;
296
- // The two halves are tracked SEPARATELY (#1960 T1). Both default to in-process, so a cold/plain
297
- // bootstrap is byte-for-byte the pre-split behavior.
298
245
  let currentReaderBackend: GatewayBackend = "in-process";
299
246
  let currentWriterBackend: GatewayBackend = "in-process";
300
- // The file path a WORKER WRITER was stood up against, RETAINED here so a writer-only re-init
301
- // (ensureInit self-heal after a lone shutdownWriter) can reconstruct the worker writer WITHOUT
302
- // depending on `getDbPath()` — worker-WRITER bootstrap intentionally calls `closeDb()` (the worker owns
303
- // the sole RW connection), which clears `getDbPath()`, so relying on it would silently re-init the
304
- // writer in-process against a torn-down main handle (HIGH-1, codex-terra L1 review). Deliberately
305
- // tracks the WRITER only: a worker READER never closes the main handle, so an in-process writer under a
306
- // worker reader must still self-heal to `":memory:"` (= the ambient `getDb()`), never to a file path.
247
+ // Retained for callers that release their bootstrap handle after initializing the gateway.
307
248
  let writerWorkerDbPath: string | undefined;
249
+ let gatewayDbGeneration = -1;
308
250
 
309
251
  function replaceReader(next: ReaderGateway): void {
310
252
  const previous = reader;
@@ -314,19 +256,7 @@ function replaceReader(next: ReaderGateway): void {
314
256
  if (previous) void previous.destroy().catch((error) => console.error(`[gateway] reader teardown failed: ${errMessage(error)}`));
315
257
  }
316
258
 
317
- /**
318
- * Stand up the unified gateway. Idempotent-friendly: re-calling it replaces the backend (tearing the
319
- * old one down). Chooses in-process for BOTH halves by default — the Phase-0 no-op — so a plain
320
- * `getGateway()` never spawns worker threads. Pass `{ backend: "worker" }` (file DB) to route both
321
- * families through the real pools, or `{ readerBackend: "worker" }` alone for the Phase-R shape:
322
- * reads off the loop, writes still on the ambient main connection.
323
- *
324
- * THE TWO HALVES ARE STOOD UP INDEPENDENTLY and neither reaches into the other's state. In particular
325
- * this function NEVER touches the main connection: `closeDb()` is the CALLER's step, required only for
326
- * a worker WRITER (which then owns the sole RW connection). So `{ readerBackend: "worker" }` leaves the
327
- * writer exactly as a default init leaves it — in-process, running op bodies against the live ambient
328
- * `getDb()` — and the ~1380 raw-handle callsites (incl. `/health`) keep working untouched.
329
- */
259
+ /** Select reader placement independently; file writes always use one FIFO and one worker. */
330
260
  export function initGateway(options: InitGatewayOptions = {}): void {
331
261
  const { reader: readerB, writer: writerB } = resolveGatewayBackends(options);
332
262
  const dbPath = options.dbPath ?? getDbPath();
@@ -338,17 +268,8 @@ export function initGateway(options: InitGatewayOptions = {}): void {
338
268
  `requested worker half(s): ${halves}`,
339
269
  );
340
270
  }
341
- // ── WRITER half ─────────────────────────────────────────────────────────────────────────────────
342
- // `initWriter` picks its backend from the path: a file → the worker pool, `":memory:"` → in-process.
343
- // The in-process writer holds no connection of its own and runs the op against the ambient `getDb()`
344
- // (the real main handle, file or memory) — which is why an in-process writer is passed `":memory:"`
345
- // even when the process is on a file DB, and why it is unaffected by a worker-backed reader.
346
- initWriter({ ...options.writer, path: writerB === "worker" ? (dbPath as string) : ":memory:" });
347
- // RETAIN for writer-only self-heal (HIGH-1) — getDbPath() is cleared by a worker writer's closeDb().
348
- writerWorkerDbPath = writerB === "worker" ? (dbPath as string) : undefined;
349
- // ── READER half ─────────────────────────────────────────────────────────────────────────────────
350
- // Force the backend rather than letting it fall out of the path, so a file-DB server in Phase 0 still
351
- // runs every read synchronously on the main connection (no worker spawned, no callsite moved).
271
+ initWriter({ ...options.writer, path: writerB === "worker" ? dbPath : ":memory:" });
272
+ writerWorkerDbPath = writerB === "worker" ? dbPath : undefined;
352
273
  replaceReader(
353
274
  readerB === "worker"
354
275
  ? createReaderGateway({
@@ -362,6 +283,7 @@ export function initGateway(options: InitGatewayOptions = {}): void {
362
283
  );
363
284
  currentReaderBackend = readerB;
364
285
  currentWriterBackend = writerB;
286
+ gatewayDbGeneration = getDbGeneration();
365
287
  // An in-transaction crash seam is a main-thread closure; once op bodies run on the WRITER thread it
366
288
  // can never be delivered, so arming one must FAIL rather than silently inject nothing (L-C #1899).
367
289
  // Keyed on the WRITER half only — the seam is armed inside write-op bodies, so a worker reader leaves
@@ -369,7 +291,7 @@ export function initGateway(options: InitGatewayOptions = {}): void {
369
291
  setWriterFaultsDeliverable(writerB === "in-process");
370
292
  }
371
293
 
372
- /** Tear the gateway down (both pools). After this, the next `getGateway()` lazily re-inits in-process. */
294
+ /** Tear the gateway down (both pools). The next getGateway() selects placement from the current database. */
373
295
  export async function shutdownGateway(): Promise<void> {
374
296
  const previousReader = reader;
375
297
  reader = undefined;
@@ -381,17 +303,7 @@ export async function shutdownGateway(): Promise<void> {
381
303
  await previousReader?.destroy();
382
304
  }
383
305
 
384
- /**
385
- * Tear down JUST the reader half — terminates any worker-pool threads and replaces them with a fresh
386
- * in-process reader. The writer is left COMPLETELY untouched (#1960 T2 server teardown).
387
- *
388
- * Deliberately NOT `shutdownGateway()`: that also calls `shutdownWriter()`, which unconditionally
389
- * REJECTS every write still queued at the writer (writer-gateway.ts) — a needless side effect on a
390
- * clean stop, since Phase-R never puts the writer on a worker (it stays in-process always). This is
391
- * the shutdown counterpart the design pass calls for (§1.5): "worker threads must be torn down on
392
- * shutdown or a restart can leave orphaned threads holding WAL read marks." Safe to call even when the
393
- * reader was never worker-backed — the in-process reader's `destroy()` resolves immediately.
394
- */
306
+ /** Release reader workers without rejecting the writer FIFO during graceful shutdown. */
395
307
  export async function shutdownGatewayReader(): Promise<void> {
396
308
  const previous = reader;
397
309
  reader = createReaderGateway({ backend: "in-process" });
@@ -404,16 +316,7 @@ export function isGatewayInitialized(): boolean {
404
316
  return reader !== undefined;
405
317
  }
406
318
 
407
- /**
408
- * The live WRITER backend. Domains whose post-commit main-thread work is not yet worker-safe (e.g.
409
- * getDb-backed effect delivery) read this to refuse rather than commit-then-silently-drop.
410
- *
411
- * DELIBERATELY THE WRITER HALF, not "either half" (#1960 T1). Every caller is really asking "is the
412
- * main RW connection still ours?" — `events.ts`'s keyless-append guard and `managed-policy.ts`'s
413
- * worker-safe builder both branch on that, and it is the WRITER flip that surrenders the connection.
414
- * A worker-backed READER changes nothing for them, so they must not start refusing when reads move off
415
- * the loop. Use `readerBackend()` for the read half.
416
- */
319
+ /** The live writer placement, retained as the historical backend alias. */
417
320
  export function gatewayBackend(): GatewayBackend {
418
321
  return currentWriterBackend;
419
322
  }
@@ -429,23 +332,13 @@ export function writerBackend(): GatewayBackend {
429
332
  }
430
333
 
431
334
  function ensureInit(): void {
432
- if (reader === undefined) {
433
- // Cold gateway: stand BOTH halves up (in-process by default).
335
+ if (reader === undefined || (getDbPath() !== undefined && gatewayDbGeneration !== getDbGeneration())) {
336
+ // A replaced database owns new pools; never send its writes to the previous file (#1870 S8).
434
337
  initGateway();
435
338
  return;
436
339
  }
437
- // The reader and writer are normally stood up AND torn down together by
438
- // initGateway()/shutdownGateway(), but the writer CAN be torn down on its own (`shutdownWriter()` —
439
- // used by the writer suite's afterEach and reachable directly), leaving `reader` defined while the
440
- // writer backend is undefined. A reader-only sentinel then skips re-init and the next write hits
441
- // `requireBackend()` → "writer gateway not initialized" — the failure L1 (#1875) surfaced once feature
442
- // writes began routing through `getGateway().write/coalesce(...)`. Restore JUST the writer, matching
443
- // the live backend, so a lone shutdownWriter() self-heals WITHOUT disturbing the reader (never
444
- // downgrading a worker-backed reader to in-process).
340
+ // A lone writer teardown preserves reader placement. Rebuild only that writer.
445
341
  if (!isWriterInitialized()) {
446
- // Reconstruct the writer against the RETAINED WRITER worker path (never getDbPath(), which closeDb()
447
- // clears at worker-writer bootstrap — HIGH-1). For in-process, ":memory:" selects the in-process
448
- // writer. Keyed on the WRITER half so a worker READER never drags the writer onto a worker.
449
342
  initWriter({ path: currentWriterBackend === "worker" ? writerWorkerDbPath : ":memory:" });
450
343
  }
451
344
  }
@@ -503,8 +396,8 @@ const GATEWAY: DbGateway = {
503
396
  };
504
397
 
505
398
  /**
506
- * The process-wide DB gateway — the sole sanctioned DB entry point (ADR §3.3). Lazily stands up the
507
- * in-process backend on first use if `initGateway()` was not called explicitly, so a caller never sees
399
+ * The process-wide DB gateway — the sole sanctioned DB entry point (ADR §3.3). Lazily selects pools for the
400
+ * current database on first use if `initGateway()` was not called explicitly, so a caller never sees
508
401
  * an uninitialized gateway. The returned facade is stable across `initGateway()` re-inits.
509
402
  */
510
403
  export function getGateway(): DbGateway {
@@ -0,0 +1,13 @@
1
+ import { pruneKernelReplayResults } from "@humwick/kernel/sqlite-kernel-persistence";
2
+ import { getDb } from "./connection";
3
+ import { pruneTerminalCommands } from "./command-retention";
4
+ import { pruneTokenUsage } from "./token-usage-retention";
5
+ import type { WriterOpSpec } from "./write-ops";
6
+
7
+ // One gateway call is one small transaction; never drain a backlog inside the writer job (#3619).
8
+ const BATCH = 25;
9
+ export const HISTORY_RETENTION_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = {
10
+ "historyRetention.kernel": { offLoop: true, idempotent: true, fn: (_args, ctx) => pruneKernelReplayResults(getDb(), ctx.now, BATCH) },
11
+ "historyRetention.tokens": { offLoop: true, idempotent: true, fn: (_args, ctx) => pruneTokenUsage(ctx.now - 90 * 24 * 60 * 60_000, BATCH) },
12
+ "historyRetention.commands": { offLoop: true, idempotent: true, fn: (_args, ctx) => pruneTerminalCommands(ctx.now - 30 * 24 * 60 * 60_000, 1_000, ctx.now - 60 * 60_000) },
13
+ };
@@ -9,8 +9,8 @@ import type {
9
9
  setInboxThreadState,
10
10
  } from "./inbox.ts";
11
11
 
12
- export function getInboxStateAsync(operatorId: string): Promise<ReturnType<typeof getInboxState>> {
13
- return getGateway().read("inbox.state", { operatorId }) as unknown as Promise<ReturnType<typeof getInboxState>>;
12
+ export function getInboxStateAsync(operatorId: string, options: { excludeOffline?: boolean } = {}): Promise<ReturnType<typeof getInboxState>> {
13
+ return getGateway().read("inbox.state", { operatorId, ...(options.excludeOffline ? { excludeOffline: true } : {}) }) as unknown as Promise<ReturnType<typeof getInboxState>>;
14
14
  }
15
15
  export function listChatHistoryImportsAsync(input: Parameters<typeof listChatHistoryImports>[0] = {}): Promise<ReturnType<typeof listChatHistoryImports>> {
16
16
  return getGateway().read("inbox.historyImports", input) as unknown as Promise<ReturnType<typeof listChatHistoryImports>>;
@@ -3,6 +3,6 @@
3
3
  import { getInboxState, listChatHistoryImports } from "./inbox.ts";
4
4
 
5
5
  export const INBOX_READ_OPS = {
6
- "inbox.state": (args: { operatorId: string }) => getInboxState(args.operatorId),
6
+ "inbox.state": (args: { operatorId: string; excludeOffline?: boolean }) => getInboxState(args.operatorId, { excludeOffline: args.excludeOffline }),
7
7
  "inbox.historyImports": (args: Parameters<typeof listChatHistoryImports>[0]) => listChatHistoryImports(args),
8
8
  };
package/src/db/inbox.ts CHANGED
@@ -10,12 +10,18 @@ import type {
10
10
  InboxThreadState,
11
11
  } from "../types";
12
12
 
13
- export function getInboxState(operatorId: string): InboxState {
13
+ /**
14
+ * #2410 — `excludeOffline` (opt-in, the #2396 contract) keeps only peers whose agent is registered
15
+ * and not offline: the dashboard's "Show offline" switch hides every other thread, and the table
16
+ * accrues a row per agent id ever chatted with, so the full read is mostly long-dead peers.
17
+ */
18
+ export function getInboxState(operatorId: string, options: { excludeOffline?: boolean } = {}): InboxState {
19
+ const live = options.excludeOffline ? " AND peer_id IN (SELECT id FROM agents WHERE status <> 'offline')" : "";
14
20
  const threads = (getDb().query(
15
- "SELECT * FROM inbox_thread_state WHERE operator_id = ? ORDER BY updated_at DESC",
21
+ `SELECT * FROM inbox_thread_state WHERE operator_id = ?${live} ORDER BY updated_at DESC`,
16
22
  ).all(operatorId) as any[]).map(rowToInboxThreadState);
17
23
  const drafts = (getDb().query(
18
- "SELECT * FROM inbox_drafts WHERE operator_id = ? ORDER BY updated_at DESC",
24
+ `SELECT * FROM inbox_drafts WHERE operator_id = ?${live} ORDER BY updated_at DESC`,
19
25
  ).all(operatorId) as any[]).map(rowToInboxDraft);
20
26
  return { operatorId, threads, drafts };
21
27
  }
@@ -40,13 +40,13 @@ function cleanText(value: string | undefined, field: string, max: number): strin
40
40
  return cleaned;
41
41
  }
42
42
 
43
- export function associateIssue(issueRefId: string, entityType: IssueAssociationEntityType, entityId: string, relation?: IssueRefRelation): IssueAssociation {
43
+ export function associateIssue(issueRefId: string, entityType: IssueAssociationEntityType, entityId: string, relation?: IssueRefRelation, submittedAt: number = Date.now()): IssueAssociation {
44
44
  const cleanedIssueRefId = cleanText(issueRefId, "issueRefId", 120);
45
45
  if (!getIssueRef(cleanedIssueRefId)) throw new ValidationError(`issue ref ${cleanedIssueRefId} not found`);
46
46
  const cleanedEntityType = cleanEntityType(entityType);
47
47
  const cleanedEntityId = cleanText(entityId, "entityId", 240);
48
48
  const cleanedRelation = optionalEnum(relation, "relation", ISSUE_REF_RELATIONS);
49
- const now = Date.now();
49
+ const now = submittedAt;
50
50
  getDb().query(`
51
51
  INSERT INTO issue_associations (issue_ref_id, entity_type, entity_id, created_at, relation)
52
52
  VALUES (?, ?, ?, ?, ?)
@@ -3,11 +3,14 @@ import { randomUUID } from "node:crypto";
3
3
  import { getGateway } from "./gateway.ts";
4
4
  import type { IssueRef } from "../types";
5
5
  import type { IssueTrackerIssueSummary } from "../issue-tracker/adapter";
6
- import type { ResolveIssueRefByExternalKeyInput, ResolveIssueRefFromStringInput, UpdateIssueRefInput, UpsertIssueRefInput } from "./issue-refs.ts";
6
+ import type { ListIssueRefsOptions, ResolveIssueRefByExternalKeyInput, ResolveIssueRefFromStringInput, UpdateIssueRefInput, UpsertIssueRefInput } from "./issue-refs.ts";
7
7
  import type { IssueLifecycleActionRecord, UpsertIssueLifecycleActionInput } from "./issue-lifecycle.ts";
8
8
 
9
9
  const write = <T>(op: string, args: unknown, opts?: { idempotencyKey?: string }) => getGateway().write(op, args as never, opts) as unknown as Promise<T>;
10
10
 
11
+ const read = <T>(op: string, args: unknown = {}) => getGateway().read(op as never, args as never) as unknown as Promise<T>;
12
+
13
+ export const listIssueRefsAsync = (opts: ListIssueRefsOptions = {}) => read<IssueRef[]>("issueRefs.list", opts);
11
14
  export const upsertIssueRefAsync = (input: UpsertIssueRefInput) => write<IssueRef>("issueRefs.upsert", input);
12
15
  export const resolveIssueRefByExternalKeyAsync = (input: ResolveIssueRefByExternalKeyInput) => write<IssueRef>("issueRefs.resolveExternalKey", input);
13
16
  export const resolveIssueRefFromStringAsync = (input: ResolveIssueRefFromStringInput) => write<IssueRef>("issueRefs.resolveFromString", input);
@@ -0,0 +1,6 @@
1
+ // #3799 — the issue-ref listing on the reader pool (it ran as a cold main-thread scan, 10 s on swap-bound I/O).
2
+ import { listIssueRefs, type ListIssueRefsOptions } from "./issue-refs.ts";
3
+
4
+ export const ISSUE_REFS_READ_OPS = {
5
+ "issueRefs.list": (args: ListIssueRefsOptions) => listIssueRefs(args),
6
+ };
@@ -252,7 +252,8 @@ export function resolveIssueRefFromString(input: ResolveIssueRefFromStringInput,
252
252
  }, now);
253
253
  }
254
254
 
255
- export function listIssueRefs(opts: ListIssueRefsOptions = {}): IssueRef[] {
255
+ /** Listing SQL, exported so the query-plan gate pins the production statement (#3799). */
256
+ export function buildListIssueRefsQuery(opts: ListIssueRefsOptions = {}): { sql: string; params: Array<string | number> } {
256
257
  const conditions: string[] = [];
257
258
  const params: Array<string | number> = [];
258
259
  if (opts.provider) {
@@ -271,13 +272,12 @@ export function listIssueRefs(opts: ListIssueRefsOptions = {}): IssueRef[] {
271
272
  if (!Number.isSafeInteger(limit) || limit <= 0 || limit > 500) throw new ValidationError("limit must be between 1 and 500");
272
273
  params.push(limit);
273
274
  const where = conditions.length ? `WHERE ${conditions.join(" AND ")}` : "";
274
- const rows = getDb().query(`
275
- SELECT * FROM issue_refs
276
- ${where}
277
- ORDER BY updated_at DESC, created_at DESC, id DESC
278
- LIMIT ?
279
- `).all(...params) as IssueRefRow[];
280
- return rows.map(rowToIssueRef);
275
+ return { sql: `SELECT * FROM issue_refs ${where} ORDER BY updated_at DESC, created_at DESC, id DESC LIMIT ?`, params };
276
+ }
277
+
278
+ export function listIssueRefs(opts: ListIssueRefsOptions = {}): IssueRef[] {
279
+ const { sql, params } = buildListIssueRefsQuery(opts);
280
+ return (getDb().query(sql).all(...params) as IssueRefRow[]).map(rowToIssueRef);
281
281
  }
282
282
 
283
283
  export function updateIssueRef(id: string, input: UpdateIssueRefInput, now: number = Date.now()): IssueRef | null {
@@ -1,4 +1,5 @@
1
1
  import { ensureEventLogSchema } from "@humwick/kernel/event-log";
2
+ import { ensureKernelReplayRetentionSchema } from "@humwick/kernel/sqlite-kernel-persistence";
2
3
  import { getDb } from "./connection.ts";
3
4
 
4
5
  /**
@@ -11,4 +12,5 @@ import { getDb } from "./connection.ts";
11
12
  */
12
13
  export function ensureKernelEventLogSchema(): void {
13
14
  ensureEventLogSchema(getDb());
15
+ ensureKernelReplayRetentionSchema(getDb(), Date.now());
14
16
  }
@@ -1,7 +1,8 @@
1
1
  // #3363 — reads of the Kernel landing boundary and incident entities (kernel/landing-incident.ts) for
2
2
  // the red-main controller. Writes go through the Kernel ops (src/services/red-main-incident.ts).
3
3
  import type { LandBoundary, RedMainIncident } from "@humwick/kernel/landing-incident";
4
- import type { ShippingRedMain } from "@humwick/sdk";
4
+ import { ciRunUrl, type ShippingFailingTest, type ShippingRedMain } from "@humwick/sdk";
5
+ import type { BaseKnownFailure } from "@humwick/sdk/base-known-failures";
5
6
  import { getDb } from "./connection.ts";
6
7
  import { LAND_INCIDENT_TABLE, OPEN_INCIDENT_STATES } from "./land-incident-eligibility.ts";
7
8
 
@@ -81,12 +82,57 @@ export function openRedMainIncidentForRemote(remote: string): RedMainIncident |
81
82
  return row ? incident(row) : null;
82
83
  }
83
84
 
84
- /** The Shipping page's "lane stopped" lines: each open incident with its red sha. */
85
- export function openRedMainLines(): ShippingRedMain[] {
85
+ type OpenIncidentRow = Record<string, unknown> & { redRemote: string; redSha: string };
86
+
87
+ /** Open incidents with their red boundary. `i.*`: the Kernel adds a newer field's column only when the
88
+ * landing module starts, so a read right after deploy must not name it (#3362 §11 failingTests). */
89
+ function openIncidentRows(remote?: string): OpenIncidentRow[] {
86
90
  if (!tablesReady()) return [];
87
- return getDb().query(`SELECT i.id AS incidentId, i.laneKey, i.state, i.mainFailurePolicy, b.remote, b.landedTipSha AS sha
91
+ return getDb().query(`SELECT i.*, b.remote AS redRemote, b.landedTipSha AS redSha
88
92
  FROM ${LAND_INCIDENT_TABLE} i JOIN ${BOUNDARY_TABLE} b ON b.id = i.redBoundaryId
89
- WHERE i.state IN ${OPEN_STATES_SQL} ORDER BY i.openedAt, i.id`).all() as ShippingRedMain[];
93
+ WHERE i.state IN ${OPEN_STATES_SQL} AND (? IS NULL OR b.remote = ?) ORDER BY i.openedAt, i.id`).all(remote ?? null, remote ?? null) as OpenIncidentRow[];
94
+ }
95
+
96
+ function failingTestsOf(row: Record<string, unknown>): ShippingFailingTest[] {
97
+ if (typeof row.failingTests !== "string") return [];
98
+ try {
99
+ const parsed: unknown = JSON.parse(row.failingTests);
100
+ return Array.isArray(parsed) ? parsed.filter((entry): entry is ShippingFailingTest =>
101
+ typeof entry?.file === "string" && typeof entry?.name === "string") : [];
102
+ } catch {
103
+ console.warn(`[red-main] incident ${String(row.id)} has unreadable failingTests; showing none`);
104
+ return [];
105
+ }
106
+ }
107
+
108
+ function culpritTaskIds(row: Record<string, unknown>): number[] {
109
+ const ids = JSON.parse(String(row.culpritBoundaryIds ?? "[]")) as string[];
110
+ if (!ids.length) return [];
111
+ const rows = getDb().query(`SELECT DISTINCT taskId FROM ${BOUNDARY_TABLE} WHERE taskId IS NOT NULL AND id IN (${ids.map(() => "?").join(",")}) ORDER BY taskId`)
112
+ .all(...ids) as { taskId: number }[];
113
+ return rows.map((entry) => entry.taskId);
114
+ }
115
+
116
+ /** The Shipping page's red-main lines: each open incident with its red sha, failing cases, owners and run. */
117
+ export function openRedMainLines(): ShippingRedMain[] {
118
+ return openIncidentRows().map((row) => {
119
+ const failingTests = failingTestsOf(row);
120
+ const ownerTaskIds = culpritTaskIds(row);
121
+ return {
122
+ incidentId: String(row.id), laneKey: String(row.laneKey), state: String(row.state),
123
+ ...(row.mainFailurePolicy ? { mainFailurePolicy: row.mainFailurePolicy as "stop" | "advisory" } : {}),
124
+ remote: row.redRemote, sha: row.redSha,
125
+ runUrl: ciRunUrl(row.redRemote, Number(row.ciRunId), Number(row.ciAttempt)),
126
+ ...(failingTests.length ? { failingTests } : {}),
127
+ ...(ownerTaskIds.length ? { ownerTaskIds } : {}),
128
+ };
129
+ });
130
+ }
131
+
132
+ /** #3362 §11: failing cases already present on `remote`'s main, which delivery gates hold out of unrelated runs. */
133
+ export function baseKnownFailures(remote: string): BaseKnownFailure[] {
134
+ return openIncidentRows(remote).flatMap((row) =>
135
+ failingTestsOf(row).map((test) => ({ ...test, incidentId: String(row.id), sha: row.redSha })));
90
136
  }
91
137
 
92
138
  /** #3381 — whether any partial land happened (for `remote`, or anywhere when omitted): a boundary or a
@@ -110,7 +110,7 @@ export interface InsertLandGateAttestationInput extends Omit<LandGateAttestation
110
110
  * can legitimately land twice (a revert-and-reland, a retried push), and the FIRST green attestation
111
111
  * is as true as the second — so a conflict keeps the original rather than churning the row.
112
112
  */
113
- export function insertLandGateAttestation(input: InsertLandGateAttestationInput): LandGateAttestationRecord {
113
+ export function insertLandGateAttestation(input: InsertLandGateAttestationInput, submittedAt: number = Date.now()): LandGateAttestationRecord {
114
114
  const record = decodeLandGateAttestationRow({
115
115
  repo: input.repo,
116
116
  tree_sha: input.treeSha,
@@ -121,7 +121,7 @@ export function insertLandGateAttestation(input: InsertLandGateAttestationInput)
121
121
  gate_names: JSON.stringify(input.gateNames),
122
122
  gates_ran: input.gatesRan,
123
123
  workspace_id: input.workspaceId ?? null,
124
- attested_at: input.attestedAt ?? Date.now(),
124
+ attested_at: input.attestedAt ?? submittedAt,
125
125
  suite_coverage: input.suiteCoverage ?? null,
126
126
  });
127
127
  getDb().query(`
@@ -110,7 +110,7 @@ function receiptId(input: InsertLandingReceiptInput): string {
110
110
  return `landing_${createHash("sha256").update(key).digest("hex").slice(0, 24)}`;
111
111
  }
112
112
 
113
- export function insertLandingReceipt(input: InsertLandingReceiptInput): LandingReceipt {
113
+ export function insertLandingReceipt(input: InsertLandingReceiptInput, submittedAt: number = Date.now()): LandingReceipt {
114
114
  const receipt: LandingReceipt = decodeLandingReceiptRow({
115
115
  id: receiptId(input),
116
116
  project_id: input.projectId ?? null,
@@ -127,7 +127,7 @@ export function insertLandingReceipt(input: InsertLandingReceiptInput): LandingR
127
127
  team_id: input.teamId ?? null,
128
128
  orchestrator_id: input.orchestratorId ?? null,
129
129
  host: input.host ?? null,
130
- landed_at: input.landedAt ?? Date.now(),
130
+ landed_at: input.landedAt ?? submittedAt,
131
131
  });
132
132
  getDb().query(`
133
133
  INSERT INTO landing_receipts (
@@ -0,0 +1,5 @@
1
+ import { getDb } from "./connection";
2
+ import type { ContextState } from "../types";
3
+ export function persistAdvisoryContext(agentId: string, context: ContextState): void {
4
+ getDb().query("UPDATE agents SET context_state = ? WHERE id = ?").run(JSON.stringify(context), agentId);
5
+ }
@@ -0,0 +1,76 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { getGateway } from "./gateway";
3
+ import type { clearAgentNotice, recordTerminalEvent } from "./terminal-events";
4
+ import type { recordCrashReport } from "./crash-reports";
5
+ import type { stampSpawnPrincipal } from "./agent-ownership";
6
+ import type { markSpawnRegistrationConfirmed } from "../commands-db";
7
+ import type { seedSpawnPromptMirror } from "./message-reads";
8
+ import type { resolveQueuedPolicyMessages, resolveQueuedDirectMessages } from "./delivery";
9
+ import type { resolveQueuedCoordinatorMessages } from "./coordinator-delivery";
10
+ import type { updateManagedAgentState } from "../config-store";
11
+ import type { deleteWorkspace } from "./workspaces";
12
+ import type { addSubscription, removeSubscription, removeSubscriptionsForTask } from "./notification-subscriptions";
13
+
14
+ export function clearAgentNoticeAsync(...args: Parameters<typeof clearAgentNotice>): Promise<ReturnType<typeof clearAgentNotice>> {
15
+ return getGateway().write("lifecycleTail.clearAgentNotice", args) as unknown as Promise<ReturnType<typeof clearAgentNotice>>;
16
+ }
17
+
18
+ export function recordTerminalEventAsync(...args: Parameters<typeof recordTerminalEvent>): Promise<ReturnType<typeof recordTerminalEvent>> {
19
+ return getGateway().write("lifecycleTail.recordTerminalEvent", args, { idempotencyKey: randomUUID() }) as unknown as Promise<ReturnType<typeof recordTerminalEvent>>;
20
+ }
21
+
22
+ export function recordCrashReportAsync(...args: Parameters<typeof recordCrashReport>): Promise<ReturnType<typeof recordCrashReport>> {
23
+ return getGateway().write("lifecycleTail.recordCrashReport", args, { idempotencyKey: randomUUID() }) as unknown as Promise<ReturnType<typeof recordCrashReport>>;
24
+ }
25
+
26
+ export function stampSpawnPrincipalAsync(...args: Parameters<typeof stampSpawnPrincipal>): Promise<ReturnType<typeof stampSpawnPrincipal>> {
27
+ return getGateway().write("lifecycleTail.stampSpawnPrincipal", args) as unknown as Promise<ReturnType<typeof stampSpawnPrincipal>>;
28
+ }
29
+
30
+ export function markSpawnRegistrationConfirmedAsync(...args: Parameters<typeof markSpawnRegistrationConfirmed>): Promise<ReturnType<typeof markSpawnRegistrationConfirmed>> {
31
+ return getGateway().write("lifecycleTail.markSpawnRegistrationConfirmed", args) as unknown as Promise<ReturnType<typeof markSpawnRegistrationConfirmed>>;
32
+ }
33
+
34
+ export function seedSpawnPromptMirrorAsync(...args: Parameters<typeof seedSpawnPromptMirror>): Promise<ReturnType<typeof seedSpawnPromptMirror>> {
35
+ return getGateway().write("lifecycleTail.seedSpawnPromptMirror", args) as unknown as Promise<ReturnType<typeof seedSpawnPromptMirror>>;
36
+ }
37
+
38
+ export function resolveQueuedPolicyMessagesAsync(...args: Parameters<typeof resolveQueuedPolicyMessages>): Promise<ReturnType<typeof resolveQueuedPolicyMessages>> {
39
+ return getGateway().write("lifecycleTail.resolveQueuedPolicyMessages", args) as unknown as Promise<ReturnType<typeof resolveQueuedPolicyMessages>>;
40
+ }
41
+
42
+ export function resolveQueuedDirectMessagesAsync(...args: Parameters<typeof resolveQueuedDirectMessages>): Promise<ReturnType<typeof resolveQueuedDirectMessages>> {
43
+ return getGateway().write("lifecycleTail.resolveQueuedDirectMessages", args) as unknown as Promise<ReturnType<typeof resolveQueuedDirectMessages>>;
44
+ }
45
+
46
+ export function resolveQueuedCoordinatorMessagesAsync(...args: Parameters<typeof resolveQueuedCoordinatorMessages>): Promise<ReturnType<typeof resolveQueuedCoordinatorMessages>> {
47
+ return getGateway().write("lifecycleTail.resolveQueuedCoordinatorMessages", args) as unknown as Promise<ReturnType<typeof resolveQueuedCoordinatorMessages>>;
48
+ }
49
+
50
+ export function updateManagedAgentStateAsync(...args: Parameters<typeof updateManagedAgentState>): Promise<ReturnType<typeof updateManagedAgentState>> {
51
+ return getGateway().write("lifecycleTail.updateManagedAgentState", args) as unknown as Promise<ReturnType<typeof updateManagedAgentState>>;
52
+ }
53
+
54
+ export function deleteWorkspaceAsync(...args: Parameters<typeof deleteWorkspace>): Promise<ReturnType<typeof deleteWorkspace>> {
55
+ return getGateway().write("lifecycleTail.deleteWorkspace", args) as unknown as Promise<ReturnType<typeof deleteWorkspace>>;
56
+ }
57
+
58
+ export function addSubscriptionAsync(...args: Parameters<typeof addSubscription>): Promise<ReturnType<typeof addSubscription>> {
59
+ return getGateway().write("lifecycleTail.addSubscription", args, { idempotencyKey: randomUUID() }) as unknown as Promise<ReturnType<typeof addSubscription>>;
60
+ }
61
+
62
+ export function removeSubscriptionAsync(...args: Parameters<typeof removeSubscription>): Promise<ReturnType<typeof removeSubscription>> {
63
+ return getGateway().write("lifecycleTail.removeSubscription", args) as unknown as Promise<ReturnType<typeof removeSubscription>>;
64
+ }
65
+
66
+ export function removeSubscriptionsForTaskAsync(...args: Parameters<typeof removeSubscriptionsForTask>): Promise<ReturnType<typeof removeSubscriptionsForTask>> {
67
+ return getGateway().write("lifecycleTail.removeSubscriptionsForTask", args) as unknown as Promise<ReturnType<typeof removeSubscriptionsForTask>>;
68
+ }
69
+
70
+ export function addSubscriptionsAsync(inputs: Array<Parameters<typeof addSubscription>[0]>): Promise<Array<ReturnType<typeof addSubscription>>> {
71
+ return getGateway().write("notifications.subscriptions.addBatch", { inputs }, { idempotencyKey: randomUUID() }) as unknown as Promise<Array<ReturnType<typeof addSubscription>>>;
72
+ }
73
+
74
+ export function upsertManagedAgentStateAsync(...args: Parameters<typeof import("../config-store").upsertManagedAgentState>): Promise<ReturnType<typeof import("../config-store").upsertManagedAgentState>> {
75
+ return getGateway().write("lifecycleTail.upsertManagedAgentState", args) as unknown as Promise<ReturnType<typeof import("../config-store").upsertManagedAgentState>>;
76
+ }