humanish 0.107.0 → 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 (521) hide show
  1. package/ARCHITECTURE.md +22 -17
  2. package/CHANGELOG.md +14 -0
  3. package/CONTEXT.md +51 -44
  4. package/README.md +145 -172
  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-ui.js +1 -1
  14. package/dist/actors/codex/codex-admission.d.ts +91 -0
  15. package/dist/actors/codex/codex-admission.js +150 -0
  16. package/dist/actors/codex/restricted-executable.d.ts +4 -4
  17. package/dist/actors/codex/restricted-executable.js +8 -8
  18. package/dist/actors/codex/restricted-launch.d.ts +2 -1
  19. package/dist/actors/codex/restricted-launch.js +1 -1
  20. package/dist/actors/codex/restricted-participant.js +8 -6
  21. package/dist/actors/codex/restricted-policy.d.ts +2 -2
  22. package/dist/actors/codex/restricted-policy.js +2 -2
  23. package/dist/actors/codex/restricted-session.d.ts +2 -2
  24. package/dist/actors/codex/restricted-session.js +10 -5
  25. package/dist/actors/computer-use/actor.d.ts +16 -16
  26. package/dist/actors/computer-use/actor.js +2 -2
  27. package/dist/actors/computer-use/admission-limit.d.ts +1 -1
  28. package/dist/actors/computer-use/admission-limit.js +1 -1
  29. package/dist/actors/computer-use/loop/actions.d.ts +3 -3
  30. package/dist/actors/computer-use/loop/actions.js +10 -10
  31. package/dist/actors/computer-use/loop/backstop.d.ts +3 -3
  32. package/dist/actors/computer-use/loop/backstop.js +14 -12
  33. package/dist/actors/computer-use/loop/ending.d.ts +5 -5
  34. package/dist/actors/computer-use/loop/ending.js +7 -7
  35. package/dist/actors/computer-use/loop/observation.d.ts +2 -2
  36. package/dist/actors/computer-use/loop/observation.js +9 -9
  37. package/dist/actors/computer-use/loop/provider-call.d.ts +1 -1
  38. package/dist/actors/computer-use/loop/provider-call.js +1 -1
  39. package/dist/actors/computer-use/loop/session.js +3 -3
  40. package/dist/actors/computer-use/loop/spend.d.ts +1 -1
  41. package/dist/actors/computer-use/loop/spend.js +1 -1
  42. package/dist/actors/computer-use/loop/trace.js +9 -8
  43. package/dist/actors/computer-use/loop/types.d.ts +25 -23
  44. package/dist/actors/computer-use/loop/usage.js +2 -2
  45. package/dist/actors/computer-use/openai-context.d.ts +37 -0
  46. package/dist/actors/computer-use/openai-context.js +214 -0
  47. package/dist/actors/computer-use/openai-provider.d.ts +11 -8
  48. package/dist/actors/computer-use/openai-provider.js +45 -34
  49. package/dist/actors/computer-use/openai-requests.d.ts +36 -10
  50. package/dist/actors/computer-use/openai-requests.js +82 -15
  51. package/dist/actors/computer-use/openai-wire.d.ts +19 -7
  52. package/dist/actors/computer-use/openai-wire.js +36 -34
  53. package/dist/actors/contract.d.ts +78 -43
  54. package/dist/actors/contract.js +29 -23
  55. package/dist/actors/local-agent/claude-session.d.ts +1 -1
  56. package/dist/actors/local-agent/claude-session.js +10 -9
  57. package/dist/actors/local-agent/cli.d.ts +8 -6
  58. package/dist/actors/local-agent/cli.js +24 -28
  59. package/dist/actors/local-agent/readiness.d.ts +2 -2
  60. package/dist/actors/local-agent/readiness.js +4 -4
  61. package/dist/actors/reasoning-effort.js +6 -6
  62. package/dist/actors/registry.d.ts +10 -10
  63. package/dist/actors/registry.js +18 -17
  64. package/dist/actors/scripted-browser/actor.d.ts +8 -8
  65. package/dist/actors/scripted-browser/actor.js +16 -16
  66. package/dist/actors/scripted-browser/browser-command.js +1 -1
  67. package/dist/actors/scripted-browser/steps.js +1 -1
  68. package/dist/actors/scripted-browser/types.d.ts +1 -1
  69. package/dist/actors/stop-conditions.d.ts +1 -1
  70. package/dist/analysis/codex-config.d.ts +6 -2
  71. package/dist/analysis/codex-config.js +22 -14
  72. package/dist/analysis/service.js +5 -5
  73. package/dist/cli/commands/analyze.js +19 -16
  74. package/dist/cli/commands/codex.js +9 -9
  75. package/dist/cli/commands/comms.js +54 -33
  76. package/dist/cli/commands/feedback.js +20 -21
  77. package/dist/cli/commands/lab-format.d.ts +5 -4
  78. package/dist/cli/commands/lab-format.js +35 -23
  79. package/dist/cli/commands/lab-route-computer-use.js +6 -7
  80. package/dist/cli/commands/lab-route-preview.js +4 -3
  81. package/dist/cli/commands/lab-route-shared-world.js +3 -3
  82. package/dist/cli/commands/lab-run.js +10 -11
  83. package/dist/cli/commands/lab-scorer.d.ts +2 -2
  84. package/dist/cli/commands/lab-scorer.js +1 -1
  85. package/dist/cli/commands/migrate.d.ts +4 -0
  86. package/dist/cli/commands/migrate.js +65 -0
  87. package/dist/cli/commands/observe.js +147 -108
  88. package/dist/cli/commands/run-command.d.ts +10 -0
  89. package/dist/cli/commands/run-command.js +85 -0
  90. package/dist/cli/commands/runs.js +137 -138
  91. package/dist/cli/commands/setup.d.ts +2 -2
  92. package/dist/cli/commands/setup.js +26 -21
  93. package/dist/cli/commands/study.d.ts +3 -0
  94. package/dist/cli/commands/study.js +182 -0
  95. package/dist/cli/commands/tui.d.ts +4 -4
  96. package/dist/cli/commands/tui.js +21 -21
  97. package/dist/cli/commands/watch.js +60 -75
  98. package/dist/cli/deprecations.d.ts +18 -0
  99. package/dist/cli/deprecations.js +48 -0
  100. package/dist/cli/doctor.d.ts +15 -5
  101. package/dist/cli/doctor.js +103 -48
  102. package/dist/cli/first-run-path.d.ts +12 -10
  103. package/dist/cli/first-run-path.js +30 -28
  104. package/dist/cli/io.d.ts +41 -6
  105. package/dist/cli/io.js +97 -22
  106. package/dist/cli/observer-follow.d.ts +2 -2
  107. package/dist/cli/observer-follow.js +5 -6
  108. package/dist/cli/orientation.d.ts +6 -3
  109. package/dist/cli/orientation.js +43 -39
  110. package/dist/cli/product-sentence.d.ts +6 -0
  111. package/dist/cli/product-sentence.js +6 -0
  112. package/dist/cli/program.d.ts +6 -1
  113. package/dist/cli/program.js +109 -40
  114. package/dist/cli/telemetry.d.ts +15 -15
  115. package/dist/cli/telemetry.js +48 -40
  116. package/dist/cli.js +1 -1
  117. package/dist/comms/capture-surface.d.ts +13 -12
  118. package/dist/comms/capture-surface.js +23 -22
  119. package/dist/comms/catch-host.d.ts +7 -7
  120. package/dist/comms/catch-host.js +14 -14
  121. package/dist/comms/email-catch.d.ts +3 -3
  122. package/dist/comms/email-catch.js +8 -8
  123. package/dist/comms/external-evidence.js +2 -2
  124. package/dist/comms/extract.js +2 -2
  125. package/dist/comms/fake-inbox.d.ts +2 -2
  126. package/dist/comms/fake-inbox.js +2 -2
  127. package/dist/comms/receiving-render.d.ts +1 -1
  128. package/dist/comms/receiving-render.js +2 -2
  129. package/dist/comms/sandbox-catch-script.d.ts +6 -6
  130. package/dist/comms/sandbox-catch-script.js +6 -6
  131. package/dist/comms/sandbox-catch.d.ts +36 -37
  132. package/dist/comms/sandbox-catch.js +34 -35
  133. package/dist/comms/setup.js +42 -8
  134. package/dist/comms/thread-evidence.d.ts +1 -1
  135. package/dist/comms/thread-evidence.js +6 -6
  136. package/dist/comms/types.d.ts +6 -6
  137. package/dist/comms/types.js +3 -3
  138. package/dist/evidence/frame-signature.d.ts +1 -1
  139. package/dist/evidence/frame-signature.js +4 -4
  140. package/dist/evidence/redaction.d.ts +3 -3
  141. package/dist/evidence/redaction.js +4 -4
  142. package/dist/feedback/draft.js +36 -78
  143. package/dist/feedback/export-bundle.js +1 -1
  144. package/dist/feedback/export.d.ts +5 -1
  145. package/dist/feedback/export.js +7 -8
  146. package/dist/feedback/feedback.d.ts +2 -2
  147. package/dist/feedback/feedback.js +21 -3
  148. package/dist/guest/chromium-text.js +2 -2
  149. package/dist/guest/desktop-native.d.ts +1 -1
  150. package/dist/guest/runtime.js +1 -1
  151. package/dist/index.d.ts +12 -10
  152. package/dist/index.js +8 -6
  153. package/dist/keys/key-resolution.d.ts +5 -5
  154. package/dist/keys/key-resolution.js +23 -23
  155. package/dist/lab/adapter-extension.d.ts +7 -7
  156. package/dist/lab/adapter-extension.js +13 -36
  157. package/dist/lab/adapter-scorer-loader.d.ts +7 -7
  158. package/dist/lab/adapter-scorer-loader.js +32 -32
  159. package/dist/lab/composition-rules.js +42 -42
  160. package/dist/lab/config.js +65 -25
  161. package/dist/lab/deprecated-fields.d.ts +10 -0
  162. package/dist/lab/deprecated-fields.js +24 -0
  163. package/dist/lab/device-presets.d.ts +8 -8
  164. package/dist/lab/device-presets.js +11 -11
  165. package/dist/lab/discover.d.ts +13 -9
  166. package/dist/lab/discover.js +117 -57
  167. package/dist/lab/doctor.d.ts +10 -3
  168. package/dist/lab/doctor.js +47 -9
  169. package/dist/lab/init-templates.js +147 -147
  170. package/dist/lab/init.d.ts +1 -1
  171. package/dist/lab/init.js +41 -9
  172. package/dist/lab/keys.d.ts +2 -0
  173. package/dist/lab/keys.js +42 -8
  174. package/dist/lab/lab-deps.d.ts +7 -12
  175. package/dist/lab/parse/actors.js +9 -9
  176. package/dist/lab/parse/comms.js +5 -5
  177. package/dist/lab/parse/execution.js +13 -13
  178. package/dist/lab/parse/study-v3.d.ts +23 -0
  179. package/dist/lab/parse/study-v3.js +259 -0
  180. package/dist/lab/parse/subject-state.d.ts +7 -7
  181. package/dist/lab/parse/subject-state.js +16 -16
  182. package/dist/lab/parse/subject.js +28 -28
  183. package/dist/lab/parse/values.d.ts +1 -1
  184. package/dist/lab/parse/values.js +3 -3
  185. package/dist/lab/persona-resolve.d.ts +4 -4
  186. package/dist/lab/persona-resolve.js +4 -4
  187. package/dist/lab/plan-participants.d.ts +2 -2
  188. package/dist/lab/plan-types.d.ts +4 -4
  189. package/dist/lab/plan.d.ts +1 -7
  190. package/dist/lab/plan.js +10 -41
  191. package/dist/lab/preflight-probes.js +11 -11
  192. package/dist/lab/preflight-result.d.ts +2 -1
  193. package/dist/lab/preflight-result.js +5 -4
  194. package/dist/lab/preflight.d.ts +7 -5
  195. package/dist/lab/preflight.js +5 -5
  196. package/dist/lab/routing.d.ts +31 -25
  197. package/dist/lab/routing.js +60 -29
  198. package/dist/lab/run-lab-events.d.ts +0 -3
  199. package/dist/lab/run-lab-events.js +0 -6
  200. package/dist/lab/run-lab-homes.d.ts +22 -10
  201. package/dist/lab/run-lab-homes.js +5 -1
  202. package/dist/lab/run-lab-options.d.ts +1 -1
  203. package/dist/lab/run-lab-options.js +16 -13
  204. package/dist/lab/summary.d.ts +7 -6
  205. package/dist/lab/summary.js +10 -10
  206. package/dist/lab/tasks.d.ts +15 -15
  207. package/dist/lab/tasks.js +14 -14
  208. package/dist/lab/types.d.ts +101 -95
  209. package/dist/lab/types.js +2 -0
  210. package/dist/lab/validation.d.ts +13 -13
  211. package/dist/lab/validation.js +44 -42
  212. package/dist/lab/warnings.d.ts +10 -0
  213. package/dist/lab/warnings.js +61 -33
  214. package/dist/library-aliases.d.ts +56 -0
  215. package/dist/library-aliases.js +22 -0
  216. package/dist/observer/artifact.d.ts +1 -1
  217. package/dist/observer/artifact.js +6 -6
  218. package/dist/observer/data.d.ts +6 -6
  219. package/dist/observer/data.js +5 -4
  220. package/dist/observer/exposure.d.ts +1 -1
  221. package/dist/observer/exposure.js +11 -11
  222. package/dist/observer/http.js +1 -1
  223. package/dist/observer/library.d.ts +1 -1
  224. package/dist/observer/library.js +4 -2
  225. package/dist/observer/listen.js +5 -4
  226. package/dist/observer/render.d.ts +1 -1
  227. package/dist/observer/render.js +10 -5
  228. package/dist/observer/run-routes.d.ts +3 -3
  229. package/dist/observer/run-routes.js +1 -1
  230. package/dist/observer/serve.js +7 -3
  231. package/dist/observer/tunnel.js +1 -1
  232. package/dist/observer-app.html +4 -4
  233. package/dist/routes/computer-use/bundle-parts.d.ts +9 -9
  234. package/dist/routes/computer-use/bundle-parts.js +15 -15
  235. package/dist/routes/computer-use/bundle.js +3 -3
  236. package/dist/routes/computer-use/e2b-desktop/comms.d.ts +1 -1
  237. package/dist/routes/computer-use/e2b-desktop/comms.js +14 -14
  238. package/dist/routes/computer-use/e2b-desktop/desktop.js +4 -4
  239. package/dist/routes/computer-use/e2b-desktop/fidelity.d.ts +4 -3
  240. package/dist/routes/computer-use/e2b-desktop/fidelity.js +11 -10
  241. package/dist/routes/computer-use/e2b-desktop/prepare.js +7 -7
  242. package/dist/routes/computer-use/e2b-desktop/start.js +9 -8
  243. package/dist/routes/computer-use/e2b-desktop/teardown.js +5 -4
  244. package/dist/routes/computer-use/external-comms.d.ts +1 -1
  245. package/dist/routes/computer-use/external-comms.js +1 -1
  246. package/dist/routes/computer-use/fanout-bundle.js +18 -18
  247. package/dist/routes/computer-use/fanout-records.js +10 -11
  248. package/dist/routes/computer-use/live-flush.d.ts +1 -1
  249. package/dist/routes/computer-use/live-flush.js +6 -6
  250. package/dist/routes/computer-use/live-phase.d.ts +4 -2
  251. package/dist/routes/computer-use/live-phase.js +6 -6
  252. package/dist/routes/computer-use/local-vm.js +1 -1
  253. package/dist/routes/computer-use/participant-desktop.d.ts +4 -4
  254. package/dist/routes/computer-use/participant-desktop.js +4 -4
  255. package/dist/routes/computer-use/participant-execution.d.ts +4 -4
  256. package/dist/routes/computer-use/participant-execution.js +9 -9
  257. package/dist/routes/computer-use/participant-model.d.ts +6 -0
  258. package/dist/routes/computer-use/participant-model.js +31 -13
  259. package/dist/routes/computer-use/participant-prompt.d.ts +11 -11
  260. package/dist/routes/computer-use/participant-prompt.js +6 -6
  261. package/dist/routes/computer-use/participant-runs.d.ts +7 -7
  262. package/dist/routes/computer-use/participant-runs.js +13 -13
  263. package/dist/routes/computer-use/plan.js +22 -22
  264. package/dist/routes/computer-use/preflight.js +21 -21
  265. package/dist/routes/computer-use/rerun-selection.js +1 -1
  266. package/dist/routes/computer-use/result.js +11 -11
  267. package/dist/routes/computer-use/route.d.ts +2 -1
  268. package/dist/routes/computer-use/route.js +15 -14
  269. package/dist/routes/computer-use/self-report.d.ts +7 -7
  270. package/dist/routes/computer-use/self-report.js +31 -31
  271. package/dist/routes/computer-use/setup.d.ts +1 -1
  272. package/dist/routes/computer-use/setup.js +17 -18
  273. package/dist/routes/computer-use/single-bundle.d.ts +7 -7
  274. package/dist/routes/computer-use/single-bundle.js +28 -30
  275. package/dist/routes/computer-use/subject-projection.d.ts +1 -1
  276. package/dist/routes/computer-use/subject-projection.js +6 -6
  277. package/dist/routes/computer-use/types.d.ts +40 -42
  278. package/dist/routes/computer-use/types.js +10 -10
  279. package/dist/routes/preview.d.ts +8 -2
  280. package/dist/routes/preview.js +8 -4
  281. package/dist/routes/scripted/bundle.d.ts +2 -2
  282. package/dist/routes/scripted/bundle.js +13 -12
  283. package/dist/routes/scripted/plan.d.ts +1 -1
  284. package/dist/routes/scripted/plan.js +9 -9
  285. package/dist/routes/scripted/result.js +5 -5
  286. package/dist/routes/scripted/route.js +5 -6
  287. package/dist/routes/scripted/scenario.js +2 -2
  288. package/dist/routes/scripted/setup.js +7 -7
  289. package/dist/routes/scripted/subject.js +1 -1
  290. package/dist/routes/scripted/surface-records.js +3 -3
  291. package/dist/routes/scripted/types.d.ts +3 -5
  292. package/dist/routes/scripted/types.js +1 -1
  293. package/dist/routes/shared-world/bundle-records.js +9 -8
  294. package/dist/routes/shared-world/bundle.d.ts +5 -5
  295. package/dist/routes/shared-world/bundle.js +40 -38
  296. package/dist/routes/shared-world/checkpoints.d.ts +1 -1
  297. package/dist/routes/shared-world/checkpoints.js +1 -1
  298. package/dist/routes/shared-world/comms.d.ts +5 -5
  299. package/dist/routes/shared-world/comms.js +14 -14
  300. package/dist/routes/shared-world/external-public.d.ts +4 -3
  301. package/dist/routes/shared-world/external-public.js +16 -12
  302. package/dist/routes/shared-world/handoff.d.ts +7 -6
  303. package/dist/routes/shared-world/handoff.js +65 -57
  304. package/dist/routes/shared-world/lobby-code.d.ts +2 -2
  305. package/dist/routes/shared-world/lobby-code.js +9 -9
  306. package/dist/routes/shared-world/participant-specs.d.ts +7 -6
  307. package/dist/routes/shared-world/participant-specs.js +31 -24
  308. package/dist/routes/shared-world/plan.js +7 -7
  309. package/dist/routes/shared-world/provenance.d.ts +2 -2
  310. package/dist/routes/shared-world/provenance.js +2 -2
  311. package/dist/routes/shared-world/provisioned.js +14 -13
  312. package/dist/routes/shared-world/result.js +20 -21
  313. package/dist/routes/shared-world/route.js +23 -22
  314. package/dist/routes/shared-world/setup.d.ts +3 -3
  315. package/dist/routes/shared-world/setup.js +4 -4
  316. package/dist/routes/shared-world/types.d.ts +30 -28
  317. package/dist/routes/shared-world/types.js +4 -4
  318. package/dist/routes/terminal/adapter.d.ts +3 -3
  319. package/dist/routes/terminal/adapter.js +5 -5
  320. package/dist/routes/terminal/bundle.d.ts +3 -3
  321. package/dist/routes/terminal/bundle.js +22 -21
  322. package/dist/routes/terminal/credentials.d.ts +4 -4
  323. package/dist/routes/terminal/credentials.js +7 -7
  324. package/dist/routes/terminal/dry-run.js +4 -4
  325. package/dist/routes/terminal/encoding.js +2 -2
  326. package/dist/routes/terminal/ledger.d.ts +3 -3
  327. package/dist/routes/terminal/ledger.js +14 -14
  328. package/dist/routes/terminal/live-finish.js +3 -3
  329. package/dist/routes/terminal/live-sandbox.js +12 -13
  330. package/dist/routes/terminal/persona.js +1 -1
  331. package/dist/routes/terminal/plan.js +11 -11
  332. package/dist/routes/terminal/recorder.js +2 -2
  333. package/dist/routes/terminal/result.js +8 -8
  334. package/dist/routes/terminal/route.js +6 -7
  335. package/dist/routes/terminal/sandbox.d.ts +1 -1
  336. package/dist/routes/terminal/sandbox.js +1 -1
  337. package/dist/routes/terminal/session.js +8 -7
  338. package/dist/routes/terminal/token-usage.d.ts +1 -1
  339. package/dist/routes/terminal/token-usage.js +7 -8
  340. package/dist/routes/terminal/trace.d.ts +2 -2
  341. package/dist/routes/terminal/trace.js +2 -2
  342. package/dist/routes/terminal/types.d.ts +26 -28
  343. package/dist/routes/terminal/types.js +3 -3
  344. package/dist/run/bundle-shape.js +3 -3
  345. package/dist/run/bundle.d.ts +46 -46
  346. package/dist/run/bundle.js +2 -1
  347. package/dist/run/cost-summary.js +3 -3
  348. package/dist/run/costs.js +7 -1
  349. package/dist/run/detail.d.ts +6 -6
  350. package/dist/run/detail.js +4 -4
  351. package/dist/run/dry-run-inputs.js +1 -1
  352. package/dist/run/dry-run.js +18 -18
  353. package/dist/run/judge.d.ts +19 -13
  354. package/dist/run/judge.js +18 -8
  355. package/dist/run/paths.d.ts +1 -1
  356. package/dist/run/paths.js +1 -1
  357. package/dist/run/pricing.d.ts +11 -6
  358. package/dist/run/pricing.js +20 -13
  359. package/dist/run/projection.d.ts +14 -14
  360. package/dist/run/projection.js +15 -15
  361. package/dist/run/reclaim.js +2 -2
  362. package/dist/run/results.d.ts +5 -5
  363. package/dist/run/run-index.d.ts +8 -6
  364. package/dist/run/run-index.js +15 -16
  365. package/dist/run/run-not-found.d.ts +5 -0
  366. package/dist/run/run-not-found.js +15 -0
  367. package/dist/run/run.d.ts +5 -4
  368. package/dist/run/run.js +1 -1
  369. package/dist/run/sandbox-receipts.d.ts +2 -2
  370. package/dist/run/sandbox-receipts.js +3 -3
  371. package/dist/run/shared-world-evidence.d.ts +36 -35
  372. package/dist/run/shared-world-evidence.js +4 -4
  373. package/dist/run/shared-world-shape.d.ts +1 -1
  374. package/dist/run/shared-world-shape.js +6 -6
  375. package/dist/run/stats.d.ts +12 -6
  376. package/dist/run/stats.js +116 -58
  377. package/dist/run/status.d.ts +8 -29
  378. package/dist/run/status.js +5 -27
  379. package/dist/run/stored-runs.js +2 -1
  380. package/dist/run/stream-shape.js +1 -1
  381. package/dist/run/streams.d.ts +6 -6
  382. package/dist/run/study-provenance.d.ts +47 -0
  383. package/dist/run/study-provenance.js +63 -0
  384. package/dist/run/study-result.d.ts +16 -0
  385. package/dist/run/study-result.js +9 -0
  386. package/dist/run/text.d.ts +2 -0
  387. package/dist/run/text.js +4 -0
  388. package/dist/run-lab.d.ts +7 -7
  389. package/dist/run-lab.js +1 -3
  390. package/dist/study/convert.d.ts +33 -0
  391. package/dist/study/convert.js +432 -0
  392. package/dist/study/field-paths.d.ts +12 -0
  393. package/dist/study/field-paths.js +126 -0
  394. package/dist/study/files.d.ts +26 -0
  395. package/dist/study/files.js +43 -0
  396. package/dist/study/migrate.d.ts +48 -0
  397. package/dist/study/migrate.js +408 -0
  398. package/dist/study/owned-files.d.ts +38 -0
  399. package/dist/study/owned-files.js +182 -0
  400. package/dist/subject/clone.d.ts +1 -1
  401. package/dist/subject/desktop-cli.d.ts +1 -1
  402. package/dist/subject/desktop-cli.js +2 -2
  403. package/dist/subject/local-tree-archive.js +1 -1
  404. package/dist/subject/local-tree.d.ts +1 -1
  405. package/dist/subject/node-bootstrap.js +1 -1
  406. package/dist/subject/runtime.js +8 -9
  407. package/dist/subject/serve.d.ts +1 -1
  408. package/dist/subject/serve.js +3 -3
  409. package/dist/subject/state.d.ts +1 -1
  410. package/dist/subject/steps.d.ts +5 -5
  411. package/dist/subject/steps.js +4 -4
  412. package/dist/substrates/command-failure.d.ts +3 -3
  413. package/dist/substrates/command-failure.js +3 -3
  414. package/dist/substrates/detached.d.ts +6 -6
  415. package/dist/substrates/detached.js +7 -7
  416. package/dist/substrates/e2b/cdp-probe.d.ts +9 -9
  417. package/dist/substrates/e2b/cdp-probe.js +14 -17
  418. package/dist/substrates/e2b/desktop-browser.d.ts +2 -2
  419. package/dist/substrates/e2b/desktop-browser.js +8 -8
  420. package/dist/substrates/e2b/desktop-cdp.d.ts +9 -9
  421. package/dist/substrates/e2b/desktop-cdp.js +8 -8
  422. package/dist/substrates/e2b/desktop-executor.d.ts +1 -1
  423. package/dist/substrates/e2b/desktop-executor.js +1 -1
  424. package/dist/substrates/e2b/desktop-geometry.d.ts +3 -3
  425. package/dist/substrates/e2b/desktop-geometry.js +7 -7
  426. package/dist/substrates/e2b/desktop-media.d.ts +1 -1
  427. package/dist/substrates/e2b/desktop-media.js +1 -1
  428. package/dist/substrates/e2b/desktop-screenshot-cleanup.d.ts +3 -3
  429. package/dist/substrates/e2b/desktop-screenshot-cleanup.js +3 -3
  430. package/dist/substrates/e2b/sandbox.d.ts +1 -1
  431. package/dist/substrates/e2b/sandbox.js +1 -1
  432. package/dist/substrates/e2b/sdk.d.ts +11 -11
  433. package/dist/substrates/e2b/sdk.js +6 -6
  434. package/dist/tui/actions.d.ts +1 -1
  435. package/dist/tui/actions.js +13 -13
  436. package/dist/tui/contract.d.ts +16 -16
  437. package/dist/tui/contract.js +10 -10
  438. package/dist/tui/launch.d.ts +4 -4
  439. package/dist/tui/launch.js +18 -19
  440. package/dist/tui/project.js +5 -5
  441. package/dist/tui-app.js +82 -82
  442. package/dist/verify/actor.d.ts +8 -8
  443. package/dist/verify/actor.js +36 -36
  444. package/dist/verify/artifacts.d.ts +2 -2
  445. package/dist/verify/artifacts.js +3 -3
  446. package/dist/verify/context-growth.d.ts +9 -0
  447. package/dist/verify/context-growth.js +62 -0
  448. package/dist/verify/costs.d.ts +6 -6
  449. package/dist/verify/costs.js +8 -8
  450. package/dist/verify/shared-world-concurrent.d.ts +2 -2
  451. package/dist/verify/shared-world-concurrent.js +79 -76
  452. package/dist/verify/shared-world.d.ts +2 -2
  453. package/dist/verify/shared-world.js +16 -16
  454. package/dist/verify/subject.d.ts +4 -4
  455. package/dist/verify/subject.js +18 -18
  456. package/dist/verify/verify.js +92 -43
  457. package/docs/README.md +25 -32
  458. package/docs/architecture/actor-contract.md +56 -87
  459. package/docs/architecture/desktop-sessions.md +7 -7
  460. package/docs/architecture/external-public-shared-world.md +61 -59
  461. package/docs/architecture/github-feedback-loop.md +1 -4
  462. package/docs/architecture/guest-desktop.md +2 -2
  463. package/docs/architecture/observer.md +34 -34
  464. package/docs/architecture/restricted-codex-analysis.md +34 -28
  465. package/docs/architecture/serve.md +34 -37
  466. package/docs/architecture/state-driven-executor.md +55 -58
  467. package/docs/architecture/task-protocol-support.md +5 -5
  468. package/docs/architecture/terminal-product-route.md +67 -107
  469. package/docs/contracts/README.md +24 -0
  470. package/docs/contracts/adapter-admission.md +3 -3
  471. package/docs/contracts/adapter-fixtures.md +2 -5
  472. package/docs/contracts/core.md +1 -3
  473. package/docs/contracts/errors.md +62 -0
  474. package/docs/contracts/feedback.md +8 -9
  475. package/docs/contracts/policy.md +7 -12
  476. package/docs/contracts/run-bundle.md +45 -44
  477. package/docs/contracts/schemas.md +421 -362
  478. package/docs/contracts/study-analysis.md +3 -3
  479. package/docs/contracts/study-costs.md +11 -7
  480. package/docs/decisions/0001-run-bundle-is-the-source-of-truth.md +1 -1
  481. package/docs/decisions/0002-observer-is-one-self-contained-file.md +2 -2
  482. package/docs/decisions/0003-contained-paths-and-cleanup-authority.md +3 -3
  483. package/docs/principles/actor-fidelity.md +4 -4
  484. package/docs/principles/engineering.md +3 -3
  485. package/docs/principles/invariants-and-defaults.md +38 -38
  486. package/docs/principles/self-driving-harness.md +1 -5
  487. package/docs/principles/three-roles.md +1 -1
  488. package/docs/product/automatic-analysis.md +7 -7
  489. package/examples/participant/README.md +5 -5
  490. package/examples/participant/run.mjs +11 -10
  491. package/examples/scorer/README.md +3 -3
  492. package/examples/scorer/run.mjs +11 -12
  493. package/package.json +16 -17
  494. package/skills/humanish/SKILL.md +60 -58
  495. package/skills/humanish/agents/openai.yaml +1 -1
  496. package/AGENTS.md +0 -99
  497. package/CONTRIBUTING.md +0 -148
  498. package/dist/actors/codex/qualified-versions.d.ts +0 -72
  499. package/dist/actors/codex/qualified-versions.js +0 -132
  500. package/dist/cli/commands/lab.d.ts +0 -3
  501. package/dist/cli/commands/lab.js +0 -199
  502. package/dist/cli/renamed-options.d.ts +0 -11
  503. package/dist/cli/renamed-options.js +0 -18
  504. package/dist/observer/static.d.ts +0 -39
  505. package/dist/observer/static.js +0 -369
  506. package/docs/architecture/comms-inbox.md +0 -122
  507. package/docs/architecture/desktop-recording.md +0 -80
  508. package/docs/architecture/local-browser-runtime.md +0 -178
  509. package/docs/architecture/observer-review.md +0 -144
  510. package/docs/architecture/participant-media.md +0 -90
  511. package/docs/architecture/project-layout.md +0 -62
  512. package/docs/architecture/real-email-receiving.md +0 -136
  513. package/docs/assets/humanish-drawdb-hero.png +0 -0
  514. package/docs/assets/humanish-observer-hero.png +0 -0
  515. package/docs/goals/current.md +0 -207
  516. package/docs/product/lobby-trivia-3player-external-public.md +0 -77
  517. package/docs/product/open-source-install-experience.md +0 -240
  518. package/docs/ramp/README.md +0 -295
  519. package/docs/release/open-source-readiness.md +0 -222
  520. package/docs/release/public-readiness-standard.md +0 -210
  521. package/docs/roadmap/world-class-open-source-v0.md +0 -311
