humanish 0.15.2 → 0.16.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 (59) hide show
  1. package/README.md +15 -7
  2. package/dist/actor-contract.d.ts +2 -3
  3. package/dist/actor-contract.js +6 -7
  4. package/dist/actor-contract.js.map +1 -1
  5. package/dist/actor-registry.d.ts +4 -4
  6. package/dist/actor-registry.js +8 -7
  7. package/dist/actor-registry.js.map +1 -1
  8. package/dist/artifact-reference.js +1 -1
  9. package/dist/artifact-reference.js.map +1 -1
  10. package/dist/concurrent-shared-world-lab.js +24 -11
  11. package/dist/concurrent-shared-world-lab.js.map +1 -1
  12. package/dist/cua-actor-lab.d.ts +101 -4
  13. package/dist/cua-actor-lab.js +456 -77
  14. package/dist/cua-actor-lab.js.map +1 -1
  15. package/dist/device-presets.d.ts +4 -4
  16. package/dist/device-presets.js +5 -5
  17. package/dist/device-presets.js.map +1 -1
  18. package/dist/e2b-terminal-lab.d.ts +18 -20
  19. package/dist/e2b-terminal-lab.js +28 -28
  20. package/dist/e2b-terminal-lab.js.map +1 -1
  21. package/dist/index.d.ts +1 -1
  22. package/dist/index.js.map +1 -1
  23. package/dist/lab-config.d.ts +27 -28
  24. package/dist/lab-config.js +6 -6
  25. package/dist/lab-config.js.map +1 -1
  26. package/dist/lab-engine.d.ts +1 -1
  27. package/dist/lab-engine.js +8 -10
  28. package/dist/lab-engine.js.map +1 -1
  29. package/dist/observer-assets.js +92 -15
  30. package/dist/observer-assets.js.map +1 -1
  31. package/dist/oss-meta-lab.js +2 -4
  32. package/dist/oss-meta-lab.js.map +1 -1
  33. package/dist/program.js +1 -1
  34. package/dist/program.js.map +1 -1
  35. package/dist/run.d.ts +38 -0
  36. package/dist/run.js +71 -1
  37. package/dist/run.js.map +1 -1
  38. package/dist/shared-world-lab.d.ts +20 -1
  39. package/dist/shared-world-lab.js +197 -23
  40. package/dist/shared-world-lab.js.map +1 -1
  41. package/dist/terminal-agent-actor.d.ts +12 -7
  42. package/dist/terminal-agent-actor.js +18 -16
  43. package/dist/terminal-agent-actor.js.map +1 -1
  44. package/docs/architecture/actor-contract.md +32 -21
  45. package/docs/architecture/observer.md +15 -9
  46. package/docs/architecture/state-driven-executor.md +3 -3
  47. package/docs/architecture/terminal-product-lane.md +29 -25
  48. package/docs/assets/humanish-drawdb-hero.png +0 -0
  49. package/docs/contracts/adapter-fixtures.md +4 -2
  50. package/docs/contracts/core.md +9 -4
  51. package/docs/contracts/feedback.md +4 -2
  52. package/docs/contracts/policy.md +5 -3
  53. package/docs/contracts/run-bundle.md +24 -3
  54. package/docs/contracts/schemas.md +34 -23
  55. package/docs/goals/current.md +69 -20
  56. package/docs/ramp/README.md +32 -13
  57. package/docs/release/open-source-readiness.md +5 -4
  58. package/docs/release/public-readiness-standard.md +6 -1
  59. package/package.json +1 -1
@@ -1,11 +1,15 @@
1
1
  import type { ActorPersonaRef, ActorStatus, ActorCompletionReason, ActorTrace } from "./actor-contract.js";
2
- /** The fail-closed marker a SLICE-1 live invocation surfaces (never a raw crash). */
2
+ /**
3
+ * Backward-compatible fail-closed marker for the intentionally unsupported direct runner.
4
+ * The name is retained because it is already exported public API.
5
+ */
3
6
  export declare const TERMINAL_AGENT_NOT_IMPLEMENTED_CODE: "HUMANISH_TERMINAL_AGENT_NOT_IMPLEMENTED";
4
7
  /**
5
8
  * Options the engine hands the terminal agent session. The transport is the captured
6
9
  * non-interactive exec stream (stdin disabled), NOT an interactive PTY — see ActorProtocol
7
- * "terminal-exec" and the goal packet's PTY ruling. Fields here are the SLICE-1 contract; SLICE 2
8
- * consumes them to drive the in-sandbox `codex exec` and capture its redacted output.
10
+ * "terminal-exec" and the goal packet's PTY ruling. This compatibility shape documents the
11
+ * descriptor boundary; the route-owned live implementation composes equivalent inputs with the
12
+ * additional provider, policy, cap, and cleanup controls it needs.
9
13
  */
