@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,191 @@
1
+ /**
2
+ * lib/runtime/child-env.mjs — the ONE child-env builder for every runtime spawn.
3
+ *
4
+ * Every lane that starts an agent runtime (today the `claude` binary) builds its
5
+ * child environment here, through `buildRuntimeEnv`. There are two shapes:
6
+ *
7
+ * STOCK no retarget. The child keeps the seat's own Claude credential
8
+ * (`CLAUDE_CODE_OAUTH_TOKEN`, keychain, or a Console key the lane
9
+ * owns). Foreign `*_API_KEY` / `*_AUTH_TOKEN` / `*_SECRET` /
10
+ * `*_ACCESS_KEY` / `*_PRIVATE_KEY` values are scrubbed (§7.3).
11
+ *
12
+ * RETARGET the router pointed the session at a third-party backend
13
+ * (`ANTHROPIC_BASE_URL` in the retarget set). This is where the old
14
+ * builder leaked: its scrub regex ends in `_AUTH_TOKEN$`, which does
15
+ * not match `CLAUDE_CODE_OAUTH_TOKEN`, so a Max subscription token
16
+ * rode into a child whose base URL was someone else's server. With
17
+ * only a base URL set, "a saved claude.ai login remains the active
18
+ * credential" — the token would have been sent to that server
19
+ * (F1 §5.3). A retarget therefore ALWAYS:
20
+ * - scrubs `CLAUDE_CODE_OAUTH_*` and every `*_OAUTH_TOKEN`;
21
+ * - scrubs every inherited `ANTHROPIC_*` variable, then injects
22
+ * only the allowlisted retarget keys;
23
+ * - refuses (a returned error, never a throw) when the retarget
24
+ * carries no usable `ANTHROPIC_AUTH_TOKEN`, or carries a
25
+ * subscription OAuth token (`sk-ant-oat…`) as that token;
26
+ * - forces `ANTHROPIC_API_KEY=""` (no keychain fallthrough) and
27
+ * `CLAUDE_CODE_ATTRIBUTION_HEADER=0` (a third-party prompt cache
28
+ * is poisoned by the per-request attribution header).
29
+ *
30
+ * Pure: no process.env read, no clock, no I/O. The caller passes the base env.
31
+ *
32
+ * @module lib/runtime/child-env
33
+ */
34
+
35
+ "use strict";
36
+
37
+ /**
38
+ * Env keys a retarget set may introduce. Everything else in a retarget set is
39
+ * dropped, so an internal marker (e.g. `__credFingerprint`) can never reach a
40
+ * child.
41
+ */
42
+ export const RETARGET_KEYS = Object.freeze(new Set([
43
+ "ANTHROPIC_BASE_URL",
44
+ "ANTHROPIC_AUTH_TOKEN",
45
+ "ANTHROPIC_API_KEY",
46
+ "ANTHROPIC_MODEL",
47
+ "ANTHROPIC_SMALL_FAST_MODEL",
48
+ "CLAUDE_CODE_ATTRIBUTION_HEADER",
49
+ "CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS",
50
+ // Slot → model mapping (design §4.7: ANTHROPIC_SMALL_FAST_MODEL is deprecated).
51
+ "ANTHROPIC_DEFAULT_OPUS_MODEL",
52
+ "ANTHROPIC_DEFAULT_SONNET_MODEL",
53
+ "ANTHROPIC_DEFAULT_HAIKU_MODEL",
54
+ "ANTHROPIC_DEFAULT_FABLE_MODEL",
55
+ "CLAUDE_CODE_SUBAGENT_MODEL",
56
+ // The cohort-llm helper credential (see COHORT_HELPER_KEY below).
57
+ "COHORT_LLM_BASE_URL",
58
+ "COHORT_LLM_API_KEY_HELPER",
59
+ "CLAUDE_CODE_API_KEY_HELPER_TTL_MS",
60
+ ]));
61
+
62
+ /**
63
+ * A cohort-llm retarget authenticates with an `apiKeyHelper` that prints the
64
+ * seat's short-lived token, not with a static ANTHROPIC_AUTH_TOKEN. Claude Code
65
+ * ranks ANTHROPIC_AUTH_TOKEN ABOVE apiKeyHelper (code.claude.com/docs/en/iam,
66
+ * "Authentication precedence"), so a static token would pin the session to a
67
+ * token that dies after at most an hour. The helper counts as the retarget's
68
+ * credential only when the retarget names the SAME gateway in
69
+ * COHORT_LLM_BASE_URL and ANTHROPIC_BASE_URL — a Cohort seat token is never
70
+ * handed to a third-party base URL. The runtime adapter turns the helper
71
+ * command into `--settings {"apiKeyHelper": …}`.
72
+ */
73
+ export const COHORT_HELPER_KEY = "COHORT_LLM_API_KEY_HELPER";
74
+
75
+ const trimUrl = (u) => (typeof u === "string" ? u.trim().replace(/\/+$/, "") : "");
76
+
77
+ /** Does this retarget authenticate through the cohort-llm apiKeyHelper? */
78
+ export function isCohortHelperRetarget(retarget) {
79
+ const set = retarget && typeof retarget === "object" ? retarget : {};
80
+ const helper = set[COHORT_HELPER_KEY];
81
+ return isRetarget(set) && typeof helper === "string" && helper.trim() !== "" &&
82
+ trimUrl(set.COHORT_LLM_BASE_URL) !== "" && trimUrl(set.COHORT_LLM_BASE_URL) === trimUrl(set.ANTHROPIC_BASE_URL);
83
+ }
84
+
85
+ /** Prefix of a Claude subscription OAuth token (`claude setup-token` output). */
86
+ const SUBSCRIPTION_TOKEN_PREFIX = /^sk-ant-oat/i;
87
+
88
+ /**
89
+ * Credential-shaped in EVERY shape (stock and retarget). Unchanged from the
90
+ * historical §7.3 scrub so the stock path stays byte-compatible: it keeps the
91
+ * seat's `CLAUDE_CODE_OAUTH_TOKEN`, which a stock Anthropic spawn needs.
92
+ * @param {string} k
93
+ */
94
+ export function isCredentialKey(k) {
95
+ return /(_API_KEY|_AUTH_TOKEN|_SECRET|_ACCESS_KEY|_PRIVATE_KEY)$/i.test(k) || k === "ANTHROPIC_API_KEY";
96
+ }
97
+
98
+ /**
99
+ * Additionally scrubbed on a retarget: the Claude subscription credential in
100
+ * any spelling, and the whole inherited `ANTHROPIC_*` namespace (credentials,
101
+ * a stale base URL, custom headers) — the retarget set re-injects what the
102
+ * child actually needs.
103
+ * @param {string} k
104
+ */
105
+ export function isRetargetScrubbedKey(k) {
106
+ return (
107
+ isCredentialKey(k) ||
108
+ /^CLAUDE_CODE_OAUTH/i.test(k) ||
109
+ /_OAUTH_TOKEN$/i.test(k) ||
110
+ /^ANTHROPIC_/i.test(k) ||
111
+ /^COHORT_LLM_TOKEN$/i.test(k)
112
+ );
113
+ }
114
+
115
+ /** Does a retarget set actually point the child at another backend? */
116
+ export function isRetarget(retarget) {
117
+ return !!(retarget && typeof retarget === "object" &&
118
+ typeof retarget.ANTHROPIC_BASE_URL === "string" && retarget.ANTHROPIC_BASE_URL.trim() !== "");
119
+ }
120
+
121
+ /**
122
+ * Build a child env.
123
+ *
124
+ * @param {object} o
125
+ * @param {object} o.baseEnv the parent env to start from (never mutated)
126
+ * @param {object} [o.retarget] the router's envForSpawn, or {} / null
127
+ * @param {boolean} [o.keepAnthropicApiKey=false] stock only: keep the parent's
128
+ * ANTHROPIC_API_KEY (a Console key the lane owns) instead of scrubbing it
129
+ * @returns {{ok:true, env:object, retargeting:boolean} |
130
+ * {ok:false, error:{code:"retarget_without_token"|"retarget_with_subscription_token", message:string}}}
131
+ */
132
+ export function buildRuntimeEnv({ baseEnv, retarget = {}, keepAnthropicApiKey = false } = {}) {
133
+ const src = baseEnv && typeof baseEnv === "object" ? baseEnv : {};
134
+ const set = retarget && typeof retarget === "object" ? retarget : {};
135
+ const retargeting = isRetarget(set);
136
+
137
+ const viaHelper = retargeting && isCohortHelperRetarget(set);
138
+ if (retargeting && typeof set[COHORT_HELPER_KEY] === "string" && set[COHORT_HELPER_KEY].trim() !== "" && !viaHelper) {
139
+ return {
140
+ ok: false,
141
+ error: {
142
+ code: "retarget_helper_mismatch",
143
+ message: `refusing to retarget to ${set.ANTHROPIC_BASE_URL}: the cohort-llm key helper is only valid for the gateway named in COHORT_LLM_BASE_URL`,
144
+ },
145
+ };
146
+ }
147
+ if (retargeting && !viaHelper) {
148
+ const token = set.ANTHROPIC_AUTH_TOKEN;
149
+ if (typeof token !== "string" || token.trim() === "") {
150
+ return {
151
+ ok: false,
152
+ error: {
153
+ code: "retarget_without_token",
154
+ message: `refusing to retarget to ${set.ANTHROPIC_BASE_URL}: no ANTHROPIC_AUTH_TOKEN for that backend (the seat's own Claude credential is never sent to a third party)`,
155
+ },
156
+ };
157
+ }
158
+ if (SUBSCRIPTION_TOKEN_PREFIX.test(token.trim())) {
159
+ return {
160
+ ok: false,
161
+ error: {
162
+ code: "retarget_with_subscription_token",
163
+ message: `refusing to retarget to ${set.ANTHROPIC_BASE_URL}: the token is a Claude subscription OAuth token, which may never be sent to a third-party endpoint`,
164
+ },
165
+ };
166
+ }
167
+ }
168
+
169
+ const out = {};
170
+ for (const [k, v] of Object.entries(src)) {
171
+ if (retargeting ? isRetargetScrubbedKey(k) : isCredentialKey(k)) continue;
172
+ out[k] = v;
173
+ }
174
+ if (!retargeting && keepAnthropicApiKey && typeof src.ANTHROPIC_API_KEY === "string") {
175
+ out.ANTHROPIC_API_KEY = src.ANTHROPIC_API_KEY;
176
+ }
177
+ for (const [k, v] of Object.entries(set)) {
178
+ if (RETARGET_KEYS.has(k)) out[k] = v;
179
+ }
180
+ if (retargeting) {
181
+ // Empty string, NOT unset: an unset key lets Claude Code fall through to a
182
+ // keychain login against api.anthropic.com.
183
+ out.ANTHROPIC_API_KEY = "";
184
+ out.CLAUDE_CODE_ATTRIBUTION_HEADER = "0";
185
+ // The helper must be the credential in use: a static token would outrank it.
186
+ if (viaHelper) delete out.ANTHROPIC_AUTH_TOKEN;
187
+ }
188
+ return { ok: true, env: out, retargeting, viaHelper };
189
+ }
190
+
191
+ export default { buildRuntimeEnv, isCredentialKey, isRetargetScrubbedKey, isRetarget, isCohortHelperRetarget, RETARGET_KEYS, COHORT_HELPER_KEY };
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * lib/runtime/legacy-shell-guard.mjs — the legacy shell lanes are retired for engine-cohort seats (W4-E1, row 36).
4
+ *
5
+ * Three shell scripts run the `claude` binary directly, outside the runtime
6
+ * adapter: scripts/spawn-session.sh, scripts/continuous-monitor.sh and
7
+ * scripts/local-triggers/run-trigger.sh. They are RETIRED for a seat whose
8
+ * config/agent.json `runtime.engine` is `cohort`, not ported:
9
+ *
10
+ * - each has a maintained JS successor that already goes through
11
+ * `buildSpawn` with the seat's engine — `maestro session spawn` (peers) and
12
+ * the dispatcher for spawn-session.sh, the poller + dispatcher for
13
+ * continuous-monitor.sh, the cadence bus
14
+ * (`scripts/cadence/enqueue-cadence-tick.mjs`) for run-trigger.sh;
15
+ * - no daemon lane, generated plist or cadence calls them (doctor already
16
+ * flags plists that still call run-trigger.sh);
17
+ * - porting them would keep a third spawn path to hold at parity with the
18
+ * adapter (argv mapping, credential scrub, send gate, spend cap) for tools
19
+ * an operator runs by hand.
20
+ *
21
+ * Each script calls this guard first. On an engine-cohort seat the guard
22
+ * refuses (exit 3, the reason on stderr) — running `claude` there would spend
23
+ * the seat's Anthropic credential on work the org routed to cohort-llm and
24
+ * bypass the engine's in-process send gate. On a claude seat it exits 0 and the
25
+ * script behaves exactly as before. `maestro doctor` warns on engine-cohort
26
+ * seats that the lanes are retired.
27
+ *
28
+ * node lib/runtime/legacy-shell-guard.mjs <script-name> <agent-root>
29
+ *
30
+ * @module lib/runtime/legacy-shell-guard
31
+ */
32
+
33
+ "use strict";
34
+
35
+ import { pathToFileURL } from "node:url";
36
+ import { realpathSync } from "node:fs";
37
+ import { readSeatEngine, SHELL_LEGACY_LANES } from "./adapter.mjs";
38
+
39
+ /** The exit code a retired lane stops with. */
40
+ export const LEGACY_LANE_REFUSED_EXIT = 3;
41
+
42
+ /** The successor to use instead of each retired script. */
43
+ export const LEGACY_LANE_SUCCESSORS = Object.freeze({
44
+ "spawn-session.sh": "maestro session spawn --name <slug> \"<prompt>\" (or let the dispatcher take the work)",
45
+ "continuous-monitor.sh": "the maestro daemon's pollers and dispatcher",
46
+ "run-trigger.sh": "node scripts/cadence/enqueue-cadence-tick.mjs <trigger> --source=manual",
47
+ });
48
+
49
+ /**
50
+ * May a legacy shell lane run on this seat? PURE.
51
+ * @param {{engine:string, script:string}} o
52
+ * @returns {{allowed:true}|{allowed:false, exitCode:number, message:string}}
53
+ */
54
+ export function legacyShellLaneVerdict({ engine, script }) {
55
+ if (engine !== "cohort") return { allowed: true };
56
+ const name = String(script || "").split("/").pop() || "this script";
57
+ const successor = LEGACY_LANE_SUCCESSORS[name];
58
+ return {
59
+ allowed: false,
60
+ exitCode: LEGACY_LANE_REFUSED_EXIT,
61
+ message:
62
+ `${name} is retired on this seat: runtime.engine is "cohort", and this legacy lane runs the claude binary directly, ` +
63
+ `outside the runtime adapter.${successor ? ` Use ${successor}.` : ""}`,
64
+ };
65
+ }
66
+
67
+ /** The retired scripts' names, from the adapter's register. */
68
+ export function legacyLaneNames() {
69
+ return SHELL_LEGACY_LANES.map((l) => l.path.split("/").pop());
70
+ }
71
+
72
+ /**
73
+ * The CLI edge.
74
+ * @param {string[]} argv [script, agentRoot]
75
+ * @param {{readSeatEngine?:(root:string)=>string, stderr?:{write:(s:string)=>void}}} [deps]
76
+ * @returns {number} exit code
77
+ */
78
+ export function main(argv, deps = {}) {
79
+ const [script, agentRoot] = argv;
80
+ if (!script || !agentRoot) {
81
+ (deps.stderr || process.stderr).write("usage: legacy-shell-guard.mjs <script-name> <agent-root>\n");
82
+ return 2;
83
+ }
84
+ const v = legacyShellLaneVerdict({ engine: (deps.readSeatEngine || readSeatEngine)(agentRoot), script });
85
+ if (v.allowed) return 0;
86
+ (deps.stderr || process.stderr).write(`${v.message}\n`);
87
+ return v.exitCode;
88
+ }
89
+
90
+ const isEntry = (() => {
91
+ try {
92
+ return process.argv[1] && import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href;
93
+ } catch {
94
+ return false;
95
+ }
96
+ })();
97
+ if (isEntry) process.exitCode = main(process.argv.slice(2));
@@ -0,0 +1,162 @@
1
+ /**
2
+ * lib/runtime/seat-engine.mjs — which engine a spawn runs, decided once per spawn (W4-E1, CF-44, row 5).
3
+ *
4
+ * Every JavaScript site that launches a session — the supervisor's main
5
+ * session, `maestro session spawn` peers, and the daemon's dispatcher, resume,
6
+ * cadence, responder, classifier and ack lanes — asks this module ONCE per
7
+ * spawn for the seat's engine (config/agent.json `runtime.engine`) and spreads
8
+ * the answer into `buildSpawn`:
9
+ *
10
+ * engine claude `{}` — the buildSpawn input, and so the argv and env, are
11
+ * byte-for-byte what they were before this module existed.
12
+ * engine cohort `{engine:"cohort", cohortToken, agentRoot}` — the adapter
13
+ * launches the Cohort Engine (`cli.mjs run` for run lanes,
14
+ * `cli.mjs session` for main-session and peer) with the seat
15
+ * token and the token helper, every Claude credential scrubbed.
16
+ *
17
+ * Reading the config on every spawn is the rollback: flipping `runtime.engine`
18
+ * back to `claude` restores the claude binary on the NEXT spawn, with no
19
+ * restart (design §8.4: "Rollback is one flag flip").
20
+ *
21
+ * An engine-cohort seat never falls back to claude. With no seat token the
22
+ * adapter returns `cohort_token_unavailable` and the lane reports a failure —
23
+ * running claude instead would spend the seat's Anthropic credential on work
24
+ * the org routed to cohort-llm.
25
+ *
26
+ * The decisions (`seatEngineFields`, `engineRunShape`, `sessionBudgetUsd`) are
27
+ * pure; `seatTokenSync` / `seatToken` are the edge.
28
+ *
29
+ * @module lib/runtime/seat-engine
30
+ */
31
+
32
+ "use strict";
33
+
34
+ import { isRetarget } from "./child-env.mjs";
35
+ import { isCohortRouted, readSeatEngine } from "./adapter.mjs";
36
+
37
+ /**
38
+ * The buildSpawn fields for a seat's engine. PURE.
39
+ * `baseUrl` is the gateway the seat token was minted against (the token
40
+ * manager's `baseUrl`, from config/org.yaml `llmBaseUrl` or the env): the engine
41
+ * must talk to the same gateway, never the adapter's default.
42
+ * @param {{engine:string, agentRoot?:string|null, token?:string|null, baseUrl?:string|null}} o
43
+ * @returns {{}|{engine:"cohort", cohortToken:string|undefined, agentRoot:string|undefined, cohortBaseUrl?:string}}
44
+ */
45
+ export function seatEngineFields({ engine, agentRoot = null, token = null, baseUrl = null }) {
46
+ if (engine !== "cohort") return {};
47
+ return {
48
+ engine: "cohort",
49
+ cohortToken: typeof token === "string" && token ? token : undefined,
50
+ agentRoot: typeof agentRoot === "string" && agentRoot ? agentRoot : undefined,
51
+ ...(typeof baseUrl === "string" && baseUrl ? { cohortBaseUrl: baseUrl } : {}),
52
+ };
53
+ }
54
+
55
+ /**
56
+ * What a routed run lane passes for engine cohort. PURE.
57
+ *
58
+ * The engine talks to cohort-llm directly, so a router retarget never applies:
59
+ * model the router's flag when the router chose the cohort provider (a
60
+ * cohort-* tier), else the lane's own Anthropic slot (sonnet/opus/haiku),
61
+ * which the adapter maps to a Cohort tier. A third-party id is never
62
+ * handed to the engine.
63
+ * knobs the router's --max-turns/--effort/--agents, unless they were sized for
64
+ * a third-party backend (CF-11).
65
+ * retarget `{}`.
66
+ *
67
+ * @param {{target?:object|null, laneModel?:string|null}} o
68
+ * @returns {{model:string|null, knobs:object|null, retarget:{}}}
69
+ */
70
+ export function engineRunShape({ target = null, laneModel = null }) {
71
+ const t = target && typeof target === "object" ? target : null;
72
+ const cohortTarget = t ? isCohortRouted({ target: t }) : false;
73
+ const foreign = t ? !cohortTarget && isRetarget(t.envForSpawn) : false;
74
+ const model = cohortTarget && t && t.modelFlag ? String(t.modelFlag) : laneModel ? String(laneModel) : null;
75
+ return { model, knobs: foreign ? null : t, retarget: {} };
76
+ }
77
+
78
+ /** The smallest per-session cap passed: one model call's worth at most. */
79
+ export const MIN_SESSION_BUDGET_USD = 0.01;
80
+
81
+ /**
82
+ * The per-session spend cap for an engine-cohort dispatcher session, from the
83
+ * seat's funded envelope (budget-guard `dailyAllowance`). PURE.
84
+ *
85
+ * A session may not spend more than one day's binding allowance (the lower of
86
+ * the envelope's share for today and the local cap). No funded envelope → no
87
+ * cap is invented (null): the budget guard's bands still govern the seat.
88
+ * An envelope with nothing left today gets {@link MIN_SESSION_BUDGET_USD}.
89
+ *
90
+ * @param {{funded?:boolean, allowanceUSD?:number}|null|undefined} allowance
91
+ * @returns {number|null}
92
+ */
93
+ export function sessionBudgetUsd(allowance) {
94
+ if (!allowance || allowance.funded !== true) return null;
95
+ const usd = Number(allowance.allowanceUSD);
96
+ if (!Number.isFinite(usd)) return null;
97
+ const cents = Math.ceil(Math.max(0, usd) * 100) / 100;
98
+ return Math.max(MIN_SESSION_BUDGET_USD, cents);
99
+ }
100
+
101
+ // ---------------------------------------------------------------------------
102
+ // Edge: the seat token
103
+ // ---------------------------------------------------------------------------
104
+
105
+ /**
106
+ * A usable seat token right now, without a network call (a synchronous spawn
107
+ * path). null when none is cached.
108
+ * @param {{peek?:(o:{allowStale:boolean})=>({token?:string}|null)}|null} tokenManager
109
+ */
110
+ export function seatTokenSync(tokenManager) {
111
+ try {
112
+ const t = tokenManager && typeof tokenManager.peek === "function" ? tokenManager.peek({ allowStale: true }) : null;
113
+ return t && typeof t.token === "string" && t.token ? t.token : null;
114
+ } catch {
115
+ return null;
116
+ }
117
+ }
118
+
119
+ /**
120
+ * A seat token: the cached one, else minted through the manager. null when the
121
+ * seat cannot get one (no OrgApiKey, the gateway refuses) — never throws.
122
+ * @param {{peek?:Function, getToken?:Function}|null} tokenManager
123
+ * @returns {Promise<string|null>}
124
+ */
125
+ export async function seatToken(tokenManager) {
126
+ const cached = seatTokenSync(tokenManager);
127
+ if (cached) return cached;
128
+ try {
129
+ const t = tokenManager && typeof tokenManager.getToken === "function" ? await tokenManager.getToken() : null;
130
+ return t && t.ok !== false && typeof t.token === "string" && t.token ? t.token : null;
131
+ } catch {
132
+ return null;
133
+ }
134
+ }
135
+
136
+ /**
137
+ * The seat's engine and its buildSpawn fields, for a lane that may wait for a
138
+ * token (responder, classifier, ack, the supervisor, `session spawn`). A claude
139
+ * seat reads config/agent.json and nothing else — no token manager is touched.
140
+ * Never throws.
141
+ * @param {string} agentRoot
142
+ * @param {{readSeatEngine?:(root:string)=>string, tokenManager?:(root:string)=>any}} [deps]
143
+ * @returns {Promise<{engine:"claude"|"cohort", fields:object}>}
144
+ */
145
+ export async function resolveSeatSpawn(agentRoot, deps = {}) {
146
+ let engine = "claude";
147
+ try {
148
+ engine = (deps.readSeatEngine || readSeatEngine)(agentRoot) === "cohort" ? "cohort" : "claude";
149
+ } catch {
150
+ engine = "claude"; // unreadable config: the default engine, as readSeatEngine answers
151
+ }
152
+ if (engine !== "cohort") return { engine, fields: {} };
153
+ let manager = null;
154
+ try {
155
+ manager = deps.tokenManager ? deps.tokenManager(agentRoot) : (await import("../org/llm-token.mjs")).seatTokenManager({ agentRoot });
156
+ } catch {
157
+ manager = null; // no seat key: the adapter refuses the spawn (cohort_token_unavailable)
158
+ }
159
+ return { engine, fields: seatEngineFields({ engine, agentRoot, token: await seatToken(manager), baseUrl: manager && typeof manager.baseUrl === "string" ? manager.baseUrl : null }) };
160
+ }
161
+
162
+ export default { seatEngineFields, engineRunShape, sessionBudgetUsd, seatTokenSync, seatToken, resolveSeatSpawn, MIN_SESSION_BUDGET_USD };