@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,538 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Agent WhatsApp Handler — Twilio Inbound WhatsApp Webhook
|
|
4
|
+
*
|
|
5
|
+
* Receives inbound WhatsApp messages via Twilio webhook, maps senders to known
|
|
6
|
+
* contacts, writes messages to the inbox for the inbox processor, and logs everything.
|
|
7
|
+
*
|
|
8
|
+
* WhatsApp messages arrive at Twilio via the same Messages webhook as SMS, but
|
|
9
|
+
* with "whatsapp:" prefix on the From/To fields. This handler listens on a
|
|
10
|
+
* separate port so it can be configured as the WhatsApp-specific webhook in Twilio.
|
|
11
|
+
*
|
|
12
|
+
* Endpoints:
|
|
13
|
+
* POST /whatsapp — Twilio WhatsApp webhook (returns TwiML)
|
|
14
|
+
* POST /whatsapp/status — Delivery status callback
|
|
15
|
+
* GET /health — Health check
|
|
16
|
+
*
|
|
17
|
+
* Environment:
|
|
18
|
+
* TWILIO_ACCOUNT_SID — For request validation
|
|
19
|
+
* TWILIO_AUTH_TOKEN — For request validation
|
|
20
|
+
* WHATSAPP_PORT — Port to listen on (default: 3002)
|
|
21
|
+
*
|
|
22
|
+
* Usage:
|
|
23
|
+
* node scripts/whatsapp-handler.mjs
|
|
24
|
+
*
|
|
25
|
+
* Configure in Twilio Console:
|
|
26
|
+
* WhatsApp Sandbox (or WABA) → "When a message comes in" → POST → <url>/whatsapp
|
|
27
|
+
* Status callback → POST → <url>/whatsapp/status
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
import fs from "node:fs";
|
|
31
|
+
import path from "node:path";
|
|
32
|
+
import http from "node:http";
|
|
33
|
+
import { URL } from "node:url";
|
|
34
|
+
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
// Configuration
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
|
|
39
|
+
const PORT = parseInt(process.env.WHATSAPP_PORT || "3002", 10);
|
|
40
|
+
const AGENT_REPO_DIR =
|
|
41
|
+
process.env.AGENT_DIR ||
|
|
42
|
+
process.env.AGENT_REPO_DIR ||
|
|
43
|
+
path.resolve(path.dirname(new URL(import.meta.url).pathname), "..");
|
|
44
|
+
|
|
45
|
+
let _agent = null;
|
|
46
|
+
function loadAgent() {
|
|
47
|
+
if (_agent) return _agent;
|
|
48
|
+
try {
|
|
49
|
+
_agent = JSON.parse(fs.readFileSync(path.join(AGENT_REPO_DIR, "config/agent.json"), "utf-8"));
|
|
50
|
+
} catch {
|
|
51
|
+
_agent = { firstName: "Agent", phone: "" };
|
|
52
|
+
}
|
|
53
|
+
return _agent;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const INBOX_DIR = path.join(AGENT_REPO_DIR, "state", "inbox", "whatsapp");
|
|
57
|
+
const LOG_DIR = path.join(AGENT_REPO_DIR, "logs", "whatsapp");
|
|
58
|
+
const CALLER_ID_MAP_PATH = path.join(AGENT_REPO_DIR, "config", "caller-id-map.yaml");
|
|
59
|
+
const AGENT_NUMBER = loadAgent().phone || "";
|
|
60
|
+
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
// Utilities
|
|
63
|
+
// ---------------------------------------------------------------------------
|
|
64
|
+
|
|
65
|
+
function ensureDir(dir) {
|
|
66
|
+
try {
|
|
67
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
68
|
+
} catch {
|
|
69
|
+
// Already exists or inaccessible
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function today() {
|
|
74
|
+
return new Date().toISOString().split("T")[0];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function timestamp() {
|
|
78
|
+
return new Date().toISOString().replace(/[:.]/g, "-");
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Strip the "whatsapp:" prefix from phone numbers.
|
|
83
|
+
* Twilio sends WhatsApp numbers as "whatsapp:+1234567890".
|
|
84
|
+
*/
|
|
85
|
+
function stripWhatsAppPrefix(number) {
|
|
86
|
+
if (typeof number === "string" && number.startsWith("whatsapp:")) {
|
|
87
|
+
return number.substring(9);
|
|
88
|
+
}
|
|
89
|
+
return number || "";
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Load caller-id-map.yaml and build a phone-to-user lookup.
|
|
94
|
+
* Simple YAML parsing — avoids external dependency.
|
|
95
|
+
*/
|
|
96
|
+
function loadCallerIdMap() {
|
|
97
|
+
const map = new Map();
|
|
98
|
+
try {
|
|
99
|
+
const content = fs.readFileSync(CALLER_ID_MAP_PATH, "utf-8");
|
|
100
|
+
const userBlocks = content.split(/^\s{2}\w+:/gm);
|
|
101
|
+
const userKeys = content.match(/^\s{2}(\w+):/gm) || [];
|
|
102
|
+
|
|
103
|
+
for (let i = 0; i < userKeys.length; i++) {
|
|
104
|
+
const key = userKeys[i].trim().replace(":", "");
|
|
105
|
+
const block = userBlocks[i + 1] || "";
|
|
106
|
+
|
|
107
|
+
const nameMatch = block.match(/name:\s*"([^"]+)"/);
|
|
108
|
+
const name = nameMatch ? nameMatch[1] : key;
|
|
109
|
+
|
|
110
|
+
const accessMatch = block.match(/access_level:\s*(\w+)/);
|
|
111
|
+
const accessLevel = accessMatch ? accessMatch[1] : "default";
|
|
112
|
+
|
|
113
|
+
const emailMatch = block.match(/email:\s*"([^"]+)"/);
|
|
114
|
+
const email = emailMatch ? emailMatch[1] : "";
|
|
115
|
+
|
|
116
|
+
// Extract phone numbers
|
|
117
|
+
const phoneMatch = block.match(/phone:\s*\[([^\]]*)\]/);
|
|
118
|
+
if (phoneMatch) {
|
|
119
|
+
const phones = phoneMatch[1].match(/"([^"]+)"/g) || [];
|
|
120
|
+
for (const phoneStr of phones) {
|
|
121
|
+
const phone = phoneStr.replace(/"/g, "");
|
|
122
|
+
map.set(phone, { id: key, name, accessLevel, email });
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Also check for whatsapp-specific numbers
|
|
127
|
+
const waMatch = block.match(/whatsapp:\s*\[([^\]]*)\]/);
|
|
128
|
+
if (waMatch) {
|
|
129
|
+
const waNumbers = waMatch[1].match(/"([^"]+)"/g) || [];
|
|
130
|
+
for (const waStr of waNumbers) {
|
|
131
|
+
const waNum = waStr.replace(/"/g, "");
|
|
132
|
+
map.set(waNum, { id: key, name, accessLevel, email });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
} catch (err) {
|
|
137
|
+
console.error(`[CALLER-MAP] Failed to load: ${err.message}`);
|
|
138
|
+
}
|
|
139
|
+
return map;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Load on startup; reload periodically
|
|
143
|
+
let callerMap = loadCallerIdMap();
|
|
144
|
+
setInterval(() => {
|
|
145
|
+
callerMap = loadCallerIdMap();
|
|
146
|
+
}, 60_000);
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Look up a phone number in the caller ID map.
|
|
150
|
+
*/
|
|
151
|
+
function lookupSender(phoneNumber) {
|
|
152
|
+
const clean = stripWhatsAppPrefix(phoneNumber);
|
|
153
|
+
if (callerMap.has(clean)) {
|
|
154
|
+
return callerMap.get(clean);
|
|
155
|
+
}
|
|
156
|
+
const stripped = clean.replace(/^\+/, "");
|
|
157
|
+
for (const [key, value] of callerMap) {
|
|
158
|
+
if (key.replace(/^\+/, "") === stripped) {
|
|
159
|
+
return value;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Parse URL-encoded form body (application/x-www-form-urlencoded).
|
|
167
|
+
*/
|
|
168
|
+
function parseFormBody(body) {
|
|
169
|
+
const params = new URLSearchParams(body);
|
|
170
|
+
const result = {};
|
|
171
|
+
for (const [key, value] of params) {
|
|
172
|
+
result[key] = value;
|
|
173
|
+
}
|
|
174
|
+
return result;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// ---------------------------------------------------------------------------
|
|
178
|
+
// Logging
|
|
179
|
+
// ---------------------------------------------------------------------------
|
|
180
|
+
|
|
181
|
+
function logWhatsApp(entry) {
|
|
182
|
+
const dir = path.join(LOG_DIR, today());
|
|
183
|
+
ensureDir(dir);
|
|
184
|
+
|
|
185
|
+
const logFile = path.join(dir, `${today()}-whatsapp.jsonl`);
|
|
186
|
+
const line = JSON.stringify({
|
|
187
|
+
...entry,
|
|
188
|
+
logged_at: new Date().toISOString(),
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
try {
|
|
192
|
+
fs.appendFileSync(logFile, line + "\n");
|
|
193
|
+
} catch (err) {
|
|
194
|
+
console.error(`[LOG] Failed to write: ${err.message}`);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
console.log(
|
|
198
|
+
`[WA] ${entry.direction || "inbound"} ${entry.from} -> ${entry.to}: ${(entry.body || "").substring(0, 100)}`,
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Log to the main audit trail.
|
|
204
|
+
*/
|
|
205
|
+
function logAudit(action, details) {
|
|
206
|
+
const auditDir = path.join(AGENT_REPO_DIR, "logs", "audit");
|
|
207
|
+
ensureDir(auditDir);
|
|
208
|
+
|
|
209
|
+
const auditFile = path.join(auditDir, `${today()}-actions.jsonl`);
|
|
210
|
+
const entry = {
|
|
211
|
+
timestamp: new Date().toISOString(),
|
|
212
|
+
agent: "whatsapp-handler",
|
|
213
|
+
action,
|
|
214
|
+
...details,
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
try {
|
|
218
|
+
fs.appendFileSync(auditFile, JSON.stringify(entry) + "\n");
|
|
219
|
+
} catch (err) {
|
|
220
|
+
console.error(`[AUDIT] Failed to write: ${err.message}`);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// ---------------------------------------------------------------------------
|
|
225
|
+
// Inbox Writer
|
|
226
|
+
// ---------------------------------------------------------------------------
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Write an inbound WhatsApp message to the inbox as a YAML file.
|
|
230
|
+
* Follows the same schema as SMS/Slack/Gmail inbox items.
|
|
231
|
+
*/
|
|
232
|
+
function writeToInbox(msgData) {
|
|
233
|
+
ensureDir(INBOX_DIR);
|
|
234
|
+
|
|
235
|
+
const ts = timestamp();
|
|
236
|
+
const messageSid = msgData.MessageSid || msgData.SmsSid || "unknown";
|
|
237
|
+
const filename = `${ts}-${messageSid}.yaml`;
|
|
238
|
+
const filePath = path.join(INBOX_DIR, filename);
|
|
239
|
+
|
|
240
|
+
const rawFrom = stripWhatsAppPrefix(msgData.From || "");
|
|
241
|
+
const sender = lookupSender(rawFrom);
|
|
242
|
+
const senderName = sender ? sender.name : rawFrom || "unknown";
|
|
243
|
+
const senderId = sender ? sender.id : "unknown";
|
|
244
|
+
const senderPrivilege = sender ? sender.accessLevel : "unknown";
|
|
245
|
+
|
|
246
|
+
// Check for media
|
|
247
|
+
const numMedia = parseInt(msgData.NumMedia || "0", 10);
|
|
248
|
+
const mediaUrls = [];
|
|
249
|
+
for (let i = 0; i < numMedia; i++) {
|
|
250
|
+
const url = msgData[`MediaUrl${i}`];
|
|
251
|
+
const contentType = msgData[`MediaContentType${i}`];
|
|
252
|
+
if (url) {
|
|
253
|
+
mediaUrls.push({ url, content_type: contentType || "unknown" });
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Detect message type hints
|
|
258
|
+
const body = msgData.Body || "";
|
|
259
|
+
const profileName = msgData.ProfileName || "";
|
|
260
|
+
const forwarded = msgData.Forwarded === "true";
|
|
261
|
+
const frequentlyForwarded = msgData.FrequentlyForwarded === "true";
|
|
262
|
+
|
|
263
|
+
const yaml = [
|
|
264
|
+
`id: "${messageSid}"`,
|
|
265
|
+
`service: "whatsapp"`,
|
|
266
|
+
`channel: "whatsapp/${senderId}"`,
|
|
267
|
+
`sender: "${senderName}"`,
|
|
268
|
+
`sender_phone: "${rawFrom}"`,
|
|
269
|
+
`sender_privilege: "${senderPrivilege}"`,
|
|
270
|
+
`sender_profile_name: "${profileName}"`,
|
|
271
|
+
`timestamp: "${new Date().toISOString()}"`,
|
|
272
|
+
`subject: "WhatsApp from ${senderName}"`,
|
|
273
|
+
`content: |`,
|
|
274
|
+
` ${body.replace(/\n/g, "\n ")}`,
|
|
275
|
+
`to: "${stripWhatsAppPrefix(msgData.To || "")}"`,
|
|
276
|
+
`is_reply: false`,
|
|
277
|
+
`is_forwarded: ${forwarded}`,
|
|
278
|
+
`is_frequently_forwarded: ${frequentlyForwarded}`,
|
|
279
|
+
`priority_signals:`,
|
|
280
|
+
` from_ceo: ${senderPrivilege === "ceo"}`,
|
|
281
|
+
` tagged_urgent: ${body.toLowerCase().includes("urgent")}`,
|
|
282
|
+
` contains_deadline: false`,
|
|
283
|
+
` mentions_agent: ${body.toLowerCase().includes((loadAgent().firstName || "agent").toLowerCase())}`,
|
|
284
|
+
];
|
|
285
|
+
|
|
286
|
+
if (mediaUrls.length > 0) {
|
|
287
|
+
yaml.push(`media:`);
|
|
288
|
+
for (const m of mediaUrls) {
|
|
289
|
+
yaml.push(` - url: "${m.url}"`);
|
|
290
|
+
yaml.push(` content_type: "${m.content_type}"`);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
yaml.push(`raw_ref: "whatsapp:${messageSid}"`);
|
|
295
|
+
|
|
296
|
+
try {
|
|
297
|
+
fs.writeFileSync(filePath, yaml.join("\n") + "\n");
|
|
298
|
+
console.log(`[INBOX] Written: ${filename}`);
|
|
299
|
+
return filePath;
|
|
300
|
+
} catch (err) {
|
|
301
|
+
console.error(`[INBOX] Failed to write: ${err.message}`);
|
|
302
|
+
return null;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// ---------------------------------------------------------------------------
|
|
307
|
+
// TwiML Response
|
|
308
|
+
// ---------------------------------------------------------------------------
|
|
309
|
+
|
|
310
|
+
function twimlAck() {
|
|
311
|
+
return '<?xml version="1.0" encoding="UTF-8"?>\n<Response></Response>';
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// ---------------------------------------------------------------------------
|
|
315
|
+
// HTTP Server
|
|
316
|
+
// ---------------------------------------------------------------------------
|
|
317
|
+
|
|
318
|
+
const server = http.createServer(async (req, res) => {
|
|
319
|
+
const url = new URL(req.url, `http://localhost:${PORT}`);
|
|
320
|
+
|
|
321
|
+
// Health check
|
|
322
|
+
if (req.method === "GET" && url.pathname === "/health") {
|
|
323
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
324
|
+
res.end(
|
|
325
|
+
JSON.stringify({
|
|
326
|
+
status: "ok",
|
|
327
|
+
service: "agent-whatsapp-handler",
|
|
328
|
+
uptime: process.uptime(),
|
|
329
|
+
timestamp: new Date().toISOString(),
|
|
330
|
+
knownContacts: callerMap.size,
|
|
331
|
+
}),
|
|
332
|
+
);
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// Root info
|
|
337
|
+
if (req.method === "GET" && url.pathname === "/") {
|
|
338
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
339
|
+
res.end(
|
|
340
|
+
JSON.stringify({
|
|
341
|
+
service: "Agent WhatsApp Handler",
|
|
342
|
+
description: "Twilio inbound WhatsApp webhook for the agent's inbox",
|
|
343
|
+
endpoints: {
|
|
344
|
+
health: "/health",
|
|
345
|
+
whatsapp: "/whatsapp (POST)",
|
|
346
|
+
status: "/whatsapp/status (POST)",
|
|
347
|
+
},
|
|
348
|
+
}),
|
|
349
|
+
);
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// WhatsApp message webhook
|
|
354
|
+
if (req.method === "POST" && url.pathname === "/whatsapp") {
|
|
355
|
+
let body = "";
|
|
356
|
+
req.on("data", (chunk) => {
|
|
357
|
+
body += chunk.toString();
|
|
358
|
+
});
|
|
359
|
+
req.on("end", () => {
|
|
360
|
+
try {
|
|
361
|
+
const msgData = parseFormBody(body);
|
|
362
|
+
|
|
363
|
+
const rawFrom = msgData.From || "unknown";
|
|
364
|
+
const rawTo = msgData.To || "";
|
|
365
|
+
const from = stripWhatsAppPrefix(rawFrom);
|
|
366
|
+
const to = stripWhatsAppPrefix(rawTo);
|
|
367
|
+
const messageBody = msgData.Body || "";
|
|
368
|
+
const messageSid = msgData.MessageSid || msgData.SmsSid || "unknown";
|
|
369
|
+
const numMedia = parseInt(msgData.NumMedia || "0", 10);
|
|
370
|
+
const profileName = msgData.ProfileName || "";
|
|
371
|
+
|
|
372
|
+
// Log the inbound WhatsApp message
|
|
373
|
+
logWhatsApp({
|
|
374
|
+
direction: "inbound",
|
|
375
|
+
messageSid,
|
|
376
|
+
from,
|
|
377
|
+
to,
|
|
378
|
+
body: messageBody,
|
|
379
|
+
numMedia,
|
|
380
|
+
profileName,
|
|
381
|
+
timestamp: new Date().toISOString(),
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
// Write to inbox for processing
|
|
385
|
+
const inboxPath = writeToInbox(msgData);
|
|
386
|
+
|
|
387
|
+
// Log to audit trail
|
|
388
|
+
logAudit("whatsapp_received", {
|
|
389
|
+
from,
|
|
390
|
+
to,
|
|
391
|
+
messageSid,
|
|
392
|
+
profileName,
|
|
393
|
+
body_preview: messageBody.substring(0, 100),
|
|
394
|
+
inbox_path: inboxPath,
|
|
395
|
+
sender_identified: !!lookupSender(from),
|
|
396
|
+
num_media: numMedia,
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
// Check if from CEO — log as priority
|
|
400
|
+
const sender = lookupSender(from);
|
|
401
|
+
if (sender && sender.accessLevel === "ceo") {
|
|
402
|
+
console.log(
|
|
403
|
+
`[PRIORITY] WhatsApp from CEO (${sender.name}): ${messageBody.substring(0, 100)}`,
|
|
404
|
+
);
|
|
405
|
+
|
|
406
|
+
// Write priority trigger
|
|
407
|
+
const priorityFile = path.join(
|
|
408
|
+
INBOX_DIR,
|
|
409
|
+
`priority-${Date.now()}.yaml`,
|
|
410
|
+
);
|
|
411
|
+
const priorityYaml =
|
|
412
|
+
[
|
|
413
|
+
`type: priority_trigger`,
|
|
414
|
+
`reason: "WhatsApp from CEO"`,
|
|
415
|
+
`source_item: "whatsapp:${messageSid}"`,
|
|
416
|
+
`timestamp: "${new Date().toISOString()}"`,
|
|
417
|
+
`sender: "${sender.name}"`,
|
|
418
|
+
`channel: "whatsapp/${sender.id}"`,
|
|
419
|
+
`content: |`,
|
|
420
|
+
` ${messageBody.replace(/\n/g, "\n ")}`,
|
|
421
|
+
].join("\n") + "\n";
|
|
422
|
+
|
|
423
|
+
try {
|
|
424
|
+
fs.writeFileSync(priorityFile, priorityYaml);
|
|
425
|
+
console.log(`[PRIORITY] Priority trigger written`);
|
|
426
|
+
} catch (err) {
|
|
427
|
+
console.error(`[PRIORITY] Failed: ${err.message}`);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// Return TwiML acknowledgement (no auto-reply)
|
|
432
|
+
res.writeHead(200, { "Content-Type": "text/xml" });
|
|
433
|
+
res.end(twimlAck());
|
|
434
|
+
} catch (err) {
|
|
435
|
+
console.error(`[WA] Error processing webhook: ${err.message}`);
|
|
436
|
+
res.writeHead(200, { "Content-Type": "text/xml" });
|
|
437
|
+
res.end(twimlAck());
|
|
438
|
+
}
|
|
439
|
+
});
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// Delivery status callback
|
|
444
|
+
if (req.method === "POST" && url.pathname === "/whatsapp/status") {
|
|
445
|
+
let body = "";
|
|
446
|
+
req.on("data", (chunk) => {
|
|
447
|
+
body += chunk.toString();
|
|
448
|
+
});
|
|
449
|
+
req.on("end", () => {
|
|
450
|
+
try {
|
|
451
|
+
const statusData = parseFormBody(body);
|
|
452
|
+
|
|
453
|
+
const messageSid = statusData.MessageSid || "unknown";
|
|
454
|
+
const messageStatus = statusData.MessageStatus || "unknown";
|
|
455
|
+
const to = stripWhatsAppPrefix(statusData.To || "");
|
|
456
|
+
const from = stripWhatsAppPrefix(statusData.From || "");
|
|
457
|
+
const errorCode = statusData.ErrorCode || "";
|
|
458
|
+
const errorMessage = statusData.ErrorMessage || "";
|
|
459
|
+
|
|
460
|
+
logWhatsApp({
|
|
461
|
+
direction: "status",
|
|
462
|
+
messageSid,
|
|
463
|
+
from,
|
|
464
|
+
to,
|
|
465
|
+
status: messageStatus,
|
|
466
|
+
errorCode,
|
|
467
|
+
errorMessage,
|
|
468
|
+
timestamp: new Date().toISOString(),
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
// Log failures to audit
|
|
472
|
+
if (
|
|
473
|
+
messageStatus === "failed" ||
|
|
474
|
+
messageStatus === "undelivered" ||
|
|
475
|
+
errorCode
|
|
476
|
+
) {
|
|
477
|
+
logAudit("whatsapp_delivery_failure", {
|
|
478
|
+
messageSid,
|
|
479
|
+
to,
|
|
480
|
+
from,
|
|
481
|
+
status: messageStatus,
|
|
482
|
+
errorCode,
|
|
483
|
+
errorMessage,
|
|
484
|
+
});
|
|
485
|
+
console.error(
|
|
486
|
+
`[WA-STATUS] DELIVERY FAILURE: ${messageSid} to ${to} — ${messageStatus} (${errorCode}: ${errorMessage})`,
|
|
487
|
+
);
|
|
488
|
+
} else {
|
|
489
|
+
console.log(
|
|
490
|
+
`[WA-STATUS] ${messageSid}: ${messageStatus}`,
|
|
491
|
+
);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
res.writeHead(200, { "Content-Type": "text/xml" });
|
|
495
|
+
res.end(twimlAck());
|
|
496
|
+
} catch (err) {
|
|
497
|
+
console.error(`[WA-STATUS] Error: ${err.message}`);
|
|
498
|
+
res.writeHead(200, { "Content-Type": "text/xml" });
|
|
499
|
+
res.end(twimlAck());
|
|
500
|
+
}
|
|
501
|
+
});
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// 404 for everything else
|
|
506
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
507
|
+
res.end(JSON.stringify({ error: "Not found" }));
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
// ---------------------------------------------------------------------------
|
|
511
|
+
// Start
|
|
512
|
+
// ---------------------------------------------------------------------------
|
|
513
|
+
|
|
514
|
+
ensureDir(INBOX_DIR);
|
|
515
|
+
ensureDir(LOG_DIR);
|
|
516
|
+
|
|
517
|
+
server.listen(PORT, "0.0.0.0", () => {
|
|
518
|
+
console.log(`\n========================================`);
|
|
519
|
+
console.log(` Agent WhatsApp Handler`);
|
|
520
|
+
console.log(` Port: ${PORT}`);
|
|
521
|
+
console.log(` Health: http://0.0.0.0:${PORT}/health`);
|
|
522
|
+
console.log(` Webhook: POST /whatsapp`);
|
|
523
|
+
console.log(` Status: POST /whatsapp/status`);
|
|
524
|
+
console.log(` Known contacts: ${callerMap.size}`);
|
|
525
|
+
console.log(` Inbox: ${INBOX_DIR}`);
|
|
526
|
+
console.log(` Logs: ${LOG_DIR}`);
|
|
527
|
+
console.log(`========================================\n`);
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
// Graceful shutdown
|
|
531
|
+
process.on("SIGTERM", () => {
|
|
532
|
+
console.log("[WA] Shutting down...");
|
|
533
|
+
server.close(() => process.exit(0));
|
|
534
|
+
});
|
|
535
|
+
process.on("SIGINT", () => {
|
|
536
|
+
console.log("[WA] Shutting down...");
|
|
537
|
+
server.close(() => process.exit(0));
|
|
538
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Desktop Operations Team
|
|
2
|
+
# Controls real macOS applications on the Mac mini
|
|
3
|
+
|
|
4
|
+
name: desktop-operations
|
|
5
|
+
lead: desktop-operator
|
|
6
|
+
description: >
|
|
7
|
+
Manages all desktop application control on the Mac mini.
|
|
8
|
+
The "hands" of the CEO Brain — executing Slack, email, WhatsApp,
|
|
9
|
+
and browser operations under strict governance.
|
|
10
|
+
|
|
11
|
+
members:
|
|
12
|
+
- desktop-operator # Central desktop control coordinator
|
|
13
|
+
- slack-operator # Slack app control
|
|
14
|
+
- gmail-operator # Gmail browser control
|
|
15
|
+
- whatsapp-operator # WhatsApp Desktop control
|
|
16
|
+
- browser-operator # General browser operations
|
|
17
|
+
- calendar-ops # Calendar management (shared with executive-office)
|
|
18
|
+
|
|
19
|
+
responsibilities:
|
|
20
|
+
- Application monitoring and observation
|
|
21
|
+
- Message drafting and sending (with approval)
|
|
22
|
+
- Channel and inbox triage
|
|
23
|
+
- Follow-up execution
|
|
24
|
+
- Screenshot capture and state verification
|
|
25
|
+
- Action logging and audit trail
|
|
26
|
+
|
|
27
|
+
governance:
|
|
28
|
+
- All send operations require appropriate approval level
|
|
29
|
+
- All actions are logged with before/after state capture
|
|
30
|
+
- Rate limits enforced per application
|
|
31
|
+
- Emergency stop halts all desktop operations
|
|
32
|
+
- Forbidden actions are never executed regardless of instruction
|
|
33
|
+
|
|
34
|
+
escalation: chief-of-staff
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Executive Office Team
|
|
2
|
+
# The core team that produces executive outputs and manages CEO operations
|
|
3
|
+
|
|
4
|
+
name: executive-office
|
|
5
|
+
lead: chief-of-staff
|
|
6
|
+
description: >
|
|
7
|
+
The primary operating team. Produces all executive outputs, manages the
|
|
8
|
+
CEO's operational cadence, and coordinates across all domain teams.
|
|
9
|
+
|
|
10
|
+
members:
|
|
11
|
+
- chief-of-staff # Team lead and orchestrator
|
|
12
|
+
- ceo-briefing # Brief and memo production
|
|
13
|
+
- communications # Outbound communications governance
|
|
14
|
+
- pmo-execution # Project tracking and follow-through
|
|
15
|
+
- calendar-ops # Calendar and scheduling
|
|
16
|
+
- decision-log # Decision recording
|
|
17
|
+
- workflow-automation # Scheduled workflow management
|
|
18
|
+
|
|
19
|
+
responsibilities:
|
|
20
|
+
- Morning and evening briefs
|
|
21
|
+
- Communications triage and drafting
|
|
22
|
+
- Follow-up management
|
|
23
|
+
- Decision tracking
|
|
24
|
+
- Calendar management
|
|
25
|
+
- Executive cadence execution
|
|
26
|
+
|
|
27
|
+
escalation: principal # Escalates to CEO
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Legal & Regulatory Team
|
|
2
|
+
# Handles all legal, regulatory, and compliance matters
|
|
3
|
+
|
|
4
|
+
name: legal-and-regulatory
|
|
5
|
+
lead: regulatory-compliance
|
|
6
|
+
description: >
|
|
7
|
+
Manages regulatory submission, legal structuring,
|
|
8
|
+
fund operations compliance, and risk management.
|
|
9
|
+
|
|
10
|
+
members:
|
|
11
|
+
- regulatory-compliance # regulatory compliance
|
|
12
|
+
- legal-structuring # Legal entity and contract work
|
|
13
|
+
- fund-ops # Fund administration and investor reporting
|
|
14
|
+
- risk-register # Risk identification and tracking
|
|
15
|
+
|
|
16
|
+
responsibilities:
|
|
17
|
+
- Regulatory gap remediation tracking
|
|
18
|
+
- Regulatory submission preparation
|
|
19
|
+
- Legal structuring for M&A
|
|
20
|
+
- Fund compliance and reporting
|
|
21
|
+
- Risk register maintenance
|
|
22
|
+
- Monthly risk refresh
|
|
23
|
+
|
|
24
|
+
escalation: chief-of-staff
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Platform & Engineering Team
|
|
2
|
+
# Handles technical architecture, engineering coordination, and product strategy
|
|
3
|
+
|
|
4
|
+
name: platform-and-engineering
|
|
5
|
+
lead: product-strategy
|
|
6
|
+
description: >
|
|
7
|
+
Manages the company's platform development, engineering coordination,
|
|
8
|
+
and technical architecture decisions.
|
|
9
|
+
|
|
10
|
+
members:
|
|
11
|
+
- product-strategy # Product roadmap and prioritisation
|
|
12
|
+
- platform-architecture # Technical architecture
|
|
13
|
+
- engineering-coordination # Cross-repo engineering health
|
|
14
|
+
|
|
15
|
+
responsibilities:
|
|
16
|
+
- Platform maturity tracking
|
|
17
|
+
- Engineering health monitoring
|
|
18
|
+
- Architecture decision support
|
|
19
|
+
- Technical debt management
|
|
20
|
+
- Build and test status
|
|
21
|
+
- Production readiness assessment
|
|
22
|
+
|
|
23
|
+
escalation: chief-of-staff
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Strategy & Growth Team
|
|
2
|
+
# Handles strategic analysis, corporate development, and capital markets
|
|
3
|
+
|
|
4
|
+
name: strategy-and-growth
|
|
5
|
+
lead: strategic-planning
|
|
6
|
+
description: >
|
|
7
|
+
Manages all strategic analysis, M&A execution, capital raising,
|
|
8
|
+
and competitive positioning for the company.
|
|
9
|
+
|
|
10
|
+
members:
|
|
11
|
+
- strategic-planning # Strategic analysis and scenarios
|
|
12
|
+
- corporate-development # M&A and rollup execution
|
|
13
|
+
- rollup-target-sourcing # Acquisition target pipeline
|
|
14
|
+
- capital-raising # LP relationships and fundraising
|
|
15
|
+
- competitive-intelligence # Competitor monitoring
|
|
16
|
+
- market-research # Market and sector analysis
|
|
17
|
+
- partnerships # Strategic partnerships
|
|
18
|
+
- board-prep # Board materials and governance
|
|
19
|
+
|
|
20
|
+
responsibilities:
|
|
21
|
+
- Weekly strategic memo
|
|
22
|
+
- Rollup pipeline management
|
|
23
|
+
- Deal preparation and execution
|
|
24
|
+
- Capital raising support
|
|
25
|
+
- Competitive intelligence
|
|
26
|
+
- Board pack preparation
|
|
27
|
+
- Quarterly scenario analysis
|
|
28
|
+
|
|
29
|
+
escalation: chief-of-staff
|