humanish 0.106.0 → 0.107.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (459) hide show
  1. package/AGENTS.md +4 -2
  2. package/ARCHITECTURE.md +17 -16
  3. package/CHANGELOG.md +24 -0
  4. package/CONTEXT.md +42 -39
  5. package/CONTRIBUTING.md +8 -6
  6. package/README.md +8 -3
  7. package/dist/actors/codex/app-server-client.js +2 -1
  8. package/dist/actors/codex/app-server-trace.d.ts +0 -1
  9. package/dist/actors/codex/app-server-trace.js +1 -3
  10. package/dist/actors/codex/app-server.js +2 -1
  11. package/dist/actors/codex/protocol-compat.d.ts +27 -0
  12. package/dist/actors/codex/protocol-compat.js +357 -0
  13. package/dist/actors/codex/protocol-contract.d.ts +61 -0
  14. package/dist/actors/codex/protocol-contract.js +471 -0
  15. package/dist/actors/codex/qualified-versions.d.ts +31 -4
  16. package/dist/actors/codex/qualified-versions.js +51 -6
  17. package/dist/actors/codex/restricted-executable.d.ts +24 -0
  18. package/dist/actors/codex/restricted-executable.js +97 -22
  19. package/dist/actors/codex/restricted-launch.d.ts +7 -1
  20. package/dist/actors/codex/restricted-launch.js +42 -3
  21. package/dist/actors/codex/restricted-notifications.d.ts +101 -0
  22. package/dist/actors/codex/restricted-notifications.js +277 -0
  23. package/dist/actors/codex/restricted-participant.d.ts +30 -0
  24. package/dist/actors/codex/restricted-participant.js +60 -2
  25. package/dist/actors/codex/restricted-policy.d.ts +9 -1
  26. package/dist/actors/codex/restricted-session.d.ts +14 -1
  27. package/dist/actors/codex/restricted-session.js +50 -17
  28. package/dist/actors/codex/restricted-transport.d.ts +29 -0
  29. package/dist/actors/codex/restricted-transport.js +139 -27
  30. package/dist/actors/codex/restricted-turn.d.ts +19 -4
  31. package/dist/actors/codex/restricted-turn.js +43 -30
  32. package/dist/actors/computer-use/actor.d.ts +1 -1
  33. package/dist/actors/computer-use/actor.js +4 -4
  34. package/dist/actors/computer-use/loop/backstop.js +1 -1
  35. package/dist/actors/computer-use/loop/ending.d.ts +2 -2
  36. package/dist/actors/computer-use/loop/ending.js +2 -2
  37. package/dist/actors/computer-use/loop/spend.d.ts +1 -1
  38. package/dist/actors/computer-use/loop/spend.js +3 -3
  39. package/dist/actors/computer-use/loop/trace.js +2 -2
  40. package/dist/actors/computer-use/loop/types.d.ts +14 -5
  41. package/dist/actors/computer-use/loop.js +4 -4
  42. package/dist/actors/computer-use/openai-provider.d.ts +1 -1
  43. package/dist/actors/computer-use/openai-provider.js +2 -2
  44. package/dist/actors/contract.d.ts +10 -8
  45. package/dist/actors/contract.js +7 -1
  46. package/dist/actors/local-agent/cli.js +1 -1
  47. package/dist/actors/scripted-browser/actor.d.ts +2 -2
  48. package/dist/actors/scripted-browser/journey.js +15 -4
  49. package/dist/actors/scripted-browser/steps.js +18 -0
  50. package/dist/actors/scripted-browser/types.d.ts +11 -1
  51. package/dist/actors/stop-conditions.js +1 -3
  52. package/dist/analysis/automatic-completion.d.ts +13 -8
  53. package/dist/analysis/automatic-completion.js +14 -8
  54. package/dist/analysis/automatic-config.d.ts +1 -1
  55. package/dist/analysis/automatic-config.js +2 -2
  56. package/dist/analysis/automatic.d.ts +10 -4
  57. package/dist/analysis/automatic.js +17 -13
  58. package/dist/analysis/diagnostics.d.ts +23 -0
  59. package/dist/analysis/diagnostics.js +112 -0
  60. package/dist/analysis/evidence-sources.js +2 -2
  61. package/dist/analysis/evidence.js +6 -6
  62. package/dist/analysis/execute.d.ts +7 -1
  63. package/dist/analysis/execute.js +39 -12
  64. package/dist/analysis/job.d.ts +8 -5
  65. package/dist/analysis/job.js +15 -14
  66. package/dist/analysis/load.d.ts +1 -1
  67. package/dist/analysis/load.js +5 -5
  68. package/dist/analysis/provider.d.ts +9 -1
  69. package/dist/analysis/restricted-codex.d.ts +2 -0
  70. package/dist/analysis/restricted-codex.js +10 -1
  71. package/dist/analysis/service.d.ts +2 -0
  72. package/dist/analysis/service.js +31 -12
  73. package/dist/analysis/sharing.d.ts +2 -2
  74. package/dist/analysis/sharing.js +5 -5
  75. package/dist/analysis/store-executions.d.ts +5 -5
  76. package/dist/analysis/store-executions.js +12 -12
  77. package/dist/analysis/store.d.ts +4 -4
  78. package/dist/analysis/store.js +13 -13
  79. package/dist/cli/commands/analysis-signals.d.ts +2 -1
  80. package/dist/cli/commands/analysis-signals.js +4 -1
  81. package/dist/cli/commands/analyze.js +4 -2
  82. package/dist/cli/commands/comms.js +8 -1
  83. package/dist/cli/commands/lab-route-computer-use.d.ts +0 -2
  84. package/dist/cli/commands/lab-route-computer-use.js +26 -14
  85. package/dist/cli/commands/lab-route-preview.d.ts +1 -3
  86. package/dist/cli/commands/lab-route-preview.js +3 -4
  87. package/dist/cli/commands/lab-route-run.d.ts +6 -4
  88. package/dist/cli/commands/lab-route-run.js +6 -2
  89. package/dist/cli/commands/lab-route-scripted.d.ts +0 -2
  90. package/dist/cli/commands/lab-route-scripted.js +0 -1
  91. package/dist/cli/commands/lab-route-shared-world.d.ts +0 -2
  92. package/dist/cli/commands/lab-route-shared-world.js +0 -1
  93. package/dist/cli/commands/lab-route-terminal.d.ts +0 -2
  94. package/dist/cli/commands/lab-route-terminal.js +0 -1
  95. package/dist/cli/commands/lab-run.js +76 -45
  96. package/dist/cli/commands/lab-scorer.d.ts +0 -2
  97. package/dist/cli/commands/lab.js +12 -6
  98. package/dist/cli/commands/observe.js +22 -0
  99. package/dist/cli/commands/run-signals.d.ts +30 -0
  100. package/dist/cli/commands/run-signals.js +146 -0
  101. package/dist/cli/commands/runs.js +10 -8
  102. package/dist/cli/commands/watch.js +12 -10
  103. package/dist/cli/doctor.d.ts +3 -0
  104. package/dist/cli/doctor.js +10 -2
  105. package/dist/cli/io.d.ts +5 -4
  106. package/dist/cli/io.js +12 -8
  107. package/dist/cli/program.js +3 -3
  108. package/dist/cli/renamed-options.d.ts +11 -0
  109. package/dist/cli/renamed-options.js +18 -0
  110. package/dist/cli/telemetry.d.ts +2 -2
  111. package/dist/cli/telemetry.js +1 -1
  112. package/dist/comms/capture-surface.d.ts +1 -1
  113. package/dist/comms/catch-host.d.ts +1 -1
  114. package/dist/comms/connections.js +4 -4
  115. package/dist/comms/external-evidence.d.ts +27 -0
  116. package/dist/comms/external-evidence.js +93 -0
  117. package/dist/comms/lease-store.js +7 -7
  118. package/dist/comms/types.js +1 -1
  119. package/dist/evidence/browser-hygiene.d.ts +1 -1
  120. package/dist/evidence/browser-hygiene.js +1 -1
  121. package/dist/evidence/redaction.js +1 -1
  122. package/dist/evidence/secret-scrub.d.ts +9 -0
  123. package/dist/evidence/secret-scrub.js +96 -0
  124. package/dist/feedback/draft.js +7 -9
  125. package/dist/feedback/export-bundle.js +4 -4
  126. package/dist/feedback/export.js +9 -9
  127. package/dist/feedback/feedback.d.ts +1 -1
  128. package/dist/index.d.ts +3 -6
  129. package/dist/index.js +3 -6
  130. package/dist/keys/key-resolution.d.ts +3 -1
  131. package/dist/keys/key-resolution.js +18 -16
  132. package/dist/lab/adapter-extension.d.ts +28 -6
  133. package/dist/lab/adapter-extension.js +65 -126
  134. package/dist/lab/adapter-scorer-loader.d.ts +25 -5
  135. package/dist/lab/adapter-scorer-loader.js +24 -0
  136. package/dist/lab/composition-rules.d.ts +2 -0
  137. package/dist/lab/composition-rules.js +35 -26
  138. package/dist/lab/config.js +28 -26
  139. package/dist/lab/device-presets.d.ts +2 -2
  140. package/dist/lab/discover.js +1 -3
  141. package/dist/lab/doctor.d.ts +44 -9
  142. package/dist/lab/doctor.js +149 -41
  143. package/dist/lab/init-plan.js +1 -3
  144. package/dist/lab/keys.js +1 -1
  145. package/dist/lab/lab-deps.d.ts +85 -0
  146. package/dist/lab/lab-deps.js +4 -0
  147. package/dist/lab/parse/actors.js +8 -7
  148. package/dist/lab/parse/comms.js +3 -2
  149. package/dist/lab/parse/execution.js +3 -2
  150. package/dist/lab/parse/subject-state.js +2 -1
  151. package/dist/lab/parse/subject.js +2 -1
  152. package/dist/lab/parse/values.d.ts +0 -1
  153. package/dist/lab/parse/values.js +0 -3
  154. package/dist/lab/persona-resolve.d.ts +3 -3
  155. package/dist/lab/persona-resolve.js +4 -4
  156. package/dist/lab/persona.js +1 -3
  157. package/dist/lab/plan-base.d.ts +6 -2
  158. package/dist/lab/plan-base.js +22 -7
  159. package/dist/lab/plan-participants.d.ts +5 -5
  160. package/dist/lab/plan-participants.js +2 -2
  161. package/dist/lab/plan-types.d.ts +33 -7
  162. package/dist/lab/plan.d.ts +3 -11
  163. package/dist/lab/plan.js +18 -42
  164. package/dist/lab/preflight-result.js +0 -2
  165. package/dist/lab/preflight.d.ts +0 -3
  166. package/dist/lab/preflight.js +1 -1
  167. package/dist/lab/requirements.d.ts +20 -0
  168. package/dist/lab/requirements.js +54 -0
  169. package/dist/lab/route-inputs.d.ts +23 -12
  170. package/dist/lab/route-inputs.js +48 -51
  171. package/dist/lab/routing.d.ts +19 -24
  172. package/dist/lab/routing.js +14 -47
  173. package/dist/lab/run-lab-events.d.ts +6 -11
  174. package/dist/lab/run-lab-events.js +3 -11
  175. package/dist/lab/run-lab-homes.d.ts +64 -0
  176. package/dist/lab/run-lab-homes.js +3 -0
  177. package/dist/lab/run-lab-options.d.ts +12 -66
  178. package/dist/lab/run-lab-options.js +45 -275
  179. package/dist/lab/summary.d.ts +9 -4
  180. package/dist/lab/summary.js +15 -8
  181. package/dist/lab/types.d.ts +132 -132
  182. package/dist/lab/validation.d.ts +15 -15
  183. package/dist/lab/validation.js +28 -28
  184. package/dist/lab/warnings.js +20 -19
  185. package/dist/observer/artifact.d.ts +1 -1
  186. package/dist/observer/artifact.js +3 -3
  187. package/dist/observer/data.js +2 -2
  188. package/dist/observer/render.js +2 -2
  189. package/dist/observer/run-routes.d.ts +1 -1
  190. package/dist/observer/run-routes.js +5 -5
  191. package/dist/observer/serve.d.ts +17 -0
  192. package/dist/observer/serve.js +34 -3
  193. package/dist/observer-app.html +1 -1
  194. package/dist/routes/computer-use/bundle-parts.d.ts +1 -1
  195. package/dist/routes/computer-use/bundle-parts.js +10 -3
  196. package/dist/routes/computer-use/bundle.d.ts +4 -11
  197. package/dist/routes/computer-use/bundle.js +9 -15
  198. package/dist/routes/computer-use/diagnostics.d.ts +1 -1
  199. package/dist/routes/computer-use/diagnostics.js +1 -1
  200. package/dist/routes/computer-use/e2b-desktop/comms.d.ts +10 -10
  201. package/dist/routes/computer-use/e2b-desktop/comms.js +11 -14
  202. package/dist/routes/computer-use/e2b-desktop/desktop.d.ts +2 -2
  203. package/dist/routes/computer-use/e2b-desktop/desktop.js +4 -7
  204. package/dist/routes/computer-use/e2b-desktop/fidelity.d.ts +13 -13
  205. package/dist/routes/computer-use/e2b-desktop/fidelity.js +11 -11
  206. package/dist/routes/computer-use/e2b-desktop/prepare.d.ts +3 -3
  207. package/dist/routes/computer-use/e2b-desktop/prepare.js +33 -36
  208. package/dist/routes/computer-use/e2b-desktop/start.d.ts +1 -1
  209. package/dist/routes/computer-use/e2b-desktop/start.js +24 -23
  210. package/dist/routes/computer-use/e2b-desktop/state.d.ts +5 -4
  211. package/dist/routes/computer-use/e2b-desktop/state.js +5 -3
  212. package/dist/routes/computer-use/e2b-desktop/teardown.d.ts +1 -1
  213. package/dist/routes/computer-use/e2b-desktop/teardown.js +29 -17
  214. package/dist/routes/computer-use/external-comms.d.ts +4 -4
  215. package/dist/routes/computer-use/external-comms.js +19 -43
  216. package/dist/routes/computer-use/fanout-bundle.d.ts +3 -3
  217. package/dist/routes/computer-use/fanout-bundle.js +25 -29
  218. package/dist/routes/computer-use/{fanout-lanes.js → fanout-records.js} +25 -19
  219. package/dist/routes/computer-use/in-process-desktop.d.ts +3 -10
  220. package/dist/routes/computer-use/in-process-desktop.js +3 -9
  221. package/dist/routes/computer-use/live-flush.d.ts +7 -5
  222. package/dist/routes/computer-use/live-flush.js +19 -27
  223. package/dist/routes/computer-use/{run-lanes.js → live-phase.js} +14 -13
  224. package/dist/routes/computer-use/local-tree-pack.d.ts +3 -3
  225. package/dist/routes/computer-use/local-tree-pack.js +4 -5
  226. package/dist/routes/computer-use/local-vm.d.ts +11 -8
  227. package/dist/routes/computer-use/local-vm.js +39 -66
  228. package/dist/routes/computer-use/participant-desktop.d.ts +8 -23
  229. package/dist/routes/computer-use/participant-desktop.js +5 -25
  230. package/dist/routes/computer-use/{lanes.d.ts → participant-execution.d.ts} +10 -10
  231. package/dist/routes/computer-use/{lanes.js → participant-execution.js} +35 -22
  232. package/dist/routes/computer-use/participant-facts.d.ts +7 -1
  233. package/dist/routes/computer-use/participant-facts.js +12 -1
  234. package/dist/routes/computer-use/participant-model.d.ts +19 -11
  235. package/dist/routes/computer-use/participant-model.js +58 -33
  236. package/dist/routes/computer-use/participant-prompt.d.ts +3 -3
  237. package/dist/routes/computer-use/participant-prompt.js +4 -4
  238. package/dist/routes/computer-use/participant-runs.d.ts +6 -6
  239. package/dist/routes/computer-use/participant-runs.js +8 -8
  240. package/dist/routes/computer-use/plan.d.ts +21 -29
  241. package/dist/routes/computer-use/plan.js +59 -65
  242. package/dist/routes/computer-use/preflight.d.ts +6 -11
  243. package/dist/routes/computer-use/preflight.js +26 -18
  244. package/dist/routes/computer-use/rerun-selection.js +10 -6
  245. package/dist/routes/computer-use/result.d.ts +1 -1
  246. package/dist/routes/computer-use/result.js +40 -30
  247. package/dist/routes/computer-use/route.d.ts +3 -4
  248. package/dist/routes/computer-use/route.js +21 -19
  249. package/dist/routes/computer-use/self-report.d.ts +2 -2
  250. package/dist/routes/computer-use/self-report.js +4 -4
  251. package/dist/routes/computer-use/setup.d.ts +8 -17
  252. package/dist/routes/computer-use/setup.js +98 -86
  253. package/dist/routes/computer-use/single-bundle.d.ts +8 -11
  254. package/dist/routes/computer-use/single-bundle.js +20 -25
  255. package/dist/routes/computer-use/subject-projection.d.ts +5 -7
  256. package/dist/routes/computer-use/subject-projection.js +20 -19
  257. package/dist/routes/computer-use/types.d.ts +169 -211
  258. package/dist/routes/computer-use/types.js +13 -6
  259. package/dist/routes/preview.js +0 -1
  260. package/dist/routes/scripted/bundle.d.ts +3 -6
  261. package/dist/routes/scripted/bundle.js +11 -16
  262. package/dist/routes/scripted/plan.d.ts +5 -7
  263. package/dist/routes/scripted/plan.js +6 -4
  264. package/dist/routes/scripted/result.d.ts +4 -1
  265. package/dist/routes/scripted/result.js +10 -6
  266. package/dist/routes/scripted/route.js +10 -11
  267. package/dist/routes/scripted/scenario.d.ts +1 -1
  268. package/dist/routes/scripted/scenario.js +1 -1
  269. package/dist/routes/scripted/setup.d.ts +3 -2
  270. package/dist/routes/scripted/setup.js +22 -21
  271. package/dist/routes/scripted/subject.d.ts +8 -3
  272. package/dist/routes/scripted/subject.js +11 -6
  273. package/dist/routes/scripted/surface-records.js +1 -1
  274. package/dist/routes/scripted/surface-sessions.d.ts +2 -2
  275. package/dist/routes/scripted/surface-sessions.js +4 -4
  276. package/dist/routes/scripted/types.d.ts +19 -36
  277. package/dist/routes/scripted/types.js +1 -2
  278. package/dist/routes/shared-world/{seat-records.js → bundle-records.js} +8 -8
  279. package/dist/routes/shared-world/bundle.d.ts +2 -2
  280. package/dist/routes/shared-world/bundle.js +22 -26
  281. package/dist/routes/shared-world/checkpoints.d.ts +4 -4
  282. package/dist/routes/shared-world/checkpoints.js +4 -4
  283. package/dist/routes/shared-world/comms.d.ts +5 -4
  284. package/dist/routes/shared-world/comms.js +28 -41
  285. package/dist/routes/shared-world/external-public.d.ts +5 -5
  286. package/dist/routes/shared-world/external-public.js +19 -20
  287. package/dist/routes/shared-world/handoff.d.ts +4 -4
  288. package/dist/routes/shared-world/handoff.js +50 -50
  289. package/dist/routes/shared-world/lobby-code.d.ts +5 -5
  290. package/dist/routes/shared-world/lobby-code.js +13 -13
  291. package/dist/routes/shared-world/{seats.d.ts → participant-specs.d.ts} +8 -6
  292. package/dist/routes/shared-world/{seats.js → participant-specs.js} +46 -51
  293. package/dist/routes/shared-world/plan.d.ts +2 -6
  294. package/dist/routes/shared-world/plan.js +1 -2
  295. package/dist/routes/shared-world/provenance.d.ts +4 -4
  296. package/dist/routes/shared-world/provenance.js +4 -4
  297. package/dist/routes/shared-world/provisioned.d.ts +3 -2
  298. package/dist/routes/shared-world/provisioned.js +48 -41
  299. package/dist/routes/shared-world/result.js +31 -19
  300. package/dist/routes/shared-world/route.js +37 -41
  301. package/dist/routes/shared-world/setup.d.ts +5 -4
  302. package/dist/routes/shared-world/setup.js +12 -14
  303. package/dist/routes/shared-world/types.d.ts +53 -126
  304. package/dist/routes/shared-world/types.js +2 -2
  305. package/dist/routes/terminal/adapter.d.ts +8 -8
  306. package/dist/routes/terminal/adapter.js +28 -125
  307. package/dist/routes/terminal/bundle.d.ts +7 -12
  308. package/dist/routes/terminal/bundle.js +24 -34
  309. package/dist/routes/terminal/credentials.d.ts +2 -2
  310. package/dist/routes/terminal/credentials.js +16 -16
  311. package/dist/routes/terminal/dry-run.d.ts +1 -1
  312. package/dist/routes/terminal/dry-run.js +9 -11
  313. package/dist/routes/terminal/encoding.d.ts +1 -1
  314. package/dist/routes/terminal/encoding.js +2 -2
  315. package/dist/routes/terminal/ledger.d.ts +6 -6
  316. package/dist/routes/terminal/ledger.js +9 -9
  317. package/dist/routes/terminal/live-finish.d.ts +1 -2
  318. package/dist/routes/terminal/live-finish.js +21 -20
  319. package/dist/routes/terminal/live-sandbox.d.ts +4 -2
  320. package/dist/routes/terminal/live-sandbox.js +25 -21
  321. package/dist/routes/terminal/participant-text.d.ts +23 -0
  322. package/dist/routes/terminal/participant-text.js +165 -0
  323. package/dist/routes/terminal/plan.d.ts +2 -6
  324. package/dist/routes/terminal/plan.js +13 -9
  325. package/dist/routes/terminal/recorder.d.ts +6 -1
  326. package/dist/routes/terminal/recorder.js +12 -4
  327. package/dist/routes/terminal/result.js +4 -4
  328. package/dist/routes/terminal/route.js +26 -26
  329. package/dist/routes/terminal/runtime.d.ts +3 -2
  330. package/dist/routes/terminal/runtime.js +3 -3
  331. package/dist/routes/terminal/sandbox.d.ts +5 -3
  332. package/dist/routes/terminal/sandbox.js +13 -16
  333. package/dist/routes/terminal/session.js +16 -14
  334. package/dist/routes/terminal/token-usage.js +5 -5
  335. package/dist/routes/terminal/trace.d.ts +5 -8
  336. package/dist/routes/terminal/trace.js +9 -64
  337. package/dist/routes/terminal/types.d.ts +85 -93
  338. package/dist/routes/terminal/types.js +9 -4
  339. package/dist/run/active-runs.d.ts +13 -0
  340. package/dist/run/active-runs.js +12 -0
  341. package/dist/run/bundle-shape.d.ts +2 -1
  342. package/dist/run/bundle-shape.js +4 -4
  343. package/dist/run/bundle.d.ts +63 -56
  344. package/dist/run/bundle.js +9 -8
  345. package/dist/run/cost-summary.js +3 -2
  346. package/dist/run/costs.d.ts +6 -6
  347. package/dist/run/costs.js +10 -10
  348. package/dist/run/detail.d.ts +5 -5
  349. package/dist/run/detail.js +6 -6
  350. package/dist/run/dry-run.js +5 -12
  351. package/dist/run/{study-files.d.ts → evidence-files.d.ts} +4 -4
  352. package/dist/run/{study-files.js → evidence-files.js} +5 -5
  353. package/dist/run/feedback-shape.js +1 -1
  354. package/dist/run/judge.d.ts +16 -4
  355. package/dist/run/judge.js +24 -7
  356. package/dist/run/locate.d.ts +2 -0
  357. package/dist/run/locate.js +3 -1
  358. package/dist/run/outcomes.d.ts +3 -3
  359. package/dist/run/outcomes.js +3 -3
  360. package/dist/run/participant-records.d.ts +2 -2
  361. package/dist/run/participant-records.js +2 -2
  362. package/dist/run/paths.js +1 -1
  363. package/dist/run/pricing.d.ts +19 -9
  364. package/dist/run/pricing.js +30 -18
  365. package/dist/run/projection.d.ts +13 -13
  366. package/dist/run/projection.js +8 -8
  367. package/dist/run/reclaim.d.ts +7 -1
  368. package/dist/run/reclaim.js +24 -4
  369. package/dist/run/results.d.ts +1 -1
  370. package/dist/run/run-index.d.ts +1 -1
  371. package/dist/run/run-index.js +11 -11
  372. package/dist/run/run.d.ts +4 -2
  373. package/dist/run/run.js +9 -5
  374. package/dist/run/sandbox-receipts.d.ts +4 -4
  375. package/dist/run/sandbox-receipts.js +4 -4
  376. package/dist/run/shared-world-evidence.d.ts +47 -47
  377. package/dist/run/shared-world-shape.d.ts +3 -3
  378. package/dist/run/shared-world-shape.js +11 -11
  379. package/dist/run/stats.d.ts +5 -5
  380. package/dist/run/stats.js +8 -8
  381. package/dist/run/status.d.ts +16 -6
  382. package/dist/run/status.js +31 -8
  383. package/dist/run/streams.d.ts +26 -19
  384. package/dist/run/terminal-contract.d.ts +5 -5
  385. package/dist/run/terminal-contract.js +4 -4
  386. package/dist/run/transient-comms-secrets.d.ts +5 -0
  387. package/dist/run/transient-comms-secrets.js +12 -0
  388. package/dist/run-lab.d.ts +36 -34
  389. package/dist/run-lab.js +41 -37
  390. package/dist/subject/desktop-cli.d.ts +1 -1
  391. package/dist/subject/desktop-cli.js +1 -1
  392. package/dist/subject/local-tree-archive.d.ts +1 -1
  393. package/dist/subject/local-tree-archive.js +4 -4
  394. package/dist/subject/local-tree.d.ts +2 -2
  395. package/dist/subject/local-tree.js +1 -1
  396. package/dist/subject/node-bootstrap.d.ts +1 -1
  397. package/dist/subject/node-bootstrap.js +4 -4
  398. package/dist/subject/runtime.js +5 -5
  399. package/dist/subject/serve.js +1 -1
  400. package/dist/subject/steps.d.ts +4 -4
  401. package/dist/subject/steps.js +5 -5
  402. package/dist/substrates/desktop-session.d.ts +2 -0
  403. package/dist/substrates/e2b/cdp-probe.d.ts +2 -2
  404. package/dist/substrates/e2b/cdp-probe.js +1 -1
  405. package/dist/substrates/e2b/desktop-browser.d.ts +3 -3
  406. package/dist/substrates/e2b/desktop-browser.js +4 -4
  407. package/dist/substrates/e2b/desktop-cdp.d.ts +7 -7
  408. package/dist/substrates/e2b/desktop-cdp.js +4 -4
  409. package/dist/substrates/e2b/desktop-geometry.d.ts +4 -4
  410. package/dist/substrates/e2b/desktop-geometry.js +3 -3
  411. package/dist/substrates/e2b/desktop-media.js +2 -2
  412. package/dist/substrates/e2b/sandbox.d.ts +2 -0
  413. package/dist/substrates/e2b/sandbox.js +22 -8
  414. package/dist/substrates/e2b/sdk.d.ts +12 -1
  415. package/dist/substrates/e2b/sdk.js +30 -9
  416. package/dist/substrates/local/runtime-host.d.ts +2 -0
  417. package/dist/substrates/local/runtime-host.js +6 -0
  418. package/dist/tui/actions.d.ts +7 -5
  419. package/dist/tui/actions.js +18 -9
  420. package/dist/tui-app.js +42 -42
  421. package/dist/verify/actor.d.ts +10 -10
  422. package/dist/verify/actor.js +15 -15
  423. package/dist/verify/artifacts.d.ts +1 -1
  424. package/dist/verify/artifacts.js +3 -3
  425. package/dist/verify/costs.d.ts +2 -2
  426. package/dist/verify/costs.js +2 -2
  427. package/dist/verify/liveness.d.ts +1 -1
  428. package/dist/verify/liveness.js +4 -1
  429. package/dist/verify/rerun.d.ts +1 -1
  430. package/dist/verify/rerun.js +1 -1
  431. package/dist/verify/shared-world.js +2 -2
  432. package/dist/verify/verify.js +6 -6
  433. package/docs/README.md +1 -1
  434. package/docs/architecture/actor-contract.md +60 -22
  435. package/docs/architecture/desktop-sessions.md +9 -9
  436. package/docs/architecture/external-public-shared-world.md +5 -0
  437. package/docs/architecture/observer.md +4 -4
  438. package/docs/architecture/restricted-codex-analysis.md +40 -4
  439. package/docs/architecture/state-driven-executor.md +4 -5
  440. package/docs/architecture/task-protocol-support.md +3 -5
  441. package/docs/architecture/{terminal-product-lane.md → terminal-product-route.md} +24 -16
  442. package/docs/contracts/run-bundle.md +10 -8
  443. package/docs/contracts/schemas.md +109 -53
  444. package/docs/contracts/study-analysis.md +24 -0
  445. package/docs/decisions/0004-participant-desktops-stay-in-the-route.md +2 -1
  446. package/docs/product/automatic-analysis.md +1 -0
  447. package/docs/ramp/README.md +2 -1
  448. package/package.json +4 -4
  449. package/skills/humanish/SKILL.md +3 -2
  450. package/skills/humanish/agents/openai.yaml +1 -1
  451. package/dist/deprecated.d.ts +0 -90
  452. package/dist/deprecated.js +0 -106
  453. package/dist/lab/bag-overrides.d.ts +0 -18
  454. package/dist/lab/bag-overrides.js +0 -121
  455. package/dist/routes/computer-use/legacy-lane-spec.d.ts +0 -62
  456. package/dist/routes/computer-use/legacy-lane-spec.js +0 -39
  457. /package/dist/routes/computer-use/{fanout-lanes.d.ts → fanout-records.d.ts} +0 -0
  458. /package/dist/routes/computer-use/{run-lanes.d.ts → live-phase.d.ts} +0 -0
  459. /package/dist/routes/shared-world/{seat-records.d.ts → bundle-records.d.ts} +0 -0
