@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,163 @@
1
+ /**
2
+ * check-no-residual-identity.mjs — de-identification ratchet.
3
+ *
4
+ * The framework is white-label: it must carry NO trace of its first instance's
5
+ * real identity (the Sophie / Mehran / Adaptic deployment). Once a path has been
6
+ * de-identified (tokenised with {{agent.*}}/{{company.*}} or rewritten
7
+ * persona-agnostic), it must STAY clean. This guard scans a curated list of
8
+ * already-de-identified paths for the original instance identity and fails on any
9
+ * regression. EXPAND `DE_IDENTIFIED_PATHS` as each increment de-identifies more of
10
+ * the corpus (triggers → agents → lib → templates → docs).
11
+ *
12
+ * These markers are the ORIGINAL client identity (NOT confidential data — that is
13
+ * the job of check-no-confidential.mjs), so they are safe to hardcode here. The
14
+ * generic placeholders the framework now ships (Northwind / Alex / Jordan etc.)
15
+ * are intentional examples and are NOT flagged.
16
+ *
17
+ * Pure, dependency-light: Node builtins only. ESM.
18
+ *
19
+ * Usage: `node scripts/ci/check-no-residual-identity.mjs` (exit 0 ok / 1 found)
20
+ * @module scripts/ci/check-no-residual-identity
21
+ */
22
+
23
+ "use strict";
24
+
25
+ import { readdirSync, readFileSync, existsSync, statSync } from "node:fs";
26
+ import path from "node:path";
27
+ import { fileURLToPath } from "node:url";
28
+
29
+ const REPO_ROOT = path.resolve(fileURLToPath(new URL(".", import.meta.url)), "..", "..");
30
+
31
+ /**
32
+ * Paths confirmed de-identified that must remain free of the original instance
33
+ * identity. Grow this list as increments land. 2.0 grew it with bin/, scripts/,
34
+ * scaffold/, and services/ (the §4.5 rebrand sweep cleaned their offenders).
35
+ * @type {string[]}
36
+ */
37
+ export const DE_IDENTIFIED_PATHS = [
38
+ "schedules/triggers",
39
+ "agents",
40
+ "lib",
41
+ "teams",
42
+ "bin",
43
+ "scripts",
44
+ "scaffold",
45
+ "services",
46
+ ];
47
+ /** @deprecated retained for back-compat with callers/tests referencing the old name. */
48
+ export const DE_SOPHIED_PATHS = DE_IDENTIFIED_PATHS;
49
+
50
+ /**
51
+ * SELF-EXEMPTION (the guard-of-the-guard). These two files carry identity
52
+ * tokens BY DESIGN — this guard's own IDENTITY_PATTERNS literals/labels/header
53
+ * doctrine, and check-no-confidential.mjs's scope-note naming what this guard
54
+ * covers — so scanning them can never come clean. They are skipped by exact
55
+ * repo-relative path. The policy assert below keeps this list from ever
56
+ * growing into a general escape hatch: every entry MUST be a scripts/ci/
57
+ * check-no-* guard, or the module throws at import.
58
+ * @type {string[]}
59
+ */
60
+ export const EXEMPT_FILES = [
61
+ "scripts/ci/check-no-residual-identity.mjs",
62
+ "scripts/ci/check-no-residual-identity.test.mjs", // seeds/asserts the markers by design
63
+ "scripts/ci/check-no-confidential.mjs",
64
+ ];
65
+
66
+ /**
67
+ * Enforce the exemption policy. Exported so the test can drive the throwing
68
+ * branch directly; invoked at module load over the real EXEMPT_FILES.
69
+ * @param {string[]} files
70
+ */
71
+ export function assertExemptPolicy(files) {
72
+ for (const f of files) {
73
+ if (!String(f).startsWith("scripts/ci/check-no-")) {
74
+ throw new Error(
75
+ `check-no-residual-identity: EXEMPT_FILES entry "${f}" is out of policy — ` +
76
+ "only scripts/ci/check-no-* guards may self-exempt (the list is not a general escape hatch)",
77
+ );
78
+ }
79
+ }
80
+ }
81
+ assertExemptPolicy(EXEMPT_FILES);
82
+
83
+ /** Original-instance identity markers the framework must not reintroduce. @type {Array<{label:string, re:RegExp}>} */
84
+ export const IDENTITY_PATTERNS = [
85
+ { label: "agent name (Sophie)", re: /\bSophie\b/i },
86
+ { label: "principal name (Mehran)", re: /\bMehran\b/i },
87
+ { label: "company (Adaptic)", re: /\bAdaptic\b/ },
88
+ { label: "surname (Granfar)", re: /\bGranfar\b/i },
89
+ { label: "surname (Nguyen)", re: /\bNguyen\b/i },
90
+ { label: "principal first name (Hootan)", re: /\bHootan\b/i },
91
+ { label: "colleague (Nima)", re: /\bNima\b/ },
92
+ { label: "instance regulator (DFSA)", re: /\bDFSA\b/ },
93
+ { label: "instance email (@adaptic.ai)", re: /@adaptic\.ai/i },
94
+ { label: "instance repo slug (sophie-ai)", re: /\bsophie-ai\b/i },
95
+ { label: "instance home path (/Users/sophie)", re: /\/Users\/sophie/i },
96
+ { label: "old package scope (@adaptic/)", re: /@adaptic\// },
97
+ ];
98
+
99
+ /** Scan a text blob for identity markers. Pure. @returns {Array<{label:string, match:string}>} */
100
+ export function scanIdentity(text) {
101
+ if (typeof text !== "string" || text.length === 0) return [];
102
+ const hits = [];
103
+ for (const p of IDENTITY_PATTERNS) {
104
+ const m = text.match(p.re);
105
+ if (m) hits.push({ label: p.label, match: m[0] });
106
+ }
107
+ return hits;
108
+ }
109
+
110
+ function walkFiles(dir) {
111
+ const out = [];
112
+ for (const name of readdirSync(dir)) {
113
+ if (name === "node_modules" || name === ".git") continue;
114
+ const p = path.join(dir, name);
115
+ let st;
116
+ try { st = statSync(p); } catch { continue; }
117
+ if (st.isDirectory()) out.push(...walkFiles(p));
118
+ else out.push(p);
119
+ }
120
+ return out;
121
+ }
122
+
123
+ /**
124
+ * @param {object} [opts] @param {string} [opts.cwd=REPO_ROOT] @param {string[]} [opts.dirs=DE_IDENTIFIED_PATHS]
125
+ * @returns {Array<{ file: string, hits: Array<{label:string, match:string}> }>}
126
+ */
127
+ export function findResidualIdentity(opts = {}) {
128
+ const cwd = opts.cwd || REPO_ROOT;
129
+ const dirs = opts.dirs || DE_IDENTIFIED_PATHS;
130
+ const exempt = new Set(opts.exemptFiles || EXEMPT_FILES);
131
+ const offenders = [];
132
+ for (const d of dirs) {
133
+ const abs = path.join(cwd, d);
134
+ if (!existsSync(abs)) continue;
135
+ for (const file of walkFiles(abs)) {
136
+ const rel = path.relative(cwd, file);
137
+ if (exempt.has(rel)) continue; // self-exemption (policy-asserted above)
138
+ let body;
139
+ try { body = readFileSync(file, "utf8"); } catch { continue; }
140
+ const hits = scanIdentity(body);
141
+ if (hits.length) offenders.push({ file: rel, hits });
142
+ }
143
+ }
144
+ return offenders;
145
+ }
146
+
147
+ /** @param {string} [cwd=REPO_ROOT] @returns {Promise<number>} */
148
+ export async function run(cwd = REPO_ROOT) {
149
+ const offenders = findResidualIdentity({ cwd });
150
+ if (offenders.length === 0) {
151
+ console.log(`check-no-residual-identity: OK (${DE_IDENTIFIED_PATHS.length} de-identified path(s) clean)`);
152
+ return 0;
153
+ }
154
+ console.error("check-no-residual-identity: FAIL — original instance identity reintroduced into de-identified paths:");
155
+ for (const o of offenders) {
156
+ for (const h of o.hits) console.error(` ${o.file} :: ${h.label} ("${h.match}")`);
157
+ }
158
+ return 1;
159
+ }
160
+
161
+ if (import.meta.url === `file://${process.argv[1]}`) {
162
+ run().then((c) => process.exit(c)).catch((e) => { console.error("check-no-residual-identity: ERROR", e && e.message ? e.message : e); process.exit(2); });
163
+ }
@@ -0,0 +1,89 @@
1
+ /**
2
+ * check-no-residual-identity.test.mjs — the de-identification ratchet's own
3
+ * guard-of-the-guard (2.0 §4.5(8)):
4
+ * (i) exempt files are skipped by the scan,
5
+ * (ii) an out-of-policy exemption entry throws (the list can never grow
6
+ * into a general escape hatch),
7
+ * (iii) a seeded marker in a tmp corpus still fails — the exemption did not
8
+ * blunt the ratchet.
9
+ * Run: node --test scripts/ci/check-no-residual-identity.test.mjs
10
+ */
11
+
12
+ "use strict";
13
+
14
+ import { test } from "node:test";
15
+ import assert from "node:assert/strict";
16
+ import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
17
+ import { tmpdir } from "node:os";
18
+ import { join } from "node:path";
19
+
20
+ import {
21
+ DE_IDENTIFIED_PATHS,
22
+ EXEMPT_FILES,
23
+ IDENTITY_PATTERNS,
24
+ assertExemptPolicy,
25
+ findResidualIdentity,
26
+ scanIdentity,
27
+ run,
28
+ } from "./check-no-residual-identity.mjs";
29
+
30
+ test("ratchet coverage: 2.0 grew the de-identified paths with bin/scripts/scaffold/services", () => {
31
+ for (const d of ["bin", "scripts", "scaffold", "services", "lib"]) {
32
+ assert.ok(DE_IDENTIFIED_PATHS.includes(d), `${d} ratcheted`);
33
+ }
34
+ assert.ok(
35
+ IDENTITY_PATTERNS.some((p) => p.label.includes("@adaptic/")),
36
+ "old package scope pattern present",
37
+ );
38
+ });
39
+
40
+ test("(i) exempt files are skipped: a marker inside an exempt path never offends", () => {
41
+ const cwd = mkdtempSync(join(tmpdir(), "ratchet-"));
42
+ mkdirSync(join(cwd, "scripts", "ci"), { recursive: true });
43
+ // The exempt guard file carries identity tokens BY DESIGN.
44
+ writeFileSync(join(cwd, "scripts", "ci", "check-no-residual-identity.mjs"), "// patterns: Sophie Mehran Adaptic\n");
45
+ writeFileSync(join(cwd, "scripts", "ci", "check-no-confidential.mjs"), "// scope note naming Sophie\n");
46
+ const offenders = findResidualIdentity({ cwd });
47
+ assert.deepEqual(offenders, [], "both exempt files skipped");
48
+ rmSync(cwd, { recursive: true, force: true });
49
+ });
50
+
51
+ test("(ii) an out-of-policy exemption entry throws at policy assert", () => {
52
+ assert.doesNotThrow(() => assertExemptPolicy(EXEMPT_FILES), "the real list is in policy");
53
+ assert.throws(
54
+ () => assertExemptPolicy(["lib/org/client.mjs"]),
55
+ /out of policy/,
56
+ "a non-guard path can never self-exempt",
57
+ );
58
+ assert.throws(() => assertExemptPolicy(["scripts/ci/run-tests.mjs"]), /out of policy/, "even scripts/ci files must be check-no-* guards");
59
+ for (const f of EXEMPT_FILES) {
60
+ assert.match(f, /^scripts\/ci\/check-no-/, `${f} matches the policy prefix`);
61
+ }
62
+ });
63
+
64
+ test("(iii) a seeded marker in a NON-exempt file still fails the ratchet", async () => {
65
+ const cwd = mkdtempSync(join(tmpdir(), "ratchet-"));
66
+ mkdirSync(join(cwd, "scripts", "daemon"), { recursive: true });
67
+ mkdirSync(join(cwd, "services", "x"), { recursive: true });
68
+ writeFileSync(join(cwd, "scripts", "daemon", "sneaky.mjs"), 'const who = "Sophie";\n');
69
+ writeFileSync(join(cwd, "services", "x", "pkg.json"), '{"name": "@adaptic/oops"}\n');
70
+ const offenders = findResidualIdentity({ cwd });
71
+ assert.equal(offenders.length, 2, "both seeded markers caught");
72
+ const labels = offenders.flatMap((o) => o.hits.map((h) => h.label)).join("|");
73
+ assert.match(labels, /Sophie/);
74
+ assert.match(labels, /@adaptic\//);
75
+ const code = await run(cwd);
76
+ assert.equal(code, 1, "run() exits non-zero on offenders");
77
+ rmSync(cwd, { recursive: true, force: true });
78
+ });
79
+
80
+ test("scanIdentity flags every 2.0 pattern incl. the package scope; placeholders stay clean", () => {
81
+ assert.ok(scanIdentity("npm i @adaptic/maestro").some((h) => /@adaptic\//.test(h.match)));
82
+ assert.equal(scanIdentity("Northwind's Alex and Jordan shipped it").length, 0, "generic placeholders are intentional");
83
+ assert.equal(scanIdentity("").length, 0);
84
+ });
85
+
86
+ test("the LIVE repo is clean under the expanded ratchet (the commit that lands it is green)", async () => {
87
+ const code = await run();
88
+ assert.equal(code, 0, "expanded ratchet must be green in-tree");
89
+ });
@@ -0,0 +1,205 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * check-tarball-fidelity.mjs — packaging fidelity guard (Phase 0 item 0.13c).
4
+ *
5
+ * `npm publish` ships whatever `npm pack` produces. The cheaper static guard
6
+ * `check-no-build-artifacts.mjs` inspects the git index; this one inspects the
7
+ * *actual tarball* — the bytes that reach the fleet via `npm update`. It runs a
8
+ * real `npm pack` into a tmp dir, extracts it, and asserts:
9
+ *
10
+ * 1. Completeness — every package.json `files[]` entry is represented in the
11
+ * tarball (a missing entry means agents install a broken tree, e.g. the
12
+ * relative `../../lib/...` imports the daemon depends on would 404).
13
+ * 2. Hygiene — the extracted tree contains no `node_modules/`, no Python
14
+ * bytecode (`*.pyc`/`*.pyo`/`__pycache__/`), and no symlinks (a tracked
15
+ * symlink resolves only on the author's machine and cannot survive
16
+ * pack/install; cf. the broken `validate_outbound.py` cross-tenant link).
17
+ * 3. Requireability — the package main (exports["."], default lib/index.js)
18
+ * is present in the extracted tree, so a consumer's `import` resolves.
19
+ *
20
+ * This is a SLOW check (it shells out to `npm pack` and `tar`), so it is wired
21
+ * as its own opt-in npm script (`npm run test:pack`) and is NOT part of the
22
+ * default fast `check`/`test` path. CI runs it best-effort.
23
+ *
24
+ * Node builtins + child_process only (maestro is "type":"module", near-zero-dep).
25
+ *
26
+ * Usage: `node scripts/ci/check-tarball-fidelity.mjs` (exit 0 ok / 1 found / 2 error)
27
+ * @module scripts/ci/check-tarball-fidelity
28
+ */
29
+
30
+ "use strict";
31
+
32
+ import { execFileSync } from "node:child_process";
33
+ import {
34
+ mkdtempSync,
35
+ rmSync,
36
+ readFileSync,
37
+ readdirSync,
38
+ lstatSync,
39
+ existsSync,
40
+ } from "node:fs";
41
+ import { tmpdir } from "node:os";
42
+ import path from "node:path";
43
+ import { fileURLToPath } from "node:url";
44
+
45
+ const REPO_ROOT = path.resolve(fileURLToPath(new URL(".", import.meta.url)), "..", "..");
46
+
47
+ /** Patterns that must never appear in the packaged tree. @type {Array<{label:string, re:RegExp}>} */
48
+ export const FORBIDDEN_PATTERNS = [
49
+ { label: "bundled node_modules", re: /(^|\/)node_modules(\/|$)/ },
50
+ { label: "python bytecode (*.pyc)", re: /\.pyc$/ },
51
+ { label: "python bytecode (*.pyo)", re: /\.pyo$/ },
52
+ { label: "bytecode cache dir (__pycache__)", re: /(^|\/)__pycache__(\/|$)/ },
53
+ ];
54
+
55
+ /**
56
+ * The "main" file a consumer's bare `import "@cohortapp/agent-sdk"` resolves to.
57
+ * Falls back to lib/index.js (the documented default) when exports["."] is odd.
58
+ * @param {object} pkg
59
+ * @returns {string|null} repo-relative path or null
60
+ */
61
+ export function resolveMainEntry(pkg) {
62
+ const dot = pkg && pkg.exports && pkg.exports["."];
63
+ let rel = null;
64
+ if (typeof dot === "string") rel = dot;
65
+ else if (dot && typeof dot === "object") rel = dot.default || dot.import || dot.require || null;
66
+ rel = rel || pkg.main || "lib/index.js";
67
+ return rel.replace(/^\.\//, "");
68
+ }
69
+
70
+ /**
71
+ * Recursively walk `dir`, returning every entry as
72
+ * { rel, isSymlink, isDir } with rel relative to `dir` (posix-style).
73
+ * Symlinks are reported but NOT followed.
74
+ * @param {string} dir
75
+ * @returns {Array<{ rel: string, isSymlink: boolean, isDir: boolean }>}
76
+ */
77
+ export function walkTree(dir) {
78
+ const out = [];
79
+ const stack = [dir];
80
+ while (stack.length) {
81
+ const cur = stack.pop();
82
+ let entries;
83
+ try { entries = readdirSync(cur, { withFileTypes: true }); } catch { continue; }
84
+ for (const e of entries) {
85
+ const full = path.join(cur, e.name);
86
+ const rel = path.relative(dir, full).split(path.sep).join("/");
87
+ // Use lstat so we classify the link itself, never its target.
88
+ let st;
89
+ try { st = lstatSync(full); } catch { continue; }
90
+ const isSymlink = st.isSymbolicLink();
91
+ const isDir = !isSymlink && st.isDirectory();
92
+ out.push({ rel, isSymlink, isDir });
93
+ if (isDir) stack.push(full);
94
+ }
95
+ }
96
+ return out;
97
+ }
98
+
99
+ /**
100
+ * Run npm pack + extraction and assess the tarball. Pure-ish: takes no globals
101
+ * beyond REPO_ROOT and the filesystem, cleans up its own tmp dir.
102
+ *
103
+ * @param {object} [opts] @param {string} [opts.cwd=REPO_ROOT]
104
+ * @returns {{ ok: boolean, offenders: Array<{file:string,reason:string}>, missing: string[], tarballFiles: number, mainEntry: string }}
105
+ */
106
+ export function checkTarball(opts = {}) {
107
+ const cwd = opts.cwd || REPO_ROOT;
108
+ const pkg = JSON.parse(readFileSync(path.join(cwd, "package.json"), "utf8"));
109
+ const filesAllowlist = Array.isArray(pkg.files) ? pkg.files : [];
110
+ const mainEntry = resolveMainEntry(pkg);
111
+
112
+ const work = mkdtempSync(path.join(tmpdir(), "maestro-pack-"));
113
+ try {
114
+ // 1) Real pack into the tmp dir. --json gives the manifest; the .tgz lands
115
+ // in --pack-destination. Suppress npm's own stdout noise via --silent.
116
+ const raw = execFileSync(
117
+ "npm",
118
+ ["pack", "--json", "--silent", "--pack-destination", work],
119
+ { cwd, encoding: "utf8", maxBuffer: 64 * 1024 * 1024 },
120
+ );
121
+ const manifest = JSON.parse(raw);
122
+ const entry = Array.isArray(manifest) ? manifest[0] : manifest;
123
+ const tarballPath = path.join(work, entry.filename);
124
+
125
+ // 2) Extract the tarball (npm tarballs root everything under "package/").
126
+ execFileSync("tar", ["-xzf", tarballPath, "-C", work]);
127
+ const pkgRoot = path.join(work, "package");
128
+ if (!existsSync(pkgRoot)) {
129
+ throw new Error(`extracted tarball has no package/ root (${tarballPath})`);
130
+ }
131
+
132
+ const tree = walkTree(pkgRoot);
133
+ const filePaths = tree.filter((t) => !t.isDir).map((t) => t.rel);
134
+
135
+ // 3) Hygiene — forbidden artifacts + symlinks in the EXTRACTED tree.
136
+ const offenders = [];
137
+ for (const t of tree) {
138
+ if (t.isSymlink) {
139
+ offenders.push({ file: t.rel, reason: "symlink in tarball (does not survive install; may point cross-tenant)" });
140
+ continue;
141
+ }
142
+ for (const p of FORBIDDEN_PATTERNS) {
143
+ if (p.re.test(t.rel)) { offenders.push({ file: t.rel, reason: p.label }); break; }
144
+ }
145
+ }
146
+
147
+ // 4) Completeness — every files[] entry must be represented. A directory
148
+ // entry (e.g. "lib/") is satisfied by any packaged path beneath it; a
149
+ // file entry must appear verbatim.
150
+ const missing = [];
151
+ for (const decl of filesAllowlist) {
152
+ const norm = decl.replace(/^\.\//, "").replace(/\/+$/, "");
153
+ const asDirPrefix = norm + "/";
154
+ const present = filePaths.some(
155
+ (f) => f === norm || f.startsWith(asDirPrefix),
156
+ );
157
+ if (!present) missing.push(decl);
158
+ }
159
+
160
+ // 5) Requireability — the package main must be in the tree.
161
+ if (!filePaths.includes(mainEntry)) {
162
+ missing.push(`${mainEntry} (package main / exports["."])`);
163
+ }
164
+
165
+ return {
166
+ ok: offenders.length === 0 && missing.length === 0,
167
+ offenders,
168
+ missing,
169
+ tarballFiles: filePaths.length,
170
+ mainEntry,
171
+ };
172
+ } finally {
173
+ try { rmSync(work, { recursive: true, force: true }); } catch { /* */ }
174
+ }
175
+ }
176
+
177
+ /** @param {string} [cwd=REPO_ROOT] @returns {Promise<number>} */
178
+ export async function run(cwd = REPO_ROOT) {
179
+ let res;
180
+ try {
181
+ res = checkTarball({ cwd });
182
+ } catch (err) {
183
+ console.error(`check-tarball-fidelity: ERROR — ${err && err.message ? err.message : err}`);
184
+ return 2;
185
+ }
186
+ if (res.ok) {
187
+ console.log(`check-tarball-fidelity: OK (${res.tarballFiles} files; main "${res.mainEntry}" present; no node_modules/.pyc/symlinks)`);
188
+ return 0;
189
+ }
190
+ if (res.missing.length) {
191
+ console.error("check-tarball-fidelity: FAIL — declared files[] / main missing from the tarball:");
192
+ for (const m of res.missing) console.error(` ${m}`);
193
+ }
194
+ if (res.offenders.length) {
195
+ console.error("check-tarball-fidelity: FAIL — forbidden artifacts in the tarball:");
196
+ for (const o of res.offenders) console.error(` ${o.file} :: ${o.reason}`);
197
+ }
198
+ return 1;
199
+ }
200
+
201
+ if (import.meta.url === `file://${process.argv[1]}`) {
202
+ run()
203
+ .then((c) => process.exit(c))
204
+ .catch((e) => { console.error("check-tarball-fidelity: ERROR", e && e.message ? e.message : e); process.exit(2); });
205
+ }
@@ -0,0 +1,83 @@
1
+ /**
2
+ * check-unresolved-tokens.mjs — CI guard that fails if a framework prompt file
3
+ * contains a `{{token}}` outside the known render vocabulary.
4
+ *
5
+ * Framework operational prompts (triggers, agent definitions, skills, prompt
6
+ * templates) carry {{agent.*}} identity tokens that lib/render.mjs resolves at
7
+ * load time. A typo ({{agent.firstname}}) or stray braces would render to
8
+ * nothing and ship a broken prompt to a model. This guard scans those files and
9
+ * fails on any token not in lib/render.mjs KNOWN_TOKENS.
10
+ *
11
+ * Pure, dependency-light: Node builtins + lib/render.mjs. ESM.
12
+ *
13
+ * Usage: `node scripts/ci/check-unresolved-tokens.mjs` (exit 0 ok / 1 found)
14
+ * @module scripts/ci/check-unresolved-tokens
15
+ */
16
+
17
+ "use strict";
18
+
19
+ import { readdirSync, readFileSync, existsSync, statSync } from "node:fs";
20
+ import path from "node:path";
21
+ import { fileURLToPath } from "node:url";
22
+ import { unknownTokens } from "../../lib/render.mjs";
23
+
24
+ const REPO_ROOT = path.resolve(fileURLToPath(new URL(".", import.meta.url)), "..", "..");
25
+
26
+ /** Directories whose .md prompt files carry render tokens. @type {string[]} */
27
+ export const SCAN_DIRS = [
28
+ "schedules/triggers",
29
+ "agents",
30
+ "plugins/maestro-skills/skills",
31
+ "docs/prompts",
32
+ ];
33
+
34
+ /** Recursively collect *.md files under a directory. */
35
+ function walkMd(dir) {
36
+ const out = [];
37
+ for (const name of readdirSync(dir)) {
38
+ const p = path.join(dir, name);
39
+ let st;
40
+ try { st = statSync(p); } catch { continue; }
41
+ if (st.isDirectory()) out.push(...walkMd(p));
42
+ else if (name.endsWith(".md")) out.push(p);
43
+ }
44
+ return out;
45
+ }
46
+
47
+ /**
48
+ * Find prompt files containing unknown tokens.
49
+ * @param {object} [opts] @param {string} [opts.cwd=REPO_ROOT] @param {string[]} [opts.dirs=SCAN_DIRS]
50
+ * @returns {Array<{ file: string, tokens: string[] }>}
51
+ */
52
+ export function findUnresolvedTokens(opts = {}) {
53
+ const cwd = opts.cwd || REPO_ROOT;
54
+ const dirs = opts.dirs || SCAN_DIRS;
55
+ const offenders = [];
56
+ for (const d of dirs) {
57
+ const abs = path.join(cwd, d);
58
+ if (!existsSync(abs)) continue;
59
+ for (const file of walkMd(abs)) {
60
+ let body;
61
+ try { body = readFileSync(file, "utf8"); } catch { continue; }
62
+ const bad = unknownTokens(body);
63
+ if (bad.length) offenders.push({ file: path.relative(cwd, file), tokens: bad });
64
+ }
65
+ }
66
+ return offenders;
67
+ }
68
+
69
+ /** @param {string} [cwd=REPO_ROOT] @returns {Promise<number>} */
70
+ export async function run(cwd = REPO_ROOT) {
71
+ const offenders = findUnresolvedTokens({ cwd });
72
+ if (offenders.length === 0) {
73
+ console.log("check-unresolved-tokens: OK (no unknown {{tokens}} in prompt files)");
74
+ return 0;
75
+ }
76
+ console.error("check-unresolved-tokens: FAIL — unknown/typo tokens that will not render:");
77
+ for (const o of offenders) console.error(` ${o.file}: ${o.tokens.map((t) => `{{${t}}}`).join(", ")}`);
78
+ return 1;
79
+ }
80
+
81
+ if (import.meta.url === `file://${process.argv[1]}`) {
82
+ run().then((c) => process.exit(c)).catch((e) => { console.error("check-unresolved-tokens: ERROR", e && e.message ? e.message : e); process.exit(2); });
83
+ }
@@ -0,0 +1,109 @@
1
+ /**
2
+ * check.mjs — CI guard aggregator. Runs every individual maestro CI guard and
3
+ * exits non-zero if any of them fail, printing a one-line-per-check summary.
4
+ *
5
+ * Adapted from OpenClaw's scripts/check.mjs runner. Pure, dependency-light:
6
+ * Node builtins only. ESM module (maestro is "type":"module").
7
+ *
8
+ * Each guard is imported as a module and its `run()` is awaited, so a single
9
+ * Node process executes the whole suite (no per-check subprocess spawn). A
10
+ * guard that throws is treated as a failure rather than crashing the suite, so
11
+ * the summary still lists every check's outcome.
12
+ *
13
+ * Currently aggregates:
14
+ * - check-no-conflict-markers : no git conflict markers in tracked files
15
+ * - check-exports-exist : every package.json exports[] target exists
16
+ * - check-files-exist : every package.json files[] entry exists
17
+ * - check-no-confidential : no confidential instance data in the tarball
18
+ * - check-unresolved-tokens : no unknown {{tokens}} in framework prompt files
19
+ * - check-no-residual-identity: de-Robin'd paths stay persona-agnostic
20
+ * - check-no-build-artifacts : no tracked .pyc/symlinks reach the tarball
21
+ * - check-docs-accuracy : README links resolve; counts/agent-refs WARN
22
+ *
23
+ * Usage: `node scripts/ci/check.mjs`
24
+ * exit 0 → all checks passed; exit 1 → one or more failed.
25
+ *
26
+ * @module scripts/ci/check
27
+ */
28
+
29
+ "use strict";
30
+
31
+ import { run as runConflictMarkers } from "./check-no-conflict-markers.mjs";
32
+ import { run as runExportsExist } from "./check-exports-exist.mjs";
33
+ import { run as runFilesExist } from "./check-files-exist.mjs";
34
+ import { run as runNoConfidential } from "./check-no-confidential.mjs";
35
+ import { run as runUnresolvedTokens } from "./check-unresolved-tokens.mjs";
36
+ import { run as runNoResidualIdentity } from "./check-no-residual-identity.mjs";
37
+ import { run as runNoBuildArtifacts } from "./check-no-build-artifacts.mjs";
38
+ import { run as runDocsAccuracy } from "./check-docs-accuracy.mjs";
39
+
40
+ /**
41
+ * The ordered list of guards this aggregator runs.
42
+ * Each entry's `run` returns a Promise<number> exit code (0 = pass).
43
+ * @type {Array<{ name: string, run: () => Promise<number> }>}
44
+ */
45
+ export const CHECKS = [
46
+ { name: "check-no-conflict-markers", run: runConflictMarkers },
47
+ { name: "check-exports-exist", run: runExportsExist },
48
+ { name: "check-files-exist", run: runFilesExist },
49
+ { name: "check-no-confidential", run: runNoConfidential },
50
+ { name: "check-unresolved-tokens", run: runUnresolvedTokens },
51
+ { name: "check-no-residual-identity", run: runNoResidualIdentity },
52
+ { name: "check-no-build-artifacts", run: runNoBuildArtifacts },
53
+ { name: "check-docs-accuracy", run: runDocsAccuracy },
54
+ ];
55
+
56
+ /**
57
+ * Run every guard in {@link CHECKS}, capturing pass/fail without letting one
58
+ * throw abort the rest.
59
+ *
60
+ * @param {Array<{ name: string, run: () => Promise<number> }>} [checks=CHECKS]
61
+ * @returns {Promise<{ ok: boolean, results: Array<{ name: string, passed: boolean, code: number, error?: string }> }>}
62
+ */
63
+ export async function runAll(checks = CHECKS) {
64
+ const results = [];
65
+ for (const check of checks) {
66
+ try {
67
+ const code = await check.run();
68
+ results.push({ name: check.name, passed: code === 0, code });
69
+ } catch (err) {
70
+ results.push({
71
+ name: check.name,
72
+ passed: false,
73
+ code: 2,
74
+ error: err && err.message ? err.message : String(err),
75
+ });
76
+ }
77
+ }
78
+ const ok = results.every((r) => r.passed);
79
+ return { ok, results };
80
+ }
81
+
82
+ /**
83
+ * Run all checks and print a summary block.
84
+ *
85
+ * @returns {Promise<number>} Process exit code (0 = all passed, 1 = any failed).
86
+ */
87
+ export async function run() {
88
+ const { ok, results } = await runAll();
89
+ console.log("");
90
+ console.log("=== maestro CI guards summary ===");
91
+ for (const r of results) {
92
+ const mark = r.passed ? "PASS" : "FAIL";
93
+ const extra = r.error ? ` (error: ${r.error})` : "";
94
+ console.log(` [${mark}] ${r.name}${extra}`);
95
+ }
96
+ const passedCount = results.filter((r) => r.passed).length;
97
+ console.log(`=== ${passedCount}/${results.length} checks passed ===`);
98
+ return ok ? 0 : 1;
99
+ }
100
+
101
+ // Run when invoked directly (not when imported).
102
+ if (import.meta.url === `file://${process.argv[1]}`) {
103
+ run()
104
+ .then((code) => process.exit(code))
105
+ .catch((err) => {
106
+ console.error("check (aggregator): ERROR", err && err.message ? err.message : err);
107
+ process.exit(2);
108
+ });
109
+ }