humanish 0.106.1 → 0.108.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (668) hide show
  1. package/ARCHITECTURE.md +38 -32
  2. package/CHANGELOG.md +28 -0
  3. package/CONTEXT.md +51 -41
  4. package/README.md +152 -174
  5. package/SECURITY.md +16 -26
  6. package/TELEMETRY.md +8 -6
  7. package/dist/actors/affordance.d.ts +4 -4
  8. package/dist/actors/affordance.js +12 -12
  9. package/dist/actors/agent-session.d.ts +2 -2
  10. package/dist/actors/agent-session.js +7 -7
  11. package/dist/actors/codex/app-server-actor-trace.d.ts +1 -1
  12. package/dist/actors/codex/app-server-actor-trace.js +1 -1
  13. package/dist/actors/codex/app-server-client.js +2 -1
  14. package/dist/actors/codex/app-server-trace.d.ts +0 -1
  15. package/dist/actors/codex/app-server-trace.js +1 -3
  16. package/dist/actors/codex/app-server-ui.js +1 -1
  17. package/dist/actors/codex/app-server.js +2 -1
  18. package/dist/actors/codex/codex-admission.d.ts +91 -0
  19. package/dist/actors/codex/codex-admission.js +150 -0
  20. package/dist/actors/codex/protocol-compat.d.ts +27 -0
  21. package/dist/actors/codex/protocol-compat.js +357 -0
  22. package/dist/actors/codex/protocol-contract.d.ts +61 -0
  23. package/dist/actors/codex/protocol-contract.js +471 -0
  24. package/dist/actors/codex/restricted-executable.d.ts +28 -4
  25. package/dist/actors/codex/restricted-executable.js +104 -29
  26. package/dist/actors/codex/restricted-launch.d.ts +9 -2
  27. package/dist/actors/codex/restricted-launch.js +43 -4
  28. package/dist/actors/codex/restricted-notifications.d.ts +101 -0
  29. package/dist/actors/codex/restricted-notifications.js +277 -0
  30. package/dist/actors/codex/restricted-participant.d.ts +30 -0
  31. package/dist/actors/codex/restricted-participant.js +66 -6
  32. package/dist/actors/codex/restricted-policy.d.ts +11 -3
  33. package/dist/actors/codex/restricted-policy.js +2 -2
  34. package/dist/actors/codex/restricted-session.d.ts +16 -3
  35. package/dist/actors/codex/restricted-session.js +60 -22
  36. package/dist/actors/codex/restricted-transport.d.ts +29 -0
  37. package/dist/actors/codex/restricted-transport.js +139 -27
  38. package/dist/actors/codex/restricted-turn.d.ts +19 -4
  39. package/dist/actors/codex/restricted-turn.js +43 -30
  40. package/dist/actors/computer-use/actor.d.ts +17 -17
  41. package/dist/actors/computer-use/actor.js +6 -6
  42. package/dist/actors/computer-use/admission-limit.d.ts +1 -1
  43. package/dist/actors/computer-use/admission-limit.js +1 -1
  44. package/dist/actors/computer-use/loop/actions.d.ts +3 -3
  45. package/dist/actors/computer-use/loop/actions.js +10 -10
  46. package/dist/actors/computer-use/loop/backstop.d.ts +3 -3
  47. package/dist/actors/computer-use/loop/backstop.js +15 -13
  48. package/dist/actors/computer-use/loop/ending.d.ts +7 -7
  49. package/dist/actors/computer-use/loop/ending.js +9 -9
  50. package/dist/actors/computer-use/loop/observation.d.ts +2 -2
  51. package/dist/actors/computer-use/loop/observation.js +9 -9
  52. package/dist/actors/computer-use/loop/provider-call.d.ts +1 -1
  53. package/dist/actors/computer-use/loop/provider-call.js +1 -1
  54. package/dist/actors/computer-use/loop/session.js +3 -3
  55. package/dist/actors/computer-use/loop/spend.d.ts +2 -2
  56. package/dist/actors/computer-use/loop/spend.js +4 -4
  57. package/dist/actors/computer-use/loop/trace.js +11 -10
  58. package/dist/actors/computer-use/loop/types.d.ts +37 -26
  59. package/dist/actors/computer-use/loop/usage.js +2 -2
  60. package/dist/actors/computer-use/loop.js +4 -4
  61. package/dist/actors/computer-use/openai-context.d.ts +37 -0
  62. package/dist/actors/computer-use/openai-context.js +214 -0
  63. package/dist/actors/computer-use/openai-provider.d.ts +12 -9
  64. package/dist/actors/computer-use/openai-provider.js +47 -36
  65. package/dist/actors/computer-use/openai-requests.d.ts +36 -10
  66. package/dist/actors/computer-use/openai-requests.js +82 -15
  67. package/dist/actors/computer-use/openai-wire.d.ts +19 -7
  68. package/dist/actors/computer-use/openai-wire.js +36 -34
  69. package/dist/actors/contract.d.ts +86 -49
  70. package/dist/actors/contract.js +29 -23
  71. package/dist/actors/local-agent/claude-session.d.ts +1 -1
  72. package/dist/actors/local-agent/claude-session.js +10 -9
  73. package/dist/actors/local-agent/cli.d.ts +8 -6
  74. package/dist/actors/local-agent/cli.js +24 -28
  75. package/dist/actors/local-agent/readiness.d.ts +2 -2
  76. package/dist/actors/local-agent/readiness.js +4 -4
  77. package/dist/actors/reasoning-effort.js +6 -6
  78. package/dist/actors/registry.d.ts +10 -10
  79. package/dist/actors/registry.js +18 -17
  80. package/dist/actors/scripted-browser/actor.d.ts +8 -8
  81. package/dist/actors/scripted-browser/actor.js +16 -16
  82. package/dist/actors/scripted-browser/browser-command.js +1 -1
  83. package/dist/actors/scripted-browser/journey.js +15 -4
  84. package/dist/actors/scripted-browser/steps.js +19 -1
  85. package/dist/actors/scripted-browser/types.d.ts +12 -2
  86. package/dist/actors/stop-conditions.d.ts +1 -1
  87. package/dist/actors/stop-conditions.js +1 -3
  88. package/dist/analysis/automatic-completion.d.ts +13 -8
  89. package/dist/analysis/automatic-completion.js +14 -8
  90. package/dist/analysis/automatic-config.d.ts +1 -1
  91. package/dist/analysis/automatic-config.js +2 -2
  92. package/dist/analysis/automatic.d.ts +10 -4
  93. package/dist/analysis/automatic.js +17 -13
  94. package/dist/analysis/codex-config.d.ts +6 -2
  95. package/dist/analysis/codex-config.js +22 -14
  96. package/dist/analysis/diagnostics.d.ts +23 -0
  97. package/dist/analysis/diagnostics.js +112 -0
  98. package/dist/analysis/evidence-sources.js +2 -2
  99. package/dist/analysis/evidence.js +6 -6
  100. package/dist/analysis/execute.d.ts +7 -1
  101. package/dist/analysis/execute.js +39 -12
  102. package/dist/analysis/job.d.ts +8 -5
  103. package/dist/analysis/job.js +15 -14
  104. package/dist/analysis/load.d.ts +1 -1
  105. package/dist/analysis/load.js +5 -5
  106. package/dist/analysis/provider.d.ts +9 -1
  107. package/dist/analysis/restricted-codex.d.ts +2 -0
  108. package/dist/analysis/restricted-codex.js +10 -1
  109. package/dist/analysis/service.d.ts +2 -0
  110. package/dist/analysis/service.js +35 -16
  111. package/dist/analysis/sharing.d.ts +2 -2
  112. package/dist/analysis/sharing.js +5 -5
  113. package/dist/analysis/store-executions.d.ts +5 -5
  114. package/dist/analysis/store-executions.js +12 -12
  115. package/dist/analysis/store.d.ts +4 -4
  116. package/dist/analysis/store.js +13 -13
  117. package/dist/cli/commands/analysis-signals.d.ts +2 -1
  118. package/dist/cli/commands/analysis-signals.js +4 -1
  119. package/dist/cli/commands/analyze.js +23 -18
  120. package/dist/cli/commands/codex.js +9 -9
  121. package/dist/cli/commands/comms.js +62 -34
  122. package/dist/cli/commands/feedback.js +20 -21
  123. package/dist/cli/commands/lab-format.d.ts +5 -4
  124. package/dist/cli/commands/lab-format.js +35 -23
  125. package/dist/cli/commands/lab-route-computer-use.d.ts +0 -2
  126. package/dist/cli/commands/lab-route-computer-use.js +32 -21
  127. package/dist/cli/commands/lab-route-preview.d.ts +1 -3
  128. package/dist/cli/commands/lab-route-preview.js +7 -7
  129. package/dist/cli/commands/lab-route-run.d.ts +6 -4
  130. package/dist/cli/commands/lab-route-run.js +6 -2
  131. package/dist/cli/commands/lab-route-scripted.d.ts +0 -2
  132. package/dist/cli/commands/lab-route-scripted.js +0 -1
  133. package/dist/cli/commands/lab-route-shared-world.d.ts +0 -2
  134. package/dist/cli/commands/lab-route-shared-world.js +3 -4
  135. package/dist/cli/commands/lab-route-terminal.d.ts +0 -2
  136. package/dist/cli/commands/lab-route-terminal.js +0 -1
  137. package/dist/cli/commands/lab-run.js +84 -54
  138. package/dist/cli/commands/lab-scorer.d.ts +2 -4
  139. package/dist/cli/commands/lab-scorer.js +1 -1
  140. package/dist/cli/commands/migrate.d.ts +4 -0
  141. package/dist/cli/commands/migrate.js +65 -0
  142. package/dist/cli/commands/observe.js +168 -107
  143. package/dist/cli/commands/run-command.d.ts +10 -0
  144. package/dist/cli/commands/run-command.js +85 -0
  145. package/dist/cli/commands/run-signals.d.ts +30 -0
  146. package/dist/cli/commands/run-signals.js +146 -0
  147. package/dist/cli/commands/runs.js +137 -136
  148. package/dist/cli/commands/setup.d.ts +2 -2
  149. package/dist/cli/commands/setup.js +26 -21
  150. package/dist/cli/commands/study.d.ts +3 -0
  151. package/dist/cli/commands/study.js +182 -0
  152. package/dist/cli/commands/tui.d.ts +4 -4
  153. package/dist/cli/commands/tui.js +21 -21
  154. package/dist/cli/commands/watch.js +64 -77
  155. package/dist/cli/deprecations.d.ts +18 -0
  156. package/dist/cli/deprecations.js +48 -0
  157. package/dist/cli/doctor.d.ts +18 -5
  158. package/dist/cli/doctor.js +111 -48
  159. package/dist/cli/first-run-path.d.ts +12 -10
  160. package/dist/cli/first-run-path.js +30 -28
  161. package/dist/cli/io.d.ts +46 -10
  162. package/dist/cli/io.js +109 -30
  163. package/dist/cli/observer-follow.d.ts +2 -2
  164. package/dist/cli/observer-follow.js +5 -6
  165. package/dist/cli/orientation.d.ts +6 -3
  166. package/dist/cli/orientation.js +43 -39
  167. package/dist/cli/product-sentence.d.ts +6 -0
  168. package/dist/cli/product-sentence.js +6 -0
  169. package/dist/cli/program.d.ts +6 -1
  170. package/dist/cli/program.js +112 -43
  171. package/dist/cli/telemetry.d.ts +17 -17
  172. package/dist/cli/telemetry.js +49 -41
  173. package/dist/cli.js +1 -1
  174. package/dist/comms/capture-surface.d.ts +14 -13
  175. package/dist/comms/capture-surface.js +23 -22
  176. package/dist/comms/catch-host.d.ts +8 -8
  177. package/dist/comms/catch-host.js +14 -14
  178. package/dist/comms/connections.js +4 -4
  179. package/dist/comms/email-catch.d.ts +3 -3
  180. package/dist/comms/email-catch.js +8 -8
  181. package/dist/comms/external-evidence.d.ts +27 -0
  182. package/dist/comms/external-evidence.js +93 -0
  183. package/dist/comms/extract.js +2 -2
  184. package/dist/comms/fake-inbox.d.ts +2 -2
  185. package/dist/comms/fake-inbox.js +2 -2
  186. package/dist/comms/lease-store.js +7 -7
  187. package/dist/comms/receiving-render.d.ts +1 -1
  188. package/dist/comms/receiving-render.js +2 -2
  189. package/dist/comms/sandbox-catch-script.d.ts +6 -6
  190. package/dist/comms/sandbox-catch-script.js +6 -6
  191. package/dist/comms/sandbox-catch.d.ts +36 -37
  192. package/dist/comms/sandbox-catch.js +34 -35
  193. package/dist/comms/setup.js +42 -8
  194. package/dist/comms/thread-evidence.d.ts +1 -1
  195. package/dist/comms/thread-evidence.js +6 -6
  196. package/dist/comms/types.d.ts +6 -6
  197. package/dist/comms/types.js +4 -4
  198. package/dist/evidence/browser-hygiene.d.ts +1 -1
  199. package/dist/evidence/browser-hygiene.js +1 -1
  200. package/dist/evidence/frame-signature.d.ts +1 -1
  201. package/dist/evidence/frame-signature.js +4 -4
  202. package/dist/evidence/redaction.d.ts +3 -3
  203. package/dist/evidence/redaction.js +5 -5
  204. package/dist/evidence/secret-scrub.d.ts +9 -0
  205. package/dist/evidence/secret-scrub.js +96 -0
  206. package/dist/feedback/draft.js +41 -85
  207. package/dist/feedback/export-bundle.js +5 -5
  208. package/dist/feedback/export.d.ts +5 -1
  209. package/dist/feedback/export.js +16 -17
  210. package/dist/feedback/feedback.d.ts +3 -3
  211. package/dist/feedback/feedback.js +21 -3
  212. package/dist/guest/chromium-text.js +2 -2
  213. package/dist/guest/desktop-native.d.ts +1 -1
  214. package/dist/guest/runtime.js +1 -1
  215. package/dist/index.d.ts +14 -15
  216. package/dist/index.js +10 -11
  217. package/dist/keys/key-resolution.d.ts +7 -5
  218. package/dist/keys/key-resolution.js +40 -38
  219. package/dist/lab/adapter-extension.d.ts +35 -13
  220. package/dist/lab/adapter-extension.js +50 -134
  221. package/dist/lab/adapter-scorer-loader.d.ts +32 -12
  222. package/dist/lab/adapter-scorer-loader.js +56 -32
  223. package/dist/lab/composition-rules.js +58 -58
  224. package/dist/lab/config.js +85 -43
  225. package/dist/lab/deprecated-fields.d.ts +10 -0
  226. package/dist/lab/deprecated-fields.js +24 -0
  227. package/dist/lab/device-presets.d.ts +10 -10
  228. package/dist/lab/device-presets.js +11 -11
  229. package/dist/lab/discover.d.ts +13 -9
  230. package/dist/lab/discover.js +118 -60
  231. package/dist/lab/doctor.d.ts +53 -11
  232. package/dist/lab/doctor.js +193 -47
  233. package/dist/lab/init-plan.js +1 -3
  234. package/dist/lab/init-templates.js +147 -147
  235. package/dist/lab/init.d.ts +1 -1
  236. package/dist/lab/init.js +41 -9
  237. package/dist/lab/keys.d.ts +2 -0
  238. package/dist/lab/keys.js +43 -9
  239. package/dist/lab/lab-deps.d.ts +80 -0
  240. package/dist/lab/lab-deps.js +4 -0
  241. package/dist/lab/parse/actors.js +17 -16
  242. package/dist/lab/parse/comms.js +8 -7
  243. package/dist/lab/parse/execution.js +15 -14
  244. package/dist/lab/parse/study-v3.d.ts +23 -0
  245. package/dist/lab/parse/study-v3.js +259 -0
  246. package/dist/lab/parse/subject-state.d.ts +7 -7
  247. package/dist/lab/parse/subject-state.js +18 -17
  248. package/dist/lab/parse/subject.js +30 -29
  249. package/dist/lab/parse/values.d.ts +1 -2
  250. package/dist/lab/parse/values.js +3 -6
  251. package/dist/lab/persona-resolve.d.ts +7 -7
  252. package/dist/lab/persona-resolve.js +8 -8
  253. package/dist/lab/persona.js +1 -3
  254. package/dist/lab/plan-base.d.ts +0 -2
  255. package/dist/lab/plan-base.js +6 -4
  256. package/dist/lab/plan-participants.d.ts +7 -7
  257. package/dist/lab/plan-participants.js +2 -2
  258. package/dist/lab/plan-types.d.ts +26 -8
  259. package/dist/lab/plan.d.ts +4 -18
  260. package/dist/lab/plan.js +24 -79
  261. package/dist/lab/preflight-probes.js +11 -11
  262. package/dist/lab/preflight-result.d.ts +2 -1
  263. package/dist/lab/preflight-result.js +5 -6
  264. package/dist/lab/preflight.d.ts +7 -8
  265. package/dist/lab/preflight.js +6 -6
  266. package/dist/lab/requirements.d.ts +20 -0
  267. package/dist/lab/requirements.js +54 -0
  268. package/dist/lab/route-inputs.d.ts +23 -12
  269. package/dist/lab/route-inputs.js +48 -51
  270. package/dist/lab/routing.d.ts +42 -41
  271. package/dist/lab/routing.js +66 -68
  272. package/dist/lab/run-lab-events.d.ts +3 -11
  273. package/dist/lab/run-lab-events.js +2 -16
  274. package/dist/lab/run-lab-homes.d.ts +76 -0
  275. package/dist/lab/run-lab-homes.js +7 -0
  276. package/dist/lab/run-lab-options.d.ts +12 -66
  277. package/dist/lab/run-lab-options.js +58 -285
  278. package/dist/lab/summary.d.ts +15 -9
  279. package/dist/lab/summary.js +24 -17
  280. package/dist/lab/tasks.d.ts +15 -15
  281. package/dist/lab/tasks.js +14 -14
  282. package/dist/lab/types.d.ts +201 -195
  283. package/dist/lab/types.js +2 -0
  284. package/dist/lab/validation.d.ts +21 -21
  285. package/dist/lab/validation.js +61 -59
  286. package/dist/lab/warnings.d.ts +10 -0
  287. package/dist/lab/warnings.js +70 -41
  288. package/dist/library-aliases.d.ts +56 -0
  289. package/dist/library-aliases.js +22 -0
  290. package/dist/observer/artifact.d.ts +2 -2
  291. package/dist/observer/artifact.js +9 -9
  292. package/dist/observer/data.d.ts +6 -6
  293. package/dist/observer/data.js +7 -6
  294. package/dist/observer/exposure.d.ts +1 -1
  295. package/dist/observer/exposure.js +11 -11
  296. package/dist/observer/http.js +1 -1
  297. package/dist/observer/library.d.ts +1 -1
  298. package/dist/observer/library.js +4 -2
  299. package/dist/observer/listen.js +5 -4
  300. package/dist/observer/render.d.ts +1 -1
  301. package/dist/observer/render.js +12 -7
  302. package/dist/observer/run-routes.d.ts +4 -4
  303. package/dist/observer/run-routes.js +6 -6
  304. package/dist/observer/serve.d.ts +17 -0
  305. package/dist/observer/serve.js +41 -6
  306. package/dist/observer/tunnel.js +1 -1
  307. package/dist/observer-app.html +4 -4
  308. package/dist/routes/computer-use/bundle-parts.d.ts +9 -9
  309. package/dist/routes/computer-use/bundle-parts.js +24 -17
  310. package/dist/routes/computer-use/bundle.d.ts +4 -11
  311. package/dist/routes/computer-use/bundle.js +12 -18
  312. package/dist/routes/computer-use/diagnostics.d.ts +1 -1
  313. package/dist/routes/computer-use/diagnostics.js +1 -1
  314. package/dist/routes/computer-use/e2b-desktop/comms.d.ts +11 -11
  315. package/dist/routes/computer-use/e2b-desktop/comms.js +24 -27
  316. package/dist/routes/computer-use/e2b-desktop/desktop.d.ts +2 -2
  317. package/dist/routes/computer-use/e2b-desktop/desktop.js +8 -11
  318. package/dist/routes/computer-use/e2b-desktop/fidelity.d.ts +16 -15
  319. package/dist/routes/computer-use/e2b-desktop/fidelity.js +20 -19
  320. package/dist/routes/computer-use/e2b-desktop/prepare.d.ts +3 -3
  321. package/dist/routes/computer-use/e2b-desktop/prepare.js +40 -43
  322. package/dist/routes/computer-use/e2b-desktop/start.d.ts +1 -1
  323. package/dist/routes/computer-use/e2b-desktop/start.js +32 -30
  324. package/dist/routes/computer-use/e2b-desktop/state.d.ts +5 -4
  325. package/dist/routes/computer-use/e2b-desktop/state.js +5 -3
  326. package/dist/routes/computer-use/e2b-desktop/teardown.d.ts +1 -1
  327. package/dist/routes/computer-use/e2b-desktop/teardown.js +33 -20
  328. package/dist/routes/computer-use/external-comms.d.ts +4 -4
  329. package/dist/routes/computer-use/external-comms.js +19 -43
  330. package/dist/routes/computer-use/fanout-bundle.d.ts +3 -3
  331. package/dist/routes/computer-use/fanout-bundle.js +38 -42
  332. package/dist/routes/computer-use/{fanout-lanes.js → fanout-records.js} +33 -28
  333. package/dist/routes/computer-use/in-process-desktop.d.ts +3 -10
  334. package/dist/routes/computer-use/in-process-desktop.js +3 -9
  335. package/dist/routes/computer-use/live-flush.d.ts +7 -5
  336. package/dist/routes/computer-use/live-flush.js +20 -28
  337. package/dist/routes/computer-use/{run-lanes.d.ts → live-phase.d.ts} +4 -2
  338. package/dist/routes/computer-use/{run-lanes.js → live-phase.js} +17 -16
  339. package/dist/routes/computer-use/local-tree-pack.d.ts +3 -3
  340. package/dist/routes/computer-use/local-tree-pack.js +4 -5
  341. package/dist/routes/computer-use/local-vm.d.ts +11 -8
  342. package/dist/routes/computer-use/local-vm.js +40 -67
  343. package/dist/routes/computer-use/participant-desktop.d.ts +8 -23
  344. package/dist/routes/computer-use/participant-desktop.js +5 -25
  345. package/dist/routes/computer-use/{lanes.d.ts → participant-execution.d.ts} +11 -11
  346. package/dist/routes/computer-use/{lanes.js → participant-execution.js} +39 -26
  347. package/dist/routes/computer-use/participant-facts.d.ts +7 -1
  348. package/dist/routes/computer-use/participant-facts.js +12 -1
  349. package/dist/routes/computer-use/participant-model.d.ts +25 -11
  350. package/dist/routes/computer-use/participant-model.js +76 -34
  351. package/dist/routes/computer-use/participant-prompt.d.ts +13 -13
  352. package/dist/routes/computer-use/participant-prompt.js +8 -8
  353. package/dist/routes/computer-use/participant-runs.d.ts +11 -11
  354. package/dist/routes/computer-use/participant-runs.js +18 -18
  355. package/dist/routes/computer-use/plan.d.ts +21 -29
  356. package/dist/routes/computer-use/plan.js +70 -78
  357. package/dist/routes/computer-use/preflight.d.ts +3 -5
  358. package/dist/routes/computer-use/preflight.js +40 -36
  359. package/dist/routes/computer-use/rerun-selection.js +11 -7
  360. package/dist/routes/computer-use/result.d.ts +1 -1
  361. package/dist/routes/computer-use/result.js +48 -38
  362. package/dist/routes/computer-use/route.d.ts +5 -5
  363. package/dist/routes/computer-use/route.js +36 -33
  364. package/dist/routes/computer-use/self-report.d.ts +8 -8
  365. package/dist/routes/computer-use/self-report.js +33 -33
  366. package/dist/routes/computer-use/setup.d.ts +9 -15
  367. package/dist/routes/computer-use/setup.js +106 -83
  368. package/dist/routes/computer-use/single-bundle.d.ts +13 -16
  369. package/dist/routes/computer-use/single-bundle.js +46 -53
  370. package/dist/routes/computer-use/subject-projection.d.ts +6 -8
  371. package/dist/routes/computer-use/subject-projection.js +24 -23
  372. package/dist/routes/computer-use/types.d.ts +195 -238
  373. package/dist/routes/computer-use/types.js +21 -13
  374. package/dist/routes/preview.d.ts +8 -2
  375. package/dist/routes/preview.js +8 -5
  376. package/dist/routes/scripted/bundle.d.ts +5 -8
  377. package/dist/routes/scripted/bundle.js +23 -27
  378. package/dist/routes/scripted/plan.d.ts +6 -8
  379. package/dist/routes/scripted/plan.js +15 -13
  380. package/dist/routes/scripted/result.d.ts +4 -1
  381. package/dist/routes/scripted/result.js +15 -11
  382. package/dist/routes/scripted/route.js +15 -17
  383. package/dist/routes/scripted/scenario.d.ts +1 -1
  384. package/dist/routes/scripted/scenario.js +3 -3
  385. package/dist/routes/scripted/setup.d.ts +3 -2
  386. package/dist/routes/scripted/setup.js +27 -26
  387. package/dist/routes/scripted/subject.d.ts +8 -3
  388. package/dist/routes/scripted/subject.js +10 -6
  389. package/dist/routes/scripted/surface-records.js +4 -4
  390. package/dist/routes/scripted/surface-sessions.d.ts +2 -2
  391. package/dist/routes/scripted/surface-sessions.js +4 -4
  392. package/dist/routes/scripted/types.d.ts +21 -40
  393. package/dist/routes/scripted/types.js +2 -3
  394. package/dist/routes/shared-world/{seat-records.js → bundle-records.js} +17 -16
  395. package/dist/routes/shared-world/bundle.d.ts +7 -7
  396. package/dist/routes/shared-world/bundle.js +60 -62
  397. package/dist/routes/shared-world/checkpoints.d.ts +5 -5
  398. package/dist/routes/shared-world/checkpoints.js +5 -5
  399. package/dist/routes/shared-world/comms.d.ts +8 -7
  400. package/dist/routes/shared-world/comms.js +38 -51
  401. package/dist/routes/shared-world/external-public.d.ts +6 -5
  402. package/dist/routes/shared-world/external-public.js +28 -25
  403. package/dist/routes/shared-world/handoff.d.ts +10 -9
  404. package/dist/routes/shared-world/handoff.js +89 -81
  405. package/dist/routes/shared-world/lobby-code.d.ts +7 -7
  406. package/dist/routes/shared-world/lobby-code.js +22 -22
  407. package/dist/routes/shared-world/{seats.d.ts → participant-specs.d.ts} +15 -12
  408. package/dist/routes/shared-world/{seats.js → participant-specs.js} +65 -63
  409. package/dist/routes/shared-world/plan.d.ts +2 -6
  410. package/dist/routes/shared-world/plan.js +8 -9
  411. package/dist/routes/shared-world/provenance.d.ts +4 -4
  412. package/dist/routes/shared-world/provenance.js +4 -4
  413. package/dist/routes/shared-world/provisioned.d.ts +3 -2
  414. package/dist/routes/shared-world/provisioned.js +55 -48
  415. package/dist/routes/shared-world/result.js +47 -36
  416. package/dist/routes/shared-world/route.js +54 -57
  417. package/dist/routes/shared-world/setup.d.ts +6 -5
  418. package/dist/routes/shared-world/setup.js +16 -18
  419. package/dist/routes/shared-world/types.d.ts +70 -141
  420. package/dist/routes/shared-world/types.js +5 -5
  421. package/dist/routes/terminal/adapter.d.ts +10 -10
  422. package/dist/routes/terminal/adapter.js +32 -129
  423. package/dist/routes/terminal/bundle.d.ts +10 -15
  424. package/dist/routes/terminal/bundle.js +43 -52
  425. package/dist/routes/terminal/credentials.d.ts +4 -4
  426. package/dist/routes/terminal/credentials.js +20 -20
  427. package/dist/routes/terminal/dry-run.d.ts +1 -1
  428. package/dist/routes/terminal/dry-run.js +13 -15
  429. package/dist/routes/terminal/encoding.d.ts +1 -1
  430. package/dist/routes/terminal/encoding.js +4 -4
  431. package/dist/routes/terminal/ledger.d.ts +8 -8
  432. package/dist/routes/terminal/ledger.js +22 -22
  433. package/dist/routes/terminal/live-finish.d.ts +1 -2
  434. package/dist/routes/terminal/live-finish.js +24 -23
  435. package/dist/routes/terminal/live-sandbox.d.ts +3 -2
  436. package/dist/routes/terminal/live-sandbox.js +31 -32
  437. package/dist/routes/terminal/participant-text.d.ts +23 -0
  438. package/dist/routes/terminal/participant-text.js +165 -0
  439. package/dist/routes/terminal/persona.js +1 -1
  440. package/dist/routes/terminal/plan.d.ts +2 -6
  441. package/dist/routes/terminal/plan.js +23 -19
  442. package/dist/routes/terminal/recorder.d.ts +6 -1
  443. package/dist/routes/terminal/recorder.js +12 -4
  444. package/dist/routes/terminal/result.js +12 -12
  445. package/dist/routes/terminal/route.js +30 -31
  446. package/dist/routes/terminal/runtime.d.ts +3 -2
  447. package/dist/routes/terminal/runtime.js +3 -3
  448. package/dist/routes/terminal/sandbox.d.ts +4 -4
  449. package/dist/routes/terminal/sandbox.js +10 -10
  450. package/dist/routes/terminal/session.js +22 -19
  451. package/dist/routes/terminal/token-usage.d.ts +1 -1
  452. package/dist/routes/terminal/token-usage.js +10 -11
  453. package/dist/routes/terminal/trace.d.ts +7 -10
  454. package/dist/routes/terminal/trace.js +11 -66
  455. package/dist/routes/terminal/types.d.ts +104 -114
  456. package/dist/routes/terminal/types.js +12 -7
  457. package/dist/run/active-runs.d.ts +13 -0
  458. package/dist/run/active-runs.js +12 -0
  459. package/dist/run/bundle-shape.d.ts +2 -1
  460. package/dist/run/bundle-shape.js +7 -7
  461. package/dist/run/bundle.d.ts +99 -92
  462. package/dist/run/bundle.js +10 -8
  463. package/dist/run/cost-summary.js +6 -5
  464. package/dist/run/costs.d.ts +6 -6
  465. package/dist/run/costs.js +17 -11
  466. package/dist/run/detail.d.ts +9 -9
  467. package/dist/run/detail.js +10 -10
  468. package/dist/run/dry-run-inputs.js +1 -1
  469. package/dist/run/dry-run.js +23 -30
  470. package/dist/run/{study-files.d.ts → evidence-files.d.ts} +4 -4
  471. package/dist/run/{study-files.js → evidence-files.js} +5 -5
  472. package/dist/run/feedback-shape.js +1 -1
  473. package/dist/run/judge.d.ts +34 -16
  474. package/dist/run/judge.js +41 -14
  475. package/dist/run/locate.d.ts +2 -0
  476. package/dist/run/locate.js +3 -1
  477. package/dist/run/outcomes.d.ts +3 -3
  478. package/dist/run/outcomes.js +3 -3
  479. package/dist/run/participant-records.d.ts +2 -2
  480. package/dist/run/participant-records.js +2 -2
  481. package/dist/run/paths.d.ts +1 -1
  482. package/dist/run/paths.js +2 -2
  483. package/dist/run/pricing.d.ts +30 -15
  484. package/dist/run/pricing.js +49 -30
  485. package/dist/run/projection.d.ts +27 -27
  486. package/dist/run/projection.js +23 -23
  487. package/dist/run/reclaim.d.ts +6 -0
  488. package/dist/run/reclaim.js +15 -5
  489. package/dist/run/results.d.ts +5 -5
  490. package/dist/run/run-index.d.ts +9 -7
  491. package/dist/run/run-index.js +24 -25
  492. package/dist/run/run-not-found.d.ts +5 -0
  493. package/dist/run/run-not-found.js +15 -0
  494. package/dist/run/run.d.ts +7 -4
  495. package/dist/run/run.js +10 -6
  496. package/dist/run/sandbox-receipts.d.ts +5 -5
  497. package/dist/run/sandbox-receipts.js +6 -6
  498. package/dist/run/shared-world-evidence.d.ts +67 -66
  499. package/dist/run/shared-world-evidence.js +4 -4
  500. package/dist/run/shared-world-shape.d.ts +3 -3
  501. package/dist/run/shared-world-shape.js +16 -16
  502. package/dist/run/stats.d.ts +17 -11
  503. package/dist/run/stats.js +124 -66
  504. package/dist/run/status.d.ts +21 -32
  505. package/dist/run/status.js +34 -33
  506. package/dist/run/stored-runs.js +2 -1
  507. package/dist/run/stream-shape.js +1 -1
  508. package/dist/run/streams.d.ts +29 -22
  509. package/dist/run/study-provenance.d.ts +47 -0
  510. package/dist/run/study-provenance.js +63 -0
  511. package/dist/run/study-result.d.ts +16 -0
  512. package/dist/run/study-result.js +9 -0
  513. package/dist/run/terminal-contract.d.ts +5 -5
  514. package/dist/run/terminal-contract.js +4 -4
  515. package/dist/run/text.d.ts +2 -0
  516. package/dist/run/text.js +4 -0
  517. package/dist/run/transient-comms-secrets.d.ts +5 -0
  518. package/dist/run/transient-comms-secrets.js +12 -0
  519. package/dist/run-lab.d.ts +40 -38
  520. package/dist/run-lab.js +42 -40
  521. package/dist/study/convert.d.ts +33 -0
  522. package/dist/study/convert.js +432 -0
  523. package/dist/study/field-paths.d.ts +12 -0
  524. package/dist/study/field-paths.js +126 -0
  525. package/dist/study/files.d.ts +26 -0
  526. package/dist/study/files.js +43 -0
  527. package/dist/study/migrate.d.ts +48 -0
  528. package/dist/study/migrate.js +408 -0
  529. package/dist/study/owned-files.d.ts +38 -0
  530. package/dist/study/owned-files.js +182 -0
  531. package/dist/subject/clone.d.ts +1 -1
  532. package/dist/subject/desktop-cli.d.ts +2 -2
  533. package/dist/subject/desktop-cli.js +3 -3
  534. package/dist/subject/local-tree-archive.d.ts +1 -1
  535. package/dist/subject/local-tree-archive.js +5 -5
  536. package/dist/subject/local-tree.d.ts +3 -3
  537. package/dist/subject/local-tree.js +1 -1
  538. package/dist/subject/node-bootstrap.d.ts +1 -1
  539. package/dist/subject/node-bootstrap.js +4 -4
  540. package/dist/subject/runtime.js +10 -11
  541. package/dist/subject/serve.d.ts +1 -1
  542. package/dist/subject/serve.js +4 -4
  543. package/dist/subject/state.d.ts +1 -1
  544. package/dist/subject/steps.d.ts +8 -8
  545. package/dist/subject/steps.js +7 -7
  546. package/dist/substrates/command-failure.d.ts +3 -3
  547. package/dist/substrates/command-failure.js +3 -3
  548. package/dist/substrates/detached.d.ts +6 -6
  549. package/dist/substrates/detached.js +7 -7
  550. package/dist/substrates/e2b/cdp-probe.d.ts +11 -11
  551. package/dist/substrates/e2b/cdp-probe.js +15 -18
  552. package/dist/substrates/e2b/desktop-browser.d.ts +5 -5
  553. package/dist/substrates/e2b/desktop-browser.js +12 -12
  554. package/dist/substrates/e2b/desktop-cdp.d.ts +15 -15
  555. package/dist/substrates/e2b/desktop-cdp.js +11 -11
  556. package/dist/substrates/e2b/desktop-executor.d.ts +1 -1
  557. package/dist/substrates/e2b/desktop-executor.js +1 -1
  558. package/dist/substrates/e2b/desktop-geometry.d.ts +6 -6
  559. package/dist/substrates/e2b/desktop-geometry.js +9 -9
  560. package/dist/substrates/e2b/desktop-media.d.ts +1 -1
  561. package/dist/substrates/e2b/desktop-media.js +3 -3
  562. package/dist/substrates/e2b/desktop-screenshot-cleanup.d.ts +3 -3
  563. package/dist/substrates/e2b/desktop-screenshot-cleanup.js +3 -3
  564. package/dist/substrates/e2b/sandbox.d.ts +1 -1
  565. package/dist/substrates/e2b/sandbox.js +2 -2
  566. package/dist/substrates/e2b/sdk.d.ts +11 -11
  567. package/dist/substrates/e2b/sdk.js +8 -8
  568. package/dist/substrates/local/runtime-host.d.ts +2 -0
  569. package/dist/substrates/local/runtime-host.js +6 -0
  570. package/dist/tui/actions.d.ts +8 -6
  571. package/dist/tui/actions.js +31 -22
  572. package/dist/tui/contract.d.ts +16 -16
  573. package/dist/tui/contract.js +10 -10
  574. package/dist/tui/launch.d.ts +4 -4
  575. package/dist/tui/launch.js +18 -19
  576. package/dist/tui/project.js +5 -5
  577. package/dist/tui-app.js +83 -83
  578. package/dist/verify/actor.d.ts +14 -14
  579. package/dist/verify/actor.js +45 -45
  580. package/dist/verify/artifacts.d.ts +3 -3
  581. package/dist/verify/artifacts.js +6 -6
  582. package/dist/verify/context-growth.d.ts +9 -0
  583. package/dist/verify/context-growth.js +62 -0
  584. package/dist/verify/costs.d.ts +7 -7
  585. package/dist/verify/costs.js +9 -9
  586. package/dist/verify/liveness.d.ts +1 -1
  587. package/dist/verify/liveness.js +4 -1
  588. package/dist/verify/rerun.d.ts +1 -1
  589. package/dist/verify/rerun.js +1 -1
  590. package/dist/verify/shared-world-concurrent.d.ts +2 -2
  591. package/dist/verify/shared-world-concurrent.js +79 -76
  592. package/dist/verify/shared-world.d.ts +2 -2
  593. package/dist/verify/shared-world.js +18 -18
  594. package/dist/verify/subject.d.ts +4 -4
  595. package/dist/verify/subject.js +18 -18
  596. package/dist/verify/verify.js +98 -49
  597. package/docs/README.md +26 -33
  598. package/docs/architecture/actor-contract.md +105 -98
  599. package/docs/architecture/desktop-sessions.md +14 -14
  600. package/docs/architecture/external-public-shared-world.md +66 -59
  601. package/docs/architecture/github-feedback-loop.md +1 -4
  602. package/docs/architecture/guest-desktop.md +2 -2
  603. package/docs/architecture/observer.md +37 -37
  604. package/docs/architecture/restricted-codex-analysis.md +70 -30
  605. package/docs/architecture/serve.md +34 -37
  606. package/docs/architecture/state-driven-executor.md +55 -59
  607. package/docs/architecture/task-protocol-support.md +7 -9
  608. package/docs/architecture/{terminal-product-lane.md → terminal-product-route.md} +83 -115
  609. package/docs/contracts/README.md +24 -0
  610. package/docs/contracts/adapter-admission.md +3 -3
  611. package/docs/contracts/adapter-fixtures.md +2 -5
  612. package/docs/contracts/core.md +1 -3
  613. package/docs/contracts/errors.md +62 -0
  614. package/docs/contracts/feedback.md +8 -9
  615. package/docs/contracts/policy.md +7 -12
  616. package/docs/contracts/run-bundle.md +54 -51
  617. package/docs/contracts/schemas.md +505 -390
  618. package/docs/contracts/study-analysis.md +26 -2
  619. package/docs/contracts/study-costs.md +11 -7
  620. package/docs/decisions/0001-run-bundle-is-the-source-of-truth.md +1 -1
  621. package/docs/decisions/0002-observer-is-one-self-contained-file.md +2 -2
  622. package/docs/decisions/0003-contained-paths-and-cleanup-authority.md +3 -3
  623. package/docs/decisions/0004-participant-desktops-stay-in-the-route.md +2 -1
  624. package/docs/principles/actor-fidelity.md +4 -4
  625. package/docs/principles/engineering.md +3 -3
  626. package/docs/principles/invariants-and-defaults.md +38 -38
  627. package/docs/principles/self-driving-harness.md +1 -5
  628. package/docs/principles/three-roles.md +1 -1
  629. package/docs/product/automatic-analysis.md +8 -7
  630. package/examples/participant/README.md +5 -5
  631. package/examples/participant/run.mjs +11 -10
  632. package/examples/scorer/README.md +3 -3
  633. package/examples/scorer/run.mjs +11 -12
  634. package/package.json +16 -17
  635. package/skills/humanish/SKILL.md +63 -60
  636. package/skills/humanish/agents/openai.yaml +1 -1
  637. package/AGENTS.md +0 -99
  638. package/CONTRIBUTING.md +0 -148
  639. package/dist/actors/codex/qualified-versions.d.ts +0 -45
  640. package/dist/actors/codex/qualified-versions.js +0 -87
  641. package/dist/cli/commands/lab.d.ts +0 -3
  642. package/dist/cli/commands/lab.js +0 -193
  643. package/dist/deprecated.d.ts +0 -90
  644. package/dist/deprecated.js +0 -106
  645. package/dist/lab/bag-overrides.d.ts +0 -18
  646. package/dist/lab/bag-overrides.js +0 -121
  647. package/dist/observer/static.d.ts +0 -39
  648. package/dist/observer/static.js +0 -369
  649. package/dist/routes/computer-use/legacy-lane-spec.d.ts +0 -62
  650. package/dist/routes/computer-use/legacy-lane-spec.js +0 -39
  651. package/docs/architecture/comms-inbox.md +0 -122
  652. package/docs/architecture/desktop-recording.md +0 -80
  653. package/docs/architecture/local-browser-runtime.md +0 -178
  654. package/docs/architecture/observer-review.md +0 -144
  655. package/docs/architecture/participant-media.md +0 -90
  656. package/docs/architecture/project-layout.md +0 -62
  657. package/docs/architecture/real-email-receiving.md +0 -136
  658. package/docs/assets/humanish-drawdb-hero.png +0 -0
  659. package/docs/assets/humanish-observer-hero.png +0 -0
  660. package/docs/goals/current.md +0 -207
  661. package/docs/product/lobby-trivia-3player-external-public.md +0 -77
  662. package/docs/product/open-source-install-experience.md +0 -240
  663. package/docs/ramp/README.md +0 -294
  664. package/docs/release/open-source-readiness.md +0 -222
  665. package/docs/release/public-readiness-standard.md +0 -210
  666. package/docs/roadmap/world-class-open-source-v0.md +0 -311
  667. /package/dist/routes/computer-use/{fanout-lanes.d.ts → fanout-records.d.ts} +0 -0
  668. /package/dist/routes/shared-world/{seat-records.d.ts → bundle-records.d.ts} +0 -0