@@ -2,181 +2,94 @@ import type { Verdict } from "../../run/judge.js";
2
2
  import type { RunDesktopRecording } from "../../evidence/desktop-recording-types.js";
3
3
  import type { CuaExecutor, CuaLiveMetadata, CuaLoopResult, CuaProvider } from "../../actors/computer-use/loop.js";
4
4
  import type { CommsReceivingRun } from "../../comms/receiving.js";
5
- import { type ParticipantDesktop } from "./participant-desktop.js";
5
+ import { type ParticipantDesktop, type ParticipantDesktopFactory } from "./participant-desktop.js";
6
6
  import type { SubjectPhaseEvent } from "../../subject/steps.js";
7
7
  import type { DesktopBrowserEvidence } from "../../substrates/e2b/desktop-browser.js";
8
- import { type AutomaticAnalysisHooks, type AutomaticAnalysisResult } from "../../analysis/automatic-completion.js";
8
+ import { type AutomaticAnalysisResult } from "../../analysis/automatic-completion.js";
9
+ import type { AutomaticAnalysisRefusal } from "../../analysis/job.js";
9
10
  import { type CuaDiagnostics } from "./diagnostics.js";
10
11
  import type { ActorCompletionReason, ActorStatus, ActorStopCause, ActorTokenUsage, ActorTraceItem } from "../../actors/contract.js";
