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
@@ -1,6 +1,7 @@
1
1
  // Builds each participant's actor spec and mission, resolves its entry URL, derives the session
2
2
  // and sandbox time budgets, and records a follower that never received the host's lobby code.
3
- import { DEFAULT_OPENAI_CU_MODEL } from "../../actors/computer-use/openai-provider.js";
3
+ import { defaultSubjectPhaseSink } from "../../subject/steps.js";
4
+ import { pricedModel } from "../../lab/plan-base.js";
4
5
  import { scrubPersonaBrief } from "../../lab/persona.js";
5
6
  import { resolveParticipant } from "../../run/participant.js";
6
7
  import { attachObserverRuntimeStreamUrls } from "../../observer/render.js";
@@ -11,11 +12,11 @@ import { participantAssignment } from "../../lab/participant-assignment.js";
11
12
  import { redactText } from "../../evidence/redaction.js";
12
13
  import { MAX_SANDBOX_MS, SANDBOX_TIMEOUT_BUFFER_MS, SUBJECT_PROVISION_BUDGET_MS, } from "../../substrates/e2b/lifetime.js";
13
14
  import { DEFAULT_STATE_STEP_TIMEOUT_MS } from "../../subject/state.js";
14
- // The DEFAULT per-seat session budget is DERIVED, not flat. On a provisioned route the binding
15
- // constraint is the SUBJECT sandbox (it must outlive every seat: timeoutMs + provisioning +
15
+ // The default per-seat session budget is derived from the route. On a provisioned route the binding
16
+ // constraint is the subject sandbox (it must outlive every seat: timeoutMs + provisioning +
16
17
  // seeding + teardown buffer, and E2B refuses a sandbox over one hour), so the derivation hands
17
18
  // each seat the most that cap allows — capped at 15 minutes, floored at the historical 300s so a
18
- // seed-heavy lab never gets LESS room than it always had. App-url seats have no subject sandbox
19
+ // seed-heavy lab never gets less room than it always had. App-url seats have no subject sandbox
19
20
  // and default to 30 minutes (seat sandbox: 30m + 10m buffer stays well under the hour). An
20
21
  // explicit execution.timeoutMs is never adjusted. The handoff latch scales off this (40%).
21
22
  const MAX_DERIVED_SESSION_MS = 15 * 60_000;
@@ -74,9 +75,9 @@ function buildActorSpec(participant, personas) {
74
75
  traceArtifactPath: `actors/${run.streamId}.json`,
75
76
  };
76
77
  }
77
- /** Thread the host-yielded lobby CODE into a follower's mission at runtime (external-public route).
78
- * The CODE flows into the follower's join instruction; it is persisted only as the composed prompt
79
- * the model reads (never a raw bundle field), and the lab scrubs the CODE from all narration. The
78
+ /** Thread the host-yielded lobby code into a follower's mission at runtime (external-public route).
79
+ * The code flows into the follower's join instruction; it is persisted only as the composed prompt
80
+ * the model reads (never a raw bundle field), and the lab scrubs the code from all narration. The
80
81
  * follower joins through the real UI (a direct /lobby/CODE visit does not auto-join a non-member). */
