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
@@ -1,4 +1,4 @@
1
- import { describeQualifiedCodexCliVersions } from "../actors/codex/qualified-versions.js";
1
+ import { defaultCodexCliVersion, describeCodexCliAdmission, } from "../actors/codex/codex-admission.js";
2
2
  import { validCodexAnalysisConfig } from "./codex-config.js";
3
3
  import { randomUUID } from "node:crypto";
4
4
  import { lstat, mkdir, realpath, rmdir } from "node:fs/promises";
@@ -10,11 +10,12 @@ import { loadRunBundlePrepared, resolveRunPath } from "../run/locate.js";
10
10
  import { physicalCwdOf, runIdOf, resolvePhysicalCwd, validatePreparedRunRootIdentity, } from "../run/paths.js";
11
11
  import { isRunStatusRecord, RUN_STATUS_FILE } from "../run/status.js";
12
12
  import { captureEvidence, EVIDENCE_LIMITS } from "./evidence.js";
13
- import { pathMissing, readBoundedStudyFile } from "../run/study-files.js";
13
+ import { pathMissing, readBoundedFile } from "../run/evidence-files.js";
14
14
  import { estimateAnalysisAdmission, preferLargerAnalysisOutput, runAnalysis, ANALYSIS_PROMPT_VERSION, } from "./execute.js";
15
- import { appendStudyAnalysisCorrection, assertAnalysisPublicationCapacity, listAnalyses, writeStudyAnalysis, } from "./store.js";
16
- import { beginStudyAnalysisExecution, writeStudyAnalysisExecutionReceipt, } from "./store-executions.js";
17
- import { loadStudyAnalysis } from "./load.js";
15
+ import { appendAnalysisCorrection, assertAnalysisPublicationCapacity, listAnalyses, writeAnalysis, } from "./store.js";
16
+ import { beginAnalysisExecution, writeAnalysisExecutionReceipt } from "./store-executions.js";
17
+ import { keepRejectedAnalysisOutput } from "./diagnostics.js";
18
+ import { loadAnalysis } from "./load.js";
18
19
  import { hashAnalysisValue } from "./validation.js";
19
20
  import { ANALYSIS_CORRECTION_SCHEMA, } from "./types.js";
20
21
  import { RUN_BUNDLE_FILE } from "../run/bundle.js";
