humanish 0.0.1 → 0.15.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 (196) hide show
  1. package/AGENTS.md +77 -0
  2. package/CONTRIBUTING.md +39 -0
  3. package/LICENSE +21 -0
  4. package/README.md +435 -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 +356 -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 +327 -0
  32. package/dist/codex-app-server-ui.js.map +1 -0
  33. package/dist/codex-app-server.d.ts +141 -0
  34. package/dist/codex-app-server.js +747 -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 +1092 -0
  50. package/dist/concurrent-shared-world-lab.js.map +1 -0
  51. package/dist/core/git-state.d.ts +31 -0
  52. package/dist/core/git-state.js +142 -0
  53. package/dist/core/git-state.js.map +1 -0
  54. package/dist/core/index.d.ts +4 -0
  55. package/dist/core/index.js +3 -0
  56. package/dist/core/index.js.map +1 -0
  57. package/dist/core/run-primitives.d.ts +66 -0
  58. package/dist/core/run-primitives.js +120 -0
  59. package/dist/core/run-primitives.js.map +1 -0
  60. package/dist/cua-actor-lab.d.ts +620 -0
  61. package/dist/cua-actor-lab.js +2834 -0
  62. package/dist/cua-actor-lab.js.map +1 -0
  63. package/dist/device-presets.d.ts +67 -0
  64. package/dist/device-presets.js +50 -0
  65. package/dist/device-presets.js.map +1 -0
  66. package/dist/e2b-desktop-executor.d.ts +101 -0
  67. package/dist/e2b-desktop-executor.js +309 -0
  68. package/dist/e2b-desktop-executor.js.map +1 -0
  69. package/dist/e2b-desktop-launch.d.ts +144 -0
  70. package/dist/e2b-desktop-launch.js +59 -0
  71. package/dist/e2b-desktop-launch.js.map +1 -0
  72. package/dist/e2b-detached.d.ts +53 -0
  73. package/dist/e2b-detached.js +130 -0
  74. package/dist/e2b-detached.js.map +1 -0
  75. package/dist/e2b-terminal-lab.d.ts +345 -0
  76. package/dist/e2b-terminal-lab.js +1467 -0
  77. package/dist/e2b-terminal-lab.js.map +1 -0
  78. package/dist/env-file.d.ts +14 -0
  79. package/dist/env-file.js +108 -0
  80. package/dist/env-file.js.map +1 -0
  81. package/dist/feedback.d.ts +51 -0
  82. package/dist/feedback.js +313 -0
  83. package/dist/feedback.js.map +1 -0
  84. package/dist/image-evidence.d.ts +2 -0
  85. package/dist/image-evidence.js +33 -0
  86. package/dist/image-evidence.js.map +1 -0
  87. package/dist/index.d.ts +63 -0
  88. package/dist/index.js +33 -0
  89. package/dist/index.js.map +1 -0
  90. package/dist/init-templates.d.ts +12 -0
  91. package/dist/init-templates.js +369 -0
  92. package/dist/init-templates.js.map +1 -0
  93. package/dist/init.d.ts +26 -0
  94. package/dist/init.js +343 -0
  95. package/dist/init.js.map +1 -0
  96. package/dist/lab-app-runner.d.ts +78 -0
  97. package/dist/lab-app-runner.js +403 -0
  98. package/dist/lab-app-runner.js.map +1 -0
  99. package/dist/lab-config.d.ts +578 -0
  100. package/dist/lab-config.js +1751 -0
  101. package/dist/lab-config.js.map +1 -0
  102. package/dist/lab-engine.d.ts +77 -0
  103. package/dist/lab-engine.js +216 -0
  104. package/dist/lab-engine.js.map +1 -0
  105. package/dist/lab-preflight.d.ts +67 -0
  106. package/dist/lab-preflight.js +385 -0
  107. package/dist/lab-preflight.js.map +1 -0
  108. package/dist/labs.d.ts +53 -0
  109. package/dist/labs.js +176 -0
  110. package/dist/labs.js.map +1 -0
  111. package/dist/observer-assets.d.ts +2 -0
  112. package/dist/observer-assets.js +2630 -0
  113. package/dist/observer-assets.js.map +1 -0
  114. package/dist/observer-data.d.ts +63 -0
  115. package/dist/observer-data.js +145 -0
  116. package/dist/observer-data.js.map +1 -0
  117. package/dist/observer-static.d.ts +39 -0
  118. package/dist/observer-static.js +192 -0
  119. package/dist/observer-static.js.map +1 -0
  120. package/dist/observer.d.ts +46 -0
  121. package/dist/observer.js +353 -0
  122. package/dist/observer.js.map +1 -0
  123. package/dist/openai-responses-cu.d.ts +113 -0
  124. package/dist/openai-responses-cu.js +531 -0
  125. package/dist/openai-responses-cu.js.map +1 -0
  126. package/dist/oss-lab.d.ts +52 -0
  127. package/dist/oss-lab.js +299 -0
  128. package/dist/oss-lab.js.map +1 -0
  129. package/dist/oss-meta-lab-scoring.d.ts +15 -0
  130. package/dist/oss-meta-lab-scoring.js +145 -0
  131. package/dist/oss-meta-lab-scoring.js.map +1 -0
  132. package/dist/oss-meta-lab.d.ts +279 -0
  133. package/dist/oss-meta-lab.js +4889 -0
  134. package/dist/oss-meta-lab.js.map +1 -0
  135. package/dist/oss-remote-telemetry.d.ts +77 -0
  136. package/dist/oss-remote-telemetry.js +403 -0
  137. package/dist/oss-remote-telemetry.js.map +1 -0
  138. package/dist/persona.d.ts +35 -0
  139. package/dist/persona.js +133 -0
  140. package/dist/persona.js.map +1 -0
  141. package/dist/pi-agent-core.d.ts +77 -0
  142. package/dist/pi-agent-core.js +203 -0
  143. package/dist/pi-agent-core.js.map +1 -0
  144. package/dist/program.d.ts +54 -0
  145. package/dist/program.js +2347 -0
  146. package/dist/program.js.map +1 -0
  147. package/dist/redaction.d.ts +90 -0
  148. package/dist/redaction.js +292 -0
  149. package/dist/redaction.js.map +1 -0
  150. package/dist/run.d.ts +784 -0
  151. package/dist/run.js +4555 -0
  152. package/dist/run.js.map +1 -0
  153. package/dist/scripted-browser-actor.d.ts +294 -0
  154. package/dist/scripted-browser-actor.js +1286 -0
  155. package/dist/scripted-browser-actor.js.map +1 -0
  156. package/dist/scripted-browser-lab.d.ts +107 -0
  157. package/dist/scripted-browser-lab.js +738 -0
  158. package/dist/scripted-browser-lab.js.map +1 -0
  159. package/dist/shared-world-lab.d.ts +208 -0
  160. package/dist/shared-world-lab.js +1048 -0
  161. package/dist/shared-world-lab.js.map +1 -0
  162. package/dist/source-archive.d.ts +82 -0
  163. package/dist/source-archive.js +365 -0
  164. package/dist/source-archive.js.map +1 -0
  165. package/dist/stop-conditions.d.ts +26 -0
  166. package/dist/stop-conditions.js +66 -0
  167. package/dist/stop-conditions.js.map +1 -0
  168. package/dist/terminal-agent-actor.d.ts +36 -0
  169. package/dist/terminal-agent-actor.js +23 -0
  170. package/dist/terminal-agent-actor.js.map +1 -0
  171. package/docs/architecture/actor-contract.md +431 -0
  172. package/docs/architecture/github-feedback-loop.md +189 -0
  173. package/docs/architecture/local-codex-tui-actor.md +213 -0
  174. package/docs/architecture/observer.md +118 -0
  175. package/docs/architecture/oss-lab-poc.md +242 -0
  176. package/docs/architecture/project-layout.md +166 -0
  177. package/docs/architecture/state-driven-executor.md +203 -0
  178. package/docs/architecture/terminal-product-lane.md +148 -0
  179. package/docs/contracts/adapter-fixtures.md +80 -0
  180. package/docs/contracts/core.md +71 -0
  181. package/docs/contracts/feedback.md +145 -0
  182. package/docs/contracts/policy.md +305 -0
  183. package/docs/contracts/run-bundle.md +358 -0
  184. package/docs/contracts/schemas.md +984 -0
  185. package/docs/goals/current.md +409 -0
  186. package/docs/principles/invariants-and-defaults.md +135 -0
  187. package/docs/principles/self-driving-harness.md +129 -0
  188. package/docs/product/open-source-install-experience.md +229 -0
  189. package/docs/ramp/README.md +200 -0
  190. package/docs/release/open-source-readiness.md +208 -0
  191. package/docs/release/public-readiness-standard.md +205 -0
  192. package/docs/roadmap/world-class-open-source-v0.md +311 -0
  193. package/package.json +102 -8
  194. package/skills/humanish/SKILL.md +244 -0
  195. package/skills/humanish/agents/openai.yaml +7 -0
  196. package/index.js +0 -1
