@junghanacs/entwurf 0.35.1 → 0.36.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 (55) hide show
  1. package/AGENTS.md +2 -2
  2. package/CHANGELOG.md +403 -0
  3. package/CONTRIBUTING.md +1 -1
  4. package/DELIVERY.md +17 -0
  5. package/FAQ.md +3 -3
  6. package/README.md +30 -16
  7. package/VERIFY.md +12 -10
  8. package/demo/README.md +1 -1
  9. package/docs/acp-backend-rail.md +69 -5
  10. package/docs/setup-clean-host.md +30 -22
  11. package/mcp/entwurf-bridge/dist/pi-extensions/lib/codex-fresh-preflight.js +4 -3
  12. package/mcp/entwurf-bridge/dist/pi-extensions/lib/native-push/codex-ws-client.js +99 -18
  13. package/mcp/entwurf-bridge/dist/pi-extensions/lib/pi-durable-runtime.js +3 -3
  14. package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-pi-durable.js +59 -14
  15. package/mcp/entwurf-bridge/dist/scripts/codex-socket-classify.js +44 -0
  16. package/mcp/entwurf-bridge/tsconfig.build.json +5 -0
  17. package/package.json +21 -16
  18. package/pi/pi-durable/bootstrap.mjs +12 -8
  19. package/pi/pi-durable/carrier/runtime.js +52 -2
  20. package/pi/pi-durable/carrier/subagent.js +6 -1
  21. package/pi/pi-durable/carrier/tui.js +31 -4
  22. package/pi/pi-durable/carrier-relocation.mjs +2 -2
  23. package/pi/pi-durable/overlay/upstream-pin.json +79 -36
  24. package/pi-extensions/lib/codex-fresh-preflight.ts +4 -3
  25. package/pi-extensions/lib/native-push/codex-ws-client.ts +129 -18
  26. package/pi-extensions/lib/pi-durable-runtime.ts +4 -4
  27. package/pi-extensions/meta-bridge-pi-durable.ts +77 -21
  28. package/run.sh +116 -39
  29. package/scripts/check-acp-prompt-lifecycle.ts +4 -2
  30. package/scripts/check-acp-session-reuse.ts +4 -2
  31. package/scripts/check-acp-stop-reason.ts +4 -2
  32. package/scripts/check-acp-stream-hooks.ts +4 -2
  33. package/scripts/check-acp-usage-accounting.ts +4 -2
  34. package/scripts/check-codex-app-server-launch.ts +55 -12
  35. package/scripts/check-codex-native-push.ts +231 -12
  36. package/scripts/check-gate-qualification.ts +4 -4
  37. package/scripts/check-herdr-supply.ts +32 -7
  38. package/scripts/codex-app-server-launch.sh +54 -29
  39. package/scripts/codex-socket-classify.ts +46 -0
  40. package/scripts/emit-pi-durable-carrier.ts +159 -168
  41. package/scripts/fixtures/herdr-supply.json +10 -9
  42. package/scripts/lib/acp-gate-home.ts +75 -0
  43. package/scripts/lib/codex-socket-listener.ts +429 -0
  44. package/scripts/mutants/acp-stop-reason.json +11 -0
  45. package/scripts/mutants/codex-app-server-launch.json +39 -12
  46. package/scripts/mutants/codex-native.json +67 -0
  47. package/scripts/mutants/control-send-receipt.json +1 -1
  48. package/scripts/mutants/herdr-supply.json +6 -6
  49. package/scripts/mutants/pack-install.json +3 -3
  50. package/scripts/mutants/pi-durable.json +165 -16
  51. package/scripts/mutants/pi-floor.json +5 -5
  52. package/scripts/pi-durable-contact-host.mjs +1 -1
  53. package/scripts/smoke-codex-fresh-live.ts +31 -7
  54. package/scripts/smoke-pi-durable-fresh-live.ts +22 -3
  55. package/pi/pi-durable/overlay/runtime-contacts.patch +0 -283
package/AGENTS.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # AGENTS.md — Maintainer Guidelines for entwurf
2
2
 
3
- For agents who own this repository: durable invariants and the documents that own the changing evidence. This is the **entwurf capability package**: garden-citizen dispatch substrate, native-harness bridges, ACP plugin, and pi adapter. Entwurf is the subject; pi is one adapter. ACP is a plugin, not the boundary. V2 addresses existing citizens; `entwurf_fresh_call` creates a new sibling.
3
+ For agents who own this repository: durable invariants and the documents that own the changing evidence. This is the **entwurf capability package**: visible sibling lifecycle and garden-id delivery — the v2 dispatch core, native-harness bridges, ACP plugin, and pi adapter. Entwurf is the subject; pi is one adapter. ACP is a plugin, not the boundary. V2 addresses existing citizens; `entwurf_fresh_call` creates a new sibling.
4
4
 
5
5
  ## North Star — One Forged Screwdriver
6
6
 
@@ -42,7 +42,7 @@ Ask: does this follow capability rather than a surface name; record backend asym
42
42
  14. **Native-hook ownership is structural.** Use shipped exec launchers and provenance, shared plausible-owner-pid policy, no shell fallback or ancestry guess. Version floors belong to their package source and are enforced there; hook contract/docs own the changing detail.
43
43
  15. **Crash, don’t warn.** Invalid config/path/model/store state throws. Empty catches are only bounded environment probes; diagnostics go to stderr.
44
44
  16. **mux launches, never delivers.** A tmux handle is an ephemeral view, not an address or liveness receipt; screen text/keystrokes are not delivery evidence. A Codex caller's seat is the pane whose title carries its own thread-id, a placement input only; it is never an address, and never a pane nobody named. Cross-window adjacency requires the documented observed-coordinate proof, never pane guessing.
45
- 17. **Supply the missing surface; do not become the harness.** Installation supplies Entwurf bytes, development fixtures, and declared upstream SDK dependencies. Where upstream omits a native execution surface from its distribution, Entwurf may carry that pinned, removable app/TUI with its declared overlay and deterministic emit/import relocation, against one coherent published-library version set. Native execution, auth, queues, storage, transcript and recovery remain upstream-owned (Rule 9). Provenance, license, rebuild and installed-consumer proof belong to the supply contract. No Entwurf-owned copying/inlining of provider model catalogs, subscription, credential or login; no launch-time download, repair, update or fallback. Setup checks capability, version-set coherence and carrier integrity: absent optional capability is explicit skip; incomplete installation, mismatch and drift are named non-green refusals. Portability and runtime evidence remain separate.
45
+ 17. **Supply the missing surface; do not become the harness.** Installation supplies Entwurf bytes, development fixtures, and declared upstream SDK dependencies. Where upstream omits a native execution surface from its distribution, Entwurf owns that thin, removable app/TUI composition as canonical source and ships its deterministic emission (type strip + import relocation) as a carrier, against one coherent published-library version set. The engine — native execution, auth, queues, storage, transcript, compaction, cancellation and recovery — remains the upstream SDK (Rule 9). Provenance, license, rebuild and installed-consumer proof belong to the supply contract. No Entwurf-owned copying/inlining of provider model catalogs, subscription, credential or login; no launch-time download, repair, update or fallback. Setup checks capability, version-set coherence and carrier integrity: absent optional capability is explicit skip; incomplete installation, mismatch and drift are named non-green refusals. Portability and runtime evidence remain separate.
46
46
 
