@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,111 @@
1
+ /**
2
+ * check-no-build-artifacts.mjs — packaging hygiene ratchet (Phase 0 item 0.5).
3
+ *
4
+ * The npm tarball ships everything under the package.json `files[]` allowlist,
5
+ * which includes `scripts/`. Two artifact classes must never be tracked there:
6
+ *
7
+ * 1. Python bytecode (`*.pyc`, `*.pyo`, anything under `__pycache__/`). Beyond
8
+ * being build output, the original instance shipped cross-tenant bytecode
9
+ * (e.g. `send-email-as-principal.cpython-313.pyc`) inside the tarball — a
10
+ * confidentiality leak that source-level scrubbing alone would miss.
11
+ * 2. Symlinks. A tracked symlink resolves only on the author's machine
12
+ * (the broken `validate_outbound.py -> /Users/agent/...` symlink silently
13
+ * disabled Layer-0 outbound validation on every other machine) and cannot
14
+ * survive `npm pack`/install intact. Ship real files, never links.
15
+ *
16
+ * Source of truth is `git ls-files -s` (the index), so this catches artifacts
17
+ * the moment they are staged, before they can be published.
18
+ *
19
+ * Pure, dependency-light: Node builtins only. ESM.
20
+ *
21
+ * Usage: `node scripts/ci/check-no-build-artifacts.mjs` (exit 0 ok / 1 found)
22
+ * @module scripts/ci/check-no-build-artifacts
23
+ */
24
+
25
+ "use strict";
26
+
27
+ import { execFileSync } from "node:child_process";
28
+ import path from "node:path";
29
+ import { fileURLToPath } from "node:url";
30
+
31
+ const REPO_ROOT = path.resolve(fileURLToPath(new URL(".", import.meta.url)), "..", "..");
32
+
33
+ /** Tracked-path patterns that must never appear in the index. @type {Array<{label:string, re:RegExp}>} */
34
+ export const ARTIFACT_PATTERNS = [
35
+ { label: "python bytecode (*.pyc)", re: /\.pyc$/ },
36
+ { label: "python bytecode (*.pyo)", re: /\.pyo$/ },
37
+ { label: "bytecode cache dir (__pycache__)", re: /(^|\/)__pycache__(\/|$)/ },
38
+ ];
39
+
40
+ /** git's mode for a symbolic link entry in `git ls-files -s`. */
41
+ const GIT_SYMLINK_MODE = "120000";
42
+
43
+ /**
44
+ * Parse `git ls-files -s` output into {mode, path} rows. Each line is:
45
+ * <mode> <object> <stage>\t<path>
46
+ * @param {string} stdout
47
+ * @returns {Array<{mode:string, path:string}>}
48
+ */
49
+ export function parseLsFiles(stdout) {
50
+ const rows = [];
51
+ for (const line of stdout.split("\n")) {
52
+ if (!line) continue;
53
+ const tab = line.indexOf("\t");
54
+ if (tab === -1) continue;
55
+ const meta = line.slice(0, tab).split(/\s+/);
56
+ const file = line.slice(tab + 1);
57
+ rows.push({ mode: meta[0] || "", path: file });
58
+ }
59
+ return rows;
60
+ }
61
+
62
+ /**
63
+ * @param {object} [opts] @param {string} [opts.cwd=REPO_ROOT]
64
+ * @returns {Array<{ file: string, reason: string }>}
65
+ */
66
+ export function findArtifacts(opts = {}) {
67
+ const cwd = opts.cwd || REPO_ROOT;
68
+ let stdout;
69
+ try {
70
+ stdout = execFileSync("git", ["ls-files", "-s"], { cwd, encoding: "utf8", maxBuffer: 64 * 1024 * 1024 });
71
+ } catch (err) {
72
+ // No git / not a work tree: cannot assess, fail closed.
73
+ throw new Error(`git ls-files failed: ${err && err.message ? err.message : err}`);
74
+ }
75
+ const offenders = [];
76
+ for (const { mode, path: file } of parseLsFiles(stdout)) {
77
+ if (mode === GIT_SYMLINK_MODE) {
78
+ offenders.push({ file, reason: "tracked symlink (does not survive npm pack; may point cross-tenant)" });
79
+ continue;
80
+ }
81
+ for (const p of ARTIFACT_PATTERNS) {
82
+ if (p.re.test(file)) {
83
+ offenders.push({ file, reason: p.label });
84
+ break;
85
+ }
86
+ }
87
+ }
88
+ return offenders;
89
+ }
90
+
91
+ /** @param {string} [cwd=REPO_ROOT] @returns {Promise<number>} */
92
+ export async function run(cwd = REPO_ROOT) {
93
+ let offenders;
94
+ try {
95
+ offenders = findArtifacts({ cwd });
96
+ } catch (err) {
97
+ console.error(`check-no-build-artifacts: ERROR — ${err.message}`);
98
+ return 2;
99
+ }
100
+ if (offenders.length === 0) {
101
+ console.log("check-no-build-artifacts: OK (no tracked bytecode or symlinks)");
102
+ return 0;
103
+ }
104
+ console.error("check-no-build-artifacts: FAIL — packaging artifacts tracked in the index:");
105
+ for (const o of offenders) console.error(` ${o.file} :: ${o.reason}`);
106
+ return 1;
107
+ }
108
+
109
+ if (import.meta.url === `file://${process.argv[1]}`) {
110
+ run().then((c) => process.exit(c)).catch((e) => { console.error("check-no-build-artifacts: ERROR", e && e.message ? e.message : e); process.exit(2); });
111
+ }
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Tests for check-no-build-artifacts.mjs — packaging hygiene guard.
3
+ * Pure-function level (parseLsFiles + pattern matching); no git invocation.
4
+ * @module scripts/ci/check-no-build-artifacts.test
5
+ */
6
+
7
+ import { describe, it } from "node:test";
8
+ import assert from "node:assert/strict";
9
+ import { parseLsFiles, ARTIFACT_PATTERNS } from "./check-no-build-artifacts.mjs";
10
+
11
+ /** Re-implement the offender classification over parsed rows (mirrors findArtifacts' inner loop). */
12
+ function classify(rows) {
13
+ const out = [];
14
+ for (const { mode, path: file } of rows) {
15
+ if (mode === "120000") { out.push({ file, reason: "symlink" }); continue; }
16
+ for (const p of ARTIFACT_PATTERNS) if (p.re.test(file)) { out.push({ file, reason: p.label }); break; }
17
+ }
18
+ return out;
19
+ }
20
+
21
+ describe("check-no-build-artifacts: parseLsFiles", () => {
22
+ it("parses mode + path from `git ls-files -s` rows", () => {
23
+ const stdout = [
24
+ "100644 abc123 0\tlib/index.js",
25
+ "120000 def456 0\tscripts/validate_outbound.py",
26
+ "100755 aaa111 0\tscripts/send-email.sh",
27
+ ].join("\n");
28
+ const rows = parseLsFiles(stdout);
29
+ assert.equal(rows.length, 3);
30
+ assert.deepEqual(rows[0], { mode: "100644", path: "lib/index.js" });
31
+ assert.equal(rows[1].mode, "120000");
32
+ assert.equal(rows[1].path, "scripts/validate_outbound.py");
33
+ });
34
+
35
+ it("ignores blank lines and malformed rows (no tab)", () => {
36
+ const rows = parseLsFiles("\n100644 abc 0\tok.js\ngarbage-no-tab\n");
37
+ assert.equal(rows.length, 1);
38
+ assert.equal(rows[0].path, "ok.js");
39
+ });
40
+
41
+ it("preserves paths containing spaces (split only on the first tab)", () => {
42
+ const rows = parseLsFiles("100644 abc 0\tdocs/a file with spaces.md");
43
+ assert.equal(rows[0].path, "docs/a file with spaces.md");
44
+ });
45
+ });
46
+
47
+ describe("check-no-build-artifacts: classification", () => {
48
+ it("flags tracked symlinks", () => {
49
+ const off = classify(parseLsFiles("120000 x 0\tscripts/validate_outbound.py"));
50
+ assert.equal(off.length, 1);
51
+ assert.equal(off[0].reason, "symlink");
52
+ });
53
+
54
+ it("flags .pyc, .pyo, and __pycache__ paths", () => {
55
+ const off = classify(parseLsFiles([
56
+ "100644 a 0\tscripts/__pycache__/x.cpython-313.pyc",
57
+ "100644 b 0\tscripts/foo.pyo",
58
+ "100644 c 0\tscripts/__pycache__/bar.py",
59
+ ].join("\n")));
60
+ assert.equal(off.length, 3);
61
+ });
62
+
63
+ it("passes clean trees (real source files, executable shell)", () => {
64
+ const off = classify(parseLsFiles([
65
+ "100644 a 0\tlib/index.js",
66
+ "100755 b 0\tscripts/send-email.sh",
67
+ "100644 c 0\tscripts/validate_outbound.py",
68
+ ].join("\n")));
69
+ assert.equal(off.length, 0);
70
+ });
71
+ });
@@ -0,0 +1,198 @@
1
+ /**
2
+ * check-no-confidential.mjs — CI guard that fails if confidential instance data
3
+ * would ship in the published npm tarball.
4
+ *
5
+ * Why this exists: `@cohortapp/agent-sdk` is a *framework* published (publicly) to
6
+ * npm and copied into every agent repo. It must never carry one instance's
7
+ * confidential business data. A path-based prune (`files[]` + `.npmignore`) is
8
+ * necessary but NOT sufficient — confidential markers leak into otherwise-
9
+ * legitimate framework files (e.g. architecture docs that use real M&A targets
10
+ * as examples). This guard inspects the *contents* of every file that would
11
+ * actually ship (`npm pack --dry-run --json`) for a denylist of markers and
12
+ * fails closed.
13
+ *
14
+ * IMPORTANT — the denylist is NOT hardcoded here. A content-denylist that
15
+ * embeds the confidential terms would itself become the leak it prevents (a
16
+ * shipped file that literally lists the protected names). The sensitive
17
+ * markers live in `<repo>/.confidential-patterns.json`, which is deliberately
18
+ * NOT shipped (absent from files[]; listed in .npmignore). This source file
19
+ * contains only safe, generic structural logic. If that denylist file is
20
+ * absent (e.g. in an installed package or a fork), the content scan is skipped
21
+ * with a warning and only the generic path check runs.
22
+ *
23
+ * Scope note: the denylist is the genuinely-confidential set (named live
24
+ * acquisition targets, their principals, entity registration numbers) — NOT
25
+ * pervasive instance identity (the original Sophie/Mehran/Adaptic deployment). De-
26
+ * identifying those is the check-no-residual-identity guard's job.
27
+ *
28
+ * Pure, dependency-light: Node builtins only. ESM ("type":"module").
29
+ *
30
+ * Usage: `node scripts/ci/check-no-confidential.mjs`
31
+ * exit 0 → clean; exit 1 → confidential content would ship; exit 2 → could
32
+ * not run `npm pack` (fail closed for a security guard).
33
+ *
34
+ * @module scripts/ci/check-no-confidential
35
+ */
36
+
37
+ "use strict";
38
+
39
+ import { execFileSync } from "node:child_process";
40
+ import { readFileSync, existsSync } from "node:fs";
41
+ import path from "node:path";
42
+ import { fileURLToPath } from "node:url";
43
+
44
+ /** Repo root: two levels up from scripts/ci/. @type {string} */
45
+ const REPO_ROOT = path.resolve(fileURLToPath(new URL(".", import.meta.url)), "..", "..");
46
+
47
+ /** Non-shipped denylist file (see header). @type {string} */
48
+ export const DENYLIST_RELATIVE = ".confidential-patterns.json";
49
+
50
+ /**
51
+ * Generic, safe-to-ship path markers (directory/category names, not the
52
+ * confidential association itself). Defense-in-depth against re-adding a
53
+ * `docs/` blanket to files[].
54
+ * @type {RegExp}
55
+ */
56
+ export const DENY_PATH_RE = /(?:^|\/)business-synthesis\/|ownership-structure|final-ownership/i;
57
+
58
+ /** Extensions whose contents are scanned (text formats only). @type {Set<string>} */
59
+ export const TEXT_EXT = new Set([
60
+ ".md", ".markdown", ".json", ".yaml", ".yml", ".js", ".mjs", ".cjs",
61
+ ".ts", ".txt", ".html", ".htm", ".latex", ".tex", ".sh", ".py", ".env", ".example",
62
+ ]);
63
+
64
+ /**
65
+ * Load and compile content patterns from the non-shipped denylist file.
66
+ *
67
+ * @param {string} [cwd=REPO_ROOT]
68
+ * @returns {{ patterns: Array<{ label: string, re: RegExp }>, present: boolean }}
69
+ */
70
+ export function loadContentPatterns(cwd = REPO_ROOT) {
71
+ const file = path.join(cwd, DENYLIST_RELATIVE);
72
+ if (!existsSync(file)) return { patterns: [], present: false };
73
+ const raw = JSON.parse(readFileSync(file, "utf8"));
74
+ const patterns = (raw.contentPatterns || []).map((p) => ({
75
+ label: p.label || "confidential marker",
76
+ re: new RegExp(p.pattern, p.flags || ""),
77
+ }));
78
+ return { patterns, present: true };
79
+ }
80
+
81
+ /**
82
+ * Scan a single text blob for confidential markers. Pure (no I/O) — unit-testable.
83
+ *
84
+ * @param {string} text
85
+ * @param {Array<{ label: string, re: RegExp }>} patterns
86
+ * @returns {Array<{ label: string, match: string }>}
87
+ */
88
+ export function scanText(text, patterns) {
89
+ if (typeof text !== "string" || text.length === 0 || !Array.isArray(patterns)) return [];
90
+ const hits = [];
91
+ for (const p of patterns) {
92
+ const m = text.match(p.re);
93
+ if (m) hits.push({ label: p.label, match: m[0] });
94
+ }
95
+ return hits;
96
+ }
97
+
98
+ /**
99
+ * Ask npm which files the tarball would contain.
100
+ *
101
+ * @param {string} [cwd=REPO_ROOT]
102
+ * @returns {string[]} relative paths
103
+ */
104
+ export function listPackedFiles(cwd = REPO_ROOT) {
105
+ const out = execFileSync("npm", ["pack", "--dry-run", "--json"], {
106
+ cwd,
107
+ encoding: "utf8",
108
+ maxBuffer: 32 * 1024 * 1024,
109
+ stdio: ["ignore", "pipe", "ignore"],
110
+ });
111
+ const parsed = JSON.parse(out);
112
+ const entry = Array.isArray(parsed) ? parsed[0] : parsed;
113
+ const files = (entry && entry.files) || [];
114
+ return files.map((f) => f.path).filter((p) => typeof p === "string");
115
+ }
116
+
117
+ /**
118
+ * Inspect every would-ship file for confidential paths/content.
119
+ *
120
+ * @param {object} [opts]
121
+ * @param {string} [opts.cwd=REPO_ROOT]
122
+ * @param {string[]} [opts.files] - Pre-computed packed file list (skips npm pack).
123
+ * @param {Array<{ label: string, re: RegExp }>} [opts.patterns] - Pre-loaded content patterns.
124
+ * @returns {{ ok: boolean, scanned: number, denylistPresent: boolean, pathHits: string[], contentHits: Array<{ file: string, label: string, match: string }> }}
125
+ */
126
+ export function scanPackedForConfidential(opts = {}) {
127
+ const cwd = opts.cwd || REPO_ROOT;
128
+ const files = opts.files || listPackedFiles(cwd);
129
+ let patterns = opts.patterns;
130
+ let denylistPresent = true;
131
+ if (!patterns) {
132
+ const loaded = loadContentPatterns(cwd);
133
+ patterns = loaded.patterns;
134
+ denylistPresent = loaded.present;
135
+ }
136
+ const pathHits = files.filter((f) => DENY_PATH_RE.test(f));
137
+ const contentHits = [];
138
+ let scanned = 0;
139
+ if (patterns.length > 0) {
140
+ for (const rel of files) {
141
+ const ext = path.extname(rel).toLowerCase();
142
+ if (!TEXT_EXT.has(ext)) continue;
143
+ const abs = path.resolve(cwd, rel);
144
+ if (!existsSync(abs)) continue;
145
+ let body;
146
+ try {
147
+ body = readFileSync(abs, "utf8");
148
+ } catch {
149
+ continue;
150
+ }
151
+ scanned++;
152
+ for (const hit of scanText(body, patterns)) {
153
+ contentHits.push({ file: rel, label: hit.label, match: hit.match });
154
+ }
155
+ }
156
+ }
157
+ return { ok: pathHits.length === 0 && contentHits.length === 0, scanned, denylistPresent, pathHits, contentHits };
158
+ }
159
+
160
+ /**
161
+ * Run the guard and print a human report.
162
+ *
163
+ * @param {string} [cwd=REPO_ROOT]
164
+ * @returns {Promise<number>} exit code (0 ok, 1 leak found, 2 could not run).
165
+ */
166
+ export async function run(cwd = REPO_ROOT) {
167
+ let result;
168
+ try {
169
+ result = scanPackedForConfidential({ cwd });
170
+ } catch (err) {
171
+ console.error("check-no-confidential: ERROR — could not run `npm pack --dry-run --json` (failing closed):", err && err.message ? err.message : err);
172
+ return 2;
173
+ }
174
+ const { ok, scanned, denylistPresent, pathHits, contentHits } = result;
175
+ if (!denylistPresent) {
176
+ console.warn(`check-no-confidential: WARN — ${DENYLIST_RELATIVE} not present; ran path-only scan (content scan skipped).`);
177
+ }
178
+ if (ok) {
179
+ const mode = denylistPresent ? `${scanned} packed text files scanned` : "path-only";
180
+ console.log(`check-no-confidential: OK (${mode}; no confidential markers)`);
181
+ return 0;
182
+ }
183
+ console.error("check-no-confidential: FAIL — confidential content would ship in the npm tarball:");
184
+ for (const p of pathHits) console.error(` [path] ${p}`);
185
+ for (const c of contentHits) console.error(` [content] ${c.file} :: ${c.label} ("${c.match}")`);
186
+ console.error(`check-no-confidential: ${pathHits.length} path hit(s) + ${contentHits.length} content hit(s)`);
187
+ return 1;
188
+ }
189
+
190
+ // Run when invoked directly (not when imported).
191
+ if (import.meta.url === `file://${process.argv[1]}`) {
192
+ run()
193
+ .then((code) => process.exit(code))
194
+ .catch((err) => {
195
+ console.error("check-no-confidential: ERROR", err && err.message ? err.message : err);
196
+ process.exit(2);
197
+ });
198
+ }
@@ -0,0 +1,169 @@
1
+ /**
2
+ * check-no-conflict-markers.mjs — CI guard that fails if any tracked file
3
+ * contains a git merge-conflict marker.
4
+ *
5
+ * Ported/adapted from OpenClaw's scripts/check-no-conflict-markers.mjs idea.
6
+ * Pure, dependency-light: Node builtins + git (via execFile) only. ESM module
7
+ * (maestro is "type":"module").
8
+ *
9
+ * A successful `git merge` that hit a conflict leaves lines like
10
+ * `<<<<<<< HEAD`, `=======`, `>>>>>>> branch`, and (with merge.conflictStyle
11
+ * diff3) `||||||| base`. If one of those slips past review into a commit, the
12
+ * code may still parse but is semantically broken. This guard scans every
13
+ * tracked, text file for those exact markers and exits non-zero if found.
14
+ *
15
+ * Usage (standalone): `node scripts/ci/check-no-conflict-markers.mjs`
16
+ * exit 0 → clean; exit 1 → markers found (details printed to stderr).
17
+ *
18
+ * Programmatic: `import { findConflictMarkers, lineHasConflictMarker } from "./check-no-conflict-markers.mjs"`
19
+ *
20
+ * @module scripts/ci/check-no-conflict-markers
21
+ */
22
+
23
+ "use strict";
24
+
25
+ import { execFile } from "node:child_process";
26
+ import { promisify } from "node:util";
27
+ import { readFile } from "node:fs/promises";
28
+ import path from "node:path";
29
+ import { fileURLToPath } from "node:url";
30
+
31
+ const execFileAsync = promisify(execFile);
32
+
33
+ /** Repo root: two levels up from scripts/ci/. @type {string} */
34
+ const REPO_ROOT = path.resolve(fileURLToPath(new URL(".", import.meta.url)), "..", "..");
35
+
36
+ /**
37
+ * Conflict-marker prefixes. A line is a marker if, after stripping a trailing
38
+ * carriage return, it equals one of these or starts with one followed by a
39
+ * space. Markers are exactly seven repeated characters — we match the prefix
40
+ * and then require either end-of-line or a single space so that e.g. a markdown
41
+ * rule of eight or more `=` does not false-positive.
42
+ * @type {string[]}
43
+ */
44
+ const MARKER_PREFIXES = ["<<<<<<<", "=======", ">>>>>>>", "|||||||"];
45
+
46
+ /**
47
+ * True if a single line of text is a git conflict marker.
48
+ *
49
+ * @param {string} line - One line of file content (without the newline).
50
+ * @returns {boolean}
51
+ */
52
+ export function lineHasConflictMarker(line) {
53
+ if (typeof line !== "string") return false;
54
+ // Tolerate CRLF: drop a trailing carriage return.
55
+ const trimmed = line.endsWith("\r") ? line.slice(0, -1) : line;
56
+ for (const prefix of MARKER_PREFIXES) {
57
+ if (trimmed === prefix) return true;
58
+ if (trimmed.startsWith(prefix + " ")) return true;
59
+ }
60
+ return false;
61
+ }
62
+
63
+ /**
64
+ * Scan a blob of file content for conflict markers.
65
+ *
66
+ * @param {string} content - Full file text.
67
+ * @returns {Array<{ line: number, text: string }>} 1-based line hits.
68
+ */
69
+ export function scanContentForMarkers(content) {
70
+ if (typeof content !== "string" || content.length === 0) return [];
71
+ const hits = [];
72
+ const lines = content.split("\n");
73
+ for (let i = 0; i < lines.length; i++) {
74
+ if (lineHasConflictMarker(lines[i])) {
75
+ hits.push({ line: i + 1, text: lines[i].replace(/\r$/, "") });
76
+ }
77
+ }
78
+ return hits;
79
+ }
80
+
81
+ /**
82
+ * Heuristic: skip obviously-binary content so we don't read megabytes of
83
+ * images/audio looking for ASCII markers. A NUL byte in the first 8 KiB is the
84
+ * classic "this is binary" signal git itself uses.
85
+ *
86
+ * @param {Buffer} buf
87
+ * @returns {boolean}
88
+ */
89
+ function looksBinary(buf) {
90
+ const n = Math.min(buf.length, 8192);
91
+ for (let i = 0; i < n; i++) {
92
+ if (buf[i] === 0) return true;
93
+ }
94
+ return false;
95
+ }
96
+
97
+ /**
98
+ * List every tracked file path (relative to repo root) via git.
99
+ *
100
+ * @param {string} [cwd=REPO_ROOT]
101
+ * @returns {Promise<string[]>}
102
+ */
103
+ export async function listTrackedFiles(cwd = REPO_ROOT) {
104
+ // -z gives NUL-separated paths so filenames with spaces/newlines are safe.
105
+ const { stdout } = await execFileAsync("git", ["ls-files", "-z"], {
106
+ cwd,
107
+ maxBuffer: 64 * 1024 * 1024,
108
+ });
109
+ return stdout.split("\0").filter((p) => p.length > 0);
110
+ }
111
+
112
+ /**
113
+ * Scan all tracked files for conflict markers.
114
+ *
115
+ * @param {string} [cwd=REPO_ROOT]
116
+ * @returns {Promise<Array<{ file: string, hits: Array<{ line: number, text: string }> }>>}
117
+ * One entry per offending file. Empty array means the tree is clean.
118
+ */
119
+ export async function findConflictMarkers(cwd = REPO_ROOT) {
120
+ const files = await listTrackedFiles(cwd);
121
+ const offenders = [];
122
+ for (const rel of files) {
123
+ const abs = path.resolve(cwd, rel);
124
+ let buf;
125
+ try {
126
+ buf = await readFile(abs);
127
+ } catch {
128
+ // File tracked but missing on disk (sparse checkout, deleted-not-staged):
129
+ // nothing to scan, skip quietly.
130
+ continue;
131
+ }
132
+ if (looksBinary(buf)) continue;
133
+ const hits = scanContentForMarkers(buf.toString("utf8"));
134
+ if (hits.length > 0) offenders.push({ file: rel, hits });
135
+ }
136
+ return offenders;
137
+ }
138
+
139
+ /**
140
+ * Run the check and print a human report.
141
+ *
142
+ * @param {string} [cwd=REPO_ROOT]
143
+ * @returns {Promise<number>} Process exit code (0 = clean, 1 = markers found).
144
+ */
145
+ export async function run(cwd = REPO_ROOT) {
146
+ const offenders = await findConflictMarkers(cwd);
147
+ if (offenders.length === 0) {
148
+ console.log("check-no-conflict-markers: OK (no conflict markers in tracked files)");
149
+ return 0;
150
+ }
151
+ console.error("check-no-conflict-markers: FAIL — conflict markers found:");
152
+ for (const { file, hits } of offenders) {
153
+ for (const h of hits) {
154
+ console.error(` ${file}:${h.line}: ${h.text}`);
155
+ }
156
+ }
157
+ console.error(`check-no-conflict-markers: ${offenders.length} file(s) contain conflict markers`);
158
+ return 1;
159
+ }
160
+
161
+ // Run when invoked directly (not when imported).
162
+ if (import.meta.url === `file://${process.argv[1]}`) {
163
+ run()
164
+ .then((code) => process.exit(code))
165
+ .catch((err) => {
166
+ console.error("check-no-conflict-markers: ERROR", err && err.message ? err.message : err);
167
+ process.exit(2);
168
+ });
169
+ }