@humwick/server 0.130.0 → 0.130.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/docs/guides/tools-administration.md +6 -1
- package/docs/guides/tools-coordination.md +1 -0
- package/docs/guides/tools-tasks.md +8 -0
- package/docs/guides/workflows.md +58 -0
- package/docs/openapi.json +414 -1
- package/package.json +8 -17
- package/public/assets/{MessageBubble-BWpoBjl4.js → MessageBubble-BWLqMGKG.js} +2 -2
- package/public/assets/{PlanGraphPanel-C0auck3n.js → PlanGraphPanel-3TlIQpjk.js} +2 -2
- package/public/assets/{TraceView-DBnOx7AQ.js → TraceView-Wimm0Czv.js} +2 -2
- package/public/assets/{VaultDecisionCard-0kp2oNBC.js → VaultDecisionCard-Bau_vNax.js} +2 -2
- package/public/assets/{activity-yLztXEBt.js → activity-CrSurn-r.js} +2 -2
- package/public/assets/{agent-lineage-BbJDR1dW.js → agent-lineage-CknAJKcb.js} +2 -2
- package/public/assets/agent-liveness-CaNwK0Zf.js +2 -0
- package/public/assets/{agent-name-CTZBrSD9.js → agent-name-DKbiIhBo.js} +2 -2
- package/public/assets/agent-profiles-DwF6EQ4R.js +2 -0
- package/public/assets/{agent-project-badge-9TqzUUYE.js → agent-project-badge-Diz4Sjjb.js} +2 -2
- package/public/assets/{agent-tools-D4n40pn8.js → agent-tools-CRhpRQza.js} +2 -2
- package/public/assets/{agent-type-icon-D6FUarOf.js → agent-type-icon-LrUEU3lB.js} +2 -2
- package/public/assets/{agents-BYDslkJc.js → agents-B-v66C-4.js} +2 -2
- package/public/assets/{analytics-B-XSbEMC.js → analytics-BqCb-LKi.js} +2 -2
- package/public/assets/{artifact-viewer-DdWIfV6M.js → artifact-viewer-kf4pGuAR.js} +2 -2
- package/public/assets/{artifacts-oBOqks-2.js → artifacts-D32zyw4Y.js} +2 -2
- package/public/assets/{artifacts-DPN1q4pA.js → artifacts-DJevXcvg.js} +2 -2
- package/public/assets/{automation-4KcRFXEu.js → automation-BpRajx_5.js} +2 -2
- package/public/assets/{backlog-Cw9xPTCF.js → backlog-D_UjTdzX.js} +2 -2
- package/public/assets/{busy-health-CTu32MZt.js → busy-health-N3VEh4ao.js} +2 -2
- package/public/assets/{channels-BiXzg1G9.js → channels-9jopungq.js} +2 -2
- package/public/assets/{chat-Ctk2qwvA.js → chat-CSXrTB3C.js} +2 -2
- package/public/assets/{code-preview-Bm1wWqAp.js → code-preview-p1NnmqK0.js} +2 -2
- package/public/assets/{connectors-C36ax4Vw.js → connectors-CZdqlDNL.js} +2 -2
- package/public/assets/{cosmos-Jj9LK2Wf.js → cosmos-BgdsE4dG.js} +2 -2
- package/public/assets/{crate-agent-H6S7-B9T.js → crate-agent-30aXTKva.js} +2 -2
- package/public/assets/{dependency-graph-Cd1E23wa.js → dependency-graph-B_jvw2GE.js} +2 -2
- package/public/assets/{deploys-Bwfq146q.js → deploys-DoN6bAb5.js} +2 -2
- package/public/assets/{display-CfO7rTuF.js → display-BrKWFGJz.js} +2 -2
- package/public/assets/{files-DhhZI2Ih.js → files-D6XEu8Ng.js} +2 -2
- package/public/assets/fleet-C7jQWbw2.js +2 -0
- package/public/assets/{fleet-metrics-BkHP-P3R.js → fleet-metrics-BiDs3MLx.js} +2 -2
- package/public/assets/{formatted-body-Cm1RrzmN.js → formatted-body-CQBwc1fb.js} +3 -3
- package/public/assets/{formatted-body-impl-DQiOuOD1.js → formatted-body-impl-DyG0WsQS.js} +2 -2
- package/public/assets/{host-providers-dialog-CHqwXTov.js → host-providers-dialog-DKaW31dN.js} +2 -2
- package/public/assets/index-CRHep3M9.js +15 -0
- package/public/assets/index-MYAIwYTX.css +2 -0
- package/public/assets/{insights-fH1EL-qZ.js → insights-CzrtkpOE.js} +2 -2
- package/public/assets/{integrations-C5Oix6ng.js → integrations-aVsUmigt.js} +2 -2
- package/public/assets/{issue-ref-chip-ODyondIa.js → issue-ref-chip-BnSlM_95.js} +2 -2
- package/public/assets/{log-viewer-Cvfy6PW7.js → log-viewer-qe7Ee47Z.js} +2 -2
- package/public/assets/{maintenance-D8CDH5wZ.js → maintenance-NfjqFZAk.js} +2 -2
- package/public/assets/{managed-agents-egllbpij.js → managed-agents-BiH0HgaE.js} +2 -2
- package/public/assets/{markdown-preview-CYSFgVgK.js → markdown-preview-BixaT3Xr.js} +3 -3
- package/public/assets/{markdown-preview-impl-BteVIjX4.js → markdown-preview-impl-DNGlWIS3.js} +2 -2
- package/public/assets/{memory-C8WmXsyr.js → memory-DNsCl6UX.js} +2 -2
- package/public/assets/{messages-BzQdqlO6.js → messages-DopU1L1X.js} +2 -2
- package/public/assets/{orchestrators-B1HxzkNw.js → orchestrators-Cq7ckLQT.js} +2 -2
- package/public/assets/{overview-DCUnI4Z7.js → overview-C1DCTzzV.js} +2 -2
- package/public/assets/{pairs-ftCd2XcD.js → pairs-DE_m6rrE.js} +2 -2
- package/public/assets/{profile-icon-B2zH8DMH.js → profile-icon-B3rfh77F.js} +2 -2
- package/public/assets/project-profile-instructions-DQWZE0kA.js +2 -0
- package/public/assets/projects-Br2Bd2h1.js +2 -0
- package/public/assets/{prompt-settings-Bftq9czX.js → prompt-settings-BKvFsvGD.js} +2 -2
- package/public/assets/provider-display-DsuWMvVL.js +2 -0
- package/public/assets/{registry-DWCU5c8q.js → registry-Cw38_6gW.js} +2 -2
- package/public/assets/run-card-CpKqRbhg.js +2 -0
- package/public/assets/scroll-text-BKXS1ahr.js +2 -0
- package/public/assets/{secrets-C7GIUATz.js → secrets-DxI-vzSq.js} +2 -2
- package/public/assets/{service-access-settings-C3aujqTG.js → service-access-settings-D9s_VJbd.js} +2 -2
- package/public/assets/{settings-C6sZ9eBa.js → settings-CKZTVGIx.js} +2 -2
- package/public/assets/{shipping-Bu8p1gEw.js → shipping-B9YtnwtG.js} +2 -2
- package/public/assets/{stats-V9Z-GxUd.js → stats-DyUBKyWI.js} +2 -2
- package/public/assets/{status-dot-CVv0iGHL.js → status-dot-DYqlEUhJ.js} +2 -2
- package/public/assets/{store-BvtFdlGX.js → store-DcClXLH0.js} +3 -3
- package/public/assets/{tasks-CXU75HRF.js → tasks-Bh7Chr4-.js} +2 -2
- package/public/assets/{teams-BPf976zb.js → teams-bowI7qVY.js} +2 -2
- package/public/assets/{terminal-viewer-DE9BOe-8.js → terminal-viewer-BgVLHdsU.js} +3 -3
- package/public/assets/{terminal-viewer-impl-D04pjmGh.js → terminal-viewer-impl-Dz22UPy6.js} +2 -2
- package/public/assets/token-estimate-Co-Jdphh.js +2 -0
- package/public/assets/{use-agent-terminal-B1yR456R.js → use-agent-terminal-DSQQ-iY7.js} +2 -2
- package/public/assets/{use-decisions-D-S4tpDf.js → use-decisions-samMQhQf.js} +2 -2
- package/public/assets/use-project-list-59LheVP7.js +2 -0
- package/public/assets/{use-selectors-CnrAk2YP.js → use-selectors-BZa25xEB.js} +2 -2
- package/public/assets/{user-avatar-nBFIcR4M.js → user-avatar-DHxlvUvV.js} +2 -2
- package/public/assets/versioned-prompt-editor-BmED5DnJ.js +8 -0
- package/public/assets/{work-queue-TCjJxeT-.js → work-queue-CSvpuNLz.js} +2 -2
- package/public/assets/{workflow-marker-Cf3Hf2fN.js → workflow-marker-DAZcj5qt.js} +2 -2
- package/public/assets/{workflows-CXQX20Qj.js → workflows-DdmxRSyg.js} +2 -2
- package/public/assets/{workspaces-qSYzKYMA.js → workspaces-BxeKfVuF.js} +2 -2
- package/public/cosmos.html +4 -4
- package/public/index.html +31 -29
- package/runner/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/runner/plugins/claude/hooks/gate-run-guard.provisioned.mjs +31 -1
- package/runner/src/adapters/claude-effort.ts +2 -4
- package/runner/src/adapters/codex-launch-config.ts +4 -5
- package/runner/src/adapters/codex.ts +1 -1
- package/runner/src/adapters/opencode-provider.ts +7 -22
- package/runner/src/adapters/opencode.ts +4 -4
- package/runner/src/agent-runner/credentials.ts +42 -12
- package/runner/src/agent-runner/inbox.ts +27 -0
- package/runner/src/agent-runner/lifecycle-milestones.ts +0 -2
- package/runner/src/bin/claude.ts +4 -0
- package/runner/src/bin/codex.ts +4 -0
- package/runner/src/bin/opencode.ts +4 -0
- package/runner/src/index.ts +5 -2
- package/runner/src/provider-setup.ts +34 -0
- package/runner/src/providers.ts +2 -1
- package/runner/src/runner-core.ts +18 -23
- package/runner/src/spawn-input.ts +2 -1
- package/runner/src/test-run-dedup.ts +59 -56
- package/scripts/cd-config.ts +24 -3
- package/scripts/gate-run-lease.ts +10 -7
- package/scripts/gate.sh +5 -1
- package/src/branch-land-notice.ts +93 -0
- package/src/branch-landed.ts +7 -76
- package/src/bus.ts +19 -20
- package/src/cd-deploy-notify.ts +30 -2
- package/src/cd-host-lag-notify.ts +7 -6
- package/src/ci/incidents.ts +2 -2
- package/src/ci/monitor.ts +5 -8
- package/src/ci/root-missing.ts +2 -7
- package/src/ci/transition-notify.ts +7 -39
- package/src/cli/cd-pauses.ts +19 -0
- package/src/cli/orchestrator.ts +1 -1
- package/src/cli/state.ts +2 -19
- package/src/cli/task-edit.ts +22 -0
- package/src/cli/task.ts +3 -1
- package/src/cli/workflow.ts +8 -2
- package/src/commands-db.ts +10 -6
- package/src/commands-write.ts +8 -0
- package/src/config-store-write.ts +13 -1
- package/src/config-store.ts +25 -14
- package/src/db/activity-async.ts +6 -1
- package/src/db/activity-write-ops.ts +13 -1
- package/src/db/activity.ts +1 -14
- package/src/db/agent-lifecycle-write-ops.ts +1 -0
- package/src/db/agent-meta.ts +2 -2
- package/src/db/agent-ownership-write-ops.ts +4 -0
- package/src/db/agent-search.ts +1 -15
- package/src/db/agents-async.ts +58 -7
- package/src/db/agents-write-ops.ts +28 -5
- package/src/db/agents.ts +81 -54
- package/src/db/artifacts-write-ops.ts +8 -3
- package/src/db/bus-outbox-write-ops.ts +1 -0
- package/src/db/channels-write-ops.ts +4 -0
- package/src/db/ci-incidents-async.ts +5 -5
- package/src/db/ci-incidents-write-ops.ts +2 -2
- package/src/db/claude-api-budget-ops.ts +5 -5
- package/src/db/claude-app-oauth.ts +4 -4
- package/src/db/codex-reset-consumes-write-ops.ts +3 -0
- package/src/db/command-row.ts +10 -2
- package/src/db/commands-list-query.ts +2 -0
- package/src/db/commands-spawn-read.ts +1 -1
- package/src/db/commands-write-ops.ts +21 -0
- package/src/db/config-store-write-ops.ts +9 -2
- package/src/db/continuation-archives-async.ts +5 -0
- package/src/db/continuation-archives-write-ops.ts +9 -0
- package/src/db/continuations.ts +2 -2
- package/src/db/db-writer-worker.ts +8 -1
- package/src/db/delivery-write-ops.ts +5 -0
- package/src/db/deploy-events-async.ts +1 -0
- package/src/db/deploy-events-read-ops.ts +2 -1
- package/src/db/deploy-events.ts +35 -4
- package/src/db/hosts-registration.ts +10 -2
- package/src/db/hosts-write-ops.ts +14 -0
- package/src/db/hosts.ts +9 -6
- package/src/db/inbox-write-ops.ts +4 -0
- package/src/db/inbox.ts +0 -14
- package/src/db/index.ts +2 -0
- package/src/db/insights-write-ops.ts +1 -0
- package/src/db/integrations-async.ts +8 -0
- package/src/db/integrations-ops.ts +15 -0
- package/src/db/integrations.ts +15 -21
- package/src/db/issue-lifecycle.ts +3 -4
- package/src/db/issue-refs-async.ts +20 -0
- package/src/db/issue-refs-write-ops.ts +29 -0
- package/src/db/issue-refs.ts +7 -8
- package/src/db/long-running-work.ts +2 -2
- package/src/db/macos-privacy.ts +1 -1
- package/src/db/main-connection-writes.ts +23 -2
- package/src/db/maintenance-job-reconcile.ts +61 -0
- package/src/db/maintenance-job-runs-async.ts +14 -0
- package/src/db/maintenance-job-write-ops.ts +9 -0
- package/src/db/mappers.ts +2 -14
- package/src/db/merge-lease.ts +1 -15
- package/src/db/message-reads-write-ops.ts +3 -0
- package/src/db/message-write-ops.ts +4 -0
- package/src/db/migrations.ts +7 -15
- package/src/db/orchestrators-async.ts +7 -3
- package/src/db/orchestrators-write-ops.ts +7 -1
- package/src/db/orchestrators.ts +21 -77
- package/src/db/pairs.ts +1 -13
- package/src/db/project-profile-instructions.ts +50 -0
- package/src/db/prompt-versions-ops.ts +1 -0
- package/src/db/prompt-versions.ts +9 -2
- package/src/db/provider-catalog-write-ops.ts +4 -4
- package/src/db/provider-config-history.ts +8 -3
- package/src/db/provider-flap-messages-write-ops.ts +1 -0
- package/src/db/provider-model-seed.ts +34 -0
- package/src/db/provider-quota-lease-write-ops.ts +1 -0
- package/src/db/provider-quota-write-ops.ts +2 -0
- package/src/db/provisioning-write-ops.ts +9 -8
- package/src/db/read-op-marshaling-fixtures.ts +5 -0
- package/src/db/read-ops.ts +4 -0
- package/src/db/routing-policy.ts +3 -4
- package/src/db/schema.ts +9 -3
- package/src/db/secrets-broker-write-ops.ts +5 -5
- package/src/db/secrets-vault-write.ts +7 -7
- package/src/db/services-write-ops.ts +3 -0
- package/src/db/spawn-delegation-state.ts +11 -4
- package/src/db/spawn-tree-cleanup.ts +3 -0
- package/src/db/stats-async.ts +4 -3
- package/src/db/task-entity.ts +23 -2
- package/src/db/task-list.ts +3 -1
- package/src/db/tasks.ts +1 -17
- package/src/db/team-spawn-delegation.ts +1 -1
- package/src/db/teams-write-ops.ts +4 -4
- package/src/db/timer-cutover-write-ops.ts +7 -0
- package/src/db/timer-ingress-write-ops.ts +9 -0
- package/src/db/timer-ingress.ts +7 -1
- package/src/db/timer-operator-write-ops.ts +14 -0
- package/src/db/timer-transfer-write-ops.ts +4 -0
- package/src/db/timer-write-ops.ts +14 -0
- package/src/db/token-db-write-ops.ts +21 -0
- package/src/db/token-standing.ts +15 -11
- package/src/db/user-settings-write-ops.ts +1 -0
- package/src/db/vault-backup.ts +2 -2
- package/src/db/vault-expiry.ts +2 -2
- package/src/db/vault-health.ts +3 -3
- package/src/db/vault-token-ops.ts +8 -8
- package/src/db/web-tool-call-ops.ts +3 -3
- package/src/db/workflow-contact.ts +1 -1
- package/src/db/workflow-task-read-ops.ts +30 -0
- package/src/db/write-ops.ts +15 -1
- package/src/db/writer-fault-seam.ts +5 -2
- package/src/db/writer-gateway.ts +21 -12
- package/src/dispatch-availability.ts +10 -6
- package/src/ephemeral/{landing-ingress-proof-worker.ts → landing-ingress-proof.test-fixture.ts} +4 -2
- package/src/host/disk-alert.ts +121 -0
- package/src/lifecycle-manager.ts +3 -2
- package/src/maintenance/cd-watcher.ts +3 -3
- package/src/maintenance/critical-job-watchdog.ts +16 -17
- package/src/maintenance/index.ts +1 -0
- package/src/maintenance/jobs.ts +3 -2
- package/src/maintenance/scheduler.ts +84 -128
- package/src/maintenance/stalled-delivery-pager.ts +6 -5
- package/src/maintenance/workspaces.ts +1 -1
- package/src/managed-policy.ts +31 -27
- package/src/mcp/index.ts +5 -2
- package/src/mcp/output-descriptions.ts +8 -8
- package/src/mcp/presentation.ts +4 -4
- package/src/mcp/project-profile-instructions.ts +32 -0
- package/src/mcp/tool-groups.ts +1 -1
- package/src/mcp/tools-spawn.ts +4 -3
- package/src/mcp-agent-action.ts +1 -2
- package/src/mcp-host-tools.ts +1 -1
- package/src/mcp-issue-ref-tools.ts +12 -11
- package/src/mcp-maintenance-tools.ts +2 -2
- package/src/mcp-profile-trust-tools.ts +4 -4
- package/src/mcp-provider-catalog.ts +2 -2
- package/src/mcp-task-tools.ts +11 -5
- package/src/mcp-team-template-tools.ts +3 -3
- package/src/mcp-workflow-tools.ts +10 -3
- package/src/notification-types.ts +2 -1
- package/src/operator-alarm.ts +26 -11
- package/src/package-pack.ts +42 -39
- package/src/project-instructions.ts +4 -0
- package/src/project-profile-instruction-text.ts +6 -0
- package/src/project-profile-instructions.ts +20 -0
- package/src/provider-catalog-store.ts +3 -49
- package/src/provider-config-store.ts +12 -11
- package/src/provider-model-seed.ts +1 -18
- package/src/provider-quota-config-store.ts +5 -4
- package/src/provider-secrets.test-fixture.ts +3 -3
- package/src/recipe-runner.ts +2 -2
- package/src/repo-config-source.ts +10 -4
- package/src/routes/agent-profiles.ts +6 -6
- package/src/routes/agents-spawn.ts +1 -1
- package/src/routes/agents.ts +6 -6
- package/src/routes/commands-listing.ts +4 -0
- package/src/routes/commands.ts +2 -2
- package/src/routes/continuation-archives.ts +2 -2
- package/src/routes/host-resource-control.ts +4 -1
- package/src/routes/index.ts +10 -1
- package/src/routes/integrations.ts +24 -50
- package/src/routes/issue-refs.ts +7 -7
- package/src/routes/orchestrator-bootstrap.ts +3 -3
- package/src/routes/orchestrator-host-registration.ts +2 -2
- package/src/routes/orchestrator-host-utilization.ts +3 -1
- package/src/routes/orchestrator-proxy.ts +2 -2
- package/src/routes/orchestrator.ts +4 -4
- package/src/routes/project-profile-instructions.ts +27 -0
- package/src/routes/project-trust.ts +2 -2
- package/src/routes/provider-config.ts +9 -8
- package/src/routes/provider-quota-config.ts +2 -2
- package/src/routes/settings.ts +5 -5
- package/src/routes/stats.ts +6 -6
- package/src/routes/task-http.ts +15 -1
- package/src/routes/task-issues.ts +11 -26
- package/src/routes/tasks.ts +22 -53
- package/src/routes/team-templates.ts +5 -5
- package/src/routes/teams-config.ts +2 -2
- package/src/routes/tokens.ts +12 -5
- package/src/routes/workflows.ts +20 -5
- package/src/routing-policy-normalize.ts +1 -2
- package/src/routing-step-defaults.ts +0 -2
- package/src/runner-token-mint-limit.ts +63 -0
- package/src/runtime-grant.ts +4 -2
- package/src/runtime-tokens.ts +50 -9
- package/src/security.ts +13 -20
- package/src/server-background.ts +1 -1
- package/src/server.ts +5 -2
- package/src/services/host-utilization.ts +23 -0
- package/src/services/idle-epics.ts +5 -6
- package/src/services/issue-lifecycle.ts +57 -61
- package/src/services/issue-refs.ts +9 -13
- package/src/services/kernel-timers-cutover-chaos-worker.ts +12 -7
- package/src/services/kernel-timers-ingress.ts +1 -1
- package/src/services/kernel-timers-request-key-migration-chaos-worker.ts +4 -1
- package/src/services/landed-ancestry.ts +19 -3
- package/src/services/memory-areas.ts +15 -51
- package/src/services/plan-ci-notice.ts +57 -0
- package/src/services/plan-ci-recovery.ts +2 -55
- package/src/services/plan-wake-digest.ts +1 -0
- package/src/services/profile-trust.ts +4 -3
- package/src/services/project-config-read.ts +70 -0
- package/src/services/project-profile-instructions.ts +54 -0
- package/src/services/provisioning-harness/budget-baseline.json +4 -4
- package/src/services/restart-spawn.ts +61 -49
- package/src/services/self-care-state.ts +2 -1
- package/src/services/self-effort.ts +5 -5
- package/src/services/send-message.ts +5 -1
- package/src/services/spawn-agent.ts +13 -2
- package/src/services/spawn-chain-inspector.ts +6 -13
- package/src/services/spawn-policy.ts +68 -0
- package/src/services/spawn-tree-cleanup.ts +2 -2
- package/src/services/task-dispatch.ts +3 -0
- package/src/services/task-state-reconcile.ts +6 -14
- package/src/services/team-templates.ts +9 -8
- package/src/services/transient-agent-reaper.ts +3 -1
- package/src/services/workflow-auto-start.ts +25 -13
- package/src/services/workflow-ci-main.ts +1 -1
- package/src/services/workflow-deferred-cleanup.ts +4 -2
- package/src/services/workflow-effect-driver.ts +2 -0
- package/src/services/workflow-effects.ts +18 -11
- package/src/services/workflow-land-notice.ts +10 -0
- package/src/services/workflow-pause-text.ts +43 -0
- package/src/services/workflow-reconcile.ts +13 -11
- package/src/services/workflow-run-view.ts +2 -0
- package/src/services/workflow-runs.ts +29 -13
- package/src/services/workflow-supervisor-state.ts +5 -0
- package/src/services/workflow-supervisor.ts +7 -3
- package/src/settings/registry.ts +1 -2
- package/src/spawn-command.ts +4 -4
- package/src/spawn-models.ts +10 -12
- package/src/spawn-placement.ts +1 -1
- package/src/spawn-targets.ts +1 -1
- package/src/startup-context-injection.ts +1 -0
- package/src/state-adoption/cd-cutover.ts +53 -7
- package/src/state-adoption/fleet-cutover.ts +35 -0
- package/src/state-adoption/fleet-plan.ts +36 -0
- package/src/state-adoption/index.ts +2 -2
- package/src/state-adoption/linux-plan.ts +2 -2
- package/src/state-adoption/linux.ts +2 -2
- package/src/state-adoption/macos-plan.ts +2 -2
- package/src/state-adoption/macos.ts +1 -1
- package/src/steward.ts +7 -6
- package/src/task-dispatch-live.ts +1 -1
- package/src/task-dispatcher.ts +1 -1
- package/src/teams-config-store.ts +4 -3
- package/src/token-db-write.ts +10 -0
- package/src/workspace-command-settle.ts +2 -1
- package/src/workspace-steward-wake.ts +2 -2
- package/node_modules/@humwick/kernel/LICENSE +0 -167
- package/node_modules/@humwick/kernel/async-entity-persistence.ts +0 -344
- package/node_modules/@humwick/kernel/async-event-log.ts +0 -107
- package/node_modules/@humwick/kernel/automations.pilot.ts +0 -147
- package/node_modules/@humwick/kernel/config.ts +0 -111
- package/node_modules/@humwick/kernel/contract.ts +0 -572
- package/node_modules/@humwick/kernel/control-authz.ts +0 -281
- package/node_modules/@humwick/kernel/control.ts +0 -645
- package/node_modules/@humwick/kernel/effects.ts +0 -493
- package/node_modules/@humwick/kernel/event-log.ts +0 -319
- package/node_modules/@humwick/kernel/http-transport.ts +0 -384
- package/node_modules/@humwick/kernel/identity-grammar.ts +0 -20
- package/node_modules/@humwick/kernel/identity.ts +0 -248
- package/node_modules/@humwick/kernel/index.ts +0 -28
- package/node_modules/@humwick/kernel/kernel-persistence.ts +0 -181
- package/node_modules/@humwick/kernel/landing-incident.ts +0 -306
- package/node_modules/@humwick/kernel/landing.ts +0 -953
- package/node_modules/@humwick/kernel/manifest-validation.ts +0 -460
- package/node_modules/@humwick/kernel/mcp-transport.ts +0 -109
- package/node_modules/@humwick/kernel/message-authority-chaos-worker.ts +0 -200
- package/node_modules/@humwick/kernel/message-authority.ts +0 -281
- package/node_modules/@humwick/kernel/module-host.ts +0 -722
- package/node_modules/@humwick/kernel/openapi-init.ts +0 -14
- package/node_modules/@humwick/kernel/package.json +0 -47
- package/node_modules/@humwick/kernel/persistence-schema.ts +0 -248
- package/node_modules/@humwick/kernel/persistence.ts +0 -510
- package/node_modules/@humwick/kernel/registry.ts +0 -60
- package/node_modules/@humwick/kernel/sqlite-kernel-persistence.ts +0 -499
- package/node_modules/@humwick/kernel/sqlite-module-host.ts +0 -87
- package/node_modules/@humwick/kernel/timers-chaos-worker.ts +0 -186
- package/node_modules/@humwick/kernel/timers.pilot.ts +0 -1411
- package/node_modules/@humwick/kernel/workflow-activation.ts +0 -25
- package/node_modules/@humwick/kernel/workflow-backstop.ts +0 -40
- package/node_modules/@humwick/kernel/workflow-cancel-tree.ts +0 -20
- package/node_modules/@humwick/kernel/workflow-chaos-worker.ts +0 -213
- package/node_modules/@humwick/kernel/workflow-composition.ts +0 -231
- package/node_modules/@humwick/kernel/workflow-container.ts +0 -72
- package/node_modules/@humwick/kernel/workflow-control.test-fixture.ts +0 -42
- package/node_modules/@humwick/kernel/workflow-control.ts +0 -178
- package/node_modules/@humwick/kernel/workflow-definition.ts +0 -507
- package/node_modules/@humwick/kernel/workflow-dispatch.ts +0 -60
- package/node_modules/@humwick/kernel/workflow-foreach.ts +0 -167
- package/node_modules/@humwick/kernel/workflow-journal-codec.ts +0 -339
- package/node_modules/@humwick/kernel/workflow-journal.ts +0 -922
- package/node_modules/@humwick/kernel/workflow-lane.ts +0 -48
- package/node_modules/@humwick/kernel/workflow-lease-owner.ts +0 -60
- package/node_modules/@humwick/kernel/workflow-recovery.test-fixture.ts +0 -19
- package/node_modules/@humwick/kernel/workflow-runtime.ts +0 -938
- package/node_modules/@humwick/kernel/workflow-script.ts +0 -11
- package/node_modules/@humwick/kernel/workflow-state.ts +0 -299
- package/node_modules/@humwick/kernel/workflow-step-commit.ts +0 -195
- package/node_modules/@humwick/kernel/workflow-transitions.ts +0 -317
- package/node_modules/@humwick/kernel/workflow-values.ts +0 -153
- package/node_modules/@humwick/kernel/workflow.pilot.ts +0 -376
- package/node_modules/@humwick/offload/LICENSE +0 -167
- package/node_modules/@humwick/offload/README.md +0 -57
- package/node_modules/@humwick/offload/dist/async-runner.d.ts +0 -18
- package/node_modules/@humwick/offload/dist/async-runner.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/async-runner.js +0 -158
- package/node_modules/@humwick/offload/dist/async-runner.js.map +0 -1
- package/node_modules/@humwick/offload/dist/envelope.d.ts +0 -25
- package/node_modules/@humwick/offload/dist/envelope.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/envelope.js +0 -80
- package/node_modules/@humwick/offload/dist/envelope.js.map +0 -1
- package/node_modules/@humwick/offload/dist/fixtures/worker-task.d.ts +0 -10
- package/node_modules/@humwick/offload/dist/fixtures/worker-task.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/fixtures/worker-task.js +0 -59
- package/node_modules/@humwick/offload/dist/fixtures/worker-task.js.map +0 -1
- package/node_modules/@humwick/offload/dist/index.d.ts +0 -5
- package/node_modules/@humwick/offload/dist/index.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/index.js +0 -5
- package/node_modules/@humwick/offload/dist/index.js.map +0 -1
- package/node_modules/@humwick/offload/dist/subprocess-runner.d.ts +0 -62
- package/node_modules/@humwick/offload/dist/subprocess-runner.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/subprocess-runner.js +0 -295
- package/node_modules/@humwick/offload/dist/subprocess-runner.js.map +0 -1
- package/node_modules/@humwick/offload/dist/types.d.ts +0 -111
- package/node_modules/@humwick/offload/dist/types.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/types.js +0 -176
- package/node_modules/@humwick/offload/dist/types.js.map +0 -1
- package/node_modules/@humwick/offload/dist/worker-pool.d.ts +0 -23
- package/node_modules/@humwick/offload/dist/worker-pool.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/worker-pool.js +0 -435
- package/node_modules/@humwick/offload/dist/worker-pool.js.map +0 -1
- package/node_modules/@humwick/offload/dist/worker-runtime.d.ts +0 -2
- package/node_modules/@humwick/offload/dist/worker-runtime.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/worker-runtime.js +0 -27
- package/node_modules/@humwick/offload/dist/worker-runtime.js.map +0 -1
- package/node_modules/@humwick/offload/dist/worker.d.ts +0 -5
- package/node_modules/@humwick/offload/dist/worker.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/worker.js +0 -1
- package/node_modules/@humwick/offload/dist/worker.js.map +0 -1
- package/node_modules/@humwick/offload/package.json +0 -46
- package/node_modules/@humwick/offload/src/async-runner.ts +0 -170
- package/node_modules/@humwick/offload/src/envelope.ts +0 -92
- package/node_modules/@humwick/offload/src/fixtures/worker-task.ts +0 -49
- package/node_modules/@humwick/offload/src/index.ts +0 -4
- package/node_modules/@humwick/offload/src/subprocess-runner.ts +0 -334
- package/node_modules/@humwick/offload/src/types.ts +0 -235
- package/node_modules/@humwick/offload/src/worker-pool.ts +0 -463
- package/node_modules/@humwick/offload/src/worker-runtime.ts +0 -32
- package/node_modules/@humwick/offload/src/worker.ts +0 -5
- package/public/assets/agent-liveness-DyqxfB-t.js +0 -2
- package/public/assets/agent-profiles-BpI_jTxq.js +0 -2
- package/public/assets/fleet-BL4UXS_k.js +0 -2
- package/public/assets/index-B7ZerHLY.css +0 -2
- package/public/assets/index-BK0WV6hF.js +0 -15
- package/public/assets/projects-B_lmcqfO.js +0 -2
- package/public/assets/provider-display-DbLWpP3j.js +0 -2
- package/public/assets/run-card-CO_bguQf.js +0 -2
- package/public/assets/use-project-list-B-T2Bnnn.js +0 -2
- package/public/assets/versioned-prompt-editor-Diu8BIaM.js +0 -8
- package/runner/src/gate-run-lease-probe.ts +0 -38
- package/src/db/claude-catalog-reconcile.ts +0 -27
- package/src/routing-model-aliases.ts +0 -21
|
@@ -132,6 +132,7 @@ export function composeStartupContextForAgent(agent: AgentCard): ComposedSpawnIn
|
|
|
132
132
|
if (!inputs) return null;
|
|
133
133
|
const landGatesHost = landGatesHostForAgent(agent);
|
|
134
134
|
return composeSpawnInstructionsWithEvents({
|
|
135
|
+
projectId: memorySeamForAgent(agent).identity.projectId,
|
|
135
136
|
...(inputs.cwd ? { cwd: inputs.cwd } : {}),
|
|
136
137
|
// #2171 — the validation block belongs to the machine this agent runs on. This seam is
|
|
137
138
|
// synchronous (it settles a lifecycle command), so for a remote host it serves what that host's
|
|
@@ -2,15 +2,17 @@
|
|
|
2
2
|
import { isRecord, withFileLock } from "@humwick/sdk";
|
|
3
3
|
import { readFileSync } from "node:fs";
|
|
4
4
|
import { join } from "node:path";
|
|
5
|
-
import { currentPendingDeployEvent, finishDeployEvent, forceFailDeployEvent, getDeployEvent, recordDeployEventExecutor, tryBeginDeployEvent } from "../db";
|
|
5
|
+
import { currentPendingDeployEvent, finishDeployEvent, forceFailDeployEvent, getDeployEvent, getMaintenanceJobPause, recordDeployEventExecutor, recordDeployEventHosts, renewDeployEventLease, tryBeginDeployEvent } from "../db";
|
|
6
6
|
import { localDeployExecutor, serializeDeployExecutor } from "../deploy-executor";
|
|
7
7
|
import { atomicWrite, exists } from "./files";
|
|
8
8
|
import { loadJournal, type AdoptionManifest } from "./index";
|
|
9
9
|
import { parseLinuxPlan } from "./linux-plan";
|
|
10
10
|
import { parseMacosPlan } from "./macos-plan";
|
|
11
|
+
import { parseFleetPlan, type FleetPlan } from "./fleet-plan";
|
|
11
12
|
|
|
12
13
|
type Direction = "adopt" | "rollback";
|
|
13
|
-
export interface CutoverManifest { version: 1; migrationId: string; target: string; platform: "linux" | "macos"; handoff: unknown }
|
|
14
|
+
export interface CutoverManifest { version: 1; migrationId: string; target: string; platform: "linux" | "macos"; handoff: unknown; fleet?: FleetPlan }
|
|
15
|
+
export interface CutoverProgress { eventId: string; has(step: string): boolean; complete(step: string): void; steps(): string[] }
|
|
14
16
|
export interface CdPause { id: string; holder: string }
|
|
15
17
|
/** The existing maintenance pause API for the cd-watcher job. `pause` returns the active pause, ours or not. */
|
|
16
18
|
export interface CdPauseControl { pause(holder: string, reason: string): Promise<CdPause>; current(): Promise<CdPause | null>; resume(): Promise<void> }
|
|
@@ -21,6 +23,8 @@ export interface CutoverContext {
|
|
|
21
23
|
/** Runs a short deploy-ledger burst against the canonical DB. */
|
|
22
24
|
ledger: <T>(fn: () => T) => T;
|
|
23
25
|
interrupt?: (step: string) => void;
|
|
26
|
+
/** Complete an interrupted local hub handoff before using the API it supervises. */
|
|
27
|
+
recoverHandoff?: (rollback: boolean) => Promise<void>;
|
|
24
28
|
}
|
|
25
29
|
interface CutoverJournal { version: 1; manifest: CutoverManifest; events: Record<Direction, string>; pauseId?: string; completed: string[] }
|
|
26
30
|
|
|
@@ -28,7 +32,12 @@ export function parseCutoverManifest(value: unknown): { manifest: CutoverManifes
|
|
|
28
32
|
if (!isRecord(value) || value.version !== 1 || typeof value.migrationId !== "string" || !/^[A-Za-z0-9._-]{1,64}$/.test(value.migrationId)
|
|
29
33
|
|| typeof value.target !== "string" || !/^[0-9a-f]{40}$/.test(value.target) || (value.platform !== "linux" && value.platform !== "macos")) throw new Error("Invalid CD cutover manifest");
|
|
30
34
|
const adoption = (value.platform === "linux" ? parseLinuxPlan(value.handoff) : parseMacosPlan(value.handoff)).adoption;
|
|
31
|
-
|
|
35
|
+
const fleet = value.fleet === undefined ? undefined : parseFleetPlan(value.fleet);
|
|
36
|
+
if (fleet) {
|
|
37
|
+
const hub = fleet.hosts.find(host => host.id === fleet.hub)!;
|
|
38
|
+
if (hub.platform !== value.platform || JSON.stringify(hub.handoff) !== JSON.stringify(value.handoff)) throw new Error("Hub handoff must match the control host manifest");
|
|
39
|
+
}
|
|
40
|
+
return { manifest: { version: 1, migrationId: value.migrationId, target: value.target, platform: value.platform, handoff: value.handoff, ...(fleet ? { fleet } : {}) }, adoption };
|
|
32
41
|
}
|
|
33
42
|
|
|
34
43
|
async function withJournal<T>(input: unknown, create: boolean, fn: (journal: CutoverJournal, save: () => void, adoption: AdoptionManifest) => Promise<T>): Promise<T> {
|
|
@@ -55,7 +64,7 @@ const directionOf = (journal: CutoverJournal): Direction => journal.completed.so
|
|
|
55
64
|
* Every step reconciles on retry: the pause is re-ensured, the journaled lease row is re-attached
|
|
56
65
|
* and re-stamped with this process as executor, and the supervisor handoff resumes from its journal.
|
|
57
66
|
*/
|
|
58
|
-
export async function runCutover(input: unknown, context: CutoverContext & { rollback?: boolean; handoff: (rollback: boolean) => Promise<unknown> }) {
|
|
67
|
+
export async function runCutover(input: unknown, context: CutoverContext & { rollback?: boolean; handoff: (rollback: boolean, progress: CutoverProgress) => Promise<unknown> }) {
|
|
59
68
|
return withJournal(input, !context.rollback, async (journal, save, adoption) => {
|
|
60
69
|
const direction: Direction = context.rollback ? "rollback" : "adopt";
|
|
61
70
|
const { manifest } = journal;
|
|
@@ -69,6 +78,20 @@ export async function runCutover(input: unknown, context: CutoverContext & { rol
|
|
|
69
78
|
if (journal.completed.includes(`${direction}:complete`)) return result();
|
|
70
79
|
acknowledge("prepared");
|
|
71
80
|
|
|
81
|
+
const hubPrefix = manifest.fleet && `host:${manifest.fleet.hub}:handoff`;
|
|
82
|
+
const interruptedDirection = (["rollback", "adopt"] as const).find(prior => hubPrefix
|
|
83
|
+
&& journal.completed.includes(`${prior}:${hubPrefix}-started`) && !journal.completed.includes(`${prior}:${hubPrefix}`));
|
|
84
|
+
if (interruptedDirection && context.recoverHandoff) {
|
|
85
|
+
context.ledger(() => {
|
|
86
|
+
const lease = getDeployEvent(journal.events[interruptedDirection]);
|
|
87
|
+
const pause = getMaintenanceJobPause("cd-watcher");
|
|
88
|
+
if (lease?.status !== "pending" || lease.initiatedBy !== holder || !pause || pause.id !== journal.pauseId || pause.holder !== holder) throw new Error("Interrupted hub handoff no longer owns its pause and deploy lease");
|
|
89
|
+
recordDeployEventExecutor({ id: lease.id, executor: serializeDeployExecutor(localDeployExecutor(context.executorHost)) });
|
|
90
|
+
renewDeployEventLease({ id: lease.id });
|
|
91
|
+
});
|
|
92
|
+
await context.recoverHandoff(direction === "rollback");
|
|
93
|
+
}
|
|
94
|
+
|
|
72
95
|
// A pause does not cancel an in-flight deploy; the lease below proves the previous executor settled.
|
|
73
96
|
const pause = await context.pauses.pause(holder, `Humwick cutover ${manifest.migrationId} (${direction}) to ${manifest.target}; CD stays paused until explicit resume`);
|
|
74
97
|
if (pause.holder !== holder) throw new Error(`cd-watcher is paused by ${pause.holder}; refusing the cutover`);
|
|
@@ -81,7 +104,7 @@ export async function runCutover(input: unknown, context: CutoverContext & { rol
|
|
|
81
104
|
if (direction === "rollback" && getDeployEvent(journal.events.adopt)?.status === "pending") {
|
|
82
105
|
forceFailDeployEvent({ id: journal.events.adopt, reason: `superseded by rollback of ${manifest.migrationId}` });
|
|
83
106
|
}
|
|
84
|
-
const event = getDeployEvent(id) ?? tryBeginDeployEvent({ id, commitSha: manifest.target, hosts: [{ id: context.executorHost, status: "pending" }
|
|
107
|
+
const event = getDeployEvent(id) ?? tryBeginDeployEvent({ id, commitSha: manifest.target, hosts: (manifest.fleet?.hosts ?? [{ id: context.executorHost }]).map(host => ({ id: host.id, status: "pending" })), initiatedBy: holder });
|
|
85
108
|
if (!event) {
|
|
86
109
|
const held = currentPendingDeployEvent();
|
|
87
110
|
throw new Error(held ? `deploy lease ${held.id} is held by ${held.initiatedBy}; retry once it settles` : "an unreleased restart epoch blocks the deploy lease; retry once it settles");
|
|
@@ -94,14 +117,37 @@ export async function runCutover(input: unknown, context: CutoverContext & { rol
|
|
|
94
117
|
acknowledge("lease");
|
|
95
118
|
|
|
96
119
|
if (status === "pending") {
|
|
97
|
-
|
|
120
|
+
const progress: CutoverProgress = {
|
|
121
|
+
eventId: id,
|
|
122
|
+
has: (step) => journal.completed.includes(`${direction}:${step}`),
|
|
123
|
+
steps: () => [...journal.completed],
|
|
124
|
+
complete(step) {
|
|
125
|
+
acknowledge(step);
|
|
126
|
+
if (manifest.fleet && !context.ledger(() => recordDeployEventHosts(id, fleetStatuses()))) throw new Error(`Lost deploy lease ${id}`);
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
const heartbeat = setInterval(() => {
|
|
130
|
+
try { context.ledger(() => renewDeployEventLease({ id })); }
|
|
131
|
+
catch (error) { console.error(`Cutover lease heartbeat failed: ${error}`); }
|
|
132
|
+
}, 60_000);
|
|
133
|
+
heartbeat.unref();
|
|
134
|
+
try {
|
|
135
|
+
if (direction === "adopt" || manifest.fleet || handoffBegun(adoption, manifest.platform)) await context.handoff(direction === "rollback", progress);
|
|
136
|
+
} finally { clearInterval(heartbeat); }
|
|
98
137
|
acknowledge("handoff");
|
|
99
138
|
context.ledger(() => {
|
|
100
|
-
|
|
139
|
+
const event = getDeployEvent(id);
|
|
140
|
+
if (event?.status === "pending") finishDeployEvent({ id, status: terminal, hosts: manifest.fleet ? fleetStatuses() : [{ id: context.executorHost, status: terminal }] });
|
|
141
|
+
else if (event?.status !== terminal) throw new Error(`Lost deploy lease ${id}; CD remains paused`);
|
|
101
142
|
});
|
|
102
143
|
}
|
|
103
144
|
acknowledge("complete");
|
|
104
145
|
return result();
|
|
146
|
+
function fleetStatuses() {
|
|
147
|
+
return manifest.fleet!.hosts.map(host => ({ id: host.id, status: direction === "rollback" && !journal.completed.includes(`adopt:host:${host.id}:deploy-started`) ? "skipped"
|
|
148
|
+
: journal.completed.includes(`${direction}:host:${host.id}:verified`) ? terminal : "pending",
|
|
149
|
+
reason: journal.completed.filter(step => step.startsWith(`${direction}:host:${host.id}:`)).map(step => step.split(":").at(-1)).join(", ") }));
|
|
150
|
+
}
|
|
105
151
|
});
|
|
106
152
|
}
|
|
107
153
|
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// #3470: the fleet is one P4d cutover, with one pause/lease and durable progress per host.
|
|
2
|
+
import { parseCutoverManifest, runCutover, type CutoverContext, type CutoverProgress } from "./cd-cutover";
|
|
3
|
+
import { orderedFleetHosts, type FleetHost } from "./fleet-plan";
|
|
4
|
+
|
|
5
|
+
export interface FleetCutoverContext extends CutoverContext {
|
|
6
|
+
rollback?: boolean;
|
|
7
|
+
deploy(host: FleetHost, sha: string, version: string | undefined, eventId: string): Promise<void>;
|
|
8
|
+
handoff(host: FleetHost, rollback: boolean, progress: CutoverProgress): Promise<void>;
|
|
9
|
+
attest(host: FleetHost, sha: string): Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
export async function runFleetCutover(input: unknown, context: FleetCutoverContext) {
|
|
12
|
+
const { manifest } = parseCutoverManifest(input);
|
|
13
|
+
if (!manifest.fleet || manifest.fleet.hub !== context.executorHost) throw new Error("Fleet cutover must run on its pinned hub");
|
|
14
|
+
return runCutover(manifest, { ...context, handoff: async (rollback, progress) => {
|
|
15
|
+
const ordered = orderedFleetHosts(manifest.fleet!);
|
|
16
|
+
for (const host of rollback ? ordered.reverse() : ordered) {
|
|
17
|
+
const prefix = `host:${host.id}:`;
|
|
18
|
+
const touched = (phase: string) => progress.steps().includes(`adopt:${prefix}${phase}-started`);
|
|
19
|
+
if (rollback && !touched("deploy") && !touched("handoff")) continue;
|
|
20
|
+
const phase = async (name: string, action: () => Promise<void>) => {
|
|
21
|
+
if (progress.has(`${prefix}${name}`)) return;
|
|
22
|
+
progress.complete(`${prefix}${name}-started`);
|
|
23
|
+
await action();
|
|
24
|
+
progress.complete(`${prefix}${name}`);
|
|
25
|
+
};
|
|
26
|
+
const sha = rollback ? host.previous.sha : manifest.target;
|
|
27
|
+
// Restore supervisor names before the old executor resolves its legacy units on rollback.
|
|
28
|
+
if (rollback && touched("handoff")) await phase("handoff", () => context.handoff(host, true, progress));
|
|
29
|
+
if (!rollback || touched("deploy")) await phase("deploy", () => context.deploy(host, sha, rollback ? host.previous.version : undefined, progress.eventId));
|
|
30
|
+
if (!rollback) await phase("handoff", () => context.handoff(host, false, progress));
|
|
31
|
+
await context.attest(host, sha);
|
|
32
|
+
progress.complete(`${prefix}verified`);
|
|
33
|
+
}
|
|
34
|
+
} });
|
|
35
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// #3470 P7b: host identities and rollback artifacts are pinned before acquiring the deployment lease.
|
|
2
|
+
import { isRecord } from "@humwick/sdk";
|
|
3
|
+
import { absolute } from "./files";
|
|
4
|
+
import { parseLinuxPlan } from "./linux-plan";
|
|
5
|
+
import { parseMacosPlan } from "./macos-plan";
|
|
6
|
+
|
|
7
|
+
export interface FleetHost {
|
|
8
|
+
id: string;
|
|
9
|
+
hostname: string;
|
|
10
|
+
platform: "linux" | "macos";
|
|
11
|
+
handoff: unknown;
|
|
12
|
+
cli: string;
|
|
13
|
+
manifestPath: string;
|
|
14
|
+
cwd: string;
|
|
15
|
+
previous: { sha: string; version: string };
|
|
16
|
+
}
|
|
17
|
+
export interface FleetPlan { canary: string; hub: string; hosts: FleetHost[] }
|
|
18
|
+
export function parseFleetPlan(value: unknown): FleetPlan {
|
|
19
|
+
if (!isRecord(value) || typeof value.canary !== "string" || typeof value.hub !== "string" || value.canary === value.hub
|
|
20
|
+
|| !Array.isArray(value.hosts) || value.hosts.length < 2) throw new Error("Invalid fleet cutover plan");
|
|
21
|
+
const hosts = value.hosts.map((host): FleetHost => {
|
|
22
|
+
if (!isRecord(host) || typeof host.id !== "string" || !/^[A-Za-z0-9._-]+$/.test(host.id) || typeof host.hostname !== "string" || !host.hostname || !["linux", "macos"].includes(String(host.platform))
|
|
23
|
+
|| !isRecord(host.previous) || typeof host.previous.sha !== "string" || !/^[0-9a-f]{40}$/.test(host.previous.sha)
|
|
24
|
+
|| typeof host.previous.version !== "string" || !/^\d+\.\d+\.\d+$/.test(host.previous.version)) throw new Error("Invalid fleet host or rollback artifact");
|
|
25
|
+
(host.platform === "linux" ? parseLinuxPlan : parseMacosPlan)(host.handoff, host.hostname);
|
|
26
|
+
return { id: host.id, hostname: host.hostname, platform: host.platform as FleetHost["platform"], handoff: host.handoff,
|
|
27
|
+
cli: absolute(host.cli), manifestPath: absolute(host.manifestPath), cwd: absolute(host.cwd),
|
|
28
|
+
previous: { sha: host.previous.sha, version: host.previous.version } };
|
|
29
|
+
});
|
|
30
|
+
if (new Set(hosts.map(host => host.id)).size !== hosts.length || !hosts.some(host => host.id === value.hub)
|
|
31
|
+
|| !hosts.some(host => host.id === value.canary && host.platform === "linux")) throw new Error("Fleet needs a unique hub and Linux canary");
|
|
32
|
+
return { canary: value.canary, hub: value.hub, hosts };
|
|
33
|
+
}
|
|
34
|
+
export function orderedFleetHosts(plan: FleetPlan): FleetHost[] {
|
|
35
|
+
return [plan.hosts.find(host => host.id === plan.canary)!, ...plan.hosts.filter(host => host.id !== plan.canary && host.id !== plan.hub), plan.hosts.find(host => host.id === plan.hub)!];
|
|
36
|
+
}
|
|
@@ -18,8 +18,8 @@ export interface AdoptionJournal {
|
|
|
18
18
|
db?: Identity; env: EnvSnapshot[]; completed: string[];
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
export function parseAdoptionManifest(value: unknown): AdoptionManifest {
|
|
22
|
-
if (!isRecord(value) || value.version !== 1 || value.host !==
|
|
21
|
+
export function parseAdoptionManifest(value: unknown, expectedHost = hostname()): AdoptionManifest {
|
|
22
|
+
if (!isRecord(value) || value.version !== 1 || value.host !== expectedHost
|
|
23
23
|
|| !Array.isArray(value.roots) || !value.roots.length || !Array.isArray(value.envFiles)) throw new Error("Invalid adoption manifest or wrong host");
|
|
24
24
|
const roots = value.roots.map(pair => {
|
|
25
25
|
if (!isRecord(pair)) throw new Error("Invalid directory pair");
|
|
@@ -13,10 +13,10 @@ export interface LinuxPlan {
|
|
|
13
13
|
adoption: AdoptionManifest; scope: SystemdUnitScope; unitDirectory: string;
|
|
14
14
|
services: { legacy: string; canonical: string }[]; files: LinuxArtifact[]; preserve: { unit: string; mainPid: number }[];
|
|
15
15
|
}
|
|
16
|
-
export function parseLinuxPlan(value: unknown): LinuxPlan {
|
|
16
|
+
export function parseLinuxPlan(value: unknown, expectedHost?: string): LinuxPlan {
|
|
17
17
|
if (!isRecord(value) || !["user", "system"].includes(value.scope as string) || !Array.isArray(value.services) || !value.services.length
|
|
18
18
|
|| !Array.isArray(value.files) || !Array.isArray(value.preserve)) throw new Error("Invalid Linux handoff manifest");
|
|
19
|
-
const adoption = parseAdoptionManifest(value.adoption);
|
|
19
|
+
const adoption = parseAdoptionManifest(value.adoption, expectedHost);
|
|
20
20
|
const unitDirectory = absolute(value.unitDirectory);
|
|
21
21
|
const services = value.services.map(item => {
|
|
22
22
|
if (!isRecord(item) || typeof item.legacy !== "string" || !/^agent-relay(?:-orchestrator)?(?:-dev)?\.service$/.test(item.legacy)
|
|
@@ -26,7 +26,7 @@ export async function adoptLinux(input: unknown, options: LinuxHandoffOptions =
|
|
|
26
26
|
const inspect = async (unit: string): Promise<UnitState> => {
|
|
27
27
|
const output = await manager("show", unit, "--property=ActiveState,UnitFileState,MainPID,InvocationID");
|
|
28
28
|
const props = Object.fromEntries(output.trim().split("\n").map(line => { const i = line.indexOf("="); return [line.slice(0, i), line.slice(i + 1)]; }));
|
|
29
|
-
if (!["active", "inactive", "failed"].includes(props.ActiveState!) || !["enabled", "disabled", "static", "", "not-found"].includes(props.UnitFileState!)) throw new Error(`Unsupported service state: ${unit}`);
|
|
29
|
+
if (!["active", "inactive", "failed"].includes(props.ActiveState!) || !["enabled", "disabled", "static", "transient", "", "not-found"].includes(props.UnitFileState!)) throw new Error(`Unsupported service state: ${unit}`);
|
|
30
30
|
return { active: props.ActiveState === "active", enabled: props.UnitFileState === "enabled", mainPid: Number(props.MainPID || 0), invocationId: props.InvocationID! };
|
|
31
31
|
};
|
|
32
32
|
return withFileLock(`${journalPath}.lock`, async () => {
|
|
@@ -34,7 +34,7 @@ export async function adoptLinux(input: unknown, options: LinuxHandoffOptions =
|
|
|
34
34
|
const saved = prior?.linux as LinuxJournal | undefined;
|
|
35
35
|
if (saved && (JSON.stringify(saved.plan) !== JSON.stringify(plan) || saved.artifacts?.length !== plan.files.length || saved.services?.length !== plan.services.length
|
|
36
36
|
|| saved.preserved?.length !== plan.preserve.length || !Array.isArray(saved.completed))) throw new Error("Linux journal does not match manifest");
|
|
37
|
-
if (options.rollback && !saved)
|
|
37
|
+
if (options.rollback && !saved) return { journal: journalPath, direction: "rollback", preserved: [], unchanged: true };
|
|
38
38
|
const artifacts = checkArtifacts(plan, saved?.artifacts);
|
|
39
39
|
const services = saved?.services ?? await Promise.all(plan.services.map(async service => {
|
|
40
40
|
const canonical = await inspect(service.canonical);
|
|
@@ -15,10 +15,10 @@ export function plistLabel(content: string, expected: string): void {
|
|
|
15
15
|
const labels = [...content.matchAll(/<key>\s*Label\s*<\/key>\s*<string>([^<]*)<\/string>/g)];
|
|
16
16
|
if (labels.length !== 1 || labels[0]![1] !== expected) throw new Error(`Plist Label must match ${expected}`);
|
|
17
17
|
}
|
|
18
|
-
export function parseMacosPlan(value: unknown): MacosPlan {
|
|
18
|
+
export function parseMacosPlan(value: unknown, expectedHost?: string): MacosPlan {
|
|
19
19
|
if (!isRecord(value) || typeof value.domain !== "string" || !/^gui\/\d+$/.test(value.domain)
|
|
20
20
|
|| !Array.isArray(value.services) || !value.services.length || !Array.isArray(value.files) || !Array.isArray(value.preserve)) throw new Error("Invalid macOS handoff manifest");
|
|
21
|
-
const adoption = parseAdoptionManifest(value.adoption);
|
|
21
|
+
const adoption = parseAdoptionManifest(value.adoption, expectedHost);
|
|
22
22
|
const plistDirectory = absolute(value.plistDirectory);
|
|
23
23
|
const services = value.services.map(item => {
|
|
24
24
|
if (!isRecord(item) || typeof item.legacy !== "string"
|
|
@@ -47,7 +47,7 @@ export async function adoptMacos(input: unknown, options: MacosHandoffOptions =
|
|
|
47
47
|
if (saved && (JSON.stringify(saved.plan) !== JSON.stringify(plan) || saved.artifacts?.length !== plan.files.length || saved.services?.length !== plan.services.length
|
|
48
48
|
|| !saved.services.every(state => typeof state.loaded === "boolean" && typeof state.disabled === "boolean" && typeof state.canonicalDisabled === "boolean")
|
|
49
49
|
|| !Array.isArray(saved.completed))) throw new Error("macOS journal does not match manifest");
|
|
50
|
-
if (options.rollback && !saved)
|
|
50
|
+
if (options.rollback && !saved) return { journal: journalPath, direction: "rollback", preserved: [], unchanged: true };
|
|
51
51
|
const artifacts = checkMacosArtifacts(plan, saved?.artifacts);
|
|
52
52
|
const flags = await disabled();
|
|
53
53
|
const services = saved?.services ?? await Promise.all(plan.services.map(async service => {
|
package/src/steward.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { basename } from "node:path";
|
|
2
2
|
import { stewardFallbackTarget } from "./config";
|
|
3
|
-
import {
|
|
3
|
+
import { getManagedAgentState, getSpawnPolicy, getStewardConfig } from "./config-store";
|
|
4
|
+
import { deleteConfigAsync, setConfigAsync } from "./config-store-write";
|
|
4
5
|
import { listOrchestrators } from "./db";
|
|
5
6
|
import { getLifecycleManager } from "./lifecycle-manager";
|
|
6
7
|
import { renderTemplate } from "./prompt-resolver";
|
|
@@ -137,7 +138,7 @@ function stewardPolicyDiffers(existing: SpawnPolicy, desired: SpawnPolicy): bool
|
|
|
137
138
|
* - it still has a live/transitioning managed process. Deleting the policy under a running process
|
|
138
139
|
* would orphan it: `onConfigChanged` finds no policy for a deleted key, so nothing would stop it.
|
|
139
140
|
*/
|
|
140
|
-
function collapseLegacyStewardPolicies(canonicalName: string, repoRoot: string, owner: Orchestrator): boolean | undefined {
|
|
141
|
+
async function collapseLegacyStewardPolicies(canonicalName: string, repoRoot: string, owner: Orchestrator): Promise<boolean | undefined> {
|
|
141
142
|
let inheritedEnabled: boolean | undefined;
|
|
142
143
|
for (const legacyName of legacyStewardPolicyNames(repoRoot, owner.id)) {
|
|
143
144
|
if (legacyName === canonicalName) continue;
|
|
@@ -151,7 +152,7 @@ function collapseLegacyStewardPolicies(canonicalName: string, repoRoot: string,
|
|
|
151
152
|
continue;
|
|
152
153
|
}
|
|
153
154
|
if (legacy.enabled === false) inheritedEnabled = false;
|
|
154
|
-
|
|
155
|
+
await deleteConfigAsync("spawn-policy", legacyName, "steward-legacy-collapse");
|
|
155
156
|
getLifecycleManager().onConfigChanged("spawn-policy", legacyName);
|
|
156
157
|
console.warn(`[steward] collapsed legacy steward policy '${legacyName}' into '${canonicalName}' (#1955)`);
|
|
157
158
|
}
|
|
@@ -165,7 +166,7 @@ function collapseLegacyStewardPolicies(canonicalName: string, repoRoot: string,
|
|
|
165
166
|
* owns the repo. Idempotent — refreshes the policy only when config-derived fields
|
|
166
167
|
* change, so it can be called on every sweep without churn.
|
|
167
168
|
*/
|
|
168
|
-
export function
|
|
169
|
+
export async function ensureRepoStewardAsync(repoRoot: string, owningOrchestrator?: Orchestrator): Promise<string | null> {
|
|
169
170
|
const config = getStewardConfig();
|
|
170
171
|
if (!config.enabled) return null;
|
|
171
172
|
const owner = owningOrchestrator ?? listOrchestrators().find((orch) =>
|
|
@@ -177,7 +178,7 @@ export function ensureRepoSteward(repoRoot: string, owningOrchestrator?: Orchest
|
|
|
177
178
|
const name = repoStewardPolicyName(repoRoot, owner.id);
|
|
178
179
|
// #1955 mechanism 1 — merge a legacy suffix-less twin for this (repo, host) BEFORE reading the
|
|
179
180
|
// canonical row, so the pair converges on one policy instead of coexisting as two.
|
|
180
|
-
const inheritedEnabled = collapseLegacyStewardPolicies(name, repoRoot, owner);
|
|
181
|
+
const inheritedEnabled = await collapseLegacyStewardPolicies(name, repoRoot, owner);
|
|
181
182
|
const baseDesired = desiredStewardPolicy(repoRoot, owner, config);
|
|
182
183
|
const existing = getSpawnPolicy(name);
|
|
183
184
|
// #1761 (9) — respect an operator's per-policy stop. desiredStewardPolicy hardcodes `enabled:true`;
|
|
@@ -193,7 +194,7 @@ export function ensureRepoSteward(repoRoot: string, owningOrchestrator?: Orchest
|
|
|
193
194
|
: { ...baseDesired, ...(inheritedEnabled === undefined ? {} : { enabled: inheritedEnabled }) };
|
|
194
195
|
if (existing && !stewardPolicyDiffers(existing.value, desired)) return name;
|
|
195
196
|
|
|
196
|
-
|
|
197
|
+
await setConfigAsync("spawn-policy", name, desired, "steward-autoprovision");
|
|
197
198
|
getLifecycleManager().onConfigChanged("spawn-policy", name);
|
|
198
199
|
return name;
|
|
199
200
|
}
|
|
@@ -16,7 +16,7 @@ export type DispatchSnapshot = DispatchContext & Required<Pick<DispatchContext,
|
|
|
16
16
|
export async function captureDispatchContext(ctx: Omit<DispatchContext, "policy" | "bands" | "catalog"> = {}): Promise<DispatchSnapshot> {
|
|
17
17
|
const now = ctx.now ?? Date.now();
|
|
18
18
|
const [snapshot, orchestrators, hostViews] = await Promise.all([providerQuotaRoutingSnapshotAsync(now), listOrchestratorsAsync(), listHostViewsAsync()]);
|
|
19
|
-
const { targetAdmission: assess, targetUnavailableReason } = liveTargetAdmission(orchestrators, hostViews, ctx.orchestratorId, ctx.spawnCap);
|
|
19
|
+
const { targetAdmission: assess, targetUnavailableReason } = liveTargetAdmission(orchestrators, hostViews, snapshot.catalog, ctx.orchestratorId, ctx.spawnCap);
|
|
20
20
|
const probeUncertainty = new Set<string>();
|
|
21
21
|
const targetAdmission = (target: Parameters<typeof assess>[0]) => {
|
|
22
22
|
const result = assess(target);
|
package/src/task-dispatcher.ts
CHANGED
|
@@ -310,7 +310,7 @@ export function dispatchTask(shape: TaskDispatch | undefined, pin: DispatchPin =
|
|
|
310
310
|
if (eligibility(target.provider)) throw routingResolutionError(preferences, catalog, eligibility);
|
|
311
311
|
if (ctx.mustResolveAvailable && bandRank(bandFor(target.provider, bands)) > bandRank("normal")) warnings.push(`[CRITICAL] mustResolveAvailable: degraded to ${target.provider} (${bandFor(target.provider, bands)} band). Contention likely.`);
|
|
312
312
|
}
|
|
313
|
-
if (
|
|
313
|
+
if (ctx.targetAvailable && !ctx.targetAvailable(target)) {
|
|
314
314
|
throw new Error(ctx.targetUnavailableReason?.(target) ?? `No eligible online host runs ${target.provider}/${target.model ?? "default"}${target.effort ? ` at effort ${target.effort}` : ""}.`);
|
|
315
315
|
}
|
|
316
316
|
if (factors.preferences) factors.preferences = { ...factors.preferences, excluded: preferenceExclusions(preferences, factors.ranking, (p) => eligibility(p) ?? (!advertised.has(p) ? "not-advertised" : undefined)) };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { getConfig
|
|
1
|
+
import { getConfig } from "./config-store";
|
|
2
|
+
import { setConfigAsync } from "./config-store-write";
|
|
2
3
|
import { emitConfigChanged } from "./sse";
|
|
3
4
|
import {
|
|
4
5
|
DEFAULT_TEAMS_CONFIG,
|
|
@@ -14,9 +15,9 @@ export function getTeamsConfig(): TeamsConfig {
|
|
|
14
15
|
return entry ? normalizeTeamsConfig(entry.value) : { ...DEFAULT_TEAMS_CONFIG };
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
export function
|
|
18
|
+
export async function setTeamsConfigAsync(value: unknown, opts: { updatedBy?: string } = {}): Promise<TeamsConfig> {
|
|
18
19
|
const normalized = normalizeTeamsConfig(value);
|
|
19
|
-
const entry =
|
|
20
|
+
const entry = await setConfigAsync(TEAMS_CONFIG_NAMESPACE, TEAMS_CONFIG_KEY, normalized, opts.updatedBy);
|
|
20
21
|
emitConfigChanged(entry.namespace, entry.key, entry.version);
|
|
21
22
|
return normalized;
|
|
22
23
|
}
|
package/src/token-db-write.ts
CHANGED
|
@@ -13,6 +13,7 @@ import { getGateway } from "./db/gateway.ts";
|
|
|
13
13
|
import type { CreateTokenInput, HandoffTokenInput, PruneExpiredTokenRecordsInput, TokenHandoff } from "./token-db.ts";
|
|
14
14
|
import type { TokenRevokeReason } from "./security.ts";
|
|
15
15
|
import type { TokenRecord } from "./types.ts";
|
|
16
|
+
import type { LaunchFact } from "./db/launch-facts.ts";
|
|
16
17
|
|
|
17
18
|
/** Mint a component token off-loop. The `jti` is generated here so it is BOTH the token's id and the
|
|
18
19
|
* gateway idempotency key that satisfies the non-idempotent-op retry-safety gate (H5 §3.7.1). */
|
|
@@ -24,6 +25,15 @@ export function createTokenAsync(input: CreateTokenInput): Promise<{ token: stri
|
|
|
24
25
|
}>;
|
|
25
26
|
}
|
|
26
27
|
|
|
28
|
+
/** Mint a runner token and, for a fresh launch, record its launch fact, in one writer op (#1870 S7). */
|
|
29
|
+
export function createRunnerTokenAsync(input: CreateTokenInput, launch?: { agentId: string; fact: LaunchFact }): Promise<{ token: string; record: TokenRecord }> {
|
|
30
|
+
const jti = randomUUID();
|
|
31
|
+
return getGateway().write("tokens.createRunner", { input, jti, ...(launch ? { launch } : {}) }, { idempotencyKey: jti }) as unknown as Promise<{
|
|
32
|
+
token: string;
|
|
33
|
+
record: TokenRecord;
|
|
34
|
+
}>;
|
|
35
|
+
}
|
|
36
|
+
|
|
27
37
|
/** Hand a token off to its successor off-loop (#1245): fold the eligibility read, then mint and link the
|
|
28
38
|
* successor or replay the pending one — atomic in one op (ADR §3.4). Resolves `null` when ineligible. */
|
|
29
39
|
export function handoffTokenAsync(input: HandoffTokenInput): Promise<TokenHandoff | null> {
|
|
@@ -280,7 +280,7 @@ async function settleWorkspaceMergeCommandResult(command: Command, markTransitio
|
|
|
280
280
|
// genuine-but-unverifiable land on its next pass instead of it being stranded as falsely-landed.
|
|
281
281
|
const landTargetRef = landedWorkspace?.baseRef ?? "main";
|
|
282
282
|
const landAncestry = mergeResult.merged === true && !prLanded && landedCommitCount !== 0 && landedWorkspace
|
|
283
|
-
? await verifyWorkspaceLandedAncestry(landedWorkspace.repoRoot, authoritativeLandedSha, landTargetRef
|
|
283
|
+
? await verifyWorkspaceLandedAncestry(landedWorkspace.repoRoot, authoritativeLandedSha, landTargetRef.startsWith("origin/") ? landTargetRef : `origin/${landTargetRef}`, cleanString(mergeResult.landVerifiedSha, "result.landVerifiedSha", { max: 64 }))
|
|
284
284
|
: "confirmed";
|
|
285
285
|
const ancestryUnconfirmed = landAncestry !== "confirmed";
|
|
286
286
|
const normalizedStatus = ancestryUnconfirmed
|
|
@@ -381,6 +381,7 @@ async function settleWorkspaceMergeCommandResult(command: Command, markTransitio
|
|
|
381
381
|
taskIds: resolveLandedTaskIds({ workspace: landedWorkspace,
|
|
382
382
|
sourceHeadSha: typeof command.params.expectedHeadSha === "string" ? command.params.expectedHeadSha : undefined }),
|
|
383
383
|
mergedSha: authoritativeLandedSha,
|
|
384
|
+
...(landAncestry === "confirmed" && !prLanded ? { landVerifiedSha: authoritativeLandedSha } : { landVerifiedSha: stringValue(mergeResult.landVerifiedSha) }),
|
|
384
385
|
// Git/PR titles have no 200-character limit. Bound display text without rejecting the land (#3244).
|
|
385
386
|
subject: stringValue(prLanded ? prLanded.subject : mergeResult.subject)?.slice(0, 200),
|
|
386
387
|
prLand: Boolean(prLanded),
|
|
@@ -4,7 +4,7 @@ import { resolveStewardIdentity } from "./steward-identity";
|
|
|
4
4
|
import { getLifecycleManager } from "./lifecycle-manager";
|
|
5
5
|
import { getManagedAgentState } from "./config-store";
|
|
6
6
|
import { stewardHandoffIdentity } from "./steward-provenance";
|
|
7
|
-
import {
|
|
7
|
+
import { ensureRepoStewardAsync } from "./steward";
|
|
8
8
|
import { recordStewardWakeFailure } from "./workspace-steward-failure";
|
|
9
9
|
import { workspaceStewardEligible } from "./steward-queue";
|
|
10
10
|
import { workspaceOwnerOrchestrator } from "./workspace-host";
|
|
@@ -71,7 +71,7 @@ export async function wakeRepoSteward(ws: WorkspaceRecord, reason: string, opts:
|
|
|
71
71
|
return { ok: false, cooldown: false, error: ownerResult.error };
|
|
72
72
|
}
|
|
73
73
|
try {
|
|
74
|
-
const policyName =
|
|
74
|
+
const policyName = await ensureRepoStewardAsync(ws.repoRoot, ownerResult.owner);
|
|
75
75
|
if (!policyName) throw new Error("cannot spawn steward: steward policy could not be provisioned");
|
|
76
76
|
const { ownerAgentId, coordinatorAgentId } = resolveStewardIdentity(ws);
|
|
77
77
|
const coordinatorLine = coordinatorAgentId
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
# PolyForm Shield License 1.0.0
|
|
2
|
-
|
|
3
|
-
<https://polyformproject.org/licenses/shield/1.0.0>
|
|
4
|
-
|
|
5
|
-
## Acceptance
|
|
6
|
-
|
|
7
|
-
In order to get any license under these terms, you must agree
|
|
8
|
-
to them as both strict obligations and conditions to all
|
|
9
|
-
your licenses.
|
|
10
|
-
|
|
11
|
-
## Copyright License
|
|
12
|
-
|
|
13
|
-
The licensor grants you a copyright license for the
|
|
14
|
-
software to do everything you might do with the software
|
|
15
|
-
that would otherwise infringe the licensor's copyright
|
|
16
|
-
in it for any permitted purpose. However, you may
|
|
17
|
-
only distribute the software according to [Distribution
|
|
18
|
-
License](#distribution-license) and make changes or new works
|
|
19
|
-
based on the software according to [Changes and New Works
|
|
20
|
-
License](#changes-and-new-works-license).
|
|
21
|
-
|
|
22
|
-
## Distribution License
|
|
23
|
-
|
|
24
|
-
The licensor grants you an additional copyright license
|
|
25
|
-
to distribute copies of the software. Your license
|
|
26
|
-
to distribute covers distributing the software with
|
|
27
|
-
changes and new works permitted by [Changes and New Works
|
|
28
|
-
License](#changes-and-new-works-license).
|
|
29
|
-
|
|
30
|
-
## Notices
|
|
31
|
-
|
|
32
|
-
You must ensure that anyone who gets a copy of any part of
|
|
33
|
-
the software from you also gets a copy of these terms or the
|
|
34
|
-
URL for them above, as well as copies of any plain-text lines
|
|
35
|
-
beginning with `Required Notice:` that the licensor provided
|
|
36
|
-
with the software. For example:
|
|
37
|
-
|
|
38
|
-
> Required Notice: Copyright Yoyodyne, Inc. (http://example.com)
|
|
39
|
-
|
|
40
|
-
## Changes and New Works License
|
|
41
|
-
|
|
42
|
-
The licensor grants you an additional copyright license to
|
|
43
|
-
make changes and new works based on the software for any
|
|
44
|
-
permitted purpose.
|
|
45
|
-
|
|
46
|
-
## Patent License
|
|
47
|
-
|
|
48
|
-
The licensor grants you a patent license for the software that
|
|
49
|
-
covers patent claims the licensor can license, or becomes able
|
|
50
|
-
to license, that you would infringe by using the software.
|
|
51
|
-
|
|
52
|
-
## Noncompete
|
|
53
|
-
|
|
54
|
-
Any purpose is a permitted purpose, except for providing any
|
|
55
|
-
product that competes with the software or any product the
|
|
56
|
-
licensor or any of its affiliates provides using the software.
|
|
57
|
-
|
|
58
|
-
## Competition
|
|
59
|
-
|
|
60
|
-
Goods and services compete even when they provide functionality
|
|
61
|
-
through different kinds of interfaces or for different technical
|
|
62
|
-
platforms. Applications can compete with services, libraries
|
|
63
|
-
with plugins, frameworks with development tools, and so on,
|
|
64
|
-
even if they're written in different programming languages
|
|
65
|
-
or for different computer architectures. Goods and services
|
|
66
|
-
compete even when provided free of charge. If you market a
|
|
67
|
-
product as a practical substitute for the software or another
|
|
68
|
-
product, it definitely competes.
|
|
69
|
-
|
|
70
|
-
## New Products
|
|
71
|
-
|
|
72
|
-
If you are using the software to provide a product that does
|
|
73
|
-
not compete, but the licensor or any of its affiliates brings
|
|
74
|
-
your product into competition by providing a new version of
|
|
75
|
-
the software or another product using the software, you may
|
|
76
|
-
continue using versions of the software available under these
|
|
77
|
-
terms beforehand to provide your competing product, but not
|
|
78
|
-
any later versions.
|
|
79
|
-
|
|
80
|
-
## Discontinued Products
|
|
81
|
-
|
|
82
|
-
You may begin using the software to compete with a product
|
|
83
|
-
or service that the licensor or any of its affiliates has
|
|
84
|
-
stopped providing, unless the licensor includes a plain-text
|
|
85
|
-
line beginning with `Licensor Line of Business:` with the
|
|
86
|
-
software that mentions that line of business. For example:
|
|
87
|
-
|
|
88
|
-
> Licensor Line of Business: YoyodyneCMS Content Management
|
|
89
|
-
System (http://example.com/cms)
|
|
90
|
-
|
|
91
|
-
## Sales of Business
|
|
92
|
-
|
|
93
|
-
If the licensor or any of its affiliates sells a line of
|
|
94
|
-
business developing the software or using the software
|
|
95
|
-
to provide a product, the buyer can also enforce
|
|
96
|
-
[Noncompete](#noncompete) for that product.
|
|
97
|
-
|
|
98
|
-
## Fair Use
|
|
99
|
-
|
|
100
|
-
You may have "fair use" rights for the software under the
|
|
101
|
-
law. These terms do not limit them.
|
|
102
|
-
|
|
103
|
-
## No Other Rights
|
|
104
|
-
|
|
105
|
-
These terms do not allow you to sublicense or transfer any of
|
|
106
|
-
your licenses to anyone else, or prevent the licensor from
|
|
107
|
-
granting licenses to anyone else. These terms do not imply
|
|
108
|
-
any other licenses.
|
|
109
|
-
|
|
110
|
-
## Patent Defense
|
|
111
|
-
|
|
112
|
-
If you make any written claim that the software infringes or
|
|
113
|
-
contributes to infringement of any patent, your patent license
|
|
114
|
-
for the software granted under these terms ends immediately. If
|
|
115
|
-
your company makes such a claim, your patent license ends
|
|
116
|
-
immediately for work on behalf of your company.
|
|
117
|
-
|
|
118
|
-
## Violations
|
|
119
|
-
|
|
120
|
-
The first time you are notified in writing that you have
|
|
121
|
-
violated any of these terms, or done anything with the software
|
|
122
|
-
not covered by your licenses, your licenses can nonetheless
|
|
123
|
-
continue if you come into full compliance with these terms,
|
|
124
|
-
and take practical steps to correct past violations, within
|
|
125
|
-
32 days of receiving notice. Otherwise, all your licenses
|
|
126
|
-
end immediately.
|
|
127
|
-
|
|
128
|
-
## No Liability
|
|
129
|
-
|
|
130
|
-
***As far as the law allows, the software comes as is, without
|
|
131
|
-
any warranty or condition, and the licensor will not be liable
|
|
132
|
-
to you for any damages arising out of these terms or the use
|
|
133
|
-
or nature of the software, under any kind of legal claim.***
|
|
134
|
-
|
|
135
|
-
## Definitions
|
|
136
|
-
|
|
137
|
-
The **licensor** is the individual or entity offering these
|
|
138
|
-
terms, and the **software** is the software the licensor makes
|
|
139
|
-
available under these terms.
|
|
140
|
-
|
|
141
|
-
A **product** can be a good or service, or a combination
|
|
142
|
-
of them.
|
|
143
|
-
|
|
144
|
-
**You** refers to the individual or entity agreeing to these
|
|
145
|
-
terms.
|
|
146
|
-
|
|
147
|
-
**Your company** is any legal entity, sole proprietorship,
|
|
148
|
-
or other kind of organization that you work for, plus all
|
|
149
|
-
its affiliates.
|
|
150
|
-
|
|
151
|
-
**Affiliates** means the other organizations than an
|
|
152
|
-
organization has control over, is under the control of, or is
|
|
153
|
-
under common control with.
|
|
154
|
-
|
|
155
|
-
**Control** means ownership of substantially all the assets of
|
|
156
|
-
an entity, or the power to direct its management and policies
|
|
157
|
-
by vote, contract, or otherwise. Control can be direct or
|
|
158
|
-
indirect.
|
|
159
|
-
|
|
160
|
-
**Your licenses** are all the licenses granted to you for the
|
|
161
|
-
software under these terms.
|
|
162
|
-
|
|
163
|
-
**Use** means anything you do with the software requiring one
|
|
164
|
-
of your licenses.
|
|
165
|
-
|
|
166
|
-
Required Notice: Copyright 2026 Exelerus AB
|
|
167
|
-
Licensor Line of Business: provider-independent runtimes and coordination software for teams of AI agents
|