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,1751 +0,0 @@
1
- import { CUA_SPEECH_LIMITS } from "./cua-speech.js";
2
- export { CUA_SPEECH_LIMITS } from "./cua-speech.js";
3
- import { ACTOR_TRACE_SCHEMA } from "./actor-contract.js";
4
- import { CuaProviderError, isCuaProviderError } from "./cua-provider-error.js";
5
- import { classifyCuaAction, summarizeAffordanceUse } from "./affordance.js";
6
- import { commandFailureInfo, isCommandExitError } from "./command-failure.js";
7
- import { evaluateStopWhen } from "./stop-conditions.js";
8
- import { TaskTracker } from "./tasks.js";
9
- import { isCuaAdmissionLimitError } from "./cua-admission-limit.js";
10
- import { CuaExecutorError, isCuaExecutorError } from "./cua-executor-error.js";
11
- export const CUA_PROVIDER_CLEANUP_GRACE_MS = 5000;
12
- /** Runtime validation is also required for third-party provider ports. */
13
- export function validClosingReport(value) {
14
- if (value === null || typeof value !== "object" || Array.isArray(value))
15
- return false;
16
- const report = value;
17
- return Object.keys(report).length === 2
18
- && typeof report.summary === "string" && report.summary.trim().length > 0 && report.summary.length <= 4_000
19
- && Array.isArray(report.frictionReports) && report.frictionReports.length <= 8
20
- && report.frictionReports.every((item) => typeof item === "string" && item.trim().length > 0 && item.length <= 2_000);
21
- }
22
- function validTokenCount(value) {
23
- return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
24
- }
25
- function normalizedUsageTurns(usage) {
26
- if (!Array.isArray(usage.turns) || usage.turns.length === 0)
27
- return undefined;
28
- const fields = ["input", "output", "cachedInput", "cacheWriteInput"];
29
- const turns = [];
30
- for (const raw of usage.turns) {
31
- if (!raw || typeof raw !== "object" || Array.isArray(raw))
32
- return undefined;
33
- if (fields.every(field => raw[field] === undefined) || fields.some(field => raw[field] !== undefined && !validTokenCount(raw[field])))
34
- return undefined;
35
- if ((raw.cachedInput ?? 0) + (raw.cacheWriteInput ?? 0) > (raw.input ?? 0))
36
- return undefined;
37
- turns.push(Object.fromEntries(fields.flatMap(field => raw[field] === undefined ? [] : [[field, raw[field]]])));
38
- }
39
- return fields.every(field => turns.reduce((sum, turn) => sum + (turn[field] ?? 0), 0) === (usage[field] ?? 0))
40
- ? turns : undefined;
41
- }
42
- function completeTurnUsage(usage) {
43
- return usage !== undefined && validTokenCount(usage.input) && validTokenCount(usage.output)
44
- && (usage.cachedInput === undefined || validTokenCount(usage.cachedInput))
45
- && (usage.cacheWriteInput === undefined || validTokenCount(usage.cacheWriteInput))
46
- && (usage.cachedInput ?? 0) + (usage.cacheWriteInput ?? 0) <= usage.input
47
- && (usage.turns === undefined || normalizedUsageTurns(usage) !== undefined);
48
- }
49
- // Waiting is a legitimate strategy, not idleness. A persona told to sign up and verify by email
50
- // polls its inbox — screenshot, wait, screenshot, wait — and at 6 steps that ended the session as
51
- // `gave_up`/`failed` in well under a minute, before the mail could plausibly arrive. The concurrent
52
- // shared-world route already overrode these to 80/40 for exactly this reason; the knowledge existed
53
- // in the codebase and never reached the default every other route uses.
54
- const DEFAULT_IDLE_STEPS = 24;
55
- // The no-progress signal is much stronger since #383 (a stale frame alone no longer counts — the
56
- // actor must also be repeating itself), so this needs less headroom than the raw idle count.
57
- const DEFAULT_NO_PROGRESS_STEPS = 20;
58
- const IDLE_PROGRESS_FORGIVENESS_STEPS = 2;
59
- /** How many recent turns the repetition check looks back over (#383). */
60
- const ACTION_REPEAT_WINDOW = 3;
61
- /** Click/scroll coordinates are bucketed to this many pixels before fingerprinting, so a one-pixel
62
- * jitter between two otherwise identical clicks still reads as the same attempt. */
63
- const ACTION_FINGERPRINT_BUCKET = 24;
64
- /**
65
- * A public-safe fingerprint of ONE turn's actions, used only in memory to tell "trying the same
66
- * thing again" from "trying something new" (#383).
67
- *
68
- * Never includes typed text or key contents — a `type` contributes its LENGTH, exactly as
69
- * describeCuaAction does, so this can never become a keylogger. Coordinates are bucketed so that
70
- * re-clicking the same control counts as a repeat while moving to a different control does not.
71
- */
72
- export function actionFingerprint(actions) {
73
- const bucket = (value) => Math.round(value / ACTION_FINGERPRINT_BUCKET);
74
- return actions
75
- .map((action) => {
76
- switch (action.kind) {
77
- case "click":
78
- case "double_click":
79
- case "move":
80
- return `${action.kind}@${bucket(action.x)},${bucket(action.y)}`;
81
- case "scroll":
82
- return `scroll@${bucket(action.x)},${bucket(action.y)}:${Math.sign(action.dx)},${Math.sign(action.dy)}`;
83
- case "type":
84
- return `type:${action.text.length}`;
85
- case "speak":
86
- return `speak:${action.text.length}`;
87
- case "keypress":
88
- return `keypress:${action.keys.join("+")}`;
89
- case "drag":
90
- return `drag:${action.path.length}`;
91
- case "wait":
92
- return "wait";
93
- case "screenshot":
94
- return "screenshot";
95
- }
96
- })
97
- .join("|");
98
- }
99
- function isIdleAction(action) {
100
- return action.kind === "screenshot" || action.kind === "wait";
101
- }
102
- function isIdleTurn(actions) {
103
- return actions.length === 0 || actions.every(isIdleAction);
104
- }
105
- // Caps for stableProgressKey. The progress key is a coarse turn-over-turn comparison input,
106
- // not a faithful serialization, so it bounds depth, breadth, string length, and total output —
107
- // a huge or deeply nested appState can never blow up the comparison or the trace logging in
108
- // tests. The values are deliberately generous (real route/turn/modal projections are tiny) but
109
- // finite.
110
- const STABLE_KEY_MAX_DEPTH = 6;
111
- const STABLE_KEY_MAX_KEYS = 64;
112
- const STABLE_KEY_MAX_ARRAY = 64;
113
- const STABLE_KEY_MAX_STRING = 256;
114
- const STABLE_KEY_MAX_TOTAL = 8192;
115
- /**
116
- * A deterministic, bounded, sorted-key projection of an appState object, used as the friction
117
- * loop's progress key. Two structurally-equal states (regardless of key insertion order) map
118
- * to the SAME string, so key reordering can never fabricate a progress delta; two different
119
- * states map to different strings (within the caps).
120
- *
121
- * Correctness-load-bearing: it MUST NOT throw on a cyclic or huge input. Cycles are detected
122
- * with a seen-set (a back-edge degrades to the marker "[Circular]"); depth, key count, array
123
- * length, string length, and total output length are all capped so an adversarial or merely
124
- * large appState degrades to a bounded value rather than crashing the loop. Pure: it never
125
- * mutates the input. (See docs/architecture/state-driven-executor.md.)
126
- */
127
- export function stableProgressKey(appState) {
128
- const seen = new Set();
129
- let truncated = false;
130
- const encode = (value, depth) => {
131
- if (truncated)
132
- return '"…"';
133
- if (value === null)
134
- return "null";
135
- const type = typeof value;
136
- if (type === "number")
137
- return Number.isFinite(value) ? JSON.stringify(value) : `"${String(value)}"`;
138
- if (type === "boolean")
139
- return value ? "true" : "false";
140
- if (type === "bigint")
141
- return `"${value.toString()}"`;
142
- if (type === "string") {
143
- const s = value;
144
- return JSON.stringify(s.length > STABLE_KEY_MAX_STRING ? `${s.slice(0, STABLE_KEY_MAX_STRING)}…` : s);
145
- }
146
- if (type === "function" || type === "symbol" || type === "undefined")
147
- return `"[${type}]"`;
148
- // object or array
149
- if (depth >= STABLE_KEY_MAX_DEPTH)
150
- return '"[MaxDepth]"';
151
- if (seen.has(value))
152
- return '"[Circular]"';
153
- seen.add(value);
154
- try {
155
- if (Array.isArray(value)) {
156
- const cap = Math.min(value.length, STABLE_KEY_MAX_ARRAY);
157
- const parts = [];
158
- for (let i = 0; i < cap; i += 1) {
159
- parts.push(encode(value[i], depth + 1));
160
- if (truncated)
161
- break;
162
- }
163
- if (value.length > STABLE_KEY_MAX_ARRAY)
164
- parts.push('"…"');
165
- return `[${parts.join(",")}]`;
166
- }
167
- const record = value;
168
- const keys = Object.keys(record).sort();
169
- const cap = Math.min(keys.length, STABLE_KEY_MAX_KEYS);
170
- const parts = [];
171
- for (let i = 0; i < cap; i += 1) {
172
- const key = keys[i];
173
- parts.push(`${JSON.stringify(key)}:${encode(record[key], depth + 1)}`);
174
- if (truncated)
175
- break;
176
- }
177
- if (keys.length > STABLE_KEY_MAX_KEYS)
178
- parts.push('"…":"…"');
179
- return `{${parts.join(",")}}`;
180
- }
181
- finally {
182
- // Leave the set so sibling subtrees that legitimately repeat a shared reference still
183
- // serialize once per occurrence-path without false "Circular" hits across siblings.
184
- seen.delete(value);
185
- }
186
- };
187
- let out = encode(appState, 0);
188
- if (out.length > STABLE_KEY_MAX_TOTAL) {
189
- truncated = true;
190
- out = `${out.slice(0, STABLE_KEY_MAX_TOTAL)}…`;
191
- }
192
- return out;
193
- }
194
- /** The friction progress key: a stable projection of appState when present, else stateSignature. */
195
- /** Pixels of vertical scroll per progress bucket (#393): a real scroll step (typically >=100px)
196
- * crosses a bucket and counts as progress; sub-bucket jiggle does not, so an actor nudging the
197
- * same dead panel cannot stay "progressing" forever. */
198
- const SCROLL_PROGRESS_BUCKET_PX = 200;
199
- function progressKeyOf(observation) {
200
- const base = observation.appState !== undefined ? stableProgressKey(observation.appState) : observation.stateSignature;
201
- // Scroll position is state (#393): a scroll-pinned section keeps the frame hash constant while
202
- // the participant genuinely advances, so the offset rides the key — bucketed, never raw.
203
- return observation.scrollY === undefined
204
- ? base
205
- : `${base}#s${Math.round(observation.scrollY / SCROLL_PROGRESS_BUCKET_PX)}`;
206
- }
207
- /** A public-safe one-line action label. Never includes raw typed text. */
208
- export function describeCuaAction(action) {
209
- switch (action.kind) {
210
- case "click":
211
- return `click (${action.x}, ${action.y})`;
212
- case "double_click":
213
- return `double-click (${action.x}, ${action.y})`;
214
- case "move":
215
- return `move (${action.x}, ${action.y})`;
216
- case "scroll":
217
- return `scroll (${action.dx}, ${action.dy}) at (${action.x}, ${action.y})`;
218
- case "type":
219
- return `type [${action.text.length} chars]`;
220
- case "speak":
221
- return `speak [${action.text.length} chars]`;
222
- case "keypress":
223
- return `keypress ${action.keys.join("+")}`;
224
- case "drag":
225
- return `drag ${action.path.length} points`;
226
- case "wait":
227
- return action.ms === undefined ? "wait" : `wait ${action.ms}ms`;
228
- case "screenshot":
229
- return "screenshot";
230
- }
231
- }
232
- /** Exported so the participant-vs-harness distinction is pinned directly, not inferred from a run. */
233
- export function statusForCompletionReason(reason) {
234
- switch (reason) {
235
- case "goal_satisfied":
236
- case "turn_completed": // turn_completed is a Codex-lane reason; this loop emits goal_satisfied
237
- return "passed";
238
- // A session that ran out of time or budget did not reach its goal, whatever it achieved along
239
- // the way. Calling that `passed` is how a truncated study came to be reported as a green one —
240
- // and why "raise the timeout" kept landing on the operator instead of on the tool. This switch
241
- // is exhaustive with no default, so a new completion reason forces a compile error here.
242
- case "budget_reached":
243
- return "incomplete";
244
- case "timed_out":
245
- return "timed_out";
246
- case "blocked_approval":
247
- return "blocked";
248
- // A participant who stopped trying is the single most valuable thing a usability study
249
- // produces. Recording it as `failed` said the instrument broke, which is a different claim and
250
- // a false one — see docs/principles/three-roles.md.
251
- case "gave_up":
252
- return "abandoned";
253
- // Only the harness failing is a harness failure.
254
- case "actor_error":
255
- case "step_failed": // step_failed is the scripted-browser lane's reason; this loop never emits it
256
- case "harness_error":
257
- return "failed";
258
- }
259
- }
260
- // Distinct error classes so the loop can tell a deadline/abort apart from a real
261
- // adapter failure when raceSettle rejects.
262
- /**
263
- * Read the fixed closing line the prompt asks for (#570): the FIRST non-empty line of the
264
- * participant's last message, exactly one of three phrases, punctuation and case forgiven. Anything
265
- * else is absence, never a guess. Exported for tests.
266
- */
267
- export function declaredOutcomeFromClosingLine(message) {
268
- if (message === undefined)
269
- return undefined;
270
- const first = message.split(/\r?\n/).map((line) => line.trim()).find((line) => line.length > 0);
271
- if (first === undefined)
272
- return undefined;
273
- const normalized = first.replace(/^[*_#>\s-]+|[*_.!\s]+$/g, "").toLowerCase();
274
- if (normalized === "reached the goal")
275
- return "reached";
276
- if (normalized === "did not reach the goal")
277
- return "not_reached";
278
- if (normalized === "blocked")
279
- return "blocked";
280
- return undefined;
281
- }
282
- class CuaDeadlineError extends Error {
283
- }
284
- class CuaAbortError extends Error {
285
- }
286
- /** A single call outlived its own bound while the session still had budget: a stall, not a deadline. */
287
- class CuaStallError extends Error {
288
- what;
289
- afterMs;
290
- constructor(what, afterMs) {
291
- super(`${what} produced nothing within ${afterMs}ms`);
292
- this.what = what;
293
- this.afterMs = afterMs;
294
- }
295
- }
296
- export const DEFAULT_TURN_TIMEOUT_MS = 180_000;
297
- export const DEFAULT_OBSERVATION_TIMEOUT_MS = 60_000;
298
- // Internal control-flow signal: the per-turn frame guard already set completionReason/reason
299
- // to a structured harness_error; this just unwinds the loop without being misread as an adapter
300
- // failure in the catch block (it carries no message to persist).
301
- class CuaFrameGuardStop extends Error {
302
- }
303
- // Internal control-flow signal for deterministic harness stop conditions that match before the
304
- // model is asked for another turn. completionReason/reason are already set by the caller.
305
- class CuaStopWhenStop extends Error {
306
- }
307
- const neverAbort = new AbortController().signal;
308
- /**
309
- * Wait on a port promise, but stop waiting if the wall-clock budget runs out or
310
- * the caller aborts. The underlying promise may still settle later (a promise
311
- * cannot be force-cancelled); we simply stop blocking the loop on it. An
312
- * already-settled promise always wins, so a fast op is never spuriously failed.
313
- */
314
- /**
315
- * raceSettle with a second, tighter clock: the call's own bound. When the tighter clock wins the
316
- * result is a CuaStallError (the caller decides whether to retry); when the session clock wins it
317
- * stays a CuaDeadlineError, so the existing budget_reached / timed_out reading is untouched.
318
- */
319
- async function raceBounded(what, promise, remainingMs, boundMs, signal) {
320
- const cap = Math.min(remainingMs, boundMs);
321
- const boundWins = boundMs < remainingMs;
322
- try {
323
- return await raceSettle(promise, cap, signal);
324
- }
325
- catch (error) {
326
- if (error instanceof CuaDeadlineError && boundWins)
327
- throw new CuaStallError(what, cap);
328
- throw error;
329
- }
330
- }
331
- function raceSettle(promise, remainingMs, signal) {
332
- if (signal?.aborted) {
333
- return Promise.reject(new CuaAbortError());
334
- }
335
- return new Promise((resolve, reject) => {
336
- let settled = false;
337
- const finish = (apply) => {
338
- if (settled)
339
- return;
340
- settled = true;
341
- clearTimeout(timer);
342
- signal?.removeEventListener("abort", onAbort);
343
- apply();
344
- };
345
- const onAbort = () => finish(() => reject(new CuaAbortError()));
346
- const timer = setTimeout(() => finish(() => reject(new CuaDeadlineError())), Math.max(0, remainingMs));
347
- if (typeof timer.unref === "function")
348
- timer.unref();
349
- signal?.addEventListener("abort", onAbort, { once: true });
350
- promise.then((value) => finish(() => resolve(value)), (error) => finish(() => reject(error)));
351
- });
352
- }
353
- /**
354
- * Drive the computer-use loop to a single explicit completion and return an
355
- * ActorTrace. Every screenshot is redacted through the injected RedactionHooks
356
- * before its ref is recorded, so the trace is public-safe by construction.
357
- */
358
- export async function runComputerUseLoop(options) {
359
- if (options.provider.executionProfile?.billing === "account-unknown" &&
360
- (options.maxUsd !== undefined || options.overRunBudget !== undefined || options.estimateTurnCostUsd !== undefined ||
361
- options.provider.modelSettings?.maxOutputTokens !== undefined)) {
362
- throw new CuaProviderError("request_rejected", { dispatched: false, usageComplete: false, cleanup: "confirmed" });
363
- }
364
- const { instructions, provider, executor, persona, redaction, timeoutMs, now, signal, idleSteps = DEFAULT_IDLE_STEPS, noProgressSteps = DEFAULT_NO_PROGRESS_STEPS, acknowledgeSafetyChecks = () => null, redactScreenshots = false, scrubText = (text) => text, writeScreenshot = async (name) => `screenshots/${name}`, stopWhen, dwell, sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)), tasks, maxUsd, overRunBudget, estimateTurnCostUsd, requireReportedUsageForSpendCap = false, onObservedUrl, onMessage, onScreenshot, onTrace } = options;
365
- const noProgressRecoverySteps = Math.min(Math.max(1, noProgressSteps - 1), 3);
366
- const idleRecoverySteps = Math.min(Math.max(1, idleSteps - 1), 3);
367
- // Model-authored narration: literal-scrub known provisioned values, THEN pattern-redact.
368
- // A value the model transcribes (a DB password it read on screen) has no shape, so redactText
369
- // alone cannot catch it — the lab's scrubKnownValues, injected as scrubText, closes that.
370
- const redactNarration = (text) => redaction.redactText(scrubText(text));
371
- const startedAtMs = now();
372
- const remaining = () => timeoutMs - (now() - startedAtMs);
373
- const turnTimeoutMs = options.turnTimeoutMs ?? DEFAULT_TURN_TIMEOUT_MS;
374
- const observationTimeoutMs = options.observationTimeoutMs ?? DEFAULT_OBSERVATION_TIMEOUT_MS;
375
- const items = [];
376
- const providerRequests = [];
377
- let providerCleanupUnconfirmed = false;
378
- const liveMetadata = () => ({
379
- ...(provider.executionProfile === undefined ? {} : { executionProfile: provider.executionProfile }),
380
- ...(provider.requestPolicy === "fail_closed" ? { providerRequests: providerRequests.map(row => ({ ...row })),
381
- historyTurnsOmitted: provider.historyTurnsOmitted ?? 0 } : {})
382
- });
383
- const flushTrace = () => onTrace?.(items.slice(), runningUsage(), liveMetadata());
384
- // The ONE recording choke point (#441): every trace item is stamped `at` from the
385
- // loop's injected clock as it is recorded, so timed playback reads recorded facts
386
- // (deterministic in tests via the injected `now`).
387
- const record = (item) => {
388
- items.push({ ...item, at: new Date(now()).toISOString() });
389
- };
390
- // Affordance classification (#369): WHICH route the actor took, recorded per dispatched action.
391
- // Collected here because the typed text exists only at dispatch — describeCuaAction deliberately
392
- // destroys it before it can reach the trace. Only the CLASS (and a scheme-shaped signal) is kept.
393
- const affordanceObservations = [];
394
- const counts = {
395
- turns: 0,
396
- actions: 0,
397
- materialActions: 0,
398
- screenshots: 0,
399
- reasonings: 0,
400
- messages: 0,
401
- idleTurns: 0,
402
- noProgressTurns: 0
403
- };
404
- // The last few turns' action fingerprints, in memory only, for the #383 corroboration rule.
405
- const recentFingerprints = [];
406
- // Productivity signal for the wall-clock deadline: a session that took at least one material
407
- // (non-idle) action before the cap reached its BUDGET rather than stalling. A deadline hit with
408
- // zero material actions is still an honest failure (timed_out). Kept beside counts.materialActions
409
- // so the evidence self-describes the distinction.
410
- let materialActions = 0;
411
- let interruptedActionOutcome = false;
412
- let seq = 0;
413
- let usageInput = 0;
414
- let usageCachedInput = 0;
415
- let usageCacheWriteInput = 0;
416
- let usageOutput = 0;
417
- let sawUsage = false;
418
- let incompleteInteractionUsage = false;
419
- let unreportedInteractionUsage = false;
420
- let interactionRequestPending = false;
421
- // Per model-inference usage, in order (#334): the recorded fact long-context pricing tiers
422
- // need. A continuing native tool interaction may contain several inference requests.
423
- const usageTurns = [];
424
- const knownPendingUsage = () => {
425
- const usage = interactionRequestPending ? provider.pendingRequestUsage : undefined;
426
- if (!completeTurnUsage(usage))
427
- return undefined;
428
- const turns = usage.turns === undefined ? undefined : normalizedUsageTurns(usage);
429
- return { input: usage.input, output: usage.output,
430
- ...(usage.cachedInput === undefined ? {} : { cachedInput: usage.cachedInput }),
431
- ...(usage.cacheWriteInput === undefined ? {} : { cacheWriteInput: usage.cacheWriteInput }),
432
- ...(turns === undefined ? {} : { turns }) };
433
- };
434
- const withPendingUsage = (settled) => {
435
- const pendingUsage = knownPendingUsage();
436
- if (pendingUsage === undefined)
437
- return settled;
438
- const input = (settled.input ?? 0) + pendingUsage.input;
439
- const output = (settled.output ?? 0) + pendingUsage.output;
440
- return {
441
- ...settled,
442
- input,
443
- output,
444
- ...((settled.cachedInput !== undefined || pendingUsage.cachedInput !== undefined)
445
- ? { cachedInput: (settled.cachedInput ?? 0) + (pendingUsage.cachedInput ?? 0) } : {}),
446
- ...((settled.cacheWriteInput !== undefined || pendingUsage.cacheWriteInput !== undefined)
447
- ? { cacheWriteInput: (settled.cacheWriteInput ?? 0) + (pendingUsage.cacheWriteInput ?? 0) } : {}),
448
- turns: [...(settled.turns ?? []), ...(pendingUsage.turns ?? [{ input: pendingUsage.input, output: pendingUsage.output,
449
- ...(pendingUsage.cachedInput === undefined ? {} : { cachedInput: pendingUsage.cachedInput }),
450
- ...(pendingUsage.cacheWriteInput === undefined ? {} : { cacheWriteInput: pendingUsage.cacheWriteInput }) }])],
451
- ...(settled.total === undefined ? {} : { total: input + output })
452
- };
453
- };
454
- // The running usage snapshot both spend guards consume: totals plus the per-request ledger,
455
- // shaped exactly like the trace's final tokenUsage so one estimator prices both identically.
456
- // Unlike the persisted trace (where absent means "unreported"), this runtime callback arg
457
- // ALWAYS carries numeric cache fields: pre-#334 guards received an object whose cachedInput
458
- // was always a number (0 included), and arithmetic on a suddenly-undefined field yields NaN —
459
- // which comparison operators swallow silently (red-team finding: a stale study-budget guard
460
- // would run uncapped without a sound).
461
- const accountUsage = () => ({
462
- ...(usageTurns.some(t => t.input !== undefined) ? { input: usageInput } : {}),
463
- ...(usageTurns.some(t => t.output !== undefined) ? { output: usageOutput } : {}),
464
- ...(usageTurns.some(t => t.cachedInput !== undefined) ? { cachedInput: usageCachedInput } : {}),
465
- ...(usageTurns.some(t => t.cacheWriteInput !== undefined) ? { cacheWriteInput: usageCacheWriteInput } : {}),
466
- ...(usageTurns.length > 0 ? { turns: usageTurns.map(t => ({ ...t })) } : {}),
467
- ...(providerRequests.length > 0 && providerRequests.every(r => r.usageComplete && completeTurnUsage(r.usage))
468
- ? { total: usageInput + usageOutput } : {})
469
- });
470
- const runningUsage = () => withPendingUsage(provider.executionProfile?.billing === "account-unknown" ? accountUsage() : ({
471
- input: usageInput,
472
- output: usageOutput,
473
- cachedInput: usageCachedInput,
474
- cacheWriteInput: usageCacheWriteInput,
475
- ...(usageTurns.length > 0 ? { turns: usageTurns } : {})
476
- }));
477
- const hasUnreportedInteractionUsage = () => unreportedInteractionUsage || provider.interactionUsageIncomplete === true;
478
- const usageUnavailableForCap = () => incompleteInteractionUsage || unreportedInteractionUsage ||
479
- (interactionRequestPending ? knownPendingUsage() === undefined : provider.interactionUsageIncomplete === true);
480
- let lastResponseId;
481
- let currentPhase = "initializing computer-use loop";
482
- let lastActionTitle;
483
- let lastMaterialActionTitle;
484
- let lastScreenshotRef;
485
- const recentActionTitles = [];
486
- const nextId = (kind) => `${kind}-${(seq += 1).toString().padStart(3, "0")}`;
487
- const bump = (key) => {
488
- counts[key] = (counts[key] ?? 0) + 1;
489
- };
490
- const recordUsage = (turn, interaction = true) => {
491
- if (turn.providerRequestPending === true)
492
- return;
493
- const raw = turn.usage;
494
- const turns = raw?.turns === undefined ? undefined : normalizedUsageTurns(raw);
495
- if (interaction && (!completeTurnUsage(raw) || turn.providerRequest?.usageComplete === false))
496
- incompleteInteractionUsage = true;
497
- if (interaction && raw?.turns !== undefined && turns === undefined)
498
- unreportedInteractionUsage = true;
499
- if (raw === undefined)
500
- return;
501
- const usage = {
502
- ...(validTokenCount(raw.input) ? { input: raw.input } : {}),
503
- ...(validTokenCount(raw.output) ? { output: raw.output } : {}),
504
- ...(validTokenCount(raw.cachedInput) ? { cachedInput: raw.cachedInput } : {}),
505
- ...(validTokenCount(raw.cacheWriteInput) ? { cacheWriteInput: raw.cacheWriteInput } : {})
506
- };
507
- if (Object.keys(usage).length === 0)
508
- return;
509
- sawUsage = true;
510
- usageInput += usage.input ?? 0;
511
- usageCachedInput += usage.cachedInput ?? 0;
512
- usageCacheWriteInput += usage.cacheWriteInput ?? 0;
513
- usageOutput += usage.output ?? 0;
514
- if (raw.turns === undefined)
515
- usageTurns.push(usage);
516
- else if (turns !== undefined)
517
- usageTurns.push(...turns);
518
- };
519
- /** Marked providers own one attempt through settlement; an outer race never retries it. */
520
- const markedRequest = async (request, kind, capMs) => {
521
- const controller = new AbortController();
522
- const onAbort = () => controller.abort();
523
- if (signal?.aborted)
524
- controller.abort();
525
- else
526
- signal?.addEventListener("abort", onAbort, { once: true });
527
- let settlement;
528
- let failure;
529
- let failed = false;
530
- let accepted;
531
- let pendingYield = false;
532
- const pending = Promise.resolve().then(() => {
533
- if (controller.signal.aborted)
534
- throw new CuaProviderError("cancelled", { dispatched: false, usageComplete: false, cleanup: "confirmed" });
535
- return kind === "debrief" ? provider.debrief(request, controller.signal) : provider.nextTurn(request, controller.signal);
536
- }).then(turn => { settlement = { turn }; return turn; }, (error) => { settlement = { error }; throw error; });
537
- void pending.catch(() => undefined);
538
- try {
539
- accepted = await raceBounded(`participant ${kind}`, pending, remaining(), capMs, signal);
540
- if (accepted.providerRequestPending === true) {
541
- if (kind !== "interaction" || accepted.done || accepted.actions.length === 0 || accepted.pendingSafetyChecks.length > 0 ||
542
- accepted.providerRequest !== undefined || accepted.usage !== undefined || accepted.interruption !== undefined || accepted.closingReport !== undefined) {
543
- throw new CuaProviderError("invalid_response", { dispatched: "unknown", usageComplete: false, cleanup: "unconfirmed" });
544
- }
545
- pendingYield = true;
546
- }
547
- else {
548
- const r = accepted.providerRequest;
549
- if (!r || r.dispatched !== true || typeof r.usageComplete !== "boolean" || r.cleanup !== "confirmed") {
550
- throw new CuaProviderError("invalid_response", { dispatched: "unknown", usageComplete: false, cleanup: "unconfirmed" }, accepted.usage);
551
- }
552
- }
553
- }
554
- catch (error) {
555
- failed = true;
556
- failure = error;
557
- }
558
- finally {
559
- controller.abort();
560
- signal?.removeEventListener("abort", onAbort);
561
- if (settlement === undefined) {
562
- let timer;
563
- try {
564
- await Promise.race([pending.catch(() => undefined), new Promise(resolve => {
565
- timer = setTimeout(resolve, CUA_PROVIDER_CLEANUP_GRACE_MS);
566
- })]);
567
- }
568
- finally {
569
- clearTimeout(timer);
570
- }
571
- }
572
- }
573
- if (!failed && pendingYield) {
574
- interactionRequestPending = true;
575
- return accepted;
576
- }
577
- const final = settlement;
578
- const typed = isCuaProviderError(failure) ? failure : final && "error" in final && isCuaProviderError(final.error) ? final.error : undefined;
579
- const turn = final && "turn" in final ? final.turn : undefined;
580
- const raw = typed?.receipt ?? turn?.providerRequest;
581
- const receipt = raw && (typeof raw.dispatched === "boolean" || raw.dispatched === "unknown") &&
582
- typeof raw.usageComplete === "boolean" && ["confirmed", "unconfirmed"].includes(raw.cleanup) ? { dispatched: raw.dispatched, usageComplete: raw.usageComplete, cleanup: raw.cleanup }
583
- : { dispatched: "unknown", usageComplete: false, cleanup: "unconfirmed" };
584
- const rawUsage = typed?.usage ?? (turn?.providerRequestPending === true ? undefined : turn?.usage);
585
- const usage = rawUsage === undefined ? undefined : Object.fromEntries(["input", "output", "cachedInput", "cacheWriteInput", "total"].flatMap(key => {
586
- const value = rawUsage[key];
587
- return validTokenCount(value) ? [[key, value]] : [];
588
- }));
589
- // restricted-codex-session sets dispatched only after initialize/config/account/
590
- // thread/MCP admission, immediately before turn/start; it is not a success claim.
591
- const settledKind = interactionRequestPending ? "interaction" : kind;
592
- providerRequests.push({ ordinal: providerRequests.length + 1, kind: settledKind, ...receipt,
593
- profileVerified: provider.executionProfile !== undefined && receipt.dispatched === true,
594
- ...(typed ? { errorCode: typed.code, ...(typed.failurePhase === undefined ? {} : { failurePhase: typed.failurePhase }) } : {}),
595
- ...(usage === undefined ? {} : { usage: { ...usage } }) });
596
- if (receipt.cleanup !== "confirmed") {
597
- providerCleanupUnconfirmed = true;
598
- record({ id: nextId("notice"), kind: "notice", lifecycle: "completed", status: "error",
599
- title: "participant request cleanup unconfirmed", text: "The request did not confirm cleanup within the settlement boundary. No further participant request or action is admitted." });
600
- }
601
- if (settledKind === "interaction" && receipt.dispatched !== false && (!receipt.usageComplete || !completeTurnUsage(usage)))
602
- unreportedInteractionUsage = true;
603
- interactionRequestPending = false;
604
- if (failed) {
605
- if (usage)
606
- recordUsage({ actions: [], pendingSafetyChecks: [], done: false, usage, providerRequest: receipt }, settledKind === "interaction");
607
- if (failure instanceof CuaAbortError || failure instanceof CuaDeadlineError)
608
- throw failure;
609
- if (failure instanceof CuaStallError)
610
- throw new CuaProviderError("timeout", receipt, usage, typed?.failurePhase);
611
- throw typed ?? new CuaProviderError("process_failed", receipt, usage);
612
- }
613
- return accepted;
614
- };
615
- // Whether any observation this run surfaced structured appState (a non-vision/state executor).
616
- // RUNTIME-ONLY signal: used solely to self-describe in redaction.notes that app state drove
617
- // progress detection and was NOT written to the trace — the appState itself never persists.
618
- let observedAppState = false;
619
- // Guarded screenshot persistence: a non-vision executor returns an observation with no
620
- // screenshot, and the loop persists none that turn (counts.screenshots stays 0 → the existing
621
- // "n/a" branch resolves redaction.screenshots). No Buffer.alloc(0) ever reaches disk.
622
- const maybeRecordScreenshot = async (observation, label) => {
623
- const frame = observation.screenshot;
624
- if (frame === undefined)
625
- return;
626
- currentPhase = `writing screenshot ${label}`;
627
- // Default: persist the raw frame (full fidelity, local-only). redactScreenshots flips to the
628
- // publish-safe blurred thumbnail. Either way the bytes the model already saw were raw.
629
- const { bytes, method } = redactScreenshots
630
- ? await redaction.redactScreenshot(frame, { label }).then((r) => ({ bytes: r.buffer, method: r.method }))
631
- : { bytes: frame, method: "none" };
632
- const path = await writeScreenshot(`${label}.png`, bytes);
633
- const screenshotRef = { path, redaction: method };
634
- lastScreenshotRef = screenshotRef;
635
- record({
636
- id: nextId("screenshot"),
637
- kind: "screenshot",
638
- lifecycle: "completed",
639
- title: label,
640
- screenshotRef
641
- });
642
- bump("screenshots");
643
- };
644
- // One projection feeds BOTH the stop guard and the task tracker, so a criterion that would stop
645
- // the run and a criterion that completes a task can never see different evidence for one turn.
646
- const stopObservationOf = (observation) => ({
647
- ...(observation.url === undefined ? {} : { url: observation.url }),
648
- ...(observation.text === undefined ? {} : { text: observation.text }),
649
- ...(observation.appState === undefined ? {} : { appState: observation.appState })
650
- });
651
- const matchedStopWhen = (observation) => evaluateStopWhen(stopWhen, stopObservationOf(observation));
652
- // The funnel is recorded, never consulted: task completion does not steer the loop. Evaluated
653
- // BEFORE the stopWhen check each turn so a final task whose criterion coincides with the stop
654
- // condition still lands in the funnel of the very turn that ends the session.
655
- const taskTracker = tasks !== undefined && tasks.length > 0 ? new TaskTracker(tasks) : undefined;
656
- const observeTasks = (observation, turn) => {
657
- if (taskTracker === undefined)
658
- return;
659
- for (const completion of taskTracker.observe(stopObservationOf(observation), turn)) {
660
- // The id is researcher-authored config and the kinds are rule-type names; the matched VALUES
661
- // (a URL, page text) never appear here — the same discipline as stopWhenTraceItem.
662
- record({
663
- id: nextId("notice"),
664
- kind: "notice",
665
- lifecycle: "completed",
666
- status: "matched",
667
- title: `task completed: ${redactNarration(completion.id)}`,
668
- text: redactNarration(`turn ${turn}; matched rule ${completion.matchedRuleIndex} (${completion.matchedKinds.join("+")})`)
669
- });
670
- }
671
- };
672
- let completionReason = "goal_satisfied";
673
- let stopCause;
674
- let declaredOutcome;
675
- let reason = "computer-use loop completed";
676
- let stopConditionMatch;
677
- const stopForAdmissionLimit = () => {
678
- completionReason = "budget_reached";
679
- stopCause = "adapter_limit";
680
- reason = "the adapter reported a local admission limit before provider dispatch; the participant did not report completion. No actions or closing request followed the refusal.";
681
- record({ id: nextId("notice"), kind: "notice", lifecycle: "completed", status: "warn",
682
- title: "adapter admission limit reached", text: reason });
683
- };
684
- const requiresUsage = requireReportedUsageForSpendCap && (maxUsd !== undefined || overRunBudget !== undefined);
685
- const stopForUnreportedUsage = () => {
686
- unreportedInteractionUsage = true;
687
- completionReason = "harness_error";
688
- stopCause = "usage_unreported";
689
- reason = "provider usage is unavailable for a request, so the declared model-spend cap cannot be established; no further participant or closing request was dispatched";
690
- record({ id: nextId("notice"), kind: "notice", lifecycle: "completed", status: "error",
691
- title: "provider usage unavailable", text: reason });
692
- };
693
- // A vision provider against a screenshot-less observation is a fail-closed harness error, not
694
- // a silent crash: record it and break. Returns true when the run must stop. (The provider sets
695
- // requiresFrame; a state-reasoning provider omits it.)
696
- const frameGuardTripped = (observation) => {
697
- if (provider.requiresFrame === true && observation.screenshot === undefined) {
698
- completionReason = "harness_error";
699
- reason = `provider ${provider.id} requires a screenshot frame but the executor returned an observation with no screenshot (vision provider against a state-only executor)`;
700
- return true;
701
- }
702
- return false;
703
- };
704
- // Loop-local state. Declared here (before the try) so the initial observe + the per-turn
705
- // frame guard can fail closed cleanly while these still scope across the loop.
706
- let previousResponseId;
707
- let previousExecution;
708
- let closingObservation;
709
- let closingTrigger;
710
- let debrief;
711
- let consecutiveIdle = 0;
712
- // One canonical "no progress" signal: turns that did not change the UI state
713
- // signature (idle or not). The nudge, the stop threshold, and the reason all
714
- // key off this counter, and it catches alternating idle/no-progress stalls
715
- // that two separate counters would let slip past every backstop but the clock.
716
- let consecutiveNoProgress = 0;
717
- let lastSignature = "";
718
- let contextHint;
719
- let idleProgressForgivenessUsed = 0;
720
- // Acks granted for the previous turn's safety checks. They must ride the
721
- // NEXT request (the one carrying that call's computer_call_output), so they
722
- // are staged here rather than written onto the request already sent.
723
- let pendingAcks;
724
- try {
725
- currentPhase = "observing initial UI state";
726
- // Legacy executors retry a stalled observe once (#480). A transport that cannot safely
727
- // replay pending requests opts out, so even a shorter outer bound stops without retrying.
728
- const observeBounded = async (label) => {
729
- try {
730
- return await raceBounded(`observe (${label})`, executor.observe(), remaining(), observationTimeoutMs, signal);
731
- }
732
- catch (error) {
733
- if (!(error instanceof CuaStallError))
734
- throw error;
735
- if (executor.stallRecovery === "fail_closed") {
736
- // The outer bound says nothing about whether the still-pending request completed.
737
- // The owning session will close it; this loop must not send a replacement request.
738
- throw new CuaExecutorError("deadline_exceeded", "outcome_uncertain");
739
- }
740
- record({
741
- id: nextId("notice"),
742
- kind: "notice",
743
- lifecycle: "completed",
744
- status: "warn",
745
- title: "observation stalled; retrying once",
746
- text: `${error.what} produced nothing within ${error.afterMs}ms; asking the desktop again`
747
- });
748
- return await raceBounded(`observe (${label}, retry)`, executor.observe(), remaining(), observationTimeoutMs, signal);
749
- }
750
- };
751
- const seenSpeechIds = new Set();
752
- let pendingHeardSpeech = [];
753
- let heardSpeechChanged = false;
754
- const collectHeardSpeech = (value) => {
755
- for (const utterance of value.heardSpeech ?? []) {
756
- if (seenSpeechIds.has(utterance.id))
757
- continue;
758
- seenSpeechIds.add(utterance.id);
759
- pendingHeardSpeech.push(utterance);
760
- heardSpeechChanged = true;
761
- record({ id: nextId("notice"), kind: "notice", lifecycle: "completed", status: "ok",
762
- title: "speech heard", text: redactNarration(utterance.text) });
763
- }
764
- if (pendingHeardSpeech.length > CUA_SPEECH_LIMITS.utterances) {
765
- throw new CuaExecutorError("invalid_response", "outcome_uncertain");
766
- }
767
- return pendingHeardSpeech.length === 0 ? value : { ...value, heardSpeech: pendingHeardSpeech.slice() };
768
- };
769
- // The declared observation window (#510). The harness holds, looks, and takes nothing back to
770
- // the model: no action, no turn, no tokens. It runs once, cut to whatever session budget is
771
- // left, and says in the trace that the time was deliberate.
772
- let dwellDone = false;
773
- let dwellHeldMs = 0;
774
- const dwellIfDue = async (observation, turnNumber) => {
775
- if (dwell === undefined || dwellDone)
776
- return undefined;
777
- if (dwell.when !== undefined && evaluateStopWhen(dwell.when, stopObservationOf(observation)) === undefined)
778
- return undefined;
779
- dwellDone = true;
780
- const trigger = dwell.when === undefined ? "at the start" : "its condition matched";
781
- const budget = Math.min(dwell.ms, Math.max(0, remaining() - dwell.everyMs));
782
- if (budget < dwell.everyMs) {
783
- record({
784
- id: nextId("notice"),
785
- kind: "notice",
786
- lifecycle: "completed",
787
- status: "warn",
788
- title: "dwell window skipped",
789
- text: `${trigger} at turn ${turnNumber}, but only ${Math.max(0, remaining())}ms of session budget remained for a ${dwell.ms}ms window`
790
- });
791
- return undefined;
792
- }
793
- const dwellStartedAtMs = now();
794
- record({
795
- id: nextId("notice"),
796
- kind: "notice",
797
- lifecycle: "started",
798
- title: "dwell window started",
799
- text: `${trigger} at turn ${turnNumber}: holding ${budget}ms, a frame every ${dwell.everyMs}ms, no actions, no model turns`
800
- });
801
- let frames = 0;
802
- while (now() - dwellStartedAtMs < budget) {
803
- if (signal?.aborted)
804
- throw new CuaAbortError();
805
- await sleep(Math.min(dwell.everyMs, budget - (now() - dwellStartedAtMs)));
806
- currentPhase = `dwell frame ${frames + 1}`;
807
- const frameObservation = collectHeardSpeech(await observeBounded(`dwell frame ${frames + 1}`));
808
- frames += 1;
809
- if (frameObservation.screenshot !== undefined)
810
- onScreenshot?.(frameObservation.screenshot);
811
- await maybeRecordScreenshot(frameObservation, `dwell-${frames.toString().padStart(2, "0")}`);
812
- flushTrace();
813
- observeTasks(frameObservation, turnNumber);
814
- }
815
- dwellHeldMs = now() - dwellStartedAtMs;
816
- record({
817
- id: nextId("notice"),
818
- kind: "notice",
819
- lifecycle: "completed",
820
- // A window that ENDS the session is structured, harness-owned completion evidence, the
821
- // same class as a matched stopWhen, and the verdict resolver reads it that way.
822
- status: dwell.then === "stop" ? "matched" : "ok",
823
- title: "dwell window complete",
824
- text: `${frames} frame(s) over ${dwellHeldMs}ms; no model turn was requested during the window`
825
- });
826
- if (dwell.then === "stop")
827
- return "stop";
828
- contextHint = `The study held this page under observation for ${Math.round(dwellHeldMs / 1000)} seconds (a declared dwell window; you took no actions in that time). Continue the mission from the current state of the page.`;
829
- return "continue";
830
- };
831
- let observation = collectHeardSpeech(await observeBounded("initial"));
832
- // Runtime-only: hand the seat's live location.href back to the orchestrator (never persisted).
833
- onObservedUrl?.(observation.url);
834
- if (observation.screenshot !== undefined)
835
- onScreenshot?.(observation.screenshot);
836
- if (observation.appState !== undefined)
837
- observedAppState = true;
838
- // Fail closed BEFORE the first turn if a vision provider got a screenshot-less observation.
839
- if (frameGuardTripped(observation))
840
- throw new CuaFrameGuardStop();
841
- await maybeRecordScreenshot(observation, "turn-00-start");
842
- flushTrace();
843
- observeTasks(observation, 0);
844
- const initialDwell = await dwellIfDue(observation, 0);
845
- if (initialDwell !== undefined) {
846
- observation = collectHeardSpeech(await observeBounded("after dwell"));
847
- onObservedUrl?.(observation.url);
848
- if (observation.screenshot !== undefined)
849
- onScreenshot?.(observation.screenshot);
850
- await maybeRecordScreenshot(observation, "turn-00-after-dwell");
851
- observeTasks(observation, 0);
852
- if (initialDwell === "stop") {
853
- completionReason = "goal_satisfied";
854
- reason = `dwell window complete (${dwellHeldMs}ms held at the start)`;
855
- closingObservation = observation;
856
- closingTrigger = "dwell";
857
- throw new CuaStopWhenStop();
858
- }
859
- }
860
- stopConditionMatch = matchedStopWhen(observation);
861
- if (stopConditionMatch) {
862
- completionReason = "goal_satisfied";
863
- reason = stopWhenReason(stopConditionMatch);
864
- closingObservation = observation;
865
- closingTrigger = "stop_when";
866
- record(stopWhenTraceItem(nextId("notice"), stopConditionMatch, redactNarration));
867
- throw new CuaStopWhenStop();
868
- }
869
- // The progress key prefers a stable appState projection (route/turn/modal deltas drive
870
- // progress) and falls back to the executor's stateSignature — so a state executor with a
871
- // constant signature still registers progress, and a vision executor behaves exactly as before.
872
- lastSignature = progressKeyOf(observation);
873
- // Bounded by wall-clock and the friction backstops, never a turn count.
874
- for (;;) {
875
- if (signal?.aborted) {
876
- completionReason = "harness_error";
877
- reason = "run aborted by the harness";
878
- stopCause = "harness_aborted";
879
- break;
880
- }
881
- if (now() - startedAtMs > timeoutMs) {
882
- stopCause = "time_limit";
883
- if (materialActions > 0) {
884
- completionReason = "budget_reached";
885
- reason = `reached the ${timeoutMs}ms time budget after productive activity (${materialActions} material action(s), ${counts.turns} turn(s))`;
886
- }
887
- else {
888
- completionReason = "timed_out";
889
- reason = `wall-clock deadline reached after ${timeoutMs}ms with no material progress`;
890
- }
891
- break;
892
- }
893
- const turnNumber = (counts.turns ?? 0) + 1;
894
- const request = { instructions, observation, ...(provider.requestPolicy !== "fail_closed" || previousExecution === undefined ? {} : { previousExecution }) };
895
- if (previousResponseId !== undefined)
896
- request.previousResponseId = previousResponseId;
897
- if (contextHint !== undefined)
898
- request.contextHint = contextHint;
899
- if (pendingAcks !== undefined)
900
- request.acknowledgedSafetyChecks = pendingAcks;
901
- contextHint = undefined;
902
- pendingAcks = undefined;
903
- currentPhase = `requesting provider turn ${turnNumber}`;
904
- // Bounded per call (#469): one hung request used to be indistinguishable from thinking
905
- // and cost the lane its whole remaining budget. One retry with a notice; then the lane ends
906
- // as harness_error, named, instead of thirty silent minutes.
907
- let turn;
908
- // A timeout race alone does not cancel its losing provider promise. Strict accounting
909
- // owns this signal so a delayed transport failure cannot retry after the loop has ended.
910
- if (provider.requestPolicy === "fail_closed") {
911
- turn = await markedRequest(request, "interaction", turnTimeoutMs);
912
- }
913
- else {
914
- const requestController = requiresUsage ? new AbortController() : undefined;
915
- const onRequestAbort = () => requestController?.abort();
916
- if (requestController) {
917
- if (signal?.aborted)
918
- requestController.abort();
919
- else
920
- signal?.addEventListener("abort", onRequestAbort, { once: true });
921
- }
922
- const requestSignal = requestController?.signal ?? signal ?? neverAbort;
923
- try {
924
- turn = await raceBounded(`provider turn ${turnNumber}`, provider.nextTurn(request, requestSignal), remaining(), turnTimeoutMs, signal);
925
- }
926
- catch (error) {
927
- if (isCuaAdmissionLimitError(error)) {
928
- stopForAdmissionLimit();
929
- break;
930
- }
931
- // A thrown request may have been billed without returning usage. Admission refusal is
932
- // the explicit no-dispatch exception above; strict capped routes cannot safely retry.
933
- if (requiresUsage) {
934
- stopForUnreportedUsage();
935
- break;
936
- }
937
- if (!(error instanceof CuaStallError))
938
- throw error;
939
- unreportedInteractionUsage = true;
940
- record({
941
- id: nextId("notice"),
942
- kind: "notice",
943
- lifecycle: "completed",
944
- status: "warn",
945
- title: "provider turn stalled; retrying once",
946
- text: `${error.what} produced nothing within ${error.afterMs}ms; sending the same observation again`
947
- });
948
- try {
949
- turn = await raceBounded(`provider turn ${turnNumber} (retry)`, provider.nextTurn(request, signal ?? neverAbort), remaining(), turnTimeoutMs, signal);
950
- }
951
- catch (retryError) {
952
- if (isCuaAdmissionLimitError(retryError)) {
953
- stopForAdmissionLimit();
954
- break;
955
- }
956
- if (!(retryError instanceof CuaStallError))
957
- throw retryError;
958
- unreportedInteractionUsage = true;
959
- completionReason = "harness_error";
960
- reason = `provider turn ${turnNumber} stalled twice (${retryError.afterMs}ms each); the model produced no turn and the lane was ended rather than left to run out its budget`;
961
- record({
962
- id: nextId("notice"),
963
- kind: "notice",
964
- lifecycle: "completed",
965
- status: "error",
966
- title: "provider turn stalled twice",
967
- text: reason
968
- });
969
- break;
970
- }
971
- }
972
- finally {
973
- if (requestController)
974
- signal?.removeEventListener("abort", onRequestAbort);
975
- requestController?.abort();
976
- }
977
- }
978
- if (request.contextHint)
979
- record({ id: nextId("notice"), kind: "notice", title: "Participant context hint", text: redactNarration(request.contextHint), lifecycle: "completed" });
980
- bump("turns");
981
- pendingHeardSpeech = [];
982
- heardSpeechChanged = false;
983
- previousResponseId = turn.responseId ?? previousResponseId;
984
- lastResponseId = turn.responseId ?? lastResponseId;
985
- recordUsage(turn);
986
- // A host-authenticated provider may learn its account billing class during
987
- // startup. Never price that account usage from an API model rate.
988
- if (provider.executionProfile?.billing === "account-unknown" &&
989
- (maxUsd !== undefined || overRunBudget !== undefined || estimateTurnCostUsd !== undefined)) {
990
- completionReason = "harness_error";
991
- reason = "Codex is using a ChatGPT account; API dollar caps cannot bound account usage. Use a finite timeout or the OpenAI API participant.";
992
- break;
993
- }
994
- if (turn.interruption !== undefined) {
995
- // A provider can exhaust its response budget before producing visible text, or midway
996
- // through an action. Preserve usage and partial narration, but never interpret either as
997
- // participant completion or dispatch actions from an explicitly incomplete response.
998
- overRunBudget?.(runningUsage());
999
- if (turn.reasoning) {
1000
- record({ id: nextId("reasoning"), kind: "reasoning", lifecycle: "completed", status: "warn",
1001
- title: `incomplete reasoning turn ${turnNumber}`, text: redactNarration(turn.reasoning) });
1002
- bump("reasonings");
1003
- }
1004
- if (turn.message) {
1005
- record({ id: nextId("message"), kind: "message", lifecycle: "completed", status: "warn",
1006
- title: `incomplete message turn ${turnNumber}`, text: redactNarration(turn.message) });
1007
- bump("messages");
1008
- }
1009
- const tokenLimit = turn.interruption === "token_limit" || turn.interruption === "output_limit";
1010
- stopCause = turn.interruption === "output_limit" ? "provider_output_limit"
1011
- : tokenLimit ? "provider_token_limit" : turn.interruption === "unexpected_status" ? "provider_status" : "provider_incomplete";
1012
- const unexpectedStatus = turn.interruption === "unexpected_status";
1013
- completionReason = tokenLimit ? "budget_reached" : "harness_error";
1014
- reason = tokenLimit
1015
- ? "the provider's output/context token limit interrupted this response; the participant did not report completion. No actions or closing request followed the incomplete response."
1016
- : unexpectedStatus
1017
- ? "the provider returned an unexpected noncompleted response status; the participant did not report completion. No actions or closing request followed this response."
1018
- : "the provider returned an explicitly incomplete response; the participant did not report completion. No actions or closing request followed the incomplete response.";
1019
- record({ id: nextId("notice"), kind: "notice", lifecycle: "completed", status: tokenLimit ? "warn" : "error",
1020
- title: tokenLimit ? "provider token limit reached" : unexpectedStatus ? "unexpected provider response status" : "provider response incomplete", text: reason });
1021
- break;
1022
- }
1023
- if (requiresUsage && usageUnavailableForCap()) {
1024
- stopForUnreportedUsage();
1025
- break;
1026
- }
1027
- // RUNTIME-ONLY: hand the model's narration back so the concurrent host-first barrier can read
1028
- // the lobby code the host states after creating the lobby (CDP url-read is unreliable). Raw
1029
- // text stays in memory; only an extracted code is used (and only as a digest).
1030
- {
1031
- const narration = [turn.reasoning, turn.message]
1032
- .filter((t) => typeof t === "string" && t.length > 0)
1033
- .join("\n");
1034
- if (narration.length > 0)
1035
- onMessage?.(narration);
1036
- }
1037
- // FAIL-CLOSED spend cap (runaway-retry guard). Placed alongside the wall-clock runaway stop
1038
- // above and BEFORE the next provider.nextTurn request, so a model stuck retrying cannot keep
1039
- // spending: the moment the running estimate crosses maxUsd the loop breaks with a terminal,
1040
- // non-harness-error stop. A null estimate cannot trip it (preflight guaranteed a rate).
1041
- //
1042
- // A harness spend cap interrupts the session regardless of prior activity. budget_reached
1043
- // maps to incomplete; zero executed actions do not establish that the participant gave up.
1044
- // Cite the running estimate, cap, and progress so the operator can inspect the interruption.
1045
- if (maxUsd !== undefined && estimateTurnCostUsd) {
1046
- const running = estimateTurnCostUsd(runningUsage());
1047
- // Fail CLOSED and LOUD on a non-finite estimate: a stale positional estimator (the
1048
- // pre-#334 (input, output, cachedInput) signature) arithmetics the usage OBJECT into
1049
- // NaN, and NaN > maxUsd is false forever — a spend cap that silently never trips is
1050
- // the one failure mode this guard exists to prevent (red-team finding).
1051
- if (running !== null && !Number.isFinite(running)) {
1052
- completionReason = "harness_error";
1053
- reason = "the injected estimateTurnCostUsd returned a non-finite estimate while execution.caps.maxUsd is set — likely a stale pre-#334 positional (input, output, cachedInput) callback; it now receives one ActorTokenUsage object. Failing closed instead of running uncapped.";
1054
- break;
1055
- }
1056
- if (running !== null && running > maxUsd) {
1057
- stopCause = "spend_limit";
1058
- if (materialActions > 0) {
1059
- completionReason = "budget_reached";
1060
- reason = `estimated spend $${running} crossed execution.caps.maxUsd=$${maxUsd} after productive activity (${materialActions} material action(s), ${counts.turns} turn(s)); aborted fail-closed before the next model turn`;
1061
- }
1062
- else {
1063
- completionReason = "budget_reached";
1064
- reason = `estimated spend $${running} crossed execution.caps.maxUsd=$${maxUsd} with no material progress; aborted fail-closed before the next model turn`;
1065
- }
1066
- break;
1067
- }
1068
- }
1069
- // The STUDY budget (#299), beside the per-lane cap above and before any further model turn.
1070
- if (overRunBudget) {
1071
- const runStop = overRunBudget(runningUsage());
1072
- if (runStop !== null) {
1073
- stopCause = "study_spend_limit";
1074
- completionReason = "budget_reached";
1075
- reason = runStop;
1076
- break;
1077
- }
1078
- }
1079
- if (turn.reasoning) {
1080
- record({
1081
- id: nextId("reasoning"),
1082
- kind: "reasoning",
1083
- lifecycle: "completed",
1084
- title: `reasoning turn ${turnNumber}`,
1085
- text: redactNarration(turn.reasoning)
1086
- });
1087
- bump("reasonings");
1088
- }
1089
- if (turn.message) {
1090
- record({
1091
- id: nextId("message"),
1092
- kind: "message",
1093
- lifecycle: "completed",
1094
- title: `message turn ${turnNumber}`,
1095
- text: redactNarration(turn.message)
1096
- });
1097
- bump("messages");
1098
- }
1099
- if (turn.pendingSafetyChecks.length > 0) {
1100
- const acks = acknowledgeSafetyChecks(turn.pendingSafetyChecks);
1101
- if (acks === null || acks.length === 0) {
1102
- // Safety-check categories are provider-defined enums (e.g.
1103
- // "malicious_instructions"), not free text; record them (redacted for
1104
- // defense-in-depth) so the evidence shows WHY the run paused.
1105
- const checks = redaction.redactText(turn.pendingSafetyChecks.map((check) => check.code).join(", "));
1106
- record({
1107
- id: nextId("approval"),
1108
- kind: "approval",
1109
- lifecycle: "completed",
1110
- status: "blocked",
1111
- title: `safety check: ${checks}`
1112
- });
1113
- completionReason = "blocked_approval";
1114
- reason = `paused on model safety check(s): ${checks}; not acknowledged`;
1115
- break;
1116
- }
1117
- pendingAcks = acks;
1118
- }
1119
- if (turn.done || turn.actions.length === 0) {
1120
- // The participant's own word, when its reply format has one (#570). "not_reached" is a
1121
- // participant who stopped without finishing: gave_up, which tallies as abandoned. "blocked"
1122
- // keeps goal_satisfied here (the actor did stop on purpose) and the lane's credibility read
1123
- // turns it into a blocked participant, the same path a narrated blocker takes.
1124
- // A schema field first; failing that, the fixed first line the prompt asks for (#570).
1125
- const outcome = turn.outcome ?? declaredOutcomeFromClosingLine(turn.message);
1126
- if (outcome !== undefined)
1127
- declaredOutcome = outcome;
1128
- completionReason = outcome === "not_reached" ? "gave_up" : "goal_satisfied";
1129
- const summary = turn.message?.trim();
1130
- reason = summary
1131
- ? redactNarration(summary)
1132
- : "model reported a natural endpoint with no further action";
1133
- // A done turn takes no actions, so the cadence above never observes the participant's
1134
- // FINAL state — and a task completed by that state read as incomplete. The first live
1135
- // study caught it: both participants reached the dashboard, said so, and the funnel
1136
- // reported 0/2. One guarded closing observation feeds the tracker; a failed observe
1137
- // ordinarily changes nothing (the funnel stays honest about what it saw), and no
1138
- // screenshot or stop evaluation rides it — the session is already over. An explicit
1139
- // executor failure still fails the harness instead of disappearing behind completion.
1140
- if (taskTracker !== undefined) {
1141
- try {
1142
- currentPhase = "observing closing task state";
1143
- const closing = collectHeardSpeech(await observeBounded("closing"));
1144
- observeTasks(closing, turnNumber);
1145
- }
1146
- catch (error) {
1147
- // Ordinary closing observations remain best-effort. A declared executor failure
1148
- // must not disappear behind a participant's reported success.
1149
- if (isCuaExecutorError(error))
1150
- throw error;
1151
- }
1152
- }
1153
- break;
1154
- }
1155
- const idleThisTurn = isIdleTurn(turn.actions);
1156
- previousExecution = { actions: [] };
1157
- let rejectedActionTitle;
1158
- for (const [actionIndex, action] of turn.actions.entries()) {
1159
- if (signal?.aborted)
1160
- throw new CuaAbortError();
1161
- const actionTitle = describeCuaAction(action);
1162
- lastActionTitle = actionTitle;
1163
- recentActionTitles.push(actionTitle);
1164
- if (recentActionTitles.length > 8)
1165
- recentActionTitles.shift();
1166
- // Captured so a recovered (skipped) material action can restore it: a
1167
- // skipped action must not leave its title as the "last material action".
1168
- const priorMaterialActionTitle = lastMaterialActionTitle;
1169
- if (!isIdleAction(action)) {
1170
- lastMaterialActionTitle = actionTitle;
1171
- materialActions += 1;
1172
- counts.materialActions = materialActions;
1173
- }
1174
- bump("actions");
1175
- // Classify BEFORE execute, mirroring counts.actions: the record is of what the actor
1176
- // CHOSE, so an action that then fails to actuate is still an honest record of the route
1177
- // it reached for.
1178
- affordanceObservations.push(classifyCuaAction(action));
1179
- currentPhase = `executing ${actionTitle}`;
1180
- // Record the action as completed only AFTER execute() resolves: a failed
1181
- // action must not appear as a plainly-completed ui_action (#248). On
1182
- // failure the error notice below captures the failing action + phase.
1183
- const executeAction = async (idleBound) => {
1184
- const actionController = new AbortController();
1185
- const onAbort = () => actionController.abort();
1186
- if (signal?.aborted)
1187
- actionController.abort();
1188
- else
1189
- signal?.addEventListener("abort", onAbort, { once: true });
1190
- try {
1191
- const pending = executor.execute(action, actionController.signal);
1192
- if (idleBound === undefined)
1193
- await raceSettle(pending, remaining(), signal);
1194
- else
1195
- await raceBounded(`idle action ${actionTitle}`, pending, remaining(), idleBound, signal);
1196
- }
1197
- catch (error) {
1198
- if (error instanceof CuaStallError && executor.stallRecovery === "fail_closed") {
1199
- throw new CuaExecutorError("deadline_exceeded", "outcome_uncertain");
1200
- }
1201
- if (error instanceof CuaDeadlineError || error instanceof CuaAbortError) {
1202
- // The loop's deadline/abort may win before the executor can report whether its
1203
- // write reached the desktop. Cancellation alone does not establish rollback.
1204
- interruptedActionOutcome = true;
1205
- record({
1206
- id: nextId("notice"), kind: "notice", lifecycle: "completed", status: "warn",
1207
- title: "action outcome uncertain",
1208
- text: redactNarration(`action: ${actionTitle}; disposition: outcome_uncertain; the loop stopped waiting before execution was acknowledged; the action was not retried`)
1209
- });
1210
- }
1211
- throw error;
1212
- }
1213
- finally {
1214
- signal?.removeEventListener("abort", onAbort);
1215
- // A deadline also closes async executor preparation, so a late pointer read
1216
- // cannot actuate after the loop stopped waiting for this action.
1217
- actionController.abort();
1218
- }
1219
- };
1220
- let actionSkipped = false;
1221
- try {
1222
- if (isIdleAction(action)) {
1223
- // Observation actions only look (#480). A `wait` that hangs inside the SDK has, by
1224
- // definition, waited; skipping it with a notice loses nothing the participant chose.
1225
- const idleBound = observationTimeoutMs + (action.kind === "wait" ? (action.ms ?? 0) : 0);
1226
- try {
1227
- await executeAction(idleBound);
1228
- }
1229
- catch (error) {
1230
- if (!(error instanceof CuaStallError))
1231
- throw error;
1232
- actionSkipped = true;
1233
- record({
1234
- id: nextId("notice"),
1235
- kind: "notice",
1236
- lifecycle: "completed",
1237
- status: "warn",
1238
- title: "observation action stalled; skipped",
1239
- text: `${error.what} produced nothing within ${error.afterMs}ms; the desktop was not asked again and the next screenshot decides`
1240
- });
1241
- }
1242
- }
1243
- else {
1244
- await executeAction();
1245
- }
1246
- }
1247
- catch (error) {
1248
- // A declared pre-dispatch action rejection leaves the desktop usable.
1249
- // Other typed failures retain their terminal handling, independently of
1250
- // the legacy E2B CommandExitError recovery below.
1251
- if (isCuaExecutorError(error)) {
1252
- previousExecution.actions.push({ index: actionIndex, status: error.disposition });
1253
- if (error.disposition === "not_dispatched" && !isIdleAction(action)) {
1254
- materialActions -= 1;
1255
- counts.materialActions = materialActions;
1256
- lastMaterialActionTitle = priorMaterialActionTitle;
1257
- }
1258
- if (error.code === "action_rejected" && error.disposition === "not_dispatched") {
1259
- rejectedActionTitle = actionTitle;
1260
- // Later actions may depend on this one (type, then submit). Return
1261
- // their full acknowledgement list and let a fresh observation decide.
1262
- for (let index = actionIndex + 1; index < turn.actions.length; index++) {
1263
- previousExecution.actions.push({ index, status: "not_dispatched" });
1264
- }
1265
- record({
1266
- id: nextId("notice"), kind: "notice", lifecycle: "completed", status: "warn",
1267
- title: "action rejected before dispatch",
1268
- text: redactNarration(`action: ${actionTitle}; code: action_rejected; disposition: not_dispatched; remaining batch actions not dispatched: ${turn.actions.length - actionIndex - 1}`)
1269
- });
1270
- break;
1271
- }
1272
- throw error;
1273
- }
1274
- if (!isCommandExitError(error))
1275
- throw error;
1276
- if (!isIdleAction(action)) {
1277
- // The material count was applied above assuming the action would
1278
- // actuate; it did not, so roll it back — a failed action is not
1279
- // progress. The next observe() hands the model a fresh screenshot to
1280
- // adapt, and because a skipped action changes nothing on screen a
1281
- // persistently-failing run makes no progress and still terminates
1282
- // honestly via the idle/no-progress backstop (gave_up), never a
1283
- // silent actor_error and never an infinite loop.
1284
- materialActions -= 1;
1285
- counts.materialActions = materialActions;
1286
- // Roll back the title too, so a later gave_up backstop notice never
1287
- // cites a never-actuated action as the "last material action" while
1288
- // counts.materialActions is 0 (honest-evidence invariant).
1289
- lastMaterialActionTitle = priorMaterialActionTitle;
1290
- }
1291
- previousExecution.actions.push({ index: actionIndex, status: "skipped" });
1292
- const { exitCode, stderrTail } = commandFailureInfo(error);
1293
- record({
1294
- id: nextId("notice"),
1295
- kind: "notice",
1296
- lifecycle: "completed",
1297
- status: "error",
1298
- title: "action skipped: desktop command failed",
1299
- // Public-safe: describeCuaAction never includes raw typed text, the
1300
- // exit code is a number, and the tail is only the substrate's own
1301
- // stderr (tailed+whitespace-collapsed); the whole line is still run
1302
- // through redactNarration (scrubKnownValues + pattern redaction).
1303
- text: redactNarration([
1304
- `action: ${actionTitle}`,
1305
- exitCode === undefined ? undefined : `exit code: ${exitCode}`,
1306
- stderrTail.length > 0 ? `stderr: ${stderrTail}` : undefined
1307
- ].filter(Boolean).join("; "))
1308
- });
1309
- continue;
1310
- }
1311
- previousExecution.actions.push({ index: actionIndex, status: actionSkipped ? "skipped" : "completed" });
1312
- record({
1313
- id: nextId("ui_action"),
1314
- kind: "ui_action",
1315
- lifecycle: "completed",
1316
- title: actionTitle,
1317
- ...(action.kind === "speak" ? { text: redactNarration(action.text) } : {}),
1318
- // Structured pin coordinates (#441), exactly the click classes the Observer
1319
- // pins render — recorded fact instead of a title re-parse downstream.
1320
- ...(action.kind === "click" || action.kind === "double_click"
1321
- ? { coord: { x: action.x, y: action.y } }
1322
- : {})
1323
- });
1324
- }
1325
- if (signal?.aborted)
1326
- throw new CuaAbortError();
1327
- currentPhase = `observing UI state after turn ${turnNumber}`;
1328
- observation = collectHeardSpeech(await observeBounded(`after turn ${turnNumber}`));
1329
- // Runtime-only: hand the seat's live location.href back to the orchestrator (never persisted).
1330
- onObservedUrl?.(observation.url);
1331
- if (observation.screenshot !== undefined)
1332
- onScreenshot?.(observation.screenshot);
1333
- if (observation.appState !== undefined)
1334
- observedAppState = true;
1335
- // Per-turn fail-closed vision guard: a vision provider can never reason over a missing frame.
1336
- if (frameGuardTripped(observation))
1337
- break;
1338
- await maybeRecordScreenshot(observation, `turn-${turnNumber.toString().padStart(2, "0")}`);
1339
- flushTrace();
1340
- observeTasks(observation, turnNumber);
1341
- const dwellOutcome = await dwellIfDue(observation, turnNumber);
1342
- if (dwellOutcome !== undefined) {
1343
- observation = collectHeardSpeech(await observeBounded("after dwell"));
1344
- onObservedUrl?.(observation.url);
1345
- if (observation.screenshot !== undefined)
1346
- onScreenshot?.(observation.screenshot);
1347
- await maybeRecordScreenshot(observation, `turn-${turnNumber.toString().padStart(2, "0")}-after-dwell`);
1348
- observeTasks(observation, turnNumber);
1349
- if (dwellOutcome === "stop") {
1350
- completionReason = "goal_satisfied";
1351
- reason = `dwell window complete (${dwellHeldMs}ms held after turn ${turnNumber})`;
1352
- closingObservation = observation;
1353
- closingTrigger = "dwell";
1354
- break;
1355
- }
1356
- }
1357
- stopConditionMatch = matchedStopWhen(observation);
1358
- if (stopConditionMatch) {
1359
- completionReason = "goal_satisfied";
1360
- reason = stopWhenReason(stopConditionMatch);
1361
- closingObservation = observation;
1362
- closingTrigger = "stop_when";
1363
- record(stopWhenTraceItem(nextId("notice"), stopConditionMatch, redactNarration));
1364
- break;
1365
- }
1366
- // Progress prefers the stable appState projection; a state executor with a constant
1367
- // stateSignature still registers progress when its appState changed (and vice versa).
1368
- const progressKey = progressKeyOf(observation);
1369
- const frameChanged = progressKey !== lastSignature;
1370
- lastSignature = progressKey;
1371
- // CORROBORATION (#383). A stale frame alone is NOT evidence of a stuck agent. The frame hash is
1372
- // a coarse whole-screen measure, and on a light-themed web app it can miss a renamed row, a new
1373
- // list item, or an opened panel — a measured run had 9 visibly different consecutive frames hash
1374
- // identically while the agent was a foreign key away from finishing. Ending a lane on that
1375
- // signal alone recorded working sessions as `gave_up`, capping every browser run at roughly
1376
- // noProgressSteps turns and writing harness artifacts into evidence as actor behavior.
1377
- //
1378
- // So a no-progress turn now requires BOTH a stale frame AND the agent repeating something it
1379
- // just tried. An agent doing varied work is never counted stuck, however blind the hash is;
1380
- // an agent re-clicking the same dead control trips it as fast as it did before — arguably
1381
- // faster, since that is the actual signature of being stuck.
1382
- const fingerprint = actionFingerprint(turn.actions);
1383
- const repeatingRecentAction = fingerprint.length > 0 && recentFingerprints.includes(fingerprint);
1384
- recentFingerprints.push(fingerprint);
1385
- if (recentFingerprints.length > ACTION_REPEAT_WINDOW)
1386
- recentFingerprints.shift();
1387
- // Corroboration governs the FRAME-STALENESS backstop only. The idle backstop below is a direct
1388
- // behavioral signal already (the agent took nothing but screenshots and waits), so it keeps
1389
- // reading the frame on its own — a repeated screenshot is exactly what an idle streak IS, and
1390
- // feeding repetition into it would grant an extra forgiveness step for being idle.
1391
- const observedProgress = frameChanged || heardSpeechChanged;
1392
- const progressed = observedProgress || !repeatingRecentAction;
1393
- // A screenshot/wait turn while the UI visibly changes may be patience through loading or a
1394
- // transition, so grant a bounded recovery window. Do not grant infinite immunity: animated
1395
- // pixels or state-executor turn counters can otherwise keep a screenshot/wait loop alive
1396
- // until the wall-clock timeout.
1397
- if (idleThisTurn) {
1398
- if (observedProgress && idleProgressForgivenessUsed < IDLE_PROGRESS_FORGIVENESS_STEPS) {
1399
- idleProgressForgivenessUsed += 1;
1400
- consecutiveIdle = 0;
1401
- }
1402
- else {
1403
- consecutiveIdle += 1;
1404
- }
1405
- }
1406
- else {
1407
- idleProgressForgivenessUsed = 0;
1408
- consecutiveIdle = 0;
1409
- }
1410
- if (idleThisTurn)
1411
- bump("idleTurns");
1412
- consecutiveNoProgress = progressed ? 0 : consecutiveNoProgress + 1;
1413
- if (!progressed)
1414
- bump("noProgressTurns");
1415
- // An unchanged screen can be legitimate waiting (for example, a shared-world lobby).
1416
- // Recovery may suggest another approach, but must not instruct early abandonment while
1417
- // the task still calls for waiting. The counters, time and spend guards own hard stops.
1418
- const contextHints = [];
1419
- if (rejectedActionTitle !== undefined) {
1420
- contextHints.push(`Your action (${rejectedActionTitle}) was rejected before dispatch. No input from that action or the rest of its batch was sent. Choose your next action from the fresh screenshot; do not assume the rejected action succeeded.`);
1421
- }
1422
- if (consecutiveNoProgress >= noProgressRecoverySteps && consecutiveNoProgress < noProgressSteps) {
1423
- contextHints.push(`No visible progress for ${consecutiveNoProgress} step(s). ` +
1424
- "If your task calls for waiting for another participant or a pending transition, you may continue waiting. " +
1425
- "Choose whether to continue or stop based on your situation and what you observe.");
1426
- }
1427
- if (consecutiveIdle >= idleRecoverySteps && consecutiveIdle < idleSteps) {
1428
- contextHints.push(`You are only waiting or taking screenshots for ${consecutiveIdle} step(s). ` +
1429
- "If your task calls for waiting, you may continue within the remaining session time. " +
1430
- "When the relevant controls become actionable, continue your task; describe any blocker you actually encounter.");
1431
- }
1432
- if (contextHints.length > 0)
1433
- contextHint = contextHints.join(" ");
1434
- if (consecutiveIdle >= idleSteps) {
1435
- completionReason = "gave_up";
1436
- reason = `gave up: ${consecutiveIdle} consecutive turns with no material UI action (only screenshot/wait)`;
1437
- record(backstopTraceItem({
1438
- id: nextId("notice"),
1439
- reason,
1440
- lastMaterialActionTitle,
1441
- recentActionTitles,
1442
- screenshotRef: lastScreenshotRef,
1443
- redactNarration
1444
- }));
1445
- break;
1446
- }
1447
- if (consecutiveNoProgress >= noProgressSteps) {
1448
- completionReason = "gave_up";
1449
- reason = `gave up: ${consecutiveNoProgress} consecutive turns with no change to the UI state`;
1450
- record(backstopTraceItem({
1451
- id: nextId("notice"),
1452
- reason,
1453
- lastMaterialActionTitle,
1454
- recentActionTitles,
1455
- screenshotRef: lastScreenshotRef,
1456
- redactNarration
1457
- }));
1458
- break;
1459
- }
1460
- }
1461
- }
1462
- catch (error) {
1463
- if (error instanceof CuaFrameGuardStop || error instanceof CuaStopWhenStop) {
1464
- // completionReason/reason were already set by the frame guard or stopWhen guard.
1465
- }
1466
- else if (error instanceof CuaDeadlineError) {
1467
- stopCause = "time_limit";
1468
- if (materialActions > 0) {
1469
- completionReason = "budget_reached";
1470
- reason = interruptedActionOutcome
1471
- ? `reached the ${timeoutMs}ms time budget with ${materialActions} material action attempt(s), ${counts.turns} turn(s); the latest action outcome is uncertain`
1472
- : `reached the ${timeoutMs}ms time budget after productive activity (${materialActions} material action(s), ${counts.turns} turn(s))`;
1473
- }
1474
- else {
1475
- completionReason = "timed_out";
1476
- reason = `wall-clock deadline reached after ${timeoutMs}ms with no material progress`;
1477
- }
1478
- }
1479
- else if (error instanceof CuaAbortError) {
1480
- completionReason = "harness_error";
1481
- reason = "run aborted by the harness";
1482
- stopCause = "harness_aborted";
1483
- }
1484
- else if (isCuaProviderError(error)) {
1485
- completionReason = "harness_error";
1486
- reason = `participant provider error: ${error.code}${error.failurePhase ? ` during ${error.failurePhase}` : ""}; cleanup: ${error.receipt.cleanup}`;
1487
- record({ id: nextId("notice"), kind: "notice", lifecycle: "completed", status: "error",
1488
- title: "participant provider error", text: reason });
1489
- }
1490
- else if (isCuaExecutorError(error)) {
1491
- completionReason = "harness_error";
1492
- reason = `desktop executor error: ${error.code}; disposition: ${error.disposition}`;
1493
- record({
1494
- id: nextId("notice"), kind: "notice", lifecycle: "completed", status: "error",
1495
- title: "desktop executor error",
1496
- text: [
1497
- `phase: ${redactNarration(currentPhase)}`,
1498
- `code: ${error.code}`,
1499
- `disposition: ${error.disposition}`,
1500
- lastActionTitle === undefined ? undefined : `last action: ${redactNarration(lastActionTitle)}`
1501
- ].filter(Boolean).join("; "),
1502
- ...(lastScreenshotRef === undefined ? {} : { screenshotRef: lastScreenshotRef })
1503
- });
1504
- }
1505
- else {
1506
- completionReason = "actor_error";
1507
- const rawMessage = error instanceof Error ? error.message : String(error);
1508
- const message = redactNarration(rawMessage);
1509
- reason = redactNarration(`computer-use loop error: ${rawMessage}`);
1510
- record({
1511
- id: nextId("notice"),
1512
- kind: "notice",
1513
- lifecycle: "completed",
1514
- status: "error",
1515
- title: "computer-use loop error",
1516
- text: [
1517
- `phase: ${redactNarration(currentPhase)}`,
1518
- error instanceof Error && error.name ? `error: ${redactNarration(error.name)}` : undefined,
1519
- `message: ${message}`,
1520
- lastActionTitle === undefined ? undefined : `last action: ${redactNarration(lastActionTitle)}`
1521
- ].filter(Boolean).join("; "),
1522
- ...(lastScreenshotRef === undefined ? {} : { screenshotRef: lastScreenshotRef })
1523
- });
1524
- }
1525
- }
1526
- // Structured completion must stop interaction immediately, but the participant may not yet
1527
- // have spoken. Request one read-only account using the already captured final observation.
1528
- // No callbacks that coordinate live participants and no executor calls occur after this point.
1529
- if (closingTrigger !== undefined && closingObservation !== undefined) {
1530
- const note = (status, detail, usageReported) => {
1531
- debrief = { trigger: closingTrigger, status, reason: redactNarration(detail),
1532
- ...(usageReported === undefined ? {} : { usageReported }) };
1533
- record({ id: nextId("notice"), kind: "notice", lifecycle: "completed",
1534
- status: status === "completed" ? "ok" : "warn", title: `participant debrief ${status}`,
1535
- text: redactNarration(detail) });
1536
- };
1537
- let skip;
1538
- if ((counts.turns ?? 0) === 0)
1539
- skip = "the study stopped before any participant turn";
1540
- else if (provider.debrief === undefined)
1541
- skip = "this provider does not support read-only closing reports";
1542
- else if (providerCleanupUnconfirmed)
1543
- skip = "participant request cleanup is unconfirmed";
1544
- else if (signal?.aborted)
1545
- skip = "the study was cancelled";
1546
- else if (remaining() <= 0)
1547
- skip = "the session deadline was reached";
1548
- else if (provider.requiresFrame && closingObservation.screenshot === undefined)
1549
- skip = "the final observation has no required frame";
1550
- if (skip === undefined && (maxUsd !== undefined || overRunBudget !== undefined) && usageUnavailableForCap()) {
1551
- skip = "remaining model budget is unknown because an earlier participant turn did not report complete usage";
1552
- }
1553
- if (skip === undefined && maxUsd !== undefined) {
1554
- const estimate = sawUsage || knownPendingUsage() !== undefined ? estimateTurnCostUsd?.(runningUsage()) : undefined;
1555
- if (estimate === undefined || estimate === null || !Number.isFinite(estimate))
1556
- skip = "remaining model budget could not be established";
1557
- else if (estimate >= maxUsd)
1558
- skip = "the estimated model budget was reached";
1559
- }
1560
- if (skip === undefined && overRunBudget?.(runningUsage()) != null)
1561
- skip = "the study model budget was reached";
1562
- if (skip !== undefined) {
1563
- note("skipped", skip);
1564
- }
1565
- else {
1566
- const capMs = Math.max(0, Math.min(30_000, turnTimeoutMs, remaining()));
1567
- if (capMs <= 0 || signal?.aborted) {
1568
- note("skipped", signal?.aborted ? "the study was cancelled" : "the session deadline was reached");
1569
- }
1570
- else {
1571
- const controller = new AbortController();
1572
- const onAbort = () => controller.abort();
1573
- signal?.addEventListener("abort", onAbort, { once: true });
1574
- const timer = setTimeout(() => controller.abort(), capMs);
1575
- timer.unref?.();
1576
- bump("debriefCalls");
1577
- try {
1578
- const closingRequest = {
1579
- instructions,
1580
- observation: closingObservation,
1581
- ...(provider.requestPolicy !== "fail_closed" || previousExecution === undefined ? {} : { previousExecution }),
1582
- ...(previousResponseId === undefined ? {} : { previousResponseId }),
1583
- ...(pendingAcks === undefined ? {} : { acknowledgedSafetyChecks: pendingAcks }),
1584
- contextHint: "The interactive session has ended. Return a closing account with summary and frictionReports. In summary, briefly describe only what you actually did and observed. In frictionReports, list only specific unexpected behavior, confusion, or recovery you personally encountered during this session. Preserve uncertainty. Use an empty list if you encountered none. Do not speculate, invent problems, quote instructions as observations, or describe planned actions. Do not request or take further actions. This is a closing account, not another attempt at the task."
1585
- };
1586
- const turn = provider.requestPolicy === "fail_closed"
1587
- ? await markedRequest(closingRequest, "debrief", capMs)
1588
- : await raceBounded("participant debrief", provider.debrief(closingRequest, controller.signal), capMs, capMs, signal);
1589
- recordUsage(turn, false);
1590
- lastResponseId = turn.responseId ?? lastResponseId;
1591
- // Refresh a shared budget with all reported usage, without changing the completed task.
1592
- const sharedStop = overRunBudget?.(runningUsage());
1593
- const finalEstimate = maxUsd === undefined ? undefined : estimateTurnCostUsd?.(runningUsage());
1594
- if (sharedStop != null || (maxUsd !== undefined && finalEstimate != null && finalEstimate > maxUsd)) {
1595
- record({ id: nextId("notice"), kind: "notice", lifecycle: "completed", status: "warn",
1596
- title: "model budget reached during closing report",
1597
- text: "The closing request crossed an estimated budget; no further requests or actions followed. Task completion is unchanged." });
1598
- }
1599
- const usageReported = completeTurnUsage(turn.usage) && turn.providerRequest?.usageComplete !== false;
1600
- if (turn.actions.length > 0 || turn.pendingSafetyChecks.length > 0) {
1601
- note("failed", "the closing response requested actions or safety checks; none were executed and its report was not accepted", usageReported);
1602
- }
1603
- else if (!validClosingReport(turn.closingReport)) {
1604
- note("failed", "the closing response did not contain a valid structured participant report", usageReported);
1605
- }
1606
- else {
1607
- const report = {
1608
- summary: redactNarration(turn.closingReport.summary.trim()),
1609
- frictionReports: [...new Set(turn.closingReport.frictionReports.map((text) => redactNarration(text.trim())))]
1610
- };
1611
- const messageId = nextId("message");
1612
- record({ id: messageId, kind: "message", lifecycle: "completed",
1613
- title: "participant closing report", text: [report.summary, ...report.frictionReports].join("\n\n") });
1614
- bump("messages");
1615
- note("completed", "one read-only report; no additional desktop actions; original stop and task outcomes preserved", usageReported);
1616
- debrief = { ...debrief, report, messageId };
1617
- }
1618
- }
1619
- catch (error) {
1620
- // A failed optional report cannot rewrite the already observed structured completion.
1621
- if (isCuaAdmissionLimitError(error)) {
1622
- note("skipped", "the adapter reported a local admission limit before provider dispatch; no closing request was sent");
1623
- }
1624
- else {
1625
- const detail = signal?.aborted ? "cancelled" : controller.signal.aborted || error instanceof CuaDeadlineError || error instanceof CuaStallError
1626
- ? "closing report deadline reached" : error instanceof Error ? error.message : String(error);
1627
- const closingReceipt = provider.requestPolicy === "fail_closed" ? providerRequests.at(-1) : undefined;
1628
- const usageReported = closingReceipt?.usageComplete === true && completeTurnUsage(closingReceipt.usage);
1629
- note("failed", `${detail}; closing request usage is ${usageReported ? "reported" : "unreported"}`, usageReported);
1630
- }
1631
- }
1632
- finally {
1633
- clearTimeout(timer);
1634
- signal?.removeEventListener("abort", onAbort);
1635
- controller.abort();
1636
- }
1637
- }
1638
- }
1639
- flushTrace();
1640
- }
1641
- const completedAtMs = now();
1642
- const status = statusForCompletionReason(completionReason);
1643
- const ids = {};
1644
- if (provider.version !== undefined)
1645
- ids.model = provider.version;
1646
- // responseId is provider-authored and opaque; redact for defense-in-depth.
1647
- if (lastResponseId !== undefined)
1648
- ids.turnId = redaction.redactText(lastResponseId);
1649
- const screenshotNote = !(counts.screenshots && counts.screenshots > 0)
1650
- ? "no screenshots captured"
1651
- : redactScreenshots
1652
- ? `${counts.screenshots} screenshot(s) redacted to blurred thumbnails via RedactionHooks`
1653
- : `${counts.screenshots} full-fidelity screenshot(s) retained for local use — NOT redacted for publishing; set redactScreenshots to blur a share-as-is bundle`;
1654
- // Self-describing artifact (invariant 6): when a non-vision executor surfaced structured app
1655
- // state, the trace declares HOW it handled that surface — app state drove progress detection
1656
- // each turn and was NOT written to the trace (it is a runtime-only progress input, like
1657
- // stateSignature). The appState itself never appears anywhere in this bundle.
1658
- const notes = observedAppState
1659
- ? `${screenshotNote}. App state was observed each turn to drive progress detection (a state-driven executor) and was NOT written to the trace — it is a runtime-only progress input, never persisted as evidence in this slice.`
1660
- : screenshotNote;
1661
- const trace = {
1662
- schema: ACTOR_TRACE_SCHEMA,
1663
- provider: provider.id,
1664
- ...liveMetadata(),
1665
- ...(provider.version === undefined ? {} : { providerVersion: provider.version }),
1666
- protocol: "cua-loop",
1667
- lane: "computer-use",
1668
- persona,
1669
- redaction: {
1670
- status: "passed",
1671
- screenshots: !(counts.screenshots && counts.screenshots > 0)
1672
- ? "n/a"
1673
- : redactScreenshots
1674
- ? "blurred"
1675
- : "raw",
1676
- notes
1677
- },
1678
- startedAt: new Date(startedAtMs).toISOString(),
1679
- completedAt: new Date(completedAtMs).toISOString(),
1680
- durationMs: completedAtMs - startedAtMs,
1681
- status,
1682
- completionReason,
1683
- ...(stopCause === undefined ? {} : { stopCause }),
1684
- reason,
1685
- ids,
1686
- ...(provider.modelSettings === undefined
1687
- ? {}
1688
- : { modelSettings: { reasoningEffort: provider.modelSettings.reasoningEffort,
1689
- ...(provider.modelSettings.maxOutputTokens === undefined ? {} : { maxOutputTokens: provider.modelSettings.maxOutputTokens }) } }),
1690
- counts,
1691
- items,
1692
- ...(affordanceObservations.length > 0 ? { affordanceUse: summarizeAffordanceUse(affordanceObservations) } : {}),
1693
- ...(declaredOutcome === undefined ? {} : { declaredOutcome }),
1694
- ...(debrief === undefined ? {} : { debrief }),
1695
- ...(interactionRequestPending || hasUnreportedInteractionUsage() || (requiresUsage && incompleteInteractionUsage)
1696
- ? { interactionUsageIncomplete: true } : {}),
1697
- // The funnel is present exactly when a protocol was declared — including a session that ended
1698
- // on turn 0, whose funnel honestly reads 0/N. No tasks declared means no funnel, not an empty one.
1699
- ...(taskTracker === undefined ? {} : { taskFunnel: taskTracker.funnel() }),
1700
- ...(sawUsage
1701
- ? {
1702
- tokenUsage: provider.executionProfile?.billing === "account-unknown" ? accountUsage() : {
1703
- input: usageInput,
1704
- output: usageOutput,
1705
- // Recorded only when the provider actually reported it, so a reader can tell "no cache
1706
- // hits" from "this provider does not say" (#391); same for cache writes (#334).
1707
- ...(usageCachedInput > 0 ? { cachedInput: usageCachedInput } : {}),
1708
- ...(usageCacheWriteInput > 0 ? { cacheWriteInput: usageCacheWriteInput } : {}),
1709
- ...(usageTurns.length > 0 ? { turns: usageTurns.map((turn) => ({ ...turn })) } : {}),
1710
- total: usageInput + usageOutput
1711
- }
1712
- }
1713
- : {}),
1714
- capabilities: provider.capabilities
1715
- };
1716
- return { status, completionReason, reason, trace };
1717
- }
1718
- function stopWhenReason(match) {
1719
- return `stopWhen matched ${match.id} (${match.kinds.join("+")})`;
1720
- }
1721
- function stopWhenTraceItem(id, match, redactNarration) {
1722
- return {
1723
- id,
1724
- kind: "notice",
1725
- lifecycle: "completed",
1726
- status: "matched",
1727
- title: `stopWhen matched: ${match.id}`,
1728
- text: redactNarration(`Harness stop condition matched rule ${match.id} using ${match.kinds.join(", ")}. Raw observed URL/text/appState were runtime-only and were not persisted; when a screenshot was available, the immediately preceding screenshot item is the visual evidence for the matched surface.`)
1729
- };
1730
- }
1731
- function backstopTraceItem(args) {
1732
- const details = [
1733
- `reason: ${args.reason}`,
1734
- args.lastMaterialActionTitle === undefined
1735
- ? "last material action: none"
1736
- : `last material action: ${args.lastMaterialActionTitle}`,
1737
- args.recentActionTitles.length === 0
1738
- ? "recent actions: none"
1739
- : `recent actions: ${args.recentActionTitles.join(" -> ")}`
1740
- ];
1741
- return {
1742
- id: args.id,
1743
- kind: "notice",
1744
- lifecycle: "completed",
1745
- status: "blocked",
1746
- title: "computer-use backstop gave up",
1747
- text: args.redactNarration(details.join("; ")),
1748
- ...(args.screenshotRef === undefined ? {} : { screenshotRef: args.screenshotRef })
1749
- };
1750
- }
1751
- //# sourceMappingURL=computer-use.js.map