humanish 0.108.0 → 0.109.1

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 (461) hide show
  1. package/ARCHITECTURE.md +58 -59
  2. package/CHANGELOG.md +22 -0
  3. package/CONTEXT.md +44 -44
  4. package/README.md +3 -3
  5. package/TELEMETRY.md +2 -2
  6. package/dist/actors/codex/app-server-trace.js +2 -1
  7. package/dist/actors/codex/restricted-participant.js +12 -12
  8. package/dist/actors/codex/restricted-session.d.ts +2 -2
  9. package/dist/actors/computer-use/actor.d.ts +6 -6
  10. package/dist/actors/computer-use/actor.js +2 -2
  11. package/dist/actors/computer-use/admission-limit.d.ts +2 -2
  12. package/dist/actors/computer-use/admission-limit.js +3 -3
  13. package/dist/actors/computer-use/executor-error.d.ts +2 -2
  14. package/dist/actors/computer-use/executor-error.js +3 -3
  15. package/dist/actors/computer-use/loop/actions.js +5 -5
  16. package/dist/actors/computer-use/loop/debrief.js +2 -2
  17. package/dist/actors/computer-use/loop/ending.d.ts +1 -1
  18. package/dist/actors/computer-use/loop/ending.js +12 -11
  19. package/dist/actors/computer-use/loop/observation.js +6 -5
  20. package/dist/actors/computer-use/loop/provider-call.js +11 -11
  21. package/dist/actors/computer-use/loop/session.d.ts +4 -4
  22. package/dist/actors/computer-use/loop/session.js +2 -2
  23. package/dist/actors/computer-use/loop/trace.js +3 -2
  24. package/dist/actors/computer-use/loop/types.d.ts +24 -24
  25. package/dist/actors/computer-use/loop/usage.d.ts +2 -2
  26. package/dist/actors/computer-use/loop.d.ts +6 -1
  27. package/dist/actors/computer-use/loop.js +26 -4
  28. package/dist/actors/computer-use/openai-provider.d.ts +2 -2
  29. package/dist/actors/computer-use/openai-provider.js +8 -8
  30. package/dist/actors/computer-use/provider-error.d.ts +4 -4
  31. package/dist/actors/computer-use/provider-error.js +6 -6
  32. package/dist/actors/contract.d.ts +4 -4
  33. package/dist/actors/contract.js +1 -1
  34. package/dist/actors/local-agent/claude-session.js +3 -3
  35. package/dist/actors/local-agent/cli.d.ts +1 -1
  36. package/dist/actors/local-agent/cli.js +1 -1
  37. package/dist/actors/reasoning-effort.js +3 -3
  38. package/dist/actors/registry.d.ts +2 -2
  39. package/dist/actors/registry.js +3 -3
  40. package/dist/actors/scripted-browser/actor.d.ts +2 -2
  41. package/dist/actors/scripted-browser/actor.js +1 -1
  42. package/dist/analysis/automatic-completion.d.ts +7 -7
  43. package/dist/analysis/automatic-completion.js +1 -1
  44. package/dist/analysis/automatic-config.d.ts +6 -6
  45. package/dist/analysis/automatic-config.js +1 -1
  46. package/dist/analysis/execute.d.ts +1 -1
  47. package/dist/analysis/execute.js +1 -1
  48. package/dist/analysis/types.d.ts +6 -0
  49. package/dist/browser-control/client.js +16 -16
  50. package/dist/browser-control/dispatcher.js +4 -4
  51. package/dist/browser-control/protocol.js +14 -14
  52. package/dist/browser-control/recording-transfer.js +4 -4
  53. package/dist/browser-control/transport.js +7 -7
  54. package/dist/cli/commands/analysis-signals.d.ts +2 -2
  55. package/dist/cli/commands/comms.js +14 -22
  56. package/dist/cli/commands/migrate.js +15 -4
  57. package/dist/cli/commands/observe.d.ts +0 -1
  58. package/dist/cli/commands/observe.js +0 -15
  59. package/dist/cli/commands/run-command.d.ts +2 -2
  60. package/dist/cli/commands/run-command.js +3 -3
  61. package/dist/cli/commands/runs.js +9 -7
  62. package/dist/cli/commands/setup.js +5 -7
  63. package/dist/cli/commands/study-format.d.ts +9 -0
  64. package/dist/cli/commands/{lab-format.js → study-format.js} +5 -5
  65. package/dist/cli/commands/{lab-route-computer-use.d.ts → study-route-computer-use.d.ts} +6 -6
  66. package/dist/cli/commands/{lab-route-computer-use.js → study-route-computer-use.js} +12 -12
  67. package/dist/cli/commands/{lab-route-open.d.ts → study-route-open.d.ts} +4 -4
  68. package/dist/cli/commands/{lab-route-open.js → study-route-open.js} +2 -2
  69. package/dist/cli/commands/{lab-route-preview.d.ts → study-route-preview.d.ts} +7 -7
  70. package/dist/cli/commands/{lab-route-preview.js → study-route-preview.js} +3 -3
  71. package/dist/cli/commands/study-route-run.d.ts +19 -0
  72. package/dist/cli/commands/{lab-route-run.js → study-route-run.js} +6 -6
  73. package/dist/cli/commands/study-route-scripted.d.ts +17 -0
  74. package/dist/cli/commands/{lab-route-scripted.js → study-route-scripted.js} +4 -4
  75. package/dist/cli/commands/{lab-route-shared-world.d.ts → study-route-shared-world.d.ts} +5 -5
  76. package/dist/cli/commands/{lab-route-shared-world.js → study-route-shared-world.js} +7 -7
  77. package/dist/cli/commands/study-route-terminal.d.ts +17 -0
  78. package/dist/cli/commands/{lab-route-terminal.js → study-route-terminal.js} +4 -4
  79. package/dist/cli/commands/study-run.d.ts +9 -0
  80. package/dist/cli/commands/{lab-run.js → study-run.js} +34 -34
  81. package/dist/cli/commands/{lab-scorer.d.ts → study-scorer.d.ts} +5 -5
  82. package/dist/cli/commands/{lab-scorer.js → study-scorer.js} +1 -1
  83. package/dist/cli/commands/study.js +13 -49
  84. package/dist/cli/commands/tui.js +12 -12
  85. package/dist/cli/commands/watch.js +30 -65
  86. package/dist/cli/deprecations.d.ts +1 -13
  87. package/dist/cli/deprecations.js +0 -30
  88. package/dist/cli/doctor.d.ts +3 -3
  89. package/dist/cli/doctor.js +16 -16
  90. package/dist/cli/first-run-path.d.ts +4 -4
  91. package/dist/cli/first-run-path.js +7 -7
  92. package/dist/cli/io.d.ts +3 -3
  93. package/dist/cli/io.js +2 -2
  94. package/dist/cli/observer-follow.d.ts +2 -2
  95. package/dist/cli/observer-follow.js +2 -2
  96. package/dist/cli/orientation.d.ts +4 -4
  97. package/dist/cli/orientation.js +58 -20
  98. package/dist/cli/program.js +3 -4
  99. package/dist/cli/telemetry.d.ts +1 -1
  100. package/dist/cli/telemetry.js +14 -20
  101. package/dist/comms/catch-host.d.ts +1 -1
  102. package/dist/comms/catch-host.js +3 -3
  103. package/dist/comms/connections.d.ts +1 -1
  104. package/dist/comms/connections.js +2 -2
  105. package/dist/comms/external-evidence.d.ts +5 -5
  106. package/dist/comms/external-evidence.js +4 -3
  107. package/dist/comms/fake-inbox.d.ts +2 -2
  108. package/dist/comms/fake-inbox.js +2 -2
  109. package/dist/comms/receiving-runtime.d.ts +4 -4
  110. package/dist/comms/sandbox-catch.d.ts +2 -2
  111. package/dist/comms/sandbox-catch.js +2 -2
  112. package/dist/comms/setup.d.ts +2 -2
  113. package/dist/comms/setup.js +29 -32
  114. package/dist/evidence/redaction.d.ts +11 -0
  115. package/dist/evidence/redaction.js +43 -0
  116. package/dist/feedback/draft.js +2 -2
  117. package/dist/feedback/export-bundle.js +5 -4
  118. package/dist/feedback/export.js +3 -2
  119. package/dist/feedback/proof.d.ts +1 -1
  120. package/dist/feedback/proof.js +2 -2
  121. package/dist/guest/bootstrap.js +6 -6
  122. package/dist/guest/browser-tools.js +8 -8
  123. package/dist/guest/chromium-text.js +17 -17
  124. package/dist/guest/desktop-executor.d.ts +2 -2
  125. package/dist/guest/desktop-executor.js +20 -20
  126. package/dist/guest/desktop-keys.js +4 -4
  127. package/dist/guest/desktop-media.d.ts +2 -2
  128. package/dist/guest/desktop-media.js +16 -16
  129. package/dist/guest/desktop-native.js +10 -10
  130. package/dist/guest/runtime-desktop.js +2 -2
  131. package/dist/guest/runtime-processes.d.ts +2 -2
  132. package/dist/guest/runtime-processes.js +2 -2
  133. package/dist/guest/runtime.js +5 -5
  134. package/dist/index.d.ts +13 -15
  135. package/dist/index.js +6 -8
  136. package/dist/observer/artifact.d.ts +1 -1
  137. package/dist/observer/artifact.js +1 -1
  138. package/dist/observer/data.d.ts +1 -1
  139. package/dist/observer/library.d.ts +2 -0
  140. package/dist/observer/library.js +4 -1
  141. package/dist/observer/render.js +7 -1
  142. package/dist/observer/run-routes.d.ts +1 -0
  143. package/dist/observer/run-routes.js +37 -12
  144. package/dist/observer/serve.d.ts +1 -1
  145. package/dist/observer-app.html +1 -1
  146. package/dist/routes/computer-use/bundle-parts.js +3 -2
  147. package/dist/routes/computer-use/bundle.d.ts +2 -2
  148. package/dist/routes/computer-use/bundle.js +7 -6
  149. package/dist/routes/computer-use/e2b-desktop/comms.d.ts +5 -5
  150. package/dist/routes/computer-use/e2b-desktop/comms.js +5 -4
  151. package/dist/routes/computer-use/e2b-desktop/fidelity.d.ts +1 -1
  152. package/dist/routes/computer-use/e2b-desktop/prepare.d.ts +1 -1
  153. package/dist/routes/computer-use/e2b-desktop/prepare.js +3 -3
  154. package/dist/routes/computer-use/e2b-desktop/start.js +3 -4
  155. package/dist/routes/computer-use/e2b-desktop/state.d.ts +2 -2
  156. package/dist/routes/computer-use/e2b-desktop/teardown.js +2 -3
  157. package/dist/routes/computer-use/external-comms.d.ts +3 -3
  158. package/dist/routes/computer-use/fanout-bundle.js +11 -10
  159. package/dist/routes/computer-use/fanout-records.js +2 -2
  160. package/dist/routes/computer-use/in-process-desktop.js +1 -1
  161. package/dist/routes/computer-use/live-flush.d.ts +3 -3
  162. package/dist/routes/computer-use/live-phase.d.ts +2 -3
  163. package/dist/routes/computer-use/live-phase.js +3 -3
  164. package/dist/routes/computer-use/local-tree-pack.d.ts +5 -5
  165. package/dist/routes/computer-use/local-tree-pack.js +1 -1
  166. package/dist/routes/computer-use/local-vm.d.ts +8 -8
  167. package/dist/routes/computer-use/local-vm.js +2 -2
  168. package/dist/routes/computer-use/participant-desktop.d.ts +3 -3
  169. package/dist/routes/computer-use/participant-desktop.js +1 -1
  170. package/dist/routes/computer-use/participant-execution.js +1 -1
  171. package/dist/routes/computer-use/participant-model.js +3 -3
  172. package/dist/routes/computer-use/participant-prompt.d.ts +5 -5
  173. package/dist/routes/computer-use/participant-prompt.js +3 -3
  174. package/dist/routes/computer-use/participant-runs.d.ts +10 -10
  175. package/dist/routes/computer-use/participant-runs.js +14 -13
  176. package/dist/routes/computer-use/plan.d.ts +12 -12
  177. package/dist/routes/computer-use/plan.js +27 -27
  178. package/dist/routes/computer-use/preflight.d.ts +5 -5
  179. package/dist/routes/computer-use/preflight.js +5 -5
  180. package/dist/routes/computer-use/rerun-selection.d.ts +1 -1
  181. package/dist/routes/computer-use/rerun-selection.js +3 -2
  182. package/dist/routes/computer-use/result.d.ts +4 -4
  183. package/dist/routes/computer-use/result.js +13 -12
  184. package/dist/routes/computer-use/route.d.ts +12 -12
  185. package/dist/routes/computer-use/route.js +19 -19
  186. package/dist/routes/computer-use/self-report.js +1 -1
  187. package/dist/routes/computer-use/setup.d.ts +22 -22
  188. package/dist/routes/computer-use/setup.js +15 -15
  189. package/dist/routes/computer-use/single-bundle.d.ts +4 -4
  190. package/dist/routes/computer-use/single-bundle.js +14 -13
  191. package/dist/routes/computer-use/subject-projection.d.ts +3 -3
  192. package/dist/routes/computer-use/types.d.ts +34 -34
  193. package/dist/routes/computer-use/types.js +3 -3
  194. package/dist/routes/preview.d.ts +6 -6
  195. package/dist/routes/preview.js +5 -5
  196. package/dist/routes/scripted/bundle.d.ts +6 -6
  197. package/dist/routes/scripted/bundle.js +10 -9
  198. package/dist/routes/scripted/plan.d.ts +7 -7
  199. package/dist/routes/scripted/plan.js +6 -6
  200. package/dist/routes/scripted/result.d.ts +3 -3
  201. package/dist/routes/scripted/result.js +9 -9
  202. package/dist/routes/scripted/route.d.ts +9 -9
  203. package/dist/routes/scripted/route.js +11 -11
  204. package/dist/routes/scripted/scenario.d.ts +1 -1
  205. package/dist/routes/scripted/scenario.js +3 -3
  206. package/dist/routes/scripted/setup.d.ts +6 -6
  207. package/dist/routes/scripted/setup.js +4 -4
  208. package/dist/routes/scripted/subject.d.ts +5 -5
  209. package/dist/routes/scripted/subject.js +3 -3
  210. package/dist/routes/scripted/surface-records.d.ts +1 -1
  211. package/dist/routes/scripted/surface-records.js +2 -2
  212. package/dist/routes/scripted/surface-sessions.d.ts +3 -3
  213. package/dist/routes/scripted/types.d.ts +17 -17
  214. package/dist/routes/scripted/types.js +1 -1
  215. package/dist/routes/shared-world/bundle-records.js +3 -3
  216. package/dist/routes/shared-world/bundle.js +15 -14
  217. package/dist/routes/shared-world/checkpoints.d.ts +3 -3
  218. package/dist/routes/shared-world/checkpoints.js +1 -1
  219. package/dist/routes/shared-world/comms.d.ts +9 -9
  220. package/dist/routes/shared-world/comms.js +6 -5
  221. package/dist/routes/shared-world/participant-specs.d.ts +3 -3
  222. package/dist/routes/shared-world/participant-specs.js +7 -7
  223. package/dist/routes/shared-world/plan.d.ts +9 -9
  224. package/dist/routes/shared-world/plan.js +9 -9
  225. package/dist/routes/shared-world/provisioned.d.ts +8 -8
  226. package/dist/routes/shared-world/provisioned.js +4 -4
  227. package/dist/routes/shared-world/result.d.ts +6 -6
  228. package/dist/routes/shared-world/result.js +11 -10
  229. package/dist/routes/shared-world/route.d.ts +11 -11
  230. package/dist/routes/shared-world/route.js +19 -19
  231. package/dist/routes/shared-world/setup.d.ts +13 -13
  232. package/dist/routes/shared-world/setup.js +19 -19
  233. package/dist/routes/shared-world/types.d.ts +27 -27
  234. package/dist/routes/terminal/adapter.d.ts +2 -2
  235. package/dist/routes/terminal/adapter.js +4 -4
  236. package/dist/routes/terminal/bundle.d.ts +11 -11
  237. package/dist/routes/terminal/bundle.js +12 -12
  238. package/dist/routes/terminal/credentials.d.ts +4 -4
  239. package/dist/routes/terminal/credentials.js +5 -5
  240. package/dist/routes/terminal/dry-run.d.ts +4 -4
  241. package/dist/routes/terminal/dry-run.js +9 -9
  242. package/dist/routes/terminal/ledger.d.ts +2 -2
  243. package/dist/routes/terminal/lifetime.d.ts +1 -1
  244. package/dist/routes/terminal/lifetime.js +1 -1
  245. package/dist/routes/terminal/live-finish.d.ts +2 -2
  246. package/dist/routes/terminal/live-finish.js +7 -7
  247. package/dist/routes/terminal/live-sandbox.d.ts +2 -2
  248. package/dist/routes/terminal/live-sandbox.js +3 -2
  249. package/dist/routes/terminal/participant-text.js +2 -1
  250. package/dist/routes/terminal/persona.d.ts +2 -2
  251. package/dist/routes/terminal/persona.js +2 -2
  252. package/dist/routes/terminal/plan.d.ts +7 -7
  253. package/dist/routes/terminal/plan.js +5 -5
  254. package/dist/routes/terminal/result.d.ts +5 -5
  255. package/dist/routes/terminal/result.js +7 -7
  256. package/dist/routes/terminal/route.d.ts +9 -9
  257. package/dist/routes/terminal/route.js +14 -14
  258. package/dist/routes/terminal/session.d.ts +5 -5
  259. package/dist/routes/terminal/session.js +7 -7
  260. package/dist/routes/terminal/trace.d.ts +2 -2
  261. package/dist/routes/terminal/types.d.ts +24 -24
  262. package/dist/routes/terminal/types.js +2 -2
  263. package/dist/run/bundle.d.ts +7 -7
  264. package/dist/run/bundle.js +2 -2
  265. package/dist/run/costs.d.ts +23 -0
  266. package/dist/run/costs.js +72 -43
  267. package/dist/run/dry-run-inputs.d.ts +1 -1
  268. package/dist/run/dry-run-inputs.js +1 -1
  269. package/dist/run/dry-run.js +2 -2
  270. package/dist/run/outcomes.d.ts +1 -1
  271. package/dist/run/participant.d.ts +1 -1
  272. package/dist/run/preflight-receipts.js +1 -1
  273. package/dist/run/pricing.js +2 -2
  274. package/dist/run/projection.d.ts +32 -32
  275. package/dist/run/projection.js +44 -44
  276. package/dist/run/reclaim.d.ts +1 -1
  277. package/dist/run/reclaim.js +1 -1
  278. package/dist/run/results.d.ts +2 -2
  279. package/dist/run/run-cost.d.ts +53 -0
  280. package/dist/run/run-cost.js +105 -0
  281. package/dist/run/run-index-analysis.d.ts +15 -0
  282. package/dist/run/run-index-analysis.js +77 -0
  283. package/dist/run/run-index.d.ts +11 -1
  284. package/dist/run/run-index.js +63 -49
  285. package/dist/run/run.d.ts +3 -3
  286. package/dist/run/run.js +2 -2
  287. package/dist/run/shared-world-evidence.d.ts +1 -1
  288. package/dist/run/shared-world-shape.js +1 -1
  289. package/dist/run/stats.d.ts +3 -3
  290. package/dist/run/stats.js +14 -14
  291. package/dist/run/status.d.ts +10 -2
  292. package/dist/run/status.js +6 -3
  293. package/dist/run/streams.d.ts +2 -2
  294. package/dist/run/study-provenance.d.ts +4 -2
  295. package/dist/run/study-provenance.js +7 -4
  296. package/dist/run/study-result.d.ts +0 -5
  297. package/dist/run/study-result.js +1 -1
  298. package/dist/run-study.d.ts +112 -0
  299. package/dist/{run-lab.js → run-study.js} +52 -45
  300. package/dist/{lab → study}/adapter-extension.d.ts +8 -20
  301. package/dist/{lab → study}/adapter-extension.js +2 -14
  302. package/dist/{lab → study}/adapter-scorer-loader.d.ts +10 -10
  303. package/dist/{lab → study}/adapter-scorer-loader.js +3 -3
  304. package/dist/study/composition-rules.d.ts +7 -0
  305. package/dist/{lab → study}/composition-rules.js +12 -12
  306. package/dist/study/config.d.ts +15 -0
  307. package/dist/{lab → study}/config.js +37 -20
  308. package/dist/study/convert.d.ts +1 -1
  309. package/dist/study/convert.js +15 -15
  310. package/dist/{lab → study}/device-presets.d.ts +2 -2
  311. package/dist/{lab → study}/discover.d.ts +29 -23
  312. package/dist/{lab → study}/discover.js +97 -118
  313. package/dist/{lab → study}/doctor.d.ts +11 -11
  314. package/dist/{lab → study}/doctor.js +18 -18
  315. package/dist/study/files.d.ts +2 -2
  316. package/dist/study/files.js +6 -5
  317. package/dist/{lab → study}/init-templates.d.ts +2 -2
  318. package/dist/{lab → study}/init-templates.js +16 -11
  319. package/dist/{lab → study}/init.d.ts +1 -1
  320. package/dist/{lab → study}/init.js +7 -4
  321. package/dist/{lab → study}/keys.d.ts +2 -2
  322. package/dist/{lab → study}/keys.js +10 -10
  323. package/dist/study/migrate.d.ts +8 -3
  324. package/dist/study/migrate.js +60 -4
  325. package/dist/{lab → study}/parse/actors.d.ts +5 -5
  326. package/dist/{lab → study}/parse/actors.js +5 -5
  327. package/dist/study/parse/comms.d.ts +12 -0
  328. package/dist/study/parse/execution.d.ts +19 -0
  329. package/dist/{lab → study}/parse/study-v3.d.ts +3 -5
  330. package/dist/{lab → study}/parse/study-v3.js +3 -3
  331. package/dist/{lab → study}/parse/subject-state.d.ts +8 -8
  332. package/dist/{lab → study}/parse/subject-state.js +4 -4
  333. package/dist/{lab → study}/parse/subject.d.ts +3 -3
  334. package/dist/{lab → study}/parse/subject.js +8 -8
  335. package/dist/{lab → study}/parse/values.d.ts +2 -2
  336. package/dist/{lab → study}/persona-resolve.d.ts +4 -4
  337. package/dist/{lab → study}/persona-resolve.js +2 -2
  338. package/dist/{lab → study}/plan-base.d.ts +7 -7
  339. package/dist/{lab → study}/plan-base.js +1 -1
  340. package/dist/{lab → study}/plan-participants.d.ts +10 -10
  341. package/dist/{lab → study}/plan-participants.js +4 -4
  342. package/dist/{lab → study}/plan-types.d.ts +28 -28
  343. package/dist/{lab → study}/plan-types.js +2 -2
  344. package/dist/study/plan.d.ts +13 -0
  345. package/dist/{lab → study}/plan.js +20 -20
  346. package/dist/study/preflight-probes.d.ts +3 -0
  347. package/dist/{lab → study}/preflight-probes.js +9 -8
  348. package/dist/study/preflight-result.d.ts +8 -0
  349. package/dist/{lab → study}/preflight-result.js +3 -3
  350. package/dist/{lab → study}/preflight.d.ts +31 -31
  351. package/dist/{lab → study}/preflight.js +8 -8
  352. package/dist/{lab → study}/requirements.d.ts +3 -3
  353. package/dist/{lab → study}/requirements.js +1 -1
  354. package/dist/study/route-inputs.d.ts +28 -0
  355. package/dist/{lab → study}/route-inputs.js +1 -1
  356. package/dist/{lab → study}/routing.d.ts +12 -12
  357. package/dist/{lab/run-lab-events.d.ts → study/run-study-events.d.ts} +10 -10
  358. package/dist/{lab/run-lab-events.js → study/run-study-events.js} +4 -4
  359. package/dist/{lab/run-lab-homes.d.ts → study/run-study-homes.d.ts} +8 -17
  360. package/dist/study/run-study-homes.js +3 -0
  361. package/dist/study/run-study-options.d.ts +28 -0
  362. package/dist/{lab/run-lab-options.js → study/run-study-options.js} +16 -15
  363. package/dist/{lab/lab-deps.d.ts → study/study-deps.d.ts} +2 -2
  364. package/dist/{lab/lab-deps.js → study/study-deps.js} +2 -2
  365. package/dist/{lab → study}/summary.d.ts +10 -10
  366. package/dist/{lab → study}/summary.js +15 -15
  367. package/dist/{lab → study}/tasks.d.ts +3 -3
  368. package/dist/{lab → study}/tasks.js +1 -1
  369. package/dist/{lab → study}/types.d.ts +104 -104
  370. package/dist/{lab → study}/types.js +1 -1
  371. package/dist/{lab → study}/validation.d.ts +19 -19
  372. package/dist/{lab → study}/validation.js +13 -13
  373. package/dist/{lab → study}/warnings.d.ts +4 -4
  374. package/dist/{lab → study}/warnings.js +1 -1
  375. package/dist/subject/clone.d.ts +6 -6
  376. package/dist/subject/clone.js +2 -2
  377. package/dist/subject/local-tree-archive.d.ts +2 -2
  378. package/dist/subject/local-tree-archive.js +3 -3
  379. package/dist/subject/local-tree.d.ts +3 -3
  380. package/dist/subject/runtime.js +2 -2
  381. package/dist/subject/serve.d.ts +4 -4
  382. package/dist/subject/state.d.ts +3 -3
  383. package/dist/subject/state.js +1 -1
  384. package/dist/subject/steps.d.ts +1 -1
  385. package/dist/subject/steps.js +1 -1
  386. package/dist/substrates/desktop-session.js +2 -2
  387. package/dist/substrates/detached.d.ts +1 -1
  388. package/dist/substrates/e2b/desktop-browser.d.ts +4 -4
  389. package/dist/substrates/e2b/desktop-browser.js +1 -1
  390. package/dist/substrates/e2b/desktop-cdp.d.ts +1 -1
  391. package/dist/substrates/e2b/desktop-cdp.js +1 -1
  392. package/dist/substrates/e2b/desktop-executor.d.ts +1 -1
  393. package/dist/substrates/e2b/desktop-executor.js +12 -12
  394. package/dist/substrates/e2b/desktop-geometry.d.ts +1 -1
  395. package/dist/substrates/e2b/desktop-geometry.js +1 -1
  396. package/dist/substrates/e2b/desktop-media.d.ts +3 -3
  397. package/dist/substrates/e2b/lifetime.js +1 -1
  398. package/dist/substrates/e2b/sandbox.d.ts +3 -3
  399. package/dist/substrates/e2b/sandbox.js +1 -1
  400. package/dist/substrates/e2b/sdk.d.ts +1 -1
  401. package/dist/substrates/e2b/sdk.js +1 -1
  402. package/dist/substrates/local/runtime-config.d.ts +4 -4
  403. package/dist/substrates/local/runtime-config.js +4 -4
  404. package/dist/tui/contract.d.ts +8 -8
  405. package/dist/tui/contract.js +2 -2
  406. package/dist/tui/launch.d.ts +3 -3
  407. package/dist/tui/launch.js +22 -16
  408. package/dist/tui-app.js +139 -139
  409. package/dist/verify/subject.d.ts +1 -1
  410. package/dist/verify/subject.js +1 -1
  411. package/dist/verify/verify.js +2 -1
  412. package/docs/architecture/actor-contract.md +5 -5
  413. package/docs/architecture/browser-control.md +1 -1
  414. package/docs/architecture/external-public-shared-world.md +8 -7
  415. package/docs/architecture/github-feedback-loop.md +1 -1
  416. package/docs/architecture/task-protocol-support.md +1 -1
  417. package/docs/architecture/terminal-product-route.md +18 -18
  418. package/docs/contracts/adapter-fixtures.md +2 -2
  419. package/docs/contracts/errors.md +8 -8
  420. package/docs/contracts/run-bundle.md +6 -4
  421. package/docs/contracts/schemas.md +61 -42
  422. package/docs/contracts/study-analysis.md +4 -1
  423. package/docs/contracts/study-costs.md +17 -2
  424. package/examples/README.md +1 -1
  425. package/examples/scorer/scorer.mjs +3 -3
  426. package/package.json +2 -1
  427. package/skills/humanish/SKILL.md +8 -6
  428. package/skills/humanish/agents/openai.yaml +1 -1
  429. package/dist/cli/commands/lab-format.d.ts +0 -9
  430. package/dist/cli/commands/lab-route-run.d.ts +0 -19
  431. package/dist/cli/commands/lab-route-scripted.d.ts +0 -17
  432. package/dist/cli/commands/lab-route-terminal.d.ts +0 -17
  433. package/dist/cli/commands/lab-run.d.ts +0 -9
  434. package/dist/lab/composition-rules.d.ts +0 -7
  435. package/dist/lab/config.d.ts +0 -7
  436. package/dist/lab/deprecated-fields.d.ts +0 -10
  437. package/dist/lab/deprecated-fields.js +0 -24
  438. package/dist/lab/parse/comms.d.ts +0 -12
  439. package/dist/lab/parse/execution.d.ts +0 -19
  440. package/dist/lab/plan.d.ts +0 -13
  441. package/dist/lab/preflight-probes.d.ts +0 -3
  442. package/dist/lab/preflight-result.d.ts +0 -8
  443. package/dist/lab/route-inputs.d.ts +0 -28
  444. package/dist/lab/run-lab-homes.js +0 -7
  445. package/dist/lab/run-lab-options.d.ts +0 -28
  446. package/dist/library-aliases.d.ts +0 -56
  447. package/dist/library-aliases.js +0 -22
  448. package/dist/run-lab.d.ts +0 -112
  449. /package/dist/{lab → study}/device-presets.js +0 -0
  450. /package/dist/{lab → study}/init-paths.d.ts +0 -0
  451. /package/dist/{lab → study}/init-paths.js +0 -0
  452. /package/dist/{lab → study}/init-plan.d.ts +0 -0
  453. /package/dist/{lab → study}/init-plan.js +0 -0
  454. /package/dist/{lab → study}/parse/comms.js +0 -0
  455. /package/dist/{lab → study}/parse/execution.js +0 -0
  456. /package/dist/{lab → study}/parse/values.js +0 -0
  457. /package/dist/{lab → study}/participant-assignment.d.ts +0 -0
  458. /package/dist/{lab → study}/participant-assignment.js +0 -0
  459. /package/dist/{lab → study}/persona.d.ts +0 -0
  460. /package/dist/{lab → study}/persona.js +0 -0
  461. /package/dist/{lab → study}/routing.js +0 -0
