humanish 0.106.0 → 0.107.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (459) hide show
  1. package/AGENTS.md +4 -2
  2. package/ARCHITECTURE.md +17 -16
  3. package/CHANGELOG.md +24 -0
  4. package/CONTEXT.md +42 -39
  5. package/CONTRIBUTING.md +8 -6
  6. package/README.md +8 -3
  7. package/dist/actors/codex/app-server-client.js +2 -1
  8. package/dist/actors/codex/app-server-trace.d.ts +0 -1
  9. package/dist/actors/codex/app-server-trace.js +1 -3
  10. package/dist/actors/codex/app-server.js +2 -1
  11. package/dist/actors/codex/protocol-compat.d.ts +27 -0
  12. package/dist/actors/codex/protocol-compat.js +357 -0
  13. package/dist/actors/codex/protocol-contract.d.ts +61 -0
  14. package/dist/actors/codex/protocol-contract.js +471 -0
  15. package/dist/actors/codex/qualified-versions.d.ts +31 -4
  16. package/dist/actors/codex/qualified-versions.js +51 -6
  17. package/dist/actors/codex/restricted-executable.d.ts +24 -0
  18. package/dist/actors/codex/restricted-executable.js +97 -22
  19. package/dist/actors/codex/restricted-launch.d.ts +7 -1
  20. package/dist/actors/codex/restricted-launch.js +42 -3
  21. package/dist/actors/codex/restricted-notifications.d.ts +101 -0
  22. package/dist/actors/codex/restricted-notifications.js +277 -0
  23. package/dist/actors/codex/restricted-participant.d.ts +30 -0
  24. package/dist/actors/codex/restricted-participant.js +60 -2
  25. package/dist/actors/codex/restricted-policy.d.ts +9 -1
  26. package/dist/actors/codex/restricted-session.d.ts +14 -1
  27. package/dist/actors/codex/restricted-session.js +50 -17
  28. package/dist/actors/codex/restricted-transport.d.ts +29 -0
  29. package/dist/actors/codex/restricted-transport.js +139 -27
  30. package/dist/actors/codex/restricted-turn.d.ts +19 -4
  31. package/dist/actors/codex/restricted-turn.js +43 -30
  32. package/dist/actors/computer-use/actor.d.ts +1 -1
  33. package/dist/actors/computer-use/actor.js +4 -4
  34. package/dist/actors/computer-use/loop/backstop.js +1 -1
  35. package/dist/actors/computer-use/loop/ending.d.ts +2 -2
  36. package/dist/actors/computer-use/loop/ending.js +2 -2
  37. package/dist/actors/computer-use/loop/spend.d.ts +1 -1
  38. package/dist/actors/computer-use/loop/spend.js +3 -3
  39. package/dist/actors/computer-use/loop/trace.js +2 -2
  40. package/dist/actors/computer-use/loop/types.d.ts +14 -5
  41. package/dist/actors/computer-use/loop.js +4 -4
  42. package/dist/actors/computer-use/openai-provider.d.ts +1 -1
  43. package/dist/actors/computer-use/openai-provider.js +2 -2
  44. package/dist/actors/contract.d.ts +10 -8
  45. package/dist/actors/contract.js +7 -1
  46. package/dist/actors/local-agent/cli.js +1 -1
  47. package/dist/actors/scripted-browser/actor.d.ts +2 -2
  48. package/dist/actors/scripted-browser/journey.js +15 -4
  49. package/dist/actors/scripted-browser/steps.js +18 -0
  50. package/dist/actors/scripted-browser/types.d.ts +11 -1
  51. package/dist/actors/stop-conditions.js +1 -3
  52. package/dist/analysis/automatic-completion.d.ts +13 -8
  53. package/dist/analysis/automatic-completion.js +14 -8
  54. package/dist/analysis/automatic-config.d.ts +1 -1
  55. package/dist/analysis/automatic-config.js +2 -2
  56. package/dist/analysis/automatic.d.ts +10 -4
  57. package/dist/analysis/automatic.js +17 -13
  58. package/dist/analysis/diagnostics.d.ts +23 -0
  59. package/dist/analysis/diagnostics.js +112 -0
  60. package/dist/analysis/evidence-sources.js +2 -2
  61. package/dist/analysis/evidence.js +6 -6
  62. package/dist/analysis/execute.d.ts +7 -1
  63. package/dist/analysis/execute.js +39 -12
  64. package/dist/analysis/job.d.ts +8 -5
  65. package/dist/analysis/job.js +15 -14
  66. package/dist/analysis/load.d.ts +1 -1
  67. package/dist/analysis/load.js +5 -5
  68. package/dist/analysis/provider.d.ts +9 -1
  69. package/dist/analysis/restricted-codex.d.ts +2 -0
  70. package/dist/analysis/restricted-codex.js +10 -1
  71. package/dist/analysis/service.d.ts +2 -0
  72. package/dist/analysis/service.js +31 -12
  73. package/dist/analysis/sharing.d.ts +2 -2
  74. package/dist/analysis/sharing.js +5 -5
  75. package/dist/analysis/store-executions.d.ts +5 -5
  76. package/dist/analysis/store-executions.js +12 -12
  77. package/dist/analysis/store.d.ts +4 -4
  78. package/dist/analysis/store.js +13 -13
  79. package/dist/cli/commands/analysis-signals.d.ts +2 -1
  80. package/dist/cli/commands/analysis-signals.js +4 -1
  81. package/dist/cli/commands/analyze.js +4 -2
  82. package/dist/cli/commands/comms.js +8 -1
  83. package/dist/cli/commands/lab-route-computer-use.d.ts +0 -2
  84. package/dist/cli/commands/lab-route-computer-use.js +26 -14
  85. package/dist/cli/commands/lab-route-preview.d.ts +1 -3
  86. package/dist/cli/commands/lab-route-preview.js +3 -4
  87. package/dist/cli/commands/lab-route-run.d.ts +6 -4
  88. package/dist/cli/commands/lab-route-run.js +6 -2
  89. package/dist/cli/commands/lab-route-scripted.d.ts +0 -2
  90. package/dist/cli/commands/lab-route-scripted.js +0 -1
  91. package/dist/cli/commands/lab-route-shared-world.d.ts +0 -2
  92. package/dist/cli/commands/lab-route-shared-world.js +0 -1
  93. package/dist/cli/commands/lab-route-terminal.d.ts +0 -2
  94. package/dist/cli/commands/lab-route-terminal.js +0 -1
  95. package/dist/cli/commands/lab-run.js +76 -45
  96. package/dist/cli/commands/lab-scorer.d.ts +0 -2
  97. package/dist/cli/commands/lab.js +12 -6
  98. package/dist/cli/commands/observe.js +22 -0
  99. package/dist/cli/commands/run-signals.d.ts +30 -0
  100. package/dist/cli/commands/run-signals.js +146 -0
  101. package/dist/cli/commands/runs.js +10 -8
  102. package/dist/cli/commands/watch.js +12 -10
  103. package/dist/cli/doctor.d.ts +3 -0
  104. package/dist/cli/doctor.js +10 -2
  105. package/dist/cli/io.d.ts +5 -4
  106. package/dist/cli/io.js +12 -8
  107. package/dist/cli/program.js +3 -3
  108. package/dist/cli/renamed-options.d.ts +11 -0
  109. package/dist/cli/renamed-options.js +18 -0
  110. package/dist/cli/telemetry.d.ts +2 -2
  111. package/dist/cli/telemetry.js +1 -1
  112. package/dist/comms/capture-surface.d.ts +1 -1
  113. package/dist/comms/catch-host.d.ts +1 -1
  114. package/dist/comms/connections.js +4 -4
  115. package/dist/comms/external-evidence.d.ts +27 -0
  116. package/dist/comms/external-evidence.js +93 -0
  117. package/dist/comms/lease-store.js +7 -7
  118. package/dist/comms/types.js +1 -1
  119. package/dist/evidence/browser-hygiene.d.ts +1 -1
  120. package/dist/evidence/browser-hygiene.js +1 -1
  121. package/dist/evidence/redaction.js +1 -1
  122. package/dist/evidence/secret-scrub.d.ts +9 -0
  123. package/dist/evidence/secret-scrub.js +96 -0
  124. package/dist/feedback/draft.js +7 -9
  125. package/dist/feedback/export-bundle.js +4 -4
  126. package/dist/feedback/export.js +9 -9
  127. package/dist/feedback/feedback.d.ts +1 -1
  128. package/dist/index.d.ts +3 -6
  129. package/dist/index.js +3 -6
  130. package/dist/keys/key-resolution.d.ts +3 -1
  131. package/dist/keys/key-resolution.js +18 -16
  132. package/dist/lab/adapter-extension.d.ts +28 -6
  133. package/dist/lab/adapter-extension.js +65 -126
  134. package/dist/lab/adapter-scorer-loader.d.ts +25 -5
  135. package/dist/lab/adapter-scorer-loader.js +24 -0
  136. package/dist/lab/composition-rules.d.ts +2 -0
  137. package/dist/lab/composition-rules.js +35 -26
  138. package/dist/lab/config.js +28 -26
  139. package/dist/lab/device-presets.d.ts +2 -2
  140. package/dist/lab/discover.js +1 -3
  141. package/dist/lab/doctor.d.ts +44 -9
  142. package/dist/lab/doctor.js +149 -41
  143. package/dist/lab/init-plan.js +1 -3
  144. package/dist/lab/keys.js +1 -1
  145. package/dist/lab/lab-deps.d.ts +85 -0
  146. package/dist/lab/lab-deps.js +4 -0
  147. package/dist/lab/parse/actors.js +8 -7
  148. package/dist/lab/parse/comms.js +3 -2
  149. package/dist/lab/parse/execution.js +3 -2
  150. package/dist/lab/parse/subject-state.js +2 -1
  151. package/dist/lab/parse/subject.js +2 -1
  152. package/dist/lab/parse/values.d.ts +0 -1
  153. package/dist/lab/parse/values.js +0 -3
  154. package/dist/lab/persona-resolve.d.ts +3 -3
  155. package/dist/lab/persona-resolve.js +4 -4
  156. package/dist/lab/persona.js +1 -3
  157. package/dist/lab/plan-base.d.ts +6 -2
  158. package/dist/lab/plan-base.js +22 -7
  159. package/dist/lab/plan-participants.d.ts +5 -5
  160. package/dist/lab/plan-participants.js +2 -2
  161. package/dist/lab/plan-types.d.ts +33 -7
  162. package/dist/lab/plan.d.ts +3 -11
  163. package/dist/lab/plan.js +18 -42
  164. package/dist/lab/preflight-result.js +0 -2
  165. package/dist/lab/preflight.d.ts +0 -3
  166. package/dist/lab/preflight.js +1 -1
  167. package/dist/lab/requirements.d.ts +20 -0
  168. package/dist/lab/requirements.js +54 -0
  169. package/dist/lab/route-inputs.d.ts +23 -12
  170. package/dist/lab/route-inputs.js +48 -51
  171. package/dist/lab/routing.d.ts +19 -24
  172. package/dist/lab/routing.js +14 -47
  173. package/dist/lab/run-lab-events.d.ts +6 -11
  174. package/dist/lab/run-lab-events.js +3 -11
  175. package/dist/lab/run-lab-homes.d.ts +64 -0
  176. package/dist/lab/run-lab-homes.js +3 -0
  177. package/dist/lab/run-lab-options.d.ts +12 -66
  178. package/dist/lab/run-lab-options.js +45 -275
  179. package/dist/lab/summary.d.ts +9 -4
  180. package/dist/lab/summary.js +15 -8
  181. package/dist/lab/types.d.ts +132 -132
  182. package/dist/lab/validation.d.ts +15 -15
  183. package/dist/lab/validation.js +28 -28
  184. package/dist/lab/warnings.js +20 -19
  185. package/dist/observer/artifact.d.ts +1 -1
  186. package/dist/observer/artifact.js +3 -3
  187. package/dist/observer/data.js +2 -2
  188. package/dist/observer/render.js +2 -2
  189. package/dist/observer/run-routes.d.ts +1 -1
  190. package/dist/observer/run-routes.js +5 -5
  191. package/dist/observer/serve.d.ts +17 -0
  192. package/dist/observer/serve.js +34 -3
  193. package/dist/observer-app.html +1 -1
  194. package/dist/routes/computer-use/bundle-parts.d.ts +1 -1
  195. package/dist/routes/computer-use/bundle-parts.js +10 -3
  196. package/dist/routes/computer-use/bundle.d.ts +4 -11
  197. package/dist/routes/computer-use/bundle.js +9 -15
  198. package/dist/routes/computer-use/diagnostics.d.ts +1 -1
  199. package/dist/routes/computer-use/diagnostics.js +1 -1
  200. package/dist/routes/computer-use/e2b-desktop/comms.d.ts +10 -10
  201. package/dist/routes/computer-use/e2b-desktop/comms.js +11 -14
  202. package/dist/routes/computer-use/e2b-desktop/desktop.d.ts +2 -2
  203. package/dist/routes/computer-use/e2b-desktop/desktop.js +4 -7
  204. package/dist/routes/computer-use/e2b-desktop/fidelity.d.ts +13 -13
  205. package/dist/routes/computer-use/e2b-desktop/fidelity.js +11 -11
  206. package/dist/routes/computer-use/e2b-desktop/prepare.d.ts +3 -3
  207. package/dist/routes/computer-use/e2b-desktop/prepare.js +33 -36
  208. package/dist/routes/computer-use/e2b-desktop/start.d.ts +1 -1
  209. package/dist/routes/computer-use/e2b-desktop/start.js +24 -23
  210. package/dist/routes/computer-use/e2b-desktop/state.d.ts +5 -4
  211. package/dist/routes/computer-use/e2b-desktop/state.js +5 -3
  212. package/dist/routes/computer-use/e2b-desktop/teardown.d.ts +1 -1
  213. package/dist/routes/computer-use/e2b-desktop/teardown.js +29 -17
  214. package/dist/routes/computer-use/external-comms.d.ts +4 -4
  215. package/dist/routes/computer-use/external-comms.js +19 -43
  216. package/dist/routes/computer-use/fanout-bundle.d.ts +3 -3
  217. package/dist/routes/computer-use/fanout-bundle.js +25 -29
  218. package/dist/routes/computer-use/{fanout-lanes.js → fanout-records.js} +25 -19
  219. package/dist/routes/computer-use/in-process-desktop.d.ts +3 -10
  220. package/dist/routes/computer-use/in-process-desktop.js +3 -9
  221. package/dist/routes/computer-use/live-flush.d.ts +7 -5
  222. package/dist/routes/computer-use/live-flush.js +19 -27
  223. package/dist/routes/computer-use/{run-lanes.js → live-phase.js} +14 -13
  224. package/dist/routes/computer-use/local-tree-pack.d.ts +3 -3
  225. package/dist/routes/computer-use/local-tree-pack.js +4 -5
  226. package/dist/routes/computer-use/local-vm.d.ts +11 -8
  227. package/dist/routes/computer-use/local-vm.js +39 -66
  228. package/dist/routes/computer-use/participant-desktop.d.ts +8 -23
  229. package/dist/routes/computer-use/participant-desktop.js +5 -25
  230. package/dist/routes/computer-use/{lanes.d.ts → participant-execution.d.ts} +10 -10
  231. package/dist/routes/computer-use/{lanes.js → participant-execution.js} +35 -22
  232. package/dist/routes/computer-use/participant-facts.d.ts +7 -1
  233. package/dist/routes/computer-use/participant-facts.js +12 -1
  234. package/dist/routes/computer-use/participant-model.d.ts +19 -11
  235. package/dist/routes/computer-use/participant-model.js +58 -33
  236. package/dist/routes/computer-use/participant-prompt.d.ts +3 -3
  237. package/dist/routes/computer-use/participant-prompt.js +4 -4
  238. package/dist/routes/computer-use/participant-runs.d.ts +6 -6
  239. package/dist/routes/computer-use/participant-runs.js +8 -8
  240. package/dist/routes/computer-use/plan.d.ts +21 -29
  241. package/dist/routes/computer-use/plan.js +59 -65
  242. package/dist/routes/computer-use/preflight.d.ts +6 -11
  243. package/dist/routes/computer-use/preflight.js +26 -18
  244. package/dist/routes/computer-use/rerun-selection.js +10 -6
  245. package/dist/routes/computer-use/result.d.ts +1 -1
  246. package/dist/routes/computer-use/result.js +40 -30
  247. package/dist/routes/computer-use/route.d.ts +3 -4
  248. package/dist/routes/computer-use/route.js +21 -19
  249. package/dist/routes/computer-use/self-report.d.ts +2 -2
  250. package/dist/routes/computer-use/self-report.js +4 -4
  251. package/dist/routes/computer-use/setup.d.ts +8 -17
  252. package/dist/routes/computer-use/setup.js +98 -86
  253. package/dist/routes/computer-use/single-bundle.d.ts +8 -11
  254. package/dist/routes/computer-use/single-bundle.js +20 -25
  255. package/dist/routes/computer-use/subject-projection.d.ts +5 -7
  256. package/dist/routes/computer-use/subject-projection.js +20 -19
  257. package/dist/routes/computer-use/types.d.ts +169 -211
  258. package/dist/routes/computer-use/types.js +13 -6
  259. package/dist/routes/preview.js +0 -1
  260. package/dist/routes/scripted/bundle.d.ts +3 -6
  261. package/dist/routes/scripted/bundle.js +11 -16
  262. package/dist/routes/scripted/plan.d.ts +5 -7
  263. package/dist/routes/scripted/plan.js +6 -4
  264. package/dist/routes/scripted/result.d.ts +4 -1
  265. package/dist/routes/scripted/result.js +10 -6
  266. package/dist/routes/scripted/route.js +10 -11
  267. package/dist/routes/scripted/scenario.d.ts +1 -1
  268. package/dist/routes/scripted/scenario.js +1 -1
  269. package/dist/routes/scripted/setup.d.ts +3 -2
  270. package/dist/routes/scripted/setup.js +22 -21
  271. package/dist/routes/scripted/subject.d.ts +8 -3
  272. package/dist/routes/scripted/subject.js +11 -6
  273. package/dist/routes/scripted/surface-records.js +1 -1
  274. package/dist/routes/scripted/surface-sessions.d.ts +2 -2
  275. package/dist/routes/scripted/surface-sessions.js +4 -4
  276. package/dist/routes/scripted/types.d.ts +19 -36
  277. package/dist/routes/scripted/types.js +1 -2
  278. package/dist/routes/shared-world/{seat-records.js → bundle-records.js} +8 -8
  279. package/dist/routes/shared-world/bundle.d.ts +2 -2
  280. package/dist/routes/shared-world/bundle.js +22 -26
  281. package/dist/routes/shared-world/checkpoints.d.ts +4 -4
  282. package/dist/routes/shared-world/checkpoints.js +4 -4
  283. package/dist/routes/shared-world/comms.d.ts +5 -4
  284. package/dist/routes/shared-world/comms.js +28 -41
  285. package/dist/routes/shared-world/external-public.d.ts +5 -5
  286. package/dist/routes/shared-world/external-public.js +19 -20
  287. package/dist/routes/shared-world/handoff.d.ts +4 -4
  288. package/dist/routes/shared-world/handoff.js +50 -50
  289. package/dist/routes/shared-world/lobby-code.d.ts +5 -5
  290. package/dist/routes/shared-world/lobby-code.js +13 -13
  291. package/dist/routes/shared-world/{seats.d.ts → participant-specs.d.ts} +8 -6
  292. package/dist/routes/shared-world/{seats.js → participant-specs.js} +46 -51
  293. package/dist/routes/shared-world/plan.d.ts +2 -6
  294. package/dist/routes/shared-world/plan.js +1 -2
  295. package/dist/routes/shared-world/provenance.d.ts +4 -4
  296. package/dist/routes/shared-world/provenance.js +4 -4
  297. package/dist/routes/shared-world/provisioned.d.ts +3 -2
  298. package/dist/routes/shared-world/provisioned.js +48 -41
  299. package/dist/routes/shared-world/result.js +31 -19
  300. package/dist/routes/shared-world/route.js +37 -41
  301. package/dist/routes/shared-world/setup.d.ts +5 -4
  302. package/dist/routes/shared-world/setup.js +12 -14
  303. package/dist/routes/shared-world/types.d.ts +53 -126
  304. package/dist/routes/shared-world/types.js +2 -2
  305. package/dist/routes/terminal/adapter.d.ts +8 -8
  306. package/dist/routes/terminal/adapter.js +28 -125
  307. package/dist/routes/terminal/bundle.d.ts +7 -12
  308. package/dist/routes/terminal/bundle.js +24 -34
  309. package/dist/routes/terminal/credentials.d.ts +2 -2
  310. package/dist/routes/terminal/credentials.js +16 -16
  311. package/dist/routes/terminal/dry-run.d.ts +1 -1
  312. package/dist/routes/terminal/dry-run.js +9 -11
  313. package/dist/routes/terminal/encoding.d.ts +1 -1
  314. package/dist/routes/terminal/encoding.js +2 -2
  315. package/dist/routes/terminal/ledger.d.ts +6 -6
  316. package/dist/routes/terminal/ledger.js +9 -9
  317. package/dist/routes/terminal/live-finish.d.ts +1 -2
  318. package/dist/routes/terminal/live-finish.js +21 -20
  319. package/dist/routes/terminal/live-sandbox.d.ts +4 -2
  320. package/dist/routes/terminal/live-sandbox.js +25 -21
  321. package/dist/routes/terminal/participant-text.d.ts +23 -0
  322. package/dist/routes/terminal/participant-text.js +165 -0
  323. package/dist/routes/terminal/plan.d.ts +2 -6
  324. package/dist/routes/terminal/plan.js +13 -9
  325. package/dist/routes/terminal/recorder.d.ts +6 -1
  326. package/dist/routes/terminal/recorder.js +12 -4
  327. package/dist/routes/terminal/result.js +4 -4
  328. package/dist/routes/terminal/route.js +26 -26
  329. package/dist/routes/terminal/runtime.d.ts +3 -2
  330. package/dist/routes/terminal/runtime.js +3 -3
  331. package/dist/routes/terminal/sandbox.d.ts +5 -3
  332. package/dist/routes/terminal/sandbox.js +13 -16
  333. package/dist/routes/terminal/session.js +16 -14
  334. package/dist/routes/terminal/token-usage.js +5 -5
  335. package/dist/routes/terminal/trace.d.ts +5 -8
  336. package/dist/routes/terminal/trace.js +9 -64
  337. package/dist/routes/terminal/types.d.ts +85 -93
  338. package/dist/routes/terminal/types.js +9 -4
  339. package/dist/run/active-runs.d.ts +13 -0
  340. package/dist/run/active-runs.js +12 -0
  341. package/dist/run/bundle-shape.d.ts +2 -1
  342. package/dist/run/bundle-shape.js +4 -4
  343. package/dist/run/bundle.d.ts +63 -56
  344. package/dist/run/bundle.js +9 -8
  345. package/dist/run/cost-summary.js +3 -2
  346. package/dist/run/costs.d.ts +6 -6
  347. package/dist/run/costs.js +10 -10
  348. package/dist/run/detail.d.ts +5 -5
  349. package/dist/run/detail.js +6 -6
  350. package/dist/run/dry-run.js +5 -12
  351. package/dist/run/{study-files.d.ts → evidence-files.d.ts} +4 -4
  352. package/dist/run/{study-files.js → evidence-files.js} +5 -5
  353. package/dist/run/feedback-shape.js +1 -1
  354. package/dist/run/judge.d.ts +16 -4
  355. package/dist/run/judge.js +24 -7
  356. package/dist/run/locate.d.ts +2 -0
  357. package/dist/run/locate.js +3 -1
  358. package/dist/run/outcomes.d.ts +3 -3
  359. package/dist/run/outcomes.js +3 -3
  360. package/dist/run/participant-records.d.ts +2 -2
  361. package/dist/run/participant-records.js +2 -2
  362. package/dist/run/paths.js +1 -1
  363. package/dist/run/pricing.d.ts +19 -9
  364. package/dist/run/pricing.js +30 -18
  365. package/dist/run/projection.d.ts +13 -13
  366. package/dist/run/projection.js +8 -8
  367. package/dist/run/reclaim.d.ts +7 -1
  368. package/dist/run/reclaim.js +24 -4
  369. package/dist/run/results.d.ts +1 -1
  370. package/dist/run/run-index.d.ts +1 -1
  371. package/dist/run/run-index.js +11 -11
  372. package/dist/run/run.d.ts +4 -2
  373. package/dist/run/run.js +9 -5
  374. package/dist/run/sandbox-receipts.d.ts +4 -4
  375. package/dist/run/sandbox-receipts.js +4 -4
  376. package/dist/run/shared-world-evidence.d.ts +47 -47
  377. package/dist/run/shared-world-shape.d.ts +3 -3
  378. package/dist/run/shared-world-shape.js +11 -11
  379. package/dist/run/stats.d.ts +5 -5
  380. package/dist/run/stats.js +8 -8
  381. package/dist/run/status.d.ts +16 -6
  382. package/dist/run/status.js +31 -8
  383. package/dist/run/streams.d.ts +26 -19
  384. package/dist/run/terminal-contract.d.ts +5 -5
  385. package/dist/run/terminal-contract.js +4 -4
  386. package/dist/run/transient-comms-secrets.d.ts +5 -0
  387. package/dist/run/transient-comms-secrets.js +12 -0
  388. package/dist/run-lab.d.ts +36 -34
  389. package/dist/run-lab.js +41 -37
  390. package/dist/subject/desktop-cli.d.ts +1 -1
  391. package/dist/subject/desktop-cli.js +1 -1
  392. package/dist/subject/local-tree-archive.d.ts +1 -1
  393. package/dist/subject/local-tree-archive.js +4 -4
  394. package/dist/subject/local-tree.d.ts +2 -2
  395. package/dist/subject/local-tree.js +1 -1
  396. package/dist/subject/node-bootstrap.d.ts +1 -1
  397. package/dist/subject/node-bootstrap.js +4 -4
  398. package/dist/subject/runtime.js +5 -5
  399. package/dist/subject/serve.js +1 -1
  400. package/dist/subject/steps.d.ts +4 -4
  401. package/dist/subject/steps.js +5 -5
  402. package/dist/substrates/desktop-session.d.ts +2 -0
  403. package/dist/substrates/e2b/cdp-probe.d.ts +2 -2
  404. package/dist/substrates/e2b/cdp-probe.js +1 -1
  405. package/dist/substrates/e2b/desktop-browser.d.ts +3 -3
  406. package/dist/substrates/e2b/desktop-browser.js +4 -4
  407. package/dist/substrates/e2b/desktop-cdp.d.ts +7 -7
  408. package/dist/substrates/e2b/desktop-cdp.js +4 -4
  409. package/dist/substrates/e2b/desktop-geometry.d.ts +4 -4
  410. package/dist/substrates/e2b/desktop-geometry.js +3 -3
  411. package/dist/substrates/e2b/desktop-media.js +2 -2
  412. package/dist/substrates/e2b/sandbox.d.ts +2 -0
  413. package/dist/substrates/e2b/sandbox.js +22 -8
  414. package/dist/substrates/e2b/sdk.d.ts +12 -1
  415. package/dist/substrates/e2b/sdk.js +30 -9
  416. package/dist/substrates/local/runtime-host.d.ts +2 -0
  417. package/dist/substrates/local/runtime-host.js +6 -0
  418. package/dist/tui/actions.d.ts +7 -5
  419. package/dist/tui/actions.js +18 -9
  420. package/dist/tui-app.js +42 -42
  421. package/dist/verify/actor.d.ts +10 -10
  422. package/dist/verify/actor.js +15 -15
  423. package/dist/verify/artifacts.d.ts +1 -1
  424. package/dist/verify/artifacts.js +3 -3
  425. package/dist/verify/costs.d.ts +2 -2
  426. package/dist/verify/costs.js +2 -2
  427. package/dist/verify/liveness.d.ts +1 -1
  428. package/dist/verify/liveness.js +4 -1
  429. package/dist/verify/rerun.d.ts +1 -1
  430. package/dist/verify/rerun.js +1 -1
  431. package/dist/verify/shared-world.js +2 -2
  432. package/dist/verify/verify.js +6 -6
  433. package/docs/README.md +1 -1
  434. package/docs/architecture/actor-contract.md +60 -22
  435. package/docs/architecture/desktop-sessions.md +9 -9
  436. package/docs/architecture/external-public-shared-world.md +5 -0
  437. package/docs/architecture/observer.md +4 -4
  438. package/docs/architecture/restricted-codex-analysis.md +40 -4
  439. package/docs/architecture/state-driven-executor.md +4 -5
  440. package/docs/architecture/task-protocol-support.md +3 -5
  441. package/docs/architecture/{terminal-product-lane.md → terminal-product-route.md} +24 -16
  442. package/docs/contracts/run-bundle.md +10 -8
  443. package/docs/contracts/schemas.md +109 -53
  444. package/docs/contracts/study-analysis.md +24 -0
  445. package/docs/decisions/0004-participant-desktops-stay-in-the-route.md +2 -1
  446. package/docs/product/automatic-analysis.md +1 -0
  447. package/docs/ramp/README.md +2 -1
  448. package/package.json +4 -4
  449. package/skills/humanish/SKILL.md +3 -2
  450. package/skills/humanish/agents/openai.yaml +1 -1
  451. package/dist/deprecated.d.ts +0 -90
  452. package/dist/deprecated.js +0 -106
  453. package/dist/lab/bag-overrides.d.ts +0 -18
  454. package/dist/lab/bag-overrides.js +0 -121
  455. package/dist/routes/computer-use/legacy-lane-spec.d.ts +0 -62
  456. package/dist/routes/computer-use/legacy-lane-spec.js +0 -39
  457. /package/dist/routes/computer-use/{fanout-lanes.d.ts → fanout-records.d.ts} +0 -0
  458. /package/dist/routes/computer-use/{run-lanes.d.ts → live-phase.d.ts} +0 -0
  459. /package/dist/routes/shared-world/{seat-records.d.ts → bundle-records.d.ts} +0 -0
