@junghanacs/entwurf 0.12.10 → 0.13.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 (86) hide show
  1. package/AGENTS.md +6 -3
  2. package/BASELINE.md +56 -163
  3. package/CHANGELOG.md +35 -0
  4. package/CONTRIBUTING.md +4 -2
  5. package/DELIVERY.md +117 -261
  6. package/README.md +74 -399
  7. package/VERIFY.md +59 -85
  8. package/demo/README.md +1 -1
  9. package/docs/acp-backend-rail.md +231 -0
  10. package/docs/external-mcp-host.md +132 -0
  11. package/docs/fresh-cut-policy.md +99 -0
  12. package/docs/setup-clean-host.md +123 -328
  13. package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +21 -48
  14. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/acp-client.js +12 -0
  15. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/backend-adapter.js +155 -11
  16. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/config.js +16 -4
  17. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/engraving.js +42 -1
  18. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/models.js +66 -7
  19. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/overlay.js +190 -5
  20. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/tool-surface.js +12 -4
  21. package/mcp/entwurf-bridge/src/index.ts +21 -48
  22. package/package.json +14 -9
  23. package/pi/settings.reference.json +1 -1
  24. package/pi-extensions/acp-provider.ts +20 -10
  25. package/pi-extensions/entwurf-control.ts +20 -49
  26. package/pi-extensions/lib/acp/acp-client.ts +22 -0
  27. package/pi-extensions/lib/acp/augment.ts +99 -2
  28. package/pi-extensions/lib/acp/backend-adapter.ts +190 -14
  29. package/pi-extensions/lib/acp/backend.ts +310 -37
  30. package/pi-extensions/lib/acp/config.ts +19 -5
  31. package/pi-extensions/lib/acp/engraving.ts +46 -2
  32. package/pi-extensions/lib/acp/event-mapper.ts +26 -16
  33. package/pi-extensions/lib/acp/models.ts +69 -7
  34. package/pi-extensions/lib/acp/overlay.ts +234 -5
  35. package/pi-extensions/lib/acp/tool-surface.ts +12 -4
  36. package/prompts/engraving.md +13 -5
  37. package/run.sh +386 -119
  38. package/scripts/check-acp-carrier-augment.ts +246 -10
  39. package/scripts/check-acp-cortex.ts +668 -0
  40. package/scripts/check-acp-prompt-lifecycle.ts +565 -0
  41. package/scripts/check-acp-provider-surface.ts +50 -6
  42. package/scripts/check-acp-sdk-surface.ts +60 -21
  43. package/scripts/check-acp-session-reuse.ts +64 -1
  44. package/scripts/check-acp-stop-reason.ts +342 -0
  45. package/scripts/check-entwurf-v2-surface.ts +41 -0
  46. package/scripts/check-gate-qualification.ts +7 -2
  47. package/scripts/check-probe-cli-shim.ts +879 -0
  48. package/scripts/check-probe-ordering.ts +2482 -0
  49. package/scripts/check-release-gate-outcomes.ts +332 -0
  50. package/scripts/check-shell-quote.ts +4 -4
  51. package/scripts/fixtures/probe-cli-shim +20 -0
  52. package/scripts/fixtures/probe-mcp-server.ts +168 -12
  53. package/scripts/lib/live-skip.ts +33 -0
  54. package/scripts/lib/probe-acp-turn.ts +228 -0
  55. package/scripts/lib/probe-cli-shim.ts +464 -0
  56. package/scripts/lib/probe-cli-target.ts +165 -0
  57. package/scripts/lib/probe-event-log.ts +383 -0
  58. package/scripts/lib/probe-verdict.ts +1213 -0
  59. package/scripts/lib/step-outcome.sh +88 -0
  60. package/scripts/mutants/acp-augment.json +106 -0
  61. package/scripts/mutants/acp-cortex.json +196 -0
  62. package/scripts/mutants/acp-prompt-lifecycle.json +100 -0
  63. package/scripts/mutants/acp-stop-reason.json +80 -0
  64. package/scripts/mutants/probe-ordering.json +1054 -0
  65. package/scripts/mutants/release-gate.json +105 -0
  66. package/scripts/mutants/v2-surface.json +26 -15
  67. package/scripts/smoke-acp-bundled-mcp-live.ts +4 -3
  68. package/scripts/smoke-acp-carrier-augment-live.ts +2 -2
  69. package/scripts/smoke-acp-cortex-live.ts +386 -0
  70. package/scripts/smoke-acp-long-turn-live.ts +185 -0
  71. package/scripts/smoke-acp-mcp-live.ts +2 -2
  72. package/scripts/smoke-acp-memory-containment-live.ts +2 -2
  73. package/scripts/smoke-acp-ordering-probe-live.ts +848 -0
  74. package/scripts/smoke-acp-overlay-live.ts +2 -2
  75. package/scripts/smoke-acp-provider-live.ts +2 -2
  76. package/scripts/smoke-acp-raw-turn-live.ts +3 -3
  77. package/scripts/smoke-acp-session-reuse-live.ts +2 -2
  78. package/scripts/smoke-acp-skill-live.ts +2 -2
  79. package/scripts/smoke-acp-socket-citizen-live.ts +4 -3
  80. package/scripts/smoke-acp-v2-send-live.ts +4 -3
  81. package/scripts/smoke-agy-native-push-live.ts +4 -3
  82. package/scripts/smoke-claude-native-resume-live.sh +13 -3
  83. package/scripts/smoke-entwurf-chain-live.ts +352 -0
  84. package/scripts/smoke-entwurf-v2-matrix-live.ts +2 -2
  85. package/scripts/smoke-entwurf-v2-spawn-resume-live.ts +2 -4
  86. package/scripts/smoke-meta-install-state.sh +4 -0
package/AGENTS.md CHANGED
@@ -64,7 +64,9 @@ Detailed incident histories belong in CHANGELOG/issues/BASELINE and source-adjac
64
64
  - The common turn sequence stays backend-invariant: spawn → initialize → newSession → enforceModel → prompt → event map.
65
65
  - Rich operator/project context rides the **first user message augment**, not a large system prompt. The actual callable schema is the tool truth; prose never grants a tool.
