humanish 0.106.1 → 0.108.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 (668) hide show
  1. package/ARCHITECTURE.md +38 -32
  2. package/CHANGELOG.md +28 -0
  3. package/CONTEXT.md +51 -41
  4. package/README.md +152 -174
  5. package/SECURITY.md +16 -26
  6. package/TELEMETRY.md +8 -6
  7. package/dist/actors/affordance.d.ts +4 -4
  8. package/dist/actors/affordance.js +12 -12
  9. package/dist/actors/agent-session.d.ts +2 -2
  10. package/dist/actors/agent-session.js +7 -7
  11. package/dist/actors/codex/app-server-actor-trace.d.ts +1 -1
  12. package/dist/actors/codex/app-server-actor-trace.js +1 -1
  13. package/dist/actors/codex/app-server-client.js +2 -1
  14. package/dist/actors/codex/app-server-trace.d.ts +0 -1
  15. package/dist/actors/codex/app-server-trace.js +1 -3
  16. package/dist/actors/codex/app-server-ui.js +1 -1
  17. package/dist/actors/codex/app-server.js +2 -1
  18. package/dist/actors/codex/codex-admission.d.ts +91 -0
  19. package/dist/actors/codex/codex-admission.js +150 -0
  20. package/dist/actors/codex/protocol-compat.d.ts +27 -0
  21. package/dist/actors/codex/protocol-compat.js +357 -0
  22. package/dist/actors/codex/protocol-contract.d.ts +61 -0
  23. package/dist/actors/codex/protocol-contract.js +471 -0
  24. package/dist/actors/codex/restricted-executable.d.ts +28 -4
  25. package/dist/actors/codex/restricted-executable.js +104 -29
  26. package/dist/actors/codex/restricted-launch.d.ts +9 -2
  27. package/dist/actors/codex/restricted-launch.js +43 -4
  28. package/dist/actors/codex/restricted-notifications.d.ts +101 -0
  29. package/dist/actors/codex/restricted-notifications.js +277 -0
  30. package/dist/actors/codex/restricted-participant.d.ts +30 -0
  31. package/dist/actors/codex/restricted-participant.js +66 -6
  32. package/dist/actors/codex/restricted-policy.d.ts +11 -3
  33. package/dist/actors/codex/restricted-policy.js +2 -2
  34. package/dist/actors/codex/restricted-session.d.ts +16 -3
  35. package/dist/actors/codex/restricted-session.js +60 -22
  36. package/dist/actors/codex/restricted-transport.d.ts +29 -0
  37. package/dist/actors/codex/restricted-transport.js +139 -27
  38. package/dist/actors/codex/restricted-turn.d.ts +19 -4
  39. package/dist/actors/codex/restricted-turn.js +43 -30
  40. package/dist/actors/computer-use/actor.d.ts +17 -17
  41. package/dist/actors/computer-use/actor.js +6 -6
  42. package/dist/actors/computer-use/admission-limit.d.ts +1 -1
  43. package/dist/actors/computer-use/admission-limit.js +1 -1
  44. package/dist/actors/computer-use/loop/actions.d.ts +3 -3
  45. package/dist/actors/computer-use/loop/actions.js +10 -10
  46. package/dist/actors/computer-use/loop/backstop.d.ts +3 -3
  47. package/dist/actors/computer-use/loop/backstop.js +15 -13
  48. package/dist/actors/computer-use/loop/ending.d.ts +7 -7
  49. package/dist/actors/computer-use/loop/ending.js +9 -9
  50. package/dist/actors/computer-use/loop/observation.d.ts +2 -2
  51. package/dist/actors/computer-use/loop/observation.js +9 -9
  52. package/dist/actors/computer-use/loop/provider-call.d.ts +1 -1
  53. package/dist/actors/computer-use/loop/provider-call.js +1 -1
  54. package/dist/actors/computer-use/loop/session.js +3 -3
  55. package/dist/actors/computer-use/loop/spend.d.ts +2 -2
  56. package/dist/actors/computer-use/loop/spend.js +4 -4
  57. package/dist/actors/computer-use/loop/trace.js +11 -10
  58. package/dist/actors/computer-use/loop/types.d.ts +37 -26
  59. package/dist/actors/computer-use/loop/usage.js +2 -2
  60. package/dist/actors/computer-use/loop.js +4 -4
  61. package/dist/actors/computer-use/openai-context.d.ts +37 -0
  62. package/dist/actors/computer-use/openai-context.js +214 -0
  63. package/dist/actors/computer-use/openai-provider.d.ts +12 -9
  64. package/dist/actors/computer-use/openai-provider.js +47 -36
  65. package/dist/actors/computer-use/openai-requests.d.ts +36 -10
  66. package/dist/actors/computer-use/openai-requests.js +82 -15
  67. package/dist/actors/computer-use/openai-wire.d.ts +19 -7
  68. package/dist/actors/computer-use/openai-wire.js +36 -34
  69. package/dist/actors/contract.d.ts +86 -49
  70. package/dist/actors/contract.js +29 -23
  71. package/dist/actors/local-agent/claude-session.d.ts +1 -1
  72. package/dist/actors/local-agent/claude-session.js +10 -9
  73. package/dist/actors/local-agent/cli.d.ts +8 -6
  74. package/dist/actors/local-agent/cli.js +24 -28
  75. package/dist/actors/local-agent/readiness.d.ts +2 -2
  76. package/dist/actors/local-agent/readiness.js +4 -4
  77. package/dist/actors/reasoning-effort.js +6 -6
  78. package/dist/actors/registry.d.ts +10 -10
  79. package/dist/actors/registry.js +18 -17
  80. package/dist/actors/scripted-browser/actor.d.ts +8 -8
  81. package/dist/actors/scripted-browser/actor.js +16 -16
  82. package/dist/actors/scripted-browser/browser-command.js +1 -1
  83. package/dist/actors/scripted-browser/journey.js +15 -4
  84. package/dist/actors/scripted-browser/steps.js +19 -1
  85. package/dist/actors/scripted-browser/types.d.ts +12 -2
  86. package/dist/actors/stop-conditions.d.ts +1 -1
  87. package/dist/actors/stop-conditions.js +1 -3
  88. package/dist/analysis/automatic-completion.d.ts +13 -8
  89. package/dist/analysis/automatic-completion.js +14 -8
  90. package/dist/analysis/automatic-config.d.ts +1 -1
  91. package/dist/analysis/automatic-config.js +2 -2
  92. package/dist/analysis/automatic.d.ts +10 -4
  93. package/dist/analysis/automatic.js +17 -13
  94. package/dist/analysis/codex-config.d.ts +6 -2
  95. package/dist/analysis/codex-config.js +22 -14
  96. package/dist/analysis/diagnostics.d.ts +23 -0
  97. package/dist/analysis/diagnostics.js +112 -0
  98. package/dist/analysis/evidence-sources.js +2 -2
  99. package/dist/analysis/evidence.js +6 -6
  100. package/dist/analysis/execute.d.ts +7 -1
  101. package/dist/analysis/execute.js +39 -12
  102. package/dist/analysis/job.d.ts +8 -5
  103. package/dist/analysis/job.js +15 -14
  104. package/dist/analysis/load.d.ts +1 -1
  105. package/dist/analysis/load.js +5 -5
  106. package/dist/analysis/provider.d.ts +9 -1
  107. package/dist/analysis/restricted-codex.d.ts +2 -0
  108. package/dist/analysis/restricted-codex.js +10 -1
  109. package/dist/analysis/service.d.ts +2 -0
  110. package/dist/analysis/service.js +35 -16
  111. package/dist/analysis/sharing.d.ts +2 -2
  112. package/dist/analysis/sharing.js +5 -5
  113. package/dist/analysis/store-executions.d.ts +5 -5
  114. package/dist/analysis/store-executions.js +12 -12
  115. package/dist/analysis/store.d.ts +4 -4
  116. package/dist/analysis/store.js +13 -13
  117. package/dist/cli/commands/analysis-signals.d.ts +2 -1
  118. package/dist/cli/commands/analysis-signals.js +4 -1
  119. package/dist/cli/commands/analyze.js +23 -18
  120. package/dist/cli/commands/codex.js +9 -9
  121. package/dist/cli/commands/comms.js +62 -34
  122. package/dist/cli/commands/feedback.js +20 -21
  123. package/dist/cli/commands/lab-format.d.ts +5 -4
  124. package/dist/cli/commands/lab-format.js +35 -23
  125. package/dist/cli/commands/lab-route-computer-use.d.ts +0 -2
  126. package/dist/cli/commands/lab-route-computer-use.js +32 -21
  127. package/dist/cli/commands/lab-route-preview.d.ts +1 -3
  128. package/dist/cli/commands/lab-route-preview.js +7 -7
  129. package/dist/cli/commands/lab-route-run.d.ts +6 -4
  130. package/dist/cli/commands/lab-route-run.js +6 -2
  131. package/dist/cli/commands/lab-route-scripted.d.ts +0 -2
  132. package/dist/cli/commands/lab-route-scripted.js +0 -1
  133. package/dist/cli/commands/lab-route-shared-world.d.ts +0 -2
  134. package/dist/cli/commands/lab-route-shared-world.js +3 -4
  135. package/dist/cli/commands/lab-route-terminal.d.ts +0 -2
  136. package/dist/cli/commands/lab-route-terminal.js +0 -1
  137. package/dist/cli/commands/lab-run.js +84 -54
  138. package/dist/cli/commands/lab-scorer.d.ts +2 -4
  139. package/dist/cli/commands/lab-scorer.js +1 -1
  140. package/dist/cli/commands/migrate.d.ts +4 -0
  141. package/dist/cli/commands/migrate.js +65 -0
  142. package/dist/cli/commands/observe.js +168 -107
  143. package/dist/cli/commands/run-command.d.ts +10 -0
  144. package/dist/cli/commands/run-command.js +85 -0
  145. package/dist/cli/commands/run-signals.d.ts +30 -0
  146. package/dist/cli/commands/run-signals.js +146 -0
  147. package/dist/cli/commands/runs.js +137 -136
  148. package/dist/cli/commands/setup.d.ts +2 -2
  149. package/dist/cli/commands/setup.js +26 -21
  150. package/dist/cli/commands/study.d.ts +3 -0
  151. package/dist/cli/commands/study.js +182 -0
  152. package/dist/cli/commands/tui.d.ts +4 -4
  153. package/dist/cli/commands/tui.js +21 -21
  154. package/dist/cli/commands/watch.js +64 -77
  155. package/dist/cli/deprecations.d.ts +18 -0
  156. package/dist/cli/deprecations.js +48 -0
  157. package/dist/cli/doctor.d.ts +18 -5
  158. package/dist/cli/doctor.js +111 -48
  159. package/dist/cli/first-run-path.d.ts +12 -10
  160. package/dist/cli/first-run-path.js +30 -28
  161. package/dist/cli/io.d.ts +46 -10
  162. package/dist/cli/io.js +109 -30
  163. package/dist/cli/observer-follow.d.ts +2 -2
  164. package/dist/cli/observer-follow.js +5 -6
  165. package/dist/cli/orientation.d.ts +6 -3
  166. package/dist/cli/orientation.js +43 -39
  167. package/dist/cli/product-sentence.d.ts +6 -0
  168. package/dist/cli/product-sentence.js +6 -0
  169. package/dist/cli/program.d.ts +6 -1
  170. package/dist/cli/program.js +112 -43
  171. package/dist/cli/telemetry.d.ts +17 -17
  172. package/dist/cli/telemetry.js +49 -41
  173. package/dist/cli.js +1 -1
  174. package/dist/comms/capture-surface.d.ts +14 -13
  175. package/dist/comms/capture-surface.js +23 -22
  176. package/dist/comms/catch-host.d.ts +8 -8
  177. package/dist/comms/catch-host.js +14 -14
  178. package/dist/comms/connections.js +4 -4
  179. package/dist/comms/email-catch.d.ts +3 -3
  180. package/dist/comms/email-catch.js +8 -8
  181. package/dist/comms/external-evidence.d.ts +27 -0
  182. package/dist/comms/external-evidence.js +93 -0
  183. package/dist/comms/extract.js +2 -2
  184. package/dist/comms/fake-inbox.d.ts +2 -2
  185. package/dist/comms/fake-inbox.js +2 -2
  186. package/dist/comms/lease-store.js +7 -7
  187. package/dist/comms/receiving-render.d.ts +1 -1
  188. package/dist/comms/receiving-render.js +2 -2
  189. package/dist/comms/sandbox-catch-script.d.ts +6 -6
  190. package/dist/comms/sandbox-catch-script.js +6 -6
  191. package/dist/comms/sandbox-catch.d.ts +36 -37
  192. package/dist/comms/sandbox-catch.js +34 -35
  193. package/dist/comms/setup.js +42 -8
  194. package/dist/comms/thread-evidence.d.ts +1 -1
  195. package/dist/comms/thread-evidence.js +6 -6
  196. package/dist/comms/types.d.ts +6 -6
  197. package/dist/comms/types.js +4 -4
  198. package/dist/evidence/browser-hygiene.d.ts +1 -1
  199. package/dist/evidence/browser-hygiene.js +1 -1
  200. package/dist/evidence/frame-signature.d.ts +1 -1
  201. package/dist/evidence/frame-signature.js +4 -4
  202. package/dist/evidence/redaction.d.ts +3 -3
  203. package/dist/evidence/redaction.js +5 -5
  204. package/dist/evidence/secret-scrub.d.ts +9 -0
  205. package/dist/evidence/secret-scrub.js +96 -0
  206. package/dist/feedback/draft.js +41 -85
  207. package/dist/feedback/export-bundle.js +5 -5
  208. package/dist/feedback/export.d.ts +5 -1
  209. package/dist/feedback/export.js +16 -17
  210. package/dist/feedback/feedback.d.ts +3 -3
  211. package/dist/feedback/feedback.js +21 -3
  212. package/dist/guest/chromium-text.js +2 -2
  213. package/dist/guest/desktop-native.d.ts +1 -1
  214. package/dist/guest/runtime.js +1 -1
  215. package/dist/index.d.ts +14 -15
  216. package/dist/index.js +10 -11
  217. package/dist/keys/key-resolution.d.ts +7 -5
  218. package/dist/keys/key-resolution.js +40 -38
  219. package/dist/lab/adapter-extension.d.ts +35 -13
  220. package/dist/lab/adapter-extension.js +50 -134
  221. package/dist/lab/adapter-scorer-loader.d.ts +32 -12
  222. package/dist/lab/adapter-scorer-loader.js +56 -32
  223. package/dist/lab/composition-rules.js +58 -58
  224. package/dist/lab/config.js +85 -43
  225. package/dist/lab/deprecated-fields.d.ts +10 -0
  226. package/dist/lab/deprecated-fields.js +24 -0
  227. package/dist/lab/device-presets.d.ts +10 -10
  228. package/dist/lab/device-presets.js +11 -11
  229. package/dist/lab/discover.d.ts +13 -9
  230. package/dist/lab/discover.js +118 -60
  231. package/dist/lab/doctor.d.ts +53 -11
  232. package/dist/lab/doctor.js +193 -47
  233. package/dist/lab/init-plan.js +1 -3
  234. package/dist/lab/init-templates.js +147 -147
  235. package/dist/lab/init.d.ts +1 -1
  236. package/dist/lab/init.js +41 -9
  237. package/dist/lab/keys.d.ts +2 -0
  238. package/dist/lab/keys.js +43 -9
  239. package/dist/lab/lab-deps.d.ts +80 -0
  240. package/dist/lab/lab-deps.js +4 -0
  241. package/dist/lab/parse/actors.js +17 -16
  242. package/dist/lab/parse/comms.js +8 -7
  243. package/dist/lab/parse/execution.js +15 -14
  244. package/dist/lab/parse/study-v3.d.ts +23 -0
  245. package/dist/lab/parse/study-v3.js +259 -0
  246. package/dist/lab/parse/subject-state.d.ts +7 -7
  247. package/dist/lab/parse/subject-state.js +18 -17
  248. package/dist/lab/parse/subject.js +30 -29
  249. package/dist/lab/parse/values.d.ts +1 -2
  250. package/dist/lab/parse/values.js +3 -6
  251. package/dist/lab/persona-resolve.d.ts +7 -7
  252. package/dist/lab/persona-resolve.js +8 -8
  253. package/dist/lab/persona.js +1 -3
  254. package/dist/lab/plan-base.d.ts +0 -2
  255. package/dist/lab/plan-base.js +6 -4
  256. package/dist/lab/plan-participants.d.ts +7 -7
  257. package/dist/lab/plan-participants.js +2 -2
  258. package/dist/lab/plan-types.d.ts +26 -8
  259. package/dist/lab/plan.d.ts +4 -18
  260. package/dist/lab/plan.js +24 -79
  261. package/dist/lab/preflight-probes.js +11 -11
  262. package/dist/lab/preflight-result.d.ts +2 -1
  263. package/dist/lab/preflight-result.js +5 -6
  264. package/dist/lab/preflight.d.ts +7 -8
  265. package/dist/lab/preflight.js +6 -6
  266. package/dist/lab/requirements.d.ts +20 -0
  267. package/dist/lab/requirements.js +54 -0
  268. package/dist/lab/route-inputs.d.ts +23 -12
  269. package/dist/lab/route-inputs.js +48 -51
  270. package/dist/lab/routing.d.ts +42 -41
  271. package/dist/lab/routing.js +66 -68
  272. package/dist/lab/run-lab-events.d.ts +3 -11
  273. package/dist/lab/run-lab-events.js +2 -16
  274. package/dist/lab/run-lab-homes.d.ts +76 -0
  275. package/dist/lab/run-lab-homes.js +7 -0
  276. package/dist/lab/run-lab-options.d.ts +12 -66
  277. package/dist/lab/run-lab-options.js +58 -285
  278. package/dist/lab/summary.d.ts +15 -9
  279. package/dist/lab/summary.js +24 -17
  280. package/dist/lab/tasks.d.ts +15 -15
  281. package/dist/lab/tasks.js +14 -14
  282. package/dist/lab/types.d.ts +201 -195
  283. package/dist/lab/types.js +2 -0
  284. package/dist/lab/validation.d.ts +21 -21
  285. package/dist/lab/validation.js +61 -59
  286. package/dist/lab/warnings.d.ts +10 -0
  287. package/dist/lab/warnings.js +70 -41
  288. package/dist/library-aliases.d.ts +56 -0
  289. package/dist/library-aliases.js +22 -0
  290. package/dist/observer/artifact.d.ts +2 -2
  291. package/dist/observer/artifact.js +9 -9
  292. package/dist/observer/data.d.ts +6 -6
  293. package/dist/observer/data.js +7 -6
  294. package/dist/observer/exposure.d.ts +1 -1
  295. package/dist/observer/exposure.js +11 -11
  296. package/dist/observer/http.js +1 -1
  297. package/dist/observer/library.d.ts +1 -1
  298. package/dist/observer/library.js +4 -2
  299. package/dist/observer/listen.js +5 -4
  300. package/dist/observer/render.d.ts +1 -1
  301. package/dist/observer/render.js +12 -7
  302. package/dist/observer/run-routes.d.ts +4 -4
  303. package/dist/observer/run-routes.js +6 -6
  304. package/dist/observer/serve.d.ts +17 -0
  305. package/dist/observer/serve.js +41 -6
  306. package/dist/observer/tunnel.js +1 -1
  307. package/dist/observer-app.html +4 -4
  308. package/dist/routes/computer-use/bundle-parts.d.ts +9 -9
  309. package/dist/routes/computer-use/bundle-parts.js +24 -17
  310. package/dist/routes/computer-use/bundle.d.ts +4 -11
  311. package/dist/routes/computer-use/bundle.js +12 -18
  312. package/dist/routes/computer-use/diagnostics.d.ts +1 -1
  313. package/dist/routes/computer-use/diagnostics.js +1 -1
  314. package/dist/routes/computer-use/e2b-desktop/comms.d.ts +11 -11
  315. package/dist/routes/computer-use/e2b-desktop/comms.js +24 -27
  316. package/dist/routes/computer-use/e2b-desktop/desktop.d.ts +2 -2
  317. package/dist/routes/computer-use/e2b-desktop/desktop.js +8 -11
  318. package/dist/routes/computer-use/e2b-desktop/fidelity.d.ts +16 -15
  319. package/dist/routes/computer-use/e2b-desktop/fidelity.js +20 -19
  320. package/dist/routes/computer-use/e2b-desktop/prepare.d.ts +3 -3
  321. package/dist/routes/computer-use/e2b-desktop/prepare.js +40 -43
  322. package/dist/routes/computer-use/e2b-desktop/start.d.ts +1 -1
  323. package/dist/routes/computer-use/e2b-desktop/start.js +32 -30
  324. package/dist/routes/computer-use/e2b-desktop/state.d.ts +5 -4
  325. package/dist/routes/computer-use/e2b-desktop/state.js +5 -3
  326. package/dist/routes/computer-use/e2b-desktop/teardown.d.ts +1 -1
  327. package/dist/routes/computer-use/e2b-desktop/teardown.js +33 -20
  328. package/dist/routes/computer-use/external-comms.d.ts +4 -4
  329. package/dist/routes/computer-use/external-comms.js +19 -43
  330. package/dist/routes/computer-use/fanout-bundle.d.ts +3 -3
  331. package/dist/routes/computer-use/fanout-bundle.js +38 -42
  332. package/dist/routes/computer-use/{fanout-lanes.js → fanout-records.js} +33 -28
  333. package/dist/routes/computer-use/in-process-desktop.d.ts +3 -10
  334. package/dist/routes/computer-use/in-process-desktop.js +3 -9
  335. package/dist/routes/computer-use/live-flush.d.ts +7 -5
  336. package/dist/routes/computer-use/live-flush.js +20 -28
  337. package/dist/routes/computer-use/{run-lanes.d.ts → live-phase.d.ts} +4 -2
  338. package/dist/routes/computer-use/{run-lanes.js → live-phase.js} +17 -16
  339. package/dist/routes/computer-use/local-tree-pack.d.ts +3 -3
  340. package/dist/routes/computer-use/local-tree-pack.js +4 -5
  341. package/dist/routes/computer-use/local-vm.d.ts +11 -8
  342. package/dist/routes/computer-use/local-vm.js +40 -67
  343. package/dist/routes/computer-use/participant-desktop.d.ts +8 -23
  344. package/dist/routes/computer-use/participant-desktop.js +5 -25
  345. package/dist/routes/computer-use/{lanes.d.ts → participant-execution.d.ts} +11 -11
  346. package/dist/routes/computer-use/{lanes.js → participant-execution.js} +39 -26
  347. package/dist/routes/computer-use/participant-facts.d.ts +7 -1
  348. package/dist/routes/computer-use/participant-facts.js +12 -1
  349. package/dist/routes/computer-use/participant-model.d.ts +25 -11
  350. package/dist/routes/computer-use/participant-model.js +76 -34
  351. package/dist/routes/computer-use/participant-prompt.d.ts +13 -13
  352. package/dist/routes/computer-use/participant-prompt.js +8 -8
  353. package/dist/routes/computer-use/participant-runs.d.ts +11 -11
  354. package/dist/routes/computer-use/participant-runs.js +18 -18
  355. package/dist/routes/computer-use/plan.d.ts +21 -29
  356. package/dist/routes/computer-use/plan.js +70 -78
  357. package/dist/routes/computer-use/preflight.d.ts +3 -5
  358. package/dist/routes/computer-use/preflight.js +40 -36
  359. package/dist/routes/computer-use/rerun-selection.js +11 -7
  360. package/dist/routes/computer-use/result.d.ts +1 -1
  361. package/dist/routes/computer-use/result.js +48 -38
  362. package/dist/routes/computer-use/route.d.ts +5 -5
  363. package/dist/routes/computer-use/route.js +36 -33
  364. package/dist/routes/computer-use/self-report.d.ts +8 -8
  365. package/dist/routes/computer-use/self-report.js +33 -33
  366. package/dist/routes/computer-use/setup.d.ts +9 -15
  367. package/dist/routes/computer-use/setup.js +106 -83
  368. package/dist/routes/computer-use/single-bundle.d.ts +13 -16
  369. package/dist/routes/computer-use/single-bundle.js +46 -53
  370. package/dist/routes/computer-use/subject-projection.d.ts +6 -8
  371. package/dist/routes/computer-use/subject-projection.js +24 -23
  372. package/dist/routes/computer-use/types.d.ts +195 -238
  373. package/dist/routes/computer-use/types.js +21 -13
  374. package/dist/routes/preview.d.ts +8 -2
  375. package/dist/routes/preview.js +8 -5
  376. package/dist/routes/scripted/bundle.d.ts +5 -8
  377. package/dist/routes/scripted/bundle.js +23 -27
  378. package/dist/routes/scripted/plan.d.ts +6 -8
  379. package/dist/routes/scripted/plan.js +15 -13
  380. package/dist/routes/scripted/result.d.ts +4 -1
  381. package/dist/routes/scripted/result.js +15 -11
  382. package/dist/routes/scripted/route.js +15 -17
  383. package/dist/routes/scripted/scenario.d.ts +1 -1
  384. package/dist/routes/scripted/scenario.js +3 -3
  385. package/dist/routes/scripted/setup.d.ts +3 -2
  386. package/dist/routes/scripted/setup.js +27 -26
  387. package/dist/routes/scripted/subject.d.ts +8 -3
  388. package/dist/routes/scripted/subject.js +10 -6
  389. package/dist/routes/scripted/surface-records.js +4 -4
  390. package/dist/routes/scripted/surface-sessions.d.ts +2 -2
  391. package/dist/routes/scripted/surface-sessions.js +4 -4
  392. package/dist/routes/scripted/types.d.ts +21 -40
  393. package/dist/routes/scripted/types.js +2 -3
  394. package/dist/routes/shared-world/{seat-records.js → bundle-records.js} +17 -16
  395. package/dist/routes/shared-world/bundle.d.ts +7 -7
  396. package/dist/routes/shared-world/bundle.js +60 -62
  397. package/dist/routes/shared-world/checkpoints.d.ts +5 -5
  398. package/dist/routes/shared-world/checkpoints.js +5 -5
  399. package/dist/routes/shared-world/comms.d.ts +8 -7
  400. package/dist/routes/shared-world/comms.js +38 -51
  401. package/dist/routes/shared-world/external-public.d.ts +6 -5
  402. package/dist/routes/shared-world/external-public.js +28 -25
  403. package/dist/routes/shared-world/handoff.d.ts +10 -9
  404. package/dist/routes/shared-world/handoff.js +89 -81
  405. package/dist/routes/shared-world/lobby-code.d.ts +7 -7
  406. package/dist/routes/shared-world/lobby-code.js +22 -22
  407. package/dist/routes/shared-world/{seats.d.ts → participant-specs.d.ts} +15 -12
  408. package/dist/routes/shared-world/{seats.js → participant-specs.js} +65 -63
  409. package/dist/routes/shared-world/plan.d.ts +2 -6
  410. package/dist/routes/shared-world/plan.js +8 -9
  411. package/dist/routes/shared-world/provenance.d.ts +4 -4
  412. package/dist/routes/shared-world/provenance.js +4 -4
  413. package/dist/routes/shared-world/provisioned.d.ts +3 -2
  414. package/dist/routes/shared-world/provisioned.js +55 -48
  415. package/dist/routes/shared-world/result.js +47 -36
  416. package/dist/routes/shared-world/route.js +54 -57
  417. package/dist/routes/shared-world/setup.d.ts +6 -5
  418. package/dist/routes/shared-world/setup.js +16 -18
  419. package/dist/routes/shared-world/types.d.ts +70 -141
  420. package/dist/routes/shared-world/types.js +5 -5
  421. package/dist/routes/terminal/adapter.d.ts +10 -10
  422. package/dist/routes/terminal/adapter.js +32 -129
  423. package/dist/routes/terminal/bundle.d.ts +10 -15
  424. package/dist/routes/terminal/bundle.js +43 -52
  425. package/dist/routes/terminal/credentials.d.ts +4 -4
  426. package/dist/routes/terminal/credentials.js +20 -20
  427. package/dist/routes/terminal/dry-run.d.ts +1 -1
  428. package/dist/routes/terminal/dry-run.js +13 -15
  429. package/dist/routes/terminal/encoding.d.ts +1 -1
  430. package/dist/routes/terminal/encoding.js +4 -4
  431. package/dist/routes/terminal/ledger.d.ts +8 -8
  432. package/dist/routes/terminal/ledger.js +22 -22
  433. package/dist/routes/terminal/live-finish.d.ts +1 -2
  434. package/dist/routes/terminal/live-finish.js +24 -23
  435. package/dist/routes/terminal/live-sandbox.d.ts +3 -2
  436. package/dist/routes/terminal/live-sandbox.js +31 -32
  437. package/dist/routes/terminal/participant-text.d.ts +23 -0
  438. package/dist/routes/terminal/participant-text.js +165 -0
  439. package/dist/routes/terminal/persona.js +1 -1
  440. package/dist/routes/terminal/plan.d.ts +2 -6
  441. package/dist/routes/terminal/plan.js +23 -19
  442. package/dist/routes/terminal/recorder.d.ts +6 -1
  443. package/dist/routes/terminal/recorder.js +12 -4
  444. package/dist/routes/terminal/result.js +12 -12
  445. package/dist/routes/terminal/route.js +30 -31
  446. package/dist/routes/terminal/runtime.d.ts +3 -2
  447. package/dist/routes/terminal/runtime.js +3 -3
  448. package/dist/routes/terminal/sandbox.d.ts +4 -4
  449. package/dist/routes/terminal/sandbox.js +10 -10
  450. package/dist/routes/terminal/session.js +22 -19
  451. package/dist/routes/terminal/token-usage.d.ts +1 -1
  452. package/dist/routes/terminal/token-usage.js +10 -11
  453. package/dist/routes/terminal/trace.d.ts +7 -10
  454. package/dist/routes/terminal/trace.js +11 -66
  455. package/dist/routes/terminal/types.d.ts +104 -114
  456. package/dist/routes/terminal/types.js +12 -7
  457. package/dist/run/active-runs.d.ts +13 -0
  458. package/dist/run/active-runs.js +12 -0
  459. package/dist/run/bundle-shape.d.ts +2 -1
  460. package/dist/run/bundle-shape.js +7 -7
  461. package/dist/run/bundle.d.ts +99 -92
  462. package/dist/run/bundle.js +10 -8
  463. package/dist/run/cost-summary.js +6 -5
  464. package/dist/run/costs.d.ts +6 -6
  465. package/dist/run/costs.js +17 -11
  466. package/dist/run/detail.d.ts +9 -9
  467. package/dist/run/detail.js +10 -10
  468. package/dist/run/dry-run-inputs.js +1 -1
  469. package/dist/run/dry-run.js +23 -30
  470. package/dist/run/{study-files.d.ts → evidence-files.d.ts} +4 -4
  471. package/dist/run/{study-files.js → evidence-files.js} +5 -5
  472. package/dist/run/feedback-shape.js +1 -1
  473. package/dist/run/judge.d.ts +34 -16
  474. package/dist/run/judge.js +41 -14
  475. package/dist/run/locate.d.ts +2 -0
  476. package/dist/run/locate.js +3 -1
  477. package/dist/run/outcomes.d.ts +3 -3
  478. package/dist/run/outcomes.js +3 -3
  479. package/dist/run/participant-records.d.ts +2 -2
  480. package/dist/run/participant-records.js +2 -2
  481. package/dist/run/paths.d.ts +1 -1
  482. package/dist/run/paths.js +2 -2
  483. package/dist/run/pricing.d.ts +30 -15
  484. package/dist/run/pricing.js +49 -30
  485. package/dist/run/projection.d.ts +27 -27
  486. package/dist/run/projection.js +23 -23
  487. package/dist/run/reclaim.d.ts +6 -0
  488. package/dist/run/reclaim.js +15 -5
  489. package/dist/run/results.d.ts +5 -5
  490. package/dist/run/run-index.d.ts +9 -7
  491. package/dist/run/run-index.js +24 -25
  492. package/dist/run/run-not-found.d.ts +5 -0
  493. package/dist/run/run-not-found.js +15 -0
  494. package/dist/run/run.d.ts +7 -4
  495. package/dist/run/run.js +10 -6
  496. package/dist/run/sandbox-receipts.d.ts +5 -5
  497. package/dist/run/sandbox-receipts.js +6 -6
  498. package/dist/run/shared-world-evidence.d.ts +67 -66
  499. package/dist/run/shared-world-evidence.js +4 -4
  500. package/dist/run/shared-world-shape.d.ts +3 -3
  501. package/dist/run/shared-world-shape.js +16 -16
  502. package/dist/run/stats.d.ts +17 -11
  503. package/dist/run/stats.js +124 -66
  504. package/dist/run/status.d.ts +21 -32
  505. package/dist/run/status.js +34 -33
  506. package/dist/run/stored-runs.js +2 -1
  507. package/dist/run/stream-shape.js +1 -1
  508. package/dist/run/streams.d.ts +29 -22
  509. package/dist/run/study-provenance.d.ts +47 -0
  510. package/dist/run/study-provenance.js +63 -0
  511. package/dist/run/study-result.d.ts +16 -0
  512. package/dist/run/study-result.js +9 -0
  513. package/dist/run/terminal-contract.d.ts +5 -5
  514. package/dist/run/terminal-contract.js +4 -4
  515. package/dist/run/text.d.ts +2 -0
  516. package/dist/run/text.js +4 -0
  517. package/dist/run/transient-comms-secrets.d.ts +5 -0
  518. package/dist/run/transient-comms-secrets.js +12 -0
  519. package/dist/run-lab.d.ts +40 -38
  520. package/dist/run-lab.js +42 -40
  521. package/dist/study/convert.d.ts +33 -0
  522. package/dist/study/convert.js +432 -0
  523. package/dist/study/field-paths.d.ts +12 -0
  524. package/dist/study/field-paths.js +126 -0
  525. package/dist/study/files.d.ts +26 -0
  526. package/dist/study/files.js +43 -0
  527. package/dist/study/migrate.d.ts +48 -0
  528. package/dist/study/migrate.js +408 -0
  529. package/dist/study/owned-files.d.ts +38 -0
  530. package/dist/study/owned-files.js +182 -0
  531. package/dist/subject/clone.d.ts +1 -1
  532. package/dist/subject/desktop-cli.d.ts +2 -2
  533. package/dist/subject/desktop-cli.js +3 -3
  534. package/dist/subject/local-tree-archive.d.ts +1 -1
  535. package/dist/subject/local-tree-archive.js +5 -5
  536. package/dist/subject/local-tree.d.ts +3 -3
  537. package/dist/subject/local-tree.js +1 -1
  538. package/dist/subject/node-bootstrap.d.ts +1 -1
  539. package/dist/subject/node-bootstrap.js +4 -4
  540. package/dist/subject/runtime.js +10 -11
  541. package/dist/subject/serve.d.ts +1 -1
  542. package/dist/subject/serve.js +4 -4
  543. package/dist/subject/state.d.ts +1 -1
  544. package/dist/subject/steps.d.ts +8 -8
  545. package/dist/subject/steps.js +7 -7
  546. package/dist/substrates/command-failure.d.ts +3 -3
  547. package/dist/substrates/command-failure.js +3 -3
  548. package/dist/substrates/detached.d.ts +6 -6
  549. package/dist/substrates/detached.js +7 -7
  550. package/dist/substrates/e2b/cdp-probe.d.ts +11 -11
  551. package/dist/substrates/e2b/cdp-probe.js +15 -18
  552. package/dist/substrates/e2b/desktop-browser.d.ts +5 -5
  553. package/dist/substrates/e2b/desktop-browser.js +12 -12
  554. package/dist/substrates/e2b/desktop-cdp.d.ts +15 -15
  555. package/dist/substrates/e2b/desktop-cdp.js +11 -11
  556. package/dist/substrates/e2b/desktop-executor.d.ts +1 -1
  557. package/dist/substrates/e2b/desktop-executor.js +1 -1
  558. package/dist/substrates/e2b/desktop-geometry.d.ts +6 -6
  559. package/dist/substrates/e2b/desktop-geometry.js +9 -9
  560. package/dist/substrates/e2b/desktop-media.d.ts +1 -1
  561. package/dist/substrates/e2b/desktop-media.js +3 -3
  562. package/dist/substrates/e2b/desktop-screenshot-cleanup.d.ts +3 -3
  563. package/dist/substrates/e2b/desktop-screenshot-cleanup.js +3 -3
  564. package/dist/substrates/e2b/sandbox.d.ts +1 -1
  565. package/dist/substrates/e2b/sandbox.js +2 -2
  566. package/dist/substrates/e2b/sdk.d.ts +11 -11
  567. package/dist/substrates/e2b/sdk.js +8 -8
  568. package/dist/substrates/local/runtime-host.d.ts +2 -0
  569. package/dist/substrates/local/runtime-host.js +6 -0
  570. package/dist/tui/actions.d.ts +8 -6
  571. package/dist/tui/actions.js +31 -22
  572. package/dist/tui/contract.d.ts +16 -16
  573. package/dist/tui/contract.js +10 -10
  574. package/dist/tui/launch.d.ts +4 -4
  575. package/dist/tui/launch.js +18 -19
  576. package/dist/tui/project.js +5 -5
  577. package/dist/tui-app.js +83 -83
  578. package/dist/verify/actor.d.ts +14 -14
  579. package/dist/verify/actor.js +45 -45
  580. package/dist/verify/artifacts.d.ts +3 -3
  581. package/dist/verify/artifacts.js +6 -6
  582. package/dist/verify/context-growth.d.ts +9 -0
  583. package/dist/verify/context-growth.js +62 -0
  584. package/dist/verify/costs.d.ts +7 -7
  585. package/dist/verify/costs.js +9 -9
  586. package/dist/verify/liveness.d.ts +1 -1
  587. package/dist/verify/liveness.js +4 -1
  588. package/dist/verify/rerun.d.ts +1 -1
  589. package/dist/verify/rerun.js +1 -1
  590. package/dist/verify/shared-world-concurrent.d.ts +2 -2
  591. package/dist/verify/shared-world-concurrent.js +79 -76
  592. package/dist/verify/shared-world.d.ts +2 -2
  593. package/dist/verify/shared-world.js +18 -18
  594. package/dist/verify/subject.d.ts +4 -4
  595. package/dist/verify/subject.js +18 -18
  596. package/dist/verify/verify.js +98 -49
  597. package/docs/README.md +26 -33
  598. package/docs/architecture/actor-contract.md +105 -98
  599. package/docs/architecture/desktop-sessions.md +14 -14
  600. package/docs/architecture/external-public-shared-world.md +66 -59
  601. package/docs/architecture/github-feedback-loop.md +1 -4
  602. package/docs/architecture/guest-desktop.md +2 -2
  603. package/docs/architecture/observer.md +37 -37
  604. package/docs/architecture/restricted-codex-analysis.md +70 -30
  605. package/docs/architecture/serve.md +34 -37
  606. package/docs/architecture/state-driven-executor.md +55 -59
  607. package/docs/architecture/task-protocol-support.md +7 -9
  608. package/docs/architecture/{terminal-product-lane.md → terminal-product-route.md} +83 -115
  609. package/docs/contracts/README.md +24 -0
  610. package/docs/contracts/adapter-admission.md +3 -3
  611. package/docs/contracts/adapter-fixtures.md +2 -5
  612. package/docs/contracts/core.md +1 -3
  613. package/docs/contracts/errors.md +62 -0
  614. package/docs/contracts/feedback.md +8 -9
  615. package/docs/contracts/policy.md +7 -12
  616. package/docs/contracts/run-bundle.md +54 -51
  617. package/docs/contracts/schemas.md +505 -390
  618. package/docs/contracts/study-analysis.md +26 -2
  619. package/docs/contracts/study-costs.md +11 -7
  620. package/docs/decisions/0001-run-bundle-is-the-source-of-truth.md +1 -1
  621. package/docs/decisions/0002-observer-is-one-self-contained-file.md +2 -2
  622. package/docs/decisions/0003-contained-paths-and-cleanup-authority.md +3 -3
  623. package/docs/decisions/0004-participant-desktops-stay-in-the-route.md +2 -1
  624. package/docs/principles/actor-fidelity.md +4 -4
  625. package/docs/principles/engineering.md +3 -3
  626. package/docs/principles/invariants-and-defaults.md +38 -38
  627. package/docs/principles/self-driving-harness.md +1 -5
  628. package/docs/principles/three-roles.md +1 -1
  629. package/docs/product/automatic-analysis.md +8 -7
  630. package/examples/participant/README.md +5 -5
  631. package/examples/participant/run.mjs +11 -10
  632. package/examples/scorer/README.md +3 -3
  633. package/examples/scorer/run.mjs +11 -12
  634. package/package.json +16 -17
  635. package/skills/humanish/SKILL.md +63 -60
  636. package/skills/humanish/agents/openai.yaml +1 -1
  637. package/AGENTS.md +0 -99
  638. package/CONTRIBUTING.md +0 -148
  639. package/dist/actors/codex/qualified-versions.d.ts +0 -45
  640. package/dist/actors/codex/qualified-versions.js +0 -87
  641. package/dist/cli/commands/lab.d.ts +0 -3
  642. package/dist/cli/commands/lab.js +0 -193
  643. package/dist/deprecated.d.ts +0 -90
  644. package/dist/deprecated.js +0 -106
  645. package/dist/lab/bag-overrides.d.ts +0 -18
  646. package/dist/lab/bag-overrides.js +0 -121
  647. package/dist/observer/static.d.ts +0 -39
  648. package/dist/observer/static.js +0 -369
  649. package/dist/routes/computer-use/legacy-lane-spec.d.ts +0 -62
  650. package/dist/routes/computer-use/legacy-lane-spec.js +0 -39
  651. package/docs/architecture/comms-inbox.md +0 -122
  652. package/docs/architecture/desktop-recording.md +0 -80
  653. package/docs/architecture/local-browser-runtime.md +0 -178
  654. package/docs/architecture/observer-review.md +0 -144
  655. package/docs/architecture/participant-media.md +0 -90
  656. package/docs/architecture/project-layout.md +0 -62
  657. package/docs/architecture/real-email-receiving.md +0 -136
  658. package/docs/assets/humanish-drawdb-hero.png +0 -0
  659. package/docs/assets/humanish-observer-hero.png +0 -0
  660. package/docs/goals/current.md +0 -207
  661. package/docs/product/lobby-trivia-3player-external-public.md +0 -77
  662. package/docs/product/open-source-install-experience.md +0 -240
  663. package/docs/ramp/README.md +0 -294
  664. package/docs/release/open-source-readiness.md +0 -222
  665. package/docs/release/public-readiness-standard.md +0 -210
  666. package/docs/roadmap/world-class-open-source-v0.md +0 -311
  667. /package/dist/routes/computer-use/{fanout-lanes.d.ts → fanout-records.d.ts} +0 -0
  668. /package/dist/routes/shared-world/{seat-records.d.ts → bundle-records.d.ts} +0 -0
