@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.
Files changed (731) hide show
  1. package/.claude/commands/init-agent.md +104 -0
  2. package/.claude/commands/init-maestro.md +1187 -0
  3. package/.claude/settings.json +161 -0
  4. package/.env.example +216 -0
  5. package/README.md +632 -0
  6. package/agents/browser-operator/agent.md +52 -0
  7. package/agents/calendar-ops/agent.md +50 -0
  8. package/agents/communications/agent.md +96 -0
  9. package/agents/decision-log/agent.md +65 -0
  10. package/agents/desktop-operator/agent.md +59 -0
  11. package/agents/gmail-operator/agent.md +62 -0
  12. package/agents/inbound-dispatcher/agent.md +66 -0
  13. package/agents/inbox-processor/agent.md +39 -0
  14. package/agents/pmo-execution/agent.md +60 -0
  15. package/agents/session-spawner/agent.md +64 -0
  16. package/agents/slack-operator/agent.md +60 -0
  17. package/agents/whatsapp-operator/agent.md +60 -0
  18. package/agents/workflow-automation/agent.md +61 -0
  19. package/archetypes/altitudes/c-suite.yaml +58 -0
  20. package/archetypes/altitudes/founder.yaml +68 -0
  21. package/archetypes/altitudes/senior-manager.yaml +63 -0
  22. package/archetypes/altitudes/svp.yaml +60 -0
  23. package/archetypes/altitudes/vp.yaml +50 -0
  24. package/archetypes/archetype.schema.json +77 -0
  25. package/archetypes/base.yaml +47 -0
  26. package/archetypes/capabilities/commercial-leader.yaml +159 -0
  27. package/archetypes/capabilities/compliance-officer.yaml +159 -0
  28. package/archetypes/capabilities/executive-operator.yaml +169 -0
  29. package/archetypes/capabilities/finance-leader.yaml +162 -0
  30. package/archetypes/capabilities/operations-leader.yaml +154 -0
  31. package/archetypes/capabilities/product-leader.yaml +148 -0
  32. package/archetypes/capabilities/technical-leader.yaml +146 -0
  33. package/archetypes/functions/commercial-leader.yaml +62 -0
  34. package/archetypes/functions/compliance-officer.yaml +64 -0
  35. package/archetypes/functions/executive-operator.yaml +70 -0
  36. package/archetypes/functions/finance-leader.yaml +70 -0
  37. package/archetypes/functions/operations-leader.yaml +62 -0
  38. package/archetypes/functions/product-leader.yaml +61 -0
  39. package/archetypes/functions/technical-leader.yaml +57 -0
  40. package/bin/cohort-mcp.mjs +81 -0
  41. package/bin/maestro.mjs +3516 -0
  42. package/bin/maestro.test.mjs +1015 -0
  43. package/desktop-control/README.md +56 -0
  44. package/desktop-control/app-profiles/gmail.yaml +120 -0
  45. package/desktop-control/app-profiles/slack.yaml +315 -0
  46. package/desktop-control/app-profiles/whatsapp.yaml +107 -0
  47. package/docs/architecture/agent-topology.md +2239 -0
  48. package/docs/architecture/archetype-agent-factory.md +110 -0
  49. package/docs/architecture/collective-memory-and-org-mesh.md +115 -0
  50. package/docs/architecture/continuous-monitoring.md +221 -0
  51. package/docs/architecture/mcp-capability-map.md +585 -0
  52. package/docs/architecture/system-architecture.md +1272 -0
  53. package/docs/company-context/README.md +40 -0
  54. package/docs/guides/agent-persona-setup.md +600 -0
  55. package/docs/guides/agents-observe-setup.md +64 -0
  56. package/docs/guides/billing-console-keys.md +88 -0
  57. package/docs/guides/ccxray-diagnostics.md +65 -0
  58. package/docs/guides/channel-bus.md +127 -0
  59. package/docs/guides/claude-mem-setup.md +79 -0
  60. package/docs/guides/claude-pace-setup.md +56 -0
  61. package/docs/guides/claudraband-sessions.md +98 -0
  62. package/docs/guides/clawteam-swarm.md +116 -0
  63. package/docs/guides/code-review-graph-setup.md +86 -0
  64. package/docs/guides/email-setup.md +431 -0
  65. package/docs/guides/mac-mini.md +119 -0
  66. package/docs/guides/media-generation-setup.md +349 -0
  67. package/docs/guides/model-routing.md +162 -0
  68. package/docs/guides/observability-otel.md +265 -0
  69. package/docs/guides/org-onboarding.md +132 -0
  70. package/docs/guides/outbound-governance-setup.md +437 -0
  71. package/docs/guides/pdf-generation-setup.md +315 -0
  72. package/docs/guides/poller-daemon-setup.md +563 -0
  73. package/docs/guides/rag-context-setup.md +459 -0
  74. package/docs/guides/self-optimization-pattern.md +82 -0
  75. package/docs/guides/setup-wizard.md +178 -0
  76. package/docs/guides/slack-setup.md +350 -0
  77. package/docs/guides/telegram-setup.md +227 -0
  78. package/docs/guides/twilio-subaccounts-setup.md +223 -0
  79. package/docs/guides/verification.md +128 -0
  80. package/docs/guides/voice-mode.md +188 -0
  81. package/docs/guides/voice-sms-setup.md +698 -0
  82. package/docs/guides/webhook-relay-setup.md +349 -0
  83. package/docs/guides/whatsapp-setup.md +288 -0
  84. package/docs/prompts/board-pack-cover-template.md +36 -0
  85. package/docs/prompts/decision-recommendation-template.md +88 -0
  86. package/docs/prompts/followup-message-template.md +141 -0
  87. package/docs/prompts/investor-letter-template.md +52 -0
  88. package/docs/prompts/morning-brief-template.md +82 -0
  89. package/docs/prompts/presentation-template.md +58 -0
  90. package/docs/prompts/weekly-strategic-memo-template.md +104 -0
  91. package/docs/research/hallucinated-tool-output-investigation.md +151 -0
  92. package/docs/runbooks/backup-restore.md +205 -0
  93. package/docs/runbooks/cohort-cutover.md +129 -0
  94. package/docs/runbooks/fleet-operations.md +200 -0
  95. package/docs/runbooks/incident-response.md +226 -0
  96. package/docs/runbooks/mac-mini-bootstrap.md +431 -0
  97. package/docs/runbooks/perpetual-operations.md +509 -0
  98. package/docs/runbooks/recovery-and-failover.md +260 -0
  99. package/framework-features.json +267 -0
  100. package/ingest/README.md +87 -0
  101. package/lib/action-executor.js +689 -0
  102. package/lib/action-executor.test.mjs +871 -0
  103. package/lib/agent-root.mjs +37 -0
  104. package/lib/archetype.mjs +236 -0
  105. package/lib/archetype.test.mjs +132 -0
  106. package/lib/autonomy.mjs +114 -0
  107. package/lib/autonomy.test.mjs +66 -0
  108. package/lib/backlog.mjs +358 -0
  109. package/lib/backlog.test.mjs +266 -0
  110. package/lib/budget-guard.mjs +279 -0
  111. package/lib/budget-guard.test.mjs +291 -0
  112. package/lib/cadence-bus-schedule.test.mjs +194 -0
  113. package/lib/cadence-bus.mjs +1120 -0
  114. package/lib/cadence-bus.test.mjs +720 -0
  115. package/lib/cadences.mjs +205 -0
  116. package/lib/cadences.test.mjs +125 -0
  117. package/lib/capability.mjs +154 -0
  118. package/lib/capability.test.mjs +78 -0
  119. package/lib/channels/base-adapter.mjs +719 -0
  120. package/lib/channels/base-adapter.test.mjs +590 -0
  121. package/lib/channels/channel.mjs +128 -0
  122. package/lib/channels/channels.test.mjs +371 -0
  123. package/lib/channels/contract.mjs +215 -0
  124. package/lib/channels/contract.test.mjs +137 -0
  125. package/lib/channels/conversation-resolver.mjs +95 -0
  126. package/lib/channels/gmail/adapter.mjs +87 -0
  127. package/lib/channels/inbox-item.mjs +255 -0
  128. package/lib/channels/inbox-item.test.mjs +335 -0
  129. package/lib/channels/index.mjs +94 -0
  130. package/lib/channels/orgmail/adapter.mjs +353 -0
  131. package/lib/channels/orgmail/adapter.test.mjs +311 -0
  132. package/lib/channels/pairing.mjs +363 -0
  133. package/lib/channels/pairing.test.mjs +270 -0
  134. package/lib/channels/registry.mjs +164 -0
  135. package/lib/channels/slack/adapter.mjs +317 -0
  136. package/lib/channels/slack-adapter.test.mjs +212 -0
  137. package/lib/channels/sms/adapter.mjs +43 -0
  138. package/lib/channels/telegram/adapter.mjs +432 -0
  139. package/lib/channels/telegram-adapter.test.mjs +306 -0
  140. package/lib/channels/voice/adapter.mjs +301 -0
  141. package/lib/channels/voice/adapter.test.mjs +278 -0
  142. package/lib/channels/whatsapp/adapter-baileys.mjs +587 -0
  143. package/lib/channels/whatsapp/adapter-baileys.test.mjs +359 -0
  144. package/lib/channels/whatsapp/adapter-twilio.mjs +65 -0
  145. package/lib/channels/whatsapp/baileys-typing.test.mjs +154 -0
  146. package/lib/charter.mjs +256 -0
  147. package/lib/charter.test.mjs +89 -0
  148. package/lib/claude-bin.mjs +134 -0
  149. package/lib/claude-bin.test.mjs +75 -0
  150. package/lib/collective/capture.mjs +185 -0
  151. package/lib/collective/capture.test.mjs +121 -0
  152. package/lib/collective/cards.mjs +201 -0
  153. package/lib/collective/cards.test.mjs +114 -0
  154. package/lib/collective/config.mjs +186 -0
  155. package/lib/collective/config.test.mjs +123 -0
  156. package/lib/collective/global-config.mjs +113 -0
  157. package/lib/collective/global-config.test.mjs +75 -0
  158. package/lib/collective/presence.mjs +201 -0
  159. package/lib/collective/presence.test.mjs +95 -0
  160. package/lib/collective/recall.mjs +215 -0
  161. package/lib/collective/recall.test.mjs +116 -0
  162. package/lib/comms/send-gate.mjs +554 -0
  163. package/lib/comms/send-gate.test.mjs +577 -0
  164. package/lib/comms.mjs +67 -0
  165. package/lib/comms.test.mjs +41 -0
  166. package/lib/diagnostics/alerts.mjs +424 -0
  167. package/lib/diagnostics/alerts.test.mjs +318 -0
  168. package/lib/diagnostics/backup-freshness.mjs +188 -0
  169. package/lib/diagnostics/backup-freshness.test.mjs +185 -0
  170. package/lib/diagnostics/counters.mjs +269 -0
  171. package/lib/diagnostics/counters.test.mjs +206 -0
  172. package/lib/diagnostics/events.mjs +188 -0
  173. package/lib/diagnostics/events.test.mjs +290 -0
  174. package/lib/diagnostics/otel.mjs +237 -0
  175. package/lib/diagnostics/otel.test.mjs +196 -0
  176. package/lib/diagnostics/trace.mjs +216 -0
  177. package/lib/diagnostics/trace.test.mjs +251 -0
  178. package/lib/env-compat.mjs +74 -0
  179. package/lib/env-compat.test.mjs +104 -0
  180. package/lib/feature-init.mjs +331 -0
  181. package/lib/fs-atomic.mjs +112 -0
  182. package/lib/fs-atomic.test.mjs +72 -0
  183. package/lib/fs-ownership.mjs +111 -0
  184. package/lib/fs-ownership.test.mjs +158 -0
  185. package/lib/hooks/bus.mjs +347 -0
  186. package/lib/hooks/bus.test.mjs +387 -0
  187. package/lib/index.js +16 -0
  188. package/lib/learning/config.mjs +106 -0
  189. package/lib/learning/config.test.mjs +75 -0
  190. package/lib/learning/counters.mjs +156 -0
  191. package/lib/learning/counters.test.mjs +69 -0
  192. package/lib/learning/curator-consolidate.test.mjs +238 -0
  193. package/lib/learning/curator.mjs +453 -0
  194. package/lib/learning/curator.test.mjs +106 -0
  195. package/lib/learning/log.mjs +40 -0
  196. package/lib/learning/reflect.mjs +534 -0
  197. package/lib/learning/reflect.test.mjs +0 -0
  198. package/lib/learning/session-index.mjs +352 -0
  199. package/lib/learning/session-index.test.mjs +125 -0
  200. package/lib/learning/skill-writer.mjs +474 -0
  201. package/lib/learning/skill-writer.test.mjs +210 -0
  202. package/lib/mcp/server.mjs +328 -0
  203. package/lib/mcp/server.test.mjs +400 -0
  204. package/lib/model-router/auth-profiles.mjs +758 -0
  205. package/lib/model-router/auth-profiles.test.mjs +580 -0
  206. package/lib/model-router/catalog/anthropic.yaml +153 -0
  207. package/lib/model-router/catalog/deepseek.yaml +86 -0
  208. package/lib/model-router/catalog/moonshot.yaml +81 -0
  209. package/lib/model-router/catalog/qwen.yaml +114 -0
  210. package/lib/model-router/catalog.mjs +925 -0
  211. package/lib/model-router/catalog.test.mjs +385 -0
  212. package/lib/model-router/economics.mjs +564 -0
  213. package/lib/model-router/economics.test.mjs +344 -0
  214. package/lib/model-router/failover.mjs +298 -0
  215. package/lib/model-router/failover.test.mjs +439 -0
  216. package/lib/model-router/health.mjs +453 -0
  217. package/lib/model-router/health.test.mjs +338 -0
  218. package/lib/model-router/integration-coverage.test.mjs +829 -0
  219. package/lib/model-router/integration.test.mjs +564 -0
  220. package/lib/model-router/ledger.mjs +402 -0
  221. package/lib/model-router/ledger.test.mjs +382 -0
  222. package/lib/model-router/llm-task.mjs +515 -0
  223. package/lib/model-router/llm-task.test.mjs +392 -0
  224. package/lib/model-router/org-credentials.mjs +260 -0
  225. package/lib/model-router/org-credentials.test.mjs +265 -0
  226. package/lib/model-router/pricing-refresh.mjs +463 -0
  227. package/lib/model-router/pricing-refresh.test.mjs +286 -0
  228. package/lib/model-router/reconcile.mjs +429 -0
  229. package/lib/model-router/reconcile.test.mjs +316 -0
  230. package/lib/model-router/repair.mjs +471 -0
  231. package/lib/model-router/repair.test.mjs +180 -0
  232. package/lib/model-router/resolve.mjs +1206 -0
  233. package/lib/model-router/spawn.mjs +497 -0
  234. package/lib/model-router/spawn.test.mjs +425 -0
  235. package/lib/model-router/taxonomy.mjs +893 -0
  236. package/lib/model-router/taxonomy.test.mjs +410 -0
  237. package/lib/model-router.mjs +677 -0
  238. package/lib/model-router.test.mjs +907 -0
  239. package/lib/org/activity.mjs +211 -0
  240. package/lib/org/activity.test.mjs +134 -0
  241. package/lib/org/approvals.mjs +448 -0
  242. package/lib/org/approvals.test.mjs +216 -0
  243. package/lib/org/awareness.mjs +222 -0
  244. package/lib/org/awareness.test.mjs +159 -0
  245. package/lib/org/board.mjs +229 -0
  246. package/lib/org/board.test.mjs +177 -0
  247. package/lib/org/bootstrap-context.mjs +169 -0
  248. package/lib/org/bootstrap-context.test.mjs +153 -0
  249. package/lib/org/client.mjs +1628 -0
  250. package/lib/org/client.test.mjs +1107 -0
  251. package/lib/org/cohort-client.mjs +67 -0
  252. package/lib/org/cohort-client.test.mjs +126 -0
  253. package/lib/org/cost-sync.mjs +227 -0
  254. package/lib/org/cost-sync.test.mjs +153 -0
  255. package/lib/org/doctor.mjs +212 -0
  256. package/lib/org/doctor.test.mjs +212 -0
  257. package/lib/org/handoff.mjs +293 -0
  258. package/lib/org/handoff.test.mjs +269 -0
  259. package/lib/org/integration-tools.mjs +182 -0
  260. package/lib/org/integration-tools.test.mjs +160 -0
  261. package/lib/org/keys.mjs +131 -0
  262. package/lib/org/keys.test.mjs +92 -0
  263. package/lib/org/knowledge.mjs +463 -0
  264. package/lib/org/knowledge.test.mjs +319 -0
  265. package/lib/org/leases.mjs +335 -0
  266. package/lib/org/leases.test.mjs +235 -0
  267. package/lib/org/mesh-integration.test.mjs +127 -0
  268. package/lib/org/mesh.mjs +459 -0
  269. package/lib/org/mesh.test.mjs +345 -0
  270. package/lib/org/messaging.mjs +503 -0
  271. package/lib/org/messaging.test.mjs +238 -0
  272. package/lib/org/policy.mjs +345 -0
  273. package/lib/org/policy.test.mjs +237 -0
  274. package/lib/org/protocol.checksum +1 -0
  275. package/lib/org/protocol.checksum.test.mjs +90 -0
  276. package/lib/org/protocol.mjs +967 -0
  277. package/lib/org/protocol.test.mjs +264 -0
  278. package/lib/org/registry.mjs +194 -0
  279. package/lib/org/registry.test.mjs +100 -0
  280. package/lib/org/tool-surface-integration.test.mjs +120 -0
  281. package/lib/org/tool-surface.mjs +2535 -0
  282. package/lib/org/tool-surface.test.mjs +589 -0
  283. package/lib/org/ui-parity.mjs +3236 -0
  284. package/lib/org/ui-parity.test.mjs +348 -0
  285. package/lib/org/verify.mjs +176 -0
  286. package/lib/org/verify.test.mjs +194 -0
  287. package/lib/rag/embed.mjs +188 -0
  288. package/lib/rag/indexer.mjs +425 -0
  289. package/lib/rag/rag.test.mjs +505 -0
  290. package/lib/rag/search.mjs +475 -0
  291. package/lib/rate-guard.mjs +246 -0
  292. package/lib/rate-guard.test.mjs +201 -0
  293. package/lib/render.mjs +112 -0
  294. package/lib/render.test.mjs +68 -0
  295. package/lib/resource-governor.mjs +297 -0
  296. package/lib/resource-governor.test.mjs +262 -0
  297. package/lib/scheduling/dynamic-jobs.mjs +675 -0
  298. package/lib/scheduling/dynamic-jobs.test.mjs +344 -0
  299. package/lib/scheduling/jitter.mjs +0 -0
  300. package/lib/scheduling/jitter.test.mjs +140 -0
  301. package/lib/secrets/broker.mjs +315 -0
  302. package/lib/secrets/broker.test.mjs +280 -0
  303. package/lib/secrets/providers.mjs +461 -0
  304. package/lib/secrets/providers.test.mjs +274 -0
  305. package/lib/security/audit-engine.mjs +684 -0
  306. package/lib/security/audit-engine.test.mjs +389 -0
  307. package/lib/security/coerce-args.mjs +552 -0
  308. package/lib/security/coerce-args.test.mjs +281 -0
  309. package/lib/security/dangerous-tools.mjs +97 -0
  310. package/lib/security/dangerous-tools.test.mjs +68 -0
  311. package/lib/security/external-content.mjs +145 -0
  312. package/lib/security/external-content.test.mjs +67 -0
  313. package/lib/security/redact.mjs +592 -0
  314. package/lib/security/redact.test.mjs +441 -0
  315. package/lib/security/secret-equal.mjs +73 -0
  316. package/lib/security/secret-equal.test.mjs +55 -0
  317. package/lib/session-permissions.mjs +101 -0
  318. package/lib/session-permissions.test.mjs +100 -0
  319. package/lib/setup/claude-probe.mjs +74 -0
  320. package/lib/setup/completeness.mjs +175 -0
  321. package/lib/setup/completeness.test.mjs +110 -0
  322. package/lib/setup/context-pack.mjs +173 -0
  323. package/lib/setup/context-pack.test.mjs +89 -0
  324. package/lib/setup/enrich.mjs +277 -0
  325. package/lib/setup/enrich.test.mjs +115 -0
  326. package/lib/setup/enroll-from-cohort.mjs +441 -0
  327. package/lib/setup/enroll-from-cohort.test.mjs +233 -0
  328. package/lib/setup/integration.test.mjs +162 -0
  329. package/lib/setup/io.mjs +360 -0
  330. package/lib/setup/io.test.mjs +77 -0
  331. package/lib/setup/run-generator.mjs +81 -0
  332. package/lib/setup/runner.mjs +244 -0
  333. package/lib/setup/runner.test.mjs +132 -0
  334. package/lib/setup/sections/comms.mjs +173 -0
  335. package/lib/setup/sections/company.mjs +120 -0
  336. package/lib/setup/sections/enrich.mjs +138 -0
  337. package/lib/setup/sections/identity.mjs +182 -0
  338. package/lib/setup/sections/identity.test.mjs +140 -0
  339. package/lib/setup/sections/learning.mjs +153 -0
  340. package/lib/setup/sections/learning.test.mjs +81 -0
  341. package/lib/setup/sections/messaging.mjs +219 -0
  342. package/lib/setup/sections/messaging.test.mjs +127 -0
  343. package/lib/setup/sections/model.mjs +102 -0
  344. package/lib/setup/sections/operating-model.mjs +78 -0
  345. package/lib/setup/sections/org.mjs +475 -0
  346. package/lib/setup/sections/org.test.mjs +313 -0
  347. package/lib/setup/sections/orgmail.mjs +173 -0
  348. package/lib/setup/sections/orgmail.test.mjs +118 -0
  349. package/lib/setup/sections/recovery.mjs +159 -0
  350. package/lib/setup/sections/recovery.test.mjs +98 -0
  351. package/lib/setup/sections/tools.mjs +132 -0
  352. package/lib/setup/sections/verify.mjs +97 -0
  353. package/lib/setup/sot.mjs +205 -0
  354. package/lib/setup/sot.test.mjs +81 -0
  355. package/lib/setup/state.mjs +151 -0
  356. package/lib/setup/state.test.mjs +92 -0
  357. package/lib/singleton.js +229 -0
  358. package/lib/singleton.test.mjs +135 -0
  359. package/lib/telemetry/alerts.mjs +216 -0
  360. package/lib/telemetry/alerts.test.mjs +109 -0
  361. package/lib/telemetry/collect.mjs +512 -0
  362. package/lib/telemetry/collect.test.mjs +202 -0
  363. package/lib/tool-definitions-integration.test.mjs +83 -0
  364. package/lib/tool-definitions.js +738 -0
  365. package/lib/tool-definitions.test.mjs +437 -0
  366. package/lib/util/fetch-timeout.mjs +136 -0
  367. package/lib/util/fetch-timeout.test.mjs +202 -0
  368. package/lib/util/reconnect.mjs +343 -0
  369. package/lib/util/reconnect.test.mjs +369 -0
  370. package/lib/util/unhandled.mjs +205 -0
  371. package/lib/util/unhandled.test.mjs +216 -0
  372. package/lib/voice/context-loader.mjs +466 -0
  373. package/lib/voice/index.mjs +100 -0
  374. package/lib/voice/openai-realtime.mjs +510 -0
  375. package/lib/voice/outbound.mjs +542 -0
  376. package/lib/voice/outbound.test.mjs +69 -0
  377. package/lib/voice/post-call-brief.mjs +428 -0
  378. package/lib/voice/provider.mjs +52 -0
  379. package/lib/voice/session-rotation.mjs +257 -0
  380. package/lib/voice/stt.mjs +161 -0
  381. package/lib/voice/stt.test.mjs +226 -0
  382. package/lib/voice/tool-bridge.mjs +370 -0
  383. package/lib/voice/tts.mjs +104 -0
  384. package/lib/voice/twilio-sip-bridge.mjs +288 -0
  385. package/lib/voice/voice.test.mjs +990 -0
  386. package/mcp/README.md +80 -0
  387. package/package.json +151 -0
  388. package/plugins/maestro-skills/plugin.json +139 -0
  389. package/plugins/maestro-skills/skills/agents-observe.md +110 -0
  390. package/plugins/maestro-skills/skills/board-deck.md +68 -0
  391. package/plugins/maestro-skills/skills/books-close.md +77 -0
  392. package/plugins/maestro-skills/skills/brand-steward.md +121 -0
  393. package/plugins/maestro-skills/skills/calendar-plan.md +57 -0
  394. package/plugins/maestro-skills/skills/call-working-sessions.md +124 -0
  395. package/plugins/maestro-skills/skills/ccxray-diagnostics.md +91 -0
  396. package/plugins/maestro-skills/skills/claude-pace.md +61 -0
  397. package/plugins/maestro-skills/skills/code-review-graph.md +99 -0
  398. package/plugins/maestro-skills/skills/crm-pipeline.md +65 -0
  399. package/plugins/maestro-skills/skills/decision-brief.md +89 -0
  400. package/plugins/maestro-skills/skills/directory-hygiene.md +125 -0
  401. package/plugins/maestro-skills/skills/draft-comms.md +84 -0
  402. package/plugins/maestro-skills/skills/evening-wrap.md +53 -0
  403. package/plugins/maestro-skills/skills/files-find.md +65 -0
  404. package/plugins/maestro-skills/skills/generative-ui.md +228 -0
  405. package/plugins/maestro-skills/skills/hiring-triage.md +74 -0
  406. package/plugins/maestro-skills/skills/inbox-triage.md +61 -0
  407. package/plugins/maestro-skills/skills/mail-triage.md +86 -0
  408. package/plugins/maestro-skills/skills/morning-brief.md +54 -0
  409. package/plugins/maestro-skills/skills/native-artifacts.md +157 -0
  410. package/plugins/maestro-skills/skills/org-board.md +133 -0
  411. package/plugins/maestro-skills/skills/org-credential.md +68 -0
  412. package/plugins/maestro-skills/skills/org-recall.md +81 -0
  413. package/plugins/maestro-skills/skills/pipeline-review.md +76 -0
  414. package/plugins/maestro-skills/skills/regulatory-status.md +81 -0
  415. package/plugins/maestro-skills/skills/router-why.md +78 -0
  416. package/plugins/maestro-skills/skills/schedule-meeting.md +91 -0
  417. package/plugins/maestro-skills/skills/session-search.md +71 -0
  418. package/plugins/maestro-skills/skills/set-reminder.md +93 -0
  419. package/plugins/maestro-skills/skills/slack-followup.md +64 -0
  420. package/plugins/maestro-skills/skills/team-activity.md +86 -0
  421. package/plugins/maestro-skills/skills/weekly-memo.md +70 -0
  422. package/policies/action-classification.yaml +114 -0
  423. package/policies/ai-disclosure.yaml +294 -0
  424. package/policies/communication-style.md +139 -0
  425. package/policies/information-barriers.yaml +118 -0
  426. package/policies/prompt-injection-defence.yaml +138 -0
  427. package/public/assets/icon-dark.png +0 -0
  428. package/public/assets/icon-dark.svg +9 -0
  429. package/public/assets/icon-light.svg +9 -0
  430. package/public/assets/logo-dark.svg +15 -0
  431. package/public/assets/logo-light.svg +15 -0
  432. package/scaffold/.mcp.json +7 -0
  433. package/scaffold/CLAUDE.md +368 -0
  434. package/scaffold/config/agent.json +55 -0
  435. package/scaffold/config/agent.ts +76 -0
  436. package/scaffold/config/agent.ts.example +89 -0
  437. package/scaffold/config/alerts.yaml +23 -0
  438. package/scaffold/config/allowlist.yaml.example +25 -0
  439. package/scaffold/config/caller-id-map.yaml +46 -0
  440. package/scaffold/config/collective.yaml +49 -0
  441. package/scaffold/config/company.json +20 -0
  442. package/scaffold/config/known-agents.json +6 -0
  443. package/scaffold/config/learning.yaml +55 -0
  444. package/scaffold/config/model-routing.yaml.example +104 -0
  445. package/scaffold/config/org.yaml +25 -0
  446. package/scaffold/config/orgmail.yaml.example +19 -0
  447. package/scaffold/config/recovery.yaml +72 -0
  448. package/scaffold/config/secrets.yaml +27 -0
  449. package/scaffold/config/slack.yaml.example +35 -0
  450. package/scaffold/config/telegram.yaml.example +38 -0
  451. package/scaffold/config/voice.yaml.example +89 -0
  452. package/scaffold/config/whatsapp.yaml.example +39 -0
  453. package/schedules/README.md +49 -0
  454. package/schedules/triggers/backlog-executor.md +102 -0
  455. package/schedules/triggers/brand-steward.md +72 -0
  456. package/schedules/triggers/daily-evening-wrap.md +159 -0
  457. package/schedules/triggers/daily-midday-sweep.md +58 -0
  458. package/schedules/triggers/daily-morning-brief.md +55 -0
  459. package/schedules/triggers/directory-hygiene.md +81 -0
  460. package/schedules/triggers/dynamic-jobs.md +40 -0
  461. package/schedules/triggers/inbox-processor.md +115 -0
  462. package/schedules/triggers/meeting-action-capture.md +60 -0
  463. package/schedules/triggers/meeting-prep.md +69 -0
  464. package/schedules/triggers/messaging-inbound.md +50 -0
  465. package/schedules/triggers/org-pulse.md +24 -0
  466. package/schedules/triggers/quarterly-self-assessment.md +54 -0
  467. package/schedules/triggers/weekly-engineering-health.md +37 -0
  468. package/schedules/triggers/weekly-execution.md +65 -0
  469. package/schedules/triggers/weekly-hiring.md +53 -0
  470. package/schedules/triggers/weekly-priorities.md +38 -0
  471. package/schedules/triggers/weekly-strategic-memo.md +124 -0
  472. package/scripts/archive-email.sh +55 -0
  473. package/scripts/cadence/cadence-status.mjs +36 -0
  474. package/scripts/cadence/enqueue-cadence-tick.mjs +174 -0
  475. package/scripts/cadence/enqueue-cadence-tick.test.mjs +187 -0
  476. package/scripts/cadence/launchd-cadence-wrapper.sh +85 -0
  477. package/scripts/cadence/launchd-cloud-relay-wrapper.sh +95 -0
  478. package/scripts/cadence/launchd-socket-mode-wrapper.sh +95 -0
  479. package/scripts/ci/check-docs-accuracy.mjs +493 -0
  480. package/scripts/ci/check-docs-accuracy.test.mjs +409 -0
  481. package/scripts/ci/check-exports-exist.mjs +140 -0
  482. package/scripts/ci/check-files-exist.mjs +107 -0
  483. package/scripts/ci/check-no-build-artifacts.mjs +111 -0
  484. package/scripts/ci/check-no-build-artifacts.test.mjs +71 -0
  485. package/scripts/ci/check-no-confidential.mjs +198 -0
  486. package/scripts/ci/check-no-conflict-markers.mjs +169 -0
  487. package/scripts/ci/check-no-residual-identity.mjs +163 -0
  488. package/scripts/ci/check-no-residual-identity.test.mjs +89 -0
  489. package/scripts/ci/check-tarball-fidelity.mjs +205 -0
  490. package/scripts/ci/check-unresolved-tokens.mjs +83 -0
  491. package/scripts/ci/check.mjs +109 -0
  492. package/scripts/ci/check.test.mjs +194 -0
  493. package/scripts/ci/run-coverage.mjs +82 -0
  494. package/scripts/ci/run-tests.mjs +71 -0
  495. package/scripts/cloud-relay/README.md +59 -0
  496. package/scripts/cloud-relay/index.mjs +233 -0
  497. package/scripts/cloud-relay/package.json +15 -0
  498. package/scripts/cloud-relay/railway.json +13 -0
  499. package/scripts/cloud-relay/voice/README.md +94 -0
  500. package/scripts/cloud-relay/voice/package-lock.json +39 -0
  501. package/scripts/cloud-relay/voice/package.json +16 -0
  502. package/scripts/cloud-relay/voice/railway.json +13 -0
  503. package/scripts/cloud-relay/voice/server.mjs +532 -0
  504. package/scripts/collective/hook-runner.mjs +211 -0
  505. package/scripts/collective/hook-runner.test.mjs +90 -0
  506. package/scripts/collective/org-pulse.mjs +72 -0
  507. package/scripts/collective/org-sync.mjs +61 -0
  508. package/scripts/collective/recall.mjs +45 -0
  509. package/scripts/collective/who.mjs +30 -0
  510. package/scripts/comms-monitor.sh +288 -0
  511. package/scripts/configure-whatsapp-sandbox.sh +201 -0
  512. package/scripts/continuous-monitor.sh +91 -0
  513. package/scripts/cost/fleet-digest.mjs +407 -0
  514. package/scripts/cost/fleet-digest.test.mjs +207 -0
  515. package/scripts/cost/track-claude-usage.mjs +169 -0
  516. package/scripts/daemon/agent-daemon.mjs +989 -0
  517. package/scripts/daemon/agent-daemon.test.mjs +525 -0
  518. package/scripts/daemon/cadence-consumer-governance.test.mjs +220 -0
  519. package/scripts/daemon/cadence-consumer.mjs +1080 -0
  520. package/scripts/daemon/cadence-consumer.test.mjs +770 -0
  521. package/scripts/daemon/cadence-handlers.mjs +1121 -0
  522. package/scripts/daemon/cadence-handlers.test.mjs +617 -0
  523. package/scripts/daemon/classifier.mjs +704 -0
  524. package/scripts/daemon/classifier.test.mjs +238 -0
  525. package/scripts/daemon/classify-kind.mjs +54 -0
  526. package/scripts/daemon/classify-kind.test.mjs +40 -0
  527. package/scripts/daemon/context-compiler.mjs +605 -0
  528. package/scripts/daemon/context-compiler.test.mjs +300 -0
  529. package/scripts/daemon/dispatcher-cooldown.test.mjs +122 -0
  530. package/scripts/daemon/dispatcher-governance.test.mjs +886 -0
  531. package/scripts/daemon/dispatcher.mjs +1516 -0
  532. package/scripts/daemon/health.mjs +72 -0
  533. package/scripts/daemon/inbox-deferral.mjs +210 -0
  534. package/scripts/daemon/inbox-deferral.test.mjs +242 -0
  535. package/scripts/daemon/integration.test.mjs +149 -0
  536. package/scripts/daemon/launchd-wrapper-generic.sh +96 -0
  537. package/scripts/daemon/launchd-wrapper-slack-events.sh +37 -0
  538. package/scripts/daemon/launchd-wrapper.sh +91 -0
  539. package/scripts/daemon/lib/session-router.mjs +274 -0
  540. package/scripts/daemon/lib/session-router.test.mjs +295 -0
  541. package/scripts/daemon/maestro-daemon.mjs +275 -0
  542. package/scripts/daemon/prompt-builder.mjs +685 -0
  543. package/scripts/daemon/prompt-builder.test.mjs +213 -0
  544. package/scripts/daemon/responder.mjs +854 -0
  545. package/scripts/daemon/session-lock.mjs +721 -0
  546. package/scripts/daemon/session-lock.test.mjs +252 -0
  547. package/scripts/daemon/session-outcomes.mjs +640 -0
  548. package/scripts/daemon/session-outcomes.test.mjs +533 -0
  549. package/scripts/daemon/typing-registry.mjs +90 -0
  550. package/scripts/daemon/typing-registry.test.mjs +77 -0
  551. package/scripts/daemon/voice-webhook-server.mjs +804 -0
  552. package/scripts/decisions/capture-decision.mjs +116 -0
  553. package/scripts/disclosure_assessment.py +873 -0
  554. package/scripts/disclosure_boundaries.py +562 -0
  555. package/scripts/email-signature-principal.html +52 -0
  556. package/scripts/email-signature.html +60 -0
  557. package/scripts/email_quote_thread.py +167 -0
  558. package/scripts/email_thread_dedup.py +362 -0
  559. package/scripts/emergency-stop.sh +81 -0
  560. package/scripts/healthcheck.sh +116 -0
  561. package/scripts/hooks/block-mcp-cohort-send.sh +15 -0
  562. package/scripts/hooks/block-mcp-slack-send.sh +7 -0
  563. package/scripts/hooks/post-action-log.sh +126 -0
  564. package/scripts/hooks/pre-send-audit.sh +174 -0
  565. package/scripts/hooks/pre-send-audit.test.mjs +215 -0
  566. package/scripts/hooks/session-end-log.sh +27 -0
  567. package/scripts/hooks/session-start-banner.sh +115 -0
  568. package/scripts/huddle/audio-bridge.mjs +664 -0
  569. package/scripts/huddle/boot-slack-cdp.sh +102 -0
  570. package/scripts/huddle/huddle-controller.mjs +942 -0
  571. package/scripts/huddle/huddle-server.mjs +1229 -0
  572. package/scripts/huddle/launch-slack.sh +232 -0
  573. package/scripts/huddle/openai-realtime-bridge.mjs +462 -0
  574. package/scripts/huddle/package-lock.json +62 -0
  575. package/scripts/huddle/package.json +22 -0
  576. package/scripts/huddle/setup-audio.sh +239 -0
  577. package/scripts/huddle/start-call.mjs +318 -0
  578. package/scripts/huddle/test-pipeline.mjs +263 -0
  579. package/scripts/learning/consolidate-skills.mjs +72 -0
  580. package/scripts/learning/session-search.mjs +125 -0
  581. package/scripts/llm_email_dedup.py +442 -0
  582. package/scripts/local-triggers/generate-plists.sh +432 -0
  583. package/scripts/local-triggers/generate-plists.test.mjs +413 -0
  584. package/scripts/local-triggers/install-all.sh +49 -0
  585. package/scripts/local-triggers/plists/.gitkeep +0 -0
  586. package/scripts/local-triggers/run-trigger.sh +63 -0
  587. package/scripts/local-triggers/templates/rag-reindex.plist.template +47 -0
  588. package/scripts/local-triggers/templates/voice-relay-poller.plist.template +54 -0
  589. package/scripts/local-triggers/templates/voice-tunnel.plist.template +55 -0
  590. package/scripts/local-triggers/templates/voice-webhook.plist.template +51 -0
  591. package/scripts/maintenance/backup-to-cloud.sh +124 -0
  592. package/scripts/maintenance/health-check.sh +377 -0
  593. package/scripts/media-generation/README.md +105 -0
  594. package/scripts/media-generation/gemini-image-client.mjs +173 -0
  595. package/scripts/media-generation/generate-assets.mjs +289 -0
  596. package/scripts/media-generation/veo-video-client.mjs +219 -0
  597. package/scripts/org/send-orgmail.mjs +227 -0
  598. package/scripts/outbound-dedup-cleanup.sh +43 -0
  599. package/scripts/outbound-dedup.sh +477 -0
  600. package/scripts/outbound_dedup.py +115 -0
  601. package/scripts/parse-voice-transcript.mjs +481 -0
  602. package/scripts/pdf-generation/README.md +63 -0
  603. package/scripts/pdf-generation/build-document.mjs +247 -0
  604. package/scripts/pdf-generation/templates/board-pack.latex +136 -0
  605. package/scripts/pdf-generation/templates/corporate-letter.latex +126 -0
  606. package/scripts/pdf-generation/templates/memo.latex +114 -0
  607. package/scripts/poll-slack-events.sh +35 -0
  608. package/scripts/poller/calendar-poller.mjs +12 -0
  609. package/scripts/poller/gmail-poller.mjs +192 -0
  610. package/scripts/poller/imap-client.mjs +289 -0
  611. package/scripts/poller/inbox-scan-poller.mjs +156 -0
  612. package/scripts/poller/inbox-scan-poller.test.mjs +231 -0
  613. package/scripts/poller/index.mjs +73 -0
  614. package/scripts/poller/intra-session-check.mjs +285 -0
  615. package/scripts/poller/lib/cloud-relay-dedup.mjs +88 -0
  616. package/scripts/poller/lib/cloud-relay-dedup.test.mjs +133 -0
  617. package/scripts/poller/lib/slash-command-handlers.mjs +177 -0
  618. package/scripts/poller/secondary-gmail-poller.mjs +132 -0
  619. package/scripts/poller/slack-cloud-relay-client.mjs +368 -0
  620. package/scripts/poller/slack-poller.mjs +854 -0
  621. package/scripts/poller/slack-socket-mode.mjs +917 -0
  622. package/scripts/poller/slack-socket-mode.test.mjs +753 -0
  623. package/scripts/poller/trigger.mjs +75 -0
  624. package/scripts/poller/utils.mjs +371 -0
  625. package/scripts/poller/voice-cloud-relay-client.mjs +179 -0
  626. package/scripts/poller/voice-poller.mjs +236 -0
  627. package/scripts/poller-launchd/install.sh +66 -0
  628. package/scripts/poller-launchd/poller.plist.template +40 -0
  629. package/scripts/poller-launchd/whatsapp-handler.plist.template +39 -0
  630. package/scripts/post-interaction-indexer.py +1598 -0
  631. package/scripts/pre-draft-context.py +994 -0
  632. package/scripts/pre_draft_lookup.py +258 -0
  633. package/scripts/rag/build-index.mjs +47 -0
  634. package/scripts/rag/ingest.mjs +111 -0
  635. package/scripts/rag/search.mjs +119 -0
  636. package/scripts/rag-indexer.py +629 -0
  637. package/scripts/restore-from-backup.sh +248 -0
  638. package/scripts/restore-from-backup.test.mjs +178 -0
  639. package/scripts/resume-operations.sh +80 -0
  640. package/scripts/search-secondary-inbox.py +181 -0
  641. package/scripts/secondary-inbox-poller.py +437 -0
  642. package/scripts/self-optimization/compute-metrics.py +398 -0
  643. package/scripts/send-email-as-principal.py +369 -0
  644. package/scripts/send-email-threaded.py +392 -0
  645. package/scripts/send-email-with-attachment.py +377 -0
  646. package/scripts/send-email.sh +131 -0
  647. package/scripts/send-sms.sh +175 -0
  648. package/scripts/send-whatsapp.sh +292 -0
  649. package/scripts/session-start.sh +106 -0
  650. package/scripts/setup/boot-claude-session.sh +94 -0
  651. package/scripts/setup/configure-macos.sh +674 -0
  652. package/scripts/setup/configure-twilio-sip-trunk.mjs +207 -0
  653. package/scripts/setup/configure-voice-tunnel.mjs +182 -0
  654. package/scripts/setup/generate-agent-env.mjs +92 -0
  655. package/scripts/setup/generate-agent-package-json.mjs +222 -0
  656. package/scripts/setup/generate-agent-package-json.test.mjs +143 -0
  657. package/scripts/setup/generate-autonomy.mjs +60 -0
  658. package/scripts/setup/generate-backlog.mjs +101 -0
  659. package/scripts/setup/generate-cadences.mjs +92 -0
  660. package/scripts/setup/generate-capability.mjs +162 -0
  661. package/scripts/setup/generate-charter.mjs +76 -0
  662. package/scripts/setup/generate-comms.mjs +59 -0
  663. package/scripts/setup/generate-company.mjs +92 -0
  664. package/scripts/setup/init-agent.sh +547 -0
  665. package/scripts/setup/init-agent.test.mjs +151 -0
  666. package/scripts/setup/init-archetype.mjs +74 -0
  667. package/scripts/setup/init-backup.mjs +54 -0
  668. package/scripts/setup/init-cadence-bus.mjs +60 -0
  669. package/scripts/setup/init-channel-bus.mjs +46 -0
  670. package/scripts/setup/init-cost-tracking.mjs +45 -0
  671. package/scripts/setup/init-decision-capture.mjs +66 -0
  672. package/scripts/setup/init-known-agents.mjs +57 -0
  673. package/scripts/setup/init-learning.mjs +70 -0
  674. package/scripts/setup/init-memory-executive.mjs +45 -0
  675. package/scripts/setup/init-model-router.mjs +124 -0
  676. package/scripts/setup/init-rag.mjs +174 -0
  677. package/scripts/setup/init-session-router.mjs +38 -0
  678. package/scripts/setup/init-slack-socket-mode.mjs +260 -0
  679. package/scripts/setup/init-telegram.mjs +165 -0
  680. package/scripts/setup/init-voice-realtime.mjs +204 -0
  681. package/scripts/setup/init-whatsapp-baileys.mjs +77 -0
  682. package/scripts/setup/install-dev-tools.sh +150 -0
  683. package/scripts/setup/lib/install-plist.mjs +95 -0
  684. package/scripts/setup/migrate-agent-to-sot.mjs +192 -0
  685. package/scripts/setup/render-environment-yaml.mjs +133 -0
  686. package/scripts/slack-events-ctl.sh +177 -0
  687. package/scripts/slack-events-server.mjs +1045 -0
  688. package/scripts/slack-react.mjs +89 -0
  689. package/scripts/slack-responded.sh +232 -0
  690. package/scripts/slack-send.sh +287 -0
  691. package/scripts/slack-typing.mjs +196 -0
  692. package/scripts/slack-upload-v2.py +95 -0
  693. package/scripts/sms-handler.mjs +450 -0
  694. package/scripts/spawn-session.sh +120 -0
  695. package/scripts/sync-protocol.mjs +217 -0
  696. package/scripts/system-verify.sh +184 -0
  697. package/scripts/test-email-thread-dedup.py +239 -0
  698. package/scripts/test-information-barriers.py +484 -0
  699. package/scripts/test-llm-email-dedup.py +251 -0
  700. package/scripts/test-pre-draft-integration.py +203 -0
  701. package/scripts/test-rag-phase2.sh +442 -0
  702. package/scripts/test-rag-search.sh +251 -0
  703. package/scripts/test-voice-parser.mjs +316 -0
  704. package/scripts/user-context-search.py +659 -0
  705. package/scripts/validate_outbound.py +1504 -0
  706. package/scripts/watchdog/ai.maestro.memory-watchdog.plist +41 -0
  707. package/scripts/watchdog/force-reboot.sh +157 -0
  708. package/scripts/watchdog/memory-watchdog.sh +473 -0
  709. package/scripts/whatsapp-handler.mjs +538 -0
  710. package/teams/desktop-operations.yaml +34 -0
  711. package/teams/executive-office.yaml +27 -0
  712. package/teams/legal-and-regulatory.yaml +24 -0
  713. package/teams/platform-and-engineering.yaml +23 -0
  714. package/teams/strategy-and-growth.yaml +29 -0
  715. package/workflows/continuous/backlog-executor.yaml +141 -0
  716. package/workflows/continuous/inbound-monitor.yaml +168 -0
  717. package/workflows/daily/applicant-triage.yaml +197 -0
  718. package/workflows/daily/comms-triage.yaml +80 -0
  719. package/workflows/daily/evening-wrap.yaml +105 -0
  720. package/workflows/daily/morning-brief.yaml +164 -0
  721. package/workflows/daily/slack-followup-sweep.yaml +87 -0
  722. package/workflows/event-driven/README.md +50 -0
  723. package/workflows/event-driven/agent-failure-investigation.yaml +137 -0
  724. package/workflows/event-driven/pr-review.yaml +107 -0
  725. package/workflows/monthly/board-readiness.yaml +76 -0
  726. package/workflows/quarterly/strategic-scenario-analysis.yaml +85 -0
  727. package/workflows/session-protocol.md +171 -0
  728. package/workflows/weekly/engineering-health.yaml +154 -0
  729. package/workflows/weekly/hiring-review.yaml +169 -0
  730. package/workflows/weekly/rollup-pipeline-review.yaml +76 -0
  731. package/workflows/weekly/strategic-memo.yaml +79 -0
