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.
- package/AGENTS.md +77 -0
- package/CONTRIBUTING.md +39 -0
- package/LICENSE +21 -0
- package/README.md +437 -8
- package/SECURITY.md +34 -0
- package/dist/actor-contract.d.ts +107 -0
- package/dist/actor-contract.js +286 -0
- package/dist/actor-contract.js.map +1 -0
- package/dist/actor-registry.d.ts +73 -0
- package/dist/actor-registry.js +93 -0
- package/dist/actor-registry.js.map +1 -0
- package/dist/adapter-extension.d.ts +54 -0
- package/dist/adapter-extension.js +214 -0
- package/dist/adapter-extension.js.map +1 -0
- package/dist/argv.d.ts +1 -0
- package/dist/argv.js +8 -0
- package/dist/argv.js.map +1 -0
- package/dist/artifact-reference.d.ts +22 -0
- package/dist/artifact-reference.js +47 -0
- package/dist/artifact-reference.js.map +1 -0
- package/dist/browser-evidence-hygiene.d.ts +7 -0
- package/dist/browser-evidence-hygiene.js +40 -0
- package/dist/browser-evidence-hygiene.js.map +1 -0
- package/dist/claude-agent-sdk.d.ts +94 -0
- package/dist/claude-agent-sdk.js +363 -0
- package/dist/claude-agent-sdk.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +5 -0
- package/dist/cli.js.map +1 -0
- package/dist/codex-app-server-ui.d.ts +39 -0
- package/dist/codex-app-server-ui.js +357 -0
- package/dist/codex-app-server-ui.js.map +1 -0
- package/dist/codex-app-server.d.ts +144 -0
- package/dist/codex-app-server.js +754 -0
- package/dist/codex-app-server.js.map +1 -0
- package/dist/command-failure.d.ts +29 -0
- package/dist/command-failure.js +54 -0
- package/dist/command-failure.js.map +1 -0
- package/dist/computer-use-actor.d.ts +52 -0
- package/dist/computer-use-actor.js +48 -0
- package/dist/computer-use-actor.js.map +1 -0
- package/dist/computer-use.d.ts +232 -0
- package/dist/computer-use.js +615 -0
- package/dist/computer-use.js.map +1 -0
- package/dist/concurrency.d.ts +1 -0
- package/dist/concurrency.js +27 -0
- package/dist/concurrency.js.map +1 -0
- package/dist/concurrent-shared-world-lab.d.ts +115 -0
- package/dist/concurrent-shared-world-lab.js +1094 -0
- package/dist/concurrent-shared-world-lab.js.map +1 -0
- package/dist/core/git-state.d.ts +33 -0
- package/dist/core/git-state.js +277 -0
- package/dist/core/git-state.js.map +1 -0
- package/dist/core/git-workspace.d.ts +31 -0
- package/dist/core/git-workspace.js +447 -0
- package/dist/core/git-workspace.js.map +1 -0
- package/dist/core/index.d.ts +4 -0
- package/dist/core/index.js +3 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/run-primitives.d.ts +66 -0
- package/dist/core/run-primitives.js +120 -0
- package/dist/core/run-primitives.js.map +1 -0
- package/dist/cua-actor-lab.d.ts +621 -0
- package/dist/cua-actor-lab.js +2845 -0
- package/dist/cua-actor-lab.js.map +1 -0
- package/dist/device-presets.d.ts +67 -0
- package/dist/device-presets.js +50 -0
- package/dist/device-presets.js.map +1 -0
- package/dist/e2b-desktop-executor.d.ts +101 -0
- package/dist/e2b-desktop-executor.js +309 -0
- package/dist/e2b-desktop-executor.js.map +1 -0
- package/dist/e2b-desktop-launch.d.ts +144 -0
- package/dist/e2b-desktop-launch.js +59 -0
- package/dist/e2b-desktop-launch.js.map +1 -0
- package/dist/e2b-detached.d.ts +53 -0
- package/dist/e2b-detached.js +130 -0
- package/dist/e2b-detached.js.map +1 -0
- package/dist/e2b-terminal-lab.d.ts +345 -0
- package/dist/e2b-terminal-lab.js +1532 -0
- package/dist/e2b-terminal-lab.js.map +1 -0
- package/dist/env-file.d.ts +14 -0
- package/dist/env-file.js +108 -0
- package/dist/env-file.js.map +1 -0
- package/dist/feedback.d.ts +51 -0
- package/dist/feedback.js +351 -0
- package/dist/feedback.js.map +1 -0
- package/dist/image-evidence.d.ts +2 -0
- package/dist/image-evidence.js +33 -0
- package/dist/image-evidence.js.map +1 -0
- package/dist/index.d.ts +63 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/init-templates.d.ts +12 -0
- package/dist/init-templates.js +369 -0
- package/dist/init-templates.js.map +1 -0
- package/dist/init.d.ts +26 -0
- package/dist/init.js +429 -0
- package/dist/init.js.map +1 -0
- package/dist/lab-app-runner.d.ts +78 -0
- package/dist/lab-app-runner.js +403 -0
- package/dist/lab-app-runner.js.map +1 -0
- package/dist/lab-config.d.ts +583 -0
- package/dist/lab-config.js +1789 -0
- package/dist/lab-config.js.map +1 -0
- package/dist/lab-engine.d.ts +77 -0
- package/dist/lab-engine.js +216 -0
- package/dist/lab-engine.js.map +1 -0
- package/dist/lab-preflight.d.ts +67 -0
- package/dist/lab-preflight.js +385 -0
- package/dist/lab-preflight.js.map +1 -0
- package/dist/labs.d.ts +53 -0
- package/dist/labs.js +382 -0
- package/dist/labs.js.map +1 -0
- package/dist/observer-assets.d.ts +2 -0
- package/dist/observer-assets.js +2630 -0
- package/dist/observer-assets.js.map +1 -0
- package/dist/observer-data.d.ts +63 -0
- package/dist/observer-data.js +145 -0
- package/dist/observer-data.js.map +1 -0
- package/dist/observer-static.d.ts +39 -0
- package/dist/observer-static.js +306 -0
- package/dist/observer-static.js.map +1 -0
- package/dist/observer.d.ts +46 -0
- package/dist/observer.js +550 -0
- package/dist/observer.js.map +1 -0
- package/dist/openai-responses-cu.d.ts +113 -0
- package/dist/openai-responses-cu.js +545 -0
- package/dist/openai-responses-cu.js.map +1 -0
- package/dist/oss-lab.d.ts +52 -0
- package/dist/oss-lab.js +344 -0
- package/dist/oss-lab.js.map +1 -0
- package/dist/oss-meta-lab-scoring.d.ts +15 -0
- package/dist/oss-meta-lab-scoring.js +145 -0
- package/dist/oss-meta-lab-scoring.js.map +1 -0
- package/dist/oss-meta-lab.d.ts +277 -0
- package/dist/oss-meta-lab.js +4529 -0
- package/dist/oss-meta-lab.js.map +1 -0
- package/dist/oss-remote-telemetry.d.ts +77 -0
- package/dist/oss-remote-telemetry.js +403 -0
- package/dist/oss-remote-telemetry.js.map +1 -0
- package/dist/persona.d.ts +35 -0
- package/dist/persona.js +133 -0
- package/dist/persona.js.map +1 -0
- package/dist/pi-agent-core.d.ts +77 -0
- package/dist/pi-agent-core.js +203 -0
- package/dist/pi-agent-core.js.map +1 -0
- package/dist/program.d.ts +54 -0
- package/dist/program.js +2349 -0
- package/dist/program.js.map +1 -0
- package/dist/redaction.d.ts +90 -0
- package/dist/redaction.js +292 -0
- package/dist/redaction.js.map +1 -0
- package/dist/run-paths.d.ts +56 -0
- package/dist/run-paths.js +340 -0
- package/dist/run-paths.js.map +1 -0
- package/dist/run.d.ts +794 -0
- package/dist/run.js +4844 -0
- package/dist/run.js.map +1 -0
- package/dist/scripted-browser-actor.d.ts +297 -0
- package/dist/scripted-browser-actor.js +1399 -0
- package/dist/scripted-browser-actor.js.map +1 -0
- package/dist/scripted-browser-lab.d.ts +107 -0
- package/dist/scripted-browser-lab.js +788 -0
- package/dist/scripted-browser-lab.js.map +1 -0
- package/dist/selected-output-paths.d.ts +49 -0
- package/dist/selected-output-paths.js +354 -0
- package/dist/selected-output-paths.js.map +1 -0
- package/dist/shared-world-lab.d.ts +208 -0
- package/dist/shared-world-lab.js +1049 -0
- package/dist/shared-world-lab.js.map +1 -0
- package/dist/source-archive.d.ts +82 -0
- package/dist/source-archive.js +408 -0
- package/dist/source-archive.js.map +1 -0
- package/dist/stop-conditions.d.ts +26 -0
- package/dist/stop-conditions.js +66 -0
- package/dist/stop-conditions.js.map +1 -0
- package/dist/terminal-agent-actor.d.ts +36 -0
- package/dist/terminal-agent-actor.js +23 -0
- package/dist/terminal-agent-actor.js.map +1 -0
- package/docs/architecture/actor-contract.md +431 -0
- package/docs/architecture/github-feedback-loop.md +189 -0
- package/docs/architecture/local-codex-tui-actor.md +213 -0
- package/docs/architecture/observer.md +118 -0
- package/docs/architecture/oss-lab-poc.md +250 -0
- package/docs/architecture/project-layout.md +166 -0
- package/docs/architecture/state-driven-executor.md +203 -0
- package/docs/architecture/terminal-product-lane.md +148 -0
- package/docs/contracts/adapter-fixtures.md +80 -0
- package/docs/contracts/core.md +71 -0
- package/docs/contracts/feedback.md +145 -0
- package/docs/contracts/policy.md +311 -0
- package/docs/contracts/run-bundle.md +358 -0
- package/docs/contracts/schemas.md +984 -0
- package/docs/goals/current.md +428 -0
- package/docs/principles/invariants-and-defaults.md +135 -0
- package/docs/principles/self-driving-harness.md +129 -0
- package/docs/product/open-source-install-experience.md +237 -0
- package/docs/ramp/README.md +207 -0
- package/docs/release/open-source-readiness.md +208 -0
- package/docs/release/public-readiness-standard.md +205 -0
- package/docs/roadmap/world-class-open-source-v0.md +311 -0
- package/package.json +102 -8
- package/skills/humanish/SKILL.md +244 -0
- package/skills/humanish/agents/openai.yaml +7 -0
- package/index.js +0 -1
|
@@ -0,0 +1,984 @@
|
|
|
1
|
+
# Contract Schema Index
|
|
2
|
+
|
|
3
|
+
Date: 2026-06-02 (updated 2026-06-24)
|
|
4
|
+
|
|
5
|
+
Status: schema map aligned to the shipped v0.6.x surface. Rows marked
|
|
6
|
+
"reserved" name layering intent only — no code emits or validates them yet.
|
|
7
|
+
Do not emit a reserved schema.
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
|
|
11
|
+
This document names the core Humanish contracts before more implementation
|
|
12
|
+
lands. It is intentionally public-safe: examples use synthetic ids, local
|
|
13
|
+
relative artifact paths, env var names without values, and redacted evidence
|
|
14
|
+
notes.
|
|
15
|
+
|
|
16
|
+
Core contracts are reusable. Adapter contracts describe a target app, CLI, or
|
|
17
|
+
workflow without leaking private upstream truth into core.
|
|
18
|
+
|
|
19
|
+
## Ownership Rule
|
|
20
|
+
|
|
21
|
+
| Layer | Owns | Does not own |
|
|
22
|
+
| --- | --- | --- |
|
|
23
|
+
| Core | Schema versions, run ids, artifact layout, lifecycle events, actor/substrate status, evidence shape, review, verification, redaction, feedback mechanics, latest/history indexes. | Product routes, real customer data, private screenshots, private transcripts, credential values, target-specific acceptance language. |
|
|
24
|
+
| Adapter | Product routes, scenario/persona choices, app topology, env var names, network allowlists, coverage vocabulary, milestones, fixture data, target-specific proof expectations. | Generic run bundle schema, public-safety gates, provider secret values, raw private artifacts, GitHub mutation authority. |
|
|
25
|
+
|
|
26
|
+
## Contract Index
|
|
27
|
+
|
|
28
|
+
| Contract | Schema | Public-safe fixture |
|
|
29
|
+
| --- | --- | --- |
|
|
30
|
+
| Run bundle | `humanish.run-bundle.v1` | `synthetic-run-bundle` |
|
|
31
|
+
| Adapter | `humanish.adapter.v1` | `synthetic-cli-adapter` |
|
|
32
|
+
| Lab | `humanish.lab.v2` | `first-run` |
|
|
33
|
+
| Persona | `humanish.persona.v1` | `synthetic-maintainer` |
|
|
34
|
+
| Scenario | `humanish.scenario.v1` | `first-run-smoke` |
|
|
35
|
+
| Actor trace | `humanish.actor-trace.v1` | `synthetic-actor-trace` |
|
|
36
|
+
| Substrate | reserved (never shipped) | none |
|
|
37
|
+
| Evidence stream | reserved (streams live inside the run bundle) | see [`run-bundle.md`](run-bundle.md) |
|
|
38
|
+
| Review | `humanish.review.v1` | `contract-proof-review` |
|
|
39
|
+
| Verification | `humanish.verify-result.v1` | `five-check-verify` |
|
|
40
|
+
| Policy | `humanish.policy.v1` (fixture-only; not engine-validated) | `public-safety-policy` |
|
|
41
|
+
| Feedback | `humanish.feedback.v1` | `public-safe-feedback` |
|
|
42
|
+
| Terminal cost ledger | `humanish.terminal-cost-ledger.v1` | see Terminal Cost Ledger below |
|
|
43
|
+
| Terminal no-spend proof | `humanish.terminal-no-spend-proof.v1` | see Terminal Cost Ledger below |
|
|
44
|
+
| Adapter score | `humanish.adapter-score.v1` (`RunBundle.adapterScore`; namespaced; route-specific acceptance semantics) | see Product-Adapter Extension Seam below |
|
|
45
|
+
| Adapter artifact | `humanish.adapter-artifact.v1` (`RunBundle.adapterArtifacts[]`; namespaced; local relative proof references) | see Product-Adapter Extension Seam below |
|
|
46
|
+
| Shared-world evidence | `humanish.shared-world.v1` (additive `RunBundle.sharedWorld` + `RunBundle.attributionClass`; `topologyMode: sequential \| concurrent`) | see Shared-World Evidence below |
|
|
47
|
+
|
|
48
|
+
## Lab Manifest
|
|
49
|
+
|
|
50
|
+
Schema: `humanish.lab.v2` (`src/lab-config.ts`). There is deliberately no v1
|
|
51
|
+
compatibility: v1 (`kind`, top-level `sims`) had zero real users and was
|
|
52
|
+
deleted when labs became config.
|
|
53
|
+
|
|
54
|
+
A lab is a composition over code primitives, not a hardcoded kind:
|
|
55
|
+
|
|
56
|
+
- `subject`: what the run acts on — `this-repo`, `clone` (owner/repo slugs,
|
|
57
|
+
optional in-sandbox `serve` + env var names + `state`), `local-tree` (the
|
|
58
|
+
operator's own working tree, packed on the host and provisioned in-sandbox
|
|
59
|
+
in place of a clone; see below), `app-url`
|
|
60
|
+
(loopback unless `policies.allowPublicTargets` declares an owned deployment),
|
|
61
|
+
`local-app` (an already-running LOCAL dev server driven IN-PROCESS via a
|
|
62
|
+
custom `CuaExecutor`, NO clone and NO E2B desktop — always loopback), or
|
|
63
|
+
`terminal-product` (a CLI/product a real autonomous terminal agent studies
|
|
64
|
+
from PUBLIC surfaces only — see below). A
|
|
65
|
+
`local-app` subject pairs a computer-use actor with `execution.target: local`
|
|
66
|
+
(or absent) and is library-assisted: the caller supplies
|
|
67
|
+
`cuaHooks.buildExecutor` + `buildProvider`; with no hooks the engine fails
|
|
68
|
+
closed (`HUMANISH_CUA_LAB_LOCAL_APP_NO_EXECUTOR`), never a desktop attempt. See
|
|
69
|
+
[`docs/architecture/state-driven-executor.md`](../architecture/state-driven-executor.md);
|
|
70
|
+
- `subject.localTree` (`local-tree` subjects, computer-use route): pack/upload
|
|
71
|
+
knobs for the packed working tree: `exclude[]` (extra archive excludes on
|
|
72
|
+
top of the always-on denylist; entries match as a repo-relative path
|
|
73
|
+
prefix or an exact basename, absolute paths and glob syntax are rejected
|
|
74
|
+
at parse time, and leading `./` / trailing `/` are normalized), `keep`
|
|
75
|
+
(preserve the sandbox on a failed lane for debugging, mirroring
|
|
76
|
+
`subject.clone.keep`; a kept local-tree sandbox holds the packed working
|
|
77
|
+
tree, including any file that survived the denylist), and
|
|
78
|
+
`maxArchiveBytes` (upload size cap override; default 256 MiB). Routing requires `execution.target: e2b-desktop` and a
|
|
79
|
+
computer-use actor; `subject.serve`/`env`/`state` apply exactly as they do
|
|
80
|
+
on the clone route (identical install/build/start/state semantics). The
|
|
81
|
+
packed root is the lab resolution cwd; there is no path field, by design
|
|
82
|
+
(an absolute path in a lab manifest would be a machine-specific,
|
|
83
|
+
unshareable, leak-prone artifact). Enumeration is git-aware when the root
|
|
84
|
+
is a git work tree (`git ls-files --cached --others --exclude-standard`,
|
|
85
|
+
honoring `.gitignore`) or a denylist-only recursive walk otherwise; an
|
|
86
|
+
always-on denylist (`.git`, `node_modules`, `.humanish`, `.env*`, key/cert
|
|
87
|
+
file patterns, and common credential-shaped names; the authoritative list
|
|
88
|
+
is `LOCAL_TREE_DENYLIST_BASENAME_PATTERNS` in `src/source-archive.ts`)
|
|
89
|
+
applies in both modes and is not overridable. The denylist matches names,
|
|
90
|
+
not contents; a secret in a file it does not name packs like any other
|
|
91
|
+
file, so review the pack summary line and use `localTree.exclude`. The lab packs
|
|
92
|
+
ONCE per run and uploads the identical archive to every fan-out lane. The
|
|
93
|
+
in-sandbox commit refresh clone subjects use is skipped: `.git` is never
|
|
94
|
+
uploaded, so identity comes from the host-side archive digest instead. See
|
|
95
|
+
[`docs/goals/local-tree-subject/goal.md`](../goals/local-tree-subject/goal.md);
|
|
96
|
+
- `subject.product` (terminal-product subjects): the product the agent studies.
|
|
97
|
+
`product.name` is a public-safe token (committed fixtures use a NEUTRAL mock
|
|
98
|
+
name); `product.publicSurfaces[]` is the list of http(s) URLs (docs, llms.txt,
|
|
99
|
+
skill manifest) that are the ONLY world the agent sees — the lab does not
|
|
100
|
+
clone/provision the product, so its provenance is recorded UNPINNED
|
|
101
|
+
(invariant 5). `serve`/`clone`/`state`/`repos`/`appUrl` are rejected on a
|
|
102
|
+
terminal-product subject (a field that cannot act on the route is a parse
|
|
103
|
+
error, not silently dropped). See
|
|
104
|
+
[`docs/architecture/terminal-product-lane.md`](../architecture/terminal-product-lane.md);
|
|
105
|
+
- `subject.state` (clone or local-tree subjects, computer-use route): the
|
|
106
|
+
subject's state story. `state.seed[]` declares ordered, bounded
|
|
107
|
+
seed/migration/fixture steps (`{ name, command, when: before-build |
|
|
108
|
+
before-start | after-ready, timeoutMs }`) executed in-sandbox around the
|
|
109
|
+
serve sequence; `state.external[]` declares env var NAMES (each must also
|
|
110
|
+
appear in `subject.env`) pointing at state the lab does not control,
|
|
111
|
+
recorded as UNPINNED in provenance. Commands persist in evidence as
|
|
112
|
+
sha256-16 digests only, never as text;
|
|
113
|
+
- `actors`: who drives it. On the computer-use and scripted-browser routes
|
|
114
|
+
`actors[0].type` is a real dispatch key resolved against the actor registry;
|
|
115
|
+
elsewhere it is a descriptive label (e.g. `synthetic-persona`).
|
|
116
|
+
`actors[0].count` carries route-specific meanings: synthetic route lane
|
|
117
|
+
count (simCount); scripted-browser route surface roster (1 = desktop,
|
|
118
|
+
2 = desktop + mobile, default 1); computer-use **E2B** route the HOMOGENEOUS
|
|
119
|
+
fan-out lane count (N identical lanes, each its own E2B desktop — per-lane
|
|
120
|
+
worlds, cap 16). The in-process/local-app computer-use route stays single
|
|
121
|
+
lane (no E2B to fan out);
|
|
122
|
+
- `actors[0].lanes[]` (computer-use E2B route): a DIFFERENTIATED fan-out roster,
|
|
123
|
+
each `{ id?, actorType?, surface?, caseGroup?, persona?, device?,
|
|
124
|
+
instruction?, target?, entry? }` becoming one independent E2B desktop (or, on the
|
|
125
|
+
shared-world routes, one role/seat against the shared plane). `actorType`,
|
|
126
|
+
`surface`, and `caseGroup` are adapter-owned public-safe labels for grouping
|
|
127
|
+
simulated users; they are not core enums, and `actorType` is deliberately
|
|
128
|
+
separate from the execution dispatch key `actors[0].type`. `lanes` is XOR with
|
|
129
|
+
`count` (declare a roster OR a homogeneous count) and XOR with
|
|
130
|
+
`actors[0].laneFocus` (a roster's per-lane `instruction` is the steer);
|
|
131
|
+
`lanes[].device` is XOR with a raw `execution.desktop.resolution`. Lane ids
|
|
132
|
+
default `lane-01`..`lane-NN`, must be unique, and name per-lane evidence paths
|
|
133
|
+
(`actors/<streamId>.json`, `screenshots/<laneId>/`). Cap 16 lanes. On every
|
|
134
|
+
non-cua route `lanes` is inert (warned). `subject.clone.fanout` is REJECTED on
|
|
135
|
+
the cua route (declare fan-out via `count`/`lanes`; `clone.fanout` drives the
|
|
136
|
+
OSS smoke/meta routes only);
|
|
137
|
+
- `actors[0].lanes[].target` (app-url × computer-use E2B route only): an
|
|
138
|
+
absolute browser URL that lane opens instead of `subject.appUrl`. This is the
|
|
139
|
+
setup-produced-target handoff for crawler/swarm labs: an adapter may start any
|
|
140
|
+
topology it needs, then declare exactly which target each actor should drive.
|
|
141
|
+
If any lane declares `target`, every lane in that roster must declare one.
|
|
142
|
+
Public/non-loopback targets still require `policies.allowPublicTargets: true`.
|
|
143
|
+
`target` is mutually exclusive with `entry`: `target` is an absolute app-url
|
|
144
|
+
browser target; `entry` is a shared-world same-origin seat path;
|
|
145
|
+
- `actors[0].roster[]` (computer-use E2B route): compact authoring sugar for
|
|
146
|
+
repeated lane groups, each `{ id, count, actorType?, surface?, caseGroup?,
|
|
147
|
+
persona?, device?, instruction?, target?, entry? }`. The parser expands it into
|
|
148
|
+
deterministic `lanes[]` before the engine runs (`viewer-01`, `viewer-02`,
|
|
149
|
+
...), so the runtime and run bundle keep one normalized lane shape. `roster`
|
|
150
|
+
is XOR with explicit `lanes`, homogeneous `count`, and `laneFocus`;
|
|
151
|
+
- `execution.concurrency` (computer-use E2B route): bounds in-flight (paid)
|
|
152
|
+
fan-out lanes; default `min(laneCount, 3)`. The env override
|
|
153
|
+
`HUMANISH_CUA_MAX_CONCURRENCY` may only LOWER the effective bound, never raise
|
|
154
|
+
concurrent paid desktops (invariant 3). Inert (warned) on other routes.
|
|
155
|
+
`execution.timeoutMs` is the PER-LANE session budget on this route (semantics
|
|
156
|
+
change: it was the single-session budget pre-fan-out); there is no run-level
|
|
157
|
+
wall clock. `policies.allowPublicTargets` cannot combine with N>1 against one
|
|
158
|
+
implicit public `subject.appUrl` (ambiguous shared-world-ish topology); it may
|
|
159
|
+
combine with N>1 only when the roster declares explicit `lanes[].target` for
|
|
160
|
+
every lane;
|
|
161
|
+
- `execution`: where it runs — `local`, `e2b-desktop`, or `e2b-terminal`, plus
|
|
162
|
+
desktop device/resolution and timeouts. app-url subjects pair `e2b-desktop`
|
|
163
|
+
with a computer-use actor, or `local` (or absent) with a scripted-browser
|
|
164
|
+
actor; terminal-product subjects pair `e2b-terminal` (or absent → implied)
|
|
165
|
+
with a registered terminal actor;
|
|
166
|
+
- `execution.desktop.template` (e2b-desktop computer-use routes): a custom E2B
|
|
167
|
+
desktop TEMPLATE (image) NAME or ID the run launches on — for a subject that
|
|
168
|
+
needs runtimes the stock `desktop` image lacks (e.g. node/bun/a local Postgres
|
|
169
|
+
baked into an adopter-maintained image). Any non-empty string is a valid
|
|
170
|
+
name/id (no allowlist); a blank/whitespace value is rejected. Threaded to the
|
|
171
|
+
SDK's `Sandbox.create(template, opts)` on EVERY desktop-creating route (the
|
|
172
|
+
single-lane + fan-out cua lanes, the sequential shared-world plane, and the
|
|
173
|
+
concurrent shared-world subject AND every actor sandbox); when absent the call
|
|
174
|
+
stays the byte-stable `Sandbox.create(opts)` default (the stock template). The
|
|
175
|
+
template actually used is recorded in the run bundle as `desktopTemplate`
|
|
176
|
+
(public-safe — a template name is not a secret). Inert (warned) on every route
|
|
177
|
+
that creates no desktop, incl. the in-process `local-app` cua route and the
|
|
178
|
+
meta route — never silently ignored (invariant 6);
|
|
179
|
+
- `execution.desktop.browser` (e2b-desktop computer-use/fan-out routes, plus
|
|
180
|
+
sequential and concurrent shared-world actor seats): optional browser family
|
|
181
|
+
preference: `default`, `chrome`, `chromium`, or `firefox`. Absent/default
|
|
182
|
+
preserves the historical desktop opener behavior. A concrete value means
|
|
183
|
+
launch that browser or fail closed; when configured, the bundle records
|
|
184
|
+
`desktopBrowser` with the requested value and the resolved in-sandbox command
|
|
185
|
+
when known. Inert (warned) where this route-specific browser launcher is not
|
|
186
|
+
used;
|
|
187
|
+
- `execution.terminal` + `execution.runtimeAuth` (terminal-product route):
|
|
188
|
+
`terminal.transport` is `exec-stream` — captured NON-interactive exec output
|
|
189
|
+
(stdin disabled); `pty` is rejected because labeling captured exec output as
|
|
190
|
+
an interactive PTY would overstate the mechanism (invariant 6; a true duplex
|
|
191
|
+
PTY transport is a deferred slice). `terminal.stdin` defaults to `disabled`
|
|
192
|
+
(`sent`/assisted input is rejected until the interventions ledger + a
|
|
193
|
+
non-comparable marker exist). `runtimeAuth: openai-env` declares the agent's
|
|
194
|
+
runtime-auth channel — recorded as NAMES ONLY; the command-scoped injection
|
|
195
|
+
(`keyPlacement: in-sandbox-command-scoped`) is enforced by the engine in a
|
|
196
|
+
later slice;
|
|
197
|
+
- `scenario`: `mode: dry-run` (contract evidence, no spend) or `live`.
|
|
198
|
+
`scenario.ref` is CONSUMED (and REQUIRED) on the scripted-browser route: it
|
|
199
|
+
resolves a committed scenario (`humanish/scenarios/<ref>.yaml` or a repo
|
|
200
|
+
path) whose `browser.steps` ARE what the actor executes, digest-pinned into
|
|
201
|
+
bundle provenance; on other routes `ref`/`inline` stay forward-declared
|
|
202
|
+
warnings. On the scripted route `live` gates real browser ACTUATION against
|
|
203
|
+
the declared app — provider spend stays $0 by mechanism (no model runs);
|
|
204
|
+
- `scenario.caps` (terminal-product route): `{ maxUsd, maxJobs, maxMinutes }`,
|
|
205
|
+
all non-negative numbers (0 = no-spend, the default). The blast-radius budget
|
|
206
|
+
that bounds the in-sandbox live key by MECHANISM, not by hope — the live key
|
|
207
|
+
is never exercised without a fail-closed cap in force. `maxMinutes` is the
|
|
208
|
+
wall-clock kill; `maxUsd`/`maxJobs` are enforced fail-closed against the cost
|
|
209
|
+
ledger (a run whose KNOWN spend exceeds the cap fails closed,
|
|
210
|
+
`HUMANISH_TERMINAL_LAB_CAPS_EXCEEDED`). The no-spend proof is derived from that
|
|
211
|
+
real ledger, never asserted (see Terminal Cost Ledger And No-Spend Proof).
|
|
212
|
+
Inert (warned) on every other route;
|
|
213
|
+
- `policies`: `redactRepos`, `redactScreenshots`, `allowPublicTargets`, and the
|
|
214
|
+
terminal-product credential-boundary booleans `allowPrivateRepoAccess`,
|
|
215
|
+
`allowProviderCredentials`, `allowPaymentCredentials`, `allowGitHubMutation`
|
|
216
|
+
(all DEFAULT FALSE — deny-by-default; only the runtime LLM key enters, and
|
|
217
|
+
only command-scoped). The scripted-browser route is loopback-only and rejects
|
|
218
|
+
`redactScreenshots: true` (blur unimplemented there) and
|
|
219
|
+
`allowPublicTargets: true` fail-closed rather than ignoring them.
|
|
220
|
+
|
|
221
|
+
Lab backends report results in their own schemas (`humanish.run-result.v1`,
|
|
222
|
+
`humanish.oss-lab-result.v1`, `humanish.oss-meta-lab-result.v1`,
|
|
223
|
+
`humanish.cua-lab-result.v2`, `humanish.scripted-lab-result.v1`,
|
|
224
|
+
`humanish.terminal-lab-result.v1`); the evidence record stays
|
|
225
|
+
`humanish.run-bundle.v1` in every case. The computer-use result bumped to v2 for
|
|
226
|
+
fan-out: it carries `plan` (the pre-flight lane table — concurrency, waves,
|
|
227
|
+
per-lane session budget, worst-case sandbox-minutes), `lanes[]` (ALWAYS present,
|
|
228
|
+
length 1 at N=1; per-lane status/session/sandbox/subject), and `laneSummary`
|
|
229
|
+
(passed/skipped/harnessError/hollow counts). The top-level `session`/`sandbox`
|
|
230
|
+
mirror the first lane and `subject.commit` is unanimity-gated across lanes
|
|
231
|
+
(omitted with a divergence warning when lanes resolve different commits). At N=1
|
|
232
|
+
the run bundle is byte-stable with the pre-fan-out output; only the result
|
|
233
|
+
projection changed. A fan-out run records a `cua-lab.fanout.plan` bundle event
|
|
234
|
+
(and a `cua-lab.fanout.fail-fast` event when a harness error skips queued lanes);
|
|
235
|
+
`ok = observer.ok ∧ no skipped lane ∧ all lanes terminal ∧ no harness error ∧ no
|
|
236
|
+
hollow lane`.
|
|
237
|
+
|
|
238
|
+
Explicit failed-lane reruns are supported on the CUA fan-out route via
|
|
239
|
+
`humanish lab run <lab> --rerun-failed-from <run-id> [--lanes lane-a,lane-b]`.
|
|
240
|
+
The source run must be a live CUA fan-out bundle. Humanish creates a NEW run for
|
|
241
|
+
the selected failed/blocked/timed-out/hollow lanes (or explicit lane ids), leaves
|
|
242
|
+
the source verdict unchanged, and records lineage as `run.rerun` plus a
|
|
243
|
+
`cua-lab.fanout.rerun` event: source run id, selected lane ids, and previous lane
|
|
244
|
+
statuses/reasons. This is intentionally not automatic retry; a passing rerun is a
|
|
245
|
+
nondeterminism candidate for human/product scoring, not a rewrite of the old run.
|
|
246
|
+
|
|
247
|
+
Manifests are human-authored `.yaml` source under `humanish/labs/*.yaml` for
|
|
248
|
+
committed public-safe labs, or ignored `.humanish/labs/*.yaml` /
|
|
249
|
+
`.humanish/local/labs/*.yaml` for private local dogfood. Fields the engine does
|
|
250
|
+
not yet consume are accepted but reported as warnings (`humanish lab inspect`
|
|
251
|
+
shows them), so a manifest never silently claims behavior that did not run.
|
|
252
|
+
|
|
253
|
+
Committed fixture (`humanish/labs/first-run.yaml`):
|
|
254
|
+
|
|
255
|
+
```yaml
|
|
256
|
+
schema: humanish.lab.v2
|
|
257
|
+
id: first-run
|
|
258
|
+
title: First-run synthetic Observer
|
|
259
|
+
description: Public-safe starter lab that generates a synthetic run bundle and Observer without provider spend.
|
|
260
|
+
subject:
|
|
261
|
+
source: this-repo
|
|
262
|
+
actors:
|
|
263
|
+
- type: synthetic-persona
|
|
264
|
+
count: 4
|
|
265
|
+
scenario:
|
|
266
|
+
mode: dry-run
|
|
267
|
+
defaults:
|
|
268
|
+
open: true
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
## Run Bundle
|
|
272
|
+
|
|
273
|
+
Run bundles are the canonical evidence record. Observer data, review Markdown,
|
|
274
|
+
feedback drafts, and issue text are projections from the bundle.
|
|
275
|
+
|
|
276
|
+
Core-owned fields:
|
|
277
|
+
|
|
278
|
+
- `schema`
|
|
279
|
+
- `runId`
|
|
280
|
+
- `mode`
|
|
281
|
+
- `simCount`
|
|
282
|
+
- `createdAt`
|
|
283
|
+
- `artifactRoot`
|
|
284
|
+
- `source.git`
|
|
285
|
+
- `lifecycle`
|
|
286
|
+
- `simulations`
|
|
287
|
+
- `streams`
|
|
288
|
+
- `events`
|
|
289
|
+
- `redaction`
|
|
290
|
+
- `artifacts`
|
|
291
|
+
- `review`
|
|
292
|
+
- `feedbackCandidates`
|
|
293
|
+
- `subject` (optional, additive): structured subject provenance —
|
|
294
|
+
`{ source: clone | app-url | local-tree, repo?, commit?, archiveSha256?,
|
|
295
|
+
dirty?, envNames?, state }` where `state` is `{ provenance: seeded |
|
|
296
|
+
unpinned | declared-not-run | undeclared, seed?: [{ name, when,
|
|
297
|
+
commandDigest, ok?, exitCode?, timedOut?, durationMs? }], externalEnvNames?
|
|
298
|
+
}`. Emitted by the computer-use backend; absent on pre-existing and other
|
|
299
|
+
backends' bundles. `repo`/`commit` are clone-route fields; `archiveSha256`
|
|
300
|
+
(64-hex sha256, the local-tree provenance pin) and `dirty` (host git
|
|
301
|
+
porcelain status at pack time) are local-tree-route fields, additive under
|
|
302
|
+
`humanish.run-bundle.v1`: a dirty working tree cannot be commit-pinned, so
|
|
303
|
+
the archive content digest stands in for it. `commandDigest` is the
|
|
304
|
+
sha256-16 of the exact seed command — command text and env values never
|
|
305
|
+
appear. `humanish verify` fails closed when a LIVE `local-tree` bundle carries
|
|
306
|
+
no well-formed `archiveSha256`, in addition to the existing `subject state
|
|
307
|
+
provenance` check.
|
|
308
|
+
- `desktopTemplate` (optional, additive): the custom E2B desktop TEMPLATE (image)
|
|
309
|
+
the run's sandbox(es) launched on, from `execution.desktop.template` — so the
|
|
310
|
+
evidence shows WHICH image ran. Present only when a template was configured;
|
|
311
|
+
absent == the stock `desktop` template, so every pre-existing bundle is
|
|
312
|
+
byte-stable. Public-safe (a template name is not a secret).
|
|
313
|
+
- `attributionClass` (optional, additive): `isolated | shared-world`. Absent ==
|
|
314
|
+
`isolated`, so every existing bundle is byte-stable. The interaction-attribution
|
|
315
|
+
honesty axis (#164) — ORTHOGONAL to the persona-sampling evidence classes. Set
|
|
316
|
+
to `shared-world` by the shared-world backend, paired with `sharedWorld`.
|
|
317
|
+
- `sharedWorld` (optional, additive): the shared-world evidence block
|
|
318
|
+
(`humanish.shared-world.v1`) — see [Shared-World Evidence](#shared-world-evidence)
|
|
319
|
+
below. Present only on shared-world runs; verified fail-closed by the
|
|
320
|
+
`shared-world evidence` check in `humanish verify`.
|
|
321
|
+
|
|
322
|
+
Adapter-owned fields:
|
|
323
|
+
|
|
324
|
+
- `source.packageName`
|
|
325
|
+
- `source.humanishSource`
|
|
326
|
+
- `persona`
|
|
327
|
+
- `scenario`
|
|
328
|
+
- target-specific stream labels and public-safe summaries
|
|
329
|
+
|
|
330
|
+
Synthetic fixture:
|
|
331
|
+
|
|
332
|
+
```yaml
|
|
333
|
+
schema: humanish.run-bundle.v1
|
|
334
|
+
runId: synthetic-run-bundle-2026-06-02t10-00-00-000z-proof
|
|
335
|
+
mode: dry-run
|
|
336
|
+
simCount: 1
|
|
337
|
+
createdAt: "2026-06-02T10:00:00.000Z"
|
|
338
|
+
artifactRoot: .humanish/runs/synthetic-run-bundle-2026-06-02t10-00-00-000z-proof
|
|
339
|
+
source:
|
|
340
|
+
packageName: fixture-app
|
|
341
|
+
humanishSource: present
|
|
342
|
+
git:
|
|
343
|
+
schema: humanish.git-state.v1
|
|
344
|
+
status: clean
|
|
345
|
+
capturedAt: "2026-06-02T10:00:00.000Z"
|
|
346
|
+
head:
|
|
347
|
+
shortSha: null
|
|
348
|
+
refState: unknown
|
|
349
|
+
changes:
|
|
350
|
+
staged: 0
|
|
351
|
+
unstaged: 0
|
|
352
|
+
untracked: 0
|
|
353
|
+
total: 0
|
|
354
|
+
note: public-safe synthetic fixture
|
|
355
|
+
persona:
|
|
356
|
+
id: synthetic-maintainer
|
|
357
|
+
name: Synthetic Maintainer
|
|
358
|
+
source: humanish/personas/synthetic-maintainer.yaml
|
|
359
|
+
sourceDigest: synthetic
|
|
360
|
+
scenario:
|
|
361
|
+
id: first-run-smoke
|
|
362
|
+
title: First-run smoke
|
|
363
|
+
goal: Prove setup and verification without private data.
|
|
364
|
+
source: humanish/scenarios/first-run-smoke.yaml
|
|
365
|
+
sourceDigest: synthetic
|
|
366
|
+
lifecycle:
|
|
367
|
+
- at: "2026-06-02T10:00:00.000Z"
|
|
368
|
+
event: run.created
|
|
369
|
+
message: Created synthetic contract fixture.
|
|
370
|
+
redaction:
|
|
371
|
+
status: passed
|
|
372
|
+
notes: Synthetic fixture only.
|
|
373
|
+
artifacts:
|
|
374
|
+
run: run.json
|
|
375
|
+
reviewJson: review.json
|
|
376
|
+
reviewMarkdown: review.md
|
|
377
|
+
observerData: observer/observer-data.json
|
|
378
|
+
events: events.ndjson
|
|
379
|
+
review:
|
|
380
|
+
schema: humanish.review.v1
|
|
381
|
+
verdict: contract_proof_only
|
|
382
|
+
summary: Synthetic contract fixture generated.
|
|
383
|
+
gaps: []
|
|
384
|
+
feedbackCandidates: []
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
## Shared-World Evidence
|
|
388
|
+
|
|
389
|
+
The shared-world topology (#164) is the DECLARED override of the per-lane-worlds
|
|
390
|
+
default: N distinct actor ROLES drive ONE provisioned, mutable service plane (one
|
|
391
|
+
app + one seeded DB) so their actions interact through shared state. The ONE
|
|
392
|
+
subject plane is provisioned via `subject.source: clone` (a fresh `git clone`) or
|
|
393
|
+
`subject.source: local-tree` (the operator's own working tree, packed on the host
|
|
394
|
+
and provisioned in-sandbox in place of a clone - see `subject.localTree` above);
|
|
395
|
+
both sources are accepted on the sequential AND concurrent shared-world routes. A
|
|
396
|
+
shared-world bundle adds TWO additive, optional fields to `humanish.run-bundle.v1`
|
|
397
|
+
(absent on every other bundle, so they stay byte-stable):
|
|
398
|
+
|
|
399
|
+
- `attributionClass: isolated | shared-world` — a new, ORTHOGONAL honesty axis
|
|
400
|
+
("how well did the run attribute INTERACTION?"), distinct from the persona-sampling
|
|
401
|
+
evidence classes ("how representative is the actor?"). Absent == `isolated`.
|
|
402
|
+
- `sharedWorld` (`humanish.shared-world.v1`): TWO variants discriminated by
|
|
403
|
+
`topologyMode: "sequential" | "concurrent"` (validateSharedWorldEvidence branches on
|
|
404
|
+
it FIRST; unknown/missing or a mismatched shape fails closed). Common fields:
|
|
405
|
+
- `topology: shared-world`
|
|
406
|
+
- `topologyMode: sequential | concurrent`
|
|
407
|
+
- `roleCount` — the DECLARED number of role/persona seats.
|
|
408
|
+
- `plane: { commit?, seedDigest, envNames, hostDigest?, exposure? }` — the ONE
|
|
409
|
+
shared-plane provenance. `seedDigest` is the sha256-16 of the ordered seed-step
|
|
410
|
+
command digests (the seed RECIPE identity, not the runtime state); `envNames` are
|
|
411
|
+
NAMES only. `hostDigest`/`exposure` are CONCURRENT-only (below).
|
|
412
|
+
- `attributionLimits: [...]` — the verify-enforced attribution ceiling (the set
|
|
413
|
+
differs per `topologyMode`, below).
|
|
414
|
+
|
|
415
|
+
SEQUENTIAL shape (`topologyMode: sequential`, #164 PR1):
|
|
416
|
+
- `sequence: [roleId, …]` — the role ids that actually took a turn, in declared order.
|
|
417
|
+
- `timeline: (checkpoint | turn)[]` — a harness-clocked, strictly alternating
|
|
418
|
+
timeline that starts `cp-baseline`, alternates checkpoint → turn → checkpoint,
|
|
419
|
+
and ends on a checkpoint:
|
|
420
|
+
- checkpoint = `{ kind: checkpoint, name, digest, deltaFromPrev }` — `digest` is
|
|
421
|
+
sha256-16(scrub+redact(probe stdout)); the record is DIGEST-ONLY (no
|
|
422
|
+
value-shaped field). `deltaFromPrev` is true when the observed state changed
|
|
423
|
+
across the intervening turn.
|
|
424
|
+
- turn = `{ kind: turn, roleId, simId, streamId, commit?, seedDigest }` — references
|
|
425
|
+
a real RunSimulation/RunStream; carries the plane provenance it observed
|
|
426
|
+
(identical across turns by construction — the single-plane proof).
|
|
427
|
+
- Sequential `attributionLimits` MUST contain `sequential-only`, `no-concurrent-races`,
|
|
428
|
+
and `delta-attributed-to-turn-not-action`.
|
|
429
|
+
|
|
430
|
+
CONCURRENT shape (`topologyMode: concurrent`, #164 phase 2 — N personas drive ONE
|
|
431
|
+
getHost-exposed plane AT ONCE; NO `timeline`/`sequence`):
|
|
432
|
+
- `plane.hostDigest` — sha256-16 of the harness-minted `getHost` ORIGIN every actor
|
|
433
|
+
drove (a first-class provisioned-subject target — invariant 2). A DIGEST, not the raw
|
|
434
|
+
URL: a getHost URL embeds the live sandbox id and matches the publish-safety e2b-URL
|
|
435
|
+
redaction, so it never lands raw in a published bundle (the raw tokenless URL is
|
|
436
|
+
surfaced only on the ephemeral lab result). The orchestrator confirms the URL is
|
|
437
|
+
TOKENLESS (no authKey — invariant 1) before digesting.
|
|
438
|
+
- `plane.exposure: synthetic` — the REQUIRED author attestation that the subject behind
|
|
439
|
+
the internet-reachable getHost URL is synthetic seeded data (author-trust + a
|
|
440
|
+
provenance gate, NOT a no-real-data guarantee).
|
|
441
|
+
- `laneWindows: [{ roleId, simId, streamId, startedAt, endedAt, verdict, routeHostDigest,
|
|
442
|
+
commit?, seedDigest }]` — one harness-clocked window per actor; OVERLAPPING windows
|
|
443
|
+
prove ≥2 personas were active simultaneously. `routeHostDigest` == `plane.hostDigest`
|
|
444
|
+
(every actor drove exactly the harness-minted host).
|
|
445
|
+
- `stateSeries: [{ timestamp, digest }]` — cadence digests of the shared world under
|
|
446
|
+
load (baseline + periodic + final). DIGEST-ONLY: the allowed-keys tripwire permits
|
|
447
|
+
ONLY `timestamp` + `digest` (no per-delta→actor field — causation under concurrency is
|
|
448
|
+
structurally inexpressible).
|
|
449
|
+
- `outcomes: [{ roleId, simId, streamId, status, completionReason?, ok }]` — per-persona
|
|
450
|
+
OUTCOME (the "M of N succeeded" headline).
|
|
451
|
+
- Concurrent `attributionLimits` MUST contain `concurrent`,
|
|
452
|
+
`best-effort-causal-attribution`, `non-deterministic-shared-state`,
|
|
453
|
+
`window-and-snapshot-granularity`, `contention-observed-not-proven-safe`,
|
|
454
|
+
`state-change-not-isolated-to-actors`, and MUST NOT contain `sequential-only` or
|
|
455
|
+
`no-concurrent-races` (a sequential guarantee on a concurrent run is an overclaim).
|
|
456
|
+
|
|
457
|
+
The `shared-world evidence` check in `humanish verify` is fail-closed (live runs only;
|
|
458
|
+
dry-run contract bundles are skipped). It dispatches on `topologyMode` FIRST.
|
|
459
|
+
SEQUENTIAL: the timeline must be well-formed (start `cp-baseline`, strictly alternate,
|
|
460
|
+
end on a checkpoint, turn order == sequence, sequence length == roleCount == turn
|
|
461
|
+
count, no `laneWindows`); every turn's simId/streamId resolves; every checkpoint digest
|
|
462
|
+
is sha256-16 with NO value-shaped field; all turns share ONE plane provenance; the
|
|
463
|
+
mandatory limits are present; and a PASSED run shows ≥1 checkpoint `deltaFromPrev` (the
|
|
464
|
+
delta-on-pass gate). CONCURRENT: no `timeline`; laneWindows + stateSeries + outcomes
|
|
465
|
+
cover exactly roleCount; the required limits are present AND the forbidden ones absent;
|
|
466
|
+
`plane.hostDigest` present and every `routeHostDigest` equals it (invariant 2);
|
|
467
|
+
`plane.exposure == synthetic` AND `subject.state.provenance == seeded` (the
|
|
468
|
+
synthetic-subject gate); stateSeries snapshots are digest-only (allowed-keys tripwire);
|
|
469
|
+
all laneWindows share ONE plane provenance; and the CONCURRENCY-ON-PASS gate — a PASSED
|
|
470
|
+
run MUST show ≥2 overlapping laneWindows AND a stateSeries delta whose timestamp is
|
|
471
|
+
AT/AFTER an overlap interval start (otherwise it was not actually concurrent, or the
|
|
472
|
+
world never changed under load). The per-role no-engagement guard applies to both.
|
|
473
|
+
Checkpoints / stateSeries persist digest-only by DEFAULT until the #108 PII/PHI
|
|
474
|
+
detector lands.
|
|
475
|
+
|
|
476
|
+
WHAT THE BUNDLE CAN / CANNOT CLAIM. SEQUENTIAL: each role's own behavior at full
|
|
477
|
+
fidelity; the OBSERVED system outcome as an ordered DIGEST sequence; and the
|
|
478
|
+
SEQUENCED-INTERACTION proof (role B entered a world already containing role A's mutation
|
|
479
|
+
— the checkpoint after A strictly precedes B's turn). It CANNOT claim action-granular
|
|
480
|
+
causation, concurrency/races (sequential-only), or exact-state determinism. CONCURRENT:
|
|
481
|
+
each persona's own behavior at full fidelity; per-persona OUTCOME against the contended
|
|
482
|
+
world ("M of N"); PROVEN CONCURRENCY (overlapping windows); and system-state evolution
|
|
483
|
+
under load (the stateSeries) with best-effort temporal correlation. It CANNOT claim
|
|
484
|
+
strict causal attribution of a delta to an actor (concurrent ⇒ ambiguous), determinism
|
|
485
|
+
of exact state, per-action granularity, or concurrency-SAFETY (races are OBSERVED, never
|
|
486
|
+
PROVEN absent). HONESTY: the deterministic $0 gate proves the plumbing + the attribution
|
|
487
|
+
contract; the concurrency CAPABILITY at scale is backed only by a separately-authorized
|
|
488
|
+
live receipt.
|
|
489
|
+
|
|
490
|
+
## Adapter
|
|
491
|
+
|
|
492
|
+
Adapters describe target-specific affordances without changing core contracts.
|
|
493
|
+
|
|
494
|
+
Core-owned fields:
|
|
495
|
+
|
|
496
|
+
- `schema`
|
|
497
|
+
- `id`
|
|
498
|
+
- normalized route/reference shape
|
|
499
|
+
- public-safety validation of adapter references
|
|
500
|
+
|
|
501
|
+
Adapter-owned fields:
|
|
502
|
+
|
|
503
|
+
- `name`
|
|
504
|
+
- `routes`
|
|
505
|
+
- route descriptions
|
|
506
|
+
- target-specific commands, paths, milestones, and vocabulary
|
|
507
|
+
|
|
508
|
+
Synthetic fixture:
|
|
509
|
+
|
|
510
|
+
```yaml
|
|
511
|
+
schema: humanish.adapter.v1
|
|
512
|
+
id: synthetic-cli-adapter
|
|
513
|
+
name: Synthetic CLI Adapter
|
|
514
|
+
routes:
|
|
515
|
+
- id: help
|
|
516
|
+
path: synthetic-cli --help
|
|
517
|
+
description: Public-safe command discovery.
|
|
518
|
+
- id: dry-run
|
|
519
|
+
path: synthetic-cli run --dry-run --json
|
|
520
|
+
description: Generate a synthetic run bundle.
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
## Persona And Scenario
|
|
524
|
+
|
|
525
|
+
Personas and scenarios define trial intent. They are adapter-owned source
|
|
526
|
+
documents that core copies into run bundles by digest and id.
|
|
527
|
+
|
|
528
|
+
Core-owned fields:
|
|
529
|
+
|
|
530
|
+
- schema naming rules
|
|
531
|
+
- id/source/sourceDigest references inside run bundles
|
|
532
|
+
- redaction gates before persona/scenario text can appear in public feedback
|
|
533
|
+
|
|
534
|
+
Adapter-owned fields:
|
|
535
|
+
|
|
536
|
+
- persona traits
|
|
537
|
+
- scenario goals
|
|
538
|
+
- steps and expectations
|
|
539
|
+
- accessibility or workflow constraints
|
|
540
|
+
|
|
541
|
+
Synthetic fixture:
|
|
542
|
+
|
|
543
|
+
```yaml
|
|
544
|
+
persona:
|
|
545
|
+
schema: humanish.persona.v1
|
|
546
|
+
id: synthetic-maintainer
|
|
547
|
+
name: Synthetic Maintainer
|
|
548
|
+
summary: Privacy-safe maintainer evaluating first-run clarity.
|
|
549
|
+
constraints:
|
|
550
|
+
- Do not use real personal data.
|
|
551
|
+
- Treat credentials as env var names only.
|
|
552
|
+
scenario:
|
|
553
|
+
schema: humanish.scenario.v1
|
|
554
|
+
id: first-run-smoke
|
|
555
|
+
title: First-run smoke
|
|
556
|
+
persona: synthetic-maintainer
|
|
557
|
+
goal: Prove setup, dry-run evidence, verification, and feedback drafting.
|
|
558
|
+
mode: dry-run
|
|
559
|
+
steps:
|
|
560
|
+
- name: Inspect help
|
|
561
|
+
expectation: Help explains setup and verification commands.
|
|
562
|
+
- name: Verify bundle
|
|
563
|
+
expectation: Verification passes without private data.
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
## Actor Trace
|
|
567
|
+
|
|
568
|
+
Actors execute or simulate the trial. Actor evidence is the provider-neutral
|
|
569
|
+
`humanish.actor-trace.v1` (`src/actor-contract.ts`): Codex app-server items,
|
|
570
|
+
Claude Agent SDK blocks, pi events, computer-use cycles, scripted browser
|
|
571
|
+
steps, and in-sandbox terminal-agent exec output all map onto one `ActorTrace`.
|
|
572
|
+
Registered actors live in
|
|
573
|
+
`src/actor-registry.ts` (`codex-app-server`, `pi-agent-core`,
|
|
574
|
+
`claude-agent-sdk`, `openai-computer-use`, `scripted-browser`, `codex-exec`).
|
|
575
|
+
There is no `humanish.actor.v1`; that name never shipped.
|
|
576
|
+
|
|
577
|
+
Core-owned fields:
|
|
578
|
+
|
|
579
|
+
- `schema`
|
|
580
|
+
- `provider` / `providerVersion`
|
|
581
|
+
- `protocol` (`json-rpc` | `json-stream` | `in-process-sdk` | `cua-loop` |
|
|
582
|
+
`scripted-steps` | `terminal-exec`)
|
|
583
|
+
- `lane` (`code` | `app` | `computer-use` | `scripted-browser` | `terminal`)
|
|
584
|
+
- `persona` (`id`, `traitsApplied`, `promptDigest`)
|
|
585
|
+
- `capabilities.keyPlacement` (`external` | `in-sandbox-command-scoped`): WHERE
|
|
586
|
+
the actor's runtime key lives — registry metadata the engine enforces. The
|
|
587
|
+
terminal agent declares `in-sandbox-command-scoped` (the agent-under-test runs
|
|
588
|
+
inside the sandbox); every other actor is `external` (absent === external).
|
|
589
|
+
- `redaction` (`status`, `screenshots: n/a|raw|blurred|ocr_scrubbed`, `notes`)
|
|
590
|
+
- `startedAt` / `completedAt` / `durationMs`
|
|
591
|
+
- `status` / `completionReason` / `reason` (`completionReason` includes
|
|
592
|
+
`step_failed`: a deterministic scripted step/expectation evaluated false —
|
|
593
|
+
the subject failed the script while the harness executed faithfully)
|
|
594
|
+
- `ids`, `counts`, `items[]`, optional `tokenUsage`, `capabilities`
|
|
595
|
+
|
|
596
|
+
Unexpected actor-loop diagnostics live inside `items[]` as
|
|
597
|
+
`kind: notice`, `status: error` rows. They are public-safe evidence, not crash
|
|
598
|
+
dumps: redacted message, coarse phase, optional error name, last normalized UI
|
|
599
|
+
action, and last screenshot reference. They must not carry raw stacks, env
|
|
600
|
+
values, target URLs, or unredacted provider payloads.
|
|
601
|
+
|
|
602
|
+
Adapter-owned fields:
|
|
603
|
+
|
|
604
|
+
- the prompt, mission, persona text, and lane focus that produced the trace
|
|
605
|
+
- product-specific acceptance notes
|
|
606
|
+
|
|
607
|
+
Synthetic fixture (abridged; see `src/actor-contract.ts` for the full type):
|
|
608
|
+
|
|
609
|
+
```yaml
|
|
610
|
+
schema: humanish.actor-trace.v1
|
|
611
|
+
provider: codex-app-server
|
|
612
|
+
protocol: json-rpc
|
|
613
|
+
lane: code
|
|
614
|
+
persona:
|
|
615
|
+
id: synthetic-maintainer
|
|
616
|
+
traitsApplied: []
|
|
617
|
+
promptDigest: synthetic
|
|
618
|
+
redaction:
|
|
619
|
+
status: passed
|
|
620
|
+
screenshots: n/a
|
|
621
|
+
notes: Synthetic fixture only.
|
|
622
|
+
startedAt: "2026-06-02T10:00:00.000Z"
|
|
623
|
+
completedAt: "2026-06-02T10:00:01.000Z"
|
|
624
|
+
durationMs: 1000
|
|
625
|
+
status: passed
|
|
626
|
+
completionReason: turn_completed
|
|
627
|
+
reason: Synthetic dry-run fixture completed.
|
|
628
|
+
ids: {}
|
|
629
|
+
counts: {}
|
|
630
|
+
items: []
|
|
631
|
+
```
|
|
632
|
+
|
|
633
|
+
## Substrate
|
|
634
|
+
|
|
635
|
+
Reserved: `humanish.substrate.v1` is named here for layering intent but has
|
|
636
|
+
never shipped — no code emits or validates it. Substrate truth today lives
|
|
637
|
+
inside run bundles (per-stream transport and status) and lab execution config
|
|
638
|
+
(`execution.target: local | e2b-desktop`). Do not emit this schema.
|
|
639
|
+
|
|
640
|
+
## Terminal Cost Ledger And No-Spend Proof
|
|
641
|
+
|
|
642
|
+
The terminal-product lane (`src/e2b-terminal-lab.ts`) places a real provider key
|
|
643
|
+
INSIDE the sandbox, so the no-spend claim must be REAL — derived from a ledger,
|
|
644
|
+
never asserted. The live run writes both to `terminal-ledgers.json` (a `cost`
|
|
645
|
+
block + a `noSpendProof` block, additive to `humanish.terminal-ledgers.v1`).
|
|
646
|
+
|
|
647
|
+
The cost ledger (`humanish.terminal-cost-ledger.v1`) has one line per category —
|
|
648
|
+
`product`, `media`, `payment`, `provider` — and follows a strict **null
|
|
649
|
+
discipline** that distinguishes three states and never conflates them:
|
|
650
|
+
|
|
651
|
+
- `usd: 0` — **known zero**: the category was metered and billed nothing.
|
|
652
|
+
- `usd: null` — **not measured**: no spend signal exists for the category this
|
|
653
|
+
slice. `null` is written explicitly (never `undefined`-omitted, never guessed
|
|
654
|
+
to `0`). A line with `null` says "this category exists but we did not measure
|
|
655
|
+
it"; the no-spend proof reports it as unmeasured and does NOT claim it is zero.
|
|
656
|
+
- line **absent** — **not applicable** (n/a) to the lane/run.
|
|
657
|
+
|
|
658
|
+
`knownTotalUsd` sums ONLY the non-null lines (a `null` line contributes nothing
|
|
659
|
+
and is never coerced to `0`); `fullyMeasured` is true only when no line is null.
|
|
660
|
+
This slice meters only the `provider` line, populated from the actor trace's
|
|
661
|
+
`tokenUsage.costUsd` when present (else `null`); `product`/`media`/`payment` are
|
|
662
|
+
`null` until the SLICE-4 adapter supplies them.
|
|
663
|
+
|
|
664
|
+
```yaml
|
|
665
|
+
schema: humanish.terminal-cost-ledger.v1
|
|
666
|
+
currency: usd
|
|
667
|
+
lines:
|
|
668
|
+
product: { usd: null, count: null, source: unmeasured, note: "…no signal yet…" }
|
|
669
|
+
media: { usd: null, count: null, source: unmeasured, note: "…no signal yet…" }
|
|
670
|
+
payment: { usd: null, count: null, source: unmeasured, note: "…no signal yet…" }
|
|
671
|
+
provider: { usd: null, source: unmeasured, note: "…no tokenUsage.costUsd this run…" }
|
|
672
|
+
knownTotalUsd: 0
|
|
673
|
+
fullyMeasured: false
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
The no-spend proof (`humanish.terminal-no-spend-proof.v1`) is DERIVED from the
|
|
677
|
+
ledger. It vouches only for what it measured: `knownZeroLines` (proven zero),
|
|
678
|
+
`knownNonZeroLines` (break `satisfied`), and `unmeasuredLines` (the `null` lines
|
|
679
|
+
it explicitly CANNOT vouch for). `satisfied` is true only when every KNOWN line
|
|
680
|
+
is within `maxUsd` (for a no-spend run, `maxUsd: 0` ⇒ every known line is `0`);
|
|
681
|
+
unmeasured lines never make it satisfied. A proof never claims zero on a `null`
|
|
682
|
+
line — verification fails closed if it does.
|
|
683
|
+
|
|
684
|
+
```yaml
|
|
685
|
+
schema: humanish.terminal-no-spend-proof.v1
|
|
686
|
+
maxUsd: 0
|
|
687
|
+
satisfied: true
|
|
688
|
+
knownZeroLines: []
|
|
689
|
+
knownNonZeroLines: []
|
|
690
|
+
unmeasuredLines: [product, media, payment, provider]
|
|
691
|
+
knownTotalUsd: 0
|
|
692
|
+
statement: "No-spend proof SATISFIED for maxUsd=0: every MEASURED spend line is zero…"
|
|
693
|
+
```
|
|
694
|
+
|
|
695
|
+
**Full caps enforcement (fail-closed, not advisory).** `scenario.caps.maxUsd`
|
|
696
|
+
is enforced against the ledger: if the observed KNOWN spend exceeds `maxUsd`, the
|
|
697
|
+
run fails closed (`HUMANISH_TERMINAL_LAB_CAPS_EXCEEDED`); `maxJobs` likewise when
|
|
698
|
+
a known job count is present; `maxMinutes` is the wall-clock kill (unchanged).
|
|
699
|
+
Unknowns (`null`) never trip a cap (we cannot claim a violation we did not
|
|
700
|
+
measure) and never grant a green pass (they surface as unmeasured). `verifyRun`
|
|
701
|
+
fails closed when a live bundle lacks the cost ledger or no-spend proof, when the
|
|
702
|
+
proof claims zero on a `null` line, or when known spend exceeds the declared cap.
|
|
703
|
+
|
|
704
|
+
## Product-Adapter Extension Seam
|
|
705
|
+
|
|
706
|
+
The terminal-product and browser/computer-use lanes let an adopter attach
|
|
707
|
+
product-specific scoring + feedback as a THIN in-repo extension WITHOUT forking
|
|
708
|
+
core. The seam is the EXPORTED contract types plus DI hooks:
|
|
709
|
+
`TerminalProductLabHooks` for terminal-product runs, and the browser adapter
|
|
710
|
+
hooks inherited by `CuaActorLabHooks` / `SharedWorldLabHooks` for CUA,
|
|
711
|
+
sequential shared-world, and concurrent shared-world runs. This is never a
|
|
712
|
+
built-in product scorer (the adopter's scorecard lives in the adopter's repo).
|
|
713
|
+
|
|
714
|
+
Three product-agnostic carriers keep core's nouns closed while letting the adapter
|
|
715
|
+
record its own:
|
|
716
|
+
|
|
717
|
+
- **Adapter score** (`humanish.adapter-score.v1`, `RunBundle.adapterScore`).
|
|
718
|
+
A namespaced summary the adapter's `score` hook returns: `{ schema, namespace,
|
|
719
|
+
status, score, summary, data? }`. Core never reads `data` — the adopter's
|
|
720
|
+
component rubric rides there; `namespace` (an adopter slug) scopes the whole
|
|
721
|
+
record so a future inert-field audit never misfires.
|
|
722
|
+
- **Namespaced product-noun block** (`RunFeedbackCandidate.adapter`). The
|
|
723
|
+
adapter's `deriveFeedback` hook returns feedback candidates that satisfy core's
|
|
724
|
+
feedback-candidate shape; product-specific concepts (public CLI/product command
|
|
725
|
+
observed, hosted product success-or-blocker, feedback id/draft, media/job/asset
|
|
726
|
+
ids, explicit no-media/no-provider-spend proof, defection/friction risk) are
|
|
727
|
+
recorded ONLY under `adapter: { namespace, data }` — never as core enums. Core
|
|
728
|
+
validates the SHAPE (a non-empty `namespace` + a `data` record); the keys inside
|
|
729
|
+
`data` are the adapter's.
|
|
730
|
+
- **Adapter artifacts** (`humanish.adapter-artifact.v1`,
|
|
731
|
+
`RunBundle.adapterArtifacts[]`). A namespaced list of local relative artifact
|
|
732
|
+
references the adapter's `deriveArtifacts` hook returns after writing
|
|
733
|
+
product/state proof files under the ignored run directory. Core validates only
|
|
734
|
+
schema/namespace/label/path/kind/note and local-path safety, Observer links the
|
|
735
|
+
artifacts, and `verifyRun` fails closed if a referenced file is missing.
|
|
736
|
+
|
|
737
|
+
```yaml
|
|
738
|
+
# RunBundle.adapterScore (namespaced; data is the adopter's, core never reads it)
|
|
739
|
+
schema: humanish.adapter-score.v1
|
|
740
|
+
namespace: adopter-slug
|
|
741
|
+
status: pass
|
|
742
|
+
score: 88
|
|
743
|
+
summary: Product study scored by the adopter's own rubric.
|
|
744
|
+
data: { productRubric: { discovery: 1, firstImage: 1 }, hostedProductSucceeded: true }
|
|
745
|
+
```
|
|
746
|
+
|
|
747
|
+
```yaml
|
|
748
|
+
# RunFeedbackCandidate.adapter — product nouns stay NON-core under the namespace
|
|
749
|
+
adapter:
|
|
750
|
+
namespace: adopter-slug
|
|
751
|
+
data:
|
|
752
|
+
publicCommandObserved: "product generate --prompt '…'"
|
|
753
|
+
hostedProductOutcome: success
|
|
754
|
+
feedbackId: null
|
|
755
|
+
mediaJobIds: []
|
|
756
|
+
noMediaSpendProof: { mediaUsd: null, providerUsd: 0 }
|
|
757
|
+
defectionFrictionRisk: low
|
|
758
|
+
```
|
|
759
|
+
|
|
760
|
+
```yaml
|
|
761
|
+
# RunBundle.adapterArtifacts — product/state proof payloads stay adapter-owned
|
|
762
|
+
- schema: humanish.adapter-artifact.v1
|
|
763
|
+
namespace: adopter-slug
|
|
764
|
+
label: Product state readback
|
|
765
|
+
path: adapter/product-state-readback.json
|
|
766
|
+
kind: state
|
|
767
|
+
note: Adapter-owned product/state proof.
|
|
768
|
+
```
|
|
769
|
+
|
|
770
|
+
Acceptance semantics are route-specific:
|
|
771
|
+
|
|
772
|
+
- Terminal-product runs keep the mission-based `review` verdict unchanged; the
|
|
773
|
+
adapter score is additive because the route is a public-product study lane.
|
|
774
|
+
- Browser/computer-use runs treat `adapterScore.status: fail` as product-red:
|
|
775
|
+
the bundle keeps the adapter score, `review.verdict` becomes `fail` when it
|
|
776
|
+
was pass-like, a generic adapter gap is appended, and the route result returns
|
|
777
|
+
`ok: false`. This closes the false-positive class where a generic actor reaches
|
|
778
|
+
a terminal session but an adopter scorer finds no product-visible completion
|
|
779
|
+
evidence.
|
|
780
|
+
|
|
781
|
+
The `e2b-terminal` substrate is added to `RunFeedbackCandidate.substrate` so a
|
|
782
|
+
terminal-agent candidate names its substrate honestly; browser candidates use
|
|
783
|
+
the existing `e2b-desktop` substrate. Lanes invoke hooks over FULLY-ASSEMBLED,
|
|
784
|
+
redacted evidence (`TerminalProductScoringContext` or
|
|
785
|
+
`BrowserLabScoringContext`: `bundle`, runtime-only `runDir`, run identifiers,
|
|
786
|
+
actor/backend metadata; all exported public types), scrub+redact returned
|
|
787
|
+
payloads, and DROP any malformed score, candidate, or artifact reference with a
|
|
788
|
+
warning so a bad extension never poisons a verifiable bundle. Default behavior
|
|
789
|
+
(no hook) is unchanged. `verifyRun` re-checks the surviving shapes fail-closed,
|
|
790
|
+
including existence for referenced adapter artifacts.
|
|
791
|
+
|
|
792
|
+
## Evidence Streams
|
|
793
|
+
|
|
794
|
+
Reserved: `humanish.evidence-stream.v1` has never shipped as a standalone
|
|
795
|
+
schema, and streams are not standalone artifacts. They are the `streams` array
|
|
796
|
+
inside `humanish.run-bundle.v1`, normalizing UI, browser, terminal, TUI,
|
|
797
|
+
code-agent UI, artifact, and summary lanes — each with transport, terminal
|
|
798
|
+
tail, completion, meaningful-use verdicts, and artifact pointers. See
|
|
799
|
+
[`run-bundle.md`](run-bundle.md#completion-and-meaningful-use-verdicts) for
|
|
800
|
+
the stream shape, the meaningful-use rubric, and hard-failure rules.
|
|
801
|
+
|
|
802
|
+
## Review
|
|
803
|
+
|
|
804
|
+
Review summarizes whether evidence supports the claim. It does not replace
|
|
805
|
+
verification or maintainer acceptance.
|
|
806
|
+
|
|
807
|
+
Core-owned fields:
|
|
808
|
+
|
|
809
|
+
- `schema`
|
|
810
|
+
- `verdict`
|
|
811
|
+
- `summary`
|
|
812
|
+
- `gaps`
|
|
813
|
+
|
|
814
|
+
Adapter-owned fields:
|
|
815
|
+
|
|
816
|
+
- vocabulary labels
|
|
817
|
+
- milestone names
|
|
818
|
+
- product-specific gap language
|
|
819
|
+
|
|
820
|
+
Synthetic fixture:
|
|
821
|
+
|
|
822
|
+
```yaml
|
|
823
|
+
schema: humanish.review.v1
|
|
824
|
+
verdict: contract_proof_only
|
|
825
|
+
summary: Synthetic dry-run proves bundle shape, not product behavior.
|
|
826
|
+
gaps:
|
|
827
|
+
- Live product behavior was not exercised.
|
|
828
|
+
```
|
|
829
|
+
|
|
830
|
+
## Verification
|
|
831
|
+
|
|
832
|
+
Verification checks bundles and evidence pointers. It fails closed when schema,
|
|
833
|
+
redaction, or artifacts are missing.
|
|
834
|
+
|
|
835
|
+
Core-owned fields:
|
|
836
|
+
|
|
837
|
+
- `schema`
|
|
838
|
+
- `ok`
|
|
839
|
+
- `run`
|
|
840
|
+
- `bundlePath`
|
|
841
|
+
- check names
|
|
842
|
+
- check booleans
|
|
843
|
+
- `warnings` (advisory postures, e.g. raw screenshots; never flip `ok`)
|
|
844
|
+
- machine-readable error codes
|
|
845
|
+
|
|
846
|
+
Adapter-owned fields:
|
|
847
|
+
|
|
848
|
+
- optional target-specific checks
|
|
849
|
+
- acceptance proof commands
|
|
850
|
+
- coverage-specific check names
|
|
851
|
+
|
|
852
|
+
Synthetic fixture:
|
|
853
|
+
|
|
854
|
+
```yaml
|
|
855
|
+
schema: humanish.verify-result.v1
|
|
856
|
+
ok: true
|
|
857
|
+
run: synthetic-run-bundle-2026-06-02t10-00-00-000z-proof
|
|
858
|
+
bundlePath: .humanish/runs/synthetic-run-bundle-2026-06-02t10-00-00-000z-proof/run.json
|
|
859
|
+
checks:
|
|
860
|
+
- name: run.json exists
|
|
861
|
+
ok: true
|
|
862
|
+
message: run.json present
|
|
863
|
+
- name: redaction passed
|
|
864
|
+
ok: true
|
|
865
|
+
message: redaction status must be passed
|
|
866
|
+
shareSafety:
|
|
867
|
+
status: share_ready
|
|
868
|
+
reasons: []
|
|
869
|
+
```
|
|
870
|
+
|
|
871
|
+
## Policy
|
|
872
|
+
|
|
873
|
+
Policy names boundaries before an actor runs or feedback is promoted.
|
|
874
|
+
`humanish.policy.v1` exists today only as an adapter fixture shape
|
|
875
|
+
(`adapters/fixtures/`); the engine does not validate it. The committed policy
|
|
876
|
+
source files scaffolded by `humanish init` use `humanish.redaction-policy.v1`,
|
|
877
|
+
`humanish.network-policy.v1`, and `humanish.credentials-policy.v1`.
|
|
878
|
+
|
|
879
|
+
Core-owned fields:
|
|
880
|
+
|
|
881
|
+
- `schema`
|
|
882
|
+
- policy kind
|
|
883
|
+
- default action
|
|
884
|
+
- validation outcome
|
|
885
|
+
- redaction status
|
|
886
|
+
- no-secret-value persistence rules
|
|
887
|
+
|
|
888
|
+
Adapter-owned fields:
|
|
889
|
+
|
|
890
|
+
- allowed env var names
|
|
891
|
+
- allowed public hosts
|
|
892
|
+
- app-specific credential manifest
|
|
893
|
+
- network allowlist
|
|
894
|
+
- scenario-specific authority
|
|
895
|
+
|
|
896
|
+
Synthetic fixture:
|
|
897
|
+
|
|
898
|
+
```yaml
|
|
899
|
+
schema: humanish.policy.v1
|
|
900
|
+
kind: public-safety
|
|
901
|
+
default: deny_sensitive_material
|
|
902
|
+
deny:
|
|
903
|
+
- pii
|
|
904
|
+
- phi
|
|
905
|
+
- secrets
|
|
906
|
+
- tokens
|
|
907
|
+
- raw_private_transcripts
|
|
908
|
+
- private_screenshots
|
|
909
|
+
allow:
|
|
910
|
+
- synthetic_personas
|
|
911
|
+
- synthetic_fixtures
|
|
912
|
+
- env_var_names
|
|
913
|
+
credentialManifest:
|
|
914
|
+
- envName: OPENAI_API_KEY
|
|
915
|
+
valuePersisted: false
|
|
916
|
+
network:
|
|
917
|
+
default: local_only
|
|
918
|
+
allowedHosts:
|
|
919
|
+
- localhost
|
|
920
|
+
```
|
|
921
|
+
|
|
922
|
+
## Feedback
|
|
923
|
+
|
|
924
|
+
Feedback turns verified evidence into public-safe issue draft material. The
|
|
925
|
+
default public CLI prints issue text or a prefilled URL; it does not mutate
|
|
926
|
+
GitHub.
|
|
927
|
+
|
|
928
|
+
Core-owned fields:
|
|
929
|
+
|
|
930
|
+
- `schema`
|
|
931
|
+
- run/source/evidence pointers
|
|
932
|
+
- redaction status
|
|
933
|
+
- idempotency key
|
|
934
|
+
- proposed next state
|
|
935
|
+
- failure owner enum
|
|
936
|
+
- public issue eligibility gates
|
|
937
|
+
|
|
938
|
+
Adapter-owned fields:
|
|
939
|
+
|
|
940
|
+
- adapter id
|
|
941
|
+
- scenario id
|
|
942
|
+
- persona id
|
|
943
|
+
- expected/actual language
|
|
944
|
+
- target-specific reproduction steps
|
|
945
|
+
- acceptance proof commands
|
|
946
|
+
|
|
947
|
+
Synthetic fixture:
|
|
948
|
+
|
|
949
|
+
```yaml
|
|
950
|
+
schema: humanish.feedback.v1
|
|
951
|
+
run_id: synthetic-run-bundle-2026-06-02t10-00-00-000z-proof
|
|
952
|
+
adapter_id: synthetic-cli-adapter
|
|
953
|
+
scenario_id: first-run-smoke
|
|
954
|
+
persona_id: synthetic-maintainer
|
|
955
|
+
actor: synthetic-dry-run
|
|
956
|
+
substrate: local-filesystem
|
|
957
|
+
failure_owner: harness
|
|
958
|
+
summary: Synthetic user needed clearer verification instructions.
|
|
959
|
+
expected: Verification command is visible and public-safe.
|
|
960
|
+
actual: Dry-run review noted missing live behavior proof.
|
|
961
|
+
source_bundle: .humanish/runs/synthetic-run-bundle-2026-06-02t10-00-00-000z-proof/run.json
|
|
962
|
+
evidence:
|
|
963
|
+
- path: .humanish/runs/synthetic-run-bundle-2026-06-02t10-00-00-000z-proof/review.md
|
|
964
|
+
kind: review
|
|
965
|
+
note: Public-safe synthetic review.
|
|
966
|
+
redaction:
|
|
967
|
+
status: passed
|
|
968
|
+
notes: Synthetic fixture only.
|
|
969
|
+
idempotency_key: synthetic-cli-adapter:first-run-smoke:verification-instructions
|
|
970
|
+
proposed_next_state: watch
|
|
971
|
+
acceptance_proof:
|
|
972
|
+
- pnpm humanish -- verify --run latest --json
|
|
973
|
+
```
|
|
974
|
+
|
|
975
|
+
## Contract Stop Conditions
|
|
976
|
+
|
|
977
|
+
Do not promote a contract fixture when:
|
|
978
|
+
|
|
979
|
+
- it needs private artifact data to make sense;
|
|
980
|
+
- it contains credential values instead of env var names;
|
|
981
|
+
- it embeds raw hosted stream URLs or auth-bearing links;
|
|
982
|
+
- it uses product-specific private nouns in a core-owned schema;
|
|
983
|
+
- it implies GitHub mutation without explicit maintainer authority;
|
|
984
|
+
- it cannot be proven with `git diff --check` and public-surface scanning.
|