10
14
  export interface TerminalAgentSessionOptions {
11
15
  /** Where the session writes its native trace/transcript/event-stream artifacts. */
@@ -16,7 +20,7 @@ export interface TerminalAgentSessionOptions {
16
20
  persona: ActorPersonaRef;
17
21
  /** The product's declared PUBLIC surfaces (http(s) URLs / refs) — the only world the agent sees. */
18
22
  publicSurfaces: string[];
19
- /** Session wall-clock budget (also bounded by scenario.caps.maxMinutes in SLICE 2). */
23
+ /** Session wall-clock budget (the route also requires scenario.caps.maxMinutes). */
20
24
  timeoutMs: number;
21
25
  /** Per-run verdict nonce: the agent must echo it so replayed text can't forge the verdict. */
22
26
  verdictNonce: string;
@@ -29,8 +33,9 @@ export interface TerminalAgentSessionResult {
29
33
  trace: ActorTrace;
30
34
  }
31
35
  /**
32
- * Registry-facing session entry. SLICE 1: NOT yet live the dry-run lab path never calls this,
33
- * and a live engine call fails closed with a structured error before reaching here. Calling it
34
- * directly throws the same fail-closed marker rather than pretending to drive a real agent.
36
+ * Backward-compatible registry entry. Direct execution is intentionally unsupported: only the
37
+ * terminal-product lab route owns enough context to enforce command-scoped auth, caps, evidence
38
+ * capture, and by-id cleanup together. Fail closed instead of implying that the descriptor method
39
+ * itself runs the shipped live route.
35
40
  */
36
41
  export declare function runTerminalAgentSession(_options: TerminalAgentSessionOptions): Promise<TerminalAgentSessionResult>;
@@ -1,23 +1,25 @@
1
- // The terminal agent actor: a real autonomous coding agent (Codex) discovering and using a
2
- // CLI/product from PUBLIC SURFACES ONLY, running INSIDE an E2B shell with command-scoped runtime
3
- // auth, capturing its non-interactive exec output (stdin disabled) as a redacted event stream +
4
- // normalized transcript. This is the registry seam for the terminal-product lane.
1
+ // Registry contract for the terminal-product lane. The shipped live implementation is
2
+ // intentionally route-owned by `runTerminalProductLab` in `e2b-terminal-lab.ts`: that route must
3
+ // coordinate sandbox creation, command-scoped runtime auth, caps, evidence capture, and by-id
4
+ // cleanup as one fail-closed lifecycle.
5
5
  //
6
- // SLICE 1 SCOPE (honest): this module declares the session CONTRACT — the option/result shapes
7
- // and the registry-facing `runTerminalAgentSession` entry but the LIVE session is NOT
8
- // implemented here yet. The dry-run lab path (src/e2b-terminal-lab.ts) never invokes runSession;
9
- // it builds a contract-only bundle. A live (non-dry-run) call into the engine returns a
10
- // structured "not yet implemented in this slice" failure, and calling runSession directly throws
11
- // the same fail-closed marker. SLICE 2 implements the real create -> inject (command-scoped) ->
12
- // run `codex exec --json` -> capture -> teardown session on the @e2b/desktop commands.run surface.
13
- /** The fail-closed marker a SLICE-1 live invocation surfaces (never a raw crash). */
6
+ // `runTerminalAgentSession` remains exported because it was part of the public actor-descriptor
7
+ // shape before the route-owned lifecycle shipped. Its options cannot carry the host/provider
8
+ // controls needed to enforce that lifecycle, so direct calls are intentionally unsupported and
9
+ // fail closed. Use `runTerminalProductLab` (or `runLab` with a terminal-product config) for both
10
+ // dry-run and live execution.
11
+ /**
12
+ * Backward-compatible fail-closed marker for the intentionally unsupported direct runner.
13
+ * The name is retained because it is already exported public API.
14
+ */
14
15
  export const TERMINAL_AGENT_NOT_IMPLEMENTED_CODE = "HUMANISH_TERMINAL_AGENT_NOT_IMPLEMENTED";
15
16
  /**
16
- * Registry-facing session entry. SLICE 1: NOT yet live the dry-run lab path never calls this,
17
- * and a live engine call fails closed with a structured error before reaching here. Calling it
18
- * directly throws the same fail-closed marker rather than pretending to drive a real agent.
17
+ * Backward-compatible registry entry. Direct execution is intentionally unsupported: only the
18
+ * terminal-product lab route owns enough context to enforce command-scoped auth, caps, evidence
19
+ * capture, and by-id cleanup together. Fail closed instead of implying that the descriptor method
20
+ * itself runs the shipped live route.
19
21
  */
20
22
  export async function runTerminalAgentSession(_options) {
21
- throw new Error(`${TERMINAL_AGENT_NOT_IMPLEMENTED_CODE}: the live terminal-agent session (in-sandbox Codex exec + command-scoped runtime auth) is implemented in SLICE 2. SLICE 1 only produces the dry-run contract bundle.`);
23
+ throw new Error(`${TERMINAL_AGENT_NOT_IMPLEMENTED_CODE}: direct runTerminalAgentSession calls are intentionally unsupported. Terminal execution is route-owned so the lab can enforce command-scoped runtime auth, caps, evidence capture, and by-id cleanup together. Use runTerminalProductLab or runLab with a terminal-product config.`);
22
24
  }
23
25
  //# sourceMappingURL=terminal-agent-actor.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"terminal-agent-actor.js","sourceRoot":"","sources":["../src/terminal-agent-actor.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,iGAAiG;AACjG,gGAAgG;AAChG,kFAAkF;AAClF,EAAE;AACF,+FAA+F;AAC/F,wFAAwF;AACxF,iGAAiG;AACjG,wFAAwF;AACxF,iGAAiG;AACjG,gGAAgG;AAChG,mGAAmG;AAInG,qFAAqF;AACrF,MAAM,CAAC,MAAM,mCAAmC,GAAG,yCAAkD,CAAC;AA+BtG;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,QAAqC;IAErC,MAAM,IAAI,KAAK,CACb,GAAG,mCAAmC,uKAAuK,CAC9M,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"terminal-agent-actor.js","sourceRoot":"","sources":["../src/terminal-agent-actor.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,iGAAiG;AACjG,8FAA8F;AAC9F,wCAAwC;AACxC,EAAE;AACF,gGAAgG;AAChG,6FAA6F;AAC7F,+FAA+F;AAC/F,iGAAiG;AACjG,8BAA8B;AAI9B;;;GAGG;AACH,MAAM,CAAC,MAAM,mCAAmC,GAAG,yCAAkD,CAAC;AAgCtG;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,QAAqC;IAErC,MAAM,IAAI,KAAK,CACb,GAAG,mCAAmC,qRAAqR,CAC5T,CAAC;AACJ,CAAC"}
@@ -1,27 +1,34 @@
1
1
  # Actor Contract
2
2
 
3
- Date: 2026-06-06 (updated 2026-06-11)
4
-
5
- Status: accepted design, partially implemented. Shipped: the evidence schema
6
- `humanish.actor-trace.v1` (`src/actor-contract.ts`) and a registry of five
7
- actors (`src/actor-registry.ts`: `codex-app-server`, `pi-agent-core`,
8
- `claude-agent-sdk`, `openai-computer-use`, `scripted-browser`), with
9
- `actors[0].type` a real dispatch key on the computer-use and scripted-browser
10
- lab routes. Not yet shipped (roadmap, not near-term claims): the full
11
- `Actor.run(input)` interface, `RedactionHooks` injection, `ApprovalPolicy`,
12
- `StagehandCuaActor`, and the `persona-fidelity` verify check. Decision 6's
13
- capture-time screenshot stance was recanted in 0.6.0; see the inline notes and
14
- the capture-vs-publish rule in
3
+ Date: 2026-06-06 (current-state note updated 2026-07-14)
4
+
5
+ Status: accepted contract with a partially open extension surface. Shipped:
6
+ the evidence schema `humanish.actor-trace.v1` (`src/actor-contract.ts`) and a
7
+ closed first-party registry of six descriptors (`src/actor-registry.ts`:
8
+ `codex-app-server`, `pi-agent-core`, `claude-agent-sdk`,
9
+ `openai-computer-use`, `scripted-browser`, `codex-exec`). `actors[0].type` is a
10
+ real dispatch key on the computer-use, scripted-browser, and terminal-product
11
+ routes. Product scoring, feedback, and artifact hooks are extension seams, but
12
+ public out-of-tree actor registration and its conformance certification are not
13
+ shipped. Also not shipped: the full `Actor.run(input)` interface,
14
+ `RedactionHooks` injection, `ApprovalPolicy`, `StagehandCuaActor`, and the
15
+ `persona-fidelity` verify check. Decision 6's capture-time screenshot stance
16
+ was recanted in 0.6.0; see the inline notes and the capture-vs-publish rule in
15
17
  [`docs/principles/invariants-and-defaults.md`](../principles/invariants-and-defaults.md).
16
18
 
19
+ `codex-exec` is a real dispatch key for terminal-product labs, but the exported
20
+ descriptor `runSession` is a fail-closed compatibility entry. Live execution is
21
+ owned by `runTerminalProductLab`, which coordinates sandbox creation,
22
+ command-scoped runtime auth, evidence, caps, and by-id cleanup.
23
+
17
24
  ## Context
18
25
 
19
- > 2026-06-11: this section describes the world as it stood when the design was
20
- > accepted (one real actor, hardcoded dispatch). That ceiling has since been
21
- > removed the registry now holds the four actors listed in the status note.
26
+ > Historical context: this section describes the world as it stood when the
27
+ > design was accepted (one real actor, hardcoded dispatch). The current state is
28
+ > the six-descriptor first-party registry described in the status note above.
22
29
 
23
- An actor is the thing that drives a persona scenario and produces evidence. Today
24
- Humanish has exactly one real actor: the local Codex integration in
30
+ An actor is the thing that drives a persona scenario and produces evidence. At
31
+ design time Humanish had exactly one real actor: the local Codex integration in
25
32
  `src/codex-app-server.ts` (plus the `codex-exec` and `codex-tui` variants in
26
33
  `src/run.ts`). The actor selection is a hardcoded `if (actor === ...)` dispatch,
27
34
  `RunStream.codex` is Codex-shaped, and the evidence schema is
@@ -91,6 +98,9 @@ API surface.
91
98
 
92
99
  ## The contract
93
100
 
101
+ The excerpt below shows the central contract fields; exported source types are
102
+ authoritative.
103
+
94
104
  ```ts
95
105
  export const ACTOR_TRACE_SCHEMA = "humanish.actor-trace.v1";
96
106
 
@@ -127,20 +137,21 @@ export interface ActorTraceItem {
127
137
  export interface ActorCapabilities {
128
138
  headless: boolean;
129
139
  structuredTrace: boolean;
130
- lanes: Array<"code" | "app" | "computer-use" | "scripted-browser">;
140
+ lanes: Array<"code" | "app" | "computer-use" | "scripted-browser" | "terminal">;
131
141
  producesScreenshots: boolean;
132
142
  byoModel: boolean;
133
143
  preGrantableApprovals: boolean; // can run unattended without a human prompt
134
144
  inProcessTools: boolean; // can inject product tools without a subprocess
135
145
  license: "open" | "source-available" | "proprietary";
146
+ keyPlacement?: "external" | "in-sandbox-command-scoped";
136
147
  }
137
148
 
138
149
  export interface ActorTrace {
139
150
  schema: typeof ACTOR_TRACE_SCHEMA;
140
- provider: string; // "codex-app-server" | "pi-agent-core" | "claude-agent-sdk" | "openai-responses-cu" | "browser-persona"
151
+ provider: string; // e.g. "codex-app-server" | "pi-agent-core" | "claude-agent-sdk" | "openai-responses-cu" | "browser-persona" | "codex"
141
152
  providerVersion?: string;
142
- protocol: "json-rpc" | "json-stream" | "in-process-sdk" | "cua-loop" | "scripted-steps";
143
- lane: "code" | "app" | "computer-use" | "scripted-browser";
153
+ protocol: "json-rpc" | "json-stream" | "in-process-sdk" | "cua-loop" | "scripted-steps" | "terminal-exec";
154
+ lane: "code" | "app" | "computer-use" | "scripted-browser" | "terminal";
144
155
  persona: { id: string; traitsApplied: string[]; promptDigest: string }; // proves traits were threaded
145
156
  // "raw" = full-fidelity frames retained (valid for LOCAL use; redact before
146
157
  // publishing); "blurred"/"ocr_scrubbed" = publish-safe; "n/a" = none captured.
@@ -1,16 +1,22 @@
1
1
  # Observer Architecture
2
2
 
3
- Date: 2026-06-01
3
+ Date: 2026-06-01 (current-state note updated 2026-07-14)
4
4
 
5
- Status: implemented for synthetic stream contracts and local `codex-exec`
6
- active-run Observer snapshots; broader live actor adapters next.
5
+ Status: implemented for synthetic streams and persisted live browser,
6
+ terminal-product, fan-out, and sequential/concurrent shared-world evidence.
7
+ Plain computer-use and shared-world runs can publish an in-progress bundle to
8
+ an attached loopback Observer without persisting runtime stream-auth URLs. The
9
+ version-pinned README image is a synthetic technical sample, not real-application
10
+ proof.
7
11
 
8
12
  ## Decision
9
13
 
10
14
  The Observer is a mission-control surface over durable run artifacts, not a
11
15
  static report page.
12
16
 
13
- Every run writes immutable local evidence under `.humanish/runs/<run-id>/`:
17
+ Every run writes durable local evidence under `.humanish/runs/<run-id>/`. Active
18
+ runs refresh their bundle and Observer projection; later review, feedback, or
19
+ Observer commands may add derived artifacts:
14
20
 
15
21
  ```text
16
22
  .humanish/runs/<run-id>/
@@ -25,7 +31,7 @@ Every run writes immutable local evidence under `.humanish/runs/<run-id>/`:
25
31
 
26
32
  `run.json` remains the source bundle. `observer/observer-data.json` is the
27
33
  normalized view model consumed by the Observer. `events.ndjson` is the appendable
28
- event stream contract that live adapters will update while a run is active.
34
+ event stream contract that live adapters update while a run is active.
29
35
 
30
36
  ## Stream Model
31
37
 
@@ -95,12 +101,12 @@ A host adapter may provide:
95
101
  If no embed URL exists, the Observer still renders the Codex-style timeline and
96
102
  session contract instead of failing the lane.
97
103
 
98
- ## Current Gaps
104
+ ## Historical slice and remaining gaps
99
105
 
100
- This slice implemented the Observer substrate, synthetic stream contracts, and
101
- active-run Observer snapshots for local `codex-exec`.
106
+ The original 2026-06-01 slice implemented the Observer substrate and synthetic
107
+ stream contracts; local `codex-exec` active-run snapshots followed.
102
108
 
103
- Since shipped (updated 2026-06-11):
109
+ Subsequent additions through 2026-06-11 included:
104
110
 
105
111
  - Playwright-backed browser proof with scripted, app-specific
106
112
  `browser.steps` authored in `humanish/scenarios/*.yaml` (`src/run.ts`);
@@ -134,9 +134,9 @@ import { runLab, parseLabConfig, type CuaExecutor, type CuaProvider } from "huma
134
134
 
135
135
  // local-app YAML (shareable; fails closed without hooks):
136
136
  // schema: humanish.lab.v2
137
- // id: pixel-bae-state
137
+ // id: downstream-local-app-state
138
138
  // subject: { source: local-app, appUrl: http://localhost:5173 }
139
- // actors: [{ type: openai-computer-use, persona: pixel-pat, mission: "…" }]
139
+ // actors: [{ type: openai-computer-use, persona: curious-tester, mission: "…" }]
140
140
  // scenario: { mode: live }
141
141
  const parsed = parseLabConfig(yaml);
142
142
  if (!parsed.ok) throw new Error(parsed.error.message);
@@ -199,5 +199,5 @@ Read every optional field defensively, and spread-omit optional fields
199
199
  surface with no precedent in this repo (the scripted lane loads only declarative
200
200
  YAML; serve commands run isolated inside the disposable E2B sandbox). It earns
201
201
  its place only behind its own clamping / trust / digest-pinning design.
202
- pixel-bae does not need it: a library caller builds the bridge in their own
202
+ the validated library consumer does not need it: a caller builds the bridge in its own
203
203
  trusted code (entry point 2 above).
@@ -1,11 +1,14 @@
1
1
  # Terminal-product real-agent lane (issue #154)
2
2
 
3
- Date: 2026-06-16
4
-
5
- Status: SLICE 1 shipped the config + routing skeleton, DRY-RUN only. The live
6
- in-sandbox backend, the command-scoped credential boundary, cleanup,
7
- interventions, the cost/no-spend ledger, and the product-adapter extension seam
8
- are later slices. See the ratified goal packet
3
+ Date: 2026-06-16 (current-state note updated 2026-07-14)
4
+
5
+ Status: live terminal-product route shipped in `0.8.0`. The in-sandbox backend,
6
+ command-scoped credential placement, exact-id cleanup proof, an interventions ledger,
7
+ cost/no-spend ledger, caps, and product scoring/feedback hooks are implemented;
8
+ the kept 2026-07-09 live receipt verifies 15/15 checks and `share_ready` at a
9
+ `$0` cap. That capability receipt is not adopter replacement: no deletion
10
+ branch has yet removed the reference adopter's bespoke generic study harness.
11
+ See the ratified goal packet
9
12
  ([`docs/goals/terminal-product-lane/goal.md`](../goals/terminal-product-lane/goal.md))
10
13
  for the full slice plan and the safety contract.
11
14
 
@@ -33,7 +36,7 @@ fail-closed cross-validation, and forward-declared warnings.
33
36
  | `subject.product` | `{ name, publicSurfaces[] }` — the only world the agent sees |
34
37
  | `execution.target` | `e2b-terminal` (or absent → implied) |
35
38
  | `execution.terminal` | `{ transport: exec-stream, stdin: disabled }` |
36
- | `execution.runtimeAuth` | `openai-env` (names-only evidence this slice) |
39
+ | `execution.runtimeAuth` | `openai-env` (names-only durable evidence) |
37
40
  | `scenario.caps` | `{ maxUsd, maxJobs, maxMinutes }` — the blast-radius budget |
38
41
  | `policies` | `allowPrivateRepoAccess` / `allowProviderCredentials` / `allowPaymentCredentials` / `allowGitHubMutation`, all DEFAULT FALSE |
39
42
  | `actors[0].type` | `codex-exec` — a registered terminal actor (`keyPlacement: in-sandbox-command-scoped`) |
@@ -54,16 +57,16 @@ blast radius is bounded by key scoping and budgets, not by hoping.*
54
57
 
55
58
  The inversion is declared as registry metadata, not a code convention: the
56
59
  terminal actor's capabilities carry `keyPlacement: "in-sandbox-command-scoped"`.
57
- SLICE 1 ships the DECLARED field + value (the contract is honest about where the
58
- key would go); SLICE 2's engine enforces command-scoped injection (only into the
60
+ SLICE 1 shipped the DECLARED field + value (the contract was honest about where
61
+ the key would go); SLICE 2's engine added command-scoped injection (only into the
59
62
  per-command `envs` of the `codex` invocation, never `Sandbox.create({envs})`)
60
63
  keyed off that capability, plus the deny-by-default credential allowlist, the
61
64
  positive-allowlist sandbox metadata, the cleanup proof, the interventions ledger,
62
65
  and a minimal fail-closed cap.
63
66
 
64
- ## SLICE 1 scope (DRY-RUN only what is honest now)
67
+ ## Historical SLICE 1 scope (DRY-RUN only when shipped)
65
68
 
66
- `runTerminalProductLab` implements ONLY the dry-run path: it builds a valid
69
+ At SLICE 1, `runTerminalProductLab` implemented only the dry-run path: it built a valid
67
70
  `humanish.run-bundle.v1` contract bundle, honestly labeled contract-only, with:
68
71
 
69
72
  - the subject declared as a terminal-product with its public surfaces, provenance
@@ -76,22 +79,22 @@ and a minimal fail-closed cap.
76
79
  - a terminal-kind stream that is an honest **contract placeholder**: stdin
77
80
  disabled, empty tail, `transport: snapshot` — **not** `pty` (captured
78
81
  non-interactive exec output is never an interactive PTY; invariant 6 + the
79
- goal packet's PTY ruling). SLICE 2 fills the redacted exec-stream capture;
82
+ goal packet's PTY ruling). SLICE 2 later added redacted exec-stream capture;
80
83
  - empty/placeholder ledgers (substrate lifecycle, command log, terminal event
81
- stream, interventions, cost) that SLICE 2/3 fill.
84
+ stream, interventions, cost) that SLICE 2/3 later filled.
82
85
 
83
- The dry-run bundle passes the EXISTING `verifyRun`. Terminal-specific verifier
86
+ The dry-run bundle passed the existing `verifyRun`. Terminal-specific verifier
84
87
  checks (terminal/transcript presence, lifecycle, cleanup, interventions,
85
- metadata allowlist, no-credential-in-artifacts, no-spend) are SLICE 2/3.
88
+ metadata allowlist, no-credential-in-artifacts, no-spend) landed in SLICE 2/3.
86
89
 
