@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/agents-async.ts
CHANGED
|
@@ -11,8 +11,16 @@
|
|
|
11
11
|
|
|
12
12
|
import { agentSessionGuardResult } from "./agent-predicates.ts";
|
|
13
13
|
import {
|
|
14
|
+
agentLifecycleWriteArgs,
|
|
15
|
+
bufferOrBypassHeartbeat,
|
|
14
16
|
getAgent,
|
|
17
|
+
prepareAgentLifecycleUpdate,
|
|
15
18
|
runBeforeAgentStatusTransitionHandlers,
|
|
19
|
+
type AgentLifecycleUpdate,
|
|
20
|
+
type AgentLifecycleUpdateResult,
|
|
21
|
+
type HeartbeatInput,
|
|
22
|
+
type OrphanedTokenPage,
|
|
23
|
+
type OrphanedTokenRevocation,
|
|
16
24
|
validateAgentSession,
|
|
17
25
|
type UpsertAgentTxResult,
|
|
18
26
|
type UpsertAgentOptions,
|
|
@@ -123,7 +131,7 @@ export async function setStatusAsync(id: string, status: AgentCard["status"], gu
|
|
|
123
131
|
const before = await getAgentAsync(id);
|
|
124
132
|
if (!agentSessionGuardResult(before, guard).ok) return false;
|
|
125
133
|
if (!before) return false;
|
|
126
|
-
if (before.status !== status) runBeforeAgentStatusTransitionHandlers(before, status);
|
|
134
|
+
if (before.status !== status) await runBeforeAgentStatusTransitionHandlers(before, status);
|
|
127
135
|
if (status === "offline" || status === "stale") evictPendingPresence(id);
|
|
128
136
|
const now = Date.now();
|
|
129
137
|
// #2111 — buffered into the short lifecycle window and submitted with its peers as ONE batch job.
|
|
@@ -209,6 +217,32 @@ export async function recordAgentExitDiagnosticsAsync(
|
|
|
209
217
|
return getAgentAsync(id);
|
|
210
218
|
}
|
|
211
219
|
|
|
220
|
+
/** `applyAgentLifecycleUpdate` with the write on the writer thread (#1870 S7). The guard, the `before` read
|
|
221
|
+
* and the transition handlers stay on the main thread ahead of submission; the op CAS-fences on
|
|
222
|
+
* `before.epoch`, so a takeover that lands in the hop turns this into a no-op instead of a clobber. */
|
|
223
|
+
export async function applyAgentLifecycleUpdateAsync(
|
|
224
|
+
id: string,
|
|
225
|
+
update: AgentLifecycleUpdate,
|
|
226
|
+
guard?: AgentSessionGuard,
|
|
227
|
+
now: number = Date.now(),
|
|
228
|
+
): Promise<AgentLifecycleUpdateResult> {
|
|
229
|
+
// Allocated first, per the ordinal-timing rule at the top of setStatusAsync.
|
|
230
|
+
const seq = nextLifecycleSeq();
|
|
231
|
+
const before = prepareAgentLifecycleUpdate(id, update, guard, false);
|
|
232
|
+
if (!before) return { ok: false, changed: false, metaWriteBytes: 0, before: null, after: null };
|
|
233
|
+
if (update.status !== undefined && update.status !== before.status) await runBeforeAgentStatusTransitionHandlers(before, update.status);
|
|
234
|
+
const result = (await getGateway().write("agents.applyLifecycleUpdate", agentLifecycleWriteArgs(before, update, seq, now))) as unknown as Omit<AgentLifecycleUpdateResult, "ok" | "before">;
|
|
235
|
+
return { ok: true, before, ...result };
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/** `recordHeartbeat` for the transports: a steady-state beat is buffered at once; a presence-critical one
|
|
239
|
+
* writes on the writer thread (#1870 S7). */
|
|
240
|
+
export async function recordHeartbeatAsync(id: string, opts: HeartbeatInput = {}): Promise<boolean> {
|
|
241
|
+
const beat = bufferOrBypassHeartbeat(id, opts);
|
|
242
|
+
if (typeof beat === "boolean") return beat;
|
|
243
|
+
return (await applyAgentLifecycleUpdateAsync(id, beat, opts.guard, opts.now ?? Date.now())).changed;
|
|
244
|
+
}
|
|
245
|
+
|
|
212
246
|
export async function heartbeatAsync(
|
|
213
247
|
id: string,
|
|
214
248
|
guard?: AgentSessionGuard,
|
|
@@ -263,7 +297,7 @@ export async function reapStaleAgentsAsync(ttlMs: number = STALE_TTL_MS, lagGrac
|
|
|
263
297
|
*/
|
|
264
298
|
export async function pruneOfflineAgentsAsync(
|
|
265
299
|
maxOfflineMs: number = DAY_MS,
|
|
266
|
-
options: { onFinality?: (result: WorkFinalFlushResult) => void } = {},
|
|
300
|
+
options: { onFinality?: (result: WorkFinalFlushResult) => void; onArchivePurgeFailure?: () => void } = {},
|
|
267
301
|
): Promise<string[]> {
|
|
268
302
|
const cutoff = Date.now() - maxOfflineMs;
|
|
269
303
|
const candidates = (await getGateway().read("agents.offlinePruneCandidates", {
|
|
@@ -271,7 +305,7 @@ export async function pruneOfflineAgentsAsync(
|
|
|
271
305
|
})) as unknown as AgentCard[];
|
|
272
306
|
const candidateIds = candidates.map((candidate) => candidate.id);
|
|
273
307
|
if (candidateIds.length === 0) return [];
|
|
274
|
-
await purgeArchivesBeforeDelete(candidateIds, cutoff);
|
|
308
|
+
if (!await purgeArchivesBeforeDelete(candidateIds, cutoff)) options.onArchivePurgeFailure?.();
|
|
275
309
|
|
|
276
310
|
const finalityQueues = takeDeferredLineageReports(candidateIds);
|
|
277
311
|
const refreshFinalityCandidates = candidates
|
|
@@ -301,11 +335,13 @@ export async function pruneOfflineAgentsAsync(
|
|
|
301
335
|
}
|
|
302
336
|
|
|
303
337
|
/** #3012 — best effort: whatever the off-loop purge leaves, the delete's own FK cascade still removes. */
|
|
304
|
-
async function purgeArchivesBeforeDelete(agentIds: string[], offlineBefore?: number): Promise<
|
|
338
|
+
async function purgeArchivesBeforeDelete(agentIds: string[], offlineBefore?: number): Promise<boolean> {
|
|
305
339
|
try {
|
|
306
340
|
await purgeContinuationArchivesAsync({ agentIds, offlineBefore });
|
|
341
|
+
return true;
|
|
307
342
|
} catch (error) {
|
|
308
343
|
console.warn("[agents] continuation archive purge before delete failed; the cascade will remove them:", error);
|
|
344
|
+
return false;
|
|
309
345
|
}
|
|
310
346
|
}
|
|
311
347
|
|
|
@@ -319,14 +355,28 @@ export async function deleteAgentAsync(id: string): Promise<{ ok: boolean; error
|
|
|
319
355
|
return deleted ? { ok: true } : { ok: false, error: "agent not found" };
|
|
320
356
|
}
|
|
321
357
|
|
|
358
|
+
// #3776 — the sweep is one short writer op per page of agents (each agent's lineage revoke stays atomic), so
|
|
359
|
+
// other writes interleave between pages. It stops when aborted or past its budget; the next run starts over.
|
|
360
|
+
const ORPHAN_SWEEP_PAGE_SIZE = 8;
|
|
361
|
+
const ORPHAN_SWEEP_BUDGET_MS = 30_000;
|
|
362
|
+
|
|
322
363
|
export async function revokeOrphanedRuntimeTokensAsync(
|
|
323
364
|
graceMs: number = STALE_TTL_MS,
|
|
324
365
|
lagGraceMs = 0,
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
366
|
+
options: { signal?: AbortSignal; budgetMs?: number; pageSize?: number } = {},
|
|
367
|
+
): Promise<{ revoked: OrphanedTokenRevocation[]; complete: boolean }> {
|
|
368
|
+
const { signal, budgetMs = ORPHAN_SWEEP_BUDGET_MS, pageSize = ORPHAN_SWEEP_PAGE_SIZE } = options;
|
|
369
|
+
const deadline = Date.now() + budgetMs;
|
|
370
|
+
const revoked: OrphanedTokenRevocation[] = [];
|
|
371
|
+
let afterId: string | undefined;
|
|
372
|
+
do {
|
|
373
|
+
if (signal?.aborted) return { revoked, complete: false };
|
|
374
|
+
const page = (await getGateway().write("agents.revokeOrphanedTokens", { graceMs, lagGraceMs, afterId, limit: pageSize })) as unknown as OrphanedTokenPage;
|
|
375
|
+
revoked.push(...page.revoked);
|
|
376
|
+
if (page.nextAfterId === null) return { revoked, complete: true };
|
|
377
|
+
afterId = page.nextAfterId;
|
|
378
|
+
} while (Date.now() < deadline);
|
|
379
|
+
return { revoked, complete: false };
|
|
330
380
|
}
|
|
331
381
|
|
|
332
382
|
export async function revokeRuntimeTokensForAgentAsync(
|
|
@@ -19,6 +19,8 @@ import { applyIdleSelfCare } from "./idle-self-care";
|
|
|
19
19
|
// write (none of these are) would need `idempotent: false` plus a caller-supplied key.
|
|
20
20
|
|
|
21
21
|
import {
|
|
22
|
+
applyAgentLifecycleUpdateInternal,
|
|
23
|
+
type AgentLifecycleWriteArgs,
|
|
22
24
|
clearAgentMetaKeys,
|
|
23
25
|
deleteAgentInternal,
|
|
24
26
|
heartbeat,
|
|
@@ -41,6 +43,7 @@ import {
|
|
|
41
43
|
import { pruneOfflineAgentsWithFinality, type AgentsPruneOfflineOpArgs } from "./agents-prune-write-op.ts";
|
|
42
44
|
import { setAgentKeepState } from "./agent-keep.ts";
|
|
43
45
|
import type { AgentCard, AgentKeep, AgentSessionGuard, ContextState, ManagedSessionExitDiagnostics, ProviderCapabilities, QuotaState, RegisterAgentInput } from "../types";
|
|
46
|
+
import type { OrphanedTokenPage } from "./agents.ts";
|
|
44
47
|
import type { LineageRevokeReason } from "./token-standing.ts";
|
|
45
48
|
import type { LifecycleWriteOutcome } from "./lifecycle-seq.ts";
|
|
46
49
|
import type { WriterOpContext, WriterOpSpec } from "./write-ops.ts";
|
|
@@ -69,7 +72,7 @@ export interface AgentsHeartbeatOpArgs {
|
|
|
69
72
|
export interface AgentsRecordContextSnapshotOpArgs { agentId: string; context: ContextState }
|
|
70
73
|
export interface AgentsReapStaleOpArgs { ttlMs: number; lagGraceMs: number; protectedIds?: string[]; seq: number }
|
|
71
74
|
export interface AgentsDeleteOpArgs { id: string }
|
|
72
|
-
export interface AgentsRevokeOrphanedTokensOpArgs { graceMs: number; lagGraceMs: number }
|
|
75
|
+
export interface AgentsRevokeOrphanedTokensOpArgs { graceMs: number; lagGraceMs: number; afterId?: string; limit?: number }
|
|
73
76
|
export interface AgentsRevokeTokensForAgentOpArgs { agentId: string; reason?: LineageRevokeReason }
|
|
74
77
|
|
|
75
78
|
export const AGENTS_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.freeze({
|
|
@@ -107,6 +110,12 @@ export const AGENTS_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.f
|
|
|
107
110
|
// coalescing window buffered them) and return a tri-state: `superseded` means a later-submitted
|
|
108
111
|
// lifecycle write already landed, which is a SUCCESS for the caller and must not be mistaken for a
|
|
109
112
|
// missing agent. See lifecycle-seq.ts.
|
|
113
|
+
"agents.applyLifecycleUpdate": {
|
|
114
|
+
// #1870 S7: bus status frame and heartbeat bypass; a replay of the same `seq` is a no-op on the fenced columns.
|
|
115
|
+
offLoop: true,
|
|
116
|
+
idempotent: true,
|
|
117
|
+
fn: (args: AgentLifecycleWriteArgs) => applyAgentLifecycleUpdateInternal(args),
|
|
118
|
+
},
|
|
110
119
|
"agents.setStatus": {
|
|
111
120
|
offLoop: true,
|
|
112
121
|
idempotent: true,
|
|
@@ -176,8 +185,8 @@ export const AGENTS_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.f
|
|
|
176
185
|
"agents.revokeOrphanedTokens": {
|
|
177
186
|
offLoop: true,
|
|
178
187
|
idempotent: true,
|
|
179
|
-
fn: (args: AgentsRevokeOrphanedTokensOpArgs, ctx: WriterOpContext):
|
|
180
|
-
revokeOrphanedRuntimeTokens(args.graceMs, args.lagGraceMs, ctx.now),
|
|
188
|
+
fn: (args: AgentsRevokeOrphanedTokensOpArgs, ctx: WriterOpContext): OrphanedTokenPage =>
|
|
189
|
+
revokeOrphanedRuntimeTokens(args.graceMs, args.lagGraceMs, ctx.now, { afterId: args.afterId, limit: args.limit }),
|
|
181
190
|
},
|
|
182
191
|
"agents.revokeTokensForAgent": {
|
|
183
192
|
offLoop: true,
|
package/src/db/agents.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { trackRelayEvent } from "../relay-event-drain";
|
|
1
2
|
import { mainThreadRegistry } from "./main-thread-state";
|
|
2
3
|
import { spawnTreeParentIds } from "./spawn-tree";
|
|
3
4
|
import { recordSpawnProcessExit } from "./spawn-process-evidence";
|
|
@@ -8,6 +9,7 @@ import { STALE_TTL_MS, DAY_MS } from "../config";
|
|
|
8
9
|
import { withoutAuthzMetaKeys } from "../authz-meta-keys";
|
|
9
10
|
import {
|
|
10
11
|
jsonBytes,
|
|
12
|
+
serializeProfileProjection,
|
|
11
13
|
splitAgentMetaForStorage,
|
|
12
14
|
splitAgentMetaPatchForStorage,
|
|
13
15
|
topLevelJsonPath,
|
|
@@ -48,10 +50,10 @@ import type {
|
|
|
48
50
|
QuotaState,
|
|
49
51
|
} from "../types";
|
|
50
52
|
|
|
51
|
-
type BeforeAgentStatusTransition = (agent: AgentCard, nextStatus: AgentCard["status"]) =>
|
|
53
|
+
type BeforeAgentStatusTransition = (agent: AgentCard, nextStatus: AgentCard["status"]) => unknown;
|
|
52
54
|
const beforeAgentStatusTransitionHandlers = mainThreadRegistry("agents.ts:beforeAgentStatusTransitionHandlers", new Set<BeforeAgentStatusTransition>());
|
|
53
55
|
|
|
54
|
-
/** Register
|
|
56
|
+
/** Register work that must finish before a status transition is persisted. */
|
|
55
57
|
export function onBeforeAgentStatusTransition(handler: BeforeAgentStatusTransition): () => void {
|
|
56
58
|
beforeAgentStatusTransitionHandlers.add(handler);
|
|
57
59
|
return () => beforeAgentStatusTransitionHandlers.delete(handler);
|
|
@@ -62,8 +64,9 @@ export function onBeforeAgentStatusTransition(handler: BeforeAgentStatusTransiti
|
|
|
62
64
|
* a writer-worker's own instance), so this must only ever be invoked main-thread-side: from
|
|
63
65
|
* `setStatus` directly, or from `setStatusAsync`'s pre-write orchestration. Never from the
|
|
64
66
|
* `agents.setStatus` op body. */
|
|
65
|
-
export function runBeforeAgentStatusTransitionHandlers(before: AgentCard, next: AgentCard["status"]): void {
|
|
66
|
-
|
|
67
|
+
export function runBeforeAgentStatusTransitionHandlers(before: AgentCard, next: AgentCard["status"]): Promise<void> {
|
|
68
|
+
const pending = [...beforeAgentStatusTransitionHandlers].map(handler => handler(before, next));
|
|
69
|
+
return trackRelayEvent(Promise.all(pending).then(() => {}), "agent.before-status");
|
|
67
70
|
}
|
|
68
71
|
|
|
69
72
|
const CONTEXT_SNAPSHOT_DEBOUNCE_MS = 60_000;
|
|
@@ -161,7 +164,7 @@ export function upsertAgentInternal(
|
|
|
161
164
|
const contextState = mergeRelayContextMarkers(input.id, input.context);
|
|
162
165
|
const storedMeta = splitAgentMetaForStorage(withCanonicalSpawnRequestId(input.meta));
|
|
163
166
|
const metaJson = JSON.stringify(storedMeta.meta);
|
|
164
|
-
const profileProjectionJson = storedMeta.
|
|
167
|
+
const profileProjectionJson = storedMeta.profileProjectionProvided ? serializeProfileProjection(input.id, storedMeta.profileProjection) : null;
|
|
165
168
|
warnIfAgentMetaOversized(input.id, metaJson, "stored meta");
|
|
166
169
|
const stmt = getDb().query(`
|
|
167
170
|
INSERT INTO agents (id, name, kind, label, tags, system_tags, machine, rig, capabilities, ready, status, instance_id, epoch, provider_capabilities, context_state, quota_state, profile_projection, meta, lifecycle, spawned_by, team_id, status_seq, ready_seq, last_seen, created_at)
|
|
@@ -479,28 +482,51 @@ export function applyAgentLifecycleUpdate(
|
|
|
479
482
|
guard?: AgentSessionGuard,
|
|
480
483
|
now: number = Date.now(),
|
|
481
484
|
): AgentLifecycleUpdateResult {
|
|
482
|
-
const
|
|
483
|
-
const before =
|
|
484
|
-
if (!before) return
|
|
485
|
-
|
|
485
|
+
const seq = nextLifecycleSeq();
|
|
486
|
+
const before = prepareAgentLifecycleUpdate(id, update, guard);
|
|
487
|
+
if (!before) return { ok: false, changed: false, metaWriteBytes: 0, before: null, after: null };
|
|
488
|
+
return { ok: true, before, ...inWriteTransaction(() => applyAgentLifecycleUpdateInternal(agentLifecycleWriteArgs(before, update, seq, now))) };
|
|
489
|
+
}
|
|
486
490
|
|
|
491
|
+
/** The writer-op args for one lifecycle delta (#1870 S7). `seq` is taken at the caller's entry (lifecycle-seq.ts
|
|
492
|
+
* rule 1); `expectedEpoch` fences the write to the instance `before` was read from across the writer hop. */
|
|
493
|
+
export interface AgentLifecycleWriteArgs {
|
|
494
|
+
id: string;
|
|
495
|
+
update: AgentLifecycleUpdate;
|
|
496
|
+
seq: number;
|
|
497
|
+
now: number;
|
|
498
|
+
expectedEpoch: number;
|
|
499
|
+
before: { instanceId?: string; spawnRequestId: string; terminalProviderExit?: unknown };
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
export function agentLifecycleWriteArgs(before: AgentCard, update: AgentLifecycleUpdate, seq: number, now: number): AgentLifecycleWriteArgs {
|
|
503
|
+
return { id: before.id, update, seq, now, expectedEpoch: before.epoch, before: { instanceId: before.instanceId, spawnRequestId: String(before.meta?.spawnRequestId ?? ""), terminalProviderExit: before.meta?.terminalProviderExit } };
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/** The main-thread half of a lifecycle delta: guard, `before` snapshot, transition handlers and presence
|
|
507
|
+
* eviction (main-thread state), all before the write is submitted. Null when the guard rejects. */
|
|
508
|
+
export function prepareAgentLifecycleUpdate(id: string, update: AgentLifecycleUpdate, guard?: AgentSessionGuard, runHandlers = true): AgentCard | null {
|
|
509
|
+
const before = getPersistedAgentRuntimeCard(id);
|
|
510
|
+
if (!before || !agentSessionGuardResult(before, guard).ok) return null;
|
|
487
511
|
const nextStatus = update.status;
|
|
488
|
-
// Pre-transition handlers
|
|
489
|
-
|
|
490
|
-
if (nextStatus !== undefined && nextStatus !== before.status) runBeforeAgentStatusTransitionHandlers(before, nextStatus);
|
|
512
|
+
// Pre-transition handlers must run BEFORE the write lands, exactly as `setStatus` does.
|
|
513
|
+
if (runHandlers && nextStatus !== undefined && nextStatus !== before.status) runBeforeAgentStatusTransitionHandlers(before, nextStatus);
|
|
491
514
|
// #1468 — a terminal transition evicts any buffered beat so a coalesced advance cannot later
|
|
492
515
|
// resurrect a gone agent at flush.
|
|
493
516
|
if (nextStatus === "offline" || nextStatus === "stale") evictPendingPresence(id);
|
|
517
|
+
return before;
|
|
518
|
+
}
|
|
494
519
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
const seq =
|
|
520
|
+
/** Op body (`agents.applyLifecycleUpdate`): the fenced UPDATE, its effects, and the offline post-commit, in the
|
|
521
|
+
* caller's transaction. #2111 review BLOCKER 1 — each written column's ordinal is raised, so a lifecycle write
|
|
522
|
+
* the coalescing window deferred cannot commit afterwards and undo it. */
|
|
523
|
+
export function applyAgentLifecycleUpdateInternal(args: AgentLifecycleWriteArgs): Omit<AgentLifecycleUpdateResult, "ok" | "before"> {
|
|
524
|
+
const { id, update, seq, now, before } = args;
|
|
525
|
+
const nextStatus = update.status;
|
|
500
526
|
// Named params throughout: the fenced-column fragments repeat `$seq`, which positional `?` could
|
|
501
527
|
// only express by counting placeholders across a dynamically-built SET list.
|
|
502
528
|
const sets: string[] = ["last_seen = $now"];
|
|
503
|
-
const params: Record<string, unknown> = { $now: now, $seq: seq, $id: id };
|
|
529
|
+
const params: Record<string, unknown> = { $now: now, $seq: seq, $id: id, $epoch: args.expectedEpoch };
|
|
504
530
|
let metaWriteBytes = 0;
|
|
505
531
|
if (nextStatus !== undefined) {
|
|
506
532
|
sets.push(fencedColumnSql("status", "$status", "$seq"));
|
|
@@ -543,7 +569,7 @@ export function applyAgentLifecycleUpdate(
|
|
|
543
569
|
}
|
|
544
570
|
if (patch.profileProjectionProvided) {
|
|
545
571
|
sets.push("profile_projection = $profileProjection");
|
|
546
|
-
params.$profileProjection =
|
|
572
|
+
params.$profileProjection = serializeProfileProjection(id, patch.profileProjection);
|
|
547
573
|
}
|
|
548
574
|
}
|
|
549
575
|
const runtime = update.runtime;
|
|
@@ -558,16 +584,10 @@ export function applyAgentLifecycleUpdate(
|
|
|
558
584
|
params.$qs = runtime?.quota ? JSON.stringify(runtime.quota) : null;
|
|
559
585
|
}
|
|
560
586
|
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
const terminalLaunch = terminalProviderLaunchId(update.meta?.terminalProviderExit ?? before.meta?.terminalProviderExit);
|
|
566
|
-
if (applied && nextStatus === "offline" && terminalLaunch) revokeVaultTokens(id, now, "provider_terminal_exit", before.instanceId, String(before.meta?.spawnRequestId ?? ""), terminalLaunch);
|
|
567
|
-
if (applied && contextState) recordContextSnapshot(id, contextState, now);
|
|
568
|
-
return applied;
|
|
569
|
-
});
|
|
570
|
-
|
|
587
|
+
const changed = getDb().query(`UPDATE agents SET ${sets.join(", ")} WHERE id = $id AND epoch = $epoch`).run(params as never).changes > 0;
|
|
588
|
+
const terminalLaunch = terminalProviderLaunchId(update.meta?.terminalProviderExit ?? before.terminalProviderExit);
|
|
589
|
+
if (changed && nextStatus === "offline" && terminalLaunch) revokeVaultTokens(id, now, "provider_terminal_exit", before.instanceId, before.spawnRequestId, terminalLaunch);
|
|
590
|
+
if (changed && contextState) recordContextSnapshot(id, contextState, now);
|
|
571
591
|
// NOTE (from setStatus): `offline` is a LIVENESS observation, not a confirmed death — it re-elects
|
|
572
592
|
// stewards and closes pairs but must NOT release a steward's workspace claim (#1789 part 2, F2).
|
|
573
593
|
// Gated on the requested status, not on a status CHANGE, matching setStatus's own condition.
|
|
@@ -575,7 +595,7 @@ export function applyAgentLifecycleUpdate(
|
|
|
575
595
|
closeOpenPairsForAgent(id, now);
|
|
576
596
|
electWorkspaceStewards();
|
|
577
597
|
}
|
|
578
|
-
return {
|
|
598
|
+
return { changed, metaWriteBytes, after: getPersistedAgentRuntimeCard(id) };
|
|
579
599
|
}
|
|
580
600
|
|
|
581
601
|
export function mergeAgentMeta(id: string, meta: Record<string, unknown>, guard?: AgentSessionGuard, now: number = Date.now()): boolean {
|
|
@@ -598,7 +618,7 @@ export function mergeAgentMeta(id: string, meta: Record<string, unknown>, guard?
|
|
|
598
618
|
warnIfAgentMetaOversized(id, metaJson, "stored meta");
|
|
599
619
|
const result = getDb()
|
|
600
620
|
.query("UPDATE agents SET meta = ?, profile_projection = ?, last_seen = ? WHERE id = ?")
|
|
601
|
-
.run(metaJson,
|
|
621
|
+
.run(metaJson, serializeProfileProjection(id, stored.profileProjection), now, id);
|
|
602
622
|
return result.changes > 0;
|
|
603
623
|
}
|
|
604
624
|
|
|
@@ -614,7 +634,7 @@ export function markAgentReadyNotified(id: string, at: number = Date.now()): boo
|
|
|
614
634
|
const merged = { ...(agent.meta ?? {}), readyNotifiedAt: at };
|
|
615
635
|
const stored = splitAgentMetaForStorage(merged);
|
|
616
636
|
return getDb().query("UPDATE agents SET meta = ?, profile_projection = ? WHERE id = ?")
|
|
617
|
-
.run(JSON.stringify(stored.meta),
|
|
637
|
+
.run(JSON.stringify(stored.meta), serializeProfileProjection(id, stored.profileProjection), id).changes > 0;
|
|
618
638
|
}
|
|
619
639
|
|
|
620
640
|
/** Delete specific keys from an agent's meta blob. Returns true if anything changed. Used to clear
|
|
@@ -633,7 +653,7 @@ export function clearAgentMetaKeys(id: string, keys: string[]): boolean {
|
|
|
633
653
|
if (!changed) return false;
|
|
634
654
|
const stored = splitAgentMetaForStorage(meta);
|
|
635
655
|
return getDb().query("UPDATE agents SET meta = ?, profile_projection = ? WHERE id = ?")
|
|
636
|
-
.run(JSON.stringify(stored.meta),
|
|
656
|
+
.run(JSON.stringify(stored.meta), serializeProfileProjection(id, stored.profileProjection), id).changes > 0;
|
|
637
657
|
}
|
|
638
658
|
|
|
639
659
|
/**
|
|
@@ -724,7 +744,7 @@ export function recordAgentExitDiagnosticsInternal(
|
|
|
724
744
|
.run({
|
|
725
745
|
$seq: lifecycleSeq,
|
|
726
746
|
$meta: JSON.stringify(stored.meta),
|
|
727
|
-
$profileProjection:
|
|
747
|
+
$profileProjection: serializeProfileProjection(id, stored.profileProjection),
|
|
728
748
|
$id: id,
|
|
729
749
|
} as never);
|
|
730
750
|
return result.changes > 0 ? agent.epoch : null;
|
|
@@ -828,21 +848,27 @@ export function heartbeat(
|
|
|
828
848
|
// withBufferedPresence / bufferedLiveAgentIds) live in the leaf module ./presence-buffer.ts so every
|
|
829
849
|
// liveness reader can fold in the buffer without an import cycle (agents.ts imports channels.ts).
|
|
830
850
|
|
|
851
|
+
/** Heartbeat: buffers the steady-state liveness advance (flushed by `flushPresence`), writes presence-critical
|
|
852
|
+
* transitions at once. False if the session guard rejects or the agent is gone. Sync twin for tests; the
|
|
853
|
+
* transports use `recordHeartbeatAsync`, which writes the bypass on the writer thread (#1870 S7). */
|
|
854
|
+
export function recordHeartbeat(id: string, opts: HeartbeatInput = {}): boolean {
|
|
855
|
+
const beat = bufferOrBypassHeartbeat(id, opts);
|
|
856
|
+
return typeof beat === "boolean" ? beat : applyAgentLifecycleUpdate(id, beat, opts.guard, opts.now ?? Date.now()).changed;
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
export interface HeartbeatInput {
|
|
860
|
+
guard?: AgentSessionGuard;
|
|
861
|
+
/** Semantic status reported by the beat (bus path); undefined for the runtime-less API path. */
|
|
862
|
+
status?: AgentCard["status"];
|
|
863
|
+
runtime?: { providerCapabilities?: ProviderCapabilities; context?: ContextState; quota?: QuotaState };
|
|
864
|
+
now?: number;
|
|
865
|
+
}
|
|
866
|
+
|
|
831
867
|
/**
|
|
832
|
-
*
|
|
833
|
-
*
|
|
834
|
-
* presence-critical transitions. Returns false if the session guard rejects or the agent is gone.
|
|
868
|
+
* The shared decision of `recordHeartbeat` and `recordHeartbeatAsync`: buffer a steady-state beat (returns
|
|
869
|
+
* the result) or hand back the lifecycle delta a presence-critical beat must write now.
|
|
835
870
|
*/
|
|
836
|
-
export function
|
|
837
|
-
id: string,
|
|
838
|
-
opts: {
|
|
839
|
-
guard?: AgentSessionGuard;
|
|
840
|
-
/** Semantic status reported by the beat (bus path); undefined for the runtime-less API path. */
|
|
841
|
-
status?: AgentCard["status"];
|
|
842
|
-
runtime?: { providerCapabilities?: ProviderCapabilities; context?: ContextState; quota?: QuotaState };
|
|
843
|
-
now?: number;
|
|
844
|
-
} = {},
|
|
845
|
-
): boolean {
|
|
871
|
+
export function bufferOrBypassHeartbeat(id: string, opts: HeartbeatInput): boolean | AgentLifecycleUpdate {
|
|
846
872
|
if (!validateAgentSession(id, opts.guard).ok) return false;
|
|
847
873
|
const current = getAgent(id);
|
|
848
874
|
if (!current) return false;
|
|
@@ -861,9 +887,9 @@ export function recordHeartbeat(
|
|
|
861
887
|
opts.runtime.context.lifecycleState !== current.context?.lifecycleState;
|
|
862
888
|
const prev = pendingPresence.get(id);
|
|
863
889
|
if (resurrection || statusChanged || lifecycleTransition) {
|
|
864
|
-
// Merge any buffered-but-unflushed runtime cols into this
|
|
865
|
-
//
|
|
866
|
-
//
|
|
890
|
+
// Merge any buffered-but-unflushed runtime cols into this write so the bypass never DISCARDS a
|
|
891
|
+
// coalesced advance (a beat that carried context but was buffered, then a status change arrives
|
|
892
|
+
// carrying none). Per column: this beat wins, else the pending value.
|
|
867
893
|
const runtime = prev
|
|
868
894
|
? {
|
|
869
895
|
providerCapabilities: opts.runtime?.providerCapabilities ?? prev.providerCapabilities,
|
|
@@ -871,16 +897,10 @@ export function recordHeartbeat(
|
|
|
871
897
|
quota: opts.runtime?.quota ?? prev.quota,
|
|
872
898
|
}
|
|
873
899
|
: opts.runtime;
|
|
874
|
-
pendingPresence.delete(id); // this
|
|
875
|
-
// #2111 —
|
|
876
|
-
//
|
|
877
|
-
|
|
878
|
-
return applyAgentLifecycleUpdate(
|
|
879
|
-
id,
|
|
880
|
-
{ status: statusChanged ? opts.status : undefined, resurrectOnBeat: true, runtime },
|
|
881
|
-
opts.guard,
|
|
882
|
-
now,
|
|
883
|
-
).changed;
|
|
900
|
+
pendingPresence.delete(id); // this write supersedes any buffered advance
|
|
901
|
+
// #2111 — one consolidated update carries both the beat and the explicit status, which overrides
|
|
902
|
+
// the resurrection CASE.
|
|
903
|
+
return { status: statusChanged ? opts.status : undefined, resurrectOnBeat: true, runtime };
|
|
884
904
|
}
|
|
885
905
|
|
|
886
906
|
// Steady state: buffer. Merge context advisory markers now (matches heartbeat()'s per-beat merge),
|
|
@@ -1192,6 +1212,10 @@ export function deleteAgent(id: string): { ok: boolean; error?: string } {
|
|
|
1192
1212
|
return deleted ? { ok: true } : { ok: false, error: "agent not found" };
|
|
1193
1213
|
}
|
|
1194
1214
|
|
|
1215
|
+
export type OrphanedTokenRevocation = { agentId: string; jtis: string[] };
|
|
1216
|
+
/** One page of the orphan sweep: agents after `afterId` in id order, up to `limit` (#3776: one short write each). */
|
|
1217
|
+
export type OrphanedTokenPage = { revoked: OrphanedTokenRevocation[]; nextAfterId: string | null };
|
|
1218
|
+
|
|
1195
1219
|
// #1057(1) — close the orphan-token window #1051 left open. A dead runner with no replacement
|
|
1196
1220
|
// used to keep its token valid until the 24h offline prune (~720× the pre-#1051 ~2min horizon).
|
|
1197
1221
|
// This sweep revokes ("stale", re-mintable — #484) the runtime tokens of agents whose process the
|
|
@@ -1204,12 +1228,18 @@ export function deleteAgent(id: string): { ok: boolean; error?: string } {
|
|
|
1204
1228
|
// `lagGraceMs` mirrors the stale reaper's #1048/#1055 discipline: while the relay's own event
|
|
1205
1229
|
// loop was stalled, a live claimant's heartbeats may not have been processed yet, so the window
|
|
1206
1230
|
// widens by the observed lag rather than misreading the backlog as post-mortem silence.
|
|
1207
|
-
export function revokeOrphanedRuntimeTokens(
|
|
1231
|
+
export function revokeOrphanedRuntimeTokens(
|
|
1232
|
+
graceMs: number = STALE_TTL_MS,
|
|
1233
|
+
lagGraceMs = 0,
|
|
1234
|
+
now = Date.now(),
|
|
1235
|
+
page: { afterId?: string; limit?: number } = {},
|
|
1236
|
+
): OrphanedTokenPage {
|
|
1208
1237
|
const cutoff = now - graceMs - Math.max(0, lagGraceMs);
|
|
1238
|
+
const limit = page.limit ?? -1;
|
|
1209
1239
|
const rows = getDb()
|
|
1210
|
-
.query(`SELECT id, meta, last_seen FROM agents WHERE status = 'offline' AND meta LIKE '%lastExitReceivedAt%' AND NOT ${reservedAgentIdSql()}
|
|
1211
|
-
.all() as Array<{ id: string; meta: string | null; last_seen: number }>;
|
|
1212
|
-
const revoked:
|
|
1240
|
+
.query(`SELECT id, meta, last_seen FROM agents WHERE status = 'offline' AND meta LIKE '%lastExitReceivedAt%' AND NOT ${reservedAgentIdSql()} AND id > ? ORDER BY id LIMIT ?`)
|
|
1241
|
+
.all(page.afterId ?? "", limit) as Array<{ id: string; meta: string | null; last_seen: number }>;
|
|
1242
|
+
const revoked: OrphanedTokenRevocation[] = [];
|
|
1213
1243
|
for (const row of rows) {
|
|
1214
1244
|
const meta = parseJson<Record<string, unknown>>(row.meta ?? "{}", {});
|
|
1215
1245
|
const receivedAt = typeof meta.lastExitReceivedAt === "number" ? meta.lastExitReceivedAt : undefined;
|
|
@@ -1218,7 +1248,7 @@ export function revokeOrphanedRuntimeTokens(graceMs: number = STALE_TTL_MS, lagG
|
|
|
1218
1248
|
const jtis = revokeProviderRuntimeTokensByJti(runtimeTokenJtisFromMeta(meta), "stale", now);
|
|
1219
1249
|
if (jtis.length > 0) revoked.push({ agentId: row.id, jtis });
|
|
1220
1250
|
}
|
|
1221
|
-
return revoked;
|
|
1251
|
+
return { revoked, nextAfterId: limit > 0 && rows.length === limit ? rows[rows.length - 1]!.id : null };
|
|
1222
1252
|
}
|
|
1223
1253
|
|
|
1224
1254
|
// #484: `reason` is stamped on each revocation so a stale-on-restart revocation
|
|
@@ -93,9 +93,9 @@ export function createAuthIdentity(input: {
|
|
|
93
93
|
providerSubject: string;
|
|
94
94
|
secretHash?: string | null;
|
|
95
95
|
metadata?: Record<string, unknown>;
|
|
96
|
-
}): AuthIdentity {
|
|
96
|
+
}, submittedAt: number = Date.now()): AuthIdentity {
|
|
97
97
|
const id = randomUUID();
|
|
98
|
-
const now =
|
|
98
|
+
const now = submittedAt;
|
|
99
99
|
getDb()
|
|
100
100
|
.query(
|
|
101
101
|
`INSERT INTO auth_identities (id, user_id, provider, provider_subject, secret_hash, metadata, created_at)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// #3799 — automation scans (run listing, reconcile/precheck/dispatch ticks) on the reader pool.
|
|
2
|
+
// A cold scan of automation_runs once blocked the hub loop for seconds on swap-bound I/O.
|
|
3
|
+
import { listAutomationRuns, listDispatchableQueuedRuns, listDueAutomations, listPendingPrecheckRuns, listReconcilableRuns } from "../automations/storage.ts";
|
|
4
|
+
|
|
5
|
+
export const AUTOMATION_READ_OPS = {
|
|
6
|
+
"automations.listRuns": (args: { automationId?: string; status?: string; limit?: number }) => listAutomationRuns(args),
|
|
7
|
+
"automations.pendingPrecheckRuns": () => listPendingPrecheckRuns(),
|
|
8
|
+
"automations.reconcilableRuns": () => listReconcilableRuns(),
|
|
9
|
+
"automations.dispatchableQueuedRuns": () => listDispatchableQueuedRuns(),
|
|
10
|
+
"automations.dueAutomations": (args: { now: number }) => listDueAutomations(args.now),
|
|
11
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { ValidationError } from "@humwick/sdk";
|
|
2
|
+
import { insertAutomation, updateAutomationNormalized, deleteAutomation } from "../automations/persistence";
|
|
3
|
+
import { nextScheduledAt } from "../automations/cron";
|
|
4
|
+
import { getAutomation, getAutomationRun, hasActiveRun, insertRun, enqueueAutomationRun, updateRun, cancelActiveRuns, rescheduleAutomation } from "../automations/storage";
|
|
5
|
+
import type { Automation } from "../types";
|
|
6
|
+
import type { WriterOpSpec } from "./write-ops";
|
|
7
|
+
|
|
8
|
+
function admitRun(input: { automationId: string; now: number; manual?: boolean; queuedRunId?: string }) {
|
|
9
|
+
const automation = getAutomation(input.automationId);
|
|
10
|
+
if (!automation) return null;
|
|
11
|
+
const active = hasActiveRun(automation.id);
|
|
12
|
+
if (input.queuedRunId) {
|
|
13
|
+
const run = getAutomationRun(input.queuedRunId);
|
|
14
|
+
if (!run || run.automationId !== automation.id || run.status !== "scheduled" || active) return null;
|
|
15
|
+
updateRun(run.id, { status: "dispatching" }, input.now);
|
|
16
|
+
return { automation, run: getAutomationRun(run.id)! };
|
|
17
|
+
}
|
|
18
|
+
if (input.manual) {
|
|
19
|
+
if (active) throw new ValidationError("automation already has an active run");
|
|
20
|
+
} else {
|
|
21
|
+
if (!automation.enabled || automation.nextRunAt === undefined || automation.nextRunAt > input.now) return null;
|
|
22
|
+
if (active && automation.concurrencyPolicy === "replace") cancelActiveRuns(automation.id, input.now, "Replaced by newer scheduled run");
|
|
23
|
+
else if (active && automation.concurrencyPolicy === "queue") enqueueAutomationRun(automation, automation.nextRunAt, input.now);
|
|
24
|
+
const next = automation.enabled ? nextScheduledAt(automation.schedule, automation.timezone, input.now) : undefined;
|
|
25
|
+
rescheduleAutomation(automation, next, input.now);
|
|
26
|
+
if (active && automation.concurrencyPolicy !== "replace") return null;
|
|
27
|
+
}
|
|
28
|
+
const run = insertRun(automation, input.manual ? input.now : automation.nextRunAt ?? input.now, input.now);
|
|
29
|
+
return { automation: getAutomation(automation.id)!, run };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const AUTOMATION_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Object.freeze({
|
|
33
|
+
"automations.create": { offLoop: true, idempotent: false, fn: (a: { normalized: Parameters<typeof insertAutomation>[0]; now: number }) => insertAutomation(a.normalized, a.now) },
|
|
34
|
+
"automations.update": { offLoop: true, idempotent: false, fn: (a: { id: string; normalized: Parameters<typeof updateAutomationNormalized>[1]; expected: Automation; now: number }) => {
|
|
35
|
+
const current = getAutomation(a.id);
|
|
36
|
+
if (!current || JSON.stringify(current) !== JSON.stringify(a.expected)) throw new ValidationError("automation changed or was deleted during catalog validation");
|
|
37
|
+
return updateAutomationNormalized(a.id, a.normalized, a.now);
|
|
38
|
+
} },
|
|
39
|
+
"automations.delete": { offLoop: true, idempotent: true, fn: (a: { id: string }) => deleteAutomation(a.id) },
|
|
40
|
+
"automations.admitRun": { offLoop: true, idempotent: false, fn: admitRun },
|
|
41
|
+
"automations.insertRun": { offLoop: true, idempotent: false, fn: (a: Parameters<typeof insertRun>) => insertRun(...a) },
|
|
42
|
+
"automations.enqueueRun": { offLoop: true, idempotent: false, fn: (a: Parameters<typeof enqueueAutomationRun>) => enqueueAutomationRun(...a) },
|
|
43
|
+
"automations.updateRun": { offLoop: true, idempotent: false, fn: (a: Parameters<typeof updateRun>) => updateRun(...a) ?? null },
|
|
44
|
+
"automations.cancelRuns": { offLoop: true, idempotent: false, fn: (a: Parameters<typeof cancelActiveRuns>) => cancelActiveRuns(...a) ?? null },
|
|
45
|
+
"automations.reschedule": { offLoop: true, idempotent: false, fn: (a: Parameters<typeof rescheduleAutomation>) => rescheduleAutomation(...a) ?? null },
|
|
46
|
+
});
|
package/src/db/blackboard.ts
CHANGED
|
@@ -161,11 +161,11 @@ export function searchEntries(
|
|
|
161
161
|
return rows.map(rowToEntry);
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
export function retractEntry(id: string): BlackboardEntry | null {
|
|
164
|
+
export function retractEntry(id: string, submittedAt: number = Date.now()): BlackboardEntry | null {
|
|
165
165
|
const existing = getEntry(id);
|
|
166
166
|
if (!existing) return null;
|
|
167
167
|
assertStatus("retracted");
|
|
168
168
|
getDb().query("UPDATE blackboard_entries SET status = 'retracted', updated_at = ? WHERE id = ?")
|
|
169
|
-
.run(
|
|
169
|
+
.run(submittedAt, id);
|
|
170
170
|
return getEntry(id);
|
|
171
171
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { getAgent } from "./agents";
|
|
2
|
+
import { createCommandInternal } from "../commands-db";
|
|
3
|
+
import { countActiveBrowserSessions, getBrowserSessionRow, insertBrowserSession, transitionBrowserSession } from "./browser-sessions";
|
|
4
|
+
import { getOrchestrator } from "./orchestrators";
|
|
5
|
+
import type { BrowserLimits } from "@humwick/sdk";
|
|
6
|
+
|
|
7
|
+
export interface StartBrowserWrite {
|
|
8
|
+
id: string; commandId: string; agentId: string; instanceId?: string; epoch?: number;
|
|
9
|
+
orchestratorId: string; limits: BrowserLimits;
|
|
10
|
+
}
|
|
11
|
+
export function startBrowserBody(input: StartBrowserWrite, now: number) {
|
|
12
|
+
const agent = getAgent(input.agentId);
|
|
13
|
+
if (!agent || agent.status === "offline" || agent.instanceId !== input.instanceId || agent.epoch !== input.epoch) return { conflict: "agent" as const };
|
|
14
|
+
const host = getOrchestrator(input.orchestratorId);
|
|
15
|
+
if (!host || host.status !== "online") return { conflict: "host" as const };
|
|
16
|
+
if (countActiveBrowserSessions({ agentId: input.agentId }) >= input.limits.perAgent) return { conflict: "agentLimit" as const };
|
|
17
|
+
if (countActiveBrowserSessions({ orchestratorId: host.id }) >= input.limits.perHost) return { conflict: "hostLimit" as const };
|
|
18
|
+
const command = createCommandInternal({ id: input.commandId, input: { type: "browser.start", source: input.agentId, target: host.agentId, correlationId: input.id,
|
|
19
|
+
params: { sessionId: input.id, agentId: input.agentId, orchestratorId: host.id, idleTimeoutMs: input.limits.idleTimeoutMinutes * 60_000, hostSessionLimit: input.limits.perHost } } }, now);
|
|
20
|
+
const row = insertBrowserSession({ id: input.id, agentId: input.agentId, orchestratorId: host.id, startCommandId: command.id, now });
|
|
21
|
+
return { row, command };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function stopBrowserBody(input: { id: string; reason: string; commandId: string }, now: number) {
|
|
25
|
+
const row = getBrowserSessionRow(input.id);
|
|
26
|
+
if (!row || (row.status !== "starting" && row.status !== "running")) return { row };
|
|
27
|
+
const host = getOrchestrator(row.orchestratorId);
|
|
28
|
+
if (!host) return { row: transitionBrowserSession(row.id, ["starting", "running"], { status: "stopped", stoppedAt: now, error: "orchestrator no longer registered" }, now) };
|
|
29
|
+
const command = createCommandInternal({ id: input.commandId, input: { type: "browser.stop", source: "system", target: host.agentId, correlationId: row.id,
|
|
30
|
+
params: { sessionId: row.id, agentId: row.agentId, orchestratorId: host.id, reason: input.reason } } }, now);
|
|
31
|
+
return { row: transitionBrowserSession(row.id, ["starting", "running"], { status: "stopping", stopCommandId: command.id }, now), command };
|
|
32
|
+
}
|
|
@@ -31,8 +31,10 @@ export const BUS_OUTBOX_WRITE_OPS: Readonly<Record<string, WriterOpSpec>> = Obje
|
|
|
31
31
|
"bus.append": {
|
|
32
32
|
offLoop: true,
|
|
33
33
|
// Appending assigns a new sequence row; retries reconcile by idempotency key rather than
|
|
34
|
-
// inserting a second durable event after a phantom acknowledgement.
|
|
34
|
+
// inserting a second durable event after a phantom acknowledgement. A plain emit never retries,
|
|
35
|
+
// so it goes keyless and writes no ledger row (#3614).
|
|
35
36
|
idempotent: false,
|
|
37
|
+
atMostOnce: true,
|
|
36
38
|
fn: (args: BusAppendOpArgs, ctx: WriterOpContext) => ({
|
|
37
39
|
...appendRelayEventInternal(args.type, args.source, args.data, args.subject, ctx.now)!, replayed: false,
|
|
38
40
|
}),
|