@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,481 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Voice Call Transcript Parser
4
+ *
5
+ * Parses voice call transcript summaries posted to Slack by the voice-ai
6
+ * post-call routing (voice-ai/lib/logger.js → postCallSummaryToSlack).
7
+ *
8
+ * Input format (Slack message text):
9
+ * *Phone call completed* — +971585291799 (243s, 38 turns)
10
+ *
11
+ * *Caller said:*
12
+ * > First thing caller said
13
+ * > Second thing caller said
14
+ * > ...
15
+ *
16
+ * _Action items from this call should be processed immediately._
17
+ *
18
+ * Output: structured object with caller identity, duration, topics,
19
+ * and extracted action items suitable for queue routing.
20
+ *
21
+ * Usage:
22
+ * import { isVoiceTranscript, parseVoiceTranscript } from './parse-voice-transcript.mjs';
23
+ *
24
+ * if (isVoiceTranscript(messageText)) {
25
+ * const parsed = parseVoiceTranscript(messageText);
26
+ * // parsed.actionItems → array of { title, context, priority, source }
27
+ * }
28
+ *
29
+ * Can also run standalone for testing:
30
+ * node scripts/parse-voice-transcript.mjs < message.txt
31
+ */
32
+
33
+ // ---------------------------------------------------------------------------
34
+ // Known callers — phone numbers to identities. Loaded from
35
+ // config/caller-id-map.yaml at runtime; falls back to an empty map. Keep
36
+ // caller-id-map.yaml in sync with voice-ai/server.js CALLER_GREETINGS.
37
+ // ---------------------------------------------------------------------------
38
+
39
+ const KNOWN_CALLERS = {}; // populated lazily from config/caller-id-map.yaml on first use
40
+
41
+ // ---------------------------------------------------------------------------
42
+ // Action item detection patterns
43
+ // ---------------------------------------------------------------------------
44
+
45
+ // Phrases that signal a request, ask, or action item
46
+ const ACTION_PATTERNS = [
47
+ // Direct requests
48
+ /\b(?:can you|could you|please|I need you to|I want you to|go ahead and|make sure|set up|look into|find out|search for|book|schedule|send|draft|prepare|create|build|update|check|review|look at|investigate|fix|handle|take care of|arrange|organize|coordinate|follow up|chase|email|call|message|write)\b/i,
49
+ // Imperative verbs — direct commands without polite framing
50
+ /\b(?:time.?box|block out|clear my|reschedule|prioriti[sz]e|research|compile|summarize|summarise|analyze|analyse|escalate|ping|nudge|chase up|circle back|loop in|pull together|put together|get me|grab|download|upload|share|forward|transfer|assign|delegate|sort out|figure out|work on|finish|complete|deliver|ship|deploy|launch|submit|file|register|sign up|enroll|enrol)\b/i,
51
+ // Questions that imply action needed
52
+ /\b(?:what(?:'s| is) the status|where are we|have you|did you|when (?:can|will)|how (?:do|can)|is there)\b/i,
53
+ // Decisions and directives
54
+ /\b(?:let's|we should|we need to|I've decided|go with|use|switch to|stop|start|change|move|cancel|approve|reject)\b/i,
55
+ // Time-sensitive signals
56
+ /\b(?:today|tomorrow|this week|by (?:end of|monday|tuesday|wednesday|thursday|friday|saturday|sunday)|asap|urgent|immediately|right now|priority)\b/i,
57
+ // Follow-up triggers
58
+ /\b(?:remind me|don't forget|make a note|keep track|follow up|circle back|loop back)\b/i,
59
+ // Also/additionally — signals a new action item being added
60
+ /\b(?:also|additionally|one more thing|and also|plus)\b/i,
61
+ ];
62
+
63
+ // Priority signal patterns
64
+ const PRIORITY_SIGNALS = {
65
+ critical:
66
+ /\b(?:urgent|emergency|asap|critical|immediately|right now|drop everything)\b/i,
67
+ high: /\b(?:today|priority|important|need this|by end of day|eod)\b/i,
68
+ medium: /\b(?:this week|soon|when you can|follow up)\b/i,
69
+ };
70
+
71
+ // Topic classification patterns
72
+ const TOPIC_PATTERNS = {
73
+ travel:
74
+ /\b(?:flight|flights|travel|book|booking|trip|australia|sydney|brisbane|airport|airline|hotel)\b/i,
75
+ calendar:
76
+ /\b(?:calendar|schedule|time.?box|block|meeting|appointment|slot|availability)\b/i,
77
+ hiring:
78
+ /\b(?:hiring|candidate|interview|role|position|recruit|applicant|offer|resume|cv)\b/i,
79
+ legal:
80
+ /\b(?:legal|contract|agreement|nda|compliance|regulatory|dfsa|licence|filing)\b/i,
81
+ engineering:
82
+ /\b(?:engineering|code|deploy|build|bug|fix|feature|platform|api|infrastructure)\b/i,
83
+ finance:
84
+ /\b(?:finance|budget|cost|expense|invoice|payment|funding|capital|runway)\b/i,
85
+ communication:
86
+ /\b(?:email|slack|message|send|reply|respond|follow.?up|chase)\b/i,
87
+ strategy:
88
+ /\b(?:strategy|roadmap|plan|initiative|priority|milestone|target|goal|objective)\b/i,
89
+ voice_ai: /\b(?:voice|phone|call|twilio|speech|conversation)\b/i,
90
+ };
91
+
92
+ // ---------------------------------------------------------------------------
93
+ // Detection
94
+ // ---------------------------------------------------------------------------
95
+
96
+ /**
97
+ * Check if a Slack message text is a voice call transcript summary.
98
+ * Uses the exact format produced by voice-ai/lib/logger.js postCallSummaryToSlack.
99
+ *
100
+ * @param {string} text - Slack message text
101
+ * @returns {boolean}
102
+ */
103
+ export function isVoiceTranscript(text) {
104
+ if (!text || typeof text !== "string") return false;
105
+ // Must contain the post-call header AND caller-said block
106
+ return text.includes("Phone call completed") && text.includes("Caller said:");
107
+ }
108
+
109
+ // ---------------------------------------------------------------------------
110
+ // Parsing
111
+ // ---------------------------------------------------------------------------
112
+
113
+ /**
114
+ * Parse a voice call transcript summary from Slack into structured data.
115
+ *
116
+ * @param {string} text - Slack message text containing the transcript
117
+ * @param {object} [meta] - Optional metadata from the Slack message
118
+ * @param {string} [meta.ts] - Slack message timestamp
119
+ * @param {string} [meta.channel] - Slack channel ID
120
+ * @returns {object} Parsed transcript with caller info, duration, topics, action items
121
+ */
122
+ export function parseVoiceTranscript(text, meta = {}) {
123
+ const result = {
124
+ type: "voice_call_transcript",
125
+ caller: null,
126
+ callerPhone: null,
127
+ callerIdentity: null,
128
+ duration: null,
129
+ durationSeconds: null,
130
+ turns: null,
131
+ callerStatements: [],
132
+ topics: [],
133
+ actionItems: [],
134
+ rawText: text,
135
+ slackTs: meta.ts || null,
136
+ slackChannel: meta.channel || null,
137
+ };
138
+
139
+ // --- Parse header line ---
140
+ // Format: *Phone call completed* — +971585291799 (243s, 38 turns)
141
+ const headerMatch = text.match(
142
+ /Phone call completed\*?\s*[-—]\s*(\+?[\d]+)\s*\((\d+)s,\s*(\d+)\s*turns?\)/,
143
+ );
144
+ if (headerMatch) {
145
+ result.callerPhone = headerMatch[1];
146
+ result.durationSeconds = parseInt(headerMatch[2], 10);
147
+ result.duration = formatDuration(result.durationSeconds);
148
+ result.turns = parseInt(headerMatch[3], 10);
149
+
150
+ // Resolve caller identity from phone number
151
+ const known = KNOWN_CALLERS[result.callerPhone];
152
+ if (known) {
153
+ result.caller = known.name;
154
+ result.callerIdentity = known;
155
+ } else {
156
+ result.caller = result.callerPhone;
157
+ result.callerIdentity = {
158
+ name: result.callerPhone,
159
+ role: "unknown",
160
+ privilege: "unknown",
161
+ };
162
+ }
163
+ }
164
+
165
+ // --- Extract caller statements ---
166
+ // Format: lines starting with > after "Caller said:"
167
+ const callerSaidMatch = text.match(
168
+ /Caller said:\*?\s*\n([\s\S]*?)(?:\n\n|_Action items|$)/,
169
+ );
170
+ if (callerSaidMatch) {
171
+ const callerBlock = callerSaidMatch[1];
172
+ result.callerStatements = callerBlock
173
+ .split("\n")
174
+ .map((line) => line.replace(/^>\s*/, "").trim())
175
+ .filter((line) => line.length > 0);
176
+ }
177
+
178
+ // --- Classify topics ---
179
+ const allCallerText = result.callerStatements.join(" ");
180
+ for (const [topic, pattern] of Object.entries(TOPIC_PATTERNS)) {
181
+ if (pattern.test(allCallerText)) {
182
+ result.topics.push(topic);
183
+ }
184
+ }
185
+
186
+ // --- Extract action items ---
187
+ result.actionItems = extractActionItems(result);
188
+
189
+ return result;
190
+ }
191
+
192
+ // ---------------------------------------------------------------------------
193
+ // Action Item Extraction
194
+ // ---------------------------------------------------------------------------
195
+
196
+ /**
197
+ * Extract action items from parsed caller statements.
198
+ * Groups related consecutive statements and identifies actionable requests.
199
+ *
200
+ * @param {object} parsed - Parsed transcript result
201
+ * @returns {Array<object>} Action items
202
+ */
203
+ function extractActionItems(parsed) {
204
+ const items = [];
205
+ const statements = parsed.callerStatements;
206
+
207
+ if (!statements || statements.length === 0) return items;
208
+
209
+ // Group consecutive statements into logical segments.
210
+ // A segment break occurs when there's a topic shift or a clear pause indicator.
211
+ const segments = segmentStatements(statements);
212
+
213
+ for (const segment of segments) {
214
+ const segmentText = segment.join(" ");
215
+
216
+ // Check if this segment contains action-worthy content
217
+ const isActionable = ACTION_PATTERNS.some((p) => p.test(segmentText));
218
+ if (!isActionable) continue;
219
+
220
+ // Determine priority
221
+ let priority = "medium";
222
+ if (PRIORITY_SIGNALS.critical.test(segmentText)) priority = "critical";
223
+ else if (PRIORITY_SIGNALS.high.test(segmentText)) priority = "high";
224
+
225
+ // Determine topic
226
+ const topics = [];
227
+ for (const [topic, pattern] of Object.entries(TOPIC_PATTERNS)) {
228
+ if (pattern.test(segmentText)) topics.push(topic);
229
+ }
230
+
231
+ // Build a concise title from the segment
232
+ const title = buildActionTitle(segmentText, topics);
233
+
234
+ // Check if caller is CEO for priority boost
235
+ if (parsed.callerIdentity?.privilege === "ceo" && priority === "medium") {
236
+ priority = "high";
237
+ }
238
+
239
+ items.push({
240
+ title,
241
+ context: segmentText,
242
+ priority,
243
+ topics,
244
+ source: "voice-call",
245
+ source_ref: parsed.slackTs
246
+ ? `slack:${parsed.slackChannel || "unknown"}:${parsed.slackTs}`
247
+ : "voice-call",
248
+ caller: parsed.caller,
249
+ caller_privilege: parsed.callerIdentity?.privilege || "unknown",
250
+ });
251
+ }
252
+
253
+ return items;
254
+ }
255
+
256
+ /**
257
+ * Segment caller statements into logical groups.
258
+ * Statements about the same topic are grouped together.
259
+ */
260
+ function segmentStatements(statements) {
261
+ if (statements.length === 0) return [];
262
+
263
+ const segments = [];
264
+ let current = [statements[0]];
265
+
266
+ for (let i = 1; i < statements.length; i++) {
267
+ const prev = statements[i - 1];
268
+ const curr = statements[i];
269
+
270
+ // Detect topic shift: if current statement matches different topic patterns
271
+ // than previous, or if there's a transitional phrase
272
+ const isTopicShift =
273
+ /\b(?:also|another thing|by the way|oh and|next|separately|on a different|switching to)\b/i.test(
274
+ curr,
275
+ ) || hasTopicShift(prev, curr);
276
+
277
+ if (isTopicShift) {
278
+ segments.push(current);
279
+ current = [curr];
280
+ } else {
281
+ current.push(curr);
282
+ }
283
+ }
284
+
285
+ if (current.length > 0) {
286
+ segments.push(current);
287
+ }
288
+
289
+ return segments;
290
+ }
291
+
292
+ /**
293
+ * Detect if two consecutive statements are about different topics.
294
+ */
295
+ function hasTopicShift(prev, curr) {
296
+ const prevTopics = new Set();
297
+ const currTopics = new Set();
298
+
299
+ for (const [topic, pattern] of Object.entries(TOPIC_PATTERNS)) {
300
+ if (pattern.test(prev)) prevTopics.add(topic);
301
+ if (pattern.test(curr)) currTopics.add(topic);
302
+ }
303
+
304
+ // If both have topics and they don't overlap, it's a shift
305
+ if (prevTopics.size > 0 && currTopics.size > 0) {
306
+ const overlap = [...prevTopics].some((t) => currTopics.has(t));
307
+ return !overlap;
308
+ }
309
+
310
+ return false;
311
+ }
312
+
313
+ /**
314
+ * Build a concise action item title from segment text.
315
+ */
316
+ function buildActionTitle(text, topics) {
317
+ // Truncate to a reasonable title length
318
+ const maxLen = 100;
319
+
320
+ // Try to extract the core request
321
+ const requestMatch = text.match(
322
+ /(?:can you|could you|please|I need you to|I want you to)\s+(.{10,80}?)(?:\.|,|$)/i,
323
+ );
324
+ if (requestMatch) {
325
+ return `CEO voice request: ${capitalize(requestMatch[1].trim())}`;
326
+ }
327
+
328
+ // Try to use the topic and first actionable phrase
329
+ const topicLabel = topics.length > 0 ? topics[0] : "general";
330
+ const shortened =
331
+ text.length > maxLen ? text.substring(0, maxLen) + "..." : text;
332
+
333
+ return `CEO voice directive (${topicLabel}): ${shortened}`;
334
+ }
335
+
336
+ // ---------------------------------------------------------------------------
337
+ // Inbox Item Generation
338
+ // ---------------------------------------------------------------------------
339
+
340
+ /**
341
+ * Convert parsed voice transcript into inbox queue items compatible
342
+ * with the poller's writeInboxItem format.
343
+ *
344
+ * @param {object} parsed - Output from parseVoiceTranscript
345
+ * @returns {Array<object>} Inbox items ready for writeInboxItem
346
+ */
347
+ export function toInboxItems(parsed) {
348
+ if (!parsed.actionItems || parsed.actionItems.length === 0) {
349
+ // Even if no specific action items detected, create one catch-all item
350
+ // for voice calls from the CEO so nothing is missed
351
+ if (parsed.callerIdentity?.privilege === "ceo") {
352
+ return [
353
+ {
354
+ id: `voice-${parsed.slackTs || Date.now()}`.replace(/\./g, "-"),
355
+ service: "slack",
356
+ channel: `dm/${parsed.caller || "unknown"}`,
357
+ sender: parsed.caller || "unknown",
358
+ sender_privilege: parsed.callerIdentity?.privilege || "unknown",
359
+ timestamp: new Date().toISOString(),
360
+ subject: `Voice call from ${parsed.caller || "unknown caller"} (${parsed.duration || "unknown"})`,
361
+ content: parsed.rawText,
362
+ thread_id: "",
363
+ is_reply: false,
364
+ is_voice_transcript: true,
365
+ voice_meta: {
366
+ caller_phone: parsed.callerPhone,
367
+ duration_seconds: parsed.durationSeconds,
368
+ turns: parsed.turns,
369
+ topics: parsed.topics,
370
+ caller_statements_count: parsed.callerStatements.length,
371
+ },
372
+ priority_signals: {
373
+ from_ceo: true,
374
+ tagged_urgent: false,
375
+ contains_deadline: false,
376
+ mentions_agent: true,
377
+ },
378
+ raw_ref: parsed.slackTs
379
+ ? `slack:${parsed.slackChannel || "unknown"}:${parsed.slackTs}`
380
+ : "",
381
+ },
382
+ ];
383
+ }
384
+ return [];
385
+ }
386
+
387
+ return parsed.actionItems.map((action, idx) => ({
388
+ id: `voice-${parsed.slackTs || Date.now()}-${idx}`.replace(/\./g, "-"),
389
+ service: "slack",
390
+ channel: `dm/${parsed.caller || "unknown"}`,
391
+ sender: parsed.caller || "unknown",
392
+ sender_privilege: action.caller_privilege || "unknown",
393
+ timestamp: new Date().toISOString(),
394
+ subject: action.title,
395
+ content: `[Voice Call Action Item]\n\nCaller: ${parsed.caller || "unknown"} (${parsed.callerPhone || "unknown"})\nDuration: ${parsed.duration || "unknown"}\nTopics: ${action.topics.join(", ") || "general"}\n\nCaller statement:\n${action.context}\n\nFull transcript summary:\n${parsed.rawText}`,
396
+ thread_id: "",
397
+ is_reply: false,
398
+ is_voice_transcript: true,
399
+ voice_meta: {
400
+ caller_phone: parsed.callerPhone,
401
+ duration_seconds: parsed.durationSeconds,
402
+ turns: parsed.turns,
403
+ topics: action.topics,
404
+ action_priority: action.priority,
405
+ },
406
+ priority_signals: {
407
+ from_ceo: action.caller_privilege === "ceo",
408
+ tagged_urgent: action.priority === "critical",
409
+ contains_deadline: PRIORITY_SIGNALS.high.test(action.context),
410
+ mentions_agent: true,
411
+ },
412
+ raw_ref: action.source_ref || "",
413
+ }));
414
+ }
415
+
416
+ // ---------------------------------------------------------------------------
417
+ // Helpers
418
+ // ---------------------------------------------------------------------------
419
+
420
+ function formatDuration(seconds) {
421
+ if (!seconds || seconds < 0) return "unknown";
422
+ const min = Math.floor(seconds / 60);
423
+ const sec = seconds % 60;
424
+ if (min === 0) return `${sec}s`;
425
+ return `${min}m ${sec}s`;
426
+ }
427
+
428
+ function capitalize(str) {
429
+ if (!str) return "";
430
+ return str.charAt(0).toUpperCase() + str.slice(1);
431
+ }
432
+
433
+ // ---------------------------------------------------------------------------
434
+ // CLI mode — for testing
435
+ // ---------------------------------------------------------------------------
436
+
437
+ if (process.argv[1] && process.argv[1].includes("parse-voice-transcript")) {
438
+ // Read from stdin or from file argument
439
+ const input = process.argv[2];
440
+
441
+ if (input) {
442
+ // File argument
443
+ const { readFileSync } = await import("fs");
444
+ const text = readFileSync(input, "utf-8");
445
+ processInput(text);
446
+ } else {
447
+ // Stdin
448
+ let text = "";
449
+ process.stdin.setEncoding("utf-8");
450
+ process.stdin.on("data", (chunk) => (text += chunk));
451
+ process.stdin.on("end", () => processInput(text));
452
+
453
+ // If no input after 100ms, show usage
454
+ setTimeout(() => {
455
+ if (!text) {
456
+ console.log("Usage: node parse-voice-transcript.mjs [file]");
457
+ console.log(
458
+ " echo 'message text' | node parse-voice-transcript.mjs",
459
+ );
460
+ console.log("");
461
+ console.log("Parses voice call transcript summaries posted to Slack.");
462
+ process.exit(0);
463
+ }
464
+ }, 100);
465
+ }
466
+ }
467
+
468
+ function processInput(text) {
469
+ if (!isVoiceTranscript(text)) {
470
+ console.log("Not a voice call transcript.");
471
+ process.exit(1);
472
+ }
473
+
474
+ const parsed = parseVoiceTranscript(text, { ts: "test", channel: "test" });
475
+ console.log("\n=== Parsed Voice Transcript ===");
476
+ console.log(JSON.stringify(parsed, null, 2));
477
+
478
+ const inboxItems = toInboxItems(parsed);
479
+ console.log("\n=== Generated Inbox Items ===");
480
+ console.log(JSON.stringify(inboxItems, null, 2));
481
+ }
@@ -0,0 +1,63 @@
1
+ # PDF Generation Pipeline
2
+
3
+ > **Full setup guide**: See [docs/guides/pdf-generation-setup.md](../../docs/guides/pdf-generation-setup.md) for complete installation, template customisation, brand integration, testing, and troubleshooting.
4
+
5
+ Generates professional PDF documents from Markdown using Pandoc + XeLaTeX.
6
+ Ported from the `~/innovation-lab` book generation pipeline, adapted for corporate documents.
7
+
8
+ ## Prerequisites
9
+
10
+ ```bash
11
+ # Install Pandoc
12
+ brew install pandoc
13
+
14
+ # Install MacTeX (for XeLaTeX)
15
+ brew install --cask mactex-no-gui
16
+
17
+ # Install Node.js dependencies
18
+ cd ~/<agent-name> && npm install
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ ```bash
24
+ # Generate a single document
25
+ node scripts/pdf-generation/build-document.mjs --input outputs/briefs/daily/2026-04-02/morning-brief.md --template corporate-letter
26
+
27
+ # Generate a board pack
28
+ node scripts/pdf-generation/build-document.mjs --input outputs/board/2026-Q2-board-pack.md --template board-pack
29
+
30
+ # Generate an investor letter
31
+ node scripts/pdf-generation/build-document.mjs --input outputs/memos/investor-update-2026-Q1.md --template investor-letter
32
+
33
+ # Available templates
34
+ # corporate-letter — Standard A4/Letter corporate document
35
+ # board-pack — Board materials with cover page and TOC
36
+ # investor-letter — Investor communications on branded letterhead
37
+ # memo — Internal memos and briefs
38
+ ```
39
+
40
+ ## Templates
41
+
42
+ LaTeX templates live in `scripts/pdf-generation/templates/`:
43
+
44
+ | Template | Page Size | Margins | Use Case |
45
+ | ------------------------ | -------------- | ------- | ---------------------------------------------------- |
46
+ | `corporate-letter.latex` | A4 (210x297mm) | 25mm | Standard correspondence, regulatory submissions |
47
+ | `board-pack.latex` | A4 | 20mm | Board packs with TOC, branded cover, section headers |
48
+ | `investor-letter.latex` | A4 | 30mm | Investor letters, LP updates |
49
+ | `memo.latex` | A4 | 20mm | Internal briefs, memos, decision documents |
50
+
51
+ ## How It Works
52
+
53
+ 1. Markdown content is authored (by agents or manually)
54
+ 2. `build-document.mjs` reads the Markdown and selects the appropriate LaTeX template
55
+ 3. Pandoc converts Markdown → PDF via XeLaTeX with brand fonts and logo placement
56
+ 4. Output PDF is saved alongside the source Markdown or to a specified output path
57
+
58
+ ## Brand Integration
59
+
60
+ - Templates reference brand assets from `public/assets/` for logos and icons
61
+ - Typography uses Georgia (main) and Helvetica Neue (sans) per brand guidelines
62
+ - Colour values sourced from `config/brand-assets.yaml`
63
+ - See `config/brand-assets.yaml → typography.pdf` for font configuration