87
- A non-dry-run (live) call returns a structured `HUMANISH_TERMINAL_AGENT_NOT_IMPLEMENTED`
88
- failure (fail-closed, clear code) — it never creates a sandbox, never injects a
89
- key, never spends. SLICE 2 implements the real session.
90
+ At SLICE 1, a non-dry-run call returned a structured
91
+ `HUMANISH_TERMINAL_AGENT_NOT_IMPLEMENTED` failure before launch or spend.
92
+ SLICE 2 implemented the real session.
90
93
 
91
94
  The DI seams SLICE 2 needs (`loadModule`, `buildSandbox`, `runtimeAuthEnv`,
92
95
  `detachedTimers`) are declared on `TerminalProductLabHooks` and threaded through
93
- `RunLabOptions.terminalHooks`, mirroring `cuaHooks` / `scriptedHooks` but only
94
- the dry-run path is implemented this slice.
96
+ `RunLabOptions.terminalHooks`, mirroring `cuaHooks` / `scriptedHooks`; only the
97
+ dry-run path was implemented in that slice.
95
98
 
96
99
  ## SLICE 4 — the product-adapter extension seam (layer 6)
97
100
 
@@ -130,12 +133,13 @@ any malformed score/candidate with a warning, and `verifyRun` re-checks the
130
133
  surviving shapes — a bad extension never poisons a verifiable bundle. Proven by
