humanish 0.107.0 → 0.108.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (521) hide show
  1. package/ARCHITECTURE.md +22 -17
  2. package/CHANGELOG.md +14 -0
  3. package/CONTEXT.md +51 -44
  4. package/README.md +145 -172
  5. package/SECURITY.md +16 -26
  6. package/TELEMETRY.md +8 -6
  7. package/dist/actors/affordance.d.ts +4 -4
  8. package/dist/actors/affordance.js +12 -12
  9. package/dist/actors/agent-session.d.ts +2 -2
  10. package/dist/actors/agent-session.js +7 -7
  11. package/dist/actors/codex/app-server-actor-trace.d.ts +1 -1
  12. package/dist/actors/codex/app-server-actor-trace.js +1 -1
  13. package/dist/actors/codex/app-server-ui.js +1 -1
  14. package/dist/actors/codex/codex-admission.d.ts +91 -0
  15. package/dist/actors/codex/codex-admission.js +150 -0
  16. package/dist/actors/codex/restricted-executable.d.ts +4 -4
  17. package/dist/actors/codex/restricted-executable.js +8 -8
  18. package/dist/actors/codex/restricted-launch.d.ts +2 -1
  19. package/dist/actors/codex/restricted-launch.js +1 -1
  20. package/dist/actors/codex/restricted-participant.js +8 -6
  21. package/dist/actors/codex/restricted-policy.d.ts +2 -2
  22. package/dist/actors/codex/restricted-policy.js +2 -2
  23. package/dist/actors/codex/restricted-session.d.ts +2 -2
  24. package/dist/actors/codex/restricted-session.js +10 -5
  25. package/dist/actors/computer-use/actor.d.ts +16 -16
  26. package/dist/actors/computer-use/actor.js +2 -2
  27. package/dist/actors/computer-use/admission-limit.d.ts +1 -1
  28. package/dist/actors/computer-use/admission-limit.js +1 -1
  29. package/dist/actors/computer-use/loop/actions.d.ts +3 -3
  30. package/dist/actors/computer-use/loop/actions.js +10 -10
  31. package/dist/actors/computer-use/loop/backstop.d.ts +3 -3
  32. package/dist/actors/computer-use/loop/backstop.js +14 -12
  33. package/dist/actors/computer-use/loop/ending.d.ts +5 -5
  34. package/dist/actors/computer-use/loop/ending.js +7 -7
  35. package/dist/actors/computer-use/loop/observation.d.ts +2 -2
  36. package/dist/actors/computer-use/loop/observation.js +9 -9
  37. package/dist/actors/computer-use/loop/provider-call.d.ts +1 -1
  38. package/dist/actors/computer-use/loop/provider-call.js +1 -1
  39. package/dist/actors/computer-use/loop/session.js +3 -3
  40. package/dist/actors/computer-use/loop/spend.d.ts +1 -1
  41. package/dist/actors/computer-use/loop/spend.js +1 -1
  42. package/dist/actors/computer-use/loop/trace.js +9 -8
  43. package/dist/actors/computer-use/loop/types.d.ts +25 -23
  44. package/dist/actors/computer-use/loop/usage.js +2 -2
  45. package/dist/actors/computer-use/openai-context.d.ts +37 -0
  46. package/dist/actors/computer-use/openai-context.js +214 -0
  47. package/dist/actors/computer-use/openai-provider.d.ts +11 -8
  48. package/dist/actors/computer-use/openai-provider.js +45 -34
  49. package/dist/actors/computer-use/openai-requests.d.ts +36 -10
  50. package/dist/actors/computer-use/openai-requests.js +82 -15
  51. package/dist/actors/computer-use/openai-wire.d.ts +19 -7
  52. package/dist/actors/computer-use/openai-wire.js +36 -34
  53. package/dist/actors/contract.d.ts +78 -43
  54. package/dist/actors/contract.js +29 -23
  55. package/dist/actors/local-agent/claude-session.d.ts +1 -1
  56. package/dist/actors/local-agent/claude-session.js +10 -9
  57. package/dist/actors/local-agent/cli.d.ts +8 -6
  58. package/dist/actors/local-agent/cli.js +24 -28
  59. package/dist/actors/local-agent/readiness.d.ts +2 -2
  60. package/dist/actors/local-agent/readiness.js +4 -4
  61. package/dist/actors/reasoning-effort.js +6 -6
  62. package/dist/actors/registry.d.ts +10 -10
  63. package/dist/actors/registry.js +18 -17
  64. package/dist/actors/scripted-browser/actor.d.ts +8 -8
  65. package/dist/actors/scripted-browser/actor.js +16 -16
  66. package/dist/actors/scripted-browser/browser-command.js +1 -1
  67. package/dist/actors/scripted-browser/steps.js +1 -1
  68. package/dist/actors/scripted-browser/types.d.ts +1 -1
  69. package/dist/actors/stop-conditions.d.ts +1 -1
  70. package/dist/analysis/codex-config.d.ts +6 -2
  71. package/dist/analysis/codex-config.js +22 -14
  72. package/dist/analysis/service.js +5 -5
  73. package/dist/cli/commands/analyze.js +19 -16
  74. package/dist/cli/commands/codex.js +9 -9
  75. package/dist/cli/commands/comms.js +54 -33
  76. package/dist/cli/commands/feedback.js +20 -21
  77. package/dist/cli/commands/lab-format.d.ts +5 -4
  78. package/dist/cli/commands/lab-format.js +35 -23
  79. package/dist/cli/commands/lab-route-computer-use.js +6 -7
  80. package/dist/cli/commands/lab-route-preview.js +4 -3
  81. package/dist/cli/commands/lab-route-shared-world.js +3 -3
  82. package/dist/cli/commands/lab-run.js +10 -11
  83. package/dist/cli/commands/lab-scorer.d.ts +2 -2
  84. package/dist/cli/commands/lab-scorer.js +1 -1
  85. package/dist/cli/commands/migrate.d.ts +4 -0
  86. package/dist/cli/commands/migrate.js +65 -0
  87. package/dist/cli/commands/observe.js +147 -108
  88. package/dist/cli/commands/run-command.d.ts +10 -0
  89. package/dist/cli/commands/run-command.js +85 -0
  90. package/dist/cli/commands/runs.js +137 -138
  91. package/dist/cli/commands/setup.d.ts +2 -2
  92. package/dist/cli/commands/setup.js +26 -21
  93. package/dist/cli/commands/study.d.ts +3 -0
  94. package/dist/cli/commands/study.js +182 -0
  95. package/dist/cli/commands/tui.d.ts +4 -4
  96. package/dist/cli/commands/tui.js +21 -21
  97. package/dist/cli/commands/watch.js +60 -75
  98. package/dist/cli/deprecations.d.ts +18 -0
  99. package/dist/cli/deprecations.js +48 -0
  100. package/dist/cli/doctor.d.ts +15 -5
  101. package/dist/cli/doctor.js +103 -48
  102. package/dist/cli/first-run-path.d.ts +12 -10
  103. package/dist/cli/first-run-path.js +30 -28
  104. package/dist/cli/io.d.ts +41 -6
  105. package/dist/cli/io.js +97 -22
  106. package/dist/cli/observer-follow.d.ts +2 -2
  107. package/dist/cli/observer-follow.js +5 -6
  108. package/dist/cli/orientation.d.ts +6 -3
  109. package/dist/cli/orientation.js +43 -39
  110. package/dist/cli/product-sentence.d.ts +6 -0
  111. package/dist/cli/product-sentence.js +6 -0
  112. package/dist/cli/program.d.ts +6 -1
  113. package/dist/cli/program.js +109 -40
  114. package/dist/cli/telemetry.d.ts +15 -15
  115. package/dist/cli/telemetry.js +48 -40
  116. package/dist/cli.js +1 -1
  117. package/dist/comms/capture-surface.d.ts +13 -12
  118. package/dist/comms/capture-surface.js +23 -22
  119. package/dist/comms/catch-host.d.ts +7 -7
  120. package/dist/comms/catch-host.js +14 -14
  121. package/dist/comms/email-catch.d.ts +3 -3
  122. package/dist/comms/email-catch.js +8 -8
  123. package/dist/comms/external-evidence.js +2 -2
  124. package/dist/comms/extract.js +2 -2
  125. package/dist/comms/fake-inbox.d.ts +2 -2
  126. package/dist/comms/fake-inbox.js +2 -2
  127. package/dist/comms/receiving-render.d.ts +1 -1
  128. package/dist/comms/receiving-render.js +2 -2
  129. package/dist/comms/sandbox-catch-script.d.ts +6 -6
  130. package/dist/comms/sandbox-catch-script.js +6 -6
  131. package/dist/comms/sandbox-catch.d.ts +36 -37
  132. package/dist/comms/sandbox-catch.js +34 -35
  133. package/dist/comms/setup.js +42 -8
  134. package/dist/comms/thread-evidence.d.ts +1 -1
  135. package/dist/comms/thread-evidence.js +6 -6
  136. package/dist/comms/types.d.ts +6 -6
  137. package/dist/comms/types.js +3 -3
  138. package/dist/evidence/frame-signature.d.ts +1 -1
  139. package/dist/evidence/frame-signature.js +4 -4
  140. package/dist/evidence/redaction.d.ts +3 -3
  141. package/dist/evidence/redaction.js +4 -4
  142. package/dist/feedback/draft.js +36 -78
  143. package/dist/feedback/export-bundle.js +1 -1
  144. package/dist/feedback/export.d.ts +5 -1
  145. package/dist/feedback/export.js +7 -8
  146. package/dist/feedback/feedback.d.ts +2 -2
  147. package/dist/feedback/feedback.js +21 -3
  148. package/dist/guest/chromium-text.js +2 -2
  149. package/dist/guest/desktop-native.d.ts +1 -1
  150. package/dist/guest/runtime.js +1 -1
  151. package/dist/index.d.ts +12 -10
  152. package/dist/index.js +8 -6
  153. package/dist/keys/key-resolution.d.ts +5 -5
  154. package/dist/keys/key-resolution.js +23 -23
  155. package/dist/lab/adapter-extension.d.ts +7 -7
  156. package/dist/lab/adapter-extension.js +13 -36
  157. package/dist/lab/adapter-scorer-loader.d.ts +7 -7
  158. package/dist/lab/adapter-scorer-loader.js +32 -32
  159. package/dist/lab/composition-rules.js +42 -42
  160. package/dist/lab/config.js +65 -25
  161. package/dist/lab/deprecated-fields.d.ts +10 -0
  162. package/dist/lab/deprecated-fields.js +24 -0
  163. package/dist/lab/device-presets.d.ts +8 -8
  164. package/dist/lab/device-presets.js +11 -11
  165. package/dist/lab/discover.d.ts +13 -9
  166. package/dist/lab/discover.js +117 -57
  167. package/dist/lab/doctor.d.ts +10 -3
  168. package/dist/lab/doctor.js +47 -9
  169. package/dist/lab/init-templates.js +147 -147
  170. package/dist/lab/init.d.ts +1 -1
  171. package/dist/lab/init.js +41 -9
  172. package/dist/lab/keys.d.ts +2 -0
  173. package/dist/lab/keys.js +42 -8
  174. package/dist/lab/lab-deps.d.ts +7 -12
  175. package/dist/lab/parse/actors.js +9 -9
  176. package/dist/lab/parse/comms.js +5 -5
  177. package/dist/lab/parse/execution.js +13 -13
  178. package/dist/lab/parse/study-v3.d.ts +23 -0
  179. package/dist/lab/parse/study-v3.js +259 -0
  180. package/dist/lab/parse/subject-state.d.ts +7 -7
  181. package/dist/lab/parse/subject-state.js +16 -16
  182. package/dist/lab/parse/subject.js +28 -28
  183. package/dist/lab/parse/values.d.ts +1 -1
  184. package/dist/lab/parse/values.js +3 -3
  185. package/dist/lab/persona-resolve.d.ts +4 -4
  186. package/dist/lab/persona-resolve.js +4 -4
  187. package/dist/lab/plan-participants.d.ts +2 -2
  188. package/dist/lab/plan-types.d.ts +4 -4
  189. package/dist/lab/plan.d.ts +1 -7
  190. package/dist/lab/plan.js +10 -41
  191. package/dist/lab/preflight-probes.js +11 -11
  192. package/dist/lab/preflight-result.d.ts +2 -1
  193. package/dist/lab/preflight-result.js +5 -4
  194. package/dist/lab/preflight.d.ts +7 -5
  195. package/dist/lab/preflight.js +5 -5
  196. package/dist/lab/routing.d.ts +31 -25
  197. package/dist/lab/routing.js +60 -29
  198. package/dist/lab/run-lab-events.d.ts +0 -3
  199. package/dist/lab/run-lab-events.js +0 -6
  200. package/dist/lab/run-lab-homes.d.ts +22 -10
  201. package/dist/lab/run-lab-homes.js +5 -1
  202. package/dist/lab/run-lab-options.d.ts +1 -1
  203. package/dist/lab/run-lab-options.js +16 -13
  204. package/dist/lab/summary.d.ts +7 -6
  205. package/dist/lab/summary.js +10 -10
  206. package/dist/lab/tasks.d.ts +15 -15
  207. package/dist/lab/tasks.js +14 -14
  208. package/dist/lab/types.d.ts +101 -95
  209. package/dist/lab/types.js +2 -0
  210. package/dist/lab/validation.d.ts +13 -13
  211. package/dist/lab/validation.js +44 -42
  212. package/dist/lab/warnings.d.ts +10 -0
  213. package/dist/lab/warnings.js +61 -33
  214. package/dist/library-aliases.d.ts +56 -0
  215. package/dist/library-aliases.js +22 -0
  216. package/dist/observer/artifact.d.ts +1 -1
  217. package/dist/observer/artifact.js +6 -6
  218. package/dist/observer/data.d.ts +6 -6
  219. package/dist/observer/data.js +5 -4
  220. package/dist/observer/exposure.d.ts +1 -1
  221. package/dist/observer/exposure.js +11 -11
  222. package/dist/observer/http.js +1 -1
  223. package/dist/observer/library.d.ts +1 -1
  224. package/dist/observer/library.js +4 -2
  225. package/dist/observer/listen.js +5 -4
  226. package/dist/observer/render.d.ts +1 -1
  227. package/dist/observer/render.js +10 -5
  228. package/dist/observer/run-routes.d.ts +3 -3
  229. package/dist/observer/run-routes.js +1 -1
  230. package/dist/observer/serve.js +7 -3
  231. package/dist/observer/tunnel.js +1 -1
  232. package/dist/observer-app.html +4 -4
  233. package/dist/routes/computer-use/bundle-parts.d.ts +9 -9
  234. package/dist/routes/computer-use/bundle-parts.js +15 -15
  235. package/dist/routes/computer-use/bundle.js +3 -3
  236. package/dist/routes/computer-use/e2b-desktop/comms.d.ts +1 -1
  237. package/dist/routes/computer-use/e2b-desktop/comms.js +14 -14
  238. package/dist/routes/computer-use/e2b-desktop/desktop.js +4 -4
  239. package/dist/routes/computer-use/e2b-desktop/fidelity.d.ts +4 -3
  240. package/dist/routes/computer-use/e2b-desktop/fidelity.js +11 -10
  241. package/dist/routes/computer-use/e2b-desktop/prepare.js +7 -7
  242. package/dist/routes/computer-use/e2b-desktop/start.js +9 -8
  243. package/dist/routes/computer-use/e2b-desktop/teardown.js +5 -4
  244. package/dist/routes/computer-use/external-comms.d.ts +1 -1
  245. package/dist/routes/computer-use/external-comms.js +1 -1
  246. package/dist/routes/computer-use/fanout-bundle.js +18 -18
  247. package/dist/routes/computer-use/fanout-records.js +10 -11
  248. package/dist/routes/computer-use/live-flush.d.ts +1 -1
  249. package/dist/routes/computer-use/live-flush.js +6 -6
  250. package/dist/routes/computer-use/live-phase.d.ts +4 -2
  251. package/dist/routes/computer-use/live-phase.js +6 -6
  252. package/dist/routes/computer-use/local-vm.js +1 -1
  253. package/dist/routes/computer-use/participant-desktop.d.ts +4 -4
  254. package/dist/routes/computer-use/participant-desktop.js +4 -4
  255. package/dist/routes/computer-use/participant-execution.d.ts +4 -4
  256. package/dist/routes/computer-use/participant-execution.js +9 -9
  257. package/dist/routes/computer-use/participant-model.d.ts +6 -0
  258. package/dist/routes/computer-use/participant-model.js +31 -13
  259. package/dist/routes/computer-use/participant-prompt.d.ts +11 -11
  260. package/dist/routes/computer-use/participant-prompt.js +6 -6
  261. package/dist/routes/computer-use/participant-runs.d.ts +7 -7
  262. package/dist/routes/computer-use/participant-runs.js +13 -13
  263. package/dist/routes/computer-use/plan.js +22 -22
  264. package/dist/routes/computer-use/preflight.js +21 -21
  265. package/dist/routes/computer-use/rerun-selection.js +1 -1
  266. package/dist/routes/computer-use/result.js +11 -11
  267. package/dist/routes/computer-use/route.d.ts +2 -1
  268. package/dist/routes/computer-use/route.js +15 -14
  269. package/dist/routes/computer-use/self-report.d.ts +7 -7
  270. package/dist/routes/computer-use/self-report.js +31 -31
  271. package/dist/routes/computer-use/setup.d.ts +1 -1
  272. package/dist/routes/computer-use/setup.js +17 -18
  273. package/dist/routes/computer-use/single-bundle.d.ts +7 -7
  274. package/dist/routes/computer-use/single-bundle.js +28 -30
  275. package/dist/routes/computer-use/subject-projection.d.ts +1 -1
  276. package/dist/routes/computer-use/subject-projection.js +6 -6
  277. package/dist/routes/computer-use/types.d.ts +40 -42
  278. package/dist/routes/computer-use/types.js +10 -10
  279. package/dist/routes/preview.d.ts +8 -2
  280. package/dist/routes/preview.js +8 -4
  281. package/dist/routes/scripted/bundle.d.ts +2 -2
  282. package/dist/routes/scripted/bundle.js +13 -12
  283. package/dist/routes/scripted/plan.d.ts +1 -1
  284. package/dist/routes/scripted/plan.js +9 -9
  285. package/dist/routes/scripted/result.js +5 -5
  286. package/dist/routes/scripted/route.js +5 -6
  287. package/dist/routes/scripted/scenario.js +2 -2
  288. package/dist/routes/scripted/setup.js +7 -7
  289. package/dist/routes/scripted/subject.js +1 -1
  290. package/dist/routes/scripted/surface-records.js +3 -3
  291. package/dist/routes/scripted/types.d.ts +3 -5
  292. package/dist/routes/scripted/types.js +1 -1
  293. package/dist/routes/shared-world/bundle-records.js +9 -8
  294. package/dist/routes/shared-world/bundle.d.ts +5 -5
  295. package/dist/routes/shared-world/bundle.js +40 -38
  296. package/dist/routes/shared-world/checkpoints.d.ts +1 -1
  297. package/dist/routes/shared-world/checkpoints.js +1 -1
  298. package/dist/routes/shared-world/comms.d.ts +5 -5
  299. package/dist/routes/shared-world/comms.js +14 -14
  300. package/dist/routes/shared-world/external-public.d.ts +4 -3
  301. package/dist/routes/shared-world/external-public.js +16 -12
  302. package/dist/routes/shared-world/handoff.d.ts +7 -6
  303. package/dist/routes/shared-world/handoff.js +65 -57
  304. package/dist/routes/shared-world/lobby-code.d.ts +2 -2
  305. package/dist/routes/shared-world/lobby-code.js +9 -9
  306. package/dist/routes/shared-world/participant-specs.d.ts +7 -6
  307. package/dist/routes/shared-world/participant-specs.js +31 -24
  308. package/dist/routes/shared-world/plan.js +7 -7
  309. package/dist/routes/shared-world/provenance.d.ts +2 -2
  310. package/dist/routes/shared-world/provenance.js +2 -2
  311. package/dist/routes/shared-world/provisioned.js +14 -13
  312. package/dist/routes/shared-world/result.js +20 -21
  313. package/dist/routes/shared-world/route.js +23 -22
  314. package/dist/routes/shared-world/setup.d.ts +3 -3
  315. package/dist/routes/shared-world/setup.js +4 -4
  316. package/dist/routes/shared-world/types.d.ts +30 -28
  317. package/dist/routes/shared-world/types.js +4 -4
  318. package/dist/routes/terminal/adapter.d.ts +3 -3
  319. package/dist/routes/terminal/adapter.js +5 -5
  320. package/dist/routes/terminal/bundle.d.ts +3 -3
  321. package/dist/routes/terminal/bundle.js +22 -21
  322. package/dist/routes/terminal/credentials.d.ts +4 -4
  323. package/dist/routes/terminal/credentials.js +7 -7
  324. package/dist/routes/terminal/dry-run.js +4 -4
  325. package/dist/routes/terminal/encoding.js +2 -2
  326. package/dist/routes/terminal/ledger.d.ts +3 -3
  327. package/dist/routes/terminal/ledger.js +14 -14
  328. package/dist/routes/terminal/live-finish.js +3 -3
  329. package/dist/routes/terminal/live-sandbox.js +12 -13
  330. package/dist/routes/terminal/persona.js +1 -1
  331. package/dist/routes/terminal/plan.js +11 -11
  332. package/dist/routes/terminal/recorder.js +2 -2
  333. package/dist/routes/terminal/result.js +8 -8
  334. package/dist/routes/terminal/route.js +6 -7
  335. package/dist/routes/terminal/sandbox.d.ts +1 -1
  336. package/dist/routes/terminal/sandbox.js +1 -1
  337. package/dist/routes/terminal/session.js +8 -7
  338. package/dist/routes/terminal/token-usage.d.ts +1 -1
  339. package/dist/routes/terminal/token-usage.js +7 -8
  340. package/dist/routes/terminal/trace.d.ts +2 -2
  341. package/dist/routes/terminal/trace.js +2 -2
  342. package/dist/routes/terminal/types.d.ts +26 -28
  343. package/dist/routes/terminal/types.js +3 -3
  344. package/dist/run/bundle-shape.js +3 -3
  345. package/dist/run/bundle.d.ts +46 -46
  346. package/dist/run/bundle.js +2 -1
  347. package/dist/run/cost-summary.js +3 -3
  348. package/dist/run/costs.js +7 -1
  349. package/dist/run/detail.d.ts +6 -6
  350. package/dist/run/detail.js +4 -4
  351. package/dist/run/dry-run-inputs.js +1 -1
  352. package/dist/run/dry-run.js +18 -18
  353. package/dist/run/judge.d.ts +19 -13
  354. package/dist/run/judge.js +18 -8
  355. package/dist/run/paths.d.ts +1 -1
  356. package/dist/run/paths.js +1 -1
  357. package/dist/run/pricing.d.ts +11 -6
  358. package/dist/run/pricing.js +20 -13
  359. package/dist/run/projection.d.ts +14 -14
  360. package/dist/run/projection.js +15 -15
  361. package/dist/run/reclaim.js +2 -2
  362. package/dist/run/results.d.ts +5 -5
  363. package/dist/run/run-index.d.ts +8 -6
  364. package/dist/run/run-index.js +15 -16
  365. package/dist/run/run-not-found.d.ts +5 -0
  366. package/dist/run/run-not-found.js +15 -0
  367. package/dist/run/run.d.ts +5 -4
  368. package/dist/run/run.js +1 -1
  369. package/dist/run/sandbox-receipts.d.ts +2 -2
  370. package/dist/run/sandbox-receipts.js +3 -3
  371. package/dist/run/shared-world-evidence.d.ts +36 -35
  372. package/dist/run/shared-world-evidence.js +4 -4
  373. package/dist/run/shared-world-shape.d.ts +1 -1
  374. package/dist/run/shared-world-shape.js +6 -6
  375. package/dist/run/stats.d.ts +12 -6
  376. package/dist/run/stats.js +116 -58
  377. package/dist/run/status.d.ts +8 -29
  378. package/dist/run/status.js +5 -27
  379. package/dist/run/stored-runs.js +2 -1
  380. package/dist/run/stream-shape.js +1 -1
  381. package/dist/run/streams.d.ts +6 -6
  382. package/dist/run/study-provenance.d.ts +47 -0
  383. package/dist/run/study-provenance.js +63 -0
  384. package/dist/run/study-result.d.ts +16 -0
  385. package/dist/run/study-result.js +9 -0
  386. package/dist/run/text.d.ts +2 -0
  387. package/dist/run/text.js +4 -0
  388. package/dist/run-lab.d.ts +7 -7
  389. package/dist/run-lab.js +1 -3
  390. package/dist/study/convert.d.ts +33 -0
  391. package/dist/study/convert.js +432 -0
  392. package/dist/study/field-paths.d.ts +12 -0
  393. package/dist/study/field-paths.js +126 -0
  394. package/dist/study/files.d.ts +26 -0
  395. package/dist/study/files.js +43 -0
  396. package/dist/study/migrate.d.ts +48 -0
  397. package/dist/study/migrate.js +408 -0
  398. package/dist/study/owned-files.d.ts +38 -0
  399. package/dist/study/owned-files.js +182 -0
  400. package/dist/subject/clone.d.ts +1 -1
  401. package/dist/subject/desktop-cli.d.ts +1 -1
  402. package/dist/subject/desktop-cli.js +2 -2
  403. package/dist/subject/local-tree-archive.js +1 -1
  404. package/dist/subject/local-tree.d.ts +1 -1
  405. package/dist/subject/node-bootstrap.js +1 -1
  406. package/dist/subject/runtime.js +8 -9
  407. package/dist/subject/serve.d.ts +1 -1
  408. package/dist/subject/serve.js +3 -3
  409. package/dist/subject/state.d.ts +1 -1
  410. package/dist/subject/steps.d.ts +5 -5
  411. package/dist/subject/steps.js +4 -4
  412. package/dist/substrates/command-failure.d.ts +3 -3
  413. package/dist/substrates/command-failure.js +3 -3
  414. package/dist/substrates/detached.d.ts +6 -6
  415. package/dist/substrates/detached.js +7 -7
  416. package/dist/substrates/e2b/cdp-probe.d.ts +9 -9
  417. package/dist/substrates/e2b/cdp-probe.js +14 -17
  418. package/dist/substrates/e2b/desktop-browser.d.ts +2 -2
  419. package/dist/substrates/e2b/desktop-browser.js +8 -8
  420. package/dist/substrates/e2b/desktop-cdp.d.ts +9 -9
  421. package/dist/substrates/e2b/desktop-cdp.js +8 -8
  422. package/dist/substrates/e2b/desktop-executor.d.ts +1 -1
  423. package/dist/substrates/e2b/desktop-executor.js +1 -1
  424. package/dist/substrates/e2b/desktop-geometry.d.ts +3 -3
  425. package/dist/substrates/e2b/desktop-geometry.js +7 -7
  426. package/dist/substrates/e2b/desktop-media.d.ts +1 -1
  427. package/dist/substrates/e2b/desktop-media.js +1 -1
  428. package/dist/substrates/e2b/desktop-screenshot-cleanup.d.ts +3 -3
  429. package/dist/substrates/e2b/desktop-screenshot-cleanup.js +3 -3
  430. package/dist/substrates/e2b/sandbox.d.ts +1 -1
  431. package/dist/substrates/e2b/sandbox.js +1 -1
  432. package/dist/substrates/e2b/sdk.d.ts +11 -11
  433. package/dist/substrates/e2b/sdk.js +6 -6
  434. package/dist/tui/actions.d.ts +1 -1
  435. package/dist/tui/actions.js +13 -13
  436. package/dist/tui/contract.d.ts +16 -16
  437. package/dist/tui/contract.js +10 -10
  438. package/dist/tui/launch.d.ts +4 -4
  439. package/dist/tui/launch.js +18 -19
  440. package/dist/tui/project.js +5 -5
  441. package/dist/tui-app.js +82 -82
  442. package/dist/verify/actor.d.ts +8 -8
  443. package/dist/verify/actor.js +36 -36
  444. package/dist/verify/artifacts.d.ts +2 -2
  445. package/dist/verify/artifacts.js +3 -3
  446. package/dist/verify/context-growth.d.ts +9 -0
  447. package/dist/verify/context-growth.js +62 -0
  448. package/dist/verify/costs.d.ts +6 -6
  449. package/dist/verify/costs.js +8 -8
  450. package/dist/verify/shared-world-concurrent.d.ts +2 -2
  451. package/dist/verify/shared-world-concurrent.js +79 -76
  452. package/dist/verify/shared-world.d.ts +2 -2
  453. package/dist/verify/shared-world.js +16 -16
  454. package/dist/verify/subject.d.ts +4 -4
  455. package/dist/verify/subject.js +18 -18
  456. package/dist/verify/verify.js +92 -43
  457. package/docs/README.md +25 -32
  458. package/docs/architecture/actor-contract.md +56 -87
  459. package/docs/architecture/desktop-sessions.md +7 -7
  460. package/docs/architecture/external-public-shared-world.md +61 -59
  461. package/docs/architecture/github-feedback-loop.md +1 -4
  462. package/docs/architecture/guest-desktop.md +2 -2
  463. package/docs/architecture/observer.md +34 -34
  464. package/docs/architecture/restricted-codex-analysis.md +34 -28
  465. package/docs/architecture/serve.md +34 -37
  466. package/docs/architecture/state-driven-executor.md +55 -58
  467. package/docs/architecture/task-protocol-support.md +5 -5
  468. package/docs/architecture/terminal-product-route.md +67 -107
  469. package/docs/contracts/README.md +24 -0
  470. package/docs/contracts/adapter-admission.md +3 -3
  471. package/docs/contracts/adapter-fixtures.md +2 -5
  472. package/docs/contracts/core.md +1 -3
  473. package/docs/contracts/errors.md +62 -0
  474. package/docs/contracts/feedback.md +8 -9
  475. package/docs/contracts/policy.md +7 -12
  476. package/docs/contracts/run-bundle.md +45 -44
  477. package/docs/contracts/schemas.md +421 -362
  478. package/docs/contracts/study-analysis.md +3 -3
  479. package/docs/contracts/study-costs.md +11 -7
  480. package/docs/decisions/0001-run-bundle-is-the-source-of-truth.md +1 -1
  481. package/docs/decisions/0002-observer-is-one-self-contained-file.md +2 -2
  482. package/docs/decisions/0003-contained-paths-and-cleanup-authority.md +3 -3
  483. package/docs/principles/actor-fidelity.md +4 -4
  484. package/docs/principles/engineering.md +3 -3
  485. package/docs/principles/invariants-and-defaults.md +38 -38
  486. package/docs/principles/self-driving-harness.md +1 -5
  487. package/docs/principles/three-roles.md +1 -1
  488. package/docs/product/automatic-analysis.md +7 -7
  489. package/examples/participant/README.md +5 -5
  490. package/examples/participant/run.mjs +11 -10
  491. package/examples/scorer/README.md +3 -3
  492. package/examples/scorer/run.mjs +11 -12
  493. package/package.json +16 -17
  494. package/skills/humanish/SKILL.md +60 -58
  495. package/skills/humanish/agents/openai.yaml +1 -1
  496. package/AGENTS.md +0 -99
  497. package/CONTRIBUTING.md +0 -148
  498. package/dist/actors/codex/qualified-versions.d.ts +0 -72
  499. package/dist/actors/codex/qualified-versions.js +0 -132
  500. package/dist/cli/commands/lab.d.ts +0 -3
  501. package/dist/cli/commands/lab.js +0 -199
  502. package/dist/cli/renamed-options.d.ts +0 -11
  503. package/dist/cli/renamed-options.js +0 -18
  504. package/dist/observer/static.d.ts +0 -39
  505. package/dist/observer/static.js +0 -369
  506. package/docs/architecture/comms-inbox.md +0 -122
  507. package/docs/architecture/desktop-recording.md +0 -80
  508. package/docs/architecture/local-browser-runtime.md +0 -178
  509. package/docs/architecture/observer-review.md +0 -144
  510. package/docs/architecture/participant-media.md +0 -90
  511. package/docs/architecture/project-layout.md +0 -62
  512. package/docs/architecture/real-email-receiving.md +0 -136
  513. package/docs/assets/humanish-drawdb-hero.png +0 -0
  514. package/docs/assets/humanish-observer-hero.png +0 -0
  515. package/docs/goals/current.md +0 -207
  516. package/docs/product/lobby-trivia-3player-external-public.md +0 -77
  517. package/docs/product/open-source-install-experience.md +0 -240
  518. package/docs/ramp/README.md +0 -295
  519. package/docs/release/open-source-readiness.md +0 -222
  520. package/docs/release/public-readiness-standard.md +0 -210
  521. package/docs/roadmap/world-class-open-source-v0.md +0 -311
