@cohortapp/agent-sdk 2.17.0 → 2.18.4

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 (526) 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.mjs +8 -6
  23. package/lib/collective/global-config.mjs +63 -1
  24. package/lib/collective/presence.mjs +142 -5
  25. package/lib/comms/send-gate.mjs +559 -1
  26. package/lib/diagnostics/alerts.mjs +49 -0
  27. package/lib/diagnostics/cadence-output-freshness.mjs +288 -0
  28. package/lib/engine/agents/definitions.mjs +343 -0
  29. package/lib/engine/agents/persist.mjs +275 -0
  30. package/lib/engine/agents/runtime.mjs +748 -0
  31. package/lib/engine/agents/usage.mjs +95 -0
  32. package/lib/engine/auth-status.mjs +139 -0
  33. package/lib/engine/budget.mjs +194 -0
  34. package/lib/engine/cli.mjs +1204 -0
  35. package/lib/engine/commands/index.mjs +269 -0
  36. package/lib/engine/context/budget.mjs +219 -0
  37. package/lib/engine/context/cache.mjs +125 -0
  38. package/lib/engine/context/child-env.mjs +215 -0
  39. package/lib/engine/context/compaction.mjs +342 -0
  40. package/lib/engine/context/images.mjs +90 -0
  41. package/lib/engine/context/instructions.mjs +327 -0
  42. package/lib/engine/context/lazy-instructions.mjs +169 -0
  43. package/lib/engine/context/manager.mjs +182 -0
  44. package/lib/engine/context/real-path.mjs +91 -0
  45. package/lib/engine/context/secret-values.mjs +163 -0
  46. package/lib/engine/context/settings.mjs +274 -0
  47. package/lib/engine/context/stream-input.mjs +159 -0
  48. package/lib/engine/guard.mjs +152 -0
  49. package/lib/engine/hooks.mjs +713 -0
  50. package/lib/engine/loop.mjs +560 -0
  51. package/lib/engine/mcp/client.mjs +254 -0
  52. package/lib/engine/mcp/config.mjs +301 -0
  53. package/lib/engine/mcp/http.mjs +201 -0
  54. package/lib/engine/mcp/index.mjs +146 -0
  55. package/lib/engine/mcp/jsonrpc.mjs +147 -0
  56. package/lib/engine/mcp/naming.mjs +66 -0
  57. package/lib/engine/mcp/resources.mjs +89 -0
  58. package/lib/engine/mcp/results.mjs +133 -0
  59. package/lib/engine/mcp/stdio.mjs +137 -0
  60. package/lib/engine/mcp/supervisor.mjs +116 -0
  61. package/lib/engine/messages.mjs +104 -0
  62. package/lib/engine/output/json.mjs +164 -0
  63. package/lib/engine/output/stream-json.mjs +266 -0
  64. package/lib/engine/permissions.mjs +845 -0
  65. package/lib/engine/process-identity.mjs +164 -0
  66. package/lib/engine/process-tree.mjs +551 -0
  67. package/lib/engine/prompt.mjs +60 -0
  68. package/lib/engine/session/store.mjs +299 -0
  69. package/lib/engine/session-runtime/args.mjs +97 -0
  70. package/lib/engine/session-runtime/host.mjs +143 -0
  71. package/lib/engine/session-runtime/inbox.mjs +122 -0
  72. package/lib/engine/session-runtime/notifications.mjs +129 -0
  73. package/lib/engine/session-runtime/registry.mjs +328 -0
  74. package/lib/engine/session-runtime/runner.mjs +344 -0
  75. package/lib/engine/session-runtime/socket.mjs +212 -0
  76. package/lib/engine/session-runtime/wakeup.mjs +115 -0
  77. package/lib/engine/skills/index.mjs +321 -0
  78. package/lib/engine/tools/bash-background.mjs +533 -0
  79. package/lib/engine/tools/bash.mjs +216 -0
  80. package/lib/engine/tools/edit.mjs +97 -0
  81. package/lib/engine/tools/glob.mjs +81 -0
  82. package/lib/engine/tools/grep.mjs +224 -0
  83. package/lib/engine/tools/index.mjs +84 -0
  84. package/lib/engine/tools/list-agents.mjs +32 -0
  85. package/lib/engine/tools/ls.mjs +127 -0
  86. package/lib/engine/tools/monitor.mjs +82 -0
  87. package/lib/engine/tools/notebook-edit.mjs +218 -0
  88. package/lib/engine/tools/read.mjs +103 -0
  89. package/lib/engine/tools/schedule-wakeup.mjs +45 -0
  90. package/lib/engine/tools/schema.mjs +144 -0
  91. package/lib/engine/tools/send-message.mjs +77 -0
  92. package/lib/engine/tools/session.mjs +70 -0
  93. package/lib/engine/tools/todo.mjs +144 -0
  94. package/lib/engine/tools/toolsearch.mjs +217 -0
  95. package/lib/engine/tools/walk.mjs +193 -0
  96. package/lib/engine/tools/web-switch.mjs +31 -0
  97. package/lib/engine/tools/webfetch-html.mjs +387 -0
  98. package/lib/engine/tools/webfetch-net.mjs +340 -0
  99. package/lib/engine/tools/webfetch.mjs +198 -0
  100. package/lib/engine/tools/websearch.mjs +91 -0
  101. package/lib/engine/tools/workflow.mjs +95 -0
  102. package/lib/engine/tools/write.mjs +76 -0
  103. package/lib/engine/tui/line-editor.mjs +137 -0
  104. package/lib/engine/tui/render.mjs +86 -0
  105. package/lib/engine/tui/tui.mjs +274 -0
  106. package/lib/engine/wire/anthropic-messages.mjs +263 -0
  107. package/lib/engine/wire/effort.mjs +36 -0
  108. package/lib/engine/wire/errors.mjs +496 -0
  109. package/lib/engine/wire/http.mjs +441 -0
  110. package/lib/engine/wire/index.mjs +76 -0
  111. package/lib/engine/wire/openai-chat.mjs +332 -0
  112. package/lib/engine/wire/prompt-cache.mjs +79 -0
  113. package/lib/engine/wire/search.mjs +140 -0
  114. package/lib/engine/wire/sse.mjs +114 -0
  115. package/lib/engine/wire/stall.mjs +349 -0
  116. package/lib/engine/wire/token-provider.mjs +175 -0
  117. package/lib/engine/wire/usage.mjs +192 -0
  118. package/lib/engine/workflow/host.mjs +524 -0
  119. package/lib/engine/workflow/journal.mjs +188 -0
  120. package/lib/engine/workflow/json-schema.mjs +171 -0
  121. package/lib/engine/workflow/meta.mjs +329 -0
  122. package/lib/engine/workflow/notifications.mjs +52 -0
  123. package/lib/engine/workflow/runtime.mjs +447 -0
  124. package/lib/engine/workflow/sandbox.mjs +534 -0
  125. package/lib/engine/workflow/worker.mjs +141 -0
  126. package/lib/engine/workflow/worktree.mjs +74 -0
  127. package/lib/execution/disposition.mjs +1 -1
  128. package/lib/execution/intake.mjs +10 -0
  129. package/lib/execution/surface-policy.mjs +15 -0
  130. package/lib/learning/curator.mjs +8 -6
  131. package/lib/learning/reflect.mjs +8 -6
  132. package/lib/model-router/catalog/cohort.yaml +137 -0
  133. package/lib/model-router/catalog.mjs +118 -1
  134. package/lib/model-router/failover.mjs +67 -16
  135. package/lib/model-router/llm-task.mjs +39 -3
  136. package/lib/model-router/resolve.mjs +89 -3
  137. package/lib/model-router/spawn.mjs +46 -47
  138. package/lib/model-router/taxonomy.mjs +126 -4
  139. package/lib/org/cost-sync.mjs +141 -11
  140. package/lib/org/inbound/broadcast.mjs +289 -0
  141. package/lib/org/inbound/collective.mjs +375 -0
  142. package/lib/org/inbound/directedness.mjs +96 -8
  143. package/lib/org/inbound/facts.mjs +78 -2
  144. package/lib/org/inbound/project.mjs +22 -0
  145. package/lib/org/inbound/surfaces.mjs +14 -0
  146. package/lib/org/llm-token.mjs +879 -0
  147. package/lib/org/mesh.mjs +61 -0
  148. package/lib/org/messaging.mjs +3 -1
  149. package/lib/org/protocol.checksum +1 -1
  150. package/lib/org/protocol.mjs +15 -0
  151. package/lib/org/quota.mjs +520 -0
  152. package/lib/org/tool-surface.mjs +104 -16
  153. package/lib/org/ui-parity.mjs +16 -1
  154. package/lib/org/work-ledger.mjs +37 -6
  155. package/lib/rate-guard.mjs +114 -1
  156. package/lib/resource-governor.mjs +41 -6
  157. package/lib/runtime/adapter.mjs +823 -0
  158. package/lib/runtime/child-env.mjs +191 -0
  159. package/lib/runtime/legacy-shell-guard.mjs +97 -0
  160. package/lib/runtime/seat-engine.mjs +162 -0
  161. package/lib/session/ask-ledger.mjs +271 -0
  162. package/lib/session/current-work.mjs +676 -0
  163. package/lib/session/feed-core.mjs +40 -3
  164. package/lib/session/launch-args.mjs +56 -4
  165. package/lib/session/status-summary.mjs +26 -9
  166. package/lib/session/upgrade-notice.mjs +42 -0
  167. package/lib/setup/claude-probe.mjs +117 -13
  168. package/lib/setup/enrich.mjs +13 -10
  169. package/lib/setup/sections/model.mjs +39 -13
  170. package/lib/telemetry/collect.mjs +208 -9
  171. package/lib/upgrade/ignored-drift.mjs +105 -0
  172. package/lib/voice/post-call-brief.mjs +30 -17
  173. package/package.json +13 -3
  174. package/plugins/maestro-skills/skills/board-work.md +5 -0
  175. package/plugins/maestro-skills/skills/inbound-triage.md +56 -15
  176. package/plugins/maestro-skills/skills/main-session.md +18 -7
  177. package/scripts/ci/check-tarball-fidelity.mjs +126 -2
  178. package/scripts/ci/run-tests.mjs +47 -19
  179. package/scripts/cohort-llm/api-key-helper.mjs +92 -0
  180. package/scripts/collective/hook-runner.mjs +29 -2
  181. package/scripts/continuous-monitor.sh +13 -0
  182. package/scripts/cost/track-claude-usage.mjs +15 -0
  183. package/scripts/daemon/agent-daemon.mjs +408 -20
  184. package/scripts/daemon/assurance.mjs +48 -12
  185. package/scripts/daemon/cadence-consumer.mjs +218 -68
  186. package/scripts/daemon/cadence-handlers.mjs +73 -4
  187. package/scripts/daemon/classifier.mjs +75 -26
  188. package/scripts/daemon/context-compiler.mjs +51 -37
  189. package/scripts/daemon/deliver.mjs +30 -1
  190. package/scripts/daemon/dispatcher.mjs +595 -149
  191. package/scripts/daemon/health.mjs +14 -1
  192. package/scripts/daemon/maestro-daemon.mjs +11 -0
  193. package/scripts/daemon/prompt-builder.mjs +24 -0
  194. package/scripts/daemon/responder.mjs +246 -79
  195. package/scripts/daemon/sdk-version.mjs +98 -16
  196. package/scripts/eval/probe-gateway.mjs +635 -0
  197. package/scripts/eval/replay/extract.mjs +270 -0
  198. package/scripts/eval/replay/grade.mjs +260 -0
  199. package/scripts/eval/replay/lib/config.mjs +50 -0
  200. package/scripts/eval/replay/lib/effects.mjs +65 -0
  201. package/scripts/eval/replay/lib/fixture.mjs +188 -0
  202. package/scripts/eval/replay/lib/judge.mjs +72 -0
  203. package/scripts/eval/replay/lib/redact.mjs +136 -0
  204. package/scripts/eval/replay/lib/sandbox.mjs +170 -0
  205. package/scripts/eval/replay/lib/schema-check.mjs +63 -0
  206. package/scripts/eval/replay/lib/transcript.mjs +76 -0
  207. package/scripts/eval/replay/mcp-replay-stub.mjs +101 -0
  208. package/scripts/eval/replay/report.mjs +185 -0
  209. package/scripts/eval/replay/run.mjs +404 -0
  210. package/scripts/fleet/rollout.mjs +1094 -0
  211. package/scripts/hooks/pre-send-audit.sh +36 -245
  212. package/scripts/hooks/pre-write-yaml-validate.mjs +275 -0
  213. package/scripts/hooks/validate-state-yaml.sh +190 -0
  214. package/scripts/huddle/huddle-llm.mjs +361 -0
  215. package/scripts/huddle/huddle-server.mjs +46 -121
  216. package/scripts/local-triggers/autoupdate.sh +448 -78
  217. package/scripts/local-triggers/run-trigger.sh +13 -0
  218. package/scripts/maintenance/pin-integrity.mjs +364 -0
  219. package/scripts/poll-slack-events.sh +41 -9
  220. package/scripts/poller/slack-socket-mode.mjs +28 -3
  221. package/scripts/session/supervisor.mjs +80 -13
  222. package/scripts/spawn-session.sh +13 -0
  223. package/bin/maestro.test.mjs +0 -1574
  224. package/lib/action-executor.test.mjs +0 -871
  225. package/lib/archetype.test.mjs +0 -132
  226. package/lib/assurance/plan-note.test.mjs +0 -234
  227. package/lib/assurance/room-budget.test.mjs +0 -486
  228. package/lib/assurance/tier.test.mjs +0 -174
  229. package/lib/autonomy.test.mjs +0 -66
  230. package/lib/backlog.test.mjs +0 -302
  231. package/lib/backup/policy.test.mjs +0 -305
  232. package/lib/budget-escalate.test.mjs +0 -232
  233. package/lib/budget-guard.envelope.test.mjs +0 -476
  234. package/lib/budget-guard.test.mjs +0 -427
  235. package/lib/cadence-bus-requeue.test.mjs +0 -83
  236. package/lib/cadence-bus-schedule.test.mjs +0 -194
  237. package/lib/cadence-bus.test.mjs +0 -720
  238. package/lib/cadences.test.mjs +0 -230
  239. package/lib/capability/inventory.test.mjs +0 -232
  240. package/lib/capability.test.mjs +0 -78
  241. package/lib/channels/base-adapter.test.mjs +0 -590
  242. package/lib/channels/channels.test.mjs +0 -371
  243. package/lib/channels/contract.test.mjs +0 -162
  244. package/lib/channels/inbox-item.test.mjs +0 -368
  245. package/lib/channels/orgmail/adapter.test.mjs +0 -448
  246. package/lib/channels/pairing.test.mjs +0 -270
  247. package/lib/channels/repeat-suppressor.test.mjs +0 -134
  248. package/lib/channels/slack-adapter.test.mjs +0 -212
  249. package/lib/channels/telegram-adapter.test.mjs +0 -306
  250. package/lib/channels/voice/adapter.test.mjs +0 -278
  251. package/lib/channels/whatsapp/adapter-baileys.test.mjs +0 -359
  252. package/lib/channels/whatsapp/baileys-typing.test.mjs +0 -154
  253. package/lib/charter.test.mjs +0 -89
  254. package/lib/claude-bin.test.mjs +0 -131
  255. package/lib/cli/board.test.mjs +0 -227
  256. package/lib/cli/design.test.mjs +0 -270
  257. package/lib/cli/doctor-checks.test.mjs +0 -336
  258. package/lib/cli/global-setup-extras.test.mjs +0 -462
  259. package/lib/cli/inbox.test.mjs +0 -230
  260. package/lib/cli/session-ack.test.mjs +0 -63
  261. package/lib/cli/session.test.mjs +0 -613
  262. package/lib/collective/capture.test.mjs +0 -121
  263. package/lib/collective/cards.test.mjs +0 -114
  264. package/lib/collective/config.test.mjs +0 -123
  265. package/lib/collective/global-config.test.mjs +0 -220
  266. package/lib/collective/global-skills.test.mjs +0 -126
  267. package/lib/collective/presence.test.mjs +0 -95
  268. package/lib/collective/recall.test.mjs +0 -116
  269. package/lib/collective/vendor-skills.test.mjs +0 -306
  270. package/lib/comms/send-gate.test.mjs +0 -770
  271. package/lib/comms.test.mjs +0 -41
  272. package/lib/context/budget.test.mjs +0 -252
  273. package/lib/context/history-scope.test.mjs +0 -79
  274. package/lib/cost/ledger-row.test.mjs +0 -183
  275. package/lib/design/design-md.test.mjs +0 -318
  276. package/lib/design/fixtures/DESIGN.golden.md +0 -238
  277. package/lib/design/fixtures/PRODUCT.golden.md +0 -67
  278. package/lib/design/fixtures/foundation.json +0 -133
  279. package/lib/design/refresh-gate.test.mjs +0 -144
  280. package/lib/design/write.test.mjs +0 -241
  281. package/lib/diagnostics/alerts.test.mjs +0 -318
  282. package/lib/diagnostics/backup-freshness.test.mjs +0 -185
  283. package/lib/diagnostics/counters.test.mjs +0 -206
  284. package/lib/diagnostics/events.test.mjs +0 -290
  285. package/lib/diagnostics/otel.test.mjs +0 -196
  286. package/lib/diagnostics/trace.test.mjs +0 -251
  287. package/lib/env-compat.test.mjs +0 -104
  288. package/lib/execution/disposition.test.mjs +0 -553
  289. package/lib/execution/drive.test.mjs +0 -270
  290. package/lib/execution/effects.test.mjs +0 -344
  291. package/lib/execution/intake.test.mjs +0 -389
  292. package/lib/execution/journal.test.mjs +0 -261
  293. package/lib/execution/match.test.mjs +0 -235
  294. package/lib/execution/pipeline.test.mjs +0 -392
  295. package/lib/execution/route.test.mjs +0 -186
  296. package/lib/execution/surface-policy.test.mjs +0 -162
  297. package/lib/fs-atomic.test.mjs +0 -72
  298. package/lib/fs-ownership.test.mjs +0 -158
  299. package/lib/goals/admission.test.mjs +0 -164
  300. package/lib/goals/classify.test.mjs +0 -167
  301. package/lib/goals/collaborate.test.mjs +0 -336
  302. package/lib/goals/gaps.test.mjs +0 -284
  303. package/lib/goals/loop.test.mjs +0 -845
  304. package/lib/hooks/bus.test.mjs +0 -387
  305. package/lib/identity/persona.test.mjs +0 -142
  306. package/lib/kpi-sensors.test.mjs +0 -278
  307. package/lib/kpi.test.mjs +0 -244
  308. package/lib/learning/config.test.mjs +0 -75
  309. package/lib/learning/counters.test.mjs +0 -69
  310. package/lib/learning/curator-consolidate.test.mjs +0 -238
  311. package/lib/learning/curator.test.mjs +0 -106
  312. package/lib/learning/reflect.test.mjs +0 -0
  313. package/lib/learning/session-index.test.mjs +0 -125
  314. package/lib/learning/skill-writer.test.mjs +0 -210
  315. package/lib/mandate/audit.test.mjs +0 -195
  316. package/lib/mandate/contract.test.mjs +0 -185
  317. package/lib/mandate/derive.test.mjs +0 -274
  318. package/lib/mandate/model.test.mjs +0 -164
  319. package/lib/mandate/refresh.test.mjs +0 -389
  320. package/lib/mcp/server.test.mjs +0 -426
  321. package/lib/model-router/auth-profiles.test.mjs +0 -580
  322. package/lib/model-router/catalog.test.mjs +0 -385
  323. package/lib/model-router/economics.test.mjs +0 -438
  324. package/lib/model-router/failover.test.mjs +0 -439
  325. package/lib/model-router/health.test.mjs +0 -338
  326. package/lib/model-router/integration-coverage.test.mjs +0 -831
  327. package/lib/model-router/integration.test.mjs +0 -564
  328. package/lib/model-router/ledger.test.mjs +0 -415
  329. package/lib/model-router/llm-task.test.mjs +0 -392
  330. package/lib/model-router/org-credentials.test.mjs +0 -265
  331. package/lib/model-router/pricing-refresh.test.mjs +0 -286
  332. package/lib/model-router/reconcile.test.mjs +0 -316
  333. package/lib/model-router/repair.test.mjs +0 -180
  334. package/lib/model-router/spawn.test.mjs +0 -446
  335. package/lib/model-router/taxonomy.test.mjs +0 -410
  336. package/lib/model-router.test.mjs +0 -1207
  337. package/lib/org/activity.test.mjs +0 -134
  338. package/lib/org/approvals.test.mjs +0 -216
  339. package/lib/org/awareness.test.mjs +0 -159
  340. package/lib/org/board-mine-cache.test.mjs +0 -53
  341. package/lib/org/board.test.mjs +0 -187
  342. package/lib/org/bootstrap-context.test.mjs +0 -153
  343. package/lib/org/client.test.mjs +0 -1206
  344. package/lib/org/cohort-client.test.mjs +0 -126
  345. package/lib/org/cost-sync.test.mjs +0 -153
  346. package/lib/org/doctor.test.mjs +0 -346
  347. package/lib/org/engagement-ledger.test.mjs +0 -112
  348. package/lib/org/engagement.test.mjs +0 -739
  349. package/lib/org/handoff.test.mjs +0 -269
  350. package/lib/org/inbound/directedness.test.mjs +0 -668
  351. package/lib/org/inbound/facts.test.mjs +0 -471
  352. package/lib/org/inbound/hydrate.test.mjs +0 -908
  353. package/lib/org/inbound/index.test.mjs +0 -429
  354. package/lib/org/inbound/project.test.mjs +0 -287
  355. package/lib/org/integration-tools.test.mjs +0 -160
  356. package/lib/org/keys.test.mjs +0 -92
  357. package/lib/org/knowledge.test.mjs +0 -326
  358. package/lib/org/leases.test.mjs +0 -235
  359. package/lib/org/mesh-directives.test.mjs +0 -110
  360. package/lib/org/mesh-integration.test.mjs +0 -127
  361. package/lib/org/mesh.test.mjs +0 -400
  362. package/lib/org/messaging.test.mjs +0 -471
  363. package/lib/org/param-contract.test.mjs +0 -477
  364. package/lib/org/policy.test.mjs +0 -237
  365. package/lib/org/protocol.checksum.test.mjs +0 -90
  366. package/lib/org/protocol.test.mjs +0 -323
  367. package/lib/org/push.test.mjs +0 -792
  368. package/lib/org/registry.test.mjs +0 -100
  369. package/lib/org/resource-tools.test.mjs +0 -361
  370. package/lib/org/tool-access.test.mjs +0 -144
  371. package/lib/org/tool-surface-integration.test.mjs +0 -120
  372. package/lib/org/tool-surface.test.mjs +0 -1268
  373. package/lib/org/typing.test.mjs +0 -291
  374. package/lib/org/ui-parity.test.mjs +0 -560
  375. package/lib/org/verify.test.mjs +0 -194
  376. package/lib/org/work-ledger.test.mjs +0 -273
  377. package/lib/plan/adoption-e2e.test.mjs +0 -366
  378. package/lib/plan/budget-enforcement.test.mjs +0 -400
  379. package/lib/plan/compile.test.mjs +0 -382
  380. package/lib/plan/emit.test.mjs +0 -269
  381. package/lib/plan/explain.test.mjs +0 -188
  382. package/lib/prompts/parallelism.test.mjs +0 -177
  383. package/lib/rag/rag.test.mjs +0 -505
  384. package/lib/rate-guard.test.mjs +0 -272
  385. package/lib/reactive-gate.test.mjs +0 -57
  386. package/lib/render.test.mjs +0 -68
  387. package/lib/resource-governor.test.mjs +0 -488
  388. package/lib/scheduling/dynamic-jobs.test.mjs +0 -344
  389. package/lib/scheduling/jitter.test.mjs +0 -140
  390. package/lib/secrets/broker.test.mjs +0 -280
  391. package/lib/secrets/providers.test.mjs +0 -274
  392. package/lib/security/audit-engine.test.mjs +0 -424
  393. package/lib/security/coerce-args.test.mjs +0 -281
  394. package/lib/security/dangerous-tools.test.mjs +0 -68
  395. package/lib/security/external-content.test.mjs +0 -84
  396. package/lib/security/redact.test.mjs +0 -441
  397. package/lib/security/secret-equal.test.mjs +0 -55
  398. package/lib/session/config.test.mjs +0 -92
  399. package/lib/session/feed-core.test.mjs +0 -198
  400. package/lib/session/first-run.test.mjs +0 -121
  401. package/lib/session/frontdoor.test.mjs +0 -205
  402. package/lib/session/handoffs.test.mjs +0 -183
  403. package/lib/session/identity.test.mjs +0 -180
  404. package/lib/session/inbox-claims.test.mjs +0 -286
  405. package/lib/session/launch-args.test.mjs +0 -157
  406. package/lib/session/liveness.test.mjs +0 -100
  407. package/lib/session/status-summary.test.mjs +0 -118
  408. package/lib/session-permissions.test.mjs +0 -120
  409. package/lib/setup/claude-probe.test.mjs +0 -187
  410. package/lib/setup/completeness.test.mjs +0 -110
  411. package/lib/setup/context-pack.test.mjs +0 -89
  412. package/lib/setup/enrich.test.mjs +0 -115
  413. package/lib/setup/enroll-from-cohort.test.mjs +0 -300
  414. package/lib/setup/integration.test.mjs +0 -162
  415. package/lib/setup/io.test.mjs +0 -77
  416. package/lib/setup/runner.test.mjs +0 -132
  417. package/lib/setup/sections/identity.test.mjs +0 -234
  418. package/lib/setup/sections/inventory.test.mjs +0 -198
  419. package/lib/setup/sections/learning.test.mjs +0 -81
  420. package/lib/setup/sections/mandate.test.mjs +0 -388
  421. package/lib/setup/sections/messaging.test.mjs +0 -127
  422. package/lib/setup/sections/model.test.mjs +0 -240
  423. package/lib/setup/sections/org.test.mjs +0 -346
  424. package/lib/setup/sections/orgmail.test.mjs +0 -118
  425. package/lib/setup/sections/recovery.test.mjs +0 -98
  426. package/lib/setup/sections/subagents.test.mjs +0 -429
  427. package/lib/setup/sections/verify.test.mjs +0 -175
  428. package/lib/setup/sot.test.mjs +0 -81
  429. package/lib/setup/state.test.mjs +0 -115
  430. package/lib/singleton.test.mjs +0 -151
  431. package/lib/subagents/cli.test.mjs +0 -389
  432. package/lib/subagents/client.test.mjs +0 -309
  433. package/lib/subagents/gap.test.mjs +0 -234
  434. package/lib/subagents/lock.test.mjs +0 -248
  435. package/lib/subagents/manifest.test.mjs +0 -175
  436. package/lib/subagents/refs.test.mjs +0 -204
  437. package/lib/subagents/resolve.test.mjs +0 -422
  438. package/lib/subagents/schema.test.mjs +0 -328
  439. package/lib/telemetry/alerts.test.mjs +0 -109
  440. package/lib/telemetry/collect.test.mjs +0 -1274
  441. package/lib/tool-definitions-integration.test.mjs +0 -83
  442. package/lib/tool-definitions.test.mjs +0 -437
  443. package/lib/upgrade/global-refresh.test.mjs +0 -65
  444. package/lib/upgrade/launchd-reconcile.test.mjs +0 -272
  445. package/lib/upgrade/post-steps.test.mjs +0 -200
  446. package/lib/upgrade/verify.test.mjs +0 -164
  447. package/lib/util/fetch-timeout.test.mjs +0 -202
  448. package/lib/util/reconnect.test.mjs +0 -369
  449. package/lib/util/unhandled.test.mjs +0 -216
  450. package/lib/voice/outbound.test.mjs +0 -69
  451. package/lib/voice/session-rotation.test.mjs +0 -114
  452. package/lib/voice/stt.test.mjs +0 -226
  453. package/lib/voice/voice.test.mjs +0 -990
  454. package/scripts/cadence/enqueue-cadence-tick.test.mjs +0 -187
  455. package/scripts/ci/check-docs-accuracy.test.mjs +0 -409
  456. package/scripts/ci/check-durable-write-seam.test.mjs +0 -90
  457. package/scripts/ci/check-no-build-artifacts.test.mjs +0 -71
  458. package/scripts/ci/check-no-residual-identity.test.mjs +0 -202
  459. package/scripts/ci/check-skill-packs.test.mjs +0 -495
  460. package/scripts/ci/check-subagent-frontmatter.test.mjs +0 -124
  461. package/scripts/ci/check.test.mjs +0 -194
  462. package/scripts/ci/conformance-org-api.test.mjs +0 -425
  463. package/scripts/cloud-relay/voice/relay-identity.test.mjs +0 -96
  464. package/scripts/collective/hook-runner.test.mjs +0 -173
  465. package/scripts/cost/fleet-digest.test.mjs +0 -207
  466. package/scripts/cost/track-claude-usage-pricing.test.mjs +0 -183
  467. package/scripts/cost/track-claude-usage.test.mjs +0 -148
  468. package/scripts/daemon/agent-daemon-board-mine.test.mjs +0 -96
  469. package/scripts/daemon/agent-daemon-design.test.mjs +0 -238
  470. package/scripts/daemon/agent-daemon-frontdoor.test.mjs +0 -60
  471. package/scripts/daemon/agent-daemon.test.mjs +0 -995
  472. package/scripts/daemon/assurance-e2e.test.mjs +0 -613
  473. package/scripts/daemon/assurance.test.mjs +0 -1791
  474. package/scripts/daemon/board-mirror.test.mjs +0 -165
  475. package/scripts/daemon/cadence-consumer-frontdoor.test.mjs +0 -393
  476. package/scripts/daemon/cadence-consumer-governance.test.mjs +0 -276
  477. package/scripts/daemon/cadence-consumer.test.mjs +0 -776
  478. package/scripts/daemon/cadence-handlers.test.mjs +0 -837
  479. package/scripts/daemon/classifier-identity.test.mjs +0 -137
  480. package/scripts/daemon/classifier.test.mjs +0 -266
  481. package/scripts/daemon/classify-kind.test.mjs +0 -40
  482. package/scripts/daemon/context-compiler.test.mjs +0 -406
  483. package/scripts/daemon/deliver.test.mjs +0 -564
  484. package/scripts/daemon/dispatcher-cooldown.test.mjs +0 -122
  485. package/scripts/daemon/dispatcher-governance.test.mjs +0 -1013
  486. package/scripts/daemon/dispatcher-resume.test.mjs +0 -166
  487. package/scripts/daemon/dispatcher-session-continuity.test.mjs +0 -365
  488. package/scripts/daemon/execution-ladder.test.mjs +0 -470
  489. package/scripts/daemon/goal-steward-cadence.test.mjs +0 -312
  490. package/scripts/daemon/inbox-deferral-session.test.mjs +0 -49
  491. package/scripts/daemon/inbox-deferral.test.mjs +0 -336
  492. package/scripts/daemon/inbox-wake.test.mjs +0 -199
  493. package/scripts/daemon/integration.test.mjs +0 -149
  494. package/scripts/daemon/lib/self-echo.test.mjs +0 -153
  495. package/scripts/daemon/lib/session-router.test.mjs +0 -554
  496. package/scripts/daemon/prompt-builder-preamble.test.mjs +0 -210
  497. package/scripts/daemon/prompt-builder.test.mjs +0 -556
  498. package/scripts/daemon/responder-cost.test.mjs +0 -68
  499. package/scripts/daemon/responder-history.test.mjs +0 -221
  500. package/scripts/daemon/sdk-version.test.mjs +0 -31
  501. package/scripts/daemon/session-lock.test.mjs +0 -252
  502. package/scripts/daemon/session-outcomes.test.mjs +0 -533
  503. package/scripts/daemon/typing-registry.test.mjs +0 -102
  504. package/scripts/hooks/pre-send-audit.test.mjs +0 -354
  505. package/scripts/huddle/huddle-prompt.test.mjs +0 -176
  506. package/scripts/local-triggers/autoupdate.test.mjs +0 -518
  507. package/scripts/local-triggers/generate-plists.test.mjs +0 -456
  508. package/scripts/media-generation/brand-clause.test.mjs +0 -135
  509. package/scripts/org/send-orgmail.first-contact.test.mjs +0 -102
  510. package/scripts/poller/inbox-privilege-injection.test.mjs +0 -167
  511. package/scripts/poller/inbox-scan-poller.test.mjs +0 -295
  512. package/scripts/poller/lib/cloud-relay-dedup.test.mjs +0 -133
  513. package/scripts/poller/slack-socket-mode.test.mjs +0 -805
  514. package/scripts/poller-launchd/install.test.mjs +0 -243
  515. package/scripts/restore-from-backup.test.mjs +0 -181
  516. package/scripts/session/feed.test.mjs +0 -196
  517. package/scripts/session/supervisor-sh.test.mjs +0 -218
  518. package/scripts/session/supervisor.test.mjs +0 -482
  519. package/scripts/setup/configure-macos.test.mjs +0 -306
  520. package/scripts/setup/gen-subagent-manifest.test.mjs +0 -124
  521. package/scripts/setup/generate-agent-package-json.test.mjs +0 -143
  522. package/scripts/setup/generate-capability.test.mjs +0 -134
  523. package/scripts/setup/init-agent.test.mjs +0 -370
  524. package/scripts/setup/init-skill-marketplace.test.mjs +0 -193
  525. package/scripts/vendor/sync-skill-packs.test.mjs +0 -103
  526. 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 };