@@ -1,8 +1,8 @@
1
1
  // Whether a local-agent participant can run on this machine before anything is acquired: its CLI
2
- // is on PATH and signed in, a hosted Codex CLI is a qualified release on a supported platform, and
2
+ // is on `PATH` and signed in, a hosted Codex CLI is a qualified release on a supported platform, and
3
3
  // a ChatGPT-account Codex is not asked to enforce a dollar cap it has no price for. Each route maps
4
4
  // the refusal's kind to its own error code.
5
- import { describeQualifiedCodexCliVersions } from "../codex/qualified-versions.js";
5
+ import { describeCodexCliAdmission } from "../codex/codex-admission.js";
6
6
  import { checkHostedCodexCompatibility, detectLocalAgents } from "./cli.js";
7
7
  export async function localAgentRefusal(args) {
8
8
  const { agent, env, caps } = args;
@@ -19,7 +19,7 @@ export async function localAgentRefusal(args) {
19
19
  return {
20
20
  kind: "signin-required",
21
21
  message: chosen.authStatus === "unauthenticated"
22
- ? `${chosen.label} reports not signed in — run \`${chosen.id === "codex" ? "codex login" : "claude auth login"}\`, then retry.`
22
+ ? `${chosen.label} reports it is not signed in; run \`${chosen.id === "codex" ? "codex login" : "claude auth login"}\`, then retry.`
23
23
  : `${chosen.label} authentication status could not be checked. Run \`${chosen.id === "codex" ? "codex login status" : "claude auth status"}\` and update the CLI if needed. No desktop was launched.`,
24
24
  };
25
25
  }
@@ -31,7 +31,7 @@ export async function localAgentRefusal(args) {
31
31
  kind: "unsupported",
32
32
  message: compatibility === "unsupported_platform"
33
33
  ? `Hosted Codex participants require Linux or macOS on x64 or arm64. This host is ${process.platform}/${process.arch}; no desktop was launched.`
34
- : `Hosted Codex participants require a qualified Codex CLI (${describeQualifiedCodexCliVersions()}). Run \`codex --version\` and install a qualified version before retrying; no desktop was launched.`,
34
+ : `Hosted Codex participants need a Codex CLI release humanish runs: ${describeCodexCliAdmission()}. Run \`humanish doctor\` for the release it found and the command that replaces it; no desktop was launched.`,
35
35
  };
36
36
  }
