@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/db/writer-gateway.ts
CHANGED
|
@@ -42,17 +42,16 @@ import { WriterDrain } from "./writer-drain";
|
|
|
42
42
|
|
|
43
43
|
import { errMessage } from "@humwick/sdk";
|
|
44
44
|
import { createWorkerPool, type WorkerPool } from "@humwick/offload";
|
|
45
|
-
import {
|
|
46
|
-
import { armedWriterFaultCount } from "./writer-fault-seam.ts";
|
|
47
|
-
import { onLoopWriteTransaction } from "./on-loop-write-transaction.ts";
|
|
45
|
+
import { getDbPath } from "./connection.ts";
|
|
48
46
|
// On-loop-block attribution (#1882 / ADR §5). `resolveLoopCallsite` pins the effective callsite onto a
|
|
49
47
|
// submission in the CALLER's context; `captureSyncFrame` times the op body where it actually runs — in
|
|
50
48
|
// the in-process drain microtask, NOT the synchronous enqueue. One-way import (loop-block-attribution
|
|
51
49
|
// imports only event-loop-lag + config), so no cycle.
|
|
52
50
|
import { captureSyncFrame, resolveLoopCallsite } from "../loop-block-attribution.ts";
|
|
51
|
+
import { markCallerResume } from "../hub-metrics.ts";
|
|
53
52
|
import { reconstructDbError, serializeDbError } from "./db-error-registry.ts";
|
|
54
53
|
import {
|
|
55
|
-
|
|
54
|
+
writerOpAllowsKeyless,
|
|
56
55
|
isOffLoopWriterOp,
|
|
57
56
|
runWriterBatch,
|
|
58
57
|
runWriterOp,
|
|
@@ -110,7 +109,7 @@ export class WriteIndeterminateError extends Error {
|
|
|
110
109
|
// ── Options & per-call opts ───────────────────────────────────────────────────────────────────────
|
|
111
110
|
|
|
112
111
|
export interface InitWriterOptions {
|
|
113
|
-
/**
|
|
112
|
+
/** File path to attach. A live file DB always uses its worker, including legacy :memory: requests. */
|
|
114
113
|
path?: string;
|
|
115
114
|
/** Soft high-water mark on the writer queue; past it, non-critical writes shed (§3.6). */
|
|
116
115
|
queueHighWater?: number;
|
|
@@ -174,14 +173,18 @@ export interface WriterStats {
|
|
|
174
173
|
* SQLite lock (H4 §3.6.1). A wedged writer is NOT idle — this is deliberately distinct from
|
|
175
174
|
* `busy:0`, which is how the naive pool-replace path mis-reported the stall. New non-critical
|
|
176
175
|
* writes shed and critical writes are held until the wedged op completes and the FIFO resumes.
|
|
176
|
+
* #3776 — names the op holding the writer and how long it has run, so health says WHICH job; null when not wedged.
|
|
177
177
|
*/
|
|
178
|
-
wedged:
|
|
178
|
+
wedged: { op: string; runningMs: number } | null;
|
|
179
179
|
/**
|
|
180
180
|
* #2276 — how many times the IN-PROCESS drain has yielded the event loop mid-convoy because its
|
|
181
181
|
* time slice was spent. 0 on the worker backend (nothing to slice). A steadily climbing count is
|
|
182
182
|
* the observable signal that write convoys are long enough to need the throttle.
|
|
183
183
|
*/
|
|
184
184
|
drainYields: number;
|
|
185
|
+
/** #3798 — writes executed since boot on the main thread and on a writer thread (a batch counts its entries). */
|
|
186
|
+
onLoopOps: number;
|
|
187
|
+
writerThreadOps: number;
|
|
185
188
|
}
|
|
186
189
|
|
|
187
190
|
// ── Backend state ─────────────────────────────────────────────────────────────────────────────────
|
|
@@ -242,8 +245,6 @@ interface InProcessBackend {
|
|
|
242
245
|
kind: "in-process";
|
|
243
246
|
stop: AbortController;
|
|
244
247
|
busy: boolean;
|
|
245
|
-
offLoop?: WorkerBackend;
|
|
246
|
-
offLoopGeneration?: number;
|
|
247
248
|
}
|
|
248
249
|
type Backend = WorkerBackend | InProcessBackend;
|
|
249
250
|
|
|
@@ -255,26 +256,28 @@ let writerTimeoutMs = DEFAULT_WRITER_TIMEOUT_MS;
|
|
|
255
256
|
let drainSliceMs = DEFAULT_DRAIN_SLICE_MS;
|
|
256
257
|
// Monotonic across re-inits (like any counter): a test that wants a delta reads it before and after.
|
|
257
258
|
let drainYields = 0;
|
|
259
|
+
let onLoopOps = 0;
|
|
260
|
+
let writerThreadOps = 0;
|
|
258
261
|
// Set while a writer job has blown its gateway deadline and the sole writer is stalled holding the
|
|
259
262
|
// lock (§3.6.1). Cleared when that in-flight job finally settles (the op completed and released the
|
|
260
263
|
// lock), which re-kicks the FIFO drain. Worker backend only — an in-process op runs synchronously on
|
|
261
264
|
// the main thread, so it cannot be observed mid-stall.
|
|
262
|
-
let
|
|
265
|
+
let wedgedOp: { op: string; startedAt: number } | undefined;
|
|
263
266
|
|
|
264
267
|
// Test-only fault injection for the precise H5 window: the op has COMMITTED, but its
|
|
265
268
|
// acknowledgement is lost before the caller observes the result. One-shot by design so a retry
|
|
266
269
|
// exercises the persisted idempotency ledger rather than repeatedly failing at the transport edge.
|
|
267
|
-
let postCommitAckLossForTests: { op: string
|
|
270
|
+
let postCommitAckLossForTests: { op: string } | undefined;
|
|
268
271
|
|
|
269
272
|
export function rejectNextWriterAckAfterCommitForTests(op: string): void {
|
|
270
|
-
postCommitAckLossForTests = { op
|
|
273
|
+
postCommitAckLossForTests = { op };
|
|
271
274
|
}
|
|
272
275
|
|
|
273
|
-
function
|
|
274
|
-
if (
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
276
|
+
function resolveWriterOp(entry: Extract<Submission, { kind: "op" }>, result: unknown): void {
|
|
277
|
+
if (postCommitAckLossForTests?.op === entry.op) {
|
|
278
|
+
postCommitAckLossForTests = undefined;
|
|
279
|
+
entry.reject(new WriteIndeterminateError(entry.op, new Error("injected post-commit lost acknowledgement"), entry.opts?.idempotencyKey));
|
|
280
|
+
} else entry.resolve(result);
|
|
278
281
|
}
|
|
279
282
|
|
|
280
283
|
/**
|
|
@@ -283,7 +286,8 @@ function losePostCommitAckForTests(op: string): boolean {
|
|
|
283
286
|
* size-1 writer pool.
|
|
284
287
|
*/
|
|
285
288
|
export function initWriter(options: InitWriterOptions = {}): void {
|
|
286
|
-
|
|
289
|
+
// A file-backed main handle never executes writer bodies, even when an old caller requests memory.
|
|
290
|
+
const path = options.path && options.path !== ":memory:" ? options.path : getDbPath() ?? options.path;
|
|
287
291
|
// EVERY caller-supplied number is validated BEFORE any of them is assigned: a RangeError thrown
|
|
288
292
|
// after an earlier field was already written would leave the module in a half-applied config the
|
|
289
293
|
// caller never asked for.
|
|
@@ -355,14 +359,14 @@ function createFileWriter(dbPath: string): WorkerBackend {
|
|
|
355
359
|
|
|
356
360
|
/** Server shutdown keeps already-admitted writes; test/reset teardown remains immediate. */
|
|
357
361
|
export async function drainWriterOnShutdown(): Promise<void> {
|
|
358
|
-
try { await shutdownDrain.start(() => !draining && !
|
|
362
|
+
try { await shutdownDrain.start(() => !draining && !wedgedOp && pendingWriteDepth() === 0 && inFlightWrites() === 0); }
|
|
359
363
|
finally { await shutdownWriter(); }
|
|
360
364
|
}
|
|
361
365
|
|
|
362
366
|
export async function shutdownWriter(): Promise<void> {
|
|
363
367
|
const current = backend;
|
|
364
368
|
backend = undefined;
|
|
365
|
-
|
|
369
|
+
wedgedOp = undefined;
|
|
366
370
|
// Reject anything still queued at the gateway so no caller hangs across a teardown.
|
|
367
371
|
const stranded = submissionQueue.splice(0, submissionQueue.length);
|
|
368
372
|
for (const entry of stranded) {
|
|
@@ -370,7 +374,6 @@ export async function shutdownWriter(): Promise<void> {
|
|
|
370
374
|
}
|
|
371
375
|
if (current?.kind === "in-process") current.stop.abort(new Error("writer gateway shut down"));
|
|
372
376
|
if (current?.kind === "worker") await current.pool.destroy();
|
|
373
|
-
if (current?.kind === "in-process") await current.offLoop?.pool.destroy();
|
|
374
377
|
}
|
|
375
378
|
|
|
376
379
|
/** Whether the gateway is initialized (some callers guard bootstrap ordering on this). */
|
|
@@ -379,12 +382,14 @@ export function isWriterInitialized(): boolean {
|
|
|
379
382
|
}
|
|
380
383
|
|
|
381
384
|
export function writerStats(): WriterStats {
|
|
382
|
-
|
|
385
|
+
const ops = { drainYields, onLoopOps, writerThreadOps };
|
|
386
|
+
if (!backend) return { backend: "uninitialized", queued: 0, busy: 0, highWater: queueHighWater, wedged: null, ...ops };
|
|
387
|
+
const wedged = wedgedOp ? { op: wedgedOp.op, runningMs: Math.round(performance.now() - wedgedOp.startedAt) } : null;
|
|
383
388
|
if (backend.kind === "in-process") {
|
|
384
|
-
return { backend: "in-process", queued: pendingWriteDepth(), busy: inFlightWrites(), highWater: queueHighWater, wedged,
|
|
389
|
+
return { backend: "in-process", queued: pendingWriteDepth(), busy: inFlightWrites(), highWater: queueHighWater, wedged, ...ops };
|
|
385
390
|
}
|
|
386
391
|
const stats = backend.pool.stats;
|
|
387
|
-
return { backend: "worker", queued: pendingWriteDepth(), busy: stats.busy, highWater: queueHighWater, wedged,
|
|
392
|
+
return { backend: "worker", queued: pendingWriteDepth(), busy: stats.busy, highWater: queueHighWater, wedged, ...ops };
|
|
388
393
|
}
|
|
389
394
|
|
|
390
395
|
function requireBackend(): Backend {
|
|
@@ -448,7 +453,7 @@ function pendingWriteDepth(): number {
|
|
|
448
453
|
|
|
449
454
|
/** Includes an in-process writer waiting asynchronously for BEGIN. */
|
|
450
455
|
function inFlightWrites(): number {
|
|
451
|
-
return backend?.kind === "worker" ? backend.pool.stats.busy :
|
|
456
|
+
return backend?.kind === "worker" ? backend.pool.stats.busy : Number(backend?.busy ?? false);
|
|
452
457
|
}
|
|
453
458
|
|
|
454
459
|
/** Reject every caller attached to a submission (used for teardown / dispatch-time backend loss). */
|
|
@@ -461,7 +466,7 @@ function rejectEntry(entry: Submission, error: unknown): void {
|
|
|
461
466
|
* before the write is ever submitted, so a keyless non-idempotent write can never be retried into a
|
|
462
467
|
* duplicate. `key` is the per-write key (the batch/coalesce paths pass each entry's own key). */
|
|
463
468
|
function guardIdempotency(op: string, key: string | undefined): void {
|
|
464
|
-
if (key === undefined && !
|
|
469
|
+
if (key === undefined && !writerOpAllowsKeyless(op)) throw new WriteRetrySafetyError(op);
|
|
465
470
|
}
|
|
466
471
|
|
|
467
472
|
/** Backpressure admission (§3.6/§3.6.1). `count` is the number of writes this submission would ADD (1
|
|
@@ -480,7 +485,7 @@ function admitOrThrow(op: string, opts: WriteOpts | undefined, count: number): v
|
|
|
480
485
|
const occupancy = pendingWriteDepth() + inFlightWrites();
|
|
481
486
|
if (occupancy + count > queueHardCap) throw new WriterOverloadedError(op, occupancy);
|
|
482
487
|
if (opts?.critical) return;
|
|
483
|
-
const workerWedged =
|
|
488
|
+
const workerWedged = wedgedOp !== undefined;
|
|
484
489
|
if (workerWedged || occupancy + count > queueHighWater) throw new WriterOverloadedError(op, occupancy);
|
|
485
490
|
}
|
|
486
491
|
|
|
@@ -511,7 +516,7 @@ async function drainLoop(): Promise<void> {
|
|
|
511
516
|
// second concurrent drain and anything submitted meanwhile is picked up by this same loop when
|
|
512
517
|
// it resumes — FIFO is preserved, the queue is only PAUSED.
|
|
513
518
|
let sliceStartedAt = performance.now();
|
|
514
|
-
while (submissionQueue.length > 0 && !
|
|
519
|
+
while (submissionQueue.length > 0 && !wedgedOp) {
|
|
515
520
|
const entry = submissionQueue.shift()!;
|
|
516
521
|
const onLoop = backend?.kind === "in-process";
|
|
517
522
|
await dispatchEntry(entry);
|
|
@@ -521,7 +526,7 @@ async function drainLoop(): Promise<void> {
|
|
|
521
526
|
sliceStartedAt = performance.now();
|
|
522
527
|
continue;
|
|
523
528
|
}
|
|
524
|
-
if (submissionQueue.length === 0 ||
|
|
529
|
+
if (submissionQueue.length === 0 || wedgedOp) continue;
|
|
525
530
|
if (performance.now() - sliceStartedAt < drainSliceMs) continue;
|
|
526
531
|
drainYields += 1;
|
|
527
532
|
await yieldEventLoop();
|
|
@@ -529,7 +534,7 @@ async function drainLoop(): Promise<void> {
|
|
|
529
534
|
}
|
|
530
535
|
} finally {
|
|
531
536
|
draining = false;
|
|
532
|
-
shutdownDrain.notify(!
|
|
537
|
+
shutdownDrain.notify(!wedgedOp && pendingWriteDepth() === 0 && inFlightWrites() === 0);
|
|
533
538
|
}
|
|
534
539
|
}
|
|
535
540
|
|
|
@@ -551,19 +556,9 @@ async function dispatchEntry(entry: Submission): Promise<void> {
|
|
|
551
556
|
if (back.kind === "in-process") {
|
|
552
557
|
back.busy = true;
|
|
553
558
|
try {
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
if (path && path !== ":memory:" && isOffLoopWriterOp(entry.op) && armedWriterFaultCount() === 0) {
|
|
558
|
-
if (back.offLoop && back.offLoopGeneration !== getDbGeneration()) {
|
|
559
|
-
await back.offLoop.pool.destroy();
|
|
560
|
-
back.offLoop = undefined;
|
|
561
|
-
}
|
|
562
|
-
back.stop.signal.throwIfAborted();
|
|
563
|
-
back.offLoop ??= createFileWriter(path);
|
|
564
|
-
back.offLoopGeneration = getDbGeneration();
|
|
565
|
-
await dispatchWorker(entry, back.offLoop);
|
|
566
|
-
} else await dispatchInProcess(entry, back.stop.signal);
|
|
559
|
+
back.stop.signal.throwIfAborted();
|
|
560
|
+
onLoopOps += entryWrites(entry);
|
|
561
|
+
await dispatchInProcess(entry);
|
|
567
562
|
} catch (error) { rejectEntry(entry, error); }
|
|
568
563
|
finally { back.busy = false; }
|
|
569
564
|
return;
|
|
@@ -571,6 +566,10 @@ async function dispatchEntry(entry: Submission): Promise<void> {
|
|
|
571
566
|
await dispatchWorker(entry, back);
|
|
572
567
|
}
|
|
573
568
|
|
|
569
|
+
function entryWrites(entry: Submission): number {
|
|
570
|
+
return entry.kind === "op" ? 1 : entry.argsList.length;
|
|
571
|
+
}
|
|
572
|
+
|
|
574
573
|
/**
|
|
575
574
|
* The per-entry dedup keys for a batch/coalesce job (H5 §3.7.1). A dbWriteBatch carries ONE key for
|
|
576
575
|
* the whole call and derives a stable per-entry key `${key}#${i}`, so a blind retry of the same batch
|
|
@@ -598,18 +597,12 @@ function entryKeys(entry: Extract<Submission, { kind: "batch" | "coalesce" }>):
|
|
|
598
597
|
* (`dispatchWorker`) is deliberately NOT wrapped: its op body runs off-thread, so there is no on-loop
|
|
599
598
|
* block to attribute (only the sub-floor enqueue, which the record floor drops).
|
|
600
599
|
*/
|
|
601
|
-
async function dispatchInProcess(entry: Submission
|
|
602
|
-
const execute = <T>(fn: () => T) =>
|
|
603
|
-
fn, (attempt) => captureSyncFrame({ op: entry.op, callsite: entry.callsite }, attempt), writerTimeoutMs, signal,
|
|
604
|
-
);
|
|
600
|
+
async function dispatchInProcess(entry: Submission): Promise<void> {
|
|
601
|
+
const execute = <T>(fn: () => T) => captureSyncFrame({ op: entry.op, callsite: entry.callsite }, fn);
|
|
605
602
|
if (entry.kind === "op") {
|
|
606
603
|
try {
|
|
607
|
-
const result = cloneIn(
|
|
608
|
-
|
|
609
|
-
entry.reject(new WriteIndeterminateError(entry.op, new Error("injected post-commit lost acknowledgement"), entry.opts?.idempotencyKey));
|
|
610
|
-
return;
|
|
611
|
-
}
|
|
612
|
-
entry.resolve(result);
|
|
604
|
+
const result = cloneIn(execute(() => runWriterOp(entry.op, cloneIn(entry.args), { now: entry.now, presence: cloneIn(entry.presence) }, entry.opts?.idempotencyKey)));
|
|
605
|
+
resolveWriterOp(entry, result);
|
|
613
606
|
} catch (error) {
|
|
614
607
|
entry.reject(reconstructInProcess(error));
|
|
615
608
|
}
|
|
@@ -618,7 +611,7 @@ async function dispatchInProcess(entry: Submission, signal: AbortSignal): Promis
|
|
|
618
611
|
// batch + coalesce share the SAVEPOINT-per-caller executor; only the fan-out differs.
|
|
619
612
|
let coalesced: CoalescedEntry[];
|
|
620
613
|
try {
|
|
621
|
-
const entries: BatchEntry[] =
|
|
614
|
+
const entries: BatchEntry[] = execute(() => runWriterBatch(
|
|
622
615
|
entry.op,
|
|
623
616
|
entry.argsList.map((a) => cloneIn(a)),
|
|
624
617
|
entryKeys(entry),
|
|
@@ -650,6 +643,11 @@ async function dispatchWorker(entry: Submission, back: WorkerBackend): Promise<v
|
|
|
650
643
|
|
|
651
644
|
// retrySafe stays false (default): a write must NEVER be auto-re-dispatched (it would repeat its
|
|
652
645
|
// effect). No pool timeout is armed — the deadline is the gateway's own (§3.6.1).
|
|
646
|
+
const startedAt = performance.now();
|
|
647
|
+
// #3798 — the drain runs outside any caller, so its dispatch and result handling are charged to the
|
|
648
|
+
// caller that submitted this entry (the reader pool does the same per read).
|
|
649
|
+
markCallerResume(entry.callsite);
|
|
650
|
+
writerThreadOps += entryWrites(entry);
|
|
653
651
|
const poolPromise = back.pool.run<WriterJobInput, WriterJobResult>(WRITER_TASK_NAME, input, { labels });
|
|
654
652
|
|
|
655
653
|
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
@@ -660,18 +658,22 @@ async function dispatchWorker(entry: Submission, back: WorkerBackend): Promise<v
|
|
|
660
658
|
}),
|
|
661
659
|
]);
|
|
662
660
|
if (timer) clearTimeout(timer);
|
|
661
|
+
markCallerResume(entry.callsite);
|
|
663
662
|
|
|
664
663
|
if (raced.done === "timeout") {
|
|
665
664
|
// WEDGED (§3.6.1). The op is still running and still holds the lock; do NOT replace the worker.
|
|
666
665
|
// Surface the caller's INDETERMINATE outcome, hold the FIFO, and resume when the op finally
|
|
667
666
|
// settles (it commits/rolls back and releases the lock on the SAME warm connection).
|
|
668
|
-
wedged
|
|
667
|
+
// #3776 — name the op: "writer wedged" alone left an incident to guess which job held the lock.
|
|
668
|
+
wedgedOp = { op: entry.op, startedAt };
|
|
669
|
+
console.warn(`[writer-gateway] writer op ${entry.op} has held the writer past its ${writerTimeoutMs}ms deadline; writes are held until it settles`);
|
|
669
670
|
rejectIndeterminate(entry);
|
|
670
671
|
poolPromise.then(
|
|
671
672
|
() => {},
|
|
672
673
|
() => {},
|
|
673
674
|
).finally(() => {
|
|
674
|
-
wedged
|
|
675
|
+
console.warn(`[writer-gateway] wedged writer op ${entry.op} settled after ${Math.round(performance.now() - startedAt)}ms`);
|
|
676
|
+
wedgedOp = undefined;
|
|
675
677
|
kickDrain();
|
|
676
678
|
}).catch((error) => console.error(`[writer-gateway] resume after wedge failed: ${errMessage(error)}`));
|
|
677
679
|
return;
|
|
@@ -701,7 +703,7 @@ function fanOutWorker(entry: Submission, result: WriterJobResult): void {
|
|
|
701
703
|
entry.reject(new Error(`writer worker returned a ${result.kind} result for a single op`));
|
|
702
704
|
return;
|
|
703
705
|
}
|
|
704
|
-
if (result.ok) entry
|
|
706
|
+
if (result.ok) resolveWriterOp(entry, result.result);
|
|
705
707
|
else entry.reject(reconstructDbError(result.error));
|
|
706
708
|
return;
|
|
707
709
|
}
|
package/src/dev.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { writeChildEnv } from "@humwick/sdk/env";
|
|
2
|
+
import { instanceDirectoryEnv } from "@humwick/sdk/isolated-env";
|
|
2
3
|
import { execFile } from "node:child_process";
|
|
3
4
|
import { shellQuote } from "@humwick/sdk/shell-utils";
|
|
4
5
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
@@ -209,7 +210,8 @@ export function createDevServicePlan(options: {
|
|
|
209
210
|
}
|
|
210
211
|
const envContent = `# ${DEV_MARKER}\n` + renderEnvFile(writeChildEnv({}, {
|
|
211
212
|
AGENT_RELAY_TOKEN: token,
|
|
212
|
-
|
|
213
|
+
...instanceDirectoryEnv(rootDir, prefix),
|
|
214
|
+
AGENT_RELAY_DEV_PROFILE: "1",
|
|
213
215
|
DB_PATH: join(rootDir, "state", "agent-relay.db"),
|
|
214
216
|
HOST: host,
|
|
215
217
|
PORT: String(port),
|
|
@@ -229,6 +231,7 @@ export function createDevServicePlan(options: {
|
|
|
229
231
|
apiPort,
|
|
230
232
|
tmuxPrefix: "ar-dev",
|
|
231
233
|
env: writeChildEnv({}, {
|
|
234
|
+
...instanceDirectoryEnv(rootDir, prefix),
|
|
232
235
|
AGENT_RELAY_DEV_PROFILE: "1",
|
|
233
236
|
}),
|
|
234
237
|
};
|
|
@@ -296,8 +299,10 @@ export async function executeDevServicePlan(plan: DevServicePlan, options: { dry
|
|
|
296
299
|
const output: string[] = [];
|
|
297
300
|
if (plan.action === "start" || plan.action === "restart") {
|
|
298
301
|
// Upgrade installed environments before either service can adopt execution records (#3139).
|
|
299
|
-
const
|
|
300
|
-
|
|
302
|
+
const paths = writeChildEnv(instanceDirectoryEnv(plan.rootDir, plan.prefix), { AGENT_RELAY_DEV_PROFILE: "1" });
|
|
303
|
+
const keys = Object.keys(paths).map((key) => key.replace("AGENT_RELAY_", "(?:AGENT_RELAY_|HUMWICK_)"));
|
|
304
|
+
const existing = readFileSync(plan.envFile, "utf8").replace(new RegExp(`^(?:export\\s+)?(?:${keys.join("|")})=.*$`, "gm"), "").trimEnd();
|
|
305
|
+
await writeFile(plan.envFile, `${existing}\n${Object.entries(paths).map(([key, value]) => `${key}=${shellQuote(value)}\n`).join("")}`, "utf8");
|
|
301
306
|
}
|
|
302
307
|
if (plan.action === "install") {
|
|
303
308
|
for (const file of plan.files) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import type
|
|
1
|
+
import { errMessage, type HostView, type Orchestrator } from "@humwick/sdk";
|
|
2
|
+
import { resolveProviderSelection, type ProviderCatalogEntry } from "@humwick/sdk/provider-catalog";
|
|
3
3
|
import type { DispatchTarget } from "./task-dispatcher";
|
|
4
4
|
import { spawnPlacementRefusal, hostSpawnAdmission, hostIdentitiesById, spawnHostCapAdmission, type SpawnCapOptions } from "./spawn-placement";
|
|
5
5
|
import { liveHostDisabledProviders } from "./host-provider-store";
|
|
@@ -17,13 +17,15 @@ export interface LiveTargetAdmission {
|
|
|
17
17
|
targetUnavailableReason: (target: DispatchTarget) => string | undefined;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
export function liveTargetAdmission(orchestrators: readonly Orchestrator[], views: readonly HostView[], orchestratorId?: string, capOpts: SpawnCapOptions = {}): LiveTargetAdmission {
|
|
20
|
+
export function liveTargetAdmission(orchestrators: readonly Orchestrator[], views: readonly HostView[], catalog: ProviderCatalogEntry[], orchestratorId?: string, capOpts: SpawnCapOptions = {}): LiveTargetAdmission {
|
|
21
21
|
const identities = hostIdentitiesById(views);
|
|
22
22
|
const byId = new Map(views.map((view) => [view.id, view]));
|
|
23
23
|
const disabled = liveHostDisabledProviders();
|
|
24
24
|
const capBlock = spawnHostCapAdmission(capOpts);
|
|
25
25
|
const hosts = orchestrators.filter((host) => !orchestratorId || host.id === orchestratorId);
|
|
26
26
|
const targetAdmission = ({ provider, model, effort }: DispatchTarget): TargetAdmission => {
|
|
27
|
+
try { resolveProviderSelection({ provider, model, effort }, catalog); }
|
|
28
|
+
catch { return { eligible: false, uncertainties: [] }; }
|
|
27
29
|
let eligible = false;
|
|
28
30
|
const uncertainties: TargetUncertainty[] = [];
|
|
29
31
|
for (const host of hosts) {
|
|
@@ -34,9 +36,11 @@ export function liveTargetAdmission(orchestrators: readonly Orchestrator[], view
|
|
|
34
36
|
}
|
|
35
37
|
return { eligible, uncertainties };
|
|
36
38
|
};
|
|
37
|
-
const targetUnavailableReason = (target: DispatchTarget) =>
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
const targetUnavailableReason = (target: DispatchTarget) => {
|
|
40
|
+
try { resolveProviderSelection(target, catalog); }
|
|
41
|
+
catch (error) { return errMessage(error); }
|
|
42
|
+
return spawnPlacementRefusal(orchestrators, views, target.provider, target.model, target.effort, orchestratorId, capOpts);
|
|
43
|
+
};
|
|
40
44
|
return { targetAdmission, targetUnavailableReason };
|
|
41
45
|
}
|
|
42
46
|
|
package/src/ephemeral/{landing-ingress-proof-worker.ts → landing-ingress-proof.test-fixture.ts}
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Precondition setup for the packaged-ephemeral landing-ingress Proof of Life.
|
|
2
2
|
* Delivery and both crash boundaries run through the packaged Relay; this fixture only registers
|
|
3
3
|
* the disposable workspace that its real ephemeral orchestrator will probe. */
|
|
4
|
-
import {
|
|
4
|
+
import { closeDb, openExistingDb } from "../db/connection.ts";
|
|
5
5
|
import { upsertWorkspace } from "../db/workspaces.ts";
|
|
6
6
|
|
|
7
7
|
const dbPath = process.env.DB_PATH;
|
|
@@ -13,7 +13,8 @@ if (!dbPath || !worktreePath || !orchestratorId || !baseSha) {
|
|
|
13
13
|
throw new Error("usage: landing-ingress-proof-worker <worktree-path> <orchestrator-id> <base-sha>");
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
// The installed Relay already owns the schema; a fixture must not migrate its live DB (#3715).
|
|
17
|
+
openExistingDb(dbPath);
|
|
17
18
|
upsertWorkspace({
|
|
18
19
|
id: workspaceId,
|
|
19
20
|
repoRoot: worktreePath,
|
|
@@ -27,4 +28,5 @@ upsertWorkspace({
|
|
|
27
28
|
orchestratorId,
|
|
28
29
|
metadata: {},
|
|
29
30
|
});
|
|
31
|
+
closeDb();
|
|
30
32
|
console.log(JSON.stringify({ workspaceId }));
|
package/src/event-loop-lag.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { trackRelayEvent } from "./relay-event-drain";
|
|
1
2
|
import { errMessage } from "@humwick/sdk";
|
|
2
3
|
import type { HealthCheck } from "./types";
|
|
3
4
|
import {
|
|
@@ -166,7 +167,7 @@ export function setLagRegressionObserver(fn: EventLoopLagRegressionObserver | un
|
|
|
166
167
|
* threshold rather than the diagnostic log threshold, and is a separate registration a caller can
|
|
167
168
|
* leave unset (e.g. ephemeral mode) with no effect.
|
|
168
169
|
*/
|
|
169
|
-
export type EventLoopLagBreakerObserver = (gapStartAt: number, gapEndAt: number, lagMs: number) => void
|
|
170
|
+
export type EventLoopLagBreakerObserver = (gapStartAt: number, gapEndAt: number, lagMs: number) => void | Promise<void>;
|
|
170
171
|
|
|
171
172
|
let breakerObserver: EventLoopLagBreakerObserver | undefined;
|
|
172
173
|
|
|
@@ -283,7 +284,8 @@ export function recordEventLoopLagSample(
|
|
|
283
284
|
// timer callback, so a throw here would become an uncaught exception in the interval — guard it:
|
|
284
285
|
// the breaker degrading is never worth killing the loop-lag sampler that watches for the freeze.
|
|
285
286
|
try {
|
|
286
|
-
breakerObserver(sampledAt - Math.max(0, elapsedMs), sampledAt, normalized);
|
|
287
|
+
const outcome = breakerObserver(sampledAt - Math.max(0, elapsedMs), sampledAt, normalized);
|
|
288
|
+
if (outcome) trackRelayEvent(outcome, "maintenance.lag-breaker");
|
|
287
289
|
} catch (error) {
|
|
288
290
|
console.warn(`[health] event-loop-lag breaker observer threw: ${errMessage(error)}`);
|
|
289
291
|
}
|
package/src/event-loop-yield.ts
CHANGED
|
@@ -11,7 +11,7 @@ export function yieldToEventLoop(): Promise<void> {
|
|
|
11
11
|
* `moreWork`, so a backlog drains over runs instead of overrunning the deadline (a breaker strike). */
|
|
12
12
|
export async function forEachPaced<T>(
|
|
13
13
|
items: () => Iterable<T>,
|
|
14
|
-
unit: (item: T) =>
|
|
14
|
+
unit: (item: T) => unknown,
|
|
15
15
|
opts: { signal?: AbortSignal; budgetMs: number; ready?: () => boolean },
|
|
16
16
|
): Promise<{ moreWork: boolean }> {
|
|
17
17
|
await yieldToEventLoop();
|
|
@@ -20,7 +20,7 @@ export async function forEachPaced<T>(
|
|
|
20
20
|
for (const item of items()) {
|
|
21
21
|
if (opts.signal?.aborted) return { moreWork: false };
|
|
22
22
|
if (performance.now() >= stopAt || opts.ready?.() === false) return { moreWork: true };
|
|
23
|
-
unit(item);
|
|
23
|
+
await unit(item);
|
|
24
24
|
await yieldToEventLoop();
|
|
25
25
|
}
|
|
26
26
|
return { moreWork: false };
|
package/src/events.ts
CHANGED
|
@@ -19,7 +19,7 @@ export interface RelayEvent {
|
|
|
19
19
|
|
|
20
20
|
type Listener = (event: RelayEvent) => void;
|
|
21
21
|
|
|
22
|
-
const listeners = new
|
|
22
|
+
const listeners = new Map<Listener, string>();
|
|
23
23
|
const fanoutQueue: Array<{ event: RelayEvent; lastSeq: number }> = [];
|
|
24
24
|
let notifying = false;
|
|
25
25
|
|
|
@@ -33,12 +33,13 @@ export function emitRelayEvent(input: Omit<RelayEvent, "seq" | "timestamp">): Pr
|
|
|
33
33
|
const appended = appendRelayEventInternal(input.type, input.source, input.data, input.subject, timestamp)!;
|
|
34
34
|
return Promise.resolve(fanOutAppendedEvent(input, appended, timestamp));
|
|
35
35
|
}
|
|
36
|
-
|
|
36
|
+
// #3614 — keyless: nothing resubmits this append, so a ledger row would only cost writes.
|
|
37
|
+
return trackRelayEvent(appendAndFanOut(structuredClone(input), {}), input.type);
|
|
37
38
|
});
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
/** #3606 — fan out to the current listeners only: no bus_outbox row, no idempotency-ledger row, no
|
|
41
|
-
* replay. For state the next tick supersedes anyway (dashboard viewer presence). */
|
|
42
|
+
* replay. For state the next tick supersedes anyway (dashboard viewer presence, agent liveness ticks). */
|
|
42
43
|
export function emitEphemeralRelayEvent(input: Omit<RelayEvent, "seq" | "timestamp" | "ephemeral">): RelayEvent {
|
|
43
44
|
return fanOutAppendedEvent({ ...input, ephemeral: true }, { seq: 0, lastSeq: 0 }, Date.now());
|
|
44
45
|
}
|
|
@@ -71,7 +72,8 @@ async function appendAndFanOut(
|
|
|
71
72
|
} catch (error) {
|
|
72
73
|
// H5: a lost acknowledgement says nothing about commit. Re-submit the exact logical append
|
|
73
74
|
// with the same durable key; the writer returns the first result without a second insert.
|
|
74
|
-
|
|
75
|
+
// A keyless emit is at-most-once: it surfaces the error, and a committed row stays replayable.
|
|
76
|
+
if (!(error instanceof WriteIndeterminateError) || !options.idempotencyKey) throw error;
|
|
75
77
|
appended = await getGateway().write("bus.append", args, { critical: true, idempotencyKey: options.idempotencyKey }) as unknown as typeof appended;
|
|
76
78
|
}
|
|
77
79
|
// A retry ledger result proves durable storage, not that this process owns a fresh live edge.
|
|
@@ -122,19 +124,19 @@ export function fanOutAppendedEvent(
|
|
|
122
124
|
|
|
123
125
|
function notify(event: RelayEvent): void {
|
|
124
126
|
measureEmit(event.type, true, () => {
|
|
125
|
-
for (const listener of listeners) {
|
|
127
|
+
for (const [listener, name] of listeners) {
|
|
126
128
|
try {
|
|
127
129
|
listener(event);
|
|
128
130
|
} catch (error) {
|
|
129
131
|
// Event projections are isolated so one transport cannot block another; a failed one (e.g. a
|
|
130
132
|
// BUSY write in a projection, #3643) is logged, not swallowed.
|
|
131
|
-
console.warn(`[events] ${event.type} listener failed: ${errMessage(error)}
|
|
133
|
+
console.warn(`[events] ${event.type} listener ${name} failed: ${errMessage(error)}`, error instanceof Error ? error.stack : error);
|
|
132
134
|
}
|
|
133
135
|
}
|
|
134
136
|
});
|
|
135
137
|
}
|
|
136
138
|
|
|
137
|
-
export function subscribeRelayEvents(listener: Listener): () => void {
|
|
138
|
-
listeners.
|
|
139
|
+
export function subscribeRelayEvents(listener: Listener, name = listener.name || "<anonymous>"): () => void {
|
|
140
|
+
listeners.set(listener, name);
|
|
139
141
|
return () => listeners.delete(listener);
|
|
140
142
|
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// #3762 — warn before a host disk fills. Pure: the single-writer utilization op settles each beat
|
|
2
|
+
// against the stored one (same seam as gate-capacity-alert.ts), so each level change alerts once.
|
|
3
|
+
// Two triggers, one level ladder: used% crossing 85/92/97, or the free-space history projecting
|
|
4
|
+
// full within 24 h (6 h = high). An episode alerts once per worse level and clears with a notice.
|
|
5
|
+
import type { HostDiskWatch, HostMachineSample } from "@humwick/sdk";
|
|
6
|
+
|
|
7
|
+
export type DiskLevel = 1 | 2 | 3;
|
|
8
|
+
|
|
9
|
+
/** Used-share rungs: warn / high / critical. */
|
|
10
|
+
export const DISK_USED_PCT_LEVELS: readonly [number, number, number] = [85, 92, 97];
|
|
11
|
+
/** An episode only clears below this, so a disk hovering on a rung does not flap. */
|
|
12
|
+
export const DISK_CLEAR_USED_PCT = 82;
|
|
13
|
+
export const DISK_ETA_WARN_H = 24;
|
|
14
|
+
export const DISK_ETA_HIGH_H = 6;
|
|
15
|
+
/** Growth needs this much history before it is a rate rather than a blip. */
|
|
16
|
+
export const DISK_MIN_TREND_SPAN_MS = 3 * 3_600_000;
|
|
17
|
+
const HISTORY_SPACING_MS = 30 * 60_000;
|
|
18
|
+
const HISTORY_MAX_SPAN_MS = 25 * 3_600_000;
|
|
19
|
+
const TREND_WINDOW_MS = 24 * 3_600_000;
|
|
20
|
+
|
|
21
|
+
export type DiskAlert =
|
|
22
|
+
| {
|
|
23
|
+
kind: "low"; level: DiskLevel; since: number; freeMb: number; totalMb: number; path?: string;
|
|
24
|
+
/** Free-space decline over the trend window, MB/h; present only while declining. */
|
|
25
|
+
rateMbPerHour?: number; etaHours?: number; spanHours?: number;
|
|
26
|
+
}
|
|
27
|
+
| { kind: "recovered"; since: number; freeMb: number; totalMb: number; path?: string };
|
|
28
|
+
|
|
29
|
+
export interface DiskNotice {
|
|
30
|
+
subject: string;
|
|
31
|
+
body: string;
|
|
32
|
+
priority: "low" | "default" | "high" | "urgent";
|
|
33
|
+
idempotencyKey: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function usageLevel(usedPct: number): number {
|
|
37
|
+
return DISK_USED_PCT_LEVELS.filter((rung) => usedPct >= rung).length;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function growthLevel(etaHours: number | undefined): number {
|
|
41
|
+
if (etaHours === undefined) return 0;
|
|
42
|
+
return etaHours < DISK_ETA_HIGH_H ? 2 : etaHours < DISK_ETA_WARN_H ? 1 : 0;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function nextHistory(prev: HostDiskWatch["history"], at: number, freeMb: number): Array<[number, number]> {
|
|
46
|
+
const kept = (prev ?? []).filter(([t]) => t >= at - HISTORY_MAX_SPAN_MS && t < at);
|
|
47
|
+
const last = kept[kept.length - 1];
|
|
48
|
+
if (!last || at - last[0] >= HISTORY_SPACING_MS) kept.push([at, freeMb]);
|
|
49
|
+
return kept;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Decline rate over the oldest point inside the trend window, or undefined (too little history / not declining). */
|
|
53
|
+
function trend(history: Array<[number, number]>, at: number, freeMb: number): { rateMbPerHour: number; etaHours: number; spanHours: number } | undefined {
|
|
54
|
+
const oldest = history.find(([t]) => t >= at - TREND_WINDOW_MS);
|
|
55
|
+
if (!oldest || at - oldest[0] < DISK_MIN_TREND_SPAN_MS) return undefined;
|
|
56
|
+
const declineMb = oldest[1] - freeMb;
|
|
57
|
+
if (declineMb <= 0) return undefined;
|
|
58
|
+
const spanHours = (at - oldest[0]) / 3_600_000;
|
|
59
|
+
const rateMbPerHour = declineMb / spanHours;
|
|
60
|
+
return { rateMbPerHour, etaHours: freeMb / rateMbPerHour, spanHours };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Stamps the relay-owned disk watch onto the stored sample and names the one alert owed, if any.
|
|
65
|
+
* A beat with no disk pair keeps the previous watch (missing telemetry is not a state change).
|
|
66
|
+
*/
|
|
67
|
+
export function settleDiskWatch(prev: HostMachineSample | undefined, next: HostMachineSample): { machine: HostMachineSample; alert?: DiskAlert } {
|
|
68
|
+
const before = prev?.diskWatch;
|
|
69
|
+
const { diskFreeMb: freeMb, diskTotalMb: totalMb } = next;
|
|
70
|
+
if (freeMb === undefined || totalMb === undefined || totalMb <= 0) {
|
|
71
|
+
return { machine: before ? { ...next, diskWatch: before } : next };
|
|
72
|
+
}
|
|
73
|
+
const history = nextHistory(before?.history, next.at, freeMb);
|
|
74
|
+
const projected = trend(history, next.at, freeMb);
|
|
75
|
+
const usedPct = ((totalMb - freeMb) / totalMb) * 100;
|
|
76
|
+
const level = Math.max(usageLevel(usedPct), growthLevel(projected?.etaHours));
|
|
77
|
+
const prevLevel = before?.level ?? 0;
|
|
78
|
+
const where = next.diskPath ? { path: next.diskPath } : {};
|
|
79
|
+
|
|
80
|
+
if (level > prevLevel) {
|
|
81
|
+
const since = before?.since ?? next.at;
|
|
82
|
+
const watch: HostDiskWatch = { level: level as DiskLevel, since, history };
|
|
83
|
+
return {
|
|
84
|
+
machine: { ...next, diskWatch: watch },
|
|
85
|
+
alert: {
|
|
86
|
+
kind: "low", level: level as DiskLevel, since, freeMb, totalMb, ...where,
|
|
87
|
+
...(projected ? { rateMbPerHour: projected.rateMbPerHour, etaHours: projected.etaHours, spanHours: projected.spanHours } : {}),
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
if (prevLevel > 0 && level === 0 && usedPct < DISK_CLEAR_USED_PCT) {
|
|
92
|
+
return { machine: { ...next, diskWatch: { history } }, alert: { kind: "recovered", since: before!.since ?? next.at, freeMb, totalMb, ...where } };
|
|
93
|
+
}
|
|
94
|
+
return { machine: { ...next, diskWatch: { ...(before?.level ? { level: before.level, since: before.since } : {}), history } } };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const gb = (mb: number) => `${(mb / 1024).toFixed(mb >= 10_240 ? 0 : 1)} GB`;
|
|
98
|
+
|
|
99
|
+
export function composeDiskNotice(hostId: string, label: string, alert: DiskAlert): DiskNotice {
|
|
100
|
+
const volume = alert.path ? ` (${alert.path})` : "";
|
|
101
|
+
const usedPct = Math.round(((alert.totalMb - alert.freeMb) / alert.totalMb) * 100);
|
|
102
|
+
if (alert.kind === "recovered") {
|
|
103
|
+
return {
|
|
104
|
+
subject: `Disk recovered on ${label}`,
|
|
105
|
+
body: `${label}${volume} has ${gb(alert.freeMb)} free of ${gb(alert.totalMb)} (${usedPct}% used); the low-disk episode is over. (#3762)`,
|
|
106
|
+
priority: "low",
|
|
107
|
+
idempotencyKey: `host-disk:${hostId}:${alert.since}:recovered`,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
const word = alert.level === 3 ? "CRITICAL" : alert.level === 2 ? "very low" : "low";
|
|
111
|
+
const growth = alert.rateMbPerHour !== undefined && alert.etaHours !== undefined
|
|
112
|
+
? ` Free space fell ~${gb(alert.rateMbPerHour * 24)}/day over the last ${Math.round(alert.spanHours ?? 0)} h; at that rate it is full in ~${Math.max(1, Math.round(alert.etaHours))} h.`
|
|
113
|
+
: "";
|
|
114
|
+
return {
|
|
115
|
+
subject: `Disk ${word} on ${label}: ${gb(alert.freeMb)} free (${usedPct}% used)`,
|
|
116
|
+
body: `${label}${volume} has ${gb(alert.freeMb)} free of ${gb(alert.totalMb)} (${usedPct}% used).${growth} `
|
|
117
|
+
+ "Check workspaces, runtime logs and caches on that host before agents start failing with ENOSPC. (#3762)",
|
|
118
|
+
priority: alert.level === 3 ? "urgent" : alert.level === 2 ? "high" : "default",
|
|
119
|
+
idempotencyKey: `host-disk:${hostId}:${alert.since}:${alert.level}`,
|
|
120
|
+
};
|
|
121
|
+
}
|