@junghanacs/entwurf 0.12.2 → 0.12.4

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 (39) hide show
  1. package/AGENTS.md +2 -2
  2. package/CHANGELOG.md +39 -0
  3. package/README.md +9 -5
  4. package/VERIFY.md +4 -4
  5. package/demo/README.md +5 -5
  6. package/demo/demo-baseline.sh +2 -2
  7. package/demo/demo.sh +3 -3
  8. package/docs/setup-clean-host.md +27 -10
  9. package/mcp/entwurf-bridge/dist/scripts/meta-bridge-store-doctor.js +55 -0
  10. package/mcp/entwurf-bridge/tsconfig.build.json +14 -6
  11. package/package.json +9 -9
  12. package/pi/entwurf-targets.json +3 -6
  13. package/pi-extensions/lib/acp/acp-client.ts +2 -2
  14. package/pi-extensions/lib/acp/models.ts +7 -9
  15. package/run.sh +74 -21
  16. package/scripts/check-acp-backend-preflight.ts +1 -1
  17. package/scripts/check-acp-config.ts +3 -3
  18. package/scripts/check-acp-event-mapper.ts +1 -1
  19. package/scripts/check-acp-provider-surface.ts +1 -1
  20. package/scripts/check-acp-sdk-surface.ts +22 -22
  21. package/scripts/check-acp-session-reuse.ts +3 -3
  22. package/scripts/check-acp-session-store.ts +6 -6
  23. package/scripts/check-acp-tool-surface.ts +2 -2
  24. package/scripts/check-entwurf-session-identity.ts +9 -9
  25. package/scripts/check-model-lock.ts +2 -2
  26. package/scripts/check-package-source-routing.ts +4 -4
  27. package/scripts/meta-bridge-doctor.sh +55 -10
  28. package/scripts/meta-bridge-state.py +2 -0
  29. package/scripts/resolve-acp-bridge.ts +1 -1
  30. package/scripts/smoke-acp-bundled-mcp-live.ts +1 -1
  31. package/scripts/smoke-acp-carrier-augment-live.ts +1 -1
  32. package/scripts/smoke-acp-mcp-live.ts +1 -1
  33. package/scripts/smoke-acp-memory-containment-live.ts +8 -9
  34. package/scripts/smoke-acp-overlay-live.ts +8 -9
  35. package/scripts/smoke-acp-provider-live.ts +1 -1
  36. package/scripts/smoke-acp-raw-turn-live.ts +12 -11
  37. package/scripts/smoke-acp-session-reuse-live.ts +24 -9
  38. package/scripts/smoke-acp-skill-live.ts +1 -1
  39. package/scripts/smoke-meta-install-state.sh +3 -3
package/AGENTS.md CHANGED
@@ -217,8 +217,8 @@ Code-level invariants pinned at the same time:
217
217
 
218
218
  ## Runtime Dependencies
219
219
 
220
- - `@modelcontextprotocol/sdk` and `zod` are the substrate runtime deps. With the Claude-first ACP plugin shipped, the Claude/ACP backend deps are pinned alongside them: `@agentclientprotocol/claude-agent-acp` (`0.50.0`), `@agentclientprotocol/sdk` (`0.29.0`), `@anthropic-ai/sdk` (`0.100.1`). The Codex/Gemini ACP packages stay out of scope (native already reaches Codex; Gemini/major tools use native).
221
- - `pi` (`@earendil-works/pi-ai`) on PATH at the pinned range (`>= 0.80.2 < 0.81` — devDep exact `0.80.2` + next-minor ceiling). Mismatches are caught by `check-dep-versions` / `check-pi-runtime-version`. 0.80 moved the standalone root `getModels()` to the deprecated `@earendil-works/pi-ai/compat` entrypoint; the curated Claude surface (`pi-extensions/lib/acp/models.ts`) imports `getModels` from `/compat` — the single subpath allowlisted in `check-pi-import-surface`. NOT the 0.80 provider-factory `providers/anthropic` subpath: although it typechecks, pi's extension loader (jiti alias map in pi-coding-agent `core/extensions/loader.ts`) resolves only the bare root, `/compat`, and `/oauth` for extensions — a `providers/*` import resolves to the unresolvable `dist/compat.js/providers/…` and crashes extension load (caught live by `smoke-resident-garden-guard`, not by static typecheck). This `/compat` use is an **extension-loader compatibility shim** chosen by loader constraint, not a preference for a deprecated API — the `<0.81` ceiling guards it; when 0.81 changes `compat` or the loader alias map, re-evaluate against whatever root/loader surface 0.81 then exposes.
220
+ - `@modelcontextprotocol/sdk` and `zod` are the substrate runtime deps. With the Claude-first ACP plugin shipped, the Claude/ACP backend deps are pinned alongside them: `@agentclientprotocol/claude-agent-acp` (`0.54.1`), `@agentclientprotocol/sdk` (`1.1.0`), `@anthropic-ai/sdk` (`0.100.1`). The Codex/Gemini ACP packages stay out of scope (native already reaches Codex; Gemini/major tools use native).
221
+ - `pi` (`@earendil-works/pi-ai`) on PATH at the pinned range (`>= 0.80.3 < 0.81` — devDep exact `0.80.3` + next-minor ceiling). Mismatches are caught by `check-dep-versions` / `check-pi-runtime-version`. 0.80 moved the standalone root `getModels()` to the deprecated `@earendil-works/pi-ai/compat` entrypoint; the curated Claude surface (`pi-extensions/lib/acp/models.ts`) imports `getModels` from `/compat` — the single subpath allowlisted in `check-pi-import-surface`. NOT the 0.80 provider-factory `providers/anthropic` subpath: although it typechecks, pi's extension loader (jiti alias map in pi-coding-agent `core/extensions/loader.ts`) resolves only the bare root, `/compat`, and `/oauth` for extensions — a `providers/*` import resolves to the unresolvable `dist/compat.js/providers/…` and crashes extension load (caught live by `smoke-resident-garden-guard`, not by static typecheck). This `/compat` use is an **extension-loader compatibility shim** chosen by loader constraint, not a preference for a deprecated API — the `<0.81` ceiling guards it; when 0.81 changes `compat` or the loader alias map, re-evaluate against whatever root/loader surface 0.81 then exposes.
222
222
 