131
134
  `tests/terminal-product-adapter-seam.test.ts` (a thin in-repo example adapter
132
135
  typing against the barrel only, registering a scorer, attaching namespaced nouns,
133
- emitting a candidate; the bundle verifies). No live rung the seam is contract,
134
- not spend.
136
+ emitting a candidate; the bundle verifies). At SLICE 4 this was contract proof,
137
+ not a live rung; the later end-to-end lane receipt is linked from the status
138
+ note.
135
139
 
136
- The adopter's real scorecard is its OWN thin extension; the live receipt for the
137
- end-to-end lane is tracked under #159, and true duplex PTY replay is deferred to
138
- SLICE 5.
140
+ The adopter's real scorecard is its OWN thin extension. The end-to-end lane's
141
+ live receipt is kept under the terminal-product goal, and true duplex PTY replay
142
+ is deferred to SLICE 5.
139
143
 
140
144
  ## The reference adopter (codename-neutral)
141
145
 
@@ -1,8 +1,10 @@
1
1
  # Adapter Fixture Parity Contract
2
2
 
3
- Date: 2026-06-02
3
+ Date: 2026-06-02 (current-state note updated 2026-07-14)
4
4
 
5
- Status: v0 draft contract for public-safe adapter fixture parity.
5
+ Status: committed contract fixtures with passing parity checks. A fixture
6
+ proves that core can carry an adapter-owned evidence shape; it does not prove a
7
+ live adopter integration or satisfy a deletion-branch depth phase.
6
8
 
