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.
Files changed (205) hide show
  1. package/AGENTS.md +77 -0
  2. package/CONTRIBUTING.md +39 -0
  3. package/LICENSE +21 -0
  4. package/README.md +437 -8
  5. package/SECURITY.md +34 -0
  6. package/dist/actor-contract.d.ts +107 -0
  7. package/dist/actor-contract.js +286 -0
  8. package/dist/actor-contract.js.map +1 -0
  9. package/dist/actor-registry.d.ts +73 -0
  10. package/dist/actor-registry.js +93 -0
  11. package/dist/actor-registry.js.map +1 -0
  12. package/dist/adapter-extension.d.ts +54 -0
  13. package/dist/adapter-extension.js +214 -0
  14. package/dist/adapter-extension.js.map +1 -0
  15. package/dist/argv.d.ts +1 -0
  16. package/dist/argv.js +8 -0
  17. package/dist/argv.js.map +1 -0
  18. package/dist/artifact-reference.d.ts +22 -0
  19. package/dist/artifact-reference.js +47 -0
  20. package/dist/artifact-reference.js.map +1 -0
  21. package/dist/browser-evidence-hygiene.d.ts +7 -0
  22. package/dist/browser-evidence-hygiene.js +40 -0
  23. package/dist/browser-evidence-hygiene.js.map +1 -0
  24. package/dist/claude-agent-sdk.d.ts +94 -0
  25. package/dist/claude-agent-sdk.js +363 -0
  26. package/dist/claude-agent-sdk.js.map +1 -0
  27. package/dist/cli.d.ts +2 -0
  28. package/dist/cli.js +5 -0
  29. package/dist/cli.js.map +1 -0
  30. package/dist/codex-app-server-ui.d.ts +39 -0
  31. package/dist/codex-app-server-ui.js +357 -0
  32. package/dist/codex-app-server-ui.js.map +1 -0
  33. package/dist/codex-app-server.d.ts +144 -0
  34. package/dist/codex-app-server.js +754 -0
  35. package/dist/codex-app-server.js.map +1 -0
  36. package/dist/command-failure.d.ts +29 -0
  37. package/dist/command-failure.js +54 -0
  38. package/dist/command-failure.js.map +1 -0
  39. package/dist/computer-use-actor.d.ts +52 -0
  40. package/dist/computer-use-actor.js +48 -0
  41. package/dist/computer-use-actor.js.map +1 -0
  42. package/dist/computer-use.d.ts +232 -0
  43. package/dist/computer-use.js +615 -0
  44. package/dist/computer-use.js.map +1 -0
  45. package/dist/concurrency.d.ts +1 -0
  46. package/dist/concurrency.js +27 -0
  47. package/dist/concurrency.js.map +1 -0
  48. package/dist/concurrent-shared-world-lab.d.ts +115 -0
  49. package/dist/concurrent-shared-world-lab.js +1094 -0
  50. package/dist/concurrent-shared-world-lab.js.map +1 -0
  51. package/dist/core/git-state.d.ts +33 -0
  52. package/dist/core/git-state.js +277 -0
  53. package/dist/core/git-state.js.map +1 -0
  54. package/dist/core/git-workspace.d.ts +31 -0
  55. package/dist/core/git-workspace.js +447 -0
  56. package/dist/core/git-workspace.js.map +1 -0
  57. package/dist/core/index.d.ts +4 -0
  58. package/dist/core/index.js +3 -0
  59. package/dist/core/index.js.map +1 -0
  60. package/dist/core/run-primitives.d.ts +66 -0
  61. package/dist/core/run-primitives.js +120 -0
  62. package/dist/core/run-primitives.js.map +1 -0
  63. package/dist/cua-actor-lab.d.ts +621 -0
  64. package/dist/cua-actor-lab.js +2845 -0
  65. package/dist/cua-actor-lab.js.map +1 -0
  66. package/dist/device-presets.d.ts +67 -0
  67. package/dist/device-presets.js +50 -0
  68. package/dist/device-presets.js.map +1 -0
  69. package/dist/e2b-desktop-executor.d.ts +101 -0
  70. package/dist/e2b-desktop-executor.js +309 -0
  71. package/dist/e2b-desktop-executor.js.map +1 -0
  72. package/dist/e2b-desktop-launch.d.ts +144 -0
  73. package/dist/e2b-desktop-launch.js +59 -0
  74. package/dist/e2b-desktop-launch.js.map +1 -0
  75. package/dist/e2b-detached.d.ts +53 -0
  76. package/dist/e2b-detached.js +130 -0
  77. package/dist/e2b-detached.js.map +1 -0
  78. package/dist/e2b-terminal-lab.d.ts +345 -0
  79. package/dist/e2b-terminal-lab.js +1532 -0
  80. package/dist/e2b-terminal-lab.js.map +1 -0
  81. package/dist/env-file.d.ts +14 -0
  82. package/dist/env-file.js +108 -0
  83. package/dist/env-file.js.map +1 -0
  84. package/dist/feedback.d.ts +51 -0
  85. package/dist/feedback.js +351 -0
  86. package/dist/feedback.js.map +1 -0
  87. package/dist/image-evidence.d.ts +2 -0
  88. package/dist/image-evidence.js +33 -0
  89. package/dist/image-evidence.js.map +1 -0
  90. package/dist/index.d.ts +63 -0
  91. package/dist/index.js +33 -0
  92. package/dist/index.js.map +1 -0
  93. package/dist/init-templates.d.ts +12 -0
  94. package/dist/init-templates.js +369 -0
  95. package/dist/init-templates.js.map +1 -0
  96. package/dist/init.d.ts +26 -0
  97. package/dist/init.js +429 -0
  98. package/dist/init.js.map +1 -0
  99. package/dist/lab-app-runner.d.ts +78 -0
  100. package/dist/lab-app-runner.js +403 -0
  101. package/dist/lab-app-runner.js.map +1 -0
  102. package/dist/lab-config.d.ts +583 -0
  103. package/dist/lab-config.js +1789 -0
  104. package/dist/lab-config.js.map +1 -0
  105. package/dist/lab-engine.d.ts +77 -0
  106. package/dist/lab-engine.js +216 -0
  107. package/dist/lab-engine.js.map +1 -0
  108. package/dist/lab-preflight.d.ts +67 -0
  109. package/dist/lab-preflight.js +385 -0
  110. package/dist/lab-preflight.js.map +1 -0
  111. package/dist/labs.d.ts +53 -0
  112. package/dist/labs.js +382 -0
  113. package/dist/labs.js.map +1 -0
  114. package/dist/observer-assets.d.ts +2 -0
  115. package/dist/observer-assets.js +2630 -0
  116. package/dist/observer-assets.js.map +1 -0
  117. package/dist/observer-data.d.ts +63 -0
  118. package/dist/observer-data.js +145 -0
  119. package/dist/observer-data.js.map +1 -0
  120. package/dist/observer-static.d.ts +39 -0
  121. package/dist/observer-static.js +306 -0
  122. package/dist/observer-static.js.map +1 -0
  123. package/dist/observer.d.ts +46 -0
  124. package/dist/observer.js +550 -0
  125. package/dist/observer.js.map +1 -0
  126. package/dist/openai-responses-cu.d.ts +113 -0
  127. package/dist/openai-responses-cu.js +545 -0
  128. package/dist/openai-responses-cu.js.map +1 -0
  129. package/dist/oss-lab.d.ts +52 -0
  130. package/dist/oss-lab.js +344 -0
  131. package/dist/oss-lab.js.map +1 -0
  132. package/dist/oss-meta-lab-scoring.d.ts +15 -0
  133. package/dist/oss-meta-lab-scoring.js +145 -0
  134. package/dist/oss-meta-lab-scoring.js.map +1 -0
  135. package/dist/oss-meta-lab.d.ts +277 -0
  136. package/dist/oss-meta-lab.js +4529 -0
  137. package/dist/oss-meta-lab.js.map +1 -0
  138. package/dist/oss-remote-telemetry.d.ts +77 -0
  139. package/dist/oss-remote-telemetry.js +403 -0
  140. package/dist/oss-remote-telemetry.js.map +1 -0
  141. package/dist/persona.d.ts +35 -0
  142. package/dist/persona.js +133 -0
  143. package/dist/persona.js.map +1 -0
  144. package/dist/pi-agent-core.d.ts +77 -0
  145. package/dist/pi-agent-core.js +203 -0
  146. package/dist/pi-agent-core.js.map +1 -0
  147. package/dist/program.d.ts +54 -0
  148. package/dist/program.js +2349 -0
  149. package/dist/program.js.map +1 -0
  150. package/dist/redaction.d.ts +90 -0
  151. package/dist/redaction.js +292 -0
  152. package/dist/redaction.js.map +1 -0
  153. package/dist/run-paths.d.ts +56 -0
  154. package/dist/run-paths.js +340 -0
  155. package/dist/run-paths.js.map +1 -0
  156. package/dist/run.d.ts +794 -0
  157. package/dist/run.js +4844 -0
  158. package/dist/run.js.map +1 -0
  159. package/dist/scripted-browser-actor.d.ts +297 -0
  160. package/dist/scripted-browser-actor.js +1399 -0
  161. package/dist/scripted-browser-actor.js.map +1 -0
  162. package/dist/scripted-browser-lab.d.ts +107 -0
  163. package/dist/scripted-browser-lab.js +788 -0
  164. package/dist/scripted-browser-lab.js.map +1 -0
  165. package/dist/selected-output-paths.d.ts +49 -0
  166. package/dist/selected-output-paths.js +354 -0
  167. package/dist/selected-output-paths.js.map +1 -0
  168. package/dist/shared-world-lab.d.ts +208 -0
  169. package/dist/shared-world-lab.js +1049 -0
  170. package/dist/shared-world-lab.js.map +1 -0
  171. package/dist/source-archive.d.ts +82 -0
  172. package/dist/source-archive.js +408 -0
  173. package/dist/source-archive.js.map +1 -0
  174. package/dist/stop-conditions.d.ts +26 -0
  175. package/dist/stop-conditions.js +66 -0
  176. package/dist/stop-conditions.js.map +1 -0
  177. package/dist/terminal-agent-actor.d.ts +36 -0
  178. package/dist/terminal-agent-actor.js +23 -0
  179. package/dist/terminal-agent-actor.js.map +1 -0
  180. package/docs/architecture/actor-contract.md +431 -0
  181. package/docs/architecture/github-feedback-loop.md +189 -0
  182. package/docs/architecture/local-codex-tui-actor.md +213 -0
  183. package/docs/architecture/observer.md +118 -0
  184. package/docs/architecture/oss-lab-poc.md +250 -0
  185. package/docs/architecture/project-layout.md +166 -0
  186. package/docs/architecture/state-driven-executor.md +203 -0
  187. package/docs/architecture/terminal-product-lane.md +148 -0
  188. package/docs/contracts/adapter-fixtures.md +80 -0
  189. package/docs/contracts/core.md +71 -0
  190. package/docs/contracts/feedback.md +145 -0
  191. package/docs/contracts/policy.md +311 -0
  192. package/docs/contracts/run-bundle.md +358 -0
  193. package/docs/contracts/schemas.md +984 -0
  194. package/docs/goals/current.md +428 -0
  195. package/docs/principles/invariants-and-defaults.md +135 -0
  196. package/docs/principles/self-driving-harness.md +129 -0
  197. package/docs/product/open-source-install-experience.md +237 -0
  198. package/docs/ramp/README.md +207 -0
  199. package/docs/release/open-source-readiness.md +208 -0
  200. package/docs/release/public-readiness-standard.md +205 -0
  201. package/docs/roadmap/world-class-open-source-v0.md +311 -0
  202. package/package.json +102 -8
  203. package/skills/humanish/SKILL.md +244 -0
  204. package/skills/humanish/agents/openai.yaml +7 -0
  205. package/index.js +0 -1