@@ -0,0 +1,227 @@
1
+ # Telegram Setup Guide
2
+
3
+ How to enable Telegram messaging for a Maestro agent: creating a bot with
4
+ BotFather, wiring the token, the in-daemon grammY long-poll adapter, inbound event
5
+ mapping (DMs, groups, forum topics, reactions, media, voice→STT), default-deny DM
6
+ pairing, and outbound sending.
7
+
8
+ **Prerequisites**: A working agent repo (`maestro create` + `maestro setup`
9
+ identity done) and a Telegram account to talk to BotFather.
10
+
11
+ ---
12
+
13
+ ## Architecture Overview
14
+
15
+ Unlike WhatsApp/SMS (which use Twilio webhooks behind a Cloudflare tunnel),
16
+ Telegram runs entirely **inside the daemon** via grammY long-polling — there is
17
+ **no relay, no tunnel, and no extra process**:
18
+
19
+ ```
20
+ ┌─────────────────────────────────────────────────────────────────┐
21
+ │ INBOUND │
22
+ │ │
23
+ │ Telegram user ──▶ Telegram Bot API │
24
+ │ │ (long-poll: getUpdates) │
25
+ │ ▼ │
26
+ │ lib/channels/telegram/adapter.mjs (grammY) │
27
+ │ │ _toEvent → MessageEvent │
28
+ │ ▼ │
29
+ │ writeInboxItem → state/inbox/telegram/*.yaml │
30
+ │ (classifier / dispatcher route — unchanged) │
31
+ ├─────────────────────────────────────────────────────────────────┤
32
+ │ OUTBOUND │
33
+ │ │
34
+ │ adapter._send ──▶ Telegram Bot API ──▶ Telegram user │
35
+ │ (typing heartbeat via sendChatAction while a session runs) │
36
+ ├─────────────────────────────────────────────────────────────────┤
37
+ │ PAIRING (default-deny) │
38
+ │ │
39
+ │ Unknown DM ──▶ "pair <code>" gate ──▶ config/allowlist.yaml │
40
+ └─────────────────────────────────────────────────────────────────┘
41
+ ```
42
+
43
+ grammY is a **dynamic dependency** (like Baileys): the package installs without
44
+ it, and the daemon only loads the Telegram adapter when `config/telegram.yaml`
45
+ exists. Flip the gate file off to disable the channel.
46
+
47
+ ---
48
+
49
+ ## 1. Create a Bot with BotFather
50
+
51
+ 1. Open Telegram and message **@BotFather**.
52
+ 2. Send `/newbot`. Choose a display name and a username ending in `bot`.
53
+ 3. BotFather replies with an HTTP API token like `123456789:ABCdef...`. Keep it secret.
54
+
55
+ ### (Optional) Let the bot read all group messages
56
+
57
+ By default a bot only sees `@mentions`, replies, and commands in groups. To let it
58
+ read every message in a group:
59
+
60
+ 1. @BotFather → `/setprivacy` → pick your bot → **Disable**.
61
+
62
+ Leave privacy **enabled** if you only want the agent to react when addressed.
63
+
64
+ ---
65
+
66
+ ## 2. Wire the Token and Activate the Channel
67
+
68
+ Run the idempotent init script (mirrors `init-whatsapp-baileys.mjs`):
69
+
70
+ ```bash
71
+ node scripts/setup/init-telegram.mjs
72
+ ```
73
+
74
+ It will:
75
+
76
+ 1. Walk you through the BotFather steps above.
77
+ 2. Prompt for the token and append `TELEGRAM_BOT_TOKEN=...` to `.env` (never
78
+ overwriting an existing value; it skips the prompt when stdin is non-interactive).
79
+ 3. **Validate the token** via the Telegram `getMe` API (no grammY needed) and print
80
+ the resolved bot username.
81
+ 4. Activate `config/telegram.yaml` from the scaffold example (the gate file).
82
+ 5. Check for the optional `grammy` npm package and print an install hint if missing.
83
+
84
+ Install grammY in the agent repo so the daemon can load the adapter:
85
+
86
+ ```bash
87
+ npm i grammy
88
+ ```
89
+
90
+ You can also set the token by hand in `.env`:
91
+
92
+ ```bash
93
+ # Telegram (grammY long-poll, in-daemon)
94
+ TELEGRAM_BOT_TOKEN=123456789:ABCdef...
95
+ ```
96
+
97
+ ### Wiring through `maestro setup`
98
+
99
+ The `comms` section of the setup wizard wires Telegram alongside the other
100
+ channels and verifies it:
101
+
102
+ ```bash
103
+ maestro setup comms
104
+ ```
105
+
106
+ It runs the same init flow, confirms `config/telegram.yaml` is present, and
107
+ includes Telegram in the capability table (the verify probe checks `getMe`).
108
+
109
+ ---
110
+
111
+ ## 3. Inbound — Event Mapping
112
+
113
+ The adapter's `_toEvent` translates each grammY update into the unified
114
+ `MessageEvent` contract (`lib/channels/contract.mjs`). Mapping:
115
+
116
+ | Telegram update | `MessageEvent` |
117
+ |---|---|
118
+ | Private message (DM) | `kind: "message"`, `source: telegram`, thread keyed to the DM |
119
+ | Group / supergroup message | `kind: "message"` with the chat as the conversation |
120
+ | Forum **topic** (`message_thread_id`) | `kind: "message"` with `thread_context` set to the topic |
121
+ | Reaction (`message_reaction`) | `kind: "reaction"` (resolves the target message text) |
122
+ | Photo / document / audio | `kind: "message"` with the media attached |
123
+ | **Voice note** | `kind: "voice_note"` — audio is run through STT and the transcript becomes the message body |
124
+
125
+ Because `MessageEvent` is serialized to the same on-disk inbox-item bytes as the
126
+ legacy poller (`lib/channels/inbox-item.mjs`), the classifier, directed-gate, and
127
+ dispatcher handle Telegram items with no special-casing.
128
+
129
+ ---
130
+
131
+ ## 4. DM Pairing (default-deny)
132
+
133
+ Telegram DMs are **default-deny**: an unknown sender cannot reach the agent until
134
+ they pair. Pairing is enforced in `BaseAdapter` (so every channel inherits it) via
135
+ `lib/channels/pairing.mjs` and the cross-channel allowlist `config/allowlist.yaml`.
136
+
137
+ - An unknown DM is intercepted **before** the classifier; the agent does not act on it.
138
+ - The sender pairs by sending exactly `pair <code>` (matched by `^pair <code>$`).
139
+ - Once redeemed, their Telegram id is added to the allowlist and subsequent messages flow normally.
140
+ - You can also seed allowlisted ids ahead of time under the `telegram:` key in `config/allowlist.yaml`.
141
+
142
+ Groups follow the bot's privacy setting (see §1); pairing applies to direct
143
+ messages.
144
+
145
+ ---
146
+
147
+ ## 5. Outbound — Sending and Typing
148
+
149
+ Outbound goes through the adapter's `_send`. While a session is working on a
150
+ Telegram conversation, `BaseAdapter`'s typing heartbeat calls `sendChatAction`
151
+ (`typing`) every few seconds so the user sees the agent "typing…" until the reply
152
+ lands — the same holding behaviour as Slack/WhatsApp. SMS/Gmail have no typing
153
+ capability and are no-ops there.
154
+
155
+ Outbound messages pass through the standard pre-send pipeline (content-hash dedup,
156
+ factual validation, audit logging) like every other channel.
157
+
158
+ ---
159
+
160
+ ## 6. Testing
161
+
162
+ | # | Test | How to Verify |
163
+ |---|---|---|
164
+ | 1 | Token valid | `node scripts/setup/init-telegram.mjs` prints `token valid — bot is @yourbot` |
165
+ | 2 | Gate file present | `config/telegram.yaml` exists |
166
+ | 3 | grammY installed | `ls node_modules/grammy` |
167
+ | 4 | Daemon loads adapter | Start the daemon; check logs for the Telegram adapter connecting |
168
+ | 5 | Inbound DM | DM the bot; check `state/inbox/telegram/` for a YAML item |
169
+ | 6 | Pairing blocks unknown | DM from an unpaired account → no agent action until `pair <code>` |
170
+ | 7 | Group mention | @mention the bot in a group; verify it's captured |
171
+ | 8 | Reaction captured | React to a message the bot can see; verify `kind: reaction` |
172
+ | 9 | Voice note → STT | Send a voice note; verify the transcript appears as the message body |
173
+ | 10 | Verify probe | `maestro setup comms` (or `maestro doctor`) shows Telegram passing |
174
+
175
+ ---
176
+
177
+ ## 7. Troubleshooting
178
+
179
+ ### `getMe` validation fails
180
+
181
+ 1. Re-copy the token from BotFather — a trailing space or missing digits breaks it.
182
+ 2. The token format is `digits:alphanumerics` (e.g. `123456789:ABCdef...`).
183
+ 3. If you regenerated the token via `/revoke`, update `TELEGRAM_BOT_TOKEN` in `.env`.
184
+
185
+ ### Bot doesn't see group messages
186
+
187
+ 1. Privacy mode is **enabled** by default — the bot only sees mentions/replies/commands.
188
+ 2. @BotFather → `/setprivacy` → your bot → **Disable**, then re-add the bot to the group.
189
+
190
+ ### Daemon starts but Telegram never connects
191
+
192
+ 1. Confirm `config/telegram.yaml` exists (the gate file) — without it the adapter never loads.
193
+ 2. Confirm `grammy` is installed in the **agent** repo: `npm i grammy`.
194
+ 3. Check the daemon logs for a token or network error from `getUpdates`.
195
+
196
+ ### Unknown sender can't reach the agent
197
+
198
+ That's the default-deny pairing working as designed. Have them send `pair <code>`,
199
+ or seed their id under `telegram:` in `config/allowlist.yaml`.
200
+
201
+ ### Conflict: "terminated by other getUpdates request"
202
+
203
+ Two processes are long-polling the same bot token. Telegram allows only one. Make
204
+ sure you aren't running a second daemon (or a stray script) with the same
205
+ `TELEGRAM_BOT_TOKEN`.
206
+
207
+ ---
208
+
209
+ ## Key Files
210
+
211
+ | File | Purpose |
212
+ |---|---|
213
+ | `lib/channels/telegram/adapter.mjs` | grammY long-poll adapter (`_connect/_toEvent/_send/_react/_setTyping`) |
214
+ | `scripts/setup/init-telegram.mjs` | Idempotent init: BotFather walkthrough, token → `.env`, `getMe` validation, gate-file activation |
215
+ | `config/telegram.yaml` | Channel gate file (activated from the scaffold example) |
216
+ | `config/allowlist.yaml` | Cross-channel default-deny DM allowlist (the `telegram:` key) |
217
+ | `lib/channels/contract.mjs` | The unified `MessageEvent` contract `_toEvent` maps onto |
218
+ | `lib/channels/base-adapter.mjs` | Session-keying, typing heartbeat, and pairing gate inherited by the adapter |
219
+
220
+ ---
221
+
222
+ ## Related Documents
223
+
224
+ - [Setup Wizard](setup-wizard.md) — the `comms` section that wires Telegram
225
+ - [Channel bus](channel-bus.md) — the unified messaging layer and `MessageEvent` contract
226
+ - [WhatsApp Setup](whatsapp-setup.md) — the Baileys channel this guide mirrors
227
+ - [Poller & Daemon Setup](poller-daemon-setup.md) — how channel events integrate with the event loop
@@ -0,0 +1,223 @@
1
+ # Twilio Sub-Accounts Setup Guide
2
+
3
+ How to create a dedicated Twilio sub-account for each Maestro agent under a single parent Twilio account. This is required for per-agent WhatsApp segregation because the **Twilio WhatsApp Sandbox webhook is account-wide** — only one URL per Twilio account.
4
+
5
+ **Prerequisites**: A parent Twilio account already exists (the company's root account). You have its `Account SID` and `Auth Token`.
6
+
7
+ ---
8
+
9
+ ## Why sub-accounts?
10
+
11
+ Each agent runs as a separate identity (one per principal) and needs:
12
+
13
+ - Its own phone number (for SMS)
14
+ - Its own WhatsApp sandbox webhook URL (the constraint)
15
+ - Its own auth token (so the agent's webhook relay can verify Twilio HMAC signatures independently)
16
+ - Its own usage logs and cost attribution
17
+
18
+ Sub-accounts give you all of this while still rolling up to the parent account for billing.
19
+
20
+ | Constraint | Sharing parent account | Per-agent sub-account |
21
+ |---|---|---|
22
+ | WhatsApp sandbox webhook | One URL for ALL agents — only the latest agent's webhook works | Each agent has their own sandbox + webhook |
23
+ | Phone numbers | Mixed across agents on one account | Each agent has their own |
24
+ | Auth Token | Shared — every agent's relay can verify everything (security risk) | Per-agent token, isolated verification |
25
+ | Cost attribution | Aggregated — hard to attribute to a specific agent | Sub-account usage rolls up but is separately reportable |
26
+ | Suspension | Suspending the parent kills all agents | Suspend just the affected agent |
27
+
28
+ ---
29
+
30
+ ## 1. Create the sub-account
31
+
32
+ Run from the agent's repo (or anywhere with `TWILIO_PARENT_ACCOUNT_SID` and `TWILIO_PARENT_AUTH_TOKEN` set):
33
+
34
+ ```bash
35
+ TWILIO_PARENT_ACCOUNT_SID=AC... # parent
36
+ TWILIO_PARENT_AUTH_TOKEN=... # parent
37
+ AGENT_NAME="jordan-lee-northwind" # whatever friendly name you want
38
+
39
+ curl -s -u "$TWILIO_PARENT_ACCOUNT_SID:$TWILIO_PARENT_AUTH_TOKEN" -X POST \
40
+ "https://api.twilio.com/2010-04-01/Accounts.json" \
41
+ --data-urlencode "FriendlyName=$AGENT_NAME" \
42
+ | python3 -m json.tool
43
+ ```
44
+
45
+ Capture from the response:
46
+
47
+ - `sid` — the new sub-account SID (starts with `AC...`)
48
+ - `auth_token` — the sub-account's auth token (use this for HMAC verification on the agent's webhook relay)
49
+ - `owner_account_sid` — confirms it's a child of the parent account
50
+
51
+ Save both to the agent's `.env`:
52
+
53
+ ```bash
54
+ # Jordan's dedicated Twilio sub-account
55
+ TWILIO_ACCOUNT_SID=ACf2... # the new sub-account SID
56
+ TWILIO_AUTH_TOKEN=c1da... # the new sub-account auth token
57
+
58
+ # Parent account — only used for sub-account management API calls
59
+ TWILIO_PARENT_ACCOUNT_SID=AC36...
60
+ TWILIO_PARENT_AUTH_TOKEN=af86...
61
+ ```
62
+
63
+ ---
64
+
65
+ ## 2. Buy a phone number under the sub-account
66
+
67
+ Search for available numbers:
68
+
69
+ ```bash
70
+ source .env
71
+ curl -s -u "$TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN" \
72
+ "https://api.twilio.com/2010-04-01/Accounts/$TWILIO_ACCOUNT_SID/AvailablePhoneNumbers/US/Local.json?AreaCode=628&SmsEnabled=true&VoiceEnabled=true&PageSize=5"
73
+ ```
74
+
75
+ Buy one (irreversible — costs ~$1.15/mo + per-message charges):
76
+
77
+ ```bash
78
+ PHONE="+16283454599"
79
+ curl -s -u "$TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN" -X POST \
80
+ "https://api.twilio.com/2010-04-01/Accounts/$TWILIO_ACCOUNT_SID/IncomingPhoneNumbers.json" \
81
+ --data-urlencode "PhoneNumber=$PHONE" \
82
+ --data-urlencode "FriendlyName=Jordan Lee - Northwind"
83
+ ```
84
+
85
+ Save the returned `sid` (starts with `PN...`) to `.env` as `TWILIO_PHONE_SID`.
86
+
87
+ ### Transferring an existing number from the parent
88
+
89
+ If the agent already has a number under the parent account that you want to move to the sub-account:
90
+
91
+ ```bash
92
+ PARENT_SID="AC36..." # parent account SID
93
+ PARENT_AUTH="af86..." # parent account auth token
94
+ PHONE_SID="PN1eb30e..." # the number to move
95
+ SUBACCOUNT_SID="ACf2..." # destination sub-account
96
+
97
+ curl -s -u "$PARENT_SID:$PARENT_AUTH" -X POST \
98
+ "https://api.twilio.com/2010-04-01/Accounts/$PARENT_SID/IncomingPhoneNumbers/$PHONE_SID.json" \
99
+ --data-urlencode "AccountSid=$SUBACCOUNT_SID"
100
+ ```
101
+
102
+ The number, all its webhook configuration, and message history move to the sub-account in one API call.
103
+
104
+ ---
105
+
106
+ ## 3. Configure the SMS webhook
107
+
108
+ After the sub-account owns the number, configure the SMS webhook to point at the agent's Railway webhook relay:
109
+
110
+ ```bash
111
+ source .env
112
+ RELAY_URL="https://${AGENT_FIRSTNAME_LOWER}-webhook-relay-production.up.railway.app"
113
+ curl -s -u "$TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN" -X POST \
114
+ "https://api.twilio.com/2010-04-01/Accounts/$TWILIO_ACCOUNT_SID/IncomingPhoneNumbers/$TWILIO_PHONE_SID.json" \
115
+ --data-urlencode "SmsUrl=$RELAY_URL/sms" \
116
+ --data-urlencode "SmsMethod=POST"
117
+ ```
118
+
119
+ ---
120
+
121
+ ## 4. Configure the WhatsApp sandbox
122
+
123
+ This is the whole reason we use sub-accounts. Each sub-account has its own independent WhatsApp sandbox.
124
+
125
+ **Important**: WhatsApp sandbox webhook configuration is **UI-only** — Twilio does not expose an API for this. You must use Playwright or the user must configure it manually.
126
+
127
+ 1. Log in to the Twilio Console (the sandbox UI uses a different login session than the API)
128
+ 2. **Switch to the sub-account** via the account selector top-left (the dropdown shows all sub-accounts under the parent)
129
+ 3. Navigate to: `https://console.twilio.com/us1/develop/sms/try-it-out/whatsapp-learn?frameUrl=%2Fconsole%2Fsms%2Fwhatsapp%2Flearn`
130
+ 4. Click **Sandbox settings** tab
131
+ 5. Set the inbound webhook URL: `https://{firstname}-webhook-relay-production.up.railway.app/whatsapp`
132
+ 6. Set the status callback URL: `https://{firstname}-webhook-relay-production.up.railway.app/whatsapp/status`
133
+ 7. Set both methods to HTTP POST
134
+ 8. Save
135
+
136
+ Note the **sandbox join code** shown on the page (e.g. `join follow-arm`). Users must send `join {code}` from their WhatsApp to `+1 415 523 8886` to enroll their number for testing with this agent's sandbox.
137
+
138
+ ### Production WhatsApp (post-sandbox)
139
+
140
+ For production WhatsApp (real WABA business number, not the shared sandbox number), each sub-account can register its own WABA. This requires Facebook Business verification per sub-account — Twilio provides a self-sign-up flow at https://www.twilio.com/docs/whatsapp/self-sign-up. Same pattern: each agent's sub-account → its own WABA → its own webhook URL.
141
+
142
+ ---
143
+
144
+ ## 5. Update the Railway webhook relay
145
+
146
+ The agent's relay verifies Twilio HMAC signatures using the sub-account's auth token (NOT the parent's). After creating the sub-account, update the Railway env var:
147
+
148
+ ```bash
149
+ source .env
150
+ cd services/webhook-relay
151
+ railway variables --service ${AGENT_FIRSTNAME_LOWER}-webhook-relay \
152
+ --set "TWILIO_AUTH_TOKEN=$TWILIO_AUTH_TOKEN"
153
+ railway up --service ${AGENT_FIRSTNAME_LOWER}-webhook-relay --detach
154
+ ```
155
+
156
+ Wait until `/health` reports `twilio_signature: true` again.
157
+
158
+ ---
159
+
160
+ ## 6. Add to init-maestro Phase 4
161
+
162
+ When `/init-maestro` runs Phase 4 Service Configuration, the Twilio step should:
163
+
164
+ 1. Check whether `TWILIO_PARENT_ACCOUNT_SID` is set in `.env` (from a previous agent's setup or org config)
165
+ 2. If yes: create a sub-account for this agent via the API (Step 1 above), then bypass the "buy new account" flow
166
+ 3. If no: this is the first agent in the org — use `TWILIO_ACCOUNT_SID` as both parent and main, and document that future agents will need sub-accounts under it
167
+ 4. Buy a phone number under the sub-account
168
+ 5. Configure SMS webhook → Railway
169
+ 6. (Manual or Playwright) Configure WhatsApp sandbox → Railway
170
+
171
+ ---
172
+
173
+ ## Verification
174
+
175
+ ```bash
176
+ # 1. Sub-account exists and is active
177
+ source .env
178
+ curl -s -u "$TWILIO_PARENT_ACCOUNT_SID:$TWILIO_PARENT_AUTH_TOKEN" \
179
+ "https://api.twilio.com/2010-04-01/Accounts/$TWILIO_ACCOUNT_SID.json" \
180
+ | python3 -m json.tool
181
+
182
+ # 2. Phone number is owned by the sub-account
183
+ curl -s -u "$TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN" \
184
+ "https://api.twilio.com/2010-04-01/Accounts/$TWILIO_ACCOUNT_SID/IncomingPhoneNumbers.json"
185
+
186
+ # 3. SMS webhook points at Railway
187
+ curl -s -u "$TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN" \
188
+ "https://api.twilio.com/2010-04-01/Accounts/$TWILIO_ACCOUNT_SID/IncomingPhoneNumbers/$TWILIO_PHONE_SID.json" \
189
+ | python3 -c "import sys,json; d=json.load(sys.stdin); print('SMS URL:', d.get('sms_url'))"
190
+
191
+ # 4. Send a test SMS using the sub-account credentials
192
+ bash scripts/send-sms.sh --to "+1...your_test_number" --body "Sub-account test from {AgentName}"
193
+
194
+ # 5. Send a WhatsApp message after joining the sandbox
195
+ bash scripts/send-whatsapp.sh --to "whatsapp:+1...your_number" --body "WhatsApp test from {AgentName}"
196
+ ```
197
+
198
+ ---
199
+
200
+ ## Closing / suspending a sub-account
201
+
202
+ When an agent is decommissioned:
203
+
204
+ ```bash
205
+ source .env
206
+ curl -s -u "$TWILIO_PARENT_ACCOUNT_SID:$TWILIO_PARENT_AUTH_TOKEN" -X POST \
207
+ "https://api.twilio.com/2010-04-01/Accounts/$TWILIO_ACCOUNT_SID.json" \
208
+ --data-urlencode "Status=closed"
209
+ ```
210
+
211
+ Closing is irreversible. Use `Status=suspended` for temporary suspension (can be reactivated).
212
+
213
+ Before closing, decide what to do with the agent's phone number:
214
+ - Transfer back to the parent account (if you want to retain the number for re-use)
215
+ - Release it (Twilio will free up the number, you stop being charged)
216
+
217
+ ---
218
+
219
+ ## Related guides
220
+
221
+ - [Webhook Relay Setup](webhook-relay-setup.md) — How the Railway relay uses `TWILIO_AUTH_TOKEN` to verify HMAC signatures
222
+ - [Voice & SMS Setup](voice-sms-setup.md) — End-to-end SMS pipeline
223
+ - [WhatsApp Setup](whatsapp-setup.md) — Sandbox vs production WhatsApp
@@ -0,0 +1,128 @@
1
+ # Verifying Maestro
2
+
3
+ How to prove the framework works — from the zero-credential automated suite to a
4
+ full live agent. Use the fast path for every change; use the live sections when
5
+ you've wired real channel/model credentials.
6
+
7
+ ## 1. Fast path — automated suite (no credentials, ~7s)
8
+
9
+ From the framework checkout (`~/maestro`):
10
+
11
+ ```bash
12
+ npm install # once
13
+ npm test # full suite — 862 tests across every subsystem
14
+ npm run check # 6 zero-dependency guards (conflict markers, exports,
15
+ # files-exist, no-confidential, unresolved tokens, identity)
16
+ ```
17
+
18
+ `npm test` is the single source of truth for the logic of all four workstreams
19
+ (it runs hermetically — every channel socket, `claude --print`, and `os`-stat is
20
+ injected, so there's no network or real spawn). Green here means the wizard,
21
+ channel contract, learning loop, governor, rate-guard, budget-guard, cadence bus,
22
+ and recovery paths all behave.
23
+
24
+ Scoped subsets (all defined in `package.json`):
25
+
26
+ ```bash
27
+ npm run test:setup # the maestro setup wizard (lib/setup/*)
28
+ npm run test:channels # channel abstraction
29
+ npm run test:cadence # cadence bus + consumer + enqueue
30
+ npm run test:voice # voice
31
+ npm run test:cli # bin/maestro.mjs
32
+ ```
33
+
34
+ Run one file directly while iterating:
35
+
36
+ ```bash
37
+ node --test lib/learning/curator-consolidate.test.mjs
38
+ node --test lib/channels/whatsapp/baileys-typing.test.mjs
39
+ ```
40
+
41
+ ## 2. The setup wizard (deterministic — safe to dry-run anywhere)
42
+
43
+ ```bash
44
+ node bin/maestro.mjs setup --help # command + flag reference
45
+ ```
46
+
47
+ Inside an **agent instance repo** (one created by `maestro create`):
48
+
49
+ ```bash
50
+ maestro setup --status # per-section detect(): unconfigured / partial / complete
51
+ maestro setup --dry-run # show what each section would do; writes nothing
52
+ maestro setup --only comms # (re)run a single section
53
+ ```
54
+
55
+ Unattended / CI config (no prompts, no LLM unless you drop `--no-enrich`):
56
+
57
+ ```bash
58
+ maestro setup --headless --answers answers.json
59
+ ```
60
+
61
+ `lib/setup/integration.test.mjs` already exercises this end-to-end: it copies the
62
+ `scaffold/`, runs the wizard headless on a fixture answers file, asserts a green
63
+ completeness gate, and re-runs to prove idempotency. That test is the canonical
64
+ "the wizard actually configures an agent" proof.
65
+
66
+ ## 3. `maestro doctor` — runtime health of a configured agent
67
+
68
+ ```bash
69
+ maestro doctor # identity + operating-model completeness, channels,
70
+ # cadence-bus arch, watchdog heartbeat, .emergency-stop
71
+ # (human-only now), governor ceiling vs RAM, open rate
72
+ # breaker, pmset autorestart, resume-pending strikes,
73
+ # today's budget band
74
+ maestro doctor --fix # apply the auto-fixable findings
75
+ ```
76
+
77
+ ## 4. Live, per-subsystem (needs the relevant credentials)
78
+
79
+ ### Messaging (real-time)
80
+ - **Telegram** — set `TELEGRAM_BOT_TOKEN`, then `node scripts/setup/init-telegram.mjs`
81
+ (validates via `getMe`, writes `config/telegram.yaml`). DM the bot; unknown DMs
82
+ are default-denied → reply `pair <code>` to pair. Long-poll runs inside the
83
+ daemon (no relay/tunnel).
84
+ - **Slack** — `node scripts/setup/init-slack-socket-mode.mjs`; enable reactions /
85
+ thread-context / CC'd channels via `config/slack.yaml`. The dedicated launchd
86
+ socket process is the single owner (do **not** also set the daemon adapter).
87
+ - **WhatsApp (Baileys)** — `npm i baileys` in the agent repo, scan the QR
88
+ (`state/whatsapp/auth/pending-qr.txt`); the agent now shows a real "typing…"
89
+ presence while it composes a reply.
90
+ - **Verify inbound actually works** — `maestro setup comms` runs a per-channel
91
+ probe that drops a sentinel and asserts a matching inbox-item / connect-log
92
+ appears within a timeout (it prints the `tail -f` command on failure).
93
+
94
+ ### Self-learning loop
95
+ - End a Claude Code session in an agent repo → the global `Stop` hook spawns the
96
+ detached reflect worker. Confirm:
97
+ - `plugins/agent-skills/skills/<id>.md` — any newly authored skill (live on disk
98
+ immediately; the next session loads it).
99
+ - `logs/audit/skills.jsonl` — every create/patch/abort/consolidate row.
100
+ - `state/learning/counters.json` — the nudge counters.
101
+ - **Verbatim recall** — invoke the `session-search` skill (discovery / scroll /
102
+ read / browse) over `state/learning/sessions.db`.
103
+ - **Skill curator** — `node scripts/learning/consolidate-skills.mjs` runs the LLM
104
+ umbrella consolidation on demand (no-op below `consolidation.minSkills`); it
105
+ otherwise fires as a detached worker from the `skill-curator` cadence when due.
106
+
107
+ ### Recovery & resource governance
108
+ - **Governor** — `lib/resource-governor.test.mjs` drives ADMIT/QUEUE/DEFER with
109
+ injected `os` stats; in production it gates every `dispatcher.spawnSession`.
110
+ - **Never-brick watchdog** — `bash -n scripts/watchdog/memory-watchdog.sh`; the
111
+ tiers are SOFT (`state/throttle.json`) → HARD (kill youngest) → CRITICAL (clean
112
+ restart) → graceful reboot. OOM never writes `.emergency-stop`.
113
+ - **At-most-once cron / outage** — `lib/cadence-bus-schedule.test.mjs` proves a
114
+ simulated multi-period outage yields exactly one catch-up tick.
115
+
116
+ ## 5. Full end-to-end on a scratch agent
117
+
118
+ ```bash
119
+ npx @cohortapp/agent-sdk create test-agent
120
+ cd test-agent
121
+ npm install
122
+ maestro setup --headless --answers answers.json # or run it interactively
123
+ maestro doctor # confirm green
124
+ npm install -g baileys # (optional) per channel you enable
125
+ ```
126
+
127
+ This goes from an empty directory to a configured, self-verifying agent using the
128
+ same code the suite covers.