@humwick/server 0.130.1 → 0.130.2

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 (437) hide show
  1. package/README.md +5 -0
  2. package/docs/guides/tools-administration.md +4 -0
  3. package/docs/guides/tools-coordination.md +1 -0
  4. package/docs/guides/tools-tasks.md +8 -0
  5. package/docs/guides/workflows.md +58 -0
  6. package/docs/openapi.json +414 -1
  7. package/package.json +8 -17
  8. package/public/assets/{MessageBubble-BWpoBjl4.js → MessageBubble-BWLqMGKG.js} +2 -2
  9. package/public/assets/{PlanGraphPanel-C0auck3n.js → PlanGraphPanel-3TlIQpjk.js} +2 -2
  10. package/public/assets/{TraceView-DBnOx7AQ.js → TraceView-Wimm0Czv.js} +2 -2
  11. package/public/assets/{VaultDecisionCard-0kp2oNBC.js → VaultDecisionCard-Bau_vNax.js} +2 -2
  12. package/public/assets/{activity-yLztXEBt.js → activity-CrSurn-r.js} +2 -2
  13. package/public/assets/{agent-lineage-BbJDR1dW.js → agent-lineage-CknAJKcb.js} +2 -2
  14. package/public/assets/agent-liveness-CaNwK0Zf.js +2 -0
  15. package/public/assets/{agent-name-CTZBrSD9.js → agent-name-DKbiIhBo.js} +2 -2
  16. package/public/assets/agent-profiles-DwF6EQ4R.js +2 -0
  17. package/public/assets/{agent-project-badge-9TqzUUYE.js → agent-project-badge-Diz4Sjjb.js} +2 -2
  18. package/public/assets/{agent-tools-D4n40pn8.js → agent-tools-CRhpRQza.js} +2 -2
  19. package/public/assets/{agent-type-icon-D6FUarOf.js → agent-type-icon-LrUEU3lB.js} +2 -2
  20. package/public/assets/{agents-BYDslkJc.js → agents-B-v66C-4.js} +2 -2
  21. package/public/assets/{analytics-B-XSbEMC.js → analytics-BqCb-LKi.js} +2 -2
  22. package/public/assets/{artifact-viewer-DdWIfV6M.js → artifact-viewer-kf4pGuAR.js} +2 -2
  23. package/public/assets/{artifacts-oBOqks-2.js → artifacts-D32zyw4Y.js} +2 -2
  24. package/public/assets/{artifacts-DPN1q4pA.js → artifacts-DJevXcvg.js} +2 -2
  25. package/public/assets/{automation-4KcRFXEu.js → automation-BpRajx_5.js} +2 -2
  26. package/public/assets/{backlog-Cw9xPTCF.js → backlog-D_UjTdzX.js} +2 -2
  27. package/public/assets/{busy-health-CTu32MZt.js → busy-health-N3VEh4ao.js} +2 -2
  28. package/public/assets/{channels-BiXzg1G9.js → channels-9jopungq.js} +2 -2
  29. package/public/assets/{chat-Ctk2qwvA.js → chat-CSXrTB3C.js} +2 -2
  30. package/public/assets/{code-preview-Bm1wWqAp.js → code-preview-p1NnmqK0.js} +2 -2
  31. package/public/assets/{connectors-C36ax4Vw.js → connectors-CZdqlDNL.js} +2 -2
  32. package/public/assets/{cosmos-Jj9LK2Wf.js → cosmos-BgdsE4dG.js} +2 -2
  33. package/public/assets/{crate-agent-H6S7-B9T.js → crate-agent-30aXTKva.js} +2 -2
  34. package/public/assets/{dependency-graph-Cd1E23wa.js → dependency-graph-B_jvw2GE.js} +2 -2
  35. package/public/assets/{deploys-Bwfq146q.js → deploys-DoN6bAb5.js} +2 -2
  36. package/public/assets/{display-CfO7rTuF.js → display-BrKWFGJz.js} +2 -2
  37. package/public/assets/{files-DhhZI2Ih.js → files-D6XEu8Ng.js} +2 -2
  38. package/public/assets/{fleet-B_rFEbnL.js → fleet-C7jQWbw2.js} +2 -2
  39. package/public/assets/{fleet-metrics-BkHP-P3R.js → fleet-metrics-BiDs3MLx.js} +2 -2
  40. package/public/assets/{formatted-body-Cm1RrzmN.js → formatted-body-CQBwc1fb.js} +3 -3
  41. package/public/assets/{formatted-body-impl-DQiOuOD1.js → formatted-body-impl-DyG0WsQS.js} +2 -2
  42. package/public/assets/{host-providers-dialog-CHqwXTov.js → host-providers-dialog-DKaW31dN.js} +2 -2
  43. package/public/assets/index-CRHep3M9.js +15 -0
  44. package/public/assets/index-MYAIwYTX.css +2 -0
  45. package/public/assets/{insights-fH1EL-qZ.js → insights-CzrtkpOE.js} +2 -2
  46. package/public/assets/{integrations-C5Oix6ng.js → integrations-aVsUmigt.js} +2 -2
  47. package/public/assets/{issue-ref-chip-ODyondIa.js → issue-ref-chip-BnSlM_95.js} +2 -2
  48. package/public/assets/{log-viewer-Cvfy6PW7.js → log-viewer-qe7Ee47Z.js} +2 -2
  49. package/public/assets/{maintenance-D8CDH5wZ.js → maintenance-NfjqFZAk.js} +2 -2
  50. package/public/assets/{managed-agents-egllbpij.js → managed-agents-BiH0HgaE.js} +2 -2
  51. package/public/assets/{markdown-preview-CYSFgVgK.js → markdown-preview-BixaT3Xr.js} +3 -3
  52. package/public/assets/{markdown-preview-impl-BteVIjX4.js → markdown-preview-impl-DNGlWIS3.js} +2 -2
  53. package/public/assets/{memory-C8WmXsyr.js → memory-DNsCl6UX.js} +2 -2
  54. package/public/assets/{messages-BzQdqlO6.js → messages-DopU1L1X.js} +2 -2
  55. package/public/assets/{orchestrators-B1HxzkNw.js → orchestrators-Cq7ckLQT.js} +2 -2
  56. package/public/assets/{overview-DCUnI4Z7.js → overview-C1DCTzzV.js} +2 -2
  57. package/public/assets/{pairs-ftCd2XcD.js → pairs-DE_m6rrE.js} +2 -2
  58. package/public/assets/{profile-icon-B2zH8DMH.js → profile-icon-B3rfh77F.js} +2 -2
  59. package/public/assets/project-profile-instructions-DQWZE0kA.js +2 -0
  60. package/public/assets/projects-Br2Bd2h1.js +2 -0
  61. package/public/assets/{prompt-settings-Bftq9czX.js → prompt-settings-BKvFsvGD.js} +2 -2
  62. package/public/assets/provider-display-DsuWMvVL.js +2 -0
  63. package/public/assets/{registry-DWCU5c8q.js → registry-Cw38_6gW.js} +2 -2
  64. package/public/assets/run-card-CpKqRbhg.js +2 -0
  65. package/public/assets/scroll-text-BKXS1ahr.js +2 -0
  66. package/public/assets/{secrets-C7GIUATz.js → secrets-DxI-vzSq.js} +2 -2
  67. package/public/assets/{service-access-settings-C3aujqTG.js → service-access-settings-D9s_VJbd.js} +2 -2
  68. package/public/assets/{settings-C6sZ9eBa.js → settings-CKZTVGIx.js} +2 -2
  69. package/public/assets/{shipping-Bu8p1gEw.js → shipping-B9YtnwtG.js} +2 -2
  70. package/public/assets/{stats-V9Z-GxUd.js → stats-DyUBKyWI.js} +2 -2
  71. package/public/assets/{status-dot-CVv0iGHL.js → status-dot-DYqlEUhJ.js} +2 -2
  72. package/public/assets/{store-BvtFdlGX.js → store-DcClXLH0.js} +3 -3
  73. package/public/assets/{tasks-CXU75HRF.js → tasks-Bh7Chr4-.js} +2 -2
  74. package/public/assets/{teams-BPf976zb.js → teams-bowI7qVY.js} +2 -2
  75. package/public/assets/{terminal-viewer-DE9BOe-8.js → terminal-viewer-BgVLHdsU.js} +3 -3
  76. package/public/assets/{terminal-viewer-impl-D04pjmGh.js → terminal-viewer-impl-Dz22UPy6.js} +2 -2
  77. package/public/assets/token-estimate-Co-Jdphh.js +2 -0
  78. package/public/assets/{use-agent-terminal-B1yR456R.js → use-agent-terminal-DSQQ-iY7.js} +2 -2
  79. package/public/assets/{use-decisions-D-S4tpDf.js → use-decisions-samMQhQf.js} +2 -2
  80. package/public/assets/use-project-list-59LheVP7.js +2 -0
  81. package/public/assets/{use-selectors-CnrAk2YP.js → use-selectors-BZa25xEB.js} +2 -2
  82. package/public/assets/{user-avatar-nBFIcR4M.js → user-avatar-DHxlvUvV.js} +2 -2
  83. package/public/assets/versioned-prompt-editor-BmED5DnJ.js +8 -0
  84. package/public/assets/{work-queue-TCjJxeT-.js → work-queue-CSvpuNLz.js} +2 -2
  85. package/public/assets/{workflow-marker-Cf3Hf2fN.js → workflow-marker-DAZcj5qt.js} +2 -2
  86. package/public/assets/{workflows-CXQX20Qj.js → workflows-DdmxRSyg.js} +2 -2
  87. package/public/assets/{workspaces-qSYzKYMA.js → workspaces-BxeKfVuF.js} +2 -2
  88. package/public/cosmos.html +4 -4
  89. package/public/index.html +31 -29
  90. package/runner/plugins/claude/.claude-plugin/plugin.json +1 -1
  91. package/runner/plugins/claude/hooks/gate-run-guard.provisioned.mjs +31 -1
  92. package/runner/src/adapters/claude-effort.ts +2 -4
  93. package/runner/src/adapters/codex-launch-config.ts +4 -5
  94. package/runner/src/adapters/codex.ts +1 -1
  95. package/runner/src/adapters/opencode-provider.ts +7 -22
  96. package/runner/src/adapters/opencode.ts +4 -4
  97. package/runner/src/agent-runner/credentials.ts +42 -12
  98. package/runner/src/agent-runner/inbox.ts +27 -0
  99. package/runner/src/agent-runner/lifecycle-milestones.ts +0 -2
  100. package/runner/src/bin/claude.ts +4 -0
  101. package/runner/src/bin/codex.ts +4 -0
  102. package/runner/src/bin/opencode.ts +4 -0
  103. package/runner/src/index.ts +5 -2
  104. package/runner/src/provider-setup.ts +34 -0
  105. package/runner/src/providers.ts +2 -1
  106. package/runner/src/runner-core.ts +18 -23
  107. package/runner/src/spawn-input.ts +2 -1
  108. package/runner/src/test-run-dedup.ts +59 -56
  109. package/scripts/cd-config.ts +8 -0
  110. package/scripts/gate-run-lease.ts +10 -7
  111. package/scripts/gate.sh +5 -1
  112. package/src/branch-land-notice.ts +93 -0
  113. package/src/branch-landed.ts +7 -76
  114. package/src/bus.ts +19 -20
  115. package/src/cd-deploy-notify.ts +30 -2
  116. package/src/cd-host-lag-notify.ts +7 -6
  117. package/src/ci/incidents.ts +2 -2
  118. package/src/ci/monitor.ts +5 -8
  119. package/src/ci/root-missing.ts +2 -7
  120. package/src/ci/transition-notify.ts +7 -39
  121. package/src/cli/cd-pauses.ts +19 -0
  122. package/src/cli/orchestrator.ts +1 -1
  123. package/src/cli/state.ts +2 -19
  124. package/src/cli/task-edit.ts +22 -0
  125. package/src/cli/task.ts +3 -1
  126. package/src/cli/workflow.ts +8 -2
  127. package/src/commands-db.ts +3 -3
  128. package/src/config-store-write.ts +13 -1
  129. package/src/config-store.ts +25 -14
  130. package/src/db/activity-async.ts +6 -1
  131. package/src/db/activity-write-ops.ts +12 -1
  132. package/src/db/activity.ts +1 -14
  133. package/src/db/agent-search.ts +1 -15
  134. package/src/db/agents-async.ts +52 -5
  135. package/src/db/agents-write-ops.ts +12 -3
  136. package/src/db/agents.ts +81 -54
  137. package/src/db/ci-incidents-async.ts +5 -5
  138. package/src/db/ci-incidents-write-ops.ts +2 -2
  139. package/src/db/command-row.ts +10 -2
  140. package/src/db/commands-list-query.ts +2 -0
  141. package/src/db/commands-spawn-read.ts +1 -1
  142. package/src/db/config-store-write-ops.ts +7 -2
  143. package/src/db/continuation-archives-async.ts +5 -0
  144. package/src/db/continuation-archives-write-ops.ts +7 -0
  145. package/src/db/continuations.ts +2 -2
  146. package/src/db/db-writer-worker.ts +8 -1
  147. package/src/db/deploy-events-async.ts +1 -0
  148. package/src/db/deploy-events-read-ops.ts +2 -1
  149. package/src/db/deploy-events.ts +35 -4
  150. package/src/db/hosts-registration.ts +10 -2
  151. package/src/db/hosts.ts +9 -6
  152. package/src/db/inbox.ts +0 -14
  153. package/src/db/index.ts +2 -0
  154. package/src/db/integrations-async.ts +8 -0
  155. package/src/db/integrations-ops.ts +15 -0
  156. package/src/db/integrations.ts +15 -21
  157. package/src/db/issue-lifecycle.ts +3 -4
  158. package/src/db/issue-refs-async.ts +20 -0
  159. package/src/db/issue-refs-write-ops.ts +29 -0
  160. package/src/db/issue-refs.ts +7 -8
  161. package/src/db/long-running-work.ts +2 -2
  162. package/src/db/main-connection-writes.ts +23 -2
  163. package/src/db/maintenance-job-reconcile.ts +61 -0
  164. package/src/db/maintenance-job-runs-async.ts +14 -0
  165. package/src/db/maintenance-job-write-ops.ts +9 -0
  166. package/src/db/mappers.ts +2 -14
  167. package/src/db/merge-lease.ts +1 -15
  168. package/src/db/migrations.ts +7 -15
  169. package/src/db/orchestrators.ts +4 -72
  170. package/src/db/pairs.ts +1 -13
  171. package/src/db/project-profile-instructions.ts +50 -0
  172. package/src/db/prompt-versions.ts +9 -2
  173. package/src/db/provider-config-history.ts +8 -3
  174. package/src/db/provider-model-seed.ts +34 -0
  175. package/src/db/read-op-marshaling-fixtures.ts +5 -0
  176. package/src/db/read-ops.ts +4 -0
  177. package/src/db/routing-policy.ts +2 -3
  178. package/src/db/schema.ts +9 -3
  179. package/src/db/spawn-delegation-state.ts +11 -4
  180. package/src/db/stats-async.ts +4 -3
  181. package/src/db/task-entity.ts +23 -2
  182. package/src/db/task-list.ts +3 -1
  183. package/src/db/tasks.ts +1 -17
  184. package/src/db/timer-ingress.ts +7 -1
  185. package/src/db/token-db-write-ops.ts +17 -0
  186. package/src/db/token-standing.ts +15 -11
  187. package/src/db/workflow-contact.ts +1 -1
  188. package/src/db/workflow-task-read-ops.ts +30 -0
  189. package/src/db/write-ops.ts +6 -0
  190. package/src/db/writer-gateway.ts +17 -11
  191. package/src/dispatch-availability.ts +10 -6
  192. package/src/ephemeral/{landing-ingress-proof-worker.ts → landing-ingress-proof.test-fixture.ts} +4 -2
  193. package/src/host/disk-alert.ts +121 -0
  194. package/src/lifecycle-manager.ts +3 -2
  195. package/src/maintenance/cd-watcher.ts +3 -3
  196. package/src/maintenance/critical-job-watchdog.ts +16 -17
  197. package/src/maintenance/index.ts +1 -0
  198. package/src/maintenance/jobs.ts +3 -2
  199. package/src/maintenance/scheduler.ts +84 -128
  200. package/src/maintenance/stalled-delivery-pager.ts +6 -5
  201. package/src/maintenance/workspaces.ts +1 -1
  202. package/src/managed-policy.ts +31 -27
  203. package/src/mcp/index.ts +5 -2
  204. package/src/mcp/output-descriptions.ts +8 -8
  205. package/src/mcp/presentation.ts +4 -4
  206. package/src/mcp/project-profile-instructions.ts +32 -0
  207. package/src/mcp/tool-groups.ts +1 -1
  208. package/src/mcp/tools-spawn.ts +4 -3
  209. package/src/mcp-agent-action.ts +1 -2
  210. package/src/mcp-issue-ref-tools.ts +12 -11
  211. package/src/mcp-maintenance-tools.ts +2 -2
  212. package/src/mcp-profile-trust-tools.ts +4 -4
  213. package/src/mcp-provider-catalog.ts +2 -2
  214. package/src/mcp-task-tools.ts +11 -5
  215. package/src/mcp-team-template-tools.ts +3 -3
  216. package/src/mcp-workflow-tools.ts +10 -3
  217. package/src/notification-types.ts +2 -1
  218. package/src/operator-alarm.ts +26 -11
  219. package/src/project-instructions.ts +4 -0
  220. package/src/project-profile-instruction-text.ts +6 -0
  221. package/src/project-profile-instructions.ts +20 -0
  222. package/src/provider-catalog-store.ts +3 -49
  223. package/src/provider-config-store.ts +12 -11
  224. package/src/provider-model-seed.ts +1 -18
  225. package/src/provider-quota-config-store.ts +5 -4
  226. package/src/provider-secrets.test-fixture.ts +3 -3
  227. package/src/recipe-runner.ts +2 -2
  228. package/src/repo-config-source.ts +10 -4
  229. package/src/routes/agent-profiles.ts +6 -6
  230. package/src/routes/agents-spawn.ts +1 -1
  231. package/src/routes/agents.ts +6 -6
  232. package/src/routes/commands-listing.ts +4 -0
  233. package/src/routes/commands.ts +2 -2
  234. package/src/routes/continuation-archives.ts +2 -2
  235. package/src/routes/index.ts +10 -1
  236. package/src/routes/integrations.ts +24 -50
  237. package/src/routes/issue-refs.ts +7 -7
  238. package/src/routes/orchestrator-bootstrap.ts +1 -1
  239. package/src/routes/orchestrator-host-registration.ts +2 -2
  240. package/src/routes/orchestrator-host-utilization.ts +3 -1
  241. package/src/routes/orchestrator-proxy.ts +2 -2
  242. package/src/routes/orchestrator.ts +2 -2
  243. package/src/routes/project-profile-instructions.ts +27 -0
  244. package/src/routes/project-trust.ts +2 -2
  245. package/src/routes/provider-config.ts +6 -6
  246. package/src/routes/provider-quota-config.ts +2 -2
  247. package/src/routes/settings.ts +5 -5
  248. package/src/routes/stats.ts +6 -6
  249. package/src/routes/task-http.ts +15 -1
  250. package/src/routes/task-issues.ts +11 -26
  251. package/src/routes/tasks.ts +22 -53
  252. package/src/routes/team-templates.ts +5 -5
  253. package/src/routes/teams-config.ts +2 -2
  254. package/src/routes/tokens.ts +12 -5
  255. package/src/routes/workflows.ts +20 -5
  256. package/src/routing-policy-normalize.ts +1 -2
  257. package/src/routing-step-defaults.ts +0 -2
  258. package/src/runner-token-mint-limit.ts +63 -0
  259. package/src/runtime-grant.ts +4 -2
  260. package/src/runtime-tokens.ts +39 -7
  261. package/src/security.ts +13 -20
  262. package/src/server-background.ts +1 -1
  263. package/src/server.ts +5 -2
  264. package/src/services/host-utilization.ts +23 -0
  265. package/src/services/idle-epics.ts +5 -6
  266. package/src/services/issue-lifecycle.ts +57 -61
  267. package/src/services/issue-refs.ts +9 -13
  268. package/src/services/kernel-timers-cutover-chaos-worker.ts +10 -7
  269. package/src/services/kernel-timers-ingress.ts +1 -1
  270. package/src/services/landed-ancestry.ts +19 -3
  271. package/src/services/memory-areas.ts +15 -51
  272. package/src/services/plan-ci-notice.ts +57 -0
  273. package/src/services/plan-ci-recovery.ts +2 -55
  274. package/src/services/plan-wake-digest.ts +1 -0
  275. package/src/services/profile-trust.ts +4 -3
  276. package/src/services/project-config-read.ts +70 -0
  277. package/src/services/project-profile-instructions.ts +54 -0
  278. package/src/services/provisioning-harness/budget-baseline.json +4 -4
  279. package/src/services/restart-spawn.ts +61 -49
  280. package/src/services/self-care-state.ts +2 -1
  281. package/src/services/self-effort.ts +5 -5
  282. package/src/services/send-message.ts +5 -1
  283. package/src/services/spawn-agent.ts +13 -2
  284. package/src/services/spawn-chain-inspector.ts +6 -13
  285. package/src/services/spawn-policy.ts +68 -0
  286. package/src/services/spawn-tree-cleanup.ts +2 -2
  287. package/src/services/task-dispatch.ts +3 -0
  288. package/src/services/task-state-reconcile.ts +6 -14
  289. package/src/services/team-templates.ts +9 -8
  290. package/src/services/transient-agent-reaper.ts +3 -1
  291. package/src/services/workflow-auto-start.ts +25 -13
  292. package/src/services/workflow-ci-main.ts +1 -1
  293. package/src/services/workflow-deferred-cleanup.ts +4 -2
  294. package/src/services/workflow-effect-driver.ts +2 -0
  295. package/src/services/workflow-effects.ts +18 -11
  296. package/src/services/workflow-land-notice.ts +10 -0
  297. package/src/services/workflow-pause-text.ts +43 -0
  298. package/src/services/workflow-reconcile.ts +13 -11
  299. package/src/services/workflow-run-view.ts +2 -0
  300. package/src/services/workflow-runs.ts +29 -13
  301. package/src/services/workflow-supervisor-state.ts +5 -0
  302. package/src/services/workflow-supervisor.ts +7 -3
  303. package/src/settings/registry.ts +1 -2
  304. package/src/spawn-command.ts +4 -4
  305. package/src/spawn-models.ts +10 -12
  306. package/src/spawn-placement.ts +1 -1
  307. package/src/spawn-targets.ts +1 -1
  308. package/src/startup-context-injection.ts +1 -0
  309. package/src/state-adoption/cd-cutover.ts +53 -7
  310. package/src/state-adoption/fleet-cutover.ts +35 -0
  311. package/src/state-adoption/fleet-plan.ts +36 -0
  312. package/src/state-adoption/index.ts +2 -2
  313. package/src/state-adoption/linux-plan.ts +2 -2
  314. package/src/state-adoption/linux.ts +2 -2
  315. package/src/state-adoption/macos-plan.ts +2 -2
  316. package/src/state-adoption/macos.ts +1 -1
  317. package/src/steward.ts +7 -6
  318. package/src/task-dispatch-live.ts +1 -1
  319. package/src/task-dispatcher.ts +1 -1
  320. package/src/teams-config-store.ts +4 -3
  321. package/src/token-db-write.ts +10 -0
  322. package/src/workspace-command-settle.ts +2 -1
  323. package/src/workspace-steward-wake.ts +2 -2
  324. package/node_modules/@humwick/kernel/LICENSE +0 -167
  325. package/node_modules/@humwick/kernel/async-entity-persistence.ts +0 -344
  326. package/node_modules/@humwick/kernel/async-event-log.ts +0 -107
  327. package/node_modules/@humwick/kernel/automations.pilot.ts +0 -147
  328. package/node_modules/@humwick/kernel/config.ts +0 -111
  329. package/node_modules/@humwick/kernel/contract.ts +0 -572
  330. package/node_modules/@humwick/kernel/control-authz.ts +0 -281
  331. package/node_modules/@humwick/kernel/control.ts +0 -645
  332. package/node_modules/@humwick/kernel/effects.ts +0 -493
  333. package/node_modules/@humwick/kernel/event-log.ts +0 -319
  334. package/node_modules/@humwick/kernel/http-transport.ts +0 -384
  335. package/node_modules/@humwick/kernel/identity-grammar.ts +0 -20
  336. package/node_modules/@humwick/kernel/identity.ts +0 -248
  337. package/node_modules/@humwick/kernel/index.ts +0 -28
  338. package/node_modules/@humwick/kernel/kernel-persistence.ts +0 -181
  339. package/node_modules/@humwick/kernel/landing-incident.ts +0 -306
  340. package/node_modules/@humwick/kernel/landing.ts +0 -953
  341. package/node_modules/@humwick/kernel/manifest-validation.ts +0 -460
  342. package/node_modules/@humwick/kernel/mcp-transport.ts +0 -109
  343. package/node_modules/@humwick/kernel/message-authority-chaos-worker.ts +0 -200
  344. package/node_modules/@humwick/kernel/message-authority.ts +0 -281
  345. package/node_modules/@humwick/kernel/module-host.ts +0 -722
  346. package/node_modules/@humwick/kernel/openapi-init.ts +0 -14
  347. package/node_modules/@humwick/kernel/package.json +0 -39
  348. package/node_modules/@humwick/kernel/persistence-schema.ts +0 -248
  349. package/node_modules/@humwick/kernel/persistence.ts +0 -510
  350. package/node_modules/@humwick/kernel/registry.ts +0 -60
  351. package/node_modules/@humwick/kernel/sqlite-kernel-persistence.ts +0 -499
  352. package/node_modules/@humwick/kernel/sqlite-module-host.ts +0 -87
  353. package/node_modules/@humwick/kernel/timers-chaos-worker.ts +0 -186
  354. package/node_modules/@humwick/kernel/timers.pilot.ts +0 -1411
  355. package/node_modules/@humwick/kernel/workflow-activation.ts +0 -25
  356. package/node_modules/@humwick/kernel/workflow-backstop.ts +0 -40
  357. package/node_modules/@humwick/kernel/workflow-cancel-tree.ts +0 -20
  358. package/node_modules/@humwick/kernel/workflow-chaos-worker.ts +0 -213
  359. package/node_modules/@humwick/kernel/workflow-composition.ts +0 -231
  360. package/node_modules/@humwick/kernel/workflow-container.ts +0 -72
  361. package/node_modules/@humwick/kernel/workflow-control.test-fixture.ts +0 -42
  362. package/node_modules/@humwick/kernel/workflow-control.ts +0 -178
  363. package/node_modules/@humwick/kernel/workflow-definition.ts +0 -507
  364. package/node_modules/@humwick/kernel/workflow-dispatch.ts +0 -60
  365. package/node_modules/@humwick/kernel/workflow-foreach.ts +0 -167
  366. package/node_modules/@humwick/kernel/workflow-journal-codec.ts +0 -339
  367. package/node_modules/@humwick/kernel/workflow-journal.ts +0 -922
  368. package/node_modules/@humwick/kernel/workflow-lane.ts +0 -48
  369. package/node_modules/@humwick/kernel/workflow-lease-owner.ts +0 -60
  370. package/node_modules/@humwick/kernel/workflow-recovery.test-fixture.ts +0 -19
  371. package/node_modules/@humwick/kernel/workflow-runtime.ts +0 -938
  372. package/node_modules/@humwick/kernel/workflow-script.ts +0 -11
  373. package/node_modules/@humwick/kernel/workflow-state.ts +0 -299
  374. package/node_modules/@humwick/kernel/workflow-step-commit.ts +0 -195
  375. package/node_modules/@humwick/kernel/workflow-transitions.ts +0 -317
  376. package/node_modules/@humwick/kernel/workflow-values.ts +0 -153
  377. package/node_modules/@humwick/kernel/workflow.pilot.ts +0 -376
  378. package/node_modules/@humwick/offload/LICENSE +0 -167
  379. package/node_modules/@humwick/offload/README.md +0 -57
  380. package/node_modules/@humwick/offload/dist/async-runner.d.ts +0 -18
  381. package/node_modules/@humwick/offload/dist/async-runner.d.ts.map +0 -1
  382. package/node_modules/@humwick/offload/dist/async-runner.js +0 -158
  383. package/node_modules/@humwick/offload/dist/async-runner.js.map +0 -1
  384. package/node_modules/@humwick/offload/dist/envelope.d.ts +0 -25
  385. package/node_modules/@humwick/offload/dist/envelope.d.ts.map +0 -1
  386. package/node_modules/@humwick/offload/dist/envelope.js +0 -80
  387. package/node_modules/@humwick/offload/dist/envelope.js.map +0 -1
  388. package/node_modules/@humwick/offload/dist/fixtures/worker-task.d.ts +0 -10
  389. package/node_modules/@humwick/offload/dist/fixtures/worker-task.d.ts.map +0 -1
  390. package/node_modules/@humwick/offload/dist/fixtures/worker-task.js +0 -59
  391. package/node_modules/@humwick/offload/dist/fixtures/worker-task.js.map +0 -1
  392. package/node_modules/@humwick/offload/dist/index.d.ts +0 -5
  393. package/node_modules/@humwick/offload/dist/index.d.ts.map +0 -1
  394. package/node_modules/@humwick/offload/dist/index.js +0 -5
  395. package/node_modules/@humwick/offload/dist/index.js.map +0 -1
  396. package/node_modules/@humwick/offload/dist/subprocess-runner.d.ts +0 -62
  397. package/node_modules/@humwick/offload/dist/subprocess-runner.d.ts.map +0 -1
  398. package/node_modules/@humwick/offload/dist/subprocess-runner.js +0 -295
  399. package/node_modules/@humwick/offload/dist/subprocess-runner.js.map +0 -1
  400. package/node_modules/@humwick/offload/dist/types.d.ts +0 -111
  401. package/node_modules/@humwick/offload/dist/types.d.ts.map +0 -1
  402. package/node_modules/@humwick/offload/dist/types.js +0 -176
  403. package/node_modules/@humwick/offload/dist/types.js.map +0 -1
  404. package/node_modules/@humwick/offload/dist/worker-pool.d.ts +0 -23
  405. package/node_modules/@humwick/offload/dist/worker-pool.d.ts.map +0 -1
  406. package/node_modules/@humwick/offload/dist/worker-pool.js +0 -435
  407. package/node_modules/@humwick/offload/dist/worker-pool.js.map +0 -1
  408. package/node_modules/@humwick/offload/dist/worker-runtime.d.ts +0 -2
  409. package/node_modules/@humwick/offload/dist/worker-runtime.d.ts.map +0 -1
  410. package/node_modules/@humwick/offload/dist/worker-runtime.js +0 -27
  411. package/node_modules/@humwick/offload/dist/worker-runtime.js.map +0 -1
  412. package/node_modules/@humwick/offload/dist/worker.d.ts +0 -5
  413. package/node_modules/@humwick/offload/dist/worker.d.ts.map +0 -1
  414. package/node_modules/@humwick/offload/dist/worker.js +0 -1
  415. package/node_modules/@humwick/offload/dist/worker.js.map +0 -1
  416. package/node_modules/@humwick/offload/package.json +0 -42
  417. package/node_modules/@humwick/offload/src/async-runner.ts +0 -170
  418. package/node_modules/@humwick/offload/src/envelope.ts +0 -92
  419. package/node_modules/@humwick/offload/src/fixtures/worker-task.ts +0 -49
  420. package/node_modules/@humwick/offload/src/index.ts +0 -4
  421. package/node_modules/@humwick/offload/src/subprocess-runner.ts +0 -334
  422. package/node_modules/@humwick/offload/src/types.ts +0 -235
  423. package/node_modules/@humwick/offload/src/worker-pool.ts +0 -463
  424. package/node_modules/@humwick/offload/src/worker-runtime.ts +0 -32
  425. package/node_modules/@humwick/offload/src/worker.ts +0 -5
  426. package/public/assets/agent-liveness-DyqxfB-t.js +0 -2
  427. package/public/assets/agent-profiles-BpI_jTxq.js +0 -2
  428. package/public/assets/index-B7ZerHLY.css +0 -2
  429. package/public/assets/index-BU3uWo2t.js +0 -15
  430. package/public/assets/projects-B_lmcqfO.js +0 -2
  431. package/public/assets/provider-display-DbLWpP3j.js +0 -2
  432. package/public/assets/run-card-CO_bguQf.js +0 -2
  433. package/public/assets/use-project-list-B-T2Bnnn.js +0 -2
  434. package/public/assets/versioned-prompt-editor-Diu8BIaM.js +0 -8
  435. package/runner/src/gate-run-lease-probe.ts +0 -38
  436. package/src/db/claude-catalog-reconcile.ts +0 -27
  437. package/src/routing-model-aliases.ts +0 -21