11
12
  import { type CuaActorDescriptor } from "../../actors/registry.js";
12
- import { type BrowserLabAdapterHooks } from "../../lab/adapter-extension.js";
13
+ import type { LabDeps, PhaseParticipant } from "../../lab/lab-deps.js";
14
+ import type { LabEvent, ParticipantRef } from "../../lab/run-lab-events.js";
15
+ import type { InProcessDriver, ProviderFactory, RunLabHomes } from "../../lab/run-lab-homes.js";
16
+ import { type BrowserScorer } from "../../lab/adapter-extension.js";
13
17
  import type { CuaActorSessionOptions } from "../../actors/computer-use/actor.js";
14
- import { type E2BDesktopModule, type E2BDesktopSandbox } from "../../substrates/e2b/sdk.js";
18
+ import { type E2BDesktopModule } from "../../substrates/e2b/sdk.js";
15
19
  import { type DesktopResourceObservation } from "../../substrates/e2b/desktop-resources.js";
16
20
  import { type DetachedTimers } from "../../substrates/detached.js";
17
- import type { ComputerUsePlan } from "../../lab/plan-types.js";
18
- import { type LabCommsEmail, type LabConfig, type LabSubjectServe } from "../../lab/types.js";
19
- import { type LocalAgentId } from "../../actors/local-agent/cli.js";
20
- import { renderObserver, type ObserverResult } from "../../observer/render.js";
21
- import { type RunLabProvenance } from "../../run/status.js";
22
- import { type RunBundle, type RunRerunLineage, type RunScorerProvenance, type RunSubjectProvenance, type RunSubjectStateStepRecord } from "../../run/bundle.js";
21
+ import type { Brain, ComputerUsePlan, ComputerUseRunner, ResidualConfig } from "../../lab/plan-types.js";
22
+ import { type LabCommsEmail, type LabConfig } from "../../lab/types.js";
23
+ import { type ObserverResult } from "../../observer/render.js";
24
+ import { type BundleRun, type RunBundle, type RunRerunLineage, type RunScorerProvenance, type RunSubjectProvenance, type RunSubjectStateStepRecord } from "../../run/bundle.js";
23
25
  import { type RunDesktopGeometry } from "../../run/streams.js";