package/dist/run.d.ts ADDED
@@ -0,0 +1,784 @@
1
+ import { type CodexAppServerTrace } from "./codex-app-server.js";
2
+ import { type ActorTrace } from "./actor-contract.js";
3
+ import { type CapturedGitState } from "./core/git-state.js";
4
+ import { type E2BDesktopModule } from "./e2b-desktop-launch.js";
5
+ export declare const RUN_BUNDLE_SCHEMA = "humanish.run-bundle.v1";
6
+ export declare const SHARED_WORLD_SCHEMA = "humanish.shared-world.v1";
7
+ export declare const REVIEW_SCHEMA = "humanish.review.v1";
8
+ export declare const VERIFY_SCHEMA = "humanish.verify-result.v1";
9
+ export declare const RUNS_SCHEMA = "humanish.runs-result.v1";
10
+ export declare const DOCTOR_SCHEMA = "humanish.doctor-result.v1";
11
+ export declare const CLEANUP_SCHEMA = "humanish.cleanup-result.v1";
12
+ export declare const PUBLIC_TARGET_CWD = "[target-cwd]";
13
+ export interface RunOptions {
14
+ cwd: string;
15
+ actor?: string;
16
+ actorCommand?: string[];
17
+ appUrl?: string;
18
+ dryRun?: boolean;
19
+ runId?: string;
20
+ simCount?: number;
21
+ timeoutMs?: number;
22
+ }
23
+ export type RunStreamKind = "ui" | "browser" | "terminal" | "tui" | "codex-ui" | "artifact" | "summary";
24
+ export type RunSimulationStatus = "queued" | "preparing" | "running" | "passed" | "complete" | "blocked" | "timed_out" | "failed" | "contract_proof_only";
25
+ export interface RunStreamCompletion {
26
+ actorLogPath?: string;
27
+ actorLogTail?: string;
28
+ actorLastMessageTail?: string;
29
+ actorPid?: number;
30
+ actorStatus?: "not_started" | "running" | "passed" | "failed" | "blocked" | "timed_out" | "suspended" | "unknown";
31
+ appLogPath?: string;
32
+ appPid?: number;
33
+ appReason?: string;
34
+ appStatus?: "not_started" | "running" | "blocked" | "failed" | "missing" | "unknown";
35
+ appUrl?: string;
36
+ checkedAt: string;
37
+ exitCode?: number;
38
+ logTail?: string;
39
+ nestedObserverPresent?: boolean;
40
+ nestedVerifyPassed?: boolean;
41
+ reason: string;
42
+ status: "running" | "passed" | "failed" | "blocked" | "timed_out";
43
+ visualReason?: string;
44
+ visualStatus?: "not_started" | "visible" | "blocked" | "unknown";
45
+ visualWindowCount?: number;
46
+ meaningfulUse?: RunMeaningfulUseScore;
47
+ }
48
+ export interface RunSetupQualitySnapshot {
49
+ schema: "humanish.setup-quality.v1";
50
+ generatedAt: string;
51
+ redaction: {
52
+ status: "passed";
53
+ rawPreviews: "included" | "suppressed";
54
+ notes: string;
55
+ };
56
+ summary: string;
57
+ status: "passed" | "needs_review" | "blocked";
58
+ checks: Array<{
59
+ id: string;
60
+ label: string;
61
+ ok: boolean;
62
+ detail: string;
63
+ }>;
64
+ tree: Array<{
65
+ path: string;
66
+ type: "file" | "directory";
67
+ sizeBytes?: number;
68
+ }>;
69
+ previews: Array<{
70
+ path: string;
71
+ language: "json" | "yaml" | "typescript" | "markdown" | "text";
72
+ truncated: boolean;
73
+ text: string;
74
+ }>;
75
+ studyQuality?: {
76
+ schema: "humanish.study-quality.v1";
77
+ rating: "none" | "ceremonial" | "useful" | "high_leverage";
78
+ summary: string;
79
+ checks: Array<{
80
+ id: string;
81
+ label: string;
82
+ ok: boolean;
83
+ detail: string;
84
+ }>;
85
+ signals: {
86
+ appUrlProofBlocked: boolean;
87
+ appUrlProofMentioned: boolean;
88
+ actorInsightCaptured: boolean;
89
+ coverageCustomized: boolean;
90
+ personaCustomized: boolean;
91
+ scenarioCustomized: boolean;
92
+ };
93
+ };
94
+ packageScripts: Record<string, string>;
95
+ humanish: {
96
+ configPresent: boolean;
97
+ personaCount: number;
98
+ scenarioCount: number;
99
+ packageScriptPresent: boolean;
100
+ gitignoreContainsRuntimeIgnore: boolean;
101
+ };
102
+ }
103
+ /**
104
+ * The CLOSED set of core meaningful-use scoring components. Closed by design: these are the generic
105
+ * dimensions core itself meters (setup/filesystem/nested/actor/product/feedback). A product-specific
106
+ * scorecard does NOT extend this enum (that would be closed-taxonomy rot — every adopter's nouns
107
+ * leaking into core); it ships as a thin in-repo extension that emits a namespaced `RunAdapterScore`
108
+ * via the lane's `score` hook, leaving its own component breakdown in that score's `data`. Exported
109
+ * so a thin adapter can type against core's score shape without forking.
110
+ */
111
+ export type RunMeaningfulUseComponentId = "setup-correctness" | "filesystem-evidence" | "nested-humanish-evidence" | "actor-activity" | "product-surface" | "feedback-quality";
112
+ export interface RunMeaningfulUseScore {
113
+ schema: "humanish.meaningful-use-score.v1";
114
+ status: "pass" | "partial" | "fail";
115
+ score: number;
116
+ summary: string;
117
+ hardFailures: string[];
118
+ components: Array<{
119
+ id: RunMeaningfulUseComponentId;
120
+ label: string;
121
+ status: "pass" | "partial" | "fail";
122
+ score: number;
123
+ detail: string;
124
+ }>;
125
+ }
126
+ /**
127
+ * A namespaced, product-agnostic score a thin adapter attaches to the bundle via the terminal-product
128
+ * lane's `score` hook (the layer-6 extension seam, issue #154 acceptance #8). Core never reads its
129
+ * `data` and knows none of the adopter's nouns — the `namespace` (e.g. `"acme-pixelforge"`) scopes
130
+ * the whole record so core schemas stay product-agnostic and a future inert-field audit does not
131
+ * misfire on a noun core never owned. The adopter's real scorecard (component weights, product
132
+ * rubric) lives in ITS repo and is summarized into the generic status/score/summary; everything
133
+ * product-specific rides under `data`. This is NOT a built-in product scorer — it is the SEAM the
134
+ * adopter's scorer plugs into without forking core.
135
+ */
136
+ export interface RunAdapterScore {
137
+ schema: "humanish.adapter-score.v1";
138
+ /** The adapter's namespace — non-core, product-scoped (e.g. an adopter slug). Required + non-empty. */
139
+ namespace: string;
140
+ status: "pass" | "partial" | "fail";
141
+ /** A 0-100 summary the adapter derived from its own (off-core) rubric. */
142
+ score: number;
143
+ summary: string;
144
+ /** Arbitrary product-specific payload (the adopter's component breakdown / nouns). Core never reads it. */
145
+ data?: Record<string, unknown>;
146
+ }
147
+ export interface RunFeedbackCandidate {
148
+ schema: "humanish.feedback-candidate.v1";
149
+ id: string;
150
+ run_id: string;
151
+ stream_id?: string;
152
+ adapter_id: string;
153
+ scenario_id: string;
154
+ persona_id: string;
155
+ actor: "codex-tui" | "codex-exec" | "codex-app-server" | "synthetic-dry-run" | "unknown";
156
+ substrate: "e2b-desktop" | "e2b-terminal" | "local-filesystem" | "codex-app-server" | "unknown";
157
+ failure_owner: "harness" | "target-app" | "actor" | "environment" | "unknown";
158
+ summary: string;
159
+ expected: string;
160
+ actual: string;
161
+ evidence: Array<{
162
+ path: string;
163
+ kind: "review" | "state" | "log" | "trace" | "screenshot" | "filesystem";
164
+ note: string;
165
+ }>;
166
+ redaction: {
167
+ status: "passed";
168
+ notes: string;
169
+ };
170
+ idempotency_key: string;
171
+ proposed_next_state: "watch" | "adapter-hardening" | "target-app-setup" | "actor-auth" | "setup-quality-review" | "study-quality-review";
172
+ acceptance_proof: string[];
173
+ /**
174
+ * OPTIONAL, ADAPTER-NAMESPACED product-noun block (the layer-6 extension seam, issue #154
175
+ * acceptance #8 + the "record product-specific concepts as NON-core nouns" list). A thin adapter
176
+ * records product-specific concepts — public CLI/product command observed, hosted product
177
+ * success-or-blocker, feedback id/draft observed, media/job/asset ids, explicit
178
+ * no-media/no-provider-spend proof, defection/friction risk — WITHOUT making any of them core
179
+ * primitives. They ride under a single namespaced field so core's feedback enums
180
+ * (`evidence.kind`, `proposed_next_state`) stay product-agnostic and a future inert-field audit
181
+ * never misfires on a noun core never owned. Core validates only the SHAPE (a non-empty
182
+ * `namespace` + a `data` record); the keys inside `data` are the adapter's, never core's.
183
+ */
184
+ adapter?: {
185
+ /** Non-core, product-scoped namespace (e.g. an adopter slug). Required + non-empty. */
186
+ namespace: string;
187
+ /** The adapter's product nouns. Core never reads these keys — it stays product-agnostic. */
188
+ data: Record<string, unknown>;
189
+ };
190
+ }
191
+ /**
192
+ * Optional, adapter-namespaced artifact references. These let a thin in-repo
193
+ * adapter attach product/state proof outputs to the Humanish evidence packet
194
+ * without teaching core product nouns or inventing fake streams.
195
+ */
196
+ export interface RunAdapterArtifact {
197
+ schema: "humanish.adapter-artifact.v1";
198
+ namespace: string;
199
+ label: string;
200
+ path: string;
201
+ kind: "state" | "review" | "log" | "trace" | "screenshot" | "filesystem" | "summary";
202
+ note: string;
203
+ }
204
+ export interface RunSimulation {
205
+ id: string;
206
+ index: number;
207
+ personaId: string;
208
+ scenarioId: string;
209
+ status: RunSimulationStatus;
210
+ streamKind: RunStreamKind;
211
+ mode: "browser-sim" | "cli-sim" | "tui-sim" | "codex-app-sim";
212
+ progress: number;
213
+ currentStep: string;
214
+ summary: string;
215
+ streamIds: string[];
216
+ startedAt: string;
217
+ updatedAt: string;
218
+ }
219
+ export interface RunStream {
220
+ id: string;
221
+ simId: string;
222
+ /** Adapter-owned lane id for fan-out / target-swarm runs. Safe categorical metadata only. */
223
+ laneId?: string;
224
+ /** Adapter-owned actor class for grouping lanes, e.g. viewer/reviewer/admin. */
225
+ actorType?: string;
226
+ /** Adapter-owned product surface label for grouping lanes without parsing URLs. */
227
+ surface?: string;
228
+ /** Adapter-owned scenario/case grouping label. */
229
+ caseGroup?: string;
230
+ kind: RunStreamKind;
231
+ label: string;
232
+ status: RunSimulationStatus;
233
+ transport: "snapshot" | "polling" | "sse" | "pty" | "app-server";
234
+ updatedAt: string;
235
+ url?: string;
236
+ embed?: {
237
+ kind: "iframe" | "terminal" | "screenshot" | "placeholder";
238
+ url?: string;
239
+ title?: string;
240
+ };
241
+ viewport?: {
242
+ width: number;
243
+ height: number;
244
+ deviceScaleFactor?: number;
245
+ isMobile?: boolean;
246
+ };
247
+ terminal?: {
248
+ title: string;
249
+ format: "ansi" | "plain";
250
+ stdin: "disabled" | "planned" | "sent";
251
+ tail: string;
252
+ };
253
+ ui?: {
254
+ actorStatus?: string;
255
+ appStatus?: string;
256
+ appUrl?: string;
257
+ route?: string;
258
+ intent?: string;
259
+ nestedObserverPath?: string;
260
+ nestedObserverUrl?: string;
261
+ screenshotUrl?: string;
262
+ state?: string;
263
+ visualStatus?: string;
264
+ };
265
+ codex?: {
266
+ provider: "codex-app-server";
267
+ eventCount?: number;
268
+ experimentalApi?: boolean;
269
+ model?: string;
270
+ sessionId?: string;
271
+ state: "not_connected" | "connecting" | "watching" | "running" | "completed" | "failed" | "blocked" | "timed_out";
272
+ contract: string;
273
+ threadId?: string;
274
+ trace?: CodexAppServerTrace;
275
+ tracePath?: string;
276
+ turnId?: string;
277
+ };
278
+ actor?: ActorTrace;
279
+ completion?: RunStreamCompletion;
280
+ artifacts: Array<{
281
+ label: string;
282
+ path: string;
283
+ kind: "bundle" | "review" | "observer" | "events" | "screenshot" | "trace" | "log" | "filesystem";
284
+ }>;
285
+ }
286
+ export interface RunEvent {
287
+ id: string;
288
+ at: string;
289
+ level: "info" | "warn" | "error";
290
+ type: string;
291
+ message: string;
292
+ simId?: string;
293
+ streamId?: string;
294
+ }
295
+ /**
296
+ * One executed (or declared) subject-state seed step. Live records carry execution fields
297
+ * (ok/exitCode/timedOut/durationMs); dry-run "declared, not run" records carry only the
298
+ * declaration (name, phase, command DIGEST). The command itself never persists — the digest
299
+ * pins "same recipe" across bundles while the lab YAML in the consumer's repo stays the
300
+ * plaintext source of truth (publish-safe by construction).
301
+ */
302
+ export interface RunSubjectStateStepRecord {
303
+ name: string;
304
+ when: "before-build" | "before-start" | "after-ready";
305
+ /** sha256 hex of the exact command string, first 16 chars (the promptDigest convention). */
306
+ commandDigest: string;
307
+ /** Absent on declared-not-run records (dry-run; unreached steps are absent entirely). */
308
+ ok?: boolean;
309
+ exitCode?: number;
310
+ timedOut?: boolean;
311
+ durationMs?: number;
312
+ }
313
+ /**
314
+ * Structured subject provenance (invariant 5): what the subject WAS — code pin (repo/commit,
315
+ * or a local-tree archive digest) AND state story. Optional additive field on
316
+ * humanish.run-bundle.v1; absent on bundles from backends that have not adopted it (and on all
317
+ * pre-existing bundles).
318
+ */
319
+ export interface RunSubjectProvenance {
320
+ source: "clone" | "app-url" | "local-tree";
321
+ /** Clone-route only. Honors policies.redactRepos exactly as the provenance event does. */
322
+ repo?: string;
323
+ /** Clone-route: the cloned commit SHA. Local-tree route: the host-side HEAD at pack time,
324
+ * when the packed root was a git work tree. */
325
+ commit?: string;
326
+ /**
327
+ * Local-tree-route only (additive): 64 lowercase-hex sha256 over the sorted packed-entries
328
+ * list (docs/contracts/schemas.md). This is the provenance PIN for the local-tree route: a
329
+ * dirty working tree cannot be commit-pinned, so the archive content digest stands in for it.
330
+ */
331
+ archiveSha256?: string;
332
+ /**
333
+ * Local-tree-route only (additive): true when the host git work tree had uncommitted changes
334
+ * at pack time. Absent when the packed root was not a git work tree at all.
335
+ */
336
+ dirty?: boolean;
337
+ /** Declared env NAMES provisioned for the subject — names only, values never. */
338
+ envNames?: string[];
339
+ state: {
340
+ /**
341
+ * seeded: live run, steps declared, ALL ran ok, no external state declared.
342
+ * unpinned: external state declared (seed records, if any, still attached — migrating
343
+ * an external DB is still unpinned overall).
344
+ * declared-not-run: steps declared but not (all) executed ok — dry-run contract bundles
345
+ * and failed live provisioning.
346
+ * undeclared: no subject.state block (stateless apps, app-url subjects) — the explicit
347
+ * "absence declared" marker invariant 5 requires.
348
+ */
349
+ provenance: "seeded" | "unpinned" | "declared-not-run" | "undeclared";
350
+ seed?: RunSubjectStateStepRecord[];
351
+ externalEnvNames?: string[];
352
+ };
353
+ }
354
+ /**
355
+ * How well a run attributed INTERACTION between actors — a new, ORTHOGONAL honesty axis to the
356
+ * persona-sampling evidence classes (which answer "how representative is the actor?"). Absent ==
357
+ * `isolated` (every existing bundle byte-stable). `shared-world` means N roles drove ONE mutable
358
+ * plane and their per-role attribution is weaker (its ceiling is pinned in `sharedWorld.attributionLimits`).
359
+ */
360
+ export type RunAttributionClass = "isolated" | "shared-world";
361
+ /** The ONE shared service-plane provenance for a shared-world run (#164): single commit + a
362
+ * seed-recipe digest + the provisioned env NAMES (values never). */
363
+ export interface SharedWorldPlane {
364
+ /** The cloned commit SHA of the shared plane (when the clone resolved one). */
365
+ commit?: string;
366
+ /** sha256-16 over the ordered seed-step command digests — the seeded-state RECIPE identity
367
+ * (not the runtime state). Pins "same seed recipe" across bundles. */
368
+ seedDigest: string;
369
+ /** Declared env NAMES provisioned for the shared plane (values never surface). */
370
+ envNames: string[];
371
+ /**
372
+ * CONCURRENT route only (#164 phase 2): sha256-16 of the harness-minted `getHost` URL's ORIGIN
373
+ * (the first-class provisioned-subject target every actor drove — invariant 2). A DIGEST, not the
374
+ * raw URL: a getHost URL embeds the (live) sandbox id and matches the publish-safety e2b-URL
375
+ * redaction, so — like the stream URL and like sandbox ids — it never lands raw in a published
376
+ * bundle (the raw tokenless URL is surfaced only on the ephemeral lab result). The orchestrator
377
+ * confirms the URL is TOKENLESS (no authKey — invariant 1) before digesting. verify proves every
378
+ * actor drove this host by digest equality. Absent on the sequential route.
379
+ */
380
+ hostDigest?: string;
381
+ /**
382
+ * CONCURRENT route only: the author's REQUIRED attestation that the subject behind the
383
+ * internet-reachable getHost URL is synthetic seeded data (FIX-3). This is author-trust + a
384
+ * provenance gate, NOT a no-real-data guarantee. Verify fails closed if absent on the concurrent route.
385
+ */
386
+ exposure?: "synthetic";
387
+ }
388
+ /**
389
+ * CONCURRENT shape (#164 phase 2): one actor's harness-clocked activity window against the ONE
390
+ * shared plane. OVERLAPPING windows mechanically prove ≥2 personas were active simultaneously.
391
+ * `laneWindows` and `stateSeries` are INDEPENDENT series — there is deliberately NO per-delta→actor
392
+ * field (causation under concurrency is structurally inexpressible — FIX-7).
393
+ */
394
+ export interface SharedWorldLaneWindow {
395
+ roleId: string;
396
+ actorType?: string;
397
+ surface?: string;
398
+ caseGroup?: string;
399
+ /** Resolves to a real RunSimulation in this bundle. */
400
+ simId: string;
401
+ /** Resolves to a real RunStream (the actor's trace) in this bundle. */
402
+ streamId: string;
403
+ /** ms on the ONE harness clock — the wrapped [start,end] the orchestrator MEASURED (FIX-1). */
404
+ startedAt: number;
405
+ endedAt: number;
406
+ /** The actor's terminal session verdict (per-persona). */
407
+ verdict: string;
408
+ /** sha256-16 of the ORIGIN of the getHost seat URL this actor drove. verify confirms it equals
409
+ * plane.hostDigest — i.e. the actor drove EXACTLY the harness-minted host (invariant 2; FIX-2).
410
+ * A digest, not the raw URL (a getHost URL is not publish-safe — see SharedWorldPlane.hostDigest). */
411
+ routeHostDigest: string;
412
+ /** The shared plane's commit this actor observed (omitted when unresolved). */
413
+ commit?: string;
414
+ /** The shared plane's seed-recipe digest this actor observed. */
415
+ seedDigest: string;
416
+ }
417
+ /** CONCURRENT shape: one cadence checkpoint of the shared world under load. DIGEST-ONLY — the
418
+ * allowed-keys tripwire (SHARED_WORLD_STATESERIES_KEYS) permits ONLY {timestamp, digest}. */
419
+ export interface SharedWorldStateSnapshot {
420
+ /** ms on the ONE harness clock. */
421
+ timestamp: number;
422
+ /** sha256-16 of the (scrubbed, redacted) combined probe output at this snapshot. */
423
+ digest: string;
424
+ }
425
+ /** CONCURRENT shape: one persona's OUTCOME against the contended world (the "M of N" headline). */
426
+ export interface SharedWorldOutcome {
427
+ roleId: string;
428
+ actorType?: string;
429
+ surface?: string;
430
+ caseGroup?: string;
431
+ simId: string;
432
+ streamId: string;
433
+ /** Terminal session status. */
434
+ status: string;
435
+ completionReason?: string;
436
+ /** Reached its goal (terminal, engaged, no harness error). */
437
+ ok: boolean;
438
+ }
439
+ /** A timeline checkpoint: a read-only digest probe of the shared plane at one moment. Persisted
440
+ * DIGEST-ONLY — `digest` is sha256-16(scrub+redact(stdout)); no raw value ever lands. */
441
+ export interface SharedWorldCheckpoint {
442
+ kind: "checkpoint";
443
+ /** "cp-baseline" for the baseline snapshot; "cp-after-<roleId>" after each role's turn. */
444
+ name: string;
445
+ /** sha256-16 of the (scrubbed, redacted) combined probe output at this snapshot. */
446
+ digest: string;
447
+ /** True when this snapshot's digest differs from the previous checkpoint's — the observed
448
+ * state changed across the intervening turn (delta attributed to the TURN, not an action). */
449
+ deltaFromPrev: boolean;
450
+ }
451
+ /** A timeline turn: one role's seat session against the shared plane. Carries the plane
452
+ * provenance it observed (identical across turns by construction — the single-plane proof). */
453
+ export interface SharedWorldTurn {
454
+ kind: "turn";
455
+ roleId: string;
456
+ /** Resolves to a real RunSimulation in this bundle. */
457
+ simId: string;
458
+ /** Resolves to a real RunStream (the role's actor trace) in this bundle. */
459
+ streamId: string;
460
+ /** The shared plane's commit the role observed (omitted when unresolved). */
461
+ commit?: string;
462
+ /** The shared plane's seed-recipe digest the role observed. */
463
+ seedDigest: string;
464
+ }
465
+ export type SharedWorldTimelineEntry = SharedWorldCheckpoint | SharedWorldTurn;
466
+ /**
467
+ * The shared-world evidence block (`humanish.shared-world.v1`). TWO variants discriminated by
468
+ * `topologyMode` (FIX-8 — renamed off `RunBundle.mode` to avoid the dry-run|live collision):
469
+ *
470
+ * - SEQUENTIAL (`topologyMode: "sequential"`, the PoC): `sequence` + an alternating `timeline`
471
+ * (cp-baseline → turn → cp → … → cp); limits `sequential-only` etc.
472
+ * - CONCURRENT (`topologyMode: "concurrent"`, #164 phase 2): `laneWindows` + `stateSeries` +
473
+ * `outcomes`; limits `concurrent` etc. NO `timeline`.
474
+ *
475
+ * Additive + optional on `humanish.run-bundle.v1` — absent on every non-shared-world bundle.
476
+ * The mandatory `attributionLimits` are verify-enforced (FAIL CLOSED on a missing required or a
477
+ * present forbidden limit).
478
+ */
479
+ export interface SharedWorldEvidence {
480
+ schema: typeof SHARED_WORLD_SCHEMA;
481
+ topology: "shared-world";
482
+ /** The substrate discriminator (FIX-8). Branched on FIRST by validateSharedWorldEvidence. */
483
+ topologyMode: "sequential" | "concurrent";
484
+ /** The DECLARED number of role seats. */
485
+ roleCount: number;
486
+ plane: SharedWorldPlane;
487
+ /** The pinned, verify-enforced attribution ceiling (the set differs per topologyMode). */
488
+ attributionLimits: string[];
489
+ /** The role ids that actually took a turn, in declared order. */
490
+ sequence?: string[];
491
+ timeline?: SharedWorldTimelineEntry[];
492
+ /** Per-actor harness-clocked windows (overlap proves simultaneity). */
493
+ laneWindows?: SharedWorldLaneWindow[];
494
+ /** Cadence digests of the shared world under load (baseline + periodic + final). */
495
+ stateSeries?: SharedWorldStateSnapshot[];
496
+ /** Per-persona outcomes (the "M of N succeeded" headline). */
497
+ outcomes?: SharedWorldOutcome[];
498
+ }
499
+ export interface RunBundle {
500
+ schema: typeof RUN_BUNDLE_SCHEMA;
501
+ runId: string;
502
+ mode: "dry-run" | "live";
503
+ simCount: number;
504
+ createdAt: string;
505
+ cwd: string;
506
+ artifactRoot: string;
507
+ source: {
508
+ packageName: string | null;
509
+ humanishSource: "present" | "missing";
510
+ git: CapturedGitState;
511
+ };
512
+ persona: {
513
+ id: string;
514
+ name: string;
515
+ source: string;
516
+ sourceDigest: string;
517
+ };
518
+ scenario: {
519
+ id: string;
520
+ title: string;
521
+ goal: string;
522
+ source: string;
523
+ sourceDigest: string;
524
+ };
525
+ lifecycle: Array<{
526
+ at: string;
527
+ event: string;
528
+ message: string;
529
+ }>;
530
+ simulations: RunSimulation[];
531
+ streams: RunStream[];
532
+ events: RunEvent[];
533
+ redaction: {
534
+ status: "passed";
535
+ notes: string;
536
+ };
537
+ artifacts: {
538
+ run: string;
539
+ reviewJson: string;
540
+ reviewMarkdown: string;
541
+ observerData: string;
542
+ events: string;
543
+ };
544
+ review: ReviewSummary;
545
+ feedbackCandidates: RunFeedbackCandidate[];
546
+ /** Structured subject provenance (invariant 5). Optional and additive: emitted by the
547
+ * computer-use backend; tolerated absent everywhere else. */
548
+ subject?: RunSubjectProvenance;
549
+ /**
550
+ * The custom E2B desktop TEMPLATE (image) the run's sandbox(es) actually launched on, from
551
+ * `execution.desktop.template` — so the evidence shows WHICH image ran (a subject needing
552
+ * runtimes the stock `desktop` image lacks runs on an adopter's template). Optional + additive:
553
+ * present only when a template was configured (absent == the stock `desktop` template, every
554
+ * pre-existing bundle byte-stable). A template name is public-safe (not a secret).
555
+ */
556
+ desktopTemplate?: string;
557
+ /**
558
+ * Browser family requested for hosted desktop actor lanes and the in-sandbox command that opened
559
+ * it, when explicitly configured. Optional + additive; absent means the historical default opener
560
+ * path was used or the backend does not create a headed desktop.
561
+ */
562
+ desktopBrowser?: {
563
+ requested: "default" | "chrome" | "chromium" | "firefox";
564
+ resolved?: string;
565
+ };
566
+ /**
567
+ * Optional lineage for a run that intentionally re-executes selected lanes from a prior
568
+ * multi-lane run. This keeps retry-like workflows explicit: the new run is linked to the old
569
+ * evidence, but it never mutates or silently "fixes" the original verdict.
570
+ */
571
+ rerun?: RunRerunLineage;
572
+ /**
573
+ * The interaction-attribution honesty axis (#164). Absent == `isolated` (every existing bundle
574
+ * byte-stable). Set to `shared-world` by the shared-world backend, paired with `sharedWorld`.
575
+ */
576
+ attributionClass?: RunAttributionClass;
577
+ /**
578
+ * Shared-world evidence block (`humanish.shared-world.v1`). Optional + additive; present only on
579
+ * shared-world runs. Verified fail-closed by validateSharedWorldEvidence.
580
+ */
581
+ sharedWorld?: SharedWorldEvidence;
582
+ /**
583
+ * OPTIONAL, ADAPTER-NAMESPACED product score (the layer-6 extension seam, issue #154 acceptance
584
+ * #8). A thin adapter's `score` hook returns a `RunAdapterScore`; the lane attaches it here
585
+ * WITHOUT core knowing any product noun (the score is namespaced + its breakdown lives in `data`).
586
+ * The default mission-based verdict (`review`) is unchanged when no scorer hook is given.
587
+ */
588
+ adapterScore?: RunAdapterScore;
589
+ /**
590
+ * OPTIONAL, ADAPTER-NAMESPACED product/state proof artifacts. Core validates
591
+ * shape and local relative artifact references, then verifies the referenced
592
+ * files exist. The adapter owns the payload schema under `namespace`.
593
+ */
594
+ adapterArtifacts?: RunAdapterArtifact[];
595
+ /**
596
+ * Provider resources this run owns and may clean up later by exact recorded id.
597
+ * Optional + additive: absent means the producer did not record any run-owned
598
+ * remote resources. Core cleanup never enumerates provider accounts.
599
+ */
600
+ providerResources?: RunProviderResource[];
601
+ }
602
+ export interface RunProviderResource {
603
+ schema: "humanish.provider-resource.v1";
604
+ provider: "e2b-desktop";
605
+ kind: "sandbox";
606
+ id: string;
607
+ owner: "humanish";
608
+ status: "running" | "killed" | "unknown";
609
+ simId?: string;
610
+ streamId?: string;
611
+ laneId?: string;
612
+ createdAt?: string;
613
+ cleanup?: {
614
+ killed: boolean;
615
+ reason: string;
616
+ };
617
+ }
618
+ export interface RunRerunLineage {
619
+ sourceRunId: string;
620
+ selectedLaneIds: string[];
621
+ previous: Array<{
622
+ laneId: string;
623
+ streamId?: string;
624
+ status: string;
625
+ reason?: string;
626
+ actorStatus?: string;
627
+ completionReason?: string;
628
+ }>;
629
+ }
630
+ export interface ReviewSummary {
631
+ schema: typeof REVIEW_SCHEMA;
632
+ verdict: "contract_proof_only" | "pass" | "fail" | "blocked" | "timed_out";
633
+ summary: string;
634
+ gaps: string[];
635
+ }
636
+ export declare function buildRunSource(args: {
637
+ cwd: string;
638
+ capturedAt?: Date | string;
639
+ humanishSource: RunBundle["source"]["humanishSource"];
640
+ packageName: string | null;
641
+ }): Promise<RunBundle["source"]>;
642
+ export interface RunResult {
643
+ schema: "humanish.run-result.v1";
644
+ ok: boolean;
645
+ runId?: string;
646
+ mode?: "dry-run" | "live";
647
+ simCount?: number;
648
+ cwd: string;
649
+ artifactRoot?: string;
650
+ bundlePath?: string;
651
+ reviewPath?: string;
652
+ latestPath?: string;
653
+ warnings: string[];
654
+ error?: {
655
+ code: "HUMANISH_ACTOR_FANOUT_UNIMPLEMENTED" | "HUMANISH_APP_URL_OPTION_CONFLICT" | "HUMANISH_BROWSER_APP_CAPTURE_FAILED" | "HUMANISH_CODEX_APP_SERVER_FAILED" | "HUMANISH_LIVE_RUN_UNIMPLEMENTED" | "HUMANISH_LOCAL_CODEX_EXEC_FAILED" | "HUMANISH_LOCAL_CODEX_TUI_FAILED" | "HUMANISH_INVALID_APP_URL" | "HUMANISH_INVALID_ACTOR_CONCURRENCY" | "HUMANISH_INVALID_CWD" | "HUMANISH_INVALID_SIM_COUNT" | "HUMANISH_INVALID_TIMEOUT" | "HUMANISH_INVALID_PORT" | "HUMANISH_UNSUPPORTED_ACTOR" | "HUMANISH_UNSUPPORTED_RERUN_FLAGS" | "HUMANISH_WATCH_OPTION_CONFLICT";
656
+ message: string;
657
+ };
658
+ }
659
+ export interface VerifyResult {
660
+ schema: typeof VERIFY_SCHEMA;
661
+ ok: boolean;
662
+ cwd: string;
663
+ run: string;
664
+ bundlePath?: string;
665
+ checks: Array<{
666
+ name: string;
667
+ ok: boolean;
668
+ message: string;
669
+ }>;
670
+ shareSafety: {
671
+ status: "share_ready" | "local_only" | "blocked";
672
+ reasons: Array<{
673
+ code: "VERIFY_FAILED" | "PUBLIC_SAFETY_FINDINGS" | "RAW_SCREENSHOTS";
674
+ message: string;
675
+ }>;
676
+ };
677
+ warnings: string[];
678
+ error?: {
679
+ code: "HUMANISH_RUN_NOT_FOUND" | "HUMANISH_INVALID_RUN_BUNDLE";
680
+ message: string;
681
+ };
682
+ }
683
+ export interface CleanupResourceResult {
684
+ provider: RunProviderResource["provider"];
685
+ kind: RunProviderResource["kind"];
686
+ id: string;
687
+ status: "killed" | "already_clean" | "failed" | "skipped";
688
+ message: string;
689
+ }
690
+ export interface CleanupAdapterResult {
691
+ id: string;
692
+ ok: boolean;
693
+ message: string;
694
+ }
695
+ export interface CleanupResult {
696
+ schema: typeof CLEANUP_SCHEMA;
697
+ ok: boolean;
698
+ cwd: string;
699
+ run: string;
700
+ runId?: string;
701
+ bundlePath?: string;
702
+ cleanupPath?: string;
703
+ checkedAt: string;
704
+ summary: {
705
+ resources: number;
706
+ killed: number;
707
+ alreadyClean: number;
708
+ failed: number;
709
+ skipped: number;
710
+ };
711
+ resources: CleanupResourceResult[];
712
+ adapterResults: CleanupAdapterResult[];
713
+ warnings: string[];
714
+ error?: {
715
+ code: "HUMANISH_RUN_NOT_FOUND" | "HUMANISH_INVALID_RUN_BUNDLE";
716
+ message: string;
717
+ };
718
+ }
719
+ export interface RunCleanupHooks {
720
+ loadDesktopModule?: () => Promise<E2BDesktopModule>;
721
+ cleanupAdapterResources?: (ctx: {
722
+ cwd: string;
723
+ runDir: string;
724
+ bundle: RunBundle;
725
+ }) => Promise<CleanupAdapterResult[]>;
726
+ now?: () => Date;
727
+ }
728
+ export interface RunsResult {
729
+ schema: typeof RUNS_SCHEMA;
730
+ ok: boolean;
731
+ cwd: string;
732
+ runs: Array<{
733
+ runId: string;
734
+ createdAt: string | null;
735
+ mode: string | null;
736
+ path: string;
737
+ }>;
738
+ latest: string | null;
739
+ error?: {
740
+ code: "HUMANISH_RUNS_UNAVAILABLE";
741
+ message: string;
742
+ };
743
+ }
744
+ export interface DoctorResult {
745
+ schema: typeof DOCTOR_SCHEMA;
746
+ ok: boolean;
747
+ cwd: string;
748
+ checks: Array<{
749
+ name: string;
750
+ ok: boolean;
751
+ message: string;
752
+ }>;
753
+ }
754
+ export declare function runDryRun(options: RunOptions): Promise<RunResult>;
755
+ type LocalActorTerminalStatus = Extract<RunSimulationStatus, "passed" | "failed" | "blocked" | "timed_out">;
756
+ /**
757
+ * Strip ANSI/control noise from a captured terminal transcript into stable, scannable text.
758
+ * Pure (no IO). Exported so the terminal-product lane (src/e2b-terminal-lab.ts) normalizes its
759
+ * captured exec stream EXACTLY as the local-actor lanes do — the verdict-nonce scorer is only
760
+ * sound against the same normalization the marker is matched on, so the logic must not diverge.
761
+ */
762
+ export declare function normalizeLocalActorTranscript(transcript: string): string;
763
+ /**
764
+ * Extract the per-run verdict from a normalized transcript: the agent must print exactly
765
+ * `HUMANISH_ACTOR_VERDICT=<status> HUMANISH_ACTOR_NONCE=<nonce>`, and the nonce is mandatory so a
766
+ * bare marker (echoed or replayed from untrusted text) can never forge a verdict. Pure (no IO).
767
+ * Exported so the terminal-product lane scores its in-sandbox `codex exec` run by the SAME marker
768
+ * — divergent verdict logic would let the two lanes disagree about what "passed" means.
769
+ */
770
+ export declare function extractLocalActorVerdict(transcript: string, verdictNonce: string): LocalActorTerminalStatus | null;
771
+ export declare function verifyRun(cwdInput: string, runInput: string): Promise<VerifyResult>;
772
+ export declare function cleanupRun(cwdInput: string, runInput: string, hooks?: RunCleanupHooks): Promise<CleanupResult>;
773
+ export declare function loadRunBundle(cwdInput: string, runInput: string): Promise<{
774
+ bundle: RunBundle;
775
+ bundlePath: string;
776
+ runDir: string;
777
+ } | null>;
778
+ export declare function listRuns(cwdInput: string): Promise<RunsResult>;
779
+ export declare function readReview(cwdInput: string, runInput: string): Promise<VerifyResult | (ReviewSummary & {
780
+ path: string;
781
+ runId: string;
782
+ })>;
783
+ export declare function doctor(cwdInput: string): Promise<DoctorResult>;
784
+ export {};