@humwick/server 0.130.2 → 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/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-coordination.md +1 -0
- package/docs/guides/workflows.md +16 -0
- package/docs/openapi.json +73 -4
- package/package.json +8 -7
- package/public/assets/{MessageBubble-BWLqMGKG.js → MessageBubble-Bq9kr21N.js} +2 -2
- package/public/assets/{PlanGraphPanel-3TlIQpjk.js → PlanGraphPanel-Dqiroy06.js} +2 -2
- package/public/assets/{TraceView-Wimm0Czv.js → TraceView-DYU962-H.js} +2 -2
- package/public/assets/{VaultDecisionCard-Bau_vNax.js → VaultDecisionCard-DhPfzioE.js} +2 -2
- package/public/assets/{activity-CrSurn-r.js → activity-DzCcQTee.js} +2 -2
- package/public/assets/{agent-lineage-CknAJKcb.js → agent-lineage-SgDt9i3T.js} +2 -2
- package/public/assets/agent-liveness-Bq-s73jW.js +2 -0
- package/public/assets/{agent-name-DKbiIhBo.js → agent-name-CcY3Aijy.js} +2 -2
- package/public/assets/{agent-profiles-DwF6EQ4R.js → agent-profiles-cxtRBn6O.js} +2 -2
- package/public/assets/{agent-project-badge-Diz4Sjjb.js → agent-project-badge-DGYbIhaI.js} +2 -2
- package/public/assets/{agent-tools-CRhpRQza.js → agent-tools-DHbftV0N.js} +2 -2
- package/public/assets/{agent-type-icon-LrUEU3lB.js → agent-type-icon-CY113sp-.js} +2 -2
- package/public/assets/{agents-B-v66C-4.js → agents-BPzY7IlQ.js} +2 -2
- package/public/assets/{analytics-BqCb-LKi.js → analytics-DENFPv_a.js} +2 -2
- package/public/assets/{artifact-viewer-kf4pGuAR.js → artifact-viewer-KRvSc7sl.js} +2 -2
- package/public/assets/{artifacts-DJevXcvg.js → artifacts-C9gSmL3s.js} +2 -2
- package/public/assets/{artifacts-D32zyw4Y.js → artifacts-DT-HkI5O.js} +2 -2
- package/public/assets/{automation-BpRajx_5.js → automation-BsmjQhKD.js} +2 -2
- package/public/assets/{backlog-D_UjTdzX.js → backlog-8NYH_62t.js} +2 -2
- package/public/assets/{busy-health-N3VEh4ao.js → busy-health-D3hwvYb4.js} +2 -2
- package/public/assets/{channels-9jopungq.js → channels-DCJ5WL7O.js} +2 -2
- package/public/assets/{chat-CSXrTB3C.js → chat-DAIl357U.js} +3 -3
- package/public/assets/{code-preview-p1NnmqK0.js → code-preview-CzrZfr9U.js} +2 -2
- package/public/assets/{connectors-CZdqlDNL.js → connectors-xTxtlyou.js} +2 -2
- package/public/assets/{cosmos-BgdsE4dG.js → cosmos-BpebFLK2.js} +2 -2
- package/public/assets/{crate-agent-30aXTKva.js → crate-agent-BHvI5wXC.js} +2 -2
- package/public/assets/{dependency-graph-B_jvw2GE.js → dependency-graph-DGT0o3wJ.js} +2 -2
- package/public/assets/{deploys-DoN6bAb5.js → deploys-hqWOHSHE.js} +2 -2
- package/public/assets/{display-BrKWFGJz.js → display-CDeH4I8T.js} +2 -2
- package/public/assets/{files-D6XEu8Ng.js → files-BTeGVmTg.js} +2 -2
- package/public/assets/{fleet-C7jQWbw2.js → fleet-DgXtNgCa.js} +2 -2
- package/public/assets/{fleet-metrics-BiDs3MLx.js → fleet-metrics-BHEt5yc_.js} +2 -2
- package/public/assets/{formatted-body-CQBwc1fb.js → formatted-body-MLtodyPp.js} +3 -3
- package/public/assets/{formatted-body-impl-DyG0WsQS.js → formatted-body-impl-CAe664Z8.js} +2 -2
- package/public/assets/{host-providers-dialog-DKaW31dN.js → host-providers-dialog-mapF4Fj9.js} +2 -2
- package/public/assets/{index-CRHep3M9.js → index-CqqgOI5R.js} +5 -5
- package/public/assets/{insights-CzrtkpOE.js → insights-DNyf7IzF.js} +2 -2
- package/public/assets/{integrations-aVsUmigt.js → integrations-DlYOHq7T.js} +2 -2
- package/public/assets/{issue-ref-chip-BnSlM_95.js → issue-ref-chip-CeWBNWn7.js} +2 -2
- package/public/assets/{log-viewer-qe7Ee47Z.js → log-viewer-Cib8nqdE.js} +2 -2
- package/public/assets/{maintenance-NfjqFZAk.js → maintenance-DSn1cPm7.js} +2 -2
- package/public/assets/{managed-agents-BiH0HgaE.js → managed-agents-C3CkM81m.js} +2 -2
- package/public/assets/{markdown-preview-BixaT3Xr.js → markdown-preview-W4VQQPAv.js} +3 -3
- package/public/assets/{markdown-preview-impl-DNGlWIS3.js → markdown-preview-impl-CMsTdhjq.js} +2 -2
- package/public/assets/{memory-DNsCl6UX.js → memory-BV17qtO4.js} +2 -2
- package/public/assets/{messages-DopU1L1X.js → messages-Bm_1AqSA.js} +2 -2
- package/public/assets/{orchestrators-Cq7ckLQT.js → orchestrators-Dg-vfP09.js} +2 -2
- package/public/assets/{overview-C1DCTzzV.js → overview-DcYCrvlr.js} +2 -2
- package/public/assets/{pairs-DE_m6rrE.js → pairs-8o9nuG3V.js} +2 -2
- package/public/assets/{profile-icon-B3rfh77F.js → profile-icon-BsRyBMea.js} +2 -2
- package/public/assets/{project-profile-instructions-DQWZE0kA.js → project-profile-instructions-DETKFn_E.js} +2 -2
- package/public/assets/{projects-Br2Bd2h1.js → projects-M_m6AHws.js} +2 -2
- package/public/assets/{prompt-settings-BKvFsvGD.js → prompt-settings-C_mNCgeL.js} +2 -2
- package/public/assets/provider-display-BEeLXC_D.js +2 -0
- package/public/assets/{registry-Cw38_6gW.js → registry-DDHHHE5N.js} +2 -2
- package/public/assets/run-card-Dt4I4jaP.js +2 -0
- package/public/assets/{secrets-DxI-vzSq.js → secrets-BkVwxI5O.js} +2 -2
- package/public/assets/{service-access-settings-D9s_VJbd.js → service-access-settings-Crq-6a-B.js} +2 -2
- package/public/assets/{settings-CKZTVGIx.js → settings-CYcavMFu.js} +2 -2
- package/public/assets/shipping-H6gzEeZB.js +2 -0
- package/public/assets/{stats-DyUBKyWI.js → stats-BJVeWkpV.js} +2 -2
- package/public/assets/{status-dot-DYqlEUhJ.js → status-dot-BcHyw1Vw.js} +2 -2
- package/public/assets/store-DKPDIZBe.js +9 -0
- package/public/assets/{tasks-Bh7Chr4-.js → tasks-qJjlQPpx.js} +2 -2
- package/public/assets/{teams-bowI7qVY.js → teams-Cd5Sk1uX.js} +2 -2
- package/public/assets/{terminal-viewer-BgVLHdsU.js → terminal-viewer-CpY5_m7W.js} +3 -3
- package/public/assets/{terminal-viewer-impl-Dz22UPy6.js → terminal-viewer-impl-DI_2llFR.js} +2 -2
- package/public/assets/{use-agent-terminal-DSQQ-iY7.js → use-agent-terminal-0yJA_buM.js} +2 -2
- package/public/assets/{use-decisions-samMQhQf.js → use-decisions-uJXHf34W.js} +2 -2
- package/public/assets/{use-project-list-59LheVP7.js → use-project-list-CpWl6eHQ.js} +2 -2
- package/public/assets/{use-selectors-BZa25xEB.js → use-selectors-BdxBW8mL.js} +2 -2
- package/public/assets/{user-avatar-DHxlvUvV.js → user-avatar-3IndfpOc.js} +2 -2
- package/public/assets/{versioned-prompt-editor-BmED5DnJ.js → versioned-prompt-editor-CIVg7XB1.js} +2 -2
- package/public/assets/{work-queue-CSvpuNLz.js → work-queue-B9rnLwHZ.js} +2 -2
- package/public/assets/{workflow-marker-DAZcj5qt.js → workflow-marker-X8wxyhzC.js} +2 -2
- package/public/assets/{workflows-DdmxRSyg.js → workflows-o5YyMFW7.js} +2 -2
- package/public/assets/{workspaces-BxeKfVuF.js → workspaces-CzEGoAng.js} +2 -2
- package/public/cosmos.html +4 -4
- package/public/index.html +28 -28
- package/runner/plugins/claude/.claude-plugin/plugin.json +1 -1
- 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/provider-quota-harvest.ts +20 -71
- package/runner/src/agent-runner/lifecycle-milestones.ts +2 -2
- package/runner/src/agent-runner/liveness-exchange.ts +104 -0
- package/runner/src/claude-system-prompt.ts +49 -0
- 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 +2 -1
- package/runner/src/runner-core.ts +14 -15
- package/runner/src/runner-helpers.ts +0 -8
- package/runner/src/session-scratch.ts +6 -2
- package/runner/test-support/provisioning-context.ts +4 -2
- package/runner/test-support/runner-harness.ts +2 -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 +3 -3
- package/src/branch-landed.ts +25 -23
- package/src/bus.ts +21 -19
- package/src/cd-deploy-notify.ts +2 -2
- package/src/ci/notifications.ts +4 -4
- package/src/ci/root-missing.ts +3 -3
- package/src/ci/transition-notify.ts +5 -5
- package/src/claude-app/oauth-http.ts +3 -3
- package/src/cli/workflow.ts +12 -3
- package/src/commands-db.ts +4 -4
- package/src/commands-write.ts +8 -0
- package/src/compaction-watch.ts +10 -8
- package/src/config-store-write.ts +2 -2
- package/src/config.ts +4 -11
- package/src/connectors.ts +10 -8
- package/src/context-advisory.ts +22 -21
- 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/agents-async.ts +8 -5
- package/src/db/agents.ts +15 -12
- 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/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/commands-planner-stats.test-fixture.ts +8 -0
- package/src/db/commands-read-ops.ts +16 -0
- package/src/db/connection.ts +1 -182
- package/src/db/context-carry-write.ts +74 -0
- package/src/db/continuations.ts +4 -4
- package/src/db/db-error-registry.ts +12 -0
- package/src/db/gateway.ts +26 -133
- package/src/db/history-retention-ops.ts +13 -0
- package/src/db/inbox-async.ts +2 -2
- package/src/db/inbox-read-ops.ts +1 -1
- package/src/db/inbox.ts +9 -3
- package/src/db/issue-associations.ts +2 -2
- package/src/db/issue-refs-async.ts +4 -1
- package/src/db/issue-refs-read-ops.ts +6 -0
- package/src/db/issue-refs.ts +8 -8
- 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/main-connection-mode.ts +11 -0
- package/src/db/main-connection-writes.ts +20 -2
- package/src/db/maintenance-job-runs-async.ts +2 -2
- package/src/db/maintenance-job-write-ops.ts +1 -1
- package/src/db/maintenance-pauses.ts +2 -2
- package/src/db/message-send.ts +4 -0
- package/src/db/messages.ts +31 -25
- package/src/db/migrations.ts +18 -1
- package/src/db/notification-write-ops.ts +19 -0
- package/src/db/operator-answer-write.ts +19 -0
- package/src/db/orchestrators.ts +10 -4
- package/src/db/pairs-async.ts +22 -1
- package/src/db/pairs-write-ops.ts +8 -3
- package/src/db/pairs.ts +41 -48
- 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-trust-approvals.ts +2 -2
- package/src/db/prompt-templates.ts +4 -4
- package/src/db/read-op-marshaling-fixtures.ts +18 -0
- package/src/db/read-ops.ts +4 -0
- package/src/db/retention.ts +13 -2
- package/src/db/review-publish-write.ts +8 -0
- 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 +4 -1
- package/src/db/spawn-budget.ts +5 -0
- package/src/db/spawn-delegation.ts +1 -11
- package/src/db/sql-audit-indexes.ts +3 -0
- package/src/db/stats-async.ts +5 -3
- package/src/db/task-entity.ts +5 -4
- 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/token-db-write-ops.ts +2 -0
- package/src/db/token-standing-async.ts +12 -0
- package/src/db/token-standing.ts +6 -9
- 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/workspaces.ts +8 -5
- package/src/db/write-ops.ts +31 -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 +42 -46
- package/src/dev.ts +8 -3
- 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-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 +104 -98
- package/src/maintenance/breaker.ts +18 -16
- package/src/maintenance/checkout-refresh.ts +18 -1
- package/src/maintenance/critical-job-watchdog.ts +3 -3
- package/src/maintenance/events.ts +3 -3
- package/src/maintenance/history-retention-job.ts +30 -0
- package/src/maintenance/jobs.ts +29 -67
- 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 +18 -13
- package/src/maintenance/stalled-delivery-pager.ts +4 -4
- package/src/maintenance/teams.ts +19 -30
- package/src/maintenance/workspaces.ts +17 -27
- package/src/managed-policy-escalation.ts +7 -7
- package/src/managed-policy.ts +3 -3
- package/src/managed-provider-gate.ts +5 -4
- package/src/managed-spawn-reservation.ts +5 -4
- package/src/mcp/index.ts +8 -8
- package/src/mcp/output-descriptions.ts +1 -1
- package/src/mcp/presentation.ts +2 -1
- 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 +3 -2
- package/src/mcp/tool-roles.ts +81 -0
- package/src/mcp/tools-workspace.ts +1 -1
- 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 +3 -3
- 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 +1 -1
- package/src/mcp-project-journal-tools.ts +4 -12
- package/src/mcp-project-tools.ts +17 -18
- package/src/mcp-routing-policy-tools.ts +3 -2
- package/src/mcp-team-tools.ts +6 -6
- package/src/mcp-workflow-tools.ts +5 -3
- 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/notify.ts +5 -5
- package/src/observed-reset-refresh.ts +4 -4
- package/src/operator-alarm.ts +2 -5
- package/src/project-ingest.ts +6 -6
- package/src/project-instructions.ts +8 -1
- package/src/project-trust.ts +12 -11
- package/src/prompt-resolver.ts +3 -3
- package/src/provider-quota-async.ts +5 -7
- package/src/provider-timeline-event.ts +4 -7
- package/src/quota-band-delivery.ts +2 -2
- package/src/recipe-runner.ts +4 -3
- 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-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 +1 -1
- package/src/routes/agents.ts +17 -119
- 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 +1 -1
- package/src/routes/commands.ts +29 -27
- package/src/routes/context-resets.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 +2 -1
- package/src/routes/integrations.ts +9 -7
- package/src/routes/issue-activity.ts +2 -2
- package/src/routes/issue-associations.ts +4 -4
- package/src/routes/issue-refs.ts +3 -3
- 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 +1 -1
- package/src/routes/orchestrator-host-registration.ts +2 -0
- package/src/routes/orchestrator-host-utilization.ts +2 -2
- package/src/routes/orchestrator-proxy.ts +2 -2
- package/src/routes/orchestrator.ts +27 -18
- package/src/routes/pairs.ts +8 -8
- package/src/routes/project-profile-instructions.ts +1 -1
- package/src/routes/project-trust.ts +1 -1
- package/src/routes/projects.ts +16 -16
- package/src/routes/prompt-templates.ts +12 -12
- 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 +1 -1
- 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/team-templates.ts +7 -7
- package/src/routes/teams.ts +10 -10
- package/src/routes/tokens.ts +18 -17
- 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 +2 -2
- package/src/routes/workspaces.ts +17 -16
- package/src/routing-policy-push.ts +6 -6
- package/src/runtime-grant.ts +17 -11
- package/src/runtime-tokens.ts +20 -28
- package/src/secrets-broker/config.ts +1 -1
- package/src/secrets-broker/service.ts +2 -2
- package/src/security.ts +3 -1
- 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 +1 -1
- package/src/server.ts +21 -22
- 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 +9 -9
- package/src/services/idle-agent-digest.ts +17 -12
- package/src/services/idle-epics.ts +4 -4
- 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 +14 -13
- package/src/services/issue-refs.ts +4 -5
- package/src/services/kernel-timers-cutover-chaos-worker.ts +1 -1
- package/src/services/kernel-timers-ingress-chaos-worker.ts +6 -1
- package/src/services/kernel-timers-ingress.ts +3 -3
- 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 +6 -5
- 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 +3 -3
- 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 +1 -1
- 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 +8 -3
- package/src/services/profile-trust.ts +2 -2
- 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/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 +17 -16
- 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-effort-grant.ts +5 -25
- package/src/services/send-message.ts +16 -33
- package/src/services/shutdown-agent.ts +17 -14
- package/src/services/spawn-agent.ts +12 -41
- package/src/services/spawn-chain-inspector.ts +1 -1
- 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-registration-watchdog.ts +2 -2
- package/src/services/spawn-repo-probe.ts +7 -5
- package/src/services/spawn-tree-cleanup.ts +7 -8
- 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-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 +3 -4
- package/src/services/task-validation.ts +2 -2
- package/src/services/team-templates.ts +5 -5
- 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 +22 -19
- 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 +2 -1
- package/src/services/workflow-caller.ts +61 -4
- package/src/services/workflow-child-proof-worker.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 +1 -1
- package/src/services/workflow-effect-driver.ts +42 -19
- package/src/services/workflow-effects.ts +41 -27
- package/src/services/workflow-pins.ts +7 -4
- package/src/services/workflow-reconcile.ts +1 -0
- 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 +4 -3
- package/src/services/workflow-run.test-fixture.ts +1 -1
- package/src/services/workflow-runs.ts +34 -22
- package/src/services/workflow-supervisor-state.ts +21 -1
- package/src/services/workflow-supervisor.ts +4 -3
- package/src/services/workspace-recovery.ts +4 -3
- package/src/spawn-admission.ts +10 -2
- package/src/spawn-placement.ts +27 -9
- package/src/spawn-targets.ts +8 -8
- package/src/sse-agent-status.ts +15 -6
- package/src/sse.ts +49 -24
- package/src/startup-context-injection.ts +61 -57
- package/src/steward-handoff.ts +4 -3
- package/src/steward-policy-cleanup.ts +9 -8
- package/src/steward.ts +2 -2
- package/src/task-dispatch-live.ts +5 -2
- package/src/task-dispatcher.ts +2 -2
- 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 +24 -16
- 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 +2 -2
- package/public/assets/agent-liveness-CaNwK0Zf.js +0 -2
- package/public/assets/provider-display-DsuWMvVL.js +0 -2
- package/public/assets/run-card-CpKqRbhg.js +0 -2
- package/public/assets/shipping-B9YtnwtG.js +0 -2
- package/public/assets/store-DcClXLH0.js +0 -9
- package/runner/src/agent-runner/http-liveness.ts +0 -85
- package/src/db/on-loop-write-transaction.ts +0 -34
package/src/events.ts
CHANGED
|
@@ -19,7 +19,7 @@ export interface RelayEvent {
|
|
|
19
19
|
|
|
20
20
|
type Listener = (event: RelayEvent) => void;
|
|
21
21
|
|
|
22
|
-
const listeners = new
|
|
22
|
+
const listeners = new Map<Listener, string>();
|
|
23
23
|
const fanoutQueue: Array<{ event: RelayEvent; lastSeq: number }> = [];
|
|
24
24
|
let notifying = false;
|
|
25
25
|
|
|
@@ -33,12 +33,13 @@ export function emitRelayEvent(input: Omit<RelayEvent, "seq" | "timestamp">): Pr
|
|
|
33
33
|
const appended = appendRelayEventInternal(input.type, input.source, input.data, input.subject, timestamp)!;
|
|
34
34
|
return Promise.resolve(fanOutAppendedEvent(input, appended, timestamp));
|
|
35
35
|
}
|
|
36
|
-
|
|
36
|
+
// #3614 — keyless: nothing resubmits this append, so a ledger row would only cost writes.
|
|
37
|
+
return trackRelayEvent(appendAndFanOut(structuredClone(input), {}), input.type);
|
|
37
38
|
});
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
/** #3606 — fan out to the current listeners only: no bus_outbox row, no idempotency-ledger row, no
|
|
41
|
-
* replay. For state the next tick supersedes anyway (dashboard viewer presence). */
|
|
42
|
+
* replay. For state the next tick supersedes anyway (dashboard viewer presence, agent liveness ticks). */
|
|
42
43
|
export function emitEphemeralRelayEvent(input: Omit<RelayEvent, "seq" | "timestamp" | "ephemeral">): RelayEvent {
|
|
43
44
|
return fanOutAppendedEvent({ ...input, ephemeral: true }, { seq: 0, lastSeq: 0 }, Date.now());
|
|
44
45
|
}
|
|
@@ -71,7 +72,8 @@ async function appendAndFanOut(
|
|
|
71
72
|
} catch (error) {
|
|
72
73
|
// H5: a lost acknowledgement says nothing about commit. Re-submit the exact logical append
|
|
73
74
|
// with the same durable key; the writer returns the first result without a second insert.
|
|
74
|
-
|
|
75
|
+
// A keyless emit is at-most-once: it surfaces the error, and a committed row stays replayable.
|
|
76
|
+
if (!(error instanceof WriteIndeterminateError) || !options.idempotencyKey) throw error;
|
|
75
77
|
appended = await getGateway().write("bus.append", args, { critical: true, idempotencyKey: options.idempotencyKey }) as unknown as typeof appended;
|
|
76
78
|
}
|
|
77
79
|
// A retry ledger result proves durable storage, not that this process owns a fresh live edge.
|
|
@@ -122,19 +124,19 @@ export function fanOutAppendedEvent(
|
|
|
122
124
|
|
|
123
125
|
function notify(event: RelayEvent): void {
|
|
124
126
|
measureEmit(event.type, true, () => {
|
|
125
|
-
for (const listener of listeners) {
|
|
127
|
+
for (const [listener, name] of listeners) {
|
|
126
128
|
try {
|
|
127
129
|
listener(event);
|
|
128
130
|
} catch (error) {
|
|
129
131
|
// Event projections are isolated so one transport cannot block another; a failed one (e.g. a
|
|
130
132
|
// BUSY write in a projection, #3643) is logged, not swallowed.
|
|
131
|
-
console.warn(`[events] ${event.type} listener failed: ${errMessage(error)}
|
|
133
|
+
console.warn(`[events] ${event.type} listener ${name} failed: ${errMessage(error)}`, error instanceof Error ? error.stack : error);
|
|
132
134
|
}
|
|
133
135
|
}
|
|
134
136
|
});
|
|
135
137
|
}
|
|
136
138
|
|
|
137
|
-
export function subscribeRelayEvents(listener: Listener): () => void {
|
|
138
|
-
listeners.
|
|
139
|
+
export function subscribeRelayEvents(listener: Listener, name = listener.name || "<anonymous>"): () => void {
|
|
140
|
+
listeners.set(listener, name);
|
|
139
141
|
return () => listeners.delete(listener);
|
|
140
142
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { setConfigAsync } from "./config-store-write";
|
|
1
2
|
// #2855 — DB-backed readers for per-host provider enablement. Separate from
|
|
2
3
|
// host-provider-enablement.ts (a config-store-imported leaf) so this module can
|
|
3
4
|
// import getConfig/listConfig without closing a cycle.
|
|
4
5
|
import { errMessage, type SpawnProvider } from "@humwick/sdk";
|
|
5
|
-
import { getConfig, listConfig
|
|
6
|
+
import { getConfig, listConfig } from "./config-store";
|
|
6
7
|
import { listOrchestratorIds } from "./db";
|
|
7
8
|
import {
|
|
8
9
|
HOST_PROVIDER_ENABLEMENT_NAMESPACE,
|
|
@@ -75,11 +76,11 @@ export function hostProviderRefusal(hostId: string, provider: SpawnProvider): st
|
|
|
75
76
|
/** One-time env migration: missing/unmarked rows merge omitted disables
|
|
76
77
|
* without touching operator entries. In-env opt-ins store explicit true;
|
|
77
78
|
* everything else outside env seeds as disabled. */
|
|
78
|
-
export function seedHostProvidersFromEnv(
|
|
79
|
+
export async function seedHostProvidersFromEnv(
|
|
79
80
|
hostId: string,
|
|
80
81
|
envProviders: readonly string[],
|
|
81
82
|
switchableCatalog: readonly SpawnProvider[],
|
|
82
|
-
): HostProviderEnablementSetting | null {
|
|
83
|
+
): Promise<HostProviderEnablementSetting | null> {
|
|
83
84
|
const existing = getHostProviderSetting(hostId);
|
|
84
85
|
if (existing?.seeded) return null;
|
|
85
86
|
const env = new Set(envProviders);
|
|
@@ -98,5 +99,5 @@ export function seedHostProvidersFromEnv(
|
|
|
98
99
|
providers[provider] = { enabled: false, reason: "migrated from host env list" };
|
|
99
100
|
}
|
|
100
101
|
}
|
|
101
|
-
return
|
|
102
|
+
return (await setConfigAsync(HOST_PROVIDER_ENABLEMENT_NAMESPACE, hostId, { providers, seeded: true }, "migration-seed")).value;
|
|
102
103
|
}
|
|
@@ -20,6 +20,7 @@ export function hubMetricsReport(now = Date.now()) {
|
|
|
20
20
|
const emits = emitTable.snapshot(now);
|
|
21
21
|
const readerOps = readerOpTable.snapshot(now);
|
|
22
22
|
const cpuMs = callers.reduce((total, row) => total + row.cpuMs, 0);
|
|
23
|
+
const backgroundCpuMs = callers.find((row) => row.key === BACKGROUND_KEY)?.cpuMs ?? 0;
|
|
23
24
|
const calls = callers.reduce((total, row) => total + row.count, 0);
|
|
24
25
|
return {
|
|
25
26
|
generatedAt: now,
|
|
@@ -28,7 +29,9 @@ export function hubMetricsReport(now = Date.now()) {
|
|
|
28
29
|
mainThread: {
|
|
29
30
|
cpuMs: Math.round(cpuMs),
|
|
30
31
|
cpuPct: Math.round((cpuMs / windowMs) * 10_000) / 100,
|
|
31
|
-
backgroundCpuMs: Math.round(
|
|
32
|
+
backgroundCpuMs: Math.round(backgroundCpuMs),
|
|
33
|
+
// #3798 — the share of main-thread CPU a named frame (route, bus frame, timer, job) accounts for.
|
|
34
|
+
namedCpuPct: cpuMs > 0 ? Math.round(((cpuMs - backgroundCpuMs) / cpuMs) * 10_000) / 100 : 100,
|
|
32
35
|
},
|
|
33
36
|
callers: {
|
|
34
37
|
count: calls,
|
|
@@ -62,6 +65,7 @@ export function hubLoadCheck(now = Date.now()): HealthCheck {
|
|
|
62
65
|
busConnections: report.connections.bus,
|
|
63
66
|
callsPerSec: report.callers.perSec,
|
|
64
67
|
mainThreadCpuPct: report.mainThread.cpuPct,
|
|
68
|
+
mainThreadNamedCpuPct: report.mainThread.namedCpuPct,
|
|
65
69
|
},
|
|
66
70
|
};
|
|
67
71
|
}
|
package/src/hub-metrics.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// so caller CPU is split at marks (caller start/end, reader resumes): the CPU between two marks goes
|
|
5
5
|
// to the caller that ran. docs/operations.md "Hub load metrics" describes the model and its limits.
|
|
6
6
|
|
|
7
|
-
import { runWithLoopCallsite } from "./loop-block-attribution";
|
|
7
|
+
import { resolveLoopCallsite, runWithLoopCallsite, type LoopCallsiteContext } from "./loop-block-attribution";
|
|
8
8
|
|
|
9
9
|
const BUCKET_MS = 10_000;
|
|
10
10
|
const BUCKETS = 6;
|
|
@@ -109,25 +109,45 @@ export function markCallerResume(owner: string | undefined): void {
|
|
|
109
109
|
ledgerOwner = owner;
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
/**
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
112
|
+
/** #3798 — run `run` as named frame `ctx.callsite` (request, bus frame, timer tick, job): its count, wall
|
|
113
|
+
* time and main-thread CPU. Opens the loop callsite scope, so reader and writer results inside it are
|
|
114
|
+
* charged back to it. Returns what `run` returns (a sync body stays sync); on exit the ledger goes back
|
|
115
|
+
* to the enclosing frame (a job inside the scheduler tick). */
|
|
116
|
+
export function runInFrame<T>(ctx: LoopCallsiteContext & { callsite: string }, run: () => T): T {
|
|
117
|
+
const outer = resolveLoopCallsite();
|
|
118
|
+
return runWithLoopCallsite(ctx, () => {
|
|
119
|
+
const key = ctx.callsite;
|
|
120
|
+
const startedAt = performance.now();
|
|
121
|
+
markCallerResume(key);
|
|
122
|
+
const end = () => {
|
|
123
|
+
// The code finishing the frame is the frame itself, so the segment since the last mark is its own.
|
|
124
|
+
const now = Date.now();
|
|
125
|
+
settleCpu(key, now);
|
|
126
|
+
ledgerOwner = outer;
|
|
127
|
+
callerTable.add(key, now, 1, performance.now() - startedAt);
|
|
128
|
+
};
|
|
129
|
+
let result: T;
|
|
130
|
+
try {
|
|
131
|
+
result = run();
|
|
132
|
+
} catch (error) {
|
|
133
|
+
end();
|
|
134
|
+
throw error;
|
|
135
|
+
}
|
|
136
|
+
if (result instanceof Promise) return result.finally(end) as T;
|
|
137
|
+
end();
|
|
138
|
+
return result;
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** `runInFrame` as a callback, for a timer or interval body: `setInterval(framed("timer x", tick), ms)`. */
|
|
143
|
+
export function framed<A extends unknown[], T>(key: string, fn: (...args: A) => T): (...args: A) => T {
|
|
144
|
+
const ctx = { callsite: key };
|
|
145
|
+
return (...args: A) => runInFrame(ctx, () => fn(...args));
|
|
125
146
|
}
|
|
126
147
|
|
|
127
|
-
/**
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
return runWithLoopCallsite({ callsite }, () => trackCaller(callsite, run));
|
|
148
|
+
/** A bus frame: always a promise, so a sync throw reaches the frame queue's `catch`. */
|
|
149
|
+
export async function runAsCaller<T>(callsite: string, run: () => T | Promise<T>): Promise<T> {
|
|
150
|
+
return runInFrame({ callsite }, run);
|
|
131
151
|
}
|
|
132
152
|
|
|
133
153
|
// ── Emits ─────────────────────────────────────────────────────────────────────────────────────────
|
|
@@ -2,23 +2,21 @@
|
|
|
2
2
|
// one boundary per macrotask (`forEachPaced`); a backlog (a long pause, a crash that lost many settles)
|
|
3
3
|
// is drained in runs of this budget, well inside the 30s job deadline, re-run this soon while a run
|
|
4
4
|
// reports `moreWork`.
|
|
5
|
-
import { isSqliteBusyError
|
|
5
|
+
import { isSqliteBusyError } from "./db/connection";
|
|
6
6
|
import { forEachPaced } from "./event-loop-yield";
|
|
7
7
|
|
|
8
8
|
export const INJECTION_SWEEP_RUN_BUDGET_MS = 10_000;
|
|
9
9
|
export const INJECTION_SWEEP_BACKLOG_INTERVAL_MS = 5_000;
|
|
10
|
-
const SWEEP_BUSY_TIMEOUT_MS = 40;
|
|
11
10
|
|
|
12
|
-
/**
|
|
13
|
-
|
|
14
|
-
export async function pacedInjectionSweep<T>(items: () => Iterable<T>, unit: (item: T) => void, signal?: AbortSignal): Promise<{ moreWork: boolean }> {
|
|
11
|
+
/** The gateway owns write contention; wait for each unit before continuing the bounded sweep. */
|
|
12
|
+
export async function pacedInjectionSweep<T>(items: () => Iterable<T>, unit: (item: T) => unknown, signal?: AbortSignal): Promise<{ moreWork: boolean }> {
|
|
15
13
|
let contended = false;
|
|
16
|
-
return forEachPaced(items, (item) => {
|
|
14
|
+
return forEachPaced(items, async (item) => {
|
|
17
15
|
try {
|
|
18
|
-
|
|
16
|
+
await unit(item);
|
|
19
17
|
} catch (error) {
|
|
20
18
|
if (!isSqliteBusyError(error)) throw error;
|
|
21
19
|
contended = true;
|
|
22
20
|
}
|
|
23
|
-
}, { signal, budgetMs: INJECTION_SWEEP_RUN_BUDGET_MS, ready: () => !contended
|
|
21
|
+
}, { signal, budgetMs: INJECTION_SWEEP_RUN_BUDGET_MS, ready: () => !contended });
|
|
24
22
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { createActivityEventAsync } from "./db/activity-async";
|
|
1
2
|
import type { LandGateRunResult, WorkspaceRecord } from "@humwick/sdk";
|
|
2
3
|
import { emitRelayEvent } from "./events";
|
|
3
4
|
import { routeNotification, INFORMATIONAL_TTL_MS } from "./notification-router";
|
|
4
|
-
|
|
5
|
+
|
|
5
6
|
import { resolveCoordinatorAgentId } from "./steward-identity";
|
|
6
7
|
import { stewardFallbackTarget } from "./config";
|
|
7
8
|
import { routeLandGateFailure } from "./land-gate-failure-routing";
|
|
@@ -51,7 +52,7 @@ export async function notifyLandGateFailed(input: {
|
|
|
51
52
|
|
|
52
53
|
emitRelayEvent({ type: "workspace.land_gate_failed", source: "server", subject: workspace.id, data: payload });
|
|
53
54
|
|
|
54
|
-
|
|
55
|
+
(await createActivityEventAsync({
|
|
55
56
|
clientId: `workspace-land-gate-failed-${workspace.id}-${Date.now()}`,
|
|
56
57
|
kind: "state",
|
|
57
58
|
title: "Land blocked by gate failure",
|
|
@@ -60,11 +61,11 @@ export async function notifyLandGateFailed(input: {
|
|
|
60
61
|
icon: "ti-alert-octagon",
|
|
61
62
|
view: "orchestrators",
|
|
62
63
|
metadata: { source: "server", maintenanceJobId: "workspace-land-gate", workspaceId: workspace.id, repoRoot: workspace.repoRoot, gateName: gate.name, ...(input.artifactId ? { artifactId: input.artifactId } : {}) },
|
|
63
|
-
});
|
|
64
|
+
}));
|
|
64
65
|
|
|
65
66
|
const routing = await routeLandGateFailure({ workspaceId: workspace.id, branch: workspace.branch, failedAt: input.failedAt, owner, coordinator, fallback, gateName: gate.name });
|
|
66
67
|
if (routing.stale) return;
|
|
67
|
-
routeNotification({
|
|
68
|
+
await routeNotification({
|
|
68
69
|
type: "workspace.land_gate_failed",
|
|
69
70
|
scope: { author: owner, parent: routing.parent, repoRoot: workspace.repoRoot, workspaceId: workspace.id },
|
|
70
71
|
recipients: routing.recipients,
|
|
@@ -80,14 +81,14 @@ export async function notifyLandGateFailed(input: {
|
|
|
80
81
|
}
|
|
81
82
|
|
|
82
83
|
/** #902 — gate failures wake both owner and coordinator durably; full logs stay in artifacts. */
|
|
83
|
-
export function notifyLandGateWarnings(input: {
|
|
84
|
+
export async function notifyLandGateWarnings(input: {
|
|
84
85
|
workspace: Pick<WorkspaceRecord, "id" | "repoRoot" | "branch" | "baseRef" | "ownerAgentId">;
|
|
85
86
|
warnings: LandGateRunResult[];
|
|
86
87
|
/** #2474 R3 — false when any warning's wire output is a folded tail: the combined artifact is
|
|
87
88
|
* then an index (tails + per-gate full-log refs), not full output, and the label must not
|
|
88
89
|
* claim otherwise. Defaults to true (nothing folded). */
|
|
89
90
|
artifactId?: string; fullOutput?: boolean;
|
|
90
|
-
}): void {
|
|
91
|
+
}): Promise<void> {
|
|
91
92
|
const { workspace, warnings } = input;
|
|
92
93
|
if (warnings.length === 0) return;
|
|
93
94
|
const base = workspace.baseRef ?? "base";
|
|
@@ -110,7 +111,7 @@ export function notifyLandGateWarnings(input: {
|
|
|
110
111
|
emitRelayEvent({ type: "workspace.land_gate_warning", source: "server", subject: workspace.id, data: payload });
|
|
111
112
|
|
|
112
113
|
if (!owner) return;
|
|
113
|
-
routeNotification({
|
|
114
|
+
await routeNotification({
|
|
114
115
|
type: "workspace.land_gate_warning",
|
|
115
116
|
scope: { author: owner, repoRoot: workspace.repoRoot, workspaceId: workspace.id },
|
|
116
117
|
recipients: [owner],
|
|
@@ -124,13 +125,13 @@ export function notifyLandGateWarnings(input: {
|
|
|
124
125
|
});
|
|
125
126
|
}
|
|
126
127
|
|
|
127
|
-
export function notifyLandGateSkipped(input: {
|
|
128
|
+
export async function notifyLandGateSkipped(input: {
|
|
128
129
|
workspace: Pick<WorkspaceRecord, "id" | "repoRoot" | "branch" | "baseRef" | "ownerAgentId">;
|
|
129
130
|
level: "subset" | "none";
|
|
130
131
|
reason: string;
|
|
131
132
|
by: string;
|
|
132
133
|
commit?: string;
|
|
133
|
-
}): void {
|
|
134
|
+
}): Promise<void> {
|
|
134
135
|
const { workspace } = input;
|
|
135
136
|
const base = workspace.baseRef ?? "base";
|
|
136
137
|
const owner = workspace.ownerAgentId;
|
|
@@ -157,7 +158,7 @@ export function notifyLandGateSkipped(input: {
|
|
|
157
158
|
|
|
158
159
|
const recipients = [...new Set([owner, coordinator ?? fallback].filter((r): r is string => Boolean(r)))];
|
|
159
160
|
if (!recipients.length) return;
|
|
160
|
-
routeNotification({
|
|
161
|
+
await routeNotification({
|
|
161
162
|
type: "workspace.land_gate_skipped",
|
|
162
163
|
scope: { author: owner, parent: coordinator ?? undefined, repoRoot: workspace.repoRoot, workspaceId: workspace.id },
|
|
163
164
|
recipients,
|
|
@@ -6,14 +6,14 @@ import { stewardFallbackTarget } from "./config";
|
|
|
6
6
|
import type { Command, WorkspaceRecord } from "./types";
|
|
7
7
|
|
|
8
8
|
/** An offline host is uncertain, never positive evidence to release its lane (#2777). */
|
|
9
|
-
export function alertUnprovenLandLaneHolder(command: Command): void {
|
|
9
|
+
export async function alertUnprovenLandLaneHolder(command: Command): Promise<void> {
|
|
10
10
|
const workspaceId = command.correlationId ?? command.params.workspaceId;
|
|
11
11
|
const workspace = typeof workspaceId === "string" ? getWorkspace(workspaceId) : null;
|
|
12
12
|
if (!workspace) return;
|
|
13
13
|
const coordinator = resolveCoordinatorAgentId(workspace.ownerAgentId);
|
|
14
14
|
const target = coordinator ?? stewardFallbackTarget() ?? workspace.ownerAgentId;
|
|
15
15
|
if (!target) return;
|
|
16
|
-
routeNotification({
|
|
16
|
+
await routeNotification({
|
|
17
17
|
type: "workspace.land_gate_queue_stalled",
|
|
18
18
|
scope: { author: workspace.ownerAgentId, parent: coordinator ?? undefined, repoRoot: workspace.repoRoot, workspaceId: workspace.id },
|
|
19
19
|
recipients: [target], forceDelivery: true, ttlMs: null,
|
|
@@ -39,7 +39,7 @@ export async function recordLandGateQueueProgress(workspace: WorkspaceRecord, co
|
|
|
39
39
|
const coordinator = resolveCoordinatorAgentId(workspace.ownerAgentId);
|
|
40
40
|
const target = coordinator ?? stewardFallbackTarget() ?? workspace.ownerAgentId;
|
|
41
41
|
if (!target) return;
|
|
42
|
-
routeNotification({
|
|
42
|
+
await routeNotification({
|
|
43
43
|
type: "workspace.land_gate_queue_stalled",
|
|
44
44
|
scope: { author: workspace.ownerAgentId, parent: coordinator ?? undefined, repoRoot: workspace.repoRoot, workspaceId: workspace.id },
|
|
45
45
|
recipients: [target], forceDelivery: true, ttlMs: null,
|
|
@@ -1,56 +1,7 @@
|
|
|
1
1
|
import { errMessage } from "@humwick/sdk";
|
|
2
|
+
import { trackRelayEvent } from "./relay-event-drain";
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
* #1790 — the land settle path (`settleWorkspaceMergeCommand`) fires 6–12 serialized SYNCHRONOUS
|
|
5
|
-
* DB writes per land: the `branch.landed` + `landed-success` events, the per-recipient notification
|
|
6
|
-
* fan-out (each a `sendMessage` + an activity-event audit, over an all-agents audience scan), the
|
|
7
|
-
* issue/Task lifecycle drives, and — on the reviewer path — an eager policy spawn dispatch. NONE use
|
|
8
|
-
* the async busy-retry wrapper, so each raw write can block the event-loop thread up to `busy_timeout`
|
|
9
|
-
* (1s, `db/connection.ts`) under lock contention. A land BURST piles this onto the contended loop and
|
|
10
|
-
* amplifies the ~2.4s event-loop lag that made the relay HTTP server miss a concurrent `spawn` (the
|
|
11
|
-
* "socket connection closed" failures in #1790).
|
|
12
|
-
*
|
|
13
|
-
* None of that work belongs on the synchronous settle critical path. The AUTHORITATIVE land STATE —
|
|
14
|
-
* the workspace status transition (ancestry-gated, #1713) and the landed-sha stamp — plus the durable
|
|
15
|
-
* landing RECEIPT (`recordLandingReceipt`, one indexed INSERT) are written synchronously and ARE the
|
|
16
|
-
* source of truth; the events, notifications, lifecycle drives and reviewer spawn are ANNOUNCEMENTS
|
|
17
|
-
* derived from that state.
|
|
18
|
-
*
|
|
19
|
-
* ## Serialized, one-item-per-tick drain (#1790 review F2)
|
|
20
|
-
* Deferring N announcements as N `setImmediate` callbacks does NOT relieve a burst: Node/Bun drain a
|
|
21
|
-
* whole `setImmediate` batch as one contiguous group within a single check phase, BEFORE the poll
|
|
22
|
-
* phase accepts the next connection — so an N×fan-out block still refuses a `spawn` arriving during
|
|
23
|
-
* it. Instead this runs a SERIALIZED queue: each drain executes exactly ONE item and, only if the
|
|
24
|
-
* queue is still non-empty, re-schedules itself. That guarantees a full event-loop iteration — poll
|
|
25
|
-
* phase included, so incoming connections are accepted — between every two fan-outs.
|
|
26
|
-
*
|
|
27
|
-
* ## Shutdown drain (#1790 review F1)
|
|
28
|
-
* A graceful stop is a SIGTERM/SIGINT (CD deploys are graceful SIGTERMs, often triggered BY a land —
|
|
29
|
-
* a bad correlation). {@link drainPendingLandSettleSideEffects} runs every still-queued callback
|
|
30
|
-
* synchronously; the process shutdown handler (a SINGLE `once` per signal in `db/agents.ts`) calls it
|
|
31
|
-
* before re-raising, so an announcement already QUEUED by the time the signal is handled is never
|
|
32
|
-
* dropped. Accepted residual: a HARD crash (SIGKILL / power loss) still loses any un-flushed deferred
|
|
33
|
-
* announcement, but the durable landing RECEIPT is written synchronously right after the settle's own
|
|
34
|
-
* `await` resolves (`recordLandingReceipt`, before `markWorkspaceLanded`), so a land whose settle has
|
|
35
|
-
* fully RUN is never left unrecorded on a clean stop — only its wake/lifecycle drive would need a
|
|
36
|
-
* re-poll to recover.
|
|
37
|
-
*
|
|
38
|
-
* #1830 (async land-settle git probes) narrowed this guarantee: `settleWorkspaceMergeCommand` now
|
|
39
|
-
* awaits a bounded (up to ~12s worst case) async git ancestry check BEFORE it writes the land state,
|
|
40
|
-
* the receipt, or queues any announcement here. A graceful stop that lands mid-await — the event loop
|
|
41
|
-
* is genuinely free during that await, unlike the old fully-synchronous settle a signal handler could
|
|
42
|
-
* never interrupt mid-function — sees NOTHING queued for this land yet, so `drainPendingLandSettleSideEffects`
|
|
43
|
-
* flushes nothing for it and the settle can be lost in its entirety (state + receipt + announcement),
|
|
44
|
-
* not just its announcement. The land is not silently mis-recorded (no state was written either), but
|
|
45
|
-
* it is a real durability gap this module cannot close on its own — a full fix needs the settle path
|
|
46
|
-
* itself to survive/resume across a restart (a fast re-settle on startup, or a bounded shutdown drain
|
|
47
|
-
* that waits out in-flight settles). Tracked as #1831; out of scope here.
|
|
48
|
-
*
|
|
49
|
-
* Errors are isolated: a deferred announcement runs AFTER the land it announces has already settled,
|
|
50
|
-
* so a throw here can never unwind or mask the land. This is a deliberate swallow-and-log (the inline
|
|
51
|
-
* callers propagated most of these throws to the settle caller; moving them off-thread means there is
|
|
52
|
-
* no caller left to catch them, so isolation is a behavior improvement, not parity).
|
|
53
|
-
*/
|
|
4
|
+
// #1790/#1870 — serialize post-commit announcements, yielding between items and awaiting them at shutdown.
|
|
54
5
|
type LandSettleScheduler = (run: () => void) => void;
|
|
55
6
|
|
|
56
7
|
const defaultScheduler: LandSettleScheduler = (run) => {
|
|
@@ -61,7 +12,8 @@ let scheduler: LandSettleScheduler = defaultScheduler;
|
|
|
61
12
|
|
|
62
13
|
interface PendingSideEffect {
|
|
63
14
|
label: string;
|
|
64
|
-
fn: () =>
|
|
15
|
+
fn: () => unknown;
|
|
16
|
+
complete: () => void;
|
|
65
17
|
}
|
|
66
18
|
|
|
67
19
|
// One global FIFO queue drained one item per scheduler tick (F2). `scheduled` guards against
|
|
@@ -69,25 +21,36 @@ interface PendingSideEffect {
|
|
|
69
21
|
const queue: PendingSideEffect[] = [];
|
|
70
22
|
let scheduled = false;
|
|
71
23
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
24
|
+
let active: Promise<void> | undefined;
|
|
25
|
+
let shutdownDrain: Promise<void> | undefined;
|
|
26
|
+
let executing = false;
|
|
27
|
+
let draining = false;
|
|
28
|
+
|
|
29
|
+
async function runOne(item: PendingSideEffect): Promise<void> {
|
|
30
|
+
try { await item.fn(); }
|
|
31
|
+
catch (error) { console.warn(`[land-settle] deferred ${item.label} threw (land already settled; announcement only): ${errMessage(error)}`); }
|
|
32
|
+
finally { item.complete(); }
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function scheduleNext(): void {
|
|
36
|
+
if (!queue.length || scheduled || executing || draining) return;
|
|
37
|
+
scheduled = true;
|
|
38
|
+
scheduler(drainOne);
|
|
78
39
|
}
|
|
79
40
|
|
|
80
41
|
function drainOne(): void {
|
|
81
42
|
scheduled = false;
|
|
43
|
+
if (executing || draining) return;
|
|
82
44
|
const item = queue.shift();
|
|
83
|
-
if (item)
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
45
|
+
if (!item) return;
|
|
46
|
+
executing = true;
|
|
47
|
+
const running = runOne(item);
|
|
48
|
+
active = running;
|
|
49
|
+
void running.finally(() => {
|
|
50
|
+
if (active === running) active = undefined;
|
|
51
|
+
executing = false;
|
|
52
|
+
scheduleNext();
|
|
53
|
+
}).catch(error => console.warn(`[land-settle] drain failed: ${errMessage(error)}`));
|
|
91
54
|
}
|
|
92
55
|
|
|
93
56
|
/**
|
|
@@ -96,39 +59,36 @@ function drainOne(): void {
|
|
|
96
59
|
* path and DOES run once flushed. Pass `undefined` to restore the `setImmediate` default. Also drains
|
|
97
60
|
* any queued work so state never leaks across tests.
|
|
98
61
|
*/
|
|
99
|
-
export function __setLandSettleSchedulerForTests(fn: LandSettleScheduler | undefined): void {
|
|
100
|
-
drainPendingLandSettleSideEffects();
|
|
62
|
+
export async function __setLandSettleSchedulerForTests(fn: LandSettleScheduler | undefined): Promise<void> {
|
|
63
|
+
await drainPendingLandSettleSideEffects();
|
|
101
64
|
scheduler = fn ?? defaultScheduler;
|
|
102
65
|
}
|
|
103
66
|
|
|
104
67
|
/** Schedule a land-settle announcement/side-effect off the synchronous settle critical path (#1790). */
|
|
105
|
-
export function deferLandSettleSideEffect(label: string, fn: () =>
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
68
|
+
export function deferLandSettleSideEffect(label: string, fn: () => unknown): void {
|
|
69
|
+
let complete!: () => void;
|
|
70
|
+
const pending = new Promise<void>(resolve => { complete = resolve; });
|
|
71
|
+
trackRelayEvent(pending, `land-settle.${label}`);
|
|
72
|
+
queue.push({ label, fn, complete });
|
|
73
|
+
scheduleNext();
|
|
111
74
|
}
|
|
112
75
|
|
|
113
|
-
/**
|
|
114
|
-
* #1790 review F1 — run every still-queued side-effect synchronously, for the graceful-shutdown
|
|
115
|
-
* (SIGTERM/SIGINT) drain so a deferred landing announcement is never dropped on a clean stop.
|
|
116
|
-
* Re-entrant-safe: an announcement that itself defers more work is picked up by the same loop (the
|
|
117
|
-
* loop re-reads `queue.length`), and each item's throw is swallowed so one bad announcement can never
|
|
118
|
-
* block shutdown. A pathologically self-feeding queue is bounded by MAX_SHUTDOWN_DRAIN so shutdown
|
|
119
|
-
* always terminates.
|
|
120
|
-
*/
|
|
121
76
|
const MAX_SHUTDOWN_DRAIN = 100_000;
|
|
122
|
-
export function drainPendingLandSettleSideEffects(): void {
|
|
77
|
+
export function drainPendingLandSettleSideEffects(): Promise<void> {
|
|
78
|
+
if (shutdownDrain) return shutdownDrain;
|
|
123
79
|
scheduled = false;
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
80
|
+
draining = true;
|
|
81
|
+
shutdownDrain = (async () => {
|
|
82
|
+
if (active) await active;
|
|
83
|
+
let drained = 0;
|
|
84
|
+
while (queue.length) {
|
|
85
|
+
await runOne(queue.shift()!);
|
|
86
|
+
if (++drained >= MAX_SHUTDOWN_DRAIN) {
|
|
87
|
+
console.warn(`[land-settle] shutdown drain hit ${MAX_SHUTDOWN_DRAIN} items; abandoning ${queue.length} still-queued side-effect(s)`);
|
|
88
|
+
for (const item of queue.splice(0)) item.complete();
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
132
91
|
}
|
|
133
|
-
}
|
|
92
|
+
})().finally(() => { shutdownDrain = undefined; draining = false; scheduleNext(); });
|
|
93
|
+
return shutdownDrain;
|
|
134
94
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { createCommandAsync } from "./commands-write";
|
|
1
2
|
import { errMessage } from "@humwick/sdk";
|
|
2
|
-
import {
|
|
3
|
+
import { listCommands } from "./commands-db";
|
|
3
4
|
import { getAgent, listAgents } from "./db";
|
|
4
5
|
import { getManagedAgentState } from "./config-store";
|
|
5
6
|
import { emitCommandEvent } from "./command-events";
|
|
@@ -22,7 +23,7 @@ interface CompactAgentInput {
|
|
|
22
23
|
hasActiveCommand: (target: string, type: string) => boolean;
|
|
23
24
|
}
|
|
24
25
|
|
|
25
|
-
export function reconcileLifecycleContextPressure(input: LifecycleContextPressureInput): Set<string
|
|
26
|
+
export async function reconcileLifecycleContextPressure(input: LifecycleContextPressureInput): Promise<Set<string>> {
|
|
26
27
|
const byPolicy = new Map(input.policies.map((policy) => [policy.name, policy]));
|
|
27
28
|
const candidates = new Map<string, { agent: AgentCard; policy?: SpawnPolicy }>();
|
|
28
29
|
|
|
@@ -42,26 +43,26 @@ export function reconcileLifecycleContextPressure(input: LifecycleContextPressur
|
|
|
42
43
|
|
|
43
44
|
const handled = new Set<string>();
|
|
44
45
|
for (const { agent, policy } of candidates.values()) {
|
|
45
|
-
if (handleContextPressure({
|
|
46
|
+
if ((await handleContextPressure({
|
|
46
47
|
agent,
|
|
47
48
|
now: input.now,
|
|
48
49
|
hasActiveCommand: input.hasActiveCommand,
|
|
49
|
-
compact: (reason) => requestAgentCompact({
|
|
50
|
+
compact: async (reason) => (await requestAgentCompact({
|
|
50
51
|
agent,
|
|
51
52
|
reason,
|
|
52
53
|
policyName: policy?.name,
|
|
53
54
|
alwaysReload: alwaysReloadTags(agent.tags),
|
|
54
55
|
now: input.now,
|
|
55
56
|
hasActiveCommand: input.hasActiveCommand,
|
|
56
|
-
}),
|
|
57
|
-
})) {
|
|
57
|
+
})),
|
|
58
|
+
}))) {
|
|
58
59
|
handled.add(agent.id);
|
|
59
60
|
}
|
|
60
61
|
}
|
|
61
62
|
return handled;
|
|
62
63
|
}
|
|
63
64
|
|
|
64
|
-
export function requestAgentCompact(input: CompactAgentInput): Command | null {
|
|
65
|
+
export async function requestAgentCompact(input: CompactAgentInput): Promise<Command | null> {
|
|
65
66
|
// #2004 — dedup BEFORE building the resume plan (which persists a recovery message): a compaction
|
|
66
67
|
// may already be in flight as EITHER an agent.compact (native providers) or an agent.clearContext
|
|
67
68
|
// (clear-inject providers), so guard against both shapes rather than only the legacy agent.compact.
|
|
@@ -81,7 +82,7 @@ export function requestAgentCompact(input: CompactAgentInput): Command | null {
|
|
|
81
82
|
// whose identity/startup hooks still reinject the charter — never a clear, never nothing.
|
|
82
83
|
let resume: ForcedResumePlan | null = null;
|
|
83
84
|
try {
|
|
84
|
-
resume = buildForcedResumePlan(input.agent.id, now);
|
|
85
|
+
resume = (await buildForcedResumePlan(input.agent.id, now));
|
|
85
86
|
} catch (error) {
|
|
86
87
|
console.warn(`[lifecycle] forced resume plan for '${input.agent.id}' failed; degrading to a bare compact: ${errMessage(error)}`);
|
|
87
88
|
resume = null;
|
|
@@ -90,7 +91,7 @@ export function requestAgentCompact(input: CompactAgentInput): Command | null {
|
|
|
90
91
|
const spawnRequestId = typeof input.agent.meta?.spawnRequestId === "string" ? input.agent.meta.spawnRequestId : undefined;
|
|
91
92
|
const sessionName = typeof input.agent.meta?.sessionName === "string" ? input.agent.meta.sessionName : undefined;
|
|
92
93
|
const tmuxSession = typeof input.agent.meta?.tmuxSession === "string" ? input.agent.meta.tmuxSession : undefined;
|
|
93
|
-
const command =
|
|
94
|
+
const command = (await createCommandAsync({
|
|
94
95
|
type: commandType,
|
|
95
96
|
source: "system",
|
|
96
97
|
target: input.agent.id,
|
|
@@ -108,7 +109,7 @@ export function requestAgentCompact(input: CompactAgentInput): Command | null {
|
|
|
108
109
|
requestedAt: now,
|
|
109
110
|
...(resume?.params ?? {}),
|
|
110
111
|
},
|
|
111
|
-
});
|
|
112
|
+
}));
|
|
112
113
|
emitCommandEvent(command, "command.requested");
|
|
113
114
|
return command;
|
|
114
115
|
}
|