@cohortapp/agent-sdk 2.3.0
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/commands/init-agent.md +104 -0
- package/.claude/commands/init-maestro.md +1187 -0
- package/.claude/settings.json +161 -0
- package/.env.example +216 -0
- package/README.md +632 -0
- package/agents/browser-operator/agent.md +52 -0
- package/agents/calendar-ops/agent.md +50 -0
- package/agents/communications/agent.md +96 -0
- package/agents/decision-log/agent.md +65 -0
- package/agents/desktop-operator/agent.md +59 -0
- package/agents/gmail-operator/agent.md +62 -0
- package/agents/inbound-dispatcher/agent.md +66 -0
- package/agents/inbox-processor/agent.md +39 -0
- package/agents/pmo-execution/agent.md +60 -0
- package/agents/session-spawner/agent.md +64 -0
- package/agents/slack-operator/agent.md +60 -0
- package/agents/whatsapp-operator/agent.md +60 -0
- package/agents/workflow-automation/agent.md +61 -0
- package/archetypes/altitudes/c-suite.yaml +58 -0
- package/archetypes/altitudes/founder.yaml +68 -0
- package/archetypes/altitudes/senior-manager.yaml +63 -0
- package/archetypes/altitudes/svp.yaml +60 -0
- package/archetypes/altitudes/vp.yaml +50 -0
- package/archetypes/archetype.schema.json +77 -0
- package/archetypes/base.yaml +47 -0
- package/archetypes/capabilities/commercial-leader.yaml +159 -0
- package/archetypes/capabilities/compliance-officer.yaml +159 -0
- package/archetypes/capabilities/executive-operator.yaml +169 -0
- package/archetypes/capabilities/finance-leader.yaml +162 -0
- package/archetypes/capabilities/operations-leader.yaml +154 -0
- package/archetypes/capabilities/product-leader.yaml +148 -0
- package/archetypes/capabilities/technical-leader.yaml +146 -0
- package/archetypes/functions/commercial-leader.yaml +62 -0
- package/archetypes/functions/compliance-officer.yaml +64 -0
- package/archetypes/functions/executive-operator.yaml +70 -0
- package/archetypes/functions/finance-leader.yaml +70 -0
- package/archetypes/functions/operations-leader.yaml +62 -0
- package/archetypes/functions/product-leader.yaml +61 -0
- package/archetypes/functions/technical-leader.yaml +57 -0
- package/bin/cohort-mcp.mjs +81 -0
- package/bin/maestro.mjs +3516 -0
- package/bin/maestro.test.mjs +1015 -0
- package/desktop-control/README.md +56 -0
- package/desktop-control/app-profiles/gmail.yaml +120 -0
- package/desktop-control/app-profiles/slack.yaml +315 -0
- package/desktop-control/app-profiles/whatsapp.yaml +107 -0
- package/docs/architecture/agent-topology.md +2239 -0
- package/docs/architecture/archetype-agent-factory.md +110 -0
- package/docs/architecture/collective-memory-and-org-mesh.md +115 -0
- package/docs/architecture/continuous-monitoring.md +221 -0
- package/docs/architecture/mcp-capability-map.md +585 -0
- package/docs/architecture/system-architecture.md +1272 -0
- package/docs/company-context/README.md +40 -0
- package/docs/guides/agent-persona-setup.md +600 -0
- package/docs/guides/agents-observe-setup.md +64 -0
- package/docs/guides/billing-console-keys.md +88 -0
- package/docs/guides/ccxray-diagnostics.md +65 -0
- package/docs/guides/channel-bus.md +127 -0
- package/docs/guides/claude-mem-setup.md +79 -0
- package/docs/guides/claude-pace-setup.md +56 -0
- package/docs/guides/claudraband-sessions.md +98 -0
- package/docs/guides/clawteam-swarm.md +116 -0
- package/docs/guides/code-review-graph-setup.md +86 -0
- package/docs/guides/email-setup.md +431 -0
- package/docs/guides/mac-mini.md +119 -0
- package/docs/guides/media-generation-setup.md +349 -0
- package/docs/guides/model-routing.md +162 -0
- package/docs/guides/observability-otel.md +265 -0
- package/docs/guides/org-onboarding.md +132 -0
- package/docs/guides/outbound-governance-setup.md +437 -0
- package/docs/guides/pdf-generation-setup.md +315 -0
- package/docs/guides/poller-daemon-setup.md +563 -0
- package/docs/guides/rag-context-setup.md +459 -0
- package/docs/guides/self-optimization-pattern.md +82 -0
- package/docs/guides/setup-wizard.md +178 -0
- package/docs/guides/slack-setup.md +350 -0
- package/docs/guides/telegram-setup.md +227 -0
- package/docs/guides/twilio-subaccounts-setup.md +223 -0
- package/docs/guides/verification.md +128 -0
- package/docs/guides/voice-mode.md +188 -0
- package/docs/guides/voice-sms-setup.md +698 -0
- package/docs/guides/webhook-relay-setup.md +349 -0
- package/docs/guides/whatsapp-setup.md +288 -0
- package/docs/prompts/board-pack-cover-template.md +36 -0
- package/docs/prompts/decision-recommendation-template.md +88 -0
- package/docs/prompts/followup-message-template.md +141 -0
- package/docs/prompts/investor-letter-template.md +52 -0
- package/docs/prompts/morning-brief-template.md +82 -0
- package/docs/prompts/presentation-template.md +58 -0
- package/docs/prompts/weekly-strategic-memo-template.md +104 -0
- package/docs/research/hallucinated-tool-output-investigation.md +151 -0
- package/docs/runbooks/backup-restore.md +205 -0
- package/docs/runbooks/cohort-cutover.md +129 -0
- package/docs/runbooks/fleet-operations.md +200 -0
- package/docs/runbooks/incident-response.md +226 -0
- package/docs/runbooks/mac-mini-bootstrap.md +431 -0
- package/docs/runbooks/perpetual-operations.md +509 -0
- package/docs/runbooks/recovery-and-failover.md +260 -0
- package/framework-features.json +267 -0
- package/ingest/README.md +87 -0
- package/lib/action-executor.js +689 -0
- package/lib/action-executor.test.mjs +871 -0
- package/lib/agent-root.mjs +37 -0
- package/lib/archetype.mjs +236 -0
- package/lib/archetype.test.mjs +132 -0
- package/lib/autonomy.mjs +114 -0
- package/lib/autonomy.test.mjs +66 -0
- package/lib/backlog.mjs +358 -0
- package/lib/backlog.test.mjs +266 -0
- package/lib/budget-guard.mjs +279 -0
- package/lib/budget-guard.test.mjs +291 -0
- package/lib/cadence-bus-schedule.test.mjs +194 -0
- package/lib/cadence-bus.mjs +1120 -0
- package/lib/cadence-bus.test.mjs +720 -0
- package/lib/cadences.mjs +205 -0
- package/lib/cadences.test.mjs +125 -0
- package/lib/capability.mjs +154 -0
- package/lib/capability.test.mjs +78 -0
- package/lib/channels/base-adapter.mjs +719 -0
- package/lib/channels/base-adapter.test.mjs +590 -0
- package/lib/channels/channel.mjs +128 -0
- package/lib/channels/channels.test.mjs +371 -0
- package/lib/channels/contract.mjs +215 -0
- package/lib/channels/contract.test.mjs +137 -0
- package/lib/channels/conversation-resolver.mjs +95 -0
- package/lib/channels/gmail/adapter.mjs +87 -0
- package/lib/channels/inbox-item.mjs +255 -0
- package/lib/channels/inbox-item.test.mjs +335 -0
- package/lib/channels/index.mjs +94 -0
- package/lib/channels/orgmail/adapter.mjs +353 -0
- package/lib/channels/orgmail/adapter.test.mjs +311 -0
- package/lib/channels/pairing.mjs +363 -0
- package/lib/channels/pairing.test.mjs +270 -0
- package/lib/channels/registry.mjs +164 -0
- package/lib/channels/slack/adapter.mjs +317 -0
- package/lib/channels/slack-adapter.test.mjs +212 -0
- package/lib/channels/sms/adapter.mjs +43 -0
- package/lib/channels/telegram/adapter.mjs +432 -0
- package/lib/channels/telegram-adapter.test.mjs +306 -0
- package/lib/channels/voice/adapter.mjs +301 -0
- package/lib/channels/voice/adapter.test.mjs +278 -0
- package/lib/channels/whatsapp/adapter-baileys.mjs +587 -0
- package/lib/channels/whatsapp/adapter-baileys.test.mjs +359 -0
- package/lib/channels/whatsapp/adapter-twilio.mjs +65 -0
- package/lib/channels/whatsapp/baileys-typing.test.mjs +154 -0
- package/lib/charter.mjs +256 -0
- package/lib/charter.test.mjs +89 -0
- package/lib/claude-bin.mjs +134 -0
- package/lib/claude-bin.test.mjs +75 -0
- package/lib/collective/capture.mjs +185 -0
- package/lib/collective/capture.test.mjs +121 -0
- package/lib/collective/cards.mjs +201 -0
- package/lib/collective/cards.test.mjs +114 -0
- package/lib/collective/config.mjs +186 -0
- package/lib/collective/config.test.mjs +123 -0
- package/lib/collective/global-config.mjs +113 -0
- package/lib/collective/global-config.test.mjs +75 -0
- package/lib/collective/presence.mjs +201 -0
- package/lib/collective/presence.test.mjs +95 -0
- package/lib/collective/recall.mjs +215 -0
- package/lib/collective/recall.test.mjs +116 -0
- package/lib/comms/send-gate.mjs +554 -0
- package/lib/comms/send-gate.test.mjs +577 -0
- package/lib/comms.mjs +67 -0
- package/lib/comms.test.mjs +41 -0
- package/lib/diagnostics/alerts.mjs +424 -0
- package/lib/diagnostics/alerts.test.mjs +318 -0
- package/lib/diagnostics/backup-freshness.mjs +188 -0
- package/lib/diagnostics/backup-freshness.test.mjs +185 -0
- package/lib/diagnostics/counters.mjs +269 -0
- package/lib/diagnostics/counters.test.mjs +206 -0
- package/lib/diagnostics/events.mjs +188 -0
- package/lib/diagnostics/events.test.mjs +290 -0
- package/lib/diagnostics/otel.mjs +237 -0
- package/lib/diagnostics/otel.test.mjs +196 -0
- package/lib/diagnostics/trace.mjs +216 -0
- package/lib/diagnostics/trace.test.mjs +251 -0
- package/lib/env-compat.mjs +74 -0
- package/lib/env-compat.test.mjs +104 -0
- package/lib/feature-init.mjs +331 -0
- package/lib/fs-atomic.mjs +112 -0
- package/lib/fs-atomic.test.mjs +72 -0
- package/lib/fs-ownership.mjs +111 -0
- package/lib/fs-ownership.test.mjs +158 -0
- package/lib/hooks/bus.mjs +347 -0
- package/lib/hooks/bus.test.mjs +387 -0
- package/lib/index.js +16 -0
- package/lib/learning/config.mjs +106 -0
- package/lib/learning/config.test.mjs +75 -0
- package/lib/learning/counters.mjs +156 -0
- package/lib/learning/counters.test.mjs +69 -0
- package/lib/learning/curator-consolidate.test.mjs +238 -0
- package/lib/learning/curator.mjs +453 -0
- package/lib/learning/curator.test.mjs +106 -0
- package/lib/learning/log.mjs +40 -0
- package/lib/learning/reflect.mjs +534 -0
- package/lib/learning/reflect.test.mjs +0 -0
- package/lib/learning/session-index.mjs +352 -0
- package/lib/learning/session-index.test.mjs +125 -0
- package/lib/learning/skill-writer.mjs +474 -0
- package/lib/learning/skill-writer.test.mjs +210 -0
- package/lib/mcp/server.mjs +328 -0
- package/lib/mcp/server.test.mjs +400 -0
- package/lib/model-router/auth-profiles.mjs +758 -0
- package/lib/model-router/auth-profiles.test.mjs +580 -0
- package/lib/model-router/catalog/anthropic.yaml +153 -0
- package/lib/model-router/catalog/deepseek.yaml +86 -0
- package/lib/model-router/catalog/moonshot.yaml +81 -0
- package/lib/model-router/catalog/qwen.yaml +114 -0
- package/lib/model-router/catalog.mjs +925 -0
- package/lib/model-router/catalog.test.mjs +385 -0
- package/lib/model-router/economics.mjs +564 -0
- package/lib/model-router/economics.test.mjs +344 -0
- package/lib/model-router/failover.mjs +298 -0
- package/lib/model-router/failover.test.mjs +439 -0
- package/lib/model-router/health.mjs +453 -0
- package/lib/model-router/health.test.mjs +338 -0
- package/lib/model-router/integration-coverage.test.mjs +829 -0
- package/lib/model-router/integration.test.mjs +564 -0
- package/lib/model-router/ledger.mjs +402 -0
- package/lib/model-router/ledger.test.mjs +382 -0
- package/lib/model-router/llm-task.mjs +515 -0
- package/lib/model-router/llm-task.test.mjs +392 -0
- package/lib/model-router/org-credentials.mjs +260 -0
- package/lib/model-router/org-credentials.test.mjs +265 -0
- package/lib/model-router/pricing-refresh.mjs +463 -0
- package/lib/model-router/pricing-refresh.test.mjs +286 -0
- package/lib/model-router/reconcile.mjs +429 -0
- package/lib/model-router/reconcile.test.mjs +316 -0
- package/lib/model-router/repair.mjs +471 -0
- package/lib/model-router/repair.test.mjs +180 -0
- package/lib/model-router/resolve.mjs +1206 -0
- package/lib/model-router/spawn.mjs +497 -0
- package/lib/model-router/spawn.test.mjs +425 -0
- package/lib/model-router/taxonomy.mjs +893 -0
- package/lib/model-router/taxonomy.test.mjs +410 -0
- package/lib/model-router.mjs +677 -0
- package/lib/model-router.test.mjs +907 -0
- package/lib/org/activity.mjs +211 -0
- package/lib/org/activity.test.mjs +134 -0
- package/lib/org/approvals.mjs +448 -0
- package/lib/org/approvals.test.mjs +216 -0
- package/lib/org/awareness.mjs +222 -0
- package/lib/org/awareness.test.mjs +159 -0
- package/lib/org/board.mjs +229 -0
- package/lib/org/board.test.mjs +177 -0
- package/lib/org/bootstrap-context.mjs +169 -0
- package/lib/org/bootstrap-context.test.mjs +153 -0
- package/lib/org/client.mjs +1628 -0
- package/lib/org/client.test.mjs +1107 -0
- package/lib/org/cohort-client.mjs +67 -0
- package/lib/org/cohort-client.test.mjs +126 -0
- package/lib/org/cost-sync.mjs +227 -0
- package/lib/org/cost-sync.test.mjs +153 -0
- package/lib/org/doctor.mjs +212 -0
- package/lib/org/doctor.test.mjs +212 -0
- package/lib/org/handoff.mjs +293 -0
- package/lib/org/handoff.test.mjs +269 -0
- package/lib/org/integration-tools.mjs +182 -0
- package/lib/org/integration-tools.test.mjs +160 -0
- package/lib/org/keys.mjs +131 -0
- package/lib/org/keys.test.mjs +92 -0
- package/lib/org/knowledge.mjs +463 -0
- package/lib/org/knowledge.test.mjs +319 -0
- package/lib/org/leases.mjs +335 -0
- package/lib/org/leases.test.mjs +235 -0
- package/lib/org/mesh-integration.test.mjs +127 -0
- package/lib/org/mesh.mjs +459 -0
- package/lib/org/mesh.test.mjs +345 -0
- package/lib/org/messaging.mjs +503 -0
- package/lib/org/messaging.test.mjs +238 -0
- package/lib/org/policy.mjs +345 -0
- package/lib/org/policy.test.mjs +237 -0
- package/lib/org/protocol.checksum +1 -0
- package/lib/org/protocol.checksum.test.mjs +90 -0
- package/lib/org/protocol.mjs +967 -0
- package/lib/org/protocol.test.mjs +264 -0
- package/lib/org/registry.mjs +194 -0
- package/lib/org/registry.test.mjs +100 -0
- package/lib/org/tool-surface-integration.test.mjs +120 -0
- package/lib/org/tool-surface.mjs +2535 -0
- package/lib/org/tool-surface.test.mjs +589 -0
- package/lib/org/ui-parity.mjs +3236 -0
- package/lib/org/ui-parity.test.mjs +348 -0
- package/lib/org/verify.mjs +176 -0
- package/lib/org/verify.test.mjs +194 -0
- package/lib/rag/embed.mjs +188 -0
- package/lib/rag/indexer.mjs +425 -0
- package/lib/rag/rag.test.mjs +505 -0
- package/lib/rag/search.mjs +475 -0
- package/lib/rate-guard.mjs +246 -0
- package/lib/rate-guard.test.mjs +201 -0
- package/lib/render.mjs +112 -0
- package/lib/render.test.mjs +68 -0
- package/lib/resource-governor.mjs +297 -0
- package/lib/resource-governor.test.mjs +262 -0
- package/lib/scheduling/dynamic-jobs.mjs +675 -0
- package/lib/scheduling/dynamic-jobs.test.mjs +344 -0
- package/lib/scheduling/jitter.mjs +0 -0
- package/lib/scheduling/jitter.test.mjs +140 -0
- package/lib/secrets/broker.mjs +315 -0
- package/lib/secrets/broker.test.mjs +280 -0
- package/lib/secrets/providers.mjs +461 -0
- package/lib/secrets/providers.test.mjs +274 -0
- package/lib/security/audit-engine.mjs +684 -0
- package/lib/security/audit-engine.test.mjs +389 -0
- package/lib/security/coerce-args.mjs +552 -0
- package/lib/security/coerce-args.test.mjs +281 -0
- package/lib/security/dangerous-tools.mjs +97 -0
- package/lib/security/dangerous-tools.test.mjs +68 -0
- package/lib/security/external-content.mjs +145 -0
- package/lib/security/external-content.test.mjs +67 -0
- package/lib/security/redact.mjs +592 -0
- package/lib/security/redact.test.mjs +441 -0
- package/lib/security/secret-equal.mjs +73 -0
- package/lib/security/secret-equal.test.mjs +55 -0
- package/lib/session-permissions.mjs +101 -0
- package/lib/session-permissions.test.mjs +100 -0
- package/lib/setup/claude-probe.mjs +74 -0
- package/lib/setup/completeness.mjs +175 -0
- package/lib/setup/completeness.test.mjs +110 -0
- package/lib/setup/context-pack.mjs +173 -0
- package/lib/setup/context-pack.test.mjs +89 -0
- package/lib/setup/enrich.mjs +277 -0
- package/lib/setup/enrich.test.mjs +115 -0
- package/lib/setup/enroll-from-cohort.mjs +441 -0
- package/lib/setup/enroll-from-cohort.test.mjs +233 -0
- package/lib/setup/integration.test.mjs +162 -0
- package/lib/setup/io.mjs +360 -0
- package/lib/setup/io.test.mjs +77 -0
- package/lib/setup/run-generator.mjs +81 -0
- package/lib/setup/runner.mjs +244 -0
- package/lib/setup/runner.test.mjs +132 -0
- package/lib/setup/sections/comms.mjs +173 -0
- package/lib/setup/sections/company.mjs +120 -0
- package/lib/setup/sections/enrich.mjs +138 -0
- package/lib/setup/sections/identity.mjs +182 -0
- package/lib/setup/sections/identity.test.mjs +140 -0
- package/lib/setup/sections/learning.mjs +153 -0
- package/lib/setup/sections/learning.test.mjs +81 -0
- package/lib/setup/sections/messaging.mjs +219 -0
- package/lib/setup/sections/messaging.test.mjs +127 -0
- package/lib/setup/sections/model.mjs +102 -0
- package/lib/setup/sections/operating-model.mjs +78 -0
- package/lib/setup/sections/org.mjs +475 -0
- package/lib/setup/sections/org.test.mjs +313 -0
- package/lib/setup/sections/orgmail.mjs +173 -0
- package/lib/setup/sections/orgmail.test.mjs +118 -0
- package/lib/setup/sections/recovery.mjs +159 -0
- package/lib/setup/sections/recovery.test.mjs +98 -0
- package/lib/setup/sections/tools.mjs +132 -0
- package/lib/setup/sections/verify.mjs +97 -0
- package/lib/setup/sot.mjs +205 -0
- package/lib/setup/sot.test.mjs +81 -0
- package/lib/setup/state.mjs +151 -0
- package/lib/setup/state.test.mjs +92 -0
- package/lib/singleton.js +229 -0
- package/lib/singleton.test.mjs +135 -0
- package/lib/telemetry/alerts.mjs +216 -0
- package/lib/telemetry/alerts.test.mjs +109 -0
- package/lib/telemetry/collect.mjs +512 -0
- package/lib/telemetry/collect.test.mjs +202 -0
- package/lib/tool-definitions-integration.test.mjs +83 -0
- package/lib/tool-definitions.js +738 -0
- package/lib/tool-definitions.test.mjs +437 -0
- package/lib/util/fetch-timeout.mjs +136 -0
- package/lib/util/fetch-timeout.test.mjs +202 -0
- package/lib/util/reconnect.mjs +343 -0
- package/lib/util/reconnect.test.mjs +369 -0
- package/lib/util/unhandled.mjs +205 -0
- package/lib/util/unhandled.test.mjs +216 -0
- package/lib/voice/context-loader.mjs +466 -0
- package/lib/voice/index.mjs +100 -0
- package/lib/voice/openai-realtime.mjs +510 -0
- package/lib/voice/outbound.mjs +542 -0
- package/lib/voice/outbound.test.mjs +69 -0
- package/lib/voice/post-call-brief.mjs +428 -0
- package/lib/voice/provider.mjs +52 -0
- package/lib/voice/session-rotation.mjs +257 -0
- package/lib/voice/stt.mjs +161 -0
- package/lib/voice/stt.test.mjs +226 -0
- package/lib/voice/tool-bridge.mjs +370 -0
- package/lib/voice/tts.mjs +104 -0
- package/lib/voice/twilio-sip-bridge.mjs +288 -0
- package/lib/voice/voice.test.mjs +990 -0
- package/mcp/README.md +80 -0
- package/package.json +151 -0
- package/plugins/maestro-skills/plugin.json +139 -0
- package/plugins/maestro-skills/skills/agents-observe.md +110 -0
- package/plugins/maestro-skills/skills/board-deck.md +68 -0
- package/plugins/maestro-skills/skills/books-close.md +77 -0
- package/plugins/maestro-skills/skills/brand-steward.md +121 -0
- package/plugins/maestro-skills/skills/calendar-plan.md +57 -0
- package/plugins/maestro-skills/skills/call-working-sessions.md +124 -0
- package/plugins/maestro-skills/skills/ccxray-diagnostics.md +91 -0
- package/plugins/maestro-skills/skills/claude-pace.md +61 -0
- package/plugins/maestro-skills/skills/code-review-graph.md +99 -0
- package/plugins/maestro-skills/skills/crm-pipeline.md +65 -0
- package/plugins/maestro-skills/skills/decision-brief.md +89 -0
- package/plugins/maestro-skills/skills/directory-hygiene.md +125 -0
- package/plugins/maestro-skills/skills/draft-comms.md +84 -0
- package/plugins/maestro-skills/skills/evening-wrap.md +53 -0
- package/plugins/maestro-skills/skills/files-find.md +65 -0
- package/plugins/maestro-skills/skills/generative-ui.md +228 -0
- package/plugins/maestro-skills/skills/hiring-triage.md +74 -0
- package/plugins/maestro-skills/skills/inbox-triage.md +61 -0
- package/plugins/maestro-skills/skills/mail-triage.md +86 -0
- package/plugins/maestro-skills/skills/morning-brief.md +54 -0
- package/plugins/maestro-skills/skills/native-artifacts.md +157 -0
- package/plugins/maestro-skills/skills/org-board.md +133 -0
- package/plugins/maestro-skills/skills/org-credential.md +68 -0
- package/plugins/maestro-skills/skills/org-recall.md +81 -0
- package/plugins/maestro-skills/skills/pipeline-review.md +76 -0
- package/plugins/maestro-skills/skills/regulatory-status.md +81 -0
- package/plugins/maestro-skills/skills/router-why.md +78 -0
- package/plugins/maestro-skills/skills/schedule-meeting.md +91 -0
- package/plugins/maestro-skills/skills/session-search.md +71 -0
- package/plugins/maestro-skills/skills/set-reminder.md +93 -0
- package/plugins/maestro-skills/skills/slack-followup.md +64 -0
- package/plugins/maestro-skills/skills/team-activity.md +86 -0
- package/plugins/maestro-skills/skills/weekly-memo.md +70 -0
- package/policies/action-classification.yaml +114 -0
- package/policies/ai-disclosure.yaml +294 -0
- package/policies/communication-style.md +139 -0
- package/policies/information-barriers.yaml +118 -0
- package/policies/prompt-injection-defence.yaml +138 -0
- package/public/assets/icon-dark.png +0 -0
- package/public/assets/icon-dark.svg +9 -0
- package/public/assets/icon-light.svg +9 -0
- package/public/assets/logo-dark.svg +15 -0
- package/public/assets/logo-light.svg +15 -0
- package/scaffold/.mcp.json +7 -0
- package/scaffold/CLAUDE.md +368 -0
- package/scaffold/config/agent.json +55 -0
- package/scaffold/config/agent.ts +76 -0
- package/scaffold/config/agent.ts.example +89 -0
- package/scaffold/config/alerts.yaml +23 -0
- package/scaffold/config/allowlist.yaml.example +25 -0
- package/scaffold/config/caller-id-map.yaml +46 -0
- package/scaffold/config/collective.yaml +49 -0
- package/scaffold/config/company.json +20 -0
- package/scaffold/config/known-agents.json +6 -0
- package/scaffold/config/learning.yaml +55 -0
- package/scaffold/config/model-routing.yaml.example +104 -0
- package/scaffold/config/org.yaml +25 -0
- package/scaffold/config/orgmail.yaml.example +19 -0
- package/scaffold/config/recovery.yaml +72 -0
- package/scaffold/config/secrets.yaml +27 -0
- package/scaffold/config/slack.yaml.example +35 -0
- package/scaffold/config/telegram.yaml.example +38 -0
- package/scaffold/config/voice.yaml.example +89 -0
- package/scaffold/config/whatsapp.yaml.example +39 -0
- package/schedules/README.md +49 -0
- package/schedules/triggers/backlog-executor.md +102 -0
- package/schedules/triggers/brand-steward.md +72 -0
- package/schedules/triggers/daily-evening-wrap.md +159 -0
- package/schedules/triggers/daily-midday-sweep.md +58 -0
- package/schedules/triggers/daily-morning-brief.md +55 -0
- package/schedules/triggers/directory-hygiene.md +81 -0
- package/schedules/triggers/dynamic-jobs.md +40 -0
- package/schedules/triggers/inbox-processor.md +115 -0
- package/schedules/triggers/meeting-action-capture.md +60 -0
- package/schedules/triggers/meeting-prep.md +69 -0
- package/schedules/triggers/messaging-inbound.md +50 -0
- package/schedules/triggers/org-pulse.md +24 -0
- package/schedules/triggers/quarterly-self-assessment.md +54 -0
- package/schedules/triggers/weekly-engineering-health.md +37 -0
- package/schedules/triggers/weekly-execution.md +65 -0
- package/schedules/triggers/weekly-hiring.md +53 -0
- package/schedules/triggers/weekly-priorities.md +38 -0
- package/schedules/triggers/weekly-strategic-memo.md +124 -0
- package/scripts/archive-email.sh +55 -0
- package/scripts/cadence/cadence-status.mjs +36 -0
- package/scripts/cadence/enqueue-cadence-tick.mjs +174 -0
- package/scripts/cadence/enqueue-cadence-tick.test.mjs +187 -0
- package/scripts/cadence/launchd-cadence-wrapper.sh +85 -0
- package/scripts/cadence/launchd-cloud-relay-wrapper.sh +95 -0
- package/scripts/cadence/launchd-socket-mode-wrapper.sh +95 -0
- package/scripts/ci/check-docs-accuracy.mjs +493 -0
- package/scripts/ci/check-docs-accuracy.test.mjs +409 -0
- package/scripts/ci/check-exports-exist.mjs +140 -0
- package/scripts/ci/check-files-exist.mjs +107 -0
- package/scripts/ci/check-no-build-artifacts.mjs +111 -0
- package/scripts/ci/check-no-build-artifacts.test.mjs +71 -0
- package/scripts/ci/check-no-confidential.mjs +198 -0
- package/scripts/ci/check-no-conflict-markers.mjs +169 -0
- package/scripts/ci/check-no-residual-identity.mjs +163 -0
- package/scripts/ci/check-no-residual-identity.test.mjs +89 -0
- package/scripts/ci/check-tarball-fidelity.mjs +205 -0
- package/scripts/ci/check-unresolved-tokens.mjs +83 -0
- package/scripts/ci/check.mjs +109 -0
- package/scripts/ci/check.test.mjs +194 -0
- package/scripts/ci/run-coverage.mjs +82 -0
- package/scripts/ci/run-tests.mjs +71 -0
- package/scripts/cloud-relay/README.md +59 -0
- package/scripts/cloud-relay/index.mjs +233 -0
- package/scripts/cloud-relay/package.json +15 -0
- package/scripts/cloud-relay/railway.json +13 -0
- package/scripts/cloud-relay/voice/README.md +94 -0
- package/scripts/cloud-relay/voice/package-lock.json +39 -0
- package/scripts/cloud-relay/voice/package.json +16 -0
- package/scripts/cloud-relay/voice/railway.json +13 -0
- package/scripts/cloud-relay/voice/server.mjs +532 -0
- package/scripts/collective/hook-runner.mjs +211 -0
- package/scripts/collective/hook-runner.test.mjs +90 -0
- package/scripts/collective/org-pulse.mjs +72 -0
- package/scripts/collective/org-sync.mjs +61 -0
- package/scripts/collective/recall.mjs +45 -0
- package/scripts/collective/who.mjs +30 -0
- package/scripts/comms-monitor.sh +288 -0
- package/scripts/configure-whatsapp-sandbox.sh +201 -0
- package/scripts/continuous-monitor.sh +91 -0
- package/scripts/cost/fleet-digest.mjs +407 -0
- package/scripts/cost/fleet-digest.test.mjs +207 -0
- package/scripts/cost/track-claude-usage.mjs +169 -0
- package/scripts/daemon/agent-daemon.mjs +989 -0
- package/scripts/daemon/agent-daemon.test.mjs +525 -0
- package/scripts/daemon/cadence-consumer-governance.test.mjs +220 -0
- package/scripts/daemon/cadence-consumer.mjs +1080 -0
- package/scripts/daemon/cadence-consumer.test.mjs +770 -0
- package/scripts/daemon/cadence-handlers.mjs +1121 -0
- package/scripts/daemon/cadence-handlers.test.mjs +617 -0
- package/scripts/daemon/classifier.mjs +704 -0
- package/scripts/daemon/classifier.test.mjs +238 -0
- package/scripts/daemon/classify-kind.mjs +54 -0
- package/scripts/daemon/classify-kind.test.mjs +40 -0
- package/scripts/daemon/context-compiler.mjs +605 -0
- package/scripts/daemon/context-compiler.test.mjs +300 -0
- package/scripts/daemon/dispatcher-cooldown.test.mjs +122 -0
- package/scripts/daemon/dispatcher-governance.test.mjs +886 -0
- package/scripts/daemon/dispatcher.mjs +1516 -0
- package/scripts/daemon/health.mjs +72 -0
- package/scripts/daemon/inbox-deferral.mjs +210 -0
- package/scripts/daemon/inbox-deferral.test.mjs +242 -0
- package/scripts/daemon/integration.test.mjs +149 -0
- package/scripts/daemon/launchd-wrapper-generic.sh +96 -0
- package/scripts/daemon/launchd-wrapper-slack-events.sh +37 -0
- package/scripts/daemon/launchd-wrapper.sh +91 -0
- package/scripts/daemon/lib/session-router.mjs +274 -0
- package/scripts/daemon/lib/session-router.test.mjs +295 -0
- package/scripts/daemon/maestro-daemon.mjs +275 -0
- package/scripts/daemon/prompt-builder.mjs +685 -0
- package/scripts/daemon/prompt-builder.test.mjs +213 -0
- package/scripts/daemon/responder.mjs +854 -0
- package/scripts/daemon/session-lock.mjs +721 -0
- package/scripts/daemon/session-lock.test.mjs +252 -0
- package/scripts/daemon/session-outcomes.mjs +640 -0
- package/scripts/daemon/session-outcomes.test.mjs +533 -0
- package/scripts/daemon/typing-registry.mjs +90 -0
- package/scripts/daemon/typing-registry.test.mjs +77 -0
- package/scripts/daemon/voice-webhook-server.mjs +804 -0
- package/scripts/decisions/capture-decision.mjs +116 -0
- package/scripts/disclosure_assessment.py +873 -0
- package/scripts/disclosure_boundaries.py +562 -0
- package/scripts/email-signature-principal.html +52 -0
- package/scripts/email-signature.html +60 -0
- package/scripts/email_quote_thread.py +167 -0
- package/scripts/email_thread_dedup.py +362 -0
- package/scripts/emergency-stop.sh +81 -0
- package/scripts/healthcheck.sh +116 -0
- package/scripts/hooks/block-mcp-cohort-send.sh +15 -0
- package/scripts/hooks/block-mcp-slack-send.sh +7 -0
- package/scripts/hooks/post-action-log.sh +126 -0
- package/scripts/hooks/pre-send-audit.sh +174 -0
- package/scripts/hooks/pre-send-audit.test.mjs +215 -0
- package/scripts/hooks/session-end-log.sh +27 -0
- package/scripts/hooks/session-start-banner.sh +115 -0
- package/scripts/huddle/audio-bridge.mjs +664 -0
- package/scripts/huddle/boot-slack-cdp.sh +102 -0
- package/scripts/huddle/huddle-controller.mjs +942 -0
- package/scripts/huddle/huddle-server.mjs +1229 -0
- package/scripts/huddle/launch-slack.sh +232 -0
- package/scripts/huddle/openai-realtime-bridge.mjs +462 -0
- package/scripts/huddle/package-lock.json +62 -0
- package/scripts/huddle/package.json +22 -0
- package/scripts/huddle/setup-audio.sh +239 -0
- package/scripts/huddle/start-call.mjs +318 -0
- package/scripts/huddle/test-pipeline.mjs +263 -0
- package/scripts/learning/consolidate-skills.mjs +72 -0
- package/scripts/learning/session-search.mjs +125 -0
- package/scripts/llm_email_dedup.py +442 -0
- package/scripts/local-triggers/generate-plists.sh +432 -0
- package/scripts/local-triggers/generate-plists.test.mjs +413 -0
- package/scripts/local-triggers/install-all.sh +49 -0
- package/scripts/local-triggers/plists/.gitkeep +0 -0
- package/scripts/local-triggers/run-trigger.sh +63 -0
- package/scripts/local-triggers/templates/rag-reindex.plist.template +47 -0
- package/scripts/local-triggers/templates/voice-relay-poller.plist.template +54 -0
- package/scripts/local-triggers/templates/voice-tunnel.plist.template +55 -0
- package/scripts/local-triggers/templates/voice-webhook.plist.template +51 -0
- package/scripts/maintenance/backup-to-cloud.sh +124 -0
- package/scripts/maintenance/health-check.sh +377 -0
- package/scripts/media-generation/README.md +105 -0
- package/scripts/media-generation/gemini-image-client.mjs +173 -0
- package/scripts/media-generation/generate-assets.mjs +289 -0
- package/scripts/media-generation/veo-video-client.mjs +219 -0
- package/scripts/org/send-orgmail.mjs +227 -0
- package/scripts/outbound-dedup-cleanup.sh +43 -0
- package/scripts/outbound-dedup.sh +477 -0
- package/scripts/outbound_dedup.py +115 -0
- package/scripts/parse-voice-transcript.mjs +481 -0
- package/scripts/pdf-generation/README.md +63 -0
- package/scripts/pdf-generation/build-document.mjs +247 -0
- package/scripts/pdf-generation/templates/board-pack.latex +136 -0
- package/scripts/pdf-generation/templates/corporate-letter.latex +126 -0
- package/scripts/pdf-generation/templates/memo.latex +114 -0
- package/scripts/poll-slack-events.sh +35 -0
- package/scripts/poller/calendar-poller.mjs +12 -0
- package/scripts/poller/gmail-poller.mjs +192 -0
- package/scripts/poller/imap-client.mjs +289 -0
- package/scripts/poller/inbox-scan-poller.mjs +156 -0
- package/scripts/poller/inbox-scan-poller.test.mjs +231 -0
- package/scripts/poller/index.mjs +73 -0
- package/scripts/poller/intra-session-check.mjs +285 -0
- package/scripts/poller/lib/cloud-relay-dedup.mjs +88 -0
- package/scripts/poller/lib/cloud-relay-dedup.test.mjs +133 -0
- package/scripts/poller/lib/slash-command-handlers.mjs +177 -0
- package/scripts/poller/secondary-gmail-poller.mjs +132 -0
- package/scripts/poller/slack-cloud-relay-client.mjs +368 -0
- package/scripts/poller/slack-poller.mjs +854 -0
- package/scripts/poller/slack-socket-mode.mjs +917 -0
- package/scripts/poller/slack-socket-mode.test.mjs +753 -0
- package/scripts/poller/trigger.mjs +75 -0
- package/scripts/poller/utils.mjs +371 -0
- package/scripts/poller/voice-cloud-relay-client.mjs +179 -0
- package/scripts/poller/voice-poller.mjs +236 -0
- package/scripts/poller-launchd/install.sh +66 -0
- package/scripts/poller-launchd/poller.plist.template +40 -0
- package/scripts/poller-launchd/whatsapp-handler.plist.template +39 -0
- package/scripts/post-interaction-indexer.py +1598 -0
- package/scripts/pre-draft-context.py +994 -0
- package/scripts/pre_draft_lookup.py +258 -0
- package/scripts/rag/build-index.mjs +47 -0
- package/scripts/rag/ingest.mjs +111 -0
- package/scripts/rag/search.mjs +119 -0
- package/scripts/rag-indexer.py +629 -0
- package/scripts/restore-from-backup.sh +248 -0
- package/scripts/restore-from-backup.test.mjs +178 -0
- package/scripts/resume-operations.sh +80 -0
- package/scripts/search-secondary-inbox.py +181 -0
- package/scripts/secondary-inbox-poller.py +437 -0
- package/scripts/self-optimization/compute-metrics.py +398 -0
- package/scripts/send-email-as-principal.py +369 -0
- package/scripts/send-email-threaded.py +392 -0
- package/scripts/send-email-with-attachment.py +377 -0
- package/scripts/send-email.sh +131 -0
- package/scripts/send-sms.sh +175 -0
- package/scripts/send-whatsapp.sh +292 -0
- package/scripts/session-start.sh +106 -0
- package/scripts/setup/boot-claude-session.sh +94 -0
- package/scripts/setup/configure-macos.sh +674 -0
- package/scripts/setup/configure-twilio-sip-trunk.mjs +207 -0
- package/scripts/setup/configure-voice-tunnel.mjs +182 -0
- package/scripts/setup/generate-agent-env.mjs +92 -0
- package/scripts/setup/generate-agent-package-json.mjs +222 -0
- package/scripts/setup/generate-agent-package-json.test.mjs +143 -0
- package/scripts/setup/generate-autonomy.mjs +60 -0
- package/scripts/setup/generate-backlog.mjs +101 -0
- package/scripts/setup/generate-cadences.mjs +92 -0
- package/scripts/setup/generate-capability.mjs +162 -0
- package/scripts/setup/generate-charter.mjs +76 -0
- package/scripts/setup/generate-comms.mjs +59 -0
- package/scripts/setup/generate-company.mjs +92 -0
- package/scripts/setup/init-agent.sh +547 -0
- package/scripts/setup/init-agent.test.mjs +151 -0
- package/scripts/setup/init-archetype.mjs +74 -0
- package/scripts/setup/init-backup.mjs +54 -0
- package/scripts/setup/init-cadence-bus.mjs +60 -0
- package/scripts/setup/init-channel-bus.mjs +46 -0
- package/scripts/setup/init-cost-tracking.mjs +45 -0
- package/scripts/setup/init-decision-capture.mjs +66 -0
- package/scripts/setup/init-known-agents.mjs +57 -0
- package/scripts/setup/init-learning.mjs +70 -0
- package/scripts/setup/init-memory-executive.mjs +45 -0
- package/scripts/setup/init-model-router.mjs +124 -0
- package/scripts/setup/init-rag.mjs +174 -0
- package/scripts/setup/init-session-router.mjs +38 -0
- package/scripts/setup/init-slack-socket-mode.mjs +260 -0
- package/scripts/setup/init-telegram.mjs +165 -0
- package/scripts/setup/init-voice-realtime.mjs +204 -0
- package/scripts/setup/init-whatsapp-baileys.mjs +77 -0
- package/scripts/setup/install-dev-tools.sh +150 -0
- package/scripts/setup/lib/install-plist.mjs +95 -0
- package/scripts/setup/migrate-agent-to-sot.mjs +192 -0
- package/scripts/setup/render-environment-yaml.mjs +133 -0
- package/scripts/slack-events-ctl.sh +177 -0
- package/scripts/slack-events-server.mjs +1045 -0
- package/scripts/slack-react.mjs +89 -0
- package/scripts/slack-responded.sh +232 -0
- package/scripts/slack-send.sh +287 -0
- package/scripts/slack-typing.mjs +196 -0
- package/scripts/slack-upload-v2.py +95 -0
- package/scripts/sms-handler.mjs +450 -0
- package/scripts/spawn-session.sh +120 -0
- package/scripts/sync-protocol.mjs +217 -0
- package/scripts/system-verify.sh +184 -0
- package/scripts/test-email-thread-dedup.py +239 -0
- package/scripts/test-information-barriers.py +484 -0
- package/scripts/test-llm-email-dedup.py +251 -0
- package/scripts/test-pre-draft-integration.py +203 -0
- package/scripts/test-rag-phase2.sh +442 -0
- package/scripts/test-rag-search.sh +251 -0
- package/scripts/test-voice-parser.mjs +316 -0
- package/scripts/user-context-search.py +659 -0
- package/scripts/validate_outbound.py +1504 -0
- package/scripts/watchdog/ai.maestro.memory-watchdog.plist +41 -0
- package/scripts/watchdog/force-reboot.sh +157 -0
- package/scripts/watchdog/memory-watchdog.sh +473 -0
- package/scripts/whatsapp-handler.mjs +538 -0
- package/teams/desktop-operations.yaml +34 -0
- package/teams/executive-office.yaml +27 -0
- package/teams/legal-and-regulatory.yaml +24 -0
- package/teams/platform-and-engineering.yaml +23 -0
- package/teams/strategy-and-growth.yaml +29 -0
- package/workflows/continuous/backlog-executor.yaml +141 -0
- package/workflows/continuous/inbound-monitor.yaml +168 -0
- package/workflows/daily/applicant-triage.yaml +197 -0
- package/workflows/daily/comms-triage.yaml +80 -0
- package/workflows/daily/evening-wrap.yaml +105 -0
- package/workflows/daily/morning-brief.yaml +164 -0
- package/workflows/daily/slack-followup-sweep.yaml +87 -0
- package/workflows/event-driven/README.md +50 -0
- package/workflows/event-driven/agent-failure-investigation.yaml +137 -0
- package/workflows/event-driven/pr-review.yaml +107 -0
- package/workflows/monthly/board-readiness.yaml +76 -0
- package/workflows/quarterly/strategic-scenario-analysis.yaml +85 -0
- package/workflows/session-protocol.md +171 -0
- package/workflows/weekly/engineering-health.yaml +154 -0
- package/workflows/weekly/hiring-review.yaml +169 -0
- package/workflows/weekly/rollup-pipeline-review.yaml +76 -0
- package/workflows/weekly/strategic-memo.yaml +79 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
// init-agent.test.mjs — supply-chain hygiene of scripts/setup/init-agent.sh
|
|
2
|
+
//
|
|
3
|
+
// Item 0.11 (audit setup-onboarding W1/W2, policies-prompts F-15). Covers the
|
|
4
|
+
// global ~/.claude/settings.json handling: it must DEEP-MERGE maestro's
|
|
5
|
+
// additions into any pre-existing settings (preserving the operator's keys)
|
|
6
|
+
// rather than overwrite, and it must never install an allow-all permissions
|
|
7
|
+
// block or wire unpinned third-party (ruflo@latest) hooks.
|
|
8
|
+
//
|
|
9
|
+
// The deep-merge logic is embedded in init-agent.sh as the MAESTRO_MERGE_NODE
|
|
10
|
+
// program (between the BEGIN/END marker comments). We extract that *exact*
|
|
11
|
+
// program and exercise it via a subprocess — no duplicated logic — so the test
|
|
12
|
+
// pins what the script actually ships.
|
|
13
|
+
|
|
14
|
+
import { test } from "node:test";
|
|
15
|
+
import assert from "node:assert/strict";
|
|
16
|
+
import { readFileSync, writeFileSync, mkdtempSync, rmSync } from "node:fs";
|
|
17
|
+
import { execFileSync } from "node:child_process";
|
|
18
|
+
import { join, dirname } from "node:path";
|
|
19
|
+
import { tmpdir } from "node:os";
|
|
20
|
+
import { fileURLToPath } from "node:url";
|
|
21
|
+
|
|
22
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
23
|
+
const SCRIPT = join(__dirname, "init-agent.sh");
|
|
24
|
+
const scriptSrc = readFileSync(SCRIPT, "utf8");
|
|
25
|
+
|
|
26
|
+
// --- extract the embedded merge program (single source of truth) -----------
|
|
27
|
+
function extractMergeProgram() {
|
|
28
|
+
// MAESTRO_MERGE_NODE='<program>' — single-quoted bash heredoc-style literal.
|
|
29
|
+
const m = scriptSrc.match(/MAESTRO_MERGE_NODE='([\s\S]*?)'\n# --- END maestro settings deep-merge ---/);
|
|
30
|
+
assert.ok(m, "MAESTRO_MERGE_NODE program not found in init-agent.sh");
|
|
31
|
+
return m[1];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function makeTmp() {
|
|
35
|
+
const dir = mkdtempSync(join(tmpdir(), "init-agent-test-"));
|
|
36
|
+
return dir;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Run the extracted node merge program: existing settings JSON (or null for a
|
|
40
|
+
// missing file) + additions JSON on stdin -> returns the merged object.
|
|
41
|
+
function runMerge(existing, additions) {
|
|
42
|
+
const dir = makeTmp();
|
|
43
|
+
try {
|
|
44
|
+
const progPath = join(dir, "merge.cjs");
|
|
45
|
+
const inPath = join(dir, "settings.json");
|
|
46
|
+
const outPath = join(dir, "out.json");
|
|
47
|
+
writeFileSync(progPath, extractMergeProgram());
|
|
48
|
+
if (existing !== null) {
|
|
49
|
+
writeFileSync(inPath, typeof existing === "string" ? existing : JSON.stringify(existing));
|
|
50
|
+
}
|
|
51
|
+
execFileSync(process.execPath, [progPath, inPath, outPath], {
|
|
52
|
+
input: JSON.stringify(additions),
|
|
53
|
+
});
|
|
54
|
+
return JSON.parse(readFileSync(outPath, "utf8"));
|
|
55
|
+
} finally {
|
|
56
|
+
rmSync(dir, { recursive: true, force: true });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// The real additions block the script feeds in (subset that matters here).
|
|
61
|
+
const MAESTRO_ADDITIONS = {
|
|
62
|
+
$schema: "https://json.schemastore.org/claude-code-settings.json",
|
|
63
|
+
enabledPlugins: { "claude-mem": true, "context7@claude-plugins-official": true },
|
|
64
|
+
effortLevel: "high",
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
test("deep-merge preserves a pre-existing user key", () => {
|
|
68
|
+
const existing = {
|
|
69
|
+
myCustomKey: "keep-me",
|
|
70
|
+
enabledPlugins: { "user-only-plugin": true },
|
|
71
|
+
};
|
|
72
|
+
const merged = runMerge(existing, MAESTRO_ADDITIONS);
|
|
73
|
+
|
|
74
|
+
// User's top-level key survives.
|
|
75
|
+
assert.equal(merged.myCustomKey, "keep-me");
|
|
76
|
+
// User's plugin survives AND maestro's additions land alongside it (object merge).
|
|
77
|
+
assert.equal(merged.enabledPlugins["user-only-plugin"], true);
|
|
78
|
+
assert.equal(merged.enabledPlugins["claude-mem"], true);
|
|
79
|
+
assert.equal(merged.enabledPlugins["context7@claude-plugins-official"], true);
|
|
80
|
+
// Maestro scalar additions land when the user had nothing there.
|
|
81
|
+
assert.equal(merged.effortLevel, "high");
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test("existing scalar value wins over maestro addition (no clobber)", () => {
|
|
85
|
+
const existing = { effortLevel: "low", $schema: "user-schema" };
|
|
86
|
+
const merged = runMerge(existing, MAESTRO_ADDITIONS);
|
|
87
|
+
assert.equal(merged.effortLevel, "low", "user's effortLevel must not be overwritten");
|
|
88
|
+
assert.equal(merged.$schema, "user-schema", "user's $schema must not be overwritten");
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test("merge never emits an allow-all permissions block", () => {
|
|
92
|
+
const merged = runMerge({ someKey: 1 }, MAESTRO_ADDITIONS);
|
|
93
|
+
// No permissions block introduced by maestro at all.
|
|
94
|
+
assert.equal(merged.permissions, undefined);
|
|
95
|
+
const dumped = JSON.stringify(merged);
|
|
96
|
+
assert.ok(!dumped.includes("Bash(*)"), "must not contain Bash(*) allow-all");
|
|
97
|
+
assert.ok(!dumped.includes("Write(*)"), "must not contain Write(*) allow-all");
|
|
98
|
+
assert.ok(!dumped.includes("skipDangerousModePermissionPrompt"), "must not skip dangerous-mode prompt");
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test("a pre-existing user permissions block is preserved untouched", () => {
|
|
102
|
+
const existing = {
|
|
103
|
+
permissions: { allow: ["Read(/safe/*)"], deny: ["Bash(rm -rf /)"] },
|
|
104
|
+
};
|
|
105
|
+
const merged = runMerge(existing, MAESTRO_ADDITIONS);
|
|
106
|
+
assert.deepEqual(merged.permissions.allow, ["Read(/safe/*)"]);
|
|
107
|
+
assert.deepEqual(merged.permissions.deny, ["Bash(rm -rf /)"]);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test("merge handles a missing settings file (fresh machine)", () => {
|
|
111
|
+
const merged = runMerge(null, MAESTRO_ADDITIONS);
|
|
112
|
+
assert.equal(merged.effortLevel, "high");
|
|
113
|
+
assert.equal(merged.enabledPlugins["claude-mem"], true);
|
|
114
|
+
assert.equal(merged.permissions, undefined);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test("merge handles invalid/corrupt existing JSON by starting fresh", () => {
|
|
118
|
+
const merged = runMerge("{ not valid json", MAESTRO_ADDITIONS);
|
|
119
|
+
assert.equal(merged.effortLevel, "high");
|
|
120
|
+
assert.equal(merged.permissions, undefined);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// --- static guards on the script source ------------------------------------
|
|
124
|
+
|
|
125
|
+
test("init-agent.sh no longer wires unpinned ruflo@latest hooks", () => {
|
|
126
|
+
assert.ok(!/ruflo@latest/.test(scriptSrc), "ruflo@latest must be removed (supply-chain RCE)");
|
|
127
|
+
assert.ok(!/\bruflo\b/.test(scriptSrc), "no ruflo references should remain");
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
test("init-agent.sh additions contain no allow-all permissions or dangerous-skip", () => {
|
|
131
|
+
const m = scriptSrc.match(/MAESTRO_SETTINGS_ADDITIONS='([\s\S]*?)'\n/);
|
|
132
|
+
assert.ok(m, "MAESTRO_SETTINGS_ADDITIONS block not found");
|
|
133
|
+
const additions = JSON.parse(m[1]);
|
|
134
|
+
assert.equal(additions.permissions, undefined, "additions must not ship a permissions block");
|
|
135
|
+
assert.equal(additions.skipDangerousModePermissionPrompt, undefined,
|
|
136
|
+
"additions must not skip the dangerous-mode prompt");
|
|
137
|
+
assert.ok(!m[1].includes("Bash(*)"), "additions must not contain Bash(*) allow-all");
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
test("init-agent.sh chmods the .env to 600", () => {
|
|
141
|
+
assert.ok(/chmod 600 "\$ENV_FILE"/.test(scriptSrc),
|
|
142
|
+
"the agent .env must be chmod 600 after writing (no world-readable credentials)");
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
test("init-agent.sh deep-merges rather than cat>-overwriting settings.json", () => {
|
|
146
|
+
// The old destructive `cat > "$CLAUDE_SETTINGS"` heredoc must be gone.
|
|
147
|
+
assert.ok(!/cat > "\$CLAUDE_SETTINGS"/.test(scriptSrc),
|
|
148
|
+
"settings.json must be deep-merged, not overwritten via cat >");
|
|
149
|
+
assert.ok(scriptSrc.includes("node -e \"$MAESTRO_MERGE_NODE\""),
|
|
150
|
+
"the merge must run via the embedded node program");
|
|
151
|
+
});
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* init-archetype.mjs — agent-side init for the function × altitude archetype library.
|
|
4
|
+
*
|
|
5
|
+
* Run by `maestro upgrade` (auto:true) and the init wizard. Ensures the agent's
|
|
6
|
+
* config/agent.json carries a valid { function, altitude } pair, migrating a
|
|
7
|
+
* legacy single-axis `archetype` value (the six legacy archetypes ARE the six
|
|
8
|
+
* functions, so they map to { function: <same>, altitude: c-suite }). Resolves +
|
|
9
|
+
* validates the operating profile via the framework's archetypes/ library; fails
|
|
10
|
+
* closed if invalid. Idempotent — a no-op once normalised.
|
|
11
|
+
*
|
|
12
|
+
* Execution contract (see lib/feature-init.mjs runInitCommand): invoked with
|
|
13
|
+
* cwd = agent repo, env AGENT_ROOT / MAESTRO_ROOT set; the script itself may be
|
|
14
|
+
* the framework copy. We therefore load the resolver from MAESTRO_ROOT when set.
|
|
15
|
+
*
|
|
16
|
+
* @module scripts/setup/init-archetype
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
"use strict";
|
|
20
|
+
|
|
21
|
+
import { readFileSync, writeFileSync, existsSync } from "node:fs";
|
|
22
|
+
import { join, dirname, resolve } from "node:path";
|
|
23
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
24
|
+
|
|
25
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
26
|
+
const MAESTRO_ROOT =
|
|
27
|
+
process.env.MAESTRO_ROOT && existsSync(join(process.env.MAESTRO_ROOT, "lib", "archetype.mjs"))
|
|
28
|
+
? process.env.MAESTRO_ROOT
|
|
29
|
+
: resolve(here, "..", "..");
|
|
30
|
+
const AGENT_ROOT = process.env.AGENT_ROOT || process.cwd();
|
|
31
|
+
|
|
32
|
+
async function main() {
|
|
33
|
+
const arch = await import(pathToFileURL(join(MAESTRO_ROOT, "lib", "archetype.mjs")).href);
|
|
34
|
+
const { resolveArchetype, migrateLegacyArchetype, deriveLegacyArchetype, listFunctions, listAltitudes } = arch;
|
|
35
|
+
|
|
36
|
+
const cfgPath = join(AGENT_ROOT, "config", "agent.json");
|
|
37
|
+
if (!existsSync(cfgPath)) {
|
|
38
|
+
console.log(`[init-archetype] no config/agent.json at ${cfgPath} — skipping (run from an agent repo).`);
|
|
39
|
+
return 0;
|
|
40
|
+
}
|
|
41
|
+
const cfg = JSON.parse(readFileSync(cfgPath, "utf-8"));
|
|
42
|
+
|
|
43
|
+
let sel = null;
|
|
44
|
+
if (cfg.function && cfg.altitude) {
|
|
45
|
+
sel = { function: cfg.function, altitude: cfg.altitude };
|
|
46
|
+
} else if (cfg.archetype) {
|
|
47
|
+
sel = migrateLegacyArchetype(cfg.archetype);
|
|
48
|
+
if (sel) console.log(`[init-archetype] migrated legacy archetype "${cfg.archetype}" → ${sel.function} × ${sel.altitude}`);
|
|
49
|
+
}
|
|
50
|
+
if (!sel) {
|
|
51
|
+
console.error("[init-archetype] config/agent.json has no { function, altitude } and no legacy archetype.");
|
|
52
|
+
console.error(` Set "function" to one of [${listFunctions().join(", ")}] and "altitude" to one of [${listAltitudes().join(", ")}].`);
|
|
53
|
+
return 1;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const profile = await resolveArchetype(sel); // throws if the resolved profile is invalid
|
|
57
|
+
|
|
58
|
+
if (cfg.function !== sel.function || cfg.altitude !== sel.altitude || cfg.archetype !== deriveLegacyArchetype(sel)) {
|
|
59
|
+
cfg.function = sel.function;
|
|
60
|
+
cfg.altitude = sel.altitude;
|
|
61
|
+
cfg.archetype = deriveLegacyArchetype(sel);
|
|
62
|
+
writeFileSync(cfgPath, JSON.stringify(cfg, null, 2) + "\n", "utf-8");
|
|
63
|
+
console.log("[init-archetype] normalised config/agent.json (function / altitude / archetype).");
|
|
64
|
+
}
|
|
65
|
+
console.log(`[init-archetype] OK — ${profile.label} (${profile.function} × ${profile.altitude})`);
|
|
66
|
+
return 0;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
main()
|
|
70
|
+
.then((code) => process.exit(code))
|
|
71
|
+
.catch((err) => {
|
|
72
|
+
console.error(`[init-archetype] FAILED: ${err && err.message ? err.message : err}`);
|
|
73
|
+
process.exit(1);
|
|
74
|
+
});
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* init-backup.mjs — Off-machine state backup wizard.
|
|
4
|
+
*
|
|
5
|
+
* Configures `.maestro/backup-config.yaml` with bucket details and seeds
|
|
6
|
+
* a daily launchd plist that runs scripts/maintenance/backup-to-cloud.sh.
|
|
7
|
+
* Requires interactive input — does NOT auto-run.
|
|
8
|
+
*/
|
|
9
|
+
import { existsSync, writeFileSync, mkdirSync } from "node:fs";
|
|
10
|
+
import { join, resolve, dirname } from "node:path";
|
|
11
|
+
import { fileURLToPath } from "node:url";
|
|
12
|
+
|
|
13
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
const AGENT_DIR = process.env.AGENT_ROOT || process.env.AGENT_DIR || resolve(__dirname, "..", "..");
|
|
15
|
+
|
|
16
|
+
const ok = (m) => process.stdout.write(`[init-backup] ✓ ${m}\n`);
|
|
17
|
+
const warn = (m) => process.stdout.write(`[init-backup] ⚠ ${m}\n`);
|
|
18
|
+
|
|
19
|
+
mkdirSync(join(AGENT_DIR, ".maestro"), { recursive: true });
|
|
20
|
+
const cfg = join(AGENT_DIR, ".maestro/backup-config.yaml");
|
|
21
|
+
if (existsSync(cfg)) {
|
|
22
|
+
ok("backup-config.yaml already present");
|
|
23
|
+
process.exit(0);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
writeFileSync(cfg, `# Off-machine state backup configuration
|
|
27
|
+
# Fill in the bucket details, then run:
|
|
28
|
+
# maestro init backup-replication --apply
|
|
29
|
+
#
|
|
30
|
+
# Backups cover (configurable below):
|
|
31
|
+
# - state/ (queues, dashboards, inboxes — minus state/tmp/)
|
|
32
|
+
# - knowledge/
|
|
33
|
+
# - outputs/
|
|
34
|
+
# - logs/ (rotated archives only — current-day logs excluded)
|
|
35
|
+
# - config/agent.json (identity SOT)
|
|
36
|
+
|
|
37
|
+
enabled: false
|
|
38
|
+
provider: gcs # gcs | s3 | rsync
|
|
39
|
+
bucket: "" # e.g. northwind-maestro-backups
|
|
40
|
+
prefix: agent-name-here # e.g. ravi-ai (typically the repoSlug)
|
|
41
|
+
schedule: "0 3 * * *" # daily 03:00 local (overrides via launchd plist)
|
|
42
|
+
include:
|
|
43
|
+
- state
|
|
44
|
+
- knowledge
|
|
45
|
+
- outputs
|
|
46
|
+
- logs
|
|
47
|
+
- config/agent.json
|
|
48
|
+
exclude:
|
|
49
|
+
- state/tmp
|
|
50
|
+
- state/rag/index/*.bin
|
|
51
|
+
retention_days: 30
|
|
52
|
+
`);
|
|
53
|
+
ok(`wrote ${cfg}`);
|
|
54
|
+
warn("Backup is configured but NOT enabled. Edit .maestro/backup-config.yaml + set enabled: true, then re-run init.");
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* init-cadence-bus.mjs — Idempotent init step for the cadence-bus feature.
|
|
4
|
+
*
|
|
5
|
+
* Called by `maestro init` / `maestro upgrade` (via the feature-init
|
|
6
|
+
* tracker). Safe to run repeatedly. Verifies state/cadence-bus/{inbox,
|
|
7
|
+
* claimed,processed,failed,dlq} exist + logs/cadence-bus/ exists +
|
|
8
|
+
* generated launchd plists are on the cadence-bus arch.
|
|
9
|
+
*/
|
|
10
|
+
import { dirname, join, resolve } from "node:path";
|
|
11
|
+
import { fileURLToPath } from "node:url";
|
|
12
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
13
|
+
|
|
14
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
15
|
+
const AGENT_DIR = process.env.AGENT_ROOT || process.env.AGENT_DIR || resolve(__dirname, "..", "..");
|
|
16
|
+
|
|
17
|
+
const ok = (m) => process.stdout.write(`[init-cadence-bus] ✓ ${m}\n`);
|
|
18
|
+
const warn = (m) => process.stdout.write(`[init-cadence-bus] ⚠ ${m}\n`);
|
|
19
|
+
|
|
20
|
+
// Directory tree (mirror of cadence-bus.mjs's bootstrap).
|
|
21
|
+
for (const d of [
|
|
22
|
+
"state/cadence-bus/inbox",
|
|
23
|
+
"state/cadence-bus/claimed",
|
|
24
|
+
"state/cadence-bus/processed",
|
|
25
|
+
"state/cadence-bus/failed",
|
|
26
|
+
"state/cadence-bus/dlq",
|
|
27
|
+
"logs/cadence-bus",
|
|
28
|
+
]) {
|
|
29
|
+
const full = join(AGENT_DIR, d);
|
|
30
|
+
if (!existsSync(full)) {
|
|
31
|
+
mkdirSync(full, { recursive: true });
|
|
32
|
+
ok(`created ${d}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Version marker file.
|
|
37
|
+
const versionFile = join(AGENT_DIR, "state/cadence-bus/VERSION");
|
|
38
|
+
if (!existsSync(versionFile)) {
|
|
39
|
+
writeFileSync(versionFile, "1\n");
|
|
40
|
+
ok("seeded state/cadence-bus/VERSION");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Plist arch verification — flag (don't fix here, that's upgrade's job).
|
|
44
|
+
const plistDir = join(AGENT_DIR, "scripts/local-triggers/plists");
|
|
45
|
+
if (existsSync(plistDir)) {
|
|
46
|
+
let legacy = 0;
|
|
47
|
+
for (const name of readdirSync(plistDir)) {
|
|
48
|
+
if (!name.endsWith(".plist")) continue;
|
|
49
|
+
const body = readFileSync(join(plistDir, name), "utf-8");
|
|
50
|
+
if (body.includes("run-trigger.sh")) legacy++;
|
|
51
|
+
}
|
|
52
|
+
if (legacy > 0) {
|
|
53
|
+
warn(`${legacy} generated plist(s) still use the legacy spawn-per-tick pattern.`);
|
|
54
|
+
warn(" Run: npx @cohortapp/agent-sdk upgrade (will back up + regenerate)");
|
|
55
|
+
} else {
|
|
56
|
+
ok("plist arch verified");
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
ok("done");
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* init-channel-bus.mjs — Idempotent init for the channel-bus feature.
|
|
4
|
+
*
|
|
5
|
+
* Creates state/channels/ for any per-channel state, and verifies that
|
|
6
|
+
* lib/channels/ is present in the framework install. No-op if either
|
|
7
|
+
* already exist. The actual channel registration happens at daemon
|
|
8
|
+
* startup in scripts/daemon/maestro-daemon.mjs (which the framework
|
|
9
|
+
* upgrade will patch); this wizard only sets up the supporting
|
|
10
|
+
* filesystem layout.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { dirname, join, resolve } from "node:path";
|
|
14
|
+
import { fileURLToPath } from "node:url";
|
|
15
|
+
import { existsSync, mkdirSync } from "node:fs";
|
|
16
|
+
|
|
17
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
18
|
+
const AGENT_DIR = process.env.AGENT_ROOT || process.env.AGENT_DIR || resolve(__dirname, "..", "..");
|
|
19
|
+
const MAESTRO_ROOT = process.env.MAESTRO_ROOT || resolve(__dirname, "..", "..");
|
|
20
|
+
|
|
21
|
+
const ok = (m) => process.stdout.write(`[init-channel-bus] ✓ ${m}\n`);
|
|
22
|
+
const warn = (m) => process.stdout.write(`[init-channel-bus] ⚠ ${m}\n`);
|
|
23
|
+
const info = (m) => process.stdout.write(`[init-channel-bus] · ${m}\n`);
|
|
24
|
+
|
|
25
|
+
// Sanity: lib/channels/ must exist in the framework install.
|
|
26
|
+
const channelsLib = join(MAESTRO_ROOT, "lib/channels/channel.mjs");
|
|
27
|
+
if (!existsSync(channelsLib)) {
|
|
28
|
+
warn(`lib/channels/ not present in framework at ${MAESTRO_ROOT}`);
|
|
29
|
+
warn("Run `npm run upgrade` (maestro >= 1.12.0) and retry.");
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
for (const d of [
|
|
34
|
+
"state/channels",
|
|
35
|
+
"logs/channels",
|
|
36
|
+
]) {
|
|
37
|
+
const full = join(AGENT_DIR, d);
|
|
38
|
+
if (!existsSync(full)) {
|
|
39
|
+
mkdirSync(full, { recursive: true });
|
|
40
|
+
ok(`created ${d}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
info("channel bus ready. Channels register themselves at daemon startup —");
|
|
45
|
+
info("see lib/channels/index.mjs and scripts/daemon/channel-bus.mjs.");
|
|
46
|
+
ok("done");
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* init-cost-tracking.mjs — Set up local cost tracking ledger + dashboard.
|
|
4
|
+
*
|
|
5
|
+
* State:
|
|
6
|
+
* state/cost-tracking/<date>.jsonl — per-day token ledger
|
|
7
|
+
* state/dashboards/cost-summary.yaml — rollup
|
|
8
|
+
*
|
|
9
|
+
* The actual tracker is scripts/cost/track-claude-usage.mjs (shipped by the
|
|
10
|
+
* framework) which is wired into the cadence-consumer's session-spawn path.
|
|
11
|
+
*/
|
|
12
|
+
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
13
|
+
import { join, resolve, dirname } from "node:path";
|
|
14
|
+
import { fileURLToPath } from "node:url";
|
|
15
|
+
|
|
16
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
17
|
+
const AGENT_DIR = process.env.AGENT_ROOT || process.env.AGENT_DIR || resolve(__dirname, "..", "..");
|
|
18
|
+
|
|
19
|
+
const ok = (m) => process.stdout.write(`[init-cost-tracking] ✓ ${m}\n`);
|
|
20
|
+
|
|
21
|
+
for (const d of ["state/cost-tracking", "state/dashboards"]) {
|
|
22
|
+
const full = join(AGENT_DIR, d);
|
|
23
|
+
if (!existsSync(full)) {
|
|
24
|
+
mkdirSync(full, { recursive: true });
|
|
25
|
+
ok(`created ${d}`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const summary = join(AGENT_DIR, "state/dashboards/cost-summary.yaml");
|
|
30
|
+
if (!existsSync(summary)) {
|
|
31
|
+
writeFileSync(summary, `# Cost summary — auto-regenerated by scripts/cost/track-claude-usage.mjs
|
|
32
|
+
generated: null
|
|
33
|
+
window_days: 7
|
|
34
|
+
totals:
|
|
35
|
+
sessions: 0
|
|
36
|
+
input_tokens: 0
|
|
37
|
+
output_tokens: 0
|
|
38
|
+
estimated_usd: 0
|
|
39
|
+
by_model: {}
|
|
40
|
+
by_cadence: {}
|
|
41
|
+
`);
|
|
42
|
+
ok("seeded cost-summary.yaml");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
ok("done");
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* init-decision-capture.mjs — Wire decision-capture automation.
|
|
4
|
+
*
|
|
5
|
+
* Ensures knowledge/decisions/{decision-schema,index}.yaml exist and
|
|
6
|
+
* creates scripts/decisions/capture-decision.mjs locally (the helper
|
|
7
|
+
* that the agent invokes when recording a decision).
|
|
8
|
+
*/
|
|
9
|
+
import { existsSync, mkdirSync, writeFileSync, copyFileSync } from "node:fs";
|
|
10
|
+
import { join, resolve, dirname } from "node:path";
|
|
11
|
+
import { fileURLToPath } from "node:url";
|
|
12
|
+
|
|
13
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
const AGENT_DIR = process.env.AGENT_ROOT || process.env.AGENT_DIR || resolve(__dirname, "..", "..");
|
|
15
|
+
const MAESTRO_ROOT = process.env.MAESTRO_ROOT || resolve(__dirname, "..", "..");
|
|
16
|
+
|
|
17
|
+
const ok = (m) => process.stdout.write(`[init-decision-capture] ✓ ${m}\n`);
|
|
18
|
+
|
|
19
|
+
for (const d of ["knowledge/decisions", "knowledge/decisions/archive", "scripts/decisions"]) {
|
|
20
|
+
const full = join(AGENT_DIR, d);
|
|
21
|
+
if (!existsSync(full)) {
|
|
22
|
+
mkdirSync(full, { recursive: true });
|
|
23
|
+
ok(`created ${d}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Copy the framework's capture-decision helper if present.
|
|
28
|
+
const src = join(MAESTRO_ROOT, "scripts/decisions/capture-decision.mjs");
|
|
29
|
+
const dst = join(AGENT_DIR, "scripts/decisions/capture-decision.mjs");
|
|
30
|
+
if (existsSync(src) && !existsSync(dst)) {
|
|
31
|
+
copyFileSync(src, dst);
|
|
32
|
+
ok(`copied capture-decision.mjs`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Seed index.yaml + schema if missing.
|
|
36
|
+
const schemaPath = join(AGENT_DIR, "knowledge/decisions/decision-schema.yaml");
|
|
37
|
+
if (!existsSync(schemaPath)) {
|
|
38
|
+
writeFileSync(schemaPath, `# Decision Record Schema (Maestro decision-capture v1)
|
|
39
|
+
# Each decision is a YAML doc named DEC-YYYY-MM-DD-NNN.yaml under knowledge/decisions/.
|
|
40
|
+
|
|
41
|
+
schema:
|
|
42
|
+
version: "1"
|
|
43
|
+
fields:
|
|
44
|
+
id: { type: string, format: "DEC-YYYY-MM-DD-NNN", required: true }
|
|
45
|
+
date: { type: date, format: "YYYY-MM-DD", required: true }
|
|
46
|
+
title: { type: string, required: true }
|
|
47
|
+
domain: { type: string, required: true }
|
|
48
|
+
decision_maker: { type: string, required: true }
|
|
49
|
+
decision_text: { type: string, required: true }
|
|
50
|
+
context: { type: string, required: true }
|
|
51
|
+
rationale: { type: string, required: true }
|
|
52
|
+
alternatives: { type: array, required: false }
|
|
53
|
+
stakeholders: { type: array, required: false }
|
|
54
|
+
expires_at: { type: date, required: false }
|
|
55
|
+
status: { type: string, enum: [active, superseded, reversed, completed], default: active }
|
|
56
|
+
`);
|
|
57
|
+
ok("seeded decision-schema.yaml");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const indexPath = join(AGENT_DIR, "knowledge/decisions/index.yaml");
|
|
61
|
+
if (!existsSync(indexPath)) {
|
|
62
|
+
writeFileSync(indexPath, "# Decision Index — auto-maintained by capture-decision.mjs\ndecisions: []\n");
|
|
63
|
+
ok("seeded decision index");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
ok("done");
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* init-known-agents.mjs — Scaffold config/known-agents.json
|
|
4
|
+
*
|
|
5
|
+
* The Northwind agent roster is shipped as a starter; agents that have
|
|
6
|
+
* already populated their own known-agents.json keep theirs (this init
|
|
7
|
+
* step is idempotent and never overwrites).
|
|
8
|
+
*
|
|
9
|
+
* classifier.mjs reads this file at runtime to detect peer @mentions in
|
|
10
|
+
* Slack/Gmail so an agent doesn't respond to messages routed at another
|
|
11
|
+
* agent.
|
|
12
|
+
*/
|
|
13
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
14
|
+
import { join, dirname, resolve } from "node:path";
|
|
15
|
+
import { fileURLToPath } from "node:url";
|
|
16
|
+
|
|
17
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
18
|
+
const AGENT_DIR = process.env.AGENT_ROOT || process.env.AGENT_DIR || resolve(__dirname, "..", "..");
|
|
19
|
+
|
|
20
|
+
const ok = (m) => process.stdout.write(`[init-known-agents] ✓ ${m}\n`);
|
|
21
|
+
|
|
22
|
+
const TARGET = join(AGENT_DIR, "config", "known-agents.json");
|
|
23
|
+
const MAESTRO_ROOT = process.env.MAESTRO_ROOT || resolve(__dirname, "..", "..");
|
|
24
|
+
const SCAFFOLD = join(MAESTRO_ROOT, "scaffold", "config", "known-agents.json");
|
|
25
|
+
|
|
26
|
+
mkdirSync(dirname(TARGET), { recursive: true });
|
|
27
|
+
|
|
28
|
+
if (existsSync(TARGET)) {
|
|
29
|
+
// Already present — verify shape and exit. We don't merge upstream
|
|
30
|
+
// additions into existing files to avoid surprising the operator.
|
|
31
|
+
try {
|
|
32
|
+
const current = JSON.parse(readFileSync(TARGET, "utf-8"));
|
|
33
|
+
const count = Array.isArray(current.agents) ? current.agents.length : 0;
|
|
34
|
+
ok(`already present (${count} agents)`);
|
|
35
|
+
process.exit(0);
|
|
36
|
+
} catch (err) {
|
|
37
|
+
process.stderr.write(`[init-known-agents] existing file is invalid JSON: ${err.message}\n`);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Copy from scaffold (the framework's canonical roster); fall back to a
|
|
43
|
+
// minimal stub if the scaffold is missing.
|
|
44
|
+
let payload;
|
|
45
|
+
if (existsSync(SCAFFOLD)) {
|
|
46
|
+
payload = readFileSync(SCAFFOLD, "utf-8");
|
|
47
|
+
ok(`copied from ${SCAFFOLD}`);
|
|
48
|
+
} else {
|
|
49
|
+
payload = JSON.stringify({
|
|
50
|
+
schema_version: "1",
|
|
51
|
+
agents: [],
|
|
52
|
+
}, null, 2) + "\n";
|
|
53
|
+
ok("scaffold not found — wrote empty roster");
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
writeFileSync(TARGET, payload);
|
|
57
|
+
ok(`wrote ${TARGET}`);
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* init-learning.mjs — provision the self-learning loop (WS3) into an agent repo.
|
|
4
|
+
*
|
|
5
|
+
* Idempotent + auto-runnable (no TTY): used by `maestro upgrade` to roll WS3 into
|
|
6
|
+
* agents that predate it, and mirrors what lib/setup/sections/learning.mjs does
|
|
7
|
+
* for fresh installs. Seeds:
|
|
8
|
+
* - config/learning.yaml (copied from scaffold; never clobbers an
|
|
9
|
+
* existing operator-customised file)
|
|
10
|
+
* - state/learning/counters.json (zero state for the nudge counters)
|
|
11
|
+
* - state/learning/ (holds counters + the sessions.db FTS5 store)
|
|
12
|
+
*
|
|
13
|
+
* The actual skill-authoring runs out-of-band in the Stop-hook reflect worker;
|
|
14
|
+
* the global hook is wired by `maestro global-setup`, not here.
|
|
15
|
+
*
|
|
16
|
+
* @module scripts/setup/init-learning
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { existsSync, mkdirSync, writeFileSync, copyFileSync } from "node:fs";
|
|
20
|
+
import { join, resolve, dirname } from "node:path";
|
|
21
|
+
import { fileURLToPath } from "node:url";
|
|
22
|
+
|
|
23
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
24
|
+
const MAESTRO_ROOT =
|
|
25
|
+
process.env.MAESTRO_ROOT && existsSync(join(process.env.MAESTRO_ROOT, "scaffold"))
|
|
26
|
+
? process.env.MAESTRO_ROOT
|
|
27
|
+
: resolve(__dirname, "..", "..");
|
|
28
|
+
const AGENT_DIR = process.env.AGENT_ROOT || process.env.AGENT_DIR || resolve(__dirname, "..", "..");
|
|
29
|
+
|
|
30
|
+
const ok = (m) => process.stdout.write(`[init-learning] ✓ ${m}\n`);
|
|
31
|
+
|
|
32
|
+
async function main() {
|
|
33
|
+
mkdirSync(join(AGENT_DIR, "state", "learning"), { recursive: true });
|
|
34
|
+
mkdirSync(join(AGENT_DIR, "config"), { recursive: true });
|
|
35
|
+
|
|
36
|
+
// 1. config/learning.yaml — from scaffold, never overwrite an existing file.
|
|
37
|
+
const cfgDst = join(AGENT_DIR, "config", "learning.yaml");
|
|
38
|
+
if (!existsSync(cfgDst)) {
|
|
39
|
+
const scaffold = join(MAESTRO_ROOT, "scaffold", "config", "learning.yaml");
|
|
40
|
+
if (existsSync(scaffold)) { copyFileSync(scaffold, cfgDst); ok("wrote config/learning.yaml (from scaffold)"); }
|
|
41
|
+
else {
|
|
42
|
+
writeFileSync(cfgDst, "# config/learning.yaml — Self-Learning Loop (WS3)\nenabled: true\nminTurns: 4\nreviewModel: sonnet\n");
|
|
43
|
+
ok("wrote config/learning.yaml (stub)");
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// 2. state/learning/counters.json — zero state.
|
|
48
|
+
const countersDst = join(AGENT_DIR, "state", "learning", "counters.json");
|
|
49
|
+
if (!existsSync(countersDst)) {
|
|
50
|
+
try {
|
|
51
|
+
const { emptyCounters } = await import(resolve(MAESTRO_ROOT, "lib", "learning", "counters.mjs"));
|
|
52
|
+
writeFileSync(countersDst, JSON.stringify(emptyCounters(), null, 2) + "\n");
|
|
53
|
+
} catch {
|
|
54
|
+
writeFileSync(countersDst, JSON.stringify({ tool_uses_since_skill: 0, sessions_since_skill: 0, last_skill_at: null, last_reflect_at: null }, null, 2) + "\n");
|
|
55
|
+
}
|
|
56
|
+
ok("seeded state/learning/counters.json");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// 3. Best-effort: warm the transcript search index from existing session logs.
|
|
60
|
+
try {
|
|
61
|
+
const { ingestAll } = await import(resolve(MAESTRO_ROOT, "lib", "learning", "session-index.mjs"));
|
|
62
|
+
const r = await ingestAll({ agentRoot: AGENT_DIR });
|
|
63
|
+
if (r.files) ok(`indexed ${r.added} session transcript(s) into state/learning/sessions.db`);
|
|
64
|
+
} catch { /* on-demand store; non-fatal */ }
|
|
65
|
+
|
|
66
|
+
ok("done");
|
|
67
|
+
return 0;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
main().then((c) => process.exit(c || 0)).catch((e) => { process.stderr.write(`[init-learning] ${e && e.message ? e.message : e}\n`); process.exit(1); });
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* init-memory-executive.mjs — Create memory/executive/ + memory/workstreams/
|
|
4
|
+
* Referenced by agents/ceo-briefing/agent.md and several skill prompts.
|
|
5
|
+
*
|
|
6
|
+
* Seeds priorities.md and open-loops.md so morning-brief / evening-wrap
|
|
7
|
+
* don't fail on a missing file.
|
|
8
|
+
*/
|
|
9
|
+
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
10
|
+
import { join, resolve, dirname } from "node:path";
|
|
11
|
+
import { fileURLToPath } from "node:url";
|
|
12
|
+
|
|
13
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
const AGENT_DIR = process.env.AGENT_ROOT || process.env.AGENT_DIR || resolve(__dirname, "..", "..");
|
|
15
|
+
|
|
16
|
+
const ok = (m) => process.stdout.write(`[init-memory-executive] ✓ ${m}\n`);
|
|
17
|
+
|
|
18
|
+
const DIRS = [
|
|
19
|
+
"memory/executive",
|
|
20
|
+
"memory/workstreams",
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
for (const d of DIRS) {
|
|
24
|
+
const full = join(AGENT_DIR, d);
|
|
25
|
+
if (!existsSync(full)) {
|
|
26
|
+
mkdirSync(full, { recursive: true });
|
|
27
|
+
ok(`created ${d}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const seeds = {
|
|
32
|
+
"memory/executive/priorities.md": "# Executive Priorities\n\nCurrent strategic priorities maintained by the agent. Updated weekly.\n\n_Populate via /init-maestro or by the weekly-priorities cadence._\n",
|
|
33
|
+
"memory/executive/open-loops.md": "# Open Loops\n\nOutstanding commitments awaiting closure. Updated by inbox-processor and evening-wrap cadences.\n\n_Format: each loop has owner, deadline, blocker, last-touched._\n",
|
|
34
|
+
"memory/workstreams/README.md": "# Workstreams\n\nOne markdown file per active workstream. Updated by the relevant cadence (weekly-execution, weekly-engineering-health, etc.) to reflect current status, blockers, and next milestones.\n",
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
for (const [path, body] of Object.entries(seeds)) {
|
|
38
|
+
const full = join(AGENT_DIR, path);
|
|
39
|
+
if (!existsSync(full)) {
|
|
40
|
+
writeFileSync(full, body);
|
|
41
|
+
ok(`seeded ${path}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
ok("done");
|