humanish 0.105.0 → 0.106.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 (1408) hide show
  1. package/AGENTS.md +89 -94
  2. package/ARCHITECTURE.md +146 -0
  3. package/CHANGELOG.md +502 -0
  4. package/CONTEXT.md +51 -0
  5. package/CONTRIBUTING.md +111 -9
  6. package/README.md +213 -124
  7. package/SECURITY.md +1 -1
  8. package/TELEMETRY.md +112 -0
  9. package/dist/actors/affordance.d.ts +56 -0
  10. package/dist/actors/affordance.js +155 -0
  11. package/dist/actors/agent-session.js +42 -0
  12. package/dist/actors/codex/app-server-actor-trace.d.ts +11 -0
  13. package/dist/actors/codex/app-server-actor-trace.js +211 -0
  14. package/dist/actors/codex/app-server-client.d.ts +39 -0
  15. package/dist/actors/codex/app-server-client.js +116 -0
  16. package/dist/actors/codex/app-server-trace.d.ts +154 -0
  17. package/dist/actors/codex/app-server-trace.js +424 -0
  18. package/dist/actors/codex/app-server-ui.d.ts +40 -0
  19. package/dist/actors/codex/app-server-ui.js +328 -0
  20. package/dist/actors/codex/app-server.d.ts +44 -0
  21. package/dist/actors/codex/app-server.js +268 -0
  22. package/dist/actors/codex/qualified-versions.d.ts +45 -0
  23. package/dist/actors/codex/qualified-versions.js +87 -0
  24. package/dist/actors/codex/restricted-executable.d.ts +17 -0
  25. package/dist/actors/codex/restricted-executable.js +147 -0
  26. package/dist/actors/codex/restricted-launch.d.ts +116 -0
  27. package/dist/actors/codex/restricted-launch.js +222 -0
  28. package/dist/actors/codex/restricted-participant-policy.d.ts +46 -0
  29. package/dist/actors/codex/restricted-participant-policy.js +82 -0
  30. package/dist/actors/codex/restricted-participant.d.ts +20 -0
  31. package/dist/actors/codex/restricted-participant.js +432 -0
  32. package/dist/actors/codex/restricted-policy.d.ts +70 -0
  33. package/dist/actors/codex/restricted-policy.js +326 -0
  34. package/dist/actors/codex/restricted-session.d.ts +65 -0
  35. package/dist/actors/codex/restricted-session.js +432 -0
  36. package/dist/actors/codex/restricted-transport.d.ts +73 -0
  37. package/dist/actors/codex/restricted-transport.js +335 -0
  38. package/dist/actors/codex/restricted-turn.d.ts +62 -0
  39. package/dist/actors/codex/restricted-turn.js +284 -0
  40. package/dist/actors/computer-use/actor.d.ts +77 -0
  41. package/dist/actors/computer-use/actor.js +78 -0
  42. package/dist/actors/computer-use/admission-limit.d.ts +12 -0
  43. package/dist/actors/computer-use/admission-limit.js +19 -0
  44. package/dist/actors/computer-use/executor-error.js +48 -0
  45. package/dist/actors/computer-use/loop/actions.d.ts +26 -0
  46. package/dist/actors/computer-use/loop/actions.js +245 -0
  47. package/dist/actors/computer-use/loop/backstop.d.ts +42 -0
  48. package/dist/actors/computer-use/loop/backstop.js +202 -0
  49. package/dist/actors/computer-use/loop/debrief.d.ts +19 -0
  50. package/dist/actors/computer-use/loop/debrief.js +164 -0
  51. package/dist/actors/computer-use/loop/ending.d.ts +86 -0
  52. package/dist/actors/computer-use/loop/ending.js +316 -0
  53. package/dist/actors/computer-use/loop/observation.d.ts +55 -0
  54. package/dist/actors/computer-use/loop/observation.js +246 -0
  55. package/dist/actors/computer-use/loop/output-limit.d.ts +11 -0
  56. package/dist/actors/computer-use/loop/output-limit.js +21 -0
  57. package/dist/actors/computer-use/loop/provider-call.d.ts +19 -0
  58. package/dist/actors/computer-use/loop/provider-call.js +208 -0
  59. package/dist/actors/computer-use/loop/race.d.ts +34 -0
  60. package/dist/actors/computer-use/loop/race.js +79 -0
  61. package/dist/actors/computer-use/loop/session.d.ts +77 -0
  62. package/dist/actors/computer-use/loop/session.js +135 -0
  63. package/dist/actors/computer-use/loop/spend.d.ts +30 -0
  64. package/dist/actors/computer-use/loop/spend.js +85 -0
  65. package/dist/actors/computer-use/loop/trace.d.ts +35 -0
  66. package/dist/actors/computer-use/loop/trace.js +140 -0
  67. package/dist/actors/computer-use/loop/types.d.ts +404 -0
  68. package/dist/actors/computer-use/loop/types.js +1 -0
  69. package/dist/actors/computer-use/loop/usage.d.ts +102 -0
  70. package/dist/actors/computer-use/loop/usage.js +355 -0
  71. package/dist/actors/computer-use/loop.d.ts +11 -0
  72. package/dist/actors/computer-use/loop.js +248 -0
  73. package/dist/actors/computer-use/openai-provider.d.ts +107 -0
  74. package/dist/actors/computer-use/openai-provider.js +472 -0
  75. package/dist/actors/computer-use/openai-requests.d.ts +35 -0
  76. package/dist/actors/computer-use/openai-requests.js +74 -0
  77. package/dist/actors/computer-use/openai-wire.d.ts +67 -0
  78. package/dist/actors/computer-use/openai-wire.js +365 -0
  79. package/dist/actors/computer-use/provider-error.d.ts +27 -0
  80. package/dist/actors/computer-use/provider-error.js +86 -0
  81. package/dist/actors/computer-use/speech.js +6 -0
  82. package/dist/actors/contract.d.ts +315 -0
  83. package/dist/actors/contract.js +201 -0
  84. package/dist/actors/goal-source.js +38 -0
  85. package/dist/actors/local-agent/claude-session.d.ts +43 -0
  86. package/dist/actors/local-agent/claude-session.js +370 -0
  87. package/dist/actors/local-agent/cli.d.ts +115 -0
  88. package/dist/actors/local-agent/cli.js +413 -0
  89. package/dist/actors/local-agent/readiness.d.ts +31 -0
  90. package/dist/actors/local-agent/readiness.js +45 -0
  91. package/dist/actors/openai-endpoint.d.ts +2 -0
  92. package/dist/actors/openai-endpoint.js +2 -0
  93. package/dist/actors/output-token-limit.js +4 -0
  94. package/dist/actors/reasoning-effort.js +33 -0
  95. package/dist/actors/registry.d.ts +59 -0
  96. package/dist/actors/registry.js +89 -0
  97. package/dist/actors/scripted-browser/actor.d.ts +49 -0
  98. package/dist/actors/scripted-browser/actor.js +428 -0
  99. package/dist/actors/scripted-browser/browser-command.d.ts +1 -0
  100. package/dist/actors/scripted-browser/browser-command.js +48 -0
  101. package/dist/actors/scripted-browser/journey.d.ts +9 -0
  102. package/dist/actors/scripted-browser/journey.js +171 -0
  103. package/dist/actors/scripted-browser/steps.d.ts +60 -0
  104. package/dist/actors/scripted-browser/steps.js +384 -0
  105. package/dist/actors/scripted-browser/types.d.ts +135 -0
  106. package/dist/actors/scripted-browser/types.js +26 -0
  107. package/dist/actors/stop-cause.d.ts +9 -0
  108. package/dist/actors/stop-cause.js +42 -0
  109. package/dist/actors/stop-conditions.d.ts +40 -0
  110. package/dist/actors/stop-conditions.js +65 -0
  111. package/dist/analysis/automatic-completion.d.ts +38 -0
  112. package/dist/analysis/automatic-completion.js +90 -0
  113. package/dist/analysis/automatic-config.d.ts +41 -0
  114. package/dist/analysis/automatic-config.js +135 -0
  115. package/dist/analysis/automatic.d.ts +17 -0
  116. package/dist/analysis/automatic.js +279 -0
  117. package/dist/analysis/codex-config.d.ts +8 -0
  118. package/dist/analysis/codex-config.js +69 -0
  119. package/dist/analysis/evidence-sources.d.ts +23 -0
  120. package/dist/analysis/evidence-sources.js +251 -0
  121. package/dist/analysis/evidence.d.ts +18 -0
  122. package/dist/analysis/evidence.js +482 -0
  123. package/dist/analysis/execute.d.ts +52 -0
  124. package/dist/analysis/execute.js +504 -0
  125. package/dist/analysis/image-tokens.d.ts +1 -0
  126. package/dist/analysis/image-tokens.js +41 -0
  127. package/dist/analysis/job.d.ts +97 -0
  128. package/dist/analysis/job.js +311 -0
  129. package/dist/analysis/load.d.ts +3 -0
  130. package/dist/analysis/load.js +11 -0
  131. package/dist/analysis/provider.d.ts +57 -0
  132. package/dist/analysis/provider.js +227 -0
  133. package/dist/analysis/restricted-codex.d.ts +19 -0
  134. package/dist/analysis/restricted-codex.js +23 -0
  135. package/dist/analysis/service.d.ts +72 -0
  136. package/dist/analysis/service.js +399 -0
  137. package/dist/analysis/sharing.d.ts +11 -0
  138. package/dist/analysis/sharing.js +44 -0
  139. package/dist/analysis/store-executions.d.ts +27 -0
  140. package/dist/analysis/store-executions.js +224 -0
  141. package/dist/analysis/store.d.ts +31 -0
  142. package/dist/analysis/store.js +315 -0
  143. package/dist/analysis/types.d.ts +217 -0
  144. package/dist/analysis/types.js +12 -0
  145. package/dist/analysis/validation.d.ts +225 -0
  146. package/dist/analysis/validation.js +562 -0
  147. package/dist/browser-control/client.d.ts +18 -0
  148. package/dist/browser-control/client.js +239 -0
  149. package/dist/browser-control/dispatcher.d.ts +19 -0
  150. package/dist/browser-control/dispatcher.js +221 -0
  151. package/dist/browser-control/protocol.d.ts +492 -0
  152. package/dist/browser-control/protocol.js +360 -0
  153. package/dist/browser-control/recording-transfer.d.ts +3 -0
  154. package/dist/browser-control/recording-transfer.js +48 -0
  155. package/dist/browser-control/transport.d.ts +27 -0
  156. package/dist/browser-control/transport.js +189 -0
  157. package/dist/cli/commands/analysis-signals.d.ts +7 -0
  158. package/dist/cli/commands/analysis-signals.js +25 -0
  159. package/dist/cli/commands/analyze.d.ts +3 -0
  160. package/dist/cli/commands/analyze.js +212 -0
  161. package/dist/cli/commands/codex.d.ts +3 -0
  162. package/dist/cli/commands/codex.js +145 -0
  163. package/dist/cli/commands/comms.d.ts +3 -0
  164. package/dist/cli/commands/comms.js +225 -0
  165. package/dist/cli/commands/feedback.d.ts +3 -0
  166. package/dist/cli/commands/feedback.js +138 -0
  167. package/dist/cli/commands/lab-format.d.ts +8 -0
  168. package/dist/cli/commands/lab-format.js +105 -0
  169. package/dist/cli/commands/lab-route-computer-use.d.ts +20 -0
  170. package/dist/cli/commands/lab-route-computer-use.js +251 -0
  171. package/dist/cli/commands/lab-route-open.d.ts +27 -0
  172. package/dist/cli/commands/lab-route-open.js +37 -0
  173. package/dist/cli/commands/lab-route-preview.d.ts +20 -0
  174. package/dist/cli/commands/lab-route-preview.js +74 -0
  175. package/dist/cli/commands/lab-route-run.d.ts +17 -0
  176. package/dist/cli/commands/lab-route-run.js +31 -0
  177. package/dist/cli/commands/lab-route-scripted.d.ts +19 -0
  178. package/dist/cli/commands/lab-route-scripted.js +50 -0
  179. package/dist/cli/commands/lab-route-shared-world.d.ts +20 -0
  180. package/dist/cli/commands/lab-route-shared-world.js +135 -0
  181. package/dist/cli/commands/lab-route-terminal.d.ts +19 -0
  182. package/dist/cli/commands/lab-route-terminal.js +49 -0
  183. package/dist/cli/commands/lab-run.d.ts +9 -0
  184. package/dist/cli/commands/lab-run.js +166 -0
  185. package/dist/cli/commands/lab-scorer.d.ts +30 -0
  186. package/dist/cli/commands/lab-scorer.js +17 -0
  187. package/dist/cli/commands/lab.d.ts +3 -0
  188. package/dist/cli/commands/lab.js +193 -0
  189. package/dist/cli/commands/observe.d.ts +4 -0
  190. package/dist/cli/commands/observe.js +345 -0
  191. package/dist/cli/commands/runs.d.ts +11 -0
  192. package/dist/cli/commands/runs.js +314 -0
  193. package/dist/cli/commands/setup.d.ts +11 -0
  194. package/dist/cli/commands/setup.js +325 -0
  195. package/dist/cli/commands/tui.d.ts +32 -0
  196. package/dist/cli/commands/tui.js +305 -0
  197. package/dist/cli/commands/watch.d.ts +3 -0
  198. package/dist/cli/commands/watch.js +245 -0
  199. package/dist/cli/doctor.d.ts +39 -0
  200. package/dist/cli/doctor.js +263 -0
  201. package/dist/cli/first-run-path.d.ts +67 -0
  202. package/dist/cli/first-run-path.js +150 -0
  203. package/dist/cli/io.d.ts +85 -0
  204. package/dist/cli/io.js +232 -0
  205. package/dist/cli/observer-follow.d.ts +56 -0
  206. package/dist/cli/observer-follow.js +160 -0
  207. package/dist/cli/orientation.d.ts +30 -0
  208. package/dist/cli/orientation.js +114 -0
  209. package/dist/cli/program.d.ts +15 -0
  210. package/dist/cli/program.js +338 -0
  211. package/dist/cli/secret-prompt.js +39 -0
  212. package/dist/cli/telemetry.js +351 -0
  213. package/dist/cli.js +2 -4
  214. package/dist/comms/agentmail.d.ts +29 -0
  215. package/dist/comms/agentmail.js +568 -0
  216. package/dist/comms/capture-surface.d.ts +54 -0
  217. package/dist/comms/capture-surface.js +468 -0
  218. package/dist/comms/catch-host.d.ts +52 -0
  219. package/dist/comms/catch-host.js +192 -0
  220. package/dist/comms/connections.d.ts +20 -0
  221. package/dist/comms/connections.js +116 -0
  222. package/dist/comms/email-catch.d.ts +49 -0
  223. package/dist/comms/email-catch.js +236 -0
  224. package/dist/comms/extract.d.ts +7 -0
  225. package/dist/comms/extract.js +65 -0
  226. package/dist/comms/fake-inbox.d.ts +39 -0
  227. package/dist/comms/fake-inbox.js +136 -0
  228. package/dist/comms/images.d.ts +7 -0
  229. package/dist/comms/images.js +53 -0
  230. package/dist/comms/lease-store.d.ts +91 -0
  231. package/dist/comms/lease-store.js +600 -0
  232. package/dist/comms/providers.d.ts +30 -0
  233. package/dist/comms/providers.js +24 -0
  234. package/dist/comms/receiving-common.d.ts +17 -0
  235. package/dist/comms/receiving-common.js +82 -0
  236. package/dist/comms/receiving-evidence.d.ts +4 -0
  237. package/dist/comms/receiving-evidence.js +59 -0
  238. package/dist/comms/receiving-recovery.d.ts +22 -0
  239. package/dist/comms/receiving-recovery.js +100 -0
  240. package/dist/comms/receiving-render.d.ts +16 -0
  241. package/dist/comms/receiving-render.js +409 -0
  242. package/dist/comms/receiving-runtime.d.ts +41 -0
  243. package/dist/comms/receiving-runtime.js +66 -0
  244. package/dist/comms/receiving-surface.d.ts +8 -0
  245. package/dist/comms/receiving-surface.js +156 -0
  246. package/dist/comms/receiving-types.d.ts +122 -0
  247. package/dist/comms/receiving-types.js +3 -0
  248. package/dist/comms/receiving.d.ts +33 -0
  249. package/dist/comms/receiving.js +508 -0
  250. package/dist/comms/sandbox-catch-script.d.ts +16 -0
  251. package/dist/comms/sandbox-catch-script.js +331 -0
  252. package/dist/comms/sandbox-catch.d.ts +214 -0
  253. package/dist/comms/sandbox-catch.js +451 -0
  254. package/dist/comms/setup.d.ts +65 -0
  255. package/dist/comms/setup.js +259 -0
  256. package/dist/comms/thread-evidence.d.ts +28 -0
  257. package/dist/comms/thread-evidence.js +30 -0
  258. package/dist/comms/types.d.ts +76 -0
  259. package/dist/comms/types.js +8 -0
  260. package/dist/deprecated.d.ts +90 -0
  261. package/dist/deprecated.js +106 -0
  262. package/dist/evidence/browser-hygiene.js +42 -0
  263. package/dist/evidence/desktop-recorder.d.ts +39 -0
  264. package/dist/evidence/desktop-recorder.js +340 -0
  265. package/dist/evidence/desktop-recording-artifact.d.ts +5 -0
  266. package/dist/evidence/desktop-recording-artifact.js +53 -0
  267. package/dist/evidence/desktop-recording-types.d.ts +27 -0
  268. package/dist/evidence/desktop-recording-types.js +16 -0
  269. package/dist/evidence/encoded-text.d.ts +27 -0
  270. package/dist/evidence/encoded-text.js +243 -0
  271. package/dist/evidence/frame-signature.d.ts +17 -0
  272. package/dist/evidence/frame-signature.js +111 -0
  273. package/dist/evidence/image.d.ts +24 -0
  274. package/dist/evidence/image.js +170 -0
  275. package/dist/evidence/plain-text.d.ts +8 -0
  276. package/dist/evidence/plain-text.js +16 -0
  277. package/dist/evidence/redaction.d.ts +110 -0
  278. package/dist/evidence/redaction.js +329 -0
  279. package/dist/feedback/draft.d.ts +58 -0
  280. package/dist/feedback/draft.js +309 -0
  281. package/dist/feedback/export-bundle.d.ts +6 -0
  282. package/dist/feedback/export-bundle.js +585 -0
  283. package/dist/feedback/export.d.ts +50 -0
  284. package/dist/feedback/export.js +392 -0
  285. package/dist/feedback/feedback.d.ts +37 -0
  286. package/dist/feedback/feedback.js +282 -0
  287. package/dist/feedback/proof.d.ts +8 -0
  288. package/dist/feedback/proof.js +56 -0
  289. package/dist/guest/bootstrap.d.ts +55 -0
  290. package/dist/guest/bootstrap.js +348 -0
  291. package/dist/guest/browser-tools.d.ts +8 -0
  292. package/dist/guest/browser-tools.js +72 -0
  293. package/dist/guest/chromium-text.d.ts +62 -0
  294. package/dist/guest/chromium-text.js +386 -0
  295. package/dist/guest/desktop-executor.d.ts +57 -0
  296. package/dist/guest/desktop-executor.js +256 -0
  297. package/dist/guest/desktop-keys.d.ts +8 -0
  298. package/dist/guest/desktop-keys.js +89 -0
  299. package/dist/guest/desktop-media.d.ts +70 -0
  300. package/dist/guest/desktop-media.js +385 -0
  301. package/dist/guest/desktop-native.d.ts +14 -0
  302. package/dist/guest/desktop-native.js +156 -0
  303. package/dist/guest/media-config.d.ts +15 -0
  304. package/dist/guest/media-config.js +16 -0
  305. package/dist/guest/runtime-desktop.d.ts +45 -0
  306. package/dist/guest/runtime-desktop.js +420 -0
  307. package/dist/guest/runtime-processes.d.ts +28 -0
  308. package/dist/guest/runtime-processes.js +94 -0
  309. package/dist/guest/runtime.d.ts +31 -0
  310. package/dist/guest/runtime.js +124 -0
  311. package/dist/guest-media-worker.js +184 -48
  312. package/dist/guest-runtime-main.js +23 -10
  313. package/dist/guest-runtime-revision.js +1 -1
  314. package/dist/index.d.ts +32 -83
  315. package/dist/index.js +21 -42
  316. package/dist/keys/env-file.d.ts +15 -0
  317. package/dist/keys/env-file.js +109 -0
  318. package/dist/keys/key-resolution.d.ts +58 -0
  319. package/dist/keys/key-resolution.js +389 -0
  320. package/dist/lab/adapter-extension.d.ts +75 -0
  321. package/dist/lab/adapter-extension.js +253 -0
  322. package/dist/lab/adapter-scorer-loader.d.ts +43 -0
  323. package/dist/lab/adapter-scorer-loader.js +130 -0
  324. package/dist/lab/bag-overrides.d.ts +18 -0
  325. package/dist/lab/bag-overrides.js +121 -0
  326. package/dist/lab/composition-rules.d.ts +5 -0
  327. package/dist/lab/composition-rules.js +283 -0
  328. package/dist/lab/config.d.ts +7 -0
  329. package/dist/lab/config.js +208 -0
  330. package/dist/lab/device-presets.d.ts +97 -0
  331. package/dist/lab/device-presets.js +87 -0
  332. package/dist/lab/discover.d.ts +65 -0
  333. package/dist/lab/discover.js +422 -0
  334. package/dist/lab/doctor.d.ts +39 -0
  335. package/dist/lab/doctor.js +233 -0
  336. package/dist/lab/init-paths.d.ts +5 -0
  337. package/dist/lab/init-paths.js +89 -0
  338. package/dist/lab/init-plan.d.ts +20 -0
  339. package/dist/lab/init-plan.js +163 -0
  340. package/dist/lab/init-templates.d.ts +28 -0
  341. package/dist/lab/init-templates.js +416 -0
  342. package/dist/lab/init.d.ts +39 -0
  343. package/dist/lab/init.js +287 -0
  344. package/dist/lab/keys.d.ts +2 -0
  345. package/dist/lab/keys.js +264 -0
  346. package/dist/lab/parse/actors.d.ts +14 -0
  347. package/dist/lab/parse/actors.js +453 -0
  348. package/dist/lab/parse/comms.d.ts +12 -0
  349. package/dist/lab/parse/comms.js +246 -0
  350. package/dist/lab/parse/execution.d.ts +19 -0
  351. package/dist/lab/parse/execution.js +356 -0
  352. package/dist/lab/parse/subject-state.d.ts +30 -0
  353. package/dist/lab/parse/subject-state.js +179 -0
  354. package/dist/lab/parse/subject.d.ts +9 -0
  355. package/dist/lab/parse/subject.js +420 -0
  356. package/dist/lab/parse/values.d.ts +17 -0
  357. package/dist/lab/parse/values.js +65 -0
  358. package/dist/lab/participant-assignment.d.ts +12 -0
  359. package/dist/lab/participant-assignment.js +19 -0
  360. package/dist/lab/persona-resolve.d.ts +39 -0
  361. package/dist/lab/persona-resolve.js +118 -0
  362. package/dist/lab/persona.d.ts +39 -0
  363. package/dist/lab/persona.js +192 -0
  364. package/dist/lab/plan-base.d.ts +24 -0
  365. package/dist/lab/plan-base.js +113 -0
  366. package/dist/lab/plan-participants.d.ts +81 -0
  367. package/dist/lab/plan-participants.js +92 -0
  368. package/dist/lab/plan-types.d.ts +269 -0
  369. package/dist/lab/plan-types.js +5 -0
  370. package/dist/lab/plan.d.ts +27 -0
  371. package/dist/lab/plan.js +156 -0
  372. package/dist/lab/preflight-probes.d.ts +3 -0
  373. package/dist/lab/preflight-probes.js +312 -0
  374. package/dist/lab/preflight-result.d.ts +7 -0
  375. package/dist/lab/preflight-result.js +43 -0
  376. package/dist/lab/preflight.d.ts +95 -0
  377. package/dist/lab/preflight.js +117 -0
  378. package/dist/lab/route-inputs.d.ts +17 -0
  379. package/dist/lab/route-inputs.js +95 -0
  380. package/dist/lab/routing.d.ts +81 -0
  381. package/dist/lab/routing.js +214 -0
  382. package/dist/lab/run-lab-events.d.ts +69 -0
  383. package/dist/lab/run-lab-events.js +95 -0
  384. package/dist/lab/run-lab-options.d.ts +82 -0
  385. package/dist/lab/run-lab-options.js +399 -0
  386. package/dist/lab/summary.d.ts +60 -0
  387. package/dist/lab/summary.js +168 -0
  388. package/dist/lab/tasks.d.ts +91 -0
  389. package/dist/lab/tasks.js +139 -0
  390. package/dist/lab/types.d.ts +813 -0
  391. package/dist/lab/types.js +6 -0
  392. package/dist/lab/validation.d.ts +67 -0
  393. package/dist/lab/validation.js +387 -0
  394. package/dist/lab/warnings.d.ts +2 -0
  395. package/dist/lab/warnings.js +338 -0
  396. package/dist/observer/artifact.d.ts +23 -0
  397. package/dist/observer/artifact.js +235 -0
  398. package/dist/observer/data.d.ts +115 -0
  399. package/dist/observer/data.js +258 -0
  400. package/dist/observer/exposure.d.ts +64 -0
  401. package/dist/observer/exposure.js +143 -0
  402. package/dist/observer/http.js +50 -0
  403. package/dist/observer/library.js +190 -0
  404. package/dist/observer/listen.js +85 -0
  405. package/dist/observer/live.d.ts +9 -0
  406. package/dist/observer/live.js +25 -0
  407. package/dist/observer/pinned-files.d.ts +30 -0
  408. package/dist/observer/pinned-files.js +160 -0
  409. package/dist/observer/render.d.ts +69 -0
  410. package/dist/observer/render.js +350 -0
  411. package/dist/observer/run-inventory.d.ts +35 -0
  412. package/dist/observer/run-inventory.js +95 -0
  413. package/dist/observer/run-routes.d.ts +37 -0
  414. package/dist/observer/run-routes.js +373 -0
  415. package/dist/observer/serve.d.ts +97 -0
  416. package/dist/observer/serve.js +305 -0
  417. package/dist/observer/static.js +369 -0
  418. package/dist/observer/tunnel.js +112 -0
  419. package/dist/observer-app.html +9 -20
  420. package/dist/routes/computer-use/bundle-parts.d.ts +50 -0
  421. package/dist/routes/computer-use/bundle-parts.js +177 -0
  422. package/dist/routes/computer-use/bundle.d.ts +56 -0
  423. package/dist/routes/computer-use/bundle.js +184 -0
  424. package/dist/routes/computer-use/diagnostics.d.ts +38 -0
  425. package/dist/routes/computer-use/diagnostics.js +94 -0
  426. package/dist/routes/computer-use/e2b-desktop/comms.d.ts +65 -0
  427. package/dist/routes/computer-use/e2b-desktop/comms.js +225 -0
  428. package/dist/routes/computer-use/e2b-desktop/desktop.d.ts +3 -0
  429. package/dist/routes/computer-use/e2b-desktop/desktop.js +91 -0
  430. package/dist/routes/computer-use/e2b-desktop/fidelity.d.ts +65 -0
  431. package/dist/routes/computer-use/e2b-desktop/fidelity.js +156 -0
  432. package/dist/routes/computer-use/e2b-desktop/prepare.d.ts +18 -0
  433. package/dist/routes/computer-use/e2b-desktop/prepare.js +198 -0
  434. package/dist/routes/computer-use/e2b-desktop/start.d.ts +14 -0
  435. package/dist/routes/computer-use/e2b-desktop/start.js +193 -0
  436. package/dist/routes/computer-use/e2b-desktop/state.d.ts +65 -0
  437. package/dist/routes/computer-use/e2b-desktop/state.js +69 -0
  438. package/dist/routes/computer-use/e2b-desktop/teardown.d.ts +6 -0
  439. package/dist/routes/computer-use/e2b-desktop/teardown.js +152 -0
  440. package/dist/routes/computer-use/external-comms.d.ts +20 -0
  441. package/dist/routes/computer-use/external-comms.js +55 -0
  442. package/dist/routes/computer-use/fanout-bundle.d.ts +11 -0
  443. package/dist/routes/computer-use/fanout-bundle.js +274 -0
  444. package/dist/routes/computer-use/fanout-lanes.d.ts +15 -0
  445. package/dist/routes/computer-use/fanout-lanes.js +302 -0
  446. package/dist/routes/computer-use/in-process-desktop.d.ts +17 -0
  447. package/dist/routes/computer-use/in-process-desktop.js +40 -0
  448. package/dist/routes/computer-use/lanes.d.ts +35 -0
  449. package/dist/routes/computer-use/lanes.js +321 -0
  450. package/dist/routes/computer-use/legacy-lane-spec.d.ts +62 -0
  451. package/dist/routes/computer-use/legacy-lane-spec.js +39 -0
  452. package/dist/routes/computer-use/live-flush.d.ts +42 -0
  453. package/dist/routes/computer-use/live-flush.js +154 -0
  454. package/dist/routes/computer-use/local-tree-pack.d.ts +27 -0
  455. package/dist/routes/computer-use/local-tree-pack.js +47 -0
  456. package/dist/routes/computer-use/local-vm.d.ts +20 -0
  457. package/dist/routes/computer-use/local-vm.js +218 -0
  458. package/dist/routes/computer-use/participant-desktop.d.ts +63 -0
  459. package/dist/routes/computer-use/participant-desktop.js +33 -0
  460. package/dist/routes/computer-use/participant-facts.d.ts +6 -0
  461. package/dist/routes/computer-use/participant-facts.js +22 -0
  462. package/dist/routes/computer-use/participant-model.d.ts +30 -0
  463. package/dist/routes/computer-use/participant-model.js +222 -0
  464. package/dist/routes/computer-use/participant-prompt.d.ts +53 -0
  465. package/dist/routes/computer-use/participant-prompt.js +87 -0
  466. package/dist/routes/computer-use/participant-runs.d.ts +67 -0
  467. package/dist/routes/computer-use/participant-runs.js +255 -0
  468. package/dist/routes/computer-use/plan.d.ts +56 -0
  469. package/dist/routes/computer-use/plan.js +308 -0
  470. package/dist/routes/computer-use/preflight.d.ts +26 -0
  471. package/dist/routes/computer-use/preflight.js +85 -0
  472. package/dist/routes/computer-use/rerun-selection.d.ts +19 -0
  473. package/dist/routes/computer-use/rerun-selection.js +121 -0
  474. package/dist/routes/computer-use/result.d.ts +7 -0
  475. package/dist/routes/computer-use/result.js +292 -0
  476. package/dist/routes/computer-use/route.d.ts +33 -0
  477. package/dist/routes/computer-use/route.js +145 -0
  478. package/dist/routes/computer-use/run-lanes.d.ts +59 -0
  479. package/dist/routes/computer-use/run-lanes.js +135 -0
  480. package/dist/routes/computer-use/self-report.d.ts +21 -0
  481. package/dist/routes/computer-use/self-report.js +231 -0
  482. package/dist/routes/computer-use/setup.d.ts +136 -0
  483. package/dist/routes/computer-use/setup.js +371 -0
  484. package/dist/routes/computer-use/single-bundle.d.ts +97 -0
  485. package/dist/routes/computer-use/single-bundle.js +393 -0
  486. package/dist/routes/computer-use/subject-projection.d.ts +51 -0
  487. package/dist/routes/computer-use/subject-projection.js +159 -0
  488. package/dist/routes/computer-use/types.d.ts +539 -0
  489. package/dist/routes/computer-use/types.js +37 -0
  490. package/dist/routes/preview.d.ts +13 -0
  491. package/dist/routes/preview.js +36 -0
  492. package/dist/routes/scripted/bundle.d.ts +47 -0
  493. package/dist/routes/scripted/bundle.js +195 -0
  494. package/dist/routes/scripted/plan.d.ts +30 -0
  495. package/dist/routes/scripted/plan.js +95 -0
  496. package/dist/routes/scripted/result.d.ts +48 -0
  497. package/dist/routes/scripted/result.js +176 -0
  498. package/dist/routes/scripted/route.d.ts +28 -0
  499. package/dist/routes/scripted/route.js +218 -0
  500. package/dist/routes/scripted/scenario.d.ts +21 -0
  501. package/dist/routes/scripted/scenario.js +102 -0
  502. package/dist/routes/scripted/session-result.d.ts +8 -0
  503. package/dist/routes/scripted/session-result.js +60 -0
  504. package/dist/routes/scripted/setup.d.ts +45 -0
  505. package/dist/routes/scripted/setup.js +126 -0
  506. package/dist/routes/scripted/subject.d.ts +49 -0
  507. package/dist/routes/scripted/subject.js +156 -0
  508. package/dist/routes/scripted/surface-records.d.ts +26 -0
  509. package/dist/routes/scripted/surface-records.js +88 -0
  510. package/dist/routes/scripted/surface-sessions.d.ts +13 -0
  511. package/dist/routes/scripted/surface-sessions.js +40 -0
  512. package/dist/routes/scripted/types.d.ts +88 -0
  513. package/dist/routes/scripted/types.js +3 -0
  514. package/dist/routes/shared-world/bundle.d.ts +20 -0
  515. package/dist/routes/shared-world/bundle.js +446 -0
  516. package/dist/routes/shared-world/checkpoints.d.ts +25 -0
  517. package/dist/routes/shared-world/checkpoints.js +46 -0
  518. package/dist/routes/shared-world/comms.d.ts +68 -0
  519. package/dist/routes/shared-world/comms.js +176 -0
  520. package/dist/routes/shared-world/external-public.d.ts +21 -0
  521. package/dist/routes/shared-world/external-public.js +130 -0
  522. package/dist/routes/shared-world/handoff.d.ts +62 -0
  523. package/dist/routes/shared-world/handoff.js +348 -0
  524. package/dist/routes/shared-world/lobby-code.d.ts +25 -0
  525. package/dist/routes/shared-world/lobby-code.js +152 -0
  526. package/dist/routes/shared-world/plan.d.ts +27 -0
  527. package/dist/routes/shared-world/plan.js +174 -0
  528. package/dist/routes/shared-world/provenance.d.ts +27 -0
  529. package/dist/routes/shared-world/provenance.js +65 -0
  530. package/dist/routes/shared-world/provisioned.d.ts +57 -0
  531. package/dist/routes/shared-world/provisioned.js +505 -0
  532. package/dist/routes/shared-world/result.d.ts +18 -0
  533. package/dist/routes/shared-world/result.js +327 -0
  534. package/dist/routes/shared-world/route.d.ts +21 -0
  535. package/dist/routes/shared-world/route.js +277 -0
  536. package/dist/routes/shared-world/seat-records.d.ts +20 -0
  537. package/dist/routes/shared-world/seat-records.js +213 -0
  538. package/dist/routes/shared-world/seats.d.ts +38 -0
  539. package/dist/routes/shared-world/seats.js +208 -0
  540. package/dist/routes/shared-world/setup.d.ts +48 -0
  541. package/dist/routes/shared-world/setup.js +200 -0
  542. package/dist/routes/shared-world/types.d.ts +354 -0
  543. package/dist/routes/shared-world/types.js +29 -0
  544. package/dist/routes/terminal/adapter.d.ts +37 -0
  545. package/dist/routes/terminal/adapter.js +201 -0
  546. package/dist/routes/terminal/bundle.d.ts +79 -0
  547. package/dist/routes/terminal/bundle.js +305 -0
  548. package/dist/routes/terminal/credentials.d.ts +34 -0
  549. package/dist/routes/terminal/credentials.js +102 -0
  550. package/dist/routes/terminal/dry-run.d.ts +24 -0
  551. package/dist/routes/terminal/dry-run.js +157 -0
  552. package/dist/routes/terminal/encoding.js +79 -0
  553. package/dist/routes/terminal/ledger.d.ts +49 -0
  554. package/dist/routes/terminal/ledger.js +170 -0
  555. package/dist/routes/terminal/lifetime.d.ts +10 -0
  556. package/dist/routes/terminal/lifetime.js +22 -0
  557. package/dist/routes/terminal/live-finish.d.ts +31 -0
  558. package/dist/routes/terminal/live-finish.js +215 -0
  559. package/dist/routes/terminal/live-sandbox.d.ts +69 -0
  560. package/dist/routes/terminal/live-sandbox.js +452 -0
  561. package/dist/routes/terminal/persona.d.ts +20 -0
  562. package/dist/routes/terminal/persona.js +34 -0
  563. package/dist/routes/terminal/plan.d.ts +21 -0
  564. package/dist/routes/terminal/plan.js +115 -0
  565. package/dist/routes/terminal/recorder.d.ts +23 -0
  566. package/dist/routes/terminal/recorder.js +77 -0
  567. package/dist/routes/terminal/result.d.ts +47 -0
  568. package/dist/routes/terminal/result.js +114 -0
  569. package/dist/routes/terminal/route.d.ts +23 -0
  570. package/dist/routes/terminal/route.js +170 -0
  571. package/dist/routes/terminal/runtime-auth.d.ts +12 -0
  572. package/dist/routes/terminal/runtime-auth.js +23 -0
  573. package/dist/routes/terminal/runtime.d.ts +14 -0
  574. package/dist/routes/terminal/runtime.js +47 -0
  575. package/dist/routes/terminal/sandbox.d.ts +35 -0
  576. package/dist/routes/terminal/sandbox.js +126 -0
  577. package/dist/routes/terminal/session.d.ts +25 -0
  578. package/dist/routes/terminal/session.js +199 -0
  579. package/dist/routes/terminal/token-usage.d.ts +15 -0
  580. package/dist/routes/terminal/token-usage.js +93 -0
  581. package/dist/routes/terminal/trace.d.ts +40 -0
  582. package/dist/routes/terminal/trace.js +172 -0
  583. package/dist/routes/terminal/types.d.ts +342 -0
  584. package/dist/routes/terminal/types.js +31 -0
  585. package/dist/run/bundle-shape.d.ts +7 -0
  586. package/dist/run/bundle-shape.js +369 -0
  587. package/dist/run/bundle.d.ts +547 -0
  588. package/dist/run/bundle.js +44 -0
  589. package/dist/run/concurrency.js +24 -0
  590. package/dist/run/contained-output.d.ts +50 -0
  591. package/dist/run/contained-output.js +351 -0
  592. package/dist/run/cost-summary.d.ts +28 -0
  593. package/dist/run/cost-summary.js +213 -0
  594. package/dist/run/costs.js +140 -0
  595. package/dist/run/detail.d.ts +62 -0
  596. package/dist/run/detail.js +139 -0
  597. package/dist/run/dry-run-inputs.d.ts +9 -0
  598. package/dist/run/dry-run-inputs.js +90 -0
  599. package/dist/run/dry-run.d.ts +6 -0
  600. package/dist/run/dry-run.js +362 -0
  601. package/dist/run/feedback-shape.d.ts +7 -0
  602. package/dist/run/feedback-shape.js +89 -0
  603. package/dist/run/git-state.d.ts +35 -0
  604. package/dist/run/git-state.js +316 -0
  605. package/dist/run/git-workspace.d.ts +32 -0
  606. package/dist/run/git-workspace.js +450 -0
  607. package/dist/run/judge.d.ts +210 -0
  608. package/dist/run/judge.js +240 -0
  609. package/dist/run/locate.d.ts +22 -0
  610. package/dist/run/locate.js +122 -0
  611. package/dist/run/outcomes.d.ts +31 -0
  612. package/dist/run/outcomes.js +210 -0
  613. package/dist/run/participant-records.d.ts +28 -0
  614. package/dist/run/participant-records.js +63 -0
  615. package/dist/run/participant.d.ts +29 -0
  616. package/dist/run/participant.js +12 -0
  617. package/dist/run/paths.d.ts +79 -0
  618. package/dist/run/paths.js +356 -0
  619. package/dist/run/preflight-receipts.d.ts +46 -0
  620. package/dist/run/preflight-receipts.js +173 -0
  621. package/dist/run/pricing.d.ts +124 -0
  622. package/dist/run/pricing.js +298 -0
  623. package/dist/run/project.d.ts +8 -0
  624. package/dist/run/project.js +103 -0
  625. package/dist/run/projection.d.ts +184 -0
  626. package/dist/run/projection.js +356 -0
  627. package/dist/run/reclaim.d.ts +41 -0
  628. package/dist/run/reclaim.js +183 -0
  629. package/dist/run/results.d.ts +88 -0
  630. package/dist/run/results.js +3 -0
  631. package/dist/run/run-index.d.ts +107 -0
  632. package/dist/run/run-index.js +243 -0
  633. package/dist/run/run.d.ts +103 -0
  634. package/dist/run/run.js +199 -0
  635. package/dist/run/sandbox-receipts.d.ts +31 -0
  636. package/dist/run/sandbox-receipts.js +49 -0
  637. package/dist/run/shared-world-evidence.d.ts +220 -0
  638. package/dist/run/shared-world-evidence.js +49 -0
  639. package/dist/run/shared-world-shape.d.ts +26 -0
  640. package/dist/run/shared-world-shape.js +181 -0
  641. package/dist/run/stats.d.ts +82 -0
  642. package/dist/run/stats.js +258 -0
  643. package/dist/run/status.d.ts +111 -0
  644. package/dist/run/status.js +176 -0
  645. package/dist/run/stored-runs.d.ts +38 -0
  646. package/dist/run/stored-runs.js +273 -0
  647. package/dist/run/stream-shape.d.ts +4 -0
  648. package/dist/run/stream-shape.js +160 -0
  649. package/dist/run/streams.d.ts +257 -0
  650. package/dist/run/streams.js +12 -0
  651. package/dist/run/study-files.d.ts +35 -0
  652. package/dist/run/study-files.js +164 -0
  653. package/dist/run/terminal-contract.d.ts +25 -0
  654. package/dist/run/terminal-contract.js +47 -0
  655. package/dist/run/text.d.ts +2 -0
  656. package/dist/run/text.js +4 -0
  657. package/dist/run/transient-comms-secrets.js +72 -0
  658. package/dist/run/type-guards.d.ts +6 -0
  659. package/dist/run/type-guards.js +18 -0
  660. package/dist/run-lab.d.ts +110 -0
  661. package/dist/run-lab.js +148 -0
  662. package/dist/subject/clone.d.ts +37 -0
  663. package/dist/subject/clone.js +62 -0
  664. package/dist/subject/desktop-cli.d.ts +17 -0
  665. package/dist/subject/desktop-cli.js +51 -0
  666. package/dist/subject/local-tree-archive.d.ts +82 -0
  667. package/dist/subject/local-tree-archive.js +431 -0
  668. package/dist/subject/local-tree.d.ts +28 -0
  669. package/dist/subject/local-tree.js +58 -0
  670. package/dist/subject/node-bootstrap.d.ts +12 -0
  671. package/dist/subject/node-bootstrap.js +66 -0
  672. package/dist/subject/runtime.d.ts +13 -0
  673. package/dist/subject/runtime.js +50 -0
  674. package/dist/subject/serve.d.ts +39 -0
  675. package/dist/subject/serve.js +249 -0
  676. package/dist/subject/state.d.ts +23 -0
  677. package/dist/subject/state.js +58 -0
  678. package/dist/subject/steps.d.ts +37 -0
  679. package/dist/subject/steps.js +39 -0
  680. package/dist/substrates/command-failure.d.ts +23 -0
  681. package/dist/substrates/command-failure.js +45 -0
  682. package/dist/substrates/desktop-session.d.ts +41 -0
  683. package/dist/substrates/desktop-session.js +59 -0
  684. package/dist/substrates/detached.d.ts +55 -0
  685. package/dist/substrates/detached.js +139 -0
  686. package/dist/substrates/e2b/cdp-probe.d.ts +99 -0
  687. package/dist/substrates/e2b/cdp-probe.js +556 -0
  688. package/dist/substrates/e2b/desktop-browser.d.ts +81 -0
  689. package/dist/substrates/e2b/desktop-browser.js +410 -0
  690. package/dist/substrates/e2b/desktop-cdp.d.ts +77 -0
  691. package/dist/substrates/e2b/desktop-cdp.js +211 -0
  692. package/dist/substrates/e2b/desktop-executor.d.ts +92 -0
  693. package/dist/substrates/e2b/desktop-executor.js +302 -0
  694. package/dist/substrates/e2b/desktop-geometry.d.ts +83 -0
  695. package/dist/substrates/e2b/desktop-geometry.js +331 -0
  696. package/dist/substrates/e2b/desktop-media.d.ts +29 -0
  697. package/dist/substrates/e2b/desktop-media.js +151 -0
  698. package/dist/substrates/e2b/desktop-recording.d.ts +18 -0
  699. package/dist/substrates/e2b/desktop-recording.js +238 -0
  700. package/dist/substrates/e2b/desktop-resources.d.ts +11 -0
  701. package/dist/substrates/e2b/desktop-resources.js +35 -0
  702. package/dist/substrates/e2b/desktop-screenshot-cleanup.d.ts +15 -0
  703. package/dist/substrates/e2b/desktop-screenshot-cleanup.js +66 -0
  704. package/dist/substrates/e2b/lifetime.d.ts +12 -0
  705. package/dist/substrates/e2b/lifetime.js +18 -0
  706. package/dist/substrates/e2b/sandbox.d.ts +102 -0
  707. package/dist/substrates/e2b/sandbox.js +202 -0
  708. package/dist/substrates/e2b/sdk.d.ts +194 -0
  709. package/dist/substrates/e2b/sdk.js +168 -0
  710. package/dist/substrates/e2b/shell.d.ts +10 -0
  711. package/dist/substrates/e2b/shell.js +61 -0
  712. package/dist/substrates/local/captured-inbox.d.ts +6 -0
  713. package/dist/substrates/local/captured-inbox.js +87 -0
  714. package/dist/substrates/local/firecracker-desktop.d.ts +25 -0
  715. package/dist/substrates/local/firecracker-desktop.js +315 -0
  716. package/dist/substrates/local/runtime-config.d.ts +6 -0
  717. package/dist/substrates/local/runtime-config.js +91 -0
  718. package/dist/substrates/local/runtime-host.d.ts +30 -0
  719. package/dist/substrates/local/runtime-host.js +143 -0
  720. package/dist/substrates/local/runtime-release.d.ts +5 -0
  721. package/dist/substrates/local/runtime-release.js +32 -0
  722. package/dist/substrates/local/runtime-ssh.d.ts +9 -0
  723. package/dist/substrates/local/runtime-ssh.js +129 -0
  724. package/dist/substrates/local/runtime.d.ts +25 -0
  725. package/dist/substrates/local/runtime.js +190 -0
  726. package/dist/substrates/shell.d.ts +44 -0
  727. package/dist/substrates/shell.js +22 -0
  728. package/dist/tui/actions.d.ts +39 -0
  729. package/dist/tui/actions.js +203 -0
  730. package/dist/tui/contract.d.ts +144 -0
  731. package/dist/tui/contract.js +52 -0
  732. package/dist/tui/launch.js +172 -0
  733. package/dist/tui/project.d.ts +10 -0
  734. package/dist/tui/project.js +17 -0
  735. package/dist/tui-app.js +125 -125
  736. package/dist/verify/actor.d.ts +27 -0
  737. package/dist/verify/actor.js +292 -0
  738. package/dist/verify/artifacts.d.ts +47 -0
  739. package/dist/verify/artifacts.js +373 -0
  740. package/dist/verify/costs.d.ts +30 -0
  741. package/dist/verify/costs.js +129 -0
  742. package/dist/verify/liveness.d.ts +7 -0
  743. package/dist/verify/liveness.js +72 -0
  744. package/dist/verify/rerun.d.ts +3 -0
  745. package/dist/verify/rerun.js +46 -0
  746. package/dist/verify/shared-world-concurrent.d.ts +11 -0
  747. package/dist/verify/shared-world-concurrent.js +346 -0
  748. package/dist/verify/shared-world.d.ts +8 -0
  749. package/dist/verify/shared-world.js +295 -0
  750. package/dist/verify/subject.d.ts +17 -0
  751. package/dist/verify/subject.js +123 -0
  752. package/dist/verify/verify.d.ts +34 -0
  753. package/dist/verify/verify.js +333 -0
  754. package/docs/README.md +67 -0
  755. package/docs/architecture/actor-contract.md +215 -174
  756. package/docs/architecture/browser-control.md +51 -37
  757. package/docs/architecture/comms-inbox.md +8 -8
  758. package/docs/architecture/desktop-recording.md +2 -2
  759. package/docs/architecture/desktop-sessions.md +33 -21
  760. package/docs/architecture/external-public-shared-world.md +80 -64
  761. package/docs/architecture/github-feedback-loop.md +40 -27
  762. package/docs/architecture/guest-desktop.md +22 -10
  763. package/docs/architecture/local-browser-runtime.md +30 -21
  764. package/docs/architecture/observer-review.md +9 -9
  765. package/docs/architecture/observer.md +53 -57
  766. package/docs/architecture/participant-media.md +3 -3
  767. package/docs/architecture/project-layout.md +33 -137
  768. package/docs/architecture/real-email-receiving.md +7 -6
  769. package/docs/architecture/restricted-codex-analysis.md +211 -25
  770. package/docs/architecture/serve.md +89 -87
  771. package/docs/architecture/state-driven-executor.md +79 -64
  772. package/docs/architecture/task-protocol-support.md +18 -18
  773. package/docs/architecture/terminal-product-lane.md +92 -86
  774. package/docs/contracts/adapter-admission.md +8 -4
  775. package/docs/contracts/adapter-fixtures.md +6 -6
  776. package/docs/contracts/core.md +22 -24
  777. package/docs/contracts/feedback.md +33 -23
  778. package/docs/contracts/policy.md +28 -31
  779. package/docs/contracts/run-bundle.md +168 -82
  780. package/docs/contracts/schemas.md +563 -379
  781. package/docs/contracts/study-analysis.md +2 -2
  782. package/docs/contracts/study-costs.md +12 -12
  783. package/docs/decisions/0001-run-bundle-is-the-source-of-truth.md +36 -0
  784. package/docs/decisions/0002-observer-is-one-self-contained-file.md +30 -0
  785. package/docs/decisions/0003-contained-paths-and-cleanup-authority.md +35 -0
  786. package/docs/decisions/0004-participant-desktops-stay-in-the-route.md +31 -0
  787. package/docs/decisions/README.md +16 -0
  788. package/docs/goals/current.md +22 -50
  789. package/docs/principles/actor-fidelity.md +37 -40
  790. package/docs/principles/engineering.md +81 -0
  791. package/docs/principles/invariants-and-defaults.md +48 -45
  792. package/docs/principles/self-driving-harness.md +11 -10
  793. package/docs/principles/three-roles.md +12 -13
  794. package/docs/product/automatic-analysis.md +39 -9
  795. package/docs/product/lobby-trivia-3player-external-public.md +14 -13
  796. package/docs/product/open-source-install-experience.md +34 -38
  797. package/docs/ramp/README.md +91 -218
  798. package/docs/release/open-source-readiness.md +5 -2
  799. package/docs/release/public-readiness-standard.md +1 -1
  800. package/examples/README.md +11 -0
  801. package/examples/participant/README.md +80 -0
  802. package/examples/participant/app.mjs +55 -0
  803. package/examples/participant/run.mjs +116 -0
  804. package/examples/scorer/README.md +29 -0
  805. package/examples/scorer/run.mjs +63 -0
  806. package/examples/scorer/scorer.mjs +20 -0
  807. package/package.json +61 -57
  808. package/skills/humanish/SKILL.md +72 -60
  809. package/skills/humanish/agents/openai.yaml +2 -2
  810. package/dist/actor-contract.d.ts +0 -296
  811. package/dist/actor-contract.js +0 -340
  812. package/dist/actor-contract.js.map +0 -1
  813. package/dist/actor-goal-source.js +0 -32
  814. package/dist/actor-goal-source.js.map +0 -1
  815. package/dist/actor-registry.d.ts +0 -77
  816. package/dist/actor-registry.js +0 -106
  817. package/dist/actor-registry.js.map +0 -1
  818. package/dist/actor-stop-cause.d.ts +0 -9
  819. package/dist/actor-stop-cause.js +0 -42
  820. package/dist/actor-stop-cause.js.map +0 -1
  821. package/dist/adapter-extension.d.ts +0 -76
  822. package/dist/adapter-extension.js +0 -273
  823. package/dist/adapter-extension.js.map +0 -1
  824. package/dist/adapter-scorer-loader.d.ts +0 -42
  825. package/dist/adapter-scorer-loader.js +0 -129
  826. package/dist/adapter-scorer-loader.js.map +0 -1
  827. package/dist/affordance.d.ts +0 -53
  828. package/dist/affordance.js +0 -145
  829. package/dist/affordance.js.map +0 -1
  830. package/dist/agent-session.js +0 -43
  831. package/dist/agent-session.js.map +0 -1
  832. package/dist/argv.d.ts +0 -1
  833. package/dist/argv.js +0 -8
  834. package/dist/argv.js.map +0 -1
  835. package/dist/artifact-reference.d.ts +0 -22
  836. package/dist/artifact-reference.js +0 -47
  837. package/dist/artifact-reference.js.map +0 -1
  838. package/dist/automatic-analysis-completion.d.ts +0 -25
  839. package/dist/automatic-analysis-completion.js +0 -56
  840. package/dist/automatic-analysis-completion.js.map +0 -1
  841. package/dist/automatic-analysis-config.d.ts +0 -38
  842. package/dist/automatic-analysis-config.js +0 -68
  843. package/dist/automatic-analysis-config.js.map +0 -1
  844. package/dist/automatic-study-analysis.d.ts +0 -17
  845. package/dist/automatic-study-analysis.js +0 -195
  846. package/dist/automatic-study-analysis.js.map +0 -1
  847. package/dist/browser-control-client.d.ts +0 -18
  848. package/dist/browser-control-client.js +0 -176
  849. package/dist/browser-control-client.js.map +0 -1
  850. package/dist/browser-control-dispatcher.d.ts +0 -19
  851. package/dist/browser-control-dispatcher.js +0 -147
  852. package/dist/browser-control-dispatcher.js.map +0 -1
  853. package/dist/browser-control-protocol.d.ts +0 -472
  854. package/dist/browser-control-protocol.js +0 -185
  855. package/dist/browser-control-protocol.js.map +0 -1
  856. package/dist/browser-control-recording-transfer.d.ts +0 -4
  857. package/dist/browser-control-recording-transfer.js +0 -42
  858. package/dist/browser-control-recording-transfer.js.map +0 -1
  859. package/dist/browser-control-transport.d.ts +0 -27
  860. package/dist/browser-control-transport.js +0 -177
  861. package/dist/browser-control-transport.js.map +0 -1
  862. package/dist/browser-evidence-hygiene.js +0 -43
  863. package/dist/browser-evidence-hygiene.js.map +0 -1
  864. package/dist/chrome-cdp-probe.d.ts +0 -97
  865. package/dist/chrome-cdp-probe.js +0 -536
  866. package/dist/chrome-cdp-probe.js.map +0 -1
  867. package/dist/claude-agent-sdk.d.ts +0 -94
  868. package/dist/claude-agent-sdk.js +0 -367
  869. package/dist/claude-agent-sdk.js.map +0 -1
  870. package/dist/cli.js.map +0 -1
  871. package/dist/codex-app-server-ui.d.ts +0 -39
  872. package/dist/codex-app-server-ui.js +0 -357
  873. package/dist/codex-app-server-ui.js.map +0 -1
  874. package/dist/codex-app-server.d.ts +0 -144
  875. package/dist/codex-app-server.js +0 -754
  876. package/dist/codex-app-server.js.map +0 -1
  877. package/dist/command-failure.d.ts +0 -43
  878. package/dist/command-failure.js +0 -73
  879. package/dist/command-failure.js.map +0 -1
  880. package/dist/comms-agentmail.d.ts +0 -25
  881. package/dist/comms-agentmail.js +0 -418
  882. package/dist/comms-agentmail.js.map +0 -1
  883. package/dist/comms-catch-host.d.ts +0 -52
  884. package/dist/comms-catch-host.js +0 -178
  885. package/dist/comms-catch-host.js.map +0 -1
  886. package/dist/comms-connections.d.ts +0 -52
  887. package/dist/comms-connections.js +0 -123
  888. package/dist/comms-connections.js.map +0 -1
  889. package/dist/comms-email-catch.d.ts +0 -54
  890. package/dist/comms-email-catch.js +0 -212
  891. package/dist/comms-email-catch.js.map +0 -1
  892. package/dist/comms-evidence.d.ts +0 -27
  893. package/dist/comms-evidence.js +0 -31
  894. package/dist/comms-evidence.js.map +0 -1
  895. package/dist/comms-fake-inbox.d.ts +0 -45
  896. package/dist/comms-fake-inbox.js +0 -184
  897. package/dist/comms-fake-inbox.js.map +0 -1
  898. package/dist/comms-images.d.ts +0 -7
  899. package/dist/comms-images.js +0 -39
  900. package/dist/comms-images.js.map +0 -1
  901. package/dist/comms-inbox.d.ts +0 -66
  902. package/dist/comms-inbox.js +0 -389
  903. package/dist/comms-inbox.js.map +0 -1
  904. package/dist/comms-lease-store.d.ts +0 -91
  905. package/dist/comms-lease-store.js +0 -495
  906. package/dist/comms-lease-store.js.map +0 -1
  907. package/dist/comms-receiving-evidence.d.ts +0 -46
  908. package/dist/comms-receiving-evidence.js +0 -35
  909. package/dist/comms-receiving-evidence.js.map +0 -1
  910. package/dist/comms-receiving-inbox.d.ts +0 -16
  911. package/dist/comms-receiving-inbox.js +0 -410
  912. package/dist/comms-receiving-inbox.js.map +0 -1
  913. package/dist/comms-receiving-runtime.d.ts +0 -25
  914. package/dist/comms-receiving-runtime.js +0 -45
  915. package/dist/comms-receiving-runtime.js.map +0 -1
  916. package/dist/comms-receiving-types.d.ts +0 -98
  917. package/dist/comms-receiving-types.js +0 -2
  918. package/dist/comms-receiving-types.js.map +0 -1
  919. package/dist/comms-receiving.d.ts +0 -58
  920. package/dist/comms-receiving.js +0 -554
  921. package/dist/comms-receiving.js.map +0 -1
  922. package/dist/comms-sandbox-catch.d.ts +0 -229
  923. package/dist/comms-sandbox-catch.js +0 -737
  924. package/dist/comms-sandbox-catch.js.map +0 -1
  925. package/dist/comms-setup.d.ts +0 -40
  926. package/dist/comms-setup.js +0 -121
  927. package/dist/comms-setup.js.map +0 -1
  928. package/dist/comms-types.d.ts +0 -72
  929. package/dist/comms-types.js +0 -10
  930. package/dist/comms-types.js.map +0 -1
  931. package/dist/computer-use-actor.d.ts +0 -76
  932. package/dist/computer-use-actor.js +0 -68
  933. package/dist/computer-use-actor.js.map +0 -1
  934. package/dist/computer-use.d.ts +0 -429
  935. package/dist/computer-use.js +0 -1751
  936. package/dist/computer-use.js.map +0 -1
  937. package/dist/concurrency.js +0 -27
  938. package/dist/concurrency.js.map +0 -1
  939. package/dist/concurrent-shared-world-lab.d.ts +0 -186
  940. package/dist/concurrent-shared-world-lab.js +0 -2181
  941. package/dist/concurrent-shared-world-lab.js.map +0 -1
  942. package/dist/core/git-state.d.ts +0 -33
  943. package/dist/core/git-state.js +0 -277
  944. package/dist/core/git-state.js.map +0 -1
  945. package/dist/core/git-workspace.d.ts +0 -31
  946. package/dist/core/git-workspace.js +0 -447
  947. package/dist/core/git-workspace.js.map +0 -1
  948. package/dist/core/index.d.ts +0 -4
  949. package/dist/core/index.js +0 -3
  950. package/dist/core/index.js.map +0 -1
  951. package/dist/core/run-primitives.d.ts +0 -66
  952. package/dist/core/run-primitives.js +0 -120
  953. package/dist/core/run-primitives.js.map +0 -1
  954. package/dist/cua-actor-lab.d.ts +0 -855
  955. package/dist/cua-actor-lab.js +0 -3543
  956. package/dist/cua-actor-lab.js.map +0 -1
  957. package/dist/cua-admission-limit.d.ts +0 -12
  958. package/dist/cua-admission-limit.js +0 -20
  959. package/dist/cua-admission-limit.js.map +0 -1
  960. package/dist/cua-desktop-lane.d.ts +0 -35
  961. package/dist/cua-desktop-lane.js +0 -13
  962. package/dist/cua-desktop-lane.js.map +0 -1
  963. package/dist/cua-diagnostics.d.ts +0 -38
  964. package/dist/cua-diagnostics.js +0 -68
  965. package/dist/cua-diagnostics.js.map +0 -1
  966. package/dist/cua-executor-error.js +0 -48
  967. package/dist/cua-executor-error.js.map +0 -1
  968. package/dist/cua-provider-error.d.ts +0 -16
  969. package/dist/cua-provider-error.js +0 -35
  970. package/dist/cua-provider-error.js.map +0 -1
  971. package/dist/cua-speech.js +0 -2
  972. package/dist/cua-speech.js.map +0 -1
  973. package/dist/desktop-recorder.d.ts +0 -39
  974. package/dist/desktop-recorder.js +0 -226
  975. package/dist/desktop-recorder.js.map +0 -1
  976. package/dist/desktop-recording-artifact.d.ts +0 -5
  977. package/dist/desktop-recording-artifact.js +0 -54
  978. package/dist/desktop-recording-artifact.js.map +0 -1
  979. package/dist/desktop-recording-types.d.ts +0 -24
  980. package/dist/desktop-recording-types.js +0 -14
  981. package/dist/desktop-recording-types.js.map +0 -1
  982. package/dist/desktop-session.d.ts +0 -41
  983. package/dist/desktop-session.js +0 -47
  984. package/dist/desktop-session.js.map +0 -1
  985. package/dist/device-presets.d.ts +0 -67
  986. package/dist/device-presets.js +0 -55
  987. package/dist/device-presets.js.map +0 -1
  988. package/dist/doctor-lab.d.ts +0 -38
  989. package/dist/doctor-lab.js +0 -126
  990. package/dist/doctor-lab.js.map +0 -1
  991. package/dist/e2b-cua-desktop.d.ts +0 -3
  992. package/dist/e2b-cua-desktop.js +0 -708
  993. package/dist/e2b-cua-desktop.js.map +0 -1
  994. package/dist/e2b-cua-provisioning.d.ts +0 -314
  995. package/dist/e2b-cua-provisioning.js +0 -1219
  996. package/dist/e2b-cua-provisioning.js.map +0 -1
  997. package/dist/e2b-desktop-executor.d.ts +0 -101
  998. package/dist/e2b-desktop-executor.js +0 -297
  999. package/dist/e2b-desktop-executor.js.map +0 -1
  1000. package/dist/e2b-desktop-launch.d.ts +0 -243
  1001. package/dist/e2b-desktop-launch.js +0 -234
  1002. package/dist/e2b-desktop-launch.js.map +0 -1
  1003. package/dist/e2b-desktop-media.d.ts +0 -14
  1004. package/dist/e2b-desktop-media.js +0 -58
  1005. package/dist/e2b-desktop-media.js.map +0 -1
  1006. package/dist/e2b-desktop-recording.d.ts +0 -16
  1007. package/dist/e2b-desktop-recording.js +0 -162
  1008. package/dist/e2b-desktop-recording.js.map +0 -1
  1009. package/dist/e2b-desktop-resources.d.ts +0 -11
  1010. package/dist/e2b-desktop-resources.js +0 -33
  1011. package/dist/e2b-desktop-resources.js.map +0 -1
  1012. package/dist/e2b-desktop-screenshot-cleanup.d.ts +0 -15
  1013. package/dist/e2b-desktop-screenshot-cleanup.js +0 -67
  1014. package/dist/e2b-desktop-screenshot-cleanup.js.map +0 -1
  1015. package/dist/e2b-desktop-session.d.ts +0 -7
  1016. package/dist/e2b-desktop-session.js +0 -29
  1017. package/dist/e2b-desktop-session.js.map +0 -1
  1018. package/dist/e2b-detached.d.ts +0 -53
  1019. package/dist/e2b-detached.js +0 -130
  1020. package/dist/e2b-detached.js.map +0 -1
  1021. package/dist/e2b-terminal-lab.d.ts +0 -383
  1022. package/dist/e2b-terminal-lab.js +0 -2000
  1023. package/dist/e2b-terminal-lab.js.map +0 -1
  1024. package/dist/env-file.d.ts +0 -14
  1025. package/dist/env-file.js +0 -108
  1026. package/dist/env-file.js.map +0 -1
  1027. package/dist/export-bundle.d.ts +0 -7
  1028. package/dist/export-bundle.js +0 -441
  1029. package/dist/export-bundle.js.map +0 -1
  1030. package/dist/export.d.ts +0 -49
  1031. package/dist/export.js +0 -308
  1032. package/dist/export.js.map +0 -1
  1033. package/dist/feedback-proof.d.ts +0 -8
  1034. package/dist/feedback-proof.js +0 -44
  1035. package/dist/feedback-proof.js.map +0 -1
  1036. package/dist/feedback.d.ts +0 -76
  1037. package/dist/feedback.js +0 -496
  1038. package/dist/feedback.js.map +0 -1
  1039. package/dist/first-run-path.d.ts +0 -55
  1040. package/dist/first-run-path.js +0 -136
  1041. package/dist/first-run-path.js.map +0 -1
  1042. package/dist/frame-signature.d.ts +0 -24
  1043. package/dist/frame-signature.js +0 -128
  1044. package/dist/frame-signature.js.map +0 -1
  1045. package/dist/guest-bootstrap.d.ts +0 -55
  1046. package/dist/guest-bootstrap.js +0 -285
  1047. package/dist/guest-bootstrap.js.map +0 -1
  1048. package/dist/guest-browser-tools.d.ts +0 -8
  1049. package/dist/guest-browser-tools.js +0 -66
  1050. package/dist/guest-browser-tools.js.map +0 -1
  1051. package/dist/guest-chromium-text.d.ts +0 -27
  1052. package/dist/guest-chromium-text.js +0 -281
  1053. package/dist/guest-chromium-text.js.map +0 -1
  1054. package/dist/guest-desktop-executor.d.ts +0 -22
  1055. package/dist/guest-desktop-executor.js +0 -178
  1056. package/dist/guest-desktop-executor.js.map +0 -1
  1057. package/dist/guest-desktop-media.d.ts +0 -33
  1058. package/dist/guest-desktop-media.js +0 -281
  1059. package/dist/guest-desktop-media.js.map +0 -1
  1060. package/dist/guest-desktop-native.d.ts +0 -14
  1061. package/dist/guest-desktop-native.js +0 -131
  1062. package/dist/guest-desktop-native.js.map +0 -1
  1063. package/dist/guest-media-config.d.ts +0 -15
  1064. package/dist/guest-media-config.js +0 -8
  1065. package/dist/guest-media-config.js.map +0 -1
  1066. package/dist/guest-media-worker.js.map +0 -1
  1067. package/dist/guest-runtime-desktop.d.ts +0 -42
  1068. package/dist/guest-runtime-desktop.js +0 -314
  1069. package/dist/guest-runtime-desktop.js.map +0 -1
  1070. package/dist/guest-runtime-main.js.map +0 -1
  1071. package/dist/guest-runtime-revision.js.map +0 -1
  1072. package/dist/guest-runtime.d.ts +0 -31
  1073. package/dist/guest-runtime.js +0 -99
  1074. package/dist/guest-runtime.js.map +0 -1
  1075. package/dist/image-evidence.d.ts +0 -2
  1076. package/dist/image-evidence.js +0 -47
  1077. package/dist/image-evidence.js.map +0 -1
  1078. package/dist/index.js.map +0 -1
  1079. package/dist/init-templates.d.ts +0 -25
  1080. package/dist/init-templates.js +0 -541
  1081. package/dist/init-templates.js.map +0 -1
  1082. package/dist/init.d.ts +0 -38
  1083. package/dist/init.js +0 -532
  1084. package/dist/init.js.map +0 -1
  1085. package/dist/key-resolution.d.ts +0 -67
  1086. package/dist/key-resolution.js +0 -375
  1087. package/dist/key-resolution.js.map +0 -1
  1088. package/dist/lab-app-runner.d.ts +0 -78
  1089. package/dist/lab-app-runner.js +0 -403
  1090. package/dist/lab-app-runner.js.map +0 -1
  1091. package/dist/lab-config.d.ts +0 -968
  1092. package/dist/lab-config.js +0 -2714
  1093. package/dist/lab-config.js.map +0 -1
  1094. package/dist/lab-engine.d.ts +0 -97
  1095. package/dist/lab-engine.js +0 -285
  1096. package/dist/lab-engine.js.map +0 -1
  1097. package/dist/lab-preflight.d.ts +0 -70
  1098. package/dist/lab-preflight.js +0 -388
  1099. package/dist/lab-preflight.js.map +0 -1
  1100. package/dist/lab-summary.d.ts +0 -57
  1101. package/dist/lab-summary.js +0 -126
  1102. package/dist/lab-summary.js.map +0 -1
  1103. package/dist/labs.d.ts +0 -66
  1104. package/dist/labs.js +0 -401
  1105. package/dist/labs.js.map +0 -1
  1106. package/dist/listen.js +0 -84
  1107. package/dist/listen.js.map +0 -1
  1108. package/dist/local-agent-claude-session.d.ts +0 -45
  1109. package/dist/local-agent-claude-session.js +0 -203
  1110. package/dist/local-agent-claude-session.js.map +0 -1
  1111. package/dist/local-agent-cli.d.ts +0 -121
  1112. package/dist/local-agent-cli.js +0 -427
  1113. package/dist/local-agent-cli.js.map +0 -1
  1114. package/dist/local-captured-inbox.d.ts +0 -6
  1115. package/dist/local-captured-inbox.js +0 -65
  1116. package/dist/local-captured-inbox.js.map +0 -1
  1117. package/dist/local-firecracker-desktop.d.ts +0 -23
  1118. package/dist/local-firecracker-desktop.js +0 -191
  1119. package/dist/local-firecracker-desktop.js.map +0 -1
  1120. package/dist/local-firecracker-study.d.ts +0 -9
  1121. package/dist/local-firecracker-study.js +0 -135
  1122. package/dist/local-firecracker-study.js.map +0 -1
  1123. package/dist/local-runtime-config.d.ts +0 -6
  1124. package/dist/local-runtime-config.js +0 -60
  1125. package/dist/local-runtime-config.js.map +0 -1
  1126. package/dist/local-runtime-host.d.ts +0 -31
  1127. package/dist/local-runtime-host.js +0 -128
  1128. package/dist/local-runtime-host.js.map +0 -1
  1129. package/dist/local-runtime-release.d.ts +0 -7
  1130. package/dist/local-runtime-release.js +0 -33
  1131. package/dist/local-runtime-release.js.map +0 -1
  1132. package/dist/local-runtime-ssh.d.ts +0 -27
  1133. package/dist/local-runtime-ssh.js +0 -91
  1134. package/dist/local-runtime-ssh.js.map +0 -1
  1135. package/dist/local-runtime.d.ts +0 -25
  1136. package/dist/local-runtime.js +0 -133
  1137. package/dist/local-runtime.js.map +0 -1
  1138. package/dist/observer-data.d.ts +0 -114
  1139. package/dist/observer-data.js +0 -224
  1140. package/dist/observer-data.js.map +0 -1
  1141. package/dist/observer-library.js +0 -191
  1142. package/dist/observer-library.js.map +0 -1
  1143. package/dist/observer-serve.d.ts +0 -99
  1144. package/dist/observer-serve.js +0 -284
  1145. package/dist/observer-serve.js.map +0 -1
  1146. package/dist/observer-static.js +0 -357
  1147. package/dist/observer-static.js.map +0 -1
  1148. package/dist/observer.d.ts +0 -118
  1149. package/dist/observer.js +0 -947
  1150. package/dist/observer.js.map +0 -1
  1151. package/dist/openai-responses-cu.d.ts +0 -158
  1152. package/dist/openai-responses-cu.js +0 -714
  1153. package/dist/openai-responses-cu.js.map +0 -1
  1154. package/dist/orientation.d.ts +0 -29
  1155. package/dist/orientation.js +0 -95
  1156. package/dist/orientation.js.map +0 -1
  1157. package/dist/oss-lab.d.ts +0 -55
  1158. package/dist/oss-lab.js +0 -344
  1159. package/dist/oss-lab.js.map +0 -1
  1160. package/dist/oss-meta-lab-scoring.d.ts +0 -15
  1161. package/dist/oss-meta-lab-scoring.js +0 -145
  1162. package/dist/oss-meta-lab-scoring.js.map +0 -1
  1163. package/dist/oss-meta-lab.d.ts +0 -287
  1164. package/dist/oss-meta-lab.js +0 -4551
  1165. package/dist/oss-meta-lab.js.map +0 -1
  1166. package/dist/oss-remote-telemetry.d.ts +0 -77
  1167. package/dist/oss-remote-telemetry.js +0 -403
  1168. package/dist/oss-remote-telemetry.js.map +0 -1
  1169. package/dist/output-token-limit.js +0 -5
  1170. package/dist/output-token-limit.js.map +0 -1
  1171. package/dist/participant-assignment.d.ts +0 -12
  1172. package/dist/participant-assignment.js +0 -15
  1173. package/dist/participant-assignment.js.map +0 -1
  1174. package/dist/persona-resolve.d.ts +0 -44
  1175. package/dist/persona-resolve.js +0 -99
  1176. package/dist/persona-resolve.js.map +0 -1
  1177. package/dist/persona.d.ts +0 -39
  1178. package/dist/persona.js +0 -144
  1179. package/dist/persona.js.map +0 -1
  1180. package/dist/pi-agent-core.d.ts +0 -77
  1181. package/dist/pi-agent-core.js +0 -207
  1182. package/dist/pi-agent-core.js.map +0 -1
  1183. package/dist/pricing.d.ts +0 -145
  1184. package/dist/pricing.js +0 -277
  1185. package/dist/pricing.js.map +0 -1
  1186. package/dist/program.d.ts +0 -96
  1187. package/dist/program.js +0 -4030
  1188. package/dist/program.js.map +0 -1
  1189. package/dist/reasoning-effort.js +0 -26
  1190. package/dist/reasoning-effort.js.map +0 -1
  1191. package/dist/reclaim.d.ts +0 -31
  1192. package/dist/reclaim.js +0 -90
  1193. package/dist/reclaim.js.map +0 -1
  1194. package/dist/redaction.d.ts +0 -90
  1195. package/dist/redaction.js +0 -294
  1196. package/dist/redaction.js.map +0 -1
  1197. package/dist/restricted-codex-analysis.d.ts +0 -15
  1198. package/dist/restricted-codex-analysis.js +0 -13
  1199. package/dist/restricted-codex-analysis.js.map +0 -1
  1200. package/dist/restricted-codex-participant-policy.d.ts +0 -44
  1201. package/dist/restricted-codex-participant-policy.js +0 -43
  1202. package/dist/restricted-codex-participant-policy.js.map +0 -1
  1203. package/dist/restricted-codex-participant-run.d.ts +0 -20
  1204. package/dist/restricted-codex-participant-run.js +0 -79
  1205. package/dist/restricted-codex-participant-run.js.map +0 -1
  1206. package/dist/restricted-codex-participant.d.ts +0 -20
  1207. package/dist/restricted-codex-participant.js +0 -250
  1208. package/dist/restricted-codex-participant.js.map +0 -1
  1209. package/dist/restricted-codex-policy.d.ts +0 -64
  1210. package/dist/restricted-codex-policy.js +0 -176
  1211. package/dist/restricted-codex-policy.js.map +0 -1
  1212. package/dist/restricted-codex-session.d.ts +0 -44
  1213. package/dist/restricted-codex-session.js +0 -657
  1214. package/dist/restricted-codex-session.js.map +0 -1
  1215. package/dist/restricted-codex-transport.d.ts +0 -69
  1216. package/dist/restricted-codex-transport.js +0 -296
  1217. package/dist/restricted-codex-transport.js.map +0 -1
  1218. package/dist/run-detail.d.ts +0 -61
  1219. package/dist/run-detail.js +0 -137
  1220. package/dist/run-detail.js.map +0 -1
  1221. package/dist/run-index.d.ts +0 -71
  1222. package/dist/run-index.js +0 -206
  1223. package/dist/run-index.js.map +0 -1
  1224. package/dist/run-narration-secrets.js +0 -68
  1225. package/dist/run-narration-secrets.js.map +0 -1
  1226. package/dist/run-paths.d.ts +0 -56
  1227. package/dist/run-paths.js +0 -355
  1228. package/dist/run-paths.js.map +0 -1
  1229. package/dist/run-projection.d.ts +0 -186
  1230. package/dist/run-projection.js +0 -350
  1231. package/dist/run-projection.js.map +0 -1
  1232. package/dist/run-status.d.ts +0 -139
  1233. package/dist/run-status.js +0 -218
  1234. package/dist/run-status.js.map +0 -1
  1235. package/dist/run.d.ts +0 -1255
  1236. package/dist/run.js +0 -5949
  1237. package/dist/run.js.map +0 -1
  1238. package/dist/sandbox-receipts.d.ts +0 -19
  1239. package/dist/sandbox-receipts.js +0 -51
  1240. package/dist/sandbox-receipts.js.map +0 -1
  1241. package/dist/screenshot-image.d.ts +0 -11
  1242. package/dist/screenshot-image.js +0 -26
  1243. package/dist/screenshot-image.js.map +0 -1
  1244. package/dist/scripted-browser-actor.d.ts +0 -297
  1245. package/dist/scripted-browser-actor.js +0 -1399
  1246. package/dist/scripted-browser-actor.js.map +0 -1
  1247. package/dist/scripted-browser-lab.d.ts +0 -121
  1248. package/dist/scripted-browser-lab.js +0 -852
  1249. package/dist/scripted-browser-lab.js.map +0 -1
  1250. package/dist/secret-prompt.js +0 -36
  1251. package/dist/secret-prompt.js.map +0 -1
  1252. package/dist/selected-output-paths.d.ts +0 -52
  1253. package/dist/selected-output-paths.js +0 -366
  1254. package/dist/selected-output-paths.js.map +0 -1
  1255. package/dist/serve-exposure.d.ts +0 -62
  1256. package/dist/serve-exposure.js +0 -129
  1257. package/dist/serve-exposure.js.map +0 -1
  1258. package/dist/serve-http.js +0 -45
  1259. package/dist/serve-http.js.map +0 -1
  1260. package/dist/serve-tunnel.js +0 -113
  1261. package/dist/serve-tunnel.js.map +0 -1
  1262. package/dist/shared-world-lab.d.ts +0 -269
  1263. package/dist/shared-world-lab.js +0 -1424
  1264. package/dist/shared-world-lab.js.map +0 -1
  1265. package/dist/source-archive.d.ts +0 -82
  1266. package/dist/source-archive.js +0 -408
  1267. package/dist/source-archive.js.map +0 -1
  1268. package/dist/stats.d.ts +0 -82
  1269. package/dist/stats.js +0 -219
  1270. package/dist/stats.js.map +0 -1
  1271. package/dist/stop-conditions.d.ts +0 -39
  1272. package/dist/stop-conditions.js +0 -66
  1273. package/dist/stop-conditions.js.map +0 -1
  1274. package/dist/study-analysis-codex-config.d.ts +0 -11
  1275. package/dist/study-analysis-codex-config.js +0 -34
  1276. package/dist/study-analysis-codex-config.js.map +0 -1
  1277. package/dist/study-analysis-engine.d.ts +0 -47
  1278. package/dist/study-analysis-engine.js +0 -327
  1279. package/dist/study-analysis-engine.js.map +0 -1
  1280. package/dist/study-analysis-evidence.d.ts +0 -27
  1281. package/dist/study-analysis-evidence.js +0 -660
  1282. package/dist/study-analysis-evidence.js.map +0 -1
  1283. package/dist/study-analysis-job.d.ts +0 -97
  1284. package/dist/study-analysis-job.js +0 -214
  1285. package/dist/study-analysis-job.js.map +0 -1
  1286. package/dist/study-analysis-provider.d.ts +0 -40
  1287. package/dist/study-analysis-provider.js +0 -170
  1288. package/dist/study-analysis-provider.js.map +0 -1
  1289. package/dist/study-analysis-service.d.ts +0 -59
  1290. package/dist/study-analysis-service.js +0 -257
  1291. package/dist/study-analysis-service.js.map +0 -1
  1292. package/dist/study-analysis-sharing.d.ts +0 -11
  1293. package/dist/study-analysis-sharing.js +0 -35
  1294. package/dist/study-analysis-sharing.js.map +0 -1
  1295. package/dist/study-analysis-store.d.ts +0 -47
  1296. package/dist/study-analysis-store.js +0 -493
  1297. package/dist/study-analysis-store.js.map +0 -1
  1298. package/dist/study-analysis-validation.d.ts +0 -618
  1299. package/dist/study-analysis-validation.js +0 -384
  1300. package/dist/study-analysis-validation.js.map +0 -1
  1301. package/dist/study-analysis.d.ts +0 -206
  1302. package/dist/study-analysis.js +0 -4
  1303. package/dist/study-analysis.js.map +0 -1
  1304. package/dist/study-costs.js +0 -114
  1305. package/dist/study-costs.js.map +0 -1
  1306. package/dist/subject-runtime.d.ts +0 -23
  1307. package/dist/subject-runtime.js +0 -70
  1308. package/dist/subject-runtime.js.map +0 -1
  1309. package/dist/tasks.d.ts +0 -90
  1310. package/dist/tasks.js +0 -144
  1311. package/dist/tasks.js.map +0 -1
  1312. package/dist/telemetry.js +0 -324
  1313. package/dist/telemetry.js.map +0 -1
  1314. package/dist/terminal-agent-actor.d.ts +0 -41
  1315. package/dist/terminal-agent-actor.js +0 -25
  1316. package/dist/terminal-agent-actor.js.map +0 -1
  1317. package/dist/terminal-encoding.js +0 -80
  1318. package/dist/terminal-encoding.js.map +0 -1
  1319. package/dist/terminal-node-bootstrap.d.ts +0 -4
  1320. package/dist/terminal-node-bootstrap.js +0 -58
  1321. package/dist/terminal-node-bootstrap.js.map +0 -1
  1322. package/dist/terminal-participant-activity.d.ts +0 -6
  1323. package/dist/terminal-participant-activity.js +0 -34
  1324. package/dist/terminal-participant-activity.js.map +0 -1
  1325. package/dist/terminal-runtime-auth.d.ts +0 -13
  1326. package/dist/terminal-runtime-auth.js +0 -24
  1327. package/dist/terminal-runtime-auth.js.map +0 -1
  1328. package/dist/terminal-runtime.d.ts +0 -16
  1329. package/dist/terminal-runtime.js +0 -42
  1330. package/dist/terminal-runtime.js.map +0 -1
  1331. package/dist/terminal-token-usage.d.ts +0 -15
  1332. package/dist/terminal-token-usage.js +0 -94
  1333. package/dist/terminal-token-usage.js.map +0 -1
  1334. package/dist/tui-actions.d.ts +0 -39
  1335. package/dist/tui-actions.js +0 -178
  1336. package/dist/tui-actions.js.map +0 -1
  1337. package/dist/tui-contract.d.ts +0 -141
  1338. package/dist/tui-contract.js +0 -54
  1339. package/dist/tui-contract.js.map +0 -1
  1340. package/dist/tui-launch.js +0 -167
  1341. package/dist/tui-launch.js.map +0 -1
  1342. package/dist/tui-project.d.ts +0 -9
  1343. package/dist/tui-project.js +0 -18
  1344. package/dist/tui-project.js.map +0 -1
  1345. package/docs/architecture/examples/state-driven-local-app/README.md +0 -80
  1346. package/docs/architecture/examples/state-driven-local-app/app.mjs +0 -48
  1347. package/docs/architecture/examples/state-driven-local-app/runner.mjs +0 -105
  1348. package/docs/architecture/local-codex-tui-actor.md +0 -213
  1349. package/docs/architecture/oss-lab-poc.md +0 -250
  1350. package/docs/architecture/runtime-broker-core.md +0 -30
  1351. package/docs/release/0.100.0-local-setup.md +0 -31
  1352. package/docs/release/0.100.1-participant-continuity.md +0 -20
  1353. package/docs/release/0.101.0-codex-ui-tools.md +0 -28
  1354. package/docs/release/0.102.0-participant-media.md +0 -43
  1355. package/docs/release/0.103.0-desktop-recording.md +0 -29
  1356. package/docs/release/0.103.1-analysis-capture-allocation.md +0 -18
  1357. package/docs/release/0.103.2-analysis-ending-context.md +0 -21
  1358. package/docs/release/0.104.0-local-captured-inboxes.md +0 -29
  1359. package/docs/release/0.104.1-recording-startup.md +0 -24
  1360. package/docs/release/0.104.2-recording-timestamps.md +0 -32
  1361. package/docs/release/0.104.3-local-smtp-catch.md +0 -15
  1362. package/docs/release/0.105.0-participant-backgrounds.md +0 -50
  1363. package/docs/release/0.20.0-external-public-shared-world.md +0 -43
  1364. package/docs/release/0.84.0-redacted-evidence.md +0 -42
  1365. package/docs/release/0.84.1-portable-feedback.md +0 -20
  1366. package/docs/release/0.85.0-observer-review.md +0 -56
  1367. package/docs/release/0.85.1-observer-continuity.md +0 -20
  1368. package/docs/release/0.86.0-participant-evidence.md +0 -50
  1369. package/docs/release/0.86.1-task-preflight-saved-recordings.md +0 -40
  1370. package/docs/release/0.87.0-participant-endings-and-phone-review.md +0 -64
  1371. package/docs/release/0.88.0-study-diagnostics.md +0 -43
  1372. package/docs/release/0.88.1-completion-evidence-and-local-app.md +0 -79
  1373. package/docs/release/0.88.2-sequential-study-budgets.md +0 -57
  1374. package/docs/release/0.89.0-study-findings.md +0 -79
  1375. package/docs/release/0.89.1-analysis-finished-notice.md +0 -24
  1376. package/docs/release/0.90.0-automatic-analysis.md +0 -21
  1377. package/docs/release/0.91.0-analysis-quality-and-defaults.md +0 -33
  1378. package/docs/release/0.91.1-study-review-polish.md +0 -28
  1379. package/docs/release/0.92.0-grid-playback.md +0 -22
  1380. package/docs/release/0.93.0-global-playback.md +0 -26
  1381. package/docs/release/0.93.1-observer-review-controls.md +0 -24
  1382. package/docs/release/0.94.0-reliability.md +0 -48
  1383. package/docs/release/0.95.0-connections-setup.md +0 -38
  1384. package/docs/release/0.96.0-real-email-receiving.md +0 -47
  1385. package/docs/release/0.96.1-browser-navigation.md +0 -22
  1386. package/docs/release/0.97.0-codex-account-analysis.md +0 -45
  1387. package/docs/release/0.98.0-local-browser-studies.md +0 -31
  1388. package/docs/release/0.99.0-local-browser-mac.md +0 -34
  1389. package/docs/release/0.99.1-action-recovery.md +0 -19
  1390. /package/dist/{agent-session.d.ts → actors/agent-session.d.ts} +0 -0
  1391. /package/dist/{cua-executor-error.d.ts → actors/computer-use/executor-error.d.ts} +0 -0
  1392. /package/dist/{cua-speech.d.ts → actors/computer-use/speech.d.ts} +0 -0
  1393. /package/dist/{actor-goal-source.d.ts → actors/goal-source.d.ts} +0 -0
  1394. /package/dist/{output-token-limit.d.ts → actors/output-token-limit.d.ts} +0 -0
  1395. /package/dist/{reasoning-effort.d.ts → actors/reasoning-effort.d.ts} +0 -0
  1396. /package/dist/{secret-prompt.d.ts → cli/secret-prompt.d.ts} +0 -0
  1397. /package/dist/{telemetry.d.ts → cli/telemetry.d.ts} +0 -0
  1398. /package/dist/{browser-evidence-hygiene.d.ts → evidence/browser-hygiene.d.ts} +0 -0
  1399. /package/dist/{serve-http.d.ts → observer/http.d.ts} +0 -0
  1400. /package/dist/{observer-library.d.ts → observer/library.d.ts} +0 -0
  1401. /package/dist/{listen.d.ts → observer/listen.d.ts} +0 -0
  1402. /package/dist/{observer-static.d.ts → observer/static.d.ts} +0 -0
  1403. /package/dist/{serve-tunnel.d.ts → observer/tunnel.d.ts} +0 -0
  1404. /package/dist/{terminal-encoding.d.ts → routes/terminal/encoding.d.ts} +0 -0
  1405. /package/dist/{concurrency.d.ts → run/concurrency.d.ts} +0 -0
  1406. /package/dist/{study-costs.d.ts → run/costs.d.ts} +0 -0
  1407. /package/dist/{run-narration-secrets.d.ts → run/transient-comms-secrets.d.ts} +0 -0
  1408. /package/dist/{tui-launch.d.ts → tui/launch.d.ts} +0 -0