24
26
  import { type PreparedOutputRoot } from "../../run/contained-output.js";
25
- import { type LocalTreeArchive } from "../../subject/local-tree-archive.js";
26
27
  import type { ComputerUseParticipant, SharedWorldParticipant } from "../../lab/plan-participants.js";
27
28
  import type { ResolvedParticipant } from "../../run/participant.js";
28
- import type { CuaLaneSpec } from "./legacy-lane-spec.js";
29
29
  export declare const CUA_ACTOR_LAB_SCHEMA = "humanish.cua-lab-result.v2";
30
30
  export declare const CUA_FANOUT_STRATEGY: "per-lane-worlds";
31
31
  export declare const CUA_MAX_CONCURRENCY_ENV = "HUMANISH_CUA_MAX_CONCURRENCY";
32
32
  export declare const DEFAULT_APP_URL_SESSION_TIMEOUT_MS: number;
33
33
  export declare const MIN_DERIVED_SESSION_TIMEOUT_MS: number;
34
- /**
35
- * Library-level hooks. `prepareDesktop` runs after sandbox creation and before subject
36
- * provisioning / browser launch — library callers use it for extra in-sandbox setup beyond
37
- * what `subject.serve` declares (or to provision an app-url subject entirely). The rest are
38
- * DI seams so CI drives the full path with fakes at zero network/zero spend.
39
- */
40
- export interface CuaActorLabHooks extends BrowserLabAdapterHooks {
41
- /**
42
- * Runs after sandbox creation and before subject provisioning / browser launch. Widened
43
- * back-compatibly with per-lane context so a library caller can provision the right app-url
44
- * subject per lane (a one-arg `(desktop) => …` still satisfies the type). Called once per lane.
45
- */
46
- prepareDesktop?: (desktop: E2BDesktopSandbox, lane: {
47
- laneId: string;
48
- laneIndex: number;
49
- laneCount: number;
50
- }) => Promise<void>;
51
- /**
52
- * Pre-flight hook: receives the resolved lane plan BEFORE any sandbox or provider call (dry-run
53
- * AND live). The engine also prints the plan to stderr; this seam lets tests assert it without
54
- * scraping stderr. Identical plan in dry-run, marked $0.
55
- */
56
- onPreflight?: (plan: CuaParticipantPlan) => void;
57
- /**
58
- * Live subject-provisioning phase sink: one call per started/completed boundary (clone,
59
- * upload/extract, install, build, serve start, ready, and each subject.state seed-step
60
- * group). Defaults to one stderr line per event, prefixed with the lane id when laneCount > 1
61
- * (single-lane emission is unconditional: single-lane silence for the whole boot is the bug
62
- * this event stream closes). Override in tests to capture instead of writing to real stderr.
63
- */
64
- onPhase?: (event: SubjectPhaseEvent, ctx: {
65
- laneId: string;
66
- laneIndex: number;
67
- laneCount: number;
68
- }) => void;
69
- /**
70
- * Runtime-only live desktop stream callback. The URL carries an auth key and must never be
71
- * persisted into run artifacts; callers use it to hydrate an attached Observer server.
72
- */
73
- onRuntimeStreamReady?: (stream: {
74
- laneId: string;
75
- sandboxId: string;
76
- simId: string;
77
- streamId: string;
78
- url: string;
79
- }) => Promise<void> | void;
80
- /** Fired when a lane's sandbox is gone (finished or torn down): the live stream URL is now a
81
- * dead noVNC page, so the watch overlay must stop serving it and let the tile fall back to
82
- * recorded evidence (#357). Fired only for lanes whose onRuntimeStreamReady fired. */
83
- onRuntimeStreamEnded?: (stream: {
84
- laneId: string;
85
- simId: string;
86
- streamId: string;
87
- }) => Promise<void> | void;
88
- loadDesktopModule?: () => Promise<E2BDesktopModule>;
89
- runSession?: (options: CuaActorSessionOptions) => Promise<CuaLoopResult>;
90
- /**
91
- * Supply a custom executor (e.g. a window.* JS-contract bridge over an already-running local
92
- * dev server). When present (with `buildProvider`), `runCuaActorLab` takes the IN-PROCESS
93
- * branch: it NEVER loads the E2B module, creates a sandbox, runs prepareDesktop, provisions a
94
- * clone, opens a browser, or starts a stream — so `result.sandbox` is omitted, the verifiable
95
- * "no E2B SDK call" proof. The whole bundle/Observer/redaction composition below the session
96
- * call is desktop-agnostic and runs unchanged. Receives the resolved config, the
97
- * registry-resolved descriptor, and the entry appUrl.
98
- */
99
- buildExecutor?: (ctx: {
100
- config: LabConfig;
101
- actor: CuaActorDescriptor;
102
- appUrl: string;
103
- }) => Promise<CuaExecutor>;
104
- /**
105
- * Supply a custom provider (a "brain" reasoning over app STATE). REQUIRED alongside
106
- * `buildExecutor` — the default OpenAI provider is vision-based (requiresFrame) and would fail
107
- * closed against a state-only executor that returns no screenshot. (`buildProvider` ALONE is
108
- * allowed — that is just a model swap on the normal E2B route.)
109
- */
110
- buildProvider?: (ctx: {
111
- config: LabConfig;
112
- actor: CuaActorDescriptor;
113
- lane: CuaLaneSpec;
114
- /** How many participants the run has. */
115
- laneCount: number;
116
- executor: CuaExecutor;
117
- }) => Promise<CuaProvider>;
118
- /**
119
- * Substitute desktop ownership while retaining the shared participant and evidence loop.
120
- * @deprecated No replacement: a run's desktop is E2B, the local VM or in process. This goes in
121
- * the next minor.
122
- */
123
- createDesktopLane?: (spec: CuaLaneSpec, warnings: string[], artifactRoot: PreparedOutputRoot) => ParticipantDesktop;
124
- env?: Record<string, string | undefined>;
125
- renderObserverFn?: typeof renderObserver;
126
- /** Injected clock (ms) for the host-side E2B desktop create->teardown span measurement that
127
- * feeds the desktop-minute cost estimate. Defaults to Date.now; tests inject a frozen/stepped
128
- * clock so the desktop-minute line is deterministic. */
129
- now?: () => number;
130
- /** Injected clock/sleep for the detached-step polling (tests only). */
131
- detachedTimers?: DetachedTimers;
132
- /**
133
- * Local-tree packing DI seam (tests only, no npm dependency needed to exercise the route):
134
- * defaults to createLocalTreeArchive(root, opts) plus a host-side read of the produced
135
- * archive file into an ArrayBuffer. Called ONCE per run, before lane fan-out, on the live
136
- * local-tree route; the result (archive metadata + bytes) is shared byte-identically across
137
- * every fan-out lane, so one archiveSha256 describes every lane's packed content.
138
- */
139
- packLocalTree?: (args: {
140
- root: string;
141
- extraExclude?: string[];
142
- maxArchiveBytes?: number;
143
- }) => Promise<{
144
- archive: LocalTreeArchive;
145
- buffer: ArrayBuffer;
146
- }>;
147
- }
148
34
  /**
149
35
  * What a computer-use run takes besides its plan and config. The count override and rerun go to
150
36
  * participant building with the config.
151
37
  */