@@ -1,19 +1,21 @@
1
1
  import { resolve } from "node:path";
2
2
  import { Command } from "commander";
3
3
  import { COMMS_PROVIDERS, saveCommsConnection } from "../../comms/connections.js";
4
+ import { catchTokenRefusal } from "../../comms/external-evidence.js";
4
5
  import { readCommsSetup } from "../../comms/setup.js";
5
6
  import { checkCommsConnection, configureCommsLab } from "../../comms/setup.js";
6
7
  import { inspectCommsRecovery, recoverCommsReceiving } from "../../comms/receiving-recovery.js";
7
8
  import { resolveReceivingConnection } from "../../comms/receiving-runtime.js";
8
9
  import { resolveLabManifest } from "../../lab/discover.js";
10
+ import { oldStudyOption, studyOptionValue } from "../deprecations.js";
9
11
  import { runCommsCatchHost } from "../../comms/catch-host.js";
10
12
  import { DEFAULT_SANDBOX_CATCH_PORT } from "../../comms/sandbox-catch.js";
11
- import { applyEnvFileOption, JSON_OPTION_DESCRIPTION, writeResult } from "../io.js";
13
+ import { applyEnvFileOption, CWD_OPTION_DESCRIPTION, ENV_FILE_OPTION_DESCRIPTION, JSON_OPTION_DESCRIPTION, PORT_OPTION_DESCRIPTION, writeResult, messageOutput, } from "../io.js";
12
14
  export function registerCommsCommands(parent, io) {
13
15
  const comms = parent
14
16
  .command("comms")
15
17
  .description("Local email capture, real receiving connections, checks and cleanup recovery.")
16
- .summary("Off-app comms surfaces.");
18
+ .summary("Catch the email an app sends, for email-gated flows.");
17
19
  comms
18
20
  .command("providers")
19
21
  .description("List installed communication provider capabilities. No network requests.")
@@ -21,61 +23,70 @@ export function registerCommsCommands(parent, io) {
21
23
  .action((_options, command) => handleCommsProviders(io, _options, command));
22
24
  const connections = comms
23
25
  .command("connections")
24
- .description("Manage project-local non-secret connection profiles. A lab explicitly selects its receiving connection.");
26
+ .description("Manage project-local non-secret connection profiles. A study explicitly selects its receiving connection.");
25
27
  connections
26
28
  .command("list")
27
29
  .description("Show saved connections and local credential status; does not authenticate with a provider.")
28
- .option("--cwd <path>", "Target project directory.", ".")
29
- .option("--env-file <path>", "Load credentials for local status without printing values.")
30
+ .option("--cwd <path>", CWD_OPTION_DESCRIPTION, ".")
31
+ .option("--env-file <path>", ENV_FILE_OPTION_DESCRIPTION)
30
32
  .option("--json", JSON_OPTION_DESCRIPTION)
31
33
  .action((options, command) => handleCommsList(io, options, command));
32
34
  connections
33
35
  .command("add")
34
36
  .argument("[name]", "Project connection name.", "agentmail")
35
- .description("Save an AgentMail connection profile. Does not write a key, alter a lab or contact the provider.")
36
- .option("--cwd <path>", "Target project directory.", ".")
37
+ .description("Save an AgentMail connection profile. Does not write a key, alter a study or contact the provider.")
38
+ .option("--cwd <path>", CWD_OPTION_DESCRIPTION, ".")
37
39
  .option("--provider <id>", "Installed provider id.", "agentmail")
38
- .option("--api-key-env <name>", "Environment variable NAME, never its value.", "AGENTMAIL_API_KEY")
40
+ .option("--api-key-env <name>", "The name of an environment variable, never its value.", "AGENTMAIL_API_KEY")
39
41
  .option("--json", JSON_OPTION_DESCRIPTION)
40
42
  .action((name, options, command) => handleCommsAdd(io, name, options, command));
41
43
  comms
42
44
  .command("check")
43
45
  .description("Check connection and credential presence; --online authenticates without creating inboxes.")
44
- .option("--cwd <path>", "Target project directory.", ".")
46
+ .option("--cwd <path>", CWD_OPTION_DESCRIPTION, ".")
45
47
  .option("--connection <name>", "Saved connection name.", "agentmail")
46
- .option("--lab <path>", "Check the connection selected by this exact lab.")
48
+ .option("--study <path>", "Check the connection this study selects.")
49
+ .addOption(oldStudyOption("path"))
47
50
  .option("--online", "Make a read-only provider authentication request.")
48
- .option("--env-file <path>", "Load credentials without printing values.")
51
+ .option("--env-file <path>", ENV_FILE_OPTION_DESCRIPTION)
49
52
  .option("--json", JSON_OPTION_DESCRIPTION)
50
53
  .action((options, command) => handleCommsCheck(io, options, command));
51
54
  comms
52
55
  .command("configure")
53
- .description("Preview or save a local receiving-enabled copy of a supported lab. No provider requests.")
54
- .requiredOption("--lab <path>", "Exact source lab path or handle.")
55
- .option("--cwd <path>", "Target project directory.", ".")
56
+ .description("Preview or save a local receiving-enabled copy of a supported study. No provider requests.")
57
+ // Required, but checked in the action, so --lab still works for one minor.
58
+ .option("--study <path>", "Source study path or name. Required.")
59
+ .addOption(oldStudyOption("path"))
60
+ .option("--cwd <path>", CWD_OPTION_DESCRIPTION, ".")
56
61
  .option("--connection <name>", "Saved connection name.", "agentmail")
57
- .option("--apply", "Save the local copy; original lab remains unchanged.")
62
+ .option("--apply", "Save the local copy; the source study stays unchanged.")
58
63
  .option("--plan-token <digest>", "Require the source and destination to match a previous preview.")
59
64
  .option("--json", JSON_OPTION_DESCRIPTION)
65
+ .hook("preAction", (command) => {
66
+ const options = command.opts();
67
+ // The message commander gives a missing required option.
68
+ if (options.study === undefined && options.lab === undefined)
69
+ command.error("error: required option '--study <path>' not specified");
70
+ })
60
71
  .action((options, command) => handleCommsConfigure(io, options, command));
61
72
  comms
62
73
  .command("recover")
63
74
  .description("Inspect interrupted email leases; --apply deletes only privately recorded resources owned by this project and account.")
64
- .option("--cwd <path>", "Target project directory.", ".")
75
+ .option("--cwd <path>", CWD_OPTION_DESCRIPTION, ".")
65
76
  .option("--run <id>", "One run to inspect or recover.")
66
77
  .option("--apply", "Recover the selected inactive run and verify mailbox deletion.")
67
- .option("--env-file <path>", "Load credentials without printing values.")
78
+ .option("--env-file <path>", ENV_FILE_OPTION_DESCRIPTION)
68
79
  .option("--json", JSON_OPTION_DESCRIPTION)
69
80
  .action((options, command) => handleCommsRecover(io, options, command));
70
81
  comms
71
82
  .command("catch")
72
- .description("Run the email catch on this host so humanish can study an app it does not provision. Your app posts its email sends here; the persona opens /inbox; humanish drains GET /deliveries and writes digest-only evidence. Point your lab's comms.email.external.catchBaseUrl at this server.")
73
- .summary("Run the adopter-hosted email catch.")
74
- .option("--port <port>", "Port for capture + inbox (default 8025).", String(DEFAULT_SANDBOX_CATCH_PORT))
83
+ .description("Run the email catch on this host so humanish can study an app it does not provision. Your app posts its email sends here; the persona opens /inbox; humanish drains GET /deliveries and writes digest-only evidence. Point your study's comms.email.external.catchBaseUrl at this server.")
84
+ .summary("Run the email catch on this host.")
85
+ .option("--port <port>", PORT_OPTION_DESCRIPTION, String(DEFAULT_SANDBOX_CATCH_PORT))
75
86
  .option("--dir <path>", "Directory for the deliveries log and rendered inbox.", ".humanish/comms-catch")
76
- .option("--token <value>", "Require this bearer token on GET /deliveries (recommended when reachable off-host).")
87
+ .option("--token <value>", "Require this bearer token, at least 16 characters, on GET /deliveries (recommended when reachable off-host).")
77
88
  .option("--smtp-port <port>", "Also capture SMTP mail on 127.0.0.1:<port>. Point your app's SMTP transport here.")
78
- .option("--inbox-port <port>", "Also serve a READ-ONLY inbox listener on 0.0.0.0:<port>, so a persona on another machine can open /inbox. Without it the catch stays loopback-only.")
89
+ .option("--inbox-port <port>", "Also serve a read-only inbox listener on 0.0.0.0:<port>, so a persona on another machine can open /inbox. Without it the catch stays loopback-only.")
79
90
  .option("--recipient <address>", "Only render mail sent to this address (repeatable). Default: render whatever the app actually mailed.", (value, previous) => [...(previous ?? []), value])
80
91
  .action((options) => handleCommsCatch(io, options));
81
92
  }
@@ -101,25 +112,26 @@ async function handleCommsAdd(io, name, options, command) {
101
112
  ? await saveCommsConnection(resolve(options.cwd), name, options.apiKeyEnv)
102
113
  : { ok: false, message: "Only AgentMail connection setup is currently available." }),
103
114
  };
