humanish 0.106.1 → 0.108.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (668) hide show
  1. package/ARCHITECTURE.md +38 -32
  2. package/CHANGELOG.md +28 -0
  3. package/CONTEXT.md +51 -41
  4. package/README.md +152 -174
  5. package/SECURITY.md +16 -26
  6. package/TELEMETRY.md +8 -6
  7. package/dist/actors/affordance.d.ts +4 -4
  8. package/dist/actors/affordance.js +12 -12
  9. package/dist/actors/agent-session.d.ts +2 -2
  10. package/dist/actors/agent-session.js +7 -7
  11. package/dist/actors/codex/app-server-actor-trace.d.ts +1 -1
  12. package/dist/actors/codex/app-server-actor-trace.js +1 -1
  13. package/dist/actors/codex/app-server-client.js +2 -1
  14. package/dist/actors/codex/app-server-trace.d.ts +0 -1
  15. package/dist/actors/codex/app-server-trace.js +1 -3
  16. package/dist/actors/codex/app-server-ui.js +1 -1
  17. package/dist/actors/codex/app-server.js +2 -1
  18. package/dist/actors/codex/codex-admission.d.ts +91 -0
  19. package/dist/actors/codex/codex-admission.js +150 -0
  20. package/dist/actors/codex/protocol-compat.d.ts +27 -0
  21. package/dist/actors/codex/protocol-compat.js +357 -0
  22. package/dist/actors/codex/protocol-contract.d.ts +61 -0
  23. package/dist/actors/codex/protocol-contract.js +471 -0
  24. package/dist/actors/codex/restricted-executable.d.ts +28 -4
  25. package/dist/actors/codex/restricted-executable.js +104 -29
  26. package/dist/actors/codex/restricted-launch.d.ts +9 -2
  27. package/dist/actors/codex/restricted-launch.js +43 -4
  28. package/dist/actors/codex/restricted-notifications.d.ts +101 -0
  29. package/dist/actors/codex/restricted-notifications.js +277 -0
  30. package/dist/actors/codex/restricted-participant.d.ts +30 -0
  31. package/dist/actors/codex/restricted-participant.js +66 -6
  32. package/dist/actors/codex/restricted-policy.d.ts +11 -3
  33. package/dist/actors/codex/restricted-policy.js +2 -2
  34. package/dist/actors/codex/restricted-session.d.ts +16 -3
  35. package/dist/actors/codex/restricted-session.js +60 -22
  36. package/dist/actors/codex/restricted-transport.d.ts +29 -0
  37. package/dist/actors/codex/restricted-transport.js +139 -27
  38. package/dist/actors/codex/restricted-turn.d.ts +19 -4
  39. package/dist/actors/codex/restricted-turn.js +43 -30
  40. package/dist/actors/computer-use/actor.d.ts +17 -17
  41. package/dist/actors/computer-use/actor.js +6 -6
  42. package/dist/actors/computer-use/admission-limit.d.ts +1 -1
  43. package/dist/actors/computer-use/admission-limit.js +1 -1
  44. package/dist/actors/computer-use/loop/actions.d.ts +3 -3
  45. package/dist/actors/computer-use/loop/actions.js +10 -10
  46. package/dist/actors/computer-use/loop/backstop.d.ts +3 -3
  47. package/dist/actors/computer-use/loop/backstop.js +15 -13
  48. package/dist/actors/computer-use/loop/ending.d.ts +7 -7
  49. package/dist/actors/computer-use/loop/ending.js +9 -9
  50. package/dist/actors/computer-use/loop/observation.d.ts +2 -2
  51. package/dist/actors/computer-use/loop/observation.js +9 -9
  52. package/dist/actors/computer-use/loop/provider-call.d.ts +1 -1
  53. package/dist/actors/computer-use/loop/provider-call.js +1 -1
  54. package/dist/actors/computer-use/loop/session.js +3 -3
  55. package/dist/actors/computer-use/loop/spend.d.ts +2 -2
  56. package/dist/actors/computer-use/loop/spend.js +4 -4
  57. package/dist/actors/computer-use/loop/trace.js +11 -10
  58. package/dist/actors/computer-use/loop/types.d.ts +37 -26
  59. package/dist/actors/computer-use/loop/usage.js +2 -2
  60. package/dist/actors/computer-use/loop.js +4 -4
  61. package/dist/actors/computer-use/openai-context.d.ts +37 -0
  62. package/dist/actors/computer-use/openai-context.js +214 -0
  63. package/dist/actors/computer-use/openai-provider.d.ts +12 -9
  64. package/dist/actors/computer-use/openai-provider.js +47 -36
  65. package/dist/actors/computer-use/openai-requests.d.ts +36 -10
  66. package/dist/actors/computer-use/openai-requests.js +82 -15
  67. package/dist/actors/computer-use/openai-wire.d.ts +19 -7
  68. package/dist/actors/computer-use/openai-wire.js +36 -34
  69. package/dist/actors/contract.d.ts +86 -49
  70. package/dist/actors/contract.js +29 -23
  71. package/dist/actors/local-agent/claude-session.d.ts +1 -1
  72. package/dist/actors/local-agent/claude-session.js +10 -9
  73. package/dist/actors/local-agent/cli.d.ts +8 -6
  74. package/dist/actors/local-agent/cli.js +24 -28
  75. package/dist/actors/local-agent/readiness.d.ts +2 -2
  76. package/dist/actors/local-agent/readiness.js +4 -4
  77. package/dist/actors/reasoning-effort.js +6 -6
  78. package/dist/actors/registry.d.ts +10 -10
  79. package/dist/actors/registry.js +18 -17
  80. package/dist/actors/scripted-browser/actor.d.ts +8 -8
  81. package/dist/actors/scripted-browser/actor.js +16 -16
  82. package/dist/actors/scripted-browser/browser-command.js +1 -1
  83. package/dist/actors/scripted-browser/journey.js +15 -4
  84. package/dist/actors/scripted-browser/steps.js +19 -1
  85. package/dist/actors/scripted-browser/types.d.ts +12 -2
  86. package/dist/actors/stop-conditions.d.ts +1 -1
  87. package/dist/actors/stop-conditions.js +1 -3
  88. package/dist/analysis/automatic-completion.d.ts +13 -8
  89. package/dist/analysis/automatic-completion.js +14 -8
  90. package/dist/analysis/automatic-config.d.ts +1 -1
  91. package/dist/analysis/automatic-config.js +2 -2
  92. package/dist/analysis/automatic.d.ts +10 -4
  93. package/dist/analysis/automatic.js +17 -13
  94. package/dist/analysis/codex-config.d.ts +6 -2
  95. package/dist/analysis/codex-config.js +22 -14
  96. package/dist/analysis/diagnostics.d.ts +23 -0
  97. package/dist/analysis/diagnostics.js +112 -0
  98. package/dist/analysis/evidence-sources.js +2 -2
  99. package/dist/analysis/evidence.js +6 -6
  100. package/dist/analysis/execute.d.ts +7 -1
  101. package/dist/analysis/execute.js +39 -12
  102. package/dist/analysis/job.d.ts +8 -5
  103. package/dist/analysis/job.js +15 -14
  104. package/dist/analysis/load.d.ts +1 -1
  105. package/dist/analysis/load.js +5 -5
  106. package/dist/analysis/provider.d.ts +9 -1
  107. package/dist/analysis/restricted-codex.d.ts +2 -0
  108. package/dist/analysis/restricted-codex.js +10 -1
  109. package/dist/analysis/service.d.ts +2 -0
  110. package/dist/analysis/service.js +35 -16
  111. package/dist/analysis/sharing.d.ts +2 -2
  112. package/dist/analysis/sharing.js +5 -5
  113. package/dist/analysis/store-executions.d.ts +5 -5
  114. package/dist/analysis/store-executions.js +12 -12
  115. package/dist/analysis/store.d.ts +4 -4
  116. package/dist/analysis/store.js +13 -13
  117. package/dist/cli/commands/analysis-signals.d.ts +2 -1
  118. package/dist/cli/commands/analysis-signals.js +4 -1
  119. package/dist/cli/commands/analyze.js +23 -18
  120. package/dist/cli/commands/codex.js +9 -9
  121. package/dist/cli/commands/comms.js +62 -34
  122. package/dist/cli/commands/feedback.js +20 -21
  123. package/dist/cli/commands/lab-format.d.ts +5 -4
  124. package/dist/cli/commands/lab-format.js +35 -23
  125. package/dist/cli/commands/lab-route-computer-use.d.ts +0 -2
  126. package/dist/cli/commands/lab-route-computer-use.js +32 -21
  127. package/dist/cli/commands/lab-route-preview.d.ts +1 -3
  128. package/dist/cli/commands/lab-route-preview.js +7 -7
  129. package/dist/cli/commands/lab-route-run.d.ts +6 -4
  130. package/dist/cli/commands/lab-route-run.js +6 -2
  131. package/dist/cli/commands/lab-route-scripted.d.ts +0 -2
  132. package/dist/cli/commands/lab-route-scripted.js +0 -1
  133. package/dist/cli/commands/lab-route-shared-world.d.ts +0 -2
  134. package/dist/cli/commands/lab-route-shared-world.js +3 -4
  135. package/dist/cli/commands/lab-route-terminal.d.ts +0 -2
  136. package/dist/cli/commands/lab-route-terminal.js +0 -1
  137. package/dist/cli/commands/lab-run.js +84 -54
  138. package/dist/cli/commands/lab-scorer.d.ts +2 -4
  139. package/dist/cli/commands/lab-scorer.js +1 -1
  140. package/dist/cli/commands/migrate.d.ts +4 -0
  141. package/dist/cli/commands/migrate.js +65 -0
  142. package/dist/cli/commands/observe.js +168 -107
  143. package/dist/cli/commands/run-command.d.ts +10 -0
  144. package/dist/cli/commands/run-command.js +85 -0
  145. package/dist/cli/commands/run-signals.d.ts +30 -0
  146. package/dist/cli/commands/run-signals.js +146 -0
  147. package/dist/cli/commands/runs.js +137 -136
  148. package/dist/cli/commands/setup.d.ts +2 -2
  149. package/dist/cli/commands/setup.js +26 -21
  150. package/dist/cli/commands/study.d.ts +3 -0
  151. package/dist/cli/commands/study.js +182 -0
  152. package/dist/cli/commands/tui.d.ts +4 -4
  153. package/dist/cli/commands/tui.js +21 -21
  154. package/dist/cli/commands/watch.js +64 -77
  155. package/dist/cli/deprecations.d.ts +18 -0
  156. package/dist/cli/deprecations.js +48 -0
  157. package/dist/cli/doctor.d.ts +18 -5
  158. package/dist/cli/doctor.js +111 -48
  159. package/dist/cli/first-run-path.d.ts +12 -10
  160. package/dist/cli/first-run-path.js +30 -28
  161. package/dist/cli/io.d.ts +46 -10
  162. package/dist/cli/io.js +109 -30
  163. package/dist/cli/observer-follow.d.ts +2 -2
  164. package/dist/cli/observer-follow.js +5 -6
  165. package/dist/cli/orientation.d.ts +6 -3
  166. package/dist/cli/orientation.js +43 -39
  167. package/dist/cli/product-sentence.d.ts +6 -0
  168. package/dist/cli/product-sentence.js +6 -0
  169. package/dist/cli/program.d.ts +6 -1
  170. package/dist/cli/program.js +112 -43
  171. package/dist/cli/telemetry.d.ts +17 -17
  172. package/dist/cli/telemetry.js +49 -41
  173. package/dist/cli.js +1 -1
  174. package/dist/comms/capture-surface.d.ts +14 -13
  175. package/dist/comms/capture-surface.js +23 -22
  176. package/dist/comms/catch-host.d.ts +8 -8
  177. package/dist/comms/catch-host.js +14 -14
  178. package/dist/comms/connections.js +4 -4
  179. package/dist/comms/email-catch.d.ts +3 -3
  180. package/dist/comms/email-catch.js +8 -8
  181. package/dist/comms/external-evidence.d.ts +27 -0
  182. package/dist/comms/external-evidence.js +93 -0
  183. package/dist/comms/extract.js +2 -2
  184. package/dist/comms/fake-inbox.d.ts +2 -2
  185. package/dist/comms/fake-inbox.js +2 -2
  186. package/dist/comms/lease-store.js +7 -7
  187. package/dist/comms/receiving-render.d.ts +1 -1
  188. package/dist/comms/receiving-render.js +2 -2
  189. package/dist/comms/sandbox-catch-script.d.ts +6 -6
  190. package/dist/comms/sandbox-catch-script.js +6 -6
  191. package/dist/comms/sandbox-catch.d.ts +36 -37
  192. package/dist/comms/sandbox-catch.js +34 -35
  193. package/dist/comms/setup.js +42 -8
  194. package/dist/comms/thread-evidence.d.ts +1 -1
  195. package/dist/comms/thread-evidence.js +6 -6
  196. package/dist/comms/types.d.ts +6 -6
  197. package/dist/comms/types.js +4 -4
  198. package/dist/evidence/browser-hygiene.d.ts +1 -1
  199. package/dist/evidence/browser-hygiene.js +1 -1
  200. package/dist/evidence/frame-signature.d.ts +1 -1
  201. package/dist/evidence/frame-signature.js +4 -4
  202. package/dist/evidence/redaction.d.ts +3 -3
  203. package/dist/evidence/redaction.js +5 -5
  204. package/dist/evidence/secret-scrub.d.ts +9 -0
  205. package/dist/evidence/secret-scrub.js +96 -0
  206. package/dist/feedback/draft.js +41 -85
  207. package/dist/feedback/export-bundle.js +5 -5
  208. package/dist/feedback/export.d.ts +5 -1
  209. package/dist/feedback/export.js +16 -17
  210. package/dist/feedback/feedback.d.ts +3 -3
  211. package/dist/feedback/feedback.js +21 -3
  212. package/dist/guest/chromium-text.js +2 -2
  213. package/dist/guest/desktop-native.d.ts +1 -1
  214. package/dist/guest/runtime.js +1 -1
  215. package/dist/index.d.ts +14 -15
  216. package/dist/index.js +10 -11
  217. package/dist/keys/key-resolution.d.ts +7 -5
  218. package/dist/keys/key-resolution.js +40 -38
  219. package/dist/lab/adapter-extension.d.ts +35 -13
  220. package/dist/lab/adapter-extension.js +50 -134
  221. package/dist/lab/adapter-scorer-loader.d.ts +32 -12
  222. package/dist/lab/adapter-scorer-loader.js +56 -32
  223. package/dist/lab/composition-rules.js +58 -58
  224. package/dist/lab/config.js +85 -43
  225. package/dist/lab/deprecated-fields.d.ts +10 -0
  226. package/dist/lab/deprecated-fields.js +24 -0
  227. package/dist/lab/device-presets.d.ts +10 -10
  228. package/dist/lab/device-presets.js +11 -11
  229. package/dist/lab/discover.d.ts +13 -9
  230. package/dist/lab/discover.js +118 -60
  231. package/dist/lab/doctor.d.ts +53 -11
  232. package/dist/lab/doctor.js +193 -47
  233. package/dist/lab/init-plan.js +1 -3
  234. package/dist/lab/init-templates.js +147 -147
  235. package/dist/lab/init.d.ts +1 -1
  236. package/dist/lab/init.js +41 -9
  237. package/dist/lab/keys.d.ts +2 -0
  238. package/dist/lab/keys.js +43 -9
  239. package/dist/lab/lab-deps.d.ts +80 -0
  240. package/dist/lab/lab-deps.js +4 -0
  241. package/dist/lab/parse/actors.js +17 -16
  242. package/dist/lab/parse/comms.js +8 -7
  243. package/dist/lab/parse/execution.js +15 -14
  244. package/dist/lab/parse/study-v3.d.ts +23 -0
  245. package/dist/lab/parse/study-v3.js +259 -0
  246. package/dist/lab/parse/subject-state.d.ts +7 -7
  247. package/dist/lab/parse/subject-state.js +18 -17
  248. package/dist/lab/parse/subject.js +30 -29
  249. package/dist/lab/parse/values.d.ts +1 -2
  250. package/dist/lab/parse/values.js +3 -6
  251. package/dist/lab/persona-resolve.d.ts +7 -7
  252. package/dist/lab/persona-resolve.js +8 -8
  253. package/dist/lab/persona.js +1 -3
  254. package/dist/lab/plan-base.d.ts +0 -2
  255. package/dist/lab/plan-base.js +6 -4
  256. package/dist/lab/plan-participants.d.ts +7 -7
  257. package/dist/lab/plan-participants.js +2 -2
  258. package/dist/lab/plan-types.d.ts +26 -8
  259. package/dist/lab/plan.d.ts +4 -18
  260. package/dist/lab/plan.js +24 -79
  261. package/dist/lab/preflight-probes.js +11 -11
  262. package/dist/lab/preflight-result.d.ts +2 -1
  263. package/dist/lab/preflight-result.js +5 -6
  264. package/dist/lab/preflight.d.ts +7 -8
  265. package/dist/lab/preflight.js +6 -6
  266. package/dist/lab/requirements.d.ts +20 -0
  267. package/dist/lab/requirements.js +54 -0
  268. package/dist/lab/route-inputs.d.ts +23 -12
  269. package/dist/lab/route-inputs.js +48 -51
  270. package/dist/lab/routing.d.ts +42 -41
  271. package/dist/lab/routing.js +66 -68
  272. package/dist/lab/run-lab-events.d.ts +3 -11
  273. package/dist/lab/run-lab-events.js +2 -16
  274. package/dist/lab/run-lab-homes.d.ts +76 -0
  275. package/dist/lab/run-lab-homes.js +7 -0
  276. package/dist/lab/run-lab-options.d.ts +12 -66
  277. package/dist/lab/run-lab-options.js +58 -285
  278. package/dist/lab/summary.d.ts +15 -9
  279. package/dist/lab/summary.js +24 -17
  280. package/dist/lab/tasks.d.ts +15 -15
  281. package/dist/lab/tasks.js +14 -14
  282. package/dist/lab/types.d.ts +201 -195
  283. package/dist/lab/types.js +2 -0
  284. package/dist/lab/validation.d.ts +21 -21
  285. package/dist/lab/validation.js +61 -59
  286. package/dist/lab/warnings.d.ts +10 -0
  287. package/dist/lab/warnings.js +70 -41
  288. package/dist/library-aliases.d.ts +56 -0
  289. package/dist/library-aliases.js +22 -0
  290. package/dist/observer/artifact.d.ts +2 -2
  291. package/dist/observer/artifact.js +9 -9
  292. package/dist/observer/data.d.ts +6 -6
  293. package/dist/observer/data.js +7 -6
  294. package/dist/observer/exposure.d.ts +1 -1
  295. package/dist/observer/exposure.js +11 -11
  296. package/dist/observer/http.js +1 -1
  297. package/dist/observer/library.d.ts +1 -1
  298. package/dist/observer/library.js +4 -2
  299. package/dist/observer/listen.js +5 -4
  300. package/dist/observer/render.d.ts +1 -1
  301. package/dist/observer/render.js +12 -7
  302. package/dist/observer/run-routes.d.ts +4 -4
  303. package/dist/observer/run-routes.js +6 -6
  304. package/dist/observer/serve.d.ts +17 -0
  305. package/dist/observer/serve.js +41 -6
  306. package/dist/observer/tunnel.js +1 -1
  307. package/dist/observer-app.html +4 -4
  308. package/dist/routes/computer-use/bundle-parts.d.ts +9 -9
  309. package/dist/routes/computer-use/bundle-parts.js +24 -17
  310. package/dist/routes/computer-use/bundle.d.ts +4 -11
  311. package/dist/routes/computer-use/bundle.js +12 -18
  312. package/dist/routes/computer-use/diagnostics.d.ts +1 -1
  313. package/dist/routes/computer-use/diagnostics.js +1 -1
  314. package/dist/routes/computer-use/e2b-desktop/comms.d.ts +11 -11
  315. package/dist/routes/computer-use/e2b-desktop/comms.js +24 -27
  316. package/dist/routes/computer-use/e2b-desktop/desktop.d.ts +2 -2
  317. package/dist/routes/computer-use/e2b-desktop/desktop.js +8 -11
  318. package/dist/routes/computer-use/e2b-desktop/fidelity.d.ts +16 -15
  319. package/dist/routes/computer-use/e2b-desktop/fidelity.js +20 -19
  320. package/dist/routes/computer-use/e2b-desktop/prepare.d.ts +3 -3
  321. package/dist/routes/computer-use/e2b-desktop/prepare.js +40 -43
  322. package/dist/routes/computer-use/e2b-desktop/start.d.ts +1 -1
  323. package/dist/routes/computer-use/e2b-desktop/start.js +32 -30
  324. package/dist/routes/computer-use/e2b-desktop/state.d.ts +5 -4
  325. package/dist/routes/computer-use/e2b-desktop/state.js +5 -3
  326. package/dist/routes/computer-use/e2b-desktop/teardown.d.ts +1 -1
  327. package/dist/routes/computer-use/e2b-desktop/teardown.js +33 -20
  328. package/dist/routes/computer-use/external-comms.d.ts +4 -4
  329. package/dist/routes/computer-use/external-comms.js +19 -43
  330. package/dist/routes/computer-use/fanout-bundle.d.ts +3 -3
  331. package/dist/routes/computer-use/fanout-bundle.js +38 -42
  332. package/dist/routes/computer-use/{fanout-lanes.js → fanout-records.js} +33 -28
  333. package/dist/routes/computer-use/in-process-desktop.d.ts +3 -10
  334. package/dist/routes/computer-use/in-process-desktop.js +3 -9
  335. package/dist/routes/computer-use/live-flush.d.ts +7 -5
  336. package/dist/routes/computer-use/live-flush.js +20 -28
  337. package/dist/routes/computer-use/{run-lanes.d.ts → live-phase.d.ts} +4 -2
  338. package/dist/routes/computer-use/{run-lanes.js → live-phase.js} +17 -16
  339. package/dist/routes/computer-use/local-tree-pack.d.ts +3 -3
  340. package/dist/routes/computer-use/local-tree-pack.js +4 -5
  341. package/dist/routes/computer-use/local-vm.d.ts +11 -8
  342. package/dist/routes/computer-use/local-vm.js +40 -67
  343. package/dist/routes/computer-use/participant-desktop.d.ts +8 -23
  344. package/dist/routes/computer-use/participant-desktop.js +5 -25
  345. package/dist/routes/computer-use/{lanes.d.ts → participant-execution.d.ts} +11 -11
  346. package/dist/routes/computer-use/{lanes.js → participant-execution.js} +39 -26
  347. package/dist/routes/computer-use/participant-facts.d.ts +7 -1
  348. package/dist/routes/computer-use/participant-facts.js +12 -1
  349. package/dist/routes/computer-use/participant-model.d.ts +25 -11
  350. package/dist/routes/computer-use/participant-model.js +76 -34
  351. package/dist/routes/computer-use/participant-prompt.d.ts +13 -13
  352. package/dist/routes/computer-use/participant-prompt.js +8 -8
  353. package/dist/routes/computer-use/participant-runs.d.ts +11 -11
  354. package/dist/routes/computer-use/participant-runs.js +18 -18
  355. package/dist/routes/computer-use/plan.d.ts +21 -29
  356. package/dist/routes/computer-use/plan.js +70 -78
  357. package/dist/routes/computer-use/preflight.d.ts +3 -5
  358. package/dist/routes/computer-use/preflight.js +40 -36
  359. package/dist/routes/computer-use/rerun-selection.js +11 -7
  360. package/dist/routes/computer-use/result.d.ts +1 -1
  361. package/dist/routes/computer-use/result.js +48 -38
  362. package/dist/routes/computer-use/route.d.ts +5 -5
  363. package/dist/routes/computer-use/route.js +36 -33
  364. package/dist/routes/computer-use/self-report.d.ts +8 -8
  365. package/dist/routes/computer-use/self-report.js +33 -33
  366. package/dist/routes/computer-use/setup.d.ts +9 -15
  367. package/dist/routes/computer-use/setup.js +106 -83
  368. package/dist/routes/computer-use/single-bundle.d.ts +13 -16
  369. package/dist/routes/computer-use/single-bundle.js +46 -53
  370. package/dist/routes/computer-use/subject-projection.d.ts +6 -8
  371. package/dist/routes/computer-use/subject-projection.js +24 -23
  372. package/dist/routes/computer-use/types.d.ts +195 -238
  373. package/dist/routes/computer-use/types.js +21 -13
  374. package/dist/routes/preview.d.ts +8 -2
  375. package/dist/routes/preview.js +8 -5
  376. package/dist/routes/scripted/bundle.d.ts +5 -8
  377. package/dist/routes/scripted/bundle.js +23 -27
  378. package/dist/routes/scripted/plan.d.ts +6 -8
  379. package/dist/routes/scripted/plan.js +15 -13
  380. package/dist/routes/scripted/result.d.ts +4 -1
  381. package/dist/routes/scripted/result.js +15 -11
  382. package/dist/routes/scripted/route.js +15 -17
  383. package/dist/routes/scripted/scenario.d.ts +1 -1
  384. package/dist/routes/scripted/scenario.js +3 -3
  385. package/dist/routes/scripted/setup.d.ts +3 -2
  386. package/dist/routes/scripted/setup.js +27 -26
  387. package/dist/routes/scripted/subject.d.ts +8 -3
  388. package/dist/routes/scripted/subject.js +10 -6
  389. package/dist/routes/scripted/surface-records.js +4 -4
  390. package/dist/routes/scripted/surface-sessions.d.ts +2 -2
  391. package/dist/routes/scripted/surface-sessions.js +4 -4
  392. package/dist/routes/scripted/types.d.ts +21 -40
  393. package/dist/routes/scripted/types.js +2 -3
  394. package/dist/routes/shared-world/{seat-records.js → bundle-records.js} +17 -16
  395. package/dist/routes/shared-world/bundle.d.ts +7 -7
  396. package/dist/routes/shared-world/bundle.js +60 -62
  397. package/dist/routes/shared-world/checkpoints.d.ts +5 -5
  398. package/dist/routes/shared-world/checkpoints.js +5 -5
  399. package/dist/routes/shared-world/comms.d.ts +8 -7
  400. package/dist/routes/shared-world/comms.js +38 -51
  401. package/dist/routes/shared-world/external-public.d.ts +6 -5
  402. package/dist/routes/shared-world/external-public.js +28 -25
  403. package/dist/routes/shared-world/handoff.d.ts +10 -9
  404. package/dist/routes/shared-world/handoff.js +89 -81
  405. package/dist/routes/shared-world/lobby-code.d.ts +7 -7
  406. package/dist/routes/shared-world/lobby-code.js +22 -22
  407. package/dist/routes/shared-world/{seats.d.ts → participant-specs.d.ts} +15 -12
  408. package/dist/routes/shared-world/{seats.js → participant-specs.js} +65 -63
  409. package/dist/routes/shared-world/plan.d.ts +2 -6
  410. package/dist/routes/shared-world/plan.js +8 -9
  411. package/dist/routes/shared-world/provenance.d.ts +4 -4
  412. package/dist/routes/shared-world/provenance.js +4 -4
  413. package/dist/routes/shared-world/provisioned.d.ts +3 -2
  414. package/dist/routes/shared-world/provisioned.js +55 -48
  415. package/dist/routes/shared-world/result.js +47 -36
  416. package/dist/routes/shared-world/route.js +54 -57
  417. package/dist/routes/shared-world/setup.d.ts +6 -5
  418. package/dist/routes/shared-world/setup.js +16 -18
  419. package/dist/routes/shared-world/types.d.ts +70 -141
  420. package/dist/routes/shared-world/types.js +5 -5
  421. package/dist/routes/terminal/adapter.d.ts +10 -10
  422. package/dist/routes/terminal/adapter.js +32 -129
  423. package/dist/routes/terminal/bundle.d.ts +10 -15
  424. package/dist/routes/terminal/bundle.js +43 -52
  425. package/dist/routes/terminal/credentials.d.ts +4 -4
  426. package/dist/routes/terminal/credentials.js +20 -20
  427. package/dist/routes/terminal/dry-run.d.ts +1 -1
  428. package/dist/routes/terminal/dry-run.js +13 -15
  429. package/dist/routes/terminal/encoding.d.ts +1 -1
  430. package/dist/routes/terminal/encoding.js +4 -4
  431. package/dist/routes/terminal/ledger.d.ts +8 -8
  432. package/dist/routes/terminal/ledger.js +22 -22
  433. package/dist/routes/terminal/live-finish.d.ts +1 -2
  434. package/dist/routes/terminal/live-finish.js +24 -23
  435. package/dist/routes/terminal/live-sandbox.d.ts +3 -2
  436. package/dist/routes/terminal/live-sandbox.js +31 -32
  437. package/dist/routes/terminal/participant-text.d.ts +23 -0
  438. package/dist/routes/terminal/participant-text.js +165 -0
  439. package/dist/routes/terminal/persona.js +1 -1
  440. package/dist/routes/terminal/plan.d.ts +2 -6
  441. package/dist/routes/terminal/plan.js +23 -19
  442. package/dist/routes/terminal/recorder.d.ts +6 -1
  443. package/dist/routes/terminal/recorder.js +12 -4
  444. package/dist/routes/terminal/result.js +12 -12
  445. package/dist/routes/terminal/route.js +30 -31
  446. package/dist/routes/terminal/runtime.d.ts +3 -2
  447. package/dist/routes/terminal/runtime.js +3 -3
  448. package/dist/routes/terminal/sandbox.d.ts +4 -4
  449. package/dist/routes/terminal/sandbox.js +10 -10
  450. package/dist/routes/terminal/session.js +22 -19
  451. package/dist/routes/terminal/token-usage.d.ts +1 -1
  452. package/dist/routes/terminal/token-usage.js +10 -11
  453. package/dist/routes/terminal/trace.d.ts +7 -10
  454. package/dist/routes/terminal/trace.js +11 -66
  455. package/dist/routes/terminal/types.d.ts +104 -114
  456. package/dist/routes/terminal/types.js +12 -7
  457. package/dist/run/active-runs.d.ts +13 -0
  458. package/dist/run/active-runs.js +12 -0
  459. package/dist/run/bundle-shape.d.ts +2 -1
  460. package/dist/run/bundle-shape.js +7 -7
  461. package/dist/run/bundle.d.ts +99 -92
  462. package/dist/run/bundle.js +10 -8
  463. package/dist/run/cost-summary.js +6 -5
  464. package/dist/run/costs.d.ts +6 -6
  465. package/dist/run/costs.js +17 -11
  466. package/dist/run/detail.d.ts +9 -9
  467. package/dist/run/detail.js +10 -10
  468. package/dist/run/dry-run-inputs.js +1 -1
  469. package/dist/run/dry-run.js +23 -30
  470. package/dist/run/{study-files.d.ts → evidence-files.d.ts} +4 -4
  471. package/dist/run/{study-files.js → evidence-files.js} +5 -5
  472. package/dist/run/feedback-shape.js +1 -1
  473. package/dist/run/judge.d.ts +34 -16
  474. package/dist/run/judge.js +41 -14
  475. package/dist/run/locate.d.ts +2 -0
  476. package/dist/run/locate.js +3 -1
  477. package/dist/run/outcomes.d.ts +3 -3
  478. package/dist/run/outcomes.js +3 -3
  479. package/dist/run/participant-records.d.ts +2 -2
  480. package/dist/run/participant-records.js +2 -2
  481. package/dist/run/paths.d.ts +1 -1
  482. package/dist/run/paths.js +2 -2
  483. package/dist/run/pricing.d.ts +30 -15
  484. package/dist/run/pricing.js +49 -30
  485. package/dist/run/projection.d.ts +27 -27
  486. package/dist/run/projection.js +23 -23
  487. package/dist/run/reclaim.d.ts +6 -0
  488. package/dist/run/reclaim.js +15 -5
  489. package/dist/run/results.d.ts +5 -5
  490. package/dist/run/run-index.d.ts +9 -7
  491. package/dist/run/run-index.js +24 -25
  492. package/dist/run/run-not-found.d.ts +5 -0
  493. package/dist/run/run-not-found.js +15 -0
  494. package/dist/run/run.d.ts +7 -4
  495. package/dist/run/run.js +10 -6
  496. package/dist/run/sandbox-receipts.d.ts +5 -5
  497. package/dist/run/sandbox-receipts.js +6 -6
  498. package/dist/run/shared-world-evidence.d.ts +67 -66
  499. package/dist/run/shared-world-evidence.js +4 -4
  500. package/dist/run/shared-world-shape.d.ts +3 -3
  501. package/dist/run/shared-world-shape.js +16 -16
  502. package/dist/run/stats.d.ts +17 -11
  503. package/dist/run/stats.js +124 -66
  504. package/dist/run/status.d.ts +21 -32
  505. package/dist/run/status.js +34 -33
  506. package/dist/run/stored-runs.js +2 -1
  507. package/dist/run/stream-shape.js +1 -1
  508. package/dist/run/streams.d.ts +29 -22
  509. package/dist/run/study-provenance.d.ts +47 -0
  510. package/dist/run/study-provenance.js +63 -0
  511. package/dist/run/study-result.d.ts +16 -0
  512. package/dist/run/study-result.js +9 -0
  513. package/dist/run/terminal-contract.d.ts +5 -5
  514. package/dist/run/terminal-contract.js +4 -4
  515. package/dist/run/text.d.ts +2 -0
  516. package/dist/run/text.js +4 -0
  517. package/dist/run/transient-comms-secrets.d.ts +5 -0
  518. package/dist/run/transient-comms-secrets.js +12 -0
  519. package/dist/run-lab.d.ts +40 -38
  520. package/dist/run-lab.js +42 -40
  521. package/dist/study/convert.d.ts +33 -0
  522. package/dist/study/convert.js +432 -0
  523. package/dist/study/field-paths.d.ts +12 -0
  524. package/dist/study/field-paths.js +126 -0
  525. package/dist/study/files.d.ts +26 -0
  526. package/dist/study/files.js +43 -0
  527. package/dist/study/migrate.d.ts +48 -0
  528. package/dist/study/migrate.js +408 -0
  529. package/dist/study/owned-files.d.ts +38 -0
  530. package/dist/study/owned-files.js +182 -0
  531. package/dist/subject/clone.d.ts +1 -1
  532. package/dist/subject/desktop-cli.d.ts +2 -2
  533. package/dist/subject/desktop-cli.js +3 -3
  534. package/dist/subject/local-tree-archive.d.ts +1 -1
  535. package/dist/subject/local-tree-archive.js +5 -5
  536. package/dist/subject/local-tree.d.ts +3 -3
  537. package/dist/subject/local-tree.js +1 -1
  538. package/dist/subject/node-bootstrap.d.ts +1 -1
  539. package/dist/subject/node-bootstrap.js +4 -4
  540. package/dist/subject/runtime.js +10 -11
  541. package/dist/subject/serve.d.ts +1 -1
  542. package/dist/subject/serve.js +4 -4
  543. package/dist/subject/state.d.ts +1 -1
  544. package/dist/subject/steps.d.ts +8 -8
  545. package/dist/subject/steps.js +7 -7
  546. package/dist/substrates/command-failure.d.ts +3 -3
  547. package/dist/substrates/command-failure.js +3 -3
  548. package/dist/substrates/detached.d.ts +6 -6
  549. package/dist/substrates/detached.js +7 -7
  550. package/dist/substrates/e2b/cdp-probe.d.ts +11 -11
  551. package/dist/substrates/e2b/cdp-probe.js +15 -18
  552. package/dist/substrates/e2b/desktop-browser.d.ts +5 -5
  553. package/dist/substrates/e2b/desktop-browser.js +12 -12
  554. package/dist/substrates/e2b/desktop-cdp.d.ts +15 -15
  555. package/dist/substrates/e2b/desktop-cdp.js +11 -11
  556. package/dist/substrates/e2b/desktop-executor.d.ts +1 -1
  557. package/dist/substrates/e2b/desktop-executor.js +1 -1
  558. package/dist/substrates/e2b/desktop-geometry.d.ts +6 -6
  559. package/dist/substrates/e2b/desktop-geometry.js +9 -9
  560. package/dist/substrates/e2b/desktop-media.d.ts +1 -1
  561. package/dist/substrates/e2b/desktop-media.js +3 -3
  562. package/dist/substrates/e2b/desktop-screenshot-cleanup.d.ts +3 -3
  563. package/dist/substrates/e2b/desktop-screenshot-cleanup.js +3 -3
  564. package/dist/substrates/e2b/sandbox.d.ts +1 -1
  565. package/dist/substrates/e2b/sandbox.js +2 -2
  566. package/dist/substrates/e2b/sdk.d.ts +11 -11
  567. package/dist/substrates/e2b/sdk.js +8 -8
  568. package/dist/substrates/local/runtime-host.d.ts +2 -0
  569. package/dist/substrates/local/runtime-host.js +6 -0
  570. package/dist/tui/actions.d.ts +8 -6
  571. package/dist/tui/actions.js +31 -22
  572. package/dist/tui/contract.d.ts +16 -16
  573. package/dist/tui/contract.js +10 -10
  574. package/dist/tui/launch.d.ts +4 -4
  575. package/dist/tui/launch.js +18 -19
  576. package/dist/tui/project.js +5 -5
  577. package/dist/tui-app.js +83 -83
  578. package/dist/verify/actor.d.ts +14 -14
  579. package/dist/verify/actor.js +45 -45
  580. package/dist/verify/artifacts.d.ts +3 -3
  581. package/dist/verify/artifacts.js +6 -6
  582. package/dist/verify/context-growth.d.ts +9 -0
  583. package/dist/verify/context-growth.js +62 -0
  584. package/dist/verify/costs.d.ts +7 -7
  585. package/dist/verify/costs.js +9 -9
  586. package/dist/verify/liveness.d.ts +1 -1
  587. package/dist/verify/liveness.js +4 -1
  588. package/dist/verify/rerun.d.ts +1 -1
  589. package/dist/verify/rerun.js +1 -1
  590. package/dist/verify/shared-world-concurrent.d.ts +2 -2
  591. package/dist/verify/shared-world-concurrent.js +79 -76
  592. package/dist/verify/shared-world.d.ts +2 -2
  593. package/dist/verify/shared-world.js +18 -18
  594. package/dist/verify/subject.d.ts +4 -4
  595. package/dist/verify/subject.js +18 -18
  596. package/dist/verify/verify.js +98 -49
  597. package/docs/README.md +26 -33
  598. package/docs/architecture/actor-contract.md +105 -98
  599. package/docs/architecture/desktop-sessions.md +14 -14
  600. package/docs/architecture/external-public-shared-world.md +66 -59
  601. package/docs/architecture/github-feedback-loop.md +1 -4
  602. package/docs/architecture/guest-desktop.md +2 -2
  603. package/docs/architecture/observer.md +37 -37
  604. package/docs/architecture/restricted-codex-analysis.md +70 -30
  605. package/docs/architecture/serve.md +34 -37
  606. package/docs/architecture/state-driven-executor.md +55 -59
  607. package/docs/architecture/task-protocol-support.md +7 -9
  608. package/docs/architecture/{terminal-product-lane.md → terminal-product-route.md} +83 -115
  609. package/docs/contracts/README.md +24 -0
  610. package/docs/contracts/adapter-admission.md +3 -3
  611. package/docs/contracts/adapter-fixtures.md +2 -5
  612. package/docs/contracts/core.md +1 -3
  613. package/docs/contracts/errors.md +62 -0
  614. package/docs/contracts/feedback.md +8 -9
  615. package/docs/contracts/policy.md +7 -12
  616. package/docs/contracts/run-bundle.md +54 -51
  617. package/docs/contracts/schemas.md +505 -390
  618. package/docs/contracts/study-analysis.md +26 -2
  619. package/docs/contracts/study-costs.md +11 -7
  620. package/docs/decisions/0001-run-bundle-is-the-source-of-truth.md +1 -1
  621. package/docs/decisions/0002-observer-is-one-self-contained-file.md +2 -2
  622. package/docs/decisions/0003-contained-paths-and-cleanup-authority.md +3 -3
  623. package/docs/decisions/0004-participant-desktops-stay-in-the-route.md +2 -1
  624. package/docs/principles/actor-fidelity.md +4 -4
  625. package/docs/principles/engineering.md +3 -3
  626. package/docs/principles/invariants-and-defaults.md +38 -38
  627. package/docs/principles/self-driving-harness.md +1 -5
  628. package/docs/principles/three-roles.md +1 -1
  629. package/docs/product/automatic-analysis.md +8 -7
  630. package/examples/participant/README.md +5 -5
  631. package/examples/participant/run.mjs +11 -10
  632. package/examples/scorer/README.md +3 -3
  633. package/examples/scorer/run.mjs +11 -12
  634. package/package.json +16 -17
  635. package/skills/humanish/SKILL.md +63 -60
  636. package/skills/humanish/agents/openai.yaml +1 -1
  637. package/AGENTS.md +0 -99
  638. package/CONTRIBUTING.md +0 -148
  639. package/dist/actors/codex/qualified-versions.d.ts +0 -45
  640. package/dist/actors/codex/qualified-versions.js +0 -87
  641. package/dist/cli/commands/lab.d.ts +0 -3
  642. package/dist/cli/commands/lab.js +0 -193
  643. package/dist/deprecated.d.ts +0 -90
  644. package/dist/deprecated.js +0 -106
  645. package/dist/lab/bag-overrides.d.ts +0 -18
  646. package/dist/lab/bag-overrides.js +0 -121
  647. package/dist/observer/static.d.ts +0 -39
  648. package/dist/observer/static.js +0 -369
  649. package/dist/routes/computer-use/legacy-lane-spec.d.ts +0 -62
  650. package/dist/routes/computer-use/legacy-lane-spec.js +0 -39
  651. package/docs/architecture/comms-inbox.md +0 -122
  652. package/docs/architecture/desktop-recording.md +0 -80
  653. package/docs/architecture/local-browser-runtime.md +0 -178
  654. package/docs/architecture/observer-review.md +0 -144
  655. package/docs/architecture/participant-media.md +0 -90
  656. package/docs/architecture/project-layout.md +0 -62
  657. package/docs/architecture/real-email-receiving.md +0 -136
  658. package/docs/assets/humanish-drawdb-hero.png +0 -0
  659. package/docs/assets/humanish-observer-hero.png +0 -0
  660. package/docs/goals/current.md +0 -207
  661. package/docs/product/lobby-trivia-3player-external-public.md +0 -77
  662. package/docs/product/open-source-install-experience.md +0 -240
  663. package/docs/ramp/README.md +0 -294
  664. package/docs/release/open-source-readiness.md +0 -222
  665. package/docs/release/public-readiness-standard.md +0 -210
  666. package/docs/roadmap/world-class-open-source-v0.md +0 -311
  667. /package/dist/routes/computer-use/{fanout-lanes.d.ts → fanout-records.d.ts} +0 -0
  668. /package/dist/routes/shared-world/{seat-records.d.ts → bundle-records.d.ts} +0 -0
