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,428 @@
1
+ # Current Goals
2
+
3
+ Status date: 2026-07-14 (rev 14)
4
+
5
+ This page is the current public-safe operating goal for `humanish`. Keep it
6
+ short enough to reread before a coding session and concrete enough that future
7
+ agents can choose useful work without private context.
8
+
9
+ ## North Star
10
+
11
+ Humanish should be the open-source CLI that lets a maintainer ask:
12
+
13
+ > What happens when realistic synthetic personas try to use this app, CLI, or
14
+ > agent-facing workflow?
15
+
16
+ The answer should be observable, verifiable, public-safe, and easy to turn into
17
+ actionable feedback.
18
+
19
+ ## Current Safety State (`0.15.1`)
20
+
21
+ - Managed run, Observer, feedback, lab, actor-output, and source-archive paths
22
+ bind to validated physical filesystem identities and fail closed on unsafe
23
+ traversal, link, special-file, or retargeting states.
24
+ - Provider IDs stored in `run.json` are mutable evidence, not cleanup
25
+ authority. `humanish cleanup` writes an inspection receipt; same-process
26
+ teardown continues to use the provider handles that created the resources.
27
+ - The bundled `oss` manifest defaults to dry-run. Live OSS meta-lab execution
28
+ fails with `HUMANISH_OSS_META_LIVE_ISOLATION_REQUIRED` before side effects
29
+ until repository-derived instructions have an isolated credential boundary.
30
+ - Ordinary Git repositories and verified linked worktrees remain supported.
31
+ Git metadata that cannot pass containment validation is recorded as
32
+ unavailable rather than followed.
33
+
34
+ ## Definition Of Awesome
35
+
36
+ A world-class Humanish run should eventually provide:
37
+
38
+ - one human-friendly command that starts simulations and opens Observer;
39
+ - multiple synthetic personas with different goals, patience, and skill levels;
40
+ - UI, CLI, TUI, and code-agent lanes in one mission-control Observer;
41
+ - real evidence: screenshots, terminal transcripts, lifecycle events, traces,
42
+ filesystem setup-quality snapshots, artifacts, and verifier output;
43
+ - clear pass, fail, blocked, and gap states;
44
+ - public-safe feedback issue drafts that do not mutate GitHub by default;
45
+ - first-class `.yaml` lab manifests for reusable simulation runs;
46
+ - adapter contracts that let projects customize behavior without forking core;
47
+ - release gates that prevent PII, PHI, secrets, private artifacts, and stale
48
+ internal residue from reaching the public repo or package.
49
+
50
+ ## Current Objective
51
+
52
+ Make the public package and repo credible enough that an external maintainer can:
53
+
54
+ 1. install the skill;
55
+ 2. install `humanish`;
56
+ 3. run `humanish init`;
57
+ 4. run `humanish watch`;
58
+ 5. run `humanish watch first-run` or another lab manifest;
59
+ 6. inspect Observer evidence;
60
+ 7. verify the bundle;
61
+ 8. produce a public-safe feedback draft;
62
+ 9. understand the next live-adapter path without reading chat history.
63
+
64
+ ## Near-Term Goals
65
+
66
+ ### 1. Public Readiness
67
+
68
+ Keep the repository clean and public-safe.
69
+
70
+ Acceptance:
71
+
72
+ ```bash
73
+ pnpm release:check
74
+ git diff --check
75
+ ```
76
+
77
+ Fresh clone release checks should pass before public visibility changes.
78
+
79
+ ### 2. Future-Agent Ramp
80
+
81
+ Maintain a durable ramp that tells future contributors and coding agents where
82
+ to start, what exists, what remains, and what proof is required.
83
+
84
+ Acceptance:
85
+
86
+ - [`docs/ramp/README.md`](../ramp/README.md) stays current;
87
+ - this page stays current;
88
+ - README links both;
89
+ - release package includes both docs directories.
90
+
91
+ ### 3. Fresh-Agent Install Proof
92
+
93
+ Prove the skill and package setup flow from a disposable target app with no chat
94
+ context.
95
+
96
+ Target proof:
97
+
98
+ ```bash
99
+ npm i -D humanish
100
+ npx humanish init --yes
101
+ npx humanish watch --json --no-open
102
+ npx humanish verify --run latest --json
103
+ npx humanish feedback issue --run latest --repo owner/repo --format markdown
104
+ ```
105
+
106
+ The proof target must use synthetic personas and no real user data.
107
+
108
+ ### 4. Live Browser Adapter
109
+
110
+ Graduate from synthetic UI lanes to a real browser journey against a local app.
111
+
112
+ Minimum acceptance:
113
+
114
+ - local app target detection;
115
+ - browser launch;
116
+ - route/state capture;
117
+ - screenshot artifact;
118
+ - run bundle references screenshot evidence;
119
+ - Observer renders the screenshot;
120
+ - `verify` fails closed if required evidence is missing;
121
+ - bounded desktop/mobile two-step browser persona proof with per-step traces and
122
+ screenshots. `done`
123
+ - LLM-driven browser lane: the registered `openai-computer-use` actor dispatches
124
+ from a lab config (`subject.source: app-url`, loopback entry only) into a hosted
125
+ E2B desktop, fills the provider-neutral `stream.actor` trace seam, and persists
126
+ a verified redacted bundle (0.3.0 registered the actor; 0.4.0 made
127
+ `actors[].type` a real dispatch key). `done`
128
+ - Clone subject provider: `subject.source: clone` + `serve` clones a repo INTO the
129
+ sandbox, installs/builds/starts it from config, probes readiness, and records
130
+ provenance (repo, commit, env names) in the bundle — config-only computer-use
131
+ labs against real apps (0.5.0; see `docs/goals/proof-roadmap/goal.md` —
132
+ repo-only, not shipped in the npm package — and
133
+ `docs/principles/invariants-and-defaults.md`, which ships in the package).
134
+ `done`
135
+ - De-paranoia (0.6.0): the redaction redesign + demoted defaults. Screenshots are
136
+ full-fidelity by default (redaction binds the publish boundary, not capture —
137
+ `policies.redactScreenshots` opts back in); `policies.allowPublicTargets` lets an
138
+ owner drive a declared deployment/preview; `subject.clone.keep` is honored on
139
+ failure for debugging; `serve.installTimeoutMs`/`buildTimeoutMs` are configurable
140
+ for monorepo-scale builds. Doctrine updated with the capture-vs-publish rule. This
141
+ re-sequences the proof roadmap: a redaction redesign and an overridable
142
+ public-target policy are prerequisites for any decision-grade depth evidence, so
143
+ they land BEFORE the consumer-web-app / agent-skill depth phases. `done`
144
+ - Device presets (0.6.1): viewport/device is a real dimension, with LITERAL values copied
145
+ from the in-house sims (mobile 414×896 … wide 1920×1080; default `desktop` 1440×950) —
146
+ not guessed. `execution.desktop.device` picks the per-run viewport; the guessed 1280×800
147
+ is gone. Honest fidelity: on the E2B route only width/height render (real mobile *layout*)
148
+ + the model is told its device, matching the sims' organic lanes; true touch/DPR/UA needs
149
+ the CDP actor. Per-*persona* device (N×devices) rides fan-out. `done`
150
+
151
+ ### 5. Live Terminal And Codex Lanes
152
+
153
+ Make local PTY and Codex-style lanes reliable enough that Observer can show
154
+ running, passed, failed, blocked, and timed-out states without human inference.
155
+
156
+ Minimum acceptance:
157
+
158
+ - sanitized transcript persistence;
159
+ - explicit completion reason;
160
+ - verifier checks redaction status;
161
+ - Observer polling reflects lane completion;
162
+ - no raw private transcript or credential values.
163
+
164
+ Terminal-product real-agent lane (0.8.0; depth-axis layer 6, so an adopter can delete a
165
+ bespoke real-agent sim for humanish + a thin adapter — see
166
+ `docs/goals/terminal-product-lane/goal.md`):
167
+
168
+ - `subject.source: terminal-product` + `execution.target: e2b-terminal` + the registered
169
+ `codex-exec` terminal actor route a config to a real Codex agent studying a product from
170
+ public surfaces inside an E2B shell. `done`
171
+ - The credential-placement inversion is enforced by construction AND by verifier: the runtime
172
+ key is injected ONLY command-scoped into the `codex` invocation, never sandbox-global; a
173
+ deny-by-default allowlist excludes GitHub/payment/deploy/db creds; metadata is a positive
174
+ allowlist; stdin is disabled with an always-present interventions ledger; cleanup is proven
175
+ or the run fails closed. `done`
176
+ - Cost/no-spend ledger with the null-vs-known-zero-vs-absent discipline (unknowns are `null`,
177
+ never guessed); the no-spend proof is DERIVED from the ledger, never asserted; `maxUsd`/
178
+ `maxJobs`/`maxMinutes` caps enforced fail-closed. `done`
179
+ - Product-adapter extension seam: exported contract types + a scorer/feedback DI hook +
180
+ adapter-namespaced product nouns, so an adopter attaches scoring/feedback as a thin
181
+ in-repo extension without forking core. `done`
182
+ - Cleanup is proven BY EXACT CREATED ID: `Sandbox.kill(id)`, confirmed further by
183
+ `Sandbox.getInfo(id)` where the SDK exposes it, and humanish never calls `Sandbox.list`. A live
184
+ rung never needs a dedicated or isolated E2B key; the SAME shared operator key used everywhere
185
+ else in this repo is safe, because humanish only ever reaches a sandbox it created (see
186
+ "The placement rule" corollary in `docs/principles/invariants-and-defaults.md`).
187
+ - LIVE-PROVEN (2026-07-09): a real Codex agent, bootstrapped in a stock E2B shell (Node
188
+ installed in-sandbox, run via `npx -y @openai/codex@latest exec`), studied a public
189
+ agent-CLI product from its declared public surfaces and ran the product's free zero-spend
190
+ guide within `$0` no-spend caps; verdict nonce-verified, cleanup proven BY EXACT ID
191
+ (`getInfo(id)` SandboxNotFoundError, never `Sandbox.list`), verify 15/15, share_ready
192
+ (`docs/goals/terminal-product-lane/receipts/terminal-live-rung-2026-07-09.md`). This closes
193
+ the #159 live-receipt gap. Optional follow-up: a custom image with the agent runtime baked in
194
+ to drop the per-run npx bootstrap. Duplex-PTY/xterm replay is a deferred SLICE 5.
195
+
196
+ Multi-lane fan-out for the computer-use lab (0.9.0; proof-roadmap layer 2, the prerequisite
197
+ for multi-actor shared-state work — #163, see `docs/goals/multi-lane-fanout/goal.md`):
198
+
199
+ - `actors[0].lanes[]` (differentiated roster: per-lane persona/device/starting-surface) XOR
200
+ `actors[0].count` (homogeneous) fan out N independent E2B desktops in ONE run bundle;
201
+ `per-lane worlds` is the only topology this slice (shared-world is #164). `done`
202
+ - `execution.concurrency` bounds in-flight paid desktops (default min(N,3); env may only
203
+ lower it); a pre-flight spend/lane plan prints before any sandbox/provider call and at $0
204
+ in dry-run; per-lane teardown reclaims ONLY each lane's own sandbox by id (never
205
+ account-wide). `done`
206
+ - Proven deterministically (fake substrate: bounded concurrency, by-id teardown, fail-fast,
207
+ hollow-lane caught) AND with a kept live rung (2 lanes, two distinct desktops, both
208
+ reclaimed by id, bundle verifies — `docs/goals/multi-lane-fanout/receipts/`). `done`
209
+ - Deferred: seed-fork provisioning (PR-2), in-process-route fan-out, shared-world topology
210
+ (#164).
211
+
212
+ Shared-world topology — multi-actor against ONE shared mutable service (0.10.0; proof-roadmap
213
+ layer 7; #164; `docs/goals/shared-world-topology/`). The north-star sim leverage: MANY personas,
214
+ ONE shared world.
215
+
216
+ - Sequential (`topology: shared-world`, concurrency 1): one sandbox, N role seats take turns
217
+ against the shared DB; a checkpoint timeline proves role B acted on a world already containing
218
+ role A's mutation. `done`
219
+ - **Concurrent (`topology: shared-world` + `concurrency > 1`): one subject sandbox served +
220
+ `getHost`-exposed, N actor desktop sandboxes drive that one URL SIMULTANEOUSLY** (reuses fan-out
221
+ orchestration; all N+1 reclaimed by id). Honest attribution under concurrency: per-persona
222
+ outcomes + harness-clocked `laneWindows` proving real overlap + a `stateSeries` of the shared
223
+ world under load; causation is structurally inexpressible (independent series, no
224
+ per-delta→actor field). `done`
225
+ - A new `attributionClass: isolated | shared-world` honesty axis + verify FAIL-CLOSED on the
226
+ required/forbidden `attributionLimits` sets + a concurrency-on-pass gate (a passed concurrent
227
+ run must show real overlap AND a state delta coincident with it). `getHost` URLs are
228
+ internet-reachable → the route is gated (verify) to synthetic+seeded subjects; the raw URL is
229
+ digest-only in evidence. `done`
230
+ - **LIVE-PROVEN (0.10.1):** a kept live receipt ran 3 personas concurrently against ONE
231
+ getHost-exposed synthetic plane — all 3 passed, all 3 lane-windows overlapped on the real clock,
232
+ the shared stateSeries evolved under load, N+1=4 sandboxes reclaimed by id, verify ok
233
+ (`docs/goals/shared-world-topology/receipts/concurrent-live-rung-2026-06-17.md`). One trial =
234
+ phase-change proof, not scale. The next step is the real downstream sim migration (a
235
+ synthetic-seeded multi-role app in the adopter's domain). Per-action causation,
236
+ cross-sandbox concurrency beyond getHost, and #108 PII/PHI remain out of scope.
237
+ - shared-world (sequential AND concurrent) now also accepts `subject.source: local-tree` alongside
238
+ `clone`: the ONE subject sandbox packs the operator's own working tree instead of cloning,
239
+ reusing `provisionLocalTreeSubject` from the local-tree keystone (0.14.0). Provenance carries
240
+ `archiveSha256` (the pin - one archive per run, so no per-lane unanimity math applies) plus
241
+ host-side commit/dirty when the packed root is a git work tree; local-tree has no repo/publicRepo
242
+ field. The N actor desktops on the concurrent route still drive the harness-minted getHost URL
243
+ exactly as before; only the subject's provisioning + provenance source changed. The multi-origin
244
+ design (`docs/goals/multi-origin-shared-world/design.md`) remains a separate, still-held
245
+ downstream slice. `next patch`
246
+
247
+ Adopter-driven engine features (0.11.0; surfaced by real bespoke-sim migrations):
248
+
249
+ - `execution.desktop.template` — run a lab on a CUSTOM E2B desktop image (name/ID) instead of the
250
+ stock `desktop` template, threaded to `Sandbox.create(template, opts)` via one
251
+ `createDesktopSandbox` seam across every desktop route (cua single+fan-out, sequential +
252
+ concurrent shared-world subject+actors). Absent == the byte-stable stock-template call; recorded
253
+ as `RunBundle.desktopTemplate`. Lets a Node/bun/DB-bearing adopter image run without
254
+ installing the runtime per lane. `done`
255
+ - `humanish observe --run <id>` — serves a run's Observer over `http://127.0.0.1:<port>` (loopback
256
+ only, path-traversal-guarded to the run dir, `/`->`/observer/index.html`) instead of `file://`,
257
+ so browsers/automation can open it and artifact links resolve. `done`
258
+
259
+ Patch hardening (0.11.1):
260
+
261
+ - concurrent shared-world review now fails closed when any actor lane records a failed terminal
262
+ trace; a lane can remain evidence without making the aggregate review green. `done`
263
+ - scripted-browser labs can provision a single cloned synthetic subject, expose it through a
264
+ tokenless sandbox host, and drive deterministic scripted steps while persisting only public-safe
265
+ provenance and host digests. `done`
266
+
267
+ Adopter-driven roster/readback ergonomics (0.12.0):
268
+
269
+ - Lane grouping metadata (`actorType`, `surface`, `caseGroup`) is adapter-owned and projected into
270
+ Observer `laneGroups[]` plus stream labels, so downstream projects can group simulated users
271
+ without teaching Humanish private role names. `done`
272
+ - `actors[0].roster[]` is compact authoring sugar for repeated lane groups. The parser expands it
273
+ into deterministic `lanes[]` (`<group.id>-01`, `<group.id>-02`, ...) before the engine runs, so
274
+ the runtime and run bundle keep one normalized lane shape. `done`
275
+
276
+ Provenance hardening (0.12.1):
277
+
278
+ - Clone-subject provenance now refreshes after successful provisioning phases, so `subject.commit`
279
+ records the served subject HEAD rather than only the initial clone HEAD. This preserves truthful
280
+ run-bundle provenance when an adopter's install/provisioning step checks out the exact revision to
281
+ test. `done`
282
+
283
+ Adapter artifact evidence (0.12.15):
284
+
285
+ - Browser/shared-world adapter hooks may now write product/state proof files under the ignored run
286
+ directory and return namespaced `humanish.adapter-artifact.v1` references. Core validates only the
287
+ generic reference shape and local-path safety, Observer links the artifacts, and `verify` fails
288
+ closed if a referenced file disappears. The payload schema and product nouns stay in the adapter's
289
+ namespace. `done`
290
+
291
+ Evidence hygiene and readback polish (0.12.16):
292
+
293
+ - Browser-backed lanes launch Chromium with shared evidence-hygiene defaults (first-run/update
294
+ background surfaces suppressed, extensions/sync/component update disabled, password/autofill
295
+ profile prompts disabled) so screenshots prefer product pixels over browser chrome. `done`
296
+ - Run-bundle producers now use percent-scale simulation progress consistently: terminal states
297
+ serialize as `100`, and only true in-progress shared-world snapshots serialize partial progress.
298
+ This keeps Observer status pills from rendering completed runs as low-percentage complete states.
299
+ `done`
300
+ - Verify results now separate valid local evidence from public-promotable evidence with
301
+ `shareSafety.status`. Raw full-fidelity screenshot runs remain valid local proof
302
+ (`local_only`), while feedback draft/issue commands require `share_ready` and fail
303
+ closed with structured reasons. `done`
304
+
305
+ Attached CUA live Observer (next patch):
306
+
307
+ - Plain computer-use labs now honor the same attached `onObserverReady` lifecycle as shared-world
308
+ labs: a live CUA run writes an in-progress bundle before actor sessions complete, loopback
309
+ `serveObserver` can hydrate desktop stream iframes while actors are still running, and stream auth
310
+ URLs remain runtime-only through the Observer WeakMap rather than persisted into `run.json` or
311
+ `observer-data.json`. `done`
312
+
313
+ Local working-tree subject + operator observability (0.14.0):
314
+
315
+ - `subject.source: local-tree` packs the lab resolution cwd on the host (git-aware
316
+ enumeration honoring `.gitignore` and including uncommitted work, an always-on
317
+ non-overridable secrets denylist, symlinks stored never dereferenced, one
318
+ enumeration driving both the tar file list and the digest), uploads the
319
+ once-per-run archive into each lane's desktop sandbox, extracts into the subject
320
+ dir, and reuses the clone route's install/build/state/start/probe pipeline
321
+ unchanged. Provenance pins the tree by `archiveSha256` (a dirty tree cannot be
322
+ commit-pinned) plus host-side commit/dirty; `verify` fails closed on a live
323
+ local-tree bundle without a well-formed pin. Live-proven twice with kept
324
+ receipts: a dirty synthetic fixture and this repo packing itself
325
+ (`docs/goals/local-tree-subject/receipts/`). `done`
326
+ - Subject provisioning phase events: started/completed boundaries for
327
+ clone/upload/extract/install/build/serve/readiness/seed-step phases stream to
328
+ stderr by default (injectable via `CuaActorLabHooks.onPhase` /
329
+ `SharedWorldLabHooks.onPhase`) and the completed trail persists into
330
+ `bundle.events`; a single-lane provisioned boot is never silent again. `done`
331
+ - Truthful CLI envelopes at the command boundary: any uncaught action error emits
332
+ one structured `humanish.cli-response.v1` envelope (never a raw stack trace under
333
+ `--json`, never a second stdout document after a flushed envelope), `humanish runs`
334
+ gained a real failure branch, and `doctor` failure now exits 2 like every other
335
+ structured command (behavioral change). `done`
336
+
337
+ ### 6. Lab Manifest Shape
338
+
339
+ Make reusable simulations feel like source artifacts, not hardcoded command
340
+ branches.
341
+
342
+ Minimum acceptance:
343
+
344
+ - `humanish/labs/*.yaml` is the committed lab source convention;
345
+ - `.humanish/labs/*.yaml` and `.humanish/local/labs/*.yaml` are ignored local
346
+ overlays;
347
+ - `humanish watch [lab]`, `humanish lab list`, `humanish lab inspect <lab>`, and
348
+ `humanish lab run <lab>` are supported;
349
+ - `--env-file <path>` loads local values for the current command without
350
+ persisting values into artifacts;
351
+ - maintainer dogfood labs such as `oss` are examples, not the canonical
352
+ consumer taxonomy.
353
+
354
+ ### 7. OSS Lab Health Readback
355
+
356
+ Make the maintainer `oss` lab report nested lane health back into the
357
+ top-level Observer instead of relying on a human watching the desktops.
358
+
359
+ The `0.15.1` safety state above governs this lane. The completed bullets below
360
+ record prior capability and evidence shape; they do not mean the live
361
+ entrypoint is currently enabled.
362
+
363
+ Minimum acceptance:
364
+
365
+ - each lane records setup status; `done`
366
+ - each lane records target app status/URL or blocker; `done`
367
+ - each lane records nested Observer presence; `done`
368
+ - each lane records nested verification status or blocker; `done`
369
+ - each lane records setup-quality filesystem evidence and Observer can inspect
370
+ it; `done`
371
+ - top-level Observer updates lane verdicts from evidence; `done`
372
+ - feedback candidates are derived from setup-quality/actor evidence; `done`
373
+ - Codex app-server actor telemetry is persisted as redacted trace, event, and
374
+ transcript artifacts; `done`
375
+ - each lane receives a meaningful-use score over setup, filesystem, nested
376
+ Humanish proof, actor activity, product surface, and feedback; `done`
377
+ - provider-backed nested app-url proof now drives a bounded two-step
378
+ desktop/mobile browser persona journey in a headed E2B lane; `done`
379
+ - app-specific executable browser steps can now be authored under
380
+ `humanish/scenarios/*.yaml` and are summarized into top-level nested proof
381
+ evidence; `done`
382
+ - repeated public app/tool headed proofs with app-specific manifests have passed
383
+ against two public targets; `done`
384
+ - next gap: richer multi-step product journeys and broader multi-persona
385
+ matrices.
386
+
387
+ ## Non-Goals
388
+
389
+ Do not make these default behavior:
390
+
391
+ - live provider spend;
392
+ - GitHub API mutation;
393
+ - hosted queues, databases, or webhooks;
394
+ - production deploys;
395
+ - real customer/user/patient data;
396
+ - private screenshots or raw transcripts;
397
+ - private upstream artifacts.
398
+
399
+ Maintainer-only tooling can exist later, but it must be opt-in, token-explicit,
400
+ and dry-run-first.
401
+
402
+ ## Drift Alarms
403
+
404
+ Stop and correct course if:
405
+
406
+ - docs start depending on chat memory;
407
+ - Observer gets prettier without stronger evidence;
408
+ - feedback drafts imply product proof from synthetic contract proof;
409
+ - tests pass while generated artifacts are not inspectable;
410
+ - actor setup/use trials produce findings that never become feedback candidates;
411
+ - live labs require private infrastructure to look impressive;
412
+ - package docs link to files that are not shipped;
413
+ - public-safety gates become optional.
414
+
415
+ ## Best Next Work
416
+
417
+ The next most useful engineering slice is repeated agent dogfood against real
418
+ apps and tools, while preserving the public-safety boundary:
419
+
420
+ - public/open-source fixture proof for publishable examples;
421
+ - private maintainer dogfood through the repo-only public-safe packet, which is
422
+ intentionally not part of the npm payload, at
423
+ [`docs/goals/private-repo-agent-dogfood/goal.md`](https://github.com/danielgwilson/humanish/blob/main/docs/goals/private-repo-agent-dogfood/goal.md);
424
+ - then richer provider-backed app-specific browser persona manifests.
425
+
426
+ That sequence keeps the package honest: first prove a new maintainer or agent
427
+ can start, then prove Humanish can observe real product behavior, then use the
428
+ failures to improve the harness.
@@ -0,0 +1,135 @@
1
+ # Invariants and Defaults
2
+
3
+ Humanish's safety and honesty rules come in exactly two strengths. Confusing them is how
4
+ harnesses rot: a route-scoped default gets written down as if it were doctrine, then the next
5
+ legitimate use case looks like a violation and either gets blocked (capability loss) or
6
+ waved through ad hoc (safety loss). This page is the boundary.
7
+
8
+ ## Invariants
9
+
10
+ True on every route, enforced in code, never overridable by config. A feature that cannot
11
+ satisfy these does not ship; a third-party extension that cannot satisfy these does not
12
+ certify (see the conformance suite).
13
+
14
+ 1. **Secret values never reach PUBLISHED evidence.** No key, token, credential value, or
15
+ session-secret may appear in any artifact that leaves the operator's machine — a committed
16
+ file, a shared bundle, a feedback issue. Names of provisioned environment variables are
17
+ evidence; their values never are. Harness-level errors pass through redaction before
18
+ persisting, because SDK error strings can echo secrets. The enforcement point is the
19
+ PUBLISH/VERIFY boundary, not capture: a local run's text artifacts are scrubbed of
20
+ secret-shaped values unconditionally, and raw screenshots (which may render on-screen
21
+ content) are retained locally under gitignored `.humanish/` and never emitted by a publish
22
+ command (feedback/review carry path strings, not pixels). In this repo the CI binary-asset
23
+ scan additionally blocks them from commit; downstream projects do not get that scan — their
24
+ protection is the init-scaffolded `.gitignore` plus their own review. To share a bundle
25
+ as-is, set `policies.redactScreenshots: true` (blurs
26
+ at capture); a redact-on-export step for already-captured raw bundles is planned, not yet
27
+ shipped. (See "the capture-vs-publish rule" below — blurring frames at *capture* was a
28
+ default mistaken for this invariant.)
29
+ - Scope note: the literal scrub of KNOWN provisioned values runs on harness log-tails,
30
+ errors, AND model-authored narration (reasoning/message) before it persists; secret-SHAPED
31
+ values are caught everywhere by pattern redaction. The text artifacts are local
32
+ (gitignored) regardless.
33
+ 2. **Actors only drive harness-minted URLs.** A model with input control (mouse, keyboard,
34
+ terminal) is only ever pointed at a URL the harness itself issued or validated under a
35
+ declared policy (loopback entry, provisioned subject, declared external target). Never an
36
+ arbitrary URL from unvalidated input.
37
+ 3. **Live spend is explicit.** No configuration default, omission, or fallback may cause
38
+ provider or sandbox spend. Spend requires an affirmative declaration (`scenario.mode:
39
+ live`, an env opt-in gate for spend-bearing tests).
40
+ 4. **Evidence verifies fail-closed.** A run bundle that cannot pass verification (schema,
41
+ redaction status, artifact presence, public-safety scan) is a failed run, even when the
42
+ session "worked." The gate applies to the harness's own error reports.
43
+ 5. **Provenance is recorded or its absence is declared.** Every bundle states what the
44
+ subject was (commit, image, fixture, or an explicit "unpinned" marker). Evidence that
45
+ cannot say what it measured cannot support a decision.
46
+ 6. **Claims match mechanism.** A config field that is parsed but not consumed warns; a
47
+ document that overstates behavior is a defect; an evidence artifact never claims a
48
+ stronger evidence class than its actor and scenario can support.
49
+ 7. **Reclamation is by exact created id, never account-wide enumeration.** A route that
50
+ creates a provider resource (an E2B sandbox, for example) tracks the exact id it created and
51
+ reclaims and PROVES cleanup against that id alone (a returned found-and-killed boolean, a
52
+ getInfo-by-id NotFound check). No route ever calls a provider's list-everything endpoint to
53
+ discover or verify its own cleanup, because that endpoint enumerates the whole account/team,
54
+ not just what humanish created. This is what makes a single shared operator key safe: humanish
55
+ only ever reaches a resource it created, never anything else the key's owner is running.
56
+ The one narrow exception is an explicit, maintainer-run orphan sweep (never a default, never
57
+ reachable by a normal lab run) that is itself opt-in gated (an explicit flag or env var) and
58
+ documented as such at its call site.
59
+
60
+ ## Defaults
61
+
62
+ Right most of the time, overridable with declared friction (an explicit config field, an
63
+ env gate, a warning in the run output). Overriding a default is a supported use case;
64
+ silently drifting from one is not.
65
+
66
+ | Default | Why it is the default | Legitimate override |
67
+ |---|---|---|
68
+ | Dry-run | Spend safety (invariant 3 sets the floor; dry-run keeps the floor far away) | `scenario.mode: live` |
69
+ | Per-lane worlds | Isolation, attribution, reproducibility | `subject.topology: shared-world` — N seats against ONE provisioned, mutable plane for scenarios that ARE about interaction between roles (#164). `execution.concurrency: 1` (default) = SEQUENTIAL turns (one sandbox); `> 1` = CONCURRENT (one getHost-exposed subject sandbox + N actor sandboxes driving it at once, synthetic-subject only). The bundle declares the weaker `attributionClass: shared-world` + a verify-enforced `attributionLimits` ceiling (the concurrent set drops `sequential-only` and adds `best-effort-causal-attribution` etc.), so the looser per-role attribution is honest, not hidden. |
70
+ | External key placement | Smallest blast radius: when the keyed process (e.g. a computer-use provider loop) runs outside the sandbox, its key never enters | In-sandbox placement when the keyed process runs inside (an agent harness under test); declared per actor type, with a spend budget |
71
+ | Loopback entry URLs | Public-safety: never drive third-party sites unbidden | `policies.allowPublicTargets` for an owner-declared deployment/preview (a Vercel preview of your own app). Multi-lane public/preview fan-out needs explicit `actors[0].lanes[].target` for every lane, so the adapter-owned topology is declared rather than inferred. Provisioned clone subjects always serve in-sandbox on loopback |
72
+ | Full-fidelity screenshots, local | The common case is watching a sim of your OWN app locally; blur destroys the deliverable. Raw frames live in gitignored `.humanish/` (this repo's CI adds a binary-asset commit scan; downstream projects rely on the scaffolded `.gitignore` and their own review) | `policies.redactScreenshots: true` blurs at capture for share-as-is bundles (a redact-on-export step for raw bundles is planned) |
73
+ | Synthetic, seeded state | Pinned provenance; no real user data in evidence paths | Declared external state, recorded as UNPINNED in provenance |
74
+ | Single lane | Cost + evidence simplicity | Declared fan-out where the backend supports it — `actors[0].count: N` (homogeneous), explicit `actors[0].lanes[]` (differentiated persona/device/instruction), or compact `actors[0].roster[]` groups that normalize into lanes on the computer-use E2B route (per-lane worlds, cap 16; `execution.concurrency` bounds concurrent paid lanes) |
75
+ | Stock `desktop` template | The stock E2B desktop image is right for most subjects; absent `execution.desktop.template` keeps `Sandbox.create(opts)` byte-stable | `execution.desktop.template` names a custom E2B desktop image (any name/id, no allowlist) for a subject needing baked-in runtimes the stock image lacks (e.g. node/bun/a local Postgres) — threaded to `Sandbox.create(template, opts)` on every desktop-creating route and recorded in the bundle as `desktopTemplate` (public-safe) |
76
+ | Desktop default URL opener | Preserve the route/image's historical browser/default opener behavior when unset | `execution.desktop.browser: chrome | chromium | firefox` makes hosted CUA/shared-world browser choice explicit, fail-closed, and recorded as `desktopBrowser` in the run bundle |
77
+
78
+ ## The placement rule (worked example)
79
+
80
+ "No environment variables enter the sandbox" was once stated as a rule. It is not one — it
81
+ is the external-placement *default* as instantiated on the computer-use route, where the
82
+ model's brain runs outside the sandbox. The underlying invariant-level principle is:
83
+
84
+ > **Keys live where the keyed process runs — and nowhere else. Names go in evidence; values
85
+ > never. Blast radius is bounded by key scoping and budgets, not by hoping.**
86
+
87
+ Consequences:
88
+
89
+ - A computer-use provider loop runs outside → forwarding env into its sandbox is rejected.
90
+ - A subject app (a real web app under test) runs inside → its declared env names are
91
+ provisioned in, values never persisted.
92
+ - An agent harness under test runs inside with real keys → that is the point of the lab;
93
+ the keys are presumed exfiltratable by the agent (sandboxing does not protect them — key
94
+ scoping and spend budgets do), and the lane carries a budget/ledger.
95
+
96
+ Placement is registry metadata per actor type, enforced by the engine — not a vibe.
97
+
98
+ Two corollaries:
99
+
100
+ - **Serve commands are author-trusted.** A lab's `serve` steps execute inside the disposable
101
+ sandbox with the declared subject env present — the same trust class as the repo's own
102
+ package.json scripts. Run only lab configs you trust; declare only the env names the
103
+ subject genuinely needs.
104
+ - **Pattern redaction is not enough for provisioned values.** A provisioned value (a database
105
+ password, an arbitrary token) has no detectable "shape," so the harness scrubs every value
106
+ it provisioned by LITERAL match before any log tail or error can persist — pattern-based
107
+ redaction is the second pass, not the only one.
108
+
109
+ ## The capture-vs-publish rule (worked example)
110
+
111
+ "Every screenshot is blurred to a 128px thumbnail" was once enforced at *capture* — the
112
+ loop never retained a usable frame. That destroyed the core deliverable for the common case
113
+ (a developer watching a sim of their OWN app locally) to defend against a leak that can only
114
+ happen at *publish*. The proof it was a default, not an invariant: the same product already
115
+ shipped raw full-resolution frames on the meta route with only a "do not publish" warning +
116
+ the `.humanish/` gitignore + the binary-asset scan. Two routes, opposite policies, identical
117
+ threat. The corrected principle:
118
+
119
+ > **A default's enforcement point belongs at the PUBLISH/VERIFY boundary, never at
120
+ > CAPTURE/RUNTIME — unless capture-time is the only physically possible point.**
121
+
122
+ Consequences:
123
+
124
+ - Screenshots are retained **raw and full-fidelity** by default, in gitignored `.humanish/`.
125
+ `policies.redactScreenshots: true` blurs at capture for a share-as-is bundle; a
126
+ redact-on-export step for already-captured raw bundles is planned (not yet shipped). The
127
+ frame sent to the provider is always raw regardless — the model must see the screen to act.
128
+ - The loopback wall and the synthetic-data stance were the same error: enforcing at
129
+ capture/runtime (rejecting a public target outright; banning realistic local input) what
130
+ belongs at publish (an owner-declared `allowPublicTargets`; redaction at the publish step). A genuine
131
+ capture-time invariant — shell-injection shape checks, id-shape validation — passes the test
132
+ because capture *is* the only point it can hold.
133
+
134
+ Litmus: for any constraint, ask "is this true everywhere, or true by default? — and if a
135
+ default, is it enforced at the boundary where the risk is actually realized?"