@junghanacs/entwurf 0.30.0 → 0.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/AGENTS.md +1 -0
  2. package/CHANGELOG.md +229 -0
  3. package/DELIVERY.md +1 -0
  4. package/README.md +49 -4
  5. package/VERIFY.md +23 -4
  6. package/demo/README.md +1 -1
  7. package/docs/acp-backend-rail.md +111 -18
  8. package/docs/setup-clean-host.md +104 -4
  9. package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +7 -7
  10. package/mcp/entwurf-bridge/dist/pi-extensions/entwurf-capabilities.json +1 -0
  11. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/backend-adapter.js +43 -0
  12. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-deliverability.js +7 -1
  13. package/mcp/entwurf-bridge/dist/pi-extensions/lib/fresh-call-composition.js +34 -3
  14. package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-sender-identity.js +7 -1
  15. package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-session.js +28 -2
  16. package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +30 -2
  17. package/mcp/entwurf-bridge/dist/pi-extensions/lib/pi-durable-fresh-preflight.js +92 -0
  18. package/mcp/entwurf-bridge/dist/pi-extensions/lib/pi-durable-runtime.js +288 -0
  19. package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-pi-durable.js +744 -0
  20. package/mcp/entwurf-bridge/src/index.ts +7 -7
  21. package/mcp/entwurf-bridge/tsconfig.build.json +8 -1
  22. package/package.json +15 -12
  23. package/pi/entwurf-capabilities.json +1 -0
  24. package/pi/pi-durable/bootstrap.mjs +281 -0
  25. package/pi/pi-durable/overlay/runtime-contacts.patch +91 -0
  26. package/pi/pi-durable/overlay/upstream-pin.json +16 -0
  27. package/pi-extensions/lib/acp/backend-adapter.ts +68 -0
  28. package/pi-extensions/lib/acp/backend.ts +41 -5
  29. package/pi-extensions/lib/entwurf-deliverability.ts +7 -1
  30. package/pi-extensions/lib/fresh-call-composition.ts +42 -7
  31. package/pi-extensions/lib/meta-sender-identity.ts +7 -1
  32. package/pi-extensions/lib/meta-session.ts +28 -2
  33. package/pi-extensions/lib/mux-fresh-call.ts +34 -2
  34. package/pi-extensions/lib/pi-durable-fresh-preflight.ts +113 -0
  35. package/pi-extensions/lib/pi-durable-runtime.ts +384 -0
  36. package/pi-extensions/meta-bridge-pi-durable.ts +1020 -0
  37. package/run.sh +214 -36
  38. package/scripts/check-fresh-call-dispatch.ts +18 -0
  39. package/scripts/check-gate-qualification.ts +4 -2
  40. package/scripts/check-herdr-plugin-build.ts +159 -57
  41. package/scripts/check-pi-durable-contact.ts +834 -0
  42. package/scripts/check-pi-durable-receive.ts +1116 -0
  43. package/scripts/check-pi-durable-send.ts +1661 -0
  44. package/scripts/fixtures/herdr-supply.json +8 -8
  45. package/scripts/lib/pi-durable-fresh-live-receipts.ts +139 -0
  46. package/scripts/lib/pi-durable-r1.ts +100 -0
  47. package/scripts/lib/pi-durable-reap.ts +27 -0
  48. package/scripts/lib/pi-durable-receive.ts +137 -0
  49. package/scripts/mutants/acp-prompt-lifecycle.json +2 -2
  50. package/scripts/mutants/acp-vendor-rejection.json +62 -0
  51. package/scripts/mutants/control-send-receipt.json +1 -1
  52. package/scripts/mutants/copilot-birth.json +2 -2
  53. package/scripts/mutants/herdr-plugin-build.json +11 -0
  54. package/scripts/mutants/herdr-supply.json +3 -3
  55. package/scripts/mutants/meta-hook-session-switch.json +4 -2
  56. package/scripts/mutants/mux-fresh-call.json +69 -3
  57. package/scripts/mutants/omp-birth.json +2 -2
  58. package/scripts/mutants/omp-fresh.json +6 -4
  59. package/scripts/mutants/pack-install.json +3 -3
  60. package/scripts/mutants/pi-durable.json +390 -0
  61. package/scripts/mutants/pi-floor.json +2 -2
  62. package/scripts/pi-durable-contact-host.mjs +105 -0
  63. package/scripts/pi-durable-receive-host.mjs +127 -0
  64. package/scripts/pi-durable-send-host.mjs +213 -0
  65. package/scripts/smoke-acp-raw-turn-live.ts +1 -1
  66. package/scripts/smoke-herdr-fresh-call-live.ts +21 -7
  67. package/scripts/smoke-pi-durable-fresh-live.ts +624 -0
  68. package/scripts/smoke-setup-verdict.sh +21 -2
  69. package/scripts/tsconfig.json +1 -0
package/AGENTS.md CHANGED
@@ -100,6 +100,7 @@ implement → affected focused gates → independent review → one amendment bu
100
100
  ## Type and Working Boundaries
101
101
 
102
102
  - Each `.ts` file belongs to one declared typecheck fence; `exclude` may move a file between fences but never out of all of them, so an exclude states the receiving `include` in the same change. Root pi extensions use TypeBox through `@earendil-works/pi-ai`; MCP/scripts use explicit `.ts` imports required by Node strip-types. Installed surfaces route to compiled JS. Behavior-adjacent `.test.ts` takes the fence `test/` takes — `scripts/tsconfig.json`, never the emit-capable root program — and is kept out of the tarball by a files-array negation whose tripwire is `check-pack`.
103
+ - Develop only on branches in this repository checkout; never use worktrees or tmp development clones. Isolated test fixtures and temporary evidence are not development checkouts.
103
104
  - Make surgical, one-contract changes. Removal repairs source and its proof together; a green gate never proves retired behavior.
104
105
  - Before commit, sweep repository-wide for retired authority vocabulary and landed-plan future tense. Historical tombstones may remain; live docs, source, gates, and usage must agree.
