humanish 0.106.1 → 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 (453) hide show
  1. package/AGENTS.md +4 -4
  2. package/ARCHITECTURE.md +17 -16
  3. package/CHANGELOG.md +14 -0
  4. package/CONTEXT.md +42 -39
  5. package/CONTRIBUTING.md +8 -8
  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 +30 -3
  16. package/dist/actors/codex/qualified-versions.js +50 -5
  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 +9 -7
  45. package/dist/actors/local-agent/cli.js +1 -1
  46. package/dist/actors/scripted-browser/actor.d.ts +2 -2
  47. package/dist/actors/scripted-browser/journey.js +15 -4
  48. package/dist/actors/scripted-browser/steps.js +18 -0
  49. package/dist/actors/scripted-browser/types.d.ts +11 -1
  50. package/dist/actors/stop-conditions.js +1 -3
  51. package/dist/analysis/automatic-completion.d.ts +13 -8
  52. package/dist/analysis/automatic-completion.js +14 -8
  53. package/dist/analysis/automatic-config.d.ts +1 -1
  54. package/dist/analysis/automatic-config.js +2 -2
  55. package/dist/analysis/automatic.d.ts +10 -4
  56. package/dist/analysis/automatic.js +17 -13
  57. package/dist/analysis/diagnostics.d.ts +23 -0
  58. package/dist/analysis/diagnostics.js +112 -0
  59. package/dist/analysis/evidence-sources.js +2 -2
  60. package/dist/analysis/evidence.js +6 -6
  61. package/dist/analysis/execute.d.ts +7 -1
  62. package/dist/analysis/execute.js +39 -12
  63. package/dist/analysis/job.d.ts +8 -5
  64. package/dist/analysis/job.js +15 -14
  65. package/dist/analysis/load.d.ts +1 -1
  66. package/dist/analysis/load.js +5 -5
  67. package/dist/analysis/provider.d.ts +9 -1
  68. package/dist/analysis/restricted-codex.d.ts +2 -0
  69. package/dist/analysis/restricted-codex.js +10 -1
  70. package/dist/analysis/service.d.ts +2 -0
  71. package/dist/analysis/service.js +31 -12
  72. package/dist/analysis/sharing.d.ts +2 -2
  73. package/dist/analysis/sharing.js +5 -5
  74. package/dist/analysis/store-executions.d.ts +5 -5
  75. package/dist/analysis/store-executions.js +12 -12
  76. package/dist/analysis/store.d.ts +4 -4
  77. package/dist/analysis/store.js +13 -13
  78. package/dist/cli/commands/analysis-signals.d.ts +2 -1
  79. package/dist/cli/commands/analysis-signals.js +4 -1
  80. package/dist/cli/commands/analyze.js +4 -2
  81. package/dist/cli/commands/comms.js +8 -1
  82. package/dist/cli/commands/lab-route-computer-use.d.ts +0 -2
  83. package/dist/cli/commands/lab-route-computer-use.js +26 -14
  84. package/dist/cli/commands/lab-route-preview.d.ts +1 -3
  85. package/dist/cli/commands/lab-route-preview.js +3 -4
  86. package/dist/cli/commands/lab-route-run.d.ts +6 -4
  87. package/dist/cli/commands/lab-route-run.js +6 -2
  88. package/dist/cli/commands/lab-route-scripted.d.ts +0 -2
  89. package/dist/cli/commands/lab-route-scripted.js +0 -1
  90. package/dist/cli/commands/lab-route-shared-world.d.ts +0 -2
  91. package/dist/cli/commands/lab-route-shared-world.js +0 -1
  92. package/dist/cli/commands/lab-route-terminal.d.ts +0 -2
  93. package/dist/cli/commands/lab-route-terminal.js +0 -1
  94. package/dist/cli/commands/lab-run.js +76 -45
  95. package/dist/cli/commands/lab-scorer.d.ts +0 -2
  96. package/dist/cli/commands/lab.js +12 -6
  97. package/dist/cli/commands/observe.js +22 -0
  98. package/dist/cli/commands/run-signals.d.ts +30 -0
  99. package/dist/cli/commands/run-signals.js +146 -0
  100. package/dist/cli/commands/runs.js +10 -8
  101. package/dist/cli/commands/watch.js +12 -10
  102. package/dist/cli/doctor.d.ts +3 -0
  103. package/dist/cli/doctor.js +10 -2
  104. package/dist/cli/io.d.ts +5 -4
  105. package/dist/cli/io.js +12 -8
  106. package/dist/cli/program.js +3 -3
  107. package/dist/cli/renamed-options.d.ts +11 -0
  108. package/dist/cli/renamed-options.js +18 -0
  109. package/dist/cli/telemetry.d.ts +2 -2
  110. package/dist/cli/telemetry.js +1 -1
  111. package/dist/comms/capture-surface.d.ts +1 -1
  112. package/dist/comms/catch-host.d.ts +1 -1
  113. package/dist/comms/connections.js +4 -4
  114. package/dist/comms/external-evidence.d.ts +27 -0
  115. package/dist/comms/external-evidence.js +93 -0
  116. package/dist/comms/lease-store.js +7 -7
  117. package/dist/comms/types.js +1 -1
  118. package/dist/evidence/browser-hygiene.d.ts +1 -1
  119. package/dist/evidence/browser-hygiene.js +1 -1
  120. package/dist/evidence/redaction.js +1 -1
  121. package/dist/evidence/secret-scrub.d.ts +9 -0
  122. package/dist/evidence/secret-scrub.js +96 -0
  123. package/dist/feedback/draft.js +7 -9
  124. package/dist/feedback/export-bundle.js +4 -4
  125. package/dist/feedback/export.js +9 -9
  126. package/dist/feedback/feedback.d.ts +1 -1
  127. package/dist/index.d.ts +3 -6
  128. package/dist/index.js +3 -6
  129. package/dist/keys/key-resolution.d.ts +3 -1
  130. package/dist/keys/key-resolution.js +18 -16
  131. package/dist/lab/adapter-extension.d.ts +28 -6
  132. package/dist/lab/adapter-extension.js +65 -126
  133. package/dist/lab/adapter-scorer-loader.d.ts +25 -5
  134. package/dist/lab/adapter-scorer-loader.js +24 -0
  135. package/dist/lab/composition-rules.js +20 -20
  136. package/dist/lab/config.js +28 -26
  137. package/dist/lab/device-presets.d.ts +2 -2
  138. package/dist/lab/discover.js +1 -3
  139. package/dist/lab/doctor.d.ts +44 -9
  140. package/dist/lab/doctor.js +149 -41
  141. package/dist/lab/init-plan.js +1 -3
  142. package/dist/lab/keys.js +1 -1
  143. package/dist/lab/lab-deps.d.ts +85 -0
  144. package/dist/lab/lab-deps.js +4 -0
  145. package/dist/lab/parse/actors.js +8 -7
  146. package/dist/lab/parse/comms.js +3 -2
  147. package/dist/lab/parse/execution.js +3 -2
  148. package/dist/lab/parse/subject-state.js +2 -1
  149. package/dist/lab/parse/subject.js +2 -1
  150. package/dist/lab/parse/values.d.ts +0 -1
  151. package/dist/lab/parse/values.js +0 -3
  152. package/dist/lab/persona-resolve.d.ts +3 -3
  153. package/dist/lab/persona-resolve.js +4 -4
  154. package/dist/lab/persona.js +1 -3
  155. package/dist/lab/plan-base.d.ts +0 -2
  156. package/dist/lab/plan-base.js +6 -4
  157. package/dist/lab/plan-participants.d.ts +5 -5
  158. package/dist/lab/plan-participants.js +2 -2
  159. package/dist/lab/plan-types.d.ts +22 -4
  160. package/dist/lab/plan.d.ts +3 -11
  161. package/dist/lab/plan.js +18 -42
  162. package/dist/lab/preflight-result.js +0 -2
  163. package/dist/lab/preflight.d.ts +0 -3
  164. package/dist/lab/preflight.js +1 -1
  165. package/dist/lab/requirements.d.ts +20 -0
  166. package/dist/lab/requirements.js +54 -0
  167. package/dist/lab/route-inputs.d.ts +23 -12
  168. package/dist/lab/route-inputs.js +48 -51
  169. package/dist/lab/routing.d.ts +19 -24
  170. package/dist/lab/routing.js +14 -47
  171. package/dist/lab/run-lab-events.d.ts +6 -11
  172. package/dist/lab/run-lab-events.js +3 -11
  173. package/dist/lab/run-lab-homes.d.ts +64 -0
  174. package/dist/lab/run-lab-homes.js +3 -0
  175. package/dist/lab/run-lab-options.d.ts +12 -66
  176. package/dist/lab/run-lab-options.js +45 -275
  177. package/dist/lab/summary.d.ts +9 -4
  178. package/dist/lab/summary.js +15 -8
  179. package/dist/lab/types.d.ts +132 -132
  180. package/dist/lab/validation.d.ts +15 -15
  181. package/dist/lab/validation.js +28 -28
  182. package/dist/lab/warnings.js +20 -19
  183. package/dist/observer/artifact.d.ts +1 -1
  184. package/dist/observer/artifact.js +3 -3
  185. package/dist/observer/data.js +2 -2
  186. package/dist/observer/render.js +2 -2
  187. package/dist/observer/run-routes.d.ts +1 -1
  188. package/dist/observer/run-routes.js +5 -5
  189. package/dist/observer/serve.d.ts +17 -0
  190. package/dist/observer/serve.js +34 -3
  191. package/dist/routes/computer-use/bundle-parts.d.ts +1 -1
  192. package/dist/routes/computer-use/bundle-parts.js +10 -3
  193. package/dist/routes/computer-use/bundle.d.ts +4 -11
  194. package/dist/routes/computer-use/bundle.js +9 -15
  195. package/dist/routes/computer-use/diagnostics.d.ts +1 -1
  196. package/dist/routes/computer-use/diagnostics.js +1 -1
  197. package/dist/routes/computer-use/e2b-desktop/comms.d.ts +10 -10
  198. package/dist/routes/computer-use/e2b-desktop/comms.js +11 -14
  199. package/dist/routes/computer-use/e2b-desktop/desktop.d.ts +2 -2
  200. package/dist/routes/computer-use/e2b-desktop/desktop.js +4 -7
  201. package/dist/routes/computer-use/e2b-desktop/fidelity.d.ts +13 -13
  202. package/dist/routes/computer-use/e2b-desktop/fidelity.js +11 -11
  203. package/dist/routes/computer-use/e2b-desktop/prepare.d.ts +3 -3
  204. package/dist/routes/computer-use/e2b-desktop/prepare.js +33 -36
  205. package/dist/routes/computer-use/e2b-desktop/start.d.ts +1 -1
  206. package/dist/routes/computer-use/e2b-desktop/start.js +24 -23
  207. package/dist/routes/computer-use/e2b-desktop/state.d.ts +5 -4
  208. package/dist/routes/computer-use/e2b-desktop/state.js +5 -3
  209. package/dist/routes/computer-use/e2b-desktop/teardown.d.ts +1 -1
  210. package/dist/routes/computer-use/e2b-desktop/teardown.js +29 -17
  211. package/dist/routes/computer-use/external-comms.d.ts +4 -4
  212. package/dist/routes/computer-use/external-comms.js +19 -43
  213. package/dist/routes/computer-use/fanout-bundle.d.ts +3 -3
  214. package/dist/routes/computer-use/fanout-bundle.js +25 -29
  215. package/dist/routes/computer-use/{fanout-lanes.js → fanout-records.js} +25 -19
  216. package/dist/routes/computer-use/in-process-desktop.d.ts +3 -10
  217. package/dist/routes/computer-use/in-process-desktop.js +3 -9
  218. package/dist/routes/computer-use/live-flush.d.ts +7 -5
  219. package/dist/routes/computer-use/live-flush.js +19 -27
  220. package/dist/routes/computer-use/{run-lanes.js → live-phase.js} +12 -11
  221. package/dist/routes/computer-use/local-tree-pack.d.ts +3 -3
  222. package/dist/routes/computer-use/local-tree-pack.js +4 -5
  223. package/dist/routes/computer-use/local-vm.d.ts +11 -8
  224. package/dist/routes/computer-use/local-vm.js +39 -66
  225. package/dist/routes/computer-use/participant-desktop.d.ts +8 -23
  226. package/dist/routes/computer-use/participant-desktop.js +5 -25
  227. package/dist/routes/computer-use/{lanes.d.ts → participant-execution.d.ts} +10 -10
  228. package/dist/routes/computer-use/{lanes.js → participant-execution.js} +35 -22
  229. package/dist/routes/computer-use/participant-facts.d.ts +7 -1
  230. package/dist/routes/computer-use/participant-facts.js +12 -1
  231. package/dist/routes/computer-use/participant-model.d.ts +19 -11
  232. package/dist/routes/computer-use/participant-model.js +49 -25
  233. package/dist/routes/computer-use/participant-prompt.d.ts +3 -3
  234. package/dist/routes/computer-use/participant-prompt.js +4 -4
  235. package/dist/routes/computer-use/participant-runs.d.ts +6 -6
  236. package/dist/routes/computer-use/participant-runs.js +8 -8
  237. package/dist/routes/computer-use/plan.d.ts +21 -29
  238. package/dist/routes/computer-use/plan.js +52 -60
  239. package/dist/routes/computer-use/preflight.d.ts +3 -5
  240. package/dist/routes/computer-use/preflight.js +20 -16
  241. package/dist/routes/computer-use/rerun-selection.js +10 -6
  242. package/dist/routes/computer-use/result.d.ts +1 -1
  243. package/dist/routes/computer-use/result.js +40 -30
  244. package/dist/routes/computer-use/route.d.ts +3 -4
  245. package/dist/routes/computer-use/route.js +21 -19
  246. package/dist/routes/computer-use/self-report.d.ts +2 -2
  247. package/dist/routes/computer-use/self-report.js +4 -4
  248. package/dist/routes/computer-use/setup.d.ts +8 -14
  249. package/dist/routes/computer-use/setup.js +96 -72
  250. package/dist/routes/computer-use/single-bundle.d.ts +8 -11
  251. package/dist/routes/computer-use/single-bundle.js +20 -25
  252. package/dist/routes/computer-use/subject-projection.d.ts +5 -7
  253. package/dist/routes/computer-use/subject-projection.js +20 -19
  254. package/dist/routes/computer-use/types.d.ts +169 -210
  255. package/dist/routes/computer-use/types.js +13 -5
  256. package/dist/routes/preview.js +0 -1
  257. package/dist/routes/scripted/bundle.d.ts +3 -6
  258. package/dist/routes/scripted/bundle.js +11 -16
  259. package/dist/routes/scripted/plan.d.ts +5 -7
  260. package/dist/routes/scripted/plan.js +6 -4
  261. package/dist/routes/scripted/result.d.ts +4 -1
  262. package/dist/routes/scripted/result.js +10 -6
  263. package/dist/routes/scripted/route.js +10 -11
  264. package/dist/routes/scripted/scenario.d.ts +1 -1
  265. package/dist/routes/scripted/scenario.js +1 -1
  266. package/dist/routes/scripted/setup.d.ts +3 -2
  267. package/dist/routes/scripted/setup.js +22 -21
  268. package/dist/routes/scripted/subject.d.ts +8 -3
  269. package/dist/routes/scripted/subject.js +9 -5
  270. package/dist/routes/scripted/surface-records.js +1 -1
  271. package/dist/routes/scripted/surface-sessions.d.ts +2 -2
  272. package/dist/routes/scripted/surface-sessions.js +4 -4
  273. package/dist/routes/scripted/types.d.ts +19 -36
  274. package/dist/routes/scripted/types.js +1 -2
  275. package/dist/routes/shared-world/{seat-records.js → bundle-records.js} +8 -8
  276. package/dist/routes/shared-world/bundle.d.ts +2 -2
  277. package/dist/routes/shared-world/bundle.js +22 -26
  278. package/dist/routes/shared-world/checkpoints.d.ts +4 -4
  279. package/dist/routes/shared-world/checkpoints.js +4 -4
  280. package/dist/routes/shared-world/comms.d.ts +5 -4
  281. package/dist/routes/shared-world/comms.js +28 -41
  282. package/dist/routes/shared-world/external-public.d.ts +5 -5
  283. package/dist/routes/shared-world/external-public.js +19 -20
  284. package/dist/routes/shared-world/handoff.d.ts +4 -4
  285. package/dist/routes/shared-world/handoff.js +50 -50
  286. package/dist/routes/shared-world/lobby-code.d.ts +5 -5
  287. package/dist/routes/shared-world/lobby-code.js +13 -13
  288. package/dist/routes/shared-world/{seats.d.ts → participant-specs.d.ts} +8 -6
  289. package/dist/routes/shared-world/{seats.js → participant-specs.js} +43 -48
  290. package/dist/routes/shared-world/plan.d.ts +2 -6
  291. package/dist/routes/shared-world/plan.js +1 -2
  292. package/dist/routes/shared-world/provenance.d.ts +4 -4
  293. package/dist/routes/shared-world/provenance.js +4 -4
  294. package/dist/routes/shared-world/provisioned.d.ts +3 -2
  295. package/dist/routes/shared-world/provisioned.js +46 -40
  296. package/dist/routes/shared-world/result.js +31 -19
  297. package/dist/routes/shared-world/route.js +37 -41
  298. package/dist/routes/shared-world/setup.d.ts +5 -4
  299. package/dist/routes/shared-world/setup.js +12 -14
  300. package/dist/routes/shared-world/types.d.ts +53 -126
  301. package/dist/routes/shared-world/types.js +2 -2
  302. package/dist/routes/terminal/adapter.d.ts +8 -8
  303. package/dist/routes/terminal/adapter.js +28 -125
  304. package/dist/routes/terminal/bundle.d.ts +7 -12
  305. package/dist/routes/terminal/bundle.js +24 -34
  306. package/dist/routes/terminal/credentials.d.ts +2 -2
  307. package/dist/routes/terminal/credentials.js +16 -16
  308. package/dist/routes/terminal/dry-run.d.ts +1 -1
  309. package/dist/routes/terminal/dry-run.js +9 -11
  310. package/dist/routes/terminal/encoding.d.ts +1 -1
  311. package/dist/routes/terminal/encoding.js +2 -2
  312. package/dist/routes/terminal/ledger.d.ts +6 -6
  313. package/dist/routes/terminal/ledger.js +9 -9
  314. package/dist/routes/terminal/live-finish.d.ts +1 -2
  315. package/dist/routes/terminal/live-finish.js +21 -20
  316. package/dist/routes/terminal/live-sandbox.d.ts +3 -2
  317. package/dist/routes/terminal/live-sandbox.js +20 -20
  318. package/dist/routes/terminal/participant-text.d.ts +23 -0
  319. package/dist/routes/terminal/participant-text.js +165 -0
  320. package/dist/routes/terminal/plan.d.ts +2 -6
  321. package/dist/routes/terminal/plan.js +13 -9
  322. package/dist/routes/terminal/recorder.d.ts +6 -1
  323. package/dist/routes/terminal/recorder.js +12 -4
  324. package/dist/routes/terminal/result.js +4 -4
  325. package/dist/routes/terminal/route.js +26 -26
  326. package/dist/routes/terminal/runtime.d.ts +3 -2
  327. package/dist/routes/terminal/runtime.js +3 -3
  328. package/dist/routes/terminal/sandbox.d.ts +3 -3
  329. package/dist/routes/terminal/sandbox.js +9 -9
  330. package/dist/routes/terminal/session.js +16 -14
  331. package/dist/routes/terminal/token-usage.js +5 -5
  332. package/dist/routes/terminal/trace.d.ts +5 -8
  333. package/dist/routes/terminal/trace.js +9 -64
  334. package/dist/routes/terminal/types.d.ts +85 -93
  335. package/dist/routes/terminal/types.js +9 -4
  336. package/dist/run/active-runs.d.ts +13 -0
  337. package/dist/run/active-runs.js +12 -0
  338. package/dist/run/bundle-shape.d.ts +2 -1
  339. package/dist/run/bundle-shape.js +4 -4
  340. package/dist/run/bundle.d.ts +63 -56
  341. package/dist/run/bundle.js +9 -8
  342. package/dist/run/cost-summary.js +3 -2
  343. package/dist/run/costs.d.ts +6 -6
  344. package/dist/run/costs.js +10 -10
  345. package/dist/run/detail.d.ts +5 -5
  346. package/dist/run/detail.js +6 -6
  347. package/dist/run/dry-run.js +5 -12
  348. package/dist/run/{study-files.d.ts → evidence-files.d.ts} +4 -4
  349. package/dist/run/{study-files.js → evidence-files.js} +5 -5
  350. package/dist/run/feedback-shape.js +1 -1
  351. package/dist/run/judge.d.ts +16 -4
  352. package/dist/run/judge.js +24 -7
  353. package/dist/run/locate.d.ts +2 -0
  354. package/dist/run/locate.js +3 -1
  355. package/dist/run/outcomes.d.ts +3 -3
  356. package/dist/run/outcomes.js +3 -3
  357. package/dist/run/participant-records.d.ts +2 -2
  358. package/dist/run/participant-records.js +2 -2
  359. package/dist/run/paths.js +1 -1
  360. package/dist/run/pricing.d.ts +19 -9
  361. package/dist/run/pricing.js +30 -18
  362. package/dist/run/projection.d.ts +13 -13
  363. package/dist/run/projection.js +8 -8
  364. package/dist/run/reclaim.d.ts +6 -0
  365. package/dist/run/reclaim.js +13 -3
  366. package/dist/run/results.d.ts +1 -1
  367. package/dist/run/run-index.d.ts +1 -1
  368. package/dist/run/run-index.js +11 -11
  369. package/dist/run/run.d.ts +4 -2
  370. package/dist/run/run.js +9 -5
  371. package/dist/run/sandbox-receipts.d.ts +4 -4
  372. package/dist/run/sandbox-receipts.js +4 -4
  373. package/dist/run/shared-world-evidence.d.ts +47 -47
  374. package/dist/run/shared-world-shape.d.ts +3 -3
  375. package/dist/run/shared-world-shape.js +11 -11
  376. package/dist/run/stats.d.ts +5 -5
  377. package/dist/run/stats.js +8 -8
  378. package/dist/run/status.d.ts +16 -6
  379. package/dist/run/status.js +31 -8
  380. package/dist/run/streams.d.ts +26 -19
  381. package/dist/run/terminal-contract.d.ts +5 -5
  382. package/dist/run/terminal-contract.js +4 -4
  383. package/dist/run/transient-comms-secrets.d.ts +5 -0
  384. package/dist/run/transient-comms-secrets.js +12 -0
  385. package/dist/run-lab.d.ts +36 -34
  386. package/dist/run-lab.js +41 -37
  387. package/dist/subject/desktop-cli.d.ts +1 -1
  388. package/dist/subject/desktop-cli.js +1 -1
  389. package/dist/subject/local-tree-archive.d.ts +1 -1
  390. package/dist/subject/local-tree-archive.js +4 -4
  391. package/dist/subject/local-tree.d.ts +2 -2
  392. package/dist/subject/local-tree.js +1 -1
  393. package/dist/subject/node-bootstrap.d.ts +1 -1
  394. package/dist/subject/node-bootstrap.js +4 -4
  395. package/dist/subject/runtime.js +5 -5
  396. package/dist/subject/serve.js +1 -1
  397. package/dist/subject/steps.d.ts +4 -4
  398. package/dist/subject/steps.js +5 -5
  399. package/dist/substrates/e2b/cdp-probe.d.ts +2 -2
  400. package/dist/substrates/e2b/cdp-probe.js +1 -1
  401. package/dist/substrates/e2b/desktop-browser.d.ts +3 -3
  402. package/dist/substrates/e2b/desktop-browser.js +4 -4
  403. package/dist/substrates/e2b/desktop-cdp.d.ts +7 -7
  404. package/dist/substrates/e2b/desktop-cdp.js +4 -4
  405. package/dist/substrates/e2b/desktop-geometry.d.ts +4 -4
  406. package/dist/substrates/e2b/desktop-geometry.js +3 -3
  407. package/dist/substrates/e2b/desktop-media.js +2 -2
  408. package/dist/substrates/e2b/sandbox.js +1 -1
  409. package/dist/substrates/e2b/sdk.js +2 -2
  410. package/dist/substrates/local/runtime-host.d.ts +2 -0
  411. package/dist/substrates/local/runtime-host.js +6 -0
  412. package/dist/tui/actions.d.ts +7 -5
  413. package/dist/tui/actions.js +18 -9
  414. package/dist/tui-app.js +42 -42
  415. package/dist/verify/actor.d.ts +10 -10
  416. package/dist/verify/actor.js +15 -15
  417. package/dist/verify/artifacts.d.ts +1 -1
  418. package/dist/verify/artifacts.js +3 -3
  419. package/dist/verify/costs.d.ts +2 -2
  420. package/dist/verify/costs.js +2 -2
  421. package/dist/verify/liveness.d.ts +1 -1
  422. package/dist/verify/liveness.js +4 -1
  423. package/dist/verify/rerun.d.ts +1 -1
  424. package/dist/verify/rerun.js +1 -1
  425. package/dist/verify/shared-world.js +2 -2
  426. package/dist/verify/verify.js +6 -6
  427. package/docs/README.md +1 -1
  428. package/docs/architecture/actor-contract.md +60 -22
  429. package/docs/architecture/desktop-sessions.md +9 -9
  430. package/docs/architecture/external-public-shared-world.md +5 -0
  431. package/docs/architecture/observer.md +4 -4
  432. package/docs/architecture/restricted-codex-analysis.md +36 -2
  433. package/docs/architecture/state-driven-executor.md +4 -5
  434. package/docs/architecture/task-protocol-support.md +3 -5
  435. package/docs/architecture/{terminal-product-lane.md → terminal-product-route.md} +24 -16
  436. package/docs/contracts/run-bundle.md +10 -8
  437. package/docs/contracts/schemas.md +109 -53
  438. package/docs/contracts/study-analysis.md +24 -0
  439. package/docs/decisions/0004-participant-desktops-stay-in-the-route.md +2 -1
  440. package/docs/product/automatic-analysis.md +1 -0
  441. package/docs/ramp/README.md +2 -1
  442. package/package.json +4 -4
  443. package/skills/humanish/SKILL.md +3 -2
  444. package/skills/humanish/agents/openai.yaml +1 -1
  445. package/dist/deprecated.d.ts +0 -90
  446. package/dist/deprecated.js +0 -106
  447. package/dist/lab/bag-overrides.d.ts +0 -18
  448. package/dist/lab/bag-overrides.js +0 -121
  449. package/dist/routes/computer-use/legacy-lane-spec.d.ts +0 -62
  450. package/dist/routes/computer-use/legacy-lane-spec.js +0 -39
  451. /package/dist/routes/computer-use/{fanout-lanes.d.ts → fanout-records.d.ts} +0 -0
  452. /package/dist/routes/computer-use/{run-lanes.d.ts → live-phase.d.ts} +0 -0
  453. /package/dist/routes/shared-world/{seat-records.d.ts → bundle-records.d.ts} +0 -0