66
66
  - A backend may have no carrier or use launch-time model pinning; those asymmetries stay inside its adapter.
67
- - Claude is the reference adapter. Cortex enters only after the current rail conditions in `docs/acp-backend-rail.md` and `NEXT.md` are satisfied.
67
+ - A streaming assistant message starts `pending`. ACP terminal reasons are mapped explicitly; refusal, exhausted turn budget, unknown, or absent reasons end as errors, and the raw reason is preserved. Never restore a default-to-success branch.
68
+ - Bootstrap steps carry wall-clock bounds; a running prompt does not. A turn ends only when the agent answers, the operator aborts (ACP `session/cancel` first, bounded cleanup after), or the child dies. Elapsed time is not evidence, and a prompt-phase failure we author must never read as transient to pi's retry classifier — a cutoff plus blind retry replays the whole prompt from cold.
69
+ - Claude is the reference adapter. Cortex is the second landed adapter (0.13.0): session-scoped dual-HOME containment, overlay-private `mcp.json` projection (its ACP server ignores the wire `mcpServers` param), `CORTEX_HOME` presence refusal, per-turn set-model. Current contract: `docs/acp-backend-rail.md` “Cortex Code audit (D1–D10)”.
68
70
  - entwurf never supplies, copies, proxies, decrypts, or bypasses vendor credentials/subscriptions. It uses the operator's existing local authenticated backend.
69
71
 
70
72
  ## Citizen Identity and Dispatch
@@ -110,10 +112,11 @@ pnpm check
110
112
  ./run.sh check-install-surface
111
113
  ./run.sh check-install-container # require Docker in release acceptance
112
114
 
113
- LIVE=1 ./run.sh release-gate /path/to/scratch
115
+ LIVE=1 ./run.sh release-gate /path/to/scratch --cut
114
116
  LIVE=1 ./run.sh smoke-acp-socket-citizen-live
115
117
  LIVE=1 ./run.sh smoke-acp-bundled-mcp-live
116
118
  LIVE=1 ./run.sh smoke-acp-v2-send-live
119
+ LIVE=1 ENTWURF_ACP_CORTEX_CONNECTION=<conn> ./run.sh smoke-acp-cortex-live # on-demand; outside the claude release floor
117
120
  LIVE=1 AGY_CONVERSATION_ID=<id> ./run.sh smoke-agy-native-push-live