104
- writeResult(command, io, result, (value) => `${value.message}\n`);
115
+ writeResult(command, io, result, messageOutput);
105
116
  io.setExitCode(result.ok ? 0 : 2);
106
117
  }
107
118
  async function handleCommsCheck(io, options, command) {
108
119
  if (!(await applyEnvFileOption({ command, cwd: options.cwd, envFile: options.envFile, io })))
109
120
  return;
110
121
  let connection = options.connection;
111
- if (options.lab) {
112
- const lab = await resolveLabManifest(options.cwd, options.lab);
113
- if (!lab.ok || lab.config.comms?.email?.kind !== "real") {
122
+ const study = studyOptionValue(command, io, options);
123
+ if (study) {
124
+ const resolved = await resolveLabManifest(options.cwd, study);
125
+ if (!resolved.ok || resolved.config.comms?.email?.kind !== "real") {
114
126
  const result = {
115
127
  ok: false,
116
- message: "This lab does not select a real email connection.",
128
+ message: "This study does not select a real email connection.",
117
129
  };
118
- writeResult(command, io, result, (value) => `${value.message}\n`);
130
+ writeResult(command, io, result, messageOutput);
119
131
  io.setExitCode(2);
120
132
  return;
121
133
  }
122
- connection = lab.config.comms.email.connection;
134
+ connection = resolved.config.comms.email.connection;
123
135
  }
124
136
  const result = await checkCommsConnection({
125
137
  cwd: resolve(options.cwd),
@@ -127,12 +139,22 @@ async function handleCommsCheck(io, options, command) {
127
139
  env: process.env,
128
140
  online: options.online === true,
129
141
  });
130
- writeResult(command, io, result, (value) => `${value.message}\n`);
142
+ writeResult(command, io, result, messageOutput);
131
143
  io.setExitCode(result.ok ? 0 : 2);
132
144
  }
133
145
  async function handleCommsConfigure(io, options, command) {
134
- const result = await configureCommsLab({ ...options, cwd: resolve(options.cwd) });
135
- writeResult(command, io, result, (value) => `${value.message}\n`);
146
+ const study = studyOptionValue(command, io, options);
147
+ // The preAction hook refuses a call without either option.
148
+ if (study === undefined)
149
+ return;
150
+ const result = await configureCommsLab({
151
+ cwd: resolve(options.cwd),
152
+ lab: study,
153
+ connection: options.connection,
154
+ ...(options.apply === undefined ? {} : { apply: options.apply }),
155
+ ...(options.planToken === undefined ? {} : { planToken: options.planToken }),
156
+ });
157
+ writeResult(command, io, result, messageOutput);
136
158
  io.setExitCode(result.ok ? 0 : 2);
137
159
  }
138
160
  async function handleCommsRecover(io, options, command) {
@@ -164,7 +186,7 @@ async function handleCommsRecover(io, options, command) {
164
186
  adapter,
165
187
  })),
166
188
  };
167
- writeResult(command, io, result, (value) => `${value.message}\n`);
189
+ writeResult(command, io, result, messageOutput);
168
190
  io.setExitCode(result.ok ? 0 : 2);
169
191
  }
