@humwick/server 0.130.1 → 0.130.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/bundled/prompts/manifest.json +1 -0
- package/bundled/prompts/task.hydration.md +1 -1
- package/bundled/roles/builder.md +1 -1
- package/docs/guides/sub-coordinators.md +12 -5
- package/docs/guides/tools-administration.md +4 -0
- package/docs/guides/tools-coordination.md +2 -0
- package/docs/guides/tools-tasks.md +8 -0
- package/docs/guides/workflows.md +74 -0
- package/docs/openapi.json +486 -4
- package/package.json +10 -18
- package/public/assets/{MessageBubble-BWpoBjl4.js → MessageBubble-Bq9kr21N.js} +2 -2
- package/public/assets/{PlanGraphPanel-C0auck3n.js → PlanGraphPanel-Dqiroy06.js} +2 -2
- package/public/assets/{TraceView-DBnOx7AQ.js → TraceView-DYU962-H.js} +2 -2
- package/public/assets/{VaultDecisionCard-0kp2oNBC.js → VaultDecisionCard-DhPfzioE.js} +2 -2
- package/public/assets/{activity-yLztXEBt.js → activity-DzCcQTee.js} +2 -2
- package/public/assets/{agent-lineage-BbJDR1dW.js → agent-lineage-SgDt9i3T.js} +2 -2
- package/public/assets/agent-liveness-Bq-s73jW.js +2 -0
- package/public/assets/{agent-name-CTZBrSD9.js → agent-name-CcY3Aijy.js} +2 -2
- package/public/assets/agent-profiles-cxtRBn6O.js +2 -0
- package/public/assets/{agent-project-badge-9TqzUUYE.js → agent-project-badge-DGYbIhaI.js} +2 -2
- package/public/assets/{agent-tools-D4n40pn8.js → agent-tools-DHbftV0N.js} +2 -2
- package/public/assets/{agent-type-icon-D6FUarOf.js → agent-type-icon-CY113sp-.js} +2 -2
- package/public/assets/{agents-BYDslkJc.js → agents-BPzY7IlQ.js} +2 -2
- package/public/assets/{analytics-B-XSbEMC.js → analytics-DENFPv_a.js} +2 -2
- package/public/assets/{artifact-viewer-DdWIfV6M.js → artifact-viewer-KRvSc7sl.js} +2 -2
- package/public/assets/{artifacts-DPN1q4pA.js → artifacts-C9gSmL3s.js} +2 -2
- package/public/assets/{artifacts-oBOqks-2.js → artifacts-DT-HkI5O.js} +2 -2
- package/public/assets/{automation-4KcRFXEu.js → automation-BsmjQhKD.js} +2 -2
- package/public/assets/{backlog-Cw9xPTCF.js → backlog-8NYH_62t.js} +2 -2
- package/public/assets/{busy-health-CTu32MZt.js → busy-health-D3hwvYb4.js} +2 -2
- package/public/assets/{channels-BiXzg1G9.js → channels-DCJ5WL7O.js} +2 -2
- package/public/assets/{chat-Ctk2qwvA.js → chat-DAIl357U.js} +3 -3
- package/public/assets/{code-preview-Bm1wWqAp.js → code-preview-CzrZfr9U.js} +2 -2
- package/public/assets/{connectors-C36ax4Vw.js → connectors-xTxtlyou.js} +2 -2
- package/public/assets/{cosmos-Jj9LK2Wf.js → cosmos-BpebFLK2.js} +2 -2
- package/public/assets/{crate-agent-H6S7-B9T.js → crate-agent-BHvI5wXC.js} +2 -2
- package/public/assets/{dependency-graph-Cd1E23wa.js → dependency-graph-DGT0o3wJ.js} +2 -2
- package/public/assets/{deploys-Bwfq146q.js → deploys-hqWOHSHE.js} +2 -2
- package/public/assets/{display-CfO7rTuF.js → display-CDeH4I8T.js} +2 -2
- package/public/assets/{files-DhhZI2Ih.js → files-BTeGVmTg.js} +2 -2
- package/public/assets/{fleet-B_rFEbnL.js → fleet-DgXtNgCa.js} +2 -2
- package/public/assets/{fleet-metrics-BkHP-P3R.js → fleet-metrics-BHEt5yc_.js} +2 -2
- package/public/assets/{formatted-body-Cm1RrzmN.js → formatted-body-MLtodyPp.js} +3 -3
- package/public/assets/{formatted-body-impl-DQiOuOD1.js → formatted-body-impl-CAe664Z8.js} +2 -2
- package/public/assets/{host-providers-dialog-CHqwXTov.js → host-providers-dialog-mapF4Fj9.js} +2 -2
- package/public/assets/index-CqqgOI5R.js +15 -0
- package/public/assets/index-MYAIwYTX.css +2 -0
- package/public/assets/{insights-fH1EL-qZ.js → insights-DNyf7IzF.js} +2 -2
- package/public/assets/{integrations-C5Oix6ng.js → integrations-DlYOHq7T.js} +2 -2
- package/public/assets/{issue-ref-chip-ODyondIa.js → issue-ref-chip-CeWBNWn7.js} +2 -2
- package/public/assets/{log-viewer-Cvfy6PW7.js → log-viewer-Cib8nqdE.js} +2 -2
- package/public/assets/{maintenance-D8CDH5wZ.js → maintenance-DSn1cPm7.js} +2 -2
- package/public/assets/{managed-agents-egllbpij.js → managed-agents-C3CkM81m.js} +2 -2
- package/public/assets/{markdown-preview-CYSFgVgK.js → markdown-preview-W4VQQPAv.js} +3 -3
- package/public/assets/{markdown-preview-impl-BteVIjX4.js → markdown-preview-impl-CMsTdhjq.js} +2 -2
- package/public/assets/{memory-C8WmXsyr.js → memory-BV17qtO4.js} +2 -2
- package/public/assets/{messages-BzQdqlO6.js → messages-Bm_1AqSA.js} +2 -2
- package/public/assets/{orchestrators-B1HxzkNw.js → orchestrators-Dg-vfP09.js} +2 -2
- package/public/assets/{overview-DCUnI4Z7.js → overview-DcYCrvlr.js} +2 -2
- package/public/assets/{pairs-ftCd2XcD.js → pairs-8o9nuG3V.js} +2 -2
- package/public/assets/{profile-icon-B2zH8DMH.js → profile-icon-BsRyBMea.js} +2 -2
- package/public/assets/project-profile-instructions-DETKFn_E.js +2 -0
- package/public/assets/projects-M_m6AHws.js +2 -0
- package/public/assets/{prompt-settings-Bftq9czX.js → prompt-settings-C_mNCgeL.js} +2 -2
- package/public/assets/provider-display-BEeLXC_D.js +2 -0
- package/public/assets/{registry-DWCU5c8q.js → registry-DDHHHE5N.js} +2 -2
- package/public/assets/run-card-Dt4I4jaP.js +2 -0
- package/public/assets/scroll-text-BKXS1ahr.js +2 -0
- package/public/assets/{secrets-C7GIUATz.js → secrets-BkVwxI5O.js} +2 -2
- package/public/assets/{service-access-settings-C3aujqTG.js → service-access-settings-Crq-6a-B.js} +2 -2
- package/public/assets/{settings-C6sZ9eBa.js → settings-CYcavMFu.js} +2 -2
- package/public/assets/shipping-H6gzEeZB.js +2 -0
- package/public/assets/{stats-V9Z-GxUd.js → stats-BJVeWkpV.js} +2 -2
- package/public/assets/{status-dot-CVv0iGHL.js → status-dot-BcHyw1Vw.js} +2 -2
- package/public/assets/store-DKPDIZBe.js +9 -0
- package/public/assets/{tasks-CXU75HRF.js → tasks-qJjlQPpx.js} +2 -2
- package/public/assets/{teams-BPf976zb.js → teams-Cd5Sk1uX.js} +2 -2
- package/public/assets/{terminal-viewer-DE9BOe-8.js → terminal-viewer-CpY5_m7W.js} +3 -3
- package/public/assets/{terminal-viewer-impl-D04pjmGh.js → terminal-viewer-impl-DI_2llFR.js} +2 -2
- package/public/assets/token-estimate-Co-Jdphh.js +2 -0
- package/public/assets/{use-agent-terminal-B1yR456R.js → use-agent-terminal-0yJA_buM.js} +2 -2
- package/public/assets/{use-decisions-D-S4tpDf.js → use-decisions-uJXHf34W.js} +2 -2
- package/public/assets/use-project-list-CpWl6eHQ.js +2 -0
- package/public/assets/{use-selectors-CnrAk2YP.js → use-selectors-BdxBW8mL.js} +2 -2
- package/public/assets/{user-avatar-nBFIcR4M.js → user-avatar-3IndfpOc.js} +2 -2
- package/public/assets/versioned-prompt-editor-CIVg7XB1.js +8 -0
- package/public/assets/{work-queue-TCjJxeT-.js → work-queue-B9rnLwHZ.js} +2 -2
- package/public/assets/{workflow-marker-Cf3Hf2fN.js → workflow-marker-X8wxyhzC.js} +2 -2
- package/public/assets/{workflows-CXQX20Qj.js → workflows-o5YyMFW7.js} +2 -2
- package/public/assets/{workspaces-qSYzKYMA.js → workspaces-CzEGoAng.js} +2 -2
- package/public/cosmos.html +4 -4
- package/public/index.html +31 -29
- package/runner/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/runner/plugins/claude/hooks/gate-run-guard.provisioned.mjs +31 -1
- package/runner/src/adapters/claude-effort.ts +2 -4
- package/runner/src/adapters/claude-headless.ts +1 -1
- package/runner/src/adapters/claude-launch-exit.ts +26 -0
- package/runner/src/adapters/claude-session-probe.ts +1 -1
- package/runner/src/adapters/claude-tmux.ts +38 -10
- package/runner/src/adapters/claude.ts +28 -75
- package/runner/src/adapters/codex-launch-config.ts +4 -5
- package/runner/src/adapters/codex.ts +1 -1
- package/runner/src/adapters/opencode-provider.ts +7 -22
- package/runner/src/adapters/opencode.ts +4 -4
- package/runner/src/adapters/provider-quota-harvest.ts +20 -71
- package/runner/src/agent-runner/credentials.ts +42 -12
- package/runner/src/agent-runner/inbox.ts +27 -0
- package/runner/src/agent-runner/lifecycle-milestones.ts +2 -4
- package/runner/src/agent-runner/liveness-exchange.ts +104 -0
- package/runner/src/bin/claude.ts +4 -0
- package/runner/src/bin/codex.ts +4 -0
- package/runner/src/bin/opencode.ts +4 -0
- package/runner/src/claude-system-prompt.ts +49 -0
- package/runner/src/index.ts +5 -2
- package/runner/src/launch-assembly.ts +14 -10
- package/runner/src/profile-home.ts +1 -1
- package/runner/src/project-instructions.ts +2 -2
- package/runner/src/provider-command.ts +18 -0
- package/runner/src/provider-setup.ts +35 -0
- package/runner/src/providers.ts +2 -1
- package/runner/src/runner-core.ts +32 -38
- package/runner/src/runner-helpers.ts +0 -8
- package/runner/src/session-scratch.ts +6 -2
- package/runner/src/spawn-input.ts +2 -1
- package/runner/src/test-run-dedup.ts +59 -56
- package/runner/test-support/provisioning-context.ts +4 -2
- package/runner/test-support/runner-harness.ts +2 -1
- package/scripts/cd-config.ts +8 -0
- package/scripts/gate-run-lease.ts +10 -7
- package/scripts/gate.sh +5 -1
- package/scripts/steward-policy-cleanup.ts +2 -2
- package/src/agent-authz.ts +2 -2
- package/src/agent-drive-arbiter.ts +3 -8
- package/src/agent-exit-cleanup-async.ts +2 -2
- package/src/agent-exit-cleanup.ts +23 -19
- package/src/agent-lifecycle-events.ts +112 -85
- package/src/agent-ref.ts +3 -2
- package/src/agent-status-events.ts +43 -14
- package/src/auth/password.ts +4 -3
- package/src/auth/session-refresh.ts +1 -1
- package/src/auth/session.test-fixture.ts +2 -2
- package/src/auth/session.ts +7 -7
- package/src/automations/crud.ts +8 -81
- package/src/automations/dispatch.ts +33 -58
- package/src/automations/index.ts +1 -1
- package/src/automations/persistence.ts +65 -0
- package/src/automations/precheck.ts +18 -16
- package/src/automations/read-async.ts +11 -0
- package/src/automations/reconcile.ts +30 -39
- package/src/automations/storage.ts +33 -10
- package/src/automations/write-async.ts +33 -0
- package/src/branch-land-notice.ts +93 -0
- package/src/branch-landed.ts +31 -98
- package/src/bus.ts +40 -39
- package/src/cd-deploy-notify.ts +32 -4
- package/src/cd-host-lag-notify.ts +7 -6
- package/src/ci/incidents.ts +2 -2
- package/src/ci/monitor.ts +5 -8
- package/src/ci/notifications.ts +4 -4
- package/src/ci/root-missing.ts +4 -9
- package/src/ci/transition-notify.ts +12 -44
- package/src/claude-app/oauth-http.ts +3 -3
- package/src/cli/cd-pauses.ts +19 -0
- package/src/cli/orchestrator.ts +1 -1
- package/src/cli/state.ts +2 -19
- package/src/cli/task-edit.ts +22 -0
- package/src/cli/task.ts +3 -1
- package/src/cli/workflow.ts +19 -4
- package/src/commands-db.ts +7 -7
- package/src/commands-write.ts +8 -0
- package/src/compaction-watch.ts +10 -8
- package/src/config-store-write.ts +13 -1
- package/src/config-store.ts +25 -14
- package/src/config.ts +4 -11
- package/src/connectors.ts +10 -8
- package/src/context-advisory.ts +22 -21
- package/src/db/activity-async.ts +6 -1
- package/src/db/activity-write-ops.ts +12 -1
- package/src/db/activity.ts +1 -14
- package/src/db/agent-action-write.ts +36 -0
- package/src/db/agent-control-async.ts +9 -0
- package/src/db/agent-control-write.ts +49 -0
- package/src/db/agent-effort-observe.ts +22 -0
- package/src/db/agent-meta.ts +14 -3
- package/src/db/agent-search.ts +1 -15
- package/src/db/agents-async.ts +59 -9
- package/src/db/agents-write-ops.ts +12 -3
- package/src/db/agents.ts +95 -65
- package/src/db/auth-identities.ts +2 -2
- package/src/db/automation-read-ops.ts +11 -0
- package/src/db/automation-write-ops.ts +46 -0
- package/src/db/blackboard.ts +2 -2
- package/src/db/browser-session-write.ts +32 -0
- package/src/db/bus-outbox-write-ops.ts +3 -1
- package/src/db/checkout-refresh-schema.ts +47 -0
- package/src/db/checkout-refresh.ts +5 -5
- package/src/db/ci-incidents-async.ts +5 -5
- package/src/db/ci-incidents-write-ops.ts +2 -2
- package/src/db/command-agent-profile-backfill.ts +39 -0
- package/src/db/command-agent-profiles.ts +5 -1
- package/src/db/command-retention.ts +126 -0
- package/src/db/command-row.ts +10 -2
- package/src/db/commands-list-query.ts +2 -0
- package/src/db/commands-planner-stats.test-fixture.ts +8 -0
- package/src/db/commands-read-ops.ts +16 -0
- package/src/db/commands-spawn-read.ts +1 -1
- package/src/db/config-store-write-ops.ts +7 -2
- package/src/db/connection.ts +1 -182
- package/src/db/context-carry-write.ts +74 -0
- package/src/db/continuation-archives-async.ts +5 -0
- package/src/db/continuation-archives-write-ops.ts +7 -0
- package/src/db/continuations.ts +6 -6
- package/src/db/db-error-registry.ts +12 -0
- package/src/db/db-writer-worker.ts +8 -1
- package/src/db/deploy-events-async.ts +1 -0
- package/src/db/deploy-events-read-ops.ts +2 -1
- package/src/db/deploy-events.ts +35 -4
- package/src/db/gateway.ts +26 -133
- package/src/db/history-retention-ops.ts +13 -0
- package/src/db/hosts-registration.ts +10 -2
- package/src/db/hosts.ts +9 -6
- package/src/db/inbox-async.ts +2 -2
- package/src/db/inbox-read-ops.ts +1 -1
- package/src/db/inbox.ts +9 -17
- package/src/db/index.ts +2 -0
- package/src/db/integrations-async.ts +8 -0
- package/src/db/integrations-ops.ts +15 -0
- package/src/db/integrations.ts +15 -21
- package/src/db/issue-associations.ts +2 -2
- package/src/db/issue-lifecycle.ts +3 -4
- package/src/db/issue-refs-async.ts +23 -0
- package/src/db/issue-refs-read-ops.ts +6 -0
- package/src/db/issue-refs-write-ops.ts +29 -0
- package/src/db/issue-refs.ts +15 -16
- package/src/db/kernel-event-log-schema.ts +2 -0
- package/src/db/land-boundaries.ts +51 -5
- package/src/db/land-gate-attestations.ts +2 -2
- package/src/db/landing-receipts.ts +2 -2
- package/src/db/lifecycle-context-write.ts +5 -0
- package/src/db/lifecycle-tail-async.ts +76 -0
- package/src/db/lifecycle-tail-write-ops.ts +62 -0
- package/src/db/lifecycle-write-window.ts +2 -1
- package/src/db/lineage-pair-dedupe-sql.ts +3 -3
- package/src/db/long-running-work.ts +2 -2
- package/src/db/main-connection-mode.ts +11 -0
- package/src/db/main-connection-writes.ts +41 -2
- package/src/db/maintenance-job-reconcile.ts +61 -0
- package/src/db/maintenance-job-runs-async.ts +14 -0
- package/src/db/maintenance-job-write-ops.ts +9 -0
- package/src/db/maintenance-pauses.ts +2 -2
- package/src/db/mappers.ts +2 -14
- package/src/db/merge-lease.ts +1 -15
- package/src/db/message-send.ts +4 -0
- package/src/db/messages.ts +31 -25
- package/src/db/migrations.ts +25 -16
- package/src/db/notification-write-ops.ts +19 -0
- package/src/db/operator-answer-write.ts +19 -0
- package/src/db/orchestrators.ts +14 -76
- package/src/db/pairs-async.ts +22 -1
- package/src/db/pairs-write-ops.ts +8 -3
- package/src/db/pairs.ts +42 -61
- package/src/db/plan-dispatch-schema.ts +5 -1
- package/src/db/plan-ready-notices.ts +43 -0
- package/src/db/plan-tools-include-migration.ts +36 -0
- package/src/db/plans-write-ops.ts +2 -0
- package/src/db/presence-buffer.ts +5 -0
- package/src/db/presence-loop.ts +18 -23
- package/src/db/presence-write.ts +0 -6
- package/src/db/project-entries-async.ts +14 -0
- package/src/db/project-entries-read-ops.ts +5 -1
- package/src/db/project-entries-write-ops.ts +8 -0
- package/src/db/project-entries.ts +15 -12
- package/src/db/project-journal.ts +2 -2
- package/src/db/project-profile-instructions.ts +50 -0
- package/src/db/project-trust-approvals.ts +2 -2
- package/src/db/prompt-templates.ts +4 -4
- package/src/db/prompt-versions.ts +9 -2
- package/src/db/provider-config-history.ts +8 -3
- package/src/db/provider-model-seed.ts +34 -0
- package/src/db/read-op-marshaling-fixtures.ts +23 -0
- package/src/db/read-ops.ts +8 -0
- package/src/db/retention.ts +13 -2
- package/src/db/review-publish-write.ts +8 -0
- package/src/db/routing-policy.ts +2 -3
- package/src/db/runtime-admin-async.ts +19 -0
- package/src/db/runtime-admin-write-ops.ts +36 -0
- package/src/db/runtime-tail-async.ts +288 -0
- package/src/db/runtime-tail-write-ops.ts +97 -0
- package/src/db/schema.ts +13 -4
- package/src/db/spawn-budget.ts +5 -0
- package/src/db/spawn-delegation-state.ts +11 -4
- package/src/db/spawn-delegation.ts +1 -11
- package/src/db/sql-audit-indexes.ts +3 -0
- package/src/db/stats-async.ts +9 -6
- package/src/db/task-entity.ts +28 -6
- package/src/db/task-list.ts +3 -1
- package/src/db/tasks.ts +1 -17
- package/src/db/team-claim-policy.ts +60 -0
- package/src/db/teams-async.ts +4 -0
- package/src/db/teams-write-ops.ts +4 -0
- package/src/db/terminal-events.ts +15 -0
- package/src/db/timer-cutover-bodies.ts +292 -0
- package/src/db/timer-cutover-core.ts +37 -278
- package/src/db/timer-cutover-state.ts +40 -0
- package/src/db/timer-cutover-write-ops.ts +1 -40
- package/src/db/timer-ingress.ts +7 -1
- package/src/db/token-db-write-ops.ts +19 -0
- package/src/db/token-standing-async.ts +12 -0
- package/src/db/token-standing.ts +21 -20
- package/src/db/token-usage-retention.ts +33 -0
- package/src/db/token-usage-write-ops.ts +1 -1
- package/src/db/token-usage.ts +4 -1
- package/src/db/user-invites-async.ts +13 -0
- package/src/db/user-invites.ts +3 -3
- package/src/db/users.ts +14 -6
- package/src/db/workflow-contact.ts +1 -1
- package/src/db/workflow-task-read-ops.ts +30 -0
- package/src/db/workspaces.ts +8 -5
- package/src/db/write-ops.ts +37 -12
- package/src/db/writer-fault-seam.ts +2 -9
- package/src/db/writer-fault-test-ops.ts +18 -0
- package/src/db/writer-gateway.ts +58 -56
- package/src/dev.ts +8 -3
- package/src/dispatch-availability.ts +10 -6
- package/src/ephemeral/{landing-ingress-proof-worker.ts → landing-ingress-proof.test-fixture.ts} +4 -2
- package/src/event-loop-lag.ts +4 -2
- package/src/event-loop-yield.ts +2 -2
- package/src/events.ts +10 -8
- package/src/host/disk-alert.ts +121 -0
- package/src/host-provider-store.ts +5 -4
- package/src/hub-metrics-report.ts +5 -1
- package/src/hub-metrics.ts +38 -18
- package/src/injection-sweep-pacing.ts +6 -8
- package/src/land-gate-notifications.ts +11 -10
- package/src/land-gate-queue-progress.ts +3 -3
- package/src/land-settle-dispatch.ts +52 -92
- package/src/lifecycle-context-pressure.ts +11 -10
- package/src/lifecycle-manager.ts +107 -100
- package/src/maintenance/breaker.ts +18 -16
- package/src/maintenance/cd-watcher.ts +3 -3
- package/src/maintenance/checkout-refresh.ts +18 -1
- package/src/maintenance/critical-job-watchdog.ts +19 -20
- package/src/maintenance/events.ts +3 -3
- package/src/maintenance/history-retention-job.ts +30 -0
- package/src/maintenance/index.ts +1 -0
- package/src/maintenance/jobs.ts +32 -69
- package/src/maintenance/long-running-work.ts +3 -1
- package/src/maintenance/offline-agent-prune-job.ts +28 -0
- package/src/maintenance/orphaned-sessions.ts +5 -4
- package/src/maintenance/pauses.ts +4 -10
- package/src/maintenance/plan-ready-notice-job.ts +71 -0
- package/src/maintenance/scheduler.ts +98 -137
- package/src/maintenance/stalled-delivery-pager.ts +10 -9
- package/src/maintenance/teams.ts +19 -30
- package/src/maintenance/workspaces.ts +18 -28
- package/src/managed-policy-escalation.ts +7 -7
- package/src/managed-policy.ts +32 -28
- package/src/managed-provider-gate.ts +5 -4
- package/src/managed-spawn-reservation.ts +5 -4
- package/src/mcp/index.ts +12 -9
- package/src/mcp/output-descriptions.ts +8 -8
- package/src/mcp/presentation.ts +6 -5
- package/src/mcp/project-profile-instructions.ts +32 -0
- package/src/mcp/runtime-output.ts +6 -1
- package/src/mcp/self-care-visibility.ts +2 -2
- package/src/mcp/spawn-targets-matrix.ts +10 -1
- package/src/mcp/tool-groups.ts +4 -3
- package/src/mcp/tool-roles.ts +81 -0
- package/src/mcp/tools-spawn.ts +4 -3
- package/src/mcp/tools-workspace.ts +1 -1
- package/src/mcp-agent-action.ts +1 -2
- package/src/mcp-blackboard-tools.ts +6 -5
- package/src/mcp-decision-tools.ts +7 -7
- package/src/mcp-egress-tools.ts +10 -9
- package/src/mcp-issue-activity-tools.ts +2 -2
- package/src/mcp-issue-association-tools.ts +4 -4
- package/src/mcp-issue-ref-tools.ts +13 -12
- package/src/mcp-maintenance-tools.ts +2 -2
- package/src/mcp-merge-tools.ts +5 -5
- package/src/mcp-notification-subscription-tools.ts +14 -15
- package/src/mcp-output-levels.test-fixture.ts +1 -1
- package/src/mcp-profile-trust-tools.ts +5 -5
- package/src/mcp-project-journal-tools.ts +4 -12
- package/src/mcp-project-tools.ts +17 -18
- package/src/mcp-provider-catalog.ts +2 -2
- package/src/mcp-routing-policy-tools.ts +3 -2
- package/src/mcp-task-tools.ts +11 -5
- package/src/mcp-team-template-tools.ts +3 -3
- package/src/mcp-team-tools.ts +6 -6
- package/src/mcp-workflow-tools.ts +13 -4
- package/src/memory-area-injection.ts +13 -12
- package/src/memory-boundary-capture.ts +6 -6
- package/src/memory-injection.ts +45 -43
- package/src/merge-pause-maintenance.ts +5 -4
- package/src/notification-router.ts +44 -17
- package/src/notification-types.ts +2 -1
- package/src/notify.ts +5 -5
- package/src/observed-reset-refresh.ts +4 -4
- package/src/operator-alarm.ts +23 -11
- package/src/project-ingest.ts +6 -6
- package/src/project-instructions.ts +12 -1
- package/src/project-profile-instruction-text.ts +6 -0
- package/src/project-profile-instructions.ts +20 -0
- package/src/project-trust.ts +12 -11
- package/src/prompt-resolver.ts +3 -3
- package/src/provider-catalog-store.ts +3 -49
- package/src/provider-config-store.ts +12 -11
- package/src/provider-model-seed.ts +1 -18
- package/src/provider-quota-async.ts +5 -7
- package/src/provider-quota-config-store.ts +5 -4
- package/src/provider-secrets.test-fixture.ts +3 -3
- package/src/provider-timeline-event.ts +4 -7
- package/src/quota-band-delivery.ts +2 -2
- package/src/recipe-runner.ts +6 -5
- package/src/repo-config-source.ts +10 -4
- package/src/retention-config-store.ts +4 -3
- package/src/reviewer-pipeline.ts +11 -10
- package/src/routes/_route.ts +4 -4
- package/src/routes/_shared.ts +13 -12
- package/src/routes/agent-effort.ts +5 -5
- package/src/routes/agent-heartbeat-quota.ts +23 -0
- package/src/routes/agent-keep.ts +1 -1
- package/src/routes/agent-profiles.ts +6 -6
- package/src/routes/agent-reporting.ts +1 -1
- package/src/routes/agent-self-effort.ts +5 -5
- package/src/routes/agent-sessions.ts +24 -24
- package/src/routes/agents-spawn.ts +2 -2
- package/src/routes/agents.ts +19 -121
- package/src/routes/auth.ts +14 -15
- package/src/routes/authority-audit.ts +2 -2
- package/src/routes/automations.ts +6 -5
- package/src/routes/channel-binding-delete.ts +1 -1
- package/src/routes/channel-output.ts +3 -3
- package/src/routes/claude-api-budget.ts +5 -5
- package/src/routes/commands-listing.ts +5 -1
- package/src/routes/commands.ts +31 -29
- package/src/routes/context-resets.ts +2 -2
- package/src/routes/continuation-archives.ts +2 -2
- package/src/routes/coordinator-teams.ts +1 -1
- package/src/routes/decisions.ts +2 -2
- package/src/routes/host-secret-files.ts +1 -1
- package/src/routes/hosts.ts +11 -11
- package/src/routes/inbox.ts +3 -2
- package/src/routes/index.ts +12 -2
- package/src/routes/integrations.ts +32 -56
- package/src/routes/issue-activity.ts +2 -2
- package/src/routes/issue-associations.ts +4 -4
- package/src/routes/issue-refs.ts +9 -9
- package/src/routes/kernel-timers-operator.ts +1 -1
- package/src/routes/memory.ts +1 -1
- package/src/routes/merges.ts +11 -11
- package/src/routes/messages.ts +23 -17
- package/src/routes/orchestrator-bootstrap.ts +2 -2
- package/src/routes/orchestrator-host-registration.ts +4 -2
- package/src/routes/orchestrator-host-utilization.ts +5 -3
- package/src/routes/orchestrator-proxy.ts +4 -4
- package/src/routes/orchestrator.ts +28 -19
- package/src/routes/pairs.ts +8 -8
- package/src/routes/project-profile-instructions.ts +27 -0
- package/src/routes/project-trust.ts +3 -3
- package/src/routes/projects.ts +16 -16
- package/src/routes/prompt-templates.ts +12 -12
- package/src/routes/provider-config.ts +6 -6
- package/src/routes/provider-quota-config.ts +2 -2
- package/src/routes/provider-quotas.ts +10 -10
- package/src/routes/run-command.ts +1 -1
- package/src/routes/secrets-backup.ts +2 -2
- package/src/routes/secrets-import.ts +1 -1
- package/src/routes/secrets-vault.ts +7 -7
- package/src/routes/settings.ts +6 -6
- package/src/routes/shipping.ts +9 -1
- package/src/routes/spawn-policy.ts +8 -7
- package/src/routes/sse.ts +2 -2
- package/src/routes/stats.ts +6 -6
- package/src/routes/task-http.ts +15 -1
- package/src/routes/task-issues.ts +11 -26
- package/src/routes/tasks.ts +22 -53
- package/src/routes/team-templates.ts +12 -12
- package/src/routes/teams-config.ts +2 -2
- package/src/routes/teams.ts +10 -10
- package/src/routes/tokens.ts +30 -22
- package/src/routes/users.ts +24 -24
- package/src/routes/viewer-read.ts +3 -3
- package/src/routes/web-tool-calls.ts +4 -4
- package/src/routes/workflows.ts +22 -7
- package/src/routes/workspaces.ts +17 -16
- package/src/routing-policy-normalize.ts +1 -2
- package/src/routing-policy-push.ts +6 -6
- package/src/routing-step-defaults.ts +0 -2
- package/src/runner-token-mint-limit.ts +63 -0
- package/src/runtime-grant.ts +21 -13
- package/src/runtime-tokens.ts +59 -35
- package/src/secrets-broker/config.ts +1 -1
- package/src/secrets-broker/service.ts +2 -2
- package/src/security.ts +16 -21
- package/src/self-resume-carry.ts +21 -110
- package/src/self-resume-supersede.ts +4 -3
- package/src/self-resume.ts +54 -66
- package/src/server-background.ts +2 -2
- package/src/server.ts +26 -24
- package/src/services/agent-action.ts +12 -31
- package/src/services/agent-effort.ts +7 -32
- package/src/services/agent-hang-watchdog-job.ts +2 -2
- package/src/services/agent-heartbeat.ts +166 -0
- package/src/services/agent-reporting.ts +1 -1
- package/src/services/browser-inventory.ts +3 -3
- package/src/services/browser-session-state.ts +3 -2
- package/src/services/browser-session.ts +21 -27
- package/src/services/bus-command-update.ts +9 -9
- package/src/services/checkout-refresh-state.ts +1 -0
- package/src/services/checkout-refresh.test-fixture.ts +3 -2
- package/src/services/command-host.ts +7 -2
- package/src/services/coordinator-digest.ts +3 -2
- package/src/services/dispatch-command.ts +12 -13
- package/src/services/effective-launch-driver.ts +14 -9
- package/src/services/host-changed-paths.test-fixture.ts +5 -6
- package/src/services/host-project-readiness.ts +2 -2
- package/src/services/host-providers.ts +1 -1
- package/src/services/host-utilization.ts +27 -4
- package/src/services/idle-agent-digest.ts +17 -12
- package/src/services/idle-epics.ts +9 -10
- package/src/services/interrupt-agent.ts +12 -9
- package/src/services/issue-activity.ts +3 -3
- package/src/services/issue-associations.ts +15 -18
- package/src/services/issue-lifecycle-comments.ts +3 -2
- package/src/services/issue-lifecycle.ts +69 -72
- package/src/services/issue-refs.ts +10 -15
- package/src/services/kernel-timers-cutover-chaos-worker.ts +11 -8
- package/src/services/kernel-timers-ingress-chaos-worker.ts +6 -1
- package/src/services/kernel-timers-ingress.ts +4 -4
- package/src/services/kernel-timers-message-authority-chaos-worker.ts +3 -10
- package/src/services/kernel-timers-operator-chaos-worker.ts +3 -2
- package/src/services/kernel-timers-outbox.ts +1 -1
- package/src/services/kernel-timers-stage10-operator.ts +1 -1
- package/src/services/kernel-timers.ts +4 -3
- package/src/services/land-gate-placement.ts +11 -2
- package/src/services/land-issue-relations.ts +5 -4
- package/src/services/land-restart-retry.ts +7 -6
- package/src/services/landed-ancestry.ts +25 -8
- package/src/services/legacy-landing-host.ts +4 -1
- package/src/services/legacy-landing-recovery.ts +8 -6
- package/src/services/managed-running.ts +17 -17
- package/src/services/memory-areas.ts +17 -53
- package/src/services/merge-pause.ts +9 -15
- package/src/services/operator-decisions.ts +37 -41
- package/src/services/orchestrator-registration-recovery.ts +6 -2
- package/src/services/orchestrator-upgrade.ts +14 -12
- package/src/services/permission-decision.ts +4 -3
- package/src/services/plan-ci-notice.ts +57 -0
- package/src/services/plan-ci-recovery.ts +2 -55
- package/src/services/plan-conformance.ts +4 -4
- package/src/services/plan-dispatch-policy.ts +10 -3
- package/src/services/plan-dispatch.ts +35 -14
- package/src/services/plan-graph.ts +39 -261
- package/src/services/plan-import.ts +1 -1
- package/src/services/plan-live-bindings.ts +8 -37
- package/src/services/plan-task-create.ts +1 -1
- package/src/services/plan-terminal-refs.ts +2 -12
- package/src/services/plan-wake-digest.ts +9 -3
- package/src/services/profile-trust.ts +6 -5
- package/src/services/project-config-read.ts +70 -0
- package/src/services/project-profile-instructions.ts +54 -0
- package/src/services/project.ts +11 -10
- package/src/services/prompt-templates.ts +6 -5
- package/src/services/provider-hold-nudge.ts +9 -9
- package/src/services/provider-hold-record.ts +13 -12
- package/src/services/provider-state-audit.ts +19 -18
- package/src/services/provisioning-harness/budget-baseline.json +4 -4
- package/src/services/provisioning-harness/driver.ts +1 -1
- package/src/services/provisioning-harness/fixture-matrix.ts +3 -3
- package/src/services/provisioning-harness/lifecycle.ts +24 -22
- package/src/services/provisioning-harness/prepare.ts +16 -17
- package/src/services/rate-limit-resume.ts +10 -9
- package/src/services/red-main-auto-revert.ts +7 -5
- package/src/services/red-main-controller-deps.ts +20 -3
- package/src/services/red-main-incident.ts +3 -1
- package/src/services/red-main-quarantine.ts +2 -3
- package/src/services/register-agent.ts +22 -22
- package/src/services/restart-project-role.ts +1 -1
- package/src/services/restart-spawn.ts +74 -61
- package/src/services/review-publish.ts +7 -24
- package/src/services/review-ref-reconcile.ts +29 -38
- package/src/services/runtime-dependency-alert.ts +27 -0
- package/src/services/scheduler-command.ts +11 -9
- package/src/services/scheduler.ts +5 -5
- package/src/services/self-care-state.ts +2 -1
- package/src/services/self-effort-grant.ts +5 -25
- package/src/services/self-effort.ts +5 -5
- package/src/services/send-message.ts +21 -34
- package/src/services/shutdown-agent.ts +17 -14
- package/src/services/spawn-agent.ts +25 -43
- package/src/services/spawn-chain-inspector.ts +7 -14
- package/src/services/spawn-cwd-placement.ts +21 -5
- package/src/services/spawn-issue-activity.ts +8 -6
- package/src/services/spawn-launch.ts +17 -1
- package/src/services/spawn-loss-escalation.ts +1 -1
- package/src/services/spawn-policy.ts +68 -0
- package/src/services/spawn-registration-watchdog.ts +2 -2
- package/src/services/spawn-repo-probe.ts +7 -5
- package/src/services/spawn-tree-cleanup.ts +8 -9
- package/src/services/steward-reaper.ts +4 -4
- package/src/services/task-context-hydration.ts +25 -1
- package/src/services/task-delivery.ts +20 -34
- package/src/services/task-dispatch.ts +3 -0
- package/src/services/task-entity.ts +40 -203
- package/src/services/task-issue-link.ts +13 -20
- package/src/services/task-issue-weave.ts +12 -11
- package/src/services/task-lifecycle.ts +27 -31
- package/src/services/task-repo-cwd.ts +37 -0
- package/src/services/task-review-hold.ts +4 -17
- package/src/services/task-semantic-events.ts +13 -11
- package/src/services/task-state-reconcile.ts +8 -17
- package/src/services/task-validation.ts +2 -2
- package/src/services/team-templates.ts +12 -11
- package/src/services/team.ts +31 -98
- package/src/services/terminal-provider-exit.ts +6 -5
- package/src/services/timer-message-fire-chaos-worker.ts +7 -3
- package/src/services/timer-message-fire-outbox.ts +1 -1
- package/src/services/transient-agent-reaper.ts +25 -20
- package/src/services/turn-reconcile-audit.ts +9 -9
- package/src/services/user-onboarding.ts +8 -6
- package/src/services/user-profile.ts +6 -9
- package/src/services/work-finality.ts +16 -4
- package/src/services/workflow-auto-start.ts +26 -13
- package/src/services/workflow-caller.ts +61 -4
- package/src/services/workflow-child-proof-worker.ts +1 -1
- package/src/services/workflow-ci-main.ts +1 -1
- package/src/services/workflow-control-proof-worker.ts +1 -1
- package/src/services/workflow-coordinator.ts +8 -2
- package/src/services/workflow-decisions.ts +5 -5
- package/src/services/workflow-deferred-cleanup.ts +5 -3
- package/src/services/workflow-effect-driver.ts +42 -17
- package/src/services/workflow-effects.ts +58 -37
- package/src/services/workflow-land-notice.ts +10 -0
- package/src/services/workflow-pause-text.ts +43 -0
- package/src/services/workflow-pins.ts +7 -4
- package/src/services/workflow-reconcile.ts +14 -11
- package/src/services/workflow-resume-pins.ts +3 -3
- package/src/services/workflow-routing-defaults.ts +18 -0
- package/src/services/workflow-run-view.ts +6 -3
- package/src/services/workflow-run.test-fixture.ts +1 -1
- package/src/services/workflow-runs.ts +61 -33
- package/src/services/workflow-supervisor-state.ts +26 -1
- package/src/services/workflow-supervisor.ts +11 -6
- package/src/services/workspace-recovery.ts +4 -3
- package/src/settings/registry.ts +1 -2
- package/src/spawn-admission.ts +10 -2
- package/src/spawn-command.ts +4 -4
- package/src/spawn-models.ts +10 -12
- package/src/spawn-placement.ts +28 -10
- package/src/spawn-targets.ts +9 -9
- package/src/sse-agent-status.ts +15 -6
- package/src/sse.ts +49 -24
- package/src/startup-context-injection.ts +62 -57
- package/src/state-adoption/cd-cutover.ts +53 -7
- package/src/state-adoption/fleet-cutover.ts +35 -0
- package/src/state-adoption/fleet-plan.ts +36 -0
- package/src/state-adoption/index.ts +2 -2
- package/src/state-adoption/linux-plan.ts +2 -2
- package/src/state-adoption/linux.ts +2 -2
- package/src/state-adoption/macos-plan.ts +2 -2
- package/src/state-adoption/macos.ts +1 -1
- package/src/steward-handoff.ts +4 -3
- package/src/steward-policy-cleanup.ts +9 -8
- package/src/steward.ts +9 -8
- package/src/task-dispatch-live.ts +6 -3
- package/src/task-dispatcher.ts +3 -3
- package/src/teams-config-store.ts +4 -3
- package/src/token-db-write.ts +10 -0
- package/src/token-db.ts +2 -2
- package/src/token-usage-async.ts +2 -4
- package/src/user-awaiting-reply.ts +5 -5
- package/src/workspace-actions.ts +24 -29
- package/src/workspace-auto-merge.ts +14 -12
- package/src/workspace-changed-paths-client.ts +16 -5
- package/src/workspace-cleanup-stale.ts +30 -7
- package/src/workspace-command-settle.ts +26 -17
- package/src/workspace-config.ts +1 -1
- package/src/workspace-conflict-resolver.ts +9 -7
- package/src/workspace-dead-owner-recovery.ts +5 -4
- package/src/workspace-escalation.ts +12 -11
- package/src/workspace-human-escalation.ts +3 -3
- package/src/workspace-land-gate-watchdog.ts +3 -3
- package/src/workspace-land-refusal.ts +20 -0
- package/src/workspace-land-stopped.ts +1 -0
- package/src/workspace-merge.ts +10 -26
- package/src/workspace-nothing-to-land-notice.ts +2 -2
- package/src/workspace-orphans.ts +18 -37
- package/src/workspace-pr-completion.ts +10 -8
- package/src/workspace-rekey.ts +3 -3
- package/src/workspace-steward-failure.ts +2 -2
- package/src/workspace-steward-wake.ts +4 -4
- package/node_modules/@humwick/kernel/LICENSE +0 -167
- package/node_modules/@humwick/kernel/async-entity-persistence.ts +0 -344
- package/node_modules/@humwick/kernel/async-event-log.ts +0 -107
- package/node_modules/@humwick/kernel/automations.pilot.ts +0 -147
- package/node_modules/@humwick/kernel/config.ts +0 -111
- package/node_modules/@humwick/kernel/contract.ts +0 -572
- package/node_modules/@humwick/kernel/control-authz.ts +0 -281
- package/node_modules/@humwick/kernel/control.ts +0 -645
- package/node_modules/@humwick/kernel/effects.ts +0 -493
- package/node_modules/@humwick/kernel/event-log.ts +0 -319
- package/node_modules/@humwick/kernel/http-transport.ts +0 -384
- package/node_modules/@humwick/kernel/identity-grammar.ts +0 -20
- package/node_modules/@humwick/kernel/identity.ts +0 -248
- package/node_modules/@humwick/kernel/index.ts +0 -28
- package/node_modules/@humwick/kernel/kernel-persistence.ts +0 -181
- package/node_modules/@humwick/kernel/landing-incident.ts +0 -306
- package/node_modules/@humwick/kernel/landing.ts +0 -953
- package/node_modules/@humwick/kernel/manifest-validation.ts +0 -460
- package/node_modules/@humwick/kernel/mcp-transport.ts +0 -109
- package/node_modules/@humwick/kernel/message-authority-chaos-worker.ts +0 -200
- package/node_modules/@humwick/kernel/message-authority.ts +0 -281
- package/node_modules/@humwick/kernel/module-host.ts +0 -722
- package/node_modules/@humwick/kernel/openapi-init.ts +0 -14
- package/node_modules/@humwick/kernel/package.json +0 -39
- package/node_modules/@humwick/kernel/persistence-schema.ts +0 -248
- package/node_modules/@humwick/kernel/persistence.ts +0 -510
- package/node_modules/@humwick/kernel/registry.ts +0 -60
- package/node_modules/@humwick/kernel/sqlite-kernel-persistence.ts +0 -499
- package/node_modules/@humwick/kernel/sqlite-module-host.ts +0 -87
- package/node_modules/@humwick/kernel/timers-chaos-worker.ts +0 -186
- package/node_modules/@humwick/kernel/timers.pilot.ts +0 -1411
- package/node_modules/@humwick/kernel/workflow-activation.ts +0 -25
- package/node_modules/@humwick/kernel/workflow-backstop.ts +0 -40
- package/node_modules/@humwick/kernel/workflow-cancel-tree.ts +0 -20
- package/node_modules/@humwick/kernel/workflow-chaos-worker.ts +0 -213
- package/node_modules/@humwick/kernel/workflow-composition.ts +0 -231
- package/node_modules/@humwick/kernel/workflow-container.ts +0 -72
- package/node_modules/@humwick/kernel/workflow-control.test-fixture.ts +0 -42
- package/node_modules/@humwick/kernel/workflow-control.ts +0 -178
- package/node_modules/@humwick/kernel/workflow-definition.ts +0 -507
- package/node_modules/@humwick/kernel/workflow-dispatch.ts +0 -60
- package/node_modules/@humwick/kernel/workflow-foreach.ts +0 -167
- package/node_modules/@humwick/kernel/workflow-journal-codec.ts +0 -339
- package/node_modules/@humwick/kernel/workflow-journal.ts +0 -922
- package/node_modules/@humwick/kernel/workflow-lane.ts +0 -48
- package/node_modules/@humwick/kernel/workflow-lease-owner.ts +0 -60
- package/node_modules/@humwick/kernel/workflow-recovery.test-fixture.ts +0 -19
- package/node_modules/@humwick/kernel/workflow-runtime.ts +0 -938
- package/node_modules/@humwick/kernel/workflow-script.ts +0 -11
- package/node_modules/@humwick/kernel/workflow-state.ts +0 -299
- package/node_modules/@humwick/kernel/workflow-step-commit.ts +0 -195
- package/node_modules/@humwick/kernel/workflow-transitions.ts +0 -317
- package/node_modules/@humwick/kernel/workflow-values.ts +0 -153
- package/node_modules/@humwick/kernel/workflow.pilot.ts +0 -376
- package/node_modules/@humwick/offload/LICENSE +0 -167
- package/node_modules/@humwick/offload/README.md +0 -57
- package/node_modules/@humwick/offload/dist/async-runner.d.ts +0 -18
- package/node_modules/@humwick/offload/dist/async-runner.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/async-runner.js +0 -158
- package/node_modules/@humwick/offload/dist/async-runner.js.map +0 -1
- package/node_modules/@humwick/offload/dist/envelope.d.ts +0 -25
- package/node_modules/@humwick/offload/dist/envelope.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/envelope.js +0 -80
- package/node_modules/@humwick/offload/dist/envelope.js.map +0 -1
- package/node_modules/@humwick/offload/dist/fixtures/worker-task.d.ts +0 -10
- package/node_modules/@humwick/offload/dist/fixtures/worker-task.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/fixtures/worker-task.js +0 -59
- package/node_modules/@humwick/offload/dist/fixtures/worker-task.js.map +0 -1
- package/node_modules/@humwick/offload/dist/index.d.ts +0 -5
- package/node_modules/@humwick/offload/dist/index.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/index.js +0 -5
- package/node_modules/@humwick/offload/dist/index.js.map +0 -1
- package/node_modules/@humwick/offload/dist/subprocess-runner.d.ts +0 -62
- package/node_modules/@humwick/offload/dist/subprocess-runner.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/subprocess-runner.js +0 -295
- package/node_modules/@humwick/offload/dist/subprocess-runner.js.map +0 -1
- package/node_modules/@humwick/offload/dist/types.d.ts +0 -111
- package/node_modules/@humwick/offload/dist/types.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/types.js +0 -176
- package/node_modules/@humwick/offload/dist/types.js.map +0 -1
- package/node_modules/@humwick/offload/dist/worker-pool.d.ts +0 -23
- package/node_modules/@humwick/offload/dist/worker-pool.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/worker-pool.js +0 -435
- package/node_modules/@humwick/offload/dist/worker-pool.js.map +0 -1
- package/node_modules/@humwick/offload/dist/worker-runtime.d.ts +0 -2
- package/node_modules/@humwick/offload/dist/worker-runtime.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/worker-runtime.js +0 -27
- package/node_modules/@humwick/offload/dist/worker-runtime.js.map +0 -1
- package/node_modules/@humwick/offload/dist/worker.d.ts +0 -5
- package/node_modules/@humwick/offload/dist/worker.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/worker.js +0 -1
- package/node_modules/@humwick/offload/dist/worker.js.map +0 -1
- package/node_modules/@humwick/offload/package.json +0 -42
- package/node_modules/@humwick/offload/src/async-runner.ts +0 -170
- package/node_modules/@humwick/offload/src/envelope.ts +0 -92
- package/node_modules/@humwick/offload/src/fixtures/worker-task.ts +0 -49
- package/node_modules/@humwick/offload/src/index.ts +0 -4
- package/node_modules/@humwick/offload/src/subprocess-runner.ts +0 -334
- package/node_modules/@humwick/offload/src/types.ts +0 -235
- package/node_modules/@humwick/offload/src/worker-pool.ts +0 -463
- package/node_modules/@humwick/offload/src/worker-runtime.ts +0 -32
- package/node_modules/@humwick/offload/src/worker.ts +0 -5
- package/public/assets/agent-liveness-DyqxfB-t.js +0 -2
- package/public/assets/agent-profiles-BpI_jTxq.js +0 -2
- package/public/assets/index-B7ZerHLY.css +0 -2
- package/public/assets/index-BU3uWo2t.js +0 -15
- package/public/assets/projects-B_lmcqfO.js +0 -2
- package/public/assets/provider-display-DbLWpP3j.js +0 -2
- package/public/assets/run-card-CO_bguQf.js +0 -2
- package/public/assets/shipping-Bu8p1gEw.js +0 -2
- package/public/assets/store-BvtFdlGX.js +0 -9
- package/public/assets/use-project-list-B-T2Bnnn.js +0 -2
- package/public/assets/versioned-prompt-editor-Diu8BIaM.js +0 -8
- package/runner/src/agent-runner/http-liveness.ts +0 -85
- package/runner/src/gate-run-lease-probe.ts +0 -38
- package/src/db/claude-catalog-reconcile.ts +0 -27
- package/src/db/on-loop-write-transaction.ts +0 -34
- package/src/routing-model-aliases.ts +0 -21
package/src/routes/users.ts
CHANGED
|
@@ -60,14 +60,14 @@ export const getMe: Handler = (req) => {
|
|
|
60
60
|
return user ? json({ ...user, hasPassword: hasPasswordLogin(user.id) } satisfies CurrentUser) : error("user not found", 404);
|
|
61
61
|
};
|
|
62
62
|
|
|
63
|
-
export const patchMe: Handler = (req) => patchUserProfile(req, { id: requestUserId(req) });
|
|
63
|
+
export const patchMe: Handler = async (req) => (await patchUserProfile(req, { id: requestUserId(req) }));
|
|
64
64
|
|
|
65
|
-
export const patchUserById: Handler = (req, params) => patchUserProfile(req, params);
|
|
65
|
+
export const patchUserById: Handler = async (req, params) => (await patchUserProfile(req, params));
|
|
66
66
|
|
|
67
67
|
async function patchUserProfile(req: Request, params: Record<string, string>): Promise<Response> {
|
|
68
68
|
try {
|
|
69
69
|
const userId = userIdParam(req, params);
|
|
70
|
-
if (!canManageUser(req, userId)) return authorityDenied(req, "forbidden");
|
|
70
|
+
if (!canManageUser(req, userId)) return (await authorityDenied(req, "forbidden"));
|
|
71
71
|
const parsed = await parseBody<unknown>(req);
|
|
72
72
|
if (!parsed.ok) return error(parsed.error, parsed.status);
|
|
73
73
|
if (!isRecord(parsed.body)) return error("body must be an object");
|
|
@@ -76,14 +76,14 @@ async function patchUserProfile(req: Request, params: Record<string, string>): P
|
|
|
76
76
|
const role = optionalEnum(body.role, "role", INVITE_ROLES);
|
|
77
77
|
const status = optionalEnum(body.status, "status", ACCOUNT_STATUSES);
|
|
78
78
|
if (role || status) {
|
|
79
|
-
if (!isAdminRequest(req)) return authorityDenied(req, "only an admin can change a user's role or status");
|
|
79
|
+
if (!isAdminRequest(req)) return (await authorityDenied(req, "only an admin can change a user's role or status"));
|
|
80
80
|
const before = getUser(userId);
|
|
81
81
|
const after = await changeUserAccess({ actorUserId: requestUserId(req), userId, role, status });
|
|
82
|
-
if (before && after.role !== before.role) recordUserManagement(req, userId, "change role", { from: before.role, to: after.role });
|
|
83
|
-
if (before && after.status !== before.status) recordUserManagement(req, userId, after.status === "suspended" ? "suspend" : "reactivate");
|
|
82
|
+
if (before && after.role !== before.role) (await recordUserManagement(req, userId, "change role", { from: before.role, to: after.role }));
|
|
83
|
+
if (before && after.status !== before.status) (await recordUserManagement(req, userId, after.status === "suspended" ? "suspend" : "reactivate"));
|
|
84
84
|
}
|
|
85
85
|
const displayName = cleanString(body.displayName, "displayName", { required: !role && !status, max: 120 });
|
|
86
|
-
if (displayName) return json(updateUserDisplayName({ userId, displayName }));
|
|
86
|
+
if (displayName) return json((await updateUserDisplayName({ userId, displayName })));
|
|
87
87
|
const user = userOr404(userId);
|
|
88
88
|
return user instanceof Response ? user : json(user);
|
|
89
89
|
} catch (e) {
|
|
@@ -91,9 +91,9 @@ async function patchUserProfile(req: Request, params: Record<string, string>): P
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
export const postMyAvatar: Handler = (req) => postUserAvatar(req, { id: requestUserId(req) });
|
|
94
|
+
export const postMyAvatar: Handler = async (req) => (await postUserAvatar(req, { id: requestUserId(req) }));
|
|
95
95
|
|
|
96
|
-
export const postUserAvatarById: Handler = (req, params) => postUserAvatar(req, params);
|
|
96
|
+
export const postUserAvatarById: Handler = async (req, params) => (await postUserAvatar(req, params));
|
|
97
97
|
|
|
98
98
|
async function avatarUploadInput(req: Request): Promise<{ bytes: Uint8Array; filename?: string; mediaType: string; digest?: string }> {
|
|
99
99
|
const contentType = req.headers.get("content-type") ?? "";
|
|
@@ -123,7 +123,7 @@ async function postUserAvatar(req: Request, params: Record<string, string>): Pro
|
|
|
123
123
|
const userId = userIdParam(req, params);
|
|
124
124
|
const user = userOr404(userId);
|
|
125
125
|
if (user instanceof Response) return user;
|
|
126
|
-
if (!canManageUser(req, userId)) return authorityDenied(req, "forbidden");
|
|
126
|
+
if (!canManageUser(req, userId)) return (await authorityDenied(req, "forbidden"));
|
|
127
127
|
const input = await avatarUploadInput(req);
|
|
128
128
|
const result = await storeUserAvatar({ userId, actor: requestUserAddress(req), ...input });
|
|
129
129
|
return json(result, 201);
|
|
@@ -132,25 +132,25 @@ async function postUserAvatar(req: Request, params: Record<string, string>): Pro
|
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
-
export const deleteMyAvatar: Handler = (req) => deleteUserAvatar(req, { id: requestUserId(req) });
|
|
135
|
+
export const deleteMyAvatar: Handler = async (req) => (await deleteUserAvatar(req, { id: requestUserId(req) }));
|
|
136
136
|
|
|
137
|
-
export const deleteUserAvatarById: Handler = (req, params) => deleteUserAvatar(req, params);
|
|
137
|
+
export const deleteUserAvatarById: Handler = async (req, params) => (await deleteUserAvatar(req, params));
|
|
138
138
|
|
|
139
139
|
async function deleteUserAvatar(req: Request, params: Record<string, string>): Promise<Response> {
|
|
140
140
|
try {
|
|
141
141
|
const userId = userIdParam(req, params);
|
|
142
142
|
const user = userOr404(userId);
|
|
143
143
|
if (user instanceof Response) return user;
|
|
144
|
-
if (!canManageUser(req, userId)) return authorityDenied(req, "forbidden");
|
|
144
|
+
if (!canManageUser(req, userId)) return (await authorityDenied(req, "forbidden"));
|
|
145
145
|
return json(await removeUserAvatar({ userId }));
|
|
146
146
|
} catch (e) {
|
|
147
147
|
return profileError(e);
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
-
export const getUserAvatar: Handler = (req, params) => serveUserAvatar(req, params, false);
|
|
151
|
+
export const getUserAvatar: Handler = async (req, params) => (await serveUserAvatar(req, params, false));
|
|
152
152
|
|
|
153
|
-
export const headUserAvatar: Handler = (req, params) => serveUserAvatar(req, params, true);
|
|
153
|
+
export const headUserAvatar: Handler = async (req, params) => (await serveUserAvatar(req, params, true));
|
|
154
154
|
|
|
155
155
|
async function serveUserAvatar(req: Request, params: Record<string, string>, head: boolean): Promise<Response> {
|
|
156
156
|
const userId = userIdParam(req, params);
|
|
@@ -158,7 +158,7 @@ async function serveUserAvatar(req: Request, params: Record<string, string>, hea
|
|
|
158
158
|
if (!user?.avatarArtifactId) return error("avatar not found", 404);
|
|
159
159
|
const artifact = await getArtifactAsync(user.avatarArtifactId);
|
|
160
160
|
if (!artifact) return error("avatar artifact not found", 404);
|
|
161
|
-
if (!canReadAvatar(req, userId, artifact)) return authorityDenied(req, "forbidden");
|
|
161
|
+
if (!canReadAvatar(req, userId, artifact)) return (await authorityDenied(req, "forbidden"));
|
|
162
162
|
const blob = await getArtifactBlobAsync(artifact.blobDigest);
|
|
163
163
|
if (!blob) return error("avatar blob not found", 404);
|
|
164
164
|
const headers = {
|
|
@@ -183,15 +183,15 @@ export const invitesDisabled = () => error("user invites are disabled", 404);
|
|
|
183
183
|
/** POST /api/users/invites — admin only. The code is shown once; share `/invite/<code>` by hand. */
|
|
184
184
|
export const postUserInvite: Handler = async (req) => {
|
|
185
185
|
if (!userInvitesEnabled()) return invitesDisabled();
|
|
186
|
-
if (!isAdminRequest(req)) return authorityDenied(req, "only an admin can invite users");
|
|
186
|
+
if (!isAdminRequest(req)) return (await authorityDenied(req, "only an admin can invite users"));
|
|
187
187
|
const parsed = await parseBody<unknown>(req);
|
|
188
188
|
if (!parsed.ok) return error(parsed.error, parsed.status);
|
|
189
189
|
const body = isRecord(parsed.body) ? parsed.body : {};
|
|
190
190
|
try {
|
|
191
191
|
const role = optionalEnum(body.role, "role", INVITE_ROLES) ?? "operator";
|
|
192
192
|
const displayName = cleanString(body.displayName, "displayName", { max: 120 });
|
|
193
|
-
const { invite, code } = createInvite({ role, displayName, createdBy: requestUserId(req) });
|
|
194
|
-
recordUserManagement(req, `invite:${invite.id}`, "create invite", { role, ...(displayName ? { displayName } : {}) });
|
|
193
|
+
const { invite, code } = (await createInvite({ role, displayName, createdBy: requestUserId(req) }));
|
|
194
|
+
(await recordUserManagement(req, `invite:${invite.id}`, "create invite", { role, ...(displayName ? { displayName } : {}) }));
|
|
195
195
|
return json({ invite, code, path: `/invite/${code}` }, 201);
|
|
196
196
|
} catch (e) {
|
|
197
197
|
if (e instanceof ValidationError) return error(e.message, 400);
|
|
@@ -202,7 +202,7 @@ export const postUserInvite: Handler = async (req) => {
|
|
|
202
202
|
/** PUT /api/users/me/password — a signed-in user, or the admin token for the default admin. */
|
|
203
203
|
export const putMyPassword: Handler = async (req) => {
|
|
204
204
|
const acting = resolveActingUser(req);
|
|
205
|
-
if (!acting) return authorityDenied(req, "sign in to set a password");
|
|
205
|
+
if (!acting) return (await authorityDenied(req, "sign in to set a password"));
|
|
206
206
|
const parsed = await parseBody<unknown>(req);
|
|
207
207
|
if (!parsed.ok) return error(parsed.error, parsed.status);
|
|
208
208
|
if (!isRecord(parsed.body)) return error("password required");
|
|
@@ -219,11 +219,11 @@ export const putMyPassword: Handler = async (req) => {
|
|
|
219
219
|
|
|
220
220
|
/** DELETE /api/users/:id/sessions — sign the user out everywhere; their next call gets 401. */
|
|
221
221
|
export const deleteUserSessions: Handler = async (req, params) => {
|
|
222
|
-
if (!isAdminRequest(req)) return authorityDenied(req, "only an admin can sign a user out");
|
|
222
|
+
if (!isAdminRequest(req)) return (await authorityDenied(req, "only an admin can sign a user out"));
|
|
223
223
|
try {
|
|
224
224
|
const userId = decodeURIComponent(params.id!);
|
|
225
225
|
const revoked = await revokeUserSessions(userId);
|
|
226
|
-
recordUserManagement(req, userId, "revoke sessions", { revoked });
|
|
226
|
+
(await recordUserManagement(req, userId, "revoke sessions", { revoked }));
|
|
227
227
|
return json({ revoked });
|
|
228
228
|
} catch (e) {
|
|
229
229
|
return profileError(e);
|
|
@@ -232,7 +232,7 @@ export const deleteUserSessions: Handler = async (req, params) => {
|
|
|
232
232
|
|
|
233
233
|
/** POST /api/users/:id/handover — every agent of the user gets `toUserId` as its principal. */
|
|
234
234
|
export const postUserHandover: Handler = async (req, params) => {
|
|
235
|
-
if (!isAdminRequest(req)) return authorityDenied(req, "only an admin can hand over agents");
|
|
235
|
+
if (!isAdminRequest(req)) return (await authorityDenied(req, "only an admin can hand over agents"));
|
|
236
236
|
try {
|
|
237
237
|
const parsed = await parseBody<unknown>(req);
|
|
238
238
|
if (!parsed.ok) return error(parsed.error, parsed.status);
|
|
@@ -240,7 +240,7 @@ export const postUserHandover: Handler = async (req, params) => {
|
|
|
240
240
|
const toUserId = cleanString(body.toUserId, "toUserId", { required: true, max: 64 })!;
|
|
241
241
|
const fromUserId = decodeURIComponent(params.id!);
|
|
242
242
|
const agentIds = await handOverAgents({ fromUserId, toUserId });
|
|
243
|
-
recordUserManagement(req, fromUserId, "hand over agents", { toUserId, agentIds });
|
|
243
|
+
(await recordUserManagement(req, fromUserId, "hand over agents", { toUserId, agentIds }));
|
|
244
244
|
return json({ toUserId, agentIds });
|
|
245
245
|
} catch (e) {
|
|
246
246
|
return profileError(e);
|
|
@@ -12,15 +12,15 @@ export function scopeResourceReads(method: string, path: string, handler: Handle
|
|
|
12
12
|
const viewer = viewerScopeForRequest(req);
|
|
13
13
|
if (!viewer || viewer.seesAll) return handler(req, params);
|
|
14
14
|
const id = params.id!;
|
|
15
|
-
if (resource === "agents" && !agentVisibleTo(viewer, id)) return authorityDenied(req, "agent not found", 404, id, "read agent");
|
|
15
|
+
if (resource === "agents" && !agentVisibleTo(viewer, id)) return (await authorityDenied(req, "agent not found", 404, id, "read agent"));
|
|
16
16
|
if (resource === "tasks") {
|
|
17
17
|
const taskId = parseId(id);
|
|
18
|
-
if (taskId !== null && !taskVisibleTo(viewer, { id: taskId })) return authorityDenied(req, "task not found", 404, id, "read task");
|
|
18
|
+
if (taskId !== null && !taskVisibleTo(viewer, { id: taskId })) return (await authorityDenied(req, "task not found", 404, id, "read task"));
|
|
19
19
|
}
|
|
20
20
|
if (resource === "messages") {
|
|
21
21
|
const messageId = parseId(id);
|
|
22
22
|
const message = messageId === null ? null : await getMessageAsync(messageId);
|
|
23
|
-
if (message && !messageVisibleTo(viewer, message)) return authorityDenied(req, "you can only read your own messages", 403, id, path.endsWith("/thread") ? "read thread" : "read message");
|
|
23
|
+
if (message && !messageVisibleTo(viewer, message)) return (await authorityDenied(req, "you can only read your own messages", 403, id, path.endsWith("/thread") ? "read thread" : "read message"));
|
|
24
24
|
}
|
|
25
25
|
return handler(req, params);
|
|
26
26
|
};
|
|
@@ -5,27 +5,27 @@ import { ingestWebToolCall, queryWebSearchBudget, queryWebToolCalls, queryWebToo
|
|
|
5
5
|
import { authorizeRoute, error, json, parseBody, type Handler } from "./_shared";
|
|
6
6
|
|
|
7
7
|
export const getWebToolCalls: Handler = async req => {
|
|
8
|
-
const denied = authorizeRoute(req, { scope: "agent:read" });
|
|
8
|
+
const denied = (await authorizeRoute(req, { scope: "agent:read" }));
|
|
9
9
|
if (denied) return denied;
|
|
10
10
|
try { return json(await queryWebToolCalls(Object.fromEntries(new URL(req.url).searchParams))); }
|
|
11
11
|
catch (e) { if (e instanceof ValidationError) return error(e.message, 400); throw e; }
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
export const getWebToolCallSummary: Handler = async req => {
|
|
15
|
-
const denied = authorizeRoute(req, { scope: "agent:read" });
|
|
15
|
+
const denied = (await authorizeRoute(req, { scope: "agent:read" }));
|
|
16
16
|
if (denied) return denied;
|
|
17
17
|
try { return json(await queryWebToolCallSummary(Object.fromEntries(new URL(req.url).searchParams))); }
|
|
18
18
|
catch (e) { if (e instanceof ValidationError) return error(e.message, 400); throw e; }
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
export const getWebSearchBudget: Handler = async req => {
|
|
22
|
-
const denied = authorizeRoute(req, { scope: "agent:read" });
|
|
22
|
+
const denied = (await authorizeRoute(req, { scope: "agent:read" }));
|
|
23
23
|
if (denied) return denied;
|
|
24
24
|
return json(await queryWebSearchBudget());
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
export const postWebToolCall: Handler = async req => {
|
|
28
|
-
const denied = authorizeRoute(req, { scope: "agent:write" });
|
|
28
|
+
const denied = (await authorizeRoute(req, { scope: "agent:write" }));
|
|
29
29
|
if (denied) return denied;
|
|
30
30
|
const body = await parseBody<unknown>(req);
|
|
31
31
|
if (!body.ok) return error(body.error, body.status);
|
package/src/routes/workflows.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { parseWorkflowDecisionResponse } from "../services/workflow-decisions";
|
|
2
2
|
// #3076 — the dashboard's workflow run reads: the run list (by status and project), one run, the stats
|
|
3
3
|
// window and the workflows that ran, all from the workflow run records relay_workflow_get reads, with its visibility rule.
|
|
4
|
-
// #3120 — the catalog. #3166 — cancel a run, as relay_workflow_cancel does.
|
|
4
|
+
// #3120 — the catalog. #3166 — cancel a run, as relay_workflow_cancel does. #3757 — pause and unpause one.
|
|
5
5
|
import { OpError } from "@humwick/kernel";
|
|
6
6
|
import { isRecord, WORKFLOW_STATS_WINDOWS, type WorkflowStatsWindow } from "@humwick/sdk";
|
|
7
7
|
import { resolveProjectAsync, ValidationError } from "../db";
|
|
@@ -9,8 +9,9 @@ import { McpNotFoundError } from "../mcp-errors";
|
|
|
9
9
|
import { authContextFromRequest } from "../services/auth-context";
|
|
10
10
|
import { ServiceAuthError } from "../services/errors";
|
|
11
11
|
import { readWorkflowCatalog } from "../services/workflow-catalog";
|
|
12
|
+
import { parseWorkflowPins } from "../services/workflow-pins";
|
|
12
13
|
import { requireSpawnBudget } from "../spawn-budget";
|
|
13
|
-
import { amendWorkflowRunBudget, cancelWorkflowRun, getWorkflowRun, readWorkflowRunBudget, listWorkflowRuns, resumeWorkflowRun, startWorkflowRun } from "../services/workflow-runs";
|
|
14
|
+
import { amendWorkflowRunBudget, cancelWorkflowRun, getWorkflowRun, pauseWorkflowRun, readWorkflowRunBudget, listWorkflowRuns, resumeWorkflowRun, startWorkflowRun } from "../services/workflow-runs";
|
|
14
15
|
import { workflowDefinitions, workflowStats } from "../services/workflow-stats";
|
|
15
16
|
import { cleanString, taskIdField } from "../validation";
|
|
16
17
|
import { error, json, parseBody, type Handler } from "./_shared";
|
|
@@ -83,7 +84,22 @@ export const postWorkflowRunCancelRoute: Handler = async (req, params) => {
|
|
|
83
84
|
}
|
|
84
85
|
};
|
|
85
86
|
|
|
86
|
-
|
|
87
|
+
/** #3757 — pause (a `reason` is required) or unpause a run, as relay_workflow_resume's `pause` does; the dashboard's buttons use these. */
|
|
88
|
+
function workflowRunPauseRoute(pause: boolean): Handler {
|
|
89
|
+
return async (req, params) => {
|
|
90
|
+
const parsed = await parseBody<unknown>(req);
|
|
91
|
+
if (!parsed.ok) return error(parsed.error, parsed.status);
|
|
92
|
+
if (parsed.body !== null && !isRecord(parsed.body)) return error("body must be a JSON object", 400);
|
|
93
|
+
try {
|
|
94
|
+
const reason = cleanString(parsed.body?.reason, "reason", { max: 2000 });
|
|
95
|
+
return json(await pauseWorkflowRun({ runId: params.runId!, pause, ...(reason ? { reason } : {}) }, authContextFromRequest(req)));
|
|
96
|
+
} catch (e) { return runRouteError(e); }
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
export const postWorkflowRunPauseRoute = workflowRunPauseRoute(true);
|
|
100
|
+
export const postWorkflowRunUnpauseRoute = workflowRunPauseRoute(false);
|
|
101
|
+
|
|
102
|
+
function runRouteError(e: unknown): Response {
|
|
87
103
|
if (e instanceof McpNotFoundError) return error(e.message, 404);
|
|
88
104
|
if (e instanceof ServiceAuthError) return error(e.message, 403);
|
|
89
105
|
if (e instanceof ValidationError) return error(e.message, 400);
|
|
@@ -91,7 +107,7 @@ function budgetRouteError(e: unknown): Response {
|
|
|
91
107
|
}
|
|
92
108
|
|
|
93
109
|
export const getWorkflowRunBudgetRoute: Handler = async (req, params) => {
|
|
94
|
-
try { return json(await readWorkflowRunBudget(params.runId!, authContextFromRequest(req))); } catch (e) { return
|
|
110
|
+
try { return json(await readWorkflowRunBudget(params.runId!, authContextFromRequest(req))); } catch (e) { return runRouteError(e); }
|
|
95
111
|
};
|
|
96
112
|
|
|
97
113
|
export const patchWorkflowRunBudgetRoute: Handler = async (req, params) => {
|
|
@@ -100,7 +116,7 @@ export const patchWorkflowRunBudgetRoute: Handler = async (req, params) => {
|
|
|
100
116
|
try {
|
|
101
117
|
const { tokenCap } = requireSpawnBudget(parsed.body);
|
|
102
118
|
return json(await amendWorkflowRunBudget({ runId: params.runId!, tokenCap }, authContextFromRequest(req)));
|
|
103
|
-
} catch (e) { return
|
|
119
|
+
} catch (e) { return runRouteError(e); }
|
|
104
120
|
};
|
|
105
121
|
|
|
106
122
|
export const postWorkflowRunResumeRoute: Handler = async (req, params) => {
|
|
@@ -108,7 +124,7 @@ export const postWorkflowRunResumeRoute: Handler = async (req, params) => {
|
|
|
108
124
|
if (!parsed.ok) return error(parsed.error, parsed.status);
|
|
109
125
|
if (!isRecord(parsed.body)) return error("body must be a JSON object", 400);
|
|
110
126
|
try {
|
|
111
|
-
return json(await resumeWorkflowRun({ runId: params.runId!, decision: parseWorkflowDecisionResponse(parsed.body.decision), activationId: cleanString(parsed.body.activationId, "activationId", { max: 2000 }), note: cleanString(parsed.body.note, "note", { max: 8000 }) }, authContextFromRequest(req)));
|
|
127
|
+
return json(await resumeWorkflowRun({ runId: params.runId!, pins: parseWorkflowPins(parsed.body.pins), step: cleanString(parsed.body.step, "step", { max: 64 }), decision: parseWorkflowDecisionResponse(parsed.body.decision), activationId: cleanString(parsed.body.activationId, "activationId", { max: 2000 }), note: cleanString(parsed.body.note, "note", { max: 8000 }) }, authContextFromRequest(req)));
|
|
112
128
|
} catch (e) {
|
|
113
129
|
if (e instanceof McpNotFoundError) return error(e.message, 404);
|
|
114
130
|
if (e instanceof ServiceAuthError) return error(e.message, 403);
|
|
@@ -131,7 +147,6 @@ export const postWorkflowRunStartRoute: Handler = async (req) => {
|
|
|
131
147
|
try {
|
|
132
148
|
const workflow = cleanString(parsed.body.workflow, "workflow", { max: 64 });
|
|
133
149
|
if (!workflow) throw new ValidationError("workflow is required");
|
|
134
|
-
const { parseWorkflowPins } = await import("../services/workflow-pins");
|
|
135
150
|
return json(await startWorkflowRun({ workflow, taskId: taskIdField(parsed.body.taskId), pins: parseWorkflowPins(parsed.body.pins), inputs: parsed.body.inputs as Record<string, unknown> | undefined, requestKey: cleanString(parsed.body.requestKey, "requestKey", { max: 200 }), budget: parsed.body.budget }, authContextFromRequest(req)), 202);
|
|
136
151
|
} catch (e) {
|
|
137
152
|
if (e instanceof ServiceAuthError) return error(e.message, 403);
|
package/src/routes/workspaces.ts
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
|
+
import { createCommandAsync } from "../commands-write";
|
|
2
|
+
import { deleteWorkspaceAsync } from "../db/lifecycle-tail-async";
|
|
1
3
|
// Auto-split from routes.ts (#299). Domain: workspaces.
|
|
2
4
|
import { RELAY_TOKEN_HEADER, isRecord } from "@humwick/sdk";
|
|
3
5
|
import { TERMINAL_WORKSPACE_STATUSES, describeWorkspacePhase, landReceipt } from "../workspace-phase";
|
|
4
6
|
import { VALID_WORKSPACE_STATUSES, cleanMeta, cleanString, optionalEnum } from "../validation";
|
|
5
|
-
import { ValidationError,
|
|
7
|
+
import { ValidationError, getAgent, getWorkspace, listMergeLeases, listOrchestrators, listRepoStewards, listWorkspaces, updateWorkspaceStatus, withResolvedWorkspaceProjectsAsync } from "../db";
|
|
6
8
|
import { recoverIsolatedWorkspace } from "../services/workspace-recovery";
|
|
7
9
|
import { WORKSPACE_ACTIONS, applyWorkspaceAction, waitForWorkspaceStatus } from "../workspace-actions";
|
|
8
10
|
import { buildWorkspaceCleanupCommand, cleanupStaleWorkspaces } from "../workspace-cleanup-stale";
|
|
9
11
|
import { auditEvent, authAuditMetadata, authorizeRoute, emitCommand, error, isRootCredentialRequest, json, parseBody, type Handler } from "./_shared";
|
|
10
12
|
import { collectWorkspaceOrphans } from "../workspace-orphans";
|
|
11
|
-
import {
|
|
12
|
-
import { LAND_STRATEGIES, isOwnerAlive, isOwnerProcessConfirmedGone, withOwnerOnline } from "../workspace-merge";
|
|
13
|
+
import { getCommand } from "../commands-db";
|
|
14
|
+
import { LAND_STRATEGIES, isOwnerAlive, isOwnerProcessConfirmedGone, withOwnerOnline, AUTO_MERGE_POLICIES } from "../workspace-merge";
|
|
13
15
|
import { isPathWithinBase } from "../utils";
|
|
14
16
|
import { resolve } from "node:path";
|
|
15
17
|
import { type WorkspaceAutoMergePolicy, type WorkspaceDiagnostics, type WorkspaceGitState, type WorkspaceLandGateLevel, type WorkspaceLandingPolicy, type WorkspaceMergeStrategy, type WorkspaceRecoveryBranch, type WorkspaceRecord, type WorkspaceStatus } from "../types";
|
|
16
|
-
import { AUTO_MERGE_POLICIES } from "../workspace-merge";
|
|
17
18
|
import { workspaceActiveClaim } from "../workspace-claim";
|
|
18
19
|
import { resolveCoordinatorAgentId } from "../steward-identity";
|
|
19
20
|
import { relayToken } from "../config";
|
|
@@ -231,7 +232,7 @@ export const getWorkspaceRecoveryBranches: Handler = async (req) => {
|
|
|
231
232
|
};
|
|
232
233
|
|
|
233
234
|
export const postWorkspaceRecoveryBranchDiscard: Handler = async (req) => {
|
|
234
|
-
const denied = authorizeRoute(req, { scope: "command:write" });
|
|
235
|
+
const denied = (await authorizeRoute(req, { scope: "command:write" }));
|
|
235
236
|
if (denied) return denied;
|
|
236
237
|
const parsed = await parseBody<unknown>(req);
|
|
237
238
|
if (!parsed.ok) return error(parsed.error, parsed.status);
|
|
@@ -256,13 +257,13 @@ export const postWorkspaceRecoveryBranchDiscard: Handler = async (req) => {
|
|
|
256
257
|
if (target.safeToDelete !== true && !force) {
|
|
257
258
|
return error(`branch holds work or cannot be proven safe (${target.preserveReason ?? `${target.unmergedAhead ?? target.ahead ?? "?"} unlanded commit(s)`}); land it first or pass force:true with reason to discard`, 409);
|
|
258
259
|
}
|
|
259
|
-
const command =
|
|
260
|
+
const command = (await createCommandAsync({
|
|
260
261
|
type: "workspace.recovery-branch-discard",
|
|
261
262
|
source: "system",
|
|
262
263
|
target: orch.agentId,
|
|
263
264
|
correlationId: branch,
|
|
264
265
|
params: { action: "recovery-branch-discard", repoRoot, branch, baseRef: baseRef ?? target.baseRef, baseSha: baseSha ?? target.baseSha, force, reason, requestedBy: "steward", requestedAt: Date.now() },
|
|
265
|
-
});
|
|
266
|
+
}));
|
|
266
267
|
emitCommand(command);
|
|
267
268
|
await auditEvent({
|
|
268
269
|
clientId: `workspace-recovery-branch-discard-${Date.now()}`,
|
|
@@ -282,7 +283,7 @@ export const postWorkspaceRecoveryBranchDiscard: Handler = async (req) => {
|
|
|
282
283
|
};
|
|
283
284
|
|
|
284
285
|
export const postWorkspaceOrphanReclaim: Handler = async (req) => {
|
|
285
|
-
const denied = authorizeRoute(req, { scope: "command:write" });
|
|
286
|
+
const denied = (await authorizeRoute(req, { scope: "command:write" }));
|
|
286
287
|
if (denied) return denied;
|
|
287
288
|
const parsed = await parseBody<unknown>(req);
|
|
288
289
|
if (!parsed.ok) return error(parsed.error, parsed.status);
|
|
@@ -306,12 +307,12 @@ export const postWorkspaceOrphanReclaim: Handler = async (req) => {
|
|
|
306
307
|
? listOrchestrators().find((candidate) => candidate.id === target.orchestratorId && candidate.status === "online")
|
|
307
308
|
: listOrchestrators().find((candidate) => candidate.status === "online" && isPathWithinBase(repoRoot, candidate.baseDir));
|
|
308
309
|
if (!orch) return error("no online orchestrator owns this path", 409);
|
|
309
|
-
const command =
|
|
310
|
+
const command = (await createCommandAsync({
|
|
310
311
|
type: "workspace.cleanup",
|
|
311
312
|
source: "system",
|
|
312
313
|
target: orch.agentId,
|
|
313
314
|
params: { action: "cleanup", worktreePath, repoRoot, branch, baseRef, baseSha, deleteBranch: true, reclaim: true, requestedBy: "dashboard", requestedAt: Date.now() },
|
|
314
|
-
});
|
|
315
|
+
}));
|
|
315
316
|
emitCommand(command);
|
|
316
317
|
await auditEvent({
|
|
317
318
|
clientId: `workspace-orphan-reclaim-${Date.now()}`,
|
|
@@ -443,7 +444,7 @@ export const getWorkspaceDiagnostics: Handler = async (_req, params) => {
|
|
|
443
444
|
};
|
|
444
445
|
|
|
445
446
|
export const postWorkspaceCleanupStale: Handler = async (req) => {
|
|
446
|
-
const denied = authorizeRoute(req, { scope: "command:write" });
|
|
447
|
+
const denied = (await authorizeRoute(req, { scope: "command:write" }));
|
|
447
448
|
if (denied) return denied;
|
|
448
449
|
const parsed = await parseBody<unknown>(req);
|
|
449
450
|
if (!parsed.ok) return error(parsed.error, parsed.status);
|
|
@@ -475,7 +476,7 @@ export const postWorkspaceAction: Handler = async (req, params) => {
|
|
|
475
476
|
// owner-merge cwd-authz short-circuit below, so a recovered row still runs the standard cwd check.
|
|
476
477
|
let freshlyRecovered = false;
|
|
477
478
|
if (!workspace) {
|
|
478
|
-
const recovery = recoverIsolatedWorkspace(authContextFromRequest(req), isRecord(parsed.body.workspace) ? parsed.body.workspace : undefined, params.id!);
|
|
479
|
+
const recovery = (await recoverIsolatedWorkspace(authContextFromRequest(req), isRecord(parsed.body.workspace) ? parsed.body.workspace : undefined, params.id!));
|
|
479
480
|
if (!recovery.ok) return error("workspace not found", 404);
|
|
480
481
|
workspace = recovery.workspace;
|
|
481
482
|
freshlyRecovered = recovery.created;
|
|
@@ -509,7 +510,7 @@ export const postWorkspaceAction: Handler = async (req, params) => {
|
|
|
509
510
|
// fuzzy label match (the 545ca290 impersonation hole); steward authz resolves the actual
|
|
510
511
|
// elected steward, not the null-prone `workspace.stewardAgentId` mirror.
|
|
511
512
|
const authorized = isWorkspaceRecoveryAuthorized(authCtx, workspace);
|
|
512
|
-
const denied = authorizeRoute(req, { scope: requiresCommand ? "command:write" : "agent:write" });
|
|
513
|
+
const denied = (await authorizeRoute(req, { scope: requiresCommand ? "command:write" : "agent:write" }));
|
|
513
514
|
if (denied) return denied;
|
|
514
515
|
if (!authorized) return error("forbidden", 403);
|
|
515
516
|
// A raw root credential or a VERIFIED component recovery principal (one of the four #1747
|
|
@@ -534,7 +535,7 @@ export const postWorkspaceAction: Handler = async (req, params) => {
|
|
|
534
535
|
hasComponentScope(component, "command:write");
|
|
535
536
|
if (!ownsMergeRequest && !isRecoveryAction) {
|
|
536
537
|
const authzCwd = freshlyRecovered ? workspace.sourceCwd : workspace.worktreePath;
|
|
537
|
-
const denied = authorizeRoute(req, { scope: requiresCommand ? "command:write" : "agent:write", resource: { agentId, cwd: authzCwd } });
|
|
538
|
+
const denied = (await authorizeRoute(req, { scope: requiresCommand ? "command:write" : "agent:write", resource: { agentId, cwd: authzCwd } }));
|
|
538
539
|
if (denied) return denied;
|
|
539
540
|
}
|
|
540
541
|
|
|
@@ -617,7 +618,7 @@ export const postWorkspaceAction: Handler = async (req, params) => {
|
|
|
617
618
|
};
|
|
618
619
|
|
|
619
620
|
export const deleteWorkspaceById: Handler = async (req, params) => {
|
|
620
|
-
const denied = authorizeRoute(req, { scope: "command:write" });
|
|
621
|
+
const denied = (await authorizeRoute(req, { scope: "command:write" }));
|
|
621
622
|
if (denied) return denied;
|
|
622
623
|
const workspace = getWorkspace(params.id!);
|
|
623
624
|
if (!workspace) return error("workspace not found", 404);
|
|
@@ -626,7 +627,7 @@ export const deleteWorkspaceById: Handler = async (req, params) => {
|
|
|
626
627
|
// outlives this row: once the workspace is gone the reconciler sees the ledger entry, treats the
|
|
627
628
|
// round as closed, and deletes each leaked ref by its OWN stored value with backoff until origin
|
|
628
629
|
// confirms. So a purge just drops the workspace row; the ledger owns cleanup.
|
|
629
|
-
const removed =
|
|
630
|
+
const removed = (await deleteWorkspaceAsync(workspace.id));
|
|
630
631
|
if (!removed) return error("workspace not found", 404);
|
|
631
632
|
await auditEvent({
|
|
632
633
|
clientId: `workspace-delete-${workspace.id}-${Date.now()}`,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { ValidationError } from "@humwick/sdk";
|
|
2
|
-
import { currentDispatchModels } from "./routing-model-aliases";
|
|
3
2
|
import { normalizeStepRoutingDefaults } from "./routing-step-defaults";
|
|
4
3
|
import {
|
|
5
4
|
isRecord,
|
|
@@ -199,7 +198,7 @@ export function normalizeDispatchPolicy(raw: unknown): DispatchPolicy {
|
|
|
199
198
|
*/
|
|
200
199
|
/** Pure projection used by reader-gateway callers that already captured the policy snapshot. */
|
|
201
200
|
export function dispatchPolicyFor(policy: RoutingPolicy): DispatchPolicy {
|
|
202
|
-
return policy.dispatch
|
|
201
|
+
return policy.dispatch ?? DEFAULT_DISPATCH_POLICY;
|
|
203
202
|
}
|
|
204
203
|
|
|
205
204
|
const MAX_RULES = 100;
|
|
@@ -5,7 +5,7 @@ import { emitRelayEvent } from "./events";
|
|
|
5
5
|
import { routeNotification } from "./notification-router";
|
|
6
6
|
import { renderTemplate } from "./prompt-resolver";
|
|
7
7
|
import { parseJson } from "./utils";
|
|
8
|
-
import { isRecord } from "@humwick/sdk";
|
|
8
|
+
import { fireAndForget, isRecord } from "@humwick/sdk";
|
|
9
9
|
import type { RoutingPolicy } from "@humwick/sdk";
|
|
10
10
|
|
|
11
11
|
const PUSH_TTL_MS = 15 * 60 * 1000;
|
|
@@ -33,16 +33,16 @@ export function notifyRoutingPolicyChanged(policy: RoutingPolicy, previous: Rout
|
|
|
33
33
|
if (pending) clearTimeout(pending.timer);
|
|
34
34
|
pending = {
|
|
35
35
|
db, previous: baseline, policy: structuredClone(policy), updatedBy: opts.updatedBy,
|
|
36
|
-
timer: setTimeout(() => {
|
|
36
|
+
timer: setTimeout(() => void fireAndForget("[routing-policy] FYI", async () => {
|
|
37
37
|
const settled = pending;
|
|
38
38
|
pending = undefined;
|
|
39
39
|
try {
|
|
40
40
|
if (!settled || settled.db !== getDb()) return;
|
|
41
|
-
pushSettledPolicy(settled.previous, settled.policy, settled.updatedBy);
|
|
41
|
+
await pushSettledPolicy(settled.previous, settled.policy, settled.updatedBy);
|
|
42
42
|
} catch (error) {
|
|
43
43
|
console.warn("Routing policy FYI failed:", error);
|
|
44
44
|
}
|
|
45
|
-
}, QUIET_WINDOW_MS),
|
|
45
|
+
}), QUIET_WINDOW_MS),
|
|
46
46
|
};
|
|
47
47
|
pending.timer.unref();
|
|
48
48
|
}
|
|
@@ -98,13 +98,13 @@ function ruleDelta(previous: unknown[], current: unknown[], path: string): strin
|
|
|
98
98
|
return delta;
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
function pushSettledPolicy(previous: RoutingPolicy, policy: RoutingPolicy, updatedBy?: string): void {
|
|
101
|
+
async function pushSettledPolicy(previous: RoutingPolicy, policy: RoutingPolicy, updatedBy?: string): Promise<void> {
|
|
102
102
|
const delta = policyDelta(previous, policy);
|
|
103
103
|
if (delta.length === 0) return;
|
|
104
104
|
const recipients = getSpawnCapableAgentIds();
|
|
105
105
|
if (recipients.length === 0) return;
|
|
106
106
|
|
|
107
|
-
routeNotification({
|
|
107
|
+
await routeNotification({
|
|
108
108
|
type: "routing.policy.changed",
|
|
109
109
|
scope: {},
|
|
110
110
|
recipients,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { cleanString, isRecord, isSpawnProvider, ValidationError, type StepRoutingDefaults, type StepRoutingTarget } from "@humwick/sdk";
|
|
2
|
-
import { VALID_EFFORTS } from "@humwick/sdk/provider-catalog";
|
|
3
2
|
import { WORKFLOW_PIN_FIELDS } from "@humwick/kernel/workflow-definition";
|
|
4
3
|
|
|
5
4
|
export function normalizeStepRoutingDefaults(raw: unknown): StepRoutingDefaults {
|
|
@@ -25,7 +24,6 @@ function normalizeRoles(raw: unknown, where: string): Record<string, StepRouting
|
|
|
25
24
|
for (const key of Object.keys(target)) if (!(WORKFLOW_PIN_FIELDS as readonly string[]).includes(key)) throw new ValidationError(`${where}.${role}.${key} is not a routing field`);
|
|
26
25
|
const fields = Object.fromEntries(Object.entries(target).map(([key, value]) => [key, cleanString(value, `${where}.${role}.${key}`, { required: true, max: 200 })]));
|
|
27
26
|
if (fields.provider !== undefined && !isSpawnProvider(fields.provider)) throw new ValidationError(`${where}.${role}.provider is not a provider`);
|
|
28
|
-
if (fields.effort !== undefined && !(VALID_EFFORTS as readonly string[]).includes(fields.effort)) throw new ValidationError(`${where}.${role}.effort must be ${VALID_EFFORTS.join(", ")}`);
|
|
29
27
|
return [role, fields as StepRoutingTarget];
|
|
30
28
|
}));
|
|
31
29
|
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// #3775 — per-subject cap on runner token successor mints (renew, orchestrator re-mint, boundary
|
|
2
|
+
// re-derive). A runner stuck re-minting after 401 minted 700-1,400 tokens/min and overloaded the
|
|
3
|
+
// hub writer; this refuses the excess before any token row is written. A spawn subject
|
|
4
|
+
// (`runner:spawn:<id>`) keeps one subject across its whole token lineage, so it is the key. Only a
|
|
5
|
+
// real mint is charged: a replayed handoff (retry or concurrent caller) writes nothing.
|
|
6
|
+
|
|
7
|
+
/** At most this many new tokens per subject in any rolling window. */
|
|
8
|
+
export const RUNNER_TOKEN_MINTS_PER_WINDOW = 3;
|
|
9
|
+
export const RUNNER_TOKEN_MINT_WINDOW_MS = 60_000;
|
|
10
|
+
const MAX_TRACKED_SUBJECTS = 10_000;
|
|
11
|
+
|
|
12
|
+
export class RunnerTokenMintLimit {
|
|
13
|
+
/** Recent mint times per subject, oldest first, at most RUNNER_TOKEN_MINTS_PER_WINDOW long. */
|
|
14
|
+
private readonly mints = new Map<string, number[]>();
|
|
15
|
+
/** Subjects currently refused, so a trip logs once rather than once per refused mint. */
|
|
16
|
+
private readonly tripped = new Set<string>();
|
|
17
|
+
private readonly now: () => number;
|
|
18
|
+
private readonly log: (message: string) => void;
|
|
19
|
+
|
|
20
|
+
constructor(options: { now?: () => number; log?: (message: string) => void } = {}) {
|
|
21
|
+
this.now = options.now ?? Date.now;
|
|
22
|
+
this.log = options.log ?? console.warn;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Seconds `sub` must wait before its next mint, or undefined when it may mint now. Charges nothing. */
|
|
26
|
+
refusal(sub: string): number | undefined {
|
|
27
|
+
const recent = this.recent(sub);
|
|
28
|
+
if (recent.length < RUNNER_TOKEN_MINTS_PER_WINDOW) {
|
|
29
|
+
this.tripped.delete(sub);
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
if (!this.tripped.has(sub)) {
|
|
33
|
+
if (this.tripped.size >= MAX_TRACKED_SUBJECTS) this.tripped.clear();
|
|
34
|
+
this.tripped.add(sub);
|
|
35
|
+
this.log(`[token-mint] rate limit tripped for ${sub}: ${RUNNER_TOKEN_MINTS_PER_WINDOW} tokens minted in the last ${RUNNER_TOKEN_MINT_WINDOW_MS / 1000}s; refusing until the window frees`);
|
|
36
|
+
}
|
|
37
|
+
return Math.max(1, Math.ceil((recent[0]! + RUNNER_TOKEN_MINT_WINDOW_MS - this.now()) / 1000));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Record one new token minted for `sub`. */
|
|
41
|
+
charge(sub: string): void {
|
|
42
|
+
const recent = this.recent(sub);
|
|
43
|
+
if (!this.mints.has(sub) && this.mints.size >= MAX_TRACKED_SUBJECTS) this.mints.delete(this.mints.keys().next().value!);
|
|
44
|
+
recent.push(this.now());
|
|
45
|
+
if (recent.length > RUNNER_TOKEN_MINTS_PER_WINDOW) recent.shift();
|
|
46
|
+
this.mints.set(sub, recent);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
reset(): void {
|
|
50
|
+
this.mints.clear();
|
|
51
|
+
this.tripped.clear();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
private recent(sub: string): number[] {
|
|
55
|
+
const since = this.now() - RUNNER_TOKEN_MINT_WINDOW_MS;
|
|
56
|
+
const recent = (this.mints.get(sub) ?? []).filter((at) => at > since);
|
|
57
|
+
if (recent.length) this.mints.set(sub, recent);
|
|
58
|
+
else this.mints.delete(sub);
|
|
59
|
+
return recent;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const runnerTokenMintLimit = new RunnerTokenMintLimit();
|