@@ -4,10 +4,11 @@
4
4
  // shape for pattern redaction to find.
5
5
  import { redactText, toErrorMessage } from "../evidence/redaction.js";
6
6
  import { scrubSecretValues } from "../evidence/secret-scrub.js";
7
- import { addressedRecipients } from "../lab/parse/comms.js";
7
+ import { addressedRecipients } from "../study/parse/comms.js";
8
8
  import { writeContainedOutputFile } from "../run/contained-output.js";
9
9
  import { FakeInbox } from "./fake-inbox.js";
10
10
  import { collectExternalCommsThread } from "./sandbox-catch.js";
11
+ import { plural } from "../run/text.js";
11
12
  /**
12
13
  * The shortest catch bearer token humanish uses. The token guards GET /deliveries on a host the run
13
14
  * reaches over the network, so it must not be guessable: 16 random base64 characters are 96 bits.
@@ -33,7 +34,7 @@ export function catchTokenRefusal(token) {
33
34
  return undefined;
34
35
  return `The comms catch token is ${token.length} characters; it must be at least ${MIN_CATCH_TOKEN_LENGTH}, such as the output of \`openssl rand -hex 16\`, on the catch and in the run.`;
35
36
  }
36
- /** The catch token the run sends: the value of `authTokenEnv`, when the lab names one. */
37
+ /** The catch token the run sends: the value of `authTokenEnv`, when the study names one. */
37
38
  export function catchTokenOf(external, env) {
38
39
  return external.authTokenEnv === undefined ? undefined : env[external.authTokenEnv];
39
40
  }
