@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,674 @@
1
+ #!/bin/bash
2
+ # =============================================================================
3
+ # configure-macos.sh — Mac Mini Hardening for Maestro Agent Deployment
4
+ # =============================================================================
5
+ #
6
+ # Configures a Mac mini as a headless, always-on agent server:
7
+ # 1. Enables automatic login (no password on reboot)
8
+ # 2. Disables sleep, standby, and screen saver
9
+ # 3. Configures Parsec for remote desktop access (auto-launch on login)
10
+ # 4. Launches Slack with Chrome DevTools Protocol (CDP) for huddle automation
11
+ # 5. Sets up BlackHole virtual audio for voice integration
12
+ # 6. Configures Login Items for all required apps
13
+ # 7. Installs launchd agents for boot-time service startup
14
+ #
15
+ # Usage:
16
+ # sudo ./scripts/setup/configure-macos.sh # Full configuration
17
+ # sudo ./scripts/setup/configure-macos.sh --check # Verify current config
18
+ # ./scripts/setup/configure-macos.sh --apps-only # Non-sudo app setup only
19
+ #
20
+ # IMPORTANT: Some steps require sudo (auto-login, power management).
21
+ # Run with sudo for full configuration.
22
+ #
23
+ # =============================================================================
24
+
25
+ set -e
26
+
27
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
28
+ AGENT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
29
+ AGENT_NAME=$(basename "$AGENT_DIR")
30
+ CURRENT_USER=$(whoami)
31
+
32
+ # The directory from which this script was invoked — used as the boot-time
33
+ # Claude Code working directory (e.g. ~/agent-name, ~/wundr, etc.)
34
+ CALLER_DIR="${PWD}"
35
+
36
+ # Colours
37
+ RED='\033[0;31m'
38
+ GREEN='\033[0;32m'
39
+ YELLOW='\033[1;33m'
40
+ BLUE='\033[0;34m'
41
+ CYAN='\033[0;36m'
42
+ NC='\033[0m'
43
+
44
+ log() { echo -e "${BLUE}[config]${NC} $1"; }
45
+ ok() { echo -e "${GREEN} ✓${NC} $1"; }
46
+ warn() { echo -e "${YELLOW} ⚠${NC} $1"; }
47
+ fail() { echo -e "${RED} ✗${NC} $1"; }
48
+ section() { echo ""; echo -e "${CYAN}━━━ $1 ━━━${NC}"; }
49
+
50
+ # =============================================================================
51
+ # 1. AUTO-LOGIN (requires sudo)
52
+ # =============================================================================
53
+
54
+ configure_auto_login() {
55
+ section "Auto-Login Configuration"
56
+
57
+ if [ "$(id -u)" -ne 0 ]; then
58
+ warn "Skipping auto-login — requires sudo"
59
+ warn "Run: sudo ./scripts/setup/configure-macos.sh"
60
+ return 0
61
+ fi
62
+
63
+ log "Configuring auto-login for user: $SUDO_USER"
64
+
65
+ # Enable auto-login via defaults
66
+ defaults write /Library/Preferences/com.apple.loginwindow autoLoginUser "$SUDO_USER"
67
+
68
+ # Disable login screen items that slow down boot
69
+ defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME -bool false
70
+ defaults write /Library/Preferences/com.apple.loginwindow GuestEnabled -bool false
71
+
72
+ # Disable "Reopen windows when logging back in" prompt
73
+ defaults write com.apple.loginwindow TALLogoutSavesState -bool false
74
+ defaults write com.apple.loginwindow LoginwindowLaunchesRelaunchApps -bool false
75
+
76
+ ok "Auto-login enabled for $SUDO_USER"
77
+
78
+ # --- Disable all password gates that could block unattended operation -------
79
+ local real_home
80
+ real_home=$(eval echo "~$SUDO_USER")
81
+
82
+ # Disable "Require password after sleep or screen saver"
83
+ sudo -u "$SUDO_USER" defaults write com.apple.screensaver askForPassword -int 0
84
+ sudo -u "$SUDO_USER" defaults write com.apple.screensaver askForPasswordDelay -int 0
85
+ ok "Screen saver password prompt disabled"
86
+
87
+ # Disable screen lock via sysadminctl
88
+ sysadminctl -screenLock off 2>/dev/null || true
89
+ ok "Screen lock disabled"
90
+
91
+ # Disable idle logout (Privacy & Security > Log out when idle)
92
+ defaults write /Library/Preferences/.GlobalPreferences com.apple.autologout.AutoLogOutDelay -int 0
93
+ ok "Idle auto-logout disabled"
94
+
95
+ # Disable screen lock on wake for current user
96
+ sudo -u "$SUDO_USER" defaults -currentHost write com.apple.screensaver idleTime -int 0
97
+ ok "Screen saver idle timer set to never"
98
+
99
+ # Prevent display from sleeping and requiring login on wake
100
+ # (already handled by pmset displaysleep 0, but belt-and-suspenders)
101
+ defaults write /Library/Preferences/com.apple.loginwindow DisableScreenLock -bool true 2>/dev/null || true
102
+
103
+ warn "NOTE: FileVault must be disabled for auto-login to work"
104
+ warn "Check: fdesetup status"
105
+
106
+ # Check FileVault status
107
+ if fdesetup status 2>/dev/null | grep -q "On"; then
108
+ warn "FileVault is ON — auto-login will NOT work until FileVault is disabled"
109
+ warn "Disable with: sudo fdesetup disable"
110
+ warn "This is a security trade-off for headless server operation"
111
+ else
112
+ ok "FileVault is off — auto-login will work"
113
+ fi
114
+ }
115
+
116
+ # =============================================================================
117
+ # 2. PREVENT SLEEP / STANDBY / SCREEN SAVER
118
+ # =============================================================================
119
+
120
+ configure_power_management() {
121
+ section "Power Management (No Sleep)"
122
+
123
+ if [ "$(id -u)" -ne 0 ]; then
124
+ warn "Skipping power management — requires sudo"
125
+ return 0
126
+ fi
127
+
128
+ log "Disabling all sleep modes..."
129
+
130
+ # Disable system sleep
131
+ pmset -a sleep 0
132
+
133
+ # Disable display sleep (0 = never)
134
+ pmset -a displaysleep 0
135
+
136
+ # Disable hard disk sleep
137
+ pmset -a disksleep 0
138
+
139
+ # Disable standby mode
140
+ pmset -a standby 0
141
+
142
+ # Disable Power Nap
143
+ pmset -a powernap 0
144
+
145
+ # Disable hibernation
146
+ pmset -a hibernatemode 0
147
+
148
+ # Wake on network access (Wake-on-LAN)
149
+ pmset -a womp 1
150
+
151
+ # Auto-restart after power failure
152
+ pmset -a autorestart 1
153
+
154
+ # Disable proximity wake (Apple Watch)
155
+ pmset -a proximitywake 0
156
+
157
+ ok "Sleep disabled (system, display, disk, standby)"
158
+ ok "Wake-on-LAN enabled"
159
+ ok "Auto-restart on power failure enabled"
160
+
161
+ # Disable screen saver
162
+ log "Disabling screen saver..."
163
+ defaults -currentHost write com.apple.screensaver idleTime -int 0
164
+ ok "Screen saver disabled"
165
+
166
+ # Verify
167
+ log "Current power settings:"
168
+ pmset -g | grep -E "sleep|standby|hibernatemode|womp|autorestart" | while read -r line; do
169
+ echo " $line"
170
+ done
171
+ }
172
+
173
+ # =============================================================================
174
+ # 3. PARSEC AUTO-LAUNCH
175
+ # =============================================================================
176
+
177
+ configure_parsec() {
178
+ section "Parsec Remote Desktop"
179
+
180
+ # Check if Parsec is installed
181
+ if [ -d "/Applications/Parsec.app" ]; then
182
+ ok "Parsec installed"
183
+ else
184
+ warn "Parsec not installed"
185
+ warn "Install from: https://parsec.app/downloads"
186
+ warn "Or: brew install --cask parsec"
187
+ return 0
188
+ fi
189
+
190
+ # Add Parsec to Login Items via osascript
191
+ log "Adding Parsec to Login Items..."
192
+ osascript -e 'tell application "System Events" to make login item at end with properties {path:"/Applications/Parsec.app", hidden:false}' 2>/dev/null || true
193
+ ok "Parsec added to Login Items (launches on boot)"
194
+
195
+ # Create a launchd agent for Parsec as a fallback
196
+ local PLIST_PATH="$HOME/Library/LaunchAgents/com.parsec.agent.plist"
197
+
198
+ if [ ! -f "$PLIST_PATH" ]; then
199
+ cat > "$PLIST_PATH" << 'PLIST_EOF'
200
+ <?xml version="1.0" encoding="UTF-8"?>
201
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
202
+ <plist version="1.0">
203
+ <dict>
204
+ <key>Label</key>
205
+ <string>com.parsec.agent</string>
206
+ <key>ProgramArguments</key>
207
+ <array>
208
+ <string>open</string>
209
+ <string>-a</string>
210
+ <string>Parsec</string>
211
+ </array>
212
+ <key>RunAtLoad</key>
213
+ <true/>
214
+ <key>StandardOutPath</key>
215
+ <string>/dev/null</string>
216
+ <key>StandardErrorPath</key>
217
+ <string>/dev/null</string>
218
+ </dict>
219
+ </plist>
220
+ PLIST_EOF
221
+ launchctl load "$PLIST_PATH" 2>/dev/null || true
222
+ ok "Parsec launchd agent installed (backup auto-launch)"
223
+ else
224
+ ok "Parsec launchd agent already exists"
225
+ fi
226
+ }
227
+
228
+ # =============================================================================
229
+ # 4. SLACK WITH CDP (Chrome DevTools Protocol)
230
+ # =============================================================================
231
+
232
+ configure_slack_cdp() {
233
+ section "Slack with CDP (Huddle Support)"
234
+
235
+ if [ ! -d "/Applications/Slack.app" ]; then
236
+ warn "Slack not installed"
237
+ warn "Install: brew install --cask slack"
238
+ return 0
239
+ fi
240
+
241
+ ok "Slack installed"
242
+
243
+ # Remove Slack from Login Items (we manage it ourselves via boot-slack-cdp)
244
+ log "Ensuring Slack is NOT in Login Items (managed by launchd instead)..."
245
+ osascript -e 'tell application "System Events" to delete login item "Slack"' 2>/dev/null || true
246
+
247
+ # Install the boot-time Slack CDP launcher as a launchd agent
248
+ local PLIST_NAME="ai.maestro.slack-cdp.plist"
249
+ local PLIST_PATH="$HOME/Library/LaunchAgents/$PLIST_NAME"
250
+
251
+ cat > "$PLIST_PATH" << PLIST_EOF
252
+ <?xml version="1.0" encoding="UTF-8"?>
253
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
254
+ <plist version="1.0">
255
+ <dict>
256
+ <key>Label</key>
257
+ <string>ai.maestro.slack-cdp</string>
258
+ <key>ProgramArguments</key>
259
+ <array>
260
+ <string>/bin/bash</string>
261
+ <string>${AGENT_DIR}/scripts/huddle/boot-slack-cdp.sh</string>
262
+ </array>
263
+ <key>RunAtLoad</key>
264
+ <true/>
265
+ <key>StandardOutPath</key>
266
+ <string>${AGENT_DIR}/logs/huddle/boot-slack-cdp-stdout.log</string>
267
+ <key>StandardErrorPath</key>
268
+ <string>${AGENT_DIR}/logs/huddle/boot-slack-cdp-stderr.log</string>
269
+ <key>EnvironmentVariables</key>
270
+ <dict>
271
+ <key>PATH</key>
272
+ <string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
273
+ <key>CDP_PORT</key>
274
+ <string>9222</string>
275
+ </dict>
276
+ </dict>
277
+ </plist>
278
+ PLIST_EOF
279
+
280
+ launchctl unload "$PLIST_PATH" 2>/dev/null || true
281
+ launchctl load "$PLIST_PATH"
282
+ ok "Slack CDP launchd agent installed (launches with --remote-debugging-port on boot)"
283
+ }
284
+
285
+ # =============================================================================
286
+ # 5. VIRTUAL AUDIO (BlackHole for Huddle Voice)
287
+ # =============================================================================
288
+
289
+ configure_audio() {
290
+ section "Virtual Audio (BlackHole)"
291
+
292
+ if [ -f "$AGENT_DIR/scripts/huddle/setup-audio.sh" ]; then
293
+ log "Running audio setup..."
294
+ bash "$AGENT_DIR/scripts/huddle/setup-audio.sh" --check 2>&1 | while read -r line; do
295
+ echo " $line"
296
+ done
297
+
298
+ # If BlackHole is not installed, offer to install
299
+ if ! command -v SwitchAudioSource &>/dev/null || ! SwitchAudioSource -a 2>/dev/null | grep -q "BlackHole"; then
300
+ warn "BlackHole not installed — run: ./scripts/huddle/setup-audio.sh"
301
+ else
302
+ ok "BlackHole audio devices present"
303
+ fi
304
+ else
305
+ warn "Audio setup script not found at scripts/huddle/setup-audio.sh"
306
+ fi
307
+ }
308
+
309
+ # =============================================================================
310
+ # 6. OTHER APP LAUNCHES
311
+ # =============================================================================
312
+
313
+ configure_app_launches() {
314
+ section "Application Auto-Launch"
315
+
316
+ # WhatsApp (if installed)
317
+ if [ -d "/Applications/WhatsApp.app" ]; then
318
+ osascript -e 'tell application "System Events" to make login item at end with properties {path:"/Applications/WhatsApp.app", hidden:true}' 2>/dev/null || true
319
+ ok "WhatsApp added to Login Items"
320
+ else
321
+ warn "WhatsApp not installed (optional — install if agent uses WhatsApp)"
322
+ fi
323
+
324
+ # Safari (for Gmail web access)
325
+ # Safari is always available on macOS, but we don't need it as a Login Item
326
+ # The poller uses IMAP directly, not the browser
327
+ log "Safari: not needed as Login Item (Gmail uses IMAP polling)"
328
+
329
+ # Ensure required directories exist (as the real user, not root)
330
+ local real_user="${SUDO_USER:-$CURRENT_USER}"
331
+ local dirs=("$AGENT_DIR/logs/huddle" "$AGENT_DIR/state/huddle" "$AGENT_DIR/logs/watchdog")
332
+ for d in "${dirs[@]}"; do
333
+ mkdir -p "$d"
334
+ chown "$real_user:staff" "$d" 2>/dev/null || true
335
+ done
336
+ ok "Log and state directories verified (owned by $real_user)"
337
+
338
+ # --- Claude Code boot session (opens Terminal with interactive claude) ------
339
+ local BOOT_SCRIPT="$AGENT_DIR/scripts/setup/boot-claude-session.sh"
340
+ if [ -f "$BOOT_SCRIPT" ]; then
341
+ chmod +x "$BOOT_SCRIPT"
342
+
343
+ local PLIST_NAME="ai.maestro.boot-claude-session"
344
+ local PLIST_PATH="$real_home/Library/LaunchAgents/${PLIST_NAME}.plist"
345
+ local real_home
346
+ real_home=$(eval echo "~$real_user")
347
+
348
+ # Use the directory from which configure-macos.sh was invoked
349
+ local boot_agent_dir="$CALLER_DIR"
350
+
351
+ cat > "$PLIST_PATH" << PLIST_EOF
352
+ <?xml version="1.0" encoding="UTF-8"?>
353
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
354
+ <plist version="1.0">
355
+ <dict>
356
+ <key>Label</key>
357
+ <string>${PLIST_NAME}</string>
358
+ <key>ProgramArguments</key>
359
+ <array>
360
+ <string>/bin/bash</string>
361
+ <string>${BOOT_SCRIPT}</string>
362
+ <string>${boot_agent_dir}</string>
363
+ </array>
364
+ <key>RunAtLoad</key>
365
+ <true/>
366
+ <key>StandardOutPath</key>
367
+ <string>${AGENT_DIR}/logs/watchdog/boot-session-stdout.log</string>
368
+ <key>StandardErrorPath</key>
369
+ <string>${AGENT_DIR}/logs/watchdog/boot-session-stderr.log</string>
370
+ <key>EnvironmentVariables</key>
371
+ <dict>
372
+ <key>PATH</key>
373
+ <string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:${real_home}/.local/bin</string>
374
+ <key>HOME</key>
375
+ <string>${real_home}</string>
376
+ </dict>
377
+ </dict>
378
+ </plist>
379
+ PLIST_EOF
380
+
381
+ chown "$real_user:staff" "$PLIST_PATH" 2>/dev/null || true
382
+
383
+ # Load as the real user
384
+ if [ "$(id -u)" -eq 0 ]; then
385
+ su "$real_user" -c "launchctl unload '$PLIST_PATH' 2>/dev/null; launchctl load '$PLIST_PATH'" 2>/dev/null || true
386
+ else
387
+ launchctl unload "$PLIST_PATH" 2>/dev/null || true
388
+ launchctl load "$PLIST_PATH" 2>/dev/null || true
389
+ fi
390
+
391
+ ok "Claude Code boot session agent installed (opens Terminal + claude on login)"
392
+ else
393
+ warn "Boot session script not found at $BOOT_SCRIPT"
394
+ fi
395
+ }
396
+
397
+ # =============================================================================
398
+ # 7. MEMORY WATCHDOG
399
+ # =============================================================================
400
+
401
+ configure_memory_watchdog() {
402
+ section "Memory Watchdog (OOM Protection)"
403
+
404
+ local WATCHDOG_SCRIPT="$AGENT_DIR/scripts/watchdog/memory-watchdog.sh"
405
+ local PLIST_SOURCE="$AGENT_DIR/scripts/watchdog/ai.maestro.memory-watchdog.plist"
406
+
407
+ if [ ! -f "$WATCHDOG_SCRIPT" ]; then
408
+ fail "Watchdog script not found at $WATCHDOG_SCRIPT"
409
+ return 0
410
+ fi
411
+
412
+ chmod +x "$WATCHDOG_SCRIPT"
413
+ ok "Watchdog script executable"
414
+
415
+ # Determine the real user's home for LaunchAgents
416
+ local real_user="${SUDO_USER:-$CURRENT_USER}"
417
+ local real_home
418
+ real_home=$(eval echo "~$real_user")
419
+ local PLIST_DEST="$real_home/Library/LaunchAgents/ai.maestro.memory-watchdog.plist"
420
+
421
+ # Install the plist (update paths for this agent directory)
422
+ # Template plists may contain `__AGENT_DIR__` (preferred) or the legacy
423
+ # `/Users/robin/maestro` literal — substitute both for compatibility.
424
+ sed -e "s|__AGENT_DIR__|$AGENT_DIR|g" -e "s|/Users/robin/maestro|$AGENT_DIR|g" "$PLIST_SOURCE" > "$PLIST_DEST"
425
+ chown "$real_user:staff" "$PLIST_DEST" 2>/dev/null || true
426
+
427
+ # Load it (as the real user)
428
+ if [ "$(id -u)" -eq 0 ]; then
429
+ su "$real_user" -c "launchctl unload '$PLIST_DEST' 2>/dev/null; launchctl load '$PLIST_DEST'" 2>/dev/null || true
430
+ else
431
+ launchctl unload "$PLIST_DEST" 2>/dev/null || true
432
+ launchctl load "$PLIST_DEST" 2>/dev/null || true
433
+ fi
434
+
435
+ ok "Memory watchdog launchd agent installed (runs every 30s)"
436
+ log "Thresholds: warn=60% critical=75% emergency=85% max_procs=8"
437
+ log "Override via env: WATCHDOG_WARN_PERCENT, WATCHDOG_CRITICAL_PERCENT, etc."
438
+
439
+ # Create log directory with correct ownership
440
+ mkdir -p "$AGENT_DIR/logs/watchdog"
441
+ chown "$real_user:staff" "$AGENT_DIR/logs/watchdog" 2>/dev/null || true
442
+ }
443
+
444
+ # =============================================================================
445
+ # 8. ORCHESTRATOR AND SUBSYSTEMS ON BOOT
446
+ # =============================================================================
447
+
448
+ configure_boot_services() {
449
+ section "Boot-Time Services (Daemon + Pollers + Triggers)"
450
+
451
+ log "Verifying launchd agents are installed..."
452
+
453
+ local LAUNCH_AGENTS_DIR="$HOME/Library/LaunchAgents"
454
+ local EXPECTED_AGENTS=(
455
+ "ai.maestro.*-daemon"
456
+ "ai.maestro.*-poller"
457
+ "ai.maestro.*-inbox-processor"
458
+ "ai.maestro.*-backlog-executor"
459
+ "ai.maestro.*-meeting-prep"
460
+ "ai.maestro.*-meeting-action-capture"
461
+ "ai.maestro.*-midday-sweep"
462
+ )
463
+
464
+ # Count installed agents (current ai.maestro.* namespace + legacy ai.adaptic.*)
465
+ local installed_count
466
+ installed_count=$(ls "$LAUNCH_AGENTS_DIR"/ai.maestro.*.plist "$LAUNCH_AGENTS_DIR"/ai.adaptic.*.plist 2>/dev/null | wc -l | tr -d ' ')
467
+
468
+ if [ "$installed_count" -gt 0 ]; then
469
+ ok "$installed_count launchd agents installed"
470
+
471
+ # Check which are loaded
472
+ local loaded_count
473
+ loaded_count=$(launchctl list 2>/dev/null | grep -cE 'ai\.(maestro|adaptic)' || true)
474
+ if [ "$loaded_count" -gt 0 ]; then
475
+ ok "$loaded_count agents currently loaded"
476
+ else
477
+ warn "Agents installed but none loaded — run: npm run init-agent"
478
+ fi
479
+ else
480
+ warn "No launchd agents found — run: npm run init-agent"
481
+ fi
482
+
483
+ # Check if the daemon is running
484
+ if launchctl list 2>/dev/null | grep -q "daemon"; then
485
+ ok "Main daemon is loaded"
486
+ else
487
+ warn "Main daemon not loaded — the orchestrator won't start on boot"
488
+ warn "Run: npm run init-agent to install all launchd agents"
489
+ fi
490
+
491
+ # Check Slack events server
492
+ if [ -f "$AGENT_DIR/state/locks/slack-events-server.pid" ]; then
493
+ local EVENTS_PID
494
+ EVENTS_PID=$(cat "$AGENT_DIR/state/locks/slack-events-server.pid")
495
+ if kill -0 "$EVENTS_PID" 2>/dev/null; then
496
+ ok "Slack events server running (PID $EVENTS_PID)"
497
+ else
498
+ warn "Slack events server PID file exists but process not running"
499
+ fi
500
+ else
501
+ warn "Slack events server not running — start with: npm run slack:events:start"
502
+ fi
503
+ }
504
+
505
+ # =============================================================================
506
+ # 9. SYSTEM VERIFICATION
507
+ # =============================================================================
508
+
509
+ verify_all() {
510
+ section "System Verification"
511
+
512
+ local issues=0
513
+
514
+ # Check auto-login
515
+ local auto_login_user
516
+ auto_login_user=$(defaults read /Library/Preferences/com.apple.loginwindow autoLoginUser 2>/dev/null || echo "")
517
+ if [ -n "$auto_login_user" ]; then
518
+ ok "Auto-login: $auto_login_user"
519
+ else
520
+ fail "Auto-login: not configured"
521
+ issues=$((issues + 1))
522
+ fi
523
+
524
+ # Check sleep settings
525
+ local sleep_val
526
+ sleep_val=$(pmset -g | grep "^ sleep" | awk '{print $2}')
527
+ if [ "$sleep_val" = "0" ]; then
528
+ ok "System sleep: disabled"
529
+ else
530
+ fail "System sleep: $sleep_val minutes (should be 0)"
531
+ issues=$((issues + 1))
532
+ fi
533
+
534
+ # Check display sleep
535
+ local dsleep_val
536
+ dsleep_val=$(pmset -g | grep "displaysleep" | awk '{print $2}')
537
+ if [ "$dsleep_val" = "0" ]; then
538
+ ok "Display sleep: disabled"
539
+ else
540
+ fail "Display sleep: $dsleep_val minutes (should be 0)"
541
+ issues=$((issues + 1))
542
+ fi
543
+
544
+ # Check Parsec
545
+ if pgrep -x "parsecd" &>/dev/null; then
546
+ ok "Parsec: running"
547
+ elif [ -d "/Applications/Parsec.app" ]; then
548
+ warn "Parsec: installed but not running"
549
+ else
550
+ fail "Parsec: not installed"
551
+ issues=$((issues + 1))
552
+ fi
553
+
554
+ # Check Slack with CDP
555
+ if pgrep -x "Slack" &>/dev/null; then
556
+ if curl -s --connect-timeout 2 "http://localhost:9222/json/version" 2>/dev/null | python3 -c "import sys,json; json.load(sys.stdin)" 2>/dev/null; then
557
+ ok "Slack: running with CDP on port 9222"
558
+ else
559
+ warn "Slack: running but CDP not available (no huddle support)"
560
+ fi
561
+ else
562
+ fail "Slack: not running"
563
+ issues=$((issues + 1))
564
+ fi
565
+
566
+ # Check Node.js
567
+ if command -v node &>/dev/null; then
568
+ ok "Node.js: $(node --version)"
569
+ else
570
+ fail "Node.js: not installed"
571
+ issues=$((issues + 1))
572
+ fi
573
+
574
+ # Check Claude CLI
575
+ if command -v claude &>/dev/null; then
576
+ ok "Claude CLI: installed"
577
+ else
578
+ fail "Claude CLI: not installed"
579
+ issues=$((issues + 1))
580
+ fi
581
+
582
+ # Check memory watchdog
583
+ if launchctl list 2>/dev/null | grep -q "ai.maestro.memory-watchdog"; then
584
+ ok "Memory watchdog: running"
585
+ elif [ -f "$HOME/Library/LaunchAgents/ai.maestro.memory-watchdog.plist" ]; then
586
+ warn "Memory watchdog: installed but not loaded"
587
+ else
588
+ fail "Memory watchdog: not installed"
589
+ issues=$((issues + 1))
590
+ fi
591
+
592
+ # Check heartbeat freshness
593
+ local heartbeat_file="$AGENT_DIR/state/heartbeat"
594
+ if [ -f "$heartbeat_file" ]; then
595
+ local hb_age
596
+ hb_age=$(( $(date +%s) - $(date -j -f "%Y-%m-%dT%H:%M:%SZ" "$(cat "$heartbeat_file")" +%s 2>/dev/null || echo 0) ))
597
+ if [ "$hb_age" -lt 120 ]; then
598
+ ok "Heartbeat: fresh (${hb_age}s ago)"
599
+ else
600
+ warn "Heartbeat: stale (${hb_age}s ago — watchdog may not be running)"
601
+ fi
602
+ else
603
+ warn "Heartbeat: no heartbeat file found"
604
+ fi
605
+
606
+ # Summary
607
+ echo ""
608
+ if [ "$issues" -eq 0 ]; then
609
+ ok "All checks passed"
610
+ else
611
+ fail "$issues issue(s) found — see above"
612
+ fi
613
+
614
+ return "$issues"
615
+ }
616
+
617
+ # =============================================================================
618
+ # MAIN
619
+ # =============================================================================
620
+
621
+ main() {
622
+ echo ""
623
+ echo "╔══════════════════════════════════════════════════════════════╗"
624
+ echo "║ Maestro — Mac Mini Configuration ║"
625
+ echo "╠══════════════════════════════════════════════════════════════╣"
626
+ echo "║ Maestro: $AGENT_DIR"
627
+ echo "║ Boot target: $CALLER_DIR"
628
+ echo "║ Current user: $CURRENT_USER"
629
+ echo "╚══════════════════════════════════════════════════════════════╝"
630
+
631
+ case "${1:-full}" in
632
+ --check|check)
633
+ verify_all
634
+ ;;
635
+ --apps-only|apps)
636
+ configure_parsec
637
+ configure_slack_cdp
638
+ configure_audio
639
+ configure_app_launches
640
+ configure_memory_watchdog
641
+ configure_boot_services
642
+ ;;
643
+ --full|full|"")
644
+ configure_auto_login
645
+ configure_power_management
646
+ configure_parsec
647
+ configure_slack_cdp
648
+ configure_audio
649
+ configure_app_launches
650
+ configure_memory_watchdog
651
+ configure_boot_services
652
+
653
+ section "Configuration Complete"
654
+ echo ""
655
+ log "Next steps:"
656
+ echo " 1. Reboot to test auto-login: sudo shutdown -r now"
657
+ echo " 2. After reboot, verify: ./scripts/setup/configure-macos.sh --check"
658
+ echo " 3. Configure Parsec account (first time only): open /Applications/Parsec.app"
659
+ echo " 4. Run agent setup: npm run init-agent"
660
+ echo " 5. Configure identity: claude \"/init-maestro\""
661
+ echo ""
662
+ ;;
663
+ *)
664
+ echo "Usage: $0 [--full|--check|--apps-only]"
665
+ echo ""
666
+ echo " --full Full configuration (requires sudo for auto-login and power)"
667
+ echo " --check Verify current configuration"
668
+ echo " --apps-only Configure apps and services only (no sudo needed)"
669
+ exit 1
670
+ ;;
671
+ esac
672
+ }
673
+
674
+ main "$@"