@cohortapp/agent-sdk 2.16.0 → 2.18.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.json +18 -0
- package/.env.example +23 -7
- package/README.md +1 -0
- package/bin/maestro.mjs +62 -0
- package/docs/guides/billing-console-keys.md +60 -0
- package/docs/guides/front-door-session.md +54 -9
- package/docs/guides/mac-mini.md +20 -25
- package/docs/guides/poller-daemon-setup.md +4 -1
- package/docs/guides/setup-wizard.md +1 -1
- package/docs/runbooks/fleet-rollout.md +156 -0
- package/docs/runbooks/mac-mini-bootstrap.md +12 -14
- package/lib/action-executor.js +19 -3
- package/lib/budget-guard.mjs +279 -3
- package/lib/channels/base-adapter.mjs +3 -1
- package/lib/channels/contract.mjs +2 -1
- package/lib/channels/inbox-item.mjs +8 -0
- package/lib/claude-bin.mjs +5 -6
- package/lib/cli/doctor-checks.mjs +141 -10
- package/lib/cli/global-setup-extras.mjs +5 -1
- package/lib/cli/inbox.mjs +100 -15
- package/lib/cli/seat-auth.mjs +463 -0
- package/lib/cli/session.mjs +80 -12
- package/lib/collective/capture.mjs +8 -6
- package/lib/collective/global-config.mjs +63 -1
- package/lib/collective/presence.mjs +142 -5
- package/lib/comms/send-gate.mjs +559 -1
- package/lib/context/budget.mjs +327 -0
- package/lib/context/history-scope.mjs +138 -0
- package/lib/diagnostics/alerts.mjs +49 -0
- package/lib/diagnostics/cadence-output-freshness.mjs +288 -0
- package/lib/engine/agents/definitions.mjs +343 -0
- package/lib/engine/agents/persist.mjs +275 -0
- package/lib/engine/agents/runtime.mjs +748 -0
- package/lib/engine/agents/usage.mjs +95 -0
- package/lib/engine/auth-status.mjs +139 -0
- package/lib/engine/budget.mjs +194 -0
- package/lib/engine/cli.mjs +1204 -0
- package/lib/engine/commands/index.mjs +269 -0
- package/lib/engine/context/budget.mjs +219 -0
- package/lib/engine/context/cache.mjs +125 -0
- package/lib/engine/context/child-env.mjs +215 -0
- package/lib/engine/context/compaction.mjs +342 -0
- package/lib/engine/context/images.mjs +90 -0
- package/lib/engine/context/instructions.mjs +327 -0
- package/lib/engine/context/lazy-instructions.mjs +169 -0
- package/lib/engine/context/manager.mjs +182 -0
- package/lib/engine/context/real-path.mjs +91 -0
- package/lib/engine/context/secret-values.mjs +163 -0
- package/lib/engine/context/settings.mjs +274 -0
- package/lib/engine/context/stream-input.mjs +159 -0
- package/lib/engine/guard.mjs +152 -0
- package/lib/engine/hooks.mjs +713 -0
- package/lib/engine/loop.mjs +560 -0
- package/lib/engine/mcp/client.mjs +254 -0
- package/lib/engine/mcp/config.mjs +301 -0
- package/lib/engine/mcp/http.mjs +201 -0
- package/lib/engine/mcp/index.mjs +146 -0
- package/lib/engine/mcp/jsonrpc.mjs +147 -0
- package/lib/engine/mcp/naming.mjs +66 -0
- package/lib/engine/mcp/resources.mjs +89 -0
- package/lib/engine/mcp/results.mjs +133 -0
- package/lib/engine/mcp/stdio.mjs +137 -0
- package/lib/engine/mcp/supervisor.mjs +116 -0
- package/lib/engine/messages.mjs +104 -0
- package/lib/engine/output/json.mjs +164 -0
- package/lib/engine/output/stream-json.mjs +266 -0
- package/lib/engine/permissions.mjs +845 -0
- package/lib/engine/process-identity.mjs +164 -0
- package/lib/engine/process-tree.mjs +551 -0
- package/lib/engine/prompt.mjs +60 -0
- package/lib/engine/session/store.mjs +299 -0
- package/lib/engine/session-runtime/args.mjs +97 -0
- package/lib/engine/session-runtime/host.mjs +143 -0
- package/lib/engine/session-runtime/inbox.mjs +122 -0
- package/lib/engine/session-runtime/notifications.mjs +129 -0
- package/lib/engine/session-runtime/registry.mjs +328 -0
- package/lib/engine/session-runtime/runner.mjs +344 -0
- package/lib/engine/session-runtime/socket.mjs +212 -0
- package/lib/engine/session-runtime/wakeup.mjs +115 -0
- package/lib/engine/skills/index.mjs +321 -0
- package/lib/engine/tools/bash-background.mjs +533 -0
- package/lib/engine/tools/bash.mjs +216 -0
- package/lib/engine/tools/edit.mjs +97 -0
- package/lib/engine/tools/glob.mjs +81 -0
- package/lib/engine/tools/grep.mjs +224 -0
- package/lib/engine/tools/index.mjs +84 -0
- package/lib/engine/tools/list-agents.mjs +32 -0
- package/lib/engine/tools/ls.mjs +127 -0
- package/lib/engine/tools/monitor.mjs +82 -0
- package/lib/engine/tools/notebook-edit.mjs +218 -0
- package/lib/engine/tools/read.mjs +103 -0
- package/lib/engine/tools/schedule-wakeup.mjs +45 -0
- package/lib/engine/tools/schema.mjs +144 -0
- package/lib/engine/tools/send-message.mjs +77 -0
- package/lib/engine/tools/session.mjs +70 -0
- package/lib/engine/tools/todo.mjs +144 -0
- package/lib/engine/tools/toolsearch.mjs +217 -0
- package/lib/engine/tools/walk.mjs +193 -0
- package/lib/engine/tools/web-switch.mjs +31 -0
- package/lib/engine/tools/webfetch-html.mjs +387 -0
- package/lib/engine/tools/webfetch-net.mjs +340 -0
- package/lib/engine/tools/webfetch.mjs +198 -0
- package/lib/engine/tools/websearch.mjs +91 -0
- package/lib/engine/tools/workflow.mjs +95 -0
- package/lib/engine/tools/write.mjs +76 -0
- package/lib/engine/tui/line-editor.mjs +137 -0
- package/lib/engine/tui/render.mjs +86 -0
- package/lib/engine/tui/tui.mjs +274 -0
- package/lib/engine/wire/anthropic-messages.mjs +263 -0
- package/lib/engine/wire/effort.mjs +36 -0
- package/lib/engine/wire/errors.mjs +496 -0
- package/lib/engine/wire/http.mjs +441 -0
- package/lib/engine/wire/index.mjs +76 -0
- package/lib/engine/wire/openai-chat.mjs +332 -0
- package/lib/engine/wire/prompt-cache.mjs +79 -0
- package/lib/engine/wire/search.mjs +140 -0
- package/lib/engine/wire/sse.mjs +114 -0
- package/lib/engine/wire/stall.mjs +349 -0
- package/lib/engine/wire/token-provider.mjs +175 -0
- package/lib/engine/wire/usage.mjs +192 -0
- package/lib/engine/workflow/host.mjs +524 -0
- package/lib/engine/workflow/journal.mjs +188 -0
- package/lib/engine/workflow/json-schema.mjs +171 -0
- package/lib/engine/workflow/meta.mjs +329 -0
- package/lib/engine/workflow/notifications.mjs +52 -0
- package/lib/engine/workflow/runtime.mjs +447 -0
- package/lib/engine/workflow/sandbox.mjs +534 -0
- package/lib/engine/workflow/worker.mjs +141 -0
- package/lib/engine/workflow/worktree.mjs +74 -0
- package/lib/execution/disposition.mjs +1 -1
- package/lib/execution/intake.mjs +10 -0
- package/lib/execution/surface-policy.mjs +15 -0
- package/lib/learning/curator.mjs +8 -6
- package/lib/learning/reflect.mjs +8 -6
- package/lib/model-router/catalog/cohort.yaml +137 -0
- package/lib/model-router/catalog.mjs +118 -1
- package/lib/model-router/economics.mjs +9 -0
- package/lib/model-router/failover.mjs +67 -16
- package/lib/model-router/llm-task.mjs +39 -3
- package/lib/model-router/resolve.mjs +95 -3
- package/lib/model-router/spawn.mjs +46 -47
- package/lib/model-router/taxonomy.mjs +126 -4
- package/lib/org/cost-sync.mjs +141 -11
- package/lib/org/inbound/broadcast.mjs +289 -0
- package/lib/org/inbound/collective.mjs +375 -0
- package/lib/org/inbound/directedness.mjs +96 -8
- package/lib/org/inbound/facts.mjs +82 -4
- package/lib/org/inbound/hydrate.mjs +555 -51
- package/lib/org/inbound/project.mjs +22 -0
- package/lib/org/inbound/surfaces.mjs +14 -0
- package/lib/org/llm-token.mjs +879 -0
- package/lib/org/mesh.mjs +61 -0
- package/lib/org/messaging.mjs +3 -1
- package/lib/org/protocol.checksum +1 -1
- package/lib/org/protocol.mjs +15 -0
- package/lib/org/quota.mjs +520 -0
- package/lib/org/tool-surface.mjs +104 -16
- package/lib/org/ui-parity.mjs +16 -1
- package/lib/org/work-ledger.mjs +37 -6
- package/lib/rate-guard.mjs +114 -1
- package/lib/resource-governor.mjs +41 -6
- package/lib/runtime/adapter.mjs +823 -0
- package/lib/runtime/child-env.mjs +191 -0
- package/lib/runtime/legacy-shell-guard.mjs +97 -0
- package/lib/runtime/seat-engine.mjs +162 -0
- package/lib/session/ask-ledger.mjs +271 -0
- package/lib/session/current-work.mjs +676 -0
- package/lib/session/feed-core.mjs +40 -3
- package/lib/session/launch-args.mjs +56 -4
- package/lib/session/status-summary.mjs +26 -9
- package/lib/session/upgrade-notice.mjs +42 -0
- package/lib/setup/claude-probe.mjs +117 -13
- package/lib/setup/enrich.mjs +13 -10
- package/lib/setup/sections/model.mjs +39 -13
- package/lib/telemetry/collect.mjs +208 -9
- package/lib/upgrade/ignored-drift.mjs +105 -0
- package/lib/voice/post-call-brief.mjs +30 -17
- package/package.json +15 -3
- package/plugins/maestro-skills/skills/board-work.md +5 -0
- package/plugins/maestro-skills/skills/inbound-triage.md +56 -15
- package/plugins/maestro-skills/skills/main-session.md +18 -7
- package/scripts/ci/check-tarball-fidelity.mjs +126 -2
- package/scripts/ci/run-tests.mjs +47 -19
- package/scripts/cohort-llm/api-key-helper.mjs +92 -0
- package/scripts/collective/hook-runner.mjs +29 -2
- package/scripts/continuous-monitor.sh +13 -0
- package/scripts/cost/track-claude-usage.mjs +15 -0
- package/scripts/daemon/agent-daemon.mjs +408 -20
- package/scripts/daemon/assurance.mjs +48 -12
- package/scripts/daemon/cadence-consumer.mjs +218 -68
- package/scripts/daemon/cadence-handlers.mjs +73 -4
- package/scripts/daemon/classifier.mjs +75 -26
- package/scripts/daemon/context-compiler.mjs +104 -59
- package/scripts/daemon/deliver.mjs +30 -1
- package/scripts/daemon/dispatcher.mjs +804 -157
- package/scripts/daemon/health.mjs +14 -1
- package/scripts/daemon/lib/session-router.mjs +310 -42
- package/scripts/daemon/maestro-daemon.mjs +11 -0
- package/scripts/daemon/prompt-builder.mjs +121 -12
- package/scripts/daemon/responder.mjs +315 -146
- package/scripts/daemon/sdk-version.mjs +98 -16
- package/scripts/eval/probe-gateway.mjs +635 -0
- package/scripts/eval/replay/extract.mjs +270 -0
- package/scripts/eval/replay/grade.mjs +260 -0
- package/scripts/eval/replay/lib/config.mjs +50 -0
- package/scripts/eval/replay/lib/effects.mjs +65 -0
- package/scripts/eval/replay/lib/fixture.mjs +188 -0
- package/scripts/eval/replay/lib/judge.mjs +72 -0
- package/scripts/eval/replay/lib/redact.mjs +136 -0
- package/scripts/eval/replay/lib/sandbox.mjs +170 -0
- package/scripts/eval/replay/lib/schema-check.mjs +63 -0
- package/scripts/eval/replay/lib/transcript.mjs +76 -0
- package/scripts/eval/replay/mcp-replay-stub.mjs +101 -0
- package/scripts/eval/replay/report.mjs +185 -0
- package/scripts/eval/replay/run.mjs +404 -0
- package/scripts/fleet/rollout.mjs +1094 -0
- package/scripts/hooks/pre-send-audit.sh +36 -245
- package/scripts/hooks/pre-write-yaml-validate.mjs +275 -0
- package/scripts/hooks/validate-state-yaml.sh +190 -0
- package/scripts/huddle/huddle-llm.mjs +361 -0
- package/scripts/huddle/huddle-server.mjs +46 -121
- package/scripts/local-triggers/autoupdate.sh +448 -78
- package/scripts/local-triggers/run-trigger.sh +13 -0
- package/scripts/maintenance/pin-integrity.mjs +364 -0
- package/scripts/poll-slack-events.sh +41 -9
- package/scripts/poller/slack-socket-mode.mjs +28 -3
- package/scripts/session/supervisor.mjs +80 -13
- package/scripts/spawn-session.sh +13 -0
- package/bin/maestro.test.mjs +0 -1574
- package/lib/action-executor.test.mjs +0 -871
- package/lib/archetype.test.mjs +0 -132
- package/lib/assurance/plan-note.test.mjs +0 -234
- package/lib/assurance/room-budget.test.mjs +0 -486
- package/lib/assurance/tier.test.mjs +0 -174
- package/lib/autonomy.test.mjs +0 -66
- package/lib/backlog.test.mjs +0 -302
- package/lib/backup/policy.test.mjs +0 -305
- package/lib/budget-escalate.test.mjs +0 -232
- package/lib/budget-guard.envelope.test.mjs +0 -476
- package/lib/budget-guard.test.mjs +0 -427
- package/lib/cadence-bus-requeue.test.mjs +0 -83
- package/lib/cadence-bus-schedule.test.mjs +0 -194
- package/lib/cadence-bus.test.mjs +0 -720
- package/lib/cadences.test.mjs +0 -230
- package/lib/capability/inventory.test.mjs +0 -232
- package/lib/capability.test.mjs +0 -78
- package/lib/channels/base-adapter.test.mjs +0 -590
- package/lib/channels/channels.test.mjs +0 -371
- package/lib/channels/contract.test.mjs +0 -162
- package/lib/channels/inbox-item.test.mjs +0 -368
- package/lib/channels/orgmail/adapter.test.mjs +0 -448
- package/lib/channels/pairing.test.mjs +0 -270
- package/lib/channels/repeat-suppressor.test.mjs +0 -134
- package/lib/channels/slack-adapter.test.mjs +0 -212
- package/lib/channels/telegram-adapter.test.mjs +0 -306
- package/lib/channels/voice/adapter.test.mjs +0 -278
- package/lib/channels/whatsapp/adapter-baileys.test.mjs +0 -359
- package/lib/channels/whatsapp/baileys-typing.test.mjs +0 -154
- package/lib/charter.test.mjs +0 -89
- package/lib/claude-bin.test.mjs +0 -131
- package/lib/cli/board.test.mjs +0 -227
- package/lib/cli/design.test.mjs +0 -270
- package/lib/cli/doctor-checks.test.mjs +0 -336
- package/lib/cli/global-setup-extras.test.mjs +0 -462
- package/lib/cli/inbox.test.mjs +0 -230
- package/lib/cli/session-ack.test.mjs +0 -63
- package/lib/cli/session.test.mjs +0 -613
- package/lib/collective/capture.test.mjs +0 -121
- package/lib/collective/cards.test.mjs +0 -114
- package/lib/collective/config.test.mjs +0 -123
- package/lib/collective/global-config.test.mjs +0 -220
- package/lib/collective/global-skills.test.mjs +0 -126
- package/lib/collective/presence.test.mjs +0 -95
- package/lib/collective/recall.test.mjs +0 -116
- package/lib/collective/vendor-skills.test.mjs +0 -306
- package/lib/comms/send-gate.test.mjs +0 -770
- package/lib/comms.test.mjs +0 -41
- package/lib/cost/ledger-row.test.mjs +0 -183
- package/lib/design/design-md.test.mjs +0 -318
- package/lib/design/fixtures/DESIGN.golden.md +0 -238
- package/lib/design/fixtures/PRODUCT.golden.md +0 -67
- package/lib/design/fixtures/foundation.json +0 -133
- package/lib/design/refresh-gate.test.mjs +0 -144
- package/lib/design/write.test.mjs +0 -241
- package/lib/diagnostics/alerts.test.mjs +0 -318
- package/lib/diagnostics/backup-freshness.test.mjs +0 -185
- package/lib/diagnostics/counters.test.mjs +0 -206
- package/lib/diagnostics/events.test.mjs +0 -290
- package/lib/diagnostics/otel.test.mjs +0 -196
- package/lib/diagnostics/trace.test.mjs +0 -251
- package/lib/env-compat.test.mjs +0 -104
- package/lib/execution/disposition.test.mjs +0 -553
- package/lib/execution/drive.test.mjs +0 -270
- package/lib/execution/effects.test.mjs +0 -344
- package/lib/execution/intake.test.mjs +0 -389
- package/lib/execution/journal.test.mjs +0 -261
- package/lib/execution/match.test.mjs +0 -235
- package/lib/execution/pipeline.test.mjs +0 -392
- package/lib/execution/route.test.mjs +0 -186
- package/lib/execution/surface-policy.test.mjs +0 -162
- package/lib/fs-atomic.test.mjs +0 -72
- package/lib/fs-ownership.test.mjs +0 -158
- package/lib/goals/admission.test.mjs +0 -164
- package/lib/goals/classify.test.mjs +0 -167
- package/lib/goals/collaborate.test.mjs +0 -336
- package/lib/goals/gaps.test.mjs +0 -284
- package/lib/goals/loop.test.mjs +0 -845
- package/lib/hooks/bus.test.mjs +0 -387
- package/lib/identity/persona.test.mjs +0 -142
- package/lib/kpi-sensors.test.mjs +0 -278
- package/lib/kpi.test.mjs +0 -244
- package/lib/learning/config.test.mjs +0 -75
- package/lib/learning/counters.test.mjs +0 -69
- package/lib/learning/curator-consolidate.test.mjs +0 -238
- package/lib/learning/curator.test.mjs +0 -106
- package/lib/learning/reflect.test.mjs +0 -0
- package/lib/learning/session-index.test.mjs +0 -125
- package/lib/learning/skill-writer.test.mjs +0 -210
- package/lib/mandate/audit.test.mjs +0 -195
- package/lib/mandate/contract.test.mjs +0 -185
- package/lib/mandate/derive.test.mjs +0 -274
- package/lib/mandate/model.test.mjs +0 -164
- package/lib/mandate/refresh.test.mjs +0 -389
- package/lib/mcp/server.test.mjs +0 -426
- package/lib/model-router/auth-profiles.test.mjs +0 -580
- package/lib/model-router/catalog.test.mjs +0 -385
- package/lib/model-router/economics.test.mjs +0 -438
- package/lib/model-router/failover.test.mjs +0 -439
- package/lib/model-router/health.test.mjs +0 -338
- package/lib/model-router/integration-coverage.test.mjs +0 -831
- package/lib/model-router/integration.test.mjs +0 -564
- package/lib/model-router/ledger.test.mjs +0 -415
- package/lib/model-router/llm-task.test.mjs +0 -392
- package/lib/model-router/org-credentials.test.mjs +0 -265
- package/lib/model-router/pricing-refresh.test.mjs +0 -286
- package/lib/model-router/reconcile.test.mjs +0 -316
- package/lib/model-router/repair.test.mjs +0 -180
- package/lib/model-router/spawn.test.mjs +0 -446
- package/lib/model-router/taxonomy.test.mjs +0 -410
- package/lib/model-router.test.mjs +0 -1207
- package/lib/org/activity.test.mjs +0 -134
- package/lib/org/approvals.test.mjs +0 -216
- package/lib/org/awareness.test.mjs +0 -159
- package/lib/org/board-mine-cache.test.mjs +0 -53
- package/lib/org/board.test.mjs +0 -187
- package/lib/org/bootstrap-context.test.mjs +0 -153
- package/lib/org/client.test.mjs +0 -1206
- package/lib/org/cohort-client.test.mjs +0 -126
- package/lib/org/cost-sync.test.mjs +0 -153
- package/lib/org/doctor.test.mjs +0 -346
- package/lib/org/engagement-ledger.test.mjs +0 -112
- package/lib/org/engagement.test.mjs +0 -739
- package/lib/org/handoff.test.mjs +0 -269
- package/lib/org/inbound/directedness.test.mjs +0 -668
- package/lib/org/inbound/facts.test.mjs +0 -471
- package/lib/org/inbound/hydrate.test.mjs +0 -453
- package/lib/org/inbound/index.test.mjs +0 -429
- package/lib/org/inbound/project.test.mjs +0 -287
- package/lib/org/integration-tools.test.mjs +0 -160
- package/lib/org/keys.test.mjs +0 -92
- package/lib/org/knowledge.test.mjs +0 -326
- package/lib/org/leases.test.mjs +0 -235
- package/lib/org/mesh-directives.test.mjs +0 -110
- package/lib/org/mesh-integration.test.mjs +0 -127
- package/lib/org/mesh.test.mjs +0 -400
- package/lib/org/messaging.test.mjs +0 -471
- package/lib/org/param-contract.test.mjs +0 -477
- package/lib/org/policy.test.mjs +0 -237
- package/lib/org/protocol.checksum.test.mjs +0 -90
- package/lib/org/protocol.test.mjs +0 -323
- package/lib/org/push.test.mjs +0 -792
- package/lib/org/registry.test.mjs +0 -100
- package/lib/org/resource-tools.test.mjs +0 -361
- package/lib/org/tool-access.test.mjs +0 -144
- package/lib/org/tool-surface-integration.test.mjs +0 -120
- package/lib/org/tool-surface.test.mjs +0 -1268
- package/lib/org/typing.test.mjs +0 -291
- package/lib/org/ui-parity.test.mjs +0 -560
- package/lib/org/verify.test.mjs +0 -194
- package/lib/org/work-ledger.test.mjs +0 -273
- package/lib/plan/adoption-e2e.test.mjs +0 -366
- package/lib/plan/budget-enforcement.test.mjs +0 -400
- package/lib/plan/compile.test.mjs +0 -382
- package/lib/plan/emit.test.mjs +0 -269
- package/lib/plan/explain.test.mjs +0 -188
- package/lib/prompts/parallelism.test.mjs +0 -177
- package/lib/rag/rag.test.mjs +0 -505
- package/lib/rate-guard.test.mjs +0 -272
- package/lib/reactive-gate.test.mjs +0 -57
- package/lib/render.test.mjs +0 -68
- package/lib/resource-governor.test.mjs +0 -488
- package/lib/scheduling/dynamic-jobs.test.mjs +0 -344
- package/lib/scheduling/jitter.test.mjs +0 -140
- package/lib/secrets/broker.test.mjs +0 -280
- package/lib/secrets/providers.test.mjs +0 -274
- package/lib/security/audit-engine.test.mjs +0 -424
- package/lib/security/coerce-args.test.mjs +0 -281
- package/lib/security/dangerous-tools.test.mjs +0 -68
- package/lib/security/external-content.test.mjs +0 -84
- package/lib/security/redact.test.mjs +0 -441
- package/lib/security/secret-equal.test.mjs +0 -55
- package/lib/session/config.test.mjs +0 -92
- package/lib/session/feed-core.test.mjs +0 -198
- package/lib/session/first-run.test.mjs +0 -121
- package/lib/session/frontdoor.test.mjs +0 -205
- package/lib/session/handoffs.test.mjs +0 -183
- package/lib/session/identity.test.mjs +0 -180
- package/lib/session/inbox-claims.test.mjs +0 -286
- package/lib/session/launch-args.test.mjs +0 -157
- package/lib/session/liveness.test.mjs +0 -100
- package/lib/session/status-summary.test.mjs +0 -118
- package/lib/session-permissions.test.mjs +0 -120
- package/lib/setup/claude-probe.test.mjs +0 -187
- package/lib/setup/completeness.test.mjs +0 -110
- package/lib/setup/context-pack.test.mjs +0 -89
- package/lib/setup/enrich.test.mjs +0 -115
- package/lib/setup/enroll-from-cohort.test.mjs +0 -300
- package/lib/setup/integration.test.mjs +0 -162
- package/lib/setup/io.test.mjs +0 -77
- package/lib/setup/runner.test.mjs +0 -132
- package/lib/setup/sections/identity.test.mjs +0 -234
- package/lib/setup/sections/inventory.test.mjs +0 -198
- package/lib/setup/sections/learning.test.mjs +0 -81
- package/lib/setup/sections/mandate.test.mjs +0 -388
- package/lib/setup/sections/messaging.test.mjs +0 -127
- package/lib/setup/sections/model.test.mjs +0 -240
- package/lib/setup/sections/org.test.mjs +0 -346
- package/lib/setup/sections/orgmail.test.mjs +0 -118
- package/lib/setup/sections/recovery.test.mjs +0 -98
- package/lib/setup/sections/subagents.test.mjs +0 -429
- package/lib/setup/sections/verify.test.mjs +0 -175
- package/lib/setup/sot.test.mjs +0 -81
- package/lib/setup/state.test.mjs +0 -115
- package/lib/singleton.test.mjs +0 -151
- package/lib/subagents/cli.test.mjs +0 -389
- package/lib/subagents/client.test.mjs +0 -309
- package/lib/subagents/gap.test.mjs +0 -234
- package/lib/subagents/lock.test.mjs +0 -248
- package/lib/subagents/manifest.test.mjs +0 -175
- package/lib/subagents/refs.test.mjs +0 -204
- package/lib/subagents/resolve.test.mjs +0 -422
- package/lib/subagents/schema.test.mjs +0 -328
- package/lib/telemetry/alerts.test.mjs +0 -109
- package/lib/telemetry/collect.test.mjs +0 -1274
- package/lib/tool-definitions-integration.test.mjs +0 -83
- package/lib/tool-definitions.test.mjs +0 -437
- package/lib/upgrade/global-refresh.test.mjs +0 -65
- package/lib/upgrade/launchd-reconcile.test.mjs +0 -272
- package/lib/upgrade/post-steps.test.mjs +0 -200
- package/lib/upgrade/verify.test.mjs +0 -164
- package/lib/util/fetch-timeout.test.mjs +0 -202
- package/lib/util/reconnect.test.mjs +0 -369
- package/lib/util/unhandled.test.mjs +0 -216
- package/lib/voice/outbound.test.mjs +0 -69
- package/lib/voice/session-rotation.test.mjs +0 -114
- package/lib/voice/stt.test.mjs +0 -226
- package/lib/voice/voice.test.mjs +0 -990
- package/scripts/cadence/enqueue-cadence-tick.test.mjs +0 -187
- package/scripts/ci/check-docs-accuracy.test.mjs +0 -409
- package/scripts/ci/check-durable-write-seam.test.mjs +0 -90
- package/scripts/ci/check-no-build-artifacts.test.mjs +0 -71
- package/scripts/ci/check-no-residual-identity.test.mjs +0 -202
- package/scripts/ci/check-skill-packs.test.mjs +0 -495
- package/scripts/ci/check-subagent-frontmatter.test.mjs +0 -124
- package/scripts/ci/check.test.mjs +0 -194
- package/scripts/ci/conformance-org-api.test.mjs +0 -425
- package/scripts/cloud-relay/voice/relay-identity.test.mjs +0 -96
- package/scripts/collective/hook-runner.test.mjs +0 -173
- package/scripts/cost/fleet-digest.test.mjs +0 -207
- package/scripts/cost/track-claude-usage-pricing.test.mjs +0 -183
- package/scripts/cost/track-claude-usage.test.mjs +0 -148
- package/scripts/daemon/agent-daemon-board-mine.test.mjs +0 -96
- package/scripts/daemon/agent-daemon-design.test.mjs +0 -238
- package/scripts/daemon/agent-daemon-frontdoor.test.mjs +0 -60
- package/scripts/daemon/agent-daemon.test.mjs +0 -995
- package/scripts/daemon/assurance-e2e.test.mjs +0 -613
- package/scripts/daemon/assurance.test.mjs +0 -1791
- package/scripts/daemon/board-mirror.test.mjs +0 -165
- package/scripts/daemon/cadence-consumer-frontdoor.test.mjs +0 -393
- package/scripts/daemon/cadence-consumer-governance.test.mjs +0 -276
- package/scripts/daemon/cadence-consumer.test.mjs +0 -776
- package/scripts/daemon/cadence-handlers.test.mjs +0 -837
- package/scripts/daemon/classifier-identity.test.mjs +0 -137
- package/scripts/daemon/classifier.test.mjs +0 -266
- package/scripts/daemon/classify-kind.test.mjs +0 -40
- package/scripts/daemon/context-compiler.test.mjs +0 -300
- package/scripts/daemon/deliver.test.mjs +0 -564
- package/scripts/daemon/dispatcher-cooldown.test.mjs +0 -122
- package/scripts/daemon/dispatcher-governance.test.mjs +0 -1013
- package/scripts/daemon/dispatcher-resume.test.mjs +0 -166
- package/scripts/daemon/execution-ladder.test.mjs +0 -470
- package/scripts/daemon/goal-steward-cadence.test.mjs +0 -312
- package/scripts/daemon/inbox-deferral-session.test.mjs +0 -49
- package/scripts/daemon/inbox-deferral.test.mjs +0 -336
- package/scripts/daemon/inbox-wake.test.mjs +0 -199
- package/scripts/daemon/integration.test.mjs +0 -149
- package/scripts/daemon/lib/self-echo.test.mjs +0 -153
- package/scripts/daemon/lib/session-router.test.mjs +0 -295
- package/scripts/daemon/prompt-builder-preamble.test.mjs +0 -210
- package/scripts/daemon/prompt-builder.test.mjs +0 -344
- package/scripts/daemon/responder-cost.test.mjs +0 -68
- package/scripts/daemon/responder-history.test.mjs +0 -185
- package/scripts/daemon/sdk-version.test.mjs +0 -31
- package/scripts/daemon/session-lock.test.mjs +0 -252
- package/scripts/daemon/session-outcomes.test.mjs +0 -533
- package/scripts/daemon/typing-registry.test.mjs +0 -102
- package/scripts/hooks/pre-send-audit.test.mjs +0 -354
- package/scripts/huddle/huddle-prompt.test.mjs +0 -176
- package/scripts/local-triggers/autoupdate.test.mjs +0 -518
- package/scripts/local-triggers/generate-plists.test.mjs +0 -456
- package/scripts/media-generation/brand-clause.test.mjs +0 -135
- package/scripts/org/send-orgmail.first-contact.test.mjs +0 -102
- package/scripts/poller/inbox-privilege-injection.test.mjs +0 -167
- package/scripts/poller/inbox-scan-poller.test.mjs +0 -295
- package/scripts/poller/lib/cloud-relay-dedup.test.mjs +0 -133
- package/scripts/poller/slack-socket-mode.test.mjs +0 -805
- package/scripts/poller-launchd/install.test.mjs +0 -243
- package/scripts/restore-from-backup.test.mjs +0 -181
- package/scripts/session/feed.test.mjs +0 -196
- package/scripts/session/supervisor-sh.test.mjs +0 -218
- package/scripts/session/supervisor.test.mjs +0 -482
- package/scripts/setup/configure-macos.test.mjs +0 -306
- package/scripts/setup/gen-subagent-manifest.test.mjs +0 -124
- package/scripts/setup/generate-agent-package-json.test.mjs +0 -143
- package/scripts/setup/generate-capability.test.mjs +0 -134
- package/scripts/setup/init-agent.test.mjs +0 -370
- package/scripts/setup/init-skill-marketplace.test.mjs +0 -193
- package/scripts/vendor/sync-skill-packs.test.mjs +0 -103
- package/scripts/watchdog/memory-watchdog.test.mjs +0 -64
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* lib/runtime/child-env.mjs — the ONE child-env builder for every runtime spawn.
|
|
3
|
+
*
|
|
4
|
+
* Every lane that starts an agent runtime (today the `claude` binary) builds its
|
|
5
|
+
* child environment here, through `buildRuntimeEnv`. There are two shapes:
|
|
6
|
+
*
|
|
7
|
+
* STOCK no retarget. The child keeps the seat's own Claude credential
|
|
8
|
+
* (`CLAUDE_CODE_OAUTH_TOKEN`, keychain, or a Console key the lane
|
|
9
|
+
* owns). Foreign `*_API_KEY` / `*_AUTH_TOKEN` / `*_SECRET` /
|
|
10
|
+
* `*_ACCESS_KEY` / `*_PRIVATE_KEY` values are scrubbed (§7.3).
|
|
11
|
+
*
|
|
12
|
+
* RETARGET the router pointed the session at a third-party backend
|
|
13
|
+
* (`ANTHROPIC_BASE_URL` in the retarget set). This is where the old
|
|
14
|
+
* builder leaked: its scrub regex ends in `_AUTH_TOKEN$`, which does
|
|
15
|
+
* not match `CLAUDE_CODE_OAUTH_TOKEN`, so a Max subscription token
|
|
16
|
+
* rode into a child whose base URL was someone else's server. With
|
|
17
|
+
* only a base URL set, "a saved claude.ai login remains the active
|
|
18
|
+
* credential" — the token would have been sent to that server
|
|
19
|
+
* (F1 §5.3). A retarget therefore ALWAYS:
|
|
20
|
+
* - scrubs `CLAUDE_CODE_OAUTH_*` and every `*_OAUTH_TOKEN`;
|
|
21
|
+
* - scrubs every inherited `ANTHROPIC_*` variable, then injects
|
|
22
|
+
* only the allowlisted retarget keys;
|
|
23
|
+
* - refuses (a returned error, never a throw) when the retarget
|
|
24
|
+
* carries no usable `ANTHROPIC_AUTH_TOKEN`, or carries a
|
|
25
|
+
* subscription OAuth token (`sk-ant-oat…`) as that token;
|
|
26
|
+
* - forces `ANTHROPIC_API_KEY=""` (no keychain fallthrough) and
|
|
27
|
+
* `CLAUDE_CODE_ATTRIBUTION_HEADER=0` (a third-party prompt cache
|
|
28
|
+
* is poisoned by the per-request attribution header).
|
|
29
|
+
*
|
|
30
|
+
* Pure: no process.env read, no clock, no I/O. The caller passes the base env.
|
|
31
|
+
*
|
|
32
|
+
* @module lib/runtime/child-env
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
"use strict";
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Env keys a retarget set may introduce. Everything else in a retarget set is
|
|
39
|
+
* dropped, so an internal marker (e.g. `__credFingerprint`) can never reach a
|
|
40
|
+
* child.
|
|
41
|
+
*/
|
|
42
|
+
export const RETARGET_KEYS = Object.freeze(new Set([
|
|
43
|
+
"ANTHROPIC_BASE_URL",
|
|
44
|
+
"ANTHROPIC_AUTH_TOKEN",
|
|
45
|
+
"ANTHROPIC_API_KEY",
|
|
46
|
+
"ANTHROPIC_MODEL",
|
|
47
|
+
"ANTHROPIC_SMALL_FAST_MODEL",
|
|
48
|
+
"CLAUDE_CODE_ATTRIBUTION_HEADER",
|
|
49
|
+
"CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS",
|
|
50
|
+
// Slot → model mapping (design §4.7: ANTHROPIC_SMALL_FAST_MODEL is deprecated).
|
|
51
|
+
"ANTHROPIC_DEFAULT_OPUS_MODEL",
|
|
52
|
+
"ANTHROPIC_DEFAULT_SONNET_MODEL",
|
|
53
|
+
"ANTHROPIC_DEFAULT_HAIKU_MODEL",
|
|
54
|
+
"ANTHROPIC_DEFAULT_FABLE_MODEL",
|
|
55
|
+
"CLAUDE_CODE_SUBAGENT_MODEL",
|
|
56
|
+
// The cohort-llm helper credential (see COHORT_HELPER_KEY below).
|
|
57
|
+
"COHORT_LLM_BASE_URL",
|
|
58
|
+
"COHORT_LLM_API_KEY_HELPER",
|
|
59
|
+
"CLAUDE_CODE_API_KEY_HELPER_TTL_MS",
|
|
60
|
+
]));
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* A cohort-llm retarget authenticates with an `apiKeyHelper` that prints the
|
|
64
|
+
* seat's short-lived token, not with a static ANTHROPIC_AUTH_TOKEN. Claude Code
|
|
65
|
+
* ranks ANTHROPIC_AUTH_TOKEN ABOVE apiKeyHelper (code.claude.com/docs/en/iam,
|
|
66
|
+
* "Authentication precedence"), so a static token would pin the session to a
|
|
67
|
+
* token that dies after at most an hour. The helper counts as the retarget's
|
|
68
|
+
* credential only when the retarget names the SAME gateway in
|
|
69
|
+
* COHORT_LLM_BASE_URL and ANTHROPIC_BASE_URL — a Cohort seat token is never
|
|
70
|
+
* handed to a third-party base URL. The runtime adapter turns the helper
|
|
71
|
+
* command into `--settings {"apiKeyHelper": …}`.
|
|
72
|
+
*/
|
|
73
|
+
export const COHORT_HELPER_KEY = "COHORT_LLM_API_KEY_HELPER";
|
|
74
|
+
|
|
75
|
+
const trimUrl = (u) => (typeof u === "string" ? u.trim().replace(/\/+$/, "") : "");
|
|
76
|
+
|
|
77
|
+
/** Does this retarget authenticate through the cohort-llm apiKeyHelper? */
|
|
78
|
+
export function isCohortHelperRetarget(retarget) {
|
|
79
|
+
const set = retarget && typeof retarget === "object" ? retarget : {};
|
|
80
|
+
const helper = set[COHORT_HELPER_KEY];
|
|
81
|
+
return isRetarget(set) && typeof helper === "string" && helper.trim() !== "" &&
|
|
82
|
+
trimUrl(set.COHORT_LLM_BASE_URL) !== "" && trimUrl(set.COHORT_LLM_BASE_URL) === trimUrl(set.ANTHROPIC_BASE_URL);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** Prefix of a Claude subscription OAuth token (`claude setup-token` output). */
|
|
86
|
+
const SUBSCRIPTION_TOKEN_PREFIX = /^sk-ant-oat/i;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Credential-shaped in EVERY shape (stock and retarget). Unchanged from the
|
|
90
|
+
* historical §7.3 scrub so the stock path stays byte-compatible: it keeps the
|
|
91
|
+
* seat's `CLAUDE_CODE_OAUTH_TOKEN`, which a stock Anthropic spawn needs.
|
|
92
|
+
* @param {string} k
|
|
93
|
+
*/
|
|
94
|
+
export function isCredentialKey(k) {
|
|
95
|
+
return /(_API_KEY|_AUTH_TOKEN|_SECRET|_ACCESS_KEY|_PRIVATE_KEY)$/i.test(k) || k === "ANTHROPIC_API_KEY";
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Additionally scrubbed on a retarget: the Claude subscription credential in
|
|
100
|
+
* any spelling, and the whole inherited `ANTHROPIC_*` namespace (credentials,
|
|
101
|
+
* a stale base URL, custom headers) — the retarget set re-injects what the
|
|
102
|
+
* child actually needs.
|
|
103
|
+
* @param {string} k
|
|
104
|
+
*/
|
|
105
|
+
export function isRetargetScrubbedKey(k) {
|
|
106
|
+
return (
|
|
107
|
+
isCredentialKey(k) ||
|
|
108
|
+
/^CLAUDE_CODE_OAUTH/i.test(k) ||
|
|
109
|
+
/_OAUTH_TOKEN$/i.test(k) ||
|
|
110
|
+
/^ANTHROPIC_/i.test(k) ||
|
|
111
|
+
/^COHORT_LLM_TOKEN$/i.test(k)
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** Does a retarget set actually point the child at another backend? */
|
|
116
|
+
export function isRetarget(retarget) {
|
|
117
|
+
return !!(retarget && typeof retarget === "object" &&
|
|
118
|
+
typeof retarget.ANTHROPIC_BASE_URL === "string" && retarget.ANTHROPIC_BASE_URL.trim() !== "");
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Build a child env.
|
|
123
|
+
*
|
|
124
|
+
* @param {object} o
|
|
125
|
+
* @param {object} o.baseEnv the parent env to start from (never mutated)
|
|
126
|
+
* @param {object} [o.retarget] the router's envForSpawn, or {} / null
|
|
127
|
+
* @param {boolean} [o.keepAnthropicApiKey=false] stock only: keep the parent's
|
|
128
|
+
* ANTHROPIC_API_KEY (a Console key the lane owns) instead of scrubbing it
|
|
129
|
+
* @returns {{ok:true, env:object, retargeting:boolean} |
|
|
130
|
+
* {ok:false, error:{code:"retarget_without_token"|"retarget_with_subscription_token", message:string}}}
|
|
131
|
+
*/
|
|
132
|
+
export function buildRuntimeEnv({ baseEnv, retarget = {}, keepAnthropicApiKey = false } = {}) {
|
|
133
|
+
const src = baseEnv && typeof baseEnv === "object" ? baseEnv : {};
|
|
134
|
+
const set = retarget && typeof retarget === "object" ? retarget : {};
|
|
135
|
+
const retargeting = isRetarget(set);
|
|
136
|
+
|
|
137
|
+
const viaHelper = retargeting && isCohortHelperRetarget(set);
|
|
138
|
+
if (retargeting && typeof set[COHORT_HELPER_KEY] === "string" && set[COHORT_HELPER_KEY].trim() !== "" && !viaHelper) {
|
|
139
|
+
return {
|
|
140
|
+
ok: false,
|
|
141
|
+
error: {
|
|
142
|
+
code: "retarget_helper_mismatch",
|
|
143
|
+
message: `refusing to retarget to ${set.ANTHROPIC_BASE_URL}: the cohort-llm key helper is only valid for the gateway named in COHORT_LLM_BASE_URL`,
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
if (retargeting && !viaHelper) {
|
|
148
|
+
const token = set.ANTHROPIC_AUTH_TOKEN;
|
|
149
|
+
if (typeof token !== "string" || token.trim() === "") {
|
|
150
|
+
return {
|
|
151
|
+
ok: false,
|
|
152
|
+
error: {
|
|
153
|
+
code: "retarget_without_token",
|
|
154
|
+
message: `refusing to retarget to ${set.ANTHROPIC_BASE_URL}: no ANTHROPIC_AUTH_TOKEN for that backend (the seat's own Claude credential is never sent to a third party)`,
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
if (SUBSCRIPTION_TOKEN_PREFIX.test(token.trim())) {
|
|
159
|
+
return {
|
|
160
|
+
ok: false,
|
|
161
|
+
error: {
|
|
162
|
+
code: "retarget_with_subscription_token",
|
|
163
|
+
message: `refusing to retarget to ${set.ANTHROPIC_BASE_URL}: the token is a Claude subscription OAuth token, which may never be sent to a third-party endpoint`,
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const out = {};
|
|
170
|
+
for (const [k, v] of Object.entries(src)) {
|
|
171
|
+
if (retargeting ? isRetargetScrubbedKey(k) : isCredentialKey(k)) continue;
|
|
172
|
+
out[k] = v;
|
|
173
|
+
}
|
|
174
|
+
if (!retargeting && keepAnthropicApiKey && typeof src.ANTHROPIC_API_KEY === "string") {
|
|
175
|
+
out.ANTHROPIC_API_KEY = src.ANTHROPIC_API_KEY;
|
|
176
|
+
}
|
|
177
|
+
for (const [k, v] of Object.entries(set)) {
|
|
178
|
+
if (RETARGET_KEYS.has(k)) out[k] = v;
|
|
179
|
+
}
|
|
180
|
+
if (retargeting) {
|
|
181
|
+
// Empty string, NOT unset: an unset key lets Claude Code fall through to a
|
|
182
|
+
// keychain login against api.anthropic.com.
|
|
183
|
+
out.ANTHROPIC_API_KEY = "";
|
|
184
|
+
out.CLAUDE_CODE_ATTRIBUTION_HEADER = "0";
|
|
185
|
+
// The helper must be the credential in use: a static token would outrank it.
|
|
186
|
+
if (viaHelper) delete out.ANTHROPIC_AUTH_TOKEN;
|
|
187
|
+
}
|
|
188
|
+
return { ok: true, env: out, retargeting, viaHelper };
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export default { buildRuntimeEnv, isCredentialKey, isRetargetScrubbedKey, isRetarget, isCohortHelperRetarget, RETARGET_KEYS, COHORT_HELPER_KEY };
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* lib/runtime/legacy-shell-guard.mjs — the legacy shell lanes are retired for engine-cohort seats (W4-E1, row 36).
|
|
4
|
+
*
|
|
5
|
+
* Three shell scripts run the `claude` binary directly, outside the runtime
|
|
6
|
+
* adapter: scripts/spawn-session.sh, scripts/continuous-monitor.sh and
|
|
7
|
+
* scripts/local-triggers/run-trigger.sh. They are RETIRED for a seat whose
|
|
8
|
+
* config/agent.json `runtime.engine` is `cohort`, not ported:
|
|
9
|
+
*
|
|
10
|
+
* - each has a maintained JS successor that already goes through
|
|
11
|
+
* `buildSpawn` with the seat's engine — `maestro session spawn` (peers) and
|
|
12
|
+
* the dispatcher for spawn-session.sh, the poller + dispatcher for
|
|
13
|
+
* continuous-monitor.sh, the cadence bus
|
|
14
|
+
* (`scripts/cadence/enqueue-cadence-tick.mjs`) for run-trigger.sh;
|
|
15
|
+
* - no daemon lane, generated plist or cadence calls them (doctor already
|
|
16
|
+
* flags plists that still call run-trigger.sh);
|
|
17
|
+
* - porting them would keep a third spawn path to hold at parity with the
|
|
18
|
+
* adapter (argv mapping, credential scrub, send gate, spend cap) for tools
|
|
19
|
+
* an operator runs by hand.
|
|
20
|
+
*
|
|
21
|
+
* Each script calls this guard first. On an engine-cohort seat the guard
|
|
22
|
+
* refuses (exit 3, the reason on stderr) — running `claude` there would spend
|
|
23
|
+
* the seat's Anthropic credential on work the org routed to cohort-llm and
|
|
24
|
+
* bypass the engine's in-process send gate. On a claude seat it exits 0 and the
|
|
25
|
+
* script behaves exactly as before. `maestro doctor` warns on engine-cohort
|
|
26
|
+
* seats that the lanes are retired.
|
|
27
|
+
*
|
|
28
|
+
* node lib/runtime/legacy-shell-guard.mjs <script-name> <agent-root>
|
|
29
|
+
*
|
|
30
|
+
* @module lib/runtime/legacy-shell-guard
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
"use strict";
|
|
34
|
+
|
|
35
|
+
import { pathToFileURL } from "node:url";
|
|
36
|
+
import { realpathSync } from "node:fs";
|
|
37
|
+
import { readSeatEngine, SHELL_LEGACY_LANES } from "./adapter.mjs";
|
|
38
|
+
|
|
39
|
+
/** The exit code a retired lane stops with. */
|
|
40
|
+
export const LEGACY_LANE_REFUSED_EXIT = 3;
|
|
41
|
+
|
|
42
|
+
/** The successor to use instead of each retired script. */
|
|
43
|
+
export const LEGACY_LANE_SUCCESSORS = Object.freeze({
|
|
44
|
+
"spawn-session.sh": "maestro session spawn --name <slug> \"<prompt>\" (or let the dispatcher take the work)",
|
|
45
|
+
"continuous-monitor.sh": "the maestro daemon's pollers and dispatcher",
|
|
46
|
+
"run-trigger.sh": "node scripts/cadence/enqueue-cadence-tick.mjs <trigger> --source=manual",
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* May a legacy shell lane run on this seat? PURE.
|
|
51
|
+
* @param {{engine:string, script:string}} o
|
|
52
|
+
* @returns {{allowed:true}|{allowed:false, exitCode:number, message:string}}
|
|
53
|
+
*/
|
|
54
|
+
export function legacyShellLaneVerdict({ engine, script }) {
|
|
55
|
+
if (engine !== "cohort") return { allowed: true };
|
|
56
|
+
const name = String(script || "").split("/").pop() || "this script";
|
|
57
|
+
const successor = LEGACY_LANE_SUCCESSORS[name];
|
|
58
|
+
return {
|
|
59
|
+
allowed: false,
|
|
60
|
+
exitCode: LEGACY_LANE_REFUSED_EXIT,
|
|
61
|
+
message:
|
|
62
|
+
`${name} is retired on this seat: runtime.engine is "cohort", and this legacy lane runs the claude binary directly, ` +
|
|
63
|
+
`outside the runtime adapter.${successor ? ` Use ${successor}.` : ""}`,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** The retired scripts' names, from the adapter's register. */
|
|
68
|
+
export function legacyLaneNames() {
|
|
69
|
+
return SHELL_LEGACY_LANES.map((l) => l.path.split("/").pop());
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* The CLI edge.
|
|
74
|
+
* @param {string[]} argv [script, agentRoot]
|
|
75
|
+
* @param {{readSeatEngine?:(root:string)=>string, stderr?:{write:(s:string)=>void}}} [deps]
|
|
76
|
+
* @returns {number} exit code
|
|
77
|
+
*/
|
|
78
|
+
export function main(argv, deps = {}) {
|
|
79
|
+
const [script, agentRoot] = argv;
|
|
80
|
+
if (!script || !agentRoot) {
|
|
81
|
+
(deps.stderr || process.stderr).write("usage: legacy-shell-guard.mjs <script-name> <agent-root>\n");
|
|
82
|
+
return 2;
|
|
83
|
+
}
|
|
84
|
+
const v = legacyShellLaneVerdict({ engine: (deps.readSeatEngine || readSeatEngine)(agentRoot), script });
|
|
85
|
+
if (v.allowed) return 0;
|
|
86
|
+
(deps.stderr || process.stderr).write(`${v.message}\n`);
|
|
87
|
+
return v.exitCode;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const isEntry = (() => {
|
|
91
|
+
try {
|
|
92
|
+
return process.argv[1] && import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href;
|
|
93
|
+
} catch {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
})();
|
|
97
|
+
if (isEntry) process.exitCode = main(process.argv.slice(2));
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* lib/runtime/seat-engine.mjs — which engine a spawn runs, decided once per spawn (W4-E1, CF-44, row 5).
|
|
3
|
+
*
|
|
4
|
+
* Every JavaScript site that launches a session — the supervisor's main
|
|
5
|
+
* session, `maestro session spawn` peers, and the daemon's dispatcher, resume,
|
|
6
|
+
* cadence, responder, classifier and ack lanes — asks this module ONCE per
|
|
7
|
+
* spawn for the seat's engine (config/agent.json `runtime.engine`) and spreads
|
|
8
|
+
* the answer into `buildSpawn`:
|
|
9
|
+
*
|
|
10
|
+
* engine claude `{}` — the buildSpawn input, and so the argv and env, are
|
|
11
|
+
* byte-for-byte what they were before this module existed.
|
|
12
|
+
* engine cohort `{engine:"cohort", cohortToken, agentRoot}` — the adapter
|
|
13
|
+
* launches the Cohort Engine (`cli.mjs run` for run lanes,
|
|
14
|
+
* `cli.mjs session` for main-session and peer) with the seat
|
|
15
|
+
* token and the token helper, every Claude credential scrubbed.
|
|
16
|
+
*
|
|
17
|
+
* Reading the config on every spawn is the rollback: flipping `runtime.engine`
|
|
18
|
+
* back to `claude` restores the claude binary on the NEXT spawn, with no
|
|
19
|
+
* restart (design §8.4: "Rollback is one flag flip").
|
|
20
|
+
*
|
|
21
|
+
* An engine-cohort seat never falls back to claude. With no seat token the
|
|
22
|
+
* adapter returns `cohort_token_unavailable` and the lane reports a failure —
|
|
23
|
+
* running claude instead would spend the seat's Anthropic credential on work
|
|
24
|
+
* the org routed to cohort-llm.
|
|
25
|
+
*
|
|
26
|
+
* The decisions (`seatEngineFields`, `engineRunShape`, `sessionBudgetUsd`) are
|
|
27
|
+
* pure; `seatTokenSync` / `seatToken` are the edge.
|
|
28
|
+
*
|
|
29
|
+
* @module lib/runtime/seat-engine
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
"use strict";
|
|
33
|
+
|
|
34
|
+
import { isRetarget } from "./child-env.mjs";
|
|
35
|
+
import { isCohortRouted, readSeatEngine } from "./adapter.mjs";
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The buildSpawn fields for a seat's engine. PURE.
|
|
39
|
+
* `baseUrl` is the gateway the seat token was minted against (the token
|
|
40
|
+
* manager's `baseUrl`, from config/org.yaml `llmBaseUrl` or the env): the engine
|
|
41
|
+
* must talk to the same gateway, never the adapter's default.
|
|
42
|
+
* @param {{engine:string, agentRoot?:string|null, token?:string|null, baseUrl?:string|null}} o
|
|
43
|
+
* @returns {{}|{engine:"cohort", cohortToken:string|undefined, agentRoot:string|undefined, cohortBaseUrl?:string}}
|
|
44
|
+
*/
|
|
45
|
+
export function seatEngineFields({ engine, agentRoot = null, token = null, baseUrl = null }) {
|
|
46
|
+
if (engine !== "cohort") return {};
|
|
47
|
+
return {
|
|
48
|
+
engine: "cohort",
|
|
49
|
+
cohortToken: typeof token === "string" && token ? token : undefined,
|
|
50
|
+
agentRoot: typeof agentRoot === "string" && agentRoot ? agentRoot : undefined,
|
|
51
|
+
...(typeof baseUrl === "string" && baseUrl ? { cohortBaseUrl: baseUrl } : {}),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* What a routed run lane passes for engine cohort. PURE.
|
|
57
|
+
*
|
|
58
|
+
* The engine talks to cohort-llm directly, so a router retarget never applies:
|
|
59
|
+
* model the router's flag when the router chose the cohort provider (a
|
|
60
|
+
* cohort-* tier), else the lane's own Anthropic slot (sonnet/opus/haiku),
|
|
61
|
+
* which the adapter maps to a Cohort tier. A third-party id is never
|
|
62
|
+
* handed to the engine.
|
|
63
|
+
* knobs the router's --max-turns/--effort/--agents, unless they were sized for
|
|
64
|
+
* a third-party backend (CF-11).
|
|
65
|
+
* retarget `{}`.
|
|
66
|
+
*
|
|
67
|
+
* @param {{target?:object|null, laneModel?:string|null}} o
|
|
68
|
+
* @returns {{model:string|null, knobs:object|null, retarget:{}}}
|
|
69
|
+
*/
|
|
70
|
+
export function engineRunShape({ target = null, laneModel = null }) {
|
|
71
|
+
const t = target && typeof target === "object" ? target : null;
|
|
72
|
+
const cohortTarget = t ? isCohortRouted({ target: t }) : false;
|
|
73
|
+
const foreign = t ? !cohortTarget && isRetarget(t.envForSpawn) : false;
|
|
74
|
+
const model = cohortTarget && t && t.modelFlag ? String(t.modelFlag) : laneModel ? String(laneModel) : null;
|
|
75
|
+
return { model, knobs: foreign ? null : t, retarget: {} };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** The smallest per-session cap passed: one model call's worth at most. */
|
|
79
|
+
export const MIN_SESSION_BUDGET_USD = 0.01;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* The per-session spend cap for an engine-cohort dispatcher session, from the
|
|
83
|
+
* seat's funded envelope (budget-guard `dailyAllowance`). PURE.
|
|
84
|
+
*
|
|
85
|
+
* A session may not spend more than one day's binding allowance (the lower of
|
|
86
|
+
* the envelope's share for today and the local cap). No funded envelope → no
|
|
87
|
+
* cap is invented (null): the budget guard's bands still govern the seat.
|
|
88
|
+
* An envelope with nothing left today gets {@link MIN_SESSION_BUDGET_USD}.
|
|
89
|
+
*
|
|
90
|
+
* @param {{funded?:boolean, allowanceUSD?:number}|null|undefined} allowance
|
|
91
|
+
* @returns {number|null}
|
|
92
|
+
*/
|
|
93
|
+
export function sessionBudgetUsd(allowance) {
|
|
94
|
+
if (!allowance || allowance.funded !== true) return null;
|
|
95
|
+
const usd = Number(allowance.allowanceUSD);
|
|
96
|
+
if (!Number.isFinite(usd)) return null;
|
|
97
|
+
const cents = Math.ceil(Math.max(0, usd) * 100) / 100;
|
|
98
|
+
return Math.max(MIN_SESSION_BUDGET_USD, cents);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
// Edge: the seat token
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* A usable seat token right now, without a network call (a synchronous spawn
|
|
107
|
+
* path). null when none is cached.
|
|
108
|
+
* @param {{peek?:(o:{allowStale:boolean})=>({token?:string}|null)}|null} tokenManager
|
|
109
|
+
*/
|
|
110
|
+
export function seatTokenSync(tokenManager) {
|
|
111
|
+
try {
|
|
112
|
+
const t = tokenManager && typeof tokenManager.peek === "function" ? tokenManager.peek({ allowStale: true }) : null;
|
|
113
|
+
return t && typeof t.token === "string" && t.token ? t.token : null;
|
|
114
|
+
} catch {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* A seat token: the cached one, else minted through the manager. null when the
|
|
121
|
+
* seat cannot get one (no OrgApiKey, the gateway refuses) — never throws.
|
|
122
|
+
* @param {{peek?:Function, getToken?:Function}|null} tokenManager
|
|
123
|
+
* @returns {Promise<string|null>}
|
|
124
|
+
*/
|
|
125
|
+
export async function seatToken(tokenManager) {
|
|
126
|
+
const cached = seatTokenSync(tokenManager);
|
|
127
|
+
if (cached) return cached;
|
|
128
|
+
try {
|
|
129
|
+
const t = tokenManager && typeof tokenManager.getToken === "function" ? await tokenManager.getToken() : null;
|
|
130
|
+
return t && t.ok !== false && typeof t.token === "string" && t.token ? t.token : null;
|
|
131
|
+
} catch {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* The seat's engine and its buildSpawn fields, for a lane that may wait for a
|
|
138
|
+
* token (responder, classifier, ack, the supervisor, `session spawn`). A claude
|
|
139
|
+
* seat reads config/agent.json and nothing else — no token manager is touched.
|
|
140
|
+
* Never throws.
|
|
141
|
+
* @param {string} agentRoot
|
|
142
|
+
* @param {{readSeatEngine?:(root:string)=>string, tokenManager?:(root:string)=>any}} [deps]
|
|
143
|
+
* @returns {Promise<{engine:"claude"|"cohort", fields:object}>}
|
|
144
|
+
*/
|
|
145
|
+
export async function resolveSeatSpawn(agentRoot, deps = {}) {
|
|
146
|
+
let engine = "claude";
|
|
147
|
+
try {
|
|
148
|
+
engine = (deps.readSeatEngine || readSeatEngine)(agentRoot) === "cohort" ? "cohort" : "claude";
|
|
149
|
+
} catch {
|
|
150
|
+
engine = "claude"; // unreadable config: the default engine, as readSeatEngine answers
|
|
151
|
+
}
|
|
152
|
+
if (engine !== "cohort") return { engine, fields: {} };
|
|
153
|
+
let manager = null;
|
|
154
|
+
try {
|
|
155
|
+
manager = deps.tokenManager ? deps.tokenManager(agentRoot) : (await import("../org/llm-token.mjs")).seatTokenManager({ agentRoot });
|
|
156
|
+
} catch {
|
|
157
|
+
manager = null; // no seat key: the adapter refuses the spawn (cohort_token_unavailable)
|
|
158
|
+
}
|
|
159
|
+
return { engine, fields: seatEngineFields({ engine, agentRoot, token: await seatToken(manager), baseUrl: manager && typeof manager.baseUrl === "string" ? manager.baseUrl : null }) };
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export default { seatEngineFields, engineRunShape, sessionBudgetUsd, seatTokenSync, seatToken, resolveSeatSpawn, MIN_SESSION_BUDGET_USD };
|