@junghanacs/entwurf 0.34.2 → 0.35.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 (70) hide show
  1. package/CHANGELOG.md +244 -0
  2. package/README.md +7 -0
  3. package/VERIFY.md +16 -5
  4. package/demo/README.md +109 -175
  5. package/demo/demo-baseline.sh +5 -1
  6. package/demo/demo.sh +6 -2
  7. package/demo/herdr-pi-cc-20261011.provenance.json +64 -0
  8. package/docs/acp-backend-rail.md +28 -2
  9. package/docs/assets/entwurf-demo.gif +0 -0
  10. package/docs/setup-clean-host.md +1 -1
  11. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/backend-adapter.js +46 -2
  12. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/model-ids.js +67 -0
  13. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/models.js +9 -20
  14. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-visible-resume.js +11 -0
  15. package/mcp/entwurf-bridge/dist/pi-extensions/lib/fresh-call-dispatch.js +27 -1
  16. package/mcp/entwurf-bridge/dist/pi-extensions/lib/herdr-fresh-call.js +3 -0
  17. package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +2 -0
  18. package/mcp/entwurf-bridge/dist/pi-extensions/lib/resume-launch-identity.js +13 -4
  19. package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-pi-durable.js +119 -11
  20. package/package.json +4 -2
  21. package/pi-extensions/lib/acp/backend-adapter.ts +52 -2
  22. package/pi-extensions/lib/acp/model-ids.js +77 -0
  23. package/pi-extensions/lib/acp/models.ts +15 -22
  24. package/pi-extensions/lib/entwurf-v2-visible-resume.ts +12 -0
  25. package/pi-extensions/lib/fresh-call-dispatch.ts +25 -1
  26. package/pi-extensions/lib/herdr-fresh-call.ts +5 -0
  27. package/pi-extensions/lib/mux-fresh-call.ts +3 -0
  28. package/pi-extensions/lib/resume-launch-identity.ts +12 -4
  29. package/pi-extensions/meta-bridge-pi-durable.ts +153 -13
  30. package/run.sh +118 -20
  31. package/scripts/check-acp-backend-preflight.ts +10 -2
  32. package/scripts/check-acp-cortex.ts +7 -6
  33. package/scripts/check-acp-prompt-lifecycle.ts +2 -2
  34. package/scripts/check-acp-provider-surface.ts +1 -1
  35. package/scripts/check-acp-session-reuse.ts +5 -5
  36. package/scripts/check-acp-stop-reason.ts +2 -2
  37. package/scripts/check-acp-stream-hooks.ts +2 -2
  38. package/scripts/check-acp-usage-accounting.ts +2 -2
  39. package/scripts/check-fresh-call-dispatch.ts +47 -4
  40. package/scripts/check-gate-qualification.ts +8 -5
  41. package/scripts/check-probe-ordering.ts +13 -6
  42. package/scripts/check-release-gate-outcomes.ts +159 -1
  43. package/scripts/check-resume-launch-identity.ts +38 -0
  44. package/scripts/ci-qualify-decide.sh +114 -17
  45. package/scripts/mutants/acp-cortex.json +17 -8
  46. package/scripts/mutants/acp-set-model-readback.json +28 -0
  47. package/scripts/mutants/demo-reproducibility.json +155 -0
  48. package/scripts/mutants/fresh-call-dispatch.json +11 -0
  49. package/scripts/mutants/herdr-dev-checkout.json +70 -0
  50. package/scripts/mutants/pi-durable.json +117 -0
  51. package/scripts/mutants/release-gate.json +28 -2
  52. package/scripts/mutants/resume-launch-identity.json +15 -0
  53. package/scripts/mutants/v2-visible-resume.json +11 -0
  54. package/scripts/resolve-acp-bridge.ts +1 -1
  55. package/scripts/smoke-acp-bundled-mcp-live.ts +1 -1
  56. package/scripts/smoke-acp-carrier-augment-live.ts +1 -1
  57. package/scripts/smoke-acp-long-turn-live.ts +1 -1
  58. package/scripts/smoke-acp-mcp-live.ts +1 -1
  59. package/scripts/smoke-acp-memory-containment-live.ts +1 -1
  60. package/scripts/smoke-acp-ordering-probe-live.ts +1 -1
  61. package/scripts/smoke-acp-overlay-live.ts +1 -1
  62. package/scripts/smoke-acp-provider-live.ts +1 -1
  63. package/scripts/smoke-acp-raw-turn-live.ts +1 -1
  64. package/scripts/smoke-acp-session-reuse-live.ts +1 -1
  65. package/scripts/smoke-acp-skill-live.ts +1 -1
  66. package/scripts/smoke-acp-socket-citizen-live.ts +2 -2
  67. package/scripts/smoke-acp-v2-send-live.ts +1 -1
  68. package/scripts/smoke-entwurf-chain-live.ts +1 -1
  69. package/scripts/smoke-mux-lifecycle-live.ts +1 -1
  70. package/scripts/tsconfig.json +1 -0
