@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,205 @@
1
+ # Runbook — Backup and Restore
2
+
3
+ For an operator who must (a) confirm an agent's backups are real and current, or
4
+ (b) rebuild a dead Mac mini and recover its secrets and state. A Maestro agent's
5
+ durable state (`state/`: queues, cost ledger, learning DB, allowlists), its logs,
6
+ and its `.env` secrets live on a single disk. Losing the disk without a working
7
+ backup loses the agent's local history; this runbook is how you avoid that and
8
+ how you recover when it happens.
9
+
10
+ This complements `docs/runbooks/mac-mini-bootstrap.md` (fresh provisioning) and
11
+ `docs/runbooks/incident-response.md` (a compromised, not dead, machine). For a
12
+ compromised machine, do NOT restore onto the same hardware — rebuild on a clean
13
+ box.
14
+
15
+ ## What is backed up, and the honest gaps
16
+
17
+ Off-machine backup is driven by `scripts/maintenance/backup-to-cloud.sh`, reading
18
+ `.maestro/backup-config.yaml`, run daily via launchd. Configure it with
19
+ `maestro init backup-replication --apply` (`scripts/setup/init-backup.mjs`).
20
+
21
+ Know these caveats before you rely on it:
22
+
23
+ - **Backup is opt-in and silent when off.** If `.maestro/backup-config.yaml` is
24
+ missing or `enabled: false`, the script exits 0 and does nothing. An agent with
25
+ no backup configured looks identical to a healthy one in casual inspection —
26
+ check explicitly (below).
27
+ - **Coverage historically excluded `logs/` and the audit records.** Confirm your
28
+ config's include paths cover `state/`, `logs/`, and `.maestro/`. If `logs/` is
29
+ excluded, a dead machine loses that agent's local compliance history — the
30
+ org-server export (next section) is your compensating control.
31
+ - **`retention_days` may not be enforced** by older builds; do not assume old
32
+ archives are pruned.
33
+ - **Archives may be unencrypted** unless you enabled client-side encryption.
34
+ Treat the backup bucket as sensitive, restrict access, and prefer an encrypted
35
+ bucket and encrypted archives.
36
+
37
+ The org server is your fleet-as-DR layer for the audit record: every
38
+ side-effecting action is a hash-chained `org_events` row at Cohort, exportable
39
+ as OCSF/OTel (`cohort export-audit`). So even if a single mini's local `logs/`
40
+ are lost, the authoritative cross-agent audit trail survives on the server. The
41
+ local logs hold richer detail (transcripts, raw messages); the server holds the
42
+ non-repudiable record.
43
+
44
+ ## Confirm a backup is real and current (do this before you need it)
45
+
46
+ ```bash
47
+ cd ~/<agent>-ai
48
+
49
+ # 1. Is backup configured and enabled?
50
+ test -f .maestro/backup-config.yaml && grep -E '^enabled:' .maestro/backup-config.yaml
51
+
52
+ # 2. Did the last run succeed, and when?
53
+ tail -n 20 logs/maintenance/backup.log
54
+
55
+ # 3. Does the configured destination actually have today's archive?
56
+ # (provider-specific; e.g. for GCS:)
57
+ # gcloud storage ls "gs://<bucket>/<prefix>/$(date -u +%F)/"
58
+
59
+ # 4. doctor surfaces backup freshness in the governance posture.
60
+ maestro doctor
61
+ ```
62
+
63
+ If `maestro doctor` does not flag a missing/stale backup red, do not assume the
64
+ backup is fine — verify the destination has a recent archive. A backup you have
65
+ never restored from is a hypothesis, not a backup; periodically restore one agent
66
+ into a scratch directory to prove the archive is usable.
67
+
68
+ ---
69
+
70
+ ## Restore a dead Mac mini
71
+
72
+ You are rebuilding an agent on replacement hardware. The order matters: provision
73
+ the host, recover secrets, restore state, re-establish org identity, then resume.
74
+
75
+ ### 1. Provision the replacement host
76
+
77
+ Follow `docs/runbooks/mac-mini-bootstrap.md` to get a clean Mac mini to the point
78
+ where `~/maestro` is available and the agent repo is cloned to `~/<agent>-ai`.
79
+ Do not start the daemon yet.
80
+
81
+ ### 2. Recover secrets
82
+
83
+ The `.env` is plaintext and there is no broker yet, so secret recovery is the
84
+ hardest step. In priority order:
85
+
86
+ - **From the backup archive**, if `.maestro/` and the agent's secret material
87
+ were included and the archive is encrypted at rest. Restore `.env` from the
88
+ archive, then immediately `chmod 600 .env`.
89
+ - **From the operator's escrow**, if your deployment keeps a sealed copy (e.g. in
90
+ a password manager entry per agent). This is the recommended belt-and-braces
91
+ until the secrets broker ships.
92
+ - **By re-issuing**, for anything you cannot recover: rotate the credential at
93
+ its source (Slack, WhatsApp, Gmail OAuth, relay) and write the new value. The
94
+ agent's Cohort device token specifically should be RE-MINTED, not restored —
95
+ see step 4.
96
+
97
+ If you are recovering after a *theft* (not just a hardware failure), treat every
98
+ secret as exposed and rotate per `docs/runbooks/incident-response.md` Scenario B
99
+ rather than restoring the old values.
100
+
101
+ ```bash
102
+ cd ~/<agent>-ai
103
+ # after placing .env:
104
+ chmod 600 .env
105
+ stat -f '%Sp' .env # confirm -rw------- (0600)
106
+ ```
107
+
108
+ ### 3. Restore state from the latest archive
109
+
110
+ ```bash
111
+ cd ~/<agent>-ai
112
+ # Pull the most recent archive from the configured destination into a temp dir,
113
+ # then unpack into the repo root so state/, logs/, and .maestro/ land in place.
114
+ # (provider-specific download; example for GCS:)
115
+ # gcloud storage cp "gs://<bucket>/<prefix>/<DATE>/<archive>" /tmp/restore.tar.gz
116
+ mkdir -p /tmp/restore && tar -xzf /tmp/restore.tar.gz -C /tmp/restore
117
+ # Inspect before overwriting:
118
+ ls /tmp/restore
119
+ # Then place state/ (and logs/ if backed up) into the repo:
120
+ cp -R /tmp/restore/state ./
121
+ cp -R /tmp/restore/logs ./ 2>/dev/null || true
122
+ ```
123
+
124
+ Sanity-check the restored state: the cost ledger and learning DB are SQLite
125
+ (`better-sqlite3`); a torn copy will fail to open. If `state/` is corrupt or
126
+ incomplete, the agent can still start — its durable queues will be empty, and it
127
+ re-establishes cursors — but you will have lost in-flight work. Note the gap in
128
+ the rebuild ticket.
129
+
130
+ ### 4. Re-establish org-server identity
131
+
132
+ Do NOT restore the old device token. Mint a fresh one so the rebuilt agent has a
133
+ clean, attributable identity:
134
+
135
+ ```bash
136
+ # On the operator station, against Cohort:
137
+ cohort --db "$COHORT_DB" pair approve <agentId> --scopes <scopes>
138
+ # This prints a new device token — write it into ~/<agent>-ai/.env on the mini.
139
+ ```
140
+
141
+ If the dead agent was previously `admin.deactivate`d (e.g. it died during an
142
+ incident), `admin.reactivate` it first. Confirm the agent appears in the registry
143
+ with the expected owner, sponsor, autonomy tier, and scopes — a rebuild is a good
144
+ moment to re-certify access.
145
+
146
+ ### 5. Resume operations
147
+
148
+ ```bash
149
+ cd ~/<agent>-ai
150
+ maestro doctor # green governance posture before going live
151
+ ./scripts/resume-operations.sh # health check, clear any stale .emergency-stop, load launchd
152
+ ```
153
+
154
+ Watch the first cadence ticks and the first inbound message end-to-end. Confirm
155
+ the agent heartbeats to the org server (`presence.beat`) and that its first
156
+ side-effecting action lands a row in the audit chain (`cohort doctor` chain
157
+ check passes).
158
+
159
+ ### 6. Re-arm backup on the new machine
160
+
161
+ A rebuilt machine with no backup is the next dead machine.
162
+
163
+ ```bash
164
+ cd ~/<agent>-ai
165
+ maestro init backup-replication --apply # if .maestro/backup-config.yaml absent
166
+ # confirm include paths cover state/, logs/, .maestro/; confirm encryption on.
167
+ maestro doctor # backup freshness should clear within a day
168
+ ```
169
+
170
+ ---
171
+
172
+ ## Cohort fleet-as-DR exports
173
+
174
+ The org server is the disaster-recovery layer for the audit/compliance record and
175
+ for fleet metadata, independent of any single mini's backup.
176
+
177
+ - **Audit history** survives machine loss: `cohort export-audit --format ocsf`
178
+ (or `--format otel`) reconstructs every approval, decision, cost, and handoff
179
+ the lost agent participated in, with hash-chain provenance, from the server's
180
+ `org_events`. Run this as part of restore to confirm the lost agent's history
181
+ is intact server-side, and to fill any gap left by missing local `logs/`.
182
+ - **Identity and registry** survive: the agent's owner, sponsor, tier, scopes,
183
+ and credential bindings are server-side records re-bound at re-pair time, not
184
+ reconstructed from the dead disk.
185
+ - **Cost rollups** survive: per-agent/model/day spend reported via `cost.report`
186
+ is server-side, so financial accounting for the lost period is recoverable even
187
+ if the local ledger is gone.
188
+
189
+ Back up the Cohort database itself on its own schedule — it is the single point
190
+ whose loss takes the fleet's audit trail with it. Treat the Cohort DB and
191
+ `COHORT_SIGNING_SECRET` as tier-zero: encrypted backups, restricted access,
192
+ tested restore.
193
+
194
+ ## Quick reference
195
+
196
+ | Need | Command |
197
+ |---|---|
198
+ | Is backup on? | `grep -E '^enabled:' .maestro/backup-config.yaml` |
199
+ | Last backup status | `tail logs/maintenance/backup.log` |
200
+ | Configure backup | `maestro init backup-replication --apply` |
201
+ | Governance posture incl. backup freshness | `maestro doctor` |
202
+ | Re-mint agent identity | `cohort pair approve <agentId> --scopes <...>` |
203
+ | Recover audit history | `cohort export-audit --format ocsf` |
204
+ | Resume after restore | `./scripts/resume-operations.sh` |
205
+ | Lock down `.env` | `chmod 600 .env` |
@@ -0,0 +1,129 @@
1
+ # Runbook — Cohort Cutover
2
+
3
+ For the operator moving the org server and the agent fleet from the Neolith
4
+ name to Cohort. The `cohort` branch of this repo carries the full text rename —
5
+ `services/neolith` → `services/cohort`, package `@neolith/agent-sdk` →
6
+ `@cohortapp/agent-sdk`, `COHORT_*` env names, `bin/cohort.mjs` — and this runbook
7
+ is the infrastructure the code change cannot reach: the Railway repoint, the
8
+ variable names, the npm scope, and the per-machine fleet update. The
9
+ product-app side of the same cutover (domains, OAuth, app releases) lives in
10
+ the `adapticai/hq` repo as `COHORT-RENAME.md`.
11
+
12
+ Companion runbooks: `docs/runbooks/fleet-operations.md` (rollout rings — reuse
13
+ them for every step here that touches minis), `docs/runbooks/backup-restore.md`,
14
+ `docs/runbooks/incident-response.md`. `DEPLOYMENT.md` describes the org-server
15
+ architecture this runbook repoints.
16
+
17
+ Order: npm scope first (additive), then the org server, then the avatar
18
+ worker, then the fleet, cleanup last.
19
+
20
+ ---
21
+
22
+ ## 1. Org server on Railway
23
+
24
+ The service builds from this repo with the **repo root as build context** —
25
+ the Dockerfile reaches up for `lib/` (`DEPLOYMENT.md` §2.1). The rename moved
26
+ `services/neolith` → `services/cohort`, so make all of this **one** Settings
27
+ visit, not three:
28
+
29
+ 1. **Variables.** `COHORT_*` is the canonical prefix, but every entry point —
30
+ `bin/maestro.mjs`, `bin/cohort-mcp.mjs`, `lib/org/client.mjs`, and the
31
+ server's own `bin/cohort.mjs` — first runs `applyBrandEnvCompat()`
32
+ (`lib/env-compat.mjs`), bridging `NEOLITH_*` ⇄ `COHORT_*`. The repoint
33
+ therefore works with the existing `NEOLITH_*` variables untouched. Add the
34
+ canonical spellings anyway and migrate onto them: `COHORT_ADMIN_TOKEN`,
35
+ `COHORT_SIGNING_KEY` / `COHORT_SIGNING_KEY_FILE`, `COHORT_CRED_KEY`,
36
+ `COHORT_DB` (SQLite pilot) or `DATABASE_URL` (Postgres), `COHORT_PORT`
37
+ (default 7470). Annotated list: `services/cohort/.env.example`. Delete the
38
+ legacy twins at cleanup (§5), not before.
39
+ 2. **Source → Branch:** `main` → `cohort`.
40
+ 3. **Config path, same action:** if the service pins a Railway Config File
41
+ (`services/neolith/railway.json`) or a Root Directory under
42
+ `services/neolith`, change it to `services/cohort/…` — otherwise the first
43
+ `cohort` build cannot find its config. The tracked
44
+ `services/cohort/railway.json` pins
45
+ `dockerfilePath: services/cohort/Dockerfile`,
46
+ `startCommand: node bin/cohort.mjs serve`, healthcheck `/v1/ops`.
47
+
48
+ Verify after the deploy: build green, `/v1/ops` healthy, agent heartbeats
49
+ landing, a `credential.lease` succeeds, and `org_events` keep chaining — the
50
+ audit hash chain is content-based, so a branch or name change never breaks it.
51
+
52
+ **Do not rename the Railway service in the same window.** Every fleet
53
+ machine's `config/org.yaml` pins `server.url` (e.g.
54
+ `https://neolith.up.railway.app`) plus the TLS fingerprint; renaming the
55
+ service changes the `*.up.railway.app` host and strands the fleet. Move the
56
+ fleet to a stable custom domain first (§2), then rename freely.
57
+
58
+ ---
59
+
60
+ ## 2. Custom domain for the org server
61
+
62
+ Railway → service → Settings → Networking: add `org.cohortapp.com`; create the
63
+ CNAME Railway displays at the `cohortapp.com` DNS host. Old and new hosts
64
+ serve in parallel — there is no flag day for the fleet.
65
+
66
+ Then roll `config/org.yaml` across machines through rings, never all at once:
67
+
68
+ - `server.url` → `https://org.cohortapp.com`
69
+ - `server.fingerprint` → re-pin against the new host's TLS cert
70
+
71
+ Pairing survives the move — agent identity is the device keypair, not the URL.
72
+
73
+ ---
74
+
75
+ ## 3. Avatar worker
76
+
77
+ `services/avatar` kept its name. The Railway avatars service needs only
78
+ **Source → Branch: `main` → `cohort`** — Root Directory stays
79
+ `services/avatar` and its `railway.json` (`dockerfilePath: Dockerfile`,
80
+ `startCommand: node bin/avatar-worker.mjs start`) is unchanged.
81
+
82
+ ---
83
+
84
+ ## 4. npm scope and the fleet
85
+
86
+ The package is now `@cohortapp/agent-sdk` (bins: `maestro`, `cohort`,
87
+ `cohort-mcp`, plus legacy aliases `neolith` and `neolith-mcp` so installed
88
+ launchd jobs survive the bump; `.npmrc` keeps the `@neolith:registry` mapping).
89
+
90
+ 1. Create the npm org/scope **`cohort`** on npmjs.com.
91
+ 2. First publish is manual — Trusted Publishing is configured on an existing
92
+ package's settings page. From a `cohort`-branch checkout:
93
+ `npm publish --access public` as an org member.
94
+ 3. Wire Trusted Publishing: npmjs.com → `@cohortapp/agent-sdk` → Settings →
95
+ Trusted Publisher → GitHub Actions, org `adapticai`, repo `maestro`,
96
+ workflow `auto-publish-npm.yml`. The workflow is already OIDC-ready
97
+ (`id-token: write`, npm ≥ 11.5.1, strips the `.npmrc` authToken line,
98
+ no-ops on already-published versions).
99
+ 4. Bump each mini through rings (`docs/runbooks/fleet-operations.md`), canary
100
+ first:
101
+
102
+ ```bash
103
+ cd ~/<agent>-ai
104
+ maestro doctor # BEFORE posture
105
+ npm install @cohortapp/agent-sdk@latest
106
+ maestro doctor # AFTER must be no worse
107
+ ./scripts/resume-operations.sh
108
+ ```
109
+
110
+ Machines still on `@neolith/agent-sdk` keep working against the repointed
111
+ server — the org protocol is frozen and name-agnostic, and `config/org.yaml`
112
+ pins the URL, not the package name — so the fleet bump can trail the server
113
+ cutover by days.
114
+
115
+ ---
116
+
117
+ ## 5. Cleanup
118
+
119
+ - Delete the `NEOLITH_*` variables from the Railway services once the
120
+ `COHORT_*` twins are set and a deploy has been verified reading them (the
121
+ env-compat bridge makes the overlap safe, not permanent).
122
+ - `npm deprecate @neolith/agent-sdk "renamed to @cohortapp/agent-sdk"` — if the
123
+ old scope was ever published.
124
+ - After the fleet is on `org.cohortapp.com`: optionally rename the Railway
125
+ service, then sweep anything pinned to the old `*.up.railway.app` host
126
+ (monitors, webhooks, stray `org.yaml` stragglers — the registry's presence
127
+ view shows who stopped heartbeating).
128
+ - Merge `cohort` → `main` and point the services back at `main`, mirroring the
129
+ hq-side sequence.
@@ -0,0 +1,200 @@
1
+ # Runbook — Fleet Operations
2
+
3
+ For an operator running 40–60 Maestro agents as a fleet. Covers rollout rings,
4
+ version skew, cross-agent triage, fleet-wide pause, and decommissioning an agent.
5
+ Maestro's per-machine substrate is strong; the fleet layer is the part you
6
+ operate by convention plus the Cohort org server. Where a fleet primitive is
7
+ still maturing, this runbook says so and gives the manual procedure.
8
+
9
+ Companion runbooks: `docs/runbooks/incident-response.md` (one bad agent),
10
+ `docs/runbooks/backup-restore.md` (one dead agent),
11
+ `docs/runbooks/recovery-and-failover.md` (operational recovery).
12
+
13
+ ## The fleet is vendored per machine
14
+
15
+ Each agent runs `~/maestro` as a checkout/package on its own Mac mini. There is
16
+ no central push that updates all of them at once — upgrades are per machine and
17
+ drift is the default unless you manage it. This is why rings, a version floor, and
18
+ skew-watching matter operationally rather than as nice-to-haves.
19
+
20
+ The org server gives you the cross-machine views that the minis cannot give
21
+ themselves: registry/identity, presence/heartbeat, approvals, decisions, cost
22
+ rollups, policy distribution, and the audit export. Use it as the fleet's control
23
+ and observation plane; use SSH/runbooks on individual minis for anything the
24
+ server does not yet do remotely.
25
+
26
+ ---
27
+
28
+ ## Rollout rings
29
+
30
+ Never upgrade all 40–60 agents at once. Promote through rings and let each ring
31
+ bake before the next.
32
+
33
+ 1. **Canary (1–2 agents).** Pick low-stakes agents (not the CEO's, not a
34
+ compliance-adjacent one). Upgrade, then watch a full day of real traffic:
35
+ inbound handled, cadences firing, sends going out, heartbeats green, no new
36
+ doctor red flags, cost in band.
37
+ 2. **Early ring (~10%).** A representative spread of archetypes. Bake 1–2 days.
38
+ Watch for archetype-specific breakage (a tool one role uses heavily that the
39
+ canary did not exercise).
40
+ 3. **Broad ring (~50%).** Bake a day.
41
+ 4. **Fleet (remainder).** Only after the broad ring is clean.
42
+
43
+ Per-agent upgrade on a mini:
44
+
45
+ ```bash
46
+ cd ~/<agent>-ai
47
+ maestro doctor # capture the BEFORE posture
48
+ npm update @cohortapp/agent-sdk # or: git -C ~/maestro pull, for direct checkouts
49
+ maestro doctor # AFTER posture must be no worse
50
+ ./scripts/resume-operations.sh # restart cleanly so the daemon picks up the new code
51
+ ```
52
+
53
+ Promotion gate between rings: zero new doctor red flags, heartbeats present for
54
+ every upgraded agent, no spike in the audit export's failure/refusal families, and
55
+ cost-per-session unchanged. If any ring regresses, STOP promoting and roll back
56
+ that ring before touching the next.
57
+
58
+ ### Rollback
59
+
60
+ Pin the agent back to the last-known-good version and restart:
61
+
62
+ ```bash
63
+ cd ~/<agent>-ai
64
+ npm install @cohortapp/agent-sdk@<last-good-version> # or: git -C ~/maestro checkout <good-sha>
65
+ ./scripts/resume-operations.sh
66
+ maestro doctor
67
+ ```
68
+
69
+ For a direct `~/maestro` checkout, rollback is a `git checkout` of the known-good
70
+ SHA followed by a restart. Record the rollback and the regression in the rollout
71
+ ticket so the canary catches it next time.
72
+
73
+ ---
74
+
75
+ ## Version skew
76
+
77
+ A fleet mid-rollout is heterogeneous by design; the risk is *unbounded* skew and
78
+ agents below the floor.
79
+
80
+ - **Take inventory.** The registry should carry each agent's `maestroVersion` via
81
+ its heartbeat. Where that field is not yet populated, collect it manually:
82
+ `for a in <agents>; do ssh "$a" 'cd ~/<repo> && node -p "require(\"@cohortapp/agent-sdk/package.json\").version"'; done`.
83
+ - **Hold a version floor.** Define the minimum version any agent may run
84
+ (typically the last version that fixed a security or durability bug). Agents
85
+ below the floor are upgraded out of band, not left to the normal ring cadence —
86
+ a below-floor agent is an exposure, not just stale.
87
+ - **Bound the spread.** Do not let the newest and oldest agents differ by more
88
+ than one minor version in steady state. If a rollout stalls, either finish it
89
+ or roll the leading ring back to close the gap.
90
+ - **Watch for protocol skew with the server.** The agent↔Cohort protocol is
91
+ versioned. If you upgrade the server, confirm the oldest agent in the fleet
92
+ still speaks the protocol before you cut over; if not, raise the floor first.
93
+
94
+ ---
95
+
96
+ ## Cross-agent triage
97
+
98
+ With 40–60 agents you cannot watch 40–60 Slack DM streams. Triage from the org
99
+ server's aggregate views, then drill into the one machine that needs it.
100
+
101
+ 1. **Fleet health at a glance.** Presence/heartbeat tells you who is alive. A
102
+ stale heartbeat is the first signal — an agent that stopped beating is either
103
+ wedged, off, or its machine is down. (Where a `maestro fleet status` rollup is
104
+ available, use it; otherwise read presence from the server and `maestro
105
+ doctor` on suspects.)
106
+ 2. **Behavioral signals, not single failures.** Agents fail silently by
107
+ completing with wrong output, so triage on patterns from the audit/cost
108
+ export: refusal spikes, per-tool failure rates above baseline, cost-per-session
109
+ p99 climbing, an agent that has gone quiet (no events) during its active hours.
110
+ Pull these from `cohort export-audit --format otel` (spans carry the
111
+ `gen_ai.*` and cost attributes) and the cost rollup.
112
+ 3. **Correlate one interaction.** To reconstruct a single user interaction across
113
+ item → classification → session → send, follow the trace/decision identifiers:
114
+ the model-router `decision_id` joins a routing decision to its ledger row to
115
+ its resume marker, and the audit chain's `seq`/`row_hash` order the events.
116
+ This is how you answer "what did agent X actually do at 14:05" authoritatively.
117
+ 4. **Drill to the machine.** Once you have the suspect, SSH in and run `maestro
118
+ doctor` for the one-screen governance posture (heartbeats, throttle, breaker,
119
+ budget band, stuck markers, permissions hygiene), then read its `logs/`.
120
+
121
+ ---
122
+
123
+ ## Fleet-wide pause (break-glass)
124
+
125
+ When you need everything to stop — a fleet-level security event, a bad upgrade
126
+ caught mid-rollout, a provider outage causing runaway retries.
127
+
128
+ There is no single command that pauses all minis today; pause is the sum of
129
+ per-agent kill switches plus server-side deactivation. Sequence:
130
+
131
+ 1. **Cut coordination at the server.** Deactivate each agent (or, if your build
132
+ supports it, suspend the fleet); a deactivated agent's tokens are revoked and
133
+ it cannot coordinate or be impersonated:
134
+ ```bash
135
+ for a in $(cat fleet-roster.txt); do
136
+ cohort --db "$COHORT_DB" admin deactivate "$a" --reason "fleet pause <ticket>"
137
+ done
138
+ ```
139
+ 2. **Halt execution on each mini** (the local break-glass), in parallel where you
140
+ have fan-out SSH:
141
+ ```bash
142
+ # per machine:
143
+ cd ~/<agent>-ai && ./scripts/emergency-stop.sh
144
+ ```
145
+ This drops `.emergency-stop`, unloads launchd jobs, and kills running sessions.
146
+ 3. **Confirm silence.** Heartbeats stop; the audit export shows no new
147
+ side-effecting events. If any agent is still acting, it did not honor the stop
148
+ — investigate that machine directly.
149
+
150
+ Resume is deliberate and per agent (see "Resume" below). Do not script a
151
+ fleet-wide auto-resume; a pause exists because something needed a human decision.
152
+
153
+ Resume after the cause is cleared:
154
+
155
+ ```bash
156
+ # per machine:
157
+ cd ~/<agent>-ai && ./scripts/resume-operations.sh
158
+ # then on the operator station, per agent:
159
+ cohort --db "$COHORT_DB" admin reactivate "$a"
160
+ ```
161
+
162
+ ---
163
+
164
+ ## Decommissioning an agent
165
+
166
+ Retiring an agent permanently. The goal is no orphaned identity, no live
167
+ credentials, and a preserved audit trail.
168
+
169
+ 1. **Stop it.** Local break-glass plus server deactivation:
170
+ ```bash
171
+ cd ~/<agent>-ai && ./scripts/emergency-stop.sh
172
+ cohort --db "$COHORT_DB" admin deactivate <agentId> --reason "decommission"
173
+ ```
174
+ Deactivation revokes its tokens — the identity-side half of the kill switch.
175
+ 2. **Preserve its history before you touch the machine.** Export its audit trail
176
+ from the server (`cohort export-audit --format ocsf`, filtered to the agent)
177
+ and take a final off-machine backup of its `state/` and `logs/`
178
+ (`docs/runbooks/backup-restore.md`). A decommissioned agent's compliance
179
+ record must outlive the agent — retain per `docs/compliance/evidence-map.md`.
180
+ 3. **Revoke channel access at the source.** Slack token, WhatsApp session, Gmail
181
+ OAuth, Telegram bot, relay secrets — revoke each in its provider so the retired
182
+ identity cannot send even if a credential lingers.
183
+ 4. **Drain in-flight obligations.** Check the audit export's `handoff` and
184
+ `approval` families for anything the agent owed another agent or a human;
185
+ reassign or close those before the agent is gone, or they become orphaned.
186
+ 5. **Wipe the machine.** Securely erase `.env` and `state/` on the mini (the
187
+ plaintext secrets especially). If the hardware is being redeployed for a new
188
+ agent, treat it as a fresh provision (`docs/runbooks/mac-mini-bootstrap.md`),
189
+ not a rename of the old one.
190
+ 6. **Close the identity.** Mark the registry record decommissioned (its lifecycle
191
+ state), with the date and the operator who did it. Do not delete the record —
192
+ the audit trail references it; a deleted identity makes its history
193
+ un-attributable.
194
+ 7. **Notify.** If the agent was HR-adjacent or interacted with people who relied
195
+ on it, tell those people it is retired (and who to talk to instead) — the
196
+ deployer's transparency duty does not end when the agent does.
197
+
198
+ A decommissioning is done when: the agent cannot authenticate, cannot send on any
199
+ channel, has no live launchd jobs, its history is exported and retained, its
200
+ registry record is marked retired (not deleted), and affected humans are notified.