170
192
  catch {
@@ -173,11 +195,17 @@ async function handleCommsRecover(io, options, command) {
173
195
  ok: false,
174
196
  message: "Recovery could not complete. Select one recorded run with --run, check its connection, and retry. No unrecorded resources are eligible.",
175
197
  };
176
- writeResult(command, io, result, (value) => `${value.message}\n`);
198
+ writeResult(command, io, result, messageOutput);
177
199
  io.setExitCode(2);
178
200
  }
179
201
  }
180
202
  async function handleCommsCatch(io, options) {
203
+ const tokenRefusal = catchTokenRefusal(options.token);
204
+ if (tokenRefusal !== undefined) {
205
+ io.writeErr(`--token: ${tokenRefusal} The token guards GET /deliveries, and runs scrub it from their warnings.\n`);
206
+ io.setExitCode(2);
207
+ return;
208
+ }
181
209
  const port = Number.parseInt(options.port, 10);
182
210
  if (!Number.isInteger(port) || port <= 0 || port > 65_534) {
183
211
  io.writeErr("--port must be an integer between 1 and 65534.\n");
@@ -1,24 +1,24 @@
1
1
  import { Command } from "commander";
2
2
  import { draftFeedback, listFeedback, renderIssueMarkdown, renderIssueUrl, verifyFeedback, } from "../../feedback/feedback.js";
3
- import { candidateOption, JSON_OPTION_DESCRIPTION, wantsJson, writeResult, } from "../io.js";
3
+ import { candidateOption, CWD_OPTION_DESCRIPTION, JSON_OPTION_DESCRIPTION, RUN_OPTION_DESCRIPTION, wantsJson, writeResult, humanError, writeHuman, } from "../io.js";
4
4
  export function registerFeedbackCommands(parent, io) {
5
5
  const feedback = parent
6
6
  .command("feedback")
7
- .description("Create public-safe feedback drafts without GitHub API mutation.")
8
- .summary("Create public-safe feedback drafts, no GitHub API.");
7
+ .description("Draft public-safe feedback issues from a run. humanish never calls the GitHub API.")
8
+ .summary("Draft public-safe feedback issues from a run.");
9
9
  feedback
10
10
  .command("list")
11
11
  .description("List recorded feedback candidates and any saved draft.")
12
- .addHelpText("after", "\nWith no candidates, feedback draft and feedback issue can generate a run-summary follow-up. Public drafting still requires share_ready verification.\n")
13
- .option("--run <id>", "Run id or latest pointer.", "latest")
14
- .option("--cwd <path>", "Target project directory.", ".")
12
+ .addHelpText("after", "\nWith no candidates, feedback draft and feedback issue write a run-summary follow-up for a live run that verifies share_ready. A dry run gets no draft.\n")
13
+ .option("--run <id>", RUN_OPTION_DESCRIPTION, "latest")
14
+ .option("--cwd <path>", CWD_OPTION_DESCRIPTION, ".")
15
15
  .option("--json", JSON_OPTION_DESCRIPTION)
16
16
  .action((options, command) => handleFeedbackList(io, options, command));
17
17
  feedback
18
18
  .command("draft")
19
19
  .description("Generate a public-safe feedback draft from verified evidence.")
20
- .option("--run <id>", "Run id or latest pointer.", "latest")
21
- .option("--cwd <path>", "Target project directory.", ".")
20
+ .option("--run <id>", RUN_OPTION_DESCRIPTION, "latest")
21
+ .option("--cwd <path>", CWD_OPTION_DESCRIPTION, ".")
22
22
  .option("--analysis <id>", "Independent analysis version; use with --finding.")
23
23
  .option("--finding <id>", "Finding within --analysis, separate from participant candidates.")
24
24
  .option("--candidate <id>", "Which finding to draft (ids from `feedback list`); default: the first.")
@@ -27,8 +27,8 @@ export function registerFeedbackCommands(parent, io) {
27
27
  feedback
28
28
  .command("verify")
29
29
  .description("Verify the feedback draft for public issue eligibility.")
30
- .option("--run <id>", "Run id or latest pointer.", "latest")
31
- .option("--cwd <path>", "Target project directory.", ".")
30
+ .option("--run <id>", RUN_OPTION_DESCRIPTION, "latest")
31
+ .option("--cwd <path>", CWD_OPTION_DESCRIPTION, ".")
32
32
  .option("--analysis <id>", "Independent analysis version; use with --finding.")
33
33
  .option("--finding <id>", "Finding within --analysis, separate from participant candidates.")
34
34
  .option("--candidate <id>", "Which finding to verify (ids from `feedback list`); default: the first.")
@@ -37,8 +37,8 @@ export function registerFeedbackCommands(parent, io) {
37
37
  feedback
38
38
  .command("issue")
39
39
  .description("Print Markdown for a public GitHub issue. Does not mutate GitHub.")
40
- .option("--run <id>", "Run id or latest pointer.", "latest")
41
- .option("--cwd <path>", "Target project directory.", ".")
40
+ .option("--run <id>", RUN_OPTION_DESCRIPTION, "latest")
41
+ .option("--cwd <path>", CWD_OPTION_DESCRIPTION, ".")
42
42
  .requiredOption("--repo <owner/repo>", "Repository slug used in rendered filing instructions.")
43
43
  .option("--format <format>", "Output format.", "markdown")
44
44
  .option("--analysis <id>", "Independent analysis version; use with --finding.")
@@ -49,8 +49,8 @@ export function registerFeedbackCommands(parent, io) {
49
49
  feedback
50
50
  .command("issue-url")
51
51
  .description("Print a prefilled public issue URL. Does not mutate GitHub.")
52
- .option("--run <id>", "Run id or latest pointer.", "latest")
53
- .option("--cwd <path>", "Target project directory.", ".")
52
+ .option("--run <id>", RUN_OPTION_DESCRIPTION, "latest")
53
+ .option("--cwd <path>", CWD_OPTION_DESCRIPTION, ".")
54
54
  .requiredOption("--repo <owner/repo>", "Repository slug used in the generated URL.")
55
55
  .option("--analysis <id>", "Independent analysis version; use with --finding.")
56
56
  .option("--finding <id>", "Finding within --analysis, separate from participant candidates.")
@@ -87,7 +87,7 @@ async function handleFeedbackIssue(io, options, command) {
87
87
  io.writeOut(result.issueMarkdown);
88
88
  }
89
89
  else {
90
- io.writeErr(formatFeedbackHuman(result));
90
+ writeHuman(command, io, formatFeedbackHuman(result));
91
91
  }
92
92
  io.setExitCode(result.ok ? 0 : 2);
93
93
  }
@@ -100,14 +100,13 @@ async function handleFeedbackIssueUrl(io, options, command) {
100
100
  io.writeOut(`${result.issueUrl}\n`);
101
101
  }
102
102
  else {
103
- io.writeErr(formatFeedbackHuman(result));
103
+ writeHuman(command, io, formatFeedbackHuman(result));
104
104
  }
105
105
  io.setExitCode(result.ok ? 0 : 2);
106
106
  }
107
107
  function formatFeedbackHuman(result) {
108
- if (!result.ok) {
109
- return `${result.error?.code}: ${result.error?.message}\n`;
110
- }
108
+ if (!result.ok)
109
+ return humanError(result.error);
111
110
  const candidates = result.candidates ?? [];
112
111
  const noCandidates = result.candidates !== undefined && candidates.length === 0;
113
112
  return ([
@@ -123,11 +122,11 @@ function formatFeedbackHuman(result) {
123
122
  ...(noCandidates
124
123
  ? [
125
124
  "candidates: none recorded",
126
- "With no candidates, feedback draft and feedback issue can generate a run-summary follow-up after share_ready verification.",
125
+ "With no candidates, feedback draft and feedback issue write a run-summary follow-up for a live run that verifies share_ready.",
127
126
  ...(result.draft ? [`summary: ${result.draft.summary}`] : []),
128
127
  ]
129
128
  : []),
130
- // Every finding the run produced, so the second and third are one flag away (#609).
129
+ // Every finding the run produced, so the second and third are one flag away.
131
130
  ...(candidates.length > 1 || (candidates.length === 1 && result.draft === undefined)
132
131
  ? [
133
132
  `candidates (${candidates.length}; choose one with --candidate <id>):`,
@@ -1,8 +1,9 @@
1
+ import type { HumanOutput } from "../io.js";
1
2
  import type { CuaActorLabResult } from "../../routes/computer-use/types.js";
2
3
  import type { ScriptedBrowserLabResult } from "../../routes/scripted/types.js";
3
4
  import type { TerminalProductLabResult } from "../../routes/terminal/types.js";
4
5
  import type { ConcurrentSharedWorldLabResult } from "../../routes/shared-world/types.js";
5
- export declare function formatConcurrentSharedWorldLabHuman(result: ConcurrentSharedWorldLabResult): string;
6
- export declare function formatTerminalLabHuman(result: TerminalProductLabResult): string;
7
- export declare function formatScriptedLabHuman(result: ScriptedBrowserLabResult): string;
8
- export declare function formatCuaLabHuman(result: CuaActorLabResult): string;
6
+ export declare function formatConcurrentSharedWorldLabHuman(result: ConcurrentSharedWorldLabResult): HumanOutput;
7
+ export declare function formatTerminalLabHuman(result: TerminalProductLabResult): HumanOutput;
8
+ export declare function formatScriptedLabHuman(result: ScriptedBrowserLabResult): HumanOutput;
9
+ export declare function formatCuaLabHuman(result: CuaActorLabResult): HumanOutput;
@@ -1,10 +1,28 @@
1
1
  import { formatCuaDiagnostics, formatCuaStopCause } from "../../routes/computer-use/diagnostics.js";
2
+ /** A lab run's first lines: the command that ran, whether it was a dry run, how it ended, and its route. */
3
+ function runHeader(result, route) {
4
+ const kind = result.dryRun === true ? "dry run" : result.dryRun === false ? "live run" : "run";
5
+ return [
6
+ `humanish run ${result.studyId}: ${kind} ${result.ok ? "finished" : "failed"}`,
7
+ `route: ${route}`,
8
+ ];
9
+ }
10
+ /**
11
+ * A run's human output: its lines on stdout and, when it failed with an error, that error on
12
+ * stderr through formatCliError.
13
+ */
14
+ function withError(error, lines) {
15
+ const stdout = `${lines.join("\n")}\n`;
16
+ return error === undefined ? stdout : { stdout, error };
17
+ }
18
+ /** A participant's status in words: a dry run's placeholder status says that nothing ran live. */
19
+ function participantStatus(status) {
20
+ return status === "contract_proof_only" ? "dry run, nothing ran live" : status;
21
+ }
2
22
  export function formatConcurrentSharedWorldLabHuman(result) {
3
- return ([
4
- `humanish lab concurrent-shared-world ${result.ok ? (result.dryRun ? "dry-run" : "live") : "failed"}`,
5
- ...(result.error ? [`${result.error.code}: ${result.error.message}`] : []),
23
+ return withError(result.error, [
24
+ ...runHeader(result, "shared-world"),
6
25
  `run: ${result.runId}`,
7
- `lab: ${result.labId}`,
8
26
  `actor: ${result.actor}`,
9
27
  `topology: ${result.topology}/${result.topologyMode} (${result.roleCount} persona${result.roleCount === 1 ? "" : "s"}, concurrency ${result.concurrency})`,
10
28
  ...(result.host ? [`host: ${result.host}`] : []),
@@ -16,7 +34,7 @@ export function formatConcurrentSharedWorldLabHuman(result) {
16
34
  : [
17
35
  `overlap: ${result.overlapProven ? "proven" : "not observed"} (this run only; no scale or adoption claim)`,
18
36
  ]),
19
- ...result.roles.map((participant) => `persona ${participant.id} (${participant.persona}): ${participant.status}${participant.session ? ` (${participant.session.completionReason})` : ""} ${participant.ok ? "ok" : "not-ok"}`),
37
+ ...result.roles.map((participant) => `persona ${participant.id} (${participant.persona}): ${participantStatus(participant.status)}${participant.session ? ` (${participant.session.completionReason})` : ""}${participant.ok ? "" : ", not ok"}`),
20
38
  ...(result.subjectSandbox
21
39
  ? [
22
40
  `subject sandbox: ${result.subjectSandbox.sandboxId} killed=${result.subjectSandbox.killed ? "yes" : "no"}`,
@@ -27,14 +45,12 @@ export function formatConcurrentSharedWorldLabHuman(result) {
27
45
  ? []
28
46
  : [`opened: ${result.observer.opened ? "yes" : "no"}`]),
29
47
  ...result.warnings.map((warning) => `warning: ${warning}`),
30
- ].join("\n") + "\n");
48
+ ]);
31
49
  }
32
50
  export function formatTerminalLabHuman(result) {
33
- return ([
34
- `humanish lab terminal ${result.ok ? (result.dryRun ? "dry-run" : "live") : "failed"}`,
35
- ...(result.error ? [`${result.error.code}: ${result.error.message}`] : []),
51
+ return withError(result.error, [
52
+ ...runHeader(result, "terminal"),
36
53
  `run: ${result.runId}`,
37
- `lab: ${result.labId}`,
38
54
  `actor: ${result.actor}`,
39
55
  `product: ${result.product}`,
40
56
  ...(result.observer?.observerPath ? [`observer: ${result.observer.observerPath}`] : []),
@@ -42,14 +58,12 @@ export function formatTerminalLabHuman(result) {
42
58
  ? []
43
59
  : [`opened: ${result.observer.opened ? "yes" : "no"}`]),
44
60
  ...result.warnings.map((warning) => `warning: ${warning}`),
45
- ].join("\n") + "\n");
61
+ ]);
46
62
  }
47
63
  export function formatScriptedLabHuman(result) {
48
- return ([
49
- `humanish lab scripted ${result.ok ? (result.dryRun ? "dry-run" : "live") : "failed"}`,
50
- ...(result.error ? [`${result.error.code}: ${result.error.message}`] : []),
64
+ return withError(result.error, [
65
+ ...runHeader(result, "scripted"),
51
66
  `run: ${result.runId}`,
52
- `lab: ${result.labId}`,
53
67
  `actor: ${result.actor}`,
54
68
  `subject: ${result.appUrl}`,
55
69
  ...(result.scenario
@@ -63,14 +77,12 @@ export function formatScriptedLabHuman(result) {
63
77
  ? []
64
78
  : [`opened: ${result.observer.opened ? "yes" : "no"}`]),
65
79
  ...result.warnings.map((warning) => `warning: ${warning}`),
66
- ].join("\n") + "\n");
80
+ ]);
67
81
  }
68
82
  export function formatCuaLabHuman(result) {
69
- return ([
70
- `humanish lab cua ${result.ok ? (result.dryRun ? "dry-run" : "live") : "failed"}`,
71
- ...(result.error ? [`${result.error.code}: ${result.error.message}`] : []),
83
+ return withError(result.error, [
84
+ ...runHeader(result, "computer-use"),
72
85
  `run: ${result.runId}`,
73
- `lab: ${result.labId}`,
74
86
  `actor: ${result.actor}`,
75
87
  `subject: ${result.appUrl}`,
76
88
  ...(result.subject?.source === "clone"
@@ -83,11 +95,11 @@ export function formatCuaLabHuman(result) {
83
95
  : []),
84
96
  ...(result.diagnostics ? [`diagnostic: ${formatCuaDiagnostics(result.diagnostics)}`] : []),
85
97
  ...((result.lanes?.length ?? 0) > 1
86
- ? result.lanes.map((participant) => `participant ${participant.id}: ${participant.status}${participant.session ? ` (${participant.session.completionReason})` : ""}${participant.diagnostics ? ` · ${formatCuaDiagnostics(participant.diagnostics)}` : ""}${participant.session ? ` · ${participant.session.reason}` : ""}`)
98
+ ? result.lanes.map((participant) => `participant ${participant.id}: ${participantStatus(participant.status)}${participant.session ? ` (${participant.session.completionReason})` : ""}${participant.diagnostics ? ` · ${formatCuaDiagnostics(participant.diagnostics)}` : ""}${participant.session ? ` · ${participant.session.reason}` : ""}`)
87
99
  : []),
88
100
  ...(result.session && (result.lanes?.length ?? 0) <= 1
89
101
  ? [
90
- `session: ${result.session.status} (${result.session.completionReason})${result.session.stopCause ? ` · ${formatCuaStopCause(result.session.stopCause)}` : ""} · ${result.session.reason}`,
102
+ `session: ${participantStatus(result.session.status)} (${result.session.completionReason})${result.session.stopCause ? ` · ${formatCuaStopCause(result.session.stopCause)}` : ""} · ${result.session.reason}`,
91
103
  `screenshots: ${result.session.screenshots}`,
92
104
  ]
93
105
  : []),
@@ -101,5 +113,5 @@ export function formatCuaLabHuman(result) {
101
113
  ? []
102
114
  : [`opened: ${result.observer.opened ? "yes" : "no"}`]),
103
115
  ...result.warnings.map((warning) => `warning: ${warning}`),
104
- ].join("\n") + "\n");
116
+ ]);
105
117
  }
@@ -1,5 +1,4 @@
1
1
  import { Command } from "commander";
2
- import type { RunLabProvenance } from "../../run/status.js";
3
2
  import type { LabConfig } from "../../lab/types.js";
4
3
  import { type CliIo, type LabCommandOptions } from "../io.js";
5
4
  import type { RouteRun } from "./lab-route-run.js";
@@ -7,7 +6,6 @@ interface ComputerUseRouteArgs {
7
6
  command: Command;
8
7
  io: CliIo;
9
8
  config: LabConfig;
10
- labProvenance?: RunLabProvenance;
11
9
  mode: "run" | "watch";
12
10
  options: LabCommandOptions;
13
11
  }
@@ -2,15 +2,16 @@ import { automaticAnalysisSucceeded } from "../../analysis/automatic-completion.
2
2
  import { Command } from "commander";
3
3
  import {} from "../../run-lab.js";
4
4
  import { resolveLabDryRun } from "../../lab/plan.js";
5
- import { CUA_ACTOR_LAB_SCHEMA } from "../../routes/computer-use/types.js";
6
5
  import { serveObserver } from "../../observer/render.js";
7
6
  import { startExposedObserver, validateExposure } from "../../observer/exposure.js";
8
7
  import { ServeTunnelError } from "../../observer/tunnel.js";
9
8
  import { cliAnalysisOptions } from "./analysis-signals.js";
9
+ import { onRunShutdown } from "./run-signals.js";
10
10
  import { parseLabCount, parseParticipantIds, parseObserverPort, wantsJson, writeResult, } from "../io.js";
11
11
  import { exposureRequestFromOptions, followObserver, planObserver, showObserver, staticObserverOpen, withObserverServer, } from "../observer-follow.js";
12
12
  import { formatCuaLabHuman } from "./lab-format.js";
13
13
  import { resolveRouteShouldOpen } from "./lab-route-open.js";
14
+ import { studyResultIdentity } from "../../run/study-result.js";
14
15
  /**
15
16
  * The computer-use route's CLI setup: its settings, the watch and exposure plan, the runLab options
16
17
  * with the live Observer hook, and how it presents the outcome or a run error. Undefined when
@@ -29,6 +30,7 @@ export function computerUseRouteRun(args) {
29
30
  tunnel: undefined,
30
31
  exposeWarnings: [],
31
32
  publicTarget: undefined,
33
+ releaseShutdown: undefined,
32
34
  };
33
35
  return {
34
36
  options: cuaRunOptions(args, settings, prepared, live),
@@ -37,16 +39,20 @@ export function computerUseRouteRun(args) {
37
39
  if (outcome.route !== "computer-use") {
38
40
  throw new Error(`Expected the computer-use route, got ${outcome.route}.`);
39
41
  }
40
- await reportCuaRun(args, prepared, outcome.result, live);
42
+ try {
43
+ await reportCuaRun(args, prepared, outcome.result, live);
44
+ }
45
+ finally {
46
+ live.releaseShutdown?.();
47
+ }
41
48
  },
42
49
  };
43
50
  }
44
51
  function refuseCua(args, dryRun, code, message) {
45
52
  const result = {
46
- schema: CUA_ACTOR_LAB_SCHEMA,
53
+ ...studyResultIdentity("computer-use", args.config.id),
47
54
  ok: false,
48
55
  cwd: args.options.cwd,
49
- labId: args.config.id,
50
56
  actor: args.config.actors[0]?.type ?? "",
51
57
  appUrl: "",
52
58
  dryRun,
@@ -66,15 +72,15 @@ function resolveCuaSettings(args) {
66
72
  mode: args.mode,
67
73
  wantsMachine,
68
74
  });
69
- const participantIds = parseParticipantIds(args.options.lanes);
75
+ const participantIds = parseParticipantIds(args.options.participants);
70
76
  if (participantIds.length > 0 && !args.options.rerunFailedFrom) {
71
- args.io.writeErr("error: --lanes requires --rerun-failed-from.\n");
77
+ args.io.writeErr("error: --participants requires --rerun-failed-from.\n");
72
78
  args.io.setExitCode(2);
73
79
  return undefined;
74
80
  }
75
- const count = parseLabCount(args.options.count ?? args.options.sims, args.config.actors[0]?.count ?? 1);
81
+ const count = parseLabCount(args.options.count, args.config.actors[0]?.count ?? 1);
76
82
  if (count === null) {
77
- args.io.writeErr("error: --count/--sims must be a positive integer.\n");
83
+ args.io.writeErr("error: --count must be a positive integer.\n");
78
84
  args.io.setExitCode(2);
79
85
  return undefined;
80
86
  }
@@ -90,7 +96,7 @@ function resolveCuaSettings(args) {
90
96
  /** Validates exposure and plans the finished-run Observer, or returns undefined after refusing. */
91
97
  function prepareCuaWatch(args, settings) {
92
98
  // Validate exposure up front (fail-closed matrix), before any run/spend. A live CUA watch is the
93
- // one surface that serves runtime E2B stream URLs, so it MUST sit behind edge auth.
99
+ // one surface that serves runtime E2B stream URLs, so it must sit behind edge auth.
94
100
  const exposeValidation = validateExposure("watch", exposureRequestFromOptions(args.options), {
95
101
  dryRun: settings.dryRun,
96
102
  detach: args.options.detach === true,
@@ -122,7 +128,6 @@ function cuaRunOptions(args, settings, prepared, live) {
122
128
  return {
123
129
  ...cliAnalysisOptions(args.io),
124
130
  cwd: args.options.cwd,
125
- ...(args.labProvenance === undefined ? {} : { lab: args.labProvenance }),
126
131
  // A followed watch opens the served Observer (or prints the phone target under --expose), so
127
132
  // its static render never opens. A non-follow watch opens what its plan says, once. Run mode
128
133
  // keeps the static open.
@@ -135,7 +140,7 @@ function cuaRunOptions(args, settings, prepared, live) {
135
140
  dryRun: settings.dryRun,
136
141
  ...(settings.wantsFollow
137
142
  ? {
138
- // Fires INSIDE runLab, before the actor loop and before sandbox creation, so a
143
+ // Fires inside runLab, before the actor loop and before sandbox creation, so a
139
144
  // tunnel-auth failure aborts before any spend and leaves no orphaned sandbox.
140
145
  onObserverReady: (observer) => attachLiveObserver(args.io, settings, prepared.exposure, live, observer),
141
146
  }
@@ -153,20 +158,24 @@ function cuaRunOptions(args, settings, prepared, live) {
153
158
  }),
154
159
  };
155
160
  }
161
+ /** Closes the loopback server and any tunnel the watch attached. Safe to call twice. */
162
+ async function closeLiveAttachment(io, live) {
163
+ const { server, tunnel } = live;
164
+ live.server = null;
165
+ live.tunnel = undefined;
166
+ await server?.close().catch((cleanupError) => {
167
+ io.writeErr(`watch cleanup failed: ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}\n`);
168
+ });
169
+ await tunnel?.close().catch(() => undefined);
170
+ }
156
171
  /**
157
172
  * Tears down the loopback server and any tunnel started inside onObserverReady, then reports a
158
173
  * tunnel startup failure or rethrows. The sandbox is created after onObserverReady returns, so a
159
174
  * tunnel failure cannot orphan one.
160
175
  */
161
176
  async function closeLiveAfterRunError(args, settings, live, error) {
162
- await live.server?.close().catch((cleanupError) => {
163
- args.io.writeErr(`watch cleanup failed: ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}\n`);
164
- });
165
- live.server = null;
166
- if (live.tunnel) {
167
- await live.tunnel.close().catch(() => undefined);
168
- live.tunnel = undefined;
169
- }
177
+ await closeLiveAttachment(args.io, live);
178
+ live.releaseShutdown?.();
170
179
  if (error instanceof ServeTunnelError) {
171
180
  refuseCua(args, settings.dryRun, error.code, error.message);
172
181
  return;
@@ -182,6 +191,8 @@ async function attachLiveObserver(io, settings, exposure, live, observer) {
182
191
  port: settings.port,
183
192
  exposed: exposure.exposed,
184
193
  });
194
+ // A signal that stops the run closes the server and any tunnel before the process exits.
195
+ live.releaseShutdown ??= onRunShutdown(() => closeLiveAttachment(io, live));
185
196
  }
186
197
  if (exposure.exposed) {
187
198
  const activeServer = live.server;
@@ -202,7 +213,7 @@ async function attachLiveObserver(io, settings, exposure, live, observer) {
202
213
  async function reportCuaRun(args, prepared, result, live) {
203
214
  const { server, observer: attachedObserver } = live;
204
215
  const exposeRequested = prepared.exposure.exposed;
205
- // Serving is NOT gated on result.ok: a timed_out, incomplete or failed run still comes up so the
216
+ // Serving is not gated on result.ok: a timed_out, incomplete or failed run still comes up so the
206
217
  // operator can inspect its evidence live (and, under --expose, from a phone).
207
218
  let output = result;
208
219
  if (server && attachedObserver) {
@@ -212,7 +223,7 @@ async function reportCuaRun(args, prepared, result, live) {
212
223
  observer: withObserverServer(attachedResult, server),
213
224
  warnings: [
214
225
  ...result.warnings,
215
- "Live CUA server is polling observer-data.json with no-store caching.",
226
+ "The live computer-use server polls observer-data.json with no-store caching.",
216
227
  ...(exposeRequested
217
228
  ? [
218
229
  `Exposed live desktop stream URLs to an edge-authenticated remote viewer${live.tunnel ? ` via ${live.tunnel.url.replace(/\/$/, "")}` : ""}.`,
@@ -1,5 +1,4 @@
1
1
  import { Command } from "commander";
2
- import type { RunLabProvenance } from "../../run/status.js";
3
2
  import type { LabConfig } from "../../lab/types.js";
4
3
  import { type CliIo, type LabCommandOptions } from "../io.js";
5
4
  import type { RouteRun } from "./lab-route-run.js";
@@ -8,12 +7,11 @@ interface PreviewRouteArgs {
8
7
  io: CliIo;
9
8
  lab: string;
10
9
  config: LabConfig;
11
- labProvenance?: RunLabProvenance;
12
10
  mode: "run" | "watch";
13
11
  options: LabCommandOptions;
14
12
  }
15
13
  /**
16
- * The preview route's CLI setup: the sim count and Observer plan, its runLab options, and how it
14
+ * The preview route's CLI setup: the participant count and Observer plan, its runLab options, and how it
17
15
  * presents the outcome. Undefined when setup has already written its own result.
18
16
  */
19
17
  export declare function previewRouteRun(args: PreviewRouteArgs): RouteRun | undefined;