humanish 0.107.0 → 0.109.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 (671) hide show
  1. package/ARCHITECTURE.md +73 -69
  2. package/CHANGELOG.md +27 -0
  3. package/CONTEXT.md +51 -44
  4. package/README.md +148 -175
  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-trace.js +2 -1
  14. package/dist/actors/codex/app-server-ui.js +1 -1
  15. package/dist/actors/codex/codex-admission.d.ts +91 -0
  16. package/dist/actors/codex/codex-admission.js +150 -0
  17. package/dist/actors/codex/restricted-executable.d.ts +4 -4
  18. package/dist/actors/codex/restricted-executable.js +8 -8
  19. package/dist/actors/codex/restricted-launch.d.ts +2 -1
  20. package/dist/actors/codex/restricted-launch.js +1 -1
  21. package/dist/actors/codex/restricted-participant.js +20 -18
  22. package/dist/actors/codex/restricted-policy.d.ts +2 -2
  23. package/dist/actors/codex/restricted-policy.js +2 -2
  24. package/dist/actors/codex/restricted-session.d.ts +3 -3
  25. package/dist/actors/codex/restricted-session.js +10 -5
  26. package/dist/actors/computer-use/actor.d.ts +18 -18
  27. package/dist/actors/computer-use/actor.js +4 -4
  28. package/dist/actors/computer-use/admission-limit.d.ts +3 -3
  29. package/dist/actors/computer-use/admission-limit.js +4 -4
  30. package/dist/actors/computer-use/executor-error.d.ts +2 -2
  31. package/dist/actors/computer-use/executor-error.js +3 -3
  32. package/dist/actors/computer-use/loop/actions.d.ts +3 -3
  33. package/dist/actors/computer-use/loop/actions.js +15 -15
  34. package/dist/actors/computer-use/loop/backstop.d.ts +3 -3
  35. package/dist/actors/computer-use/loop/backstop.js +14 -12
  36. package/dist/actors/computer-use/loop/debrief.js +2 -2
  37. package/dist/actors/computer-use/loop/ending.d.ts +6 -6
  38. package/dist/actors/computer-use/loop/ending.js +18 -17
  39. package/dist/actors/computer-use/loop/observation.d.ts +2 -2
  40. package/dist/actors/computer-use/loop/observation.js +15 -14
  41. package/dist/actors/computer-use/loop/provider-call.d.ts +1 -1
  42. package/dist/actors/computer-use/loop/provider-call.js +12 -12
  43. package/dist/actors/computer-use/loop/session.d.ts +4 -4
  44. package/dist/actors/computer-use/loop/session.js +4 -4
  45. package/dist/actors/computer-use/loop/spend.d.ts +1 -1
  46. package/dist/actors/computer-use/loop/spend.js +1 -1
  47. package/dist/actors/computer-use/loop/trace.js +11 -9
  48. package/dist/actors/computer-use/loop/types.d.ts +47 -45
  49. package/dist/actors/computer-use/loop/usage.d.ts +2 -2
  50. package/dist/actors/computer-use/loop/usage.js +2 -2
  51. package/dist/actors/computer-use/loop.d.ts +6 -1
  52. package/dist/actors/computer-use/loop.js +26 -4
  53. package/dist/actors/computer-use/openai-context.d.ts +37 -0
  54. package/dist/actors/computer-use/openai-context.js +214 -0
  55. package/dist/actors/computer-use/openai-provider.d.ts +13 -10
  56. package/dist/actors/computer-use/openai-provider.js +52 -41
  57. package/dist/actors/computer-use/openai-requests.d.ts +36 -10
  58. package/dist/actors/computer-use/openai-requests.js +82 -15
  59. package/dist/actors/computer-use/openai-wire.d.ts +19 -7
  60. package/dist/actors/computer-use/openai-wire.js +36 -34
  61. package/dist/actors/computer-use/provider-error.d.ts +4 -4
  62. package/dist/actors/computer-use/provider-error.js +6 -6
  63. package/dist/actors/contract.d.ts +82 -47
  64. package/dist/actors/contract.js +30 -24
  65. package/dist/actors/local-agent/claude-session.d.ts +1 -1
  66. package/dist/actors/local-agent/claude-session.js +13 -12
  67. package/dist/actors/local-agent/cli.d.ts +9 -7
  68. package/dist/actors/local-agent/cli.js +24 -28
  69. package/dist/actors/local-agent/readiness.d.ts +2 -2
  70. package/dist/actors/local-agent/readiness.js +4 -4
  71. package/dist/actors/reasoning-effort.js +8 -8
  72. package/dist/actors/registry.d.ts +12 -12
  73. package/dist/actors/registry.js +21 -20
  74. package/dist/actors/scripted-browser/actor.d.ts +10 -10
  75. package/dist/actors/scripted-browser/actor.js +17 -17
  76. package/dist/actors/scripted-browser/browser-command.js +1 -1
  77. package/dist/actors/scripted-browser/steps.js +1 -1
  78. package/dist/actors/scripted-browser/types.d.ts +1 -1
  79. package/dist/actors/stop-conditions.d.ts +1 -1
  80. package/dist/analysis/automatic-completion.d.ts +7 -7
  81. package/dist/analysis/automatic-completion.js +1 -1
  82. package/dist/analysis/automatic-config.d.ts +6 -6
  83. package/dist/analysis/automatic-config.js +1 -1
  84. package/dist/analysis/codex-config.d.ts +6 -2
  85. package/dist/analysis/codex-config.js +22 -14
  86. package/dist/analysis/execute.d.ts +1 -1
  87. package/dist/analysis/execute.js +1 -1
  88. package/dist/analysis/service.js +5 -5
  89. package/dist/analysis/types.d.ts +6 -0
  90. package/dist/browser-control/client.js +16 -16
  91. package/dist/browser-control/dispatcher.js +4 -4
  92. package/dist/browser-control/protocol.js +14 -14
  93. package/dist/browser-control/recording-transfer.js +4 -4
  94. package/dist/browser-control/transport.js +7 -7
  95. package/dist/cli/commands/analysis-signals.d.ts +2 -2
  96. package/dist/cli/commands/analyze.js +19 -16
  97. package/dist/cli/commands/codex.js +9 -9
  98. package/dist/cli/commands/comms.js +48 -35
  99. package/dist/cli/commands/feedback.js +20 -21
  100. package/dist/cli/commands/migrate.d.ts +4 -0
  101. package/dist/cli/commands/migrate.js +65 -0
  102. package/dist/cli/commands/observe.d.ts +0 -1
  103. package/dist/cli/commands/observe.js +136 -112
  104. package/dist/cli/commands/run-command.d.ts +10 -0
  105. package/dist/cli/commands/run-command.js +85 -0
  106. package/dist/cli/commands/runs.js +136 -139
  107. package/dist/cli/commands/setup.d.ts +2 -2
  108. package/dist/cli/commands/setup.js +27 -24
  109. package/dist/cli/commands/study-format.d.ts +9 -0
  110. package/dist/cli/commands/{lab-format.js → study-format.js} +39 -27
  111. package/dist/cli/commands/{lab-route-computer-use.d.ts → study-route-computer-use.d.ts} +6 -6
  112. package/dist/cli/commands/{lab-route-computer-use.js → study-route-computer-use.js} +17 -18
  113. package/dist/cli/commands/{lab-route-open.d.ts → study-route-open.d.ts} +4 -4
  114. package/dist/cli/commands/{lab-route-open.js → study-route-open.js} +2 -2
  115. package/dist/cli/commands/{lab-route-preview.d.ts → study-route-preview.d.ts} +7 -7
  116. package/dist/cli/commands/{lab-route-preview.js → study-route-preview.js} +7 -6
  117. package/dist/cli/commands/study-route-run.d.ts +19 -0
  118. package/dist/cli/commands/{lab-route-run.js → study-route-run.js} +6 -6
  119. package/dist/cli/commands/study-route-scripted.d.ts +17 -0
  120. package/dist/cli/commands/{lab-route-scripted.js → study-route-scripted.js} +4 -4
  121. package/dist/cli/commands/{lab-route-shared-world.d.ts → study-route-shared-world.d.ts} +5 -5
  122. package/dist/cli/commands/{lab-route-shared-world.js → study-route-shared-world.js} +10 -10
  123. package/dist/cli/commands/study-route-terminal.d.ts +17 -0
  124. package/dist/cli/commands/{lab-route-terminal.js → study-route-terminal.js} +4 -4
  125. package/dist/cli/commands/study-run.d.ts +9 -0
  126. package/dist/cli/commands/{lab-run.js → study-run.js} +44 -45
  127. package/dist/cli/commands/{lab-scorer.d.ts → study-scorer.d.ts} +7 -7
  128. package/dist/cli/commands/{lab-scorer.js → study-scorer.js} +2 -2
  129. package/dist/cli/commands/study.d.ts +3 -0
  130. package/dist/cli/commands/study.js +146 -0
  131. package/dist/cli/commands/tui.d.ts +4 -4
  132. package/dist/cli/commands/tui.js +31 -31
  133. package/dist/cli/commands/watch.js +71 -121
  134. package/dist/cli/deprecations.d.ts +6 -0
  135. package/dist/cli/deprecations.js +18 -0
  136. package/dist/cli/doctor.d.ts +18 -8
  137. package/dist/cli/doctor.js +114 -59
  138. package/dist/cli/first-run-path.d.ts +15 -13
  139. package/dist/cli/first-run-path.js +35 -33
  140. package/dist/cli/io.d.ts +44 -9
  141. package/dist/cli/io.js +98 -23
  142. package/dist/cli/observer-follow.d.ts +3 -3
  143. package/dist/cli/observer-follow.js +6 -7
  144. package/dist/cli/orientation.d.ts +10 -7
  145. package/dist/cli/orientation.js +89 -47
  146. package/dist/cli/product-sentence.d.ts +6 -0
  147. package/dist/cli/product-sentence.js +6 -0
  148. package/dist/cli/program.d.ts +6 -1
  149. package/dist/cli/program.js +111 -43
  150. package/dist/cli/telemetry.d.ts +16 -16
  151. package/dist/cli/telemetry.js +46 -44
  152. package/dist/cli.js +1 -1
  153. package/dist/comms/capture-surface.d.ts +13 -12
  154. package/dist/comms/capture-surface.js +23 -22
  155. package/dist/comms/catch-host.d.ts +7 -7
  156. package/dist/comms/catch-host.js +17 -17
  157. package/dist/comms/connections.d.ts +1 -1
  158. package/dist/comms/connections.js +2 -2
  159. package/dist/comms/email-catch.d.ts +3 -3
  160. package/dist/comms/email-catch.js +8 -8
  161. package/dist/comms/external-evidence.d.ts +5 -5
  162. package/dist/comms/external-evidence.js +5 -4
  163. package/dist/comms/extract.js +2 -2
  164. package/dist/comms/fake-inbox.d.ts +3 -3
  165. package/dist/comms/fake-inbox.js +3 -3
  166. package/dist/comms/receiving-render.d.ts +1 -1
  167. package/dist/comms/receiving-render.js +2 -2
  168. package/dist/comms/receiving-runtime.d.ts +4 -4
  169. package/dist/comms/sandbox-catch-script.d.ts +6 -6
  170. package/dist/comms/sandbox-catch-script.js +6 -6
  171. package/dist/comms/sandbox-catch.d.ts +38 -39
  172. package/dist/comms/sandbox-catch.js +36 -37
  173. package/dist/comms/setup.d.ts +2 -2
  174. package/dist/comms/setup.js +56 -25
  175. package/dist/comms/thread-evidence.d.ts +1 -1
  176. package/dist/comms/thread-evidence.js +6 -6
  177. package/dist/comms/types.d.ts +6 -6
  178. package/dist/comms/types.js +3 -3
  179. package/dist/evidence/frame-signature.d.ts +1 -1
  180. package/dist/evidence/frame-signature.js +4 -4
  181. package/dist/evidence/redaction.d.ts +3 -3
  182. package/dist/evidence/redaction.js +4 -4
  183. package/dist/feedback/draft.js +38 -80
  184. package/dist/feedback/export-bundle.js +1 -1
  185. package/dist/feedback/export.d.ts +5 -1
  186. package/dist/feedback/export.js +10 -10
  187. package/dist/feedback/feedback.d.ts +2 -2
  188. package/dist/feedback/feedback.js +21 -3
  189. package/dist/feedback/proof.d.ts +1 -1
  190. package/dist/feedback/proof.js +2 -2
  191. package/dist/guest/bootstrap.js +6 -6
  192. package/dist/guest/browser-tools.js +8 -8
  193. package/dist/guest/chromium-text.js +19 -19
  194. package/dist/guest/desktop-executor.d.ts +2 -2
  195. package/dist/guest/desktop-executor.js +20 -20
  196. package/dist/guest/desktop-keys.js +4 -4
  197. package/dist/guest/desktop-media.d.ts +2 -2
  198. package/dist/guest/desktop-media.js +16 -16
  199. package/dist/guest/desktop-native.d.ts +1 -1
  200. package/dist/guest/desktop-native.js +10 -10
  201. package/dist/guest/runtime-desktop.js +2 -2
  202. package/dist/guest/runtime-processes.d.ts +2 -2
  203. package/dist/guest/runtime-processes.js +2 -2
  204. package/dist/guest/runtime.js +6 -6
  205. package/dist/index.d.ts +14 -14
  206. package/dist/index.js +8 -8
  207. package/dist/keys/key-resolution.d.ts +5 -5
  208. package/dist/keys/key-resolution.js +23 -23
  209. package/dist/observer/artifact.d.ts +2 -2
  210. package/dist/observer/artifact.js +7 -7
  211. package/dist/observer/data.d.ts +6 -6
  212. package/dist/observer/data.js +5 -4
  213. package/dist/observer/exposure.d.ts +1 -1
  214. package/dist/observer/exposure.js +11 -11
  215. package/dist/observer/http.js +1 -1
  216. package/dist/observer/library.d.ts +3 -1
  217. package/dist/observer/library.js +8 -3
  218. package/dist/observer/listen.js +5 -4
  219. package/dist/observer/render.d.ts +1 -1
  220. package/dist/observer/render.js +17 -6
  221. package/dist/observer/run-routes.d.ts +4 -3
  222. package/dist/observer/run-routes.js +38 -13
  223. package/dist/observer/serve.d.ts +1 -1
  224. package/dist/observer/serve.js +7 -3
  225. package/dist/observer/tunnel.js +1 -1
  226. package/dist/observer-app.html +4 -4
  227. package/dist/routes/computer-use/bundle-parts.d.ts +9 -9
  228. package/dist/routes/computer-use/bundle-parts.js +18 -17
  229. package/dist/routes/computer-use/bundle.d.ts +2 -2
  230. package/dist/routes/computer-use/bundle.js +10 -9
  231. package/dist/routes/computer-use/e2b-desktop/comms.d.ts +6 -6
  232. package/dist/routes/computer-use/e2b-desktop/comms.js +18 -17
  233. package/dist/routes/computer-use/e2b-desktop/desktop.js +4 -4
  234. package/dist/routes/computer-use/e2b-desktop/fidelity.d.ts +5 -4
  235. package/dist/routes/computer-use/e2b-desktop/fidelity.js +11 -10
  236. package/dist/routes/computer-use/e2b-desktop/prepare.d.ts +1 -1
  237. package/dist/routes/computer-use/e2b-desktop/prepare.js +10 -10
  238. package/dist/routes/computer-use/e2b-desktop/start.js +7 -7
  239. package/dist/routes/computer-use/e2b-desktop/state.d.ts +2 -2
  240. package/dist/routes/computer-use/e2b-desktop/teardown.js +2 -2
  241. package/dist/routes/computer-use/external-comms.d.ts +4 -4
  242. package/dist/routes/computer-use/external-comms.js +1 -1
  243. package/dist/routes/computer-use/fanout-bundle.js +27 -26
  244. package/dist/routes/computer-use/fanout-records.js +12 -13
  245. package/dist/routes/computer-use/live-flush.d.ts +4 -4
  246. package/dist/routes/computer-use/live-flush.js +6 -6
  247. package/dist/routes/computer-use/live-phase.d.ts +5 -4
  248. package/dist/routes/computer-use/live-phase.js +8 -8
  249. package/dist/routes/computer-use/local-tree-pack.d.ts +5 -5
  250. package/dist/routes/computer-use/local-tree-pack.js +1 -1
  251. package/dist/routes/computer-use/local-vm.d.ts +8 -8
  252. package/dist/routes/computer-use/local-vm.js +3 -3
  253. package/dist/routes/computer-use/participant-desktop.d.ts +7 -7
  254. package/dist/routes/computer-use/participant-desktop.js +5 -5
  255. package/dist/routes/computer-use/participant-execution.d.ts +4 -4
  256. package/dist/routes/computer-use/participant-execution.js +10 -10
  257. package/dist/routes/computer-use/participant-model.d.ts +6 -0
  258. package/dist/routes/computer-use/participant-model.js +33 -15
  259. package/dist/routes/computer-use/participant-prompt.d.ts +15 -15
  260. package/dist/routes/computer-use/participant-prompt.js +9 -9
  261. package/dist/routes/computer-use/participant-runs.d.ts +16 -16
  262. package/dist/routes/computer-use/participant-runs.js +26 -25
  263. package/dist/routes/computer-use/plan.d.ts +12 -12
  264. package/dist/routes/computer-use/plan.js +42 -42
  265. package/dist/routes/computer-use/preflight.d.ts +5 -5
  266. package/dist/routes/computer-use/preflight.js +25 -25
  267. package/dist/routes/computer-use/rerun-selection.d.ts +1 -1
  268. package/dist/routes/computer-use/rerun-selection.js +4 -3
  269. package/dist/routes/computer-use/result.d.ts +4 -4
  270. package/dist/routes/computer-use/result.js +22 -21
  271. package/dist/routes/computer-use/route.d.ts +12 -11
  272. package/dist/routes/computer-use/route.js +31 -30
  273. package/dist/routes/computer-use/self-report.d.ts +7 -7
  274. package/dist/routes/computer-use/self-report.js +32 -32
  275. package/dist/routes/computer-use/setup.d.ts +23 -23
  276. package/dist/routes/computer-use/setup.js +28 -29
  277. package/dist/routes/computer-use/single-bundle.d.ts +11 -11
  278. package/dist/routes/computer-use/single-bundle.js +40 -41
  279. package/dist/routes/computer-use/subject-projection.d.ts +4 -4
  280. package/dist/routes/computer-use/subject-projection.js +6 -6
  281. package/dist/routes/computer-use/types.d.ts +71 -73
  282. package/dist/routes/computer-use/types.js +12 -12
  283. package/dist/routes/preview.d.ts +13 -7
  284. package/dist/routes/preview.js +11 -7
  285. package/dist/routes/scripted/bundle.d.ts +7 -7
  286. package/dist/routes/scripted/bundle.js +20 -18
  287. package/dist/routes/scripted/plan.d.ts +8 -8
  288. package/dist/routes/scripted/plan.js +13 -13
  289. package/dist/routes/scripted/result.d.ts +3 -3
  290. package/dist/routes/scripted/result.js +13 -13
  291. package/dist/routes/scripted/route.d.ts +9 -9
  292. package/dist/routes/scripted/route.js +15 -16
  293. package/dist/routes/scripted/scenario.d.ts +1 -1
  294. package/dist/routes/scripted/scenario.js +5 -5
  295. package/dist/routes/scripted/setup.d.ts +6 -6
  296. package/dist/routes/scripted/setup.js +8 -8
  297. package/dist/routes/scripted/subject.d.ts +5 -5
  298. package/dist/routes/scripted/subject.js +4 -4
  299. package/dist/routes/scripted/surface-records.d.ts +1 -1
  300. package/dist/routes/scripted/surface-records.js +4 -4
  301. package/dist/routes/scripted/surface-sessions.d.ts +3 -3
  302. package/dist/routes/scripted/types.d.ts +18 -20
  303. package/dist/routes/scripted/types.js +2 -2
  304. package/dist/routes/shared-world/bundle-records.js +11 -10
  305. package/dist/routes/shared-world/bundle.d.ts +5 -5
  306. package/dist/routes/shared-world/bundle.js +46 -43
  307. package/dist/routes/shared-world/checkpoints.d.ts +4 -4
  308. package/dist/routes/shared-world/checkpoints.js +2 -2
  309. package/dist/routes/shared-world/comms.d.ts +14 -14
  310. package/dist/routes/shared-world/comms.js +19 -18
  311. package/dist/routes/shared-world/external-public.d.ts +4 -3
  312. package/dist/routes/shared-world/external-public.js +16 -12
  313. package/dist/routes/shared-world/handoff.d.ts +7 -6
  314. package/dist/routes/shared-world/handoff.js +65 -57
  315. package/dist/routes/shared-world/lobby-code.d.ts +2 -2
  316. package/dist/routes/shared-world/lobby-code.js +9 -9
  317. package/dist/routes/shared-world/participant-specs.d.ts +10 -9
  318. package/dist/routes/shared-world/participant-specs.js +38 -31
  319. package/dist/routes/shared-world/plan.d.ts +9 -9
  320. package/dist/routes/shared-world/plan.js +16 -16
  321. package/dist/routes/shared-world/provenance.d.ts +2 -2
  322. package/dist/routes/shared-world/provenance.js +2 -2
  323. package/dist/routes/shared-world/provisioned.d.ts +8 -8
  324. package/dist/routes/shared-world/provisioned.js +18 -17
  325. package/dist/routes/shared-world/result.d.ts +6 -6
  326. package/dist/routes/shared-world/result.js +29 -29
  327. package/dist/routes/shared-world/route.d.ts +11 -11
  328. package/dist/routes/shared-world/route.js +40 -39
  329. package/dist/routes/shared-world/setup.d.ts +16 -16
  330. package/dist/routes/shared-world/setup.js +23 -23
  331. package/dist/routes/shared-world/types.d.ts +55 -53
  332. package/dist/routes/shared-world/types.js +4 -4
  333. package/dist/routes/terminal/adapter.d.ts +5 -5
  334. package/dist/routes/terminal/adapter.js +9 -9
  335. package/dist/routes/terminal/bundle.d.ts +13 -13
  336. package/dist/routes/terminal/bundle.js +28 -27
  337. package/dist/routes/terminal/credentials.d.ts +8 -8
  338. package/dist/routes/terminal/credentials.js +12 -12
  339. package/dist/routes/terminal/dry-run.d.ts +4 -4
  340. package/dist/routes/terminal/dry-run.js +12 -12
  341. package/dist/routes/terminal/encoding.js +2 -2
  342. package/dist/routes/terminal/ledger.d.ts +5 -5
  343. package/dist/routes/terminal/ledger.js +14 -14
  344. package/dist/routes/terminal/lifetime.d.ts +1 -1
  345. package/dist/routes/terminal/lifetime.js +1 -1
  346. package/dist/routes/terminal/live-finish.d.ts +2 -2
  347. package/dist/routes/terminal/live-finish.js +10 -10
  348. package/dist/routes/terminal/live-sandbox.d.ts +2 -2
  349. package/dist/routes/terminal/live-sandbox.js +15 -15
  350. package/dist/routes/terminal/participant-text.js +2 -1
  351. package/dist/routes/terminal/persona.d.ts +2 -2
  352. package/dist/routes/terminal/persona.js +3 -3
  353. package/dist/routes/terminal/plan.d.ts +7 -7
  354. package/dist/routes/terminal/plan.js +15 -15
  355. package/dist/routes/terminal/recorder.js +2 -2
  356. package/dist/routes/terminal/result.d.ts +5 -5
  357. package/dist/routes/terminal/result.js +14 -14
  358. package/dist/routes/terminal/route.d.ts +9 -9
  359. package/dist/routes/terminal/route.js +19 -20
  360. package/dist/routes/terminal/sandbox.d.ts +1 -1
  361. package/dist/routes/terminal/sandbox.js +1 -1
  362. package/dist/routes/terminal/session.d.ts +5 -5
  363. package/dist/routes/terminal/session.js +14 -13
  364. package/dist/routes/terminal/token-usage.d.ts +1 -1
  365. package/dist/routes/terminal/token-usage.js +7 -8
  366. package/dist/routes/terminal/trace.d.ts +4 -4
  367. package/dist/routes/terminal/trace.js +2 -2
  368. package/dist/routes/terminal/types.d.ts +48 -50
  369. package/dist/routes/terminal/types.js +5 -5
  370. package/dist/run/bundle-shape.js +3 -3
  371. package/dist/run/bundle.d.ts +49 -49
  372. package/dist/run/bundle.js +3 -2
  373. package/dist/run/cost-summary.js +3 -3
  374. package/dist/run/costs.d.ts +23 -0
  375. package/dist/run/costs.js +79 -44
  376. package/dist/run/detail.d.ts +6 -6
  377. package/dist/run/detail.js +4 -4
  378. package/dist/run/dry-run-inputs.d.ts +1 -1
  379. package/dist/run/dry-run-inputs.js +2 -2
  380. package/dist/run/dry-run.js +20 -20
  381. package/dist/run/judge.d.ts +19 -13
  382. package/dist/run/judge.js +18 -8
  383. package/dist/run/outcomes.d.ts +1 -1
  384. package/dist/run/participant.d.ts +1 -1
  385. package/dist/run/paths.d.ts +1 -1
  386. package/dist/run/paths.js +1 -1
  387. package/dist/run/preflight-receipts.js +1 -1
  388. package/dist/run/pricing.d.ts +11 -6
  389. package/dist/run/pricing.js +22 -15
  390. package/dist/run/projection.d.ts +46 -46
  391. package/dist/run/projection.js +57 -57
  392. package/dist/run/reclaim.d.ts +1 -1
  393. package/dist/run/reclaim.js +3 -3
  394. package/dist/run/results.d.ts +5 -5
  395. package/dist/run/run-cost.d.ts +53 -0
  396. package/dist/run/run-cost.js +105 -0
  397. package/dist/run/run-index-analysis.d.ts +15 -0
  398. package/dist/run/run-index-analysis.js +77 -0
  399. package/dist/run/run-index.d.ts +19 -7
  400. package/dist/run/run-index.js +77 -64
  401. package/dist/run/run-not-found.d.ts +5 -0
  402. package/dist/run/run-not-found.js +15 -0
  403. package/dist/run/run.d.ts +6 -5
  404. package/dist/run/run.js +3 -3
  405. package/dist/run/sandbox-receipts.d.ts +2 -2
  406. package/dist/run/sandbox-receipts.js +3 -3
  407. package/dist/run/shared-world-evidence.d.ts +37 -36
  408. package/dist/run/shared-world-evidence.js +4 -4
  409. package/dist/run/shared-world-shape.d.ts +1 -1
  410. package/dist/run/shared-world-shape.js +7 -7
  411. package/dist/run/stats.d.ts +14 -8
  412. package/dist/run/stats.js +121 -63
  413. package/dist/run/status.d.ts +16 -29
  414. package/dist/run/status.js +10 -29
  415. package/dist/run/stored-runs.js +2 -1
  416. package/dist/run/stream-shape.js +1 -1
  417. package/dist/run/streams.d.ts +7 -7
  418. package/dist/run/study-provenance.d.ts +49 -0
  419. package/dist/run/study-provenance.js +66 -0
  420. package/dist/run/study-result.d.ts +11 -0
  421. package/dist/run/study-result.js +9 -0
  422. package/dist/run/text.d.ts +2 -0
  423. package/dist/run/text.js +4 -0
  424. package/dist/run-study.d.ts +112 -0
  425. package/dist/{run-lab.js → run-study.js} +52 -47
  426. package/dist/{lab → study}/adapter-extension.d.ts +15 -27
  427. package/dist/{lab → study}/adapter-extension.js +10 -45
  428. package/dist/{lab → study}/adapter-scorer-loader.d.ts +17 -17
  429. package/dist/{lab → study}/adapter-scorer-loader.js +34 -34
  430. package/dist/study/composition-rules.d.ts +7 -0
  431. package/dist/{lab → study}/composition-rules.js +53 -53
  432. package/dist/study/config.d.ts +15 -0
  433. package/dist/{lab → study}/config.js +98 -41
  434. package/dist/study/convert.d.ts +33 -0
  435. package/dist/study/convert.js +432 -0
  436. package/dist/{lab → study}/device-presets.d.ts +10 -10
  437. package/dist/{lab → study}/device-presets.js +11 -11
  438. package/dist/study/discover.d.ts +75 -0
  439. package/dist/{lab → study}/discover.js +134 -95
  440. package/dist/{lab → study}/doctor.d.ts +19 -12
  441. package/dist/{lab → study}/doctor.js +58 -20
  442. package/dist/study/field-paths.d.ts +12 -0
  443. package/dist/study/field-paths.js +126 -0
  444. package/dist/study/files.d.ts +26 -0
  445. package/dist/study/files.js +44 -0
  446. package/dist/{lab → study}/init-templates.d.ts +2 -2
  447. package/dist/study/init-templates.js +421 -0
  448. package/dist/{lab → study}/init.d.ts +2 -2
  449. package/dist/{lab → study}/init.js +46 -11
  450. package/dist/study/keys.d.ts +4 -0
  451. package/dist/{lab → study}/keys.js +46 -12
  452. package/dist/study/migrate.d.ts +48 -0
  453. package/dist/study/migrate.js +408 -0
  454. package/dist/study/owned-files.d.ts +38 -0
  455. package/dist/study/owned-files.js +182 -0
  456. package/dist/{lab → study}/parse/actors.d.ts +5 -5
  457. package/dist/{lab → study}/parse/actors.js +14 -14
  458. package/dist/study/parse/comms.d.ts +12 -0
  459. package/dist/{lab → study}/parse/comms.js +5 -5
  460. package/dist/study/parse/execution.d.ts +19 -0
  461. package/dist/{lab → study}/parse/execution.js +13 -13
  462. package/dist/study/parse/study-v3.d.ts +21 -0
  463. package/dist/study/parse/study-v3.js +259 -0
  464. package/dist/study/parse/subject-state.d.ts +30 -0
  465. package/dist/{lab → study}/parse/subject-state.js +19 -19
  466. package/dist/{lab → study}/parse/subject.d.ts +3 -3
  467. package/dist/{lab → study}/parse/subject.js +34 -34
  468. package/dist/{lab → study}/parse/values.d.ts +3 -3
  469. package/dist/{lab → study}/parse/values.js +3 -3
  470. package/dist/{lab → study}/persona-resolve.d.ts +8 -8
  471. package/dist/{lab → study}/persona-resolve.js +6 -6
  472. package/dist/{lab → study}/plan-base.d.ts +7 -7
  473. package/dist/{lab → study}/plan-base.js +1 -1
  474. package/dist/{lab → study}/plan-participants.d.ts +12 -12
  475. package/dist/{lab → study}/plan-participants.js +4 -4
  476. package/dist/{lab → study}/plan-types.d.ts +31 -31
  477. package/dist/{lab → study}/plan-types.js +2 -2
  478. package/dist/study/plan.d.ts +13 -0
  479. package/dist/study/plan.js +101 -0
  480. package/dist/study/preflight-probes.d.ts +3 -0
  481. package/dist/{lab → study}/preflight-probes.js +20 -19
  482. package/dist/study/preflight-result.d.ts +8 -0
  483. package/dist/{lab → study}/preflight-result.js +5 -4
  484. package/dist/study/preflight.d.ts +94 -0
  485. package/dist/{lab → study}/preflight.js +12 -12
  486. package/dist/{lab → study}/requirements.d.ts +3 -3
  487. package/dist/{lab → study}/requirements.js +1 -1
  488. package/dist/study/route-inputs.d.ts +28 -0
  489. package/dist/{lab → study}/route-inputs.js +1 -1
  490. package/dist/{lab → study}/routing.d.ts +39 -33
  491. package/dist/{lab → study}/routing.js +60 -29
  492. package/dist/{lab/run-lab-events.d.ts → study/run-study-events.d.ts} +10 -13
  493. package/dist/{lab/run-lab-events.js → study/run-study-events.js} +3 -9
  494. package/dist/{lab/run-lab-homes.d.ts → study/run-study-homes.d.ts} +21 -18
  495. package/dist/{lab/run-lab-homes.js → study/run-study-homes.js} +1 -1
  496. package/dist/study/run-study-options.d.ts +28 -0
  497. package/dist/{lab/run-lab-options.js → study/run-study-options.js} +29 -25
  498. package/dist/{lab/lab-deps.d.ts → study/study-deps.d.ts} +8 -13
  499. package/dist/{lab/lab-deps.js → study/study-deps.js} +2 -2
  500. package/dist/{lab → study}/summary.d.ts +16 -15
  501. package/dist/{lab → study}/summary.js +21 -21
  502. package/dist/{lab → study}/tasks.d.ts +18 -18
  503. package/dist/{lab → study}/tasks.js +14 -14
  504. package/dist/{lab → study}/types.d.ts +202 -196
  505. package/dist/{lab → study}/types.js +3 -1
  506. package/dist/{lab → study}/validation.d.ts +27 -27
  507. package/dist/{lab → study}/validation.js +53 -51
  508. package/dist/study/warnings.d.ts +12 -0
  509. package/dist/{lab → study}/warnings.js +62 -34
  510. package/dist/subject/clone.d.ts +7 -7
  511. package/dist/subject/clone.js +2 -2
  512. package/dist/subject/desktop-cli.d.ts +1 -1
  513. package/dist/subject/desktop-cli.js +2 -2
  514. package/dist/subject/local-tree-archive.d.ts +2 -2
  515. package/dist/subject/local-tree-archive.js +4 -4
  516. package/dist/subject/local-tree.d.ts +4 -4
  517. package/dist/subject/node-bootstrap.js +1 -1
  518. package/dist/subject/runtime.js +9 -10
  519. package/dist/subject/serve.d.ts +5 -5
  520. package/dist/subject/serve.js +3 -3
  521. package/dist/subject/state.d.ts +4 -4
  522. package/dist/subject/state.js +1 -1
  523. package/dist/subject/steps.d.ts +6 -6
  524. package/dist/subject/steps.js +5 -5
  525. package/dist/substrates/command-failure.d.ts +3 -3
  526. package/dist/substrates/command-failure.js +3 -3
  527. package/dist/substrates/desktop-session.js +2 -2
  528. package/dist/substrates/detached.d.ts +6 -6
  529. package/dist/substrates/detached.js +7 -7
  530. package/dist/substrates/e2b/cdp-probe.d.ts +9 -9
  531. package/dist/substrates/e2b/cdp-probe.js +14 -17
  532. package/dist/substrates/e2b/desktop-browser.d.ts +6 -6
  533. package/dist/substrates/e2b/desktop-browser.js +9 -9
  534. package/dist/substrates/e2b/desktop-cdp.d.ts +10 -10
  535. package/dist/substrates/e2b/desktop-cdp.js +9 -9
  536. package/dist/substrates/e2b/desktop-executor.d.ts +2 -2
  537. package/dist/substrates/e2b/desktop-executor.js +13 -13
  538. package/dist/substrates/e2b/desktop-geometry.d.ts +4 -4
  539. package/dist/substrates/e2b/desktop-geometry.js +8 -8
  540. package/dist/substrates/e2b/desktop-media.d.ts +4 -4
  541. package/dist/substrates/e2b/desktop-media.js +1 -1
  542. package/dist/substrates/e2b/desktop-screenshot-cleanup.d.ts +3 -3
  543. package/dist/substrates/e2b/desktop-screenshot-cleanup.js +3 -3
  544. package/dist/substrates/e2b/lifetime.js +1 -1
  545. package/dist/substrates/e2b/sandbox.d.ts +4 -4
  546. package/dist/substrates/e2b/sandbox.js +2 -2
  547. package/dist/substrates/e2b/sdk.d.ts +12 -12
  548. package/dist/substrates/e2b/sdk.js +7 -7
  549. package/dist/substrates/local/runtime-config.d.ts +4 -4
  550. package/dist/substrates/local/runtime-config.js +4 -4
  551. package/dist/tui/actions.d.ts +1 -1
  552. package/dist/tui/actions.js +13 -13
  553. package/dist/tui/contract.d.ts +23 -23
  554. package/dist/tui/contract.js +11 -11
  555. package/dist/tui/launch.d.ts +7 -7
  556. package/dist/tui/launch.js +36 -31
  557. package/dist/tui/project.js +5 -5
  558. package/dist/tui-app.js +139 -139
  559. package/dist/verify/actor.d.ts +8 -8
  560. package/dist/verify/actor.js +36 -36
  561. package/dist/verify/artifacts.d.ts +2 -2
  562. package/dist/verify/artifacts.js +3 -3
  563. package/dist/verify/context-growth.d.ts +9 -0
  564. package/dist/verify/context-growth.js +62 -0
  565. package/dist/verify/costs.d.ts +6 -6
  566. package/dist/verify/costs.js +8 -8
  567. package/dist/verify/shared-world-concurrent.d.ts +2 -2
  568. package/dist/verify/shared-world-concurrent.js +79 -76
  569. package/dist/verify/shared-world.d.ts +2 -2
  570. package/dist/verify/shared-world.js +16 -16
  571. package/dist/verify/subject.d.ts +5 -5
  572. package/dist/verify/subject.js +19 -19
  573. package/dist/verify/verify.js +94 -44
  574. package/docs/README.md +25 -32
  575. package/docs/architecture/actor-contract.md +60 -91
  576. package/docs/architecture/browser-control.md +1 -1
  577. package/docs/architecture/desktop-sessions.md +7 -7
  578. package/docs/architecture/external-public-shared-world.md +68 -65
  579. package/docs/architecture/github-feedback-loop.md +2 -5
  580. package/docs/architecture/guest-desktop.md +2 -2
  581. package/docs/architecture/observer.md +34 -34
  582. package/docs/architecture/restricted-codex-analysis.md +34 -28
  583. package/docs/architecture/serve.md +34 -37
  584. package/docs/architecture/state-driven-executor.md +55 -58
  585. package/docs/architecture/task-protocol-support.md +6 -6
  586. package/docs/architecture/terminal-product-route.md +70 -110
  587. package/docs/contracts/README.md +24 -0
  588. package/docs/contracts/adapter-admission.md +3 -3
  589. package/docs/contracts/adapter-fixtures.md +4 -7
  590. package/docs/contracts/core.md +1 -3
  591. package/docs/contracts/errors.md +62 -0
  592. package/docs/contracts/feedback.md +8 -9
  593. package/docs/contracts/policy.md +7 -12
  594. package/docs/contracts/run-bundle.md +42 -44
  595. package/docs/contracts/schemas.md +446 -368
  596. package/docs/contracts/study-analysis.md +7 -4
  597. package/docs/contracts/study-costs.md +28 -9
  598. package/docs/decisions/0001-run-bundle-is-the-source-of-truth.md +1 -1
  599. package/docs/decisions/0002-observer-is-one-self-contained-file.md +2 -2
  600. package/docs/decisions/0003-contained-paths-and-cleanup-authority.md +3 -3
  601. package/docs/principles/actor-fidelity.md +4 -4
  602. package/docs/principles/engineering.md +3 -3
  603. package/docs/principles/invariants-and-defaults.md +38 -38
  604. package/docs/principles/self-driving-harness.md +1 -5
  605. package/docs/principles/three-roles.md +1 -1
  606. package/docs/product/automatic-analysis.md +7 -7
  607. package/examples/README.md +1 -1
  608. package/examples/participant/README.md +5 -5
  609. package/examples/participant/run.mjs +11 -10
  610. package/examples/scorer/README.md +3 -3
  611. package/examples/scorer/run.mjs +11 -12
  612. package/examples/scorer/scorer.mjs +3 -3
  613. package/package.json +16 -17
  614. package/skills/humanish/SKILL.md +64 -60
  615. package/skills/humanish/agents/openai.yaml +1 -1
  616. package/AGENTS.md +0 -99
  617. package/CONTRIBUTING.md +0 -148
  618. package/dist/actors/codex/qualified-versions.d.ts +0 -72
  619. package/dist/actors/codex/qualified-versions.js +0 -132
  620. package/dist/cli/commands/lab-format.d.ts +0 -8
  621. package/dist/cli/commands/lab-route-run.d.ts +0 -19
  622. package/dist/cli/commands/lab-route-scripted.d.ts +0 -17
  623. package/dist/cli/commands/lab-route-terminal.d.ts +0 -17
  624. package/dist/cli/commands/lab-run.d.ts +0 -9
  625. package/dist/cli/commands/lab.d.ts +0 -3
  626. package/dist/cli/commands/lab.js +0 -199
  627. package/dist/cli/renamed-options.d.ts +0 -11
  628. package/dist/cli/renamed-options.js +0 -18
  629. package/dist/lab/composition-rules.d.ts +0 -7
  630. package/dist/lab/config.d.ts +0 -7
  631. package/dist/lab/discover.d.ts +0 -65
  632. package/dist/lab/init-templates.js +0 -416
  633. package/dist/lab/keys.d.ts +0 -2
  634. package/dist/lab/parse/comms.d.ts +0 -12
  635. package/dist/lab/parse/execution.d.ts +0 -19
  636. package/dist/lab/parse/subject-state.d.ts +0 -30
  637. package/dist/lab/plan.d.ts +0 -19
  638. package/dist/lab/plan.js +0 -132
  639. package/dist/lab/preflight-probes.d.ts +0 -3
  640. package/dist/lab/preflight-result.d.ts +0 -7
  641. package/dist/lab/preflight.d.ts +0 -92
  642. package/dist/lab/route-inputs.d.ts +0 -28
  643. package/dist/lab/run-lab-options.d.ts +0 -28
  644. package/dist/lab/warnings.d.ts +0 -2
  645. package/dist/observer/static.d.ts +0 -39
  646. package/dist/observer/static.js +0 -369
  647. package/dist/run-lab.d.ts +0 -112
  648. package/docs/architecture/comms-inbox.md +0 -122
  649. package/docs/architecture/desktop-recording.md +0 -80
  650. package/docs/architecture/local-browser-runtime.md +0 -178
  651. package/docs/architecture/observer-review.md +0 -144
  652. package/docs/architecture/participant-media.md +0 -90
  653. package/docs/architecture/project-layout.md +0 -62
  654. package/docs/architecture/real-email-receiving.md +0 -136
  655. package/docs/assets/humanish-drawdb-hero.png +0 -0
  656. package/docs/assets/humanish-observer-hero.png +0 -0
  657. package/docs/goals/current.md +0 -207
  658. package/docs/product/lobby-trivia-3player-external-public.md +0 -77
  659. package/docs/product/open-source-install-experience.md +0 -240
  660. package/docs/ramp/README.md +0 -295
  661. package/docs/release/open-source-readiness.md +0 -222
  662. package/docs/release/public-readiness-standard.md +0 -210
  663. package/docs/roadmap/world-class-open-source-v0.md +0 -311
  664. /package/dist/{lab → study}/init-paths.d.ts +0 -0
  665. /package/dist/{lab → study}/init-paths.js +0 -0
  666. /package/dist/{lab → study}/init-plan.d.ts +0 -0
  667. /package/dist/{lab → study}/init-plan.js +0 -0
  668. /package/dist/{lab → study}/participant-assignment.d.ts +0 -0
  669. /package/dist/{lab → study}/participant-assignment.js +0 -0
  670. /package/dist/{lab → study}/persona.d.ts +0 -0
  671. /package/dist/{lab → study}/persona.js +0 -0
