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
@@ -2,28 +2,29 @@ import { isMaxOutputTokens } from "../actors/output-token-limit.js";
2
2
  import { PARTICIPANT_ID_MAX_CHARS, PARTICIPANT_ID_PATTERN, focusOf, rosterOf, } from "./parse/actors.js";
3
3
  import { isHttpUrl, isLoopbackUrl } from "./parse/subject.js";
4
4
  import { declaredTargets } from "./plan-participants.js";
5
- import { actorResolvesToComputerUse, cuaLaneCount, MAX_CUA_LANES, registeredComputerUseActors, resolveSeatUrl, isComputerUseComposition, isScriptedBrowserComposition, isSharedWorldComposition, isTerminalProductComposition, } from "./routing.js";
5
+ import { actorResolvesToComputerUse, computerUseParticipantCount, MAX_COMPUTER_USE_PARTICIPANTS, registeredComputerUseActors, resolveEntryUrl, isComputerUseComposition, isScriptedBrowserComposition, isSharedWorldComposition, isTerminalProductComposition, } from "./routing.js";
6
6
  /**
7
7
  * Cross-validate the computer-use fan-out declaration (`per-lane-worlds`). Returns the failure
8
- * message, or null when valid. Enforced at parse and re-enforced in the engine (runCuaActorLab
9
- * is itself exported npm surface). Structural roster shape (id/device validity, id uniqueness) is
10
- * already checked in parseLanes; this is the route-scoped XOR/cap/policy layer.
8
+ * message, or null when valid. The parser enforces it, and runLab checks it again for a config
9
+ * that skipped the parser. It runs rosterStructuralValidationReason (id and device
10
+ * validity, unique ids) first, then the route-scoped XOR, cap and policy checks.
11
11
  */
