@humwick/server 0.130.0 → 0.130.2
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/docs/guides/tools-administration.md +6 -1
- package/docs/guides/tools-coordination.md +1 -0
- package/docs/guides/tools-tasks.md +8 -0
- package/docs/guides/workflows.md +58 -0
- package/docs/openapi.json +414 -1
- package/package.json +8 -17
- package/public/assets/{MessageBubble-BWpoBjl4.js → MessageBubble-BWLqMGKG.js} +2 -2
- package/public/assets/{PlanGraphPanel-C0auck3n.js → PlanGraphPanel-3TlIQpjk.js} +2 -2
- package/public/assets/{TraceView-DBnOx7AQ.js → TraceView-Wimm0Czv.js} +2 -2
- package/public/assets/{VaultDecisionCard-0kp2oNBC.js → VaultDecisionCard-Bau_vNax.js} +2 -2
- package/public/assets/{activity-yLztXEBt.js → activity-CrSurn-r.js} +2 -2
- package/public/assets/{agent-lineage-BbJDR1dW.js → agent-lineage-CknAJKcb.js} +2 -2
- package/public/assets/agent-liveness-CaNwK0Zf.js +2 -0
- package/public/assets/{agent-name-CTZBrSD9.js → agent-name-DKbiIhBo.js} +2 -2
- package/public/assets/agent-profiles-DwF6EQ4R.js +2 -0
- package/public/assets/{agent-project-badge-9TqzUUYE.js → agent-project-badge-Diz4Sjjb.js} +2 -2
- package/public/assets/{agent-tools-D4n40pn8.js → agent-tools-CRhpRQza.js} +2 -2
- package/public/assets/{agent-type-icon-D6FUarOf.js → agent-type-icon-LrUEU3lB.js} +2 -2
- package/public/assets/{agents-BYDslkJc.js → agents-B-v66C-4.js} +2 -2
- package/public/assets/{analytics-B-XSbEMC.js → analytics-BqCb-LKi.js} +2 -2
- package/public/assets/{artifact-viewer-DdWIfV6M.js → artifact-viewer-kf4pGuAR.js} +2 -2
- package/public/assets/{artifacts-oBOqks-2.js → artifacts-D32zyw4Y.js} +2 -2
- package/public/assets/{artifacts-DPN1q4pA.js → artifacts-DJevXcvg.js} +2 -2
- package/public/assets/{automation-4KcRFXEu.js → automation-BpRajx_5.js} +2 -2
- package/public/assets/{backlog-Cw9xPTCF.js → backlog-D_UjTdzX.js} +2 -2
- package/public/assets/{busy-health-CTu32MZt.js → busy-health-N3VEh4ao.js} +2 -2
- package/public/assets/{channels-BiXzg1G9.js → channels-9jopungq.js} +2 -2
- package/public/assets/{chat-Ctk2qwvA.js → chat-CSXrTB3C.js} +2 -2
- package/public/assets/{code-preview-Bm1wWqAp.js → code-preview-p1NnmqK0.js} +2 -2
- package/public/assets/{connectors-C36ax4Vw.js → connectors-CZdqlDNL.js} +2 -2
- package/public/assets/{cosmos-Jj9LK2Wf.js → cosmos-BgdsE4dG.js} +2 -2
- package/public/assets/{crate-agent-H6S7-B9T.js → crate-agent-30aXTKva.js} +2 -2
- package/public/assets/{dependency-graph-Cd1E23wa.js → dependency-graph-B_jvw2GE.js} +2 -2
- package/public/assets/{deploys-Bwfq146q.js → deploys-DoN6bAb5.js} +2 -2
- package/public/assets/{display-CfO7rTuF.js → display-BrKWFGJz.js} +2 -2
- package/public/assets/{files-DhhZI2Ih.js → files-D6XEu8Ng.js} +2 -2
- package/public/assets/fleet-C7jQWbw2.js +2 -0
- package/public/assets/{fleet-metrics-BkHP-P3R.js → fleet-metrics-BiDs3MLx.js} +2 -2
- package/public/assets/{formatted-body-Cm1RrzmN.js → formatted-body-CQBwc1fb.js} +3 -3
- package/public/assets/{formatted-body-impl-DQiOuOD1.js → formatted-body-impl-DyG0WsQS.js} +2 -2
- package/public/assets/{host-providers-dialog-CHqwXTov.js → host-providers-dialog-DKaW31dN.js} +2 -2
- package/public/assets/index-CRHep3M9.js +15 -0
- package/public/assets/index-MYAIwYTX.css +2 -0
- package/public/assets/{insights-fH1EL-qZ.js → insights-CzrtkpOE.js} +2 -2
- package/public/assets/{integrations-C5Oix6ng.js → integrations-aVsUmigt.js} +2 -2
- package/public/assets/{issue-ref-chip-ODyondIa.js → issue-ref-chip-BnSlM_95.js} +2 -2
- package/public/assets/{log-viewer-Cvfy6PW7.js → log-viewer-qe7Ee47Z.js} +2 -2
- package/public/assets/{maintenance-D8CDH5wZ.js → maintenance-NfjqFZAk.js} +2 -2
- package/public/assets/{managed-agents-egllbpij.js → managed-agents-BiH0HgaE.js} +2 -2
- package/public/assets/{markdown-preview-CYSFgVgK.js → markdown-preview-BixaT3Xr.js} +3 -3
- package/public/assets/{markdown-preview-impl-BteVIjX4.js → markdown-preview-impl-DNGlWIS3.js} +2 -2
- package/public/assets/{memory-C8WmXsyr.js → memory-DNsCl6UX.js} +2 -2
- package/public/assets/{messages-BzQdqlO6.js → messages-DopU1L1X.js} +2 -2
- package/public/assets/{orchestrators-B1HxzkNw.js → orchestrators-Cq7ckLQT.js} +2 -2
- package/public/assets/{overview-DCUnI4Z7.js → overview-C1DCTzzV.js} +2 -2
- package/public/assets/{pairs-ftCd2XcD.js → pairs-DE_m6rrE.js} +2 -2
- package/public/assets/{profile-icon-B2zH8DMH.js → profile-icon-B3rfh77F.js} +2 -2
- package/public/assets/project-profile-instructions-DQWZE0kA.js +2 -0
- package/public/assets/projects-Br2Bd2h1.js +2 -0
- package/public/assets/{prompt-settings-Bftq9czX.js → prompt-settings-BKvFsvGD.js} +2 -2
- package/public/assets/provider-display-DsuWMvVL.js +2 -0
- package/public/assets/{registry-DWCU5c8q.js → registry-Cw38_6gW.js} +2 -2
- package/public/assets/run-card-CpKqRbhg.js +2 -0
- package/public/assets/scroll-text-BKXS1ahr.js +2 -0
- package/public/assets/{secrets-C7GIUATz.js → secrets-DxI-vzSq.js} +2 -2
- package/public/assets/{service-access-settings-C3aujqTG.js → service-access-settings-D9s_VJbd.js} +2 -2
- package/public/assets/{settings-C6sZ9eBa.js → settings-CKZTVGIx.js} +2 -2
- package/public/assets/{shipping-Bu8p1gEw.js → shipping-B9YtnwtG.js} +2 -2
- package/public/assets/{stats-V9Z-GxUd.js → stats-DyUBKyWI.js} +2 -2
- package/public/assets/{status-dot-CVv0iGHL.js → status-dot-DYqlEUhJ.js} +2 -2
- package/public/assets/{store-BvtFdlGX.js → store-DcClXLH0.js} +3 -3
- package/public/assets/{tasks-CXU75HRF.js → tasks-Bh7Chr4-.js} +2 -2
- package/public/assets/{teams-BPf976zb.js → teams-bowI7qVY.js} +2 -2
- package/public/assets/{terminal-viewer-DE9BOe-8.js → terminal-viewer-BgVLHdsU.js} +3 -3
- package/public/assets/{terminal-viewer-impl-D04pjmGh.js → terminal-viewer-impl-Dz22UPy6.js} +2 -2
- package/public/assets/token-estimate-Co-Jdphh.js +2 -0
- package/public/assets/{use-agent-terminal-B1yR456R.js → use-agent-terminal-DSQQ-iY7.js} +2 -2
- package/public/assets/{use-decisions-D-S4tpDf.js → use-decisions-samMQhQf.js} +2 -2
- package/public/assets/use-project-list-59LheVP7.js +2 -0
- package/public/assets/{use-selectors-CnrAk2YP.js → use-selectors-BZa25xEB.js} +2 -2
- package/public/assets/{user-avatar-nBFIcR4M.js → user-avatar-DHxlvUvV.js} +2 -2
- package/public/assets/versioned-prompt-editor-BmED5DnJ.js +8 -0
- package/public/assets/{work-queue-TCjJxeT-.js → work-queue-CSvpuNLz.js} +2 -2
- package/public/assets/{workflow-marker-Cf3Hf2fN.js → workflow-marker-DAZcj5qt.js} +2 -2
- package/public/assets/{workflows-CXQX20Qj.js → workflows-DdmxRSyg.js} +2 -2
- package/public/assets/{workspaces-qSYzKYMA.js → workspaces-BxeKfVuF.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/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/agent-runner/credentials.ts +42 -12
- package/runner/src/agent-runner/inbox.ts +27 -0
- package/runner/src/agent-runner/lifecycle-milestones.ts +0 -2
- 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/index.ts +5 -2
- package/runner/src/provider-setup.ts +34 -0
- package/runner/src/providers.ts +2 -1
- package/runner/src/runner-core.ts +18 -23
- package/runner/src/spawn-input.ts +2 -1
- package/runner/src/test-run-dedup.ts +59 -56
- package/scripts/cd-config.ts +24 -3
- package/scripts/gate-run-lease.ts +10 -7
- package/scripts/gate.sh +5 -1
- package/src/branch-land-notice.ts +93 -0
- package/src/branch-landed.ts +7 -76
- package/src/bus.ts +19 -20
- package/src/cd-deploy-notify.ts +30 -2
- 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/root-missing.ts +2 -7
- package/src/ci/transition-notify.ts +7 -39
- 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 +8 -2
- package/src/commands-db.ts +10 -6
- package/src/commands-write.ts +8 -0
- package/src/config-store-write.ts +13 -1
- package/src/config-store.ts +25 -14
- package/src/db/activity-async.ts +6 -1
- package/src/db/activity-write-ops.ts +13 -1
- package/src/db/activity.ts +1 -14
- package/src/db/agent-lifecycle-write-ops.ts +1 -0
- package/src/db/agent-meta.ts +2 -2
- package/src/db/agent-ownership-write-ops.ts +4 -0
- package/src/db/agent-search.ts +1 -15
- package/src/db/agents-async.ts +58 -7
- package/src/db/agents-write-ops.ts +28 -5
- package/src/db/agents.ts +81 -54
- package/src/db/artifacts-write-ops.ts +8 -3
- package/src/db/bus-outbox-write-ops.ts +1 -0
- package/src/db/channels-write-ops.ts +4 -0
- package/src/db/ci-incidents-async.ts +5 -5
- package/src/db/ci-incidents-write-ops.ts +2 -2
- package/src/db/claude-api-budget-ops.ts +5 -5
- package/src/db/claude-app-oauth.ts +4 -4
- package/src/db/codex-reset-consumes-write-ops.ts +3 -0
- package/src/db/command-row.ts +10 -2
- package/src/db/commands-list-query.ts +2 -0
- package/src/db/commands-spawn-read.ts +1 -1
- package/src/db/commands-write-ops.ts +21 -0
- package/src/db/config-store-write-ops.ts +9 -2
- package/src/db/continuation-archives-async.ts +5 -0
- package/src/db/continuation-archives-write-ops.ts +9 -0
- package/src/db/continuations.ts +2 -2
- package/src/db/db-writer-worker.ts +8 -1
- package/src/db/delivery-write-ops.ts +5 -0
- 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/hosts-registration.ts +10 -2
- package/src/db/hosts-write-ops.ts +14 -0
- package/src/db/hosts.ts +9 -6
- package/src/db/inbox-write-ops.ts +4 -0
- package/src/db/inbox.ts +0 -14
- package/src/db/index.ts +2 -0
- package/src/db/insights-write-ops.ts +1 -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-lifecycle.ts +3 -4
- package/src/db/issue-refs-async.ts +20 -0
- package/src/db/issue-refs-write-ops.ts +29 -0
- package/src/db/issue-refs.ts +7 -8
- package/src/db/long-running-work.ts +2 -2
- package/src/db/macos-privacy.ts +1 -1
- package/src/db/main-connection-writes.ts +23 -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/mappers.ts +2 -14
- package/src/db/merge-lease.ts +1 -15
- package/src/db/message-reads-write-ops.ts +3 -0
- package/src/db/message-write-ops.ts +4 -0
- package/src/db/migrations.ts +7 -15
- package/src/db/orchestrators-async.ts +7 -3
- package/src/db/orchestrators-write-ops.ts +7 -1
- package/src/db/orchestrators.ts +21 -77
- package/src/db/pairs.ts +1 -13
- package/src/db/project-profile-instructions.ts +50 -0
- package/src/db/prompt-versions-ops.ts +1 -0
- package/src/db/prompt-versions.ts +9 -2
- package/src/db/provider-catalog-write-ops.ts +4 -4
- package/src/db/provider-config-history.ts +8 -3
- package/src/db/provider-flap-messages-write-ops.ts +1 -0
- package/src/db/provider-model-seed.ts +34 -0
- package/src/db/provider-quota-lease-write-ops.ts +1 -0
- package/src/db/provider-quota-write-ops.ts +2 -0
- package/src/db/provisioning-write-ops.ts +9 -8
- package/src/db/read-op-marshaling-fixtures.ts +5 -0
- package/src/db/read-ops.ts +4 -0
- package/src/db/routing-policy.ts +3 -4
- package/src/db/schema.ts +9 -3
- package/src/db/secrets-broker-write-ops.ts +5 -5
- package/src/db/secrets-vault-write.ts +7 -7
- package/src/db/services-write-ops.ts +3 -0
- package/src/db/spawn-delegation-state.ts +11 -4
- package/src/db/spawn-tree-cleanup.ts +3 -0
- package/src/db/stats-async.ts +4 -3
- package/src/db/task-entity.ts +23 -2
- package/src/db/task-list.ts +3 -1
- package/src/db/tasks.ts +1 -17
- package/src/db/team-spawn-delegation.ts +1 -1
- package/src/db/teams-write-ops.ts +4 -4
- package/src/db/timer-cutover-write-ops.ts +7 -0
- package/src/db/timer-ingress-write-ops.ts +9 -0
- package/src/db/timer-ingress.ts +7 -1
- package/src/db/timer-operator-write-ops.ts +14 -0
- package/src/db/timer-transfer-write-ops.ts +4 -0
- package/src/db/timer-write-ops.ts +14 -0
- package/src/db/token-db-write-ops.ts +21 -0
- package/src/db/token-standing.ts +15 -11
- package/src/db/user-settings-write-ops.ts +1 -0
- package/src/db/vault-backup.ts +2 -2
- package/src/db/vault-expiry.ts +2 -2
- package/src/db/vault-health.ts +3 -3
- package/src/db/vault-token-ops.ts +8 -8
- package/src/db/web-tool-call-ops.ts +3 -3
- package/src/db/workflow-contact.ts +1 -1
- package/src/db/workflow-task-read-ops.ts +30 -0
- package/src/db/write-ops.ts +15 -1
- package/src/db/writer-fault-seam.ts +5 -2
- package/src/db/writer-gateway.ts +21 -12
- 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/host/disk-alert.ts +121 -0
- package/src/lifecycle-manager.ts +3 -2
- package/src/maintenance/cd-watcher.ts +3 -3
- package/src/maintenance/critical-job-watchdog.ts +16 -17
- package/src/maintenance/index.ts +1 -0
- package/src/maintenance/jobs.ts +3 -2
- package/src/maintenance/scheduler.ts +84 -128
- package/src/maintenance/stalled-delivery-pager.ts +6 -5
- package/src/maintenance/workspaces.ts +1 -1
- package/src/managed-policy.ts +31 -27
- package/src/mcp/index.ts +5 -2
- package/src/mcp/output-descriptions.ts +8 -8
- package/src/mcp/presentation.ts +4 -4
- package/src/mcp/project-profile-instructions.ts +32 -0
- package/src/mcp/tool-groups.ts +1 -1
- package/src/mcp/tools-spawn.ts +4 -3
- package/src/mcp-agent-action.ts +1 -2
- package/src/mcp-host-tools.ts +1 -1
- package/src/mcp-issue-ref-tools.ts +12 -11
- package/src/mcp-maintenance-tools.ts +2 -2
- package/src/mcp-profile-trust-tools.ts +4 -4
- package/src/mcp-provider-catalog.ts +2 -2
- package/src/mcp-task-tools.ts +11 -5
- package/src/mcp-team-template-tools.ts +3 -3
- package/src/mcp-workflow-tools.ts +10 -3
- package/src/notification-types.ts +2 -1
- package/src/operator-alarm.ts +26 -11
- package/src/package-pack.ts +42 -39
- package/src/project-instructions.ts +4 -0
- package/src/project-profile-instruction-text.ts +6 -0
- package/src/project-profile-instructions.ts +20 -0
- 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-config-store.ts +5 -4
- package/src/provider-secrets.test-fixture.ts +3 -3
- package/src/recipe-runner.ts +2 -2
- package/src/repo-config-source.ts +10 -4
- package/src/routes/agent-profiles.ts +6 -6
- package/src/routes/agents-spawn.ts +1 -1
- package/src/routes/agents.ts +6 -6
- package/src/routes/commands-listing.ts +4 -0
- package/src/routes/commands.ts +2 -2
- package/src/routes/continuation-archives.ts +2 -2
- package/src/routes/host-resource-control.ts +4 -1
- package/src/routes/index.ts +10 -1
- package/src/routes/integrations.ts +24 -50
- package/src/routes/issue-refs.ts +7 -7
- package/src/routes/orchestrator-bootstrap.ts +3 -3
- package/src/routes/orchestrator-host-registration.ts +2 -2
- package/src/routes/orchestrator-host-utilization.ts +3 -1
- package/src/routes/orchestrator-proxy.ts +2 -2
- package/src/routes/orchestrator.ts +4 -4
- package/src/routes/project-profile-instructions.ts +27 -0
- package/src/routes/project-trust.ts +2 -2
- package/src/routes/provider-config.ts +9 -8
- package/src/routes/provider-quota-config.ts +2 -2
- package/src/routes/settings.ts +5 -5
- 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 +5 -5
- package/src/routes/teams-config.ts +2 -2
- package/src/routes/tokens.ts +12 -5
- package/src/routes/workflows.ts +20 -5
- package/src/routing-policy-normalize.ts +1 -2
- package/src/routing-step-defaults.ts +0 -2
- package/src/runner-token-mint-limit.ts +63 -0
- package/src/runtime-grant.ts +4 -2
- package/src/runtime-tokens.ts +50 -9
- package/src/security.ts +13 -20
- package/src/server-background.ts +1 -1
- package/src/server.ts +5 -2
- package/src/services/host-utilization.ts +23 -0
- package/src/services/idle-epics.ts +5 -6
- package/src/services/issue-lifecycle.ts +57 -61
- package/src/services/issue-refs.ts +9 -13
- package/src/services/kernel-timers-cutover-chaos-worker.ts +12 -7
- package/src/services/kernel-timers-ingress.ts +1 -1
- package/src/services/kernel-timers-request-key-migration-chaos-worker.ts +4 -1
- package/src/services/landed-ancestry.ts +19 -3
- package/src/services/memory-areas.ts +15 -51
- package/src/services/plan-ci-notice.ts +57 -0
- package/src/services/plan-ci-recovery.ts +2 -55
- package/src/services/plan-wake-digest.ts +1 -0
- package/src/services/profile-trust.ts +4 -3
- package/src/services/project-config-read.ts +70 -0
- package/src/services/project-profile-instructions.ts +54 -0
- package/src/services/provisioning-harness/budget-baseline.json +4 -4
- package/src/services/restart-spawn.ts +61 -49
- package/src/services/self-care-state.ts +2 -1
- package/src/services/self-effort.ts +5 -5
- package/src/services/send-message.ts +5 -1
- package/src/services/spawn-agent.ts +13 -2
- package/src/services/spawn-chain-inspector.ts +6 -13
- package/src/services/spawn-policy.ts +68 -0
- package/src/services/spawn-tree-cleanup.ts +2 -2
- package/src/services/task-dispatch.ts +3 -0
- package/src/services/task-state-reconcile.ts +6 -14
- package/src/services/team-templates.ts +9 -8
- package/src/services/transient-agent-reaper.ts +3 -1
- package/src/services/workflow-auto-start.ts +25 -13
- package/src/services/workflow-ci-main.ts +1 -1
- package/src/services/workflow-deferred-cleanup.ts +4 -2
- package/src/services/workflow-effect-driver.ts +2 -0
- package/src/services/workflow-effects.ts +18 -11
- package/src/services/workflow-land-notice.ts +10 -0
- package/src/services/workflow-pause-text.ts +43 -0
- package/src/services/workflow-reconcile.ts +13 -11
- package/src/services/workflow-run-view.ts +2 -0
- package/src/services/workflow-runs.ts +29 -13
- package/src/services/workflow-supervisor-state.ts +5 -0
- package/src/services/workflow-supervisor.ts +7 -3
- package/src/settings/registry.ts +1 -2
- package/src/spawn-command.ts +4 -4
- package/src/spawn-models.ts +10 -12
- package/src/spawn-placement.ts +1 -1
- package/src/spawn-targets.ts +1 -1
- package/src/startup-context-injection.ts +1 -0
- 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.ts +7 -6
- package/src/task-dispatch-live.ts +1 -1
- package/src/task-dispatcher.ts +1 -1
- package/src/teams-config-store.ts +4 -3
- package/src/token-db-write.ts +10 -0
- package/src/workspace-command-settle.ts +2 -1
- package/src/workspace-steward-wake.ts +2 -2
- 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 -47
- 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 -46
- 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/fleet-BL4UXS_k.js +0 -2
- package/public/assets/index-B7ZerHLY.css +0 -2
- package/public/assets/index-BK0WV6hF.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/use-project-list-B-T2Bnnn.js +0 -2
- package/public/assets/versioned-prompt-editor-Diu8BIaM.js +0 -8
- package/runner/src/gate-run-lease-probe.ts +0 -38
- package/src/db/claude-catalog-reconcile.ts +0 -27
- package/src/routing-model-aliases.ts +0 -21
|
@@ -16,7 +16,7 @@ import { resolveWhoamiRole } from "../mcp/identity-projection";
|
|
|
16
16
|
import { listManagedOrchestratorsForAgent } from "../orchestrator-lookup";
|
|
17
17
|
import { applyDefaultSharedMcp } from "../shared-mcp";
|
|
18
18
|
import { buildSpawnCommand, generateSpawnRequestId, resolveSpawnModelParams, resolveSpawnModelParamsAsync } from "../spawn-command";
|
|
19
|
-
import { SUCCESSOR_LAUNCH, runnerRuntimeTokenEnv } from "../runtime-tokens";
|
|
19
|
+
import { SUCCESSOR_LAUNCH, runnerRuntimeTokenEnv, runnerRuntimeTokenEnvAsync, type RunnerRuntimeTokenInput } from "../runtime-tokens";
|
|
20
20
|
import { restartEffortState } from "./self-effort";
|
|
21
21
|
// #2033 — from isolated-workspace-placement.ts, NOT ./spawn-identity: that module also exports
|
|
22
22
|
// buildProspectiveSpawnIdentity, which imports mcp/identity.ts → self-resume.ts → restart-spawn.ts,
|
|
@@ -27,7 +27,7 @@ import { restartInstructionParamsForAgent, restartInstructionParamsForAgentAsync
|
|
|
27
27
|
import { launchedProjectRole, projectRoleRestartError, refuseSyncProjectRoleRestart, restartProjectRole } from "./restart-project-role";
|
|
28
28
|
import { authContextFromSystem } from "./auth-context";
|
|
29
29
|
import { markManagedAgentRunning } from "./managed-running";
|
|
30
|
-
import type { AgentCard, AgentProfile, Command, Orchestrator, SpawnApprovalMode } from "../types";
|
|
30
|
+
import type { AgentCard, AgentProfile, SpawnPolicy, Command, Orchestrator, SpawnApprovalMode } from "../types";
|
|
31
31
|
|
|
32
32
|
export type SelfRestartReason = "upgrade" | "token-remint" | "manual" | "reset-unconfirmed";
|
|
33
33
|
type RestartOptions = { resumeId?: string; continuation?: string; generation?: number; reason?: string };
|
|
@@ -116,30 +116,9 @@ function buildRestartSpawnParamsForAgent(
|
|
|
116
116
|
requestedBy,
|
|
117
117
|
// Override the policy builder's normal mint so stable team/project bindings are also
|
|
118
118
|
// carried by the fresh token, not merely preserved incidentally on the agent row.
|
|
119
|
-
env: runnerRuntimeTokenEnv(
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
cwd: policy.value.cwd,
|
|
123
|
-
provider: policy.value.provider,
|
|
124
|
-
label: policy.value.label,
|
|
125
|
-
policyName: policy.value.name,
|
|
126
|
-
spawnRequestId: requestId,
|
|
127
|
-
createdBy: requestedBy,
|
|
128
|
-
profile: policy.value.profile || undefined,
|
|
129
|
-
// #2245 — the successor's posture comes from the POLICY (server config, unforgeable), the
|
|
130
|
-
// same value `buildManagedSpawnParams` launches it with; stamp it into the signed constraints.
|
|
131
|
-
approvalMode: policy.value.permissionMode,
|
|
132
|
-
...(agent.teamId ? { teamId: agent.teamId } : {}),
|
|
133
|
-
...(projectId ? { projectId } : {}),
|
|
134
|
-
...([...stewardExtraCwdPrefixes, ...isolatedExtraCwdPrefixes].length
|
|
135
|
-
? { extraCwdPrefixes: [...stewardExtraCwdPrefixes, ...isolatedExtraCwdPrefixes] }
|
|
136
|
-
: {}),
|
|
137
|
-
}),
|
|
138
|
-
...(opts.continuation ? { prompt: opts.continuation } : {}),
|
|
139
|
-
...(restartResumeWorkspace ? { resumeWorkspace: restartResumeWorkspace } : {}),
|
|
140
|
-
// F5 — carry the self-restart generation marker on BOTH successor spawns (policy and
|
|
141
|
-
// dashboard/non-policy), so the audit lineage is symmetric regardless of branch.
|
|
142
|
-
...(opts.generation ? { extra: { selfRestart: { generation: opts.generation, reason: opts.reason } } } : {}),
|
|
119
|
+
env: runnerRuntimeTokenEnv(managedRestartTokenInput(agent, policy.value, requestId, requestedBy, projectId,
|
|
120
|
+
[...stewardExtraCwdPrefixes, ...isolatedExtraCwdPrefixes])),
|
|
121
|
+
...managedRestartOptions(opts, restartResumeWorkspace),
|
|
143
122
|
};
|
|
144
123
|
return opts.resumeId ? withResumeParams(params, opts.resumeId, agent.id) : params;
|
|
145
124
|
}
|
|
@@ -160,7 +139,7 @@ function buildRestartSpawnParamsForAgent(
|
|
|
160
139
|
const resolvedProfile = withResolvedProvisioning(profileName ? getAgentProfile(profileName)?.value : undefined, provider);
|
|
161
140
|
const agentProfile = resolvedProfile ? applyDefaultSharedMcp(resolvedProfile) : undefined;
|
|
162
141
|
const workspaceMode = stringValue(agent.meta?.workspaceMode) ?? "inherit";
|
|
163
|
-
const resolvedModel = resolveSpawnModelParams(provider, model, effort, { modelSource: "runtime"
|
|
142
|
+
const resolvedModel = resolveSpawnModelParams(provider, model, effort, { modelSource: "runtime" });
|
|
164
143
|
const projectedInstructions = restartInstructionParamsForAgent(agent, { spawnRequestId: predecessorSpawnRequestId, cwd }) ?? {};
|
|
165
144
|
// #1598 — canonicalize so a worktree/subdir cwd binds to its owning checkout's project.
|
|
166
145
|
const projectId = resolveProjectForCanonicalCwd(cwd).project?.id;
|
|
@@ -175,7 +154,7 @@ function buildRestartSpawnParamsForAgent(
|
|
|
175
154
|
cwd,
|
|
176
155
|
orchestrator.baseDir,
|
|
177
156
|
);
|
|
178
|
-
|
|
157
|
+
const options = {
|
|
179
158
|
provider,
|
|
180
159
|
modelParams: resolvedModel,
|
|
181
160
|
cwd,
|
|
@@ -185,7 +164,10 @@ function buildRestartSpawnParamsForAgent(
|
|
|
185
164
|
policyName: policyName || undefined,
|
|
186
165
|
spawnRequestId: requestId,
|
|
187
166
|
requestedBy,
|
|
188
|
-
}
|
|
167
|
+
};
|
|
168
|
+
const tokenContext = { orchestratorId: orchestrator.id, projectId, extraCwdPrefixes: stewardExtraCwdPrefixes };
|
|
169
|
+
return buildRestartSpawnCommand(agent, predecessorSpawnRequestId, agentProfile, projectedInstructions, opts, options, tokenContext,
|
|
170
|
+
runnerRuntimeTokenEnv(restartTokenInput(agent, options, tokenContext)));
|
|
189
171
|
}
|
|
190
172
|
|
|
191
173
|
/** Worker-safe restart command construction used by HTTP/orchestrator/self-restart flows. */
|
|
@@ -233,14 +215,8 @@ async function buildRestartSpawnParamsForAgentAsync(
|
|
|
233
215
|
const params = {
|
|
234
216
|
...await buildManagedSpawnParamsAsync(relaunchPolicy(policy.value, relaunch.effort), requestId, { createdBy: requestedBy, authority: SUCCESSOR_LAUNCH, identityAgentId: agent.id, gitRepoRoot }),
|
|
235
217
|
...relaunch.carried, agentId: agent.id, requestedBy,
|
|
236
|
-
env:
|
|
237
|
-
|
|
238
|
-
createdBy: requestedBy, profile: policy.value.profile || undefined, ...(agent.teamId ? { teamId: agent.teamId } : {}),
|
|
239
|
-
approvalMode: policy.value.permissionMode,
|
|
240
|
-
...(projectId ? { projectId } : {}), ...(combinedExtraCwdPrefixes.length ? { extraCwdPrefixes: combinedExtraCwdPrefixes } : {}), }),
|
|
241
|
-
...(opts.continuation ? { prompt: opts.continuation } : {}),
|
|
242
|
-
...(restartResumeWorkspace ? { resumeWorkspace: restartResumeWorkspace } : {}),
|
|
243
|
-
...(opts.generation ? { extra: { selfRestart: { generation: opts.generation, reason: opts.reason } } } : {}),
|
|
218
|
+
env: await runnerRuntimeTokenEnvAsync(managedRestartTokenInput(agent, policy.value, requestId, requestedBy, projectId, combinedExtraCwdPrefixes)),
|
|
219
|
+
...managedRestartOptions(opts, restartResumeWorkspace),
|
|
244
220
|
};
|
|
245
221
|
return opts.resumeId ? withResumeParams(params, opts.resumeId, agent.id) : params;
|
|
246
222
|
}
|
|
@@ -257,15 +233,55 @@ async function buildRestartSpawnParamsForAgentAsync(
|
|
|
257
233
|
const profileName = role ? role.profileName : stringValue(agent.meta?.profile);
|
|
258
234
|
const resolvedProfile = role ? undefined : await withResolvedProvisioningAsync(profileName ? getAgentProfile(profileName)?.value : undefined, provider);
|
|
259
235
|
const agentProfile = role?.agentProfile ?? (resolvedProfile ? applyDefaultSharedMcp(resolvedProfile) : undefined);
|
|
260
|
-
const resolvedModel = await resolveSpawnModelParamsAsync(provider, model, effort, { modelSource: "runtime"
|
|
236
|
+
const resolvedModel = await resolveSpawnModelParamsAsync(provider, model, effort, { modelSource: "runtime" });
|
|
261
237
|
const projectedInstructions = await restartInstructionParamsForAgentAsync(agent, { spawnRequestId: predecessorSpawnRequestId, cwd, ...(role ? { profile: role.agentProfile } : {}) }) ?? {};
|
|
262
238
|
const projectId = resolveProjectForCanonicalCwd(cwd).project?.id;
|
|
263
239
|
const stewardExtraCwdPrefixes = stewardWorktreeCwdPrefixes(isProvenStewardAgent(agent.id, policyName), cwd, orchestrator.baseDir);
|
|
264
|
-
|
|
240
|
+
const options = {
|
|
265
241
|
provider, modelParams: resolvedModel, cwd, workspaceMode, profile: profileName || undefined,
|
|
266
242
|
...relaunch.carried, ...role?.spawn, policyName: policyName || undefined, spawnRequestId: requestId,
|
|
267
243
|
requestedBy,
|
|
268
|
-
}
|
|
244
|
+
};
|
|
245
|
+
const tokenContext = { orchestratorId: orchestrator.id, projectId, extraCwdPrefixes: stewardExtraCwdPrefixes };
|
|
246
|
+
return buildRestartSpawnCommand(agent, predecessorSpawnRequestId, agentProfile, projectedInstructions, opts, options, tokenContext,
|
|
247
|
+
await runnerRuntimeTokenEnvAsync(restartTokenInput(agent, options, tokenContext)));
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function managedRestartOptions(opts: RestartOptions, restartResumeWorkspace: ReturnType<typeof resumeWorkspaceForRestart>) {
|
|
251
|
+
return {
|
|
252
|
+
...(opts.continuation ? { prompt: opts.continuation } : {}),
|
|
253
|
+
...(restartResumeWorkspace ? { resumeWorkspace: restartResumeWorkspace } : {}),
|
|
254
|
+
// F5 — carry the self-restart generation marker on BOTH successor spawns (policy and
|
|
255
|
+
// dashboard/non-policy), so the audit lineage is symmetric regardless of branch.
|
|
256
|
+
...(opts.generation ? { extra: { selfRestart: { generation: opts.generation, reason: opts.reason } } } : {}),
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function managedRestartTokenInput(agent: AgentCard, policy: SpawnPolicy, requestId: string, requestedBy: string, projectId: string | undefined, extraCwdPrefixes: string[]): RunnerRuntimeTokenInput {
|
|
261
|
+
return {
|
|
262
|
+
authority: SUCCESSOR_LAUNCH, agentId: agent.id, orchestratorId: policy.orchestratorId,
|
|
263
|
+
cwd: policy.cwd, provider: policy.provider, label: policy.label, policyName: policy.name,
|
|
264
|
+
spawnRequestId: requestId, createdBy: requestedBy, profile: policy.profile || undefined,
|
|
265
|
+
// #2245: both successor paths stamp the policy's current posture into signed constraints.
|
|
266
|
+
approvalMode: policy.permissionMode,
|
|
267
|
+
...(agent.teamId ? { teamId: agent.teamId } : {}),
|
|
268
|
+
...(projectId ? { projectId } : {}),
|
|
269
|
+
...(extraCwdPrefixes.length ? { extraCwdPrefixes } : {}),
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
type RestartTokenContext = Pick<RunnerRuntimeTokenInput, "orchestratorId" | "projectId" | "extraCwdPrefixes">;
|
|
274
|
+
const restartApprovalMode = (agent: AgentCard): SpawnApprovalMode => (stringValue(agent.meta?.approvalMode) as SpawnApprovalMode | undefined) ?? "guarded";
|
|
275
|
+
const restartLabel = (agent: AgentCard): string | undefined => (stringValue(agent.meta?.label) ?? agent.label) || undefined;
|
|
276
|
+
|
|
277
|
+
/** The successor token a non-policy restart carries; the sync twin and the writer-op path mint the same input. */
|
|
278
|
+
function restartTokenInput(agent: AgentCard, options: Omit<Parameters<typeof buildSpawnCommand>[0], "env">, tokenContext: RestartTokenContext): RunnerRuntimeTokenInput {
|
|
279
|
+
return { ...tokenContext, authority: SUCCESSOR_LAUNCH,
|
|
280
|
+
agentId: agent.id, cwd: options.cwd, provider: options.provider, label: restartLabel(agent),
|
|
281
|
+
policyName: options.policyName, spawnRequestId: options.spawnRequestId,
|
|
282
|
+
createdBy: options.requestedBy, profile: options.profile, approvalMode: restartApprovalMode(agent),
|
|
283
|
+
...(agent.teamId ? { teamId: agent.teamId } : {}),
|
|
284
|
+
};
|
|
269
285
|
}
|
|
270
286
|
|
|
271
287
|
function buildRestartSpawnCommand(
|
|
@@ -275,25 +291,21 @@ function buildRestartSpawnCommand(
|
|
|
275
291
|
projectedInstructions: Record<string, unknown>,
|
|
276
292
|
opts: RestartOptions,
|
|
277
293
|
options: Omit<Parameters<typeof buildSpawnCommand>[0], "env">,
|
|
278
|
-
tokenContext:
|
|
294
|
+
tokenContext: RestartTokenContext,
|
|
295
|
+
env: Record<string, string>,
|
|
279
296
|
): Record<string, unknown> {
|
|
280
297
|
const memorySeam = parseMemorySeam(projectedInstructions.memorySeam);
|
|
281
298
|
const resumeWorkspace = resumeWorkspaceForRestart(agent);
|
|
282
299
|
const providerArgs = metaStringArray(agent.meta, "providerArgs");
|
|
283
|
-
const approvalMode = (
|
|
284
|
-
const label = (
|
|
300
|
+
const approvalMode = restartApprovalMode(agent);
|
|
301
|
+
const label = restartLabel(agent);
|
|
285
302
|
const params = buildSpawnCommand({
|
|
286
303
|
...options,
|
|
287
304
|
orchestratorId: tokenContext.orchestratorId,
|
|
288
305
|
headless: true, requestedAt: Date.now(),
|
|
289
306
|
...(opts.continuation ? { prompt: opts.continuation } : {}),
|
|
290
307
|
...(opts.generation ? { extra: { selfRestart: { generation: opts.generation, reason: opts.reason } } } : {}),
|
|
291
|
-
env
|
|
292
|
-
agentId: agent.id, cwd: options.cwd, provider: options.provider, label,
|
|
293
|
-
policyName: options.policyName, spawnRequestId: options.spawnRequestId,
|
|
294
|
-
createdBy: options.requestedBy, profile: options.profile, approvalMode,
|
|
295
|
-
...(agent.teamId ? { teamId: agent.teamId } : {}),
|
|
296
|
-
}),
|
|
308
|
+
env,
|
|
297
309
|
agentId: agent.id, tags: agent.tags, systemTags: agent.systemTags, capabilities: agent.capabilities,
|
|
298
310
|
label,
|
|
299
311
|
approvalMode, permissionMode: approvalMode,
|
|
@@ -2,9 +2,10 @@ import { renderLiveRunsSection } from "../live-runs-section";
|
|
|
2
2
|
import { renderOpenDecisionsSection } from "../operator-decisions-section";
|
|
3
3
|
import { renderIdleEpicsSection } from "./idle-epics";
|
|
4
4
|
import { renderPlanWakeDigest } from "./plan-wake-digest";
|
|
5
|
+
import { renderPausedRunsSection } from "./workflow-pause-text";
|
|
5
6
|
|
|
6
7
|
/** Stored live state survives every self-care boundary; tracker refresh must never block a wake. */
|
|
7
8
|
export function renderSelfCareState(agentId: string): string {
|
|
8
9
|
return [renderLiveRunsSection(agentId), renderOpenDecisionsSection(agentId),
|
|
9
|
-
renderIdleEpicsSection(agentId, [], false), renderPlanWakeDigest(agentId)].filter(Boolean).join("\n\n");
|
|
10
|
+
renderIdleEpicsSection(agentId, [], false), renderPlanWakeDigest(agentId), renderPausedRunsSection(agentId)].filter(Boolean).join("\n\n");
|
|
10
11
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { stringValue, type SpawnProvider } from "@humwick/sdk";
|
|
2
|
-
import {
|
|
2
|
+
import { findProviderCatalog, findProviderCatalogModel, type ProviderCatalogEntry } from "@humwick/sdk/provider-catalog";
|
|
3
3
|
import { findConfirmedEffortSwitch, findLaunchEffort, type LaunchEffort } from "../db/commands-effort-read";
|
|
4
4
|
import { getAgentEffortState } from "../db/agent-effort-state";
|
|
5
5
|
import { SELF_EFFORT_BAND, getSelfEffortCeiling, type SelfEffortIdentity } from "../db/self-effort-permissions";
|
|
@@ -44,7 +44,7 @@ export function resolveSpawnSelfEffort(
|
|
|
44
44
|
if (!(base ?? known?.defaultEffort)) throw new ValidationError("selfEffort without selfEffortCeiling needs a base effort: set effort, or pass selfEffortCeiling");
|
|
45
45
|
return { band: true };
|
|
46
46
|
}
|
|
47
|
-
const levels = known?.efforts ??
|
|
47
|
+
const levels = known?.efforts ?? [];
|
|
48
48
|
if (!levels.includes(ceiling)) {
|
|
49
49
|
throw new ValidationError(`selfEffortCeiling ${ceiling} is not an effort ${known ? `${known.provider} model ${known.alias}` : provider} offers (${levels.join(", ")})`);
|
|
50
50
|
}
|
|
@@ -90,7 +90,7 @@ export function selfEffortBase(agent: AgentCard): string | undefined {
|
|
|
90
90
|
|
|
91
91
|
/** One step down and one step up from `base` on `ladder`, clamped at both ends. */
|
|
92
92
|
export function selfEffortBand(base: string, ladder: readonly string[]): { floor: string; ceiling: string } {
|
|
93
|
-
const levels = ladder.includes(base) ? ladder :
|
|
93
|
+
const levels = ladder.includes(base) ? ladder : [base];
|
|
94
94
|
const at = levels.indexOf(base);
|
|
95
95
|
return { floor: levels[Math.max(0, at - 1)]!, ceiling: levels[Math.min(levels.length - 1, at + 1)]! };
|
|
96
96
|
}
|
|
@@ -119,7 +119,7 @@ export function selfEffortPolicyFor(agent: AgentCard, grant: SelfEffortGrant, mo
|
|
|
119
119
|
if ("ceiling" in grant) return { ceiling: grant.ceiling };
|
|
120
120
|
const base = selfEffortBase(agent);
|
|
121
121
|
if (!base) throw new ValidationError("your self-change band has no base effort; ask your coordinator to set your effort");
|
|
122
|
-
return { band: true, base, ...selfEffortBand(base, modelEfforts ?? agentCatalogModel(agent)?.efforts ??
|
|
122
|
+
return { band: true, base, ...selfEffortBand(base, modelEfforts ?? agentCatalogModel(agent)?.efforts ?? [base]) };
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
/** #2950 H3 — a restart successor launches at the agent's desired effort (#2984: applied or still pending),
|
|
@@ -138,7 +138,7 @@ export function restartEffortState(agent: AgentCard): { effort?: string; carried
|
|
|
138
138
|
export function assertSelfEffortAllowed(agent: AgentCard, level: string, modelEfforts: readonly string[] | undefined): SelfEffortPolicy {
|
|
139
139
|
const policy = spawnSelfEffortPolicy(agent, modelEfforts);
|
|
140
140
|
if (!policy) throw new ValidationError("selfEffort is not enabled for you, so you cannot change your own effort; ask your coordinator");
|
|
141
|
-
const ladder = modelEfforts
|
|
141
|
+
const ladder = modelEfforts ?? agentCatalogModel(agent)?.efforts ?? [];
|
|
142
142
|
const at = ladder.indexOf(level);
|
|
143
143
|
if (at < 0 || at > ladder.indexOf(policy.ceiling)) {
|
|
144
144
|
throw new ValidationError(policy.band
|
|
@@ -45,6 +45,7 @@ import {
|
|
|
45
45
|
import { recentFinalResponseCaptureIds } from "../db/lineage-startup-captures";
|
|
46
46
|
import { yieldToEventLoop } from "../event-loop-yield";
|
|
47
47
|
import { markAgentWorkFinal } from "./work-finality";
|
|
48
|
+
import { agentProviderState } from "../provider-state";
|
|
48
49
|
import { planSend, type DeliveryReceipt } from "../agent-ref";
|
|
49
50
|
import { receiptWithChannelSuppression } from "./channel-suppression-receipt";
|
|
50
51
|
import { emitMessageDeliveryUpdated, emitMessageQueued, emitNewMessages } from "../sse";
|
|
@@ -203,7 +204,8 @@ function resolveSendTarget(input: SendMessageInput, from: string): DeliveryRecei
|
|
|
203
204
|
}
|
|
204
205
|
// excludeId: a bare ref must never resolve back to its own author — that self-loop silently
|
|
205
206
|
// swallows the message (the reddit-briefing → telegram bridge break, #290).
|
|
206
|
-
const
|
|
207
|
+
const agents = listAgents();
|
|
208
|
+
const plan = planSend(input.to, agents, { excludeId: from });
|
|
207
209
|
// Ambiguous is a real "can't decide" → reject on every transport (categorically unlike
|
|
208
210
|
// not_found, which stores). HTTP → 409, MCP → invalid-params.
|
|
209
211
|
if (plan.kind === "ambiguous") throw new AmbiguousTargetError(plan.message);
|
|
@@ -215,6 +217,8 @@ function resolveSendTarget(input: SendMessageInput, from: string): DeliveryRecei
|
|
|
215
217
|
// direct (incl. a single OFFLINE match — receipt already carries reason "recipient offline")
|
|
216
218
|
// / fanout / passthrough: adopt the canonical (possibly rewritten) id + the receipt.
|
|
217
219
|
input.to = plan.to;
|
|
220
|
+
const providerState = agentProviderState(agents.find(agent => agent.id === plan.to));
|
|
221
|
+
if (providerState?.reason === "providerSetupRequired") throw new ValidationError(providerState.message ?? providerState.recommendedAction ?? "Provider setup required; restart the runner after completing setup.");
|
|
218
222
|
return plan.receipt;
|
|
219
223
|
}
|
|
220
224
|
|
|
@@ -44,7 +44,7 @@ import { emitCommandEvent } from "../command-events";
|
|
|
44
44
|
import { redactCommandSecrets } from "../command-secrets";
|
|
45
45
|
import { buildSpawnCommand, generateSpawnRequestId } from "../spawn-command"; import { systemTagsForSpawn } from "../agent-system-tags";
|
|
46
46
|
import { resolveSpawnLandBlocked } from "../land-block";
|
|
47
|
-
import {
|
|
47
|
+
import { runnerRuntimeTokenEnvAsync } from "../runtime-tokens";
|
|
48
48
|
import { liveSpawnQuota } from "../spawn-quota";
|
|
49
49
|
import { resolveCanonicalHost } from "../host-identity";
|
|
50
50
|
import { resolveSpawnHostAnchor } from "../spawn-targets";
|
|
@@ -59,6 +59,7 @@ import { isolatedSpawnGitRepoError, resolveSpawnRepoRoot } from "./spawn-repo-pr
|
|
|
59
59
|
import { autoSeedProjectForCwdAsync } from "./project"; import { applyProjectCapabilityGates } from "../project-trust";
|
|
60
60
|
import { assertProjectRoleMcpCwd, assertProjectRoleMcpTrusted, projectRoleProfile, projectRoleProvenance, projectRoleSpawnDefaults, withRoleProfile } from "../project-roles";
|
|
61
61
|
import { spawnWarnings } from "./spawn-warnings";
|
|
62
|
+
import { enforceSpawnPolicy, spawnerKind, spawnPolicyTask, type AppliedSpawnPolicy } from "./spawn-policy";
|
|
62
63
|
import { resolveSpawnProjectRole } from "./spawn-project-role";
|
|
63
64
|
import { profileProviderPin, resolveSpawnLaunch } from "./spawn-launch";
|
|
64
65
|
import { hydrateTaskContext, projectTaskHydration } from "./task-context-hydration";
|
|
@@ -210,6 +211,8 @@ export interface SpawnAgentInput extends SelfEffortSpawnInput {
|
|
|
210
211
|
roleSnapshot?: import("../project-roles").ProjectRole;
|
|
211
212
|
workflowCaller?: WorkflowSpawnQuota;
|
|
212
213
|
roleSha?: string; workflowRunId?: string; roleProfile?: string; taskRepoCwd?: string; roleHost?: string;
|
|
214
|
+
/** #3736 — the workflows of the run tree spawning this step, for a spawn-policy `require.workflow`. Service-only. */
|
|
215
|
+
workflowNames?: string[];
|
|
213
216
|
prompt?: string;
|
|
214
217
|
systemPromptAppend?: string;
|
|
215
218
|
/**
|
|
@@ -324,6 +327,8 @@ export interface SpawnAgentResult {
|
|
|
324
327
|
dispatchDecision?: Awaited<ReturnType<typeof dispatchTaskAsync>>;
|
|
325
328
|
/** #3043 — the spawn went ahead, but the caller should know (a role read from a stale default branch). */
|
|
326
329
|
warnings?: string[];
|
|
330
|
+
/** #3736 — the project spawn-policy rules that applied to this spawn. */
|
|
331
|
+
spawnPolicy?: AppliedSpawnPolicy;
|
|
327
332
|
}
|
|
328
333
|
|
|
329
334
|
/** Reject when a component token's signed resource constraints disallow the target (#323). */
|
|
@@ -428,6 +433,11 @@ export async function spawnAgent(input: SpawnAgentInput, ctx: AuthContext): Prom
|
|
|
428
433
|
});
|
|
429
434
|
|
|
430
435
|
assertOrchestratorSupportsLaunchMode(orchestrator, launchMode, input.providerArgs);
|
|
436
|
+
// #3736 — the project's spawn policy, before any side effect: a refusal names the rule, the allowed set and the hint.
|
|
437
|
+
const spawnPolicy = await enforceSpawnPolicy(
|
|
438
|
+
{ projectId: lazyRoot?.projectId ?? resolveProjectForCwd(resolvedCwd)?.id, ...(lazyRoot ? {} : { checkout: { cwd: resolvedCwd, orchestratorId: orchestrator.id } }) },
|
|
439
|
+
{ spawner: spawnerKind(ctx, input, caller), task: spawnPolicyTask(linkedTask), subject: { role: projectRole?.name, profile: profileName, workflows: input.workflowNames } },
|
|
440
|
+
);
|
|
431
441
|
|
|
432
442
|
// Resolve + validate the named agent profile server-side (was HTTP-only; the MCP path passed
|
|
433
443
|
// the name through unvalidated). Omitted profile uses Relay's spawn default so coordinator
|
|
@@ -703,7 +713,7 @@ export async function spawnAgent(input: SpawnAgentInput, ctx: AuthContext): Prom
|
|
|
703
713
|
// Child runner token. `agentInitiated` (set whenever an agent is the caller) forces a
|
|
704
714
|
// non-spawn-capable child (no grandchildren); `spawnedBy` stamps authoritative lineage the
|
|
705
715
|
// child can't forge (it registers with spawnedBy = caller, read from the signed token).
|
|
706
|
-
const env = { ...callerEnv, ...
|
|
716
|
+
const env = { ...callerEnv, ...await runnerRuntimeTokenEnvAsync({
|
|
707
717
|
agentId: targetAgentId,
|
|
708
718
|
orchestratorId: orchestrator.id,
|
|
709
719
|
cwd: resolvedCwd,
|
|
@@ -900,6 +910,7 @@ export async function spawnAgent(input: SpawnAgentInput, ctx: AuthContext): Prom
|
|
|
900
910
|
...(autoScaffoldedTask ? { task: autoScaffoldedTask } : {}),
|
|
901
911
|
...(taskDispatchDecision ? { dispatchDecision: taskDispatchDecision } : {}),
|
|
902
912
|
...(warnings.length ? { warnings } : {}),
|
|
913
|
+
...(spawnPolicy ? { spawnPolicy } : {}),
|
|
903
914
|
};
|
|
904
915
|
}
|
|
905
916
|
|
|
@@ -24,7 +24,7 @@ import { join } from "node:path";
|
|
|
24
24
|
import type { LaunchMode, SpawnProvider } from "@humwick/sdk";
|
|
25
25
|
import { withResolvedProvisioning } from "../db";
|
|
26
26
|
import { getAgentProfile } from "../config-store";
|
|
27
|
-
import { buildSpawnCommand } from "../spawn-command";
|
|
27
|
+
import { buildSpawnCommand, resolveSpawnModelParams } from "../spawn-command";
|
|
28
28
|
import { spawnOptionsFromControl } from "../../orchestrator/src/control";
|
|
29
29
|
import type { SpawnOptions } from "../../orchestrator/src/spawn/types";
|
|
30
30
|
import { buildEnv, buildRunnerCommand } from "../../orchestrator/src/spawn/command";
|
|
@@ -139,18 +139,10 @@ export function prepareSpawnChain(opts: SpawnChainRequest, observe?: SpawnChainP
|
|
|
139
139
|
prompt: opts.spawn?.prompt,
|
|
140
140
|
systemPromptAppend: opts.spawn?.systemPromptAppend,
|
|
141
141
|
headless: opts.spawn?.headless ?? true,
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
...(opts.spawn.effort ? { effort: opts.spawn.effort } : {}),
|
|
147
|
-
// #2595 — window passes through the same payload field production threads.
|
|
148
|
-
...(typeof opts.spawn.contextWindowTokens === "number" && Number.isSafeInteger(opts.spawn.contextWindowTokens) && opts.spawn.contextWindowTokens > 0
|
|
149
|
-
? { contextWindowTokens: opts.spawn.contextWindowTokens }
|
|
150
|
-
: {}),
|
|
151
|
-
},
|
|
152
|
-
}
|
|
153
|
-
: {}),
|
|
142
|
+
modelParams: {
|
|
143
|
+
...resolveSpawnModelParams(provider, opts.spawn?.model, opts.spawn?.effort),
|
|
144
|
+
...(opts.spawn?.contextWindowTokens !== undefined ? { contextWindowTokens: opts.spawn.contextWindowTokens } : {}),
|
|
145
|
+
},
|
|
154
146
|
} as Parameters<typeof buildSpawnCommand>[0]);
|
|
155
147
|
|
|
156
148
|
return prepareCommandChain(cmdParams, opts, observe);
|
|
@@ -216,6 +208,7 @@ export function prepareCommandChain(
|
|
|
216
208
|
provider: cli.provider,
|
|
217
209
|
...(cli.model ? { model: cli.model } : {}),
|
|
218
210
|
...(cli.effort ? { effort: cli.effort } : {}),
|
|
211
|
+
...(cli.modelRecord ? { modelRecord: cli.modelRecord } : {}),
|
|
219
212
|
// #2595 — the real runner CLI carries the window as a flag; carry it through the same seam.
|
|
220
213
|
...(cli.contextWindowTokens !== undefined ? { contextWindowTokens: cli.contextWindowTokens } : {}),
|
|
221
214
|
runnerId: "inspector",
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// #3736 — the one spawn-policy check. spawnAgent runs it for every spawn (relay_spawn_agent,
|
|
2
|
+
// relay_task_dispatch, POST /api/agents/spawn, workflow steps, sub-coordinators); the workflow
|
|
3
|
+
// auto-start asks it which workflow a Task's work runs through. A project without the file, or with
|
|
4
|
+
// an invalid or unreadable one, is not restricted: stored config never fails a spawn.
|
|
5
|
+
import { stringValue, type AgentCard } from "@humwick/sdk";
|
|
6
|
+
import {
|
|
7
|
+
matchSpawnPolicy, SPAWN_POLICY_FILE, spawnPolicyAtCommit, spawnPolicyRefusal, spawnPolicyWorkflow,
|
|
8
|
+
type SpawnerKind, type SpawnPolicy, type SpawnPolicySubject, type SpawnPolicyTask,
|
|
9
|
+
} from "@humwick/sdk/spawn-policy";
|
|
10
|
+
import { ValidationError } from "../db";
|
|
11
|
+
import type { AuthContext } from "./auth-context";
|
|
12
|
+
import { readProjectConfigFirst, type ProjectCheckout } from "./project-config-read";
|
|
13
|
+
|
|
14
|
+
/** Where the policy is read: the spawn's own checkout first, then the project's registered roots. */
|
|
15
|
+
export interface SpawnPolicyWhere {
|
|
16
|
+
projectId?: string;
|
|
17
|
+
checkout?: ProjectCheckout;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** The rules that applied, for the caller's receipt. */
|
|
21
|
+
export interface AppliedSpawnPolicy {
|
|
22
|
+
file: string;
|
|
23
|
+
ref: string;
|
|
24
|
+
sha: string;
|
|
25
|
+
rules: string[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface LoadedSpawnPolicy {
|
|
29
|
+
policy: SpawnPolicy;
|
|
30
|
+
ref: string;
|
|
31
|
+
sha: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async function loadSpawnPolicy(where: SpawnPolicyWhere): Promise<LoadedSpawnPolicy | undefined> {
|
|
35
|
+
if (!where.projectId) return undefined;
|
|
36
|
+
const { lookup } = await readProjectConfigFirst(where.projectId, where.checkout ? [where.checkout] : [], SPAWN_POLICY_FILE, spawnPolicyAtCommit, "spawns are not restricted until it is fixed");
|
|
37
|
+
return lookup?.status === "found" ? { policy: lookup.config, ref: lookup.ref, sha: lookup.sha } : undefined;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** A workflow run's step, a sub-coordinator, any other agent, or a caller with no agent (dashboard, operator). */
|
|
41
|
+
export function spawnerKind(ctx: AuthContext, input: { workflowRunId?: string }, caller: AgentCard | undefined): SpawnerKind {
|
|
42
|
+
if (ctx.actor.kind === "system" && input.workflowRunId) return "workflow";
|
|
43
|
+
if (!caller) return "operator";
|
|
44
|
+
return stringValue(caller.meta?.profile) === "sub-coordinator" ? "sub-coordinator" : "coordinator";
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function spawnPolicyTask(task: { id: number; tags?: readonly string[]; paths?: readonly string[] } | undefined): SpawnPolicyTask | undefined {
|
|
48
|
+
return task ? { id: task.id, ...(task.tags ? { tags: task.tags } : {}), ...(task.paths ? { paths: task.paths } : {}) } : undefined;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Refuses a spawn the project's policy does not allow (a `ValidationError` naming the rule, the
|
|
52
|
+
* allowed set and the hint); otherwise the rules that applied, if any. */
|
|
53
|
+
export async function enforceSpawnPolicy(where: SpawnPolicyWhere, facts: { spawner: SpawnerKind; task?: SpawnPolicyTask; subject: SpawnPolicySubject }): Promise<AppliedSpawnPolicy | undefined> {
|
|
54
|
+
const loaded = await loadSpawnPolicy(where);
|
|
55
|
+
if (!loaded) return undefined;
|
|
56
|
+
const rules = matchSpawnPolicy(loaded.policy, facts);
|
|
57
|
+
if (!rules.length) return undefined;
|
|
58
|
+
const refusal = spawnPolicyRefusal(rules, facts.subject, facts.task);
|
|
59
|
+
if (refusal) throw new ValidationError(refusal);
|
|
60
|
+
return { file: SPAWN_POLICY_FILE, ref: loaded.ref, sha: loaded.sha, rules: rules.map((rule) => rule.name) };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** The workflow the project's policy routes this Task's work through, and the rule that says so. */
|
|
64
|
+
export async function spawnPolicyWorkflowFor(where: SpawnPolicyWhere, facts: { spawner: SpawnerKind; task: SpawnPolicyTask }): Promise<{ workflow: string; rule: string } | undefined> {
|
|
65
|
+
const loaded = await loadSpawnPolicy(where);
|
|
66
|
+
const chosen = loaded && spawnPolicyWorkflow(matchSpawnPolicy(loaded.policy, facts));
|
|
67
|
+
return chosen ? { workflow: chosen.workflow, rule: chosen.rule.name } : undefined;
|
|
68
|
+
}
|
|
@@ -4,11 +4,11 @@ import { getGateway } from "../db/gateway";
|
|
|
4
4
|
import { getAgentAsync } from "../db";
|
|
5
5
|
import { shutdownAgent } from "./shutdown-agent";
|
|
6
6
|
import { currentStop } from "./workflow-effects";
|
|
7
|
-
import { invoke,
|
|
7
|
+
import { invoke, supervisorNow, type Supervisor } from "./workflow-supervisor-state";
|
|
8
8
|
|
|
9
9
|
/** Every retry resumes the same outbox effect; only host witnesses release reservations. */
|
|
10
10
|
export async function performSpawnTreeCleanup(sup: Supervisor, effect: WorkflowEffect): Promise<boolean> {
|
|
11
|
-
const now = (
|
|
11
|
+
const now = supervisorNow();
|
|
12
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 });
|
|
@@ -105,6 +105,7 @@ export interface TaskDispatchSpawnInput {
|
|
|
105
105
|
/** #3045 — the workflow run dispatching this step; #3091 the base profile its step pins, the run's checkout standing in
|
|
106
106
|
* for the Task's repo root, and the host its role is read on first. Service-only. */
|
|
107
107
|
workflowRunId?: string;
|
|
108
|
+
workflowNames?: string[];
|
|
108
109
|
workflowCaller?: SpawnAgentInput["workflowCaller"];
|
|
109
110
|
roleProfile?: string;
|
|
110
111
|
taskRepoCwd?: string;
|
|
@@ -139,6 +140,7 @@ export async function spawnTaskDispatch(input: TaskDispatchSpawnInput, ctx: Auth
|
|
|
139
140
|
role,
|
|
140
141
|
roleSha, roleSnapshot,
|
|
141
142
|
workflowRunId,
|
|
143
|
+
workflowNames: input.workflowNames,
|
|
142
144
|
workflowCaller: input.workflowCaller,
|
|
143
145
|
roleProfile,
|
|
144
146
|
taskRepoCwd,
|
|
@@ -173,6 +175,7 @@ export async function spawnTaskDispatch(input: TaskDispatchSpawnInput, ctx: Auth
|
|
|
173
175
|
...(decision ? { decision } : {}),
|
|
174
176
|
...(reviewTaskId !== undefined ? { reviewTaskId } : {}),
|
|
175
177
|
...(spawn.warnings ? { warnings: spawn.warnings } : {}),
|
|
178
|
+
...(spawn.spawnPolicy ? { spawnPolicy: spawn.spawnPolicy } : {}),
|
|
176
179
|
...(verbose ? { command: summarizeSpawnCommandForCaller(spawn.command) } : {}),
|
|
177
180
|
};
|
|
178
181
|
}
|
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
// live in src/db/task-state-reconcile.ts; every change is applied by its conditional writer, which
|
|
5
5
|
// re-checks the rule in the transaction, then audited here with one `task.reconciled` relay event.
|
|
6
6
|
import { errMessage } from "@humwick/sdk";
|
|
7
|
-
import {
|
|
8
|
-
import { getIssueRef
|
|
7
|
+
import { writerLockAvailable } from "../db/connection";
|
|
8
|
+
import { getIssueRef } from "../db/issue-refs";
|
|
9
|
+
import { updateIssueRefAsync } from "../db/issue-refs-async";
|
|
9
10
|
import { applyTaskStateReconcileAsync, listTaskStateReconcileCandidatesAsync } from "../db/task-state-reconcile-async";
|
|
10
11
|
import { TASK_RECONCILE_ACTOR, type TaskReconcileRule, type TaskStateReconcileApplied } from "../db/task-state-reconcile";
|
|
11
12
|
import { emitRelayEvent } from "../events";
|
|
@@ -104,19 +105,10 @@ async function refreshIssueRefs(refIds: string[], opts: TaskStateReconcileOption
|
|
|
104
105
|
try {
|
|
105
106
|
const live = await (opts.adapterResolver ?? resolveIssueTrackerAdapter)(ref).getStatus(ref);
|
|
106
107
|
const status = live.status === "open" || live.status === "closed" ? live.status : ref.status;
|
|
107
|
-
// The tracker read can take long: re-check the lock right before the write
|
|
108
|
+
// The tracker read can take long: re-check the lock right before the write. The write itself waits on
|
|
109
|
+
// the writer thread, never on the loop (#1870 S7).
|
|
108
110
|
if (steps.contended()) break;
|
|
109
|
-
|
|
110
|
-
try {
|
|
111
|
-
withFastFailConnection(STEP_BUSY_TIMEOUT_MS, () => updateIssueRef(ref.id, { status, title: live.title, closeReason: live.closeReason, statusSyncedAt: Date.now() }));
|
|
112
|
-
return true;
|
|
113
|
-
} catch (error) {
|
|
114
|
-
if (!isSqliteBusyError(error)) throw error;
|
|
115
|
-
result.moreWork = true;
|
|
116
|
-
return false;
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
if (!written) break;
|
|
111
|
+
await updateIssueRefAsync(ref.id, { status, title: live.title, closeReason: live.closeReason, statusSyncedAt: Date.now() });
|
|
120
112
|
closedAny ||= status === "closed";
|
|
121
113
|
} catch (error) {
|
|
122
114
|
refreshFailedAt.set(id, now);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isRecord, SPAWN_PROVIDERS, VALID_WORKSPACE_MODES, APPROVAL_MODES, VALID_AGENT_LIFECYCLES } from "@humwick/sdk";
|
|
2
2
|
import { getTeam, ValidationError } from "../db";
|
|
3
|
-
import {
|
|
3
|
+
import { getConfig, listConfig } from "../config-store";
|
|
4
|
+
import { deleteConfigAsync, setConfigAsync } from "../config-store-write";
|
|
4
5
|
import { TEAM_TEMPLATE_NAMESPACE } from "../team-template-config";
|
|
5
6
|
import { cleanString, optionalEnum } from "../validation";
|
|
6
7
|
import type { AuthContext } from "./auth-context";
|
|
@@ -47,11 +48,11 @@ function withTimestamps(template: TeamTemplate, existing?: TeamTemplate): TeamTe
|
|
|
47
48
|
};
|
|
48
49
|
}
|
|
49
50
|
|
|
50
|
-
export function
|
|
51
|
+
export async function saveTeamTemplateAsync(input: Record<string, unknown>, updatedBy?: string): Promise<TeamTemplate> {
|
|
51
52
|
if (input.teamId !== undefined && input.composition !== undefined) {
|
|
52
53
|
throw new ValidationError("teamId capture and manual composition are mutually exclusive");
|
|
53
54
|
}
|
|
54
|
-
if (input.teamId !== undefined) return
|
|
55
|
+
if (input.teamId !== undefined) return captureTeamTemplateFromTeamAsync(cleanString(input.teamId, "teamId", { required: true, max: 120 })!, input, updatedBy);
|
|
55
56
|
const slug = templateSlug(input);
|
|
56
57
|
const existing = getConfig<TeamTemplate>(TEAM_TEMPLATE_NAMESPACE, slug)?.value;
|
|
57
58
|
const template = withTimestamps({
|
|
@@ -64,7 +65,7 @@ export function saveTeamTemplate(input: Record<string, unknown>, updatedBy?: str
|
|
|
64
65
|
...(cleanString(input.definitionOfDone, "definitionOfDone", { max: 4000 }) ? { definitionOfDone: cleanString(input.definitionOfDone, "definitionOfDone", { max: 4000 }) } : {}),
|
|
65
66
|
...(input.planSkeleton !== undefined ? { planSkeleton: input.planSkeleton as TeamTemplate["planSkeleton"] } : {}),
|
|
66
67
|
}, existing);
|
|
67
|
-
return
|
|
68
|
+
return (await setConfigAsync(TEAM_TEMPLATE_NAMESPACE, template.slug, template, updatedBy)).value as TeamTemplate;
|
|
68
69
|
}
|
|
69
70
|
|
|
70
71
|
export function listTeamTemplates(): TeamTemplate[] {
|
|
@@ -75,8 +76,8 @@ export function getTeamTemplate(slug: string): TeamTemplate | null {
|
|
|
75
76
|
return getConfig<TeamTemplate>(TEAM_TEMPLATE_NAMESPACE, slug)?.value ?? null;
|
|
76
77
|
}
|
|
77
78
|
|
|
78
|
-
export function
|
|
79
|
-
return
|
|
79
|
+
export function deleteTeamTemplateAsync(slug: string, updatedBy?: string): Promise<boolean> {
|
|
80
|
+
return deleteConfigAsync(TEAM_TEMPLATE_NAMESPACE, slug, updatedBy);
|
|
80
81
|
}
|
|
81
82
|
|
|
82
83
|
function parseFrozenComposition(raw: string): Array<Record<string, unknown>> {
|
|
@@ -107,7 +108,7 @@ function compositionFromFrozenSnapshot(raw: string): TeamTemplateCompositionEntr
|
|
|
107
108
|
return composition;
|
|
108
109
|
}
|
|
109
110
|
|
|
110
|
-
export function
|
|
111
|
+
export async function captureTeamTemplateFromTeamAsync(teamId: string, input: Record<string, unknown> = {}, updatedBy?: string): Promise<TeamTemplate> {
|
|
111
112
|
const team = getTeam(teamId);
|
|
112
113
|
if (!team) throw new ValidationError(`team ${teamId} not found`);
|
|
113
114
|
if (!team.composition) throw new ValidationError("team has no frozen composition snapshot; dissolve it before capture");
|
|
@@ -123,7 +124,7 @@ export function captureTeamTemplateFromTeam(teamId: string, input: Record<string
|
|
|
123
124
|
...(team.brief ? { brief: team.brief } : {}),
|
|
124
125
|
...(team.definitionOfDone ? { definitionOfDone: team.definitionOfDone } : {}),
|
|
125
126
|
}, existing);
|
|
126
|
-
return
|
|
127
|
+
return (await setConfigAsync(TEAM_TEMPLATE_NAMESPACE, template.slug, template, updatedBy)).value as TeamTemplate;
|
|
127
128
|
}
|
|
128
129
|
|
|
129
130
|
function cleanWait(value: unknown): number {
|
|
@@ -15,6 +15,7 @@ import { activeAgentKeep } from "./agent-keep";
|
|
|
15
15
|
import { automaticDisposalBlocker } from "./automatic-disposal";
|
|
16
16
|
import { agentGenerationKey } from "../db/agent-shutdown-in-flight";
|
|
17
17
|
import { workflowAgentObligation } from "./workflow-agent-obligation";
|
|
18
|
+
import { workflowRunPaused } from "../db/workflow-task-read-ops";
|
|
18
19
|
import type { AgentCard, Command, WorkspaceRecord } from "../types";
|
|
19
20
|
import { emitCommandEvent } from "../command-events";
|
|
20
21
|
|
|
@@ -356,7 +357,8 @@ export async function reapTransientAgents(context: { signal?: AbortSignal } = {}
|
|
|
356
357
|
if (completedProviderTurns(agent) === 0) { transientTracker.delete(agent.id); waiting.push(agent.id); continue; }
|
|
357
358
|
// #3234 — an empty branch is not completion while the workflow still awaits this agent's delivery.
|
|
358
359
|
const runId = workflowRunIdOf(agent);
|
|
359
|
-
|
|
360
|
+
// #3757 — a paused run keeps all its step agents.
|
|
361
|
+
if (runId && (workflowRunPaused(runId) || await workflowAgentObligation(runId, agent.id))) { transientTracker.delete(agent.id); waiting.push(agent.id); continue; }
|
|
360
362
|
const entry = transientTracker.get(agent.id) ?? { firstIdleAt: now };
|
|
361
363
|
transientTracker.set(agent.id, entry);
|
|
362
364
|
const idleForMs = now - entry.firstIdleAt;
|