@@ -0,0 +1,105 @@
1
+ /** The accounting's analysis spend, or null when the run sent no analysis request. */
2
+ export function analysisCostOf(accounting) {
3
+ const requests = accounting.dispatched + accounting.unresolved;
4
+ if (requests === 0)
5
+ return null;
6
+ const historyWhole = accounting.warnings.every((warning) => warning === "ANALYSIS_HISTORY_NOT_RECORDED");
7
+ return {
8
+ requests,
9
+ estimatedUsd: accounting.estimatedUsd,
10
+ complete: accounting.unpriced === 0 && historyWhole,
11
+ providers: [...accounting.providers],
12
+ };
13
+ }
14
+ export function runCost(subtotal, analysis) {
15
+ if (subtotal === null || subtotal === undefined)
16
+ return { run: null, analysis: null, total: null };
17
+ const run = {
18
+ usd: typeof subtotal.estimatedTotalUsd === "number" ? subtotal.estimatedTotalUsd : null,
19
+ complete: subtotal.fullyEstimated === undefined ? null : subtotal.fullyEstimated,
20
+ ratesAsOf: subtotal.ratesAsOf ?? null,
21
+ placeholder: subtotal.placeholder === true,
22
+ };
23
+ const spent = analysis ?? null;
24
+ const known = [run.usd, spent?.estimatedUsd].filter((usd) => typeof usd === "number");
25
+ if (known.length === 0)
26
+ return { run, analysis: spent, total: null };
27
+ const lowerBound = run.usd === null || run.complete === false || spent?.complete === false;
28
+ return {
29
+ run,
30
+ analysis: spent,
31
+ total: {
32
+ usd: round6(known.reduce((sum, usd) => sum + usd, 0)),
33
+ complete: lowerBound ? false : run.complete,
34
+ },
35
+ };
36
+ }
37
+ /**
38
+ * A run index entry's cost: its participants-and-desktops figure, complete or a lower bound when
39
+ * the status record says which, plus its analyses.
40
+ */
41
+ export function indexedRunCost(entry) {
42
+ return runCost({
43
+ estimatedTotalUsd: entry.estimatedCostUsd ?? null,
44
+ ...(entry.estimatedCostComplete === undefined
45
+ ? {}
46
+ : { fullyEstimated: entry.estimatedCostComplete }),
47
+ }, entry.analysisCost);
48
+ }
49
+ /** Six decimals, as the run cost summary rounds, so sums of small estimates do not drift. */
50
+ function round6(value) {
51
+ return Math.round(value * 1e6) / 1e6;
52
+ }
53
+ /** An estimate, saying so when some of the spend has no price and is not in it. */
54
+ function estimateText(usd, complete) {
55
+ return `est. ~$${usd.toFixed(2)}${complete === false ? " plus unpriced usage" : ""}`;
56
+ }
57
+ function analysesNoun(requests) {
58
+ return requests === 1 ? "analysis" : `${requests} analyses`;
59
+ }
60
+ function billedBy(providers) {
61
+ const names = providers.map((provider) => provider === "openai" ? "OpenAI API key" : "Codex account");
62
+ return names.length === 0 ? "" : ` (${names.join(" and ")})`;
63
+ }
64
+ /**
65
+ * The cost as separate parts: participants and desktops, then the analysis and the total when the
66
+ * run sent an analysis request. Empty when the run has no cost summary.
67
+ */
68
+ export function runCostParts(cost) {
69
+ if (cost.run === null)
70
+ return [];
71
+ const rates = `rates as of ${cost.run.ratesAsOf}${cost.run.placeholder ? ", placeholder" : ""}`;
72
+ const parts = [
73
+ cost.run.usd === null
74
+ ? "Participants + desktops: cost not estimated"
75
+ : `Participants + desktops: ${estimateText(cost.run.usd, cost.run.complete)} (${rates})`,
76
+ ];
77
+ const analysis = cost.analysis;
78
+ if (analysis === null)
79
+ return parts;
80
+ const noun = analysesNoun(analysis.requests);
81
+ const label = noun.charAt(0).toUpperCase() + noun.slice(1);
82
+ if (analysis.estimatedUsd === null)
83
+ parts.push(analysis.providers.length === 1 && analysis.providers[0] === "codex"
84
+ ? `${label}: Codex account, dollar cost unknown`
85
+ : `${label}: cost not estimated${billedBy(analysis.providers)}`);
86
+ else
87
+ parts.push(`${label}: ${estimateText(analysis.estimatedUsd, analysis.complete)}${billedBy(analysis.providers)}`);
88
+ if (cost.total !== null)
89
+ parts.push(`Total: ${estimateText(cost.total.usd, cost.total.complete)}`);
90
+ return parts;
91
+ }
92
+ /**
93
+ * The cost in one short label for a list row: the total, and how many analyses it includes.
94
+ * Undefined when the run has no cost summary.
95
+ */
96
+ export function runCostLabel(cost) {
97
+ if (cost.run === null)
98
+ return undefined;
99
+ const amount = cost.total === null
100
+ ? "cost not estimated"
101
+ : `~$${cost.total.usd.toFixed(2)} est.${cost.total.complete === false ? " plus unpriced usage" : ""}`;
102
+ return cost.analysis === null
103
+ ? amount
104
+ : `${amount}, with ${analysesNoun(cost.analysis.requests)}`;
105
+ }
@@ -0,0 +1,15 @@
1
+ import { type RunAnalysisCost } from "./run-cost.js";
2
+ /** Per-run analysis costs, keyed on their fingerprint. Nothing here is authoritative. */
3
+ export declare class AnalysisCostCache {
4
+ private readonly slots;
5
+ get(runId: string, fingerprint: string): {
6
+ cost: RunAnalysisCost | undefined;
7
+ } | undefined;
8
+ set(runId: string, fingerprint: string, cost: RunAnalysisCost | undefined): void;
9
+ retain(keep: Set<string>): void;
10
+ }
11
+ /**
12
+ * The run's analysis spend for its index entry, read with the same reader stats uses. Undefined
13
+ * when the run sent no analysis request or its run directory cannot be bound.
14
+ */
15
+ export declare function readIndexedAnalysisCost(cwd: string, runId: string, cache: AnalysisCostCache | undefined): Promise<RunAnalysisCost | undefined>;
@@ -0,0 +1,77 @@
1
+ import { readdir, stat } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { AUTOMATIC_ANALYSIS_DIRECTORY } from "../analysis/job.js";
4
+ import { ANALYSIS_DIRECTORY, ANALYSIS_EXECUTION_DIRECTORY } from "../analysis/store.js";
5
+ import { readAnalysisAccounting } from "./costs.js";
6
+ import { bindExistingRunArtifactPaths } from "./paths.js";
7
+ import { analysisCostOf } from "./run-cost.js";
8
+ // A run's analysis is written after its status record and bundle are final, so the index keys a
9
+ // run's analysis cost on a fingerprint of the analysis directories, not on the status record. A
10
+ // receipt lands inside an attempt directory that already exists, which changes that directory's
11
+ // mtime and not its parent's, so each attempt directory is part of the fingerprint.
12
+ /** Stat signatures of everything an analysis write changes; null when the run has no analysis. */
13
+ async function analysisFingerprint(runDir) {
14
+ const signatures = [];
15
+ for (const directory of [ANALYSIS_EXECUTION_DIRECTORY, ANALYSIS_DIRECTORY]) {
16
+ const root = path.join(runDir, directory);
17
+ const rootSignature = await signature(root);
18
+ if (rootSignature === null)
19
+ continue;
20
+ signatures.push(`${directory}:${rootSignature}`);
21
+ const children = await readdir(root).catch(() => []);
22
+ for (const child of children.sort((left, right) => left.localeCompare(right)))
23
+ signatures.push(`${directory}/${child}:${await signature(path.join(root, child))}`);
24
+ }
25
+ const job = await signature(path.join(runDir, AUTOMATIC_ANALYSIS_DIRECTORY, "job.json"));
26
+ if (job !== null)
27
+ signatures.push(`job:${job}`);
28
+ return signatures.length === 0 ? null : signatures.join("|");
29
+ }
30
+ async function signature(file) {
31
+ try {
32
+ const stats = await stat(file);
33
+ return `${Number(stats.ino)}:${stats.mtimeMs}:${stats.ctimeMs}:${stats.size}`;
34
+ }
35
+ catch {
36
+ return null;
37
+ }
38
+ }
39
+ /** Per-run analysis costs, keyed on their fingerprint. Nothing here is authoritative. */
40
+ export class AnalysisCostCache {
41
+ slots = new Map();
42
+ get(runId, fingerprint) {
43
+ const slot = this.slots.get(runId);
44
+ return slot?.fingerprint === fingerprint ? { cost: slot.cost } : undefined;
45
+ }
46
+ set(runId, fingerprint, cost) {
47
+ this.slots.set(runId, { fingerprint, cost });
48
+ }
49
+ retain(keep) {
50
+ for (const runId of this.slots.keys())
51
+ if (!keep.has(runId))
52
+ this.slots.delete(runId);
53
+ }
54
+ }
55
+ /**
56
+ * The run's analysis spend for its index entry, read with the same reader stats uses. Undefined
57
+ * when the run sent no analysis request or its run directory cannot be bound.
58
+ */
59
+ export async function readIndexedAnalysisCost(cwd, runId, cache) {
60
+ const fingerprint = await analysisFingerprint(path.join(cwd, ".humanish", "runs", runId));
61
+ if (fingerprint === null)
62
+ return undefined;
63
+ const cached = cache?.get(runId, fingerprint);
64
+ if (cached !== undefined)
65
+ return cached.cost;
66
+ let prepared;
67
+ try {
68
+ prepared = await bindExistingRunArtifactPaths(cwd, runId);
69
+ }
70
+ catch {
71
+ // Not cached: a directory that cannot be bound now may bind on the next refresh.
72
+ return undefined;
73
+ }
74
+ const cost = analysisCostOf(await readAnalysisAccounting(prepared)) ?? undefined;
75
+ cache?.set(runId, fingerprint, cost);
76
+ return cost;
77
+ }
@@ -1,4 +1,7 @@
1
- import { type RunLabProvenance, type RunLiveness, type RunStatusRecord } from "./status.js";
1
+ import { AnalysisCostCache } from "./run-index-analysis.js";
2
+ import type { RunAnalysisCost } from "./run-cost.js";
3
+ import { type RunLiveness, type RunStatusRecord } from "./status.js";
4
+ import { type RunStudyProvenance } from "./study-provenance.js";
2
5
  declare const RUN_INDEX_SCHEMA = "humanish.run-index.v1";