@@ -5,8 +5,8 @@ import { type RunRerunLineage } from "../../run/bundle.js";
5
5
  import type { PreparedSelectedOutputDirectory } from "../../run/contained-output.js";
6
6
  import { type CuaActorLabErrorCode, type CuaParticipantPlan, type CuaParticipantPlanEntry, type DesktopParticipantRun } from "./types.js";
7
7
  export declare function defaultSessionTimeoutMs(config: LabConfig): number;
8
- /** Per-lane sandbox deadline (each lane owns its own desktop). Mirrors the single-lane formula
9
- * verbatim so N=1 stays byte-stable: explicit sandboxTimeoutMs, else session budget + (clone
8
+ /** Per-participant sandbox deadline (each one owns its own desktop). Mirrors the
9
+ * single-participant formula verbatim so N=1 stays byte-stable: explicit sandboxTimeoutMs, else session budget + (clone
10
10
  * or local-tree: provision budget + Σ state-step budgets) + the server-side
11
11
  * reclamation buffer. Local-tree shares the clone route's provisioning budget: it swaps a
12
12
  * git clone for an upload+extract, but the shared install/build/state/start/probe pipeline
@@ -21,8 +21,8 @@ export declare function resolveParticipantSandboxMs(config: LabConfig): number;
21
21
  */
