humanish 0.108.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 (455) hide show
  1. package/ARCHITECTURE.md +58 -59
  2. package/CHANGELOG.md +13 -0
  3. package/CONTEXT.md +44 -44
  4. package/README.md +3 -3
  5. package/TELEMETRY.md +2 -2
  6. package/dist/actors/codex/app-server-trace.js +2 -1
  7. package/dist/actors/codex/restricted-participant.js +12 -12
  8. package/dist/actors/codex/restricted-session.d.ts +2 -2
  9. package/dist/actors/computer-use/actor.d.ts +6 -6
  10. package/dist/actors/computer-use/actor.js +2 -2
  11. package/dist/actors/computer-use/admission-limit.d.ts +2 -2
  12. package/dist/actors/computer-use/admission-limit.js +3 -3
  13. package/dist/actors/computer-use/executor-error.d.ts +2 -2
  14. package/dist/actors/computer-use/executor-error.js +3 -3
  15. package/dist/actors/computer-use/loop/actions.js +5 -5
  16. package/dist/actors/computer-use/loop/debrief.js +2 -2
  17. package/dist/actors/computer-use/loop/ending.d.ts +1 -1
  18. package/dist/actors/computer-use/loop/ending.js +12 -11
  19. package/dist/actors/computer-use/loop/observation.js +6 -5
  20. package/dist/actors/computer-use/loop/provider-call.js +11 -11
  21. package/dist/actors/computer-use/loop/session.d.ts +4 -4
  22. package/dist/actors/computer-use/loop/session.js +2 -2
  23. package/dist/actors/computer-use/loop/trace.js +3 -2
  24. package/dist/actors/computer-use/loop/types.d.ts +24 -24
  25. package/dist/actors/computer-use/loop/usage.d.ts +2 -2
  26. package/dist/actors/computer-use/loop.d.ts +6 -1
  27. package/dist/actors/computer-use/loop.js +26 -4
  28. package/dist/actors/computer-use/openai-provider.d.ts +2 -2
  29. package/dist/actors/computer-use/openai-provider.js +8 -8
  30. package/dist/actors/computer-use/provider-error.d.ts +4 -4
  31. package/dist/actors/computer-use/provider-error.js +6 -6
  32. package/dist/actors/contract.d.ts +4 -4
  33. package/dist/actors/contract.js +1 -1
  34. package/dist/actors/local-agent/claude-session.js +3 -3
  35. package/dist/actors/local-agent/cli.d.ts +1 -1
  36. package/dist/actors/local-agent/cli.js +1 -1
  37. package/dist/actors/reasoning-effort.js +3 -3
  38. package/dist/actors/registry.d.ts +2 -2
  39. package/dist/actors/registry.js +3 -3
  40. package/dist/actors/scripted-browser/actor.d.ts +2 -2
  41. package/dist/actors/scripted-browser/actor.js +1 -1
  42. package/dist/analysis/automatic-completion.d.ts +7 -7
  43. package/dist/analysis/automatic-completion.js +1 -1
  44. package/dist/analysis/automatic-config.d.ts +6 -6
  45. package/dist/analysis/automatic-config.js +1 -1
  46. package/dist/analysis/execute.d.ts +1 -1
  47. package/dist/analysis/execute.js +1 -1
  48. package/dist/analysis/types.d.ts +6 -0
  49. package/dist/browser-control/client.js +16 -16
  50. package/dist/browser-control/dispatcher.js +4 -4
  51. package/dist/browser-control/protocol.js +14 -14
  52. package/dist/browser-control/recording-transfer.js +4 -4
  53. package/dist/browser-control/transport.js +7 -7
  54. package/dist/cli/commands/analysis-signals.d.ts +2 -2
  55. package/dist/cli/commands/comms.js +14 -22
  56. package/dist/cli/commands/observe.d.ts +0 -1
  57. package/dist/cli/commands/observe.js +0 -15
  58. package/dist/cli/commands/run-command.d.ts +2 -2
  59. package/dist/cli/commands/run-command.js +3 -3
  60. package/dist/cli/commands/runs.js +3 -5
  61. package/dist/cli/commands/setup.js +5 -7
  62. package/dist/cli/commands/study-format.d.ts +9 -0
  63. package/dist/cli/commands/{lab-format.js → study-format.js} +5 -5
  64. package/dist/cli/commands/{lab-route-computer-use.d.ts → study-route-computer-use.d.ts} +6 -6
  65. package/dist/cli/commands/{lab-route-computer-use.js → study-route-computer-use.js} +12 -12
  66. package/dist/cli/commands/{lab-route-open.d.ts → study-route-open.d.ts} +4 -4
  67. package/dist/cli/commands/{lab-route-open.js → study-route-open.js} +2 -2
  68. package/dist/cli/commands/{lab-route-preview.d.ts → study-route-preview.d.ts} +7 -7
  69. package/dist/cli/commands/{lab-route-preview.js → study-route-preview.js} +3 -3
  70. package/dist/cli/commands/study-route-run.d.ts +19 -0
  71. package/dist/cli/commands/{lab-route-run.js → study-route-run.js} +6 -6
  72. package/dist/cli/commands/study-route-scripted.d.ts +17 -0
  73. package/dist/cli/commands/{lab-route-scripted.js → study-route-scripted.js} +4 -4
  74. package/dist/cli/commands/{lab-route-shared-world.d.ts → study-route-shared-world.d.ts} +5 -5
  75. package/dist/cli/commands/{lab-route-shared-world.js → study-route-shared-world.js} +7 -7
  76. package/dist/cli/commands/study-route-terminal.d.ts +17 -0
  77. package/dist/cli/commands/{lab-route-terminal.js → study-route-terminal.js} +4 -4
  78. package/dist/cli/commands/study-run.d.ts +9 -0
  79. package/dist/cli/commands/{lab-run.js → study-run.js} +34 -34
  80. package/dist/cli/commands/{lab-scorer.d.ts → study-scorer.d.ts} +5 -5
  81. package/dist/cli/commands/{lab-scorer.js → study-scorer.js} +1 -1
  82. package/dist/cli/commands/study.js +13 -49
  83. package/dist/cli/commands/tui.js +12 -12
  84. package/dist/cli/commands/watch.js +30 -65
  85. package/dist/cli/deprecations.d.ts +1 -13
  86. package/dist/cli/deprecations.js +0 -30
  87. package/dist/cli/doctor.d.ts +3 -3
  88. package/dist/cli/doctor.js +16 -16
  89. package/dist/cli/first-run-path.d.ts +4 -4
  90. package/dist/cli/first-run-path.js +7 -7
  91. package/dist/cli/io.d.ts +3 -3
  92. package/dist/cli/io.js +2 -2
  93. package/dist/cli/observer-follow.d.ts +2 -2
  94. package/dist/cli/observer-follow.js +2 -2
  95. package/dist/cli/orientation.d.ts +4 -4
  96. package/dist/cli/orientation.js +58 -20
  97. package/dist/cli/program.js +3 -4
  98. package/dist/cli/telemetry.d.ts +1 -1
  99. package/dist/cli/telemetry.js +14 -20
  100. package/dist/comms/catch-host.d.ts +1 -1
  101. package/dist/comms/catch-host.js +3 -3
  102. package/dist/comms/connections.d.ts +1 -1
  103. package/dist/comms/connections.js +2 -2
  104. package/dist/comms/external-evidence.d.ts +5 -5
  105. package/dist/comms/external-evidence.js +4 -3
  106. package/dist/comms/fake-inbox.d.ts +2 -2
  107. package/dist/comms/fake-inbox.js +2 -2
  108. package/dist/comms/receiving-runtime.d.ts +4 -4
  109. package/dist/comms/sandbox-catch.d.ts +2 -2
  110. package/dist/comms/sandbox-catch.js +2 -2
  111. package/dist/comms/setup.d.ts +2 -2
  112. package/dist/comms/setup.js +29 -32
  113. package/dist/feedback/draft.js +2 -2
  114. package/dist/feedback/export.js +3 -2
  115. package/dist/feedback/proof.d.ts +1 -1
  116. package/dist/feedback/proof.js +2 -2
  117. package/dist/guest/bootstrap.js +6 -6
  118. package/dist/guest/browser-tools.js +8 -8
  119. package/dist/guest/chromium-text.js +17 -17
  120. package/dist/guest/desktop-executor.d.ts +2 -2
  121. package/dist/guest/desktop-executor.js +20 -20
  122. package/dist/guest/desktop-keys.js +4 -4
  123. package/dist/guest/desktop-media.d.ts +2 -2
  124. package/dist/guest/desktop-media.js +16 -16
  125. package/dist/guest/desktop-native.js +10 -10
  126. package/dist/guest/runtime-desktop.js +2 -2
  127. package/dist/guest/runtime-processes.d.ts +2 -2
  128. package/dist/guest/runtime-processes.js +2 -2
  129. package/dist/guest/runtime.js +5 -5
  130. package/dist/index.d.ts +13 -15
  131. package/dist/index.js +6 -8
  132. package/dist/observer/artifact.d.ts +1 -1
  133. package/dist/observer/artifact.js +1 -1
  134. package/dist/observer/data.d.ts +1 -1
  135. package/dist/observer/library.d.ts +2 -0
  136. package/dist/observer/library.js +4 -1
  137. package/dist/observer/render.js +7 -1
  138. package/dist/observer/run-routes.d.ts +1 -0
  139. package/dist/observer/run-routes.js +37 -12
  140. package/dist/observer/serve.d.ts +1 -1
  141. package/dist/observer-app.html +1 -1
  142. package/dist/routes/computer-use/bundle-parts.js +3 -2
  143. package/dist/routes/computer-use/bundle.d.ts +2 -2
  144. package/dist/routes/computer-use/bundle.js +7 -6
  145. package/dist/routes/computer-use/e2b-desktop/comms.d.ts +5 -5
  146. package/dist/routes/computer-use/e2b-desktop/comms.js +5 -4
  147. package/dist/routes/computer-use/e2b-desktop/fidelity.d.ts +1 -1
  148. package/dist/routes/computer-use/e2b-desktop/prepare.d.ts +1 -1
  149. package/dist/routes/computer-use/e2b-desktop/prepare.js +3 -3
  150. package/dist/routes/computer-use/e2b-desktop/start.js +3 -4
  151. package/dist/routes/computer-use/e2b-desktop/state.d.ts +2 -2
  152. package/dist/routes/computer-use/e2b-desktop/teardown.js +2 -3
  153. package/dist/routes/computer-use/external-comms.d.ts +3 -3
  154. package/dist/routes/computer-use/fanout-bundle.js +11 -10
  155. package/dist/routes/computer-use/fanout-records.js +2 -2
  156. package/dist/routes/computer-use/live-flush.d.ts +3 -3
  157. package/dist/routes/computer-use/live-phase.d.ts +2 -3
  158. package/dist/routes/computer-use/live-phase.js +3 -3
  159. package/dist/routes/computer-use/local-tree-pack.d.ts +5 -5
  160. package/dist/routes/computer-use/local-tree-pack.js +1 -1
  161. package/dist/routes/computer-use/local-vm.d.ts +8 -8
  162. package/dist/routes/computer-use/local-vm.js +2 -2
  163. package/dist/routes/computer-use/participant-desktop.d.ts +3 -3
  164. package/dist/routes/computer-use/participant-desktop.js +1 -1
  165. package/dist/routes/computer-use/participant-execution.js +1 -1
  166. package/dist/routes/computer-use/participant-model.js +3 -3
  167. package/dist/routes/computer-use/participant-prompt.d.ts +5 -5
  168. package/dist/routes/computer-use/participant-prompt.js +3 -3
  169. package/dist/routes/computer-use/participant-runs.d.ts +10 -10
  170. package/dist/routes/computer-use/participant-runs.js +14 -13
  171. package/dist/routes/computer-use/plan.d.ts +12 -12
  172. package/dist/routes/computer-use/plan.js +24 -24
  173. package/dist/routes/computer-use/preflight.d.ts +5 -5
  174. package/dist/routes/computer-use/preflight.js +5 -5
  175. package/dist/routes/computer-use/rerun-selection.d.ts +1 -1
  176. package/dist/routes/computer-use/rerun-selection.js +3 -2
  177. package/dist/routes/computer-use/result.d.ts +4 -4
  178. package/dist/routes/computer-use/result.js +13 -12
  179. package/dist/routes/computer-use/route.d.ts +12 -12
  180. package/dist/routes/computer-use/route.js +19 -19
  181. package/dist/routes/computer-use/self-report.js +1 -1
  182. package/dist/routes/computer-use/setup.d.ts +22 -22
  183. package/dist/routes/computer-use/setup.js +15 -15
  184. package/dist/routes/computer-use/single-bundle.d.ts +4 -4
  185. package/dist/routes/computer-use/single-bundle.js +14 -13
  186. package/dist/routes/computer-use/subject-projection.d.ts +3 -3
  187. package/dist/routes/computer-use/types.d.ts +34 -34
  188. package/dist/routes/computer-use/types.js +3 -3
  189. package/dist/routes/preview.d.ts +6 -6
  190. package/dist/routes/preview.js +5 -5
  191. package/dist/routes/scripted/bundle.d.ts +6 -6
  192. package/dist/routes/scripted/bundle.js +10 -9
  193. package/dist/routes/scripted/plan.d.ts +7 -7
  194. package/dist/routes/scripted/plan.js +6 -6
  195. package/dist/routes/scripted/result.d.ts +3 -3
  196. package/dist/routes/scripted/result.js +9 -9
  197. package/dist/routes/scripted/route.d.ts +9 -9
  198. package/dist/routes/scripted/route.js +11 -11
  199. package/dist/routes/scripted/scenario.d.ts +1 -1
  200. package/dist/routes/scripted/scenario.js +3 -3
  201. package/dist/routes/scripted/setup.d.ts +6 -6
  202. package/dist/routes/scripted/setup.js +4 -4
  203. package/dist/routes/scripted/subject.d.ts +5 -5
  204. package/dist/routes/scripted/subject.js +3 -3
  205. package/dist/routes/scripted/surface-records.d.ts +1 -1
  206. package/dist/routes/scripted/surface-records.js +2 -2
  207. package/dist/routes/scripted/surface-sessions.d.ts +3 -3
  208. package/dist/routes/scripted/types.d.ts +17 -17
  209. package/dist/routes/scripted/types.js +1 -1
  210. package/dist/routes/shared-world/bundle-records.js +3 -3
  211. package/dist/routes/shared-world/bundle.js +15 -14
  212. package/dist/routes/shared-world/checkpoints.d.ts +3 -3
  213. package/dist/routes/shared-world/checkpoints.js +1 -1
  214. package/dist/routes/shared-world/comms.d.ts +9 -9
  215. package/dist/routes/shared-world/comms.js +6 -5
  216. package/dist/routes/shared-world/participant-specs.d.ts +3 -3
  217. package/dist/routes/shared-world/participant-specs.js +7 -7
  218. package/dist/routes/shared-world/plan.d.ts +9 -9
  219. package/dist/routes/shared-world/plan.js +9 -9
  220. package/dist/routes/shared-world/provisioned.d.ts +8 -8
  221. package/dist/routes/shared-world/provisioned.js +4 -4
  222. package/dist/routes/shared-world/result.d.ts +6 -6
  223. package/dist/routes/shared-world/result.js +11 -10
  224. package/dist/routes/shared-world/route.d.ts +11 -11
  225. package/dist/routes/shared-world/route.js +19 -19
  226. package/dist/routes/shared-world/setup.d.ts +13 -13
  227. package/dist/routes/shared-world/setup.js +19 -19
  228. package/dist/routes/shared-world/types.d.ts +27 -27
  229. package/dist/routes/terminal/adapter.d.ts +2 -2
  230. package/dist/routes/terminal/adapter.js +4 -4
  231. package/dist/routes/terminal/bundle.d.ts +11 -11
  232. package/dist/routes/terminal/bundle.js +12 -12
  233. package/dist/routes/terminal/credentials.d.ts +4 -4
  234. package/dist/routes/terminal/credentials.js +5 -5
  235. package/dist/routes/terminal/dry-run.d.ts +4 -4
  236. package/dist/routes/terminal/dry-run.js +9 -9
  237. package/dist/routes/terminal/ledger.d.ts +2 -2
  238. package/dist/routes/terminal/lifetime.d.ts +1 -1
  239. package/dist/routes/terminal/lifetime.js +1 -1
  240. package/dist/routes/terminal/live-finish.d.ts +2 -2
  241. package/dist/routes/terminal/live-finish.js +7 -7
  242. package/dist/routes/terminal/live-sandbox.d.ts +2 -2
  243. package/dist/routes/terminal/live-sandbox.js +3 -2
  244. package/dist/routes/terminal/participant-text.js +2 -1
  245. package/dist/routes/terminal/persona.d.ts +2 -2
  246. package/dist/routes/terminal/persona.js +2 -2
  247. package/dist/routes/terminal/plan.d.ts +7 -7
  248. package/dist/routes/terminal/plan.js +5 -5
  249. package/dist/routes/terminal/result.d.ts +5 -5
  250. package/dist/routes/terminal/result.js +7 -7
  251. package/dist/routes/terminal/route.d.ts +9 -9
  252. package/dist/routes/terminal/route.js +14 -14
  253. package/dist/routes/terminal/session.d.ts +5 -5
  254. package/dist/routes/terminal/session.js +7 -7
  255. package/dist/routes/terminal/trace.d.ts +2 -2
  256. package/dist/routes/terminal/types.d.ts +24 -24
  257. package/dist/routes/terminal/types.js +2 -2
  258. package/dist/run/bundle.d.ts +7 -7
  259. package/dist/run/bundle.js +2 -2
  260. package/dist/run/costs.d.ts +23 -0
  261. package/dist/run/costs.js +72 -43
  262. package/dist/run/dry-run-inputs.d.ts +1 -1
  263. package/dist/run/dry-run-inputs.js +1 -1
  264. package/dist/run/dry-run.js +2 -2
  265. package/dist/run/outcomes.d.ts +1 -1
  266. package/dist/run/participant.d.ts +1 -1
  267. package/dist/run/preflight-receipts.js +1 -1
  268. package/dist/run/pricing.js +2 -2
  269. package/dist/run/projection.d.ts +32 -32
  270. package/dist/run/projection.js +44 -44
  271. package/dist/run/reclaim.d.ts +1 -1
  272. package/dist/run/reclaim.js +1 -1
  273. package/dist/run/results.d.ts +2 -2
  274. package/dist/run/run-cost.d.ts +53 -0
  275. package/dist/run/run-cost.js +105 -0
  276. package/dist/run/run-index-analysis.d.ts +15 -0
  277. package/dist/run/run-index-analysis.js +77 -0
  278. package/dist/run/run-index.d.ts +11 -1
  279. package/dist/run/run-index.js +63 -49
  280. package/dist/run/run.d.ts +3 -3
  281. package/dist/run/run.js +2 -2
  282. package/dist/run/shared-world-evidence.d.ts +1 -1
  283. package/dist/run/shared-world-shape.js +1 -1
  284. package/dist/run/stats.d.ts +3 -3
  285. package/dist/run/stats.js +14 -14
  286. package/dist/run/status.d.ts +10 -2
  287. package/dist/run/status.js +6 -3
  288. package/dist/run/streams.d.ts +2 -2
  289. package/dist/run/study-provenance.d.ts +4 -2
  290. package/dist/run/study-provenance.js +7 -4
  291. package/dist/run/study-result.d.ts +0 -5
  292. package/dist/run/study-result.js +1 -1
  293. package/dist/run-study.d.ts +112 -0
  294. package/dist/{run-lab.js → run-study.js} +52 -45
  295. package/dist/{lab → study}/adapter-extension.d.ts +8 -20
  296. package/dist/{lab → study}/adapter-extension.js +2 -14
  297. package/dist/{lab → study}/adapter-scorer-loader.d.ts +10 -10
  298. package/dist/{lab → study}/adapter-scorer-loader.js +3 -3
  299. package/dist/study/composition-rules.d.ts +7 -0
  300. package/dist/{lab → study}/composition-rules.js +12 -12
  301. package/dist/study/config.d.ts +15 -0
  302. package/dist/{lab → study}/config.js +37 -20
  303. package/dist/study/convert.d.ts +1 -1
  304. package/dist/study/convert.js +15 -15
  305. package/dist/{lab → study}/device-presets.d.ts +2 -2
  306. package/dist/{lab → study}/discover.d.ts +29 -23
  307. package/dist/{lab → study}/discover.js +97 -118
  308. package/dist/{lab → study}/doctor.d.ts +11 -11
  309. package/dist/{lab → study}/doctor.js +18 -18
  310. package/dist/study/files.d.ts +2 -2
  311. package/dist/study/files.js +6 -5
  312. package/dist/{lab → study}/init-templates.d.ts +2 -2
  313. package/dist/{lab → study}/init-templates.js +16 -11
  314. package/dist/{lab → study}/init.d.ts +1 -1
  315. package/dist/{lab → study}/init.js +7 -4
  316. package/dist/{lab → study}/keys.d.ts +2 -2
  317. package/dist/{lab → study}/keys.js +10 -10
  318. package/dist/study/migrate.d.ts +1 -1
  319. package/dist/{lab → study}/parse/actors.d.ts +5 -5
  320. package/dist/{lab → study}/parse/actors.js +5 -5
  321. package/dist/study/parse/comms.d.ts +12 -0
  322. package/dist/study/parse/execution.d.ts +19 -0
  323. package/dist/{lab → study}/parse/study-v3.d.ts +3 -5
  324. package/dist/{lab → study}/parse/study-v3.js +3 -3
  325. package/dist/{lab → study}/parse/subject-state.d.ts +8 -8
  326. package/dist/{lab → study}/parse/subject-state.js +4 -4
  327. package/dist/{lab → study}/parse/subject.d.ts +3 -3
  328. package/dist/{lab → study}/parse/subject.js +8 -8
  329. package/dist/{lab → study}/parse/values.d.ts +2 -2
  330. package/dist/{lab → study}/persona-resolve.d.ts +4 -4
  331. package/dist/{lab → study}/persona-resolve.js +2 -2
  332. package/dist/{lab → study}/plan-base.d.ts +7 -7
  333. package/dist/{lab → study}/plan-base.js +1 -1
  334. package/dist/{lab → study}/plan-participants.d.ts +10 -10
  335. package/dist/{lab → study}/plan-participants.js +4 -4
  336. package/dist/{lab → study}/plan-types.d.ts +28 -28
  337. package/dist/{lab → study}/plan-types.js +2 -2
  338. package/dist/study/plan.d.ts +13 -0
  339. package/dist/{lab → study}/plan.js +20 -20
  340. package/dist/study/preflight-probes.d.ts +3 -0
  341. package/dist/{lab → study}/preflight-probes.js +9 -8
  342. package/dist/study/preflight-result.d.ts +8 -0
  343. package/dist/{lab → study}/preflight-result.js +3 -3
  344. package/dist/{lab → study}/preflight.d.ts +31 -31
  345. package/dist/{lab → study}/preflight.js +8 -8
  346. package/dist/{lab → study}/requirements.d.ts +3 -3
  347. package/dist/{lab → study}/requirements.js +1 -1
  348. package/dist/study/route-inputs.d.ts +28 -0
  349. package/dist/{lab → study}/route-inputs.js +1 -1
  350. package/dist/{lab → study}/routing.d.ts +12 -12
  351. package/dist/{lab/run-lab-events.d.ts → study/run-study-events.d.ts} +10 -10
  352. package/dist/{lab/run-lab-events.js → study/run-study-events.js} +3 -3
  353. package/dist/{lab/run-lab-homes.d.ts → study/run-study-homes.d.ts} +8 -17
  354. package/dist/study/run-study-homes.js +3 -0
  355. package/dist/study/run-study-options.d.ts +28 -0
  356. package/dist/{lab/run-lab-options.js → study/run-study-options.js} +13 -12
  357. package/dist/{lab/lab-deps.d.ts → study/study-deps.d.ts} +2 -2
  358. package/dist/{lab/lab-deps.js → study/study-deps.js} +2 -2
  359. package/dist/{lab → study}/summary.d.ts +10 -10
  360. package/dist/{lab → study}/summary.js +15 -15
  361. package/dist/{lab → study}/tasks.d.ts +3 -3
  362. package/dist/{lab → study}/tasks.js +1 -1
  363. package/dist/{lab → study}/types.d.ts +104 -104
  364. package/dist/{lab → study}/types.js +1 -1
  365. package/dist/{lab → study}/validation.d.ts +19 -19
  366. package/dist/{lab → study}/validation.js +13 -13
  367. package/dist/{lab → study}/warnings.d.ts +4 -4
  368. package/dist/{lab → study}/warnings.js +1 -1
  369. package/dist/subject/clone.d.ts +6 -6
  370. package/dist/subject/clone.js +2 -2
  371. package/dist/subject/local-tree-archive.d.ts +2 -2
  372. package/dist/subject/local-tree-archive.js +3 -3
  373. package/dist/subject/local-tree.d.ts +3 -3
  374. package/dist/subject/runtime.js +2 -2
  375. package/dist/subject/serve.d.ts +4 -4
  376. package/dist/subject/state.d.ts +3 -3
  377. package/dist/subject/state.js +1 -1
  378. package/dist/subject/steps.d.ts +1 -1
  379. package/dist/subject/steps.js +1 -1
  380. package/dist/substrates/desktop-session.js +2 -2
  381. package/dist/substrates/detached.d.ts +1 -1
  382. package/dist/substrates/e2b/desktop-browser.d.ts +4 -4
  383. package/dist/substrates/e2b/desktop-browser.js +1 -1
  384. package/dist/substrates/e2b/desktop-cdp.d.ts +1 -1
  385. package/dist/substrates/e2b/desktop-cdp.js +1 -1
  386. package/dist/substrates/e2b/desktop-executor.d.ts +1 -1
  387. package/dist/substrates/e2b/desktop-executor.js +12 -12
  388. package/dist/substrates/e2b/desktop-geometry.d.ts +1 -1
  389. package/dist/substrates/e2b/desktop-geometry.js +1 -1
  390. package/dist/substrates/e2b/desktop-media.d.ts +3 -3
  391. package/dist/substrates/e2b/lifetime.js +1 -1
  392. package/dist/substrates/e2b/sandbox.d.ts +3 -3
  393. package/dist/substrates/e2b/sandbox.js +1 -1
  394. package/dist/substrates/e2b/sdk.d.ts +1 -1
  395. package/dist/substrates/e2b/sdk.js +1 -1
  396. package/dist/substrates/local/runtime-config.d.ts +4 -4
  397. package/dist/substrates/local/runtime-config.js +4 -4
  398. package/dist/tui/contract.d.ts +8 -8
  399. package/dist/tui/contract.js +2 -2
  400. package/dist/tui/launch.d.ts +3 -3
  401. package/dist/tui/launch.js +22 -16
  402. package/dist/tui-app.js +139 -139
  403. package/dist/verify/subject.d.ts +1 -1
  404. package/dist/verify/subject.js +1 -1
  405. package/dist/verify/verify.js +2 -1
  406. package/docs/architecture/actor-contract.md +5 -5
  407. package/docs/architecture/browser-control.md +1 -1
  408. package/docs/architecture/external-public-shared-world.md +8 -7
  409. package/docs/architecture/github-feedback-loop.md +1 -1
  410. package/docs/architecture/task-protocol-support.md +1 -1
  411. package/docs/architecture/terminal-product-route.md +18 -18
  412. package/docs/contracts/adapter-fixtures.md +2 -2
  413. package/docs/contracts/errors.md +8 -8
  414. package/docs/contracts/run-bundle.md +1 -4
  415. package/docs/contracts/schemas.md +61 -42
  416. package/docs/contracts/study-analysis.md +4 -1
  417. package/docs/contracts/study-costs.md +17 -2
  418. package/examples/README.md +1 -1
  419. package/examples/scorer/scorer.mjs +3 -3
  420. package/package.json +1 -1
  421. package/skills/humanish/SKILL.md +8 -6
  422. package/skills/humanish/agents/openai.yaml +1 -1
  423. package/dist/cli/commands/lab-format.d.ts +0 -9
  424. package/dist/cli/commands/lab-route-run.d.ts +0 -19
  425. package/dist/cli/commands/lab-route-scripted.d.ts +0 -17
  426. package/dist/cli/commands/lab-route-terminal.d.ts +0 -17
  427. package/dist/cli/commands/lab-run.d.ts +0 -9
  428. package/dist/lab/composition-rules.d.ts +0 -7
  429. package/dist/lab/config.d.ts +0 -7
  430. package/dist/lab/deprecated-fields.d.ts +0 -10
  431. package/dist/lab/deprecated-fields.js +0 -24
  432. package/dist/lab/parse/comms.d.ts +0 -12
  433. package/dist/lab/parse/execution.d.ts +0 -19
  434. package/dist/lab/plan.d.ts +0 -13
  435. package/dist/lab/preflight-probes.d.ts +0 -3
  436. package/dist/lab/preflight-result.d.ts +0 -8
  437. package/dist/lab/route-inputs.d.ts +0 -28
  438. package/dist/lab/run-lab-homes.js +0 -7
  439. package/dist/lab/run-lab-options.d.ts +0 -28
  440. package/dist/library-aliases.d.ts +0 -56
  441. package/dist/library-aliases.js +0 -22
  442. package/dist/run-lab.d.ts +0 -112
  443. /package/dist/{lab → study}/device-presets.js +0 -0
  444. /package/dist/{lab → study}/init-paths.d.ts +0 -0
  445. /package/dist/{lab → study}/init-paths.js +0 -0
  446. /package/dist/{lab → study}/init-plan.d.ts +0 -0
  447. /package/dist/{lab → study}/init-plan.js +0 -0
  448. /package/dist/{lab → study}/parse/comms.js +0 -0
  449. /package/dist/{lab → study}/parse/execution.js +0 -0
  450. /package/dist/{lab → study}/parse/values.js +0 -0
  451. /package/dist/{lab → study}/participant-assignment.d.ts +0 -0
  452. /package/dist/{lab → study}/participant-assignment.js +0 -0
  453. /package/dist/{lab → study}/persona.d.ts +0 -0
  454. /package/dist/{lab → study}/persona.js +0 -0
  455. /package/dist/{lab → study}/routing.js +0 -0