3
6
  export interface RunIndexEntry {
4
7
  runId: string;
@@ -12,7 +15,7 @@ export interface RunIndexEntry {
12
15
  * one run's record carries that pid.
13
16
  */
14
17
  pid?: number;
15
- lab?: RunLabProvenance;
18
+ study?: RunStudyProvenance;
16
19
  startedAt?: string;
17
20
  updatedAt?: string;
18
21
  completedAt?: string;
@@ -22,8 +25,13 @@ export interface RunIndexEntry {
22
25
  reachedGoal: number;
23
26
  reportedFriction?: number;
24
27
  };
28
+ /** Participants and desktops only; analysis bills separately and is in `analysisCost`. */
25
29
  estimatedCostUsd?: number | null;
26
- /** Wall-clock span when both ends are known; used for per-lab medians. */
30
+ /** False when that figure is a lower bound; absent when unknown (a status record before 0.109). */
31
+ estimatedCostComplete?: boolean;
32
+ /** The run's analysis requests, every attempt counted once; absent when it sent none. */
33
+ analysisCost?: RunAnalysisCost;
34
+ /** Wall-clock span when both ends are known; used for per-study medians. */
27
35
  durationMs?: number;
28
36
  }
29
37
  export interface RunIndexResult {
@@ -31,7 +39,7 @@ export interface RunIndexResult {
31
39
  cwd: string;
32
40
  /** Newest first, by the best timestamp each entry has. */
33
41
  runs: RunIndexEntry[];
34
- /** Directories that could not be read at all, by name — surfaced, never silently dropped. */
42
+ /** Directories that could not be read at all, by name: surfaced, never silently dropped. */
35
43
  unreadable: string[];
36
44
  }
37
45
  /** What a cached entry was derived from, so a changed file invalidates exactly that entry. */
@@ -48,6 +56,8 @@ interface CacheKey {
48
56
  */
49
57
  export declare class RunIndexCache {
50
58
  private readonly slots;
59
+ /** Analysis costs, keyed on their own fingerprint: analysis lands after the status record. */
60
+ readonly analysis: AnalysisCostCache;
51
61
  get(runId: string, key: CacheKey): RunIndexEntry | undefined;
52
62
  set(runId: string, key: CacheKey, entry: RunIndexEntry): void;
53
63
  /** Drop entries for runs that no longer exist, so a long-lived surface cannot leak. */
@@ -59,7 +69,8 @@ interface BundleFacts {
59
69
  runId?: string;
60
70
  mode?: string;
61
71
  createdAt?: string;
62
- lab?: RunLabProvenance;
72
+ study?: unknown;
73
+ lab?: unknown;
63
74
  persona?: {
64
75
  source?: string;
65
76
  };
@@ -79,6 +90,7 @@ interface BundleFacts {
79
90
  };
80
91
  cost?: {
81
92
  estimatedTotalUsd?: number | null;
93
+ fullyEstimated?: unknown;
82
94
  };
83
95
  }
84
96
  /**
@@ -95,8 +107,8 @@ export interface ReadRunIndexOptions {
95
107
  cache?: RunIndexCache;
96
108
  /** Injectable clock, so liveness classification is reproducible in tests. */
97
109
  nowMs?: number;
98
- /** Cap the number of runs returned (newest first). The full directory is still enumerated —
99
- * a cap on reads, not on truth — and the count reflects what was read. */
110
+ /** Cap the number of runs returned (newest first). The full directory is still enumerated;
111
+ * the cap limits reads, and the count reflects what was read. */
100
112
  limit?: number;
101
113
  }
102
114
  /**
@@ -1,21 +1,23 @@
1
- // The run index (#455 PR 2): list and classify every run in a project without parsing bundles.
1
+ // The run index: list and classify every run in a project without parsing bundles.
2
2
  //
3
- // The existing `listRuns` walks each run tree — screenshots included — validating symlinks and
3
+ // The existing `listRuns` walks each run tree, screenshots included, validating symlinks and
4
4
  // then parses each `run.json`: measured 197ms cold / 152ms warm at 25 runs. That is fine for a
5
5
  // command that prints once and exits, and much too hot for a surface that refreshes on a cadence
6
6
  // over SSH. This module reads the small `status.json` record each run now writes (586 bytes beside
7
7
  // a 92KB bundle) and caches per-run entries keyed on the stat of the file each was derived from.
8
8
  //
9
- // Honesty rules, unchanged from the record itself:
9
+ // Rules, unchanged from the record itself:
10
10
  // - `run.json` is the evidence-of-record. Every field here is a projection for listing and
11
11
  // classification; nothing here is a claim about what a participant did.
12
12
  // - A run with no status record is not assumed finished. It is classified from what is on disk:
13
- // a bundle means finished, receipts without a bundle mean interrupted. That is the honest
14
- // reading of a run whose process died — and, before this contract existed, of every run.
13
+ // a bundle means finished, receipts without a bundle mean interrupted. That is the
14
+ // reading of a run whose process died (and, before this contract existed, of every run).
15
15
  // - One unreadable run directory degrades that run, never the listing.
16
16
  import { readdir, readFile, stat } from "node:fs/promises";
17
17
  import path from "node:path";
18
- import { RUN_STATUS_FILE, classifyRunStatus, inferLegacyLabId, isRunStatusRecord, } from "./status.js";
18
+ import { AnalysisCostCache, readIndexedAnalysisCost } from "./run-index-analysis.js";
19
+ import { RUN_STATUS_FILE, classifyRunStatus, isRunStatusRecord, } from "./status.js";
20
+ import { studyProvenanceOf } from "./study-provenance.js";
19
21
  import { RUN_BUNDLE_FILE } from "./bundle.js";
20
22
  const RUN_INDEX_SCHEMA = "humanish.run-index.v1";
21
23
  /**
@@ -25,6 +27,8 @@ const RUN_INDEX_SCHEMA = "humanish.run-index.v1";
25
27
  */
26
28
  export class RunIndexCache {
27
29
  slots = new Map();
30
+ /** Analysis costs, keyed on their own fingerprint: analysis lands after the status record. */
31
+ analysis = new AnalysisCostCache();
28
32
  get(runId, key) {
29
33
  const slot = this.slots.get(runId);
30
34
  if (slot === undefined)
@@ -45,6 +49,7 @@ export class RunIndexCache {
45
49
  if (!keep.has(runId))
46
50
  this.slots.delete(runId);
47
51
  }
52
+ this.analysis.retain(keep);
48
53
  }
49
54
  get size() {
50
55
  return this.slots.size;
@@ -78,7 +83,7 @@ function entryFromStatus(record, nowMs) {
78
83
  liveness: classifyRunStatus(record, nowMs),
79
84
  mode: record.mode,
80
85
  ...(typeof record.pid === "number" ? { pid: record.pid } : {}),
81
- ...(record.lab === undefined ? {} : { lab: record.lab }),
86
+ ...studyEntry(studyProvenanceOf(record)),
82
87
  startedAt: record.startedAt,
83
88
  updatedAt: record.updatedAt,
84
89
  ...(record.completedAt === undefined ? {} : { completedAt: record.completedAt }),
@@ -89,6 +94,9 @@ function entryFromStatus(record, nowMs) {
89
94
  ...(record.outcome?.estimatedCostUsd === undefined
90
95
  ? {}
91
96
  : { estimatedCostUsd: record.outcome.estimatedCostUsd }),
97
+ ...(typeof record.outcome?.estimatedCostComplete === "boolean"
98
+ ? { estimatedCostComplete: record.outcome.estimatedCostComplete }
99
+ : {}),
92
100
  ...(Number.isFinite(started) && Number.isFinite(ended) ? { durationMs: ended - started } : {}),
93
101
  };
94
102
  }
@@ -98,9 +106,9 @@ function usableStatusRecord(raw, runId) {
98
106
  }
99
107
  /**
100
108
  * The bundle-only reading, for a run with no usable status record. A bundle on disk usually means
101
- * the run reached its final write. But a live run now flushes an IN-PROGRESS bundle as it goes (so
109
+ * the run reached its final write. But a live run now flushes an in-progress bundle as it goes (so
102
110
  * anything asking what a participant is doing has something to read), and that bundle marks its
103
- * simulations `running`. With no status record there is no freshness to judge, and the honest
111
+ * simulations `running`. With no status record there is no freshness to judge, and the
104
112
  * reading of "it started, and nothing here says it finished" is interrupted, not finished.
105
113
  */
106
114
  function bundleLiveness(bundle) {
@@ -117,18 +125,16 @@ export function runLiveness(runId, status, bundle, nowMs) {
117
125
  ? { liveness: classifyRunStatus(status, nowMs), record: status }
118
126
  : { liveness: bundleLiveness(bundle) };
119
127
  }
128
+ function studyEntry(study) {
129
+ return study === undefined ? {} : { study };
130
+ }
120
131
  function entryFromBundle(runId, bundle) {
121
- const legacyLabId = bundle.lab === undefined ? inferLegacyLabId(bundle) : undefined;
122
132
  return {
123
133
  runId,
124
134
  derivedFrom: "bundle",
125
135
  liveness: bundleLiveness(bundle),
126
136
  ...(bundle.mode === "dry-run" || bundle.mode === "live" ? { mode: bundle.mode } : {}),
127
- ...(bundle.lab !== undefined
128
- ? { lab: bundle.lab }
129
- : legacyLabId === undefined
130
- ? {}
131
- : { lab: { id: legacyLabId } }),
137
+ ...studyEntry(studyProvenanceOf(bundle)),
132
138
  ...(bundle.createdAt === undefined ? {} : { startedAt: bundle.createdAt }),
133
139
  ...(bundle.review?.verdict === undefined ? {} : { verdict: bundle.review.verdict }),
134
140
  ...(bundle.review?.participants === undefined
@@ -137,6 +143,9 @@ function entryFromBundle(runId, bundle) {
137
143
  ...(bundle.cost?.estimatedTotalUsd === undefined
138
144
  ? {}
139
145
  : { estimatedCostUsd: bundle.cost.estimatedTotalUsd }),
146
+ ...(typeof bundle.cost?.fullyEstimated === "boolean"
147
+ ? { estimatedCostComplete: bundle.cost.fullyEstimated }
148
+ : {}),
140
149
  };
141
150
  }
142
151
  /**
@@ -160,58 +169,15 @@ export async function readRunIndex(cwdInput, options = {}) {
160
169
  const runs = [];
161
170
  const unreadable = [];
162
171
  for (const runId of runIds) {
163
- const runDir = path.join(runsRoot, runId);
164
- const statusFile = path.join(runDir, RUN_STATUS_FILE);
165
- const bundleFile = path.join(runDir, RUN_BUNDLE_FILE);
166
- // Cheapest source first: the status record. Its stat is the cache key, so a live run whose
167
- // record ticks every 5s re-reads 586 bytes and nothing else.
168
- const statusKey = await statKey(statusFile);
169
- if (statusKey !== null) {
170
- const cached = cache?.get(runId, statusKey);
171
- if (cached !== undefined) {
172
- // A running record's liveness is time-dependent, so it is recomputed even on a cache hit:
173
- // an unchanged record can still have gone stale. An ended record (finished or
174
- // interrupted, both with completedAt) keeps the liveness it was cached with.
175
- runs.push(cached.derivedFrom === "status" &&
176
- cached.updatedAt !== undefined &&
177
- cached.completedAt === undefined
178
- ? {
179
- ...cached,
180
- liveness: classifyRunStatus({ state: "running", updatedAt: cached.updatedAt }, nowMs),
181
- }
182
- : cached);
183
- continue;
184
- }
185
- const raw = await readJson(statusFile);
186
- if (usableStatusRecord(raw, runId)) {
187
- const entry = entryFromStatus(raw, nowMs);
188
- cache?.set(runId, statusKey, entry);
189
- runs.push(entry);
190
- continue;
191
- }
192
- }
193
- // No usable status record: fall back to the bundle. This is every run written before the
194
- // contract existed, and it is why an old project still lists correctly.
195
- const bundleKey = await statKey(bundleFile);
196
- if (bundleKey !== null) {
197
- const cached = cache?.get(runId, bundleKey);
198
- if (cached !== undefined) {
199
- runs.push(cached);
200
- continue;
201
- }
202
- const raw = await readJson(bundleFile);
203
- if (raw !== null && typeof raw === "object") {
204
- const entry = entryFromBundle(runId, raw);
205
- cache?.set(runId, bundleKey, entry);
206
- runs.push(entry);
207
- continue;
208
- }
172
+ const entry = await readEntry(runId, path.join(runsRoot, runId), cache, nowMs);
173
+ if (entry === "unreadable") {
209
174
  unreadable.push(runId);
210
175
  continue;
211
176
  }
212
- // Neither record nor bundle: receipts without an outcome. That is precisely an interrupted
213
- // run — the shape a dropped connection leaves — and saying so is more useful than hiding it.
214
- runs.push({ runId, derivedFrom: "directory", liveness: "interrupted" });
177
+ const analysisCost = entry.derivedFrom === "directory"
178
+ ? undefined
179
+ : await readIndexedAnalysisCost(cwd, runId, cache?.analysis);
180
+ runs.push(analysisCost === undefined ? entry : { ...entry, analysisCost });
215
181
  }
216
182
  cache?.retain(runIds);
217
183
  runs.sort((left, right) => sortKey(right) - sortKey(left));
@@ -222,6 +188,53 @@ export async function readRunIndex(cwdInput, options = {}) {
222
188
  unreadable,
223
189
  };
224
190
  }
191
+ /** One run's entry, cheapest source first, or "unreadable" when its bundle cannot be parsed. */
192
+ async function readEntry(runId, runDir, cache, nowMs) {
193
+ const statusFile = path.join(runDir, RUN_STATUS_FILE);
194
+ const bundleFile = path.join(runDir, RUN_BUNDLE_FILE);
195
+ // Cheapest source first: the status record. Its stat is the cache key, so a live run whose
196
+ // record ticks every 5s re-reads 586 bytes and nothing else.
197
+ const statusKey = await statKey(statusFile);
198
+ if (statusKey !== null) {
199
+ const cached = cache?.get(runId, statusKey);
200
+ if (cached !== undefined) {
201
+ // A running record's liveness is time-dependent, so it is recomputed even on a cache hit:
202
+ // an unchanged record can still have gone stale. An ended record (finished or
203
+ // interrupted, both with completedAt) keeps the liveness it was cached with.
204
+ return cached.derivedFrom === "status" &&
205
+ cached.updatedAt !== undefined &&
206
+ cached.completedAt === undefined
207
+ ? {
208
+ ...cached,
209
+ liveness: classifyRunStatus({ state: "running", updatedAt: cached.updatedAt }, nowMs),
210
+ }
211
+ : cached;
212
+ }
213
+ const raw = await readJson(statusFile);
214
+ if (usableStatusRecord(raw, runId)) {
215
+ const entry = entryFromStatus(raw, nowMs);
216
+ cache?.set(runId, statusKey, entry);
217
+ return entry;
218
+ }
219
+ }
220
+ // No usable status record: fall back to the bundle. This is every run written before the
221
+ // contract existed, and it is why an old project still lists correctly.
222
+ const bundleKey = await statKey(bundleFile);
223
+ if (bundleKey !== null) {
224
+ const cached = cache?.get(runId, bundleKey);
225
+ if (cached !== undefined)
226
+ return cached;
227
+ const raw = await readJson(bundleFile);
228
+ if (raw === null || typeof raw !== "object")
229
+ return "unreadable";
230
+ const entry = entryFromBundle(runId, raw);
231
+ cache?.set(runId, bundleKey, entry);
232
+ return entry;
233
+ }
234
+ // Neither record nor bundle: receipts without an outcome. That is precisely an interrupted
235
+ // run (the shape a dropped connection leaves), and saying so is more useful than hiding it.
236
+ return { runId, derivedFrom: "directory", liveness: "interrupted" };
237
+ }
225
238
  /** Newest-first ordering: the most recent thing known about a run, else its id's own timestamp. */
226
239
  function sortKey(entry) {
227
240
  for (const candidate of [entry.completedAt, entry.updatedAt, entry.startedAt]) {
@@ -0,0 +1,5 @@
1
+ /**
2
+ * The message for a run that is not there: how to start one when the project has no runs, or how
3
+ * to list them when it has. Only the runs directory's entry names are read.
4
+ */
5
+ export declare function runNotFoundMessage(cwdInput: string, runInput: string): Promise<string>;
@@ -0,0 +1,15 @@
1
+ import { readdir } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { resolveRunsRoot } from "./paths.js";
4
+ /**
5
+ * The message for a run that is not there: how to start one when the project has no runs, or how
6
+ * to list them when it has. Only the runs directory's entry names are read.
7
+ */
8
+ export async function runNotFoundMessage(cwdInput, runInput) {
9
+ const cwd = path.resolve(cwdInput);
10
+ const entries = await readdir(resolveRunsRoot(cwd)).catch(() => []);
11
+ const hasRun = entries.some((name) => !name.startsWith(".") && !name.endsWith(".json"));
12
+ return hasRun
13
+ ? `No run ${runInput}; humanish runs lists them.`
14
+ : `No runs in ${cwd} yet; start one with humanish run first-run.`;
15
+ }
package/dist/run/run.d.ts CHANGED
@@ -2,7 +2,8 @@ import { renderObserver, type ObserverResult } from "../observer/render.js";
2
2
  import { type RunBundle } from "./bundle.js";
3
3
  import type { ExecutionOutcome } from "./judge.js";
4
4
  import { type PreparedRunArtifactPaths, type RunIdInUse } from "./paths.js";
5
- import { type RunLabProvenance, type RunStatusHandle } from "./status.js";
5
+ import { type RunStatusHandle } from "./status.js";
6
+ import type { RunStudyProvenance } from "./study-provenance.js";
6
7
  interface StartRunOptions {
7
8
  /** Project directory, in the form the route resolved it. */
8
9
  cwd: string;
@@ -10,10 +11,10 @@ interface StartRunOptions {
10
11
  runId?: string | undefined;
11
12
  mintRunId: () => string;
12
13
  mode: "dry-run" | "live";
13
- lab?: RunLabProvenance | undefined;
14
+ study?: RunStudyProvenance | undefined;
14
15
  /** review.md for the published bundle. */
15
16
  renderReview: (bundle: RunBundle) => string;
16
- /** Used by `FinishedRun.renderObserver`; `render` is the `LabDeps.renderObserver` seam. */
17
+ /** Used by `FinishedRun.renderObserver`; `render` is the `StudyDeps.renderObserver` seam. */
17
18
  observer?: {
18
19
  open: boolean;
19
20
  render?: typeof renderObserver | undefined;
@@ -25,8 +26,8 @@ interface Run {
25
26
  readonly runId: string;
26
27
  readonly createdAt: string;
27
28
  readonly mode: "dry-run" | "live";
28
- /** The manifest the run came from (#455); bundleHead copies it into the bundle. */
29
- readonly lab?: RunLabProvenance;
29
+ /** The manifest the run came from; bundleHead copies it into the bundle. */
30
+ readonly study?: RunStudyProvenance;
30
31
  /** Routes write their evidence files through these and hand them to participants. */
31
32
  readonly paths: PreparedRunArtifactPaths;
32
33
  /**
package/dist/run/run.js CHANGED
@@ -9,7 +9,7 @@ import {} from "./results.js";
9
9
  import { createRunArtifactPaths, validatePreparedRunArtifactPaths, } from "./paths.js";
10
10
  import { registerActiveRun } from "./active-runs.js";
11
11
  import { writeContainedOutputFile, writePreparedRunLatestPointer } from "./contained-output.js";
12
- import { beginRunStatus, runStatusOutcome, } from "./status.js";
12
+ import { beginRunStatus, runStatusOutcome } from "./status.js";
13
13
  /** An entry point called in a state that does not admit it. */
14
14
  class RunLifecycleError extends Error {
15
15
  name = "RunLifecycleError";
@@ -88,7 +88,7 @@ export async function runScope(fn) {
88
88
  const created = await createRunArtifactPaths(options.cwd, runId);
89
89
  if (!created.ok)
90
90
  return created;
91
- // beginRunStatus reads only the mode and the lab provenance from the run's options.
91
+ // beginRunStatus reads only the mode and the study provenance from the run's options.
92
92
  status = beginRunStatus(created.paths, { ...options, runId });
93
93
  // Registered before the first write lands: a signal while it is still settling reaches
94
94
  // the handle, whose interrupt queues behind that write.
@@ -156,7 +156,7 @@ export async function runScope(fn) {
156
156
  runId,
157
157
  createdAt,
158
158
  mode: options.mode,
159
- ...(options.lab === undefined ? {} : { lab: options.lab }),
159
+ ...(options.study === undefined ? {} : { study: options.study }),
160
160
  paths,
161
161
  writeSnapshot(bundle) {
162
162
  if (closed)
@@ -9,7 +9,7 @@ export interface SandboxReceipt {
9
9
  /** Who allocated the sandbox. Receipts written before this field existed have none. */
10
10
  provider?: SandboxProviderId;
11
11
  sandboxId: string;
12
- /** The create-time sandbox TTL (ms), when known — how long the server-side backstop runs. */
12
+ /** The create-time sandbox TTL (ms), when known: how long the server-side backstop runs. */
13
13
  timeoutMs?: number;
14
14
  }
15
15
  /**
@@ -22,7 +22,7 @@ export interface ParsedSandboxReceipt extends Omit<SandboxReceipt, "provider"> {
22
22
  }
23
23
  /**
24
24
  * Append one receipt. Best-effort by design: the receipt exists to protect the run, so a failed
25
- * receipt write must never fail the participant — the only cost of a miss is that `reclaim` cannot see
25
+ * receipt write must never fail the participant. The only cost of a miss is that `reclaim` cannot see
26
26
  * this id and the TTL backstop covers it instead. Containment is the same prepare step every
27
27
  * artifact write uses; append (not atomic-replace) keeps racing participants' receipts intact.
28
28
  */
@@ -6,7 +6,7 @@ import { prepareContainedOutputFile } from "./contained-output.js";
6
6
  export const SANDBOX_RECEIPTS_ARTIFACT = "sandbox-receipts.ndjson";
7
7
  /**
8
8
  * Append one receipt. Best-effort by design: the receipt exists to protect the run, so a failed
9
- * receipt write must never fail the participant — the only cost of a miss is that `reclaim` cannot see
9
+ * receipt write must never fail the participant. The only cost of a miss is that `reclaim` cannot see
10
10
  * this id and the TTL backstop covers it instead. Containment is the same prepare step every
11
11
  * artifact write uses; append (not atomic-replace) keeps racing participants' receipts intact.
12
12
  */
@@ -16,7 +16,7 @@ export async function appendSandboxReceipt(root, receipt) {
16
16
  await appendFile(filePath, `${JSON.stringify(receipt)}\n`, "utf8");
17
17
  }
18
18
  catch {
19
- // Swallowed on purpose — see the contract above.
19
+ // Swallowed on purpose; see the contract above.
20
20
  }
21
21
  }
22
22
  /** Parse a receipts file leniently: a torn final line (crash mid-append) drops, valid lines keep. */
@@ -42,7 +42,7 @@ export function parseSandboxReceipts(text) {
42
42
  }
43
43
  }
44
44
  catch {
45
- // torn line — skip
45
+ // A torn line: skip it.
46
46
  }
47
47
  }
48
48
  return receipts;