@@ -26,10 +26,11 @@ import path from "node:path";
26
26
  import { completeAutomaticAnalysis } from "../../analysis/automatic-completion.js";
27
27
  import { runScope } from "../../run/run.js";
28
28
  import { resolveAutomaticAnalysis } from "../../analysis/automatic-config.js";
29
- import { computerUseInputWithScorer } from "../../lab/route-inputs.js";
30
- import { planComputerUseLab } from "./plan.js";
29
+ import { browserRouteScorer } from "../../lab/adapter-scorer-loader.js";
30
+ import { withLateScorer } from "../../lab/route-inputs.js";
31
+ import { callerDrivingOf, planComputerUseLab } from "./plan.js";
31
32
  import { finishCuaRun } from "./result.js";
32
- import { runLabParticipants } from "./run-lanes.js";
33
+ import { runLabParticipants } from "./live-phase.js";
33
34
  import { admitCuaRun, refuseCuaLab, startCuaRun } from "./setup.js";
34
35
  import { CUA_ACTOR_LAB_SCHEMA, } from "./types.js";
35
36
  /**
@@ -38,12 +39,12 @@ import { CUA_ACTOR_LAB_SCHEMA, } from "./types.js";
38
39
  * run and its analysis.
39
40
  */
40
41
  export async function runCuaActorLab(options) {
41
- const { config, dryRun, lab, ...input } = options;
42
+ const { config, dryRun, ...input } = options;
42
43
  // planComputerUseLab makes every configuration refusal, in the order this route always has.
43
44
  const planned = planComputerUseLab(config, {
44
45
  dryRun,
45
- ...(lab === undefined ? {} : { lab }),
46
- ...(input.hooks === undefined ? {} : { hooks: input.hooks }),
46
+ hasRunSession: input.deps?.runSession !== undefined,
47
+ driving: callerDrivingOf(input),
47
48
  ...(input.countOverride === undefined ? {} : { countOverride: input.countOverride }),
48
49
  ...(input.rerun === undefined ? {} : { rerun: input.rerun }),
49
50
  });
@@ -53,7 +54,7 @@ export async function runCuaActorLab(options) {
53
54
  }
54
55
  /**
55
56
  * A refused computer-use lab's result, at the refusal's stage: a before-scope refusal has its own
56
- * envelope and no analysis record; the others come after the cwd checks, and the lane cap after
57
+ * envelope and no analysis record; the others come after the cwd checks, and the participant cap after
57
58
  * the personas are read.
58
59
  */
59
60
  export async function computerUseLabRefusal(options, refusal) {
@@ -72,9 +73,9 @@ export async function computerUseLabRefusal(options, refusal) {
72
73
  warnings: [],
73
74
  error: { code: refusal.code, message: refusal.message },
74
75
  };
75
- // The other refusals come after the cwd checks, and the lane cap after the personas are read.
76
+ // The other refusals come after the cwd checks, and the participant cap after the personas are read.
76
77
  const analysis = resolveAutomaticAnalysis(config.review?.analysis);
77
- return completeAutomaticAnalysis(await refuseCuaLab(options, refusal), undefined, analysis.ok ? analysis.config : undefined, options.automaticAnalysis, { trigger: config.review?.analysis === undefined ? "default" : "explicit" });
78
+ return completeAutomaticAnalysis(await refuseCuaLab(options, refusal), undefined, analysis.ok ? analysis.config : undefined, options, { trigger: config.review?.analysis === undefined ? "default" : "explicit" });
78
79
  }
79
80
  /**
80
81
  * runLab's step for a computer-use plan. It runs the plan's local checks (admitCuaRun: the
@@ -92,24 +93,22 @@ export async function admitComputerUsePlan(plan, input, config) {
92
93
  return {
93
94
  ok: true,
94
95
  run: async (scorer) => {
95
- const running = computerUseInputWithScorer(input, scorer);
96
- // The scorer's hooks wrap the admitted bag, so the runSession, provider and desktop the
97
- // checks admitted stay the ones the run uses.
98
- const admitted = { ...admission.admitted, hooks: running.hooks ?? admission.admitted.hooks };
99
- return cuaOutcome(await runAdmittedCuaRun(plan, running, admitted));
96
+ // The scorer joins the input only; the runSession, provider and desktop the checks admitted
97
+ // stay the ones the run uses.
98
+ const running = withLateScorer(input, scorer, browserRouteScorer);
99
+ return cuaOutcome(await runAdmittedCuaRun(plan, running, admission.admitted));
100
100
  },
101
101
  };
102
102
  }
103
103
  function cuaOutcome(result) {
104
- return { route: "computer-use", backend: "cua", result };
104
+ return { route: "computer-use", result };
105
105
  }
106
106
  /**
107
107
  * Run a computer-use plan: its local checks, then the run. The run scope in runAdmittedCuaRun
108
108
  * finalizes any status record the run opened, on every exit, so a test or library caller does not
109
109
  * leave the 5 s status cadence writing into a directory something else is deleting (an unrelated
110
- * ENOTEMPTY). Participants come from the plan. `config` is still read for values the plan does not
111
- * carry yet (the actor's model and local agent, persona ids, comms settings, the per-participant
112
- * cap) and by the compatibility hooks, which take the whole config.
110
+ * ENOTEMPTY). Participants, the brain, the subject, the caps and the residual config come from the
111
+ * plan. `config` is what the caller's createProvider and inProcess executor receive.
113
112
  */
114
113
  export async function runComputerUsePlan(plan, input, config) {
115
114
  const admission = await admitCuaRun(plan, input, config);
@@ -129,9 +128,12 @@ function runAdmittedCuaRun(plan, input, admitted) {
129
128
  });
130
129
  }
