@junghanacs/entwurf 0.40.0 → 0.41.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 (128) hide show
  1. package/AGENTS.md +4 -2
  2. package/BASELINE.md +55 -2
  3. package/CHANGELOG.md +562 -0
  4. package/CONTRIBUTING.md +1 -1
  5. package/DELIVERY.md +18 -2
  6. package/FAQ.md +8 -4
  7. package/README.md +60 -45
  8. package/VERIFY.md +14 -11
  9. package/demo/README.md +1 -1
  10. package/docs/acp-backend-rail.md +6 -2
  11. package/docs/external-mcp-host.md +8 -6
  12. package/docs/fresh-cut-policy.md +9 -1
  13. package/docs/setup-clean-host.md +76 -20
  14. package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +81 -19
  15. package/mcp/entwurf-bridge/dist/pi-extensions/lib/cc-retire-pidfd.py +236 -0
  16. package/mcp/entwurf-bridge/dist/pi-extensions/lib/cc-retire-request.js +473 -0
  17. package/mcp/entwurf-bridge/dist/pi-extensions/lib/control-retire.js +125 -0
  18. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-retire-production.js +149 -0
  19. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-retire.js +158 -0
  20. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-surface.js +2 -1
  21. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-visible-resume.js +283 -20
  22. package/mcp/entwurf-bridge/dist/pi-extensions/lib/fresh-call-composition.js +7 -0
  23. package/mcp/entwurf-bridge/dist/pi-extensions/lib/fresh-call-dispatch.js +47 -3
  24. package/mcp/entwurf-bridge/dist/pi-extensions/lib/herdr-fresh-call.js +3 -1
  25. package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-session.js +96 -16
  26. package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +5 -29
  27. package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-launch.js +28 -0
  28. package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-resume-call.js +26 -11
  29. package/mcp/entwurf-bridge/dist/pi-extensions/lib/pi-retire-request.js +76 -0
  30. package/mcp/entwurf-bridge/dist/pi-extensions/lib/resume-launch-identity.js +67 -17
  31. package/mcp/entwurf-bridge/dist/pi-extensions/lib/retirement-event.js +211 -0
  32. package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-hook.js +124 -10
  33. package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-pi-durable.js +53 -2
  34. package/mcp/entwurf-bridge/dist/scripts/meta-facts.js +1 -1
  35. package/mcp/entwurf-bridge/dist/scripts/probe-bridge-command.js +1 -0
  36. package/mcp/entwurf-bridge/src/index.ts +93 -19
  37. package/mcp/entwurf-bridge/test.sh +2 -2
  38. package/mcp/entwurf-bridge/tsconfig.build.json +10 -1
  39. package/package.json +15 -14
  40. package/pi/meta-bridge/entwurf-meta-receive/scripts/hook-launch.sh +3 -3
  41. package/pi/pi-durable/carrier/tui.js +18 -3
  42. package/pi/pi-durable/overlay/upstream-pin.json +12 -12
  43. package/pi-extensions/entwurf-control.ts +55 -20
  44. package/pi-extensions/lib/acp/backend-adapter.ts +5 -3
  45. package/pi-extensions/lib/acp/backend.ts +12 -9
  46. package/pi-extensions/lib/cc-retire-pidfd.py +236 -0
  47. package/pi-extensions/lib/cc-retire-request.ts +553 -0
  48. package/pi-extensions/lib/control-retire.ts +195 -0
  49. package/pi-extensions/lib/entwurf-control-rpc.ts +17 -1
  50. package/pi-extensions/lib/entwurf-v2-retire-production.ts +227 -0
  51. package/pi-extensions/lib/entwurf-v2-retire.ts +269 -0
  52. package/pi-extensions/lib/entwurf-v2-surface.ts +2 -1
  53. package/pi-extensions/lib/entwurf-v2-visible-resume.ts +390 -36
  54. package/pi-extensions/lib/fresh-call-composition.ts +15 -0
  55. package/pi-extensions/lib/fresh-call-dispatch.ts +45 -4
  56. package/pi-extensions/lib/herdr-fresh-call.ts +5 -0
  57. package/pi-extensions/lib/meta-session.ts +140 -16
  58. package/pi-extensions/lib/mux-fresh-call.ts +7 -27
  59. package/pi-extensions/lib/mux-launch.ts +29 -0
  60. package/pi-extensions/lib/mux-resume-call.ts +33 -12
  61. package/pi-extensions/lib/pi-retire-request.ts +111 -0
  62. package/pi-extensions/lib/resume-launch-identity.ts +104 -18
  63. package/pi-extensions/lib/retirement-event.ts +253 -0
  64. package/pi-extensions/meta-bridge-hook.ts +142 -13
  65. package/pi-extensions/meta-bridge-pi-durable.ts +57 -3
  66. package/run.sh +123 -34
  67. package/scripts/agy-bridge-config.py +4 -1
  68. package/scripts/build-bridge.sh +14 -0
  69. package/scripts/check-capability-bundle-reach.ts +135 -2
  70. package/scripts/check-entwurf-bridge-boot.ts +2 -1
  71. package/scripts/check-entwurf-fact-provider.ts +1 -0
  72. package/scripts/check-entwurf-v2-production.ts +2 -0
  73. package/scripts/check-entwurf-v2-surface.ts +7 -0
  74. package/scripts/check-gate-qualification.ts +14 -8
  75. package/scripts/check-herdr-activation.ts +2 -2
  76. package/scripts/check-herdr-placement.ts +1 -0
  77. package/scripts/check-hook-launch-topology.ts +6 -15
  78. package/scripts/check-install-container.sh +2 -2
  79. package/scripts/check-meta-doctor-oracle.sh +27 -1
  80. package/scripts/check-meta-facts.ts +8 -3
  81. package/scripts/check-meta-hook-session-switch.ts +230 -13
  82. package/scripts/check-meta-identity-consumers.ts +1 -0
  83. package/scripts/check-meta-listing.ts +1 -0
  84. package/scripts/check-meta-manifest-schema.py +1 -1
  85. package/scripts/check-meta-session.ts +31 -0
  86. package/scripts/check-meta-v3-record.ts +55 -1
  87. package/scripts/check-mux-resume-call.ts +35 -9
  88. package/scripts/check-peer-facts.ts +1 -0
  89. package/scripts/check-pi-durable-contact.ts +3 -1
  90. package/scripts/check-pi-durable-send.ts +4 -2
  91. package/scripts/check-pi-mcp-bridge.ts +1 -0
  92. package/scripts/check-resume-launch-identity.ts +62 -23
  93. package/scripts/lib/codex-fresh-live-protocol.ts +3 -2
  94. package/scripts/lib/meta-hook-bundle.ts +72 -0
  95. package/scripts/meta-bridge-claude-floor.sh +13 -9
  96. package/scripts/meta-bridge-doctor.sh +17 -0
  97. package/scripts/meta-bridge-install.sh +6 -0
  98. package/scripts/meta-facts.ts +1 -1
  99. package/scripts/mutants/bridge-boot-resume.json +5 -2
  100. package/scripts/mutants/cc-retire-pidfd.json +129 -0
  101. package/scripts/mutants/cc-retire-request.json +171 -0
  102. package/scripts/mutants/control-retire.json +105 -0
  103. package/scripts/mutants/control-send-receipt.json +1 -1
  104. package/scripts/mutants/copilot-receive.json +2 -6
  105. package/scripts/mutants/entwurf-v2-retire.json +476 -0
  106. package/scripts/mutants/fresh-call-dispatch.json +37 -0
  107. package/scripts/mutants/meta-hook-session-switch.json +88 -0
  108. package/scripts/mutants/meta-identity.json +57 -0
  109. package/scripts/mutants/mux-fresh-call.json +1 -1
  110. package/scripts/mutants/mux-resume-call.json +40 -4
  111. package/scripts/mutants/pack-install.json +4 -4
  112. package/scripts/mutants/pi-durable.json +139 -0
  113. package/scripts/mutants/pi-floor.json +5 -5
  114. package/scripts/mutants/pi-retire-request.json +72 -0
  115. package/scripts/mutants/resume-launch-identity.json +35 -8
  116. package/scripts/mutants/retirement-event.json +195 -0
  117. package/scripts/mutants/v2-surface.json +16 -0
  118. package/scripts/mutants/v2-visible-resume.json +283 -13
  119. package/scripts/probe-bridge-command.ts +1 -0
  120. package/scripts/smoke-agy-install-state.sh +2 -2
  121. package/scripts/smoke-codex-fresh-live.ts +2 -1
  122. package/scripts/smoke-copilot-mcp-state.sh +1 -1
  123. package/scripts/smoke-herdr-raw-install-live.sh +15 -7
  124. package/scripts/smoke-meta-install-state.sh +4 -4
  125. package/scripts/smoke-mux-lifecycle-live.ts +10 -10
  126. package/scripts/smoke-omp-mcp-state.sh +1 -1
  127. package/scripts/smoke-pi-durable-fresh-live.ts +5 -3
  128. package/scripts/smoke-pi-provider-state.sh +3 -3
