@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,7 @@
1
+ import { framed } from "../hub-metrics";
2
+ import { getGateway } from "./gateway";
3
+ import { normalizePhase, readCutover } from "./timer-cutover-state";
4
+ import type { CutoverWriterState, CutoverStepArgs, CutoverStepResults } from "./timer-cutover-bodies";
1
5
  import { randomUUID } from "node:crypto";
2
6
  import {
3
7
  clearExpiredLegacyMessageClaimsInTx,
@@ -64,48 +68,9 @@ export type TimerMessageCutoverTickResult =
64
68
  | { state: "absent" | "idle" | "waiting-for-lease" }
65
69
  | { state: "advanced" | "holding" | "aborting"; phase: TimerMessageCutoverPhase; epoch: number; liveClaims?: number; guard: TimerMessageDeadlineGuard };
66
70
 
67
- function normalizePhase(phase: string): TimerMessageCutoverPhase {
68
- return phase === "leased" || phase === "quiescing" || phase === "draining" || phase === "quiesced" || phase === "aborting"
69
- ? phase
70
- : "idle";
71
- }
72
-
73
- function journalOf(row: TimerMessageCutoverRow): TimerMessageCutoverJournalEntry[] {
74
- return Array.isArray(row.phaseJournal) ? row.phaseJournal as TimerMessageCutoverJournalEntry[] : [];
75
- }
76
-
77
- function appendJournal(row: TimerMessageCutoverRow, entry: TimerMessageCutoverJournalEntry): string {
78
- return JSON.stringify([...journalOf(row), entry]);
79
- }
80
-
81
- function readCutover(): TimerMessageCutoverRow | null {
82
- const row = getDb().query("SELECT * FROM timer_message_cutover WHERE id = 1").get() as any;
83
- return row ? {
84
- id: 1,
85
- protocolVersion: row.protocol_version,
86
- epoch: row.epoch,
87
- desiredMode: row.desired_mode,
88
- observedMode: row.observed_mode,
89
- phase: row.phase,
90
- leaseOwner: row.lease_owner,
91
- leaseExpiresAt: row.lease_expires_at,
92
- quiesceStartedAt: row.quiesce_started_at,
93
- quiesceDeadline: row.quiesce_deadline,
94
- lastCompletedTimer: row.last_completed_timer,
95
- ingressPolicy: row.ingress_policy,
96
- messageMutationGate: row.message_mutation_gate,
97
- gateEpoch: row.gate_epoch,
98
- abortRequested: row.abort_requested === 1,
99
- phaseJournal: JSON.parse(row.phase_journal),
100
- updatedAt: row.updated_at,
101
- } : null;
102
- }
103
-
104
71
  /** Singleton Stage-6 lease/quiesce state machine. It has no HTTP/MCP/CLI binding: production stays
105
72
  * shadow and the only boot wiring is recovery of an already-existing non-idle journal. */
106
- // LC-4c (#1920) owns extraction of this remaining synchronous state-machine core into a db-domain
107
- // writer-op module. It cannot be safely folded into this service in LC-4b: doing so breaches the
108
- // file-size ratchet; callers with an awaitable batch facade are already migrated here.
73
+ // #1870 — only transaction bodies cross the writer seam; fault hooks and timers stay on main.
109
74
  export class TimerMessageCutoverCoordinator {
110
75
  readonly ownerId: string;
111
76
  readonly #now: () => number;
@@ -158,7 +123,7 @@ export class TimerMessageCutoverCoordinator {
158
123
  if (!acquired) return false;
159
124
  const guard = this.deadlineGuard();
160
125
  if (!guard.safe) {
161
- this.requestAbort(`deadline guard refused entry (slack=${guard.slackMs}, required=${guard.requiredMs})`);
126
+ await this.requestAbort(`deadline guard refused entry (slack=${guard.slackMs}, required=${guard.requiredMs})`);
162
127
  await this.tick();
163
128
  await this.tick();
164
129
  return false;
@@ -166,15 +131,9 @@ export class TimerMessageCutoverCoordinator {
166
131
  return true;
167
132
  }
168
133
 
169
- requestAbort(reason = "abort requested"): boolean {
134
+ async requestAbort(reason = "abort requested"): Promise<boolean> {
170
135
  const now = this.#now();
171
- return writeTransaction(() => {
172
- const row = readCutover();
173
- if (!row || normalizePhase(row.phase) === "idle") return false;
174
- return getDb().query(`UPDATE timer_message_cutover
175
- SET abort_requested = 1, phase_journal = ?, updated_at = ? WHERE id = 1`)
176
- .run(appendJournal(row, { epoch: row.epoch, phase: "aborting", at: now, reason }), now).changes === 1;
177
- });
136
+ return await this.#writeStep("abort", { now, reason });
178
137
  }
179
138
 
180
139
  /** Stage 9: commit only the durable route marker while the same all-surface gate remains closed. */
@@ -182,19 +141,7 @@ export class TimerMessageCutoverCoordinator {
182
141
  const now = this.#now();
183
142
  const epoch = this.#epoch;
184
143
  if (epoch === undefined) throw new Error("cutover lease is not owned");
185
- writeTransaction(() => {
186
- const row = this.#owned(epoch, now);
187
- if (normalizePhase(row.phase) !== "quiesced" || row.messageMutationGate !== "closed") {
188
- throw new Error("ingress routing activation requires the live quiesced gate owner");
189
- }
190
- const changed = getDb().query(`UPDATE timer_message_cutover SET ingress_policy = 'ingress',
191
- phase_journal = ?, updated_at = ?
192
- WHERE id = 1 AND epoch = ? AND lease_owner = ? AND lease_expires_at > ?
193
- AND phase = 'quiesced' AND message_mutation_gate = 'closed'`)
194
- .run(appendJournal(row, { epoch, phase: "quiesced", at: now, reason: "authoritative ingress routing activated under fence" }),
195
- now, epoch, this.ownerId, now);
196
- if (changed.changes !== 1) throw new Error("cutover lease lost before ingress routing activation");
197
- });
144
+ await this.#writeStep("activate", { now, epoch });
198
145
  await this.#faults.afterRoutingActivation?.(epoch);
199
146
  }
200
147
 
@@ -205,23 +152,7 @@ export class TimerMessageCutoverCoordinator {
205
152
  const epoch = this.#epoch;
206
153
  if (epoch === undefined) throw new Error("cutover lease is not owned");
207
154
  await this.#faults.afterG1BeforeReopen?.(epoch);
208
- writeTransaction(() => {
209
- const row = this.#owned(epoch, now);
210
- if (normalizePhase(row.phase) !== "quiesced" || row.messageMutationGate !== "closed" || row.ingressPolicy !== "ingress") {
211
- throw new Error("G1 completion requires fenced authoritative ingress routing");
212
- }
213
- const changed = getDb().query(`UPDATE timer_message_cutover SET
214
- protocol_version = MAX(COALESCE(protocol_version, 1), 2),
215
- phase = 'idle', lease_owner = NULL, lease_expires_at = NULL,
216
- quiesce_started_at = NULL, quiesce_deadline = NULL,
217
- message_mutation_gate = 'open', gate_epoch = NULL, abort_requested = 0,
218
- phase_journal = ?, updated_at = ?
219
- WHERE id = 1 AND epoch = ? AND lease_owner = ? AND lease_expires_at > ?
220
- AND phase = 'quiesced' AND message_mutation_gate = 'closed' AND ingress_policy = 'ingress'`)
221
- .run(appendJournal(row, { epoch, phase: "idle", at: now, reason: "G1 proven; gate reopened under legacy authority" }),
222
- now, epoch, this.ownerId, now);
223
- if (changed.changes !== 1) throw new Error("cutover lease lost before G1 gate reopen");
224
- });
155
+ await this.#writeStep("completeLegacy", { now, epoch });
225
156
  this.#epoch = undefined;
226
157
  }
227
158
 
@@ -236,37 +167,7 @@ export class TimerMessageCutoverCoordinator {
236
167
  const now = this.#now();
237
168
  const epoch = this.#epoch;
238
169
  if (epoch === undefined) throw new Error("cutover lease is not owned");
239
- writeTransaction(() => {
240
- const row = this.#owned(epoch, now);
241
- if (normalizePhase(row.phase) !== "quiesced" || row.messageMutationGate !== "closed"
242
- || row.ingressPolicy !== "ingress") {
243
- throw new Error("authority-transfer completion requires the live quiesced ingress gate owner");
244
- }
245
- // Only ACTIVE (scheduled) rows must converge on the target backend — terminal rows never
246
- // dispatch, so their backend is irrelevant and must not block completion (an ordinary kernel-mode
247
- // cancel terminalizes a kernel-owned row that a reverse would otherwise be unable to move).
248
- const wrongOwners = (getDb().query(`SELECT count(*) AS n FROM timer_message_authority
249
- WHERE lifecycle='scheduled' AND backend != ?`).get(expectedBackend) as { n: number }).n;
250
- if (wrongOwners !== 0) throw new Error(`${wrongOwners} scheduled MESSAGE owners are not ${expectedBackend}`);
251
- const expectedFrozen = expectedBackend === "kernel" ? 1 : 0;
252
- const projectionMismatch = (getDb().query(`SELECT count(*) AS n FROM timer_message_authority a
253
- JOIN scheduled_timers s ON s.id=a.timer_id
254
- WHERE a.lifecycle='scheduled' AND (s.command IS NOT NULL OR s.message_authority_frozen != ?)`)
255
- .get(expectedFrozen) as { n: number }).n;
256
- if (projectionMismatch !== 0) throw new Error(`${projectionMismatch} MESSAGE compatibility projections disagree with ${mode}`);
257
- const changed = getDb().query(`UPDATE timer_message_cutover SET
258
- desired_mode = ?, observed_mode = ?, phase = 'idle', lease_owner = NULL,
259
- lease_expires_at = NULL, quiesce_started_at = NULL, quiesce_deadline = NULL,
260
- message_mutation_gate = 'open', gate_epoch = NULL, abort_requested = 0,
261
- phase_journal = ?, updated_at = ?
262
- WHERE id=1 AND epoch=? AND lease_owner=? AND lease_expires_at>?
263
- AND phase='quiesced' AND message_mutation_gate='closed' AND ingress_policy='ingress'`)
264
- .run(mode, mode, appendJournal(row, {
265
- epoch, phase: "idle", at: now,
266
- reason: `${mode} per-row ownership proven; MESSAGE mutation gate reopened`,
267
- }), now, epoch, this.ownerId, now);
268
- if (changed.changes !== 1) throw new Error("cutover lease lost before authority-transfer completion");
269
- });
170
+ await this.#writeStep("completeTransfer", { now, epoch, mode, expectedBackend });
270
171
  this.#epoch = undefined;
271
172
  await this.#faults.afterModeCommit?.(epoch, mode);
272
173
  }
@@ -275,22 +176,11 @@ export class TimerMessageCutoverCoordinator {
275
176
  * benignly refuse while reverse projection owns the quiesced writer window. `targetMode` is the mode
276
177
  * the reverse restores (dual-read→shadow or kernel→dual-read); `sourceObservedMode` is the currently
277
178
  * observed mode the reverse departs from. */
278
- markReverseTransferDesired(targetMode: KernelTimersDesiredMode, sourceObservedMode: KernelTimersDesiredMode): void {
179
+ async markReverseTransferDesired(targetMode: KernelTimersDesiredMode, sourceObservedMode: KernelTimersDesiredMode): Promise<void> {
279
180
  const now = this.#now();
280
181
  const epoch = this.#epoch;
281
182
  if (epoch === undefined) throw new Error("cutover lease is not owned");
282
- writeTransaction(() => {
283
- const row = this.#owned(epoch, now);
284
- const changed = getDb().query(`UPDATE timer_message_cutover SET desired_mode=?,
285
- phase_journal=?, updated_at=?
286
- WHERE id=1 AND epoch=? AND lease_owner=? AND lease_expires_at>?
287
- AND phase='quiesced' AND message_mutation_gate='closed' AND observed_mode=?`)
288
- .run(targetMode, appendJournal(row, {
289
- epoch, phase: "quiesced", at: now,
290
- reason: `${targetMode} rollback desired; kernel decision commits quiesced for reverse projection`,
291
- }), now, epoch, this.ownerId, now, sourceObservedMode);
292
- if (changed.changes !== 1) throw new Error(`reverse transfer requires observed ${sourceObservedMode} under the live fence`);
293
- });
183
+ await this.#writeStep("reverse", { now, epoch, targetMode, sourceObservedMode });
294
184
  }
295
185
 
296
186
  /** One deterministic recovery/coordination step. The deadline guard is recomputed on every call,
@@ -315,7 +205,7 @@ export class TimerMessageCutoverCoordinator {
315
205
  : boundedOut
316
206
  ? "bounded quiesce timeout reached"
317
207
  : `deadline guard tripped (slack=${guard.slackMs}, required=${guard.requiredMs})`;
318
- if (normalizePhase(row.phase) !== "aborting") this.#transition(row.epoch, "aborting", reason);
208
+ if (normalizePhase(row.phase) !== "aborting") await this.#transition(row.epoch, "aborting", reason);
319
209
  else await this.#finishAbort(row.epoch, reason);
320
210
  return { state: "aborting", phase: "aborting", epoch: row.epoch, guard };
321
211
  }
@@ -327,20 +217,20 @@ export class TimerMessageCutoverCoordinator {
327
217
 
328
218
  switch (normalizePhase(row.phase)) {
329
219
  case "leased":
330
- if (!this.#closeGate(row.epoch, now)) {
220
+ if (!await this.#closeGate(row.epoch, now)) {
331
221
  return { state: "aborting", phase: "aborting", epoch: row.epoch, guard: this.deadlineGuard(now) };
332
222
  }
333
223
  await this.#faults.afterGateClose?.(row.epoch);
334
224
  return { state: "advanced", phase: "quiescing", epoch: row.epoch, guard };
335
225
  case "quiescing":
336
- this.#transition(row.epoch, "draining", "message claims are fenced; begin bounded drain");
226
+ await this.#transition(row.epoch, "draining", "message claims are fenced; begin bounded drain");
337
227
  return { state: "advanced", phase: "draining", epoch: row.epoch, guard };
338
228
  case "draining": {
339
- writeTransaction((tx) => clearExpiredLegacyMessageClaimsInTx(tx, now));
229
+ await this.#writeStep("clearClaims", { now });
340
230
  const liveClaims = countLiveLegacyMessageClaims(now);
341
231
  await this.#faults.duringClaimDrain?.(row.epoch, liveClaims);
342
232
  if (liveClaims === 0) {
343
- this.#transition(row.epoch, "quiesced", "all live legacy MESSAGE claims drained");
233
+ await this.#transition(row.epoch, "quiesced", "all live legacy MESSAGE claims drained");
344
234
  return { state: "advanced", phase: "quiesced", epoch: row.epoch, liveClaims, guard };
345
235
  }
346
236
  return { state: "holding", phase: "draining", epoch: row.epoch, liveClaims, guard };
@@ -358,11 +248,22 @@ export class TimerMessageCutoverCoordinator {
358
248
  /** Boot recovery is deliberately non-creative: absent/idle shadow state stays a production no-op. */
359
249
  startRecovery(): void {
360
250
  if (this.#ticker) return;
361
- const pass = () => void this.tick().catch((error) => console.warn(`timer MESSAGE cutover recovery failed: ${String(error)}`));
251
+ const pass = framed("timer message-cutover", () => this.tick().catch((error) => console.warn(`timer MESSAGE cutover recovery failed: ${String(error)}`)));
362
252
  pass();
363
253
  this.#ticker = setInterval(pass, this.#tickMs);
364
254
  }
365
255
 
256
+ async #writeStep<K extends keyof CutoverStepArgs>(step: K, args: CutoverStepArgs[K]): Promise<CutoverStepResults[K]> {
257
+ const epoch = this.#epoch;
258
+ const state: CutoverWriterState = { ownerId: this.ownerId, epoch, leaseMs: this.#leaseMs,
259
+ quiesceTimeoutMs: this.#quiesceTimeoutMs, worstCaseMs: this.#worstCaseMs,
260
+ authoritativeActivation: this.#authoritativeActivation, operationLeaseFence: this.#operationLeaseFence };
261
+ const result = await getGateway().write("timerCutover.coordinatorStep", { step, state, args },
262
+ { critical: true, idempotencyKey: randomUUID() }) as unknown as { value: CutoverStepResults[K]; clearEpoch?: boolean };
263
+ if (result.clearEpoch && this.#epoch === epoch) this.#epoch = undefined;
264
+ return result.value;
265
+ }
266
+
366
267
  stop(): void {
367
268
  if (this.#ticker) clearInterval(this.#ticker);
368
269
  this.#ticker = undefined;
@@ -371,57 +272,7 @@ export class TimerMessageCutoverCoordinator {
371
272
  async #acquire(create: boolean): Promise<boolean> {
372
273
  const now = this.#now();
373
274
  let acquiredEpoch: number | undefined;
374
- let takeover = false;
375
- writeTransaction(() => {
376
- // Stage-10 pins the resolved leg before it asks this independent coordinator to close the
377
- // global gate. Check that pin's operation lease under THIS acquisition transaction: if an
378
- // abort won after pin but before requestQuiesce, it cannot be followed by a stale gate close.
379
- const fence = this.#operationLeaseFence;
380
- if (fence) {
381
- const live = getDb().query(`SELECT 1 FROM timer_message_cutover_operation
382
- WHERE id=1 AND request_id=? AND state='running' AND abort_requested=0
383
- AND lease_owner=? AND lease_expires_at > ?`)
384
- .get(fence.requestId, fence.ownerId, now);
385
- if (!live) return;
386
- }
387
- const row = readCutover();
388
- if (!row) {
389
- if (!create) return;
390
- acquiredEpoch = 1;
391
- const journal: TimerMessageCutoverJournalEntry[] = [{ epoch: 1, phase: "leased", at: now, reason: "initial lease acquired" }];
392
- getDb().query(`INSERT INTO timer_message_cutover
393
- (id, protocol_version, epoch, desired_mode, observed_mode, phase, lease_owner, lease_expires_at,
394
- quiesce_started_at, quiesce_deadline, last_completed_timer, ingress_policy,
395
- message_mutation_gate, gate_epoch, abort_requested, phase_journal, updated_at)
396
- VALUES (1, 1, 1, 'shadow', 'shadow', 'leased', ?, ?, NULL, NULL, NULL, 'legacy', 'open', NULL, 0, ?, ?)`)
397
- .run(this.ownerId, now + this.#leaseMs, JSON.stringify(journal), now);
398
- return;
399
- }
400
- const rowPhase = normalizePhase(row.phase);
401
- const liveForeign = row.leaseOwner !== null && row.leaseOwner !== this.ownerId && (row.leaseExpiresAt ?? 0) > now;
402
- if (liveForeign) return;
403
- if (row.leaseOwner === this.ownerId && (row.leaseExpiresAt ?? 0) > now && this.#epoch === row.epoch) {
404
- acquiredEpoch = row.epoch;
405
- return;
406
- }
407
- const nextEpoch = row.epoch + 1;
408
- takeover = row.leaseOwner !== null || rowPhase !== "idle" || row.messageMutationGate === "closed";
409
- const nextPhase: TimerMessageCutoverPhase = rowPhase === "idle" ? "leased" : rowPhase;
410
- const entry: TimerMessageCutoverJournalEntry = {
411
- epoch: nextEpoch,
412
- phase: takeover ? "takeover" : "leased",
413
- at: now,
414
- reason: takeover ? `expired epoch ${row.epoch} taken over in phase ${rowPhase}` : "lease acquired",
415
- };
416
- const result = getDb().query(`UPDATE timer_message_cutover SET
417
- protocol_version = COALESCE(protocol_version, 1), epoch = ?, phase = ?, lease_owner = ?, lease_expires_at = ?,
418
- gate_epoch = CASE WHEN message_mutation_gate = 'closed' THEN ? ELSE NULL END,
419
- phase_journal = ?, updated_at = ?
420
- WHERE id = 1 AND (lease_owner IS NULL OR lease_expires_at <= ? OR lease_owner = ?)`)
421
- .run(nextEpoch, nextPhase, this.ownerId, now + this.#leaseMs, nextEpoch,
422
- appendJournal(row, entry), now, now, this.ownerId);
423
- if (result.changes === 1) acquiredEpoch = nextEpoch;
424
- });
275
+ ({ acquiredEpoch } = await this.#writeStep("acquire", { now, create }));
425
276
  if (acquiredEpoch === undefined) return false;
426
277
  this.#epoch = acquiredEpoch;
427
278
  await this.#faults.afterLeaseAcquire?.(acquiredEpoch);
@@ -430,116 +281,24 @@ export class TimerMessageCutoverCoordinator {
430
281
 
431
282
  async #renew(epoch: number): Promise<boolean> {
432
283
  const now = this.#now();
433
- const renewed = writeTransaction(() => {
434
- const row = readCutover();
435
- if (!row || row.epoch !== epoch || row.leaseOwner !== this.ownerId || (row.leaseExpiresAt ?? 0) <= now) return false;
436
- const deadlineCap = row.messageMutationGate === "closed" && row.quiesceDeadline !== null
437
- ? row.quiesceDeadline
438
- : Number.MAX_SAFE_INTEGER;
439
- const nextExpiry = Math.min(now + this.#leaseMs, deadlineCap);
440
- return getDb().query(`UPDATE timer_message_cutover SET lease_expires_at = ?, phase_journal = ?, updated_at = ?
441
- WHERE id = 1 AND epoch = ? AND lease_owner = ? AND lease_expires_at > ?`)
442
- .run(nextExpiry, appendJournal(row, { epoch, phase: "renewed", at: now }), now,
443
- epoch, this.ownerId, now).changes === 1;
444
- });
284
+ const renewed = await this.#writeStep("renew", { now, epoch });
445
285
  if (renewed) await this.#faults.afterRenewal?.(epoch);
446
286
  return renewed;
447
287
  }
448
288
 
449
- #closeGate(epoch: number, now: number): boolean {
450
- return writeTransaction(() => {
451
- const row = this.#owned(epoch, now);
452
- // `requestQuiesce` acquires the coordinator lease before the following tick closes the gate.
453
- // Recheck the Stage-10 operation lease in this close transaction: an abort (or expiry) that
454
- // won in that interval must leave this independent coordinator open and unleased, never
455
- // permit stale authority to close the MESSAGE gate after the abort's release observed it open.
456
- const fence = this.#operationLeaseFence;
457
- if (fence) {
458
- const live = getDb().query(`SELECT 1 FROM timer_message_cutover_operation
459
- WHERE id=1 AND request_id=? AND state='running' AND abort_requested=0
460
- AND lease_owner=? AND lease_expires_at > ?`)
461
- .get(fence.requestId, fence.ownerId, now);
462
- if (!live) {
463
- const released = getDb().query(`UPDATE timer_message_cutover SET
464
- phase = 'idle', lease_owner = NULL, lease_expires_at = NULL,
465
- quiesce_started_at = NULL, quiesce_deadline = NULL,
466
- message_mutation_gate = 'open', gate_epoch = NULL, abort_requested = 0,
467
- desired_mode = observed_mode, phase_journal = ?, updated_at = ?
468
- WHERE id=1 AND epoch=? AND lease_owner=? AND lease_expires_at>? AND phase='leased'`)
469
- .run(appendJournal(row, {
470
- epoch, phase: "idle", at: now,
471
- reason: "Stage-10 operation lease no longer authorizes MESSAGE gate close",
472
- }), now, epoch, this.ownerId, now);
473
- if (released.changes !== 1) throw new Error("cutover lease lost while releasing stale Stage-10 gate request");
474
- this.#epoch = undefined;
475
- return false;
476
- }
477
- }
478
- // Re-read all three deadline sources under the SAME writer lock that closes the gate. A
479
- // deadline mutation that won the race is therefore observed here and refuses entry; one that
480
- // loses cannot commit until after the closed marker and is caught by the next continuous tick.
481
- const guard = this.deadlineGuard(now);
482
- if (!guard.safe) {
483
- const changed = getDb().query(`UPDATE timer_message_cutover SET phase = 'aborting', abort_requested = 1,
484
- phase_journal = ?, updated_at = ? WHERE id = 1 AND epoch = ? AND lease_owner = ? AND phase = 'leased'`)
485
- .run(appendJournal(row, {
486
- epoch, phase: "aborting", at: now,
487
- reason: `deadline guard refused atomic gate close (slack=${guard.slackMs}, required=${guard.requiredMs})`,
488
- }), now, epoch, this.ownerId);
489
- if (changed.changes !== 1) throw new Error("cutover lease lost while refusing gate close");
490
- return false;
491
- }
492
- const deadline = Math.min(
493
- now + this.#quiesceTimeoutMs,
494
- guard.deadlines.earliestDeadline === null ? Number.MAX_SAFE_INTEGER : guard.deadlines.earliestDeadline - 1,
495
- );
496
- const changed = getDb().query(`UPDATE timer_message_cutover SET phase = 'quiescing',
497
- message_mutation_gate = 'closed', gate_epoch = ?, quiesce_started_at = ?, quiesce_deadline = ?,
498
- ingress_policy = CASE WHEN ? THEN 'activating' ELSE ingress_policy END,
499
- phase_journal = ?, updated_at = ?
500
- WHERE id = 1 AND epoch = ? AND lease_owner = ? AND phase = 'leased'`)
501
- .run(epoch, now, deadline, this.#authoritativeActivation ? 1 : 0,
502
- appendJournal(row, { epoch, phase: "quiescing", at: now, reason: "MESSAGE mutation gate closed" }),
503
- now, epoch, this.ownerId);
504
- if (changed.changes !== 1) throw new Error("cutover lease lost before gate close");
505
- return true;
506
- });
289
+ async #closeGate(epoch: number, now: number): Promise<boolean> {
290
+ return await this.#writeStep("closeGate", { epoch, now });
507
291
  }
508
292
 
509
- #transition(epoch: number, phase: TimerMessageCutoverPhase, reason: string): void {
293
+ async #transition(epoch: number, phase: TimerMessageCutoverPhase, reason: string): Promise<void> {
510
294
  const now = this.#now();
511
- writeTransaction(() => {
512
- const row = this.#owned(epoch, now);
513
- const changed = getDb().query(`UPDATE timer_message_cutover SET phase = ?, phase_journal = ?, updated_at = ?
514
- WHERE id = 1 AND epoch = ? AND lease_owner = ? AND lease_expires_at > ?`)
515
- .run(phase, appendJournal(row, { epoch, phase, at: now, reason }), now, epoch, this.ownerId, now);
516
- if (changed.changes !== 1) throw new Error(`cutover lease lost before phase ${phase}`);
517
- });
295
+ await this.#writeStep("transition", { epoch, phase, reason, now });
518
296
  }
519
297
 
520
298
  async #finishAbort(epoch: number, reason: string): Promise<void> {
521
299
  await this.#faults.beforeLeaseRelease?.(epoch);
522
300
  const now = this.#now();
523
- writeTransaction(() => {
524
- const row = this.#owned(epoch, now);
525
- const changed = getDb().query(`UPDATE timer_message_cutover SET
526
- phase = 'idle', lease_owner = NULL, lease_expires_at = NULL,
527
- quiesce_started_at = NULL, quiesce_deadline = NULL,
528
- message_mutation_gate = 'open', gate_epoch = NULL, abort_requested = 0,
529
- phase_journal = ?, updated_at = ?
530
- WHERE id = 1 AND epoch = ? AND lease_owner = ? AND lease_expires_at > ?`)
531
- .run(appendJournal(row, { epoch, phase: "idle", at: now, reason: `gate reopened: ${reason}` }),
532
- now, epoch, this.ownerId, now);
533
- if (changed.changes !== 1) throw new Error("cutover lease lost before abort release");
534
- });
301
+ await this.#writeStep("finishAbort", { epoch, reason, now });
535
302
  this.#epoch = undefined;
536
303
  }
537
-
538
- #owned(epoch: number, now: number): TimerMessageCutoverRow {
539
- const row = readCutover();
540
- if (!row || row.epoch !== epoch || row.leaseOwner !== this.ownerId || (row.leaseExpiresAt ?? 0) <= now) {
541
- throw new Error(`cutover epoch ${epoch} is not owned by ${this.ownerId}`);
542
- }
543
- return row;
544
- }
545
304
  }
@@ -0,0 +1,40 @@
1
+ import { getDb } from "./connection";
2
+ import type { TimerMessageCutoverRow } from "./timer-message-flip";
3
+ import type { TimerMessageCutoverPhase, TimerMessageCutoverJournalEntry } from "./timer-cutover-core";
4
+
5
+ export function normalizePhase(phase: string): TimerMessageCutoverPhase {
6
+ return phase === "leased" || phase === "quiescing" || phase === "draining" || phase === "quiesced" || phase === "aborting"
7
+ ? phase
8
+ : "idle";
9
+ }
10
+
11
+ export function journalOf(row: TimerMessageCutoverRow): TimerMessageCutoverJournalEntry[] {
12
+ return Array.isArray(row.phaseJournal) ? row.phaseJournal as TimerMessageCutoverJournalEntry[] : [];
13
+ }
14
+
15
+ export function appendJournal(row: TimerMessageCutoverRow, entry: TimerMessageCutoverJournalEntry): string {
16
+ return JSON.stringify([...journalOf(row), entry]);
17
+ }
18
+
19
+ export function readCutover(): TimerMessageCutoverRow | null {
20
+ const row = getDb().query("SELECT * FROM timer_message_cutover WHERE id = 1").get() as any;
21
+ return row ? {
22
+ id: 1,
23
+ protocolVersion: row.protocol_version,
24
+ epoch: row.epoch,
25
+ desiredMode: row.desired_mode,
26
+ observedMode: row.observed_mode,
27
+ phase: row.phase,
28
+ leaseOwner: row.lease_owner,
29
+ leaseExpiresAt: row.lease_expires_at,
30
+ quiesceStartedAt: row.quiesce_started_at,
31
+ quiesceDeadline: row.quiesce_deadline,
32
+ lastCompletedTimer: row.last_completed_timer,
33
+ ingressPolicy: row.ingress_policy,
34
+ messageMutationGate: row.message_mutation_gate,
35
+ gateEpoch: row.gate_epoch,
36
+ abortRequested: row.abort_requested === 1,
37
+ phaseJournal: JSON.parse(row.phase_journal),
38
+ updatedAt: row.updated_at,
39
+ } : null;
40
+ }
@@ -1,3 +1,4 @@
1
+ import { readCutover, appendJournal } from "./timer-cutover-state";
1
2
  // Narrow cutover recovery write operations. The release is deliberately critical: it reopens the
2
3
  // dispatch gate after a crashed transfer; shedding it can leave both dispatchers fenced indefinitely.
3
4
 
@@ -19,15 +20,6 @@ interface BatchCheckpoint {
19
20
  done: boolean;
20
21
  }
21
22
 
22
- type TimerMessageCutoverPhase = "idle" | "leased" | "quiescing" | "draining" | "quiesced" | "aborting";
23
-
24
- interface TimerMessageCutoverJournalEntry {
25
- epoch: number;
26
- phase: TimerMessageCutoverPhase | "takeover" | "renewed";
27
- at: number;
28
- reason?: string;
29
- }
30
-
31
23
  function operationRow(): OperationRow | null {
32
24
  return getDb().query("SELECT failures, journal FROM timer_message_cutover_operation WHERE id=1")
33
25
  .get() as OperationRow | null;
@@ -37,37 +29,6 @@ function appendOperationEntry(row: OperationRow, entry: Record<string, unknown>)
37
29
  return JSON.stringify([...JSON.parse(row.journal) as Array<Record<string, unknown>>, entry]);
38
30
  }
39
31
 
40
- function readCutover(): TimerMessageCutoverRow | null {
41
- const row = getDb().query("SELECT * FROM timer_message_cutover WHERE id = 1").get() as any;
42
- return row ? {
43
- id: 1,
44
- protocolVersion: row.protocol_version,
45
- epoch: row.epoch,
46
- desiredMode: row.desired_mode,
47
- observedMode: row.observed_mode,
48
- phase: row.phase,
49
- leaseOwner: row.lease_owner,
50
- leaseExpiresAt: row.lease_expires_at,
51
- quiesceStartedAt: row.quiesce_started_at,
52
- quiesceDeadline: row.quiesce_deadline,
53
- lastCompletedTimer: row.last_completed_timer,
54
- ingressPolicy: row.ingress_policy,
55
- messageMutationGate: row.message_mutation_gate,
56
- gateEpoch: row.gate_epoch,
57
- abortRequested: row.abort_requested === 1,
58
- phaseJournal: JSON.parse(row.phase_journal),
59
- updatedAt: row.updated_at,
60
- } : null;
61
- }
62
-
63
- function journalOf(row: TimerMessageCutoverRow): TimerMessageCutoverJournalEntry[] {
64
- return Array.isArray(row.phaseJournal) ? row.phaseJournal as TimerMessageCutoverJournalEntry[] : [];
65
- }
66
-
67
- function appendJournal(row: TimerMessageCutoverRow, entry: TimerMessageCutoverJournalEntry): string {
68
- return JSON.stringify([...journalOf(row), entry]);
69
- }
70
-
71
32
  /**
72
33
  * Operator-abort escape hatch for an interrupted transfer. This is a writer-op body, so the
73
34
  * gateway executor already owns its transaction; keeping it here avoids a writer-registry →
@@ -104,13 +104,18 @@ function rowToIntent(row: IntentDbRow): TimerIngressIntentRow {
104
104
  };
105
105
  }
106
106
 
107
+ const installedOn = new WeakSet<object>();
108
+
107
109
  /** Idempotent, crash-safe schema install (one transaction; re-running over existing data is a
108
110
  * no-op). Bootstrap DDL — it runs ONCE at startup as its own committed statement, never lazily
109
111
  * inside an op, so a rolled-back op can never undo the schema it ran against (§4 allowlist). */
110
112
  export function installTimerIngressSchema(
111
- options: { requestKeyMigrationFaults?: TimerIngressRequestKeyMigrationFaults } = {},
113
+ options: { requestKeyMigrationFaults?: TimerIngressRequestKeyMigrationFaults; ifNotInstalled?: boolean } = {},
112
114
  ): void {
113
115
  const db = getDb();
116
+ // #1870 S7: `startServer` installs it before bind (the boot exception); `createTimerIngress` passes
117
+ // `ifNotInstalled` so its later call runs no DDL on the main connection. Explicit calls always install.
118
+ if (options.ifNotInstalled && installedOn.has(db)) return;
114
119
  db.transaction(() => {
115
120
  // AUTOINCREMENT is deliberate: `seq` must be monotone and NEVER reused (the watermark's meaning
116
121
  // depends on it — and it doubles as the per-timer apply FENCE), even if settled rows are pruned.
@@ -165,6 +170,7 @@ export function installTimerIngressSchema(
165
170
  db.run("INSERT OR IGNORE INTO timer_ingress_watermark (id, applied_seq, updated_at) VALUES (1, 0, 0)");
166
171
  options.requestKeyMigrationFaults?.beforeCommit?.();
167
172
  }).immediate();
173
+ installedOn.add(db);
168
174
  }
169
175
 
170
176
  // ── Reads ───────────────────────────────────────────────────────────────────────────────────────
@@ -1,3 +1,4 @@
1
+ import { retireHandedOffPredecessorBody } from "./token-standing";
1
2
  // Token-db writer-op registry (ADR 0001 §3.1/§3.4/§3.7.1, S3 L-F #1898). Domain-owned map; the op
2
3
  // BODIES live in `../token-db.ts` and the shared `write-ops.ts` edit is one import + spread.
3
4
  //
@@ -25,6 +26,7 @@ import {
25
26
  type PruneExpiredTokenRecordsInput,
26
27
  } from "../token-db.ts";
27
28
  import type { TokenRecord } from "../types.ts";
29
+ import { recordLaunchFact, type LaunchFact } from "./launch-facts.ts";
28
30
  import type { TokenRevokeReason } from "../security.ts";
29
31
  import type { WriterOpContext, WriterOpSpec } from "./write-ops.ts";
30
32
 
@@ -41,6 +43,11 @@ export interface HandoffTokenOpArgs {
41
43
  readonly newJti: string;
42
44
  }
43
45
 
46
+ /** Args for `tokens.createRunner`: a runner mint plus, for a fresh launch, its launch fact (#1870 S7). */
47
+ export interface CreateRunnerTokenOpArgs extends CreateTokenOpArgs {
48
+ readonly launch?: { readonly agentId: string; readonly fact: LaunchFact };
49
+ }
50
+
44
51
  export interface RevokeTokenOpArgs {
45
52
  readonly jti: string;
46
53
  readonly reason?: TokenRevokeReason;
@@ -66,12 +73,24 @@ function stripHandoffToken(result: unknown): unknown {
66
73
 
67
74
  export const TOKEN_DB_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.freeze({
68
75
  // Non-idempotent (mints a new row each apply); the facade supplies `jti` as the ledger key.
76
+ "tokens.retireHandedOffPredecessor": { offLoop: true, idempotent: true, fn: (args: { jti: string }, ctx) => retireHandedOffPredecessorBody(args.jti, ctx.now) },
69
77
  "tokens.create": {
70
78
  offLoop: true,
71
79
  idempotent: false,
72
80
  fn: (args: CreateTokenOpArgs, ctx: WriterOpContext) => createTokenInternal(args.input, args.jti, ctx.now),
73
81
  serializeIdempotencyResult: stripCreateToken,
74
82
  },
83
+ // A runner mint and the launch fact its successors derive from, in one transaction.
84
+ "tokens.createRunner": {
85
+ offLoop: true,
86
+ idempotent: false,
87
+ fn: (args: CreateRunnerTokenOpArgs, ctx: WriterOpContext) => {
88
+ const issued = createTokenInternal(args.input, args.jti, ctx.now);
89
+ if (args.launch) recordLaunchFact(args.launch.agentId, args.launch.fact, ctx.now);
90
+ return issued;
91
+ },
92
+ serializeIdempotencyResult: stripCreateToken,
93
+ },
75
94
  // Non-idempotent (mints and links a successor); folds the eligibility read (ADR §3.4).
76
95
  "tokens.handoff": {
77
96
  offLoop: true,
@@ -0,0 +1,12 @@
1
+ import { getGateway } from "./gateway";
2
+ import { trackRelayEvent } from "../relay-event-drain";
3
+
4
+ // A concurrent authentication must see a predecessor as retired while its writer op is pending.
5
+ const retiring = new Set<string>();
6
+ export function tokenRetirementPending(jti: string): boolean { return retiring.has(jti); }
7
+ export function retireHandedOffPredecessor(jti: string): void {
8
+ if (retiring.has(jti)) return;
9
+ retiring.add(jti);
10
+ const write = getGateway().write("tokens.retireHandedOffPredecessor", { jti });
11
+ trackRelayEvent(write.finally(() => retiring.delete(jti)), "token.handoff.retired");
12
+ }