@@ -73,7 +74,7 @@ export async function collectExternalCommsEvidence(args) {
73
74
  if (collected.captured > 0) {
74
75
  return {
75
76
  warnings: scrubbed([
76
- `The email catch captured ${collected.captured} email send(s), but none matched a declared recipient inbox, so no email evidence was written. Set comms.email.recipients[].address to the address the app sends to.`,
77
+ `The email catch captured ${plural(collected.captured, "email send")}, but none matched a declared recipient inbox, so no email evidence was written. Set comms.email.recipients[].address to the address the app sends to.`,
77
78
  ]),
78
79
  };
79
80
  }
@@ -21,11 +21,11 @@ export declare class FakeInbox implements CommsChannel {
21
21
  constructor(options?: FakeInboxOptions);
22
22
  provision(participantId: string): Promise<CommsAddress>;
23
23
  /**
24
- * Provision an inbox for `participantId` at an explicit address (a lab-declared recipient), so
24
+ * Provision an inbox for `participantId` at an explicit address (a study-declared recipient), so
25
25
  * the app-under-test's send to that literal address resolves in `deliverRaw` (which drops
26
26
  * recipients with no provisioned inbox). Declaring the same address intentionally shares its
27
27
  * inbox; if `participantId` already held a different auto-generated address, the declared
28
- * address supersedes it (the lab's declaration wins). Idempotent: re-declaring the same address
28
+ * address supersedes it (the study's declaration wins). Idempotent: re-declaring the same address
29
29
  * returns the existing inbox without clearing it.
30
30
  */
31
31
  provisionAddress(participantId: string, value: string): Promise<CommsAddress>;
@@ -60,11 +60,11 @@ export class FakeInbox {
60
60
  return address;
61
61
  }
62
62
  /**
63
- * Provision an inbox for `participantId` at an explicit address (a lab-declared recipient), so
63
+ * Provision an inbox for `participantId` at an explicit address (a study-declared recipient), so
64
64
  * the app-under-test's send to that literal address resolves in `deliverRaw` (which drops
65
65
  * recipients with no provisioned inbox). Declaring the same address intentionally shares its
66
66
  * inbox; if `participantId` already held a different auto-generated address, the declared
67
- * address supersedes it (the lab's declaration wins). Idempotent: re-declaring the same address
67
+ * address supersedes it (the study's declaration wins). Idempotent: re-declaring the same address
68
68
  * returns the existing inbox without clearing it.
69
69
  */
70
70
  async provisionAddress(participantId, value) {
@@ -1,4 +1,4 @@
1
- import type { LabConfig } from "../lab/types.js";
1
+ import type { StudyConfig } from "../study/types.js";
2
2
  import { type CommsConnection } from "./connections.js";
3
3
  import { type KeyResolutionDeps } from "../keys/key-resolution.js";
4
4
  import type { ReceivingAdapter } from "./receiving-types.js";
@@ -14,9 +14,9 @@ export declare function resolveReceivingConnection(cwd: string, name: string, en
14
14
  apiKey: string;
15
15
  adapter: ReceivingAdapter;
16
16
  }>;
17
- /** What receiving reads from a lab: its email declaration and the subject env it guards. */
17
+ /** What receiving reads from a study: its email declaration and the subject env it guards. */
18
18
  export interface ReceivingSource {
19
- readonly comms?: LabConfig["comms"];
19
+ readonly comms?: StudyConfig["comms"];
20
20
  readonly subject: {
21
21
  readonly env?: readonly string[];
22
22
  readonly envValues?: Readonly<Record<string, string>>;
@@ -32,7 +32,7 @@ export declare function prepareReceivingRun(args: {
32
32
  registerSecrets(values: string[]): void;
33
33
  }): Promise<import("./receiving.js").CommsReceivingRun | undefined>;
34
34
  /** The restriction survives restarts and screenshot redaction; it is not a claim of local processing. */
35
- export declare function receivingPublication(config: Pick<LabConfig, "comms">, dryRun: boolean): {
35
+ export declare function receivingPublication(config: Pick<StudyConfig, "comms">, dryRun: boolean): {
36
36
  publication: {
37
37
  restrictions: ["real-communications"];
38
38
  };
@@ -78,7 +78,7 @@ export declare function drainCommsCatch(shell: Shell, deployed: Pick<DeployedCom
78
78
  export declare function parseDeliveriesNdjson(text: string): RawCapturedSend[];
79
79
  /**
80
80
  * The distinct `to` addresses the captured mail was actually sent to, parsed with the same profiles
81
- * that route it. A lab run knows its recipients from the declared roster; a standalone catch does not,
81
+ * that route it. A run knows its recipients from the declared roster; a standalone catch does not,
82
82
  * so it discovers them from the mail itself. Otherwise an operator who forgot to name an address gets
83
83
  * a technically-healthy catch rendering an empty inbox forever: a false green.
84
84
  */
@@ -139,7 +139,7 @@ export declare function externalInboxUrl(external: ExternalCommsCatch): string;
139
139
  /**
140
140
  * Probe an adopter-hosted catch the way the in-sandbox one is probed: assert humanish's service marker in
141
141
  * /health, not merely any 2xx: an adopter's reverse proxy or a captive portal will happily return
142
- * 200 for anything, and a comms lab whose catch is not actually there collects nothing while
142
+ * 200 for anything, and a comms study whose catch is not actually there collects nothing while
143
143
  * looking fine. Fail-closed callers treat `false` as a hard stop before spending on a run.
144
144
  */
145
145
  export declare function externalCatchHealthy(external: ExternalCommsCatch, options?: {
@@ -171,7 +171,7 @@ export function parseDeliveriesNdjson(text) {
171
171
  }
172
172
  /**
173
173
  * The distinct `to` addresses the captured mail was actually sent to, parsed with the same profiles
174
- * that route it. A lab run knows its recipients from the declared roster; a standalone catch does not,
174
+ * that route it. A run knows its recipients from the declared roster; a standalone catch does not,
175
175
  * so it discovers them from the mail itself. Otherwise an operator who forgot to name an address gets
176
176
  * a technically-healthy catch rendering an empty inbox forever: a false green.
177
177
  */
@@ -298,7 +298,7 @@ export function externalInboxUrl(external) {
298
298
  /**
299
299
  * Probe an adopter-hosted catch the way the in-sandbox one is probed: assert humanish's service marker in
300
300
  * /health, not merely any 2xx: an adopter's reverse proxy or a captive portal will happily return
301
- * 200 for anything, and a comms lab whose catch is not actually there collects nothing while
301
+ * 200 for anything, and a comms study whose catch is not actually there collects nothing while
302
302
  * looking fine. Fail-closed callers treat `false` as a hard stop before spending on a run.
303
303
  */
304
304
  export async function externalCatchHealthy(external, options = {}) {
@@ -55,9 +55,9 @@ export interface CommsConfigureResult {
55
55
  connection?: string;
56
56
  }
57
57
  /** Save a local copy, never rewrite a committed manifest or silently shadow it by handle. */
58
- export declare function configureCommsLab(args: {
58
+ export declare function configureCommsStudy(args: {
59
59
  cwd: string;
60
- lab: string;
60
+ study: string;
61
61
  connection: string;
62
62
  apply?: boolean;
63
63
  planToken?: string;
@@ -8,11 +8,10 @@ import { discoverProviderKeys, listUserKeys, probeKeySources, } from "../keys/ke
8
8
  import { COMMS_PROVIDERS, commsProviderLabel, DEFAULT_COMMS_PROVIDER, } from "./providers.js";
9
9
  import { createReceivingAdapter } from "./receiving-runtime.js";
10
10
  import { RECEIVING_SCOPE_UNSUPPORTED } from "./receiving-types.js";
11
- import { parseLabConfig } from "../lab/config.js";
12
- import { resolveLabManifest } from "../lab/discover.js";
11
+ import { parseStudy } from "../study/config.js";
12
+ import { resolveStudyManifest } from "../study/discover.js";
13
13
  import { assertPreparedSelectedOutputDirectory, prepareManagedHumanishOutputDirectory, prepareSelectedOutputDirectory, readContainedRegularFile, writeContainedOutputFile, } from "../run/contained-output.js";
14
14
  import { otherStudyFiles } from "../study/files.js";
15
- import { convertStudyText, isStudyV3 } from "../study/convert.js";
16
15
  import { isNodeError } from "../run/type-guards.js";
17
16
  export async function checkCommsConnection(args) {
18
17
  const base = {
@@ -109,65 +108,63 @@ export async function receivingRequiredKey(cwd, connectionName) {
109
108
  }
110
109
  }
111
110
  /** Save a local copy, never rewrite a committed manifest or silently shadow it by handle. */
112
- export async function configureCommsLab(args) {
111
+ export async function configureCommsStudy(args) {
113
112
  const base = { schema: "humanish.comms-configure.v1", ok: false, applied: false };
114
113
  try {
115
114
  const connection = (await readCommsConnections(args.cwd)).connections[args.connection];
116
115
  if (!connection)
117
116
  return { ...base, message: "Save the selected connection first." };
118
- const source = await resolveLabManifest(args.cwd, args.lab);
119
- if (!source.ok)
120
- return { ...base, message: "The selected lab could not be read safely." };
117
+ const source = await resolveStudyManifest(args.cwd, args.study);
118
+ if (!source.ok) {
119
+ // A v2 source or a labs/ file gets discovery's refusal, which names the fix.
120
+ const named = source.error.code === "HUMANISH_STUDY_V2_UNSUPPORTED" ||
121
+ source.error.code === "HUMANISH_STUDY_RETIRED_DIRECTORY";
122
+ return {
123
+ ...base,
124
+ message: named ? source.error.message : "The selected study could not be read safely.",
125
+ };
126
+ }
121
127
  const root = await prepareSelectedOutputDirectory(args.cwd, args.cwd);
122
128
  const rel = path
123
129
  .relative(root.requestedPath, path.resolve(args.cwd, source.path))
124
130
  .replace(/\\/g, "/");
125
131
  const bytes = await readContainedRegularFile(root, rel);
126
132
  if (!bytes || bytes.length > 1024 * 1024)
127
- return { ...base, message: "The lab is missing or too large." };
133
+ return { ...base, message: "The study file is missing or too large." };
128
134
  const text = bytes.toString("utf8");
129
135
  const raw = parse(text);
130
136
  if (!raw || typeof raw !== "object" || Array.isArray(raw))
131
- return { ...base, message: "The lab must be a mapping." };
132
- const lab = raw;
133
- const existing = lab.comms;
137
+ return { ...base, message: "The study file must be a mapping." };
138
+ const studyRecord = raw;
139
+ const existing = studyRecord.comms;
134
140
  if (existing?.email && existing.email.connection === undefined)
135
141
  return {
136
142
  ...base,
137
- message: "This lab uses local capture. Preserve it or make a separate lab before selecting real email.",
143
+ message: "This study uses local capture. Preserve it or make a separate study before selecting real email.",
138
144
  };
139
- // The copy is a v3 study. A v2 source is converted first, so the copy keeps its comments.
140
- let studyText = text;
141
- if (!isStudyV3(raw)) {
142
- const converted = convertStudyText(text, args.cwd);
143
- if (!converted.ok)
144
- return {
145
- ...base,
146
- message: `This lab could not be converted to a v3 study: ${converted.reason}`,
147
- };
148
- studyText = converted.conversion.text;
149
- }
150
- const study = parseDocument(studyText);
145
+ // Discovery resolved the source, so it is a v3 study, and the copy keeps its comments.
146
+ const study = parseDocument(text);
151
147
  study.setIn(["comms", "email", "connection"], args.connection);
152
- const validated = parseLabConfig(study.toJS());
148
+ const validated = parseStudy(study.toJS());
153
149
  if (!validated.ok)
154
150
  return {
155
151
  ...base,
156
- message: "This lab does not support real email receiving. Use a hosted computer-use app-url, clone or local-tree route; shared-world must be concurrent.",
152
+ message: "This study does not support real email receiving. Use a hosted computer-use app-url, clone or local-tree route; shared-world must be concurrent.",
157
153
  };
158
154
  const filename = path
159
155
  .basename(source.path)
160
156
  .replace(/\.ya?ml$/, "")
161
157
  .replace(/-receiving$/, "") + "-receiving.yaml";
162
158
  if (!/^[A-Za-z0-9_][A-Za-z0-9._-]{0,110}\.yaml$/.test(filename))
163
- return { ...base, message: "Use a simple lab filename before configuring email." };
159
+ return { ...base, message: "Use a simple study filename before configuring email." };
164
160
  const destination = `.humanish/local/studies/${filename}`;
165
161
  if (path.basename(rel) === filename)
166
162
  return {
167
163
  ...base,
168
- message: "This is already the local receiving copy. Select its original lab to configure a separate copy, or edit this manifest directly.",
164
+ message: "This is already the local receiving copy. Select its original study to configure a separate copy, or edit this study file directly.",
169
165
  };
170
- // A second file with this name in another study directory would make discovery refuse both.
166
+ // A second file with this name in another study directory would shadow it, or take the name
167
+ // migrate needs to move a labs/ file.
171
168
  const stem = filename.replace(/\.yaml$/, "");
172
169
  const others = await otherStudyFiles(stem,
173
170
  // Any directory entry counts, a dangling symbolic link included: discovery would see it too.
@@ -215,7 +212,7 @@ export async function configureCommsLab(args) {
215
212
  if (args.planToken !== undefined && args.planToken !== token)
216
213
  return {
217
214
  ...base,
218
- message: "The lab or destination changed since preview. Preview again before saving.",
215
+ message: "The study or destination changed since preview. Preview again before saving.",
219
216
  };
220
217
  const directory = await prepareManagedHumanishOutputDirectory(args.cwd, "local", "studies");
221
218
  const lockPath = path.join(directory.physicalPath, ".comms-configure.lock");
@@ -239,13 +236,13 @@ export async function configureCommsLab(args) {
239
236
  return {
240
237
  ...plan,
241
238
  applied: true,
242
- message: `Saved ${destination}. Start that exact lab path; the original manifest was preserved.`,
239
+ message: `Saved ${destination}. Start that exact study path; the original file was preserved.`,
243
240
  };
244
241
  }
245
242
  catch {
246
243
  return {
247
244
  ...base,
248
- message: "Could not configure this lab safely. Check configuration, paths and permissions; no provider resources were created.",
245
+ message: "Could not configure this study safely. Check configuration, paths and permissions; no provider resources were created.",
249
246
  };
250
247
  }
251
248
  }
@@ -2,6 +2,17 @@
2
2
  export declare function sensitivePatterns(): readonly RegExp[];
3
3
  /** True if the text contains any secret-shaped token or known local path. */
4
4
  export declare function containsSensitive(text: string): boolean;
5
+ /**
6
+ * What a shared copy of a run says in place of a provider sandbox id. scripts/public-surface-scan.mjs
7
+ * passes only this value at a sandbox-id key.
8
+ */
9
+ export declare const REDACTED_SANDBOX_ID = "[redacted-sandbox-id]";
10
+ /**
11
+ * `value` with every sandbox id replaced by REDACTED_SANDBOX_ID: strings at `sandboxId` and
12
+ * `subjectSandboxId`, and the `id` of each `providerResources` entry. A run keeps raw ids as local
13
+ * evidence for cleanup; a copy made to be shared names no sandbox.
14
+ */
15
+ export declare function redactSandboxIds(value: unknown): unknown;
5
16
  /** Redact secrets to [REDACTED_SECRET] and local paths to their path labels. */
6
17
  export declare function redactText(text: string): string;
7
18
  /** Redact every sensitive match (secrets and paths) to a single [REDACTED_SECRET] label. */
@@ -55,6 +55,49 @@ export function containsSensitive(text) {
55
55
  function redactLocalPaths(text, label) {
56
56
  return LOCAL_PATH_PATTERNS.reduce((current, [pattern, replacement]) => current.replace(pattern, (match) => (label ?? replacement) + (match.match(/\\+$/)?.[0] ?? "")), text);
57
57
  }
58
+ /**
59
+ * What a shared copy of a run says in place of a provider sandbox id. scripts/public-surface-scan.mjs
60
+ * passes only this value at a sandbox-id key.
61
+ */
62
+ export const REDACTED_SANDBOX_ID = "[redacted-sandbox-id]";
63
+ /** The keys run writers put a sandbox id under; `providerResources` entries hold one as `id`. */
64
+ const SANDBOX_ID_KEYS = new Set(["sandboxId", "subjectSandboxId"]);
65
+ /**
66
+ * `value` with every sandbox id replaced by REDACTED_SANDBOX_ID: strings at `sandboxId` and
67
+ * `subjectSandboxId`, and the `id` of each `providerResources` entry. A run keeps raw ids as local
68
+ * evidence for cleanup; a copy made to be shared names no sandbox.
69
+ */
70
+ export function redactSandboxIds(value) {
71
+ if (Array.isArray(value)) {
72
+ const items = value.map(redactSandboxIds);
73
+ return items.every((item, index) => item === value[index]) ? value : items;
74
+ }
75
+ if (value === null || typeof value !== "object")
76
+ return value;
77
+ let changed = false;
78
+ // fromEntries keeps a key such as __proto__ an own property, as JSON.parse made it.
79
+ const entries = Object.entries(value).map(([key, child]) => {
80
+ let next;
81
+ if (SANDBOX_ID_KEYS.has(key) && typeof child === "string")
82
+ next = REDACTED_SANDBOX_ID;
83
+ else if (key === "providerResources" && Array.isArray(child))
84
+ next = child.map((resource) => resource !== null &&
85
+ typeof resource === "object" &&
86
+ !Array.isArray(resource) &&
87
+ "id" in resource
88
+ ? Object.fromEntries(Object.entries(redactSandboxIds(resource)).map(([field, entry]) => [
89
+ field,
90
+ field === "id" ? REDACTED_SANDBOX_ID : entry,
91
+ ]))
92
+ : redactSandboxIds(resource));
93
+ else
94
+ next = redactSandboxIds(child);
95
+ if (next !== child && JSON.stringify(next) !== JSON.stringify(child))
96
+ changed = true;
97
+ return [key, next];
98
+ });
99
+ return changed ? Object.fromEntries(entries) : value;
100
+ }
58
101
  /** Redact secrets to [REDACTED_SECRET] and local paths to their path labels. */
59
102
  export function redactText(text) {
60
103
  const withoutSecrets = SECRET_PATTERNS.reduce((current, pattern) => current.replace(pattern, "[REDACTED_SECRET]"), text);
@@ -100,7 +100,7 @@ export function buildDraft(bundle, bundlePath, candidateId) {
100
100
  proposed_next_state: "study-quality-review",
101
101
  acceptance_proof: [
102
102
  feedbackProofCommands(bundle.runId).verify,
103
- feedbackProofCommands(bundle.runId).watch,
103
+ feedbackProofCommands(bundle.runId).observe,
104
104
  ],
105
105
  };
106
106
  }
@@ -192,7 +192,7 @@ export async function buildAnalysisDraft(context, options) {
192
192
  proposed_next_state: "study-quality-review",
193
193
  acceptance_proof: [
194
194
  feedbackProofCommands(bundle.runId).verify,
195
- feedbackProofCommands(bundle.runId).watch,
195
+ feedbackProofCommands(bundle.runId).observe,
196
196
  ],
197
197
  };
198
198
  }
@@ -8,7 +8,7 @@ import { parse as parseYaml } from "yaml";
8
8
  import { ACTOR_TRACE_SCHEMA } from "../actors/contract.js";
9
9
  import { renderObserver } from "../observer/render.js";
10
10
  import { buildObserverData } from "../observer/data.js";
11
- import { containsSensitive, redactScreenshot, redactText } from "../evidence/redaction.js";
11
+ import { containsSensitive, redactSandboxIds, redactScreenshot, redactText, } from "../evidence/redaction.js";
12
12
  import { decodeEscapes } from "../evidence/encoded-text.js";
13
13
  import { readPlainText } from "../evidence/plain-text.js";
14
14
  import { streamScreenshotPaths } from "../verify/artifacts.js";
@@ -224,7 +224,8 @@ function transformText(file, imagePaths) {
224
224
  const parsed = JSON.parse(text);
225
225
  // Parsing also resolves escape sequences in string values before inspection.
226
226
  assertNoInlineRaster(JSON.stringify(parsed));
227
- const transformed = updateScreenshotDeclarations(parsed, imagePaths);
227
+ // The copy names no sandbox: an id is local operational evidence, and the copy is shared.
228
+ const transformed = redactSandboxIds(updateScreenshotDeclarations(parsed, imagePaths));
228
229
  if (JSON.stringify(transformed) === JSON.stringify(parsed))
229
230
  return file.bytes;
230
231
  assertRewritableNumbers(text);
@@ -237,7 +238,7 @@ function transformText(file, imagePaths) {
237
238
  return line;
238
239
  const parsed = JSON.parse(line);
239
240
  assertNoInlineRaster(JSON.stringify(parsed));
240
- const updated = JSON.stringify(updateScreenshotDeclarations(parsed, imagePaths));
241
+ const updated = JSON.stringify(redactSandboxIds(updateScreenshotDeclarations(parsed, imagePaths)));
241
242
  if (updated === JSON.stringify(parsed))
242
243
  return line;
243
244
  assertRewritableNumbers(line);
@@ -329,7 +330,7 @@ async function writeDerivative(source, stagePaths, bundle) {
329
330
  bytes = transformText(file, imagePaths);
330
331
  if (file.path === "run.json") {
331
332
  assertRewritableNumbers(file.bytes.toString("utf8"));
332
- const transformed = updateScreenshotDeclarations(bundle, imagePaths);
333
+ const transformed = redactSandboxIds(updateScreenshotDeclarations(bundle, imagePaths));
333
334
  transformed.redaction = {
334
335
  status: "passed",
335
336
  notes: `${bundle.redaction.notes} Exported copy: screenshots were blurred during export; the original capture is retained separately. See derivation.json.`,
@@ -23,6 +23,7 @@ import { analysisSharingProblems } from "../analysis/sharing.js";
23
23
  import { EVIDENCE_LIMITS, validateAnalysisEvidence } from "../analysis/evidence.js";
24
24
  import { readBoundedFile } from "../run/evidence-files.js";
25
25
  import { shellQuote } from "../substrates/shell.js";
26
+ import { plural } from "../run/text.js";
26
27
  const EXPORT_SCHEMA = "humanish.export-result.v1";
27
28
  /** Past this the file stops being a thing you attach to an email. Declared, never silent. */
28
29
  export const DEFAULT_EXPORT_MAX_BYTES = 25 * 1024 * 1024;
@@ -361,7 +362,7 @@ export function formatExportHuman(result) {
361
362
  if (result.format === "bundle") {
362
363
  return [
363
364
  `humanish export ${result.runId}`,
364
- `workspace: ${result.path} (${(result.bytes / 1024).toFixed(0)} KB, ${result.embeddedImages} blurred image(s))`,
365
+ `workspace: ${result.path} (${(result.bytes / 1024).toFixed(0)} KB, ${plural(result.embeddedImages, "blurred image")})`,
365
366
  `share safety: ${result.shareSafety.status}`,
366
367
  `verify: humanish verify --cwd ${shellQuote(result.path)} --run ${shellQuote(result.runId)}`,
367
368
  `feedback: humanish feedback draft --cwd ${shellQuote(result.path)} --run ${shellQuote(result.runId)}`,
@@ -371,7 +372,7 @@ export function formatExportHuman(result) {
371
372
  }
372
373
  const lines = [
373
374
  `humanish export ${result.runId}`,
374
- `file: ${result.path} (${(result.bytes / 1024).toFixed(0)} KB, ${result.embeddedImages} image(s) embedded)`,
375
+ `file: ${result.path} (${(result.bytes / 1024).toFixed(0)} KB, ${plural(result.embeddedImages, "image")} embedded)`,
375
376
  `share safety: ${result.shareSafety.status}${result.watermarked ? " (watermarked: local only)" : ""}`,
376
377
  ...result.warnings.map((warning) => `warning: ${warning}`),
377
378
  ];
@@ -2,7 +2,7 @@ import type { RunBundle, RunFeedbackCandidate } from "../run/bundle.js";
2
2
  /** Commands run from the evidence workspace using an installed humanish CLI. */
3
3
  export declare function feedbackProofCommands(runId: string): {
4
4
  verify: string;
5
- watch: string;
5
+ observe: string;
6
6
  };
7
7
  /** Legacy command compatibility belongs in the draft, never in the source receipt. */
8
8
  export declare function projectFeedbackAcceptanceProof(bundle: RunBundle, candidate: RunFeedbackCandidate): string[];
@@ -5,7 +5,7 @@ export function feedbackProofCommands(runId) {
5
5
  const argument = /^[a-z0-9][a-z0-9._-]*$/i.test(runId) ? runId : shellQuote(runId);
6
6
  return {
7
7
  verify: `humanish verify --run ${argument} --json`,
8
- watch: `humanish watch --run ${argument} --no-open`,
8
+ observe: `humanish observe --run ${argument} --no-open`,
9
9
  };
10
10
  }
11
11
  /** Legacy command compatibility belongs in the draft, never in the source receipt. */
@@ -17,7 +17,7 @@ export function projectFeedbackAcceptanceProof(bundle, candidate) {
17
17
  if (instruction === `pnpm humanish -- verify --run ${bundle.runId} --json`)
18
18
  return commands.verify;
19
19
  if (instruction === `pnpm humanish -- watch --run ${bundle.runId} --no-open`)
20
- return commands.watch;
20
+ return commands.observe;
21
21
  return instruction;
22
22
  });
23
23
  }
@@ -1,6 +1,6 @@
1
1
  import { desktopRecordingConfigSchema, } from "../evidence/desktop-recording-types.js";
2
2
  import { validateBrowserControlIdentity, sameBrowserControlIdentity, } from "../browser-control/protocol.js";
3
- import { CuaExecutorError } from "../actors/computer-use/executor-error.js";
3
+ import { ComputerUseExecutorError } from "../actors/computer-use/executor-error.js";
4
4
  import { createBrowserControlClient } from "../browser-control/client.js";
5
5
  import { guestMediaConfigSchema } from "./media-config.js";
6
6
  export const GUEST_BOOTSTRAP_VERSION = 1;
@@ -15,7 +15,7 @@ export const GUEST_BOOTSTRAP_LIMITS = Object.freeze({
15
15
  connectMs: 3000,
16
16
  port: 5251,
17
17
  });
18
- const refused = () => new CuaExecutorError("protocol_mismatch", "not_dispatched");
18
+ const refused = () => new ComputerUseExecutorError("protocol_mismatch", "not_dispatched");
19
19
  /** Same entry authority as the local desktop's opaque app-port forward. */
20
20
  export function validateGuestInitialUrl(value) {
21
21
  try {
@@ -223,7 +223,7 @@ export class GuestBootstrapReader {
223
223
  return;
224
224
  this.terminal = true;
225
225
  this.release();
226
- this.reject(new CuaExecutorError(code, "not_dispatched"));
226
+ this.reject(new ComputerUseExecutorError(code, "not_dispatched"));
227
227
  this.stream.destroy();
228
228
  this.onFailure();
229
229
  }
@@ -249,7 +249,7 @@ export async function connectGuestBootstrap(stream, identity, signal, initialUrl
249
249
  const request = encodeGuestBootstrap(identity, false, initialUrl, media, recording);
250
250
  await new Promise((resolve, reject) => {
251
251
  let bytes = Buffer.alloc(0), done = false;
252
- const timer = setTimeout(() => finish(new CuaExecutorError("deadline_exceeded", "not_dispatched")), GUEST_BOOTSTRAP_LIMITS.connectMs);
252
+ const timer = setTimeout(() => finish(new ComputerUseExecutorError("deadline_exceeded", "not_dispatched")), GUEST_BOOTSTRAP_LIMITS.connectMs);
253
253
  const finish = (error) => {
254
254
  if (done)
255
255
  return;
@@ -277,9 +277,9 @@ export async function connectGuestBootstrap(stream, identity, signal, initialUrl
277
277
  const end = () => {
278
278
  if (done)
279
279
  stream.destroy();
280
- finish(new CuaExecutorError("transport_failed", "not_dispatched"));
280
+ finish(new ComputerUseExecutorError("transport_failed", "not_dispatched"));
281
281
  };
282
- const abort = () => finish(new CuaExecutorError("session_revoked", "not_dispatched"));
282
+ const abort = () => finish(new ComputerUseExecutorError("session_revoked", "not_dispatched"));
283
283
  const data = (chunk) => {
284
284
  if (!Buffer.isBuffer(chunk) || bytes.length + chunk.length > 64 + 1028) {
285
285
  finish(refused());
@@ -1,5 +1,5 @@
1
1
  import { BROWSER_CONTROL_LIMITS } from "../browser-control/protocol.js";
2
- import { CuaExecutorError, isCuaExecutorError } from "../actors/computer-use/executor-error.js";
2
+ import { ComputerUseExecutorError, isComputerUseExecutorError, } from "../actors/computer-use/executor-error.js";
3
3
  /** Owner-only composition for a single headed Chromium page. Never an actor API. */
4
4
  export function createGuestBrowserTools(native, content) {
5
5
  let addressBarArmed = false;
@@ -11,7 +11,7 @@ export function createGuestBrowserTools(native, content) {
11
11
  const inputGeneration = ++generation;
12
12
  await native.input(args, signal);
13
13
  if (signal.aborted || inputGeneration !== generation)
14
- throw new CuaExecutorError("session_revoked", "outcome_uncertain");
14
+ throw new ComputerUseExecutorError("session_revoked", "outcome_uncertain");
15
15
  // Positive navigation intent, not an inference from document.hasFocus().
16
16
  addressBarArmed =
17
17
  args.length === 3 &&
@@ -28,15 +28,15 @@ export function createGuestBrowserTools(native, content) {
28
28
  // separate qualification. Do not silently switch routes or transliterate.
29
29
  if (!/^[\x20-\x7e]+$/.test(text) ||
30
30
  Buffer.byteLength(text) > BROWSER_CONTROL_LIMITS.textBytes) {
31
- throw new CuaExecutorError("action_rejected", "not_dispatched");
31
+ throw new ComputerUseExecutorError("action_rejected", "not_dispatched");
32
32
  }
33
33
  const preparedGeneration = generation;
34
34
  let used = false;
35
35
  function check() {
36
36
  if (signal.aborted)
37
- throw new CuaExecutorError("session_revoked", "not_dispatched");
37
+ throw new ComputerUseExecutorError("session_revoked", "not_dispatched");
38
38
  if (used || preparedGeneration !== generation)
39
- throw new CuaExecutorError("action_rejected", "not_dispatched");
39
+ throw new ComputerUseExecutorError("action_rejected", "not_dispatched");
40
40
  }
41
41
  check();
42
42
  await content.assertReady(signal);
@@ -52,15 +52,15 @@ export function createGuestBrowserTools(native, content) {
52
52
  try {
53
53
  await native.input(["key", "--clearmodifiers", "ctrl+l"], signal);
54
54
  if (signal.aborted)
55
- throw new CuaExecutorError("session_revoked", "outcome_uncertain");
55
+ throw new ComputerUseExecutorError("session_revoked", "outcome_uncertain");
56
56
  await content.assertReady(signal);
57
57
  if (signal.aborted || preparedGeneration !== generation)
58
- throw new CuaExecutorError("session_revoked", "outcome_uncertain");
58
+ throw new ComputerUseExecutorError("session_revoked", "outcome_uncertain");
59
59
  await native.typeAscii(text, signal);
60
60
  }
61
61
  catch (error) {
62
62
  // Ctrl+L itself is input. No content fallback after that dispatch.
63
- throw new CuaExecutorError(isCuaExecutorError(error) ? error.code : "execution_failed", "outcome_uncertain");
63
+ throw new ComputerUseExecutorError(isComputerUseExecutorError(error) ? error.code : "execution_failed", "outcome_uncertain");
64
64
  }
65
65
  },
66
66
  async close() {