@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,503 @@
1
+ /**
2
+ * lib/org/messaging.mjs — the maestro seam for posting / @mentioning / calling
3
+ * ON Cohort (SP10).
4
+ *
5
+ * Why this exists
6
+ * ---------------
7
+ * The org protocol froze a `messaging.*` / `calling.*` surface (protocol.mjs)
8
+ * so a fleet of agents can participate in the org's OWN human messaging app —
9
+ * post a message, @mention a teammate, react, read channel history, and join /
10
+ * start a call — exactly as they already do on Slack/Telegram/WhatsApp. This
11
+ * module is the agent-side helper layer over that surface. It is to messaging
12
+ * what cost-sync.mjs is to cost.report: a thin, fail-open wrapper over
13
+ * lib/org/client.call/read that adds the cross-cutting policy + telemetry the
14
+ * raw RPC must not skip.
15
+ *
16
+ * Three invariants this layer enforces (and the raw client.call cannot):
17
+ *
18
+ * 1. EVERY outbound message runs lib/comms/send-gate.screenOutbound BEFORE the
19
+ * messaging.send RPC. A blocked message (banned phrase / AI-disclosure /
20
+ * information barrier / off-allowlist) is NOT sent — sendMessage returns a
21
+ * blocked frame and never touches the wire. This closes the same gap the
22
+ * send-gate closes for the channel adapters: the org messaging path is just
23
+ * another real send path, so it must run the one shared chokepoint.
24
+ *
25
+ * 2. After a successful send we emit `afterSend` on the typed hook bus
26
+ * (lib/hooks/bus.getHookBus) so audit/delivery-receipt subscribers observe
27
+ * the org messaging path like every other send. afterSend is observe-only
28
+ * (never cancellable) — the cancellable gate already ran in step 1.
29
+ *
30
+ * 3. We attribute the send to the cost ledger with `source: "messaging"` so the
31
+ * org rollup can see how much messaging the agent does. A plain message send
32
+ * is a ZERO-token, zero-LLM action, so the attributed row carries 0 spend —
33
+ * it is a COUNT/attribution row, not an LLM-spend row (the G16 honesty line
34
+ * stays intact: messaging is not an LLM-in-the-loop cost).
35
+ *
36
+ * Wire shape (frozen in protocol.mjs):
37
+ * messaging.send / .react / .edit — POST /v1/messaging.* (Bearer + x-org-protocol,
38
+ * x-idempotency-key on send — idempotent on the
39
+ * client-supplied message id).
40
+ * messaging.history / .channels — POST /v1/messaging.* (read scope, non-mutating).
41
+ * calling.start / .join / .invite / .end — POST /v1/calling.* (calling.write scope).
42
+ *
43
+ * Fail-open by design: a disabled/unreachable org server yields an error frame,
44
+ * never a throw — so the messaging path can never take down the agent. The
45
+ * send-gate, hook bus, and ledger are all injectable for deterministic tests.
46
+ *
47
+ * Node builtins + the existing maestro libs only. ESM.
48
+ *
49
+ * @module lib/org/messaging
50
+ */
51
+
52
+ "use strict";
53
+
54
+ import { isEnabled, configFromAgent, call, read } from "./client.mjs";
55
+ import { errFrame } from "./protocol.mjs";
56
+ import { screenOutbound } from "../comms/send-gate.mjs";
57
+ import { getHookBus } from "../hooks/bus.mjs";
58
+
59
+ // ---------------------------------------------------------------------------
60
+ // Internal helpers
61
+ // ---------------------------------------------------------------------------
62
+
63
+ /**
64
+ * Resolve the {base, token} the RPC needs from an agent cfg, or null when the
65
+ * org integration is disabled / unconfigured (so the caller fails open).
66
+ * @param {object} cfg
67
+ * @returns {{base:string, token:string}|null}
68
+ */
69
+ function resolveOrg(cfg) {
70
+ if (!isEnabled(cfg)) return null;
71
+ const c = configFromAgent(cfg);
72
+ if (!c.base) return null;
73
+ return { base: c.base, token: c.token };
74
+ }
75
+
76
+ /** A best-effort agent id for ledger attribution (never throws). */
77
+ function agentIdOf(cfg) {
78
+ const n = (cfg && cfg.org && cfg.org.cohort) || {};
79
+ return n.agentId || n.id || (cfg && cfg.identity && cfg.identity.id) || (cfg && cfg.agentId) || null;
80
+ }
81
+
82
+ /**
83
+ * Attribute a messaging action to the cost ledger with source="messaging".
84
+ * A message send is zero-token / zero-LLM, so the attributed row carries 0
85
+ * spend — it's a COUNT row, not an LLM-spend row. Fail-open and fully optional:
86
+ * the write is best-effort (writeLedgerRow never throws) and entirely skipped
87
+ * when an injected `ledger:null` opts out (tests / read-only callers).
88
+ *
89
+ * @param {object} o - { cfg, agentRoot, action, channel }
90
+ * @param {object} deps - { ledgerImpl?, catalog? } injectable for tests
91
+ */
92
+ async function attributeMessaging(o, deps = {}) {
93
+ // Opt-out: an explicit `ledgerImpl: null` (or false) disables attribution.
94
+ if (Object.prototype.hasOwnProperty.call(deps, "ledgerImpl") && !deps.ledgerImpl) return;
95
+ try {
96
+ const writeLedgerRow =
97
+ deps.ledgerImpl || (await import("../model-router/ledger.mjs")).writeLedgerRow;
98
+ // No model is involved in a plain message send, so the catalog is empty and
99
+ // the row prices to $0 (estimated_usd:0). The attribution is the `source`.
100
+ writeLedgerRow(
101
+ deps.catalog || {},
102
+ {
103
+ agent: agentIdOf(o.cfg),
104
+ source: "messaging",
105
+ task_class: o.action || "messaging.send",
106
+ lane: o.channel || null,
107
+ inputTokens: 0,
108
+ outputTokens: 0,
109
+ exitReason: "ok",
110
+ },
111
+ { agentRoot: o.agentRoot, now: deps.now }
112
+ );
113
+ } catch {
114
+ /* fail-open: attribution must never block or break a send */
115
+ }
116
+ }
117
+
118
+ /** Emit afterSend on the hook bus (observe-only; never throws). */
119
+ async function emitAfterSend(ctx, deps = {}) {
120
+ try {
121
+ const bus = deps.hookBus || getHookBus();
122
+ await bus.emit("afterSend", ctx);
123
+ } catch {
124
+ /* fail-open: a broken subscriber must never break the send */
125
+ }
126
+ }
127
+
128
+ // ---------------------------------------------------------------------------
129
+ // Messaging — send / react / history / channels
130
+ // ---------------------------------------------------------------------------
131
+
132
+ /**
133
+ * Post a message to an org channel ON Cohort (messaging.send). THE outbound
134
+ * primitive — it runs the shared send-gate BEFORE the wire, emits afterSend on
135
+ * success, and attributes a source="messaging" ledger row.
136
+ *
137
+ * Flow:
138
+ * 1. resolve org enrollment (disabled ⇒ fail-open error frame, no send).
139
+ * 2. screenOutbound({channel, recipient:channel, text:body}) — a BLOCK returns
140
+ * a frame `{ok:false, error:{code:"FORBIDDEN_SCOPE"|"BAD_REQUEST", message}}`
141
+ * and the message is NEVER sent (no client.call).
142
+ * 3. messaging.send RPC (Bearer + x-org-protocol + x-idempotency-key from the
143
+ * client-supplied message id, so a retried send dedupes server-side).
144
+ * 4. on ok: emit afterSend + attribute the ledger row.
145
+ *
146
+ * @param {object} params
147
+ * @param {string} params.channel org channel id to post into
148
+ * @param {string} params.body the message text
149
+ * @param {string[]} [params.mentions] agent/user ids to @mention
150
+ * @param {string} [params.idempotencyId] stable client message id (idempotency key)
151
+ * @param {string} [params.threadId] reply within a thread
152
+ * @param {object} o - {
153
+ * cfg, agentRoot?, fetchImpl?,
154
+ * jurisdiction?, firstContact?, internalDomains?, allowlist?, // → send-gate
155
+ * gateImpl?, hookBus?, ledgerImpl?, catalog?, now? // → test seams
156
+ * }
157
+ * @returns {Promise<object>} res frame {ok:true,result}|{ok:false,error,blocked?}
158
+ */
159
+ export async function sendMessage(params = {}, o = {}) {
160
+ const channel = params.channel != null ? String(params.channel) : "";
161
+ const body = params.body != null ? String(params.body) : "";
162
+ if (!channel) return errFrame("BAD_REQUEST", "missing channel");
163
+ if (!body) return errFrame("BAD_REQUEST", "missing body");
164
+
165
+ // (2) The one shared outbound chokepoint — runs BEFORE the wire.
166
+ const gate = o.gateImpl || screenOutbound;
167
+ let screened;
168
+ try {
169
+ screened = await gate({
170
+ channel: "cohort",
171
+ recipient: channel,
172
+ text: body,
173
+ agentRoot: o.agentRoot || process.cwd(),
174
+ jurisdiction: o.jurisdiction,
175
+ firstContact: o.firstContact !== undefined ? o.firstContact : false,
176
+ internalDomains: o.internalDomains || [],
177
+ allowlist: o.allowlist,
178
+ });
179
+ } catch (err) {
180
+ // A gate fault is fail-CLOSED for an outbound message: never send when we
181
+ // could not screen it (mirrors the send-gate's own external posture).
182
+ return { ...errFrame("INTERNAL", `send-gate error: ${err && err.message ? err.message : String(err)}`), blocked: true };
183
+ }
184
+ if (!screened || !screened.allow) {
185
+ // A blocked message is NOT sent. Surface the policy reason; mark blocked so
186
+ // the caller can distinguish a policy refusal from a transport failure.
187
+ return { ...errFrame("FORBIDDEN_SCOPE", screened && screened.reason ? screened.reason : "blocked by send-gate"), blocked: true };
188
+ }
189
+ const text = screened.redactedText != null ? screened.redactedText : body;
190
+
191
+ // (1) org resolution AFTER the gate so a policy violation is caught even when
192
+ // the org is disabled (defence: the gate is the one chokepoint).
193
+ const org = resolveOrg(o.cfg);
194
+ if (!org) return errFrame("BAD_REQUEST", "org messaging disabled or unconfigured");
195
+
196
+ // (3) the wire — idempotent on the client message id.
197
+ const idempotencyId = params.idempotencyId != null ? String(params.idempotencyId) : "";
198
+ const wire = {
199
+ channel,
200
+ body: text,
201
+ ...(Array.isArray(params.mentions) && params.mentions.length ? { mentions: params.mentions.map(String) } : {}),
202
+ ...(params.threadId != null ? { threadId: String(params.threadId) } : {}),
203
+ ...(idempotencyId ? { id: idempotencyId } : {}),
204
+ };
205
+ const frame = await call("messaging.send", wire, {
206
+ base: org.base,
207
+ token: org.token,
208
+ idempotencyKey: idempotencyId || undefined,
209
+ fetchImpl: o.fetchImpl,
210
+ });
211
+
212
+ // (4) on success: observe-only afterSend + source="messaging" attribution.
213
+ if (frame && frame.ok) {
214
+ await emitAfterSend(
215
+ { channel: "cohort", recipient: channel, text, mentions: wire.mentions || [], result: frame.result, source: "messaging" },
216
+ o
217
+ );
218
+ await attributeMessaging({ cfg: o.cfg, agentRoot: o.agentRoot, action: "messaging.send", channel }, o);
219
+ }
220
+ return frame;
221
+ }
222
+
223
+ /**
224
+ * React to a message ON Cohort (messaging.react). A reaction is not a content
225
+ * send, so it does NOT run the banned-phrase send-gate (there is no prose to
226
+ * screen) — but it is still attributed (source="messaging") and fail-open.
227
+ * @param {object} params - { channel, messageId, emoji }
228
+ * @param {object} o - { cfg, agentRoot?, fetchImpl?, ... test seams }
229
+ * @returns {Promise<object>} res frame
230
+ */
231
+ export async function reactMessage(params = {}, o = {}) {
232
+ const channel = params.channel != null ? String(params.channel) : "";
233
+ const messageId = params.messageId != null ? String(params.messageId) : "";
234
+ const emoji = params.emoji != null ? String(params.emoji) : "";
235
+ if (!channel || !messageId || !emoji) return errFrame("BAD_REQUEST", "missing channel, messageId, or emoji");
236
+
237
+ const org = resolveOrg(o.cfg);
238
+ if (!org) return errFrame("BAD_REQUEST", "org messaging disabled or unconfigured");
239
+
240
+ const frame = await call("messaging.react", { channel, messageId, emoji }, {
241
+ base: org.base,
242
+ token: org.token,
243
+ idempotencyKey: o.idempotencyKey,
244
+ fetchImpl: o.fetchImpl,
245
+ });
246
+ if (frame && frame.ok) {
247
+ await attributeMessaging({ cfg: o.cfg, agentRoot: o.agentRoot, action: "messaging.react", channel }, o);
248
+ }
249
+ return frame;
250
+ }
251
+
252
+ /**
253
+ * Fetch recent channel history ON Cohort (messaging.history). Read-scope,
254
+ * non-mutating. Returns the messages array, or [] on any failure (fail-open).
255
+ * @param {object} params - { channel, since?, cursor?, limit? }
256
+ * @param {object} o - { cfg, fetchImpl? }
257
+ * @returns {Promise<object[]>}
258
+ */
259
+ export async function fetchHistory(params = {}, o = {}) {
260
+ const channel = params.channel != null ? String(params.channel) : "";
261
+ if (!channel) return [];
262
+ const org = resolveOrg(o.cfg);
263
+ if (!org) return [];
264
+
265
+ const frame = await call(
266
+ "messaging.history",
267
+ {
268
+ channel,
269
+ ...(params.since != null ? { since: params.since } : {}),
270
+ ...(params.cursor != null ? { cursor: params.cursor } : {}),
271
+ ...(Number.isFinite(params.limit) ? { limit: params.limit } : {}),
272
+ },
273
+ { base: org.base, token: org.token, fetchImpl: o.fetchImpl }
274
+ );
275
+ if (!frame || !frame.ok || !frame.result) return [];
276
+ const r = frame.result;
277
+ if (Array.isArray(r)) return r;
278
+ if (Array.isArray(r.messages)) return r.messages;
279
+ if (Array.isArray(r.items)) return r.items;
280
+ return [];
281
+ }
282
+
283
+ /**
284
+ * List the org channels visible to this agent (messaging.channels). Read-scope.
285
+ * Returns the channels array, or [] on any failure (fail-open).
286
+ * @param {object} o - { cfg, fetchImpl? }
287
+ * @returns {Promise<object[]>}
288
+ */
289
+ export async function listChannels(o = {}) {
290
+ const org = resolveOrg(o.cfg);
291
+ if (!org) return [];
292
+ const frame = await call("messaging.channels", {}, { base: org.base, token: org.token, fetchImpl: o.fetchImpl });
293
+ if (!frame || !frame.ok || !frame.result) return [];
294
+ const r = frame.result;
295
+ if (Array.isArray(r)) return r;
296
+ if (Array.isArray(r.channels)) return r.channels;
297
+ return [];
298
+ }
299
+
300
+ // ---------------------------------------------------------------------------
301
+ // Calling — start / join
302
+ // ---------------------------------------------------------------------------
303
+
304
+ /**
305
+ * Start a call ON Cohort (calling.start). calling.write scope. Attributed
306
+ * (source="messaging") and fail-open. There is no prose to screen, so the
307
+ * banned-phrase send-gate does not run — but an `invitees` list is passed
308
+ * through so the server can ring participants.
309
+ * @param {object} params - { channel?, invitees?, topic?, idempotencyId? }
310
+ * @param {object} o - { cfg, agentRoot?, fetchImpl?, ... test seams }
311
+ * @returns {Promise<object>} res frame {ok:true,result:{callId,...}}|{ok:false,error}
312
+ */
313
+ export async function initiateCall(params = {}, o = {}) {
314
+ const org = resolveOrg(o.cfg);
315
+ if (!org) return errFrame("BAD_REQUEST", "org calling disabled or unconfigured");
316
+ const idempotencyId = params.idempotencyId != null ? String(params.idempotencyId) : "";
317
+ const wire = {
318
+ ...(params.channel != null ? { channel: String(params.channel) } : {}),
319
+ ...(Array.isArray(params.invitees) && params.invitees.length ? { invitees: params.invitees.map(String) } : {}),
320
+ ...(params.topic != null ? { topic: String(params.topic) } : {}),
321
+ ...(idempotencyId ? { id: idempotencyId } : {}),
322
+ };
323
+ const frame = await call("calling.start", wire, {
324
+ base: org.base,
325
+ token: org.token,
326
+ idempotencyKey: idempotencyId || undefined,
327
+ fetchImpl: o.fetchImpl,
328
+ });
329
+ if (frame && frame.ok) {
330
+ await attributeMessaging({ cfg: o.cfg, agentRoot: o.agentRoot, action: "calling.start", channel: wire.channel || null }, o);
331
+ }
332
+ return frame;
333
+ }
334
+
335
+ /**
336
+ * Join an existing call ON Cohort (calling.join). calling.write scope.
337
+ * Attributed (source="messaging") and fail-open.
338
+ * @param {object} params - { callId }
339
+ * @param {object} o - { cfg, agentRoot?, fetchImpl?, ... test seams }
340
+ * @returns {Promise<object>} res frame
341
+ */
342
+ export async function joinCall(params = {}, o = {}) {
343
+ const callId = params.callId != null ? String(params.callId) : "";
344
+ if (!callId) return errFrame("BAD_REQUEST", "missing callId");
345
+ const org = resolveOrg(o.cfg);
346
+ if (!org) return errFrame("BAD_REQUEST", "org calling disabled or unconfigured");
347
+ const frame = await call("calling.join", { callId }, {
348
+ base: org.base,
349
+ token: org.token,
350
+ idempotencyKey: o.idempotencyKey,
351
+ fetchImpl: o.fetchImpl,
352
+ });
353
+ if (frame && frame.ok) {
354
+ await attributeMessaging({ cfg: o.cfg, agentRoot: o.agentRoot, action: "calling.join", channel: callId }, o);
355
+ }
356
+ return frame;
357
+ }
358
+
359
+ // ---------------------------------------------------------------------------
360
+ // Inbound — pull new messages / @mentions / call-invites for THIS agent
361
+ // ---------------------------------------------------------------------------
362
+
363
+ /**
364
+ * Pull org events newer than `cursor` that are DIRECTED AT this agent — new
365
+ * messages in a channel it is in, @mentions, and call-invites — and project them
366
+ * onto the unified MessageEvent contract so the existing daemon inbox pipeline
367
+ * (classifier → dispatcher → responder) reacts to them like any other channel.
368
+ *
369
+ * This is the read leg the inbound cadence handler drives. It is pure over the
370
+ * injected fetch: the handler decides whether to escalate and where to write the
371
+ * resulting items. The cursor advance is the caller's responsibility (returned
372
+ * here as `nextCursor`) so a crash never loses or double-delivers events.
373
+ *
374
+ * Mention detection: an event whose `mentions[]` (or `mentioned_agents[]`)
375
+ * includes this agent's id, OR a DM-kind event addressed to it, counts as
376
+ * directed. We do NOT include the agent's own outbound echoes (`from` == self).
377
+ *
378
+ * @param {object} o - { cfg, agentId?, cursor?, limit?, fetchImpl? }
379
+ * @returns {Promise<{events:object[], nextCursor:(number|string|null)}>}
380
+ */
381
+ export async function pullInbound(o = {}) {
382
+ const org = resolveOrg(o.cfg);
383
+ if (!org) return { events: [], nextCursor: o.cursor ?? null };
384
+ const me = o.agentId || agentIdOf(o.cfg);
385
+
386
+ const cursor = o.cursor ?? 0;
387
+ const limit = Number.isFinite(o.limit) ? o.limit : 200;
388
+ const path = `events?cursor=${encodeURIComponent(cursor)}&limit=${encodeURIComponent(limit)}&family=messaging,calling`;
389
+ const r = await read(path, { base: org.base, token: org.token, fetchImpl: o.fetchImpl });
390
+ if (!r.ok || !r.payload) return { events: [], nextCursor: cursor };
391
+
392
+ const raw = Array.isArray(r.payload) ? r.payload : (Array.isArray(r.payload.events) ? r.payload.events : []);
393
+ let maxSeq = cursor;
394
+ const events = [];
395
+ for (const ev of raw) {
396
+ if (ev && (ev.seq != null) && Number.isFinite(Number(ev.seq))) {
397
+ maxSeq = Math.max(Number(maxSeq) || 0, Number(ev.seq));
398
+ }
399
+ const directed = isDirectedAtAgent(ev, me);
400
+ if (!directed) continue;
401
+ events.push(toMessageEvent(ev, me));
402
+ }
403
+ return { events, nextCursor: raw.length ? maxSeq : cursor };
404
+ }
405
+
406
+ /**
407
+ * Decide whether an org event is directed at this agent (an inbound it should
408
+ * react to) vs ambient chatter / its own echo. Pure.
409
+ * @param {object} ev @param {string} me agent id
410
+ * @returns {boolean}
411
+ */
412
+ export function isDirectedAtAgent(ev, me) {
413
+ if (!ev || typeof ev !== "object") return false;
414
+ const family = ev.family || (ev.kind ? String(ev.kind).split(".")[0] : "");
415
+ if (family && family !== "messaging" && family !== "calling") return false;
416
+ const p = ev.payload || ev;
417
+ const from = String(p.from || p.author || p.sender || (ev.actor || "")).trim();
418
+ if (me && from && from === String(me)) return false; // ignore own echoes
419
+
420
+ const mentions = []
421
+ .concat(Array.isArray(p.mentions) ? p.mentions : [])
422
+ .concat(Array.isArray(p.mentioned_agents) ? p.mentioned_agents : [])
423
+ .map((m) => String(m));
424
+ if (me && mentions.includes(String(me))) return true;
425
+
426
+ // A DM / direct call-invite addressed to this agent is directed even with no
427
+ // explicit @mention.
428
+ const to = []
429
+ .concat(Array.isArray(p.to) ? p.to : (p.to != null ? [p.to] : []))
430
+ .concat(Array.isArray(p.invitees) ? p.invitees : [])
431
+ .map((t) => String(t));
432
+ if (me && to.includes(String(me))) return true;
433
+
434
+ const kind = String(p.kind || ev.kind || "").toLowerCase();
435
+ if (kind.includes("dm") || kind.includes("invite") || family === "calling") {
436
+ return !me || to.includes(String(me)) || mentions.includes(String(me)) || to.length === 0;
437
+ }
438
+ return false;
439
+ }
440
+
441
+ /**
442
+ * Project an org messaging/calling event onto the unified MessageEvent contract
443
+ * (lib/channels/contract.MessageEvent) so eventToInboxItem can serialise it into
444
+ * the legacy inbox pipeline unchanged. Pure.
445
+ * @param {object} ev @param {string} me
446
+ * @returns {object} MessageEvent
447
+ */
448
+ export function toMessageEvent(ev, me) {
449
+ const p = (ev && ev.payload) || ev || {};
450
+ const family = ev.family || (ev.kind ? String(ev.kind).split(".")[0] : "messaging");
451
+ const isCall = family === "calling";
452
+ const channelId = String(p.channel || p.channelId || p.callId || "");
453
+ const messageId = String(p.id || p.messageId || ev.entity_id || ev.seq || "");
454
+ const fromId = String(p.from || p.author || p.sender || ev.actor || "");
455
+ const text = isCall
456
+ ? (p.topic ? `Call invite: ${p.topic}` : "Call invite")
457
+ : (p.body != null ? String(p.body) : (p.text != null ? String(p.text) : ""));
458
+
459
+ return {
460
+ channel: "cohort",
461
+ message_id: messageId,
462
+ id: messageId ? `cohort-${messageId}` : undefined,
463
+ thread_id: p.threadId != null ? String(p.threadId) : "",
464
+ from: { id: fromId, name: String(p.fromName || p.authorName || fromId) },
465
+ text,
466
+ timestamp: ev.at || p.at || new Date().toISOString(),
467
+ kind: isCall ? "call" : "message",
468
+ subject: isCall ? "Cohort call invite" : "Cohort message",
469
+ channel_id: channelId,
470
+ channel_label: String(p.channelName || channelId || "cohort"),
471
+ sender: String(p.fromName || fromId),
472
+ priority_signals: {
473
+ from_ceo: false,
474
+ tagged_urgent: false,
475
+ contains_deadline: false,
476
+ mentions_agent: !!(me && []
477
+ .concat(Array.isArray(p.mentions) ? p.mentions : [])
478
+ .concat(Array.isArray(p.mentioned_agents) ? p.mentioned_agents : [])
479
+ .map(String)
480
+ .includes(String(me))),
481
+ },
482
+ raw_ref: `cohort:${channelId}:${messageId}`,
483
+ ingest_source: "cohort",
484
+ source: {
485
+ channel: "cohort",
486
+ chatId: channelId,
487
+ threadRef: p.threadId != null ? String(p.threadId) : undefined,
488
+ userScope: isCall ? "channel" : (channelId ? "channel" : "dm"),
489
+ },
490
+ };
491
+ }
492
+
493
+ export default {
494
+ sendMessage,
495
+ reactMessage,
496
+ fetchHistory,
497
+ listChannels,
498
+ initiateCall,
499
+ joinCall,
500
+ pullInbound,
501
+ isDirectedAtAgent,
502
+ toMessageEvent,
503
+ };