humanish 0.0.1 → 0.15.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 (205) hide show
  1. package/AGENTS.md +77 -0
  2. package/CONTRIBUTING.md +39 -0
  3. package/LICENSE +21 -0
  4. package/README.md +437 -8
  5. package/SECURITY.md +34 -0
  6. package/dist/actor-contract.d.ts +107 -0
  7. package/dist/actor-contract.js +286 -0
  8. package/dist/actor-contract.js.map +1 -0
  9. package/dist/actor-registry.d.ts +73 -0
  10. package/dist/actor-registry.js +93 -0
  11. package/dist/actor-registry.js.map +1 -0
  12. package/dist/adapter-extension.d.ts +54 -0
  13. package/dist/adapter-extension.js +214 -0
  14. package/dist/adapter-extension.js.map +1 -0
  15. package/dist/argv.d.ts +1 -0
  16. package/dist/argv.js +8 -0
  17. package/dist/argv.js.map +1 -0
  18. package/dist/artifact-reference.d.ts +22 -0
  19. package/dist/artifact-reference.js +47 -0
  20. package/dist/artifact-reference.js.map +1 -0
  21. package/dist/browser-evidence-hygiene.d.ts +7 -0
  22. package/dist/browser-evidence-hygiene.js +40 -0
  23. package/dist/browser-evidence-hygiene.js.map +1 -0
  24. package/dist/claude-agent-sdk.d.ts +94 -0
  25. package/dist/claude-agent-sdk.js +363 -0
  26. package/dist/claude-agent-sdk.js.map +1 -0
  27. package/dist/cli.d.ts +2 -0
  28. package/dist/cli.js +5 -0
  29. package/dist/cli.js.map +1 -0
  30. package/dist/codex-app-server-ui.d.ts +39 -0
  31. package/dist/codex-app-server-ui.js +357 -0
  32. package/dist/codex-app-server-ui.js.map +1 -0
  33. package/dist/codex-app-server.d.ts +144 -0
  34. package/dist/codex-app-server.js +754 -0
  35. package/dist/codex-app-server.js.map +1 -0
  36. package/dist/command-failure.d.ts +29 -0
  37. package/dist/command-failure.js +54 -0
  38. package/dist/command-failure.js.map +1 -0
  39. package/dist/computer-use-actor.d.ts +52 -0
  40. package/dist/computer-use-actor.js +48 -0
  41. package/dist/computer-use-actor.js.map +1 -0
  42. package/dist/computer-use.d.ts +232 -0
  43. package/dist/computer-use.js +615 -0
  44. package/dist/computer-use.js.map +1 -0
  45. package/dist/concurrency.d.ts +1 -0
  46. package/dist/concurrency.js +27 -0
  47. package/dist/concurrency.js.map +1 -0
  48. package/dist/concurrent-shared-world-lab.d.ts +115 -0
  49. package/dist/concurrent-shared-world-lab.js +1094 -0
  50. package/dist/concurrent-shared-world-lab.js.map +1 -0
  51. package/dist/core/git-state.d.ts +33 -0
  52. package/dist/core/git-state.js +277 -0
  53. package/dist/core/git-state.js.map +1 -0
  54. package/dist/core/git-workspace.d.ts +31 -0
  55. package/dist/core/git-workspace.js +447 -0
  56. package/dist/core/git-workspace.js.map +1 -0
  57. package/dist/core/index.d.ts +4 -0
  58. package/dist/core/index.js +3 -0
  59. package/dist/core/index.js.map +1 -0
  60. package/dist/core/run-primitives.d.ts +66 -0
  61. package/dist/core/run-primitives.js +120 -0
  62. package/dist/core/run-primitives.js.map +1 -0
  63. package/dist/cua-actor-lab.d.ts +621 -0
  64. package/dist/cua-actor-lab.js +2845 -0
  65. package/dist/cua-actor-lab.js.map +1 -0
  66. package/dist/device-presets.d.ts +67 -0
  67. package/dist/device-presets.js +50 -0
  68. package/dist/device-presets.js.map +1 -0
  69. package/dist/e2b-desktop-executor.d.ts +101 -0
  70. package/dist/e2b-desktop-executor.js +309 -0
  71. package/dist/e2b-desktop-executor.js.map +1 -0
  72. package/dist/e2b-desktop-launch.d.ts +144 -0
  73. package/dist/e2b-desktop-launch.js +59 -0
  74. package/dist/e2b-desktop-launch.js.map +1 -0
  75. package/dist/e2b-detached.d.ts +53 -0
  76. package/dist/e2b-detached.js +130 -0
  77. package/dist/e2b-detached.js.map +1 -0
  78. package/dist/e2b-terminal-lab.d.ts +345 -0
  79. package/dist/e2b-terminal-lab.js +1532 -0
  80. package/dist/e2b-terminal-lab.js.map +1 -0
  81. package/dist/env-file.d.ts +14 -0
  82. package/dist/env-file.js +108 -0
  83. package/dist/env-file.js.map +1 -0
  84. package/dist/feedback.d.ts +51 -0
  85. package/dist/feedback.js +351 -0
  86. package/dist/feedback.js.map +1 -0
  87. package/dist/image-evidence.d.ts +2 -0
  88. package/dist/image-evidence.js +33 -0
  89. package/dist/image-evidence.js.map +1 -0
  90. package/dist/index.d.ts +63 -0
  91. package/dist/index.js +33 -0
  92. package/dist/index.js.map +1 -0
  93. package/dist/init-templates.d.ts +12 -0
  94. package/dist/init-templates.js +369 -0
  95. package/dist/init-templates.js.map +1 -0
  96. package/dist/init.d.ts +26 -0
  97. package/dist/init.js +429 -0
  98. package/dist/init.js.map +1 -0
  99. package/dist/lab-app-runner.d.ts +78 -0
  100. package/dist/lab-app-runner.js +403 -0
  101. package/dist/lab-app-runner.js.map +1 -0
  102. package/dist/lab-config.d.ts +583 -0
  103. package/dist/lab-config.js +1789 -0
  104. package/dist/lab-config.js.map +1 -0
  105. package/dist/lab-engine.d.ts +77 -0
  106. package/dist/lab-engine.js +216 -0
  107. package/dist/lab-engine.js.map +1 -0
  108. package/dist/lab-preflight.d.ts +67 -0
  109. package/dist/lab-preflight.js +385 -0
  110. package/dist/lab-preflight.js.map +1 -0
  111. package/dist/labs.d.ts +53 -0
  112. package/dist/labs.js +382 -0
  113. package/dist/labs.js.map +1 -0
  114. package/dist/observer-assets.d.ts +2 -0
  115. package/dist/observer-assets.js +2630 -0
  116. package/dist/observer-assets.js.map +1 -0
  117. package/dist/observer-data.d.ts +63 -0
  118. package/dist/observer-data.js +145 -0
  119. package/dist/observer-data.js.map +1 -0
  120. package/dist/observer-static.d.ts +39 -0
  121. package/dist/observer-static.js +306 -0
  122. package/dist/observer-static.js.map +1 -0
  123. package/dist/observer.d.ts +46 -0
  124. package/dist/observer.js +550 -0
  125. package/dist/observer.js.map +1 -0
  126. package/dist/openai-responses-cu.d.ts +113 -0
  127. package/dist/openai-responses-cu.js +545 -0
  128. package/dist/openai-responses-cu.js.map +1 -0
  129. package/dist/oss-lab.d.ts +52 -0
  130. package/dist/oss-lab.js +344 -0
  131. package/dist/oss-lab.js.map +1 -0
  132. package/dist/oss-meta-lab-scoring.d.ts +15 -0
  133. package/dist/oss-meta-lab-scoring.js +145 -0
  134. package/dist/oss-meta-lab-scoring.js.map +1 -0
  135. package/dist/oss-meta-lab.d.ts +277 -0
  136. package/dist/oss-meta-lab.js +4529 -0
  137. package/dist/oss-meta-lab.js.map +1 -0
  138. package/dist/oss-remote-telemetry.d.ts +77 -0
  139. package/dist/oss-remote-telemetry.js +403 -0
  140. package/dist/oss-remote-telemetry.js.map +1 -0
  141. package/dist/persona.d.ts +35 -0
  142. package/dist/persona.js +133 -0
  143. package/dist/persona.js.map +1 -0
  144. package/dist/pi-agent-core.d.ts +77 -0
  145. package/dist/pi-agent-core.js +203 -0
  146. package/dist/pi-agent-core.js.map +1 -0
  147. package/dist/program.d.ts +54 -0
  148. package/dist/program.js +2349 -0
  149. package/dist/program.js.map +1 -0
  150. package/dist/redaction.d.ts +90 -0
  151. package/dist/redaction.js +292 -0
  152. package/dist/redaction.js.map +1 -0
  153. package/dist/run-paths.d.ts +56 -0
  154. package/dist/run-paths.js +340 -0
  155. package/dist/run-paths.js.map +1 -0
  156. package/dist/run.d.ts +794 -0
  157. package/dist/run.js +4844 -0
  158. package/dist/run.js.map +1 -0
  159. package/dist/scripted-browser-actor.d.ts +297 -0
  160. package/dist/scripted-browser-actor.js +1399 -0
  161. package/dist/scripted-browser-actor.js.map +1 -0
  162. package/dist/scripted-browser-lab.d.ts +107 -0
  163. package/dist/scripted-browser-lab.js +788 -0
  164. package/dist/scripted-browser-lab.js.map +1 -0
  165. package/dist/selected-output-paths.d.ts +49 -0
  166. package/dist/selected-output-paths.js +354 -0
  167. package/dist/selected-output-paths.js.map +1 -0
  168. package/dist/shared-world-lab.d.ts +208 -0
  169. package/dist/shared-world-lab.js +1049 -0
  170. package/dist/shared-world-lab.js.map +1 -0
  171. package/dist/source-archive.d.ts +82 -0
  172. package/dist/source-archive.js +408 -0
  173. package/dist/source-archive.js.map +1 -0
  174. package/dist/stop-conditions.d.ts +26 -0
  175. package/dist/stop-conditions.js +66 -0
  176. package/dist/stop-conditions.js.map +1 -0
  177. package/dist/terminal-agent-actor.d.ts +36 -0
  178. package/dist/terminal-agent-actor.js +23 -0
  179. package/dist/terminal-agent-actor.js.map +1 -0
  180. package/docs/architecture/actor-contract.md +431 -0
  181. package/docs/architecture/github-feedback-loop.md +189 -0
  182. package/docs/architecture/local-codex-tui-actor.md +213 -0
  183. package/docs/architecture/observer.md +118 -0
  184. package/docs/architecture/oss-lab-poc.md +250 -0
  185. package/docs/architecture/project-layout.md +166 -0
  186. package/docs/architecture/state-driven-executor.md +203 -0
  187. package/docs/architecture/terminal-product-lane.md +148 -0
  188. package/docs/contracts/adapter-fixtures.md +80 -0
  189. package/docs/contracts/core.md +71 -0
  190. package/docs/contracts/feedback.md +145 -0
  191. package/docs/contracts/policy.md +311 -0
  192. package/docs/contracts/run-bundle.md +358 -0
  193. package/docs/contracts/schemas.md +984 -0
  194. package/docs/goals/current.md +428 -0
  195. package/docs/principles/invariants-and-defaults.md +135 -0
  196. package/docs/principles/self-driving-harness.md +129 -0
  197. package/docs/product/open-source-install-experience.md +237 -0
  198. package/docs/ramp/README.md +207 -0
  199. package/docs/release/open-source-readiness.md +208 -0
  200. package/docs/release/public-readiness-standard.md +205 -0
  201. package/docs/roadmap/world-class-open-source-v0.md +311 -0
  202. package/package.json +102 -8
  203. package/skills/humanish/SKILL.md +244 -0
  204. package/skills/humanish/agents/openai.yaml +7 -0
  205. package/index.js +0 -1