37
37
  if (chosen.billing === "account-unknown" &&
@@ -1,19 +1,19 @@
1
1
  // The provider-declared reasoning-effort vocabulary, kept in its own module so the lab schema and
2
2
  // the OpenAI provider can share it without the schema depending on a provider.
3
3
  //
4
- // WHY THIS EXISTS AT ALL: effort was reachable in the provider and unreachable from a lab. Every
5
- // computer-use run humanish had ever done was therefore the provider default — not by decision but
6
- // by omission (#497). Effort changes who the PARTICIPANT is, the same way a persona prompt does
4
+ // Why this exists: effort was reachable in the provider and unreachable from a lab. Every
5
+ // computer-use run humanish had ever done was therefore the provider default, not by decision but
6
+ // by omission. Effort changes who the participant is, the same way a persona prompt does
7
7
  // (docs/principles/actor-fidelity.md: capability settings are recruiting decisions), so pinning it
8
8
  // invisibly meant every persona finding was really a finding about that persona at medium, with the
9
9
  // second half unsaid.
10
10
  //
11
- // SUPPORT IS MODEL-DEPENDENT. OpenAI documents the vocabulary below as the union across models and
11
+ // Support is model-dependent. OpenAI documents the vocabulary below as the union across models and
12
12
  // states plainly that "supported values are model-dependent"; there is no offline way to know which
13
13
  // subset a given model id accepts. So this module refuses to pretend: it validates that a lab asked
14
- // for a REAL effort level, and a model that does not support the one it was asked for fails on the
14
+ // for a real effort level, and a model that does not support the one it was asked for fails on the
15
15
  // first turn with the provider's own message rather than being silently downgraded. Silent
16
- // downgrade is the worse failure — it would record an effort the run did not actually use.
16
+ // downgrade is the worse failure: it would record an effort the run did not actually use.
17
17
  /** The documented vocabulary, ordered from least to most reasoning. */
18
18
  export const REASONING_EFFORTS = [
19
19
  "none",
@@ -27,27 +27,27 @@ export interface TerminalActorDescriptor extends ActorDescriptorBase {
27
27
  }
28
28
  export type ActorDescriptor = CodexActorDescriptor | CuaActorDescriptor | ScriptedBrowserActorDescriptor | TerminalActorDescriptor;
29
29
  /**
30
- * REGISTRY CONTRACT: an actor whose capabilities include the "computer-use" lane is a
31
- * CuaActorDescriptor — its runSession takes CuaActorSessionOptions and returns a CuaLoopResult.
30
+ * Registry contract: an actor whose capabilities include the "computer-use" run kind is a
31
+ * CuaActorDescriptor: its runSession takes CuaActorSessionOptions and returns a CuaLoopResult.
32
32
  * Any future computer-use provider (e.g. stagehand-cua) must keep that session signature and add
33
33
  * its id to CuaActorDescriptor["id"], so code narrowed by this guard can still tell the ids apart.
34
34
  * This guard is what lets the lab dispatch on capabilities rather than on hardcoded actor ids.
35
35
  */
36
36
  export declare function isCuaActorDescriptor(descriptor: ActorDescriptor): descriptor is CuaActorDescriptor;
37
37
  /**
38
- * REGISTRY CONTRACT (mirror of isCuaActorDescriptor): an actor whose capabilities include the
39
- * "scripted-browser" lane IS a ScriptedBrowserActorDescriptor — runSession takes
38
+ * Registry contract (mirror of isCuaActorDescriptor): an actor whose capabilities include the
39
+ * "scripted-browser" run kind is a ScriptedBrowserActorDescriptor; runSession takes
40
40
  * ScriptedBrowserSessionOptions and returns ScriptedBrowserSessionResult (trace fully formed,
41
- * like the CUA shape — no separate toActorTrace). Any future scripted driver (e.g. a HAR
41
+ * like the CUA shape; no separate toActorTrace). Any future scripted driver (e.g. a HAR
42
42
  * replayer) must keep this signature; it is what lets the lab dispatch on capabilities, not ids.
43
43
  */
44
44
  export declare function isScriptedBrowserActorDescriptor(descriptor: ActorDescriptor): descriptor is ScriptedBrowserActorDescriptor;
45
45
  /**
46
- * REGISTRY CONTRACT (mirror of isCuaActorDescriptor / isScriptedBrowserActorDescriptor): an actor
47
- * whose capabilities include the "terminal" lane IS a TerminalActorDescriptor. This is the guard
48
- * the terminal-product lab uses for route selection and capability enforcement. The current
49
- * descriptor's direct runSession is intentionally unsupported; live execution is route-owned.
50
- * Any future terminal actor must declare keyPlacement honestly and integrate with that lifecycle.
46
+ * Registry contract (mirror of isCuaActorDescriptor / isScriptedBrowserActorDescriptor): an actor
47
+ * whose capabilities include the "terminal" run kind is a TerminalActorDescriptor. This is the
48
+ * guard the terminal-product route uses for route selection and capability enforcement. The current
49
+ * descriptor's direct runSession is intentionally unsupported; live execution is route-owned. Any
50
+ * future terminal actor must declare the keyPlacement it uses and integrate with that lifecycle.
51
51
  */
52
52
  export declare function isTerminalActorDescriptor(descriptor: ActorDescriptor): descriptor is TerminalActorDescriptor;
53
53
  export declare const actorRegistry: Record<ActorId, ActorDescriptor>;
@@ -6,8 +6,8 @@ import { LOCAL_AGENT_CAPABILITIES } from "./local-agent/cli.js";
6
6
  import { OPENAI_RESPONSES_CU_CAPABILITIES } from "./computer-use/openai-provider.js";
7
7
  import { runScriptedBrowserSession, } from "./scripted-browser/actor.js";
8
8
  /**
9
- * REGISTRY CONTRACT: an actor whose capabilities include the "computer-use" lane is a
10
- * CuaActorDescriptor — its runSession takes CuaActorSessionOptions and returns a CuaLoopResult.
9
+ * Registry contract: an actor whose capabilities include the "computer-use" run kind is a
10
+ * CuaActorDescriptor: its runSession takes CuaActorSessionOptions and returns a CuaLoopResult.
11
11
  * Any future computer-use provider (e.g. stagehand-cua) must keep that session signature and add
12
12
  * its id to CuaActorDescriptor["id"], so code narrowed by this guard can still tell the ids apart.
13
13
  * This guard is what lets the lab dispatch on capabilities rather than on hardcoded actor ids.
@@ -16,21 +16,21 @@ export function isCuaActorDescriptor(descriptor) {
16
16
  return descriptor.capabilities.lanes.includes("computer-use");
17
17
  }
18
18
  /**
19
- * REGISTRY CONTRACT (mirror of isCuaActorDescriptor): an actor whose capabilities include the
20
- * "scripted-browser" lane IS a ScriptedBrowserActorDescriptor — runSession takes
19
+ * Registry contract (mirror of isCuaActorDescriptor): an actor whose capabilities include the
20
+ * "scripted-browser" run kind is a ScriptedBrowserActorDescriptor; runSession takes
21
21
  * ScriptedBrowserSessionOptions and returns ScriptedBrowserSessionResult (trace fully formed,
22
- * like the CUA shape — no separate toActorTrace). Any future scripted driver (e.g. a HAR
22
+ * like the CUA shape; no separate toActorTrace). Any future scripted driver (e.g. a HAR
23
23
  * replayer) must keep this signature; it is what lets the lab dispatch on capabilities, not ids.
24
24
  */
25
25
  export function isScriptedBrowserActorDescriptor(descriptor) {
26
26
  return descriptor.capabilities.lanes.includes("scripted-browser");
27
27
  }
28
28
  /**
29
- * REGISTRY CONTRACT (mirror of isCuaActorDescriptor / isScriptedBrowserActorDescriptor): an actor
30
- * whose capabilities include the "terminal" lane IS a TerminalActorDescriptor. This is the guard
31
- * the terminal-product lab uses for route selection and capability enforcement. The current
32
- * descriptor's direct runSession is intentionally unsupported; live execution is route-owned.
33
- * Any future terminal actor must declare keyPlacement honestly and integrate with that lifecycle.
29
+ * Registry contract (mirror of isCuaActorDescriptor / isScriptedBrowserActorDescriptor): an actor
30
+ * whose capabilities include the "terminal" run kind is a TerminalActorDescriptor. This is the
31
+ * guard the terminal-product route uses for route selection and capability enforcement. The current
32
+ * descriptor's direct runSession is intentionally unsupported; live execution is route-owned. Any
33
+ * future terminal actor must declare the keyPlacement it uses and integrate with that lifecycle.
34
34
  */
35
35
  export function isTerminalActorDescriptor(descriptor) {
36
36
  return descriptor.capabilities.lanes.includes("terminal");
@@ -43,13 +43,14 @@ export const actorRegistry = {
43
43
  runSession: runCodexAppServerSession,
44
44
  toActorTrace: codexResultToActorTrace,
45
45
  },
46
- // The ActorId names the actor slot (keeps the lane open for a future stagehand-cua provider);
47
- // the trace's `provider` string stays "openai-responses-cu" (the concrete model adapter).
48
- // The operator's own signed-in coding agent as the computer-use brain (Codex on a ChatGPT plan,
49
- // Claude Code on a Max plan). Same lane, same loop, same evidence — the only difference is where
50
- // the next action comes from, which is exactly why it is a provider swap and not a new lane.
51
- // It exists so someone new can watch a persona drive a real desktop without first going to find
52
- // an API key; the machine they are on very often already has one of these signed in.
46
+ // The ActorId names the actor slot (keeps the slot open for a future stagehand-cua
47
+ // provider); the trace's `provider` string stays "openai-responses-cu" (the concrete model
48
+ // adapter). The operator's own signed-in coding agent as the computer-use brain (Codex on a
49
+ // ChatGPT plan, Claude Code on a Max plan). Same run kind, same loop, same evidence; the only
50
+ // difference is where the next action comes from, which is exactly why it is a provider swap and
51
+ // not a new run kind. It exists so someone new can watch a persona drive a real desktop
52
+ // without first going to find an API key; the machine they are on very often already has one of
53
+ // these signed in.
53
54
  "local-agent": {
54
55
  id: "local-agent",
55
56
  label: "Local coding agent (operator-authenticated)",
@@ -10,10 +10,10 @@ export interface ScriptedBrowserSessionOptions {
10
10
  urlPolicy?: ScriptedBrowserEvidenceUrlPolicy;
11
11
  /** Parsed + validated by the backend (scenario.ref is consumed there, fail-closed). */
12
12
  journey: BrowserPersonaJourney;
13
- /** ONE session per surface. */
13
+ /** One session per surface. */
14
14
  surface: BrowserSurface;
15
15
  /** id = actors[0].persona ?? "scripted-journey"; promptDigest = journey.sourceDigest prefix
16
- * (the step manifest IS the "prompt" — no model prompt exists on this route). */
16
+ * (the step manifest is the "prompt"; no model prompt exists on this route). */
17
17
  persona: ActorPersonaRef;
18
18
  /** Journey wall-clock budget in ms; the lab route passes execution.timeoutMs or 300_000. */
19
19
  timeoutMs: number;
@@ -30,19 +30,19 @@ export interface ScriptedBrowserSessionResult extends ActorSessionResult {
30
30
  capture: BrowserSurfaceCapture;
31
31
  }
32
32
  /**
33
- * Run the scripted journey for ONE surface and return native capture + ActorTrace projection.
33
+ * Run the scripted journey for one surface and return native capture + ActorTrace projection.
34
34
  *
35
35
  * Completion semantics (the contract the projection tests pin):
36
36
  * - every step executed, every assertion passed, HTTP probe ok -> passed / goal_satisfied
37
- * (the scenario's expect blocks ARE the success predicate; a pass claims "the app still
37
+ * (the scenario's expect blocks are the success predicate; a pass claims "the app still
38
38
  * affords this exact journey", nothing about user behavior);
39
39
  * - a step's expectation evaluated false, a step target missing/unactionable, or an
40
- * unreachable subject -> failed / step_failed (the harness executed faithfully; the SUBJECT
41
- * did not satisfy the script — distinct from actor_error/harness_error);
40
+ * unreachable subject -> failed / step_failed (the harness executed faithfully; the subject
41
+ * did not satisfy the script, distinct from actor_error/harness_error);
42
42
  * - journey exceeded timeoutMs -> timed_out / timed_out;
43
43
  * - browser launch/import crash -> failed / harness_error;
44
- * - gave_up / blocked_approval are UNREACHABLE from this actor (no persona patience, no
45
- * approvals exist on a deterministic replay) — asserted in tests.
44
+ * - gave_up / blocked_approval are unreachable from this actor (no persona patience, no
45
+ * approvals exist on a deterministic replay), asserted in tests.
46
46
  */
47
47
  export declare function runScriptedBrowserSession(options: ScriptedBrowserSessionOptions): Promise<ScriptedBrowserSessionResult>;
48
48
  /** Internal lab seam: the run root is already prepared and must stay bound to that identity. */
@@ -9,12 +9,12 @@
9
9
  // The step executor's `page` is typed as the narrow structural ScriptedPageLike instead of
10
10
  // playwright's Page (browserPersonaPageState already took { evaluate, url }; E2BDesktopLike is
11
11
  // the same seam pattern). playwright's real Page satisfies it; tests inject fakes and run
12
- // the REAL step executor at $0 with zero browser dependence. playwright-core stays the lazy
12
+ // the real step executor at $0 with zero browser dependence. playwright-core stays the lazy
13
13
  // production default behind launchPlaywrightChromium.
14
14
  //
15
- // Spend posture: nothing in this module can spend provider money — no provider client is
15
+ // Spend posture: nothing in this module can spend provider money: no provider client is
16
16
  // importable from this code path. tokenUsage on every projected trace records zeros as an
17
- // affirmative $0 declaration that is TRUE by mechanism.
17
+ // affirmative $0 declaration that is true by mechanism.
18
18
  import { stat } from "node:fs/promises";
19
19
  import path from "node:path";
20
20
  import { CHROMIUM_EVIDENCE_HYGIENE_FLAGS } from "../../evidence/browser-hygiene.js";
@@ -24,7 +24,7 @@ import { ACTOR_TRACE_SCHEMA, SCRIPTED_BROWSER_CAPABILITIES, } from "../contract.
24
24
  import { buildBlockedBrowserPersonaSteps, buildBrowserTrace, captureBlockedStepScreenshot, compactBrowserError, executeBrowserPersonaStep, probeAppUrl, sanitizeBrowserEvidenceUrl, screenshotPathForBrowserStep, surfaceScreenshotPath, tracePathForBrowserSurface, } from "./steps.js";
25
25
  import { LOOPBACK_EVIDENCE_URL_POLICY, } from "./types.js";
26
26
  /** Production default: lazy playwright-core import + chromium.launch, exactly as the driver
27
- * always did. Kept in ONE place so the optional peer is touched by exactly one code path. */
27
+ * always did. Kept in one place so the optional peer is touched by exactly one code path. */
28
28
  async function launchPlaywrightChromium(args) {
29
29
  const { chromium } = await import("playwright-core");
30
30
  const browser = await chromium.launch({
@@ -50,19 +50,19 @@ class ScriptedJourneyTimeoutError extends Error {
50
50
  }
51
51
  }
52
52
  /**
53
- * Run the scripted journey for ONE surface and return native capture + ActorTrace projection.
53
+ * Run the scripted journey for one surface and return native capture + ActorTrace projection.
54
54
  *
55
55
  * Completion semantics (the contract the projection tests pin):
56
56
  * - every step executed, every assertion passed, HTTP probe ok -> passed / goal_satisfied
57
- * (the scenario's expect blocks ARE the success predicate; a pass claims "the app still
57
+ * (the scenario's expect blocks are the success predicate; a pass claims "the app still
58
58
  * affords this exact journey", nothing about user behavior);
59
59
  * - a step's expectation evaluated false, a step target missing/unactionable, or an
60
- * unreachable subject -> failed / step_failed (the harness executed faithfully; the SUBJECT
61
- * did not satisfy the script — distinct from actor_error/harness_error);
60
+ * unreachable subject -> failed / step_failed (the harness executed faithfully; the subject
61
+ * did not satisfy the script, distinct from actor_error/harness_error);
62
62
  * - journey exceeded timeoutMs -> timed_out / timed_out;
63
63
  * - browser launch/import crash -> failed / harness_error;
64
- * - gave_up / blocked_approval are UNREACHABLE from this actor (no persona patience, no
65
- * approvals exist on a deterministic replay) — asserted in tests.
64
+ * - gave_up / blocked_approval are unreachable from this actor (no persona patience, no
65
+ * approvals exist on a deterministic replay), asserted in tests.
66
66
  */
67
67
  export async function runScriptedBrowserSession(options) {
68
68
  assertScriptedSessionPathIds(options);
@@ -107,7 +107,7 @@ export async function runScriptedBrowserSessionInPreparedRoot(options, preparedA
107
107
  trace,
108
108
  };
109
109
  };
110
- // Launch FIRST: a browser that cannot start is a harness failure, never subject evidence.
110
+ // Launch first: a browser that cannot start is a harness failure, never subject evidence.
111
111
  let browser;
112
112
  try {
113
113
  browser = await launch({ browserCommand, timeoutMs: options.timeoutMs });
@@ -289,7 +289,7 @@ async function runScriptedJourney(args) {
289
289
  };
290
290
  }
291
291
  /** Race one step against the journey's remaining wall-clock budget. A hanging step rejects
292
- * with the timeout error; the journey's catch path then records honest blocked steps. */
292
+ * with the timeout error; the journey's catch path then records the remaining steps as blocked. */
293
293
  async function withJourneyDeadline(promise, deadline, timeoutMs) {
294
294
  const remaining = deadline - Date.now();
295
295
  if (remaining <= 0) {
@@ -353,7 +353,7 @@ async function persistScriptedFailureCapture(args) {
353
353
  };
354
354
  }
355
355
  /** Project one surface capture into humanish.actor-trace.v1. screenshotRefs are attached only
356
- * for frames that actually exist on disk (honest counts; blocked-not-executed steps name a
356
+ * for frames that actually exist on disk (so counts match disk; blocked-not-executed steps name a
357
357
  * path that was never written). */
358
358
  async function projectScriptedActorTrace(args) {
359
359
  const writtenScreenshots = new Set();
@@ -371,7 +371,7 @@ async function projectScriptedActorTrace(args) {
371
371
  const items = args.capture.steps.map((step) => {
372
372
  const assertions = step.assertions ?? [];
373
373
  assertionCount += assertions.length;
374
- const assertionLines = assertions.map((assertion) => `${assertion.id}: ${assertion.status} — ${assertion.reason}`);
374
+ const assertionLines = assertions.map((assertion) => `${assertion.id}: ${assertion.status} (${assertion.reason})`);
375
375
  return {
376
376
  id: step.id,
377
377
  kind: "ui_action",
@@ -401,7 +401,7 @@ async function projectScriptedActorTrace(args) {
401
401
  status: args.status,
402
402
  completionReason: args.completionReason,
403
403
  reason: redactText(args.reason),
404
- // No session/model ids exist on a deterministic replay — absence declared by omission.
404
+ // No session/model ids exist on a deterministic replay; absence declared by omission.
405
405
  ids: {},
406
406
  counts: {
407
407
  steps: args.journey.steps.length,
@@ -412,7 +412,7 @@ async function projectScriptedActorTrace(args) {
412
412
  screenshots: writtenScreenshots.size,
413
413
  },
414
414
  items,
415
- // Affirmative $0 declaration, TRUE by mechanism: no provider client is importable from
415
+ // Affirmative $0 declaration, true by mechanism: no provider client is importable from
416
416
  // this code path, so zeros are a recorded fact, not an estimate.
417
417
  tokenUsage: { input: 0, output: 0, total: 0, costUsd: 0 },
418
418
  capabilities: SCRIPTED_BROWSER_CAPABILITIES,
@@ -1,5 +1,5 @@
1
1
  // Find a Chromium binary on the host for the scripted browser: HUMANISH_BROWSER_COMMAND first, then
2
- // the macOS Chrome path, then google-chrome, chromium and chromium-browser on PATH. A candidate
2
+ // the macOS Chrome path, then google-chrome, chromium and chromium-browser on `PATH`. A candidate
3
3
  // counts only if `--version` runs.
4
4
  import { execFile } from "node:child_process";
5
5
  import path from "node:path";
@@ -176,7 +176,7 @@ async function waitForPageText(page, expectedText, timeoutMs) {
176
176
  }
177
177
  export function buildBlockedBrowserPersonaSteps(args) {
178
178
  // The journey never ran, so no screenshot was written for these steps. The
179
- // failure IS the evidence: keep the blocked status + reason, but omit the
179
+ // failure is the evidence: keep the blocked status + reason, but omit the
180
180
  // screenshot reference so the bundle never claims an artifact that does not
181
181
  // exist (otherwise verify's missingLocalEvidenceArtifacts fails closed on
182
182
  // evidence that was never meant to exist).
@@ -108,7 +108,7 @@ export interface BrowserPersonaStepCapture {
108
108
  /**
109
109
  * Path to the step screenshot the producer actually wrote. Omitted for blocked
110
110
  * steps where the failure itself is the recorded evidence and no screenshot was
111
- * written — the bundle must not reference an artifact that does not exist. A step that
111
+ * written: the bundle must not reference an artifact that does not exist. A step that
112
112
  * ran and attempted a screenshot keeps this even when its assertions failed, so a broken
113
113
  * producer still fails verify.
114
114
  */
@@ -14,7 +14,7 @@ export interface StopWhen {
14
14
  any: StopWhenRule[];
15
15
  }
16
16
  /**
17
- * A declared observation window (#510): once `when` matches (or at the start, when `when` is
17
+ * A declared observation window: once `when` matches (or at the start, when `when` is
18
18
  * absent), the harness holds the page for `ms`, captures a frame every `everyMs`, takes no action
19
19
  * and requests no model turn, then hands control back to the participant (`then: continue`) or
20
20
  * ends the session (`then: stop`). Bounded by the session budget: a window that would outlast it
@@ -2,7 +2,11 @@ import type { CodexAnalysisIdentity, AnalysisConfig } from "./types.js";
2
2
  export declare const CODEX_ANALYSIS_MODEL: "gpt-6-astra";
3
3
  /** Before dispatch, analysis replaces the default release with the detected one. */
4
4
  export declare function codexAnalysisIdentity(model: string, cliVersion?: string): CodexAnalysisIdentity;
5
- /** Execution admission: the identity must name a release qualified on this host. */
5
+ /** Execution admission: an isolated-mode host, and an identity naming a release the launcher starts. */
6
6
  export declare function validCodexAnalysisConfig(config: AnalysisConfig, platform?: NodeJS.Platform, arch?: string): boolean;
7
- /** Reading historical artifacts never inserts defaults or selects a launch policy. */
7
+ /**
8
+ * Reading historical artifacts never inserts defaults or selects a launch policy: the restricted
9
+ * analyst's fixed identity, from any recordable release, so a change to launch admission never
10
+ * invalidates a saved report.
11
+ */
8
12
  export declare function validStoredCodexAnalysisConfig(config: AnalysisConfig): boolean;
@@ -1,7 +1,7 @@
1
- import { RECORDED_CODEX_CLI_VERSIONS } from "../actors/contract.js";
2
- import { defaultCodexCliVersion, qualifiedCodexCliVersions, } from "../actors/codex/qualified-versions.js";
1
+ import { isRecordedCodexCliVersion } from "../actors/contract.js";
2
+ import { admitsCodexCliVersion, defaultCodexCliVersion, supportsIsolatedCodex, } from "../actors/codex/codex-admission.js";
3
3
  import { RESTRICTED_CODEX_ANALYSIS_IDENTITY, RESTRICTED_CODEX_ANALYSIS_MODELS, } from "../actors/codex/restricted-policy.js";
4
- /** This account route is qualified against per-host CLI releases, one model and one tool policy. */
4
+ /** This account route runs the releases codex-admission.ts admits, one model and one tool policy. */
5
5
  const CODEX_ANALYSIS_TOOL_POLICY = RESTRICTED_CODEX_ANALYSIS_IDENTITY.toolPolicy;
6
6
  export const CODEX_ANALYSIS_MODEL = RESTRICTED_CODEX_ANALYSIS_MODELS[0];
7
7
  const CODEX_ANALYSIS_EFFORT = RESTRICTED_CODEX_ANALYSIS_IDENTITY.reasoningEffort;
@@ -26,13 +26,6 @@ export function codexAnalysisIdentity(model, cliVersion = defaultCodexCliVersion
26
26
  cliVersion,
27
27
  });
28
28
  }
29
- /** Reader profiles are append-only. A new launch qualification must not invalidate a saved report. */
30
- const storedProfiles = RECORDED_CODEX_CLI_VERSIONS.map((cliVersion) => ({
31
- cliVersion,
32
- toolPolicy: "restricted-codex-v1",
33
- model: "gpt-6-astra",
34
- reasoningEffort: "low",
35
- }));
36
29
  function matchesProfile(config, expected) {
37
30
  if (config.provider !== "codex")
38
31
  return false;
@@ -54,16 +47,31 @@ function matchesProfile(config, expected) {
54
47
  Object.keys(config.identity).length === Object.keys(expected).length &&
55
48
  Object.entries(expected).every(([key, value]) => config.identity[key] === value));
56
49
  }
57
- /** Execution admission: the identity must name a release qualified on this host. */
50
+ /** Execution admission: an isolated-mode host, and an identity naming a release the launcher starts. */
58
51
  export function validCodexAnalysisConfig(config, platform = process.platform, arch = process.arch) {
59
52
  if (config.provider !== "codex")
60
53
  return false;
61
54
  const cliVersion = config.identity?.cliVersion;
62
55
  return (config.model === CODEX_ANALYSIS_MODEL &&
63
- qualifiedCodexCliVersions(platform, arch).some((version) => version === cliVersion) &&
56
+ supportsIsolatedCodex(platform, arch) &&
57
+ typeof cliVersion === "string" &&
58
+ admitsCodexCliVersion(cliVersion) &&
64
59
  matchesProfile(config, codexAnalysisIdentity(config.model, cliVersion)));
65
60
  }
66
- /** Reading historical artifacts never inserts defaults or selects a launch policy. */
61
+ /**
62
+ * Reading historical artifacts never inserts defaults or selects a launch policy: the restricted
63
+ * analyst's fixed identity, from any recordable release, so a change to launch admission never
64
+ * invalidates a saved report.
65
+ */
67
66
  export function validStoredCodexAnalysisConfig(config) {
68
- return storedProfiles.some((profile) => matchesProfile(config, identityFor(profile)));
67
+ if (config.provider !== "codex")
68
+ return false;
69
+ const cliVersion = config.identity?.cliVersion;
70
+ return (isRecordedCodexCliVersion(cliVersion) &&
71
+ matchesProfile(config, identityFor({
72
+ cliVersion,
73
+ toolPolicy: "restricted-codex-v1",
74
+ model: "gpt-6-astra",
75
+ reasoningEffort: "low",
76
+ })));
69
77
  }
@@ -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";
@@ -43,7 +43,7 @@ const messages = {
43
43
  ANALYSIS_VERIFY_FAILED: "The run must pass verification before analysis.",
44
44
  ANALYSIS_RUN_ACTIVE: "Analysis requires a completed recording. Wait for the study to finish.",
45
45
  ANALYSIS_NO_PARTICIPANTS: "This run contains no participant evidence to analyze.",
46
- 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.",
47
47
  ANALYSIS_SOURCE_UNAVAILABLE: "The source recording is missing, unsafe, or exceeds the input limit.",
48
48
  ANALYSIS_SOURCE_CHANGED: "The source recording changed during analysis. The result cannot be published against different evidence.",
49
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.",
@@ -56,9 +56,9 @@ const messages = {
56
56
  };
57
57
  const codexRecovery = {
58
58
  analysis_codex_busy: "Another restricted Codex analyst or setup check is active in this process. Wait for it to finish, then explicitly retry.",
59
- 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.`,
60
- analysis_codex_unsupported_version: `Codex account analysis requires a qualified CLI version (${describeQualifiedCodexCliVersions()}). Other versions have not passed this tool-policy contract.`,
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 a release humanish was tested with (${describeQualifiedCodexCliVersions()}), then retry.`,
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.`,
62
62
  analysis_codex_unsupported_platform: "This platform has not qualified the restricted Codex account launcher.",
63
63
  analysis_codex_login_required: "Sign in to Codex with a ChatGPT account, then retry humanish analyze --provider codex --rerun.",
64
64
  analysis_codex_unsupported_auth: "Codex analysis requires ChatGPT account authentication; API-key and custom provider authentication are not used as fallbacks.",
@@ -5,7 +5,7 @@ import { analyzeRun, correctAnalysis, dryRunBundleRefusal, showAnalysis, } from
5
5
  import { listAnalyses } from "../../analysis/store.js";
6
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,8 +126,6 @@ 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)
@@ -141,7 +139,12 @@ async function handleAnalyze(io, options, command) {
141
139
  if (value.reused)
142
140
  lines.push("No new request sent.");
143
141
  lines.push(...value.warnings);
144
- 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 };
145
148
  });
146
149
  io.setExitCode(result.ok ? 0 : 2);
147
150
  }
@@ -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"}`,