@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,463 @@
1
+ /**
2
+ * lib/org/knowledge.mjs — agent-facing shared-memory API over the Cohort
3
+ * knowledge plane (SPEC-org-server §4.7).
4
+ *
5
+ * THE compounding-collaboration lever. Where lib/learning/ and lib/collective/
6
+ * give one agent a memory of its OWN sessions, this module gives every agent a
7
+ * window into the ORG's shared, ACL'd knowledge: a fact promoted by agent A is
8
+ * retrievable by agent B inside the ACL, invisible outside it. It is the org-wide
9
+ * RAG source an agent's context-assembly can consult — `recall(query)` pulls the
10
+ * shared facts the server's RLS floor permits, and `remember(fact)` lands new
11
+ * shared knowledge for everyone else.
12
+ *
13
+ * The verb surface is deliberately small and human:
14
+ * - remember(fact, {group}) → knowledge.append (episodes; commutes) or
15
+ * knowledge.replace (CAS) when {id, expectedVersion}
16
+ * - recall(query, {group?}) → knowledge.search → the ACL-visible facts
17
+ * - forget(id, {reason?}) → knowledge.invalidate (tombstone, NEVER delete)
18
+ * - rewrite(id, text, …) → knowledge.rewrite (designated-owner-only)
19
+ * - upsertContact / contacts → contacts.upsert / contacts.list
20
+ * - recordMeeting / meetings → meetings.record / meetings.list
21
+ *
22
+ * ──────────────────────────────────────────────────────────────────────────
23
+ * THE SERVER IS AUTHORITATIVE FOR ACL. This is load-bearing and non-negotiable.
24
+ *
25
+ * This module NEVER decides what an agent may read or write. It does not inspect
26
+ * a fact's `group`, does not know which barrier:<cell> the agent holds, and does
27
+ * NOT filter `recall()` results. The non-bypassable RLS floor — org/unit group
28
+ * membership, `barrier:<cell>` DENY-OVERRIDE (never returned unless explicitly
29
+ * granted, even to an org/unit member), and participant-derived ACLs — lives in
30
+ * the server's query layer (the SQLite/Postgres-RLS floor every read passes
31
+ * through). The agent's groups derive from its VERIFIED identity, not from
32
+ * anything this client sends. `recall()` renders exactly what the server chose to
33
+ * return; the `{group}` argument is a SCOPING HINT to the server, never a filter
34
+ * the client enforces. If you want to narrow a search, the server still applies
35
+ * the floor on top of your hint — a hint can only ever shrink, never widen, what
36
+ * comes back.
37
+ *
38
+ * Every `recall()` is a SIDE-EFFECTING, AUDITED retrieval: the server appends a
39
+ * 'knowledge' org_events row {agent, query, returned_ids, groups_considered} —
40
+ * the regulator-facing read-audit trail. There is no "silent" read of the plane.
41
+ * ──────────────────────────────────────────────────────────────────────────
42
+ *
43
+ * G16 (zero-LLM-in-the-coordination-loop): NOTHING here makes an LLM call. These
44
+ * are pure parameter shaping + a fail-open HTTP round-trip. Episode CONSOLIDATION
45
+ * (the optional ingest worker that distils episodes into facts) is the only LLM
46
+ * consumer in the plane and lives server-side, OUT of this synchronous path.
47
+ *
48
+ * Fail-open by design: a disabled/unreachable server makes `remember/forget`
49
+ * a no-op `{ok:false, skipped}` and `recall/contacts/meetings` return `[]` —
50
+ * never a throw — so the org knowledge binding can never take down the agent's
51
+ * main path. `fetchImpl` is injectable everywhere for deterministic tests.
52
+ *
53
+ * Node builtins only (global fetch on Node 20). ESM.
54
+ *
55
+ * @module lib/org/knowledge
56
+ */
57
+
58
+ "use strict";
59
+
60
+ import {
61
+ isEnabled,
62
+ configFromAgent,
63
+ knowledgeAppend,
64
+ knowledgeReplace,
65
+ knowledgeRewrite,
66
+ knowledgeInvalidate,
67
+ knowledgeSearch,
68
+ contactsUpsert,
69
+ contactsList,
70
+ meetingsRecord,
71
+ meetingsList,
72
+ } from "./client.mjs";
73
+ import { KNOWLEDGE_GROUP_KINDS } from "./protocol.mjs";
74
+
75
+ /** Default cap on facts returned by a single recall (the server may cap lower). */
76
+ const DEFAULT_RECALL_LIMIT = 20;
77
+
78
+ // ---------------------------------------------------------------------------
79
+ // Group hints (the server is still authoritative — these are advisory shapes)
80
+ // ---------------------------------------------------------------------------
81
+
82
+ /**
83
+ * Normalise a group hint to a `group_id` string of the form the plane uses:
84
+ * `org` | `unit:<id>` | `barrier:<cell>` (KNOWLEDGE_GROUP_KINDS). Accepts either
85
+ * a ready string or a `{kind, id}` object. Returns undefined when nothing usable
86
+ * is given (the server then picks the group from the caller's verified identity).
87
+ *
88
+ * This is a SHAPE helper only — emitting `barrier:<cell>` here does NOT grant the
89
+ * agent that cell. The server still deny-overrides any barrier group the agent's
90
+ * verified identity was not explicitly granted.
91
+ *
92
+ * @param {string|{kind?:string,id?:string,cell?:string}|undefined} group
93
+ * @returns {string|undefined}
94
+ */
95
+ export function normalizeGroup(group) {
96
+ if (group == null) return undefined;
97
+ if (typeof group === "string") {
98
+ const s = group.trim();
99
+ if (!s) return undefined;
100
+ if (s === "org") return "org";
101
+ // Already in `kind:rest` form, or a bare unit/barrier id we leave to the server.
102
+ if (s.includes(":")) {
103
+ const kind = s.split(":", 1)[0];
104
+ return KNOWLEDGE_GROUP_KINDS.includes(kind) ? s : undefined;
105
+ }
106
+ return undefined;
107
+ }
108
+ if (typeof group === "object") {
109
+ const kind = group.kind ? String(group.kind) : "";
110
+ if (kind === "org") return "org";
111
+ const id = group.id != null ? String(group.id) : (group.cell != null ? String(group.cell) : "");
112
+ if ((kind === "unit" || kind === "barrier") && id) return `${kind}:${id}`;
113
+ }
114
+ return undefined;
115
+ }
116
+
117
+ // ---------------------------------------------------------------------------
118
+ // remember — land shared knowledge (append episode, or CAS-replace a fact)
119
+ // ---------------------------------------------------------------------------
120
+
121
+ /**
122
+ * Remember a fact into the org's shared knowledge plane.
123
+ *
124
+ * Default path is `knowledge.append` — an episode, the SOLE shared-write
125
+ * primitive; it COMMUTES, so concurrent appends from different agents both land
126
+ * with no coordination. When the caller supplies `{id, expectedVersion}` it's an
127
+ * update to an existing fact and routes to `knowledge.replace` (compare-and-swap
128
+ * on the version; a stale CAS comes back as a CONFLICT frame). Use `rewrite()`
129
+ * (not this) for an owner-only in-place rewrite.
130
+ *
131
+ * The `group` is a HINT only; the server assigns/validates the fact's group from
132
+ * the caller's verified identity subject to the RLS floor. Never throws; returns
133
+ * a benign skipped result when the integration is disabled.
134
+ *
135
+ * @param {string|{text:string,...}} fact the episode text, or a fact object
136
+ * @param {object} opts - {
137
+ * cfg, group?, id?, expectedVersion?, kind?, participants?, provenance?,
138
+ * links?, refs?, idempotencyKey?, fetchImpl?
139
+ * }
140
+ * @returns {Promise<{ok:boolean, skipped?:boolean, mode?:'append'|'replace', id?:string, result?:any, error?:object}>}
141
+ */
142
+ export async function remember(fact, opts = {}) {
143
+ if (!isEnabled(opts.cfg)) return { ok: false, skipped: true };
144
+ const params = factToParams(fact, opts);
145
+ if (!params.text && !params.id) return { ok: false, skipped: false, error: { code: "BAD_REQUEST", message: "empty fact" } };
146
+
147
+ const c = configFromAgent(opts.cfg);
148
+ const tx = { base: c.base, token: c.token, fetchImpl: opts.fetchImpl };
149
+
150
+ // {id, expectedVersion} ⇒ CAS replace of an existing fact; otherwise append.
151
+ const isReplace = !!(params.id && (opts.expectedVersion != null || params.expectedVersion != null));
152
+ if (isReplace) {
153
+ const replaceParams = { ...params, expectedVersion: opts.expectedVersion ?? params.expectedVersion };
154
+ const frame = await knowledgeReplace(replaceParams, { ...tx, idempotencyKey: opts.idempotencyKey });
155
+ return shapeWrite(frame, "replace", params.id);
156
+ }
157
+
158
+ const frame = await knowledgeAppend(params, {
159
+ ...tx,
160
+ idempotencyKey: opts.idempotencyKey || (params.id ? `knowledge.append:${params.id}` : undefined),
161
+ });
162
+ return shapeWrite(frame, "append", params.id);
163
+ }
164
+
165
+ /**
166
+ * Rewrite a fact in place (knowledge.rewrite) — DESIGNATED-OWNER-ONLY. Distinct
167
+ * from remember()'s CAS path: rewrite is the owner asserting authorship, not a
168
+ * versioned update; the server enforces ownership and rejects a non-owner. Use
169
+ * sparingly — most updates should append (provenance-preserving) or CAS-replace.
170
+ *
171
+ * @param {string} id
172
+ * @param {string|{text:string,...}} fact
173
+ * @param {object} opts - { cfg, group?, provenance?, idempotencyKey?, fetchImpl? }
174
+ * @returns {Promise<{ok:boolean, skipped?:boolean, mode?:'rewrite', id?:string, result?:any, error?:object}>}
175
+ */
176
+ export async function rewrite(id, fact, opts = {}) {
177
+ if (!isEnabled(opts.cfg)) return { ok: false, skipped: true };
178
+ if (!id) return { ok: false, skipped: false, error: { code: "BAD_REQUEST", message: "missing id" } };
179
+ const params = { ...factToParams(fact, opts), id: String(id) };
180
+ const c = configFromAgent(opts.cfg);
181
+ const frame = await knowledgeRewrite(params, {
182
+ base: c.base, token: c.token, idempotencyKey: opts.idempotencyKey, fetchImpl: opts.fetchImpl,
183
+ });
184
+ return shapeWrite(frame, "rewrite", params.id);
185
+ }
186
+
187
+ // ---------------------------------------------------------------------------
188
+ // recall — the org-RAG read (ACL-floored by the server; the client never filters)
189
+ // ---------------------------------------------------------------------------
190
+
191
+ /**
192
+ * Recall shared knowledge for a query — the org-wide RAG source. Calls
193
+ * `knowledge.search` and returns the facts the SERVER chose to return after
194
+ * applying the non-bypassable RLS floor. The client performs NO ACL filtering:
195
+ * whatever facts come back are, by construction, the ones this agent's verified
196
+ * groups may see (barrier:<cell> deny-override already applied server-side).
197
+ *
198
+ * This is the call an agent's context-assembly makes to pull org knowledge into a
199
+ * prompt — drop it alongside the local lib/collective recall. Because every
200
+ * retrieval is audited server-side (org_events family 'knowledge'), do not loop
201
+ * it gratuitously; one query per context build is the intended cadence.
202
+ *
203
+ * The `{group}` option is a scoping HINT to the server (it can only shrink the
204
+ * result, never widen it past the floor). `lexical` flags that a keyword/lexical
205
+ * match was requested — an acceptable phase-4 stand-in for vector search, which
206
+ * the server notes; ranking/embedding is the server's job either way.
207
+ *
208
+ * Fail-open: a disabled/unreachable server yields []. Never throws.
209
+ *
210
+ * @param {string} query natural-language or keyword query
211
+ * @param {object} opts - {
212
+ * cfg, group?, limit?, kind?, includeInvalid?, lexical?, idempotencyKey?, fetchImpl?
213
+ * }
214
+ * @returns {Promise<object[]>} the ACL-visible facts (server-filtered), or []
215
+ */
216
+ export async function recall(query, opts = {}) {
217
+ const r = await recallDetailed(query, opts);
218
+ return r.facts;
219
+ }
220
+
221
+ /**
222
+ * Like recall(), but returns the full retrieval envelope the server reported:
223
+ * `{ ok, facts, returnedIds, groupsConsidered }`. `returnedIds`/`groupsConsidered`
224
+ * mirror the read-audit row the server wrote — useful for surfacing provenance
225
+ * (e.g. "answered from facts X,Y across groups org,unit:eng") without a second
226
+ * call, and for the cascade/blast-radius drill. Still does no client-side ACL
227
+ * filtering. Fail-open: yields `{ok:false, facts:[]}`.
228
+ *
229
+ * @param {string} query
230
+ * @param {object} opts - see recall()
231
+ * @returns {Promise<{ok:boolean, facts:object[], returnedIds:string[], groupsConsidered:string[], error?:object}>}
232
+ */
233
+ export async function recallDetailed(query, opts = {}) {
234
+ const empty = { ok: false, facts: [], returnedIds: [], groupsConsidered: [] };
235
+ if (!isEnabled(opts.cfg)) return empty;
236
+ const q = query == null ? "" : String(query);
237
+ if (!q.trim()) return empty;
238
+
239
+ const params = { query: q };
240
+ const group = normalizeGroup(opts.group);
241
+ if (group) params.group = group;
242
+ params.limit = Number.isFinite(opts.limit) && opts.limit > 0 ? Math.floor(opts.limit) : DEFAULT_RECALL_LIMIT;
243
+ if (opts.kind) params.kind = String(opts.kind);
244
+ if (opts.includeInvalid) params.includeInvalid = true;
245
+ if (opts.lexical) params.lexical = true;
246
+
247
+ const c = configFromAgent(opts.cfg);
248
+ const frame = await knowledgeSearch(params, {
249
+ base: c.base, token: c.token, idempotencyKey: opts.idempotencyKey, fetchImpl: opts.fetchImpl,
250
+ });
251
+ if (!frame || !frame.ok) {
252
+ return { ok: false, facts: [], returnedIds: [], groupsConsidered: [], error: frame && frame.error };
253
+ }
254
+ const result = frame.result || {};
255
+ // Render WHATEVER the server returned. We do NOT re-derive, re-sort, or filter
256
+ // by group — the server already applied the RLS floor. We only coerce shapes.
257
+ const facts = pickArray(result, ["facts", "results", "items"]);
258
+ const returnedIds = Array.isArray(result.returned_ids)
259
+ ? result.returned_ids.map(String)
260
+ : facts.map((f) => (f && (f.id != null ? String(f.id) : null))).filter(Boolean);
261
+ const groupsConsidered = Array.isArray(result.groups_considered) ? result.groups_considered.map(String) : [];
262
+ return { ok: true, facts, returnedIds, groupsConsidered };
263
+ }
264
+
265
+ // ---------------------------------------------------------------------------
266
+ // forget — invalidate (tombstone), never hard-delete
267
+ // ---------------------------------------------------------------------------
268
+
269
+ /**
270
+ * Forget a fact — INVALIDATE, DON'T DELETE. Routes to `knowledge.invalidate`:
271
+ * the server marks the fact invalid (provenance + tombstone) and excludes it from
272
+ * future recall, but the ROW PERSISTS for audit and the cascade/blast-radius
273
+ * drill (provenance can still enumerate everyone who read the bad fact). There is
274
+ * no client-side delete and no server hard-delete in this plane.
275
+ *
276
+ * Fail-open: disabled ⇒ `{ok:false, skipped:true}`. Never throws.
277
+ *
278
+ * @param {string} id the fact id to invalidate
279
+ * @param {object} opts - { cfg, reason?, supersededBy?, idempotencyKey?, fetchImpl? }
280
+ * @returns {Promise<{ok:boolean, skipped?:boolean, id?:string, result?:any, error?:object}>}
281
+ */
282
+ export async function forget(id, opts = {}) {
283
+ if (!isEnabled(opts.cfg)) return { ok: false, skipped: true };
284
+ if (!id) return { ok: false, skipped: false, error: { code: "BAD_REQUEST", message: "missing id" } };
285
+ const c = configFromAgent(opts.cfg);
286
+ const params = { id: String(id) };
287
+ if (opts.reason) params.reason = String(opts.reason);
288
+ if (opts.supersededBy) params.supersededBy = String(opts.supersededBy);
289
+ const frame = await knowledgeInvalidate(params, {
290
+ base: c.base,
291
+ token: c.token,
292
+ idempotencyKey: opts.idempotencyKey || `knowledge.invalidate:${params.id}`,
293
+ fetchImpl: opts.fetchImpl,
294
+ });
295
+ return shapeWrite(frame, "invalidate", params.id);
296
+ }
297
+
298
+ // ---------------------------------------------------------------------------
299
+ // contacts + meetings (ACL-filtered registries on the same plane)
300
+ // ---------------------------------------------------------------------------
301
+
302
+ /**
303
+ * Upsert an org contact into the shared registry (contacts.upsert). Idempotent.
304
+ * ACL-filtered on read by the server like every other knowledge surface. Fail-open.
305
+ * @param {object} contact - { id?, name?, emails?, phones?, handles?, org?, group?, fields? }
306
+ * @param {object} opts - { cfg, idempotencyKey?, fetchImpl? }
307
+ * @returns {Promise<{ok:boolean, skipped?:boolean, id?:string, result?:any, error?:object}>}
308
+ */
309
+ export async function upsertContact(contact, opts = {}) {
310
+ if (!isEnabled(opts.cfg)) return { ok: false, skipped: true };
311
+ const c = configFromAgent(opts.cfg);
312
+ const params = contact && typeof contact === "object" ? { ...contact } : {};
313
+ const group = normalizeGroup(params.group);
314
+ if (group) params.group = group; else delete params.group;
315
+ const frame = await contactsUpsert(params, {
316
+ base: c.base,
317
+ token: c.token,
318
+ idempotencyKey: opts.idempotencyKey || (params.id ? `contacts.upsert:${params.id}` : undefined),
319
+ fetchImpl: opts.fetchImpl,
320
+ });
321
+ return shapeWrite(frame, "contact", params.id, "contacts.upsert");
322
+ }
323
+
324
+ /**
325
+ * List org contacts the agent may see (contacts.list). The SERVER ACL-filters;
326
+ * the client renders the list as-is. Returns [] when disabled or on failure.
327
+ * @param {object} opts - { cfg, q?, group?, limit?, fetchImpl? }
328
+ * @returns {Promise<object[]>}
329
+ */
330
+ export async function listContacts(opts = {}) {
331
+ if (!isEnabled(opts.cfg)) return [];
332
+ const c = configFromAgent(opts.cfg);
333
+ return contactsList({
334
+ base: c.base, token: c.token, fetchImpl: opts.fetchImpl,
335
+ q: opts.q, group: normalizeGroup(opts.group), limit: opts.limit,
336
+ });
337
+ }
338
+
339
+ /**
340
+ * Record a meeting into the shared registry (meetings.record). Idempotent. The
341
+ * server derives a participant ACL for the meeting fact. Fail-open.
342
+ * @param {object} meeting - { id?, title?, at?, participants?, notes?, group?, refs?, fields? }
343
+ * @param {object} opts - { cfg, idempotencyKey?, fetchImpl? }
344
+ * @returns {Promise<{ok:boolean, skipped?:boolean, id?:string, result?:any, error?:object}>}
345
+ */
346
+ export async function recordMeeting(meeting, opts = {}) {
347
+ if (!isEnabled(opts.cfg)) return { ok: false, skipped: true };
348
+ const c = configFromAgent(opts.cfg);
349
+ const params = meeting && typeof meeting === "object" ? { ...meeting } : {};
350
+ const group = normalizeGroup(params.group);
351
+ if (group) params.group = group; else delete params.group;
352
+ const frame = await meetingsRecord(params, {
353
+ base: c.base,
354
+ token: c.token,
355
+ idempotencyKey: opts.idempotencyKey || (params.id ? `meetings.record:${params.id}` : undefined),
356
+ fetchImpl: opts.fetchImpl,
357
+ });
358
+ return shapeWrite(frame, "meeting", params.id, "meetings.record");
359
+ }
360
+
361
+ /**
362
+ * List org meetings the agent may see (meetings.list). The SERVER ACL-filters
363
+ * (participant-derived). Returns [] when disabled or on failure.
364
+ * @param {object} opts - { cfg, q?, group?, since?, limit?, fetchImpl? }
365
+ * @returns {Promise<object[]>}
366
+ */
367
+ export async function listMeetings(opts = {}) {
368
+ if (!isEnabled(opts.cfg)) return [];
369
+ const c = configFromAgent(opts.cfg);
370
+ return meetingsList({
371
+ base: c.base, token: c.token, fetchImpl: opts.fetchImpl,
372
+ q: opts.q, group: normalizeGroup(opts.group), since: opts.since, limit: opts.limit,
373
+ });
374
+ }
375
+
376
+ // ---------------------------------------------------------------------------
377
+ // internals (pure shaping)
378
+ // ---------------------------------------------------------------------------
379
+
380
+ /** Coerce a fact arg (string text or fact object) + opts into the wire params. */
381
+ function factToParams(fact, opts = {}) {
382
+ const base = typeof fact === "string" ? { text: fact } : (fact && typeof fact === "object" ? { ...fact } : {});
383
+ // Pull through the structured options without letting opts plumbing leak.
384
+ if (opts.id != null && base.id == null) base.id = opts.id;
385
+ if (opts.kind != null && base.kind == null) base.kind = opts.kind;
386
+ if (opts.participants != null && base.participants == null) base.participants = opts.participants;
387
+ if (opts.provenance != null && base.provenance == null) base.provenance = opts.provenance;
388
+ if (opts.links != null && base.links == null) base.links = opts.links;
389
+ if (opts.refs != null && base.refs == null) base.refs = opts.refs;
390
+ if (opts.expectedVersion != null && base.expectedVersion == null) base.expectedVersion = opts.expectedVersion;
391
+ const group = normalizeGroup(opts.group != null ? opts.group : base.group);
392
+ if (group) base.group = group; else delete base.group;
393
+ if (base.id != null) base.id = String(base.id);
394
+ return base;
395
+ }
396
+
397
+ /** Methods that have already emitted their one-shot "server does not implement" warning. */
398
+ const _unimplementedWarned = new Set();
399
+
400
+ /**
401
+ * Loudly, ONCE per method, surface that the org server has no handler for a
402
+ * write the agent attempted (dispatch returns NOT_FOUND). Silently swallowing
403
+ * this (as the old wrappers did) hides a real capability gap — the doctor and
404
+ * the operator need to see it. Fail-open: writing the warning never throws.
405
+ * @param {string} method the wire method (e.g. "contacts.upsert")
406
+ */
407
+ function warnUnimplemented(method) {
408
+ if (_unimplementedWarned.has(method)) return;
409
+ _unimplementedWarned.add(method);
410
+ try {
411
+ // eslint-disable-next-line no-console
412
+ console.warn(
413
+ `[maestro/org] the org server does not implement ${method} (NOT_FOUND) — ` +
414
+ `this write was dropped. Upgrade Cohort or run \`maestro doctor\` for detail.`
415
+ );
416
+ } catch { /* fail-open */ }
417
+ }
418
+
419
+ /**
420
+ * Normalise a write res frame into the module's `{ok, mode, id, result|error}`
421
+ * shape. When the server returns NOT_FOUND (the method's handler lane is not
422
+ * built), the result is flagged `unimplemented:true` AND a one-shot warning is
423
+ * emitted, so a genuine capability gap is never swallowed silently.
424
+ * @param {object} frame the res frame
425
+ * @param {string} mode the surface label (e.g. "contact", "meeting")
426
+ * @param {string} [id]
427
+ * @param {string} [method] the wire method, for the unimplemented warning
428
+ */
429
+ function shapeWrite(frame, mode, id, method) {
430
+ const ok = !!(frame && frame.ok);
431
+ const result = ok ? (frame.result ?? null) : undefined;
432
+ const resolvedId = (result && result.id) || id || undefined;
433
+ if (ok) return { ok: true, mode, id: resolvedId, result };
434
+ const error = (frame && frame.error) || { code: "INTERNAL", message: "no frame" };
435
+ if (error.code === "NOT_FOUND") {
436
+ if (method) warnUnimplemented(method);
437
+ return { ok: false, mode, id: resolvedId, unimplemented: true, error };
438
+ }
439
+ return { ok: false, mode, id: resolvedId, error };
440
+ }
441
+
442
+ /** Return the first array found under the given keys, else []. */
443
+ function pickArray(obj, keys) {
444
+ if (Array.isArray(obj)) return obj;
445
+ if (!obj || typeof obj !== "object") return [];
446
+ for (const k of keys) if (Array.isArray(obj[k])) return obj[k];
447
+ return [];
448
+ }
449
+
450
+ export const _internals = { factToParams, shapeWrite, pickArray, DEFAULT_RECALL_LIMIT };
451
+
452
+ export default {
453
+ remember,
454
+ rewrite,
455
+ recall,
456
+ recallDetailed,
457
+ forget,
458
+ upsertContact,
459
+ listContacts,
460
+ recordMeeting,
461
+ listMeetings,
462
+ normalizeGroup,
463
+ };