@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,292 @@
1
+ #!/bin/bash
2
+ # send-whatsapp.sh — Send outbound WhatsApp message via Twilio REST API as the agent
3
+ #
4
+ # Supports two modes:
5
+ # 1. Sandbox mode (default until production WABA is active):
6
+ # Uses Twilio sandbox number +14155238886
7
+ # Recipients must have joined the sandbox first
8
+ # 2. Production mode (--production flag or WHATSAPP_MODE=production):
9
+ # Uses the agent's own Twilio number as WhatsApp Business sender
10
+ #
11
+ # Usage:
12
+ # ./scripts/send-whatsapp.sh --to "+971501234567" --body "Hello"
13
+ # ./scripts/send-whatsapp.sh --to "+971501234567" --body "Hello" --production
14
+ # ./scripts/send-whatsapp.sh --to "+971501234567" --template "intro_greeting" --vars "Var1,Var2"
15
+ #
16
+ # Environment variables (from .env):
17
+ # TWILIO_ACCOUNT_SID — Twilio account SID
18
+ # TWILIO_AUTH_TOKEN — Twilio auth token
19
+ # TWILIO_PHONE_NUMBER — The agent's Twilio phone number
20
+ # WHATSAPP_MODE — "sandbox" (default) or "production"
21
+ # WHATSAPP_SANDBOX_NUMBER — Sandbox sender (default: +14155238886)
22
+ set -e
23
+
24
+ # Load environment
25
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
26
+ AGENT_REPO_DIR="${AGENT_DIR:-$(dirname "$SCRIPT_DIR")}"
27
+
28
+ if [ -f "$AGENT_REPO_DIR/.env" ]; then
29
+ source "$AGENT_REPO_DIR/.env"
30
+ fi
31
+
32
+ # Defaults
33
+ MODE="${WHATSAPP_MODE:-sandbox}"
34
+ SANDBOX_NUMBER="${WHATSAPP_SANDBOX_NUMBER:-+14155238886}"
35
+ PRODUCTION_NUMBER="${TWILIO_PHONE_NUMBER:-+16282656712}"
36
+ TO=""
37
+ BODY=""
38
+ TEMPLATE=""
39
+ TEMPLATE_VARS=""
40
+ MEDIA_URL=""
41
+
42
+ # Parse arguments
43
+ while [[ $# -gt 0 ]]; do
44
+ case "$1" in
45
+ --to)
46
+ TO="$2"
47
+ shift 2
48
+ ;;
49
+ --body)
50
+ BODY="$2"
51
+ shift 2
52
+ ;;
53
+ --template)
54
+ TEMPLATE="$2"
55
+ shift 2
56
+ ;;
57
+ --vars)
58
+ TEMPLATE_VARS="$2"
59
+ shift 2
60
+ ;;
61
+ --media)
62
+ MEDIA_URL="$2"
63
+ shift 2
64
+ ;;
65
+ --production)
66
+ MODE="production"
67
+ shift
68
+ ;;
69
+ --sandbox)
70
+ MODE="sandbox"
71
+ shift
72
+ ;;
73
+ -h|--help)
74
+ echo "Usage: send-whatsapp.sh --to \"+971501234567\" --body \"message text\""
75
+ echo ""
76
+ echo "Options:"
77
+ echo " --to Recipient phone number (E.164 format, required)"
78
+ echo " --body Message text (required unless --template is used)"
79
+ echo " --template WhatsApp message template name (for business-initiated messages)"
80
+ echo " --vars Comma-separated template variables (e.g. \"Name,Company\")"
81
+ echo " --media URL of media to attach (image, PDF, etc.)"
82
+ echo " --production Use production WhatsApp Business number"
83
+ echo " --sandbox Use Twilio WhatsApp sandbox (default)"
84
+ echo " -h Show this help"
85
+ echo ""
86
+ echo "Sandbox mode: Recipients must first join the sandbox by sending"
87
+ echo " 'join <sandbox-keyword>' to +1 415 523 8886 on WhatsApp."
88
+ echo ""
89
+ echo "Production mode: Requires approved WhatsApp Business Account."
90
+ echo " Business-initiated messages need approved templates."
91
+ echo " User-initiated (within 24h window): free-form messages allowed."
92
+ exit 0
93
+ ;;
94
+ *)
95
+ echo "ERROR: Unknown argument: $1" >&2
96
+ exit 1
97
+ ;;
98
+ esac
99
+ done
100
+
101
+ # Validate required arguments
102
+ if [ -z "$TO" ]; then
103
+ echo "ERROR: --to is required" >&2
104
+ exit 1
105
+ fi
106
+
107
+ if [ -z "$BODY" ] && [ -z "$TEMPLATE" ]; then
108
+ echo "ERROR: --body or --template is required" >&2
109
+ exit 1
110
+ fi
111
+
112
+ # Validate Twilio credentials
113
+ if [ -z "$TWILIO_ACCOUNT_SID" ]; then
114
+ echo "ERROR: TWILIO_ACCOUNT_SID not set" >&2
115
+ exit 1
116
+ fi
117
+
118
+ if [ -z "$TWILIO_AUTH_TOKEN" ]; then
119
+ echo "ERROR: TWILIO_AUTH_TOKEN not set" >&2
120
+ exit 1
121
+ fi
122
+
123
+ # Determine sender number based on mode
124
+ if [ "$MODE" = "production" ]; then
125
+ FROM_NUMBER="$PRODUCTION_NUMBER"
126
+ else
127
+ FROM_NUMBER="$SANDBOX_NUMBER"
128
+ fi
129
+
130
+ # --- Outbound dedup: prevent concurrent sessions from sending the same WhatsApp ---
131
+ DEDUP_ACQUIRED=""
132
+ if [ -x "$SCRIPT_DIR/outbound-dedup.sh" ]; then
133
+ DEDUP_KEY=$("$SCRIPT_DIR/outbound-dedup.sh" generate-key whatsapp "$TO" "" "${BODY:-$TEMPLATE}" 2>/dev/null) || true
134
+ if [ -n "$DEDUP_KEY" ]; then
135
+ ACQUIRE_RESULT=$("$SCRIPT_DIR/outbound-dedup.sh" acquire whatsapp "$DEDUP_KEY" "${SOPHIE_SESSION_ID:-$$}" 2>/dev/null) || true
136
+ if [ "$ACQUIRE_RESULT" = "DEDUP_SKIP" ]; then
137
+ echo "DEDUP_SKIP: Another session is already sending this WhatsApp message"
138
+ exit 0
139
+ fi
140
+ if [ "$ACQUIRE_RESULT" = "CLAIMED" ]; then
141
+ DEDUP_ACQUIRED="1"
142
+ fi
143
+ fi
144
+ fi
145
+
146
+ # ── Pre-send factual validation ─────────────────────────────────
147
+ # Checks relationship claims, AI disclosure, in-person scheduling, title accuracy
148
+ # Blocks send if critical issues found. Fail-open on errors.
149
+ if [ ! -f "$SCRIPT_DIR/validate_outbound.py" ]; then
150
+ echo "BLOCKED: outbound validator (validate_outbound.py) missing — refusing WhatsApp send (fail closed)." >&2
151
+ exit 1
152
+ fi
153
+ if [ -n "$BODY" ]; then
154
+ VALIDATION_RESULT=$(echo "$BODY" | python3 "$SCRIPT_DIR/validate_outbound.py" --type whatsapp --recipient "$TO" --quiet 2>/dev/null) || VALIDATION_EXIT=$?
155
+ VALIDATION_EXIT=${VALIDATION_EXIT:-0}
156
+ if [ "$VALIDATION_EXIT" = "1" ]; then
157
+ BLOCKERS=$(echo "$VALIDATION_RESULT" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('metadata',{}).get('blockers',0))" 2>/dev/null) || BLOCKERS=0
158
+ if [ "$BLOCKERS" -gt 0 ]; then
159
+ echo "VALIDATION_BLOCK: $BLOCKERS issue(s) found in WhatsApp message to $TO"
160
+ echo "$VALIDATION_RESULT" | python3 -c "
161
+ import json,sys
162
+ d=json.load(sys.stdin)
163
+ for i in d.get('issues',[]):
164
+ if i.get('severity')=='block':
165
+ print(f\" [{i['type']}] {i['description']}\")
166
+ if i.get('suggestion'): print(f\" -> {i['suggestion']}\")
167
+ " 2>/dev/null || true
168
+ echo "Fix the above issues before sending." >&2
169
+ exit 1
170
+ fi
171
+ fi
172
+ fi
173
+
174
+ # ── Pre-send policy gate (shared send-gate chokepoint) ──────────────
175
+ # Unified policy layer ABOVE validate_outbound.py (Layer 0): banned phrases,
176
+ # AI-disclosure, information barriers, recipient allowlist — all in
177
+ # lib/comms/send-gate.mjs. WhatsApp recipients are phone numbers (external), so
178
+ # an unreadable policy fails CLOSED here.
179
+ if [ -n "$BODY" ]; then
180
+ SEND_GATE="$AGENT_REPO_DIR/lib/comms/send-gate.mjs"
181
+ if [ ! -f "$SEND_GATE" ]; then
182
+ SEND_GATE="$AGENT_REPO_DIR/node_modules/@cohortapp/agent-sdk/lib/comms/send-gate.mjs"
183
+ fi
184
+ if [ -f "$SEND_GATE" ]; then
185
+ NODE_BIN="${MAESTRO_NODE_BIN:-/opt/homebrew/bin/node}"
186
+ command -v "$NODE_BIN" >/dev/null 2>&1 || NODE_BIN="node"
187
+ # Replies by default; MAESTRO_SEND_FIRST_CONTACT=true for first contact. The
188
+ # truthfulness invariant (never deny being an AI) applies regardless.
189
+ GATE_REASON=$(printf '%s' "$BODY" | AGENT_DIR="$AGENT_REPO_DIR" "$NODE_BIN" "$SEND_GATE" \
190
+ --channel whatsapp --recipient "$TO" --agent-root "$AGENT_REPO_DIR" \
191
+ --first-contact "${MAESTRO_SEND_FIRST_CONTACT:-false}" 2>&1) || GATE_EXIT=$?
192
+ GATE_EXIT=${GATE_EXIT:-0}
193
+ if [ "$GATE_EXIT" != "0" ]; then
194
+ echo "SEND_GATE_BLOCK: WhatsApp message to $TO blocked by policy gate" >&2
195
+ echo "$GATE_REASON" >&2
196
+ exit 1
197
+ fi
198
+ fi
199
+ fi
200
+
201
+ # Build the Twilio API request
202
+ # WhatsApp messages use the same Messages API but with "whatsapp:" prefix on numbers
203
+ WHATSAPP_TO="whatsapp:${TO}"
204
+ WHATSAPP_FROM="whatsapp:${FROM_NUMBER}"
205
+
206
+ # Build curl arguments
207
+ CURL_ARGS=(
208
+ -s -w "\n%{http_code}"
209
+ -X POST "https://api.twilio.com/2010-04-01/Accounts/${TWILIO_ACCOUNT_SID}/Messages.json"
210
+ -u "${TWILIO_ACCOUNT_SID}:${TWILIO_AUTH_TOKEN}"
211
+ --data-urlencode "To=${WHATSAPP_TO}"
212
+ --data-urlencode "From=${WHATSAPP_FROM}"
213
+ )
214
+
215
+ if [ -n "$BODY" ]; then
216
+ CURL_ARGS+=(--data-urlencode "Body=${BODY}")
217
+ fi
218
+
219
+ if [ -n "$MEDIA_URL" ]; then
220
+ CURL_ARGS+=(--data-urlencode "MediaUrl=${MEDIA_URL}")
221
+ fi
222
+
223
+ # For template messages in production mode, use ContentSid if available
224
+ # Otherwise templates are sent as Body with template syntax
225
+ # (Twilio Content API for templates is separate; for now we use Body-based approach)
226
+
227
+ # Send WhatsApp message via Twilio REST API
228
+ RESPONSE=$(curl "${CURL_ARGS[@]}")
229
+
230
+ # Split response body and HTTP status code
231
+ HTTP_CODE=$(echo "$RESPONSE" | tail -1)
232
+ RESPONSE_BODY=$(echo "$RESPONSE" | sed '$d')
233
+
234
+ # Extract message SID and status from response
235
+ MESSAGE_SID=$(echo "$RESPONSE_BODY" | grep -o '"sid": *"[^"]*"' | head -1 | sed 's/"sid": *"//' | sed 's/"//')
236
+ STATUS=$(echo "$RESPONSE_BODY" | grep -o '"status": *"[^"]*"' | head -1 | sed 's/"status": *"//' | sed 's/"//')
237
+ ERROR_CODE=$(echo "$RESPONSE_BODY" | grep -o '"code": *[0-9]*' | head -1 | sed 's/"code": *//')
238
+ ERROR_MSG=$(echo "$RESPONSE_BODY" | grep -o '"message": *"[^"]*"' | head -1 | sed 's/"message": *"//' | sed 's/"//')
239
+
240
+ # Log to WhatsApp log
241
+ LOG_DIR="$AGENT_REPO_DIR/logs/whatsapp/$(date +%Y-%m-%d)"
242
+ mkdir -p "$LOG_DIR"
243
+ LOG_FILE="$LOG_DIR/$(date +%Y-%m-%d)-whatsapp.jsonl"
244
+
245
+ BODY_PREVIEW=$(echo "${BODY:-template:$TEMPLATE}" | head -c 200 | sed 's/"/\\"/g' | tr '\n' ' ')
246
+
247
+ LOG_ENTRY=$(cat <<LOGEOF
248
+ {"timestamp":"$(date -u +%Y-%m-%dT%H:%M:%S.000Z)","direction":"outbound","messageSid":"${MESSAGE_SID}","from":"${FROM_NUMBER}","to":"${TO}","body":"${BODY_PREVIEW}","mode":"${MODE}","http_code":"${HTTP_CODE}","status":"${STATUS}","logged_at":"$(date -u +%Y-%m-%dT%H:%M:%S.000Z)"}
249
+ LOGEOF
250
+ )
251
+ echo "$LOG_ENTRY" >> "$LOG_FILE"
252
+
253
+ # Log to audit trail
254
+ AUDIT_DIR="$AGENT_REPO_DIR/logs/audit"
255
+ mkdir -p "$AUDIT_DIR"
256
+ AUDIT_FILE="$AUDIT_DIR/$(date +%Y-%m-%d)-actions.jsonl"
257
+
258
+ AUDIT_ENTRY=$(cat <<AUDITEOF
259
+ {"timestamp":"$(date -u +%Y-%m-%dT%H:%M:%S.000Z)","agent":"send-whatsapp","action":"whatsapp_sent","to":"${TO}","from":"${FROM_NUMBER}","mode":"${MODE}","body_preview":"$(echo "${BODY:-template:$TEMPLATE}" | head -c 100 | sed 's/"/\\"/g' | tr '\n' ' ')","messageSid":"${MESSAGE_SID}","http_code":"${HTTP_CODE}","status":"${STATUS}"}
260
+ AUDITEOF
261
+ )
262
+ echo "$AUDIT_ENTRY" >> "$AUDIT_FILE"
263
+
264
+ # Output result
265
+ if [ "$HTTP_CODE" = "201" ] || [ "$HTTP_CODE" = "200" ]; then
266
+ # Post-send: confirm the dedup lock
267
+ if [ -n "$DEDUP_ACQUIRED" ] && [ -n "$DEDUP_KEY" ] && [ -x "$SCRIPT_DIR/outbound-dedup.sh" ]; then
268
+ PREVIEW=$(printf '%s' "${BODY:-template:$TEMPLATE}" | head -c 200)
269
+ "$SCRIPT_DIR/outbound-dedup.sh" confirm whatsapp "$DEDUP_KEY" "To:$TO SID:$MESSAGE_SID $PREVIEW" 2>/dev/null || true
270
+ fi
271
+ echo "WhatsApp message sent successfully (${MODE} mode)"
272
+ echo " To: $TO"
273
+ echo " From: $FROM_NUMBER (whatsapp:${FROM_NUMBER})"
274
+ echo " SID: $MESSAGE_SID"
275
+ echo " Status: $STATUS"
276
+ echo " Mode: $MODE"
277
+ exit 0
278
+ else
279
+ echo "ERROR: WhatsApp send failed (HTTP $HTTP_CODE)" >&2
280
+ if [ -n "$ERROR_CODE" ]; then
281
+ echo " Error code: $ERROR_CODE" >&2
282
+ echo " Error message: $ERROR_MSG" >&2
283
+ fi
284
+ if [ "$MODE" = "sandbox" ] && [ "$ERROR_CODE" = "63007" ]; then
285
+ echo "" >&2
286
+ echo "HINT: The recipient has not joined the Twilio WhatsApp sandbox." >&2
287
+ echo "Ask them to send 'join <keyword>' to +1 415 523 8886 on WhatsApp." >&2
288
+ echo "Check Twilio Console > Messaging > Try it Out > WhatsApp for the keyword." >&2
289
+ fi
290
+ echo "$RESPONSE_BODY" >&2
291
+ exit 1
292
+ fi
@@ -0,0 +1,106 @@
1
+ #!/bin/bash
2
+ # Session Start — Called at the beginning of every Claude Code session
3
+ # Sets up intra-session inbox polling via CronCreate, reads dashboards,
4
+ # and checks for pending decisions.
5
+ #
6
+ # Usage: source scripts/session-start.sh (or called automatically)
7
+ # This script is idempotent — safe to run multiple times.
8
+
9
+ set -e
10
+
11
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
12
+ SOPHIE_AI_DIR="$(dirname "$SCRIPT_DIR")"
13
+ TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
14
+ TODAY=$(date -u +"%Y-%m-%d")
15
+ SESSION_ID="session-$(date +%s)"
16
+ LOG_DIR="$SOPHIE_AI_DIR/logs/sessions"
17
+ LOG_FILE="$LOG_DIR/${TODAY}-sessions.jsonl"
18
+
19
+ mkdir -p "$LOG_DIR"
20
+ mkdir -p "$SOPHIE_AI_DIR/state/triggers/priority"
21
+ mkdir -p "$SOPHIE_AI_DIR/state/inbox/slack"
22
+ mkdir -p "$SOPHIE_AI_DIR/state/inbox/internal"
23
+
24
+ # ─── 1. Log session start ───────────────────────────────────────────
25
+ echo "{\"event\":\"session_start\",\"session_id\":\"$SESSION_ID\",\"timestamp\":\"$TIMESTAMP\"}" >> "$LOG_FILE"
26
+ echo "[session-start] Session $SESSION_ID started at $TIMESTAMP"
27
+
28
+ # ─── 2. Check emergency stop ────────────────────────────────────────
29
+ if [ -f "$SOPHIE_AI_DIR/.emergency-stop" ]; then
30
+ echo "[session-start] EMERGENCY STOP ACTIVE — halting session start"
31
+ echo "{\"event\":\"session_blocked\",\"session_id\":\"$SESSION_ID\",\"reason\":\"emergency_stop\",\"timestamp\":\"$TIMESTAMP\"}" >> "$LOG_FILE"
32
+ exit 1
33
+ fi
34
+
35
+ # ─── 3. Read executive summary dashboard ────────────────────────────
36
+ DASHBOARD="$SOPHIE_AI_DIR/state/dashboards/executive-summary.yaml"
37
+ if [ -f "$DASHBOARD" ]; then
38
+ echo "[session-start] Executive summary loaded"
39
+ # Extract key metrics for session log
40
+ OPEN_ITEMS=$(grep "total_open_items:" "$DASHBOARD" 2>/dev/null | awk '{print $2}' || echo "?")
41
+ CRITICAL=$(grep "critical_items:" "$DASHBOARD" 2>/dev/null | awk '{print $2}' || echo "?")
42
+ SLA_BREACHES=$(grep "sla_breaches:" "$DASHBOARD" 2>/dev/null | awk '{print $2}' || echo "?")
43
+ echo "[session-start] Open: $OPEN_ITEMS | Critical: $CRITICAL | SLA breaches: $SLA_BREACHES"
44
+ else
45
+ echo "[session-start] WARNING: Executive summary dashboard not found"
46
+ fi
47
+
48
+ # ─── 4. Check for pending decisions ─────────────────────────────────
49
+ DECISION_QUEUE="$SOPHIE_AI_DIR/state/queues/decision-queue.yaml"
50
+ if [ -f "$DECISION_QUEUE" ]; then
51
+ PENDING=$(grep -c "status: open" "$DECISION_QUEUE" 2>/dev/null || echo "0")
52
+ if [ "$PENDING" -gt 0 ]; then
53
+ echo "[session-start] $PENDING pending decisions in queue"
54
+ fi
55
+ fi
56
+
57
+ # ─── 5. Check state/inbox/ for unprocessed items ────────────────────
58
+ UNPROCESSED=0
59
+ for svc_dir in "$SOPHIE_AI_DIR/state/inbox/slack" "$SOPHIE_AI_DIR/state/inbox/gmail" "$SOPHIE_AI_DIR/state/inbox/calendar" "$SOPHIE_AI_DIR/state/inbox/sms" "$SOPHIE_AI_DIR/state/inbox/internal"; do
60
+ if [ -d "$svc_dir" ]; then
61
+ COUNT=$(find "$svc_dir" -name "*.yaml" -maxdepth 1 2>/dev/null | wc -l | tr -d ' ')
62
+ UNPROCESSED=$((UNPROCESSED + COUNT))
63
+ fi
64
+ done
65
+ if [ "$UNPROCESSED" -gt 0 ]; then
66
+ echo "[session-start] $UNPROCESSED unprocessed inbox items found"
67
+ fi
68
+
69
+ # ─── 6. Check for existing priority triggers ────────────────────────
70
+ TRIGGER_DIR="$SOPHIE_AI_DIR/state/triggers/priority"
71
+ TRIGGER_COUNT=$(find "$TRIGGER_DIR" -name "*.yaml" -maxdepth 1 2>/dev/null | wc -l | tr -d ' ')
72
+ if [ "$TRIGGER_COUNT" -gt 0 ]; then
73
+ echo "[session-start] $TRIGGER_COUNT priority triggers pending — process immediately"
74
+ fi
75
+
76
+ # ─── 7. Output CronCreate instruction ───────────────────────────────
77
+ # This section outputs the CronCreate command that the Claude Code session
78
+ # should execute to set up 2-minute recurring inbox polling.
79
+ # The actual CronCreate call must be made by Claude Code (not bash).
80
+ cat <<'CRON_INSTRUCTION'
81
+
82
+ ════════════════════════════════════════════════════════════════════
83
+ INTRA-SESSION POLLING SETUP REQUIRED
84
+ ════════════════════════════════════════════════════════════════════
85
+ Execute the following CronCreate to enable 2-minute inbox polling:
86
+
87
+ CronCreate:
88
+ interval: "2m"
89
+ command: "Run intra-session inbox check"
90
+ instructions: |
91
+ 1. Run: node scripts/poller/intra-session-check.mjs
92
+ 2. Check state/inbox/ for new unprocessed items
93
+ 3. Check state/triggers/priority/ for new trigger files
94
+ 4. If a CEO message (from_ceo: true) is found:
95
+ - Create a priority trigger at state/triggers/priority/
96
+ - Interrupt current work to process the CEO message
97
+ 5. Report: "[inbox-poll] N new items, M priority triggers"
98
+
99
+ ════════════════════════════════════════════════════════════════════
100
+ CRON_INSTRUCTION
101
+
102
+ # ─── 8. Final session start log entry ───────────────────────────────
103
+ echo "{\"event\":\"session_ready\",\"session_id\":\"$SESSION_ID\",\"timestamp\":\"$(date -u +"%Y-%m-%dT%H:%M:%SZ")\",\"dashboard_loaded\":true,\"unprocessed_inbox\":$UNPROCESSED,\"pending_triggers\":$TRIGGER_COUNT,\"polling_setup\":\"pending_croncreate\"}" >> "$LOG_FILE"
104
+
105
+ echo ""
106
+ echo "[session-start] Session ready. Set up CronCreate polling (see above)."
@@ -0,0 +1,94 @@
1
+ #!/bin/bash
2
+ # =============================================================================
3
+ # boot-claude-session.sh — Launch interactive Claude Code session on boot
4
+ # =============================================================================
5
+ #
6
+ # Opens Terminal.app with a Claude Code interactive session in the agent's
7
+ # working directory. Called via launchd at login.
8
+ #
9
+ # This is separate from the maestro daemon (which runs headless as a Node.js
10
+ # process for polling/dispatching). This script provides a visible, interactive
11
+ # Claude Code session that the operator can observe and interact with.
12
+ #
13
+ # Usage:
14
+ # ./scripts/setup/boot-claude-session.sh <agent-dir>
15
+ #
16
+ # =============================================================================
17
+
18
+ set -euo pipefail
19
+
20
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
21
+ MAESTRO_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
22
+
23
+ # Agent directory required as first argument (e.g. ~/<firstname>-ai).
24
+ AGENT_DIR="${1:?Agent directory required as first argument (e.g. ~/<firstname>-ai)}"
25
+ if [ ! -d "$AGENT_DIR" ]; then
26
+ echo "ERROR: Agent directory does not exist: $AGENT_DIR" >&2
27
+ exit 1
28
+ fi
29
+
30
+ AGENT_NAME=$(basename "$AGENT_DIR")
31
+ # Resolve the agent's display name from config/agent.json (SOT), falling
32
+ # back to the directory basename. Used for the Terminal window banner.
33
+ AGENT_DISPLAY="$AGENT_NAME"
34
+ if [ -f "$AGENT_DIR/config/agent.json" ]; then
35
+ if command -v jq >/dev/null 2>&1; then
36
+ fn=$(jq -r '.fullName // empty' "$AGENT_DIR/config/agent.json")
37
+ [ -n "$fn" ] && AGENT_DISPLAY="$fn"
38
+ fi
39
+ fi
40
+ LOG_FILE="$MAESTRO_DIR/logs/watchdog/$(date +%Y-%m-%d)-boot-session.log"
41
+ mkdir -p "$(dirname "$LOG_FILE")"
42
+
43
+ log() {
44
+ echo "[$(date -u +"%Y-%m-%dT%H:%M:%SZ")] $1" | tee -a "$LOG_FILE"
45
+ }
46
+
47
+ # Wait for the system to settle after login (network, services, etc.)
48
+ log "Waiting 15s for system to settle..."
49
+ sleep 15
50
+
51
+ # Check for emergency stop
52
+ if [ -f "$AGENT_DIR/.emergency-stop" ]; then
53
+ log "Emergency stop active — not starting Claude session"
54
+ exit 0
55
+ fi
56
+
57
+ if [ -f "$MAESTRO_DIR/.emergency-stop" ]; then
58
+ log "Emergency stop active in maestro — not starting Claude session"
59
+ exit 0
60
+ fi
61
+
62
+ # Check if claude CLI is available
63
+ if ! command -v claude &>/dev/null; then
64
+ # Try common paths
65
+ CLAUDE_PATH=""
66
+ for p in "$HOME/.local/bin/claude" "/opt/homebrew/bin/claude" "/usr/local/bin/claude"; do
67
+ if [ -x "$p" ]; then
68
+ CLAUDE_PATH="$p"
69
+ break
70
+ fi
71
+ done
72
+
73
+ if [ -z "$CLAUDE_PATH" ]; then
74
+ log "ERROR: claude CLI not found"
75
+ exit 1
76
+ fi
77
+ else
78
+ CLAUDE_PATH=$(which claude)
79
+ fi
80
+
81
+ log "Starting Claude Code session in $AGENT_DIR (claude: $CLAUDE_PATH)"
82
+
83
+ # Open Terminal.app with Claude Code running in the agent directory
84
+ osascript <<APPLESCRIPT
85
+ tell application "Terminal"
86
+ activate
87
+ -- Open a new window with claude running in the agent directory
88
+ do script "cd '$AGENT_DIR' && clear && echo '╔══════════════════════════════════════════════════════════╗' && echo '║ $AGENT_DISPLAY — Boot Session ($(date +%Y-%m-%d))' && echo '╠══════════════════════════════════════════════════════════╣' && echo '║ Agent dir: $AGENT_DIR' && echo '║ Claude: $CLAUDE_PATH' && echo '╚══════════════════════════════════════════════════════════╝' && echo '' && '$CLAUDE_PATH'"
89
+ -- Set the window title
90
+ set custom title of front window to "$AGENT_NAME — Claude Code"
91
+ end tell
92
+ APPLESCRIPT
93
+
94
+ log "Terminal window opened with Claude Code session"