81
82
  export function withLobbyCodeMission(spec, code) {
82
83
  return {
@@ -111,58 +112,46 @@ export function startParticipantFlush(ctx, live, bundle) {
111
112
  live.flush = startLiveTraceFlush({
112
113
  bundle,
113
114
  participantRuns: ctx.actorSpecs,
114
- model: ctx.config.actors[0]?.model ?? DEFAULT_OPENAI_CU_MODEL,
115
+ model: pricedModel(ctx.plan.brain),
115
116
  write: (snapshot) => ctx.run.writeSnapshot(snapshot),
116
117
  });
117
118
  }
118
119
  /**
119
- * The caller's desktop hooks, plus the runtime stream URLs each seat reports to the live Observer.
120
- * The Observer learns of a stream before the caller's stream hook runs.
120
+ * The runtime stream URLs each seat reports to the live Observer. The Observer learns of a stream
121
+ * before the caller's onStream runs.
121
122
  */
122
- function runtimeStreamHooks(hooks, live) {
123
- return {
124
- ...(hooks.loadDesktopModule ? { loadDesktopModule: hooks.loadDesktopModule } : {}),
125
- ...(hooks.detachedTimers ? { detachedTimers: hooks.detachedTimers } : {}),
126
- ...(hooks.env ? { env: hooks.env } : {}),
127
- ...(hooks.prepareDesktop
128
- ? {
129
- prepareDesktop: (desktop, participant) => hooks.prepareDesktop(desktop, participant),
130
- }
131
- : {}),
132
- onRuntimeStreamReady: (stream) => {
133
- live.streamUrls.push({ streamId: stream.streamId, url: stream.url });
134
- if (live.observer) {
135
- attachObserverRuntimeStreamUrls(live.observer, live.streamUrls);
136
- }
137
- return hooks.onRuntimeStreamReady?.(stream);
138
- },
139
- onRuntimeStreamEnded: (stream) => {
140
- // Mark, never remove (#357): the tile falls back to recorded evidence and says why.
141
- for (const entry of live.streamUrls) {
142
- if (entry.streamId === stream.streamId)
123
+ function participantStreams(onStream, live) {
124
+ return (event) => {
125
+ if (event.type === "ready")
126
+ live.streamUrls.push({ streamId: event.streamId, url: event.url });
127
+ // Mark, never remove (#357): the tile falls back to recorded evidence and says why.
128
+ else
129
+ for (const entry of live.streamUrls)
130
+ if (entry.streamId === event.streamId)
143
131
  entry.ended = true;
144
- }
145
- if (live.observer) {
146
- attachObserverRuntimeStreamUrls(live.observer, live.streamUrls);
147
- }
148
- return hooks.onRuntimeStreamEnded?.(stream);
149
- },
132
+ if (live.observer)
133
+ attachObserverRuntimeStreamUrls(live.observer, live.streamUrls);
134
+ return onStream?.(event);
150
135
  };
151
136
  }
152
137
  /**
153
- * The runner deps both planes give every participant. cloneRoute=false + subjectEnvNames=[] keep subject
154
- * creds out of every actor sandbox (FIX-10). `scrubKnownValues` is the plane's scrub: the
155
- * external-public plane also scrubs the latched lobby code.
138
+ * The runner deps both planes give every participant. The `shared-app` subject keeps three things
139
+ * out of every actor sandbox: the subject env names' values, the GitHub token, and clone
140
+ * or local-tree provisioning. The committed subject.envValues still reach it, non-secret by parse.
141
+ * `scrubKnownValues` is the plane's scrub: the external-public plane also scrubs the latched lobby
142
+ * code.
156
143
  */
157
144
  export function participantRunDeps(ctx, live, scrubKnownValues) {
158
- const { config, descriptor, env, receiving, runBudget } = ctx;
145
+ const { config, env, receiving, runBudget } = ctx;
159
146
  return {
160
147
  onTrace: (participantId, items, usage, metadata) => live.flush?.flush(participantId, items, usage, metadata),
161
- config,
162
- descriptor,
163
- cloneRoute: false,
164
- subjectEnvNames: [],
165
- hasGithubToken: false,
148
+ residual: ctx.plan.residual,
149
+ labId: ctx.plan.labId,
150
+ caps: ctx.plan.caps,
151
+ subject: {
152
+ kind: "shared-app",
153
+ ...(config.subject.serve?.url === undefined ? {} : { serveUrl: config.subject.serve.url }),
154
+ },
166
155
  env,
167
156
  openaiApiKey: ctx.openaiApiKey,
168
157
  e2bApiKey: ctx.e2bApiKey,
@@ -176,15 +165,21 @@ export function participantRunDeps(ctx, live, scrubKnownValues) {
176
165
  scrubKnownValues,
177
166
  runSession: ctx.runSession,
178
167
  // A local-agent brain runs each seat on the operator's signed-in agent, as on computer use.
179
- ...(ctx.plan.brain.kind === "local-agent" ? { localAgent: ctx.plan.brain.agent } : {}),
168
+ brain: ctx.plan.brain,
180
169
  ...(receiving ? { receiving } : {}),
181
170
  now: ctx.now,
182
- hooks: runtimeStreamHooks(ctx.hooks, live),
171
+ // The seat's desktop seams, and the caller's prepareDesktop with the seat as its target.
172
+ ...(ctx.deps.desktopModule === undefined ? {} : { desktopModule: ctx.deps.desktopModule }),
173
+ ...(ctx.deps.detachedTimers === undefined ? {} : { detachedTimers: ctx.deps.detachedTimers }),
174
+ ...(ctx.input.prepareDesktop === undefined ? {} : { prepareDesktop: ctx.input.prepareDesktop }),
175
+ onStream: participantStreams(ctx.input.onStream, live),
176
+ // A seat visits the shared app and provisions no subject, so it reports no phase of its own.
177
+ reportSubjectPhase: defaultSubjectPhaseSink,
183
178
  ...(runBudget === undefined ? {} : { runBudget }),
184
- // Concurrent lanes are independent evidence seats: a requested-vs-verified screen
185
- // mismatch is recorded as separate facts + a warning instead of failing the lane's
179
+ // Concurrent participants are independent evidence seats: a requested-vs-verified screen
180
+ // mismatch is recorded as separate facts + a warning instead of failing the participant's
186
181
  // device claim closed, so one seat's window-manager drift cannot abort the whole
187
- // live multi-actor world (the single-lane/fan-out routes keep fail-closed).
182
+ // live multi-actor world (the single-participant/fan-out routes keep fail-closed).
188
183
  screenMismatchPolicy: "record-evidence",
189
184
  };
190
185
  }
@@ -1,7 +1,6 @@
1
1
  import { type CuaActorDescriptor } from "../../actors/registry.js";
2
2
  import type { RoutePlanResult, RouteRefusal, SharedWorldPlan } from "../../lab/plan-types.js";
3
3
  import type { LabConfig, LabSubjectState } from "../../lab/types.js";
4
- import type { RunLabProvenance } from "../../run/status.js";
5
4
  import type { ConcurrentSharedWorldLabErrorCode } from "./types.js";
6
5
  /** The error a shared-world lab returns before a run starts. */
7
6
  export interface SharedWorldRefusal extends RouteRefusal<"shared-world", ConcurrentSharedWorldLabErrorCode> {
@@ -17,11 +16,8 @@ export declare function sharedWorldDescriptorOf(actorType: string): CuaActorDesc
17
16
  */
18
17
  export declare function planSharedWorldLab(config: LabConfig, input: {
19
18
  readonly dryRun: boolean;
20
- readonly lab?: RunLabProvenance;
21
- /** A caller's session runner cannot enforce maxOutputTokens. */
22
- readonly hooks?: {
23
- readonly runSession?: unknown;
24
- };
19
+ /** Whether deps.runSession is set: a caller's session runner cannot enforce maxOutputTokens. */
20
+ readonly hasRunSession?: boolean;
25
21
  }): SharedWorldPlanResult;
26
22
  /** The provisioned plane's declared subject state. The external-public plane declares none. */
27
23
  export declare function planeStateOf(plan: SharedWorldPlan): LabSubjectState | undefined;
@@ -55,7 +55,7 @@ export function planSharedWorldLab(config, input) {
55
55
  : concurrentSharedWorldValidationReason(config));
56
56
  if (invalidReason)
57
57
  return refuse(invalid, invalidReason, actor);
58
- if (config.actors[0]?.maxOutputTokens !== undefined && input.hooks?.runSession)
58
+ if (config.actors[0]?.maxOutputTokens !== undefined && input.hasRunSession === true)
59
59
  return refuse(invalid, "maxOutputTokens cannot be enforced by a custom runSession.", actor);
60
60
  const caps = config.execution?.caps;
61
61
  if (!input.dryRun && (caps?.maxUsd !== undefined || caps?.maxTotalUsd !== undefined)) {
@@ -88,7 +88,6 @@ export function planSharedWorldLab(config, input) {
88
88
  throw new Error("a shared-world participant has no caller brain");
89
89
  const base = planBase(config, {
90
90
  dryRun: input.dryRun,
91
- ...(input.lab === undefined ? {} : { lab: input.lab }),
92
91
  analysis,
93
92
  });
94
93
  return {
@@ -2,18 +2,18 @@ import type { RunSubjectProvenance } from "../../run/bundle.js";
2
2
  import type { LocalTreeArchive } from "../../subject/local-tree-archive.js";
3
3
  /** Extract the in-sandbox port from the (loopback) serve.url so getHost can expose it. */
4
4
  export declare function servePort(serveUrl: string): number;
5
- /** A getHost URL must be TOKENLESS (no userinfo, no query — no authKey; invariant 1). */
5
+ /** A getHost URL must be tokenless (no userinfo and no query, so no authKey; invariant 1). */
6
6
  export declare function isTokenlessHost(value: string): boolean;
7
- /** sha256-16 of a URL's ORIGIN — the publish-safe host identity persisted in the bundle (the raw
7
+ /** sha256-16 of a URL's origin: the publish-safe host identity persisted in the bundle (the raw
8
8
  * getHost URL embeds the live sandbox id + matches the e2b-URL redaction, so it never lands raw). */
9
9
  export declare function hostOriginDigest(url: string): string;
10
10
  /** A public-safe, human-readable route label for the bundle (host redacted to a placeholder; the
11
11
  * entry path kept). Never contains the raw getHost URL. */
12
12
  export declare function publicSafeRouteLabel(entry: string | undefined): string;
13
13
  /**
14
- * Build the ONE subject sandbox's provenance (invariant 5): clone (repo + optional commit) or
14
+ * Build the one subject sandbox's provenance (invariant 5): clone (repo + optional commit) or
15
15
  * local-tree (archiveSha256 + optional commit/dirty from the once-per-run host-packed archive -
16
- * archiveSha256 IS the pin; there is only ONE archive, so no per-lane unanimity math applies,
16
+ * archiveSha256 is the pin; there is only one archive, so no per-participant unanimity math applies,
17
17
  * unlike the cua fan-out route). Used for both the in-progress and final bundle: the archive
18
18
  * never changes mid-run (packed before any sandbox exists).
19
19
  */
@@ -8,7 +8,7 @@ export function servePort(serveUrl) {
8
8
  return Number(url.port);
9
9
  return url.protocol === "https:" ? 443 : 80;
10
10
  }
11
- /** A getHost URL must be TOKENLESS (no userinfo, no query — no authKey; invariant 1). */
11
+ /** A getHost URL must be tokenless (no userinfo and no query, so no authKey; invariant 1). */
12
12
  export function isTokenlessHost(value) {
13
13
  try {
14
14
  const url = new URL(value);
@@ -18,7 +18,7 @@ export function isTokenlessHost(value) {
18
18
  return false;
19
19
  }
20
20
  }
21
- /** sha256-16 of a URL's ORIGIN — the publish-safe host identity persisted in the bundle (the raw
21
+ /** sha256-16 of a URL's origin: the publish-safe host identity persisted in the bundle (the raw
22
22
  * getHost URL embeds the live sandbox id + matches the e2b-URL redaction, so it never lands raw). */
23
23
  export function hostOriginDigest(url) {
24
24
  try {
@@ -34,9 +34,9 @@ export function publicSafeRouteLabel(entry) {
34
34
  return `[provisioned-subject]${entry ?? "/"}`;
35
35
  }
36
36
  /**
37
- * Build the ONE subject sandbox's provenance (invariant 5): clone (repo + optional commit) or
37
+ * Build the one subject sandbox's provenance (invariant 5): clone (repo + optional commit) or
38
38
  * local-tree (archiveSha256 + optional commit/dirty from the once-per-run host-packed archive -
39
- * archiveSha256 IS the pin; there is only ONE archive, so no per-lane unanimity math applies,
39
+ * archiveSha256 is the pin; there is only one archive, so no per-participant unanimity math applies,
40
40
  * unlike the cua fan-out route). Used for both the in-progress and final bundle: the archive
41
41
  * never changes mid-run (packed before any sandbox exists).
42
42
  */
@@ -3,7 +3,7 @@ import type { RunSubjectStateStepRecord } from "../../run/bundle.js";
3
3
  import type { SharedWorldStateSnapshot } from "../../run/shared-world-evidence.js";
4
4
  import type { LocalTreeArchive } from "../../subject/local-tree-archive.js";
5
5
  import type { DetachedTimers } from "../../substrates/detached.js";
6
- import type { SharedWorldLabHooks } from "./types.js";
6
+ import type { LabDeps } from "../../lab/lab-deps.js";
7
7
  import { type ActorRunResult, type SubjectDesktopUsage, type LiveParticipants, type PlaneContext } from "./types.js";
8
8
  /** What the provisioned plane needs besides the shared plane context. */
9
9
  export interface ProvisionedPlaneSetup {
@@ -35,6 +35,7 @@ export interface ProvisionedPlaneOutcome {
35
35
  subjectCommit: string | undefined;
36
36
  subjectSandboxId: string | undefined;
37
37
  subjectKilled: boolean;
38
+ subjectReleaseWarning: string | undefined;
38
39
  subjectDesktop: SubjectDesktopUsage | undefined;
39
40
  getHostUrl: string | undefined;
40
41
  /** Set when the teardown drain wrote a comms thread. */
@@ -47,7 +48,7 @@ export declare function runProvisionedPlane(ctx: PlaneContext, live: LivePartici
47
48
  */
48
49
  export declare function packSubjectTree(cwd: string, config: {
49
50
  readonly subject: Pick<LabConfig["subject"], "localTree">;
50
- }, hooks: SharedWorldLabHooks, scrubKnownValues: (text: string) => string): Promise<{
51
+ }, deps: LabDeps, scrubKnownValues: (text: string) => string): Promise<{
51
52
  ok: true;
52
53
  archive: LocalTreeArchive;
53
54
  buffer: ArrayBuffer;
@@ -1,4 +1,4 @@
1
- // The PROVISIONED-GETHOST plane: the harness provisions ONE subject sandbox (clone or local-tree,
1
+ // The provisioned-getHost plane: the harness provisions one subject sandbox (clone or local-tree,
2
2
  // install/build, seed, serve on 0.0.0.0), exposes it through getHost, probes its state on a
3
3
  // cadence, and runs every seat against that one shared plane. All sandboxes are torn down by exact
4
4
  // id in the plane's finally, never through Sandbox.list.
@@ -10,6 +10,7 @@ import { mapWithConcurrency } from "../../run/concurrency.js";
10
10
  import { provisionCloneSubject } from "../../subject/clone.js";
11
11
  import { provisionLocalTreeSubject } from "../../subject/local-tree.js";
12
12
  import { defaultSharedWorldPhaseSink } from "../../subject/steps.js";
13
+ import { phaseEvent } from "../../lab/run-lab-events.js";
13
14
  import { loadE2BDesktopModule } from "../../substrates/e2b/sdk.js";
14
15
  import { observeDesktopResources, } from "../../substrates/e2b/desktop-resources.js";
15
16
  import { acquireE2BDesktopSandbox, readE2BRelease } from "../../substrates/e2b/sandbox.js";
@@ -19,14 +20,14 @@ import { inboxRecipientFor, participantHasInboxRecipient, } from "../computer-us
19
20
  import { resolveSubjectState } from "../computer-use/subject-projection.js";
20
21
  import { withInboxMission } from "../computer-use/participant-prompt.js";
21
22
  import { planeStateOf } from "./plan.js";
22
- import { runCuaParticipant } from "../computer-use/lanes.js";
23
+ import { runCuaParticipant } from "../computer-use/participant-execution.js";
23
24
  import { buildConcurrentSharedWorldBundle, judgeSharedWorldRun } from "./bundle.js";
24
25
  import { runCheckpointSnapshot } from "./checkpoints.js";
25
26
  import { drainSubjectComms } from "./comms.js";
26
27
  import { buildSubjectProvenance, hostOriginDigest, isTokenlessHost, servePort, } from "./provenance.js";
27
28
  import { SANDBOX_TIMEOUT_BUFFER_MS, SUBJECT_PROVISION_BUDGET_MS, } from "../../substrates/e2b/lifetime.js";
28
29
  import { DEFAULT_STATE_STEP_TIMEOUT_MS } from "../../subject/state.js";
29
- import { resolveActorEntryUrl, participantRunDeps, startParticipantFlush } from "./seats.js";
30
+ import { resolveActorEntryUrl, participantRunDeps, startParticipantFlush, } from "./participant-specs.js";
30
31
  import { CONCURRENT_SHARED_WORLD_PROVIDER_METADATA, } from "./types.js";
31
32
  import { addressedRecipients } from "../../lab/parse/comms.js";
32
33
  /**
@@ -41,12 +42,13 @@ class ObserverGateError extends Error {
41
42
  this.name = "ObserverGateError";
42
43
  }
43
44
  }
44
- /** The ONE subject sandbox and the loops that run against it until teardown. */
45
+ /** The one subject sandbox and the loops that run against it until teardown. */
45
46
  class SubjectPlane {
46
47
  commsInboxUrl;
47
48
  subjectCommit;
48
49
  subjectSandboxId;
49
50
  subjectKilled = false;
51
+ subjectReleaseWarning;
50
52
  getHostUrl;
51
53
  // The subject desktop's host-side span and size, priced in the run's cost estimate.
52
54
  subjectCreatedAtMs;
@@ -57,17 +59,17 @@ class SubjectPlane {
57
59
  subjectAllocation;
58
60
  subjectDesktop;
59
61
  subjectShell;
60
- // The in-sandbox email catch on the ONE subject sandbox (#297); drained at teardown. Undefined
62
+ // The in-sandbox email catch on the one subject sandbox (#297); drained at teardown. Undefined
61
63
  // unless a comms lab declared it.
62
64
  deployedComms;
63
- // Background prober dispose signal (FIX-9: cleared in teardown).
65
+ // Background prober dispose signal, cleared in teardown.
64
66
  proberDisposed = false;
65
67
  releaseDispose = () => { };
66
68
  disposeSignal;
67
69
  proberLoop;
68
70
  snapshotIndex = 0;
69
- // Persona inbox SURFACE (#297 slice B, shared-world): the serve->getHost origin-rewrite map
70
- // (REQUIRED here so the app's loopback verify links resolve to a reachable host), and the
71
+ // Persona inbox surface (#297 slice B, shared-world): the serve->getHost origin-rewrite map
72
+ // (required here so the app's loopback verify links resolve to a reachable host), and the
71
73
  // dedicated surface render loop.
72
74
  commsOriginMap = [];
73
75
  surfaceRenderedCount = 0;
@@ -98,12 +100,12 @@ class SubjectPlane {
98
100
  this.setup.stateSnapshots.push({ timestamp, digest: snapshot.digest });
99
101
  }
100
102
  async acquire() {
101
- const { plan, hooks, env, requestTimeoutMs, timeoutMs } = this.ctx;
103
+ const { plan, deps, env, requestTimeoutMs, timeoutMs } = this.ctx;
102
104
  const { subjectEnvNames, commsEnv } = this.setup;
103
- const subjectModule = await (hooks.loadDesktopModule ?? loadE2BDesktopModule)();
104
- // The ONE subject sandbox: headless service host (no GUI seat). The SUBJECT env is provisioned
105
- // HERE; the actor sandboxes get NONE of it (FIX-10). A custom desktop template (image) is
106
- // honored on BOTH the subject sandbox (here) and every actor sandbox (via runCuaParticipant, which
105
+ const subjectModule = await (deps.desktopModule ?? loadE2BDesktopModule)();
106
+ // The one subject sandbox: headless service host (no GUI seat). The subject env is provisioned
107
+ // here; the actor sandboxes get none of it. A custom desktop template (image) is
108
+ // honored on both the subject sandbox (here) and every actor sandbox (via runCuaParticipant, which
107
109
  // reads the same config); absent keeps the byte-stable Sandbox.create(opts) default. The
108
110
  // receipt is on disk before any work, so `humanish reclaim` can kill it by exact id.
109
111
  const subject = await acquireE2BDesktopSandbox({
@@ -143,18 +145,16 @@ class SubjectPlane {
143
145
  this.subjectSandboxId = subject.allocation.resourceId;
144
146
  this.subjectCreatedAtMs = this.ctx.now();
145
147
  this.subjectResources = await observeDesktopResources(this.subjectDesktop);
146
- if (hooks.prepareDesktop) {
147
- await hooks.prepareDesktop(this.subjectDesktop);
148
- }
148
+ await this.ctx.input.prepareDesktop?.(this.subjectDesktop, { kind: "subject" });
149
149
  }
150
- // Start the in-sandbox email catch BEFORE the subject serve, so the app's send-API base URL
150
+ // Start the in-sandbox email catch before the subject serve, so the app's send-API base URL
151
151
  // (injected into its env at create) resolves the moment it boots. Fail closed if the catch can't
152
152
  // stand up rather than let a comms-declared app silently send real mail to the internet.
153
153
  async deployCatch() {
154
154
  const { commsEmail, commsPort } = this.setup;
155
155
  if (commsEmail && commsPort !== undefined) {
156
- // A SECOND (0.0.0.0) read-only inbox listener on commsPort+1 so the persona — which lives in a
157
- // DIFFERENT sandbox here — can reach the inbox surface via getHost; capture stays loopback.
156
+ // A second (0.0.0.0) read-only inbox listener on commsPort+1 so the persona, which lives in
157
+ // another sandbox here, can reach the inbox surface via getHost; capture stays loopback.
158
158
  this.deployedComms = await deployCommsCatch(this.subjectShell, {
159
159
  port: commsPort,
160
160
  inboxPort: commsPort + 1,
@@ -166,15 +166,19 @@ class SubjectPlane {
166
166
  }
167
167
  }
168
168
  }
169
- // Provision the ONE shared plane: clone + install/build + seed + serve on 0.0.0.0 + probe
170
- // (clone route), or upload/extract the once-per-run packed archive + the SAME shared serve
169
+ // Provision the one shared plane: clone + install/build + seed + serve on 0.0.0.0 + probe
170
+ // (clone route), or upload/extract the once-per-run packed archive + the same shared serve
171
171
  // pipeline (local-tree route).
172
172
  async provision() {
173
- const { plan, hooks, requestTimeoutMs, scrubKnownValues } = this.ctx;
173
+ const { plan, requestTimeoutMs, scrubKnownValues } = this.ctx;
174
174
  const { serve, timers, stateStepRecords } = this.setup;
175
175
  const state = planeStateOf(plan);
176
176
  const subjectShell = this.subjectShell;
177
- const onSubjectPhase = hooks.onPhase ?? defaultSharedWorldPhaseSink;
177
+ const sink = this.ctx.input.deps?.subjectPhaseSink ?? defaultSharedWorldPhaseSink;
178
+ const onSubjectPhase = (event) => {
179
+ sink(event);
180
+ this.ctx.input.emit?.(phaseEvent(event, { kind: "subject" }));
181
+ };
178
182
  if (this.setup.localTreeRoute) {
179
183
  await provisionLocalTreeSubject(subjectShell, {
180
184
  archiveBuffer: this.setup.localTreeArchiveBuffer,
@@ -209,13 +213,13 @@ class SubjectPlane {
209
213
  });
210
214
  }
211
215
  }
212
- // Expose the served port via getHost (FIX-2). Fail closed if the SDK lacks it.
216
+ // Expose the served port via getHost. Fail closed if the SDK lacks it.
213
217
  exposeHost() {
214
218
  const subjectDesktop = this.subjectDesktop;
215
219
  if (typeof subjectDesktop.getHost !== "function") {
216
220
  throw new Error("the installed @e2b/desktop SDK does not expose getHost(port); the concurrent shared-world route requires it to reach the subject plane");
217
221
  }
218
- // getHost returns a BARE host (e.g. "3000-<sandboxId>.e2b.app", no scheme); e2b exposes the
222
+ // getHost returns a bare host (e.g. "3000-<sandboxId>.e2b.app", no scheme); e2b exposes the
219
223
  // port over https. Normalize to a full URL before the tokenless check + before persisting.
220
224
  const rawHost = subjectDesktop.getHost(servePort(this.setup.serve.url));
221
225
  const hostUrl = /^https?:\/\//i.test(rawHost) ? rawHost : `https://${rawHost}`;
@@ -224,12 +228,12 @@ class SubjectPlane {
224
228
  }
225
229
  this.getHostUrl = hostUrl;
226
230
  }
227
- // Persona inbox SURFACE (#297 slice B, shared-world): getHost-expose the read-only inbox listener so
228
- // a persona in a DIFFERENT sandbox can open it; build the serve->getHost origin map (REQUIRED here —
231
+ // Persona inbox surface (#297 slice B, shared-world): getHost-expose the read-only inbox listener so
232
+ // a persona in another sandbox can open it; build the serve->getHost origin map (required here:
229
233
  // the app's loopback verify links must be rewritten to a reachable host); provision the surface
230
- // channel; write the EMPTY inbox up front (so /inbox never 404s); and start a render loop that drains
234
+ // channel; write the empty inbox up front (so /inbox never 404s); and start a render loop that drains
231
235
  // + re-renders on a cadence. The loop shares the prober's dispose signal (disposed together, before
232
- // the teardown evidence drain), and uses a DEDICATED FakeInbox + cursor (independent of that drain).
236
+ // the teardown evidence drain), and uses a dedicated FakeInbox + cursor (independent of that drain).
233
237
  async startInboxSurface() {
234
238
  const { commsEmail } = this.setup;
235
239
  const { requestTimeoutMs } = this.ctx;
@@ -303,7 +307,7 @@ class SubjectPlane {
303
307
  this.disposeSignal,
304
308
  ]);
305
309
  if (timer)
306
- clearTimeout(timer); // FIX-9: no dangling prober timer.
310
+ clearTimeout(timer); // No dangling prober timer.
307
311
  if (this.proberDisposed)
308
312
  break;
309
313
  await this.snapshot().catch(() => undefined);
@@ -311,8 +315,8 @@ class SubjectPlane {
311
315
  })();
312
316
  }
313
317
  /**
314
- * FIX-9: stop the prober, take a final snapshot while the subject is still alive, then tear
315
- * down the ONE subject sandbox BY id (the actor sandboxes are torn down inside runCuaParticipant).
318
+ * Stop the prober, take a final snapshot while the subject is still alive, then tear
319
+ * down the one subject sandbox by id (the actor sandboxes are torn down inside runCuaParticipant).
316
320
  * Returns the comms thread's path when the drain wrote one.
317
321
  */
318
322
  async teardown() {
@@ -345,7 +349,10 @@ class SubjectPlane {
345
349
  this.subjectKilled = reading.released;
346
350
  if (reading.warning)
347
351
  warnings.push(reading.warning);
348
- // Without a kill method nothing ran, so there is no teardown time to record.
352
+ if (!reading.released)
353
+ this.subjectReleaseWarning = reading.warning ?? "Subject sandbox release is unconfirmed.";
354
+ // Without a kill method, or in E2B debug mode, no kill reached E2B, so there is no teardown
355
+ // time to record.
349
356
  if (released.status !== "unconfirmed" || released.reason !== "release_unavailable")
350
357
  this.subjectTornDownAtMs = this.ctx.now();
351
358
  }
@@ -384,11 +391,10 @@ async function publishInProgress(plane, ctx, live, setup) {
384
391
  });
385
392
  const snapshotArgs = {
386
393
  plan,
394
+ run: ctx.run,
387
395
  descriptor: ctx.descriptor,
388
- createdAt: ctx.createdAt,
389
396
  dryRun: false,
390
397
  inProgress: true,
391
- runId: ctx.runId,
392
398
  source: ctx.source,
393
399
  actorSpecs: ctx.actorSpecs,
394
400
  actorResults: [],
@@ -416,9 +422,9 @@ async function publishInProgress(plane, ctx, live, setup) {
416
422
  }
417
423
  startParticipantFlush(ctx, live, inProgressBundle);
418
424
  }
419
- // Launch N actor sandboxes CONCURRENTLY, INDEPENDENT (FIX-11: runCuaParticipant + mapWithConcurrency,
420
- // NOT runCuaParticipants — no pipeline gate / fail-fast). Each actor's window is measured on the ONE
421
- // orchestrator clock (FIX-1).
425
+ // Launch N actor sandboxes concurrently and independently (runCuaParticipant + mapWithConcurrency;
426
+ // runCuaParticipants would add a pipeline gate and fail-fast). Each actor's window is measured on the
427
+ // one orchestrator clock.
422
428
  function runParticipants(plane, ctx, live, setup) {
423
429
  const { now } = ctx;
424
430
  const participants = ctx.plan.plane.participants;
@@ -426,7 +432,7 @@ function runParticipants(plane, ctx, live, setup) {
426
432
  const baseActorDeps = participantRunDeps(ctx, live, ctx.scrubKnownValues);
427
433
  return mapWithConcurrency(ctx.actorSpecs, Math.max(1, ctx.concurrency), async (spec, i) => {
428
434
  const route = resolveActorEntryUrl(plane.getHostUrl, participants[i]?.entry);
429
- // Tell this persona its (getHost-reachable) inbox URL — but only when comms is live AND this lane
435
+ // Tell this persona its (getHost-reachable) inbox URL, but only when comms is live and this participant
430
436
  // has a declared recipient it can actually receive mail into (else it would stall on an empty
431
437
  // inbox). Only the in-sandbox catch exists on this plane; the adopter-hosted catch is the
432
438
  // external-public plane's (#387).
@@ -471,6 +477,7 @@ export async function runProvisionedPlane(ctx, live, setup) {
471
477
  subjectCommit: plane.subjectCommit,
472
478
  subjectSandboxId: plane.subjectSandboxId,
473
479
  subjectKilled: plane.subjectKilled,
480
+ subjectReleaseWarning: plane.subjectReleaseWarning,
474
481
  subjectDesktop: plane.desktopUsage(),
475
482
  getHostUrl: plane.getHostUrl,
476
483
  commsArtifactPath,
@@ -480,8 +487,8 @@ export async function runProvisionedPlane(ctx, live, setup) {
480
487
  * Packs the working tree once per run, on the host, for a local-tree subject. Returns the archive,
481
488
  * or the message the run fails with.
482
489
  */
483
- export async function packSubjectTree(cwd, config, hooks, scrubKnownValues) {
484
- const packLocalTree = hooks.packLocalTree ?? defaultPackLocalTree;
490
+ export async function packSubjectTree(cwd, config, deps, scrubKnownValues) {
491
+ const packLocalTree = deps.packLocalTree ?? defaultPackLocalTree;
485
492
  try {
486
493
  const packed = await packLocalTree({
487
494
  root: cwd,