@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
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { resolveIssueRefFromStringAsync } from "../db/issue-refs-async";
|
|
2
|
+
|
|
1
3
|
import { isRecord } from "@humwick/sdk";
|
|
2
4
|
import { resolveProjectForCwd, spawnIssuePromptAsync } from "../db";
|
|
3
|
-
|
|
5
|
+
|
|
4
6
|
import { defaultIssueRepo } from "../config";
|
|
5
7
|
import { parseJson } from "../utils";
|
|
6
8
|
import { recordAndEmitIssueActivity } from "./issue-activity";
|
|
@@ -32,8 +34,8 @@ export async function recordSpawnPromptIssueActivity(agent: AgentCard, spawnRequ
|
|
|
32
34
|
if (!num || seen.has(num)) continue;
|
|
33
35
|
seen.add(num);
|
|
34
36
|
try {
|
|
35
|
-
const issueRef =
|
|
36
|
-
recordAndEmitIssueActivity({
|
|
37
|
+
const issueRef = await resolveIssueRefFromStringAsync({ ref: `#${num}`, defaultRepo: issueRepo });
|
|
38
|
+
await recordAndEmitIssueActivity({
|
|
37
39
|
agentId: agent.id,
|
|
38
40
|
action: "edit",
|
|
39
41
|
issueRefId: issueRef.id,
|
|
@@ -58,7 +60,7 @@ export async function recordSpawnPromptIssueActivity(agent: AgentCard, spawnRequ
|
|
|
58
60
|
* as recordSpawnPromptIssueActivity so prompt + branch refs for the same issue
|
|
59
61
|
* are deduplicated at the DB layer.
|
|
60
62
|
*/
|
|
61
|
-
export function recordWorkspaceIssueActivity(workspace: WorkspaceRecord): void {
|
|
63
|
+
export async function recordWorkspaceIssueActivity(workspace: WorkspaceRecord): Promise<void> {
|
|
62
64
|
const agentId = workspace.ownerAgentId;
|
|
63
65
|
if (!agentId || workspace.mode !== "isolated") return;
|
|
64
66
|
|
|
@@ -86,8 +88,8 @@ export function recordWorkspaceIssueActivity(workspace: WorkspaceRecord): void {
|
|
|
86
88
|
|
|
87
89
|
for (const num of seen) {
|
|
88
90
|
try {
|
|
89
|
-
const issueRef =
|
|
90
|
-
recordAndEmitIssueActivity({
|
|
91
|
+
const issueRef = await resolveIssueRefFromStringAsync({ ref: `#${num}`, defaultRepo: issueRepo });
|
|
92
|
+
await recordAndEmitIssueActivity({
|
|
91
93
|
agentId,
|
|
92
94
|
action: "edit",
|
|
93
95
|
issueRefId: issueRef.id,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { memoryRetirementMessage } from "../memory-retirement";
|
|
2
2
|
// #3121 — the provider, model and effort a spawn launches with, resolved in one place: spawnAgent uses it, and a
|
|
3
3
|
// caller that must know a launch before anything spawns (a workflow's start check) asks the same seam.
|
|
4
|
-
import type
|
|
4
|
+
import { errMessage, type SpawnProvider, type TaskDispatch } from "@humwick/sdk";
|
|
5
5
|
import { isProviderEnabled, type ProviderCatalogEntry } from "@humwick/sdk/provider-catalog";
|
|
6
6
|
import { builtInProfileSpawnDefaults, profileProviderRefusal } from "../agent-profile-catalog";
|
|
7
7
|
import { DEFAULT_SPAWN_PROFILE_NAME, getAgentProfile } from "../config-store";
|
|
@@ -14,6 +14,7 @@ import { captureDispatchContext, withProbeUncertainty, type DispatchSnapshot } f
|
|
|
14
14
|
import { finalizeLaunchDecision } from "./spawn-launch-decision";
|
|
15
15
|
import type { SpawnCapOptions } from "../spawn-placement";
|
|
16
16
|
import { resolveProjectRoleForProvider } from "./spawn-project-role";
|
|
17
|
+
import { PinnedHostCapacityError } from "../spawn-admission";
|
|
17
18
|
|
|
18
19
|
export interface SpawnLaunchInput {
|
|
19
20
|
profile?: string;
|
|
@@ -82,6 +83,21 @@ export async function resolveSpawnLaunch(input: SpawnLaunchInput, captured?: Dis
|
|
|
82
83
|
mustResolveAvailable: mustResolveAvailableFor(input.dispatchShape), orchestratorId: input.orchestratorId, spawnCap: input.spawnCap,
|
|
83
84
|
avoidProviders: input.avoidProviders,
|
|
84
85
|
});
|
|
86
|
+
try {
|
|
87
|
+
return await resolveLaunch(input, snapshot);
|
|
88
|
+
} catch (error) {
|
|
89
|
+
if (!input.orchestratorId || !snapshot.pinnedHostAtAgentCap) throw error;
|
|
90
|
+
// #3816 — prove capacity is the only refusal using the same full launch resolver.
|
|
91
|
+
try {
|
|
92
|
+
await resolveSpawnLaunch({ ...input, spawnCap: { ...input.spawnCap, attach: true } });
|
|
93
|
+
} catch {
|
|
94
|
+
throw error;
|
|
95
|
+
}
|
|
96
|
+
throw new PinnedHostCapacityError(errMessage(error), input.orchestratorId);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async function resolveLaunch(input: SpawnLaunchInput, snapshot: DispatchSnapshot): Promise<SpawnLaunch> {
|
|
85
101
|
const { catalog } = snapshot;
|
|
86
102
|
let provider = input.provider;
|
|
87
103
|
const profile = input.profile ? getAgentProfile(input.profile)?.value : undefined;
|
|
@@ -224,7 +224,7 @@ export async function escalateLostSpawnCommand(command: Command): Promise<SpawnL
|
|
|
224
224
|
// A child that DID register is alive regardless of what happened to its command row; never
|
|
225
225
|
// convert a bookkeeping loss into a phantom failure for a running agent.
|
|
226
226
|
if (spawnRequestId && await spawnWatchdogHasRegisteredAsync(spawnRequestId)) return null;
|
|
227
|
-
notifyAgentSpawnFailed({
|
|
227
|
+
await notifyAgentSpawnFailed({
|
|
228
228
|
parent,
|
|
229
229
|
...(spawnRequestId ? { spawnRequestId } : {}),
|
|
230
230
|
...(isRecord(command.params) && stringValue(command.params.provider) ? { provider: stringValue(command.params.provider)! } : {}),
|
|
@@ -209,12 +209,12 @@ export async function reapUnregisteredSpawnCommands(
|
|
|
209
209
|
const representativeId = unconfirmedIds[unconfirmedIds.length - 1] ?? group.rows[group.rows.length - 1]!.id;
|
|
210
210
|
if (undispatchable) {
|
|
211
211
|
lostSpawnCommandIds.push(representativeId);
|
|
212
|
-
notifyAgentSpawnFailed({ parent: group.parent, spawnRequestId: group.spawnRequestId, provider: group.provider, reason });
|
|
212
|
+
await notifyAgentSpawnFailed({ parent: group.parent, spawnRequestId: group.spawnRequestId, provider: group.provider, reason });
|
|
213
213
|
continue;
|
|
214
214
|
}
|
|
215
215
|
if (group.latestUpdatedAt >= notifyCutoff) {
|
|
216
216
|
notifiedUnconfirmedSpawnCommandIds.push(representativeId);
|
|
217
|
-
notifyAgentSpawnUnconfirmed({
|
|
217
|
+
await notifyAgentSpawnUnconfirmed({
|
|
218
218
|
parent: group.parent,
|
|
219
219
|
spawnRequestId: group.spawnRequestId,
|
|
220
220
|
provider: group.provider,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { cleanLandPlacement, readRepoLandPlacement } from "@humwick/sdk/land-gates";
|
|
2
|
+
import { repoWorkspaceDepsDisabled } from "@humwick/sdk/worktree-config";
|
|
2
3
|
import { existsSync } from "node:fs";
|
|
3
4
|
import { isAbsolute } from "node:path";
|
|
4
5
|
import { isRecord, normalizeGitRemoteIdentity, ValidationError, type Orchestrator } from "@humwick/sdk";
|
|
@@ -9,7 +10,7 @@ import { findGitRepoRoot } from "./canonical-root";
|
|
|
9
10
|
import { runGit, toProjectGitResult } from "./git-process";
|
|
10
11
|
import { remoteUrlFromGitRemoteAsync } from "./git-remote";
|
|
11
12
|
|
|
12
|
-
export type RepoProbe = { kind: "present"; repoRoot?: string; remoteIdentity?: string; placementPlatforms?: string[]; toolchainError?: string }
|
|
13
|
+
export type RepoProbe = { kind: "present"; repoRoot?: string; remoteIdentity?: string; placementPlatforms?: string[]; workspaceDepsDisabled?: boolean; toolchainError?: string }
|
|
13
14
|
/** `occupied`: the path exists but is not inside a git checkout, so no clone can land there (#3347). */
|
|
14
15
|
| { kind: "absent"; occupied?: boolean } | { kind: "timeout" } | { kind: "unavailable"; reason?: string };
|
|
15
16
|
|
|
@@ -77,17 +78,18 @@ export async function probeLocalSourceRepo(path: string, baseRef?: string | null
|
|
|
77
78
|
if (!root) return { kind: "absent", occupied: true };
|
|
78
79
|
const remote = await remoteUrlFromGitRemoteAsync(root, { refresh: true });
|
|
79
80
|
let placementPlatforms: string[] | undefined;
|
|
81
|
+
const workspaceDepsDisabled = await repoWorkspaceDepsDisabled(placementGit(root));
|
|
80
82
|
if (baseRef !== undefined) {
|
|
81
83
|
try {
|
|
82
84
|
placementPlatforms = await readRepoLandPlacement(baseRef ?? undefined, placementGit(root));
|
|
83
85
|
} catch (error) { return { kind: "unavailable", reason: String(error) }; }
|
|
84
86
|
}
|
|
85
|
-
return { kind: "present", repoRoot: root, ...(placementPlatforms ? { placementPlatforms } : {}), ...(remote ? { remoteIdentity: normalizeGitRemoteIdentity(remote) } : {}) };
|
|
87
|
+
return { kind: "present", repoRoot: root, workspaceDepsDisabled, ...(placementPlatforms ? { placementPlatforms } : {}), ...(remote ? { remoteIdentity: normalizeGitRemoteIdentity(remote) } : {}) };
|
|
86
88
|
}
|
|
87
89
|
|
|
88
90
|
async function probeRemoteRepo(host: Orchestrator, path: string, baseRef?: string | null, toolchain = false): Promise<RepoProbe> {
|
|
89
91
|
if (!host.apiUrl || !isTrustedOrchestratorApiUrl(host.apiUrl)) return { kind: "unavailable" };
|
|
90
|
-
const result = await fetchHostJson<{ isGitRepo: boolean; definite?: boolean; pathExists?: boolean; repoRoot?: string; remoteIdentity?: string; placementPlatforms?: string[]; placementError?: string; toolchainError?: string }>(host.apiUrl, "/api/repo/identity", {
|
|
92
|
+
const result = await fetchHostJson<{ isGitRepo: boolean; definite?: boolean; pathExists?: boolean; repoRoot?: string; remoteIdentity?: string; placementPlatforms?: string[]; workspaceDepsDisabled?: boolean; placementError?: string; toolchainError?: string }>(host.apiUrl, "/api/repo/identity", {
|
|
91
93
|
query: new URLSearchParams({ path, ...(toolchain ? { toolchain: "1" } : {}), ...(baseRef ? { baseRef } : baseRef === null ? { placement: "1" } : {}) }), timeoutMs: toolchain ? 50_000 : 20_000,
|
|
92
94
|
validate: (body) => {
|
|
93
95
|
if (!isRecord(body) || typeof body.isGitRepo !== "boolean"
|
|
@@ -101,14 +103,14 @@ async function probeRemoteRepo(host: Orchestrator, path: string, baseRef?: strin
|
|
|
101
103
|
let placementPlatforms: string[] | undefined;
|
|
102
104
|
try { placementPlatforms = cleanLandPlacement({ placement: { platforms: body.placementPlatforms } })?.platforms; }
|
|
103
105
|
catch (error) { console.warn(`${host.id}: invalid repository placement: ${String(error)}`); }
|
|
104
|
-
return { ok: true, value: { ...(typeof body.toolchainError === "string" ? { toolchainError: body.toolchainError } : {}), isGitRepo: body.isGitRepo, definite: body.definite === true, pathExists: body.pathExists === true, ...(typeof body.placementError === "string" ? { placementError: body.placementError } : {}), ...(placementPlatforms ? { placementPlatforms } : {}),
|
|
106
|
+
return { ok: true, value: { workspaceDepsDisabled: body.workspaceDepsDisabled === true, ...(typeof body.toolchainError === "string" ? { toolchainError: body.toolchainError } : {}), isGitRepo: body.isGitRepo, definite: body.definite === true, pathExists: body.pathExists === true, ...(typeof body.placementError === "string" ? { placementError: body.placementError } : {}), ...(placementPlatforms ? { placementPlatforms } : {}),
|
|
105
107
|
...(typeof body.repoRoot === "string" ? { repoRoot: body.repoRoot } : {}),
|
|
106
108
|
...(typeof body.remoteIdentity === "string" ? { remoteIdentity: body.remoteIdentity } : {}) } };
|
|
107
109
|
},
|
|
108
110
|
});
|
|
109
111
|
if (result.ok && baseRef !== undefined && result.value.placementError) return { kind: "unavailable", reason: result.value.placementError };
|
|
110
112
|
if (result.ok) return result.value.isGitRepo
|
|
111
|
-
? { kind: "present", ...(result.value.toolchainError ? { toolchainError: result.value.toolchainError } : {}), ...(result.value.repoRoot ? { repoRoot: result.value.repoRoot } : {}), ...(result.value.placementPlatforms ? { placementPlatforms: result.value.placementPlatforms } : {}), ...(result.value.remoteIdentity ? { remoteIdentity: result.value.remoteIdentity } : {}) }
|
|
113
|
+
? { kind: "present", workspaceDepsDisabled: result.value.workspaceDepsDisabled, ...(result.value.toolchainError ? { toolchainError: result.value.toolchainError } : {}), ...(result.value.repoRoot ? { repoRoot: result.value.repoRoot } : {}), ...(result.value.placementPlatforms ? { placementPlatforms: result.value.placementPlatforms } : {}), ...(result.value.remoteIdentity ? { remoteIdentity: result.value.remoteIdentity } : {}) }
|
|
112
114
|
// Old orchestrators also returned false for a killed/timed-out probe (#2715).
|
|
113
115
|
: result.value.definite === true ? { kind: "absent", ...(result.value.pathExists ? { occupied: true } : {}) } : { kind: "unavailable" };
|
|
114
116
|
const failure = result.failure;
|
|
@@ -2,36 +2,35 @@ import { errMessage, stringValue } from "@humwick/sdk";
|
|
|
2
2
|
import type { WorkflowEffect } from "@humwick/kernel/workflow.pilot";
|
|
3
3
|
import { getGateway } from "../db/gateway";
|
|
4
4
|
import { getAgentAsync } from "../db";
|
|
5
|
+
import { isTerminalCommandStatus } from "../db/command-terminal-status";
|
|
5
6
|
import { shutdownAgent } from "./shutdown-agent";
|
|
6
7
|
import { currentStop } from "./workflow-effects";
|
|
7
|
-
import { invoke, supervisorNow, type Supervisor } from "./workflow-supervisor-state";
|
|
8
|
+
import { invoke, retryResult, supervisorNow, type Supervisor } from "./workflow-supervisor-state";
|
|
8
9
|
|
|
9
10
|
/** Every retry resumes the same outbox effect; only host witnesses release reservations. */
|
|
10
11
|
export async function performSpawnTreeCleanup(sup: Supervisor, effect: WorkflowEffect): Promise<boolean> {
|
|
11
12
|
const now = supervisorNow();
|
|
12
|
-
if (typeof effect.result?.nextAttemptAt === "number" && effect.result.nextAttemptAt > now) return false;
|
|
13
13
|
const agentId = String(effect.payload.agentId);
|
|
14
14
|
await getGateway().write("spawnTree.prepareCleanup", { agentId });
|
|
15
15
|
const targets = await getGateway().read("spawnTree.cleanupTargets", { agentId });
|
|
16
16
|
const retry: Array<{ spawnRequestId: string; error: string }> = [];
|
|
17
|
+
let inFlight = false;
|
|
17
18
|
for (const target of targets) {
|
|
18
19
|
if (target.processGone) continue;
|
|
19
20
|
try {
|
|
20
21
|
const agent = await getAgentAsync(target.agentId);
|
|
21
22
|
const generation = stringValue(agent?.meta?.spawnRequestId) ?? target.spawnRequestId;
|
|
22
|
-
const { id, prior } = await currentStop(`${effect.id}:stop:${target.spawnRequestId}:${generation}`,
|
|
23
|
-
command.result?.targetNotFound !== true || now - command.updatedAt >= 15 * 60_000);
|
|
23
|
+
const { id, prior } = await currentStop(`${effect.id}:stop:${target.spawnRequestId}:${generation}`, now);
|
|
24
24
|
const command = prior ?? (await shutdownAgent({
|
|
25
25
|
...(agent ? { agentId: agent.id } : {}), spawnRequestId: generation, orchestratorId: target.orchestratorId,
|
|
26
26
|
commandId: id, requireProcessTreeProof: true, graceful: false, force: true,
|
|
27
27
|
reason: String(effect.payload.reason), requestedVia: "bus", requestedBy: "workflow",
|
|
28
28
|
}, { actor: { id: "workflow", kind: "system" }, scopes: [] })).command;
|
|
29
29
|
if (command.status !== "succeeded" || command.result?.processTreeStopped !== true) retry.push({ spawnRequestId: target.spawnRequestId, error: `shutdown ${command.id}: ${command.status}` });
|
|
30
|
+
if (!isTerminalCommandStatus(command.status)) inFlight = true;
|
|
30
31
|
} catch (error) { retry.push({ spawnRequestId: target.spawnRequestId, error: errMessage(error) }); }
|
|
31
32
|
}
|
|
32
|
-
const
|
|
33
|
-
await invoke(sup, "settleEffect", { id: effect.id, status: retry.length ? "pending" : "done", result:
|
|
34
|
-
targets: targets.length, retry, checkedAt: now, ...(retry.length ? { nextAttemptAt: now + delay } : {}),
|
|
35
|
-
} });
|
|
33
|
+
const result = { targets: targets.length, retry, checkedAt: now, ...(inFlight ? { inFlight } : {}) };
|
|
34
|
+
await invoke(sup, "settleEffect", { id: effect.id, status: retry.length ? "pending" : "done", result: retry.length ? retryResult(effect.result, result, now) : result });
|
|
36
35
|
return retry.length === 0;
|
|
37
36
|
}
|
|
@@ -164,13 +164,13 @@ export async function reapIdleStewards(opts: { now?: number; signal?: AbortSigna
|
|
|
164
164
|
if (entry.attempts >= STEWARD_REAP_MAX_ATTEMPTS) {
|
|
165
165
|
if (!entry.alarmed) {
|
|
166
166
|
entry.alarmed = true;
|
|
167
|
-
raiseOperatorAlarm({
|
|
167
|
+
(await raiseOperatorAlarm({
|
|
168
168
|
clientId: `steward-zombie-blocking-${agent.id}`,
|
|
169
169
|
source: "steward-reaper",
|
|
170
170
|
subject: "Steward zombie is blocking a repo/host steward slot",
|
|
171
171
|
detail: `Steward \`${agent.id}\` (${agent.label ?? "unlabelled"}, host ${agent.machine ?? "unknown"}) ignored ${entry.attempts} shutdown attempt(s) and is holding the one-per-repo/host steward slot — no new steward can spawn there until it is killed. Investigate and terminate it manually.`,
|
|
172
172
|
metadata: { maintenanceJobId: "steward-reaper", agentId: agent.id, label: agent.label, machine: agent.machine, attempts: entry.attempts },
|
|
173
|
-
});
|
|
173
|
+
}));
|
|
174
174
|
}
|
|
175
175
|
reapTracker.set(agent.id, entry);
|
|
176
176
|
alarmed.push(agent.id);
|
|
@@ -192,7 +192,7 @@ export async function reapIdleStewards(opts: { now?: number; signal?: AbortSigna
|
|
|
192
192
|
entry.lastAt = now;
|
|
193
193
|
reapTracker.set(agent.id, entry);
|
|
194
194
|
if (graceful) {
|
|
195
|
-
requestTransientAgentShutdown(agent, {
|
|
195
|
+
(await requestTransientAgentShutdown(agent, {
|
|
196
196
|
reason: disabled ? "steward-disabled" : "steward-orphan-idle",
|
|
197
197
|
requestedBy: "steward-reaper",
|
|
198
198
|
activityTitle: disabled ? "Orphaned steward reaped (spawning disabled)" : "Orphaned steward reaped",
|
|
@@ -201,7 +201,7 @@ export async function reapIdleStewards(opts: { now?: number; signal?: AbortSigna
|
|
|
201
201
|
: "Steward has no live managed policy state and has been idle past the keepalive grace; reaping.",
|
|
202
202
|
landReason: disabled ? "steward-disabled" : "steward-orphan-idle",
|
|
203
203
|
now,
|
|
204
|
-
});
|
|
204
|
+
}));
|
|
205
205
|
} else {
|
|
206
206
|
// A plain agent-targeted `agent.shutdown` — graceful or not — is INERT against a runner that
|
|
207
207
|
// has stopped reading its own commands (runner-core keys kill-hardness off the command TYPE,
|
|
@@ -48,6 +48,10 @@ export interface TaskHydrationFacets {
|
|
|
48
48
|
/** #2728 — the Task's `context` facet (free-text facts a coordinator must not resend by message). */
|
|
49
49
|
context?: string;
|
|
50
50
|
doneWhen?: string;
|
|
51
|
+
/** #3808 — the Task's `terminalStage` (deployed = deploy/live proof happens after land). */
|
|
52
|
+
terminalStage?: string;
|
|
53
|
+
/** #3808 — the Task's `onDeploy` follow-up, run after the deploy, not by the worker. */
|
|
54
|
+
onDeploy?: string;
|
|
51
55
|
issues: ResolvedIssueSpec[];
|
|
52
56
|
/** Decisions/rules: discussion + milestone write-throughs and steers (the narrative ledger). */
|
|
53
57
|
decisions: TaskEvent[];
|
|
@@ -165,12 +169,28 @@ function renderContextFacet(value: string | undefined): string {
|
|
|
165
169
|
return `\nContext (Task data):\n${fence(truncate(text, TASK_CONTEXT_LIMIT))}\n`;
|
|
166
170
|
}
|
|
167
171
|
|
|
172
|
+
/** #3808 — post-deploy criteria rendered apart from the worker's acceptance: they are checked after land
|
|
173
|
+
* (QA / onDeploy) and must never read as unmet delivery criteria. Empty when the Task has none, so the
|
|
174
|
+
* template line collapses to a blank line (the `{{context}}` seam's shape). */
|
|
175
|
+
function renderAfterLandFacet(facets: Pick<TaskHydrationFacets, "terminalStage" | "onDeploy">): string {
|
|
176
|
+
const onDeploy = facets.onDeploy?.trim();
|
|
177
|
+
const deployed = facets.terminalStage === "deployed";
|
|
178
|
+
if (!onDeploy && !deployed) return "";
|
|
179
|
+
const parts = [
|
|
180
|
+
"\nAfter land (checked by QA/onDeploy once the change is live; NOT yours and never blocks delivery — deliver `complete` when code, tests and the delivery gate pass):",
|
|
181
|
+
];
|
|
182
|
+
if (deployed) parts.push("- Terminal stage is deployed: deploy, live-check and independent-reproduction criteria in the acceptance above belong here, not to your delivery.");
|
|
183
|
+
if (onDeploy) parts.push(`- onDeploy follow-up:\n${fence(truncate(onDeploy, TASK_CONTEXT_LIMIT))}`);
|
|
184
|
+
return `${parts.join("\n")}\n`;
|
|
185
|
+
}
|
|
186
|
+
|
|
168
187
|
export function renderTaskHydration(facets: TaskHydrationFacets): string {
|
|
169
188
|
const issues = facets.issues.length ? facets.issues.map(renderIssue).join("\n") : "- none linked";
|
|
170
189
|
const decisions = facets.decisions.length ? facets.decisions.map(renderEvent).join("\n") : "- none recorded";
|
|
171
190
|
const history = facets.history.length ? facets.history.map(renderEvent).join("\n") : "- none yet";
|
|
172
191
|
const memory = facets.memory ? `\n${fence(facets.memory)}\n` : "";
|
|
173
192
|
const context = renderContextFacet(facets.context);
|
|
193
|
+
const afterLand = renderAfterLandFacet(facets);
|
|
174
194
|
const rendered = renderTemplate("task.hydration", {
|
|
175
195
|
taskId: String(facets.taskId),
|
|
176
196
|
title: inlineSafe(facets.title),
|
|
@@ -180,6 +200,7 @@ export function renderTaskHydration(facets: TaskHydrationFacets): string {
|
|
|
180
200
|
intent: fence(facets.intent || "(no intent recorded)"),
|
|
181
201
|
context,
|
|
182
202
|
doneWhen: fence(facets.doneWhen || "(no explicit acceptance recorded)"),
|
|
203
|
+
afterLand,
|
|
183
204
|
issues,
|
|
184
205
|
decisions,
|
|
185
206
|
history,
|
|
@@ -187,7 +208,8 @@ export function renderTaskHydration(facets: TaskHydrationFacets): string {
|
|
|
187
208
|
steer: fence(facets.steer || "(no steer provided — proceed toward the acceptance above)"),
|
|
188
209
|
}).trimEnd();
|
|
189
210
|
// Saved operator templates can predate {{context}}; required Task data must still reach the worker (#3245).
|
|
190
|
-
|
|
211
|
+
const withContext = context && !rendered.includes(context.trim()) ? `${rendered}\n${context}`.trimEnd() : rendered;
|
|
212
|
+
return afterLand && !withContext.includes(afterLand.trim()) ? `${withContext}\n${afterLand}`.trimEnd() : withContext;
|
|
191
213
|
}
|
|
192
214
|
|
|
193
215
|
function hasTaskMemory(envelope: TaskMemoryEnvelope): boolean {
|
|
@@ -346,6 +368,8 @@ export async function hydrateTaskContext(input: HydrateTaskContextInput): Promis
|
|
|
346
368
|
intent: task.intent ?? task.title,
|
|
347
369
|
...(task.context?.trim() ? { context: task.context } : {}),
|
|
348
370
|
...(task.doneWhen ? { doneWhen: task.doneWhen } : {}),
|
|
371
|
+
...(task.terminalStage ? { terminalStage: task.terminalStage } : {}),
|
|
372
|
+
...(task.onDeploy?.trim() ? { onDeploy: task.onDeploy } : {}),
|
|
349
373
|
issues,
|
|
350
374
|
decisions,
|
|
351
375
|
history,
|
|
@@ -1,20 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
insertTaskEvent,
|
|
5
|
-
markTaskDeliverableEffectsCompleteAsync,
|
|
6
|
-
ownedIsolatedWorkspace,
|
|
7
|
-
recordGateAsync,
|
|
8
|
-
recordTaskDeliverableAsync,
|
|
9
|
-
recordTaskDeliverableWithLandingIngressAsync,
|
|
10
|
-
setTaskStage,
|
|
11
|
-
setTaskStatus,
|
|
12
|
-
setTaskStatusAsync,
|
|
13
|
-
transitionWorkspaceLandStateAsync,
|
|
14
|
-
workspaceLandAuthorization, workspaceLandAuthorizationWithdrawn,
|
|
15
|
-
ValidationError,
|
|
16
|
-
type CompleteDeliveryArmOutcome,
|
|
17
|
-
} from "../db";
|
|
1
|
+
import { setTaskStatusAsync, setTaskStageAsync } from "../db/task-entity-async";
|
|
2
|
+
import { insertTaskEventAsync } from "../db/runtime-tail-async";
|
|
3
|
+
import { getTaskDetail, getWorkspace, markTaskDeliverableEffectsCompleteAsync, ownedIsolatedWorkspace, recordGateAsync, recordTaskDeliverableAsync, recordTaskDeliverableWithLandingIngressAsync, transitionWorkspaceLandStateAsync, workspaceLandAuthorization, workspaceLandAuthorizationWithdrawn, ValidationError, type CompleteDeliveryArmOutcome } from "../db";
|
|
18
4
|
import { refreshWorkspaceGitState } from "../workspace-probe";
|
|
19
5
|
import { pinWorkspaceDeliveryTip } from "../workspace-delivery-tip";
|
|
20
6
|
import { recoverIsolatedWorkspace, type WorkspaceRecoveryHint } from "./workspace-recovery";
|
|
@@ -25,7 +11,7 @@ import { emitTaskChanged, emitNewMessages } from "../sse";
|
|
|
25
11
|
import { agentBoundTaskIds, hasTaskReadAdminScope } from "../task-authz";
|
|
26
12
|
import { applyWorkspaceAction } from "../workspace-actions";
|
|
27
13
|
import { LAND_IN_FLIGHT_STATUSES, LAND_REQUEST_STALE_ON_HEAD_ADVANCE_STATUSES } from "../workspace-phase";
|
|
28
|
-
import {
|
|
14
|
+
import { findLatestCommandByCorrelationAsync } from "../commands-write";
|
|
29
15
|
import { mergeCommandNeedsRetry } from "../workspace-merge-progress";
|
|
30
16
|
import { workspaceLandNeedsRearm } from "../workspace-land-retry";
|
|
31
17
|
import { emitTaskSemanticNotification } from "./task-semantic-events";
|
|
@@ -120,7 +106,7 @@ function shouldRebindToWorkspace(task: TaskDetail, ws: WorkspaceRecord | undefin
|
|
|
120
106
|
return Boolean(task.branch && ws?.branch && task.branch !== ws.branch);
|
|
121
107
|
}
|
|
122
108
|
|
|
123
|
-
function resolveWorkspace(ctx: AuthContext, input: Pick<DeliverTaskInput, "workspaceId" | "workspace" | "idempotencyKey">, taskId: number, opts: { allowRebind?: boolean } = {}): WorkspaceRecord | undefined {
|
|
109
|
+
async function resolveWorkspace(ctx: AuthContext, input: Pick<DeliverTaskInput, "workspaceId" | "workspace" | "idempotencyKey">, taskId: number, opts: { allowRebind?: boolean } = {}): Promise<WorkspaceRecord | undefined> {
|
|
124
110
|
const caller = ctx.callerAgentId;
|
|
125
111
|
const explicit = input.workspaceId?.trim();
|
|
126
112
|
let ws = explicit ? getWorkspace(explicit) : caller ? ownedIsolatedWorkspace(caller) : undefined;
|
|
@@ -133,7 +119,7 @@ function resolveWorkspace(ctx: AuthContext, input: Pick<DeliverTaskInput, "works
|
|
|
133
119
|
// server-authoritative recovery (signed spawn-request association + immutable agent.spawn params +
|
|
134
120
|
// orchestrator baseDir containment); the descriptor is an untrusted hint, never trusted verbatim.
|
|
135
121
|
if (!ws && input.workspace) {
|
|
136
|
-
const recovery = recoverIsolatedWorkspace(ctx, input.workspace, explicit);
|
|
122
|
+
const recovery = (await recoverIsolatedWorkspace(ctx, input.workspace, explicit));
|
|
137
123
|
if (recovery.ok) ws = recovery.workspace;
|
|
138
124
|
}
|
|
139
125
|
if (!ws) return undefined;
|
|
@@ -149,18 +135,18 @@ function resolveWorkspace(ctx: AuthContext, input: Pick<DeliverTaskInput, "works
|
|
|
149
135
|
return ws;
|
|
150
136
|
}
|
|
151
137
|
|
|
152
|
-
function rebindTaskToWorkspaceIfNeeded(task: TaskDetail, ws: WorkspaceRecord | undefined, actor: string): TaskDetail {
|
|
138
|
+
async function rebindTaskToWorkspaceIfNeeded(task: TaskDetail, ws: WorkspaceRecord | undefined, actor: string): Promise<TaskDetail> {
|
|
153
139
|
if (!shouldRebindToWorkspace(task, ws)) return task;
|
|
154
|
-
|
|
140
|
+
(await setTaskStatusAsync(task.id, {
|
|
155
141
|
status: "in_progress",
|
|
156
142
|
note: `fix-forward rebind to workspace ${ws.id} (${ws.branch})`,
|
|
157
143
|
actor,
|
|
158
|
-
});
|
|
159
|
-
return
|
|
144
|
+
}));
|
|
145
|
+
return (await setTaskStageAsync(task.id, {
|
|
160
146
|
deliverableStage: "committed-on-branch",
|
|
161
147
|
branch: ws.branch,
|
|
162
148
|
actor,
|
|
163
|
-
});
|
|
149
|
+
}));
|
|
164
150
|
}
|
|
165
151
|
|
|
166
152
|
function cleanReason(value: unknown, disposition: "blocked" | "failed"): string {
|
|
@@ -189,7 +175,7 @@ function skippedRequiredGateReports(reason: string): Required<Pick<TaskDeliveryG
|
|
|
189
175
|
// Non-landing dispositions (blocked/failed/needs-review, and a verdict-only complete that closes on
|
|
190
176
|
// delivery with no land) keep their honest existing wording. #2518 adds the third shape: a complete
|
|
191
177
|
// delivery ACCEPTED but HELD for coordinator review — it says exactly that and never claims landing.
|
|
192
|
-
function notifyDelivery(taskId: number, eventId: number, metadata: TaskDeliverableEventMetadata, landing: boolean): void {
|
|
178
|
+
async function notifyDelivery(taskId: number, eventId: number, metadata: TaskDeliverableEventMetadata, landing: boolean): Promise<void> {
|
|
193
179
|
const task = getTaskDetail(taskId);
|
|
194
180
|
if (!task) return;
|
|
195
181
|
const linkedIssues = task.issues.map((issue) => ({ provider: issue.provider, repo: issue.repo, externalKey: issue.externalKey, title: issue.title, status: issue.status }));
|
|
@@ -227,7 +213,7 @@ function notifyDelivery(taskId: number, eventId: number, metadata: TaskDeliverab
|
|
|
227
213
|
const notArmedWarning = metadata.landNotArmedReason && unmergedAhead > 0
|
|
228
214
|
? `\n⚠ NOT landed: ${unmergedAhead} unmerged commit(s) remain on ${metadata.workspaceId ?? "the workspace"} (no land armed — ${metadata.landNotArmedReason}). Land it explicitly if this work belongs on main.`
|
|
229
215
|
: "";
|
|
230
|
-
const delivered = routeNotification({
|
|
216
|
+
const delivered = await routeNotification({
|
|
231
217
|
type: "task.deliverable",
|
|
232
218
|
scope: {
|
|
233
219
|
taskId: String(taskId),
|
|
@@ -309,7 +295,7 @@ export async function deliverTask(input: DeliverTaskInput, ctx: AuthContext): Pr
|
|
|
309
295
|
// `complete` changes, from a hard reject to the same owner-authorized resolve the land path had.
|
|
310
296
|
// The TASK-record rebind itself (rebindTaskToWorkspaceIfNeeded) is still gated on `wantsLand`.
|
|
311
297
|
let workspace = input.disposition === "complete" || input.workspaceId
|
|
312
|
-
? resolveWorkspace(ctx, input, taskId, { allowRebind: input.disposition === "complete" })
|
|
298
|
+
? (await resolveWorkspace(ctx, input, taskId, { allowRebind: input.disposition === "complete" }))
|
|
313
299
|
: undefined;
|
|
314
300
|
// A workspace that could actually carry a land: isolated, live on disk, and on a branch. Mirrors
|
|
315
301
|
// the preconditions enforced below (:live isolated workspace / :exact resolved source ref), so a
|
|
@@ -459,7 +445,7 @@ export async function deliverTask(input: DeliverTaskInput, ctx: AuthContext): Pr
|
|
|
459
445
|
}
|
|
460
446
|
if (ahead > 0) landNotArmed = { reason: workspaceLandBlocked(workspace) ? "workspace-land-blocked" : landDecision.reason, unmergedAhead: ahead };
|
|
461
447
|
}
|
|
462
|
-
const currentTask = wantsLand && !noWork ? rebindTaskToWorkspaceIfNeeded(before, workspace, actor) : before;
|
|
448
|
+
const currentTask = wantsLand && !noWork ? (await rebindTaskToWorkspaceIfNeeded(before, workspace, actor)) : before;
|
|
463
449
|
const sourceRef = wantsLand ? replayLand?.sourceRef ?? workspace?.branch?.trim() : undefined;
|
|
464
450
|
// Only the HEAD returned by THIS host probe can authorize ingress. Persisted metadata may be
|
|
465
451
|
// stale, and the caller's commit list is a self-report; neither is authority for a mutable ref.
|
|
@@ -520,7 +506,7 @@ export async function deliverTask(input: DeliverTaskInput, ctx: AuthContext): Pr
|
|
|
520
506
|
// Pin the delivered tip captured at delivery; the host publishes it ONLY if reachable from the
|
|
521
507
|
// verified workspace tip, else REFUSES (H1 — fail closed), so no unrelated local commit rides in.
|
|
522
508
|
const deliveredSha = input.commits?.length ? input.commits[input.commits.length - 1]?.sha : undefined;
|
|
523
|
-
reviewPublish = dispatchReviewPublish(reviewWorkspace, { requestedBy: actor, taskId, sha: deliveredSha, emit: emitCommand });
|
|
509
|
+
reviewPublish = (await dispatchReviewPublish(reviewWorkspace, { requestedBy: actor, taskId, sha: deliveredSha, emit: emitCommand }));
|
|
524
510
|
}
|
|
525
511
|
const deliveryInput = {
|
|
526
512
|
...input,
|
|
@@ -617,9 +603,9 @@ export async function deliverTask(input: DeliverTaskInput, ctx: AuthContext): Pr
|
|
|
617
603
|
const detail = getTaskDetail(taskId) ?? currentTask;
|
|
618
604
|
if (detail) {
|
|
619
605
|
emitTaskChanged(detail, "task.deliverable");
|
|
620
|
-
notifyDelivery(taskId, delivery.event.id, eventMeta ?? (delivery.event.metadata as unknown as TaskDeliverableEventMetadata), wantsLand && armOutcome === "armed");
|
|
606
|
+
await notifyDelivery(taskId, delivery.event.id, eventMeta ?? (delivery.event.metadata as unknown as TaskDeliverableEventMetadata), wantsLand && armOutcome === "armed");
|
|
621
607
|
if (input.disposition === "failed") {
|
|
622
|
-
emitTaskSemanticNotification({ task: detail, transition: "gate-failed", actor, occurrenceKey: `event:${delivery.event.id}`, outcome: { disposition: "failed" } });
|
|
608
|
+
await emitTaskSemanticNotification({ task: detail, transition: "gate-failed", actor, occurrenceKey: `event:${delivery.event.id}`, outcome: { disposition: "failed" } });
|
|
623
609
|
}
|
|
624
610
|
}
|
|
625
611
|
}
|
|
@@ -685,7 +671,7 @@ export async function deliverTask(input: DeliverTaskInput, ctx: AuthContext): Pr
|
|
|
685
671
|
// into same-head `already-requested`; only terminal non-PR attempts qualify,
|
|
686
672
|
// so a currently running merge or a PR waiting on GitHub is never doubled.
|
|
687
673
|
const priorMerge = LAND_IN_FLIGHT_STATUSES.has(liveWorkspace.status)
|
|
688
|
-
?
|
|
674
|
+
? await findLatestCommandByCorrelationAsync("workspace.merge", liveWorkspace.id)
|
|
689
675
|
: null;
|
|
690
676
|
const retryableMergePlan = mergeCommandNeedsRetry(priorMerge);
|
|
691
677
|
const withdrawnLand = !hadLandAuthorization
|
|
@@ -697,7 +683,7 @@ export async function deliverTask(input: DeliverTaskInput, ctx: AuthContext): Pr
|
|
|
697
683
|
// exhausted. applyWorkspaceAction clears the old retry incident before re-arming it.
|
|
698
684
|
|| retryableMergePlan || workspaceLandNeedsRearm(liveWorkspace) || withdrawnLand;
|
|
699
685
|
if (reenterLand) {
|
|
700
|
-
markAgentWorkFinal(actor, "task-deliver");
|
|
686
|
+
(await markAgentWorkFinal(actor, "task-deliver"));
|
|
701
687
|
const result = await applyWorkspaceAction(liveWorkspace, {
|
|
702
688
|
action: "ready",
|
|
703
689
|
agentId: actor,
|