7
9
  ## Purpose
8
10
 
@@ -1,8 +1,11 @@
1
1
  # Core Contract
2
2
 
3
- Date: 2026-06-02
3
+ Date: 2026-06-02 (current-state note updated 2026-07-14)
4
4
 
5
- Status: v0 draft contract with tested primitive helpers in `src/core`.
5
+ Status: the listed primitives are shipped and tested. This document does not
6
+ claim that every producer already uses one centralized store: run identity,
7
+ history, and provider-resource lifecycle still span route-specific code and
8
+ remain consolidation work.
6
9
 
7
10
  ## Purpose
8
11
 
@@ -19,7 +22,9 @@ setup, or repository-specific proof language.
19
22
  Core records must be safe to include in public run bundles by default:
20
23
 
21
24
  - artifact paths are relative;
22
- - run ids contain only lowercase letters, numbers, and dashes;
25
+ - ids produced by the core run-id builder contain only lowercase letters,
26
+ numbers, and dashes; runtime readers separately accept existing IDs that are
27
+ any safe single path segment;
23
28
  - git state summarizes status without branch names, remotes, file names, file
24
29
  paths, or absolute working directories;
25
30
  - lifecycle and timing records are explicit inputs, not inferred prose;
@@ -29,7 +34,7 @@ Core records must be safe to include in public run bundles by default:
29
34
 