@@ -1,3 +1,4 @@
1
+ import { type PreparedRunArtifactPaths } from "./paths.js";
1
2
  import type { RunIndexEntry } from "./run-index.js";
2
3
  /** Additive accounting for retained attempts. Null means no estimate, never an invented zero. */
3
4
  export interface CostTotals {
@@ -25,3 +26,25 @@ export declare function emptyCostTotals(): CostTotals;
25
26
  export declare function addCostTotals(into: CostTotals, next: CostTotals): void;
26
27
  /** A read-only, bounded accounting pass. Never validates findings, dispatches, repairs or writes. */
27
28
  export declare function readCostTotals(cwd: string, entry: RunIndexEntry): Promise<CostRow>;
29
+ /** One run's analysis history, every distinct attempt counted once. */
30
+ export interface AnalysisAccounting {
31
+ attempts: number;
32
+ /** Attempts that sent a request and recorded its usage. */
33
+ dispatched: number;
34
+ notDispatched: number;
35
+ /** Dispatched or possibly dispatched attempts without a complete price. */
36
+ unpriced: number;
37
+ /** A dispatch marker survives with no usable final accounting. */
38
+ unresolved: number;
39
+ /** The known estimates of the dispatched attempts; 0 when every attempt sent nothing. */
40
+ estimatedUsd: number | null;
41
+ /** Who billed the dispatched attempts. */
42
+ providers: Array<"openai" | "codex">;
43
+ /** History that could not be read whole; ANALYSIS_HISTORY_NOT_RECORDED when there is none. */
44
+ warnings: string[];
45
+ }
46
+ /**
47
+ * The single reader of a run's analysis spend. Stats totals and every surface that shows one
48
+ * run's cost read it, so they cannot disagree. Receipts are read without opening evidence.
49
+ */
50
+ export declare function readAnalysisAccounting(prepared: PreparedRunArtifactPaths): Promise<AnalysisAccounting>;
package/dist/run/costs.js CHANGED
@@ -87,49 +87,14 @@ export async function readCostTotals(cwd, entry) {
87
87
  costs.incompleteRunEstimates = 1;
88
88
  runWarnings.push("RUN_COST_COMPLETENESS_UNKNOWN");
89
89
  }
90
- const [history, automatic] = await Promise.all([
91
- readAnalysisAccountingRecords(prepared),
92
- readAutomaticAnalysisAccounting(prepared),
93
- ]);
94
- analysisWarnings.push(...history.warnings);
95
- const records = new Map(history.records.map((record) => [record.id, record]));
96
- if (automatic === "unknown")
97
- analysisWarnings.push("AUTOMATIC_ANALYSIS_ACCOUNTING_UNKNOWN");
98
- else if (automatic) {
99
- if (automatic.uncertain)
100
- analysisWarnings.push("AUTOMATIC_ANALYSIS_ACCOUNTING_UNKNOWN");
101
- const id = automatic.reused ? automatic.analysisId : automatic.attemptId;
102
- if (id && (automatic.started || automatic.analysisId !== null) && !records.has(id)) {
103
- records.set(id, { id, receipt: null, start: null, legacy: false });
104
- }
105
- }
106
- for (const record of records.values()) {
107
- costs.analysisAttempts += 1;
108
- if (record.legacy)
109
- analysisWarnings.push("ANALYSIS_LEGACY_REPORT_ACCOUNTING");
110
- const usage = record.receipt?.usage;
111
- if (!usage) {
112
- costs.analysisUnpricedAttempts += 1;
113
- costs.analysisUnresolvedAttempts += 1;
114
- continue;
115
- }
116
- if (!usage.dispatched) {
117
- costs.analysisNotDispatchedAttempts += 1;
118
- costs.analysisEstimatedUsd = sumKnown(costs.analysisEstimatedUsd, 0);
119
- }
120
- else {
121
- costs.analysisDispatchedAttempts += 1;
122
- if (isKnownUsd(usage.estimatedCostUsd)) {
123
- costs.analysisEstimatedUsd = sumKnown(costs.analysisEstimatedUsd, usage.estimatedCostUsd);
124
- }
125
- if (!isKnownUsd(usage.estimatedCostUsd) || !usage.usageComplete)
126
- costs.analysisUnpricedAttempts += 1;
127
- }
128
- }
129
- // A skipped/queued automatic job says nothing about historical manual requests.
130
- // Only final no-dispatch receipts contribute a supported zero to recorded attempts.
131
- if (records.size === 0)
132
- analysisWarnings.push("ANALYSIS_HISTORY_NOT_RECORDED");
90
+ const analysis = await readAnalysisAccounting(prepared);
91
+ analysisWarnings.push(...analysis.warnings);
92
+ costs.analysisAttempts = analysis.attempts;
93
+ costs.analysisDispatchedAttempts = analysis.dispatched;
94
+ costs.analysisNotDispatchedAttempts = analysis.notDispatched;
95
+ costs.analysisUnpricedAttempts = analysis.unpriced;
96
+ costs.analysisUnresolvedAttempts = analysis.unresolved;
97
+ costs.analysisEstimatedUsd = analysis.estimatedUsd;
133
98
  costs.analysisHistoryUncertainRuns = analysisWarnings.length > 0 ? 1 : 0;
134
99
  }