package/dist/run/judge.js CHANGED
@@ -6,7 +6,7 @@
6
6
  // participantPassed, participantHarnessFailed);
7
7
  // 2. the judgment shapes (Judgment and judgmentOf, SharedWorldJudgment, ExecutionOutcome,
8
8
  // OutcomePolicy);
9
- // 3. one judge per route: computer-use calls judgeOneParticipant (one lane, no rerun) or
9
+ // 3. one judge per route: computer-use calls judgeOneParticipant (one participant, no rerun) or
10
10
  // judgeParticipants, shared-world calls judgeSharedWorld, terminal calls judgeTerminal,
11
11
  // scripted calls judgeScripted and preview calls judgePreview;
12
12
  // 4. foldScorerFailures, which every route with a scorer applies before the run finishes;
@@ -24,7 +24,7 @@ export function hollowCompletion(ending) {
24
24
  }
25
25
  /**
26
26
  * The participant said it reached the goal but reported a blocker. A declared outcome is its own
27
- * word and wins (#570). Without one, the closing report is read, unless a stop condition ended the
27
+ * word and wins. Without one, the closing report is read, unless a stop condition ended the
28
28
  * session: a matched stopWhen is structured completion evidence and overrides the text.
29
29
  */
30
30
  export function selfReportedBlocker(ending) {
@@ -65,7 +65,7 @@ export function participantHarnessFailed(participant) {
65
65
  * goal_satisfied claim with zero engagement is a session that ran out before anything happened;
66
66
  * one whose final message describes a blocker is a participant who could not proceed and said so.
67
67
  * Both keep their trace status (the claim is evidence); neither is a participant who reached the
68
- * goal. One rule for the single lane and the fan-out roll-up (#476).
68
+ * goal. One rule for the single participant and the fan-out roll-up.
69
69
  */
70
70
  export function participantStatus(status, judgments) {
71
71
  if (status !== "passed" || judgments === undefined)
@@ -76,6 +76,16 @@ export function participantStatus(status, judgments) {
76
76
  return "blocked";
77
77
  return status;
78
78
  }
79
+ /**
80
+ * A verdict as review.md prints it. The schema keeps `contract_proof_only`, which a dry run always
81
+ * gets and a live run gets while it is in progress or when no participant result came back, so
82
+ * the reader sees "dry run" or "no verdict" by the run's mode.
83
+ */
84
+ export function verdictText(verdict, mode) {
85
+ if (verdict !== "contract_proof_only")
86
+ return verdict;
87
+ return mode === "dry-run" ? "dry run" : "no verdict";
88
+ }
79
89
  /** The review verdict for one participant's status. */
80
90
  export function verdictForStatus(status) {
81
91
  switch (status) {
@@ -98,6 +108,17 @@ export function verdictForStatus(status) {
98
108
  export function judgmentOf(verdict, dryRun) {
99
109
  return { verdict, passed: dryRun || verdict === "pass" };
100
110
  }
111
+ /**
112
+ * The execution failure for one sandbox whose release is unconfirmed. `warning` is the route's
113
+ * release warning, already scrubbed. `recovery` says how to release it by hand; without one,
114
+ * reclaim kills by the id the run recorded at create time.
115
+ */
116
+ export function sandboxCleanupFailure(owner, warning, runId, recovery) {
117
+ return {
118
+ kind: "sandbox-cleanup",
119
+ message: `${owner}: ${warning ?? "Sandbox release is unconfirmed."} ${recovery ?? `Reclaim it by recorded id with \`humanish reclaim --run ${runId}\`.`}`,
120
+ };
121
+ }
101
122
  /** Each route's outcome policy, in one place. */
102
123
  export const OUTCOME_POLICIES = {
103
124
  "computer-use": { participants: "gate", sandboxCleanup: "warns", evidence: "fails" },
@@ -111,7 +132,7 @@ export const OUTCOME_POLICIES = {
111
132
  * A run with one participant: its tallied status is the verdict, so a hollow pass fails and a
112
133
  * self-reported blocker reads as blocked. Without a session, a harness failure fails the run and
113
134
  * a dry run is a contract. A run still in progress is a contract until it finishes. Computer-use
114
- * calls it for one lane with no rerun, and terminal calls it through judgeTerminal.
135
+ * calls it for one participant with no rerun, and terminal calls it through judgeTerminal.
115
136
  */
116
137
  export function judgeOneParticipant(args) {
117
138
  const status = args.participant === undefined ? undefined : judgedStatus(args.participant);
@@ -137,9 +158,9 @@ export function judgeParticipants(args) {
137
158
  return judgmentOf(verdict, args.dryRun);
138
159
  }
139
160
  /**
140
- * Why a shared-world run whose seats all passed still fails, or undefined when its world facts
141
- * meet what verify's shared-world check requires of a pass: two seats live at the same time and,
142
- * on the provisioned plane, a shared-state change at or after the first overlap started.
161
+ * Why a shared-world run whose participants all passed still fails, or undefined when its world
162
+ * facts meet what verify's shared-world check requires of a pass: two participants live at the same
163
+ * time and, on the provisioned plane, a shared-state change at or after the first overlap started.
143
164
  */
144
165
  export function sharedWorldShortfall(world) {
145
166
  if (!world.overlap) {
@@ -151,9 +172,9 @@ export function sharedWorldShortfall(world) {
151
172
  return undefined;
152
173
  }
153
174
  /**
154
- * A shared-world run: it passes only when every expected seat passed and the world facts have no
155
- * shortfall, and otherwise fails (this route has no timed_out verdict). A dry run and a run still
156
- * in progress are contracts. Lobby convergence is recorded but not read.
175
+ * A shared-world run: it passes only when every expected participant passed and the world facts
176
+ * have no shortfall, and otherwise fails (this route has no timed_out verdict). A dry run and a run
177
+ * still in progress are contracts. Lobby convergence is recorded but not read.
157
178
  */
158
179
  export function judgeSharedWorld(args) {
159
180
  const passed = args.participants.length === args.expected &&
@@ -220,14 +241,20 @@ export function foldScorerFailures(review, failures) {
220
241
  }
221
242
  return folded;
222
243
  }
223
- /** The run's execution outcome under its route's policy. A failure of a kind the policy lets warn is dropped. */
244
+ /** The run's execution outcome under its route's policy. A failure of a kind the policy lets warn is a warning. */
224
245
  export function judgeExecution(failures, policy) {
225
- const counted = failures.filter((failure) => failure.kind === "sandbox-cleanup"
246
+ const counts = (failure) => failure.kind === "sandbox-cleanup"
226
247
  ? policy.sandboxCleanup === "fails"
227
248
  : failure.kind === "evidence"
228
249
  ? policy.evidence === "fails"
229
- : true);
230
- return { succeeded: counted.length === 0, failures: counted };
250
+ : true;
251
+ const counted = failures.filter(counts);
252
+ const warnings = failures.filter((failure) => !counts(failure));
253
+ return {
254
+ succeeded: counted.length === 0,
255
+ failures: counted,
256
+ ...(warnings.length === 0 ? {} : { warnings }),
257
+ };
231
258
  }
232
259
  /**
233
260
  * The result's ok: the run worked as an execution, no scorer failed it, and on a gate route every
@@ -2,6 +2,8 @@ import { type PreparedRunArtifactPaths } from "./paths.js";
2
2
  import { type PreparedSelectedOutputDirectory } from "./contained-output.js";
3
3
  import type { RunPointer } from "./results.js";
4
4
  import { type RunBundle } from "./bundle.js";
5
+ /** The run input that resolves through latest.json rather than naming a run directory. */
6
+ export declare const LATEST_RUN_ALIAS = "latest";
5
7
  /** Resolve "latest" or an explicit run id to its prepared artifact paths. */
6
8
  export declare function resolveRunPath(cwd: string, runInput: string): Promise<PreparedRunArtifactPaths | null>;
7
9
  export declare function readLatest(runsRoot: PreparedSelectedOutputDirectory): Promise<RunPointer | null>;
@@ -5,9 +5,11 @@ import { assertPreparedSelectedOutputDirectory, bindExistingManagedHumanishOutpu
5
5
  import { RUN_BUNDLE_FILE } from "./bundle.js";
6
6
  import { isRunBundle, isRunPointer } from "./bundle-shape.js";
7
7
  import { isNodeError } from "./type-guards.js";
8
+ /** The run input that resolves through latest.json rather than naming a run directory. */
9
+ export const LATEST_RUN_ALIAS = "latest";
8
10
  /** Resolve "latest" or an explicit run id to its prepared artifact paths. */
9
11
  export async function resolveRunPath(cwd, runInput) {
10
- if (runInput === "latest") {
12
+ if (runInput === LATEST_RUN_ALIAS) {
11
13
  const runsRoot = await bindExistingManagedHumanishOutputDirectory(cwd, "runs");
12
14
  if (!runsRoot) {
13
15
  return null;
@@ -1,16 +1,16 @@
1
1
  import { type ActorStatus } from "../actors/contract.js";
2
2
  import { type CuaGoalSource } from "../actors/goal-source.js";
3
3
  import type { TaskFunnel } from "../lab/tasks.js";
4
- import type { ParticipantOutcomes, ReviewSummary, StudyTaskFunnel } from "./bundle.js";
4
+ import type { ParticipantOutcomes, ReviewSummary, RunTaskFunnel } from "./bundle.js";
5
5
  /** Tally participant outcomes from actor statuses. Statuses this does not recognise are counted in
6
6
  * `total` but nowhere else, so the parts can never exceed the whole. */
7
7
  export declare function tallyParticipantOutcomes(statuses: readonly ActorStatus[],
8
8
  /** Per-participant: did this one report friction or a defect? Same order as `statuses`. */
9
9
  reportedFriction?: readonly boolean[]): ParticipantOutcomes;
10
10
  /** Roll per-participant funnels up into the study funnel. Undefined when nothing measured one. */
11
- export declare function aggregateTaskFunnels(funnels: readonly TaskFunnel[]): StudyTaskFunnel | undefined;
11
+ export declare function aggregateTaskFunnels(funnels: readonly TaskFunnel[]): RunTaskFunnel | undefined;
12
12
  /** The funnel as one line, denominator on every number: `signup 2/2 · verify-email 1/2`. */
13
- export declare function formatStudyTaskFunnel(funnel: StudyTaskFunnel): string;
13
+ export declare function formatRunTaskFunnel(funnel: RunTaskFunnel): string;
14
14
  type ParticipantOutcomeDetail = {
15
15
  status: ActorStatus;
16
16
  label?: string;
@@ -68,7 +68,7 @@ export function aggregateTaskFunnels(funnels) {
68
68
  };
69
69
  }
70
70
  /** The funnel as one line, denominator on every number: `signup 2/2 · verify-email 1/2`. */
71
- export function formatStudyTaskFunnel(funnel) {
71
+ export function formatRunTaskFunnel(funnel) {
72
72
  if (funnel.tasks.length === 0)
73
73
  return "no tasks declared";
74
74
  return funnel.tasks
@@ -138,7 +138,7 @@ export function formatParticipantOutcomes(outcomes, terminalCauses = []) {
138
138
  };
139
139
  append(outcomes.abandoned, ["abandoned"], "gave up");
140
140
  append(outcomes.ranOut, ["incomplete", "timed_out"], "interrupted (stop details unavailable)");
141
- // "blocked" covers an approval the run could not give AND a blocker the participant reported in
141
+ // "blocked" covers an approval the run could not give and a blocker the participant reported in
142
142
  // its own words, so the label names no cause.
143
143
  if (outcomes.blocked > 0)
144
144
  parts.push(`${outcomes.blocked} blocked`);
@@ -191,7 +191,7 @@ export function withCuaReviewProvenance(review, streams) {
191
191
  const outcomes = formatParticipantOutcomes(review.participants, details);
192
192
  // Preserve rerun context, participant narration and adapter-specific findings. Refreshing a
193
193
  // historical summary qualifies its old tally instead of silently discarding that context.
194
- const header = `Run gate: ${review.verdict}. Participants: ${outcomes}.${review.tasks ? ` Tasks: ${formatStudyTaskFunnel(review.tasks)}.` : ""}`;
194
+ const header = `Run gate: ${review.verdict}. Participants: ${outcomes}.${review.tasks ? ` Tasks: ${formatRunTaskFunnel(review.tasks)}.` : ""}`;
195
195
  const prefix = `${header} Recorded summary: `;
196
196
  const recorded = review.summary.startsWith(prefix)
197
197
  ? review.summary.slice(prefix.length)
@@ -12,7 +12,7 @@ export declare function participantIds(position: number): ParticipantIds;
12
12
  /** A participant's record, at its 1-based place in the bundle, with its one stream. */
13
13
  export declare function participantRecord(ids: ParticipantIds, place: number, fields: Omit<RunSimulation, "id" | "index" | "streamIds">): RunSimulation;
14
14
  /**
15
- * A participant's stream. `participantId` is the route's own participant id (a fan-out lane's id),
15
+ * A participant's stream. `participantId` is the route's own participant id (a fan-out entry's `lane-NN` id),
16
16
  * saved right after the record id when the route has one.
17
17
  */
18
18
  export declare function participantStream(ids: ParticipantIds, fields: Omit<RunStream, "id" | "simId" | "laneId">, participantId?: string): RunStream;
@@ -24,5 +24,5 @@ export declare function participantResourceIds(ids: ParticipantIds, participantI
24
24
  export declare function recordIdOf(stream: RunStream): string;
25
25
  /** The record id a saved event names, when it names one. */
26
26
  export declare function eventRecordIdOf(event: RunEvent): string | undefined;
27
- /** The participant id an adapter recorded on a saved stream (a fan-out lane id), when it has one. */
27
+ /** The participant id an adapter recorded on a saved stream (a fan-out `lane-NN` id), when it has one. */
28
28
  export declare function streamParticipantIdOf(stream: RunStream): string | undefined;
@@ -30,7 +30,7 @@ export function participantRecord(ids, place, fields) {
30
30
  };
31
31
  }
32
32
  /**
33
- * A participant's stream. `participantId` is the route's own participant id (a fan-out lane's id),
33
+ * A participant's stream. `participantId` is the route's own participant id (a fan-out entry's `lane-NN` id),
34
34
  * saved right after the record id when the route has one.
35
35
  */
36
36
  export function participantStream(ids, fields, participantId) {
@@ -57,7 +57,7 @@ export function recordIdOf(stream) {
57
57
  export function eventRecordIdOf(event) {
58
58
  return event.simId;
59
59
  }
60
- /** The participant id an adapter recorded on a saved stream (a fan-out lane id), when it has one. */
60
+ /** The participant id an adapter recorded on a saved stream (a fan-out `lane-NN` id), when it has one. */
61
61
  export function streamParticipantIdOf(stream) {
62
62
  return stream.laneId;
63
63
  }
@@ -49,7 +49,7 @@ export declare function createRunArtifactPaths(cwdInput: string, runId: string):
49
49
  export declare function validatePreparedRunArtifactPaths(prepared: PreparedRunArtifactPaths): Promise<PreparedRunArtifactPaths>;
50
50
  /**
51
51
  * The physical project directory for a caller's cwd, bound before a run is resolved so a symlinked
52
- * cwd retargeted later cannot move reads or writes to another project (#1012). A cwd that does not
52
+ * cwd retargeted later cannot move reads or writes to another project. A cwd that does not
53
53
  * resolve is returned as given, so the caller still reports it missing.
54
54
  */
55
55
  export declare function resolvePhysicalCwd(cwdInput: string): Promise<string>;
package/dist/run/paths.js CHANGED
@@ -107,7 +107,7 @@ export async function validatePreparedRunArtifactPaths(prepared) {
107
107
  }
108
108
  /**
109
109
  * The physical project directory for a caller's cwd, bound before a run is resolved so a symlinked
110
- * cwd retargeted later cannot move reads or writes to another project (#1012). A cwd that does not
110
+ * cwd retargeted later cannot move reads or writes to another project. A cwd that does not
111
111
  * resolve is returned as given, so the caller still reports it missing.
112
112
  */
113
113
  export async function resolvePhysicalCwd(cwdInput) {
@@ -262,7 +262,7 @@ async function assertNoSymlinkDescendants(directory) {
262
262
  const entries = await readdir(directory, { withFileTypes: true });
263
263
  for (const entry of entries) {
264
264
  const child = path.join(directory, entry.name);
265
- // A run directory can be written CONCURRENTLY with this walk — the atomic writer creates a
265
+ // A run directory can be written concurrently with this walk: the atomic writer creates a
266
266
  // `.humanish-write-*.tmp` sibling and renames it, and a run now also refreshes its own status
267
267
  // record on a cadence. An entry that vanished between readdir and lstat therefore proves
268
268
  // nothing except that it is gone, and a path that no longer exists cannot be a symlink escape:
@@ -10,12 +10,12 @@ export interface ModelRate {
10
10
  * a reduced rate. Optional: absent means we do not model a discount and every input token is
11
11
  * billed at `inputUsdPerToken`. */
12
12
  cachedInputUsdPerToken?: number;
13
- /** USD per input token newly WRITTEN to the provider's prompt cache, when the provider bills
13
+ /** USD per input token newly written to the provider's prompt cache, when the provider bills
14
14
  * writes (OpenAI: GPT-5.6+ bills `cache_write_tokens` at 1.25x the uncached input rate, as the
15
- * TOTAL rate for those tokens — not an extra charge on top). Absent = writes are free (every
15
+ * total rate for those tokens, with no extra charge on top). Absent = writes are free (every
16
16
  * pre-5.6 model) and any reported write tokens price at the plain input rate. */
17
17
  cacheWriteUsdPerToken?: number;
18
- /** Long-context tier, when the provider re-prices the WHOLE request past an input-size
18
+ /** Long-context tier, when the provider re-prices the whole request past an input-size
19
19
  * threshold (OpenAI GPT-5.6: >272K input tokens => 2x input-side, 1.5x output, full request).
20
20
  * Priced exactly only when the usage carries per-request `turns` records; totals alone cannot
21
21
  * say which requests crossed, so without turns the estimate stays on the short-context rate,
@@ -25,11 +25,11 @@ export interface ModelRate {
25
25
  inputMultiplier: number;
26
26
  outputMultiplier: number;
27
27
  };
28
- /** "YYYY-MM-DD" the entry was last checked against `source`. */
28
+ /** The `YYYY-MM-DD` date the entry was last checked against `source`. */
29
29
  asOf: string;
30
30
  /** Public pricing page the number came from (a comment/URL, never a secret). */
31
31
  source: string;
32
- /** true = a stand-in NOT copied from a live sheet; the estimate carries this flag so a
32
+ /** true = a stand-in that was not copied from a live sheet; the estimate carries this flag so a
33
33
  * placeholder rate is never mistaken for a confirmed one. */
34
34
  placeholder?: boolean;
35
35
  }
@@ -52,8 +52,8 @@ export interface DesktopResourceRate {
52
52
  source: string;
53
53
  }
54
54
  /**
55
- * The token-derived cost ESTIMATE for one actor lane. `estimatedCostUsd: null` = DECLARED ABSENT
56
- * (unknown rate or no token usage) — never coerced to 0. A non-null figure ALWAYS carries its
55
+ * The token-derived cost estimate for one actor trace. `estimatedCostUsd: null` = declared absent
56
+ * (unknown rate or no token usage) and is never coerced to 0. A non-null figure always carries its
57
57
  * pricing provenance (`ratesAsOf` + `source`) so the mechanism (a rate-table multiply) matches
58
58
  * the claim (an estimate, not a charge). Defined here so the rate table and the field that
59
59
  * consumes it live together; `ActorTrace` imports it type-only.
@@ -71,22 +71,26 @@ export interface ActorEstimatedCost {
71
71
  modelId?: string;
72
72
  /** true when the rate is a stand-in, not a live sheet. */
73
73
  placeholder?: boolean;
74
+ /** Set when usage arrived as runtime-turn totals that each sum several requests. No request's
75
+ * own size is known, so no per-request long-context tier was applied: tokens are priced at the
76
+ * base tier, cached input at the cached rate. */
77
+ basis?: "aggregated_turns_base_rate";
74
78
  breakdown?: {
75
79
  inputUsd: number;
76
80
  outputUsd: number;
77
81
  inputTokens: number;
78
82
  outputTokens: number;
79
83
  /** Of `inputTokens`, how many were billed at the reduced cached rate. Present only when the
80
- * provider reported cache hits AND the rate sheet models a cached rate. */
84
+ * provider reported cache hits and the rate sheet models a cached rate. */
81
85
  cachedInputTokens?: number;
82
- /** Of `inputTokens`, how many were billed at the cache-WRITE rate (OpenAI 5.6+). */
86
+ /** Of `inputTokens`, how many were billed at the cache-write rate (OpenAI 5.6+). */
83
87
  cacheWriteInputTokens?: number;
84
88
  /** How many requests crossed the long-context threshold and were re-tiered. Present only
85
89
  * when per-request `turns` records made exact tiering possible. */
86
90
  longContextTurns?: number;
87
91
  };
88
92
  }
89
- /** The desktop-minute cost ESTIMATE (host-side create->teardown span * a per-minute rate). Same
93
+ /** The desktop-minute cost estimate (host-side create->teardown span * a per-minute rate). Same
90
94
  * null-discipline as ActorEstimatedCost: `estimatedCostUsd: null` = not measured (no duration). */
91
95
  export interface DesktopCostEstimate {
92
96
  estimatedCostUsd: number | null;
@@ -100,6 +104,11 @@ export interface DesktopCostEstimate {
100
104
  usdPerSecond?: number;
101
105
  }
102
106
  export declare const MODEL_RATES: Record<string, ModelRate>;
107
+ /**
108
+ * The refusal for a spend cap on a model this table cannot price. It names the priced models,
109
+ * since an npm install cannot edit this file.
110
+ */
111
+ export declare function unpricedCapMessage(model: string): string;
103
112
  export declare const DESKTOP_RATE: DesktopRate;
104
113
  export declare function isDesktopResources(value: unknown): value is DesktopResources;
105
114
  /** Price one observed allocation. Missing quantities/rates stay unknown, never a stock guess. */
@@ -108,17 +117,23 @@ export declare function estimateAllocatedDesktopCost(minutes: number | undefined
108
117
  * precision. */
109
118
  export declare function round6(n: number): number;
110
119
  /**
111
- * Estimate one actor lane's model-token cost from its trace tokenUsage + model id. Deterministic;
112
- * the rate table is injectable (tests pass a fake sheet). Returns a DECLARED-ABSENT estimate
113
- * (estimatedCostUsd: null + a reason) for a missing rate or missing usage — never a guessed cost.
120
+ * Estimate one actor trace's model-token cost from its trace tokenUsage + model id. Deterministic;
121
+ * the rate table is injectable (tests pass a fake sheet). Returns a declared-absent estimate
122
+ * (estimatedCostUsd: null + a reason) for a missing rate or missing usage, never a guessed cost.
114
123
  */
115
124
  export declare function estimateActorCostForExecution(usage: ActorTokenUsage | undefined, modelId: string | undefined, profile?: {
116
125
  billing?: unknown;
117
126
  }): ActorEstimatedCost;
127
+ /**
128
+ * Price usage reported as runtime-turn totals, such as Codex `turn.completed`, which sums every
129
+ * request in the turn. Pricing a turn as one request would apply the long-context tier to the
130
+ * whole turn, so the per-turn records are dropped and the totals price on the base tier.
131
+ */
132
+ export declare function estimateAggregatedTurnCost(tokenUsage: ActorTokenUsage | undefined, modelId: string | undefined): ActorEstimatedCost;
118
133
  export declare function estimateActorCost(tokenUsage: ActorTokenUsage | undefined, modelId: string | undefined, rates?: Record<string, ModelRate>): ActorEstimatedCost;
119
134
  /**
120
135
  * Estimate the E2B desktop-minute cost from a host-side create->teardown span (minutes). The rate
121
- * is injectable. Returns a DECLARED-ABSENT estimate (null + "no_duration") when no duration was
122
- * measured (no sandbox / unmeasurable span) — never a guessed 0.
136
+ * is injectable. Returns a declared-absent estimate (null + "no_duration") when no duration was
137
+ * measured (no sandbox / unmeasurable span), never a guessed 0.
123
138
  */
124
139
  export declare function estimateDesktopCost(minutes: number | undefined, rate?: DesktopRate): DesktopCostEstimate;
@@ -1,18 +1,18 @@
1
- // OPERATOR-EDITABLE ESTIMATES — NOT authoritative prices. Providers change pricing without
2
- // notice. When they do, update BOTH the number AND the `asOf` date on the affected entry.
3
- // Every dollar figure humanish derives from this table is surfaced/persisted as an ESTIMATE,
4
- // labeled "estimated (rates as of <asOf>)", and is NEVER presented as an exact charge.
1
+ // Operator-editable estimates, which are not authoritative prices. Providers change pricing without
2
+ // notice. When they do, update both the number and the `asOf` date on the affected entry.
3
+ // Every dollar figure humanish derives from this table is surfaced/persisted as an estimate,
4
+ // labeled "estimated (rates as of <asOf>)", and is never presented as an exact charge.
5
5
  //
6
- // This module is PURE (node builtins only, no deps) and deterministic: the estimator functions take
7
- // an OPTIONAL injected rate table/rate so tests drive assertions with a fake sheet and never depend
8
- // on the live numbers below. An UNKNOWN model/desktop rate yields a DECLARED-ABSENT estimate
9
- // (estimatedCostUsd: null + a reason), NEVER a guessed or silent-zero cost (invariant 5). A bare
6
+ // This module is pure (node builtins only, no deps) and deterministic: the estimator functions take
7
+ // an optional injected rate table/rate so tests drive assertions with a fake sheet and never depend
8
+ // on the live numbers below. An unknown model/desktop rate yields a declared-absent estimate
9
+ // (estimatedCostUsd: null + a reason) and never a guessed or silent-zero cost. A bare
10
10
  // `costUsd` elsewhere in the contract means a provider actually billed that amount; the
11
11
  // token-derived estimate here always lives under `estimatedCostUsd` so a reader can never confuse
12
- // an estimate for an authoritative charge (invariant 6).
12
+ // an estimate for an authoritative charge.
13
13
  export const PRICING_SCHEMA = "humanish.pricing.v1";
14
14
  export const ACTOR_ESTIMATED_COST_SCHEMA = "humanish.actor-estimated-cost.v1";
15
- // The gpt-5.6 long-context tier: >272K input tokens re-prices the FULL request at 2x
15
+ // The gpt-5.6 long-context tier: >272K input tokens re-prices the full request at 2x
16
16
  // input-side / 1.5x output (developers.openai.com/api/docs/models/gpt-5.6-sol, 2026-08-18).
17
17
  const LONG_CONTEXT_TIER_272K = {
18
18
  thresholdInputTokens: 272_000,
@@ -41,17 +41,17 @@ function rateWithLongContextTier(inPer1M, cachedPer1M, writePer1M, outPer1M, asO
41
41
  const GPT56_SOL_PROMO_AS_OF = "2026-09-03";
42
42
  const GPT6_ASTRA_AS_OF = "2026-09-03";
43
43
  // Per-model rates, keyed on the model id that lands in trace.ids.model (lookup is
44
- // case-insensitive on a trimmed id). An id NOT present here is DECLARED ABSENT, never guessed.
44
+ // case-insensitive on a trimmed id). An id missing here is declared absent, never guessed.
45
45
  export const MODEL_RATES = {
46
46
  // OpenAI computer-use-preview (the classic CUA model). ~$3 / 1M input, ~$12 / 1M output.
47
- // source: openai.com/api/pricing (verify — providers change without notice).
47
+ // source: openai.com/api/pricing (verify: providers change without notice).
48
48
  "computer-use-preview": {
49
49
  inputUsdPerToken: 3e-6,
50
50
  outputUsdPerToken: 12e-6,
51
51
  asOf: "2026-08-01",
52
52
  source: "openai.com/api/pricing (computer-use-preview)",
53
53
  },
54
- // gpt-5.5: the PREVIOUS-generation CUA default, kept so pinned labs and old bundles still
54
+ // gpt-5.5: the previous-generation CUA default, kept so pinned labs and old bundles still
55
55
  // price. Pre-5.6 models bill no cache-write fee (prompt-caching guide) and no long-context
56
56
  // tier was published for it.
57
57
  "gpt-5.5": {
@@ -59,7 +59,7 @@ export const MODEL_RATES = {
59
59
  outputUsdPerToken: 30e-6,
60
60
  cachedInputUsdPerToken: 0.5e-6,
61
61
  asOf: "2026-08-05",
62
- source: "openrouter.ai/openai/gpt-5.5 (gpt-5.5 no longer on openai.com/api/pricing; see #334)",
62
+ source: "openrouter.ai/openai/gpt-5.5 (gpt-5.5 is no longer listed on openai.com/api/pricing)",
63
63
  },
64
64
  // The gpt-5.6 family (live sheet 2026-08-18, standard tier, short-context base rates;
65
65
  // the longContext block prices the >272K re-tier when per-request turns are recorded).
@@ -74,7 +74,7 @@ export const MODEL_RATES = {
74
74
  "gpt-5.6-cyber": rateWithLongContextTier(12.5, 1.25, 15.625, 75),
75
75
  // Daybreak program aliases (blue -> sol, red -> cyber today). OpenAI repoints these as new
76
76
  // frontier models ship, so prefer the explicit tier id in labs; the entries exist so a
77
- // configured alias still prices at what the alias bills TODAY.
77
+ // configured alias still prices at what the alias bills today.
78
78
  "daybreak-blue-latest": rateWithLongContextTier(4, 0.4, 5, 20, GPT56_SOL_PROMO_AS_OF),
79
79
  "daybreak-red-latest": rateWithLongContextTier(12.5, 1.25, 15.625, 75),
80
80
  // gpt-6-astra (shipped 2026-09-03; API access announced as rolling out). Same two mechanics
@@ -96,6 +96,13 @@ const DESKTOP_RESOURCE_RATE = {
96
96
  // 2026-09-05 had 8 vCPU / 8 GiB. This is the largest CPU/RAM combination on that public sheet, not
97
97
  // a provider billing ceiling or a claim about custom/enterprise templates. Runtime CUA estimates
98
98
  // use observed allocation resources through estimateAllocatedDesktopCost instead of this fallback.
99
+ /**
100
+ * The refusal for a spend cap on a model this table cannot price. It names the priced models,
101
+ * since an npm install cannot edit this file.
102
+ */
103
+ export function unpricedCapMessage(model) {
104
+ return `execution.caps sets a spend cap (maxUsd or maxTotalUsd), but humanish has no rate for model "${model}", so it cannot enforce the cap and refuses to start. Priced models: ${Object.keys(MODEL_RATES).sort().join(", ")}. Use one of them, or remove maxUsd and maxTotalUsd to run without a cap.`;
105
+ }
99
106
  export const DESKTOP_RATE = {
100
107
  usdPerMinute: 0.00888,
101
108
  asOf: "2026-09-05",
@@ -157,9 +164,9 @@ export function round6(n) {
157
164
  return Math.round(n * 1e6) / 1e6;
158
165
  }
159
166
  /**
160
- * Estimate one actor lane's model-token cost from its trace tokenUsage + model id. Deterministic;
161
- * the rate table is injectable (tests pass a fake sheet). Returns a DECLARED-ABSENT estimate
162
- * (estimatedCostUsd: null + a reason) for a missing rate or missing usage — never a guessed cost.
167
+ * Estimate one actor trace's model-token cost from its trace tokenUsage + model id. Deterministic;
168
+ * the rate table is injectable (tests pass a fake sheet). Returns a declared-absent estimate
169
+ * (estimatedCostUsd: null + a reason) for a missing rate or missing usage, never a guessed cost.
163
170
  */
164
171
  export function estimateActorCostForExecution(usage, modelId, profile) {
165
172
  return profile?.billing === "account-unknown"
@@ -172,6 +179,18 @@ export function estimateActorCostForExecution(usage, modelId, profile) {
172
179
  }
173
180
  : estimateActorCost(usage, modelId);
174
181
  }
182
+ /**
183
+ * Price usage reported as runtime-turn totals, such as Codex `turn.completed`, which sums every
184
+ * request in the turn. Pricing a turn as one request would apply the long-context tier to the
185
+ * whole turn, so the per-turn records are dropped and the totals price on the base tier.
186
+ */
187
+ export function estimateAggregatedTurnCost(tokenUsage, modelId) {
188
+ const { turns: _turns, ...totals } = tokenUsage ?? {};
189
+ const estimate = estimateActorCost(tokenUsage === undefined ? undefined : totals, modelId);
190
+ return estimate.estimatedCostUsd === null
191
+ ? estimate
192
+ : { ...estimate, basis: "aggregated_turns_base_rate" };
193
+ }
175
194
  export function estimateActorCost(tokenUsage, modelId, rates = MODEL_RATES) {
176
195
  if (!tokenUsage || (tokenUsage.input === undefined && tokenUsage.output === undefined)) {
177
196
  return {
@@ -193,15 +212,15 @@ export function estimateActorCost(tokenUsage, modelId, rates = MODEL_RATES) {
193
212
  }
194
213
  const inTok = tokenUsage.input ?? 0;
195
214
  const outTok = tokenUsage.output ?? 0;
196
- // Long-context tiering needs to know each REQUEST's input size (the provider re-prices whole
197
- // requests past the threshold), so it engages only when per-turn usage records exist AND their
198
- // input sums to the reported total — a partial turn ledger must not silently price the missing
215
+ // Long-context tiering needs to know each request's input size (the provider re-prices whole
216
+ // requests past the threshold), so it engages only when per-turn usage records exist and their
217
+ // input sums to the reported total, because a partial turn ledger must not silently price the missing
199
218
  // remainder at the wrong tier. Otherwise totals price on the base (short-context) rate, which is
200
219
  // the under-estimate direction and never trips a cap early.
201
220
  const turns = tokenUsage.turns ?? [];
202
221
  const sumOf = (field) => turns.reduce((sum, turn) => sum + (turn[field] ?? 0), 0);
203
- // The ledger is trusted only when it decomposes the totals EXACTLY — all four sums, not just
204
- // input/output. A ledger that carries request sizes but not the cache splits would otherwise
222
+ // The ledger is trusted only when it decomposes the totals exactly, in all four sums including the
223
+ // cache splits. A ledger that carries request sizes but not the cache splits would otherwise
205
224
  // price every token at the full rate while the session totals sit ignored, overstating spend
206
225
  // 3.5-5x and tripping caps early. Inconsistent evidence falls back to the totals path, which
207
226
  // honors the declared splits on the base tier.
@@ -217,15 +236,15 @@ export function estimateActorCost(tokenUsage, modelId, rates = MODEL_RATES) {
217
236
  let writeTotal = 0;
218
237
  let longContextTurns = 0;
219
238
  // Price one request's usage at one tier. Cached input is billed at a fraction of the full rate,
220
- // and on a session that threads provider state it is the MAJORITY of input — pricing it at the
221
- // full rate overstates real spend by up to ~10x. Cache WRITES bill at their own rate (1.25x on
239
+ // and on a session that threads provider state it is the majority of input, and pricing it at the
240
+ // full rate overstates real spend by up to ~10x. Cache writes bill at their own rate (1.25x on
222
241
  // OpenAI 5.6+) as the total rate for those tokens; a sheet without a write rate prices writes as
223
- // plain input (pre-5.6: writes are free-of-extra-fee, i.e. plain input). Every piece is honestly
224
- // absent: no reported split means no discount and no surcharge assumed.
242
+ // plain input (pre-5.6: writes are free-of-extra-fee, i.e. plain input). An unreported piece
243
+ // stays absent: no reported split means no discount and no surcharge assumed.
225
244
  const priceRequest = (usage, tierable) => {
226
245
  const reqIn = usage.input ?? 0;
227
246
  const reqOut = usage.output ?? 0;
228
- // Tiering applies only to a real per-REQUEST record: session totals crossing the threshold
247
+ // Tiering applies only to a real per-request record: session totals crossing the threshold
229
248
  // say nothing about any single request, so totals always price on the base tier.
230
249
  const long = tierable && rate.longContext !== undefined && reqIn > rate.longContext.thresholdInputTokens;
231
250
  const inMul = long ? rate.longContext.inputMultiplier : 1;
@@ -281,8 +300,8 @@ export function estimateActorCost(tokenUsage, modelId, rates = MODEL_RATES) {
281
300
  }
282
301
  /**
283
302
  * Estimate the E2B desktop-minute cost from a host-side create->teardown span (minutes). The rate
284
- * is injectable. Returns a DECLARED-ABSENT estimate (null + "no_duration") when no duration was
285
- * measured (no sandbox / unmeasurable span) — never a guessed 0.
303
+ * is injectable. Returns a declared-absent estimate (null + "no_duration") when no duration was
304
+ * measured (no sandbox / unmeasurable span), never a guessed 0.
286
305
  */
287
306
  export function estimateDesktopCost(minutes, rate = DESKTOP_RATE) {
288
307
  if (minutes === undefined || !Number.isFinite(minutes) || minutes < 0) {