@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
@@ -5,11 +5,11 @@ import { getLaunchFact } from "./db/launch-facts";
5
5
  import { getTokenProfile } from "./token-db";
6
6
  import { getAgentProfile, spawnGrantForProfile, toolGroupsForProfile } from "./config-store";
7
7
  import { FLEET_SCOPE } from "./security";
8
- import { stringValue } from "@humwick/sdk";
8
+ import { registryToolName, stringValue } from "@humwick/sdk";
9
9
  import { canonicalAgentProfileName, hasScope } from "@humwick/sdk/types";
10
10
  import { COORDINATOR_PROFILE_NAMES } from "./agent-system-tags";
11
11
  import { SECRETS_DEFAULT_PROFILES, SECRETS_TOOL_GROUP, SECRETS_WRITE_SCOPE } from "./secrets-broker/config";
12
- import { resolveRelayTools, SELF_CARE_TOOL_GROUP } from "./mcp/tool-groups";
12
+ import { RELAY_TOOL_GROUPS, resolveRelayTools, SELF_CARE_TOOL_GROUP } from "./mcp/tool-groups";
13
13
 
14
14
  // Scopes that turn an agent's runtime token into a spawn-capable one (#221). Appended to the
15
15
  // provider-agent base scope only when the resolved profile permits (maxSpawnedAgents > 0).
@@ -24,7 +24,11 @@ const SPAWN_SCOPES = ["command:spawn", "command:shutdown"] as const;
24
24
  const FLEET_OPS_PROFILES = new Set(["coordinator", "ops-assistant"]);
25
25
  // #1925 H10 — fleet visibility is coordinator-facing. Keep this a fixed trusted-profile allowlist,
26
26
  // like command:fleet, rather than a user-editable profile setting that could widen worker tokens.
27
- const HOST_READ_PROFILES = new Set(["coordinator"]);
27
+ const HOST_WRITE_PROFILES = new Set(["coordinator"]);
28
+ // #3772 — the reboot runbook reads resource_control held/waiter counts from /api/hosts; ops profiles read, never write.
29
+ const HOST_READ_PROFILES = new Set([...HOST_WRITE_PROFILES, "ops-assistant", "sec-ops"]);
30
+ // #3780 — operations and QA need hub diagnostics; coordinators can delegate the read scope.
31
+ const STATS_READ_PROFILES = new Set(["coordinator", "ops-assistant", "qa"]);
28
32
  // #3073 — coordinator-only groups (not in WORKER_TOOL_GROUPS) a coordinator always gets, even when its stored override predates them.
29
33
  const COORDINATOR_ONLY_TOOL_GROUPS = ["decisions", "workflows", "project", "routing"] as const;
30
34
  // #3327 — the coordinator edits routing preferences, like Edin in the dashboard.
@@ -43,11 +47,10 @@ function callerMayMintHostsScope(callerScopes: string[] | undefined, scope: "hos
43
47
  return callerScopes === undefined || hasScope(callerScopes, scope);
44
48
  }
45
49
 