package/CHANGELOG.md CHANGED
@@ -4,6 +4,250 @@ All notable changes to this project will be documented here. Format follows [Kee
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## 0.35.1 - 2026-10-13
8
+
9
+ ### ACP
10
+
11
+ - **Claude rows move to Opus/Sonnet 5.5 (#128).** The curated `entwurf` Claude ids are
12
+ now `claude-opus-5-5`, `claude-sonnet-5-5` and `claude-fable-5-1`; the Cortex rows keep
13
+ their native 5 ids. Driver `claude-agent-acp` stays 0.85.1, whose SDK already lists the
14
+ 5.5 ids. Curation and launch checks alone do not certify a live 5.5 turn; the narrow
15
+ LIVE evidence is recorded under the release boundary below. The retired
16
+ `claude-opus-5` / `claude-sonnet-5` are not aliased: an Entwurf-built pi launch
17
+ (`entwurf_fresh_call` `entwurf/<id>`, or `entwurf_resume_call` of a session recorded on
18
+ one) refuses them as `acp-model-not-curated` before a pane opens, because Pi's substring
19
+ resolver would otherwise open them on the Cortex rows. Records and transcripts are not
20
+ rewritten.
21
+ - **Claude set-model answers are read back before the prompt (#128).** The driver answers
22
+ `claude-sonnet-5-5` and `claude-opus-5-5` with its alias rows `sonnet` / `opus`, named
23
+ `Sonnet 5.5` / `Opus 5.5`, and `claude-fable-5-1` with its own row (measured against
24
+ 0.85.1 without a prompt). The claude adapter now accepts only that answer: a missing
25
+ model option, another row, or any row other than that exact value/name pair refuses the
26
+ turn before the prompt instead of letting a different model answer under the requested
27
+ id. Cortex answers are not read back; they are unmeasured.
28
+
29
+ ### Developer checkout
30
+
31
+ - **A source-only menu returns a host to its checkout.** `./run.sh menu` offers a read-only
32
+ readiness check, or switches to the developer board: after that same check and the exact
33
+ confirmation `DEV`, it runs the existing `plugins/herdr/use-dev-checkout.sh --apply`, which
34
+ deactivates the currently owned installation and then links Pi / Claude Code wiring and
35
+ Herdr's local plugin to this checkout. It needs an interactive terminal, runs only from a
36
+ source checkout, and adds no installer, npm acquisition, retry or recovery. Its prompts
37
+ and messages are English.
38
+
39
+ ### pi-durable
40
+
41
+ - **A read withdraws the inbox notices it made stale (#140).** A doorbell queues one native
42
+ follow-up per arriving message, while `entwurf_inbox_read` drains them all, so each
43
+ leftover notice started a run that read an empty inbox. After a read attempt, the
44
+ pi-durable host aborts (`Submission.abort`) its own queued notices whose announced mail is
45
+ no longer unread. Reads and rings share one gate. A failed inspection of the mailbox
46
+ retains the tracked notices; a failed abort releases its tracked handle without retry.
47
+ Both are named on stderr and leave the read's outcome unchanged. This does not claim the
48
+ native queued notice was removed after a failed abort, nor crash-safe receive.
49
+
50
+ ### Release boundary and verification
51
+
52
+ - **Driver unchanged by operator instruction.** `claude-agent-acp` stays 0.85.1. The 0.89.1
53
+ line (ACP SDK 1.6 → 1.8, agent SDK 0.3.293) is a separate lane and is not read as
54
+ compatible here.
55
+ - **Local evidence is focused, not a whole pass.** Each slice ran its affected focused gates
56
+ and its affected qualification groups once as PARTIAL receipts, each with a green
57
+ control: the #128 launch cut killed 99/99 claims in 12 groups, the set-model readback
58
+ 75/75 in 12 groups, and the menu 6/6 in one group. The set now holds 956 claims across
59
+ 72 lanes. By operator instruction the FULL floor and the whole qualification BODY were
60
+ not repeated locally during development; both ran in the first prepared SHA's exact CI.
61
+ Push run 38258514409 at `b93bb37` first failed `check` at `check-herdr-sandbox`
62
+ `[QK:HS-NO-RESIDUE]`: a sandbox process still held the private HOME after
63
+ `herdr server stop` and the gate's fixed 2 s wait. A rerun of the failed job on the same
64
+ SHA passed that assertion, and the run concluded with all four required jobs green and
65
+ the qualification body at 956/956 claims killed. The first red stays on record as a
66
+ teardown-timing observation; it is not read as a pass.
67
+ - **LIVE release gate, native Codex excluded for this cut.** As in 0.35.0, the operator
68
+ excluded native Codex: its MUST step stays wired and declined for lack of the
69
+ operator-supplied app-server pid and model tiers, so no Codex app-server, sibling or
70
+ turn started. That SKIP is an unmeasured per-cut exception, not a PASS or a standing
71
+ waiver. The gate ran from fresh scratch at `b93bb37`, with HEAD, index and tracked tree
72
+ identical before and after: `/tmp/entwurf-release-gate-0.35.1.aXzo1A/release-gate.log`,
73
+ MUST PASS=23 FAIL=0 SKIP=1 (only native Codex), BEHAVIOR PASS=1 FAIL=0 SKIP=0, standard
74
+ `--cut` exit 1 / BLOCKED (MUST SKIP). An earlier attempt failed only its static step,
75
+ because the checkout's bridge `dist` was older than the source mtimes
76
+ (`check-bridge-delivery` staleness); the bridge was rebuilt and the whole gate re-run,
77
+ and only the re-run is the receipt.
78
+ - **What the 5.5 evidence covers.** The ACP steps drove `claude-sonnet-5-5` prompt turns,
79
+ the provider-path ones through the set-model readback above. `claude-opus-5-5` ran only
80
+ as a turn-free socket citizen whose record and `get_info` report
81
+ `entwurf/claude-opus-5-5`; neither it nor Fable 5.1 has prompt-turn evidence. Before the
82
+ gate, one no-prompt wire measurement against 0.85.1 recorded the set-model answers for
83
+ all three ids, and one operator-started ACP turn on `claude-sonnet-5-5` reported its own
84
+ exact model id; that is a model's self-report, not a gate.
85
+ - **Unpublished candidate carrier.** As in 0.35.0, `plugins/herdr/runtime-lock.json`
86
+ temporarily names the closed `herdr-checkout` source: an npm-source lock must agree with
87
+ the checkout's core version, and 0.35.1 has no published integrity yet. The Herdr
88
+ manifest stays 0.35.0. After the operator publishes core 0.35.1, a separate Herdr
89
+ snapshot re-pins the measured registry bytes.
90
+ - **Publication boundary.** This record amendment carries no source change and takes its
91
+ own exact CI, qualification body included, before the make artifact, core tag and GitHub
92
+ Release. npm publication belongs to the operator; the Herdr re-pin follows it.
93
+
94
+ ## v2026.10.12-herdr.0.35.0 — Herdr Entwurf plugin 0.35.0
95
+
96
+ A separate Herdr plugin snapshot, not another core release: core package0.35.0 and
97
+ its `v0.35.0` tag remain unchanged. The operator has published the core to npm.
98
+
99
+ ### Herdr plugin
100
+
101
+ - **Re-pin the published core0.35.0 and close the checkout window.**
102
+ `plugins/herdr/runtime-lock.json` returns to production npm source
103
+ `@junghanacs/entwurf@0.35.0` with the registry's measured sha512
104
+ (`sha512-ENivJbtr…umf2zA==`). The plugin manifest moves0.34.2→0.35.0;
105
+ admission remains Herdr>=0.9.0 and the one-build/one-pane/Linux shape is unchanged.
106
+ - **The same core capability through Herdr.** This snapshot follows the renewed demo
107
+ and source-tooling restoration, plus #137's conservative TOML-only qualification
108
+ refinement. It records no new demo or model turn and changes no rail, gate or mutant.
109
+ - **Upgrade by acquisition source, not just version.** A settled npm-source0.34.2
110
+ installation can rebind under the plugin README's ownership conditions. A host that
111
+ installed the intervening `herdr-checkout` candidate must explicitly deactivate by
112
+ its own absolute runtime path before reinstalling the npm-source snapshot.
113
+ No operator installation or active session is rewired by this release work.
114
+
115
+ ### Source-specific verification
116
+
117
+ - Registry metadata reports version/latest0.35.0, repair0.12.8-repair.1. The downloaded
118
+ tarball is11083782 bytes, SHA256
119
+ `82ae9ab99b799c987fe0dac4bb76fc406afe42088a128a131af4d69a97592e71`, equal to the preserved
120
+ core release candidate. Independently computed sha512 equals `dist.integrity`;
121
+ the registry-shipped runtime helper is byte-equal to this checkout's.
122
+ - Required exact-registry-tarball Docker consumer passed without repacking. Real-npm
123
+ 0.34.2→0.35.0 swap and harness-seeded torn-swap recovery passed: the product restored
124
+ the last-good tree before reacquisition, certified the new registry digest, then
125
+ performed an exact-request no-op and owned-fixture removal. Seven focused
126
+ Herdr/manifests gates passed; HEAD/index/work surface stayed unchanged during that run.
127
+ - At preparation time, public-ref install/use/deactivate/reinstall and the exact pushed
128
+ plugin SHA's ordinary four-job CI/#137 next-plugin BODY-SKIP observation are still
129
+ pending. Their actual outcomes must be recorded in the release checkpoint and #137
130
+ before tagging/closing; this paragraph is not their acceptance. Earlier npm or
131
+ checkout-carrier receipts cannot certify these source-specific axes.
132
+ - Core0.35.0's whole940 qualification and native Codex LIVE remain explicit per-cut
133
+ unmeasured exceptions, never PASS or standing waivers. This plugin-only metadata
134
+ change does not run the approximately95-minute BODY or another core release aggregate.
135
+
136
+ ## 0.35.0 - 2026-10-12
137
+
138
+ ### Collaboration and qualification
139
+
140
+ - **A renewed demo after the 0.12.0 transition.** This is the first newly recorded
141
+ collaboration demo release since the 0.12.0 hard cut from `pi-shell-acp` to `entwurf`.
142
+ The capability is visible again in a real shared workbench, while #137 reduces redundant
143
+ qualification work without introducing a blanket plugin or data-file exemption.
144
+ - **Real Pi ↔ native Claude Code collaboration in Herdr (#138).** The README now shows the
145
+ accepted whole-workbench recording below the hero, linked to the Herdr section. The original
146
+ GIF bytes were published without captions or a retake; recording tooling remains separate.
147
+ - **Restore maintainer demo recipes and source tooling (#138).** The checkout now carries
148
+ the take/renderer/helpers and Node fixtures, including the actual whole-Herdr recipe and
149
+ original publication provenance. A new LIVE take is distinct from the private original;
150
+ missing historical tool versions are not invented. Archived v1 scripts refuse before any
151
+ command. Every LIVE scene refuses a non-approved selector or OpenRouter redirect first, and
152
+ missing LIVE cannot allocate capture resources; mixed subject/terminal tails are
153
+ kept, absent recording cannot certify success, and rerendering preserves the original
154
+ take's agg input. The renderer refuses publication destinations and parent aliases;
155
+ publication still requires separate review and copy. Source tests have their own discovered
156
+ Node floor and type fence, while maintainer TypeScript stays out of the installed package.
157
+ Neither source tooling nor the narrow privacy scan certifies a package consumer, original
158
+ capture replay, or whole-host/public-readability acceptance.
159
+ - **Avoid redundant qualification for untouched TOML find ranges (#137).** Push replay reads
160
+ manifests at the named HEAD and checks every joined find span on both blobs. Only exact-once,
161
+ unmoved, untouched TOML spans may skip. Markdown/JSON data stays file-level, because a
162
+ shorter presence literal or a later duplicate JSON key outside the find can re-satisfy an
163
+ oracle. Code/unknown subjects, signature sources and deciding machinery also remain
164
+ file-level, and uncertainty runs the body. The FULL floor and exact-SHA core
165
+ release qualification obligation are unchanged. The earlier source landing kept 0.34.2;
166
+ this separate preparation moves the core package to 0.35.0.
167
+
168
+ ### Release boundary and verification
169
+
170
+ - **Reviewed source, not borrowed release evidence.** The implementation commit `52cdd7f`
171
+ follows the final consistency closure and independent review. Its frozen source candidate
172
+ passed the FULL deterministic floor in 762 seconds with HEAD, index and work surface
173
+ unchanged. Affected PARTIAL groups killed all 24 release-gate and 12 demo claims at their
174
+ owning QK signatures, with four green controls; the other 904 claims were not run locally.
175
+ The set now contains 940 distinct claims. Those local receipts are development evidence,
176
+ not a whole qualification pass. The later test-only checkpoint `41a8d78` closes fixture
177
+ cleanup on green and assertion-red paths, including the fake recorder's owned teardown.
178
+ Its affected demo PARTIAL killed all 12 claims at their QKs with two green controls,
179
+ followed by frozen FULL 766s/0 on identical source/index/HEAD. All five measured fixture
180
+ prefixes had zero new residue; historical and original/native evidence was preserved.
181
+ - **Whole qualification BODY deferred by explicit operator instruction for this cut.**
182
+ The operator requested main publication without repeating the approximately 95-minute
183
+ qualification body. The ordinary push uses a one-commit `[skip ci]` marker to prevent its
184
+ automatic start; the existing `workflow_dispatch` with `qualify=false` can run the four
185
+ ordinary CI jobs without the body. This changes no product gate or workflow wiring.
186
+ A floor-only run is not exact-SHA whole qualification acceptance, and no skipped BODY
187
+ is reported as PASS. The unchanged release oracle would refuse it; make's preserved
188
+ artifact/tag/GitHub Release sequence remains pending, rather than bypassing that oracle.
189
+ - **Supply the real GIF decoder to the offline CI floor, not to the product.** The first
190
+ floor-only main run `38170795980` passed the three install/artifact jobs but stopped
191
+ `check:full` on the new demo fixtures because Ubuntu lacked `ffprobe` (`ENOENT`).
192
+ The check job now installs Ubuntu's `ffmpeg` package before the FULL floor and records
193
+ the decoder version. The fixtures still fake the renderer/caption tools and judge real
194
+ GIF bytes through `ffprobe`; no decoding assertion or missing-tool failure is skipped.
195
+ This is job-only scaffolding, not operator/global or npm setup. The CI recovery result
196
+ belongs in #137/#138's live checkpoint; the original failed run remains historical.
197
+ - **Native Codex LIVE is explicitly deferred for this cut, to the next release.** The operator
198
+ requested its exclusion from this verification. No native Codex sibling/app-server or turn
199
+ is started, and its product MUST wiring remains intact. This is an unmeasured per-cut
200
+ exception, not PASS or a standing waiver. Other required axes remain required; record
201
+ their actual outcomes and any named Codex SKIP separately, never round that SKIP green.
202
+ The earlier frozen versioned candidate's LIVE aggregate ran in
203
+ `/tmp/entwurf-release-gate-0.35.0.wypGz0/release-gate.log`: MUST PASS=23 FAIL=0 SKIP=1
204
+ (only native Codex), BEHAVIOR PASS=1 FAIL=0 SKIP=0, standard `--cut` exit 1 / BLOCKED.
205
+ Its runtime observation predates the test-only fixture checkpoint and is not borrowed
206
+ as that changed candidate's full release acceptance.
207
+ - **Unpublished candidate verification carrier.** The npm-source lock must agree with the
208
+ checkout's core version, so the 0.35.0 preparation temporarily uses the existing closed
209
+ `herdr-checkout` carrier without inventing an npm integrity. The published 0.34.2 pin and
210
+ Herdr manifest version remain historical/separate; this is not a Herdr 0.35.0 snapshot.
211
+ A host that changes acquisition source must explicitly deactivate/activate, never inherit
212
+ an activation. Operator installations are not rewired by this preparation. After the
213
+ operator publishes core 0.35.0, the later Herdr snapshot must re-pin the measured registry
214
+ bytes and perform literal #137 next-plugin acceptance; neither is claimed here.
215
+ - **Publication boundary.** The latest instruction narrows this lane to the 0.35.0 main
216
+ preparation and ordinary push, then a completion handoff. npm publication belongs to
217
+ the operator; after it, the Herdr plugin's separate 0.35.0 snapshot and measured npm
218
+ re-pin can follow. No npm publication, Herdr version bump or registry pin is executed
219
+ here. No accepted make artifact, core tag or GitHub Release is claimed prematurely.
220
+
221
+ ## v2026.10.11-herdr.0.34.2 — Herdr Entwurf plugin 0.34.2
222
+
223
+ A Herdr plugin snapshot, not a core release: no package version, npm artifact or core tag moves.
224
+
225
+ ### Herdr plugin
226
+
227
+ - **Runtime re-pinned to the published 0.34.2 (#136).** `plugins/herdr/runtime-lock.json` returns
228
+ from the `herdr-checkout` verification carrier the 0.34.2 preparation rode to the npm production
229
+ source: `@junghanacs/entwurf@0.34.2` with the registry's measured sha512
230
+ (`sha512-RbEkv3Ha…s/5ksg==`). The manifest version moves 0.34.1 → 0.34.2; `min_herdr_version`
231
+ stays 0.9.0. The checkout window is closed. A plugin host now receives the #136 fix: its
232
+ runtime's `doctor-meta-bridge` derives plugin-runtime mode from the activation ledger and
233
+ certifies the activation's absolute wiring.
234
+ - **Upgrading.** A host on the npm 0.34.1 snapshot stays on the npm source, so its next
235
+ `herdr plugin install` is a same-source rebind under the plugin README's conditions. A host that
236
+ installed from `main` while the lock named `herdr-checkout` needs `herdr-plugin-deactivate` by
237
+ its absolute runtime path, then `herdr plugin install` again.
238
+
239
+ ### Verification
240
+
241
+ - **Registry, measured before the pin.** `npm view` reports version 0.34.2 with `latest` →
242
+ 0.34.2 and `repair` → 0.12.8-repair.1. The downloaded tarball is 13595042 bytes with sha256
243
+ `e75efb0c…c009`, equal to the artifact accepted as 0.34.2. Its sha512, computed independently
244
+ from those bytes, equals `dist.integrity`. A sandboxed `pi install
245
+ npm:@junghanacs/entwurf@0.34.2` resolved the bridge to the registry install and listed the
246
+ `entwurf` models.
247
+ - The focused Herdr gates, `pnpm check`, the public `main` install journey and the exact-SHA CI run
248
+ on the pushed commit will be recorded in the GitHub release and #136, not claimed here. No gate, mutant or matrix changed, so no
249
+ qualification PARTIAL is owed.
250
+
7
251
  ## 0.34.2 - 2026-10-11
8
252
 
9
253
  ### Release coordination
package/README.md CHANGED
@@ -6,6 +6,13 @@ transcript, authentication, tools, or runtime.
6
6
 
7
7
  ![entwurf — a forged screwdriver for garden-citizen dispatch](docs/assets/entwurf-hero.jpg)
8
8
 
9
+ **Pi ↔ native Claude Code inside the [Herdr workbench](#herdr-workbench).**
10
+ A recorded source-checkout demo: callback → task → native Bash → reply.
11
+ [Source recipe and original provenance](demo/README.md#whole-herdr-pi--native-claude-code-138)
12
+ (the recipe creates a new take; the original private capture is not shipped).
13
+
14
+ ![Pi and native Claude Code collaborating inside Herdr](docs/assets/entwurf-demo.gif)
15
+
9
16
  [![npm](https://img.shields.io/npm/v/@junghanacs/entwurf?logo=npm)](https://www.npmjs.com/package/@junghanacs/entwurf) · maintained by [junghanacs.com](https://junghanacs.com/)
10
17
 
11
18
  A sibling is a visible session with its own runtime boundary, not a disposable
package/VERIFY.md CHANGED
@@ -58,6 +58,15 @@ install and pack gates that consume a tarball; gates that spawn a subprocess or
58
58
  gates that read product source as text; and the mutant EXECUTION COORDINATES described below. A
59
59
  new hand-built gate needs a reason one of those five applies.
60
60
 
61
+ The maintainer demo lane (#138) is source-only Node strip-types/CLI and subprocess
62
+ fixtures, not an installed adapter contract. Its `demo/**/*.test.ts` uses `node:test`,
63
+ so `check-demo-reproducibility` discovers and runs it separately in the deterministic
64
+ floor, with sandboxed HOME/XDG and fake version-only Pi metadata. Do not add Node tests
65
+ to the Vitest include and call them reached. Take/renderer/helper TS stays out of the
66
+ package; the paired scripts type fence checks it. Fake-tool tests, private original
67
+ capture, a new opt-in LIVE take, published GIF approval and exact release/package
68
+ acceptance remain distinct axes; see [the source recipe](./demo/README.md).
69
+
61
70
  **Four rules bind a migrated gate that carries mutants**, and each of them was measured rather
62
71
  than assumed (#119 V3 slice 2):
63
72
 
@@ -87,6 +96,7 @@ that moved out of `scripts/` and into a file beside its subject would otherwise
87
96
 
88
97
  - **Deterministic floor — two tiers (#70):** `pnpm check` is the everyday CORE — toolchain (lint + typecheck), the vitest lanes, and the pure-unit / behavioral-contract / source-topology gates plus the cheap static coherence checks. It prints its own total wall time; acceptance is ≤60s on the reference host `oracle` (an operator measurement, never a hard wall-clock gate on arbitrary hosts). `pnpm run check:full` is the FULL deterministic floor — the core plus the hermetic-integration and package/install tiers — and is what the frozen-candidate protocol, push CI, release-gate, and `prepublishOnly` run. Exact membership is the named `check:*` group scripts in `package.json` (the executable SSOT — this document records meaning and principles, not the command list); a gate changes tier by semantic-class decision, never by getting faster or slower. One core member assumes a build output: the beside test `pi-extensions/entwurf-control.test.ts` (reached through `check-tests-beside-behavior`) registers the COMPILED bridge and refuses by name when it is absent. `prepare` normally builds it at install; after an `--ignore-scripts` install or a bridge source change, run `pnpm run build-bridge` (in the sandbox candidate when verifying one) before the core. The FULL tier carries the qualification HEAD (`check-gate-manifests`, through `check:hermetic`); the everyday core does not, and neither tier carries the separately scheduled mutant-executing body (`check-gate-qualification`).
89
98
  - **Discriminating power of that floor:** `./run.sh check-gate-qualification` (scheduled, not ambient: the whole body runs only as the bare call — in the CI `check` job on a branch push that touched the qualification surface, and — for a cut — at the prepared SHA, where the exact-SHA release oracle requires that CI step once and the prepared state awaits it, never presumed PASS; a cut therefore batches its commits into that one prepared push (#132 took the cut's body off the local `release-gate`). Development runs no whole body (#133): a lane that changes a gate/mutant/matrix runs its affected exact-argv groups once, after review, as PARTIAL receipts — `./run.sh check-gate-qualification --group '<argv JSON>' --receipt <absolute path outside the repo>`, whose arguments reach the runner's parser unchanged and are refused there by name, before any body or snapshot, when malformed, missing or repeated. A receipt is a measurement of one group, never a qualification pass. Neither form is inside the default check chains; a semver TAG push triggers no CI at all, and the exact-SHA evidence a release quotes is whichever run at that commit CARRIES the body — the branch run when the push touched the qualification surface, else a dispatch run; a push that touched none of the qualification surface skips the body, and `workflow_dispatch -f qualify=true` plus a weekly `schedule` run it unconditionally — the exact-SHA release oracle refuses a SHA whose body step did not conclude success) re-plants committed defect mutants (`scripts/mutants/*.json`, one per closed defect class) in an isolated snapshot repo and requires each to turn its gate red **bounded and at its claimed `[QK:<claim>]` signature** — a wrong-reason red fails, a baseline-red control voids the whole group, and the runner is negative-controlled on every run (zero-match/multi-match/survived/wrong-reason/hang/control-red/impurity). This measures whether the deterministic gates still *block* what they claim to block; it is **not a new evidence level** (L0–L5 are untouched) and never substitutes for LIVE evidence. Per-cut records cite claim IDs + killed mutant IDs — "N checks passed" alone is not evidence. `check-agy-permission-matrix` complements it with the enumerated permission contract space (literal cells + stated exclusion rules, oracle independent of the SUT). The gate's HEAD is separable and IS in the floor: `check-gate-manifests` runs the runner self-test, validates the committed manifest set against the origin index, and asserts the declared lane inventory, while executing zero COMMITTED mutants (the self-test runs only its synthetic fixture mutants, in tmp fixture repos) and never snapshotting the repo — three of the five reds qualification has ever produced in CI died in that head, in under five seconds.
99
+ - **Push matching is conservative and hunk-aware (#137).** Git ranges read mutant manifests from the named HEAD commit, not a later working tree. Signature sources and the existing deciding machinery always match at file level, including paths that are also subjects. Only TOML subjects (`.toml`) may skip, and only when every mutant's joined `find` span occurs exactly once on both blobs, stays on the same lines, and intersects no zero-context diff hunk. Markdown, JSON, code and unknown subject types remain file-level. An outside-find early return/import/caller change can weaken a code mutant without editing its literal find. A presence/`includes` oracle whose required literal is shorter than the find can be re-satisfied by an out-of-span restatement; a scratch-repo probe measured exactly that false SKIP for `ADMISSION-LEGACY-DOCUMENTED` in `DELIVERY.md`. A later duplicate JSON key wins under `JSON.parse`, which every current JSON data oracle uses. TOML refuses a redefined key, and the current TOML oracles are exact-count/absence checks; a future TOML subject with a presence oracle reopens this boundary. `QUALIFY-FILTER-TOML-ONLY-REFINEMENT` pins Markdown/JSON at file level. Moved, absent, ambiguous, binary or unreadable spans/diffs/manifests run the body with a named reason; renames are compared as delete/add. `--files-from` has no hunk evidence and retains path identity. There is no Herdr filename or release-shape exemption. Span matching is not proof of unchanged kill-power. The rule narrows per-push qualification to those declared TOML spans; forced/scheduled and exact-SHA release qualification remain the backstop. This narrows redundant data-only pushes, never the FULL floor or exact-SHA release body's obligation; a body-less plugin SHA cannot supply the core SHA's evidence.
90
100
  - **The snapshot is source-only (#125).** It replicates the git work surface and never copies an ignored artifact from the checkout. A gate that consumes an ignored build output — the compiled `entwurf-bridge` a pi citizen registers — declares it on each of its mutants (`"build": {"argv": [...], "output": "<dir>"}`, one declaration per gate group). For that group only, the runner builds the output from the snapshot's own bytes before the control, rebuilds it after every mutation and from the restored bytes before the post-control (which must reproduce the baseline digest), never counts a build red as a kill, voids a run whose gate writes into the output, and removes the output when the group ends. The runner self-test owns this as `[QK:QUALIFY-BUILD-*]`.
91
101
  - **Live floor:** `LIVE=1 ./run.sh release-gate <scratch-project-dir> --cut` — `pnpm run check:full` + the v2-native live gates + the ACP plugin acceptance floor. It reports a **two-tier summary**:
92
102
  - **MUST tier** (release-blocking — owns the exit code; "green" applies only here): `pnpm run check:full`, `smoke-entwurf-v2-matrix-live`, `check-bridge`, `doctor-pi-provider` (#81 — `check-bridge` proves the launcher this checkout SHIPS; this proves the invocation the operator's pi provider actually EXECS, by booting it and requiring the entwurf verb set back, because `command -v` answers yes for a command that exits 127; wired as a step on 2026-08-19 after a relocated pnpm cmd-shim cost a cut sixteen LIVE steps before the same fact surfaced at `smoke-acp-bundled-mcp-live`), the resident-garden-guard zero-token half (record birth / record-keyed socket / attach-on-reopen), the `smoke-acp-*-live` ACP plugin smokes (socket-citizen / raw-turn / overlay / provider / session-reuse / carrier-augment / memory-containment / rgg / mcp / skill / bundled-mcp / v2-send), the axis wired in on 2026-07-31 that the aggregate had simply never listed (`smoke-claude-native-resume-live`), `smoke-entwurf-chain-live` — the cross-harness delivery chain (native Claude Code → pi GPT → pi ACP Sonnet → mailbox terminus) proving sender identity and replyability at every hop plus a real read receipt at the end — the integrated `smoke-mux-lifecycle-live` (its own note below), and the two OMP steps 0.16.0 wired: `smoke-omp-receive-live` (the addressed roundtrip into a live omp citizen; it reads the capability registry and decides its own outcome rather than passing by default) and `smoke-omp-fresh-live` (the clause 7 receipt the release stop now requires). (`smoke-session-id-name` is gone — #50 C3: its `--session-id`/`--name` substrate has no entwurf consumer anymore.)
@@ -96,7 +106,7 @@ that moved out of `scripts/` and into a file beside its subject would otherwise
96
106
 
97
107
  > **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
108
 
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`), and the 0.30.1 preparation rode that closed verification carrier again without inventing a registry integrity. The plugin snapshot `v2026.10.9-herdr.0.34.0` pinned the published `@junghanacs/entwurf@0.34.0` with its measured sha512 (#132); 0.31–0.33 were never pinned. The 0.34.1 preparation rode the closed `herdr-checkout` verification carrier again without inventing a registry integrity, and the snapshot `v2026.10.9-herdr.0.34.1` re-pins the published `@junghanacs/entwurf@0.34.1` with its measured sha512 (#135). 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 the 0.34.0 registry acquisition. That pin's real-npm swap / torn-swap recovery was measured locally on 2026-10-09 by driving the registry-shipped `scripts/herdr-runtime.mjs` (byte-equal to this checkout's) with its own npm acquisition: a 0.33.0 → 0.34.0 swap, and the same upgrade torn between its two renames then resumed, where the last-good 0.33.0 tree was restored before 0.34.0 was acquired again. Both ended `runtime-ready` at observed digest `sha256-e9d995ff…`, the accepted 0.34.0 artifact. That local receipt is recorded in the [#132 thread](https://github.com/junghan0611/entwurf/issues/132); it covers runtime recovery, not this smoke's cells. This smoke's public-ref acceptance of the 0.34.0 pin was measured locally at `--ref main`: PASS at resolved `b5d15d8` and again at the docs follow-up `8ed4d1a`, each acquiring `kind=npm @junghanacs/entwurf@0.34.0` — a main-ref receipt, not a tag-ref, native or full-Herdr claim. The 0.34.1 re-pin's npm-source rows — swap / torn-swap recovery, this smoke at a public ref, and the package consumer — are its own, recorded with that pin and never inherited from 0.34.0; 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.
109
+ > **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`), and the 0.30.1 preparation rode that closed verification carrier again without inventing a registry integrity. The plugin snapshot `v2026.10.9-herdr.0.34.0` pinned the published `@junghanacs/entwurf@0.34.0` with its measured sha512 (#132); 0.31–0.33 were never pinned. The 0.34.1 preparation rode the closed `herdr-checkout` verification carrier again without inventing a registry integrity, and the snapshot `v2026.10.9-herdr.0.34.1` re-pins the published `@junghanacs/entwurf@0.34.1` with its measured sha512 (#135). The 0.34.2 preparation rode the same carrier, and the snapshot `v2026.10.11-herdr.0.34.2` re-pins the published `@junghanacs/entwurf@0.34.2` with its measured sha512 (#136). 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 the 0.34.0 registry acquisition. That pin's real-npm swap / torn-swap recovery was measured locally on 2026-10-09 by driving the registry-shipped `scripts/herdr-runtime.mjs` (byte-equal to this checkout's) with its own npm acquisition: a 0.33.0 → 0.34.0 swap, and the same upgrade torn between its two renames then resumed, where the last-good 0.33.0 tree was restored before 0.34.0 was acquired again. Both ended `runtime-ready` at observed digest `sha256-e9d995ff…`, the accepted 0.34.0 artifact. That local receipt is recorded in the [#132 thread](https://github.com/junghan0611/entwurf/issues/132); it covers runtime recovery, not this smoke's cells. This smoke's public-ref acceptance of the 0.34.0 pin was measured locally at `--ref main`: PASS at resolved `b5d15d8` and again at the docs follow-up `8ed4d1a`, each acquiring `kind=npm @junghanacs/entwurf@0.34.0` — a main-ref receipt, not a tag-ref, native or full-Herdr claim. The 0.34.1 re-pin's npm-source rows — swap / torn-swap recovery, this smoke at a public ref, and the package consumer — are its own, recorded with that pin and never inherited from 0.34.0; 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
110
 
101
111
  > **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
112
 
@@ -106,7 +116,7 @@ that moved out of `scripts/` and into a file beside its subject would otherwise
106
116
  >
107
117
  > A cut that touches the prompt-lifecycle contract (no wall clock on a running turn) owes one long-turn acceptance the aggregate floor is too short to carry: `LIVE=1 ./run.sh smoke-acp-long-turn-live` drives a real turn whose tool work outlasts the retired 600s cutoff and requires exactly one cold ACP bootstrap in the transcript. It takes >12 minutes by construction and is on-demand, not part of `release-gate`.
108
118
  >
109
- > **The integrated mux lifecycle IS a release-gate MUST.** `LIVE=1 ./run.sh smoke-mux-lifecycle-live` enters through a real MCP `tools/call` on the shipped bridge launcher and follows one citizen the whole way: fresh-call launch receipt, the sibling's own nonce callback whose SENDER ENVELOPE is the address, an `entwurf_v2` control-socket send that lands in the sibling's own transcript, `entwurf_resume_call` REFUSED while that citizen is live, a stable-handle close proving pane and socket gone with the record preserved, delivery to the dormant citizen refused honestly, then the public `entwurf_resume_call` — whose LAUNCH and OBSERVATION receipts stay apart — and finally an `entwurf_v2` send the resumed session answers with a fact it was told BEFORE the window closed. That last step is the point: a socket answering under the same garden id proves a process stood up at that address, and only the recall proves the same conversation came back. Both pi provider shapes are driven to it (native `openai-codex/gpt-6-luna` and recorded-ACP `entwurf/claude-sonnet-5`, the only shape that re-injects a bridge extension), and the Claude Code cell ends where its capability ends: its resume is refused as `target-not-pi` with no window opened and no lock residue (the per-gid coordination lock is released).
119
+ > **The integrated mux lifecycle IS a release-gate MUST.** `LIVE=1 ./run.sh smoke-mux-lifecycle-live` enters through a real MCP `tools/call` on the shipped bridge launcher and follows one citizen the whole way: fresh-call launch receipt, the sibling's own nonce callback whose SENDER ENVELOPE is the address, an `entwurf_v2` control-socket send that lands in the sibling's own transcript, `entwurf_resume_call` REFUSED while that citizen is live, a stable-handle close proving pane and socket gone with the record preserved, delivery to the dormant citizen refused honestly, then the public `entwurf_resume_call` — whose LAUNCH and OBSERVATION receipts stay apart — and finally an `entwurf_v2` send the resumed session answers with a fact it was told BEFORE the window closed. That last step is the point: a socket answering under the same garden id proves a process stood up at that address, and only the recall proves the same conversation came back. Both pi provider shapes are driven to it (native `openai-codex/gpt-6-luna` and recorded-ACP `entwurf/claude-sonnet-5-5`, the only shape that re-injects a bridge extension), and the Claude Code cell ends where its capability ends: its resume is refused as `target-not-pi` with no window opened and no lock residue (the per-gid coordination lock is released).
110
120
  >
111
121
  > One cell cannot be fully fenced, and that is recorded rather than glossed: the recorded-ACP pi cell runs under the operator's REAL home, because its provider spawns `claude` as a child that authenticates from there — measured, a fenced HOME kills that turn with `Authentication required` before the model is ever reached, and `CLAUDE_CONFIG_DIR` alone does not fix it. That is the same trade `smoke-acp-bundled-mcp-live` already makes. While that cell runs, its citizen's control socket and per-gid lock exist under the operator's own `~/.pi/entwurf-control` and `~/.pi/entwurf-v2-locks`; its meta store stays fixture, so no garden record is minted outside the fixture, and the run ends by proving all six real roots hold the entry sets they started with, with no fixture garden id and no leftover lock.
112
122
  >
@@ -268,7 +278,7 @@ consumer image outside this standing protocol.
268
278
  ### Verifying the two capabilities a gate cannot fully judge
269
279
 
270
280
  - **Garden-id delivery:** discover a target with `entwurf_peers`, then `entwurf_v2 fire-and-forget` — the intent axis is single-valued since the visible-first cut. It reaches a live pi target over its control socket, a deliverable self-fetch citizen through the mailbox, and a probe-alive native-push conversation by direct injection. A DORMANT in-domain citizen rejects as `dormant-fire-forget-unsupported` — delivery never wakes it; reopen it with the separate lifecycle verb `entwurf_resume_call {target}`, then dispatch again. A wrong target state is rejected, never auto-fixed and never launched into.
271
- - **ACP continuity:** a direct `pi --provider entwurf --model claude-sonnet-5` turn, or the `smoke-acp-session-reuse-live` gate (process-scoped reuse + recall). Multi-turn reuse is proven by that gate, not by any v1 resume tool.
281
+ - **ACP continuity:** a direct `pi --provider entwurf --model claude-sonnet-5-5` turn, or the `smoke-acp-session-reuse-live` gate (process-scoped reuse + recall). Multi-turn reuse is proven by that gate, not by any v1 resume tool.
272
282
  - **agy citizenship:** in a fresh agy conversation, the first `PreInvocation` must yield a garden id, `entwurf_self` must report `agentId=meta-session/antigravity` and `replyable:true` only while the native probe is alive, and a reply to that same garden id must direct-inject into the same conversation. No mailbox/receiver-marker evidence counts on this rail.
273
283
 
274
284
  ### What NOT to do — bypassing the operational path
@@ -383,7 +393,7 @@ strips Claude hooks (`hooks: {}` overlay). Strip those carriers:
383
393
  cd /path/to/scratch
384
394
  env -u CLAUDE_CONFIG_DIR -u PI_SESSION_ID -u PI_AGENT_ID \
385
395
  LIVE=1 /path/to/entwurf/run.sh release-gate /path/to/scratch --cut
386
- pi --provider entwurf --model claude-sonnet-5 -p "reply with ok only" # one-turn smoke
396
+ pi --provider entwurf --model claude-sonnet-5-5 -p "reply with ok only" # one-turn smoke
387
397
  ```
388
398
 
389
399
  The one-turn smoke is a **provider**-surface check (auth + model routing + a real
@@ -411,7 +421,7 @@ frozen here.
411
421
 
412
422
  ## 1A. Main Agent Evaluation — Is `entwurf` Claude strong enough?
413
423
 
414
- Separate from continuity gates. Gates prove "sessions continue"; this questionnaire examines tool self-awareness / native tool usability / MCP-boundary awareness / long-turn focus / quality vs direct Claude Code. Run it against `entwurf/claude-sonnet-5` via a direct `pi --provider entwurf` turn (or a live ACP session); accumulate turns by re-prompting the same target.
424
+ Separate from continuity gates. Gates prove "sessions continue"; this questionnaire examines tool self-awareness / native tool usability / MCP-boundary awareness / long-turn focus / quality vs direct Claude Code. Run it against `entwurf/claude-sonnet-5-5` via a direct `pi --provider entwurf` turn (or a live ACP session); accumulate turns by re-prompting the same target.
415
425
 
416
426
  ### 1A.0 Two carrier surfaces — engraving vs pi-context-augment (load-bearing)
417
427
 
@@ -449,6 +459,7 @@ The single-turn / multi-turn / cross-process / persistence-boundary / shutdown i
449
459
  | Tool-call / event mapping | `check-acp-event-mapper`, `smoke-acp-provider-live` |
450
460
  | 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` |
451
461
  | 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) |
462
+ | Claude set-model answer read back before the prompt — an exact row, or the one alias row (value and name) measured for the requested id; a missing model option, another row or any other value/name pair refuses with non-transient text. Deterministic only: the measured 0.85.1 answer shapes are fixture literals, not a runtime certificate. | `check-acp-set-model-readback` (two mutants), `check-probe-ordering` |
452
463
  | Operator mcpServers / skills reach the live session | `smoke-acp-mcp-live`, `smoke-acp-skill-live`, `check-acp-config` |
453
464
  | Overlay isolation + memory containment | `check-acp-overlay`, `smoke-acp-memory-containment-live`, `check-acp-tool-surface` |
454
465