humanish 0.80.0 → 0.81.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -3
- package/dist/actor-contract.d.ts +16 -0
- package/dist/actor-contract.js.map +1 -1
- package/dist/chrome-cdp-probe.js +13 -0
- package/dist/chrome-cdp-probe.js.map +1 -1
- package/dist/computer-use.d.ts +7 -1
- package/dist/computer-use.js +156 -13
- package/dist/computer-use.js.map +1 -1
- package/dist/cua-actor-lab.d.ts +7 -6
- package/dist/cua-actor-lab.js +95 -21
- package/dist/cua-actor-lab.js.map +1 -1
- package/dist/e2b-desktop-launch.d.ts +28 -1
- package/dist/e2b-desktop-launch.js +88 -1
- package/dist/e2b-desktop-launch.js.map +1 -1
- package/dist/e2b-desktop-screenshot-cleanup.d.ts +15 -0
- package/dist/e2b-desktop-screenshot-cleanup.js +67 -0
- package/dist/e2b-desktop-screenshot-cleanup.js.map +1 -0
- package/dist/e2b-terminal-lab.d.ts +3 -2
- package/dist/e2b-terminal-lab.js +176 -85
- package/dist/e2b-terminal-lab.js.map +1 -1
- package/dist/first-run-path.js +2 -2
- package/dist/first-run-path.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lab-config.d.ts +11 -14
- package/dist/lab-config.js +2 -2
- package/dist/lab-config.js.map +1 -1
- package/dist/openai-responses-cu.js +76 -49
- package/dist/openai-responses-cu.js.map +1 -1
- package/dist/program.js +16 -7
- package/dist/program.js.map +1 -1
- package/dist/run.d.ts +1 -1
- package/dist/terminal-node-bootstrap.d.ts +4 -0
- package/dist/terminal-node-bootstrap.js +58 -0
- package/dist/terminal-node-bootstrap.js.map +1 -0
- package/dist/terminal-runtime-auth.d.ts +13 -0
- package/dist/terminal-runtime-auth.js +24 -0
- package/dist/terminal-runtime-auth.js.map +1 -0
- package/docs/architecture/actor-contract.md +22 -0
- package/docs/architecture/terminal-product-lane.md +108 -7
- package/docs/contracts/feedback.md +14 -0
- package/docs/contracts/schemas.md +1 -1
- package/docs/goals/current.md +45 -13
- package/docs/ramp/README.md +1 -1
- package/package.json +4 -2
package/dist/run.d.ts
CHANGED
|
@@ -831,7 +831,7 @@ export interface RunCostLine {
|
|
|
831
831
|
modelId?: string;
|
|
832
832
|
/** null = NOT MEASURED / no rate; never coerced to 0. */
|
|
833
833
|
estimatedCostUsd: number | null;
|
|
834
|
-
reason?: "no_rate_for_model" | "no_rate_for_desktop" | "no_token_usage" | "no_duration";
|
|
834
|
+
reason?: "no_rate_for_model" | "no_rate_for_desktop" | "no_token_usage" | "no_duration" | "closing_usage_unreported";
|
|
835
835
|
/** Pricing provenance date; non-null iff estimatedCostUsd is non-null. */
|
|
836
836
|
ratesAsOf: string | null;
|
|
837
837
|
source?: string;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const TERMINAL_NODE_VERSION = "22.23.2";
|
|
2
|
+
export declare const TERMINAL_NODE_NPM_PREFIX_SCRIPT: string;
|
|
3
|
+
/** Unkeyed runtime prerequisite for stock Linux desktops. No apt repository refresh (#674). */
|
|
4
|
+
export declare const TERMINAL_NODE_BOOTSTRAP_COMMAND: string;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// Node 22 remains a supported LTS line. Pin the official release and trusted archive hashes:
|
|
2
|
+
// https://nodejs.org/en/about/previous-releases
|
|
3
|
+
// https://nodejs.org/dist/v22.23.2/SHASUMS256.txt (checked 2026-09-05)
|
|
4
|
+
// A checksum fetched alongside the archive at runtime would not pin what we trust.
|
|
5
|
+
export const TERMINAL_NODE_VERSION = "22.23.2";
|
|
6
|
+
// npm normally derives its global prefix from the real Node executable. This distribution
|
|
7
|
+
// lives under /opt, while its public executables use /usr/local/bin. Set only a missing
|
|
8
|
+
// built-in default; npm's environment, CLI, user and global config still take precedence.
|
|
9
|
+
export const TERMINAL_NODE_NPM_PREFIX_SCRIPT = [
|
|
10
|
+
'const fs = require("node:fs");',
|
|
11
|
+
'const file = process.argv[1];',
|
|
12
|
+
'let existing = "";',
|
|
13
|
+
'try { existing = fs.readFileSync(file, "utf8"); } catch (error) { if (error.code !== "ENOENT") throw error; }',
|
|
14
|
+
'if (!/^[\\t ]*prefix[\\t ]*=/m.test(existing)) fs.appendFileSync(file, "\\nprefix=/usr/local\\n");'
|
|
15
|
+
].join(" ");
|
|
16
|
+
/** Unkeyed runtime prerequisite for stock Linux desktops. No apt repository refresh (#674). */
|
|
17
|
+
export const TERMINAL_NODE_BOOTSTRAP_COMMAND = [
|
|
18
|
+
"set -eu",
|
|
19
|
+
"# humanish terminal-node-bootstrap",
|
|
20
|
+
"node_major=0",
|
|
21
|
+
`if command -v node >/dev/null 2>&1; then node_major=$(node -e 'console.log(Number(process.versions.node.split(".")[0]))' 2>/dev/null || echo 0); fi`,
|
|
22
|
+
`if command -v node >/dev/null 2>&1 && command -v npm >/dev/null 2>&1 && [ "$node_major" -ge 20 ] && npm --version >/dev/null 2>&1; then`,
|
|
23
|
+
// An explicit exit under set -e runs the stock login shell's failing clear_console logout hook
|
|
24
|
+
// and turns this successful fast path into exit 1. Finish the compound command naturally.
|
|
25
|
+
" :",
|
|
26
|
+
"else",
|
|
27
|
+
`case "$(uname -s):$(uname -m)" in`,
|
|
28
|
+
` Linux:x86_64) node_arch=x64; node_sha=b294a556e639d64338823920e5866c21c02741742d2e1529ee1a225c1ec9252a ;;`,
|
|
29
|
+
` Linux:aarch64|Linux:arm64) node_arch=arm64; node_sha=013b59cfd2819703a6f4a14ab891fc46fc2a4e3f5bcd92de3fb4929b43e35b30 ;;`,
|
|
30
|
+
` *) echo 'humanish: terminal runtime requires a supported Linux x64/arm64 desktop or working Node >=20 and npm' >&2; exit 1 ;;`,
|
|
31
|
+
"esac",
|
|
32
|
+
"for prerequisite in curl sha256sum tar gzip mktemp sudo; do",
|
|
33
|
+
` command -v "$prerequisite" >/dev/null 2>&1 || { echo "humanish: terminal runtime bootstrap requires $prerequisite" >&2; exit 1; }`,
|
|
34
|
+
"done",
|
|
35
|
+
`node_archive="node-v${TERMINAL_NODE_VERSION}-linux-$node_arch.tar.gz"`,
|
|
36
|
+
`node_target="/opt/humanish/node-v${TERMINAL_NODE_VERSION}-linux-$node_arch"`,
|
|
37
|
+
`node_temp=$(mktemp -d /tmp/humanish-node.XXXXXX)`,
|
|
38
|
+
`trap 'rm -rf "$node_temp"' EXIT`,
|
|
39
|
+
`curl --fail --silent --show-error --location --proto '=https' --proto-redir '=https' --connect-timeout 10 --max-time 90 --retry 1 --retry-max-time 120 --output "$node_temp/$node_archive" "https://nodejs.org/dist/v${TERMINAL_NODE_VERSION}/$node_archive"`,
|
|
40
|
+
`(cd "$node_temp" && printf '%s %s\\n' "$node_sha" "$node_archive" | sha256sum --check --status) || { echo 'humanish: terminal Node archive checksum did not match the trusted release' >&2; exit 1; }`,
|
|
41
|
+
// Only a verified official archive reaches privileged extraction. The versioned install is
|
|
42
|
+
// root-owned; subsequent ordinary and sudo shells find it through standard /usr/local/bin.
|
|
43
|
+
"sudo -n mkdir -p /opt/humanish /usr/local/bin",
|
|
44
|
+
`sudo -n tar --extract --gzip --file "$node_temp/$node_archive" --directory /opt/humanish --no-same-owner`,
|
|
45
|
+
"for executable in node npm npx; do",
|
|
46
|
+
` sudo -n ln -sfn "$node_target/bin/$executable" "/usr/local/bin/$executable"`,
|
|
47
|
+
"done",
|
|
48
|
+
// Keep global product executables on the existing ordinary/sudo PATH (#679). The new
|
|
49
|
+
// versioned distribution is the only config we modify; no user/global npmrc or profile.
|
|
50
|
+
`sudo -n "$node_target/bin/node" -e '${TERMINAL_NODE_NPM_PREFIX_SCRIPT}' "$node_target/lib/node_modules/npm/npmrc"`,
|
|
51
|
+
"hash -r",
|
|
52
|
+
`node -e 'process.exit(Number(process.versions.node.split(".")[0]) >= 20 ? 0 : 1)' && npm --version >/dev/null`,
|
|
53
|
+
// Product installation already uses sudo; detect a template whose sudo PATH cannot see Node
|
|
54
|
+
// rather than changing global PATH or permissions to make it look supported.
|
|
55
|
+
`sudo -n node -e 'process.exit(Number(process.versions.node.split(".")[0]) >= 20 ? 0 : 1)' && sudo -n npm --version >/dev/null`,
|
|
56
|
+
"fi"
|
|
57
|
+
].join("\n");
|
|
58
|
+
//# sourceMappingURL=terminal-node-bootstrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-node-bootstrap.js","sourceRoot":"","sources":["../src/terminal-node-bootstrap.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,gDAAgD;AAChD,uEAAuE;AACvE,mFAAmF;AACnF,MAAM,CAAC,MAAM,qBAAqB,GAAG,SAAS,CAAC;AAE/C,0FAA0F;AAC1F,wFAAwF;AACxF,0FAA0F;AAC1F,MAAM,CAAC,MAAM,+BAA+B,GAAG;IAC7C,gCAAgC;IAChC,+BAA+B;IAC/B,oBAAoB;IACpB,+GAA+G;IAC/G,oGAAoG;CACrG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEZ,+FAA+F;AAC/F,MAAM,CAAC,MAAM,+BAA+B,GAAG;IAC7C,SAAS;IACT,oCAAoC;IACpC,cAAc;IACd,qJAAqJ;IACrJ,yIAAyI;IACzI,+FAA+F;IAC/F,0FAA0F;IAC1F,KAAK;IACL,MAAM;IACN,mCAAmC;IACnC,6GAA6G;IAC7G,4HAA4H;IAC5H,iIAAiI;IACjI,MAAM;IACN,6DAA6D;IAC7D,qIAAqI;IACrI,MAAM;IACN,uBAAuB,qBAAqB,2BAA2B;IACvE,oCAAoC,qBAAqB,oBAAoB;IAC7E,kDAAkD;IAClD,iCAAiC;IACjC,wNAAwN,qBAAqB,iBAAiB;IAC9P,wMAAwM;IACxM,2FAA2F;IAC3F,2FAA2F;IAC3F,+CAA+C;IAC/C,0GAA0G;IAC1G,oCAAoC;IACpC,+EAA+E;IAC/E,MAAM;IACN,qFAAqF;IACrF,wFAAwF;IACxF,uCAAuC,+BAA+B,6CAA6C;IACnH,SAAS;IACT,+GAA+G;IAC/G,4FAA4F;IAC5F,6EAA6E;IAC7E,+HAA+H;IAC/H,IAAI;CACL,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { E2BNetworkOptions } from "./e2b-desktop-launch.js";
|
|
2
|
+
export declare const OPENAI_EGRESS_HOST = "api.openai.com";
|
|
3
|
+
/** E2B envd installs the sandbox-specific proxy CA into this system bundle before routing. */
|
|
4
|
+
export declare const E2B_SYSTEM_CA_BUNDLE = "/etc/ssl/certs/ca-certificates.crt";
|
|
5
|
+
/** An inert nonsecret value satisfies Codex exec's auth prerequisite. E2B replaces the header. */
|
|
6
|
+
export declare const OPENAI_EGRESS_PLACEHOLDER = "humanish-egress-auth-placeholder";
|
|
7
|
+
/**
|
|
8
|
+
* Keep the runtime key in the host-side E2B request, outside sandbox env/files. The installed
|
|
9
|
+
* E2B SDK declares that transform headers override existing request headers. This adds no routing
|
|
10
|
+
* restrictions: every sandbox process can still spend via the provider proxy. Never log the
|
|
11
|
+
* returned options. An adopter's existing exact-host rule must not be silently overwritten.
|
|
12
|
+
*/
|
|
13
|
+
export declare function buildOpenAiEgressNetwork(keyValue: string, existing?: E2BNetworkOptions): E2BNetworkOptions;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export const OPENAI_EGRESS_HOST = "api.openai.com";
|
|
2
|
+
/** E2B envd installs the sandbox-specific proxy CA into this system bundle before routing. */
|
|
3
|
+
export const E2B_SYSTEM_CA_BUNDLE = "/etc/ssl/certs/ca-certificates.crt";
|
|
4
|
+
/** An inert nonsecret value satisfies Codex exec's auth prerequisite. E2B replaces the header. */
|
|
5
|
+
export const OPENAI_EGRESS_PLACEHOLDER = "humanish-egress-auth-placeholder";
|
|
6
|
+
/**
|
|
7
|
+
* Keep the runtime key in the host-side E2B request, outside sandbox env/files. The installed
|
|
8
|
+
* E2B SDK declares that transform headers override existing request headers. This adds no routing
|
|
9
|
+
* restrictions: every sandbox process can still spend via the provider proxy. Never log the
|
|
10
|
+
* returned options. An adopter's existing exact-host rule must not be silently overwritten.
|
|
11
|
+
*/
|
|
12
|
+
export function buildOpenAiEgressNetwork(keyValue, existing) {
|
|
13
|
+
if (Object.keys(existing?.rules ?? {}).some((host) => host.toLowerCase().replace(/\.$/, "") === OPENAI_EGRESS_HOST)) {
|
|
14
|
+
throw new Error("openai-egress conflicts with an existing api.openai.com network rule; refusing to overwrite it.");
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
...existing,
|
|
18
|
+
rules: {
|
|
19
|
+
...existing?.rules,
|
|
20
|
+
[OPENAI_EGRESS_HOST]: [{ transform: { headers: { Authorization: `Bearer ${keyValue}` } } }]
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=terminal-runtime-auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-runtime-auth.js","sourceRoot":"","sources":["../src/terminal-runtime-auth.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,kBAAkB,GAAG,gBAAgB,CAAC;AACnD,8FAA8F;AAC9F,MAAM,CAAC,MAAM,oBAAoB,GAAG,oCAAoC,CAAC;AACzE,kGAAkG;AAClG,MAAM,CAAC,MAAM,yBAAyB,GAAG,kCAAkC,CAAC;AAE5E;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CACtC,QAAgB,EAChB,QAA4B;IAE5B,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,kBAAkB,CAAC,EAAE,CAAC;QACpH,MAAM,IAAI,KAAK,CAAC,iGAAiG,CAAC,CAAC;IACrH,CAAC;IACD,OAAO;QACL,GAAG,QAAQ;QACX,KAAK,EAAE;YACL,GAAG,QAAQ,EAAE,KAAK;YAClB,CAAC,kBAAkB,CAAC,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,QAAQ,EAAE,EAAE,EAAE,EAAE,CAAC;SAC5F;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -293,6 +293,28 @@ not cost — a live scripted run drives a real browser against a real running ap
|
|
|
293
293
|
declaration as spend. "Live" on this route must never silently come to mean "costs money";
|
|
294
294
|
this paragraph is the record of that decision.
|
|
295
295
|
|
|
296
|
+
## Optional closing report
|
|
297
|
+
|
|
298
|
+
`CuaProvider.debrief` is an optional read-only request after a structured
|
|
299
|
+
`stopWhen` or dwell stop. It returns a `CuaTurn` with `closingReport` containing
|
|
300
|
+
`summary` and `frictionReports`; an empty friction list is valid. The loop rejects
|
|
301
|
+
actions, pending safety checks, and invalid report shapes. It redacts accepted
|
|
302
|
+
reports, records them in `ActorTrace.debrief`, and projects one readable message
|
|
303
|
+
without invoking action or communication callbacks.
|
|
304
|
+
|
|
305
|
+
This request uses the final observation and retained provider history. It does
|
|
306
|
+
not expose the hidden stop criterion or change the original task outcome. It is
|
|
307
|
+
skipped before any participant turn, after natural completion, without provider
|
|
308
|
+
support, or without remaining time and known budget. An attempted request's
|
|
309
|
+
unreported usage remains an unknown cost line. `counts.debriefCalls` is separate
|
|
310
|
+
from interaction turns, and reported usage contributes to aggregate cost.
|
|
311
|
+
|
|
312
|
+
The OpenAI implementation makes one request with tools disabled and structured
|
|
313
|
+
output; no HTTP or policy retries. Stateless/ZDR mode does not offer retrospective
|
|
314
|
+
reporting because it does not retain the required session history. The
|
|
315
|
+
[paired live receipt](../goals/computer-use-actor/receipts/structured-closing-report-2026-09-05.md)
|
|
316
|
+
records both report recovery and control failures in the separate legacy parser.
|
|
317
|
+
|
|
296
318
|
## The state-driven executor seam (shipped — the transport-agnostic intent, made real)
|
|
297
319
|
|
|
298
320
|
The `CuaExecutor` / `CuaProvider` ports are the concrete realization of the "plural harnesses /
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Terminal-product real-agent lane (issue #154)
|
|
2
2
|
|
|
3
|
-
Date: 2026-06-16 (
|
|
3
|
+
Date: 2026-06-16 (runtime-auth contract updated 2026-09-05)
|
|
4
4
|
|
|
5
5
|
Status: live terminal-product route shipped in `0.8.0`. The in-sandbox backend,
|
|
6
6
|
command-scoped credential placement, exact-id cleanup proof, an interventions ledger,
|
|
@@ -16,8 +16,8 @@ for the full slice plan and the safety contract.
|
|
|
16
16
|
|
|
17
17
|
A lab lane for **terminal-product real-agent studies**: a real autonomous coding
|
|
18
18
|
agent (Codex) discovering and using a CLI/product from its **public surfaces
|
|
19
|
-
only**, running **inside an E2B shell** with
|
|
20
|
-
|
|
19
|
+
only**, running **inside an E2B shell** with declared runtime-auth placement and
|
|
20
|
+
spend/time caps, emitting durable terminal/substrate/cost/no-spend/cleanup/
|
|
21
21
|
intervention proof that verifies fail-closed. This is distinct from the browser
|
|
22
22
|
lanes: it is not testing whether a browser can click a local web app — it tests
|
|
23
23
|
whether an autonomous agent can discover and use a CLI/product surface from
|
|
@@ -36,7 +36,7 @@ fail-closed cross-validation, and forward-declared warnings.
|
|
|
36
36
|
| `subject.product` | `{ name, publicSurfaces[] }` — the only world the agent sees |
|
|
37
37
|
| `execution.target` | `e2b-terminal` (or absent → implied) |
|
|
38
38
|
| `execution.terminal` | `{ transport: exec-stream, stdin: disabled }` |
|
|
39
|
-
| `execution.runtimeAuth` | `openai-env` (names-only durable evidence
|
|
39
|
+
| `execution.runtimeAuth` | `openai-env` (default) or opt-in `openai-egress`; names-only durable evidence |
|
|
40
40
|
| `scenario.caps` | `{ maxUsd, maxJobs, maxMinutes }` — the blast-radius budget |
|
|
41
41
|
| `policies` | `allowPrivateRepoAccess` / `allowProviderCredentials` / `allowPaymentCredentials` / `allowGitHubMutation`, all DEFAULT FALSE |
|
|
42
42
|
| `actors[0].type` | `codex-exec` — a registered terminal actor (`keyPlacement: in-sandbox-command-scoped`) |
|
|
@@ -46,9 +46,110 @@ Routing is `routesToTerminalProduct(config)` — the single source of truth that
|
|
|
46
46
|
both `selectLabBackend` and the forward-declared-warning logic consume, mirroring
|
|
47
47
|
`routesToComputerUse` / `routesToScriptedBrowser`.
|
|
48
48
|
|
|
49
|
-
##
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
## Runtime auth: raw-key placement and remaining provider access
|
|
50
|
+
|
|
51
|
+
`execution.runtimeAuth: openai-env` remains the compatible default. It supplies
|
|
52
|
+
`CODEX_API_KEY` command-scoped to Codex, with `OPENAI_API_KEY` also supplied when
|
|
53
|
+
that was the host source. Child processes can read and use the raw key.
|
|
54
|
+
|
|
55
|
+
Opt in to keeping the raw key outside the sandbox:
|
|
56
|
+
|
|
57
|
+
```yaml
|
|
58
|
+
execution:
|
|
59
|
+
target: e2b-terminal
|
|
60
|
+
runtimeAuth: openai-egress
|
|
61
|
+
terminal:
|
|
62
|
+
transport: exec-stream
|
|
63
|
+
stdin: disabled
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`openai-egress` resolves the same host key (`CODEX_API_KEY` first, otherwise
|
|
67
|
+
`OPENAI_API_KEY`) and supplies it only to E2B's host-side network rule for
|
|
68
|
+
`api.openai.com`. The rule sets the HTTPS `Authorization` header. The sandbox's
|
|
69
|
+
Codex command receives the nonsecret value `humanish-egress-auth-placeholder`
|
|
70
|
+
under `CODEX_API_KEY`, plus `CODEX_CA_CERTIFICATE` pointing at E2B's existing
|
|
71
|
+
system CA bundle (`/etc/ssl/certs/ca-certificates.crt`) so TLS verification trusts
|
|
72
|
+
the platform's proxy CA. Humanish does not disable TLS verification or download
|
|
73
|
+
an unauthenticated CA. The sandbox receives no raw runtime key in command env, sandbox env,
|
|
74
|
+
files, metadata, or captured evidence. The host still scrubs the actual key from
|
|
75
|
+
output and errors, including errors during sandbox creation.
|
|
76
|
+
|
|
77
|
+
This mode supports the default OpenAI endpoint only. Humanish explicitly sets
|
|
78
|
+
Codex's built-in `openai` provider and `openai_base_url` to
|
|
79
|
+
`https://api.openai.com/v1` for that invocation. It does not support a custom
|
|
80
|
+
provider, proxy base URL, or regional endpoint under this mode. `openai-env`
|
|
81
|
+
retains its existing command behavior. E2B header rules are a public-beta
|
|
82
|
+
capability; the local contract is checked against the installed Desktop SDK
|
|
83
|
+
(`@e2b/desktop` 2.3.3, resolving `e2b` 2.46.1).
|
|
84
|
+
|
|
85
|
+
**The sandbox still has a spendable OpenAI proxy capability.** Every process can
|
|
86
|
+
make authenticated requests to that host from sandbox creation until teardown,
|
|
87
|
+
including bootstrap/setup commands and commands launched outside Codex. Calls
|
|
88
|
+
made outside Codex may be absent from its usage ledger. This mode does not impose
|
|
89
|
+
a provider-side spending limit, restrict models/API paths, or make
|
|
90
|
+
`scenario.caps.maxUsd` a preventive provider budget. A hard provider budget needs
|
|
91
|
+
a separately enforced control; do not infer zero spend from an unmeasured ledger
|
|
92
|
+
line.
|
|
93
|
+
|
|
94
|
+
Public internet discovery stays unrestricted unless the lab already declares
|
|
95
|
+
`execution.egressAllow`. The mode preserves that allowlist and its deny-all
|
|
96
|
+
fallback without adding hosts. If an allowlist omits `api.openai.com`, provider
|
|
97
|
+
requests can fail. E2B domain allowlists are routing controls rather than strict
|
|
98
|
+
destination isolation on shared infrastructure. An existing exact OpenAI host
|
|
99
|
+
rule is rejected instead of silently overwritten.
|
|
100
|
+
|
|
101
|
+
Evidence records the selected auth mode and the residual proxy capability.
|
|
102
|
+
Resolved live actor traces use `keyPlacement: external` in `openai-egress`; the
|
|
103
|
+
actor registry continues to describe the default `in-sandbox-command-scoped`
|
|
104
|
+
placement. Dry runs record declarations and prove no live proxy behavior.
|
|
105
|
+
|
|
106
|
+
The upstream contracts are documented in [E2B internet access and network
|
|
107
|
+
rules](https://docs.e2b.dev/network/internet-access) and [Codex advanced
|
|
108
|
+
configuration](https://developers.openai.com/codex/config-advanced),
|
|
109
|
+
[Codex custom CA bundles](https://developers.openai.com/codex/auth#custom-ca-bundles),
|
|
110
|
+
and [E2B's CA installer](https://github.com/e2b-dev/infra/blob/main/packages/envd/internal/host/cacerts.go).
|
|
111
|
+
E2B's installed
|
|
112
|
+
SDK documents that transformed headers override request headers. Deterministic
|
|
113
|
+
request/redaction tests do not establish live wire behavior. The [2026-09-05
|
|
114
|
+
transport receipt](../goals/terminal-product-lane/receipts/2026-09-05-runtime-egress-auth.md)
|
|
115
|
+
records the controlled live header/auth checks and their scope.
|
|
116
|
+
|
|
117
|
+
## Runtime prerequisite
|
|
118
|
+
|
|
119
|
+
The terminal route reuses a working Node >=20 and npm from the calling shell.
|
|
120
|
+
Otherwise it installs the pinned official Node 22.23.2 Linux x64 or arm64 archive,
|
|
121
|
+
downloaded over verified HTTPS and checked against an architecture-specific
|
|
122
|
+
SHA256 committed in the bootstrap. It does not refresh apt repositories or fetch
|
|
123
|
+
an unpinned checksum beside the archive. Node 22 is a supported LTS line on the
|
|
124
|
+
[official release schedule](https://nodejs.org/en/about/previous-releases); the
|
|
125
|
+
trusted hashes come from its [release manifest](https://nodejs.org/dist/v22.23.2/SHASUMS256.txt).
|
|
126
|
+
|
|
127
|
+
Installation requires `curl`, `sha256sum`, `tar`, `gzip`, `mktemp`, and passwordless
|
|
128
|
+
`sudo`. Only a verified archive is extracted into a root-owned versioned directory
|
|
129
|
+
under `/opt/humanish`; `/usr/local/bin` links make Node/npm/npx available to later
|
|
130
|
+
shells. In that new distribution only, a missing built-in npm `prefix` defaults
|
|
131
|
+
to `/usr/local`, so global product executables use the existing PATH. Existing
|
|
132
|
+
distribution settings and higher-priority npm overrides are preserved; an adopter
|
|
133
|
+
override can still choose a bin directory outside PATH. The installer changes no
|
|
134
|
+
user/global npm configuration, global permissions, or shell startup files. It
|
|
135
|
+
checks Node/npm in both ordinary and sudo shells after installation. The existing
|
|
136
|
+
runtime fast path preserves user-specific installations; a later sudo product
|
|
137
|
+
install can still fail if that installation is absent from sudo's PATH.
|
|
138
|
+
|
|
139
|
+
The [global executable receipt](../goals/terminal-product-lane/receipts/2026-09-05-global-npm-prefix.md)
|
|
140
|
+
records the regression found after the initial runtime-only proof and its stock
|
|
141
|
+
desktop checks. npm documents [global executable locations](https://docs.npmjs.com/cli/v10/configuring-npm/folders#executables)
|
|
142
|
+
and the [distribution built-in configuration](https://docs.npmjs.com/cli/v10/configuring-npm/npmrc#built-in-config-file).
|
|
143
|
+
|
|
144
|
+
An egress allowlist must permit `nodejs.org` if the runtime needs installation,
|
|
145
|
+
as well as the registries and product surfaces the study uses. Missing tools,
|
|
146
|
+
unsupported architectures, a failed download or checksum, and a failed runtime
|
|
147
|
+
check stop the lane before Codex. Downloads have finite connection, transfer, and
|
|
148
|
+
retry bounds within the existing five-minute bootstrap deadline.
|
|
149
|
+
|
|
150
|
+
## The original command-scoped safety contract
|
|
151
|
+
|
|
152
|
+
The default mode **inverts** the credential-placement default of every other E2B route.
|
|
52
153
|
On the computer-use route the model's key stays *outside* the sandbox; here the
|
|
53
154
|
agent-under-test runs *inside* with a real `OPENAI_API_KEY`/`CODEX_API_KEY` and
|
|
54
155
|
is **presumed exfiltratable**. The doctrine (invariants-and-defaults.md, the
|
|
@@ -52,6 +52,20 @@ setup-quality gap, ceremonial/absent study quality, target-app blocker, or
|
|
|
52
52
|
Humanish CLI blocker. The OSS
|
|
53
53
|
meta-lab is one maintainer dogfood example, not the only candidate source.
|
|
54
54
|
|
|
55
|
+
For completed computer-use sessions, participant-reported friction comes from
|
|
56
|
+
the redacted closing report and observed-report clauses in earlier messages.
|
|
57
|
+
Matching `stopWhen` or ending a dwell window does not discard an earlier
|
|
58
|
+
report or change the successful completion verdict. Exact repeated reports
|
|
59
|
+
appear once in the lane's candidate. Harness notices, reasoning, and observed
|
|
60
|
+
page content do not become participant findings; quoted app copy and negated
|
|
61
|
+
reports retain the existing exclusions. Code excerpts are treated as quoted
|
|
62
|
+
material. Interim matching requires an observation-shaped clause and filters
|
|
63
|
+
common plans, questions, and hypotheticals; a report followed by a retry plan
|
|
64
|
+
can still qualify. This text
|
|
65
|
+
heuristic does not establish that a reported defect is real or independently
|
|
66
|
+
confirmed. A custom session's closing `reason` remains eligible even when it
|
|
67
|
+
was not repeated in the message trace.
|
|
68
|
+
|
|
55
69
|
### `draft`
|
|
56
70
|
|
|
57
71
|
Builds structured feedback from the strongest run candidate first. If no
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Date: 2026-06-02 (current-state note updated 2026-07-14)
|
|
4
4
|
|
|
5
5
|
Status: reference map for the major contracts shipped through source version
|
|
6
|
-
`0.
|
|
6
|
+
`0.81.0`; it is not an exhaustive inventory of command/result envelopes. Exported types,
|
|
7
7
|
schema constants, parsers, and validators in `src/` are authoritative. Rows
|
|
8
8
|
marked "reserved" name layering intent only — no code emits or validates them
|
|
9
9
|
yet. Do not emit a reserved schema.
|
package/docs/goals/current.md
CHANGED
|
@@ -29,11 +29,19 @@ study completed, reproduced, and produced a real accessibility finding via a
|
|
|
29
29
|
keyboard-first participant
|
|
30
30
|
([docs/goals/email-gated-signup/receipts/](email-gated-signup/receipts/)).
|
|
31
31
|
|
|
32
|
-
## Current Program Truth (source `0.
|
|
32
|
+
## Current Program Truth (source `0.81.0`)
|
|
33
33
|
|
|
34
34
|
The package source and repository implementation in this tree agree on these
|
|
35
35
|
points:
|
|
36
36
|
|
|
37
|
+
**Mobile input correction, 2026-09-05 (#676).** The historical 4/4 TodoMVC phone-lane rename
|
|
38
|
+
failures describe the shipped desktop pointer-to-touch conversion path. In two new hosted
|
|
39
|
+
conformance probes, SDK double click emitted two single clicks; direct touch opened the same
|
|
40
|
+
original editor in both. A separate local native-X control reproduced the difference by toggling
|
|
41
|
+
conversion. Mobile viewport and touch flags do not certify gesture equivalence or establish a
|
|
42
|
+
physical-device app defect. Mobile lanes using touch conversion now carry that advisory in run
|
|
43
|
+
warnings. [Method, traces summary and limits](computer-use-actor/receipts/mobile-input-conformance-2026-09-05.md).
|
|
44
|
+
|
|
37
45
|
The immutable 2026-06-10 proof-roadmap packet is paired with a
|
|
38
46
|
[current implementation checkpoint](https://github.com/danielgwilson/humanish/blob/main/docs/goals/proof-roadmap/README.md).
|
|
39
47
|
|
|
@@ -463,6 +471,23 @@ Stop and correct course if:
|
|
|
463
471
|
|
|
464
472
|
## Best Next Work
|
|
465
473
|
|
|
474
|
+
**2026-09-05 (0.81.0).** First use now distinguishes the free evidence preview
|
|
475
|
+
from a live participant study, with concise successful setup output and complete JSON details
|
|
476
|
+
(#660). The website has runnable docs and a generated CLI reference (#661, #668). Retained participant
|
|
477
|
+
reports survive automatic stops. Supported providers with retained history can add one closing
|
|
478
|
+
report when time and known budget remain; clean reports such as “no confusion or hesitation”
|
|
479
|
+
stay clean (#658, #670, #671). Desktop startup cleanup retains acquired handles and records
|
|
480
|
+
confirmed or unknown reclamation. The SDK's detached screenshot-file cleanup rejection is
|
|
481
|
+
handled (#665, #666).
|
|
482
|
+
Terminal output reconciles SDK callbacks with returned aggregates, preserving legitimate
|
|
483
|
+
repeated lines and usage turns while avoiding doubled capture (#672). Opt-in `openai-egress`
|
|
484
|
+
auth keeps the raw OpenAI runtime key outside the sandbox; every sandbox process can still
|
|
485
|
+
spend through the proxy, so this is not a provider spending limit (#663). Stock terminal
|
|
486
|
+
startup installs a checksum-verified Node archive without refreshing unrelated package mirrors
|
|
487
|
+
and gives newly installed npm a default global prefix on the standard PATH (#677, #680). Mobile studies warn that desktop pointer-to-touch conversion can change repeated-tap
|
|
488
|
+
behavior; gesture failures require direct or native touch confirmation before app attribution
|
|
489
|
+
(#678).
|
|
490
|
+
|
|
466
491
|
**2026-09-04, night (0.80.0).** The observation window reaches every desktop route: the
|
|
467
492
|
sequential and concurrent shared-world seats forward `dwell` the way they forward `stopWhen`
|
|
468
493
|
(#645), with a plumbing test per route and two live receipts, three participants holding together
|
|
@@ -490,8 +515,9 @@ gives a hosted Chrome lane a capture device (ffmpeg's test pattern generated in
|
|
|
490
515
|
`desktopBrowser.media`; a microphone is refused without an image that has an audio stack, before
|
|
491
516
|
any spend. Live, Chrome raised its real dialog with a preview of the feed, the participant chose
|
|
492
517
|
"Allow this time" and read back 640x480 (`receipts/participant-camera-2026-09-04.md`). Under
|
|
493
|
-
mobile
|
|
494
|
-
at 12 of 12.
|
|
518
|
+
the then-shipped mobile-emulation input path, TodoMVC rename had stopped 3 of 3 phone
|
|
519
|
+
participants at this checkpoint; Excalidraw read 12 of 12. The 2026-09-05 input-conformance
|
|
520
|
+
correction above qualifies attribution of those mobile failures.
|
|
495
521
|
|
|
496
522
|
**2026-09-04, later (0.78.0).** `@e2b/desktop` moved from 2.2.3 to 2.3.3 (#638): its 2.3.1
|
|
497
523
|
changelog names the socket #581 found today, a background command's event stream the SDK kept
|
|
@@ -526,10 +552,10 @@ mobile-emulated browser: `execution.desktop.fidelity.mobileEmulation: true` appl
|
|
|
526
552
|
CSS viewport, the preset's device pixel ratio, touch events and a mobile user agent before the
|
|
527
553
|
participant's first observation, and the bundle records what the page then reported about itself
|
|
528
554
|
under `desktopGeometry.fidelity` (#221, `docs/goals/computer-use-actor/receipts/mobile-emulation-2026-09-03.md`).
|
|
529
|
-
On the published 0.76.0,
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
555
|
+
On the published 0.76.0, neither phone participant could rename through the emulated input path,
|
|
556
|
+
where the 500 px runs without touch had finished. Those are historical instrument observations:
|
|
557
|
+
the 2026-09-05 conformance check found SDK double click and direct touch differ on the original
|
|
558
|
+
editor, so the earlier outcome does not establish a touch-device app defect.
|
|
533
559
|
The persona axis was replicated the same evening on drawDB and TodoMVC and given a third app,
|
|
534
560
|
Excalidraw, as the clean control (`persona-axis-phone-2026-09-03.md`); a multi-lane study's
|
|
535
561
|
second and third findings reach `feedback draft` through `--candidate` (#609); a negated report
|
|
@@ -566,16 +592,22 @@ and a Claude participant with no memory across turns (#520). `humanish stats` (#
|
|
|
566
592
|
|
|
567
593
|
The standing queue, in rough order:
|
|
568
594
|
|
|
569
|
-
1. #
|
|
595
|
+
1. #509, the microphone tier: a custom desktop image with an audio stack
|
|
596
|
+
(`execution.desktop.template`), then `media.microphone` threaded into the launch the way the
|
|
597
|
+
camera is; the parse-time refusal stands until then;
|
|
598
|
+
2. #581, the remaining half: a `Sandbox.create` that fails after the API allocated the sandbox
|
|
570
599
|
(the desktop SDK's own startup) leaves a sandbox this run never learned the id of, reclaimed only
|
|
571
600
|
by the provider's timeout; the linger itself is the SDK's held command stream, closed by the
|
|
572
|
-
2.3.3 bump (0.78.0), and `doctor` names an older SDK;
|
|
573
|
-
|
|
601
|
+
2.3.3 bump (0.78.0), and `doctor` names an older SDK; the upstream ask is drafted for the
|
|
602
|
+
operator;
|
|
603
|
+
3. #221's later tier, a real device or simulator behind the emulated lane, and #623's
|
|
604
|
+
scripted-browser route, which has no model loop and so no dwell or later-tab applier;
|
|
605
|
+
4. #513: there is still nowhere to read the docs on humanish.dev (site copy is locked; a docs
|
|
574
606
|
route needs the operator's sign-off);
|
|
575
|
-
|
|
576
|
-
|
|
607
|
+
5. the TUI views over `stats` and `export` (#455's metrics screen and `s` key), design-gated;
|
|
608
|
+
6. the launch post: a draft with every number and its receipt path sits outside the public repo,
|
|
577
609
|
awaiting the operator; nothing has been announced;
|
|
578
|
-
|
|
610
|
+
7. registry promotions (#431) and the shared-world honesty half (#365, #446), unchanged.
|
|
579
611
|
|
|
580
612
|
Earlier state, kept for the record:
|
|
581
613
|
|
package/docs/ramp/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Status: public-safe contributor and agent ramp.
|
|
4
4
|
|
|
5
|
-
Package/source version in this tree: `0.
|
|
5
|
+
Package/source version in this tree: `0.81.0` (2026-09-05). The Observer is phone-usable as a stated requirement (observer/AGENTS.md); interactive primitives start from Base UI. The Observer renderer is the observer/ workspace artifact only; the legacy string-concat renderer was deleted at cutover (#426), and rollback is a version pin to 0.42.0. The containment boundary introduced in
|
|
6
6
|
`0.15.1` remains in force: managed run and output paths bind to validated
|
|
7
7
|
physical filesystem identities, and stored provider IDs are evidence, not
|
|
8
8
|
cleanup authority. The bundled OSS meta-lab is dry-run only until
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "humanish",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.81.0",
|
|
4
4
|
"description": "Open-source-safe CLI for persona simulation, observer review, and public-safe feedback drafts.",
|
|
5
5
|
"author": "Daniel G Wilson <daniel@danielgwilson.com>",
|
|
6
6
|
"keywords": [
|
|
@@ -73,7 +73,9 @@
|
|
|
73
73
|
"tui:typecheck": "pnpm --filter humanish-tui typecheck",
|
|
74
74
|
"tui:smoke": "node scripts/tui-smoke.mjs",
|
|
75
75
|
"tui:test": "pnpm --filter humanish-tui test",
|
|
76
|
-
"release:dogfood": "node scripts/release-dogfood.mjs"
|
|
76
|
+
"release:dogfood": "node scripts/release-dogfood.mjs",
|
|
77
|
+
"docs:generate": "tsx scripts/generate-cli-docs.ts",
|
|
78
|
+
"docs:check": "tsx scripts/generate-cli-docs.ts --check"
|
|
77
79
|
},
|
|
78
80
|
"repository": {
|
|
79
81
|
"type": "git",
|