30
35
  | Primitive | Contract |
31
36
  | --- | --- |
32
- | Run id | Deterministic from explicit prefix, timestamp, and entropy; valid ids match `^[a-z0-9][a-z0-9-]{0,127}$`. |
37
+ | Run id | The core builder is deterministic from explicit prefix, timestamp, and entropy, and emits ids matching `^[a-z0-9][a-z0-9-]{0,127}$`. Runtime artifact binding uses the broader compatibility rule in `src/run-paths.ts`: one non-empty segment, excluding `.`, `..`, separators, and NUL. |
33
38
  | Artifact layout | Builds stable relative pointers under `.humanish/runs/<run-id>/` plus `.humanish/runs/latest.json`. |
34
39
  | Latest pointer | `{ schema, runId, path, updatedAt }` using `humanish.latest-run.v1`. |
35
40
  | History entry | `{ schema, runId, createdAt, mode, path }` using `humanish.run-history-entry.v1`. |
@@ -1,8 +1,10 @@
1
1
  # Feedback Contract
2
2
 
3
- Date: 2026-06-01
3
+ Date: 2026-06-01 (current-state note updated 2026-07-14)
4
4
 
5
- Status: v0 local issue draft generation with run-candidate support.
5
+ Status: local feedback candidate, draft, verification, Markdown, and issue-URL
6
+ generation are shipped. These commands do not mutate GitHub, and public output
7
+ fails closed unless the run verifies as `share_ready`.
6
8
 
