humanish 0.106.0 → 0.107.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (459) hide show
  1. package/AGENTS.md +4 -2
  2. package/ARCHITECTURE.md +17 -16
  3. package/CHANGELOG.md +24 -0
  4. package/CONTEXT.md +42 -39
  5. package/CONTRIBUTING.md +8 -6
  6. package/README.md +8 -3
  7. package/dist/actors/codex/app-server-client.js +2 -1
  8. package/dist/actors/codex/app-server-trace.d.ts +0 -1
  9. package/dist/actors/codex/app-server-trace.js +1 -3
  10. package/dist/actors/codex/app-server.js +2 -1
  11. package/dist/actors/codex/protocol-compat.d.ts +27 -0
  12. package/dist/actors/codex/protocol-compat.js +357 -0
  13. package/dist/actors/codex/protocol-contract.d.ts +61 -0
  14. package/dist/actors/codex/protocol-contract.js +471 -0
  15. package/dist/actors/codex/qualified-versions.d.ts +31 -4
  16. package/dist/actors/codex/qualified-versions.js +51 -6
  17. package/dist/actors/codex/restricted-executable.d.ts +24 -0
  18. package/dist/actors/codex/restricted-executable.js +97 -22
  19. package/dist/actors/codex/restricted-launch.d.ts +7 -1
  20. package/dist/actors/codex/restricted-launch.js +42 -3
  21. package/dist/actors/codex/restricted-notifications.d.ts +101 -0
  22. package/dist/actors/codex/restricted-notifications.js +277 -0
  23. package/dist/actors/codex/restricted-participant.d.ts +30 -0
  24. package/dist/actors/codex/restricted-participant.js +60 -2
  25. package/dist/actors/codex/restricted-policy.d.ts +9 -1
  26. package/dist/actors/codex/restricted-session.d.ts +14 -1
  27. package/dist/actors/codex/restricted-session.js +50 -17
  28. package/dist/actors/codex/restricted-transport.d.ts +29 -0
  29. package/dist/actors/codex/restricted-transport.js +139 -27
  30. package/dist/actors/codex/restricted-turn.d.ts +19 -4
  31. package/dist/actors/codex/restricted-turn.js +43 -30
  32. package/dist/actors/computer-use/actor.d.ts +1 -1
  33. package/dist/actors/computer-use/actor.js +4 -4
  34. package/dist/actors/computer-use/loop/backstop.js +1 -1
  35. package/dist/actors/computer-use/loop/ending.d.ts +2 -2
  36. package/dist/actors/computer-use/loop/ending.js +2 -2
  37. package/dist/actors/computer-use/loop/spend.d.ts +1 -1
  38. package/dist/actors/computer-use/loop/spend.js +3 -3
  39. package/dist/actors/computer-use/loop/trace.js +2 -2
  40. package/dist/actors/computer-use/loop/types.d.ts +14 -5
  41. package/dist/actors/computer-use/loop.js +4 -4
  42. package/dist/actors/computer-use/openai-provider.d.ts +1 -1
  43. package/dist/actors/computer-use/openai-provider.js +2 -2
  44. package/dist/actors/contract.d.ts +10 -8
  45. package/dist/actors/contract.js +7 -1
  46. package/dist/actors/local-agent/cli.js +1 -1
  47. package/dist/actors/scripted-browser/actor.d.ts +2 -2
  48. package/dist/actors/scripted-browser/journey.js +15 -4
  49. package/dist/actors/scripted-browser/steps.js +18 -0
  50. package/dist/actors/scripted-browser/types.d.ts +11 -1
  51. package/dist/actors/stop-conditions.js +1 -3
  52. package/dist/analysis/automatic-completion.d.ts +13 -8
  53. package/dist/analysis/automatic-completion.js +14 -8
  54. package/dist/analysis/automatic-config.d.ts +1 -1
  55. package/dist/analysis/automatic-config.js +2 -2
  56. package/dist/analysis/automatic.d.ts +10 -4
  57. package/dist/analysis/automatic.js +17 -13
  58. package/dist/analysis/diagnostics.d.ts +23 -0
  59. package/dist/analysis/diagnostics.js +112 -0
  60. package/dist/analysis/evidence-sources.js +2 -2
  61. package/dist/analysis/evidence.js +6 -6
  62. package/dist/analysis/execute.d.ts +7 -1
  63. package/dist/analysis/execute.js +39 -12
  64. package/dist/analysis/job.d.ts +8 -5
  65. package/dist/analysis/job.js +15 -14
  66. package/dist/analysis/load.d.ts +1 -1
  67. package/dist/analysis/load.js +5 -5
  68. package/dist/analysis/provider.d.ts +9 -1
  69. package/dist/analysis/restricted-codex.d.ts +2 -0
  70. package/dist/analysis/restricted-codex.js +10 -1
  71. package/dist/analysis/service.d.ts +2 -0
  72. package/dist/analysis/service.js +31 -12
  73. package/dist/analysis/sharing.d.ts +2 -2
  74. package/dist/analysis/sharing.js +5 -5
  75. package/dist/analysis/store-executions.d.ts +5 -5
  76. package/dist/analysis/store-executions.js +12 -12
  77. package/dist/analysis/store.d.ts +4 -4
  78. package/dist/analysis/store.js +13 -13
  79. package/dist/cli/commands/analysis-signals.d.ts +2 -1
  80. package/dist/cli/commands/analysis-signals.js +4 -1
  81. package/dist/cli/commands/analyze.js +4 -2
  82. package/dist/cli/commands/comms.js +8 -1
  83. package/dist/cli/commands/lab-route-computer-use.d.ts +0 -2
  84. package/dist/cli/commands/lab-route-computer-use.js +26 -14
  85. package/dist/cli/commands/lab-route-preview.d.ts +1 -3
  86. package/dist/cli/commands/lab-route-preview.js +3 -4
  87. package/dist/cli/commands/lab-route-run.d.ts +6 -4
  88. package/dist/cli/commands/lab-route-run.js +6 -2
  89. package/dist/cli/commands/lab-route-scripted.d.ts +0 -2
  90. package/dist/cli/commands/lab-route-scripted.js +0 -1
  91. package/dist/cli/commands/lab-route-shared-world.d.ts +0 -2
  92. package/dist/cli/commands/lab-route-shared-world.js +0 -1
  93. package/dist/cli/commands/lab-route-terminal.d.ts +0 -2
  94. package/dist/cli/commands/lab-route-terminal.js +0 -1
  95. package/dist/cli/commands/lab-run.js +76 -45
  96. package/dist/cli/commands/lab-scorer.d.ts +0 -2
  97. package/dist/cli/commands/lab.js +12 -6
  98. package/dist/cli/commands/observe.js +22 -0
  99. package/dist/cli/commands/run-signals.d.ts +30 -0
  100. package/dist/cli/commands/run-signals.js +146 -0
  101. package/dist/cli/commands/runs.js +10 -8
  102. package/dist/cli/commands/watch.js +12 -10
  103. package/dist/cli/doctor.d.ts +3 -0
  104. package/dist/cli/doctor.js +10 -2
  105. package/dist/cli/io.d.ts +5 -4
  106. package/dist/cli/io.js +12 -8
  107. package/dist/cli/program.js +3 -3
  108. package/dist/cli/renamed-options.d.ts +11 -0
  109. package/dist/cli/renamed-options.js +18 -0
  110. package/dist/cli/telemetry.d.ts +2 -2
  111. package/dist/cli/telemetry.js +1 -1
  112. package/dist/comms/capture-surface.d.ts +1 -1
  113. package/dist/comms/catch-host.d.ts +1 -1
  114. package/dist/comms/connections.js +4 -4
  115. package/dist/comms/external-evidence.d.ts +27 -0
  116. package/dist/comms/external-evidence.js +93 -0
  117. package/dist/comms/lease-store.js +7 -7
  118. package/dist/comms/types.js +1 -1
  119. package/dist/evidence/browser-hygiene.d.ts +1 -1
  120. package/dist/evidence/browser-hygiene.js +1 -1
  121. package/dist/evidence/redaction.js +1 -1
  122. package/dist/evidence/secret-scrub.d.ts +9 -0
  123. package/dist/evidence/secret-scrub.js +96 -0
  124. package/dist/feedback/draft.js +7 -9
  125. package/dist/feedback/export-bundle.js +4 -4
  126. package/dist/feedback/export.js +9 -9
  127. package/dist/feedback/feedback.d.ts +1 -1
  128. package/dist/index.d.ts +3 -6
  129. package/dist/index.js +3 -6
  130. package/dist/keys/key-resolution.d.ts +3 -1
  131. package/dist/keys/key-resolution.js +18 -16
  132. package/dist/lab/adapter-extension.d.ts +28 -6
  133. package/dist/lab/adapter-extension.js +65 -126
  134. package/dist/lab/adapter-scorer-loader.d.ts +25 -5
  135. package/dist/lab/adapter-scorer-loader.js +24 -0
  136. package/dist/lab/composition-rules.d.ts +2 -0
  137. package/dist/lab/composition-rules.js +35 -26
  138. package/dist/lab/config.js +28 -26
  139. package/dist/lab/device-presets.d.ts +2 -2
  140. package/dist/lab/discover.js +1 -3
  141. package/dist/lab/doctor.d.ts +44 -9
  142. package/dist/lab/doctor.js +149 -41
  143. package/dist/lab/init-plan.js +1 -3
  144. package/dist/lab/keys.js +1 -1
  145. package/dist/lab/lab-deps.d.ts +85 -0
  146. package/dist/lab/lab-deps.js +4 -0
  147. package/dist/lab/parse/actors.js +8 -7
  148. package/dist/lab/parse/comms.js +3 -2
  149. package/dist/lab/parse/execution.js +3 -2
  150. package/dist/lab/parse/subject-state.js +2 -1
  151. package/dist/lab/parse/subject.js +2 -1
  152. package/dist/lab/parse/values.d.ts +0 -1
  153. package/dist/lab/parse/values.js +0 -3
  154. package/dist/lab/persona-resolve.d.ts +3 -3
  155. package/dist/lab/persona-resolve.js +4 -4
  156. package/dist/lab/persona.js +1 -3
  157. package/dist/lab/plan-base.d.ts +6 -2
  158. package/dist/lab/plan-base.js +22 -7
  159. package/dist/lab/plan-participants.d.ts +5 -5
  160. package/dist/lab/plan-participants.js +2 -2
  161. package/dist/lab/plan-types.d.ts +33 -7
  162. package/dist/lab/plan.d.ts +3 -11
  163. package/dist/lab/plan.js +18 -42
  164. package/dist/lab/preflight-result.js +0 -2
  165. package/dist/lab/preflight.d.ts +0 -3
  166. package/dist/lab/preflight.js +1 -1
  167. package/dist/lab/requirements.d.ts +20 -0
  168. package/dist/lab/requirements.js +54 -0
  169. package/dist/lab/route-inputs.d.ts +23 -12
  170. package/dist/lab/route-inputs.js +48 -51
  171. package/dist/lab/routing.d.ts +19 -24
  172. package/dist/lab/routing.js +14 -47
  173. package/dist/lab/run-lab-events.d.ts +6 -11
  174. package/dist/lab/run-lab-events.js +3 -11
  175. package/dist/lab/run-lab-homes.d.ts +64 -0
  176. package/dist/lab/run-lab-homes.js +3 -0
  177. package/dist/lab/run-lab-options.d.ts +12 -66
  178. package/dist/lab/run-lab-options.js +45 -275
  179. package/dist/lab/summary.d.ts +9 -4
  180. package/dist/lab/summary.js +15 -8
  181. package/dist/lab/types.d.ts +132 -132
  182. package/dist/lab/validation.d.ts +15 -15
  183. package/dist/lab/validation.js +28 -28
  184. package/dist/lab/warnings.js +20 -19
  185. package/dist/observer/artifact.d.ts +1 -1
  186. package/dist/observer/artifact.js +3 -3
  187. package/dist/observer/data.js +2 -2
  188. package/dist/observer/render.js +2 -2
  189. package/dist/observer/run-routes.d.ts +1 -1
  190. package/dist/observer/run-routes.js +5 -5
  191. package/dist/observer/serve.d.ts +17 -0
  192. package/dist/observer/serve.js +34 -3
  193. package/dist/observer-app.html +1 -1
  194. package/dist/routes/computer-use/bundle-parts.d.ts +1 -1
  195. package/dist/routes/computer-use/bundle-parts.js +10 -3
  196. package/dist/routes/computer-use/bundle.d.ts +4 -11
  197. package/dist/routes/computer-use/bundle.js +9 -15
  198. package/dist/routes/computer-use/diagnostics.d.ts +1 -1
  199. package/dist/routes/computer-use/diagnostics.js +1 -1
  200. package/dist/routes/computer-use/e2b-desktop/comms.d.ts +10 -10
  201. package/dist/routes/computer-use/e2b-desktop/comms.js +11 -14
  202. package/dist/routes/computer-use/e2b-desktop/desktop.d.ts +2 -2
  203. package/dist/routes/computer-use/e2b-desktop/desktop.js +4 -7
  204. package/dist/routes/computer-use/e2b-desktop/fidelity.d.ts +13 -13
  205. package/dist/routes/computer-use/e2b-desktop/fidelity.js +11 -11
  206. package/dist/routes/computer-use/e2b-desktop/prepare.d.ts +3 -3
  207. package/dist/routes/computer-use/e2b-desktop/prepare.js +33 -36
  208. package/dist/routes/computer-use/e2b-desktop/start.d.ts +1 -1
  209. package/dist/routes/computer-use/e2b-desktop/start.js +24 -23
  210. package/dist/routes/computer-use/e2b-desktop/state.d.ts +5 -4
  211. package/dist/routes/computer-use/e2b-desktop/state.js +5 -3
  212. package/dist/routes/computer-use/e2b-desktop/teardown.d.ts +1 -1
  213. package/dist/routes/computer-use/e2b-desktop/teardown.js +29 -17
  214. package/dist/routes/computer-use/external-comms.d.ts +4 -4
  215. package/dist/routes/computer-use/external-comms.js +19 -43
  216. package/dist/routes/computer-use/fanout-bundle.d.ts +3 -3
  217. package/dist/routes/computer-use/fanout-bundle.js +25 -29
  218. package/dist/routes/computer-use/{fanout-lanes.js → fanout-records.js} +25 -19
  219. package/dist/routes/computer-use/in-process-desktop.d.ts +3 -10
  220. package/dist/routes/computer-use/in-process-desktop.js +3 -9
  221. package/dist/routes/computer-use/live-flush.d.ts +7 -5
  222. package/dist/routes/computer-use/live-flush.js +19 -27
  223. package/dist/routes/computer-use/{run-lanes.js → live-phase.js} +14 -13
  224. package/dist/routes/computer-use/local-tree-pack.d.ts +3 -3
  225. package/dist/routes/computer-use/local-tree-pack.js +4 -5
  226. package/dist/routes/computer-use/local-vm.d.ts +11 -8
  227. package/dist/routes/computer-use/local-vm.js +39 -66
  228. package/dist/routes/computer-use/participant-desktop.d.ts +8 -23
  229. package/dist/routes/computer-use/participant-desktop.js +5 -25
  230. package/dist/routes/computer-use/{lanes.d.ts → participant-execution.d.ts} +10 -10
  231. package/dist/routes/computer-use/{lanes.js → participant-execution.js} +35 -22
  232. package/dist/routes/computer-use/participant-facts.d.ts +7 -1
  233. package/dist/routes/computer-use/participant-facts.js +12 -1
  234. package/dist/routes/computer-use/participant-model.d.ts +19 -11
  235. package/dist/routes/computer-use/participant-model.js +58 -33
  236. package/dist/routes/computer-use/participant-prompt.d.ts +3 -3
  237. package/dist/routes/computer-use/participant-prompt.js +4 -4
  238. package/dist/routes/computer-use/participant-runs.d.ts +6 -6
  239. package/dist/routes/computer-use/participant-runs.js +8 -8
  240. package/dist/routes/computer-use/plan.d.ts +21 -29
  241. package/dist/routes/computer-use/plan.js +59 -65
  242. package/dist/routes/computer-use/preflight.d.ts +6 -11
  243. package/dist/routes/computer-use/preflight.js +26 -18
  244. package/dist/routes/computer-use/rerun-selection.js +10 -6
  245. package/dist/routes/computer-use/result.d.ts +1 -1
  246. package/dist/routes/computer-use/result.js +40 -30
  247. package/dist/routes/computer-use/route.d.ts +3 -4
  248. package/dist/routes/computer-use/route.js +21 -19
  249. package/dist/routes/computer-use/self-report.d.ts +2 -2
  250. package/dist/routes/computer-use/self-report.js +4 -4
  251. package/dist/routes/computer-use/setup.d.ts +8 -17
  252. package/dist/routes/computer-use/setup.js +98 -86
  253. package/dist/routes/computer-use/single-bundle.d.ts +8 -11
  254. package/dist/routes/computer-use/single-bundle.js +20 -25
  255. package/dist/routes/computer-use/subject-projection.d.ts +5 -7
  256. package/dist/routes/computer-use/subject-projection.js +20 -19
  257. package/dist/routes/computer-use/types.d.ts +169 -211
  258. package/dist/routes/computer-use/types.js +13 -6
  259. package/dist/routes/preview.js +0 -1
  260. package/dist/routes/scripted/bundle.d.ts +3 -6
  261. package/dist/routes/scripted/bundle.js +11 -16
  262. package/dist/routes/scripted/plan.d.ts +5 -7
  263. package/dist/routes/scripted/plan.js +6 -4
  264. package/dist/routes/scripted/result.d.ts +4 -1
  265. package/dist/routes/scripted/result.js +10 -6
  266. package/dist/routes/scripted/route.js +10 -11
  267. package/dist/routes/scripted/scenario.d.ts +1 -1
  268. package/dist/routes/scripted/scenario.js +1 -1
  269. package/dist/routes/scripted/setup.d.ts +3 -2
  270. package/dist/routes/scripted/setup.js +22 -21
  271. package/dist/routes/scripted/subject.d.ts +8 -3
  272. package/dist/routes/scripted/subject.js +11 -6
  273. package/dist/routes/scripted/surface-records.js +1 -1
  274. package/dist/routes/scripted/surface-sessions.d.ts +2 -2
  275. package/dist/routes/scripted/surface-sessions.js +4 -4
  276. package/dist/routes/scripted/types.d.ts +19 -36
  277. package/dist/routes/scripted/types.js +1 -2
  278. package/dist/routes/shared-world/{seat-records.js → bundle-records.js} +8 -8
  279. package/dist/routes/shared-world/bundle.d.ts +2 -2
  280. package/dist/routes/shared-world/bundle.js +22 -26
  281. package/dist/routes/shared-world/checkpoints.d.ts +4 -4
  282. package/dist/routes/shared-world/checkpoints.js +4 -4
  283. package/dist/routes/shared-world/comms.d.ts +5 -4
  284. package/dist/routes/shared-world/comms.js +28 -41
  285. package/dist/routes/shared-world/external-public.d.ts +5 -5
  286. package/dist/routes/shared-world/external-public.js +19 -20
  287. package/dist/routes/shared-world/handoff.d.ts +4 -4
  288. package/dist/routes/shared-world/handoff.js +50 -50
  289. package/dist/routes/shared-world/lobby-code.d.ts +5 -5
  290. package/dist/routes/shared-world/lobby-code.js +13 -13
  291. package/dist/routes/shared-world/{seats.d.ts → participant-specs.d.ts} +8 -6
  292. package/dist/routes/shared-world/{seats.js → participant-specs.js} +46 -51
  293. package/dist/routes/shared-world/plan.d.ts +2 -6
  294. package/dist/routes/shared-world/plan.js +1 -2
  295. package/dist/routes/shared-world/provenance.d.ts +4 -4
  296. package/dist/routes/shared-world/provenance.js +4 -4
  297. package/dist/routes/shared-world/provisioned.d.ts +3 -2
  298. package/dist/routes/shared-world/provisioned.js +48 -41
  299. package/dist/routes/shared-world/result.js +31 -19
  300. package/dist/routes/shared-world/route.js +37 -41
  301. package/dist/routes/shared-world/setup.d.ts +5 -4
  302. package/dist/routes/shared-world/setup.js +12 -14
  303. package/dist/routes/shared-world/types.d.ts +53 -126
  304. package/dist/routes/shared-world/types.js +2 -2
  305. package/dist/routes/terminal/adapter.d.ts +8 -8
  306. package/dist/routes/terminal/adapter.js +28 -125
  307. package/dist/routes/terminal/bundle.d.ts +7 -12
  308. package/dist/routes/terminal/bundle.js +24 -34
  309. package/dist/routes/terminal/credentials.d.ts +2 -2
  310. package/dist/routes/terminal/credentials.js +16 -16
  311. package/dist/routes/terminal/dry-run.d.ts +1 -1
  312. package/dist/routes/terminal/dry-run.js +9 -11
  313. package/dist/routes/terminal/encoding.d.ts +1 -1
  314. package/dist/routes/terminal/encoding.js +2 -2
  315. package/dist/routes/terminal/ledger.d.ts +6 -6
  316. package/dist/routes/terminal/ledger.js +9 -9
  317. package/dist/routes/terminal/live-finish.d.ts +1 -2
  318. package/dist/routes/terminal/live-finish.js +21 -20
  319. package/dist/routes/terminal/live-sandbox.d.ts +4 -2
  320. package/dist/routes/terminal/live-sandbox.js +25 -21
  321. package/dist/routes/terminal/participant-text.d.ts +23 -0
  322. package/dist/routes/terminal/participant-text.js +165 -0
  323. package/dist/routes/terminal/plan.d.ts +2 -6
  324. package/dist/routes/terminal/plan.js +13 -9
  325. package/dist/routes/terminal/recorder.d.ts +6 -1
  326. package/dist/routes/terminal/recorder.js +12 -4
  327. package/dist/routes/terminal/result.js +4 -4
  328. package/dist/routes/terminal/route.js +26 -26
  329. package/dist/routes/terminal/runtime.d.ts +3 -2
  330. package/dist/routes/terminal/runtime.js +3 -3
  331. package/dist/routes/terminal/sandbox.d.ts +5 -3
  332. package/dist/routes/terminal/sandbox.js +13 -16
  333. package/dist/routes/terminal/session.js +16 -14
  334. package/dist/routes/terminal/token-usage.js +5 -5
  335. package/dist/routes/terminal/trace.d.ts +5 -8
  336. package/dist/routes/terminal/trace.js +9 -64
  337. package/dist/routes/terminal/types.d.ts +85 -93
  338. package/dist/routes/terminal/types.js +9 -4
  339. package/dist/run/active-runs.d.ts +13 -0
  340. package/dist/run/active-runs.js +12 -0
  341. package/dist/run/bundle-shape.d.ts +2 -1
  342. package/dist/run/bundle-shape.js +4 -4
  343. package/dist/run/bundle.d.ts +63 -56
  344. package/dist/run/bundle.js +9 -8
  345. package/dist/run/cost-summary.js +3 -2
  346. package/dist/run/costs.d.ts +6 -6
  347. package/dist/run/costs.js +10 -10
  348. package/dist/run/detail.d.ts +5 -5
  349. package/dist/run/detail.js +6 -6
  350. package/dist/run/dry-run.js +5 -12
  351. package/dist/run/{study-files.d.ts → evidence-files.d.ts} +4 -4
  352. package/dist/run/{study-files.js → evidence-files.js} +5 -5
  353. package/dist/run/feedback-shape.js +1 -1
  354. package/dist/run/judge.d.ts +16 -4
  355. package/dist/run/judge.js +24 -7
  356. package/dist/run/locate.d.ts +2 -0
  357. package/dist/run/locate.js +3 -1
  358. package/dist/run/outcomes.d.ts +3 -3
  359. package/dist/run/outcomes.js +3 -3
  360. package/dist/run/participant-records.d.ts +2 -2
  361. package/dist/run/participant-records.js +2 -2
  362. package/dist/run/paths.js +1 -1
  363. package/dist/run/pricing.d.ts +19 -9
  364. package/dist/run/pricing.js +30 -18
  365. package/dist/run/projection.d.ts +13 -13
  366. package/dist/run/projection.js +8 -8
  367. package/dist/run/reclaim.d.ts +7 -1
  368. package/dist/run/reclaim.js +24 -4
  369. package/dist/run/results.d.ts +1 -1
  370. package/dist/run/run-index.d.ts +1 -1
  371. package/dist/run/run-index.js +11 -11
  372. package/dist/run/run.d.ts +4 -2
  373. package/dist/run/run.js +9 -5
  374. package/dist/run/sandbox-receipts.d.ts +4 -4
  375. package/dist/run/sandbox-receipts.js +4 -4
  376. package/dist/run/shared-world-evidence.d.ts +47 -47
  377. package/dist/run/shared-world-shape.d.ts +3 -3
  378. package/dist/run/shared-world-shape.js +11 -11
  379. package/dist/run/stats.d.ts +5 -5
  380. package/dist/run/stats.js +8 -8
  381. package/dist/run/status.d.ts +16 -6
  382. package/dist/run/status.js +31 -8
  383. package/dist/run/streams.d.ts +26 -19
  384. package/dist/run/terminal-contract.d.ts +5 -5
  385. package/dist/run/terminal-contract.js +4 -4
  386. package/dist/run/transient-comms-secrets.d.ts +5 -0
  387. package/dist/run/transient-comms-secrets.js +12 -0
  388. package/dist/run-lab.d.ts +36 -34
  389. package/dist/run-lab.js +41 -37
  390. package/dist/subject/desktop-cli.d.ts +1 -1
  391. package/dist/subject/desktop-cli.js +1 -1
  392. package/dist/subject/local-tree-archive.d.ts +1 -1
  393. package/dist/subject/local-tree-archive.js +4 -4
  394. package/dist/subject/local-tree.d.ts +2 -2
  395. package/dist/subject/local-tree.js +1 -1
  396. package/dist/subject/node-bootstrap.d.ts +1 -1
  397. package/dist/subject/node-bootstrap.js +4 -4
  398. package/dist/subject/runtime.js +5 -5
  399. package/dist/subject/serve.js +1 -1
  400. package/dist/subject/steps.d.ts +4 -4
  401. package/dist/subject/steps.js +5 -5
  402. package/dist/substrates/desktop-session.d.ts +2 -0
  403. package/dist/substrates/e2b/cdp-probe.d.ts +2 -2
  404. package/dist/substrates/e2b/cdp-probe.js +1 -1
  405. package/dist/substrates/e2b/desktop-browser.d.ts +3 -3
  406. package/dist/substrates/e2b/desktop-browser.js +4 -4
  407. package/dist/substrates/e2b/desktop-cdp.d.ts +7 -7
  408. package/dist/substrates/e2b/desktop-cdp.js +4 -4
  409. package/dist/substrates/e2b/desktop-geometry.d.ts +4 -4
  410. package/dist/substrates/e2b/desktop-geometry.js +3 -3
  411. package/dist/substrates/e2b/desktop-media.js +2 -2
  412. package/dist/substrates/e2b/sandbox.d.ts +2 -0
  413. package/dist/substrates/e2b/sandbox.js +22 -8
  414. package/dist/substrates/e2b/sdk.d.ts +12 -1
  415. package/dist/substrates/e2b/sdk.js +30 -9
  416. package/dist/substrates/local/runtime-host.d.ts +2 -0
  417. package/dist/substrates/local/runtime-host.js +6 -0
  418. package/dist/tui/actions.d.ts +7 -5
  419. package/dist/tui/actions.js +18 -9
  420. package/dist/tui-app.js +42 -42
  421. package/dist/verify/actor.d.ts +10 -10
  422. package/dist/verify/actor.js +15 -15
  423. package/dist/verify/artifacts.d.ts +1 -1
  424. package/dist/verify/artifacts.js +3 -3
  425. package/dist/verify/costs.d.ts +2 -2
  426. package/dist/verify/costs.js +2 -2
  427. package/dist/verify/liveness.d.ts +1 -1
  428. package/dist/verify/liveness.js +4 -1
  429. package/dist/verify/rerun.d.ts +1 -1
  430. package/dist/verify/rerun.js +1 -1
  431. package/dist/verify/shared-world.js +2 -2
  432. package/dist/verify/verify.js +6 -6
  433. package/docs/README.md +1 -1
  434. package/docs/architecture/actor-contract.md +60 -22
  435. package/docs/architecture/desktop-sessions.md +9 -9
  436. package/docs/architecture/external-public-shared-world.md +5 -0
  437. package/docs/architecture/observer.md +4 -4
  438. package/docs/architecture/restricted-codex-analysis.md +40 -4
  439. package/docs/architecture/state-driven-executor.md +4 -5
  440. package/docs/architecture/task-protocol-support.md +3 -5
  441. package/docs/architecture/{terminal-product-lane.md → terminal-product-route.md} +24 -16
  442. package/docs/contracts/run-bundle.md +10 -8
  443. package/docs/contracts/schemas.md +109 -53
  444. package/docs/contracts/study-analysis.md +24 -0
  445. package/docs/decisions/0004-participant-desktops-stay-in-the-route.md +2 -1
  446. package/docs/product/automatic-analysis.md +1 -0
  447. package/docs/ramp/README.md +2 -1
  448. package/package.json +4 -4
  449. package/skills/humanish/SKILL.md +3 -2
  450. package/skills/humanish/agents/openai.yaml +1 -1
  451. package/dist/deprecated.d.ts +0 -90
  452. package/dist/deprecated.js +0 -106
  453. package/dist/lab/bag-overrides.d.ts +0 -18
  454. package/dist/lab/bag-overrides.js +0 -121
  455. package/dist/routes/computer-use/legacy-lane-spec.d.ts +0 -62
  456. package/dist/routes/computer-use/legacy-lane-spec.js +0 -39
  457. /package/dist/routes/computer-use/{fanout-lanes.d.ts → fanout-records.d.ts} +0 -0
  458. /package/dist/routes/computer-use/{run-lanes.d.ts → live-phase.d.ts} +0 -0
  459. /package/dist/routes/shared-world/{seat-records.d.ts → bundle-records.d.ts} +0 -0
