humanish 0.0.1 → 0.15.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 (196) hide show
  1. package/AGENTS.md +77 -0
  2. package/CONTRIBUTING.md +39 -0
  3. package/LICENSE +21 -0
  4. package/README.md +435 -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 +356 -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 +327 -0
  32. package/dist/codex-app-server-ui.js.map +1 -0
  33. package/dist/codex-app-server.d.ts +141 -0
  34. package/dist/codex-app-server.js +747 -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 +1092 -0
  50. package/dist/concurrent-shared-world-lab.js.map +1 -0
  51. package/dist/core/git-state.d.ts +31 -0
  52. package/dist/core/git-state.js +142 -0
  53. package/dist/core/git-state.js.map +1 -0
  54. package/dist/core/index.d.ts +4 -0
  55. package/dist/core/index.js +3 -0
  56. package/dist/core/index.js.map +1 -0
  57. package/dist/core/run-primitives.d.ts +66 -0
  58. package/dist/core/run-primitives.js +120 -0
  59. package/dist/core/run-primitives.js.map +1 -0
  60. package/dist/cua-actor-lab.d.ts +620 -0
  61. package/dist/cua-actor-lab.js +2834 -0
  62. package/dist/cua-actor-lab.js.map +1 -0
  63. package/dist/device-presets.d.ts +67 -0
  64. package/dist/device-presets.js +50 -0
  65. package/dist/device-presets.js.map +1 -0
  66. package/dist/e2b-desktop-executor.d.ts +101 -0
  67. package/dist/e2b-desktop-executor.js +309 -0
  68. package/dist/e2b-desktop-executor.js.map +1 -0
  69. package/dist/e2b-desktop-launch.d.ts +144 -0
  70. package/dist/e2b-desktop-launch.js +59 -0
  71. package/dist/e2b-desktop-launch.js.map +1 -0
  72. package/dist/e2b-detached.d.ts +53 -0
  73. package/dist/e2b-detached.js +130 -0
  74. package/dist/e2b-detached.js.map +1 -0
  75. package/dist/e2b-terminal-lab.d.ts +345 -0
  76. package/dist/e2b-terminal-lab.js +1467 -0
  77. package/dist/e2b-terminal-lab.js.map +1 -0
  78. package/dist/env-file.d.ts +14 -0
  79. package/dist/env-file.js +108 -0
  80. package/dist/env-file.js.map +1 -0
  81. package/dist/feedback.d.ts +51 -0
  82. package/dist/feedback.js +313 -0
  83. package/dist/feedback.js.map +1 -0
  84. package/dist/image-evidence.d.ts +2 -0
  85. package/dist/image-evidence.js +33 -0
  86. package/dist/image-evidence.js.map +1 -0
  87. package/dist/index.d.ts +63 -0
  88. package/dist/index.js +33 -0
  89. package/dist/index.js.map +1 -0
  90. package/dist/init-templates.d.ts +12 -0
  91. package/dist/init-templates.js +369 -0
  92. package/dist/init-templates.js.map +1 -0
  93. package/dist/init.d.ts +26 -0
  94. package/dist/init.js +343 -0
  95. package/dist/init.js.map +1 -0
  96. package/dist/lab-app-runner.d.ts +78 -0
  97. package/dist/lab-app-runner.js +403 -0
  98. package/dist/lab-app-runner.js.map +1 -0
  99. package/dist/lab-config.d.ts +578 -0
  100. package/dist/lab-config.js +1751 -0
  101. package/dist/lab-config.js.map +1 -0
  102. package/dist/lab-engine.d.ts +77 -0
  103. package/dist/lab-engine.js +216 -0
  104. package/dist/lab-engine.js.map +1 -0
  105. package/dist/lab-preflight.d.ts +67 -0
  106. package/dist/lab-preflight.js +385 -0
  107. package/dist/lab-preflight.js.map +1 -0
  108. package/dist/labs.d.ts +53 -0
  109. package/dist/labs.js +176 -0
  110. package/dist/labs.js.map +1 -0
  111. package/dist/observer-assets.d.ts +2 -0
  112. package/dist/observer-assets.js +2630 -0
  113. package/dist/observer-assets.js.map +1 -0
  114. package/dist/observer-data.d.ts +63 -0
  115. package/dist/observer-data.js +145 -0
  116. package/dist/observer-data.js.map +1 -0
  117. package/dist/observer-static.d.ts +39 -0
  118. package/dist/observer-static.js +192 -0
  119. package/dist/observer-static.js.map +1 -0
  120. package/dist/observer.d.ts +46 -0
  121. package/dist/observer.js +353 -0
  122. package/dist/observer.js.map +1 -0
  123. package/dist/openai-responses-cu.d.ts +113 -0
  124. package/dist/openai-responses-cu.js +531 -0
  125. package/dist/openai-responses-cu.js.map +1 -0
  126. package/dist/oss-lab.d.ts +52 -0
  127. package/dist/oss-lab.js +299 -0
  128. package/dist/oss-lab.js.map +1 -0
  129. package/dist/oss-meta-lab-scoring.d.ts +15 -0
  130. package/dist/oss-meta-lab-scoring.js +145 -0
  131. package/dist/oss-meta-lab-scoring.js.map +1 -0
  132. package/dist/oss-meta-lab.d.ts +279 -0
  133. package/dist/oss-meta-lab.js +4889 -0
  134. package/dist/oss-meta-lab.js.map +1 -0
  135. package/dist/oss-remote-telemetry.d.ts +77 -0
  136. package/dist/oss-remote-telemetry.js +403 -0
  137. package/dist/oss-remote-telemetry.js.map +1 -0
  138. package/dist/persona.d.ts +35 -0
  139. package/dist/persona.js +133 -0
  140. package/dist/persona.js.map +1 -0
  141. package/dist/pi-agent-core.d.ts +77 -0
  142. package/dist/pi-agent-core.js +203 -0
  143. package/dist/pi-agent-core.js.map +1 -0
  144. package/dist/program.d.ts +54 -0
  145. package/dist/program.js +2347 -0
  146. package/dist/program.js.map +1 -0
  147. package/dist/redaction.d.ts +90 -0
  148. package/dist/redaction.js +292 -0
  149. package/dist/redaction.js.map +1 -0
  150. package/dist/run.d.ts +784 -0
  151. package/dist/run.js +4555 -0
  152. package/dist/run.js.map +1 -0
  153. package/dist/scripted-browser-actor.d.ts +294 -0
  154. package/dist/scripted-browser-actor.js +1286 -0
  155. package/dist/scripted-browser-actor.js.map +1 -0
  156. package/dist/scripted-browser-lab.d.ts +107 -0
  157. package/dist/scripted-browser-lab.js +738 -0
  158. package/dist/scripted-browser-lab.js.map +1 -0
  159. package/dist/shared-world-lab.d.ts +208 -0
  160. package/dist/shared-world-lab.js +1048 -0
  161. package/dist/shared-world-lab.js.map +1 -0
  162. package/dist/source-archive.d.ts +82 -0
  163. package/dist/source-archive.js +365 -0
  164. package/dist/source-archive.js.map +1 -0
  165. package/dist/stop-conditions.d.ts +26 -0
  166. package/dist/stop-conditions.js +66 -0
  167. package/dist/stop-conditions.js.map +1 -0
  168. package/dist/terminal-agent-actor.d.ts +36 -0
  169. package/dist/terminal-agent-actor.js +23 -0
  170. package/dist/terminal-agent-actor.js.map +1 -0
  171. package/docs/architecture/actor-contract.md +431 -0
  172. package/docs/architecture/github-feedback-loop.md +189 -0
  173. package/docs/architecture/local-codex-tui-actor.md +213 -0
  174. package/docs/architecture/observer.md +118 -0
  175. package/docs/architecture/oss-lab-poc.md +242 -0
  176. package/docs/architecture/project-layout.md +166 -0
  177. package/docs/architecture/state-driven-executor.md +203 -0
  178. package/docs/architecture/terminal-product-lane.md +148 -0
  179. package/docs/contracts/adapter-fixtures.md +80 -0
  180. package/docs/contracts/core.md +71 -0
  181. package/docs/contracts/feedback.md +145 -0
  182. package/docs/contracts/policy.md +305 -0
  183. package/docs/contracts/run-bundle.md +358 -0
  184. package/docs/contracts/schemas.md +984 -0
  185. package/docs/goals/current.md +409 -0
  186. package/docs/principles/invariants-and-defaults.md +135 -0
  187. package/docs/principles/self-driving-harness.md +129 -0
  188. package/docs/product/open-source-install-experience.md +229 -0
  189. package/docs/ramp/README.md +200 -0
  190. package/docs/release/open-source-readiness.md +208 -0
  191. package/docs/release/public-readiness-standard.md +205 -0
  192. package/docs/roadmap/world-class-open-source-v0.md +311 -0
  193. package/package.json +102 -8
  194. package/skills/humanish/SKILL.md +244 -0
  195. package/skills/humanish/agents/openai.yaml +7 -0
  196. package/index.js +0 -1