@@ -1,1219 +0,0 @@
1
- // Hosted desktop setup primitives. The lane adapter owns their lifecycle.
2
- import { readFile } from "node:fs/promises";
3
- import path from "node:path";
4
- import { CHROMIUM_EVIDENCE_HYGIENE_FLAGS, chromiumEvidenceProfilePreferencesJson } from "./browser-evidence-hygiene.js";
5
- import { chromeCdpProbeCommand, parseChromeCdpProbeOutput } from "./chrome-cdp-probe.js";
6
- import { runDesktopCommandOrThrow, toErrorMessage } from "./command-failure.js";
7
- import {} from "./device-presets.js";
8
- import { withOneRetryOnTransientE2BError } from "./e2b-desktop-launch.js";
9
- import { probeUrl, readDetachedLog, runDetachedStep, startDetachedProcess } from "./e2b-detached.js";
10
- import { isHttpUrl } from "./lab-config.js";
11
- import { digestText, redactText, redactedTail } from "./redaction.js";
12
- import {} from "./run.js";
13
- import { corepackCommandFor, needsNodeRuntime, nodeBootstrapCommand } from "./subject-runtime.js";
14
- import { TERMINAL_NODE_BOOTSTRAP_COMMAND } from "./terminal-node-bootstrap.js";
15
- export const CUA_ACTOR_LAB_PROVIDER_METADATA = {
16
- mode: "cua-actor-lab",
17
- tool: "humanish"
18
- };
19
- // Settle after opening the browser, before the first screenshot — long enough for a cold
20
- // browser + page load to paint (2s captured a blank desktop; the render empirically needs ~6-9s).
21
- export const BROWSER_SETTLE_MS = 8_000;
22
- /** Where a lane's synthetic camera feed lives inside the sandbox: a tmpfs the sandbox user can
23
- * write, and a path that contains neither /tmp/ nor /home/, which the public-safety scan reads
24
- * as an operator's local path (this one is the harness's own and belongs in the bundle). */
25
- export const SANDBOX_MEDIA_DIR = "/dev/shm/humanish-media";
26
- export const SANDBOX_CAMERA_PATH = `${SANDBOX_MEDIA_DIR}/camera.y4m`;
27
- /** The synthetic feed: ffmpeg's test pattern, 640x480 at 10 fps, six seconds (about 28 MB of
28
- * raw Y4M on the tmpfs), looped by Chrome's fake capture device. */
29
- export const SYNTHETIC_CAMERA_COMMAND = `mkdir -p ${SANDBOX_MEDIA_DIR} && ffmpeg -y -loglevel error -f lavfi -i testsrc=size=640x480:rate=10 -t 6 -pix_fmt yuv420p ${SANDBOX_CAMERA_PATH}`;
30
- /**
31
- * Put the declared camera feed in the sandbox and return the Chromium flags that present it as a
32
- * capture device (#509). Fails CLOSED: a feed that cannot be produced (no ffmpeg on the image, an
33
- * unreadable host file) is named before the browser launches, because a participant told it has
34
- * a camera and finds none reports the instrument's gap as the product's.
35
- */
36
- export async function prepareDesktopMedia(desktop, media, permission, cwd, requestTimeoutMs, readHostFile = (absolutePath) => readFile(absolutePath)) {
37
- if (media.microphone !== undefined) {
38
- if (media.microphone.source !== "speech")
39
- throw new Error("Microphone source-file injection is unsupported; use source: speech.");
40
- if (media.camera !== undefined)
41
- throw new Error("Hosted synthetic cameras cannot be combined with speech.");
42
- // The lane starts and admits the speech worker before launching the browser.
43
- return { microphone: { source: "speech" }, permission, flags: permission === "granted" ? ["--use-fake-ui-for-media-stream"] : [] };
44
- }
45
- const flags = [];
46
- let camera;
47
- if (media.camera !== undefined) {
48
- if (media.camera.source === "synthetic") {
49
- const made = await desktop.commands.run(SYNTHETIC_CAMERA_COMMAND, { requestTimeoutMs, timeoutMs: 60_000 });
50
- if (made.exitCode !== undefined && made.exitCode !== 0) {
51
- throw new Error(`the synthetic camera feed could not be generated on this desktop image (ffmpeg exited ${made.exitCode}: ${tailOf(made.stderr ?? made.stdout ?? "")}); give execution.desktop.media.camera.source a .y4m file instead`);
52
- }
53
- camera = { source: "synthetic", file: SANDBOX_CAMERA_PATH };
54
- }
55
- else {
56
- const absolutePath = path.resolve(cwd, media.camera.source);
57
- let bytes;
58
- try {
59
- bytes = await readHostFile(absolutePath);
60
- }
61
- catch (error) {
62
- throw new Error(`execution.desktop.media.camera.source could not be read (${toErrorMessage(error)})`);
63
- }
64
- if (bytes.length > 64 * 1024 * 1024) {
65
- throw new Error(`execution.desktop.media.camera.source is ${bytes.length} bytes; the camera feed is capped at 64 MiB`);
66
- }
67
- await desktop.commands.run(`mkdir -p ${SANDBOX_MEDIA_DIR}`, { requestTimeoutMs, timeoutMs: 15_000 });
68
- const payload = bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
69
- await desktop.files.write(SANDBOX_CAMERA_PATH, payload, { requestTimeoutMs, useOctetStream: true });
70
- camera = { source: "file", file: SANDBOX_CAMERA_PATH };
71
- }
72
- flags.push("--use-fake-device-for-media-stream", `--use-file-for-fake-video-capture=${SANDBOX_CAMERA_PATH}`);
73
- }
74
- if (permission === "granted")
75
- flags.push("--use-fake-ui-for-media-stream");
76
- return { ...(camera === undefined ? {} : { camera }), permission, flags };
77
- }
78
- export const SUBJECT_DIR = "/home/user/subject";
79
- // Remote path for the once-per-run packed local-tree archive; removed by the extract step
80
- // after it unpacks into SUBJECT_DIR.
81
- const LOCAL_TREE_REMOTE_ARCHIVE_PATH = "/home/user/.humanish-source.tar.gz";
82
- const CLONE_TIMEOUT_MS = 5 * 60_000;
83
- const INSTALL_TIMEOUT_MS = 10 * 60_000;
84
- const BUILD_TIMEOUT_MS = 10 * 60_000;
85
- const DEFAULT_READY_TIMEOUT_MS = 180_000;
86
- // Per-step budget for subject.state seed steps; each step's declared (or default) budget is
87
- // also summed into the default sandbox deadline so seeding never eats the session's room.
88
- export const DEFAULT_STATE_STEP_TIMEOUT_MS = 5 * 60_000;
89
- // How much of a failing step's log tail rides the (redacted) error message.
90
- const ERROR_TAIL_CHARS = 2000;
91
- /** Mid-run inbox-surface render cadence (ms). Coarse enough that the per-tick `cat` + file writes stay
92
- * cheap; fine enough that a verification email is visible seconds after the app sends it. */
93
- export const INBOX_SURFACE_CADENCE_MS = 2500;
94
- /**
95
- * The DECLARED preset to record alongside the rendered screen, or undefined when the preset
96
- * rendered faithfully.
97
- *
98
- * `desktopGeometry.screen.verified` compares the FLOORED number with itself, so on its own a
99
- * floored run is indistinguishable from a faithful one: a reader sees requested 500 / verified 500
100
- * and concludes a 500-wide screen was asked for. Recording the declared preset is what makes
101
- * "the preset width did not render" legible in the bundle.
102
- */
103
- export function declaredScreenForRender(preset, presetName, rendered) {
104
- if (preset.width === rendered[0] && preset.height === rendered[1])
105
- return undefined;
106
- return { width: preset.width, height: preset.height, preset: presetName };
107
- }
108
- /** ISO timestamp from an injectable clock (tests freeze `now` for deterministic durationMs). */
109
- function isoNow(now) {
110
- return new Date(now()).toISOString();
111
- }
112
- /** Emit a phase-started event (no ok/durationMs: those belong to the matching completed event). */
113
- /**
114
- * Run a provisioning step and, when it fails with an EXIT CODE, run it once more (#602). A cold
115
- * install of 0.74.0 lost its whole first live study to one transient TLS error inside the
116
- * sandbox's `npm install`; the parallel install twenty seconds later passed, as had the ten
117
- * before it. One retry clears that class. A TIMEOUT is not retried: its budget is already spent,
118
- * and a second wait would double it. The retry runs under its own step name so both logs stay.
119
- */
120
- async function runProvisioningStepWithOneRetry(desktop, args) {
121
- const first = await runDetachedStep(desktop, {
122
- name: args.name,
123
- command: args.command,
124
- cwd: args.cwd,
125
- timeoutMs: args.timeoutMs,
126
- requestTimeoutMs: args.requestTimeoutMs,
127
- ...args.timers
128
- });
129
- if (first.ok || first.timedOut)
130
- return { ...first, attempts: 1 };
131
- const retryStartedAt = args.now();
132
- emitPhaseStarted(args.onPhase, args.now, args.retryPhase, `${args.retryMessage} (first attempt exited ${first.exitCode ?? "null"}; retrying once)`);
133
- const second = await runDetachedStep(desktop, {
134
- name: `${args.name}-retry`,
135
- command: args.command,
136
- cwd: args.cwd,
137
- timeoutMs: args.timeoutMs,
138
- requestTimeoutMs: args.requestTimeoutMs,
139
- ...args.timers
140
- });
141
- emitPhaseCompleted(args.onPhase, args.now, retryStartedAt, args.retryPhase, second.ok, second.ok ? `${args.retryMessage}: succeeded on the second attempt` : `${args.retryMessage}: failed twice`);
142
- return { ...second, attempts: 2, ...(first.exitCode === undefined ? {} : { firstExitCode: first.exitCode }) };
143
- }
144
- function emitPhaseStarted(onPhase, now, phase, message) {
145
- onPhase?.({ at: isoNow(now), type: `cua-lab.subject.${phase}.started`, message });
146
- }
147
- /** Emit the matching phase-completed event: always carries ok and durationMs (>= 0). */
148
- function emitPhaseCompleted(onPhase, now, startedAt, phase, ok, message) {
149
- onPhase?.({
150
- at: isoNow(now),
151
- type: `cua-lab.subject.${phase}.completed`,
152
- ok,
153
- durationMs: Math.max(0, now() - startedAt),
154
- message
155
- });
156
- }
157
- /** Default phase-boundary sink (stderr): one line per event, prefixed with the lane id ONLY
158
- * when laneCount > 1. Single-lane emission is unconditional: total single-lane silence for the
159
- * whole clone/install/build/ready boot is the bug this event stream exists to close.
160
- * Overridable via CuaActorLabHooks.onPhase so deterministic tests capture instead of writing to
161
- * the real stderr. */
162
- export function defaultSubjectPhaseSink(event, ctx) {
163
- const durationSuffix = event.durationMs === undefined ? "" : ` (${event.durationMs}ms)`;
164
- const prefix = ctx.laneCount > 1 ? `humanish cua [${ctx.laneId}]` : "humanish cua";
165
- process.stderr.write(`${prefix}: ${event.message}${durationSuffix}\n`);
166
- }
167
- /**
168
- * Verify the desktop screen geometry IN-SANDBOX (the per-lane device claim is checked, never
169
- * assumed). A parseable mismatch fails closed. Unavailable/unparseable evidence is returned as
170
- * an explicit warning: the lane may still run, but its bundle records only the requested screen
171
- * and never upgrades that request into a verified measurement.
172
- */
173
- export async function inspectDesktopScreenGeometry(args) {
174
- let out = "";
175
- try {
176
- const result = await args.desktop.commands.run("xdpyinfo 2>/dev/null | grep -i dimensions || true", { requestTimeoutMs: args.requestTimeoutMs });
177
- out = (result.stdout ?? "").trim();
178
- }
179
- catch {
180
- return { warning: `Desktop screen geometry could not be measured for lane ${args.laneId}; requested geometry remains unverified.` };
181
- }
182
- const match = out.match(/(\d+)\s*x\s*(\d+)\s*pixels/i);
183
- if (!match) {
184
- return { warning: `Desktop screen geometry could not be parsed for lane ${args.laneId}; requested geometry remains unverified.` };
185
- }
186
- const width = Number(match[1]);
187
- const height = Number(match[2]);
188
- const [expectedWidth, expectedHeight] = args.requestedScreen;
189
- if (width === expectedWidth && height === expectedHeight) {
190
- return { verified: { width, height, source: "xdpyinfo" } };
191
- }
192
- return {
193
- verified: { width, height, source: "xdpyinfo" },
194
- error: `HUMANISH_CUA_LAB_DEVICE_GEOMETRY: lane ${args.laneId} requested a ${expectedWidth}x${expectedHeight} desktop but xdpyinfo reports ${width}x${height} in-sandbox; the per-lane device geometry is unverified (fail-closed).`
195
- };
196
- }
197
- async function findVisibleBrowserWindowId(desktop, requestTimeoutMs, browserFamily, launchIdentity) {
198
- if (browserFamily === "unknown")
199
- return undefined;
200
- // The candidate loop keeps the LAST identity match: with a launch identity the match is
201
- // unique anyway, and without one every family candidate matches, so the newest visible
202
- // window of the launched family wins (the window this lane just opened).
203
- const finder = browserFamily === "firefox"
204
- ? [
205
- "find_firefox_window() {",
206
- " timeout 2s xdotool search --onlyvisible --class 'firefox|Firefox' 2>/dev/null || true",
207
- "}",
208
- "window_id=",
209
- "for _ in $(seq 1 10); do",
210
- " for candidate in $(find_firefox_window); do",
211
- " window_pid=\"$(xdotool getwindowpid \"$candidate\" 2>/dev/null || true)\"",
212
- " if matches_launch_identity \"$window_pid\"; then window_id=\"$candidate\"; fi",
213
- " done",
214
- " if [ -n \"$window_id\" ]; then break; fi",
215
- " sleep 0.5",
216
- "done"
217
- ]
218
- : [
219
- "find_chrome_window() {",
220
- " timeout 2s xdotool search --onlyvisible --class 'google-chrome|Google-chrome|chromium|Chromium|chrome|Chrome' 2>/dev/null || true",
221
- "}",
222
- "window_id=",
223
- "for _ in $(seq 1 10); do",
224
- " for candidate in $(find_chrome_window); do",
225
- " window_pid=\"$(xdotool getwindowpid \"$candidate\" 2>/dev/null || true)\"",
226
- " if matches_launch_identity \"$window_pid\"; then window_id=\"$candidate\"; fi",
227
- " done",
228
- " if [ -n \"$window_id\" ]; then break; fi",
229
- " sleep 0.5",
230
- "done"
231
- ];
232
- const result = await desktop.commands.run([
233
- "set -euo pipefail",
234
- "export DISPLAY=\"${DISPLAY:-:0}\"",
235
- `launch_pid=${shellSingleQuote(launchIdentity?.processId ?? "")}`,
236
- `profile_dir=${shellSingleQuote(launchIdentity?.profileDir ?? "")}`,
237
- "matches_launch_identity() {",
238
- " if [ -z \"$launch_pid\" ] && [ -z \"$profile_dir\" ]; then return 0; fi",
239
- " local current=\"${1:-}\"",
240
- " while [[ \"$current\" =~ ^[0-9]+$ ]] && [ \"$current\" -gt 1 ]; do",
241
- " cmdline=\"$(tr '\\0' ' ' < \"/proc/$current/cmdline\" 2>/dev/null || true)\"",
242
- " if [ -n \"$profile_dir\" ] && [[ \"$cmdline\" == *\"$profile_dir\"* ]]; then return 0; fi",
243
- " if [ \"$current\" = \"$launch_pid\" ]; then return 0; fi",
244
- " current=\"$(ps -o ppid= -p \"$current\" 2>/dev/null | tr -d ' ' || true)\"",
245
- " done",
246
- " return 1",
247
- "}",
248
- ...finder,
249
- "if [ -n \"$window_id\" ]; then printf 'WINDOW_ID=%s\\n' \"$window_id\"; fi"
250
- ].join("\n"), {
251
- requestTimeoutMs,
252
- timeoutMs: 15_000
253
- });
254
- return (result.stdout ?? "").match(/^WINDOW_ID=(\S+)$/m)?.[1];
255
- }
256
- /**
257
- * Build the xdotool command that makes a browser window fill the desktop.
258
- * Exported (pure) for contract tests. A window manager can ignore Chrome's
259
- * --window-size, so xdotool is the robust path: move the window to the origin,
260
- * then size it to the exact desktop resolution so Observer screenshots carry no
261
- * dead margin around the browser.
262
- */
263
- export function buildFillDesktopWindowCommand(windowId, width, height) {
264
- return [
265
- "set -euo pipefail",
266
- `win=${shellSingleQuote(windowId)}`,
267
- `xdotool windowactivate "$win" >/dev/null 2>&1 || true`,
268
- `xdotool windowmove "$win" 0 0 >/dev/null 2>&1 || true`,
269
- `xdotool windowsize "$win" ${width} ${height} >/dev/null 2>&1 || true`,
270
- ].join("\n");
271
- }
272
- /**
273
- * Best-effort initial fill. A contained smaller window remains usable; the capture
274
- * below checks for clipping and refuses an uncorrectable window before the actor runs.
275
- */
276
- async function fillDesktopBrowserWindow(desktop, windowId, resolution, requestTimeoutMs) {
277
- const [width, height] = resolution;
278
- await desktop.commands
279
- .run(buildFillDesktopWindowCommand(windowId, width, height), {
280
- requestTimeoutMs,
281
- timeoutMs: 10_000,
282
- })
283
- .catch(() => undefined);
284
- }
285
- export async function openDesktopBrowserTarget(desktop, targetUrl, requestTimeoutMs, browserPreference,
286
- /** Launch-time flags that make mobile fidelity (#221) hold across every tab: the user agent and
287
- * touch events are browser-wide here, where the CDP holder covers only the launch page. */
288
- extraChromiumFlags = [], environment) {
289
- const requestedBrowser = browserPreference ?? "default";
290
- if (isHttpUrl(targetUrl)) {
291
- const chromiumFlags = [...CHROMIUM_EVIDENCE_HYGIENE_FLAGS, ...extraChromiumFlags].map(shellSingleQuote).join(" ");
292
- const browserLaunchCommand = [
293
- "set -euo pipefail",
294
- `target_url=${shellSingleQuote(targetUrl)}`,
295
- `browser_preference=${shellSingleQuote(requestedBrowser)}`,
296
- "chrome_profile_dir=",
297
- `chrome_preferences_json=${shellSingleQuote(chromiumEvidenceProfilePreferencesJson())}`,
298
- "prepare_chrome_profile() {",
299
- " chrome_profile_dir=\"$(mktemp -d /tmp/humanish-chrome-profile.XXXXXX)\"",
300
- " mkdir -p \"$chrome_profile_dir/Default\"",
301
- " printf '%s\\n' \"$chrome_preferences_json\" > \"$chrome_profile_dir/Default/Preferences\"",
302
- "}",
303
- "launch_browser() {",
304
- " local label=\"$1\"",
305
- " local binary=\"$2\"",
306
- " shift 2",
307
- " if command -v \"$binary\" >/dev/null 2>&1; then",
308
- " nohup \"$binary\" \"$@\" \"$target_url\" >/tmp/humanish-browser-open.log 2>&1 &",
309
- " local launch_pid=$!",
310
- " printf 'HUMANISH_BROWSER_RESOLVED=%s\\n' \"$label\"",
311
- " printf 'HUMANISH_BROWSER_PID=%s\\n' \"$launch_pid\"",
312
- " printf 'HUMANISH_BROWSER_PROFILE_DIR=%s\\n' \"$chrome_profile_dir\"",
313
- " if [[ \"$label\" =~ ^(google-chrome|google-chrome-stable|chromium|chromium-browser)$ ]]; then",
314
- " for _ in $(seq 1 30); do",
315
- " if [ -s \"$chrome_profile_dir/DevToolsActivePort\" ]; then",
316
- " head -n 1 \"$chrome_profile_dir/DevToolsActivePort\" | sed 's/^/HUMANISH_BROWSER_CDP_PORT=/'",
317
- " break",
318
- " fi",
319
- " sleep 0.1",
320
- " done",
321
- " fi",
322
- " return 0",
323
- " fi",
324
- " return 1",
325
- "}",
326
- // Fixed CDP port (not :0/random): each seat has its OWN desktop sandbox, so a known port
327
- // cannot conflict, and it makes the observer's port resolution deterministic. With :0 the
328
- // real port lives only in DevToolsActivePort; when the launch-time capture misses on a cold
329
- // start the observer falls back to 9222 and — being wrong — every CDP read fails for the
330
- // whole run (the lobby-code handoff then never sees the host's /lobby URL). 9222 is already
331
- // the fallback, so making it the actual port aligns launch, capture, and fallback.
332
- `chrome_debug_flags=(--remote-debugging-address=127.0.0.1 --remote-debugging-port=9222 ${chromiumFlags})`,
333
- "open_target() {",
334
- " case \"$browser_preference\" in",
335
- " chrome)",
336
- " prepare_chrome_profile",
337
- " launch_browser google-chrome google-chrome --new-window \"--user-data-dir=$chrome_profile_dir\" \"${chrome_debug_flags[@]}\" && return 0",
338
- " launch_browser google-chrome-stable google-chrome-stable --new-window \"--user-data-dir=$chrome_profile_dir\" \"${chrome_debug_flags[@]}\" && return 0",
339
- " echo 'requested browser chrome was not found' >&2",
340
- " return 127",
341
- " ;;",
342
- " chromium)",
343
- " prepare_chrome_profile",
344
- " launch_browser chromium chromium --new-window \"--user-data-dir=$chrome_profile_dir\" \"${chrome_debug_flags[@]}\" && return 0",
345
- " launch_browser chromium-browser chromium-browser --new-window \"--user-data-dir=$chrome_profile_dir\" \"${chrome_debug_flags[@]}\" && return 0",
346
- " echo 'requested browser chromium was not found' >&2",
347
- " return 127",
348
- " ;;",
349
- " firefox)",
350
- " prepare_chrome_profile",
351
- " launch_browser firefox firefox --new-instance --no-remote --new-window --profile \"$chrome_profile_dir\" && return 0",
352
- " echo 'requested browser firefox was not found' >&2",
353
- " return 127",
354
- " ;;",
355
- " default)",
356
- " prepare_chrome_profile",
357
- " launch_browser google-chrome google-chrome --new-window \"--user-data-dir=$chrome_profile_dir\" \"${chrome_debug_flags[@]}\" && return 0",
358
- " launch_browser google-chrome-stable google-chrome-stable --new-window \"--user-data-dir=$chrome_profile_dir\" \"${chrome_debug_flags[@]}\" && return 0",
359
- " launch_browser chromium chromium --new-window \"--user-data-dir=$chrome_profile_dir\" \"${chrome_debug_flags[@]}\" && return 0",
360
- " launch_browser chromium-browser chromium-browser --new-window \"--user-data-dir=$chrome_profile_dir\" \"${chrome_debug_flags[@]}\" && return 0",
361
- " launch_browser firefox firefox --new-instance --no-remote --new-window --profile \"$chrome_profile_dir\" && return 0",
362
- " launch_browser xdg-open xdg-open && return 0",
363
- " echo 'no browser opener found' >&2",
364
- " return 127",
365
- " ;;",
366
- " esac",
367
- "}",
368
- "open_target"
369
- ].join("\n");
370
- const result = await runDesktopCommandOrThrow(() => desktop.commands.run(browserLaunchCommand, {
371
- requestTimeoutMs,
372
- timeoutMs: 15_000,
373
- ...(environment === undefined ? {} : { envs: { ...environment } }),
374
- }), ({ exitCode, stderrTail }) => new Error(`browser launch failed${exitCode === undefined ? "" : ` with exit ${exitCode}`}: ${stderrTail}`));
375
- if (result.exitCode !== undefined && result.exitCode !== 0) {
376
- throw new Error(`browser launch failed with exit ${result.exitCode}: ${tailOf(result.stderr ?? result.stdout ?? "")}`);
377
- }
378
- const resolved = (result.stdout ?? "").match(/^HUMANISH_BROWSER_RESOLVED=(\S+)$/m)?.[1];
379
- const processId = (result.stdout ?? "").match(/^HUMANISH_BROWSER_PID=(\d+)$/m)?.[1];
380
- const profileDir = (result.stdout ?? "").match(/^HUMANISH_BROWSER_PROFILE_DIR=(\S+)$/m)?.[1];
381
- const cdpPortRaw = (result.stdout ?? "").match(/^HUMANISH_BROWSER_CDP_PORT=(\d+)$/m)?.[1];
382
- const cdpPort = cdpPortRaw === undefined ? undefined : Number(cdpPortRaw);
383
- return {
384
- family: desktopBrowserFamily(resolved ?? requestedBrowser),
385
- ...(processId === undefined || profileDir === undefined
386
- ? {}
387
- : { identity: { processId, profileDir, targetUrl, ...(cdpPort === undefined ? {} : { cdpPort }) } }),
388
- ...(browserPreference === undefined
389
- ? {}
390
- : { evidence: { requested: requestedBrowser, ...(resolved === undefined ? {} : { resolved }) } })
391
- };
392
- }
393
- if (browserPreference === undefined || browserPreference === "default") {
394
- if (desktop.open) {
395
- await desktop.open(targetUrl);
396
- }
397
- else {
398
- await desktop.launch("google-chrome", targetUrl);
399
- }
400
- return {
401
- family: desktop.open ? "unknown" : "chromium",
402
- ...(browserPreference === undefined ? {} : { evidence: { requested: requestedBrowser } })
403
- };
404
- }
405
- const launchTarget = requestedBrowser === "chrome" ? "google-chrome"
406
- : requestedBrowser === "chromium" ? "chromium"
407
- : requestedBrowser === "firefox" ? "firefox"
408
- : "google-chrome";
409
- await desktop.launch(launchTarget, targetUrl);
410
- return {
411
- family: desktopBrowserFamily(launchTarget),
412
- evidence: { requested: requestedBrowser, resolved: launchTarget }
413
- };
414
- }
415
- export function desktopBrowserFamily(value) {
416
- if (value === "firefox")
417
- return "firefox";
418
- if (value === "chrome" || value === "chromium" || value === "google-chrome" || value === "google-chrome-stable" || value === "chromium-browser") {
419
- return "chromium";
420
- }
421
- return "unknown";
422
- }
423
- /**
424
- * The URL / title / page-text / scroll observer behind stopWhen and task criteria. One probe per
425
- * observation, run on the sandbox's python3 (see chrome-cdp-probe.ts for why not node: #514).
426
- *
427
- * "active": follow the participant to whatever tab they are driving now — never pin the state
428
- * observer to the launch tab (a verification link that opened in a NEW tab left a pinned observer
429
- * reading the old tab forever).
430
- *
431
- * `onUnavailable` fires ONCE, on the first probe that could not read the page, with the reason.
432
- * The observer still degrades to `{}` for the loop; the callback is how a lane says out loud that
433
- * url/text criteria are not being measured, instead of letting the funnel report 0/N (#514).
434
- */
435
- export function makeChromeBrowserStateObserver(desktop, requestTimeoutMs, endpoint, targetId, onUnavailable,
436
- /**
437
- * Mobile emulation on later tabs (#623): the holder attaches to every page target Chrome opens
438
- * after the launch page, so a tab the participant opens later should lay out at the phone width
439
- * too. The first observation on each new target reads that page's OWN report; a target that
440
- * reports the requested width is recorded through `onCovered`, and one that does not (or cannot
441
- * be read) fires `onDrift` once, so a phone-labelled lane that spent part of its session at
442
- * desktop layout says so with the number the page gave.
443
- */
444
- drift) {
445
- let reported = false;
446
- let drifted = false;
447
- const checkedTargets = new Set(drift === undefined ? [] : [drift.emulatedTargetId]);
448
- const unavailable = (reason) => {
449
- if (!reported) {
450
- reported = true;
451
- onUnavailable?.(reason);
452
- }
453
- return {};
454
- };
455
- const checkLaterTarget = async (newTargetId) => {
456
- if (drift === undefined || checkedTargets.has(newTargetId))
457
- return;
458
- checkedTargets.add(newTargetId);
459
- const read = await desktop.commands.run(chromeCdpProbeCommand({ ...endpoint, targetId: newTargetId, prefer: "pinned", mode: "fidelity" }), { requestTimeoutMs, timeoutMs: 5_000 });
460
- const fidelity = read.exitCode !== undefined && read.exitCode !== 0 ? undefined : parseChromeCdpProbeOutput(read.stdout).fidelity;
461
- if (fidelity !== undefined && fidelity.innerWidth === drift.expectedWidth) {
462
- drift.onCovered?.(newTargetId, { innerWidth: fidelity.innerWidth, devicePixelRatio: fidelity.devicePixelRatio, maxTouchPoints: fidelity.maxTouchPoints });
463
- if (drift.expectTouch === true && fidelity.maxTouchPoints === 0 && !drifted) {
464
- // The viewport followed; touch did not (yet): the holder reloads a later tab once after its
465
- // first navigation commits, and this observation may have landed before that reload.
466
- drifted = true;
467
- drift.onDrift(`a later page target reports the ${fidelity.innerWidth} px viewport but navigator.maxTouchPoints 0 on its first observation; touch reaches a document only when it loads under the override`);
468
- }
469
- return;
470
- }
471
- if (drifted)
472
- return;
473
- drifted = true;
474
- drift.onDrift(fidelity === undefined
475
- ? "the participant drove a page target other than the emulated launch tab and that page's own read-back could not be taken; whether it laid out at the phone width is not known"
476
- : `the participant drove a page target other than the emulated launch tab and that page reports a ${fidelity.innerWidth} px viewport where ${drift.expectedWidth} px was requested (DPR ${fidelity.devicePixelRatio}); the mobile user agent and touch events are browser-wide, the viewport override was not re-applied to it`);
477
- };
478
- return async () => {
479
- const result = await desktop.commands.run(chromeCdpProbeCommand({ ...endpoint, ...(targetId === undefined ? {} : { targetId }), prefer: "active", mode: "state" }), { requestTimeoutMs, timeoutMs: 5_000 });
480
- if (result.exitCode !== undefined && result.exitCode !== 0) {
481
- return unavailable(`probe exited ${result.exitCode}: ${tailOf(result.stderr ?? result.stdout ?? "")}`);
482
- }
483
- const parsed = parseChromeCdpProbeOutput(result.stdout);
484
- if (parsed.unavailable !== undefined)
485
- return unavailable(parsed.unavailable);
486
- if (parsed.targetId !== undefined)
487
- await checkLaterTarget(parsed.targetId);
488
- return {
489
- ...(parsed.url === undefined ? {} : { url: parsed.url }),
490
- ...(parsed.title === undefined ? {} : { title: parsed.title }),
491
- ...(parsed.text === undefined ? {} : { text: parsed.text }),
492
- ...(parsed.scrollY === undefined ? {} : { scrollY: parsed.scrollY })
493
- };
494
- };
495
- }
496
- /**
497
- * Read the running browser's actual outer-window bounds and CSS layout viewport through the
498
- * already-enabled local Chrome DevTools endpoint. The returned values come from `window.*` in
499
- * the target page; requested E2B resolution is deliberately not an input to this function.
500
- * Missing channels report their reason via `onUnavailable`, so the geometry warning can name
501
- * the cause (a dead CDP endpoint, no python3) instead of only the symptom. Returns `undefined`
502
- * only when neither channel could be measured.
503
- * Outer bounds and CSS dimensions are independent channels: a background page can report zero
504
- * outer dimensions while still reporting a CSS viewport. Final captures follow the active tab;
505
- * launch captures and emulation attribution keep the pinned target.
506
- */
507
- export function makeChromeDesktopGeometryObserver(desktop, requestTimeoutMs, endpoint, targetId, onUnavailable, prefer = "pinned") {
508
- return async () => {
509
- const result = await desktop.commands.run(chromeCdpProbeCommand({ ...endpoint, ...(targetId === undefined ? {} : { targetId }), prefer, mode: "geometry" }), { requestTimeoutMs, timeoutMs: 5_000 });
510
- if (result.exitCode !== undefined && result.exitCode !== 0) {
511
- onUnavailable?.(`probe exited ${result.exitCode}: ${tailOf(result.stderr ?? result.stdout ?? "")}`);
512
- return undefined;
513
- }
514
- const parsed = parseChromeCdpProbeOutput(result.stdout);
515
- if (parsed.unavailable !== undefined) {
516
- onUnavailable?.(parsed.unavailable);
517
- return undefined;
518
- }
519
- const browserWindow = isMeasuredRect(parsed.browserWindow) ? { ...parsed.browserWindow, source: "cdp" } : undefined;
520
- const viewport = isMeasuredViewport(parsed.viewport) ? { ...parsed.viewport, source: "cdp" } : undefined;
521
- if (browserWindow === undefined && viewport === undefined) {
522
- onUnavailable?.("the page reported no usable window or viewport dimensions");
523
- return undefined;
524
- }
525
- if (browserWindow === undefined)
526
- onUnavailable?.("the page reported no usable outer-window dimensions");
527
- if (viewport === undefined)
528
- onUnavailable?.("the page reported no usable CSS viewport dimensions");
529
- return {
530
- ...(browserWindow === undefined ? {} : { browserWindow }),
531
- ...(viewport === undefined ? {} : { viewport }),
532
- ...(parsed.targetId === undefined ? {} : { targetId: parsed.targetId })
533
- };
534
- };
535
- }
536
- /** The user agent a mobile-emulated lane presents unless the lab sets its own. */
537
- export const DEFAULT_MOBILE_USER_AGENT = "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1";
538
- /**
539
- * Apply mobile emulation (#221) to the lane's launch page and read back what the page reports.
540
- * Fails CLOSED: a request that cannot be applied throws, because a desktop run labelled mobile is
541
- * the over-trust this feature exists to prevent. A read-back that cannot be taken is a warning
542
- * (the emulation was applied; only the proof is missing).
543
- */
544
- export async function applyMobileEmulation(desktop, requestTimeoutMs, endpoint, targetId, request) {
545
- const command = (mode) => chromeCdpProbeCommand({ ...endpoint, ...(targetId === undefined ? {} : { targetId }), prefer: "pinned", mode, emulation: request });
546
- const read = async () => {
547
- const result = await desktop.commands.run(command("fidelity"), { requestTimeoutMs, timeoutMs: 15_000 });
548
- if (result.exitCode !== undefined && result.exitCode !== 0) {
549
- return { unavailable: `probe exited ${result.exitCode}: ${tailOf(result.stderr ?? result.stdout ?? "")}` };
550
- }
551
- return parseChromeCdpProbeOutput(result.stdout);
552
- };
553
- // The UA / touch / DPR overrides are bound to the DevTools session that set them and lapse the
554
- // moment its socket closes (measured: only the viewport width survived a one-shot apply). So the
555
- // applier stays attached for the lane's whole life as a detached process; the sandbox teardown
556
- // ends it. Its first stdout line says what was applied.
557
- const holderName = `mobile-emulation-${Date.now().toString(36)}`;
558
- await startDetachedProcess(desktop, { name: holderName, command: command("hold"), requestTimeoutMs });
559
- let announced;
560
- for (let attempt = 0; attempt < 30 && announced === undefined; attempt += 1) {
561
- await new Promise((resolve) => setTimeout(resolve, 500));
562
- const log = await readDetachedLog(desktop, holderName, requestTimeoutMs).catch(() => "");
563
- const line = log.split("\n").find((candidate) => candidate.trim().startsWith("{"));
564
- if (line !== undefined)
565
- announced = parseChromeCdpProbeOutput(line);
566
- }
567
- if (announced === undefined) {
568
- throw new Error("mobile emulation could not be applied: the in-sandbox applier printed nothing within 15 s");
569
- }
570
- if (announced.unavailable !== undefined) {
571
- throw new Error(`mobile emulation could not be applied (${announced.unavailable}); applied before failing: ${(announced.applied ?? []).join(", ") || "nothing"}`);
572
- }
573
- const applied = announced;
574
- // Viewport/touch read-back proves context settings, not gesture equivalence. Two hosted
575
- // replicas and a native-X conversion-toggle control reproduced reset click counts (#676).
576
- const warnings = request.touch
577
- ? ["Mobile emulation uses desktop pointer-to-touch conversion, which can differ for repeated taps. Confirm gesture failures with direct or native touch input before attributing them to the app."]
578
- : [];
579
- // The reload inside the applier takes a moment; the read-back is retried until the page reports
580
- // the requested viewport and user agent, so a slow page does not read as "no proof".
581
- let readBack = await read();
582
- for (let attempt = 0; attempt < 20 && (readBack.fidelity === undefined || readBack.fidelity.innerWidth !== request.width || !readBack.fidelity.userAgent.includes(request.userAgent.slice(0, 24))); attempt += 1) {
583
- await new Promise((resolve) => setTimeout(resolve, 500));
584
- readBack = await read();
585
- }
586
- const fidelityRead = readBack;
587
- const requested = {
588
- width: request.width,
589
- height: request.height,
590
- deviceScaleFactor: request.deviceScaleFactor,
591
- touch: request.touch,
592
- userAgent: request.userAgent
593
- };
594
- const emulatedTargetId = applied.targetId ?? fidelityRead.targetId;
595
- if (fidelityRead.fidelity === undefined) {
596
- warnings.push(`Mobile emulation was applied but the page's own report could not be read (${fidelityRead.unavailable ?? "no fidelity read"}); desktopGeometry.fidelity carries the request without a resolved block.`);
597
- return { fidelity: { tier: "mobile-emulated", requested, applied: applied.applied ?? [] }, warnings, holderName, ...(emulatedTargetId === undefined ? {} : { targetId: emulatedTargetId }) };
598
- }
599
- const resolved = { ...fidelityRead.fidelity, source: "cdp" };
600
- if (resolved.innerWidth !== request.width) {
601
- warnings.push(`Mobile emulation requested a ${request.width} px viewport; the page reports ${resolved.innerWidth} px.`);
602
- }
603
- if (resolved.devicePixelRatio !== request.deviceScaleFactor) {
604
- warnings.push(`Mobile emulation requested devicePixelRatio ${request.deviceScaleFactor}; the page reports ${resolved.devicePixelRatio}.`);
605
- }
606
- if (request.touch && resolved.maxTouchPoints === 0) {
607
- warnings.push("Mobile emulation requested touch; the page reports navigator.maxTouchPoints 0.");
608
- }
609
- if (!resolved.userAgent.includes("Mobile") && !resolved.userAgent.includes("Android") && !resolved.userAgent.includes("iPhone")) {
610
- warnings.push("Mobile emulation requested a mobile user agent; the page reports a desktop one.");
611
- }
612
- return { fidelity: { tier: "mobile-emulated", requested, applied: applied.applied ?? [], resolved }, warnings, holderName, ...(emulatedTargetId === undefined ? {} : { targetId: emulatedTargetId }) };
613
- }
614
- function isMeasuredRect(value) {
615
- if (!value || typeof value !== "object")
616
- return false;
617
- const record = value;
618
- return Number.isFinite(record.x)
619
- && Number.isFinite(record.y)
620
- && isPositiveMeasurement(record.width)
621
- && isPositiveMeasurement(record.height);
622
- }
623
- function isMeasuredViewport(value) {
624
- if (!value || typeof value !== "object")
625
- return false;
626
- const record = value;
627
- return isPositiveMeasurement(record.width)
628
- && isPositiveMeasurement(record.height)
629
- && isPositiveMeasurement(record.deviceScaleFactor);
630
- }
631
- function isPositiveMeasurement(value) {
632
- return typeof value === "number" && Number.isFinite(value) && value > 0;
633
- }
634
- async function measureBrowserWindowWithXwininfo(desktop, windowId, requestTimeoutMs) {
635
- const result = await desktop.commands.run([
636
- "set -euo pipefail",
637
- `win=${shellSingleQuote(windowId)}`,
638
- // Older xdotool builds translate parent-relative offsets twice. With window
639
- // decorations that falsely reports a visible client as clipped, triggering
640
- // fullscreen and hiding the participant's address bar. Read root-relative
641
- // client coordinates directly; never substitute emulated CDP outer bounds.
642
- "LC_ALL=C xwininfo -id \"$win\" -stats 2>/dev/null"
643
- ].join("\n"), { requestTimeoutMs, timeoutMs: 5_000 });
644
- if (result.exitCode !== undefined && result.exitCode !== 0)
645
- return undefined;
646
- return parseXwininfoGeometry(result.stdout ?? "");
647
- }
648
- /** Root-relative physical client bounds from xwininfo's C-locale stats. */
649
- export function parseXwininfoGeometry(output) {
650
- const read = (label) => {
651
- const matches = [...output.matchAll(new RegExp(`^\\s*${label}:\\s*(-?\\d+)\\s*$`, "gm"))];
652
- if (matches.length !== 1)
653
- return undefined;
654
- const value = Number(matches[0][1]);
655
- return Number.isSafeInteger(value) ? value : undefined;
656
- };
657
- const x = read("Absolute upper-left X");
658
- const y = read("Absolute upper-left Y");
659
- const width = read("Width");
660
- const height = read("Height");
661
- const mapStates = [...output.matchAll(/^\s*Map State:\s*(\S+)\s*$/gm)];
662
- if (mapStates.length !== 1 || mapStates[0][1] !== "IsViewable")
663
- return undefined;
664
- if (x === undefined || y === undefined || width === undefined || height === undefined || width <= 0 || height <= 0) {
665
- return undefined;
666
- }
667
- return { x, y, width, height, source: "xwininfo" };
668
- }
669
- /** Physical X client bounds, never the page's emulated window.outerWidth/Height. */
670
- function isBrowserWindowContained(bounds, [width, height]) {
671
- return bounds.x >= 0 && bounds.y >= 0
672
- && bounds.x + bounds.width <= width && bounds.y + bounds.height <= height;
673
- }
674
- /** Bounded repair. Resizing can clear a window-manager maximize state and move the
675
- * client origin as decorations return, so remeasure before a second adjustment. */
676
- async function fitBrowserWindowWithinDesktop(desktop, windowId, resolution, requestTimeoutMs) {
677
- const run = (command) => desktop.commands.run([
678
- "set -euo pipefail",
679
- `win=${shellSingleQuote(windowId)}`,
680
- command
681
- ].join("\n"), { requestTimeoutMs, timeoutMs: 5_000 }).catch(() => undefined);
682
- await run('xdotool windowmove "$win" 0 0');
683
- await desktop.wait(250).catch(() => undefined);
684
- const moved = await measureBrowserWindowWithXwininfo(desktop, windowId, requestTimeoutMs).catch(() => undefined);
685
- if (moved === undefined)
686
- return moved;
687
- let resized = moved;
688
- // Resizing alone cannot fix an offscreen client origin. The window manager
689
- // can also center a minimum-width client at a negative x on a narrow screen.
690
- for (let attempt = 0; attempt < 2; attempt += 1) {
691
- if (isBrowserWindowContained(resized, resolution))
692
- return resized;
693
- const width = resolution[0] - resized.x;
694
- const height = resolution[1] - resized.y;
695
- if (resized.x < 0 || resized.y < 0 || width <= 0 || height <= 0)
696
- break;
697
- await run(`xdotool windowsize "$win" ${width} ${height}`);
698
- await desktop.wait(250).catch(() => undefined);
699
- const measured = await measureBrowserWindowWithXwininfo(desktop, windowId, requestTimeoutMs).catch(() => undefined);
700
- if (measured === undefined)
701
- return measured;
702
- resized = measured;
703
- }
704
- if (resized === undefined || isBrowserWindowContained(resized, resolution))
705
- return resized;
706
- // Chrome's minimum client width can equal the whole desktop. Window-manager
707
- // borders then make a decorated window impossible to contain, even after a
708
- // successful move/resize. Request fullscreen once and prove the physical result.
709
- // xprop/xdotool ship with the desktop template; wmctrl is not required.
710
- // Check state first so the fullscreen shortcut cannot toggle an existing state off.
711
- await run([
712
- 'state=$(xprop -id "$win" _NET_WM_STATE)',
713
- 'case "$state" in',
714
- ' *_NET_WM_STATE_FULLSCREEN*) ;;',
715
- ' *) xdotool windowactivate --sync "$win"; xdotool key --clearmodifiers F11 ;;',
716
- 'esac'
717
- ].join("\n"));
718
- // The fullscreen animation may report its new origin before its final width.
719
- // Give the window manager a bounded settling window, keeping missing reads unverified.
720
- for (let attempt = 0; attempt < 4; attempt += 1) {
721
- await desktop.wait(250).catch(() => undefined);
722
- const measured = await measureBrowserWindowWithXwininfo(desktop, windowId, requestTimeoutMs).catch(() => undefined);
723
- if (measured === undefined || isBrowserWindowContained(measured, resolution))
724
- return measured;
725
- resized = measured;
726
- }
727
- return resized;
728
- }
729
- /** Shared hosted-browser geometry capture used by per-lane and sequential shared-world routes. */
730
- export async function captureDesktopBrowserGeometry(args) {
731
- const warnings = [];
732
- let browserWindowId = args.browserWindowId;
733
- if (browserWindowId === undefined && args.browserFamily !== "unknown") {
734
- browserWindowId = await findVisibleBrowserWindowId(args.desktop, args.requestTimeoutMs, args.browserFamily, args.launchIdentity).catch((error) => {
735
- warnings.push(`Browser window lookup failed for lane ${args.laneId}: ${redactText(toErrorMessage(error))}`);
736
- return undefined;
737
- });
738
- }
739
- let physicalWindow;
740
- if (browserWindowId !== undefined) {
741
- if (args.resize !== false) {
742
- await fillDesktopBrowserWindow(args.desktop, browserWindowId, args.requestedScreen, args.requestTimeoutMs);
743
- // Let the window manager apply the resize before querying both X and page layout geometry.
744
- await args.desktop.wait(250).catch(() => undefined);
745
- }
746
- physicalWindow = await measureBrowserWindowWithXwininfo(args.desktop, browserWindowId, args.requestTimeoutMs)
747
- .catch(() => undefined);
748
- }
749
- else {
750
- warnings.push(`Browser window bounds could not be measured for lane ${args.laneId}; the live stream will use the full desktop.`);
751
- }
752
- let unusable;
753
- if (physicalWindow !== undefined && !isBrowserWindowContained(physicalWindow, args.requestedScreen)) {
754
- const before = physicalWindow;
755
- if (args.resize !== false && browserWindowId !== undefined) {
756
- physicalWindow = await fitBrowserWindowWithinDesktop(args.desktop, browserWindowId, args.requestedScreen, args.requestTimeoutMs);
757
- if (physicalWindow === undefined) {
758
- // Keep the last measured bad state; a missing observation cannot prove a successful fix.
759
- physicalWindow = before;
760
- unusable = `Physical browser containment could not be verified after correction for lane ${args.laneId}; the last measured window was clipped.`;
761
- }
762
- else if (isBrowserWindowContained(physicalWindow, args.requestedScreen)) {
763
- warnings.push(`Browser window clipping corrected for lane ${args.laneId}; physical bounds are ${physicalWindow.width}x${physicalWindow.height} at (${physicalWindow.x}, ${physicalWindow.y}).`);
764
- }
765
- }
766
- if (unusable === undefined && !isBrowserWindowContained(physicalWindow, args.requestedScreen)) {
767
- unusable = `Browser window is outside the captured ${args.requestedScreen[0]}x${args.requestedScreen[1]} desktop for lane ${args.laneId}: physical bounds ${physicalWindow.width}x${physicalWindow.height} at (${physicalWindow.x}, ${physicalWindow.y}), right=${physicalWindow.x + physicalWindow.width}, bottom=${physicalWindow.y + physicalWindow.height}.`;
768
- }
769
- if (unusable !== undefined)
770
- warnings.push(unusable);
771
- }
772
- if (physicalWindow === undefined) {
773
- warnings.push(`Physical browser containment is unverified for lane ${args.laneId}; X window bounds could not be measured. Page-reported outer dimensions can be emulated and do not prove physical visibility.`);
774
- }
775
- let cdpUnavailable;
776
- const chromeGeometry = args.browserFamily === "chromium"
777
- ? await makeChromeDesktopGeometryObserver(args.desktop, args.requestTimeoutMs, {
778
- ...(args.launchIdentity?.cdpPort === undefined ? {} : { cdpPort: args.launchIdentity.cdpPort }),
779
- ...(args.launchIdentity?.profileDir === undefined ? {} : { profileDir: args.launchIdentity.profileDir }),
780
- targetUrl: args.targetUrl
781
- }, args.browserTargetId, (reason) => {
782
- cdpUnavailable = reason;
783
- }, args.pagePreference ?? "pinned")().catch((error) => {
784
- cdpUnavailable = toErrorMessage(error);
785
- return undefined;
786
- })
787
- : undefined;
788
- const browserWindow = physicalWindow ?? chromeGeometry?.browserWindow;
789
- const viewport = chromeGeometry?.viewport;
790
- // The fill check reads the X window when it was measured: under mobile emulation (#221) the
791
- // page's window.outerWidth reports the EMULATED screen (414), which is not a fill failure.
792
- const fillBounds = physicalWindow;
793
- if (!browserWindow) {
794
- warnings.push(`Browser outer bounds could not be measured for lane ${args.laneId}.`);
795
- }
796
- else if (unusable === undefined && fillBounds !== undefined && (fillBounds.x !== 0 || fillBounds.y !== 0 || fillBounds.width !== args.requestedScreen[0] || fillBounds.height !== args.requestedScreen[1])) {
797
- warnings.push(`Browser window fill did not reach the requested ${args.requestedScreen[0]}x${args.requestedScreen[1]} screen for lane ${args.laneId}; measured physical bounds are ${fillBounds.width}x${fillBounds.height} at (${fillBounds.x}, ${fillBounds.y}).`);
798
- }
799
- if (!viewport) {
800
- // Name the cause, not only the symptom: the same dead DevTools channel that loses the viewport
801
- // loses every url/text observation, and a reader of the bundle should learn that here (#514).
802
- const cause = cdpUnavailable === undefined ? "" : ` DevTools probe: ${redactText(cdpUnavailable)}.`;
803
- warnings.push(args.browserFamily === "firefox"
804
- ? `Browser CSS viewport measurement is unavailable for Firefox on lane ${args.laneId}; stream.viewport is omitted instead of reading a different browser's CDP endpoint.`
805
- : `Browser CSS viewport could not be measured for lane ${args.laneId}; stream.viewport is omitted instead of copying the requested screen resolution.${cause}`);
806
- }
807
- return {
808
- ...(unusable === undefined ? {} : { unusable }),
809
- ...(browserWindowId === undefined ? {} : { browserWindowId }),
810
- ...(chromeGeometry?.targetId === undefined ? {} : { browserTargetId: chromeGeometry.targetId }),
811
- ...(browserWindow === undefined ? {} : { browserWindow }),
812
- ...(viewport === undefined ? {} : { viewport }),
813
- warnings
814
- };
815
- }
816
- function shellSingleQuote(value) {
817
- return `'${value.replace(/'/g, "'\\''")}'`;
818
- }
819
- /**
820
- * Prepare a CLI study's runtime and, only when declared, its product (#495, #515).
821
- *
822
- * The install runs UNKEYED and before the session starts, for the same reason the clone route
823
- * provisions its subject first: what is being studied begins when the participant looks at the
824
- * screen. Omitting install deliberately studies product installation; Node/npm remain a
825
- * harness prerequisite so the participant can follow the product's public npm instructions.
826
- */
827
- export async function provisionDesktopCli(desktop, args) {
828
- const install = args.install;
829
- const now = () => Date.now();
830
- if (install === undefined || needsNodeRuntime([install])) {
831
- const startedAt = now();
832
- emitPhaseStarted(args.onPhase, now, "runtime", "providing Node/npm for the desktop CLI study");
833
- const bootstrap = await runDetachedStep(desktop, {
834
- name: "desktop-cli-runtime-node",
835
- command: TERMINAL_NODE_BOOTSTRAP_COMMAND,
836
- cwd: "/home/user",
837
- timeoutMs: INSTALL_TIMEOUT_MS,
838
- requestTimeoutMs: args.requestTimeoutMs
839
- });
840
- emitPhaseCompleted(args.onPhase, now, startedAt, "runtime", bootstrap.ok, bootstrap.ok
841
- ? "Node runtime ready"
842
- : "Node runtime bootstrap failed");
843
- if (!bootstrap.ok) {
844
- throw new Error(`desktop-cli runtime bootstrap failed for "${args.product}"`);
845
- }
846
- }
847
- if (install === undefined)
848
- return;
849
- const startedAt = now();
850
- emitPhaseStarted(args.onPhase, now, "install", `installing ${args.product} on the desktop`);
851
- const result = await runDetachedStep(desktop, {
852
- name: "desktop-cli-install",
853
- command: install,
854
- cwd: "/home/user",
855
- timeoutMs: INSTALL_TIMEOUT_MS,
856
- requestTimeoutMs: args.requestTimeoutMs
857
- });
858
- emitPhaseCompleted(args.onPhase, now, startedAt, "install", result.ok, result.ok
859
- ? `${args.product} installed`
860
- : `installing ${args.product} failed`);
861
- if (!result.ok) {
862
- // Fail closed: a participant handed a desktop where the product is not installed would produce
863
- // a transcript about a missing command, and that finding belongs to the harness, not the tool.
864
- // The tail rides along, scrubbed before truncation like every other provisioning failure — a
865
- // bare "install failed" is unactionable to whoever wrote the command.
866
- throw new Error(args.scrub(`desktop-cli install failed for "${args.product}" (${result.timedOut ? "timed out" : `exit ${result.exitCode ?? "?"}`}): ${tailOf(args.scrub(result.logTail))}`));
867
- }
868
- }
869
- /**
870
- * Open a terminal window on the desktop.
871
- *
872
- * The stock template is XFCE and ships xfce4-terminal (also aliased x-terminal-emulator), verified
873
- * live before this route was built. `x-terminal-emulator` is tried first so a template that swaps
874
- * the emulator still works; a desktop with neither is a template problem and fails closed rather
875
- * than handing a participant an empty screen and calling it a study.
876
- */
877
- export async function openDesktopTerminal(desktop, requestTimeoutMs, workdir) {
878
- const dir = workdir ?? "/home/user";
879
- const result = await runDetachedStep(desktop, {
880
- name: "desktop-cli-terminal",
881
- command: [
882
- "for candidate in x-terminal-emulator xfce4-terminal gnome-terminal konsole xterm; do",
883
- ' if command -v "$candidate" >/dev/null 2>&1; then',
884
- // LANG is set on the terminal we open, not globally: the stock image declares no locale, and
885
- // a study that measures our own mojibake against an unconfigured template would be measuring
886
- // the template. The PRODUCT-side fix (an ASCII fallback when the locale is not UTF-8) is in
887
- // src/terminal-encoding.ts, and it is the one that matters for real users.
888
- ` (cd ${shellSingleQuote(dir)} 2>/dev/null || cd /home/user; DISPLAY=:0 LANG=C.UTF-8 LC_ALL=C.UTF-8 HUMANISH_STUDY_PARTICIPANT=1 nohup "$candidate" >/dev/null 2>&1 &)`,
889
- " sleep 3",
890
- ' echo "humanish: opened $candidate"',
891
- " exit 0",
892
- " fi",
893
- "done",
894
- "echo 'humanish: no terminal emulator on this desktop template' >&2",
895
- "exit 1"
896
- ].join("\n"),
897
- cwd: "/home/user",
898
- timeoutMs: 60_000,
899
- requestTimeoutMs
900
- });
901
- if (!result.ok) {
902
- throw new Error("desktop-cli lane could not open a terminal on this desktop template");
903
- }
904
- }
905
- export async function startDesktopStream(desktop, browserWindowId) {
906
- if (!browserWindowId) {
907
- await desktop.stream.start({ requireAuth: true });
908
- return;
909
- }
910
- try {
911
- await desktop.stream.start({ requireAuth: true, windowId: browserWindowId });
912
- }
913
- catch {
914
- await desktop.stream.start({ requireAuth: true });
915
- }
916
- }
917
- /**
918
- * Shared post-populate provisioning pipeline (clone AND local-tree routes): (install) ->
919
- * state(before-build) -> (build) -> state(before-start) -> detached start -> readiness probe ->
920
- * state(after-ready). Both provisioning routes populate SUBJECT_DIR by different means (git
921
- * clone vs. upload+extract) and then run this identical pipeline unchanged.
922
- *
923
- * State steps run through the same detached primitive as serve steps (author-trusted, the
924
- * "serve commands are author-trusted" corollary) under the reserved `subject-state-<name>`
925
- * label prefix, so a step name can never collide with subject-clone/subject-extract/install/
926
- * build/start. after-ready steps complete BEFORE the caller opens the browser: the actor never
927
- * drives a half-seeded subject and seeding never eats the session budget.
928
- */
929
- async function runSubjectServePipeline(desktop, args) {
930
- const timers = {
931
- ...(args.now === undefined ? {} : { now: args.now }),
932
- ...(args.sleep === undefined ? {} : { sleep: args.sleep })
933
- };
934
- const now = args.now ?? Date.now;
935
- const refresh = args.onPhaseComplete ?? (() => Promise.resolve());
936
- const stateSteps = args.state?.seed ?? [];
937
- const runStateSteps = async (when) => {
938
- const steps = stateSteps.filter((step) => (step.when ?? "before-start") === when);
939
- if (steps.length === 0) {
940
- // No declared steps for this group: no boundary to report (avoids empty-group noise on
941
- // every run, since before-build/before-start/after-ready are always called).
942
- return;
943
- }
944
- const groupStartedAt = now();
945
- emitPhaseStarted(args.onPhase, now, `state.${when}`, `running subject state seed steps (${when})`);
946
- for (const step of steps) {
947
- const stepTimeoutMs = step.timeoutMs ?? DEFAULT_STATE_STEP_TIMEOUT_MS;
948
- const startedAt = now();
949
- const result = await runDetachedStep(desktop, {
950
- name: `subject-state-${step.name}`,
951
- command: step.command,
952
- cwd: SUBJECT_DIR,
953
- timeoutMs: stepTimeoutMs,
954
- requestTimeoutMs: args.requestTimeoutMs,
955
- ...timers
956
- });
957
- args.onStateStep?.({
958
- name: step.name,
959
- when,
960
- // Digest only (sha256-16): the command text never persists: the lab YAML in the
961
- // consumer's repo is the plaintext source of truth.
962
- commandDigest: commandDigestOf(step.command),
963
- ok: result.ok,
964
- ...(result.exitCode === undefined ? {} : { exitCode: result.exitCode }),
965
- ...(result.timedOut ? { timedOut: true } : {}),
966
- durationMs: Math.max(0, now() - startedAt)
967
- });
968
- if (!result.ok) {
969
- emitPhaseCompleted(args.onPhase, now, groupStartedAt, `state.${when}`, false, `subject state seed steps failed (${when})`);
970
- // Fail closed with the existing scrub-before-truncate tail chain: literal scrub of
971
- // every provisioned value PRE-truncation, then pattern redaction + cap in tailOf.
972
- throw new Error(`subject state step "${step.name}" ${result.timedOut ? `timed out after ${stepTimeoutMs}ms` : `failed (exit ${result.exitCode})`}: ${tailOf(args.scrub(result.logTail))}`);
973
- }
974
- }
975
- emitPhaseCompleted(args.onPhase, now, groupStartedAt, `state.${when}`, true, `subject state seed steps complete (${when})`);
976
- };
977
- // Provide the runtime the pipeline needs before running it (#371). The stock desktop template
978
- // ships python3 and curl but no Node, so an `npm install` here used to die at exit 127 after the
979
- // sandbox was already paid for. Probe-first, so a template that ships its own Node pays nothing.
980
- const serveCommands = [args.serve.install, args.serve.build, args.serve.start];
981
- if (needsNodeRuntime(serveCommands)) {
982
- const runtimeStartedAt = now();
983
- emitPhaseStarted(args.onPhase, now, "runtime", "providing the Node runtime the serve pipeline needs");
984
- const bootstrap = await runProvisioningStepWithOneRetry(desktop, {
985
- name: "subject-runtime-node",
986
- command: nodeBootstrapCommand(),
987
- cwd: SUBJECT_DIR,
988
- timeoutMs: args.serve.installTimeoutMs ?? INSTALL_TIMEOUT_MS,
989
- requestTimeoutMs: args.requestTimeoutMs,
990
- timers,
991
- retryPhase: "runtime-retry",
992
- retryMessage: "Node runtime bootstrap",
993
- onPhase: args.onPhase,
994
- now
995
- });
996
- let ok = bootstrap.ok;
997
- const corepack = ok ? corepackCommandFor(serveCommands) : undefined;
998
- if (corepack) {
999
- const pm = await runDetachedStep(desktop, {
1000
- name: "subject-runtime-pm",
1001
- command: corepack,
1002
- cwd: SUBJECT_DIR,
1003
- timeoutMs: args.serve.installTimeoutMs ?? INSTALL_TIMEOUT_MS,
1004
- requestTimeoutMs: args.requestTimeoutMs,
1005
- ...timers
1006
- });
1007
- ok = pm.ok;
1008
- }
1009
- emitPhaseCompleted(args.onPhase, now, runtimeStartedAt, "runtime", ok, ok ? "Node runtime ready" : "could not provide a Node runtime");
1010
- if (!ok) {
1011
- throw new Error(`the subject's serve pipeline needs a Node runtime and this desktop template has none, and bootstrapping one failed${bootstrap.attempts === 2 ? " twice" : ""}: ${tailOf(args.scrub(bootstrap.logTail))}. Use execution.desktop.template with an image that ships Node, or change serve.install to a runtime the template provides.`);
1012
- }
1013
- }
1014
- if (args.serve.install) {
1015
- const installStartedAt = now();
1016
- emitPhaseStarted(args.onPhase, now, "install", "installing subject dependencies");
1017
- const install = await runProvisioningStepWithOneRetry(desktop, {
1018
- name: "subject-install",
1019
- command: args.serve.install,
1020
- cwd: SUBJECT_DIR,
1021
- timeoutMs: args.serve.installTimeoutMs ?? INSTALL_TIMEOUT_MS,
1022
- requestTimeoutMs: args.requestTimeoutMs,
1023
- timers,
1024
- retryPhase: "install-retry",
1025
- retryMessage: "subject install",
1026
- onPhase: args.onPhase,
1027
- now
1028
- });
1029
- emitPhaseCompleted(args.onPhase, now, installStartedAt, "install", install.ok, install.ok
1030
- ? install.attempts === 2
1031
- ? "subject dependencies installed (on the second attempt)"
1032
- : "subject dependencies installed"
1033
- : install.attempts === 2
1034
- ? "subject install failed twice"
1035
- : "subject install failed");
1036
- if (!install.ok) {
1037
- // Lead with the line a person can act on; npm's own trace follows it (#602).
1038
- const headline = install.timedOut
1039
- ? `subject install timed out after ${args.serve.installTimeoutMs ?? INSTALL_TIMEOUT_MS}ms`
1040
- : install.attempts === 2
1041
- ? `subject install failed twice (exit ${install.firstExitCode ?? "null"}, then exit ${install.exitCode ?? "null"}); the sandbox could not complete serve.install`
1042
- : `subject install failed (exit ${install.exitCode ?? "null"})`;
1043
- throw new Error(`${headline}: ${tailOf(args.scrub(install.logTail))}`);
1044
- }
1045
- await refresh();
1046
- }
1047
- // before-build: after install, before build (builds that read seeded state, e.g. SSG).
1048
- // When no build is declared this simply precedes start: equivalent to before-start.
1049
- await runStateSteps("before-build");
1050
- await refresh();
1051
- if (args.serve.build) {
1052
- const buildStartedAt = now();
1053
- emitPhaseStarted(args.onPhase, now, "build", "building subject");
1054
- const build = await runDetachedStep(desktop, {
1055
- name: "subject-build",
1056
- command: args.serve.build,
1057
- cwd: SUBJECT_DIR,
1058
- timeoutMs: args.serve.buildTimeoutMs ?? BUILD_TIMEOUT_MS,
1059
- requestTimeoutMs: args.requestTimeoutMs,
1060
- ...timers
1061
- });
1062
- emitPhaseCompleted(args.onPhase, now, buildStartedAt, "build", build.ok, build.ok ? "subject build complete" : "subject build failed");
1063
- if (!build.ok) {
1064
- throw new Error(`subject build ${build.timedOut ? "timed out" : `failed (exit ${build.exitCode})`}: ${tailOf(args.scrub(build.logTail))}`);
1065
- }
1066
- await refresh();
1067
- }
1068
- // before-start (the default phase): migrations, SQL/file fixtures, an in-sandbox DB server
1069
- // (`sudo service postgresql start && pg_isready` is a bounded step; the daemon it forks is
1070
- // reclaimed by the sandbox lifecycle like everything else).
1071
- await runStateSteps("before-start");
1072
- await refresh();
1073
- await startDetachedProcess(desktop, {
1074
- name: "subject-start",
1075
- command: args.serve.start,
1076
- cwd: SUBJECT_DIR,
1077
- requestTimeoutMs: args.requestTimeoutMs
1078
- });
1079
- // Fire-and-forget: startDetachedProcess never waits for the long-lived server to exit, so
1080
- // there is no matching completed event here (no ok/durationMs to report yet); readiness is
1081
- // the next boundary.
1082
- args.onPhase?.({ at: isoNow(now), type: "cua-lab.subject.serve.started", message: "subject server launched (detached)" });
1083
- const readyStartedAt = now();
1084
- emitPhaseStarted(args.onPhase, now, "ready", "waiting for subject to become ready");
1085
- const ready = await probeUrl(desktop, args.serve.url, {
1086
- timeoutMs: args.serve.readyTimeoutMs ?? DEFAULT_READY_TIMEOUT_MS,
1087
- requestTimeoutMs: args.requestTimeoutMs,
1088
- ...timers
1089
- });
1090
- emitPhaseCompleted(args.onPhase, now, readyStartedAt, "ready", ready, ready ? "subject is ready" : "subject did not become ready in time");
1091
- if (!ready) {
1092
- const startLog = await readDetachedLog(desktop, "subject-start", args.requestTimeoutMs).catch(() => "");
1093
- throw new Error(`subject did not answer at ${args.serve.url} within ${args.serve.readyTimeoutMs ?? DEFAULT_READY_TIMEOUT_MS}ms; server log tail: ${tailOf(args.scrub(startLog))}`);
1094
- }
1095
- // after-ready: fixture loading through the RUNNING app (loopback curl from in-sandbox:
1096
- // steps are author-trusted provisioning, not actors, so no new URL policy surface). These
1097
- // complete before the caller opens the browser and the session timer starts.
1098
- await runStateSteps("after-ready");
1099
- await refresh();
1100
- }
1101
- /**
1102
- * Provision a clone subject inside the sandbox: clone → the shared serve pipeline
1103
- * (install → state(before-build) → build → state(before-start) → start → readiness
1104
- * probe → state(after-ready)). Returns the latest subject HEAD after successful
1105
- * provisioning. Throws (with a capped log tail for the caller to redact) on any failing step:
1106
- * the lab persists that as a failed-evidence bundle.
1107
- *
1108
- * Auth: when GITHUB_TOKEN is among the declared subject env names, the clone authenticates
1109
- * via an Authorization header computed IN-SANDBOX from the provisioned env: the token never
1110
- * appears in the script text, the process argv beyond the transient git call, the clone URL,
1111
- * or .git/config.
1112
- */
1113
- export async function provisionCloneSubject(desktop, args) {
1114
- const timers = {
1115
- ...(args.now === undefined ? {} : { now: args.now }),
1116
- ...(args.sleep === undefined ? {} : { sleep: args.sleep })
1117
- };
1118
- const now = args.now ?? Date.now;
1119
- let latestCommit;
1120
- const refreshCommit = async () => {
1121
- const head = await desktop.commands.run(`git -C ${SUBJECT_DIR} rev-parse HEAD 2>/dev/null || true`, { requestTimeoutMs: args.requestTimeoutMs });
1122
- const commit = (head.stdout ?? "").trim() || undefined;
1123
- if (commit) {
1124
- latestCommit = commit;
1125
- args.onCommit?.(commit);
1126
- }
1127
- };
1128
- const cloneCommand = args.hasGithubToken
1129
- ? `auth=$(printf 'x-access-token:%s' "$GITHUB_TOKEN" | base64 -w0) && git -c http.extraHeader="Authorization: Basic $auth" clone --depth ${args.depth} https://github.com/${args.repo}.git ${SUBJECT_DIR}`
1130
- : `git clone --depth ${args.depth} https://github.com/${args.repo}.git ${SUBJECT_DIR}`;
1131
- const cloneStartedAt = now();
1132
- emitPhaseStarted(args.onPhase, now, "clone", "cloning subject repository");
1133
- const clone = await runDetachedStep(desktop, {
1134
- name: "subject-clone",
1135
- command: cloneCommand,
1136
- timeoutMs: CLONE_TIMEOUT_MS,
1137
- requestTimeoutMs: args.requestTimeoutMs,
1138
- ...timers
1139
- });
1140
- emitPhaseCompleted(args.onPhase, now, cloneStartedAt, "clone", clone.ok, clone.ok ? "subject repository cloned" : "subject clone failed");
1141
- if (!clone.ok) {
1142
- throw new Error(`subject clone ${clone.timedOut ? "timed out" : `failed (exit ${clone.exitCode})`}: ${tailOf(args.scrub(clone.logTail))}`);
1143
- }
1144
- await refreshCommit();
1145
- await runSubjectServePipeline(desktop, {
1146
- serve: args.serve,
1147
- ...(args.state === undefined ? {} : { state: args.state }),
1148
- requestTimeoutMs: args.requestTimeoutMs,
1149
- scrub: args.scrub,
1150
- ...(args.onStateStep === undefined ? {} : { onStateStep: args.onStateStep }),
1151
- ...(args.onPhase === undefined ? {} : { onPhase: args.onPhase }),
1152
- onPhaseComplete: refreshCommit,
1153
- ...timers
1154
- });
1155
- return latestCommit;
1156
- }
1157
- /**
1158
- * Provision a local-tree subject inside the sandbox: upload the once-per-run packed archive
1159
- * (identical bytes across every fan-out lane) → extract it into SUBJECT_DIR → the
1160
- * same shared serve pipeline provisionCloneSubject uses. Unlike the clone route there is no
1161
- * in-sandbox git refresh: the archive excludes .git entirely (see source-archive.ts), so
1162
- * subject identity is the host-side LocalTreeArchive captured at pack time, never anything
1163
- * resolved in-sandbox.
1164
- */
1165
- export async function provisionLocalTreeSubject(desktop, args) {
1166
- const timers = {
1167
- ...(args.now === undefined ? {} : { now: args.now }),
1168
- ...(args.sleep === undefined ? {} : { sleep: args.sleep })
1169
- };
1170
- const now = args.now ?? Date.now;
1171
- const uploadStartedAt = now();
1172
- emitPhaseStarted(args.onPhase, now, "upload", "uploading packed local-tree archive");
1173
- try {
1174
- await withOneRetryOnTransientE2BError(() => desktop.files.write(LOCAL_TREE_REMOTE_ARCHIVE_PATH, args.archiveBuffer, {
1175
- requestTimeoutMs: args.requestTimeoutMs,
1176
- useOctetStream: true
1177
- }), {
1178
- onRetry: (reason) => emitPhaseStarted(args.onPhase, now, "upload-retry", `local-tree archive upload retried once (${tailOf(args.scrub(reason))})`),
1179
- ...(args.sleep === undefined ? {} : { sleep: args.sleep })
1180
- });
1181
- }
1182
- catch (error) {
1183
- emitPhaseCompleted(args.onPhase, now, uploadStartedAt, "upload", false, "local-tree archive upload failed");
1184
- throw new Error(`subject-upload failed: ${tailOf(args.scrub(toErrorMessage(error)))}`);
1185
- }
1186
- emitPhaseCompleted(args.onPhase, now, uploadStartedAt, "upload", true, "local-tree archive uploaded");
1187
- const extractCommand = `rm -rf ${SUBJECT_DIR} && mkdir -p ${SUBJECT_DIR} && tar -xzf ${LOCAL_TREE_REMOTE_ARCHIVE_PATH} -C ${SUBJECT_DIR} && rm -f ${LOCAL_TREE_REMOTE_ARCHIVE_PATH}`;
1188
- const extractStartedAt = now();
1189
- emitPhaseStarted(args.onPhase, now, "extract", "extracting local-tree archive");
1190
- const extract = await runDetachedStep(desktop, {
1191
- name: "subject-extract",
1192
- command: extractCommand,
1193
- timeoutMs: CLONE_TIMEOUT_MS,
1194
- requestTimeoutMs: args.requestTimeoutMs,
1195
- ...timers
1196
- });
1197
- emitPhaseCompleted(args.onPhase, now, extractStartedAt, "extract", extract.ok, extract.ok ? "local-tree archive extracted" : "local-tree archive extraction failed");
1198
- if (!extract.ok) {
1199
- throw new Error(`subject extract ${extract.timedOut ? "timed out" : `failed (exit ${extract.exitCode})`}: ${tailOf(args.scrub(extract.logTail))}`);
1200
- }
1201
- await runSubjectServePipeline(desktop, {
1202
- serve: args.serve,
1203
- ...(args.state === undefined ? {} : { state: args.state }),
1204
- requestTimeoutMs: args.requestTimeoutMs,
1205
- scrub: args.scrub,
1206
- ...(args.onStateStep === undefined ? {} : { onStateStep: args.onStateStep }),
1207
- ...(args.onPhase === undefined ? {} : { onPhase: args.onPhase }),
1208
- ...timers
1209
- });
1210
- }
1211
- /** sha256 hex of the exact command string, first 16 chars (the promptDigest convention). */
1212
- export function commandDigestOf(command) {
1213
- return digestText(command, 16);
1214
- }
1215
- // The in-sandbox `tail -c` upstream is a fundamental log-tail limit we cannot redact past.
1216
- function tailOf(log) {
1217
- return redactedTail(log, ERROR_TAIL_CHARS);
1218
- }
1219
- //# sourceMappingURL=e2b-cua-provisioning.js.map