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,148 @@
1
+ # Terminal-product real-agent lane (issue #154)
2
+
3
+ Date: 2026-06-16
4
+
5
+ Status: SLICE 1 shipped — the config + routing skeleton, DRY-RUN only. The live
6
+ in-sandbox backend, the command-scoped credential boundary, cleanup,
7
+ interventions, the cost/no-spend ledger, and the product-adapter extension seam
8
+ are later slices. See the ratified goal packet
9
+ ([`docs/goals/terminal-product-lane/goal.md`](../goals/terminal-product-lane/goal.md))
10
+ for the full slice plan and the safety contract.
11
+
12
+ ## What this is
13
+
14
+ A lab lane for **terminal-product real-agent studies**: a real autonomous coding
15
+ agent (Codex) discovering and using a CLI/product from its **public surfaces
16
+ only**, running **inside an E2B shell** with command-scoped runtime auth, capped
17
+ at no-spend, emitting durable terminal/substrate/cost/no-spend/cleanup/
18
+ intervention proof that verifies fail-closed. This is distinct from the browser
19
+ lanes: it is not testing whether a browser can click a local web app — it tests
20
+ whether an autonomous agent can discover and use a CLI/product surface from
21
+ public materials.
22
+
23
+ It rides the established lane-addition pattern (proven by the scripted-browser
24
+ and local-app lanes): a new `subject.source` × `execution.target`, a routing
25
+ predicate, a backend enum + dispatch, a registered actor with a capability lane,
26
+ fail-closed cross-validation, and forward-declared warnings.
27
+
28
+ ## The composition
29
+
30
+ | Axis | Value |
31
+ | --- | --- |
32
+ | `subject.source` | `terminal-product` |
33
+ | `subject.product` | `{ name, publicSurfaces[] }` — the only world the agent sees |
34
+ | `execution.target` | `e2b-terminal` (or absent → implied) |
35
+ | `execution.terminal` | `{ transport: exec-stream, stdin: disabled }` |
36
+ | `execution.runtimeAuth` | `openai-env` (names-only evidence this slice) |
37
+ | `scenario.caps` | `{ maxUsd, maxJobs, maxMinutes }` — the blast-radius budget |
38
+ | `policies` | `allowPrivateRepoAccess` / `allowProviderCredentials` / `allowPaymentCredentials` / `allowGitHubMutation`, all DEFAULT FALSE |
39
+ | `actors[0].type` | `codex-exec` — a registered terminal actor (`keyPlacement: in-sandbox-command-scoped`) |
40
+ | `LabBackend` | `terminal` → `runTerminalProductLab` ([`src/e2b-terminal-lab.ts`](../../src/e2b-terminal-lab.ts)) |
41
+
42
+ Routing is `routesToTerminalProduct(config)` — the single source of truth that
43
+ both `selectLabBackend` and the forward-declared-warning logic consume, mirroring
44
+ `routesToComputerUse` / `routesToScriptedBrowser`.
45
+
46
+ ## The safety contract (the lane's reason to exist)
47
+
48
+ This lane **inverts** the credential-placement default of every other E2B route.
49
+ On the computer-use route the model's key stays *outside* the sandbox; here the
50
+ agent-under-test runs *inside* with a real `OPENAI_API_KEY`/`CODEX_API_KEY` and
51
+ is **presumed exfiltratable**. The doctrine (invariants-and-defaults.md, the
52
+ placement rule): *keys live where the keyed process runs — and nowhere else;
53
+ blast radius is bounded by key scoping and budgets, not by hoping.*
54
+
55
+ The inversion is declared as registry metadata, not a code convention: the
56
+ terminal actor's capabilities carry `keyPlacement: "in-sandbox-command-scoped"`.
57
+ SLICE 1 ships the DECLARED field + value (the contract is honest about where the
58
+ key would go); SLICE 2's engine enforces command-scoped injection (only into the
59
+ per-command `envs` of the `codex` invocation, never `Sandbox.create({envs})`)
60
+ keyed off that capability, plus the deny-by-default credential allowlist, the
61
+ positive-allowlist sandbox metadata, the cleanup proof, the interventions ledger,
62
+ and a minimal fail-closed cap.
63
+
64
+ ## SLICE 1 scope (DRY-RUN only — what is honest now)
65
+
66
+ `runTerminalProductLab` implements ONLY the dry-run path: it builds a valid
67
+ `humanish.run-bundle.v1` contract bundle, honestly labeled contract-only, with:
68
+
69
+ - the subject declared as a terminal-product with its public surfaces, provenance
70
+ **UNPINNED** (the agent drives public surfaces, not a clone — invariant 5);
71
+ - the author mission recorded as plaintext (public-safe committed lab text) + a
72
+ **digest** of the full composed prompt (nothing beyond the author mission goes
73
+ plaintext);
74
+ - the caps / deny-by-default policies / runtime-auth channel recorded as
75
+ declarations (names only — invariant 1);
76
+ - a terminal-kind stream that is an honest **contract placeholder**: stdin
77
+ disabled, empty tail, `transport: snapshot` — **not** `pty` (captured
78
+ non-interactive exec output is never an interactive PTY; invariant 6 + the
79
+ goal packet's PTY ruling). SLICE 2 fills the redacted exec-stream capture;
80
+ - empty/placeholder ledgers (substrate lifecycle, command log, terminal event
81
+ stream, interventions, cost) that SLICE 2/3 fill.
82
+
83
+ The dry-run bundle passes the EXISTING `verifyRun`. Terminal-specific verifier
84
+ checks (terminal/transcript presence, lifecycle, cleanup, interventions,
85
+ metadata allowlist, no-credential-in-artifacts, no-spend) are SLICE 2/3.
86
+
87
+ A non-dry-run (live) call returns a structured `HUMANISH_TERMINAL_AGENT_NOT_IMPLEMENTED`
88
+ failure (fail-closed, clear code) — it never creates a sandbox, never injects a
89
+ key, never spends. SLICE 2 implements the real session.
90
+
91
+ The DI seams SLICE 2 needs (`loadModule`, `buildSandbox`, `runtimeAuthEnv`,
92
+ `detachedTimers`) are declared on `TerminalProductLabHooks` and threaded through
93
+ `RunLabOptions.terminalHooks`, mirroring `cuaHooks` / `scriptedHooks` — but only
94
+ the dry-run path is implemented this slice.
95
+
96
+ ## SLICE 4 — the product-adapter extension seam (layer 6)
97
+
98
+ This lane is proof-roadmap **layer 6**: an adopter attaches product-specific
99
+ scoring + feedback as a THIN in-repo extension WITHOUT forking core. SLICE 4
100
+ ships the SEAM (not a built-in product scorer — the adopter's scorecard lives in
101
+ the adopter's repo):
102
+
103
+ - **Exported contract types** a thin adapter types against from the package
104
+ barrel (`humanish`) alone — never a deep `src/` import: `RunBundle`,
105
+ `RunFeedbackCandidate`, `RunAdapterScore`, `RunMeaningfulUseScore`
106
+ (+ `RunMeaningfulUseComponentId`), `ActorTrace`, and the terminal-lane
107
+ `TerminalProductScoringContext` / `TerminalLedgers` / `TerminalCostLedger` /
108
+ `NoSpendProof` / `CostLine` / record types. Before this slice these were not
109
+ exported — which FORCED a fork (a thin adapter could not type against the
110
+ bundle), the gap issue #154 acceptance #8 names.
111
+ - **A registrable scorer / feedback DI hook** on `TerminalProductLabHooks`:
112
+ `score?(ctx: TerminalProductScoringContext) => RunAdapterScore | Promise<…>`
113
+ and `deriveFeedback?(ctx) => RunFeedbackCandidate[] | Promise<…>`. The lane
114
+ calls the hooks over the FULLY-ASSEMBLED, redacted evidence and attaches the
115
+ results (`bundle.adapterScore`, appended `bundle.feedbackCandidates`) WITHOUT
116
+ core knowing any product noun. Default (no hook) behavior is unchanged: the
117
+ mission-based verdict stands alone.
118
+ - **Adapter-namespaced product nouns.** Product-specific concepts (public
119
+ CLI/product command observed, hosted product success-or-blocker, feedback
120
+ id/draft, media/job/asset ids, no-media/no-provider-spend proof,
121
+ defection/friction risk) ride ONLY under a single namespaced field
122
+ (`RunFeedbackCandidate.adapter: { namespace, data }` and
123
+ `RunAdapterScore.{namespace, data}`) so core's enums stay product-agnostic and
124
+ a future inert-field audit never misfires. No adopter noun is hardcoded into a
125
+ core enum (avoiding closed-taxonomy rot); `e2b-terminal` is added to the
126
+ substrate enum so a terminal-agent candidate names its substrate honestly.
127
+
128
+ The seam is fail-closed: the lane scrubs+redacts the returned payloads and DROPS
129
+ any malformed score/candidate with a warning, and `verifyRun` re-checks the
130
+ surviving shapes — a bad extension never poisons a verifiable bundle. Proven by
131
+ `tests/terminal-product-adapter-seam.test.ts` (a thin in-repo example adapter
132
+ typing against the barrel only, registering a scorer, attaching namespaced nouns,
133
+ emitting a candidate; the bundle verifies). No live rung — the seam is contract,
134
+ not spend.
135
+
136
+ The adopter's real scorecard is its OWN thin extension; the live receipt for the
137
+ end-to-end lane is tracked under #159, and true duplex PTY replay is deferred to
138
+ SLICE 5.
139
+
140
+ ## The reference adopter (codename-neutral)
141
+
142
+ The requesting adopter is a public creative-CLI product (see issue #154 for its
143
+ concrete public surfaces). Committed source and docs here stay codename-neutral
144
+ per the public-surface scan; the committed CI fixture
145
+ ([`humanish/labs/terminal-product-demo.yaml`](../../humanish/labs/terminal-product-demo.yaml))
146
+ uses a FICTIONAL mock CLI (`widgetsmith-cli`) with `example.com` surfaces. The
147
+ adopter's real public surfaces appear only in operator-run docs and the GitHub
148
+ issue, never in scanned committed text.
@@ -0,0 +1,80 @@
1
+ # Adapter Fixture Parity Contract
2
+
3
+ Date: 2026-06-02
4
+
5
+ Status: v0 draft contract for public-safe adapter fixture parity.
6
+
7
+ ## Purpose
8
+
9
+ Adapter fixtures prove that Humanish can carry target-specific evidence without
10
+ moving target truth into core schemas. A fixture is not a product claim. It is a
11
+ public-safe contract packet that shows the routes, personas, milestones,
12
+ terminal evidence, feedback drafts, and policy decisions a real adapter must
13
+ emit before live behavior can be trusted.
14
+
15
+ The fixture contract keeps three boundaries explicit:
16
+
17
+ - Core owns run-bundle identity, artifact layout, verification, review,
18
+ redaction, and feedback mechanics.
19
+ - Adapters own target routes, scenario language, personas, milestone names,
20
+ command surfaces, and acceptance proof.
21
+ - Public issue drafts use redacted artifact pointers only; they do not require
22
+ GitHub tokens, hosted product memory, private transcripts, or live mutation.
23
+
24
+ ## Fixture Set
25
+
26
+ The committed fixture set lives under `adapters/fixtures/`.
27
+
28
+ | Fixture | Proves | Required artifacts |
29
+ | --- | --- | --- |
30
+ | `post-auth-return-dry-run` | A web-app adapter can keep upload, studio, and auth-return milestones adapter-owned while emitting a product-neutral dry-run bundle. | `adapter.json`, `persona.json`, `scenario.json`, `milestones.json`, `run-bundle.json` |
31
+ | `terminal-feedback-lifecycle` | A terminal-first adapter can emit sanitized transcript evidence, issue-draft material, cost/redaction policy, verification checks, and feedback lifecycle proof without browser-only assumptions. | `adapter.json`, `policy.json`, `run-bundle.json`, `feedback-draft.json`, `verify-result.json`, `transcripts/sanitized-terminal.txt` |
32
+
33
+ ## Promotion Gates
34
+
35
+ A fixture can be promoted only when:
36
+
37
+ - every example is synthetic or redacted;
38
+ - artifact paths are relative and do not contain traversal segments, absolute
39
+ local paths, hosted stream URLs, or auth-bearing links;
40
+ - credential policy records env var names only, never values;
41
+ - adapter-owned nouns do not appear in core schema docs or core runtime code;
42
+ - public feedback material states that GitHub mutation was not performed;
43
+ - the fixture can be checked with `pnpm test tests/adapter-fixtures.test.ts`
44
+ and `pnpm public-surface:scan`.
45
+
46
+ ## Dry-Run Web-App Fixture Shape
47
+
48
+ The web-app fixture models a local app with three adapter-owned route groups:
49
+
50
+ - `upload`: synthetic file input and validation state;
51
+ - `studio`: synthetic work surface and result-review state;
52
+ - `auth-return`: a post-authentication return path using a synthetic state id.
53
+
54
+ The dry-run bundle does not add route or milestone fields to core. Instead, it
55
+ references adapter-owned routes through `streams[].ui.route`, milestone events
56
+ through lifecycle/event records, and the milestone manifest through relative
57
+ artifact pointers.
58
+
59
+ ## Terminal Feedback Fixture Shape
60
+
61
+ The terminal fixture models a command-driven product surface. Its bundle uses a
62
+ `terminal` evidence stream, a sanitized transcript pointer, a feedback
63
+ candidate, a separate feedback draft artifact, and a verification result that
64
+ checks required public-safe files without reading or requiring raw private
65
+ transcripts. Policy is adapter-owned and records:
66
+
67
+ - `spend_policy: no_spend`;
68
+ - `network_policy: no_network`;
69
+ - `github.mutation: not_requested`;
70
+ - `hosted_product_memory.required: false`;
71
+ - redaction status and denied material classes.
72
+
73
+ This keeps terminal and feedback parity independent from browser screenshots.
74
+
75
+ ## Proof Commands
76
+
77
+ ```bash
78
+ pnpm test tests/adapter-fixtures.test.ts
79
+ pnpm public-surface:scan
80
+ ```
@@ -0,0 +1,71 @@
1
+ # Core Contract
2
+
3
+ Date: 2026-06-02
4
+
5
+ Status: v0 draft contract with tested primitive helpers in `src/core`.
6
+
7
+ ## Purpose
8
+
9
+ Core is the reusable layer that makes a run bundle stable enough for agents,
10
+ reviewers, and maintainers to trust. It owns generic run identity, artifact
11
+ layout, source state summaries, lifecycle records, latest/history pointers, and
12
+ timing summaries.
13
+
14
+ Core does not own product routes, personas, scenarios, app topology, provider
15
+ setup, or repository-specific proof language.
16
+
17
+ ## Public-Safe Defaults
18
+
19
+ Core records must be safe to include in public run bundles by default:
20
+
21
+ - artifact paths are relative;
22
+ - run ids contain only lowercase letters, numbers, and dashes;
23
+ - git state summarizes status without branch names, remotes, file names, file
24
+ paths, or absolute working directories;
25
+ - lifecycle and timing records are explicit inputs, not inferred prose;
26
+ - latest/history pointers identify local artifacts, not hosted private logs.
27
+
28
+ ## Primitive Set
29
+
30
+ | Primitive | Contract |
31
+ | --- | --- |
32
+ | Run id | Deterministic from explicit prefix, timestamp, and entropy; valid ids match `^[a-z0-9][a-z0-9-]{0,127}$`. |
33
+ | Artifact layout | Builds stable relative pointers under `.humanish/runs/<run-id>/` plus `.humanish/runs/latest.json`. |
34
+ | Latest pointer | `{ schema, runId, path, updatedAt }` using `humanish.latest-run.v1`. |
35
+ | History entry | `{ schema, runId, createdAt, mode, path }` using `humanish.run-history-entry.v1`. |
36
+ | Lifecycle event | `{ at, event, message }`; event and message are required. |
37
+ | Timing summary | `{ startedAt, endedAt, durationMs, status }`; running records have null end and duration. |
38
+ | Git state | `{ schema, status, capturedAt, head, changes, note }` using `humanish.git-state.v1`. |
39
+
40
+ ## Git State Boundary
41
+
42
+ Git state is intentionally lossy. It answers:
43
+
44
+ - is this a work tree?
45
+ - is it clean or dirty?
46
+ - what short HEAD hash is available?
47
+ - is HEAD attached, detached, unborn, or unknown?
48
+ - how many staged, unstaged, and untracked entries exist?
49
+
50
+ It does not record:
51
+
52
+ - branch names;
53
+ - remotes;
54
+ - file names;
55
+ - file paths;
56
+ - absolute directories;
57
+ - diffs;
58
+ - commit messages.
59
+
60
+ That makes it useful for repeatability and review without turning run bundles
61
+ into a source leak.
62
+
63
+ ## Stop Conditions
64
+
65
+ Core work stops if:
66
+
67
+ - a core primitive needs a product-specific noun to make sense;
68
+ - an artifact path can escape the run root;
69
+ - a public record includes a raw cwd, branch name, remote, file name, diff, or
70
+ credential-like value;
71
+ - a run id cannot be reproduced from explicit inputs.
@@ -0,0 +1,145 @@
1
+ # Feedback Contract
2
+
3
+ Date: 2026-06-01
4
+
5
+ Status: v0 local issue draft generation with run-candidate support.
6
+
7
+ ## Purpose
8
+
9
+ Feedback is the bridge between simulation evidence and public issue filing.
10
+
11
+ `humanish feedback` should let a persona simulation say:
12
+
13
+ ```text
14
+ this user-like run found this concrete friction
15
+ here is the evidence
16
+ here is the likely owner
17
+ here is the redaction proof
18
+ here is the next state
19
+ ```
20
+
21
+ It should not be an issue spammer, infra dependency, or generic comment
22
+ collector.
23
+
24
+ ## Privacy Rule
25
+
26
+ Feedback payloads must be public-safe by default. They may not contain PII,
27
+ PHI, secrets, keys, tokens, raw private transcripts, private screenshots, raw
28
+ customer data, raw patient data, or private product source.
29
+
30
+ Public issue drafting fails closed if redaction cannot prove the payload is
31
+ safe. A verified run bundle is not automatically public-promotable: feedback
32
+ commands also require `humanish verify` to report
33
+ `shareSafety.status: share_ready`.
34
+
35
+ ## Command Stages
36
+
37
+ ```bash
38
+ humanish feedback list --run latest
39
+ humanish feedback draft --run latest --json
40
+ humanish feedback verify --run latest --json
41
+ humanish feedback issue --run latest --repo owner/repo --format markdown
42
+ humanish feedback issue-url --run latest --repo owner/repo
43
+ ```
44
+
45
+ ### `list`
46
+
47
+ Reads feedback candidates from the run bundle. Does not mutate. Candidates are
48
+ generated by lab/adapters when actor evidence identifies a concrete
49
+ setup-quality gap, ceremonial/absent study quality, target-app blocker, or
50
+ Humanish CLI blocker. The OSS
51
+ meta-lab is one maintainer dogfood example, not the only candidate source.
52
+
53
+ ### `draft`
54
+
55
+ Builds structured feedback from the strongest run candidate first. If no
56
+ candidate is present, falls back to the dry-run contract follow-up. Writes a
57
+ draft under the run bundle, not GitHub.
58
+
59
+ ### `verify`
60
+
61
+ Checks schema, evidence pointers, idempotency key, redaction result, and public
62
+ issue eligibility.
63
+
64
+ ### `issue`
65
+
66
+ Prints or writes a public-safe GitHub issue body. It does not call the GitHub
67
+ API. The user files the issue in the public or eventually public repository.
68
+
69
+ ### `issue-url`
70
+
71
+ Prints a prefilled GitHub issue URL when the platform supports one. It still
72
+ does not create the issue.
73
+
74
+ ## Schema
75
+
76
+ ```yaml
77
+ humanish_feedback:
78
+ schema: humanish.feedback.v1
79
+ run_id: "<run-id>"
80
+ adapter_id: "<adapter-id>"
81
+ scenario_id: "<scenario-id>"
82
+ persona_id: "<persona-id-or-class>"
83
+ actor: "<actor-runtime>"
84
+ substrate: "<substrate>"
85
+ failure_owner: "harness|target-app|actor|environment|unknown"
86
+ summary: "<public-safe concrete summary>"
87
+ expected: "<public-safe expected behavior>"
88
+ actual: "<public-safe observed behavior>"
89
+ source_bundle: "<path-or-url>"
90
+ evidence:
91
+ - path: "<relative artifact pointer>"
92
+ kind: "screenshot|state|review|trace|log|filesystem"
93
+ note: "<public-safe note>"
94
+ redaction:
95
+ status: "passed|failed|not_applicable"
96
+ notes: "<public-safe note>"
97
+ idempotency_key: "<stable-key>"
98
+ proposed_next_state: "watch|adapter-hardening|target-app-setup|actor-auth|setup-quality-review|study-quality-review"
99
+ acceptance_proof:
100
+ - "<command or artifact that would close this>"
101
+ adapter:
102
+ namespace: "<adapter namespace>"
103
+ data: {}
104
+ ```
105
+
106
+ `adapter` is optional and namespaced. Adapters may place product-specific
107
+ concepts there (for example route groups, milestone ids, product acceptance
108
+ details, or adopter-owned rubric data). Core validates only that `namespace` is
109
+ non-empty and `data` is a record; keys inside `data` are never core enums.
110
+
111
+ ## Failure Owners
112
+
113
+ | Owner | Meaning |
114
+ | --- | --- |
115
+ | `harness` | Humanish or adapter logic produced invalid evidence or execution. |
116
+ | `target-app` | The target app setup, dev server, or local surface blocked the run. |
117
+ | `actor` | The coding-agent/persona actor failed to complete a requested setup or usage path. |
118
+ | `environment` | E2B, local browser, shell, filesystem, network, or dependency substrate failed. |
119
+ | `unknown` | Evidence is useful but ownership is not yet clear. |
120
+
121
+ ## Issue Draft Gates
122
+
123
+ Generating a public issue draft is blocked when:
124
+
125
+ - required schema fields are missing;
126
+ - source bundle is missing;
127
+ - evidence pointers are missing or invalid;
128
+ - redaction did not pass;
129
+ - `shareSafety.status` is `local_only` or `blocked`;
130
+ - any payload may contain PII, PHI, secrets, or private operational context;
131
+ - proposed next state is `agent_ready` without a readiness block;
132
+ - the feedback is a dry-run-only product claim;
133
+ - idempotency key is missing.
134
+
135
+ ## GitHub Issue Semantics
136
+
137
+ GitHub issues filed from feedback should say `contributes to` unless the
138
+ acceptance proof closes the full product claim. The public issue should include
139
+ only redacted evidence pointers and reproduction instructions that a maintainer
140
+ can use without private local context.
141
+
142
+ The public CLI should not require GitHub tokens, hosted product memory, queues,
143
+ webhooks, Actions, databases, or Projects. Maintainers may later build separate
144
+ repo-local tooling that consumes the same issue schema, but that is outside the
145
+ default public feedback path.