@junghanacs/entwurf 0.51.0 → 0.53.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 (88) hide show
  1. package/AGENTS.md +1 -1
  2. package/BASELINE.md +116 -397
  3. package/CHANGELOG.md +191 -2
  4. package/CONTRIBUTING.md +4 -4
  5. package/DELIVERY.md +2 -2
  6. package/ENTWURF-CLI.json +1 -1
  7. package/ENTWURF.json +10 -4
  8. package/README.md +11 -8
  9. package/VERIFY.md +333 -143
  10. package/demo/README.md +1 -1
  11. package/demo/demo-baseline.sh +1 -1
  12. package/demo/demo.sh +1 -1
  13. package/docs/acp-backend-rail.md +248 -34
  14. package/docs/setup-clean-host.md +75 -80
  15. package/mcp/entwurf-bridge/dist/ENTWURF.json +10 -4
  16. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/acp-client.js +1 -1
  17. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/backend-adapter.js +90 -14
  18. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/config.js +4 -9
  19. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/context.js +15 -0
  20. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/model-ids.js +9 -12
  21. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/models.js +41 -56
  22. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/tool-surface.js +33 -6
  23. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-control-rpc.js +4 -1
  24. package/mcp/entwurf-bridge/dist/pi-extensions/lib/fresh-call-composition.js +34 -3
  25. package/mcp/entwurf-bridge/dist/pi-extensions/lib/herdr-fresh-call.js +3 -1
  26. package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-mailbox-body.js +1 -1
  27. package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +2 -1
  28. package/package.json +14 -14
  29. package/pi/pi-durable/carrier/harness-setup.js +1 -1
  30. package/pi/pi-durable/carrier/subagent.js +1 -1
  31. package/pi/pi-durable/overlay/upstream-pin.json +15 -15
  32. package/pi/settings.reference.json +0 -1
  33. package/pi-extensions/acp-provider.ts +12 -6
  34. package/pi-extensions/lib/acp/acp-client.ts +6 -7
  35. package/pi-extensions/lib/acp/backend-adapter.ts +139 -15
  36. package/pi-extensions/lib/acp/backend.ts +261 -32
  37. package/pi-extensions/lib/acp/config.ts +4 -9
  38. package/pi-extensions/lib/acp/context.ts +17 -0
  39. package/pi-extensions/lib/acp/event-mapper.ts +236 -17
  40. package/pi-extensions/lib/acp/model-ids.js +9 -12
  41. package/pi-extensions/lib/acp/models.ts +46 -57
  42. package/pi-extensions/lib/acp/tool-surface.ts +34 -6
  43. package/pi-extensions/lib/entwurf-control-rpc.ts +5 -1
  44. package/pi-extensions/lib/fresh-call-composition.ts +37 -3
  45. package/pi-extensions/lib/herdr-fresh-call.ts +3 -1
  46. package/pi-extensions/lib/meta-mailbox-body.ts +1 -1
  47. package/pi-extensions/lib/mux-fresh-call.ts +3 -1
  48. package/pi-extensions/meta-bridge-pi-durable.ts +1 -1
  49. package/run.sh +62 -120
  50. package/scripts/check-acp-carrier-augment.ts +3 -21
  51. package/scripts/check-acp-prompt-lifecycle.ts +24 -3
  52. package/scripts/check-acp-provider-surface.ts +17 -26
  53. package/scripts/check-acp-session-reuse.ts +23 -4
  54. package/scripts/check-acp-stop-reason.ts +22 -3
  55. package/scripts/check-acp-stream-hooks.ts +24 -3
  56. package/scripts/check-acp-usage-accounting.ts +53 -24
  57. package/scripts/check-copilot-receive-arm.ts +19 -2
  58. package/scripts/check-entwurf-v2-surface.ts +7 -21
  59. package/scripts/check-fresh-call-dispatch.ts +9 -3
  60. package/scripts/check-gate-qualification.ts +6 -6
  61. package/scripts/check-herdr-fresh-call.ts +1 -0
  62. package/scripts/check-install-surface.ts +6 -0
  63. package/scripts/check-pi-durable-send.ts +4 -1
  64. package/scripts/check-probe-ordering.ts +34 -24
  65. package/scripts/check-release-gate-outcomes.ts +9 -23
  66. package/scripts/lib/codex-fresh-source-receipts.ts +12 -6
  67. package/scripts/lib/probe-cli-target.ts +3 -2
  68. package/scripts/mutants/acp-augment.json +0 -26
  69. package/scripts/mutants/acp-cortex.json +10 -183
  70. package/scripts/mutants/acp-foreground-only.json +11 -0
  71. package/scripts/mutants/acp-launch-namespace.json +3 -1
  72. package/scripts/mutants/acp-prompt-lifecycle.json +2 -2
  73. package/scripts/mutants/acp-set-model-readback.json +488 -0
  74. package/scripts/mutants/agent-guidance.json +2 -2
  75. package/scripts/mutants/codex-native.json +2 -2
  76. package/scripts/mutants/control-send-receipt.json +47 -7
  77. package/scripts/mutants/mux-fresh-call.json +12 -1
  78. package/scripts/mutants/pack-install.json +4 -4
  79. package/scripts/mutants/pi-floor.json +8 -10
  80. package/scripts/mutants/release-gate.json +3 -3
  81. package/scripts/mutants/v2-surface.json +4 -6
  82. package/scripts/raw-acp-compaction-measure/probe.ts +8 -2
  83. package/scripts/smoke-acp-cortex-live.ts +4 -408
  84. package/scripts/smoke-acp-ordering-probe-live.ts +7 -1
  85. package/scripts/smoke-acp-session-reuse-live.ts +11 -2
  86. package/scripts/smoke-acp-v2-send-live.ts +1 -1
  87. package/scripts/smoke-herdr-raw-install-live.sh +4 -4
  88. package/scripts/check-acp-cortex.ts +0 -710