152
38
  export type ComputerUseRunInput = Omit<RunCuaActorLabOptions, "config" | "dryRun" | "lab">;
39
+ /**
40
+ * What runLab's local VM study gives a computer-use run: the desktop each participant runs on, the
41
+ * reason automatic analysis must not run (the study's cleanup is unconfirmed), and the signal its
42
+ * sessions abort on.
43
+ */
44
+ export interface LocalVmInput {
45
+ readonly desktop: ParticipantDesktopFactory;
46
+ /** The skip reason automatic analysis records instead of running, or undefined to run it. */
47
+ readonly analysisRefusal: () => AutomaticAnalysisRefusal | undefined;
48
+ readonly signal?: AbortSignal;
49
+ }
153
50
  export interface RunCuaActorLabOptions {
154
- automaticAnalysis?: AutomaticAnalysisHooks;
51
+ /** Cancels post-run analysis only. */
52
+ analysisSignal?: AbortSignal;
155
53
  cwd: string;
156
54
  config: LabConfig;
157
- /** Which manifest produced this run (#455); threaded into the run's status record + bundle. */
158
- lab?: RunLabProvenance;
159
55
  /** Resolved upstream (scenario.mode + CLI override); defaults safe (dry-run). */
160
56
  dryRun: boolean;
161
57
  open?: boolean;
162
58
  runId?: string;
163
- /** CLI `--count` override for the homogeneous fan-out lane count (ignored when a `lanes`
59
+ /** CLI `--count` override for the homogeneous fan-out participant count (ignored when a `lanes`
164
60
  * roster is declared — a roster's length is authoritative). */
165
61
  countOverride?: number;
166
- /** Explicitly create a new run containing failed or selected lanes from a prior fan-out run. */
62
+ /** Explicitly create a new run containing failed or selected participants from a prior fan-out run. */
167
63
  rerun?: {
168
64
  sourceRunId: string;
169
- laneIds?: string[];
65
+ participantIds?: string[];
170
66
  };
171
- hooks?: CuaActorLabHooks;
67
+ /** Keys and subject env for the run. Defaults to process.env. */
68
+ env?: Readonly<Record<string, string | undefined>>;
69
+ /** E2B only. Runs on each participant's desktop after it exists and before provisioning. */
70
+ prepareDesktop?: NonNullable<RunLabHomes["prepareDesktop"]>;
71
+ /** runLab's local VM study, for an app-url lab on the local target. */
72
+ localVm?: LocalVmInput;
172
73
  onObserverReady?: (observer: ObserverResult & {
173
74
  ok: true;
174
75
  }) => Promise<void> | void;
175
- /** Present only when the browser-route scorer hooks were CONFIG-DECLARED and loaded by the CLI
176
- * (#316); core-stamped onto the bundle as evidence. Absent for library callers. */
76
+ /** Awaited after a participant's live stream starts, and again after its sandbox is gone. */
77
+ onStream?: NonNullable<RunLabHomes["onStream"]>;
78
+ /** The caller's brain for each participant, in place of the lab's own. */
79
+ createProvider?: ProviderFactory;
80
+ /** Drives an app-url or local-app subject in this process, with no desktop. Needs createProvider. */
81
+ inProcess?: InProcessDriver;
82
+ /** Reports the plan and subject phases to onEvent; built by normalizeRunLabOptions. */
83
+ emit?: (event: LabEvent) => void;
84
+ /** Test seams. */
85
+ deps?: LabDeps;
86
+ /** Scores the assembled evidence: `RunLabOptions.scorer`, or the scorer the CLI loads. */
87
+ scorer?: BrowserScorer;
88
+ /** Present only when the scorer was CONFIG-DECLARED and loaded by the CLI (#316);
89
+ * core-stamped onto the bundle as evidence. Absent for library callers. */
177
90
  scorerProvenance?: RunScorerProvenance;
178
91
  }
179
- /** A lane's row in the pre-flight plan: identity + the device/persona it will drive. The prompt
92
+ /** A participant's row in the pre-flight plan: identity + the device/persona it will drive. The prompt
180
93
  * text never leaks — only a sha256-16 digest of the composed instructions. */