@@ -38,6 +38,7 @@ export class LiveTerminalSandbox {
38
38
  module;
39
39
  allocation;
40
40
  startupCleanup;
41
+ startupCleanupDetail;
41
42
  // The sandbox's billed span (acquired to cleanup) and size price its compute time.
42
43
  createdAtMs;
43
44
  tornDownAtMs;
@@ -51,13 +52,13 @@ export class LiveTerminalSandbox {
51
52
  });
52
53
  }
53
54
  async acquire() {
54
- const { plan, hooks, now, sanitize, runtimeEnv, e2bApiKey, runPaths, metadata } = this.inputs;
55
+ const { plan, deps, now, sanitize, runtimeEnv, e2bApiKey, runPaths, metadata } = this.inputs;
55
56
  const { warnings } = this.inputs;
56
57
  const { recordLifecycle } = this.inputs.recorder;
57
58
  const { requestTimeoutMs, sandboxTimeoutMs } = this;
58
59
  // Declared egress allowlist, or undefined for the historical unrestricted default (#538).
59
60
  const egressAllow = plan.egressAllow;
60
- const sandboxModule = await (hooks.loadModule ?? loadE2BDesktopModule)();
61
+ const sandboxModule = await (deps.desktopModule ?? loadE2BDesktopModule)();
61
62
  this.module = sandboxModule;
62
63
  await validatePreparedRunArtifactPaths(runPaths);
63
64
  // No sandbox-global env in either mode. In openai-egress, only this host-side SDK request
@@ -129,7 +130,7 @@ export class LiveTerminalSandbox {
129
130
  const { recordLifecycle } = this.inputs.recorder;
130
131
  const { requestTimeoutMs } = this;
131
132
  // --- Runtime bootstrap: no runtime env; openai-egress proxy capability is already available. ---
132
- // The stock desktop needs Node/npm on PATH before npx can run Codex. Reuse a working
133
+ // The stock desktop needs Node/npm on `PATH` before npx can run Codex. Reuse a working
133
134
  // installation or install the pinned official binary after checksum verification (#674).
134
135
  // No raw runtime key touches this step; the egress proxy, when selected, is already available.
135
136
  const bootstrapStartedAt = now();
@@ -151,7 +152,7 @@ export class LiveTerminalSandbox {
151
152
  ? `Runtime bootstrap FAILED after ${bootstrapDurationMs}ms: ${bootstrapError}. codex exec runs via npx and needs Node/npm present; the participant fails closed rather than attempting an exec with no runtime.`
152
153
  : `Runtime bootstrap ensured Node/npm present in ${bootstrapDurationMs}ms (codex exec runs via npx).`);
153
154
  if (bootstrapError) {
154
- // Fail closed as a structured lane status (never a raw throw): no codex exec is attempted
155
+ // Fail closed as a structured route status (never a raw throw): no codex exec is attempted
155
156
  // without a proven runtime; this mirrors the exec-error status assignment below so the
156
157
  // bundle and verify surface the failure the same way.
157
158
  this.status = "failed";
@@ -184,7 +185,7 @@ export class LiveTerminalSandbox {
184
185
  throw new Error(`Codex version mismatch: requested ${requested}, observed ${observed}.`);
185
186
  }
186
187
  runtime.versionStatus = "verified";
187
- recordLifecycle("terminal-lab.runtime.version", `Codex requested ${runtime.requestedVersion}, observed ${observed}; exact version selected for execution. Model ${runtime.requestedModel ?? "runtime default (unobserved)"}; reasoning effort ${runtime.requestedReasoningEffort ?? "runtime default (unobserved)"}.`);
188
+ recordLifecycle("terminal-lab.runtime.version", `Codex requested ${runtime.requestedVersion}, observed ${observed}; exact version selected for execution. Model ${runtime.requestedModel ?? "unrecorded"} (${runtime.modelStatus}); reasoning effort ${runtime.requestedReasoningEffort ?? "runtime default (unobserved)"}.`);
188
189
  }
189
190
  catch (error) {
190
191
  runtime.versionStatus = "failed";
@@ -204,15 +205,15 @@ export class LiveTerminalSandbox {
204
205
  const { requestTimeoutMs } = this;
205
206
  // --- Optional product setup (no runtime env), before the Codex exec. ---
206
207
  // Same channel and same guarantees as the runtime bootstrap above: no runtime key touches it,
207
- // and a failure fails the lane closed rather than handing the agent a half-built world. It
208
- // exists so a study can put the participant IN a prepared project — asking an agent what
208
+ // and a failure fails the run closed rather than handing the agent a half-built world. It
209
+ // exists so a study can put the participant in a prepared project: asking an agent what
209
210
  // studies a project contains, in an empty directory, measures the lab and not the product
210
- // (learned the hard way on the desktop lane, labs/tui-self-study.yaml).
211
+ // (learned the hard way on the desktop route, labs/tui-self-study.yaml).
211
212
  const install = plan.product.install;
212
213
  if (install === undefined)
213
214
  return true;
214
215
  // An optional local file, put on the machine before the install runs, so a study can meet a
215
- // build that is not published yet. Read and checked HERE rather than trusted from the
216
+ // build that is not published yet. It is read and checked here, so nothing is trusted from the
216
217
  // manifest: this puts a file from the operator's disk onto a machine an autonomous agent is
217
218
  // about to drive, so it stays inside the project, must be a regular file, and is size-capped.
218
219
  let uploadAssignment = "";
@@ -238,8 +239,8 @@ export class LiveTerminalSandbox {
238
239
  });
239
240
  const bytes = await readFile(real);
240
241
  await this.sandbox.files.write(destination, bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength));
241
- // Inlined into the command string rather than passed as `envs`: the ONLY call in this
242
- // lane that carries envs is the keyed codex exec, and that invariant is worth more than
242
+ // Inlined into the command string rather than passed as `envs`: the only call on this
243
+ // route that carries envs is the keyed codex exec, and that invariant is worth more than
243
244
  // the convenience of a second envs channel.
244
245
  uploadAssignment = `export HUMANISH_PRODUCT_UPLOAD=${shellQuote(destination)}; `;
245
246
  recordLifecycle("terminal-lab.product.uploaded", `Uploaded ${info.size} bytes to the sandbox in ${Math.max(0, now() - uploadStartedAt)}ms (no runtime env; declared egress auth may already be available).`);
@@ -299,7 +300,7 @@ export class LiveTerminalSandbox {
299
300
  prompt: composedPrompt,
300
301
  runtimeAuth: runtimeEnv.mode,
301
302
  version: runtime.observedVersion,
302
- ...(model === undefined ? {} : { model }),
303
+ model,
303
304
  ...(reasoningEffort === undefined ? {} : { reasoningEffort }),
304
305
  });
305
306
  const commandDigest = digestText(codexCommand);
@@ -341,13 +342,13 @@ export class LiveTerminalSandbox {
341
342
  at: nowIso(),
342
343
  label: "codex-exec",
343
344
  commandDigest,
344
- envNames: Object.keys(runtimeEnv.envs), // NAMES only — the credential evidence (item 4).
345
+ envNames: Object.keys(runtimeEnv.envs), // Names only: the credential evidence (item 4).
345
346
  ...(exitCode === undefined ? {} : { exitCode }),
346
347
  ...(this.timedOut ? { timedOut: true } : {}),
347
348
  durationMs,
348
349
  });