7
9
  ## Purpose
8
10
 
@@ -1,9 +1,11 @@
1
1
  # Policy Contract
2
2
 
3
- Date: 2026-06-02
3
+ Date: 2026-06-02 (current-state note updated 2026-07-14)
4
4
 
5
- Status: v0 draft contract for credential, network, spend, redaction, and
6
- assisted-run boundaries.
5
+ Status: shipped policy reference for credential, network, spend, redaction,
6
+ sharing, and assisted-run boundaries. Support remains route-specific; the
7
+ parser, route validation, and verifier determine whether a declared field is
8
+ consumed, rejected, or reported as a warning.
7
9
 
8
10
  Safety amendment (2026-07-14): beginning with `0.15.1`, stored provider IDs are
9
11
  evidence and never authorize core provider mutation. The bundled OSS meta-lab
@@ -1,9 +1,11 @@
1
1
  # Run Bundle Contract
2
2
 
3
- Date: 2026-06-02
3
+ Date: 2026-06-02 (current-state note updated 2026-07-14)
4
4
 
5
- Status: v0 draft contract for bundle identity, layout, source state, history,
6
- lifecycle, and timing primitives.
5
+ Status: `humanish.run-bundle.v1` is the shipped evidence contract. The
6
+ TypeScript shape and fail-closed verification in `src/run.ts` are
7
+ authoritative; this document explains the stable public fields and extension
8
+ rules rather than independently versioning the runtime.
7
9
 
8
10
  ## Purpose
9
11
 
@@ -77,6 +79,25 @@ Persisted `run.json` files must not contain absolute local target paths. Runtime
77
79
  commands may return the caller's working directory in process-local JSON
78
80
  responses, but durable run bundles use the public-safe `[target-cwd]` marker.
79
81
 
82
+ ## Hosted Desktop Geometry
83
+
84
+ Hosted browser streams may carry additive `desktopGeometry` evidence. Its fields keep four
85
+ different facts separate:
86
+
87
+ - `screen.requested`: the E2B/X screen size requested by config;
88
+ - `screen.verified`: the screen size measured in-sandbox with `xdpyinfo`;
89
+ - `browserWindow`: outer browser bounds measured after the window-fill attempt;
90
+ - `viewport`: the page's CSS layout viewport and device-pixel ratio measured through CDP on
91
+ Chromium-family hosted browsers.
92
+
93
+ For new hosted-desktop computer-use bundles, `stream.viewport` mirrors the measured
94
+ `desktopGeometry.viewport`; it is omitted when runtime measurement is unavailable. It is never
95
+ filled from the requested screen size. Dry-run bundles therefore carry the requested screen but
96
+ no verified screen, browser bounds, or viewport. Historical bundles remain loadable and may
97
+ contain the older requested-screen `stream.viewport` shape without `desktopGeometry`.
98
+ Deterministic Playwright-style adapters remain free to declare a viewport that they also render
99
+ exactly; this hosted-desktop rule does not change that contract.
100
+
80
101
  ## Subject Provenance
81
102
 
82
103
  `subject` is an optional, additive top-level field: structured provenance for
@@ -1,10 +1,12 @@
1
1
  # Contract Schema Index
2
2
 
3
- Date: 2026-06-02 (updated 2026-06-24)
3
+ Date: 2026-06-02 (current-state note updated 2026-07-14)
4
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.
5
+ Status: reference map for the major contracts shipped through source version
6
+ `0.16.0`; it is not an exhaustive inventory of command/result envelopes. Exported types,
7
+ schema constants, parsers, and validators in `src/` are authoritative. Rows
8
+ marked "reserved" name layering intent only — no code emits or validates them
9
+ yet. Do not emit a reserved schema.
8
10
 
