@humwick/server 0.130.1 → 0.130.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/bundled/prompts/manifest.json +1 -0
- package/bundled/prompts/task.hydration.md +1 -1
- package/bundled/roles/builder.md +1 -1
- package/docs/guides/sub-coordinators.md +12 -5
- package/docs/guides/tools-administration.md +4 -0
- package/docs/guides/tools-coordination.md +2 -0
- package/docs/guides/tools-tasks.md +8 -0
- package/docs/guides/workflows.md +74 -0
- package/docs/openapi.json +486 -4
- package/package.json +10 -18
- package/public/assets/{MessageBubble-BWpoBjl4.js → MessageBubble-Bq9kr21N.js} +2 -2
- package/public/assets/{PlanGraphPanel-C0auck3n.js → PlanGraphPanel-Dqiroy06.js} +2 -2
- package/public/assets/{TraceView-DBnOx7AQ.js → TraceView-DYU962-H.js} +2 -2
- package/public/assets/{VaultDecisionCard-0kp2oNBC.js → VaultDecisionCard-DhPfzioE.js} +2 -2
- package/public/assets/{activity-yLztXEBt.js → activity-DzCcQTee.js} +2 -2
- package/public/assets/{agent-lineage-BbJDR1dW.js → agent-lineage-SgDt9i3T.js} +2 -2
- package/public/assets/agent-liveness-Bq-s73jW.js +2 -0
- package/public/assets/{agent-name-CTZBrSD9.js → agent-name-CcY3Aijy.js} +2 -2
- package/public/assets/agent-profiles-cxtRBn6O.js +2 -0
- package/public/assets/{agent-project-badge-9TqzUUYE.js → agent-project-badge-DGYbIhaI.js} +2 -2
- package/public/assets/{agent-tools-D4n40pn8.js → agent-tools-DHbftV0N.js} +2 -2
- package/public/assets/{agent-type-icon-D6FUarOf.js → agent-type-icon-CY113sp-.js} +2 -2
- package/public/assets/{agents-BYDslkJc.js → agents-BPzY7IlQ.js} +2 -2
- package/public/assets/{analytics-B-XSbEMC.js → analytics-DENFPv_a.js} +2 -2
- package/public/assets/{artifact-viewer-DdWIfV6M.js → artifact-viewer-KRvSc7sl.js} +2 -2
- package/public/assets/{artifacts-DPN1q4pA.js → artifacts-C9gSmL3s.js} +2 -2
- package/public/assets/{artifacts-oBOqks-2.js → artifacts-DT-HkI5O.js} +2 -2
- package/public/assets/{automation-4KcRFXEu.js → automation-BsmjQhKD.js} +2 -2
- package/public/assets/{backlog-Cw9xPTCF.js → backlog-8NYH_62t.js} +2 -2
- package/public/assets/{busy-health-CTu32MZt.js → busy-health-D3hwvYb4.js} +2 -2
- package/public/assets/{channels-BiXzg1G9.js → channels-DCJ5WL7O.js} +2 -2
- package/public/assets/{chat-Ctk2qwvA.js → chat-DAIl357U.js} +3 -3
- package/public/assets/{code-preview-Bm1wWqAp.js → code-preview-CzrZfr9U.js} +2 -2
- package/public/assets/{connectors-C36ax4Vw.js → connectors-xTxtlyou.js} +2 -2
- package/public/assets/{cosmos-Jj9LK2Wf.js → cosmos-BpebFLK2.js} +2 -2
- package/public/assets/{crate-agent-H6S7-B9T.js → crate-agent-BHvI5wXC.js} +2 -2
- package/public/assets/{dependency-graph-Cd1E23wa.js → dependency-graph-DGT0o3wJ.js} +2 -2
- package/public/assets/{deploys-Bwfq146q.js → deploys-hqWOHSHE.js} +2 -2
- package/public/assets/{display-CfO7rTuF.js → display-CDeH4I8T.js} +2 -2
- package/public/assets/{files-DhhZI2Ih.js → files-BTeGVmTg.js} +2 -2
- package/public/assets/{fleet-B_rFEbnL.js → fleet-DgXtNgCa.js} +2 -2
- package/public/assets/{fleet-metrics-BkHP-P3R.js → fleet-metrics-BHEt5yc_.js} +2 -2
- package/public/assets/{formatted-body-Cm1RrzmN.js → formatted-body-MLtodyPp.js} +3 -3
- package/public/assets/{formatted-body-impl-DQiOuOD1.js → formatted-body-impl-CAe664Z8.js} +2 -2
- package/public/assets/{host-providers-dialog-CHqwXTov.js → host-providers-dialog-mapF4Fj9.js} +2 -2
- package/public/assets/index-CqqgOI5R.js +15 -0
- package/public/assets/index-MYAIwYTX.css +2 -0
- package/public/assets/{insights-fH1EL-qZ.js → insights-DNyf7IzF.js} +2 -2
- package/public/assets/{integrations-C5Oix6ng.js → integrations-DlYOHq7T.js} +2 -2
- package/public/assets/{issue-ref-chip-ODyondIa.js → issue-ref-chip-CeWBNWn7.js} +2 -2
- package/public/assets/{log-viewer-Cvfy6PW7.js → log-viewer-Cib8nqdE.js} +2 -2
- package/public/assets/{maintenance-D8CDH5wZ.js → maintenance-DSn1cPm7.js} +2 -2
- package/public/assets/{managed-agents-egllbpij.js → managed-agents-C3CkM81m.js} +2 -2
- package/public/assets/{markdown-preview-CYSFgVgK.js → markdown-preview-W4VQQPAv.js} +3 -3
- package/public/assets/{markdown-preview-impl-BteVIjX4.js → markdown-preview-impl-CMsTdhjq.js} +2 -2
- package/public/assets/{memory-C8WmXsyr.js → memory-BV17qtO4.js} +2 -2
- package/public/assets/{messages-BzQdqlO6.js → messages-Bm_1AqSA.js} +2 -2
- package/public/assets/{orchestrators-B1HxzkNw.js → orchestrators-Dg-vfP09.js} +2 -2
- package/public/assets/{overview-DCUnI4Z7.js → overview-DcYCrvlr.js} +2 -2
- package/public/assets/{pairs-ftCd2XcD.js → pairs-8o9nuG3V.js} +2 -2
- package/public/assets/{profile-icon-B2zH8DMH.js → profile-icon-BsRyBMea.js} +2 -2
- package/public/assets/project-profile-instructions-DETKFn_E.js +2 -0
- package/public/assets/projects-M_m6AHws.js +2 -0
- package/public/assets/{prompt-settings-Bftq9czX.js → prompt-settings-C_mNCgeL.js} +2 -2
- package/public/assets/provider-display-BEeLXC_D.js +2 -0
- package/public/assets/{registry-DWCU5c8q.js → registry-DDHHHE5N.js} +2 -2
- package/public/assets/run-card-Dt4I4jaP.js +2 -0
- package/public/assets/scroll-text-BKXS1ahr.js +2 -0
- package/public/assets/{secrets-C7GIUATz.js → secrets-BkVwxI5O.js} +2 -2
- package/public/assets/{service-access-settings-C3aujqTG.js → service-access-settings-Crq-6a-B.js} +2 -2
- package/public/assets/{settings-C6sZ9eBa.js → settings-CYcavMFu.js} +2 -2
- package/public/assets/shipping-H6gzEeZB.js +2 -0
- package/public/assets/{stats-V9Z-GxUd.js → stats-BJVeWkpV.js} +2 -2
- package/public/assets/{status-dot-CVv0iGHL.js → status-dot-BcHyw1Vw.js} +2 -2
- package/public/assets/store-DKPDIZBe.js +9 -0
- package/public/assets/{tasks-CXU75HRF.js → tasks-qJjlQPpx.js} +2 -2
- package/public/assets/{teams-BPf976zb.js → teams-Cd5Sk1uX.js} +2 -2
- package/public/assets/{terminal-viewer-DE9BOe-8.js → terminal-viewer-CpY5_m7W.js} +3 -3
- package/public/assets/{terminal-viewer-impl-D04pjmGh.js → terminal-viewer-impl-DI_2llFR.js} +2 -2
- package/public/assets/token-estimate-Co-Jdphh.js +2 -0
- package/public/assets/{use-agent-terminal-B1yR456R.js → use-agent-terminal-0yJA_buM.js} +2 -2
- package/public/assets/{use-decisions-D-S4tpDf.js → use-decisions-uJXHf34W.js} +2 -2
- package/public/assets/use-project-list-CpWl6eHQ.js +2 -0
- package/public/assets/{use-selectors-CnrAk2YP.js → use-selectors-BdxBW8mL.js} +2 -2
- package/public/assets/{user-avatar-nBFIcR4M.js → user-avatar-3IndfpOc.js} +2 -2
- package/public/assets/versioned-prompt-editor-CIVg7XB1.js +8 -0
- package/public/assets/{work-queue-TCjJxeT-.js → work-queue-B9rnLwHZ.js} +2 -2
- package/public/assets/{workflow-marker-Cf3Hf2fN.js → workflow-marker-X8wxyhzC.js} +2 -2
- package/public/assets/{workflows-CXQX20Qj.js → workflows-o5YyMFW7.js} +2 -2
- package/public/assets/{workspaces-qSYzKYMA.js → workspaces-CzEGoAng.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/claude-headless.ts +1 -1
- package/runner/src/adapters/claude-launch-exit.ts +26 -0
- package/runner/src/adapters/claude-session-probe.ts +1 -1
- package/runner/src/adapters/claude-tmux.ts +38 -10
- package/runner/src/adapters/claude.ts +28 -75
- 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/adapters/provider-quota-harvest.ts +20 -71
- 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 +2 -4
- package/runner/src/agent-runner/liveness-exchange.ts +104 -0
- 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/claude-system-prompt.ts +49 -0
- package/runner/src/index.ts +5 -2
- package/runner/src/launch-assembly.ts +14 -10
- package/runner/src/profile-home.ts +1 -1
- package/runner/src/project-instructions.ts +2 -2
- package/runner/src/provider-command.ts +18 -0
- package/runner/src/provider-setup.ts +35 -0
- package/runner/src/providers.ts +2 -1
- package/runner/src/runner-core.ts +32 -38
- package/runner/src/runner-helpers.ts +0 -8
- package/runner/src/session-scratch.ts +6 -2
- package/runner/src/spawn-input.ts +2 -1
- package/runner/src/test-run-dedup.ts +59 -56
- package/runner/test-support/provisioning-context.ts +4 -2
- package/runner/test-support/runner-harness.ts +2 -1
- package/scripts/cd-config.ts +8 -0
- package/scripts/gate-run-lease.ts +10 -7
- package/scripts/gate.sh +5 -1
- package/scripts/steward-policy-cleanup.ts +2 -2
- package/src/agent-authz.ts +2 -2
- package/src/agent-drive-arbiter.ts +3 -8
- package/src/agent-exit-cleanup-async.ts +2 -2
- package/src/agent-exit-cleanup.ts +23 -19
- package/src/agent-lifecycle-events.ts +112 -85
- package/src/agent-ref.ts +3 -2
- package/src/agent-status-events.ts +43 -14
- package/src/auth/password.ts +4 -3
- package/src/auth/session-refresh.ts +1 -1
- package/src/auth/session.test-fixture.ts +2 -2
- package/src/auth/session.ts +7 -7
- package/src/automations/crud.ts +8 -81
- package/src/automations/dispatch.ts +33 -58
- package/src/automations/index.ts +1 -1
- package/src/automations/persistence.ts +65 -0
- package/src/automations/precheck.ts +18 -16
- package/src/automations/read-async.ts +11 -0
- package/src/automations/reconcile.ts +30 -39
- package/src/automations/storage.ts +33 -10
- package/src/automations/write-async.ts +33 -0
- package/src/branch-land-notice.ts +93 -0
- package/src/branch-landed.ts +31 -98
- package/src/bus.ts +40 -39
- package/src/cd-deploy-notify.ts +32 -4
- 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/notifications.ts +4 -4
- package/src/ci/root-missing.ts +4 -9
- package/src/ci/transition-notify.ts +12 -44
- package/src/claude-app/oauth-http.ts +3 -3
- 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 +19 -4
- package/src/commands-db.ts +7 -7
- package/src/commands-write.ts +8 -0
- package/src/compaction-watch.ts +10 -8
- package/src/config-store-write.ts +13 -1
- package/src/config-store.ts +25 -14
- package/src/config.ts +4 -11
- package/src/connectors.ts +10 -8
- package/src/context-advisory.ts +22 -21
- package/src/db/activity-async.ts +6 -1
- package/src/db/activity-write-ops.ts +12 -1
- package/src/db/activity.ts +1 -14
- package/src/db/agent-action-write.ts +36 -0
- package/src/db/agent-control-async.ts +9 -0
- package/src/db/agent-control-write.ts +49 -0
- package/src/db/agent-effort-observe.ts +22 -0
- package/src/db/agent-meta.ts +14 -3
- package/src/db/agent-search.ts +1 -15
- package/src/db/agents-async.ts +59 -9
- package/src/db/agents-write-ops.ts +12 -3
- package/src/db/agents.ts +95 -65
- package/src/db/auth-identities.ts +2 -2
- package/src/db/automation-read-ops.ts +11 -0
- package/src/db/automation-write-ops.ts +46 -0
- package/src/db/blackboard.ts +2 -2
- package/src/db/browser-session-write.ts +32 -0
- package/src/db/bus-outbox-write-ops.ts +3 -1
- package/src/db/checkout-refresh-schema.ts +47 -0
- package/src/db/checkout-refresh.ts +5 -5
- package/src/db/ci-incidents-async.ts +5 -5
- package/src/db/ci-incidents-write-ops.ts +2 -2
- package/src/db/command-agent-profile-backfill.ts +39 -0
- package/src/db/command-agent-profiles.ts +5 -1
- package/src/db/command-retention.ts +126 -0
- package/src/db/command-row.ts +10 -2
- package/src/db/commands-list-query.ts +2 -0
- package/src/db/commands-planner-stats.test-fixture.ts +8 -0
- package/src/db/commands-read-ops.ts +16 -0
- package/src/db/commands-spawn-read.ts +1 -1
- package/src/db/config-store-write-ops.ts +7 -2
- package/src/db/connection.ts +1 -182
- package/src/db/context-carry-write.ts +74 -0
- package/src/db/continuation-archives-async.ts +5 -0
- package/src/db/continuation-archives-write-ops.ts +7 -0
- package/src/db/continuations.ts +6 -6
- package/src/db/db-error-registry.ts +12 -0
- package/src/db/db-writer-worker.ts +8 -1
- 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/gateway.ts +26 -133
- package/src/db/history-retention-ops.ts +13 -0
- package/src/db/hosts-registration.ts +10 -2
- package/src/db/hosts.ts +9 -6
- package/src/db/inbox-async.ts +2 -2
- package/src/db/inbox-read-ops.ts +1 -1
- package/src/db/inbox.ts +9 -17
- package/src/db/index.ts +2 -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-associations.ts +2 -2
- package/src/db/issue-lifecycle.ts +3 -4
- package/src/db/issue-refs-async.ts +23 -0
- package/src/db/issue-refs-read-ops.ts +6 -0
- package/src/db/issue-refs-write-ops.ts +29 -0
- package/src/db/issue-refs.ts +15 -16
- package/src/db/kernel-event-log-schema.ts +2 -0
- package/src/db/land-boundaries.ts +51 -5
- package/src/db/land-gate-attestations.ts +2 -2
- package/src/db/landing-receipts.ts +2 -2
- package/src/db/lifecycle-context-write.ts +5 -0
- package/src/db/lifecycle-tail-async.ts +76 -0
- package/src/db/lifecycle-tail-write-ops.ts +62 -0
- package/src/db/lifecycle-write-window.ts +2 -1
- package/src/db/lineage-pair-dedupe-sql.ts +3 -3
- package/src/db/long-running-work.ts +2 -2
- package/src/db/main-connection-mode.ts +11 -0
- package/src/db/main-connection-writes.ts +41 -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/maintenance-pauses.ts +2 -2
- package/src/db/mappers.ts +2 -14
- package/src/db/merge-lease.ts +1 -15
- package/src/db/message-send.ts +4 -0
- package/src/db/messages.ts +31 -25
- package/src/db/migrations.ts +25 -16
- package/src/db/notification-write-ops.ts +19 -0
- package/src/db/operator-answer-write.ts +19 -0
- package/src/db/orchestrators.ts +14 -76
- package/src/db/pairs-async.ts +22 -1
- package/src/db/pairs-write-ops.ts +8 -3
- package/src/db/pairs.ts +42 -61
- package/src/db/plan-dispatch-schema.ts +5 -1
- package/src/db/plan-ready-notices.ts +43 -0
- package/src/db/plan-tools-include-migration.ts +36 -0
- package/src/db/plans-write-ops.ts +2 -0
- package/src/db/presence-buffer.ts +5 -0
- package/src/db/presence-loop.ts +18 -23
- package/src/db/presence-write.ts +0 -6
- package/src/db/project-entries-async.ts +14 -0
- package/src/db/project-entries-read-ops.ts +5 -1
- package/src/db/project-entries-write-ops.ts +8 -0
- package/src/db/project-entries.ts +15 -12
- package/src/db/project-journal.ts +2 -2
- package/src/db/project-profile-instructions.ts +50 -0
- package/src/db/project-trust-approvals.ts +2 -2
- package/src/db/prompt-templates.ts +4 -4
- package/src/db/prompt-versions.ts +9 -2
- package/src/db/provider-config-history.ts +8 -3
- package/src/db/provider-model-seed.ts +34 -0
- package/src/db/read-op-marshaling-fixtures.ts +23 -0
- package/src/db/read-ops.ts +8 -0
- package/src/db/retention.ts +13 -2
- package/src/db/review-publish-write.ts +8 -0
- package/src/db/routing-policy.ts +2 -3
- package/src/db/runtime-admin-async.ts +19 -0
- package/src/db/runtime-admin-write-ops.ts +36 -0
- package/src/db/runtime-tail-async.ts +288 -0
- package/src/db/runtime-tail-write-ops.ts +97 -0
- package/src/db/schema.ts +13 -4
- package/src/db/spawn-budget.ts +5 -0
- package/src/db/spawn-delegation-state.ts +11 -4
- package/src/db/spawn-delegation.ts +1 -11
- package/src/db/sql-audit-indexes.ts +3 -0
- package/src/db/stats-async.ts +9 -6
- package/src/db/task-entity.ts +28 -6
- package/src/db/task-list.ts +3 -1
- package/src/db/tasks.ts +1 -17
- package/src/db/team-claim-policy.ts +60 -0
- package/src/db/teams-async.ts +4 -0
- package/src/db/teams-write-ops.ts +4 -0
- package/src/db/terminal-events.ts +15 -0
- package/src/db/timer-cutover-bodies.ts +292 -0
- package/src/db/timer-cutover-core.ts +37 -278
- package/src/db/timer-cutover-state.ts +40 -0
- package/src/db/timer-cutover-write-ops.ts +1 -40
- package/src/db/timer-ingress.ts +7 -1
- package/src/db/token-db-write-ops.ts +19 -0
- package/src/db/token-standing-async.ts +12 -0
- package/src/db/token-standing.ts +21 -20
- package/src/db/token-usage-retention.ts +33 -0
- package/src/db/token-usage-write-ops.ts +1 -1
- package/src/db/token-usage.ts +4 -1
- package/src/db/user-invites-async.ts +13 -0
- package/src/db/user-invites.ts +3 -3
- package/src/db/users.ts +14 -6
- package/src/db/workflow-contact.ts +1 -1
- package/src/db/workflow-task-read-ops.ts +30 -0
- package/src/db/workspaces.ts +8 -5
- package/src/db/write-ops.ts +37 -12
- package/src/db/writer-fault-seam.ts +2 -9
- package/src/db/writer-fault-test-ops.ts +18 -0
- package/src/db/writer-gateway.ts +58 -56
- package/src/dev.ts +8 -3
- 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/event-loop-lag.ts +4 -2
- package/src/event-loop-yield.ts +2 -2
- package/src/events.ts +10 -8
- package/src/host/disk-alert.ts +121 -0
- package/src/host-provider-store.ts +5 -4
- package/src/hub-metrics-report.ts +5 -1
- package/src/hub-metrics.ts +38 -18
- package/src/injection-sweep-pacing.ts +6 -8
- package/src/land-gate-notifications.ts +11 -10
- package/src/land-gate-queue-progress.ts +3 -3
- package/src/land-settle-dispatch.ts +52 -92
- package/src/lifecycle-context-pressure.ts +11 -10
- package/src/lifecycle-manager.ts +107 -100
- package/src/maintenance/breaker.ts +18 -16
- package/src/maintenance/cd-watcher.ts +3 -3
- package/src/maintenance/checkout-refresh.ts +18 -1
- package/src/maintenance/critical-job-watchdog.ts +19 -20
- package/src/maintenance/events.ts +3 -3
- package/src/maintenance/history-retention-job.ts +30 -0
- package/src/maintenance/index.ts +1 -0
- package/src/maintenance/jobs.ts +32 -69
- package/src/maintenance/long-running-work.ts +3 -1
- package/src/maintenance/offline-agent-prune-job.ts +28 -0
- package/src/maintenance/orphaned-sessions.ts +5 -4
- package/src/maintenance/pauses.ts +4 -10
- package/src/maintenance/plan-ready-notice-job.ts +71 -0
- package/src/maintenance/scheduler.ts +98 -137
- package/src/maintenance/stalled-delivery-pager.ts +10 -9
- package/src/maintenance/teams.ts +19 -30
- package/src/maintenance/workspaces.ts +18 -28
- package/src/managed-policy-escalation.ts +7 -7
- package/src/managed-policy.ts +32 -28
- package/src/managed-provider-gate.ts +5 -4
- package/src/managed-spawn-reservation.ts +5 -4
- package/src/mcp/index.ts +12 -9
- package/src/mcp/output-descriptions.ts +8 -8
- package/src/mcp/presentation.ts +6 -5
- package/src/mcp/project-profile-instructions.ts +32 -0
- package/src/mcp/runtime-output.ts +6 -1
- package/src/mcp/self-care-visibility.ts +2 -2
- package/src/mcp/spawn-targets-matrix.ts +10 -1
- package/src/mcp/tool-groups.ts +4 -3
- package/src/mcp/tool-roles.ts +81 -0
- package/src/mcp/tools-spawn.ts +4 -3
- package/src/mcp/tools-workspace.ts +1 -1
- package/src/mcp-agent-action.ts +1 -2
- package/src/mcp-blackboard-tools.ts +6 -5
- package/src/mcp-decision-tools.ts +7 -7
- package/src/mcp-egress-tools.ts +10 -9
- package/src/mcp-issue-activity-tools.ts +2 -2
- package/src/mcp-issue-association-tools.ts +4 -4
- package/src/mcp-issue-ref-tools.ts +13 -12
- package/src/mcp-maintenance-tools.ts +2 -2
- package/src/mcp-merge-tools.ts +5 -5
- package/src/mcp-notification-subscription-tools.ts +14 -15
- package/src/mcp-output-levels.test-fixture.ts +1 -1
- package/src/mcp-profile-trust-tools.ts +5 -5
- package/src/mcp-project-journal-tools.ts +4 -12
- package/src/mcp-project-tools.ts +17 -18
- package/src/mcp-provider-catalog.ts +2 -2
- package/src/mcp-routing-policy-tools.ts +3 -2
- package/src/mcp-task-tools.ts +11 -5
- package/src/mcp-team-template-tools.ts +3 -3
- package/src/mcp-team-tools.ts +6 -6
- package/src/mcp-workflow-tools.ts +13 -4
- package/src/memory-area-injection.ts +13 -12
- package/src/memory-boundary-capture.ts +6 -6
- package/src/memory-injection.ts +45 -43
- package/src/merge-pause-maintenance.ts +5 -4
- package/src/notification-router.ts +44 -17
- package/src/notification-types.ts +2 -1
- package/src/notify.ts +5 -5
- package/src/observed-reset-refresh.ts +4 -4
- package/src/operator-alarm.ts +23 -11
- package/src/project-ingest.ts +6 -6
- package/src/project-instructions.ts +12 -1
- package/src/project-profile-instruction-text.ts +6 -0
- package/src/project-profile-instructions.ts +20 -0
- package/src/project-trust.ts +12 -11
- package/src/prompt-resolver.ts +3 -3
- 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-async.ts +5 -7
- package/src/provider-quota-config-store.ts +5 -4
- package/src/provider-secrets.test-fixture.ts +3 -3
- package/src/provider-timeline-event.ts +4 -7
- package/src/quota-band-delivery.ts +2 -2
- package/src/recipe-runner.ts +6 -5
- package/src/repo-config-source.ts +10 -4
- package/src/retention-config-store.ts +4 -3
- package/src/reviewer-pipeline.ts +11 -10
- package/src/routes/_route.ts +4 -4
- package/src/routes/_shared.ts +13 -12
- package/src/routes/agent-effort.ts +5 -5
- package/src/routes/agent-heartbeat-quota.ts +23 -0
- package/src/routes/agent-keep.ts +1 -1
- package/src/routes/agent-profiles.ts +6 -6
- package/src/routes/agent-reporting.ts +1 -1
- package/src/routes/agent-self-effort.ts +5 -5
- package/src/routes/agent-sessions.ts +24 -24
- package/src/routes/agents-spawn.ts +2 -2
- package/src/routes/agents.ts +19 -121
- package/src/routes/auth.ts +14 -15
- package/src/routes/authority-audit.ts +2 -2
- package/src/routes/automations.ts +6 -5
- package/src/routes/channel-binding-delete.ts +1 -1
- package/src/routes/channel-output.ts +3 -3
- package/src/routes/claude-api-budget.ts +5 -5
- package/src/routes/commands-listing.ts +5 -1
- package/src/routes/commands.ts +31 -29
- package/src/routes/context-resets.ts +2 -2
- package/src/routes/continuation-archives.ts +2 -2
- package/src/routes/coordinator-teams.ts +1 -1
- package/src/routes/decisions.ts +2 -2
- package/src/routes/host-secret-files.ts +1 -1
- package/src/routes/hosts.ts +11 -11
- package/src/routes/inbox.ts +3 -2
- package/src/routes/index.ts +12 -2
- package/src/routes/integrations.ts +32 -56
- package/src/routes/issue-activity.ts +2 -2
- package/src/routes/issue-associations.ts +4 -4
- package/src/routes/issue-refs.ts +9 -9
- package/src/routes/kernel-timers-operator.ts +1 -1
- package/src/routes/memory.ts +1 -1
- package/src/routes/merges.ts +11 -11
- package/src/routes/messages.ts +23 -17
- package/src/routes/orchestrator-bootstrap.ts +2 -2
- package/src/routes/orchestrator-host-registration.ts +4 -2
- package/src/routes/orchestrator-host-utilization.ts +5 -3
- package/src/routes/orchestrator-proxy.ts +4 -4
- package/src/routes/orchestrator.ts +28 -19
- package/src/routes/pairs.ts +8 -8
- package/src/routes/project-profile-instructions.ts +27 -0
- package/src/routes/project-trust.ts +3 -3
- package/src/routes/projects.ts +16 -16
- package/src/routes/prompt-templates.ts +12 -12
- package/src/routes/provider-config.ts +6 -6
- package/src/routes/provider-quota-config.ts +2 -2
- package/src/routes/provider-quotas.ts +10 -10
- package/src/routes/run-command.ts +1 -1
- package/src/routes/secrets-backup.ts +2 -2
- package/src/routes/secrets-import.ts +1 -1
- package/src/routes/secrets-vault.ts +7 -7
- package/src/routes/settings.ts +6 -6
- package/src/routes/shipping.ts +9 -1
- package/src/routes/spawn-policy.ts +8 -7
- package/src/routes/sse.ts +2 -2
- 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 +12 -12
- package/src/routes/teams-config.ts +2 -2
- package/src/routes/teams.ts +10 -10
- package/src/routes/tokens.ts +30 -22
- package/src/routes/users.ts +24 -24
- package/src/routes/viewer-read.ts +3 -3
- package/src/routes/web-tool-calls.ts +4 -4
- package/src/routes/workflows.ts +22 -7
- package/src/routes/workspaces.ts +17 -16
- package/src/routing-policy-normalize.ts +1 -2
- package/src/routing-policy-push.ts +6 -6
- package/src/routing-step-defaults.ts +0 -2
- package/src/runner-token-mint-limit.ts +63 -0
- package/src/runtime-grant.ts +21 -13
- package/src/runtime-tokens.ts +59 -35
- package/src/secrets-broker/config.ts +1 -1
- package/src/secrets-broker/service.ts +2 -2
- package/src/security.ts +16 -21
- package/src/self-resume-carry.ts +21 -110
- package/src/self-resume-supersede.ts +4 -3
- package/src/self-resume.ts +54 -66
- package/src/server-background.ts +2 -2
- package/src/server.ts +26 -24
- package/src/services/agent-action.ts +12 -31
- package/src/services/agent-effort.ts +7 -32
- package/src/services/agent-hang-watchdog-job.ts +2 -2
- package/src/services/agent-heartbeat.ts +166 -0
- package/src/services/agent-reporting.ts +1 -1
- package/src/services/browser-inventory.ts +3 -3
- package/src/services/browser-session-state.ts +3 -2
- package/src/services/browser-session.ts +21 -27
- package/src/services/bus-command-update.ts +9 -9
- package/src/services/checkout-refresh-state.ts +1 -0
- package/src/services/checkout-refresh.test-fixture.ts +3 -2
- package/src/services/command-host.ts +7 -2
- package/src/services/coordinator-digest.ts +3 -2
- package/src/services/dispatch-command.ts +12 -13
- package/src/services/effective-launch-driver.ts +14 -9
- package/src/services/host-changed-paths.test-fixture.ts +5 -6
- package/src/services/host-project-readiness.ts +2 -2
- package/src/services/host-providers.ts +1 -1
- package/src/services/host-utilization.ts +27 -4
- package/src/services/idle-agent-digest.ts +17 -12
- package/src/services/idle-epics.ts +9 -10
- package/src/services/interrupt-agent.ts +12 -9
- package/src/services/issue-activity.ts +3 -3
- package/src/services/issue-associations.ts +15 -18
- package/src/services/issue-lifecycle-comments.ts +3 -2
- package/src/services/issue-lifecycle.ts +69 -72
- package/src/services/issue-refs.ts +10 -15
- package/src/services/kernel-timers-cutover-chaos-worker.ts +11 -8
- package/src/services/kernel-timers-ingress-chaos-worker.ts +6 -1
- package/src/services/kernel-timers-ingress.ts +4 -4
- package/src/services/kernel-timers-message-authority-chaos-worker.ts +3 -10
- package/src/services/kernel-timers-operator-chaos-worker.ts +3 -2
- package/src/services/kernel-timers-outbox.ts +1 -1
- package/src/services/kernel-timers-stage10-operator.ts +1 -1
- package/src/services/kernel-timers.ts +4 -3
- package/src/services/land-gate-placement.ts +11 -2
- package/src/services/land-issue-relations.ts +5 -4
- package/src/services/land-restart-retry.ts +7 -6
- package/src/services/landed-ancestry.ts +25 -8
- package/src/services/legacy-landing-host.ts +4 -1
- package/src/services/legacy-landing-recovery.ts +8 -6
- package/src/services/managed-running.ts +17 -17
- package/src/services/memory-areas.ts +17 -53
- package/src/services/merge-pause.ts +9 -15
- package/src/services/operator-decisions.ts +37 -41
- package/src/services/orchestrator-registration-recovery.ts +6 -2
- package/src/services/orchestrator-upgrade.ts +14 -12
- package/src/services/permission-decision.ts +4 -3
- package/src/services/plan-ci-notice.ts +57 -0
- package/src/services/plan-ci-recovery.ts +2 -55
- package/src/services/plan-conformance.ts +4 -4
- package/src/services/plan-dispatch-policy.ts +10 -3
- package/src/services/plan-dispatch.ts +35 -14
- package/src/services/plan-graph.ts +39 -261
- package/src/services/plan-import.ts +1 -1
- package/src/services/plan-live-bindings.ts +8 -37
- package/src/services/plan-task-create.ts +1 -1
- package/src/services/plan-terminal-refs.ts +2 -12
- package/src/services/plan-wake-digest.ts +9 -3
- package/src/services/profile-trust.ts +6 -5
- package/src/services/project-config-read.ts +70 -0
- package/src/services/project-profile-instructions.ts +54 -0
- package/src/services/project.ts +11 -10
- package/src/services/prompt-templates.ts +6 -5
- package/src/services/provider-hold-nudge.ts +9 -9
- package/src/services/provider-hold-record.ts +13 -12
- package/src/services/provider-state-audit.ts +19 -18
- package/src/services/provisioning-harness/budget-baseline.json +4 -4
- package/src/services/provisioning-harness/driver.ts +1 -1
- package/src/services/provisioning-harness/fixture-matrix.ts +3 -3
- package/src/services/provisioning-harness/lifecycle.ts +24 -22
- package/src/services/provisioning-harness/prepare.ts +16 -17
- package/src/services/rate-limit-resume.ts +10 -9
- package/src/services/red-main-auto-revert.ts +7 -5
- package/src/services/red-main-controller-deps.ts +20 -3
- package/src/services/red-main-incident.ts +3 -1
- package/src/services/red-main-quarantine.ts +2 -3
- package/src/services/register-agent.ts +22 -22
- package/src/services/restart-project-role.ts +1 -1
- package/src/services/restart-spawn.ts +74 -61
- package/src/services/review-publish.ts +7 -24
- package/src/services/review-ref-reconcile.ts +29 -38
- package/src/services/runtime-dependency-alert.ts +27 -0
- package/src/services/scheduler-command.ts +11 -9
- package/src/services/scheduler.ts +5 -5
- package/src/services/self-care-state.ts +2 -1
- package/src/services/self-effort-grant.ts +5 -25
- package/src/services/self-effort.ts +5 -5
- package/src/services/send-message.ts +21 -34
- package/src/services/shutdown-agent.ts +17 -14
- package/src/services/spawn-agent.ts +25 -43
- package/src/services/spawn-chain-inspector.ts +7 -14
- package/src/services/spawn-cwd-placement.ts +21 -5
- package/src/services/spawn-issue-activity.ts +8 -6
- package/src/services/spawn-launch.ts +17 -1
- package/src/services/spawn-loss-escalation.ts +1 -1
- package/src/services/spawn-policy.ts +68 -0
- package/src/services/spawn-registration-watchdog.ts +2 -2
- package/src/services/spawn-repo-probe.ts +7 -5
- package/src/services/spawn-tree-cleanup.ts +8 -9
- package/src/services/steward-reaper.ts +4 -4
- package/src/services/task-context-hydration.ts +25 -1
- package/src/services/task-delivery.ts +20 -34
- package/src/services/task-dispatch.ts +3 -0
- package/src/services/task-entity.ts +40 -203
- package/src/services/task-issue-link.ts +13 -20
- package/src/services/task-issue-weave.ts +12 -11
- package/src/services/task-lifecycle.ts +27 -31
- package/src/services/task-repo-cwd.ts +37 -0
- package/src/services/task-review-hold.ts +4 -17
- package/src/services/task-semantic-events.ts +13 -11
- package/src/services/task-state-reconcile.ts +8 -17
- package/src/services/task-validation.ts +2 -2
- package/src/services/team-templates.ts +12 -11
- package/src/services/team.ts +31 -98
- package/src/services/terminal-provider-exit.ts +6 -5
- package/src/services/timer-message-fire-chaos-worker.ts +7 -3
- package/src/services/timer-message-fire-outbox.ts +1 -1
- package/src/services/transient-agent-reaper.ts +25 -20
- package/src/services/turn-reconcile-audit.ts +9 -9
- package/src/services/user-onboarding.ts +8 -6
- package/src/services/user-profile.ts +6 -9
- package/src/services/work-finality.ts +16 -4
- package/src/services/workflow-auto-start.ts +26 -13
- package/src/services/workflow-caller.ts +61 -4
- package/src/services/workflow-child-proof-worker.ts +1 -1
- package/src/services/workflow-ci-main.ts +1 -1
- package/src/services/workflow-control-proof-worker.ts +1 -1
- package/src/services/workflow-coordinator.ts +8 -2
- package/src/services/workflow-decisions.ts +5 -5
- package/src/services/workflow-deferred-cleanup.ts +5 -3
- package/src/services/workflow-effect-driver.ts +42 -17
- package/src/services/workflow-effects.ts +58 -37
- package/src/services/workflow-land-notice.ts +10 -0
- package/src/services/workflow-pause-text.ts +43 -0
- package/src/services/workflow-pins.ts +7 -4
- package/src/services/workflow-reconcile.ts +14 -11
- package/src/services/workflow-resume-pins.ts +3 -3
- package/src/services/workflow-routing-defaults.ts +18 -0
- package/src/services/workflow-run-view.ts +6 -3
- package/src/services/workflow-run.test-fixture.ts +1 -1
- package/src/services/workflow-runs.ts +61 -33
- package/src/services/workflow-supervisor-state.ts +26 -1
- package/src/services/workflow-supervisor.ts +11 -6
- package/src/services/workspace-recovery.ts +4 -3
- package/src/settings/registry.ts +1 -2
- package/src/spawn-admission.ts +10 -2
- package/src/spawn-command.ts +4 -4
- package/src/spawn-models.ts +10 -12
- package/src/spawn-placement.ts +28 -10
- package/src/spawn-targets.ts +9 -9
- package/src/sse-agent-status.ts +15 -6
- package/src/sse.ts +49 -24
- package/src/startup-context-injection.ts +62 -57
- 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-handoff.ts +4 -3
- package/src/steward-policy-cleanup.ts +9 -8
- package/src/steward.ts +9 -8
- package/src/task-dispatch-live.ts +6 -3
- package/src/task-dispatcher.ts +3 -3
- package/src/teams-config-store.ts +4 -3
- package/src/token-db-write.ts +10 -0
- package/src/token-db.ts +2 -2
- package/src/token-usage-async.ts +2 -4
- package/src/user-awaiting-reply.ts +5 -5
- package/src/workspace-actions.ts +24 -29
- package/src/workspace-auto-merge.ts +14 -12
- package/src/workspace-changed-paths-client.ts +16 -5
- package/src/workspace-cleanup-stale.ts +30 -7
- package/src/workspace-command-settle.ts +26 -17
- package/src/workspace-config.ts +1 -1
- package/src/workspace-conflict-resolver.ts +9 -7
- package/src/workspace-dead-owner-recovery.ts +5 -4
- package/src/workspace-escalation.ts +12 -11
- package/src/workspace-human-escalation.ts +3 -3
- package/src/workspace-land-gate-watchdog.ts +3 -3
- package/src/workspace-land-refusal.ts +20 -0
- package/src/workspace-land-stopped.ts +1 -0
- package/src/workspace-merge.ts +10 -26
- package/src/workspace-nothing-to-land-notice.ts +2 -2
- package/src/workspace-orphans.ts +18 -37
- package/src/workspace-pr-completion.ts +10 -8
- package/src/workspace-rekey.ts +3 -3
- package/src/workspace-steward-failure.ts +2 -2
- package/src/workspace-steward-wake.ts +4 -4
- 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 -39
- 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 -42
- 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/index-B7ZerHLY.css +0 -2
- package/public/assets/index-BU3uWo2t.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/shipping-Bu8p1gEw.js +0 -2
- package/public/assets/store-BvtFdlGX.js +0 -9
- package/public/assets/use-project-list-B-T2Bnnn.js +0 -2
- package/public/assets/versioned-prompt-editor-Diu8BIaM.js +0 -8
- package/runner/src/agent-runner/http-liveness.ts +0 -85
- package/runner/src/gate-run-lease-probe.ts +0 -38
- package/src/db/claude-catalog-reconcile.ts +0 -27
- package/src/db/on-loop-write-transaction.ts +0 -34
- package/src/routing-model-aliases.ts +0 -21
package/src/db/migrations.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { COMMAND_RETENTION_SCHEMA, ensureCommandRetentionReferenceIndexes } from "./command-retention";
|
|
2
|
+
import { migrateCheckoutRefreshHeads } from "./checkout-refresh-schema";
|
|
3
|
+
import { TOKEN_USAGE_RETENTION_SCHEMA } from "./token-usage-retention";
|
|
1
4
|
import { PLAN_DISPATCH_SCHEMA_SQL } from "./plan-dispatch-schema";
|
|
2
5
|
import { PLAN_IMPORT_SCHEMA_SQL } from "./plan-import-schema";
|
|
3
6
|
import { ensureDurablePayloadSchema } from "./durable-payloads"; import { redactProviderConfigHistory } from "./provider-config-history"; import { retireMemoryStorage } from "./memory-retirement";
|
|
@@ -21,7 +24,6 @@ import { backfillLegacyMessages } from "./legacy-message-backfill";
|
|
|
21
24
|
import { installHistoryDeliverySettlement } from "./history-delivery-settle";
|
|
22
25
|
import { installReplyObligations } from "./reply-obligations";
|
|
23
26
|
import { beginStartupPhase, timeStartupPhase } from "../startup-timing";
|
|
24
|
-
import { Database } from "bun:sqlite";
|
|
25
27
|
import { AGENT_EXIT_REPORT_SCHEMA } from "./agent-exit-report";
|
|
26
28
|
import { CONTEXT_RESET_SCHEMA } from "./context-reset-carry";
|
|
27
29
|
import { TASK_TOKEN_TOTALS_SCHEMA } from "./token-usage";
|
|
@@ -30,20 +32,8 @@ import { migrateOperatorActionsSchema } from "./operator-actions-schema";
|
|
|
30
32
|
import { SELF_EFFORT_PERMISSIONS_SCHEMA } from "./self-effort-permissions";
|
|
31
33
|
import { AGENT_EFFORT_STATE_SCHEMA, importLegacyEffortCommands } from "./agent-effort-state";
|
|
32
34
|
import { randomUUID } from "node:crypto";
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
import { parseJson } from "../utils";
|
|
36
|
-
import { isLiveIsolatedWorkspace } from "../workspace-phase";
|
|
37
|
-
import {
|
|
38
|
-
CONTRACT_REQUIREMENTS,
|
|
39
|
-
contractCompatibility,
|
|
40
|
-
parseRuntimeCapabilities,
|
|
41
|
-
parseRuntimeContracts,
|
|
42
|
-
parseRuntimePackage,
|
|
43
|
-
type RuntimeContracts,
|
|
44
|
-
} from "../contracts";
|
|
45
|
-
import { STALE_TTL_MS, DAY_MS, CLAIM_LEASE_MS, POOL_CLAIM_LEASE_MS, WORKSPACE_MERGE_LEASE_MS } from "../config";
|
|
46
|
-
import { matchAgents } from "../agent-ref";
|
|
35
|
+
import { PROJECT_PROFILE_INSTRUCTIONS_SCHEMA_SQL } from "./project-profile-instructions";
|
|
36
|
+
import { CLAIM_LEASE_MS } from "../config";
|
|
47
37
|
import { COORDINATOR_PROFILE_NAMES } from "../agent-system-tags";
|
|
48
38
|
import { getDb } from "./connection.ts";
|
|
49
39
|
import { normalizeExistingAgentSpawnRequestIds } from "./spawn-request-id-migration.ts";
|
|
@@ -79,6 +69,7 @@ import { migrateTeamProjectSeats } from "./team-project.ts";
|
|
|
79
69
|
import { ensureArtifactCreatorAgentColumn } from "./artifacts.ts";
|
|
80
70
|
import { rewriteEmptyToolGroupsToAbsent } from "./tool-groups-empty-migration.ts";
|
|
81
71
|
import { backfillProjectMemoryToolGroup } from "./project-memory-group-migration.ts";
|
|
72
|
+
import { backfillPlanToolsIntoToolIncludes } from "./plan-tools-include-migration.ts";
|
|
82
73
|
import { removeLegacyProfileProjectInstructions } from "./profile-legacy-project-instructions-migration.ts";
|
|
83
74
|
import { migrateProfileHostSources } from "./profile-host-sources-migration.ts";
|
|
84
75
|
import { migrateProfileProjectAcks } from "./profile-project-ack-migration.ts";
|
|
@@ -154,6 +145,7 @@ function backfillProjectRootRemoteUrls(): void {
|
|
|
154
145
|
// shape, so they must run in historical order. Built-in agent seeding and the
|
|
155
146
|
// read_by backfill live here too — both run unconditionally and idempotently.
|
|
156
147
|
export function applyMigrations(): void {
|
|
148
|
+
getDb().run(PROJECT_PROFILE_INSTRUCTIONS_SCHEMA_SQL);
|
|
157
149
|
getDb().run(PLAN_IMPORT_SCHEMA_SQL);
|
|
158
150
|
ensureVaultTokensSchema();
|
|
159
151
|
ensureVaultHealthSchema();
|
|
@@ -181,7 +173,15 @@ export function applyMigrations(): void {
|
|
|
181
173
|
)
|
|
182
174
|
`);
|
|
183
175
|
getDb().run("CREATE INDEX IF NOT EXISTS idx_issue_refs_external ON issue_refs(provider, repo, external_key)");
|
|
184
|
-
|
|
176
|
+
// #3799 — matches the listing ORDER BY exactly, so a list is a bounded index walk with no sort; supersedes (updated_at DESC).
|
|
177
|
+
getDb().run("CREATE INDEX IF NOT EXISTS idx_issue_refs_listing ON issue_refs(updated_at DESC, created_at DESC, id DESC)");
|
|
178
|
+
getDb().run("DROP INDEX IF EXISTS idx_issue_refs_updated");
|
|
179
|
+
// #3799 — automation_runs list/scan indexes: status+created_at supersedes the plain status index, created_at serves the
|
|
180
|
+
// unfiltered listing, and the partial index holds exactly the open task-bound runs the reconcile pass walks.
|
|
181
|
+
getDb().run("CREATE INDEX IF NOT EXISTS idx_automation_runs_status_created ON automation_runs(status, created_at)");
|
|
182
|
+
getDb().run("DROP INDEX IF EXISTS idx_automation_runs_status");
|
|
183
|
+
getDb().run("CREATE INDEX IF NOT EXISTS idx_automation_runs_created ON automation_runs(created_at DESC)");
|
|
184
|
+
getDb().run("CREATE INDEX IF NOT EXISTS idx_automation_runs_open ON automation_runs(created_at) WHERE status IN ('scheduled', 'dispatching', 'waiting_agent', 'running') AND task_id IS NOT NULL");
|
|
185
185
|
// #2520 — the GitHub close classification (completed|not_planned) cached beside the status so
|
|
186
186
|
// plan-node terminal propagation can tell a completed close from a not-planned one. The guarded
|
|
187
187
|
// ALTER converges databases created before the column existed with the CREATE above.
|
|
@@ -678,6 +678,7 @@ export function applyMigrations(): void {
|
|
|
678
678
|
ensureIngestedMemoryIndex();
|
|
679
679
|
rewriteEmptyToolGroupsToAbsent(); // #1963 N2 — persisted relay.tools.groups:[] meant ALL; honoring [] as NONE requires rewriting existing [] → absent first
|
|
680
680
|
backfillProjectMemoryToolGroup(); // #2154 follow-up — stored/overridden profiles do not pick up the built-in `project-memory` group on their own
|
|
681
|
+
backfillPlanToolsIntoToolIncludes(); // #3812 — lean per-tool allowlists (coordinator) never gained relay_plan_start/import
|
|
681
682
|
removeLegacyProfileProjectInstructions(); // #2133 — remove retired profile policy fields before profile override migration reads legacy rows
|
|
682
683
|
backfillCustomProfileArtifacts(); // #3171 — Artifact is off by default now; keep the approved custom brainstorm exception
|
|
683
684
|
migrateAgentProfileOverridesToV2(); // #1963 N10 — back up + migrate persisted override rows to the v2 matrix (D-T=off; G6/G7 leave-untouched-and-report; flag-gated rollback)
|
|
@@ -1281,6 +1282,7 @@ export function applyMigrations(): void {
|
|
|
1281
1282
|
// addTaskCol guard as the rest of the #834 batch: existing rows read back as absent.
|
|
1282
1283
|
addTaskCol("tags", "tags TEXT");
|
|
1283
1284
|
addTaskCol("priority", "priority TEXT");
|
|
1285
|
+
addTaskCol("paths", "paths TEXT"); // #3736
|
|
1284
1286
|
// #1535 WS1 — parent/epic tree edge. Self-referential FK via ALTER TABLE ADD COLUMN is
|
|
1285
1287
|
// proven safe in this codebase already (messages.reply_to above); cycle-guarding lives
|
|
1286
1288
|
// in application code (task-entity.ts), not a DB constraint.
|
|
@@ -1294,10 +1296,13 @@ export function applyMigrations(): void {
|
|
|
1294
1296
|
addTaskCol("review_hold", "review_hold INTEGER NOT NULL DEFAULT 0 CHECK (review_hold IN (0, 1))");
|
|
1295
1297
|
addTaskCol("validation_items", "validation_items TEXT");
|
|
1296
1298
|
addTaskCol("terminal_stage", "terminal_stage TEXT");
|
|
1299
|
+
addTaskCol("on_deploy", "on_deploy TEXT");
|
|
1297
1300
|
addTaskCol("completed_at", "completed_at INTEGER");
|
|
1298
1301
|
addTaskCol("owner", "owner TEXT"); // #2862 — backfilled by backfillTaskOwners below
|
|
1299
1302
|
migratePlanBlurbsOnStartup(); // #2082 S5 — fold legacy bound-node blurbs before stripping them
|
|
1300
1303
|
getDb().run("CREATE INDEX IF NOT EXISTS idx_tasks_message_status ON tasks(message_id, status) WHERE message_id IS NOT NULL");
|
|
1304
|
+
// #3740: existing databases need the same covering expression index as fresh schemas.
|
|
1305
|
+
getDb().run("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)");
|
|
1301
1306
|
getDb().run("CREATE INDEX IF NOT EXISTS idx_tasks_kind ON tasks(kind, status, updated_at)");
|
|
1302
1307
|
getDb().run("CREATE INDEX IF NOT EXISTS idx_tasks_branch ON tasks(branch) WHERE branch IS NOT NULL");
|
|
1303
1308
|
getDb().run("CREATE INDEX IF NOT EXISTS idx_tasks_team ON tasks(team_id) WHERE team_id IS NOT NULL");
|
|
@@ -1741,6 +1746,10 @@ export function applyMigrations(): void {
|
|
|
1741
1746
|
getDb().run(AGENT_EXIT_REPORT_SCHEMA);
|
|
1742
1747
|
getDb().run(CONTEXT_RESET_SCHEMA); // #3398
|
|
1743
1748
|
getDb().run(TASK_TOKEN_TOTALS_SCHEMA);
|
|
1749
|
+
getDb().run(TOKEN_USAGE_RETENTION_SCHEMA);
|
|
1750
|
+
getDb().run(COMMAND_RETENTION_SCHEMA);
|
|
1751
|
+
migrateCheckoutRefreshHeads(getDb());
|
|
1752
|
+
ensureCommandRetentionReferenceIndexes(getDb());
|
|
1744
1753
|
getDb().run(SHIPPING_STATS_SCHEMA);
|
|
1745
1754
|
getDb().run(CI_GATE_BACKFILL_SCHEMA); getDb().run(AGENT_GATE_RUNS_SCHEMA); ensureAgentGateCommandSchema(); repairRerunGateTimings(); ensureCiShaObservationsSchema();
|
|
1746
1755
|
migrateOperatorActionsSchema();
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { sendMessageWithResultInternal } from "./messages";
|
|
2
|
+
import { insertAgentNoticeSlot, type AgentNoticeSlot } from "./terminal-events";
|
|
3
|
+
import type { SendMessageInput } from "../types";
|
|
4
|
+
import type { WriterOpContext, WriterOpSpec } from "./write-ops";
|
|
5
|
+
|
|
6
|
+
const send = (inputs: SendMessageInput[], now: number) => inputs.map(input => sendMessageWithResultInternal(input, false, {}, now));
|
|
7
|
+
export const NOTIFICATION_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.freeze({
|
|
8
|
+
"notifications.route": {
|
|
9
|
+
offLoop: true, idempotent: false,
|
|
10
|
+
fn: ({ inputs }: { inputs: SendMessageInput[] }, ctx: WriterOpContext) => send(inputs, ctx.now),
|
|
11
|
+
},
|
|
12
|
+
"notifications.agentNotice": {
|
|
13
|
+
offLoop: true, idempotent: false,
|
|
14
|
+
fn: ({ slot, inputs }: { slot: AgentNoticeSlot; inputs: SendMessageInput[] }, ctx: WriterOpContext) => {
|
|
15
|
+
const created = insertAgentNoticeSlot(slot, ctx.now);
|
|
16
|
+
return { created, results: created ? send(inputs, ctx.now) : [] };
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { answerOpenOperatorDecision, getOperatorDecision, getWorkflowOperatorDecision, insertOperatorDecision, setOperatorDecisionAnswerMessage } from "./operator-decisions";
|
|
2
|
+
import { sendMessageWithResultInternal } from "./messages";
|
|
3
|
+
import type { SendMessageInput } from "../types";
|
|
4
|
+
export interface OperatorAnswerWrite {
|
|
5
|
+
id: number;
|
|
6
|
+
answer: Parameters<typeof answerOpenOperatorDecision>[1];
|
|
7
|
+
message: SendMessageInput;
|
|
8
|
+
}
|
|
9
|
+
export function answerOperatorDecisionBody({ id, answer, message }: OperatorAnswerWrite) {
|
|
10
|
+
if (!answerOpenOperatorDecision(id, answer)) return null;
|
|
11
|
+
const result = sendMessageWithResultInternal(message, false, {}, answer.now);
|
|
12
|
+
setOperatorDecisionAnswerMessage(id, result.message.id);
|
|
13
|
+
return { decision: getOperatorDecision(id)!, result };
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function fileWorkflowDecisionBody(input: Parameters<typeof insertOperatorDecision>[0]) {
|
|
17
|
+
const existing = getWorkflowOperatorDecision(input.workflow!.effectId);
|
|
18
|
+
return existing ? { decision: existing, created: false } : { decision: insertOperatorDecision(input), created: true };
|
|
19
|
+
}
|
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, upsertAgentInternal, type UpsertAgentTxResult } from "./agents.ts";
|
|
13
|
+
import { STALE_TTL_MS } from "../config";
|
|
14
|
+
import { deleteAgentInternal, 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) {
|
|
@@ -452,13 +385,18 @@ export function reportOrchestratorRosterRow(id: string, agents: ManagedAgent[],
|
|
|
452
385
|
return { orchestrator: getOrchestrator(id), rosterChanged: true, workspaces };
|
|
453
386
|
}
|
|
454
387
|
|
|
455
|
-
|
|
456
388
|
export function deleteOrchestrator(id: string): boolean {
|
|
389
|
+
const result = deleteOrchestratorRow(id, Date.now());
|
|
390
|
+
if (result.agentId) evictPendingPresence(result.agentId);
|
|
391
|
+
return result.deleted;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
export function deleteOrchestratorRow(id: string, now: number): { deleted: boolean; agentId?: string } {
|
|
457
395
|
const orch = getOrchestrator(id);
|
|
458
|
-
if (!orch) return false;
|
|
396
|
+
if (!orch) return { deleted: false };
|
|
459
397
|
getDb().query("DELETE FROM orchestrators WHERE id = ?").run(id);
|
|
460
|
-
|
|
461
|
-
return true;
|
|
398
|
+
deleteAgentInternal(orch.agentId, now);
|
|
399
|
+
return { deleted: true, agentId: orch.agentId };
|
|
462
400
|
}
|
|
463
401
|
|
|
464
402
|
export function hasStaleOrchestrator(cutoff: number): boolean {
|
package/src/db/pairs-async.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import type { createPair, acceptPair, rejectPair, endPair, sendPairMessage, getPair, listPairs } from "./pairs";
|
|
1
3
|
import { getGateway } from "./gateway";
|
|
2
|
-
import type { getPair, listPairs } from "./pairs";
|
|
3
4
|
|
|
4
5
|
export function getPairAsync(id: string): Promise<ReturnType<typeof getPair>> {
|
|
5
6
|
return getGateway().write("pairs.getCurrent", { id }) as Promise<ReturnType<typeof getPair>>;
|
|
@@ -8,3 +9,23 @@ export function getPairAsync(id: string): Promise<ReturnType<typeof getPair>> {
|
|
|
8
9
|
export function listPairsAsync(filter?: Parameters<typeof listPairs>[0]): Promise<ReturnType<typeof listPairs>> {
|
|
9
10
|
return getGateway().write("pairs.listCurrent", filter) as unknown as Promise<ReturnType<typeof listPairs>>;
|
|
10
11
|
}
|
|
12
|
+
|
|
13
|
+
export function createPairAsync(...args: Parameters<typeof createPair>): Promise<ReturnType<typeof createPair>> {
|
|
14
|
+
return getGateway().write("pairs.createPair", args, { idempotencyKey: randomUUID() }) as unknown as Promise<ReturnType<typeof createPair>>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function acceptPairAsync(...args: Parameters<typeof acceptPair>): Promise<ReturnType<typeof acceptPair>> {
|
|
18
|
+
return getGateway().write("pairs.acceptPair", args, { idempotencyKey: randomUUID() }) as unknown as Promise<ReturnType<typeof acceptPair>>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function rejectPairAsync(...args: Parameters<typeof rejectPair>): Promise<ReturnType<typeof rejectPair>> {
|
|
22
|
+
return getGateway().write("pairs.rejectPair", args, { idempotencyKey: randomUUID() }) as unknown as Promise<ReturnType<typeof rejectPair>>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function endPairAsync(...args: Parameters<typeof endPair>): Promise<ReturnType<typeof endPair>> {
|
|
26
|
+
return getGateway().write("pairs.endPair", args, { idempotencyKey: randomUUID() }) as unknown as Promise<ReturnType<typeof endPair>>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function sendPairMessageAsync(...args: Parameters<typeof sendPairMessage>): Promise<ReturnType<typeof sendPairMessage>> {
|
|
30
|
+
return getGateway().write("pairs.sendPairMessage", args, { idempotencyKey: randomUUID() }) as unknown as Promise<ReturnType<typeof sendPairMessage>>;
|
|
31
|
+
}
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
import { getPair, listPairs } from "./pairs";
|
|
1
|
+
import { createPair, acceptPair, rejectPair, endPair, sendPairMessage, getPair, listPairs } from "./pairs";
|
|
2
2
|
import type { WriterOpSpec } from "./write-ops";
|
|
3
3
|
|
|
4
4
|
// Pair reads settle expired requests before returning the current view.
|
|
5
5
|
export const PAIRS_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = {
|
|
6
|
-
"pairs.getCurrent": { idempotent: true, offLoop: true, fn: (args: { id: string }) => getPair(args.id) },
|
|
7
|
-
"pairs.listCurrent": { idempotent: true, offLoop: true, fn: (args: Parameters<typeof listPairs>[0]) => listPairs(args) },
|
|
6
|
+
"pairs.getCurrent": { idempotent: true, offLoop: true, fn: (args: { id: string }, ctx) => getPair(args.id, ctx.now) },
|
|
7
|
+
"pairs.listCurrent": { idempotent: true, offLoop: true, fn: (args: Parameters<typeof listPairs>[0], ctx) => listPairs(args, ctx.now) },
|
|
8
|
+
"pairs.createPair": { offLoop: true, idempotent: false, fn: (a: Parameters<typeof createPair>, ctx) => createPair(a[0], a[1] ?? ctx.now) },
|
|
9
|
+
"pairs.acceptPair": { offLoop: true, idempotent: false, fn: (a: Parameters<typeof acceptPair>, ctx) => acceptPair(a[0], a[1], a[2] ?? ctx.now) },
|
|
10
|
+
"pairs.rejectPair": { offLoop: true, idempotent: false, fn: (a: Parameters<typeof rejectPair>, ctx) => rejectPair(a[0], a[1], a[2] ?? ctx.now) },
|
|
11
|
+
"pairs.endPair": { offLoop: true, idempotent: false, fn: (a: Parameters<typeof endPair>, ctx) => endPair(a[0], a[1], a[2] ?? ctx.now) },
|
|
12
|
+
"pairs.sendPairMessage": { offLoop: true, idempotent: false, fn: (a: Parameters<typeof sendPairMessage>, ctx) => sendPairMessage(a[0], a[1], a[2] ?? ctx.now) },
|
|
8
13
|
};
|
package/src/db/pairs.ts
CHANGED
|
@@ -1,22 +1,10 @@
|
|
|
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";
|
|
18
6
|
import { rowToPair } from "./mappers.ts";
|
|
19
|
-
import {
|
|
7
|
+
import { sendMessageWithResultInternal } from "./messages.ts";
|
|
20
8
|
export { closeOpenPairsForAgent } from "./pair-maintenance.ts";
|
|
21
9
|
import type {
|
|
22
10
|
AgentCard,
|
|
@@ -38,8 +26,8 @@ function expirePendingPairs(now: number = Date.now()): void {
|
|
|
38
26
|
.run(now, now, now);
|
|
39
27
|
}
|
|
40
28
|
|
|
41
|
-
function getOpenPairForAgent(agentId: string): PairSession | null {
|
|
42
|
-
expirePendingPairs();
|
|
29
|
+
function getOpenPairForAgent(agentId: string, now: number = Date.now()): PairSession | null {
|
|
30
|
+
expirePendingPairs(now);
|
|
43
31
|
const row = getDb().query(`
|
|
44
32
|
SELECT * FROM pairs
|
|
45
33
|
WHERE status IN ('pending', 'active') AND (requester_id = ? OR target_id = ?)
|
|
@@ -57,7 +45,7 @@ function pairPeer(pair: PairSession, agentId: string): string {
|
|
|
57
45
|
return pair.requesterId === agentId ? pair.targetId : pair.requesterId;
|
|
58
46
|
}
|
|
59
47
|
|
|
60
|
-
function resolvePairTarget(target: string, requesterId: string): {
|
|
48
|
+
function resolvePairTarget(target: string, requesterId: string, now: number = Date.now()): {
|
|
61
49
|
ok: true;
|
|
62
50
|
agent: AgentCard;
|
|
63
51
|
} | {
|
|
@@ -76,7 +64,7 @@ function resolvePairTarget(target: string, requesterId: string): {
|
|
|
76
64
|
const busy: Array<{ agent: AgentCard; pair: PairSession }> = [];
|
|
77
65
|
const available: AgentCard[] = [];
|
|
78
66
|
for (const agent of live) {
|
|
79
|
-
const openPair = getOpenPairForAgent(agent.id);
|
|
67
|
+
const openPair = getOpenPairForAgent(agent.id, now);
|
|
80
68
|
if (openPair) busy.push({ agent, pair: openPair });
|
|
81
69
|
else available.push(agent);
|
|
82
70
|
}
|
|
@@ -93,8 +81,8 @@ function resolvePairTarget(target: string, requesterId: string): {
|
|
|
93
81
|
return { ok: true, agent: available[0]! };
|
|
94
82
|
}
|
|
95
83
|
|
|
96
|
-
function pairSystemMessage(pair: PairSession, to: string, event: string, subject: string, body: string): Message {
|
|
97
|
-
return
|
|
84
|
+
function pairSystemMessage(pair: PairSession, to: string, event: string, subject: string, body: string, now: number = Date.now()): Message {
|
|
85
|
+
return sendMessageWithResultInternal({
|
|
98
86
|
from: "system",
|
|
99
87
|
to,
|
|
100
88
|
kind: "pair",
|
|
@@ -107,17 +95,17 @@ function pairSystemMessage(pair: PairSession, to: string, event: string, subject
|
|
|
107
95
|
targetId: pair.targetId,
|
|
108
96
|
pairStatus: pair.status,
|
|
109
97
|
},
|
|
110
|
-
});
|
|
98
|
+
}, false, {}, now).message;
|
|
111
99
|
}
|
|
112
100
|
|
|
113
|
-
export function getPair(id: string): PairSession | null {
|
|
114
|
-
expirePendingPairs();
|
|
101
|
+
export function getPair(id: string, now: number = Date.now()): PairSession | null {
|
|
102
|
+
expirePendingPairs(now);
|
|
115
103
|
const row = getDb().query("SELECT * FROM pairs WHERE id = ?").get(id) as any;
|
|
116
104
|
return row ? rowToPair(row) : null;
|
|
117
105
|
}
|
|
118
106
|
|
|
119
|
-
export function listPairs(filter?: { agentId?: string; status?: PairStatus }): PairSession[] {
|
|
120
|
-
expirePendingPairs();
|
|
107
|
+
export function listPairs(filter?: { agentId?: string; status?: PairStatus }, now: number = Date.now()): PairSession[] {
|
|
108
|
+
expirePendingPairs(now);
|
|
121
109
|
const conditions: string[] = [];
|
|
122
110
|
const params: any[] = [];
|
|
123
111
|
if (filter?.agentId) {
|
|
@@ -132,7 +120,7 @@ export function listPairs(filter?: { agentId?: string; status?: PairStatus }): P
|
|
|
132
120
|
return (getDb().query(`SELECT * FROM pairs ${where} ORDER BY updated_at DESC LIMIT 100`).all(...params) as any[]).map(rowToPair);
|
|
133
121
|
}
|
|
134
122
|
|
|
135
|
-
export function createPair(input: CreatePairInput): {
|
|
123
|
+
export function createPair(input: CreatePairInput, now: number = Date.now()): {
|
|
136
124
|
ok: true;
|
|
137
125
|
pair: PairSession;
|
|
138
126
|
invite: Message;
|
|
@@ -143,25 +131,23 @@ export function createPair(input: CreatePairInput): {
|
|
|
143
131
|
matches?: AgentCard[];
|
|
144
132
|
busy?: Array<{ agent: AgentCard; pair: PairSession }>;
|
|
145
133
|
} {
|
|
146
|
-
expirePendingPairs();
|
|
134
|
+
expirePendingPairs(now);
|
|
147
135
|
const requester = getAgent(input.from);
|
|
148
136
|
if (!requester) return { ok: false, code: "invalid", error: `requester agent ${input.from} not registered` };
|
|
149
137
|
if (requester.status === "offline" || !requester.ready) return { ok: false, code: "offline", error: `requester agent ${input.from} is not online and ready` };
|
|
150
|
-
const requesterPair = getOpenPairForAgent(input.from);
|
|
138
|
+
const requesterPair = getOpenPairForAgent(input.from, now);
|
|
151
139
|
if (requesterPair) return { ok: false, code: "busy", error: `requester is already paired`, busy: [{ agent: requester, pair: requesterPair }] };
|
|
152
140
|
|
|
153
|
-
const resolved = resolvePairTarget(input.target, input.from);
|
|
141
|
+
const resolved = resolvePairTarget(input.target, input.from, now);
|
|
154
142
|
if (!resolved.ok) return resolved;
|
|
155
143
|
if (resolved.agent.id === input.from) return { ok: false, code: "invalid", error: "cannot pair with yourself" };
|
|
156
|
-
|
|
157
|
-
const now = Date.now();
|
|
158
144
|
const ttlMs = Math.min(Math.max(input.ttlMs ?? DEFAULT_PAIR_TTL_MS, 10_000), MAX_PAIR_TTL_MS);
|
|
159
145
|
const id = randomUUID();
|
|
160
146
|
getDb().query(`
|
|
161
147
|
INSERT INTO pairs (id, requester_id, target_id, status, objective, meta, created_at, updated_at, expires_at)
|
|
162
148
|
VALUES (?, ?, ?, 'pending', ?, ?, ?, ?, ?)
|
|
163
149
|
`).run(id, input.from, resolved.agent.id, input.objective ?? null, JSON.stringify(input.meta ?? {}), now, now, now + ttlMs);
|
|
164
|
-
const pair = getPair(id)!;
|
|
150
|
+
const pair = getPair(id, now)!;
|
|
165
151
|
const objective = pair.objective ? `\n\nObjective:\n${pair.objective}` : "";
|
|
166
152
|
const invite = pairSystemMessage(
|
|
167
153
|
pair,
|
|
@@ -175,14 +161,14 @@ export function createPair(input: CreatePairInput): {
|
|
|
175
161
|
"Accept with POST /api/pairs/{id}/accept using your agentId.",
|
|
176
162
|
"Reject with POST /api/pairs/{id}/reject using your agentId.",
|
|
177
163
|
"Pairing is exclusive: each agent can be in at most one pending or active pair.",
|
|
178
|
-
].join("\n"),
|
|
164
|
+
].join("\n"), now
|
|
179
165
|
);
|
|
180
166
|
return { ok: true, pair, invite };
|
|
181
167
|
}
|
|
182
168
|
|
|
183
|
-
export function acceptPair(id: string, input: PairActionInput): { ok: true; pair: PairSession; notices: Message[] } | { ok: false; error: string; code: "not_found" | "forbidden" | "busy" | "invalid" } {
|
|
184
|
-
expirePendingPairs();
|
|
185
|
-
const pair = getPair(id);
|
|
169
|
+
export function acceptPair(id: string, input: PairActionInput, now: number = Date.now()): { ok: true; pair: PairSession; notices: Message[] } | { ok: false; error: string; code: "not_found" | "forbidden" | "busy" | "invalid" } {
|
|
170
|
+
expirePendingPairs(now);
|
|
171
|
+
const pair = getPair(id, now);
|
|
186
172
|
if (!pair) return { ok: false, code: "not_found", error: "pair not found" };
|
|
187
173
|
if (pair.status !== "pending") return { ok: false, code: "invalid", error: `pair is ${pair.status}` };
|
|
188
174
|
if (pair.targetId !== input.agentId) return { ok: false, code: "forbidden", error: "only the target agent can accept this pair" };
|
|
@@ -192,61 +178,56 @@ export function acceptPair(id: string, input: PairActionInput): { ok: true; pair
|
|
|
192
178
|
if (!requester || requester.status === "offline" || !requester.ready) return { ok: false, code: "invalid", error: "requester agent is no longer online and ready" };
|
|
193
179
|
|
|
194
180
|
for (const agentId of [pair.requesterId, pair.targetId]) {
|
|
195
|
-
const open = getOpenPairForAgent(agentId);
|
|
181
|
+
const open = getOpenPairForAgent(agentId, now);
|
|
196
182
|
if (open && open.id !== pair.id) return { ok: false, code: "busy", error: `${agentId} is already paired` };
|
|
197
183
|
}
|
|
198
|
-
|
|
199
|
-
const now = Date.now();
|
|
200
184
|
getDb().query("UPDATE pairs SET status = 'active', accepted_at = ?, updated_at = ? WHERE id = ? AND status = 'pending'")
|
|
201
185
|
.run(now, now, id);
|
|
202
|
-
const active = getPair(id)!;
|
|
186
|
+
const active = getPair(id, now)!;
|
|
203
187
|
const notices = [
|
|
204
|
-
pairSystemMessage(active, active.requesterId, "accepted", `Pair accepted by ${active.targetId}`, `Pair ${active.id} is active. Send pair messages with POST /api/pairs/${active.id}/messages
|
|
205
|
-
pairSystemMessage(active, active.targetId, "accepted", `Pair active with ${active.requesterId}`, `Pair ${active.id} is active. Send pair messages with POST /api/pairs/${active.id}/messages
|
|
188
|
+
pairSystemMessage(active, active.requesterId, "accepted", `Pair accepted by ${active.targetId}`, `Pair ${active.id} is active. Send pair messages with POST /api/pairs/${active.id}/messages.`, now),
|
|
189
|
+
pairSystemMessage(active, active.targetId, "accepted", `Pair active with ${active.requesterId}`, `Pair ${active.id} is active. Send pair messages with POST /api/pairs/${active.id}/messages.`, now),
|
|
206
190
|
];
|
|
207
191
|
return { ok: true, pair: active, notices };
|
|
208
192
|
}
|
|
209
193
|
|
|
210
|
-
export function rejectPair(id: string, input: PairActionInput): { ok: true; pair: PairSession; notice: Message } | { ok: false; error: string; code: "not_found" | "forbidden" | "invalid" } {
|
|
211
|
-
expirePendingPairs();
|
|
212
|
-
const pair = getPair(id);
|
|
194
|
+
export function rejectPair(id: string, input: PairActionInput, now: number = Date.now()): { ok: true; pair: PairSession; notice: Message } | { ok: false; error: string; code: "not_found" | "forbidden" | "invalid" } {
|
|
195
|
+
expirePendingPairs(now);
|
|
196
|
+
const pair = getPair(id, now);
|
|
213
197
|
if (!pair) return { ok: false, code: "not_found", error: "pair not found" };
|
|
214
198
|
if (pair.status !== "pending") return { ok: false, code: "invalid", error: `pair is ${pair.status}` };
|
|
215
199
|
if (pair.targetId !== input.agentId) return { ok: false, code: "forbidden", error: "only the target agent can reject this pair" };
|
|
216
|
-
const now = Date.now();
|
|
217
200
|
getDb().query("UPDATE pairs SET status = 'rejected', ended_at = ?, ended_by = ?, updated_at = ? WHERE id = ?")
|
|
218
201
|
.run(now, input.agentId, now, id);
|
|
219
|
-
const rejected = getPair(id)!;
|
|
202
|
+
const rejected = getPair(id, now)!;
|
|
220
203
|
const reason = input.reason ? `\n\nReason:\n${input.reason}` : "";
|
|
221
|
-
const notice = pairSystemMessage(rejected, rejected.requesterId, "rejected", `Pair rejected by ${input.agentId}`, `Pair ${rejected.id} was rejected.${reason}
|
|
204
|
+
const notice = pairSystemMessage(rejected, rejected.requesterId, "rejected", `Pair rejected by ${input.agentId}`, `Pair ${rejected.id} was rejected.${reason}`, now);
|
|
222
205
|
return { ok: true, pair: rejected, notice };
|
|
223
206
|
}
|
|
224
207
|
|
|
225
|
-
export function endPair(id: string, input: PairActionInput): { ok: true; pair: PairSession; notice?: Message } | { ok: false; error: string; code: "not_found" | "forbidden" | "invalid" } {
|
|
226
|
-
expirePendingPairs();
|
|
227
|
-
const pair = getPair(id);
|
|
208
|
+
export function endPair(id: string, input: PairActionInput, now: number = Date.now()): { ok: true; pair: PairSession; notice?: Message } | { ok: false; error: string; code: "not_found" | "forbidden" | "invalid" } {
|
|
209
|
+
expirePendingPairs(now);
|
|
210
|
+
const pair = getPair(id, now);
|
|
228
211
|
if (!pair) return { ok: false, code: "not_found", error: "pair not found" };
|
|
229
212
|
if (!pairParticipant(pair, input.agentId)) return { ok: false, code: "forbidden", error: "only pair participants can hang up" };
|
|
230
213
|
if (!OPEN_PAIR_STATUSES.includes(pair.status as any)) return { ok: false, code: "invalid", error: `pair is ${pair.status}` };
|
|
231
|
-
const now = Date.now();
|
|
232
214
|
getDb().query("UPDATE pairs SET status = 'ended', ended_at = ?, ended_by = ?, updated_at = ? WHERE id = ?")
|
|
233
215
|
.run(now, input.agentId, now, id);
|
|
234
|
-
const ended = getPair(id)!;
|
|
216
|
+
const ended = getPair(id, now)!;
|
|
235
217
|
const reason = input.reason ? `\n\nReason:\n${input.reason}` : "";
|
|
236
218
|
const peer = pairPeer(ended, input.agentId);
|
|
237
|
-
const notice = pairSystemMessage(ended, peer, "ended", `Pair ended by ${input.agentId}`, `Pair ${ended.id} ended.${reason}
|
|
219
|
+
const notice = pairSystemMessage(ended, peer, "ended", `Pair ended by ${input.agentId}`, `Pair ${ended.id} ended.${reason}`, now);
|
|
238
220
|
return { ok: true, pair: ended, notice };
|
|
239
221
|
}
|
|
240
222
|
|
|
241
|
-
export function sendPairMessage(id: string, input: PairMessageInput): { ok: true; pair: PairSession; message: Message } | { ok: false; error: string; code: "not_found" | "forbidden" | "invalid" } {
|
|
242
|
-
expirePendingPairs();
|
|
243
|
-
const pair = getPair(id);
|
|
223
|
+
export function sendPairMessage(id: string, input: PairMessageInput, now: number = Date.now()): { ok: true; pair: PairSession; message: Message } | { ok: false; error: string; code: "not_found" | "forbidden" | "invalid" } {
|
|
224
|
+
expirePendingPairs(now);
|
|
225
|
+
const pair = getPair(id, now);
|
|
244
226
|
if (!pair) return { ok: false, code: "not_found", error: "pair not found" };
|
|
245
227
|
if (pair.status !== "active") return { ok: false, code: "invalid", error: `pair is ${pair.status}` };
|
|
246
228
|
if (!pairParticipant(pair, input.from)) return { ok: false, code: "forbidden", error: "only pair participants can send pair messages" };
|
|
247
229
|
const to = pairPeer(pair, input.from);
|
|
248
|
-
const
|
|
249
|
-
const message = sendMessage({
|
|
230
|
+
const message = sendMessageWithResultInternal({
|
|
250
231
|
from: input.from,
|
|
251
232
|
to,
|
|
252
233
|
kind: "pair",
|
|
@@ -258,7 +239,7 @@ export function sendPairMessage(id: string, input: PairMessageInput): { ok: true
|
|
|
258
239
|
requesterId: pair.requesterId,
|
|
259
240
|
targetId: pair.targetId,
|
|
260
241
|
},
|
|
261
|
-
});
|
|
242
|
+
}, false, {}, now).message;
|
|
262
243
|
getDb().query("UPDATE pairs SET last_message_at = ?, updated_at = ? WHERE id = ?").run(now, now, id);
|
|
263
|
-
return { ok: true, pair: getPair(id)!, message };
|
|
244
|
+
return { ok: true, pair: getPair(id, now)!, message };
|
|
264
245
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// #3660 — plan autopilot tables (see plan-dispatch-store.ts); dependency-free so the startup catalog can include it.
|
|
1
|
+
// #3660 — plan autopilot tables (see plan-dispatch-store.ts) and ready-node notice state (plan-ready-notices.ts); dependency-free so the startup catalog can include it.
|
|
2
2
|
export const PLAN_DISPATCH_SCHEMA_SQL = `
|
|
3
3
|
CREATE TABLE IF NOT EXISTS task_executions (task_id INTEGER PRIMARY KEY, execution TEXT NOT NULL, updated_at INTEGER NOT NULL);
|
|
4
4
|
CREATE TABLE IF NOT EXISTS plan_dispatch (
|
|
@@ -14,4 +14,8 @@ export const PLAN_DISPATCH_SCHEMA_SQL = `
|
|
|
14
14
|
CREATE TABLE IF NOT EXISTS plan_ci_blocks (
|
|
15
15
|
run_id TEXT PRIMARY KEY, plan_id TEXT NOT NULL, task_id INTEGER NOT NULL, sha TEXT NOT NULL,
|
|
16
16
|
incident_ids TEXT NOT NULL, wait_key TEXT NOT NULL, retry_note TEXT NOT NULL, retried_at INTEGER
|
|
17
|
+
);
|
|
18
|
+
CREATE TABLE IF NOT EXISTS plan_ready_notices (
|
|
19
|
+
plan_id TEXT NOT NULL, node_id TEXT NOT NULL, ready_since INTEGER NOT NULL, notified_at INTEGER,
|
|
20
|
+
PRIMARY KEY (plan_id, node_id)
|
|
17
21
|
)`;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// #3660 — durable "ready since / already told" state per plan node, so a hub restart neither
|
|
2
|
+
// loses the unstarted-ready clock nor repeats a notice. A row exists exactly while the node is
|
|
3
|
+
// ready-and-unstarted; leaving ready deletes it, so re-entering ready starts a fresh clock.
|
|
4
|
+
import { getDb } from "./connection.ts";
|
|
5
|
+
|
|
6
|
+
export interface ReadyPlanScan { planId: string; nodeIds: string[] }
|
|
7
|
+
export interface DueReadyNodes { planId: string; nodes: Array<{ nodeId: string; readySince: number }> }
|
|
8
|
+
|
|
9
|
+
/** Reconcile every scanned plan's ready set; plans absent from `scans` (archived, done, deleted,
|
|
10
|
+
* coordinator-less) lose their rows. Returns the nodes ready for >= `dueMs` and not yet notified. */
|
|
11
|
+
export function syncPlanReadyNotices(args: { scans: ReadyPlanScan[]; now: number; dueMs: number }): DueReadyNodes[] {
|
|
12
|
+
const db = getDb();
|
|
13
|
+
const scanned = new Set(args.scans.map(scan => scan.planId));
|
|
14
|
+
for (const { plan_id } of db.query("SELECT DISTINCT plan_id FROM plan_ready_notices").all() as Array<{ plan_id: string }>) {
|
|
15
|
+
if (!scanned.has(plan_id)) db.query("DELETE FROM plan_ready_notices WHERE plan_id = ?").run(plan_id);
|
|
16
|
+
}
|
|
17
|
+
const due: DueReadyNodes[] = [];
|
|
18
|
+
for (const scan of args.scans) {
|
|
19
|
+
const keep = new Set(scan.nodeIds);
|
|
20
|
+
const rows = db.query("SELECT node_id, ready_since, notified_at FROM plan_ready_notices WHERE plan_id = ?").all(scan.planId) as
|
|
21
|
+
Array<{ node_id: string; ready_since: number; notified_at: number | null }>;
|
|
22
|
+
const nodes: DueReadyNodes["nodes"] = [];
|
|
23
|
+
const known = new Set<string>();
|
|
24
|
+
for (const row of rows) {
|
|
25
|
+
if (!keep.has(row.node_id)) { db.query("DELETE FROM plan_ready_notices WHERE plan_id = ? AND node_id = ?").run(scan.planId, row.node_id); continue; }
|
|
26
|
+
known.add(row.node_id);
|
|
27
|
+
if (row.notified_at === null && row.ready_since <= args.now - args.dueMs) nodes.push({ nodeId: row.node_id, readySince: row.ready_since });
|
|
28
|
+
}
|
|
29
|
+
for (const nodeId of keep) if (!known.has(nodeId)) db.query("INSERT INTO plan_ready_notices(plan_id, node_id, ready_since) VALUES(?, ?, ?)").run(scan.planId, nodeId, args.now);
|
|
30
|
+
if (nodes.length) due.push({ planId: scan.planId, nodes });
|
|
31
|
+
}
|
|
32
|
+
return due;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function markPlanReadyNoticed(args: { planId: string; nodeIds: string[]; now: number }): void {
|
|
36
|
+
const stmt = getDb().query("UPDATE plan_ready_notices SET notified_at = ? WHERE plan_id = ? AND node_id = ? AND notified_at IS NULL");
|
|
37
|
+
for (const nodeId of args.nodeIds) stmt.run(args.now, args.planId, nodeId);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const PLAN_READY_NOTICE_WRITE_OPS = {
|
|
41
|
+
"plans.readyNotices.sync": { offLoop: true, idempotent: true, fn: syncPlanReadyNotices },
|
|
42
|
+
"plans.readyNotices.mark": { offLoop: true, idempotent: true, fn: markPlanReadyNoticed },
|
|
43
|
+
};
|