@humwick/server 0.130.1 → 0.130.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/bundled/prompts/manifest.json +1 -0
- package/bundled/prompts/task.hydration.md +1 -1
- package/bundled/roles/builder.md +1 -1
- package/docs/guides/sub-coordinators.md +12 -5
- package/docs/guides/tools-administration.md +4 -0
- package/docs/guides/tools-coordination.md +2 -0
- package/docs/guides/tools-tasks.md +8 -0
- package/docs/guides/workflows.md +74 -0
- package/docs/openapi.json +486 -4
- package/package.json +10 -18
- package/public/assets/{MessageBubble-BWpoBjl4.js → MessageBubble-Bq9kr21N.js} +2 -2
- package/public/assets/{PlanGraphPanel-C0auck3n.js → PlanGraphPanel-Dqiroy06.js} +2 -2
- package/public/assets/{TraceView-DBnOx7AQ.js → TraceView-DYU962-H.js} +2 -2
- package/public/assets/{VaultDecisionCard-0kp2oNBC.js → VaultDecisionCard-DhPfzioE.js} +2 -2
- package/public/assets/{activity-yLztXEBt.js → activity-DzCcQTee.js} +2 -2
- package/public/assets/{agent-lineage-BbJDR1dW.js → agent-lineage-SgDt9i3T.js} +2 -2
- package/public/assets/agent-liveness-Bq-s73jW.js +2 -0
- package/public/assets/{agent-name-CTZBrSD9.js → agent-name-CcY3Aijy.js} +2 -2
- package/public/assets/agent-profiles-cxtRBn6O.js +2 -0
- package/public/assets/{agent-project-badge-9TqzUUYE.js → agent-project-badge-DGYbIhaI.js} +2 -2
- package/public/assets/{agent-tools-D4n40pn8.js → agent-tools-DHbftV0N.js} +2 -2
- package/public/assets/{agent-type-icon-D6FUarOf.js → agent-type-icon-CY113sp-.js} +2 -2
- package/public/assets/{agents-BYDslkJc.js → agents-BPzY7IlQ.js} +2 -2
- package/public/assets/{analytics-B-XSbEMC.js → analytics-DENFPv_a.js} +2 -2
- package/public/assets/{artifact-viewer-DdWIfV6M.js → artifact-viewer-KRvSc7sl.js} +2 -2
- package/public/assets/{artifacts-DPN1q4pA.js → artifacts-C9gSmL3s.js} +2 -2
- package/public/assets/{artifacts-oBOqks-2.js → artifacts-DT-HkI5O.js} +2 -2
- package/public/assets/{automation-4KcRFXEu.js → automation-BsmjQhKD.js} +2 -2
- package/public/assets/{backlog-Cw9xPTCF.js → backlog-8NYH_62t.js} +2 -2
- package/public/assets/{busy-health-CTu32MZt.js → busy-health-D3hwvYb4.js} +2 -2
- package/public/assets/{channels-BiXzg1G9.js → channels-DCJ5WL7O.js} +2 -2
- package/public/assets/{chat-Ctk2qwvA.js → chat-DAIl357U.js} +3 -3
- package/public/assets/{code-preview-Bm1wWqAp.js → code-preview-CzrZfr9U.js} +2 -2
- package/public/assets/{connectors-C36ax4Vw.js → connectors-xTxtlyou.js} +2 -2
- package/public/assets/{cosmos-Jj9LK2Wf.js → cosmos-BpebFLK2.js} +2 -2
- package/public/assets/{crate-agent-H6S7-B9T.js → crate-agent-BHvI5wXC.js} +2 -2
- package/public/assets/{dependency-graph-Cd1E23wa.js → dependency-graph-DGT0o3wJ.js} +2 -2
- package/public/assets/{deploys-Bwfq146q.js → deploys-hqWOHSHE.js} +2 -2
- package/public/assets/{display-CfO7rTuF.js → display-CDeH4I8T.js} +2 -2
- package/public/assets/{files-DhhZI2Ih.js → files-BTeGVmTg.js} +2 -2
- package/public/assets/{fleet-B_rFEbnL.js → fleet-DgXtNgCa.js} +2 -2
- package/public/assets/{fleet-metrics-BkHP-P3R.js → fleet-metrics-BHEt5yc_.js} +2 -2
- package/public/assets/{formatted-body-Cm1RrzmN.js → formatted-body-MLtodyPp.js} +3 -3
- package/public/assets/{formatted-body-impl-DQiOuOD1.js → formatted-body-impl-CAe664Z8.js} +2 -2
- package/public/assets/{host-providers-dialog-CHqwXTov.js → host-providers-dialog-mapF4Fj9.js} +2 -2
- package/public/assets/index-CqqgOI5R.js +15 -0
- package/public/assets/index-MYAIwYTX.css +2 -0
- package/public/assets/{insights-fH1EL-qZ.js → insights-DNyf7IzF.js} +2 -2
- package/public/assets/{integrations-C5Oix6ng.js → integrations-DlYOHq7T.js} +2 -2
- package/public/assets/{issue-ref-chip-ODyondIa.js → issue-ref-chip-CeWBNWn7.js} +2 -2
- package/public/assets/{log-viewer-Cvfy6PW7.js → log-viewer-Cib8nqdE.js} +2 -2
- package/public/assets/{maintenance-D8CDH5wZ.js → maintenance-DSn1cPm7.js} +2 -2
- package/public/assets/{managed-agents-egllbpij.js → managed-agents-C3CkM81m.js} +2 -2
- package/public/assets/{markdown-preview-CYSFgVgK.js → markdown-preview-W4VQQPAv.js} +3 -3
- package/public/assets/{markdown-preview-impl-BteVIjX4.js → markdown-preview-impl-CMsTdhjq.js} +2 -2
- package/public/assets/{memory-C8WmXsyr.js → memory-BV17qtO4.js} +2 -2
- package/public/assets/{messages-BzQdqlO6.js → messages-Bm_1AqSA.js} +2 -2
- package/public/assets/{orchestrators-B1HxzkNw.js → orchestrators-Dg-vfP09.js} +2 -2
- package/public/assets/{overview-DCUnI4Z7.js → overview-DcYCrvlr.js} +2 -2
- package/public/assets/{pairs-ftCd2XcD.js → pairs-8o9nuG3V.js} +2 -2
- package/public/assets/{profile-icon-B2zH8DMH.js → profile-icon-BsRyBMea.js} +2 -2
- package/public/assets/project-profile-instructions-DETKFn_E.js +2 -0
- package/public/assets/projects-M_m6AHws.js +2 -0
- package/public/assets/{prompt-settings-Bftq9czX.js → prompt-settings-C_mNCgeL.js} +2 -2
- package/public/assets/provider-display-BEeLXC_D.js +2 -0
- package/public/assets/{registry-DWCU5c8q.js → registry-DDHHHE5N.js} +2 -2
- package/public/assets/run-card-Dt4I4jaP.js +2 -0
- package/public/assets/scroll-text-BKXS1ahr.js +2 -0
- package/public/assets/{secrets-C7GIUATz.js → secrets-BkVwxI5O.js} +2 -2
- package/public/assets/{service-access-settings-C3aujqTG.js → service-access-settings-Crq-6a-B.js} +2 -2
- package/public/assets/{settings-C6sZ9eBa.js → settings-CYcavMFu.js} +2 -2
- package/public/assets/shipping-H6gzEeZB.js +2 -0
- package/public/assets/{stats-V9Z-GxUd.js → stats-BJVeWkpV.js} +2 -2
- package/public/assets/{status-dot-CVv0iGHL.js → status-dot-BcHyw1Vw.js} +2 -2
- package/public/assets/store-DKPDIZBe.js +9 -0
- package/public/assets/{tasks-CXU75HRF.js → tasks-qJjlQPpx.js} +2 -2
- package/public/assets/{teams-BPf976zb.js → teams-Cd5Sk1uX.js} +2 -2
- package/public/assets/{terminal-viewer-DE9BOe-8.js → terminal-viewer-CpY5_m7W.js} +3 -3
- package/public/assets/{terminal-viewer-impl-D04pjmGh.js → terminal-viewer-impl-DI_2llFR.js} +2 -2
- package/public/assets/token-estimate-Co-Jdphh.js +2 -0
- package/public/assets/{use-agent-terminal-B1yR456R.js → use-agent-terminal-0yJA_buM.js} +2 -2
- package/public/assets/{use-decisions-D-S4tpDf.js → use-decisions-uJXHf34W.js} +2 -2
- package/public/assets/use-project-list-CpWl6eHQ.js +2 -0
- package/public/assets/{use-selectors-CnrAk2YP.js → use-selectors-BdxBW8mL.js} +2 -2
- package/public/assets/{user-avatar-nBFIcR4M.js → user-avatar-3IndfpOc.js} +2 -2
- package/public/assets/versioned-prompt-editor-CIVg7XB1.js +8 -0
- package/public/assets/{work-queue-TCjJxeT-.js → work-queue-B9rnLwHZ.js} +2 -2
- package/public/assets/{workflow-marker-Cf3Hf2fN.js → workflow-marker-X8wxyhzC.js} +2 -2
- package/public/assets/{workflows-CXQX20Qj.js → workflows-o5YyMFW7.js} +2 -2
- package/public/assets/{workspaces-qSYzKYMA.js → workspaces-CzEGoAng.js} +2 -2
- package/public/cosmos.html +4 -4
- package/public/index.html +31 -29
- package/runner/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/runner/plugins/claude/hooks/gate-run-guard.provisioned.mjs +31 -1
- package/runner/src/adapters/claude-effort.ts +2 -4
- package/runner/src/adapters/claude-headless.ts +1 -1
- package/runner/src/adapters/claude-launch-exit.ts +26 -0
- package/runner/src/adapters/claude-session-probe.ts +1 -1
- package/runner/src/adapters/claude-tmux.ts +38 -10
- package/runner/src/adapters/claude.ts +28 -75
- package/runner/src/adapters/codex-launch-config.ts +4 -5
- package/runner/src/adapters/codex.ts +1 -1
- package/runner/src/adapters/opencode-provider.ts +7 -22
- package/runner/src/adapters/opencode.ts +4 -4
- package/runner/src/adapters/provider-quota-harvest.ts +20 -71
- package/runner/src/agent-runner/credentials.ts +42 -12
- package/runner/src/agent-runner/inbox.ts +27 -0
- package/runner/src/agent-runner/lifecycle-milestones.ts +2 -4
- package/runner/src/agent-runner/liveness-exchange.ts +104 -0
- package/runner/src/bin/claude.ts +4 -0
- package/runner/src/bin/codex.ts +4 -0
- package/runner/src/bin/opencode.ts +4 -0
- package/runner/src/claude-system-prompt.ts +49 -0
- package/runner/src/index.ts +5 -2
- package/runner/src/launch-assembly.ts +14 -10
- package/runner/src/profile-home.ts +1 -1
- package/runner/src/project-instructions.ts +2 -2
- package/runner/src/provider-command.ts +18 -0
- package/runner/src/provider-setup.ts +35 -0
- package/runner/src/providers.ts +2 -1
- package/runner/src/runner-core.ts +32 -38
- package/runner/src/runner-helpers.ts +0 -8
- package/runner/src/session-scratch.ts +6 -2
- package/runner/src/spawn-input.ts +2 -1
- package/runner/src/test-run-dedup.ts +59 -56
- package/runner/test-support/provisioning-context.ts +4 -2
- package/runner/test-support/runner-harness.ts +2 -1
- package/scripts/cd-config.ts +8 -0
- package/scripts/gate-run-lease.ts +10 -7
- package/scripts/gate.sh +5 -1
- package/scripts/steward-policy-cleanup.ts +2 -2
- package/src/agent-authz.ts +2 -2
- package/src/agent-drive-arbiter.ts +3 -8
- package/src/agent-exit-cleanup-async.ts +2 -2
- package/src/agent-exit-cleanup.ts +23 -19
- package/src/agent-lifecycle-events.ts +112 -85
- package/src/agent-ref.ts +3 -2
- package/src/agent-status-events.ts +43 -14
- package/src/auth/password.ts +4 -3
- package/src/auth/session-refresh.ts +1 -1
- package/src/auth/session.test-fixture.ts +2 -2
- package/src/auth/session.ts +7 -7
- package/src/automations/crud.ts +8 -81
- package/src/automations/dispatch.ts +33 -58
- package/src/automations/index.ts +1 -1
- package/src/automations/persistence.ts +65 -0
- package/src/automations/precheck.ts +18 -16
- package/src/automations/read-async.ts +11 -0
- package/src/automations/reconcile.ts +30 -39
- package/src/automations/storage.ts +33 -10
- package/src/automations/write-async.ts +33 -0
- package/src/branch-land-notice.ts +93 -0
- package/src/branch-landed.ts +31 -98
- package/src/bus.ts +40 -39
- package/src/cd-deploy-notify.ts +32 -4
- package/src/cd-host-lag-notify.ts +7 -6
- package/src/ci/incidents.ts +2 -2
- package/src/ci/monitor.ts +5 -8
- package/src/ci/notifications.ts +4 -4
- package/src/ci/root-missing.ts +4 -9
- package/src/ci/transition-notify.ts +12 -44
- package/src/claude-app/oauth-http.ts +3 -3
- package/src/cli/cd-pauses.ts +19 -0
- package/src/cli/orchestrator.ts +1 -1
- package/src/cli/state.ts +2 -19
- package/src/cli/task-edit.ts +22 -0
- package/src/cli/task.ts +3 -1
- package/src/cli/workflow.ts +19 -4
- package/src/commands-db.ts +7 -7
- package/src/commands-write.ts +8 -0
- package/src/compaction-watch.ts +10 -8
- package/src/config-store-write.ts +13 -1
- package/src/config-store.ts +25 -14
- package/src/config.ts +4 -11
- package/src/connectors.ts +10 -8
- package/src/context-advisory.ts +22 -21
- package/src/db/activity-async.ts +6 -1
- package/src/db/activity-write-ops.ts +12 -1
- package/src/db/activity.ts +1 -14
- package/src/db/agent-action-write.ts +36 -0
- package/src/db/agent-control-async.ts +9 -0
- package/src/db/agent-control-write.ts +49 -0
- package/src/db/agent-effort-observe.ts +22 -0
- package/src/db/agent-meta.ts +14 -3
- package/src/db/agent-search.ts +1 -15
- package/src/db/agents-async.ts +59 -9
- package/src/db/agents-write-ops.ts +12 -3
- package/src/db/agents.ts +95 -65
- package/src/db/auth-identities.ts +2 -2
- package/src/db/automation-read-ops.ts +11 -0
- package/src/db/automation-write-ops.ts +46 -0
- package/src/db/blackboard.ts +2 -2
- package/src/db/browser-session-write.ts +32 -0
- package/src/db/bus-outbox-write-ops.ts +3 -1
- package/src/db/checkout-refresh-schema.ts +47 -0
- package/src/db/checkout-refresh.ts +5 -5
- package/src/db/ci-incidents-async.ts +5 -5
- package/src/db/ci-incidents-write-ops.ts +2 -2
- package/src/db/command-agent-profile-backfill.ts +39 -0
- package/src/db/command-agent-profiles.ts +5 -1
- package/src/db/command-retention.ts +126 -0
- package/src/db/command-row.ts +10 -2
- package/src/db/commands-list-query.ts +2 -0
- package/src/db/commands-planner-stats.test-fixture.ts +8 -0
- package/src/db/commands-read-ops.ts +16 -0
- package/src/db/commands-spawn-read.ts +1 -1
- package/src/db/config-store-write-ops.ts +7 -2
- package/src/db/connection.ts +1 -182
- package/src/db/context-carry-write.ts +74 -0
- package/src/db/continuation-archives-async.ts +5 -0
- package/src/db/continuation-archives-write-ops.ts +7 -0
- package/src/db/continuations.ts +6 -6
- package/src/db/db-error-registry.ts +12 -0
- package/src/db/db-writer-worker.ts +8 -1
- package/src/db/deploy-events-async.ts +1 -0
- package/src/db/deploy-events-read-ops.ts +2 -1
- package/src/db/deploy-events.ts +35 -4
- package/src/db/gateway.ts +26 -133
- package/src/db/history-retention-ops.ts +13 -0
- package/src/db/hosts-registration.ts +10 -2
- package/src/db/hosts.ts +9 -6
- package/src/db/inbox-async.ts +2 -2
- package/src/db/inbox-read-ops.ts +1 -1
- package/src/db/inbox.ts +9 -17
- package/src/db/index.ts +2 -0
- package/src/db/integrations-async.ts +8 -0
- package/src/db/integrations-ops.ts +15 -0
- package/src/db/integrations.ts +15 -21
- package/src/db/issue-associations.ts +2 -2
- package/src/db/issue-lifecycle.ts +3 -4
- package/src/db/issue-refs-async.ts +23 -0
- package/src/db/issue-refs-read-ops.ts +6 -0
- package/src/db/issue-refs-write-ops.ts +29 -0
- package/src/db/issue-refs.ts +15 -16
- package/src/db/kernel-event-log-schema.ts +2 -0
- package/src/db/land-boundaries.ts +51 -5
- package/src/db/land-gate-attestations.ts +2 -2
- package/src/db/landing-receipts.ts +2 -2
- package/src/db/lifecycle-context-write.ts +5 -0
- package/src/db/lifecycle-tail-async.ts +76 -0
- package/src/db/lifecycle-tail-write-ops.ts +62 -0
- package/src/db/lifecycle-write-window.ts +2 -1
- package/src/db/lineage-pair-dedupe-sql.ts +3 -3
- package/src/db/long-running-work.ts +2 -2
- package/src/db/main-connection-mode.ts +11 -0
- package/src/db/main-connection-writes.ts +41 -2
- package/src/db/maintenance-job-reconcile.ts +61 -0
- package/src/db/maintenance-job-runs-async.ts +14 -0
- package/src/db/maintenance-job-write-ops.ts +9 -0
- package/src/db/maintenance-pauses.ts +2 -2
- package/src/db/mappers.ts +2 -14
- package/src/db/merge-lease.ts +1 -15
- package/src/db/message-send.ts +4 -0
- package/src/db/messages.ts +31 -25
- package/src/db/migrations.ts +25 -16
- package/src/db/notification-write-ops.ts +19 -0
- package/src/db/operator-answer-write.ts +19 -0
- package/src/db/orchestrators.ts +14 -76
- package/src/db/pairs-async.ts +22 -1
- package/src/db/pairs-write-ops.ts +8 -3
- package/src/db/pairs.ts +42 -61
- package/src/db/plan-dispatch-schema.ts +5 -1
- package/src/db/plan-ready-notices.ts +43 -0
- package/src/db/plan-tools-include-migration.ts +36 -0
- package/src/db/plans-write-ops.ts +2 -0
- package/src/db/presence-buffer.ts +5 -0
- package/src/db/presence-loop.ts +18 -23
- package/src/db/presence-write.ts +0 -6
- package/src/db/project-entries-async.ts +14 -0
- package/src/db/project-entries-read-ops.ts +5 -1
- package/src/db/project-entries-write-ops.ts +8 -0
- package/src/db/project-entries.ts +15 -12
- package/src/db/project-journal.ts +2 -2
- package/src/db/project-profile-instructions.ts +50 -0
- package/src/db/project-trust-approvals.ts +2 -2
- package/src/db/prompt-templates.ts +4 -4
- package/src/db/prompt-versions.ts +9 -2
- package/src/db/provider-config-history.ts +8 -3
- package/src/db/provider-model-seed.ts +34 -0
- package/src/db/read-op-marshaling-fixtures.ts +23 -0
- package/src/db/read-ops.ts +8 -0
- package/src/db/retention.ts +13 -2
- package/src/db/review-publish-write.ts +8 -0
- package/src/db/routing-policy.ts +2 -3
- package/src/db/runtime-admin-async.ts +19 -0
- package/src/db/runtime-admin-write-ops.ts +36 -0
- package/src/db/runtime-tail-async.ts +288 -0
- package/src/db/runtime-tail-write-ops.ts +97 -0
- package/src/db/schema.ts +13 -4
- package/src/db/spawn-budget.ts +5 -0
- package/src/db/spawn-delegation-state.ts +11 -4
- package/src/db/spawn-delegation.ts +1 -11
- package/src/db/sql-audit-indexes.ts +3 -0
- package/src/db/stats-async.ts +9 -6
- package/src/db/task-entity.ts +28 -6
- package/src/db/task-list.ts +3 -1
- package/src/db/tasks.ts +1 -17
- package/src/db/team-claim-policy.ts +60 -0
- package/src/db/teams-async.ts +4 -0
- package/src/db/teams-write-ops.ts +4 -0
- package/src/db/terminal-events.ts +15 -0
- package/src/db/timer-cutover-bodies.ts +292 -0
- package/src/db/timer-cutover-core.ts +37 -278
- package/src/db/timer-cutover-state.ts +40 -0
- package/src/db/timer-cutover-write-ops.ts +1 -40
- package/src/db/timer-ingress.ts +7 -1
- package/src/db/token-db-write-ops.ts +19 -0
- package/src/db/token-standing-async.ts +12 -0
- package/src/db/token-standing.ts +21 -20
- package/src/db/token-usage-retention.ts +33 -0
- package/src/db/token-usage-write-ops.ts +1 -1
- package/src/db/token-usage.ts +4 -1
- package/src/db/user-invites-async.ts +13 -0
- package/src/db/user-invites.ts +3 -3
- package/src/db/users.ts +14 -6
- package/src/db/workflow-contact.ts +1 -1
- package/src/db/workflow-task-read-ops.ts +30 -0
- package/src/db/workspaces.ts +8 -5
- package/src/db/write-ops.ts +37 -12
- package/src/db/writer-fault-seam.ts +2 -9
- package/src/db/writer-fault-test-ops.ts +18 -0
- package/src/db/writer-gateway.ts +58 -56
- package/src/dev.ts +8 -3
- package/src/dispatch-availability.ts +10 -6
- package/src/ephemeral/{landing-ingress-proof-worker.ts → landing-ingress-proof.test-fixture.ts} +4 -2
- package/src/event-loop-lag.ts +4 -2
- package/src/event-loop-yield.ts +2 -2
- package/src/events.ts +10 -8
- package/src/host/disk-alert.ts +121 -0
- package/src/host-provider-store.ts +5 -4
- package/src/hub-metrics-report.ts +5 -1
- package/src/hub-metrics.ts +38 -18
- package/src/injection-sweep-pacing.ts +6 -8
- package/src/land-gate-notifications.ts +11 -10
- package/src/land-gate-queue-progress.ts +3 -3
- package/src/land-settle-dispatch.ts +52 -92
- package/src/lifecycle-context-pressure.ts +11 -10
- package/src/lifecycle-manager.ts +107 -100
- package/src/maintenance/breaker.ts +18 -16
- package/src/maintenance/cd-watcher.ts +3 -3
- package/src/maintenance/checkout-refresh.ts +18 -1
- package/src/maintenance/critical-job-watchdog.ts +19 -20
- package/src/maintenance/events.ts +3 -3
- package/src/maintenance/history-retention-job.ts +30 -0
- package/src/maintenance/index.ts +1 -0
- package/src/maintenance/jobs.ts +32 -69
- package/src/maintenance/long-running-work.ts +3 -1
- package/src/maintenance/offline-agent-prune-job.ts +28 -0
- package/src/maintenance/orphaned-sessions.ts +5 -4
- package/src/maintenance/pauses.ts +4 -10
- package/src/maintenance/plan-ready-notice-job.ts +71 -0
- package/src/maintenance/scheduler.ts +98 -137
- package/src/maintenance/stalled-delivery-pager.ts +10 -9
- package/src/maintenance/teams.ts +19 -30
- package/src/maintenance/workspaces.ts +18 -28
- package/src/managed-policy-escalation.ts +7 -7
- package/src/managed-policy.ts +32 -28
- package/src/managed-provider-gate.ts +5 -4
- package/src/managed-spawn-reservation.ts +5 -4
- package/src/mcp/index.ts +12 -9
- package/src/mcp/output-descriptions.ts +8 -8
- package/src/mcp/presentation.ts +6 -5
- package/src/mcp/project-profile-instructions.ts +32 -0
- package/src/mcp/runtime-output.ts +6 -1
- package/src/mcp/self-care-visibility.ts +2 -2
- package/src/mcp/spawn-targets-matrix.ts +10 -1
- package/src/mcp/tool-groups.ts +4 -3
- package/src/mcp/tool-roles.ts +81 -0
- package/src/mcp/tools-spawn.ts +4 -3
- package/src/mcp/tools-workspace.ts +1 -1
- package/src/mcp-agent-action.ts +1 -2
- package/src/mcp-blackboard-tools.ts +6 -5
- package/src/mcp-decision-tools.ts +7 -7
- package/src/mcp-egress-tools.ts +10 -9
- package/src/mcp-issue-activity-tools.ts +2 -2
- package/src/mcp-issue-association-tools.ts +4 -4
- package/src/mcp-issue-ref-tools.ts +13 -12
- package/src/mcp-maintenance-tools.ts +2 -2
- package/src/mcp-merge-tools.ts +5 -5
- package/src/mcp-notification-subscription-tools.ts +14 -15
- package/src/mcp-output-levels.test-fixture.ts +1 -1
- package/src/mcp-profile-trust-tools.ts +5 -5
- package/src/mcp-project-journal-tools.ts +4 -12
- package/src/mcp-project-tools.ts +17 -18
- package/src/mcp-provider-catalog.ts +2 -2
- package/src/mcp-routing-policy-tools.ts +3 -2
- package/src/mcp-task-tools.ts +11 -5
- package/src/mcp-team-template-tools.ts +3 -3
- package/src/mcp-team-tools.ts +6 -6
- package/src/mcp-workflow-tools.ts +13 -4
- package/src/memory-area-injection.ts +13 -12
- package/src/memory-boundary-capture.ts +6 -6
- package/src/memory-injection.ts +45 -43
- package/src/merge-pause-maintenance.ts +5 -4
- package/src/notification-router.ts +44 -17
- package/src/notification-types.ts +2 -1
- package/src/notify.ts +5 -5
- package/src/observed-reset-refresh.ts +4 -4
- package/src/operator-alarm.ts +23 -11
- package/src/project-ingest.ts +6 -6
- package/src/project-instructions.ts +12 -1
- package/src/project-profile-instruction-text.ts +6 -0
- package/src/project-profile-instructions.ts +20 -0
- package/src/project-trust.ts +12 -11
- package/src/prompt-resolver.ts +3 -3
- package/src/provider-catalog-store.ts +3 -49
- package/src/provider-config-store.ts +12 -11
- package/src/provider-model-seed.ts +1 -18
- package/src/provider-quota-async.ts +5 -7
- package/src/provider-quota-config-store.ts +5 -4
- package/src/provider-secrets.test-fixture.ts +3 -3
- package/src/provider-timeline-event.ts +4 -7
- package/src/quota-band-delivery.ts +2 -2
- package/src/recipe-runner.ts +6 -5
- package/src/repo-config-source.ts +10 -4
- package/src/retention-config-store.ts +4 -3
- package/src/reviewer-pipeline.ts +11 -10
- package/src/routes/_route.ts +4 -4
- package/src/routes/_shared.ts +13 -12
- package/src/routes/agent-effort.ts +5 -5
- package/src/routes/agent-heartbeat-quota.ts +23 -0
- package/src/routes/agent-keep.ts +1 -1
- package/src/routes/agent-profiles.ts +6 -6
- package/src/routes/agent-reporting.ts +1 -1
- package/src/routes/agent-self-effort.ts +5 -5
- package/src/routes/agent-sessions.ts +24 -24
- package/src/routes/agents-spawn.ts +2 -2
- package/src/routes/agents.ts +19 -121
- package/src/routes/auth.ts +14 -15
- package/src/routes/authority-audit.ts +2 -2
- package/src/routes/automations.ts +6 -5
- package/src/routes/channel-binding-delete.ts +1 -1
- package/src/routes/channel-output.ts +3 -3
- package/src/routes/claude-api-budget.ts +5 -5
- package/src/routes/commands-listing.ts +5 -1
- package/src/routes/commands.ts +31 -29
- package/src/routes/context-resets.ts +2 -2
- package/src/routes/continuation-archives.ts +2 -2
- package/src/routes/coordinator-teams.ts +1 -1
- package/src/routes/decisions.ts +2 -2
- package/src/routes/host-secret-files.ts +1 -1
- package/src/routes/hosts.ts +11 -11
- package/src/routes/inbox.ts +3 -2
- package/src/routes/index.ts +12 -2
- package/src/routes/integrations.ts +32 -56
- package/src/routes/issue-activity.ts +2 -2
- package/src/routes/issue-associations.ts +4 -4
- package/src/routes/issue-refs.ts +9 -9
- package/src/routes/kernel-timers-operator.ts +1 -1
- package/src/routes/memory.ts +1 -1
- package/src/routes/merges.ts +11 -11
- package/src/routes/messages.ts +23 -17
- package/src/routes/orchestrator-bootstrap.ts +2 -2
- package/src/routes/orchestrator-host-registration.ts +4 -2
- package/src/routes/orchestrator-host-utilization.ts +5 -3
- package/src/routes/orchestrator-proxy.ts +4 -4
- package/src/routes/orchestrator.ts +28 -19
- package/src/routes/pairs.ts +8 -8
- package/src/routes/project-profile-instructions.ts +27 -0
- package/src/routes/project-trust.ts +3 -3
- package/src/routes/projects.ts +16 -16
- package/src/routes/prompt-templates.ts +12 -12
- package/src/routes/provider-config.ts +6 -6
- package/src/routes/provider-quota-config.ts +2 -2
- package/src/routes/provider-quotas.ts +10 -10
- package/src/routes/run-command.ts +1 -1
- package/src/routes/secrets-backup.ts +2 -2
- package/src/routes/secrets-import.ts +1 -1
- package/src/routes/secrets-vault.ts +7 -7
- package/src/routes/settings.ts +6 -6
- package/src/routes/shipping.ts +9 -1
- package/src/routes/spawn-policy.ts +8 -7
- package/src/routes/sse.ts +2 -2
- package/src/routes/stats.ts +6 -6
- package/src/routes/task-http.ts +15 -1
- package/src/routes/task-issues.ts +11 -26
- package/src/routes/tasks.ts +22 -53
- package/src/routes/team-templates.ts +12 -12
- package/src/routes/teams-config.ts +2 -2
- package/src/routes/teams.ts +10 -10
- package/src/routes/tokens.ts +30 -22
- package/src/routes/users.ts +24 -24
- package/src/routes/viewer-read.ts +3 -3
- package/src/routes/web-tool-calls.ts +4 -4
- package/src/routes/workflows.ts +22 -7
- package/src/routes/workspaces.ts +17 -16
- package/src/routing-policy-normalize.ts +1 -2
- package/src/routing-policy-push.ts +6 -6
- package/src/routing-step-defaults.ts +0 -2
- package/src/runner-token-mint-limit.ts +63 -0
- package/src/runtime-grant.ts +21 -13
- package/src/runtime-tokens.ts +59 -35
- package/src/secrets-broker/config.ts +1 -1
- package/src/secrets-broker/service.ts +2 -2
- package/src/security.ts +16 -21
- package/src/self-resume-carry.ts +21 -110
- package/src/self-resume-supersede.ts +4 -3
- package/src/self-resume.ts +54 -66
- package/src/server-background.ts +2 -2
- package/src/server.ts +26 -24
- package/src/services/agent-action.ts +12 -31
- package/src/services/agent-effort.ts +7 -32
- package/src/services/agent-hang-watchdog-job.ts +2 -2
- package/src/services/agent-heartbeat.ts +166 -0
- package/src/services/agent-reporting.ts +1 -1
- package/src/services/browser-inventory.ts +3 -3
- package/src/services/browser-session-state.ts +3 -2
- package/src/services/browser-session.ts +21 -27
- package/src/services/bus-command-update.ts +9 -9
- package/src/services/checkout-refresh-state.ts +1 -0
- package/src/services/checkout-refresh.test-fixture.ts +3 -2
- package/src/services/command-host.ts +7 -2
- package/src/services/coordinator-digest.ts +3 -2
- package/src/services/dispatch-command.ts +12 -13
- package/src/services/effective-launch-driver.ts +14 -9
- package/src/services/host-changed-paths.test-fixture.ts +5 -6
- package/src/services/host-project-readiness.ts +2 -2
- package/src/services/host-providers.ts +1 -1
- package/src/services/host-utilization.ts +27 -4
- package/src/services/idle-agent-digest.ts +17 -12
- package/src/services/idle-epics.ts +9 -10
- package/src/services/interrupt-agent.ts +12 -9
- package/src/services/issue-activity.ts +3 -3
- package/src/services/issue-associations.ts +15 -18
- package/src/services/issue-lifecycle-comments.ts +3 -2
- package/src/services/issue-lifecycle.ts +69 -72
- package/src/services/issue-refs.ts +10 -15
- package/src/services/kernel-timers-cutover-chaos-worker.ts +11 -8
- package/src/services/kernel-timers-ingress-chaos-worker.ts +6 -1
- package/src/services/kernel-timers-ingress.ts +4 -4
- package/src/services/kernel-timers-message-authority-chaos-worker.ts +3 -10
- package/src/services/kernel-timers-operator-chaos-worker.ts +3 -2
- package/src/services/kernel-timers-outbox.ts +1 -1
- package/src/services/kernel-timers-stage10-operator.ts +1 -1
- package/src/services/kernel-timers.ts +4 -3
- package/src/services/land-gate-placement.ts +11 -2
- package/src/services/land-issue-relations.ts +5 -4
- package/src/services/land-restart-retry.ts +7 -6
- package/src/services/landed-ancestry.ts +25 -8
- package/src/services/legacy-landing-host.ts +4 -1
- package/src/services/legacy-landing-recovery.ts +8 -6
- package/src/services/managed-running.ts +17 -17
- package/src/services/memory-areas.ts +17 -53
- package/src/services/merge-pause.ts +9 -15
- package/src/services/operator-decisions.ts +37 -41
- package/src/services/orchestrator-registration-recovery.ts +6 -2
- package/src/services/orchestrator-upgrade.ts +14 -12
- package/src/services/permission-decision.ts +4 -3
- package/src/services/plan-ci-notice.ts +57 -0
- package/src/services/plan-ci-recovery.ts +2 -55
- package/src/services/plan-conformance.ts +4 -4
- package/src/services/plan-dispatch-policy.ts +10 -3
- package/src/services/plan-dispatch.ts +35 -14
- package/src/services/plan-graph.ts +39 -261
- package/src/services/plan-import.ts +1 -1
- package/src/services/plan-live-bindings.ts +8 -37
- package/src/services/plan-task-create.ts +1 -1
- package/src/services/plan-terminal-refs.ts +2 -12
- package/src/services/plan-wake-digest.ts +9 -3
- package/src/services/profile-trust.ts +6 -5
- package/src/services/project-config-read.ts +70 -0
- package/src/services/project-profile-instructions.ts +54 -0
- package/src/services/project.ts +11 -10
- package/src/services/prompt-templates.ts +6 -5
- package/src/services/provider-hold-nudge.ts +9 -9
- package/src/services/provider-hold-record.ts +13 -12
- package/src/services/provider-state-audit.ts +19 -18
- package/src/services/provisioning-harness/budget-baseline.json +4 -4
- package/src/services/provisioning-harness/driver.ts +1 -1
- package/src/services/provisioning-harness/fixture-matrix.ts +3 -3
- package/src/services/provisioning-harness/lifecycle.ts +24 -22
- package/src/services/provisioning-harness/prepare.ts +16 -17
- package/src/services/rate-limit-resume.ts +10 -9
- package/src/services/red-main-auto-revert.ts +7 -5
- package/src/services/red-main-controller-deps.ts +20 -3
- package/src/services/red-main-incident.ts +3 -1
- package/src/services/red-main-quarantine.ts +2 -3
- package/src/services/register-agent.ts +22 -22
- package/src/services/restart-project-role.ts +1 -1
- package/src/services/restart-spawn.ts +74 -61
- package/src/services/review-publish.ts +7 -24
- package/src/services/review-ref-reconcile.ts +29 -38
- package/src/services/runtime-dependency-alert.ts +27 -0
- package/src/services/scheduler-command.ts +11 -9
- package/src/services/scheduler.ts +5 -5
- package/src/services/self-care-state.ts +2 -1
- package/src/services/self-effort-grant.ts +5 -25
- package/src/services/self-effort.ts +5 -5
- package/src/services/send-message.ts +21 -34
- package/src/services/shutdown-agent.ts +17 -14
- package/src/services/spawn-agent.ts +25 -43
- package/src/services/spawn-chain-inspector.ts +7 -14
- package/src/services/spawn-cwd-placement.ts +21 -5
- package/src/services/spawn-issue-activity.ts +8 -6
- package/src/services/spawn-launch.ts +17 -1
- package/src/services/spawn-loss-escalation.ts +1 -1
- package/src/services/spawn-policy.ts +68 -0
- package/src/services/spawn-registration-watchdog.ts +2 -2
- package/src/services/spawn-repo-probe.ts +7 -5
- package/src/services/spawn-tree-cleanup.ts +8 -9
- package/src/services/steward-reaper.ts +4 -4
- package/src/services/task-context-hydration.ts +25 -1
- package/src/services/task-delivery.ts +20 -34
- package/src/services/task-dispatch.ts +3 -0
- package/src/services/task-entity.ts +40 -203
- package/src/services/task-issue-link.ts +13 -20
- package/src/services/task-issue-weave.ts +12 -11
- package/src/services/task-lifecycle.ts +27 -31
- package/src/services/task-repo-cwd.ts +37 -0
- package/src/services/task-review-hold.ts +4 -17
- package/src/services/task-semantic-events.ts +13 -11
- package/src/services/task-state-reconcile.ts +8 -17
- package/src/services/task-validation.ts +2 -2
- package/src/services/team-templates.ts +12 -11
- package/src/services/team.ts +31 -98
- package/src/services/terminal-provider-exit.ts +6 -5
- package/src/services/timer-message-fire-chaos-worker.ts +7 -3
- package/src/services/timer-message-fire-outbox.ts +1 -1
- package/src/services/transient-agent-reaper.ts +25 -20
- package/src/services/turn-reconcile-audit.ts +9 -9
- package/src/services/user-onboarding.ts +8 -6
- package/src/services/user-profile.ts +6 -9
- package/src/services/work-finality.ts +16 -4
- package/src/services/workflow-auto-start.ts +26 -13
- package/src/services/workflow-caller.ts +61 -4
- package/src/services/workflow-child-proof-worker.ts +1 -1
- package/src/services/workflow-ci-main.ts +1 -1
- package/src/services/workflow-control-proof-worker.ts +1 -1
- package/src/services/workflow-coordinator.ts +8 -2
- package/src/services/workflow-decisions.ts +5 -5
- package/src/services/workflow-deferred-cleanup.ts +5 -3
- package/src/services/workflow-effect-driver.ts +42 -17
- package/src/services/workflow-effects.ts +58 -37
- package/src/services/workflow-land-notice.ts +10 -0
- package/src/services/workflow-pause-text.ts +43 -0
- package/src/services/workflow-pins.ts +7 -4
- package/src/services/workflow-reconcile.ts +14 -11
- package/src/services/workflow-resume-pins.ts +3 -3
- package/src/services/workflow-routing-defaults.ts +18 -0
- package/src/services/workflow-run-view.ts +6 -3
- package/src/services/workflow-run.test-fixture.ts +1 -1
- package/src/services/workflow-runs.ts +61 -33
- package/src/services/workflow-supervisor-state.ts +26 -1
- package/src/services/workflow-supervisor.ts +11 -6
- package/src/services/workspace-recovery.ts +4 -3
- package/src/settings/registry.ts +1 -2
- package/src/spawn-admission.ts +10 -2
- package/src/spawn-command.ts +4 -4
- package/src/spawn-models.ts +10 -12
- package/src/spawn-placement.ts +28 -10
- package/src/spawn-targets.ts +9 -9
- package/src/sse-agent-status.ts +15 -6
- package/src/sse.ts +49 -24
- package/src/startup-context-injection.ts +62 -57
- package/src/state-adoption/cd-cutover.ts +53 -7
- package/src/state-adoption/fleet-cutover.ts +35 -0
- package/src/state-adoption/fleet-plan.ts +36 -0
- package/src/state-adoption/index.ts +2 -2
- package/src/state-adoption/linux-plan.ts +2 -2
- package/src/state-adoption/linux.ts +2 -2
- package/src/state-adoption/macos-plan.ts +2 -2
- package/src/state-adoption/macos.ts +1 -1
- package/src/steward-handoff.ts +4 -3
- package/src/steward-policy-cleanup.ts +9 -8
- package/src/steward.ts +9 -8
- package/src/task-dispatch-live.ts +6 -3
- package/src/task-dispatcher.ts +3 -3
- package/src/teams-config-store.ts +4 -3
- package/src/token-db-write.ts +10 -0
- package/src/token-db.ts +2 -2
- package/src/token-usage-async.ts +2 -4
- package/src/user-awaiting-reply.ts +5 -5
- package/src/workspace-actions.ts +24 -29
- package/src/workspace-auto-merge.ts +14 -12
- package/src/workspace-changed-paths-client.ts +16 -5
- package/src/workspace-cleanup-stale.ts +30 -7
- package/src/workspace-command-settle.ts +26 -17
- package/src/workspace-config.ts +1 -1
- package/src/workspace-conflict-resolver.ts +9 -7
- package/src/workspace-dead-owner-recovery.ts +5 -4
- package/src/workspace-escalation.ts +12 -11
- package/src/workspace-human-escalation.ts +3 -3
- package/src/workspace-land-gate-watchdog.ts +3 -3
- package/src/workspace-land-refusal.ts +20 -0
- package/src/workspace-land-stopped.ts +1 -0
- package/src/workspace-merge.ts +10 -26
- package/src/workspace-nothing-to-land-notice.ts +2 -2
- package/src/workspace-orphans.ts +18 -37
- package/src/workspace-pr-completion.ts +10 -8
- package/src/workspace-rekey.ts +3 -3
- package/src/workspace-steward-failure.ts +2 -2
- package/src/workspace-steward-wake.ts +4 -4
- package/node_modules/@humwick/kernel/LICENSE +0 -167
- package/node_modules/@humwick/kernel/async-entity-persistence.ts +0 -344
- package/node_modules/@humwick/kernel/async-event-log.ts +0 -107
- package/node_modules/@humwick/kernel/automations.pilot.ts +0 -147
- package/node_modules/@humwick/kernel/config.ts +0 -111
- package/node_modules/@humwick/kernel/contract.ts +0 -572
- package/node_modules/@humwick/kernel/control-authz.ts +0 -281
- package/node_modules/@humwick/kernel/control.ts +0 -645
- package/node_modules/@humwick/kernel/effects.ts +0 -493
- package/node_modules/@humwick/kernel/event-log.ts +0 -319
- package/node_modules/@humwick/kernel/http-transport.ts +0 -384
- package/node_modules/@humwick/kernel/identity-grammar.ts +0 -20
- package/node_modules/@humwick/kernel/identity.ts +0 -248
- package/node_modules/@humwick/kernel/index.ts +0 -28
- package/node_modules/@humwick/kernel/kernel-persistence.ts +0 -181
- package/node_modules/@humwick/kernel/landing-incident.ts +0 -306
- package/node_modules/@humwick/kernel/landing.ts +0 -953
- package/node_modules/@humwick/kernel/manifest-validation.ts +0 -460
- package/node_modules/@humwick/kernel/mcp-transport.ts +0 -109
- package/node_modules/@humwick/kernel/message-authority-chaos-worker.ts +0 -200
- package/node_modules/@humwick/kernel/message-authority.ts +0 -281
- package/node_modules/@humwick/kernel/module-host.ts +0 -722
- package/node_modules/@humwick/kernel/openapi-init.ts +0 -14
- package/node_modules/@humwick/kernel/package.json +0 -39
- package/node_modules/@humwick/kernel/persistence-schema.ts +0 -248
- package/node_modules/@humwick/kernel/persistence.ts +0 -510
- package/node_modules/@humwick/kernel/registry.ts +0 -60
- package/node_modules/@humwick/kernel/sqlite-kernel-persistence.ts +0 -499
- package/node_modules/@humwick/kernel/sqlite-module-host.ts +0 -87
- package/node_modules/@humwick/kernel/timers-chaos-worker.ts +0 -186
- package/node_modules/@humwick/kernel/timers.pilot.ts +0 -1411
- package/node_modules/@humwick/kernel/workflow-activation.ts +0 -25
- package/node_modules/@humwick/kernel/workflow-backstop.ts +0 -40
- package/node_modules/@humwick/kernel/workflow-cancel-tree.ts +0 -20
- package/node_modules/@humwick/kernel/workflow-chaos-worker.ts +0 -213
- package/node_modules/@humwick/kernel/workflow-composition.ts +0 -231
- package/node_modules/@humwick/kernel/workflow-container.ts +0 -72
- package/node_modules/@humwick/kernel/workflow-control.test-fixture.ts +0 -42
- package/node_modules/@humwick/kernel/workflow-control.ts +0 -178
- package/node_modules/@humwick/kernel/workflow-definition.ts +0 -507
- package/node_modules/@humwick/kernel/workflow-dispatch.ts +0 -60
- package/node_modules/@humwick/kernel/workflow-foreach.ts +0 -167
- package/node_modules/@humwick/kernel/workflow-journal-codec.ts +0 -339
- package/node_modules/@humwick/kernel/workflow-journal.ts +0 -922
- package/node_modules/@humwick/kernel/workflow-lane.ts +0 -48
- package/node_modules/@humwick/kernel/workflow-lease-owner.ts +0 -60
- package/node_modules/@humwick/kernel/workflow-recovery.test-fixture.ts +0 -19
- package/node_modules/@humwick/kernel/workflow-runtime.ts +0 -938
- package/node_modules/@humwick/kernel/workflow-script.ts +0 -11
- package/node_modules/@humwick/kernel/workflow-state.ts +0 -299
- package/node_modules/@humwick/kernel/workflow-step-commit.ts +0 -195
- package/node_modules/@humwick/kernel/workflow-transitions.ts +0 -317
- package/node_modules/@humwick/kernel/workflow-values.ts +0 -153
- package/node_modules/@humwick/kernel/workflow.pilot.ts +0 -376
- package/node_modules/@humwick/offload/LICENSE +0 -167
- package/node_modules/@humwick/offload/README.md +0 -57
- package/node_modules/@humwick/offload/dist/async-runner.d.ts +0 -18
- package/node_modules/@humwick/offload/dist/async-runner.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/async-runner.js +0 -158
- package/node_modules/@humwick/offload/dist/async-runner.js.map +0 -1
- package/node_modules/@humwick/offload/dist/envelope.d.ts +0 -25
- package/node_modules/@humwick/offload/dist/envelope.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/envelope.js +0 -80
- package/node_modules/@humwick/offload/dist/envelope.js.map +0 -1
- package/node_modules/@humwick/offload/dist/fixtures/worker-task.d.ts +0 -10
- package/node_modules/@humwick/offload/dist/fixtures/worker-task.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/fixtures/worker-task.js +0 -59
- package/node_modules/@humwick/offload/dist/fixtures/worker-task.js.map +0 -1
- package/node_modules/@humwick/offload/dist/index.d.ts +0 -5
- package/node_modules/@humwick/offload/dist/index.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/index.js +0 -5
- package/node_modules/@humwick/offload/dist/index.js.map +0 -1
- package/node_modules/@humwick/offload/dist/subprocess-runner.d.ts +0 -62
- package/node_modules/@humwick/offload/dist/subprocess-runner.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/subprocess-runner.js +0 -295
- package/node_modules/@humwick/offload/dist/subprocess-runner.js.map +0 -1
- package/node_modules/@humwick/offload/dist/types.d.ts +0 -111
- package/node_modules/@humwick/offload/dist/types.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/types.js +0 -176
- package/node_modules/@humwick/offload/dist/types.js.map +0 -1
- package/node_modules/@humwick/offload/dist/worker-pool.d.ts +0 -23
- package/node_modules/@humwick/offload/dist/worker-pool.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/worker-pool.js +0 -435
- package/node_modules/@humwick/offload/dist/worker-pool.js.map +0 -1
- package/node_modules/@humwick/offload/dist/worker-runtime.d.ts +0 -2
- package/node_modules/@humwick/offload/dist/worker-runtime.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/worker-runtime.js +0 -27
- package/node_modules/@humwick/offload/dist/worker-runtime.js.map +0 -1
- package/node_modules/@humwick/offload/dist/worker.d.ts +0 -5
- package/node_modules/@humwick/offload/dist/worker.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/worker.js +0 -1
- package/node_modules/@humwick/offload/dist/worker.js.map +0 -1
- package/node_modules/@humwick/offload/package.json +0 -42
- package/node_modules/@humwick/offload/src/async-runner.ts +0 -170
- package/node_modules/@humwick/offload/src/envelope.ts +0 -92
- package/node_modules/@humwick/offload/src/fixtures/worker-task.ts +0 -49
- package/node_modules/@humwick/offload/src/index.ts +0 -4
- package/node_modules/@humwick/offload/src/subprocess-runner.ts +0 -334
- package/node_modules/@humwick/offload/src/types.ts +0 -235
- package/node_modules/@humwick/offload/src/worker-pool.ts +0 -463
- package/node_modules/@humwick/offload/src/worker-runtime.ts +0 -32
- package/node_modules/@humwick/offload/src/worker.ts +0 -5
- package/public/assets/agent-liveness-DyqxfB-t.js +0 -2
- package/public/assets/agent-profiles-BpI_jTxq.js +0 -2
- package/public/assets/index-B7ZerHLY.css +0 -2
- package/public/assets/index-BU3uWo2t.js +0 -15
- package/public/assets/projects-B_lmcqfO.js +0 -2
- package/public/assets/provider-display-DbLWpP3j.js +0 -2
- package/public/assets/run-card-CO_bguQf.js +0 -2
- package/public/assets/shipping-Bu8p1gEw.js +0 -2
- package/public/assets/store-BvtFdlGX.js +0 -9
- package/public/assets/use-project-list-B-T2Bnnn.js +0 -2
- package/public/assets/versioned-prompt-editor-Diu8BIaM.js +0 -8
- package/runner/src/agent-runner/http-liveness.ts +0 -85
- package/runner/src/gate-run-lease-probe.ts +0 -38
- package/src/db/claude-catalog-reconcile.ts +0 -27
- package/src/db/on-loop-write-transaction.ts +0 -34
- package/src/routing-model-aliases.ts +0 -21
package/src/branch-landed.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import { insertLandingReceiptAsync } from "./db/runtime-tail-async";
|
|
2
|
+
import { createActivityEventAsync } from "./db/activity-async";
|
|
3
|
+
import { announceVerifiedLand } from "./branch-land-notice";
|
|
1
4
|
import { errMessage, isHumanAgentId, type BaseWorktreeSyncResult } from "@humwick/sdk";
|
|
2
5
|
import { emitRelayEvent } from "./events";
|
|
3
6
|
import { routeNotification, INFORMATIONAL_TTL_MS } from "./notification-router";
|
|
4
7
|
import { stampLifecycleSignal, taskSignalKey } from "./lifecycle-signal-registry";
|
|
5
8
|
import { registerDefaultAudienceRules, audiencePredicates } from "./notification-rules";
|
|
6
|
-
import {
|
|
9
|
+
import { getAgent, getOrchestrator, getProject, getTaskDetail, markWorkspaceLanded, patchWorkspaceMetadataAsync, resolveProjectForCwd, updateWorkspaceStatusAsync, markWorkspaceLandedAsync } from "./db";
|
|
7
10
|
import { renderTemplate } from "./prompt-resolver";
|
|
8
11
|
import { resolveCoordinatorAgentId } from "./steward-identity";
|
|
9
12
|
import { stewardFallbackTarget } from "./config";
|
|
@@ -32,6 +35,8 @@ export interface BranchLandedInput extends LandedTaskAttributionInput {
|
|
|
32
35
|
workspace: Pick<WorkspaceRecord, "id" | "repoRoot" | "branch" | "baseRef" | "baseSha" | "ownerAgentId" | "orchestratorId">;
|
|
33
36
|
/** SHA the base now points at after the land. */
|
|
34
37
|
mergedSha?: string;
|
|
38
|
+
/** Landing host proof from its fresh origin ancestry check. Must match mergedSha. */
|
|
39
|
+
landVerifiedSha?: string;
|
|
35
40
|
/** Original command settlement clock when recovering an older land. */
|
|
36
41
|
landedAt?: number;
|
|
37
42
|
/** Subject line of the landed commit, when the orchestrator reported it. */
|
|
@@ -168,7 +173,7 @@ async function landedCommitSubjects(input: BranchLandedInput, log: BranchLandedL
|
|
|
168
173
|
}, log);
|
|
169
174
|
}
|
|
170
175
|
|
|
171
|
-
function resolveLandedTask(input: LandedTaskAttributionInput): {
|
|
176
|
+
export function resolveLandedTask(input: LandedTaskAttributionInput): {
|
|
172
177
|
taskId: number;
|
|
173
178
|
taskLabel: string;
|
|
174
179
|
projectId?: string;
|
|
@@ -206,9 +211,9 @@ function landedNotificationIdempotencyKey(input: BranchLandedInput, landedTask:
|
|
|
206
211
|
* the announcement; this combined entry preserves the original all-synchronous behavior for the
|
|
207
212
|
* maintenance reconcile path (reconcileLandedWorkspace) and direct callers/tests.
|
|
208
213
|
*/
|
|
209
|
-
export function notifyBranchLanded(input: BranchLandedInput): void {
|
|
210
|
-
recordLandingReceipt(input);
|
|
211
|
-
announceBranchLanded(input);
|
|
214
|
+
export async function notifyBranchLanded(input: BranchLandedInput): Promise<void> {
|
|
215
|
+
(await recordLandingReceipt(input));
|
|
216
|
+
await announceBranchLanded(input);
|
|
212
217
|
}
|
|
213
218
|
|
|
214
219
|
/**
|
|
@@ -219,7 +224,7 @@ export function notifyBranchLanded(input: BranchLandedInput): void {
|
|
|
219
224
|
* row with no receipt. The branch is already landed, so a receipt failure is loud (CRITICAL log) but
|
|
220
225
|
* can never unwind or mask it.
|
|
221
226
|
*/
|
|
222
|
-
export function recordLandingReceipt(input: BranchLandedInput): void {
|
|
227
|
+
export async function recordLandingReceipt(input: BranchLandedInput): Promise<void> {
|
|
223
228
|
const { workspace } = input;
|
|
224
229
|
// #1620 — a land that introduced ZERO commits is not a land: no receipt (see announceBranchLanded).
|
|
225
230
|
if (input.landedCommitCount === 0) return;
|
|
@@ -234,7 +239,7 @@ export function recordLandingReceipt(input: BranchLandedInput): void {
|
|
|
234
239
|
const mergedSha = cleanRef(input.mergedSha);
|
|
235
240
|
const commitShas = [...new Set((input.commitShas ?? []).map(cleanRef).filter((sha): sha is string => Boolean(sha)))];
|
|
236
241
|
if (commitShas.length === 0 && mergedSha) commitShas.push(mergedSha);
|
|
237
|
-
|
|
242
|
+
(await insertLandingReceiptAsync({
|
|
238
243
|
...(landedTask?.projectId ?? project?.id ? { projectId: landedTask?.projectId ?? project!.id } : {}),
|
|
239
244
|
repo: landedTask?.repo ?? project?.issueRepo ?? repoFromGitRemote(workspace.repoRoot) ?? workspace.repoRoot,
|
|
240
245
|
ref: workspace.baseRef ?? "base",
|
|
@@ -250,7 +255,7 @@ export function recordLandingReceipt(input: BranchLandedInput): void {
|
|
|
250
255
|
...(landedTask?.teamId ?? worker?.teamId ? { teamId: landedTask?.teamId ?? worker!.teamId } : {}),
|
|
251
256
|
...(workspace.orchestratorId ? { orchestratorId: workspace.orchestratorId } : {}),
|
|
252
257
|
...(orchestrator?.hostname ?? worker?.machine ?? worker?.rig ? { host: orchestrator?.hostname ?? worker?.machine ?? worker!.rig } : {}),
|
|
253
|
-
});
|
|
258
|
+
}));
|
|
254
259
|
} catch (error) {
|
|
255
260
|
console.error(`[landing-receipt] CRITICAL: failed to persist landed branch ${workspace.id}: ${errMessage(error)}`);
|
|
256
261
|
}
|
|
@@ -262,7 +267,7 @@ export function recordLandingReceipt(input: BranchLandedInput): void {
|
|
|
262
267
|
* the issue/Task lifecycle drives. #1790 — the settle path DEFERS this off its synchronous critical
|
|
263
268
|
* path; the durable receipt is recorded separately + synchronously by {@link recordLandingReceipt}.
|
|
264
269
|
*/
|
|
265
|
-
export function announceBranchLanded(input: BranchLandedInput): void {
|
|
270
|
+
export async function announceBranchLanded(input: BranchLandedInput): Promise<void> {
|
|
266
271
|
const { workspace } = input;
|
|
267
272
|
const base = workspace.baseRef ?? "base";
|
|
268
273
|
// #1620 — a land that introduced ZERO commits is not a land. It happens when a reconciliation
|
|
@@ -348,79 +353,7 @@ export function announceBranchLanded(input: BranchLandedInput): void {
|
|
|
348
353
|
}
|
|
349
354
|
})());
|
|
350
355
|
|
|
351
|
-
|
|
352
|
-
const shaLabel = shortSha ? ` as \`${shortSha}\`` : "";
|
|
353
|
-
const subjectLabel = input.subject ? ` — "${input.subject}"` : "";
|
|
354
|
-
const payload = {
|
|
355
|
-
kind: "branch.landed",
|
|
356
|
-
workspaceId: workspace.id,
|
|
357
|
-
repoRoot: workspace.repoRoot,
|
|
358
|
-
branch: landedBranch,
|
|
359
|
-
base,
|
|
360
|
-
sha: input.mergedSha,
|
|
361
|
-
author,
|
|
362
|
-
newBranch: input.newBranch,
|
|
363
|
-
pushed: input.pushed,
|
|
364
|
-
...landedTaskPayload,
|
|
365
|
-
};
|
|
366
|
-
|
|
367
|
-
// A local-only land (push disabled, or base has no upstream) has NOT reached the
|
|
368
|
-
// remote — say so rather than implying a published merge an agent would report as
|
|
369
|
-
// shipped (#285). `undefined` (older orchestrators) keeps the message generic.
|
|
370
|
-
const publishLabel = input.pushed === false ? ` Not yet pushed to \`origin/${base}\` — local only.` : "";
|
|
371
|
-
|
|
372
|
-
// The branch author cares most — push regardless of online (store-ahead delivers it on
|
|
373
|
-
// next poll if they've moved on, #234). A live owner continues in its worktree.
|
|
374
|
-
if (author) {
|
|
375
|
-
const branchLabel = landedBranch ? `\`${landedBranch}\`` : "Your branch";
|
|
376
|
-
const continueLabel = input.newBranch
|
|
377
|
-
? ` You're now on \`${input.newBranch}\` — keep working there.`
|
|
378
|
-
: " Worktree reclaimed.";
|
|
379
|
-
// Durable (ttl null): the author's own branch landing must reach them even after they go
|
|
380
|
-
// offline (store-ahead #234) — not a bystander notice that goes stale.
|
|
381
|
-
const notices = routeNotification({
|
|
382
|
-
type: "branch.landed",
|
|
383
|
-
scope: { author, repoRoot: workspace.repoRoot, workspaceId: workspace.id },
|
|
384
|
-
recipients: [author],
|
|
385
|
-
ttlMs: null,
|
|
386
|
-
message: {
|
|
387
|
-
subject: "Your branch landed",
|
|
388
|
-
body: renderTemplate("notify.land.success", {
|
|
389
|
-
branch: branchLabel,
|
|
390
|
-
base,
|
|
391
|
-
sha: `${shaLabel}${subjectLabel}`,
|
|
392
|
-
publishLabel,
|
|
393
|
-
continueLabel,
|
|
394
|
-
}),
|
|
395
|
-
payload: { ...payload, notification: "landed-success" },
|
|
396
|
-
idempotencyKey,
|
|
397
|
-
replyExpected: false,
|
|
398
|
-
},
|
|
399
|
-
});
|
|
400
|
-
if (landedTask && input.mergedSha) {
|
|
401
|
-
for (const notice of notices) stampLifecycleSignal(notice.to, taskSignalKey(landedTask.taskId, "landed-on-main", input.mergedSha));
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
// Coordinator copy (#2837), informational. No explicit recipients: the router records the rule decision (#446).
|
|
406
|
-
const mainScope = { author, repoRoot: workspace.repoRoot, workspaceId: workspace.id, teamId: landedTask?.teamId ?? (author ? getAgent(author)?.teamId : undefined), coordinatorAgentIds: [...new Set([resolveCoordinatorAgentId(author), landedTask && resolveTaskOwnerAgentId(getTaskDetail(landedTask.taskId))].filter((id): id is string => !!id && !isHumanAgentId(id)))] };
|
|
407
|
-
const branchLabel = landedBranch ? `\`${landedBranch}\`` : "A branch";
|
|
408
|
-
const authorLabel = author ? ` by \`${author}\`` : "";
|
|
409
|
-
const notices = routeNotification({
|
|
410
|
-
type: "branch.landed",
|
|
411
|
-
scope: mainScope, ...audienceWithTaskOwnerRole("branch.landed", mainScope, landedTask?.taskId), // #2862
|
|
412
|
-
ttlMs: INFORMATIONAL_TTL_MS,
|
|
413
|
-
message: {
|
|
414
|
-
subject: `Merged to ${base}`,
|
|
415
|
-
body: `🔀 ${branchLabel}${authorLabel} merged to \`${base}\`${shaLabel}${subjectLabel}.${publishLabel}`,
|
|
416
|
-
payload: { ...payload, notification: "landed-success" },
|
|
417
|
-
idempotencyKey,
|
|
418
|
-
replyExpected: false,
|
|
419
|
-
},
|
|
420
|
-
});
|
|
421
|
-
if (landedTask && input.mergedSha) {
|
|
422
|
-
for (const notice of notices) stampLifecycleSignal(notice.to, taskSignalKey(landedTask.taskId, "landed-on-main", input.mergedSha));
|
|
423
|
-
}
|
|
356
|
+
trackLandLifecycleDrive(announceVerifiedLand(input, landedTask, idempotencyKey));
|
|
424
357
|
}
|
|
425
358
|
|
|
426
359
|
/**
|
|
@@ -434,10 +367,10 @@ export function announceBranchLanded(input: BranchLandedInput): void {
|
|
|
434
367
|
* the checkout. Human WIP is never auto-clobbered; `preservedWipPaths` flags paths to merge by
|
|
435
368
|
* hand rather than blind-restore.
|
|
436
369
|
*/
|
|
437
|
-
export function notifyBaseWorktreeStrand(input: {
|
|
370
|
+
export async function notifyBaseWorktreeStrand(input: {
|
|
438
371
|
workspace: Pick<WorkspaceRecord, "id" | "repoRoot" | "branch" | "baseRef" | "ownerAgentId">;
|
|
439
372
|
sync: BaseWorktreeSyncResult;
|
|
440
|
-
}): void {
|
|
373
|
+
}): Promise<void> {
|
|
441
374
|
const { workspace, sync } = input;
|
|
442
375
|
if (sync.reconciled) return;
|
|
443
376
|
const base = workspace.baseRef ?? "base";
|
|
@@ -466,7 +399,7 @@ export function notifyBaseWorktreeStrand(input: {
|
|
|
466
399
|
|
|
467
400
|
emitRelayEvent({ type: "workspace.base_checkout_strand", source: "server", subject: workspace.id, data: payload });
|
|
468
401
|
|
|
469
|
-
|
|
402
|
+
(await createActivityEventAsync({
|
|
470
403
|
clientId: `workspace-base-strand-${workspace.id}-${Date.now()}`,
|
|
471
404
|
kind: "state",
|
|
472
405
|
title: "Base checkout stranded after land (mixed state)",
|
|
@@ -475,13 +408,13 @@ export function notifyBaseWorktreeStrand(input: {
|
|
|
475
408
|
icon: "ti-alert-octagon",
|
|
476
409
|
view: "orchestrators",
|
|
477
410
|
metadata: { source: "server", maintenanceJobId: "workspace-base-strand", workspaceId: workspace.id, repoRoot: workspace.repoRoot, unsyncedPaths: unsynced, preservedWipPaths: preservedWip },
|
|
478
|
-
});
|
|
411
|
+
}));
|
|
479
412
|
|
|
480
413
|
// Durable (ttl null) push to the owner and its coordinator — whoever works in the shared
|
|
481
414
|
// checkout must learn it's stale before acting on it. Fallback steward covers a teamless land.
|
|
482
415
|
const recipients = [...new Set([owner, coordinator, fallback].filter((r): r is string => Boolean(r)))];
|
|
483
416
|
if (recipients.length) {
|
|
484
|
-
routeNotification({
|
|
417
|
+
await routeNotification({
|
|
485
418
|
type: "workspace.base_checkout_strand",
|
|
486
419
|
scope: { author: owner, parent: coordinator ?? undefined, repoRoot: workspace.repoRoot, workspaceId: workspace.id },
|
|
487
420
|
recipients,
|
|
@@ -501,12 +434,12 @@ export function notifyBaseWorktreeStrand(input: {
|
|
|
501
434
|
* steward-task/conflict pings: it tells the worker that its post-ready idle wait ended without
|
|
502
435
|
* a completed land, so it can inspect/report instead of silently staying parked forever.
|
|
503
436
|
*/
|
|
504
|
-
export function notifyBranchLandFailed(input: {
|
|
437
|
+
export async function notifyBranchLandFailed(input: {
|
|
505
438
|
workspace: Pick<WorkspaceRecord, "id" | "repoRoot" | "branch" | "baseRef" | "ownerAgentId">;
|
|
506
439
|
commandId?: string;
|
|
507
440
|
recipients?: string[];
|
|
508
441
|
reason?: string;
|
|
509
|
-
}): void {
|
|
442
|
+
}): Promise<void> {
|
|
510
443
|
const { workspace } = input;
|
|
511
444
|
const base = workspace.baseRef ?? "base";
|
|
512
445
|
const author = workspace.ownerAgentId;
|
|
@@ -533,7 +466,7 @@ export function notifyBranchLandFailed(input: {
|
|
|
533
466
|
const recipients = withWorkspaceTaskOwnerRoles(input.recipients ?? [author, coordinator], workspace); // #2862
|
|
534
467
|
if (!recipients.length) return;
|
|
535
468
|
const branchLabel = workspace.branch ? `\`${workspace.branch}\`` : "Your branch";
|
|
536
|
-
routeNotification({
|
|
469
|
+
await routeNotification({
|
|
537
470
|
type: "landed-failure",
|
|
538
471
|
scope: { author, parent: coordinator ?? undefined, repoRoot: workspace.repoRoot, workspaceId: workspace.id },
|
|
539
472
|
recipients,
|
|
@@ -563,7 +496,7 @@ export { notifyLandGateFailed, notifyLandGateWarnings, notifyLandGateSkipped } f
|
|
|
563
496
|
* The steward id is the managed steward's policy name (reachable via `policy:<name>`) or an
|
|
564
497
|
* elected steward's agent id, whichever the caller has in scope.
|
|
565
498
|
*/
|
|
566
|
-
export function notifyStewardHandoff(input: {
|
|
499
|
+
export async function notifyStewardHandoff(input: {
|
|
567
500
|
workspace: Pick<WorkspaceRecord, "id" | "repoRoot" | "branch" | "baseRef" | "ownerAgentId">;
|
|
568
501
|
/** The steward now holding the merge — managed steward policy name or elected agent id. */
|
|
569
502
|
stewardId: string;
|
|
@@ -571,7 +504,7 @@ export function notifyStewardHandoff(input: {
|
|
|
571
504
|
coordinatorAgentId?: string | null;
|
|
572
505
|
/** Why it was handed over ("conflict", "merge state unknown", auto-merge back-off, …). */
|
|
573
506
|
reason?: string;
|
|
574
|
-
}): void {
|
|
507
|
+
}): Promise<void> {
|
|
575
508
|
const { workspace } = input;
|
|
576
509
|
const base = workspace.baseRef ?? "base";
|
|
577
510
|
const owner = workspace.ownerAgentId;
|
|
@@ -596,7 +529,7 @@ export function notifyStewardHandoff(input: {
|
|
|
596
529
|
// thinking the branch silently failed. Durable (ttl null): the owner must learn this
|
|
597
530
|
// even if it went idle. Mirror the "don't touch main" guardrail of the landed-failure wake.
|
|
598
531
|
if (owner) {
|
|
599
|
-
routeNotification({
|
|
532
|
+
await routeNotification({
|
|
600
533
|
type: "workspace.steward_handoff",
|
|
601
534
|
scope: { author: owner, repoRoot: workspace.repoRoot, workspaceId: workspace.id },
|
|
602
535
|
recipients: [owner],
|
|
@@ -619,7 +552,7 @@ export function notifyStewardHandoff(input: {
|
|
|
619
552
|
// (it spawned the branch agent and owns the merge landing). Skip when the coordinator IS
|
|
620
553
|
// the owner (no real lineage) to avoid a duplicate ping.
|
|
621
554
|
if (coordinator && coordinator !== owner) {
|
|
622
|
-
routeNotification({
|
|
555
|
+
await routeNotification({
|
|
623
556
|
type: "workspace.steward_handoff",
|
|
624
557
|
scope: { author: owner, parent: coordinator, repoRoot: workspace.repoRoot, workspaceId: workspace.id },
|
|
625
558
|
recipients: [coordinator],
|
|
@@ -682,7 +615,7 @@ const DRAINED_LAND_STRAND_BOOKKEEPING = {
|
|
|
682
615
|
* (record the receipt, announce a real land, drain the steward/strand bookkeeping so no
|
|
683
616
|
* watchdog re-wakes or re-pages a branch with nothing left to land).
|
|
684
617
|
*/
|
|
685
|
-
export async function reconcileLandedWorkspace(ws: WorkspaceRecord, preview: WorkspaceMergePreview): Promise<LandedWorkspaceReconciliation> {
|
|
618
|
+
export async function reconcileLandedWorkspace(ws: WorkspaceRecord, preview: WorkspaceMergePreview, landVerifiedSha?: string): Promise<LandedWorkspaceReconciliation> {
|
|
686
619
|
const observedSha = typeof preview.prMergeSha === "string"
|
|
687
620
|
? preview.prMergeSha
|
|
688
621
|
: typeof preview.landedSha === "string"
|
|
@@ -740,7 +673,7 @@ export async function reconcileLandedWorkspace(ws: WorkspaceRecord, preview: Wor
|
|
|
740
673
|
const closure = ownerAlive
|
|
741
674
|
? `owner \`${ws.ownerAgentId}\` is still running, so the workspace stays non-terminal and usable at ${nextStatus}${nextStatus === ws.status ? "" : ` (was ${ws.status} — out of the land queue, #1662)`} (#1631); steward/strand and no-progress bookkeeping cleared`
|
|
742
675
|
: `marking merged${landedCommitCount === 0 ? "; nothing was landed" : ""}`;
|
|
743
|
-
|
|
676
|
+
(await createActivityEventAsync({
|
|
744
677
|
clientId: "server-workspace-" + ws.id + "-merged-" + Date.now(),
|
|
745
678
|
kind: "state",
|
|
746
679
|
title: ownerAlive
|
|
@@ -751,9 +684,9 @@ export async function reconcileLandedWorkspace(ws: WorkspaceRecord, preview: Wor
|
|
|
751
684
|
icon: "ti-git-merge",
|
|
752
685
|
view: "orchestrators",
|
|
753
686
|
metadata: { source: "server", maintenanceJobId: "workspace-conflict-scan", workspaceId: ws.id, fromStatus: ws.status, toStatus: nextStatus, ...(ownerAlive ? { ownerAlive: true, keptLive: true } : {}), ...(sha ? { landedSha: sha } : {}), ...(landedCommitCount === 0 ? { landedCommitCount: 0 } : {}) },
|
|
754
|
-
});
|
|
687
|
+
}));
|
|
755
688
|
try {
|
|
756
|
-
notifyBranchLanded({ workspace: ws, mergedSha: sha, landedTipSha: sha, commitShas: sha ? [sha] : [], pushed: true, prLand: preview.prMerged === true, ...(landedCommitCount === 0 ? { landedCommitCount } : {}) });
|
|
689
|
+
await notifyBranchLanded({ workspace: ws, mergedSha: sha, landVerifiedSha, landedTipSha: sha, commitShas: sha ? [sha] : [], pushed: true, prLand: preview.prMerged === true, ...(landedCommitCount === 0 ? { landedCommitCount } : {}) });
|
|
757
690
|
} catch {
|
|
758
691
|
// Notification is best-effort; the status change + activity event still stand.
|
|
759
692
|
}
|
package/src/bus.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Server, ServerWebSocket } from "bun";
|
|
2
|
-
import { ValidationError,
|
|
2
|
+
import { ValidationError, applyAgentLifecycleUpdateAsync, getAgent, getDb, orphanTasksForAgentAsync, recordHeartbeatAsync, validateAgentSession } from "./db";
|
|
3
3
|
import { getOutboxCursor, hasReplayGap, replayEventsSlice, type BusEvent } from "./bus-outbox";
|
|
4
4
|
import { emitAgentStatus } from "./agent-status-events";
|
|
5
5
|
import { AgentStatusSubscribers, matchesSubscription, wantsAgentStatus } from "./transport-subscriptions";
|
|
@@ -11,7 +11,7 @@ import { announceSpawnedAgentReady, registerAgent } from "./services/register-ag
|
|
|
11
11
|
import { authContextFromBus } from "./services/auth-context";
|
|
12
12
|
import { commandAuthorizationResource, dispatchCommandAsync } from "./services/dispatch-command";
|
|
13
13
|
import { withRelayEventDrain } from "./relay-event-drain";
|
|
14
|
-
import { runAsCaller } from "./hub-metrics";
|
|
14
|
+
import { framed, runAsCaller } from "./hub-metrics";
|
|
15
15
|
import { auditProviderStateTransition } from "./services/provider-state-audit";
|
|
16
16
|
import { agentProviderTimelineEvent, auditRunnerTimelineEvent } from "./provider-timeline-event";
|
|
17
17
|
import { auditProviderTurnEmpty, auditProviderTurnWatchdog, auditReconciledProviderTurn } from "./services/turn-reconcile-audit";
|
|
@@ -19,6 +19,7 @@ import { ServiceAuthError } from "./services/errors";
|
|
|
19
19
|
import { ShutdownAuthError, ShutdownTargetError, shutdownAgent, shutdownInputFromBusFrame } from "./services/shutdown-agent";
|
|
20
20
|
import { flushQueuedDirectMessages } from "./services/managed-running";
|
|
21
21
|
import { updateCommandFromBus } from "./services/bus-command-update";
|
|
22
|
+
import { heartbeatFromBus } from "./services/agent-heartbeat";
|
|
22
23
|
import { isAgentUnavailable, reservedAgentIdSql } from "./db/agent-predicates";
|
|
23
24
|
import { messageMatchesAgent, targetMatchesAgent } from "./agent-ref";
|
|
24
25
|
import { probeWorkspaceOnTurnEnd } from "./workspace-probe";
|
|
@@ -34,7 +35,7 @@ import {
|
|
|
34
35
|
type BusFrame,
|
|
35
36
|
type RegisterFrame,
|
|
36
37
|
} from "@humwick/sdk/protocol";
|
|
37
|
-
import { errMessage, isRecord } from "@humwick/sdk";
|
|
38
|
+
import { errMessage, fireAndForget, isRecord } from "@humwick/sdk";
|
|
38
39
|
import { getComponentAuth, isComponentAuthorizedFor, isAuthorized, isOriginAllowed, unauthorized } from "./security";
|
|
39
40
|
import type { AgentCard, ComponentToken, ContextState, Message, ProviderCapabilities, QuotaState, RegisterAgentInput, Task } from "./types";
|
|
40
41
|
|
|
@@ -76,7 +77,7 @@ const liveBusSocketIds = new Set<string>();
|
|
|
76
77
|
// stalls unrelated agents.
|
|
77
78
|
const busFrameQueues = new Map<string, Promise<void>>();
|
|
78
79
|
|
|
79
|
-
subscribeRelayEvents(
|
|
80
|
+
subscribeRelayEvents(broadcastRelayEvent);
|
|
80
81
|
|
|
81
82
|
export function handleBusUpgrade(req: Request, server: Server<BusSocketData>): Response | undefined {
|
|
82
83
|
if (!isOriginAllowed(req)) {
|
|
@@ -95,11 +96,11 @@ export function handleBusUpgrade(req: Request, server: Server<BusSocketData>): R
|
|
|
95
96
|
return undefined;
|
|
96
97
|
}
|
|
97
98
|
|
|
98
|
-
export
|
|
99
|
+
export const busHandleOpen = framed("WS open", (ws: BusWebSocket): void => {
|
|
99
100
|
liveBusSocketIds.add(ws.data.id);
|
|
100
101
|
// Registration is explicit. The socket is not visible to projections until
|
|
101
102
|
// a valid register frame establishes identity and subscriptions.
|
|
102
|
-
}
|
|
103
|
+
});
|
|
103
104
|
|
|
104
105
|
export function busHandleMessage(ws: BusWebSocket, data: string | Buffer): void {
|
|
105
106
|
if (!liveBusSocketIds.has(ws.data.id)) return;
|
|
@@ -127,7 +128,7 @@ export function busHandleMessage(ws: BusWebSocket, data: string | Buffer): void
|
|
|
127
128
|
busFrameQueues.set(ws.data.id, queued);
|
|
128
129
|
}
|
|
129
130
|
|
|
130
|
-
export
|
|
131
|
+
export const busHandleClose = framed("WS close", (ws: BusWebSocket): void => {
|
|
131
132
|
liveBusSocketIds.delete(ws.data.id);
|
|
132
133
|
busFrameQueues.delete(ws.data.id);
|
|
133
134
|
const conn = busConnections.get(ws.data.id);
|
|
@@ -138,11 +139,14 @@ export function busHandleClose(ws: BusWebSocket): void {
|
|
|
138
139
|
// on the establishing socket id, so a foreign socket's close cannot evict the owner's binding and a stale
|
|
139
140
|
// close cannot evict a newer register's binding).
|
|
140
141
|
if (!conn.transportReconnect) {
|
|
141
|
-
|
|
142
|
-
|
|
142
|
+
const agentId = conn.agentId;
|
|
143
|
+
void fireAndForget(`[bus] mark ${agentId} stale on close`, async () => {
|
|
144
|
+
await applyAgentLifecycleUpdateAsync(agentId, { status: "stale" }, { instanceId: conn.instanceId, epoch: conn.epoch });
|
|
145
|
+
queueAgentStatusEvent(agentId);
|
|
146
|
+
});
|
|
143
147
|
}
|
|
144
148
|
}
|
|
145
|
-
}
|
|
149
|
+
});
|
|
146
150
|
|
|
147
151
|
export function getBusConnectionCount(): number {
|
|
148
152
|
return busConnections.size;
|
|
@@ -162,7 +166,7 @@ export async function expireStaleBusAgents(graceMs = busStaleGraceMs(), lagGrace
|
|
|
162
166
|
// but do NOT revoke the token — a reconnect accepts the EXISTING token and re-marks
|
|
163
167
|
// live. The #484 restart-strand revoke now fires on instance takeover in registerAgent
|
|
164
168
|
// (a fresh instanceId → epoch bump), never on a heartbeat lapse.
|
|
165
|
-
|
|
169
|
+
await applyAgentLifecycleUpdateAsync(row.id, { status: "offline" });
|
|
166
170
|
await emitAgentStatus(row.id);
|
|
167
171
|
const tasks = await orphanTasksForAgentAsync(row.id);
|
|
168
172
|
for (const task of tasks) {
|
|
@@ -187,7 +191,7 @@ async function handleFrame(ws: BusWebSocket, frame: ReturnType<typeof validateCl
|
|
|
187
191
|
await handleRegister(ws, frame);
|
|
188
192
|
return;
|
|
189
193
|
case "heartbeat":
|
|
190
|
-
await withRegistered(ws, frame, (conn) => {
|
|
194
|
+
await withRegistered(ws, frame, async (conn) => {
|
|
191
195
|
if (conn.agentId) {
|
|
192
196
|
// #633 — a runner whose provider terminally exited stays alive and keeps sending idle
|
|
193
197
|
// keepalives (semanticStatus is never "offline"). Those must NOT resurrect an agent the
|
|
@@ -199,16 +203,15 @@ async function handleFrame(ws: BusWebSocket, frame: ReturnType<typeof validateCl
|
|
|
199
203
|
if (!heldOffline) {
|
|
200
204
|
const wasUnavailable = current ? isAgentUnavailable(current) : false;
|
|
201
205
|
const runtime = runtimeFromMeta(frame.payload.meta);
|
|
202
|
-
// #1468 — coalesce the steady-state liveness write;
|
|
203
|
-
//
|
|
204
|
-
//
|
|
205
|
-
|
|
206
|
-
recordHeartbeat(conn.agentId, { guard: { instanceId: conn.instanceId, epoch: conn.epoch }, status: frame.payload.status, runtime });
|
|
206
|
+
// #1468 — coalesce the steady-state liveness write; only a status change / resurrection
|
|
207
|
+
// writes (last_seen + runtime), on the writer thread (#1870 S7). This replaces the old
|
|
208
|
+
// heartbeat()+setStatus() pair that rewrote the row twice per beat even when nothing changed.
|
|
209
|
+
await recordHeartbeatAsync(conn.agentId, { guard: { instanceId: conn.instanceId, epoch: conn.epoch }, status: frame.payload.status, runtime });
|
|
207
210
|
queueAgentStatusEvent(conn.agentId);
|
|
208
211
|
// #416 — flush queued messages if the agent transitioned from unavailable to available.
|
|
209
212
|
if (wasUnavailable) {
|
|
210
213
|
const after = getAgent(conn.agentId);
|
|
211
|
-
if (after && !isAgentUnavailable(after)) flushQueuedDirectMessages(conn.agentId);
|
|
214
|
+
if (after && !isAgentUnavailable(after)) (await flushQueuedDirectMessages(conn.agentId));
|
|
212
215
|
}
|
|
213
216
|
}
|
|
214
217
|
}
|
|
@@ -225,19 +228,16 @@ async function handleFrame(ws: BusWebSocket, frame: ReturnType<typeof validateCl
|
|
|
225
228
|
await withRegistered(ws, frame, async (conn) => {
|
|
226
229
|
if (!conn.agentId) return sendError(ws, frame.id, "AGENT_REQUIRED", "status frames require an agent registration");
|
|
227
230
|
const guard = { instanceId: conn.instanceId, epoch: conn.epoch };
|
|
228
|
-
// #
|
|
229
|
-
//
|
|
230
|
-
//
|
|
231
|
-
// thread hop mid-frame, so routing these writes through their async facades would not move
|
|
232
|
-
// them off-loop — it would only add a round-trip.
|
|
233
|
-
// #2111 — but the three writes ARE now one. This used to be getAgent(before) + setStatus
|
|
231
|
+
// #1870 S7 — the per-status-frame write runs on the writer thread; this socket's FIFO frame
|
|
232
|
+
// queue keeps its frames ordered across the hop, and the lifecycle ordinal fences it against
|
|
233
|
+
// every other lifecycle writer. #2111 — the three writes are one. This used to be getAgent(before) + setStatus
|
|
234
234
|
// (guard read + before read + UPDATE in its own BEGIN IMMEDIATE) + markReady (guard read +
|
|
235
235
|
// UPDATE) + mergeAgentMeta (two reads + UPDATE) + getAgent(after): ~7 row reads and 3 UPDATEs
|
|
236
236
|
// of one row per frame. `applyAgentLifecycleUpdate` does one guard read, one UPDATE and hands
|
|
237
237
|
// back the before/after cards the audit calls below need. The flap ledger is different: it is
|
|
238
238
|
// a cold durable history and must stay ordered with its status edge, so await it within this
|
|
239
239
|
// socket's existing FIFO frame queue.
|
|
240
|
-
const applied =
|
|
240
|
+
const applied = await applyAgentLifecycleUpdateAsync(
|
|
241
241
|
conn.agentId,
|
|
242
242
|
{ status: frame.payload.agentStatus, ready: frame.payload.ready, meta: frame.payload.meta },
|
|
243
243
|
guard,
|
|
@@ -250,27 +250,27 @@ async function handleFrame(ws: BusWebSocket, frame: ReturnType<typeof validateCl
|
|
|
250
250
|
const after = applied.after;
|
|
251
251
|
await auditProviderStateTransition(conn.agentId, before, after);
|
|
252
252
|
const timelineEvent = agentProviderTimelineEvent(after);
|
|
253
|
-
auditRunnerTimelineEvent(conn.agentId, timelineEvent);
|
|
253
|
+
(await auditRunnerTimelineEvent(conn.agentId, timelineEvent));
|
|
254
254
|
// #1621 — a turn the runner proved was cancelled out of band is a real state change the
|
|
255
255
|
// waiting coordinator has to hear about, not just an activity-feed row.
|
|
256
|
-
auditReconciledProviderTurn(conn.agentId, after, timelineEvent);
|
|
256
|
+
await auditReconciledProviderTurn(conn.agentId, after, timelineEvent);
|
|
257
257
|
// #1980 — the busy backstop is HOLDING a long turn it can't prove idle (not cancelling);
|
|
258
258
|
// tell the waiting coordinator the turn is still live rather than leaving it to guess.
|
|
259
259
|
// #2010 — but only when there's no positive busy evidence already saying so (see the
|
|
260
260
|
// busy-health gate inside auditProviderTurnWatchdog); a demonstrably working agent needs
|
|
261
261
|
// no wake.
|
|
262
|
-
auditProviderTurnWatchdog(conn.agentId, after, timelineEvent);
|
|
262
|
+
await auditProviderTurnWatchdog(conn.agentId, after, timelineEvent);
|
|
263
263
|
// #2389 — a turn that ended clean and produced nothing is the least visible failure of the
|
|
264
264
|
// three: the card reads healthy and idle. Tell the parent once the runner's own nudge has
|
|
265
265
|
// failed to recover it.
|
|
266
|
-
auditProviderTurnEmpty(conn.agentId, after, timelineEvent);
|
|
266
|
+
await auditProviderTurnEmpty(conn.agentId, after, timelineEvent);
|
|
267
267
|
// #2432 — a first ready that arrives over a status frame (children whose register kept the
|
|
268
268
|
// row not-ready, e.g. ox/opencode builders) must stamp readiness exactly like the HTTP and
|
|
269
269
|
// registration seams, or the child later reaps as a false `agent.spawn_failed`.
|
|
270
|
-
if (readyTransition) announceSpawnedAgentReady(conn.agentId, "bus-ready");
|
|
270
|
+
if (readyTransition) await announceSpawnedAgentReady(conn.agentId, "bus-ready");
|
|
271
271
|
// A parked continuation consumes one retry on a genuine ready/idle transition only.
|
|
272
272
|
const replayEpoch = continuationReplayEpoch(conn, before, after);
|
|
273
|
-
if (replayEpoch) replayParkedContinuationInjections(conn.agentId, replayEpoch);
|
|
273
|
+
if (replayEpoch) (await replayParkedContinuationInjections(conn.agentId, replayEpoch));
|
|
274
274
|
// A real PreCompact/SessionStart hook arrives as a timelineEvent in the
|
|
275
275
|
// merged meta — clears any pending stall watch (stale events ignored).
|
|
276
276
|
noteAgentTimelineEvent(conn.agentId, timelineEvent);
|
|
@@ -280,7 +280,7 @@ async function handleFrame(ws: BusWebSocket, frame: ReturnType<typeof validateCl
|
|
|
280
280
|
// #633 — silent clean-exit: a runner that stays alive after its provider terminally exited
|
|
281
281
|
// marks the offline edge with `terminalProviderExit`; the owning service turns that into a
|
|
282
282
|
// terminal event + #636 diagnosis (and clears the hold on a genuine resume).
|
|
283
|
-
reconcileTerminalProviderExit(conn.agentId, before, after);
|
|
283
|
+
await reconcileTerminalProviderExit(conn.agentId, before, after);
|
|
284
284
|
});
|
|
285
285
|
return;
|
|
286
286
|
case "ack":
|
|
@@ -306,8 +306,9 @@ async function handleCommandFrame(
|
|
|
306
306
|
target: string,
|
|
307
307
|
params: Record<string, unknown>,
|
|
308
308
|
): Promise<void> {
|
|
309
|
+
if (commandType === "agent.heartbeat") return withRelayEventDrain(() => heartbeatFromBus(conn, target, params)).then((o) => sendCommandResult(ws, frameId, o.status, o.result, o.error));
|
|
309
310
|
if (commandType === "command.update") {
|
|
310
|
-
return withRelayEventDrain(() => updateCommandFromBus({ target, params, componentAuth: conn.componentAuth }))
|
|
311
|
+
return withRelayEventDrain(async () => (await updateCommandFromBus({ target, params, componentAuth: conn.componentAuth })))
|
|
311
312
|
.then((result) => sendCommandResult(ws, frameId, result.status, result.result, result.error))
|
|
312
313
|
.catch((error) => sendError(ws, frameId, "FRAME_FAILED", errMessage(error)));
|
|
313
314
|
}
|
|
@@ -334,10 +335,10 @@ async function handleCommandFrame(
|
|
|
334
335
|
// busCommandAuthorized gate), createCommand, and the "command.requested" emit. The bus
|
|
335
336
|
// adapter only translates the typed ServiceAuthError into a rejected result frame.
|
|
336
337
|
try {
|
|
337
|
-
const command = await withRelayEventDrain(() => dispatchCommandAsync(
|
|
338
|
+
const command = await withRelayEventDrain(async () => (await dispatchCommandAsync(
|
|
338
339
|
{ type: commandType, source: conn.agentId ?? conn.componentId, target, params },
|
|
339
340
|
authContextFromBus(conn.componentAuth),
|
|
340
|
-
));
|
|
341
|
+
)));
|
|
341
342
|
sendCommandResult(ws, frameId, "succeeded", { command });
|
|
342
343
|
} catch (e) {
|
|
343
344
|
if (e instanceof ServiceAuthError) {
|
|
@@ -378,7 +379,7 @@ async function handleRegister(ws: BusWebSocket, frame: RegisterFrame): Promise<v
|
|
|
378
379
|
machine: payload.machine,
|
|
379
380
|
capabilities: payload.capabilities,
|
|
380
381
|
status: runnerManaged ? "idle" : "online",
|
|
381
|
-
ready:
|
|
382
|
+
ready: !runnerManaged,
|
|
382
383
|
instanceId: payload.instanceId,
|
|
383
384
|
...(providerCapabilities ? { providerCapabilities } : {}),
|
|
384
385
|
...(context ? { context } : {}),
|
|
@@ -386,7 +387,7 @@ async function handleRegister(ws: BusWebSocket, frame: RegisterFrame): Promise<v
|
|
|
386
387
|
...(lifecycle === "transient" || lifecycle === "persistent" ? { lifecycle } : {}),
|
|
387
388
|
meta: payload.meta,
|
|
388
389
|
};
|
|
389
|
-
const agent = registerAgent(input, authContextFromBus(ws.data.componentAuth), { emitStatus: false });
|
|
390
|
+
const agent = await registerAgent(input, authContextFromBus(ws.data.componentAuth), { emitStatus: false });
|
|
390
391
|
epoch = agent.epoch;
|
|
391
392
|
}
|
|
392
393
|
|
|
@@ -400,7 +401,7 @@ async function handleRegister(ws: BusWebSocket, frame: RegisterFrame): Promise<v
|
|
|
400
401
|
// newly registered agent stale. Fence the install on liveness and clean up the provisional
|
|
401
402
|
// registration with the same instance/epoch guard used by an established connection's close.
|
|
402
403
|
if (!liveBusSocketIds.has(ws.data.id)) {
|
|
403
|
-
if (payload.agentId &&
|
|
404
|
+
if (payload.agentId && (await applyAgentLifecycleUpdateAsync(payload.agentId, { status: "stale" }, { instanceId: payload.instanceId, epoch })).changed) {
|
|
404
405
|
queueAgentStatusEvent(payload.agentId);
|
|
405
406
|
}
|
|
406
407
|
return;
|
|
@@ -430,7 +431,7 @@ async function handleRegister(ws: BusWebSocket, frame: RegisterFrame): Promise<v
|
|
|
430
431
|
epoch,
|
|
431
432
|
cursor: getOutboxCursor(),
|
|
432
433
|
sessionId: ws.data.id,
|
|
433
|
-
features: { heartbeatAck: true },
|
|
434
|
+
features: { heartbeatAck: true, liveness: true },
|
|
434
435
|
},
|
|
435
436
|
});
|
|
436
437
|
}
|
package/src/cd-deploy-notify.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
import { getDeployEventForCommitAsync, deployChangesForCommitsAsync } from "./db/deploy-events-async";
|
|
3
|
+
import type { DeployChanges } from "./db/deploy-events";
|
|
4
|
+
import { runGit } from "./services/git-process";
|
|
1
5
|
import { VERSION } from "./config";
|
|
2
6
|
import { reportedGitSha } from "./git-sha";
|
|
3
7
|
import { routeNotification } from "./notification-router";
|
|
@@ -17,6 +21,7 @@ registerDefaultAudienceRules("cd.deploy_live", [audiencePredicates.persistentCoo
|
|
|
17
21
|
export interface CdDeployLiveInput {
|
|
18
22
|
/** Defaults to this process's package version. */
|
|
19
23
|
version?: string;
|
|
24
|
+
repoRoot?: string;
|
|
20
25
|
/** Defaults to the running process's attested commit sha (undefined on an npm install). */
|
|
21
26
|
gitSha?: string;
|
|
22
27
|
}
|
|
@@ -32,28 +37,51 @@ export interface CdDeployLiveInput {
|
|
|
32
37
|
* there is no stable identity to key the one-per-deploy dedup on, and this notice is specifically
|
|
33
38
|
* about the CD-deploy restart glitch that only that deployment model produces.
|
|
34
39
|
*/
|
|
35
|
-
export function notifyCdDeployLive(input: CdDeployLiveInput = {}): void {
|
|
40
|
+
export async function notifyCdDeployLive(input: CdDeployLiveInput = {}): Promise<void> {
|
|
36
41
|
const version = input.version ?? VERSION;
|
|
37
42
|
const gitSha = input.gitSha ?? reportedGitSha();
|
|
38
43
|
if (!gitSha) {
|
|
39
|
-
routeNotification({ type: "cd.deploy_live", scope: {}, recipients: [], message: {
|
|
44
|
+
await routeNotification({ type: "cd.deploy_live", scope: {}, recipients: [], message: {
|
|
40
45
|
body: `Humwick v${version} is now running.`, payload: { kind: "cd.deploy-live", version },
|
|
41
46
|
idempotencyKey: `release-deploy-live:${version}`, replyExpected: false,
|
|
42
47
|
} });
|
|
43
48
|
return;
|
|
44
49
|
}
|
|
45
50
|
const shortSha = gitSha.slice(0, 12);
|
|
51
|
+
const contents = await deployNoticeContents(gitSha, input.repoRoot ?? resolve(import.meta.dir, ".."));
|
|
46
52
|
|
|
47
|
-
routeNotification({
|
|
53
|
+
await routeNotification({
|
|
48
54
|
type: "cd.deploy_live",
|
|
49
55
|
scope: {},
|
|
50
56
|
ttlMs: null,
|
|
51
57
|
message: {
|
|
52
58
|
subject: `Humwick ${version} is now running`,
|
|
53
|
-
body: `Humwick v${version} (\`${shortSha}\`) is now running after a restart.
|
|
59
|
+
body: `Humwick v${version} (\`${shortSha}\`) is now running after a restart. Interrupted tool calls were the deploy, not an incident; retry them.${contents}`,
|
|
54
60
|
payload: { kind: "cd.deploy-live", version, gitSha },
|
|
55
61
|
idempotencyKey: `cd-deploy-live:${gitSha}`,
|
|
56
62
|
replyExpected: false,
|
|
57
63
|
},
|
|
58
64
|
});
|
|
59
65
|
}
|
|
66
|
+
|
|
67
|
+
async function deployNoticeContents(gitSha: string, repoRoot: string): Promise<string> {
|
|
68
|
+
const event = await getDeployEventForCommitAsync(gitSha);
|
|
69
|
+
if (!event) return "";
|
|
70
|
+
let changes: DeployChanges | undefined = event.changes;
|
|
71
|
+
if (changes?.state !== "ready") {
|
|
72
|
+
if (!event.previousSha) return "\nContents unavailable: no previous deployed SHA.";
|
|
73
|
+
const result = await runGit(["-C", repoRoot, "log", "--format=%H%x00%s", `${event.previousSha}..${gitSha}`, "--"], 5000, 1024 * 1024);
|
|
74
|
+
if (result.unavailable || result.exitCode !== 0) return "\nContents unavailable: deploy range could not be read.";
|
|
75
|
+
const commits = result.stdout.trim().split("\n").filter(Boolean).map(line => {
|
|
76
|
+
const [sha, ...subject] = line.split("\x00");
|
|
77
|
+
return { sha: sha!, subject: subject.join("\x00") };
|
|
78
|
+
});
|
|
79
|
+
changes = { state: "ready", ...await deployChangesForCommitsAsync(commits) };
|
|
80
|
+
}
|
|
81
|
+
const lines = changes.tasks.flatMap(task => [
|
|
82
|
+
`T${task.id} ${task.label.replace(/\s+/g, " ")}${task.issues.length ? ` — ${task.issues.map(issue => `${issue.repo}#${issue.externalKey} (${issue.relation ?? "references"})`).join(", ")}` : ""}`,
|
|
83
|
+
...(task.onDeploy ? [` onDeploy: ${task.onDeploy.replace(/\s+/g, " ")}`] : []),
|
|
84
|
+
]);
|
|
85
|
+
lines.push(`${changes.unmatchedCommits.length} non-Task commit(s).`);
|
|
86
|
+
return `\n${lines.join("\n")}`;
|
|
87
|
+
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { resolveCdFleetAllowlist } from "../scripts/cd-config.ts";
|
|
2
2
|
import { isCdFleetHostAllowlisted } from "../scripts/cd-fleet-membership.ts";
|
|
3
|
-
import { getConfig
|
|
4
|
-
import {
|
|
3
|
+
import { getConfig } from "./config-store.ts";
|
|
4
|
+
import { setConfigAsync } from "./config-store-write.ts";
|
|
5
|
+
import { createActivityEventAsync } from "./db/activity-async.ts";
|
|
5
6
|
import { computeFleetConvergenceAsync, type FleetConvergence } from "./fleet-convergence.ts";
|
|
6
|
-
import {
|
|
7
|
+
import { raiseOperatorAlarmAsync } from "./operator-alarm.ts";
|
|
7
8
|
import { listOrchestratorsAsync } from "./db/orchestrators-async.ts";
|
|
8
9
|
|
|
9
10
|
/** Server-side: a durable alarm per lag episode, and a recovery record when it clears. */
|
|
@@ -17,7 +18,7 @@ export async function notifyCdHostLag(convergence?: FleetConvergence, allowlist
|
|
|
17
18
|
// Keep the episode's identity while targets advance, until this Host catches up.
|
|
18
19
|
const since = previous[host.id] ?? host.lag.since;
|
|
19
20
|
current[host.id] = since;
|
|
20
|
-
|
|
21
|
+
await raiseOperatorAlarmAsync({ clientId: `cd-host-lag:${host.id}:${since}`, source: "cd-host-lag", view: "deploys",
|
|
21
22
|
subject: `CD deploy lag on ${host.id}`, dedupeEvent: true,
|
|
22
23
|
detail: `${host.id} is ${Math.floor(host.lag.ageMs / 60_000)} minutes behind ${status.targetSha.slice(0, 12)}: ${host.deferred?.reason ?? host.reason}`,
|
|
23
24
|
metadata: { orchestratorId: host.id, since, targetSha: status.targetSha, deferred: host.deferred } });
|
|
@@ -29,8 +30,8 @@ export async function notifyCdHostLag(convergence?: FleetConvergence, allowlist
|
|
|
29
30
|
if (!host || !isCdFleetHostAllowlisted(host, allowlist)) { delete current[id]; continue; }
|
|
30
31
|
if (!status.targetSha || host.gitSha !== status.targetSha) { current[id] = since; continue; }
|
|
31
32
|
delete current[id];
|
|
32
|
-
|
|
33
|
+
await createActivityEventAsync({ clientId: `cd-host-lag-resolved:${id}:${since}`, kind: "state", view: "deploys",
|
|
33
34
|
title: `CD deploy lag cleared on ${id}`, metadata: { source: "cd-host-lag", orchestratorId: id, since, resolved: true } });
|
|
34
35
|
}
|
|
35
|
-
if (JSON.stringify(current) !== JSON.stringify(previous))
|
|
36
|
+
if (JSON.stringify(current) !== JSON.stringify(previous)) await setConfigAsync("cd-host-lag", "alarms", current);
|
|
36
37
|
}
|