@cohortapp/agent-sdk 2.17.0 → 2.18.5

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 (531) hide show
  1. package/.claude/settings.json +18 -0
  2. package/.env.example +18 -5
  3. package/README.md +1 -0
  4. package/bin/maestro.mjs +62 -0
  5. package/docs/guides/billing-console-keys.md +60 -0
  6. package/docs/guides/front-door-session.md +54 -9
  7. package/docs/guides/mac-mini.md +20 -25
  8. package/docs/guides/setup-wizard.md +1 -1
  9. package/docs/runbooks/fleet-rollout.md +156 -0
  10. package/docs/runbooks/mac-mini-bootstrap.md +12 -14
  11. package/lib/action-executor.js +19 -3
  12. package/lib/budget-guard.mjs +279 -3
  13. package/lib/channels/base-adapter.mjs +3 -1
  14. package/lib/channels/contract.mjs +2 -1
  15. package/lib/channels/inbox-item.mjs +8 -0
  16. package/lib/claude-bin.mjs +5 -6
  17. package/lib/cli/doctor-checks.mjs +141 -10
  18. package/lib/cli/global-setup-extras.mjs +5 -1
  19. package/lib/cli/inbox.mjs +100 -15
  20. package/lib/cli/seat-auth.mjs +463 -0
  21. package/lib/cli/session.mjs +80 -12
  22. package/lib/collective/capture-slots.mjs +234 -0
  23. package/lib/collective/capture.mjs +8 -6
  24. package/lib/collective/config.mjs +2 -0
  25. package/lib/collective/global-config.mjs +63 -1
  26. package/lib/collective/loop-guard.mjs +155 -0
  27. package/lib/collective/presence.mjs +142 -5
  28. package/lib/comms/send-gate.mjs +559 -1
  29. package/lib/diagnostics/alerts.mjs +49 -0
  30. package/lib/diagnostics/cadence-output-freshness.mjs +288 -0
  31. package/lib/engine/agents/definitions.mjs +343 -0
  32. package/lib/engine/agents/persist.mjs +275 -0
  33. package/lib/engine/agents/runtime.mjs +748 -0
  34. package/lib/engine/agents/usage.mjs +95 -0
  35. package/lib/engine/auth-status.mjs +139 -0
  36. package/lib/engine/budget.mjs +194 -0
  37. package/lib/engine/cli.mjs +1204 -0
  38. package/lib/engine/commands/index.mjs +269 -0
  39. package/lib/engine/context/budget.mjs +219 -0
  40. package/lib/engine/context/cache.mjs +125 -0
  41. package/lib/engine/context/child-env.mjs +215 -0
  42. package/lib/engine/context/compaction.mjs +342 -0
  43. package/lib/engine/context/images.mjs +90 -0
  44. package/lib/engine/context/instructions.mjs +327 -0
  45. package/lib/engine/context/lazy-instructions.mjs +169 -0
  46. package/lib/engine/context/manager.mjs +182 -0
  47. package/lib/engine/context/real-path.mjs +91 -0
  48. package/lib/engine/context/secret-values.mjs +163 -0
  49. package/lib/engine/context/settings.mjs +274 -0
  50. package/lib/engine/context/stream-input.mjs +159 -0
  51. package/lib/engine/guard.mjs +152 -0
  52. package/lib/engine/hooks.mjs +713 -0
  53. package/lib/engine/loop.mjs +560 -0
  54. package/lib/engine/mcp/client.mjs +254 -0
  55. package/lib/engine/mcp/config.mjs +301 -0
  56. package/lib/engine/mcp/http.mjs +201 -0
  57. package/lib/engine/mcp/index.mjs +146 -0
  58. package/lib/engine/mcp/jsonrpc.mjs +147 -0
  59. package/lib/engine/mcp/naming.mjs +66 -0
  60. package/lib/engine/mcp/resources.mjs +89 -0
  61. package/lib/engine/mcp/results.mjs +133 -0
  62. package/lib/engine/mcp/stdio.mjs +137 -0
  63. package/lib/engine/mcp/supervisor.mjs +116 -0
  64. package/lib/engine/messages.mjs +104 -0
  65. package/lib/engine/output/json.mjs +164 -0
  66. package/lib/engine/output/stream-json.mjs +266 -0
  67. package/lib/engine/permissions.mjs +845 -0
  68. package/lib/engine/process-identity.mjs +164 -0
  69. package/lib/engine/process-tree.mjs +551 -0
  70. package/lib/engine/prompt.mjs +60 -0
  71. package/lib/engine/session/store.mjs +299 -0
  72. package/lib/engine/session-runtime/args.mjs +97 -0
  73. package/lib/engine/session-runtime/host.mjs +143 -0
  74. package/lib/engine/session-runtime/inbox.mjs +122 -0
  75. package/lib/engine/session-runtime/notifications.mjs +129 -0
  76. package/lib/engine/session-runtime/registry.mjs +328 -0
  77. package/lib/engine/session-runtime/runner.mjs +344 -0
  78. package/lib/engine/session-runtime/socket.mjs +212 -0
  79. package/lib/engine/session-runtime/wakeup.mjs +115 -0
  80. package/lib/engine/skills/index.mjs +321 -0
  81. package/lib/engine/tools/bash-background.mjs +533 -0
  82. package/lib/engine/tools/bash.mjs +216 -0
  83. package/lib/engine/tools/edit.mjs +97 -0
  84. package/lib/engine/tools/glob.mjs +81 -0
  85. package/lib/engine/tools/grep.mjs +224 -0
  86. package/lib/engine/tools/index.mjs +84 -0
  87. package/lib/engine/tools/list-agents.mjs +32 -0
  88. package/lib/engine/tools/ls.mjs +127 -0
  89. package/lib/engine/tools/monitor.mjs +82 -0
  90. package/lib/engine/tools/notebook-edit.mjs +218 -0
  91. package/lib/engine/tools/read.mjs +103 -0
  92. package/lib/engine/tools/schedule-wakeup.mjs +45 -0
  93. package/lib/engine/tools/schema.mjs +144 -0
  94. package/lib/engine/tools/send-message.mjs +77 -0
  95. package/lib/engine/tools/session.mjs +70 -0
  96. package/lib/engine/tools/todo.mjs +144 -0
  97. package/lib/engine/tools/toolsearch.mjs +217 -0
  98. package/lib/engine/tools/walk.mjs +193 -0
  99. package/lib/engine/tools/web-switch.mjs +31 -0
  100. package/lib/engine/tools/webfetch-html.mjs +387 -0
  101. package/lib/engine/tools/webfetch-net.mjs +340 -0
  102. package/lib/engine/tools/webfetch.mjs +198 -0
  103. package/lib/engine/tools/websearch.mjs +91 -0
  104. package/lib/engine/tools/workflow.mjs +95 -0
  105. package/lib/engine/tools/write.mjs +76 -0
  106. package/lib/engine/tui/line-editor.mjs +137 -0
  107. package/lib/engine/tui/render.mjs +86 -0
  108. package/lib/engine/tui/tui.mjs +274 -0
  109. package/lib/engine/wire/anthropic-messages.mjs +263 -0
  110. package/lib/engine/wire/effort.mjs +36 -0
  111. package/lib/engine/wire/errors.mjs +496 -0
  112. package/lib/engine/wire/http.mjs +441 -0
  113. package/lib/engine/wire/index.mjs +76 -0
  114. package/lib/engine/wire/openai-chat.mjs +332 -0
  115. package/lib/engine/wire/prompt-cache.mjs +79 -0
  116. package/lib/engine/wire/search.mjs +140 -0
  117. package/lib/engine/wire/sse.mjs +114 -0
  118. package/lib/engine/wire/stall.mjs +349 -0
  119. package/lib/engine/wire/token-provider.mjs +175 -0
  120. package/lib/engine/wire/usage.mjs +192 -0
  121. package/lib/engine/workflow/host.mjs +524 -0
  122. package/lib/engine/workflow/journal.mjs +188 -0
  123. package/lib/engine/workflow/json-schema.mjs +171 -0
  124. package/lib/engine/workflow/meta.mjs +329 -0
  125. package/lib/engine/workflow/notifications.mjs +52 -0
  126. package/lib/engine/workflow/runtime.mjs +447 -0
  127. package/lib/engine/workflow/sandbox.mjs +534 -0
  128. package/lib/engine/workflow/worker.mjs +141 -0
  129. package/lib/engine/workflow/worktree.mjs +74 -0
  130. package/lib/execution/disposition.mjs +1 -1
  131. package/lib/execution/intake.mjs +10 -0
  132. package/lib/execution/surface-policy.mjs +15 -0
  133. package/lib/learning/curator.mjs +8 -6
  134. package/lib/learning/reflect.mjs +8 -6
  135. package/lib/model-router/catalog/cohort.yaml +137 -0
  136. package/lib/model-router/catalog.mjs +118 -1
  137. package/lib/model-router/failover.mjs +67 -16
  138. package/lib/model-router/llm-task.mjs +39 -3
  139. package/lib/model-router/resolve.mjs +89 -3
  140. package/lib/model-router/spawn.mjs +46 -47
  141. package/lib/model-router/taxonomy.mjs +126 -4
  142. package/lib/org/cost-sync.mjs +141 -11
  143. package/lib/org/inbound/broadcast.mjs +289 -0
  144. package/lib/org/inbound/collective.mjs +375 -0
  145. package/lib/org/inbound/directedness.mjs +96 -8
  146. package/lib/org/inbound/facts.mjs +78 -2
  147. package/lib/org/inbound/project.mjs +22 -0
  148. package/lib/org/inbound/surfaces.mjs +14 -0
  149. package/lib/org/llm-token.mjs +879 -0
  150. package/lib/org/mesh.mjs +61 -0
  151. package/lib/org/messaging.mjs +3 -1
  152. package/lib/org/protocol.checksum +1 -1
  153. package/lib/org/protocol.mjs +15 -0
  154. package/lib/org/quota.mjs +520 -0
  155. package/lib/org/tool-surface.mjs +104 -16
  156. package/lib/org/ui-parity.mjs +16 -1
  157. package/lib/org/work-ledger.mjs +37 -6
  158. package/lib/rate-guard.mjs +114 -1
  159. package/lib/resource-governor.mjs +41 -6
  160. package/lib/runtime/adapter.mjs +833 -0
  161. package/lib/runtime/child-env.mjs +191 -0
  162. package/lib/runtime/legacy-shell-guard.mjs +97 -0
  163. package/lib/runtime/seat-engine.mjs +162 -0
  164. package/lib/session/ask-ledger.mjs +271 -0
  165. package/lib/session/current-work.mjs +676 -0
  166. package/lib/session/feed-core.mjs +40 -3
  167. package/lib/session/launch-args.mjs +56 -4
  168. package/lib/session/status-summary.mjs +26 -9
  169. package/lib/session/upgrade-notice.mjs +42 -0
  170. package/lib/setup/claude-probe.mjs +117 -13
  171. package/lib/setup/enrich.mjs +13 -10
  172. package/lib/setup/sections/model.mjs +39 -13
  173. package/lib/telemetry/collect.mjs +229 -11
  174. package/lib/upgrade/ignored-drift.mjs +105 -0
  175. package/lib/voice/post-call-brief.mjs +30 -17
  176. package/package.json +13 -3
  177. package/plugins/maestro-skills/skills/board-work.md +5 -0
  178. package/plugins/maestro-skills/skills/inbound-triage.md +56 -15
  179. package/plugins/maestro-skills/skills/main-session.md +18 -7
  180. package/scaffold/config/collective.yaml +7 -0
  181. package/scripts/ci/check-durable-write-seam.mjs +3 -1
  182. package/scripts/ci/check-tarball-fidelity.mjs +126 -2
  183. package/scripts/ci/run-tests.mjs +47 -19
  184. package/scripts/cohort-llm/api-key-helper.mjs +92 -0
  185. package/scripts/collective/hook-runner.mjs +142 -19
  186. package/scripts/continuous-monitor.sh +13 -0
  187. package/scripts/cost/track-claude-usage.mjs +15 -0
  188. package/scripts/daemon/agent-daemon.mjs +408 -20
  189. package/scripts/daemon/assurance.mjs +48 -12
  190. package/scripts/daemon/cadence-consumer.mjs +218 -68
  191. package/scripts/daemon/cadence-handlers.mjs +73 -4
  192. package/scripts/daemon/classifier.mjs +75 -26
  193. package/scripts/daemon/context-compiler.mjs +51 -37
  194. package/scripts/daemon/deliver.mjs +30 -1
  195. package/scripts/daemon/dispatcher.mjs +595 -149
  196. package/scripts/daemon/health.mjs +14 -1
  197. package/scripts/daemon/maestro-daemon.mjs +11 -0
  198. package/scripts/daemon/prompt-builder.mjs +24 -0
  199. package/scripts/daemon/responder.mjs +246 -79
  200. package/scripts/daemon/sdk-version.mjs +98 -16
  201. package/scripts/eval/probe-gateway.mjs +635 -0
  202. package/scripts/eval/replay/extract.mjs +270 -0
  203. package/scripts/eval/replay/grade.mjs +260 -0
  204. package/scripts/eval/replay/lib/config.mjs +50 -0
  205. package/scripts/eval/replay/lib/effects.mjs +65 -0
  206. package/scripts/eval/replay/lib/fixture.mjs +188 -0
  207. package/scripts/eval/replay/lib/judge.mjs +72 -0
  208. package/scripts/eval/replay/lib/redact.mjs +136 -0
  209. package/scripts/eval/replay/lib/sandbox.mjs +170 -0
  210. package/scripts/eval/replay/lib/schema-check.mjs +63 -0
  211. package/scripts/eval/replay/lib/transcript.mjs +76 -0
  212. package/scripts/eval/replay/mcp-replay-stub.mjs +101 -0
  213. package/scripts/eval/replay/report.mjs +185 -0
  214. package/scripts/eval/replay/run.mjs +404 -0
  215. package/scripts/fleet/rollout.mjs +1151 -0
  216. package/scripts/hooks/pre-send-audit.sh +36 -245
  217. package/scripts/hooks/pre-write-yaml-validate.mjs +275 -0
  218. package/scripts/hooks/validate-state-yaml.sh +190 -0
  219. package/scripts/huddle/huddle-llm.mjs +361 -0
  220. package/scripts/huddle/huddle-server.mjs +46 -121
  221. package/scripts/local-triggers/autoupdate.sh +465 -81
  222. package/scripts/local-triggers/run-trigger.sh +13 -0
  223. package/scripts/maintenance/pin-integrity.mjs +364 -0
  224. package/scripts/poll-slack-events.sh +41 -9
  225. package/scripts/poller/slack-socket-mode.mjs +28 -3
  226. package/scripts/session/supervisor.mjs +80 -13
  227. package/scripts/spawn-session.sh +13 -0
  228. package/bin/maestro.test.mjs +0 -1574
  229. package/lib/action-executor.test.mjs +0 -871
  230. package/lib/archetype.test.mjs +0 -132
  231. package/lib/assurance/plan-note.test.mjs +0 -234
  232. package/lib/assurance/room-budget.test.mjs +0 -486
  233. package/lib/assurance/tier.test.mjs +0 -174
  234. package/lib/autonomy.test.mjs +0 -66
  235. package/lib/backlog.test.mjs +0 -302
  236. package/lib/backup/policy.test.mjs +0 -305
  237. package/lib/budget-escalate.test.mjs +0 -232
  238. package/lib/budget-guard.envelope.test.mjs +0 -476
  239. package/lib/budget-guard.test.mjs +0 -427
  240. package/lib/cadence-bus-requeue.test.mjs +0 -83
  241. package/lib/cadence-bus-schedule.test.mjs +0 -194
  242. package/lib/cadence-bus.test.mjs +0 -720
  243. package/lib/cadences.test.mjs +0 -230
  244. package/lib/capability/inventory.test.mjs +0 -232
  245. package/lib/capability.test.mjs +0 -78
  246. package/lib/channels/base-adapter.test.mjs +0 -590
  247. package/lib/channels/channels.test.mjs +0 -371
  248. package/lib/channels/contract.test.mjs +0 -162
  249. package/lib/channels/inbox-item.test.mjs +0 -368
  250. package/lib/channels/orgmail/adapter.test.mjs +0 -448
  251. package/lib/channels/pairing.test.mjs +0 -270
  252. package/lib/channels/repeat-suppressor.test.mjs +0 -134
  253. package/lib/channels/slack-adapter.test.mjs +0 -212
  254. package/lib/channels/telegram-adapter.test.mjs +0 -306
  255. package/lib/channels/voice/adapter.test.mjs +0 -278
  256. package/lib/channels/whatsapp/adapter-baileys.test.mjs +0 -359
  257. package/lib/channels/whatsapp/baileys-typing.test.mjs +0 -154
  258. package/lib/charter.test.mjs +0 -89
  259. package/lib/claude-bin.test.mjs +0 -131
  260. package/lib/cli/board.test.mjs +0 -227
  261. package/lib/cli/design.test.mjs +0 -270
  262. package/lib/cli/doctor-checks.test.mjs +0 -336
  263. package/lib/cli/global-setup-extras.test.mjs +0 -462
  264. package/lib/cli/inbox.test.mjs +0 -230
  265. package/lib/cli/session-ack.test.mjs +0 -63
  266. package/lib/cli/session.test.mjs +0 -613
  267. package/lib/collective/capture.test.mjs +0 -121
  268. package/lib/collective/cards.test.mjs +0 -114
  269. package/lib/collective/config.test.mjs +0 -123
  270. package/lib/collective/global-config.test.mjs +0 -220
  271. package/lib/collective/global-skills.test.mjs +0 -126
  272. package/lib/collective/presence.test.mjs +0 -95
  273. package/lib/collective/recall.test.mjs +0 -116
  274. package/lib/collective/vendor-skills.test.mjs +0 -306
  275. package/lib/comms/send-gate.test.mjs +0 -770
  276. package/lib/comms.test.mjs +0 -41
  277. package/lib/context/budget.test.mjs +0 -252
  278. package/lib/context/history-scope.test.mjs +0 -79
  279. package/lib/cost/ledger-row.test.mjs +0 -183
  280. package/lib/design/design-md.test.mjs +0 -318
  281. package/lib/design/fixtures/DESIGN.golden.md +0 -238
  282. package/lib/design/fixtures/PRODUCT.golden.md +0 -67
  283. package/lib/design/fixtures/foundation.json +0 -133
  284. package/lib/design/refresh-gate.test.mjs +0 -144
  285. package/lib/design/write.test.mjs +0 -241
  286. package/lib/diagnostics/alerts.test.mjs +0 -318
  287. package/lib/diagnostics/backup-freshness.test.mjs +0 -185
  288. package/lib/diagnostics/counters.test.mjs +0 -206
  289. package/lib/diagnostics/events.test.mjs +0 -290
  290. package/lib/diagnostics/otel.test.mjs +0 -196
  291. package/lib/diagnostics/trace.test.mjs +0 -251
  292. package/lib/env-compat.test.mjs +0 -104
  293. package/lib/execution/disposition.test.mjs +0 -553
  294. package/lib/execution/drive.test.mjs +0 -270
  295. package/lib/execution/effects.test.mjs +0 -344
  296. package/lib/execution/intake.test.mjs +0 -389
  297. package/lib/execution/journal.test.mjs +0 -261
  298. package/lib/execution/match.test.mjs +0 -235
  299. package/lib/execution/pipeline.test.mjs +0 -392
  300. package/lib/execution/route.test.mjs +0 -186
  301. package/lib/execution/surface-policy.test.mjs +0 -162
  302. package/lib/fs-atomic.test.mjs +0 -72
  303. package/lib/fs-ownership.test.mjs +0 -158
  304. package/lib/goals/admission.test.mjs +0 -164
  305. package/lib/goals/classify.test.mjs +0 -167
  306. package/lib/goals/collaborate.test.mjs +0 -336
  307. package/lib/goals/gaps.test.mjs +0 -284
  308. package/lib/goals/loop.test.mjs +0 -845
  309. package/lib/hooks/bus.test.mjs +0 -387
  310. package/lib/identity/persona.test.mjs +0 -142
  311. package/lib/kpi-sensors.test.mjs +0 -278
  312. package/lib/kpi.test.mjs +0 -244
  313. package/lib/learning/config.test.mjs +0 -75
  314. package/lib/learning/counters.test.mjs +0 -69
  315. package/lib/learning/curator-consolidate.test.mjs +0 -238
  316. package/lib/learning/curator.test.mjs +0 -106
  317. package/lib/learning/reflect.test.mjs +0 -0
  318. package/lib/learning/session-index.test.mjs +0 -125
  319. package/lib/learning/skill-writer.test.mjs +0 -210
  320. package/lib/mandate/audit.test.mjs +0 -195
  321. package/lib/mandate/contract.test.mjs +0 -185
  322. package/lib/mandate/derive.test.mjs +0 -274
  323. package/lib/mandate/model.test.mjs +0 -164
  324. package/lib/mandate/refresh.test.mjs +0 -389
  325. package/lib/mcp/server.test.mjs +0 -426
  326. package/lib/model-router/auth-profiles.test.mjs +0 -580
  327. package/lib/model-router/catalog.test.mjs +0 -385
  328. package/lib/model-router/economics.test.mjs +0 -438
  329. package/lib/model-router/failover.test.mjs +0 -439
  330. package/lib/model-router/health.test.mjs +0 -338
  331. package/lib/model-router/integration-coverage.test.mjs +0 -831
  332. package/lib/model-router/integration.test.mjs +0 -564
  333. package/lib/model-router/ledger.test.mjs +0 -415
  334. package/lib/model-router/llm-task.test.mjs +0 -392
  335. package/lib/model-router/org-credentials.test.mjs +0 -265
  336. package/lib/model-router/pricing-refresh.test.mjs +0 -286
  337. package/lib/model-router/reconcile.test.mjs +0 -316
  338. package/lib/model-router/repair.test.mjs +0 -180
  339. package/lib/model-router/spawn.test.mjs +0 -446
  340. package/lib/model-router/taxonomy.test.mjs +0 -410
  341. package/lib/model-router.test.mjs +0 -1207
  342. package/lib/org/activity.test.mjs +0 -134
  343. package/lib/org/approvals.test.mjs +0 -216
  344. package/lib/org/awareness.test.mjs +0 -159
  345. package/lib/org/board-mine-cache.test.mjs +0 -53
  346. package/lib/org/board.test.mjs +0 -187
  347. package/lib/org/bootstrap-context.test.mjs +0 -153
  348. package/lib/org/client.test.mjs +0 -1206
  349. package/lib/org/cohort-client.test.mjs +0 -126
  350. package/lib/org/cost-sync.test.mjs +0 -153
  351. package/lib/org/doctor.test.mjs +0 -346
  352. package/lib/org/engagement-ledger.test.mjs +0 -112
  353. package/lib/org/engagement.test.mjs +0 -739
  354. package/lib/org/handoff.test.mjs +0 -269
  355. package/lib/org/inbound/directedness.test.mjs +0 -668
  356. package/lib/org/inbound/facts.test.mjs +0 -471
  357. package/lib/org/inbound/hydrate.test.mjs +0 -908
  358. package/lib/org/inbound/index.test.mjs +0 -429
  359. package/lib/org/inbound/project.test.mjs +0 -287
  360. package/lib/org/integration-tools.test.mjs +0 -160
  361. package/lib/org/keys.test.mjs +0 -92
  362. package/lib/org/knowledge.test.mjs +0 -326
  363. package/lib/org/leases.test.mjs +0 -235
  364. package/lib/org/mesh-directives.test.mjs +0 -110
  365. package/lib/org/mesh-integration.test.mjs +0 -127
  366. package/lib/org/mesh.test.mjs +0 -400
  367. package/lib/org/messaging.test.mjs +0 -471
  368. package/lib/org/param-contract.test.mjs +0 -477
  369. package/lib/org/policy.test.mjs +0 -237
  370. package/lib/org/protocol.checksum.test.mjs +0 -90
  371. package/lib/org/protocol.test.mjs +0 -323
  372. package/lib/org/push.test.mjs +0 -792
  373. package/lib/org/registry.test.mjs +0 -100
  374. package/lib/org/resource-tools.test.mjs +0 -361
  375. package/lib/org/tool-access.test.mjs +0 -144
  376. package/lib/org/tool-surface-integration.test.mjs +0 -120
  377. package/lib/org/tool-surface.test.mjs +0 -1268
  378. package/lib/org/typing.test.mjs +0 -291
  379. package/lib/org/ui-parity.test.mjs +0 -560
  380. package/lib/org/verify.test.mjs +0 -194
  381. package/lib/org/work-ledger.test.mjs +0 -273
  382. package/lib/plan/adoption-e2e.test.mjs +0 -366
  383. package/lib/plan/budget-enforcement.test.mjs +0 -400
  384. package/lib/plan/compile.test.mjs +0 -382
  385. package/lib/plan/emit.test.mjs +0 -269
  386. package/lib/plan/explain.test.mjs +0 -188
  387. package/lib/prompts/parallelism.test.mjs +0 -177
  388. package/lib/rag/rag.test.mjs +0 -505
  389. package/lib/rate-guard.test.mjs +0 -272
  390. package/lib/reactive-gate.test.mjs +0 -57
  391. package/lib/render.test.mjs +0 -68
  392. package/lib/resource-governor.test.mjs +0 -488
  393. package/lib/scheduling/dynamic-jobs.test.mjs +0 -344
  394. package/lib/scheduling/jitter.test.mjs +0 -140
  395. package/lib/secrets/broker.test.mjs +0 -280
  396. package/lib/secrets/providers.test.mjs +0 -274
  397. package/lib/security/audit-engine.test.mjs +0 -424
  398. package/lib/security/coerce-args.test.mjs +0 -281
  399. package/lib/security/dangerous-tools.test.mjs +0 -68
  400. package/lib/security/external-content.test.mjs +0 -84
  401. package/lib/security/redact.test.mjs +0 -441
  402. package/lib/security/secret-equal.test.mjs +0 -55
  403. package/lib/session/config.test.mjs +0 -92
  404. package/lib/session/feed-core.test.mjs +0 -198
  405. package/lib/session/first-run.test.mjs +0 -121
  406. package/lib/session/frontdoor.test.mjs +0 -205
  407. package/lib/session/handoffs.test.mjs +0 -183
  408. package/lib/session/identity.test.mjs +0 -180
  409. package/lib/session/inbox-claims.test.mjs +0 -286
  410. package/lib/session/launch-args.test.mjs +0 -157
  411. package/lib/session/liveness.test.mjs +0 -100
  412. package/lib/session/status-summary.test.mjs +0 -118
  413. package/lib/session-permissions.test.mjs +0 -120
  414. package/lib/setup/claude-probe.test.mjs +0 -187
  415. package/lib/setup/completeness.test.mjs +0 -110
  416. package/lib/setup/context-pack.test.mjs +0 -89
  417. package/lib/setup/enrich.test.mjs +0 -115
  418. package/lib/setup/enroll-from-cohort.test.mjs +0 -300
  419. package/lib/setup/integration.test.mjs +0 -162
  420. package/lib/setup/io.test.mjs +0 -77
  421. package/lib/setup/runner.test.mjs +0 -132
  422. package/lib/setup/sections/identity.test.mjs +0 -234
  423. package/lib/setup/sections/inventory.test.mjs +0 -198
  424. package/lib/setup/sections/learning.test.mjs +0 -81
  425. package/lib/setup/sections/mandate.test.mjs +0 -388
  426. package/lib/setup/sections/messaging.test.mjs +0 -127
  427. package/lib/setup/sections/model.test.mjs +0 -240
  428. package/lib/setup/sections/org.test.mjs +0 -346
  429. package/lib/setup/sections/orgmail.test.mjs +0 -118
  430. package/lib/setup/sections/recovery.test.mjs +0 -98
  431. package/lib/setup/sections/subagents.test.mjs +0 -429
  432. package/lib/setup/sections/verify.test.mjs +0 -175
  433. package/lib/setup/sot.test.mjs +0 -81
  434. package/lib/setup/state.test.mjs +0 -115
  435. package/lib/singleton.test.mjs +0 -151
  436. package/lib/subagents/cli.test.mjs +0 -389
  437. package/lib/subagents/client.test.mjs +0 -309
  438. package/lib/subagents/gap.test.mjs +0 -234
  439. package/lib/subagents/lock.test.mjs +0 -248
  440. package/lib/subagents/manifest.test.mjs +0 -175
  441. package/lib/subagents/refs.test.mjs +0 -204
  442. package/lib/subagents/resolve.test.mjs +0 -422
  443. package/lib/subagents/schema.test.mjs +0 -328
  444. package/lib/telemetry/alerts.test.mjs +0 -109
  445. package/lib/telemetry/collect.test.mjs +0 -1274
  446. package/lib/tool-definitions-integration.test.mjs +0 -83
  447. package/lib/tool-definitions.test.mjs +0 -437
  448. package/lib/upgrade/global-refresh.test.mjs +0 -65
  449. package/lib/upgrade/launchd-reconcile.test.mjs +0 -272
  450. package/lib/upgrade/post-steps.test.mjs +0 -200
  451. package/lib/upgrade/verify.test.mjs +0 -164
  452. package/lib/util/fetch-timeout.test.mjs +0 -202
  453. package/lib/util/reconnect.test.mjs +0 -369
  454. package/lib/util/unhandled.test.mjs +0 -216
  455. package/lib/voice/outbound.test.mjs +0 -69
  456. package/lib/voice/session-rotation.test.mjs +0 -114
  457. package/lib/voice/stt.test.mjs +0 -226
  458. package/lib/voice/voice.test.mjs +0 -990
  459. package/scripts/cadence/enqueue-cadence-tick.test.mjs +0 -187
  460. package/scripts/ci/check-docs-accuracy.test.mjs +0 -409
  461. package/scripts/ci/check-durable-write-seam.test.mjs +0 -90
  462. package/scripts/ci/check-no-build-artifacts.test.mjs +0 -71
  463. package/scripts/ci/check-no-residual-identity.test.mjs +0 -202
  464. package/scripts/ci/check-skill-packs.test.mjs +0 -495
  465. package/scripts/ci/check-subagent-frontmatter.test.mjs +0 -124
  466. package/scripts/ci/check.test.mjs +0 -194
  467. package/scripts/ci/conformance-org-api.test.mjs +0 -425
  468. package/scripts/cloud-relay/voice/relay-identity.test.mjs +0 -96
  469. package/scripts/collective/hook-runner.test.mjs +0 -173
  470. package/scripts/cost/fleet-digest.test.mjs +0 -207
  471. package/scripts/cost/track-claude-usage-pricing.test.mjs +0 -183
  472. package/scripts/cost/track-claude-usage.test.mjs +0 -148
  473. package/scripts/daemon/agent-daemon-board-mine.test.mjs +0 -96
  474. package/scripts/daemon/agent-daemon-design.test.mjs +0 -238
  475. package/scripts/daemon/agent-daemon-frontdoor.test.mjs +0 -60
  476. package/scripts/daemon/agent-daemon.test.mjs +0 -995
  477. package/scripts/daemon/assurance-e2e.test.mjs +0 -613
  478. package/scripts/daemon/assurance.test.mjs +0 -1791
  479. package/scripts/daemon/board-mirror.test.mjs +0 -165
  480. package/scripts/daemon/cadence-consumer-frontdoor.test.mjs +0 -393
  481. package/scripts/daemon/cadence-consumer-governance.test.mjs +0 -276
  482. package/scripts/daemon/cadence-consumer.test.mjs +0 -776
  483. package/scripts/daemon/cadence-handlers.test.mjs +0 -837
  484. package/scripts/daemon/classifier-identity.test.mjs +0 -137
  485. package/scripts/daemon/classifier.test.mjs +0 -266
  486. package/scripts/daemon/classify-kind.test.mjs +0 -40
  487. package/scripts/daemon/context-compiler.test.mjs +0 -406
  488. package/scripts/daemon/deliver.test.mjs +0 -564
  489. package/scripts/daemon/dispatcher-cooldown.test.mjs +0 -122
  490. package/scripts/daemon/dispatcher-governance.test.mjs +0 -1013
  491. package/scripts/daemon/dispatcher-resume.test.mjs +0 -166
  492. package/scripts/daemon/dispatcher-session-continuity.test.mjs +0 -365
  493. package/scripts/daemon/execution-ladder.test.mjs +0 -470
  494. package/scripts/daemon/goal-steward-cadence.test.mjs +0 -312
  495. package/scripts/daemon/inbox-deferral-session.test.mjs +0 -49
  496. package/scripts/daemon/inbox-deferral.test.mjs +0 -336
  497. package/scripts/daemon/inbox-wake.test.mjs +0 -199
  498. package/scripts/daemon/integration.test.mjs +0 -149
  499. package/scripts/daemon/lib/self-echo.test.mjs +0 -153
  500. package/scripts/daemon/lib/session-router.test.mjs +0 -554
  501. package/scripts/daemon/prompt-builder-preamble.test.mjs +0 -210
  502. package/scripts/daemon/prompt-builder.test.mjs +0 -556
  503. package/scripts/daemon/responder-cost.test.mjs +0 -68
  504. package/scripts/daemon/responder-history.test.mjs +0 -221
  505. package/scripts/daemon/sdk-version.test.mjs +0 -31
  506. package/scripts/daemon/session-lock.test.mjs +0 -252
  507. package/scripts/daemon/session-outcomes.test.mjs +0 -533
  508. package/scripts/daemon/typing-registry.test.mjs +0 -102
  509. package/scripts/hooks/pre-send-audit.test.mjs +0 -354
  510. package/scripts/huddle/huddle-prompt.test.mjs +0 -176
  511. package/scripts/local-triggers/autoupdate.test.mjs +0 -518
  512. package/scripts/local-triggers/generate-plists.test.mjs +0 -456
  513. package/scripts/media-generation/brand-clause.test.mjs +0 -135
  514. package/scripts/org/send-orgmail.first-contact.test.mjs +0 -102
  515. package/scripts/poller/inbox-privilege-injection.test.mjs +0 -167
  516. package/scripts/poller/inbox-scan-poller.test.mjs +0 -295
  517. package/scripts/poller/lib/cloud-relay-dedup.test.mjs +0 -133
  518. package/scripts/poller/slack-socket-mode.test.mjs +0 -805
  519. package/scripts/poller-launchd/install.test.mjs +0 -243
  520. package/scripts/restore-from-backup.test.mjs +0 -181
  521. package/scripts/session/feed.test.mjs +0 -196
  522. package/scripts/session/supervisor-sh.test.mjs +0 -218
  523. package/scripts/session/supervisor.test.mjs +0 -482
  524. package/scripts/setup/configure-macos.test.mjs +0 -306
  525. package/scripts/setup/gen-subagent-manifest.test.mjs +0 -124
  526. package/scripts/setup/generate-agent-package-json.test.mjs +0 -143
  527. package/scripts/setup/generate-capability.test.mjs +0 -134
  528. package/scripts/setup/init-agent.test.mjs +0 -370
  529. package/scripts/setup/init-skill-marketplace.test.mjs +0 -193
  530. package/scripts/vendor/sync-skill-packs.test.mjs +0 -103
  531. package/scripts/watchdog/memory-watchdog.test.mjs +0 -64
