@junghanacs/entwurf 0.14.0 → 0.14.2
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.
- package/AGENTS.md +13 -2
- package/CHANGELOG.md +63 -0
- package/DELIVERY.md +57 -0
- package/README.md +16 -7
- package/VERIFY.md +4 -4
- package/demo/README.md +3 -1
- package/demo/demo-baseline.sh +12 -1
- package/demo/demo.sh +9 -1
- package/docs/acp-backend-rail.md +103 -4
- package/docs/external-mcp-host.md +1 -1
- package/docs/setup-clean-host.md +3 -3
- package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +12 -5
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/classify-tmux-cwd.js +47 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +45 -3
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-resume-call.js +18 -47
- package/mcp/entwurf-bridge/dist/scripts/doctor-pi-provider.js +139 -47
- package/mcp/entwurf-bridge/dist/scripts/probe-bridge-command.js +294 -0
- package/mcp/entwurf-bridge/src/index.ts +14 -5
- package/mcp/entwurf-bridge/tsconfig.build.json +15 -5
- package/package.json +9 -9
- package/pi-extensions/entwurf-control.ts +13 -4
- package/pi-extensions/lib/acp/backend.ts +229 -9
- package/pi-extensions/lib/classify-tmux-cwd.ts +50 -0
- package/pi-extensions/lib/mux-fresh-call.ts +57 -4
- package/pi-extensions/lib/mux-resume-call.ts +21 -53
- package/run.sh +70 -25
- package/scripts/agy-bridge-config.py +47 -13
- package/scripts/agy-bridge.sh +73 -23
- package/scripts/check-acp-prompt-lifecycle.ts +221 -9
- package/scripts/check-entwurf-bridge-boot.ts +28 -0
- package/scripts/check-gate-qualification.ts +5 -3
- package/scripts/check-mux-resume-call.ts +11 -10
- package/scripts/check-probe-bridge-command.ts +201 -0
- package/scripts/check-release-gate-outcomes.ts +54 -1
- package/scripts/doctor-pi-provider.ts +155 -51
- package/scripts/meta-bridge-state.py +75 -1
- package/scripts/mutants/acp-prompt-lifecycle.json +25 -3
- package/scripts/mutants/bridge-command-boot.json +107 -0
- package/scripts/mutants/meta-retire.json +47 -0
- package/scripts/mutants/mux-fresh-call.json +48 -4
- package/scripts/mutants/mux-resume-call.json +3 -3
- package/scripts/mutants/release-gate.json +13 -0
- package/scripts/probe-bridge-command.ts +330 -0
- package/scripts/raw-async-delivery/README.md +158 -1
- package/scripts/raw-async-delivery/copilot-ui-server-probe.mjs +337 -0
- package/scripts/smoke-acp-raw-turn-live.ts +1 -1
- package/scripts/smoke-agy-install-state.sh +76 -2
- package/scripts/smoke-entwurf-chain-live.ts +12 -4
- package/scripts/smoke-entwurf-v2-matrix-live.ts +2 -2
- package/scripts/smoke-meta-install-state.sh +169 -3
- package/scripts/smoke-mux-fresh-call-live.ts +1 -1
- package/scripts/smoke-mux-lifecycle-live.ts +1 -1
- package/scripts/smoke-pi-provider-state.sh +135 -6
- package/scripts/smoke-resident-garden-guard.sh +2 -2
package/AGENTS.md
CHANGED
|
@@ -30,7 +30,7 @@ For agents that own this repo: invariant principles and reproducible verificatio
|
|
|
30
30
|
- **pi adapter** attaches a pi session to a record at `session_start`, hosts the record-keyed control socket, and exposes the native pi tool surface.
|
|
31
31
|
- **Native bridges** register already-running native sessions without taking over their transcript or auth: Claude Code is mailbox/self-fetch; Antigravity is probe-backed native-push. Codex has archived probe evidence, but its managed native lane was declined because pi already supplies the official GPT provider path; do not duplicate it as a native citizen or ACP backend.
|
|
32
32
|
- **ACP plugin** registers provider `entwurf` inside a pi host session and drives a backend under an isolated overlay. The host pi session is already a record-backed socket citizen; the plugin does not mint another citizen/socket/peer layer.
|
|
33
|
-
- **mux is launch-only and deliberately small.** Shipped: the tmux placement leaf (`mux-placement.ts` — inspect/append/close inside the caller's own session), the visible runtime launch composition (`mux-launch.ts`), the fresh-call composition (`mux-fresh-call.ts`), and the cwd-aware resume placement composition (`mux-resume-call.ts`). Fresh call is exposed as `entwurf_fresh_call`; visible same-id resume is `entwurf_resume_call`, composed at the two public surfaces by injecting `mux-resume-call` into the v2-side `entwurf-v2-visible-resume.ts`. The exact import graph is enumerated in [docs/mux-launch-rail.md](./docs/mux-launch-rail.md) §11. `entwurf_v2` behavior is unchanged and delivery still never imports launch. Fresh call learns a new sibling's garden id from the CALLBACK it makes, never from a lookup — so the pre-injected-token → identity-lookup design (rail §6) is **closed, not paused**. Do not reopen it without new evidence and explicit GLG re-approval. Fresh-call requires one explicit model and passes it in each runtime's measured CLI dialect (Pi `--model <provider/model>`, Claude Code `--model=<id-or-alias>`); resume takes only an existing target id and gets transcript/model/provider/cwd from its record. Do not grow either narrow carrier into a generic driver, harness profile, arbitrary command/
|
|
33
|
+
- **mux is launch-only and deliberately small.** Shipped: the tmux placement leaf (`mux-placement.ts` — inspect/append/close inside the caller's own session), the visible runtime launch composition (`mux-launch.ts`), the fresh-call composition (`mux-fresh-call.ts`), and the cwd-aware resume placement composition (`mux-resume-call.ts`). Fresh call is exposed as `entwurf_fresh_call`; visible same-id resume is `entwurf_resume_call`, composed at the two public surfaces by injecting `mux-resume-call` into the v2-side `entwurf-v2-visible-resume.ts`. The exact import graph is enumerated in [docs/mux-launch-rail.md](./docs/mux-launch-rail.md) §11. `entwurf_v2` behavior is unchanged and delivery still never imports launch. Fresh call learns a new sibling's garden id from the CALLBACK it makes, never from a lookup — so the pre-injected-token → identity-lookup design (rail §6) is **closed, not paused**. Do not reopen it without new evidence and explicit GLG re-approval. Fresh-call requires one explicit model and passes it in each runtime's measured CLI dialect (Pi `--model <provider/model>`, Claude Code `--model=<id-or-alias>`); it also takes ONE optional literal absolute `cwd` (#73 — omitted/`""` means the caller's own directory; no trim, no realpath, no project-name resolver; classified by the shared `classify-tmux-cwd.ts` leaf; the receipt echoes the REQUEST only), so a cross-repo fresh sibling is a fresh-call fact and never a reason to resume a dormant record. Resume takes only an existing target id and gets transcript/model/provider/cwd from its record. Do not grow either narrow carrier into a generic driver, harness profile, arbitrary command/env selection, or a second creation API. Ownership and import prohibitions: [docs/mux-launch-rail.md](./docs/mux-launch-rail.md) §11.
|
|
34
34
|
- **One delivery verb:** `entwurf_v2` addresses an existing garden id. Current routes are live control-socket send, active self-fetch mailbox enqueue, and probe-alive native-push. NO route starts a process: the hidden background resume for a dormant citizen was withdrawn under the visible-first rule, so a dormant in-domain citizen rejects as `dormant-fire-forget-unsupported` and the intent axis is single-valued. Every other complementary state pair rejects honestly too. Fresh creation is a separate verb — `entwurf_fresh_call` — and it returns a launch receipt only; the new sibling's address arrives asynchronously as the sender envelope of its nonce callback.
|
|
35
35
|
|
|
36
36
|
## Hard Rules
|
|
@@ -101,6 +101,17 @@ A `--entwurf-control` pi session is a citizen for the same reason a native bridg
|
|
|
101
101
|
- Sender envelope: `{ sessionId, agentId, cwd, timestamp, origin?, replyable? }`.
|
|
102
102
|
- Human-opened and spawned/resumed siblings use the same addressing and messaging semantics.
|
|
103
103
|
|
|
104
|
+
## Issue queue — a manual sweeper, not a backlog
|
|
105
|
+
|
|
106
|
+
- OPEN issues are live contracts only, capped at five. A sixth means something closes first; the cap does not bend.
|
|
107
|
+
- A slot is earned by a current defect or executable contract, not by importance, age, or possible future value.
|
|
108
|
+
- Direction, philosophy, frozen invariants and observations without a current action live in `ROADMAP.md`, durable docs, or closed history.
|
|
109
|
+
- Nothing stays open "in case." If a closed problem recurs, it returns as a new issue carrying the new evidence.
|
|
110
|
+
- Anything whose only value is knowing it gets moved to the document that owns it, then closed.
|
|
111
|
+
- A new issue brings the best available observation plus an executable next measurement. Recovering a missing signature may be the first acceptance; an idea with neither evidence nor a next measurement is not an issue.
|
|
112
|
+
- No collection points, umbrella trackers, or fallout buckets. Merge issues only when they share one cause and one acceptance.
|
|
113
|
+
- Sweep manually after a release and before opening an issue. Solved work closes at its durable SHA; it does not wait for the next release.
|
|
114
|
+
|
|
104
115
|
## Verification
|
|
105
116
|
|
|
106
117
|
Two axes are required: deterministic/package gates and opt-in LIVE evidence.
|
|
@@ -169,7 +180,7 @@ implement → affected focused gates → independent review → one amendment bu
|
|
|
169
180
|
- Every `.ts` file belongs to one typecheck fence: root emit-capable config, MCP strip-types config, or scripts strip-types config. Do not hide files with `exclude`.
|
|
170
181
|
- Root pi extensions import TypeBox through `@earendil-works/pi-ai`; do not mix direct `@sinclair/typebox` types.
|
|
171
182
|
- MCP/scripts use explicit `.ts` imports where Node strip-types requires them. Installed operator surfaces route to compiled JS.
|
|
172
|
-
- pi runtime range is `>=0.84.
|
|
183
|
+
- pi runtime range is `>=0.84.2 <0.85` with devDep exact `0.84.2`; re-evaluate loader aliases and `/compat` at every minor ceiling. The ceiling moves on measurement, never on assumption, and a previous bump's argument is never reused: at 0.83.0→0.84.0 `compat.ts` was still byte-identical but `loader.ts` was NOT, so the diff itself had to be read and judged reachable-or-not. Per-bump hashes, diff judgments, and reachability findings live in the ROADMAP **Dep bump(별도 트랙)** ledger — keep them there, not here.
|
|
173
184
|
- ACP pins are recorded in `package.json` and checked by `check-dep-versions`/`check-acp-sdk-surface`; do not describe a dependency bump as a behavioral fix without evidence.
|
|
174
185
|
|
|
175
186
|
## Working Style
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,69 @@ All notable changes to this project will be documented here. Format follows [Kee
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## 0.14.2 — 2026-08-20
|
|
8
|
+
|
|
9
|
+
This patch makes bridge availability a property of the exact invocation each harness will run, preserves child-exit facts across ACP transport closure, and records Copilot delivery as probe evidence without admitting a new citizen rail.
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- **ACTION REQUIRED — the certified runtime floor is now Pi `0.84.2`, with Claude ACP adapter `0.70.0`.** Pi's exact development pin and closed peer range move to `0.84.2` / `>=0.84.2 <0.85`; Claude ACP `0.70.0`, ACP SDK `1.3.0`, and Claude Code `>=2.1.217` are the measured support coordinates. Re-run setup after upgrading so the installed package and stable bridge launcher agree with this release. (#79)
|
|
14
|
+
- **Every live-spend harness default is now `openai-codex/gpt-5.6-luna`.** The cross-harness chain, the v2 matrix, mux fresh/lifecycle, the resident garden guard, and the `entwurf-dev` skill's Pi default all name the cheaper model; the `ENTWURF_LIVE_TARGET` / `ENTWURF_CHAIN_GPT_TARGET` / `SMOKE_RGG_MODEL` overrides are unchanged. Fixture model strings are deliberately untouched — they assert exact argv or routing and spend nothing. This is a cost decision, not a gate change: no step moved tier and the LIVE gate was re-earned on the new default rather than inherited. Antigravity has no harness-side model at all (the operator opens that conversation), so its free-account fence — `gemini-3.6-flash`, never a Pro tier — is recorded in `VERIFY.md` and the `run.sh` help.
|
|
15
|
+
- **Pi and Antigravity doctors boot the exact configured stdio invocation.** Runtime truth is separate from repair ownership: every effective Pi entry, including an unowned override, is probed without being overwritten; Antigravity preserves its configured `command`, `args`, and `env`. A valid MCP `initialize` response must arrive before `notifications/initialized` and `tools/list`, and the returned surface must equal the seven public Entwurf verbs. Closes #81.
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- **A direct-native Copilot raw probe records one bounded Linux observation without claiming support.** The current probe binds a unique marker body to `user.message.interactionId`, then to one `assistant.turn_start.turnId`, and accepts only assistant events from that turn; missing or ambiguous identity fails closed, the control session rejects any `user.message` or `assistant.*` event, and cleanup is bounded. The earlier 2026-08-19 L4 observation used a chronological slice on one workstation and its stdout was not archived, so it is not evidence that the corrected named-turn contract has run LIVE. Copilot remains outside `MetaIdentity`, backend registries, `entwurf_v2`, native-push, fresh, and resume; admission work is tracked in #82.
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- **ACP prompt failures no longer lose child exit facts when transport EOF arrives first.** A one-shot child-end latch gives an already-failed turn a bounded post-mortem settle before Entwurf teardown, preserving the original backend error plus lifecycle phase, exit code, signal, stderr tail, or an honest bounded absence. It adds no running-prompt timeout, replay, watcher, supervisor, or recovery API; #72 remains open for the natural retained-child death cause.
|
|
24
|
+
- **A configured bridge cannot pass because its name resolves, its defaults boot, or it answers `tools/list` before initialization.** Pi and Antigravity reject dead overrides, argument/environment-specific failures, invalid invocation shapes, malformed initialize replies, missing/extra verbs, and foreign or relocated launchers while retaining the rule that Entwurf never clobbers a launcher it does not own.
|
|
25
|
+
- **The release gate boots the operator's CONFIGURED Pi bridge invocation before it reaches the LIVE tier.** `check-bridge` only proves the launcher this checkout ships, so a relocated or shimmed `entwurf-bridge` that `command -v` resolves while `exec` returns 127 used to stay invisible until sixteen LIVE steps and real model spend later. `doctor-pi-provider` is now a release-gate MUST `run_step` — not LIVE-gated, with no skip arm — so that class fails in about a second instead of after a model turn. (#81 follow-up)
|
|
26
|
+
- **The bridge probe preserves the launcher's own stderr across fast exit and asynchronous stdin `EPIPE`.** It installs the pipe error guard before the first write, consumes newline JSON-RPC frames once, and waits for process exit plus stderr end before issuing the exit verdict, so a Node stack trace cannot replace the diagnostic the operator needs.
|
|
27
|
+
|
|
28
|
+
### Verification
|
|
29
|
+
|
|
30
|
+
- **Landing SHA `d0fb8e6a37d401fc5ef660c90c1051db4b0811e8`** passed exact-SHA GitHub Actions run [32230953648](https://github.com/junghan0611/entwurf/actions/runs/32230953648): `check`, `install-surface`, and `artifact-consumer` all concluded success. At that SHA the combined landing candidate passed focused bridge 11/11, Pi provider 52/52, Antigravity 177/177, qualification **184/184 killed**, and `pnpm run check:full` in 315s before push. Those two numbers belong to `d0fb8e6` and are kept as its record — they are not this release's shipped figures.
|
|
31
|
+
- **The accepted 0.14.2 candidate** passed qualification **185/185 killed** — the `release-gate` lane grew 11 → 12 with `PI-DOCTOR-IS-RELEASE-MUST`, added by `877b4da` — and `pnpm run check:full` in 207s standalone / 209s inside the gate (remeasured 2026-08-20; `run.sh` is a mutant subject, so the pre-edit 311s does not describe this tree). **185 is the shipped inventory.**
|
|
32
|
+
- **`LIVE=1 ./run.sh release-gate /tmp/entwurf-release-gate-0.14.2.c5VqTP --cut` — MUST PASS=21 FAIL=0 SKIP=0, BEHAVIOR PASS=1 FAIL=0 SKIP=0, `cut: OK`.** Log: `/tmp/entwurf-release-gate-0.14.2.c5VqTP/release-gate.log` (SHA-256 `27346d86be4a1a96a8ea8cab97687fcce807e4fa4bd6e3d179b91f85dbbcbe53`). Both model-in-loop lifecycle steps ran on the new default: `smoke-entwurf-chain-live` and `smoke-mux-lifecycle-live` passed with `openai-codex/gpt-5.6-luna`, so the cheaper default is proven LIVE rather than assumed. Cortex stayed the documented on-demand axis and is not part of this aggregate.
|
|
33
|
+
- The new hermetic `check-probe-bridge-command` lane requires sequential initialization, exact tool equality, stderr preservation, bounded cleanup, and the stdin `EPIPE` guard; its `bridge-command-boot` qualification lane carries nine claims within the shipped 185-mutant inventory.
|
|
34
|
+
|
|
35
|
+
### Notes
|
|
36
|
+
|
|
37
|
+
- Snowflake Cortex has neither a subscription nor a free tier reachable from the source-owning host (measured 2026-08-20), so `smoke-acp-cortex-live` can only report protocol SKIP here. That is an absent axis, not a pass, and no other backend substitutes for it.
|
|
38
|
+
- Copilot is probe-only in this release. #82 owns authentication, permission, liveness, stale/crash, operator-session cleanup, durable LIVE evidence, and the final admit/reject decision.
|
|
39
|
+
- #76 (subscription-first refusal of `openrouter/*` sibling launches), #78 (macOS/native-Windows portability evidence), #80 (public vocabulary), and the remaining #72 field-cause investigation stay outside this patch.
|
|
40
|
+
|
|
41
|
+
## 0.14.1 — 2026-08-13
|
|
42
|
+
|
|
43
|
+
This patch fills the cross-repository creation gap in the visible mux lifecycle shipped in 0.14.0, so one operator tmux session can form siblings in multiple project roots without borrowing a dormant session as a cwd carrier.
|
|
44
|
+
|
|
45
|
+
### Added
|
|
46
|
+
|
|
47
|
+
- **`entwurf_fresh_call` accepts one optional literal absolute `cwd` for cross-repository siblings.** Omitting it (or passing `""`) keeps the caller's current directory; Pi and Claude Code receive the selected directory through their existing visible launch path, and the launch receipt reports the requested value without claiming runtime acceptance.
|
|
48
|
+
|
|
49
|
+
### Changed
|
|
50
|
+
|
|
51
|
+
- **The lifecycle selection matrix now separates address, continuity, and project root.** Use `entwurf_v2` for an existing live citizen, `entwurf_resume_call` only for continuity with a dormant Pi citizen under its recorded cwd and garden id, and `entwurf_fresh_call` for a new sibling — omitting `cwd` for the caller's project or passing an absolute `cwd` for another repository. Resume is not a substitute for cross-repository fresh creation.
|
|
52
|
+
|
|
53
|
+
### Fixed
|
|
54
|
+
|
|
55
|
+
- **The Claude meta-bridge installer relinquishes its retired ownership of `skipDangerousModePermissionPrompt`.** Proven prior install state is restored once when the value is still exactly entwurf's former managed value; operator-changed or unproven values remain untouched, malformed ownership evidence fails loud, and later uninstall cannot overwrite the returned choice.
|
|
56
|
+
- **The cross-harness chain LIVE smoke no longer inherits the runner's `PI_SESSION_ID` / `PI_AGENT_ID`.** When release-gate (or any pi `--entwurf-control` parent) spawned hop A, the MCP bridge preferred those carriers over A's SessionStart meta-sender marker and stamped the runner's garden id on hop 1 — payload still traversed, identity assertion failed. Child env now strips the pi identity carriers so the Claude hop's own marker is authoritative.
|
|
57
|
+
|
|
58
|
+
### Verification
|
|
59
|
+
|
|
60
|
+
- Release-gate candidate: the in-gate `pnpm run check:full` exited 0 in 208s, and `./run.sh check-gate-qualification` killed **173/173** committed mutants.
|
|
61
|
+
- `LIVE=1 ./run.sh release-gate /tmp/entwurf-release-gate-0.14.1.j2eAVu --cut` — **MUST PASS=20 FAIL=0 SKIP=0**, **BEHAVIOR PASS=1 FAIL=0 SKIP=0**, `cut: OK`. Full log: `/tmp/entwurf-release-gate-0.14.1.j2eAVu/release-gate.log` (SHA-256 `bdd4d0b332d08c24210e9f56382b5898c0544fb6dffbf70287dade2f00e67c36`).
|
|
62
|
+
- Pre-tag installed-consumer diagnostics also passed: `./run.sh check-pack-install` installed the 0.14.1 tarball and proved the seven-tool boot plus physical delivery; `ENTWURF_REQUIRE_DOCKER=1 ./run.sh check-install-container` reached `container-consumer: PASS` in a checkout-invisible non-root Node 24 consumer (throwaway candidate SHA-256 `48778d33d1088af8078fe6b59ad932fb34ac8564e80bef84c34b25bab2bd5ef6`). These are diagnostic pack-once artifacts, not the preserved release candidate.
|
|
63
|
+
- On the source-owned operator host, `./run.sh install-meta-bridge` completed the retired-warning relinquishment and `./run.sh doctor-meta-bridge` passed with live MCP owner join, physical delivery, and writer parity. Exact prepared-HEAD CI and acceptance of one preserved immutable candidate remain `make` responsibilities.
|
|
64
|
+
|
|
65
|
+
### Notes
|
|
66
|
+
|
|
67
|
+
- #76 (subscription-first refusal of `openrouter/*` sibling models), #60, #72, and #75 remain outside this patch.
|
|
68
|
+
- The chain-smoke repair only scrubs ambient pi identity carriers from its children. The MCP bridge's existing pi-carrier precedence is unchanged; any general nested-runner product guard is a separate contract, not part of 0.14.1 or #76.
|
|
69
|
+
|
|
7
70
|
## 0.14.0 — 2026-08-08
|
|
8
71
|
|
|
9
72
|
Two arcs meet in this release. The product arc makes sibling sessions **visible**: opening and resuming a garden citizen is now an explicit, observable act, and the hidden alternatives were removed rather than kept as compatibility surface. The verification arc keeps the product from being swallowed by its own test cost: the everyday gate now runs in under a minute while the release floor stays strict. Claude Code native + pi + the meta-record store remain the main rail; the ACP backends (Claude ACP, Cortex) are optional service adapters on top of it.
|
package/DELIVERY.md
CHANGED
|
@@ -81,6 +81,7 @@ D8 robustness: partial reason="..."
|
|
|
81
81
|
| **Antigravity / agy** | shipped | D6; D7 partial | Record-backed native-push through LS gRPC `agentapi send-message`; no mailbox or receiver marker. |
|
|
82
82
|
| **Codex app-server-backed TUI** | verified probe | D7; D8 unproven | WebSocket-over-UDS `turn/start` into a live `threadId`; status events expose completion. No managed citizen lane yet. |
|
|
83
83
|
| **Codex embedded TUI** | deferred | D0 partial | No supported receive socket/hook on the measured standalone shape. |
|
|
84
|
+
| **Copilot CLI TUI+server** | verified probe | D7; D8 unproven | **Old chronological-slice run; the named-turn probe in the tree is unrun.** Official SDK over hidden `--ui-server`: foreground native id + metadata, two-session addressed idle enqueue, same-session auto-model reply, completion events read back through the official session event-history API. Loopback RPC authentication is not established; no managed citizen lane. Evidence is L4 direct-native on ONE Linux workstation, host-local stdout, not archived. |
|
|
84
85
|
| **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. |
|
|
85
86
|
|
|
86
87
|
“Verified probe” means the transport worked in a reproducible raw probe but entwurf
|
|
@@ -126,6 +127,62 @@ shipping commitment: GLG closed the managed native Codex lane on 2026-08-01 beca
|
|
|
126
127
|
already supplies the official GPT provider path. Entwurf will not duplicate it as a
|
|
127
128
|
native citizen or ACP backend. `turn/steer` is active-turn steering, not idle wake.
|
|
128
129
|
|
|
130
|
+
### Copilot CLI: TUI+server is the positive launch mode
|
|
131
|
+
|
|
132
|
+
**Two things are recorded here and they are not the same thing: what was MEASURED on
|
|
133
|
+
2026-08-19, and what the probe now CONTRACTS to measure.** The measurement below was
|
|
134
|
+
taken with the earlier chronological-slice probe, which scored the events following the
|
|
135
|
+
marker's position in the history. The current probe scores a named turn instead (next
|
|
136
|
+
subsection). No result below has been re-taken under that contract, and none of it is
|
|
137
|
+
retroactively a demonstration of it.
|
|
138
|
+
|
|
139
|
+
**Measured 2026-08-19 (old chronological-slice probe).** A plain Copilot TUI and shell
|
|
140
|
+
command hooks do not establish the measured route. CLI 1.0.80 launched with hidden
|
|
141
|
+
`--ui-server --port <port>` and joined by first-party `@github/copilot-sdk` 1.0.11 did:
|
|
142
|
+
protocol-v3 ping, foreground session id plus cwd/git metadata, exact session resume, idle
|
|
143
|
+
`enqueue`, same-session model-`auto` reply, and `assistant.message`/`turn_end`/`session.idle`
|
|
144
|
+
completion. A second run created a no-turn control session B, targeted A, and proved B
|
|
145
|
+
received no user/turn/assistant event, closing D3 on one Linux workstation.
|
|
146
|
+
|
|
147
|
+
The two-session shape also exposed a D8 gap: A visibly replied and persisted
|
|
148
|
+
`assistant.message` + `turn_end`, but the joining SDK client did not receive ephemeral
|
|
149
|
+
`session.idle`, so SDK `sendAndWait()` timed out. Bounded reads of the official session
|
|
150
|
+
event-history API (`session.getEvents()` / `getMessages()`) then observed the completed
|
|
151
|
+
target turn. Claim that at its real size: it is the SDK's own full event history, not a
|
|
152
|
+
narrower or more privileged view, and equally not TUI, file, or database transcript
|
|
153
|
+
scraping — the probe never reads Copilot's own storage. It is probe evidence, not a
|
|
154
|
+
product polling/retry design.
|
|
155
|
+
|
|
156
|
+
**Evidence level for everything above: L4 direct-native, ONE Linux workstation, one run.**
|
|
157
|
+
The receipt is host-local probe stdout; it was not archived as a durable artifact, so this
|
|
158
|
+
row is reproducible-by-instruction, not citable to a stored file.
|
|
159
|
+
|
|
160
|
+
**Current probe contract (not yet run LIVE).** Attribution is now a named chain rather
|
|
161
|
+
than a position in the history: the probe's unique marker body must match exactly one
|
|
162
|
+
`user.message`; that event's `interactionId` must open exactly one `assistant.turn_start`;
|
|
163
|
+
that turn_start must expose a `turnId`; and only `assistant.message` / `assistant.turn_end`
|
|
164
|
+
carrying that `turnId` are scored. Every link is required, and absent-or-ambiguous fails
|
|
165
|
+
the probe closed — there is no positional fallback and no "the turn after ours" rule.
|
|
166
|
+
Note what is deliberately NOT the key: `session.send()` resolves to the SDK's own
|
|
167
|
+
submission handle, a string that appears on no server event and is a different axis from
|
|
168
|
+
`user.message.id`/`interactionId`, so joining on it cannot hold. It is logged as a
|
|
169
|
+
diagnostic only. The next LIVE turn is what would demonstrate this contract; until then
|
|
170
|
+
it is a design, not evidence.
|
|
171
|
+
|
|
172
|
+
The probe also stays out of the operator's lifecycle, stated precisely: it never deletes
|
|
173
|
+
target session A and issues no `A.disconnect()` of its own. `client.stop()` does tear down
|
|
174
|
+
every tracked session — A included — as a wire `session.destroy`; because A's foreground
|
|
175
|
+
ownership is re-confirmed immediately before teardown, the TUI keeps A as its foreground
|
|
176
|
+
session, so the net effect on A is detach-equivalent, not removal.
|
|
177
|
+
|
|
178
|
+
This is not yet admissible as a native-push adapter. The flag is hidden from CLI help,
|
|
179
|
+
and the loopback JSON-RPC server did not enforce the SDK connection token in the
|
|
180
|
+
measured launch: an unauthenticated client connected, while a token-bearing client was
|
|
181
|
+
rejected as `AUTHENTICATION_NOT_CONFIGURED`. The TCP port is only a runtime endpoint,
|
|
182
|
+
never identity authority. Do not add a record backend or dispatch route until
|
|
183
|
+
permission ownership, stale/crash handling, and a supported fail-closed local
|
|
184
|
+
boundary are demonstrated.
|
|
185
|
+
|
|
129
186
|
## Recording a new claim
|
|
130
187
|
|
|
131
188
|
For every matrix change, record:
|
package/README.md
CHANGED
|
@@ -114,6 +114,12 @@ npx entwurf install .
|
|
|
114
114
|
npx entwurf check-bridge
|
|
115
115
|
```
|
|
116
116
|
|
|
117
|
+
For an npm upgrade, rerun the install command in the same scope (use
|
|
118
|
+
`@junghanacs/entwurf@latest` when you want the registry's stable line explicitly),
|
|
119
|
+
then make the first check from that same scope: `entwurf check-bridge` for a global
|
|
120
|
+
install or `npx entwurf check-bridge` for a project-local install. Native-harness
|
|
121
|
+
installers and process restarts remain a separate post-upgrade step below.
|
|
122
|
+
|
|
117
123
|
For manual MCP registration from a project-local install, point the host at:
|
|
118
124
|
|
|
119
125
|
```text
|
|
@@ -139,12 +145,16 @@ pnpm install
|
|
|
139
145
|
|
|
140
146
|
A development clone runs the bridge source through Node's strip-types path;
|
|
141
147
|
an npm-installed package runs the prebuilt JS under `mcp/entwurf-bridge/dist/`
|
|
142
|
-
because Node refuses to strip `.ts` files under `node_modules`.
|
|
148
|
+
because Node refuses to strip `.ts` files under `node_modules`. The dev launcher's
|
|
149
|
+
source path means `./run.sh check-bridge` needs no build. After `git pull`, however,
|
|
150
|
+
run `pnpm install` when the lockfile changed and run `pnpm run build-bridge` before
|
|
151
|
+
artifact-consuming checks such as `./run.sh check-bridge-delivery`: `dist/` is
|
|
152
|
+
gitignored and may be absent or stale immediately after a checkout or pull.
|
|
143
153
|
|
|
144
154
|
### Pi adapter / ACP plugin lane
|
|
145
155
|
|
|
146
156
|
To use the `entwurf` provider inside pi, install a compatible pi binary
|
|
147
|
-
separately (`@earendil-works/pi-coding-agent >=0.84.
|
|
157
|
+
separately (`@earendil-works/pi-coding-agent >=0.84.2 <0.85`). Then point pi at
|
|
148
158
|
the npm-installed package or development clone:
|
|
149
159
|
|
|
150
160
|
```bash
|
|
@@ -218,9 +228,8 @@ host evidence boundaries are [VERIFY.md](./VERIFY.md) and [BASELINE.md](./BASELI
|
|
|
218
228
|
|
|
219
229
|
The curated model registry exposes unprefixed Claude ids plus `cortex-` rows.
|
|
220
230
|
Codex is not an ACP backend or a shipped managed citizen lane: it has verified
|
|
221
|
-
native-delivery probe evidence only.
|
|
222
|
-
|
|
223
|
-
before calling it supported.
|
|
231
|
+
native-delivery probe evidence only. No managed Codex support is claimed; lifecycle,
|
|
232
|
+
identity, installation, and doctors remain prerequisites for any such lane.
|
|
224
233
|
|
|
225
234
|
**Snowflake Cortex Code is the second ACP backend** (contract and audit:
|
|
226
235
|
[docs/acp-backend-rail.md](./docs/acp-backend-rail.md#cortex-code-audit-d1d10)). Curated ids are
|
|
@@ -418,7 +427,7 @@ A two-pane recording covers the pre-0.12 v1 surface end-to-end — sibling resum
|
|
|
418
427
|
|
|
419
428
|
Live peer messaging carries a sender envelope `{ sessionId, agentId, cwd, timestamp, origin?, replyable? }`; `entwurf_self` returns that authoritative envelope for the current pi session or trusted meta-session. Plain external MCP hosts are non-replyable. A garden-native meta-session carries a trusted `meta-session` envelope, but **`replyable` is a fact its own rail decides, not a consequence of being trusted** — a self-fetch citizen needs a live armed receiver, a native-push citizen needs an alive adapter probe, and a pi session needs its control socket. `entwurf_self` also reports which rail a meta-session reply would ride, because a native-push citizen has no mailbox to name. `wants_reply` is an etiquette marker rendered as a `(wants reply)` badge — not a transport contract, no wait, no polling. **v2 never gates on it:** a `wants_reply` from an external/non-replyable caller is passed through and surfaced honestly beside that sender's `replyable: false`, not rejected — the decider routes on target + intent, never on sender replyability. (The retired v1 `entwurf_send` did reject it; that behaviour went with the verb.)
|
|
420
429
|
|
|
421
|
-
In ACP-backed and external native-harness sessions, `entwurf-bridge` exposes seven tools: `entwurf_v2`, `entwurf_peers`, `entwurf_fresh_call`, `entwurf_resume_call`, `entwurf_self`, `entwurf_inbox_read`, and the explicit/manual `entwurf_register_native` fallback. Native pi exposes the shared capability directly through the extension surface (`entwurf_v2`, `entwurf_peers`, `entwurf_fresh_call`, `entwurf_resume_call` tools; the socket-scan `/entwurf-sessions` command is gone — #50 C4). **For garden-id delivery/reply use `entwurf_v2`** — the canonical surface that classifies the target and routes to live-pi / Claude-Code-meta-mailbox / Antigravity-native-push, and refuses a dormant target instead of waking it. **To open a sibling that does not exist yet use `entwurf_fresh_call`** — it launches one fixed backend (`pi` or `claude-code`) as a visible window in the operator's own tmux session, requires an explicit model, passes
|
|
430
|
+
In ACP-backed and external native-harness sessions, `entwurf-bridge` exposes seven tools: `entwurf_v2`, `entwurf_peers`, `entwurf_fresh_call`, `entwurf_resume_call`, `entwurf_self`, `entwurf_inbox_read`, and the explicit/manual `entwurf_register_native` fallback. Native pi exposes the shared capability directly through the extension surface (`entwurf_v2`, `entwurf_peers`, `entwurf_fresh_call`, `entwurf_resume_call` tools; the socket-scan `/entwurf-sessions` command is gone — #50 C4). **For garden-id delivery/reply use `entwurf_v2`** — the canonical surface that classifies the target and routes to live-pi / Claude-Code-meta-mailbox / Antigravity-native-push, and refuses a dormant target instead of waking it. **To open a sibling that does not exist yet use `entwurf_fresh_call`** — it launches one fixed backend (`pi` or `claude-code`) as a visible window in the operator's own tmux session, requires an explicit model, accepts one optional literal absolute `cwd` (omit it or pass `""` to use the caller's cwd), passes the model and selected directory through the runtime's visible launch path, and hands it a first task; the sibling's first action is a nonce callback whose sender envelope carries its garden id. The launch receipt records the requested model/cwd plus tmux coordinates and never claims that the runtime accepted them or completed delivery. (The v1 verbs `entwurf` / `entwurf_resume` / `entwurf_send` are gone.) Garden-native operator commands require `--entwurf-control`. There is no spawn target allowlist — the target registry is gone (#50 C3): `entwurf_v2` and `entwurf_resume_call` address an existing record-backed citizen, while `entwurf_fresh_call` takes its explicit backend/model/task and optional cwd directly rather than resolving a model tuple from a registry file. **To reopen a DORMANT pi citizen use `entwurf_resume_call {target}`** — the record supplies transcript, model, provider and cwd, so it takes no prompt, no task and no model override; it runs no turn, returns a LAUNCH receipt and a separate OBSERVATION receipt (only the second says the citizen is back), refuses a non-pi target as `target-not-pi`, and on an unobserved socket leaves the visible window open and releases its lock rather than retrying.
|
|
422
431
|
|
|
423
432
|
### `entwurf_v2` — canonical dispatch verb
|
|
424
433
|
|
|
@@ -437,7 +446,7 @@ In ACP-backed and external native-harness sessions, `entwurf-bridge` exposes sev
|
|
|
437
446
|
|
|
438
447
|
**`entwurf_v2` is the canonical surface for garden-id delivery.** When you have a garden id and want to reach whoever it names — message, reply, or hand-off — `entwurf_v2` is the one surface that reads whether the target is live pi, dormant pi, mailbox-backed Claude Code, or native-push Antigravity and routes correctly; *when unsure which transport, use `entwurf_v2`*. This prevents callers from guessing a rail from the shape of an id.
|
|
439
448
|
|
|
440
|
-
What v2 provides is a **deterministic dispatch substrate** that moves the "which transport?" decision out of the fallible caller/model and into the decider, with transport-appropriate locking and an honest reject (no `✓ delivered`, no `.msg` garbage) when a target cannot receive. It still does **not** mint siblings, and it does not relaunch one either: every row above either reaches a citizen that is already running or refuses. Reopening a dormant pi citizen is `entwurf_resume_call`, a separate lifecycle verb that never routes through this decider. Fresh creation is the separate `entwurf_fresh_call` verb. It opens one fixed Pi or Claude Code runtime visibly in the caller's tmux session with a required explicit model passed in that runtime's measured CLI dialect
|
|
449
|
+
What v2 provides is a **deterministic dispatch substrate** that moves the "which transport?" decision out of the fallible caller/model and into the decider, with transport-appropriate locking and an honest reject (no `✓ delivered`, no `.msg` garbage) when a target cannot receive. It still does **not** mint siblings, and it does not relaunch one either: every row above either reaches a citizen that is already running or refuses. Reopening a dormant pi citizen is `entwurf_resume_call`, a separate lifecycle verb that never routes through this decider. Fresh creation is the separate `entwurf_fresh_call` verb. It opens one fixed Pi or Claude Code runtime visibly in the caller's tmux session with a required explicit model passed in that runtime's measured CLI dialect and one optional literal absolute `cwd`; omitted or `""` means the caller's cwd. It returns only a synchronous launch receipt and lets the sibling report its new address asynchronously through the sender envelope of a nonce callback. Use this cwd input for a new cross-repository sibling; do not resume a dormant citizen as a cwd substitute. The meta-mailbox row requires an **active** self-fetch receiver; native-push requires a record-backed, probe-alive native conversation and never borrows mailbox state. The [mux launch lane](./docs/mux-launch-rail.md) owns placement, fixed-runtime launch, and the two narrow compositions above it (fresh-call and resume-call placement); delivery does not import launch, and mux is not a delivery transport.
|
|
441
450
|
|
|
442
451
|
A live pi target is *reached* over its control socket, but the socket is dispatch-internal transport, never identity (#50 C4). A control socket that no meta-record claims — a pre-record-era resident, an unreadable store, or a stale/planted file — is refused for **every** intent as `record-less-socket`, and the reject names the fix (restart the resident so `session_start` births its record, or quiesce and run the fresh-cut). `entwurf_peers` reports the same state as an aggregated `record-less-socket` diagnostic rather than a peer row.
|
|
443
452
|
|
package/VERIFY.md
CHANGED
|
@@ -43,16 +43,16 @@ Verification here is not a benchmark. In production we exchange short turns and
|
|
|
43
43
|
- **Deterministic floor — two tiers (#70):** `pnpm check` is the everyday CORE — toolchain (lint + typecheck), the vitest lanes, and the pure-unit / behavioral-contract / source-topology gates plus the cheap static coherence checks. It prints its own total wall time; acceptance is ≤60s on the reference host `oracle` (an operator measurement, never a hard wall-clock gate on arbitrary hosts). `pnpm run check:full` is the FULL deterministic floor — the core plus the hermetic-integration and package/install tiers — and is what the frozen-candidate protocol, push CI, release-gate, and `prepublishOnly` run. Exact membership is the named `check:*` group scripts in `package.json` (the executable SSOT — this document records meaning and principles, not the command list); a gate changes tier by semantic-class decision, never by getting faster or slower. Both tiers exclude the separately scheduled `check-gate-qualification`.
|
|
44
44
|
- **Discriminating power of that floor:** `./run.sh check-gate-qualification` (scheduled, not ambient: standalone when a lane changes a gate/mutant/matrix, in the CI `check` job on every push, and as a release-gate MUST step — no longer inside the default check chains) re-plants committed defect mutants (`scripts/mutants/*.json`, one per closed defect class) in an isolated snapshot repo and requires each to turn its gate red **bounded and at its claimed `[QK:<claim>]` signature** — a wrong-reason red fails, a baseline-red control voids the whole group, and the runner is negative-controlled on every run (zero-match/multi-match/survived/wrong-reason/hang/control-red/impurity). This measures whether the deterministic gates still *block* what they claim to block; it is **not a new evidence level** (L0–L5 are untouched) and never substitutes for LIVE evidence. Per-cut records cite claim IDs + killed mutant IDs — "N checks passed" alone is not evidence. `check-agy-permission-matrix` complements it with the enumerated permission contract space (literal cells + stated exclusion rules, oracle independent of the SUT).
|
|
45
45
|
- **Live floor:** `LIVE=1 ./run.sh release-gate <scratch-project-dir> --cut` — `pnpm run check:full` + the v2-native live gates + the ACP plugin acceptance floor. It reports a **two-tier summary**:
|
|
46
|
-
- **MUST tier** (release-blocking — owns the exit code; "green" applies only here): `pnpm run check:full`, `check-gate-qualification`, `smoke-entwurf-v2-matrix-live`, `check-bridge`, the resident-garden-guard zero-token half (record birth / record-keyed socket / attach-on-reopen), the `smoke-acp-*-live` ACP plugin smokes (socket-citizen / raw-turn / overlay / provider / session-reuse / carrier-augment / memory-containment / rgg / mcp / skill / bundled-mcp / v2-send), the axis wired in on 2026-07-31 that the aggregate had simply never listed (`smoke-claude-native-resume-live`), and `smoke-entwurf-chain-live` — the cross-harness delivery chain (native Claude Code → pi GPT → pi ACP Sonnet → mailbox terminus) proving sender identity and replyability at every hop plus a real read receipt at the end. (`smoke-session-id-name` is gone — #50 C3: its `--session-id`/`--name` substrate has no entwurf consumer anymore.)
|
|
46
|
+
- **MUST tier** (release-blocking — owns the exit code; "green" applies only here): `pnpm run check:full`, `check-gate-qualification`, `smoke-entwurf-v2-matrix-live`, `check-bridge`, `doctor-pi-provider` (#81 — `check-bridge` proves the launcher this checkout SHIPS; this proves the invocation the operator's pi provider actually EXECS, by booting it and requiring the entwurf verb set back, because `command -v` answers yes for a command that exits 127; wired as a step on 2026-08-19 after a relocated pnpm cmd-shim cost a cut sixteen LIVE steps before the same fact surfaced at `smoke-acp-bundled-mcp-live`), the resident-garden-guard zero-token half (record birth / record-keyed socket / attach-on-reopen), the `smoke-acp-*-live` ACP plugin smokes (socket-citizen / raw-turn / overlay / provider / session-reuse / carrier-augment / memory-containment / rgg / mcp / skill / bundled-mcp / v2-send), the axis wired in on 2026-07-31 that the aggregate had simply never listed (`smoke-claude-native-resume-live`), and `smoke-entwurf-chain-live` — the cross-harness delivery chain (native Claude Code → pi GPT → pi ACP Sonnet → mailbox terminus) proving sender identity and replyability at every hop plus a real read receipt at the end. (`smoke-session-id-name` is gone — #50 C3: its `--session-id`/`--name` substrate has no entwurf consumer anymore.)
|
|
47
47
|
- **BEHAVIOR tier** (advisory, non-blocking): the resident-garden-guard positive (a model-in-loop `entwurf_self` turn). A BEHAVIOR FAIL is surfaced with its artifact path but **never blocks the cut**. The lane holds what the model *chooses*, never what our wiring fails to deliver — a gate that TELLS the model which tool to call stays MUST, because its failure is ours — measured 2026-07-24, when the tool turned out to be absent from the session schema in both observed failures (the bundled-MCP readiness gap recorded in `scripts/smoke-acp-v2-send-live.ts`).
|
|
48
48
|
- **Every MUST step is invoked and reports its own outcome.** Prerequisite-bearing LIVE MUST steps ride the P1 STEP OUTCOME protocol (`scripts/lib/step-outcome.sh`): exit 0 = PASS, exit 97 = SKIP (a prerequisite the step does not have, printed as an `[entwurf:skip]` line), anything else = FAIL. The two non-skippable static steps (`pnpm run check:full`, `check-gate-qualification`) are inline: 0 = PASS, nonzero = FAIL, no SKIP arm — they have no prerequisite to decline. A skip is never counted as a pass — that hole is what let a cortex-less host read as cortex acceptance. Without `--cut` this is the unattended diagnostic: SKIPs are reported and the run still exits 0. **`--cut` makes it acceptance and any MUST SKIP is red**, which is how "a real cut needs `LIVE=1` with `SKIP=0`" stopped being prose. A green MUST gate is **necessary, not sufficient** — GLG authorizes the cut.
|
|
49
49
|
- **When cost-bearing MUST gates run (fixed 2026-07-23, the F6/F7 lesson):** a commit that touches a rail a MUST-tier live gate covers runs that gate **before cross-review is requested** — never parked behind "run it at approval time". Deferring a wired gate to a human decision is what let F6/F7 ship reviewed-and-approved; the wiring exists so the verdict never depends on who pressed enter. "배선이 없어 못 한 것은 OK, 배선이 있는데 안 돌린 것은 우리가 남긴 구멍이다." Model-in-loop cost is spent via the subscription-backed `entwurf` provider where the gate allows it, a free-tier native model otherwise; cost is a reason to pick the cheap target, not to skip the gate.
|
|
50
50
|
|
|
51
|
-
> **Cortex is an on-demand axis, not an aggregate one.** Its rail needs an external Snowflake connection and login that the host owns, not the repo — so wiring it into the aggregate would block every cut taken on a host without that account. **The release aggregate does not re-certify Cortex**; `LIVE=1 ENTWURF_ACP_CORTEX_CONNECTION=<conn> ./run.sh smoke-acp-cortex-live` stays a required direct call whenever a cut changes Cortex rail code or an operator elects to certify that host. Its honest-skip behaviour is unchanged: run it without the connection and it reports protocol SKIP, never a pass.
|
|
51
|
+
> **Cortex is an on-demand axis, not an aggregate one.** Its rail needs an external Snowflake connection and login that the host owns, not the repo — so wiring it into the aggregate would block every cut taken on a host without that account. **The release aggregate does not re-certify Cortex**; `LIVE=1 ENTWURF_ACP_CORTEX_CONNECTION=<conn> ./run.sh smoke-acp-cortex-live` stays a required direct call whenever a cut changes Cortex rail code or an operator elects to certify that host. Its honest-skip behaviour is unchanged: run it without the connection and it reports protocol SKIP, never a pass. **Operator-host limit (2026-08-20, measured):** the source-owning host has no Snowflake subscription, and Cortex Code offers no free tier that a live turn can reach — a direct attempt confirmed it. So on this host `smoke-acp-cortex-live` can only ever report protocol SKIP, and no LIVE Cortex evidence can be produced here until Snowflake supplies a free-usable route or the account is subscribed. Record that SKIP as an absent axis; never soften it into a pass, and never substitute a different backend as Cortex evidence.
|
|
52
52
|
>
|
|
53
53
|
> A cut that touches the prompt-lifecycle contract (no wall clock on a running turn) owes one long-turn acceptance the aggregate floor is too short to carry: `LIVE=1 ./run.sh smoke-acp-long-turn-live` drives a real turn whose tool work outlasts the retired 600s cutoff and requires exactly one cold ACP bootstrap in the transcript. It takes >12 minutes by construction and is on-demand, not part of `release-gate`.
|
|
54
54
|
>
|
|
55
|
-
> **The integrated mux lifecycle IS a release-gate MUST.** `LIVE=1 ./run.sh smoke-mux-lifecycle-live` enters through a real MCP `tools/call` on the shipped bridge launcher and follows one citizen the whole way: fresh-call launch receipt, the sibling's own nonce callback whose SENDER ENVELOPE is the address, an `entwurf_v2` control-socket send that lands in the sibling's own transcript, `entwurf_resume_call` REFUSED while that citizen is live, a stable-handle close proving pane and socket gone with the record preserved, delivery to the dormant citizen refused honestly, then the public `entwurf_resume_call` — whose LAUNCH and OBSERVATION receipts stay apart — and finally an `entwurf_v2` send the resumed session answers with a fact it was told BEFORE the window closed. That last step is the point: a socket answering under the same garden id proves a process stood up at that address, and only the recall proves the same conversation came back. Both pi provider shapes are driven to it (native `openai-codex/gpt-5.6-
|
|
55
|
+
> **The integrated mux lifecycle IS a release-gate MUST.** `LIVE=1 ./run.sh smoke-mux-lifecycle-live` enters through a real MCP `tools/call` on the shipped bridge launcher and follows one citizen the whole way: fresh-call launch receipt, the sibling's own nonce callback whose SENDER ENVELOPE is the address, an `entwurf_v2` control-socket send that lands in the sibling's own transcript, `entwurf_resume_call` REFUSED while that citizen is live, a stable-handle close proving pane and socket gone with the record preserved, delivery to the dormant citizen refused honestly, then the public `entwurf_resume_call` — whose LAUNCH and OBSERVATION receipts stay apart — and finally an `entwurf_v2` send the resumed session answers with a fact it was told BEFORE the window closed. That last step is the point: a socket answering under the same garden id proves a process stood up at that address, and only the recall proves the same conversation came back. Both pi provider shapes are driven to it (native `openai-codex/gpt-5.6-luna` and recorded-ACP `entwurf/claude-sonnet-5`, the only shape that re-injects a bridge extension), and the Claude Code cell ends where its capability ends: its resume is refused as `target-not-pi` with no window opened and no lock residue (the per-gid coordination lock is released).
|
|
56
56
|
>
|
|
57
57
|
> One cell cannot be fully fenced, and that is recorded rather than glossed: the recorded-ACP pi cell runs under the operator's REAL home, because its provider spawns `claude` as a child that authenticates from there — measured, a fenced HOME kills that turn with `Authentication required` before the model is ever reached, and `CLAUDE_CONFIG_DIR` alone does not fix it. That is the same trade `smoke-acp-bundled-mcp-live` already makes. While that cell runs, its citizen's control socket and per-gid lock exist under the operator's own `~/.pi/entwurf-control` and `~/.pi/entwurf-v2-locks`; its meta store stays fixture, so no garden record is minted outside the fixture, and the run ends by proving all six real roots hold the entry sets they started with, with no fixture garden id and no leftover lock.
|
|
58
58
|
>
|
|
@@ -60,7 +60,7 @@ Verification here is not a benchmark. In production we exchange short turns and
|
|
|
60
60
|
>
|
|
61
61
|
> **Fresh-call LIVE is on-demand, not part of `release-gate`.** `LIVE=1 ./run.sh smoke-mux-fresh-call-live` opens configured Pi and Claude Code siblings, spends two model turns, and preserves their native transcripts; run it directly whenever a cut changes mux fresh-call/launch behavior. Its private tmux servers and fixture-bound entwurf write axes make it deterministic about garden-record/socket residue, but those real native turns should not appear unexpectedly in every aggregate cut.
|
|
62
62
|
>
|
|
63
|
-
> The aggregate release gate does not own a live agy conversation id, so agy's real native-push round trip is a separate acceptance axis: three fail-loud doctors plus `LIVE=1 AGY_CONVERSATION_ID=<id> ./run.sh smoke-agy-native-push-live`, followed by a fresh-conversation sender/reply check after package install. Its deterministic install/sender gates are already inside `pnpm run check:full`; do not misreport the aggregate gate as live agy evidence.
|
|
63
|
+
> The aggregate release gate does not own a live agy conversation id, so agy's real native-push round trip is a separate acceptance axis: three fail-loud doctors plus `LIVE=1 AGY_CONVERSATION_ID=<id> ./run.sh smoke-agy-native-push-live`, followed by a fresh-conversation sender/reply check after package install. Its deterministic install/sender gates are already inside `pnpm run check:full`; do not misreport the aggregate gate as live agy evidence. **Cost fence:** the agy conversation this smoke drives runs on a free account, so open it on `gemini-3.6-flash` — never a Pro tier. The model is the operator's choice at conversation-open time; entwurf never selects it, and no assertion reads it (see the shipped-lane note: model display is not part of the agy contract).
|
|
64
64
|
>
|
|
65
65
|
> Authoritative per-cut counts and digests live in BASELINE/CHANGELOG, not inline
|
|
66
66
|
> here; embedding them in the protocol makes a correct guide stale after every cut.
|
package/demo/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
> **Archived pre-0.12 evidence.** These scripts still describe the retired v1 `entwurf` / `entwurf_resume` / `entwurf_send` demo flow. They are kept for historical comparison and will be replaced by a v2-native retake in a post-0.12 follow-up; do not treat them as the current 0.12 runnable recipe.
|
|
4
4
|
|
|
5
|
+
> **Model ids here are archived, not recommended (2026-08-20).** The `entwurf/gpt-5.4` rows below record what these GIFs actually ran on. They are stale twice over: `entwurf/gpt-5.4` is no longer a curated `entwurf` ACP id at all — that provider serves only the `claude-*` and `cortex-*` rows in `pi-extensions/lib/acp/models.ts` — and the live-spend default has since moved to `openai-codex/gpt-5.6-luna` under a cheaper plan. Read them as a record of the recording, never as a default to copy; the current defaults live in `VERIFY.md` and `NEXT.md`.
|
|
6
|
+
|
|
5
7
|
Two recorded GIF scripts live here. Both use `asciinema` for capture and
|
|
6
8
|
`agg` for cast → GIF conversion. Both share the same gitignore policy
|
|
7
9
|
(`*.cast` global, `demo/*.gif`, `demo/*.log` — only the `.sh` and this
|
|
@@ -137,7 +139,7 @@ SCENE_DELAY=30 FINAL_PAUSE=10 bash demo.sh
|
|
|
137
139
|
|
|
138
140
|
## Prerequisites
|
|
139
141
|
|
|
140
|
-
- `pi` on PATH (current floor 0.84.
|
|
142
|
+
- `pi` on PATH (current floor 0.84.2)
|
|
141
143
|
- `entwurf` provider configured + auth ready for the selected sender/peer models
|
|
142
144
|
- `asciinema` installed
|
|
143
145
|
- `agg` installed (optional — only for GIF conversion)
|
package/demo/demo-baseline.sh
CHANGED
|
@@ -7,6 +7,17 @@
|
|
|
7
7
|
# 2. Entwurf surface — spawn a sibling via the entwurf tool and receive its
|
|
8
8
|
# reply in the same pane (cross-model, mode=sync).
|
|
9
9
|
#
|
|
10
|
+
# ARCHIVED pre-0.12 evidence — NOT a runnable recipe. Scene 2 drives the retired
|
|
11
|
+
# v1 `entwurf` verb, which the 0.12 cutover removed. Kept for historical
|
|
12
|
+
# comparison only. See demo/README.md.
|
|
13
|
+
#
|
|
14
|
+
# MODEL NOTE (2026-08-20). The model ids below are the ARCHIVED values these
|
|
15
|
+
# recordings actually used — they are kept as the historical record, not as a
|
|
16
|
+
# recommendation. Two things are stale about them: `entwurf/gpt-5.4` is no
|
|
17
|
+
# longer a curated `entwurf` ACP id at all (that provider serves only the
|
|
18
|
+
# claude-* and cortex-* rows in pi-extensions/lib/acp/models.ts), and GLG's
|
|
19
|
+
# live-spend default moved to `openai-codex/gpt-5.6-luna` on a Plus plan. Do
|
|
20
|
+
# NOT copy these ids into a live harness default — see VERIFY.md and NEXT.md.
|
|
10
21
|
# Layout (tmux, 220x50):
|
|
11
22
|
# pane 0 (single) — driven pi (claude-sonnet-5) — receives both prompts.
|
|
12
23
|
#
|
|
@@ -32,7 +43,7 @@ DRIVER_LOG="$OUTDIR/baseline-debug.log"
|
|
|
32
43
|
# Driven pi runs the bridge surface and answers both prompts.
|
|
33
44
|
DRIVER_MODEL=${DRIVER_MODEL:-entwurf/claude-sonnet-5} # pias
|
|
34
45
|
# Sibling spawned via entwurf in scene 2 — different backend for contrast.
|
|
35
|
-
SIBLING_MODEL=${SIBLING_MODEL:-entwurf/gpt-5.4} # piat
|
|
46
|
+
SIBLING_MODEL=${SIBLING_MODEL:-entwurf/gpt-5.4} # piat — ARCHIVED id, see MODEL NOTE above
|
|
36
47
|
SIBLING_CWD=${SIBLING_CWD:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}
|
|
37
48
|
|
|
38
49
|
# Pacing in seconds.
|
package/demo/demo.sh
CHANGED
|
@@ -7,6 +7,14 @@
|
|
|
7
7
|
# See demo/README.md. Scene 3's delivery proof was recovered as a deterministic gate
|
|
8
8
|
# (scripts/check-bridge-delivery.ts); the v2-native retake is a post-0.12 follow-up.
|
|
9
9
|
#
|
|
10
|
+
#
|
|
11
|
+
# MODEL NOTE (2026-08-20). The model ids below are the ARCHIVED values these
|
|
12
|
+
# recordings actually used — they are kept as the historical record, not as a
|
|
13
|
+
# recommendation. Two things are stale about them: `entwurf/gpt-5.4` is no
|
|
14
|
+
# longer a curated `entwurf` ACP id at all (that provider serves only the
|
|
15
|
+
# claude-* and cortex-* rows in pi-extensions/lib/acp/models.ts), and GLG's
|
|
16
|
+
# live-spend default moved to `openai-codex/gpt-5.6-luna` on a Plus plan. Do
|
|
17
|
+
# NOT copy these ids into a live harness default — see VERIFY.md and NEXT.md.
|
|
10
18
|
# Layout (tmux, 220x50):
|
|
11
19
|
# pane 0 (top) — peer pi (codex, gpt-5.4) — idle, waits for greeting
|
|
12
20
|
# pane 1 (bottom) — sender pi (claude-sonnet-5) — driven by send-keys
|
|
@@ -37,7 +45,7 @@ PEER_LOG="$OUTDIR/peer-debug.log"
|
|
|
37
45
|
SENDER_LOG="$OUTDIR/sender-debug.log"
|
|
38
46
|
|
|
39
47
|
# Models match the user's piat / pias aliases.
|
|
40
|
-
PEER_MODEL=${PEER_MODEL:-entwurf/gpt-5.4} # piat
|
|
48
|
+
PEER_MODEL=${PEER_MODEL:-entwurf/gpt-5.4} # piat — ARCHIVED id, see MODEL NOTE above
|
|
41
49
|
SENDER_MODEL=${SENDER_MODEL:-entwurf/claude-sonnet-5} # pias
|
|
42
50
|
|
|
43
51
|
# Pacing in seconds. Tuned from real runs: each scene's actual agent work
|
package/docs/acp-backend-rail.md
CHANGED
|
@@ -70,7 +70,7 @@ none.** A turn ends only on a lifecycle event:
|
|
|
70
70
|
|---|---|
|
|
71
71
|
| the agent answers | mapped through the terminal set above |
|
|
72
72
|
| the operator aborts | ACP `session/cancel` first — the agent closes its own turn (`cancelled → aborted`); process-group teardown only after a bounded grace, so an abort always returns |
|
|
73
|
-
| the child dies / stdio ends | the turn fails naming the exit status and the session-scoped stderr tail
|
|
73
|
+
| the child dies / stdio ends | the turn fails naming the exit status and the session-scoped stderr tail — or an honest bounded absence when transport EOF wins the race — on both the new and the reuse path |
|
|
74
74
|
|
|
75
75
|
Elapsed time is not evidence of failure, and a silent turn is not a failed turn: tool
|
|
76
76
|
use, reasoning, and provider queueing all legitimately outrun any number we could pick.
|
|
@@ -85,6 +85,102 @@ turned one long turn into four in 0.13.0. Gates: `check-acp-prompt-lifecycle` (b
|
|
|
85
85
|
with pi's own classifier as the oracle), `check-probe-ordering` (no production prompt
|
|
86
86
|
cutoff in source).
|
|
87
87
|
|
|
88
|
+
## Support contract (#81)
|
|
89
|
+
|
|
90
|
+
What "supported" means here, per declaration class. The classes are kept apart on purpose: one
|
|
91
|
+
undifferentiated "supported" column is what let a Claude PASS read as if it also certified Cortex.
|
|
92
|
+
|
|
93
|
+
| Surface | Declaration | Class | What a green actually says |
|
|
94
|
+
|---|---|---|---|
|
|
95
|
+
| Entwurf package | `0.14.1` | shipped baseline | the package contract these rows belong to |
|
|
96
|
+
| pi runtime | devDep exact `0.84.2`, peer `>=0.84.2 <0.85` | **exact** oracle + **closed range** | built and certified against 0.84.2; hosts inside the range are accepted, and the ceiling moves only on measurement |
|
|
97
|
+
| ACP wire SDK | `@agentclientprotocol/sdk 1.3.0` | **exact** | the shared wire oracle both adapters speak |
|
|
98
|
+
| Claude ACP adapter | `@agentclientprotocol/claude-agent-acp 0.70.0` | **exact**, bundled | the adapter we ship and certify; resolved before any PATH fallback |
|
|
99
|
+
| Claude Agent SDK | `0.3.232` (transitive) | **exact** oracle | the runtime risk surface behind the adapter |
|
|
100
|
+
| Anthropic SDK | `0.100.1` | **exact**, peer-resolution only | satisfies the Agent SDK peer floor (0.93.0+); never an API client here (gate L4) |
|
|
101
|
+
| Claude Code runtime | `>=2.1.217` (`entwurf.claudeCodeFloor`) | **floor** | below it, hook args are silently dropped; entwurf enforces this itself |
|
|
102
|
+
| Node | `>=24` (`engines.node`) | **floor** | single axis, derived everywhere else |
|
|
103
|
+
| Cortex Code | operator-installed CLI | **on-demand**, external | NOT a pinned dependency. Each LIVE record must name the exact CLI version it measured |
|
|
104
|
+
|
|
105
|
+
Current Cortex host reading: **`Cortex Code v1.1.52`, observed on the reference host `oracle`
|
|
106
|
+
(2026-08-19)**. This is an OBSERVATION of what happens to be installed, not a pin, not a range, and
|
|
107
|
+
not a direct LIVE certification — no Cortex evidence record is created by writing it down. It is
|
|
108
|
+
recorded here only so the on-demand row names a concrete number instead of an abstraction.
|
|
109
|
+
|
|
110
|
+
Reading rules that do not bend:
|
|
111
|
+
|
|
112
|
+
- **Claude PASS never certifies Cortex, and a Cortex SKIP never becomes a PASS.** They are separate
|
|
113
|
+
evidence axes with separate records; Cortex stays outside the Claude release floor.
|
|
114
|
+
- **Exact** means one measured build. **Range** means a closed accepted interval. **Floor** means a
|
|
115
|
+
minimum entwurf enforces itself. **On-demand** means the operator supplies the runtime and the
|
|
116
|
+
evidence names its version — presence of an adapter certifies no external release.
|
|
117
|
+
- A declared pin is not evidence. Package/deterministic gates bind the declarations
|
|
118
|
+
(`check-dep-versions`, `check-acp-sdk-surface`, the pack/install consumer gates); LIVE gates carry
|
|
119
|
+
the runtime claim.
|
|
120
|
+
|
|
121
|
+
### Minimum core value
|
|
122
|
+
|
|
123
|
+
One provider identity, `entwurf`, with model-id routing to backend adapters. The host pi session is
|
|
124
|
+
already the record-backed socket citizen; the ACP plugin mints no second citizen, socket, or peer
|
|
125
|
+
layer. Backend differences stay behind `adapterSettings` and adapter methods, and the turn sequence
|
|
126
|
+
stays backend-invariant.
|
|
127
|
+
|
|
128
|
+
Supported: one real model turn; curated routing with authoritative model enforcement; a narrow
|
|
129
|
+
callable tool surface; explicit MCP wiring including the entwurf bridge; session reuse with
|
|
130
|
+
delta-only user history; operator cancellation with bounded cleanup; honest terminal/error mapping.
|
|
131
|
+
|
|
132
|
+
Not supported, by design: workflow ownership, planner state, a memory DB, transcript hydration,
|
|
133
|
+
credential proxying, or a second harness inside pi.
|
|
134
|
+
|
|
135
|
+
### Capability posture
|
|
136
|
+
|
|
137
|
+
`clientCapabilities: {}` is the support posture, not an oversight. Optional upstream features do not
|
|
138
|
+
become reachable merely because an adapter ships them — but they stay out of reach for **two
|
|
139
|
+
different reasons, and collapsing them would hide a real risk**:
|
|
140
|
+
|
|
141
|
+
- **Capability-gated.** AIR typed session failures, the 0.69.0 AIR file-change report, terminal
|
|
142
|
+
output widgets and nested subagent transcripts each test a client capability entwurf does not
|
|
143
|
+
send, so the adapter itself keeps the legacy path.
|
|
144
|
+
- **Advertised but never called.** Some surfaces carry no capability prerequisite at all — 0.70.0's
|
|
145
|
+
`providers/list` / `providers/set` / `providers/disable` are advertised unconditionally. They are
|
|
146
|
+
unreachable only because the common loop never invokes them (nor `logout`). Nothing upstream
|
|
147
|
+
enforces that; it is our own call-site discipline, and it stops holding the moment we use one.
|
|
148
|
+
|
|
149
|
+
Adopting either class requires a separate observed need plus a complete rendering/lifecycle/evidence
|
|
150
|
+
contract. An optional upstream feature is not a core-value gap.
|
|
151
|
+
|
|
152
|
+
### Bump / defer rubric
|
|
153
|
+
|
|
154
|
+
`claude-agent-acp latest` is not a work queue. Certify when at least one holds:
|
|
155
|
+
|
|
156
|
+
- a turn/session/error path reachable under the default capability posture changes;
|
|
157
|
+
- the Claude Agent SDK, ACP SDK, peer resolution, pi floor, or backend process contract moves;
|
|
158
|
+
- a security, compatibility, or observed runtime defect requires the release;
|
|
159
|
+
- accumulated inactive minors are best folded into the next meaningful certification.
|
|
160
|
+
|
|
161
|
+
Otherwise record and defer. Every certification separates declared pins, deterministic/package
|
|
162
|
+
evidence, Claude LIVE aggregate evidence, and Cortex direct on-demand evidence (with its CLI
|
|
163
|
+
version). Per-bump measurements live in the ROADMAP **Dep bump(별도 트랙)** ledger.
|
|
164
|
+
|
|
165
|
+
### Bridge reachability is part of the contract
|
|
166
|
+
|
|
167
|
+
Explicit entwurf-bridge connectivity inside an ACP turn is core value, so it is measured rather than
|
|
168
|
+
assumed. `command -v` succeeding is not evidence: a launcher can resolve and still fail to exec (a
|
|
169
|
+
relocated package-manager shim deriving its target from `$0` exits 127), which leaves a turn with no
|
|
170
|
+
`mcp__entwurf-bridge__*` tool at all while every ownership check reads green. Both doctors therefore boot the exact configured stdio invocation — `command`, `args`, and
|
|
171
|
+
`env` — and require the full bridge verb set back over one shared leaf
|
|
172
|
+
(`./run.sh probe-bridge-command <cmd>` runs a simple command standalone; the agy doctor passes
|
|
173
|
+
its JSON invocation). The probe waits for a valid MCP `initialize` response before it sends
|
|
174
|
+
`notifications/initialized` and `tools/list`; a tools response alone is not boot evidence.
|
|
175
|
+
|
|
176
|
+
- **agy** probes every configured candidate invocation.
|
|
177
|
+
- **pi** probes every effective stdio invocation, including a legacy managed path or unowned
|
|
178
|
+
override. Runtime truth says whether the command pi will launch works; ownership separately says
|
|
179
|
+
whether entwurf may repair or normalize it.
|
|
180
|
+
|
|
181
|
+
entwurf never repairs a launcher it does not own — a foreign one is reported fail-loud with the
|
|
182
|
+
operator's repair named.
|
|
183
|
+
|
|
88
184
|
## Shipped adapters
|
|
89
185
|
|
|
90
186
|
| Seam | Claude | Cortex Code |
|
|
@@ -159,10 +255,13 @@ caller-session `_meta`, and cross-machine certification.
|
|
|
159
255
|
|
|
160
256
|
A backend can return `newSession` before its declared MCP server is callable. This was
|
|
161
257
|
observed intermittently on the Claude rail and directly on Cortex's private `mcp.json`
|
|
162
|
-
path. Neither `claude-agent-acp` 0.
|
|
258
|
+
path. Neither `claude-agent-acp` 0.70.0 nor the Cortex landing adds a client-side
|
|
163
259
|
readiness fence, and `mcpServerStatus()` is not called by the common loop.
|
|
164
|
-
(Re-measured at the 0.
|
|
165
|
-
|
|
260
|
+
(Re-measured at the 0.68.0 → 0.70.0 bump: AIR typed failures and the 0.69.0 AIR
|
|
261
|
+
file-change report are both capability-gated and unadvertised by entwurf; 0.70.0's
|
|
262
|
+
`providers/set` / `providers/disable` are advertised unconditionally by the adapter but
|
|
263
|
+
entwurf calls neither, so no session's provider state is transitioned; goal extension is
|
|
264
|
+
still not a fence. This bump changes no readiness behavior and closes no part of #72.)
|
|
166
265
|
|
|
167
266
|
### 11-7-a/b. Instrument and first measurement
|
|
168
267
|
|
|
@@ -9,7 +9,7 @@ the one-line registration; everything an operator needs to actually wire a host
|
|
|
9
9
|
- **plain external MCP host**: no garden meta-record / sender marker. It can call the read surfaces (`entwurf_peers`, `entwurf_inbox_read`), but `entwurf_v2` sends are **refused by default** (#50 C4: "if we don't know who sent it, we don't send it"). The operator may wire the explicit hatch below; the send then goes out external/non-replyable.
|
|
10
10
|
- **garden-native native session**: a trusted lifecycle hook minted a garden id and sender marker — `SessionStart` for Claude Code, `PreInvocation` for agy. It is not a pi control-socket session, but it can be replyable by garden id when its own mailbox/probe rail says so.
|
|
11
11
|
|
|
12
|
-
**Which verb an external agent should reach for:** to deliver to / reply to a garden id, use **`entwurf_v2`** — it is the canonical delivery surface and the only one that reads whether the target is live pi, dormant pi, mailbox-backed Claude Code, or native-push Antigravity and routes correctly. Discover targets with `entwurf_peers`, confirm your own identity with `entwurf_self`, drain a mailbox with `entwurf_inbox_read`, and use `entwurf_register_native` only as the explicit/manual fallback for binding an already-running agy conversation (normal agy birth is automatic through the installed hook). Open a NEW sibling with **`entwurf_fresh_call`**, and reopen a DORMANT pi citizen under its own garden id with **`entwurf_resume_call {target}`**. Fresh call needs its selected runtime (`pi` or `claude`) on the server's PATH; resume call always needs `pi`. Both start a runtime, while delivery does not. (The old v1 verbs `entwurf` / `entwurf_resume` / `entwurf_send` are gone.)
|
|
12
|
+
**Which verb an external agent should reach for:** to deliver to / reply to a garden id, use **`entwurf_v2`** — it is the canonical delivery surface and the only one that reads whether the target is live pi, dormant pi, mailbox-backed Claude Code, or native-push Antigravity and routes correctly. Discover targets with `entwurf_peers`, confirm your own identity with `entwurf_self`, drain a mailbox with `entwurf_inbox_read`, and use `entwurf_register_native` only as the explicit/manual fallback for binding an already-running agy conversation (normal agy birth is automatic through the installed hook). Open a NEW sibling with **`entwurf_fresh_call {backend, model, task, cwd?}`**, and reopen a DORMANT pi citizen under its own garden id with **`entwurf_resume_call {target}`**. Fresh call accepts one optional literal absolute `cwd`: omit it or pass `""` for the caller's cwd; otherwise it must name an existing directory and may not contain `#`. Use that input for a new cross-repository sibling — resume preserves a dormant Pi citizen's recorded continuity and is not a cwd substitute. Fresh call needs its selected runtime (`pi` or `claude`) on the server's PATH; resume call always needs `pi`. Both start a runtime, while delivery does not. (The old v1 verbs `entwurf` / `entwurf_resume` / `entwurf_send` are gone.)
|
|
13
13
|
|
|
14
14
|
Observed: Claude Code, Codex CLI, and Antigravity CLI all reach the read surfaces through this MCP bridge from a plain external host — `entwurf_peers` is a pure fact projection, while `entwurf_inbox_read` is a **mutating drain** (it archives the messages and stamps the read-receipt), so "read" here does not mean side-effect-free; **sending** needs an identity lane. Claude becomes symmetric/replyable through its mailbox-backed meta-session; agy becomes symmetric/replyable through its record-backed sender marker plus live native-push probe. Codex has no managed citizen lifecycle yet, so a Codex host cannot send without the explicit anonymous hatch below.
|
|
15
15
|
|
package/docs/setup-clean-host.md
CHANGED
|
@@ -11,7 +11,7 @@ only on Linux because its strict live-owner join uses `/proc`.
|
|
|
11
11
|
| Node | **`>=24.0.0`** | package and bridge runtime |
|
|
12
12
|
| npm | bundled with Node | package installation |
|
|
13
13
|
| entwurf | `@junghanacs/entwurf` | all lanes |
|
|
14
|
-
| pi | optional, `@earendil-works/pi-coding-agent >=0.84.
|
|
14
|
+
| pi | optional, `@earendil-works/pi-coding-agent >=0.84.2 <0.85` | ACP provider, control sockets |
|
|
15
15
|
| Claude Code | optional, **`>=2.1.217`** — the exec-form hook floor | Claude ACP auth/runtime and mailbox-backed native citizen |
|
|
16
16
|
| Antigravity `agy` | optional, operator-installed and authenticated | native-push citizen |
|
|
17
17
|
| Cortex Code | optional, operator-installed and authenticated | Cortex ACP backend |
|
|
@@ -56,7 +56,7 @@ lists the seven garden tools; it does not prove a backend model turn or native h
|
|
|
56
56
|
Install the exact release floor, then wire the project:
|
|
57
57
|
|
|
58
58
|
```bash
|
|
59
|
-
npm install -g @earendil-works/pi-coding-agent@0.84.
|
|
59
|
+
npm install -g @earendil-works/pi-coding-agent@0.84.2
|
|
60
60
|
pi --version
|
|
61
61
|
|
|
62
62
|
cd ~/entwurf-smoke
|
|
@@ -64,7 +64,7 @@ entwurf install .
|
|
|
64
64
|
pi -e "$(npm root -g)/@junghanacs/entwurf" --list-models entwurf
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
-
The supported range is `>=0.84.
|
|
67
|
+
The supported range is `>=0.84.2 <0.85`. It is a hard minimum: installing this
|
|
68
68
|
release onto a 0.83.x pi host upgrades the runtime rather than keeping the older
|
|
69
69
|
minor. A host using only the external MCP bridge can skip pi until it needs a
|
|
70
70
|
control socket; no delivery rail launches a pi process.
|