105
106
  - Prefer capability-domain language over identity rank. Use tabs unless the project formatter requires otherwise. GLG decides commit, push, and release gates.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,235 @@ All notable changes to this project will be documented here. Format follows [Kee
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## 0.31.0 - 2026-10-07
8
+
9
+ ### Added
10
+
11
+ - **Native durable contact (`pi-durable`, #129).**
12
+ Treat the experimental durable coding app as a separate native harness. One
13
+ native host attaches to one V3 garden id; the contact adds visible garden
14
+ identity, self/peers, canonical outbound dispatch and announce-only root-directed
15
+ mailbox receive with explicit inbox read. Runtime, TUI, model/auth, SQLite
16
+ storage, transcript and recovery remain upstream-owned. Internal subagents do
17
+ not mint another citizen. Native recovery is not exactly-once Entwurf delivery.
18
+
19
+ ### Installation
20
+
21
+ - **Entwurf's npm/source installation route stays unchanged.** Optional native
22
+ durable use additionally requires an operator-provided pinned upstream source
23
+ runtime and the narrow runtime-contact overlay (Pi 1.0.2/source `cd32f77` in this
24
+ lane). The `@earendil-works/pi-durable` **library** is npm-installable; the
25
+ experimental coding app/TUI is not supplied by the ordinary Pi npm package.
26
+ Entwurf does not install a harness or copy credentials. Existing non-durable
27
+ users do not need a source checkout. [Native durable setup boundary](docs/setup-clean-host.md#2b-optional-native-durable-pi-durable).
28
+
29
+ ### Changed
30
+
31
+ - **Pi dependency/runtime floor is 1.0.2**, with pi peer range `>=1.0.2 <1.1`.
32
+ Native durable pins upstream source `cd32f77` and its narrow contact overlay;
33
+ no upgrade to a newer experimental app or replacement runtime is included.
34
+ - **Source workspace discovery is root-only.** Explicit `packages: ['.']` keeps
35
+ pnpm's workspace scan coherent with the root install, without disabling its
36
+ dependency verification. Prepack still runs the foreground build lifecycle,
37
+ with build output on stderr so pack JSON stays readable and failures propagate.
38
+
39
+ ### Verification
40
+
41
+ - **Reviewed pre-version main:** product `165338e` and native-admission `535c2e1`
42
+ landed separately with normal hooks/shared safety scans. The final landing's
43
+ [exact-SHA CI](https://github.com/junghan0611/entwurf/actions/runs/37478003145)
44
+ at `535c2e1b63e6a66c45227e197de80bf261202aec` passed all four required jobs
45
+ and the qualification BODY **872/872 KILLED**, including the new foreign-sender
46
+ guard4.5s KILLED against subject `7bdea2c4c664…`. Implementation issue #129 is closed; #130 owns
47
+ npm-only runtime supply, Pi upgrades, ACP and UI follow-ups. This main receipt
48
+ is not the later prepared-commit or preserved-artifact acceptance.
49
+ - **Native first admission:** corrected real Pi → pi-durable → Pi LIVE36
50
+ passed in41s on `openai-codex/gpt-6.1-sol`, task-wide native5 + contact6 offering.
51
+ A consistent official SQLite backup establishes first callback, own-id inbox
52
+ read, joined successful native dispatch and the exact root doorbell reaching done.
53
+ Pi transcript row19 carries the exact expected payload and authoritative durable
54
+ sender. Native V evidence is distinct from checkout contact95/send19/receive21
55
+ scripted S + native H and installed-bootstrap import-only proof.
56
+ - **Receipt-oracle repair is portable and independently reviewed.** Exact payload,
57
+ terminal sender envelope, root scope, effective offering, call/result and doorbell
58
+ joins replace substring/union predicates. Eight inline tests and the existing mux
59
+ coordinate carry a foreign-sender guard mutant. The original35-GREEN predicate
60
+ selected fixture row15; real old-row19 delivery was independently present. Old raw,
61
+ wrong receipt and RED857/870 remain preserved, never relabelled new acceptance.
62
+ Native admission raw: `.tmp-verify/b9ffcb-pack-cause/live-pd-20261006T223708/`.
63
+ - **Versioned working-candidate P4:** FULL666s/exit0, HEAD/index/tracked work-surface
64
+ and binary diff frozen MATCH; pack dry-run580files. The pre-verdict release-metadata
65
+ patch/bytes are preserved in `.tmp-verify/031-release/prepare/p4/`, snapshot SHA
66
+ `2529949384af40c6ca15f65575638b97980817cb85d7a68bb81e9ff1b34c8fa7`, full-log SHA
67
+ `57da80e9e32159f8bc966381a2756d6a34cca647dd5ee5791ee681ed3509b0df`.
68
+ This floor used the exact private Herdr0.9.3 aarch64 supply pin; operator0.9.1 stayed
69
+ unchanged. No qualification BODY or native LIVE was executed in this P4 run.
70
+ - **Explicit agy criterion7 exception for this0.31.0 cut, confirmed by GLG
71
+ (2026-10-07):** “agy 예외. 0.30.1부터 그렇게 헀어 더 진행가자” permits continuing
72
+ prepare/make while agy1.2 remains **NOT CERTIFIED**. The historical1.1 pin and
73
+ DELIVERY certification row stay unchanged; #128 remains first-party own-context
74
+ prerequisite research. No nonce/credential extraction, old-CID replay, transport
75
+ implementation, permanent floor change or npm publication is authorized by this
76
+ exception. Other release axes remain mandatory.
77
+ - **Fresh native Claude host:** owned writer/registry refresh corrected the stale
78
+ deployed v3 bytes before P5. Source=assembled=installed writer `c8f05d394d0e`,
79
+ capability registry `2f95e94f1eb9`; strict doctor exits0 with four live owner joins.
80
+ A new Claude2.1.291 session after install, garden `20261007T024544-c71062`,
81
+ ownerPID2784041/startKey `linux:304383485`, bridge child2784080, joins sender,
82
+ receiver and V3 record with no model turn. `prepare/claude-native-cert/accepted.json`
83
+ retains the exact metadata. This is checkout-provenance certification, not an
84
+ installed emitted-JS/bin-shim, registry, model-turn or fresh delivery/reply receipt.
85
+ - **First P5 and scoped repair remain distinct.** The frozen candidate's first
86
+ `--cut` run ended RED: MUST23/2/0, BEHAVIOR1/0/0, qualification872/872 KILLED,
87
+ HEAD/index/tracked bytes MATCH. Log `/tmp/entwurf-release-gate-0.31.0.JdQ4q6/release-gate.log`.
88
+ The owned OMP receiver's stale writer was refreshed through its installer; strict
89
+ runtime/ownership doctor and fresh receive LIVE11 passed. Initial Pi's Codex relay
90
+ added one trailing newline; the exact source oracle rejected it. A fresh chain on
91
+ the unchanged candidate passed65 assertions, source audits Pi3/3 + Codex3/3, with
92
+ no oracle relaxation or old-CID replay. The owed on-demand seat×cwd fresh-call
93
+ matrix passed39. `prepare/p5-focused-1/accepted.json` retains those focused receipts;
94
+ they do not turn the original aggregate RED into GREEN. Immediate P9 was report-only,
95
+ five eligible roots312K after P5 and six328K after the focused bundle; protected
96
+ Emacs was the only reparented `/tmp` process, with no deletion or signal.
97
+ - **Final fresh P5 cut verdict:** `LIVE=1 ./run.sh release-gate
98
+ /tmp/entwurf-release-gate-0.31.0.Xzbk2b --cut` exited0 after110m15s:
99
+ **MUST PASS=25 FAIL=0 SKIP=0**, **BEHAVIOR PASS=1 FAIL=0 SKIP=0**, its own
100
+ FULL and qualification **872/872 KILLED**, frozen HEAD/index/tracked bytes MATCH.
101
+ Log SHA256 `609612baff850ec06fc74321002b33a6b71d3dabc76874dc1546b8722c317bf2`;
102
+ snapshot SHA256 `38c49ca5123ffc9883762d637084dba9ed77adbdd5f3e86287a1ace565f763de`.
103
+ `prepare/p5-final/accepted.json` retains the boundary; native durable raw is
104
+ `/tmp/smoke-pi-durable-fresh-live-2026-10-06T23-27-34-983Z`. Immediate P9 reported
105
+ unused198/eligible6/328K, protected Emacs only; no deletion/signal.
106
+ - **Fresh-eyes documentation alignment:** independent Grok review found one
107
+ underclaim bundle, not a false green: operator docs still called accepted native
108
+ admission pending and a direction note pointed to a retired branch handoff.
109
+ After the final P5 verdict, documentation-only commit `87de9f7` aligns those states
110
+ with DELIVERY/#129 and distinguishes seven citizen backends from six fresh-openable
111
+ ones. Bounded independent re-review closed the Defect (Blocker0/Defect0); normal
112
+ hooks/shared scanner passed, and main fast-forwarded locally before release-prep. Executable/gate/model/pin/manifest bytes are unchanged; no LIVE Claude ↔
113
+ durable or registry/runtime provision is inferred. Review artifacts live in
114
+ `.tmp-verify/031-release/grok-fresh-review/` and `docs-amendment/`.
115
+ - **Release acceptance is pending:** prep commit/prepared-SHA CI and preserved
116
+ artifact remain outstanding. No final candidate, tag, GitHub release or npm
117
+ publication is asserted here.
118
+
119
+ ## 0.30.1 - 2026-10-04
120
+
121
+ ### Fixed
122
+
123
+ - **Claude incomplete foreground-tool failures no longer invite a whole-prompt replay (#127).**
124
+ Only a non-aborted prompt rejection decoded as the root ACP SDK's `RequestError`, code
125
+ `-32603`, vendor `errorKind: incomplete_tool_call`, receives an authored unsafe-to-replay
126
+ verdict. Some tools may already have run. The original rejection and stderr/lifecycle/launch
127
+ evidence stay in existing diagnostics rather than tainting pi's retry/overflow classifier.
128
+ FIRST failure, abort precedence, exactly one error seal, and new/reuse session drop remain;
129
+ other failures and Cortex retain their legacy paths. This is not a global retry disable or
130
+ a claim about vendor-internal retries or real incomplete-tool frequency.
131
+ - **Herdr's existing plugin/runtime consumption boundary is aligned (#126).** The follow-up to
132
+ 0.30.0 aligned the plugin manifest with its locked runtime, re-pinned the published npm bytes,
133
+ and measured Herdr 0.9.3 supply against the unchanged 0.9.0 admission floor. Sandbox path
134
+ normalization and the Pi-native callback oracle were corrected. Operating Herdr/config stayed
135
+ unchanged; no permanent plugin/package equality policy was introduced.
136
+ - **Herdr build verification covers both carriers and the real default lock reader.** Explicit
137
+ npm and checkout fixtures assert exact sequential acquisition counts and final artifact identity.
138
+ The uninjected default reader is checked against an independent committed JSON oracle, with a
139
+ dedicated wrong-directory mutant. This changes proof, not the production build/runtime/activation.
140
+ - **Published support, source observations and execution evidence stay distinct (#127).** The
141
+ ACP rail and dependency ledger separate conditional settings, capability-gated and ambient
142
+ changes from runtime certification, stock auth messages from sealed legacy stderr tails,
143
+ upstream comments from unread SDK internals, and native/platform/loader contexts. The typed
144
+ rejection row points only to its deterministic gate: normal raw/reuse LIVE turns do not induce
145
+ that rejection.
146
+
147
+ ### Changed
148
+
149
+ - **Claude ACP closure:** adapter `0.79.0` → `0.85.1`, shared direct/child ACP wire SDK `1.4.0` →
150
+ `1.6.0`, Agent SDK `0.3.274` → `0.3.286`; the existing shared-wire contract is retained.
151
+ New reachable upstream behaviour is classified in the ACP rail and ROADMAP ledger, not
152
+ silently adopted as new Entwurf policy. Pi 1.0's range and public bridge verbs are unchanged.
153
+ - **Unpublished Herdr verification candidate:** plugin metadata is 0.30.1 and uses the closed `herdr-checkout`
154
+ verification carrier while 0.30.1 is unpublished. No npm integrity is fabricated. After
155
+ publication, re-pin only the measured registry artifact and re-prove that acquisition source;
156
+ switching an installed source still requires explicit deactivate/activate.
157
+
158
+ ### Verification
159
+
160
+ - Implementation/source review, related MUST LIVE and pre-version landing receipts are in
161
+ [#127](https://github.com/junghan0611/entwurf/issues/127), with #126's Herdr acceptance separate.
162
+ Main landing `f24820c` passed required four CI jobs, full411s and qualification841/841.
163
+ These are pre-version receipts, not this release's exact-SHA acceptance.
164
+ - The gate-only amendment landed separately at `61dbef7`: independent review closed with
165
+ zero Blockers/Defects; the frozen 0.30.0 source passed local qualification **842/842** and
166
+ full645s. Its [exact-SHA CI](https://github.com/junghan0611/entwurf/actions/runs/37181269379)
167
+ passed all four required jobs, full361s and qualification842/842. These are pre-version
168
+ implementation receipts, not 0.30.1 release acceptance. The original npm-only/version-pinned
169
+ HPB failure, old wrong-directory mutant survival, inventory RED, PARTIAL13/13 and PARTIAL14/14
170
+ receipts remain separate history; offline four positive/two negative controls are not registry
171
+ proof (`~/tmp/e0301-prepare/gate-fix/implementation-floor/`).
172
+ - **Fresh 0.30.1 working-candidate floor:** P4 full641s, followed by
173
+ `LIVE=1 ./run.sh release-gate /tmp/entwurf-release-gate-0.30.1.SLE9uA --cut`:
174
+ **MUST PASS=24 FAIL=0 SKIP=0**, **BEHAVIOR PASS=1 FAIL=0 SKIP=0**, exit0/cutOK;
175
+ its own full645s and qualification **842/842** passed. The versioned candidate on
176
+ `61dbef7` stayed frozen through both runs (seal
177
+ `541cc5a368315e6ecac4548a3492ce73024c6fe9dc5613077e14898d4fd76879`).
178
+ Complete log: `/tmp/entwurf-release-gate-0.30.1.SLE9uA/release-gate.log`, SHA256
179
+ `ea070c2ea019c05766e40e3442d1a31d68894e6cb3da7f7bbb80460c782bc020`.
180
+ - **Native Codex caller-seat acceptance:** 65 assertions, native `gpt-5.6-luna` and
181
+ Pi `openai-codex/gpt-6-luna`; personally launched app-server PID2143836 in session
182
+ A `$309` and initial Pi/fresh Codex/outbound Pi all in S `$316`, windows
183
+ `@810/@811/@812`. The outbound receipt names `codex-title-anchor`; both exact
184
+ source-role audits completed3/3. The complete pre-cleanup evidence is retained at
185
+ `.probe-artifacts/codex-fresh-live-fypXrI/`; decoded decisive receipts accompany
186
+ `~/tmp/e0301-prepare/fresh-prepare/p5-accepted.json`.
187
+ - **On-demand long-turn:** Sonnet5 completed the original three sequential240s
188
+ foreground waits in736147ms, with exactly one cold ACP bootstrap and no reported
189
+ retry/timeout; the same candidate seal remained MATCH. This normal-turn receipt does
190
+ not induce `incomplete_tool_call` or certify vendor-internal retry frequency.
191
+ - **Immediate P9:** census113 unused roots, four owned/aged/unused roots444K and one
192
+ reparented GLG Emacs daemon. All four roots were archived before four-fence-checked
193
+ reclamation; no process was killed. Post-census reports110 unused/zero reclaimable
194
+ roots, with Emacs untouched. Archive SHA256
195
+ `3132ab92d26702a5b1e3ddf9298e7e77c6abe63c276625ac2cd93b12558ad19a`;
196
+ per-root fences and before/after observations are in
197
+ `~/tmp/e0301-prepare/fresh-prepare/p9-reclaim/receipt.json`.
198
+ - **Claude checkout-provenance certification of the candidate tree:** the local
199
+ owner-managed installer was refreshed from this working0.30.1 checkout, then a NEW
200
+ native Claude2.1.289 session was opened without sending a prompt. Install finished
201
+ `2026-10-04T10:20:16.328Z`; fresh garden `20261004T192019-c50e8a` was created at
202
+ `10:20:19.625Z`. Exact launched PID3397500/startKey `linux:284430975` joins both
203
+ markers, its unique V3 record and registered bridge child3397563. Registry-authoritative
204
+ cached plugin0.1.0 and stable XDG assembly match the checkout's hook/writer/session-id/
205
+ registry bytes; plugin0.1.0 is not the root package version. Strict doctor exit0:
206
+ three live owner joins, source=assembled=installed writer `8558bb3a5aa8`, registry
207
+ `277c8dc2a183`, store v1=0/v2=0/v3=1476, PASS. The targeted leaf completed27s;
208
+ **full/BODY/P5 reruns=0**, leaf seal
209
+ `1f754eeb12ff800b2d7c1122d2b8fad030c9311e1784aab67166916ad3eb5364` MATCH.
210
+ Receipt `~/tmp/e0301-prepare/fresh-prepare/criterion4.json` SHA256
211
+ `0af3edc3d913eae2157d8229f7408c670f47b8bdd6363ff8e1f1c8a51e2b1fe6`;
212
+ doctor log SHA256 `6922043ddb500c34edaba5f70115d910cbdbfe7a1d01f8ff9ab28f2b3cf9a83f`.
213
+ This satisfies the pre-commit fresh-native criterion in dev-clone mode, not emitted-JS
214
+ package/bin-shim, final-artifact, registry, model-turn or fresh delivery/reply acceptance.
215
+ - **Explicit one-cut agy exception, authorized by GLG (2026-10-04):**
216
+ “명시 예외 승인 npm publish 전까지 쭉 가줘” authorizes this0.30.1 cut to proceed
217
+ without criterion7 acceptance. **agy native-push is NOT CERTIFIED on the1.2 line**:
218
+ measured on oracle/agy1.2.16, the answering LS port requires a CSRF nonce the external
219
+ sender does not legitimately hold; authenticated current host/CID join and same-gid
220
+ round-trip are absent. HTTP200/grpc16 `missing CSRF token` is not successful delivery.
221
+ The requirement's introduction date is unknown. The checked adapter/imprint/raw-send/
222
+ LIVE/pin subjects are unchanged from0.30.0; last native acceptance remains1.1.0
223
+ (2026-07-14), `PIN_AGY_MINOR=1.1` and DELIVERY's certification row are unchanged.
224
+ Follow-up [#128](https://github.com/junghan0611/entwurf/issues/128) is prerequisite
225
+ research: own tool-shell key presence/current CID/garden first, no nonce extraction,
226
+ discovery/cache/manager or unapproved implementation. This exception does not label
227
+ agy green, modify the permanent floor, or authorize npm publication.
228
+ - **No duplicate local floor:** GLG requested retaining the existing green evidence
229
+ and resolving only the two native leaves. P4/full, qualification BODY, P5 and duplicate
230
+ local M0/full are not restarted for the post-verdict evidence/policy prose. Exact
231
+ prepared-SHA CI (four required jobs plus its qualification BODY) and one preserved
232
+ final-artifact consumer acceptance remain separate mandatory make evidence. The
233
+ working-candidate receipts above do not certify those later axes or registry bytes;
234
+ verification prose added after each frozen verdict is not the bytes that run consumed.
235
+
7
236
  ## 0.30.0 - 2026-10-02
8
237
 
9
238
  ### Changed
package/DELIVERY.md CHANGED
@@ -116,6 +116,7 @@ physical host. Do not read a D-level cell as a Darwin receipt.
116
116
  | **Copilot CLI first-party extension** | raw transport probe; superseded by the owned product unit | D7 path observed; D3 control receipt incomplete; D8 unproven | CLI-spawned extension over stdio JSON-RPC; `joinSession()` + documented `fs.watch` → `session.send({mode:"enqueue"})`. Idle wake, exact-marker reply, and completion passed on 2026-08-23 (CLI 1.0.80, L4, one Linux host). Two-process isolation was observed but its decisive B log was not preserved. Kept as the transport receipt the owned receive unit was built on; the shipped unit differs deliberately — it announces the inbox instead of injecting the body. |
117
117
  | **Copilot CLI garden citizen** | shipped in 0.15.0; send + receive + visible fresh accepted on one host | D6; D7 partial; D3 pending; D8 unproven | Birth, garden id, MCP hand and record-backed sender identity are accepted; the RECEIVER is an installed first-party extension that binds to the V3 record, writes a receiver marker owned by the WATCHER pid, and rings a doorbell the model drains with `entwurf_inbox_read`. `wakeMode` is `self-fetch`, so dispatch reaches the mailbox rail: armed → delivered, unarmed/stale → the honest `mailbox-undeliverable` refusal. **D6 is the owned-invocation LIVE acceptance of 2026-08-23** — garden `20260823T181316-d9f6ba`, native `20fe30c8-b2bc-4600-91a0-8a409131be51`, CLI 1.0.80: receive log `joined`→`armed`→`doorbell fresh=1`→`rang`, mailbox `lastEnqueuedAt 09:23:41.235Z` / `lastReadAt 09:23:56.480Z`, and a model reply on the same record/native/gid chain. **Visible fresh (step 9 clause 7) is a separate LIVE, 2026-08-25** — launch window `@89`/`%89` nonce `mux-fresh-call-690529ae99f99faa2252aefb`; exact-callback garden `20260825T085721-f68be0`; one `entwurf_v2` → `meta-mailbox → enqueued`; same garden `lastReadAt 2026-08-24T23:57:47.784Z` plus same-gid reply; GLG saw footer garden id and a healthy multi-turn window. Those rows stay unmerged. D7 is PARTIAL: reply and read receipt were observed, the completion taxonomy and long-haul operation were not. D3 (second-session isolation of an owned invocation) is PENDING — observed once, decisive log lost to scratch cleanup. Evidence level L4: one host. Launch through the owned invocation `entwurf copilot`, which sets `COPILOT_CLI_ENABLED_FEATURE_FLAGS=EXTENSIONS` for that one process; `doctor-copilot-receive` reads live CLI environments because a session launched without it is silently inert. Visible fresh is operator-metered and is not a release-gate MUST. |
118
118
  | **OMP (`omp`) garden citizen** | shipped in 0.16.0; send + receive + visible fresh accepted on one host | D6; D3 proven; D7 partial; D8 partial | Two in-process extensions in the operator's own TUI: birth mints the `mode === "tui"` host (subagents mint nothing) and names it as sender; the RECEIVER unit joins that citizen in the SAME process, holds an `fs.watch` on its mailbox signal, and rings an announce-only doorbell through the vendor's `pi.sendUserMessage` — measured to be on the FACTORY object, not the event ctx, and measured to start a turn on an idle host with zero typing (`agent_start` +31ms). `wakeMode` is `self-fetch`: the model drains with `entwurf_inbox_read` and THAT read is the receipt. **D6 is the LIVE acceptance of 2026-08-30** (oracle, omp 18.0.0) — garden `20260830T140819-116f6a`, `lastEnqueuedAt 05:08:20.555Z` / `lastReadAt 05:08:23.958Z`, and the citizen's own transcript carrying `mcp__entwurf_bridge_entwurf_inbox_read` for its own garden id. **D3 is PROVEN, not pending**: with two live omp citizens armed, one addressed enqueue rang exactly one doorbell and the sibling persisted no transcript and kept an empty mailbox. D7 is PARTIAL (`lastReadAt` needs no scraping; the reply does). D8 is PARTIAL — dedupe and every stale-handling path are implemented and hermetically pinned, ordering/loop-guard/crash-recovery are not. The `/new` unarm is the rail-specific one: the watch lives in the operator's TUI, so pid + start-key cannot see a citizen change underneath a living process, and without an explicit unarm the previous garden id would keep reading deliverable. Requires `tools: xdev: false` in `~/.omp/agent/config.yml` — the vendor default hides MCP tool schemas from the prompt, so the doorbell would name a tool the model cannot call. The decisive receipt lines — the ordering probe, the D6 chain, the D3 isolation and the `/new` unarm — are pasted into `scripts/raw-omp-measure/README.md` §M7 rather than left in a host-local `/tmp` path. Evidence level L4: one Linux host, ARM. **Visible fresh (step 9) is ACCEPTED — the clause 7 LIVE went green on 2026-08-30:** `entwurf_fresh_call` opens omp on all three public surfaces through the bare `omp` runtime with an explicit `--approval-mode yolo` width and the `mcp__entwurf_bridge_entwurf_v` callback name, behind a five-axis pre-mutation preflight whose fifth axis is omp-specific (`tools.xdev !== true`, without which the model cannot call the callback tool at all). **The first turn is a TWO-STAGE BOOTSTRAP rather than a positional prompt, and that is a measured correction, not a preference.** `[LIVE 2026-08-30]` the positional-prompt candidate opened its window and minted its citizen (garden `20260830T181342-452167`, native `01a051f2-3107-7147-8806-fa2a6f527610`), delivered the byte-identical framing as a user message at `09:13:42.413Z`, and the model answered the literal text `ACK` at `09:13:47.105Z` with ZERO tool calls; the caller timed out at 240s. `[source]` the interactive UI defers MCP discovery (`sdk.ts:1847-1855`, `:1881-1905`) while the positional `initialMessage` prompts straight after `mode.init()` (`main.ts:540-565`), and `[측정]` an observer on the same runtime saw `turn_start` at +654ms with the entwurf tools absent and the callback tool present only at +1484ms. So the launcher now carries `{v,target,nonce,task}` on the fixed registered flag `--entwurf-bootstrap`, and the in-process birth extension polls `getAllTools`(`source:"mcp"`) AND `getActiveTools` for the exact callback name, sends a callback-ONLY prompt, arms the task only on a `tool_result` whose stored `toolCallId`, tool name, target, nonce and `isError === false` all match, and DELIVERS it at the next `turn_end` of that same session. `[LIVE 2026-08-30]` that last boundary is itself a measured correction: a first attempt sent the task from inside the `tool_result` handler with an explicit `deliverAs: "followUp"`, the hook log showed the full chain (`bootstrap-armed` → `bootstrap-ready` +440ms → `bootstrap-callback-observed` → `bootstrap-released`), and the task still never appeared in the session — `[source]` an explicit `deliverAs` queues without starting a turn in either state, while the omitted form starts one when idle (`agent-session.ts:6511-6513`), which the same transcript confirmed three seconds later when the Bundle B doorbell's omitted-option send landed and started a turn. `[측정 2026-08-30]` the callback-only half is what was proven to work: model `openai-codex/gpt-5.6-sol`, tool live at +1105ms, prompt injected at +1107ms, and the sibling calling `mcp__entwurf_bridge_entwurf_v` with the exact nonce (`omp-cb-btkvva4r87` → `20260830T184054-1aa1f2`, `meta-mailbox → enqueued`). **The clause 7 acceptance, `smoke-omp-fresh-live` (release-gate MUST), 2026-08-30, 21 assertions, omp 18.0.0 / `openai-codex/gpt-5.6-sol`:** launch through `tools/call entwurf_fresh_call` with nonce `mux-fresh-call-34faea228f3c3638684b40ff`; sibling garden `20260830T192913-df52b9` taken from the CALLBACK's sender envelope and never from the launch receipt; exactly one new citizen (§3.5); addressed `entwurf_v2` → `meta-mailbox → enqueued`; `lastEnqueuedAt 10:29:19.179Z` / `lastReadAt 10:29:24.673Z`; the drain visible in that session's own transcript for its own garden id. **Both bootstrap stages are in that transcript in order** — the callback-only prompt at offset 970, the caller's task at 4732, no four-backend positional framing anywhere, and an assistant message after the task proving it started a turn rather than sitting in a queue. The unit's own log carries the state machine: `bootstrap-armed 10:29:13.399Z` → `bootstrap-ready 10:29:13.819Z` (+420ms) → `bootstrap-callback-observed 10:29:18.663Z` (`toolCallId=call_KZJtkxfzy1IEE4ejKutCPWcm|fc_0858…`) → `bootstrap-released 10:29:18.731Z` → `bootstrap-task-sent 10:29:18.759Z`. Evidence level L4: one Linux host, ARM, one run. `check-harness-admission-parity` keeps the deterministic half of the admission from being a matter of memory. What this does NOT establish: multi-host, multi-model, or repeated fresh calls in one process. **Cross-harness leg, 2026-08-31 (first bidirectional live-turn roundtrip on the committed bytes + operator redeploy):** a claude-code citizen (`20260831T090152-f998ac`) opened a fresh omp sibling through the public surface (nonce `mux-fresh-call-807cb693b1913ce98ffdbfd1`, callback sender garden `20260831T124226-eac41a`), dispatched an addressed `entwurf_v2` → `meta-mailbox → enqueued`, and the omp citizen's own live turn drained and replied into the claude mailbox — its self-report (doorbell → `entwurf_inbox_read`; callback-only first user message, task second) agrees with every receipt on the chain. |
119
+ | **pi-durable native host** | 0.31.0 candidate; visible fresh + addressed receive + both cross-harness legs accepted on one Linux host (2026-10-06, `smoke-pi-durable-fresh-live`, 36 assertions, exit 0) | D6 (D3/D4 shown); D7 partial; D8 unproven | The operator-provided pinned source runtime (`cd32f77` + overlay) launched by the managed `entwurf pi-durable --provider … --model … --width task-wide`; the contact registers six tools and spawns the compiled bridge as a direct child; receive is announce-only self-fetch (doorbell → root submission → `entwurf_inbox_read`). Receipt (V on both sides, `openai-codex/gpt-6.1-sol`): real Pi `20261006T223710-e51e21` opened pd `20261006T223720-ba0c08` through `entwurf_fresh_call`; pd's first action called back into Pi with the exact nonce; Pi's live turn → pd mailbox ENQUEUE `2026-10-06T13-37-35-446Z-b57c69.msg`, that message's doorbell submission `done` on pd's root conversation, drained by pd's live turn (`entwurf_inbox_read` of its own id, settled); pd's live turn → Pi `entwurf_v2` settled `control-socket → sent` (native tool-result, joined by call id) and landed as exactly one Pi row with the expected payload and pd as the anchored sender. Native offering (root `pi.system`, toolsAdded/toolsRemoved applied): the six contact tools + bash/read/edit/write/subagent; pd's first root tool call is the callback. Actual model from root `pi.assistant` rows; the generation checkpoint does not retain `request.model` after completion. |
119
120
  | **Copilot CLI TUI+server** — *withdrawn lane, kept as evidence* | rejected | D7; D8 unproven | Older official-SDK probe over hidden `--ui-server`; idle enqueue worked, but loopback RPC authentication was not established. The bundled extension supersedes this candidate without reviving it. |
120
121
  | **ACP Claude / Cortex** | shipped runtime, outside this matrix | — | ACP sessions are children launched by entwurf's pi adapter, not already-running native sessions to wake. |
121
122
 
package/README.md CHANGED
@@ -27,6 +27,15 @@ Claude and Cortex Code are ACP backends. Codex and Antigravity stay native so th
27
27
  retain their own tools and work context. Capabilities differ by rail: a shipped
28
28
  citizen is not a promise of every lifecycle operation.
29
29
 
30
+ **Native durable contact (`pi-durable`) is accepted in the 0.31.0 candidate (#129).**
31
+ It is a separate native harness contact, not ordinary Pi's control-socket adapter.
32
+ The contact attaches one durable host to a garden id, adds visible identity and
33
+ two-way mailbox contact, while the upstream harness keeps its TUI, models/auth,
34
+ SQLite storage and recovery. First native admission passed on one Linux host;
35
+ release/artifact acceptance is separate. The
36
+ [installation requirements](#optional-native-durable--0310) differ from installing
37
+ the ordinary Pi CLI.
38
+
30
39
  ## Install
31
40
 
32
41
  **Choose by where you work. Neither route installs a harness, subscription or login.**
@@ -35,7 +44,7 @@ citizen is not a promise of every lifecycle operation.
35
44
 
36
45
  Prerequisites: **Node >=24.0.0**, Python 3 for `setup`, and any harnesses you choose
37
46
  to use, already installed and authenticated. Pi is optional-by-presence, supported
38
- range `>=1.0.0 <1.1`; Claude Code supported floor `>=2.1.217` is required for its
47
+ range `>=1.0.2 <1.1`; Claude Code supported floor `>=2.1.217` is required for its
39
48
  managed exec-hook lifecycle. pnpm is needed only for source-checkout setup.
40
49
 
41
50
  ```bash
@@ -63,6 +72,34 @@ Detected harness wiring on Darwin can therefore be written while setup stays
63
72
  non-green. Native Windows is **UNSUPPORTED**. The package has no npm `os`
64
73
  restriction; that is not certification of every platform's harness rails.
65
74
 
75
+ ### Optional native durable — 0.31.0
76
+
77
+ **Entwurf's npm installation does not change. Enabling durable additionally needs
78
+ an operator-provided native runtime; installing ordinary Pi from npm is not enough.**
79
+
80
+ | Component | How it is supplied | What it does not supply |
81
+ |---|---|---|
82
+ | Entwurf | Existing npm or source-checkout route above | A harness binary, source runtime, subscription or login |
83
+ | `@earendil-works/pi-durable` | npm **library** | The experimental app/TUI or Entwurf citizen attachment |
84
+ | Native experimental durable app | Pinned upstream **source checkout**, with Entwurf's narrow runtime-contact overlay | A replacement ordinary Pi CLI or an Entwurf-owned harness |
85
+
86
+ This lane retains Pi 1.0.2/source `cd32f77`; a newer global Pi installation does
87
+ not provision that experimental runtime. Existing non-durable users do not need
88
+ a Pi source checkout. Native auth and sessions stay upstream-owned: Entwurf does
89
+ not copy credentials or convert ordinary Pi sessions into durable SQLite sessions.
90
+
91
+ The package ships the compiled adapter and bootstrap: `entwurf setup` reports the
92
+ operator runtime as PASS/SKIP/FAIL without writing durable wiring, and
93
+ `entwurf pi-durable` is the managed launch. First native admission passed on
94
+ 2026-10-06: visible fresh/callback, addressed receive and real Pi ↔ pi-durable
95
+ LIVE36 on one Linux host ([receipts](./DELIVERY.md)). Installed-bootstrap import
96
+ proof does not supply or certify the native runtime; npm installation alone is
97
+ not a durable readiness verdict. #129 closed at reviewed main; release acceptance
98
+ remains its own floor.
99
+ See [setup: native durable](./docs/setup-clean-host.md#2b-optional-native-durable-pi-durable)
100
+ and [#130](https://github.com/junghan0611/entwurf/issues/130) for runtime-supply,
101
+ Pi-upgrade, ACP and UI follow-ups.
102
+
66
103
  ### Herdr workbench
67
104
 
68
105
  ```bash
@@ -182,9 +219,17 @@ and [Herdr launch](https://github.com/junghan0611/entwurf/blob/main/docs/herdr-l
182
219
  Instead of keeping native pi copies of the verbs, the adapter registers the same
183
220
  compiled bridge after record birth, under the citizen's identity, and Pi supervises
184
221
  that MCP child. **MCP is ingress; pi receive remains the record-addressed Unix
185
- control socket.** Garden identity and dispatch stay Entwurf's. What `pi-durable`
186
- or Pi codemode should mean here remains undecided: this cut neither adopts nor
187
- certifies them. Herdr 0.9.3 is a later lane, not a companion upgrade.
222
+ control socket.** Garden identity and dispatch stay Entwurf's. That 0.30.0 cut
223
+ did not adopt or certify `pi-durable` or codemode. Native durable support is now
224
+ accepted as a separate 0.31.0 candidate contact, as described above; codemode remains a
225
+ harness-internal capability, not another garden citizen. The 0.30.0 follow-up
226
+ separately measured Herdr supply 0.9.3 and
227
+ re-pinned the plugin runtime to published npm 0.30.0 with manifest 0.30.0; its
228
+ public consumer and CI receipts live in the #126 thread. That dated alignment is
229
+ not a permanent version-equality rule. 0.30.1 is published (npm, 2026-10-04); at its tag the
230
+ plugin's runtime lock is still the closed `herdr-checkout` verification carrier. Publication did
231
+ not re-pin it: the measured npm re-pin and its source-specific proof are separate, still-open
232
+ work that the [plugin source contract](./plugins/herdr/README.md) owns.
188
233
 
189
234
  Entwurf is the 0.12+ successor to
190
235
  [`@junghanacs/pi-shell-acp`](https://www.npmjs.com/package/@junghanacs/pi-shell-acp):
package/VERIFY.md CHANGED
@@ -96,7 +96,7 @@ that moved out of `scripts/` and into a file beside its subject would otherwise
96
96
 
97
97
  > **The herdr rail is an on-demand axis until it has run.** `smoke-herdr-fresh-call-live` opens a real caller inside a real herdr pane, has it invoke the PUBLIC `entwurf_fresh_call`, and reads the child's nonce callback — the one axis no deterministic gate reaches, since the rail is selected from the caller's own process environment. **The release aggregate does not yet require the herdr rail**: herdr is optional (a cut on a host without it must not block), and first evidence precedes promotion — a rail whose first acceptance run is days old has not earned a place in the gate that blocks every cut. Run it directly with `LIVE=1 ./run.sh smoke-herdr-fresh-call-live` whenever a cut changes herdr rail code, and promote it to a MUST only after the axis has a run history to point at. Without `LIVE=1`, or without herdr/pi/claude on PATH, it reports protocol SKIP — never a pass.
98
98
 
99
- > **The plugin's FIRST USER PATH is its own on-demand axis, and an npm acquisition receipt holds only for the ref it ran on (#118 홉 1).** Every other herdr gate proves the plugin against a source this repository controls: `check-herdr-plugin-build` drives a stub, and `smoke-herdr-plugin-build-live` redirects the product remote to a local bare clone with git `insteadOf` and asserts `identity.kind === "herdr-checkout"`. npm has been the production authority class since `dd84ac0`, though the lock committed in this checkout is the `herdr-checkout` verification carrier set for the 0.25.1 candidate window on 2026-09-30 (`8b92e09`). The re-proof this same document demands above (§ source switch) has one dated npm acquisition row — 2026-09-23, public `main` = `113ca53`, plugin 0.5.0, `kind=npm @junghanacs/entwurf@0.25.0`, PASS (CHANGELOG 0.25.1, "Public-remote first-user path") — and no run against this checkout's carrier or the current candidate. `LIVE=1 ./run.sh smoke-herdr-raw-install-live [--ref <REF>]` fills that row in a clean `node:24` container with no socket, config, cache or repo mounted, no `insteadOf`, the public remote spelled as a user would type it, and pi / herdr / Claude Code installed in the IMAGE BUILD as scaffolding (Hard Rule 17 — the product face begins at `herdr integration install pi`). herdr itself comes from `scripts/install-herdr-ci.sh` against `scripts/fixtures/herdr-supply.json`, so no version or digest lives here. `--ref` defaults to `main` rather than a pinned SHA because receipt (a) is defined as what a user gets today; the resolved commit is printed, so the receipt stays exact. It takes a REMOTE REF and not an arbitrary commit — measured on herdr 0.9.1, `--ref <sha>` fails as `couldn't find remote ref`, because the checkout fetches by name — so a candidate is addressed by its branch and pinned by the resolved commit the gate prints. **Its first question is a measurement, not an assumption:** herdr registers a plugin through a running server and falls back to `persist_plugin_offline` only on a connection error (`src/cli/plugin.rs:914-981,1016-1021` @ `c77af189`, 0.9.0 source), and a container has no server. The 2026-09-23 PASS installed with no server on the 0.9.1 binary `113ca53`'s `herdr-supply.json` pins, so that install path worked on 0.9.1 — inferred from the PASS, not a direct observation of the fallback branch; a later "no" on another herdr is #118 investigation output rather than a completion. `--yes` is always passed so a non-interactive exit 2 (`:189`) can never be misread as a missing server. **At a ref whose lock names `herdr-checkout` the acquisition axis reports a NAMED SKIP rather than a red, and the rest of the journey still runs.** That lock is the candidate carrier a cut legitimately sits on — 0.23.0 was tagged that way and `dd84ac0` pinned npm afterwards — so a red there would report a broken install when what is true is that the ref does not lock npm. What is asserted at BOTH lock kinds is that the runtime came from the source the ref locks, and the package name is read from the checkout manifest rather than the lock, because a `herdr-checkout` lock carries no `name` (`herdr-runtime.mjs:317-328`) and joining `undefined` throws instead of failing an assertion. **Cells [6]–[9] carry it past the install into the USE path (#118 H1-4/H1-5).** An install is not a use, so the same container then runs what those bytes became: the compiled bridge entry, the three `REQUIRED_BINS` as executables, and a real `entwurf check-bridge` printing its exact eight-verb set — the installed-runtime row below, measured rather than inferred from the bootstrap's refusal to install without them. Then the pi that this plugin WIRED is started with no `-e` and no `--no-extensions`, because the subject is the wiring and not this checkout: one `get_state` in `--mode rpc` costs zero tokens and needs no provider argument (a bogus `--provider` exits 1 before session_start; omitting the pair lets pi resolve the default the extension itself registers), and while that session is alive the cell reads its V3 record, its gardenId-keyed control socket, and the installed `entwurf peer-facts` reporting it `alive`. The plugin's own status fan is then driven with NEITHER side stubbed, in both states a user can be in: with no herdr server it must name `herdr-agent-list-failed` and go red rather than draw an empty table, and under a headless `herdr server` — scaffolding for that second read only, stopped again before the teardown — it exits 0 and COUNTS the citizen as `unobserved` instead of dropping it. Last, the shipped `entwurf herdr-plugin-deactivate` runs from the installed bin, deletes the runtime it is executing from, and the plugin reinstalls onto the host it fully left — the deactivation row, on the npm source. **What these cells still do not close:** swap / torn-swap recovery on the npm source, the package-consumer proof, and the fan drawing a citizen as a ROW — that needs `placement.kind === "herdr-pane"`, so the pi session must live in a herdr pane a session reference joins, and a headless container has no panes. **This smoke carries no test beside behavior and no mutant**, and that is a property of its class rather than an omission: it is a real-live container journey whose oracle is the container's own end state, so there is no pure seam to assert against and nothing a source mutation could kill deterministically. Like the other two herdr LIVE lanes it is **on-demand and not an aggregate MUST** — herdr is optional, a cut on a host without it must not block, and first evidence precedes promotion. Without `LIVE=1`, or without a usable Docker daemon, it reports a named SKIP; `ENTWURF_REQUIRE_DOCKER=1` turns the Docker absence red. Neither skip is a pass.
99
+ > **The plugin's FIRST USER PATH is its own on-demand axis, and an npm acquisition receipt holds only for the ref it ran on (#118 홉 1).** Every other herdr gate proves the plugin against a source this repository controls: `check-herdr-plugin-build` drives a stub, and `smoke-herdr-plugin-build-live` redirects the product remote to a local bare clone with git `insteadOf` and asserts `identity.kind === "herdr-checkout"`. npm has been the production authority class since `dd84ac0`; the 0.30.0 follow-up re-pinned `@junghanacs/entwurf@0.30.0` with its published sha512 after the candidate windows rode `herdr-checkout` (`8b92e09`). The **unpublished 0.30.1 preparation** now uses that closed verification carrier again, without inventing a registry integrity. The source re-proof has separate dated npm rows: 2026-09-23 public `main=113ca53`, plugin 0.5.0, runtime 0.25.0 (CHANGELOG 0.25.1), and the 0.30.0 re-pin accepted at public `506c46f` in the [#126 thread](https://github.com/junghan0611/entwurf/issues/126). Neither certifies a future 0.30.1 registry acquisition. After publication and a measured re-pin, that source owes its own public-ref run; checkout candidate evidence does not transfer. `LIVE=1 ./run.sh smoke-herdr-raw-install-live [--ref <REF>]` fills that row in a clean `node:24` container with no socket, config, cache or repo mounted, no `insteadOf`, the public remote spelled as a user would type it, and pi / herdr / Claude Code installed in the IMAGE BUILD as scaffolding (Hard Rule 17 — the product face begins at `herdr integration install pi`). herdr itself comes from `scripts/install-herdr-ci.sh` against `scripts/fixtures/herdr-supply.json`, so no version or digest lives here. `--ref` defaults to `main` rather than a pinned SHA because receipt (a) is defined as what a user gets today; the resolved commit is printed, so the receipt stays exact. It takes a REMOTE REF and not an arbitrary commit — measured on herdr 0.9.1, `--ref <sha>` fails as `couldn't find remote ref`, because the checkout fetches by name — so a candidate is addressed by its branch and pinned by the resolved commit the gate prints. **Its first question is a measurement, not an assumption:** herdr registers a plugin through a running server and falls back to `persist_plugin_offline` only on a connection error (`src/cli/plugin.rs:914-981,1016-1021` @ `c77af189`, 0.9.0 source), and a container has no server. The 2026-09-23 PASS installed with no server on the 0.9.1 binary `113ca53`'s `herdr-supply.json` pins, so that install path worked on 0.9.1 — inferred from the PASS, not a direct observation of the fallback branch; a later "no" on another herdr is #118 investigation output rather than a completion. `--yes` is always passed so a non-interactive exit 2 (`:189`) can never be misread as a missing server. **At a ref whose lock names `herdr-checkout` the acquisition axis reports a NAMED SKIP rather than a red, and the rest of the journey still runs.** That lock is the candidate carrier a cut legitimately sits on — 0.23.0 was tagged that way and `dd84ac0` pinned npm afterwards — so a red there would report a broken install when what is true is that the ref does not lock npm. What is asserted at BOTH lock kinds is that the runtime came from the source the ref locks, and the package name is read from the checkout manifest rather than the lock, because a `herdr-checkout` lock carries no `name` (`herdr-runtime.mjs:317-328`) and joining `undefined` throws instead of failing an assertion. **Cells [6]–[9] carry it past the install into the USE path (#118 H1-4/H1-5).** An install is not a use, so the same container then runs what those bytes became: the compiled bridge entry, the three `REQUIRED_BINS` as executables, and a real `entwurf check-bridge` printing its exact eight-verb set — the installed-runtime row below, measured rather than inferred from the bootstrap's refusal to install without them. Then the pi that this plugin WIRED is started with no `-e` and no `--no-extensions`, because the subject is the wiring and not this checkout: one `get_state` in `--mode rpc` costs zero tokens and needs no provider argument (a bogus `--provider` exits 1 before session_start; omitting the pair lets pi resolve the default the extension itself registers), and while that session is alive the cell reads its V3 record, its gardenId-keyed control socket, and the installed `entwurf peer-facts` reporting it `alive`. The plugin's own status fan is then driven with NEITHER side stubbed, in both states a user can be in: with no herdr server it must name `herdr-agent-list-failed` and go red rather than draw an empty table, and under a headless `herdr server` — scaffolding for that second read only, stopped again before the teardown — it exits 0 and COUNTS the citizen as `unobserved` instead of dropping it. Last, the shipped `entwurf herdr-plugin-deactivate` runs from the installed bin, deletes the runtime it is executing from, and the plugin reinstalls onto the host it fully left — the deactivation row, on the npm source. **What these cells still do not close:** swap / torn-swap recovery on the npm source, the package-consumer proof, and the fan drawing a citizen as a ROW — that needs `placement.kind === "herdr-pane"`, so the pi session must live in a herdr pane a session reference joins, and a headless container has no panes. **This smoke carries no test beside behavior and no mutant**, and that is a property of its class rather than an omission: it is a real-live container journey whose oracle is the container's own end state, so there is no pure seam to assert against and nothing a source mutation could kill deterministically. Like the other two herdr LIVE lanes it is **on-demand and not an aggregate MUST** — herdr is optional, a cut on a host without it must not block, and first evidence precedes promotion. Without `LIVE=1`, or without a usable Docker daemon, it reports a named SKIP; `ENTWURF_REQUIRE_DOCKER=1` turns the Docker absence red. Neither skip is a pass.
100
100
 
101
101
  > **The Herdr plugin's install-time build has two axes, and one of them needs the network (#116 M3-b3).** `check-herdr-plugin-build` is deterministic and rides `check:hermetic`: the listing reaches the runner through its own spawn seam (there is no fake `herdr` binary in this repo), and the one cell that drives the REAL binary reports a named SKIP on a host without it — `ENTWURF_REQUIRE_HERDR=1` makes that absence red. What it cannot have is the real acquisition: `npm pack git+https://github.com/junghan0611/entwurf.git#<full sha>` builds the bridge through `prepare`, which installs devDependencies from the registry. So `LIVE=1 ./run.sh smoke-herdr-plugin-build-live` owns that axis, and its cells are **two kinds of evidence, labelled as such**: three are the real Herdr journey — a real `herdr plugin install` driving the real `[[build]]`, with the UNCHANGED product remote redirected to a local bare clone by git `insteadOf` (the one substitution, which is what makes an unpushed candidate testable) — covering remote-commit available, the `{pi}` → `{pi, claude-code}` reinstall with OpenCode as a zero-write negative control and exactly ONE counted vendor MCP owner entry, and the post-build Herdr-commit gap (where the ledger has already rebound to the gap commit, so the honest assertion is that transition and not unchanged bytes). The fourth cell — remote-commit **unavailable** — calls the shipped runtime leaf directly with the fixed product argv and is therefore **acquisition-leaf evidence, not a journey**; routing it through Herdr would add a second explanation for one red. Its oracle is the honest one too: active runtime, ledger and harness bytes preserved, while the journal is left as the certified `installing` retry authority the transaction deliberately writes before acquiring, and a normal install afterwards is green. Its Claude cell is where the vendor question the deterministic gates refuse to claim gets answered — whether Claude Code accepts an ABSOLUTE executable as an MCP command — and it reports a named skip on a host without `claude`, never a pass. Like the herdr fresh-call rail, this smoke is **on-demand and not an aggregate MUST**. The release aggregate does not require the plugin build smoke: herdr is optional, a cut on a host without it must not block, and first evidence precedes promotion.
102
102
 
@@ -200,6 +200,22 @@ that moved out of `scripts/` and into a file beside its subject would otherwise
200
200
 
201
201
  Do not collapse source, package, fixture, and native-host evidence into one “green.”
202
202
 
203
+ **Native durable contact (#129).** `check-pi-durable-beside` is the deterministic
204
+ beside-test/mutant coordinate in `check:contracts`. The separate
205
+ `check-pi-durable-contact`, `check-pi-durable-send` and `check-pi-durable-receive`
206
+ are CHECKOUT-ONLY SDK/contact gates: they require the provisioned pinned overlay
207
+ runtime (`ENTWURF_PI_DURABLE_RUNTIME`) and a private compiled bridge emitted from
208
+ this candidate (`ENTWURF_PI_DURABLE_BRIDGE_ENTRY`). Missing inputs report SKIP 97,
209
+ never PASS; present invalid inputs fail. Installed packages refuse these developer
210
+ gates. Contact is adapter-direct/harness-bypassed; send/receive exercise scripted
211
+ loopback S plus actual native harness H, not vendor V. Their scoped raw records,
212
+ wire, native view and SQLite oracles do not certify every queue/crash window.
213
+ The installed-bootstrap import in `check-pack-install` proves package closure,
214
+ not runtime supply or native admission. First-release visible fresh/callback and
215
+ native caller/target/cross-harness LIVE are owed by `smoke-pi-durable-fresh-live`, a
216
+ release-gate MUST (LIVE=1; vendor V on a real Pi and a real pi-durable host, operator
217
+ runtime required); SDK or package green does not waive it.
218
+
203
219
  | Axis | Required proof | Limit |
204
220
  |---|---|---|
205
221
  | Source | `pnpm run check:full` + `./run.sh check-gate-qualification` | Does not prove an installed consumer. |
@@ -251,8 +267,10 @@ every focused gate green at the time:
251
267
  `FRESHCALL-CODEX-PREMUTATION-MCP` in a manifest the lane never touched; qualification reported
252
268
  it `MUTANT-STALE` (find matched 0×). **A stale mutant is a claim nobody is testing** — its
253
269
  assertion keeps passing while the mutation that gives it meaning is never applied — which is why
254
- this is a red rather than a warning. `check-gate-manifests` validates shape and inventory in
255
- seconds but cannot see a find that no longer matches; only the executing body can.
270
+ this is a red rather than a warning. `check-gate-manifests` also reads each subject and
271
+ validates the joined `find` exactly once (`[QK:MUTANT-FIND-MATCHES-SUBJECT]`): #127's moved
272
+ reuse-catch anchor was caught by this HEAD. It executes zero committed mutants. Only the
273
+ qualification body proves that a matching corruption is killed at its claimed signature.
256
274
  - **Any `mcp/entwurf-bridge/src/**` edit owes `pnpm run build-bridge` plus
257
275
  `./run.sh check-bridge-delivery` in the same inner loop.** `[측정 2026-09-16]` the same candidate
258
276
  reached `check:full` with a stale compiled entry and failed in 22 seconds on "artifact is not
@@ -288,7 +306,7 @@ The goal is not merely "invoke Claude Code." We want:
288
306
  **One install command to remember: `./run.sh setup <project>`.** It is idempotent — re-run the exact same command whenever anything looks wrong. There is no second install surface to juggle: from a clone `setup` runs the whole floor in order.
289
307
 
290
308
  1. `pnpm install` — installs the pinned development dependencies and builds the bridge (source-checkout bootstrap only; an installed package never runs npm/pnpm inside `node_modules`)
291
- 2. pi wiring → `<project>/.pi/settings.json` + user-scope registration — only when a `pi` inside the supported range (`>=1.0.0 <1.1`) is on PATH; absent pi is an explicit zero-state SKIP, a below-floor pi is a detected FAIL. The user-scope entry is owner-recorded (#86 C2): another root's live-or-missing ownership makes this step a zero-write refusal (setup: pi FAIL) that names `takeover-user-scope`; the install-states bind the exact managed settings path (a drifted/symlinked/corrupt target is a zero-write refusal) and the inverse removes only the recorded owner's exact entry; `doctor-pi-package` reports the verdict
309
+ 2. pi wiring → `<project>/.pi/settings.json` + user-scope registration — only when a `pi` inside the supported range (`>=1.0.2 <1.1`) is on PATH; absent pi is an explicit zero-state SKIP, a below-floor pi is a detected FAIL. The user-scope entry is owner-recorded (#86 C2): another root's live-or-missing ownership makes this step a zero-write refusal (setup: pi FAIL) that names `takeover-user-scope`; the install-states bind the exact managed settings path (a drifted/symlinked/corrupt target is a zero-write refusal) and the inverse removes only the recorded owner's exact entry; `doctor-pi-package` reports the verdict
292
310
  3. Claude meta-bridge global plugin — only when `claude` is on PATH; otherwise skipped cleanly
293
311
  4. source stable-bin exposure — including certified `entwurf` → this checkout's `run.sh`, the managed runtime Copilot fresh resolves; helper units are attempted independently and a foreign helper is a named FAIL
294
312
  5. agy bridge + exact permission + statusline + `PreInvocation` hook — only when `agy` is on PATH; each adapter is idempotent and independently doctorable
@@ -398,6 +416,7 @@ The single-turn / multi-turn / cross-process / persistence-boundary / shutdown i
398
416
  | Lifecycle policy — turn-scoped is always new; process-scoped may reuse only the live in-memory session; persisted records are not a resume/load path today | `check-acp-session-store`, `check-acp-session-reuse` |
399
417
  | Tool-call / event mapping | `check-acp-event-mapper`, `smoke-acp-provider-live` |
400
418
  | Prompt lifecycle — no wall-clock cutoff on a running turn; abort ends it by ACP `session/cancel` with bounded cleanup; a child death is reported with exit status + stderr on new AND reuse turns; our prompt-phase error text is not classified transient by pi | `check-acp-prompt-lifecycle`, `check-probe-ordering` |
419
+ | Claude typed `incomplete_tool_call` prompt failure — real pi retry/overflow classifiers reject the fixed verdict, raw evidence stays in existing diagnostics, exactly one seal and drop on new/reuse; other failures retain the legacy stderr path, cancel stays separate. A deterministic receipt does not certify the target vendor runtime. No LIVE gate induces this rejection; the raw-turn and reuse smokes certify only their own rows above. | `check-acp-vendor-rejection` (four mutants) |
401
420
  | Operator mcpServers / skills reach the live session | `smoke-acp-mcp-live`, `smoke-acp-skill-live`, `check-acp-config` |
402
421
  | Overlay isolation + memory containment | `check-acp-overlay`, `smoke-acp-memory-containment-live`, `check-acp-tool-surface` |
403
422
 
package/demo/README.md CHANGED
@@ -142,7 +142,7 @@ SCENE_DELAY=30 FINAL_PAUSE=10 bash demo.sh
142
142
 
143
143
  ## Prerequisites
144
144
 
145
- - `pi` on PATH (current floor 1.0.0)
145
+ - `pi` on PATH (current floor 1.0.2)
146
146
  - `entwurf` provider configured + auth ready for the selected sender/peer models
147
147
  - `asciinema` installed
148
148
  - `agg` installed (optional — only for GIF conversion)