131
130
  function completeCuaAnalysis(plan, input, result, finished) {
132
- return completeAutomaticAnalysis(result, finished, plan.analysis?.config, input.automaticAnalysis, {
131
+ // A local VM study whose cleanup is unconfirmed records a skip instead of analyzing.
132
+ const refusal = input.localVm?.analysisRefusal;
133
+ return completeAutomaticAnalysis(result, finished, plan.analysis?.config, input, {
133
134
  ...(plan.analysis === undefined ? {} : { trigger: plan.analysis.trigger }),
134
135
  preferLargerOutput: plan.analysis?.preferLargerOutput === true,
136
+ ...(refusal === undefined ? {} : { refusal }),
135
137
  });
136
138
  }
137
139
  async function runPlanInScope(plan, input, admitted, scope) {
@@ -1,12 +1,12 @@
1
1
  import type { CuaLoopResult } from "../../actors/computer-use/loop.js";
2
2
  import { type SessionEnding } from "../../run/judge.js";
3
3
  /**
4
- * A goal_satisfied lane counts as a self-reported blocker ONLY when its final narrative contradicts
4
+ * A goal_satisfied participant counts as a self-reported blocker ONLY when its final narrative contradicts
5
5
  * the goal AND the run's own stop predicate did NOT fire. A matched stopWhen is independent,
6
6
  * structured completion evidence, so it overrides a text scan of the free-form narrative — which can
7
7
  * otherwise trip on the subject app's OWN quoted copy (e.g. a relayed "cannot be undone" banner).
8
8
  * Resolved-arc segments never block the verdict (#453). Returns the offending reason, or undefined
9
- * when the lane is a clean pass. Exported for testing.
9
+ * when the participant is a clean pass. Exported for testing.
10
10
  */
11
11
  export declare function resolveSelfReportedBlocker(session: CuaLoopResult | undefined): string | undefined;
12
12
  /** A session's ending, reduced to what the judge's engagement and blocker rules read. */
@@ -20,7 +20,7 @@ function hasBlockerLanguage(text) {
20
20
  // Report-shaped language: what a participant writes when it finished AND has something to say.
21
21
  // Every one of the day's eleven drawDB reports (2026-09-01) opened a section "What confused me"
22
22
  // or "Accessibility defects:"; none contained a blocker word, so none became a feedback candidate
23
- // and a lane that had just replicated a keyboard-accessibility defect three times drafted "Live
23
+ // and a participant that had just replicated a keyboard-accessibility defect three times drafted "Live
24
24
  // study completed without a participant-reported finding". Friction is the INCLUSIVE scan; a
25
25
  // false positive here adds a candidate a person then reads, which is the cheap direction.
26
26
  const REPORTED_DEFECT_LANGUAGE = /\b(defects?|bugs?|accessibilit(y|ies)|inaccessible|not (keyboard|screen.?reader)[- ]?accessible|confus(ed|ing)|hesitat(ed|ion)|unexpected(ly)?|unclear|hard to (find|tell|see|read|reach)|no (visible )?focus|overlap(ped|ping|s)?|truncat(ed|es|ion)|cut off|did nothing|nothing happened|no effect)\b/;
@@ -94,7 +94,7 @@ function completionReasonBlocksVerdict(reason) {
94
94
  // with a parser error. A simpler SQL import succeeded."). The lookahead demands the retry flavor
95
95
  // on purpose: unrelated praise ("Separately, the search box worked") must never launder an
96
96
  // unresolved failure. "Login failed so I gave up" has no recovery anywhere and stays a blocker.
97
- // (#453 — the run-1 false negative: a defect report after demonstrated success failed the lane,
97
+ // (#453 — the run-1 false negative: a defect report after demonstrated success failed the participant,
98
98
  // an incentive inversion against exactly the participant behavior a study wants most.)
99
99
  const RESOLUTION_TERMS = /\b(succeed(?:ed|s)?|success(?:ful|fully)?|worked|works around|then worked|now works?|resolved|fixed|recovered|got it working|went through)\b/;
100
100
  const RETRY_RESOLUTION = /\b(simpler|simplified|retry(?:ing)?|retried|second (?:attempt|try)|another (?:attempt|try|approach)|different (?:approach|way|route)|instead|then|eventually|after that)\b[^.!?\n]{0,80}\b(succeed(?:ed|s)?|success(?:ful|fully)?|worked|went through|completed|passed)\b/;
@@ -152,12 +152,12 @@ function traceHasStopWhenMatch(session) {
152
152
  (item.title.startsWith("stopWhen matched") || item.title === "dwell window complete"));
153
153
  }
154
154
  /**
155
- * A goal_satisfied lane counts as a self-reported blocker ONLY when its final narrative contradicts
155
+ * A goal_satisfied participant counts as a self-reported blocker ONLY when its final narrative contradicts
156
156
  * the goal AND the run's own stop predicate did NOT fire. A matched stopWhen is independent,
157
157
  * structured completion evidence, so it overrides a text scan of the free-form narrative — which can
158
158
  * otherwise trip on the subject app's OWN quoted copy (e.g. a relayed "cannot be undone" banner).
159
159
  * Resolved-arc segments never block the verdict (#453). Returns the offending reason, or undefined
160
- * when the lane is a clean pass. Exported for testing.
160
+ * when the participant is a clean pass. Exported for testing.
161
161
  */
162
162
  export function resolveSelfReportedBlocker(session) {
163
163
  return session !== undefined && selfReportedBlocker(blockerFacts(session))
@@ -1,18 +1,17 @@
1
1
  import { type RunScope } from "../../run/run.js";
2
- import { type LocalAgentId } from "../../actors/local-agent/cli.js";
3
2
  import type { CuaActorDescriptor } from "../../actors/registry.js";
4
3
  import type { LabCommsEmail, LabCommsExternal, LabConfig } from "../../lab/types.js";
5
4
  import { type RunRerunLineage } from "../../run/bundle.js";
6
5
  import { type LocalTreeArchive } from "../../subject/local-tree-archive.js";
7
- import { type ComputerUseRefusal, type CuaSubjectRoute } from "./plan.js";
6
+ import { type ComputerUseRefusal } from "./plan.js";
8
7
  import type { ComputerUsePlan } from "../../lab/plan-types.js";
9
8
  import { trackRuntimeStreams, type LiveTraceFlush } from "./live-flush.js";
10
9
  import { type CuaRunBundleBase } from "./bundle.js";
11
10
  import { projectParticipantSubjects } from "./subject-projection.js";
12
- import { type CuaActorLabErrorCode, type CuaActorLabHooks, type CuaActorLabResult, type CuaParticipantDeps, type CuaParticipantPlan, type DesktopParticipantRun, type CuaSubjectProjection, type CuaSubjectProvenanceArg, type ComputerUseRunInput, type RunCuaActorLabOptions } from "./types.js";
11
+ import { type CuaActorLabErrorCode, type CuaActorLabResult, type CuaParticipantDeps, type CuaParticipantPlan, type DesktopParticipantRun, type CuaSubjectProjection, type CuaSubjectProvenanceArg, type ComputerUseRunInput, type RunCuaActorLabOptions } from "./types.js";
13
12
  /**
14
- * The envelope of a refusal the plan left for after the cwd checks. The lane cap and in-process
15
- * fan-out refusals come after the committed personas are read, so a persona-file error still wins.
13
+ * The envelope of a refusal the plan left for after the cwd checks. The participant cap and
14
+ * in-process fan-out refusals come after the committed personas are read, so a persona-file error still wins.
16
15
  */
17
16
  export declare function refuseCuaLab(options: RunCuaActorLabOptions, refusal: ComputerUseRefusal): Promise<CuaActorLabResult>;
18
17
  export type AdmittedCuaRun = Extract<Awaited<ReturnType<typeof admitCuaRun>>, {
@@ -25,13 +24,9 @@ type StartedRun = Extract<Awaited<ReturnType<RunScope["startRun"]>>, {
25
24
  export interface CuaRunSetup {
26
25
  plan: ComputerUsePlan;
27
26
  input: ComputerUseRunInput;
28
- /** Read for values the plan does not carry yet, and by the compatibility hooks, which take the
29
- * whole config. Participants come from the plan. */
30
- config: LabConfig;
31
27
  /** The physical project root. */
32
28
  cwd: string;
33
29
  descriptor: CuaActorDescriptor;
34
- subjectRoute: CuaSubjectRoute;
35
30
  run: StartedRun;
36
31
  streams: ReturnType<typeof trackRuntimeStreams>;
37
32
  participantRuns: DesktopParticipantRun[];
@@ -67,7 +62,6 @@ export interface CuaParticipantsSetup {
67
62
  }
68
63
  /** What only finishCuaRun reads besides the participants' outcomes. */
69
64
  export interface CuaFinishFacts {
70
- hooks: CuaActorLabHooks;
71
65
  rerunLineage: RunRerunLineage | undefined;
72
66
  publicRepo: string | undefined;
73
67
  subjectArgs: Omit<Parameters<typeof projectParticipantSubjects>[0], "outcomes" | "dryRun">;
@@ -96,16 +90,16 @@ export declare function admitCuaRun(plan: ComputerUsePlan, input: ComputerUseRun
96
90
  config: LabConfig;
97
91
  dryRun: boolean;
98
92
  cwd: string;
99
- hooks: CuaActorLabHooks;
93
+ seams: import("../../lab/lab-deps.js").LabDeps;
100
94
  streams: {
101
- hooks: CuaActorLabHooks;
95
+ onStream: NonNullable<import("../../lab/run-lab-homes.js").RunLabHomes["onStream"]>;
102
96
  showIn: (observer: import("../../index.js").ObserverResult & {
103
97
  ok: true;
104
98
  }) => void;
105
99
  attachFinal: (observer: import("../../index.js").ObserverResult) => void;
106
100
  };
107
- env: NodeJS.ProcessEnv;
108
- subjectRoute: CuaSubjectRoute;
101
+ env: Record<string, string | undefined>;
102
+ appUrl: string;
109
103
  fail: (code: CuaActorLabErrorCode, message: string, actorLabel?: string) => CuaActorLabResult;
110
104
  refuse: (code: CuaActorLabErrorCode, message: string, actorLabel?: string | undefined) => {
111
105
  ok: false;
@@ -124,9 +118,6 @@ export declare function admitCuaRun(plan: ComputerUsePlan, input: ComputerUseRun
124
118
  knownSecretValues: string[];
125
119
  scrubKnownValues: (text: string) => string;
126
120
  publicRepo: string | undefined;
127
- hasGithubToken: boolean;
128
- localAgentRoute: boolean;
129
- preferredLocalAgent: LocalAgentId;
130
121
  localTreeArchive: LocalTreeArchive | undefined;
131
122
  localTreeArchiveBuffer: ArrayBuffer | undefined;
132
123
  };
@@ -1,12 +1,11 @@
1
- // The computer-use run's setup: resolve the project and route, plan the lanes, make the live
2
- // checks that need no sandbox, pack a local tree, then start the run and build the lane deps and
3
- // bundle base that the lanes and the finish share.
1
+ // The computer-use run's setup: resolve the project and route, plan the participants, make the
2
+ // live checks that need no sandbox, pack a local tree, then start the run and build the
3
+ // participant deps and bundle base that the participants and the finish share.
4
4
  import { randomBytes } from "node:crypto";
5
5
  import { realpath } from "node:fs/promises";
6
6
  import path from "node:path";
7
7
  import {} from "../../run/run.js";
8
8
  import { externalInboxUrl } from "../../comms/sandbox-catch.js";
9
- import {} from "../../actors/local-agent/cli.js";
10
9
  import { redactText, scrubLiterals, toErrorMessage } from "../../evidence/redaction.js";
11
10
  import { buildRunSource } from "../../run/bundle.js";
12
11
  import { assertPreparedSelectedOutputDirectory, prepareContainedOutputDirectory, prepareSelectedOutputDirectory, } from "../../run/contained-output.js";
@@ -16,14 +15,15 @@ import { emitPreflightPlan, compileParticipantPersonas, loadCuaParticipants, san
16
15
  import { makeCuaRunBudget } from "./participant-model.js";
17
16
  import { e2bRequestTimeoutMs } from "../../substrates/e2b/lifetime.js";
18
17
  import { liveCuaRejection } from "./preflight.js";
19
- import { cuaDescriptorOf, cuaSubjectRoute, cuaSubjectRouteOf, } from "./plan.js";
18
+ import { cuaDescriptorOf, declaredAppUrl, plannedAppUrl } from "./plan.js";
20
19
  import { trackRuntimeStreams } from "./live-flush.js";
20
+ import { participantOf, phaseEvent, planEvent } from "../../lab/run-lab-events.js";
21
+ import { defaultSubjectPhaseSink } from "../../subject/steps.js";
21
22
  import {} from "./bundle.js";
22
23
  import { packRunLocalTree } from "./local-tree-pack.js";
23
24
  import { projectParticipantSubjects, subjectProvenanceArg } from "./subject-projection.js";
24
- import { CUA_ACTOR_LAB_SCHEMA, } from "./types.js";
25
+ import { CUA_ACTOR_LAB_SCHEMA, participantSubjectEnv, } from "./types.js";
25
26
  import { labPersonaIds } from "../../lab/persona-resolve.js";
26
- import { participantDesktopOf } from "./participant-desktop.js";
27
27
  /** The physical project, bound before any caller hook runs. */
28
28
  async function bindProject(cwd) {
29
29
  // Capture the physical project before reading or invoking any caller hook. A supported
@@ -33,13 +33,12 @@ async function bindProject(cwd) {
33
33
  return prepareSelectedOutputDirectory(path.dirname(physicalCwd), physicalCwd);
34
34
  }
35
35
  /**
36
- * The envelope of a refusal the plan left for after the cwd checks. The lane cap and in-process
37
- * fan-out refusals come after the committed personas are read, so a persona-file error still wins.
36
+ * The envelope of a refusal the plan left for after the cwd checks. The participant cap and
37
+ * in-process fan-out refusals come after the committed personas are read, so a persona-file error still wins.
38
38
  */
39
39
  export async function refuseCuaLab(options, refusal) {
40
40
  const { config, dryRun } = options;
41
41
  const projectRoot = await bindProject(options.cwd);
42
- const hooks = options.hooks ?? {};
43
42
  // The committed personas are read before the refusal returns, so a persona-file error wins.
44
43
  if (refusal.stage === "after-personas")
45
44
  await compileParticipantPersonas(projectRoot, labPersonaIds(config));
@@ -49,7 +48,7 @@ export async function refuseCuaLab(options, refusal) {
49
48
  cwd: projectRoot.physicalPath,
50
49
  labId: config.id,
51
50
  actor: refusal.actor ?? config.actors[0]?.type ?? "",
52
- appUrl: cuaSubjectRoute(config, hooks).appUrl,
51
+ appUrl: declaredAppUrl(config),
53
52
  dryRun,
54
53
  runId: options.runId ?? "not-created",
55
54
  lanes: [],
@@ -67,11 +66,13 @@ export async function admitCuaRun(plan, input, config) {
67
66
  const { dryRun } = plan;
68
67
  const projectRoot = await bindProject(input.cwd);
69
68
  const cwd = projectRoot.physicalPath;
70
- const hooks = input.hooks ?? {};
71
- const streams = trackRuntimeStreams(hooks);
72
- const env = hooks.env ?? process.env;
73
- const subjectRoute = cuaSubjectRouteOf(plan);
74
- const { cloneRoute, localTreeRoute, inProcessRoute, appUrl, subjectRepo, subjectEnvNames } = subjectRoute;
69
+ const seams = input.deps ?? {};
70
+ const streams = trackRuntimeStreams(input.onStream);
71
+ const env = input.env ?? process.env;
72
+ const { subject, desktop } = plan.runner;
73
+ const inProcess = desktop === "in-process";
74
+ const appUrl = plannedAppUrl(subject);
75
+ const subjectEnvNames = [...participantSubjectEnv(subject)];
75
76
  const fail = (code, message, actorLabel) => ({
76
77
  schema: CUA_ACTOR_LAB_SCHEMA,
77
78
  ok: false,
@@ -89,15 +90,29 @@ export async function admitCuaRun(plan, input, config) {
89
90
  ok: false,
90
91
  result: fail(...args),
91
92
  });
93
+ // runLab's local VM study supplies a local-target app-url lab's desktop; a direct route call or
94
+ // an in-process executor on the same lab has none. It reads the declared source, as the planner
95
+ // did: a library config the parser never saw can plan to an app-url subject from another source.
96
+ if (config.subject.source === "app-url" &&
97
+ config.execution?.target === "local" &&
98
+ input.localVm === undefined)
99
+ return refuse("HUMANISH_CUA_LAB_LOCAL_DESKTOP_MISSING", "An app-url lab with execution.target: local needs a local desktop. runLab starts one; a direct route call or an in-process executor does not.");
92
100
  const descriptor = cuaDescriptorOf(plan.actor);
93
- const runSession = hooks.runSession ?? descriptor.runSession;
101
+ const baseRunSession = seams.runSession ?? descriptor.runSession;
102
+ // A local VM study's sessions abort on its signal.
103
+ const localVmSignal = input.localVm?.signal;
104
+ const runSession = localVmSignal === undefined
105
+ ? baseRunSession
106
+ : (options) => baseRunSession({ ...options, signal: localVmSignal });
94
107
  // Adopter-hosted comms plane on the app-url route (#380): humanish provisions no subject here,
95
108
  // so it cannot host a catch — the OPERATOR runs one, and humanish still does every other part
96
109
  // of the funnel: tells each persona its address and inbox URL, drains the catch over HTTP after
97
- // the lanes, and writes the same digest-only evidence. Declaring `external` previously did
110
+ // the participants, and writes the same digest-only evidence. Declaring `external` previously did
98
111
  // nothing on this route (and, per #387, on every other) while its docs said otherwise.
99
112
  const comms = plan.residual.comms;
100
- const externalCommsConfig = !cloneRoute && !localTreeRoute && !inProcessRoute ? comms?.email?.external : undefined;
113
+ const externalCommsConfig = subject.kind !== "clone" && subject.kind !== "local-tree" && !inProcess
114
+ ? comms?.email?.external
115
+ : undefined;
101
116
  const externalCommsEmail = externalCommsConfig ? comms?.email : undefined;
102
117
  const participants = await loadCuaParticipants({ plan, cwd, projectRoot, env });
103
118
  if (!participants.ok) {
@@ -105,13 +120,13 @@ export async function admitCuaRun(plan, input, config) {
105
120
  }
106
121
  const { participantRuns, participantPlan, rerunLineage } = participants;
107
122
  const participantCount = participantRuns.length;
108
- // Pre-flight plan: BEFORE any sandbox or provider call (dry-run AND live). The hook fires for
109
- // every N (observable + testable); the stderr table prints for fan-out (N>1) so single-lane
110
- // runs stay as quiet as they always were.
123
+ // Pre-flight plan: BEFORE any sandbox or provider call (dry-run AND live). onEvent gets it for
124
+ // every N; the stderr table prints for fan-out (N>1) so single-participant runs stay as quiet as they
125
+ // always were.
111
126
  if (participantCount > 1) {
112
127
  emitPreflightPlan(participantPlan, plan.labId);
113
128
  }
114
- hooks.onPreflight?.(participantPlan);
129
+ input.emit?.(planEvent(participantPlan));
115
130
  await assertPreparedSelectedOutputDirectory(projectRoot);
116
131
  // Read keys once into locals (names only; values never logged or persisted).
117
132
  const openaiApiKey = env.OPENAI_API_KEY?.trim() ?? "";
@@ -125,43 +140,30 @@ export async function admitCuaRun(plan, input, config) {
125
140
  const scrubKnownValues = scrubLiterals(knownSecretValues);
126
141
  sanitizeParticipantRuns(participantRuns, scrubKnownValues);
127
142
  const redactRepoLabel = plan.residual.policies?.redactRepos ?? subjectEnvNames.includes("GITHUB_TOKEN");
128
- const publicRepo = cloneRoute && subjectRepo ? (redactRepoLabel ? "repo-01" : subjectRepo) : undefined;
129
- const hasGithubToken = subjectEnvNames.includes("GITHUB_TOKEN");
130
- // The operator's own signed-in coding agent is the brain, so there is no provider key to ask
131
- // for — the entire point of the actor. E2B is still required: the persona needs a machine.
132
- const localAgentRoute = descriptor.id === "local-agent";
133
- // Which local CLI, from its OWN field: `model` means the model, so that "Claude Code running
134
- // Opus" is sayable. Preflight below refuses when the chosen one is missing or signed out — that
135
- // news is worthless after a sandbox is paid for.
136
- const preferredLocalAgent = config.actors[0]?.localAgent ?? "codex";
143
+ const publicRepo = subject.kind === "clone" ? (redactRepoLabel ? "repo-01" : subject.repo) : undefined;
137
144
  // Key-gating is route-aware: the in-process route uses the caller's OWN model + executor, and
138
145
  // the local-agent route uses a CLI the operator has already signed in to.
139
- if (!dryRun && !inProcessRoute) {
146
+ if (!dryRun && !inProcess) {
140
147
  const rejection = await liveCuaRejection({
141
148
  caps: plan.caps,
142
- model: config.actors[0]?.model,
143
- hooks,
149
+ brain: plan.runner.brain,
144
150
  env,
145
- openaiApiKey,
146
- e2bApiKey,
147
- localAgentRoute,
148
- preferredLocalAgent,
149
- subjectEnvNames,
151
+ requirements: plan.requirements,
150
152
  externalCommsConfig,
151
153
  });
152
154
  if (rejection)
153
155
  return refuse(rejection.code, rejection.message, descriptor.id);
154
156
  }
155
157
  // Pack the working tree ONCE per run, on the host, BEFORE any sandbox or provider call: every
156
- // fan-out lane below uploads this SAME archive, so one archiveSha256 describes every lane's
157
- // digest. Dry-run packs nothing (no fs side effects; the contract bundle carries no
158
+ // fan-out participant below uploads this SAME archive, so one archiveSha256 describes every
159
+ // participant's digest. Dry-run packs nothing (no fs side effects; the contract bundle carries no
158
160
  // archiveSha256). A packing failure fails the run closed here, before any sandbox is
159
161
  // created and before the run directory exists.
160
162
  let localTreeArchive;
161
163
  let localTreeArchiveBuffer;
162
- if (localTreeRoute && !dryRun) {
164
+ if (subject.kind === "local-tree" && !dryRun) {
163
165
  try {
164
- const packed = await packRunLocalTree(hooks, plan.residual, cwd);
166
+ const packed = await packRunLocalTree(seams, plan.residual, cwd);
165
167
  localTreeArchive = packed.archive;
166
168
  localTreeArchiveBuffer = packed.buffer;
167
169
  }
@@ -175,10 +177,10 @@ export async function admitCuaRun(plan, input, config) {
175
177
  config,
176
178
  dryRun,
177
179
  cwd,
178
- hooks,
180
+ seams,
179
181
  streams,
180
182
  env,
181
- subjectRoute,
183
+ appUrl,
182
184
  fail,
183
185
  refuse,
184
186
  descriptor,
@@ -194,9 +196,6 @@ export async function admitCuaRun(plan, input, config) {
194
196
  knownSecretValues,
195
197
  scrubKnownValues,
196
198
  publicRepo,
197
- hasGithubToken,
198
- localAgentRoute,
199
- preferredLocalAgent,
200
199
  localTreeArchive,
201
200
  localTreeArchiveBuffer,
202
201
  },
@@ -204,8 +203,8 @@ export async function admitCuaRun(plan, input, config) {
204
203
  }
205
204
  /** Starts the run and builds what the participants and the finish read: the deps and the bundle base. */
206
205
  export async function startCuaRun(plan, input, admitted, scope) {
207
- const { config, dryRun, cwd, hooks, descriptor, participantRuns, participantPlan, publicRepo } = admitted;
208
- const { appUrl, inProcessRoute, localAppSubject, cloneRoute, localTreeRoute, subjectEnvNames } = admitted.subjectRoute;
206
+ const { dryRun, cwd, seams, descriptor, participantRuns, participantPlan, publicRepo } = admitted;
207
+ const { appUrl } = admitted;
209
208
  // The run's status record exists from here on, so anything watching the runs directory can
210
209
  // tell which lab this is and that it is alive. The fail-closed returns below leave it finished
211
210
  // with no outcome when the scope closes; a crash leaves it stale, which reads as interrupted.
@@ -216,12 +215,12 @@ export async function startCuaRun(plan, input, admitted, scope) {
216
215
  mode: dryRun ? "dry-run" : "live",
217
216
  lab: plan.lab,
218
217
  renderReview: renderCuaReviewMarkdown,
219
- observer: { open: input.open === true, render: hooks.renderObserverFn },
218
+ observer: { open: input.open === true, render: seams.renderObserver },
220
219
  });
221
220
  if (!started.ok)
222
221
  return admitted.refuse(started.code, started.message, descriptor.id);
223
222
  const { run } = started;
224
- const { runId, createdAt, paths: runPaths } = run;
223
+ const { createdAt, paths: runPaths } = run;
225
224
  const redactScreenshots = plan.residual.policies?.redactScreenshots === true;
226
225
  await prepareContainedOutputDirectory(runPaths, "screenshots");
227
226
  const source = await buildRunSource({
@@ -231,7 +230,7 @@ export async function startCuaRun(plan, input, admitted, scope) {
231
230
  packageName: "humanish",
232
231
  });
233
232
  // Live-trace flush seam (#441): runLabParticipants fills it when a live run has an in-progress bundle
234
- // to grow; lanes call it through deps.onTrace. It exists before deps so deps can reference it as
233
+ // to grow; participants call it through deps.onTrace. It exists before deps so deps can reference it as
235
234
  // a stable indirection.
236
235
  const liveTrace = {};
237
236
  const deps = cuaParticipantDeps(plan, input, admitted, {
@@ -241,7 +240,6 @@ export async function startCuaRun(plan, input, admitted, scope) {
241
240
  });
242
241
  const subjectArgs = {
243
242
  plan,
244
- subjectRoute: admitted.subjectRoute,
245
243
  ...(publicRepo === undefined ? {} : { publicRepo }),
246
244
  ...(admitted.localTreeArchive === undefined
247
245
  ? {}
@@ -254,25 +252,20 @@ export async function startCuaRun(plan, input, admitted, scope) {
254
252
  dryRun: false,
255
253
  });
256
254
  const inProgressAggregateSubject = inProgressSubjects[0];
257
- const inProgressProvenance = subjectProvenanceArg(inProgressAggregateSubject, publicRepo, subjectEnvNames);
255
+ const inProgressProvenance = subjectProvenanceArg(inProgressAggregateSubject, publicRepo, [
256
+ ...participantSubjectEnv(plan.runner.subject),
257
+ ]);
258
258
  const bundleBase = {
259
- ...(plan.lab === undefined ? {} : { lab: plan.lab }),
259
+ run,
260
260
  participantRuns,
261
261
  descriptor,
262
262
  appUrl,
263
- createdAt,
264
263
  plan,
265
- runId,
266
264
  source,
267
265
  participantPlan,
268
266
  ...(admitted.rerunLineage === undefined ? {} : { rerun: admitted.rerunLineage }),
269
267
  redactScreenshots,
270
- inProcessRoute,
271
- localAppSubject,
272
- cloneRoute,
273
- localTreeRoute,
274
268
  ...(publicRepo === undefined ? {} : { publicRepo }),
275
- subjectEnvNames,
276
269
  };
277
270
  const { externalCommsConfig, externalCommsEmail } = admitted;
278
271
  return {
@@ -280,10 +273,8 @@ export async function startCuaRun(plan, input, admitted, scope) {
280
273
  setup: {
281
274
  plan,
282
275
  input,
283
- config,
284
276
  cwd,
285
277
  descriptor,
286
- subjectRoute: admitted.subjectRoute,
287
278
  run,
288
279
  streams: admitted.streams,
289
280
  participantRuns,
@@ -306,35 +297,30 @@ export async function startCuaRun(plan, input, admitted, scope) {
306
297
  },
307
298
  fail: admitted.fail,
308
299
  },
309
- finish: { hooks, rerunLineage: admitted.rerunLineage, publicRepo, subjectArgs },
300
+ finish: { rerunLineage: admitted.rerunLineage, publicRepo, subjectArgs },
310
301
  };
311
302
  }
312
- /** The lane deps every lane reads: the route, keys, timeouts, scrubber, budget and hooks. */
303
+ /** The participant deps every participant reads: the route, keys, timeouts, scrubber, budget and seams. */
313
304
  function cuaParticipantDeps(plan, input, admitted, run) {
314
- const { config, dryRun, hooks, streams, env, descriptor, runSession, participantCount } = admitted;
315
- const { localAgentRoute, preferredLocalAgent, hasGithubToken, localTreeArchiveBuffer } = admitted;
305
+ const { config, dryRun, seams, streams, env, runSession, participantCount } = admitted;
306
+ const { localTreeArchiveBuffer } = admitted;
316
307
  const { openaiApiKey, e2bApiKey, scrubKnownValues } = admitted;
317
308
  const { externalCommsConfig, externalCommsEmail } = admitted;
318
- const { appUrl, cloneRoute, desktopCliRoute, localTreeRoute, serve, subjectRepo } = admitted.subjectRoute;
319
- const { subjectEnvNames } = admitted.subjectRoute;
309
+ const { appUrl } = admitted;
320
310
  const { runPaths, redactScreenshots, liveTrace } = run;
321
- const createDesktop = participantDesktopOf(hooks);
311
+ const createDesktop = input.localVm?.desktop;
322
312
  const timeoutMs = plan.sessionBudgetMs;
323
313
  const requestTimeoutMs = e2bRequestTimeoutMs(env);
324
314
  return {
325
315
  ...(createDesktop === undefined ? {} : { createDesktop }),
326
316
  onTrace: (participantId, items, usage, metadata) => liveTrace.flush?.(participantId, items, usage, metadata),
327
- config,
328
- descriptor,
317
+ ...callerDriving(input, config),
318
+ residual: plan.residual,
319
+ labId: plan.labId,
320
+ caps: plan.caps,
329
321
  appUrl,
330
- ...(localAgentRoute ? { localAgent: preferredLocalAgent } : {}),
331
- cloneRoute,
332
- desktopCliRoute,
333
- localTreeRoute,
334
- ...(serve === undefined ? {} : { serve }),
335
- ...(subjectRepo === undefined ? {} : { subjectRepo }),
336
- subjectEnvNames,
337
- hasGithubToken,
322
+ brain: plan.runner.brain,
323
+ subject: plan.runner.subject,
338
324
  ...(localTreeArchiveBuffer === undefined ? {} : { localTreeArchiveBuffer }),
339
325
  env,
340
326
  openaiApiKey,
@@ -348,7 +334,7 @@ function cuaParticipantDeps(plan, input, admitted, run) {
348
334
  redactScreenshots,
349
335
  scrubKnownValues,
350
336
  runSession,
351
- // The study-level ledger exists once per RUN, shared by every lane (#299). Dry runs never
337
+ // The study-level ledger exists once per RUN, shared by every participant (#299). Dry runs never
352
338
  // spend, so they carry none.
353
339
  ...(dryRun || plan.caps.maxTotalUsd === undefined
354
340
  ? {}
@@ -361,8 +347,34 @@ function cuaParticipantDeps(plan, input, admitted, run) {
361
347
  inboxUrl: externalInboxUrl(externalCommsConfig),
362
348
  },
363
349
  }),
364
- now: hooks.now ?? Date.now,
365
- hooks: streams.hooks,
350
+ now: seams.now ?? Date.now,
351
+ ...(seams.desktopModule === undefined ? {} : { desktopModule: seams.desktopModule }),
352
+ ...(input.prepareDesktop === undefined ? {} : { prepareDesktop: input.prepareDesktop }),
353
+ ...(seams.detachedTimers === undefined ? {} : { detachedTimers: seams.detachedTimers }),
354
+ onStream: streams.onStream,
355
+ reportSubjectPhase: subjectPhaseReporter(input),
356
+ };
357
+ }
358
+ /** The caller's createProvider and inProcess executor, with the run's config bound. */
359
+ function callerDriving(input, config) {
360
+ const { createProvider, inProcess } = input;
361
+ return {
362
+ ...(createProvider === undefined
363
+ ? {}
364
+ : {
365
+ createProvider: (participant, executor) => createProvider({ config, participant, executor }),
366
+ }),
367
+ ...(inProcess === undefined
368
+ ? {}
369
+ : { inProcessExecutor: (appUrl) => inProcess.executor({ config, appUrl }) }),
370
+ };
371
+ }
372
+ /** Each subject phase goes to the phase sink, stderr by default, and to onEvent. */
373
+ function subjectPhaseReporter(input) {
374
+ const sink = input.deps?.subjectPhaseSink ?? defaultSubjectPhaseSink;
375
+ return (event, participant) => {
376
+ sink(event, participant);
377
+ input.emit?.(phaseEvent(event, { kind: "participant", participant: participantOf(participant) }));
366
378
  };
367
379
  }
368
380
  function makeCuaRunId() {