135
100
  catch {
@@ -144,3 +109,67 @@ export async function readCostTotals(cwd, entry) {
144
109
  warnings: [...new Set([...runWarnings, ...analysisWarnings])],
145
110
  };
146
111
  }
112
+ /**
113
+ * The single reader of a run's analysis spend. Stats totals and every surface that shows one
114
+ * run's cost read it, so they cannot disagree. Receipts are read without opening evidence.
115
+ */
116
+ export async function readAnalysisAccounting(prepared) {
117
+ const accounting = {
118
+ attempts: 0,
119
+ dispatched: 0,
120
+ notDispatched: 0,
121
+ unpriced: 0,
122
+ unresolved: 0,
123
+ estimatedUsd: null,
124
+ providers: [],
125
+ warnings: [],
126
+ };
127
+ const [history, automatic] = await Promise.all([
128
+ readAnalysisAccountingRecords(prepared),
129
+ readAutomaticAnalysisAccounting(prepared),
130
+ ]);
131
+ accounting.warnings.push(...history.warnings);
132
+ const records = new Map(history.records.map((record) => [record.id, record]));
133
+ if (automatic === "unknown")
134
+ accounting.warnings.push("AUTOMATIC_ANALYSIS_ACCOUNTING_UNKNOWN");
135
+ else if (automatic) {
136
+ if (automatic.uncertain)
137
+ accounting.warnings.push("AUTOMATIC_ANALYSIS_ACCOUNTING_UNKNOWN");
138
+ const id = automatic.reused ? automatic.analysisId : automatic.attemptId;
139
+ if (id && (automatic.started || automatic.analysisId !== null) && !records.has(id)) {
140
+ records.set(id, { id, receipt: null, start: null, legacy: false });
141
+ }
142
+ }
143
+ const providers = new Set();
144
+ for (const record of records.values()) {
145
+ accounting.attempts += 1;
146
+ if (record.legacy)
147
+ accounting.warnings.push("ANALYSIS_LEGACY_REPORT_ACCOUNTING");
148
+ const usage = record.receipt?.usage;
149
+ if (!usage) {
150
+ accounting.unpriced += 1;
151
+ accounting.unresolved += 1;
152
+ continue;
153
+ }
154
+ if (!usage.dispatched) {
155
+ accounting.notDispatched += 1;
156
+ accounting.estimatedUsd = sumKnown(accounting.estimatedUsd, 0);
157
+ continue;
158
+ }
159
+ accounting.dispatched += 1;
160
+ if (record.receipt)
161
+ providers.add(record.receipt.provider);
162
+ if (isKnownUsd(usage.estimatedCostUsd)) {
163
+ accounting.estimatedUsd = sumKnown(accounting.estimatedUsd, usage.estimatedCostUsd);
164
+ }
165
+ if (!isKnownUsd(usage.estimatedCostUsd) || !usage.usageComplete)
166
+ accounting.unpriced += 1;
167
+ }
168
+ // A skipped or queued automatic job says nothing about earlier manual requests. Only final
169
+ // no-dispatch receipts contribute a supported zero.
170
+ if (records.size === 0)
171
+ accounting.warnings.push("ANALYSIS_HISTORY_NOT_RECORDED");
172
+ accounting.providers = [...providers].sort();
173
+ accounting.warnings = [...new Set(accounting.warnings)];
174
+ return accounting;
175
+ }
@@ -1,4 +1,4 @@
1
- import { type ResolvedPersona } from "../lab/persona.js";
1
+ import { type ResolvedPersona } from "../study/persona.js";
2
2
  import type { PreparedSelectedOutputDirectory } from "./contained-output.js";