181
94
  export interface CuaParticipantPlanEntry {
182
95
  id: string;
@@ -190,14 +103,14 @@ export interface CuaParticipantPlanEntry {
190
103
  /** Requested E2B/X screen resolution. This is not the measured browser CSS viewport. */
191
104
  resolution: [number, number];
192
105
  instructionDigest: string;
193
- /** The declared reasoning effort for this lane, when the lab declared one. The plan line is what
194
- * you read BEFORE spending money, so a declared per-lane difference has to be visible there. */
106
+ /** The declared reasoning effort for this participant, when the lab declared one. The plan line is what
107
+ * you read BEFORE spending money, so a declared per-participant difference has to be visible there. */
195
108
  reasoningEffort?: string;
196
109
  maxOutputTokens?: number;
197
- /** Present only when a lane overrides subject.appUrl; digest avoids leaking preview hosts in plan logs. */
110
+ /** Present only when a participant overrides subject.appUrl; digest avoids leaking preview hosts in plan logs. */
198
111
  targetDigest?: string;
199
112
  }
200
- /** The pre-flight spend/lane plan (pure; printed to stderr + recorded as a bundle event before
113
+ /** The pre-flight spend and participant plan (pure; printed to stderr + recorded as a bundle event before
201
114
  * any sandbox or provider call; identical in dry-run, marked $0). */
202
115
  export interface CuaParticipantPlan {
203
116
  strategy: typeof CUA_FANOUT_STRATEGY;
@@ -210,16 +123,16 @@ export interface CuaParticipantPlan {
210
123
  envLoweredConcurrencyFrom?: number;
211
124
  /** ceil(laneCount / concurrency). */
212
125
  waves: number;
213
- /** Per-lane session wall-clock budget (execution.timeoutMs); there is no run-level wall clock. */
126
+ /** Per-participant session wall-clock budget (execution.timeoutMs); there is no run-level wall clock. */
214
127
  perLaneSessionBudgetMs: number;
215
- /** Worst-case TOTAL sandbox-minutes across all lanes (each lane's full sandbox deadline). */
128
+ /** Worst-case TOTAL sandbox-minutes across all participants (each one's full sandbox deadline). */
216
129
  worstCaseSandboxMinutes: number;
217
130
  /** True for a dry-run plan (no spend); the same table appears live. */
218
131
  dryRun: boolean;
219
132
  lanes: CuaParticipantPlanEntry[];
220
133
  }
221
- /** One lane's outcome in the result projection. ALWAYS present in `result.lanes` (length 1 at
222
- * N=1). A `blocked` lane is one the pipeline-gate / fail-fast skipped before it ran. */
134
+ /** One participant's outcome in the result projection. ALWAYS present in `result.lanes` (length
135
+ * 1 at N=1). A `blocked` participant is one the pipeline-gate / fail-fast skipped before it ran. */
223
136
  export interface CuaParticipantResult {
224
137
  id: string;
225
138
  actorType?: string;
@@ -230,7 +143,7 @@ export interface CuaParticipantResult {
230
143
  device: string;
231
144
  /** Requested E2B/X screen resolution. See the run stream's desktopGeometry for measurements. */
232
145
  resolution: [number, number];
233
- /** Terminal lane status; "blocked" = skipped (gate/fail-fast); "contract_proof_only" = dry-run. */
146
+ /** Terminal participant status; "blocked" = skipped (gate/fail-fast); "contract_proof_only" = dry-run. */
234
147
  status: ActorStatus | "blocked" | "contract_proof_only";
235
148
  ok: boolean;
236
149
  session?: {
@@ -248,29 +161,29 @@ export interface CuaParticipantResult {
248
161
  };
249
162
  subject: CuaSubjectProjection;
250
163
  diagnostics?: CuaDiagnostics;
251
- /** Set when the lane was skipped (pinned reason string). */
164
+ /** Set when the participant was skipped (pinned reason string). */
252
165
  skippedReason?: string;
253
166
  error?: {
254
167
  code: CuaActorLabErrorCode;
255
168
  message: string;
256
169
  };
257
170
  }
258
- /** Aggregate counts across lanes. */
171
+ /** Aggregate counts across participants. */
259
172
  export interface CuaParticipantSummary {
260
173
  strategy: typeof CUA_FANOUT_STRATEGY;
261
174
  total: number;
262
- /** Lanes whose own verdict is ok (terminal, engaged, no harness error). */
175
+ /** Participants whose own verdict is ok (terminal, engaged, no harness error). */
263
176
  passed: number;
264
- /** Lanes skipped by the pipeline gate / fail-fast. */
177
+ /** Participants skipped by the pipeline gate / fail-fast. */
265
178
  skipped: number;
266
- /** Lanes that ended in a harness error. */
179
+ /** Participants that ended in a harness error. */
267
180
  harnessErrors: number;
268
- /** Lanes that returned goal_satisfied with zero engagement (hollow). */
181
+ /** Participants that returned goal_satisfied with zero engagement (hollow). */
269
182
  hollow: number;
270
183
  concurrency: number;
271
184
  waves: number;
272
185
  }
273
- export type CuaActorLabErrorCode = "HUMANISH_LAB_ANALYSIS_INVALID" | "HUMANISH_LAB_TASKS_UNSUPPORTED" | "HUMANISH_LAB_OPTION_CONFLICT" | "HUMANISH_LAB_OPTION_UNSUPPORTED" | "HUMANISH_CUA_LAB_FAILED" | "HUMANISH_CUA_LAB_KEYS_MISSING" | "HUMANISH_CUA_LAB_AGENT_MISSING" | "HUMANISH_CUA_LAB_AGENT_SIGNIN_REQUIRED" | "HUMANISH_CUA_LAB_SUBJECT_ENV_MISSING" | "HUMANISH_CUA_LAB_ACTOR_UNSUPPORTED" | "HUMANISH_CUA_LAB_SUBJECT_INVALID" | "HUMANISH_CUA_LAB_SUBJECT_UNSAFE" | "HUMANISH_CUA_LAB_EXECUTOR_NO_PROVIDER" | "HUMANISH_CUA_LAB_LOCAL_APP_NO_EXECUTOR" | "HUMANISH_CUA_LAB_LOCAL_DESKTOP_MISSING" | "HUMANISH_CUA_LAB_FANOUT_INVALID" | "HUMANISH_CUA_LAB_RERUN_INVALID" | "HUMANISH_CUA_LAB_DEVICE_GEOMETRY" | "HUMANISH_RUN_ID_IN_USE" | "HUMANISH_CUA_LAB_UNPRICED_CAP" | "HUMANISH_CUA_LAB_COMMS_CATCH_UNREACHABLE" | "HUMANISH_WATCH_ALLOW_REQUIRES_OAUTH" | "HUMANISH_WATCH_OAUTH_REQUIRES_TUNNEL" | "HUMANISH_WATCH_OPTION_CONFLICT" | "HUMANISH_WATCH_TUNNEL_REQUIRES_EXPOSE" | "HUMANISH_WATCH_EXPOSE_REQUIRES_EDGE_AUTH" | "HUMANISH_WATCH_EXPOSE_REQUIRES_LIVE_FOLLOW" | "HUMANISH_WATCH_SAFE_NOT_APPLICABLE" | "HUMANISH_SERVE_TUNNEL_NOT_FOUND" | "HUMANISH_SERVE_TUNNEL_START_FAILED";
186
+ export type CuaActorLabErrorCode = "HUMANISH_LAB_ANALYSIS_INVALID" | "HUMANISH_LAB_TASKS_UNSUPPORTED" | "HUMANISH_LAB_OPTION_UNSUPPORTED" | "HUMANISH_CUA_LAB_FAILED" | "HUMANISH_CUA_LAB_KEYS_MISSING" | "HUMANISH_CUA_LAB_AGENT_MISSING" | "HUMANISH_CUA_LAB_AGENT_SIGNIN_REQUIRED" | "HUMANISH_CUA_LAB_SUBJECT_ENV_MISSING" | "HUMANISH_CUA_LAB_ACTOR_UNSUPPORTED" | "HUMANISH_CUA_LAB_SUBJECT_INVALID" | "HUMANISH_CUA_LAB_SUBJECT_UNSAFE" | "HUMANISH_CUA_LAB_EXECUTOR_NO_PROVIDER" | "HUMANISH_CUA_LAB_LOCAL_APP_NO_EXECUTOR" | "HUMANISH_CUA_LAB_LOCAL_DESKTOP_MISSING" | "HUMANISH_CUA_LAB_FANOUT_INVALID" | "HUMANISH_CUA_LAB_RERUN_INVALID" | "HUMANISH_CUA_LAB_DEVICE_GEOMETRY" | "HUMANISH_RUN_ID_IN_USE" | "HUMANISH_CUA_LAB_UNPRICED_CAP" | "HUMANISH_CUA_LAB_COMMS_CATCH_UNREACHABLE" | "HUMANISH_CUA_LAB_COMMS_TOKEN_INVALID" | "HUMANISH_WATCH_ALLOW_REQUIRES_OAUTH" | "HUMANISH_WATCH_OAUTH_REQUIRES_TUNNEL" | "HUMANISH_WATCH_OPTION_CONFLICT" | "HUMANISH_WATCH_TUNNEL_REQUIRES_EXPOSE" | "HUMANISH_WATCH_EXPOSE_REQUIRES_EDGE_AUTH" | "HUMANISH_WATCH_EXPOSE_REQUIRES_LIVE_FOLLOW" | "HUMANISH_WATCH_SAFE_NOT_APPLICABLE" | "HUMANISH_SERVE_TUNNEL_NOT_FOUND" | "HUMANISH_SERVE_TUNNEL_START_FAILED";
274
187
  /** Subject provenance projection (invariant 5): what the actor actually drove. */
275
188
  export interface CuaSubjectProjection {
276
189
  source: "app-url" | "clone" | "local-tree";
@@ -310,7 +223,7 @@ export type CuaSubjectProvenanceArg = {
310
223
  };
311
224
  export interface CuaActorLabResult extends AutomaticAnalysisResult {
312
225
  schema: typeof CUA_ACTOR_LAB_SCHEMA;
313
- /** True when the Observer verified the bundle, all live lanes passed credibility checks
226
+ /** True when the Observer verified the bundle, all live participants passed credibility checks
314
227
  * (or this is a dry-run), and no declared adapter/scorer verdict failed. */
315
228
  ok: boolean;
316
229
  cwd: string;
@@ -336,15 +249,15 @@ export interface CuaActorLabResult extends AutomaticAnalysisResult {
336
249
  streamUrlPresent: boolean;
337
250
  };
338
251
  /** Subject provenance (invariant 5): what the actor actually drove. At N>1 this is the
339
- * unanimity-gated aggregate (top-level `commit` only when every lane resolved the same one). */
252
+ * unanimity-gated aggregate (top-level `commit` only when every participant resolved the same one). */
340
253
  subject?: CuaSubjectProjection;
341
- /** The pre-flight lane plan (present once lanes resolve; absent on early validation errors). */
254
+ /** The pre-flight participant plan (present once participants resolve; absent on early validation errors). */
342
255
  plan?: CuaParticipantPlan;
343
- /** Per-lane results — ALWAYS present once lanes resolve (length 1 at N=1). */
256
+ /** Per-participant results — ALWAYS present once participants resolve (length 1 at N=1). */
344
257
  lanes?: CuaParticipantResult[];
345
- /** Aggregate lane counts. */
258
+ /** Aggregate participant counts. */
346
259
  laneSummary?: CuaParticipantSummary;
347
- /** Present when this run explicitly re-executes selected lanes from a prior CUA fan-out run. */
260
+ /** Present when this run explicitly re-executes selected participants from a prior CUA fan-out run. */
348
261
  rerun?: RunRerunLineage;
349
262
  observer?: ObserverResult;
350
263
  diagnostics?: CuaDiagnostics;
@@ -355,7 +268,7 @@ export interface CuaActorLabResult extends AutomaticAnalysisResult {
355
268
  };
356
269
  }
357
270
  /**
358
- * What a computer-use lane or a shared-world seat runs: the resolved participant, plus where its
271
+ * What a computer-use or shared-world participant runs: the resolved participant, plus where its
359
272
  * evidence goes and any backstop override its route sets. The public projections are
360
273
  * CuaParticipantPlanEntry and CuaParticipantResult.
361
274
  */
@@ -380,59 +293,57 @@ export interface ParticipantRunsAndPlan {
380
293
  participantPlan: CuaParticipantPlan;
381
294
  }
382
295
  /**
383
- * The STUDY's shared spend ledger (#299): one counter across every lane. Each lane notes its own
384
- * latest running MODEL-spend estimate (monotone per lane — an estimate can only grow) and reads
385
- * back the run total; the loop stops the lane the moment the total crosses the study budget.
296
+ * The STUDY's shared spend ledger (#299): one counter across every participant. Each one notes its
297
+ * own latest running MODEL-spend estimate (monotone per participant — an estimate can only grow)
298
+ * and reads back the run total; the loop stops the participant the moment the total crosses the study budget.
386
299
  * Estimated model spend only: desktop-minutes ride the cost summary, not this ledger.
387
300
  */
388
301
  export interface CuaRunBudget {
389
302
  maxTotalUsd: number;
390
- /** Record this lane's latest running estimate (null = unpriceable, ignored) and return the
391
- * run's current total across all lanes. */
303
+ /** Record this participant's latest running estimate (null = unpriceable, ignored) and return
304
+ * the run's current total across all participants. */
392
305
  note(participantId: string, estimateUsd: number | null): number;
393
306
  }
394
- /** Shared deps every lane runner needs (resolved once in the engine). */
395
- export interface CuaParticipantDeps {
396
- /** Internal ready-desktop seam. The factory must not allocate; prepare owns that work. */
397
- createDesktop?: (spec: DesktopParticipantRun, warnings: string[], artifactRoot: PreparedOutputRoot) => ParticipantDesktop;
398
- config: LabConfig;
399
- descriptor: CuaActorDescriptor;
307
+ /**
308
+ * The subject as a participant's desktop meets it. A computer-use participant gets the plan's
309
+ * subject: a clone or local tree is provisioned in its own sandbox with the declared env, a
310
+ * desktop-cli product is set up there, and an app-url or local-app subject is only opened. A
311
+ * shared-world seat gets `shared-app`: it opens the one app the plane serves, with no subject env
312
+ * names forwarded, no GitHub token and no provisioning in its sandbox.
313
+ */
314
+ export type ParticipantSubject = ComputerUseRunner["subject"] | {
315
+ readonly kind: "shared-app";
316
+ /** The shared app's in-sandbox serve URL, which the receiving inbox maps links back to. */
317
+ readonly serveUrl?: string;
318
+ };
319
+ /** The subject env names forwarded into a participant's sandbox: a provisioned subject's only. */
320
+ export declare function participantSubjectEnv(subject: ParticipantSubject): readonly string[];
321
+ /** The serve URL a participant's inbox maps links back to: the served app's, when there is one. */
322
+ export declare function participantServeUrl(subject: ParticipantSubject): string | undefined;
323
+ /** What the E2B desktop (e2b-desktop/*) reads from a participant's deps. */
324
+ export interface E2BDesktopDeps {
325
+ /** The plan's residual config: comms, policies, the desktop and target, and subject leftovers. */
326
+ residual: Readonly<ResidualConfig>;
327
+ labId: string;
400
328
  appUrl: string;
401
- /** When set, the computer-use brain is this locally-signed-in CLI instead of a keyed API. */
402
- localAgent?: LocalAgentId;
403
- cloneRoute: boolean;
404
- /** desktop-cli (#495): a CLI studied at a desktop. Nothing is cloned and no browser is opened. */
405
- desktopCliRoute?: boolean;
406
- /** Optional so out-of-scope callers building CuaParticipantDeps directly (other engines reusing
407
- * runCuaParticipant) do not need to know about the local-tree route; undefined behaves as false. */
408
- localTreeRoute?: boolean;
409
- serve?: LabSubjectServe;
410
- subjectRepo?: string;
411
- subjectEnvNames: string[];
412
- hasGithubToken: boolean;
329
+ /** What the participant's desktop does with the subject before the participant starts. */
330
+ subject: ParticipantSubject;
413
331
  /** Local-tree route only: the once-per-run packed archive bytes, shared byte-identically
414
- * across every fan-out lane's upload step. Absent on dry-run and every other route. */
332
+ * across every fan-out participant's upload step. Absent on dry-run and every other route. */
415
333
  localTreeArchiveBuffer?: ArrayBuffer;
416
334
  env: Record<string, string | undefined>;
417
- openaiApiKey: string;
418
335
  e2bApiKey: string;
419
336
  requestTimeoutMs: number;
420
337
  sandboxMs: number;
421
- timeoutMs: number;
422
338
  participantCount: number;
423
339
  artifactRoot: PreparedOutputRoot;
424
340
  /** The lab's resolution directory: relative paths in the config (a camera .y4m) resolve here. */
425
341
  labCwd: string;
426
- redactScreenshots: boolean;
427
342
  scrubKnownValues: (text: string) => string;
428
343
  receiving?: CommsReceivingRun;
429
- runSession: (options: CuaActorSessionOptions) => Promise<CuaLoopResult>;
430
- /** The study's shared spend ledger, present exactly when execution.caps.maxTotalUsd is set on a
431
- * live run (#299). Preflight already refused the cap on an unpriced model. */
432
- runBudget?: CuaRunBudget;
433
344
  /** Adopter-hosted comms plane (#380): present on the app-url route when comms.email.external is
434
- * declared. Carries the parsed comms block (recipients drive the per-lane inbox instruction)
435
- * and the inbox URL the persona opens. The drain runs once at run level, not per lane. */
345
+ * declared. Carries the parsed comms block (recipients drive the per-participant inbox instruction)
346
+ * and the inbox URL the persona opens. The drain runs once at run level, not per participant. */
436
347
  externalComms?: {
437
348
  email: LabCommsEmail;
438
349
  inboxUrl: string;
@@ -440,19 +351,45 @@ export interface CuaParticipantDeps {
440
351
  /** Injected clock (ms). Used to measure the host-side E2B desktop create->teardown span so the
441
352
  * desktop-minute cost estimate is deterministic in tests. Defaults to Date.now. */
442
353
  now: () => number;
443
- hooks: CuaActorLabHooks;
444
- /** Lane-0 only: signal the pipeline gate after provisioning succeeds (true) or fails (false). */
445
- signalProvisioned?: (ok: boolean) => void;
354
+ /** Loads the E2B SDK for the participant's desktop. Defaults to loadE2BDesktopModule. */
355
+ desktopModule?: () => Promise<E2BDesktopModule>;
356
+ /** The caller's prepareDesktop, called with the participant as its target. */
357
+ prepareDesktop?: NonNullable<RunLabHomes["prepareDesktop"]>;
358
+ /** Clock and sleep for detached provisioning steps. */
359
+ detachedTimers?: DetachedTimers;
360
+ /** Receives each live stream's ready and ended: the Observer's tracker, then the caller's onStream. */
361
+ onStream: NonNullable<RunLabHomes["onStream"]>;
362
+ /** Reports a subject phase to the phase sink (stderr by default) and to onEvent. */
363
+ reportSubjectPhase: (event: SubjectPhaseEvent, participant: PhaseParticipant) => void;
446
364
  /**
447
365
  * How a PARSEABLE requested-vs-verified screen mismatch is treated. Default ("fail-closed"):
448
- * the lane's device claim is falsified, so the lane fails with DEVICE_GEOMETRY (the
449
- * single-lane/fan-out contract). "record-evidence" (the concurrent shared-world route):
366
+ * the participant's device claim is falsified, so it fails with DEVICE_GEOMETRY (the
367
+ * single-participant/fan-out contract). "record-evidence" (the concurrent shared-world route):
450
368
  * requested and verified stay recorded as separate facts plus an explicit warning, and the
451
- * lane keeps running, so one seat's screen drift cannot abort a live multi-actor world.
369
+ * participant keeps running, so one participant's screen drift cannot abort a live multi-actor world.
452
370
  */
453
371
  screenMismatchPolicy?: "fail-closed" | "record-evidence";
372
+ }
373
+ /** What a participant's model and session (participant-model.ts) read from its deps. */
374
+ export interface ParticipantModelDeps {
375
+ /** The caller's createProvider with the run's config bound. Absent, the plan's brain drives. */
376
+ createProvider?: (participant: ParticipantRef, executor: CuaExecutor) => Promise<CuaProvider>;
377
+ /** The plan's spend caps; maxUsd is each participant's own. */
378
+ caps: ComputerUsePlan["caps"];
379
+ /** The plan's brain: the model and, for a local agent, which signed-in CLI drives the participant. */
380
+ brain: Brain;
381
+ env: Record<string, string | undefined>;
382
+ openaiApiKey: string;
383
+ timeoutMs: number;
384
+ participantCount: number;
385
+ artifactRoot: PreparedOutputRoot;
386
+ redactScreenshots: boolean;
387
+ scrubKnownValues: (text: string) => string;
388
+ /** The study's shared spend ledger, present exactly when execution.caps.maxTotalUsd is set on a
389
+ * live run (#299). Preflight already refused the cap on an unpriced model. */
390
+ runBudget?: CuaRunBudget;
454
391
  /**
455
- * RUNTIME-ONLY observed-URL callback (#164 handoff crux): threaded into the lane's session so the
392
+ * RUNTIME-ONLY observed-URL callback (#164 handoff crux): threaded into the participant's session so the
456
393
  * orchestrator watches this seat's live location.href mid-run. Never persisted (see
457
394
  * CuaLoopOptions.onObservedUrl). The concurrent shared-world barrier passes a host-seat latch here
458
395
  * to extract a /lobby/CODE; on ordinary routes it is undefined (no-op).
@@ -468,7 +405,27 @@ export interface CuaParticipantDeps {
468
405
  * wires the incremental in-progress flush here so the attached Observer's timeline grows mid-run. */
469
406
  onTrace?: (participantId: string, items: readonly ActorTraceItem[], usage?: ActorTokenUsage, metadata?: CuaLiveMetadata) => void;
470
407
  }
471
- /** One lane's end-to-end run outcome (internal; projected into CuaParticipantResult + the bundle). */
408
+ /**
409
+ * One participant's deps: the E2B desktop's and the model's, and what runCuaParticipant reads to
410
+ * choose the desktop and run the session. setup.ts and shared-world participant-specs.ts build it.
411
+ */
412
+ export type CuaParticipantDeps = E2BDesktopDeps & ParticipantModelDeps & {
413
+ /** Internal ready-desktop seam. The factory must not allocate; prepare owns that work. */
414
+ createDesktop?: (spec: DesktopParticipantRun, warnings: string[], artifactRoot: PreparedOutputRoot) => ParticipantDesktop;
415
+ /** The caller's inProcess executor with the run's config bound. Read by the in-process desktop. */
416
+ inProcessExecutor?: (appUrl: string) => Promise<CuaExecutor>;
417
+ runSession: (options: CuaActorSessionOptions) => Promise<CuaLoopResult>;
418
+ /** Lane-0 only: signal the pipeline gate after provisioning succeeds (true) or fails (false). */
419
+ signalProvisioned?: (ok: boolean) => void;
420
+ };
421
+ /** Why a sandbox was not confirmed released. */
422
+ export interface SandboxReleaseFact {
423
+ state: "retained" | "unconfirmed";
424
+ warning: string;
425
+ /** How to release it by hand, when `humanish reclaim` cannot: a local VM has no receipt. */
426
+ recovery?: string;
427
+ }
428
+ /** One participant's end-to-end run outcome (internal; projected into CuaParticipantResult + the bundle). */
472
429
  export interface ParticipantRunOutcome {
473
430
  spec: DesktopParticipantRun;
474
431
  session?: CuaLoopResult;
@@ -477,6 +434,9 @@ export interface ParticipantRunOutcome {
477
434
  /** The model provider's cleanup is unconfirmed after the session. An execution failure only:
478
435
  * it does not change how the participant's session ended. */
479
436
  providerCleanupError?: string;
437
+ /** The model provider reported a disallowed operation after the session's last request, which
438
+ * the session's evidence does not show. An execution failure, scrubbed, like the cleanup one. */
439
+ providerPolicyError?: string;
480
440
  sandboxId?: string;
481
441
  /** Host-side E2B desktop create->teardown span (ms). An APPROXIMATION of E2B's server-side
482
442
  * billed lifetime (server-side kill-on-timeout can extend it) — so the derived dollar figure is
@@ -484,6 +444,9 @@ export interface ParticipantRunOutcome {
484
444
  desktopDurationMs?: number;
485
445
  desktopResources?: DesktopResourceObservation;
486
446
  killed: boolean;
447
+ /** Set when the sandbox was not confirmed released: kept for debugging, or a release the
448
+ * provider did not confirm. `warning` is the scrubbed release warning. */
449
+ sandboxRelease?: SandboxReleaseFact;
487
450
  streamUrlPresent: boolean;
488
451
  screenshots: string[];
489
452
  subjectCommit?: string;
@@ -496,44 +459,39 @@ export interface ParticipantRunOutcome {
496
459
  * folded into bundle.events at build time. Empty on the in-process route (no provisioning). */
497
460
  phaseRecords: SubjectPhaseEvent[];
498
461
  warnings: string[];
499
- /** Set when the lane was skipped by the pipeline gate / fail-fast (a pinned reason). */
462
+ /** Set when the participant was skipped by the pipeline gate / fail-fast (a pinned reason). */
500
463
  skippedReason?: string;
501
464
  noEngagement: boolean;
502
465
  selfReportedBlocker: boolean;
503
466
  /** The inclusive friction read (#453): blocker-shaped narration incl. self-resolved arcs.
504
- * Feeds the participants tally and feedback candidates; never the lane verdict. Optional so
467
+ * Feeds the participants tally and feedback candidates; never the participant verdict. Optional so
505
468
  * external outcome constructors (shared-world, test fakes) stay valid; absent counts as false. */
506
469
  reportedFriction?: boolean;
507
470
  harnessError: boolean;
508
471
  failureCode?: CuaActorLabErrorCode;
509
- /** Relative run-dir path of the digest-only comms-thread evidence artifact this lane wrote
472
+ /** Relative run-dir path of the digest-only comms-thread evidence artifact this participant wrote
510
473
  * (humanish.comms-thread.v1), when a comms lab captured mail into its in-sandbox catch. Registered
511
- * in the lane's stream artifacts. Absent when no comms lab ran or nothing was captured. */
474
+ * in the participant's stream artifacts. Absent when no comms lab ran or nothing was captured. */
512
475
  commsArtifactPath?: string;
513
476
  }
514
477
  /** What buildCuaFanoutBundle projects into a fan-out run bundle. */
515
478
  export interface CuaFanoutBundleArgs {
516
479
  /** The run's verdict, from the judge. */
517
480
  verdict: Verdict;
518
- /** Lab provenance for the bundle's own `lab` field (#455). */
519
- lab?: RunLabProvenance;
481
+ /** The run this bundle belongs to; the bundle head reads its id, mode, start and lab. */
482
+ run: BundleRun;
520
483
  specs: DesktopParticipantRun[];
521
484
  outcomes?: ParticipantRunOutcome[];
522
485
  subjects: CuaSubjectProjection[];
523
486
  aggregateSubject: CuaSubjectProjection;
524
487
  descriptor: CuaActorDescriptor;
525
488
  appUrl: string;
526
- createdAt: string;
527
489
  dryRun: boolean;
528
490
  plan: ComputerUsePlan;
529
- runId: string;
530
491
  source: RunBundle["source"];
531
492
  participantPlan: CuaParticipantPlan;
532
493
  rerun?: RunRerunLineage;
533
494
  failFastReason?: string;
534
- cloneRoute: boolean;
535
- localTreeRoute?: boolean;
536
495
  publicRepo?: string;
537
- subjectEnvNames: string[];
538
496
  inProgress?: boolean;
539
497
  }
@@ -7,16 +7,13 @@ import {} from "../../substrates/e2b/sdk.js";
7
7
  import {} from "../../substrates/e2b/desktop-resources.js";
8
8
  import {} from "../../substrates/detached.js";
9
9
  import {} from "../../lab/types.js";
10
- import {} from "../../actors/local-agent/cli.js";
11
- import { renderObserver } from "../../observer/render.js";
12
- import {} from "../../run/status.js";
10
+ import {} from "../../observer/render.js";
13
11
  import {} from "../../run/bundle.js";
14
12
  import {} from "../../run/streams.js";
15
13
  import {} from "../../run/contained-output.js";
16
- import {} from "../../subject/local-tree-archive.js";
17
14
  export const CUA_ACTOR_LAB_SCHEMA = "humanish.cua-lab-result.v2";
18
- // The only fan-out topology this slice ships: N lanes = N independent E2B desktop sandboxes,
19
- // each its own world (clone/serve + subject.state per lane). Shared-world is layer 7 (#164).
15
+ // The only fan-out topology this slice ships: N participants = N independent E2B desktop
16
+ // sandboxes, each its own world (clone/serve + subject.state per participant). Shared-world is layer 7 (#164).
20
17
  export const CUA_FANOUT_STRATEGY = "per-lane-worlds";
21
18
  // Env override that may only LOWER the effective concurrency (never raise concurrent paid
22
19
  // desktops — invariant 3). Read names-only into a local; the value never persists.
@@ -35,3 +32,13 @@ export const CUA_MAX_CONCURRENCY_ENV = "HUMANISH_CUA_MAX_CONCURRENCY";
35
32
  // adjusted: when it cannot be provisioned, the plan-time cap refusal shows the arithmetic.
36
33
  export const DEFAULT_APP_URL_SESSION_TIMEOUT_MS = 30 * 60_000;
37
34
  export const MIN_DERIVED_SESSION_TIMEOUT_MS = 5 * 60_000;
35
+ /** The subject env names forwarded into a participant's sandbox: a provisioned subject's only. */
36
+ export function participantSubjectEnv(subject) {
37
+ return subject.kind === "clone" || subject.kind === "local-tree" ? subject.env : [];
38
+ }
39
+ /** The serve URL a participant's inbox maps links back to: the served app's, when there is one. */
40
+ export function participantServeUrl(subject) {
41
+ if (subject.kind === "clone" || subject.kind === "local-tree")
42
+ return subject.serve.url;
43
+ return "serveUrl" in subject ? subject.serveUrl : undefined;
44
+ }