9
11
  ## Purpose
10
12
 
@@ -110,9 +112,13 @@ A lab is a composition over code primitives, not a hardcoded kind:
110
112
  appear in `subject.env`) pointing at state the lab does not control,
111
113
  recorded as UNPINNED in provenance. Commands persist in evidence as
112
114
  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`).
115
+ - `actors`: who drives it. On computer-use (including shared-world),
116
+ scripted-browser, and terminal-product routes, `actors[0].type` is a real
117
+ dispatch key resolved against the actor registry. On synthetic and meta-lab
118
+ routes it remains a descriptive label (e.g. `synthetic-persona`). The
119
+ `codex-exec` descriptor's direct `runSession` member is a fail-closed
120
+ compatibility entry, not the live runner; the terminal-product lab route
121
+ owns the live sandbox, auth, cap, evidence, and cleanup lifecycle.
116
122
  `actors[0].count` carries route-specific meanings: synthetic route lane
117
123
  count (simCount); scripted-browser route surface roster (1 = desktop,
118
124
  2 = desktop + mobile, default 1); computer-use **E2B** route the HOMOGENEOUS
@@ -188,12 +194,14 @@ A lab is a composition over code primitives, not a hardcoded kind:
188
194
  `terminal.transport` is `exec-stream` — captured NON-interactive exec output
189
195
  (stdin disabled); `pty` is rejected because labeling captured exec output as
190
196
  an interactive PTY would overstate the mechanism (invariant 6; a true duplex
191
- PTY transport is a deferred slice). `terminal.stdin` defaults to `disabled`
197
+ PTY transport does not ship). `terminal.stdin` defaults to `disabled`
192
198
  (`sent`/assisted input is rejected until the interventions ledger + a
193
199
  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;
200
+ runtime-auth channel — recorded as NAMES ONLY. On a live run, the engine
201
+ resolves the registered terminal descriptor and requires
202
+ `keyPlacement: in-sandbox-command-scoped` before creating a sandbox. The key
203
+ is passed only to the agent command, never to `Sandbox.create` or metadata;
204
+ a dry-run neither reads nor injects it;
197
205
  - `scenario`: `mode: dry-run` (contract evidence, no spend) or `live`.
198
206
  `scenario.ref` is CONSUMED (and REQUIRED) on the scripted-browser route: it
199
207
  resolves a committed scenario (`humanish/scenarios/<ref>.yaml` or a repo
@@ -483,9 +491,10 @@ world ("M of N"); PROVEN CONCURRENCY (overlapping windows); and system-state evo
483
491
  under load (the stateSeries) with best-effort temporal correlation. It CANNOT claim
484
492
  strict causal attribution of a delta to an actor (concurrent ⇒ ambiguous), determinism
485
493
  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.
494
+ PROVEN absent). HONESTY: the deterministic $0 gate proves the plumbing + the
495
+ attribution contract. A kept 2026-06-17 live receipt separately proves one
496
+ bounded three-persona trial against a synthetic plane. Neither the deterministic
497
+ gate nor that receipt proves scale, repeatability, or adopter-harness replacement.
489
498
 
490
499
  ## Adapter
491
500
 
@@ -639,27 +648,29 @@ inside run bundles (per-stream transport and status) and lab execution config
639
648
 
640
649
  ## Terminal Cost Ledger And No-Spend Proof
641
650
 
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`).
651
+ The terminal-product lane (`src/e2b-terminal-lab.ts`) passes a real provider key
652
+ only to the in-sandbox agent command, never to sandbox-global env or metadata,
653
+ so the no-spend claim must be REAL derived from a ledger, never asserted. The
654
+ live run writes both to `terminal-ledgers.json` (a `cost` block + a
655
+ `noSpendProof` block, additive to `humanish.terminal-ledgers.v1`).
646
656
 
647
657
  The cost ledger (`humanish.terminal-cost-ledger.v1`) has one line per category —
648
658
  `product`, `media`, `payment`, `provider` — and follows a strict **null
649
659
  discipline** that distinguishes three states and never conflates them:
650
660
 
651
661
  - `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
662
+ - `usd: null` — **not measured**: no spend signal exists for the category on
663
+ this run. `null` is written explicitly (never `undefined`-omitted, never guessed
654
664
  to `0`). A line with `null` says "this category exists but we did not measure
655
665
  it"; the no-spend proof reports it as unmeasured and does NOT claim it is zero.
656
666
  - line **absent** — **not applicable** (n/a) to the lane/run.
657
667
 
658
668
  `knownTotalUsd` sums ONLY the non-null lines (a `null` line contributes nothing
659
669
  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.
670
+ Core meters only the `provider` line, populated from the actor trace's
671
+ `tokenUsage.costUsd` when present (else `null`); `product`/`media`/`payment`
672
+ remain `null` unless an adapter supplies those signals through the shipped
673
+ cost-probe seam.
663
674
 
664
675
  ```yaml
665
676
  schema: humanish.terminal-cost-ledger.v1