@@ -0,0 +1,74 @@
1
+ /**
2
+ * lib/engine/workflow/worktree.mjs — a git worktree for one agent() call with
3
+ * `isolation: "worktree"`.
4
+ *
5
+ * The worktree is created on a new branch from the repository's HEAD, under the
6
+ * run's directory (outside the project, so it never shows up as untracked
7
+ * files in it). The child works there. When it ends, a worktree whose HEAD has
8
+ * not moved and whose status is clean is removed with its branch; anything
9
+ * else is kept, and the agent's result names its path and branch.
10
+ *
11
+ * Only for a working directory inside a git repository with at least one
12
+ * commit; otherwise the call gets an error (`usage: true`, which agent()
13
+ * rejects with) instead of running unisolated. A kept worktree is listed in the
14
+ * run's `end` record. Before creating one, `git worktree prune` forgets
15
+ * worktrees whose directories no longer exist.
16
+ *
17
+ * @module lib/engine/workflow/worktree
18
+ */
19
+
20
+ import { execFile } from "node:child_process";
21
+ import { mkdirSync } from "node:fs";
22
+ import path from "node:path";
23
+
24
+ const GIT_TIMEOUT_MS = 30_000;
25
+
26
+ /**
27
+ * @param {string[]} args @param {string} cwd
28
+ * @returns {Promise<{ok:boolean, stdout:string, stderr:string}>}
29
+ */
30
+ function git(args, cwd) {
31
+ // GIT_DIR and friends in the engine's environment (a hook's, say) would point git elsewhere.
32
+ const env = { PATH: process.env.PATH ?? "/usr/bin:/bin", HOME: process.env.HOME ?? "", LANG: "C", GIT_TERMINAL_PROMPT: "0" };
33
+ return new Promise((resolve) => {
34
+ execFile("git", args, { cwd, env, timeout: GIT_TIMEOUT_MS, maxBuffer: 4 * 1024 * 1024 }, (err, stdout, stderr) => {
35
+ resolve({ ok: !err, stdout: String(stdout ?? "").trim(), stderr: String(stderr ?? "").trim() || (err ? err.message : "") });
36
+ });
37
+ });
38
+ }
39
+
40
+ /**
41
+ * @param {{cwd:string, dir:string, branch:string}} o
42
+ * @returns {Promise<{ok:true, path:string, branch:string, base:string, repo:string, root:string}|{ok:false, error:string, usage?:boolean}>}
43
+ */
44
+ export async function createWorktree({ cwd, dir, branch }) {
45
+ const top = await git(["rev-parse", "--show-toplevel"], cwd);
46
+ if (!top.ok || top.stdout === "") return { ok: false, usage: true, error: `isolation "worktree" needs a git repository, and ${cwd} is not in one` };
47
+ const base = await git(["rev-parse", "HEAD"], top.stdout);
48
+ if (!base.ok) return { ok: false, usage: true, error: `isolation "worktree" needs a commit to start from; the repository at ${top.stdout} has none` };
49
+ // Forget worktrees whose directories are gone (a run directory deleted, a process
50
+ // that exited before removing one), so they do not stay registered in .git/worktrees.
51
+ await git(["worktree", "prune"], top.stdout);
52
+ mkdirSync(path.dirname(dir), { recursive: true });
53
+ const add = await git(["worktree", "add", "-b", branch, dir, base.stdout], top.stdout);
54
+ if (!add.ok) return { ok: false, error: `could not create a worktree: ${add.stderr}` };
55
+ // The child works in the same place inside the worktree as cwd is inside the repository.
56
+ const rel = path.relative(top.stdout, cwd);
57
+ return { ok: true, path: rel && !rel.startsWith("..") ? path.join(dir, rel) : dir, branch, base: base.stdout, repo: top.stdout, root: dir };
58
+ }
59
+
60
+ /**
61
+ * Remove the worktree when nothing changed; keep it otherwise.
62
+ * @param {{root:string, branch:string, base:string, repo:string}} w
63
+ * @returns {Promise<{removed:boolean, reason:string}>}
64
+ */
65
+ export async function finishWorktree(w) {
66
+ const status = await git(["status", "--porcelain"], w.root);
67
+ const head = await git(["rev-parse", "HEAD"], w.root);
68
+ if (!status.ok || !head.ok) return { removed: false, reason: "its state could not be read" };
69
+ if (status.stdout !== "" || head.stdout !== w.base) return { removed: false, reason: status.stdout !== "" ? "it has uncommitted changes" : "it has new commits" };
70
+ const rm = await git(["worktree", "remove", "--force", w.root], w.repo);
71
+ if (!rm.ok) return { removed: false, reason: `removing it failed: ${rm.stderr}` };
72
+ await git(["branch", "-D", w.branch], w.repo);
73
+ return { removed: true, reason: "unchanged" };
74
+ }
@@ -47,7 +47,7 @@ import { dedupeKey, threadKey } from "./journal.mjs";
47
47
  * directedness ladder. A human pointed at this agent; the agent owes an answer.