223
223
  ## Working Style
224
224
 
package/CHANGELOG.md CHANGED
@@ -4,6 +4,45 @@ All notable changes to this project will be documented here. Format follows [Kee
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## 0.12.4 — 2026-07-01
8
+
9
+ ### Fixed
10
+
11
+ - **Installed `doctor-meta-bridge` no longer false-fails on node_modules strip-types.** The doctor previously ran `scripts/meta-bridge-store-doctor.ts` and `scripts/check-entwurf-v2-surface.ts` through Node strip-types even from an npm/pnpm-installed package. Node refuses type stripping under `node_modules` (`ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING`), so real floor hosts reported false store-scan / v2-surface failures while development clones stayed green. The doctor now branches by package location: installed packages run the prebuilt `mcp/entwurf-bridge/dist/scripts/meta-bridge-store-doctor.js` with plain `node` and defer the repo-only v2 source-shape gate after confirming the shipped source and runtime wiring; development clones keep the raw `.ts` gates.
12
+ - **The store-doctor helper now ships as a node_modules-safe dist artifact.** The bridge build emits `dist/scripts/meta-bridge-store-doctor.js` alongside the MCP bridge closure, reusing the already-shipped `meta-session.js` dependency without adding a new runtime package lane. `check-pack` / `check-pack-install` require the artifact in the tarball and prove it scans a real fixture store under `node_modules` with plain `node`.
13
+ - **Clean-host install docs call out the 0.12.4 doctor floor check.** The walkthrough now tells operators exactly which doctor lines prove the installed-vs-dev split and flags any `ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING` as a pre-0.12.4 or broken-tarball signal.
14
+
15
+ ### Verification
16
+
17
+ - `pnpm check` passed on 2026-07-01 after the doctor/install-floor fix.
18
+ - `./run.sh check-pack-install` passed with the new installed store-doctor scan and doctor-dispatch lock assertions.
19
+ - Release-gate prep evidence: `LIVE=1 ./run.sh release-gate /tmp/psa-release-gate-0.12.4.PliLsd` passed on 2026-07-01; log `/tmp/pi-tmux-entwurf-release-gate-0124.log`; summary `MUST: PASS=17 FAIL=0 SKIP=0`, advisory `BEHAVIOR: PASS=0 FAIL=1` (`smoke-resident-garden-guard` post-`/gnew` autonomous `entwurf_self` identity turn; non-blocking).
20
+ - `hejdev6` real floor host reproduced the pre-fix strip-types failure from an installed package and passed after installing the patched tarball: compiled store-doctor scanned `1 record(s)` with plain `node`, and installed `doctor-meta-bridge` reported store-scan ok plus v2-surface deferred.
21
+
22
+ ## 0.12.3 — 2026-07-01
23
+
24
+ ### Changed
25
+
26
+ - **Claude ACP dependency lane refreshed for Sonnet 5.** The ACP runtime pins now use `@agentclientprotocol/claude-agent-acp@0.54.1` with `@agentclientprotocol/sdk@1.1.0`, while keeping the direct `@anthropic-ai/sdk@0.100.1` peer-resolution pin. The pi adapter floor is now `@earendil-works/pi-* >=0.80.3 <0.81`, matching the runtime catalog that exposes `claude-sonnet-5`.
27
+ - **Curated Claude surface moves from Sonnet 4.6 to Sonnet 5.** `claude-sonnet-5` replaces `claude-sonnet-4-6` across the ACP provider, demo/default smoke targets, pi target registry, and release docs. The Sonnet-specific 200K cap was removed; Sonnet 5 now surfaces the verified 1M context window like the Opus anchor, with a 1M ceiling guard to prevent silent future inflation.
28
+ - **Release and backend docs are version-neutral where the repo shape is stable.** The README now describes the durable repository shape instead of a point-in-time `0.12.x` state, and the clean-host/demo/verification docs reflect the current pi floor and Sonnet 5 defaults.
29
+ - **Cortex and fresh-spawn planning docs realigned to the 0.12 substrate.** The ACP backend rail documentation and NEXT/ROADMAP planning notes now describe the as-built adapter seam and the mux-visible fresh-sibling lane without re-centering old v1/fat-bridge assumptions.
30
+
31
+ ### Fixed
32
+
33
+ - **Live ACP smoke timeout cleanup no longer leaves stale timers after PASS.** Raw-turn, overlay, memory-containment, and session-reuse live smokes now clear their timeout handles when the awaited operation wins, so a successful live check exits promptly instead of lingering until the old timeout expires.
34
+ - **Session-reuse live smoke now preserves its success evidence.** The two-turn reuse smoke no longer calls `process.exit(0)` on success, allowing the turn-2/PASS log and cleanup to drain naturally while the retained ACP child is still handled by the backend exit cleanup.
35
+ - **Claude Code meta-bridge install state also disables workflow surfaces.** `enableWorkflows` and `workflowKeywordTriggerEnabled` are now managed false alongside the existing auto-memory, compaction, prompt-suggestion, progress, and auto-mode settings.
36
+ - **Unsupported ACP Codex targets are not advertised.** The target registry keeps Codex on the native `openai-codex` provider only; `entwurf/gpt-5.4` and `entwurf/gpt-5.5` are removed until an ACP Codex backend exists.
37
+
38
+ ### Verification
39
+
40
+ - `pnpm check` passed on 2026-07-01 after the dependency/model/doc updates; prep log `/tmp/pi-tmux-entwurf-prep-check-0123.log` ended with `EXIT=0`.
41
+ - `LIVE=1 ./run.sh smoke-acp-raw-turn-live` passed with `claude-sonnet-5` and exited promptly after PASS.
42
+ - `LIVE=1 ./run.sh smoke-acp-provider-live` passed with `claude-sonnet-5` through the pi provider path.
43
+ - `LIVE=1 ./run.sh smoke-acp-session-reuse-live` passed with a two-turn reused ACP child; turn 2 recalled the turn-1 codeword from delta-only prompt scope.
44
+ - `LIVE=1 ./run.sh release-gate /tmp/psa-release-gate-0.12.3.ZcRc8w` passed on 2026-07-01 with `MUST: PASS=17 FAIL=0 SKIP=0` and `BEHAVIOR: PASS=1 FAIL=0`; log `/tmp/pi-tmux-entwurf-release-gate-0123.log`.
45
+
7
46
  ## 0.12.2 — 2026-06-29
8
47
 
9
48
  ### Fixed
package/README.md CHANGED
@@ -10,9 +10,7 @@ npm package: <https://www.npmjs.com/package/@junghanacs/entwurf>
10
10
 
11
11
  Legacy package: [`@junghanacs/pi-shell-acp`](https://www.npmjs.com/package/@junghanacs/pi-shell-acp). `entwurf` is its 0.12+ successor line: the same work renamed around the garden-citizen dispatch substrate rather than the pi adapter.
12
12
 
13
- > **Public, active development.** Real working code, still young. Verify it in your own workflow before relying on it all day. Evidence calibration: [VERIFY.md](./VERIFY.md); native async-delivery capability levels: [DELIVERY.md](./DELIVERY.md).
14
-
15
- > **Current state for 0.12.1.** This repo is **entwurf-core (v2 dispatch) + a meta-bridge + a pi adapter + an ACP plugin**. Pi is one supported harness adapter — important because it supplies control sockets and hosts the ACP plugin today — but it is not the project subject. Claude Code is shipped through the meta-bridge; pi is shipped through the control-socket adapter; Codex and Antigravity (`agy`) reach the garden with verified delivery probes, documented per launch mode in [DELIVERY.md](./DELIVERY.md), with shipped adapter/install lanes landing after the 0.12.0 doc cut. The ACP plugin is Claude-first; Cortex/vendor-governed ACP backends are future lanes.
13
+ > **Repository shape.** This repo is **entwurf-core (v2 dispatch) + a meta-bridge + a pi adapter + an ACP plugin**. Pi is one supported harness adapter — important because it supplies control sockets and hosts the ACP plugin today — but it is not the project subject. Claude Code is shipped through the meta-bridge; pi is shipped through the control-socket adapter. Codex and Antigravity (`agy`) have verified delivery probes documented per launch mode in [DELIVERY.md](./DELIVERY.md); shipped adapter/install lanes are tracked separately. The ACP plugin is Claude-first; Cortex/vendor-governed ACP backends are future lanes.
16
14
 
17
15
  <details>
18
16
  <summary>Watch archived pre-0.12 demo (2131×1142 GIF, click to expand)</summary>
@@ -55,7 +53,7 @@ native Claude Code
55
53
  → entwurf_self | entwurf_v2 | entwurf_inbox_read
56
54
  ```
57
55
 
58
- This meta-bridge installer/doctor is **Claude Code only** in the shipped 0.12.0 surface. Codex and Antigravity delivery probes are recorded in [DELIVERY.md](./DELIVERY.md) as verified adapter evidence, not yet shipped install surfaces.
56
+ This meta-bridge installer/doctor is **Claude Code only** in the current shipped surface. Codex and Antigravity delivery probes are recorded in [DELIVERY.md](./DELIVERY.md) as verified adapter evidence, not yet shipped install surfaces.
59
57
 
60
58
  > **Direction.** Inverse of [`pi-acp`](https://github.com/svkozak/pi-acp). `pi-acp` lets external ACP clients talk *to* pi; `entwurf` lets garden citizens talk across harness boundaries — with pi as one adapter, not the center.
61
59
 
@@ -147,7 +145,7 @@ because Node refuses to strip `.ts` files under `node_modules`.
147
145
  ### Pi adapter / ACP plugin lane
148
146
 
149
147
  To use the `entwurf` provider inside pi, install a compatible pi binary
150
- separately (`@earendil-works/pi-coding-agent >=0.80.2 <0.81`). Then point pi at
148
+ separately (`@earendil-works/pi-coding-agent >=0.80.3 <0.81`). Then point pi at
151
149
  the npm-installed package or development clone:
152
150
 
153
151
  ```bash
@@ -183,6 +181,12 @@ entwurf install-meta-bridge
183
181
  entwurf doctor-meta-bridge
184
182
  ```
185
183
 
184
+ On npm/pnpm-installed packages, `doctor-meta-bridge` must use prebuilt JS for its
185
+ store scan and defer repo-only source-shape gates; Node refuses strip-types for
186
+ raw `.ts` helpers under `node_modules`. If the doctor reports
187
+ `ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING`, reinstall a current package before
188
+ trusting the floor result.
189
+
186
190
  For manual configuration, [`pi/settings.reference.json`](./pi/settings.reference.json)
187
191
  shows the pi adapter settings shape, and the external-host examples below show
188
192
  plain MCP registrations.
package/VERIFY.md CHANGED
@@ -44,7 +44,7 @@ Verification here is not a benchmark. In production we exchange short turns and
44
44
  ### Verifying the two capabilities a gate cannot fully judge
45
45
 
46
46
  - **Garden-id delivery:** discover a target with `entwurf_peers`, then `entwurf_v2` with the correct intent — `fire-and-forget` for a live/replyable or meta-session target, `owned-outcome` only to wake a dormant record-backed pi citizen. Picking the wrong intent is rejected, never auto-fixed.
47
- - **ACP continuity:** a direct `pi --provider entwurf --model claude-sonnet-4-6` turn, or the `smoke-acp-session-reuse-live` gate (process-scoped reuse + recall). Multi-turn reuse is proven by that gate, not by any v1 resume tool.
47
+ - **ACP continuity:** a direct `pi --provider entwurf --model claude-sonnet-5` turn, or the `smoke-acp-session-reuse-live` gate (process-scoped reuse + recall). Multi-turn reuse is proven by that gate, not by any v1 resume tool.
48
48
 
49
49
  ### What NOT to do — bypassing the operational path
50
50
 
@@ -102,7 +102,7 @@ pi install git:github.com/junghan0611/entwurf # pi auto-clones + instal
102
102
  cd /path/to/consumer-project
103
103
  ~/.pi/agent/git/github.com/junghan0611/entwurf/run.sh install . # wire bundled mcpServers
104
104
  pi --list-models entwurf # curated model surface
105
- pi --provider entwurf --model claude-sonnet-4-6 -p "reply with ok only" # one-turn smoke
105
+ pi --provider entwurf --model claude-sonnet-5 -p "reply with ok only" # one-turn smoke
106
106
  ```
107
107
 
108
108
  Expected: the package appears under pi's `User packages`; `install .` logs `added entwurfProvider.mcpServers.entwurf-bridge` + `updated <project>/.pi/settings.json`; the smoke returns a one-word reply (full bootstrap → ACP session → bridge → clean shutdown). Note: `~/.pi/agent/git/.../entwurf` is pi-managed — do not edit it (a `pi update` overwrites). Step 2 is still required after `pi install git:…`.
@@ -115,7 +115,7 @@ pnpm install # pnpm is the pinned packageManag
115
115
  pi install ./
116
116
  ./run.sh install /path/to/consumer-project
117
117
  pnpm check # full deterministic floor
118
- pi --provider entwurf --model claude-sonnet-4-6 -p "reply with ok only"
118
+ pi --provider entwurf --model claude-sonnet-5 -p "reply with ok only"
119
119
  LIVE=1 ./run.sh release-gate /path/to/consumer-project
120
120
  ```
121
121
 
@@ -140,7 +140,7 @@ Compare a fresh self-awareness report across axes: (1) same backend, different i
140
140
 
141
141
  ## 1A. Main Agent Evaluation — Is `entwurf` Claude strong enough?
142
142
 
143
- Separate from continuity gates. Gates prove "sessions continue"; this questionnaire examines tool self-awareness / native tool usability / MCP-boundary awareness / long-turn focus / quality vs direct Claude Code. Run it against `entwurf/claude-sonnet-4-6` via a direct `pi --provider entwurf` turn (or a live ACP session); accumulate turns by re-prompting the same target.
143
+ Separate from continuity gates. Gates prove "sessions continue"; this questionnaire examines tool self-awareness / native tool usability / MCP-boundary awareness / long-turn focus / quality vs direct Claude Code. Run it against `entwurf/claude-sonnet-5` via a direct `pi --provider entwurf` turn (or a live ACP session); accumulate turns by re-prompting the same target.
144
144
 
145
145
  ### 1A.0 Two carrier surfaces — engraving vs pi-context-augment (load-bearing)
146
146
 
package/demo/README.md CHANGED
@@ -17,7 +17,7 @@ Historical pre-0.12 demo, still linked from the top-level `README.md` as archive
17
17
  tools, names the carrier surface for each cited piece of
18
18
  information, and admits unknowns instead of fabricating.
19
19
  2. **Entwurf surface** — the same pane spawns a sibling via the
20
- `entwurf` tool (`mode=sync`, cross-model — driver `claude-sonnet-4-6`,
20
+ `entwurf` tool (`mode=sync`, cross-model — driver `claude-sonnet-5`,
21
21
  sibling `gpt-5.4`), prints the Session ID, and quotes the sibling's
22
22
  one-line reply verbatim.
23
23
 
@@ -81,7 +81,7 @@ grep -E '(entwurf|model-switch)' demo/sender-debug.log
81
81
  | Var | Default | Meaning |
82
82
  |---|---|---|
83
83
  | `PEER_MODEL` | `entwurf/gpt-5.4` (≡ `piat`) | top pane backend (receives greeting) |
84
- | `SENDER_MODEL` | `entwurf/claude-sonnet-4-6` (≡ `pias`) | bottom pane backend (drives scenes) |
84
+ | `SENDER_MODEL` | `entwurf/claude-sonnet-5` (≡ `pias`) | bottom pane backend (drives scenes) |
85
85
  | `SCENE_DELAY` | `25` | seconds to wait for each scene's agent work |
86
86
  | `WARMUP` | `3` | seconds to wait for both pi banners |
87
87
  | `FINAL_PAUSE` | `5` | extra wait after scene 3 (peer reply lag) |
@@ -93,7 +93,7 @@ grep -E '(entwurf|model-switch)' demo/sender-debug.log
93
93
 
94
94
  | Var | Default | Meaning |
95
95
  |---|---|---|
96
- | `DRIVER_MODEL` | `entwurf/claude-sonnet-4-6` (≡ `pias`) | the driven pane — answers Q-B0 and spawns the sibling |
96
+ | `DRIVER_MODEL` | `entwurf/claude-sonnet-5` (≡ `pias`) | the driven pane — answers Q-B0 and spawns the sibling |
97
97
  | `SIBLING_MODEL` | `entwurf/gpt-5.4` (≡ `piat`) | cross-backend sibling spawned in scene 2 |
98
98
  | `SIBLING_CWD` | repo root | cwd passed to the entwurf sibling (drives `<project-context>` injection) |
99
99
  | `SCENE1_DELAY` | `60` | seconds for the long English baseline answer |
@@ -114,7 +114,7 @@ The demo launch lines correspond to your shell aliases:
114
114
  | Alias | Model id | Use as |
115
115
  |---|---|---|
116
116
  | `piao` | `entwurf/claude-opus-4-8` | `SENDER_MODEL` (precision scenes) |
117
- | `pias` | `entwurf/claude-sonnet-4-6` | `SENDER_MODEL` (default) |
117
+ | `pias` | `entwurf/claude-sonnet-5` | `SENDER_MODEL` (default) |
118
118
  | `piat` | `entwurf/gpt-5.4` | `PEER_MODEL` (default) |
119
119
  | `piat5` | `entwurf/gpt-5.5` | either |
120
120
  | `piag` | `entwurf/gemini-3.1-pro-preview` | either |
@@ -137,7 +137,7 @@ SCENE_DELAY=30 FINAL_PAUSE=10 bash demo.sh
137
137
 
138
138
  ## Prerequisites
139
139
 
140
- - `pi` on PATH (current floor 0.80.2)
140
+ - `pi` on PATH (current floor 0.80.3)
141
141
  - `entwurf` provider configured + auth ready for the selected sender/peer models
142
142
  - `asciinema` installed
143
143
  - `agg` installed (optional — only for GIF conversion)
@@ -8,7 +8,7 @@
8
8
  # reply in the same pane (cross-model, mode=sync).
9
9
  #
10
10
  # Layout (tmux, 220x50):
11
- # pane 0 (single) — driven pi (claude-sonnet-4-6) — receives both prompts.
11
+ # pane 0 (single) — driven pi (claude-sonnet-5) — receives both prompts.
12
12
  #
13
13
  # Recording: asciinema → baseline.cast → agg → baseline.gif
14
14
 
@@ -30,7 +30,7 @@ GIF="$PUBLISH_DIR/entwurf-demo.gif"
30
30
  DRIVER_LOG="$OUTDIR/baseline-debug.log"
31
31
 
32
32
  # Driven pi runs the bridge surface and answers both prompts.
33
- DRIVER_MODEL=${DRIVER_MODEL:-entwurf/claude-sonnet-4-6} # pias
33
+ DRIVER_MODEL=${DRIVER_MODEL:-entwurf/claude-sonnet-5} # pias
34
34
  # Sibling spawned via entwurf in scene 2 — different backend for contrast.
35
35
  SIBLING_MODEL=${SIBLING_MODEL:-entwurf/gpt-5.4} # piat
36
36
  SIBLING_CWD=${SIBLING_CWD:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}
package/demo/demo.sh CHANGED
@@ -3,7 +3,7 @@
3
3
  #
4
4
  # Layout (tmux, 220x50):
5
5
  # pane 0 (top) — peer pi (codex, gpt-5.4) — idle, waits for greeting
6
- # pane 1 (bottom) — sender pi (claude-sonnet-4-6) — driven by send-keys
6
+ # pane 1 (bottom) — sender pi (claude-sonnet-5) — driven by send-keys
7
7
  #
8
8
  # Scenes (driven into sender pane):
9
9
  # 1. Spawn a sonnet sibling, store one fact.
@@ -32,7 +32,7 @@ SENDER_LOG="$OUTDIR/sender-debug.log"
32
32
 
33
33
  # Models match the user's piat / pias aliases.
34
34
  PEER_MODEL=${PEER_MODEL:-entwurf/gpt-5.4} # piat
35
- SENDER_MODEL=${SENDER_MODEL:-entwurf/claude-sonnet-4-6} # pias
35
+ SENDER_MODEL=${SENDER_MODEL:-entwurf/claude-sonnet-5} # pias
36
36
 
37
37
  # Pacing in seconds. Tuned from real runs: each scene's actual agent work
38
38
  # completes in ~5–15 s (Scene 1 sibling cold-spawn is the slowest; resume +
@@ -134,7 +134,7 @@ sleep "$WARMUP"
134
134
  # window/pane base-index configs.
135
135
  drive() {
136
136
  # Scene 1 — spawn + memory write
137
- tmux send-keys -t "$SENDER_PANE" -l 'Demo scene 1. Spawn a claude-sonnet-4-6 sibling via the entwurf tool. provider: entwurf, model: claude-sonnet-4-6, cwd: /home/junghan/repos/gh/entwurf, mode: sync. Task body: "You are a sibling for a recorded demo. Remember one fact only — my favorite forge color is tempered indigo. Reply with one short sentence acknowledging. No tool calls, no repo exploration." After it returns, print only the Session ID line so I can see it.'
137
+ tmux send-keys -t "$SENDER_PANE" -l 'Demo scene 1. Spawn a claude-sonnet-5 sibling via the entwurf tool. provider: entwurf, model: claude-sonnet-5, cwd: /home/junghan/repos/gh/entwurf, mode: sync. Task body: "You are a sibling for a recorded demo. Remember one fact only — my favorite forge color is tempered indigo. Reply with one short sentence acknowledging. No tool calls, no repo exploration." After it returns, print only the Session ID line so I can see it.'
138
138
  tmux send-keys -t "$SENDER_PANE" Enter
139
139
  sleep "$SCENE_DELAY"
140
140
 
@@ -4,9 +4,11 @@ End-to-end install of **entwurf** on a host with only `git` available — no
4
4
  node, no npm package, no pi binary, no dotfiles. The point is to validate the
5
5
  public install surface as an outside user would experience it.
6
6
 
7
- > **Scope.** This is the entwurf 0.12.1 install recipe. The base package install
7
+ > **Scope.** This is the entwurf 0.12.4 install recipe. The base package install
8
8
  > is **neutral npm**, not `pi install npm:...`. Pi is an optional adapter lane for
9
- > the ACP provider / control-socket runtime.
9
+ > the ACP provider / control-socket runtime. The 0.12.4 floor fix is explicitly
10
+ > covered here: installed packages under `node_modules` must not run raw `.ts`
11
+ > doctor helpers through Node strip-types.
10
12
 
11
13
  `entwurf` is a garden-citizen dispatch substrate and meta-bridge. It does not
12
14
  provide, copy, or mediate backend credentials — it lets the official backend CLI
@@ -30,7 +32,7 @@ ssh cleanhost 'uname -a; whoami; which git node npm pi claude 2>/dev/null'
30
32
  | Node | **24** recommended; `>=22.6.0` minimum | `engines.node` (Node strip-types / ESM runtime) |
31
33
  | npm | bundled with Node 24 | public package install path |
32
34
  | entwurf | `@junghanacs/entwurf` | neutral npm package; exposes `entwurf` and `entwurf-bridge` bins |
33
- | pi binary | **optional**, `@earendil-works/pi-coding-agent >=0.80.2 <0.81` | needed only for the pi adapter / ACP provider / spawn-bg resume lane |
35
+ | pi binary | **optional**, `@earendil-works/pi-coding-agent >=0.80.3 <0.81` | needed only for the pi adapter / ACP provider / spawn-bg resume lane |
34
36
 
35
37
  ## Stage 0 — Node 24 via nvm
36
38
 
@@ -72,9 +74,11 @@ MCP bridge can boot in Claude Code / Codex / Antigravity without pi present.
72
74
  ## Stage 2 — auth-free bridge boot
73
75
 
74
76
  Prove the installed MCP server answers `tools/list` from inside `node_modules`.
75
- This is the regression that 0.12.0 missed: Node refuses `--experimental-strip-types`
76
- for `.ts` under `node_modules`, so the installed package must boot the prebuilt
77
- JS under `mcp/entwurf-bridge/dist/`.
77
+ This is the first `node_modules` strip-types regression fixed in 0.12.0: Node
78
+ refuses `--experimental-strip-types` for `.ts` under `node_modules`, so the
79
+ installed package must boot the prebuilt JS under `mcp/entwurf-bridge/dist/`.
80
+ The 0.12.4 doctor fix below applies the same installed-vs-dev split to
81
+ `doctor-meta-bridge` helper checks.
78
82
 
79
83
  ```bash
80
84
  node --input-type=module <<'JS'
@@ -109,7 +113,7 @@ If the host will run pi sessions or the Claude ACP provider through pi, install
109
113
  a compatible pi binary separately and wire the target project.
110
114
 
111
115
  ```bash
112
- npm install -g @earendil-works/pi-coding-agent@0.80.2
116
+ npm install -g @earendil-works/pi-coding-agent@0.80.3
113
117
  pi --version
114
118
 
115
119
  mkdir -p ~/entwurf-smoke
@@ -126,7 +130,7 @@ Drift points:
126
130
  `entwurf-bridge`, and links `~/.pi/agent/entwurf-targets.json` to the package's
127
131
  `pi/entwurf-targets.json`.
128
132
  - Older pi versions may silently miss the provider/extension surface. Use the
129
- pinned floor (`>=0.80.2 <0.81`) for release verification.
133
+ pinned floor (`>=0.80.3 <0.81`) for release verification.
130
134
  - A host that only uses the external MCP bridge can skip this stage until it
131
135
  needs `owned-outcome` spawn-bg resume or pi-native control sockets.
132
136
 
@@ -141,6 +145,19 @@ entwurf install-meta-bridge
141
145
  entwurf doctor-meta-bridge
142
146
  ```
143
147
 
148
+ On an installed package (`.../node_modules/@junghanacs/entwurf`), the doctor must
149
+ not try to strip-types-run raw `.ts` helpers. In the output, check for these two
150
+ 0.12.4 floor-regression signals:
151
+
152
+ ```text
153
+ ok full store scan: no corrupt records, duplicate nativeSessionId, body/filename drift, or backend↔wakeMode contradiction
154
+ ok check-entwurf-v2-surface: shipped surface source present; exhaustive source-shape gate is a repo/release invariant (not run under node_modules)
155
+ ```
156
+
157
+ If either section reports `ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING`, the host
158
+ is still running a pre-0.12.4 package or a broken tarball. Reinstall the current
159
+ package and re-run `entwurf install-meta-bridge && entwurf doctor-meta-bridge`.
160
+
144
161
  A plain external MCP host can call tools but is non-replyable. A garden-native
145
162
  meta-session has a garden id, a mailbox, and a trusted sender marker; it can call
146
163
  `entwurf_self`, receive mailbox wakeups, and be replied to by garden id.
@@ -157,7 +174,7 @@ source ~/.bashrc
157
174
  claude login
158
175
 
159
176
  cd ~/entwurf-smoke
160
- pi --provider entwurf --model claude-sonnet-4-6 -p "reply with ok only"
177
+ pi --provider entwurf --model claude-sonnet-5 -p "reply with ok only"
161
178
  ```
162
179
 
163
180
  If the backend CLI fails directly (`claude -p "ping"`), fix that upstream first.
@@ -171,7 +188,7 @@ a raw pi-assigned uuid hard-exits before any model turn.
171
188
 
172
189
  ```bash
173
190
  pi --session-id "$(entwurf new-session-id)" \
174
- --entwurf-control --provider entwurf --model claude-sonnet-4-6
191
+ --entwurf-control --provider entwurf --model claude-sonnet-5
175
192
  # control socket: ~/.pi/entwurf-control/<garden-id>.sock
176
193
  ```
177
194
 
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * meta-bridge-store-doctor — fail-loud full scan for meta-session records.
4
+ *
5
+ * The store is the authority for native→garden lookup. Doctor must therefore
6
+ * refuse corrupt records, duplicate nativeSessionId authorities, and body ↔
7
+ * filename drift instead of auto-pruning or silently picking one.
8
+ */
9
+ import fs from "node:fs";
10
+ import path from "node:path";
11
+ import { parseMetaIdentity } from "../pi-extensions/lib/meta-session.js";
12
+ const dir = process.argv[2];
13
+ if (!dir) {
14
+ console.error("usage: node --experimental-strip-types scripts/meta-bridge-store-doctor.ts <meta-sessions-dir>");
15
+ process.exit(2);
16
+ }
17
+ const failures = [];
18
+ const nativeToFiles = new Map();
19
+ let scanned = 0;
20
+ if (!fs.existsSync(dir)) {
21
+ console.log(`meta-store scan ok: ${dir} does not exist yet (0 records)`);
22
+ process.exit(0);
23
+ }
24
+ for (const filename of fs.readdirSync(dir).sort()) {
25
+ if (!filename.endsWith(".meta.json"))
26
+ continue;
27
+ scanned += 1;
28
+ const file = path.join(dir, filename);
29
+ try {
30
+ // dual-read (3D-4 commit1): parseMetaIdentity reads v1 AND v2 and normalizes,
31
+ // so doctor's gardenId/nativeSessionId checks survive the v2 cut.
32
+ const id = parseMetaIdentity(fs.readFileSync(file, "utf8"));
33
+ const expectedFilename = `${id.gardenId}.meta.json`;
34
+ if (filename !== expectedFilename) {
35
+ failures.push(`${filename}: body/filename drift — body gardenId=${id.gardenId}, expected filename ${expectedFilename}`);
36
+ }
37
+ const files = nativeToFiles.get(id.nativeSessionId) ?? [];
38
+ files.push(filename);
39
+ nativeToFiles.set(id.nativeSessionId, files);
40
+ }
41
+ catch (err) {
42
+ failures.push(`${filename}: ${err instanceof Error ? err.message : String(err)}`);
43
+ }
44
+ }
45
+ for (const [nativeSessionId, files] of nativeToFiles.entries()) {
46
+ if (files.length > 1) {
47
+ failures.push(`duplicate nativeSessionId ${JSON.stringify(nativeSessionId)} in ${files.join(", ")} — authority ambiguity; prune manually`);
48
+ }
49
+ }
50
+ if (failures.length > 0) {
51
+ for (const failure of failures)
52
+ console.error(`FAIL: ${failure}`);
53
+ process.exit(1);
54
+ }
55
+ console.log(`meta-store scan ok: ${scanned} record(s) scanned, no corrupt/duplicate/drift records`);
@@ -33,10 +33,18 @@
33
33
  // Clear the root `exclude` (it filters out every `.ts`-extension lib file the
34
34
  // bridge graph needs). Only node_modules must stay excluded.
35
35
  "exclude": ["../../node_modules"],
36
- // Just the bridge entry (+ the dependency-free protocol.js it reaches via an
37
- // explicit `.js` import). tsc auto-follows the import graph STATIC imports
38
- // AND the lazy `await import("./entwurf-preflight.ts")` and emits exactly the
39
- // boot closure, nothing more. This tracks graph drift automatically and keeps
40
- // the pi-lane-only acp/* (unreached at boot) out of the tarball.
41
- "include": ["./src/index.ts", "../../protocol.js"]
36
+ // The bridge boot entry (+ the dependency-free protocol.js it reaches via an
37
+ // explicit `.js` import) PLUS the doctor's store-scan helper. tsc auto-follows
38
+ // the import graphSTATIC imports AND the lazy
39
+ // `await import("./entwurf-preflight.ts")` and emits exactly that closure,
40
+ // nothing more (the pi-lane-only acp/* stays out of the tarball).
41
+ //
42
+ // WHY store-doctor rides THIS build: meta-bridge-doctor.sh's full store scan
43
+ // must run from an INSTALLED package (under node_modules, where strip-types is
44
+ // refused) — the same node_modules boundary start.sh crosses. Its only repo
45
+ // import is pi-extensions/lib/meta-session.ts, which the bridge graph ALREADY
46
+ // emits here, so it adds ONE leaf JS (dist/scripts/meta-bridge-store-doctor.js)
47
+ // and ZERO new deps. It is NOT in index.ts's boot closure, so
48
+ // check-entwurf-bridge-pi-free (which walks the index eager closure) is unaffected.
49
+ "include": ["./src/index.ts", "../../protocol.js", "../../scripts/meta-bridge-store-doctor.ts"]
42
50
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@junghanacs/entwurf",
3
- "version": "0.12.2",
3
+ "version": "0.12.4",
4
4
  "description": "Garden-citizen dispatch substrate and meta-bridge for Claude Code, Codex, Antigravity, and pi harnesses.",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -67,23 +67,23 @@
67
67
  },
68
68
  "packageManager": "pnpm@10.33.0",
69
69
  "dependencies": {
70
- "@agentclientprotocol/claude-agent-acp": "0.50.0",
71
- "@agentclientprotocol/sdk": "0.29.0",
70
+ "@agentclientprotocol/claude-agent-acp": "0.54.1",
71
+ "@agentclientprotocol/sdk": "1.1.0",
72
72
  "@anthropic-ai/sdk": "0.100.1",
73
73
  "@modelcontextprotocol/sdk": "^1.12.1",
74
74
  "zod": "^3.25.0 || ^4.0.0"
75
75
  },
76
76
  "peerDependencies": {
77
- "@earendil-works/pi-ai": ">=0.80.2 <0.81",
78
- "@earendil-works/pi-coding-agent": ">=0.80.2 <0.81",
79
- "@earendil-works/pi-tui": ">=0.80.2 <0.81",
77
+ "@earendil-works/pi-ai": ">=0.80.3 <0.81",
78
+ "@earendil-works/pi-coding-agent": ">=0.80.3 <0.81",
79
+ "@earendil-works/pi-tui": ">=0.80.3 <0.81",
80
80
  "typebox": "*"
81
81
  },
82
82
  "devDependencies": {
83
83
  "@biomejs/biome": "^2.4.13",
84
- "@earendil-works/pi-ai": "0.80.2",
85
- "@earendil-works/pi-coding-agent": "0.80.2",
86
- "@earendil-works/pi-tui": "0.80.2",
84
+ "@earendil-works/pi-ai": "0.80.3",
85
+ "@earendil-works/pi-coding-agent": "0.80.3",
86
+ "@earendil-works/pi-tui": "0.80.3",
87
87
  "@types/node": "^24.3.0",
88
88
  "husky": "^9.1.7",
89
89
  "typescript": "^6.0.2"
@@ -1,20 +1,17 @@
1
1
  {
2
2
  "$comment": "Entwurf Target Registry — exact (provider, model) allowlist. SSOT for what can be spawned via entwurf. See entwurf/AGENTS.md Entwurf Orchestration. Resume path intentionally bypasses this registry per Identity Preservation Rule.",
3
3
  "$notes": {
4
- "gpt-5.5": "High-end frontier target with 400K native codex context. Cost: ~$5 input / $30 output per 1M tokens on this tier — ~6x gpt-5.4. Do not make it the default. Use explicitly for long-context / high-quality work only. ACP-routed entries are `explicitOnly`: caller must pass provider=entwurf to route through the ACP bridge, otherwise bare `gpt-5.5` resolves to native openai-codex.",
5
- "bareResolution": "Each bare model id resolves unambiguously because only the native openai-codex entry is non-explicitOnly. Bare `gpt-5.5` -> openai-codex/gpt-5.5. ACP route requires explicit provider.",
4
+ "gpt-5.5": "High-end frontier target with 400K native codex context. Cost: ~$5 input / $30 output per 1M tokens on this tier — ~6x gpt-5.4. Do not make it the default. Use explicitly for long-context / high-quality work only.",
5
+ "bareResolution": "Each bare Codex model id resolves through the native openai-codex provider. Bare `gpt-5.5` -> openai-codex/gpt-5.5. ACP Codex is not on this surface until the ACP backend is implemented.",
6
6
  "gemini": "Gemini ACP targets are routed exclusively through entwurf's `gemini --acp` backend; the host pi removed its built-in google provider in v0.71.0. ACP entries are `explicitOnly` to keep the entwurf surface honest — there is currently no native pi alternative to disambiguate against, but the flag keeps the policy stable if pi reintroduces a google provider later. 3.1 Pro is the subscription-backed high-quality ACP target. Flash / 2.5 routing through ACP is intentionally not on this surface."
7
7
  },
8
8
  "entwurfTargets": [
9
- { "provider": "entwurf", "model": "claude-sonnet-4-6", "enabled": true },
9
+ { "provider": "entwurf", "model": "claude-sonnet-5", "enabled": true },
10
10
  { "provider": "entwurf", "model": "claude-opus-4-8", "enabled": true },
11
11
 
12
12
  { "provider": "openai-codex", "model": "gpt-5.4", "enabled": true },
13
13
  { "provider": "openai-codex", "model": "gpt-5.5", "enabled": true },
14
14
 
15
- { "provider": "entwurf", "model": "gpt-5.4", "enabled": true, "explicitOnly": true },
16
- { "provider": "entwurf", "model": "gpt-5.5", "enabled": true, "explicitOnly": true },
17
-
18
15
  { "provider": "entwurf", "model": "gemini-3.1-pro-preview", "enabled": true, "explicitOnly": true }
19
16
  ]
20
17
  }
@@ -1,5 +1,5 @@
1
1
  // ACP client adapter — the ONE place that touches the @agentclientprotocol/sdk
2
- // 0.29 fluent surface (`client({ name }).connect(stream)`).
2
+ // 1.1 fluent surface (`client({ name }).connect(stream)`).
3
3
  //
4
4
  // The wire SDK deprecated the `new ClientSideConnection(toClient, stream)`
5
5
  // constructor in favour of the fluent `client()` builder. The two have
@@ -52,7 +52,7 @@ export interface AcpClientHandlers {
52
52
  }
53
53
 
54
54
  /**
55
- * Production factory — wrap the SDK 0.29 fluent `client()` into the
55
+ * Production factory — wrap the SDK 1.1 fluent `client()` into the
56
56
  * `AcpConnectionLike` seam the backend (and the live smokes) drive.
57
57
  *
58
58
  * Client-side handlers register by ACP method name; agent-side calls go through
@@ -50,18 +50,17 @@ export const ENTWURF_ACP_NO_AUTH_SENTINEL = "entwurf-no-auth";
50
50
  // both axes (protocol smoke + agent interview) — do not extend casually.
51
51
  // Exported so the claude backend adapter (backend-adapter.ts) can answer
52
52
  // `routeModel` without re-deriving the set from curatedClaudeModels().
53
- export const SUPPORTED_ANTHROPIC_MODEL_IDS = ["claude-sonnet-4-6", "claude-opus-4-8"] as const;
53
+ export const SUPPORTED_ANTHROPIC_MODEL_IDS = ["claude-sonnet-5", "claude-opus-4-8"] as const;
54
54
 
55
55
  /** The anchor model whose absence is a hard registry regression, not a soft skip. */
56
56
  export const CURATED_ANCHOR_MODEL_ID = "claude-opus-4-8";
57
57
 
58
- // Anthropic's registry reports 1M for Claude 4.6+ models, but the public
59
- // entwurf surface deliberately distinguishes Sonnet vs Opus: Sonnet stays
60
- // at 200K, Opus surfaces at 1M. (The 0.11.0 ENTWURF_ACP_CLAUDE_CONTEXT env
61
- // override is a behavior-oracle nicety deferred past S0 the loader/fence
62
- // slice only needs the anchor present and registered.)
58
+ // Anthropic's registry reports 1M for both Sonnet 5 and Opus 4.8, and the
59
+ // entwurf surface now exposes the full 1M for BOTH. Sonnet 5's 1M window is the
60
+ // whole point of the 0.12.3 bump — it is the compact-free long-context floor the
61
+ // earlier 200K Sonnet cap could not provide. We still clamp to a 1M ceiling so a
62
+ // future registry value can't silently inflate the surface past what we verify.
63
63
  const CLAUDE_CONTEXT_DEFAULT = 1_000_000;
64
- const CLAUDE_SONNET_DEFAULT = 200_000;
65
64
 
66
65
  // `getModels("anthropic")` reads the static builtin model catalog only — no env
67
66
  // read, no credential access, no network — preserving the #26 auth-boundary
@@ -79,8 +78,7 @@ function requireRegistryModel(models: readonly RegistryModel[], id: string): Reg
79
78
  }
80
79
 
81
80
  function claudeContextWindow(model: { id: string; contextWindow: number }): number {
82
- const cap = model.id === "claude-sonnet-4-6" ? CLAUDE_SONNET_DEFAULT : CLAUDE_CONTEXT_DEFAULT;
83
- return Math.min(model.contextWindow, cap);
81
+ return Math.min(model.contextWindow, CLAUDE_CONTEXT_DEFAULT);
84
82
  }
85
83
 
86
84
  /**