@humwick/server 0.130.0 → 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.
- package/README.md +5 -0
- package/docs/guides/tools-administration.md +6 -1
- package/docs/guides/tools-coordination.md +1 -0
- package/docs/guides/tools-tasks.md +8 -0
- package/docs/guides/workflows.md +58 -0
- package/docs/openapi.json +414 -1
- package/package.json +8 -17
- package/public/assets/{MessageBubble-BWpoBjl4.js → MessageBubble-BWLqMGKG.js} +2 -2
- package/public/assets/{PlanGraphPanel-C0auck3n.js → PlanGraphPanel-3TlIQpjk.js} +2 -2
- package/public/assets/{TraceView-DBnOx7AQ.js → TraceView-Wimm0Czv.js} +2 -2
- package/public/assets/{VaultDecisionCard-0kp2oNBC.js → VaultDecisionCard-Bau_vNax.js} +2 -2
- package/public/assets/{activity-yLztXEBt.js → activity-CrSurn-r.js} +2 -2
- package/public/assets/{agent-lineage-BbJDR1dW.js → agent-lineage-CknAJKcb.js} +2 -2
- package/public/assets/agent-liveness-CaNwK0Zf.js +2 -0
- package/public/assets/{agent-name-CTZBrSD9.js → agent-name-DKbiIhBo.js} +2 -2
- package/public/assets/agent-profiles-DwF6EQ4R.js +2 -0
- package/public/assets/{agent-project-badge-9TqzUUYE.js → agent-project-badge-Diz4Sjjb.js} +2 -2
- package/public/assets/{agent-tools-D4n40pn8.js → agent-tools-CRhpRQza.js} +2 -2
- package/public/assets/{agent-type-icon-D6FUarOf.js → agent-type-icon-LrUEU3lB.js} +2 -2
- package/public/assets/{agents-BYDslkJc.js → agents-B-v66C-4.js} +2 -2
- package/public/assets/{analytics-B-XSbEMC.js → analytics-BqCb-LKi.js} +2 -2
- package/public/assets/{artifact-viewer-DdWIfV6M.js → artifact-viewer-kf4pGuAR.js} +2 -2
- package/public/assets/{artifacts-oBOqks-2.js → artifacts-D32zyw4Y.js} +2 -2
- package/public/assets/{artifacts-DPN1q4pA.js → artifacts-DJevXcvg.js} +2 -2
- package/public/assets/{automation-4KcRFXEu.js → automation-BpRajx_5.js} +2 -2
- package/public/assets/{backlog-Cw9xPTCF.js → backlog-D_UjTdzX.js} +2 -2
- package/public/assets/{busy-health-CTu32MZt.js → busy-health-N3VEh4ao.js} +2 -2
- package/public/assets/{channels-BiXzg1G9.js → channels-9jopungq.js} +2 -2
- package/public/assets/{chat-Ctk2qwvA.js → chat-CSXrTB3C.js} +2 -2
- package/public/assets/{code-preview-Bm1wWqAp.js → code-preview-p1NnmqK0.js} +2 -2
- package/public/assets/{connectors-C36ax4Vw.js → connectors-CZdqlDNL.js} +2 -2
- package/public/assets/{cosmos-Jj9LK2Wf.js → cosmos-BgdsE4dG.js} +2 -2
- package/public/assets/{crate-agent-H6S7-B9T.js → crate-agent-30aXTKva.js} +2 -2
- package/public/assets/{dependency-graph-Cd1E23wa.js → dependency-graph-B_jvw2GE.js} +2 -2
- package/public/assets/{deploys-Bwfq146q.js → deploys-DoN6bAb5.js} +2 -2
- package/public/assets/{display-CfO7rTuF.js → display-BrKWFGJz.js} +2 -2
- package/public/assets/{files-DhhZI2Ih.js → files-D6XEu8Ng.js} +2 -2
- package/public/assets/fleet-C7jQWbw2.js +2 -0
- package/public/assets/{fleet-metrics-BkHP-P3R.js → fleet-metrics-BiDs3MLx.js} +2 -2
- package/public/assets/{formatted-body-Cm1RrzmN.js → formatted-body-CQBwc1fb.js} +3 -3
- package/public/assets/{formatted-body-impl-DQiOuOD1.js → formatted-body-impl-DyG0WsQS.js} +2 -2
- package/public/assets/{host-providers-dialog-CHqwXTov.js → host-providers-dialog-DKaW31dN.js} +2 -2
- package/public/assets/index-CRHep3M9.js +15 -0
- package/public/assets/index-MYAIwYTX.css +2 -0
- package/public/assets/{insights-fH1EL-qZ.js → insights-CzrtkpOE.js} +2 -2
- package/public/assets/{integrations-C5Oix6ng.js → integrations-aVsUmigt.js} +2 -2
- package/public/assets/{issue-ref-chip-ODyondIa.js → issue-ref-chip-BnSlM_95.js} +2 -2
- package/public/assets/{log-viewer-Cvfy6PW7.js → log-viewer-qe7Ee47Z.js} +2 -2
- package/public/assets/{maintenance-D8CDH5wZ.js → maintenance-NfjqFZAk.js} +2 -2
- package/public/assets/{managed-agents-egllbpij.js → managed-agents-BiH0HgaE.js} +2 -2
- package/public/assets/{markdown-preview-CYSFgVgK.js → markdown-preview-BixaT3Xr.js} +3 -3
- package/public/assets/{markdown-preview-impl-BteVIjX4.js → markdown-preview-impl-DNGlWIS3.js} +2 -2
- package/public/assets/{memory-C8WmXsyr.js → memory-DNsCl6UX.js} +2 -2
- package/public/assets/{messages-BzQdqlO6.js → messages-DopU1L1X.js} +2 -2
- package/public/assets/{orchestrators-B1HxzkNw.js → orchestrators-Cq7ckLQT.js} +2 -2
- package/public/assets/{overview-DCUnI4Z7.js → overview-C1DCTzzV.js} +2 -2
- package/public/assets/{pairs-ftCd2XcD.js → pairs-DE_m6rrE.js} +2 -2
- package/public/assets/{profile-icon-B2zH8DMH.js → profile-icon-B3rfh77F.js} +2 -2
- package/public/assets/project-profile-instructions-DQWZE0kA.js +2 -0
- package/public/assets/projects-Br2Bd2h1.js +2 -0
- package/public/assets/{prompt-settings-Bftq9czX.js → prompt-settings-BKvFsvGD.js} +2 -2
- package/public/assets/provider-display-DsuWMvVL.js +2 -0
- package/public/assets/{registry-DWCU5c8q.js → registry-Cw38_6gW.js} +2 -2
- package/public/assets/run-card-CpKqRbhg.js +2 -0
- package/public/assets/scroll-text-BKXS1ahr.js +2 -0
- package/public/assets/{secrets-C7GIUATz.js → secrets-DxI-vzSq.js} +2 -2
- package/public/assets/{service-access-settings-C3aujqTG.js → service-access-settings-D9s_VJbd.js} +2 -2
- package/public/assets/{settings-C6sZ9eBa.js → settings-CKZTVGIx.js} +2 -2
- package/public/assets/{shipping-Bu8p1gEw.js → shipping-B9YtnwtG.js} +2 -2
- package/public/assets/{stats-V9Z-GxUd.js → stats-DyUBKyWI.js} +2 -2
- package/public/assets/{status-dot-CVv0iGHL.js → status-dot-DYqlEUhJ.js} +2 -2
- package/public/assets/{store-BvtFdlGX.js → store-DcClXLH0.js} +3 -3
- package/public/assets/{tasks-CXU75HRF.js → tasks-Bh7Chr4-.js} +2 -2
- package/public/assets/{teams-BPf976zb.js → teams-bowI7qVY.js} +2 -2
- package/public/assets/{terminal-viewer-DE9BOe-8.js → terminal-viewer-BgVLHdsU.js} +3 -3
- package/public/assets/{terminal-viewer-impl-D04pjmGh.js → terminal-viewer-impl-Dz22UPy6.js} +2 -2
- package/public/assets/token-estimate-Co-Jdphh.js +2 -0
- package/public/assets/{use-agent-terminal-B1yR456R.js → use-agent-terminal-DSQQ-iY7.js} +2 -2
- package/public/assets/{use-decisions-D-S4tpDf.js → use-decisions-samMQhQf.js} +2 -2
- package/public/assets/use-project-list-59LheVP7.js +2 -0
- package/public/assets/{use-selectors-CnrAk2YP.js → use-selectors-BZa25xEB.js} +2 -2
- package/public/assets/{user-avatar-nBFIcR4M.js → user-avatar-DHxlvUvV.js} +2 -2
- package/public/assets/versioned-prompt-editor-BmED5DnJ.js +8 -0
- package/public/assets/{work-queue-TCjJxeT-.js → work-queue-CSvpuNLz.js} +2 -2
- package/public/assets/{workflow-marker-Cf3Hf2fN.js → workflow-marker-DAZcj5qt.js} +2 -2
- package/public/assets/{workflows-CXQX20Qj.js → workflows-DdmxRSyg.js} +2 -2
- package/public/assets/{workspaces-qSYzKYMA.js → workspaces-BxeKfVuF.js} +2 -2
- package/public/cosmos.html +4 -4
- package/public/index.html +31 -29
- package/runner/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/runner/plugins/claude/hooks/gate-run-guard.provisioned.mjs +31 -1
- package/runner/src/adapters/claude-effort.ts +2 -4
- package/runner/src/adapters/codex-launch-config.ts +4 -5
- package/runner/src/adapters/codex.ts +1 -1
- package/runner/src/adapters/opencode-provider.ts +7 -22
- package/runner/src/adapters/opencode.ts +4 -4
- package/runner/src/agent-runner/credentials.ts +42 -12
- package/runner/src/agent-runner/inbox.ts +27 -0
- package/runner/src/agent-runner/lifecycle-milestones.ts +0 -2
- package/runner/src/bin/claude.ts +4 -0
- package/runner/src/bin/codex.ts +4 -0
- package/runner/src/bin/opencode.ts +4 -0
- package/runner/src/index.ts +5 -2
- package/runner/src/provider-setup.ts +34 -0
- package/runner/src/providers.ts +2 -1
- package/runner/src/runner-core.ts +18 -23
- package/runner/src/spawn-input.ts +2 -1
- package/runner/src/test-run-dedup.ts +59 -56
- package/scripts/cd-config.ts +24 -3
- package/scripts/gate-run-lease.ts +10 -7
- package/scripts/gate.sh +5 -1
- package/src/branch-land-notice.ts +93 -0
- package/src/branch-landed.ts +7 -76
- package/src/bus.ts +19 -20
- package/src/cd-deploy-notify.ts +30 -2
- package/src/cd-host-lag-notify.ts +7 -6
- package/src/ci/incidents.ts +2 -2
- package/src/ci/monitor.ts +5 -8
- package/src/ci/root-missing.ts +2 -7
- package/src/ci/transition-notify.ts +7 -39
- package/src/cli/cd-pauses.ts +19 -0
- package/src/cli/orchestrator.ts +1 -1
- package/src/cli/state.ts +2 -19
- package/src/cli/task-edit.ts +22 -0
- package/src/cli/task.ts +3 -1
- package/src/cli/workflow.ts +8 -2
- package/src/commands-db.ts +10 -6
- package/src/commands-write.ts +8 -0
- package/src/config-store-write.ts +13 -1
- package/src/config-store.ts +25 -14
- package/src/db/activity-async.ts +6 -1
- package/src/db/activity-write-ops.ts +13 -1
- package/src/db/activity.ts +1 -14
- package/src/db/agent-lifecycle-write-ops.ts +1 -0
- package/src/db/agent-meta.ts +2 -2
- package/src/db/agent-ownership-write-ops.ts +4 -0
- package/src/db/agent-search.ts +1 -15
- package/src/db/agents-async.ts +58 -7
- package/src/db/agents-write-ops.ts +28 -5
- package/src/db/agents.ts +81 -54
- package/src/db/artifacts-write-ops.ts +8 -3
- package/src/db/bus-outbox-write-ops.ts +1 -0
- package/src/db/channels-write-ops.ts +4 -0
- package/src/db/ci-incidents-async.ts +5 -5
- package/src/db/ci-incidents-write-ops.ts +2 -2
- package/src/db/claude-api-budget-ops.ts +5 -5
- package/src/db/claude-app-oauth.ts +4 -4
- package/src/db/codex-reset-consumes-write-ops.ts +3 -0
- package/src/db/command-row.ts +10 -2
- package/src/db/commands-list-query.ts +2 -0
- package/src/db/commands-spawn-read.ts +1 -1
- package/src/db/commands-write-ops.ts +21 -0
- package/src/db/config-store-write-ops.ts +9 -2
- package/src/db/continuation-archives-async.ts +5 -0
- package/src/db/continuation-archives-write-ops.ts +9 -0
- package/src/db/continuations.ts +2 -2
- package/src/db/db-writer-worker.ts +8 -1
- package/src/db/delivery-write-ops.ts +5 -0
- package/src/db/deploy-events-async.ts +1 -0
- package/src/db/deploy-events-read-ops.ts +2 -1
- package/src/db/deploy-events.ts +35 -4
- package/src/db/hosts-registration.ts +10 -2
- package/src/db/hosts-write-ops.ts +14 -0
- package/src/db/hosts.ts +9 -6
- package/src/db/inbox-write-ops.ts +4 -0
- package/src/db/inbox.ts +0 -14
- package/src/db/index.ts +2 -0
- package/src/db/insights-write-ops.ts +1 -0
- package/src/db/integrations-async.ts +8 -0
- package/src/db/integrations-ops.ts +15 -0
- package/src/db/integrations.ts +15 -21
- package/src/db/issue-lifecycle.ts +3 -4
- package/src/db/issue-refs-async.ts +20 -0
- package/src/db/issue-refs-write-ops.ts +29 -0
- package/src/db/issue-refs.ts +7 -8
- package/src/db/long-running-work.ts +2 -2
- package/src/db/macos-privacy.ts +1 -1
- package/src/db/main-connection-writes.ts +23 -2
- package/src/db/maintenance-job-reconcile.ts +61 -0
- package/src/db/maintenance-job-runs-async.ts +14 -0
- package/src/db/maintenance-job-write-ops.ts +9 -0
- package/src/db/mappers.ts +2 -14
- package/src/db/merge-lease.ts +1 -15
- package/src/db/message-reads-write-ops.ts +3 -0
- package/src/db/message-write-ops.ts +4 -0
- package/src/db/migrations.ts +7 -15
- package/src/db/orchestrators-async.ts +7 -3
- package/src/db/orchestrators-write-ops.ts +7 -1
- package/src/db/orchestrators.ts +21 -77
- package/src/db/pairs.ts +1 -13
- package/src/db/project-profile-instructions.ts +50 -0
- package/src/db/prompt-versions-ops.ts +1 -0
- package/src/db/prompt-versions.ts +9 -2
- package/src/db/provider-catalog-write-ops.ts +4 -4
- package/src/db/provider-config-history.ts +8 -3
- package/src/db/provider-flap-messages-write-ops.ts +1 -0
- package/src/db/provider-model-seed.ts +34 -0
- package/src/db/provider-quota-lease-write-ops.ts +1 -0
- package/src/db/provider-quota-write-ops.ts +2 -0
- package/src/db/provisioning-write-ops.ts +9 -8
- package/src/db/read-op-marshaling-fixtures.ts +5 -0
- package/src/db/read-ops.ts +4 -0
- package/src/db/routing-policy.ts +3 -4
- package/src/db/schema.ts +9 -3
- package/src/db/secrets-broker-write-ops.ts +5 -5
- package/src/db/secrets-vault-write.ts +7 -7
- package/src/db/services-write-ops.ts +3 -0
- package/src/db/spawn-delegation-state.ts +11 -4
- package/src/db/spawn-tree-cleanup.ts +3 -0
- package/src/db/stats-async.ts +4 -3
- package/src/db/task-entity.ts +23 -2
- package/src/db/task-list.ts +3 -1
- package/src/db/tasks.ts +1 -17
- package/src/db/team-spawn-delegation.ts +1 -1
- package/src/db/teams-write-ops.ts +4 -4
- package/src/db/timer-cutover-write-ops.ts +7 -0
- package/src/db/timer-ingress-write-ops.ts +9 -0
- package/src/db/timer-ingress.ts +7 -1
- package/src/db/timer-operator-write-ops.ts +14 -0
- package/src/db/timer-transfer-write-ops.ts +4 -0
- package/src/db/timer-write-ops.ts +14 -0
- package/src/db/token-db-write-ops.ts +21 -0
- package/src/db/token-standing.ts +15 -11
- package/src/db/user-settings-write-ops.ts +1 -0
- package/src/db/vault-backup.ts +2 -2
- package/src/db/vault-expiry.ts +2 -2
- package/src/db/vault-health.ts +3 -3
- package/src/db/vault-token-ops.ts +8 -8
- package/src/db/web-tool-call-ops.ts +3 -3
- package/src/db/workflow-contact.ts +1 -1
- package/src/db/workflow-task-read-ops.ts +30 -0
- package/src/db/write-ops.ts +15 -1
- package/src/db/writer-fault-seam.ts +5 -2
- package/src/db/writer-gateway.ts +21 -12
- package/src/dispatch-availability.ts +10 -6
- package/src/ephemeral/{landing-ingress-proof-worker.ts → landing-ingress-proof.test-fixture.ts} +4 -2
- package/src/host/disk-alert.ts +121 -0
- package/src/lifecycle-manager.ts +3 -2
- package/src/maintenance/cd-watcher.ts +3 -3
- package/src/maintenance/critical-job-watchdog.ts +16 -17
- package/src/maintenance/index.ts +1 -0
- package/src/maintenance/jobs.ts +3 -2
- package/src/maintenance/scheduler.ts +84 -128
- package/src/maintenance/stalled-delivery-pager.ts +6 -5
- package/src/maintenance/workspaces.ts +1 -1
- package/src/managed-policy.ts +31 -27
- package/src/mcp/index.ts +5 -2
- package/src/mcp/output-descriptions.ts +8 -8
- package/src/mcp/presentation.ts +4 -4
- package/src/mcp/project-profile-instructions.ts +32 -0
- package/src/mcp/tool-groups.ts +1 -1
- package/src/mcp/tools-spawn.ts +4 -3
- package/src/mcp-agent-action.ts +1 -2
- package/src/mcp-host-tools.ts +1 -1
- package/src/mcp-issue-ref-tools.ts +12 -11
- package/src/mcp-maintenance-tools.ts +2 -2
- package/src/mcp-profile-trust-tools.ts +4 -4
- package/src/mcp-provider-catalog.ts +2 -2
- package/src/mcp-task-tools.ts +11 -5
- package/src/mcp-team-template-tools.ts +3 -3
- package/src/mcp-workflow-tools.ts +10 -3
- package/src/notification-types.ts +2 -1
- package/src/operator-alarm.ts +26 -11
- package/src/package-pack.ts +42 -39
- package/src/project-instructions.ts +4 -0
- package/src/project-profile-instruction-text.ts +6 -0
- package/src/project-profile-instructions.ts +20 -0
- package/src/provider-catalog-store.ts +3 -49
- package/src/provider-config-store.ts +12 -11
- package/src/provider-model-seed.ts +1 -18
- package/src/provider-quota-config-store.ts +5 -4
- package/src/provider-secrets.test-fixture.ts +3 -3
- package/src/recipe-runner.ts +2 -2
- package/src/repo-config-source.ts +10 -4
- package/src/routes/agent-profiles.ts +6 -6
- package/src/routes/agents-spawn.ts +1 -1
- package/src/routes/agents.ts +6 -6
- package/src/routes/commands-listing.ts +4 -0
- package/src/routes/commands.ts +2 -2
- package/src/routes/continuation-archives.ts +2 -2
- package/src/routes/host-resource-control.ts +4 -1
- package/src/routes/index.ts +10 -1
- package/src/routes/integrations.ts +24 -50
- package/src/routes/issue-refs.ts +7 -7
- package/src/routes/orchestrator-bootstrap.ts +3 -3
- package/src/routes/orchestrator-host-registration.ts +2 -2
- package/src/routes/orchestrator-host-utilization.ts +3 -1
- package/src/routes/orchestrator-proxy.ts +2 -2
- package/src/routes/orchestrator.ts +4 -4
- package/src/routes/project-profile-instructions.ts +27 -0
- package/src/routes/project-trust.ts +2 -2
- package/src/routes/provider-config.ts +9 -8
- package/src/routes/provider-quota-config.ts +2 -2
- package/src/routes/settings.ts +5 -5
- package/src/routes/stats.ts +6 -6
- package/src/routes/task-http.ts +15 -1
- package/src/routes/task-issues.ts +11 -26
- package/src/routes/tasks.ts +22 -53
- package/src/routes/team-templates.ts +5 -5
- package/src/routes/teams-config.ts +2 -2
- package/src/routes/tokens.ts +12 -5
- package/src/routes/workflows.ts +20 -5
- package/src/routing-policy-normalize.ts +1 -2
- package/src/routing-step-defaults.ts +0 -2
- package/src/runner-token-mint-limit.ts +63 -0
- package/src/runtime-grant.ts +4 -2
- package/src/runtime-tokens.ts +50 -9
- package/src/security.ts +13 -20
- package/src/server-background.ts +1 -1
- package/src/server.ts +5 -2
- package/src/services/host-utilization.ts +23 -0
- package/src/services/idle-epics.ts +5 -6
- package/src/services/issue-lifecycle.ts +57 -61
- package/src/services/issue-refs.ts +9 -13
- package/src/services/kernel-timers-cutover-chaos-worker.ts +12 -7
- package/src/services/kernel-timers-ingress.ts +1 -1
- package/src/services/kernel-timers-request-key-migration-chaos-worker.ts +4 -1
- package/src/services/landed-ancestry.ts +19 -3
- package/src/services/memory-areas.ts +15 -51
- package/src/services/plan-ci-notice.ts +57 -0
- package/src/services/plan-ci-recovery.ts +2 -55
- package/src/services/plan-wake-digest.ts +1 -0
- package/src/services/profile-trust.ts +4 -3
- package/src/services/project-config-read.ts +70 -0
- package/src/services/project-profile-instructions.ts +54 -0
- package/src/services/provisioning-harness/budget-baseline.json +4 -4
- package/src/services/restart-spawn.ts +61 -49
- package/src/services/self-care-state.ts +2 -1
- package/src/services/self-effort.ts +5 -5
- package/src/services/send-message.ts +5 -1
- package/src/services/spawn-agent.ts +13 -2
- package/src/services/spawn-chain-inspector.ts +6 -13
- package/src/services/spawn-policy.ts +68 -0
- package/src/services/spawn-tree-cleanup.ts +2 -2
- package/src/services/task-dispatch.ts +3 -0
- package/src/services/task-state-reconcile.ts +6 -14
- package/src/services/team-templates.ts +9 -8
- package/src/services/transient-agent-reaper.ts +3 -1
- package/src/services/workflow-auto-start.ts +25 -13
- package/src/services/workflow-ci-main.ts +1 -1
- package/src/services/workflow-deferred-cleanup.ts +4 -2
- package/src/services/workflow-effect-driver.ts +2 -0
- package/src/services/workflow-effects.ts +18 -11
- package/src/services/workflow-land-notice.ts +10 -0
- package/src/services/workflow-pause-text.ts +43 -0
- package/src/services/workflow-reconcile.ts +13 -11
- package/src/services/workflow-run-view.ts +2 -0
- package/src/services/workflow-runs.ts +29 -13
- package/src/services/workflow-supervisor-state.ts +5 -0
- package/src/services/workflow-supervisor.ts +7 -3
- package/src/settings/registry.ts +1 -2
- package/src/spawn-command.ts +4 -4
- package/src/spawn-models.ts +10 -12
- package/src/spawn-placement.ts +1 -1
- package/src/spawn-targets.ts +1 -1
- package/src/startup-context-injection.ts +1 -0
- package/src/state-adoption/cd-cutover.ts +53 -7
- package/src/state-adoption/fleet-cutover.ts +35 -0
- package/src/state-adoption/fleet-plan.ts +36 -0
- package/src/state-adoption/index.ts +2 -2
- package/src/state-adoption/linux-plan.ts +2 -2
- package/src/state-adoption/linux.ts +2 -2
- package/src/state-adoption/macos-plan.ts +2 -2
- package/src/state-adoption/macos.ts +1 -1
- package/src/steward.ts +7 -6
- package/src/task-dispatch-live.ts +1 -1
- package/src/task-dispatcher.ts +1 -1
- package/src/teams-config-store.ts +4 -3
- package/src/token-db-write.ts +10 -0
- package/src/workspace-command-settle.ts +2 -1
- package/src/workspace-steward-wake.ts +2 -2
- package/node_modules/@humwick/kernel/LICENSE +0 -167
- package/node_modules/@humwick/kernel/async-entity-persistence.ts +0 -344
- package/node_modules/@humwick/kernel/async-event-log.ts +0 -107
- package/node_modules/@humwick/kernel/automations.pilot.ts +0 -147
- package/node_modules/@humwick/kernel/config.ts +0 -111
- package/node_modules/@humwick/kernel/contract.ts +0 -572
- package/node_modules/@humwick/kernel/control-authz.ts +0 -281
- package/node_modules/@humwick/kernel/control.ts +0 -645
- package/node_modules/@humwick/kernel/effects.ts +0 -493
- package/node_modules/@humwick/kernel/event-log.ts +0 -319
- package/node_modules/@humwick/kernel/http-transport.ts +0 -384
- package/node_modules/@humwick/kernel/identity-grammar.ts +0 -20
- package/node_modules/@humwick/kernel/identity.ts +0 -248
- package/node_modules/@humwick/kernel/index.ts +0 -28
- package/node_modules/@humwick/kernel/kernel-persistence.ts +0 -181
- package/node_modules/@humwick/kernel/landing-incident.ts +0 -306
- package/node_modules/@humwick/kernel/landing.ts +0 -953
- package/node_modules/@humwick/kernel/manifest-validation.ts +0 -460
- package/node_modules/@humwick/kernel/mcp-transport.ts +0 -109
- package/node_modules/@humwick/kernel/message-authority-chaos-worker.ts +0 -200
- package/node_modules/@humwick/kernel/message-authority.ts +0 -281
- package/node_modules/@humwick/kernel/module-host.ts +0 -722
- package/node_modules/@humwick/kernel/openapi-init.ts +0 -14
- package/node_modules/@humwick/kernel/package.json +0 -47
- package/node_modules/@humwick/kernel/persistence-schema.ts +0 -248
- package/node_modules/@humwick/kernel/persistence.ts +0 -510
- package/node_modules/@humwick/kernel/registry.ts +0 -60
- package/node_modules/@humwick/kernel/sqlite-kernel-persistence.ts +0 -499
- package/node_modules/@humwick/kernel/sqlite-module-host.ts +0 -87
- package/node_modules/@humwick/kernel/timers-chaos-worker.ts +0 -186
- package/node_modules/@humwick/kernel/timers.pilot.ts +0 -1411
- package/node_modules/@humwick/kernel/workflow-activation.ts +0 -25
- package/node_modules/@humwick/kernel/workflow-backstop.ts +0 -40
- package/node_modules/@humwick/kernel/workflow-cancel-tree.ts +0 -20
- package/node_modules/@humwick/kernel/workflow-chaos-worker.ts +0 -213
- package/node_modules/@humwick/kernel/workflow-composition.ts +0 -231
- package/node_modules/@humwick/kernel/workflow-container.ts +0 -72
- package/node_modules/@humwick/kernel/workflow-control.test-fixture.ts +0 -42
- package/node_modules/@humwick/kernel/workflow-control.ts +0 -178
- package/node_modules/@humwick/kernel/workflow-definition.ts +0 -507
- package/node_modules/@humwick/kernel/workflow-dispatch.ts +0 -60
- package/node_modules/@humwick/kernel/workflow-foreach.ts +0 -167
- package/node_modules/@humwick/kernel/workflow-journal-codec.ts +0 -339
- package/node_modules/@humwick/kernel/workflow-journal.ts +0 -922
- package/node_modules/@humwick/kernel/workflow-lane.ts +0 -48
- package/node_modules/@humwick/kernel/workflow-lease-owner.ts +0 -60
- package/node_modules/@humwick/kernel/workflow-recovery.test-fixture.ts +0 -19
- package/node_modules/@humwick/kernel/workflow-runtime.ts +0 -938
- package/node_modules/@humwick/kernel/workflow-script.ts +0 -11
- package/node_modules/@humwick/kernel/workflow-state.ts +0 -299
- package/node_modules/@humwick/kernel/workflow-step-commit.ts +0 -195
- package/node_modules/@humwick/kernel/workflow-transitions.ts +0 -317
- package/node_modules/@humwick/kernel/workflow-values.ts +0 -153
- package/node_modules/@humwick/kernel/workflow.pilot.ts +0 -376
- package/node_modules/@humwick/offload/LICENSE +0 -167
- package/node_modules/@humwick/offload/README.md +0 -57
- package/node_modules/@humwick/offload/dist/async-runner.d.ts +0 -18
- package/node_modules/@humwick/offload/dist/async-runner.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/async-runner.js +0 -158
- package/node_modules/@humwick/offload/dist/async-runner.js.map +0 -1
- package/node_modules/@humwick/offload/dist/envelope.d.ts +0 -25
- package/node_modules/@humwick/offload/dist/envelope.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/envelope.js +0 -80
- package/node_modules/@humwick/offload/dist/envelope.js.map +0 -1
- package/node_modules/@humwick/offload/dist/fixtures/worker-task.d.ts +0 -10
- package/node_modules/@humwick/offload/dist/fixtures/worker-task.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/fixtures/worker-task.js +0 -59
- package/node_modules/@humwick/offload/dist/fixtures/worker-task.js.map +0 -1
- package/node_modules/@humwick/offload/dist/index.d.ts +0 -5
- package/node_modules/@humwick/offload/dist/index.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/index.js +0 -5
- package/node_modules/@humwick/offload/dist/index.js.map +0 -1
- package/node_modules/@humwick/offload/dist/subprocess-runner.d.ts +0 -62
- package/node_modules/@humwick/offload/dist/subprocess-runner.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/subprocess-runner.js +0 -295
- package/node_modules/@humwick/offload/dist/subprocess-runner.js.map +0 -1
- package/node_modules/@humwick/offload/dist/types.d.ts +0 -111
- package/node_modules/@humwick/offload/dist/types.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/types.js +0 -176
- package/node_modules/@humwick/offload/dist/types.js.map +0 -1
- package/node_modules/@humwick/offload/dist/worker-pool.d.ts +0 -23
- package/node_modules/@humwick/offload/dist/worker-pool.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/worker-pool.js +0 -435
- package/node_modules/@humwick/offload/dist/worker-pool.js.map +0 -1
- package/node_modules/@humwick/offload/dist/worker-runtime.d.ts +0 -2
- package/node_modules/@humwick/offload/dist/worker-runtime.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/worker-runtime.js +0 -27
- package/node_modules/@humwick/offload/dist/worker-runtime.js.map +0 -1
- package/node_modules/@humwick/offload/dist/worker.d.ts +0 -5
- package/node_modules/@humwick/offload/dist/worker.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/worker.js +0 -1
- package/node_modules/@humwick/offload/dist/worker.js.map +0 -1
- package/node_modules/@humwick/offload/package.json +0 -46
- package/node_modules/@humwick/offload/src/async-runner.ts +0 -170
- package/node_modules/@humwick/offload/src/envelope.ts +0 -92
- package/node_modules/@humwick/offload/src/fixtures/worker-task.ts +0 -49
- package/node_modules/@humwick/offload/src/index.ts +0 -4
- package/node_modules/@humwick/offload/src/subprocess-runner.ts +0 -334
- package/node_modules/@humwick/offload/src/types.ts +0 -235
- package/node_modules/@humwick/offload/src/worker-pool.ts +0 -463
- package/node_modules/@humwick/offload/src/worker-runtime.ts +0 -32
- package/node_modules/@humwick/offload/src/worker.ts +0 -5
- package/public/assets/agent-liveness-DyqxfB-t.js +0 -2
- package/public/assets/agent-profiles-BpI_jTxq.js +0 -2
- package/public/assets/fleet-BL4UXS_k.js +0 -2
- package/public/assets/index-B7ZerHLY.css +0 -2
- package/public/assets/index-BK0WV6hF.js +0 -15
- package/public/assets/projects-B_lmcqfO.js +0 -2
- package/public/assets/provider-display-DbLWpP3j.js +0 -2
- package/public/assets/run-card-CO_bguQf.js +0 -2
- package/public/assets/use-project-list-B-T2Bnnn.js +0 -2
- package/public/assets/versioned-prompt-editor-Diu8BIaM.js +0 -8
- package/runner/src/gate-run-lease-probe.ts +0 -38
- package/src/db/claude-catalog-reconcile.ts +0 -27
- package/src/routing-model-aliases.ts +0 -21
|
@@ -100,11 +100,13 @@ function markLandingReplay(result: unknown): unknown {
|
|
|
100
100
|
|
|
101
101
|
export const COMMANDS_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.freeze({
|
|
102
102
|
"commands.claimPending": {
|
|
103
|
+
offLoop: true,
|
|
103
104
|
idempotent: true,
|
|
104
105
|
fn: (args: { id: string; expectedType?: string; ownerToken?: string }, ctx) =>
|
|
105
106
|
claimPendingCommand(args.id, args.expectedType, args.ownerToken, ctx.now),
|
|
106
107
|
},
|
|
107
108
|
"commands.createAgentCleanupIfAbsent": {
|
|
109
|
+
offLoop: true,
|
|
108
110
|
idempotent: false,
|
|
109
111
|
fn: (args: { target: string; id: string }, ctx: WriterOpContext) => hasActiveAgentCleanup(args.target) ? null
|
|
110
112
|
: createCommandInternal({ id: args.id, input: { type: "agent.cleanup", source: "system", target: args.target,
|
|
@@ -117,10 +119,12 @@ export const COMMANDS_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object
|
|
|
117
119
|
fn: (args: { command: Command }, ctx: WriterOpContext) => settleAgentCleanupWorkspaces(args.command, ctx.now),
|
|
118
120
|
},
|
|
119
121
|
"commands.reconcileScheduler": {
|
|
122
|
+
offLoop: true,
|
|
120
123
|
idempotent: true,
|
|
121
124
|
fn: (args: Parameters<typeof reconcileSchedulerCommandsBody>[0], ctx: WriterOpContext) => reconcileSchedulerCommandsBody(args, ctx.now),
|
|
122
125
|
},
|
|
123
126
|
"commands.createLegacyLanding": {
|
|
127
|
+
offLoop: true,
|
|
124
128
|
idempotent: false,
|
|
125
129
|
fn: (args: CreateLegacyLandingArgs, ctx: WriterOpContext) => createLegacyLandingBody(args, ctx.now),
|
|
126
130
|
serializeIdempotencyResult: redactCreateResult,
|
|
@@ -136,61 +140,74 @@ export const COMMANDS_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object
|
|
|
136
140
|
recordIdempotencyResult: (result) => (result as { claimed?: boolean } | null)?.claimed === true,
|
|
137
141
|
},
|
|
138
142
|
"commands.acceptLandingProgress": {
|
|
143
|
+
offLoop: true,
|
|
139
144
|
idempotent: false,
|
|
140
145
|
fn: (args: AcceptLandingProgressArgs, ctx: WriterOpContext) => acceptLandingProgressBody(args, ctx.now),
|
|
141
146
|
},
|
|
142
147
|
"commands.acceptLandingResult": {
|
|
148
|
+
offLoop: true,
|
|
143
149
|
idempotent: false,
|
|
144
150
|
fn: (args: AcceptLandingResultArgs, ctx: WriterOpContext) => acceptLandingResultBody(args, ctx.now),
|
|
145
151
|
replayIdempotencyResult: markLandingReplay,
|
|
146
152
|
},
|
|
147
153
|
"commands.resolveLegacyPublication": {
|
|
154
|
+
offLoop: true,
|
|
148
155
|
idempotent: true,
|
|
149
156
|
fn: (args: ResolveLegacyPublicationArgs, ctx: WriterOpContext) => resolveLegacyPublicationBody(args, ctx.now),
|
|
150
157
|
},
|
|
151
158
|
"commands.acquireLegacyPublishFence": {
|
|
159
|
+
offLoop: true,
|
|
152
160
|
idempotent: false,
|
|
153
161
|
fn: (args: AcquireLegacyPublishFenceArgs, ctx: WriterOpContext) => acquireLegacyPublishFenceBody(args, ctx.now),
|
|
154
162
|
},
|
|
155
163
|
"commands.acquireKernelPublishFence": {
|
|
164
|
+
offLoop: true,
|
|
156
165
|
idempotent: false,
|
|
157
166
|
fn: (args: AcquireKernelPublishFenceArgs, ctx: WriterOpContext) => acquireKernelPublishFenceBody(args, ctx.now),
|
|
158
167
|
},
|
|
159
168
|
"commands.requestLandingRetirement": {
|
|
169
|
+
offLoop: true,
|
|
160
170
|
idempotent: false,
|
|
161
171
|
fn: (args: RequestLandingRetirementArgs, ctx: WriterOpContext) =>
|
|
162
172
|
requestLandingRetirementBody(args, ctx.now),
|
|
163
173
|
},
|
|
164
174
|
"commands.grantKernelDryRunOwnership": {
|
|
175
|
+
offLoop: true,
|
|
165
176
|
idempotent: false,
|
|
166
177
|
fn: (args: GrantKernelDryRunOwnershipArgs, ctx: WriterOpContext) =>
|
|
167
178
|
grantKernelDryRunOwnershipBody(args, ctx.now),
|
|
168
179
|
},
|
|
169
180
|
"commands.consumeLegacyPublishPermit": {
|
|
181
|
+
offLoop: true,
|
|
170
182
|
idempotent: false,
|
|
171
183
|
fn: (args: ConsumeLegacyPublishPermitArgs, ctx: WriterOpContext) => consumeLegacyPublishPermitBody(args, ctx.now),
|
|
172
184
|
},
|
|
173
185
|
"commands.recordExecutionProof": {
|
|
186
|
+
offLoop: true,
|
|
174
187
|
idempotent: false,
|
|
175
188
|
fn: (args: RecordExecutionProofArgs, ctx: WriterOpContext) => recordExecutionProofBody(args, ctx.now),
|
|
176
189
|
replayIdempotencyResult: markLandingReplay,
|
|
177
190
|
},
|
|
178
191
|
"commands.terminalizeLegacyLanding": {
|
|
192
|
+
offLoop: true,
|
|
179
193
|
idempotent: false,
|
|
180
194
|
fn: (args: TerminalizeLegacyLandingArgs, ctx: WriterOpContext) => terminalizeLegacyLandingBody(args, ctx.now),
|
|
181
195
|
replayIdempotencyResult: markLandingReplay,
|
|
182
196
|
},
|
|
183
197
|
"commands.cancelPendingLegacyLandings": {
|
|
198
|
+
offLoop: true,
|
|
184
199
|
idempotent: true,
|
|
185
200
|
fn: (args: CancelPendingLegacyLandingsArgs, ctx: WriterOpContext) => cancelPendingLegacyLandingsBody(args, ctx.now),
|
|
186
201
|
},
|
|
187
202
|
// #2609 — the withdraw's legacy-lane mid-flight cancel (pending delegates to the never-started
|
|
188
203
|
// path; accepted/running is a fenced status CAS + publish-permit retirement).
|
|
189
204
|
"commands.cancelLegacyLandingExecution": {
|
|
205
|
+
offLoop: true,
|
|
190
206
|
idempotent: false,
|
|
191
207
|
fn: (args: CancelLegacyLandingExecutionArgs, ctx: WriterOpContext) => cancelLegacyLandingExecutionBody(args, ctx.now),
|
|
192
208
|
},
|
|
193
209
|
"commands.backfillLegacyLandingPage": {
|
|
210
|
+
offLoop: true,
|
|
194
211
|
idempotent: true,
|
|
195
212
|
fn: (args: { rows: BackfillLegacyLandingRow[] }, ctx: WriterOpContext) => backfillLegacyLandingPageBody(args, ctx.now),
|
|
196
213
|
},
|
|
@@ -221,6 +238,7 @@ export const COMMANDS_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object
|
|
|
221
238
|
// only when `commandUpdateHasPostCommitEffects` says there is something to do. Idempotent: the
|
|
222
239
|
// terminal-event record is guarded by an existence check and the pill re-sets the same meta keys.
|
|
223
240
|
"commands.applyUpdatePostCommit": {
|
|
241
|
+
offLoop: true,
|
|
224
242
|
idempotent: true,
|
|
225
243
|
fn: (args: ApplyCommandUpdatePostCommitOpArgs): null => {
|
|
226
244
|
applyCommandUpdatePostCommit(args.previousStatus, args.command);
|
|
@@ -230,6 +248,7 @@ export const COMMANDS_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object
|
|
|
230
248
|
// Spawn reaping must not overwrite a concurrent async success settlement. The status predicate
|
|
231
249
|
// lives inside this writer transaction, making the rows-changed result a real CAS winner signal.
|
|
232
250
|
"commands.cancelIfStatus": {
|
|
251
|
+
offLoop: true,
|
|
233
252
|
idempotent: false,
|
|
234
253
|
fn: (args: CancelCommandIfStatusWriteArgs, ctx: WriterOpContext) => cancelCommandIfStatusInternal(args, ctx.now),
|
|
235
254
|
serializeIdempotencyResult: redactCancelResult,
|
|
@@ -243,6 +262,7 @@ export const COMMANDS_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object
|
|
|
243
262
|
// submission recovers the SAME {command, created} from the ledger (so the emit survives an
|
|
244
263
|
// indeterminate ack), while a genuine later re-drive presents a fresh id and finds `created:false`.
|
|
245
264
|
"commands.createKernelIfAbsent": {
|
|
265
|
+
offLoop: true,
|
|
246
266
|
idempotent: false,
|
|
247
267
|
fn: (args: CreateKernelCommandIfAbsentArgs, ctx: WriterOpContext) => {
|
|
248
268
|
let input = args.input;
|
|
@@ -278,6 +298,7 @@ export const COMMANDS_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object
|
|
|
278
298
|
// One caller's quota admission is all-or-nothing: the live + in-flight reads and INSERT share this
|
|
279
299
|
// operation's transaction, rather than independent-caller coalescing/savepoints.
|
|
280
300
|
"commands.createSpawnWithinQuota": {
|
|
301
|
+
offLoop: true,
|
|
281
302
|
idempotent: false,
|
|
282
303
|
fn: (args: CreateSpawnCommandWithinQuotaWriteArgs, ctx: WriterOpContext) =>
|
|
283
304
|
createSpawnCommandWithinQuotaInternal(args, ctx.now),
|
|
@@ -13,14 +13,15 @@
|
|
|
13
13
|
// `_writer_idempotency`. That result is a `ConfigEntry` whose `value` is the SAME operator data already
|
|
14
14
|
// persisted verbatim in the `config` table of the SAME database file — so this introduces NO new
|
|
15
15
|
// at-rest exposure class (unlike a signed token, which is never otherwise stored). We therefore keep
|
|
16
|
-
// the real result in the ledger
|
|
17
|
-
//
|
|
16
|
+
// the real result in the ledger, except provider credentials: the ledger is a copy outside the live row,
|
|
17
|
+
// so it masks them like config_history does (#3540, #1870 S7).
|
|
18
18
|
|
|
19
19
|
import {
|
|
20
20
|
deleteConfigInternal,
|
|
21
21
|
setConfigInternal,
|
|
22
22
|
} from "../config-store.ts";
|
|
23
23
|
import type { ConfigEntry } from "../types.ts";
|
|
24
|
+
import { credentialFreeConfigValue } from "./provider-config-history.ts";
|
|
24
25
|
import type { WriterOpContext, WriterOpSpec } from "./write-ops.ts";
|
|
25
26
|
|
|
26
27
|
/** Structured-clone-safe args for `config.set` (H6: plain data only). `value` is arbitrary JSON. */
|
|
@@ -43,14 +44,20 @@ export const CONFIG_STORE_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Ob
|
|
|
43
44
|
// retry would double-bump/duplicate. The gateway requires an idempotencyKey (the facade supplies a
|
|
44
45
|
// per-submission one) and dedups on it in the SAME transaction as the write.
|
|
45
46
|
"config.set": {
|
|
47
|
+
offLoop: true,
|
|
46
48
|
idempotent: false,
|
|
47
49
|
idempotencySnapshotKey: (args: SetConfigOpArgs) => JSON.stringify([args.namespace, args.key]),
|
|
50
|
+
serializeIdempotencyResult: (result: unknown) => {
|
|
51
|
+
const entry = result as ConfigEntry;
|
|
52
|
+
return { ...entry, value: credentialFreeConfigValue(entry) };
|
|
53
|
+
},
|
|
48
54
|
fn: (args: SetConfigOpArgs, ctx: WriterOpContext): ConfigEntry =>
|
|
49
55
|
setConfigInternal(args.namespace, args.key, args.value, args.updatedBy, ctx.now),
|
|
50
56
|
},
|
|
51
57
|
// Idempotent by construction: deleting again finds no row (`existing` null → early false) and writes
|
|
52
58
|
// nothing, so re-applying converges. No key required.
|
|
53
59
|
"config.delete": {
|
|
60
|
+
offLoop: true,
|
|
54
61
|
idempotent: true,
|
|
55
62
|
fn: (args: DeleteConfigOpArgs, ctx: WriterOpContext): boolean =>
|
|
56
63
|
deleteConfigInternal(args.namespace, args.key, args.updatedBy, ctx.now),
|
|
@@ -3,6 +3,7 @@ import { getDbPath, runDbMaintenanceWorker } from "./connection.ts";
|
|
|
3
3
|
import { purgeContinuationArchives, type ContinuationArchivePurgeInput, type ContinuationArchivePurgeResult } from "./continuation-archive-purge.ts";
|
|
4
4
|
import { syncInMemoryContinuationArchiveSearchIndex, type ContinuationArchiveSearchSyncInput, type ContinuationArchiveSearchSyncResult } from "./continuation-archive-search.ts";
|
|
5
5
|
import { getGateway } from "./gateway.ts";
|
|
6
|
+
import type { appendContinuationArchiveRefs } from "./continuations.ts";
|
|
6
7
|
import type { archiveAndAdvanceContinuation, archiveContinuationSegment, getContinuationArchiveByRef, searchContinuationArchives } from "./continuation-archives.ts";
|
|
7
8
|
|
|
8
9
|
// Anything left after the budget is still removed, by the agent delete's cascade.
|
|
@@ -24,6 +25,10 @@ export function archiveAndAdvanceContinuationAsync(input: Parameters<typeof arch
|
|
|
24
25
|
return getGateway().write("continuationArchives.compact", { input }, { idempotencyKey: requestId }) as unknown as Promise<ReturnType<typeof archiveAndAdvanceContinuation>>;
|
|
25
26
|
}
|
|
26
27
|
|
|
28
|
+
export function appendContinuationArchiveRefsAsync(agentId: string, refs: string[]): Promise<ReturnType<typeof appendContinuationArchiveRefs>> {
|
|
29
|
+
return getGateway().write("continuationArchives.appendRefs", { agentId, refs }) as unknown as Promise<ReturnType<typeof appendContinuationArchiveRefs>>;
|
|
30
|
+
}
|
|
31
|
+
|
|
27
32
|
/**
|
|
28
33
|
* #3012 — catch the side FTS index up. A lock-free reader probe gates the run; the work runs in the
|
|
29
34
|
* maintenance subprocess against the side file's own write lock, never on the hub's loop. An
|
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
import { archiveAndAdvanceContinuation, archiveContinuationSegment } from "./continuation-archives.ts";
|
|
2
|
+
import { appendContinuationArchiveRefs } from "./continuations.ts";
|
|
2
3
|
import type { WriterOpContext, WriterOpSpec } from "./write-ops.ts";
|
|
3
4
|
|
|
4
5
|
export const CONTINUATION_ARCHIVES_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.freeze({
|
|
5
6
|
"continuationArchives.archive": {
|
|
7
|
+
offLoop: true,
|
|
6
8
|
idempotent: false,
|
|
7
9
|
fn: (args: { input: Parameters<typeof archiveContinuationSegment>[0] }, ctx: WriterOpContext) =>
|
|
8
10
|
archiveContinuationSegment({ ...args.input, now: args.input.now ?? ctx.now }),
|
|
9
11
|
},
|
|
10
12
|
"continuationArchives.compact": {
|
|
13
|
+
offLoop: true,
|
|
11
14
|
idempotent: false,
|
|
12
15
|
fn: (args: { input: Parameters<typeof archiveAndAdvanceContinuation>[0] }, ctx: WriterOpContext) =>
|
|
13
16
|
archiveAndAdvanceContinuation({ ...args.input, now: args.input.now ?? ctx.now }),
|
|
14
17
|
},
|
|
18
|
+
// #1870 S7: the envelope's ref list is a set, so a replay converges.
|
|
19
|
+
"continuationArchives.appendRefs": {
|
|
20
|
+
offLoop: true,
|
|
21
|
+
idempotent: true,
|
|
22
|
+
fn: (args: { agentId: string; refs: string[] }, ctx: WriterOpContext) => appendContinuationArchiveRefs(args.agentId, args.refs, ctx.now),
|
|
23
|
+
},
|
|
15
24
|
});
|
package/src/db/continuations.ts
CHANGED
|
@@ -143,7 +143,7 @@ function mergeLedger(
|
|
|
143
143
|
return { ledger: merged.slice(start), dropped: merged.slice(0, start) };
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
-
export function appendContinuationArchiveRefs(agentId: string, archiveRefs: string[]): ContinuationEnvelope | null {
|
|
146
|
+
export function appendContinuationArchiveRefs(agentId: string, archiveRefs: string[], now: number = Date.now()): ContinuationEnvelope | null {
|
|
147
147
|
if (archiveRefs.length === 0) return getContinuationEnvelope(agentId);
|
|
148
148
|
const existing = getContinuationEnvelope(agentId);
|
|
149
149
|
if (!existing) return null;
|
|
@@ -155,7 +155,7 @@ export function appendContinuationArchiveRefs(agentId: string, archiveRefs: stri
|
|
|
155
155
|
UPDATE agent_continuations
|
|
156
156
|
SET archive_refs = ?, updated_at = ?
|
|
157
157
|
WHERE agent_id = ?
|
|
158
|
-
`).run(JSON.stringify(refs),
|
|
158
|
+
`).run(JSON.stringify(refs), now, agentId);
|
|
159
159
|
return getContinuationEnvelope(agentId);
|
|
160
160
|
}
|
|
161
161
|
|
|
@@ -14,12 +14,19 @@
|
|
|
14
14
|
// It default-exports the offload task function; `createWorkerPool` invokes it via the offload
|
|
15
15
|
// worker-runtime bootstrap.
|
|
16
16
|
|
|
17
|
+
import { relayEnv } from "@humwick/sdk/env";
|
|
17
18
|
import type { OffloadWorkerTask } from "@humwick/offload/worker";
|
|
18
19
|
import { Database } from "bun:sqlite";
|
|
19
20
|
import { applyConnectionPragmas, closeDb, getDbPath, setDb } from "./connection.ts";
|
|
20
21
|
import { serializeDbError } from "./db-error-registry.ts";
|
|
21
22
|
import { runWriterBatch, runWriterOp, type SerializedBatchEntry, type WriterJobInput, type WriterJobResult } from "./write-ops.ts";
|
|
22
23
|
|
|
24
|
+
// A lock-contention test may shorten the wait; production keeps 4 s.
|
|
25
|
+
function writerBusyTimeoutMs(): number {
|
|
26
|
+
const override = Number(relayEnv(process.env, "AGENT_RELAY_WRITER_BUSY_TIMEOUT_MS")?.trim() || Number.NaN);
|
|
27
|
+
return Number.isSafeInteger(override) && override >= 0 ? override : 4000;
|
|
28
|
+
}
|
|
29
|
+
|
|
23
30
|
/** Ensure this worker's thread-local RW connection points at `dbPath`, opening it once and reusing
|
|
24
31
|
* it across jobs. A path change (never expected in production) reopens — cheap and defensive. */
|
|
25
32
|
function ensureConnection(dbPath: string): void {
|
|
@@ -33,7 +40,7 @@ function ensureConnection(dbPath: string): void {
|
|
|
33
40
|
// per-connection pragmas before it begins executing serialized write operations.
|
|
34
41
|
applyConnectionPragmas(conn, { ensureWal: false });
|
|
35
42
|
// #1870: external 1.2 s holds wait here, below the gateway's 5 s deadline, never on the loop.
|
|
36
|
-
conn.run(
|
|
43
|
+
conn.run(`PRAGMA busy_timeout = ${writerBusyTimeoutMs()}`);
|
|
37
44
|
setDb(conn, dbPath);
|
|
38
45
|
}
|
|
39
46
|
|
|
@@ -40,23 +40,27 @@ export interface ApplyDeliveryActionOpArgs {
|
|
|
40
40
|
|
|
41
41
|
export const DELIVERY_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.freeze({
|
|
42
42
|
"delivery.recordChannelFanoutSuppression": {
|
|
43
|
+
offLoop: true,
|
|
43
44
|
idempotent: true,
|
|
44
45
|
fn: (args: { messageId: number; channelAgentId: string; reason: string }, ctx: WriterOpContext) =>
|
|
45
46
|
recordChannelFanoutSuppression(args.messageId, args.channelAgentId, args.reason, ctx.now),
|
|
46
47
|
},
|
|
47
48
|
"delivery.recordAttempt": {
|
|
49
|
+
offLoop: true,
|
|
48
50
|
idempotent: false,
|
|
49
51
|
idempotencySnapshotKey: (args: RecordDeliveryAttemptOpArgs) => String(args.messageId),
|
|
50
52
|
fn: (args: RecordDeliveryAttemptOpArgs, ctx: WriterOpContext) =>
|
|
51
53
|
recordMessageDeliveryAttempt(args.messageId, args.input, ctx.now),
|
|
52
54
|
},
|
|
53
55
|
"delivery.applyAction": {
|
|
56
|
+
offLoop: true,
|
|
54
57
|
idempotent: false,
|
|
55
58
|
idempotencySnapshotKey: (args: ApplyDeliveryActionOpArgs) => String(args.messageId),
|
|
56
59
|
fn: (args: ApplyDeliveryActionOpArgs, ctx: WriterOpContext) =>
|
|
57
60
|
applyMessageDeliveryAction(args.messageId, args.input, ctx.now),
|
|
58
61
|
},
|
|
59
62
|
"delivery.reevaluate": {
|
|
63
|
+
offLoop: true,
|
|
60
64
|
idempotent: true,
|
|
61
65
|
fn: (args: ApplyDeliveryActionOpArgs, ctx: WriterOpContext) =>
|
|
62
66
|
applyMessageDeliveryAction(args.messageId, args.input, ctx.now),
|
|
@@ -66,6 +70,7 @@ export const DELIVERY_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object
|
|
|
66
70
|
// elapsed time (chiefly tests) needs to drive it directly rather than only via real wall-clock
|
|
67
71
|
// submission time. Production callers omit it and get ctx.now, per H6.
|
|
68
72
|
"delivery.expireQueued": {
|
|
73
|
+
offLoop: true,
|
|
69
74
|
idempotent: true,
|
|
70
75
|
fn: (args: { now?: number }, ctx: WriterOpContext) => expireQueuedMessagesWithNotices(args?.now ?? ctx.now),
|
|
71
76
|
},
|
|
@@ -25,6 +25,7 @@ export function tryBeginDeployEventAsync(input: TryBeginDeployEventInput): Promi
|
|
|
25
25
|
export function backfillDeployEventVersionAsync(id: string, version: string): Promise<DeployEvent | null> {
|
|
26
26
|
return write("deployEvents.backfillVersion", { id, version });
|
|
27
27
|
}
|
|
28
|
+
export function getDeployEventForCommitAsync(commitSha: string): Promise<DeployEvent | null> { return read("deployEvents.forCommit", { commitSha }); }
|
|
28
29
|
export function getDeployEventAsync(id: string): Promise<DeployEvent | null> { return read("deployEvents.get", { id }); }
|
|
29
30
|
export function listDeployEventsAsync(limit: number, offset: number): Promise<DeployEvent[]> {
|
|
30
31
|
return read("deployEvents.list", { limit, offset });
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import {
|
|
4
4
|
currentPendingDeployEvent,
|
|
5
5
|
deployChangesForCommits,
|
|
6
|
-
getDeployEvent,
|
|
6
|
+
getDeployEvent, getDeployEventForCommit,
|
|
7
7
|
latestFailedDeployForCommit,
|
|
8
8
|
latestSuccessfulDeploy,
|
|
9
9
|
listDeployEvents,
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
} from "./deploy-events.ts";
|
|
15
15
|
|
|
16
16
|
export const DEPLOY_EVENTS_READ_OPS = {
|
|
17
|
+
"deployEvents.forCommit": (args: { commitSha: string }): DeployEvent | null => getDeployEventForCommit(args.commitSha),
|
|
17
18
|
"deployEvents.get": (args: { id: string }): DeployEvent | null => getDeployEvent(args.id),
|
|
18
19
|
"deployEvents.list": (args: { limit: number; offset: number }): DeployEvent[] => listDeployEvents(args.limit, args.offset),
|
|
19
20
|
"deployEvents.needingChanges": (args: { limit: number }): DeployEvent[] => listDeployEventsNeedingChanges(args.limit),
|
package/src/db/deploy-events.ts
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
+
import { defaultTaskIssueRelation } from "./task-issue-relation";
|
|
2
|
+
import { parseJson, type TaskDispatch } from "@humwick/sdk";
|
|
1
3
|
import { randomUUID } from "node:crypto";
|
|
2
4
|
import { getDb, writeTransaction } from "./connection.ts";
|
|
3
5
|
import { setTaskStageBody } from "./task-entity.ts";
|
|
4
6
|
import { insertTaskEvent } from "./task-core.ts";
|
|
5
7
|
import { listIssuesForEntity } from "./issue-associations.ts";
|
|
6
|
-
import type { IssueRef } from "../types";
|
|
8
|
+
import type { IssueRef, IssueRefRelation } from "../types";
|
|
7
9
|
|
|
8
10
|
export type DeployStatus = "pending" | "succeeded" | "failed" | "rolled-back";
|
|
9
11
|
export type DeployHost = { id: string; fromVersion?: string; toVersion?: string; status: string; reason?: string };
|
|
10
12
|
export type DeployCommit = { sha: string; subject: string };
|
|
11
|
-
export type DeployTaskChange = { id: number; label: string; issues: IssueRef
|
|
13
|
+
export type DeployTaskChange = { id: number; label: string; issues: Array<IssueRef & { relation?: IssueRefRelation }>; onDeploy?: string };
|
|
12
14
|
export type DeployChangesSummary = {
|
|
13
15
|
range: { previousSha?: string; commitSha: string };
|
|
14
16
|
tasks: DeployTaskChange[];
|
|
@@ -219,6 +221,24 @@ export function getDeployEvent(id: string): DeployEvent | null {
|
|
|
219
221
|
return row ? rowToDeployEvent(row) : null;
|
|
220
222
|
}
|
|
221
223
|
|
|
224
|
+
/** The running artifact may boot while its deploy ledger is still pending (#3761). */
|
|
225
|
+
export function getDeployEventForCommit(commitSha: string): DeployEvent | null {
|
|
226
|
+
const row = getDb().query("SELECT * FROM deploy_events WHERE commit_sha = ? ORDER BY started_at DESC LIMIT 1").get(commitSha);
|
|
227
|
+
const event = row ? rowToDeployEvent(row) : null;
|
|
228
|
+
if (event?.changes?.state === "ready" && event.changes.tasks.length) {
|
|
229
|
+
const notes = getDb().query("SELECT id, on_deploy, dispatch, owner_agent_id FROM tasks WHERE id IN (SELECT value FROM json_each(?))")
|
|
230
|
+
.all(JSON.stringify(event.changes.tasks.map(task => task.id))) as Array<{ id: number; on_deploy: string | null; dispatch: string | null; owner_agent_id: string | null }>;
|
|
231
|
+
const byId = new Map(notes.map(task => [task.id, task]));
|
|
232
|
+
event.changes.tasks = event.changes.tasks.map(task => {
|
|
233
|
+
const { onDeploy, ...snapshot } = task;
|
|
234
|
+
const current = byId.get(task.id);
|
|
235
|
+
const note = current ? current.on_deploy : onDeploy;
|
|
236
|
+
return { ...snapshot, ...(current ? { issues: deployTaskIssues(task.id, current.dispatch, current.owner_agent_id) } : {}), ...(note ? { onDeploy: note } : {}) };
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
return event;
|
|
240
|
+
}
|
|
241
|
+
|
|
222
242
|
/** Newest-first page of the deploy ledger for the dashboard timeline (#1327). */
|
|
223
243
|
export function listDeployEvents(limit: number, offset: number): DeployEvent[] {
|
|
224
244
|
const rows = getDb()
|
|
@@ -250,6 +270,11 @@ export function listDeployEventsNeedingChanges(limit: number): DeployEvent[] {
|
|
|
250
270
|
return rows.map(rowToDeployEvent);
|
|
251
271
|
}
|
|
252
272
|
|
|
273
|
+
function deployTaskIssues(id: number, dispatch: string | null, ownerAgentId: string | null): DeployTaskChange["issues"] {
|
|
274
|
+
const relation = defaultTaskIssueRelation(parseJson<TaskDispatch | undefined>(dispatch, undefined), ownerAgentId ?? undefined);
|
|
275
|
+
return listIssuesForEntity("task", String(id)).map(item => ({ ...item.issueRef, relation: item.association.relation ?? relation }));
|
|
276
|
+
}
|
|
277
|
+
|
|
253
278
|
/**
|
|
254
279
|
* Match a deploy's ordered commit list to every durable Task with an exact stored
|
|
255
280
|
* commit SHA. This CD-only query loads the task commit payload once; the HTTP
|
|
@@ -258,7 +283,7 @@ export function listDeployEventsNeedingChanges(limit: number): DeployEvent[] {
|
|
|
258
283
|
export function deployChangesForCommits(commits: DeployCommit[]): Pick<DeployChangesSummary, "tasks" | "unmatchedCommits"> {
|
|
259
284
|
const rangeShas = new Set(commits.map((commit) => commit.sha));
|
|
260
285
|
const matchedShas = new Set<string>();
|
|
261
|
-
const rows = getDb().query("SELECT id, title, commits FROM tasks WHERE kind = 'deliverable' AND commits IS NOT NULL ORDER BY id ASC").all() as any[];
|
|
286
|
+
const rows = getDb().query("SELECT id, title, commits, on_deploy, dispatch, owner_agent_id FROM tasks WHERE kind = 'deliverable' AND commits IS NOT NULL ORDER BY id ASC").all() as any[];
|
|
262
287
|
const tasks: DeployTaskChange[] = [];
|
|
263
288
|
for (const row of rows) {
|
|
264
289
|
let taskCommits: Array<{ sha?: unknown }>;
|
|
@@ -268,7 +293,8 @@ export function deployChangesForCommits(commits: DeployCommit[]): Pick<DeployCha
|
|
|
268
293
|
tasks.push({
|
|
269
294
|
id: Number(row.id),
|
|
270
295
|
label: String(row.title),
|
|
271
|
-
issues:
|
|
296
|
+
issues: deployTaskIssues(Number(row.id), row.dispatch, row.owner_agent_id),
|
|
297
|
+
...(row.on_deploy ? { onDeploy: String(row.on_deploy) } : {}),
|
|
272
298
|
});
|
|
273
299
|
}
|
|
274
300
|
return { tasks, unmatchedCommits: commits.filter((commit) => !matchedShas.has(commit.sha)) };
|
|
@@ -316,6 +342,11 @@ export function renewDeployEventLease(input: { id: string; now?: number }): bool
|
|
|
316
342
|
return writeTransaction(() => renewDeployEventLeaseBody(input, input.now ?? Date.now()));
|
|
317
343
|
}
|
|
318
344
|
|
|
345
|
+
/** Migration progress shares the existing deploy row and dashboard surface (#3470). */
|
|
346
|
+
export function recordDeployEventHosts(id: string, hosts: DeployHost[]): boolean {
|
|
347
|
+
return getDb().query("UPDATE deploy_events SET hosts = ? WHERE id = ? AND status = 'pending'").run(JSON.stringify(hosts), id).changes > 0;
|
|
348
|
+
}
|
|
349
|
+
|
|
319
350
|
/**
|
|
320
351
|
* Emergency operator recovery for a genuinely stranded deploy owner:
|
|
321
352
|
* `bun run scripts/release.ts --clear-deploy-lease <event-id>` (→ `failed`), or
|
|
@@ -139,8 +139,16 @@ export type HardwareReconciliation =
|
|
|
139
139
|
|
|
140
140
|
/** Capacity is an observed, runtime-varying property, not host identity. WSL2 in particular can
|
|
141
141
|
* report less RAM after a reboot, and swap may appear/disappear with zram configuration. Keep the
|
|
142
|
-
* latest value for placement without making a legitimate capacity change an anti-spoof conflict.
|
|
143
|
-
|
|
142
|
+
* latest value for placement without making a legitimate capacity change an anti-spoof conflict.
|
|
143
|
+
* `osVersion` (the kernel string) changes on every OS patch; it is not hardware identity (#3770). */
|
|
144
|
+
const TOLERANT_CAPACITY_HARDWARE_FIELDS = new Set(["totalMemMb", "totalStorageMb", "totalSwapMb", "osVersion"]);
|
|
145
|
+
|
|
146
|
+
/** The identity-defining keys present on both sides with different values: what a conflict notice names. */
|
|
147
|
+
export function conflictingHardwareFields(stored: HostHardware, reported: HostHardware): string[] {
|
|
148
|
+
const a = stored as unknown as Record<string, unknown>;
|
|
149
|
+
const b = reported as unknown as Record<string, unknown>;
|
|
150
|
+
return Object.keys(a).filter((key) => !TOLERANT_CAPACITY_HARDWARE_FIELDS.has(key) && a[key] !== undefined && b[key] !== undefined && a[key] !== b[key]).sort();
|
|
151
|
+
}
|
|
144
152
|
|
|
145
153
|
export function reconcileHardwareFields(stored: HostHardware, reported: HostHardware): HardwareReconciliation {
|
|
146
154
|
const storedRec = stored as unknown as Record<string, unknown>;
|
|
@@ -27,6 +27,7 @@ export const HOSTS_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.fr
|
|
|
27
27
|
// Idempotent by construction (re-registration converges; conflict/join tags flip only on the
|
|
28
28
|
// transition), so no idempotencyKey is required.
|
|
29
29
|
"hosts.upsertFromRegistration": {
|
|
30
|
+
offLoop: true,
|
|
30
31
|
idempotent: true,
|
|
31
32
|
fn: (a: HostRegistrationInput, ctx) => upsertHostFromRegistrationInternal(a, ctx.now),
|
|
32
33
|
},
|
|
@@ -36,42 +37,52 @@ export const HOSTS_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.fr
|
|
|
36
37
|
// the gateway's bounded-queue shedding policy, dropping a utilization update is the correct
|
|
37
38
|
// outcome, because the next beat supersedes it 30 s later (§8).
|
|
38
39
|
"hosts.recordUtilization": {
|
|
40
|
+
offLoop: true,
|
|
39
41
|
idempotent: true,
|
|
40
42
|
fn: (a: Parameters<typeof recordHostUtilizationInternal>[0]) => recordHostUtilizationInternal(a),
|
|
41
43
|
},
|
|
42
44
|
"hosts.setLabel": {
|
|
45
|
+
offLoop: true,
|
|
43
46
|
idempotent: true,
|
|
44
47
|
fn: (a: { id: string; label: string }) => setHostLabelInternal(a.id, a.label),
|
|
45
48
|
},
|
|
46
49
|
"hosts.setTags": {
|
|
50
|
+
offLoop: true,
|
|
47
51
|
idempotent: true,
|
|
48
52
|
fn: (a: { id: string; tags: string[] }) => setHostTagsInternal(a.id, a.tags),
|
|
49
53
|
},
|
|
50
54
|
"hosts.acceptHardware": {
|
|
55
|
+
offLoop: true,
|
|
51
56
|
idempotent: true,
|
|
52
57
|
fn: (a: { id: string }) => acceptHostHardwareInternal(a.id),
|
|
53
58
|
},
|
|
54
59
|
"hosts.setEnabled": {
|
|
60
|
+
offLoop: true,
|
|
55
61
|
idempotent: true,
|
|
56
62
|
fn: (a: { id: string; enabled: boolean }) => setHostEnabledInternal(a.id, a.enabled),
|
|
57
63
|
},
|
|
58
64
|
"hosts.setLandingPlacement": {
|
|
65
|
+
offLoop: true,
|
|
59
66
|
idempotent: true,
|
|
60
67
|
fn: (a: { id: string; noLandingWorkspaces: boolean | null }) => setHostLandingPlacementInternal(a.id, a.noLandingWorkspaces),
|
|
61
68
|
},
|
|
62
69
|
"hosts.setAgentCap": {
|
|
70
|
+
offLoop: true,
|
|
63
71
|
idempotent: true,
|
|
64
72
|
fn: (a: { id: string; maxAgents: number | null }) => setHostPlacementPolicyInternal(a.id, "maxAgents", a.maxAgents),
|
|
65
73
|
},
|
|
66
74
|
"hosts.setLandingCap": {
|
|
75
|
+
offLoop: true,
|
|
67
76
|
idempotent: true,
|
|
68
77
|
fn: (a: { id: string; maxLandingSlots: number | null }) => setHostPlacementPolicyInternal(a.id, "maxLandingSlots", a.maxLandingSlots),
|
|
69
78
|
},
|
|
70
79
|
"hosts.setGateBudget": {
|
|
80
|
+
offLoop: true,
|
|
71
81
|
idempotent: true,
|
|
72
82
|
fn: (a: { id: string } & HostGatePolicyPatch) => { const { id, ...patch } = a; return setHostGatePolicyInternal(id, patch); },
|
|
73
83
|
},
|
|
74
84
|
"hosts.setAdmission": {
|
|
85
|
+
offLoop: true,
|
|
75
86
|
idempotent: true,
|
|
76
87
|
fn: (a: { id: string; flags: Pick<HostPolicy, "spawnEnabled" | "gatesEnabled"> }, ctx) => {
|
|
77
88
|
const host = setHostAdmissionInternal(a.id, a.flags);
|
|
@@ -80,14 +91,17 @@ export const HOSTS_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.fr
|
|
|
80
91
|
},
|
|
81
92
|
},
|
|
82
93
|
"hosts.setPolicy": {
|
|
94
|
+
offLoop: true,
|
|
83
95
|
idempotent: true,
|
|
84
96
|
fn: (a: { id: string; policy: HostPolicy }) => setHostPolicyInternal(a.id, a.policy),
|
|
85
97
|
},
|
|
86
98
|
"hosts.claimAlias": {
|
|
99
|
+
offLoop: true,
|
|
87
100
|
idempotent: true,
|
|
88
101
|
fn: (a: { hostId: string; alias: string; source: string }, ctx) => claimHostAliasInternal(a.hostId, a.alias, a.source, ctx.now),
|
|
89
102
|
},
|
|
90
103
|
"hosts.releaseAlias": {
|
|
104
|
+
offLoop: true,
|
|
91
105
|
idempotent: true,
|
|
92
106
|
fn: (a: { alias: string }) => releaseHostAliasInternal(a.alias),
|
|
93
107
|
},
|
package/src/db/hosts.ts
CHANGED
|
@@ -9,6 +9,7 @@ import type { Host, HostDaemonSample, HostHardware, HostMachineSample, HostPolic
|
|
|
9
9
|
import { normalizeHostToken, parseJson } from "../utils";
|
|
10
10
|
import { getDb } from "./connection.ts";
|
|
11
11
|
import { primeHostAliases, type HostAliasRecord } from "../host/identity.ts";
|
|
12
|
+
import { settleDiskWatch, type DiskAlert } from "../host/disk-alert.ts";
|
|
12
13
|
import { settleGateArming, type GateCapacityAlert } from "../host/gate-capacity-alert.ts";
|
|
13
14
|
|
|
14
15
|
function rowToHost(row: any): Host {
|
|
@@ -99,18 +100,20 @@ function storedSample<T extends { at: number }>(table: "hosts" | "orchestrators"
|
|
|
99
100
|
*/
|
|
100
101
|
export function recordHostUtilizationInternal(
|
|
101
102
|
input: { hostId: string; orchestratorId: string; machine: HostMachineSample; daemon: HostDaemonSample },
|
|
102
|
-
): { hostUpdated: boolean; generationUpdated: boolean; gateAlert?: GateCapacityAlert; hostLabel?: string } {
|
|
103
|
+
): { hostUpdated: boolean; generationUpdated: boolean; gateAlert?: GateCapacityAlert; diskAlert?: DiskAlert; hostLabel?: string } {
|
|
103
104
|
// `last_seen_at` is deliberately NOT touched here: it is the Host's freshness clock and the §3.5
|
|
104
105
|
// seam already bumps it on every beat with the RELAY's clock. `machine.at` is the PRODUCER's wall
|
|
105
106
|
// clock, so writing it here would let a skewed daemon move a Host's liveness backwards.
|
|
106
107
|
const prevHost = storedSample<HostMachineSample>("hosts", input.hostId);
|
|
107
108
|
let hostUpdated = false;
|
|
108
109
|
let gateAlert: GateCapacityAlert | undefined;
|
|
110
|
+
let diskAlert: DiskAlert | undefined;
|
|
109
111
|
if (!prevHost || input.machine.at > prevHost.at) {
|
|
110
|
-
// #2822 — settled inside this single-writer read-modify-write, so each transition alerts once.
|
|
111
|
-
const
|
|
112
|
+
// #2822 / #3762 — settled inside this single-writer read-modify-write, so each transition alerts once.
|
|
113
|
+
const gate = settleGateArming(prevHost ?? undefined, input.machine);
|
|
114
|
+
const settled = settleDiskWatch(prevHost ?? undefined, gate.machine);
|
|
112
115
|
hostUpdated = getDb().query("UPDATE hosts SET utilization = ? WHERE id = ?").run(JSON.stringify(settled.machine), input.hostId).changes > 0;
|
|
113
|
-
if (hostUpdated) gateAlert = settled.alert;
|
|
116
|
+
if (hostUpdated) { gateAlert = gate.alert; diskAlert = settled.alert; }
|
|
114
117
|
}
|
|
115
118
|
|
|
116
119
|
const generationAt = storedSample<HostDaemonSample>("orchestrators", input.orchestratorId)?.at ?? null;
|
|
@@ -118,9 +121,9 @@ export function recordHostUtilizationInternal(
|
|
|
118
121
|
? false
|
|
119
122
|
: getDb().query("UPDATE orchestrators SET utilization = ? WHERE id = ?").run(JSON.stringify(input.daemon), input.orchestratorId).changes > 0;
|
|
120
123
|
|
|
121
|
-
if (!gateAlert) return { hostUpdated, generationUpdated };
|
|
124
|
+
if (!gateAlert && !diskAlert) return { hostUpdated, generationUpdated };
|
|
122
125
|
const label = (getDb().query("SELECT label FROM hosts WHERE id = ?").get(input.hostId) as { label: string } | null)?.label;
|
|
123
|
-
return { hostUpdated, generationUpdated, gateAlert, hostLabel: label ?? input.hostId };
|
|
126
|
+
return { hostUpdated, generationUpdated, ...(gateAlert ? { gateAlert } : {}), ...(diskAlert ? { diskAlert } : {}), hostLabel: label ?? input.hostId };
|
|
124
127
|
}
|
|
125
128
|
|
|
126
129
|
export function setHostLabelInternal(id: string, label: string): Host | null {
|
|
@@ -4,20 +4,24 @@ import type { WriterOpContext, WriterOpSpec } from "./write-ops.ts";
|
|
|
4
4
|
|
|
5
5
|
export const INBOX_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.freeze({
|
|
6
6
|
"inbox.setThreadState": {
|
|
7
|
+
offLoop: true,
|
|
7
8
|
idempotent: true,
|
|
8
9
|
fn: (args: { input: Parameters<typeof setInboxThreadState>[0] }, ctx: WriterOpContext) =>
|
|
9
10
|
setInboxThreadState(args.input, ctx.now),
|
|
10
11
|
},
|
|
11
12
|
"inbox.setDraft": {
|
|
13
|
+
offLoop: true,
|
|
12
14
|
idempotent: true,
|
|
13
15
|
fn: (args: { input: Parameters<typeof setInboxDraft>[0] }, ctx: WriterOpContext) =>
|
|
14
16
|
setInboxDraft(args.input, ctx.now, false),
|
|
15
17
|
},
|
|
16
18
|
"inbox.deleteDraft": {
|
|
19
|
+
offLoop: true,
|
|
17
20
|
idempotent: true,
|
|
18
21
|
fn: (args: { operatorId: string; peerId: string }) => deleteInboxDraft(args.operatorId, args.peerId),
|
|
19
22
|
},
|
|
20
23
|
"inbox.createHistoryImport": {
|
|
24
|
+
offLoop: true,
|
|
21
25
|
idempotent: true,
|
|
22
26
|
fn: (args: { input: Parameters<typeof createChatHistoryImport>[0] }, ctx: WriterOpContext) =>
|
|
23
27
|
createChatHistoryImport(args.input, ctx.now, false),
|
package/src/db/inbox.ts
CHANGED
|
@@ -1,18 +1,4 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
-
import { isRecord, stringValue, isMechanicalMessageKind } from "@humwick/sdk";
|
|
3
|
-
import { ORCHESTRATOR_PROTOCOL_VERSION, VERSION } from "../config.ts";
|
|
4
|
-
import { parseJson } from "../utils";
|
|
5
|
-
import { isLiveIsolatedWorkspace } from "../workspace-phase";
|
|
6
|
-
import {
|
|
7
|
-
CONTRACT_REQUIREMENTS,
|
|
8
|
-
contractCompatibility,
|
|
9
|
-
parseRuntimeCapabilities,
|
|
10
|
-
parseRuntimeContracts,
|
|
11
|
-
parseRuntimePackage,
|
|
12
|
-
type RuntimeContracts,
|
|
13
|
-
} from "../contracts";
|
|
14
|
-
import { STALE_TTL_MS, DAY_MS, CLAIM_LEASE_MS, POOL_CLAIM_LEASE_MS, WORKSPACE_MERGE_LEASE_MS } from "../config";
|
|
15
|
-
import { matchAgents } from "../agent-ref";
|
|
16
2
|
import { ValidationError, getDb, writeTransaction } from "./connection.ts";
|
|
17
3
|
import { rowToChatHistoryImport, rowToChatHistoryImportEntry, rowToInboxDraft, rowToInboxThreadState } from "./mappers.ts";
|
|
18
4
|
import { getMessage } from "./messages.ts";
|
package/src/db/index.ts
CHANGED
|
@@ -44,6 +44,7 @@ export * from "./task-comment-through-async.ts";
|
|
|
44
44
|
export * from "./deploy-events.ts";
|
|
45
45
|
export * from "./deploy-events-async.ts";
|
|
46
46
|
export * from "./integrations.ts";
|
|
47
|
+
export * from "./integrations-async.ts";
|
|
47
48
|
export * from "./pairs.ts";
|
|
48
49
|
export * from "./artifacts.ts";
|
|
49
50
|
export * from "./artifact-browse.ts";
|
|
@@ -75,6 +76,7 @@ export * from "./orchestrators-async.ts";
|
|
|
75
76
|
export * from "./hosts.ts";
|
|
76
77
|
export * from "./hosts-async.ts";
|
|
77
78
|
export type { HostRegistrationEvent, HostRegistrationInput, HostRegistrationResult } from "./hosts-registration.ts";
|
|
79
|
+
export { conflictingHardwareFields } from "./hosts-registration.ts";
|
|
78
80
|
export * from "./workspaces.ts";
|
|
79
81
|
export * from "./workspace-writes.ts";
|
|
80
82
|
export * from "./workspace-writes-async.ts";
|
|
@@ -7,6 +7,7 @@ import type { WriterOpContext, WriterOpSpec } from "./write-ops.ts";
|
|
|
7
7
|
|
|
8
8
|
export const INSIGHTS_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.freeze({
|
|
9
9
|
"insights.observations.record": {
|
|
10
|
+
offLoop: true,
|
|
10
11
|
// An observation is append-only; callers must provide the per-request key carried by the facade.
|
|
11
12
|
idempotent: false,
|
|
12
13
|
fn: (args: { input: Parameters<typeof recordObservation>[1] }, ctx: WriterOpContext) =>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { getGateway } from "./gateway.ts";
|
|
2
|
+
import type { IntegrationRegistryInput, reconcileIntegrationRegistry } from "./integrations.ts";
|
|
3
|
+
|
|
4
|
+
export const listIntegrationTaskStatsAsync = () => getGateway().read("integrations.taskStats", undefined);
|
|
5
|
+
|
|
6
|
+
export async function reconcileIntegrationRegistryAsync(configured: IntegrationRegistryInput[], observedSources: string[]): Promise<ReturnType<typeof reconcileIntegrationRegistry>> {
|
|
7
|
+
return await getGateway().write("integrations.reconcileRegistry", { configured, observedSources }) as unknown as ReturnType<typeof reconcileIntegrationRegistry>;
|
|
8
|
+
}
|