package/dist/run/stats.js CHANGED
@@ -3,14 +3,12 @@
3
3
  // counts as unknown and never as zero, and every rate has a denominator next to it.
4
4
  import path from "node:path";
5
5
  import { readRunIndex } from "./run-index.js";
6
- import { addStudyCosts, emptyStudyCosts, readStudyCosts, } from "./costs.js";
6
+ import { addCostTotals, emptyCostTotals, readCostTotals, } from "./costs.js";
7
7
  import { round6 } from "./pricing.js";
8
- const STATS_SCHEMA = "humanish.stats.v1";
9
- const STATS_NOTE = "Every dollar figure is a retained rate-table estimate, never a provider charge. " +
10
- "Known spend includes participant/desktop estimates and all distinct recorded analysis attempts; reuse is counted once. " +
11
- "Unknown amounts are excluded, not $0. Missing historical attempts cannot be reconstructed. " +
12
- "Analysis is attributed to its run's start date, including later reruns. " +
13
- "JSON estimatedSpendUsd and medianCostUsd retain their participant/desktop-only meaning; costs includes analysis.";
8
+ import { plural } from "./text.js";
9
+ const STATS_SCHEMA = "humanish.stats.v2";
10
+ // docs/contracts/study-costs.md holds the accounting rules this sentence summarizes.
11
+ const STATS_NOTE = "Dollar figures are estimates from humanish's rate table, never provider charges, and a cost humanish does not know is left out of every total.";
14
12
  function median(values) {
15
13
  if (values.length === 0)
16
14
  return undefined;
@@ -28,15 +26,26 @@ function addParticipants(into, entry) {
28
26
  into.reachedGoal += entry.participants.reachedGoal;
29
27
  into.reportedFriction += entry.participants.reportedFriction ?? 0;
30
28
  }
29
+ /**
30
+ * A run's participant and desktop estimate: its recorded figure, or $0 for a dry run that records
31
+ * none, since a dry run makes no model request and creates no desktop. Undefined when the cost is
32
+ * unknown, including a dry run that records an unknown (null) figure.
33
+ */
34
+ function runEstimateUsd(entry) {
35
+ const usd = entry.estimatedCostUsd;
36
+ if (typeof usd === "number" && Number.isFinite(usd) && usd >= 0)
37
+ return usd;
38
+ return usd === undefined && entry.mode === "dry-run" ? 0 : undefined;
39
+ }
31
40
  function entryTime(entry) {
32
41
  return entry.startedAt ?? entry.completedAt ?? entry.updatedAt;
33
42
  }
34
- function addToLabRow(labs, entry, priced, costs) {
35
- const labId = entry.lab?.id ?? "(no lab)";
43
+ function addToLabRow(labs, entry, runUsd, costs) {
44
+ const labId = entry.study?.id ?? "(no study)";
36
45
  let row = labs.get(labId);
37
46
  if (row === undefined) {
38
47
  row = {
39
- lab: labId,
48
+ study: labId,
40
49
  runs: 0,
41
50
  live: 0,
42
51
  dryRun: 0,
@@ -47,7 +56,7 @@ function addToLabRow(labs, entry, priced, costs) {
47
56
  unpricedRuns: 0,
48
57
  participants: emptyParticipants(),
49
58
  durations: [],
50
- costs: emptyStudyCosts(),
59
+ costs: emptyCostTotals(),
51
60
  runCosts: [],
52
61
  };
53
62
  labs.set(labId, row);
@@ -64,14 +73,14 @@ function addToLabRow(labs, entry, priced, costs) {
64
73
  }
65
74
  if (entry.mode === "live" && entry.durationMs !== undefined)
66
75
  row.durations.push(entry.durationMs);
67
- if (priced)
68
- row.runCosts.push(entry.estimatedCostUsd);
69
- else
76
+ if (runUsd === undefined)
70
77
  row.unpricedRuns += 1;
78
+ else
79
+ row.runCosts.push(runUsd);
71
80
  addParticipants(row.participants, entry);
72
- addStudyCosts(row.costs, costs);
81
+ addCostTotals(row.costs, costs);
73
82
  }
74
- function addToDayRow(days, entry, priced, costs) {
83
+ function addToDayRow(days, entry, runUsd, costs) {
75
84
  const at = entryTime(entry);
76
85
  const day = at === undefined ? "(undated)" : at.slice(0, 10);
77
86
  let dayRow = days.get(day);
@@ -82,18 +91,18 @@ function addToDayRow(days, entry, priced, costs) {
82
91
  live: 0,
83
92
  estimatedSpendUsd: 0,
84
93
  unpricedRuns: 0,
85
- costs: emptyStudyCosts(),
94
+ costs: emptyCostTotals(),
86
95
  };
87
96
  days.set(day, dayRow);
88
97
  }
89
98
  dayRow.runs += 1;
90
99
  if (entry.mode === "live")
91
100
  dayRow.live += 1;
92
- if (priced)
93
- dayRow.estimatedSpendUsd += entry.estimatedCostUsd;
94
- else
101
+ if (runUsd === undefined)
95
102
  dayRow.unpricedRuns += 1;
96
- addStudyCosts(dayRow.costs, costs);
103
+ else
104
+ dayRow.estimatedSpendUsd += runUsd;
105
+ addCostTotals(dayRow.costs, costs);
97
106
  }
98
107
  export async function computeStats(cwdInput, options = {}) {
99
108
  const cwd = path.resolve(cwdInput);
@@ -127,7 +136,7 @@ export async function computeStats(cwdInput, options = {}) {
127
136
  })),
128
137
  ];
129
138
  const selected = entries.filter((entry) => {
130
- if (options.lab !== undefined && entry.lab?.id !== options.lab)
139
+ if (options.lab !== undefined && entry.study?.id !== options.lab)
131
140
  return false;
132
141
  if (sinceMs !== undefined) {
133
142
  const at = entryTime(entry);
@@ -148,15 +157,15 @@ export async function computeStats(cwdInput, options = {}) {
148
157
  unpricedRuns: 0,
149
158
  participants: emptyParticipants(),
150
159
  verdicts: {},
151
- costs: emptyStudyCosts(),
160
+ costs: emptyCostTotals(),
152
161
  };
153
162
  const labs = new Map();
154
163
  const days = new Map();
155
164
  const costsByRun = [];
156
165
  for (const entry of selected) {
157
- const accounting = await readStudyCosts(cwd, entry);
166
+ const accounting = await readCostTotals(cwd, entry);
158
167
  costsByRun.push(accounting);
159
- addStudyCosts(totals.costs, accounting.costs);
168
+ addCostTotals(totals.costs, accounting.costs);
160
169
  totals.runs += 1;
161
170
  if (entry.mode === "live")
162
171
  totals.live += 1;
@@ -164,18 +173,16 @@ export async function computeStats(cwdInput, options = {}) {
164
173
  totals.dryRun += 1;
165
174
  if (entry.liveness === "running")
166
175
  totals.running += 1;
167
- const priced = typeof entry.estimatedCostUsd === "number" &&
168
- Number.isFinite(entry.estimatedCostUsd) &&
169
- entry.estimatedCostUsd >= 0;
170
- if (priced)
171
- totals.estimatedSpendUsd += entry.estimatedCostUsd;
172
- else
176
+ const runUsd = runEstimateUsd(entry);
177
+ if (runUsd === undefined)
173
178
  totals.unpricedRuns += 1;
179
+ else
180
+ totals.estimatedSpendUsd += runUsd;
174
181
  addParticipants(totals.participants, entry);
175
182
  if (entry.verdict !== undefined)
176
183
  totals.verdicts[entry.verdict] = (totals.verdicts[entry.verdict] ?? 0) + 1;
177
- addToLabRow(labs, entry, priced, accounting.costs);
178
- addToDayRow(days, entry, priced, accounting.costs);
184
+ addToLabRow(labs, entry, runUsd, accounting.costs);
185
+ addToDayRow(days, entry, runUsd, accounting.costs);
179
186
  }
180
187
  const labRows = [...labs.values()]
181
188
  .map(({ durations, runCosts, ...row }) => ({
@@ -186,15 +193,15 @@ export async function computeStats(cwdInput, options = {}) {
186
193
  ...(runCosts.length === 0 ? {} : { medianCostUsd: round6(median(runCosts)) }),
187
194
  costSamples: runCosts.length,
188
195
  }))
189
- .sort((a, b) => b.runs - a.runs || a.lab.localeCompare(b.lab));
196
+ .sort((a, b) => b.runs - a.runs || a.study.localeCompare(b.study));
190
197
  return {
191
198
  schema: STATS_SCHEMA,
192
199
  ok: true,
193
200
  cwd,
194
201
  ...(options.since === undefined ? {} : { since: options.since }),
195
- ...(options.lab === undefined ? {} : { lab: options.lab }),
202
+ ...(options.lab === undefined ? {} : { study: options.lab }),
196
203
  totals: { ...totals, estimatedSpendUsd: round6(totals.estimatedSpendUsd) },
197
- labs: labRows,
204
+ studies: labRows,
198
205
  days: [...days.values()]
199
206
  .map((row) => ({ ...row, estimatedSpendUsd: round6(row.estimatedSpendUsd) }))
200
207
  .sort((a, b) => a.day.localeCompare(b.day)),
@@ -212,47 +219,98 @@ function knownMoney(value) {
212
219
  function minutes(ms) {
213
220
  return `${(ms / 60_000).toFixed(1)}m`;
214
221
  }
222
+ /**
223
+ * Whether every selected run is a dry run whose accounting is a complete $0: no recorded figure,
224
+ * no incomplete estimate and no analysis attempt. Only then does the one-line report hold.
225
+ */
226
+ function onlyFreeDryRuns(t) {
227
+ return (t.runs > 0 &&
228
+ t.runs === t.dryRun &&
229
+ t.costs.estimatedTotalUsd === 0 &&
230
+ t.costs.incompleteRunEstimates === 0 &&
231
+ t.costs.analysisAttempts === 0);
232
+ }
233
+ /** The run counts, with dry runs on their own line. */
234
+ function runCountLines(t) {
235
+ if (t.runs === 0)
236
+ return ["no runs yet; start one with humanish run first-run"];
237
+ if (onlyFreeDryRuns(t))
238
+ return [`${plural(t.dryRun, "dry run")} ($0); no live runs yet`];
239
+ const running = t.running > 0 ? ` (${t.running} still running)` : "";
240
+ return [`live runs: ${t.live}${running}`, ...(t.dryRun > 0 ? [`dry runs: ${t.dryRun}`] : [])];
241
+ }
242
+ /** Spend, analysis, participants and verdicts across the selected live runs. */
243
+ function totalsLines(t) {
244
+ const c = t.costs;
245
+ const incomplete = c.incompleteRunEstimates > 0
246
+ ? `; ${plural(c.incompleteRunEstimates, "run")} with incomplete accounting`
247
+ : "";
248
+ const unpriced = c.analysisUnpricedAttempts > 0 || c.analysisUnresolvedAttempts > 0
249
+ ? `; ${c.analysisUnpricedAttempts} unpriced, ${c.analysisUnresolvedAttempts} unresolved`
250
+ : "";
251
+ const verdicts = Object.entries(t.verdicts).map(([verdict, count]) => `${verdict} ${count}`);
252
+ return [
253
+ `known estimated spend: ${knownMoney(c.estimatedTotalUsd)}`,
254
+ `participants and desktops: ${knownMoney(c.runEstimatedUsd)}${incomplete}`,
255
+ c.analysisAttempts === 0
256
+ ? "analysis: none recorded"
257
+ : `analysis: ${knownMoney(c.analysisEstimatedUsd)} over ${plural(c.analysisAttempts, "recorded attempt")}${unpriced}`,
258
+ ...(c.analysisHistoryUncertainRuns > 0
259
+ ? [
260
+ `analysis history: ${plural(c.analysisHistoryUncertainRuns, "run")} missing or uncertain; --json lists each run`,
261
+ ]
262
+ : []),
263
+ ...(t.participants.total > 0
264
+ ? [
265
+ `participants: ${t.participants.reachedGoal} of ${t.participants.total} reached the goal, ${t.participants.reportedFriction} reported friction`,
266
+ ]
267
+ : []),
268
+ ...(verdicts.length > 0 ? [`verdicts: ${verdicts.join(", ")}`] : []),
269
+ ];
270
+ }
271
+ function dayLine(row) {
272
+ return `- ${row.day}: ${plural(row.runs, "run")}, ${row.live} live, known study spend ${knownMoney(row.costs.estimatedTotalUsd)}${unpricedTail(row.unpricedRuns, row.costs.analysisUnpricedAttempts)}`;
273
+ }
274
+ /** "; 2 unpriced runs, 1 unpriced analysis", or nothing when both are zero. */
275
+ function unpricedTail(runs, analyses) {
276
+ if (runs === 0 && analyses === 0)
277
+ return "";
278
+ return `; ${plural(runs, "unpriced run")}, ${plural(analyses, "unpriced analysis", "unpriced analyses")}`;
279
+ }
215
280
  export function formatStatsHuman(result) {
216
281
  if (!result.ok)
217
- return `${result.error.code}: ${result.error.message}\n`;
282
+ return { error: result.error };
218
283
  const t = result.totals;
219
284
  const scope = [
220
- result.lab === undefined ? undefined : `lab ${result.lab}`,
285
+ result.study === undefined ? undefined : `lab ${result.study}`,
221
286
  result.since === undefined ? undefined : `since ${result.since}`,
222
287
  ].filter((part) => part !== undefined);
223
288
  const lines = [
224
289
  `humanish stats${scope.length === 0 ? "" : ` (${scope.join(", ")})`}`,
225
- `runs: ${t.runs} (${t.live} live, ${t.dryRun} dry-run${t.running > 0 ? `, ${t.running} running` : ""})`,
226
- `known estimated spend: ${knownMoney(t.costs.estimatedTotalUsd)}`,
227
- `participants + desktops: ${knownMoney(t.costs.runEstimatedUsd)}; ${t.costs.incompleteRunEstimates} run(s) with incomplete accounting`,
228
- `analysis: ${knownMoney(t.costs.analysisEstimatedUsd)} over ${t.costs.analysisAttempts} recorded attempt(s); ${t.costs.analysisUnpricedAttempts} unpriced, ${t.costs.analysisUnresolvedAttempts} unresolved`,
229
- `analysis history: ${t.costs.analysisHistoryUncertainRuns} run(s) missing or uncertain; use --json for per-run accounting`,
230
- `participants: ${t.participants.reachedGoal}/${t.participants.total} recorded goal completions, ${t.participants.reportedFriction} reported friction`,
231
- `verdicts: ${Object.entries(t.verdicts)
232
- .map(([verdict, count]) => `${verdict} ${count}`)
233
- .join(", ") || "none recorded"}`,
290
+ ...runCountLines(t),
234
291
  ];
235
- if (result.labs.length > 0) {
236
- lines.push("", "per lab:");
237
- for (const row of result.labs) {
238
- const rate = row.passRate === undefined ? "no verdicts" : `${row.passed}/${row.judged} pass`;
239
- const duration = row.medianDurationMs === undefined
240
- ? "no timed live runs"
241
- : `median ${minutes(row.medianDurationMs)} over ${row.durationSamples}`;
242
- const cost = row.medianCostUsd === undefined
243
- ? "no priced participant/desktop runs"
244
- : `participant/desktop median ${money(row.medianCostUsd)} over ${row.costSamples}`;
245
- lines.push(`- ${row.lab}: ${row.runs} run(s), ${row.live} live; ${rate}; ${duration}; known study spend ${knownMoney(row.costs.estimatedTotalUsd)}; ${cost}; ${row.unpricedRuns} unpriced runs, ${row.costs.analysisUnpricedAttempts} unpriced analyses`);
246
- }
247
- }
248
- if (result.days.length > 0) {
249
- lines.push("", "by day:");
250
- for (const row of result.days) {
251
- lines.push(`- ${row.day}: ${row.runs} run(s), ${row.live} live, known study spend ${knownMoney(row.costs.estimatedTotalUsd)}, ${row.unpricedRuns} unpriced runs, ${row.costs.analysisUnpricedAttempts} unpriced analyses`);
252
- }
292
+ // Free dry runs alone have no spend, outcome or duration to report. Anything else, an unreadable
293
+ // directory or a dry run that records a cost included, gets the full report.
294
+ const reportable = t.runs > 0 && !onlyFreeDryRuns(t);
295
+ if (reportable) {
296
+ lines.push(...totalsLines(t));
297
+ if (result.studies.length > 0)
298
+ lines.push("", "per lab:", ...result.studies.map((row) => {
299
+ const rate = row.passRate === undefined ? "no verdicts" : `${row.passed} of ${row.judged} passed`;
300
+ const duration = row.medianDurationMs === undefined
301
+ ? "no timed live runs"
302
+ : `median ${minutes(row.medianDurationMs)} over ${row.durationSamples}`;
303
+ const cost = row.medianCostUsd === undefined
304
+ ? "no priced participant/desktop runs"
305
+ : `participant/desktop median ${money(row.medianCostUsd)} over ${row.costSamples}`;
306
+ return `- ${row.study}: ${plural(row.runs, "run")}, ${row.live} live; ${rate}; ${duration}; known study spend ${knownMoney(row.costs.estimatedTotalUsd)}; ${cost}${unpricedTail(row.unpricedRuns, row.costs.analysisUnpricedAttempts)}`;
307
+ }));
308
+ if (result.days.length > 0)
309
+ lines.push("", "by day:", ...result.days.map(dayLine));
253
310
  }
254
311
  if (result.unreadable.length > 0)
255
312
  lines.push("", `unreadable run directories: ${result.unreadable.join(", ")}`);
256
- lines.push("", result.note);
313
+ if (reportable)
314
+ lines.push("", result.note);
257
315
  return `${lines.join("\n")}\n`;
258
316
  }
@@ -1,4 +1,5 @@
1
1
  import type { RunBundle } from "./bundle.js";
2
+ import { type RunStudyProvenance } from "./study-provenance.js";
2
3
  import { type PreparedOutputRoot } from "./contained-output.js";
3
4
  import type { ExecutionOutcome } from "./judge.js";
4
5
  export declare const RUN_STATUS_SCHEMA = "humanish.run-status.v1";
@@ -7,21 +8,14 @@ export declare const RUN_STATUS_FILE = "status.json";
7
8
  /** How often a live run touches `updatedAt`. */
8
9
  export declare const RUN_STATUS_TOUCH_MS = 5000;
9
10
  /**
10
- * A `running` record whose `updatedAt` is older than this is INTERRUPTED, not alive: the process
11
+ * A `running` record whose `updatedAt` is older than this is interrupted, not alive: the process
11
12
  * died without finalizing (a dropped SSH, a killed terminal, a crash). Three touch intervals of
12
13
  * slack so an ordinary scheduling hiccup or a slow disk never mislabels a healthy run.
13
14
  */
14
15
  export declare const RUN_STATUS_STALE_MS: number;
15
- /** Which manifest a run came from, when it came from one. */
16
- export interface RunLabProvenance {
17
- /** The lab id as declared in its manifest (`config.id`). */
18
- id: string;
19
- /** Repo-relative manifest path, when the run came from a file on disk. */
20
- path?: string;
21
- /** `committed` = humanish/labs, `ignored` = a local overlay, `explicit` = a path the operator passed. */
22
- origin?: "committed" | "ignored" | "explicit";
23
- }
24
- type RunStatusState = "running" | "finished";
16
+ type RunStatusState = "running" | "finished" | "interrupted";
17
+ /** The signals the CLI's run handler records when it stops a run. */
18
+ export type RunInterruptSignal = "SIGINT" | "SIGTERM" | "SIGHUP";
25
19
  /** The outcome summary a finalized record carries. Derived from the bundle; never authoritative. */
26
20
  interface RunStatusOutcome {
27
21
  /** `review.verdict` verbatim. */
@@ -47,14 +41,18 @@ export interface RunStatusRecord {
47
41
  runId: string;
48
42
  state: RunStatusState;
49
43
  mode: "dry-run" | "live";
50
- /** Absent when the run did not come from a lab manifest (a library caller, a bare `run`). */
51
- lab?: RunLabProvenance;
44
+ /** Absent when the run did not come from a study file (a library caller, a bare `run`). */
45
+ study?: RunStudyProvenance;
46
+ /** `study`'s value, written beside it until 0.109. Read either through studyProvenanceOf. */
47
+ lab?: RunStudyProvenance;
52
48
  /** The pid that owns the run, for local liveness checks. */
53
49
  pid: number;
54
50
  startedAt: string;
55
51
  /** Refreshed on a fixed cadence while the run is alive; the staleness signal. */
56
52
  updatedAt: string;
57
53
  completedAt?: string;
54
+ /** The signal that stopped the run, on an `interrupted` record. */
55
+ signal?: RunInterruptSignal;
58
56
  outcome?: RunStatusOutcome;
59
57
  }
60
58
  export interface RunStatusHandle {
@@ -64,7 +62,7 @@ export interface RunStatusHandle {
64
62
  * still has a record to classify. */
65
63
  readonly started: Promise<void>;
66
64
  /** Finalize: state `finished`, `completedAt`, and the derived outcome. Stops the cadence.
67
- * Idempotent — a second call is a no-op, so a backend with several exit paths is safe. */
65
+ * Idempotent: a second call is a no-op, so a route with several exit paths is safe. */
68
66
  finish(outcome?: RunStatusOutcome): Promise<void>;
69
67
  /** After finish, add the result's ok and execution outcome to the finished record, so status.json
70
68
  * and the result agree. Before finish it does nothing. */
@@ -72,19 +70,25 @@ export interface RunStatusHandle {
72
70
  ok: boolean;
73
71
  execution: ExecutionOutcome;
74
72
  }): Promise<void>;
73
+ /** The process is being stopped by `signal`: state `interrupted`, `completedAt` and the signal.
74
+ * It stops the cadence and makes a later finish or settle a no-op, so the route cannot write
75
+ * `running` or `finished` over it. When the run had finished it writes nothing, waits for the
76
+ * writes already queued and resolves false. */
77
+ interrupt(signal: RunInterruptSignal): Promise<boolean>;
75
78
  }
76
79
  export interface BeginRunStatusOptions {
77
80
  runId: string;
78
81
  mode: "dry-run" | "live";
79
- lab?: RunLabProvenance;
82
+ lab?: RunStudyProvenance | undefined;
80
83
  }
81
84
  /**
82
85
  * Start a run's status record and keep it fresh. Fire-and-forget by design: a status write that
83
86
  * fails must never fail the run it describes, so every write swallows its error. The interval is
84
- * `unref`'d — this file can never be the reason a process stays alive.
87
+ * `unref`'d, so this file can never be the reason a process stays alive.
85
88
  */
86
89
  export declare function beginRunStatus(runPaths: PreparedOutputRoot, options: BeginRunStatusOptions): RunStatusHandle;
87
- /** The three ways a run reads from disk. `interrupted` is a `running` record gone stale. */
90
+ /** The three ways a run reads from disk. `interrupted` is a record its stopped process wrote, or a
91
+ * `running` record gone stale. */
88
92
  export type RunLiveness = "running" | "interrupted" | "finished";
89
93
  /**
90
94
  * Classify a status record. Pure, so the TUI, the CLI and tests share one definition of "alive".
@@ -93,19 +97,4 @@ export type RunLiveness = "running" | "interrupted" | "finished";
93
97
  export declare function classifyRunStatus(record: Pick<RunStatusRecord, "state" | "updatedAt">, nowMs: number, staleMs?: number): RunLiveness;
94
98
  /** Shape guard for a record read off disk. Unknown extra fields are tolerated (additive contract). */
95
99
  export declare function isRunStatusRecord(value: unknown): value is RunStatusRecord;
96
- /**
97
- * The legacy bridge: infer a lab id for a bundle written BEFORE this contract, where the only
98
- * attribution was the `lab:<id>` convention on persona/scenario source strings. Deliberately
99
- * conservative — it reads the convention and nothing else, and a `lab:` prefix with an empty
100
- * remainder is not an id. Ids may contain colons (the removed meta-lab wrote `oss:meta`), so
101
- * only the FIRST segment is stripped. Returns undefined when the bundle carries no such marker.
102
- */
103
- export declare function inferLegacyLabId(bundle: {
104
- persona?: {
105
- source?: string;
106
- };
107
- scenario?: {
108
- source?: string;
109
- };
110
- }): string | undefined;
111
100
  export {};
@@ -9,6 +9,7 @@
9
9
  // Public safety: it holds only the run id, the lab id/path/origin (the strings `humanish lab list`
10
10
  // prints), the mode, a local pid and timestamps. It holds no hostname or user/path identity: an
11
11
  // operator may share the run directory, so a share-safety gate must have nothing to strip here.
12
+ import { isProvenanceField, studyFields } from "./study-provenance.js";
12
13
  import { writeContainedOutputFile } from "./contained-output.js";
13
14
  import { redactText } from "../evidence/redaction.js";
14
15
  export const RUN_STATUS_SCHEMA = "humanish.run-status.v1";
@@ -17,11 +18,12 @@ export const RUN_STATUS_FILE = "status.json";
17
18
  /** How often a live run touches `updatedAt`. */
18
19
  export const RUN_STATUS_TOUCH_MS = 5_000;
19
20
  /**
20
- * A `running` record whose `updatedAt` is older than this is INTERRUPTED, not alive: the process
21
+ * A `running` record whose `updatedAt` is older than this is interrupted, not alive: the process
21
22
  * died without finalizing (a dropped SSH, a killed terminal, a crash). Three touch intervals of
22
23
  * slack so an ordinary scheduling hiccup or a slow disk never mislabels a healthy run.
23
24
  */
24
25
  export const RUN_STATUS_STALE_MS = RUN_STATUS_TOUCH_MS * 3;
26
+ const RUN_INTERRUPT_SIGNALS = ["SIGINT", "SIGTERM", "SIGHUP"];
25
27
  /** The outcome a finalized status record carries, read from the bundle that was just written. */
26
28
  export function runStatusOutcome(bundle) {
27
29
  return {
@@ -45,7 +47,7 @@ export function runStatusOutcome(bundle) {
45
47
  /**
46
48
  * Start a run's status record and keep it fresh. Fire-and-forget by design: a status write that
47
49
  * fails must never fail the run it describes, so every write swallows its error. The interval is
48
- * `unref`'d — this file can never be the reason a process stays alive.
50
+ * `unref`'d, so this file can never be the reason a process stays alive.
49
51
  */
50
52
  export function beginRunStatus(runPaths, options) {
51
53
  const iso = () => new Date().toISOString();
@@ -55,7 +57,7 @@ export function beginRunStatus(runPaths, options) {
55
57
  runId: options.runId,
56
58
  state: "running",
57
59
  mode: options.mode,
58
- ...(options.lab === undefined ? {} : { lab: options.lab }),
60
+ ...studyFields(options.lab),
59
61
  pid: process.pid,
60
62
  startedAt,
61
63
  updatedAt: startedAt,
@@ -102,12 +104,16 @@ export function beginRunStatus(runPaths, options) {
102
104
  return;
103
105
  // The record is public-safe by construction, so each message passes the shape redaction
104
106
  // again even though the routes scrubbed it.
107
+ const redacted = (failure) => ({
108
+ kind: failure.kind,
109
+ message: redactText(failure.message),
110
+ });
105
111
  const execution = {
106
112
  succeeded: result.execution.succeeded,
107
- failures: result.execution.failures.map((failure) => ({
108
- kind: failure.kind,
109
- message: redactText(failure.message),
110
- })),
113
+ failures: result.execution.failures.map(redacted),
114
+ ...(result.execution.warnings === undefined
115
+ ? {}
116
+ : { warnings: result.execution.warnings.map(redacted) }),
111
117
  };
112
118
  finishedRecord = {
113
119
  ...finishedRecord,
@@ -115,6 +121,19 @@ export function beginRunStatus(runPaths, options) {
115
121
  };
116
122
  await write(finishedRecord);
117
123
  },
124
+ async interrupt(signal) {
125
+ // A finish that has not landed yet is in the chain: wait for it so the process does not
126
+ // exit with `running` on disk.
127
+ if (finished) {
128
+ await writing;
129
+ return false;
130
+ }
131
+ finished = true;
132
+ clearInterval(timer);
133
+ const completedAt = iso();
134
+ await write({ ...base, state: "interrupted", updatedAt: completedAt, completedAt, signal });
135
+ return true;
136
+ },
118
137
  };
119
138
  return handle;
120
139
  }
@@ -125,6 +144,8 @@ export function beginRunStatus(runPaths, options) {
125
144
  export function classifyRunStatus(record, nowMs, staleMs = RUN_STATUS_STALE_MS) {
126
145
  if (record.state === "finished")
127
146
  return "finished";
147
+ if (record.state === "interrupted")
148
+ return "interrupted";
128
149
  const updated = Date.parse(record.updatedAt);
129
150
  if (!Number.isFinite(updated))
130
151
  return "interrupted";
@@ -139,7 +160,10 @@ export function isRunStatusRecord(value) {
139
160
  return false;
140
161
  if (typeof record.runId !== "string" || record.runId === "")
141
162
  return false;
142
- if (record.state !== "running" && record.state !== "finished")
163
+ if (record.state !== "running" && record.state !== "finished" && record.state !== "interrupted")
164
+ return false;
165
+ if (record.signal !== undefined &&
166
+ (typeof record.signal !== "string" || !RUN_INTERRUPT_SIGNALS.includes(record.signal)))
143
167
  return false;
144
168
  if (record.mode !== "dry-run" && record.mode !== "live")
145
169
  return false;
@@ -147,30 +171,7 @@ export function isRunStatusRecord(value) {
147
171
  return false;
148
172
  if (typeof record.startedAt !== "string" || typeof record.updatedAt !== "string")
149
173
  return false;
150
- if (record.lab !== undefined) {
151
- if (record.lab === null || typeof record.lab !== "object")
152
- return false;
153
- if (typeof record.lab.id !== "string")
154
- return false;
155
- }
174
+ if (!isProvenanceField(record.study) || !isProvenanceField(record.lab))
175
+ return false;
156
176
  return true;
157
177
  }
158
- /**
159
- * The legacy bridge: infer a lab id for a bundle written BEFORE this contract, where the only
160
- * attribution was the `lab:<id>` convention on persona/scenario source strings. Deliberately
161
- * conservative — it reads the convention and nothing else, and a `lab:` prefix with an empty
162
- * remainder is not an id. Ids may contain colons (the removed meta-lab wrote `oss:meta`), so
163
- * only the FIRST segment is stripped. Returns undefined when the bundle carries no such marker.
164
- */
165
- export function inferLegacyLabId(bundle) {
166
- for (const source of [bundle.persona?.source, bundle.scenario?.source]) {
167
- if (typeof source !== "string")
168
- continue;
169
- if (!source.startsWith("lab:"))
170
- continue;
171
- const id = source.slice("lab:".length).trim();
172
- if (id !== "")
173
- return id;
174
- }
175
- return undefined;
176
- }
@@ -1,4 +1,5 @@
1
1
  import { lstat, readdir } from "node:fs/promises";
2
+ import { runNotFoundMessage } from "./run-not-found.js";
2
3
  import path from "node:path";
3
4
  import { redactText } from "../evidence/redaction.js";
4
5
  import { bindExistingRunArtifactPaths, RUNS_RELATIVE_ROOT, isSafeRunIdSegment, resolveRunsRoot, validatePreparedRunArtifactPaths, } from "./paths.js";
@@ -66,7 +67,7 @@ export async function cleanupRun(cwdInput, runInput, hooks = {}) {
66
67
  if (!resolved) {
67
68
  return cleanupRefusal(cwd, runInput, checkedAt, {
68
69
  code: "HUMANISH_RUN_NOT_FOUND",
69
- message: `Run not found: ${runInput}`,
70
+ message: await runNotFoundMessage(cwd, runInput),
70
71
  });
71
72
  }
72
73
  const runPaths = resolved;
@@ -140,7 +140,7 @@ export function isRunSimulationStatus(value) {
140
140
  value === "running" ||
141
141
  value === "passed" ||
142
142
  // Participant outcomes (docs/principles/three-roles.md). This runtime allowlist is the actual
143
- // gate — the TS union alone does not validate a bundle read back from disk.
143
+ // gate; the TS union alone does not validate a bundle read back from disk.
144
144
  value === "abandoned" ||
145
145
  value === "incomplete" ||
146
146
  value === "complete" ||