22
22
  export declare function boundedConcurrency(declared: number | undefined, participantCount: number): number;
23
23
  /**
24
- * Pure pre-flight plan resolver (runs in dry-run AND live). Returns the lane table, the
25
- * effective concurrency, the wave count, the per-lane session budget, and the worst-case total
24
+ * Pure pre-flight plan resolver (runs in dry-run AND live). Returns the participant table, the
25
+ * effective concurrency, the wave count, the per-participant session budget, and the worst-case total
26
26
  * sandbox-minutes — BEFORE any sandbox or provider call. The same plan appears in dry-run,
27
27
  * marked $0 (dryRun: true).
28
28
  */
@@ -32,7 +32,7 @@ export declare function resolveCuaParticipantPlan(config: LabConfig, opts?: {
32
32
  dryRun?: boolean;
33
33
  personas?: Map<string, ResolvedPersona>;
34
34
  }): CuaParticipantPlan;
35
- /** Print the lane plan to stderr BEFORE any sandbox/provider call (public-safe: ids, devices,
35
+ /** Print the participant plan to stderr BEFORE any sandbox/provider call (public-safe: ids, devices,
36
36
  * digests, and budgets only — no prompt text, no secrets). */
37
37
  export declare function emitPreflightPlan(participantPlan: CuaParticipantPlan, labId: string): void;