@@ -42,7 +43,7 @@ const messages = {
42
43
  ANALYSIS_VERIFY_FAILED: "The run must pass verification before analysis.",
43
44
  ANALYSIS_RUN_ACTIVE: "Analysis requires a completed recording. Wait for the study to finish.",
44
45
  ANALYSIS_NO_PARTICIPANTS: "This run contains no participant evidence to analyze.",
45
- ANALYSIS_REQUIRES_LIVE_RUN: "A dry-run proves harness contracts, not participant behavior. Select a completed live study for analysis.",
46
+ ANALYSIS_REQUIRES_LIVE_RUN: "A dry run has no participant behavior to analyze. Select a completed live run.",
46
47
  ANALYSIS_SOURCE_UNAVAILABLE: "The source recording is missing, unsafe, or exceeds the input limit.",
47
48
  ANALYSIS_SOURCE_CHANGED: "The source recording changed during analysis. The result cannot be published against different evidence.",
48
49
  ANALYSIS_BUSY: "Another analysis holds this run's .analysis-lock directory. If it was interrupted, confirm it has stopped before removing that empty directory.",
@@ -55,8 +56,9 @@ const messages = {
55
56
  };
56
57
  const codexRecovery = {
57
58
  analysis_codex_busy: "Another restricted Codex analyst or setup check is active in this process. Wait for it to finish, then explicitly retry.",
58
- analysis_codex_unavailable: `The qualified Codex CLI is unavailable. Install a qualified Codex CLI (${describeQualifiedCodexCliVersions()}) and sign in with a ChatGPT account, then retry --provider codex.`,
59
- analysis_codex_unsupported_version: `Codex account analysis requires a qualified CLI version (${describeQualifiedCodexCliVersions()}). Other versions have not passed this tool-policy contract.`,
59
+ analysis_codex_unavailable: `The Codex CLI is unavailable. Install one (${describeCodexCliAdmission()}) and sign in with a ChatGPT account, then retry --provider codex.`,
60
+ analysis_codex_unsupported_version: `This Codex CLI release is refused: ${describeCodexCliAdmission()}. \`humanish doctor\` names the release it found, why, and the command that replaces it.`,
61
+ analysis_codex_incompatible_release: `This Codex CLI release changed app-server protocol fields humanish reads, so no request was sent; the warnings name each change. Install the last tested release (${defaultCodexCliVersion()}), then retry.`,
60
62
  analysis_codex_unsupported_platform: "This platform has not qualified the restricted Codex account launcher.",
61
63
  analysis_codex_login_required: "Sign in to Codex with a ChatGPT account, then retry humanish analyze --provider codex --rerun.",
62
64
  analysis_codex_unsupported_auth: "Codex analysis requires ChatGPT account authentication; API-key and custom provider authentication are not used as fallbacks.",
@@ -140,7 +142,7 @@ export async function withAnalysisLock(prepared, action) {
140
142
  }
141
143
  /** The completion gate: the run verifies, is live and finished, and has participants. */
142
144
  export async function readCompletedAnalysisSource(cwd, prepared) {
143
- const bytes = await readBoundedStudyFile(prepared, RUN_BUNDLE_FILE, EVIDENCE_LIMITS.sourceBytes);
145
+ const bytes = await readBoundedFile(prepared, RUN_BUNDLE_FILE, EVIDENCE_LIMITS.sourceBytes);
144
146
  if (!bytes)
145
147
  throw new Error("ANALYSIS_SOURCE_UNAVAILABLE");
146
148
  const verified = await verifyRunPrepared(cwd, runIdOf(prepared), prepared);
@@ -151,7 +153,7 @@ export async function readCompletedAnalysisSource(cwd, prepared) {
151
153
  throw new Error("ANALYSIS_NO_PARTICIPANTS");
152
154
  if (loaded.bundle.mode !== "live")
153
155
  throw new Error("ANALYSIS_REQUIRES_LIVE_RUN");
154
- const statusBytes = await readBoundedStudyFile(prepared, RUN_STATUS_FILE, MAX_STATUS_BYTES);
156
+ const statusBytes = await readBoundedFile(prepared, RUN_STATUS_FILE, MAX_STATUS_BYTES);
155
157
  if (!statusBytes) {
156
158
  const missing = await pathMissing(path.join(prepared.physicalRunRoot, RUN_STATUS_FILE)).catch(() => {
157
159
  throw new Error("ANALYSIS_SOURCE_UNAVAILABLE");
@@ -258,9 +260,9 @@ async function publishAttempt(prepared, analysis, result, finalizeExecution) {
258
260
  if (finalizeExecution)
259
261
  await finalizeExecution(analysis);
260
262
  else
261
- await writeStudyAnalysisExecutionReceipt(prepared, analysis);
263
+ await writeAnalysisExecutionReceipt(prepared, analysis);
262
264
  result.executionReceiptPath = path.join(prepared.relativeRunRoot, "analysis-attempts", analysis.id, "receipt.json");
263
- await writeStudyAnalysis(prepared, analysis);
265
+ await writeAnalysis(prepared, analysis);
264
266
  result.artifactPath = path.join(prepared.relativeRunRoot, "analysis", analysis.id, "analysis.json");
265
267
  return true;
266
268
  }
@@ -308,19 +310,36 @@ async function executeAnalysis(attempt) {
308
310
  if (config.provider !== "codex" && !apiKey.trim())
309
311
  return { ...fail(input.runId, false, "ANALYSIS_API_KEY_MISSING"), admission };
310
312
  let finalizeExecution;
313
+ const rejection = {};
311
314
  const analysis = await runAnalysis(input, config, {
312
315
  apiKey,
313
316
  ...(deps.codexProvider === undefined ? {} : { codexProvider: deps.codexProvider }),
314
317
  ...(deps.analysisId === undefined ? {} : { analysisId: deps.analysisId }),
315
318
  beforeDispatch: async (context) => {
316
319
  await deps.beforeDispatch?.(context);
317
- finalizeExecution = await beginStudyAnalysisExecution(prepared, context);
320
+ finalizeExecution = await beginAnalysisExecution(prepared, context);
318
321
  },
319
322
  ...(deps.signal === undefined ? {} : { signal: deps.signal }),
320
323
  ...(deps.onProgress === undefined ? {} : { onProgress: deps.onProgress }),
321
324
  ...(deps.fetch === undefined ? {} : { fetch: deps.fetch }),
325
+ warnings: base.warnings,
326
+ onRejectedOutput: (output) => {
327
+ rejection.output = output;
328
+ },
322
329
  });
323
330
  const result = attemptResult(base, analysis);
331
+ if (rejection.output)
332
+ try {
333
+ result.rejectedOutputPath = await keepRejectedAnalysisOutput(cwd, {
334
+ runId: analysis.runId,
335
+ analysisId: analysis.id,
336
+ model: config.model,
337
+ promptVersion: analysis.promptVersion,
338
+ }, rejection.output);
339
+ }
340
+ catch {
341
+ result.warnings.push("The rejected analyst output could not be kept under .humanish/analysis-diagnostics.");
342
+ }
324
343
  if (!(await publishAttempt(prepared, analysis, result, finalizeExecution)))
325
344
  return {
326
345
  ...result,
@@ -365,7 +384,7 @@ export async function analyzeRun(cwdInput, run, options, deps = {}) {
365
384
  export async function showAnalysis(cwd, run, id) {
366
385
  const prepared = await resolveRunPath(await resolvePhysicalCwd(cwd), run).catch(() => null);
367
386
  return prepared
368
- ? loadStudyAnalysis(prepared, id)
387
+ ? loadAnalysis(prepared, id)
369
388
  : { state: "invalid", analysis: null, corrections: [], warnings: ["ANALYSIS_RUN_NOT_FOUND"] };
370
389
  }
371
390
  export async function correctAnalysis(cwd, run, options) {
@@ -373,7 +392,7 @@ export async function correctAnalysis(cwd, run, options) {
373
392
  if (!prepared)
374
393
  throw new Error("ANALYSIS_RUN_NOT_FOUND");
375
394
  return withAnalysisLock(prepared, async () => {
376
- const loaded = await loadStudyAnalysis(prepared, options.analysisId);
395
+ const loaded = await loadAnalysis(prepared, options.analysisId);
377
396
  const analysis = loaded.analysis;
378
397
  const finding = analysis?.result?.findings.find((item) => item.id === options.findingId);
379
398
  if (loaded.state !== "ready" || !analysis || !finding)
@@ -392,7 +411,7 @@ export async function correctAnalysis(cwd, run, options) {
392
411
  reason: options.reason,
393
412
  replacementClaim: options.replacementClaim ?? null,
394
413
  };
395
- await appendStudyAnalysisCorrection(prepared, correction);
414
+ await appendAnalysisCorrection(prepared, correction);
396
415
  await refreshObserver(cwd, runIdOf(prepared), prepared);
397
416
  return correction;
398
417
  });
@@ -1,9 +1,9 @@
1
1
  import type { LoadedAnalysis } from "./types.js";
2
2
  /** True for the analysis record files, matched by name inside their directories. Any other file
3
3
  * under analysis/ is ordinary evidence and follows the ordinary evidence policy. */
4
- export declare function isStudyAnalysisRecordPath(relativePath: string): boolean;
4
+ export declare function isAnalysisRecordPath(relativePath: string): boolean;
5
5
  /** Check the exact in-memory snapshot being projected; a prior filesystem scan cannot approve a later write. */
6
- export declare function studyAnalysisSharingProblems(loaded: LoadedAnalysis): {
6
+ export declare function analysisSharingProblems(loaded: LoadedAnalysis): {
7
7
  sensitive: boolean;
8
8
  unverified: boolean;
9
9
  };
@@ -1,9 +1,9 @@
1
1
  import { containsSensitive } from "../evidence/redaction.js";
2
- import { AUTOMATIC_ANALYSIS_DIRECTORY, projectAutomaticStudyAnalysisView } from "./job.js";
2
+ import { AUTOMATIC_ANALYSIS_DIRECTORY, projectAutomaticAnalysisView } from "./job.js";
3
3
  import { ANALYSIS_DIRECTORY, ANALYSIS_EXECUTION_DIRECTORY } from "./store.js";
4
4
  /** True for the analysis record files, matched by name inside their directories. Any other file
5
5
  * under analysis/ is ordinary evidence and follows the ordinary evidence policy. */
6
- export function isStudyAnalysisRecordPath(relativePath) {
6
+ export function isAnalysisRecordPath(relativePath) {
7
7
  const parts = relativePath.split("/");
8
8
  const leaf = parts.at(-1);
9
9
  const directory = parts[0];
@@ -14,7 +14,7 @@ export function isStudyAnalysisRecordPath(relativePath) {
14
14
  leaf.startsWith(".humanish-write-")));
15
15
  }
16
16
  /** Check the exact in-memory snapshot being projected; a prior filesystem scan cannot approve a later write. */
17
- export function studyAnalysisSharingProblems(loaded) {
17
+ export function analysisSharingProblems(loaded) {
18
18
  // Job metadata never approves evidence, nor does uncertain liveness revoke its approval.
19
19
  const { automatic: _automatic, ...evidence } = loaded;
20
20
  const benignAttempt = loaded.analysis?.result === null &&
@@ -30,9 +30,9 @@ export function studyAnalysisSharingProblems(loaded) {
30
30
  /** Unsafe generated text is quarantined without hiding the original recording. */
31
31
  export function projectShareCheckedAnalysis(loaded) {
32
32
  const { automatic: _automatic, ...evidence } = loaded;
33
- const automatic = projectAutomaticStudyAnalysisView(loaded.automatic);
33
+ const automatic = projectAutomaticAnalysisView(loaded.automatic);
34
34
  const safe = automatic === undefined ? evidence : { ...evidence, automatic };
35
- return studyAnalysisSharingProblems(safe).sensitive
35
+ return analysisSharingProblems(safe).sensitive
36
36
  ? {
37
37
  state: "invalid",
38
38
  analysis: null,
@@ -2,15 +2,15 @@ import { type PreparedRunArtifactPaths } from "../run/paths.js";
2
2
  import { type AnalysisExecutionReceipt, type AnalysisExecutionStart } from "./validation.js";
3
3
  import type { AnalysisArtifact } from "./types.js";
4
4
  /** Exact bounded receipt lookup for an already claimed execution, never a dispatch decision. */
5
- export declare function readStudyAnalysisExecution(prepared: PreparedRunArtifactPaths, id: string): Promise<AnalysisExecutionReceipt | null>;
5
+ export declare function readAnalysisExecution(prepared: PreparedRunArtifactPaths, id: string): Promise<AnalysisExecutionReceipt | null>;
6
6
  /**
7
7
  * Publish accounting first. Unlike a usable report, this receipt does not claim
8
8
  * the source still matches; its digests name the exact input that was attempted.
9
9
  */
10
- export declare function writeStudyAnalysisExecutionReceipt(prepared: PreparedRunArtifactPaths, value: AnalysisArtifact): Promise<void>;
10
+ export declare function writeAnalysisExecutionReceipt(prepared: PreparedRunArtifactPaths, value: AnalysisArtifact): Promise<void>;
11
11
  /** The returned closure owns one exact directory; persisted IDs never authorize overwriting it. */
12
- export declare function beginStudyAnalysisExecution(prepared: PreparedRunArtifactPaths, context: Omit<AnalysisExecutionStart, "schema" | "createdAt">): Promise<(value: AnalysisArtifact) => Promise<void>>;
13
- export declare function listStudyAnalysisExecutions(prepared: PreparedRunArtifactPaths): Promise<{
12
+ export declare function beginAnalysisExecution(prepared: PreparedRunArtifactPaths, context: Omit<AnalysisExecutionStart, "schema" | "createdAt">): Promise<(value: AnalysisArtifact) => Promise<void>>;
13
+ export declare function listAnalysisExecutions(prepared: PreparedRunArtifactPaths): Promise<{
14
14
  receipts: AnalysisExecutionReceipt[];
15
15
  warnings: string[];
16
16
  }>;
@@ -21,7 +21,7 @@ export interface AnalysisAccountingRecord {
21
21
  legacy: boolean;
22
22
  }
23
23
  /** Accounting is independent of source freshness and findings validation. No evidence is opened. */
24
- export declare function readStudyAnalysisAccountingRecords(prepared: PreparedRunArtifactPaths): Promise<{
24
+ export declare function readAnalysisAccountingRecords(prepared: PreparedRunArtifactPaths): Promise<{
25
25
  records: AnalysisAccountingRecord[];
26
26
  warnings: string[];
27
27
  }>;
@@ -3,7 +3,7 @@
3
3
  import path from "node:path";
4
4
  import { runIdOf } from "../run/paths.js";
5
5
  import { assertPreparedSelectedOutputDirectory, prepareContainedOutputDirectoryRoot, writeContainedOutputFile, } from "../run/contained-output.js";
6
- import { pathMissing, readBoundedStudyFile } from "../run/study-files.js";
6
+ import { pathMissing, readBoundedFile } from "../run/evidence-files.js";
7
7
  import { ANALYSIS_MAX_BYTES, MAX_VERSIONS, ANALYSIS_DIRECTORY, ANALYSIS_EXECUTION_DIRECTORY, claimDirectory, directoryIds, existingRoot, safeId, } from "./store.js";
8
8
  import { hashAnalysisValue, analysisExecutionStartSchema, validateAnalysisArtifact, validateAnalysisExecutionReceipt, } from "./validation.js";
9
9
  /** receipt.json and start.json in an execution directory. */
@@ -17,14 +17,14 @@ const EXECUTION_BINDING_KEYS = [
17
17
  "promptVersion",
18
18
  ];
19
19
  /** Exact bounded receipt lookup for an already claimed execution, never a dispatch decision. */
20
- export async function readStudyAnalysisExecution(prepared, id) {
20
+ export async function readAnalysisExecution(prepared, id) {
21
21
  if (!safeId(id))
22
22
  return null;
23
23
  try {
24
24
  const root = await existingRoot(prepared, ANALYSIS_EXECUTION_DIRECTORY);
25
25
  if (!root)
26
26
  return null;
27
- const bytes = await readBoundedStudyFile(root, `${id}/receipt.json`, MAX_EXECUTION_RECORD_BYTES);
27
+ const bytes = await readBoundedFile(root, `${id}/receipt.json`, MAX_EXECUTION_RECORD_BYTES);
28
28
  if (!bytes)
29
29
  return null;
30
30
  const receipt = validateAnalysisExecutionReceipt(JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes)));
@@ -38,7 +38,7 @@ export async function readStudyAnalysisExecution(prepared, id) {
38
38
  * Publish accounting first. Unlike a usable report, this receipt does not claim
39
39
  * the source still matches; its digests name the exact input that was attempted.
40
40
  */
41
- export async function writeStudyAnalysisExecutionReceipt(prepared, value) {
41
+ export async function writeAnalysisExecutionReceipt(prepared, value) {
42
42
  const receipt = executionReceipt(value, prepared);
43
43
  const root = await prepareContainedOutputDirectoryRoot(prepared, ANALYSIS_EXECUTION_DIRECTORY);
44
44
  const claimed = await claimDirectory(root, receipt.id);
@@ -68,7 +68,7 @@ function executionReceipt(value, prepared) {
68
68
  return receipt;
69
69
  }
70
70
  /** The returned closure owns one exact directory; persisted IDs never authorize overwriting it. */
71
- export async function beginStudyAnalysisExecution(prepared, context) {
71
+ export async function beginAnalysisExecution(prepared, context) {
72
72
  const start = analysisExecutionStartSchema.parse({
73
73
  ...context,
74
74
  schema: "humanish.analysis-execution-start.v1",
@@ -92,7 +92,7 @@ export async function beginStudyAnalysisExecution(prepared, context) {
92
92
  await writeContainedOutputFile(claimed, "receipt.json", `${JSON.stringify(receipt, null, 2)}\n`);
93
93
  };
94
94
  }
95
- export async function listStudyAnalysisExecutions(prepared) {
95
+ export async function listAnalysisExecutions(prepared) {
96
96
  const receipts = [];
97
97
  const warnings = [];
98
98
  try {
@@ -102,7 +102,7 @@ export async function listStudyAnalysisExecutions(prepared) {
102
102
  const inventory = await directoryIds(root, MAX_VERSIONS);
103
103
  warnings.push(...inventory.warnings);
104
104
  for (const id of inventory.ids) {
105
- const bytes = await readBoundedStudyFile(root, `${id}/receipt.json`, MAX_EXECUTION_RECORD_BYTES);
105
+ const bytes = await readBoundedFile(root, `${id}/receipt.json`, MAX_EXECUTION_RECORD_BYTES);
106
106
  if (!bytes) {
107
107
  if (!(await pathMissing(path.join(root.physicalPath, id, "receipt.json")).catch(() => false)))
108
108
  warnings.push("ANALYSIS_RECEIPT_UNREADABLE");
@@ -128,7 +128,7 @@ export async function listStudyAnalysisExecutions(prepared) {
128
128
  return { receipts, warnings: [...new Set(warnings)] };
129
129
  }
130
130
  /** Accounting is independent of source freshness and findings validation. No evidence is opened. */
131
- export async function readStudyAnalysisAccountingRecords(prepared) {
131
+ export async function readAnalysisAccountingRecords(prepared) {
132
132
  const records = new Map();
133
133
  const warnings = [];
134
134
  for (const directory of [ANALYSIS_EXECUTION_DIRECTORY, ANALYSIS_DIRECTORY]) {
@@ -145,7 +145,7 @@ export async function readStudyAnalysisAccountingRecords(prepared) {
145
145
  records.set(id, record);
146
146
  }
147
147
  if (directory === ANALYSIS_EXECUTION_DIRECTORY) {
148
- const startBytes = await readBoundedStudyFile(root, `${id}/start.json`, MAX_EXECUTION_RECORD_BYTES);
148
+ const startBytes = await readBoundedFile(root, `${id}/start.json`, MAX_EXECUTION_RECORD_BYTES);
149
149
  if (startBytes) {
150
150
  try {
151
151
  const start = analysisExecutionStartSchema.parse(JSON.parse(startBytes.toString("utf8")));
@@ -159,7 +159,7 @@ export async function readStudyAnalysisAccountingRecords(prepared) {
159
159
  }
160
160
  }
161
161
  const legacy = directory === ANALYSIS_DIRECTORY;
162
- const bytes = await readBoundedStudyFile(root, `${id}/${legacy ? "analysis.json" : "receipt.json"}`, legacy ? ANALYSIS_MAX_BYTES : MAX_EXECUTION_RECORD_BYTES);
162
+ const bytes = await readBoundedFile(root, `${id}/${legacy ? "analysis.json" : "receipt.json"}`, legacy ? ANALYSIS_MAX_BYTES : MAX_EXECUTION_RECORD_BYTES);
163
163
  if (!bytes)
164
164
  continue;
165
165
  try {
@@ -169,7 +169,7 @@ export async function readStudyAnalysisAccountingRecords(prepared) {
169
169
  // A historical report may have stale captures or invalid findings. Its strictly checked
170
170
  // accounting metadata still records incurred usage; it never approves those findings.
171
171
  const candidate = legacy
172
- ? Object.fromEntries(Object.keys(studyAnalysisExecutionReceiptKeys).map((key) => [key, raw[key]]))
172
+ ? Object.fromEntries(Object.keys(analysisExecutionReceiptKeys).map((key) => [key, raw[key]]))
173
173
  : raw;
174
174
  if (legacy)
175
175
  Object.assign(candidate, {
@@ -208,7 +208,7 @@ export async function readStudyAnalysisAccountingRecords(prepared) {
208
208
  }
209
209
  return { records: [...records.values()], warnings: [...new Set(warnings)] };
210
210
  }
211
- const studyAnalysisExecutionReceiptKeys = {
211
+ const analysisExecutionReceiptKeys = {
212
212
  id: true,
213
213
  runId: true,
214
214
  status: true,
@@ -18,14 +18,14 @@ export declare function assertAnalysisPublicationCapacity(prepared: PreparedRunA
18
18
  export declare function existingRoot(prepared: PreparedRunArtifactPaths, directory?: string): Promise<PreparedSelectedOutputDirectory | null>;
19
19
  export declare function claimDirectory(parent: PreparedSelectedOutputDirectory, id: string): Promise<PreparedSelectedOutputDirectory>;
20
20
  /** A claimed version is never reused, including after interruption before publication. */
21
- export declare function writeStudyAnalysis(prepared: PreparedRunArtifactPaths, value: AnalysisArtifact): Promise<void>;
21
+ export declare function writeAnalysis(prepared: PreparedRunArtifactPaths, value: AnalysisArtifact): Promise<void>;
22
22
  export declare function directoryIds(root: PreparedSelectedOutputDirectory, limit: number, ignoreLegacyFiles?: boolean): Promise<{
23
23
  ids: string[];
24
24
  warnings: string[];
25
25
  }>;
26
26
  /** Read one exact result without reading automatic job state or unrelated history. */
27
- export declare function readStudyAnalysisVersion(prepared: PreparedRunArtifactPaths, id: string): Promise<AnalysisListEntry | null>;
27
+ export declare function readAnalysisVersion(prepared: PreparedRunArtifactPaths, id: string): Promise<AnalysisListEntry | null>;
28
28
  /** Includes failed attempts; callers must not equate the newest attempt with usable findings. */
29
29
  export declare function listAnalyses(prepared: PreparedRunArtifactPaths): Promise<AnalysisListEntry[]>;
30
- export declare function loadStudyAnalysisRecord(prepared: PreparedRunArtifactPaths, id?: string): Promise<LoadedAnalysis>;
31
- export declare function appendStudyAnalysisCorrection(prepared: PreparedRunArtifactPaths, value: AnalysisCorrection): Promise<void>;
30
+ export declare function loadAnalysisRecord(prepared: PreparedRunArtifactPaths, id?: string): Promise<LoadedAnalysis>;
31
+ export declare function appendAnalysisCorrection(prepared: PreparedRunArtifactPaths, value: AnalysisCorrection): Promise<void>;
@@ -4,7 +4,7 @@ import path from "node:path";
4
4
  import { physicalCwdOf, runIdOf, validatePreparedRunRootIdentity, } from "../run/paths.js";
5
5
  import { assertPreparedSelectedOutputDirectory, bindExistingManagedHumanishOutputDirectory, prepareContainedOutputDirectoryRoot, writeContainedOutputFile, } from "../run/contained-output.js";
6
6
  import { EVIDENCE_LIMITS, validateAnalysisEvidence } from "./evidence.js";
7
- import { pathMissing, isStudyEvidencePath, readBoundedStudyFile } from "../run/study-files.js";
7
+ import { pathMissing, isEvidencePath, readBoundedFile } from "../run/evidence-files.js";
8
8
  import { hashAnalysisValue, validateAnalysisArtifact, validateAnalysisCorrection, } from "./validation.js";
9
9
  import { ANALYSIS_ID_PATTERN, } from "./types.js";
10
10
  import { RUN_BUNDLE_FILE } from "../run/bundle.js";
@@ -61,9 +61,9 @@ export async function claimDirectory(parent, id) {
61
61
  return prepareContainedOutputDirectoryRoot(parent, id);
62
62
  }
63
63
  /** A claimed version is never reused, including after interruption before publication. */
64
- export async function writeStudyAnalysis(prepared, value) {
64
+ export async function writeAnalysis(prepared, value) {
65
65
  const artifact = validateAnalysisArtifact(value);
66
- const source = await readBoundedStudyFile(prepared, RUN_BUNDLE_FILE, EVIDENCE_LIMITS.sourceBytes);
66
+ const source = await readBoundedFile(prepared, RUN_BUNDLE_FILE, EVIDENCE_LIMITS.sourceBytes);
67
67
  if (!source)
68
68
  throw new Error("ANALYSIS_SOURCE_UNAVAILABLE");
69
69
  await validateAnalysisEvidence(prepared, artifact, source);
@@ -73,7 +73,7 @@ export async function writeStudyAnalysis(prepared, value) {
73
73
  const root = await prepareContainedOutputDirectoryRoot(prepared, ANALYSIS_DIRECTORY);
74
74
  const claimed = await claimDirectory(root, artifact.id);
75
75
  // Recheck source immediately before publishing the immutable record.
76
- const current = await readBoundedStudyFile(prepared, RUN_BUNDLE_FILE, EVIDENCE_LIMITS.sourceBytes);
76
+ const current = await readBoundedFile(prepared, RUN_BUNDLE_FILE, EVIDENCE_LIMITS.sourceBytes);
77
77
  if (!current?.equals(source))
78
78
  throw new Error("ANALYSIS_SOURCE_CHANGED");
79
79
  await writeContainedOutputFile(claimed, "analysis.json", bytes);
@@ -100,7 +100,7 @@ export async function directoryIds(root, limit, ignoreLegacyFiles = false) {
100
100
  if (entry.name.startsWith(".humanish-write-"))
101
101
  continue;
102
102
  if (ignoreLegacyFiles &&
103
- isStudyEvidencePath(entry.name) &&
103
+ isEvidencePath(entry.name) &&
104
104
  !["analysis.json", "correction.json", "receipt.json"].includes(entry.name))
105
105
  continue;
106
106
  warnings.push("ANALYSIS_UNSAFE_ENTRY_IGNORED");
@@ -118,7 +118,7 @@ export async function directoryIds(root, limit, ignoreLegacyFiles = false) {
118
118
  async function readVersion(prepared, root, id, source) {
119
119
  if (!safeId(id))
120
120
  return { id: "invalid", state: "invalid", analysis: null, warnings: ["ANALYSIS_ID_INVALID"] };
121
- const bytes = await readBoundedStudyFile(root, `${id}/analysis.json`, ANALYSIS_MAX_BYTES);
121
+ const bytes = await readBoundedFile(root, `${id}/analysis.json`, ANALYSIS_MAX_BYTES);
122
122
  // A claimed directory without a published record is an interrupted write, not a report.
123
123
  if (bytes === null) {
124
124
  if (await pathMissing(path.join(root.physicalPath, id, "analysis.json")).catch(() => false))
@@ -159,14 +159,14 @@ async function readVersion(prepared, root, id, source) {
159
159
  return { id, state: "ready", analysis, warnings: [] };
160
160
  }
161
161
  /** Read one exact result without reading automatic job state or unrelated history. */
162
- export async function readStudyAnalysisVersion(prepared, id) {
162
+ export async function readAnalysisVersion(prepared, id) {
163
163
  if (!safeId(id))
164
164
  return null;
165
165
  try {
166
166
  const root = await existingRoot(prepared);
167
167
  if (!root)
168
168
  return null;
169
- return await readVersion(prepared, root, id, await readBoundedStudyFile(prepared, RUN_BUNDLE_FILE, EVIDENCE_LIMITS.sourceBytes));
169
+ return await readVersion(prepared, root, id, await readBoundedFile(prepared, RUN_BUNDLE_FILE, EVIDENCE_LIMITS.sourceBytes));
170
170
  }
171
171
  catch {
172
172
  return null;
@@ -179,7 +179,7 @@ export async function listAnalyses(prepared) {
179
179
  if (!root)
180
180
  return [];
181
181
  const inventory = await directoryIds(root, MAX_VERSIONS, true);
182
- const source = await readBoundedStudyFile(prepared, RUN_BUNDLE_FILE, EVIDENCE_LIMITS.sourceBytes);
182
+ const source = await readBoundedFile(prepared, RUN_BUNDLE_FILE, EVIDENCE_LIMITS.sourceBytes);
183
183
  const results = [];
184
184
  for (const id of inventory.ids) {
185
185
  const entry = await readVersion(prepared, root, id, source);
@@ -219,7 +219,7 @@ async function readCorrections(prepared, root, analysis) {
219
219
  const inventory = await directoryIds(bound, MAX_CORRECTIONS);
220
220
  warnings.push(...inventory.warnings);
221
221
  for (const id of inventory.ids) {
222
- const bytes = await readBoundedStudyFile(root, `${analysis.id}/corrections/${id}/correction.json`, MAX_CORRECTION_BYTES);
222
+ const bytes = await readBoundedFile(root, `${analysis.id}/corrections/${id}/correction.json`, MAX_CORRECTION_BYTES);
223
223
  if (!bytes) {
224
224
  // An unpublished claim directory is harmless; a present record that
225
225
  // cannot be checked must not silently erase a prior review decision.
@@ -246,7 +246,7 @@ async function readCorrections(prepared, root, analysis) {
246
246
  corrections.sort((a, b) => a.createdAt.localeCompare(b.createdAt) || a.id.localeCompare(b.id));
247
247
  return { corrections, warnings };
248
248
  }
249
- export async function loadStudyAnalysisRecord(prepared, id) {
249
+ export async function loadAnalysisRecord(prepared, id) {
250
250
  if (id !== undefined && !safeId(id))
251
251
  return empty("invalid", ["ANALYSIS_ID_INVALID"]);
252
252
  try {
@@ -290,9 +290,9 @@ function assertCorrectionBinding(analysis, correction) {
290
290
  Date.parse(correction.createdAt) < Date.parse(analysis.completedAt))
291
291
  throw new Error("ANALYSIS_CORRECTION_BINDING_INVALID");
292
292
  }
293
- export async function appendStudyAnalysisCorrection(prepared, value) {
293
+ export async function appendAnalysisCorrection(prepared, value) {
294
294
  const correction = validateAnalysisCorrection(value);
295
- const loaded = await loadStudyAnalysisRecord(prepared, correction.analysisId);
295
+ const loaded = await loadAnalysisRecord(prepared, correction.analysisId);
296
296
  if (loaded.state !== "ready" || !loaded.analysis)
297
297
  throw new Error("ANALYSIS_CORRECTION_SOURCE_UNAVAILABLE");
298
298
  assertCorrectionBinding(loaded.analysis, correction);
@@ -2,6 +2,7 @@ import type { RunLabOptions } from "../../run-lab.js";
2
2
  import type { CliIo } from "../io.js";
3
3
  /**
4
4
  * Post-run analysis cancellation for the CLI: while analysis runs, SIGINT, SIGTERM and SIGHUP abort
5
- * it. The listeners exist only during analysis, so actor signal behavior is unchanged.
5
+ * it. The listeners exist only during analysis; before it, the run's own handlers
6
+ * (run-signals.ts) hold the signals and hand them over here.
6
7
  */
7
8
  export declare function cliAnalysisOptions(io: Pick<CliIo, "writeErr">): Pick<RunLabOptions, "onEvent" | "analysisSignal">;
@@ -1,6 +1,8 @@
1
+ import { handOverRunSignals } from "./run-signals.js";
1
2
  /**
2
3
  * Post-run analysis cancellation for the CLI: while analysis runs, SIGINT, SIGTERM and SIGHUP abort
3
- * it. The listeners exist only during analysis, so actor signal behavior is unchanged.
4
+ * it. The listeners exist only during analysis; before it, the run's own handlers
5
+ * (run-signals.ts) hold the signals and hand them over here.
4
6
  */
5
7
  export function cliAnalysisOptions(io) {
6
8
  const controller = new AbortController();
@@ -13,6 +15,7 @@ export function cliAnalysisOptions(io) {
13
15
  onEvent: (event) => {
14
16
  if (event.type === "analysis-started") {
15
17
  io.writeErr("Participants finished; preparing analysis…\n");
18
+ handOverRunSignals();
16
19
  for (const signal of signals)
17
20
  process.on(signal, cancel);
18
21
  }
@@ -3,9 +3,9 @@ import { Command, Option } from "commander";
3
3
  import { forTerminal } from "../../routes/terminal/encoding.js";
4
4
  import { analyzeRun, correctAnalysis, dryRunBundleRefusal, showAnalysis, } from "../../analysis/service.js";
5
5
  import { listAnalyses } from "../../analysis/store.js";
6
- import { listStudyAnalysisExecutions } from "../../analysis/store-executions.js";
6
+ import { listAnalysisExecutions } from "../../analysis/store-executions.js";
7
7
  import { resolveRunPath } from "../../run/locate.js";
8
- import { discoverCliKeys, JSON_OPTION_DESCRIPTION, writeResult } from "../io.js";
8
+ import { CWD_OPTION_DESCRIPTION, discoverCliKeys, JSON_OPTION_DESCRIPTION, RUN_OPTION_DESCRIPTION, writeResult, humanError, } from "../io.js";
9
9
  import { resolvePhysicalCwd } from "../../run/paths.js";
10
10
  /** Commander may collect a shared flag on the parent; only explicit values override leaf defaults. */
11
11
  function analysisSelection(options, command) {
@@ -24,11 +24,11 @@ export function registerAnalyzeCommand(parent, io) {
24
24
  .command("analyze")
25
25
  .enablePositionalOptions()
26
26
  .description("Analyze retained participant evidence into versioned findings. Selected text and captures go to the chosen remote analyst. Opening Observer never starts analysis.")
27
- .summary("Generate evidence-linked study findings.")
28
- .option("--run <id>", "Completed run id or latest pointer.", "latest")
29
- .option("--cwd <path>", "Target project directory.", ".")
27
+ .summary("Analyze a live run into evidence-linked findings.")
28
+ .option("--run <id>", RUN_OPTION_DESCRIPTION, "latest")
29
+ .option("--cwd <path>", CWD_OPTION_DESCRIPTION, ".")
30
30
  .option("--provider <name>", "Analyst: openai (default) or restricted codex account. No provider fallback.")
31
- .option("--max-cost <usd>", "Required for OpenAI, including dry-run: USD admission estimate ceiling, not a billing cap. Unsupported for Codex.")
31
+ .option("--max-cost <usd>", "Required for OpenAI, also with --dry-run: send nothing when the estimated cost in USD is above this. The estimate is not a billing cap. Unsupported for Codex.")
32
32
  .option("--model <id>", "Supported vision model. OpenAI uses high effort; qualified Codex account analysis uses low effort.", DEFAULT_ANALYSIS_MODEL)
33
33
  .option("--question <text>", "Additional reviewer question; does not change participant instructions.")
34
34
  .option("--timeout-ms <ms>", "Request timeout, at most 600000 ms.", String(DEFAULT_ANALYSIS_TIMEOUT_MS))
@@ -40,23 +40,23 @@ export function registerAnalyzeCommand(parent, io) {
40
40
  analyze
41
41
  .command("list")
42
42
  .description("List immutable analysis versions, including failed attempts.")
43
- .option("--run <id>", "Run id or latest pointer.", "latest")
44
- .option("--cwd <path>", "Target project directory.", ".")
43
+ .option("--run <id>", RUN_OPTION_DESCRIPTION, "latest")
44
+ .option("--cwd <path>", CWD_OPTION_DESCRIPTION, ".")
45
45
  .option("--json", JSON_OPTION_DESCRIPTION)
46
46
  .action((options, command) => handleAnalyzeList(io, options, command));
47
47
  analyze
48
48
  .command("show")
49
49
  .description("Read validated analysis and correction history. Defaults to the latest usable version.")
50
- .option("--run <id>", "Run id or latest pointer.", "latest")
50
+ .option("--run <id>", RUN_OPTION_DESCRIPTION, "latest")
51
51
  .option("--id <id>", "Exact analysis version.")
52
- .option("--cwd <path>", "Target project directory.", ".")
52
+ .option("--cwd <path>", CWD_OPTION_DESCRIPTION, ".")
53
53
  .option("--json", JSON_OPTION_DESCRIPTION)
54
54
  .action((options, command) => handleAnalyzeShow(io, options, command));
55
55
  analyze
56
56
  .command("correct")
57
57
  .description("Append a human review note bound to one exact finding version; original claims remain intact.")
58
- .option("--run <id>", "Run id or latest pointer.", "latest")
59
- .option("--cwd <path>", "Target project directory.", ".")
58
+ .option("--run <id>", RUN_OPTION_DESCRIPTION, "latest")
59
+ .option("--cwd <path>", CWD_OPTION_DESCRIPTION, ".")
60
60
  .requiredOption("--analysis <id>", "Analysis version to review.")
61
61
  .requiredOption("--finding <id>", "Finding to review.")
62
62
  .addOption(new Option("--status <status>", "Review disposition.")
@@ -83,7 +83,7 @@ async function handleAnalyze(io, options, command) {
83
83
  if (!selected.ok || !selected.config) {
84
84
  const refusal = await dryRunBundleRefusal(await resolvePhysicalCwd(options.cwd), options.run, options.dryRun === true);
85
85
  if (refusal) {
86
- writeResult(command, io, refusal, (value) => forTerminal(`${value.error?.message ?? ""}\n${value.error?.code ?? ""}\n`));
86
+ writeResult(command, io, refusal, (value) => humanError(value.error));
87
87
  io.setExitCode(2);
88
88
  return;
89
89
  }
@@ -99,7 +99,7 @@ async function handleAnalyze(io, options, command) {
99
99
  message: selected.ok ? "Analysis is disabled." : selected.message,
100
100
  },
101
101
  };
102
- writeResult(command, io, result, (value) => `${value.error.message}\n`);
102
+ writeResult(command, io, result, (value) => humanError(value.error));
103
103
  io.setExitCode(2);
104
104
  return;
105
105
  }
@@ -126,12 +126,12 @@ async function handleAnalyze(io, options, command) {
126
126
  if (value.ok && value.dryRun)
127
127
  return `Admission estimate: $${value.admission?.estimatedCostUsd ?? "unknown"}; output allowance: ${value.admission?.outputTokenAllowance ?? "unknown"} tokens including reasoning. No request sent.\n`;
128
128
  const lines = [];
129
- if (!value.ok)
130
- lines.push(value.error?.message ?? "Analysis unavailable.", value.error?.code ?? "");
131
129
  if (value.artifactPath)
132
130
  lines.push(`${value.reused ? "Reused" : "Saved"} ${value.status} analysis: ${value.artifactPath}`);
133
131
  if (value.executionReceiptPath)
134
132
  lines.push(`Execution receipt: ${value.executionReceiptPath}`);
133
+ if (value.rejectedOutputPath)
134
+ lines.push(`Rejected output, kept locally for diagnosis: ${value.rejectedOutputPath}`);
135
135
  if (value.usage) {
136
136
  lines.push(`Recorded attempt usage${value.usage.usageComplete ? "" : " (incomplete)"}: ${value.usage.inputTokens ?? "unknown"} input tokens, ${value.usage.outputTokens ?? "unknown"} output tokens.`);
137
137
  lines.push(`Estimated attempt cost: ${value.usage.estimatedCostUsd === null ? "unknown" : `$${value.usage.estimatedCostUsd}`}.`);
@@ -139,7 +139,12 @@ async function handleAnalyze(io, options, command) {
139
139
  if (value.reused)
140
140
  lines.push("No new request sent.");
141
141
  lines.push(...value.warnings);
142
- return forTerminal(lines.filter(Boolean).join("\n") + "\n");
142
+ const stdout = lines.length === 0 ? "" : forTerminal(lines.join("\n") + "\n");
143
+ // A failed analysis keeps its artifact and usage lines on stdout; the error goes to stderr.
144
+ if (value.ok)
145
+ return stdout;
146
+ const error = value.error ?? { message: "Analysis unavailable." };
147
+ return { ...(stdout ? { stdout } : {}), error };
143
148
  });
144
149
  io.setExitCode(result.ok ? 0 : 2);
145
150
  }
@@ -152,7 +157,7 @@ async function handleAnalyzeList(io, options, command) {
152
157
  const prepared = await resolveRunPath(await resolvePhysicalCwd(options.cwd), options.run).catch(() => null);
153
158
  const versions = prepared ? await listAnalyses(prepared) : [];
154
159
  const executions = prepared
155
- ? await listStudyAnalysisExecutions(prepared)
160
+ ? await listAnalysisExecutions(prepared)
156
161
  : { receipts: [], warnings: [] };
157
162
  const result = {
158
163
  schema: "humanish.analysis-history.v1",
@@ -3,22 +3,23 @@ import { resolve } from "node:path";
3
3
  import { Command, Option } from "commander";
4
4
  import { startCodexAppServerUi } from "../../actors/codex/app-server-ui.js";
5
5
  import { redactText } from "../../evidence/redaction.js";
6
- import { JSON_OPTION_DESCRIPTION, parseObserverPort, parseTimeoutMs, writeResult, } from "../io.js";
6
+ import { CWD_OPTION_DESCRIPTION, freePortOption, JSON_OPTION_DESCRIPTION, parseObserverPort, parseTimeoutMs, writeResult, humanError, } from "../io.js";
7
7
  export function registerCodexCommands(parent, io) {
8
+ // Hidden from --help and the CLI reference: it drives a Codex app-server session directly and
9
+ // is not a step in running or reviewing a study.
8
10
  const codex = parent
9
- .command("codex")
10
- .description("Run Codex-native humanish integration surfaces.")
11
- .summary("Run Codex-native humanish integration surfaces.");
11
+ .command("codex", { hidden: true })
12
+ .description("Run Codex-native humanish integration surfaces.");
12
13
  codex
13
14
  .command("app-server")
14
15
  .description("Run a browser-visible Codex app-server actor surface and write redacted protocol artifacts.")
15
- .option("--cwd <path>", "Target project directory.", ".")
16
+ .option("--cwd <path>", CWD_OPTION_DESCRIPTION, ".")
16
17
  .option("--prompt <text>", "Prompt to submit to Codex app-server.")
17
18
  .option("--prompt-file <path>", "Read the Codex app-server prompt from a file.")
18
19
  .option("--run-root <path>", "Artifact directory for redacted app-server evidence.")
19
20
  .option("--state-file <path>", "State JSON file for external observers.")
20
21
  .option("--timeout-ms <ms>", "Actor timeout in milliseconds.", String(900_000))
21
- .option("--port <port>", "Local browser UI port.", "0")
22
+ .addOption(freePortOption())
22
23
  .option("--model <model>", "Optional Codex model override.")
23
24
  .addOption(new Option("--sandbox <mode>", "Turn sandbox policy.")
24
25
  .choices(["read-only", "workspace-write", "danger-full-access"])
@@ -101,9 +102,8 @@ export function registerCodexCommands(parent, io) {
101
102
  });
102
103
  }
103
104
  function formatCodexAppServerUiHuman(result) {
104
- if (!result.ok) {
105
- return `${result.error?.code}: ${result.error?.message}\n`;
106
- }
105
+ if (!result.ok)
106
+ return humanError(result.error);
107
107
  return ([
108
108
  "humanish codex app-server",
109
109
  `url: ${result.url ?? "not-started"}`,