@@ -4,7 +4,8 @@ import { hostname } from "node:os";
4
4
  import { join } from "node:path";
5
5
  import { ValidationError, listOrchestrators } from "./db";
6
6
  import { isSecretEnvKey } from "./db/provider-config-secrets";
7
- import { getConfig, listConfig, setConfig } from "./config-store";
7
+ import { getConfig, listConfig } from "./config-store";
8
+ import { setConfigAsync } from "./config-store-write";
8
9
  import { localOrchestratorIdFromEnv, providerConfigHomeFromEnv } from "./config";
9
10
  import { cleanString, cleanStringArray, optionalEnum } from "./validation";
10
11
  import { emitConfigChanged } from "./sse";
@@ -90,11 +91,11 @@ export function listProviderConfigEntries(host = defaultProviderConfigHost()): R
90
91
  ) as Record<SpawnProvider, ProviderConfigEntry>;
91
92
  }
92
93
 
93
- export function setProviderConfig(
94
+ export async function setProviderConfigAsync(
94
95
  provider: string,
95
96
  value: unknown,
96
97
  opts: { host?: string; updatedBy?: string } = {},
97
- ): ProviderConfigEntry {
98
+ ): Promise<ProviderConfigEntry> {
98
99
  const cleanProvider = normalizeProviderConfigProvider(provider);
99
100
  const host = normalizeProviderConfigHost(opts.host ?? defaultProviderConfigHost());
100
101
  const normalized = cleanProviderConfig(cleanProvider, resolveMaskedEnvSentinels(value, host, cleanProvider));
@@ -102,7 +103,7 @@ export function setProviderConfig(
102
103
  ensureProviderConfigDescriptors([key]);
103
104
  const validation = validateSettingValue(PROVIDER_CONFIG_NAMESPACE, key, normalized);
104
105
  if (!validation.valid) throw new ValidationError(validation.errors.join("; "));
105
- return setConfig(PROVIDER_CONFIG_NAMESPACE, key, normalized, opts.updatedBy) as ProviderConfigEntry;
106
+ return await setConfigAsync(PROVIDER_CONFIG_NAMESPACE, key, normalized, opts.updatedBy) as ProviderConfigEntry;
106
107
  }
107
108
 
108
109
  export function providerConfigPublic(entry: ProviderConfigEntry, opts: { maskEnv?: boolean } = {}): Record<string, unknown> {
@@ -138,11 +139,11 @@ export function providerConfigPublic(entry: ProviderConfigEntry, opts: { maskEnv
138
139
  * This is the server-authority write path: callers are in-process (local migration
139
140
  * or the orchestrator command-bus result handler), so no HTTP scope is required.
140
141
  */
141
- export function seedProviderConfigs(
142
+ export async function seedProviderConfigsAsync(
142
143
  host: string,
143
144
  rawByProvider: Record<string, unknown>,
144
145
  opts: { legacyHost?: string } = {},
145
- ): ProviderConfigEntry[] {
146
+ ): Promise<ProviderConfigEntry[]> {
146
147
  const seeded: ProviderConfigEntry[] = [];
147
148
  const cleanHost = normalizeProviderConfigHost(host);
148
149
  const legacyHost = opts.legacyHost ? normalizeProviderConfigHost(opts.legacyHost) : undefined;
@@ -159,7 +160,7 @@ export function seedProviderConfigs(
159
160
  // still validates; the relay owns the schema, the reporter stays dumb.
160
161
  const value = legacy?.value ?? { ...providerConfigDefaults(provider), ...(isRecord(raw) ? raw : {}) };
161
162
  try {
162
- const entry = setProviderConfig(provider, value, { host: cleanHost, updatedBy: `migration:${cleanHost}` });
163
+ const entry = await setProviderConfigAsync(provider, value, { host: cleanHost, updatedBy: `migration:${cleanHost}` });
163
164
  emitConfigChanged(entry.namespace, entry.key, entry.version);
164
165
  seeded.push(entry);
165
166
  } catch {
@@ -174,16 +175,16 @@ export function seedProviderConfigs(
174
175
  * owns the stable-id/legacy-hostname resolution together so command routes do
175
176
  * not re-parse or accidentally bypass the migration authority rules.
176
177
  */
177
- export function seedMigratedProviderConfigs(result: unknown): { host: string; seeded: ProviderConfigEntry[] } | null {
178
+ export async function seedMigratedProviderConfigsAsync(result: unknown): Promise<{ host: string; seeded: ProviderConfigEntry[] } | null> {
178
179
  if (!isRecord(result)) return null;
179
180
  const host = cleanString(result.host, "result.host", { max: 120 });
180
181
  const hostname = cleanString(result.hostname, "result.hostname", { max: 120 });
181
182
  const configs = isRecord(result.configs) ? result.configs : undefined;
182
183
  if (!host || !configs) return null;
183
- return { host, seeded: seedProviderConfigs(host, configs, { legacyHost: hostname }) };
184
+ return { host, seeded: await seedProviderConfigsAsync(host, configs, { legacyHost: hostname }) };
184
185
  }
185
186
 
186
- export function migrateLocalProviderConfigs(home = humwickHome(), host = defaultProviderConfigHost()): ProviderConfigEntry[] {
187
+ export async function migrateLocalProviderConfigsAsync(home = humwickHome(), host = defaultProviderConfigHost()): Promise<ProviderConfigEntry[]> {
187
188
  const dir = join(home, "providers");
188
189
  if (!existsSync(dir)) return [];
189
190
  const raw: Record<string, unknown> = {};
@@ -192,7 +193,7 @@ export function migrateLocalProviderConfigs(home = humwickHome(), host = default
192
193
  if (!VALID_PROVIDER_CONFIGS.includes(provider as SpawnProvider)) continue;
193
194
  raw[provider] = loadLocalProviderConfig(provider, home);
194
195
  }
195
- return seedProviderConfigs(host, raw);
196
+ return seedProviderConfigsAsync(host, raw);
196
197
  }
197
198
 
198
199
  function normalizeProviderConfigHost(host: string): string {
@@ -1,18 +1 @@
1
- import { getConfig, setConfig } from "./config-store";
2
- import { seedProviderModelOverrides } from "./provider-catalog-store";
3
- import { reconcileClaudeCatalogSeeds } from "./db/claude-catalog-reconcile";
4
- import { VERSION } from "./config";
5
- import { errMessage } from "@humwick/sdk";
6
-
7
- // Stamp only after the transactional seed succeeds so a failure retries next boot.
8
- export function reconcileProviderModelSeed(): void {
9
- try {
10
- reconcileClaudeCatalogSeeds();
11
- const stamp = `seed:${VERSION}`;
12
- if (getConfig<string>("system", "provider-model-seed-version")?.value === stamp) return;
13
- seedProviderModelOverrides(stamp);
14
- setConfig("system", "provider-model-seed-version", stamp, "server-startup");
15
- } catch (err) {
16
- console.warn(`[provider-model-seed] skipped: ${errMessage(err)}`);
17
- }
18
- }
1
+ export { reconcileProviderModelSeed, seedProviderModelOverrides } from "./db/provider-model-seed";
@@ -9,7 +9,8 @@
9
9
  // provider *spawn* config (provider-config-store.ts) by design — different scope,
10
10
  // different cardinality.
11
11
  import { ValidationError } from "./db";
12
- import { getConfig, listConfig, setConfig } from "./config-store";
12
+ import { getConfig, listConfig } from "./config-store";
13
+ import { setConfigAsync } from "./config-store-write";
13
14
  import { emitConfigChanged } from "./sse";
14
15
  import {
15
16
  DEFAULT_PROVIDER_QUOTA_CONFIG,
@@ -47,14 +48,14 @@ export function listProviderQuotaConfigs(): ProviderQuotaConfigMap {
47
48
  * clamped to 5m–15m, unset fields defaulted), so a partial body still validates.
48
49
  * Emits `config.changed` so the orchestrator + dashboard pick it up live.
49
50
  */
50
- export function setProviderQuotaConfig(
51
+ export async function setProviderQuotaConfigAsync(
51
52
  provider: string,
52
53
  value: unknown,
53
54
  opts: { updatedBy?: string } = {},
54
- ): ProviderQuotaConfig {
55
+ ): Promise<ProviderQuotaConfig> {
55
56
  const clean = assertValidProvider(provider);
56
57
  const normalized = normalizeProviderQuotaConfig(value);
57
- const entry = setConfig(PROVIDER_QUOTA_CONFIG_NAMESPACE, clean, normalized, opts.updatedBy);
58
+ const entry = await setConfigAsync(PROVIDER_QUOTA_CONFIG_NAMESPACE, clean, normalized, opts.updatedBy);
58
59
  emitConfigChanged(entry.namespace, entry.key, entry.version);
59
60
  return normalized;
60
61
  }
@@ -1,5 +1,5 @@
1
1
  import { getDb } from "./db";
2
- import { setProviderConfig } from "./provider-config-store";
2
+ import { setProviderConfigAsync } from "./provider-config-store";
3
3
 
4
4
  // #3402 — fake values under every key name the hub's central provider config holds, plus one no masking
5
5
  // list knows, so a test proves masking follows the configured values rather than key names.
@@ -25,9 +25,9 @@ export function leakedProviderSecrets(text: string): string[] {
25
25
  }
26
26
 
27
27
  /** Seeds the central provider config of `host` and returns its rows the way `sqlite3 ... select` prints them. */
28
- export function seedProviderSecrets(host: string): string {
28
+ export async function seedProviderSecrets(host: string): Promise<string> {
29
29
  for (const [provider, env] of Object.entries(PROVIDER_SECRET_ENV)) {
30
- setProviderConfig(provider, { command: provider, env: { ...env, OPENCODE_CONFIG: "/srv/opencode.json" } }, { host });
30
+ await setProviderConfigAsync(provider, { command: provider, env: { ...env, OPENCODE_CONFIG: "/srv/opencode.json" } }, { host });
31
31
  }
32
32
  return (getDb().query("SELECT namespace, key, value FROM config WHERE namespace = 'provider-config'").all() as Array<Record<string, string>>)
33
33
  .map((row) => `${row.namespace}|${row.key}|${row.value}`).join("\n");
@@ -15,7 +15,7 @@ import {
15
15
  validateRecipeArtifactRefsAsync,
16
16
  } from "./recipe-async";
17
17
  import type { AttachmentRef, Command, RecipeInstance } from "./types";
18
- import { SYSTEM_LAUNCH, runnerRuntimeTokenEnv } from "./runtime-tokens";
18
+ import { SYSTEM_LAUNCH, runnerRuntimeTokenEnvAsync } from "./runtime-tokens";
19
19
  import { generateSpawnAgentId } from "./services/spawn-identity";
20
20
 
21
21
  interface StartRecipeInput {
@@ -114,7 +114,7 @@ export async function startRecipe(input: StartRecipeInput): Promise<StartRecipeR
114
114
  env: {
115
115
  ...(agent.env ?? {}),
116
116
  ...(attachments.length ? writeChildEnv({}, { AGENT_RELAY_RECIPE_ARTIFACTS: JSON.stringify(attachments) }) : {}),
117
- ...runnerRuntimeTokenEnv({ authority: SYSTEM_LAUNCH,
117
+ ...await runnerRuntimeTokenEnvAsync({ authority: SYSTEM_LAUNCH,
118
118
  agentId,
119
119
  orchestratorId: orchestrator.id,
120
120
  cwd,
@@ -6,7 +6,8 @@
6
6
  import { dirname, resolve } from "node:path";
7
7
  import { isRecord, stringValue } from "@humwick/sdk";
8
8
  import { isTrustedOrchestratorApiUrl, relayAuthHeaders } from "./config";
9
- import { getConfig, setConfig } from "./config-store";
9
+ import { getConfig } from "./config-store";
10
+ import { setConfigAsync } from "./config-store-write";
10
11
  import { listOrchestrators, reportedRepoRootForCwd } from "./db";
11
12
  import { hostIsRelayHost } from "./relay-host-locality";
12
13
  import { normalizeHostToken, parseJson, sameHostIdentity } from "./utils";
@@ -70,11 +71,16 @@ export function hostRepoConfigSource<T>(spec: HostRepoConfigSpec<T>): HostRepoCo
70
71
  return null;
71
72
  }
72
73
 
73
- function writeCached(host: string, keys: readonly string[], found: RepoConfigSource<T> | null): void {
74
+ /** #1870 S7: writes on the writer thread, and only when the answer changed. `at` is evidence, not a
75
+ * TTL, so re-stamping an identical answer on every read only bumped the version and history. */
76
+ async function writeCached(host: string, keys: readonly string[], found: RepoConfigSource<T> | null): Promise<void> {
74
77
  const at = Date.now();
78
+ const answer = JSON.stringify(found);
75
79
  for (const key of keys) {
76
80
  try {
77
- setConfig<CachedRepoConfigSource<T>>(spec.cacheNamespace, cacheKey(host, key), { found, at }, spec.cacheNamespace);
81
+ const current = getConfig<CachedRepoConfigSource<T>>(spec.cacheNamespace, cacheKey(host, key))?.value;
82
+ if (current?.at && JSON.stringify(current.found) === answer) continue;
83
+ await setConfigAsync<CachedRepoConfigSource<T>>(spec.cacheNamespace, cacheKey(host, key), { found, at }, spec.cacheNamespace);
78
84
  } catch {
79
85
  // The cache is an optimization for the sync paths; failing to record it must never fail a caller.
80
86
  }
@@ -149,7 +155,7 @@ export function hostRepoConfigSource<T>(spec: HostRepoConfigSpec<T>): HostRepoCo
149
155
  if (hostIsRelayHost(host)) return { known: true, found: await spec.findLocalAsync(cwd) };
150
156
  const read = await readFromHost(cwd, host!);
151
157
  if (read.known) {
152
- writeCached(host!, cacheWriteKeys(cwd, read.found, opts.alsoCacheFor), read.found);
158
+ await writeCached(host!, cacheWriteKeys(cwd, read.found, opts.alsoCacheFor), read.found);
153
159
  return read;
154
160
  }
155
161
  return cachedLookup(host!, cwd);
@@ -1,12 +1,12 @@
1
1
  import { PromptVersionConflictError } from "../prompt-version-errors";
2
2
  import { versionedPromptsEnabled } from "../versioned-prompts";
3
3
  import { promptActor } from "../services/prompt-version-writer";
4
- import { setConfigAsync } from "../config-store-write";
4
+ import { deleteAgentProfileAsync, setAgentProfileAsync, setConfigAsync } from "../config-store-write";
5
5
  import { memoryRetirementMessage } from "../memory-retirement";
6
6
  // Auto-split from routes.ts (#299). Domain: agent-profiles.
7
7
  import { ValidationError, withResolvedProvisioningAsync } from "../db";
8
8
  import { cleanString, optionalEnum } from "../validation";
9
- import { deleteAgentProfile, getAgentProfile, listAgentProfiles, resolveAgentProfileKey, setAgentProfile, validateAgentProfile } from "../config-store";
9
+ import { getAgentProfile, listAgentProfiles, resolveAgentProfileKey, validateAgentProfile } from "../config-store";
10
10
  import { RELAY_TOOL_GROUPS } from "../mcp";
11
11
  import { emitConfigChanged } from "../sse";
12
12
  import { error, isAdminRequest, json, normalizeConfigPathParam, parseBody, type Handler } from "./_shared";
@@ -140,8 +140,8 @@ export const putAgentProfileRoute: Handler = async (req, params) => {
140
140
  return json(saved);
141
141
  }
142
142
  const profile = existing?.value.builtIn && isAdminRequest(req)
143
- ? setAgentProfile({ ...parsed.body, name } as AgentProfile, updatedBy, { overrideBuiltIn: true })
144
- : setAgentProfile({ ...parsed.body, name } as AgentProfile, updatedBy);
143
+ ? await setAgentProfileAsync({ ...parsed.body, name } as AgentProfile, updatedBy, { overrideBuiltIn: true })
144
+ : await setAgentProfileAsync({ ...parsed.body, name } as AgentProfile, updatedBy);
145
145
  emitConfigChanged(profile.namespace, profile.key, profile.version);
146
146
  return json(profile, existing ? 200 : profile.version === 1 ? 201 : 200);
147
147
  } catch (e) {
@@ -151,14 +151,14 @@ export const putAgentProfileRoute: Handler = async (req, params) => {
151
151
  }
152
152
  };
153
153
 
154
- export const deleteAgentProfileRoute: Handler = (req, params) => {
154
+ export const deleteAgentProfileRoute: Handler = async (req, params) => {
155
155
  try {
156
156
  const name = normalizeConfigPathParam(params.name, "name");
157
157
  const existing = getAgentProfile(name);
158
158
  if (!existing) return error(memoryRetirementMessage(name) ?? "agent profile not found", 404);
159
159
  const updatedBy = versionedPromptsEnabled() ? promptActor(req) : cleanString(new URL(req.url).searchParams.get("updatedBy") ?? undefined, "updatedBy", { max: 200 });
160
160
  if (existing.value.builtIn && !isAdminRequest(req)) return error("built-in agent profiles are managed by Relay", 400);
161
- deleteAgentProfile(name, updatedBy, { resetBuiltInOverride: existing.value.builtIn });
161
+ await deleteAgentProfileAsync(name, updatedBy, { resetBuiltInOverride: existing.value.builtIn });
162
162
  emitConfigChanged(existing.namespace, existing.key, existing.version + 1);
163
163
  return json({ ok: true });
164
164
  } catch (e) {
@@ -208,7 +208,7 @@ export const postAgentSpawn: Handler = async (req) => {
208
208
  // strip the heavy inlined provisioning file contents from the echoed-back summary.
209
209
  return json({
210
210
  ok: true, spawnRequestId: result.spawnRequestId, harnessSubagents: result.harnessSubagents, orchestratorId: result.orchestratorId, placementReason: result.placementReason, provider: result.provider, command: summarizeSpawnCommandForCaller(result.command),
211
- ...(result.task ? { task: result.task } : {}), ...(result.warnings ? { warnings: result.warnings } : {}), ...(result.dispatchDecision ? { dispatchDecision: result.dispatchDecision } : {}), ...(workflow.reason ? { workflow: { started: false, reason: workflow.reason } } : {}),
211
+ ...(result.task ? { task: result.task } : {}), ...(result.warnings ? { warnings: result.warnings } : {}), ...(result.spawnPolicy ? { spawnPolicy: result.spawnPolicy } : {}), ...(result.dispatchDecision ? { dispatchDecision: result.dispatchDecision } : {}), ...(workflow.reason ? { workflow: { started: false, reason: workflow.reason } } : {}),
212
212
  }, 202);
213
213
  } catch (e) {
214
214
  if (e instanceof McpAuthError) return error(e.message, 403);
@@ -2,7 +2,7 @@
2
2
  import { messageViewerForRequest, visibleMessages } from "./message-viewer";
3
3
  import { attachPrincipal, attachPrincipals } from "../agent-principal";
4
4
  import { VALID_AGENT_STATUSES, agentSessionStatus, auditEvent, canViewAgentRoute, error, json, normalizeAgentSessionGuard, parseBody, parseId, parseQueryInt, visibleAgentIdsForRequest, type Handler } from "./_shared";
5
- import { ValidationError, deleteAgentAsync, getAgent, getAgentAsync, getAgentIdentityAsync, getAgentQuotaSnapshotsAsync, getAgentTimelineAsync, getCrashReport, recordHeartbeat, listAgentChatHistoryAsync, listAgents, listAgentsAsync, listArtifactsForEntityAsync, listContextSnapshotsAsync, listPendingReplyObligationsAsync, markReadyAsync, searchAgentsAsync, setLabelAsync, setStatusAsync, setTagsAsync, validateAgentSession } from "../db";
5
+ import { ValidationError, deleteAgentAsync, getAgent, getAgentAsync, getAgentIdentityAsync, getAgentQuotaSnapshotsAsync, getAgentTimelineAsync, getCrashReport, recordHeartbeatAsync, listAgentChatHistoryAsync, listAgents, listAgentsAsync, listArtifactsForEntityAsync, listContextSnapshotsAsync, listPendingReplyObligationsAsync, markReadyAsync, searchAgentsAsync, setLabelAsync, setStatusAsync, setTagsAsync, validateAgentSession } from "../db";
6
6
  import { attachBranchState, attachBranchStates } from "../agent-branch-state";
7
7
  import { redactAgentCardLaunchShape } from "../agent-launch-shape-redaction";
8
8
  import { attachChannelBinding, attachChannelBindings } from "../agent-channel-binding";
@@ -258,8 +258,8 @@ function cleanAgentStatus(value: unknown): AgentStatusValue {
258
258
  // #3606 — a reported status/readiness equal to the live card is a liveness tick, not a transition: no
259
259
  // row write, no agent.status event. Presence still advances through the coalescing heartbeat buffer,
260
260
  // except for a terminal row, which a beat would resurrect.
261
- function noteUnchangedLifecycle(agentId: string, current: AgentCard, guard: AgentSessionGuard | undefined): void {
262
- if (current.status !== "offline" && current.status !== "stale") recordHeartbeat(agentId, { guard });
261
+ async function noteUnchangedLifecycle(agentId: string, current: AgentCard, guard: AgentSessionGuard | undefined): Promise<void> {
262
+ if (current.status !== "offline" && current.status !== "stale") await recordHeartbeatAsync(agentId, { guard });
263
263
  }
264
264
 
265
265
  async function applyAgentStatus(agentId: string, status: AgentStatusValue, guard: AgentSessionGuard | undefined, before: AgentCard | null): Promise<boolean> {
@@ -309,7 +309,7 @@ export const patchAgentStatus: Handler = async (req, params) => {
309
309
  const session = validateAgentSession(params.id!, guard);
310
310
  if (!session.ok) return error(session.error!, agentSessionStatus(session.error));
311
311
  const before = getAgent(params.id!);
312
- if (before?.status === status) noteUnchangedLifecycle(params.id!, before, guard);
312
+ if (before?.status === status) await noteUnchangedLifecycle(params.id!, before, guard);
313
313
  else if (!(await applyAgentStatus(params.id!, status, guard, before))) return error("agent not found", 404);
314
314
  } catch (e) {
315
315
  if (e instanceof ValidationError) return error(e.message, 400);
@@ -349,7 +349,7 @@ export const postHeartbeat: Handler = async (req, params) => {
349
349
  // A reported terminal status must not be undone by the beat's offline/stale resurrection.
350
350
  if (status !== "offline" && status !== "stale") {
351
351
  // #1468 — route the API heartbeat through the same coalescing buffer as the bus path.
352
- if (!recordHeartbeat(params.id!, { guard })) return error("agent not found", 404);
352
+ if (!(await recordHeartbeatAsync(params.id!, { guard }))) return error("agent not found", 404);
353
353
  }
354
354
  if (wasUnavailable) {
355
355
  const after = getAgent(params.id!);
@@ -429,7 +429,7 @@ export const patchAgentReady: Handler = async (req, params) => {
429
429
  const session = validateAgentSession(params.id!, guard);
430
430
  if (!session.ok) return error(session.error!, agentSessionStatus(session.error));
431
431
  const before = getAgent(params.id!);
432
- if (before?.ready === body.ready) noteUnchangedLifecycle(params.id!, before, guard);
432
+ if (before?.ready === body.ready) await noteUnchangedLifecycle(params.id!, before, guard);
433
433
  else if (!(await applyAgentReady(params.id!, body.ready, guard, before))) return error("agent not found", 404);
434
434
  } catch (e) {
435
435
  if (e instanceof ValidationError) return error(e.message, 400);
@@ -32,6 +32,10 @@ export const getCommands: Handler = async (req) => {
32
32
  limit: limitRaw ?? undefined,
33
33
  dispatchableOnly,
34
34
  oldestFirst: dispatchableOnly && status === "pending",
35
+ // #3391 — a listing omits each spawn's inline agentProfile (13.9 MB per 30 rows blocked the hub
36
+ // loop); `GET /api/commands/:id` returns the full row. The executor dispatch feed runs the rows it
37
+ // polls, so it keeps the profile.
38
+ slim: !dispatchableOnly,
35
39
  });
36
40
  return json(commands.map((command) => serializeCommandForRead(command, ctx)));
37
41
  };
@@ -29,7 +29,7 @@ import { KERNEL_CORRELATION_PREFIX, isReservedKernelCorrelationId } from "../ser
29
29
  import { prepareScheduledCommandResultForStorage, settleScheduledCommandTimer } from "../services/scheduler-command";
30
30
  import { ServiceAuthError } from "../services/errors";
31
31
  import { applyIdleRefreshResult } from "../maintenance/workspaces";
32
- import { seedMigratedProviderConfigs } from "../provider-config-store";
32
+ import { seedMigratedProviderConfigsAsync } from "../provider-config-store";
33
33
  import { notifyAgentSpawnFailed } from "../agent-lifecycle-events";
34
34
  import { scheduleRepoMerge } from "../workspace-auto-merge";
35
35
  import { settleMemoryInjectionAfterContextCommand } from "../memory-injection";
@@ -559,7 +559,7 @@ export const patchCommand: Handler = async (req, params) => {
559
559
  if (command.type === "orchestrator.migrate-provider-config" && command.status === "succeeded" && isRecord(result)) {
560
560
  // Seed central rows from the reported host-local files with server authority (#465); idempotent, a
561
561
  // stored row wins. Seeds from the request: the persisted result holds only fingerprints (#3403).
562
- const migration = seedMigratedProviderConfigs(result);
562
+ const migration = await seedMigratedProviderConfigsAsync(result);
563
563
  if (migration?.seeded.length) {
564
564
  const { host, seeded } = migration;
565
565
  await auditEvent({
@@ -1,7 +1,7 @@
1
1
  // Auto-split from routes.ts (#299). Domain: continuation archives.
2
2
  import { isRecord } from "@humwick/sdk";
3
3
  import { resolveCallerAgentId } from "../agent-ref";
4
- import { archiveContinuationSegmentAsync, appendContinuationArchiveRefs, getAgent, listAgents, ValidationError } from "../db";
4
+ import { archiveContinuationSegmentAsync, appendContinuationArchiveRefsAsync, getAgent, listAgents, ValidationError } from "../db";
5
5
  import { getComponentAuth } from "../security";
6
6
  import { cleanEpoch, cleanPositiveId, cleanString } from "../validation";
7
7
  import { error, json, parseBody, type Handler } from "./_shared";
@@ -21,7 +21,7 @@ export const postContinuationArchiveRoute: Handler = async (req) => {
21
21
  generation: cleanPositiveId(parsed.body.generation, "generation"),
22
22
  now: cleanEpoch(parsed.body.occurredAt, "occurredAt"),
23
23
  });
24
- const envelope = appendContinuationArchiveRefs(agentId, [archive.ref]);
24
+ const envelope = await appendContinuationArchiveRefsAsync(agentId, [archive.ref]);
25
25
  return json({ archive, envelope }, 201);
26
26
  } catch (e) {
27
27
  if (e instanceof ValidationError) return error(e.message, 400);
@@ -70,6 +70,7 @@ import { postIssueLifecycleReopenRoute } from "./issue-lifecycle";
70
70
  import { deleteIssueRefRoute, getIssueRefRoute, listIssueRefsRoute, patchIssueRefRoute, postIssueRefRoute, resolveIssueRefRoute } from "./issue-refs";
71
71
  import { deleteProjectEntryRoute, getProjectEntriesRoute, getProjectEntryRoute, getProjectInjectionPreviewRoute, getProjectResolveRoute, getProjectRoute, getProjectsRoute, patchProjectEntryRoute, postProjectEntryRoute } from "./projects";
72
72
  import { getPromptHistoryRoute, postPromptRevisionRoute, getPromptTemplateRoute, getPromptTemplatesRoute, postPromptTemplateResetRoute, putPromptTemplateRoute } from "./prompt-templates";
73
+ import { projectProfileInstructionsRoute } from "./project-profile-instructions";
73
74
  import { getRecipeByName, getRecipeInstanceArtifacts, getRecipeInstanceById, getRecipeInstances, getRecipes, postRecipeInstanceArtifacts, postRecipeStart, postRecipeStop } from "./recipes";
74
75
  import { getSettingRoute, getSettingsNamespaceRoute, getSettingsRoute, putSettingRoute, putSettingsDefaultRoute } from "./settings";
75
76
  import { postNotificationPreviewRoute } from "./notifications";
@@ -85,7 +86,7 @@ import { postMcp } from "../mcp";
85
86
  import { postOrchestratorBootstrap, postOrchestratorBootstrapExchange } from "./orchestrator-bootstrap";
86
87
  import { getDeploysRoute } from "./deploys";
87
88
  import { getGateStatsRoute, getShippingBoardRoute, getShippingStatsRoute, postRedMainAbandonRoute } from "./shipping";
88
- import { getWorkflowCatalogRoute, getWorkflowDefinitionsRoute, getWorkflowRunBudgetRoute, getWorkflowRunRoute, getWorkflowRunsRoute, getWorkflowStatsRoute, patchWorkflowRunBudgetRoute, postWorkflowRunCancelRoute, postWorkflowRunResumeRoute, postWorkflowRunStartRoute } from "./workflows";
89
+ import { getWorkflowCatalogRoute, getWorkflowDefinitionsRoute, getWorkflowRunBudgetRoute, getWorkflowRunRoute, getWorkflowRunsRoute, getWorkflowStatsRoute, patchWorkflowRunBudgetRoute, postWorkflowRunCancelRoute, postWorkflowRunPauseRoute, postWorkflowRunResumeRoute, postWorkflowRunStartRoute, postWorkflowRunUnpauseRoute } from "./workflows";
89
90
  import { getRestartEpochRoute, postRestartEpochAbandonRoute } from "./restart-epochs";
90
91
  import { getFleetConvergenceRoute } from "./fleet-convergence";
91
92
  import { postTimerMessageOperator } from "./kernel-timers-operator";
@@ -318,6 +319,7 @@ const routes: Route[] = [
318
319
  route("DELETE", "/api/commands/:id", deleteCommandById),
319
320
  route("POST", "/api/system/timer-message-cutover/:verb", postTimerMessageOperator),
320
321
  route("GET", "/api/agent-profiles", getAgentProfilesRoute),
322
+ route("GET", "/api/agent-profiles/:name/project-instructions", projectProfileInstructionsRoute),
321
323
  route("GET", "/api/agent-profiles/tool-groups", getAgentProfileToolGroupsRoute),
322
324
  route("POST", "/api/agent-profiles/preview", postAgentProfilePreviewRoute),
323
325
  route("GET", "/api/agent-profiles/:name/resolved", getResolvedAgentProfileRoute),
@@ -546,6 +548,11 @@ const routes: Route[] = [
546
548
  route("PATCH", "/api/issue-refs/:id", patchIssueRefRoute),
547
549
  route("DELETE", "/api/issue-refs/:id", deleteIssueRefRoute),
548
550
  route("GET", "/api/projects", getProjectsRoute),
551
+ route("GET", "/api/projects/:id/profile-instructions", projectProfileInstructionsRoute),
552
+ route("GET", "/api/projects/:id/profile-instructions/:profile", projectProfileInstructionsRoute),
553
+ route("PUT", "/api/projects/:id/profile-instructions/:profile", projectProfileInstructionsRoute),
554
+ route("GET", "/api/projects/:id/profile-instructions/:profile/history", projectProfileInstructionsRoute),
555
+ route("POST", "/api/projects/:id/profile-instructions/:profile/restore", projectProfileInstructionsRoute),
549
556
  route("POST", "/api/projects", postProjectOnboardRoute),
550
557
  route("POST", "/api/projects/:id/checkouts/bind", postProjectBindCheckoutRoute),
551
558
  route("POST", "/api/projects/:id/checkouts/unbind", postProjectUnbindCheckoutRoute),
@@ -600,6 +607,8 @@ const routes: Route[] = [
600
607
  route("GET", "/api/workflows/runs/:runId/budget", getWorkflowRunBudgetRoute),
601
608
  route("PATCH", "/api/workflows/runs/:runId/budget", patchWorkflowRunBudgetRoute),
602
609
  route("POST", "/api/workflows/runs/:runId/cancel", postWorkflowRunCancelRoute),
610
+ route("POST", "/api/workflows/runs/:runId/pause", postWorkflowRunPauseRoute),
611
+ route("POST", "/api/workflows/runs/:runId/unpause", postWorkflowRunUnpauseRoute),
603
612
  route("POST", "/api/workflows/runs/:runId/resume", postWorkflowRunResumeRoute),
604
613
  route("GET", "/api/workflows/stats", getWorkflowStatsRoute),
605
614
  route("GET", "/api/workflows/definitions", getWorkflowDefinitionsRoute),
@@ -1,7 +1,8 @@
1
+ import type { IntegrationRegistryInput } from "../db/integrations";
1
2
  // Auto-split from routes.ts (#299). Domain: integrations.
2
3
  import { INTEGRATION_RATE_LIMIT_PER_MINUTE, MAX_BODY_BYTES, getIntegrationTokens, type IntegrationTokenConfig } from "../config";
3
4
  import { VALID_ARTIFACT_KINDS, VALID_ARTIFACT_ROLES, VALID_TASK_STATUSES, agentSessionStatus, authorizeRoute, cleanAttachmentRefs, dispatchTaskCallbacksInBackground, error, json, normalizeAgentSessionGuard, parseBody, reactionEmoji, sendReactionNotificationToAuthor, validateChannelAttachmentSourceRef, withPayloadAttachments, type Handler } from "./_shared";
4
- import { ValidationError, evaluatePoolBindingsAsync, findMessageByTelegramSourceAsync, getAgent, getChannelAsync, getMessage, ingestIntegrationEvent, isIntegrationRegistryEnabled, listChannelBindingsAsync, listChannelsAsync, listIntegrationRegistry, listIntegrationTaskStats, resolveChannelRoutesAsync, sendMessageWithResult, setMessageReactionAsync, upsertChannelBindingAsync, upsertIntegrationRegistry, validateAgentSession } from "../db";
5
+ import { ValidationError, evaluatePoolBindingsAsync, findMessageByTelegramSourceAsync, getAgent, getChannelAsync, getMessage, ingestIntegrationEvent, isIntegrationRegistryEnabled, listChannelBindingsAsync, listChannelsAsync, listIntegrationTaskStatsAsync, reconcileIntegrationRegistryAsync, resolveChannelRoutesAsync, sendMessageWithResult, setMessageReactionAsync, upsertChannelBindingAsync, upsertIntegrationRegistry, validateAgentSession } from "../db";
5
6
  import { cleanMeta, cleanString, cleanStringArray, optionalEnum } from "../validation";
6
7
  import { emitChannelActivity, emitMessageQueued, emitMessageReactionUpdated, emitNewMessage, emitTaskChanged } from "../sse";
7
8
  import { getComponentAuth, getIntegrationAuth, hasIntegrationScope, isRequestAuthorizedFor } from "../security";
@@ -256,24 +257,7 @@ function normalizeIntegrationEvent(body: unknown): IntegrationEventInput {
256
257
  };
257
258
  }
258
259
 
259
- function normalizeIntegrationRegistryInput(name: string, body: unknown): {
260
- name: string;
261
- displayName?: string;
262
- description?: string;
263
- enabled?: boolean;
264
- scopes?: string[];
265
- targets?: string[];
266
- channels?: string[];
267
- type?: string;
268
- icon?: string;
269
- accentColor?: string;
270
- tags?: string[];
271
- homepageUrl?: string;
272
- repositoryUrl?: string;
273
- docsUrl?: string;
274
- manifest?: Record<string, unknown>;
275
- source: "api";
276
- } {
260
+ function normalizeIntegrationRegistryInput(name: string, body: unknown): IntegrationRegistryInput & { source: "api" } {
277
261
  if (!isRecord(body)) throw new ValidationError("body must be an object");
278
262
  if (body.enabled !== undefined && typeof body.enabled !== "boolean") throw new ValidationError("enabled must be a boolean");
279
263
  return {
@@ -364,40 +348,30 @@ function safeCallbackHost(url: string | undefined): string | undefined {
364
348
  }
365
349
  }
366
350
 
367
- function reconcileIntegrationRegistry(configured: Map<string, IntegrationTokenConfig>, observedStats: Map<string, ReturnType<typeof listIntegrationTaskStats>[number]>): Map<string, ReturnType<typeof listIntegrationRegistry>[number]> {
368
- for (const config of configured.values()) {
369
- upsertIntegrationRegistry({
370
- name: config.name,
371
- displayName: config.displayName,
372
- description: config.description,
373
- scopes: config.scopes,
374
- targets: config.targets,
375
- channels: config.channels,
376
- type: config.type,
377
- icon: config.icon,
378
- accentColor: config.accentColor,
379
- tags: config.tags,
380
- homepageUrl: config.homepageUrl,
381
- repositoryUrl: config.repositoryUrl,
382
- docsUrl: config.docsUrl,
383
- manifest: config.manifest,
384
- source: "env",
385
- });
386
- }
387
- for (const stats of observedStats.values()) {
388
- upsertIntegrationRegistry({
389
- name: stats.source,
390
- enabled: true,
391
- source: "observed",
392
- });
393
- }
394
- return new Map(listIntegrationRegistry().map((integration) => [integration.name, integration]));
351
+ async function reconcileRegistry(configured: Map<string, IntegrationTokenConfig>, observedSources: string[]) {
352
+ const registry = await reconcileIntegrationRegistryAsync([...configured.values()].map((config) => ({
353
+ name: config.name,
354
+ displayName: config.displayName,
355
+ description: config.description,
356
+ scopes: config.scopes,
357
+ targets: config.targets,
358
+ channels: config.channels,
359
+ type: config.type,
360
+ icon: config.icon,
361
+ accentColor: config.accentColor,
362
+ tags: config.tags,
363
+ homepageUrl: config.homepageUrl,
364
+ repositoryUrl: config.repositoryUrl,
365
+ docsUrl: config.docsUrl,
366
+ manifest: config.manifest,
367
+ })), observedSources);
368
+ return new Map(registry.map((integration) => [integration.name, integration]));
395
369
  }
396
370
 
397
- export const getIntegrations: Handler = () => {
371
+ export const getIntegrations: Handler = async () => {
398
372
  const configured = new Map(getIntegrationTokens().map((integration) => [integration.name, integration]));
399
- const observedStats = new Map(listIntegrationTaskStats().map((stats) => [stats.source, stats]));
400
- const registry = reconcileIntegrationRegistry(configured, observedStats);
373
+ const observedStats = new Map((await listIntegrationTaskStatsAsync()).map((stats) => [stats.source, stats]));
374
+ const registry = await reconcileRegistry(configured, [...observedStats.keys()]);
401
375
  const names = [...new Set([...configured.keys(), ...observedStats.keys(), ...registry.keys()])].sort((a, b) => a.localeCompare(b));
402
376
  const now = Date.now();
403
377
 
@@ -1,4 +1,4 @@
1
- import { deleteIssueRefMapping, getIssueRef, listIssueRefs, patchIssueRefMapping, resolveIssueRefMapping, upsertIssueRefMapping, type ListIssueRefsOptions } from "../services/issue-refs";
1
+ import { deleteIssueRefMappingAsync, getIssueRef, listIssueRefs, patchIssueRefMappingAsync, resolveIssueRefMappingAsync, upsertIssueRefMappingAsync, type ListIssueRefsOptions } from "../services/issue-refs";
2
2
  import { getIssueRefByExternalKey, issueRefClosedCompleted, issueRefForRefString } from "../db/issue-refs";
3
3
  import { advanceTerminalPlanRefsAsync } from "../services/plan-terminal-refs";
4
4
  import { cleanEnum, cleanString, optionalEnum } from "../validation";
@@ -76,7 +76,7 @@ export const postIssueRefRoute: Handler = async (req) => {
76
76
  try {
77
77
  const body = cleanUpsertBody(parsed.body);
78
78
  const before = getIssueRefByExternalKey(body.provider, body.repo, body.externalKey);
79
- const issueRef = upsertIssueRefMapping(body);
79
+ const issueRef = await upsertIssueRefMappingAsync(body);
80
80
  // #2520 — a completed close cached here propagates to the plan nodes bound to this ref.
81
81
  if (issueRefClosedCompleted(before, issueRef)) await advanceTerminalPlanRefsAsync({ issueRefId: issueRef.id });
82
82
  return json({ issueRef });
@@ -98,7 +98,7 @@ export const resolveIssueRefRoute: Handler = async (req) => {
98
98
  ? issueRefForRefString(ref, cleanString(value.defaultRepo ?? value.repo, "defaultRepo", { max: 500 }))
99
99
  : getIssueRefByExternalKey(cleanProvider(value.provider), cleanString(value.repo, "repo", { required: true, max: 500 })!, cleanString(value.externalKey, "externalKey", { required: true, max: 240 })!);
100
100
  const issueRef = ref
101
- ? resolveIssueRefMapping({
101
+ ? await resolveIssueRefMappingAsync({
102
102
  ref,
103
103
  defaultRepo: cleanString(value.defaultRepo ?? value.repo, "defaultRepo", { max: 500 }),
104
104
  provider: optionalEnum(value.provider, "provider", ISSUE_PROVIDERS, "github") as IssueProvider,
@@ -107,7 +107,7 @@ export const resolveIssueRefRoute: Handler = async (req) => {
107
107
  closeReason: cleanCloseReason(value.closeReason),
108
108
  statusSyncedAt: cleanTimestamp(value.statusSyncedAt),
109
109
  })
110
- : resolveIssueRefMapping({
110
+ : await resolveIssueRefMappingAsync({
111
111
  provider: cleanProvider(value.provider),
112
112
  repo: cleanString(value.repo, "repo", { required: true, max: 500 })!,
113
113
  externalKey: cleanString(value.externalKey, "externalKey", { required: true, max: 240 })!,
@@ -142,7 +142,7 @@ export const patchIssueRefRoute: Handler = async (req, params) => {
142
142
  try {
143
143
  const id = cleanString(params.id, "id", { required: true, max: 120 })!;
144
144
  const before = getIssueRef(id);
145
- const issueRef = patchIssueRefMapping(id, cleanPatchBody(parsed.body));
145
+ const issueRef = await patchIssueRefMappingAsync(id, cleanPatchBody(parsed.body));
146
146
  if (!issueRef) return error("issue ref not found", 404);
147
147
  // #2520 — a completed close cached here propagates to the plan nodes bound to this ref.
148
148
  if (issueRefClosedCompleted(before, issueRef)) await advanceTerminalPlanRefsAsync({ issueRefId: issueRef.id });
@@ -152,9 +152,9 @@ export const patchIssueRefRoute: Handler = async (req, params) => {
152
152
  }
153
153
  };
154
154
 
155
- export const deleteIssueRefRoute: Handler = (_req, params) => {
155
+ export const deleteIssueRefRoute: Handler = async (_req, params) => {
156
156
  try {
157
- const deleted = deleteIssueRefMapping(cleanString(params.id, "id", { required: true, max: 120 })!);
157
+ const deleted = await deleteIssueRefMappingAsync(cleanString(params.id, "id", { required: true, max: 120 })!);
158
158
  if (!deleted) return error("issue ref not found", 404);
159
159
  return json({ deleted });
160
160
  } catch (err) {
@@ -50,7 +50,7 @@ export const postOrchestratorBootstrap: Handler = async (req) => {
50
50
  "--yes",
51
51
  ];
52
52
  for (const entry of pathPrefix ?? []) args.push("--path-prefix", entry);
53
- const command = ["bunx", `agent-relay-server@${version}`, ...args].map(quoteInstallCommandArg).join(" ");
53
+ const command = ["bunx", `@humwick/server@${version}`, ...args].map(quoteInstallCommandArg).join(" ");
54
54
  return json({
55
55
  command,
56
56
  relayUrl,
@@ -4,7 +4,7 @@
4
4
  // upsert, and fanning the operator-facing events out as activity events — lives here.
5
5
  import { isRecord } from "@humwick/sdk";
6
6
  import type { HostHardware } from "@humwick/sdk";
7
- import { upsertHostFromRegistrationAsync, type HostRegistrationEvent } from "../db";
7
+ import { conflictingHardwareFields, upsertHostFromRegistrationAsync, type HostRegistrationEvent } from "../db";
8
8
  import { auditEvent, cleanSafeNumber } from "./_shared";
9
9
  import { recordOrchestratorUtilization } from "./orchestrator-host-utilization";
10
10
  import { cleanString } from "../validation";
@@ -55,7 +55,7 @@ async function emitHostRegistrationEvents(events: readonly HostRegistrationEvent
55
55
  clientId: `host-identity-conflict-${ev.hostId}-${ev.orchestratorId}-${Date.now()}`,
56
56
  kind: "state",
57
57
  title: "Host identity conflict",
58
- body: `${ev.hostname}: reported hardware differs from the stored fingerprint — bound anyway, kept first-seen (conflict:pending)`,
58
+ body: `${ev.hostname}: reported hardware differs from the stored fingerprint (${conflictingHardwareFields(ev.stored, ev.reported).join(", ")} changed) — bound anyway, kept first-seen (conflict:pending)`,
59
59
  meta: ev.hostId,
60
60
  icon: "ti-alert-triangle",
61
61
  view: "orchestrators",
@@ -141,6 +141,7 @@ export function cleanHostUtilizationSample(value: unknown, now: number): HostUti
141
141
  const swapUsedMb = nonNegative(value.swapUsedMb);
142
142
  const diskTotalMb = nonNegative(value.diskTotalMb);
143
143
  const diskFreeMb = nonNegative(value.diskFreeMb);
144
+ const diskPath = optionalString(value.diskPath, "utilization.diskPath", 200);
144
145
 
145
146
  return {
146
147
  at,
@@ -162,7 +163,7 @@ export function cleanHostUtilizationSample(value: unknown, now: number): HostUti
162
163
  ...(swapTotalMb !== undefined && swapUsedMb !== undefined && swapUsedMb <= swapTotalMb
163
164
  ? { swapTotalMb, swapUsedMb } : {}),
164
165
  ...(diskTotalMb !== undefined && diskFreeMb !== undefined && diskFreeMb <= diskTotalMb
165
- ? { diskTotalMb, diskFreeMb } : {}),
166
+ ? { diskTotalMb, diskFreeMb, ...(diskPath ? { diskPath } : {}) } : {}),
166
167
  memPressure,
167
168
  agentCountThisDaemon,
168
169
  queuedSpawnsThisDaemon,
@@ -207,6 +208,7 @@ export function toMachineSample(sample: HostUtilizationSample): HostMachineSampl
207
208
  ...(sample.swapTotalMb !== undefined ? { swapTotalMb: sample.swapTotalMb } : {}),
208
209
  ...(sample.diskFreeMb !== undefined ? { diskFreeMb: sample.diskFreeMb } : {}),
209
210
  ...(sample.diskTotalMb !== undefined ? { diskTotalMb: sample.diskTotalMb } : {}),
211
+ ...(sample.diskPath ? { diskPath: sample.diskPath } : {}),
210
212
  memPressure: sample.memPressure,
211
213
  };
212
214
  }