46
- // #3110 — the secrets broker scope follows the `secrets` tool group: an explicit group list must name
47
- // it; a full-surface profile (no list) gets it only by default (coordinator, ops-assistant). A caller
48
- // cannot confer it onto a child it spawns without holding it.
49
- function grantsSecretsScope(profile: string | undefined, toolGroups: string[] | undefined, callerScopes: string[] | undefined): boolean {
50
- const inGroup = toolGroups ? toolGroups.includes(SECRETS_TOOL_GROUP) : Boolean(profile && SECRETS_DEFAULT_PROFILES.has(profile));
50
+ // #3110/#3817 — broker groups and exact includes request the same scope, capped by the caller.
51
+ function grantsSecretsScope(profile: string | undefined, toolGroups: string[] | undefined, explicitlySelected: boolean, callerScopes: string[] | undefined): boolean {
52
+ const inGroup = (toolGroups ? toolGroups.includes(SECRETS_TOOL_GROUP) : Boolean(profile && SECRETS_DEFAULT_PROFILES.has(profile)))
53
+ || explicitlySelected;
51
54
  return inGroup && (callerScopes === undefined || hasScope(callerScopes, SECRETS_WRITE_SCOPE));
52
55
  }
53
56
 
@@ -72,6 +75,8 @@ function nonTrustedBaseline(agentInitiated: boolean): string[] {
72
75
  interface RunnerGrant {
73
76
  scope: string[];
74
77
  canSpawn: boolean;
78
+ /** A sub-coordinator under its root coordinator's project delegation: it places spawns on any host its parent can (#3804). */
79
+ delegated: boolean;
75
80
  maxSpawnedAgents: number;
76
81
  toolGroups: string[] | undefined;
77
82
  toolInclude?: string[];
@@ -93,7 +98,7 @@ export function deriveRunnerGrant(profile: string | undefined, authority: Deriva
93
98
  const selection = profile ? getAgentProfile(profile)?.value.relay.tools : undefined;
94
99
  let toolGroups = toolGroupsForProfile(profile);
95
100
  // #2897/#3073/#3110 — stored overrides predate newer trusted-profile groups: coordinators always get the coordinator-only
96
- // groups, and the secrets profiles (coordinator, ops-assistant) always get `secrets`. Keep explicit NONE and full-surface semantics.
101
+ // groups, and the coordinator gets `secrets`. Keep explicit NONE and full-surface semantics.
97
102
  if (toolGroups?.length) {
98
103
  const extra: string[] = [];
99
104
  if ((COORDINATOR_PROFILE_NAMES as readonly string[]).includes(profile ?? "")) extra.push(...COORDINATOR_ONLY_TOOL_GROUPS);
@@ -104,19 +109,21 @@ export function deriveRunnerGrant(profile: string | undefined, authority: Deriva
104
109
  }
105
110
  const fleetOps = !agentInitiated && Boolean(profile && FLEET_OPS_PROFILES.has(profile)) && callerMayMintFleetScope(callerScopes);
106
111
  const hostsRead = !agentInitiated && Boolean(profile && HOST_READ_PROFILES.has(profile)) && callerMayMintHostsScope(callerScopes, "hosts:read");
107
- resolveRelayTools({ ...selection, groups: toolGroups });
112
+ const selected = resolveRelayTools({ ...selection, groups: toolGroups });
113
+ const explicitSecrets = selection?.include?.map(registryToolName).some(name => selected.has(name) && RELAY_TOOL_GROUPS[SECRETS_TOOL_GROUP]!.includes(name)) ?? false;
108
114
  let scope = [
109
115
  ...nonTrustedBaseline(agentInitiated),
110
116
  ...(fleetOps ? [FLEET_SCOPE] : []),
111
117
  ...(hostsRead ? ["hosts:read"] : []),
112
- ...(!agentInitiated && Boolean(profile && HOST_READ_PROFILES.has(profile)) && callerMayMintHostsScope(callerScopes, "hosts:write") ? ["hosts:write"] : []),
113
- ...(grantsSecretsScope(profile, toolGroups, callerScopes) ? [SECRETS_WRITE_SCOPE] : []),
118
+ ...(profile && STATS_READ_PROFILES.has(profile.toLowerCase()) && (callerScopes === undefined || hasScope(callerScopes, "stats:read")) ? ["stats:read"] : []),
119
+ ...(!agentInitiated && Boolean(profile && HOST_WRITE_PROFILES.has(profile)) && callerMayMintHostsScope(callerScopes, "hosts:write") ? ["hosts:write"] : []),
120
+ ...(grantsSecretsScope(profile, toolGroups, explicitSecrets, callerScopes) ? [SECRETS_WRITE_SCOPE] : []),
114
121
  ...(!agentInitiated && (COORDINATOR_PROFILE_NAMES as readonly string[]).includes(profile ?? "") && (callerScopes === undefined || hasScope(callerScopes, ROUTING_WRITE_SCOPE)) ? [ROUTING_WRITE_SCOPE] : []),
115
122
  ...(grant.canSpawn ? SPAWN_SCOPES.filter(scope => !agentInitiated || callerScopes === undefined || hasScope(callerScopes, scope)) : []),
116
123
  ...(delegated && callerScopes && hasScope(callerScopes, "teams:write") ? ["teams:write"] : []),
117
124
  ];
118
125
  if (lineage?.participating && callerScopes) scope = scope.filter(scope => hasScope(callerScopes, scope));
119
- return { scope, canSpawn: grant.canSpawn, maxSpawnedAgents: grant.maxSpawnedAgents, toolGroups,
126
+ return { scope, canSpawn: grant.canSpawn, delegated, maxSpawnedAgents: grant.maxSpawnedAgents, toolGroups,
120
127
  ...(selection?.include === undefined ? {} : { toolInclude: selection.include }),
121
128
  ...(selection?.exclude === undefined ? {} : { toolExclude: selection.exclude }),
122
129
  };
@@ -149,6 +156,7 @@ export function successorGrant(agentId: string, profile: string | undefined, dep
149
156
  return {
150
157
  scope: derived.scope.filter((scope) => ceiling.scope.includes(scope)),
151
158
  canSpawn: derived.canSpawn && ceiling.canSpawn,
159
+ delegated: derived.delegated && ceiling.delegated,
152
160
  maxSpawnedAgents: Math.min(derived.maxSpawnedAgents, ceiling.maxSpawnedAgents),
153
161
  toolGroups: derived.toolGroups,
154
162
  toolInclude: derived.toolInclude,
@@ -1,9 +1,10 @@
1
- import { registryToolName } from "@humwick/sdk";
1
+ import { stringValue } from "@humwick/sdk";
2
2
  import { writeChildEnv } from "@humwick/sdk/env";
3
3
  import { deriveRunnerGrant, successorGrant } from "./runtime-grant";
4
4
  export { runnerSpawnGrantForAgent } from "./runtime-grant";
5
- import { TOKEN_RECOVERY_WINDOW_SECONDS, createToken, getToken, getTokenProfile, type CreateTokenInput } from "./token-db";
6
- import { createTokenAsync, handoffTokenAsync } from "./token-db-write";
5
+ import { TOKEN_RECOVERY_WINDOW_SECONDS, createToken, getToken, getTokenProfile, type CreateTokenInput, type HandoffTokenInput, type TokenHandoff } from "./token-db";
6
+ import { runnerTokenMintLimit } from "./runner-token-mint-limit";
7
+ import { createRunnerTokenAsync, createTokenAsync, handoffTokenAsync } from "./token-db-write";
7
8
  import { FLEET_SCOPE, verifyComponentTokenAllowExpired } from "./security";
8
9
  import { getAgentProfile, hostPinForProfile, spawnGrantForProfile, toolGroupsForProfile } from "./config-store";
9
10
  import { toolAllowlistForRunner } from "./mcp-tool-allowlist";
@@ -12,11 +13,9 @@ import { getLaunchFact, recordLaunchFact, type LaunchFact } from "./db/launch-fa
12
13
  import type { ComponentToken, SpawnApprovalMode, TokenConstraints, TokenRecord } from "./types";
13
14
  import { listManagedOrchestratorsForAgent } from "./orchestrator-lookup";
14
15
  import { sameHostIdentity } from "./utils";
15
- import { stringValue } from "@humwick/sdk";
16
- import { canonicalAgentProfileName, hasScope } from "@humwick/sdk/types";
16
+ import { canonicalAgentProfileName } from "@humwick/sdk/types";
17
17
  import { COORDINATOR_PROFILE_NAMES } from "./agent-system-tags";
18
18
  import { SECRETS_DEFAULT_PROFILES, SECRETS_TOOL_GROUP, SECRETS_WRITE_SCOPE } from "./secrets-broker/config";
19
- import { INCLUDED_TOOL_SCOPE_NEEDS, RELAY_TOOL_GROUPS, resolveRelayTools, SELF_CARE_TOOL_GROUP } from "./mcp/tool-groups";
20
19
 
21
20
  /**
22
21
  * Who vouches for a runner launch's authority (#3110 review). A launch without a positively identified
@@ -38,6 +37,22 @@ interface RuntimeTokenResult {
38
37
  record: TokenRecord;
39
38
  }
40
39
 
40
+ /** A refused successor mint; `retryAfterSeconds` marks a per-subject rate limit (HTTP 429). */
41
+ export type RunnerTokenMintRefusal = { error: string; retryAfterSeconds?: number };
42
+
43
+ /** #3775 — the one way a runner token's successor is minted: within the subject's mint limit, charged per new token. */
44
+ export async function handoffRunnerTokenAsync(sub: string, input: HandoffTokenInput): Promise<TokenHandoff | null | { retryAfterSeconds: number }> {
45
+ const retryAfterSeconds = runnerTokenMintLimit.refusal(sub);
46
+ if (retryAfterSeconds !== undefined) return { retryAfterSeconds };
47
+ const handoff = await handoffTokenAsync(input);
48
+ if (handoff && !handoff.replayed) runnerTokenMintLimit.charge(sub);
49
+ return handoff;
50
+ }
51
+
52
+ function mintRateLimited(handoff: object | null): handoff is { retryAfterSeconds: number } {
53
+ return handoff !== null && "retryAfterSeconds" in handoff;
54
+ }
55
+
41
56
  function runnerTokenOwnedByOrchestratorHost(
42
57
  constraints: NonNullable<ReturnType<typeof verifyComponentTokenAllowExpired>>["constraints"],
43
58
  orchestratorId: string,
@@ -68,7 +83,7 @@ export async function reissueRunnerRuntimeToken(input: {
68
83
  expiredToken: string;
69
84
  orchestratorId: string;
70
85
  createdBy?: string;
71
- }): Promise<RuntimeTokenResult | { error: string }> {
86
+ }): Promise<RuntimeTokenResult | RunnerTokenMintRefusal> {
72
87
  const payload = verifyComponentTokenAllowExpired(input.expiredToken, { allowStaleRevoked: true });
73
88
  // #3133 — recovery hands off from the token's record, which holds its standing; a token without one recovers nothing.
74
89
  if (!payload?.jti) return { error: "invalid or revoked runner token" };
@@ -95,7 +110,8 @@ export async function reissueRunnerRuntimeToken(input: {
95
110
  constraints: payload.constraints,
96
111
  createdBy: input.createdBy ?? `remint:${payload.jti}`,
97
112
  };
98
- const handoff = await handoffTokenAsync({ jti: payload.jti, successor, recoverExpiredWithinSeconds: TOKEN_RECOVERY_WINDOW_SECONDS, createdBy: successor.createdBy });
113
+ const handoff = await handoffRunnerTokenAsync(payload.sub, { jti: payload.jti, successor, recoverExpiredWithinSeconds: TOKEN_RECOVERY_WINDOW_SECONDS, createdBy: successor.createdBy });
114
+ if (mintRateLimited(handoff)) return { error: "runner token mint rate limited", retryAfterSeconds: handoff.retryAfterSeconds };
99
115
  return handoff ?? { error: "invalid or revoked runner token" };
100
116
  }
101
117
 
@@ -122,7 +138,7 @@ function runnerGrantKey(scope: readonly string[] | undefined, constraints: Token
122
138
  * (current profile, lineage ceiling) and the presented token's launch identity. An identical grant is left
123
139
  * alone; otherwise the token is handed off like a renewal, so a lost response is recovered by a retry.
124
140
  */
125
- export async function remintRunnerRuntimeToken(auth: ComponentToken, createdBy: string): Promise<RunnerTokenRemint | { unchanged: true; jti: string } | { error: string }> {
141
+ export async function remintRunnerRuntimeToken(auth: ComponentToken, createdBy: string): Promise<RunnerTokenRemint | { unchanged: true; jti: string } | RunnerTokenMintRefusal> {
126
142
  const previous = auth.jti ? getToken(auth.jti) : null;
127
143
  const c = auth.constraints ?? {};
128
144
  const agentId = c.agents?.length === 1 ? c.agents[0] : undefined;
@@ -149,7 +165,8 @@ export async function remintRunnerRuntimeToken(auth: ComponentToken, createdBy:
149
165
  });
150
166
  if (token.constraints?.orchestrators?.includes("")) return { error: "the agent's host is unknown, so its host pin cannot be kept" };
151
167
  if (runnerGrantKey(previous.scope, previous.constraints) === runnerGrantKey(token.scope, token.constraints)) return { unchanged: true, jti: previous.jti };
152
- const handoff = await handoffTokenAsync({ jti: previous.jti, allowedProfileIds: ["provider-agent"], successor: token, createdBy });
168
+ const handoff = await handoffRunnerTokenAsync(auth.sub, { jti: previous.jti, allowedProfileIds: ["provider-agent"], successor: token, createdBy });
169
+ if (mintRateLimited(handoff)) return { error: "runner token mint rate limited", retryAfterSeconds: handoff.retryAfterSeconds };
153
170
  if (!handoff) return { error: "the presented token was already rotated" };
154
171
  const { record } = handoff;
155
172
  return {
@@ -175,8 +192,8 @@ export function issueOrchestratorRuntimeToken(input: {
175
192
  }
176
193
 
177
194
  /** #1870 S6c — the mint on the writer thread, for the async routes. */
178
- export function issueOrchestratorRuntimeTokenAsync(input: Parameters<typeof issueOrchestratorRuntimeToken>[0]): Promise<RuntimeTokenResult> {
179
- return createTokenAsync(orchestratorTokenSpec(input));
195
+ export async function issueOrchestratorRuntimeTokenAsync(input: Parameters<typeof issueOrchestratorRuntimeToken>[0]): Promise<RuntimeTokenResult> {
196
+ return (await createTokenAsync(orchestratorTokenSpec(input)));
180
197
  }
181
198
 
182
199
  function orchestratorTokenSpec(input: Parameters<typeof issueOrchestratorRuntimeToken>[0]): CreateTokenInput {
@@ -250,21 +267,15 @@ function runnerTokenSpec(input: RunnerRuntimeTokenInput): { token: CreateTokenIn
250
267
  const grant = authority.kind === "successor" ? successorGrant(input.agentId, profile)
251
268
  : { ...deriveRunnerGrant(profile, authority.kind === "delegated" ? { agentInitiated, callerScopes: authority.callerScopes, parentAgentId: input.spawnedBy, projectId: input.projectId, maxSpawnedAgents: input.maxSpawnedAgents } : { agentInitiated }), agentInitiated };
252
269
  const { canSpawn, maxSpawnedAgents, toolGroups, toolInclude, toolExclude } = grant;
253
- const selected = resolveRelayTools({ groups: toolGroups, include: toolInclude, exclude: toolExclude });
254
- for (const authoredName of toolInclude ?? []) {
255
- const name = registryToolName(authoredName);
256
- if (!selected.has(name)) continue;
257
- const needs = INCLUDED_TOOL_SCOPE_NEEDS[name];
258
- if (RELAY_TOOL_GROUPS.kernel!.includes(name) || (needs && !needs.some((need) => hasScope(grant.scope, need)))) {
259
- throw new Error(`relay.tools.include: ${name} requires ${needs?.join(" or ") ?? "kernel control scopes"}; profile ${profile} cannot grant that scope under this launch authority`);
260
- }
261
- }
270
+ // Includes choose the surface, not launch authority. MCP scope filtering hides unavailable tools (#3817).
262
271
  // #1570 — provider-split: a Codex worker eager-loads every listed tool schema every turn (no
263
272
  // client-native deferral), so trim its always-loaded MCP surface to the lean worker set. Classified
264
273
  // by explicit worker profile (not tool-group shape — reviewers share the groups but aren't workers).
265
274
  const toolAllowlist = toolInclude !== undefined || toolExclude !== undefined
266
275
  ? undefined : toolAllowlistForRunner(input.provider, profile);
267
- const hostPinned = grant.agentInitiated ? true : (input.hostPinned ?? hostPinForProfile(input.profile));
276
+ // #3804 — an agent-spawned child stays on its launch host, except a delegated sub-coordinator: its home host is
277
+ // often full, so it places spawns wherever its parent can unless the launch pinned it.
278
+ const hostPinned = grant.agentInitiated && !grant.delegated ? true : (input.hostPinned ?? hostPinForProfile(input.profile));
268
279
  const subject = input.policyName
269
280
  ? `runner:policy:${input.policyName}`
270
281
  : input.spawnRequestId
@@ -306,6 +317,7 @@ function runnerTokenSpec(input: RunnerRuntimeTokenInput): { token: CreateTokenIn
306
317
  : { kind: "root", ...(authority.kind === "delegated" ? { launcherScopes: authority.callerScopes } : {}), ...(profile ? { profile } : {}) } };
307
318
  }
308
319
 
320
+ /** Sync twin for in-process tests; every runtime launch path mints through the writer op below. */
309
321
  export function issueRunnerRuntimeToken(input: RunnerRuntimeTokenInput): RuntimeTokenResult {
310
322
  const spec = runnerTokenSpec(input);
311
323
  const issued = createToken(spec.token);
@@ -314,7 +326,12 @@ export function issueRunnerRuntimeToken(input: RunnerRuntimeTokenInput): Runtime
314
326
  return issued;
315
327
  }
316
328
 
317
- export function issueInteractiveRunnerRuntimeToken(input: {
329
+ export function issueRunnerRuntimeTokenAsync(input: RunnerRuntimeTokenInput): Promise<RuntimeTokenResult> {
330
+ const spec = runnerTokenSpec(input);
331
+ return createRunnerTokenAsync(spec.token, spec.launchFact ? { agentId: input.agentId, fact: spec.launchFact } : undefined);
332
+ }
333
+
334
+ export async function issueInteractiveRunnerRuntimeToken(input: {
318
335
  provider: string;
319
336
  cwd: string;
320
337
  runnerId: string;
@@ -326,9 +343,9 @@ export function issueInteractiveRunnerRuntimeToken(input: {
326
343
  * authorization, so it must ride the signature rather than the caller-writable agent card. */
327
344
  approvalMode?: SpawnApprovalMode;
328
345
  createdBy?: string;
329
- }): RuntimeTokenResult {
346
+ }): Promise<RuntimeTokenResult> {
330
347
  const agentId = input.agentId ?? input.runnerId;
331
- return createToken({
348
+ return (await createTokenAsync({
332
349
  profileId: "provider-interactive",
333
350
  sub: `runner:interactive:${input.host ?? "local"}:${input.runnerId}`,
334
351
  role: "provider",
@@ -343,22 +360,22 @@ export function issueInteractiveRunnerRuntimeToken(input: {
343
360
  canDelegate: false,
344
361
  },
345
362
  createdBy: input.createdBy ?? "interactive-runner",
346
- });
363
+ }));
347
364
  }
348
365
 
349
- export function issueMcpRuntimeToken(input: {
366
+ export async function issueMcpRuntimeToken(input: {
350
367
  sessionId: string;
351
368
  agentId?: string;
352
369
  targets?: string[];
353
370
  channels?: string[];
354
371
  createdBy?: string;
355
- }): RuntimeTokenResult {
372
+ }): Promise<RuntimeTokenResult> {
356
373
  const targets = input.targets?.length
357
374
  ? input.targets
358
375
  : input.agentId
359
376
  ? ["user", input.agentId]
360
377
  : undefined;
361
- return createToken({
378
+ return (await createTokenAsync({
362
379
  profileId: "mcp-client",
363
380
  sub: input.agentId ? `mcp:${input.agentId}:${input.sessionId}` : `mcp:session:${input.sessionId}`,
364
381
  role: "mcp",
@@ -369,16 +386,16 @@ export function issueMcpRuntimeToken(input: {
369
386
  canDelegate: false,
370
387
  },
371
388
  createdBy: input.createdBy ?? "runtime",
372
- });
389
+ }));
373
390
  }
374
391
 
375
- export function issueIntegrationRuntimeToken(input: {
392
+ export async function issueIntegrationRuntimeToken(input: {
376
393
  name: string;
377
394
  targets?: string[];
378
395
  channels?: string[];
379
396
  createdBy?: string;
380
- }): RuntimeTokenResult {
381
- return createToken({
397
+ }): Promise<RuntimeTokenResult> {
398
+ return (await createTokenAsync({
382
399
  profileId: "integration-client",
383
400
  sub: input.name,
384
401
  role: "integration",
@@ -389,11 +406,18 @@ export function issueIntegrationRuntimeToken(input: {
389
406
  canDelegate: false,
390
407
  },
391
408
  createdBy: input.createdBy ?? "runtime",
392
- });
409
+ }));
393
410
  }
394
411
 
395
412
  export function runnerRuntimeTokenEnv(input: RunnerRuntimeTokenInput): Record<string, string> {
396
- const issued = issueRunnerRuntimeToken(input);
413
+ return runnerTokenEnv(input, issueRunnerRuntimeToken(input));
414
+ }
415
+
416
+ export async function runnerRuntimeTokenEnvAsync(input: RunnerRuntimeTokenInput): Promise<Record<string, string>> {
417
+ return runnerTokenEnv(input, await issueRunnerRuntimeTokenAsync(input));
418
+ }
419
+
420
+ function runnerTokenEnv(input: RunnerRuntimeTokenInput, issued: RuntimeTokenResult): Record<string, string> {
397
421
  return writeChildEnv({}, {
398
422
  AGENT_RELAY_TOKEN: issued.token,
399
423
  AGENT_RELAY_TOKEN_JTI: issued.record.jti,
@@ -9,7 +9,7 @@ import { envFilePath } from "@humwick/sdk/child-env";
9
9
  export const SECRETS_TOOL_GROUP = "secrets";
10
10
  export const SECRETS_WRITE_SCOPE = "secrets:write";
11
11
  /** Built-in profiles whose default full surface includes the secrets group. */
12
- export const SECRETS_DEFAULT_PROFILES: ReadonlySet<string> = new Set(["coordinator", "ops-assistant"]);
12
+ export const SECRETS_DEFAULT_PROFILES: ReadonlySet<string> = new Set(["coordinator"]);
13
13
 
14
14
  export const UPLOAD_LINK_TTL_MS = 15 * 60_000;
15
15
  export const SECRET_UPLOAD_PATH_PREFIX = "/api/secrets/upload/";
@@ -27,13 +27,13 @@ let client: InfisicalBrokerClient | undefined;
27
27
 
28
28
  function brokerClient(): InfisicalBrokerClient {
29
29
  client ??= new InfisicalBrokerClient(secretsBrokerSettings(), {
30
- onLoginBlocked: (detail) => raiseOperatorAlarm({
30
+ onLoginBlocked: async (detail) => (await raiseOperatorAlarm({
31
31
  clientId: "secrets-broker:login-blocked",
32
32
  source: "secrets-broker",
33
33
  subject: "Secrets broker login blocked",
34
34
  detail: `${detail}. Fix the cause, then rotate or touch the credential files to re-arm.`,
35
35
  dedupeEvent: true,
36
- }),
36
+ })),
37
37
  });
38
38
  return client;
39
39
  }
package/src/security.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { retireHandedOffPredecessor, tokenRetirementPending } from "./db/token-standing-async";
1
2
  import { BRIDGED_CORS_HEADERS, relayHeader } from "@humwick/sdk";
2
3
  import { versionedPromptsEnabled } from "./versioned-prompts";
3
4
  import { serviceAccessRouteScope } from "./service-access/scope";
@@ -233,6 +234,8 @@ export function isOrchestratorRegistrationAuthorized(req: Request): boolean {
233
234
  }
234
235
 
235
236
  const SHARED_UI_ROUTE_SCOPES: Record<string, string> = {
237
+ "/api/orchestrators/bootstrap": "token:write",
238
+ "/api/orchestrators/bootstrap/exchange": "token:write",
236
239
  "/api/claude-api-budget/summary": "agent:read",
237
240
  "/api/claude-api-budget": "system:admin",
238
241
  "/api/stats": "stats:read",
@@ -240,6 +243,7 @@ const SHARED_UI_ROUTE_SCOPES: Record<string, string> = {
240
243
  "/api/metrics/hub": "stats:read",
241
244
  "/api/shipping/board": "stats:read",
242
245
  "/api/shipping/stats": "stats:read",
246
+ "/api/shipping/known-failures": "agent:read", // #3362 §11: read by builders' delivery gates
243
247
  "/api/stats/token-usage": "stats:read",
244
248
  // #3567 — every signed-in user reads their profile and sets their password (the handler requires a session or the admin token).
245
249
  "/api/users/me": "agent:read",
@@ -252,6 +256,15 @@ function sharedUiRouteScope(pathname: string, method: string): string | undefine
252
256
  if (/^\/api\/api-budgets\/[^/]+\/summary$/.test(pathname)) return "agent:read";
253
257
  if (/^\/api\/api-budgets\/[^/]+$/.test(pathname)) return "system:admin";
254
258
  if (/^\/api\/shipping\/incidents\/[^/]+\/abandon$/.test(pathname)) return "command:write";
259
+ if (pathname === "/api/teams/config") return method === "GET" ? "teams:read" : "settings:write:teams";
260
+ if (pathname.startsWith("/api/teams")) return method === "GET" ? "teams:read" : "teams:write";
261
+ if (pathname === "/api/decisions" && method === "POST") return "teams:write"; // #2914: filing = the relay_decision scope
262
+ if (pathname.startsWith("/api/decisions")) return method === "GET" ? "teams:read" : "message:send"; // #2885: answering = messaging the coordinator
263
+ if (pathname.startsWith("/api/blackboard")) return method === "GET" ? "blackboard:read" : "blackboard:write";
264
+ if (pathname.startsWith("/api/issue-associations")) return method === "GET" ? "issue:read" : "issue:write";
265
+ if (pathname.startsWith("/api/issue-activity")) return method === "GET" ? "issue:read" : "issue:write";
266
+ if (pathname.startsWith("/api/issue-lifecycle")) return method === "GET" ? "issue:read" : "issue:write";
267
+ if (pathname.startsWith("/api/issue-refs")) return method === "GET" ? "issue:read" : "issue:write";
255
268
  return Object.hasOwn(SHARED_UI_ROUTE_SCOPES, pathname) ? SHARED_UI_ROUTE_SCOPES[pathname] : undefined;
256
269
  }
257
270
 
@@ -266,8 +279,6 @@ export function requiredScopeFor(method: string, pathname: string): string | nul
266
279
  if (pathname === "/api/route") return "agent:read";
267
280
  if (pathname === "/api/notifications/preview") return "notifications:read";
268
281
  if (pathname === "/api/mcp") return "mcp:use";
269
- if (pathname === "/api/orchestrators/bootstrap/exchange") return "token:write";
270
- if (pathname === "/api/orchestrators/bootstrap") return "token:write";
271
282
  if (pathname.match(/^\/api\/orchestrators\/[^/]+\/logs\//)) return "logs:read";
272
283
  if (pathname.match(/^\/api\/orchestrators\/[^/]+\/terminal\/[^/]+\/input$/)) return "terminal:write";
273
284
  if (pathname.match(/^\/api\/orchestrators\/[^/]+\/terminal\//)) return "terminal:read";
@@ -323,16 +334,8 @@ export function requiredScopeFor(method: string, pathname: string): string | nul
323
334
  if (pathname.match(/^\/api\/provider-quotas\/[^/]+\/reset-fired$/)) return "quota:write";
324
335
  if (pathname === "/api/provider-quotas") return method === "GET" ? "agent:read" : "quota:write";
325
336
  if (pathname === "/api/routing-policy") return method === "GET" ? "agent:read" : "settings:write:routing";
326
- if (pathname === "/api/teams/config") return method === "GET" ? "teams:read" : "settings:write:teams";
327
337
  if (pathname === "/api/settings/prompts" || pathname.startsWith("/api/settings/prompts/")) return method === "GET" ? "agent:read" : "system:admin";
328
- if (pathname.startsWith("/api/teams")) return method === "GET" ? "teams:read" : "teams:write";
329
- if (pathname === "/api/decisions" && method === "POST") return "teams:write"; // #2914: filing = the relay_decision scope
330
- if (pathname.startsWith("/api/decisions")) return method === "GET" ? "teams:read" : "message:send"; // #2885: answering = messaging the coordinator
331
- if (pathname.startsWith("/api/blackboard")) return method === "GET" ? "blackboard:read" : "blackboard:write";
332
- if (pathname.startsWith("/api/issue-associations")) return method === "GET" ? "issue:read" : "issue:write";
333
- if (pathname.startsWith("/api/issue-activity")) return method === "GET" ? "issue:read" : "issue:write";
334
- if (pathname.startsWith("/api/issue-lifecycle")) return method === "GET" ? "issue:read" : "issue:write";
335
- if (pathname.startsWith("/api/issue-refs")) return method === "GET" ? "issue:read" : "issue:write";
338
+ if (/^\/api\/projects\/[^/]+\/profile-instructions(?:\/|$)/.test(pathname)) return method === "GET" ? "agent:read" : "agent:write";
336
339
  if (pathname.startsWith("/api/projects")) return method === "GET" ? "project:read" : "project:write";
337
340
  // Insights config (the feature toggle) stays admin-only via the default; only the
338
341
  // mechanical observation feed is writable by lower-privilege callers.
@@ -466,7 +469,6 @@ export function requiredComponentScopeFor(method: string, pathname: string): str
466
469
  if (pathname === "/api/routing-policy") {
467
470
  return method === "GET" ? "agent:read" : "settings:write:routing";
468
471
  }
469
- if (pathname === "/api/teams/config") return method === "GET" ? "teams:read" : "settings:write:teams";
470
472
  if (pathname === "/api/settings/prompts" || pathname.startsWith("/api/settings/prompts/")) {
471
473
  return method === "GET" ? "agent:read" : versionedPromptsEnabled() ? "agent:write" : "system:admin";
472
474
  }
@@ -477,16 +479,9 @@ export function requiredComponentScopeFor(method: string, pathname: string): str
477
479
  if (pathname.startsWith("/api/workflows")) return method === "GET" ? "task:read" : "task:write";
478
480
  if (pathname.startsWith("/api/orchestrators")) return method === "GET" ? "agent:read" : "command:write";
479
481
  if (pathname.startsWith("/api/plans")) return method === "GET" ? "plans:read" : "plans:write";
480
- if (pathname.startsWith("/api/teams")) return method === "GET" ? "teams:read" : "teams:write";
481
- if (pathname === "/api/decisions" && method === "POST") return "teams:write"; // #2914: filing = the relay_decision scope
482
- if (pathname.startsWith("/api/decisions")) return method === "GET" ? "teams:read" : "message:send"; // #2885: answering = messaging the coordinator
483
- if (pathname.startsWith("/api/blackboard")) return method === "GET" ? "blackboard:read" : "blackboard:write";
484
- if (pathname.startsWith("/api/issue-associations")) return method === "GET" ? "issue:read" : "issue:write";
485
- if (pathname.startsWith("/api/issue-activity")) return method === "GET" ? "issue:read" : "issue:write";
486
- if (pathname.startsWith("/api/issue-lifecycle")) return method === "GET" ? "issue:read" : "issue:write";
487
- if (pathname.startsWith("/api/issue-refs")) return method === "GET" ? "issue:read" : "issue:write";
488
482
  // Fail-closed default returns system:admin, so this case is load-bearing: without it
489
483
  // every /api/projects call from a scoped component token would 403-blackhole (#405).
484
+ if (/^\/api\/projects\/[^/]+\/profile-instructions(?:\/|$)/.test(pathname)) return method === "GET" ? "agent:read" : "agent:write";
490
485
  if (pathname.startsWith("/api/projects")) return method === "GET" ? "project:read" : "project:write";
491
486
  // The Runner posts the #184 context-gathering signal here (source:"server") via its
492
487
  // provider token. Without this case the path fell through to the system:admin default
@@ -546,7 +541,7 @@ export function verifyComponentToken(token: string, nowSeconds = Math.floor(Date
546
541
  const payload = parseBase64urlJson(payloadRaw);
547
542
  if (!isComponentToken(payload)) return null;
548
543
  if (payload.exp !== undefined && payload.exp <= nowSeconds) return null;
549
- if (payload.jti && isTokenRevoked(payload.jti)) return null;
544
+ if (payload.jti && (tokenRetirementPending(payload.jti) || isTokenRevoked(payload.jti, retireHandedOffPredecessor))) return null;
550
545
  return payload;
551
546
  }
552
547
 
@@ -1,69 +1,35 @@
1
1
  import { errMessage, isRecord, stringValue } from "@humwick/sdk";
2
- import {
3
- attachRecoveryCommand, carryingRecoveryObligations, closeRecoveryObligations, getAgent, insertContextReset, openRecoveryObligation, readsToCarry,
4
- sendMessageWithResult, writeTransaction, type ContextResetFact, type RecoveryObligation,
5
- } from "./db";
2
+ import { getAgent } from "./db";
3
+ import type { ContextResetFact } from "./db/context-reset-carry";
4
+ import { commandBoundary } from "./db/context-carry-write";
5
+ import { getGateway } from "./db/gateway";
6
+ import type { SendMessageResult } from "./db/messages";
6
7
  import { emitCommandEvent } from "./command-events";
7
8
  import { createSelfRestartCommandAsync } from "./services/restart-spawn";
8
- import { isContinuationSelfResumeCommand } from "./self-resume-command";
9
9
  import { emitNewMessage } from "./sse";
10
10
  import type { Command, Message } from "./types";
11
11
 
12
- // #3398 (docs/design/self-resume-carry.md) — the one owner of self-resume recovery. An accepted boundary
13
- // opens an obligation; every provider reset fact after the first capture sends the agent one unread
14
- // "Possible unread messages" list. At least once: a listed message may already be handled.
15
-
16
- const LISTED_IDS = 200;
17
- // The loss #3398 fixes is reads in the minutes before the self-care call or during it (#3523); earlier ones are in the saved state.
18
- const CARRY_MARGIN_MS = 10 * 60_000;
19
- // A failed or swept command proves nothing about its destructive input, so its list is only a fallback.
20
- const FALLBACK_STATUSES: ReadonlySet<Command["status"]> = new Set(["failed", "canceled", "timed_out", "rejected"]);
21
-
22
- /** Opens the obligation at accept, before the boundary command exists. */
23
- export function openContextRecovery(agentId: string, generation: number, now: number): void {
24
- openRecoveryObligation(agentId, generation, now);
12
+ export async function openContextRecovery(agentId: string, generation: number, now: number): Promise<void> {
13
+ await getGateway().write("contextCarry.open", { agentId, generation, now });
25
14
  }
26
-
27
- export function attachContextRecoveryCommand(agentId: string, generation: number, commandId: string): void {
28
- attachRecoveryCommand(agentId, generation, commandId);
15
+ export async function attachContextRecoveryCommand(agentId: string, generation: number, commandId: string): Promise<void> {
16
+ await getGateway().write("contextCarry.attach", { agentId, generation, commandId });
29
17
  }
30
-
31
- /** Ingests one reset fact. Idempotent per reset id; returns the list it sent, if any. */
32
- export function recordContextReset(fact: ContextResetFact): Message | null {
33
- const now = Date.now();
34
- return sendAndEmit(() => {
35
- if (!insertContextReset(fact, now)) return null;
36
- const carrying = carryingRecoveryObligations(fact.agentId);
37
- if (!carrying.length) return null;
38
- const result = sendCarry(fact.agentId, carrying, `${fact.resetId}:0`, { resetId: fact.resetId, kind: fact.kind });
39
- closeRecoveryObligations(fact.agentId, settledBy(fact, carrying), `reset:${fact.resetId}`, now);
40
- return result;
41
- });
18
+ export async function recordContextReset(fact: ContextResetFact): Promise<Message | null> {
19
+ return emitCarry(await getGateway().write("contextCarry.reset", { fact }) as unknown as SendMessageResult | null);
42
20
  }
43
-
44
- /**
45
- * Terminal-command hook (bus, HTTP and the lease sweep): a failed boundary still sends a list now, and
46
- * stays open. One whose destructive input reached the provider unsettled is replaced by a fresh process.
47
- */
48
- export function settleContextResetCarry(command: Command): Message | null {
49
- const boundary = FALLBACK_STATUSES.has(command.status) ? commandBoundary(command) : null;
50
- if (!boundary) return null;
51
- const message = sendAndEmit(() => {
52
- const carrying = carryingRecoveryObligations(boundary.agentId);
53
- if (!carrying.some((obligation) => obligation.open && obligation.generation === boundary.generation)) return null;
54
- const sent = sendCarry(boundary.agentId, carrying, `${command.id}:fallback`, { boundaryCommandId: command.id, status: command.status });
55
- // The runner aborted before any destructive input reached the provider: no reset can follow, so nothing is owed (#3441).
56
- if (isRecord(command.result) && command.result.destructiveInputSubmitted === false) {
57
- closeRecoveryObligations(boundary.agentId, [boundary.generation], `submit-aborted:${command.id}`, Date.now());
58
- }
59
- return sent;
60
- });
61
- if (command.status === "failed" && isRecord(command.result) && command.result.destructiveInputUnsettled === true) {
62
- void replaceUnsettledBoundary(command, boundary).catch((error) => console.error(`#3398 self-restart after unsettled ${command.type} ${command.id} failed: ${errMessage(error)}`));
21
+ export async function settleContextResetCarry(command: Command): Promise<Message | null> {
22
+ const result = emitCarry(await getGateway().write("contextCarry.settle", { command }) as unknown as SendMessageResult | null);
23
+ const boundary = commandBoundary(command);
24
+ if (boundary && command.status === "failed" && isRecord(command.result) && command.result.destructiveInputUnsettled === true) {
25
+ await replaceUnsettledBoundary(command, boundary);
63
26
  }
64
- return message;
27
+ return result;
28
+ }
29
+ function emitCarry(result: SendMessageResult | null): Message | null {
30
+ if (result && (result.created || result.updated)) emitNewMessage(result.message);
31
+ return result?.message ?? null;
65
32
  }
66
-
67
33
  /** The provider may still apply the input without any observable reset: a successor's registration is the reset instead. */
68
34
  async function replaceUnsettledBoundary(command: Command, boundary: { agentId: string; generation: number }): Promise<void> {
69
35
  const agent = getAgent(boundary.agentId);
@@ -74,58 +40,3 @@ async function replaceUnsettledBoundary(command: Command, boundary: { agentId: s
74
40
  const restart = await createSelfRestartCommandAsync(agent, boundary.generation, continuation, fullContextMessageId, "reset-unconfirmed", Date.now());
75
41
  emitCommandEvent(restart, "command.requested");
76
42
  }
77
-
78
- /** A reset settles only the boundary its provider evidence names; a replaced process settles all. */
79
- function settledBy(fact: ContextResetFact, carrying: RecoveryObligation[]): number[] {
80
- const open = carrying.filter((obligation) => obligation.open);
81
- if (fact.kind === "restart") return open.map((obligation) => obligation.generation);
82
- return open.filter((obligation) => fact.commandId !== undefined && obligation.commandId === fact.commandId).map((obligation) => obligation.generation);
83
- }
84
-
85
- function commandBoundary(command: Command): { agentId: string; generation: number } | null {
86
- const selfResume = isRecord(command.params.selfResume) ? command.params.selfResume : undefined;
87
- const generation = selfResume?.generation;
88
- if (typeof generation !== "number") return null;
89
- if (command.type === "agent.restart") {
90
- const agentId = stringValue(command.params.agentId);
91
- return agentId && isRecord(command.params.selfRestart) ? { agentId, generation } : null;
92
- }
93
- return isContinuationSelfResumeCommand(command) ? { agentId: command.target, generation } : null;
94
- }
95
-
96
- type SendResult = ReturnType<typeof sendMessageWithResult>;
97
-
98
- function sendAndEmit(write: () => SendResult | null): Message | null {
99
- const result = writeTransaction(write);
100
- if (result && (result.created || result.updated)) emitNewMessage(result.message);
101
- return result?.message ?? null;
102
- }
103
-
104
- // Floor: the earliest capture start minus the margin. No upper bound: a read after the reset is a duplicate, never a loss, and needs no clock comparison.
105
- function sendCarry(agentId: string, carrying: RecoveryObligation[], key: string, detail: Record<string, unknown>): SendResult | null {
106
- const ids = readsToCarry(agentId, Math.min(...carrying.map((obligation) => obligation.openedAt)) - CARRY_MARGIN_MS);
107
- if (!ids.length) return null;
108
- return sendMessageWithResult({
109
- from: "system",
110
- to: agentId,
111
- kind: "system",
112
- subject: "Possible unread messages",
113
- body: renderCarryBody(ids),
114
- payload: { selfResumeCarry: { ...detail, generations: carrying.map((obligation) => obligation.generation), messageIds: ids } },
115
- idempotencyKey: `self-resume-carry:${agentId}:${key}`,
116
- replyExpected: false,
117
- maxAgeSeconds: null,
118
- });
119
- }
120
-
121
- function renderCarryBody(ids: number[]): string {
122
- const listed = ids.slice(0, LISTED_IDS).map((id) => `#${id}`).join(" ");
123
- const rest = ids.length > LISTED_IDS ? `\n…and ${ids.length - LISTED_IDS} more, up to #${ids.at(-1)}; every id is in this message's payload.` : "";
124
- return [
125
- `Possible unread messages: ${ids.length} message${ids.length === 1 ? "" : "s"} reached you around your context reset, after or shortly before you saved your working state, so your current context may not hold them.`,
126
- "Check each one your working state does not already cover with relay_get_message <id>, and handle it. Some may be duplicates of work you have done.",
127
- "Messages you already handled may appear here, including the reset instruction itself: do not repeat a reset instruction found here.",
128
- "",
129
- `${listed}${rest}`,
130
- ].join("\n");
131
- }
@@ -1,5 +1,6 @@
1
+ import { updateCommandAsync } from "./commands-write";
1
2
  import { getContinuationEnvelope } from "./db/continuations";
2
- import { updateCommand } from "./commands-db";
3
+
3
4
  import type { Command } from "./types";
4
5
 
5
6
  /** #3662 — a continuation belongs to one generation; once a newer one is captured, an older boundary is
@@ -14,6 +15,6 @@ export function supersedingGeneration(boundary: Command): number | null {
14
15
 
15
16
  /** Cancel (never fail) the not-yet-started injects of a superseded boundary. Accepted/running ones are
16
17
  * already in the provider's hands and settle on their own. */
17
- export function cancelSupersededInjects(pendingAttemptIds: string[], current: number): void {
18
- for (const id of pendingAttemptIds) updateCommand(id, { status: "canceled", error: `superseded by continuation generation ${current}` });
18
+ export async function cancelSupersededInjects(pendingAttemptIds: string[], current: number): Promise<void> {
19
+ for (const id of pendingAttemptIds) (await updateCommandAsync(id, { status: "canceled", error: `superseded by continuation generation ${current}` }));
19
20
  }