@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
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* init-skill-marketplace.test.mjs — rung 1 of the execution ladder.
|
|
3
|
-
* Run: node --test scripts/setup/init-skill-marketplace.test.mjs
|
|
4
|
-
*
|
|
5
|
-
* The regression under guard: skill markdown files shipped under
|
|
6
|
-
* `plugins/<id>/skills/*.md` are DEAD at runtime unless their plugin is declared
|
|
7
|
-
* by a `.claude-plugin/marketplace.json` and enabled in `~/.claude/settings.json`.
|
|
8
|
-
* They were neither, and nothing said so. These tests use an injected
|
|
9
|
-
* `probeSkillPlugin` and an injected fs so no real plugin dir or operator
|
|
10
|
-
* settings file is ever touched.
|
|
11
|
-
*/
|
|
12
|
-
"use strict";
|
|
13
|
-
|
|
14
|
-
import { test } from "node:test";
|
|
15
|
-
import assert from "node:assert/strict";
|
|
16
|
-
import { mkdtempSync, mkdirSync, writeFileSync, readFileSync, existsSync } from "node:fs";
|
|
17
|
-
import { tmpdir } from "node:os";
|
|
18
|
-
import { join } from "node:path";
|
|
19
|
-
|
|
20
|
-
import { findSkillPlugins, registerMarketplaces } from "./init-skill-marketplace.mjs";
|
|
21
|
-
|
|
22
|
-
/** An injected fs describing a plugin tree, without creating one. */
|
|
23
|
-
function fakeFs(tree) {
|
|
24
|
-
return {
|
|
25
|
-
existsSync: (p) => Object.prototype.hasOwnProperty.call(tree, String(p)),
|
|
26
|
-
readdirSync: (p, opts) => {
|
|
27
|
-
const v = tree[String(p)];
|
|
28
|
-
if (!Array.isArray(v)) throw new Error(`ENOTDIR ${p}`);
|
|
29
|
-
if (opts && opts.withFileTypes) return v.map((n) => ({ name: n, isDirectory: () => !String(n).endsWith(".md") }));
|
|
30
|
-
return v;
|
|
31
|
-
},
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
test("findSkillPlugins discovers plugins across BOTH the agent repo and the framework", () => {
|
|
36
|
-
const deps = fakeFs({
|
|
37
|
-
"/agent/plugins": ["agent-skills"],
|
|
38
|
-
"/agent/plugins/agent-skills": ["skills"],
|
|
39
|
-
"/agent/plugins/agent-skills/skills": ["morning-brief.md", "outreach.md"],
|
|
40
|
-
"/fw/plugins": ["maestro-skills"],
|
|
41
|
-
"/fw/plugins/maestro-skills": ["skills"],
|
|
42
|
-
"/fw/plugins/maestro-skills/skills": ["triage.md"],
|
|
43
|
-
});
|
|
44
|
-
const found = findSkillPlugins({ roots: ["/agent", "/fw"] }, deps);
|
|
45
|
-
assert.deepEqual(found.map((p) => p.pluginId), ["agent-skills", "maestro-skills"]);
|
|
46
|
-
assert.deepEqual(found[0].skills, ["morning-brief.md", "outreach.md"]);
|
|
47
|
-
assert.equal(found[1].skills.length, 1);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
test("findSkillPlugins ignores plugin dirs that carry no skill files", () => {
|
|
51
|
-
const deps = fakeFs({
|
|
52
|
-
"/agent/plugins": ["hooks-only", "agent-skills"],
|
|
53
|
-
"/agent/plugins/hooks-only": ["hooks"],
|
|
54
|
-
"/agent/plugins/agent-skills": ["skills"],
|
|
55
|
-
"/agent/plugins/agent-skills/skills": ["a.md"],
|
|
56
|
-
});
|
|
57
|
-
const found = findSkillPlugins({ roots: ["/agent"] }, deps);
|
|
58
|
-
assert.deepEqual(found.map((p) => p.pluginId), ["agent-skills"]);
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
test("findSkillPlugins: the agent repo wins a plugin-id collision, and no root is required", () => {
|
|
62
|
-
const deps = fakeFs({
|
|
63
|
-
"/agent/plugins": ["agent-skills"],
|
|
64
|
-
"/agent/plugins/agent-skills": ["skills"],
|
|
65
|
-
"/agent/plugins/agent-skills/skills": ["local.md"],
|
|
66
|
-
"/fw/plugins": ["agent-skills"],
|
|
67
|
-
"/fw/plugins/agent-skills": ["skills"],
|
|
68
|
-
"/fw/plugins/agent-skills/skills": ["framework.md", "another.md"],
|
|
69
|
-
});
|
|
70
|
-
const found = findSkillPlugins({ roots: ["/agent", "/fw"] }, deps);
|
|
71
|
-
assert.equal(found.length, 1, "the id is de-duplicated");
|
|
72
|
-
assert.deepEqual(found[0].skills, ["local.md"], "the agent's own copy wins");
|
|
73
|
-
// A missing plugins dir is a no-op, not a throw.
|
|
74
|
-
assert.deepEqual(findSkillPlugins({ roots: ["/nothing/here"] }, deps), []);
|
|
75
|
-
assert.deepEqual(findSkillPlugins({}, deps), []);
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
test("registerMarketplaces repairs every plugin and reports what it wrote", async () => {
|
|
79
|
-
const calls = [];
|
|
80
|
-
const deps = {
|
|
81
|
-
...fakeFs({
|
|
82
|
-
"/agent/plugins": ["agent-skills"],
|
|
83
|
-
"/agent/plugins/agent-skills": ["skills"],
|
|
84
|
-
"/agent/plugins/agent-skills/skills": ["a.md", "b.md"],
|
|
85
|
-
}),
|
|
86
|
-
probeSkillPlugin: (o) => {
|
|
87
|
-
calls.push(o);
|
|
88
|
-
return { ok: true, detail: "marketplace+enabledPlugins", repaired: ["wrote .claude-plugin/marketplace.json", "enabled in settings.json"] };
|
|
89
|
-
},
|
|
90
|
-
};
|
|
91
|
-
const res = await registerMarketplaces({ agentRoot: "/agent", maestroRoot: "/fw" }, deps);
|
|
92
|
-
|
|
93
|
-
assert.equal(calls.length, 1);
|
|
94
|
-
assert.equal(calls[0].repair, true, "a non-dry run repairs");
|
|
95
|
-
assert.equal(calls[0].pluginId, "agent-skills");
|
|
96
|
-
assert.equal(res.skillCount, 2);
|
|
97
|
-
assert.equal(res.failed.length, 0);
|
|
98
|
-
assert.deepEqual(res.repaired, [
|
|
99
|
-
"agent-skills: wrote .claude-plugin/marketplace.json",
|
|
100
|
-
"agent-skills: enabled in settings.json",
|
|
101
|
-
]);
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
test("--dry-run probes but never repairs", async () => {
|
|
105
|
-
const calls = [];
|
|
106
|
-
const deps = {
|
|
107
|
-
...fakeFs({
|
|
108
|
-
"/agent/plugins": ["agent-skills"],
|
|
109
|
-
"/agent/plugins/agent-skills": ["skills"],
|
|
110
|
-
"/agent/plugins/agent-skills/skills": ["a.md"],
|
|
111
|
-
}),
|
|
112
|
-
probeSkillPlugin: (o) => { calls.push(o); return { ok: false, degraded: "marketplace-missing", detail: "no manifest", repaired: [] }; },
|
|
113
|
-
};
|
|
114
|
-
const res = await registerMarketplaces({ agentRoot: "/agent", maestroRoot: "/fw", dryRun: true }, deps);
|
|
115
|
-
assert.equal(calls[0].repair, false, "dry run must not write");
|
|
116
|
-
assert.equal(res.repaired.length, 0);
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
test("a plugin that cannot be repaired is reported LOUDLY, never swallowed", async () => {
|
|
120
|
-
const deps = {
|
|
121
|
-
...fakeFs({
|
|
122
|
-
"/agent/plugins": ["good", "broken"],
|
|
123
|
-
"/agent/plugins/good": ["skills"],
|
|
124
|
-
"/agent/plugins/good/skills": ["a.md"],
|
|
125
|
-
"/agent/plugins/broken": ["skills"],
|
|
126
|
-
"/agent/plugins/broken/skills": ["b.md", "c.md"],
|
|
127
|
-
}),
|
|
128
|
-
probeSkillPlugin: (o) => (o.pluginId === "broken"
|
|
129
|
-
? { ok: false, degraded: "marketplace-unwritable", detail: "EACCES", repaired: [] }
|
|
130
|
-
: { ok: true, detail: "ok", repaired: [] }),
|
|
131
|
-
};
|
|
132
|
-
const res = await registerMarketplaces({ agentRoot: "/agent", maestroRoot: "/fw" }, deps);
|
|
133
|
-
|
|
134
|
-
assert.equal(res.failed.length, 1);
|
|
135
|
-
assert.equal(res.failed[0].pluginId, "broken");
|
|
136
|
-
assert.equal(res.failed[0].degraded, "marketplace-unwritable");
|
|
137
|
-
assert.equal(res.failed[0].detail, "EACCES");
|
|
138
|
-
// Its skills stay unreachable, which is what the plan compiler then refuses to cite.
|
|
139
|
-
assert.equal(res.plugins.find((p) => p.pluginId === "broken").ok, false);
|
|
140
|
-
assert.equal(res.plugins.find((p) => p.pluginId === "good").ok, true);
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
test("idempotent: a second run over an already-registered plugin writes nothing new", async () => {
|
|
144
|
-
let registered = false;
|
|
145
|
-
const deps = {
|
|
146
|
-
...fakeFs({
|
|
147
|
-
"/agent/plugins": ["agent-skills"],
|
|
148
|
-
"/agent/plugins/agent-skills": ["skills"],
|
|
149
|
-
"/agent/plugins/agent-skills/skills": ["a.md"],
|
|
150
|
-
}),
|
|
151
|
-
probeSkillPlugin: () => {
|
|
152
|
-
const repaired = registered ? [] : ["wrote marketplace.json"];
|
|
153
|
-
registered = true;
|
|
154
|
-
return { ok: true, detail: "ok", repaired };
|
|
155
|
-
},
|
|
156
|
-
};
|
|
157
|
-
const first = await registerMarketplaces({ agentRoot: "/agent" }, deps);
|
|
158
|
-
const second = await registerMarketplaces({ agentRoot: "/agent" }, deps);
|
|
159
|
-
assert.equal(first.repaired.length, 1);
|
|
160
|
-
assert.equal(second.repaired.length, 0, "no churn on a no-op re-run");
|
|
161
|
-
assert.deepEqual(first.plugins.map((p) => p.pluginId), second.plugins.map((p) => p.pluginId));
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
test("the REAL probe writes a valid marketplace manifest into a scratch plugin dir", async () => {
|
|
165
|
-
// One end-to-end pass against the actual probe, in a tmp tree, to prove the
|
|
166
|
-
// injected contract above matches the real implementation's shape.
|
|
167
|
-
const root = mkdtempSync(join(tmpdir(), "maestro-skillmkt-"));
|
|
168
|
-
const home = mkdtempSync(join(tmpdir(), "maestro-skillhome-"));
|
|
169
|
-
mkdirSync(join(root, "plugins", "agent-skills", "skills"), { recursive: true });
|
|
170
|
-
writeFileSync(join(root, "plugins", "agent-skills", "skills", "morning-brief.md"), "# morning-brief\n");
|
|
171
|
-
|
|
172
|
-
const { probeSkillPlugin } = await import("../../lib/capability/probe.mjs");
|
|
173
|
-
const res = await registerMarketplaces(
|
|
174
|
-
{ agentRoot: root, maestroRoot: root },
|
|
175
|
-
{ probeSkillPlugin: (o, d) => probeSkillPlugin(o, { ...d, homeDir: home }) },
|
|
176
|
-
);
|
|
177
|
-
|
|
178
|
-
assert.equal(res.plugins.length, 1);
|
|
179
|
-
assert.equal(res.skillCount, 1);
|
|
180
|
-
const manifestPath = join(root, "plugins", "agent-skills", ".claude-plugin", "marketplace.json");
|
|
181
|
-
assert.ok(existsSync(manifestPath), "the marketplace manifest was written");
|
|
182
|
-
const manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
183
|
-
assert.equal(manifest.name, "agent-skills");
|
|
184
|
-
assert.ok(Array.isArray(manifest.plugins) && manifest.plugins.length === 1);
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
test("the feature is registered in framework-features.json so `maestro upgrade` picks it up", async () => {
|
|
188
|
-
const features = JSON.parse(readFileSync(new URL("../../framework-features.json", import.meta.url), "utf-8"));
|
|
189
|
-
const f = (features.features || features)["skill-marketplace"];
|
|
190
|
-
assert.ok(f, "skill-marketplace feature entry exists");
|
|
191
|
-
assert.equal(f.init.auto, true, "it is an auto migration (idempotent, ~instant)");
|
|
192
|
-
assert.match(f.init.command, /init-skill-marketplace\.mjs/);
|
|
193
|
-
});
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for the vendoring maintainer tool — the half that can run with no
|
|
3
|
-
* network. `syncPack` itself downloads a pinned tarball and is not exercised
|
|
4
|
-
* here; what IS exercised is the planner and the content pin, because those are
|
|
5
|
-
* the two places a re-sync can quietly change what the fleet reads.
|
|
6
|
-
*
|
|
7
|
-
* @module scripts/vendor/sync-skill-packs.test
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { describe, it } from "node:test";
|
|
11
|
-
import assert from "node:assert/strict";
|
|
12
|
-
import { mkdtempSync, mkdirSync, writeFileSync, readFileSync, rmSync } from "node:fs";
|
|
13
|
-
import { tmpdir } from "node:os";
|
|
14
|
-
import path from "node:path";
|
|
15
|
-
import { fileURLToPath } from "node:url";
|
|
16
|
-
import { planPack, buildManifest, sha256File } from "./sync-skill-packs.mjs";
|
|
17
|
-
import { PACKS, findPack, manifestDigest } from "./skill-packs.mjs";
|
|
18
|
-
|
|
19
|
-
const REPO_ROOT = path.resolve(fileURLToPath(new URL(".", import.meta.url)), "..", "..");
|
|
20
|
-
const VENDOR = path.join(REPO_ROOT, "plugins", "maestro-skills", "vendor");
|
|
21
|
-
|
|
22
|
-
describe("sync-skill-packs: the content pin", () => {
|
|
23
|
-
it("manifestDigest is order-independent and moves for any file added, removed or changed", () => {
|
|
24
|
-
const a = [{ path: "SKILL.md", sha256: "aa" }, { path: "reference/x.md", sha256: "bb" }];
|
|
25
|
-
assert.equal(manifestDigest(a), manifestDigest([...a].reverse()), "sorted, so a re-sort is not a change");
|
|
26
|
-
assert.notEqual(manifestDigest(a), manifestDigest([...a, { path: "reference/y.md", sha256: "cc" }]));
|
|
27
|
-
assert.notEqual(manifestDigest(a), manifestDigest([a[0]]));
|
|
28
|
-
assert.notEqual(manifestDigest(a), manifestDigest([a[0], { path: "reference/x.md", sha256: "b0" }]));
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it("what the syncer would write for each committed pack still matches its pinned digest", () => {
|
|
32
|
-
// buildManifest is what a re-sync produces; if it and the committed
|
|
33
|
-
// UPSTREAM.json disagree, someone hand-edited a vendored tree.
|
|
34
|
-
for (const pack of PACKS) {
|
|
35
|
-
const doc = JSON.parse(readFileSync(path.join(VENDOR, pack.id, "UPSTREAM.json"), "utf8"));
|
|
36
|
-
const rebuilt = buildManifest(pack, doc.files);
|
|
37
|
-
assert.deepEqual(rebuilt.files, doc.files, pack.id);
|
|
38
|
-
assert.deepEqual(rebuilt.omitted, doc.omitted, `${pack.id} omitted[] matches the registry`);
|
|
39
|
-
assert.equal(rebuilt.notes, doc.notes, `${pack.id} notes match the registry`);
|
|
40
|
-
assert.equal(manifestDigest(rebuilt.files), pack.contentSha256, pack.id);
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it("every recorded sha256 is the sha256 of the file on disk", () => {
|
|
45
|
-
for (const pack of PACKS) {
|
|
46
|
-
const doc = JSON.parse(readFileSync(path.join(VENDOR, pack.id, "UPSTREAM.json"), "utf8"));
|
|
47
|
-
for (const f of doc.files) {
|
|
48
|
-
assert.equal(sha256File(path.join(VENDOR, pack.id, f.path)), f.sha256, `${pack.id}/${f.path}`);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
describe("sync-skill-packs: the planner", () => {
|
|
55
|
-
/** A fake upstream tree, so the planner runs with no network. */
|
|
56
|
-
function upstream(files) {
|
|
57
|
-
const root = mkdtempSync(path.join(tmpdir(), "maestro-upstream-"));
|
|
58
|
-
for (const [rel, body] of Object.entries(files)) {
|
|
59
|
-
const abs = path.join(root, rel);
|
|
60
|
-
mkdirSync(path.dirname(abs), { recursive: true });
|
|
61
|
-
writeFileSync(abs, body);
|
|
62
|
-
}
|
|
63
|
-
return { root, cleanup: () => rmSync(root, { recursive: true, force: true }) };
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
it("unlazy's rules take the gate checker and refuse the hook machinery", () => {
|
|
67
|
-
// The pack is vendored for its gate checker. `install-hooks.mjs` writes a
|
|
68
|
-
// Stop hook into a settings file — `--global` into the one every session on
|
|
69
|
-
// the machine reads — so it is excluded at the rule, not discouraged in
|
|
70
|
-
// prose: a file that reaches the seat can be run whatever its mode says.
|
|
71
|
-
const t = upstream({
|
|
72
|
-
"SKILL.md": "---\nname: unlazy\n---\n",
|
|
73
|
-
"SECURITY.md": "#\n",
|
|
74
|
-
"LICENSE": "MIT\n",
|
|
75
|
-
"references/gates.md": "#\n",
|
|
76
|
-
"templates/PLAN.md": "#\n",
|
|
77
|
-
"scripts/gate-check.mjs": "//\n",
|
|
78
|
-
"scripts/lib/gates.mjs": "//\n",
|
|
79
|
-
"scripts/install-hooks.mjs": "// writes a Stop hook\n",
|
|
80
|
-
"scripts/stop-hook.mjs": "// the hook body\n",
|
|
81
|
-
});
|
|
82
|
-
try {
|
|
83
|
-
const { pairs, missing } = planPack(findPack("unlazy"), t.root);
|
|
84
|
-
const took = pairs.map((p) => p.to);
|
|
85
|
-
assert.deepEqual(missing, []);
|
|
86
|
-
assert.ok(took.includes("scripts/gate-check.mjs"));
|
|
87
|
-
assert.ok(took.includes("scripts/lib/gates.mjs"));
|
|
88
|
-
assert.equal(took.includes("scripts/install-hooks.mjs"), false);
|
|
89
|
-
assert.equal(took.includes("scripts/stop-hook.mjs"), false);
|
|
90
|
-
} finally { t.cleanup(); }
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
it("a rule that produced a path its own allow-list rejects is a defect, not a quiet write", () => {
|
|
94
|
-
const pack = {
|
|
95
|
-
...findPack("unlazy"),
|
|
96
|
-
rules: [{ type: "dir", from: "scripts", to: "../escape", match: /\.mjs$/, recursive: true }],
|
|
97
|
-
};
|
|
98
|
-
const t = upstream({ "scripts/x.mjs": "//\n" });
|
|
99
|
-
try {
|
|
100
|
-
assert.throws(() => planPack(pack, t.root), /allow-list rejects/);
|
|
101
|
-
} finally { t.cleanup(); }
|
|
102
|
-
});
|
|
103
|
-
});
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* memory-watchdog.test.mjs — audit F16: the HARD tier could SIGTERM the
|
|
3
|
-
* seat's long-lived interactive main session (it only spared the OLDEST
|
|
4
|
-
* claude process, and a freshly relaunched main session is not the oldest).
|
|
5
|
-
*
|
|
6
|
-
* The rule under test is a pure shell function, `is_protected_cmdline`,
|
|
7
|
-
* extracted from the script and run under bash: a command line carrying
|
|
8
|
-
* `--name <anything>-main` or `scripts/session/feed.mjs` is never a kill
|
|
9
|
-
* candidate. The kill loop is also checked textually for the call site, so
|
|
10
|
-
* the function cannot be defined and then not used.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import { test } from "node:test";
|
|
14
|
-
import assert from "node:assert/strict";
|
|
15
|
-
import { readFileSync } from "node:fs";
|
|
16
|
-
import { spawnSync } from "node:child_process";
|
|
17
|
-
import { join, dirname } from "node:path";
|
|
18
|
-
import { fileURLToPath } from "node:url";
|
|
19
|
-
|
|
20
|
-
const SCRIPT = join(dirname(fileURLToPath(import.meta.url)), "memory-watchdog.sh");
|
|
21
|
-
|
|
22
|
-
/** Extract `is_protected_cmdline` from the script and evaluate it on one command line. Exit 0 = protected. */
|
|
23
|
-
function isProtected(cmdline) {
|
|
24
|
-
const src = readFileSync(SCRIPT, "utf8");
|
|
25
|
-
const m = src.match(/\nis_protected_cmdline\(\) \{[\s\S]*?\n\}\n/);
|
|
26
|
-
assert.ok(m, "memory-watchdog.sh defines is_protected_cmdline()");
|
|
27
|
-
const r = spawnSync("/bin/bash", ["-c", `${m[0]}\nis_protected_cmdline "$1"`, "_", cmdline], { encoding: "utf8" });
|
|
28
|
-
return r.status === 0;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
test("the main session (`--name <first>-main`) is protected, whatever the first name", () => {
|
|
32
|
-
assert.equal(isProtected("claude --name alex-main --resume 1234 --dangerously-skip-permissions"), true);
|
|
33
|
-
assert.equal(isProtected("/opt/homebrew/bin/claude --dangerously-skip-permissions --name marc-main"), true);
|
|
34
|
-
assert.equal(isProtected("node /Users/x/.npm-global/lib/node_modules/@anthropic-ai/claude-code/cli.js --name olivia-main"), true);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
test("the session feed (scripts/session/feed.mjs) is protected", () => {
|
|
38
|
-
assert.equal(isProtected("node /Users/alex/alex-ai/scripts/session/feed.mjs"), true);
|
|
39
|
-
assert.equal(isProtected("/usr/local/bin/node scripts/session/feed.mjs --agent-root /x"), true);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
test("sub-sessions, peers and print spawns are NOT protected", () => {
|
|
43
|
-
assert.equal(isProtected("claude --print --output-format json --dangerously-skip-permissions prompt"), false);
|
|
44
|
-
assert.equal(isProtected("claude --name alex-research --dangerously-skip-permissions"), false);
|
|
45
|
-
assert.equal(isProtected("claude --name alex-mainline"), false, "-main must be a whole token");
|
|
46
|
-
assert.equal(isProtected("claude --name alex-main-2"), false);
|
|
47
|
-
assert.equal(isProtected("node scripts/daemon/maestro-daemon.mjs"), false);
|
|
48
|
-
assert.equal(isProtected(""), false);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
test("the HARD-tier kill loop consults is_protected_cmdline before SIGTERM and logs the skip", () => {
|
|
52
|
-
const src = readFileSync(SCRIPT, "utf8");
|
|
53
|
-
const loop = src.slice(src.indexOf("kill_youngest_biggest_subagents() {"), src.indexOf('done <<< "$(get_claude_processes)"'));
|
|
54
|
-
assert.match(loop, /is_protected_cmdline/, "the kill loop calls the guard");
|
|
55
|
-
assert.match(loop, /skip_protected/, "a protected skip is logged");
|
|
56
|
-
assert.ok(loop.indexOf("is_protected_cmdline") < loop.indexOf('kill -TERM "$pid"'), "the guard runs before the signal");
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
test("cmdline_of reads the FULL command line (ps -ww) so a long argv is never cut before --name <first>-main on a narrow tty", () => {
|
|
60
|
-
const src = readFileSync(SCRIPT, "utf8");
|
|
61
|
-
const m = src.match(/\ncmdline_of\(\) \{[\s\S]*?\n\}\n/);
|
|
62
|
-
assert.ok(m, "memory-watchdog.sh defines cmdline_of()");
|
|
63
|
-
assert.match(m[0], /\/bin\/ps -ww /, "ps must be given -ww (unlimited width) — macOS truncates `-o command=` to the terminal width otherwise");
|
|
64
|
-
});
|