349
- // Score by the verdict-nonce marker over the SCRUBBED+REDACTED, NORMALIZED transcript — the
350
- // exact same logic the local-actor lanes use (extractLocalActorVerdict/normalizeLocalActorTranscript).
350
+ // Score by the verdict-nonce marker over the scrubbed, redacted and normalized transcript, with
351
+ // the exact same logic the local-actor routes use (extractLocalActorVerdict/normalizeLocalActorTranscript).
351
352
  const rawTranscript = terminalEvents.map((e) => e.chunk).join("");
352
353
  const normalizedTranscript = normalizeLocalActorTranscript(rawTranscript);
353
354
  const markerStatus = extractLocalActorVerdict(normalizedTranscript, verdictNonce);
@@ -377,8 +378,8 @@ export class LiveTerminalSandbox {
377
378
  }
378
379
  else {
379
380
  // No nonce-verified verdict: the agent did not (credibly) report a terminal status. A run
380
- // that exited 0 but printed no verified marker is BLOCKED evidence (the failure IS the
381
- // evidence — still structurally verifiable), not a silent pass.
381
+ // that exited 0 but printed no verified marker is blocked evidence: the failure is the
382
+ // evidence, and it stays structurally verifiable.
382
383
  this.status = "blocked";
383
384
  this.completionReason = "gave_up";
384
385
  this.reason = `codex exec exit=${exitCode ?? "null"} but no nonce-verified HUMANISH_ACTOR_VERDICT marker was emitted; recorded as blocked (the missing verdict is the evidence).`;
@@ -389,8 +390,10 @@ export class LiveTerminalSandbox {
389
390
  recordSessionError(error) {
390
391
  const { sanitize } = this.inputs;
391
392
  const { recordLifecycle } = this.inputs.recorder;
392
- if (error instanceof E2BDesktopStartupError)
393
+ if (error instanceof E2BDesktopStartupError) {
393
394
  this.startupCleanup = error.cleanup;
395
+ this.startupCleanupDetail = error.cleanupDetail;
396
+ }
394
397
  this.error = sanitize(toErrorMessage(error));
395
398
  this.status = "failed";
396
399
  this.completionReason = "harness_error";
@@ -401,11 +404,12 @@ export class LiveTerminalSandbox {
401
404
  const { now, sanitize, warnings } = this.inputs;
402
405
  const { recordLifecycle } = this.inputs.recorder;
403
406
  const { requestTimeoutMs } = this;
404
- // --- Safety contract item 8: PROVEN cleanup, BY EXACT ID, never Sandbox.list. ---
407
+ // --- Safety contract item 8: proven cleanup, by exact id, never Sandbox.list. ---
405
408
  this.cleanup = await teardownSandbox({
406
409
  allocation: this.allocation,
407
410
  sandboxModule: this.module,
408
411
  ...(this.startupCleanup === undefined ? {} : { startupCleanup: this.startupCleanup }),
412
+ startupCleanupDetail: this.startupCleanupDetail,
409
413
  requestTimeoutMs,
410
414
  sanitize,
411
415
  recordLifecycle,
@@ -431,14 +435,14 @@ export class LiveTerminalSandbox {
431
435
  }
432
436
  /** Build the in-sandbox `codex exec` command (non-interactive, JSON, stdin disabled by mechanism). */
433
437
  function buildCodexExecCommand(args) {
434
- // The prompt is passed via a heredoc on stdin of a wrapper? NO, stdin is DISABLED (item 7), so
438
+ // stdin is disabled (item 7), so no heredoc on a wrapper's stdin carries the prompt;
435
439
  // the prompt rides as the final positional arg, shell-quoted. codex exec --json runs once and
436
440
  // exits (no interactive loop). --skip-git-repo-check: the workdir is a fresh scratch dir.
437
441
  // Pinned via npx (never an ambient/preinstalled `codex` binary, which the stock @e2b/desktop
438
442
  // image does not ship, per issue #159); npm_config_update_notifier=false silences npx's own
439
443
  // update check so it cannot leak into the captured stdout the scorer/redactor parse.
440
444
  const quotedPrompt = shellQuote(args.prompt);
441
- // --dangerously-bypass-approvals-and-sandbox: codex's OWN inner sandbox is
445
+ // --dangerously-bypass-approvals-and-sandbox: codex's own inner sandbox is
442
446
  // redundant here and blocks the network/file access the study mission needs.
443
447
  // The E2B sandbox is the trust boundary (the disposable machine), and exec mode has no
444
448
  // interactive approval channel at all.
@@ -0,0 +1,23 @@
1
+ import type { ActorTraceItem } from "../../actors/contract.js";
2
+ /** What the reader found in the agent's Codex JSON stdout. */
3
+ export interface TerminalParticipantText {
4
+ /** Message and reasoning items, the most recent kept under the aggregate limits, then a notice
5
+ * when older ones were left out. */
6
+ items: ActorTraceItem[];
7
+ /** Distinct agent_message items in the stream, kept or not. */
8
+ messages: number;
9
+ /** Distinct participant items: messages, reasoning, commands, web searches and file changes.
10
+ * Lifecycle, usage, launcher diagnostics and nested command output are not activity. Zero
11
+ * means no recognized item was retained, not that the participant succeeded. */
12
+ participantItems: number;
13
+ }
14
+ /**
15
+ * Read participant text from the raw stdout as the recorder receives it. Source redaction runs on
16
+ * the stored stream and can cut through JSON framing (a redacted URL takes the closing quote with
17
+ * it), so each line is parsed here, in memory, and only decoded text that has passed `sanitize`
18
+ * is kept. The raw bytes are never stored.
19
+ */
20
+ export declare function createTerminalParticipantReader(sanitize: (text: string) => string): {
21
+ append(raw: string): void;
22
+ finish(): TerminalParticipantText;
23
+ };
@@ -0,0 +1,165 @@
1
+ import { normalizeLocalActorTranscript } from "../../run/terminal-contract.js";
2
+ import { MESSAGE_CHARS, PENDING_LINE_CHARS, TEXT_ITEMS_BYTES, TEXT_ITEMS_MAX } from "./types.js";
3
+ const itemEvents = new Set(["item.started", "item.updated", "item.completed"]);
4
+ const nonempty = (value) => typeof value === "string" && value.trim().length > 0;
5
+ const object = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
6
+ /** Each Codex item event in a run of complete JSON lines, in stream order. */
7
+ function* codexStreamItems(lines) {
8
+ for (const line of lines.split("\n")) {
9
+ let event;
10
+ try {
11
+ event = JSON.parse(line);
12
+ }
13
+ catch {
14
+ continue;
15
+ }
16
+ if (!object(event) ||
17
+ typeof event.type !== "string" ||
18
+ !itemEvents.has(event.type) ||
19
+ !object(event.item) ||
20
+ !nonempty(event.item.id))
21
+ continue;
22
+ yield { event: event.type, id: event.item.id, item: event.item };
23
+ }
24
+ }
25
+ function isParticipantItem(item) {
26
+ return (((item.type === "agent_message" || item.type === "reasoning") && nonempty(item.text)) ||
27
+ (item.type === "command_execution" && nonempty(item.command)) ||
28
+ (item.type === "web_search" &&
29
+ (nonempty(item.query) || (object(item.action) && nonempty(item.action.type)))) ||
30
+ (item.type === "file_change" &&
31
+ Array.isArray(item.changes) &&
32
+ item.changes.some((change) => object(change) && nonempty(change.path) && nonempty(change.kind))));
33
+ }
34
+ // The verdict parser removes all whitespace before matching, so a line is a marker line when its
35
+ // whitespace-free form names either marker. The parser reads the stored stream, not these items.
36
+ const MARKER = /HUMANISH_ACTOR_(?:VERDICT|NONCE)=/i;
37
+ const withoutMarkerLines = (text) => text
38
+ .split("\n")
39
+ .filter((line) => !MARKER.test(line.replace(/\s+/g, "")))
40
+ .join("\n");
41
+ /**
42
+ * Read participant text from the raw stdout as the recorder receives it. Source redaction runs on
43
+ * the stored stream and can cut through JSON framing (a redacted URL takes the closing quote with
44
+ * it), so each line is parsed here, in memory, and only decoded text that has passed `sanitize`
45
+ * is kept. The raw bytes are never stored.
46
+ */
47
+ export function createTerminalParticipantReader(sanitize) {
48
+ let pending = "";
49
+ // Set while the rest of an over-long line is skipped, up to its newline.
50
+ let skipping = false;
51
+ let droppedLines = 0;
52
+ const participantIds = new Set();
53
+ const messageIds = new Set();
54
+ const done = new Set();
55
+ // Completed or left-out items; later events for them are ignored.
56
+ const closed = new Set();
57
+ const texts = new Map();
58
+ const numbers = { message: 0, reasoning: 0 };
59
+ let left = 0;
60
+ let result;
61
+ const take = (lines) => {
62
+ for (const { event, id, item } of codexStreamItems(normalizeLocalActorTranscript(lines))) {
63
+ if (isParticipantItem(item))
64
+ participantIds.add(id);
65
+ const kind = item.type === "agent_message" ? "message" : item.type === "reasoning" ? "reasoning" : null;
66
+ if (kind === null || !nonempty(item.text) || closed.has(id))
67
+ continue;
68
+ if (kind === "message")
69
+ messageIds.add(id);
70
+ if (event === "item.completed") {
71
+ done.add(id);
72
+ closed.add(id);
73
+ }
74
+ // Redact the decoded text before cutting it, so a cut cannot split a value past the patterns.
75
+ const clean = [...sanitize(withoutMarkerLines(item.text))];
76
+ const text = (clean.length > MESSAGE_CHARS ? clean.slice(0, MESSAGE_CHARS) : clean).join("");
77
+ const previous = texts.get(id);
78
+ if (!text.trim()) {
79
+ texts.delete(id);
80
+ continue;
81
+ }
82
+ texts.set(id, { kind, number: previous?.number ?? ++numbers[kind], text });
83
+ // The oldest item beyond the count limit is left out as the stream arrives, finished or not,
84
+ // so a long stream cannot hold every message in memory.
85
+ if (texts.size > TEXT_ITEMS_MAX) {
86
+ const oldest = texts.keys().next().value;
87
+ texts.delete(oldest);
88
+ closed.add(oldest);
89
+ left += 1;
90
+ }
91
+ }
92
+ };
93
+ return {
94
+ append(raw) {
95
+ if (result)
96
+ return;
97
+ if (skipping) {
98
+ const end = raw.indexOf("\n");
99
+ if (end < 0)
100
+ return;
101
+ skipping = false;
102
+ raw = raw.slice(end + 1);
103
+ }
104
+ pending += raw;
105
+ const end = pending.lastIndexOf("\n");
106
+ if (end >= 0) {
107
+ take(pending.slice(0, end));
108
+ pending = pending.slice(end + 1);
109
+ }
110
+ // A line with no newline in sight is dropped, so one runaway line cannot grow without bound.
111
+ if (pending.length > PENDING_LINE_CHARS) {
112
+ pending = "";
113
+ skipping = true;
114
+ droppedLines += 1;
115
+ }
116
+ },
117
+ finish() {
118
+ if (result)
119
+ return result;
120
+ if (!skipping)
121
+ take(pending);
122
+ pending = "";
123
+ const entries = [...texts.entries()];
124
+ let start = entries.length;
125
+ let bytes = 0;
126
+ while (start > 0 && entries.length - start < TEXT_ITEMS_MAX) {
127
+ const size = Buffer.byteLength(entries[start - 1][1].text);
128
+ if (bytes + size > TEXT_ITEMS_BYTES)
129
+ break;
130
+ bytes += size;
131
+ start -= 1;
132
+ }
133
+ left += start;
134
+ const kept = entries.slice(start);
135
+ const items = kept.map(([source, { kind, number, text }]) => ({
136
+ id: `${kind}-${String(number).padStart(3, "0")}`,
137
+ kind,
138
+ lifecycle: done.has(source) ? "completed" : "started",
139
+ title: kind === "message" ? "agent message" : "agent reasoning",
140
+ text,
141
+ }));
142
+ const notices = [];
143
+ if (left > 0)
144
+ notices.push([
145
+ "agent text truncated",
146
+ `Kept the last ${kept.length} of ${kept.length + left} agent message and reasoning items, within ${TEXT_ITEMS_MAX} items and ${TEXT_ITEMS_BYTES / 1024} KiB. The terminal transcript keeps the captured stream.`,
147
+ ]);
148
+ if (droppedLines > 0)
149
+ notices.push([
150
+ "agent output lines skipped",
151
+ `Skipped ${droppedLines} stdout line(s) that ran past ${PENDING_LINE_CHARS} characters without a newline. Items on those lines are not in this trace or its counts.`,
152
+ ]);
153
+ notices.forEach(([title, text], index) => items.push({
154
+ id: `notice-${String(index + 1).padStart(3, "0")}`,
155
+ kind: "notice",
156
+ lifecycle: "completed",
157
+ status: "truncated",
158
+ title,
159
+ text,
160
+ }));
161
+ result = { items, messages: messageIds.size, participantItems: participantIds.size };
162
+ return result;
163
+ },
164
+ };
165
+ }
@@ -1,6 +1,5 @@
1
1
  import type { RoutePlanResult, RouteRefusal, TerminalPlan } from "../../lab/plan-types.js";
2
2
  import type { LabConfig } from "../../lab/types.js";
3
- import type { RunLabProvenance } from "../../run/status.js";
4
3
  import { type TerminalProductLabResult } from "./types.js";
5
4
  /** The error a terminal lab returns before a run starts. `actor` names the registered actor. */
6
5
  export interface TerminalRefusal extends RouteRefusal<"terminal", NonNullable<TerminalProductLabResult["error"]>["code"]> {
@@ -13,9 +12,6 @@ export type TerminalPlanResult = RoutePlanResult<TerminalPlan, TerminalRefusal>;
13
12
  */
14
13
  export declare function planTerminalLab(config: LabConfig, input: {
15
14
  readonly dryRun: boolean;
16
- readonly lab?: RunLabProvenance;
17
- /** A caller's costProbe can measure spend lines, so a positive maxUsd can trip. */
18
- readonly hooks?: {
19
- readonly costProbe?: unknown;
20
- };
15
+ /** A test's costProbe can measure spend lines, so a positive maxUsd can trip. */
16
+ readonly hasCostProbe?: boolean;
21
17
  }): TerminalPlanResult;
@@ -1,6 +1,7 @@
1
1
  // The terminal route's plan: every configuration refusal the route makes before a run starts, in
2
2
  // its order and with its codes, then the plan the run uses. The route checks nothing here again;
3
3
  // what stays in the route reads external state (keys, the runtime env, the sandbox).
4
+ import { DEFAULT_OPENAI_CU_MODEL } from "../../actors/computer-use/openai-provider.js";
4
5
  import { resolveAutomaticAnalysis } from "../../analysis/automatic-config.js";
5
6
  import { isReasoningEffort } from "../../actors/reasoning-effort.js";
6
7
  import { actorRegistry, isTerminalActorDescriptor } from "../../actors/registry.js";
@@ -48,7 +49,6 @@ export function planTerminalLab(config, input) {
48
49
  return refuse("HUMANISH_TERMINAL_LAB_SUBJECT_INVALID", "terminal-product subjects require `subject.product` with a name and at least one public surface URL.", descriptor.id);
49
50
  const base = planBase(config, {
50
51
  dryRun: input.dryRun,
51
- ...(input.lab === undefined ? {} : { lab: input.lab }),
52
52
  analysis,
53
53
  });
54
54
  const egressAllow = config.execution?.egressAllow;
@@ -62,7 +62,11 @@ export function planTerminalLab(config, input) {
62
62
  ...(actor?.mission === undefined ? {} : { mission: actor.mission }),
63
63
  runtime: {
64
64
  ...(runtimeVersion === undefined ? {} : { version: runtimeVersion }),
65
- ...(actor?.model === undefined ? {} : { model: actor.model }),
65
+ // Codex's own default can change with any release and its JSON stream does not name it, so
66
+ // the route always passes a model: the declared one, else humanish's participant default.
67
+ ...(actor?.model === undefined
68
+ ? { model: DEFAULT_OPENAI_CU_MODEL, modelSource: "humanish_default" }
69
+ : { model: actor.model, modelSource: "declared" }),
66
70
  ...(actor?.reasoningEffort === undefined ? {} : { reasoningEffort: actor.reasoningEffort }),
67
71
  ...(config.execution?.runtimeAuth === undefined
68
72
  ? {}
@@ -74,7 +78,7 @@ export function planTerminalLab(config, input) {
74
78
  const caps = config.scenario?.caps;
75
79
  if (input.dryRun)
76
80
  return { ok: true, plan: { ...shared, dryRun: true, ...(caps ? { caps } : {}) } };
77
- // The live lane injects the runtime key into one command only, and only a registered actor
81
+ // The live route injects the runtime key into one command only, and only a registered actor
78
82
  // that declares that placement may run live.
79
83
  const keyPlacement = descriptor.capabilities.keyPlacement;
80
84
  if (keyPlacement !== "in-sandbox-command-scoped")
@@ -85,12 +89,12 @@ export function planTerminalLab(config, input) {
85
89
  if (caps === undefined || maxUsd === undefined || maxMinutes === undefined || maxMinutes <= 0)
86
90
  return refuse("HUMANISH_TERMINAL_LAB_CAPS_MISSING", "A live terminal-product run grants provider access to the in-sandbox agent and so REQUIRES a fail-closed cap: scenario.caps with maxUsd (0 = no-spend) and a positive maxMinutes (the codex command's wall-clock kill). The live key is never exercised without a cap in force.", descriptor.id);
87
91
  // maxUsd is checked against the cost ledger after the session, and only known lines can trip it.
88
- // Core records the Codex provider line as unpriced tokens (no rate for model `codex`) and has no
89
- // product, media or payment signal, so without a costProbe every line is null and a positive
90
- // maxUsd could never trip. That cap would promise a bound nothing enforces, so it is refused;
91
- // maxMinutes is what bounds a live run.
92
- if (maxUsd > 0 && input.hooks?.costProbe === undefined)
93
- return refuse("HUMANISH_TERMINAL_LAB_UNPRICED_CAP", `scenario.caps.maxUsd=${maxUsd} cannot be enforced: the Codex participant's provider spend is recorded as unpriced tokens and no product, media or payment spend is measured, so a positive dollar cap can never trip. Set scenario.caps.maxUsd to 0 and bound the run with scenario.caps.maxMinutes, the codex command's wall-clock kill. No sandbox was created and the runtime key was not used.`, descriptor.id);
92
+ // The ledger's provider line takes only provider-reported cost, which Codex does not report (the
93
+ // token estimate in run.json is not a measurement), and core has no product, media or payment
94
+ // signal, so without a costProbe every line is null and a positive maxUsd could never trip. That
95
+ // cap would promise a bound nothing enforces, so it is refused; maxMinutes bounds a live run.
96
+ if (maxUsd > 0 && input.hasCostProbe !== true)
97
+ return refuse("HUMANISH_TERMINAL_LAB_UNPRICED_CAP", `scenario.caps.maxUsd=${maxUsd} cannot be enforced: Codex reports no provider cost for the participant (its token cost is only estimated after the run) and no product, media or payment spend is measured, so a positive dollar cap can never trip. Set scenario.caps.maxUsd to 0 and bound the run with scenario.caps.maxMinutes, the codex command's wall-clock kill. No sandbox was created and the runtime key was not used.`, descriptor.id);
94
98
  // The sandbox's timeout covers the steps before the codex command, maxMinutes and the teardown
95
99
  // buffer, and E2B refuses a sandbox over an hour. Refuse here, with the arithmetic, rather than
96
100
  // after the plan prints, from a provider 400 that names neither knob.
@@ -1,7 +1,8 @@
1
1
  import { type CommandLogRecord, type InterventionRecord, type LifecycleRecord, type TerminalEventRecord } from "./types.js";
2
2
  /**
3
3
  * The terminal run's ledgers and capture buffers, mutated through the live lifecycle. Every chunk
4
- * is scrubbed and redacted as it is stored; raw bytes never leave the append functions.
4
+ * is scrubbed and redacted as it is stored. Raw bytes leave the append functions only for the
5
+ * in-memory participant reader, which keeps sanitized decoded text.
5
6
  */
6
7
  export declare function createTerminalRecorder(args: {
7
8
  nowIso: () => string;
@@ -17,6 +18,10 @@ export declare function createTerminalRecorder(args: {
17
18
  stderr: string;
18
19
  combined: string;
19
20
  };
21
+ participantText: {
22
+ append(raw: string): void;
23
+ finish(): import("./participant-text.js").TerminalParticipantText;
24
+ };
20
25
  recordLifecycle: (event: string, message: string) => void;
21
26
  recordStreamedTerminalChunk: (stream: "stdout" | "stderr", raw: string) => void;
22
27
  appendReturnedTerminalOutput: (stream: "stdout" | "stderr", raw: string) => void;
@@ -1,8 +1,10 @@
1
1
  import { createHash } from "node:crypto";
2
+ import { createTerminalParticipantReader } from "./participant-text.js";
2
3
  import { MAX_TRANSCRIPT_BYTES, } from "./types.js";
3
4
  /**
4
5
  * The terminal run's ledgers and capture buffers, mutated through the live lifecycle. Every chunk
5
- * is scrubbed and redacted as it is stored; raw bytes never leave the append functions.
6
+ * is scrubbed and redacted as it is stored. Raw bytes leave the append functions only for the
7
+ * in-memory participant reader, which keeps sanitized decoded text.
6
8
  */
7
9
  export function createTerminalRecorder(args) {
8
10
  const { nowIso, sanitize, knownSecretValues } = args;
@@ -13,7 +15,9 @@ export function createTerminalRecorder(args) {
13
15
  // cross-chunk redaction below; this overlap is never added to terminal events/artifacts.
14
16
  const discardedPrefixes = { stdout: "", stderr: "", combined: "" };
15
17
  const maxDiscardedPrefixChars = Math.max(0, ...knownSecretValues.map((value) => value.length - 1));
16
- const interventions = []; // ALWAYS empty while no assisted-input path ships.
18
+ const interventions = []; // Always empty while no assisted-input path ships.
19
+ // Reads the agent's text from the raw stdout in memory; it keeps only sanitized decoded text.
20
+ const participantText = createTerminalParticipantReader(sanitize);
17
21
  let transcriptBytes = 0;
18
22
  const recordLifecycle = (event, message) => {
19
23
  lifecycle.push({ at: nowIso(), event, message: sanitize(message) });
@@ -28,10 +32,13 @@ export function createTerminalRecorder(args) {
28
32
  return;
29
33
  }
30
34
  transcriptBytes += Buffer.byteLength(raw, "utf8");
31
- // Scrub THEN redact at the SOURCE — raw bytes never leave this function (safety contract item 5).
35
+ // Scrub, then redact, at the source (safety contract item 5). Only the participant reader below
36
+ // sees the raw bytes, and it stores none of them.
32
37
  terminalEvents.push({ at: nowIso(), stream, chunk: sanitize(raw) });
38
+ if (stream === "stdout")
39
+ participantText.append(raw);
33
40
  };
34
- // E2B can stream every byte through callbacks AND return the same complete output (#667).
41
+ // E2B can stream every byte through callbacks and return the same complete output (#667).
35
42
  // Track transport delivery, independently per stream, rather than deduplicating participant
36
43
  // lines or equal usage records. Hash raw callback bytes before redaction/truncation so the
37
44
  // comparison cannot confuse two values that redact identically or lose capped-away delivery.
@@ -70,6 +77,7 @@ export function createTerminalRecorder(args) {
70
77
  terminalEvents,
71
78
  interventions,
72
79
  discardedPrefixes,
80
+ participantText,
73
81
  recordLifecycle,
74
82
  recordStreamedTerminalChunk,
75
83
  appendReturnedTerminalOutput,
@@ -46,14 +46,14 @@ export function terminalExecutionFailures(args) {
46
46
  /** The terminal-product lab result for a live run, from its session, cleanup and cost ledger. */
47
47
  export function terminalLabResult(args) {
48
48
  const { cwd, labId, actorId, productName, runId, sessionStatus, completionReason, sessionReason, sessionError, sandboxId, cleanup, cost, noSpendProof, capFailure, declaredScorerFailure, judgment, execution, observer, warnings, } = args;
49
- // The lab's exit code: verified evidence AND no harness error AND proven cleanup. A blocked/
50
- // timed-out agent run is STILL ok-as-evidence at the bundle level (the failure is the evidence),
51
- // but the LAB result surfaces ok:false on a harness error or unproven teardown (fail-closed).
49
+ // The lab's exit code: verified evidence, no harness error and proven cleanup. A blocked/
50
+ // timed-out agent run is still ok-as-evidence at the bundle level (the failure is the evidence),
51
+ // but the lab result surfaces ok:false on a harness error or unproven teardown (fail-closed).
52
52
  // remaining===0 is the by-id-confirmed-reclaimed state; remaining===1 (still present) and
53
53
  // remaining===-1 (kill(id) itself failed) are both unproven by design.
54
54
  const cleanupProven = cleanup.killed && cleanup.remaining === 0;
55
55
  // A CONFIG-DECLARED scorer that failed to render a pass (status:"fail" / malformed / throw) fails the
56
- // run RESULT too, not just the persisted verdict — the keystone lane's declared rubric is a gate, so
56
+ // run result as well as the persisted verdict: the keystone route's declared rubric is a gate, so
57
57
  // its fail must drive exit code. Library callers never set this (additive, back-compat).
58
58
  const ok = resultOk({
59
59
  judgment,