package/CHANGELOG.md CHANGED
@@ -4,6 +4,173 @@ All notable changes to this project will be documented here. Format follows [Kee
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## 0.53.1 — 2026-11-14
8
+
9
+ ### What an npm user gets
10
+
11
+ 0.53.0 exists as a tag and a GitHub release only; it was never published to npm. For a user who installs from npm, 0.53.1 is the next version after 0.52.0, so everything under 0.53.0 below ships with it for the first time: the Claude ACP 0.106 set (#142), Cortex ACP disabled, the long-tool progress line (#162), and the verification documents. This section lists only what 0.53.1 adds on top.
12
+
13
+ ### Claude ACP 0.107 and a working manual `/compact` (#163)
14
+
15
+ - **Driver 0.107.0.** `@agentclientprotocol/claude-agent-acp` 0.106.0 → 0.107.0 and the transitive `claude-agent-sdk` 0.3.322 → 0.3.323; the ACP wire SDK stays 2.6.0 and the Pi 1.5.2 set is unchanged (`7c98f8b4`). Static reading of both tarballs found `steer()` moved to its own module and no compaction diff; the new surfaces are retracted tool calls and `rate_limit` `resetsAt`.
16
+ - **Manual `/compact` no longer refuses.** Every Pi-side summary on a Claude ACP model (`/compact`, the threshold, overflow recovery, `/tree` branch summaries) used to be refused by the tool-surface preflight, which read Pi's tool-less summary request as "read/bash/edit/write excluded"; this held since v0.24.0. A request with an empty replayed tool surface and `cacheRetention: "none"` is now Pi's summary request and runs as a one-shot turn on a new child with no tools, MCP servers, plugins, pre-approvals or setting sources, no augment and no notice, so the stored summary is exactly the model's text. An ordinary turn with every tool excluded still refuses. A `cancelled` stop that Pi did not abort is sealed as an error so Pi never keeps the partial text. After a compaction the session's retained Claude child is closed at once, and the next turn opens a new child from the compacted transcript (`5b7f7c24`, review corrections `7eb200a9`). Contract: `docs/acp-backend-rail.md` §11-10.
17
+ - **The automatic threshold is not changed**, and the compaction inside a prompt the backend itself runs stays the backend's.
18
+
19
+ ### ACP tool visibility closer to Pi (#163, extends #162)
20
+
21
+ - **M1 — running command.** The `[tool:running]` line names the command instead of "Terminal" once the title arrives; a beat in the same update prints alone.
22
+ - **M2 — output preview.** A finished call previews at most 5 lines and 400 bytes of its output: head on success, tail on failure, nothing when the one-line summary already holds it, indentation kept.
23
+ - **M3 — backend compaction.** The backend's own compaction shows trigger, tokens before and after, duration and failure on one `[acp: compaction …]` line, once.
24
+ - **Control codes.** Every notice and preview line is cleaned the way Pi cleans tool output (ANSI/OSC and C0 controls removed), plus DEL and C1; the mapper's expression is compared against Pi's installed functions in a test (`e96403ec`, `f25c78de`). Contract: §11-11.
25
+ - All new lines are signed, so they stay out of transcript replay, the reuse signature and andenken `control-v1` embedding. They are display-only.
26
+ - Frames follow 0.107.0 as read, not a live capture.
27
+
28
+ ### Verification documents (0.53.1)
29
+
30
+ - `BASELINE.md` and `VERIFY.md` each open with "Why this exists" (GLG's account: why the interview checks a pi-sized Claude, and why a session that passes becomes the examiner in the replicant-to-replicant walk).
31
+ - `VERIFY.md` §1B.7a adds the manual `/compact` cell: Pi's own cut threshold (a transcript estimate of `keepRecentTokens`, default 20000, after the first user message; not Claude's occupancy), seven observations c0–c6, and `UNMEASURED` recording when compaction cannot be reached.
32
+ - Both files shrink: BASELINE.md 38211 → 18318 bytes, VERIFY.md 120927 → 120815 bytes. The retired optional rounds, question IDs, answer guide, paused agy and Cortex baselines and the long release-host rows moved verbatim to `docs/baseline-receipts.md` ("Superseded / retired material"), which is read on GitHub and is not in the npm package.
33
+
34
+ ### Verification run on this candidate (R2R, 2026-11-14)
35
+
36
+ n=1 on one host (oracle), run by an examiner session on this candidate (`a80518d1`) with GLG typing `/compact` himself; the full record is in `docs/baseline-receipts.md`.
37
+
38
+ - **BASELINE blind pass: PASS** (subject `262958`; the sibling it opened, `b3e007`, passed the carrier part with a NOTE). Both called themselves "Claude Code"; GLG ruled that is not a defect. A memory question drew an `update-config` mention: NOTE.
39
+ - **VERIFY §1B.2–5 and §1B.8: pass. §1B.6 effort, §1B.7 ESC, §1B.9 gates, c6 cancel and footer %: not measured.**
40
+ - **§1B.7a manual `/compact`:** c0 split turn with two summary children pass; c1 summary clean (0 notice or control characters) pass; **c2 old child closed before the next prompt: PASS** (two observers; the summary children's appearance is shown by transcript, not a live `ps`); c3 new bootstrap from the summary pass; c4 code word and latest fact correct (quality observation); c5 "non-use observed, provided tool set unobserved". Short context (Pi about 40k, Claude about 250k), so not long-run durability.
41
+ - **Found and fixed here:** VERIFY's description of which bridge bytes are live was half true (D2), and the §1B.8 `jq` comment "notices only" also matched the new tool lines (D3). **Left for the next lane:** the source-checkout bridge runs `src/` through strip-types while AGENTS.md Rule 11 says `run_ts` is the sole TS crossing (D1, wording is GLG's).
42
+
43
+ ### Herdr preparation
44
+
45
+ Carried from 0.53.0: while 0.53.1 is unpublished, `runtime-lock.json` stays on the closed `herdr-checkout` verification carrier and no npm 0.53.1 bytes or integrity are invented. The last published npm pin remains 0.52.0.
46
+
47
+ ### Not changed
48
+
49
+ A steer or stop to a busy ACP sibling still waits for the whole ACP turn (§11-9); no steering injection and no stop verb were added. The stop means is the local ESC.
50
+
51
+ ### Release evidence
52
+
53
+ The candidate is `a80518d1` (the documentation diet, WHY sections and manual `/compact` cell) on top of `7a100e89` (main after the #163 land) and the release-record edits of this section. Floors ran on that tree before this section's evidence was written; the seal below binds the tree they ran on, and the make step's M0 floor covers the committed prepared HEAD.
54
+
55
+ - P4 (deterministic floor), seal `f9d5acae58318dd4` (before = after; sha256 of HEAD + `git diff --binary` + `git diff --cached --binary` + untracked sha256sums, first 16 hex; no untracked files): `pnpm run build-bridge` rc=0 and byte-identical to the preserved dist manifest, then `pnpm run check:full` exit 0 in 978s. Log SHA-256 `f661de593de259721452e8fd14bc541aee2760d10aedae780d2948e12108e9f8`. This change moved no gate, mutant or matrix, so no PARTIAL group applies.
56
+ - P5 (LIVE `release-gate --cut`) on the same seal, 2026-11-14: MUST 24 PASS / 0 FAIL / 0 SKIP, BEHAVIOR 1 PASS / 0 FAIL / 0 SKIP; `cut: OK`, rc=0, 1280s. Log SHA-256 `2a0d59b799610cdf5bc3210f25363d2c47079b4b1e74993bcfaaea46853be2db`; scratch `/tmp/entwurf-release-gate-0.53.1.ie8IEn`.
57
+ - `smoke-codex-fresh-live` ran against an app-server started for this cut (`entwurf codex-app-server`, pid 1047942, in the tmux session `codex-as-0531`, separate from the gate's session), stopped after the run. Codex model `gpt-6.1-terra`, pi-side `openai-codex/gpt-6.1-terra`. No exception was used.
58
+ - P9 after P5: reclaimable roots 0, nothing deleted. One reparented `/tmp` process, the Emacs daemon running since November 9. About 103 roots each of `mux-resume-call-pd`, `herdr-resume-pd-pkg`, `herdr-resume-pd-nolauncher` and `herdr-resume-call` remain (87 after the 0.53.0 gate); they come from the beside-behaviour `*resume-call.test.ts` files, outside the owned-prefix scan. Recorded, not deleted.
59
+ - Kill-power re-measured at this shipped SHA: none (all committed claims not re-proved, #144).
60
+ - Earlier-candidate PARTIAL (operator-attested, not this SHA): head f25c78dea35d surface 59cf75be0f02 -- ["bash","run.sh","check-acp-set-model-readback"] 44/44 receipt 32bd052290f7
61
+ - Earlier-candidate PARTIAL (operator-attested, not this SHA): head f25c78dea35d surface 59cf75be0f02 -- ["bash","run.sh","check-acp-prompt-lifecycle"] 15/15 receipt e6cf8a16e881
62
+ - Earlier checkpoints, binding their own trees: #163 branch frozen FULL green at `17244d48`; main `7a100e89`, exact-SHA CI run 43570025312, four required jobs success.
63
+ - Exact prepared-SHA CI and the artifact acceptance belong to make and produce their own receipts.
64
+
65
+ ## 0.53.0 — 2026-11-13
66
+
67
+ ### Claude ACP 0.106 (#142)
68
+
69
+ Entwurf 0.53.0 moves the Claude ACP rail to driver `@agentclientprotocol/claude-agent-acp` 0.106.0 and wire SDK `@agentclientprotocol/sdk` 2.6.0 (from 0.90.0 / 1.8.0), with `claude-agent-sdk` 0.3.322 as one coherent set. The 0.52.0 Pi SDK 1.5.2 set is unchanged.
70
+
71
+ - **Curated rows.** `entwurf/claude-fable-5-2` joins the curated Claude ids; the set-model readback confirms it answers its own row. Supported Claude rows declare text-only input, because the rail sends an image only as an `[image omitted]` marker and has no path for image bytes. Cortex ACP is disabled: its old rows are not registered; exact Entwurf fresh/resume admission and the ACP adapter refuse retired Cortex ids without a Claude fallback. Existing Cortex configuration and credentials are untouched.
72
+ - **No compaction behind pi.** The driver's 0.101 idle compaction is disabled through inline `settings.idleCompaction: false`, so context never changes behind pi. A pi compaction still rebuilds the ACP session from pi's summary and recent messages; it is not a continuation of the vendor transcript.
73
+ - **Thinking as effort.** Pi thinking levels map to ACP effort (low..max; off and minimal are not offered). A new session sets effort after the set-model readback and confirms the driver's answer; a reused session re-sets only on change, and the operator sees `[acp: effort <v> read back]`. No level or an unmapped one rejects as `acp-thinking-level-unsupported`. A readback is not evidence of speed or depth.
74
+ - **Cancel.** An abort while a reused session waits for a changed effort's answer now settles at once, sends no prompt and drops the session (previously it waited up to the 30 s bootstrap bound). After a cancelled turn settles, the operator sees whether the ACP session continues or the next message opens a new one. A rebuilt transcript that follows an aborted assistant turn carries one cause-neutral status line: the turn was cut, actions may already have taken effect, and cancellation is not rollback.
75
+ - **Late updates.** A reused session installs its turn's update handler only when its own prompt goes out, so a late update from the previous, cancelled turn is no longer sealed as the new turn's answer. Inside the prompt window `session/update` carries no turn id, so that part still rests on the adapter.
76
+ - **Not measured.** An ESC during text streaming, Edit/Write effects of a cancelled turn, a real keypress or wire cancel frame, n>1 cancel trials, and canonical resume after a restart.
77
+
78
+ ### Fresh-call tool names on ACP Claude (D1)
79
+
80
+ A pi sibling opened by `entwurf_fresh_call` on a curated ACP Claude model (`entwurf/claude-*`) runs its turns inside the Claude Agent SDK and sees the bridge as `mcp__entwurf-bridge__*`, but its first-turn framing named Pi's `mcp__entwurf_bridge__*` spelling. The framing now takes the launch model and names the Claude spelling for exactly those ids; the load hint stays absent. Thinking-suffixed or fuzzy ACP ids are already refused at the dispatch root (#128). At the time, Cortex rows kept the Pi spelling because their spelling was unmeasured on this host; those rows are now retired. Found in the ACP Sonnet interview of the VERIFY walk; a LIVE fresh call on `entwurf/claude-sonnet-5-5` (n=1) called back through `mcp__entwurf-bridge__entwurf_callback`, and its first user message carried only the Claude spelling.
81
+
82
+ ### Verification documents
83
+
84
+ - `VERIFY.md` opens with Part I, the self-run walk an ACP session executes on itself (closed allow list, turn map, examiner re-measure list), ahead of the release floors in Part II and history in the appendix. Its first run (ACP Opus 5.5, n=1) passed every measured turn with no blocker; effort, ESC and gate turns were not measured.
85
+ - `BASELINE.md` opens with the core interview (Q-B0 and Q-B0-CARRIER) and its grading; dated #147/#157 host receipts moved to `docs/baseline-receipts.md`.
86
+ - The reuse documentation says that only a resident pi (`entwurf pi`, `--entwurf-control`) reuses an ACP session; plain `pi` and `pi -p` are turn-scoped.
87
+
88
+ ### Herdr preparation
89
+
90
+ An npm lock must name the checkout's own package version, so while 0.53.0 is unpublished `runtime-lock.json` returns to the closed `herdr-checkout` verification carrier, as in the 0.52.0 preparation. No npm 0.53.0 bytes or integrity are invented and the plugin manifest version is unchanged. The last published npm pin is 0.52.0; a re-pin to measured npm 0.53.0 bytes is separate work after publication. Moving an npm-activated host to the checkout source requires explicit deactivate first.
91
+
92
+ ### Cortex ACP disabled
93
+
94
+ The `entwurf` ACP provider is Claude-only. Retired `cortex-*` ids are not registered; exact fresh/resume admission refuses them, and the ACP adapter refuses a Cortex id or a settings `backend: cortex` as `cortex-acp-disabled` before any child or overlay starts, with no Claude fallback. A dormant `cortexConnection` alone does not block Claude. The Cortex LIVE smoke and its gate are removed. Pi's own fuzzy `--model` selection outside Entwurf's launch seams is not governed by this change.
95
+
96
+ ### A long ACP tool shows that it is still running (#162)
97
+
98
+ A long Bash in an ACP Claude sibling used to show only `[tool:start] Terminal` and a spinner until it finished; one real run sat that way for over seven minutes. claude-agent-acp 0.106.0 sends a running tool's elapsed time every 30 seconds with no client capability required, and the mapper dropped it. Each beat now renders as `[tool:running] <command> — 30s` (then `1m`, `1m30s`, …). The line is display-only: it stays out of transcript replay and the reuse-compat signature, and it is hidden with the other tool notices. It carries no partial output, because the adapter sends a foreground command's stdout only with its completion, even to a client that declares `_meta.terminal_output`. Both facts were measured on raw ACP frames on 2026-11-13. A steer to a busy ACP sibling still waits for the whole ACP turn (#163); that is separate work.
99
+
100
+ ### Release evidence
101
+
102
+ This candidate is `9c5fc2b` (the #162 progress fix) on top of `6402c6a` (a gate race fix), `93eb879` (Cortex ACP disabled) and the earlier preparation `1e487f7`, plus these release-record edits.
103
+
104
+ - P4 (deterministic floor) on `9c5fc2b` (seal `e6ea1dae9ccc9598`, before = after): `pnpm run check:full` exit 0 in 998s. Log SHA-256 `d546384f34e4f6e07764f205842aa0f22808361b2f16b0d581235f074618a83f`. The first P4 on the same seal (r4) was RED only at `check-bridge-delivery`: the gitignored bridge dist predated the mapper edit. `pnpm run build-bridge` repaired it with no tracked change, so the seal did not move. The #162 change added a beside-behaviour test and changed no gate, mutant or matrix, so no PARTIAL group applies.
105
+ - P5 (LIVE `release-gate --cut`) r5 on `9c5fc2b` (same seal, before = after), 2026-11-14: MUST 24 PASS / 0 FAIL / 0 SKIP, BEHAVIOR 1 PASS / 0 FAIL / 0 SKIP; `cut: OK`. Log SHA-256 `aa9d504ebf3b7a4ce05001f83e2d3606d1719531884a704b498e109393688b75`.
106
+ - `smoke-codex-fresh-live` ran against an app-server started for this cut (`entwurf codex-app-server` in a dedicated tmux session, pid 3803464), after the vendor-managed Codex daemon that held the default socket with a dead seat pane was stopped. Kernel join: `owned: LISTEN inode 121523791 held by pid 3803464 (codex) fd 31`. Codex model `gpt-6.1-terra` (`ENTWURF_CODEX_FRESH_PI_MODEL=openai-codex/gpt-6.1-terra`). 0.53.0 carries Codex LIVE acceptance; no exception was used.
107
+ - Earlier runs on this lane were RED and are preserved, each binding its own tree:
108
+ - r1 (`93eb879`, managed daemon pid 3110547): the Codex step failed because the daemon's inherited `TMUX_PANE` named a pane that no longer existed. An exception was first proposed and then withdrawn in favour of this re-measure.
109
+ - r2 (`c020d20`, pid 3803464): `check:full` failed at `COPILOT-RECEIVE-DOCTOR-UNREADABLE-ENVIRON-IS-RED`, a fixed 400 ms wait for a fixture that was not yet ready under load, fixed in `6402c6a` to wait for the fixture's ready signal (affected PARTIAL `check-copilot-receive-arm` 20/20). The Codex sibling (`gpt-6-luna`) called back with one character of the nonce missing, so the exact-nonce check correctly refused it.
110
+ - r3 (`6402c6a`, `gpt-6.1-terra`): Codex passed (66 assertions); `check:full` failed once at `check-meta-doctor-oracle` P3 (one claim not found after the mode refusal). Three standalone runs and the r5 floor passed; the cause is not isolated and is recorded as an intermittent under host load.
111
+ - P9 after r5: two `entwurf-s2b-overlay` roots reclaimed (164K). One reparented `/tmp` process, the pre-existing Emacs daemon from November 9. About 87 roots each of `mux-resume-call-pd`, `herdr-resume-pd-*` and `herdr-resume-call` remain from the beside-behaviour `*resume-call.test.ts` files, outside the owned-prefix scan; recorded, not deleted.
112
+ - The receipts below are from the earlier preparation at `1e487f7`, before the Cortex ACP disable change. They do not certify this candidate.
113
+ - Pre-version checkpoint: `234a92a`, push run 43390591770, all four required jobs success (`check`, `install-surface`, `artifact-consumer`, `macos-install-surface`).
114
+ - #142 branch checkpoints carry their own frozen FULL and affected PARTIAL results in their commit bodies (`90b5168`, `ac087af`, `6059fe6`, `28f1dd8`); those bind their own trees, not this SHA.
115
+ - P4 (deterministic floor): the candidate (HEAD `234a92a` plus the release edits and the reuse-smoke fix later committed as `1950815`, seal `d05cafb932a2d12b`) took `pnpm run check:full` r3, 971s, exit 0, seal unchanged. r1 was RED at `check-herdr-plugin-build` (`runtime-lock-incoherent`: the Herdr lock still pinned npm 0.52.0 against package 0.53.0) and was repaired by the Herdr preparation above; r2 passed before the smoke fix moved the tree. The managed bridge rebuild produced a byte-identical dist.
116
+ - P5 (LIVE `release-gate --cut`), r2 on the same seal, 2026-11-13: MUST 22 PASS / 1 FAIL / 1 SKIP, BEHAVIOR 1 PASS / 0 FAIL / 0 SKIP; `cut: BLOCKED`. Log SHA-256 `e3666d1eb9529c602c031c9584b2e4f3aa4055452d96007b92cd6bc6024ec64d`.
117
+ - FAIL `smoke-mux-lifecycle-live`: the Claude Code sibling it opened showed `API Error: 403 Attention Required! | Cloudflare` on its first turn and never called back; a vendor-side refusal, not an Entwurf defect. Re-measured standalone on the same seal: 86 checks passed, including the pi-on-ACP lane (exact callback, live send, live-resume refusal, same-id visible resume and recall). Log SHA-256 `e8b8b2b356096e7b4aae80204925139011bcf08d9f62075015d93eb2682d13b5`.
118
+ - SKIP `smoke-codex-fresh-live`: GLG chose not to supply the operator-owned Codex app-server pid and models for this cut, so the Codex fresh-call MUST step was unmeasured on that tree. `--cut` read that skip as a blocker; the Codex step was later measured green on this candidate (r5 above).
119
+ - r1 (earlier seal, 2026-11-13) was MUST 21 PASS / 2 FAIL / 1 SKIP. `smoke-acp-session-reuse-live` failed because the smoke called the backend with no thinking level and no registered `thinkingLevelMap`, which #142 refuses by design; fixed in `1950815` and passed in r2. `smoke-entwurf-chain-live` failed because its GPT hop (`openai-codex/gpt-5.6-luna`) transcribed the next citizen's garden id with one character missing and the decider refused it; no code changed, and it passed in r2. Gates that make a model copy a garden id by hand will occasionally go red this way. r1 log SHA-256 `0e18ea65404cda23de28f97a34f78f6db84820ce828313688766e80b5048af69`.
120
+ - P9 after P5: five `check-probe-ordering` roots reclaimed (176K). One reparented `/tmp` process, a pre-existing Emacs daemon from November 9. About 64 roots each of `mux-resume-call-pd`, `herdr-resume-pd-*` and `herdr-resume-call` remain; they come from the beside-behaviour `*resume-call.test.ts` files, outside the P9 owned-prefix scan. They are recorded, not deleted.
121
+ - Windows carrier and final artifact: produced and accepted in make (M3w) after green exact prepared-SHA CI.
122
+ - Kill-power re-measured at this shipped SHA: none (all 1532 committed claims not re-proved, #144).
123
+ - Earlier-candidate PARTIAL (operator-attested, not this SHA): head 7efa53565a4e surface 65eb09de0814 -- ["bash","run.sh","check-mux-fresh-call"] 162/162 receipt db6a288bf8b0
124
+
125
+ ## v2026.11.12-herdr.0.52.0 — Herdr npm runtime snapshot
126
+
127
+ This Herdr plugin snapshot pins the published `@junghanacs/entwurf@0.52.0` runtime and its measured npm sha512; it is not a new core release. The plugin manifest version remains independent of the runtime. A host switching from the checkout carrier to npm must explicitly deactivate before reinstalling; a settled npm-source host follows the existing rebind conditions. No operating host is switched automatically.
128
+
129
+ ### Evidence and boundaries
130
+
131
+ - The registry tarball SHA-256 `d053860c66ddd8b97ce4fdd49ac2a38605c2886ff62002a16582a36ac70bc5dd` matches the accepted core artifact byte for byte; independently computed sha512 matches the npm integrity and this lock. Core `v0.52.0`, its accepted artifact and npm bytes are unchanged.
132
+ - In a private sandbox, the registry-installed helper acquired npm 0.51.0, swapped to 0.52.0, and restored 0.51.0 before reacquiring 0.52.0 from a manually seeded torn-swap state. A repeat request acquired nothing; the owned runtime, cache and journal were removed. This was not recovery from an actual process kill.
133
+ - A separate private build-runner rehearsal acquired the real npm 0.52.0 runtime and activated Pi and Claude Code through its installed writers; the installed deactivate command completed. Only the integration status listing was a fixture. This is not a real Herdr registration, public-ref installation, vendor model turn or operating-host upgrade.
134
+ - On the earlier five-file candidate over `c015477a2f07`, diff `745f414d4f9d9cd1bbbc8d88562c8402d2a66454d4a14f58811ba7a9ffbc7b18`, the affected `check-dep-versions` PARTIAL killed 5/5 with both controls green; it is not kill-power measured on the eventual snapshot SHA. Public-ref installation and exact pushed-SHA CI require their own receipts.
135
+
136
+ ## 0.52.0 — 2026-11-12
137
+
138
+ ### Pi SDK 1.5.2 (#158)
139
+
140
+ Entwurf 0.52.0 moves the exact ten-member Pi SDK set from 1.5.0 to 1.5.2 and declares host Pi `>=1.5.2 <1.6` (#158). At preparation time, the published npm baseline remains 0.51.0 / SDK 1.5.0; its marked installation recipes remain independent of this source candidate. The checkout's Herdr lock returns to the existing verification carrier rather than claiming unpublished npm 0.52.0 bytes. Source-checkpoint, preparation, operating and final-artifact evidence remain distinct, and no #155 receipt transfers to this release.
141
+
142
+ - **Exact SDK set.** All ten `@earendil-works/*` members move from 1.5.0 to exactly 1.5.2, with the lockfile, the carrier's SDK manifest, the `run.sh` pin and probes, and the mutant pin literals. Measured on the registry tarballs: SHA-512 and SHA-1 match for all ten, and every one of the 16 member-to-member production edges is exactly 1.5.2. Two non-member dependency changes against 1.5.0: `pi-coding-agent` drops `grok-mermaid` 0.2.3 for `lovely-mermaid` 0.3.3, and `chord` adds an optional peer `react` 19.3.0. Whether either reaches an Entwurf consumer is not measured.
143
+ - **Release-age exception.** The operator explicitly approved on 2026-11-11 an exception for exactly the ten SDK members at 1.5.2, added to `minimumReleaseAgeExclude`. The global release-age policy and the release-age treatment of other dependencies are unchanged.
144
+ - **Maintainer: Chord `Context`.** The two owned type imports move from `@earendil-works/chord` to `@earendil-works/chord/context` for Chord's new root export; the carrier is regenerated with the official emitter, not edited by hand. Typecheck and consumer results belong to this candidate's own receipts.
145
+ - **Scheduler.** SDK 1.5.2 carries the 1.5.1 scheduler notification fix. In an isolated six-member comparison using a faux provider, with no vendor-model calls or authentication, the unchanged upstream repro stayed stuck in 10 of 10 SDK 1.5.0 runs and settled in 10 of 10 SDK 1.5.2 runs. The public-API-only variants settled on both versions and did not reproduce the old race. This is bounded fixture evidence, not Entwurf carrier, operating-session, native SQLite or load-sweep acceptance.
146
+ - **Native SQLite.** In an isolated cross-version fixture, 1.5.2 reopened a 1.5.0-written database without changing its bytes, appended 60 parallel tool calls and compacted, and a close and reopen stayed consistent; the schema version stayed 2. Operating-scale sessions, an interrupted write, a non-checkpointed WAL and concurrent access are not measured. A package downgrade is still not a data rollback.
147
+ - **Documentation.** The install guide and Herdr README retain narrow published-scope regions for npm 0.51.0 (SDK 1.5.0), while the ACP row explicitly labels the source candidate's SDK 1.5.2 declaration. The durable guide gains a short candidate boundary covering ordinary Pi cache warming and the durable edit path, which this candidate does not change. The guide's `unreadable generation` advice now distinguishes reader-version skew from a genuinely unreadable generation.
148
+ - **Herdr preparation.** An npm lock must name the checkout's own package version. While 0.52.0 is unpublished, this preparation returns `runtime-lock.json` to the existing closed `herdr-checkout` verification carrier, without inventing npm 0.52.0 bytes or integrity and without changing the plugin manifest version. Published 0.51.0 recipes retain their SDK 1.5.0 subject. An installed npm host keeps its existing runtime until an explicit source switch; deactivate before selecting the checkout source. A later re-pin to measured npm 0.52.0 bytes is separate work after publication.
149
+ - **Preparation status.** The pre-version source checkpoint and later #159 candidates have separate frozen floors and receipts. An addon-less validation tarball was installed on one operating host; the operating coordinator returned under the same identity and exchanged a nonce. The subsequent P5 Native/LIVE run and final carrier-bearing artifact acceptance remain separate. Operating-scale or interrupted sessions and all-rail behavior are not certified by the bounded SDK fixtures.
150
+
151
+ ### Peer message replies (#159)
152
+
153
+ Peer messages distinguish a requested result sent to its routed recipient from a final answer in the local session. Reply guidance preserves no-send instructions and does not impose an acknowledgment merely because an address is replyable.
154
+
155
+ ### Release evidence
156
+
157
+ - Pre-version checkpoint: `b9fa0d2`. Its CI status is not recorded here. The preceding source worktree over `669315ccb22a` took frozen FULL r2, 971s, exit 0, after the initial stale-dist refusal was preserved and a managed bridge build completed. Its recorded index is `800cce5f40a67808145810ef14e5852ea091d1c5`, patch `e006e8032c045c40e6c06b1a94421348bbd2eedaa6a7a9eedcea8bbad7c022e8`; this is not the versioned 0.52.0 preparation's P4 or prepared-SHA CI. The branch handoff update followed that floor.
158
+ - #159 candidate on `b9fa0d2` with tracked diff `7f523c44042a` and fixture `217e8ef8920c`: frozen FULL 977s exit 0; carrier S/H contact 91, send 20, native-module 15 and receive 22; addon-less validation-TGZ Linux container and private ownership rehearsal passed. These receipts bind that earlier candidate, not later edits.
159
+ - Reviewed preparation candidate: HEAD `b9fa0d2aa43e`, tracked diff `8cbd3a3c9406e0f5c2c50878a23e52b088816f8feb0e0be9484cb462faf081d4`, untracked revision-20 fixture `217e8ef8920c09abe90cd2fe141a5b671ac94600ba6d2431fa056ea37c8fee42`. Frozen FULL ran 979s, exit 0, with unchanged seal; checkout carrier contact 91, send 19, native-module 14 and receive 21 passed (S/H only, vendor V not run). Addon-less validation TGZ `6c29185842806e3e14e28d3c2efd2da24c09e581772ed0a642277506565a60a1` passed Linux container acceptance; it is not the installed `d72afb…` TGZ or the final carrier artifact.
160
+ - Native LIVE (P5): on the same reviewed dirty candidate, `release-gate --cut` ran on 2026-11-12 13:03–13:24 KST, MUST 24 PASS / 0 FAIL / 0 SKIP and BEHAVIOR 1 PASS / 0 FAIL / 0 SKIP, exit 0, unchanged seal. Codex app-server A and fixture seat S were separate tmux sessions; models were `gpt-6-luna` and `openai-codex/gpt-6.1-terra`. Preserved log SHA-256 `e37c9e103be830e9446df5f981ae54d8078141bee5ca83fdd5b65d20188b656d`. The P9 immediate census observed one reparented `/tmp` process: a pre-existing Emacs daemon from November 9, not a P5 child; evidence and unclassified roots were preserved. This is not prepared-SHA CI or final artifact acceptance.
161
+ - Native Claude host: a fresh test-owned Claude Code session on the installed `d72afb…` validation root returned its exact callback and `entwurf_self`; its direct MCP child ran the installed 0.52.0 bridge, and installed `doctor-meta-bridge` passed while it was alive. Its own fixture was retired, with the record preserved. Sonnet was requested at launch; model usage for this particular turn was not independently extracted. The separate native-resume LIVE used `claude-sonnet-5-5` for both turns and passed 13 checks, with same-native-session marker recall.
162
+ - Installation-validation tarball (unpublished, addon-less): SHA-256 `d72afb38425c1dab8dd9a7c489274e1a76071aab73874d8ba94a896f55d8a3fd`; distinct from the final carrier-bearing artifact.
163
+ - Operating installation (2026-11-12): after normal owner exit and a consistent durable/ordinary-Pi backup, host Pi 1.5.2 and the addon-less validation tarball were installed; user-scope ownership moved to its root. The operating coordinator returned under the same garden/native ID with its original module and exchanged a nonce. This is one operating return, not all-rail or release acceptance.
164
+ - Windows and final artifact: at preparation time, the carrier-bearing artifact had not yet been produced or accepted; M3w follows green exact prepared-SHA push CI in make.
165
+ - Publication and Herdr npm re-pin: at preparation time, npm publication and its later Herdr re-pin remained separate human decisions.
166
+ - Kill-power re-measured at this shipped SHA: none (all 1516 committed claims not re-proved, #144).
167
+ - Earlier-candidate PARTIAL (operator-attested, not this SHA): head 669315ccb22a surface 3bceca54266b -- ["bash","run.sh","check-dep-versions"] 5/5 receipt 2280c96ec0a3
168
+ - Earlier-candidate PARTIAL (operator-attested, not this SHA): head 669315ccb22a surface 3bceca54266b -- ["bash","run.sh","check-pack-pin-matcher"] 2/2 receipt 7e64ab9bff6e
169
+ - Earlier-candidate PARTIAL (operator-attested, not this SHA): head b9fa0d2aa43e surface 60e424985df9 -- ["bash","run.sh","check-control-send-receipt"] 7/7 receipt 4df44c1e3e40
170
+ - Earlier-candidate PARTIAL (operator-attested, not this SHA): head b9fa0d2aa43e surface 60e424985df9 -- ["bash","run.sh","check-entwurf-v2-surface"] 20/20 receipt 490e9f96b8bd
171
+ - Earlier-candidate PARTIAL (operator-attested, not this SHA): head b9fa0d2aa43e surface 60e424985df9 -- ["bash","run.sh","check-mux-fresh-call"] 161/161 receipt fd3f4e91af7c
172
+ - Earlier-candidate PARTIAL (operator-attested, not this SHA): head b9fa0d2aa43e surface 60e424985df9 -- ["bash","run.sh","check-agent-guidance-beside"] 14/14 receipt d34e4f436e4a
173
+
7
174
  ## 0.51.0 — 2026-11-04
8
175
 
9
176
  Entwurf now runs on the Pi 1.5.0 SDK set (#155). The exact SDK closure grows from nine to ten members, the supported host Pi range moves to `>=1.5.0 <1.6`, and the pi-durable carrier follows the 1.5 durable API. An operating host moves to this version only through a planned cutover, because SDK 1.5's first write to a durable session is not readable by SDK 1.4.
@@ -84,6 +251,28 @@ The first five bullets record the plugin's re-pin to the published npm 0.50.0 ru
84
251
  - Earlier-candidate PARTIAL (operator-attested, not this SHA): head fe4780ee5c82 surface 811db89aeab8 -- ["bash","run.sh","check-pi-durable-carrier"] 59/59 receipt 0558e6e723a7
85
252
  - Earlier-candidate PARTIAL (operator-attested, not this SHA): head 434874ef6d6e surface b6cee8925072 -- ["bash","run.sh","check-pi-durable-carrier"] 66/66 receipt 822f2d8b950e
86
253
 
254
+ ### Final publication receipts — 2026-11-04 update
255
+
256
+ These receipts complete publication after the earlier-candidate measurements above. The core tag and published npm bytes remain unchanged; the Herdr follow-up below is a later source commit, not part of the tagged core artifact.
257
+
258
+ - **Shipping identity and CI.** Core `v0.51.0` is fixed at `32c31ea16487f9c8defa1ac07268b94d30ca5b27`. Its [push CI run 41704213407](https://github.com/junghan0611/entwurf/actions/runs/41704213407) passed all four required jobs: check, install-surface, artifact-consumer and macos-install-surface.
259
+ - **One accepted artifact.** [Windows producer run 41706422290](https://github.com/junghan0611/entwurf/actions/runs/41706422290) produced the canonical Windows-carrier TGZ, 11,710,142 bytes, SHA-256 `04fcce26d0a6dec8b8bb9a7f14a843eee0defb313aedafa34080600853d36e4d`. The producer's packed artifact, Windows-installed artifact and preserved download have the same hash. Linux accepted that same file without repacking. The candidate and its original acceptance receipts remain preserved; a carrier-bearing macOS install was not measured.
260
+ - **Human publication and registry proof.** npm records 0.51.0 at `2026-11-03T20:59:20.652Z`, after the operator's own publication. U2 restored the original pre-publication receipt (latest 0.50.0, repair 0.12.8-repair.1) and measured latest 0.51.0 with repair unchanged. The registry download is byte-identical to the accepted TGZ; its computed SHA-512 equals `dist.integrity`, and its SHA-1 equals `dist.shasum`. A private registry-installed Pi 1.5 consumer carried the same 668 files and listed the seven curated models without a model turn.
261
+ - **Evidence correction, not a hidden retry.** The post-publication wrapper sealed its log before appending a final 203-byte line. The original manifest remains 27 OK / 1 FAIL; its expected hash equals the current log with that final line removed. A separate, self-excluding correction receipt binds the current 31 files (SHA-256 `394becc3371c384fa96554b53e82c5a50cda8721424f54b21cedd2cd276d51cd`). No registry/install run or publication was repeated to conceal the seal-ordering defect.
262
+
263
+ ### Herdr post-publication follow-up — ce5a720
264
+
265
+ - **Published npm pairing.** [`ce5a720`](https://github.com/junghan0611/entwurf/commit/ce5a720) pins `@junghanacs/entwurf@0.51.0` with its measured registry SHA-512 and sets the plugin manifest to 0.51.0. The guides now describe the Pi 1.5.0 SDK set and host range `>=1.5.0 <1.6`; the README introduction includes retirement only on explicit request. Existing source-switch and same-source ownership conditions remain unchanged. The older prepare-time checkout-carrier statements above are historical, not the current main pin.
266
+ - **Source-specific private proof.** The registry-installed helper acquired real npm 0.50.0, swapped to 0.51.0, checked the compiled bridge, three executable bins, nine verbs and 668 byte-identical files, skipped acquisition on an exact re-request and removed its owned state. A separate manually seeded torn-state test restored the previous runtime before acquiring 0.51.0; it is not a real-kill experiment. A private build-runner journey activated pi/Claude Code through the installed package and its inverse removed the owned wiring/runtime, leaving the contracted empty Pi settings shell. This is not a public-ref Herdr plugin-registry journey.
267
+ - **Follow-up verification.** Sequential independent reviews and focused checks closed the six-file product/proof/documentation candidate over 32c31ea. The affected check-dep-versions PARTIAL killed 5/5 exactly once with their own QKs, both controls green and origin unchanged (receipt `c2edc00f5670a3915f0510b5b64eecd59119ed14e9691e05e0f1f7bc51ae1e44`); the other 1508 committed mutants were not executed. The frozen local FULL ran 963s, exit 0 / tee 0, with the seal unchanged; NEXT bookkeeping was reviewed afterwards. [Exact ce5a720 push CI run 41728277499](https://github.com/junghan0611/entwurf/actions/runs/41728277499) passed the four required jobs.
268
+ - **Not an operating rollout.** The operating GR208e remains the pre-D1 validation installation until the operator installs the accepted bytes and normally restarts the affected processes. Public-ref Herdr install/use/deactivation, a new plugin snapshot/tag and operating loaded-app acceptance remain separate, unmeasured steps. Neither this follow-up nor the release-note update moves the core tag, republishes npm or changes working citizens automatically.
269
+
270
+ ### Install-handoff incident and recovery — ThinkPad, 2026-11-04
271
+
272
+ - **Prepared is not installed.** The operator reported that the developer checkout had pulled `ce5a720` (SDK 1.5.0 source) while its dependencies were still SDK 1.4.0 and the prepared installation window was waiting for Enter. A local launch refused with `pi-durable-sdk-absent: carrier → @earendil-works/pi-schema wants 1.5.0, resolves nothing`. The installation had not run: its result file and backup did not yet exist. This was an approval-wait/install-completion handoff gap, not evidence of an SDK regression or lost conversation. The launcher correctly refused incomplete supply instead of opening the session with a mixed SDK set.
273
+ - **Recovery evidence, reported from that host.** After the operator explicitly authorized the installation, the ThinkPad coordinator reported `result.exit=0`, a complete 41-file native-profile backup whose source-before/backup/source-after manifests matched, unchanged global policy, host Pi 1.5.0 and a verified exact SDK 1.5.0 closure (27 physical edges). It returned under the same garden/native session identities; the old owner was absent, and the new owner and direct compiled bridge resolved through the intended checkout. The receipt states that the installer itself opened no operating session. The actual invocation of the prepared resume script was not asserted. These are the remote host's measurements, not an Oracle re-run or general rollout proof; the over-50-active-entry and conversation-switch UI cases were not re-measured there.
274
+ - **Reusable handoff rule.** Say prominently whether the installer has actually run or is still waiting for approval. A prepared window, a pulled source tree or a printed resume command is not installation success. Before presenting reopening as ready, require the installation's recorded exit 0 and coherent carrier/SDK verification; then use the intended same-session selector and original explicit native module. Keep normal old-owner exit and the consistent complete backup before the first new-SDK write. Never send Enter or install automatically to bypass the operator's approval.
275
+
87
276
  ## 0.50.0 — 2026-11-02
88
277
 
89
278
  Same-id resume now reaches every resumable backend on both launch rails. A dormant pi, pi-durable or Claude Code citizen reopens under its own garden id in a visible tmux window or, inside Herdr, a new Herdr tab, with no fallback from one rail to the other (#157). The CLI gains one description source, safe help and a thin `entwurf claude` entry (#153, continued in #157).
@@ -897,7 +1086,7 @@ is recorded as dated evidence, not as a release gate.
897
1086
  - `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.
898
1087
  - 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.
899
1088
  - 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.
900
- - 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.
1089
+ - 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](./docs/baseline-receipts.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.
901
1090
 
902
1091
  ### Internal retirement checkpoints (#147; before public composition)
903
1092
 
@@ -1042,7 +1231,7 @@ is recorded as dated evidence, not as a release gate.
1042
1231
  once each: dormant delivery refused, native identity and transcript preserved across the
1043
1232
  promptless resume, blind recall correct. n=1; not a release-gate MUST, ACP, Herdr, Windows,
1044
1233
  release-artifact or flush/descendant claim
1045
- ([BASELINE](./BASELINE.md#147-native-round-trip-2026-10-22-n1),
1234
+ ([BASELINE](./docs/baseline-receipts.md#147-native-round-trip-2026-10-22-n1),
1046
1235
  [#147](https://github.com/junghan0611/entwurf/issues/147#issuecomment-6329217980)).
1047
1236
  - Kill-power re-measured at this shipped SHA: none (all 1173 committed claims not re-proved,
1048
1237
  #144).
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, pi-durable or Claude Code siblings ([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, pi-durable or Claude Code siblings ([capability table](./README.md)), with the garden id as their address. The ACP plugin runs on the pi host; Claude is its supported backend, and Cortex ACP is disabled. Codex remains a native-push citizen, not an ACP backend. A backend owns its authentication, transcript and native tools; the plugin narrows only surfaces its actual adapter can configure.
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
 
@@ -18,7 +18,7 @@ These are enforced by code, gates, and review. Do not weaken them in a PR; if yo
18
18
  2. **Session persistence**: only `pi:<sessionId>` is persisted. `cwd:<cwd>` is never persisted.
19
19
  3. **MCP injection**: only via `entwurfProvider.mcpServers`. No ambient `~/.mcp.json` scanning, no `~/.claude/settings.json` MCP inheritance.
20
20
  4. **Operating surface, not config inheritance**: the user's filesystem Claude Code config (`~/.claude/settings.json` hooks, env, plugins, `permissions.defaultMode`) is intentionally *not* inherited. Skills come from `skillPlugins`; callable tools are shaped by `tools` / `disallowedTools`, and `permissionAllow` still rides the inline Claude settings. The overlay authors `permissions.defaultMode: "bypassPermissions"` so an unattended ACP turn cannot suspend on an interactive prompt; this does not bypass backend authentication. `CLAUDE_CONFIG_DIR` enforces the isolation even where the SDK reads filesystem independently of `settingSources`.
21
- 5. **Backend-specific knobs stay explicit and namespaced**: retired Codex/Gemini-era ACP knobs are not carried on the current path. A backend that needs its own knob uses the `ENTWURF_ACP_*` namespace, and invalid values must throw, never fall back — cortex followed this with `ENTWURF_ACP_CORTEX_CONNECTION` (the renamed `PI_SHELL_ACP*` legacy var), and its settings key rides `adapterSettings`, not the common config.
21
+ 5. **Backend-specific knobs stay explicit and namespaced**: retired Codex/Gemini-era ACP knobs are not carried on the current path. A backend that needs its own knob uses the `ENTWURF_ACP_*` namespace, and invalid values must throw, never fall back — Cortex's former setting is historical and does not enable a disabled backend.
22
22
  6. **Bridge does not implement compaction**: When a backend compacts natively, the pi session and mapping survive that. Pi-side JSONL compaction must not be presented as backend-transcript reduction, and backend-specific compaction controls belong to the backend's own native interface. Legacy `PI_SHELL_ACP_*` compaction knobs must not reappear.
23
23
  7. **Backend coverage honesty**: changes to operating surface, session lifecycle, or persistence must state which shipped/probed backend surfaces they cover. A claim that silently drops a covered backend is a regression; if one backend is genuinely not covered, record that carve-out explicitly.
24
24
  8. **This bridge is not a second harness**: no prompt reconstruction, no transcript hydration, no tool result ledger, no Claude Code emulation.
@@ -47,10 +47,10 @@ manual — the hook does not run them. The full aggregate is `LIVE=1 ./run.sh re
47
47
  ## What gets PRs rejected
48
48
 
49
49
  - adds ambient MCP discovery (project `.mcp.json`, `~/.mcp.json`, etc.) without an explicit `entwurfProvider.mcpServers` opt-in path
50
- - inherits user / project / local backend config by default (i.e. flips `settingSources` away from `[]`, drops the `CLAUDE_CONFIG_DIR` overlay, or weakens cortex's session-scoped HOME containment)
50
+ - inherits user / project / local backend config by default (i.e. flips `settingSources` away from `[]` or drops the `CLAUDE_CONFIG_DIR` overlay)
51
51
  - weakens `resume > load > new` (e.g. silently downgrading to `new` without a logged invalidation reason)
52
52
  - introduces `console.warn` / silent fallback where the bridge should `throw` (see `AGENTS.md` "Never warn. Throw.")
53
- - changes a backend operating surface (tools, skills, MCP, permissions, sandbox) without accounting for both shipped backends (Claude, Cortex) or recording an explicit carve-out
53
+ - changes a supported backend operating surface (tools, skills, MCP, permissions, sandbox) without accounting for the affected production contract
54
54
  - adds a second transcript ledger, a prompt reconstruction layer, or any state that competes with pi's session as the source of truth
55
55
  - skews version pins across `package.json`, `run.sh`, and `README.md` (the `check-dep-versions` gate catches this; if it complains, fix all three)
56
56
 
package/DELIVERY.md CHANGED
@@ -72,7 +72,7 @@ checkout carried this command does not know it, and its generic error answer is
72
72
  CC pidfd helper observes one fd-pinned process, not a conversation, descendants or flush;
73
73
  unknown never grants safe replay. Package/source presence, compiled consumer checks and a
74
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
75
+ is [BASELINE's 2026-10-22 n=1 round trip](./docs/baseline-receipts.md#147-native-round-trip-2026-10-22-n1). Historical delivery receipts below do
76
76
  not certify these candidate components.
77
77
 
78
78
  ## Levels (D0–D8)
@@ -134,7 +134,7 @@ physical host. Do not read a D-level cell as a Darwin receipt.
134
134
  | **OMP (`omp`) garden citizen** | shipped in 0.16.0; send + receive + visible fresh accepted on one host | D6; D3 proven; D7 partial; D8 partial | Two in-process extensions in the operator's own TUI: birth mints the `mode === "tui"` host (subagents mint nothing) and names it as sender; the RECEIVER unit joins that citizen in the SAME process, holds an `fs.watch` on its mailbox signal, and rings an announce-only doorbell through the vendor's `pi.sendUserMessage` — measured to be on the FACTORY object, not the event ctx, and measured to start a turn on an idle host with zero typing (`agent_start` +31ms). `wakeMode` is `self-fetch`: the model drains with `entwurf_inbox_read` and THAT read is the receipt. **D6 is the LIVE acceptance of 2026-08-30** (oracle, omp 18.0.0) — garden `20260830T140819-116f6a`, `lastEnqueuedAt 05:08:20.555Z` / `lastReadAt 05:08:23.958Z`, and the citizen's own transcript carrying `mcp__entwurf_bridge_entwurf_inbox_read` for its own garden id. **D3 is PROVEN, not pending**: with two live omp citizens armed, one addressed enqueue rang exactly one doorbell and the sibling persisted no transcript and kept an empty mailbox. D7 is PARTIAL (`lastReadAt` needs no scraping; the reply does). D8 is PARTIAL — dedupe and every stale-handling path are implemented and hermetically pinned, ordering/loop-guard/crash-recovery are not. The `/new` unarm is the rail-specific one: the watch lives in the operator's TUI, so pid + start-key cannot see a citizen change underneath a living process, and without an explicit unarm the previous garden id would keep reading deliverable. Requires `tools: xdev: false` in `~/.omp/agent/config.yml` — the vendor default hides MCP tool schemas from the prompt, so the doorbell would name a tool the model cannot call. The decisive receipt lines — the ordering probe, the D6 chain, the D3 isolation and the `/new` unarm — are pasted into `scripts/raw-omp-measure/README.md` §M7 rather than left in a host-local `/tmp` path. Evidence level L4: one Linux host, ARM. **Visible fresh (step 9) is ACCEPTED — the clause 7 LIVE went green on 2026-08-30:** `entwurf_fresh_call` opens omp on all three public surfaces through the bare `omp` runtime with an explicit `--approval-mode yolo` width and the `mcp__entwurf_bridge_entwurf_v` callback name, behind a five-axis pre-mutation preflight whose fifth axis is omp-specific (`tools.xdev !== true`, without which the model cannot call the callback tool at all). **The first turn is a TWO-STAGE BOOTSTRAP rather than a positional prompt, and that is a measured correction, not a preference.** `[LIVE 2026-08-30]` the positional-prompt candidate opened its window and minted its citizen (garden `20260830T181342-452167`, native `01a051f2-3107-7147-8806-fa2a6f527610`), delivered the byte-identical framing as a user message at `09:13:42.413Z`, and the model answered the literal text `ACK` at `09:13:47.105Z` with ZERO tool calls; the caller timed out at 240s. `[source]` the interactive UI defers MCP discovery (`sdk.ts:1847-1855`, `:1881-1905`) while the positional `initialMessage` prompts straight after `mode.init()` (`main.ts:540-565`), and `[측정]` an observer on the same runtime saw `turn_start` at +654ms with the entwurf tools absent and the callback tool present only at +1484ms. So the launcher now carries `{v,target,nonce,task}` on the fixed registered flag `--entwurf-bootstrap`, and the in-process birth extension polls `getAllTools`(`source:"mcp"`) AND `getActiveTools` for the exact callback name, sends a callback-ONLY prompt, arms the task only on a `tool_result` whose stored `toolCallId`, tool name, target, nonce and `isError === false` all match, and DELIVERS it at the next `turn_end` of that same session. `[LIVE 2026-08-30]` that last boundary is itself a measured correction: a first attempt sent the task from inside the `tool_result` handler with an explicit `deliverAs: "followUp"`, the hook log showed the full chain (`bootstrap-armed` → `bootstrap-ready` +440ms → `bootstrap-callback-observed` → `bootstrap-released`), and the task still never appeared in the session — `[source]` an explicit `deliverAs` queues without starting a turn in either state, while the omitted form starts one when idle (`agent-session.ts:6511-6513`), which the same transcript confirmed three seconds later when the Bundle B doorbell's omitted-option send landed and started a turn. `[측정 2026-08-30]` the callback-only half is what was proven to work: model `openai-codex/gpt-5.6-sol`, tool live at +1105ms, prompt injected at +1107ms, and the sibling calling `mcp__entwurf_bridge_entwurf_v` with the exact nonce (`omp-cb-btkvva4r87` → `20260830T184054-1aa1f2`, `meta-mailbox → enqueued`). **The clause 7 acceptance, `smoke-omp-fresh-live` (release-gate MUST), 2026-08-30, 21 assertions, omp 18.0.0 / `openai-codex/gpt-5.6-sol`:** launch through `tools/call entwurf_fresh_call` with nonce `mux-fresh-call-34faea228f3c3638684b40ff`; sibling garden `20260830T192913-df52b9` taken from the CALLBACK's sender envelope and never from the launch receipt; exactly one new citizen (§3.5); addressed `entwurf_v2` → `meta-mailbox → enqueued`; `lastEnqueuedAt 10:29:19.179Z` / `lastReadAt 10:29:24.673Z`; the drain visible in that session's own transcript for its own garden id. **Both bootstrap stages are in that transcript in order** — the callback-only prompt at offset 970, the caller's task at 4732, no four-backend positional framing anywhere, and an assistant message after the task proving it started a turn rather than sitting in a queue. The unit's own log carries the state machine: `bootstrap-armed 10:29:13.399Z` → `bootstrap-ready 10:29:13.819Z` (+420ms) → `bootstrap-callback-observed 10:29:18.663Z` (`toolCallId=call_KZJtkxfzy1IEE4ejKutCPWcm|fc_0858…`) → `bootstrap-released 10:29:18.731Z` → `bootstrap-task-sent 10:29:18.759Z`. Evidence level L4: one Linux host, ARM, one run. `check-harness-admission-parity` keeps the deterministic half of the admission from being a matter of memory. What this does NOT establish: multi-host, multi-model, or repeated fresh calls in one process. **Cross-harness leg, 2026-08-31 (first bidirectional live-turn roundtrip on the committed bytes + operator redeploy):** a claude-code citizen (`20260831T090152-f998ac`) opened a fresh omp sibling through the public surface (nonce `mux-fresh-call-807cb693b1913ce98ffdbfd1`, callback sender garden `20260831T124226-eac41a`), dispatched an addressed `entwurf_v2` → `meta-mailbox → enqueued`, and the omp citizen's own live turn drained and replied into the claude mailbox — its self-report (doorbell → `entwurf_inbox_read`; callback-only first user message, task second) agrees with every receipt on the chain. |
135
135
  | **pi-durable native host** | shipped in 0.31.0 (source-runtime route; carrier route since 0.32.0, see `docs/adding-a-harness.md`), receipt below from the 0.31 route; visible fresh + addressed receive + both cross-harness legs accepted on one Linux host (2026-10-06, `smoke-pi-durable-fresh-live`, 36 assertions, exit 0) | D6 (D3/D4 shown); D7 partial; D8 unproven | The operator-provided pinned source runtime (`cd32f77` + overlay) launched by the managed `entwurf pi-durable --provider … --model … --width task-wide`; the contact registers six tools and spawns the compiled bridge as a direct child; receive is announce-only self-fetch (doorbell → root submission → `entwurf_inbox_read`). Receipt (V on both sides, `openai-codex/gpt-6.1-sol`): real Pi `20261006T223710-e51e21` opened pd `20261006T223720-ba0c08` through `entwurf_fresh_call`; pd's first action called back into Pi with the exact nonce; Pi's live turn → pd mailbox ENQUEUE `2026-10-06T13-37-35-446Z-b57c69.msg`, that message's doorbell submission `done` on pd's root conversation, drained by pd's live turn (`entwurf_inbox_read` of its own id, settled); pd's live turn → Pi `entwurf_v2` settled `control-socket → sent` (native tool-result, joined by call id) and landed as exactly one Pi row with the expected payload and pd as the anchored sender. Native offering (root `pi.system`, toolsAdded/toolsRemoved applied): the six contact tools + bash/read/edit/write/subagent; pd's first root tool call is the callback. Actual model from root `pi.assistant` rows; the generation checkpoint does not retain `request.model` after completion. |
136
136
  | **Copilot CLI TUI+server** — *withdrawn lane, kept as evidence* | rejected | D7; D8 unproven | Older official-SDK probe over hidden `--ui-server`; idle enqueue worked, but loopback RPC authentication was not established. The bundled extension supersedes this candidate without reviving it. |
137
- | **ACP Claude / Cortex** | shipped runtime, outside this matrix | — | ACP sessions are children launched by entwurf's pi adapter, not already-running native sessions to wake. |
137
+ | **ACP Claude** | shipped runtime, outside this matrix | — | ACP sessions are children launched by entwurf's pi adapter, not already-running native sessions to wake. Cortex ACP is disabled. |
138
138
 
139
139
  “Verified probe” means the transport worked in a reproducible raw probe but entwurf
140
140
  does not yet own lifecycle, installation, doctors, or release acceptance for it.
package/ENTWURF-CLI.json CHANGED
@@ -231,7 +231,7 @@
231
231
  {
232
232
  "synopsis": "release-gate [project-dir] [--cut] [--allow-skip-gemini]",
233
233
  "column": 69,
234
- "summary": "SINGLE release gate: full static (pnpm run check:full) + the v2-native live gates (v2 matrix-live, check-bridge, doctor-pi-provider, RGG) + the ACP plugin acceptance floor (12 LIVE smokes: socket-citizen/raw-turn/overlay/provider/session-reuse/carrier-augment/memory-containment/rgg/mcp/skill/bundled-mcp/v2-send) + the one surviving axis the aggregate used to omit silently (claude-native-resume; Cortex stays a documented on-demand direct call) + the cross-harness delivery chain (smoke-entwurf-chain-live) + the Codex Pi -> visible Codex -> visible Pi receipt chain (smoke-codex-fresh-live; initial Pi and the Codex it opens in one session S, explicit operator-owned app-server PID in a DIFFERENT session — that separation is the lane B claim). TWO-TIER summary: MUST (release-blocking, owns the exit code — \"green\" applies here) + BEHAVIOR (advisory, non-blocking: RGG positives model-in-loop turn). STEP OUTCOME protocol: every step is INVOKED and reports its own PASS / SKIP (exit 97, a prerequisite it does not have) / FAIL — a skip is never counted as a pass. Without --cut this is the unattended diagnostic (SKIPs reported, exit 0). WITH --cut it is read as release acceptance and ANY MUST SKIP is red, which is what makes \"a CUT needs LIVE=1, SKIP=0\" executable instead of prose. --allow-skip-gemini accepted-but-ignored (back-compat). final cut authorization is GLG's."
234
+ "summary": "SINGLE release gate: full static (pnpm run check:full) + the v2-native live gates (v2 matrix-live, check-bridge, doctor-pi-provider, RGG) + the ACP plugin acceptance floor (12 LIVE smokes: socket-citizen/raw-turn/overlay/provider/session-reuse/carrier-augment/memory-containment/rgg/mcp/skill/bundled-mcp/v2-send) + the one surviving axis the aggregate used to omit silently (claude-native-resume; Cortex ACP is disabled) + the cross-harness delivery chain (smoke-entwurf-chain-live) + the Codex Pi -> visible Codex -> visible Pi receipt chain (smoke-codex-fresh-live; initial Pi and the Codex it opens in one session S, explicit operator-owned app-server PID in a DIFFERENT session — that separation is the lane B claim). TWO-TIER summary: MUST (release-blocking, owns the exit code — \"green\" applies here) + BEHAVIOR (advisory, non-blocking: RGG positives model-in-loop turn). STEP OUTCOME protocol: every step is INVOKED and reports its own PASS / SKIP (exit 97, a prerequisite it does not have) / FAIL — a skip is never counted as a pass. Without --cut this is the unattended diagnostic (SKIPs reported, exit 0). WITH --cut it is read as release acceptance and ANY MUST SKIP is red, which is what makes \"a CUT needs LIVE=1, SKIP=0\" executable instead of prose. --allow-skip-gemini accepted-but-ignored (back-compat). final cut authorization is GLG's."
235
235
  },
236
236
  {
237
237
  "synopsis": "check-bridge",
package/ENTWURF.json CHANGED
@@ -6,8 +6,14 @@
6
6
  "editing": "Preserve decoded strings exactly unless an explicit semantic amendment is intended. Review related consumers and independent oracles atomically. Accepted payload changes advance revision; history-only edits, routine releases and unrelated code changes do not. schemaVersion tracks reader/structural compatibility. A slotted hint holds only the text around its slot: the slot value (for record-less-socket, the fresh-cut command in both invocation forms) is supplied by its code owner and never copied here. Metadata is not delivered to models."
7
7
  },
8
8
  "schemaVersion": 6,
9
- "revision": 19,
9
+ "revision": 20,
10
10
  "history": [
11
+ {
12
+ "revision": 20,
13
+ "source": "b9fa0d2aa43ebefc1c3bd5bc864c84965b52289a",
14
+ "issue": "https://github.com/junghan0611/entwurf/issues/159",
15
+ "change": "Align delivery descriptions with completion and reply routing while preserving receipt, rail, and lifecycle boundaries."
16
+ },
11
17
  {
12
18
  "revision": 19,
13
19
  "source": "2734f524bfeca6eb1a0ae092494d45576af9ebef",
@@ -126,11 +132,11 @@
126
132
  "tools": {
127
133
  "entwurf_v2": {
128
134
  "descriptions": {
129
- "mcp": "CANONICAL DELIVERY SURFACE for garden ids: message, reply, or hand off to whoever an id names. The id alone does not say which rail that citizen answers on. Give target + intent; the decider picks transport from liveness (live socket citizen → control-socket send; deliverable self-fetch citizen → meta-bridge mailbox; probe-alive native-push citizen → direct injection into its conversation) and reports ONE outcome, named per rail: a control receiver's acceptance boundary (`sent` / `queued-steer` / `queued-follow-up` / `accepted-unknown-boundary` — those four, or `mailbox-enqueued` on a re-resolved mailbox leg), a mailbox ENQUEUE receipt, a native-push INJECTION, a rejection, or lock-dirty. This receipt is not the colleague's reply or evidence of reading. EXISTING targets only; discover with entwurf_peers. A live socket can receive fire-and-forget. unsupported means only \"no control-socket probe,\" not reachability. The decider resolves the actual rail at dispatch time: a self-fetch mailbox only while deliverable, native-push direct injection only while its adapter probe is alive, or a THIRD RESULT: rejection when neither holds. An inactive self-fetch citizen is mailbox-undeliverable; native-push has NO mailbox: dead → native-push-target-dead; indeterminate → native-push-probe-indeterminate; agy (paused, #152) → native-push-paused, no probe. A dormant socket rejects this delivery verb as dormant-fire-forget-unsupported. owned-outcome was withdrawn. Only on an explicit operator request, entwurf_resume_call may visibly reopen a proven-dormant Pi, pi-durable or Claude Code citizen under the same id, submitting no prompt; that lifecycle is separate from delivery. LOCK: taken for a control-socket-DOMAIN dispatch. The mailbox and native-push rails are lock-free — deliverability and the adapter probe guard them. mode applies to a CONTROL-SOCKET send only; other plans carry no mode. wants_reply rides every rail. message caps at 16000 chars; send an artifact path + digest for more.",
130
- "durable": "Send a message to an existing garden citizen by garden id through the entwurf-bridge (intent fire-and-forget). Returns the bridge's delivery receipt, or fails with its named rejection. This receipt is not the colleague's reply."
135
+ "mcp": "Send, reply or hand off to an existing garden id; the decider selects the live rail (live socket citizen → control-socket send; deliverable self-fetch citizen → meta-bridge mailbox; probe-alive native-push citizen → direct injection into its conversation) and reports ONE outcome, named per rail: a control receiver's acceptance boundary (`sent` / `queued-steer` / `queued-follow-up` / `accepted-unknown-boundary` — those four, or `mailbox-enqueued` on a re-resolved mailbox leg), a mailbox ENQUEUE receipt, a native-push INJECTION, a rejection, or lock-dirty. A receipt is not a reply or proof of reading. A local final is not delivery: when asked to reply, call entwurf_v2 for the requested recipient (normally the replyable sender); honor routing and no-send instructions. Discover existing targets with entwurf_peers. A live socket can receive fire-and-forget; unsupported means only \"no control-socket probe,\" not reachability. For a target without a live socket, the THIRD RESULT is rejection if neither mailbox nor native-push is available. An inactive self-fetch citizen is mailbox-undeliverable; native-push has NO mailbox: dead → native-push-target-dead; indeterminate → native-push-probe-indeterminate; agy (paused) → native-push-paused, no probe. A dormant socket rejects this delivery verb as dormant-fire-forget-unsupported. This delivery verb never launches or resumes a process. Only on an explicit operator request, entwurf_resume_call may visibly reopen a proven-dormant Pi, pi-durable or Claude Code citizen under the same id, submitting no prompt; that lifecycle is separate from delivery. A control-socket-DOMAIN dispatch takes a target lock; mailbox and native-push rails are lock-free. mode applies only to a CONTROL-SOCKET send. wants_reply requests a response without authorizing an action or requiring an automatic acknowledgment; an absent or false marker does not cancel a request in the message. message caps at 16000 chars; send an artifact path + digest for more.",
136
+ "durable": "Send, reply or hand off to an existing garden id through entwurf-bridge (intent fire-and-forget), returning a delivery receipt or named rejection. The receipt is not a reply or proof of reading. For a requested reply, send to the authorized recipient, normally the replyable sender; a local final is not delivery. Honor routing and no-send instructions; an absent or false wants_reply does not cancel a request, and an address alone needs no ACK."
131
137
  },
132
138
  "parameters": {
133
- "intent": "fire-and-forget = send/reply/hand-off to an existing target after a current rail check. unsupported is not a reachability verdict; the decider picks a rail or REJECTS (self-fetch → mailbox when deliverable, else mailbox-undeliverable; native-push → alive: direct injection, dead: native-push-target-dead, indeterminate: native-push-probe-indeterminate; a paused backend — agy, #152 — rejects as native-push-paused before any probe); set wants_reply to request an answer, not to wait for one. This is the ONLY intent: owned-outcome, which resumed a dormant citizen by launching a hidden background child, was withdrawn under the visible-first rule. It is not selectable, not deprecated-but-tolerated; a dormant socket citizen is currently unreachable by this verb and rejects as dormant-fire-forget-unsupported.",
139
+ "intent": "fire-and-forget sends, replies or hands off to an existing target after a current rail check. unsupported is not a reachability verdict: self-fetch uses a deliverable mailbox or rejects as mailbox-undeliverable; native-push injects when alive, rejects dead as native-push-target-dead and indeterminate as native-push-probe-indeterminate; paused agy rejects as native-push-paused before probing. wants_reply requests a response, not a wait. This delivery verb never launches or resumes a process; a dormant socket rejects as dormant-fire-forget-unsupported.",
134
140
  "message": "Message / prompt to the colleague. In familiar language and natural sentences, convey what matters now and the context they need. Keep identifiers and evidence exact; trim repetition, not meaning. Hard cap 16000 chars; for larger payloads send a file/artifact path plus digest.",
135
141
  "mode": "Injection style for a CONTROL-SOCKET send only: steer (ask the receiver's steering queue) or follow_up (ask its follow-up queue). NEITHER is an interrupt: a busy receiver drains steering after each turn and follow-ups only when its inner loop ends, so a later steer overtakes every earlier follow_up and there is no order between the two. Both queues are volatile process memory — an abort drops what is in them. The receipt names which queue accepted the message (`queued-steer` / `queued-follow-up`); an idle receiver answers `sent`, meaning the turn was TRIGGERED, not that the model has seen the text. The mailbox and native-push plans carry no mode, so it has no effect on those rails.",
136
142
  "target": "Target garden id (use entwurf_peers to discover)",
package/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # entwurf
2
2
 
3
- `entwurf` connects independent agent harnesses as visible siblings. Open a fresh sibling, or reopen
4
- or message an existing one by its **garden id**. Every harness keeps its own runtime,
5
- authentication, tools and transcript; Entwurf adds identity, delivery, receipts and named
6
- lifecycle verbs.
3
+ `entwurf` connects independent agent harnesses as visible siblings. Open a fresh sibling, or reopen,
4
+ message or retire an existing one by its **garden id**—retirement only on your explicit request.
5
+ Every harness keeps its own runtime, authentication, tools and transcript; Entwurf adds identity,
6
+ delivery, receipts and named lifecycle verbs.
7
7
 
8
8
  ![entwurf — a forged screwdriver for visible sibling sessions](docs/assets/entwurf-hero.jpg)
9
9
 
@@ -22,8 +22,9 @@ A recorded source-checkout demo: callback → task → native Bash → reply.
22
22
  disposable worker or a subagent of a new central harness. You and the native harnesses keep
23
23
  steering; branches, worktrees, file isolation and internal delegation stay their concern.
24
24
  - **Native harnesses stay native.** Claude Code keeps its hooks and tools, Codex its own threads and
25
- delegation, pi its extensions. Entwurf reconstructs no prompt, hydrates no transcript and mediates
26
- no credential.
25
+ delegation, pi its extensions. Entwurf hydrates no native transcript and mediates no credential.
26
+ The one prompt it composes is the ACP plugin's: a new ACP session receives pi's own transcript
27
+ rendered as text ([rail](./docs/acp-backend-rail.md#adapter-contract)).
27
28
  - **One address.** A garden id names a record-backed citizen. A pane, socket, native session id or
28
29
  model is a carrier or an observation, never a second address.
29
30
  - **The same verbs on both screens.** In an ordinary tmux session or inside a Herdr workspace, a
@@ -201,7 +202,9 @@ identity, routes, roles, permissions or lifecycle. `entwurf help team`.
201
202
  **Entwurf** (기투, projection-of-self) connects independent visible siblings; a **garden id** names
202
203
  a record-backed citizen, not its pane or native transcript. The package holds the v2 core, the
203
204
  native-harness bridges, a pi adapter and an ACP plugin. ACP is one ingress, not the boundary; pi is
204
- one adapter, not the center. Claude and Cortex Code are ACP backends; Codex and Antigravity stay
205
+ one adapter, not the center. Claude is the supported ACP backend; Cortex Code ACP is disabled in
206
+ this source. Already-running processes keep their loaded bytes until an operator restarts them.
207
+ Codex and Antigravity stay
205
208
  native so they keep their own tools and work context. The pi adapter registers the compiled bridge
206
209
  with Pi's built-in MCP after record birth, while pi's own receive stays its record-addressed control
207
210
  address. [FAQ](./FAQ.md) explains ACP, MCP and context carriers.
@@ -222,7 +225,7 @@ the MCP tool descriptions and the hints extracted there, [ENTWURF-CLI.json](./EN
222
225
 
223
226
  Owns: garden identity, live-fact dispatch and receipts, native bridge integrations,
224
227
  visible lifecycle launch seams, the pi adapter and isolated ACP plugin lifecycle.
225
- Does not: a second harness, memory DB, prompt reconstruction, transcript hydration,
228
+ Does not: a second harness, memory DB, native-transcript hydration or replay,
226
229
  credential mediation, subscription bypass, pane-typing delivery or hidden orchestration.
227
230
  [AGENTS](./AGENTS.md) owns these invariants and exact capability boundaries.
228
231