38
38
  export declare function formatParticipantPlanEntry(entry: CuaParticipantPlanEntry): string;
@@ -63,5 +63,5 @@ export declare function loadCuaParticipants(args: {
63
63
  code: CuaActorLabErrorCode;
64
64
  message: string;
65
65
  }>;
66
- /** Scrub known secret values from each lane's declarative snapshot before any bundle uses it. */
66
+ /** Scrub known secret values from each participant's declarative snapshot before any bundle uses it. */
67
67
  export declare function sanitizeParticipantRuns(runs: readonly DesktopParticipantRun[], scrub: (text: string) => string): void;
@@ -26,8 +26,8 @@ export function defaultSessionTimeoutMs(config) {
26
26
  const room = MAX_SANDBOX_MS - SUBJECT_PROVISION_BUDGET_MS - stateBudgetMs - SANDBOX_TIMEOUT_BUFFER_MS;
27
27
  return Math.max(MIN_DERIVED_SESSION_TIMEOUT_MS, Math.min(DEFAULT_APP_URL_SESSION_TIMEOUT_MS, room));
28
28
  }
29
- /** Per-lane sandbox deadline (each lane owns its own desktop). Mirrors the single-lane formula
30
- * verbatim so N=1 stays byte-stable: explicit sandboxTimeoutMs, else session budget + (clone
29
+ /** Per-participant sandbox deadline (each one owns its own desktop). Mirrors the
30
+ * single-participant formula verbatim so N=1 stays byte-stable: explicit sandboxTimeoutMs, else session budget + (clone
31
31
  * or local-tree: provision budget + Σ state-step budgets) + the server-side
32
32
  * reclamation buffer. Local-tree shares the clone route's provisioning budget: it swaps a
33
33
  * git clone for an upload+extract, but the shared install/build/state/start/probe pipeline
@@ -162,8 +162,8 @@ function participantRunsAndPlan(planned, opts = {}) {
162
162
  return { runs, participantPlan };
163
163
  }
164
164
  /**
165
- * Pure pre-flight plan resolver (runs in dry-run AND live). Returns the lane table, the
166
- * effective concurrency, the wave count, the per-lane session budget, and the worst-case total
165
+ * Pure pre-flight plan resolver (runs in dry-run AND live). Returns the participant table, the
166
+ * effective concurrency, the wave count, the per-participant session budget, and the worst-case total
167
167
  * sandbox-minutes — BEFORE any sandbox or provider call. The same plan appears in dry-run,
168
168
  * marked $0 (dryRun: true).
169
169
  */
@@ -171,11 +171,11 @@ export function resolveCuaParticipantPlan(config, opts = {}) {
171
171
  const { countOverride, ...rest } = opts;
172
172
  return participantRunsAndPlan(plannedParticipantsOf(config, countOverride), rest).participantPlan;
173
173
  }
174
- /** Print the lane plan to stderr BEFORE any sandbox/provider call (public-safe: ids, devices,
174
+ /** Print the participant plan to stderr BEFORE any sandbox/provider call (public-safe: ids, devices,
175
175
  * digests, and budgets only — no prompt text, no secrets). */
176
176
  export function emitPreflightPlan(participantPlan, labId) {
177
177
  const lines = [];
178
- lines.push(`humanish cua fan-out plan (${labId}): ${participantPlan.laneCount} participant(s), strategy ${participantPlan.strategy}, concurrency ${participantPlan.concurrency}${participantPlan.envLoweredConcurrencyFrom === undefined ? "" : ` (lowered from ${participantPlan.envLoweredConcurrencyFrom} by ${CUA_MAX_CONCURRENCY_ENV})`}, ${participantPlan.waves} wave(s).`);
178
+ lines.push(`humanish computer-use fan-out plan (${labId}): ${participantPlan.laneCount} participant(s), strategy ${participantPlan.strategy}, concurrency ${participantPlan.concurrency}${participantPlan.envLoweredConcurrencyFrom === undefined ? "" : ` (lowered from ${participantPlan.envLoweredConcurrencyFrom} by ${CUA_MAX_CONCURRENCY_ENV})`}, ${participantPlan.waves} wave(s).`);
179
179
  lines.push(` session budget ${Math.round(participantPlan.perLaneSessionBudgetMs / 1000)}s per participant; worst-case ~${participantPlan.worstCaseSandboxMinutes} sandbox-minutes total${participantPlan.dryRun ? " (dry-run: $0)" : ""}.`);
180
180
  for (const entry of participantPlan.lanes) {
181
181
  lines.push(` - ${formatParticipantPlanEntry(entry)}`);
@@ -212,7 +212,7 @@ export async function compileParticipantPersonas(projectRoot, personaIds) {
212
212
  export async function loadCuaParticipants(args) {
213
213
  const { plan } = args;
214
214
  const { participants } = plan.runner;
215
- // Compile any committed personas BEFORE planning, so the plan builder stays pure and each lane's
215
+ // Compile any committed personas BEFORE planning, so the plan builder stays pure and each participant's
216
216
  // prompt carries real behavioral directives rather than a bare `Persona: <id>.` label (#381).
217
217
  const personas = await compileParticipantPersonas(args.projectRoot, participants.map((participant) => participant.personaId));
218
218
  const { runs: participantRuns, participantPlan } = participantRunsAndPlan({
@@ -244,7 +244,7 @@ export async function loadCuaParticipants(args) {
244
244
  rerunLineage: selected.rerun,
245
245
  };
246
246
  }
247
- /** Scrub known secret values from each lane's declarative snapshot before any bundle uses it. */
247
+ /** Scrub known secret values from each participant's declarative snapshot before any bundle uses it. */
248
248
  export function sanitizeParticipantRuns(runs, scrub) {
249
249
  for (const spec of runs) {
250
250
  if (spec.evidenceAssignment)
@@ -1,14 +1,13 @@
1
1
  import { type CuaActorDescriptor } from "../../actors/registry.js";
2
- import type { ComputerUsePlan, RoutePlanResult, RouteRefusal } from "../../lab/plan-types.js";
3
- import type { LabConfig, LabSubjectServe, LabSubjectState } from "../../lab/types.js";
4
- import type { RunLabProvenance } from "../../run/status.js";
5
- import { type CuaActorLabErrorCode, type CuaActorLabHooks, type RunCuaActorLabOptions } from "./types.js";
2
+ import type { ComputerUsePlan, ComputerUseRunner, RoutePlanResult, RouteRefusal } from "../../lab/plan-types.js";
3
+ import type { LabConfig, LabSubjectState } from "../../lab/types.js";
4
+ import { type CuaActorLabErrorCode, type RunCuaActorLabOptions } from "./types.js";
6
5
  /** The error a computer-use lab returns before a run starts. */
7
6
  export interface ComputerUseRefusal extends RouteRefusal<"computer-use", CuaActorLabErrorCode> {
8
7
  /**
9
8
  * Where the route returns it. "before-scope": analysis and tasks, returned before the run scope
10
9
  * with no automatic-analysis record. "in-scope": after the cwd checks. "after-personas": after
11
- * the route reads committed persona files, so a persona-file error still wins over the lane cap
10
+ * the route reads committed persona files, so a persona-file error still wins over the participant cap
12
11
  * and in-process fan-out.
13
12
  */
14
13
  readonly stage: "before-scope" | "in-scope" | "after-personas";
@@ -18,39 +17,32 @@ export interface ComputerUseRefusal extends RouteRefusal<"computer-use", CuaActo
18
17
  export type ComputerUsePlanResult = RoutePlanResult<ComputerUsePlan, ComputerUseRefusal>;
19
18
  /** The registered descriptor for a planned actor id; planComputerUseLab checked the registry. */
20
19
  export declare function cuaDescriptorOf(actor: string): CuaActorDescriptor;
21
- /** Which subject route a computer-use lab takes, derived once from its config and hooks. */
22
- export interface CuaSubjectRoute {
23
- cloneRoute: boolean;
24
- /** A CLI studied at a desktop: nothing cloned, no browser, a terminal instead. */
25
- desktopCliRoute: boolean;
26
- localTreeRoute: boolean;
27
- /**
28
- * Clone and local-tree both provision the subject in-sandbox (clone via git, local-tree via
29
- * pack+upload) and share the install/build/state/start/probe pipeline, so every seam that gates
30
- * on "does this route provision a subject" is keyed on this union.
31
- */
32
- provisionedRoute: boolean;
33
- localAppSubject: boolean;
34
- /** A caller-supplied executor drives the subject in-process; no desktop is created. */
35
- inProcessRoute: boolean;
36
- serve: LabSubjectServe | undefined;
37
- appUrl: string;
38
- subjectRepo: string | undefined;
39
- subjectEnvNames: string[];
20
+ /** Which of the caller's driving homes, createProvider and inProcess, a run has. */
21
+ export interface CallerDriving {
22
+ readonly inProcess: boolean;
23
+ readonly createProvider: boolean;
40
24
  }
41
- export declare function cuaSubjectRoute(config: LabConfig, hooks: CuaActorLabHooks): CuaSubjectRoute;
25
+ /** The driving a computer-use run's options carry. */
26
+ export declare function callerDrivingOf(options: {
27
+ readonly inProcess?: unknown;
28
+ readonly createProvider?: unknown;
29
+ }): CallerDriving;
42
30
  /** The state a planned run's provisioned subject declares. Other subjects declare none. */
43
31
  export declare function cuaDeclaredState(plan: ComputerUsePlan): LabSubjectState | undefined;
44
- /** The route facts a planned run takes: its runner's desktop and subject. */
45
- export declare function cuaSubjectRouteOf(plan: ComputerUsePlan): CuaSubjectRoute;
32
+ /** The URL a refused lab's result names, from its declaration: a provisioned subject's serve URL. */
33
+ export declare function declaredAppUrl(config: LabConfig): string;
34
+ /** The URL a planned run's participants open: a provisioned subject's served URL, else its own. */
35
+ export declare function plannedAppUrl(subject: ComputerUseRunner["subject"]): string;
46
36
  /**
47
37
  * Plan a computer-use lab. It is called for any config handed to the computer-use runner, not only
48
38
  * one routeOf sends here, so a config for another route gets this route's refusal.
49
39
  */
50
40
  export declare function planComputerUseLab(config: LabConfig, input: {
51
41
  readonly dryRun: boolean;
52
- readonly lab?: RunLabProvenance;
53
- readonly hooks?: CuaActorLabHooks;
42
+ /** Whether deps.runSession is set: a caller's session runner cannot enforce maxOutputTokens. */
43
+ readonly hasRunSession?: boolean;
44
+ /** Which of the caller's driving homes are set; neither when absent. */
45
+ readonly driving?: CallerDriving;
54
46
  readonly countOverride?: number;
55
47
  readonly rerun?: RunCuaActorLabOptions["rerun"];
56
48
  }): ComputerUsePlanResult;
@@ -15,7 +15,6 @@ import { isLocalBrowserLab } from "../../substrates/local/runtime-config.js";
15
15
  import { boundedConcurrency, defaultSessionTimeoutMs, resolveParticipantSandboxMs, } from "./participant-runs.js";
16
16
  import { MAX_SANDBOX_MS } from "../../substrates/e2b/lifetime.js";
17
17
  import {} from "./types.js";
18
- import { participantDesktopOf } from "./participant-desktop.js";
19
18
  /** The registered descriptor for a planned actor id; planComputerUseLab checked the registry. */
20
19
  export function cuaDescriptorOf(actor) {
21
20
  const descriptor = actorRegistry[actor];
@@ -23,7 +22,7 @@ export function cuaDescriptorOf(actor) {
23
22
  throw new Error(`planned actor "${actor}" is not a registered computer-use actor`);
24
23
  return descriptor;
25
24
  }
26
- export function cuaSubjectRoute(config, hooks) {
25
+ function declaredSubjectRoute(config, driving) {
27
26
  const cloneRoute = config.subject.source === "clone";
28
27
  const localTreeRoute = config.subject.source === "local-tree";
29
28
  const provisionedRoute = cloneRoute || localTreeRoute;
@@ -34,34 +33,36 @@ export function cuaSubjectRoute(config, hooks) {
34
33
  localTreeRoute,
35
34
  provisionedRoute,
36
35
  localAppSubject: config.subject.source === "local-app",
37
- inProcessRoute: hooks.buildExecutor !== undefined,
36
+ inProcessRoute: driving.inProcess,
38
37
  serve,
39
38
  appUrl: (provisionedRoute ? serve?.url : config.subject.appUrl) ?? "",
40
39
  subjectRepo: cloneRoute ? (config.subject.repos?.[0] ?? "") : undefined,
41
40
  subjectEnvNames: provisionedRoute ? (config.subject.env ?? []) : [],
42
41
  };
43
42
  }
43
+ /** The driving a computer-use run's options carry. */
44
+ export function callerDrivingOf(options) {
45
+ return {
46
+ inProcess: options.inProcess !== undefined,
47
+ createProvider: options.createProvider !== undefined,
48
+ };
49
+ }
44
50
  /** The state a planned run's provisioned subject declares. Other subjects declare none. */
45
51
  export function cuaDeclaredState(plan) {
46
52
  const { subject } = plan.runner;
47
53
  return subject.kind === "clone" || subject.kind === "local-tree" ? subject.state : undefined;
48
54
  }
49
- /** The route facts a planned run takes: its runner's desktop and subject. */
50
- export function cuaSubjectRouteOf(plan) {
51
- const { desktop, subject } = plan.runner;
52
- const provisioned = subject.kind === "clone" || subject.kind === "local-tree" ? subject : undefined;
53
- return {
54
- cloneRoute: subject.kind === "clone",
55
- desktopCliRoute: subject.kind === "desktop-cli",
56
- localTreeRoute: subject.kind === "local-tree",
57
- provisionedRoute: provisioned !== undefined,
58
- localAppSubject: subject.kind === "local-app",
59
- inProcessRoute: desktop === "in-process",
60
- serve: provisioned?.serve,
61
- appUrl: provisioned?.serve.url ?? ("appUrl" in subject ? subject.appUrl : ""),
62
- subjectRepo: subject.kind === "clone" ? subject.repo : undefined,
63
- subjectEnvNames: [...(provisioned?.env ?? [])],
64
- };
55
+ /** The URL a refused lab's result names, from its declaration: a provisioned subject's serve URL. */
56
+ export function declaredAppUrl(config) {
57
+ const { subject } = config;
58
+ const provisioned = subject.source === "clone" || subject.source === "local-tree";
59
+ return (provisioned ? subject.serve?.url : subject.appUrl) ?? "";
60
+ }
61
+ /** The URL a planned run's participants open: a provisioned subject's served URL, else its own. */
62
+ export function plannedAppUrl(subject) {
63
+ if (subject.kind === "clone" || subject.kind === "local-tree")
64
+ return subject.serve.url;
65
+ return "appUrl" in subject ? subject.appUrl : "";
65
66
  }
66
67
  const invalid = (message) => ({
67
68
  code: "HUMANISH_CUA_LAB_SUBJECT_INVALID",
@@ -72,22 +73,22 @@ const invalid = (message) => ({
72
73
  * is touched. The parser enforces most of these too; the engine repeats them for library callers
73
74
  * that hand it a config directly. The groups run in this order, and each returns its first reason.
74
75
  */
75
- function cuaLabRejection(config, hooks, subjectRoute) {
76
- return (unsupportedDeclarationReason(config, hooks, subjectRoute) ??
76
+ function cuaLabRejection(config, hasRunSession, driving, subjectRoute) {
77
+ return (unsupportedDeclarationReason(config, hasRunSession, driving, subjectRoute) ??
77
78
  subjectStructureReason(config, subjectRoute) ??
78
79
  entryTargetReason(config, subjectRoute) ??
79
- driverReason(config, hooks, subjectRoute) ??
80
+ driverReason(driving, subjectRoute) ??
80
81
  rosterShapeReason(config));
81
82
  }
82
83
  /** A declaration this route cannot honor, for any subject or with the caller's own driver. */
83
- function unsupportedDeclarationReason(config, hooks, { inProcessRoute }) {
84
+ function unsupportedDeclarationReason(config, hasRunSession, driving, { inProcessRoute }) {
84
85
  const reason = desktopMediaValidationReason(config) ||
85
86
  outputTokenLimitValidationReason(config) ||
86
87
  scenarioCapsValidationReason(config);
87
88
  if (reason)
88
89
  return invalid(reason);
89
90
  if (config.actors[0]?.maxOutputTokens !== undefined &&
90
- (hooks.runSession || hooks.buildProvider || hooks.buildExecutor))
91
+ (hasRunSession || driving.createProvider || driving.inProcess))
91
92
  return invalid("maxOutputTokens cannot be enforced by a custom runSession/provider/executor route.");
92
93
  const receivingReason = receivingEmailValidationReason(config);
93
94
  if (receivingReason)
@@ -151,14 +152,14 @@ function entryTargetReason(config, subjectRoute) {
151
152
  : "subject.appUrl and actors[0].lanes[].target entries must be valid http(s) URLs.",
152
153
  };
153
154
  }
154
- /** Something to drive the subject: the caller's executor with its provider, or a local desktop. */
155
- function driverReason(config, hooks, { localAppSubject, inProcessRoute }) {
155
+ /** Something to drive the subject: the caller's executor with its provider. */
156
+ function driverReason(driving, { localAppSubject, inProcessRoute }) {
156
157
  // A custom executor needs a custom provider too: the default OpenAI provider is vision-based
157
158
  // and would fail closed against an executor that returns no screenshot.
158
- if (hooks.buildExecutor !== undefined && hooks.buildProvider === undefined)
159
+ if (driving.inProcess && !driving.createProvider)
159
160
  return {
160
161
  code: "HUMANISH_CUA_LAB_EXECUTOR_NO_PROVIDER",
161
- message: "cuaHooks.buildExecutor requires cuaHooks.buildProvider — a state-driven executor returns no screenshot, so it must be paired with a NON-vision provider (the default OpenAI computer-use provider is vision-based and would fail closed).",
162
+ message: "RunLabOptions.inProcess requires RunLabOptions.createProvider — a state-driven executor returns no screenshot, so it must be paired with a NON-vision provider (the default OpenAI computer-use provider is vision-based and would fail closed).",
162
163
  };
163
164
  // There is no built-in in-process driver for a local app.
164
165
  if (localAppSubject && !inProcessRoute)
@@ -166,21 +167,12 @@ function driverReason(config, hooks, { localAppSubject, inProcessRoute }) {
166
167
  code: "HUMANISH_CUA_LAB_LOCAL_APP_NO_EXECUTOR",
167
168
  message: "subject.source: local-app has no built-in driver. Supply one through runLab(config, { inProcess: { executor }, createProvider }); a state-driven executor needs a non-vision provider.",
168
169
  };
169
- // runLab gives a local browser study its desktop lane; a direct route call or an in-process
170
- // executor on the same lab has none.
171
- if (config.subject.source === "app-url" &&
172
- config.execution?.target === "local" &&
173
- participantDesktopOf(hooks) === undefined)
174
- return {
175
- code: "HUMANISH_CUA_LAB_LOCAL_DESKTOP_MISSING",
176
- message: "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.",
177
- };
178
170
  return undefined;
179
171
  }
180
- /** The lane roster, then the sandbox deadline its session budget derives. */
172
+ /** The participant roster, then the sandbox deadline its session budget derives. */
181
173
  function rosterShapeReason(config) {
182
- // Lanes XOR count/laneFocus, device XOR raw resolution, cap, unique ids,
183
- // allowPublicTargets with more than one lane, clone.fanout.
174
+ // `lanes` XOR `count`/`laneFocus`, device XOR raw resolution, cap, unique ids,
175
+ // allowPublicTargets with more than one participant, clone.fanout.
184
176
  const fanoutReason = cuaLaneValidationReason(config);
185
177
  if (fanoutReason)
186
178
  return { code: "HUMANISH_CUA_LAB_FANOUT_INVALID", message: fanoutReason };
@@ -195,12 +187,17 @@ function rosterShapeReason(config) {
195
187
  const headroomMs = derivedSandboxMs - sessionMs;
196
188
  return invalid(`execution.timeoutMs ${Math.round(sessionMs / 60_000)}m derives a ${Math.round(derivedSandboxMs / 60_000)}m sandbox deadline, and a sandbox may not live longer than ${MAX_SANDBOX_MS / 60_000}m. The deadline is the session budget plus ${Math.round(headroomMs / 60_000)}m of provisioning and teardown headroom${provisionedRoute ? " (this route clones, installs, builds and serves the subject before the actor starts)" : ""}. Lower execution.timeoutMs to at most ${Math.round((MAX_SANDBOX_MS - headroomMs) / 60_000)}m, or set execution.desktop.sandboxTimeoutMs explicitly.`);
197
189
  }
190
+ /** The plan's rerun: the source run and, when given, the participants to rerun. */
191
+ function rerunPlan({ sourceRunId, participantIds, }) {
192
+ return { sourceRunId, ...(participantIds === undefined ? {} : { participantIds }) };
193
+ }
198
194
  /**
199
195
  * Plan a computer-use lab. It is called for any config handed to the computer-use runner, not only
200
196
  * one routeOf sends here, so a config for another route gets this route's refusal.
201
197
  */
202
198
  export function planComputerUseLab(config, input) {
203
- const hooks = input.hooks ?? {};
199
+ const hasRunSession = input.hasRunSession === true;
200
+ const driving = input.driving ?? { inProcess: false, createProvider: false };
204
201
  const refuse = (stage, code, message, actor) => ({
205
202
  ok: false,
206
203
  refusal: {
@@ -223,10 +220,10 @@ export function planComputerUseLab(config, input) {
223
220
  if (!descriptor || !isCuaActorDescriptor(descriptor))
224
221
  return refuse("in-scope", "HUMANISH_CUA_LAB_ACTOR_UNSUPPORTED", `actors[0].type "${actorType}" is not a registered computer-use actor.`);
225
222
  const actor = descriptor.id;
226
- const rejection = cuaLabRejection(config, hooks, cuaSubjectRoute(config, hooks));
223
+ const rejection = cuaLabRejection(config, hasRunSession, driving, declaredSubjectRoute(config, driving));
227
224
  if (rejection)
228
225
  return refuse("in-scope", rejection.code, rejection.message, actor);
229
- // A shared world runs every seat against one app; this route would run them as separate lanes.
226
+ // A shared world runs every seat against one app; this route would run them as separate participants.
230
227
  // It comes after the rules above, so a shared-world config that breaks one of them, which runLab
231
228
  // sends here, still gets that rule's message.
232
229
  if (config.subject.topology === "shared-world")
@@ -234,9 +231,9 @@ export function planComputerUseLab(config, input) {
234
231
  // The in-process route drives subject.appUrl on this machine and creates no desktop, so it would
235
232
  // skip the subject a clone, local-tree or desktop-cli lab declares.
236
233
  const source = config.subject.source;
237
- if (hooks.buildExecutor !== undefined &&
234
+ if (driving.inProcess &&
238
235
  (source === "clone" || source === "local-tree" || source === "desktop-cli"))
239
- return refuse("in-scope", "HUMANISH_CUA_LAB_SUBJECT_INVALID", `cuaHooks.buildExecutor drives subject.appUrl in this process, and a ${source} subject needs the hosted desktop the in-process route never creates. Use an app-url or local-app subject with buildExecutor, or remove buildExecutor to run on a hosted desktop.`, actor);
236
+ return refuse("in-scope", "HUMANISH_CUA_LAB_SUBJECT_INVALID", `RunLabOptions.inProcess drives subject.appUrl in this process, and a ${source} subject needs the hosted desktop the in-process route never creates. Use an app-url or local-app subject with inProcess, or remove inProcess to run on a hosted desktop.`, actor);
240
237
  // The parser's rule; without a product the desktop study fails later.
241
238
  const productReason = desktopCliProductReason(config);
242
239
  if (productReason)
@@ -245,22 +242,25 @@ export function planComputerUseLab(config, input) {
245
242
  if (participants.length > MAX_CUA_LANES)
246
243
  return refuse("after-personas", "HUMANISH_CUA_LAB_FANOUT_INVALID", `Computer-use fan-out is capped at ${MAX_CUA_LANES} participants (resolved ${participants.length}); N concurrent paid desktops is real spend.`, actor);
247
244
  const [first, ...rest] = participants;
248
- if (hooks.buildExecutor !== undefined && rest.length > 0)
249
- return refuse("after-personas", "HUMANISH_CUA_LAB_FANOUT_INVALID", "Fan-out to more than one participant is not supported on the in-process route (RunLabOptions.inProcess, or the deprecated cuaHooks.buildExecutor): fan-out provisions one independent E2B desktop per participant, which the in-process route deliberately skips. Run a single in-process participant, or fan out on the E2B route.", actor);
245
+ if (driving.inProcess && rest.length > 0)
246
+ return refuse("after-personas", "HUMANISH_CUA_LAB_FANOUT_INVALID", "Fan-out to more than one participant is not supported on the in-process route (RunLabOptions.inProcess): fan-out provisions one independent E2B desktop per participant, which the in-process route deliberately skips. Run a single in-process participant, or fan out on the E2B route.", actor);
250
247
  if (first === undefined)
251
248
  throw new Error("computerUseParticipants returned no participant");
252
249
  const appUrl = config.subject.appUrl ?? "";
250
+ const declaredServeUrl = config.subject.serve?.url;
251
+ const serveUrl = declaredServeUrl === undefined ? {} : { serveUrl: declaredServeUrl };
253
252
  const appUrlSubject = {
254
253
  kind: "app-url",
255
254
  appUrl,
256
255
  publicTargets: config.policies?.allowPublicTargets === true,
256
+ ...serveUrl,
257
257
  };
258
258
  const product = config.subject.product;
259
259
  const hosted = source === "desktop-cli" && product !== undefined
260
- ? { kind: "desktop-cli", product }
260
+ ? { kind: "desktop-cli", product, ...serveUrl }
261
261
  : (provisionedSubject(config) ?? appUrlSubject);
262
- const brain = brainOf(config, hooks.buildProvider !== undefined);
263
- const runner = hooks.buildExecutor !== undefined
262
+ const brain = brainOf(config, driving.createProvider);
263
+ const runner = driving.inProcess
264
264
  ? {
265
265
  desktop: "in-process",
266
266
  brain: callerBrainOf(config),
@@ -275,7 +275,6 @@ export function planComputerUseLab(config, input) {
275
275
  const provisioned = source === "clone" || source === "local-tree";
276
276
  const base = planBase(config, {
277
277
  dryRun: input.dryRun,
278
- ...(input.lab === undefined ? {} : { lab: input.lab }),
279
278
  analysis,
280
279
  });
281
280
  return {
@@ -289,18 +288,11 @@ export function planComputerUseLab(config, input) {
289
288
  sessionBudgetMs: config.execution?.timeoutMs ?? defaultSessionTimeoutMs(config),
290
289
  sandboxMs: resolveParticipantSandboxMs(config),
291
290
  caps: capsOf(config),
292
- ...(input.rerun === undefined
293
- ? {}
294
- : {
295
- rerun: {
296
- sourceRunId: input.rerun.sourceRunId,
297
- ...(input.rerun.laneIds === undefined ? {} : { participantIds: input.rerun.laneIds }),
298
- },
299
- }),
291
+ ...(input.rerun === undefined ? {} : { rerun: rerunPlan(input.rerun) }),
300
292
  requirements: base.dryRun || runner.desktop === "in-process"
301
293
  ? []
302
294
  : desktopRequirements(config, {
303
- e2b: runner.desktop === "e2b-desktop" && hooks.createDesktopLane === undefined,
295
+ e2b: runner.desktop === "e2b-desktop",
304
296
  brain,
305
297
  localVm: runner.desktop === "local-vm",
306
298
  externalCatch: !provisioned,
@@ -1,6 +1,6 @@
1
1
  import type { Brain, ComputerUsePlan } from "../../lab/plan-types.js";
2
2
  import type { LabCommsExternal } from "../../lab/types.js";
3
- import type { CuaActorLabErrorCode, CuaActorLabHooks } from "./types.js";
3
+ import type { CuaActorLabErrorCode } from "./types.js";
4
4
  /**
5
5
  * The first reason a live computer-use run cannot start on this machine: missing keys, a missing
6
6
  * or signed-out local agent, missing subject env, a spend cap with no price, or an unreachable
@@ -11,11 +11,9 @@ export declare function liveCuaRejection(args: {
11
11
  caps: ComputerUsePlan["caps"];
12
12
  /** The plan's brain: whether a local agent drives the participant, and the model a cap prices. */
13
13
  brain: Brain;
14
- hooks: CuaActorLabHooks;
15
14
  env: Record<string, string | undefined>;
16
- openaiApiKey: string;
17
- e2bApiKey: string;
18
- subjectEnvNames: string[];
15
+ /** The plan's requirements: which keys and subject env names this run needs. */
16
+ requirements: ComputerUsePlan["requirements"];
19
17
  externalCommsConfig: LabCommsExternal | undefined;
20
18
  }): Promise<{
21
19
  code: CuaActorLabErrorCode;
@@ -1,10 +1,11 @@
1
1
  import { pricedModel } from "../../lab/plan-base.js";
2
+ import { missingKeys, missingSubjectEnv } from "../../lab/requirements.js";
2
3
  import { detectLocalAgents } from "../../actors/local-agent/cli.js";
3
4
  import { localAgentRefusal } from "../../actors/local-agent/readiness.js";
4
5
  import { describeMissingKeys } from "../../keys/key-resolution.js";
6
+ import { catchTokenOf, catchTokenRefusal } from "../../comms/external-evidence.js";
5
7
  import { externalCatchHealthy } from "../../comms/sandbox-catch.js";
6
8
  import { MODEL_RATES } from "../../run/pricing.js";
7
- import { participantDesktopOf } from "./participant-desktop.js";
8
9
  /** The computer-use code for each local-agent refusal; shared-world keeps the same kinds. */
9
10
  const LOCAL_AGENT_REFUSAL_CODES = {
10
11
  "agent-missing": "HUMANISH_CUA_LAB_AGENT_MISSING",
@@ -19,19 +20,16 @@ const LOCAL_AGENT_REFUSAL_CODES = {
19
20
  * already paid for a desktop.
20
21
  */
21
22
  export async function liveCuaRejection(args) {
22
- const { caps, brain, hooks, env, openaiApiKey, e2bApiKey, subjectEnvNames, externalCommsConfig } = args;
23
- // The operator's own signed-in coding agent is the brain, so there is no provider key to ask
24
- // for. E2B is still required: the persona needs a machine.
23
+ const { caps, brain, env, requirements, externalCommsConfig } = args;
24
+ // The plan lists OPENAI_API_KEY only for an openai brain (a signed-in local agent or the
25
+ // caller's provider needs none) and E2B_API_KEY only when this run creates hosted desktops.
25
26
  const localAgent = brain.kind === "local-agent" ? brain.agent : undefined;
26
- const missingKeys = [
27
- ...(openaiApiKey || localAgent || hooks.buildProvider ? [] : ["OPENAI_API_KEY"]),
28
- ...(e2bApiKey || participantDesktopOf(hooks) !== undefined ? [] : ["E2B_API_KEY"]),
29
- ];
30
- if (missingKeys.length > 0) {
27
+ const missing = missingKeys(requirements, env);
28
+ if (missing.length > 0) {
31
29
  // The moment someone new actually hits the wall. If a signed-in coding agent is sitting
32
30
  // right there, say so HERE rather than making them go and find an API key — that detour is
33
31
  // where most people trying humanish stop.
34
- const suggestion = missingKeys.includes("OPENAI_API_KEY")
32
+ const suggestion = missing.includes("OPENAI_API_KEY")
35
33
  ? await (async () => {
36
34
  const ready = (await detectLocalAgents({ env })).filter((agent) => agent.authStatus === "authenticated");
37
35
  return ready.length === 0
@@ -42,21 +40,22 @@ export async function liveCuaRejection(args) {
42
40
  : "";
43
41
  return {
44
42
  code: "HUMANISH_CUA_LAB_KEYS_MISSING",
45
- message: `Live computer-use labs need ${missingKeys.join(" and ")} in the environment (values are never persisted). ${describeMissingKeys(missingKeys, env)}${suggestion}`,
43
+ message: `Live computer-use labs need ${missing.join(" and ")} in the environment (values are never persisted). ${describeMissingKeys(missing, env)}${suggestion}`,
46
44
  };
47
45
  }
48
- if (localAgent && !hooks.buildProvider) {
46
+ // A caller's createProvider makes the brain `caller`, so only the lab's own local agent is checked.
47
+ if (localAgent) {
49
48
  // Refuse HERE, before a sandbox exists. "codex is not installed" discovered after the
50
49
  // machine is paid for is the same information delivered at the worst possible moment.
51
50
  const refusal = await localAgentRefusal({ agent: localAgent, env, caps });
52
51
  if (refusal)
53
52
  return { code: LOCAL_AGENT_REFUSAL_CODES[refusal.kind], message: refusal.message };
54
53
  }
55
- const missingSubjectEnv = subjectEnvNames.filter((name) => !env[name]?.trim());
56
- if (missingSubjectEnv.length > 0) {
54
+ const unsetSubjectEnv = missingSubjectEnv(requirements, env);
55
+ if (unsetSubjectEnv.length > 0) {
57
56
  return {
58
57
  code: "HUMANISH_CUA_LAB_SUBJECT_ENV_MISSING",
59
- message: `subject.env declares ${missingSubjectEnv.join(", ")} but the environment does not provide ${missingSubjectEnv.length === 1 ? "it" : "them"} (pass via --env-file; values are never persisted).`,
58
+ message: `subject.env declares ${unsetSubjectEnv.join(", ")} but the environment does not provide ${unsetSubjectEnv.length === 1 ? "it" : "them"} (pass via --env-file; values are never persisted).`,
60
59
  };
61
60
  }
62
61
  // FAIL-CLOSED CAP TENSION (discipline #3): a maxUsd cap needs a MEASURABLE per-turn estimate.
@@ -76,9 +75,14 @@ export async function liveCuaRejection(args) {
76
75
  }
77
76
  }
78
77
  // Adopter-hosted comms catch (#380): fail closed BEFORE any sandbox is created — a comms lab
79
- // whose catch is unreachable collects nothing while every lane still spends. The probe asserts
78
+ // whose catch is unreachable collects nothing while every participant still spends. The probe asserts
80
79
  // OUR service marker in /health, so an adopter's proxy answering 200 for everything cannot
81
80
  // pass for a catch.
81
+ const tokenRefusal = externalCommsConfig === undefined
82
+ ? undefined
83
+ : catchTokenRefusal(catchTokenOf(externalCommsConfig, env));
84
+ if (tokenRefusal !== undefined)
85
+ return { code: "HUMANISH_CUA_LAB_COMMS_TOKEN_INVALID", message: tokenRefusal };
82
86
  if (externalCommsConfig && !(await externalCatchHealthy(externalCommsConfig))) {
83
87
  return {
84
88
  code: "HUMANISH_CUA_LAB_COMMS_CATCH_UNREACHABLE",
@@ -99,13 +99,17 @@ function snapshotPriorParticipant(stream) {
99
99
  const reason = stream.ui?.state ?? stream.actor?.reason;
100
100
  const actions = stream.actor?.counts.actions ?? 0;
101
101
  const messages = stream.actor?.counts.messages ?? 0;
102
+ // The judge's status decides, so a participant the review counts as blocked is rerunnable. A
103
+ // bundle written before streams carried it falls back to the trace status and counts.
102
104
  const hollow = completionReason === "goal_satisfied" && actions === 0 && messages === 0;
103
- const rerunnable = stream.status !== "passed" ||
104
- actorStatus === "failed" ||
105
- actorStatus === "blocked" ||
106
- actorStatus === "timed_out" ||
107
- completionReason === "harness_error" ||
108
- hollow;
105
+ const rerunnable = stream.judgedStatus !== undefined
106
+ ? stream.judgedStatus !== "passed"
107
+ : stream.status !== "passed" ||
108
+ actorStatus === "failed" ||
109
+ actorStatus === "blocked" ||
110
+ actorStatus === "timed_out" ||
111
+ completionReason === "harness_error" ||
112
+ hollow;
109
113
  return {
110
114
  participantId: stream.laneId,
111
115
  previous: {
@@ -1,4 +1,4 @@
1
- import type { runLabParticipants } from "./run-lanes.js";
1
+ import type { runLabParticipants } from "./live-phase.js";
2
2
  import type { CuaFinishFacts, CuaRunSetup } from "./setup.js";
3
3
  import { type CuaActorLabResult } from "./types.js";
4
4
  /** Builds and publishes the final bundle, runs the adapter hooks, renders the Observer and returns the result. */