@humwick/server 0.130.2 → 0.130.4
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 +175 -4
- package/package.json +8 -7
- package/public/assets/{MessageBubble-BWLqMGKG.js → MessageBubble-BOkmEvgZ.js} +2 -2
- package/public/assets/{PlanGraphPanel-3TlIQpjk.js → PlanGraphPanel-BkaDJp0r.js} +2 -2
- package/public/assets/{TraceView-Wimm0Czv.js → TraceView-B99Uu2yT.js} +2 -2
- package/public/assets/{VaultDecisionCard-Bau_vNax.js → VaultDecisionCard-DUIfTTFF.js} +2 -2
- package/public/assets/{activity-CrSurn-r.js → activity-ZIX0N1El.js} +2 -2
- package/public/assets/{agent-lineage-CknAJKcb.js → agent-lineage-kq9TPYFw.js} +2 -2
- package/public/assets/agent-liveness-DSQY1Aa_.js +2 -0
- package/public/assets/{agent-name-DKbiIhBo.js → agent-name-C_7F4DFR.js} +2 -2
- package/public/assets/{agent-profiles-DwF6EQ4R.js → agent-profiles-BNOcrGcY.js} +2 -2
- package/public/assets/{agent-project-badge-Diz4Sjjb.js → agent-project-badge-B6yAh70a.js} +2 -2
- package/public/assets/{agent-tools-CRhpRQza.js → agent-tools-CcrhmOzF.js} +2 -2
- package/public/assets/{agent-type-icon-LrUEU3lB.js → agent-type-icon-CXSLrKiq.js} +2 -2
- package/public/assets/{agents-B-v66C-4.js → agents-DIZG97_X.js} +2 -2
- package/public/assets/{analytics-BqCb-LKi.js → analytics-rasmoPjR.js} +2 -2
- package/public/assets/{artifact-viewer-kf4pGuAR.js → artifact-viewer-tBpTrEPb.js} +2 -2
- package/public/assets/{artifacts-DJevXcvg.js → artifacts-BNkrynP1.js} +2 -2
- package/public/assets/{artifacts-D32zyw4Y.js → artifacts-Bjq-ZyBA.js} +2 -2
- package/public/assets/{automation-BpRajx_5.js → automation-Cx422L3L.js} +2 -2
- package/public/assets/{backlog-D_UjTdzX.js → backlog-RuFQ8PUu.js} +2 -2
- package/public/assets/{busy-health-N3VEh4ao.js → busy-health-BvNQ9g5x.js} +2 -2
- package/public/assets/{channels-9jopungq.js → channels-DNbKAS0I.js} +2 -2
- package/public/assets/{chat-CSXrTB3C.js → chat-Bp3Fx73h.js} +3 -3
- package/public/assets/{code-preview-p1NnmqK0.js → code-preview-KIRZA6cz.js} +2 -2
- package/public/assets/{connectors-CZdqlDNL.js → connectors-k7vO4vvc.js} +2 -2
- package/public/assets/{cosmos-BgdsE4dG.js → cosmos-BuVoq1aw.js} +2 -2
- package/public/assets/{crate-agent-30aXTKva.js → crate-agent-irqlt4NH.js} +2 -2
- package/public/assets/{dependency-graph-B_jvw2GE.js → dependency-graph-D_rurNBz.js} +2 -2
- package/public/assets/{deploys-DoN6bAb5.js → deploys-yzZqIpxE.js} +2 -2
- package/public/assets/{display-BrKWFGJz.js → display-BemJG1f_.js} +2 -2
- package/public/assets/{files-D6XEu8Ng.js → files-DXWcrxOz.js} +2 -2
- package/public/assets/{fleet-C7jQWbw2.js → fleet-TEuOCZXE.js} +2 -2
- package/public/assets/{fleet-metrics-BiDs3MLx.js → fleet-metrics-BGoDAFI-.js} +2 -2
- package/public/assets/{formatted-body-impl-DyG0WsQS.js → formatted-body-impl-BB9eq9nN.js} +2 -2
- package/public/assets/{formatted-body-CQBwc1fb.js → formatted-body-qy2nTD_1.js} +3 -3
- package/public/assets/{host-providers-dialog-DKaW31dN.js → host-providers-dialog-BGPHxuwT.js} +2 -2
- package/public/assets/{index-CRHep3M9.js → index-BC5XZc0z.js} +5 -5
- package/public/assets/{index-MYAIwYTX.css → index-D8Rp9pz2.css} +1 -1
- package/public/assets/{insights-CzrtkpOE.js → insights-C-KQG0h-.js} +2 -2
- package/public/assets/{integrations-aVsUmigt.js → integrations-ClPRPyKU.js} +2 -2
- package/public/assets/{issue-ref-chip-BnSlM_95.js → issue-ref-chip-DbH8J9Ak.js} +2 -2
- package/public/assets/{log-viewer-qe7Ee47Z.js → log-viewer-PH4zVn24.js} +2 -2
- package/public/assets/{maintenance-NfjqFZAk.js → maintenance-5lV43uTL.js} +2 -2
- package/public/assets/{managed-agents-BiH0HgaE.js → managed-agents-BdgU35aX.js} +2 -2
- package/public/assets/{markdown-preview-BixaT3Xr.js → markdown-preview-DNT4OUwQ.js} +3 -3
- package/public/assets/{markdown-preview-impl-DNGlWIS3.js → markdown-preview-impl-CnCcPy0A.js} +2 -2
- package/public/assets/{memory-DNsCl6UX.js → memory--GgWH1gH.js} +2 -2
- package/public/assets/{messages-DopU1L1X.js → messages-CzFl_97O.js} +2 -2
- package/public/assets/{orchestrators-Cq7ckLQT.js → orchestrators-CVvJVkzv.js} +2 -2
- package/public/assets/overview-DsrZvE86.js +2 -0
- package/public/assets/{pairs-DE_m6rrE.js → pairs-D2d0d2py.js} +2 -2
- package/public/assets/{profile-icon-B3rfh77F.js → profile-icon-_SMuSbYF.js} +2 -2
- package/public/assets/{project-profile-instructions-DQWZE0kA.js → project-profile-instructions-Apn15y43.js} +2 -2
- package/public/assets/{projects-Br2Bd2h1.js → projects-D3B6kto5.js} +2 -2
- package/public/assets/{prompt-settings-BKvFsvGD.js → prompt-settings-DnPB6Ez6.js} +2 -2
- package/public/assets/provider-display-bWwiuedV.js +2 -0
- package/public/assets/{registry-Cw38_6gW.js → registry-D790cIhN.js} +2 -2
- package/public/assets/run-card-BCro-Odj.js +2 -0
- package/public/assets/{secrets-DxI-vzSq.js → secrets-CVXvfvbU.js} +2 -2
- package/public/assets/{service-access-settings-D9s_VJbd.js → service-access-settings-D3Xxqb9w.js} +2 -2
- package/public/assets/{settings-CKZTVGIx.js → settings-CoUC7Jci.js} +2 -2
- package/public/assets/shipping-D_Lp9n_J.js +2 -0
- package/public/assets/{stats-DyUBKyWI.js → stats-CXiNjB9S.js} +2 -2
- package/public/assets/{status-dot-DYqlEUhJ.js → status-dot-C703YIy1.js} +2 -2
- package/public/assets/store-BgDALGIX.js +9 -0
- package/public/assets/{tasks-Bh7Chr4-.js → tasks-DO0WpJCx.js} +2 -2
- package/public/assets/{teams-bowI7qVY.js → teams-FGkdi_tL.js} +2 -2
- package/public/assets/{terminal-viewer-BgVLHdsU.js → terminal-viewer-Dh8dSC7e.js} +3 -3
- package/public/assets/{terminal-viewer-impl-Dz22UPy6.js → terminal-viewer-impl-B5Zriip3.js} +2 -2
- package/public/assets/{use-agent-terminal-DSQQ-iY7.js → use-agent-terminal-CRUVDvLC.js} +2 -2
- package/public/assets/{use-decisions-samMQhQf.js → use-decisions-CoaqRh4l.js} +2 -2
- package/public/assets/{use-project-list-59LheVP7.js → use-project-list-X-BgT53X.js} +2 -2
- package/public/assets/{use-selectors-BZa25xEB.js → use-selectors-0X_UZkk-.js} +2 -2
- package/public/assets/{user-avatar-DHxlvUvV.js → user-avatar-CkLhVBGu.js} +2 -2
- package/public/assets/{versioned-prompt-editor-BmED5DnJ.js → versioned-prompt-editor-BkTi7eim.js} +2 -2
- package/public/assets/{work-queue-CSvpuNLz.js → work-queue-DDOLEyKo.js} +2 -2
- package/public/assets/{workflow-marker-DAZcj5qt.js → workflow-marker-CzOsB8BM.js} +2 -2
- package/public/assets/{workflows-DdmxRSyg.js → workflows-DJilvmRM.js} +2 -2
- package/public/assets/{workspaces-BxeKfVuF.js → workspaces-CHcfbLR3.js} +2 -2
- package/public/cosmos.html +4 -4
- package/public/index.html +29 -29
- package/runner/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/runner/src/adapters/claude-api.ts +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 +3 -2
- 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/login-link.ts +35 -0
- 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/index.ts +7 -1
- package/src/cli/init.ts +53 -0
- package/src/cli/orchestrator.ts +1 -7
- package/src/cli/setup.ts +6 -4
- 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 +3 -12
- 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/workflow-execution.ts +3 -3
- 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 +12 -16
- 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/init.ts +299 -0
- package/src/injection-sweep-pacing.ts +6 -8
- package/src/invite-link.ts +16 -9
- 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 +44 -17
- 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-providers.ts +18 -0
- 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 +7 -3
- 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 +3 -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 +4 -5
- package/src/routes/secrets-import.ts +3 -4
- package/src/routes/secrets-vault.ts +12 -14
- 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-install.ts +30 -0
- 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 +25 -26
- 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/auth-context.ts +6 -0
- 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-api-key.ts +73 -0
- 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/setup.ts +47 -8
- 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/utils.ts +7 -0
- 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/overview-C1DCTzzV.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/lifecycle-manager.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
+
import { framed } from "./hub-metrics";
|
|
2
|
+
import { upsertManagedAgentStateAsync, updateManagedAgentStateAsync } from "./db/lifecycle-tail-async";
|
|
3
|
+
import { createActivityEventAsync } from "./db/activity-async";
|
|
4
|
+
import { createCommandAsync, prepareCommandWriteAsync, submitPreparedCommandAsync } from "./commands-write";
|
|
1
5
|
import { timePostBindPhase } from "./post-bind-startup";
|
|
2
6
|
import { requestAgentExitCleanup } from "./agent-exit-cleanup";
|
|
3
7
|
import { hostSpawnsDrained } from "./db/spawn-host-cap";
|
|
4
|
-
|
|
5
|
-
import { createCommandAsync, prepareCommandWriteAsync } from "./commands-write";
|
|
8
|
+
|
|
6
9
|
import { errMessage, fireAndForget, guardedInterval } from "@humwick/sdk";
|
|
7
10
|
import { agentProviderState } from "./provider-state";
|
|
8
|
-
import {
|
|
9
|
-
import { getManagedAgentState, listSpawnPolicies
|
|
11
|
+
import { getAgent, getDb, getOrchestrator, listOrchestrators, listWorkspaces, pendingOwnRelayRunIds } from "./db";
|
|
12
|
+
import { getManagedAgentState, listSpawnPolicies } from "./config-store"; import { managedSpawnReservationCurrent, restoreDrainedSpawnReservation } from "./managed-spawn-reservation";
|
|
10
13
|
import { emitRelayEvent } from "./events";
|
|
11
14
|
import { alwaysReloadTags, reconcileLifecycleContextPressure, requestAgentCompact } from "./lifecycle-context-pressure";
|
|
12
15
|
import { escalateManagedSpawnFailure, escalateOfflineOrchestrator } from "./managed-policy-escalation";
|
|
@@ -82,7 +85,7 @@ export class LifecycleManager {
|
|
|
82
85
|
|
|
83
86
|
start(): void {
|
|
84
87
|
if (this.timer) return;
|
|
85
|
-
const tick = () => timePostBindPhase("lifecycle.tick", () => this.tick());
|
|
88
|
+
const tick = framed("timer lifecycle", () => timePostBindPhase("lifecycle.tick", () => this.tick()));
|
|
86
89
|
void fireAndForget("[lifecycle] tick", tick);
|
|
87
90
|
this.timer = guardedInterval("[lifecycle] tick", this.tickMs, tick);
|
|
88
91
|
}
|
|
@@ -102,13 +105,13 @@ export class LifecycleManager {
|
|
|
102
105
|
// #2171 — validation instructions must come from the policy's launch host. The tick primes
|
|
103
106
|
// remote land-gate files once per host so synchronous spawn composition reads current cache.
|
|
104
107
|
await primeLandGatesForPolicies(policies);
|
|
105
|
-
const contextHandled = this.reconcileContextPressure(policies);
|
|
108
|
+
const contextHandled = (await this.reconcileContextPressure(policies));
|
|
106
109
|
for (const policy of policies) {
|
|
107
110
|
await this.reconcilePolicy(policy, contextHandled);
|
|
108
111
|
}
|
|
109
112
|
}
|
|
110
113
|
|
|
111
|
-
onMessageForPolicy(policyName: string):
|
|
114
|
+
async onMessageForPolicy(policyName: string): Promise<PolicySpawnOutcome> {
|
|
112
115
|
const policy = this.loadPolicies().find((item) => item.name === policyName);
|
|
113
116
|
if (!policy) return { woke: false, reason: `no spawn policy '${policyName}'` };
|
|
114
117
|
if (policy.mode !== "on-demand") return { woke: false, reason: `spawn policy '${policyName}' is not on-demand` };
|
|
@@ -139,8 +142,7 @@ export class LifecycleManager {
|
|
|
139
142
|
// FAILURE, not a success. Propagate it so callers don't stamp a false hand-off.
|
|
140
143
|
// Explicit wake (watchdog / auto-merge / cooldown re-wake): exempt from the respawn-rate backstop
|
|
141
144
|
// — its own STEWARD_HANDOFF_REWAKE_MAX + wake cooldown already bound it (#1745).
|
|
142
|
-
const command = this.spawnAgent(policy, "message-trigger", { enforceStewardRate: false });
|
|
143
|
-
if (command instanceof Promise) return this.policyWakeOutcome(policyName, command, state);
|
|
145
|
+
const command = (await this.spawnAgent(policy, "message-trigger", { enforceStewardRate: false }));
|
|
144
146
|
if (!command) return { woke: false, reason: `steward spawn failed for '${policyName}' (${this.policyWakeFailureReason(policyName, state)})` };
|
|
145
147
|
return { woke: true, via: "spawned", command };
|
|
146
148
|
}
|
|
@@ -186,13 +188,13 @@ export class LifecycleManager {
|
|
|
186
188
|
// drifted registration copies (epic #342). Only the orchestrator-report projection
|
|
187
189
|
// below still enters managed-running from the lifecycle manager.
|
|
188
190
|
|
|
189
|
-
onOrchestratorManagedAgentsReported(orchestratorId: string, agents: ManagedAgent[], exitedAgents: ManagedSessionExitDiagnostics[] = []): void {
|
|
191
|
+
async onOrchestratorManagedAgentsReported(orchestratorId: string, agents: ManagedAgent[], exitedAgents: ManagedSessionExitDiagnostics[] = []): Promise<void> {
|
|
190
192
|
for (const agent of agents) {
|
|
191
193
|
if (!agent.policyName || !agent.spawnRequestId) continue;
|
|
192
194
|
const state = getManagedAgentState(agent.policyName);
|
|
193
195
|
if (!state || state.spawnRequestId !== agent.spawnRequestId) continue;
|
|
194
196
|
// Same came-up-running core the registration transports use — one home, no drift.
|
|
195
|
-
markManagedAgentRunning(
|
|
197
|
+
(await markManagedAgentRunning(
|
|
196
198
|
{
|
|
197
199
|
policyName: agent.policyName,
|
|
198
200
|
spawnRequestId: agent.spawnRequestId,
|
|
@@ -202,7 +204,7 @@ export class LifecycleManager {
|
|
|
202
204
|
},
|
|
203
205
|
authContextFromSystem(),
|
|
204
206
|
{ now: this.now },
|
|
205
|
-
);
|
|
207
|
+
));
|
|
206
208
|
|
|
207
209
|
// Liveness reconciliation: the orchestrator just reported this process as
|
|
208
210
|
// running. If the relay record says offline, the two truths disagree
|
|
@@ -211,12 +213,12 @@ export class LifecycleManager {
|
|
|
211
213
|
if (reportedAgentId) {
|
|
212
214
|
const relayAgent = getAgent(reportedAgentId);
|
|
213
215
|
if (relayAgent && relayAgent.status === "offline") {
|
|
214
|
-
this.emitLivenessMismatch(
|
|
216
|
+
(await this.emitLivenessMismatch(
|
|
215
217
|
reportedAgentId,
|
|
216
218
|
agent.policyName,
|
|
217
219
|
agent.spawnRequestId,
|
|
218
220
|
"orchestrator reports the process running but relay marked it offline",
|
|
219
|
-
);
|
|
221
|
+
));
|
|
220
222
|
}
|
|
221
223
|
}
|
|
222
224
|
}
|
|
@@ -238,23 +240,23 @@ export class LifecycleManager {
|
|
|
238
240
|
(state.tmuxSession && agent.tmuxSession === state.tmuxSession) ||
|
|
239
241
|
(agent.policyName === policy.name && (!state.spawnRequestId || agent.spawnRequestId === state.spawnRequestId))
|
|
240
242
|
));
|
|
241
|
-
this.markPolicyFailure(policy, state, exited?.lastError ?? "orchestrator session disappeared", { exited });
|
|
243
|
+
(await this.markPolicyFailure(policy, state, exited?.lastError ?? "orchestrator session disappeared", { exited }));
|
|
242
244
|
} else if (state.status === "stopping" && !reported) {
|
|
243
|
-
const next =
|
|
245
|
+
const next = (await updateManagedAgentStateAsync(policy.name, {
|
|
244
246
|
status: "stopped",
|
|
245
247
|
agentId: undefined,
|
|
246
248
|
tmuxSession: undefined,
|
|
247
249
|
lastStopAt: this.now(),
|
|
248
|
-
});
|
|
249
|
-
if (next) this.emitState(next);
|
|
250
|
+
}));
|
|
251
|
+
if (next) (await this.emitState(next));
|
|
250
252
|
}
|
|
251
253
|
}
|
|
252
254
|
}
|
|
253
255
|
|
|
254
|
-
onAgentDisappeared(agentId: string): void {
|
|
256
|
+
async onAgentDisappeared(agentId: string): Promise<void> {
|
|
255
257
|
// Reconcile the agent's worktrees before policy handling — this runs for
|
|
256
258
|
// every agent (managed or not), so it must not depend on a policy match.
|
|
257
|
-
this.reconcileWorkspacesForAgent(agentId);
|
|
259
|
+
(await this.reconcileWorkspacesForAgent(agentId));
|
|
258
260
|
const policy = this.loadPolicies().find((item) => getManagedAgentState(item.name)?.agentId === agentId);
|
|
259
261
|
if (!policy) {
|
|
260
262
|
const agent = getAgent(agentId);
|
|
@@ -264,23 +266,23 @@ export class LifecycleManager {
|
|
|
264
266
|
const state = getManagedAgentState(policy.name);
|
|
265
267
|
if (!state) return;
|
|
266
268
|
if (state.status === "stopping") {
|
|
267
|
-
const next =
|
|
269
|
+
const next = (await updateManagedAgentStateAsync(policy.name, {
|
|
268
270
|
status: "stopped",
|
|
269
271
|
agentId: undefined,
|
|
270
272
|
tmuxSession: undefined,
|
|
271
273
|
lastStopAt: this.now(),
|
|
272
|
-
});
|
|
273
|
-
if (next) this.emitState(next);
|
|
274
|
+
}));
|
|
275
|
+
if (next) (await this.emitState(next));
|
|
274
276
|
return;
|
|
275
277
|
}
|
|
276
|
-
this.markPolicyFailure(policy, state, "agent disappeared");
|
|
278
|
+
(await this.markPolicyFailure(policy, state, "agent disappeared"));
|
|
277
279
|
if (isStewardPolicy(policy)) void retryStewardLandsAfterSlotFreed().catch(error => console.warn(`[steward] slot recovery failed: ${errMessage(error)}`));
|
|
278
280
|
}
|
|
279
281
|
|
|
280
|
-
onConfigChanged(namespace: string, key: string): void {
|
|
282
|
+
async onConfigChanged(namespace: string, key: string): Promise<void> {
|
|
281
283
|
if (namespace !== "spawn-policy") return;
|
|
282
284
|
const policy = this.loadPolicies().find((item) => item.name === key);
|
|
283
|
-
if (policy)
|
|
285
|
+
if (policy) await fireAndForget(`[lifecycle] reconcile ${policy.name}`, async () => (await this.reconcilePolicy(policy, (await this.reconcileContextPressure([policy])))));
|
|
284
286
|
}
|
|
285
287
|
|
|
286
288
|
onRelayUpdated(_newVersion: string): void {
|
|
@@ -289,9 +291,16 @@ export class LifecycleManager {
|
|
|
289
291
|
}
|
|
290
292
|
}
|
|
291
293
|
|
|
292
|
-
spawnAgent(policy: SpawnPolicy, reason = "reconcile", opts: { enforceStewardRate?: boolean } = {}):
|
|
294
|
+
spawnAgent(policy: SpawnPolicy, reason = "reconcile", opts: { enforceStewardRate?: boolean } = {}): Promise<Command | null> {
|
|
293
295
|
const pending = this.pendingSpawnPreparations.get(policy.name);
|
|
294
296
|
if (pending) return pending;
|
|
297
|
+
const preparation = this.prepareSpawn(policy, reason, opts);
|
|
298
|
+
this.pendingSpawnPreparations.set(policy.name, preparation);
|
|
299
|
+
void preparation.finally(() => { if (this.pendingSpawnPreparations.get(policy.name) === preparation) this.pendingSpawnPreparations.delete(policy.name); }).catch(() => {});
|
|
300
|
+
return preparation;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
private async prepareSpawn(policy: SpawnPolicy, reason: string, opts: { enforceStewardRate?: boolean }): Promise<Command | null> {
|
|
295
304
|
// #1745 — universal steward chokepoint: every spawn path (message-trigger, reconcile respawn,
|
|
296
305
|
// backoff-expired, always-on) funnels through here, so the kill-switch + per-repo cap gate lives
|
|
297
306
|
// here as the last line of defence. A denied steward spawn returns null WITHOUT churning managed
|
|
@@ -310,7 +319,7 @@ export class LifecycleManager {
|
|
|
310
319
|
}
|
|
311
320
|
}
|
|
312
321
|
// #2656 — a disabled provider parks the policy (visible reason, no backoff); a later tick resumes it.
|
|
313
|
-
const providerOff = managedPolicyProviderDisabledMessage(policy); if (providerOff) { const parked = parkManagedPolicyForDisabledProvider(policy, providerOff); if (parked) this.emitState(parked, `spawn skipped: ${providerOff}`); return null; }
|
|
322
|
+
const providerOff = managedPolicyProviderDisabledMessage(policy); if (providerOff) { const parked = (await parkManagedPolicyForDisabledProvider(policy, providerOff)); if (parked) (await this.emitState(parked, `spawn skipped: ${providerOff}`)); return null; }
|
|
314
323
|
const orch = getOrchestrator(policy.orchestratorId);
|
|
315
324
|
if (!orch || orch.status !== "online") {
|
|
316
325
|
const state = getManagedAgentState(policy.name) ?? {
|
|
@@ -322,45 +331,42 @@ export class LifecycleManager {
|
|
|
322
331
|
consecutiveFailures: 0,
|
|
323
332
|
updatedAt: this.now(),
|
|
324
333
|
};
|
|
325
|
-
this.markBackoff(policy, state, "orchestrator offline");
|
|
334
|
+
(await this.markBackoff(policy, state, "orchestrator offline"));
|
|
326
335
|
const next = getManagedAgentState(policy.name);
|
|
327
|
-
if (next) escalateOfflineOrchestrator(policy, next, orch);
|
|
336
|
+
if (next) void fireAndForget(`[lifecycle] escalate ${policy.name}`, () => escalateOfflineOrchestrator(policy, next, orch));
|
|
328
337
|
return null;
|
|
329
338
|
}
|
|
330
339
|
if (hostSpawnsDrained(orch.agentId)) return null;
|
|
331
340
|
const spawnRequestId = generateSpawnRequestId(); const policySnapshot = JSON.stringify(policy);
|
|
332
341
|
// Reserve `starting` before an async parameter build. A second queued wake can then observe
|
|
333
342
|
// the reservation instead of minting a second request id while provisioning resolves.
|
|
334
|
-
const priorState = getManagedAgentState(policy.name); const reserved =
|
|
335
|
-
this.emitState(reserved, `spawn: ${reason}`);
|
|
336
|
-
const releaseReservation = (error: unknown): void => { const current = getManagedAgentState(policy.name); if (current?.spawnRequestId === spawnRequestId) { if (current.status === "starting") this.markPolicyFailure(policy, current, errMessage(error)); } };
|
|
343
|
+
const priorState = getManagedAgentState(policy.name); const reserved = (await upsertManagedAgentStateAsync({ policyName: policy.name, status: "starting", orchestratorId: policy.orchestratorId, provider: policy.provider, spawnRequestId, lastSpawnAt: this.now(), restartCount: priorState?.restartCount ?? 0, consecutiveFailures: priorState?.consecutiveFailures ?? 0 }));
|
|
344
|
+
(await this.emitState(reserved, `spawn: ${reason}`));
|
|
345
|
+
const releaseReservation = async (error: unknown): Promise<void> => { const current = getManagedAgentState(policy.name); if (current?.spawnRequestId === spawnRequestId) { if (current.status === "starting") (await this.markPolicyFailure(policy, current, errMessage(error))); } };
|
|
337
346
|
let params: Record<string, unknown> | Promise<Record<string, unknown>>;
|
|
338
347
|
try { params = this.buildManagedSpawnParams(policy, spawnRequestId, { createdBy: "lifecycle-manager", authority: SYSTEM_LAUNCH, requestedAt: this.now() }); }
|
|
339
|
-
catch (error) { releaseReservation(error); return null; }
|
|
348
|
+
catch (error) { (await releaseReservation(error)); return null; }
|
|
340
349
|
const finish = async (spawnParams: Record<string, unknown>): Promise<Command | null> => {
|
|
341
350
|
const prepared = await prepareCommandWriteAsync({ type: "agent.spawn", source: "system", target: orch.agentId,
|
|
342
351
|
correlationId: spawnRequestId, params: { ...spawnParams, reason } }, { hostCap: { exempt: "managed-policy" } });
|
|
343
352
|
// Re-check after all async launch preparation, including vault reads (#3574).
|
|
344
353
|
if (!managedSpawnReservationCurrent(policy, policySnapshot, spawnRequestId)) return null;
|
|
345
|
-
if (hostSpawnsDrained(orch.agentId)) { restoreDrainedSpawnReservation(policy, spawnRequestId, priorState); return null; }
|
|
346
|
-
const command =
|
|
354
|
+
if (hostSpawnsDrained(orch.agentId)) { (await restoreDrainedSpawnReservation(policy, spawnRequestId, priorState)); return null; }
|
|
355
|
+
const command = (await submitPreparedCommandAsync(prepared));
|
|
347
356
|
emitCommandEvent(command, "command.requested");
|
|
348
357
|
// #1745 — record the actual spawn so the respawn-rate backstop can bound a repeatedly-dying
|
|
349
358
|
// steward (registers, then exits on quota — never a spawn failure, so backoff never engages).
|
|
350
359
|
if (isStewardPolicy(policy)) noteStewardSpawn(policy.name, this.now());
|
|
351
360
|
return command;
|
|
352
361
|
};
|
|
353
|
-
|
|
354
|
-
this.pendingSpawnPreparations.set(policy.name, preparation);
|
|
355
|
-
void preparation.finally(() => { if (this.pendingSpawnPreparations.get(policy.name) === preparation) this.pendingSpawnPreparations.delete(policy.name); }).catch(() => { /* preparation never rejects: it catches above */ });
|
|
356
|
-
return preparation;
|
|
362
|
+
return Promise.resolve(params).then(finish).catch(async (error) => { await releaseReservation(error); return null; });
|
|
357
363
|
}
|
|
358
364
|
|
|
359
|
-
stopAgent(policy: SpawnPolicy, graceful = true, reason = "reconcile-stop"): Command | null {
|
|
365
|
+
async stopAgent(policy: SpawnPolicy, graceful = true, reason = "reconcile-stop"): Promise<Command | null> {
|
|
360
366
|
const orch = getOrchestrator(policy.orchestratorId);
|
|
361
367
|
if (!orch) return null;
|
|
362
368
|
const state = getManagedAgentState(policy.name);
|
|
363
|
-
const next =
|
|
369
|
+
const next = (await upsertManagedAgentStateAsync({
|
|
364
370
|
policyName: policy.name,
|
|
365
371
|
status: "stopping",
|
|
366
372
|
agentId: state?.agentId,
|
|
@@ -372,9 +378,9 @@ export class LifecycleManager {
|
|
|
372
378
|
lastStopAt: this.now(),
|
|
373
379
|
restartCount: state?.restartCount ?? 0,
|
|
374
380
|
consecutiveFailures: state?.consecutiveFailures ?? 0,
|
|
375
|
-
});
|
|
376
|
-
this.emitState(next, `stop: ${reason}`);
|
|
377
|
-
const command =
|
|
381
|
+
}));
|
|
382
|
+
(await this.emitState(next, `stop: ${reason}`));
|
|
383
|
+
const command = (await createCommandAsync({
|
|
378
384
|
type: "agent.shutdown",
|
|
379
385
|
source: "system",
|
|
380
386
|
target: orch.agentId,
|
|
@@ -392,7 +398,7 @@ export class LifecycleManager {
|
|
|
392
398
|
requestedBy: "lifecycle-manager",
|
|
393
399
|
requestedAt: this.now(),
|
|
394
400
|
},
|
|
395
|
-
});
|
|
401
|
+
}));
|
|
396
402
|
emitCommandEvent(command, "command.requested");
|
|
397
403
|
return command;
|
|
398
404
|
}
|
|
@@ -404,7 +410,7 @@ export class LifecycleManager {
|
|
|
404
410
|
const restartRequestId = generateSpawnRequestId();
|
|
405
411
|
const restartSpawn = buildManagedSpawnParamsAsync(policy, restartRequestId, { createdBy: "lifecycle-manager", authority: SYSTEM_LAUNCH, requestedAt: this.now(), ...(state?.agentId ? { identityAgentId: state.agentId } : {}) }); const finish = async (spawnParams: Record<string, unknown>): Promise<Command | null> => {
|
|
406
412
|
if (hostSpawnsDrained(orch.agentId)) return null;
|
|
407
|
-
const restarted =
|
|
413
|
+
const restarted = (await upsertManagedAgentStateAsync({
|
|
408
414
|
policyName: policy.name,
|
|
409
415
|
status: "stopping",
|
|
410
416
|
agentId: state?.agentId,
|
|
@@ -416,8 +422,8 @@ export class LifecycleManager {
|
|
|
416
422
|
lastStopAt: this.now(),
|
|
417
423
|
restartCount: (state?.restartCount ?? 0) + 1,
|
|
418
424
|
consecutiveFailures: state?.consecutiveFailures ?? 0,
|
|
419
|
-
});
|
|
420
|
-
this.emitState(restarted, `restart: ${reason}`);
|
|
425
|
+
}));
|
|
426
|
+
(await this.emitState(restarted, `restart: ${reason}`));
|
|
421
427
|
const command = await createCommandAsync({ type: "agent.restart",
|
|
422
428
|
source: "system",
|
|
423
429
|
target: orch.agentId,
|
|
@@ -451,7 +457,7 @@ export class LifecycleManager {
|
|
|
451
457
|
if (!state) {
|
|
452
458
|
if (enabled && policy.mode === "always-on") await this.spawnAgent(policy, "always-on");
|
|
453
459
|
else if (enabled && hasQueuedPolicyWork(policy.name)) await this.spawnAgent(policy, "message-trigger");
|
|
454
|
-
else this.ensureStoppedState(policy);
|
|
460
|
+
else (await this.ensureStoppedState(policy));
|
|
455
461
|
return;
|
|
456
462
|
}
|
|
457
463
|
|
|
@@ -460,7 +466,7 @@ export class LifecycleManager {
|
|
|
460
466
|
// #1021 A3 — a never-registered spawn has no exit diagnostics, so isFastFailStorm
|
|
461
467
|
// can never trip and it would back off/retry forever in silence. Flag it so the
|
|
462
468
|
// escalation fires once it has failed repeatedly.
|
|
463
|
-
this.markPolicyFailure(policy, state, "spawn timed out before registration", { registerTimeout: true });
|
|
469
|
+
(await this.markPolicyFailure(policy, state, "spawn timed out before registration", { registerTimeout: true }));
|
|
464
470
|
}
|
|
465
471
|
return;
|
|
466
472
|
}
|
|
@@ -481,13 +487,13 @@ export class LifecycleManager {
|
|
|
481
487
|
const unconfirmedDead = agent?.meta?.lifecycleAction === "kill-failed" || managedRunningAgentAlive(agent);
|
|
482
488
|
if (!unconfirmedDead) {
|
|
483
489
|
this.stopRetries.delete(policy.name);
|
|
484
|
-
const next =
|
|
490
|
+
const next = (await updateManagedAgentStateAsync(policy.name, {
|
|
485
491
|
status: "stopped",
|
|
486
492
|
agentId: undefined,
|
|
487
493
|
tmuxSession: undefined,
|
|
488
494
|
lastStopAt: this.now(),
|
|
489
|
-
});
|
|
490
|
-
if (next) this.emitState(next);
|
|
495
|
+
}));
|
|
496
|
+
if (next) (await this.emitState(next));
|
|
491
497
|
} else if (isStewardPolicy(policy) && agent && (agent.status === "busy" || pendingOwnRelayRunIds(agent, this.now()).length > 0 || this.holdsActiveWorkspaceClaim(agent.id))) {
|
|
492
498
|
// #1761 — DEFER the forceful escalation while the steward is genuinely WORKING. Within the
|
|
493
499
|
// STOP_TIMEOUT window a `stopping` policy still reads managedProcessActive, so
|
|
@@ -511,7 +517,7 @@ export class LifecycleManager {
|
|
|
511
517
|
const retries = (this.stopRetries.get(policy.name) ?? 0) + 1;
|
|
512
518
|
if (retries <= MAX_STEWARD_STOP_RETRIES) {
|
|
513
519
|
this.stopRetries.set(policy.name, retries);
|
|
514
|
-
this.stopAgent(policy, false, `stop-retry-${retries} (unconfirmed dead after ${Math.round(STOP_TIMEOUT_MS / 1000)}s)`);
|
|
520
|
+
(await this.stopAgent(policy, false, `stop-retry-${retries} (unconfirmed dead after ${Math.round(STOP_TIMEOUT_MS / 1000)}s)`));
|
|
515
521
|
} else {
|
|
516
522
|
// Budget exhausted — release the policy from `stopping` to `stopped` and let go of the
|
|
517
523
|
// handle. This is now SAFE (unlike pre-#1745, when clearing the handle let a duplicate
|
|
@@ -521,13 +527,13 @@ export class LifecycleManager {
|
|
|
521
527
|
// deliberately no-ops on `stopping`, so transition directly here.
|
|
522
528
|
console.warn(`[lifecycle] steward '${policy.name}' stop did not confirm dead after ${MAX_STEWARD_STOP_RETRIES} forceful attempts; releasing the handle (agent cap + orphan reaper now own the zombie)`);
|
|
523
529
|
this.stopRetries.delete(policy.name);
|
|
524
|
-
const next =
|
|
530
|
+
const next = (await updateManagedAgentStateAsync(policy.name, {
|
|
525
531
|
status: "stopped",
|
|
526
532
|
agentId: undefined,
|
|
527
533
|
tmuxSession: undefined,
|
|
528
534
|
lastStopAt: this.now(),
|
|
529
|
-
});
|
|
530
|
-
if (next) this.emitState(next, "stop-retry exhausted: releasing handle");
|
|
535
|
+
}));
|
|
536
|
+
if (next) (await this.emitState(next, "stop-retry exhausted: releasing handle"));
|
|
531
537
|
}
|
|
532
538
|
}
|
|
533
539
|
}
|
|
@@ -540,28 +546,28 @@ export class LifecycleManager {
|
|
|
540
546
|
// stopping wedge (if any) gets its full MAX_STEWARD_STOP_RETRIES (#1761).
|
|
541
547
|
this.stopRetries.delete(policy.name);
|
|
542
548
|
if (!enabled) {
|
|
543
|
-
this.stopAgent(policy, true, "policy-disabled");
|
|
549
|
+
(await this.stopAgent(policy, true, "policy-disabled"));
|
|
544
550
|
return;
|
|
545
551
|
}
|
|
546
552
|
if (!managedRunningAgentAlive(agent)) {
|
|
547
|
-
this.markPolicyFailure(policy, state, agentTerminalFailureMessage(agent) ?? "agent offline");
|
|
553
|
+
(await this.markPolicyFailure(policy, state, agentTerminalFailureMessage(agent) ?? "agent offline"));
|
|
548
554
|
return;
|
|
549
555
|
}
|
|
550
|
-
this.resetBackoffAfterHealthyRun(policy, state);
|
|
556
|
+
(await this.resetBackoffAfterHealthyRun(policy, state));
|
|
551
557
|
if (policy.mode === "on-demand" && this.isIdle(policy, state)) {
|
|
552
|
-
this.stopAgent(policy, true, "idle-timeout");
|
|
558
|
+
(await this.stopAgent(policy, true, "idle-timeout"));
|
|
553
559
|
return;
|
|
554
560
|
}
|
|
555
561
|
if (contextHandled.has(agent.id)) return;
|
|
556
562
|
if (this.shouldCompact(agent)) {
|
|
557
|
-
requestAgentCompact({
|
|
563
|
+
(await requestAgentCompact({
|
|
558
564
|
agent,
|
|
559
565
|
reason: "context-threshold",
|
|
560
566
|
policyName: policy.name,
|
|
561
567
|
alwaysReload: alwaysReloadTags(agent.tags),
|
|
562
568
|
now: this.now,
|
|
563
569
|
hasActiveCommand: (target, type) => this.hasActiveCommand(target, type),
|
|
564
|
-
});
|
|
570
|
+
}));
|
|
565
571
|
return;
|
|
566
572
|
}
|
|
567
573
|
if (policy.scheduledDailyRestart && this.dailyRestartDue(policy, state) && this.isIdle(policy, state, 3600)) {
|
|
@@ -589,60 +595,60 @@ export class LifecycleManager {
|
|
|
589
595
|
}
|
|
590
596
|
}
|
|
591
597
|
|
|
592
|
-
private reconcileContextPressure(policies: SpawnPolicy[]): Set<string
|
|
593
|
-
return reconcileLifecycleContextPressure({
|
|
598
|
+
private async reconcileContextPressure(policies: SpawnPolicy[]): Promise<Set<string>> {
|
|
599
|
+
return (await reconcileLifecycleContextPressure({
|
|
594
600
|
policies,
|
|
595
601
|
now: this.now,
|
|
596
602
|
hasActiveCommand: (target, type) => this.hasActiveCommand(target, type),
|
|
597
|
-
});
|
|
603
|
+
}));
|
|
598
604
|
}
|
|
599
605
|
|
|
600
|
-
private ensureStoppedState(policy: SpawnPolicy): void {
|
|
601
|
-
const state =
|
|
606
|
+
private async ensureStoppedState(policy: SpawnPolicy): Promise<void> {
|
|
607
|
+
const state = (await upsertManagedAgentStateAsync({
|
|
602
608
|
policyName: policy.name,
|
|
603
609
|
status: "stopped",
|
|
604
610
|
orchestratorId: policy.orchestratorId,
|
|
605
611
|
provider: policy.provider,
|
|
606
|
-
});
|
|
607
|
-
this.emitState(state);
|
|
612
|
+
}));
|
|
613
|
+
(await this.emitState(state));
|
|
608
614
|
}
|
|
609
615
|
|
|
610
|
-
private markPolicyFailure(
|
|
616
|
+
private async markPolicyFailure(
|
|
611
617
|
policy: SpawnPolicy,
|
|
612
618
|
state: ManagedAgentState,
|
|
613
619
|
error: string,
|
|
614
620
|
opts: { exited?: ManagedSessionExitDiagnostics; registerTimeout?: boolean } = {},
|
|
615
|
-
): void {
|
|
621
|
+
): Promise<void> {
|
|
616
622
|
if (state.status === "stopping") return;
|
|
617
623
|
// Read the terminal reason from the adapter-surfaced typed provider state rather
|
|
618
624
|
// than re-parsing raw provider log text (#745 / #725 §4.4 leak #13).
|
|
619
625
|
const agentId = state.agentId || opts.exited?.agentId;
|
|
620
626
|
const modelUnavailable = agentId ? agentTerminalFailureMessage(getAgent(agentId)) : null;
|
|
621
627
|
if (modelUnavailable) {
|
|
622
|
-
this.markFailed(policy, state, modelUnavailable);
|
|
628
|
+
(await this.markFailed(policy, state, modelUnavailable));
|
|
623
629
|
return;
|
|
624
630
|
}
|
|
625
631
|
const failures = state.consecutiveFailures + 1;
|
|
626
632
|
if (isFastFailStorm(failures, opts.exited)) {
|
|
627
|
-
this.markFailed(policy, state, error);
|
|
633
|
+
(await this.markFailed(policy, state, error));
|
|
628
634
|
return;
|
|
629
635
|
}
|
|
630
|
-
this.markBackoff(policy, state, error, failures);
|
|
636
|
+
(await this.markBackoff(policy, state, error, failures));
|
|
631
637
|
// #1021 A3 — a register-never spawn never reaches markFailed (no exit diagnostics), so
|
|
632
638
|
// without this its escalation would never fire. Escalate once it has failed repeatedly.
|
|
633
639
|
if (isStewardPolicy(policy) && failures === MAX_FAST_FAILURES) {
|
|
634
640
|
const next = getManagedAgentState(policy.name);
|
|
635
|
-
if (next) escalateManagedSpawnFailure(policy, next, { phase: "spawn-backoff", error });
|
|
641
|
+
if (next) void fireAndForget(`[lifecycle] escalate ${policy.name}`, () => escalateManagedSpawnFailure(policy, next, { phase: "spawn-backoff", error }));
|
|
636
642
|
} else if (!isStewardPolicy(policy) && opts.registerTimeout && failures >= MAX_FAST_FAILURES) {
|
|
637
643
|
const next = getManagedAgentState(policy.name);
|
|
638
|
-
if (next) escalateManagedSpawnFailure(policy, next, { phase: "register-timeout", error });
|
|
644
|
+
if (next) void fireAndForget(`[lifecycle] escalate ${policy.name}`, () => escalateManagedSpawnFailure(policy, next, { phase: "register-timeout", error }));
|
|
639
645
|
}
|
|
640
646
|
}
|
|
641
647
|
|
|
642
|
-
private markBackoff(policy: SpawnPolicy, state: ManagedAgentState, error: string, failures = state.consecutiveFailures + 1): void {
|
|
648
|
+
private async markBackoff(policy: SpawnPolicy, state: ManagedAgentState, error: string, failures = state.consecutiveFailures + 1): Promise<void> {
|
|
643
649
|
if (state.status === "stopping") return;
|
|
644
650
|
const delay = this.backoffDelay(policy, state);
|
|
645
|
-
const next =
|
|
651
|
+
const next = (await upsertManagedAgentStateAsync({
|
|
646
652
|
policyName: policy.name,
|
|
647
653
|
status: "backoff",
|
|
648
654
|
agentId: undefined,
|
|
@@ -655,13 +661,13 @@ export class LifecycleManager {
|
|
|
655
661
|
consecutiveFailures: failures,
|
|
656
662
|
backoffUntil: this.now() + delay * 1000,
|
|
657
663
|
lastError: error,
|
|
658
|
-
});
|
|
659
|
-
this.emitState(next);
|
|
664
|
+
}));
|
|
665
|
+
(await this.emitState(next));
|
|
660
666
|
}
|
|
661
667
|
|
|
662
|
-
private markFailed(policy: SpawnPolicy, state: ManagedAgentState, error: string): void {
|
|
668
|
+
private async markFailed(policy: SpawnPolicy, state: ManagedAgentState, error: string): Promise<void> {
|
|
663
669
|
const failures = state.consecutiveFailures + 1;
|
|
664
|
-
const next =
|
|
670
|
+
const next = (await upsertManagedAgentStateAsync({
|
|
665
671
|
policyName: policy.name,
|
|
666
672
|
status: "failed",
|
|
667
673
|
agentId: undefined,
|
|
@@ -674,10 +680,10 @@ export class LifecycleManager {
|
|
|
674
680
|
consecutiveFailures: failures,
|
|
675
681
|
backoffUntil: isStewardPolicy(policy) ? this.now() + this.backoffDelay(policy, state) * 1000 : undefined,
|
|
676
682
|
lastError: error,
|
|
677
|
-
});
|
|
678
|
-
this.emitState(next);
|
|
683
|
+
}));
|
|
684
|
+
(await this.emitState(next));
|
|
679
685
|
// #1021 A3 — failed policies require an explicit wake/operator action. Surface the failure.
|
|
680
|
-
escalateManagedSpawnFailure(policy, next, { phase: "failed", error });
|
|
686
|
+
void fireAndForget(`[lifecycle] escalate ${policy.name}`, () => escalateManagedSpawnFailure(policy, next, { phase: "failed", error }));
|
|
681
687
|
}
|
|
682
688
|
|
|
683
689
|
private backoffDelay(policy: SpawnPolicy, state: ManagedAgentState | null): number {
|
|
@@ -687,16 +693,16 @@ export class LifecycleManager {
|
|
|
687
693
|
return schedule[index]!;
|
|
688
694
|
}
|
|
689
695
|
|
|
690
|
-
private resetBackoffAfterHealthyRun(policy: SpawnPolicy, state: ManagedAgentState): void {
|
|
696
|
+
private async resetBackoffAfterHealthyRun(policy: SpawnPolicy, state: ManagedAgentState): Promise<void> {
|
|
691
697
|
if (state.consecutiveFailures === 0) return;
|
|
692
698
|
const healthySince = state.healthySince ?? state.lastSpawnAt;
|
|
693
699
|
if (!healthySince || this.now() - healthySince < policy.backoff.resetAfterSeconds * 1000) return;
|
|
694
|
-
const next =
|
|
700
|
+
const next = (await updateManagedAgentStateAsync(policy.name, {
|
|
695
701
|
consecutiveFailures: 0,
|
|
696
702
|
backoffUntil: undefined,
|
|
697
703
|
lastError: undefined,
|
|
698
|
-
});
|
|
699
|
-
if (next) this.emitState(next);
|
|
704
|
+
}));
|
|
705
|
+
if (next) (await this.emitState(next));
|
|
700
706
|
}
|
|
701
707
|
|
|
702
708
|
private dailyRestartDue(_policy: SpawnPolicy, state: ManagedAgentState): boolean {
|
|
@@ -760,10 +766,10 @@ export class LifecycleManager {
|
|
|
760
766
|
// emitManagedState (src/services/managed-running.ts) so the registration service
|
|
761
767
|
// and this lifecycle reconciler emit identically (epic #342). We track the prior
|
|
762
768
|
// status per policy here only to compute the from→to for the transition row.
|
|
763
|
-
private emitState(state: ManagedAgentState, reason?: string): void {
|
|
769
|
+
private async emitState(state: ManagedAgentState, reason?: string): Promise<void> {
|
|
764
770
|
const previous = this.lastStatusByPolicy.get(state.policyName);
|
|
765
771
|
this.lastStatusByPolicy.set(state.policyName, state.status);
|
|
766
|
-
emitManagedState(state, previous, reason, this.now);
|
|
772
|
+
(await emitManagedState(state, previous, reason, this.now));
|
|
767
773
|
if (state.status === "stopped" && state.lastStopAt && this.loadPolicies().some(policy => policy.name === state.policyName && isStewardPolicy(policy))) {
|
|
768
774
|
void retryStewardLandsAfterSlotFreed().catch(error => console.warn(`[steward] slot recovery failed: ${errMessage(error)}`));
|
|
769
775
|
}
|
|
@@ -774,7 +780,7 @@ export class LifecycleManager {
|
|
|
774
780
|
// event (banner) and a persisted activity event (timeline). Observability only —
|
|
775
781
|
// it does not mutate agent status, since a live process may still have a dead
|
|
776
782
|
// relay connection.
|
|
777
|
-
private emitLivenessMismatch(agentId: string, policyName: string | undefined, spawnRequestId: string | undefined, detail: string): void {
|
|
783
|
+
private async emitLivenessMismatch(agentId: string, policyName: string | undefined, spawnRequestId: string | undefined, detail: string): Promise<void> {
|
|
778
784
|
emitRelayEvent({
|
|
779
785
|
type: "liveness.mismatch",
|
|
780
786
|
source: "lifecycle-manager",
|
|
@@ -783,7 +789,7 @@ export class LifecycleManager {
|
|
|
783
789
|
});
|
|
784
790
|
// #1912 §4 retained: orchestrator-report reconciliation is a synchronous projection loop;
|
|
785
791
|
// changing only its audit to a detached promise would make dashboard event order ambiguous.
|
|
786
|
-
|
|
792
|
+
(await createActivityEventAsync({
|
|
787
793
|
clientId: `liveness-mismatch-${agentId}-${this.now()}-${++this.transitionSeq}`,
|
|
788
794
|
kind: "state",
|
|
789
795
|
title: `Liveness mismatch: ${agentId}`,
|
|
@@ -792,11 +798,11 @@ export class LifecycleManager {
|
|
|
792
798
|
view: "managed-agents",
|
|
793
799
|
agentId,
|
|
794
800
|
metadata: { source: "lifecycle-manager", policyName, spawnRequestId, mismatch: true, detail },
|
|
795
|
-
});
|
|
801
|
+
}));
|
|
796
802
|
}
|
|
797
803
|
|
|
798
|
-
private reconcileWorkspacesForAgent(agentId: string): void {
|
|
799
|
-
requestAgentExitCleanup(agentId);
|
|
804
|
+
private async reconcileWorkspacesForAgent(agentId: string): Promise<void> {
|
|
805
|
+
(await requestAgentExitCleanup(agentId));
|
|
800
806
|
}
|
|
801
807
|
|
|
802
808
|
}
|