humanish 0.34.0 → 0.35.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.
- package/AGENTS.md +8 -0
- package/README.md +11 -7
- package/dist/concurrent-shared-world-lab.d.ts +3 -0
- package/dist/concurrent-shared-world-lab.js +33 -5
- package/dist/concurrent-shared-world-lab.js.map +1 -1
- package/dist/cua-actor-lab.d.ts +11 -3
- package/dist/cua-actor-lab.js +38 -17
- package/dist/cua-actor-lab.js.map +1 -1
- package/dist/init-templates.js +1 -1
- package/dist/lab-config.d.ts +18 -6
- package/dist/lab-config.js +84 -2
- package/dist/lab-config.js.map +1 -1
- package/docs/contracts/schemas.md +37 -15
- package/docs/goals/current.md +1 -1
- package/docs/principles/invariants-and-defaults.md +1 -1
- package/docs/ramp/README.md +5 -4
- package/package.json +1 -1
- package/skills/humanish/SKILL.md +53 -9
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Date: 2026-06-02 (current-state note updated 2026-07-14)
|
|
4
4
|
|
|
5
5
|
Status: reference map for the major contracts shipped through source version
|
|
6
|
-
`0.
|
|
6
|
+
`0.35.0`; it is not an exhaustive inventory of command/result envelopes. Exported types,
|
|
7
7
|
schema constants, parsers, and validators in `src/` are authoritative. Rows
|
|
8
8
|
marked "reserved" name layering intent only — no code emits or validates them
|
|
9
9
|
yet. Do not emit a reserved schema.
|
|
@@ -160,10 +160,19 @@ A lab is a composition over code primitives, not a hardcoded kind:
|
|
|
160
160
|
deterministic `lanes[]` before the engine runs (`viewer-01`, `viewer-02`,
|
|
161
161
|
...), so the runtime and run bundle keep one normalized lane shape. `roster`
|
|
162
162
|
is XOR with explicit `lanes`, homogeneous `count`, and `laneFocus`;
|
|
163
|
-
- `execution.concurrency` (computer-use E2B
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
163
|
+
- `execution.concurrency` (computer-use E2B routes, including shared-world): a
|
|
164
|
+
CAP on lanes in flight at once. When omitted, every declared seat runs
|
|
165
|
+
simultaneously (the parser fills `concurrency = laneCount` for multi-seat
|
|
166
|
+
labs) — total sessions and spend are identical either way; only wall-clock
|
|
167
|
+
and simultaneity differ. Declaring a value below the seat count runs seats in
|
|
168
|
+
waves and emits a warning saying so, because a green waved run is otherwise
|
|
169
|
+
indistinguishable from the all-live run the author meant. On shared-world
|
|
170
|
+
labs this field is also the sequential/concurrent selector: `concurrency: 1`
|
|
171
|
+
is the sequential turn-taking PoC; anything higher (including the filled
|
|
172
|
+
default) is the concurrent substrate. The env override
|
|
173
|
+
`HUMANISH_CUA_MAX_CONCURRENCY` may only LOWER the effective bound, never
|
|
174
|
+
raise concurrent paid desktops (invariant 3), and a lowering is recorded on
|
|
175
|
+
the plan (`envLoweredConcurrencyFrom`). Inert (warned) on other routes.
|
|
167
176
|
`execution.timeoutMs` is the PER-LANE session budget on this route (semantics
|
|
168
177
|
change: it was the single-session budget pre-fan-out); there is no run-level
|
|
169
178
|
wall clock. `policies.allowPublicTargets` cannot combine with N>1 against one
|
|
@@ -243,22 +252,35 @@ A lab is a composition over code primitives, not a hardcoded kind:
|
|
|
243
252
|
only command-scoped). The scripted-browser route is loopback-only and rejects
|
|
244
253
|
`redactScreenshots: true` (blur unimplemented there) and
|
|
245
254
|
`allowPublicTargets: true` fail-closed rather than ignoring them.
|
|
246
|
-
- `comms` (clone/local-tree
|
|
255
|
+
- `comms` (#297; hosted on the clone/local-tree computer-use lanes and the
|
|
256
|
+
CONCURRENT shared-world getHost plane — warned inert everywhere else,
|
|
257
|
+
including app-url/operator-provided subjects and the sequential
|
|
258
|
+
`concurrency: 1` shared world, neither of which has a catch to host): off-app
|
|
247
259
|
email/SMS the app itself SENDS, made a persona-driven testable surface.
|
|
248
260
|
`comms.email` = `{ kind: fake, injectEnv, port?, recipients?, linkOrigin? }`.
|
|
249
261
|
`injectEnv` is the ADOPTER-NAMED env var the app reads for its email-API base
|
|
250
262
|
URL (e.g. `RESEND_API_URL`); the harness sets it to an in-sandbox catch (so it
|
|
251
263
|
is NOT declared in `subject.env`) that captures the app's sends without touching
|
|
252
|
-
the internet
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
264
|
+
the internet — verify the app actually reads that variable, because a run whose
|
|
265
|
+
catch captured zero sends warns at teardown for exactly that. `kind` must be
|
|
266
|
+
`fake` (`real`/provider-backed is rejected until implemented); `port` ≤ 65534
|
|
267
|
+
(the catch reserves `port+1` for the read-only inbox listener the shared-world
|
|
268
|
+
route getHost-exposes). `recipients[]` = `{ lane, address? }`: OMIT the list
|
|
269
|
+
and the parser fills one deterministic address per lane
|
|
270
|
+
(`<laneId>@example.test`) so every seat can do email (#351). When declared, a
|
|
271
|
+
`lane` must be one of the lab's real lane ids (roster ids, or the generated
|
|
272
|
+
`lane-01..lane-NN` under `count`) — an unknown lane is a hard parse error
|
|
273
|
+
listing them, zero addressed lanes is a hard error, partial coverage warns
|
|
274
|
+
with the uncovered lanes. Each addressed lane's actor prompt is extended with
|
|
275
|
+
the full handoff: its address ("enter exactly that"), the inbox URL, and the
|
|
276
|
+
wait steering ("waiting for an email is normal, not a blocker"). `linkOrigin`
|
|
277
|
+
is an optional operator-declared origin the app bakes into links when it
|
|
278
|
+
differs from the serve origin; the harness rewrites captured links through it
|
|
279
|
+
so a clicked link resolves to a reachable host. Captured mail is drained into a
|
|
259
280
|
digest-only `humanish.comms-thread.v1` artifact (from/to/subject/link DIGESTS +
|
|
260
|
-
an OTP COUNT — no raw address/link/code persists)
|
|
261
|
-
|
|
281
|
+
an OTP COUNT — no raw address/link/code persists); the READABLE proof a
|
|
282
|
+
persona saw the email is its screenshots of the inbox page. Requires `python3`
|
|
283
|
+
in the subject sandbox (the stock E2B desktop template has it).
|
|
262
284
|
|
|
263
285
|
Lab backends report results in their own schemas (`humanish.run-result.v1`,
|
|
264
286
|
`humanish.oss-lab-result.v1`, `humanish.oss-meta-lab-result.v1`,
|
package/docs/goals/current.md
CHANGED
|
@@ -16,7 +16,7 @@ Humanish should be the open-source CLI that lets a maintainer ask:
|
|
|
16
16
|
The answer should be observable, verifiable, public-safe, and easy to turn into
|
|
17
17
|
actionable feedback.
|
|
18
18
|
|
|
19
|
-
## Current Program Truth (source `0.
|
|
19
|
+
## Current Program Truth (source `0.35.0`)
|
|
20
20
|
|
|
21
21
|
The package source and repository implementation in this tree agree on these
|
|
22
22
|
points:
|
|
@@ -82,7 +82,7 @@ silently drifting from one is not.
|
|
|
82
82
|
| Default | Why it is the default | Legitimate override |
|
|
83
83
|
|---|---|---|
|
|
84
84
|
| Dry-run | Spend safety (invariant 3 sets the floor; dry-run keeps the floor far away) | `scenario.mode: live` |
|
|
85
|
-
| 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` (
|
|
85
|
+
| 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` (an explicit choice) = SEQUENTIAL turns (one sandbox); higher = CONCURRENT — and since #350 an omitted concurrency fills to the seat count, so every declared seat runs live at once by default (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. |
|
|
86
86
|
| 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 |
|
|
87
87
|
| 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 |
|
|
88
88
|
| 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) |
|
package/docs/ramp/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Status: public-safe contributor and agent ramp.
|
|
4
4
|
|
|
5
|
-
Package/source version in this tree: `0.
|
|
5
|
+
Package/source version in this tree: `0.35.0` (2026-08-05). The containment boundary introduced in
|
|
6
6
|
`0.15.1` remains in force: managed run and output paths bind to validated
|
|
7
7
|
physical filesystem identities, and stored provider IDs are evidence, not
|
|
8
8
|
cleanup authority. The bundled OSS meta-lab is dry-run only until
|
|
@@ -17,7 +17,7 @@ context.
|
|
|
17
17
|
Read these in order:
|
|
18
18
|
|
|
19
19
|
1. [`AGENTS.md`](../../AGENTS.md) for public boundary and engineering rules.
|
|
20
|
-
2. [`docs/principles/invariants-and-defaults.md`](../principles/invariants-and-defaults.md) —
|
|
20
|
+
2. [`docs/principles/invariants-and-defaults.md`](../principles/invariants-and-defaults.md) — which rules are invariants and which are overridable defaults, each with the reason it exists and the check that enforces it. (The enforcement is what makes a rule real here — when a doc sentence and a test disagree, trust the test and say so.)
|
|
21
21
|
3. [`README.md`](../../README.md) for install, commands, and package shape.
|
|
22
22
|
4. [`docs/goals/current.md`](../goals/current.md) for the active product goal.
|
|
23
23
|
5. [`docs/goals/proof-roadmap/goal.md`](https://github.com/danielgwilson/humanish/blob/main/docs/goals/proof-roadmap/goal.md) for the ratified proof architecture (repo-only; not shipped in the npm package, hence the absolute link).
|
|
@@ -113,8 +113,9 @@ Implemented:
|
|
|
113
113
|
Still not good enough:
|
|
114
114
|
|
|
115
115
|
The [current proof-roadmap checkpoint](https://github.com/danielgwilson/humanish/blob/main/docs/goals/proof-roadmap/README.md)
|
|
116
|
-
supersedes implementation-status phrases in the
|
|
117
|
-
|
|
116
|
+
supersedes implementation-status phrases in the 2026-06-10 roadmap packet
|
|
117
|
+
(kept as written — it is a dated record; its README carries current status)
|
|
118
|
+
without changing its success standard.
|
|
118
119
|
|
|
119
120
|
- capability receipts are not adopter replacement: no first-party deletion
|
|
120
121
|
branch has yet removed a bespoke generic harness while preserving
|
package/package.json
CHANGED
package/skills/humanish/SKILL.md
CHANGED
|
@@ -151,6 +151,24 @@ A lab is a composition (`subject` × `actors` × `execution` × `scenario` ×
|
|
|
151
151
|
`npx humanish lab inspect <lab>` to see how a manifest parses, including
|
|
152
152
|
warnings for fields the engine does not consume yet.
|
|
153
153
|
|
|
154
|
+
### Many actors at once (fan-out, shared worlds, concurrency)
|
|
155
|
+
|
|
156
|
+
- **Every declared seat runs live at once by default.** A 6-lane roster is 6
|
|
157
|
+
simultaneous actors; total sessions and spend are the same either way, only
|
|
158
|
+
wall-clock and simultaneity differ. `execution.concurrency` is a CAP, not a
|
|
159
|
+
mode: declare it only to bound simultaneous paid desktops, and expect a parse
|
|
160
|
+
warning when the cap makes seats run in waves (a green waved run looks
|
|
161
|
+
identical to the all-live run you meant, so the harness says so up front).
|
|
162
|
+
- **Per-lane worlds vs one shared world.** A plain multi-lane computer-use lab
|
|
163
|
+
gives each actor its OWN app instance (independent studies in parallel). Add
|
|
164
|
+
`subject.topology: shared-world` for N actors in ONE world (a lobby, a shared
|
|
165
|
+
DB, actors seeing each other's changes). `execution.concurrency: 1` on a
|
|
166
|
+
shared-world lab is the sequential turn-taking variant — one actor at a time,
|
|
167
|
+
and note comms/email has no wiring there.
|
|
168
|
+
- **Watching it:** each live lane is its own Observer tile/stream; lanes beyond
|
|
169
|
+
a declared cap start when a slot frees, which on a capped run looks like idle
|
|
170
|
+
tiles — another reason to leave the cap out unless you need it.
|
|
171
|
+
|
|
154
172
|
Use committed `humanish/labs/*.yaml` for public-safe, reproducible labs. Use
|
|
155
173
|
ignored `.humanish/labs/*.yaml` or `.humanish/local/labs/*.yaml` for private repo
|
|
156
174
|
targets, local-only dogfood, or machine-specific settings. Never commit private
|
|
@@ -179,19 +197,45 @@ the app sent it to finish a step.
|
|
|
179
197
|
```yaml
|
|
180
198
|
comms:
|
|
181
199
|
email:
|
|
182
|
-
injectEnv: RESEND_API_URL
|
|
183
|
-
|
|
184
|
-
|
|
200
|
+
injectEnv: RESEND_API_URL # adopter-named: whatever env var YOUR app reads for its
|
|
201
|
+
# email-API base URL. The harness sets it to the in-sandbox catch — do NOT also
|
|
202
|
+
# list it in subject.env. VERIFY the app actually reads this variable: a stock
|
|
203
|
+
# email SDK does not honor a base-URL env unless the app passes it through, and
|
|
204
|
+
# an app that ignores it sends real mail (or throws) while the inbox stays empty.
|
|
205
|
+
# A run where the catch captured zero sends warns at teardown for exactly this.
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
That is the whole block for the common case. Every lane automatically gets a
|
|
209
|
+
deterministic inbox address (`<laneId>@example.test`), and each actor's prompt is
|
|
210
|
+
extended with the full handoff: its address ("when the app asks for an email
|
|
211
|
+
address, enter exactly that"), the inbox URL to open, and the wait steering
|
|
212
|
+
("waiting for an email is normal, not a blocker"). Declare `recipients` only to
|
|
213
|
+
customize addresses or limit which lanes do email:
|
|
214
|
+
|
|
215
|
+
```yaml
|
|
185
216
|
recipients:
|
|
186
|
-
- lane:
|
|
187
|
-
|
|
217
|
+
- lane: signup-01 # this lab's REAL lane id — a roster lane's `id`, or the
|
|
218
|
+
# generated lane-01..lane-NN names when you use `count`. An unknown lane
|
|
219
|
+
# is a hard parse error listing the lab's actual lane ids (a mismatch
|
|
220
|
+
# would silently disable the funnel for that seat, which is how a
|
|
221
|
+
# 6-actor field run lost every inbox at once). Lanes you leave out get
|
|
222
|
+
# no inbox and are never told one exists — the parser warns which.
|
|
223
|
+
address: user@example.test # what the actor signs up with; the evidence
|
|
224
|
+
# drain matches captured mail against it.
|
|
188
225
|
```
|
|
189
226
|
|
|
190
227
|
The app keeps calling its email API normally (Resend/SendGrid-shaped, or a custom
|
|
191
|
-
profile); only the base URL is redirected.
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
228
|
+
profile); only the base URL is redirected. Route support: the clone/local-tree
|
|
229
|
+
computer-use route (inbox on the sandbox's own loopback) and the CONCURRENT
|
|
230
|
+
shared-world route (inbox getHost-exposed from the subject sandbox; the default
|
|
231
|
+
since every seat now runs live at once). Declared anywhere else — app-url /
|
|
232
|
+
operator-provided subjects, or a sequential `concurrency: 1` shared world — it is
|
|
233
|
+
warned inert at parse: no catch exists there and no actor hears about an inbox.
|
|
234
|
+
It needs `python3` in the subject sandbox (the stock E2B desktop has it).
|
|
235
|
+
Evidence is digest-only (`humanish.comms-thread.v1` — counts and digests, never
|
|
236
|
+
raw mail); the *readable* proof a persona saw the email is its screenshots of the
|
|
237
|
+
inbox page. See `docs/contracts/schemas.md` for the full `comms:` shape and
|
|
238
|
+
`humanish <cmd> --help` for run flags — this skill does not restate them.
|
|
195
239
|
|
|
196
240
|
## First Proof Run
|
|
197
241
|
|