@@ -0,0 +1,130 @@
1
+ // Detached process management for E2B sandboxes — the substrate primitive behind serving a
2
+ // subject app in-sandbox. E2B's foreground `commands.run` deadlines on long-running work, so
3
+ // every consumer of the pattern has historically re-implemented the same workaround. This
4
+ // module lands it once:
5
+ //
6
+ // - Scripts are written via `files.write`, never heredocs — which eliminates the
7
+ // sentinel-collision bug class (a command line that equals the heredoc terminator) by
8
+ // construction.
9
+ // - Bounded steps (install/build) run detached with an ATOMICALLY-written status file
10
+ // (write tmp + mv), polled by short foreground commands; a timeout kills the process
11
+ // group and surfaces a capped log tail for the caller to redact and persist.
12
+ // - Long-lived steps (a dev/prod server) launch fully detached via `setsid -f`; the sandbox
13
+ // lifecycle (kill-on-timeout) owns their reclamation.
14
+ // - Readiness is an explicit curl probe against the declared URL.
15
+ //
16
+ // Log tails are returned RAW; callers must pass them through redaction before persisting
17
+ // (build output can echo env values and paths).
18
+ const WORK_ROOT = "/tmp/humanish-subject";
19
+ const DEFAULT_POLL_INTERVAL_MS = 3000;
20
+ const DEFAULT_REQUEST_TIMEOUT_MS = 30_000;
21
+ const LOG_TAIL_BYTES = 8192;
22
+ const NAME_PATTERN = /^[a-z0-9-]+$/;
23
+ function assertName(name) {
24
+ if (!NAME_PATTERN.test(name)) {
25
+ throw new Error(`Detached step name must match ${NAME_PATTERN} (got "${name}").`);
26
+ }
27
+ }
28
+ /** Single-quote a value for safe interpolation into a shell script. */
29
+ function shq(value) {
30
+ return `'${value.replaceAll("'", "'\\''")}'`;
31
+ }
32
+ function stepDir(name) {
33
+ return `${WORK_ROOT}/${name}`;
34
+ }
35
+ // The wrapper script: runs the command from its own session (setsid launch makes the script
36
+ // the process-group leader, so `kill -- -PID` reclaims the whole tree), logs everything, and
37
+ // writes the exit code atomically so a poller can never read a half-written status.
38
+ function wrapperScript(name, command, cwd) {
39
+ const dir = stepDir(name);
40
+ return [
41
+ "#!/bin/bash",
42
+ `mkdir -p ${shq(dir)}`,
43
+ `echo $$ > ${shq(`${dir}/pid`)}`,
44
+ cwd === undefined ? ": # no cwd override" : `cd ${shq(cwd)} || { echo 127 > ${shq(`${dir}/status.tmp`)}; mv ${shq(`${dir}/status.tmp`)} ${shq(`${dir}/status`)}; exit 127; }`,
45
+ `( ${command} ) > ${shq(`${dir}/log.txt`)} 2>&1`,
46
+ "code=$?",
47
+ `echo $code > ${shq(`${dir}/status.tmp`)}`,
48
+ `mv ${shq(`${dir}/status.tmp`)} ${shq(`${dir}/status`)}`,
49
+ "exit $code",
50
+ ""
51
+ ].join("\n");
52
+ }
53
+ async function writeAndLaunch(desktop, name, command, cwd, requestTimeoutMs) {
54
+ assertName(name);
55
+ const dir = stepDir(name);
56
+ const scriptPath = `${dir}/run.sh`;
57
+ await desktop.commands.run(`mkdir -p ${shq(dir)}`, { requestTimeoutMs });
58
+ await desktop.files.write(scriptPath, wrapperScript(name, command, cwd));
59
+ await desktop.commands.run(`chmod +x ${shq(scriptPath)} && setsid -f ${shq(scriptPath)} < /dev/null > /dev/null 2>&1`, { requestTimeoutMs });
60
+ }
61
+ /** Read the capped log tail for a step (raw — caller redacts). */
62
+ export async function readDetachedLog(desktop, name, requestTimeoutMs = DEFAULT_REQUEST_TIMEOUT_MS) {
63
+ assertName(name);
64
+ const result = await desktop.commands.run(`tail -c ${LOG_TAIL_BYTES} ${shq(`${stepDir(name)}/log.txt`)} 2>/dev/null || true`, { requestTimeoutMs });
65
+ return result.stdout ?? "";
66
+ }
67
+ /**
68
+ * Run a BOUNDED step (install/build) detached, polling its atomic status file until it
69
+ * exits or the budget runs out. On timeout the process group is killed and the log tail is
70
+ * still captured so failures stay diagnosable.
71
+ */
72
+ export async function runDetachedStep(desktop, options) {
73
+ const requestTimeoutMs = options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
74
+ const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
75
+ const now = options.now ?? Date.now;
76
+ const sleep = options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
77
+ const dir = stepDir(options.name);
78
+ await writeAndLaunch(desktop, options.name, options.command, options.cwd, requestTimeoutMs);
79
+ const deadline = now() + options.timeoutMs;
80
+ for (;;) {
81
+ const status = await desktop.commands.run(`cat ${shq(`${dir}/status`)} 2>/dev/null || true`, { requestTimeoutMs });
82
+ const text = (status.stdout ?? "").trim();
83
+ if (text.length > 0) {
84
+ const exitCode = Number.parseInt(text, 10);
85
+ const logTail = await readDetachedLog(desktop, options.name, requestTimeoutMs);
86
+ return { ok: exitCode === 0, exitCode, timedOut: false, logTail };
87
+ }
88
+ if (now() >= deadline) {
89
+ // Kill the whole process group (the script is its own session leader via setsid).
90
+ await desktop.commands
91
+ .run(`kill -- -$(cat ${shq(`${dir}/pid`)} 2>/dev/null) 2>/dev/null || true`, { requestTimeoutMs })
92
+ .catch(() => undefined);
93
+ const logTail = await readDetachedLog(desktop, options.name, requestTimeoutMs);
94
+ return { ok: false, timedOut: true, logTail };
95
+ }
96
+ await sleep(pollIntervalMs);
97
+ }
98
+ }
99
+ /**
100
+ * Launch a LONG-LIVED process (the subject's server) fully detached and return immediately.
101
+ * No status polling: liveness is the caller's readiness probe, and reclamation belongs to
102
+ * the sandbox lifecycle (create with kill-on-timeout).
103
+ */
104
+ export async function startDetachedProcess(desktop, options) {
105
+ await writeAndLaunch(desktop, options.name, options.command, options.cwd, options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS);
106
+ }
107
+ /**
108
+ * Poll a URL from INSIDE the sandbox until it answers 2xx/3xx or the budget runs out.
109
+ * Returns true when the subject is ready.
110
+ */
111
+ export async function probeUrl(desktop, url, options) {
112
+ const requestTimeoutMs = options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
113
+ const intervalMs = options.intervalMs ?? 1500;
114
+ const now = options.now ?? Date.now;
115
+ const sleep = options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
116
+ const deadline = now() + options.timeoutMs;
117
+ for (;;) {
118
+ const result = await desktop.commands
119
+ .run(`curl -sf -o /dev/null --max-time 5 ${shq(url)} && echo READY || echo WAIT`, { requestTimeoutMs })
120
+ .catch(() => ({ stdout: "WAIT" }));
121
+ if ((result.stdout ?? "").includes("READY")) {
122
+ return true;
123
+ }
124
+ if (now() >= deadline) {
125
+ return false;
126
+ }
127
+ await sleep(intervalMs);
128
+ }
129
+ }
130
+ //# sourceMappingURL=e2b-detached.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"e2b-detached.js","sourceRoot":"","sources":["../src/e2b-detached.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,345 @@
1
+ import type { ActorCompletionReason, ActorPersonaRef, ActorStatus, ActorTrace } from "./actor-contract.js";
2
+ import type { LabConfig, LabScenarioCaps } from "./lab-config.js";
3
+ import { type E2BDesktopModule } from "./e2b-desktop-launch.js";
4
+ import { renderObserver, type ObserverResult } from "./observer.js";
5
+ import { type RunAdapterScore, type RunBundle, type RunFeedbackCandidate } from "./run.js";
6
+ import { TERMINAL_AGENT_NOT_IMPLEMENTED_CODE } from "./terminal-agent-actor.js";
7
+ /** Provider-neutral metadata constant: the lane's non-secret tag (mirrors CUA_ACTOR_LAB_PROVIDER_METADATA). */
8
+ export declare const TERMINAL_PRODUCT_LAB_PROVIDER_METADATA: {
9
+ readonly mode: "terminal-product-lab";
10
+ readonly tool: "humanish";
11
+ };
12
+ export declare const TERMINAL_EVENTS_ARTIFACT = "terminal-events.ndjson";
13
+ export declare const TERMINAL_TRANSCRIPT_ARTIFACT = "terminal-transcript.txt";
14
+ export declare const TERMINAL_LEDGERS_ARTIFACT = "terminal-ledgers.json";
15
+ export declare const TERMINAL_PRODUCT_LAB_SCHEMA = "humanish.terminal-lab-result.v1";
16
+ /**
17
+ * Library-level hooks: the DI seams that drive the full live path against a fake sandbox + mock
18
+ * CLI at zero spend. The deterministic merge-gate test wires loadModule (a fake @e2b/desktop
19
+ * module) + env (the operator key source) + now (an injected clock); the live rung uses none of
20
+ * them (it loads the real module and reads the real environment).
21
+ */
22
+ /**
23
+ * The read-only evidence a thin adapter's scorer/feedback hook sees (the layer-6 extension seam,
24
+ * issue #154 acceptance #8). It is the FULLY-ASSEMBLED, redacted, verifiable evidence — the live run
25
+ * bundle, the provider-neutral actor trace, and the persisted ledgers (substrate/command/
26
+ * interventions/cleanup/cost/no-spend). Every member is an EXPORTED public type, so a thin adapter
27
+ * types against `import("humanish")` alone — never a deep `src/` import. The adapter reads this
28
+ * to score the product attempt and derive feedback; it cannot mutate core's evidence (the lane
29
+ * attaches only the namespaced `RunAdapterScore` it returns + the feedback candidates it derives).
30
+ */
31
+ export interface TerminalProductScoringContext {
32
+ /** The assembled live run bundle (already redacted/scrubbed + verifiable). Read-only to the adapter. */
33
+ bundle: RunBundle;
34
+ /** The provider-neutral actor trace for the in-sandbox agent session. */
35
+ trace: ActorTrace;
36
+ /** The persisted terminal-product ledgers (lifecycle/command/interventions/cleanup/cost/no-spend). */
37
+ ledgers: TerminalLedgers;
38
+ /** The studied product name (public-safe). */
39
+ product: string;
40
+ /** The lab id (the run's scenario scope). */
41
+ labId: string;
42
+ /** The run id (for building namespaced idempotency keys + evidence pointers). */
43
+ runId: string;
44
+ }
45
+ export interface TerminalProductLabHooks {
46
+ /** Lazy-load the E2B module (tests inject a fake; default loadE2BDesktopModule). */
47
+ loadModule?: () => Promise<E2BDesktopModule>;
48
+ /**
49
+ * The operator environment the lane reads the runtime key from (and from which it asserts no
50
+ * banned credential is requested). Defaults to process.env. The runtime key is injected ONLY
51
+ * into the command-scoped `codex` invocation — NEVER Sandbox.create envs (the credential
52
+ * boundary); tests plant a fake key here and assert it never reaches metadata/global env/artifacts.
53
+ */
54
+ env?: Record<string, string | undefined>;
55
+ renderObserverFn?: typeof renderObserver;
56
+ /** Injected clock for deterministic timestamps + wall-clock arithmetic (tests only). */
57
+ now?: () => number;
58
+ /**
59
+ * SLICE-3 DI seam for the cost ledger. The lane has NO real product-spend signal yet (that is the
60
+ * adapter's job in SLICE 4), so this slice populates only the provider line (from the trace's
61
+ * tokenUsage when present). This seam lets the deterministic test (and, later, a SLICE-4 adapter)
62
+ * inject KNOWN spend lines so the fail-closed cap enforcement can be exercised at $0 without a
63
+ * real billable run. Production callers never pass this — they get the null-discipline default.
64
+ */
65
+ costProbe?: (context: {
66
+ tokenCostUsd?: number;
67
+ }) => Partial<Record<"product" | "media" | "payment" | "provider", CostLine>> | undefined;
68
+ /**
69
+ * THE LAYER-6 EXTENSION SEAM (issue #154 acceptance #8: "product-adapter hooks WITHOUT forking
70
+ * core"). A thin in-repo/out-of-tree adapter registers a product scorer here. The lane calls it
71
+ * (when provided) over the fully-assembled evidence and attaches the returned, ADAPTER-NAMESPACED
72
+ * `RunAdapterScore` to `bundle.adapterScore` WITHOUT core knowing any product noun (the score is
73
+ * namespaced + its component breakdown rides in `data`). When NO scorer is given, the default
74
+ * mission-based verdict (`review`) is unchanged. This is the SEAM the adopter's scorecard plugs
75
+ * into — NOT a built-in product scorer (that lives in the adopter's repo).
76
+ */
77
+ score?: (ctx: TerminalProductScoringContext) => RunAdapterScore | Promise<RunAdapterScore>;
78
+ /**
79
+ * Companion seam: derive product-feedback candidates from the same assembled evidence. The lane
80
+ * appends the returned candidates to `bundle.feedbackCandidates`. The adapter records its
81
+ * product-specific concepts (public CLI command observed, hosted success-or-blocker, feedback id,
82
+ * media/job ids, no-spend proof, defection/friction risk) under each candidate's ADAPTER-NAMESPACED
83
+ * `adapter` block — never as core enums (issue #154's "record product-specific concepts as
84
+ * NON-core nouns" list). The candidates must still satisfy core's feedback-candidate shape (which
85
+ * the bundle verifier enforces), so a malformed adapter candidate fails closed.
86
+ */
87
+ deriveFeedback?: (ctx: TerminalProductScoringContext) => RunFeedbackCandidate[] | Promise<RunFeedbackCandidate[]>;
88
+ }
89
+ export interface RunTerminalProductLabOptions {
90
+ cwd: string;
91
+ config: LabConfig;
92
+ /** Resolved upstream (scenario.mode + CLI override); defaults safe (dry-run). */
93
+ dryRun: boolean;
94
+ open?: boolean;
95
+ runId?: string;
96
+ hooks?: TerminalProductLabHooks;
97
+ }
98
+ export interface TerminalProductLabResult {
99
+ schema: typeof TERMINAL_PRODUCT_LAB_SCHEMA;
100
+ /** True when the bundle verified AND (dry-run, or the live session reached a terminal verdict
101
+ * without a harness error + cleanup was proven). The agent's pass/fail is evidence, not the
102
+ * lab's exit code. */
103
+ ok: boolean;
104
+ cwd: string;
105
+ labId: string;
106
+ /** The registry-resolved actor id that ran (or would run) the session. */
107
+ actor: string;
108
+ /** The studied product name (public-safe). */
109
+ product: string;
110
+ dryRun: boolean;
111
+ runId: string;
112
+ /** Live-only: the in-sandbox agent session verdict (omitted on dry-run / pre-session failure). */
113
+ session?: {
114
+ status: ActorStatus;
115
+ completionReason: ActorCompletionReason;
116
+ reason: string;
117
+ };
118
+ /** Live-only: the sandbox lifecycle proof (the key/auth value is NEVER surfaced here). */
119
+ sandbox?: {
120
+ sandboxId: string;
121
+ killed: boolean;
122
+ /** BY-ID proof (never a re-list): 0 = confirmed reclaimed, 1 = still present (unconfirmed),
123
+ * -1 = kill(id) itself failed or was unavailable. See TerminalLedgers["cleanup"]. */
124
+ remaining: number;
125
+ };
126
+ /** Live-only: the spend ledger surfaced on the result (SLICE 3) — unknowns are null, never guessed.
127
+ * Lets a programmatic caller read spend without parsing the bundle. */
128
+ cost?: {
129
+ knownTotalUsd: number;
130
+ fullyMeasured: boolean;
131
+ /** Per-category USD: a known number, or null = NOT MEASURED (never coerced to 0). */
132
+ lines: Record<"product" | "media" | "payment" | "provider", number | null>;
133
+ };
134
+ /** Live-only: the no-spend proof DERIVED from the ledger (SLICE 3). */
135
+ noSpend?: {
136
+ satisfied: boolean;
137
+ maxUsd: number | null;
138
+ knownZeroLines: string[];
139
+ unmeasuredLines: string[];
140
+ };
141
+ observer?: ObserverResult;
142
+ warnings: string[];
143
+ error?: {
144
+ code: "HUMANISH_TERMINAL_LAB_FAILED" | "HUMANISH_TERMINAL_LAB_ACTOR_UNSUPPORTED" | "HUMANISH_TERMINAL_LAB_SUBJECT_INVALID" | "HUMANISH_TERMINAL_LAB_KEYPLACEMENT_INVALID" | "HUMANISH_TERMINAL_LAB_RUNTIME_AUTH_MISSING" | "HUMANISH_TERMINAL_LAB_CAPS_MISSING" | "HUMANISH_TERMINAL_LAB_CAPS_EXCEEDED" | "HUMANISH_TERMINAL_LAB_CREDENTIAL_DENIED" | "HUMANISH_TERMINAL_LAB_CLEANUP_UNPROVEN" | typeof TERMINAL_AGENT_NOT_IMPLEMENTED_CODE;
145
+ message: string;
146
+ };
147
+ }
148
+ export declare function runTerminalProductLab(options: RunTerminalProductLabOptions): Promise<TerminalProductLabResult>;
149
+ /** Substrate lifecycle ledger entry (create/readiness/exec/cleanup events with timestamps). */
150
+ export interface LifecycleRecord {
151
+ at: string;
152
+ event: string;
153
+ /** Redacted+scrubbed before persisting (it never carries a secret, but the harness never trusts that). */
154
+ message: string;
155
+ }
156
+ /** Command-log ledger entry: which command ran, with what exit/duration (NEVER its env values). */
157
+ export interface CommandLogRecord {
158
+ at: string;
159
+ /** A public-safe label for the command (e.g. "codex-exec"); the full argv is bound by digest only. */
160
+ label: string;
161
+ /** sha256-12 of the exact command string — pins "same recipe" without persisting it. */
162
+ commandDigest: string;
163
+ /** The env var NAMES injected command-scoped (values NEVER persisted) — the credential evidence. */
164
+ envNames: string[];
165
+ exitCode?: number;
166
+ timedOut?: boolean;
167
+ durationMs: number;
168
+ }
169
+ /**
170
+ * One operator intervention (assisted-input event). SLICE 2 ships NO assisted-input path, so this
171
+ * ledger is ALWAYS empty — but always PRESENT (the safety contract: empty-present is the contract,
172
+ * an absent ledger fails verify). The shape is fixed now so an assisted path (deferred) can fill it.
173
+ */
174
+ export interface InterventionRecord {
175
+ at: string;
176
+ kind: "stdin";
177
+ /** Redacted+scrubbed digest of the injected input (never the raw bytes). */
178
+ inputDigest: string;
179
+ }
180
+ /**
181
+ * One cost line of the spend ledger. THE NULL DISCIPLINE (issue #154, the cost/no-spend asks):
182
+ * three distinct states are crisply modeled and NEVER conflated —
183
+ * - `usd: 0` => KNOWN to be zero. A measured-and-zero spend (we metered this category and it
184
+ * billed nothing). The no-spend proof may legitimately assert this is zero.
185
+ * - `usd: null` => NOT MEASURED. We carry NO spend signal for this category this slice. `null` is
186
+ * written explicitly (never undefined-omitted, never guessed to 0). The no-spend
187
+ * proof must list this line as UNMEASURED and must NOT claim it is zero.
188
+ * - line ABSENT => NOT APPLICABLE to this lane/run (n/a). The line simply does not appear in
189
+ * `lines`. (This slice always emits all four lines, so absence is reserved for
190
+ * future lanes that genuinely have no such category.)
191
+ * `null` vs missing-key is the load-bearing distinction: a missing key means "this category does not
192
+ * exist for this run"; a present key with `null` means "this category exists but we did not measure
193
+ * it". A no-spend proof that claimed zero on a `null` line would claim more than it measured.
194
+ */
195
+ export interface CostLine {
196
+ /** known zero (0) | not measured (null). The key is ALWAYS present when the line is applicable. */
197
+ usd: number | null;
198
+ /** Optional billable-unit count, same discipline: a known count, or null = not measured. */
199
+ count?: number | null;
200
+ /** How this line's value was established (provenance for the verifier + the human reviewer). */
201
+ source: "provider-token-usage" | "no-spend-signal" | "operator-cap" | "unmeasured";
202
+ /** A short, public-safe note (never a secret value). */
203
+ note: string;
204
+ }
205
+ /** The cost categories the lane meters. product/media/payment are adapter signals (SLICE 4); the
206
+ * provider line can be populated this slice from the actor trace's tokenUsage.costUsd when present. */
207
+ export type CostCategory = "product" | "media" | "payment" | "provider";
208
+ /**
209
+ * The spend ledger (a block of `TerminalLedgers`). The no-spend PROOF is DERIVED from this — never
210
+ * asserted independently. Every applicable category appears as a line; unknowns are `null`.
211
+ */
212
+ export interface TerminalCostLedger {
213
+ schema: "humanish.terminal-cost-ledger.v1";
214
+ /** USD currency unit (recorded explicitly so a future multi-currency lane is unambiguous). */
215
+ currency: "usd";
216
+ lines: Record<CostCategory, CostLine>;
217
+ /** Sum of the KNOWN (non-null) lines. null lines contribute NOTHING and are NOT guessed as 0. */
218
+ knownTotalUsd: number;
219
+ /** True when every applicable line is measured (no null). When false, knownTotalUsd is a LOWER
220
+ * bound, not the full spend — the no-spend proof says so honestly. */
221
+ fullyMeasured: boolean;
222
+ }
223
+ /**
224
+ * The no-spend proof, DERIVED from the cost ledger (issue #154: "derived from a ledger, not
225
+ * asserted"). It is honest about what it knows: it lists the KNOWN-zero lines it can vouch for and,
226
+ * separately, the UNMEASURED (null) lines it CANNOT vouch for. `satisfied` is true only when every
227
+ * KNOWN line is zero (a known non-zero line fails it); but a proof with unmeasured lines explicitly
228
+ * says it could not measure them — it never claims zero on a line the ledger marks null.
229
+ */
230
+ export interface NoSpendProof {
231
+ schema: "humanish.terminal-no-spend-proof.v1";
232
+ /** The maxUsd cap this proof was evaluated against (the no-spend scenario declares maxUsd: 0). */
233
+ maxUsd: number | null;
234
+ /** True iff every KNOWN (measured) line is <= maxUsd (for a no-spend run, == 0). */
235
+ satisfied: boolean;
236
+ /** Categories the ledger MEASURED and found at (known) zero — the proof CAN vouch for these. */
237
+ knownZeroLines: CostCategory[];
238
+ /** Categories the ledger measured with a known NON-zero spend (these break `satisfied`). */
239
+ knownNonZeroLines: CostCategory[];
240
+ /** Categories the ledger marks `null` (NOT MEASURED). The proof explicitly lists these and does
241
+ * NOT claim they are zero — it claims only that it could not measure them this slice. */
242
+ unmeasuredLines: CostCategory[];
243
+ /** Sum of the known lines (== 0 for a satisfied no-spend run). */
244
+ knownTotalUsd: number;
245
+ /** Human-readable honesty statement covering both what is proven and what is unmeasured. */
246
+ statement: string;
247
+ }
248
+ /** The persisted terminal-product ledgers artifact (substrate lifecycle + command log + interventions + cleanup + cost). */
249
+ export interface TerminalLedgers {
250
+ schema: "humanish.terminal-ledgers.v1";
251
+ lifecycle: LifecycleRecord[];
252
+ commandLog: CommandLogRecord[];
253
+ /** ALWAYS present; ALWAYS empty this slice (no assisted-input path) — the safety contract. */
254
+ interventions: InterventionRecord[];
255
+ cleanup: {
256
+ /** True when Sandbox.kill(id) resolved without throwing (either found-and-killed, or a 404
257
+ * meaning the exact id was already gone -- both prove absence; see `remaining`/`reason`). */
258
+ killed: boolean;
259
+ /** BY-ID proof, NEVER derived from Sandbox.list: 0 = confirmed reclaimed (kill(id) RESOLVED
260
+ * -- returned true "found and killed" OR false "404, exact id already gone" -- and, when the
261
+ * SDK exposes it, getInfo(id) did not report a live sandbox); 1 = getInfo(id) still reports
262
+ * this exact sandbox running/paused (NOT reclaimed); -1 = kill(id) itself failed, threw, or
263
+ * was unavailable (the server-side kill-on-timeout is the backstop). */
264
+ remaining: number;
265
+ /** Honest, human-readable statement of which by-id signal produced `remaining`. */
266
+ reason: string;
267
+ };
268
+ /** The spend ledger (SLICE 3, additive). Unknowns are `null`, never guessed; the no-spend proof
269
+ * below is DERIVED from it. */
270
+ cost: TerminalCostLedger;
271
+ /** The no-spend proof DERIVED from `cost` (SLICE 3). Never an independent assertion. */
272
+ noSpendProof: NoSpendProof;
273
+ }
274
+ /**
275
+ * Build the sandbox metadata from a POSITIVE ALLOWLIST (safety contract item 6). This is the ONLY
276
+ * way metadata is set on the terminal lane — it carries solely non-secret labels and rejects any
277
+ * value that is not a plain short label. A verifier check asserts the persisted metadata has no
278
+ * prompt/token/secret shapes; this builder makes that true by construction.
279
+ */
280
+ export declare function buildSandboxMetadata(allowlist: {
281
+ labId: string;
282
+ simId: string;
283
+ runId: string;
284
+ }): Record<string, string>;
285
+ /**
286
+ * Project the terminal-product lab run into a humanish.run-bundle.v1 (no schema change — a new
287
+ * producer only). DRY-RUN: a contract bundle. The terminal stream is a contract placeholder
288
+ * (stdin disabled, no captured tail — honest: nothing ran), the subject is declared UNPINNED, and
289
+ * the caps/policies/runtime-auth declarations + empty ledgers are recorded so SLICE 2 has a stable
290
+ * shape to fill. Exported for the bundle-builder tests.
291
+ */
292
+ export declare function buildTerminalProductBundle(args: {
293
+ actorId: string;
294
+ createdAt: string;
295
+ dryRun: boolean;
296
+ labId: string;
297
+ labTitle?: string;
298
+ mission: string;
299
+ persona: ActorPersonaRef;
300
+ productName: string;
301
+ publicSurfaces: string[];
302
+ caps?: LabScenarioCaps;
303
+ runtimeAuth?: string;
304
+ stdin: "disabled" | "planned" | "sent";
305
+ policies: {
306
+ allowPrivateRepoAccess: boolean;
307
+ allowProviderCredentials: boolean;
308
+ allowPaymentCredentials: boolean;
309
+ allowGitHubMutation: boolean;
310
+ };
311
+ runId: string;
312
+ source: RunBundle["source"];
313
+ }): RunBundle;
314
+ /**
315
+ * Build the LIVE terminal-product run bundle (mode "live") from the captured session: the actor
316
+ * trace seam (stream.actor = trace), the substrate-lifecycle events, the terminal stream with the
317
+ * redacted transcript tail, and references to the written evidence artifacts (terminal event
318
+ * stream, transcript, ledgers, actor trace). verifyRun's terminal-product check (gated on
319
+ * mode==="live") enforces the ledgers + proven cleanup + interventions-present over this bundle.
320
+ */
321
+ export declare function buildLiveTerminalProductBundle(args: {
322
+ actorId: string;
323
+ createdAt: string;
324
+ labId: string;
325
+ labTitle?: string;
326
+ mission: string;
327
+ persona: ActorPersonaRef;
328
+ productName: string;
329
+ publicSurfaces: string[];
330
+ caps?: LabScenarioCaps;
331
+ runtimeAuthKeyName: string;
332
+ policies: {
333
+ allowPrivateRepoAccess: boolean;
334
+ allowProviderCredentials: boolean;
335
+ allowPaymentCredentials: boolean;
336
+ allowGitHubMutation: boolean;
337
+ };
338
+ runId: string;
339
+ source: RunBundle["source"];
340
+ trace: ActorTrace;
341
+ ledgers: TerminalLedgers;
342
+ sandboxId?: string;
343
+ sessionError?: string;
344
+ sessionReason: string;
345
+ }): RunBundle;