118
121
  ```
119
122
 
@@ -145,7 +148,7 @@ LIVE=1 AGY_CONVERSATION_ID=<id> ./run.sh smoke-agy-native-push-live
145
148
  - Every `.ts` file belongs to one typecheck fence: root emit-capable config, MCP strip-types config, or scripts strip-types config. Do not hide files with `exclude`.
146
149
  - Root pi extensions import TypeBox through `@earendil-works/pi-ai`; do not mix direct `@sinclair/typebox` types.
147
150
  - MCP/scripts use explicit `.ts` imports where Node strip-types requires them. Installed operator surfaces route to compiled JS.
148
- - pi runtime range is `>=0.82.1 <0.83` with devDep exact `0.82.1`; re-evaluate loader aliases and `/compat` at the minor ceiling.
151
+ - pi runtime range is `>=0.83.0 <0.84` with devDep exact `0.83.0`; re-evaluate loader aliases and `/compat` at the minor ceiling. Re-measured at the 0.82.1→0.83.0 move: `packages/coding-agent/src/core/extensions/loader.ts` and `packages/ai/src/compat.ts` are byte-identical across the two tags, so the ceiling moved on measurement, not assumption.
149
152
  - ACP pins are recorded in `package.json` and checked by `check-dep-versions`/`check-acp-sdk-surface`; do not describe a dependency bump as a behavioral fix without evidence.
150
153
 
151
154
  ## Working Style
package/BASELINE.md CHANGED
@@ -6,28 +6,43 @@ silently drifted into a different identity / context surface. Questions
6
6
  are deliberately open-ended — they probe what the agent actually sees,
7
7
  not what it was told to claim.
8
8
 
9
- The 0.12 shipped ACP backend is **Claude**; the main question bank below is the
10
- Claude ACP baseline. Antigravity (`agy`) is also shipped, but as a native-push
11
- garden citizen rather than an ACP backend, so it has a separate citizen/round-trip
12
- baseline below instead of being forced into Claude's overlay questions. Codex
13
- (pi-native / delivery probe) and Gemini (historical non-goal ACP probe) remain
14
- reference axes, not the shipped ACP baseline.
9
+ Claude is the reference ACP backend. Cortex Code has a separate compact baseline
10
+ because it has no system-prompt carrier and keeps its own native tool surface.
11
+ Antigravity (`agy`) is a native-push citizen rather than an ACP backend and therefore
12
+ has a separate citizen/round-trip baseline. Historical Codex/Gemini probes are not
13
+ part of this operator interview.
15
14
 
16
- ## Release-host baseline — #51 repair cut
15
+ ## Release-host baseline
17
16
 
18
17
  This table is the operator-facing support/certification view. It complements the
19
18
  model interview below; a persuasive answer from the model cannot turn an unmeasured
20
- host into a certified one.
21
-
22
- | Surface | Automated artifact evidence | Direct/native evidence | Current verdict |
23
- |---|---|---|---|
24
- | Node 24 Linux package consumer | Required `artifact-consumer` CI: read-only candidate `.tgz`, checkout-invisible, non-root global install, PATH shims, frozen package root, path+sha256 regular-file fence, strict doctor fixture | None required for the package layout itself | Package-consumer shape verified. The planted Claude cache/owner/bridge are synthetic and prove no real Claude lifecycle. |
25
- | Claude Code 2.1.217 exec form | `check-hook-launch-topology` + `check-claude-floor-coherence`; doctor oracle healthy fixture + 21 defect mutations | B2 actual Claude session on NixOS: args per element, literal `${HOME}`, direct parent, FileChanged exit 2 → idle wake | Runtime behavior verified at 2.1.217 on one host; this is the supported floor. |
26
- | Claude Code 2.1.138 negative | Launcher empty-argv refusal + installer/doctor floor checks | B actual Claude session on NixOS: args discarded while runtime reported success | Unsupported; no shell-form fallback. |
27
- | Maintainer NixOS installed package | Gates and B/B2 are green; the published `0.12.8-repair.1` artifact was installed from the registry for acceptance, then the V3 development wiring was restored | 2026-07-25: registry install → installed `install-meta-bridge` → NEW Claude session with a live MCP child → installed doctor **exit 0** (HISTORY) | Host-certified for the published repair artifact, including physical `entwurf_v2` delivery and the live owner join. The doctor first went RED on a managed dev-bin shadowing the registry bridge. This host now runs dev wiring again; stable `0.12.8` earns its own host proof. |
28
- | Secondary Ubuntu Linux installed package | Linux artifact-consumer gate models the package shape, not this machine | 2026-07-25: same registry artifact, isolated clean `PI_CODING_AGENT_DIR`, NEW Claude session with a live MCP child → installed doctor **exit 0** (HISTORY) | Recovery closed for `0.12.8-repair.1`. Hand-patched hooks and validate output remain non-acceptance; a stable artifact is a separate proof. |
29
- | macOS Claude meta-bridge | No artifact-consumer job and no `/proc` live join | None | **Not yet verified/certified for this repair cut.** Installer refuses Darwin and doctor remains nonzero; uninstall permits Darwin to remove older managed state. This is not permanent—future native validation may reopen it, and package-level `os` stays unrestricted. |
30
- | WSL2 / Windows | None | None | Unverified / outside this repair cut. |
19
+ host into a certified one. Verdicts are one of **certified** (a real host ran the
20
+ installed doctor green), **shape-only** (gates model the package, no live host),
21
+ or **unverified**.
22
+
23
+ | Surface | Verdict | Evidence |
24
+ |---|---|---|
25
+ | Node 24 Linux package consumer | shape-only | Required `artifact-consumer` CI |
26
+ | Claude Code >=2.1.217 exec form | **certified** supported floor | Topology + floor gates, doctor oracle; B2 live NixOS session |
27
+ | Claude Code 2.1.138 | **unsupported** | Launcher refuses empty argv; no shell-form fallback |
28
+ | Maintainer NixOS installed package | **certified** for `0.12.8-repair.1` | 2026-07-25 registry install doctor exit 0 (HISTORY) |
29
+ | Secondary Ubuntu installed package | **certified** for `0.12.8-repair.1` | 2026-07-25 same artifact, isolated agent dir → doctor exit 0 (HISTORY) |
30
+ | macOS Claude meta-bridge | unverified | Installer refuses Darwin; no `/proc` live join |
31
+ | WSL2 / Windows | unverified | None |
32
+
33
+ Notes the table cannot carry without becoming prose again:
34
+
35
+ - **shape-only is not a live proof.** The `artifact-consumer` job verifies a read-only
36
+ candidate `.tgz`, checkout-invisible non-root global install, PATH shims, a frozen
37
+ package root, the path+sha256 regular-file fence, and a strict doctor fixture. Its
38
+ planted Claude cache/owner/bridge are synthetic — no real Claude lifecycle runs there.
39
+ - **Both certified hosts are certified for the published repair artifact only**, including
40
+ physical `entwurf_v2` delivery and the live owner join. Stable cuts earn their own host
41
+ proof; hand-patched hooks and `plugin validate` output are never acceptance.
42
+ - **The maintainer host first went doctor-RED** on a managed dev-bin shadowing the registry
43
+ bridge, and now runs dev wiring again.
44
+ - **macOS is not permanently excluded.** Future native validation may reopen it, and the
45
+ package-level `os` field stays unrestricted.
31
46
 
32
47
  **Operator acceptance rule:** on a claimed Claude host, reinstall from the released
33
48
  artifact, restart every old Claude process, open a new session, and run the doctor
@@ -72,20 +87,16 @@ expected isolation-closed response, **FAIL** = listed failure mode,
72
87
  > `check-acp-carrier-augment`) and the live `smoke-acp-memory-containment-live`;
73
88
  > this document records the model-side observation.
74
89
 
75
- ## Per-ACP-backend specifics
90
+ ## Claude-specific surface
76
91
 
77
- Pick the active **ACP backend's** column before pasting a question block. Claude
78
- is the 0.12 shipped ACP baseline; Codex/Gemini are historical probe reference.
79
- Do not replace the Gemini column with agy: agy does not use this overlay/carrier
80
- contract at all, and its shipped baseline is the native-citizen section below.
92
+ The two-round question bank below is the Claude reference baseline.
81
93
 
82
- | Slot | Claude *(shipped)* | Codex *(probe)* | Gemini *(probe)* |
83
- |---|---|---|---|
84
- | Config-dir env (Q-L2) | `CLAUDE_CONFIG_DIR` | `CODEX_HOME` / `CODEX_SQLITE_HOME` | `GEMINI_CLI_HOME` |
85
- | Native dir to compare | `~/.claude/` | `~/.codex/` | `~/.gemini/` |
86
- | Read-class native tools (Q-L3) | `Read`, `Bash` (ls/find/grep) | `exec_command` | `read_file`, `list_directory`, `glob`, `grep_search` |
87
- | Project memory file (Q-L4) | `CLAUDE.md` / `.claude/` | `~/.codex/AGENTS.md` | `GEMINI.md` |
88
- | Memory write target (Q-L5W) | `CLAUDE.md`, hooks, agents | `~/.codex/memories`, AGENTS.md | `GEMINI.md`, `MEMORY.md`, autoMemory inbox |
94
+ | Slot | Expected Claude surface |
95
+ |---|---|
96
+ | Config dir (Q-L2) | `CLAUDE_CONFIG_DIR`, pointing at the entwurf overlay rather than `~/.claude/` |
97
+ | Read-class tools (Q-L3) | `Read`, `Bash` (ls/find/grep) |
98
+ | Project memory (Q-L4) | `CLAUDE.md` / `.claude/`, not inherited through the overlay |
99
+ | Native memory write (Q-L5W) | none; do not create `CLAUDE.md`, hooks, or agents as a memory substitute |
89
100
 
90
101
  ---
91
102
 
@@ -246,144 +257,26 @@ same-process concurrency.
246
257
 
247
258
  ---
248
259
 
249
- ## Probe appendix — Gemini engraving substitution (`Q-H`, not 0.12 baseline)
250
-
251
- Historical Gemini probe, retained for the probe lane only — **not** part of
252
- the shipped Claude baseline. Gemini's `applySubstitutions` rewrites unknown
253
- `${name}` tokens; the bridge inserts a U+200B between `$` and `{` in operator
254
- engraving body so the regex misses while the visual text stays stable. The
255
- former carrier-isolation canary literal is a doc-era artifact with **no code
256
- surface on 0.12** — do not assert it as a current expectation.
260
+ ## Cortex baseline
257
261
 
258
- Setup (operator side): author a test engraving with literal `${AvailableTools}` /
259
- `${SubAgents}` / `${arbitrary_unknown_key}` tokens, plumb it through the Gemini
260
- overlay, open a fresh Gemini ACP session, then ask `Q-H`:
262
+ Run these checks in a fresh `entwurf/cortex-*` session. Do not grade Cortex against
263
+ Claude's overlay or system-prompt carrier.
261
264
 
262
- ~~~
263
- [Q-H] Verify whether these three lines are visually present in your system
264
- prompt, and if so quote the visible text exactly:
265
- - TOKEN_A = ${AvailableTools}
266
- - TOKEN_B = ${SubAgents}
267
- - TOKEN_C = ${arbitrary_unknown_key}
268
- ~~~
265
+ | ID | Check | PASS | FAIL |
266
+ |---|---|---|---|
267
+ | Q-CX-ID | Backend identity | Identifies Cortex and the selected enforced model; does not claim to be Claude Code. | Reports the Claude backend or an unenforced/default model. |
268
+ | Q-CX-TOOLS | Native surface | Reports Cortex-native tools; garden tools arrive only through `entwurf-bridge`. | Lists Claude's `Read/Bash/Edit/Write` allowlist as its native surface. |
269
+ | Q-CX-MCP | Bridge projection | `entwurf-bridge` is reachable through the overlay-private `cortex/mcp.json`; no ambient operator MCP catalog appears. | Bridge absent, or unrelated operator MCP servers leak in. |
270
+ | Q-CX-CARRIER | Context carrier | Says Cortex has no system-prompt engraving carrier; engraving/context arrived in the first-user augment. | Claims `_meta.systemPrompt` delivered the engraving. |
271
+ | Q-CX-HOME | Containment | Distinguishes isolated HOME from the real operator HOME restored only for the bridge; `CORTEX_HOME` is absent. | Claims broad operator home/config inheritance or a present `CORTEX_HOME`. |
269
272
 
270
- - **PASS** All three quoted with `${...}` visually preserved (the ZWSP is invisible; a PASS looks identical to the input).
271
- - **FAIL** TOKEN_A shows a tool list in place of `${AvailableTools}`; any token mutated, dropped, or interpolated.
273
+ The live `smoke-acp-cortex-live` and deterministic `check-acp-cortex` remain the
274
+ oracles. This interview tests whether the model describes that surface honestly.
272
275
 
273
276
  ---
274
277
 
275
278
  # HISTORY (pointer)
276
279
 
277
- 2026-07-25 repair.1 installed-native host acceptance (stable-promotion prerequisite):
278
- the published registry artifact `@junghanacs/entwurf@0.12.8-repair.1` was installed
279
- fresh on two Linux hosts (maintainer + secondary) through the package's stable bins.
280
- Each host ran installed `entwurf install-meta-bridge`, opened a NEW real Claude Code
281
- session with a live MCP child, and ran the installed `entwurf doctor-meta-bridge`
282
- against an isolated clean `PI_CODING_AGENT_DIR`; both doctors reached **PASS**, including
283
- the live MCP owner join and a physical `entwurf_v2` delivery. The maintainer host first
284
- proved the oracle's value by failing when its managed dev-bin shadowed the registry
285
- `entwurf-bridge`: the installed v2 hook wrote a v2 record while the checkout's v3 bridge
286
- refused it. Removing the managed dev bin made PATH resolve the registry bridge, after
287
- which the same native proof passed. The test-created v2 record from that failed mixed-path
288
- attempt was preserved under `meta-sessions.proof-failed-20260725T165227/`; the maintainer's
289
- V3 development wiring was restored after acceptance. This closes VERIFY's two-host
290
- repair.1 prerequisite for a separately authorized stable `0.12.8`; it is host
291
- corroboration of the published repair artifact, not evidence for the future stable
292
- candidate, which still earns exact-SHA CI, LIVE, and preserved-artifact acceptance.
293
- Exact pre-version closure checkpoint `28a52fe2d6e9ca29b657a33e5c80ff4debda2f0f`
294
- passed GitHub Actions run [30149759311](https://github.com/junghan0611/entwurf/actions/runs/30149759311):
295
- `check`, `install-surface`, and `artifact-consumer` all success. The host proof then found
296
- a one-line `remove-dev-bin` dispatch defect, so the eventual stable landing HEAD must earn
297
- a fresh exact-SHA run; this checkpoint is not reused as that acceptance.
298
-
299
- 2026-07-24 (night) upgrade-harness + review acceptance at exact HEAD
300
- `cbda097` (branch `repair/v2-core-debt`, merged to main the same night — the
301
- hard-cut branch chronicle lives in issue #50): the three-cell harness gained
302
- the UPGRADE axis — `setup` / `install` / `install-meta-bridge` refuse a
303
- pre-cut (v1/v2) meta-record store BEFORE their first write, prescribe on
304
- three axes (pre-cut → migrate; problems → repair first; both → repair FIRST,
305
- then migrate), and the proof seeds every host state from frozen fixture bytes
306
- (`fixtures/meta-store`, sha256-manifested, excluded from the tarball).
307
- Deterministic cells at this HEAD: `pnpm check` EXIT=0 (source cell
308
- `check-upgrade-gate` 57/0), `check-pack-install` EXIT=0,
309
- `ENTWURF_REQUIRE_DOCKER=1 check-install-container` EXIT=0 — candidate
310
- `junghanacs-entwurf-0.12.8-repair.1.tgz` **sha256
311
- `db17165f962c938d71ef97cb7a86252549dc91b00d5ec67f63ec65b41039e6dc`**,
312
- 11413738 bytes, image `sha256:f1158c7f34cf35a047bf0513c38282bb2fa253529e5ae404b32c6d93697410be`.
313
- Live at this HEAD: `LIVE=1 release-gate` **MUST 16/1/0 + BEHAVIOR 1/0,
314
- EXIT=1** — the single FAIL is `smoke-acp-bundled-mcp-live`, the known
315
- bundled-MCP readiness race (ROADMAP 「🔴 OPEN」, GLG: observe, don't fix;
316
- sample recorded with transcript; isolated re-run PASS 4/4). Every other MUST
317
- passed at this HEAD, including `smoke-acp-v2-send-live` (send identity /
318
- replyability) and the matrix honest-reject. **A release cut stays blocked on
319
- that red by the gate's own words; the merge to main was GLG's explicit call
320
- with the race documented as an open observation item.**
321
-
322
- 2026-07-24 dependency-uplift acceptance at exact HEAD
323
- `7cbeb29b6afcfbaf4fc28da3b7929037c339113d` (branch `repair/v2-core-debt`): pi
324
- runtime **0.80.7 → 0.82.0** and Claude ACP **claude-agent-acp 0.54.1 → 0.61.0 /
325
- ACP SDK 1.1.0 → 1.3.0** as two separate cuts, with `@anthropic-ai/sdk` held at
326
- **0.100.1** (measured through the real module graph: claude-agent-sdk 0.3.217's
327
- `>=0.93.0` peer resolves to 0.100.1 there; dropping the direct pin under this
328
- repo's `autoInstallPeers:false` leaves only 0.91.1 and the peer goes unmet).
329
- Deterministic 3 cells all EXIT=0 on Node 24 Linux — checkout (`pnpm
330
- build-bridge && pnpm check`), installed tree (`check-pack-install`: resolved
331
- tree holds only `@earendil-works@0.82.0`, loader drove the pinned pi, installed
332
- bin delivered a `.msg`), clean consumer (`ENTWURF_REQUIRE_DOCKER=1
333
- check-install-container`, candidate `junghanacs-entwurf-0.12.8-repair.1.tgz`
334
- **sha256 `ab5dee07585c8d7a4f8f174cedea0051489ae1a26766ff1baf8edd7377d5bac7`**,
335
- 11391060 bytes, image `sha256:f1158c7f34cf35a047bf0513c38282bb2fa253529e5ae404b32c6d93697410be`).
336
- Live: `LIVE=1 ./run.sh release-gate` measured **MUST 17/0/0 + BEHAVIOR 1/0,
337
- EXIT=0** at this HEAD — the first aggregate to include
338
- `smoke-acp-v2-send-live`, which closes the SEND half of ACP citizenship (an ACP
339
- model calls `entwurf_v2` and the `.msg` lands carrying the resident's own garden
340
- id, `entwurf/<model>`, replyable — a gid never present in the prompt). Two
341
- stale claims were retired against measurement rather than argument: the
342
- extension-loader `/compat` shim survives 0.82.0 (root / `/compat` / `/oauth`
343
- untouched; `/providers/all` is an addition, and the curated Claude anchors are
344
- byte-identical across the bump), and the "one-shot bundled-MCP teardown hang"
345
- that a gate comment used as its rationale does not reproduce on this
346
- combination. What a plain `pi -p` genuinely lacks is garden identity, and only
347
- without `--entwurf-control` — now documented as a provider/citizen boundary
348
- instead of read as a defect.
349
-
350
- 2026-07-24 record-era aggregate floor: `LIVE=1 ./run.sh release-gate` measured
351
- **MUST 16/0/0 + BEHAVIOR 1/0, EXIT=0** on the `repair/v2-core-debt` branch after
352
- the #50 C1–C3 cuts and the observability repair — the first aggregate run since
353
- 2026-06-27 (every individual smoke had been green, but the two-tier summary and
354
- exit code of the aggregate command itself had gone unverified for the whole
355
- hard-cut window; three MUST live smokes were found dead on the pre-C2 address
356
- contract and re-authored in the same pass). The step count moved 17→16 with the
357
- v2-cutover smoke retirements. Evidence log: `/tmp/pi-tmux-release-gate.log`
358
- (scratch `/tmp/entwurf-rg-scratch-20260724`).
359
-
360
- 2026-07-22 repair evidence: Linux artifact-consumer C is committed locally as
361
- `328c66e` (not yet pushed at the time of this baseline update); B/B2 direct-native
362
- observations and the exec-only production cut are documented in issue #51 and
363
- VERIFY's host matrix. **Post-provenance C was re-proven rather than inheriting the
364
- earlier green:** the first rerun correctly went RED because its stand-in Claude was
365
- container PID 1, which the product rejects as an impossible/reparented owner. The
366
- fixture now keeps an outer PID-1 shell and runs the consumer as pid 8; both default
367
- pack-once and caller-preserved exact-tgz modes reached doctor PASS with marker
368
- `ownerPid=8 (>1)` and identical artifact sha256. The preserved file's
369
- inode/size/mtime/sha tuple was unchanged across acceptance. Evidence logs:
370
- `/tmp/pi-tmux-entwurf-exact-final.log` and
371
- `/tmp/pi-tmux-entwurf-default-final.log`; the digest belongs in the external cut log,
372
- not inside this shipped file (embedding it would mutate the tarball it names).
373
- This was the `0.12.7-1` gate candidate, **not** the approved release artifact. Exact
374
- mode was later repeated for `0.12.8-repair.0`, and those accepted bytes were published
375
- under `repair` on 2026-07-22. Field evidence then invalidated that release: its installed
376
- MCP dist omitted `entwurf-capabilities.json`, so tools/list and the old doctor stayed
377
- green while every `entwurf_v2` send died ENOENT. The repaired candidate must be
378
- `0.12.8-repair.1` and must earn fresh exact-SHA CI, LIVE-gate, preserved-artifact, and
379
- container evidence; none of repair.0's release evidence transfers. Maintainer/secondary-host
380
- installed doctor GREEN remains deliberately pending until after repair.1 publication.
381
-
382
-
383
- Per-release baselines — the 0.9.0 garden-native identity cut (17 PASS / 0 FAIL /
384
- 0 SKIP `/gnew`-inclusive gate, #28), and the older 0.8.x / 0.5.0 context-pressure
385
- baselines — live in **CHANGELOG.md and git history**, including the gate names of
386
- their era (several of which, e.g. `smoke-all` / `smoke-async-resume` /
387
- `smoke-compaction-policy` / `sentinel` / `xt-tool-surface`, were retired in the
388
- v2 cutover). The live calibration reference is the current release floor in
389
- [VERIFY.md](./VERIFY.md) §0A — most recent: **2026-07-24 MUST 16/0/0 + BEHAVIOR 1/0**.
280
+ Per-release counts, digests, host observations, and incident chronology live in
281
+ [CHANGELOG.md](./CHANGELOG.md), release artifacts, issues, and git history. This
282
+ file keeps only the current operator interview and support verdicts.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,41 @@ All notable changes to this project will be documented here. Format follows [Kee
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## 0.13.1 — 2026-07-31
8
+
9
+ ### Changed
10
+
11
+ - **ACP prompt lifecycle no longer applies a 600-second wall-clock cutoff to a running turn.** Bootstrap remains bounded; user abort sends ACP cancellation before bounded teardown, and child exit/stdio failure now preserves lifecycle phase, exit/signal, and stderr evidence without automatic cold replay.
12
+ - **The release gate now makes actual invocation auditable.** Every MUST step reports PASS, protocol SKIP, or FAIL; `--cut` refuses a MUST SKIP without misreporting it as a failed call. The aggregate includes the native resume, spawn substrate, and authenticated cross-harness delivery chain; Cortex remains an explicitly documented on-demand host-auth axis.
13
+
14
+ ### Fixed
15
+
16
+ - **Claude's tiny non-empty engraving carrier owns its leading boundary.** The SDK fixed identity sentence and `# Engraving Here` now occupy separate blocks while preserving auto-memory containment, deterministic signature bytes, and the empty override opt-out.
17
+ - **The ACP provenance and v2 dispatch surfaces state their real boundaries.** First-user augment versus system carrier is rail-specific, and the `entwurf_v2` description fits the host tool-description cap.
18
+
19
+ ### Verification
20
+
21
+ - The versioned release tree passed `pnpm check`, including **144/144** kill-qualified mutants across 10 lanes and `check-pack` at **309 files**.
22
+ - `LIVE=1 ./run.sh release-gate /tmp/entwurf-release-gate-0.13.1.LeOQDB --cut` passed: **MUST PASS=20 FAIL=0 SKIP=0**, **BEHAVIOR PASS=1 FAIL=0 SKIP=0**, `cut: OK`. Full log: `/tmp/entwurf-release-gate-0.13.1.LeOQDB/release-gate.log`.
23
+ - On-demand lifecycle acceptance `LIVE=1 ./run.sh smoke-acp-long-turn-live` passed on the final source set: a **733,635ms** turn exceeded the retired 600s cutoff with exactly one cold ACP bootstrap and no replay. Cortex is deliberately aggregate-excluded for this cut because the oracle has no Snowflake connection; its 0.13.0 thinkpad LIVE evidence is carry-forward, not a fresh 0.13.1 host certification.
24
+ - `check-pack-install` packed and installed `0.13.1` into a fresh consumer, proving the installed bridge boot/delivery and previous-generation lifecycle without touching the real data tree. The preserved exact candidate's checkout-invisible Docker consumer acceptance remains a `make` responsibility.
25
+
26
+ ## 0.13.0 — 2026-07-30
27
+
28
+ ### Added
29
+
30
+ - **Snowflake Cortex Code joins the ACP rail as the first non-claude backend** — the `cortexAdapter` contributed by hvkiefer (PR #40), landed together with the revisions the CP0 live audit of 2026-07-29 measured against Cortex Code v1.1.52 (`docs/acp-backend-rail.md` §11-8 records the ten defects D1–D10 and the agreed contract; the deltas are drift repair, not contributor error). As landed: the curated surface is the GLG-decided 4-row set (`cortex-auto`, `cortex-claude-opus-5`, `cortex-claude-sonnet-5`, `cortex-openai-gpt-5.4`) riding real pi-ai registry bases behind the reserved `cortex-` routing prefix; launch is `cortex acp serve` from PATH (+ `-c <connection>` via `entwurfProvider.cortexConnection` / `ENTWURF_ACP_CORTEX_CONNECTION`) with **no `-m` pin** — the model is enforced per turn through `session/set_config_option("model", <native id>)`, the same wire call as claude, so a curated id the running cortex no longer serves fails loud before the prompt. Containment is a **session-scoped dual-HOME overlay**: cortex's config/skill/hook surface is `homedir()`-anchored and `CORTEX_HOME` outranks `SNOWFLAKE_HOME`, so the adapter refuses an ambient `CORTEX_HOME` outright (empty string included), runs the child under an isolated HOME (global-scope leak measured to zero; explicit cwd project scope retained), passes through only the measured-minimum auth (`connections.toml`, optional `config.toml`, `cortex/cache/credential_cache` — symlink-through, never copied), authors `autoUpdate: false`, and — because cortex's ACP `newSession` ignores the wire `mcpServers` param — **projects** the envelope-enriched explicit `entwurfProvider.mcpServers` into the overlay-private `cortex/mcp.json`, restoring the real operator HOME on the `entwurf-bridge` entry alone so a cortex sibling sees the real garden (an isolated-HOME bridge measured an empty citizen roster); non-stdio entries fail loud before spawn. Cortex is system-prompt-carrier-less: the operator engraving rides the first-user augment. Coverage: the deterministic `check-acp-cortex` gate (in `pnpm check`) plus the `acp-cortex` mutant lane's twelve kill-qualified claims — ten on that gate, and two cross-gate: the production overlay call site passing `resolveSessionKey`'s authoritative value (`check-acp-session-reuse`) and the real compiled provider entry registering both adapters' curated rows (`check-acp-provider-surface`, so an entry that silently dropped every `cortex-` row can no longer go green) — and the on-demand CP2 live smoke `LIVE=1 ENTWURF_ACP_CORTEX_CONNECTION=<conn> ./run.sh smoke-acp-cortex-live` — a real cortex model turn delivering outbound `entwurf_v2` to a seeded peer as itself, plus overlay disk facts and process-group reclaim (an MCP-configured cortex child ignores stdin EOF) — deliberately outside the claude-only **aggregate** LIVE floor, so a host that runs no cortex cannot redden a claude release; that is a wiring decision, and a cut shipping cortex still owes a deliberate run of it.
31
+ - **A host that does not run Cortex is unaffected by this release.** The external `cortex` CLI is not an npm dependency, and neither package install nor provider registration looks for the executable: the four curated rows are enumerated deterministically from the compiled provider entry, and `cortex acp serve` is spawned only when a turn actually selects a `cortex-` model — so selecting one on a host without Cortex fails loud at that turn rather than degrading install or the rest of the provider. The deterministic `check-acp-cortex` gate runs on fake/injected seams and needs neither the CLI nor Snowflake auth; the aggregate release floor contains no Cortex LIVE step; and the dedicated smoke honest-skips without `LIVE=1`, without `cortex` on `PATH`, or without a connection on the adapter seam. Rows are deliberately **not** hidden by PATH detection — that would make the provider surface differ per host and dissolve the exact-six-row fence — so an explicit operator enable/disable control remains a separate future contract, not a silent behaviour of this cut.
32
+ - **The ACP ordering probe lands as a gated instrument, and the readiness question it exists to answer stays open.** The rail's open question — whether MCP tool availability precedes what `newSession` returns — had no observable signal, so the probe injects a controlled fixture startup delay and reads control + D1 + D2 paired runs off one shared NDJSON axis instead of reconstructing order from separate logs with drifting clocks. A raw client may stand in for the backend only while a gate holds it to the same calls, arguments, and order, so `check-probe-ordering` pins the sequence against `backend.ts` source, attributes every failure to its wire phase, drives the probe-mode fixture as a real child process, types the event log at its door, and replays the paired-verdict truth table through the pure classifier. The log's door is a gate too: the envelope belongs to the writer, `ts` derives from a single clock read, and per `(runId, pid)` writer the raw append order must have strictly increasing `seq` and a non-regressing clock — a JSON-valid line with an unknown marker, a broken sort axis, or a payload the classifier cannot judge takes the INVALIDATED path instead of moving a verdict. The runner now holds the child open past the turn until the marker lands, the child exits, or a deadline anchored on the fixture's own delay markers passes, and only a deadline close lets a missing marker read as evidence; every intervention reports ordering and callability as two axes so a settled comparison is not buried by an unsettled verdict, and each ordering value is named for the comparison it is (`prompt-request-ahead-of-wire` says we issued the request first, never that the server failed to wait). The delta-B name oracle cannot be the model, so that seam is a CLI shim at `CLAUDE_CODE_EXECUTABLE`: the consumer half (target preconditions by key presence, absolute/regular/executable/no-script-suffix assertions, path+sha256 roster pinning with a post-pair re-hash, snapshot channel doors, receive-axis single-prompt binding, structural-vs-reading severity split) and then the producer shim itself both land kill-qualified. **No readiness finding is claimed.** The first paired run under the door contract produced 57 events with zero malformed lines, so the parser is calibrated rather than merely strict, and rail §11-7-b carries the numbers — but the verdict is inconclusive, and an inconclusive verdict is not "nothing wrong". Artifacts predating the window protocol re-parse as INVALIDATED and remain forensic records only.
33
+
34
+ ### Verification
35
+
36
+ - Pre-version landing HEAD `9f1c7dc9e1fa77103e29a6f1884af7759e1595eb` passed exact-SHA GitHub Actions run [30505001694](https://github.com/junghan0611/entwurf/actions/runs/30505001694): `check`, `install-surface`, and `artifact-consumer` all success. That run is also the third-party half of the optionality claim above, at the strength its sources actually carry: `.github/workflows/ci.yml` provisions only checkout, pnpm, and Node 24 — it installs no Cortex CLI and supplies no Snowflake auth — and the required Linux `artifact-consumer` job ran the candidate inside a clean `node:24-bookworm` container and passed. That is a workflow-configuration fact plus a passing consumer run; it is not a probe of the runner image's contents.
37
+ - The prepared tree passed an independent `pnpm check`, including `check-gate-qualification` at **111/111 committed mutants killed** (the `acp-cortex` lane contributing twelve). Then `LIVE=1 ./run.sh release-gate /tmp/entwurf-release-gate-0.13.0.drnRyR` completed all green: **MUST PASS=17 FAIL=0 SKIP=0** and **BEHAVIOR PASS=1 FAIL=0**, EXIT=0. Full log: `/tmp/entwurf-release-gate-0.13.0.drnRyR/release-gate.log`; per-step artifacts are preserved inside it.
38
+ - Cortex acceptance on the landing tree (2026-07-30, Linux/thinkpad, Cortex Code v1.1.52, connection on the adapter seam): the on-demand `smoke-acp-cortex-live` passed **23/23** — a deliberate rerun *after* the `resolveSessionKey` overlay-scope repair, so the shipped claim no longer rests on the earlier CP2 run's code. `check-pack-install` enumerated the **exact six curated rows (claude 2 + cortex 4)** out of the installed package's own model list, and `ENTWURF_REQUIRE_DOCKER=1 ./run.sh check-install-container` consumed candidate `sha256=63342aa8a144011dee86ebea8f0b778c7860e54dc0f1c710438983c679e8af87` on `node:24-bookworm` (`id=sha256:fcd0f74fb415c752…`, `repoDigest=node@sha256:5711a0d445a1af54…`).
39
+ - Cross-rail live round trips are **operator-session evidence, not a gate** (2026-07-29, same implementation set): a Cortex resident used the host pi citizen's garden id rather than inventing one — `agentId=entwurf/cortex-claude-sonnet-5`, `backend=pi`, reply envelope `origin=pi-session`, `replyable=true` — and exchanged real turns with native Claude Code (mailbox drain), pi native (control socket), and pi ACP Claude Sonnet (control socket). The record `20260729T204101-7aaa6f` remains on disk as corroboration.
40
+ - **Deferred to `make` as a release-blocking tag gate:** the preserved exact 0.13.0 candidate must be installed into a fresh temporary root and drive one cold `entwurf/cortex-claude-sonnet-5` turn from *those installed bytes* — unique nonce, exit 0, candidate SHA-256 unchanged before and after, resolved installed package root recorded. Until it runs, installed-artifact evidence and real-Cortex evidence have never met in one execution; a RED there stops the cut before the tag. Prepared-HEAD exact-SHA CI and preserved-candidate container acceptance remain deferred to `make` as usual.
41
+
7
42
  ## 0.12.10 — 2026-07-27
8
43
 
9
44
  ### Changed
package/CONTRIBUTING.md CHANGED
@@ -4,7 +4,9 @@ This is a daily-driver bridge. Correctness beats feature breadth. Read this befo
4
4
 
5
5
  ## What this repo is
6
6
 
7
- `entwurf` is a **garden-citizen dispatch bridge** — entwurf-core (v2 dispatch) + a meta-bridge + a pi adapter + a **Claude-first ACP plugin** — that lets already-running harnesses address one another by garden id; pi is one adapter, not the subject. The ACP plugin borrows the backend's identity (system prompt preset, model behavior, tool implementations) and shapes the *operating surface* — what tools, MCP, skills, and permissions are visible — to match pi's own policy. Claude is the shipped ACP backend, Codex is a native garden citizen, and the Gemini path is deprecated. That is the entire scope.
7
+ `entwurf` is a **garden-citizen dispatch bridge** — entwurf-core (v2 dispatch) + a meta-bridge + a pi adapter + an **ACP plugin on a two-backend adapter rail** — that lets already-running harnesses address one another by garden id; pi is one adapter, not the subject. The ACP plugin borrows the backend's identity (system prompt preset, model behavior, tool implementations) and shapes the *operating surface* — tools, MCP, skills, permissions — to match pi's own policy **wherever that backend exposes a knob for it**. Where it does not, the plugin does not fake one: a cortex session keeps its own native tool surface and receives MCP through an overlay projection, so "shaped to pi's policy" is a Claude-strength claim, not a universal one. Claude is the reference ACP backend and Snowflake Cortex Code is the second (landed 0.13.0, `cortex-` prefixed ids — [docs/acp-backend-rail.md](./docs/acp-backend-rail.md#cortex-code-audit-d1d10)); Codex has native delivery-probe evidence but no managed citizen lane, and Gemini is not a shipped backend. That is the entire scope.
8
+
9
+ **How a backend joins the rail** (the shape a PR must take): one adapter object in `pi-extensions/lib/acp/backend-adapter.ts` + its own curated rows/overlay modules + its own `check-acp-*` gate and mutant lane. Backend-specific *behavior* must stay behind the adapter, and backend-specific settings ride the opaque `adapterSettings` seam rather than growing the common config. That is not a ban on ever touching the common layer (`backend.ts`'s turn loop, `acp-client.ts`, `event-mapper.ts`, `session-store.ts`, `config.ts`) — cortex's landing did change `backend.ts` to pass the authoritative session key through the generic `ensureOverlay` seam. The rule is narrower and stricter: a common-layer change must be **backend-invariant** (it reads no backend name and branches on no backend) and **separately gated**. A common file that grows an `if (backend === …)` is the thing to reject.
8
10
 
9
11
  If a change moves the bridge toward "second harness" — prompt reconstruction, transcript hydration, ambient discovery, silent fallback — it does not belong here.
10
12
 
@@ -16,7 +18,7 @@ These are enforced by code, gates, and review. Do not weaken them in a PR; if yo
16
18
  2. **Session persistence**: only `pi:<sessionId>` is persisted. `cwd:<cwd>` is never persisted.
17
19
  3. **MCP injection**: only via `entwurfProvider.mcpServers`. No ambient `~/.mcp.json` scanning, no `~/.claude/settings.json` MCP inheritance.
18
20
  4. **Operating surface, not config inheritance**: the user's filesystem Claude Code config (`~/.claude/settings.json` hooks, env, plugins, `permissions.defaultMode`) is intentionally *not* inherited. Skills come from `skillPlugins`, permissions from `permissionAllow`, deferred-tool surface from `disallowedTools`. The `CLAUDE_CONFIG_DIR` overlay enforces this even where the SDK reads filesystem independently of `settingSources`.
19
- 5. **Backend-specific knobs stay explicit and namespaced**: Codex/Gemini-era ACP knobs are not part of the current Claude-first shipped path. If a future backend lane reintroduces a sandbox or mode knob, it must use the `ENTWURF_ACP_*` namespace and invalid values must throw, never fall back.
21
+ 5. **Backend-specific knobs stay explicit and namespaced**: retired Codex/Gemini-era ACP knobs are not carried on the current path. A backend that needs its own knob uses the `ENTWURF_ACP_*` namespace, and invalid values must throw, never fall back — cortex followed this with `ENTWURF_ACP_CORTEX_CONNECTION` (the renamed `PI_SHELL_ACP*` legacy var), and its settings key rides `adapterSettings`, not the common config.
20
22
  6. **Bridge does not implement compaction**: When a backend compacts natively, the pi session and mapping survive that. Pi-side JSONL compaction must not be presented as backend-transcript reduction, and backend-specific compaction controls belong to the backend's own native interface. Legacy `PI_SHELL_ACP_*` compaction knobs must not reappear.
21
23
  7. **Backend coverage honesty**: changes to operating surface, session lifecycle, or persistence must state which shipped/probed backend surfaces they cover. A claim that silently drops a covered backend is a regression; if one backend is genuinely not covered, record that carve-out explicitly.
22
24
  8. **This bridge is not a second harness**: no prompt reconstruction, no transcript hydration, no tool result ledger, no Claude Code emulation.