@@ -0,0 +1,583 @@
1
+ import type { StopWhen } from "./stop-conditions.js";
2
+ export declare const LAB_CONFIG_SCHEMA = "humanish.lab.v2";
3
+ /**
4
+ * Where the run acts: the host repo, a fresh clone, a running app a browser actor drives
5
+ * (`app-url`), an already-running LOCAL dev server driven IN-PROCESS via a custom
6
+ * CuaExecutor with NO clone and NO E2B desktop (`local-app`), or the operator's own local
7
+ * working tree packed and provisioned in-sandbox in place of a clone (`local-tree`).
8
+ * `local-app` routes to the cua backend and is library-assisted: a caller supplies
9
+ * `cuaHooks.buildExecutor` + `buildProvider` (no built-in driver exists yet), and the engine
10
+ * fails closed (HUMANISH_CUA_LAB_LOCAL_APP_NO_EXECUTOR) when run without them: a structured
11
+ * error, never a desktop attempt. See docs/architecture/state-driven-executor.md.
12
+ */
13
+ export type LabSubjectSource = "this-repo" | "clone" | "app-url" | "local-app" | "terminal-product" | "local-tree";
14
+ /**
15
+ * How a subject's WORLD relates across actor lanes. `per-lane-worlds` (the default; absent ==
16
+ * this) is the only fan-out topology the computer-use route ships — N lanes, N independent
17
+ * worlds, isolation + per-lane attribution. `shared-world` (#164) is the DECLARED override: ONE
18
+ * provisioned, mutable service plane that N role SEATS take turns against IN DECLARED ORDER, so
19
+ * their actions interact through shared state. Consumed ONLY on the shared-world route (clone ×
20
+ * e2b-desktop × a computer-use actor); inert/warned everywhere else (invariant 6).
21
+ */
22
+ export type LabSubjectTopology = "per-lane-worlds" | "shared-world";
23
+ export interface LabSubjectClone {
24
+ /** git clone depth; 1 (shallow) by default. Consumed on the computer-use clone route. */
25
+ depth?: number;
26
+ /** how many independent clone lanes to fan out (one sandbox/desktop each). */
27
+ fanout?: number;
28
+ /** keep the disposable clone for debugging instead of discarding. */
29
+ keep?: boolean;
30
+ }
31
+ /**
32
+ * `local-tree`: how the operator's own working tree is packed and provisioned in-sandbox in
33
+ * place of a clone. Internal shape (not re-exported from src/index.ts, same as LabSubjectClone).
34
+ */
35
+ export interface LabSubjectLocalTree {
36
+ /** extra archive excludes (path prefixes/basenames) added on top of the always-on denylist. */
37
+ exclude?: string[];
38
+ /** keep the disposable sandbox on failure for debugging (mirrors subject.clone.keep). */
39
+ keep?: boolean;
40
+ /** upload size cap override in bytes; default 256 MiB. */
41
+ maxArchiveBytes?: number;
42
+ }
43
+ /** How a cloned subject is installed/built/started inside the sandbox (computer-use route). */
44
+ export interface LabSubjectServe {
45
+ /** Optional bounded install step (e.g. "pnpm install --frozen-lockfile"). */
46
+ install?: string;
47
+ /** Optional bounded build step. */
48
+ build?: string;
49
+ /** Required long-lived start command — launched detached; the sandbox lifecycle owns it. */
50
+ start: string;
51
+ /** Loopback entry URL: the readiness-probe target and the URL the actor drives. The lab
52
+ * serves the clone INSIDE the sandbox, so this is always loopback (not subject to
53
+ * allowPublicTargets — that governs app-url subjects, i.e. external deployments). */
54
+ url: string;
55
+ /** Budget for the served app to answer the readiness probe. Default 180000. */
56
+ readyTimeoutMs?: number;
57
+ /** Override the install-step timeout (default 600000). Monorepos can exceed it. */
58
+ installTimeoutMs?: number;
59
+ /** Override the build-step timeout (default 600000). Large builds can exceed it. */
60
+ buildTimeoutMs?: number;
61
+ }
62
+ /** When a state step runs, relative to the serve sequence (clone subjects, computer-use route). */
63
+ export type LabStateStepWhen = "before-build" | "before-start" | "after-ready";
64
+ export interface LabSubjectStateStep {
65
+ /**
66
+ * [a-z0-9-] step label (must start alphanumeric), <=40 chars, unique across steps; becomes
67
+ * the detached-step name `subject-state-<name>` (interpolates into in-sandbox file paths —
68
+ * the shape is load-bearing, validated at parse AND re-enforced in the engine).
69
+ */
70
+ name: string;
71
+ /**
72
+ * Author-trusted shell command (same trust class as serve.install/build/start — the
73
+ * "serve commands are author-trusted" corollary). Runs detached in the subject directory
74
+ * with an atomic status file, kill-on-timeout, and a capped log tail. Persisted in
75
+ * evidence as a sha256-16 DIGEST only, never as text.
76
+ */
77
+ command: string;
78
+ /**
79
+ * Phase: before-build (after install — for builds that read the DB, e.g. SSG),
80
+ * before-start (after build, before the server launches — migrations, SQL/file fixtures,
81
+ * an in-sandbox `service postgresql start`), after-ready (after the readiness probe —
82
+ * fixtures loaded through the RUNNING app's API). Default: before-start.
83
+ */
84
+ when?: LabStateStepWhen;
85
+ /** Wall-clock budget per step. Default 300000. */
86
+ timeoutMs?: number;
87
+ }
88
+ /**
89
+ * A shared-world state CHECKPOINT: an author-trusted, READ-ONLY, AGGREGATE/DIGEST probe command
90
+ * (counts, max-timestamps, hashes) run at baseline and after each role's turn. Reuses the
91
+ * seed-step validation shape (name [a-z0-9-] ≤40, unique; command required). Persisted DIGEST-ONLY
92
+ * (only sha256-16(scrub+redact(stdout)) ever lands — never the raw value), same lockdown as the
93
+ * seed surface. Consumed ONLY on the shared-world route (#164); inert/warned elsewhere.
94
+ */
95
+ export interface LabSubjectStateCheckpoint {
96
+ /**
97
+ * [a-z0-9-] probe label (must start alphanumeric), <=40 chars, unique across checkpoints;
98
+ * names the detached step (`checkpoint-<snapshot>-<name>`) — load-bearing shape, validated at
99
+ * parse AND re-enforced in the engine.
100
+ */
101
+ name: string;
102
+ /**
103
+ * Author-trusted READ-ONLY shell command (same trust class as serve/seed — the "serve commands
104
+ * are author-trusted" corollary). Its stdout is scrubbed + pattern-redacted, then digested
105
+ * (sha256-16); the raw value never persists.
106
+ */
107
+ command: string;
108
+ /**
109
+ * Optional extra literal values to scrub from this probe's stdout before digesting (author-known
110
+ * values that may appear in the probe output, beyond the harness-provisioned env values which are
111
+ * always scrubbed). Names/values are NEVER persisted — only the digest is.
112
+ */
113
+ redact?: string[];
114
+ }
115
+ /** The subject's STATE story (clone subjects): seeded in-sandbox, or declared external. */
116
+ export interface LabSubjectState {
117
+ /** Ordered seed/migration/fixture steps. Order within a phase is declaration order. */
118
+ seed?: LabSubjectStateStep[];
119
+ /**
120
+ * Env var NAMES whose values point at state the lab does NOT control (e.g. a shared dev
121
+ * DB). Must be a subset of subject.env (so the declaration is mechanically backed by a
122
+ * provisioned name, not a vibe). Flips state provenance to "unpinned".
123
+ */
124
+ external?: string[];
125
+ /**
126
+ * Shared-world state checkpoints (#164): read-only digest probes run at baseline + after each
127
+ * role's turn to produce the harness-clocked interaction timeline. Consumed ONLY on the
128
+ * shared-world route; inert/warned elsewhere (invariant 6). Shape-validated everywhere.
129
+ */
130
+ checkpoint?: LabSubjectStateCheckpoint[];
131
+ }
132
+ /**
133
+ * `terminal-product`: the product-under-study a terminal agent must discover and use from PUBLIC
134
+ * SURFACES ONLY (the terminal-product route's subject). The subject is NOT provisioned/cloned —
135
+ * the agent drives the declared public surfaces, so provenance is UNPINNED (invariant 5). The
136
+ * concrete product name + surfaces are operator data; committed fixtures use a NEUTRAL mock name.
137
+ */
138
+ export interface LabSubjectProduct {
139
+ /** Public-safe product label (shape-validated like a lab id; interpolates into evidence). */
140
+ name: string;
141
+ /**
142
+ * The product's PUBLIC surfaces — the only world the agent sees. Each must be an http(s) URL
143
+ * (e.g. a docs page, an llms.txt, a skill manifest). Validated at parse; recorded in evidence.
144
+ */
145
+ publicSurfaces: string[];
146
+ }
147
+ export interface LabSubject {
148
+ source: LabSubjectSource;
149
+ /**
150
+ * WORLD topology across actor lanes. Absent == `per-lane-worlds` (the isolation default; every
151
+ * existing lab is byte-stable). `shared-world` is the declared override (#164): one mutable
152
+ * service plane, N role seats taking turns. Consumed ONLY on the shared-world route (clone ×
153
+ * e2b-desktop × a computer-use actor + a roster of ≥2 lanes); inert/warned elsewhere.
154
+ */
155
+ topology?: LabSubjectTopology;
156
+ /**
157
+ * CONCURRENT shared-world route ONLY (#164 phase 2): the author's REQUIRED attestation that the
158
+ * subject behind the internet-reachable `getHost` URL is SYNTHETIC seeded data. The concurrent
159
+ * route exposes the subject on a tokenless public URL for the run's duration, so real/external
160
+ * data must never sit behind it. This is author-trust + a provenance gate (verify also requires
161
+ * `subject.state.provenance == "seeded"`), NOT a no-real-data guarantee. Required when
162
+ * `topology: shared-world` + `execution.concurrency > 1`; inert/warned elsewhere.
163
+ */
164
+ exposure?: "synthetic";
165
+ /** `clone`: one or more owner/repo slugs (public or authorized-private). */
166
+ repos?: string[];
167
+ clone?: LabSubjectClone;
168
+ /**
169
+ * `app-url`: a loopback http(s) URL the computer-use actor drives (127.0.0.1/localhost
170
+ * only — driving arbitrary public sites is not allowed). The URL must be reachable from
171
+ * INSIDE the desktop sandbox; library callers provision it via the prepareDesktop hook.
172
+ * For a config-only path use `clone` + `serve` — the lab serves the app itself.
173
+ *
174
+ * `local-app`: the loopback http(s) URL of an already-running LOCAL dev server the caller's
175
+ * custom CuaExecutor drives in-process (no sandbox, no public-target option — always
176
+ * loopback). Passed to `buildExecutor` so the bridge knows where the app lives.
177
+ */
178
+ appUrl?: string;
179
+ /** `clone` (computer-use route): how the cloned app is served in-sandbox. */
180
+ serve?: LabSubjectServe;
181
+ /**
182
+ * Env var NAMES the subject app needs, provisioned into the sandbox from the caller's
183
+ * environment (--env-file). Names are recorded in evidence; values never are. Consumed
184
+ * on the computer-use clone route.
185
+ */
186
+ env?: string[];
187
+ /**
188
+ * `clone` (computer-use route): the subject's state story — seed/migration/fixture steps
189
+ * executed in-sandbox around the serve sequence, and/or declared external state. Recorded
190
+ * in the run bundle as structured provenance (invariant 5): seeded with command digests,
191
+ * UNPINNED for external state, declared-not-run for dry-run/failed provisioning.
192
+ */
193
+ state?: LabSubjectState;
194
+ /**
195
+ * `terminal-product` (terminal route): the product the terminal agent discovers + uses from
196
+ * PUBLIC surfaces only. Consumed on the terminal route; rejected on every other source.
197
+ */
198
+ product?: LabSubjectProduct;
199
+ /**
200
+ * `local-tree` (computer-use route): local-tree packs the lab resolution cwd (the project
201
+ * directory humanish runs from) instead of cloning a repo. `exclude` adds extra archive excludes
202
+ * on top of the always-on denylist; `keep` preserves the sandbox on failure for debugging;
203
+ * `maxArchiveBytes` caps the upload. Consumed on the local-tree route; rejected on every other
204
+ * source.
205
+ */
206
+ localTree?: LabSubjectLocalTree;
207
+ }
208
+ export interface LabActorLaneFocus {
209
+ id?: string;
210
+ label?: string;
211
+ /** Per-lane steer appended to the actor's mission. Consumed on the app-url route. */
212
+ instruction?: string;
213
+ }
214
+ /**
215
+ * One differentiated fan-out lane on the computer-use E2B route (per-lane worlds). Each lane
216
+ * becomes an independent E2B desktop sandbox with its own persona/device/starting-steer. All
217
+ * fields optional: an omitted persona/device/instruction inherits the actor-level default. `id`
218
+ * defaults to `lane-01`..`lane-NN` and must be a public-safe token (it names per-lane evidence
219
+ * paths). Consumed ONLY on the computer-use E2B route (inert/warned elsewhere).
220
+ */
221
+ export interface LabActorLane {
222
+ /** Public-safe lane label (interpolates into per-lane evidence paths). Default lane-NN. */
223
+ id?: string;
224
+ /**
225
+ * App-defined actor type label for grouping simulated users ("operator", "viewer",
226
+ * "maintainer", etc.). This is NOT the execution actor dispatch key (`actors[0].type`);
227
+ * it is adapter-owned taxonomy for roster/readback.
228
+ */
229
+ actorType?: string;
230
+ /** App-defined surface label for grouping lanes that start from different product areas. */
231
+ surface?: string;
232
+ /** App-defined correlation id tying lanes to one shared case/account/work item. */
233
+ caseGroup?: string;
234
+ /** Persona id/label threaded into this lane's actor prompt. Default: actors[0].persona. */
235
+ persona?: string;
236
+ /** Named device preset this lane renders at. XOR raw execution.desktop.resolution. */
237
+ device?: string;
238
+ /** Per-lane steer appended to this lane's mission (the roster's per-lane focus). */
239
+ instruction?: string;
240
+ /**
241
+ * Deterministic lane completion guard. When set, this lane stops as soon as the runtime
242
+ * observation matches any declared rule; actor-level stopWhen is used as the default.
243
+ */
244
+ stopWhen?: StopWhen;
245
+ /**
246
+ * App-url computer-use ONLY: absolute browser URL this lane opens instead of `subject.appUrl`.
247
+ * This is the generic setup-produced-target handoff for crawler/swarm labs: product adapters may
248
+ * start any topology they need, then hand Humanish explicit lane targets. Public/non-loopback
249
+ * targets still require `policies.allowPublicTargets: true`. Inert/rejected on clone, local-app,
250
+ * shared-world, scripted-browser, and terminal routes.
251
+ */
252
+ target?: string;
253
+ /**
254
+ * Shared-world ONLY (#164): this role's per-seat loopback entry route, resolved against
255
+ * `subject.serve.url` and REQUIRED to be same-origin (loopback) with it — the seat opens
256
+ * `serve.url + entry`. Validated at parse AND re-enforced in the engine. Inert/warned on every
257
+ * non-shared-world route (the per-lane-worlds fan-out roster has no per-lane entry).
258
+ */
259
+ entry?: string;
260
+ }
261
+ /**
262
+ * Compact authoring sugar for repeated lane groups. The parser expands each group into concrete
263
+ * `lanes[]` with deterministic ids (`<group.id>-01`, `<group.id>-02`, ...). The runtime never
264
+ * consumes this shape directly; it always sees ordinary `LabActorLane` entries.
265
+ */
266
+ export interface LabActorRosterGroup extends Omit<LabActorLane, "id"> {
267
+ /** Public-safe group id; prefixes generated lane ids. */
268
+ id: string;
269
+ /** Number of lanes to generate for this group. */
270
+ count: number;
271
+ }
272
+ export interface LabActor {
273
+ /**
274
+ * The actor label. On app-url subjects this is a REAL dispatch key: it must resolve to a
275
+ * registered computer-use actor (e.g. openai-computer-use, paired with e2b-desktop) or a
276
+ * registered scripted-browser actor (e.g. scripted-browser, local execution), and that
277
+ * descriptor runs the session. On other routes it remains a free-form label (built-ins use
278
+ * descriptive labels like synthetic-persona, humanish-setup, codex-app-server).
279
+ */
280
+ type: string;
281
+ /** Lane count — route-specific (see HONEST SCOPE header): synthetic simCount; scripted
282
+ * surface roster {1 = desktop, 2 = desktop + mobile, default 1}; computer-use E2B route the
283
+ * HOMOGENEOUS fan-out lane count (cap 16). XOR `lanes`. */
284
+ count?: number;
285
+ /** Computer-use E2B route: a DIFFERENTIATED fan-out roster (per-lane worlds). XOR `count`,
286
+ * `roster`, and `laneFocus`. Cap 16 lanes. Consumed only on the cua E2B route
287
+ * (inert/warned elsewhere). */
288
+ lanes?: LabActorLane[];
289
+ /** Persona id/label threaded into the actor prompt. Consumed on the app-url route. */
290
+ persona?: string;
291
+ /** Consumed on the app-url route (laneFocus.instruction appended to the mission). XOR `lanes`. */
292
+ laneFocus?: LabActorLaneFocus;
293
+ /** Free-form mission threaded into the actor prompt. Consumed on the app-url route. */
294
+ mission?: string;
295
+ /** Provider model override. Consumed on the app-url route. */
296
+ model?: string;
297
+ /**
298
+ * Deterministic completion guard used as the default for CUA lanes. Lane-level stopWhen
299
+ * overrides this value.
300
+ */
301
+ stopWhen?: StopWhen;
302
+ }
303
+ export type LabExecutionTarget = "local" | "e2b-desktop" | "e2b-terminal";
304
+ /** Terminal transport: the captured non-interactive exec stream (stdin disabled). NOT an
305
+ * interactive duplex PTY — labeling captured exec output "pty" would be a claim/mechanism
306
+ * mismatch (invariant 6 + the goal packet's PTY ruling), so this lane uses "exec-stream". */
307
+ export type LabTerminalTransport = "exec-stream";
308
+ /** Whether operator stdin reaches the in-sandbox agent. Disabled by default (the run is
309
+ * autonomous + comparable to an unassisted baseline). "planned" reserves the interventions-ledger
310
+ * path SLICE 2 builds; "sent" (assisted input) is NOT shippable until the ledger + comparability
311
+ * flag + verify check exist (the safety contract forbids an assisted run masquerading as green). */
312
+ export type LabTerminalStdin = "disabled" | "planned" | "sent";
313
+ export interface LabExecutionTerminal {
314
+ /** Transport label. Default (and only honest value this slice) is "exec-stream". */
315
+ transport?: LabTerminalTransport;
316
+ /** Operator stdin posture. Default "disabled". */
317
+ stdin?: LabTerminalStdin;
318
+ }
319
+ /**
320
+ * The runtime-auth channel for the in-sandbox agent (terminal route). "openai-env" declares that
321
+ * OPENAI_API_KEY/CODEX_API_KEY is the runtime key — to be injected ONLY into the command-scoped
322
+ * `codex` invocation (keyPlacement "in-sandbox-command-scoped"), never sandbox-global. DECLARED
323
+ * this slice (recorded as names-only evidence); the engine injection lands in SLICE 2.
324
+ */
325
+ export type LabRuntimeAuth = "openai-env";
326
+ export type LabDesktopBrowser = "default" | "chrome" | "chromium" | "firefox";
327
+ export interface LabExecutionDesktop {
328
+ /**
329
+ * Named device preset (mobile / small-mobile / narrow-mobile / tablet / desktop / wide) the
330
+ * run renders at. Consumed on the computer-use route; default `desktop` (1440x950). On that
331
+ * route only width/height physically render (the X screen is sized to the preset, so
332
+ * width-based responsive CSS fires) — touch/DPR/UA are sim-parity prompt signals, not rendered.
333
+ */
334
+ device?: string;
335
+ /** Raw desktop resolution [width, height] — an escape hatch that overrides `device`. */
336
+ resolution?: [number, number];
337
+ /**
338
+ * Browser family to launch for hosted desktop actor lanes. Absent/default preserves the
339
+ * historical desktop opener behavior. A concrete value means "launch this browser or fail"
340
+ * instead of silently accepting the template's default URL opener.
341
+ */
342
+ browser?: LabDesktopBrowser;
343
+ /** Sandbox server-side timeout. Consumed on the app-url route. */
344
+ sandboxTimeoutMs?: number;
345
+ /**
346
+ * Custom E2B desktop TEMPLATE (image) the run launches on — a non-empty template NAME or ID —
347
+ * instead of the stock `desktop` template. Lets a subject that needs runtimes the stock image
348
+ * lacks (e.g. node/bun/a local Postgres baked into an adopter-maintained image) run as-is. Any
349
+ * string is a valid template name/id (there is no allowlist). Consumed ONLY on the
350
+ * `execution.target: e2b-desktop` computer-use routes (the cua/shared-world/concurrent backends
351
+ * that call `Sandbox.create`); inert/warned on every route that creates no desktop. Threaded to
352
+ * `Sandbox.create(template, opts)`; absent leaves the byte-stable `Sandbox.create(opts)` default.
353
+ * A template name is public-safe (not a secret) and is recorded in the run bundle.
354
+ */
355
+ template?: string;
356
+ /** Use the Codex app-server client mode for headed desktop actor surfaces. Consumed (meta). */
357
+ codexAppServer?: boolean;
358
+ }
359
+ export interface LabExecution {
360
+ target?: LabExecutionTarget;
361
+ /** Actor session wall-clock budget. Consumed on the app-url route. */
362
+ timeoutMs?: number;
363
+ /** FORWARD-DECLARED. */
364
+ completionTimeoutMs?: number;
365
+ /** FORWARD-DECLARED. */
366
+ concurrency?: number;
367
+ desktop?: LabExecutionDesktop;
368
+ /** `terminal-product` route: the terminal transport + stdin posture. Consumed on that route. */
369
+ terminal?: LabExecutionTerminal;
370
+ /** `terminal-product` route: the in-sandbox agent's runtime-auth channel. Consumed (names-only
371
+ * evidence this slice; command-scoped injection in SLICE 2). Inert on other routes. */
372
+ runtimeAuth?: LabRuntimeAuth;
373
+ }
374
+ export type LabScenarioMode = "dry-run" | "live";
375
+ /**
376
+ * The blast-radius budget for a route that places a live key inside the sandbox (terminal route).
377
+ * Per the safety contract, the live key is never exercised without a fail-closed cap in force.
378
+ * All values are non-negative numbers (0 is the no-spend default). DECLARED + recorded this slice;
379
+ * SLICE 2 folds in a minimal fail-closed cap and SLICE 3 enforces the full ledger.
380
+ */
381
+ export interface LabScenarioCaps {
382
+ /** Max USD the run may spend (provider + product). 0 = no-spend. */
383
+ maxUsd?: number;
384
+ /** Max billable product jobs the agent may trigger. 0 = none. */
385
+ maxJobs?: number;
386
+ /** Max wall-clock minutes for the agent session. */
387
+ maxMinutes?: number;
388
+ }
389
+ export interface LabScenario {
390
+ /** Reference a committed scenario by id (humanish/scenarios/<ref>.yaml) or path. CONSUMED
391
+ * (and REQUIRED) on the scripted-browser route; FORWARD-DECLARED elsewhere. */
392
+ ref?: string;
393
+ /** Or inline the scenario body. FORWARD-DECLARED (PR #2). */
394
+ inline?: Record<string, unknown>;
395
+ /** dry-run = contract evidence (no provider spend); live = real run. Consumed. */
396
+ mode?: LabScenarioMode;
397
+ /** Spend/job/time caps. Consumed (recorded in the bundle) on the terminal-product route;
398
+ * inert (warned) elsewhere. */
399
+ caps?: LabScenarioCaps;
400
+ }
401
+ export interface LabPolicies {
402
+ /**
403
+ * Redact target repo labels in durable artifacts. Consumed on the meta route and on the
404
+ * computer-use clone route (provenance), where it DEFAULTS to true when the clone
405
+ * authenticates via GITHUB_TOKEN (a token-bearing clone is treated as private until
406
+ * declared otherwise).
407
+ */
408
+ redactRepos?: boolean;
409
+ /**
410
+ * Blur+downscale persisted screenshots on the computer-use route. Default FALSE — the common
411
+ * case is watching a sim of your OWN app locally (gitignored .humanish), where full fidelity is
412
+ * the deliverable. Set true for unowned subjects or bundles meant to be shared as-is. The
413
+ * provider always sees raw frames; this only governs what is persisted. Raw bundles stay
414
+ * local (gitignored, commit-scan-guarded); a redact-on-export step for them is planned.
415
+ */
416
+ redactScreenshots?: boolean;
417
+ /**
418
+ * Allow an app-url subject to point at a non-loopback (public/preview/staging) URL the lab
419
+ * owner declares. Default FALSE (loopback-only). The invariant is "the actor drives a target
420
+ * the owner declared" — setting this IS that declaration (e.g. a Vercel preview of your app).
421
+ */
422
+ allowPublicTargets?: boolean;
423
+ /**
424
+ * Terminal-product credential-boundary policies — all DEFAULT FALSE (deny-by-default). They are
425
+ * DECLARED + recorded this slice; the engine ENFORCES them by construction (what the sandbox is
426
+ * and is not given) + verifier checks in SLICE 2. Setting any to true is an affirmative,
427
+ * recorded declaration that widens the agent's blast radius.
428
+ */
429
+ /** Allow the in-sandbox agent to clone/inspect a private/downstream repo. Default FALSE — the
430
+ * agent works from PUBLIC surfaces only (safety contract item 3). */
431
+ allowPrivateRepoAccess?: boolean;
432
+ /** Allow media/creative-provider keys into the sandbox. Default FALSE (only the runtime LLM key
433
+ * enters, command-scoped — safety contract item 4). */
434
+ allowProviderCredentials?: boolean;
435
+ /** Allow payment-provider keys into the sandbox. Default FALSE. */
436
+ allowPaymentCredentials?: boolean;
437
+ /** Allow GitHub write tokens (mutating operations) into the sandbox. Default FALSE. */
438
+ allowGitHubMutation?: boolean;
439
+ }
440
+ export interface LabReview {
441
+ /** FORWARD-DECLARED (PR #2). */
442
+ scoring?: string;
443
+ /** FORWARD-DECLARED (PR #2). */
444
+ milestones?: string;
445
+ /** FORWARD-DECLARED (PR #2). */
446
+ vocabulary?: string;
447
+ }
448
+ export interface LabDefaults {
449
+ open?: boolean;
450
+ }
451
+ export interface LabConfig {
452
+ schema: typeof LAB_CONFIG_SCHEMA;
453
+ id: string;
454
+ title?: string;
455
+ description?: string;
456
+ subject: LabSubject;
457
+ actors: LabActor[];
458
+ execution?: LabExecution;
459
+ /** FORWARD-DECLARED (PR #2). */
460
+ personas?: Record<string, unknown>[];
461
+ scenario?: LabScenario;
462
+ policies?: LabPolicies;
463
+ review?: LabReview;
464
+ defaults?: LabDefaults;
465
+ }
466
+ export interface LabConfigParseSuccess {
467
+ ok: true;
468
+ config: LabConfig;
469
+ warnings: string[];
470
+ }
471
+ export interface LabConfigParseFailure {
472
+ ok: false;
473
+ error: {
474
+ code: "HUMANISH_LAB_INVALID";
475
+ message: string;
476
+ };
477
+ }
478
+ export type LabConfigParseResult = LabConfigParseSuccess | LabConfigParseFailure;
479
+ /**
480
+ * Validate a parsed YAML object into a LabConfig. Pure: the caller owns file IO. Structural
481
+ * validation only. Fields the engine does not yet consume are accepted but reported in
482
+ * `warnings` so `lab inspect` never silently swallows a setting that does nothing.
483
+ */
484
+ export declare function parseLabConfig(raw: unknown): LabConfigParseResult;
485
+ export declare const MAX_CUA_LANES = 16;
486
+ /** True when `type` resolves to a registered terminal actor (the "terminal" lane). Exported so
487
+ * the engine + tests can resolve the dispatch the same way the parser does. */
488
+ export declare function actorResolvesToTerminal(type: string | undefined): boolean;
489
+ /**
490
+ * True when this config routes to the computer-use backend: an app-url subject whose first
491
+ * actor resolves to a registered computer-use actor, or a clone subject on a hosted desktop
492
+ * whose first actor does. Single source of truth — selectLabBackend and the warning logic
493
+ * both use it. (The app-url branch used to be unconditionally true; it narrowed when the
494
+ * scripted-browser lane arrived. Behavior-preserving for every parse-valid config —
495
+ * selectLabBackend keeps a bare app-url fallback to the cua backend so library-API configs
496
+ * with unknown actors still hit its fail-closed ACTOR_UNSUPPORTED.)
497
+ */
498
+ /**
499
+ * The declared fan-out lane count on the computer-use route: a `lanes[]` roster's length, else
500
+ * a homogeneous `count`, else 1. The single source of truth shared by the parser, the engine,
501
+ * and the pre-flight plan so the lane count is computed ONE way everywhere.
502
+ */
503
+ export declare function cuaLaneCount(config: LabConfig): number;
504
+ /**
505
+ * Cross-validate the computer-use fan-out declaration (per-lane worlds). Returns the failure
506
+ * message, or null when valid. Enforced at parse AND re-enforced in the engine (runCuaActorLab
507
+ * is itself exported npm surface). Structural lane shape (id/device validity, id uniqueness) is
508
+ * already checked in parseLanes; this is the route-scoped XOR/cap/policy layer.
509
+ */
510
+ export declare function cuaLaneValidationReason(config: LabConfig): string | null;
511
+ /**
512
+ * Engine-level path-token validation for configs supplied directly through the
513
+ * public TypeScript/JavaScript API instead of parseLabConfig.
514
+ */
515
+ export declare function laneRosterStructuralValidationReason(config: LabConfig): string | null;
516
+ /**
517
+ * Cross-validate a `topology: shared-world` declaration (#164). Returns the failure message, or
518
+ * null when valid. Enforced at parse AND re-enforced in the engine (runSharedWorldLab is exported
519
+ * npm surface). The shared-world override REQUIRES: a clone or local-tree source + e2b-desktop
520
+ * target + a computer-use actor + a `subject.serve` block + an `actors[0].lanes` roster of ≥2 roles (the
521
+ * roster IS the role roster — no parallel roles[] field), and every role `entry` must resolve
522
+ * same-origin (loopback) with serve.url. Fail-closed: a half-declared shared-world is rejected,
523
+ * never silently downgraded.
524
+ */
525
+ export declare function sharedWorldValidationReason(config: LabConfig): string | null;
526
+ export declare function routesToComputerUse(config: LabConfig): boolean;
527
+ /**
528
+ * True when this config routes to the SHARED-WORLD backend (#164): a clone or local-tree subject
529
+ * on a hosted desktop whose first actor resolves to a computer-use actor AND that declares the
530
+ * `shared-world` topology. Mirror of routesToComputerUse; the single source of truth shared by
531
+ * selectLabBackend (which checks it BEFORE the cua route) and the warning logic. The same
532
+ * clone/local-tree × e2b-desktop × computer-use composition WITHOUT `topology: shared-world` stays per-lane-worlds
533
+ * (the cua route) — the topology declaration is the override switch.
534
+ */
535
+ export declare function routesToSharedWorld(config: LabConfig): boolean;
536
+ /**
537
+ * True when this config routes to the CONCURRENT shared-world backend (#164 phase 2): a shared-world
538
+ * config with `execution.concurrency > 1` (N actor seats driving ONE getHost-exposed plane AT ONCE).
539
+ * `concurrency` absent or 1 stays the sequential PoC (`routesToSharedWorld` → the sequential
540
+ * backend). selectLabBackend checks this BEFORE routesToSharedWorld.
541
+ */
542
+ export declare function routesToConcurrentSharedWorld(config: LabConfig): boolean;
543
+ /**
544
+ * Cross-validate a CONCURRENT shared-world declaration (#164 phase 2). Returns the failure message,
545
+ * or null when valid. Includes the base shared-world checks PLUS the concurrent extras: a synthetic
546
+ * subject attestation (FIX-3), a 0.0.0.0 serve bind (FIX-4 — getHost only routes to a port bound on
547
+ * all interfaces), and no `subject.clone.keep`/`subject.localTree.keep` (FIX-9 - either would
548
+ * orphan actor sandboxes). Enforced at parse AND re-enforced in the engine (runConcurrentSharedWorld
549
+ * is exported npm surface).
550
+ */
551
+ export declare function concurrentSharedWorldValidationReason(config: LabConfig): string | null;
552
+ /**
553
+ * Resolve a shared-world seat's entry URL from `serve.url` + a role's `entry` (relative path or
554
+ * same-origin absolute URL). Returns null when the combination is not a same-origin loopback URL
555
+ * (the load-bearing public-safety boundary — a seat only ever drives the in-sandbox app).
556
+ */
557
+ export declare function resolveSeatUrl(serveUrl: string, entry: string | undefined): string | null;
558
+ /**
559
+ * True when this config routes to the scripted-browser backend: an app-url subject whose
560
+ * first actor resolves to a registered scripted-browser actor (execution.target local or
561
+ * absent — the parse layer enforces that pairing). Mirror of routesToComputerUse; the single
562
+ * source of truth for selectLabBackend and the warning logic.
563
+ */
564
+ export declare function routesToScriptedBrowser(config: LabConfig): boolean;
565
+ export declare function routesToLocalScriptedBrowser(config: LabConfig): boolean;
566
+ export declare function routesToProvisionedScriptedBrowser(config: LabConfig): boolean;
567
+ /**
568
+ * True when this config routes to the terminal-product backend: a terminal-product subject whose
569
+ * first actor resolves to a registered terminal actor (execution.target e2b-terminal or absent —
570
+ * the parse layer enforces that pairing). Mirror of routesToComputerUse/routesToScriptedBrowser;
571
+ * the single source of truth for selectLabBackend and the warning logic.
572
+ */
573
+ export declare function routesToTerminalProduct(config: LabConfig): boolean;
574
+ export declare function isLoopbackUrl(value: string): boolean;
575
+ /** A well-formed http(s) URL (any host). Shape gate before the loopback/public-target policy. */
576
+ export declare function isHttpUrl(value: string): boolean;
577
+ /**
578
+ * Semantic validation for `subject.state`, shared by parseLabConfig and the engine
579
+ * (runCuaActorLab re-enforces it on configs that arrive through the library API). Returns
580
+ * the failure message, or null when the declaration is valid. Reads the candidate
581
+ * defensively — library callers can hand the engine arbitrarily-shaped objects.
582
+ */
583
+ export declare function subjectStateInvalidReason(state: LabSubjectState, env: readonly string[] | undefined): string | null;