@@ -0,0 +1,409 @@
1
+ # Current Goals
2
+
3
+ Status date: 2026-07-08 (rev 13)
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
+ ## Definition Of Awesome
20
+
21
+ A world-class Humanish run should eventually provide:
22
+
23
+ - one human-friendly command that starts simulations and opens Observer;
24
+ - multiple synthetic personas with different goals, patience, and skill levels;
25
+ - UI, CLI, TUI, and code-agent lanes in one mission-control Observer;
26
+ - real evidence: screenshots, terminal transcripts, lifecycle events, traces,
27
+ filesystem setup-quality snapshots, artifacts, and verifier output;
28
+ - clear pass, fail, blocked, and gap states;
29
+ - public-safe feedback issue drafts that do not mutate GitHub by default;
30
+ - first-class `.yaml` lab manifests for reusable simulation runs;
31
+ - adapter contracts that let projects customize behavior without forking core;
32
+ - release gates that prevent PII, PHI, secrets, private artifacts, and stale
33
+ internal residue from reaching the public repo or package.
34
+
35
+ ## Current Objective
36
+
37
+ Make the public package and repo credible enough that an external maintainer can:
38
+
39
+ 1. install the skill;
40
+ 2. install `humanish`;
41
+ 3. run `humanish init`;
42
+ 4. run `humanish watch`;
43
+ 5. run `humanish watch first-run` or another lab manifest;
44
+ 6. inspect Observer evidence;
45
+ 7. verify the bundle;
46
+ 8. produce a public-safe feedback draft;
47
+ 9. understand the next live-adapter path without reading chat history.
48
+
49
+ ## Near-Term Goals
50
+
51
+ ### 1. Public Readiness
52
+
53
+ Keep the repository clean and public-safe.
54
+
55
+ Acceptance:
56
+
57
+ ```bash
58
+ pnpm release:check
59
+ git diff --check
60
+ ```
61
+
62
+ Fresh clone release checks should pass before public visibility changes.
63
+
64
+ ### 2. Future-Agent Ramp
65
+
66
+ Maintain a durable ramp that tells future contributors and coding agents where
67
+ to start, what exists, what remains, and what proof is required.
68
+
69
+ Acceptance:
70
+
71
+ - [`docs/ramp/README.md`](../ramp/README.md) stays current;
72
+ - this page stays current;
73
+ - README links both;
74
+ - release package includes both docs directories.
75
+
76
+ ### 3. Fresh-Agent Install Proof
77
+
78
+ Prove the skill and package setup flow from a disposable target app with no chat
79
+ context.
80
+
81
+ Target proof:
82
+
83
+ ```bash
84
+ npm i -D humanish
85
+ npx humanish init --yes
86
+ npx humanish watch --json --no-open
87
+ npx humanish verify --run latest --json
88
+ npx humanish feedback issue --run latest --repo owner/repo --format markdown
89
+ ```
90
+
91
+ The proof target must use synthetic personas and no real user data.
92
+
93
+ ### 4. Live Browser Adapter
94
+
95
+ Graduate from synthetic UI lanes to a real browser journey against a local app.
96
+
97
+ Minimum acceptance:
98
+
99
+ - local app target detection;
100
+ - browser launch;
101
+ - route/state capture;
102
+ - screenshot artifact;
103
+ - run bundle references screenshot evidence;
104
+ - Observer renders the screenshot;
105
+ - `verify` fails closed if required evidence is missing;
106
+ - bounded desktop/mobile two-step browser persona proof with per-step traces and
107
+ screenshots. `done`
108
+ - LLM-driven browser lane: the registered `openai-computer-use` actor dispatches
109
+ from a lab config (`subject.source: app-url`, loopback entry only) into a hosted
110
+ E2B desktop, fills the provider-neutral `stream.actor` trace seam, and persists
111
+ a verified redacted bundle (0.3.0 registered the actor; 0.4.0 made
112
+ `actors[].type` a real dispatch key). `done`
113
+ - Clone subject provider: `subject.source: clone` + `serve` clones a repo INTO the
114
+ sandbox, installs/builds/starts it from config, probes readiness, and records
115
+ provenance (repo, commit, env names) in the bundle — config-only computer-use
116
+ labs against real apps (0.5.0; see `docs/goals/proof-roadmap/goal.md` —
117
+ repo-only, not shipped in the npm package — and
118
+ `docs/principles/invariants-and-defaults.md`, which ships in the package).
119
+ `done`
120
+ - De-paranoia (0.6.0): the redaction redesign + demoted defaults. Screenshots are
121
+ full-fidelity by default (redaction binds the publish boundary, not capture —
122
+ `policies.redactScreenshots` opts back in); `policies.allowPublicTargets` lets an
123
+ owner drive a declared deployment/preview; `subject.clone.keep` is honored on
124
+ failure for debugging; `serve.installTimeoutMs`/`buildTimeoutMs` are configurable
125
+ for monorepo-scale builds. Doctrine updated with the capture-vs-publish rule. This
126
+ re-sequences the proof roadmap: a redaction redesign and an overridable
127
+ public-target policy are prerequisites for any decision-grade depth evidence, so
128
+ they land BEFORE the consumer-web-app / agent-skill depth phases. `done`
129
+ - Device presets (0.6.1): viewport/device is a real dimension, with LITERAL values copied
130
+ from the in-house sims (mobile 414×896 … wide 1920×1080; default `desktop` 1440×950) —
131
+ not guessed. `execution.desktop.device` picks the per-run viewport; the guessed 1280×800
132
+ is gone. Honest fidelity: on the E2B route only width/height render (real mobile *layout*)
133
+ + the model is told its device, matching the sims' organic lanes; true touch/DPR/UA needs
134
+ the CDP actor. Per-*persona* device (N×devices) rides fan-out. `done`
135
+
136
+ ### 5. Live Terminal And Codex Lanes
137
+
138
+ Make local PTY and Codex-style lanes reliable enough that Observer can show
139
+ running, passed, failed, blocked, and timed-out states without human inference.
140
+
141
+ Minimum acceptance:
142
+
143
+ - sanitized transcript persistence;
144
+ - explicit completion reason;
145
+ - verifier checks redaction status;
146
+ - Observer polling reflects lane completion;
147
+ - no raw private transcript or credential values.
148
+
149
+ Terminal-product real-agent lane (0.8.0; depth-axis layer 6, so an adopter can delete a
150
+ bespoke real-agent sim for humanish + a thin adapter — see
151
+ `docs/goals/terminal-product-lane/goal.md`):
152
+
153
+ - `subject.source: terminal-product` + `execution.target: e2b-terminal` + the registered
154
+ `codex-exec` terminal actor route a config to a real Codex agent studying a product from
155
+ public surfaces inside an E2B shell. `done`
156
+ - The credential-placement inversion is enforced by construction AND by verifier: the runtime
157
+ key is injected ONLY command-scoped into the `codex` invocation, never sandbox-global; a
158
+ deny-by-default allowlist excludes GitHub/payment/deploy/db creds; metadata is a positive
159
+ allowlist; stdin is disabled with an always-present interventions ledger; cleanup is proven
160
+ or the run fails closed. `done`
161
+ - Cost/no-spend ledger with the null-vs-known-zero-vs-absent discipline (unknowns are `null`,
162
+ never guessed); the no-spend proof is DERIVED from the ledger, never asserted; `maxUsd`/
163
+ `maxJobs`/`maxMinutes` caps enforced fail-closed. `done`
164
+ - Product-adapter extension seam: exported contract types + a scorer/feedback DI hook +
165
+ adapter-namespaced product nouns, so an adopter attaches scoring/feedback as a thin
166
+ in-repo extension without forking core. `done`
167
+ - Cleanup is proven BY EXACT CREATED ID: `Sandbox.kill(id)`, confirmed further by
168
+ `Sandbox.getInfo(id)` where the SDK exposes it, and humanish never calls `Sandbox.list`. A live
169
+ rung never needs a dedicated or isolated E2B key; the SAME shared operator key used everywhere
170
+ else in this repo is safe, because humanish only ever reaches a sandbox it created (see
171
+ "The placement rule" corollary in `docs/principles/invariants-and-defaults.md`).
172
+ - LIVE-PROVEN (2026-07-09): a real Codex agent, bootstrapped in a stock E2B shell (Node
173
+ installed in-sandbox, run via `npx -y @openai/codex@latest exec`), studied a public
174
+ agent-CLI product from its declared public surfaces and ran the product's free zero-spend
175
+ guide within `$0` no-spend caps; verdict nonce-verified, cleanup proven BY EXACT ID
176
+ (`getInfo(id)` SandboxNotFoundError, never `Sandbox.list`), verify 15/15, share_ready
177
+ (`docs/goals/terminal-product-lane/receipts/terminal-live-rung-2026-07-09.md`). This closes
178
+ the #159 live-receipt gap. Optional follow-up: a custom image with the agent runtime baked in
179
+ to drop the per-run npx bootstrap. Duplex-PTY/xterm replay is a deferred SLICE 5.
180
+
181
+ Multi-lane fan-out for the computer-use lab (0.9.0; proof-roadmap layer 2, the prerequisite
182
+ for multi-actor shared-state work — #163, see `docs/goals/multi-lane-fanout/goal.md`):
183
+
184
+ - `actors[0].lanes[]` (differentiated roster: per-lane persona/device/starting-surface) XOR
185
+ `actors[0].count` (homogeneous) fan out N independent E2B desktops in ONE run bundle;
186
+ `per-lane worlds` is the only topology this slice (shared-world is #164). `done`
187
+ - `execution.concurrency` bounds in-flight paid desktops (default min(N,3); env may only
188
+ lower it); a pre-flight spend/lane plan prints before any sandbox/provider call and at $0
189
+ in dry-run; per-lane teardown reclaims ONLY each lane's own sandbox by id (never
190
+ account-wide). `done`
191
+ - Proven deterministically (fake substrate: bounded concurrency, by-id teardown, fail-fast,
192
+ hollow-lane caught) AND with a kept live rung (2 lanes, two distinct desktops, both
193
+ reclaimed by id, bundle verifies — `docs/goals/multi-lane-fanout/receipts/`). `done`
194
+ - Deferred: seed-fork provisioning (PR-2), in-process-route fan-out, shared-world topology
195
+ (#164).
196
+
197
+ Shared-world topology — multi-actor against ONE shared mutable service (0.10.0; proof-roadmap
198
+ layer 7; #164; `docs/goals/shared-world-topology/`). The north-star sim leverage: MANY personas,
199
+ ONE shared world.
200
+
201
+ - Sequential (`topology: shared-world`, concurrency 1): one sandbox, N role seats take turns
202
+ against the shared DB; a checkpoint timeline proves role B acted on a world already containing
203
+ role A's mutation. `done`
204
+ - **Concurrent (`topology: shared-world` + `concurrency > 1`): one subject sandbox served +
205
+ `getHost`-exposed, N actor desktop sandboxes drive that one URL SIMULTANEOUSLY** (reuses fan-out
206
+ orchestration; all N+1 reclaimed by id). Honest attribution under concurrency: per-persona
207
+ outcomes + harness-clocked `laneWindows` proving real overlap + a `stateSeries` of the shared
208
+ world under load; causation is structurally inexpressible (independent series, no
209
+ per-delta→actor field). `done`
210
+ - A new `attributionClass: isolated | shared-world` honesty axis + verify FAIL-CLOSED on the
211
+ required/forbidden `attributionLimits` sets + a concurrency-on-pass gate (a passed concurrent
212
+ run must show real overlap AND a state delta coincident with it). `getHost` URLs are
213
+ internet-reachable → the route is gated (verify) to synthetic+seeded subjects; the raw URL is
214
+ digest-only in evidence. `done`
215
+ - **LIVE-PROVEN (0.10.1):** a kept live receipt ran 3 personas concurrently against ONE
216
+ getHost-exposed synthetic plane — all 3 passed, all 3 lane-windows overlapped on the real clock,
217
+ the shared stateSeries evolved under load, N+1=4 sandboxes reclaimed by id, verify ok
218
+ (`docs/goals/shared-world-topology/receipts/concurrent-live-rung-2026-06-17.md`). One trial =
219
+ phase-change proof, not scale. The next step is the real downstream sim migration (a
220
+ synthetic-seeded multi-role app in the adopter's domain). Per-action causation,
221
+ cross-sandbox concurrency beyond getHost, and #108 PII/PHI remain out of scope.
222
+ - shared-world (sequential AND concurrent) now also accepts `subject.source: local-tree` alongside
223
+ `clone`: the ONE subject sandbox packs the operator's own working tree instead of cloning,
224
+ reusing `provisionLocalTreeSubject` from the local-tree keystone (0.14.0). Provenance carries
225
+ `archiveSha256` (the pin - one archive per run, so no per-lane unanimity math applies) plus
226
+ host-side commit/dirty when the packed root is a git work tree; local-tree has no repo/publicRepo
227
+ field. The N actor desktops on the concurrent route still drive the harness-minted getHost URL
228
+ exactly as before; only the subject's provisioning + provenance source changed. The multi-origin
229
+ design (`docs/goals/multi-origin-shared-world/design.md`) remains a separate, still-held
230
+ downstream slice. `next patch`
231
+
232
+ Adopter-driven engine features (0.11.0; surfaced by real bespoke-sim migrations):
233
+
234
+ - `execution.desktop.template` — run a lab on a CUSTOM E2B desktop image (name/ID) instead of the
235
+ stock `desktop` template, threaded to `Sandbox.create(template, opts)` via one
236
+ `createDesktopSandbox` seam across every desktop route (cua single+fan-out, sequential +
237
+ concurrent shared-world subject+actors). Absent == the byte-stable stock-template call; recorded
238
+ as `RunBundle.desktopTemplate`. Lets a Node/bun/DB-bearing adopter image run without
239
+ installing the runtime per lane. `done`
240
+ - `humanish observe --run <id>` — serves a run's Observer over `http://127.0.0.1:<port>` (loopback
241
+ only, path-traversal-guarded to the run dir, `/`->`/observer/index.html`) instead of `file://`,
242
+ so browsers/automation can open it and artifact links resolve. `done`
243
+
244
+ Patch hardening (0.11.1):
245
+
246
+ - concurrent shared-world review now fails closed when any actor lane records a failed terminal
247
+ trace; a lane can remain evidence without making the aggregate review green. `done`
248
+ - scripted-browser labs can provision a single cloned synthetic subject, expose it through a
249
+ tokenless sandbox host, and drive deterministic scripted steps while persisting only public-safe
250
+ provenance and host digests. `done`
251
+
252
+ Adopter-driven roster/readback ergonomics (0.12.0):
253
+
254
+ - Lane grouping metadata (`actorType`, `surface`, `caseGroup`) is adapter-owned and projected into
255
+ Observer `laneGroups[]` plus stream labels, so downstream projects can group simulated users
256
+ without teaching Humanish private role names. `done`
257
+ - `actors[0].roster[]` is compact authoring sugar for repeated lane groups. The parser expands it
258
+ into deterministic `lanes[]` (`<group.id>-01`, `<group.id>-02`, ...) before the engine runs, so
259
+ the runtime and run bundle keep one normalized lane shape. `done`
260
+
261
+ Provenance hardening (0.12.1):
262
+
263
+ - Clone-subject provenance now refreshes after successful provisioning phases, so `subject.commit`
264
+ records the served subject HEAD rather than only the initial clone HEAD. This preserves truthful
265
+ run-bundle provenance when an adopter's install/provisioning step checks out the exact revision to
266
+ test. `done`
267
+
268
+ Adapter artifact evidence (0.12.15):
269
+
270
+ - Browser/shared-world adapter hooks may now write product/state proof files under the ignored run
271
+ directory and return namespaced `humanish.adapter-artifact.v1` references. Core validates only the
272
+ generic reference shape and local-path safety, Observer links the artifacts, and `verify` fails
273
+ closed if a referenced file disappears. The payload schema and product nouns stay in the adapter's
274
+ namespace. `done`
275
+
276
+ Evidence hygiene and readback polish (0.12.16):
277
+
278
+ - Browser-backed lanes launch Chromium with shared evidence-hygiene defaults (first-run/update
279
+ background surfaces suppressed, extensions/sync/component update disabled, password/autofill
280
+ profile prompts disabled) so screenshots prefer product pixels over browser chrome. `done`
281
+ - Run-bundle producers now use percent-scale simulation progress consistently: terminal states
282
+ serialize as `100`, and only true in-progress shared-world snapshots serialize partial progress.
283
+ This keeps Observer status pills from rendering completed runs as low-percentage complete states.
284
+ `done`
285
+ - Verify results now separate valid local evidence from public-promotable evidence with
286
+ `shareSafety.status`. Raw full-fidelity screenshot runs remain valid local proof
287
+ (`local_only`), while feedback draft/issue commands require `share_ready` and fail
288
+ closed with structured reasons. `done`
289
+
290
+ Attached CUA live Observer (next patch):
291
+
292
+ - Plain computer-use labs now honor the same attached `onObserverReady` lifecycle as shared-world
293
+ labs: a live CUA run writes an in-progress bundle before actor sessions complete, loopback
294
+ `serveObserver` can hydrate desktop stream iframes while actors are still running, and stream auth
295
+ URLs remain runtime-only through the Observer WeakMap rather than persisted into `run.json` or
296
+ `observer-data.json`. `done`
297
+
298
+ Local working-tree subject + operator observability (0.14.0):
299
+
300
+ - `subject.source: local-tree` packs the lab resolution cwd on the host (git-aware
301
+ enumeration honoring `.gitignore` and including uncommitted work, an always-on
302
+ non-overridable secrets denylist, symlinks stored never dereferenced, one
303
+ enumeration driving both the tar file list and the digest), uploads the
304
+ once-per-run archive into each lane's desktop sandbox, extracts into the subject
305
+ dir, and reuses the clone route's install/build/state/start/probe pipeline
306
+ unchanged. Provenance pins the tree by `archiveSha256` (a dirty tree cannot be
307
+ commit-pinned) plus host-side commit/dirty; `verify` fails closed on a live
308
+ local-tree bundle without a well-formed pin. Live-proven twice with kept
309
+ receipts: a dirty synthetic fixture and this repo packing itself
310
+ (`docs/goals/local-tree-subject/receipts/`). `done`
311
+ - Subject provisioning phase events: started/completed boundaries for
312
+ clone/upload/extract/install/build/serve/readiness/seed-step phases stream to
313
+ stderr by default (injectable via `CuaActorLabHooks.onPhase` /
314
+ `SharedWorldLabHooks.onPhase`) and the completed trail persists into
315
+ `bundle.events`; a single-lane provisioned boot is never silent again. `done`
316
+ - Truthful CLI envelopes at the command boundary: any uncaught action error emits
317
+ one structured `humanish.cli-response.v1` envelope (never a raw stack trace under
318
+ `--json`, never a second stdout document after a flushed envelope), `humanish runs`
319
+ gained a real failure branch, and `doctor` failure now exits 2 like every other
320
+ structured command (behavioral change). `done`
321
+
322
+ ### 6. Lab Manifest Shape
323
+
324
+ Make reusable simulations feel like source artifacts, not hardcoded command
325
+ branches.
326
+
327
+ Minimum acceptance:
328
+
329
+ - `humanish/labs/*.yaml` is the committed lab source convention;
330
+ - `.humanish/labs/*.yaml` and `.humanish/local/labs/*.yaml` are ignored local
331
+ overlays;
332
+ - `humanish watch [lab]`, `humanish lab list`, `humanish lab inspect <lab>`, and
333
+ `humanish lab run <lab>` are supported;
334
+ - `--env-file <path>` loads local values for the current command without
335
+ persisting values into artifacts;
336
+ - maintainer dogfood labs such as `oss` are examples, not the canonical
337
+ consumer taxonomy.
338
+
339
+ ### 7. OSS Lab Health Readback
340
+
341
+ Make the maintainer `oss` lab report nested lane health back into the
342
+ top-level Observer instead of relying on a human watching the desktops.
343
+
344
+ Minimum acceptance:
345
+
346
+ - each lane records setup status; `done`
347
+ - each lane records target app status/URL or blocker; `done`
348
+ - each lane records nested Observer presence; `done`
349
+ - each lane records nested verification status or blocker; `done`
350
+ - each lane records setup-quality filesystem evidence and Observer can inspect
351
+ it; `done`
352
+ - top-level Observer updates lane verdicts from evidence; `done`
353
+ - feedback candidates are derived from setup-quality/actor evidence; `done`
354
+ - Codex app-server actor telemetry is persisted as redacted trace, event, and
355
+ transcript artifacts; `done`
356
+ - each lane receives a meaningful-use score over setup, filesystem, nested
357
+ Humanish proof, actor activity, product surface, and feedback; `done`
358
+ - provider-backed nested app-url proof now drives a bounded two-step
359
+ desktop/mobile browser persona journey in a headed E2B lane; `done`
360
+ - app-specific executable browser steps can now be authored under
361
+ `humanish/scenarios/*.yaml` and are summarized into top-level nested proof
362
+ evidence; `done`
363
+ - repeated public app/tool headed proofs with app-specific manifests have passed
364
+ against two public targets; `done`
365
+ - next gap: richer multi-step product journeys and broader multi-persona
366
+ matrices.
367
+
368
+ ## Non-Goals
369
+
370
+ Do not make these default behavior:
371
+
372
+ - live provider spend;
373
+ - GitHub API mutation;
374
+ - hosted queues, databases, or webhooks;
375
+ - production deploys;
376
+ - real customer/user/patient data;
377
+ - private screenshots or raw transcripts;
378
+ - private upstream artifacts.
379
+
380
+ Maintainer-only tooling can exist later, but it must be opt-in, token-explicit,
381
+ and dry-run-first.
382
+
383
+ ## Drift Alarms
384
+
385
+ Stop and correct course if:
386
+
387
+ - docs start depending on chat memory;
388
+ - Observer gets prettier without stronger evidence;
389
+ - feedback drafts imply product proof from synthetic contract proof;
390
+ - tests pass while generated artifacts are not inspectable;
391
+ - actor setup/use trials produce findings that never become feedback candidates;
392
+ - live labs require private infrastructure to look impressive;
393
+ - package docs link to files that are not shipped;
394
+ - public-safety gates become optional.
395
+
396
+ ## Best Next Work
397
+
398
+ The next most useful engineering slice is repeated agent dogfood against real
399
+ apps and tools, while preserving the public-safety boundary:
400
+
401
+ - public/open-source fixture proof for publishable examples;
402
+ - private maintainer dogfood through the repo-only public-safe packet, which is
403
+ intentionally not part of the npm payload, at
404
+ [`docs/goals/private-repo-agent-dogfood/goal.md`](https://github.com/danielgwilson/humanish/blob/main/docs/goals/private-repo-agent-dogfood/goal.md);
405
+ - then richer provider-backed app-specific browser persona manifests.
406
+
407
+ That sequence keeps the package honest: first prove a new maintainer or agent
408
+ can start, then prove Humanish can observe real product behavior, then use the
409
+ 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?"