47
47
  History and incident detail belong in [CHANGELOG.md](./CHANGELOG.md), issue threads, [BASELINE.md](./BASELINE.md), or source-adjacent comments. When prose and behavior disagree, repair the owning source or document.
48
48
 
package/CHANGELOG.md CHANGED
@@ -4,6 +4,409 @@ All notable changes to this project will be documented here. Format follows [Kee
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## 0.36.1 - 2026-10-14
8
+
9
+ ### ACP
10
+
11
+ - **Claude ACP closure (#128):** adapter `0.85.1` → `0.90.0`, shared direct/child ACP wire SDK
12
+ `1.6.0` → `1.8.0`, Agent SDK `0.3.286` → `0.3.296`; the shared-wire contract is retained and
13
+ Entwurf adds no new policy. Two no-prompt readbacks against the installed 0.90.0 found the
14
+ three curated ids answering exactly as on 0.85.1, so the set-model alias rows are unchanged.
15
+ The first followed only the production launch and overlay seam; the second also built every
16
+ session with the production session meta under the shipped defaults. Neither sent a prompt or
17
+ saw a model-turn update, but they do not prove zero API calls, measure the billing rail or an
18
+ operator's own settings, or certify a 0.90.0 prompt turn. The first run's two operating
19
+ observations, both with the cause unmeasured, are in the ROADMAP ledger.
20
+ - **ACP gates no longer touch the operator's Claude overlay (#128).** Five offline gates that
21
+ drive the compiled turn loop now sandbox HOME, XDG and the pi agent dir before importing the
22
+ backend; a tripwire and a paired mutant hold that.
23
+
24
+ ### Codex
25
+
26
+ - **The Codex fresh-call smoke reads app-server socket ownership from the kernel (#128).** It
27
+ used to accept the named app-server when its argv spelled `--listen` for the default control
28
+ socket. It now takes the physical endpoint the production socket classifier resolves, and
29
+ requires exactly one process in the named PID's own subtree (the named PID, bound to the start
30
+ time read when its identity was checked, or one of its descendants) to hold that socket's
31
+ kernel LISTEN inode, and a bounded second read must agree. Anything else fails closed as
32
+ not-owned or indeterminate. The 0.36.1 LIVE run exercised it once on an owned app-server
33
+ started with the explicit `--listen` wrapper (below); a vendor-managed daemon is still not
34
+ admitted by it.
35
+
36
+ ### pi-durable
37
+
38
+ - **The pi-durable fresh-call smoke waits for its doorbell turn to end.** It took pd's native
39
+ snapshot as soon as Pi's relay reached the fixture, then required the doorbell submission to
40
+ be `done`. A pi-durable input stays `placed` while the run that consumed it is active and turns
41
+ `done` only when that run ends, so a slow final generation read as a failed admission. The
42
+ 0.36.1 LIVE run caught exactly that (submission `placed`, the last generation task still
43
+ `running`, every delivery receipt green). The smoke now waits, with its existing bounded
44
+ `until`, for this message's submission to settle (`done` or `unanswered`) before the snapshot,
45
+ and still requires `done`. Smoke-only; no pi-durable runtime byte changes.
46
+
47
+ ### Release boundary and verification
48
+
49
+ - **Scope.** A core patch over `v0.36.0`: the four #128 checkpoints `fdf8c3d`, `3da44be`,
50
+ `3e4f52f` and `3242922` above, the handoff `b043833`, and the smoke fix `91cc080`. The
51
+ pi-durable runtime, the Herdr manifest (0.36.0), its host pin (Herdr 0.9.4) and the plugin
52
+ implementation are unchanged; the Herdr runtime's acquisition source does change (the carrier
53
+ below). #142 is not in it. Still open in #128 and not claimed here: admission of a
54
+ vendor-managed Codex daemon, the Copilot 1.0.97 cell, agy 1.3.1 (not certified), the OMP
55
+ 18.10.4 doctors, and the remaining native cells.
56
+ - **Local evidence before this preparation is focused, not a whole pass.** Each affected
57
+ qualification wave (PARTIAL) measured its own checkpoint, each with a green control, and none
58
+ is carried to another. The Codex socket-ownership bytes killed 150/150 in the
59
+ `check-mux-fresh-call` group; 825 of the 975 committed claims were not run. The dependency move
60
+ killed 4/4 in `check-dep-versions`; 971 of 975 were not run. The gate isolation killed 45/45 in
61
+ five groups (prompt lifecycle 15, usage accounting 12, stream hooks 10, stop reason 7, session
62
+ reuse 1); 931 of the 976 committed claims were not run. The qualification body has not run on
63
+ any of them.
64
+ - **Unpublished candidate carrier.** As in 0.36.0, `plugins/herdr/runtime-lock.json`
65
+ temporarily names the closed `herdr-checkout` source: an npm-source lock must agree with the
66
+ checkout's core version, and 0.36.1 has no published integrity yet. The Herdr manifest stays
67
+ 0.36.0. Operating effect: a Herdr plugin installed from `--ref main` while this carrier stands
68
+ acquires this cut's checkout runtime, not npm 0.36.0. The `v2026.10.14-herdr.0.36.0` tag and
69
+ the npm 0.36.0 bytes are unchanged, and moving a host between the two sources needs an
70
+ explicit deactivate/activate. Re-pinning the registry bytes is a separate, verified commit
71
+ after the operator publishes core 0.36.1.
72
+ - **The local FULL is RED, and its Herdr cell is CI's.** `pnpm run check:full` ran once on the
73
+ frozen candidate (642 s, exit 1). `check:core` passed, `check:hermetic` passed every step but
74
+ its last, and `check-herdr-sandbox` failed its version boundary: the pin is Herdr 0.9.4 and
75
+ the host binary was 0.9.3. That cell is not to run locally (it reads the operator's own
76
+ panes), and the aggregate reached it unnoticed; before failing it executed the host binary's
77
+ `--version` once and read no pane. `check:package`, which never ran, then passed alone
78
+ (163 s; 601 files in the dry-run pack). By the operator's decision for this cut only, the
79
+ sandbox cell is owed to the prepared SHA's CI, which runs it on the digest-pinned Herdr 0.9.4
80
+ and must pass there; the exception is not inherited by a later cut. Logs: FULL
81
+ `29b08c71e3d3c92fecb936f5611838088d35b8c5566f4dde99e03cc4b76b0078`, package
82
+ `937e69eeb551bcd0aea049550185e1f6d9f24d917f28099f768928554a16ae84`.
83
+ - **LIVE, taken step by step, not as `release-gate --cut`.** The gate's first MUST step re-runs
84
+ `check:full`, so it would have reached the same local Herdr cell. By the operator's decision for
85
+ this cut, the gate's other 23 MUST steps ran in its own order, command, environment and
86
+ working directory (`run.sh` 7027-7127), stopping at the first red, with no static step. The
87
+ first run passed steps 1-22 and failed `smoke-pi-durable-fresh-live` on the race fixed above.
88
+ The fixed smoke then passed alone on the same candidate (36 assertions, 66 s); steps 1-22 are
89
+ reused because the fix is not an input to them. **MUST 23/23 PASS (22 + the fixed step 23),
90
+ SKIP 0**. The advisory BEHAVIOR step was not run. Among them: the 12 ACP smokes ran the first
91
+ prompt turns on the 0.90.0 driver, and `smoke-codex-fresh-live` passed 66 assertions against
92
+ an app-server started for this cut in its own tmux session (pid 2345801, the named PID's child
93
+ 2345861 holding the kernel LISTEN inode) with `gpt-5.6-luna` and `openai-codex/gpt-5.6-luna`.
94
+ The gate session held no ambient identity carrier, and the candidate fingerprint was the same
95
+ before and after each run. Scratch `/tmp/entwurf-release-gate-0.36.1.1aZK83`. This is local
96
+ LIVE evidence, not a release-gate verdict and not the exact CI.
97
+ - **Exact CI owes the whole floor.** The prepared SHA's exact CI (the four required jobs, the
98
+ qualification body, and `check-herdr-sandbox` on pinned Herdr 0.9.4) is the next checkpoint and
99
+ is not presumed PASS.
100
+ - **Publication boundary.** No make artifact, core tag, GitHub Release or npm publication
101
+ is claimed; they wait for the exact CI, the make decision and the operator.
102
+
103
+ ## v2026.10.14-herdr.0.36.0 — Herdr Entwurf plugin 0.36.0
104
+
105
+ A separate Herdr plugin snapshot, not another core release: core package 0.36.0 and
106
+ its `v0.36.0` tag remain unchanged. The operator has published the core to npm.
107
+
108
+ ### Herdr plugin
109
+
110
+ - **Re-pin the published core 0.36.0.** `plugins/herdr/runtime-lock.json` names npm
111
+ `@junghanacs/entwurf@0.36.0` with the registry's measured sha512
112
+ (`sha512-3aPk69RmAF35x…244UwQ==`). The plugin manifest moves 0.35.1 → 0.36.0;
113
+ admission remains Herdr >= 0.9.0 and the one-build/one-pane/Linux shape is unchanged.
114
+ - **The measured Herdr moves to 0.9.4.** `scripts/fixtures/herdr-supply.json` pins
115
+ v0.9.4 (`7e26bad9`), protocol 22, with both Linux asset digests taken from the
116
+ immutable release and named by its attestation. On aarch64 the pin rests on a
117
+ private CLI baseline: version, protocol 22, 18 `integration status` rows unchanged
118
+ from 0.9.3, pi (v9) and claude (v10) integrations seeded by 0.9.3 reading `current`
119
+ and reinstalling byte-identically, and a residue-free `server stop`. The full
120
+ `check-herdr-sandbox` has not run at this pin on either architecture; its first run
121
+ is this snapshot's CI. The x86_64 asset is recorded as not yet executed.
122
+ - **Herdr 0.9.4 changes how plugins are installed.** It builds each install or update
123
+ in a new managed installation directory, keeps the previous one until no server uses
124
+ it, and adds `herdr plugin update`. The plugin README now says so. The Entwurf runtime
125
+ and harness wiring live outside the checkout, so an update should leave an activated
126
+ host working; that is not yet measured.
127
+
128
+ ### Source-specific verification
129
+
130
+ - Registry metadata reports version/latest 0.36.0, repair 0.12.8-repair.1. The downloaded
131
+ tarball is 11121634 bytes, SHA256
132
+ `7478acd01828280ccb989c4eeb230ae5238bddeeb791f6caa209a4fca2e24a0a`, byte-identical to
133
+ the preserved accepted core candidate; independently computed sha512 equals
134
+ `dist.integrity`. A sandboxed `pi install npm:@junghanacs/entwurf@0.36.0` resolved the
135
+ ACP bridge inside the sandbox and listed the curated `entwurf` models.
136
+ - **Focused gates on the branch.** On aarch64, with the digest-checked Herdr 0.9.4 first
137
+ on `PATH`, nine focused gates passed: `check-herdr-supply` (11 assertions),
138
+ `check-herdr-plugin` (49), `check-herdr-plugin-profile` (14), `check-herdr-plugin-build`
139
+ (21), `check-herdr-runtime-bootstrap` (31), `check-herdr-activation` (33),
140
+ `check-herdr-placement` (25), `check-herdr-fresh-call` (45) and `check-gate-manifests`.
141
+ That last one validated 971 committed mutants across 72 lanes and executed none of them.
142
+ The scripts typecheck fence was clean.
143
+ - **Receipt binding tightened, then re-checked.** Review found that the supply gate's
144
+ receipt check accepted a `herdr 0.9.40` receipt for the 0.9.4 pin, because it matched a
145
+ substring. It now requires the receipt to begin with the exact version token. Nine
146
+ in-memory stimuli against the gate's own check then returned the expected verdicts. They
147
+ include that prefix-version counterexample, which is refused, and a synthetic future x86_64
148
+ positive, which is not execution evidence. The supply gate, the fence and
149
+ `check-gate-manifests` were re-run green. The supply group's qualification PARTIAL killed
150
+ 11/11 mutants with a green control. The other 960 committed mutants did not run, so this is
151
+ not qualification of the snapshot.
152
+ - **The npm runtime swap against the real registry.** These cells used the production
153
+ runtime helper against the real registry, in sandboxed user roots.
154
+ - Seeding: the 0.35.1 runtime came from its own committed lock and package metadata.
155
+ - Swap: 0.35.1 → 0.36.0 took one acquisition. The cached 0.36.0 tarball's sha512 equals
156
+ the lock. Its sha256 `7478acd0…` equals the ready journal's observed digest and the
157
+ accepted core candidate.
158
+ - Journals: the `installing` journal carried the 0.35.1 identity as `previousRuntime`;
159
+ the `runtime-ready` journal carries `previousRuntime: null`.
160
+ - Last-good tree: when acquisition began, the 0.35.1 tree was still at the active address.
161
+ That it stays there until the candidate verifies comes from the helper's source order
162
+ (write `installing`, acquire and verify in staging, then swap). The run observed only
163
+ the start of that window.
164
+ - Torn swap: a manually seeded one (the active tree moved to the backup address; not a
165
+ killed process or power loss) was restored before acquisition and reported
166
+ `recovered: torn-swap`.
167
+ - Re-request: an exact re-request acquired nothing and left journal and tree
168
+ byte-identical.
169
+ - Removal: the owned removal reclaimed cache, runtime and journal.
170
+ - Not certified by these cells: Herdr's install/update relocation, harness wiring, the
171
+ installed CLI's deactivate path, a model turn, or recovery from a real kill.
172
+ - Pending, and not claimed here:
173
+ - the pushed SHA's four-job CI, with the full `check-herdr-sandbox` and the qualification
174
+ body (971 mutants);
175
+ - the public-ref install/use/update/deactivate journey on Herdr 0.9.4, including whether
176
+ an activated runtime survives a plugin update.
177
+
178
+ ### Publication checkpoint
179
+
180
+ Recorded after the snapshot, as docs only; no Herdr plugin byte, manifest or pin changes with it.
181
+
182
+ - **Publication checkpoint for `v2026.10.14-herdr.0.36.0`, measured at its commit `9f33dd1`
183
+ before the snapshot was published.** The snapshot's push CI 38479767989 passed all four jobs
184
+ and the official exact-SHA oracle. Its check job verified the pinned x86_64 Herdr 0.9.4 digest
185
+ before execution; `check-herdr-sandbox` passed 12 assertions on private Herdr 0.9.4; the
186
+ qualification body killed 971/971. On Herdr 0.9.4 in a clean aarch64 container, the unchanged
187
+ `smoke-herdr-raw-install-live --ref main` passed at that commit. A driver-level journey then
188
+ went from the public `v2026.10.13-herdr.0.35.1` snapshot on Pi 1.1.0, through a pinned Pi
189
+ upgrade to 1.2.0, to a version-changing cross-ref reinstall of the 0.36.0 plugin (`herdr
190
+ plugin install … --ref main`) under a private Herdr server, and passed 10/10: wiring entries
191
+ unchanged; a session born before the reinstall kept its process, garden id and control socket;
192
+ a session was born after it; `herdr plugin update` at that same ref was only an
193
+ already-up-to-date no-op; and deactivate removed the owned runtime, cache, ledger and wiring
194
+ entries. On a fixed Pi 1.2.0 the 0.35.1 snapshot refuses by its own range: 0.35.1 and 0.36.0
195
+ accept disjoint Pi ranges. Not certified: a session's MCP or model continuity, `pi update
196
+ self`, a host upgrade, a `plugin update` that finds a new commit, a herdr-pane row, an x86_64
197
+ container, the tag as `--ref`, or when Herdr reclaims a retained previous installation. The
198
+ supply manifest's x86_64 `executed: false` remains the preparation-time declaration; flipping
199
+ it is a separate change.
200
+
201
+ ## 0.36.0 - 2026-10-13
202
+
203
+ ### pi-durable
204
+
205
+ - **The thin app/TUI composition is Entwurf-owned source (#141).** The six carrier files
206
+ are emitted from `pi/pi-durable/src/experimental/durable/*.ts` (with `src/LICENSE`), which
207
+ folds in the retired `runtime-contacts.patch`, and run on the 1.2.0 SDK set (below). Net
208
+ against 0.35.1, three carrier files change: `runtime.js` `60c2965e…118403`, `tui.js`
209
+ `0f9ebaf8…b3abc5` and `subagent.js` `1cb2390b…a64220`. `harness-setup.js`, `prompt.js`,
210
+ `sessions.js` and LICENSE keep their 0.35.1 bytes. The source checkpoint `86d4b65` left the
211
+ package version at 0.35.1; this release sets 0.36.0. The first step (S0) moved ownership
212
+ alone: no carrier byte, no LICENSE and no SDK version (then 1.1.0) changed, only the pin's
213
+ carrier source blob ids. The upstream SDK still owns
214
+ execution, auth, queues, storage/transcript, compaction, cancellation and recovery (Rule 17).
215
+ - **Pin schema 3.** `pi/pi-durable/overlay/upstream-pin.json` keeps its path and the shapes
216
+ installed readers use. A frozen `origin` holds the upstream commit, its recorded blobs, the
217
+ retired patch's digest and the 0.35.1 carrier digests. Only `carrier` is generated.
218
+ - **Emitter.** `scripts/emit-pi-durable-carrier.ts --check` reads only in-repo source, and a
219
+ missing file is a named refusal. A host running a different Node gets the byte proof plus a
220
+ named emitter-identity SKIP, not a PASS. `--write` names every generated field it changes.
221
+ `--origin <clone>` checks provenance only. The CI `check` job runs the pinned emitter Node
222
+ exactly, with `ENTWURF_REQUIRE_EMITTER_NODE=1`; other jobs float the major.
223
+ - **Typecheck fence.** `pi/pi-durable/tsconfig.json` is the fourth `pnpm typecheck` program:
224
+ strict, `erasableSyntaxOnly` / `verbatimModuleSyntax`, and `rootDirs` onto the installed
225
+ `pi-coding-agent/dist`, so internals are typed by their published declarations. Its explicit
226
+ empty `exclude` receives what the root program excludes. The exact devDependency
227
+ `@types/proper-lockfile@4.1.4` supplies the one missing declaration.
228
+ - **Formatting.** The owned source uses upstream width (indentWidth 3), with no per-file
229
+ exception. Formatting `tui.ts` wrapped its one Entwurf-written dock line and added one trailing
230
+ comma, so `tui.js` was re-emitted (sha256 `63600d4b…095b`, the S1-B1 intermediate; the S1-B3
231
+ changes below produce the current `0f9ebaf8…b3abc5`). A parser-derived token/AST
232
+ comparison found nothing else changed. The `PI-DURABLE-FOOTER-BADGE-PROTECTED` mutant follows
233
+ the wrapped line and plants the same fault.
234
+ - **Proof.** New claims: `PI-DURABLE-CARRIER-EMIT-SOURCE-EQUAL`, `-EMIT-NODE-EXACT`,
235
+ `PI-DURABLE-SOURCE-FENCE-RESOLVES`, `PI-DURABLE-SOURCE-NOT-SHIPPED` (the source, the fence and the
236
+ retired patch stay out of the JS-only tarball; proved on npm's own file list with
237
+ `--ignore-scripts` beside the carrier, while check-pack keeps the same tripwire on the floor), and
238
+ `PI-DURABLE-EMITTER-NODE-CI-BOUND` / `-CI-REQUIRED`. These two read the check job's active
239
+ setup-node input and its actual `check:full` step env, never comment text or another step.
240
+ Retired with the patch: `PI-DURABLE-CARRIER-PATCH-SECTIONS`.
241
+ - **SDK set 1.2.0 (#141 S1-B2).** The nine published `@earendil-works/*` production dependencies
242
+ move from 1.1.0 to 1.2.0, with the pin's `sdk.members`, the install constellation, the pin-leak
243
+ matcher and the declared ranges (`>=1.2.0 <1.3`). `pi-client` and `pi-protocol` leave the set (not
244
+ published at 1.2.0); the only new third-party package is `@silvia-odwyer/photon@0.3.3`.
245
+ - **1.2.0 tool output (#141 S1-B3).** On the 1.2.0 SDK set a native durable tool result's model
246
+ channel is `output`, which the SDK renamed from 1.1's `content`. When a result omits `output`, the
247
+ model gets the text the tool retained through `api.output()`. `content` is not read, so a result
248
+ naming only `content` that retained no output reaches the model as nothing. The subagent tool (now
249
+ `satisfies ToolExecutionResult`), the contact's bridge tools and the synthetic native-module
250
+ fixture retain none, so they answer in `output`. The ordinary Pi
251
+ `ToolExecutionComponent.updateResult` and `InputSubmissionDraft` keep `content`.
252
+ - **Fatal session.** The carrier runtime takes the Session's own close listener and the report that
253
+ follows it: a session that failed and closed itself is on screen at once (`Session failed: <cause>.
254
+ It takes no more input, and a tool still running may take a while to stop. Close this session,
255
+ then reopen it with --continue.`) and input to it is refused by name, without waiting for
256
+ `closed`, which a tool ignoring its abort can hold off. A normal `close()` unsubscribes first and
257
+ is no failure. A failure listener subscribed after the failure is told at once, once. On that
258
+ signal the contact retires its receiver as `session-failed` before the next doorbell — also when
259
+ the session had already failed before the contact attached, so no receiver marker is left behind;
260
+ a normal close still retires it as `closed`, and a cleanup failure is thrown, not swallowed.
261
+ - **Compaction failure.** The TUI draws the conversation's retained `pi.live.compactionFailure`
262
+ (`Compaction failed (<reason>): <error>`) for as long as the SDK keeps it. A failed background
263
+ compaction the SDK starts on its own (`threshold`) had no other report; the manual one keeps its
264
+ existing notice beside the line.
265
+ - **Proof (S1-B3).** New claims `PI-DURABLE-SUBAGENT-OUTPUT-MODEL-VISIBLE`,
266
+ `-BRIDGE-TOOL-OUTPUT-MODEL-VISIBLE`, `-FATAL-SESSION-VIEW`, `-FATAL-SESSION-SHOWN`,
267
+ `-FATAL-SUBMIT-REFUSED`, `-RECEIVER-RETIRE-ON-FATAL`, `-SELF-CLOSE-NOT-FAILURE` and
268
+ `-COMPACTION-FAILURE-SHOWN` run the real bootstrap and carrier on the published 1.2.0 SDK with a
269
+ faux model and an injected storage failure; each mutant plants its fault in the generated carrier
270
+ or the bridge source.
271
+
272
+ ### Codex
273
+
274
+ - **The 0.162.1 control endpoint is accepted as its exact alias (#141).** Codex 0.162.1 binds its
275
+ 0600 control socket under `realpath(/tmp)/codex-daemon-<euid>/`, named by the sha256 of the
276
+ canonical advertised path, and makes the advertised path a symlink to it. One classifier,
277
+ `checkCodexSocketFile`, accepts a plain socket or exactly that alias (link owner, byte-equal
278
+ target, a 0700 socket directory owned by the same euid, a socket no other user can open) and
279
+ refuses every other symlink. The delivery probe, `codex queue --remote` and the fresh-call
280
+ preflight connect to the socket it verified. The managed launcher runs the same classifier's
281
+ compiled twin (`mcp/entwurf-bridge/dist/scripts/codex-socket-classify.js`) and keeps no copy of
282
+ its own: a missing twin is an incomplete installation, refused as
283
+ `codex-app-server-classifier-missing` (reinstall the package, or run `pnpm run build-bridge` in
284
+ a source checkout), and an answer it does not recognise is refused by name. This is measured
285
+ on the 0.162.1 layout only and promises nothing about a later Codex. The plain-socket layout is
286
+ kept; its native acceptance remains the dated 0.153.4 record, not a claim about every older or
287
+ newer version.
288
+ - **Stated limits.** The launcher reports a dangling exact alias as the dead leftover the vendor
289
+ removes on start and launches over it, but its alias and dangling-alias paths have no LIVE
290
+ observation; they are proven on the classifier in a sandbox. The birth hook's thread naming,
291
+ the fresh Codex TUI's `--remote` endpoint and the fresh-call smoke's thread reads still hand the
292
+ advertised path to a connect without classifying it. Those connections worked in the named
293
+ diagnostic on this host; they remain unclassified. That is recorded as an Observation: not
294
+ every Codex connection goes through the classifier. A same-euid process can still replace the
295
+ verified socket file; that residual is named, not locked.
296
+
297
+ ### Docs
298
+
299
+ - **Open, reopen and message lead the one-line surfaces.** The README, FAQ, CONTRIBUTING,
300
+ AGENTS, the Herdr plugin README and manifest description, and the package description and
301
+ keywords name the three verbs and where each lands, instead of describing Entwurf as
302
+ garden-id messaging alone. The README gains an open/reopen/message table with each verb's
303
+ harness scope. FAQ's tmux list includes pi-durable again, and CONTRIBUTING no longer calls
304
+ the shipped Codex native-push citizen an unreleased candidate.
305
+
306
+ ### Release boundary and verification
307
+
308
+ - **Review.** The source checkpoint `86d4b65` and its amendment `d1c9103` were reviewed by
309
+ the #141 coordinator, Fable advisory reviews (no Blocker; their Defects were fixed before
310
+ the checkpoint) and a read-only Grok review of `86d4b65`. Grok's eight documentation and
311
+ live-authority findings were closed in `d1c9103`, and its recheck found no new Defect. The
312
+ Codex fix `90fa8bb` follows a coordinator-approved design with a read-only Grok design
313
+ review; a Fable advisory review of its pre-commit bytes found no Blocker, and its one Defect,
314
+ the missing Codex entry above, is closed in this section.
315
+ - **Local evidence before this preparation is focused, not a whole pass.** Each affected
316
+ qualification wave (PARTIAL) measured its own candidate and none is carried to another. S0
317
+ killed 70/70 in two groups; 891 of its 961 committed claims were not run. The S1-B3 source
318
+ bytes killed 82/82 in three groups (dep-versions 4, pin-matcher 2, pi-durable beside 76), each
319
+ with a green control; 887 of the 969 committed claims were not run there, nor was the
320
+ node-floor coherence group. The Codex fix bytes, verified content-identical to `90fa8bb`,
321
+ killed 219/219 in six groups (app-server launch 10, native push 8, admission parity 2,
322
+ attribution self-test 1, gate manifests 52, mux fresh call 146), each with a green control;
323
+ 752 of the 971 committed claims were not run. An earlier wave over that fix stopped at its
324
+ first group with 9 killed and one WRONG-REASON; it is kept as it was, not relabelled. The
325
+ vitest results cache drifting outside the dependency seal and one socket fixture temp root
326
+ observed during the native-push group are recorded, not waived. A fresh Entwurf-only npm
327
+ consumer of the `86d4b65` source bytes (packed with 0.35.1 metadata) proved graph and load
328
+ only: nine SDK members at 1.2.0, 24/24 carrier dist targets inside the consumer, and the
329
+ public launch reaching the SDK's own model refusal before any birth. A store migrated by a
330
+ 1.2.0 run and reopened on 1.1.0 kept its version-2 tool task blocked as `task_too_old`: a
331
+ one-time fixture receipt, not a supported downgrade.
332
+ - **Codex 0.162.1 diagnostic is not a cut.** On the pre-amendment candidate, one Linux
333
+ `smoke-codex-fresh-live` diagnostic against a live 0.162.1 app-server passed 65 assertions,
334
+ native push included, with `gpt-5.6-sol` on the Codex side and `openai-codex/gpt-6.1-sol` for
335
+ the Pi sibling only. It is not release-gate acceptance and covers no other model. The earlier
336
+ local FULL and LIVE `--cut` were taken on the pre-fix candidate (the cut was BLOCKED when the
337
+ advertised alias was refused) and are not evidence for this one. The frozen FULL and the final
338
+ LIVE `--cut` passed on this candidate (below); the installed-consumer proof
339
+ (`check-pack-install`, run by the CI `install-surface` job, not by `check:full`) and the
340
+ prepared SHA's CI body are pending.
341
+ - **Final frozen floor on this candidate.** One frozen tree, HEAD `90fa8bb` plus this release's
342
+ metadata, with the same work-surface fingerprint before and after both runs.
343
+ `pnpm run check:full` passed once (817 s, exit 0; 599 files in the dry-run pack).
344
+ `LIVE=1 ./run.sh release-gate <scratch> --cut` passed once: **MUST PASS=24 FAIL=0 SKIP=0**,
345
+ **BEHAVIOR PASS=1 FAIL=0 SKIP=0**, `cut: OK`. Its own static FULL (814 s) means this floor ran
346
+ FULL twice. The Codex step named the operator-owned 0.162.1 app-server by pid (851181) with
347
+ `gpt-5.6-sol` on the Codex side and `openai-codex/gpt-6.1-sol` for the Pi siblings, and passed
348
+ 65 assertions, native push included; it attaches to an existing server, so the managed
349
+ launcher's alias and dangling-alias paths remain unobserved. Scratch
350
+ `/tmp/entwurf-release-gate-0.36.0.lw5Xju`, log SHA-256
351
+ `17a2bd54efaaeba2899bf9bbd3c13c0e68749d9d03367347c4872d6f4126ad30`; FULL log SHA-256
352
+ `184ea443326a72858d25b70ba25b44e804307205586d8a03d4af7c5b07ee1288`. A read-only host census
353
+ afterwards found one `entwurf-chain-*` and one `smoke-pi-durable-fresh-live-*` root from this
354
+ run, the same per-run residue earlier LIVE runs left; it is recorded and was not cleaned. This
355
+ is local acceptance only: not the exact CI, not a whole qualification pass.
356
+ - **Exact CI pending.** The prepared SHA's exact CI (the four required jobs and the
357
+ qualification body) is the next checkpoint and is not presumed PASS.
358
+ - **Unpublished candidate carrier.** As in 0.35.1, `plugins/herdr/runtime-lock.json`
359
+ temporarily names the closed `herdr-checkout` source: an npm-source lock must agree with
360
+ the checkout's core version, and 0.36.0 has no published integrity yet. The Herdr
361
+ manifest stays 0.35.1. After the operator publishes core 0.36.0, a separate Herdr snapshot
362
+ re-pins the measured registry bytes.
363
+ - **Publication boundary.** No make artifact, core tag, GitHub Release or npm publication
364
+ is claimed; they wait for the exact CI, the make decision and the operator.
365
+
366
+ ## v2026.10.13-herdr.0.35.1 — Herdr Entwurf plugin 0.35.1
367
+
368
+ A separate Herdr plugin snapshot, not another core release: core package 0.35.1 and
369
+ its `v0.35.1` tag remain unchanged. The operator has published the core to npm.
370
+
371
+ ### Herdr plugin
372
+
373
+ - **Re-pin the published core 0.35.1 and close the checkout window.**
374
+ `plugins/herdr/runtime-lock.json` returns to production npm source
375
+ `@junghanacs/entwurf@0.35.1` with the registry's measured sha512
376
+ (`sha512-cZZaGfNP…EIchcQ==`). The plugin manifest moves 0.35.0 → 0.35.1;
377
+ admission remains Herdr >= 0.9.0 and the one-build/one-pane/Linux shape is unchanged.
378
+ - **The same core capability through Herdr.** The runtime this snapshot acquires carries
379
+ core 0.35.1: the Claude 5.5 curation with its set-model readback and the pi-durable inbox
380
+ repair (#140). The core release also adds an English, source-only checkout menu. The
381
+ plugin changes no rail, gate or mutant.
382
+ - **Upgrade by acquisition source, not just version.** A settled npm-source 0.35.0
383
+ installation can rebind under the plugin README's ownership conditions. A host that
384
+ installed the intervening `herdr-checkout` candidate must explicitly deactivate by
385
+ its own absolute runtime path before reinstalling the npm-source snapshot.
386
+ No operator installation or active session is rewired by this release work.
387
+
388
+ ### Source-specific verification
389
+
390
+ - Registry metadata reports version/latest 0.35.1, repair 0.12.8-repair.1. The downloaded
391
+ tarball is 11101943 bytes, SHA256
392
+ `6edbcf9fbf31a6df1aff04f34b28ac279a071917d13916410bf466fd33a44eae`, equal to the preserved
393
+ core release candidate. Independently computed sha512 equals `dist.integrity`;
394
+ the registry-shipped runtime helper is byte-equal to this checkout's.
395
+ - Required exact-registry-tarball Docker consumer passed without repacking. Real-npm
396
+ 0.35.0 → 0.35.1 swap and harness-seeded torn-swap recovery passed: the product restored
397
+ the last-good tree before reacquisition, certified the new registry digest, then
398
+ performed an exact-request no-op and owned-fixture removal. Seven focused
399
+ Herdr/manifest gates passed with HEAD, index and work surface unchanged.
400
+ `check-herdr-sandbox` was not run locally for this snapshot because it reads the
401
+ operator's own herdr panes; it rides the pushed SHA's FULL floor in CI.
402
+ - At preparation time, the public-ref install/use/deactivate/reinstall journey and the
403
+ pushed plugin SHA's ordinary four-job CI are still pending. Their actual outcomes belong
404
+ to the release checkpoint; this paragraph is not their acceptance. Earlier npm or
405
+ checkout-carrier receipts cannot certify these source-specific axes.
406
+ - Core 0.35.1's native Codex LIVE remains an explicit per-cut unmeasured exception, not a
407
+ PASS or a standing waiver. Its whole qualification body ran at the core release SHA;
408
+ this plugin-only metadata change does not borrow that body as its own.
409
+
7
410
  ## 0.35.1 - 2026-10-13
8
411
 
9
412
  ### ACP
package/CONTRIBUTING.md CHANGED
@@ -4,7 +4,7 @@ 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 + 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 is not on this rail at all — it is an unreleased native-push candidate with record birth and delivery-probe evidence (see AGENTS.md, DELIVERY.md), never ACP-managed — and Gemini is not a shipped backend. That is the entire ACP-rail scope.
7
+ `entwurf` opens and messages visible sibling sessions across independent harnesses, and reopens dormant pi siblings in tmux ([capability table](./README.md)), with the garden id as their address — entwurf-core (v2 dispatch) + a meta-bridge + a pi adapter + an **ACP plugin on a two-backend adapter rail**; 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 is not on this rail at all — it is a shipped native-push citizen that keeps its own vendor tools and work context (see AGENTS.md, DELIVERY.md), never ACP-managed — and Gemini is not a shipped backend. That is the entire ACP-rail scope.
8
8
 
9
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.
10
10
 
package/DELIVERY.md CHANGED
@@ -193,6 +193,21 @@ no daemon and no pid file: Ctrl-C is the operator's. A live socket, an unidentif
193
193
  second `--listen` are named refusals; a dead socket file is reported and launched over. Passing
194
194
  the raw vendor command by hand remains equivalent and is not deprecated.
195
195
 
196
+ **The control endpoint from Codex 0.162.1 (#141).** `[source rust-v0.162.1]` The advertised path is
197
+ now only an alias: the vendor binds a 0600 socket under `realpath(/tmp)/codex-daemon-<euid>/`, named
198
+ by the sha256 of the canonical advertised path, and symlinks the advertised path to it
199
+ (`app-server-transport/src/transport/unix_socket.rs:43-131, 290-304`; `uds/src/daemon_directory.rs:1-38`).
200
+ One classifier, `checkCodexSocketFile`, accepts exactly a plain socket or that exact alias — link
201
+ owner, byte-equal target, a 0700 socket directory, a socket no other user can open — and refuses
202
+ every other symlink. The delivery probe, `codex queue --remote` and the fresh-call preflight connect
203
+ to the socket it verified, never to the alias again. The launcher runs the same classifier's
204
+ compiled twin (`mcp/entwurf-bridge/dist/scripts/codex-socket-classify.js`) directly, refuses any
205
+ answer it does not recognise, and reports a dangling exact alias as the dead leftover the vendor
206
+ removes on start. A same-euid process can still replace the verified socket file; that residual is
207
+ named, not locked. The alias layout is certified on the classifier in a sandbox; the 0.162.1
208
+ app-server protocol itself requires a named LIVE observation; a diagnostic is not release-cut
209
+ acceptance, which separately requires the official release gate.
210
+
196
211
  #95 D1 (GLG, 2026-09-16) retired the requirement that this session be named `codex`, and with it the
197
212
  rule that an omitted-placement Codex TARGET selected it. The operator still owns the app-server and
198
213
  still chooses its room; Entwurf neither creates nor supervises it, and a missing app-server rejects.
@@ -489,6 +504,8 @@ ENTWURF_CODEX_FRESH_PI_MODEL=<pi-model> \
489
504
  ./run.sh smoke-codex-fresh-live
490
505
  ```
491
506
 
507
+ The gate reads that ownership from the kernel, not from argv (#128). It takes the endpoint `checkCodexSocketFile` verified, finds its one LISTEN row in the named process's own socket table, and requires exactly one process in the named PID's own subtree to hold that inode — and still hold it on a bounded second read of that holder's fds, with every walked pid's parent and start time unchanged and the named PID still the process whose uid, argv and environment were checked (`scripts/lib/codex-socket-listener.ts`). A wrapper whose child listens (the pnpm `codex.js` shape measured at the 0.36.0 cut) and a listener started with the vendor-default `--listen unix://` are both read as what they are; a subtree that holds no fd on the inode is not-owned, and zero or several rows, several holders, an unreadable entry, or a pid, parent, fd or row that moved between reads is indeterminate. Either is a FAIL. A positive is only this ownership fact: it does not admit a vendor-managed daemon as an operator shape, and it does not satisfy the separate A ≠ S seat precondition.
508
+
492
509
  This is the intended gate entrypoint, not acceptance by command name. The accepted receipt above
493
510
  has a fixture only collecting evidence: a real visible record-backed Pi opens Codex from outside the
494
511
  home, and the later exact callback and bidirectional delivery receipts close the topology claim.
package/FAQ.md CHANGED
@@ -8,7 +8,7 @@ No. Entwurf is closer to a workshop than a factory: it connects independently ow
8
8
 
9
9
  ## What does Entwurf do?
10
10
 
11
- It gives an existing session a stable **garden id** and routes a message, reply, or visible sibling launch through the rail that session actually supports. It does not reconstruct prompts, hydrate transcripts, manage credentials, or emulate another harness.
11
+ It opens, reopens and messages visible sibling sessions across independent harnesses, each under a stable **garden id**. `entwurf_fresh_call` opens a new sibling in the caller's Herdr workspace or tmux session by default, `entwurf_resume_call` reopens a dormant pi sibling under the same id, and `entwurf_v2` delivers a message, reply or hand-off to an existing one through the rail it actually supports. It does not reconstruct prompts, hydrate transcripts, manage credentials, or emulate another harness.
12
12
 
13
13
  ## What is a garden id?
14
14
 
@@ -28,11 +28,11 @@ No. [`entwurf_v2`](./README.md#entwurf_v2--canonical-dispatch-verb) only address
28
28
 
29
29
  ## Where do visible siblings open?
30
30
 
31
- Inside Herdr, Entwurf opens a new unfocused tab in the caller's workspace and currently admits pi and Claude Code. Outside Herdr, it opens one of the fixed pi, Claude Code, Copilot, OMP, or Codex runtimes in a visible tmux window. The runtime keeps its own model, tools, authentication, and transcript.
31
+ Inside Herdr, Entwurf opens a new unfocused tab in the caller's workspace and currently admits pi and Claude Code. Outside Herdr, it opens one of the fixed pi, pi-durable, Claude Code, Copilot, OMP, or Codex runtimes in a new window of the caller's tmux session, or of an existing session the caller names; without an explicit tmux placement, a Codex caller opens beside its own TUI pane. A dormant pi sibling reopens under the same id in a visible tmux window. The runtime keeps its own model, tools, authentication, and transcript.
32
32
 
33
33
  ## Does Entwurf replace Herdr or tmux?
34
34
 
35
- No. Herdr and tmux provide visible seats. Entwurf provides identity, delivery, and receipts across independent harness sessions. A pane or tmux session is a location for a sibling, never its address or liveness proof.
35
+ No. Herdr and tmux provide visible seats. Entwurf opens siblings into them, reopens dormant pi siblings, and carries identity, delivery, and receipts across independent harness sessions. A pane or tmux session is a location for a sibling, never its address or liveness proof.
36
36
 
37
37
  ## How do I install it?
38
38
 
package/README.md CHANGED
@@ -1,10 +1,12 @@
1
1
  # entwurf
2
2
 
3
- `entwurf` is a garden-citizen dispatch substrate: a thin bridge that lets independent
4
- agent harnesses address one another by **garden id**, without owning each other's
5
- transcript, authentication, tools, or runtime.
3
+ `entwurf` connects independent agent harnesses as visible siblings: open a new session,
4
+ reopen a dormant pi session in tmux, or reach an existing sibling by **garden id**. Fresh
5
+ sessions open in the caller's Herdr workspace or tmux session by default; explicit tmux
6
+ placement can name another existing session. Each harness keeps its own runtime,
7
+ authentication, tools and transcript.
6
8
 
7
- ![entwurf — a forged screwdriver for garden-citizen dispatch](docs/assets/entwurf-hero.jpg)
9
+ ![entwurf — a forged screwdriver for visible sibling sessions](docs/assets/entwurf-hero.jpg)
8
10
 
9
11
  **Pi ↔ native Claude Code inside the [Herdr workbench](#herdr-workbench).**
10
12
  A recorded source-checkout demo: callback → task → native Bash → reply.
@@ -21,12 +23,15 @@ receipts and named lifecycle verbs; the operator and native harnesses keep steer
21
23
  Git branches, worktrees, file isolation and internal delegation remain their concern.
22
24
  [Short answers: FAQ](./FAQ.md).
23
25
 
24
- ```text
25
- pi / pi-durable / Claude Code / Copilot / OMP / Antigravity / Codex
26
- → record-backed garden id
27
- → entwurf_v2
28
- → control-socket | self-fetch mailbox | native-push
29
- ```
26
+ | Verb | Tool | Where it lands | Harnesses |
27
+ |---|---|---|---|
28
+ | **Open** a new sibling | `entwurf_fresh_call` | Herdr: a new unfocused tab in the caller's workspace. tmux: a new window in the caller's session, or an existing session named by `placement.tmuxSession`; without an explicit tmux placement, a Codex caller opens beside its own TUI pane | Herdr: pi, Claude Code. tmux: pi, pi-durable, Claude Code, Copilot, OMP, Codex |
29
+ | **Reopen** a dormant sibling | `entwurf_resume_call` | A visible tmux window under the same garden id, with the transcript, model, provider and cwd its record names; no turn is run | pi |
30
+ | **Message** an existing sibling | `entwurf_v2` | Its own rail: control socket, self-fetch mailbox or native push; delivery starts no process | pi, pi-durable, Claude Code, Copilot, OMP, Antigravity, Codex |
31
+
32
+ Antigravity is message-only: an existing conversation registers itself, and Entwurf never
33
+ launches one. A launch receipt is neither the new sibling's address nor proof that it
34
+ processed its task; the sibling's own callback envelope supplies its garden id.
30
35
 
31
36
  The package holds the v2 core, native-harness bridges, a pi adapter and an ACP
32
37
  plugin. ACP is one ingress, not the boundary; pi is one adapter, not the center.
@@ -40,14 +45,15 @@ receipts; [CHANGELOG](./CHANGELOG.md) records source history.
40
45
  ## Install
41
46
 
42
47
  **Choose by where you work. Bring your own harnesses, subscriptions and login.**
43
- The native durable route below additionally supplies the upstream app/TUI missing from its npm
44
- release; it does not supply credentials or take ownership of the harness.
48
+ The native durable route below additionally supplies an app/TUI, Entwurf's own thin composition of
49
+ the durable app upstream omits from its npm release; it does not supply credentials or take
50
+ ownership of the harness.
45
51
 
46
52
  ### Direct — ordinary shell or tmux
47
53
 
48
54
  Prerequisites: **Node >=24.0.0**, Python 3 for `setup`, and any harnesses you choose
49
55
  to use, already installed and authenticated. Pi is optional-by-presence, supported
50
- range `>=1.1.0 <1.2`; Claude Code supported floor `>=2.1.217` is required for its
56
+ range `>=1.2.0 <1.3`; Claude Code supported floor `>=2.1.217` is required for its
51
57
  managed exec-hook lifecycle. pnpm is needed only for source-checkout setup.
52
58
 
53
59
  ```bash
@@ -77,7 +83,7 @@ restriction; that is not certification of every platform's harness rails.
77
83
 
78
84
  ### Native durable (pi-durable)
79
85
 
80
- **The package supplies the pinned upstream app/TUI and nine exact Pi 1.1.0 SDK
86
+ **The package supplies Entwurf's owned app/TUI carrier and nine exact Pi 1.2.0 SDK
81
87
  members.** No separate runtime checkout, patch, build or ordinary Pi CLI is needed.
82
88
  The launch verifies carrier integrity and every reachable SDK edge's name/version;
83
89
  incomplete, drifted or mixed supply refuses by name.
@@ -87,8 +93,9 @@ entwurf pi-durable --provider <provider> --model <model-id> --width task-wide
87
93
  entwurf pi-durable --continue
88
94
  ```
89
95
 
90
- The contact adds garden identity and two-way mailbox communication. Runtime/TUI,
91
- models/auth, queues, SQLite, transcripts and recovery remain upstream-owned:
96
+ The contact adds garden identity and two-way mailbox communication. Entwurf owns the
97
+ thin app/TUI composition (shipped as an emitted JS carrier); execution, models/auth, queues,
98
+ SQLite, transcripts and recovery remain the upstream SDK's:
92
99
  [Hard Rule 17](./AGENTS.md#hard-rules), **supply the missing surface; do not become the harness**.
93
100
 
94
101
  Optional `--native-module <absolute file>` initializes trusted ESM before runtime/TUI
@@ -161,6 +168,13 @@ Liveness is read at dispatch time; an id's shape does not tell you its transport
161
168
 
162
169
  ### `entwurf_v2` — canonical dispatch verb
163
170
 
171
+ ```text
172
+ pi / pi-durable / Claude Code / Copilot / OMP / Antigravity / Codex
173
+ → record-backed garden id
174
+ → entwurf_v2
175
+ → control-socket | self-fetch mailbox | native-push
176
+ ```
177
+
164
178
  | What you want | Tool | What its receipt means |
165
179
  |---|---|---|
166
180
  | Message, reply or hand off to an existing garden id | `entwurf_v2 {target, intent:"fire-and-forget", message}` | Receiver acceptance boundary, mailbox enqueue or native injection; not completion |