package/CHANGELOG.md CHANGED
@@ -4,6 +4,568 @@ All notable changes to this project will be documented here. Format follows [Kee
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## 0.41.1 — 2026-10-23
8
+
9
+ **Unpublished candidate; release acceptance is not complete.** The actual operator
10
+ transition and Native aggregate below have been measured. Final prepared-SHA CI and
11
+ the requested manual BODY, the exact carrier-bearing artifact, main promotion, tags
12
+ and publication remain separate gates. Main still carries the published 0.41.0 Herdr
13
+ lock: promoting the checkout lock can change what main-tracking installations acquire.
14
+ A validation artifact or an earlier checkpoint's green run is not final acceptance.
15
+
16
+ ### Pi 1.4.0 reference shell
17
+
18
+ - Move the coherent nine-member production SDK set from exact 1.3.0 to exact 1.4.0,
19
+ keeping Entwurf's owned app/TUI composition and deterministic carrier emission.
20
+ The SDK owns execution, storage, queues, compaction and recovery; this adds no second
21
+ engine, supervisor, automatic retry policy or credential surface. The ordinary Pi
22
+ adapter's supported range becomes `>=1.4.0 <1.5`.
23
+ - Show sleeping tasks in the background-task tally, their local wake time in the task
24
+ panel, and the SDK's blocked reason verbatim. Keep cancellation distinct from retry;
25
+ no new retry command or UI is added.
26
+ - Adapt the ACP vendor-rejection test to pi-ai 1.4's bounded HTTP-status matching:
27
+ digits inside opaque request/tool ids no longer classify as transient. The raw
28
+ `Internal error` control remains transient. The production non-replay verdict and
29
+ raw diagnostic preservation are unchanged.
30
+ - Add SDK 1.3 public-API-generated SQL fixtures and independent SQLite conformance
31
+ tests for the SDK 1.4 schema transition, row/index preservation, constraints,
32
+ reopening and future-version refusal. These are SDK conformance, not a local
33
+ mutation claim over the upstream engine. Keep fixture data and its generator out
34
+ of installed packages, with npm packlist and tarball-floor checks.
35
+ - Separate this unpublished candidate's checkout instructions from public npm
36
+ 0.41.0 / SDK 1.3 instructions. The Herdr lock uses the closed `herdr-checkout`
37
+ verification carrier; it invents no unpublished npm integrity. No new Herdr
38
+ snapshot or registry publication is implied.
39
+ - Keep the Codex LIVE fixture callback-only on its outbound Pi leg. Asking for an
40
+ extra ACK created a fourth real tool call while the audit required three. The
41
+ exact-three, nonce and terminal-turn assertions remain unchanged; only the two
42
+ matching task strings changed, not production routing or retry behavior.
43
+ - Trim historical platform details, dated labels and duplicated lifecycle prose
44
+ from the README while retaining operator consent, unknown-outcome handling,
45
+ platform limits and the published-versus-candidate install distinction.
46
+
47
+ ### Upgrade boundary
48
+
49
+ Opening each existing durable session with SDK 1.4 migrates its SQLite storage to
50
+ schema 2. SDK 1.3 / Entwurf 0.41.0 refuses that session. Reinstalling the older package
51
+ is not data rollback: restoring a pre-upgrade backup reopens the old data, but omits
52
+ work done after that backup. Database restoration does not undo external messages,
53
+ tool/file/network effects, meta records or mailbox read receipts. Preserve the newer
54
+ set and inspect unknown outcomes before considering a restore or resend.
55
+ Even a refused SDK 1.4 open can change the file header
56
+ and sidecars while preserving logical rows (measured on a future-schema copy). Back up the complete target session
57
+ file set before its first new-SDK open.
58
+
59
+ Close the old owner normally and prove the process has exited before cutover. A
60
+ stale lock is not proof: a bounded, SQLite-free fixture reproduced a stalled but live
61
+ owner losing its lock. This lock behavior already existed in 0.41.0. Use the resume
62
+ picker to select the intended session rather than guessing with `--continue`.
63
+
64
+ SDK 1.4 counts a task SDK 1.3 left running as an interrupted run at its first open;
65
+ SDK 1.4's own normal close does not add a restart. Repeated interruptions can park a
66
+ task at the restart limit. Inspect outcomes before any resend; cancellation is not
67
+ retry, and recovery of an actual parked model generation remains unmeasured.
68
+
69
+ ### Preparation and operating evidence — not final release acceptance
70
+
71
+ Implementation checkpoint `3ed079b` follows independent source/proof reviews. Its
72
+ earlier working candidate passed the deterministic FULL floor in 885 seconds with
73
+ source/index unchanged, carrier 45 tests, storage conformance 11 tests, and ACP
74
+ vendor rejection 14 tests. The final pre-commit vocabulary sweep then changed one
75
+ harness-table SDK literal into a reference to the pin authority, independently read
76
+ and checked. These are implementation-era observations, not this prepared version's
77
+ FULL, native LIVE, installed artifact, operating-session migration or exact-SHA CI.
78
+
79
+ Private sandbox observations separately cover old-package refusal, backup restoration
80
+ and loss of later marker work, SDK task replay/parking, candidate shell open/close,
81
+ SDK 1.3-born fixture identity carried into the SDK 1.4 shell, and in-process open
82
+ failure releasing the session lock. Parked non-generation Hold tasks did not block
83
+ root input; conversation abort cancelled only the non-background Hold. None proves
84
+ real model-generation continuity or an operating citizen's actual upgrade.
85
+
86
+ Kill-power re-measured at this shipped SHA: none (all 1178 committed claims not
87
+ re-proved, #144).
88
+
89
+ That required line records the source's preparation-time measurement state, not a
90
+ prediction of later CI. GLG separately requested manual BODY evidence. The earlier
91
+ validation SHA `ff86c88bd58ba776e15ef48e1e4be566971a3e9a` has a four-job green push run
92
+ [39790950791](https://github.com/junghan0611/entwurf/actions/runs/39790950791) and a
93
+ separate `workflow_dispatch qualify=true` run
94
+ [39792701159](https://github.com/junghan0611/entwurf/actions/runs/39792701159): 85 lanes,
95
+ 1178 unique claims KILLED, survived/error/skipped 0. Those are that SHA's receipts,
96
+ not this later prepared SHA's. Its requested exact-SHA CI/BODY results must be recorded
97
+ separately in [#148's live evidence thread](https://github.com/junghan0611/entwurf/issues/148#issuecomment-6348113761);
98
+ no future result is invented here and the standing release policy is unchanged.
99
+
100
+ Earlier-candidate PARTIAL (operator-attested, not this SHA): head addcb8cd0bac surface
101
+ 6a9481bc357c -- `["bash","run.sh","check-dep-versions"]` 4/4 receipt 48d085e06816.
102
+
103
+ Earlier-candidate PARTIAL (operator-attested, not this SHA): head addcb8cd0bac surface
104
+ 6a9481bc357c -- `["bash","run.sh","check-pack-pin-matcher"]` 2/2 receipt 593dd0401502.
105
+
106
+ Earlier-candidate PARTIAL (operator-attested, not this SHA): head addcb8cd0bac surface
107
+ 6a9481bc357c -- `["bash","run.sh","check-pi-durable-carrier"]` 35/35 receipt 258f783406a7.
108
+
109
+ Earlier-candidate PARTIAL (operator-attested, not this SHA): head ff86c88bd58b surface
110
+ 7c75301f53a9 -- `["bash","run.sh","check-release-gate-outcomes"]` 21/21 receipt 251b71584442.
111
+
112
+ Earlier-candidate PARTIAL (operator-attested, not this SHA): head ff86c88bd58b surface
113
+ 7c75301f53a9 -- `["bash","run.sh","check-mux-fresh-call"]` 150/150 receipt 56c3558f9a15.
114
+
115
+ Both ff86c88 PARTIAL receipts were taken with the Codex fixture correction still
116
+ uncommitted on that head, on the recorded working surface.
117
+
118
+ The versioned working candidate's earlier FULL completed in 890 seconds, exit 0,
119
+ with source/index unchanged (log SHA256 `757115f291c05f397631f6e8de48a2b77fdfde973d5219edf70e63658c3b8e88`).
120
+ It predates later checkpoint metadata and is not a final committed-SHA CI result.
121
+
122
+ **Actual operator transition:** after the human closed the original owners and their
123
+ exit was proven with the scheme-aware owner classifier, the complete session file
124
+ set was consistently backed up without opening SQLite. The exact Linux validation
125
+ tarball (`92e5b2722ab8063d2bc50936db358a36a02a5e92e36babc3e1fbf98b399c2f44`)
126
+ was accepted unchanged in a container, separately exercised through an isolated pnpm
127
+ global old-to-new takeover, then installed as the operator's 0.41.1/SDK 1.4 runtime.
128
+ User-scope extension loading and doctors passed. The coordinator resumed the actual
129
+ old conversation: garden/native/createdAt/cwd stayed unchanged, a new owner attached,
130
+ a real model turn recalled the pre-close agreement and used tools, and four
131
+ send/read/reply/read receipts closed a round trip with an existing Claude Code sibling.
132
+ The human-reopened Pi reviewer also confirmed its identity, model, tools and recall.
133
+ No separate live DB query or universal transcript/parked-generation recovery claim is
134
+ made. This addon-less Linux validation tarball is not the carrier-bearing release file.
135
+
136
+ **Native aggregate:** the first run at `ff86c88` was MUST 23/1/0 and BEHAVIOR 1/0/0:
137
+ the extra requested ACK was a fourth distinct call, not parser duplication. Its raw
138
+ failure is preserved. After the scoped fixture correction, an affected fresh Codex
139
+ run passed 66 assertions with both terminal audits exactly 3/3. The new full run at
140
+ `a9d05847295230ed58f53b0bfd689d9ebd6ac1da` then passed **MUST 24/0/0,
141
+ BEHAVIOR 1/0/0**, including the deterministic FULL; source/index stayed unchanged.
142
+ The operator still used the **ff86c88 validation install**, not an installed a9d0584
143
+ artifact. Its runtime closure (bridge dist, pi-durable carrier, bootstrap and resolver)
144
+ was byte-identical to the checkout before and after the run; README and LIVE fixture
145
+ bytes differ. This is checkout-gate evidence with that installed runtime, not a claim
146
+ that the complete a9d0584 package was installed or accepted.
147
+ Scratch `/tmp/entwurf-release-gate-0.41.1-r2.cl0DDR`, log `release-gate.log`, SHA256
148
+ `020f489bf6fe024447bfc26a12f3499e5b80e844b0dcadf1e474e6adc8b4ae05`.
149
+ P9 was a read-only census: root 4.9 GiB and home 6.9 GiB free, with the existing
150
+ Emacs infrastructure identified rather than killed; current receipts and scratch
151
+ were preserved. Only the explicitly owned test app-server was normally stopped.
152
+
153
+ The final prepared-SHA push CI/manual BODY and Win32-bearing artifact acceptance
154
+ are still pending. The validation tarball has no Win32 addon; it cannot stand for
155
+ M3w or final macOS/Windows acceptance. No tag, GitHub release, npm publication,
156
+ Herdr re-pin or laptop rollout has occurred. Earlier 0.41.0 receipts below remain
157
+ historical.
158
+
159
+ ## v2026.10.22-herdr.0.41.0 — Herdr Entwurf plugin 0.41.0
160
+
161
+ A separate Herdr plugin snapshot, not another core release: core package 0.41.0 and its
162
+ `v0.41.0` tag remain unchanged. Core 0.41.0 is now published to npm; the publication is
163
+ verified from the registry, not from observing who ran it.
164
+
165
+ **Reading guide (2026-10-22).** The `## 0.41.0` section below and the body of the
166
+ [v0.41.0 GitHub release](https://github.com/junghan0611/entwurf/releases/tag/v0.41.0) are
167
+ prepare-time and make-time text: their npm wording (the Herdr lock's "unpublished candidate",
168
+ "npm publication each need their own approval") predates the publication. The publish is the later registry fact recorded in this section (`latest` 0.41.0,
169
+ published 2026-10-22T04:37:02.853Z, registry bytes equal to the accepted candidate). Neither the
170
+ published tarball's CHANGELOG nor the core release page is amended by this snapshot.
171
+
172
+ ### Herdr plugin
173
+
174
+ - **Re-pin the published core 0.41.0 and close the checkout window.**
175
+ `plugins/herdr/runtime-lock.json` returns from the `herdr-checkout` carrier that core 0.41.0
176
+ rode to production npm source `@junghanacs/entwurf@0.41.0` with the registry's measured
177
+ sha512 (`sha512-hSf6St0u…fBlvA==`). The plugin manifest moves 0.40.0 → 0.41.0; admission
178
+ remains Herdr >= 0.9.0 and the one-build/one-pane/Linux shape is unchanged. From the
179
+ `v2026.10.20-herdr.0.40.0` snapshot to `v0.41.0`, the changes under `plugins/herdr/`,
180
+ `scripts/herdr-runtime.mjs` and `scripts/fixtures/herdr-supply.json` were that lock's return
181
+ to `herdr-checkout` and the plugin README's resume/retire wording; the runtime helper and the
182
+ Herdr supply pin did not change.
183
+ - **What the acquired runtime now carries.** Core 0.41.0's lifecycle verbs ride in the runtime's
184
+ bytes: its installed bridge lists nine tools, `entwurf_retire_call` among them. Inside Herdr,
185
+ `entwurf_resume_call` still refuses as `herdr-resume-unsupported`. This snapshot measures no
186
+ retirement or resume through Herdr.
187
+ - **Pi range unchanged.** The acquired runtime still accepts Pi `>=1.3.0 <1.4`; core 0.41.0
188
+ keeps the Pi 1.3.0 SDK set.
189
+ - **Upgrade by acquisition source, not just version.** A settled npm-source 0.40.0 installation
190
+ can rebind under the plugin README's ownership conditions. A host that installed an
191
+ intervening `herdr-checkout` candidate must explicitly deactivate by its own absolute runtime
192
+ path before reinstalling the npm-source snapshot. No operator installation or active session
193
+ is rewired by this release work.
194
+ - **README.** The first-user-path receipt description no longer says the installed
195
+ `check-bridge` lists an eight-verb set; it names the verb set the installed bridge declares,
196
+ nine since 0.41.0.
197
+ - **Raw-install smoke scaffolding follows the Claude Code floor.** The first public-ref run of
198
+ `smoke-herdr-raw-install-live` at `cfdae0e` built its container with Claude Code 2.1.278, a
199
+ hand-kept pin from 2026-09-19, and the acquired 0.41.0 runtime refused to wire Claude below its
200
+ supported floor `>= 2.1.306` — the product's intended refusal, not a runtime defect. The smoke now
201
+ derives its exact Claude Code version from `package.json` `entwurf.claudeCodeFloor` instead of
202
+ retyping it. The product floor, the Pi, Herdr and Node pins and the smoke's end-state oracle are
203
+ unchanged.
204
+
205
+ ### Source-specific verification
206
+
207
+ - Registry metadata reports `latest` 0.41.0 and `repair` 0.12.8-repair.1, 642 files, published
208
+ 2026-10-22T04:37:02.853Z. The downloaded registry tarball is byte-equal to the preserved
209
+ accepted core candidate (SHA256 `2bd03ba900324a7c0882c2738c29593df0a1e4829fb3ae18d22be62186cf67ad`,
210
+ 11399545 bytes); its independently computed sha512 and sha1 equal `dist.integrity` and
211
+ `dist.shasum`, so core make's Docker consumer of those bytes (`node:24-bookworm`, repoDigest
212
+ `node@sha256:6dac556d…`) is reused here, not repeated. A sandboxed `pi install` of the
213
+ registry package resolved its bridge inside the sandbox, recorded the registry URL with that
214
+ integrity, and listed the curated Claude anchors with `--list-models entwurf`; a sandboxed
215
+ global npm install of the same package passed its installed `check-bridge` with nine tools.
216
+ No model turn. The accepted run stripped every `PI_`, `ENTWURF_`, `CLAUDE`, `CODEX_HOME`,
217
+ `TMUX` and `HERDR_` carrier and ran on the branch worktree, whose only checkout input (the
218
+ bridge resolver script) is unchanged; an earlier run from the clean tag HEAD left `TMUX` and
219
+ non-identity `PI_*` variables set and is kept only as a preliminary record.
220
+ - **The npm runtime swap against the real registry**, by the registry-shipped
221
+ `scripts/herdr-runtime.mjs` (byte-equal to this checkout's) in sandboxed user roots, 22/22
222
+ checks. The 0.40.0 runtime was seeded from its own committed lock (`036e268`); the swap to
223
+ 0.41.0 took one acquisition, the cached tarball's sha512 equals the lock and its sha256 equals
224
+ both the ready journal's observed digest and the accepted candidate. The `installing` journal
225
+ carried the 0.40.0 identity as `previousRuntime` and the `runtime-ready` journal carries
226
+ `null`; when acquisition began the 0.40.0 tree was still at the active address. A manually
227
+ seeded torn swap (the active tree moved to the backup address with a half candidate in
228
+ staging; not a killed process) was restored before acquisition and reported `recovered:
229
+ torn-swap-with-candidate`. An exact re-request acquired nothing and left journal and tree
230
+ byte-identical, and the owned removal reclaimed cache, runtime and journal. The helper is a
231
+ leaf that probes no Pi, so these cells certify neither a Pi upgrade nor Herdr's
232
+ install/update relocation, harness wiring, the installed CLI's deactivate path, a model turn,
233
+ or recovery from a real kill.
234
+ - **Focused gates on the branch**, with HEAD, index and work surface unchanged across them:
235
+ `check-herdr-supply` (11 assertions), `check-herdr-plugin` (49),
236
+ `check-herdr-plugin-profile` (14), `check-herdr-runtime-bootstrap` (31),
237
+ `check-herdr-activation` (33), `check-herdr-placement` (25), `check-herdr-fresh-call` (45),
238
+ `check-herdr-plugin-build` (21, its real-binary cell on herdr 0.9.5), `check-herdr-sandbox`
239
+ (12, a private herdr 0.9.5 server), `check-dep-versions`, `check-install-surface` and
240
+ `check-gate-manifests` (1173 committed mutants across 85 lanes validated, none executed).
241
+ - Pending, and not claimed here: the pushed SHA's four-job CI and the public-ref
242
+ install/use/deactivate journey of this npm pin, on Herdr 0.9.5 (the binary
243
+ `scripts/fixtures/herdr-supply.json` names) with Pi 1.3.0, from the public `main` ref rather
244
+ than the tag. Earlier npm or checkout-carrier receipts cannot certify these source-specific
245
+ axes. Those outcomes are recorded in the snapshot's post-push acceptance ledger, not in this
246
+ frozen text.
247
+
248
+ ## 0.41.0 - 2026-10-22
249
+
250
+ A sibling's garden id is its birthday, and this cut lets it rest and come back under it. A
251
+ sibling can now be opened, spoken to, retired when the human operator names it, and reopened
252
+ under the same id with its conversation intact. That holds for ordinary Pi and native Claude
253
+ Code. Retirement is a pause in a long session, not cleanup: it is never autonomous, a paired
254
+ requested/outcome record beside the target's record is attempted for every request with any
255
+ recording failure reported on its own axis, and the record and transcript stay.
256
+ A durable pi-durable sibling can drive both verbs. Each was measured once on real sessions, which
257
+ is recorded as dated evidence, not as a release gate.
258
+
259
+ ### Fresh call
260
+
261
+ - **A Pi-dialect model names its provider, and never OpenRouter (#76).** The dispatch root both
262
+ rails share now refuses, before either rail is asked anything, a pi or pi-durable model whose
263
+ provider segment is `openrouter` in any letter case (`model-openrouter-forbidden`) and a pi
264
+ model that names no provider at all (`pi-model-not-provider-qualified`). The second replaces
265
+ the 2026-08-13 non-goal that allowed a bare id: GLG decided on 2026-10-21 that the provider is
266
+ stated explicitly, because a bare alias resolves to whichever catalog row Pi prefers (the
267
+ 2026-09-17 bare `terra` opened on an OpenRouter row). It is a call-time input contract, not a
268
+ version pin: no model list, catalog copy, resolved-row or endpoint check was added, so a later
269
+ model name passes this provider check once it is written `<provider>/<id>` (not a promise
270
+ that it launches, nor a bypass of #128). Other backends' model names
271
+ (a claude-code `opus` alias) are not judged; resume and #128 curation are unchanged. The
272
+ refusal checks the name a caller wrote, not the endpoint a provider name reaches. The
273
+ `entwurf_fresh_call` model description says both rules. Proof:
274
+ `pi-extensions/lib/fresh-call-dispatch.test.ts` (three QKs) and three mutants in the
275
+ `fresh-call-dispatch` lane (12 → 15), executed through `./run.sh check-fresh-call-provider`.
276
+
277
+ ### pi-durable
278
+
279
+ - **The durable contact offers `entwurf_resume_call` (#147 L1).** A pi-durable citizen (the
280
+ coordinator's host) could not call the existing same-id resume verb: its contact exposed six bridge
281
+ tools and resume was not among them. It now registers a seventh, under the bridge's own
282
+ single-`target` schema, and forwards the call to the bridge unchanged. The verb itself is
283
+ unchanged by L1: at that checkpoint pi-only targets (L2 below widens the domain), a live target
284
+ refused, no turn, the record supplies the launch facts. Nothing new authorises who may resume, a
285
+ retire verb is not here, and a running durable host offers the tool only after it is restarted onto a build that
286
+ carries it. Because the bootstrap reserves every contact tool name, an operator native module
287
+ that registers a tool named `entwurf_resume_call` is now refused as `native-module-name-reserved`.
288
+ Proof: two QKs in `pi-extensions/meta-bridge-pi-durable.test.ts` — the tool is offered and hands
289
+ the bridge exactly `{target}`, and a faux model's call on the published runtime reaches this
290
+ package's compiled bridge through the contact's production connector and reads the bridge's named
291
+ refusal for a test-owned record of a backend with no same-id resume (codex since L2; no citizen is
292
+ resumed). Two mutants
293
+ in the `pi-durable` lane (84 → 86), executed through `./run.sh check-pi-durable-beside`. The
294
+ independent tool lists of `check-pi-durable-contact`, `check-pi-durable-send` and
295
+ `smoke-pi-durable-fresh-live` now name seven tools. One default-cell `check-pi-durable-send` run
296
+ (scripted loopback endpoint and the carrier app's native tool path; no vendor model turn) offered
297
+ `entwurf_resume_call` in the app's first model request, and its parameters there equal the
298
+ bridge's own listed schema — read from that run's raw wire receipt, because the default cell's
299
+ QK judges only self, peers and v2; the seven-tool `native-module` cell was not run. A running
300
+ coordinator host offering seven tools, and any operator rollout, remain unmeasured.
301
+
302
+ ### Operator-requested retirement (#147)
303
+
304
+ - `entwurf_retire_call {target}` makes one explicitly human-requested Pi or Claude Code attempt. Development, coordinator status and record-backed attribution are not standing permission. Where a host provides or is configured with an approval step, that step applies as well; Pi and pi-durable 1.3.0 have no built-in approval prompt by default. MCP annotations and caller identity are hints and attribution, not permission. No autonomous cleanup, roster expansion or automatic replay.
305
+ - The per-request production binding captures its directories and cancellation signal. Requested/outcome events share an id in a target-gid append-only sidecar with explicit actor/target fields. Action, record-write failure and lock cleanup stay independent; an append failure cannot turn a possibly effective action into a safe retry. The source bridge lists nine tools, ordinary Pi seven active plus two hidden, and the durable contact eight.
306
+ - Independent review repaired a metadata-test oracle, random-id privacy-test flakiness and snapshot/file-target consistency. A private `node_modules` compiled consumer passed29 assertions over anonymous/self refusal, existing resume refusal, inert Node RPC and two-line attribution. Operator dist hashes stayed unchanged. That consumer is not real Pi/Claude Code retirement, Native/LIVE, G4 rollout or release acceptance; final candidate floors and exact-SHA CI are still owed.
307
+ - 2026-10-22, source `a9c9459`: one operator-requested, test-owned Native round trip per backend — a fresh pi-durable caller (actual offering of all eight contact tools) retired and same-id resumed a fresh ordinary Pi and a native Claude Code 2.1.307 target once each, with dormant delivery refused, identity and transcript preserved across the promptless resume, and blind recall. n=1; not a MUST gate, ACP, Herdr, Windows, release-artifact or flush/descendant claim ([BASELINE](./BASELINE.md#147-native-round-trip-2026-10-22-n1)). The five stale on-disk Codex/Copilot/OMP reader copies were rolled forward with their owning installers; Copilot birth's doctor runtime axis remains RED on a historical hook error. GLG explicitly deferred its Native runtime validation for this landing: the current free `auto` account, not a subscription, is impractical to test (GLG reports a greeting taking over a minute; not re-benchmarked here). On-disk reader compatibility is closed with that named runtime deferral; resident-process reloads and broader runtime/release acceptance remain unmeasured. Earlier component receipts below do not become this candidate's kill-power.
308
+
309
+ ### Internal retirement checkpoints (#147; before public composition)
310
+
311
+ - **Pi's control server now serves an internal `retire` RPC.** A Pi started from this
312
+ checkout can already receive it; this is not a claim about the published 0.40.0 package.
313
+ Immutable garden/native identity, TUI, idle and no-pending guards precede one SDK shutdown
314
+ request. The shared production response envelope and strict one-shot client keep
315
+ `shutdown-requested` distinct from exit, flush or model silence. Busy work is refused, not
316
+ aborted or queued for a later shutdown.
317
+ - **Claude Code has a fixed Linux pidfd helper and request adapter.** The helper is copied
318
+ beside the compiled adapter; it pins a process, checks its start key, accepts one complete
319
+ go/cancel frame and requests one fd SIGTERM with bounded exit observation. Fresh
320
+ record/receiver/sender birth, arm binding, owner domain and pid/key joins run before helper
321
+ spawn and after ready. Unknown is not safe-retry permission. A fd-process exit does not
322
+ prove conversation identity, descendant termination or transcript flush.
323
+ - **A private dispatcher preserves action and cleanup independently.** Trusted caller
324
+ attribution/self refusal, fresh target and liveness checks, one adapter and one lock release
325
+ are composed through mandatory seams. It creates no grant/role database. At these component
326
+ checkpoints there was no accepted production host composition or public retirement MCP/contact
327
+ registration. The later candidate composition above owns its separate binding and runtime proof.
328
+ - **Proof remains candidate-local:** owned receiver/helper fixtures; independent review;
329
+ primitive PARTIAL Pi9 + CC11, later request-adapter PARTIAL9+6+15+40, then pure-dispatcher
330
+ PARTIAL10 on different candidates; private compiled consumer28 and a missing-Pi-entry
331
+ negative on the adapter candidate. These are not release-SHA kill-power, installed retirement
332
+ runtime or four-cell native lifecycle evidence. Actual host composition, G4 reader rollout,
333
+ public caller integration and the preserved #106 B append-only attribution record remain
334
+ open. Existing live/release floors are not waived by these checkpoints.
335
+
336
+ ### Resume
337
+
338
+ - **`entwurf_resume_call` reopens a dormant Claude Code citizen under its own garden id (#147 L2).**
339
+ The verb's domain is now pi and claude-code, a closed set; every other backend is the named
340
+ `target-backend-unsupported` (the retired `target-not-pi` has no alias). A Claude Code target is
341
+ launched as the fixed `claude --resume <record nativeSessionId>` at the record's cwd — no model or
342
+ permission flag it was once started with is restored, and no transcript is read; the record's
343
+ session id must be a lowercase UUID and its recorded transcript an existing file. Dormancy means
344
+ the LAST VALIDATED owner the Entwurf hook armed is proven gone AND that arm is still the record's
345
+ last one: the receiver marker, read through the no-follow fd reader (`readStoreRecordFile`: a
346
+ symlink or non-regular entry is corrupt, never followed) and judged by the shared
347
+ `classifyMarkerOwner`, must name this record's session and an owner proven DEAD, and the record
348
+ re-read after that verdict must carry the same non-null `attachIncarnation` the marker copied.
349
+ No marker, an unreadable or mismatched one, a live owner, an inconclusive one and an unbound one
350
+ each refuse by name (`target-receiver-absent` / `-corrupt` / `-mismatch` / `-unbound`,
351
+ `target-live`, `target-indeterminate`) with no window; the launch uses the re-read record, and no
352
+ marker or record is removed or rewritten. The observation succeeds only when a NEW live owner in
353
+ the pane this call opened re-arms the marker for the same session with a fresh binding the
354
+ current record also carries (same createdAt); a record defect stops it at once as
355
+ `record-unreadable` with its cause (window kept), and an unseen re-arm is `resume-unobserved`.
356
+ The verb submits no prompt; for Claude Code what the runtime does after it comes back (a doorbell
357
+ on unread mail may wake a turn) is unmeasured. Both backends' resume windows now carry the fixed
358
+ identity scrub fresh-call already had (`-e PI_SESSION_ID= -e PI_AGENT_ID=`, shared from
359
+ `mux-launch.ts`), because a resumed Claude Code never re-exports its own. Inside herdr the tmux
360
+ resume rail refuses as `herdr-resume-unsupported` instead of using an ambient `TMUX` (this also
361
+ applies to pi). The receipt names the caller from the same authoritative identity fresh_call reads,
362
+ as attribution only: an anonymous caller is `unattributed`, never refused, while a defect in the
363
+ caller's own store fails the call loud — for pi resume too — exactly as fresh_call does.
364
+ - **The arm binding: one new V3 key, `attachIncarnation` (#147 L2 B1).** A dead receiver marker
365
+ used to be resume evidence even when a LATER attach of the same session had committed but could
366
+ not re-arm the marker (owner unproven, marker write failed), so a second window could open on a
367
+ live session. Now the Claude Code hook mints a clock-independent 128-bit value (`randomBytes(16)`)
368
+ on every arm-capable event (SessionStart, CwdChanged, FileChanged — an arm revision, so one live
369
+ process mints many), commits it in the same atomic record upsert and copies it into the receiver
370
+ marker; UserPromptSubmit and every other writer preserve it, and nothing fills it by inference.
371
+ Every write the hook makes to an existing record runs under a per-gid record-arm lock in its own
372
+ directory (`meta-record-arm-locks`, beside the receivers dir; never the v2 dispatch lock visible
373
+ resume holds across its observation): the garden id is learned by a read-only certified lookup,
374
+ an absent record is published create-only (`upsertMetaSession` `expectAction` refuses a raced
375
+ create instead of turning it into an unlocked attach), an arm waits at most 2 s for the lock and
376
+ otherwise writes NOTHING and logs ERROR, and a busy UserPromptSubmit skips its backfill. A marker
377
+ write failure after the record committed is an ERROR logged after `INFO armed watch`, and resume
378
+ then refuses that garden as unbound. **Schema:** the same V3, one key wider — absent reads as
379
+ `null` ("no binding observed"), every serialize emits it, a present value must be 32 lowercase
380
+ hex, every other stray key is still refused; gardenId, nativeSessionId and createdAt keep their
381
+ values and no record is rewritten. `meta-facts` citizens carry the key verbatim. **One-way per host:** a reader that predates the key refuses
382
+ every record that carries it, and an old writer certifies the whole store first, so once one new
383
+ write lands every old reader and writer on that host refuses — a mixed-reader incident on oracle
384
+ on 2026-10-21 (records written by a Pi loaded from the development checkout) took the CC hook
385
+ and the pi-durable contact down until the checkout dist and the CC hook bundle were re-deployed.
386
+ Codex birth, the Copilot extension/receiver, the OMP bridge/receiver and the external
387
+ `entwurf-peek` mirror still carried the old reader there at L2; the on-disk copies were rolled
388
+ forward on 2026-10-22 (see the retirement section).
389
+ Old dormant Claude Code citizens whose record has no binding stay `target-receiver-unbound` until
390
+ a human reopens them once under a new hook. **Accepted boundary (GLG, 2026-10-21, current live
391
+ Pi/CC cohort scope):** only committed hook attaches are guarded — a process that holds the session
392
+ without one (hooks disabled, a record-arm lock timeout or a store failure at its start) is
393
+ invisible to the proof. The installed CC hook bundle now carries `lib/entwurf-v2-lock`, and the
394
+ doctor's writer-version parity checks it beside the writer.
395
+ - **Claude Code floor `>=2.1.306`** (`package.json` `entwurf.claudeCodeFloor`, GLG 2026-10-21):
396
+ same-id resume runs `claude --resume` from the record's last observed cwd, and the vendor CLI
397
+ reference says the session-id search covers other projects only from v2.1.223. 2.1.306 is the
398
+ version GLG relayed as running here; it is a declared floor with no LIVE receipt at 2.1.306 itself
399
+ (the 2026-10-22 n=1 round trip ran on 2.1.307). The
400
+ exec-form observations at 2.1.217 stand as observations.
401
+ - Proof: QKs beside the composition (`entwurf-v2-visible-resume.test.ts`), in
402
+ `check-resume-launch-identity`, `check-mux-resume-call`, `check-meta-v3-record`,
403
+ `check-meta-session`, `check-meta-hook-session-switch` (binding pair, UPS preserve, unproven owner,
404
+ lock busy/wait/own-dir, two overlapping successful schedules, and an install-closure check that
405
+ compares the hook's static double-quoted `from` imports with what the installer copies and then
406
+ runs the staged compiled hook) and `check-meta-doctor-oracle` (installed binding; lock module
407
+ missing/drifted). Mutants: v2-visible-resume 18 → 40, mux-resume-call 10 → 13,
408
+ resume-launch-identity 7 → 10, meta-hook-session-switch 17 → 25, meta-identity 4 → 9, existing
409
+ ones re-anchored. At the L2 checkpoint the LIVE dormant→resume journey for Claude Code had not
410
+ been measured, and `smoke-mux-lifecycle-live`'s Claude Code cell, which expects the still-live
411
+ sibling's resume to be refused as `target-live`, had not been run. Retire (G3) and the caller's
412
+ four cells were not part of L2; the later 2026-10-22 n=1 round trip is recorded in the
413
+ retirement section. The Claude Code dormant leg is still not a release-gate MUST.
414
+
415
+ ### Team bookmarks
416
+
417
+ - **`team.json.example` shows one way to keep long-lived siblings in view.** It is a fictional,
418
+ caller-maintained bookmark: each member's name, the descriptive form of address
419
+ `coordinating sibling` or `sibling`, backend, garden id and native session id. The real
420
+ `team.json` at a repository root stays ignored. No program loads either file; the record stays
421
+ the address authority, liveness is re-read from `entwurf peer-facts`, and membership is not
422
+ permission to send, resume or retire.
423
+
424
+ ### Herdr plugin
425
+
426
+ - **Back to the checkout carrier for this unpublished candidate.** `plugins/herdr/runtime-lock.json`
427
+ moves from the published `@junghanacs/entwurf@0.40.0` npm pin to the closed `herdr-checkout`
428
+ source, as the 0.40.0 preparation did; no npm integrity is invented and the plugin manifest
429
+ version is not bumped. The npm re-pin follows publication in its own Herdr snapshot. Inside
430
+ Herdr, `entwurf_resume_call` still refuses as `herdr-resume-unsupported`; retirement from a
431
+ Herdr pane was not measured.
432
+
433
+ ### Upgrade notes
434
+
435
+ - A running process keeps the bytes it loaded. Ordinary Pi's built-in MCP bridge and pi-durable
436
+ load the compiled `dist`, `start.sh` hosts load the source in a checkout, and installed
437
+ hook/extension copies change only through their owning installers; restart the session after
438
+ that ([setup](./docs/setup-clean-host.md#applying-new-source-to-a-running-host)). A reader that
439
+ predates `attachIncarnation` refuses records carrying it, so roll every installed reader forward.
440
+ - Claude Code needs `>=2.1.306` for same-id resume. Its retirement uses a Linux pidfd helper and is
441
+ refused elsewhere. The native-Windows preview has no resume, and retirement was not
442
+ measured there. Copilot's Native
443
+ runtime validation is deferred by GLG's decision on the free `auto` account.
444
+
445
+ ### Evidence boundary
446
+
447
+ - **One real round trip per backend, at `a9c9459`, not at this release's SHA.** A fresh pi-durable
448
+ caller retired and same-id resumed a fresh ordinary Pi and a native Claude Code 2.1.307 target
449
+ once each: dormant delivery refused, native identity and transcript preserved across the
450
+ promptless resume, blind recall correct. n=1; not a release-gate MUST, ACP, Herdr, Windows,
451
+ release-artifact or flush/descendant claim
452
+ ([BASELINE](./BASELINE.md#147-native-round-trip-2026-10-22-n1),
453
+ [#147](https://github.com/junghan0611/entwurf/issues/147#issuecomment-6329217980)).
454
+ - Kill-power re-measured at this shipped SHA: none (all 1173 committed claims not re-proved,
455
+ #144).
456
+ - Earlier-candidate PARTIAL (operator-attested, not this SHA): head 639f783df2d5 surface
457
+ d53b8f8d6602 -- `["bash","run.sh","check-entwurf-v2-retire"]` 32/32 receipt fc08567fb8d3
458
+ - Earlier-candidate PARTIAL (operator-attested, not this SHA): head 639f783df2d5 surface
459
+ d53b8f8d6602 -- `["bash","run.sh","check-retirement-event"]` 16/16 receipt 948a9661fdc0
460
+ - Earlier-candidate PARTIAL (operator-attested, not this SHA): head 639f783df2d5 surface
461
+ d53b8f8d6602 -- `["bash","run.sh","check-pi-durable-beside"]` 44/44 receipt 61e5b0552648
462
+ - Earlier-candidate PARTIAL (operator-attested, not this SHA): head 639f783df2d5 surface
463
+ d53b8f8d6602 -- `["bash","run.sh","smoke-agy-install-state"]` 12/12 receipt deccfdbf3990
464
+ - Earlier-candidate PARTIAL (operator-attested, not this SHA): head 639f783df2d5 surface
465
+ d53b8f8d6602 -- `["bash","scripts/smoke-pi-provider-state.sh"]` 5/5 receipt 9de492738ef4
466
+ - Earlier-candidate PARTIAL (operator-attested, not this SHA): head a9c945921a7e surface
467
+ 80a4f8a7b942 -- `["bash","run.sh","check-entwurf-v2-surface"]` 17/17 receipt b4c765bd35b7
468
+ - Earlier-candidate PARTIAL (operator-attested, not this SHA): head a9c945921a7e surface
469
+ 80a4f8a7b942 -- `["bash","run.sh","check-pi-durable-beside"]` 44/44 receipt b6751a543d7a
470
+ - **Local static and LIVE floor, measured on this preparation's candidate:** head `c318f30` plus
471
+ the three release-prep files (this evidence line excepted); the HEAD/index/worktree fingerprint
472
+ and the 94-file compiled `dist` were unchanged before and after each run. `pnpm run check:full`
473
+ PASS (exit 0, 882 s) with the host herdr at the supply pin 0.9.5, where `check-herdr-sandbox`
474
+ passed its 12 assertions on a private server and left the operator's panes and Pi trust store
475
+ untouched. Two earlier local attempts stayed RED and are kept, each at its own head: at
476
+ `bf24e17`, a `dist` built 35 s before the last `.ts` commit (the managed rebuild then produced
477
+ byte-identical output); at `c318f30`, the host herdr 0.9.4 against the 0.9.5 pin. `LIVE=1 ./run.sh release-gate <scratch> --cut`:
478
+ **MUST PASS=24 FAIL=0 SKIP=0, BEHAVIOR PASS=1 FAIL=0, cut OK**, 11:59:15–12:19:05 KST, with the
479
+ caller identity carriers stripped. The Codex step ran against a test-owned app-server started
480
+ for this run in its own tmux session (pid named from its own launch, start ticks recorded,
481
+ stopped by one TERM afterwards) from a different gate session, with the requested tiers
482
+ `gpt-6-luna` and `openai-codex/gpt-6-luna` — the request, not a billing or model-identity
483
+ proof. Receipts on the operator host: `.tmp-verify/release-0.41.0/` (`full-r3/full.log`
484
+ `44332ee7fd78`, `live/release-gate.log` `6f56fffab3da`).
485
+ - **Still owed before the tag.** This prepared SHA's exact push CI (four required jobs). This
486
+ release is carrier-bearing, so its candidate is the native-Windows preview workflow's pack at
487
+ the prepared SHA, never a local `npm pack`. The strict `doctor-meta-bridge` on an installed
488
+ 0.41.0 Claude host in a new post-install session, the agy shipped-lane cell and the Codex
489
+ caller-seat cell (VERIFY release acceptance 4, 7, 8) follow that candidate. Tag, GitHub
490
+ release and npm publication each need their own approval.
491
+
492
+ ## v2026.10.20-herdr.0.40.0 — Herdr Entwurf plugin 0.40.0
493
+
494
+ A separate Herdr plugin snapshot, not another core release: core package 0.40.0 and its
495
+ `v0.40.0` tag remain unchanged. The operator has published the core to npm.
496
+
497
+ **Reading guide (2026-10-20).** The `## 0.40.0` section below and the body of the
498
+ [v0.40.0 GitHub release](https://github.com/junghan0611/entwurf/releases/tag/v0.40.0) are
499
+ prepare-time text: their "still owed before the tag" lines and their npm wording predate the
500
+ cut. The cut-time acceptance (exact-SHA CI, the Windows preview candidate, the Linux consumer,
501
+ the installed remote-pair gate, VERIFY §3.4, and §3.7 (agy) excluded for that cut only by the
502
+ operator's decision, not a PASS) is recorded in the
503
+ [#107 cut receipt](https://github.com/junghan0611/entwurf/issues/107#issuecomment-6281283301).
504
+ The publish is the later registry fact recorded in this section (`latest` 0.40.0, published
505
+ 2026-10-20T01:49:33Z, registry bytes equal to the accepted candidate). Neither the published
506
+ tarball's CHANGELOG nor the release page is amended by this snapshot.
507
+
508
+ ### Herdr plugin
509
+
510
+ - **Re-pin the published core 0.40.0 and close the checkout window.**
511
+ `plugins/herdr/runtime-lock.json` returns from the `herdr-checkout` carrier that core 0.40.0
512
+ rode to production npm source `@junghanacs/entwurf@0.40.0` with the registry's measured
513
+ sha512 (`sha512-y9HgQIcm…bQnZUW/g==`). The plugin manifest moves 0.39.0 → 0.40.0; admission
514
+ remains Herdr >= 0.9.0 and the one-build/one-pane/Linux shape is unchanged. From the
515
+ `v2026.10.19-herdr.0.39.0` snapshot to `v0.40.0`, the only change under `plugins/herdr/`,
516
+ `scripts/herdr-runtime.mjs` and `scripts/fixtures/herdr-supply.json` was that lock's return
517
+ to `herdr-checkout`.
518
+ - **Pi range unchanged.** The acquired runtime still accepts Pi `>=1.3.0 <1.4`; core 0.40.0
519
+ keeps the Pi 1.3.0 SDK set.
520
+ - **Not a remote-pair certification.** Core 0.40.0's remote pair (#107) is carried in the
521
+ acquired runtime's bytes, but this snapshot measures no remote delivery, no SSH and no second
522
+ host through Herdr. The one real exchange remains the core section's L4 trial.
523
+ - **Upgrade by acquisition source, not just version.** A settled npm-source 0.39.0 installation
524
+ can rebind under the plugin README's ownership conditions. A host that installed an
525
+ intervening `herdr-checkout` candidate must explicitly deactivate by its own absolute runtime
526
+ path before reinstalling the npm-source snapshot. No operator installation or active session
527
+ is rewired by this release work.
528
+
529
+ ### Source-specific verification
530
+
531
+ - Registry metadata reports `latest` 0.40.0 and `repair` 0.12.8-repair.1, 621 files, published
532
+ 2026-10-20T01:49:33Z. The downloaded registry tarball is byte-equal to the preserved accepted
533
+ core candidate (SHA256 `4a6906ac38ff5024b9e07f7a092cc54a7686696082893293dfa653036f87fa55`,
534
+ 11292707 bytes); its independently computed sha512 and sha1 equal `dist.integrity` and
535
+ `dist.shasum`, so core make's Docker consumer of those bytes (`node:24-bookworm`, repoDigest
536
+ `node@sha256:6dac556d…`) is reused here, not repeated. A sandboxed `pi install` of the
537
+ registry package resolved its bridge inside the sandbox, recorded the registry URL with that
538
+ integrity, and listed the curated Claude anchors with `--list-models entwurf`; a sandboxed
539
+ global npm install of the same package passed its installed `check-bridge`. No model turn.
540
+ - **The npm runtime swap against the real registry**, by the registry-shipped
541
+ `scripts/herdr-runtime.mjs` (byte-equal to this checkout's) in sandboxed user roots, 22/22
542
+ checks. The 0.39.0 runtime was seeded from its own committed lock (`ba46dec`); the swap to
543
+ 0.40.0 took one acquisition, the cached tarball's sha512 equals the lock and its sha256 equals
544
+ both the ready journal's observed digest and the accepted candidate. The `installing` journal
545
+ carried the 0.39.0 identity as `previousRuntime` and the `runtime-ready` journal carries
546
+ `null`; when acquisition began the 0.39.0 tree was still at the active address. A manually
547
+ seeded torn swap (the active tree moved to the backup address with a half candidate in
548
+ staging; not a killed process) was restored before acquisition and reported `recovered:
549
+ torn-swap-with-candidate`. An exact re-request acquired nothing and left journal and tree
550
+ byte-identical, and the owned removal reclaimed cache, runtime and journal. The helper is a
551
+ leaf that probes no Pi, so these cells certify neither a Pi upgrade nor Herdr's
552
+ install/update relocation, harness wiring, the installed CLI's deactivate path, a model turn,
553
+ or recovery from a real kill.
554
+ - **Focused gates on the branch**, with HEAD, index and work surface unchanged across them:
555
+ `check-herdr-supply` (11 assertions), `check-herdr-plugin` (49),
556
+ `check-herdr-plugin-profile` (14), `check-herdr-runtime-bootstrap` (31),
557
+ `check-herdr-activation` (33), `check-herdr-placement` (25), `check-herdr-fresh-call` (45),
558
+ `check-dep-versions`, `check-install-surface` and `check-gate-manifests` (1034 committed
559
+ mutants across 79 lanes validated, none executed). `check-herdr-plugin-build` and
560
+ `check-herdr-sandbox` were not run locally because they run the operator's own herdr; they
561
+ ride the pushed SHA's FULL floor in CI.
562
+ - Pending, and not claimed here: the pushed SHA's four-job CI and the public-ref
563
+ install/use/deactivate journey of this npm pin, on Herdr 0.9.5 (the binary
564
+ `scripts/fixtures/herdr-supply.json` names) with Pi 1.3.0, from the public `main` ref rather
565
+ than the tag. Earlier npm or checkout-carrier receipts cannot certify these source-specific
566
+ axes. Those outcomes are recorded in the snapshot's post-push acceptance ledger, not in this
567
+ frozen text.
568
+
7
569
  ## 0.40.0 - 2026-10-20
8
570
 
9
571
  The bridge is crossed and the questions are carried forward. A person laid a bridge
package/CONTRIBUTING.md CHANGED
@@ -4,7 +4,7 @@ This is a daily-driver bridge. Correctness beats feature breadth. Read this befo
4
4
 
5
5
  ## What this repo is
6
6
 
7
- `entwurf` opens and messages visible sibling sessions across independent harnesses, and reopens dormant pi siblings in tmux ([capability table](./README.md)), with the garden id as their address — entwurf-core (v2 dispatch) + a meta-bridge + a pi adapter + an **ACP plugin on a two-backend adapter rail**; pi is one adapter, not the subject. The ACP plugin borrows the backend's identity (system prompt preset, model behavior, tool implementations) and shapes the *operating surface* — tools, MCP, skills, permissions — to match pi's own policy **wherever that backend exposes a knob for it**. Where it does not, the plugin does not fake one: a cortex session keeps its own native tool surface and receives MCP through an overlay projection, so "shaped to pi's policy" is a Claude-strength claim, not a universal one. Claude is the reference ACP backend and Snowflake Cortex Code is the second (landed 0.13.0, `cortex-` prefixed ids — [docs/acp-backend-rail.md](./docs/acp-backend-rail.md#cortex-code-audit-d1d10)); Codex is not on this rail at all — it is a shipped native-push citizen that keeps its own vendor tools and work context (see AGENTS.md, DELIVERY.md), never ACP-managed — and Gemini is not a shipped backend. That is the entire ACP-rail scope.
7
+ `entwurf` opens and messages visible sibling sessions across independent harnesses, and reopens dormant pi or Claude Code siblings in tmux ([capability table](./README.md)), with the garden id as their address — entwurf-core (v2 dispatch) + a meta-bridge + a pi adapter + an **ACP plugin on a two-backend adapter rail**; pi is one adapter, not the subject. The ACP plugin borrows the backend's identity (system prompt preset, model behavior, tool implementations) and shapes the *operating surface* — tools, MCP, skills, permissions — to match pi's own policy **wherever that backend exposes a knob for it**. Where it does not, the plugin does not fake one: a cortex session keeps its own native tool surface and receives MCP through an overlay projection, so "shaped to pi's policy" is a Claude-strength claim, not a universal one. Claude is the reference ACP backend and Snowflake Cortex Code is the second (landed 0.13.0, `cortex-` prefixed ids — [docs/acp-backend-rail.md](./docs/acp-backend-rail.md#cortex-code-audit-d1d10)); Codex is not on this rail at all — it is a shipped native-push citizen that keeps its own vendor tools and work context (see AGENTS.md, DELIVERY.md), never ACP-managed — and Gemini is not a shipped backend. That is the entire ACP-rail scope.
8
8
 
9
9
  **How a backend joins the rail** (the shape a PR must take): one adapter object in `pi-extensions/lib/acp/backend-adapter.ts` + its own curated rows/overlay modules + its own `check-acp-*` gate and mutant lane. Backend-specific *behavior* must stay behind the adapter, and backend-specific settings ride the opaque `adapterSettings` seam rather than growing the common config. That is not a ban on ever touching the common layer (`backend.ts`'s turn loop, `acp-client.ts`, `event-mapper.ts`, `session-store.ts`, `config.ts`) — cortex's landing did change `backend.ts` to pass the authoritative session key through the generic `ensureOverlay` seam. The rule is narrower and stricter: a common-layer change must be **backend-invariant** (it reads no backend name and branches on no backend) and **separately gated**. A common file that grows an `if (backend === …)` is the thing to reject.
10
10
 
package/DELIVERY.md CHANGED
@@ -59,6 +59,22 @@ ringing any doorbell, its filenames are ISO stamps so a drain is a global FIFO,
59
59
  is an honest `mailbox-undeliverable` refusal, and its receipt is that FILE. A mailbox enqueue is a
60
60
  durable file receipt; a control-socket queue is process memory.
61
61
 
62
+ ### Candidate lifecycle commands are not delivery boundaries (#147)
63
+
64
+ The current checkout's Pi control server also accepts the internal `retire` RPC, so a Pi
65
+ started from that checkout can expose it before a release is cut. It requires matching
66
+ record/native identity, a TUI, idle state and no pending work. Its `shutdown-requested` ACK
67
+ is not socket closure, process exit, flush or model silence. This command is not itself a public
68
+ MCP/contact verb and is not part of the four send boundaries above; the candidate public
69
+ `entwurf_retire_call` reaches a Pi target through it. A Pi whose process started before its
70
+ checkout carried this command does not know it, and its generic error answer is classified as
71
+ `unknown`/`malformed-response`, never as a safe refusal or a reason to replay. The candidate
72
+ CC pidfd helper observes one fd-pinned process, not a conversation, descendants or flush;
73
+ unknown never grants safe replay. Package/source presence, compiled consumer checks and a
74
+ real native lifecycle remain separate evidence axes; the one dated native lifecycle measurement
75
+ is [BASELINE's 2026-10-22 n=1 round trip](./BASELINE.md#147-native-round-trip-2026-10-22-n1). Historical delivery receipts below do
76
+ not certify these candidate components.
77
+
62
78
  ## Levels (D0–D8)
63
79
 
64
80
  These are independent of VERIFY's `L0–L5` evidence levels and BASELINE's question
@@ -109,7 +125,7 @@ physical host. Do not read a D-level cell as a Darwin receipt.
109
125
  | Harness / surface | Product status | Capability | Transport and boundary |
110
126
  |---|---|---|---|
111
127
  | **pi Entwurf** | shipped | D7; D8 partial | Record-addressed Unix control socket. A record-less socket is diagnostic only and never dispatched. A pi session calls the verbs through Pi's built-in MCP running the compiled `entwurf-bridge` (#125); the receive rail is unchanged. |
112
- | **Claude Code interactive `>=2.1.217`** | shipped; Linux certified | D6; D7/D8 partial | Per-session mailbox + exec-form `FileChanged`/`asyncRewake`. B2 proved idle wake and same-session continuity on one NixOS host. |
128
+ | **Claude Code interactive `>=2.1.306`** | shipped; Linux certified | D6; D7/D8 partial | Per-session mailbox + exec-form `FileChanged`/`asyncRewake`. B2 proved idle wake and same-session continuity on one NixOS host. `>=2.1.306` is the current declared floor; that historical B2 receipt does not certify #147 resume/retire lifecycle on this floor. |
113
129
  | **Antigravity / agy** | shipped | D6; D7 partial | Record-backed native-push through LS gRPC `agentapi send-message`; no mailbox or receiver marker. Admitted before the #82 step 9 contract and not re-evaluated under it, so it is legacy citizen evidence, not a step-9 supported harness: `entwurf_fresh_call` cannot open an agy sibling, and nothing here should be read as claiming visible lifecycle parity. |
114
130
  | **Codex CLI app-server citizen** | supported in 0.21.0; caller-seat topology ACCEPTED on Linux at 0.153.4, 2026-09-16 (56 assertions, exit 0), and the caller-DIRECTORY axis ACCEPTED the same day on the same host (#95 lane C, 65 assertions, exit 0; the 2026-09-12 explicit-home acceptance is history — #95 D1 retired that room) | D6 accepted; D7 partial; D8 unproven | Vendor-trusted user-scope `SessionStart` birth plus strict per-request metadata join; no shared-pid sender marker. `thread/loaded/list` probes the operator-owned app-server UDS and one-shot `codex queue` delivers with no retry. The operator owns the app-server and seats it wherever they like; Entwurf creates, moves and supervises none of it. Since #95 lane B a Codex CALLER with no explicit placement opens its sibling beside its OWN pane, located by the `thread-id` its `[tui].terminal_title` writes into the pane title; 0 or 2+ matching panes refuse with no fallback, and the title is a placement input only — never an address, liveness or delivery fact. #95 D1 (2026-09-16) retired the fixed `codex` home that omitted-placement Codex TARGETS used to select, so an omitted seat is the caller's own session for every backend. Exact 0.153.4 source still bounds placing a sibling beside a TUI whose thread nobody named as unsupported; the anchor resolves only the pane showing the caller's own thread. |
115
131
  | **Codex embedded TUI** | deferred | D0 partial | At the 2026-09-08 Codex 0.153.4 measurement, standalone mode had no `watchPaths`/`FileChanged`/`asyncRewake` analogue or supported idle receive route. This is dated vendor evidence, not a claim that the current candidate lacks records or fresh. |
@@ -128,7 +144,7 @@ Re-audit backend versions before turning probe evidence into a shipped adapter.
128
144
 
129
145
  ### Claude Code: durable body, edge-triggered wake
130
146
 
131
- Claude's hook contract is exec-only at `>=2.1.217`. `SessionStart` arms a per-session
147
+ Claude's hook contract is exec-only at `>=2.1.306`. `SessionStart` arms a per-session
132
148
  watch path; the sender writes durable `*.msg` bodies before poking the signal;
133
149
  `FileChanged` emits a doorbell and `asyncRewake` wakes the idle session. The receiver
134
150
  then calls `entwurf_inbox_read`, which drains all unread bodies and archives them as