3
3
  import type { RunBundle } from "./bundle.js";
4
4
  export declare function loadDryRunInputs(projectRoot: PreparedSelectedOutputDirectory, humanishSource: "present" | "missing"): Promise<{
@@ -1,5 +1,5 @@
1
1
  import { parse as parseYaml } from "yaml";
2
- import { parseResolvedPersona } from "../lab/persona.js";
2
+ import { parseResolvedPersona } from "../study/persona.js";
3
3
  import { digestText } from "../evidence/redaction.js";
4
4
  import { readImplicitProjectFile } from "./project.js";
5
5
  import { escapeRegExp } from "./text.js";
@@ -40,7 +40,7 @@ async function runDryRunInScope(options, scope) {
40
40
  message: "--count must be a positive integer.",
41
41
  });
42
42
  }
43
- // Bind the physical project, as the lab routes do: a symlinked cwd retargeted mid-run cannot
43
+ // Bind the physical project, as the routes do: a symlinked cwd retargeted mid-run cannot
44
44
  // redirect source reads or run storage into another project.
45
45
  const physicalCwd = await realpath(requestedCwd);
46
46
  const projectRoot = await prepareSelectedOutputDirectory(path.dirname(physicalCwd), physicalCwd);
@@ -64,7 +64,7 @@ async function runDryRunInScope(options, scope) {
64
64
  runId: options.runId,
65
65
  mintRunId: () => `dryrun-${createdAt.replace(/[:.]/g, "-")}-${randomUUID().slice(0, 8)}`,
66
66
  mode: options.dryRun ? "dry-run" : "live",
67
- lab: options.lab,
67
+ study: options.study,
68
68
  renderReview: renderReviewMarkdown,
69
69
  // The run starts at the time its id and source were stamped with.
70
70
  now: () => Date.parse(createdAt),
@@ -1,6 +1,6 @@
1
1
  import { type ActorStatus } from "../actors/contract.js";
2
2
  import { type CuaGoalSource } from "../actors/goal-source.js";
3
- import type { TaskFunnel } from "../lab/tasks.js";
3
+ import type { TaskFunnel } from "../study/tasks.js";
4
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. */
@@ -1,5 +1,5 @@
1
1
  import type { ActorPersonaRef } from "../actors/contract.js";
2
- import type { Participant } from "../lab/plan-participants.js";
2
+ import type { Participant } from "../study/plan-participants.js";
3
3
  import type { RunParticipantAssignment } from "./streams.js";
4
4
  /**
5
5
  * A planned participant resolved for one run: the plan's record unchanged, plus what the route
@@ -1,4 +1,4 @@
1
- // Sandbox receipts for `humanish lab preflight`. A probe has no run directory, so it journals its
1
+ // Sandbox receipts for `humanish study check`. A probe has no run directory, so it journals its
2
2
  // sandbox under .humanish/preflight/<probe-id>/ before any work runs in it. A confirmed kill
3
3
  // removes the journal. A journal that stays means the probe's sandbox may still be running, and
4
4
  // `humanish reclaim --preflight` kills it by the recorded id once it is safe to.
@@ -67,7 +67,7 @@ export const MODEL_RATES = {
67
67
  // cyber = the Daybreak frontier tier.
68
68
  "gpt-5.6-sol": rateWithLongContextTier(4, 0.4, 5, 20, GPT56_SOL_PROMO_AS_OF),
69
69
  // "gpt-5.6" is OpenAI's own alias for gpt-5.6-sol (models index); priced identically so a
70
- // lab configured with the alias never reads as unpriced.
70
+ // study configured with the alias never reads as unpriced.
71
71
  "gpt-5.6": rateWithLongContextTier(4, 0.4, 5, 20, GPT56_SOL_PROMO_AS_OF),
72
72
  "gpt-5.6-terra": rateWithLongContextTier(2, 0.2, 2.5, 12),
73
73
  "gpt-5.6-luna": rateWithLongContextTier(0.2, 0.02, 0.25, 1.2),
@@ -79,7 +79,7 @@ export const MODEL_RATES = {
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
81
81
  // as the 5.6 family on the sheet: writes at 1.25x, >272K re-tiers at 2x input-side / 1.5x
82
- // output ($20 / $2 / $25 / $75 long-context columns). These rates cover explicit lab
82
+ // output ($20 / $2 / $25 / $75 long-context columns). These rates cover explicit study
83
83
  // model choices and the study-analysis default; the computer-use default is separate.
84
84
  "gpt-6-astra": rateWithLongContextTier(10, 1, 12.5, 50, GPT6_ASTRA_AS_OF, GPT6_ASTRA_SOURCE),
85
85
  };
@@ -1,32 +1,32 @@
1
1
  import type { RunIndexEntry } from "./run-index.js";
2
- /** One lab as the labs list shows it. */
3
- export interface LabRollup {
4
- labId: string;
5
- /** Total runs attributed to this lab. */
2
+ /** One study as the study list shows it. */
3
+ export interface StudyRollup {
4
+ studyId: string;
5
+ /** Total runs attributed to this study. */
6
6
  runs: number;
7
7
  /** Runs whose status record is fresh right now. */
8
8
  live: number;
9
- /** The newest run of this lab, whatever its state. */
9
+ /** The newest run of this study, whatever its state. */
10
10
  latest?: RunIndexEntry;
11
11
  /** Live runs, newest first; the labs list shows the first one inline. */
12
12
  liveRuns: RunIndexEntry[];
13
13
  }
14
14
  /**
15
- * Group runs by lab, newest-first within each lab and by recency between labs. Runs with no lab
15
+ * Group runs by study, newest-first within each study and by recency between studies. Runs with no study
16
16
  * attribution are collected under `unattributed` rather than invented into a study. That is the
17
17
  * home for pre-contract runs and library callers.
18
18
  */
19
- export declare function groupRunsByLab(entries: readonly RunIndexEntry[]): {
20
- labs: LabRollup[];
19
+ export declare function groupRunsByStudy(entries: readonly RunIndexEntry[]): {
20
+ studies: StudyRollup[];
21
21
  unattributed: RunIndexEntry[];
22
22
  };
23
23
  /**
24
- * What the launch screen may claim about a lab, and on what evidence. Every figure carries the
24
+ * What the launch screen may claim about a study, and on what evidence. Every figure carries the
25
25
  * number of runs it came from; `sample: 0` means there is nothing to claim and the caller must
26
26
  * say so rather than showing an empty number.
27
27
  */
28
- export interface LabExpectation {
29
- /** How many completed runs of this lab the figures are drawn from. */
28
+ export interface StudyExpectation {
29
+ /** How many completed runs of this study the figures are drawn from. */
30
30
  sample: number;
31
31
  medianDurationMs?: number;
32
32
  /** Range across the sample, so the UI can show a span instead of a false point estimate. */
@@ -40,7 +40,7 @@ export interface LabExpectation {
40
40
  costUnknown: number;
41
41
  }
42
42
  /**
43
- * Derive what to expect from a lab's own history. Only finished runs count: an interrupted run's
43
+ * Derive what to expect from a study's own history. Only finished runs count: an interrupted run's
44
44
  * duration is the length of an accident, not of a study, and including it would quietly bias the
45
45
  * estimate the operator uses to decide whether to press Start.
46
46
  *
@@ -49,22 +49,22 @@ export interface LabExpectation {
49
49
  * next to a control that spends money. Pass the mode the figure is about; omit it only for a
50
50
  * summary that is not attached to an action.
51
51
  */
52
- export declare function expectationFor(entries: readonly RunIndexEntry[], mode?: "dry-run" | "live"): LabExpectation;
52
+ export declare function expectationFor(entries: readonly RunIndexEntry[], mode?: "dry-run" | "live"): StudyExpectation;
53
53
  /**
54
54
  * The one sentence the launch screen shows about time and money, with its denominator attached.
55
- * A lab with no history says so plainly instead of borrowing another lab's numbers or inventing
55
+ * A study with no history says so plainly instead of borrowing another study's numbers or inventing
56
56
  * a range. "No runs yet" is information, and the operator can still press Start.
57
57
  */
58
- export declare function expectationLine(expectation: LabExpectation): string;
58
+ export declare function expectationLine(expectation: StudyExpectation): string;
59
59
  /**
60
- * The one line a lab may say about itself, wherever it is shown.
60
+ * The one line a study may say about itself, wherever it is shown.
61
61
  *
62
62
  * Prefers live figures: cost and duration are what someone reads before spending, and a median
63
63
  * diluted by dry runs reports a live study as cheaper and faster than it has ever been. With no
64
64
  * live history it reports the count and claims nothing about time or money. That is why this is
65
65
  * shared rather than reimplemented per surface, since the two disagreeing is the whole failure.
66
66
  */
67
- export declare function labSummaryLine(row: Pick<LabRow, "runs" | "declared" | "expectation" | "liveExpectation">): string;
67
+ export declare function studySummaryLine(row: Pick<StudyRow, "runs" | "declared" | "expectation" | "liveExpectation">): string;
68
68
  /** Compact duration: seconds under a minute, then m/s, then h/m. */
69
69
  export declare function formatDuration(ms: number): string;
70
70
  export interface NormalizedThought {
@@ -101,16 +101,16 @@ export declare function listWindow(args: {
101
101
  };
102
102
  /** The label for a run's state, in the register the surfaces share. */
103
103
  export declare function livenessLabel(entry: Pick<RunIndexEntry, "liveness" | "verdict">): string;
104
- /** A lab as the labs list shows it: what is declared, joined to what actually happened. */
105
- export interface LabRow {
104
+ /** A study as the study list shows it: what is declared, joined to what actually happened. */
105
+ export interface StudyRow {
106
106
  /**
107
- * Stable identity for this row. A manifest's path when it has one, else the lab id, because two
107
+ * Stable identity for this row. A manifest's path when it has one, else the study id, because two
108
108
  * manifests can declare the same id, and keying rows by id makes them collapse into a pair of
109
109
  * indistinguishable duplicates.
110
110
  */
111
111
  key: string;
112
112
  /** The declared id. Run history attributes to this, so it is not unique across manifests. */
113
- labId: string;
113
+ studyId: string;
114
114
  /**
115
115
  * The handle an operator would actually type. Lab resolution is by filename, so the manifest
116
116
  * `\`.humanish/labs/persona-contrast-live.yaml\`` is reached as `persona-contrast-live` even when
@@ -121,24 +121,24 @@ export interface LabRow {
121
121
  title?: string;
122
122
  /**
123
123
  * The shortest label that is unique among the rows it is listed with: the title when no other
124
- * lab shares it, else the filename, else the full path. A list is only navigable if every row can
124
+ * study shares it, else the filename, else the full path. A list is only navigable if every row can
125
125
  * be told from every other one, and a title is not guaranteed to be distinct: two manifests in
126
126
  * this repo carry the same title and the same declared id, differing only by filename.
127
127
  */
128
128
  label: string;
129
129
  /** The manifest's own words, for the list to say what this study is. */
130
130
  description?: string;
131
- /** Repo-relative manifest path, absent for a lab known only from run history. */
131
+ /** Repo-relative manifest path, absent for a study known only from run history. */
132
132
  path?: string;
133
133
  origin?: "committed" | "ignored" | "explicit";
134
134
  /**
135
- * False for a lab that has runs but no manifest here: renamed, deleted, or run from a path that
135
+ * False for a study that has runs but no manifest here: renamed, deleted, or run from a path that
136
136
  * is gone. Its runs are still evidence and must stay reachable, so it is listed and marked rather
137
137
  * than dropped.
138
138
  */
139
139
  declared: boolean;
140
140
  /**
141
- * How many other manifests declare this same lab id. Above zero, the run history below is shared
141
+ * How many other manifests declare this same study id. Above zero, the run history below is shared
142
142
  * between them and cannot be attributed to one file. That is worth saying, because it is a
143
143
  * misconfiguration the operator almost certainly does not know about.
144
144
  */
@@ -148,11 +148,11 @@ export interface LabRow {
148
148
  latest?: RunIndexEntry;
149
149
  liveRuns: RunIndexEntry[];
150
150
  /** Across every finished run, whatever its mode. A summary, never attached to a spend decision. */
151
- expectation: LabExpectation;
151
+ expectation: StudyExpectation;
152
152
  /** Live runs only: the figure that belongs beside anything that spends money. */
153
- liveExpectation: LabExpectation;
153
+ liveExpectation: StudyExpectation;
154
154
  }
155
- export interface DeclaredLab {
155
+ export interface DeclaredStudy {
156
156
  id: string;
157
157
  title?: string;
158
158
  /** The manifest's own description, so a list of studies can say what each one is. */
@@ -161,7 +161,7 @@ export interface DeclaredLab {
161
161
  origin?: "committed" | "ignored" | "explicit";
162
162
  }
163
163
  /**
164
- * Join declared lab manifests to run history.
164
+ * Join declared study manifests to run history.
165
165
  *
166
166
  * Neither side alone is the truth. A fresh project has manifests and no runs, and those labs are the
167
167
  * whole screen, and a list built only from history would be empty on exactly the first visit that
@@ -174,11 +174,11 @@ export interface DeclaredLab {
174
174
  * share an id. Collapsing them hides a real file; keying by id duplicates a row with no way to tell
175
175
  * the copies apart. Both happen in practice: this repo has exactly that pair.
176
176
  *
177
- * Order puts a lab someone is working in first, then labs by how recently they ran, then declared
177
+ * Order puts a study someone is working in first, then studies by how recently they ran, then declared
178
178
  * labs that have never run (alphabetically by the displayed label, so the order on screen is the
179
179
  * order a reader can predict), then labs known only from history.
180
180
  */
181
- export declare function labRows(declared: readonly DeclaredLab[], entries: readonly RunIndexEntry[]): {
182
- rows: LabRow[];
181
+ export declare function studyRows(declared: readonly DeclaredStudy[], entries: readonly RunIndexEntry[]): {
182
+ rows: StudyRow[];
183
183
  unattributed: RunIndexEntry[];
184
184
  };
@@ -1,5 +1,5 @@
1
1
  // The disk→view-model projection. Pure functions, no I/O, no rendering: this is where
2
- // lab grouping, the trust line's arithmetic, thought normalization and list-window math live, so
2
+ // study grouping, the trust line's arithmetic, thought normalization and list-window math live, so
3
3
  // the parts most likely to be wrong are testable without a terminal.
4
4
  //
5
5
  // The rules these encode, because they are the ones a UI is most tempted to break:
@@ -8,42 +8,42 @@
8
8
  // - truncation is reported, never silent;
9
9
  // - a participant's reported thinking is quoted, never paraphrased or summarized.
10
10
  /**
11
- * Group runs by lab, newest-first within each lab and by recency between labs. Runs with no lab
11
+ * Group runs by study, newest-first within each study and by recency between studies. Runs with no study
12
12
  * attribution are collected under `unattributed` rather than invented into a study. That is the
13
13
  * home for pre-contract runs and library callers.
14
14
  */
15
- export function groupRunsByLab(entries) {
16
- const byLab = new Map();
15
+ export function groupRunsByStudy(entries) {
16
+ const byStudy = new Map();
17
17
  const unattributed = [];
18
18
  for (const entry of entries) {
19
- const labId = entry.study?.id;
20
- if (labId === undefined) {
19
+ const studyId = entry.study?.id;
20
+ if (studyId === undefined) {
21
21
  unattributed.push(entry);
22
22
  continue;
23
23
  }
24
- const bucket = byLab.get(labId);
24
+ const bucket = byStudy.get(studyId);
25
25
  if (bucket === undefined)
26
- byLab.set(labId, [entry]);
26
+ byStudy.set(studyId, [entry]);
27
27
  else
28
28
  bucket.push(entry);
29
29
  }
30
- const labs = [...byLab.entries()].map(([labId, runs]) => {
30
+ const studies = [...byStudy.entries()].map(([studyId, runs]) => {
31
31
  const liveRuns = runs.filter((run) => run.liveness === "running");
32
32
  return {
33
- labId,
33
+ studyId,
34
34
  runs: runs.length,
35
35
  live: liveRuns.length,
36
36
  ...(runs[0] === undefined ? {} : { latest: runs[0] }),
37
37
  liveRuns,
38
38
  };
39
39
  });
40
- // A lab someone is working in sorts first; otherwise most recently used.
41
- labs.sort((left, right) => {
40
+ // A study someone is working in sorts first; otherwise most recently used.
41
+ studies.sort((left, right) => {
42
42
  if (left.live !== right.live)
43
43
  return right.live - left.live;
44
44
  return recencyOf(right.latest) - recencyOf(left.latest);
45
45
  });
46
- return { labs, unattributed };
46
+ return { studies, unattributed };
47
47
  }
48
48
  function recencyOf(entry) {
49
49
  if (entry === undefined)
@@ -58,7 +58,7 @@ function recencyOf(entry) {
58
58
  return 0;
59
59
  }
60
60
  /**
61
- * Derive what to expect from a lab's own history. Only finished runs count: an interrupted run's
61
+ * Derive what to expect from a study's own history. Only finished runs count: an interrupted run's
62
62
  * duration is the length of an accident, not of a study, and including it would quietly bias the
63
63
  * estimate the operator uses to decide whether to press Start.
64
64
  *
@@ -103,7 +103,7 @@ function median(sorted) {
103
103
  }
104
104
  /**
105
105
  * The one sentence the launch screen shows about time and money, with its denominator attached.
106
- * A lab with no history says so plainly instead of borrowing another lab's numbers or inventing
106
+ * A study with no history says so plainly instead of borrowing another study's numbers or inventing
107
107
  * a range. "No runs yet" is information, and the operator can still press Start.
108
108
  */
109
109
  export function expectationLine(expectation) {
@@ -132,14 +132,14 @@ export function expectationLine(expectation) {
132
132
  return `${parts.join(" · ")} · ${sample}${unknown}`;
133
133
  }
134
134
  /**
135
- * The one line a lab may say about itself, wherever it is shown.
135
+ * The one line a study may say about itself, wherever it is shown.
136
136
  *
137
137
  * Prefers live figures: cost and duration are what someone reads before spending, and a median
138
138
  * diluted by dry runs reports a live study as cheaper and faster than it has ever been. With no
139
139
  * live history it reports the count and claims nothing about time or money. That is why this is
140
140
  * shared rather than reimplemented per surface, since the two disagreeing is the whole failure.
141
141
  */
142
- export function labSummaryLine(row) {
142
+ export function studySummaryLine(row) {
143
143
  if (row.runs === 0)
144
144
  return row.declared ? "never run" : "no runs";
145
145
  if (row.liveExpectation.sample > 0)
@@ -240,12 +240,12 @@ export function livenessLabel(entry) {
240
240
  }
241
241
  }
242
242
  /** The addressable handle for a manifest: its filename without directory or extension. */
243
- function labNameFromPath(manifestPath) {
243
+ function studyNameFromPath(manifestPath) {
244
244
  const base = manifestPath.split("/").pop() ?? manifestPath;
245
245
  return base.replace(/\.(ya?ml)$/i, "");
246
246
  }
247
247
  /**
248
- * Join declared lab manifests to run history.
248
+ * Join declared study manifests to run history.
249
249
  *
250
250
  * Neither side alone is the truth. A fresh project has manifests and no runs, and those labs are the
251
251
  * whole screen, and a list built only from history would be empty on exactly the first visit that
@@ -258,57 +258,57 @@ function labNameFromPath(manifestPath) {
258
258
  * share an id. Collapsing them hides a real file; keying by id duplicates a row with no way to tell
259
259
  * the copies apart. Both happen in practice: this repo has exactly that pair.
260
260
  *
261
- * Order puts a lab someone is working in first, then labs by how recently they ran, then declared
261
+ * Order puts a study someone is working in first, then studies by how recently they ran, then declared
262
262
  * labs that have never run (alphabetically by the displayed label, so the order on screen is the
263
263
  * order a reader can predict), then labs known only from history.
264
264
  */
265
- export function labRows(declared, entries) {
266
- const { labs, unattributed } = groupRunsByLab(entries);
267
- const byId = new Map(labs.map((lab) => [lab.labId, lab]));
265
+ export function studyRows(declared, entries) {
266
+ const { studies, unattributed } = groupRunsByStudy(entries);
267
+ const byId = new Map(studies.map((study) => [study.studyId, study]));
268
268
  const runsOf = new Map();
269
269
  for (const entry of entries) {
270
- const labId = entry.study?.id;
271
- if (labId === undefined)
270
+ const studyId = entry.study?.id;
271
+ if (studyId === undefined)
272
272
  continue;
273
- const bucket = runsOf.get(labId);
273
+ const bucket = runsOf.get(studyId);
274
274
  if (bucket === undefined)
275
- runsOf.set(labId, [entry]);
275
+ runsOf.set(studyId, [entry]);
276
276
  else
277
277
  bucket.push(entry);
278
278
  }
279
279
  const idCounts = new Map();
280
- for (const lab of declared)
281
- idCounts.set(lab.id, (idCounts.get(lab.id) ?? 0) + 1);
282
- const build = (labId, manifest, isDeclared) => {
283
- const rollup = byId.get(labId);
280
+ for (const study of declared)
281
+ idCounts.set(study.id, (idCounts.get(study.id) ?? 0) + 1);
282
+ const build = (studyId, manifest, isDeclared) => {
283
+ const rollup = byId.get(studyId);
284
284
  const manifestPath = manifest?.path;
285
285
  return {
286
- key: manifestPath ?? `id:${labId}`,
287
- labId,
288
- name: manifestPath === undefined ? labId : labNameFromPath(manifestPath),
286
+ key: manifestPath ?? `id:${studyId}`,
287
+ studyId,
288
+ name: manifestPath === undefined ? studyId : studyNameFromPath(manifestPath),
289
289
  ...(manifest?.title === undefined ? {} : { title: manifest.title }),
290
290
  ...(manifestPath === undefined ? {} : { path: manifestPath }),
291
291
  ...(manifest?.origin === undefined ? {} : { origin: manifest.origin }),
292
292
  declared: isDeclared,
293
293
  // Replaced by assignLabels once the whole set is known; a label is only meaningful relative
294
294
  // to the rows it sits beside.
295
- label: manifest?.title ?? (manifestPath === undefined ? labId : labNameFromPath(manifestPath)),
295
+ label: manifest?.title ?? (manifestPath === undefined ? studyId : studyNameFromPath(manifestPath)),
296
296
  ...(manifest?.description === undefined ? {} : { description: manifest.description }),
297
- sharesIdWith: Math.max(0, (idCounts.get(labId) ?? 0) - 1),
297
+ sharesIdWith: Math.max(0, (idCounts.get(studyId) ?? 0) - 1),
298
298
  runs: rollup?.runs ?? 0,
299
299
  live: rollup?.live ?? 0,
300
300
  ...(rollup?.latest === undefined ? {} : { latest: rollup.latest }),
301
301
  liveRuns: rollup?.liveRuns ?? [],
302
- expectation: expectationFor(runsOf.get(labId) ?? []),
303
- liveExpectation: expectationFor(runsOf.get(labId) ?? [], "live"),
302
+ expectation: expectationFor(runsOf.get(studyId) ?? []),
303
+ liveExpectation: expectationFor(runsOf.get(studyId) ?? [], "live"),
304
304
  };
305
305
  };
306
- const declaredIds = new Set(declared.map((lab) => lab.id));
306
+ const declaredIds = new Set(declared.map((study) => study.id));
307
307
  const rows = [
308
- ...declared.map((lab) => build(lab.id, lab, true)),
309
- ...labs
310
- .filter((lab) => !declaredIds.has(lab.labId))
311
- .map((lab) => build(lab.labId, undefined, false)),
308
+ ...declared.map((study) => build(study.id, study, true)),
309
+ ...studies
310
+ .filter((study) => !declaredIds.has(study.studyId))
311
+ .map((study) => build(study.studyId, undefined, false)),
312
312
  ];
313
313
  // Resolve each row's label before sorting, so the list is ordered by what a reader actually sees.
314
314
  assignLabels(rows);
@@ -334,7 +334,7 @@ export function labRows(declared, entries) {
334
334
  *
335
335
  * Falling straight back to the filename whenever a title repeats, instead of decorating the
336
336
  * duplicate with a suffix, keeps the label something the operator can act on, because the filename
337
- * is exactly what `humanish lab run` takes.
337
+ * is exactly what `humanish run` takes.
338
338
  */
339
339
  function assignLabels(rows) {
340
340
  const count = (values) => {
@@ -38,7 +38,7 @@ export declare function reclaimRunSandboxes(cwd: string, runInput: string, hooks
38
38
  */
39
39
  export declare function reclaimPinnedRunSandboxes(cwd: string, runPaths: PreparedRunArtifactPaths, hooks?: ReclaimHooks): Promise<ReclaimResult>;
40
40
  /**
41
- * Kill the sandboxes left by interrupted `humanish lab preflight` probes. A probe journals under
41
+ * Kill the sandboxes left by interrupted `humanish study check` probes. A probe journals under
42
42
  * .humanish/preflight/<probe-id>/ and removes the journal after a confirmed kill, so what is left
43
43
  * belongs to a probe that died or could not confirm its teardown. A journal whose probe may still
44
44
  * be running is left alone with the reason (see preflightReclaimDecision).
@@ -80,7 +80,7 @@ async function reclaimRun(cwd, runInput, locate, hooks) {
80
80
  return result;
81
81
  }
82
82
  /**
83
- * Kill the sandboxes left by interrupted `humanish lab preflight` probes. A probe journals under
83
+ * Kill the sandboxes left by interrupted `humanish study check` probes. A probe journals under
84
84
  * .humanish/preflight/<probe-id>/ and removes the journal after a confirmed kill, so what is left
85
85
  * belongs to a probe that died or could not confirm its teardown. A journal whose probe may still
86
86
  * be running is left alone with the reason (see preflightReclaimDecision).