12
- export function cuaLaneValidationReason(config) {
12
+ export function computerUseValidationReason(config) {
13
13
  const actor = config.actors[0];
14
14
  const roster = rosterOf(actor);
15
15
  const structuralReason = rosterStructuralValidationReason(config);
16
16
  if (structuralReason) {
17
17
  return structuralReason;
18
18
  }
19
- // clone.fanout is a declared behavior change: rejected on the cua route (was inert-warned).
20
- // Fan-out is declared via `actors[0].count` or `actors[0].lanes`; subject.clone.fanout never applied here.
19
+ // clone.fanout is a declared behavior change: rejected on the computer-use route (was
20
+ // inert-warned). Fan-out is declared via `actors[0].count` or `actors[0].lanes`;
21
+ // subject.clone.fanout never applied here.
21
22
  if (config.subject.clone?.fanout !== undefined) {
22
23
  return "`subject.clone.fanout` is not used on the computer-use route: declare fan-out with actors[0].count (homogeneous) or actors[0].lanes (a roster of participants). (No current route reads clone.fanout.)";
23
24
  }
24
25
  if (roster !== undefined) {
25
26
  if (actor?.count !== undefined) {
26
- return "Declare EITHER actors[0].count (a homogeneous participant count) OR actors[0].lanes (a differentiated roster), not both.";
27
+ return "Set either `actors[0].count` (identical participants) or `actors[0].lanes` (a roster of distinct participants), not both.";
27
28
  }
28
29
  if (focusOf(actor) !== undefined) {
29
30
  return "actors[0].laneFocus and actors[0].lanes are mutually exclusive: each roster entry's `instruction` is the fan-out steer; laneFocus is the steer for a single participant.";
@@ -35,7 +36,7 @@ export function cuaLaneValidationReason(config) {
35
36
  const targeted = roster.filter((entry) => entry.target !== undefined);
36
37
  if (targeted.length > 0) {
37
38
  if (config.subject.source !== "app-url") {
38
- return "actors[0].lanes[].target is supported only on app-url computer-use labs — clone/shared-world/local-app routes provision or own their entry URL by mechanism.";
39
+ return "`actors[0].lanes[].target` works only on app-url computer-use studies. Clone, shared-world and local-app studies set each participant's entry URL themselves; remove `target`.";
39
40
  }
40
41
  if (roster.some((entry) => entry.entry !== undefined)) {
41
42
  return "actors[0].lanes[].target and actors[0].lanes[].entry are mutually exclusive: target is an app-url fan-out browser URL; entry is a shared-world same-origin participant path.";
@@ -45,21 +46,21 @@ export function cuaLaneValidationReason(config) {
45
46
  }
46
47
  }
47
48
  }
48
- const participantCount = cuaLaneCount(config);
49
- if (participantCount > MAX_CUA_LANES) {
50
- return `Computer-use fan-out is capped at ${MAX_CUA_LANES} participants (declared ${participantCount}); N concurrent paid desktops is real spend, and there is no override above the cap this slice.`;
49
+ const participantCount = computerUseParticipantCount(config);
50
+ if (participantCount > MAX_COMPUTER_USE_PARTICIPANTS) {
51
+ return `A computer-use study runs at most ${MAX_COMPUTER_USE_PARTICIPANTS} participants, and this one declares ${participantCount}. Each participant is a paid desktop and they all run at once, so no setting raises the cap; split the roster across studies.`;
51
52
  }
52
53
  // Public targets fan out into N independent worlds driving the same public app, which is an
53
54
  // ambiguous shared-world-ish shape, not a per-participant target swarm. Permit N>1 public runs only
54
55
  // when every roster entry declares its own target, making the adapter-owned topology explicit. But when
55
56
  // `subject.topology: shared-world` is also declared, N participants against one public target is the
56
- // external-public shared-world topology (#164 phase 2), so route it there (a real public deployment
57
+ // external-public shared-world topology, so route it there (a real public deployment
57
58
  // as the shared plane) instead of refusing; externalPublicSharedWorldValidationReason then applies.
58
59
  if (participantCount > 1 &&
59
60
  config.policies?.allowPublicTargets === true &&
60
61
  declaredTargets(config).length === 0 &&
61
62
  config.subject.topology !== "shared-world") {
62
- return "policies.allowPublicTargets cannot be combined with fan-out to more than one participant (N>1): N participants against one declared public target is the SHARED-WORLD topology (layer 7, #164), not `per-lane-worlds`. Declare `subject.topology: shared-world` to run the external-public shared-world route, fan out against a loopback/provisioned subject, or run a single public-target participant.";
63
+ return "`policies.allowPublicTargets` with more than one participant sends them all to one public app, which is a shared world. Set `subject.topology: shared-world` to run them together there, give each `actors[0].lanes[]` entry its own `target`, or run one participant.";
63
64
  }
64
65
  return null;
65
66
  }
@@ -96,10 +97,10 @@ function rosterStructuralValidationReason(config) {
96
97
  return null;
97
98
  }
98
99
  /**
99
- * Cross-validate a `topology: shared-world` declaration (#164). Returns the failure message, or
100
+ * Cross-validate a `topology: shared-world` declaration. Returns the failure message, or
100
101
  * null when the one shared-world route can run it: the external-public checks for an app-url
101
102
  * subject, the provisioned checks otherwise. Enforced at parse and again by the route, since
102
- * runConcurrentSharedWorld is exported.
103
+ * runLab takes a config that skipped the parser.
103
104
  */
104
105
  export function sharedWorldValidationReason(config) {
105
106
  return config.subject.source === "app-url"
@@ -119,7 +120,7 @@ function provisionedSharedWorldStructureReason(config) {
119
120
  return structuralReason;
120
121
  }
121
122
  if (config.subject.source !== "clone" && config.subject.source !== "local-tree") {
122
- return "`subject.topology: shared-world` requires `subject.source: clone` or `subject.source: local-tree` - the shared world is ONE provisioned, served, seeded plane (#164).";
123
+ return "`subject.topology: shared-world` needs `subject.source: clone` or `local-tree`, which humanish serves as one seeded app every participant uses, or `app-url` for a public deployment you own.";
123
124
  }
124
125
  if (config.execution?.target !== "e2b-desktop") {
125
126
  return "`subject.topology: shared-world` requires `execution.target: e2b-desktop`: the role participants drive hosted desktop browsers against one in-sandbox app.";
@@ -129,17 +130,17 @@ function provisionedSharedWorldStructureReason(config) {
129
130
  }
130
131
  const serve = config.subject.serve;
131
132
  if (!serve) {
132
- return "`subject.topology: shared-world` requires `subject.serve` (start + url) — the lab serves ONE shared app in-sandbox that every role drives.";
133
+ return "`subject.topology: shared-world` needs `subject.serve` (start and url): humanish starts one copy of the app in the sandbox, and every participant uses it.";
133
134
  }
134
135
  const roster = rosterOf(config.actors[0]);
135
136
  if (!roster || roster.length < 2) {
136
- return "`subject.topology: shared-world` requires an `actors[0].lanes` roster of at least 2 roles (the roster IS the role roster: declare ≥2 participants; a single-role shared world proves no interaction).";
137
+ return "`subject.topology: shared-world` needs an `actors[0].lanes` roster of at least 2 participants: with one participant there is nobody to interact with.";
137
138
  }
138
139
  if (!config.subject.state?.checkpoint || config.subject.state.checkpoint.length === 0) {
139
- return "`subject.topology: shared-world` requires `subject.state.checkpoint` (≥1 read-only digest probe) — the checkpoint series is how the run shows the shared state changing; without it the run cannot show that participants changed the shared app.";
140
+ return "`subject.topology: shared-world` needs at least one read-only `subject.state.checkpoint` probe: the checkpoints are how the run shows that participants changed the shared app.";
140
141
  }
141
142
  for (const entry of roster) {
142
- if (entry.entry !== undefined && resolveSeatUrl(serve.url, entry.entry) === null) {
143
+ if (entry.entry !== undefined && resolveEntryUrl(serve.url, entry.entry) === null) {
143
144
  return `actors[0].lanes role "${entry.id ?? "(unnamed)"}".entry must resolve same-origin (loopback) with subject.serve.url (${serve.url}); got "${entry.entry}".`;
144
145
  }
145
146
  }
@@ -198,7 +199,7 @@ export function receivingEmailValidationReason(config) {
198
199
  }
199
200
  return undefined;
200
201
  }
201
- /** Refuse task declarations that the selected execution path would discard (#737).
202
+ /** Refuse task declarations that the selected execution path would discard.
202
203
  * Direct runners pass their actual support rather than trusting the config's dispatch shape. */
203
204
  export function taskProtocolValidationReason(config, supportsTasks = isComputerUseComposition(config) && !isSharedWorldComposition(config)) {
204
205
  for (const [index, actor] of config.actors.entries()) {
@@ -263,7 +264,8 @@ export function outputTokenLimitValidationReason(config) {
263
264
  * Shared-world participants share one live app, so at least two must be live at once. The
264
265
  * sequential shared-world route (`execution.concurrency: 1`) was removed in 0.106.0; the parser
265
266
  * fills an omitted concurrency with the participant count. Both callers check it after their
266
- * two-participant roster floor, so a one-seat roster gets the roster refusal, never this one.
267
+ * two-participant roster floor, so a one-participant roster gets the roster refusal, never this
268
+ * one.
267
269
  */
268
270
  function sharedWorldConcurrencyReason(config) {
269
271
  // Direct library callers skip the parser, so an omitted value defaults here exactly as the
@@ -275,12 +277,12 @@ function sharedWorldConcurrencyReason(config) {
275
277
  return `shared-world labs need \`execution.concurrency\` of at least 2 (got ${concurrency}). Sequential shared-world turns (concurrency 1) were removed in 0.106.0: omit execution.concurrency to run every participant at once, or set it to 2 or more. A provisioned subject also needs \`subject.exposure: synthetic\` and a \`serve.start\` that binds 0.0.0.0.`;
276
278
  }
277
279
  /**
278
- * Cross-validate a concurrent shared-world declaration (#164 phase 2). Returns the failure message,
280
+ * Cross-validate a concurrent shared-world declaration. Returns the failure message,
279
281
  * or null when valid. Includes the base shared-world checks plus the concurrent extras: a synthetic
280
282
  * subject attestation, a 0.0.0.0 serve bind (getHost only routes to a port bound on
281
283
  * all interfaces), and no `subject.clone.keep`/`subject.localTree.keep` (either would
282
- * orphan actor sandboxes). Enforced at parse and re-enforced in the engine (runConcurrentSharedWorld
283
- * is exported npm surface).
284
+ * orphan actor sandboxes). Enforced at parse and re-enforced in the engine (runLab
285
+ * takes a config that skipped the parser).
284
286
  */
285
287
  export function concurrentSharedWorldValidationReason(config) {
286
288
  const base = provisionedSharedWorldStructureReason(config);
@@ -291,11 +293,11 @@ export function concurrentSharedWorldValidationReason(config) {
291
293
  if (sharedWorldConcurrency)
292
294
  return sharedWorldConcurrency;
293
295
  if (config.subject.exposure !== "synthetic") {
294
- return "the concurrent shared-world route requires `subject.exposure: synthetic` — the subject is exposed on an internet-reachable getHost URL for the run, so the author must attest it is synthetic seeded data (no real/external data behind a getHost URL).";
296
+ return "A shared-world study needs `subject.exposure: synthetic`. The subject is reachable from the internet at a public sandbox URL during the run, so the study must declare that its data is synthetic and seeded.";
295
297
  }
296
298
  const serve = config.subject.serve;
297
299
  if (!serve || !serve.start.includes("0.0.0.0")) {
298
- return "the concurrent shared-world route requires `subject.serve.start` to bind all interfaces (e.g. `-H 0.0.0.0` / `--host 0.0.0.0` / `HOST=0.0.0.0`) — getHost only routes to a 0.0.0.0-bound port; a loopback-only bind 502s. (The readiness probe stays loopback.)";
300
+ return "A shared-world study needs `subject.serve.start` to listen on all interfaces (for example `-H 0.0.0.0`, `--host 0.0.0.0` or `HOST=0.0.0.0`): the public sandbox URL reaches only a port bound to 0.0.0.0, and a loopback-only server answers 502. The readiness probe still uses loopback.";
299
301
  }
300
302
  if (config.subject.clone?.keep === true || config.subject.localTree?.keep === true) {
301
303
  const keepField = config.subject.clone?.keep === true ? "subject.clone.keep" : "subject.localTree.keep";
@@ -304,15 +306,15 @@ export function concurrentSharedWorldValidationReason(config) {
304
306
  return null;
305
307
  }
306
308
  /**
307
- * Cross-validate the external-public shared-world declaration (#164 phase 2): a real public
309
+ * Cross-validate the external-public shared-world declaration: a real public
308
310
  * deployment used directly as the shared plane (no getHost, no clone, no subject sandbox, no seed).
309
311
  * The counterpart of concurrentSharedWorldValidationReason for a plane the harness does not own:
310
312
  * it rejects every provisioned-subject field (serve/state.seed/state.checkpoint/exposure/clone/repos
311
- * are inert with no sandbox, so they fail closed per invariant 6), and requires a
313
+ * are inert with no sandbox, so they fail closed), and requires a
312
314
  * non-loopback appUrl + allowPublicTargets + the operator-ownership attestation subject.publicTarget +
313
315
  * concurrency >= 2 + an actors[0].lanes roster of ≥2 with exactly one host participant. The getHost synthetic
314
316
  * gate is deliberately unreachable here (there is no internet-reachable harness-owned URL to attest).
315
- * Enforced at parse and re-enforced in the engine (runConcurrentSharedWorld is exported npm surface).
317
+ * Enforced at parse and re-enforced in the engine (runLab takes a config that skipped the parser).
316
318
  */
317
319
  export function externalPublicSharedWorldValidationReason(config) {
318
320
  const structuralReason = rosterStructuralValidationReason(config);
@@ -320,7 +322,7 @@ export function externalPublicSharedWorldValidationReason(config) {
320
322
  return structuralReason;
321
323
  }
322
324
  if (config.subject.source !== "app-url") {
323
- return "the external-public shared-world route requires `subject.source: app-url` — a real public deployment is used directly as the shared plane (no clone, no provisioned subject).";
325
+ return "An external-public shared-world study needs `subject.source: app-url`: the participants share a public deployment you already run, so there is nothing to clone or serve.";
324
326
  }
325
327
  if (config.execution?.target !== "e2b-desktop") {
326
328
  return "the external-public shared-world route requires `execution.target: e2b-desktop`: the role participants drive hosted desktop browsers against the one public deployment.";
@@ -336,40 +338,40 @@ export function externalPublicSharedWorldValidationReason(config) {
336
338
  if (sharedWorldConcurrency)
337
339
  return sharedWorldConcurrency;
338
340
  if (config.policies?.allowPublicTargets !== true) {
339
- return "the external-public shared-world route requires `policies.allowPublicTargets: true` — the shared plane is a real non-loopback public deployment.";
341
+ return "An external-public shared-world study needs `policies.allowPublicTargets: true`, because the participants drive a public deployment.";
340
342
  }
341
343
  const appUrl = config.subject.appUrl ?? "";
342
344
  if (!isHttpUrl(appUrl) || isLoopbackUrl(appUrl)) {
343
- return "the external-public shared-world route requires a non-loopback http(s) `subject.appUrl` — a loopback URL is not a shared public plane (use the getHost provisioned route for a local subject).";
345
+ return "An external-public shared-world study needs a public http(s) `subject.appUrl`, not a loopback URL. For an app you run locally, use a clone or local-tree subject, which humanish serves itself.";
344
346
  }
345
- // The operator-ownership attestation (the honest analog of exposure: synthetic — you cannot claim
347
+ // The operator-ownership attestation (the counterpart of exposure: synthetic; you cannot claim
346
348
  // synthetic on a real site, but you must attest you own/operate it). Author-trust; unverifiable.
347
349
  if (config.subject.publicTarget?.authorized !== true) {
348
- return "the external-public shared-world route requires `subject.publicTarget: { owner, authorized: true }` — you must attest you own/operate the public deployment used as the shared plane (author-trust; the harness cannot verify ownership).";
350
+ return "An external-public shared-world study needs `subject.publicTarget: { owner, authorized: true }` to declare that you own or operate the public deployment. humanish cannot check ownership, so the study states it.";
349
351
  }
350
352
  // No provisioned-subject field is allowed: with no sandbox they cannot act, so they are rejected
351
- // with a precise reason, never silently ignored (invariant 6). exposure: synthetic in particular
353
+ // with a precise reason, never silently ignored. exposure: synthetic in particular
352
354
  // would be a false claim on a real site (the harness neither provisioned nor exposed it).
353
355
  if (config.subject.exposure !== undefined) {
354
- return "`subject.exposure: synthetic` is forbidden on the external-public shared-world route — you cannot attest a real public deployment is synthetic seeded data; use `subject.publicTarget` to attest ownership instead.";
356
+ return "`subject.exposure: synthetic` does not apply to an external-public shared-world study: a real public deployment is not seeded synthetic data. Declare ownership with `subject.publicTarget` instead.";
355
357
  }
356
358
  if (config.subject.serve !== undefined) {
357
- return "`subject.serve` is forbidden on the external-public shared-world route — the harness does not serve the plane (it is an already-deployed public app); there is no in-sandbox serve to run.";
359
+ return "`subject.serve` does not apply to an external-public shared-world study: the app is already deployed, so humanish serves nothing. Remove `subject.serve`.";
358
360
  }
359
361
  if (config.subject.state?.seed !== undefined ||
360
362
  config.subject.state?.checkpoint !== undefined ||
361
363
  config.subject.state !== undefined) {
362
- return "`subject.state` (seed/checkpoint/external) is forbidden on the external-public shared-world route — the harness neither seeds nor snapshots the plane (no in-sandbox filesystem to digest); no authoritative shared-state proof is possible on this class.";
364
+ return "`subject.state` (seed, checkpoint or external) does not apply to an external-public shared-world study: humanish cannot seed or read a deployment it does not run. Remove `subject.state`.";
363
365
  }
364
366
  if (config.subject.clone !== undefined || config.subject.repos !== undefined) {
365
- return "`subject.clone`/`subject.repos` are forbidden on the external-public shared-world route — nothing is cloned; the public deployment IS the plane.";
367
+ return "`subject.clone` and `subject.repos` do not apply to an external-public shared-world study: the participants use the public deployment, so nothing is cloned. Remove them.";
366
368
  }
367
369
  if (roster.some((entry) => entry.entry !== undefined)) {
368
370
  return "`actors[0].lanes[].entry` (the loopback same-origin participant path) is forbidden on the external-public shared-world route: there is no harness-served serve.url to resolve it against; participants open the public appUrl and reach the shared session through the real UI.";
369
371
  }
370
372
  const hostEntries = roster.filter((entry) => entry.host === true);
371
373
  if (hostEntries.length !== 1) {
372
- return `the external-public shared-world route requires EXACTLY ONE \`host: true\` participant (the designated host that creates the shared session; got ${hostEntries.length}). The other ≥1 participants are followers that join it.`;
374
+ return `An external-public shared-world study needs exactly one \`host: true\` participant, the one who creates the shared session, and this study has ${hostEntries.length}. Every other participant joins that session.`;
373
375
  }
374
376
  return null;
375
377
  }
@@ -1,2 +1,12 @@
1
1
  import type { LabConfig } from "./types.js";
2
+ /**
3
+ * The fields a config sets that its route does not read, each as `field` or `field (reason)`. A v2
4
+ * file gets them as one warning; a v3 study is refused for any of them.
5
+ */
6
+ export declare function inertFieldLabels(config: LabConfig): string[];
7
+ /**
8
+ * The same fields as `inertFieldLabels`, as paths without their reasons, such as
9
+ * `actors[0].lanes[].entry` or `execution.timeoutMs`. `humanish migrate` drops each one.
10
+ */
11
+ export declare function inertFieldPaths(config: LabConfig): string[];
2
12
  export declare function forwardDeclaredWarnings(config: LabConfig): string[];
@@ -13,13 +13,13 @@ const otherRoute = (routes) => !promptRoute(routes) && !routes.scripted;
13
13
  /** Rows for each actor, reported as `actors[<index>].<field>`, in this order per actor. */
14
14
  const ACTOR_ROWS = [
15
15
  // Shared-world-only fields on the roster: a participant's `entry` is inert anywhere else
16
- // (invariant 6).
16
+ // (claims match mechanism).
17
17
  {
18
18
  field: "lanes[].entry",
19
19
  reason: "the per-participant loopback entry is a shared-world capability; needs subject.topology: shared-world",
20
20
  applies: (actor, routes) => Boolean(rosterOf(actor)?.some((entry) => entry.entry !== undefined)) && !routes.shared,
21
21
  },
22
- // The host-seat marker acts only on the external-public shared-world route; inert elsewhere.
22
+ // The host marker acts only on the external-public shared-world route; inert elsewhere.
23
23
  {
24
24
  field: "lanes[].host",
25
25
  reason: "the designated host-participant marker; needs the external-public shared-world route: app-url × topology shared-world × allowPublicTargets",
@@ -35,7 +35,7 @@ const ACTOR_ROWS = [
35
35
  },
36
36
  {
37
37
  field: "lanes",
38
- reason: "fan-out is a computer-use route capability; terminal fan-out is a later slice",
38
+ reason: "only the computer-use route runs more than one participant",
39
39
  applies: (actor, routes) => routes.terminal && Boolean(rosterOf(actor)),
40
40
  },
41
41
  {
@@ -69,7 +69,7 @@ const ACTOR_ROWS = [
69
69
  { field: "lanes", applies: (actor, routes) => otherRoute(routes) && Boolean(rosterOf(actor)) },
70
70
  ];
71
71
  const TERMINAL_ONLY = "needs subject.source: terminal-product + a registered terminal actor";
72
- const RESERVED = "reserved for a later slice; not yet consumed";
72
+ const RESERVED = "reserved; no route reads it yet";
73
73
  /** Rows for the rest of the config, reported after the actor rows, in this order. */
74
74
  const CONFIG_ROWS = [
75
75
  // The computer-use routes consume (clone) subject.{serve,env,state,clone.depth}, and so does the
@@ -90,8 +90,9 @@ const CONFIG_ROWS = [
90
90
  field: "subject.state",
91
91
  applies: (config, routes) => Boolean(config.subject.state) && !routes.cua && !routes.scripted,
92
92
  },
93
- // topology + checkpoint act only on the shared-world route (#164); a set-but-unconsumed value
94
- // (incl. an explicit per-lane-worlds, which the cua route already is by mechanism) warns inert.
93
+ // topology + checkpoint act only on the shared-world route; a set-but-unconsumed value
94
+ // (incl. an explicit per-lane-worlds, which the computer-use route already is by mechanism) warns
95
+ // inert.
95
96
  {
96
97
  field: "subject.topology",
97
98
  reason: "drives behavior only on the shared-world route; needs subject.topology: shared-world + clone × e2b-desktop × a computer-use actor + a roster of ≥2 participants",
@@ -113,7 +114,7 @@ const CONFIG_ROWS = [
113
114
  // getHost-exposed plane) and on scripted clones; inert elsewhere.
114
115
  {
115
116
  field: "subject.exposure",
116
- reason: "the synthetic-subject attestation for a getHost-exposed plane; needs shared-world or clone × e2b-desktop × scripted-browser",
117
+ reason: "the statement that a subject served on a public sandbox URL holds only synthetic data; needs shared-world or clone × e2b-desktop × scripted-browser",
117
118
  applies: (config, routes) => config.subject.exposure !== undefined &&
118
119
  !routes.shared &&
119
120
  !(routes.scripted && config.subject.source === "clone"),
@@ -121,10 +122,10 @@ const CONFIG_ROWS = [
121
122
  // comms.email drives the in-sandbox email/SMS catch, which needs a subject sandbox that humanish
122
123
  // provisions (clone or local-tree) so it holds a handle to host the catch. On an app-url /
123
124
  // operator-provided subject there is no such handle, so a declared comms block would silently
124
- // collect nothing — a false green. Warn at parse time (fires on inspect + dry-run too).
125
+ // collect nothing, a false green. Warn at parse time (fires on inspect + dry-run too).
125
126
  {
126
127
  field: "comms.email",
127
- reason: "the in-sandbox email/SMS catch needs a harness-provisioned subject to host it — subject.source: clone or local-tree; on an app-url or operator-provided subject humanish holds no sandbox handle. Declare `comms.email.external` to run the catch yourself: humanish then points the persona at your inbox, drains your catch, and writes the same evidence — see #328",
128
+ reason: "the email catch runs in a sandbox humanish provisions, which needs `subject.source: clone` or `local-tree`, and an app-url subject has none. To use email here, run the catch yourself with `humanish comms catch` and declare `comms.email.external`: humanish then points each persona at your inbox, reads your catch and records the same evidence",
128
129
  applies: (config) => config.comms?.email?.kind === "fake" &&
129
130
  config.comms.email.external === undefined &&
130
131
  config.subject.source !== "clone" &&
@@ -139,9 +140,9 @@ const CONFIG_ROWS = [
139
140
  applies: (config) => Boolean(config.comms?.email?.external) &&
140
141
  (config.subject.source === "clone" || config.subject.source === "local-tree"),
141
142
  },
142
- // clone.keep is consumed on the cua route (honored on failure: the sandbox is left up to debug
143
- // a failed install/boot; otherwise always killed). clone.fanout is rejected on the cua route
144
- // (a hard parse error above), so it can never reach this warning list there.
143
+ // clone.keep is consumed on the computer-use route (honored on failure: the sandbox is left up to
144
+ // debug a failed install/boot; otherwise always killed). clone.fanout is rejected on the
145
+ // computer-use route (a hard parse error above), so it can never reach this warning list there.
145
146
  {
146
147
  field: "execution.timeoutMs",
147
148
  applies: (config, routes) => !routes.cua &&
@@ -153,23 +154,24 @@ const CONFIG_ROWS = [
153
154
  field: "execution.completionTimeoutMs",
154
155
  applies: (config) => config.execution?.completionTimeoutMs !== undefined,
155
156
  },
156
- // execution.concurrency is consumed on the cua route (it bounds in-flight fan-out participants);
157
- // inert (warned) everywhere else.
157
+ // execution.concurrency is consumed on the computer-use route (it bounds in-flight fan-out
158
+ // participants); inert (warned) everywhere else.
158
159
  {
159
160
  field: "execution.concurrency",
160
161
  applies: (config, routes) => config.execution?.concurrency !== undefined && !routes.cua,
161
162
  },
162
- // execution.caps is consumed on the cua route (maxUsd is the fail-closed spend abort); inert
163
- // (warned) everywhere else so a misplaced budget field is never trusted to cap a route it cannot.
163
+ // execution.caps is consumed on the computer-use route (maxUsd is the fail-closed spend abort);
164
+ // inert (warned) everywhere else so a misplaced budget field is never trusted to cap a route it
165
+ // cannot.
164
166
  {
165
167
  field: "execution.caps",
166
- reason: "the fail-closed spend abort is a computer-use route capability; needs a computer-use actor on e2b-desktop",
168
+ reason: "only the computer-use route enforces it, with a computer-use actor on e2b-desktop",
167
169
  applies: (config, routes) => Boolean(config.execution?.caps) && !routes.cua,
168
170
  },
169
171
  // terminal-product consumes subject.product, scenario.caps, execution.{terminal,runtimeAuth}:
170
172
  // dry-run records the contract; live execution enforces caps and command-scoped auth. On every
171
173
  // other route they are inert and must warn so a
172
- // misplaced safety/budget field is never trusted to do something it cannot (invariant 6).
174
+ // misplaced safety/budget field is never trusted to do something it cannot.
173
175
  {
174
176
  field: "subject.product",
175
177
  reason: "needs subject.source: terminal-product or desktop-cli with the matching actor",
@@ -229,9 +231,9 @@ const CONFIG_ROWS = [
229
231
  applies: (config, routes) => !routes.cua && config.execution?.desktop?.sandboxTimeoutMs !== undefined,
230
232
  },
231
233
  // execution.desktop.template (the custom E2B desktop image) is consumed only where a desktop is
232
- // actually created via Sandbox.create — the e2b-desktop computer-use routes (cua/shared-world/
233
- // concurrent). It is inert on every other route (incl. the in-process local-app cua route, which
234
- // creates no desktop): warn so an unconsumed template is never silently ignored (invariant 6).
234
+ // actually created via Sandbox.create: the e2b-desktop computer-use routes (cua/shared-world/
235
+ // concurrent). It is inert on every other route (incl. the in-process local-app computer-use
236
+ // route, which creates no desktop): warn so an unconsumed template is never silently ignored.
235
237
  {
236
238
  field: "execution.desktop.template",
237
239
  reason: "the custom E2B desktop image is consumed only on execution.target: e2b-desktop computer-use routes that create a desktop; needs a computer-use actor on e2b-desktop",
@@ -251,8 +253,8 @@ const CONFIG_ROWS = [
251
253
  applies: (config, routes) => Boolean(config.scenario?.ref) && !routes.scripted,
252
254
  },
253
255
  { field: "scenario.inline", applies: (config) => Boolean(config.scenario?.inline) },
254
- // review.{scoring,milestones,vocabulary} stay forward-declared (reserved for #319) on every route.
255
- // review.scorer (#316) is consumed (loaded + wired, or fail-closed at load) on every scorer-capable
256
+ // review.{scoring,milestones,vocabulary} stay forward-declared on every route.
257
+ // review.scorer is consumed (loaded + wired, or fail-closed at load) on every scorer-capable
256
258
  // route, so it does not warn there; on the scripted-browser route the actor carries no scorer seam,
257
259
  // so a declared scorer is flagged inert (the run also fails closed at load).
258
260
  {
@@ -297,9 +299,11 @@ function rowLabel(row, prefix = "") {
297
299
  ? `${prefix}${row.field}`
298
300
  : `${prefix}${row.field} (${row.reason})`;
299
301
  }
300
- // Report fields that are present but not yet consumed by the engine, so a user never trusts a
301
- // setting that silently does nothing. Keeps the schema forward-correct and honest.
302
- export function forwardDeclaredWarnings(config) {
302
+ /**
303
+ * The fields a config sets that its route does not read, each as `field` or `field (reason)`. A v2
304
+ * file gets them as one warning; a v3 study is refused for any of them.
305
+ */
306
+ export function inertFieldLabels(config) {
303
307
  const routes = routesOf(config);
304
308
  const inert = [];
305
309
  for (const [index, actor] of config.actors.entries()) {
@@ -310,14 +314,38 @@ export function forwardDeclaredWarnings(config) {
310
314
  for (const row of CONFIG_ROWS)
311
315
  if (row.applies(config, routes))
312
316
  inert.push(rowLabel(row));
317
+ return inert;
318
+ }
319
+ /**
320
+ * The same fields as `inertFieldLabels`, as paths without their reasons, such as
321
+ * `actors[0].lanes[].entry` or `execution.timeoutMs`. `humanish migrate` drops each one.
322
+ */
323
+ export function inertFieldPaths(config) {
324
+ const routes = routesOf(config);
325
+ const paths = [];
326
+ for (const [index, actor] of config.actors.entries()) {
327
+ for (const row of ACTOR_ROWS)
328
+ if (row.applies(actor, routes))
329
+ paths.push(`actors[${index}].${row.field}`);
330
+ }
331
+ for (const row of CONFIG_ROWS)
332
+ if (row.applies(config, routes))
333
+ paths.push(row.field);
334
+ return paths;
335
+ }
336
+ // Report fields that are present but not yet consumed by the engine, so a user never trusts a
337
+ // setting that silently does nothing.
338
+ export function forwardDeclaredWarnings(config) {
339
+ const routes = routesOf(config);
340
+ const inert = inertFieldLabels(config);
313
341
  const warnings = inert.length === 0
314
342
  ? []
315
343
  : [
316
- `Forward-declared fields are set but not yet consumed by the engine (planned for a later slice): ${inert.join(", ")}.`,
344
+ `These fields are set, but no route reads them yet, so they have no effect: ${inert.join(", ")}.`,
317
345
  ];
318
- // A declared cap below the seat count is legal but loud: the roster promises N live actors and
319
- // the cap delivers waves of M. Say so up front (inspect + dry-run + run) — a green run in waves
320
- // is otherwise indistinguishable from the all-live run the author meant (#350).
346
+ // A declared cap below the participant count is legal but loud: the roster promises N live actors
347
+ // and the cap delivers waves of M. Say so up front (inspect + dry-run + run): a green run in
348
+ // waves is otherwise indistinguishable from the all-live run the author meant.
321
349
  {
322
350
  const participantCount = rosterOf(config.actors[0])?.length ?? config.actors[0]?.count ?? 1;
323
351
  const cap = config.execution?.concurrency;
@@ -325,14 +353,14 @@ export function forwardDeclaredWarnings(config) {
325
353
  warnings.push(`execution.concurrency ${cap} caps a ${participantCount}-participant roster: participants run in waves of ${cap}, never all live at once. Remove execution.concurrency (the default runs all ${participantCount} participants simultaneously) or set it to ${participantCount}; declare a lower cap only to bound simultaneous paid desktops.`);
326
354
  }
327
355
  }
328
- // Partial email coverage is legal but loud (#351): a participant without an addressed recipient never
329
- // hears an inbox exists, so an email-gated flow on that seat dead-ends by construction.
356
+ // Partial email coverage is legal but loud: a participant without an addressed recipient never
357
+ // hears an inbox exists, so an email-gated flow on that participant dead-ends by construction.
330
358
  if (routes.cua && config.comms?.email?.recipients) {
331
359
  const participantIds = declaredParticipantIds(config);
332
360
  const covered = new Set(addressedRecipients(config.comms.email).map((recipient) => recipient.participantId));
333
361
  const uncovered = participantIds.filter((id) => !covered.has(id));
334
362
  if (covered.size > 0 && uncovered.length > 0 && participantIds.length > 1) {
335
- warnings.push(`comms.email covers ${covered.size} of ${participantIds.length} participants; the uncovered participant(s) get no inbox and are never told one exists: ${uncovered.join(", ")}. Add addressed recipients for them if their flows need email.`);
363
+ warnings.push(`comms.email covers ${covered.size} of ${participantIds.length} participants. These get no inbox and are never told one exists: ${uncovered.join(", ")}. Add a recipient with an address for each one whose flow needs email.`);
336
364
  }
337
365
  }
338
366
  return warnings;
@@ -0,0 +1,56 @@
1
+ import { CuaAdmissionLimitError as AdmissionLimitError } from "./actors/computer-use/admission-limit.js";
2
+ import type { CuaAction as Action, CuaExecutor as Executor, CuaLoopOptions as LoopOptions, CuaLoopResult as LoopResult, CuaObservation as Observation, CuaProvider as Provider, CuaSafetyCheck as SafetyCheck, CuaTurn as Turn, CuaTurnRequest as TurnRequest } from "./actors/computer-use/loop.js";
3
+ import type { BrowserLabScoringContext as BrowserScoringContext } from "./lab/adapter-extension.js";
4
+ import { parseLabConfig as parseStudy } from "./lab/config.js";
5
+ import type { LabRoute as StudyRoute } from "./lab/routing.js";
6
+ import type { LabEvent as StudyEvent } from "./lab/run-lab-events.js";
7
+ import { type LabConfig as StudyConfig } from "./lab/types.js";
8
+ import { runPackageLab as runStudy, type LabOutcome as StudyOutcome, type LabResult as StudyResult, type RunLabOptions as RunStudyOptions } from "./run-lab.js";
9
+ /** @deprecated Use `runStudy`, the same function. 0.109 removes `runLab`. */
10
+ export declare const runLab: typeof runStudy;
11
+ /** @deprecated Use `parseStudy`, the same function. 0.109 removes `parseLabConfig`. */
12
+ export declare const parseLabConfig: typeof parseStudy;
13
+ /**
14
+ * The `humanish.lab.v2` schema id, which 0.109 stops parsing.
15
+ * @deprecated Write `STUDY_SCHEMA` (`humanish.study.v3`) files. 0.109 removes `LAB_CONFIG_SCHEMA`.
16
+ */
17
+ export declare const LAB_CONFIG_SCHEMA = "humanish.lab.v2";
18
+ /** @deprecated Use `StudyConfig`, the same type. 0.109 removes `LabConfig`. */
19
+ export type LabConfig = StudyConfig;
20
+ /** @deprecated Use `StudyEvent`, the same type. 0.109 removes `LabEvent`. */
21
+ export type LabEvent = StudyEvent;
22
+ /** @deprecated Use `StudyOutcome`, the same type. 0.109 removes `LabOutcome`. */
23
+ export type LabOutcome = StudyOutcome;
24
+ /** @deprecated Use `StudyResult`, the same type. 0.109 removes `LabResult`. */
25
+ export type LabResult<R extends StudyRoute = StudyRoute> = StudyResult<R>;
26
+ /** @deprecated Use `StudyRoute`, the same type. 0.109 removes `LabRoute`. */
27
+ export type LabRoute = StudyRoute;
28
+ /** @deprecated Use `RunStudyOptions`, the same type. 0.109 removes `RunLabOptions`. */
29
+ export type RunLabOptions = RunStudyOptions;
30
+ /** @deprecated Use `BrowserScoringContext`, the same type. 0.109 removes `BrowserLabScoringContext`. */
31
+ export type BrowserLabScoringContext = BrowserScoringContext;
32
+ /**
33
+ * @deprecated Use `ComputerUseAdmissionLimitError`, the same class, so `instanceof` matches either
34
+ * name. 0.109 removes `CuaAdmissionLimitError`.
35
+ */
36
+ export declare const CuaAdmissionLimitError: typeof AdmissionLimitError;
37
+ /** @deprecated Use `ComputerUseAdmissionLimitError`. 0.109 removes `CuaAdmissionLimitError`. */
38
+ export type CuaAdmissionLimitError = AdmissionLimitError;
39
+ /** @deprecated Use `ComputerUseAction`, the same type. 0.109 removes `CuaAction`. */
40
+ export type CuaAction = Action;
41
+ /** @deprecated Use `ComputerUseExecutor`, the same type. 0.109 removes `CuaExecutor`. */
42
+ export type CuaExecutor = Executor;
43
+ /** @deprecated Use `ComputerUseLoopOptions`, the same type. 0.109 removes `CuaLoopOptions`. */
44
+ export type CuaLoopOptions = LoopOptions;
45
+ /** @deprecated Use `ComputerUseLoopResult`, the same type. 0.109 removes `CuaLoopResult`. */
46
+ export type CuaLoopResult = LoopResult;
47
+ /** @deprecated Use `ComputerUseObservation`, the same type. 0.109 removes `CuaObservation`. */
48
+ export type CuaObservation = Observation;
49
+ /** @deprecated Use `ComputerUseProvider`, the same type. 0.109 removes `CuaProvider`. */
50
+ export type CuaProvider = Provider;
51
+ /** @deprecated Use `ComputerUseSafetyCheck`, the same type. 0.109 removes `CuaSafetyCheck`. */
52
+ export type CuaSafetyCheck = SafetyCheck;
53
+ /** @deprecated Use `ComputerUseTurn`, the same type. 0.109 removes `CuaTurn`. */
54
+ export type CuaTurn = Turn;
55
+ /** @deprecated Use `ComputerUseTurnRequest`, the same type. 0.109 removes `CuaTurnRequest`. */
56
+ export type CuaTurnRequest = TurnRequest;
@@ -0,0 +1,22 @@
1
+ // The names 0.107's library exported for running a lab and driving a computer-use participant.
2
+ // Each is the same function, constant, class or type as the name that replaces it, so an existing
3
+ // import, call or `instanceof` check keeps working, and editors mark it deprecated.
4
+ // Removed in 0.109.0: this module and its exports in src/index.ts.
5
+ import { CuaAdmissionLimitError as AdmissionLimitError } from "./actors/computer-use/admission-limit.js";
6
+ import { parseLabConfig as parseStudy } from "./lab/config.js";
7
+ import { LAB_CONFIG_SCHEMA as V2_SCHEMA } from "./lab/types.js";
8
+ import { runPackageLab as runStudy, } from "./run-lab.js";
9
+ /** @deprecated Use `runStudy`, the same function. 0.109 removes `runLab`. */
10
+ export const runLab = runStudy;
11
+ /** @deprecated Use `parseStudy`, the same function. 0.109 removes `parseLabConfig`. */
12
+ export const parseLabConfig = parseStudy;
13
+ /**
14
+ * The `humanish.lab.v2` schema id, which 0.109 stops parsing.
15
+ * @deprecated Write `STUDY_SCHEMA` (`humanish.study.v3`) files. 0.109 removes `LAB_CONFIG_SCHEMA`.
16
+ */
17
+ export const LAB_CONFIG_SCHEMA = V2_SCHEMA;
18
+ /**
19
+ * @deprecated Use `ComputerUseAdmissionLimitError`, the same class, so `instanceof` matches either
20
+ * name. 0.109 removes `CuaAdmissionLimitError`.
21
+ */
22
+ export const CuaAdmissionLimitError = AdmissionLimitError;
@@ -1,7 +1,7 @@
1
1
  import type { LoadedAnalysis } from "../analysis/types.js";
2
2
  import { type ObserverData } from "./data.js";
3
3
  /**
4
- * Resolve — and in a repo checkout, build — the Observer artifact BEFORE any run or
4
+ * Resolve (and in a repo checkout, build) the Observer artifact before any run or
5
5
  * lab work starts. A missing artifact must cost seconds at startup, never a completed
6
6
  * session (a live participant spends real money before the render step would have noticed).
7
7
  * Unconditional on purpose: the artifact is the only renderer now, so the fail-before-