48
48
  */
49
49
  export const T0_REASONS = Object.freeze([
50
- "direct", "dm", "mention", "named", "assignee", "reviewer", "owner",
50
+ "direct", "dm", "mention", "collective", "named", "assignee", "reviewer", "owner",
51
51
  "approver", "requester", "proposer", "participant", "invited", "attendee",
52
52
  "waiting_on",
53
53
  ]);
@@ -64,6 +64,7 @@ export const INTAKE_ORIGINS = Object.freeze([
64
64
  export const SURFACE_FAMILY = Object.freeze({
65
65
  dm: "messaging",
66
66
  mention: "messaging",
67
+ broadcast: "messaging",
67
68
  thread_reply: "messaging",
68
69
  call: "calling",
69
70
  task_assigned: "board",
@@ -99,6 +100,7 @@ export const SURFACE_TOPIC = Object.freeze({
99
100
  export const KIND_SURFACE = Object.freeze({
100
101
  message: "dm",
101
102
  mention: "mention",
103
+ broadcast: "broadcast",
102
104
  thread_reply: "thread_reply",
103
105
  call: "call",
104
106
  voice_note: "dm",
@@ -129,6 +131,7 @@ export const KIND_SURFACE = Object.freeze({
129
131
  export const RECONSTRUCTED_REASON = Object.freeze({
130
132
  dm: "dm",
131
133
  mention: "mention",
134
+ broadcast: "collective",
132
135
  thread_reply: "thread",
133
136
  call: "invited",
134
137
  task_assigned: "assignee",
@@ -424,6 +427,13 @@ export function fromChannelEvent(item, o = {}) {
424
427
  surface = "mention";
425
428
  reason = "mention";
426
429
  why.push(`${service} channel item names me`);
430
+ } else if (kind === "broadcast") {
431
+ // The org projection already proved the four broadcast conditions (human
432
+ // author, my room, not threaded, collective address) before stamping the
433
+ // kind; a channel adapter that stamps it is making the same claim.
434
+ surface = "broadcast";
435
+ reason = "collective";
436
+ why.push(`${service} channel item is a human's roll-call to the whole room`);
427
437
  } else if (kind === "thread_reply" || (item.is_reply === true && s(item.thread_id))) {
428
438
  // A reply in a thread. Whether the agent is IN that thread is a fact only
429
439
  // the adapter has; without it this is a lane-tier claim at best.
@@ -140,6 +140,21 @@ export const ORG_SURFACE_POLICY = Object.freeze({
140
140
  maxChainDepth: 2,
141
141
  ambientDrop: false,
142
142
  }),
143
+ /**
144
+ * A human's roll-call to the whole room. Respondable, now, in public — and
145
+ * the chain depth is ONE: the answer is a single post about myself, and a
146
+ * roll-call must never become a conversation between thirteen agents.
147
+ */
148
+ broadcast: Object.freeze({
149
+ respondable: true,
150
+ replyMethod: "messaging.send",
151
+ latency: "now",
152
+ actionClasses: Object.freeze([]),
153
+ offlineSafe: true,
154
+ selfApprove: true,
155
+ maxChainDepth: 1,
156
+ ambientDrop: true,
157
+ }),
143
158
  /** A reply in a thread I am part of. Same room, same tightness as a mention. */
144
159
  thread_reply: Object.freeze({
145
160
  respondable: true,
@@ -339,14 +339,16 @@ export function parseConsolidationEnvelope(text, validIds) {
339
339
  export async function defaultConsolidateSpawn(prompt, opts = {}) {
340
340
  try {
341
341
  const { spawnSync } = await import("node:child_process");
342
- const { resolveClaudeBin, daemonClaudeArgs, augmentedPath } = await import("../claude-bin.mjs");
343
- const model = opts.model || "sonnet";
344
- const args = ["--print", "--model", model, ...daemonClaudeArgs()];
345
- const res = spawnSync(resolveClaudeBin(), args, {
346
- input: prompt,
342
+ const { buildSpawn } = await import("../runtime/adapter.mjs");
343
+ // argv + env from the runtime adapter (lane "curator"): --print --model <m>
344
+ // <daemon MCP args>, prompt on stdin, PATH augmented.
345
+ const spec = buildSpawn({ lane: "curator", model: opts.model || "sonnet", prompt, mcp: {}, env: process.env });
346
+ if (!spec.ok) return "";
347
+ const res = spawnSync(spec.bin, spec.argv, {
348
+ input: spec.stdin,
347
349
  encoding: "utf8",
348
350
  timeout: opts.timeoutMs || CONSOLIDATE_TIMEOUT_MS,
349
- env: { ...process.env, PATH: augmentedPath() },
351
+ env: spec.env,
350
352
  maxBuffer: 8 * 1024 * 1024,
351
353
  });
352
354
  if (res.status === 0 && res.stdout) return res.stdout;
@@ -28,7 +28,7 @@
28
28
  "use strict";
29
29
 
30
30
  import { spawnSync } from "node:child_process";
31
- import { resolveClaudeBin, daemonClaudeArgs, augmentedPath } from "../claude-bin.mjs";
31
+ import { buildSpawn } from "../runtime/adapter.mjs";
32
32
  import { captureSession, countUserTurns } from "../collective/capture.mjs";
33
33
  import { readRecentCards } from "../collective/cards.mjs";
34
34
  import { jaccard, tokenSet } from "../collective/recall.mjs";
@@ -146,13 +146,15 @@ export function buildReviewPrompt(transcriptText, extras = {}) {
146
146
  /** Default reviewer spawn: one `claude --print --model <sonnet>`. Fail-open → "". */
147
147
  export function defaultReviewSpawn(prompt, opts = {}) {
148
148
  try {
149
- const model = opts.model || "sonnet";
150
- const args = ["--print", "--model", model, ...daemonClaudeArgs()];
151
- const res = spawnSync(resolveClaudeBin(), args, {
152
- input: prompt,
149
+ // argv + env from the runtime adapter (lane "reflect"): --print --model <m>
150
+ // <daemon MCP args>, prompt on stdin, PATH augmented.
151
+ const spec = buildSpawn({ lane: "reflect", model: opts.model || "sonnet", prompt, mcp: {}, env: process.env });
152
+ if (!spec.ok) return "";
153
+ const res = spawnSync(spec.bin, spec.argv, {
154
+ input: spec.stdin,
153
155
  encoding: "utf8",
154
156
  timeout: opts.timeoutMs || REFLECT_TIMEOUT_MS,
155
- env: { ...process.env, PATH: augmentedPath() },
157
+ env: spec.env,
156
158
  maxBuffer: 8 * 1024 * 1024,
157
159
  });
158
160
  if (res.status === 0 && res.stdout) return res.stdout;
@@ -0,0 +1,137 @@
1
+ # lib/model-router/catalog/cohort.yaml
2
+ # Bundled cohort-llm catalog rows (ships with @cohortapp/agent-sdk).
3
+ #
4
+ # cohort-llm is Cohort's OWN model gateway (hq docs/cohort-llm/design.md §4).
5
+ # The rows are Cohort model TIERS, never upstream model ids: the gateway routes
6
+ # each tier to its legs (design §4.7) and failover never changes the tier a seat
7
+ # is billed for (§5.1 TierRate).
8
+ #
9
+ # first_party: true — this provider is Cohort's own infrastructure, so:
10
+ # - tool_reliability A is an explicit first-party declaration (the gateway owns
11
+ # tier→leg selection and the parity eval, design §8.4), not a probe grade;
12
+ # - data_classes allows public/internal/sensitive without a config backends
13
+ # entry (it is not a third-party supplier; the gateway's own data-class
14
+ # supplier gates, design §4.7, sit behind it).
15
+ #
16
+ # auth: seat_token — there is no static env key. The seat exchanges its
17
+ # OrgApiKey for a short-lived cst_… token at POST /cohort/v1/tokens
18
+ # (lib/org/llm-token.mjs). There is deliberately no auth_env key.
19
+ #
20
+ # endpoints are the DEFAULT gateway; the loader rewrites both to
21
+ # org.cohort.llmBaseUrl or COHORT_LLM_BASE_URL when either is set.
22
+ #
23
+ # cost: null on every row. cohort-llm prices usage from its versioned price book
24
+ # and returns the cost (x-cohort-cost-micros / the cohort SSE frame); a local
25
+ # $/MTok here would be the kind of guess design C7 removes. Budget-guard reads
26
+ # /cohort/v1/quota for cohort-metered seats instead of pricing tokens.
27
+ #
28
+ # context_window follows the tier's smallest leg in the design §4.7 starting slot
29
+ # map (R3 research, fetched 2026-09-14):
30
+ # cohort-agentic GLM-5.3 (1M) → DeepSeek-V4-Pro-0813 (1M) → 1M
31
+ # cohort-reason Kimi-K3 (1M) → GLM-5.3 (1M) → 1M
32
+ # cohort-fast gpt-oss-120b (131K) → GLM-5.3-Flash (1M) → 131K
33
+ # cohort-extract DeepSeek-V4-Flash-0731 (1M) → GLM-5.3-Flash (1M) → 1M
34
+ # max_tokens is the gateway's default per-request ceiling (32K, design §4.1).
35
+ # The slot map is PROVISIONAL until the parity eval (design §8.4, W4-C).
36
+ #
37
+ # tier_map: the Anthropic-slot aliases a claude-shaped caller passes
38
+ # (`--model opus`, ANTHROPIC_DEFAULT_*_MODEL) → Cohort tiers, used when a seat's
39
+ # routing selects this provider. fable is the premium slot (Kimi-K3 class, R3).
40
+
41
+ provider: cohort
42
+ first_party: true
43
+ auth: seat_token
44
+ endpoints:
45
+ anthropic: https://llm.cohortapp.com
46
+ openai: https://llm.cohortapp.com/v1
47
+ data_residency: us
48
+ data_classes: [public, internal, sensitive]
49
+ tier_map:
50
+ fable: cohort-reason
51
+ opus: cohort-agentic
52
+ sonnet: cohort-agentic
53
+ haiku: cohort-fast
54
+ models:
55
+ - id: cohort-agentic
56
+ status: available
57
+ replaced_by: null
58
+ context_window: 1000000
59
+ context_tokens: 950000
60
+ max_tokens: 32000
61
+ cost: { input: null, output: null, cache_read: null, cache_write: null, tiered: [] }
62
+ cost_provenance: { source: gateway, fetched: "2026-09-14", volatile: true }
63
+ compat:
64
+ cache_control: anthropic
65
+ max_tokens_field: max_tokens
66
+ thinking_format: anthropic
67
+ requires_reasoning_echo: false
68
+ rejects_duplicate_tool_names: false
69
+ omit_temperature: false
70
+ supports_prompt_cache_key: true
71
+ tool_reliability: A
72
+ harness: { session: true, direct: true, batch: false }
73
+ quality: {}
74
+ notes: "2026-09-14: first-party tier; main agent loop. Legs GLM-5.3 → DeepSeek-V4-Pro-0813 (design §4.7, provisional)."
75
+
76
+ - id: cohort-reason
77
+ status: available
78
+ replaced_by: null
79
+ context_window: 1000000
80
+ context_tokens: 950000
81
+ max_tokens: 32000
82
+ cost: { input: null, output: null, cache_read: null, cache_write: null, tiered: [] }
83
+ cost_provenance: { source: gateway, fetched: "2026-09-14", volatile: true }
84
+ compat:
85
+ cache_control: anthropic
86
+ max_tokens_field: max_tokens
87
+ thinking_format: anthropic
88
+ requires_reasoning_echo: false
89
+ rejects_duplicate_tool_names: false
90
+ omit_temperature: false
91
+ supports_prompt_cache_key: true
92
+ tool_reliability: A
93
+ harness: { session: true, direct: true, batch: false }
94
+ quality: {}
95
+ notes: "2026-09-14: first-party tier; hardest background work (TTFT). Legs Kimi-K3 → GLM-5.3 (design §4.7, provisional)."
96
+
97
+ - id: cohort-fast
98
+ status: available
99
+ replaced_by: null
100
+ context_window: 131072
101
+ context_tokens: 124000
102
+ max_tokens: 32000
103
+ cost: { input: null, output: null, cache_read: null, cache_write: null, tiered: [] }
104
+ cost_provenance: { source: gateway, fetched: "2026-09-14", volatile: true }
105
+ compat:
106
+ cache_control: anthropic
107
+ max_tokens_field: max_tokens
108
+ thinking_format: anthropic
109
+ requires_reasoning_echo: false
110
+ rejects_duplicate_tool_names: false
111
+ omit_temperature: false
112
+ supports_prompt_cache_key: true
113
+ tool_reliability: A
114
+ harness: { session: true, direct: true, batch: false }
115
+ quality: {}
116
+ notes: "2026-09-14: first-party tier; classifier/haiku lanes. Legs gpt-oss-120b (131K) → GLM-5.3-Flash (design §4.7, provisional)."
117
+
118
+ - id: cohort-extract
119
+ status: available
120
+ replaced_by: null
121
+ context_window: 1000000
122
+ context_tokens: 950000
123
+ max_tokens: 32000
124
+ cost: { input: null, output: null, cache_read: null, cache_write: null, tiered: [] }
125
+ cost_provenance: { source: gateway, fetched: "2026-09-14", volatile: true }
126
+ compat:
127
+ cache_control: anthropic
128
+ max_tokens_field: max_tokens
129
+ thinking_format: anthropic
130
+ requires_reasoning_echo: false
131
+ rejects_duplicate_tool_names: false
132
+ omit_temperature: false
133
+ supports_prompt_cache_key: true
134
+ tool_reliability: A
135
+ harness: { session: true, direct: true, batch: false }
136
+ quality: {}
137
+ notes: "2026-09-14: first-party tier; structured extraction. Legs DeepSeek-V4-Flash-0731 → GLM-5.3-Flash (design §4.7, provisional)."
@@ -43,6 +43,9 @@ import {
43
43
  import { join, resolve, dirname, basename } from "node:path";
44
44
  import { fileURLToPath } from "node:url";
45
45
 
46
+ import { resolveLlmBaseUrl, cohortEndpoints } from "../org/llm-token.mjs";
47
+ import { loadOrgConfig } from "../org/client.mjs";
48
+
46
49
  // js-yaml is a hard dependency of @cohortapp/agent-sdk (package.json), but we still
47
50
  // import it defensively so the read path can degrade rather than crash if the
48
51
  // dep tree is ever broken on a machine.
@@ -87,12 +90,17 @@ const VALID_COST_KEYS = new Set([
87
90
 
88
91
  const COST_FIELDS = ["input", "output", "cache_read", "cache_write"];
89
92
 
93
+ /** How a provider authenticates: a static env key, or a Cohort seat token. */
94
+ const VALID_AUTH = new Set(["env", "seat_token"]);
95
+ const DATA_CLASS_NAMES = new Set(["public", "internal", "sensitive"]);
96
+
90
97
  // Bundled providers we recognise. The authority-merge rule "never add providers"
91
98
  // is enforced for the overlay (tighten-only); agent config MAY introduce a new
92
99
  // provider via catalog_overrides (it is the highest authority and the agent owns
93
100
  // its own machine), but we surface a warning so a typo'd provider name is loud.
94
101
  const BUNDLED_PROVIDERS = new Set([
95
102
  "anthropic",
103
+ "cohort",
96
104
  "deepseek",
97
105
  "moonshot",
98
106
  "qwen",
@@ -294,6 +302,7 @@ function normaliseRow(provider, rawRow, errors) {
294
302
  tool_reliability: VALID_GRADES.has(tool_reliability) ? tool_reliability : null,
295
303
  harness: normaliseHarness(rawRow.harness, errors, label),
296
304
  quality: rawRow.quality && typeof rawRow.quality === "object" ? { ...rawRow.quality } : {},
305
+ notes: typeof rawRow.notes === "string" ? rawRow.notes : null,
297
306
  };
298
307
  return { ok: true, row };
299
308
  }
@@ -323,6 +332,7 @@ function parseProviderDoc(doc, label, errors) {
323
332
  errors.push({ source: label, error: "catalog document missing string `provider`" });
324
333
  return null;
325
334
  }
335
+ const meta = providerMeta(doc, label, errors);
326
336
  const rows = new Map();
327
337
  const models = Array.isArray(doc.models) ? doc.models : [];
328
338
  if (!Array.isArray(doc.models)) {
@@ -337,6 +347,7 @@ function parseProviderDoc(doc, label, errors) {
337
347
  row.endpoints = doc.endpoints && typeof doc.endpoints === "object" ? { ...doc.endpoints } : {};
338
348
  row.data_residency =
339
349
  typeof doc.data_residency === "string" ? doc.data_residency : null;
350
+ Object.assign(row, cloneMeta(meta));
340
351
  rows.set(row.id, row);
341
352
  }
342
353
  return {
@@ -344,10 +355,59 @@ function parseProviderDoc(doc, label, errors) {
344
355
  auth_env: typeof doc.auth_env === "string" ? doc.auth_env : null,
345
356
  endpoints: doc.endpoints && typeof doc.endpoints === "object" ? { ...doc.endpoints } : {},
346
357
  data_residency: typeof doc.data_residency === "string" ? doc.data_residency : null,
358
+ ...cloneMeta(meta),
347
359
  rows,
348
360
  };
349
361
  }
350
362
 
363
+ /**
364
+ * Provider-level identity the router gates on (hoisted onto every row):
365
+ * first_party Cohort's own infrastructure (the cohort-llm gateway). A
366
+ * first-party provider declares its own grade and data-class
367
+ * allowance instead of earning them from a probe/config entry.
368
+ * auth "env" (auth_env names a static key, the default) or
369
+ * "seat_token" (a short-lived Cohort seat token, lib/org/llm-token.mjs).
370
+ * data_classes classes a FIRST-PARTY provider allows without a config entry.
371
+ * tier_map Anthropic-slot alias (fable/opus/sonnet/haiku) → this provider's row id.
372
+ */
373
+ function providerMeta(doc, label, errors) {
374
+ const auth = doc.auth == null ? "env" : doc.auth;
375
+ if (!VALID_AUTH.has(auth)) errors.push({ source: label, error: `auth "${auth}" not in {env,seat_token}` });
376
+ const firstParty = doc.first_party === true;
377
+ let dataClasses = null;
378
+ if (doc.data_classes != null) {
379
+ if (!Array.isArray(doc.data_classes)) {
380
+ errors.push({ source: label, error: "data_classes must be an array" });
381
+ } else {
382
+ const bad = doc.data_classes.filter((c) => !DATA_CLASS_NAMES.has(c));
383
+ if (bad.length) errors.push({ source: label, error: `unknown data_classes ${JSON.stringify(bad)}` });
384
+ dataClasses = doc.data_classes.filter((c) => DATA_CLASS_NAMES.has(c));
385
+ if (!firstParty) errors.push({ source: label, error: "data_classes is only honoured on a first_party provider (third parties are allowed per config backends)" });
386
+ }
387
+ }
388
+ const tierMap = {};
389
+ if (doc.tier_map != null) {
390
+ if (typeof doc.tier_map !== "object" || Array.isArray(doc.tier_map)) {
391
+ errors.push({ source: label, error: "tier_map must be an object" });
392
+ } else {
393
+ for (const [k, v] of Object.entries(doc.tier_map)) {
394
+ if (typeof v === "string" && v) tierMap[String(k).toLowerCase()] = v;
395
+ else errors.push({ source: label, error: `tier_map.${k} must be a row id string` });
396
+ }
397
+ }
398
+ }
399
+ return { first_party: firstParty, auth: VALID_AUTH.has(auth) ? auth : "env", data_classes: dataClasses, tier_map: tierMap };
400
+ }
401
+
402
+ function cloneMeta(meta) {
403
+ return {
404
+ first_party: meta.first_party,
405
+ auth: meta.auth,
406
+ data_classes: meta.data_classes ? [...meta.data_classes] : null,
407
+ tier_map: { ...meta.tier_map },
408
+ };
409
+ }
410
+
351
411
  // ---------------------------------------------------------------------------
352
412
  // Source gathering (each returns provider docs + records its file mtime)
353
413
  // ---------------------------------------------------------------------------
@@ -596,6 +656,8 @@ function mergePartialRow(byRef, ref, entry, layer, errors, warnings) {
596
656
  row.auth_env = entry.auth_env ?? null;
597
657
  row.endpoints = entry.endpoints ?? {};
598
658
  row.data_residency = entry.data_residency ?? null;
659
+ // A config-created row is never first-party: that is a bundled declaration.
660
+ Object.assign(row, { first_party: false, auth: "env", data_classes: null, tier_map: {} });
599
661
  byRef.set(ref, row);
600
662
  }
601
663
  return;
@@ -689,6 +751,11 @@ export function loadCatalog(agentRoot, opts = {}) {
689
751
  for (const row of parsed.rows.values()) byRef.set(row.ref, row);
690
752
  }
691
753
 
754
+ // The cohort gateway's base URL is seat configuration, not catalog data:
755
+ // org.cohort.llmBaseUrl, then COHORT_LLM_BASE_URL, then the default. Applied
756
+ // on the bundled floor so an explicit agent catalog_override still wins.
757
+ applyCohortBaseUrl(byRef, providersByName, cohortBaseUrlFor(root, opts));
758
+
692
759
  // Layer 3: pricing cache (COST ONLY).
693
760
  const pricing = gatherPricingCache(root, opts, errors, mtimes);
694
761
  if (pricing) {
@@ -745,6 +812,10 @@ export function loadCatalog(agentRoot, opts = {}) {
745
812
  auth_env: doc.auth_env,
746
813
  endpoints: doc.endpoints,
747
814
  data_residency: doc.data_residency,
815
+ first_party: doc.first_party === true,
816
+ auth: doc.auth || "env",
817
+ data_classes: doc.data_classes || null,
818
+ tier_map: doc.tier_map || {},
748
819
  });
749
820
  }
750
821
 
@@ -761,6 +832,49 @@ export function loadCatalog(agentRoot, opts = {}) {
761
832
  };
762
833
  }
763
834
 
835
+ /** The cohort gateway base URL for this load (injectable, else config/env). */
836
+ function cohortBaseUrlFor(root, opts) {
837
+ if (opts && typeof opts.cohortLlmBaseUrl === "string" && opts.cohortLlmBaseUrl) {
838
+ return opts.cohortLlmBaseUrl.replace(/\/+$/, "");
839
+ }
840
+ let cfg = opts && opts.orgConfig !== undefined ? opts.orgConfig : null;
841
+ if (cfg === null) {
842
+ try { cfg = existsSync(join(root, "config", "org.yaml")) ? loadOrgConfig(root) : {}; } catch { cfg = {}; }
843
+ }
844
+ return resolveLlmBaseUrl({ cfg, env: (opts && opts.env) || process.env });
845
+ }
846
+
847
+ /** Point the cohort provider (and its rows) at a gateway base URL. */
848
+ function applyCohortBaseUrl(byRef, providersByName, baseUrl) {
849
+ const doc = providersByName.get("cohort");
850
+ if (!doc) return;
851
+ const endpoints = cohortEndpoints(baseUrl);
852
+ doc.endpoints = { ...doc.endpoints, ...endpoints };
853
+ for (const row of byRef.values()) {
854
+ if (row.provider === "cohort") row.endpoints = { ...row.endpoints, ...endpoints };
855
+ }
856
+ }
857
+
858
+ /**
859
+ * The Cohort tier for a claude-shaped model flag. A `cohort-*` id passes
860
+ * through; an Anthropic-slot alias or id (fable/opus/sonnet/haiku, e.g.
861
+ * "claude-sonnet-4-6") maps through the provider's tier_map; anything else is
862
+ * null (the caller decides — never a silent guess).
863
+ * @param {string} modelFlag
864
+ * @param {Record<string,string>} tierMap
865
+ * @returns {string|null}
866
+ */
867
+ export function cohortTierFor(modelFlag, tierMap) {
868
+ const m = typeof modelFlag === "string" ? modelFlag.trim().toLowerCase() : "";
869
+ if (!m) return null;
870
+ if (m.startsWith("cohort-")) return m;
871
+ const map = tierMap && typeof tierMap === "object" ? tierMap : {};
872
+ for (const slot of ["fable", "opus", "sonnet", "haiku"]) {
873
+ if ((m === slot || m.includes(slot)) && map[slot]) return map[slot];
874
+ }
875
+ return null;
876
+ }
877
+
764
878
  function maxMtime(mtimes) {
765
879
  let m = 0;
766
880
  for (const t of mtimes) if (t > m) m = t;
@@ -863,6 +977,7 @@ function mtimeSignature(root, opts) {
863
977
  }
864
978
  }
865
979
  for (const [tag, fn, injected] of [
980
+ ["org", (r) => join(r, "config", "org.yaml"), opts.orgConfig !== undefined || typeof opts.cohortLlmBaseUrl === "string"],
866
981
  ["price", pricingCachePath, opts.pricingCache !== undefined],
867
982
  ["local", localConfigPath, opts.localConfig !== undefined],
868
983
  ["agent", agentConfigPath, opts.agentConfig !== undefined],
@@ -870,6 +985,8 @@ function mtimeSignature(root, opts) {
870
985
  if (injected) parts.push(`${tag}:injected`);
871
986
  else parts.push(`${tag}:${mtimeSafe(fn(root))}`);
872
987
  }
988
+ // The gateway URL may come from the environment.
989
+ parts.push(`llm:${typeof opts.cohortLlmBaseUrl === "string" ? opts.cohortLlmBaseUrl : ((opts.env || process.env).COHORT_LLM_BASE_URL || "")}`);
873
990
  // Overlay is passed by value (already verified); fold its version in.
874
991
  if (opts.overlay) parts.push(`ovl:${opts.overlay.version || "?"}`);
875
992
  return parts.join("|");
@@ -922,4 +1039,4 @@ export const _internals = {
922
1039
  mtimeSignature,
923
1040
  };
924
1041
 
925
- export default { loadCatalog, loadCatalogCached, invalidateCatalogCache, lookupModel, listModels };
1042
+ export default { loadCatalog, loadCatalogCached, invalidateCatalogCache, lookupModel, listModels, cohortTierFor };