@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
package/src/db/orchestrators.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { isDeepStrictEqual } from "node:util";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { ORCHESTRATOR_PROTOCOL_VERSION, VERSION } from "../config.ts";
|
|
2
|
+
import { stringValue, orchestratorAgentId } from "@humwick/sdk";
|
|
3
|
+
import { VERSION } from "../config.ts";
|
|
5
4
|
import { parseJson } from "../utils";
|
|
6
|
-
import { isLiveIsolatedWorkspace } from "../workspace-phase";
|
|
7
5
|
import {
|
|
8
6
|
CONTRACT_REQUIREMENTS,
|
|
9
7
|
contractCompatibility,
|
|
@@ -12,77 +10,13 @@ import {
|
|
|
12
10
|
parseRuntimePackage,
|
|
13
11
|
type RuntimeContracts,
|
|
14
12
|
} from "../contracts";
|
|
15
|
-
import { STALE_TTL_MS
|
|
16
|
-
import {
|
|
17
|
-
import { deleteAgent, heartbeat, upsertAgent } from "./agents.ts";
|
|
13
|
+
import { STALE_TTL_MS } from "../config";
|
|
14
|
+
import { deleteAgent, heartbeat, upsertAgent, upsertAgentInternal, type UpsertAgentTxResult } from "./agents.ts";
|
|
18
15
|
import { evictPendingPresence } from "./presence-buffer.ts";
|
|
19
16
|
import { getDb, writeTransaction } from "./connection.ts";
|
|
20
17
|
import { fencedColumnSql, nextLifecycleSeq } from "./lifecycle-seq.ts";
|
|
21
18
|
import { electWorkspaceStewards, emitWorkspaceUpsert, getWorkspace, upsertWorkspaceFromManagedAgentRow, type WorkspaceUpsertResult } from "./workspaces.ts";
|
|
22
|
-
import type {
|
|
23
|
-
AgentCard,
|
|
24
|
-
ActivityEvent,
|
|
25
|
-
ActivityEventInput,
|
|
26
|
-
AgentKind,
|
|
27
|
-
AgentSessionGuard,
|
|
28
|
-
Artifact,
|
|
29
|
-
ArtifactBlob,
|
|
30
|
-
ArtifactKind,
|
|
31
|
-
ArtifactLink,
|
|
32
|
-
ArtifactSensitivity,
|
|
33
|
-
ArtifactVisibility,
|
|
34
|
-
AttachmentRef,
|
|
35
|
-
ChannelBinding,
|
|
36
|
-
ChannelBindingMode,
|
|
37
|
-
ChannelRouteTarget,
|
|
38
|
-
ChatHistoryImport,
|
|
39
|
-
ChatHistoryImportEntry,
|
|
40
|
-
ChannelSummary,
|
|
41
|
-
ChannelTargetHealth,
|
|
42
|
-
CreatePairInput,
|
|
43
|
-
HealthCheck,
|
|
44
|
-
HealthReport,
|
|
45
|
-
ManagedAgent,
|
|
46
|
-
ManagedSessionExitDiagnostics,
|
|
47
|
-
Message,
|
|
48
|
-
MessageDeliveryAttempt,
|
|
49
|
-
MessageDeliveryStatus,
|
|
50
|
-
HostDaemonSample,
|
|
51
|
-
Orchestrator,
|
|
52
|
-
OrchestratorHealth,
|
|
53
|
-
OrchestratorRuntimeInput,
|
|
54
|
-
OrchestratorStatus,
|
|
55
|
-
OrchestratorUpgradeState,
|
|
56
|
-
PairActionInput,
|
|
57
|
-
PairMessageInput,
|
|
58
|
-
PairSession,
|
|
59
|
-
PairStatus,
|
|
60
|
-
RegisterAgentInput,
|
|
61
|
-
ReplyObligation,
|
|
62
|
-
RegisterOrchestratorInput,
|
|
63
|
-
SendMessageInput,
|
|
64
|
-
PollQuery,
|
|
65
|
-
SpawnApprovalMode,
|
|
66
|
-
SpawnProvider,
|
|
67
|
-
Task,
|
|
68
|
-
TaskEvent,
|
|
69
|
-
TaskSeverity,
|
|
70
|
-
TaskStatus,
|
|
71
|
-
IntegrationEventInput,
|
|
72
|
-
IntegrationSummary,
|
|
73
|
-
IntegrationTaskStats,
|
|
74
|
-
InboxDraft,
|
|
75
|
-
InboxState,
|
|
76
|
-
InboxThreadState,
|
|
77
|
-
ContextSnapshot,
|
|
78
|
-
ContextState,
|
|
79
|
-
ProviderCapabilities,
|
|
80
|
-
QueuedSpawn,
|
|
81
|
-
TaskStatusInput,
|
|
82
|
-
WorkspaceMetadata,
|
|
83
|
-
WorkspaceRecord,
|
|
84
|
-
WorkspaceStatus,
|
|
85
|
-
} from "../types";
|
|
19
|
+
import type { ManagedAgent, HostDaemonSample, Orchestrator, OrchestratorHealth, OrchestratorRuntimeInput, OrchestratorStatus, OrchestratorUpgradeState, RegisterAgentInput, RegisterOrchestratorInput, SpawnProvider, QueuedSpawn } from "../types";
|
|
86
20
|
|
|
87
21
|
// --- Orchestrators ---
|
|
88
22
|
|
|
@@ -185,7 +119,6 @@ export function setOrchestratorUpgradeState(id: string, state: OrchestratorUpgra
|
|
|
185
119
|
return getOrchestrator(id);
|
|
186
120
|
}
|
|
187
121
|
|
|
188
|
-
|
|
189
122
|
function orchestratorHealth(version: string | undefined, compatibility: ReturnType<typeof contractCompatibility>): OrchestratorHealth {
|
|
190
123
|
const issues: OrchestratorHealth["issues"] = [];
|
|
191
124
|
if (!version) {
|
|
@@ -259,8 +192,8 @@ function mergeOrchestratorRuntimeMeta(meta: Record<string, unknown>, input: Orch
|
|
|
259
192
|
};
|
|
260
193
|
}
|
|
261
194
|
|
|
262
|
-
|
|
263
|
-
|
|
195
|
+
/** The orchestrator row write alone (no agent registration); returns the agent registration to follow. */
|
|
196
|
+
function writeOrchestratorRow(input: RegisterOrchestratorInput, now: number): RegisterAgentInput {
|
|
264
197
|
// #1554 — the command-delivery key. Built from the SAME helper the orchestrator's command poller
|
|
265
198
|
// binds with, so a registered host is always addressed under the exact id it polls under.
|
|
266
199
|
const agentId = orchestratorAgentId(input.id);
|
|
@@ -311,7 +244,7 @@ export function upsertOrchestrator(input: RegisterOrchestratorInput): Orchestrat
|
|
|
311
244
|
});
|
|
312
245
|
|
|
313
246
|
// Also register as an agent so the orchestrator can receive messages
|
|
314
|
-
|
|
247
|
+
return {
|
|
315
248
|
id: agentId,
|
|
316
249
|
name: `Orchestrator (${input.hostname})`,
|
|
317
250
|
tags: ["orchestrator", input.hostname],
|
|
@@ -329,11 +262,23 @@ export function upsertOrchestrator(input: RegisterOrchestratorInput): Orchestrat
|
|
|
329
262
|
...(input.protocolVersion !== undefined ? { protocolVersion: input.protocolVersion } : {}),
|
|
330
263
|
...(input.gitSha ? { gitSha: input.gitSha } : {}),
|
|
331
264
|
},
|
|
332
|
-
}
|
|
265
|
+
};
|
|
266
|
+
}
|
|
333
267
|
|
|
268
|
+
export function upsertOrchestrator(input: RegisterOrchestratorInput): Orchestrator {
|
|
269
|
+
upsertAgent(writeOrchestratorRow(input, Date.now()));
|
|
334
270
|
return getOrchestrator(input.id)!;
|
|
335
271
|
}
|
|
336
272
|
|
|
273
|
+
/** #1870 S6c — the whole registration as one off-loop op: the orchestrator row and its agent row
|
|
274
|
+
* commit together. The agent's main-thread follow-ups (presence eviction, pool binding, steward
|
|
275
|
+
* election) run in the facade from the returned `agent`/`contextState`. */
|
|
276
|
+
export function registerOrchestratorOp(input: RegisterOrchestratorInput, now: number, seq: number): { orchestrator: Orchestrator } & UpsertAgentTxResult {
|
|
277
|
+
const agentInput = writeOrchestratorRow(input, now);
|
|
278
|
+
const tx = upsertAgentInternal(agentInput, undefined, now, seq);
|
|
279
|
+
return { orchestrator: getOrchestrator(input.id)!, ...tx };
|
|
280
|
+
}
|
|
281
|
+
|
|
337
282
|
export function getOrchestrator(id: string): Orchestrator | null {
|
|
338
283
|
const row = getDb().query("SELECT * FROM orchestrators WHERE id = ?").get(id) as any;
|
|
339
284
|
return row ? rowToOrchestrator(row) : null;
|
|
@@ -440,7 +385,6 @@ export function reportOrchestratorRosterRow(id: string, agents: ManagedAgent[],
|
|
|
440
385
|
return { orchestrator: getOrchestrator(id), rosterChanged: true, workspaces };
|
|
441
386
|
}
|
|
442
387
|
|
|
443
|
-
|
|
444
388
|
export function deleteOrchestrator(id: string): boolean {
|
|
445
389
|
const orch = getOrchestrator(id);
|
|
446
390
|
if (!orch) return false;
|
package/src/db/pairs.ts
CHANGED
|
@@ -1,17 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
-
import {
|
|
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";
|
|
2
|
+
import { DAY_MS } from "../config";
|
|
15
3
|
import { matchAgents } from "../agent-ref";
|
|
16
4
|
import { getAgent, listAgents } from "./agents.ts";
|
|
17
5
|
import { getDb } from "./connection.ts";
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { ProjectProfileInstructions } from "../types";
|
|
2
|
+
import { getDb, ValidationError } from "./connection";
|
|
3
|
+
import { promptHistory, writePromptVersion } from "./prompt-versions";
|
|
4
|
+
import type { WriterOpContext, WriterOpSpec } from "./write-ops";
|
|
5
|
+
|
|
6
|
+
export const PROJECT_PROFILE_INSTRUCTIONS_SCHEMA_SQL = `
|
|
7
|
+
CREATE TABLE IF NOT EXISTS project_profile_instructions (
|
|
8
|
+
project_id TEXT NOT NULL REFERENCES projects(id), profile TEXT NOT NULL,
|
|
9
|
+
slug TEXT NOT NULL UNIQUE, PRIMARY KEY (project_id, profile)
|
|
10
|
+
);
|
|
11
|
+
CREATE INDEX IF NOT EXISTS project_profile_instructions_profile ON project_profile_instructions(profile);
|
|
12
|
+
`;
|
|
13
|
+
|
|
14
|
+
export interface ProjectProfileKey { projectId: string; profile: string }
|
|
15
|
+
const columns = `p.project_id AS projectId, p.profile, coalesce(h.template, '') AS template,
|
|
16
|
+
coalesce(h.version, 0) AS version, coalesce(h.updated_at, 0) AS updatedAt`;
|
|
17
|
+
|
|
18
|
+
export function getProjectProfileInstructions(key: ProjectProfileKey): ProjectProfileInstructions {
|
|
19
|
+
return getDb().query(`SELECT ${columns} FROM project_profile_instructions p
|
|
20
|
+
LEFT JOIN prompt_heads h ON h.slug = p.slug WHERE p.project_id = ? AND p.profile = ?`)
|
|
21
|
+
.get(key.projectId, key.profile) as ProjectProfileInstructions | null
|
|
22
|
+
?? { ...key, template: "", version: 0, updatedAt: 0 };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function instructionSlug(key: ProjectProfileKey): string {
|
|
26
|
+
return `project-profile:${JSON.stringify([key.projectId, key.profile])}`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function writeProjectProfileInstructions(args: ProjectProfileKey & {
|
|
30
|
+
template?: string; expectedVersion: number; actor: string; reason?: string; restoreVersion?: number;
|
|
31
|
+
}, now: number): ProjectProfileInstructions {
|
|
32
|
+
if (!getDb().query("SELECT 1 FROM projects WHERE id = ?").get(args.projectId)) throw new ValidationError("project not found");
|
|
33
|
+
getDb().query("INSERT OR IGNORE INTO project_profile_instructions VALUES (?, ?, ?)").run(args.projectId, args.profile, instructionSlug(args));
|
|
34
|
+
writePromptVersion({ ...args, slug: instructionSlug(args), action: args.restoreVersion === undefined ? undefined : "restore" }, now);
|
|
35
|
+
return getProjectProfileInstructions(args);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export const PROJECT_PROFILE_INSTRUCTION_READ_OPS = {
|
|
39
|
+
"projectProfileInstructions.get": getProjectProfileInstructions,
|
|
40
|
+
"projectProfileInstructions.history": (key: ProjectProfileKey) => promptHistory(instructionSlug(key)),
|
|
41
|
+
"projectProfileInstructions.list": (key: { projectId?: string; profile?: string }) => getDb().query(`SELECT ${columns}
|
|
42
|
+
FROM project_profile_instructions p LEFT JOIN prompt_heads h ON h.slug = p.slug
|
|
43
|
+
WHERE (?1 IS NULL OR p.project_id = ?1) AND (?2 IS NULL OR p.profile = ?2)`)
|
|
44
|
+
.all(key.projectId ?? null, key.profile ?? null) as ProjectProfileInstructions[],
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const PROJECT_PROFILE_INSTRUCTION_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = {
|
|
48
|
+
"projectProfileInstructions.write": { offLoop: true, idempotent: false,
|
|
49
|
+
fn: (args: Parameters<typeof writeProjectProfileInstructions>[0], ctx: WriterOpContext) => writeProjectProfileInstructions(args, ctx.now) },
|
|
50
|
+
};
|
|
@@ -10,6 +10,7 @@ export const PROMPT_VERSION_READ_OPS = {
|
|
|
10
10
|
|
|
11
11
|
export const PROMPT_VERSION_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = {
|
|
12
12
|
"prompts.write": {
|
|
13
|
+
offLoop: true,
|
|
13
14
|
idempotent: false,
|
|
14
15
|
fn: (args: PromptWrite, ctx: WriterOpContext) => writePromptVersion(args, ctx.now),
|
|
15
16
|
},
|
|
@@ -5,6 +5,7 @@ import { PROFILE_PROMPT_SCHEMA_SQL } from "./prompt-version-migration";
|
|
|
5
5
|
export { migratePromptVersions, promptLegacyHistory } from "./prompt-version-migration";
|
|
6
6
|
import { bundledPrompt, hasBundledPrompt, BUNDLED_PROMPT_MANIFEST, profilePromptSlug, versionedPromptsEnabled } from "../versioned-prompts";
|
|
7
7
|
import { getDb, ValidationError } from "./connection";
|
|
8
|
+
import { validateProjectProfileInstructionText } from "../project-profile-instruction-text";
|
|
8
9
|
|
|
9
10
|
export const PROMPT_VERSIONS_SCHEMA_SQL = PROFILE_PROMPT_SCHEMA_SQL + `
|
|
10
11
|
CREATE TABLE IF NOT EXISTS prompt_heads (
|
|
@@ -32,7 +33,10 @@ export function promptVersionMetadata(slug: string): Partial<PromptTemplate> | u
|
|
|
32
33
|
if (!versionedPromptsEnabled()) return;
|
|
33
34
|
const current = head(slug);
|
|
34
35
|
const bundle = hasBundledPrompt(slug) ? bundledPrompt(slug) : undefined;
|
|
35
|
-
if (!current && !bundle)
|
|
36
|
+
if (!current && !bundle) {
|
|
37
|
+
if (getDb().query("SELECT 1 FROM project_profile_instructions WHERE slug = ?").get(slug)) return { template: "", version: 0, updatedAt: 0, source: "canonical" };
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
36
40
|
return {
|
|
37
41
|
template: current?.template ?? bundle!.template,
|
|
38
42
|
version: current?.version ?? 0, seedHash: current?.seed_hash ?? null,
|
|
@@ -50,7 +54,8 @@ export function promptHistory(slug: string): PromptRevision[] {
|
|
|
50
54
|
function checkedPromptHead(args: Pick<PromptWrite, "slug" | "expectedVersion">, current = head(args.slug)): Head | null {
|
|
51
55
|
if (!versionedPromptsEnabled()) throw new ValidationError("versioned prompt not found");
|
|
52
56
|
const mapped = !current && !hasBundledPrompt(args.slug) ? getDb().query(`SELECT 1 FROM prompt_profile_slots
|
|
53
|
-
WHERE system_slug = ?1 OR EXISTS (SELECT 1 FROM json_each(append_slugs) WHERE value = ?1)
|
|
57
|
+
WHERE system_slug = ?1 OR EXISTS (SELECT 1 FROM json_each(append_slugs) WHERE value = ?1)
|
|
58
|
+
UNION ALL SELECT 1 FROM project_profile_instructions WHERE slug = ?1 LIMIT 1`).get(args.slug) : true;
|
|
54
59
|
if (!mapped) throw new ValidationError("versioned prompt not found");
|
|
55
60
|
if (!Number.isSafeInteger(args.expectedVersion) || args.expectedVersion! < 0) throw new ValidationError(`expectedVersion for ${args.slug} must be a non-negative integer`);
|
|
56
61
|
if (args.expectedVersion !== (current?.version ?? 0)) throw new PromptVersionConflictError(JSON.stringify({ slug: args.slug, ...promptVersionMetadata(args.slug), version: current?.version ?? 0 }));
|
|
@@ -70,6 +75,8 @@ function appendPromptVersion(args: PromptWrite, current: Head | null, now: numbe
|
|
|
70
75
|
if (args.action === "restore" && !restored) throw new ValidationError("prompt revision not found");
|
|
71
76
|
const template = args.action === "adopt" ? bundle!.template : restored?.template ?? args.template;
|
|
72
77
|
if (template === undefined) throw new ValidationError("template required");
|
|
78
|
+
const projectProfile = getDb().query("SELECT project_id, profile FROM project_profile_instructions WHERE slug = ?").get(args.slug) as { project_id: string; profile: string } | null;
|
|
79
|
+
if (projectProfile) validateProjectProfileInstructionText(template, `project ${projectProfile.project_id} profile ${projectProfile.profile} instructions`);
|
|
73
80
|
const seedHash = args.action === "adopt" ? bundle!.hash : restored ? restored.seedHash ?? null : current?.seed_hash ?? null;
|
|
74
81
|
const version = (current?.version ?? 0) + 1;
|
|
75
82
|
getDb().query("INSERT INTO prompt_revisions VALUES (?, ?, ?, ?, ?, ?, ?)")
|
|
@@ -9,8 +9,8 @@ import type { SpawnProvider } from "../types.ts";
|
|
|
9
9
|
import type { WriterOpContext, WriterOpSpec } from "./write-ops.ts";
|
|
10
10
|
|
|
11
11
|
export const PROVIDER_CATALOG_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.freeze({
|
|
12
|
-
"providerCatalog.upsert": { idempotent: false, fn: (args: { input: ProviderModelOverrideInput }, ctx: WriterOpContext) => upsertProviderModelOverride(args.input, ctx.now) },
|
|
13
|
-
"providerCatalog.setDisabled": { idempotent: false, fn: (args: { provider: SpawnProvider; alias: string; disabled: boolean; updatedBy?: string }, ctx: WriterOpContext) => setProviderModelDisabled(args.provider, args.alias, args.disabled, args.updatedBy, ctx.now) },
|
|
14
|
-
"providerCatalog.remove": { idempotent: false, fn: (args: { provider: SpawnProvider; alias: string; updatedBy?: string }, ctx: WriterOpContext) => removeProviderModelOverride(args.provider, args.alias, args.updatedBy, ctx.now) },
|
|
15
|
-
"providerCatalog.setDefault": { idempotent: false, fn: (args: { provider: SpawnProvider; alias: string; updatedBy?: string }, ctx: WriterOpContext) => setProviderDefaultModel(args.provider, args.alias, args.updatedBy, ctx.now) },
|
|
12
|
+
"providerCatalog.upsert": { offLoop: true, idempotent: false, fn: (args: { input: ProviderModelOverrideInput }, ctx: WriterOpContext) => upsertProviderModelOverride(args.input, ctx.now) },
|
|
13
|
+
"providerCatalog.setDisabled": { offLoop: true, idempotent: false, fn: (args: { provider: SpawnProvider; alias: string; disabled: boolean; updatedBy?: string }, ctx: WriterOpContext) => setProviderModelDisabled(args.provider, args.alias, args.disabled, args.updatedBy, ctx.now) },
|
|
14
|
+
"providerCatalog.remove": { offLoop: true, idempotent: false, fn: (args: { provider: SpawnProvider; alias: string; updatedBy?: string }, ctx: WriterOpContext) => removeProviderModelOverride(args.provider, args.alias, args.updatedBy, ctx.now) },
|
|
15
|
+
"providerCatalog.setDefault": { offLoop: true, idempotent: false, fn: (args: { provider: SpawnProvider; alias: string; updatedBy?: string }, ctx: WriterOpContext) => setProviderDefaultModel(args.provider, args.alias, args.updatedBy, ctx.now) },
|
|
16
16
|
});
|
|
@@ -13,11 +13,16 @@ function redactionPatch(env: unknown, nextEnv?: Record<string, unknown>): Record
|
|
|
13
13
|
).map(([key]) => [key, SECRET_VALUE_MASK]));
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
/**
|
|
17
|
-
export function
|
|
18
|
-
|
|
16
|
+
/** A config value with its provider credentials masked: what any copy outside the live row stores (#3540). */
|
|
17
|
+
export function credentialFreeConfigValue(entry: ConfigEntry, nextValue?: unknown): unknown {
|
|
18
|
+
return entry.namespace === "provider-config" && isRecord(entry.value) && isRecord(entry.value.env)
|
|
19
19
|
? { ...entry.value, env: { ...entry.value.env, ...redactionPatch(entry.value.env, isRecord(nextValue) && isRecord(nextValue.env) ? nextValue.env : undefined) } }
|
|
20
20
|
: entry.value;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Update and delete archive through the same seam so neither persists credentials (#3540). */
|
|
24
|
+
export function recordConfigHistory(entry: ConfigEntry, changedAt: string, changedBy?: string, nextValue?: unknown): void {
|
|
25
|
+
const value = credentialFreeConfigValue(entry, nextValue);
|
|
21
26
|
getDb().query(`
|
|
22
27
|
INSERT INTO config_history (namespace, key, value, version, changed_at, changed_by)
|
|
23
28
|
VALUES (?, ?, ?, ?, ?, ?)
|
|
@@ -3,6 +3,7 @@ import type { WriterOpSpec } from "./write-ops.ts";
|
|
|
3
3
|
|
|
4
4
|
export const PROVIDER_FLAP_MESSAGES_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.freeze({
|
|
5
5
|
"providerFlapMessages.ensureIndex": {
|
|
6
|
+
offLoop: true,
|
|
6
7
|
idempotent: true,
|
|
7
8
|
fn: () => {
|
|
8
9
|
ensureProviderFlapMessagesIndex();
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { providerCatalogList } from "@humwick/sdk/provider-catalog";
|
|
2
|
+
import { getDb } from "./connection";
|
|
3
|
+
|
|
4
|
+
const SEED_KEY = "provider-model-db-catalog-v1";
|
|
5
|
+
|
|
6
|
+
/** One migration backfills missing rows; later boots and releases leave the database alone. */
|
|
7
|
+
export function reconcileProviderModelSeed(): void {
|
|
8
|
+
const db = getDb();
|
|
9
|
+
if (db.query("SELECT 1 FROM config WHERE namespace = 'system' AND key = ?").get(SEED_KEY)) return;
|
|
10
|
+
db.transaction(() => {
|
|
11
|
+
seedProviderModelOverrides("seed:db-catalog-v1");
|
|
12
|
+
db.query("INSERT INTO config (namespace, key, value, version, updated_at, updated_by) VALUES ('system', ?, 'true', 1, ?, 'server-startup')")
|
|
13
|
+
.run(SEED_KEY, Date.now());
|
|
14
|
+
})();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Insert-only migration: operator edits, disabled entries and tombstones always win. */
|
|
18
|
+
export function seedProviderModelOverrides(stamp: string, now = Date.now()): { inserted: number } {
|
|
19
|
+
const db = getDb();
|
|
20
|
+
const insert = db.query(`INSERT INTO provider_model_overrides (provider, alias, entry, deleted, disabled, updated_at, updated_by)
|
|
21
|
+
VALUES (?, ?, ?, 0, ?, ?, ?) ON CONFLICT(provider, alias) DO NOTHING`);
|
|
22
|
+
const defaultModel = db.query(`INSERT INTO provider_model_defaults (provider, alias, updated_at, updated_by)
|
|
23
|
+
VALUES (?, ?, ?, ?) ON CONFLICT(provider) DO NOTHING`);
|
|
24
|
+
return db.transaction(() => {
|
|
25
|
+
let inserted = 0;
|
|
26
|
+
for (const provider of providerCatalogList()) {
|
|
27
|
+
for (const model of provider.models) {
|
|
28
|
+
inserted += insert.run(provider.provider, model.alias, JSON.stringify(model), model.disabled ? 1 : 0, now, stamp).changes;
|
|
29
|
+
}
|
|
30
|
+
if (provider.defaultModel) defaultModel.run(provider.provider, provider.defaultModel, now, stamp);
|
|
31
|
+
}
|
|
32
|
+
return { inserted };
|
|
33
|
+
})();
|
|
34
|
+
}
|
|
@@ -17,6 +17,7 @@ export const PROVIDER_QUOTA_LEASE_WRITE_OPS: Readonly<Record<string, WriterOpSpe
|
|
|
17
17
|
acquireProviderQuotaLeaseInTx(normalizeProviderQuotaLeaseAcquireInput({ ...args.input, now: args.input.now ?? ctx.now })),
|
|
18
18
|
},
|
|
19
19
|
"providerQuotaLeases.release": {
|
|
20
|
+
offLoop: true,
|
|
20
21
|
idempotent: true,
|
|
21
22
|
fn: (args: { input: Parameters<typeof releaseProviderQuotaLeaseInTx>[0] }) => releaseProviderQuotaLeaseInTx(args.input),
|
|
22
23
|
},
|
|
@@ -54,6 +54,7 @@ export const PROVIDER_QUOTA_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> =
|
|
|
54
54
|
// It returns concrete messages for main-thread SSE fanout; never call notifySystemMessage in a
|
|
55
55
|
// worker, whose listener set is intentionally not shared with the server.
|
|
56
56
|
"providerQuotas.routeNotification": {
|
|
57
|
+
offLoop: true,
|
|
57
58
|
// Routing inserts message rows. The effect facade supplies a stable per-effect key so a
|
|
58
59
|
// post-commit acknowledgement loss returns these exact messages instead of routing twice.
|
|
59
60
|
idempotent: false,
|
|
@@ -63,6 +64,7 @@ export const PROVIDER_QUOTA_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> =
|
|
|
63
64
|
fn: (args: { input: RouteNotificationInput; now?: number }, ctx: WriterOpContext) => routeProviderQuotaNotificationInTx(args.input, args.now ?? ctx.now),
|
|
64
65
|
},
|
|
65
66
|
"providerQuotas.pruneHistory": {
|
|
67
|
+
offLoop: true,
|
|
66
68
|
idempotent: true,
|
|
67
69
|
fn: (args: { olderThan: number }) => ({ changes: pruneProviderQuotaHistory(args.olderThan) }),
|
|
68
70
|
},
|
|
@@ -26,18 +26,19 @@ import type { WriterOpContext, WriterOpSpec } from "./write-ops.ts";
|
|
|
26
26
|
|
|
27
27
|
export const PROVISIONING_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.freeze({
|
|
28
28
|
// Creating a capability mints a random id, so the generic durable ledger owns phantom-ACK retry.
|
|
29
|
-
"provisioning.capabilities.create": { idempotent: false, fn: (args: CreateProvisioningCapabilityInput, ctx: WriterOpContext) => createProvisioningCapability(args, ctx.now) },
|
|
30
|
-
"provisioning.capabilities.update": { idempotent: true, fn: (args: { id: string; patch: UpdateProvisioningCapabilityInput }, ctx: WriterOpContext) => updateProvisioningCapability(args.id, args.patch, ctx.now) },
|
|
31
|
-
"provisioning.capabilities.delete": { idempotent: true, fn: (args: { id: string }) => deleteProvisioningCapability(args.id) },
|
|
29
|
+
"provisioning.capabilities.create": { offLoop: true, idempotent: false, fn: (args: CreateProvisioningCapabilityInput, ctx: WriterOpContext) => createProvisioningCapability(args, ctx.now) },
|
|
30
|
+
"provisioning.capabilities.update": { offLoop: true, idempotent: true, fn: (args: { id: string; patch: UpdateProvisioningCapabilityInput }, ctx: WriterOpContext) => updateProvisioningCapability(args.id, args.patch, ctx.now) },
|
|
31
|
+
"provisioning.capabilities.delete": { offLoop: true, idempotent: true, fn: (args: { id: string }) => deleteProvisioningCapability(args.id) },
|
|
32
32
|
// The capability lookup and its variant insert/update execute under one writer lock.
|
|
33
|
-
"provisioning.variants.createMcp": { idempotent: false, fn: (args: { capabilityId: string; input: CreateMcpProvisioningVariantInput }, ctx: WriterOpContext) => createMcpProvisioningVariant(args.capabilityId, args.input, ctx.now) },
|
|
34
|
-
"provisioning.variants.patch": { idempotent: true, fn: (args: { id: string; patch: PatchProvisioningAssetVariantInput }, ctx: WriterOpContext) => patchProvisioningAssetVariant(args.id, args.patch, ctx.now) },
|
|
35
|
-
"provisioning.variants.validate": { idempotent: true, fn: (args: { id: string }, ctx: WriterOpContext) => validateProvisioningAssetVariant(args.id, ctx.now) },
|
|
36
|
-
"provisioning.assets.upsert": { idempotent: false, fn: (args: UpsertProvisioningAssetInput, ctx: WriterOpContext) => upsertProvisioningAsset(args, ctx.now) },
|
|
33
|
+
"provisioning.variants.createMcp": { offLoop: true, idempotent: false, fn: (args: { capabilityId: string; input: CreateMcpProvisioningVariantInput }, ctx: WriterOpContext) => createMcpProvisioningVariant(args.capabilityId, args.input, ctx.now) },
|
|
34
|
+
"provisioning.variants.patch": { offLoop: true, idempotent: true, fn: (args: { id: string; patch: PatchProvisioningAssetVariantInput }, ctx: WriterOpContext) => patchProvisioningAssetVariant(args.id, args.patch, ctx.now) },
|
|
35
|
+
"provisioning.variants.validate": { offLoop: true, idempotent: true, fn: (args: { id: string }, ctx: WriterOpContext) => validateProvisioningAssetVariant(args.id, ctx.now) },
|
|
36
|
+
"provisioning.assets.upsert": { offLoop: true, idempotent: false, fn: (args: UpsertProvisioningAssetInput, ctx: WriterOpContext) => upsertProvisioningAsset(args, ctx.now) },
|
|
37
37
|
"provisioning.assets.importGithub": {
|
|
38
|
+
offLoop: true,
|
|
38
39
|
idempotent: false,
|
|
39
40
|
fn: (args: { input: ImportProvisioningAssetFromGitHubInput; source: GitHubVendoredSource; definition: ResolvedAssetDefinition; now: number; target?: ProvisioningGitHubImportTarget }) =>
|
|
40
41
|
upsertImportedAssetBody(args.input, args.source, args.definition, args.now, args.target),
|
|
41
42
|
},
|
|
42
|
-
"provisioning.assets.delete": { idempotent: true, fn: (args: { kind: ProvisioningAssetKind; name: string; provider?: AgentProfileProvider }) => deleteProvisioningAsset(args.kind, args.name, args.provider) },
|
|
43
|
+
"provisioning.assets.delete": { offLoop: true, idempotent: true, fn: (args: { kind: ProvisioningAssetKind; name: string; provider?: AgentProfileProvider }) => deleteProvisioningAsset(args.kind, args.name, args.provider) },
|
|
43
44
|
});
|
|
@@ -101,6 +101,9 @@ export const KERNEL_ENTITY_CATALOG = {
|
|
|
101
101
|
} as const;
|
|
102
102
|
|
|
103
103
|
export const READ_OP_MARSHALING_FIXTURES: ReadOpFixtures = {
|
|
104
|
+
"projectProfileInstructions.get": { args: { projectId: "missing", profile: "worker" } },
|
|
105
|
+
"projectProfileInstructions.history": { args: { projectId: "missing", profile: "worker" } },
|
|
106
|
+
"projectProfileInstructions.list": { args: { projectId: "missing" } },
|
|
104
107
|
"planGraph.import.preview": { args: { scope: "import-fixture", actor: "system", expectedVersion: 0, requestKey: "preview", documentHash: "h", requestHash: "h", newPlanId: "plan-fixture", executions: { a: { workflow: "build-review" } }, document: { version: 1, key: "fixture", revision: "r1", title: "Fixture", acceptance: [{ id: "works", text: "Works" }], tasks: [{ key: "a", title: "A", intent: "Build A" }] } } },
|
|
105
108
|
"guides.search": { args: { query: "violet", guides: [{ id: "workflows", title: "Workflows", summary: "Build and review", tags: ["review"], body: "A violet checksum", revision: "fixture-revision" }] } },
|
|
106
109
|
"commands.latestByCorrelation": { args: { type: "scheduler.cancel", correlationId: "fixture" } },
|
|
@@ -164,6 +167,7 @@ export const READ_OP_MARSHALING_FIXTURES: ReadOpFixtures = {
|
|
|
164
167
|
|
|
165
168
|
// --- channels / projects / teams / hosts --------------------------------------------------------
|
|
166
169
|
"channels.bindingOwner": { args: { id: "binding-t9" } },
|
|
170
|
+
"integrations.taskStats": { args: undefined },
|
|
167
171
|
"channels.snapshot": { args: undefined },
|
|
168
172
|
"channels.bindings": { args: {} },
|
|
169
173
|
"channels.routes": { args: { channelId: "channel-t9" } },
|
|
@@ -216,6 +220,7 @@ export const READ_OP_MARSHALING_FIXTURES: ReadOpFixtures = {
|
|
|
216
220
|
"ciIncidents.sha.hasExpired": { args: { now: FIXTURE_NOW } },
|
|
217
221
|
"ciIncidents.lease.hasExpired": { args: { now: FIXTURE_NOW } },
|
|
218
222
|
"deployEvents.get": { args: { id: "dep-t9" } },
|
|
223
|
+
"deployEvents.forCommit": { args: { commitSha: "a".repeat(40) } },
|
|
219
224
|
// #2189 P7 — restart-epoch reads. Every one is a point/keyset read against ids that do not exist in
|
|
220
225
|
// the fixture DB, which is the point: marshaling has to survive the empty answer too.
|
|
221
226
|
"restartEpoch.openAll": { args: undefined },
|
package/src/db/read-ops.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { INTEGRATIONS_READ_OPS } from "./integrations-ops.ts";
|
|
1
2
|
import { PROMPT_VERSION_READ_OPS } from "./prompt-versions-ops";
|
|
3
|
+
import { PROJECT_PROFILE_INSTRUCTION_READ_OPS } from "./project-profile-instructions";
|
|
2
4
|
import { VAULT_READ_OPS } from "./secrets-vault";
|
|
3
5
|
import { GUIDE_READ_OPS } from "./guides-search";
|
|
4
6
|
import { ROUTING_POLICY_READ_OPS } from "./routing-policy";
|
|
@@ -129,6 +131,7 @@ const SPIN_MAX_MS = 2_000;
|
|
|
129
131
|
export const readOps = {
|
|
130
132
|
...GUIDE_READ_OPS,
|
|
131
133
|
...PROMPT_VERSION_READ_OPS,
|
|
134
|
+
...PROJECT_PROFILE_INSTRUCTION_READ_OPS,
|
|
132
135
|
...SERVICE_ACCESS_READ_OPS,
|
|
133
136
|
...VAULT_TOKEN_READ_OPS,
|
|
134
137
|
...VAULT_HEALTH_READ_OPS,
|
|
@@ -254,6 +257,7 @@ export const readOps = {
|
|
|
254
257
|
...PROJECTS_READ_OPS,
|
|
255
258
|
...PROJECT_ENTRIES_READ_OPS,
|
|
256
259
|
...CHANNELS_READ_OPS,
|
|
260
|
+
...INTEGRATIONS_READ_OPS,
|
|
257
261
|
} satisfies Record<string, ReadOpFn>;
|
|
258
262
|
|
|
259
263
|
/** The registered read-op names. */
|
package/src/db/routing-policy.ts
CHANGED
|
@@ -3,7 +3,6 @@ import { isRecord, ValidationError, type RoutingPolicy, type RoutingPolicyEnvelo
|
|
|
3
3
|
import { getConfig, setConfigInternal } from "../config-store";
|
|
4
4
|
import { getDb } from "./connection";
|
|
5
5
|
import { DEFAULT_ROUTING_POLICY, normalizeRoutingPolicy, ROUTING_POLICY_NAMESPACE as NS, ROUTING_POLICY_KEY as KEY } from "../routing-policy-normalize";
|
|
6
|
-
import { currentRoutingModels } from "../routing-model-aliases";
|
|
7
6
|
|
|
8
7
|
export function readRoutingPolicy(): RoutingPolicyEnvelope {
|
|
9
8
|
const entry = getConfig(NS, KEY);
|
|
@@ -19,7 +18,7 @@ export function readRoutingPolicy(): RoutingPolicyEnvelope {
|
|
|
19
18
|
policy.migration = { sourceSchemaVersion: 1, notes: stored.migration.notes.filter((note): note is string => typeof note === "string") };
|
|
20
19
|
}
|
|
21
20
|
}
|
|
22
|
-
return { policy
|
|
21
|
+
return { policy, revision: entry?.version ?? 0, diagnostics: policy.migration ?? null };
|
|
23
22
|
}
|
|
24
23
|
|
|
25
24
|
export interface RoutingPolicyWrite {
|
|
@@ -53,12 +52,12 @@ export function writeRoutingPolicy(args: RoutingPolicyWrite, now: number) {
|
|
|
53
52
|
}
|
|
54
53
|
}
|
|
55
54
|
const policy: RoutingPolicy = { ...parsed, ...(migration ? { migration } : {}), ...(sourceRevision ? { migrationSourceRevision: sourceRevision } : {}) };
|
|
56
|
-
const changed = (isRecord(stored?.value) && stored.value.schemaVersion === 1) || JSON.stringify(
|
|
55
|
+
const changed = (isRecord(stored?.value) && stored.value.schemaVersion === 1) || JSON.stringify(policy) !== JSON.stringify(current.policy);
|
|
57
56
|
if (changed) setConfigInternal(NS, KEY, policy, args.updatedBy, now);
|
|
58
57
|
return { envelope: readRoutingPolicy(), previous: current.policy, changed };
|
|
59
58
|
}
|
|
60
59
|
|
|
61
60
|
export const ROUTING_POLICY_READ_OPS = { "routingPolicy.get": () => readRoutingPolicy() };
|
|
62
61
|
export const ROUTING_POLICY_WRITE_OPS = {
|
|
63
|
-
"routingPolicy.set": { idempotent: false, fn: (args: RoutingPolicyWrite, ctx: { now: number }) => writeRoutingPolicy(args, ctx.now) },
|
|
62
|
+
"routingPolicy.set": { offLoop: true, idempotent: false, fn: (args: RoutingPolicyWrite, ctx: { now: number }) => writeRoutingPolicy(args, ctx.now) },
|
|
64
63
|
};
|
package/src/db/schema.ts
CHANGED
|
@@ -25,7 +25,8 @@ import { resetLifecycleSeqSeed } from "./lifecycle-seq.ts";
|
|
|
25
25
|
import { resetFannedSeq } from "../sse-outbox-cursor";
|
|
26
26
|
import { dropLegacyContinuationArchiveIndex } from "./continuation-archive-search.ts";
|
|
27
27
|
import { applyMigrations } from "./migrations.ts";
|
|
28
|
-
import { PROMPT_TEMPLATES_SCHEMA_SQL, seedPromptTemplatesIfNeeded } from "./prompt-templates-schema";
|
|
28
|
+
import { reconcileProviderModelSeed } from "./provider-model-seed"; import { PROMPT_TEMPLATES_SCHEMA_SQL, seedPromptTemplatesIfNeeded } from "./prompt-templates-schema";
|
|
29
|
+
import { PROJECT_PROFILE_INSTRUCTIONS_SCHEMA_SQL } from "./project-profile-instructions";
|
|
29
30
|
import { ensureLandingPhaseOneSchema } from "./landing-schema.ts";
|
|
30
31
|
import { beginStartupPhase, timeStartupPhase } from "../startup-timing";
|
|
31
32
|
import { resetMainConnectionWrites } from "./main-connection-writes";
|
|
@@ -552,6 +553,7 @@ export function initDb(path: string = "agent-relay.db"): Database {
|
|
|
552
553
|
CREATE INDEX IF NOT EXISTS idx_config_history_key ON config_history(namespace, key, version);
|
|
553
554
|
|
|
554
555
|
${PROMPT_TEMPLATES_SCHEMA_SQL}
|
|
556
|
+
${PROJECT_PROFILE_INSTRUCTIONS_SCHEMA_SQL}
|
|
555
557
|
|
|
556
558
|
-- Per-user settings (#391, epic #388). The user dimension the global \`config\` table lacks:
|
|
557
559
|
-- the same \`(namespace, key)\` descriptor address resolves to a per-user value, keyed by the
|
|
@@ -844,6 +846,8 @@ export function initDb(path: string = "agent-relay.db"): Database {
|
|
|
844
846
|
-- distinct from severity). Both optional; absent on claim-kind rows.
|
|
845
847
|
tags TEXT,
|
|
846
848
|
priority TEXT,
|
|
849
|
+
-- #3736 — paths[] (JSON array of repo-relative paths) a project spawn policy matches.
|
|
850
|
+
paths TEXT,
|
|
847
851
|
-- #1535 WS1 — parent/epic tree edge: a task has at most one parent. Cycle-guarded
|
|
848
852
|
-- in application code (src/db/task-entity.ts setTaskParent), the same way as the
|
|
849
853
|
-- depends-on DAG below (#834 finding 7) — SQLite CHECK can't express acyclicity.
|
|
@@ -858,7 +862,7 @@ export function initDb(path: string = "agent-relay.db"): Database {
|
|
|
858
862
|
-- gate-validated but does NOT arm a land (no ingress); the coordinator's clear (CAS on
|
|
859
863
|
-- the held delivery's host-probed HEAD) promotes that exact delivery. Distinct from the
|
|
860
864
|
-- permanent workspace landBlocked. Default 0 keeps every pre-#2518 Task unheld.
|
|
861
|
-
validation_items TEXT, terminal_stage TEXT, completed_at INTEGER,
|
|
865
|
+
validation_items TEXT, terminal_stage TEXT, completed_at INTEGER, on_deploy TEXT,
|
|
862
866
|
review_hold INTEGER NOT NULL DEFAULT 0 CHECK (review_hold IN (0, 1)),
|
|
863
867
|
-- #2862 durable owner: a coordinator role (coordinator:TEAM) or a human id, never an agent id.
|
|
864
868
|
owner TEXT
|
|
@@ -867,6 +871,8 @@ export function initDb(path: string = "agent-relay.db"): Database {
|
|
|
867
871
|
CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status);
|
|
868
872
|
CREATE INDEX IF NOT EXISTS idx_tasks_target ON tasks(target);
|
|
869
873
|
CREATE INDEX IF NOT EXISTS idx_tasks_updated ON tasks(updated_at);
|
|
874
|
+
-- #3740: cover the integration aggregation without fetching task bodies/metadata.
|
|
875
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_integration_stats ON tasks(coalesce(json_extract(metadata, '$.relayIntegrationName'), source), status, claimed_by, last_seen_at, updated_at, source);
|
|
870
876
|
CREATE INDEX IF NOT EXISTS idx_tasks_message_status
|
|
871
877
|
ON tasks(message_id, status)
|
|
872
878
|
WHERE message_id IS NOT NULL;
|
|
@@ -1456,7 +1462,7 @@ export function initDb(path: string = "agent-relay.db"): Database {
|
|
|
1456
1462
|
ensureLandingPhaseOneSchema();
|
|
1457
1463
|
// Vault catalog, environments and metadata upgrades share applyMigrations (#3561, #3562).
|
|
1458
1464
|
timeStartupPhase("db.migrations", applyMigrations);
|
|
1459
|
-
timeStartupPhase("db.prompt-seed", seedPromptTemplatesIfNeeded);
|
|
1465
|
+
timeStartupPhase("db.prompt-seed", seedPromptTemplatesIfNeeded); timeStartupPhase("db.model-seed", reconcileProviderModelSeed);
|
|
1460
1466
|
timeStartupPhase("db.token-profile-seed", seedBuiltInTokenProfiles);
|
|
1461
1467
|
|
|
1462
1468
|
timeStartupPhase("db.planner-statistics", () => refreshPlannerStats(getDb()));
|
|
@@ -14,10 +14,10 @@ import type { WriterOpContext, WriterOpSpec } from "./write-ops.ts";
|
|
|
14
14
|
export const SECRETS_BROKER_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.freeze({
|
|
15
15
|
// Caller-generated ids + INSERT OR IGNORE make both inserts safe to replay.
|
|
16
16
|
"secretsBroker.audit.record": { idempotent: true, offLoop: true, fn: (a: SecretAuditInput, ctx: WriterOpContext) => recordSecretAudit(a, ctx.now) },
|
|
17
|
-
"secretsBroker.link.create": { idempotent: true, fn: (a: SecretUploadLinkInput, ctx: WriterOpContext) => createSecretUploadLink(a, ctx.now) },
|
|
17
|
+
"secretsBroker.link.create": { offLoop: true, idempotent: true, fn: (a: SecretUploadLinkInput, ctx: WriterOpContext) => createSecretUploadLink(a, ctx.now) },
|
|
18
18
|
// A replayed claim must not hand the link out twice: the ledger returns the first claim's result.
|
|
19
|
-
"secretsBroker.link.claim": { idempotent: false, fn: (a: { tokenHash: string }, ctx: WriterOpContext) => claimSecretUploadLink(a.tokenHash, ctx.now) },
|
|
20
|
-
"secretsBroker.loginLatch.set": { idempotent: true, fn: (a: { fingerprint: string; state: SecretBrokerLoginLatchState }, ctx: WriterOpContext) => setSecretBrokerLoginLatch(a, ctx.now) },
|
|
21
|
-
"secretsBroker.loginLatch.clear": { idempotent: true, fn: (a: { fingerprint: string }) => clearSecretBrokerLoginLatch(a.fingerprint) },
|
|
22
|
-
"secretsBroker.link.finish": { idempotent: true, fn: (a: Parameters<typeof finishSecretUploadLink>[0]) => finishSecretUploadLink(a) },
|
|
19
|
+
"secretsBroker.link.claim": { offLoop: true, idempotent: false, fn: (a: { tokenHash: string }, ctx: WriterOpContext) => claimSecretUploadLink(a.tokenHash, ctx.now) },
|
|
20
|
+
"secretsBroker.loginLatch.set": { offLoop: true, idempotent: true, fn: (a: { fingerprint: string; state: SecretBrokerLoginLatchState }, ctx: WriterOpContext) => setSecretBrokerLoginLatch(a, ctx.now) },
|
|
21
|
+
"secretsBroker.loginLatch.clear": { offLoop: true, idempotent: true, fn: (a: { fingerprint: string }) => clearSecretBrokerLoginLatch(a.fingerprint) },
|
|
22
|
+
"secretsBroker.link.finish": { offLoop: true, idempotent: true, fn: (a: Parameters<typeof finishSecretUploadLink>[0]) => finishSecretUploadLink(a) },
|
|
23
23
|
});
|
|
@@ -87,11 +87,11 @@ export function editVaultMetadata(args: { name: string; patch: VaultMetadataPatc
|
|
|
87
87
|
});
|
|
88
88
|
}
|
|
89
89
|
export const VAULT_WRITE_OPS = {
|
|
90
|
-
"secretsVault.metadata": { idempotent: true, fn: editVaultMetadata },
|
|
91
|
-
"secretsVault.delete": { idempotent: false, fn: deleteVaultSecret },
|
|
92
|
-
"secretsVault.set": { idempotent: true, fn: setVaultRow },
|
|
93
|
-
"secretsVault.request": { idempotent: false, fn: (args: Parameters<typeof fileVaultDecision>[0]) => fileVaultDecision(args) },
|
|
94
|
-
"secretsVault.withdraw": { idempotent: true, fn: withdrawVaultDecisions },
|
|
95
|
-
"secretsVault.expire": { idempotent: true, fn: expireVaultDecisions },
|
|
96
|
-
"secretsVault.answer": { idempotent: true, fn: (args: { id: number; now: number }) => answerOpenOperatorDecision(args.id, { answers: {}, answeredBy: "vault-form", now: args.now }) },
|
|
90
|
+
"secretsVault.metadata": { offLoop: true, idempotent: true, fn: editVaultMetadata },
|
|
91
|
+
"secretsVault.delete": { offLoop: true, idempotent: false, fn: deleteVaultSecret },
|
|
92
|
+
"secretsVault.set": { offLoop: true, idempotent: true, fn: setVaultRow },
|
|
93
|
+
"secretsVault.request": { offLoop: true, idempotent: false, fn: (args: Parameters<typeof fileVaultDecision>[0]) => fileVaultDecision(args) },
|
|
94
|
+
"secretsVault.withdraw": { offLoop: true, idempotent: true, fn: withdrawVaultDecisions },
|
|
95
|
+
"secretsVault.expire": { offLoop: true, idempotent: true, fn: expireVaultDecisions },
|
|
96
|
+
"secretsVault.answer": { offLoop: true, idempotent: true, fn: (args: { id: number; now: number }) => answerOpenOperatorDecision(args.id, { answers: {}, answeredBy: "vault-form", now: args.now }) },
|
|
97
97
|
};
|
|
@@ -16,6 +16,7 @@ function parsedParams(raw: string): Record<string, unknown> {
|
|
|
16
16
|
|
|
17
17
|
export const SERVICES_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.freeze({
|
|
18
18
|
"services.spawnWatchdog.markUnconfirmed": {
|
|
19
|
+
offLoop: true,
|
|
19
20
|
idempotent: true,
|
|
20
21
|
fn: (args: { rows: SpawnCommandPatchRow[]; now: number; phase: "dispatch_unacknowledged" | "registration_unconfirmed" }) => {
|
|
21
22
|
const changed: string[] = [];
|
|
@@ -31,6 +32,7 @@ export const SERVICES_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object
|
|
|
31
32
|
},
|
|
32
33
|
},
|
|
33
34
|
"services.spawnWatchdog.markConfirmed": {
|
|
35
|
+
offLoop: true,
|
|
34
36
|
idempotent: true,
|
|
35
37
|
fn: (args: { rows: SpawnCommandPatchRow[]; now: number }) => {
|
|
36
38
|
const changed: string[] = [];
|
|
@@ -46,6 +48,7 @@ export const SERVICES_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object
|
|
|
46
48
|
},
|
|
47
49
|
},
|
|
48
50
|
"services.providerFlap.persist": {
|
|
51
|
+
offLoop: true,
|
|
49
52
|
idempotent: true,
|
|
50
53
|
fn: (args: { agentId: string; kind: string; episodeCount: number; lastEpisodeAt: number; latestSuppressedSeq: number }) => {
|
|
51
54
|
const row = getDb().query(`
|