@@ -5,16 +5,16 @@ import { type CuaSubjectProvenanceArg, type ParticipantRunOutcome } from "./type
5
5
  /** The human-readable state story appended to the provenance event (and review.md via it). */
6
6
  export declare function describeSubjectState(state: RunSubjectProvenance["state"], dryRun: boolean): string;
7
7
  /**
8
- * Feedback candidates derived from what LIVE participants actually reported (#392).
8
+ * Feedback candidates derived from what live participants actually reported.
9
9
  *
10
- * A live run's feedback draft used to fall through to a dry-run template, because no browser route
11
- * ever built a candidate. The candidate worth filing is the one the study produced: a participant
10
+ * A live run's feedback draft comes from these candidates, never from a dry-run template. The
11
+ * candidate worth filing is the one the study produced: a participant
12
12
  * who reported friction on the way (the most valuable thing a run captures), or one who stopped
13
- * trying. A clean pass files nothing here — feedback exists to carry findings, and a run without
14
- * any falls back to an honest live summary in the draft layer instead of a template.
13
+ * trying. A clean pass files nothing here: feedback exists to carry findings, and a run without
14
+ * any falls back to a live summary in the draft layer instead of a template.
15
15
  *
16
- * Everything quoted is already scrub+redacted — participant messages and `session.reason` pass
17
- * through redactNarration in the loop — and passes redactText again here as defense-in-depth.
16
+ * Everything quoted is already scrub+redacted (participant messages and `session.reason` pass
17
+ * through redactNarration in the loop) and passes redactText again here as defense-in-depth.
18
18
  */
19
19
  export declare function participantFeedbackCandidates(args: {
20
20
  runId: string;
@@ -34,8 +34,8 @@ export declare function participantFeedbackCandidates(args: {
34
34
  commsArtifactPath?: string;
35
35
  }>;
36
36
  }): RunFeedbackCandidate[];
37
- /** Human-readable provenance line for the single-participant subject.provenance event (invariant 5):
38
- * claims "cloned/packed and served" ONLY when it actually happened. */
37
+ /** Human-readable provenance line for the single-participant subject.provenance event:
38
+ * claims "cloned/packed and served" only when it actually happened. */
39
39
  export declare function subjectProvenanceMessage(provenance: CuaSubjectProvenanceArg, publicAppUrl: string, dryRun: boolean, hasSession: boolean): string;
40
40
  export declare function providerResourcesForOutcome(args: {
41
41
  outcome: ParticipantRunOutcome | undefined;
@@ -14,9 +14,9 @@ export function describeSubjectState(state, dryRun) {
14
14
  case "seeded":
15
15
  return `seeded (${state.seed?.length ?? 0} step(s): ${(state.seed ?? []).map((record) => record.name).join(", ")})`;
16
16
  case "unpinned":
17
- return `UNPINNED (external: ${(state.externalEnvNames ?? []).join(", ")})`;
17
+ return `unpinned (external: ${(state.externalEnvNames ?? []).join(", ")})`;
18
18
  case "declared-not-run":
19
- return `declared, not run (${dryRun ? "dry-run contract" : "provisioning did not complete"})`;
19
+ return `declared, not run (${dryRun ? "dry run" : "provisioning did not complete"})`;
20
20
  case "undeclared":
21
21
  return "undeclared";
22
22
  case "external-public":
@@ -24,16 +24,16 @@ export function describeSubjectState(state, dryRun) {
24
24
  }
25
25
  }
26
26
  /**
27
- * Feedback candidates derived from what LIVE participants actually reported (#392).
27
+ * Feedback candidates derived from what live participants actually reported.
28
28
  *
29
- * A live run's feedback draft used to fall through to a dry-run template, because no browser route
30
- * ever built a candidate. The candidate worth filing is the one the study produced: a participant
29
+ * A live run's feedback draft comes from these candidates, never from a dry-run template. The
30
+ * candidate worth filing is the one the study produced: a participant
31
31
  * who reported friction on the way (the most valuable thing a run captures), or one who stopped
32
- * trying. A clean pass files nothing here — feedback exists to carry findings, and a run without
33
- * any falls back to an honest live summary in the draft layer instead of a template.
32
+ * trying. A clean pass files nothing here: feedback exists to carry findings, and a run without
33
+ * any falls back to a live summary in the draft layer instead of a template.
34
34
  *
35
- * Everything quoted is already scrub+redacted — participant messages and `session.reason` pass
36
- * through redactNarration in the loop — and passes redactText again here as defense-in-depth.
35
+ * Everything quoted is already scrub+redacted (participant messages and `session.reason` pass
36
+ * through redactNarration in the loop) and passes redactText again here as defense-in-depth.
37
37
  */
38
38
  export function participantFeedbackCandidates(args) {
39
39
  const candidates = [];
@@ -59,8 +59,8 @@ export function participantFeedbackCandidates(args) {
59
59
  persona_id: participant.personaId,
60
60
  actor: "computer-use",
61
61
  substrate: args.substrate,
62
- // The participant is reporting on the PRODUCT: friction and abandonment are target-app
63
- // findings by the three-roles rule. A harness failure never reaches this builder — it is
62
+ // The participant is reporting on the product: friction and abandonment are target-app
63
+ // findings by the three-roles rule. A harness failure never reaches this builder; it is
64
64
  // not a participant report.
65
65
  failure_owner: "target-app",
66
66
  summary,
@@ -109,12 +109,12 @@ export function participantFeedbackCandidates(args) {
109
109
  }
110
110
  return candidates;
111
111
  }
112
- /** Human-readable provenance line for the single-participant subject.provenance event (invariant 5):
113
- * claims "cloned/packed and served" ONLY when it actually happened. */
112
+ /** Human-readable provenance line for the single-participant subject.provenance event:
113
+ * claims "cloned/packed and served" only when it actually happened. */
114
114
  export function subjectProvenanceMessage(provenance, publicAppUrl, dryRun, hasSession) {
115
115
  if (provenance.source === "clone") {
116
116
  if (dryRun) {
117
- return `Subject declared: clone of ${provenance.repo}, to be served at ${publicAppUrl} in-sandbox (dry-run contract; nothing cloned)`;
117
+ return `Subject declared: clone of ${provenance.repo}, to be served at ${publicAppUrl} in-sandbox (dry run; nothing cloned)`;
118
118
  }
119
119
  if (provenance.commit) {
120
120
  return hasSession
@@ -124,7 +124,7 @@ export function subjectProvenanceMessage(provenance, publicAppUrl, dryRun, hasSe
124
124
  return `Subject clone attempted from ${provenance.repo}; commit unresolved (provisioning failed before resolution)`;
125
125
  }
126
126
  if (dryRun) {
127
- return `Subject declared: local working tree, to be packed and served at ${publicAppUrl} in-sandbox (dry-run contract; nothing packed)`;
127
+ return `Subject declared: local working tree, to be packed and served at ${publicAppUrl} in-sandbox (dry run; nothing packed)`;
128
128
  }
129
129
  if (provenance.archiveSha256) {
130
130
  const dirtyLabel = provenance.dirty === true
@@ -2,7 +2,7 @@
2
2
  // and buildCuaRunBundle sends it to the single-participant or the fan-out builder with that
3
3
  // shape's arguments. renderCuaReviewMarkdown writes review.md. shared-world/bundle.ts holds the
4
4
  // same for that route.
5
- import { judgeOneParticipant, judgeParticipants } from "../../run/judge.js";
5
+ import { judgeOneParticipant, judgeParticipants, verdictText, } from "../../run/judge.js";
6
6
  import { desktopSpanToMinutes } from "../../run/cost-summary.js";
7
7
  import { e2bDesktopTemplate } from "../../substrates/e2b/sandbox.js";
8
8
  import { providerResourcesForOutcome } from "./bundle-parts.js";
@@ -157,13 +157,13 @@ export function renderCuaReviewMarkdown(bundle) {
157
157
  "",
158
158
  `- run: ${bundle.runId}`,
159
159
  `- mode: ${bundle.mode}`,
160
- `- run gate: ${bundle.review.verdict}`,
160
+ `- run gate: ${verdictText(bundle.review.verdict, bundle.mode)}`,
161
161
  `- summary: ${bundle.review.summary}`,
162
162
  ...(provenance ? [`- subject: ${provenance.message}`] : []),
163
163
  ...(trace
164
164
  ? [
165
165
  `- actor: ${trace.provider} (${trace.lane}/${trace.protocol})`,
166
- // Honest count: name the trace's actual screenshot mode ("raw" | "blurred"); say
166
+ // Name the trace's actual screenshot mode ("raw" | "blurred"); say
167
167
  // nothing when no frames exist ("n/a") rather than claim a redaction that never ran.
168
168
  `- evidence: ${trace.items.length} trace item(s), ${trace.counts.screenshots ?? 0} ${trace.redaction.screenshots === "raw" || trace.redaction.screenshots === "blurred"
169
169
  ? `${trace.redaction.screenshots} screenshot(s)`
@@ -19,7 +19,7 @@ export interface ParticipantComms {
19
19
  }
20
20
  /**
21
21
  * On an in-sandbox subject route, redirect the app's email-API sends into an in-sandbox catch
22
- * (loopback) so its verification mail is CAPTURED, not sent to the internet. Undefined when the
22
+ * (loopback) so its verification mail is captured instead of sent to the internet. Undefined when the
23
23
  * lab declares no fake email, which leaves the participant unchanged.
24
24
  */
25
25
  export declare function planParticipantComms(comms: LabConfig["comms"], serveUrl: string | undefined, targetUrl: string, inSandboxSubject: boolean): ParticipantComms | undefined;
@@ -1,4 +1,4 @@
1
- // Off-app email for one E2B desktop participant (#297): the in-sandbox catch the subject app sends to, the
1
+ // Off-app email for one E2B desktop participant: the in-sandbox catch the subject app sends to, the
2
2
  // persona's inbox surface, the real-email receiving surface, and the evidence drained at teardown.
3
3
  import { setTimeout as delay } from "node:timers/promises";
4
4
  import { buildOriginMap } from "../../../comms/capture-surface.js";
@@ -15,7 +15,7 @@ import { addressedRecipients } from "../../../lab/parse/comms.js";
15
15
  const INBOX_SURFACE_CADENCE_MS = 2500;
16
16
  /**
17
17
  * On an in-sandbox subject route, redirect the app's email-API sends into an in-sandbox catch
18
- * (loopback) so its verification mail is CAPTURED, not sent to the internet. Undefined when the
18
+ * (loopback) so its verification mail is captured instead of sent to the internet. Undefined when the
19
19
  * lab declares no fake email, which leaves the participant unchanged.
20
20
  */
21
21
  export function planParticipantComms(comms, serveUrl, targetUrl, inSandboxSubject) {
@@ -42,7 +42,7 @@ export function planParticipantComms(comms, serveUrl, targetUrl, inSandboxSubjec
42
42
  export function participantCommsEnv(comms) {
43
43
  if (comms === undefined)
44
44
  return {};
45
- // injectEnv is absent on an adopter-hosted plane (#328): there is no subject env to inject
45
+ // injectEnv is absent on an adopter-hosted plane: there is no subject env to inject
46
46
  // because the operator points their own app at their own catch.
47
47
  const env = comms.email.injectEnv === undefined
48
48
  ? {}
@@ -75,23 +75,23 @@ export async function startCommsCatch(shell, comms, requestTimeoutMs) {
75
75
  if (!deployed.ready) {
76
76
  throw new Error(`comms email catch did not become ready on 127.0.0.1:${comms.port} in the subject sandbox`);
77
77
  }
78
- // Write the EMPTY inbox once up front so the persona's /inbox always resolves to the "No messages
79
- // yet." page — never a bare 404 — the instant it navigates there, even before any mail arrives OR if
78
+ // Write the empty inbox once up front so the persona's /inbox always resolves to the "No messages
79
+ // yet." page (never a bare 404) the instant it navigates there, even before any mail arrives or if
80
80
  // the app sends to an address no declared recipient matches (the loop only re-renders on new mail).
81
81
  await writeInboxSurface(shell, deployed.surfaceDir, [], {
82
82
  originMap: comms.originMap,
83
83
  requestTimeoutMs,
84
84
  });
85
- // The surface uses its OWN FakeInbox + cursor, independent of the teardown evidence drain (two
86
- // readers of the append-only NDJSON — no double-count).
85
+ // The surface uses its own FakeInbox + cursor, independent of the teardown evidence drain (two
86
+ // readers of the append-only NDJSON, so no double-count).
87
87
  const stop = new AbortController();
88
88
  let renderedCount = 0;
89
89
  const loop = (async () => {
90
90
  // Render-first (so even a short session gets a populated inbox), then refresh on a cadence. The
91
- // cadence uses a REAL timer, NOT the injected instant clock: this loop is unbounded, so an instant
91
+ // cadence uses a real timer instead of the injected instant clock: this loop is unbounded, so an instant
92
92
  // sleep would busy-spin and starve the session's own timers. `stop` interrupts the wait
93
93
  // (and clears the timer) so teardown never blocks for a full cadence. Each refresh
94
- // is a full, idempotent rebuild; `renderedCount` only advances on a SUCCESSFUL render so a
94
+ // is a full, idempotent rebuild; `renderedCount` only advances on a successful render so a
95
95
  // transient failure retries cleanly (no duplicate emails).
96
96
  for (;;) {
97
97
  try {
@@ -200,19 +200,19 @@ export async function drainCommsEvidence(args) {
200
200
  return path;
201
201
  }
202
202
  if (collected.captured > 0) {
203
- // Captured mail that matched no declared recipient must not vanish silently (invariant 6:
204
- // honest signals): tell the operator to declare comms.email.recipients[].address to match
203
+ // Captured mail that matched no declared recipient must not vanish silently: tell the
204
+ // operator to declare comms.email.recipients[].address to match
205
205
  // the address the app actually sends to (e.g. the one the persona surface will sign up with).
206
- warnings.push(`Comms catch captured ${collected.captured} email send(s) but none matched a declared recipient inbox — no comms evidence written. Declare comms.email.recipients[].address to match the address the app sends to.`);
206
+ warnings.push(`The email catch captured ${collected.captured} email send(s), but none matched a declared recipient inbox, so no email evidence was written. Set comms.email.recipients[].address to the address the app sends to.`);
207
207
  }
208
208
  else {
209
- // Zero captures is the silent-broken shape (#351): the app never posted to the catch at
209
+ // Zero captures is the silent-broken shape: the app never posted to the catch at
210
210
  // all, so the personas stared at an empty inbox. Most common cause: the app does not
211
211
  // actually read the declared injectEnv var for its email API base URL.
212
212
  const transportHint = comms.email.smtp
213
213
  ? `Verify the app reads ${comms.email.smtp.hostEnv}/${comms.email.smtp.portEnv} for its SMTP host and port`
214
214
  : `Verify the app reads ${comms.email.injectEnv} for its email API base URL (an SDK that ignores it sends real mail or throws)`;
215
- warnings.push(`Comms catch captured ZERO email sends — the app never delivered mail through the catch. ${transportHint} and that the flow reached an email step.`);
215
+ warnings.push(`The email catch captured no email sends: the app never delivered mail through it. ${transportHint} and that the flow reached an email step.`);
216
216
  }
217
217
  }
218
218
  catch (error) {
@@ -15,7 +15,7 @@ export function createE2BParticipantDesktop(spec, deps, warnings) {
15
15
  warnings,
16
16
  targetUrl,
17
17
  desktopCliRoute: deps.subject.kind === "desktop-cli",
18
- // Off-app comms (#297): gated entirely on config.comms; no comms declared, no change.
18
+ // Off-app comms: gated entirely on config.comms; no comms declared, no change.
19
19
  comms: planParticipantComms(deps.residual.comms, participantServeUrl(deps.subject), targetUrl, deps.subject.kind === "clone" || deps.subject.kind === "local-tree"),
20
20
  // The default or injected sink sees every event, started and completed alike, so an operator
21
21
  // watching stderr sees both halves of each phase; the state keeps only completed ones.
@@ -23,9 +23,9 @@ export function createE2BParticipantDesktop(spec, deps, warnings) {
23
23
  if (event.ok !== undefined)
24
24
  state.phaseRecords.push(event);
25
25
  deps.reportSubjectPhase(event, {
26
- laneId: spec.planned.id,
27
- laneIndex: spec.planned.index,
28
- laneCount: deps.participantCount,
26
+ id: spec.planned.id,
27
+ index: spec.planned.index,
28
+ count: deps.participantCount,
29
29
  });
30
30
  },
31
31
  };
@@ -19,7 +19,8 @@ export declare function mobileLaunchFlags(residual: Readonly<ResidualConfig>, sp
19
19
  * observation. A request that cannot be applied fails the participant closed with the reason. Only
20
20
  * participants on a mobile preset are emulated: a run-wide flag must not hand a desktop or tablet
21
21
  * participant an iPhone user agent (the first live proof did exactly that to the desktop newcomer
22
- * beside the phone participant). Those participants carry no fidelity block, which is honest.
22
+ * beside the phone participant). Those participants carry no fidelity block, since nothing was
23
+ * emulated.
23
24
  */
24
25
  export declare function applyParticipantMobileFidelity(args: {
25
26
  desktop: E2BDesktopSandbox;
@@ -44,8 +45,8 @@ export declare function participantBrowserStateObserver(args: {
44
45
  }): ReturnType<typeof makeChromeBrowserStateObserver>;
45
46
  /**
46
47
  * The participant's final browser geometry, measured while the sandbox is alive. A final capture that
47
- * measured EITHER field wins whole, so a partial final capture omits fields the launch-time capture
48
- * had (honest omission); only a final capture that measured NOTHING falls back to the launch-time
48
+ * measured either field wins whole, so a partial final capture omits fields the launch-time capture
49
+ * had; only a final capture that measured nothing falls back to the launch-time
49
50
  * capture. Also reads the emulation holder's log into the fidelity block.
50
51
  */
51
52
  export declare function finalParticipantGeometry(args: {
@@ -1,5 +1,5 @@
1
- // Device fidelity for one E2B desktop participant: mobile emulation beyond viewport size (#221), the
2
- // browser-state observer that watches it for drift (#623), and the final browser geometry.
1
+ // Device fidelity for one E2B desktop participant: mobile emulation beyond viewport size, the
2
+ // browser-state observer that watches it for drift, and the final browser geometry.
3
3
  import { redactText, toErrorMessage } from "../../../evidence/redaction.js";
4
4
  import { readDetachedLog } from "../../../substrates/detached.js";
5
5
  import { applyMobileEmulation, DEFAULT_MOBILE_USER_AGENT, makeChromeBrowserStateObserver, } from "../../../substrates/e2b/desktop-cdp.js";
@@ -28,7 +28,8 @@ function cdpEndpoint(identity, targetUrl) {
28
28
  * observation. A request that cannot be applied fails the participant closed with the reason. Only
29
29
  * participants on a mobile preset are emulated: a run-wide flag must not hand a desktop or tablet
30
30
  * participant an iPhone user agent (the first live proof did exactly that to the desktop newcomer
31
- * beside the phone participant). Those participants carry no fidelity block, which is honest.
31
+ * beside the phone participant). Those participants carry no fidelity block, since nothing was
32
+ * emulated.
32
33
  */
33
34
  export async function applyParticipantMobileFidelity(args) {
34
35
  const { spec, deps } = args;
@@ -63,10 +64,10 @@ export function participantBrowserStateObserver(args) {
63
64
  return makeChromeBrowserStateObserver(args.desktop, deps.requestTimeoutMs, cdpEndpoint(args.launchIdentity, args.targetUrl), {
64
65
  targetId: args.targetId,
65
66
  // Once per participant: a dark observation channel is a gap in the instrument, and the
66
- // funnel's NEVER MEASURED count needs this line to explain itself (#514).
67
+ // funnel's "never measured" count needs this line to explain itself.
67
68
  onUnavailable: (reason) => {
68
69
  warnings.push(`Browser-state observer unavailable for participant ${spec.planned.id} (${redactText(deps.scrubKnownValues(reason))}); ` +
69
- "urlIncludes/urlPathEquals/textIncludes stop conditions and task criteria are NOT being measured this session.");
70
+ "urlIncludes, urlPathEquals and textIncludes stop conditions and task criteria are not measured in this session.");
70
71
  },
71
72
  drift: fidelity.emulatedTargetId === undefined
72
73
  ? undefined
@@ -75,11 +76,11 @@ export function participantBrowserStateObserver(args) {
75
76
  expectedWidth: spec.planned.device.preset.width,
76
77
  expectTouch: fidelity.applied?.requested.touch === true,
77
78
  onDrift: (reason) => {
78
- warnings.push(`Mobile emulation drift for participant ${spec.planned.id}: ${reason} (#623).`);
79
+ warnings.push(`Mobile emulation drift for participant ${spec.planned.id}: ${reason}.`);
79
80
  },
80
81
  onCovered: (coveredTargetId, read) => {
81
82
  // A later tab the page itself reported at the phone width: evidence that
82
- // the emulation followed the participant (#623), kept on the bundle.
83
+ // the emulation followed the participant, kept on the bundle.
83
84
  if (fidelity.applied === undefined)
84
85
  return;
85
86
  fidelity.applied = {
@@ -95,8 +96,8 @@ export function participantBrowserStateObserver(args) {
95
96
  }
96
97
  /**
97
98
  * The participant's final browser geometry, measured while the sandbox is alive. A final capture that
98
- * measured EITHER field wins whole, so a partial final capture omits fields the launch-time capture
99
- * had (honest omission); only a final capture that measured NOTHING falls back to the launch-time
99
+ * measured either field wins whole, so a partial final capture omits fields the launch-time capture
100
+ * had; only a final capture that measured nothing falls back to the launch-time
100
101
  * capture. Also reads the emulation holder's log into the fidelity block.
101
102
  */
102
103
  export async function finalParticipantGeometry(args) {
@@ -126,7 +127,7 @@ export async function finalParticipantGeometry(args) {
126
127
  ];
127
128
  warnings.push(...geometryWarnings);
128
129
  // The emulation holder's own log, after its announce line: which later targets it
129
- // attached to, what it sent, and any reply that came back as an error (#623). Read while
130
+ // attached to, what it sent, and any reply that came back as an error. Read while
130
131
  // the sandbox is alive; the first live proof had no way to say what the holder did.
131
132
  if (fidelity.applied !== undefined && fidelity.holderName !== undefined) {
132
133
  const holderLog = await readDetachedLog(e2bShell(desktop), fidelity.holderName, deps.requestTimeoutMs).catch(() => "");
@@ -24,7 +24,7 @@ export async function acquireParticipantDesktop(ctx, state) {
24
24
  const { residual, env } = deps;
25
25
  const subjectEnvNames = participantSubjectEnv(deps.subject);
26
26
  const subjectEnvValues = residual.subject.envValues ?? {};
27
- // Off-app comms (#297): the base-URL env is injected at sandbox create, so the app reads it at
27
+ // Off-app comms: the base-URL env is injected at sandbox create, so the app reads it at
28
28
  // boot; the catch starts right after create.
29
29
  const commsEnv = participantCommsEnv(ctx.comms);
30
30
  const desktopModule = await (deps.desktopModule ?? loadE2BDesktopModule)();
@@ -39,10 +39,10 @@ export async function acquireParticipantDesktop(ctx, state) {
39
39
  metadata: {
40
40
  ...CUA_ACTOR_LAB_PROVIDER_METADATA,
41
41
  labId: deps.labId,
42
- simId: spec.recordId,
43
- laneId: spec.planned.id,
44
- laneIndex: String(spec.planned.index),
45
- laneCount: String(deps.participantCount),
42
+ recordId: spec.recordId,
43
+ participantId: spec.planned.id,
44
+ participantIndex: String(spec.planned.index),
45
+ participantCount: String(deps.participantCount),
46
46
  },
47
47
  // The participant's model key never enters the sandbox (the model drives from outside).
48
48
  // The subject's declared env names are provisioned here on the clone route.
@@ -129,7 +129,7 @@ export async function verifyParticipantScreen(ctx, state, desktop) {
129
129
  state.desktopGeometry = { ...state.desktopGeometry, warnings: [screenGeometry.warning] };
130
130
  }
131
131
  if (screenGeometry.error && deps.screenMismatchPolicy !== "record-evidence") {
132
- state.failureCode = "HUMANISH_CUA_LAB_DEVICE_GEOMETRY";
132
+ state.failureCode = "HUMANISH_COMPUTER_USE_DEVICE_GEOMETRY";
133
133
  throw new Error(screenGeometry.error);
134
134
  }
135
135
  if (screenGeometry.error && screenGeometry.verified) {
@@ -149,7 +149,7 @@ export async function provisionParticipantSubject(ctx, state, desktop) {
149
149
  const { residual, subject } = deps;
150
150
  const shell = e2bShell(desktop);
151
151
  if (subject.kind === "desktop-cli") {
152
- // Prepare the runtime and any declared product install, UNKEYED. With install omitted,
152
+ // Prepare the runtime and any declared product install, with no keys. With install omitted,
153
153
  // the participant discovers and installs the product from its public surfaces.
154
154
  await provisionDesktopCli(shell, {
155
155
  product: subject.product.name,
@@ -7,6 +7,7 @@ import { captureDesktopBrowserGeometry } from "../../../substrates/e2b/desktop-g
7
7
  import { prepareDesktopMedia, startE2BDesktopMedia, } from "../../../substrates/e2b/desktop-media.js";
8
8
  import { startE2BDesktopRecording } from "../../../substrates/e2b/desktop-recording.js";
9
9
  import { applyParticipantMobileFidelity, mobileLaunchFlags } from "./fidelity.js";
10
+ import { streamEvent } from "../../../lab/run-lab-homes.js";
10
11
  /** Start the declared speech worker and screen recording. A recording that cannot start is a warning. */
11
12
  export async function startParticipantMedia(ctx, state, desktop) {
12
13
  const { spec, deps, warnings } = ctx;
@@ -47,13 +48,13 @@ export async function openParticipantSurface(ctx, state, desktop) {
47
48
  if (subject.kind === "desktop-cli") {
48
49
  // A terminal window, opened the way the browser is opened on every other route: the
49
50
  // participant arrives at a desktop with the thing they were asked to use already in front
50
- // of them. They can still open another from the dock — that is the point of a desktop.
51
+ // of them. They can still open another from the dock; that is the point of a desktop.
51
52
  await openDesktopTerminal(desktop, deps.requestTimeoutMs, subject.product.workdir);
52
53
  await desktop.wait(DESKTOP_SETTLE_MS).catch(() => undefined);
53
54
  return;
54
55
  }
55
56
  const requestedMedia = residual.execution?.desktop?.media;
56
- // A declared camera (#509) is in place before the browser starts: the feed is generated or
57
+ // A declared camera is in place before the browser starts: the feed is generated or
57
58
  // uploaded first, and a feed that cannot be produced fails the participant closed here.
58
59
  const mediaEvidence = requestedMedia === undefined
59
60
  ? undefined
@@ -76,7 +77,7 @@ export async function openParticipantSurface(ctx, state, desktop) {
76
77
  state.browserLaunched = true;
77
78
  noteDevToolsReadiness(ctx, browserLaunch.devTools, emulationFlags.length > 0);
78
79
  await desktop.wait(DESKTOP_SETTLE_MS).catch(() => undefined);
79
- // Mobile fidelity (#221) is applied outside startParticipantStream's best-effort catch, so a request
80
+ // Mobile fidelity is applied outside startParticipantStream's best-effort catch, so a request
80
81
  // that cannot be applied fails the participant closed.
81
82
  state.fidelity = await applyParticipantMobileFidelity({
82
83
  desktop,
@@ -91,7 +92,7 @@ export async function openParticipantSurface(ctx, state, desktop) {
91
92
  }
92
93
  /**
93
94
  * DevTools answering later than this after launch is recorded as a warning on the participant. Six live
94
- * launches answered in 4.8-7.7 s; the reads this wait now guards used to give up at about 11 s.
95
+ * launches answered in 4.8-7.7 s; without this wait the reads it guards give up at about 11 s.
95
96
  */
96
97
  const SLOW_DEVTOOLS_MS = 10_000;
97
98
  /**
@@ -168,14 +169,14 @@ export async function startParticipantStream(ctx, state, desktop) {
168
169
  });
169
170
  if (typeof candidateStreamUrl === "string" && candidateStreamUrl.trim().length > 0) {
170
171
  state.streamUrl = candidateStreamUrl;
171
- await deps.onStream({
172
+ await deps.onStream(streamEvent({
172
173
  type: "ready",
173
174
  participantId: spec.planned.id,
174
175
  sandboxId: desktop.sandboxId,
175
- simId: spec.recordId,
176
+ recordId: spec.recordId,
176
177
  streamId: spec.streamId,
177
178
  url: candidateStreamUrl,
178
- });
179
+ }));
179
180
  }
180
181
  else {
181
182
  warnings.push("Live desktop stream started but did not return a usable watch URL; Observer will fall back to screenshots.");
@@ -188,7 +189,7 @@ export async function startParticipantStream(ctx, state, desktop) {
188
189
  // never a participant finding about missing controls. Both computer-use and shared-world participants
189
190
  // use this route.
190
191
  if (state.initialBrowserGeometry?.unusable !== undefined) {
191
- state.failureCode = "HUMANISH_CUA_LAB_DEVICE_GEOMETRY";
192
+ state.failureCode = "HUMANISH_COMPUTER_USE_DEVICE_GEOMETRY";
192
193
  throw new Error(`${state.failureCode}: ${state.initialBrowserGeometry.unusable} Participant actions were not started.`);
193
194
  }
194
195
  }
@@ -7,6 +7,7 @@ import { readE2BRelease } from "../../../substrates/e2b/sandbox.js";
7
7
  import { e2bShell } from "../../../substrates/e2b/shell.js";
8
8
  import { drainCommsEvidence } from "./comms.js";
9
9
  import { finalParticipantGeometry } from "./fidelity.js";
10
+ import { streamEvent } from "../../../lab/run-lab-homes.js";
10
11
  /**
11
12
  * Each route's own keep flag gates its own participants only: a clone.keep can never leak into a
12
13
  * local-tree participant's teardown decision, and vice versa.
@@ -145,16 +146,16 @@ export async function finishE2BDesktop(ctx, state, failed) {
145
146
  state.sandboxTornDownAtMs = deps.now();
146
147
  // The participant's live stream is now a dead page whichever teardown path ran (released, kept, or
147
148
  // release-failed-awaiting-TTL); tell the watch overlay so the tile falls back to recorded
148
- // evidence instead of "sandbox not found" (#357). Guarded: a viewer callback must never
149
+ // evidence instead of "sandbox not found". Guarded: a viewer callback must never
149
150
  // break teardown.
150
151
  if (state.streamUrl !== undefined) {
151
152
  try {
152
- await deps.onStream({
153
+ await deps.onStream(streamEvent({
153
154
  type: "ended",
154
155
  participantId: spec.planned.id,
155
- simId: spec.recordId,
156
+ recordId: spec.recordId,
156
157
  streamId: spec.streamId,
157
- });
158
+ }));
158
159
  }
159
160
  catch {
160
161
  // viewer-side only; nothing to record
@@ -2,7 +2,7 @@ import type { LabCommsEmail, LabCommsExternal } from "../../lab/types.js";
2
2
  import type { PreparedRunArtifactPaths } from "../../run/paths.js";
3
3
  import type { DesktopParticipantRun, ParticipantRunOutcome } from "./types.js";
4
4
  /**
5
- * Adopter-hosted drain (#380): once per RUN, after every participant finished — the catch is one
5
+ * Adopter-hosted drain: once per run, after every participant finished, because the catch is one
6
6
  * shared external endpoint, not a per-sandbox file. Same routing and digest-only artifact as
7
7
  * the in-sandbox drain; the artifact is registered on every participant that declared a recipient
8
8
  * address, since the thread carries each inbox's mail. A drain failure never fails the run.
@@ -1,7 +1,7 @@
1
1
  import { collectExternalCommsEvidence } from "../../comms/external-evidence.js";
2
2
  import { participantHasInboxRecipient } from "./participant-desktop.js";
3
3
  /**
4
- * Adopter-hosted drain (#380): once per RUN, after every participant finished — the catch is one
4
+ * Adopter-hosted drain: once per run, after every participant finished, because the catch is one
5
5
  * shared external endpoint, not a per-sandbox file. Same routing and digest-only artifact as
6
6
  * the in-sandbox drain; the artifact is registered on every participant that declared a recipient
7
7
  * address, since the thread carries each inbox's mail. A drain failure never fails the run.
@@ -35,26 +35,26 @@ function fanoutReview(args, streams) {
35
35
  // The judge's verdict: live fan-out must prove every participant (judgeParticipants).
36
36
  const verdict = args.verdict;
37
37
  const passedParticipants = (outcomes ?? []).filter((outcome) => participantPassed(participantFactsOf(outcome))).length;
38
- // What happened to the PARTICIPANTS, with the denominator attached. The verdict above has to
38
+ // What happened to the participants, with the denominator attached. The verdict above has to
39
39
  // collapse the run to one word; this does not (docs/principles/three-roles.md).
40
40
  const terminalOutcomes = (outcomes ?? []).filter((outcome) => outcome?.session?.status !== undefined);
41
41
  const participants = terminalOutcomes.length > 0
42
42
  ? tallyParticipantOutcomes(
43
- // A NO-ENGAGEMENT participant is not one who reached the goal. It said "done" having
43
+ // A no-engagement participant is not one who reached the goal. It said "done" having
44
44
  // taken zero actions and said nothing, and `passedParticipants` above already refuses to
45
- // count it — but `reachedGoal` was reading the trace status directly, so one run could be both
46
- // "not a passed participant" AND "1/1 reached the goal". The headline number a researcher reads
45
+ // count it, but `reachedGoal` was reading the trace status directly, so one run could be both
46
+ // "not a passed participant" and "1/1 reached the goal". The headline number a researcher reads
47
47
  // first was the dishonest one. Found by a provider bug that ended a study on turn one.
48
48
  terminalOutcomes.map((outcome) => participantStatus(outcome.session.status, {
49
49
  noEngagement: outcome.noEngagement === true,
50
50
  selfReportedBlocker: outcome.selfReportedBlocker === true,
51
51
  })),
52
- // A participant who reached the goal AND told you the road there was broken is the most
52
+ // A participant who reached the goal and told you the road there was broken is the most
53
53
  // useful result a study produces; reporting only the outcome would bury it.
54
54
  terminalOutcomes.map((outcome) => outcome.reportedFriction === true))
55
55
  : undefined;
56
56
  // The study funnel: per-task completion rates across every session that measured one. This is
57
- // "where did people get stuck" as data, next to WHO got stuck (participants) above.
57
+ // "where did people get stuck" as data, next to who got stuck (participants) above.
58
58
  const participantFunnels = (outcomes ?? [])
59
59
  .map((outcome) => outcome?.session?.trace.taskFunnel)
60
60
  .filter((funnel) => funnel !== undefined);
@@ -74,12 +74,12 @@ function fanoutReview(args, streams) {
74
74
  summary: args.inProgress === true
75
75
  ? `Live computer-use fan-out is running (${specs.length} participants, one world each); terminal participant evidence has not been written yet.`
76
76
  : args.dryRun
77
- ? `${args.rerun ? `Rerun contract from ${args.rerun.sourceRunId}: ` : ""}Dry-run fan-out contract: ${specs.length} participants composed for ${args.descriptor.id} against ${args.appUrl}, one world each; no desktops launched, $0 spend.`
77
+ ? `${args.rerun ? `Rerun from ${args.rerun.sourceRunId}: ` : ""}Dry-run fan-out: ${specs.length} participants composed for ${args.descriptor.id} against ${args.appUrl}, one world each; no desktops launched, $0 spend.`
78
78
  : `${args.rerun ? `Rerun from ${args.rerun.sourceRunId}: ` : ""}Computer-use fan-out (${specs.length} participants, one world each): ${passedParticipants}/${specs.length} participant(s) reached a terminal, engaged verdict${participants ? `: ${formatParticipantOutcomes(participants, participantEndings)}` : ""}${runTasks ? `; tasks: ${formatRunTaskFunnel(runTasks)}` : ""}.`,
79
79
  gaps: args.inProgress === true
80
80
  ? ["Live fan-out session is still running."]
81
81
  : args.dryRun
82
- ? ["Live fan-out session not yet run (dry-run contract only)."]
82
+ ? ["Live fan-out session not yet run (dry run only)."]
83
83
  : specs
84
84
  .map((spec, index) => ({ spec, outcome: outcomes?.[index] }))
85
85
  .filter(({ outcome }) => outcome === undefined ||
@@ -112,7 +112,7 @@ function fanoutDesktopBrowser(args) {
112
112
  }
113
113
  function fanoutCost(args) {
114
114
  const { specs, outcomes } = args;
115
- // Run-level cost ESTIMATE: one model-token line per participant that ran a session (from its persisted
115
+ // Run-level cost estimate: one model-token line per participant that ran a session (from its persisted
116
116
  // trace.estimatedCost) + a desktop line per owned allocation, priced at its observed resources.
117
117
  // `per-lane-worlds` participants have no shared provisioning to double-count. Omitted on a pure dry-run.
118
118
  const costTraces = specs
@@ -218,22 +218,22 @@ export function buildCuaFanoutBundle(args) {
218
218
  persona: {
219
219
  id: specs[0].persona.id,
220
220
  name: `Computer-use fan-out (${specs.length} participants)`,
221
- source: `lab:${plan.labId}`,
221
+ source: `study:${plan.labId}`,
222
222
  sourceDigest: specs[0].persona.promptDigest,
223
223
  },
224
224
  scenario: {
225
225
  id: `cua-${plan.labId}`,
226
226
  title: plan.title ?? `Computer-use fan-out: ${plan.labId}`,
227
- // Redacted at WRITE time, like every other raw-text surface in the bundle. Participant records are
228
- // digest-only by design, but scenario.goal keeps one participant's composed instructions verbatim —
227
+ // Redacted at write time, like every other raw-text surface in the bundle. Participant records are
228
+ // digest-only by design, but scenario.goal keeps one participant's composed instructions verbatim,
229
229
  // and an adopter whose authored participant text must name a runtime world URL (an inbox on a route
230
230
  // where the harness does not inject one) put an *.e2b.app address in it. That landed raw here
231
231
  // and in observer-data.json, the sensitive-text scanner matched it, and verify failed a bundle
232
- // this writer produced. The only adopter-side workaround was scanner evasion (#412).
232
+ // this writer produced. The only adopter-side workaround was scanner evasion.
233
233
  //
234
234
  // The instructions the model actually receives are untouched; only the persisted copy changes.
235
235
  goal: redactText(specs[0].evidenceInstructions ?? specs[0].instructions),
236
- source: `lab:${plan.labId}`,
236
+ source: `study:${plan.labId}`,
237
237
  sourceDigest: specs[0].persona.promptDigest,
238
238
  },
239
239
  lifecycle: [
@@ -251,14 +251,14 @@ export function buildCuaFanoutBundle(args) {
251
251
  status: "passed",
252
252
  notes: ranLive
253
253
  ? anyRaw
254
- ? "Typed text recorded as length only and reasoning/messages pass through text redaction. Some participants captured FULL-FIDELITY (raw) screenshots, retained for local use and NOT redacted for publishing; set policies.redactScreenshots: true to blur a share-as-is bundle."
254
+ ? "Typed text is recorded as its length only, and reasoning and messages pass through text redaction. Some participants captured unblurred screenshots, kept for local use and not redacted for publishing. Set policies.redactScreenshots: true to blur screenshots in a bundle you plan to share."
255
255
  : "Typed text recorded as length only and reasoning/messages pass through text redaction. Screenshots are blurred at capture (policies.redactScreenshots: true) for a share-as-is bundle."
256
- : "Dry-run fan-out contract bundle: no desktops launched and no screenshots captured. Typed text is recorded as length only and reasoning/messages pass through text redaction whenever a session runs.",
256
+ : "Dry-run fan-out bundle: no desktops launched and no screenshots captured. Typed text is recorded as length only and reasoning/messages pass through text redaction whenever a session runs.",
257
257
  },
258
258
  artifacts: bundleArtifacts(),
259
259
  review,
260
- // What the participants reported, when any reported anything (#392). Dry-run and in-progress
261
- // bundles carry none — there is no participant yet to quote.
260
+ // What the participants reported, when any reported anything. Dry-run and in-progress
261
+ // bundles carry none: there is no participant yet to quote.
262
262
  feedbackCandidates: fanoutFeedbackCandidates(args),
263
263
  // Selected hosted image, including the optional speech default; omitted on the stock desktop.
264
264
  ...(desktopTemplate === undefined ? {} : { desktopTemplate }),