@junghanacs/entwurf 0.18.2 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +2 -2
- package/BASELINE.md +23 -5
- package/CHANGELOG.md +415 -0
- package/DELIVERY.md +59 -6
- package/README.md +43 -12
- package/VERIFY.md +10 -2
- package/docs/acp-backend-rail.md +9 -1
- package/docs/external-mcp-host.md +8 -5
- package/docs/setup-clean-host.md +93 -7
- package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +18 -7
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/models.js +3 -3
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/overlay.js +6 -2
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +76 -9
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-placement.js +54 -6
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/resolve-tmux-session.js +114 -0
- package/mcp/entwurf-bridge/src/index.ts +22 -7
- package/package.json +2 -2
- package/pi-extensions/acp-provider.ts +1 -1
- package/pi-extensions/entwurf-control.ts +27 -3
- package/pi-extensions/lib/acp/models.ts +3 -3
- package/pi-extensions/lib/acp/overlay.ts +6 -2
- package/pi-extensions/lib/meta-session.ts +25 -0
- package/pi-extensions/lib/mux-fresh-call.ts +98 -11
- package/pi-extensions/lib/mux-placement.ts +65 -10
- package/pi-extensions/lib/resolve-tmux-session.ts +137 -0
- package/run.sh +71 -26
- package/scripts/agy-bridge.sh +1 -1
- package/scripts/agy-imprint.sh +10 -7
- package/scripts/check-acp-carrier-augment.ts +6 -5
- package/scripts/check-acp-cortex.ts +41 -0
- package/scripts/check-acp-provider-surface.ts +9 -6
- package/scripts/check-copilot-birth-hook.ts +3 -1
- package/scripts/check-copilot-receive-arm.ts +169 -21
- package/scripts/check-copilot-statusline.ts +3 -1
- package/scripts/check-fresh-cut-gate.sh +54 -2
- package/scripts/check-gate-qualification.ts +13 -12
- package/scripts/check-hook-launch-topology.ts +6 -5
- package/scripts/check-install-surface.ts +2 -1
- package/scripts/check-meta-facts.ts +6 -4
- package/scripts/check-meta-hook-session-switch.ts +4 -3
- package/scripts/check-meta-identity-consumers.ts +8 -7
- package/scripts/check-meta-receiver-marker.ts +2 -1
- package/scripts/check-mux-launch-tmux.ts +77 -2
- package/scripts/check-mux-launch.ts +17 -0
- package/scripts/check-mux-placement-tmux.ts +61 -1
- package/scripts/check-mux-placement.ts +33 -0
- package/scripts/check-omp-birth-hook.ts +3 -2
- package/scripts/check-probe-bridge-command.ts +3 -1
- package/scripts/check-setup-qualification.sh +21 -0
- package/scripts/copilot-bridge-doctor.sh +15 -5
- package/scripts/copilot-bridge-install.sh +6 -2
- package/scripts/copilot-launch.sh +16 -2
- package/scripts/copilot-receive-bridge.sh +80 -13
- package/scripts/lib/reclaim-on-exit.ts +86 -0
- package/scripts/meta-bridge-doctor.sh +56 -15
- package/scripts/meta-bridge-install.sh +13 -7
- package/scripts/meta-bridge-uninstall.sh +6 -4
- package/scripts/mutants/acp-cortex.json +26 -2
- package/scripts/mutants/copilot-receive.json +26 -0
- package/scripts/mutants/fresh-cut.json +26 -0
- package/scripts/mutants/mux-boundary.json +24 -0
- package/scripts/mutants/mux-fresh-call.json +81 -0
- package/scripts/mutants/omp-birth.json +33 -3
- package/scripts/mutants/setup-verdict.json +13 -0
- package/scripts/omp-bridge-doctor.sh +110 -31
- package/scripts/omp-bridge-install.sh +6 -2
- package/scripts/omp-receive-install.sh +7 -2
- package/scripts/raw-async-delivery/README.md +10 -1
- package/scripts/raw-codex-measure/README.md +689 -0
- package/scripts/raw-codex-measure/source-audit.md +243 -0
- package/scripts/raw-macos-measure/README.md +148 -0
- package/scripts/raw-macos-measure/probe.sh +389 -0
- package/scripts/smoke-meta-async-drift.sh +7 -5
- package/scripts/smoke-meta-install-state.sh +70 -19
- package/scripts/smoke-mux-fresh-call-live.ts +175 -3
- package/scripts/smoke-omp-bridge-state.sh +43 -2
- package/scripts/smoke-setup-verdict.sh +100 -0
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ Claude Code / Copilot / Codex / agy / omp / pi
|
|
|
19
19
|
→ control-socket | meta-mailbox | native-push
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
[`entwurf_v2`](#entwurf_v2--canonical-dispatch-verb) is the canonical dispatch surface over *existing* garden citizens — live control-socket send, meta-mailbox enqueue, and native-push into a live Antigravity conversation. It starts no process on any rail: the hidden background resume that used to answer a dormant target was withdrawn under the visible-first rule, so a dormant citizen rejects honestly here and is reopened by a separate lifecycle verb, `entwurf_resume_call`. The meta-record is the sole address authority (#50 C4): a record-less control socket is refused as a `record-less-socket` diagnostic, never dispatched. The v1 entwurf verbs are gone. Fresh siblings and resumes are separate verbs — `entwurf_fresh_call` opens a NEW sibling in the operator's own
|
|
22
|
+
[`entwurf_v2`](#entwurf_v2--canonical-dispatch-verb) is the canonical dispatch surface over *existing* garden citizens — live control-socket send, meta-mailbox enqueue, and native-push into a live Antigravity conversation. It starts no process on any rail: the hidden background resume that used to answer a dormant target was withdrawn under the visible-first rule, so a dormant citizen rejects honestly here and is reopened by a separate lifecycle verb, `entwurf_resume_call`. The meta-record is the sole address authority (#50 C4): a record-less control socket is refused as a `record-less-socket` diagnostic, never dispatched. The v1 entwurf verbs are gone. Fresh siblings and resumes are separate verbs — `entwurf_fresh_call` opens a NEW sibling in the operator's tmux — the caller's own session, or one existing named session on the same server — and learns its garden id from the callback it makes, while `entwurf_resume_call` reopens a DORMANT pi citizen under its own garden id in a visible window without running a turn; the non-Claude ACP lane landed earlier — Snowflake Cortex Code became the second backend in 0.13.0.
|
|
23
23
|
|
|
24
24
|
**Garden id is deliberate vocabulary.** It is not a decorative synonym for session id, worker, delegate, or subagent. The unfamiliar word is a guard: each harness keeps its own identity and transcript, while `entwurf` supplies a narrow addressable surface between siblings.
|
|
25
25
|
|
|
@@ -79,6 +79,33 @@ A few words that look unusual for a coding tool.
|
|
|
79
79
|
|
|
80
80
|
## Install
|
|
81
81
|
|
|
82
|
+
**Platform evidence, in one breath.** The Entwurf-only install surface on
|
|
83
|
+
macOS is CERTIFIED (CI) (`macos-install-surface`). On macOS every
|
|
84
|
+
garden-native harness rail (pi, Claude, Copilot, OMP, agy), marker join,
|
|
85
|
+
ACP turn, and mux is NOT CERTIFIED — pending physical host; on Linux those
|
|
86
|
+
same rails are the certified axis. native Windows is UNSUPPORTED.
|
|
87
|
+
CERTIFIED (CI) is weaker than a physical-host doctor green.
|
|
88
|
+
The npm package has no `os` restriction; that is installability, not a
|
|
89
|
+
support claim.
|
|
90
|
+
|
|
91
|
+
**macOS in this release.** This release adds macOS support for Entwurf's
|
|
92
|
+
install surface: the npm package installs, `entwurf --help` and `entwurf
|
|
93
|
+
check-bridge` boot, and `entwurf setup` composes the integrations it finds.
|
|
94
|
+
The four installers that previously rejected Darwin by platform name no longer
|
|
95
|
+
do. We validated that surface only in macOS CI because the developers did not
|
|
96
|
+
have a physical Mac. So macOS native-harness rails—marker join, an ACP turn,
|
|
97
|
+
and mux included—are not yet certified; setup writes their wiring but reports
|
|
98
|
+
them non-green. Linux's certified rail status is unchanged.
|
|
99
|
+
|
|
100
|
+
On Darwin, `entwurf setup` that detects a harness is intentionally
|
|
101
|
+
non-green: the wiring WAS written and nothing failed to install, but the
|
|
102
|
+
harness rail is NOT CERTIFIED — pending physical host. That FAIL is not
|
|
103
|
+
an install defect. An Entwurf-only host (no harness on PATH) stays green.
|
|
104
|
+
|
|
105
|
+
A physical Mac can send host facts without installing or logging in:
|
|
106
|
+
`scripts/raw-macos-measure/probe.sh` (`/bin/sh`, ~3.5s). Measurement,
|
|
107
|
+
not certification.
|
|
108
|
+
|
|
82
109
|
`entwurf` is a neutral npm package first. Get the package, then run **`entwurf setup
|
|
83
110
|
<project>`** — one command, the same front door from an npm global install, an npm
|
|
84
111
|
project-local install, or a source checkout. It composes every harness it finds on the
|
|
@@ -187,6 +214,9 @@ gitignored and may be absent or stale immediately after a checkout or pull.
|
|
|
187
214
|
|
|
188
215
|
### Pi adapter / ACP plugin lane
|
|
189
216
|
|
|
217
|
+
This rail is CERTIFIED on Linux; on macOS it is NOT CERTIFIED — pending
|
|
218
|
+
physical host (control sockets, mux, ACP plugin hosting).
|
|
219
|
+
|
|
190
220
|
To use the `entwurf` provider inside pi, install a compatible pi binary
|
|
191
221
|
separately (`@earendil-works/pi-coding-agent >=0.85.1 <0.86`). Then point pi at
|
|
192
222
|
the npm-installed package or development clone:
|
|
@@ -217,10 +247,10 @@ for every harness it detects — you do not paste this list to install. This is
|
|
|
217
247
|
surface: each unit has its own installer, its own doctor with a named refusal, and its own
|
|
218
248
|
inverse, so a single broken unit can be redone without touching the rest.
|
|
219
249
|
|
|
220
|
-
- **Claude Code** (Linux
|
|
221
|
-
- **Antigravity / agy** — `install-agy-bridge`, `install-agy-statusline`, `install-agy-hooks`, each with a matching `doctor-agy-*`.
|
|
222
|
-
- **GitHub Copilot CLI** — four independent units, four independent failure modes: `install-copilot-bridge` (birth: garden id + who-sent, on the first prompt), `install-copilot-mcp` (the entwurf tool hand, where `entwurf_inbox_read` lives), `install-copilot-receive` (the receiver extension: doorbell + receiver marker), `install-copilot-statusline` (optional for a manual citizen, required for supported fresh) — each with a matching `doctor-copilot-*` and `uninstall-copilot-*`.
|
|
223
|
-
- **OMP (`omp`)** — four units, in-process extensions rather than launchers: `install-omp-bridge` (birth: the `mode === "tui"` visible host, its garden id on the status line, and who-sent), `install-omp-mcp` (the omp-native `entwurf-bridge` entry), `install-omp-config` (the one operator setting `tools: xdev: false`, without which the vendor mounts MCP tools as `xd://` devices the model cannot call), `install-omp-receive` (the receiver extension: mailbox watch + announce-only doorbell) — each with a matching `uninstall-omp-*`, and a `doctor-omp-*` for all but the setting, whose runtime axis `doctor-omp-mcp` owns. The setting writer owns exactly the lines it adds and refuses an explicit operator `tools: xdev: true` by name rather than overwriting it.
|
|
250
|
+
- **Claude Code** (Linux CERTIFIED; macOS NOT CERTIFIED — pending physical host) — `install-meta-bridge`, `doctor-meta-bridge`.
|
|
251
|
+
- **Antigravity / agy** (Linux CERTIFIED; macOS NOT CERTIFIED — pending physical host) — `install-agy-bridge`, `install-agy-statusline`, `install-agy-hooks`, each with a matching `doctor-agy-*`.
|
|
252
|
+
- **GitHub Copilot CLI** (Linux CERTIFIED; macOS NOT CERTIFIED — pending physical host) — four independent units, four independent failure modes: `install-copilot-bridge` (birth: garden id + who-sent, on the first prompt), `install-copilot-mcp` (the entwurf tool hand, where `entwurf_inbox_read` lives), `install-copilot-receive` (the receiver extension: doorbell + receiver marker), `install-copilot-statusline` (optional for a manual citizen, required for supported fresh) — each with a matching `doctor-copilot-*` and `uninstall-copilot-*`.
|
|
253
|
+
- **OMP (`omp`)** (Linux CERTIFIED; macOS NOT CERTIFIED — pending physical host) — four units, in-process extensions rather than launchers: `install-omp-bridge` (birth: the `mode === "tui"` visible host, its garden id on the status line, and who-sent), `install-omp-mcp` (the omp-native `entwurf-bridge` entry), `install-omp-config` (the one operator setting `tools: xdev: false`, without which the vendor mounts MCP tools as `xd://` devices the model cannot call), `install-omp-receive` (the receiver extension: mailbox watch + announce-only doorbell) — each with a matching `uninstall-omp-*`, and a `doctor-omp-*` for all but the setting, whose runtime axis `doctor-omp-mcp` owns. The setting writer owns exactly the lines it adds and refuses an explicit operator `tools: xdev: true` by name rather than overwriting it.
|
|
224
254
|
|
|
225
255
|
Run them as `entwurf <command>`. Which unit a doctor's refusal names, and the clean-host
|
|
226
256
|
walk-through for each harness, live in [docs/setup-clean-host.md](./docs/setup-clean-host.md).
|
|
@@ -275,10 +305,10 @@ Copilot units included — and restart its existing processes; reach for a singl
|
|
|
275
305
|
only when a **new** session using the
|
|
276
306
|
installed artifact makes `doctor-meta-bridge` exit 0 with the live owner join.
|
|
277
307
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
308
|
+
The Claude meta-bridge rail is CERTIFIED on Linux. On macOS it is
|
|
309
|
+
NOT CERTIFIED — pending physical host. The Darwin install fence is
|
|
310
|
+
open; uninstall was already open. Detailed diagnosis and clean-host
|
|
311
|
+
steps live in
|
|
282
312
|
[docs/setup-clean-host.md](./docs/setup-clean-host.md).
|
|
283
313
|
|
|
284
314
|
The active citizen store is V3-only. A store that fails certification is never
|
|
@@ -303,7 +333,8 @@ host evidence boundaries are [VERIFY.md](./VERIFY.md) and [BASELINE.md](./BASELI
|
|
|
303
333
|
2. **`require.resolve(...)` against the bundled package dependency** (`@agentclientprotocol/claude-agent-acp`). This is the default path; no extra global install needed.
|
|
304
334
|
3. **`PATH:claude-agent-acp` fallback** — used when the package resolution fails (e.g. a hand-edited `node_modules`).
|
|
305
335
|
|
|
306
|
-
The curated model registry exposes unprefixed Claude ids
|
|
336
|
+
The curated model registry exposes unprefixed Claude ids — `claude-opus-5`, `claude-sonnet-5`,
|
|
337
|
+
`claude-fable-5-1` — plus the `cortex-` rows below.
|
|
307
338
|
Codex is not an ACP backend or a shipped managed citizen lane: it has verified
|
|
308
339
|
native-delivery probe evidence only. No managed Codex support is claimed; lifecycle,
|
|
309
340
|
identity, installation, and doctors remain prerequisites for any such lane.
|
|
@@ -513,7 +544,7 @@ A two-pane recording covers the pre-0.12 v1 surface end-to-end — sibling resum
|
|
|
513
544
|
|
|
514
545
|
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.)
|
|
515
546
|
|
|
516
|
-
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 / self-fetch meta-mailbox (Claude Code, Copilot, OMP) / 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`, `claude-code`, `copilot`, or `omp`) as a visible window
|
|
547
|
+
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 / self-fetch meta-mailbox (Claude Code, Copilot, OMP) / 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`, `claude-code`, `copilot`, or `omp`) as a visible window on the operator's own tmux server, requires an explicit model, accepts one optional literal absolute `cwd` (omit it or pass `""` to use the caller's cwd) and one optional `placement.tmuxSession` naming an EXISTING session on that server to open the sibling in instead of the caller's own (the operator's project seat — nothing is ever created: an absent session is `tmux-session-missing` and a name outside the addressed grammar `[A-Za-z0-9][A-Za-z0-9_-]*` is `tmux-session-name-invalid`, with no window and no session left behind. The two inputs never infer each other, and the positive form of that matters more than the prohibition: **with `cwd` omitted, a seated sibling starts in THIS agent's own working directory**, measured — it does not inherit the target session's path or its active pane, so naming the `org` seat does not put the sibling in the `org` project. Pass `cwd` when you want a different directory. entwurf never resolves that path: it hands the literal string to tmux, so with a SYMLINKED directory the receipt echoes what you asked for while the record, the transcript path, the callback envelope and `pane_current_path` all show the path the OS resolved it to — two spellings of one place, and the resolved one is what `entwurf_resume_call` later reopens), passes the model and selected directory through the runtime's visible launch path, and hands it a first task; a `copilot` launch goes through entwurf's own managed invocation and is refused before any window opens if this host lacks the Copilot birth, MCP, receiver or visible-footer units, and an `omp` launch carries its task in the `--entwurf-bootstrap` payload instead of an argv prompt because that vendor connects its MCP tools after the session has already started. The sibling's first action is a nonce callback whose sender envelope carries its garden id. The launch receipt records the requested model/cwd/seat plus tmux coordinates — including the RESOLVED target session id, which is where the window actually is — 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.
|
|
517
548
|
|
|
518
549
|
### `entwurf_v2` — canonical dispatch verb
|
|
519
550
|
|
|
@@ -532,7 +563,7 @@ In ACP-backed and external native-harness sessions, `entwurf-bridge` exposes sev
|
|
|
532
563
|
|
|
533
564
|
**`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, Copilot or OMP, 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.
|
|
534
565
|
|
|
535
|
-
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, Claude Code, Copilot or OMP runtime visibly
|
|
566
|
+
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, Claude Code, Copilot or OMP runtime visibly on the caller's tmux server — its own session by default, or one EXISTING named session via the optional `placement.tmuxSession` — 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. Copilot opens through `entwurf copilot`, never the bare vendor; OMP is the opposite — the bare `omp` runtime with no positional prompt at all, because that vendor connects its MCP tools after the session has started, so the task rides a two-stage `--entwurf-bootstrap` payload the installed birth extension releases once the callback tool has actually answered. 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.
|
|
536
567
|
|
|
537
568
|
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.
|
|
538
569
|
|
package/VERIFY.md
CHANGED
|
@@ -58,7 +58,7 @@ Verification here is not a benchmark. In production we exchange short turns and
|
|
|
58
58
|
>
|
|
59
59
|
> Be honest about its cost, because it is a MUST: it spends real model turns on the operator's configured runtimes (two pi siblings, each resumed once, plus one Claude Code sibling), it READS the operator's real runtime config, and the siblings' native session transcripts stay in the real pi agent dir — they are not cleaned up, and they are part of the evidence a resume was real. The fence is per-axis rather than absolute: the four meta roots (records, mailbox, receivers, senders) are fixture for every cell, so no garden record is ever minted outside it; the native pi cell's control socket and v2 lock are fixture too; the ACP pi cell's are REAL and transient (see the paragraph above); and the Claude cell runs its runtime under the real HOME while its mailbox and meta stay fixture. The run ends by proving the operator's SIX real roots — the four meta roots plus `~/.pi/entwurf-control` and `~/.pi/entwurf-v2-locks` — hold the entry sets they started with, with no fixture garden id anywhere, and that proof now runs on the failure path as well as the green one. Missing prerequisites decline with the protocol SKIP (97), which `release-gate --cut` refuses rather than rounding up.
|
|
60
60
|
>
|
|
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
|
|
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 four model turns (two in the caller's own session, two in a second SEAT session on the same private server — the #105 seat x cwd matrix), 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. **Both this smoke and `smoke-mux-lifecycle-live` enumerate `pi` and `claude-code` only — that exclusion is intentional.** A Copilot visible-fresh (step 9 clause 7) was accepted on 2026-08-25 as an operator-metered LIVE (receipts in `DELIVERY.md`'s Copilot matrix row and the issue #82 thread). It still spends Copilot premium quota, still needs its own grant to re-run, and is never folded into those loops or into the release-gate MUST tier.
|
|
62
62
|
|
|
63
63
|
> **A visible-fresh receipt outside the MUST tier is no longer the general rule — it is Copilot's preserved exception.** #87 measured what that wording permitted: because clause 7 sat outside every aggregate, a harness could be admitted as a full D6 citizen that `entwurf_fresh_call` cannot open, carry an honest "not a supported harness" sentence in the delivery matrix, and still pass the whole floor toward a cut. From OMP onward, the FIRST release of a harness admitted under the #82 contract owes its clause 7 receipt as a release-gate MUST step (`smoke-omp-fresh-live`), and the deterministic half of the same rule (`check-harness-admission-parity`, inside `check:full`) makes a citizen backend missing from `FRESH_CALL_BACKENDS` a red floor rather than a documented one. Forward-only by decision: Copilot's row is not reopened. The contract lives in `docs/adding-a-harness.md` step 9, "The release stop"; this note exists so the cost discipline above is not read as permission.
|
|
64
64
|
>
|
|
@@ -77,6 +77,7 @@ Do not collapse source, package, fixture, and native-host evidence into one “g
|
|
|
77
77
|
| Packed install | `check-pack-install` | Real tarball, but checkout-visible. |
|
|
78
78
|
| Linux artifact consumer | required `check-install-container` CI job against one preserved candidate | Fixtures prove package/oracle shape, not a real Claude lifecycle. |
|
|
79
79
|
| Exact release commit | all required CI jobs green, and the `check` job's qualification body step concluded success, at the exact SHA | A different green SHA is not transferable evidence. |
|
|
80
|
+
| macOS Entwurf-only install | required `macos-install-surface` CI job at the exact release SHA | Shape-only, CERTIFIED (CI): certifies the Entwurf-only install path on macOS only — never Claude/Copilot/OMP/agy wiring, the pi rail, ACP or mux. Promoted from non-voting (`continue-on-error`) to required in 0.20.0 after its first CERTIFIED (CI) green on a GitHub Actions `macos-latest` runner (not a physical host): run 34303884286 @ `70eda03` (2026-09-09), 65s, all 10 steps success — the packed candidate installed clean, `entwurf --help` and `entwurf check-bridge` ran (the latter listing the seven current `entwurf-bridge` MCP tools), an all-harness-absent `entwurf setup` reached `result: green` across the five documented SKIP probes (`pi`/`claude`/`agy`/`copilot`/`omp`), and five checked paths (`.pi`, `settings.json`, `.gemini`, `.copilot`, `auth.json.bak`) plus a byte-identical `auth.json` proved zero harness/credential writes. A macOS runner failure now blocks every release cut, the same as any other required job. |
|
|
80
81
|
| LIVE runtime | `LIVE=1 ./run.sh release-gate <scratch> --cut` plus any shipped on-demand backend axis | `--cut` enforces `SKIP=0`; a red wired gate blocks the cut. |
|
|
81
82
|
| Native Claude host | installed strict doctor against a new real session | Missing live join is `NOT CERTIFIED`, not a fixture PASS. |
|
|
82
83
|
| Native agy host | three doctors plus conversation-id-gated native-push round trip | Aggregate release-gate does not own an agy conversation id. |
|
|
@@ -155,6 +156,13 @@ Expected tail on a fully green host: `DONE: entwurf setup — result: green (com
|
|
|
155
156
|
|
|
156
157
|
The wiring / meta-bridge / smoke steps are internal building blocks of `setup` (`install_local_package`, `scripts/meta-bridge-install.sh`, `validate_entwurf_bridge`) — call `setup`, never the parts. Consumers who `npm install @junghanacs/entwurf` get the obvious npm surface; that path is not the developer concern here.
|
|
157
158
|
|
|
159
|
+
Installation portability and rail certification are separate axes (Hard Rule 17).
|
|
160
|
+
A harness-absent `setup` on the macOS CI runner reaching `result: green` is
|
|
161
|
+
CERTIFIED (CI) for the Entwurf-only install surface only. On a platform that is
|
|
162
|
+
not certified, a detected harness is named non-green (FAIL) whose wording is
|
|
163
|
+
not an install failure: the wiring WAS written, but the rail is NOT CERTIFIED —
|
|
164
|
+
pending physical host. That FAIL is the honest setup verdict, not a skip.
|
|
165
|
+
|
|
158
166
|
### 1.1 Variables (optional)
|
|
159
167
|
|
|
160
168
|
```bash
|
|
@@ -286,7 +294,7 @@ Pass: user/assistant turns accumulate normally; the transcript is not broken/emp
|
|
|
286
294
|
The minimum passing bar:
|
|
287
295
|
|
|
288
296
|
1. **Deterministic floor green:** `pnpm run check:full` passes (the core tier plus the hermetic-integration and package/install tiers, incl. `check-pack`), plus a `./run.sh check-gate-qualification` green on the same candidate.
|
|
289
|
-
2. **All
|
|
297
|
+
2. **All four required CI jobs green on the exact release commit:** `check`, `install-surface`, the required Linux `artifact-consumer`, and `macos-install-surface` — promoted from non-voting to required in 0.20.0 (see the release acceptance axes table above for what its green run does and does not certify); preserve the Linux artifact-consumer's tarball digest and image identity. A macOS runner failure now blocks the cut like any other required job.
|
|
290
298
|
3. **Live floor MUST green:** `LIVE=1 ./run.sh release-gate <dir> --cut` exits 0 reporting `MUST PASS=N FAIL=0 SKIP=0`; with `--cut` a single SKIP is red, so the exit code itself now carries this condition. A BEHAVIOR FAIL is advisory, not blocking.
|
|
291
299
|
4. **Native-host doctor green where the Claude meta-bridge is claimed:** a new post-install Claude session exists, live evidence is present, and the installed `doctor-meta-bridge` exits 0. `NOT CERTIFIED` is a release failure for that host, not a skip.
|
|
292
300
|
5. **Honest self-recognition:** the bridged model identifies its actual harness/backend, lists `entwurf-bridge` as the single MCP server with its seven current tools, and presents a backend-native (not normalized) tool surface.
|
package/docs/acp-backend-rail.md
CHANGED
|
@@ -197,7 +197,7 @@ operator's repair named.
|
|
|
197
197
|
|
|
198
198
|
| Seam | Claude | Cortex Code |
|
|
199
199
|
|---|---|---|
|
|
200
|
-
| Model ids | unprefixed `claude-sonnet-5`, `claude-opus-5` | `cortex-auto`, `cortex-claude-opus-5`, `cortex-claude-sonnet-5`, `cortex-openai-gpt-5.4`; prefix stripped before set-model |
|
|
200
|
+
| Model ids | unprefixed `claude-sonnet-5`, `claude-opus-5`, `claude-fable-5-1` | `cortex-auto`, `cortex-claude-opus-5`, `cortex-claude-sonnet-5`, `cortex-openai-gpt-5.4`; prefix stripped before set-model |
|
|
201
201
|
| Launch | bundled `claude-agent-acp`; `CLAUDE_AGENT_ACP_COMMAND` override | `cortex acp serve`; optional connection; `CORTEX_ACP_COMMAND` override; never a launch-time `-m` |
|
|
202
202
|
| Model authority | per-turn ACP set-model | per-turn ACP set-model; an unavailable curated id fails before prompt |
|
|
203
203
|
| Carrier | engraving in `_meta.systemPrompt` | no system-prompt carrier; engraving rides the first-user augment |
|
|
@@ -256,6 +256,14 @@ Cortex containment was measured against the live CLI rather than copied from Cla
|
|
|
256
256
|
exact-writes an overlay-private `cortex/mcp.json`. Non-stdio declarations fail before
|
|
257
257
|
spawn. Only the `entwurf-bridge` entry receives the real operator HOME required to
|
|
258
258
|
see the garden store.
|
|
259
|
+
- **`realHome` absoluteness:** the D10 guard judges the captured `realHome` in BOTH
|
|
260
|
+
path flavors (POSIX and win32), so the refusal rule states the contract rather than
|
|
261
|
+
the host it happens to run on. This claims no native-Windows support — native
|
|
262
|
+
Windows is UNSUPPORTED. The certified ACP axis remains Linux
|
|
263
|
+
desktop/workstation; macOS ACP turns are NOT CERTIFIED — pending physical
|
|
264
|
+
host. The flavor-explicit form only stops a POSIX host from reading a
|
|
265
|
+
drive/UNC path as relative, which is what made the defect unkillable on
|
|
266
|
+
Linux (PR #77).
|
|
259
267
|
- **Carrier:** Cortex has no `_meta.systemPrompt` contract. The engraving is placed at
|
|
260
268
|
the head of the first-user augment; claiming a system-prompt engraving is false.
|
|
261
269
|
|
|
@@ -11,7 +11,7 @@ the one-line registration; everything an operator needs to actually wire a host
|
|
|
11
11
|
|
|
12
12
|
**Being garden-native is not the same as being replyable, and Copilot is the case that separates them.** Its hook writes a sender marker, so an `entwurf_v2` send carries its own garden id and the receiver learns who wrote — measured 2026-08-21 on Copilot CLI 1.0.80, where a live send arrived under its own garden id with `origin: "meta-session"` and `replyable: false`. Replyability arrived later and through a different process: a first-party extension (`run.sh install-copilot-receive`) that the CLI forks, which binds to the same V3 record and writes a receiver marker owned by its own pid (#82 RAIL 5). So a Copilot citizen is `replyable: true` exactly while that extension is armed for it, and `replyable: false` — honestly, with a real garden identity — when it is not installed, not launched with `COPILOT_CLI_ENABLED_FEATURE_FLAGS=EXTENSIONS` (which is what `entwurf copilot` sets for one invocation), not yet born, or gone. Read the two facts off different rails: the sender marker answers *who sent this*; the receiver marker answers *can a reply land*. The onboarding obligations are in [`adding-a-harness.md`](./adding-a-harness.md) step 7, and the evidence boundary — the managed LIVE acceptance that moved receive to D6, and what D7-partial / D3-pending still exclude — is in [`DELIVERY.md`](../DELIVERY.md).
|
|
13
13
|
|
|
14
|
-
**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, a mailbox-backed self-fetch citizen (Claude Code, Copilot, OMP), 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 on the server's PATH (`pi`, `claude`, `entwurf` or `omp` — Copilot opens through the managed `entwurf copilot` invocation, never the bare vendor, while OMP is opened as the bare `omp` runtime); resume call always needs `pi`. Both start a runtime, while delivery does not. (The old v1 verbs `entwurf` / `entwurf_resume` / `entwurf_send` are gone.)
|
|
14
|
+
**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, a mailbox-backed self-fetch citizen (Claude Code, Copilot, OMP), 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?, placement?}`**, 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 also accepts one optional `placement.tmuxSession`: the exact name of an EXISTING session on the caller's own tmux server, so the sibling opens in the operator's project seat rather than beside the caller. It creates nothing — an absent session is refused as `tmux-session-missing`, a name outside `[A-Za-z0-9][A-Za-z0-9_-]*` as `tmux-session-name-invalid`, and no window and no session are left behind either way. The seat and the `cwd` never infer each other: with `cwd` omitted a seated sibling starts in the CALLING agent's own directory, not the target session's path. Fresh call needs its selected runtime on the server's PATH (`pi`, `claude`, `entwurf` or `omp` — Copilot opens through the managed `entwurf copilot` invocation, never the bare vendor, while OMP is opened as the bare `omp` runtime); resume call always needs `pi`. Both start a runtime, while delivery does not. (The old v1 verbs `entwurf` / `entwurf_resume` / `entwurf_send` are gone.)
|
|
15
15
|
|
|
16
16
|
Observed: Claude Code, Codex CLI, Antigravity CLI, GitHub Copilot CLI and OMP 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, Copilot and OMP become symmetric/replyable through a mailbox-backed meta-session — Claude's watch armed by its own hook, Copilot's by the forked extension it installs, OMP's by an extension running inside the operator's own TUI process; 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.
|
|
17
17
|
|
|
@@ -52,9 +52,12 @@ Prerequisites on the host running the external MCP client:
|
|
|
52
52
|
> carrier reader trims and tests truthiness, so empty and absent are the same answer by
|
|
53
53
|
> construction. Pinned by `[QK:FRESHCALL-IDENTITY-SCRUB]` in the `check-mux-fresh-call` vitest lane,
|
|
54
54
|
> inside `check:full`. The DETECT half is unchanged and still load-bearing, because a seam covers
|
|
55
|
-
> only the launches that pass through it: `doctor-omp-bridge` reads
|
|
56
|
-
>
|
|
57
|
-
>
|
|
55
|
+
> only the launches that pass through it: `doctor-omp-bridge` reads each live `omp`
|
|
56
|
+
> process's environment (on Linux, `/proc/<pid>/environ`) and goes RED on its own
|
|
57
|
+
> axis when one carries either carrier. The remaining uncertified Darwin axis is
|
|
58
|
+
> per-process environment DISCOVERY, not `/proc` absence; macOS rails are
|
|
59
|
+
> NOT CERTIFIED — pending physical host. An omp the operator started
|
|
60
|
+
> from a pi citizen's bash never touched the seam and is still unsupported, exactly
|
|
58
61
|
> as this boundary says.
|
|
59
62
|
|
|
60
63
|
Example env file:
|
|
@@ -151,7 +154,7 @@ entwurf doctor-agy-hooks
|
|
|
151
154
|
|
|
152
155
|
The three adapters deliberately own different atoms:
|
|
153
156
|
|
|
154
|
-
- bridge: one `entwurf-bridge` server in `~/.gemini/config/mcp_config.json`, plus one narrow permission string per tool the normal agy workflow calls — `mcp(entwurf-bridge/entwurf_v2)`, `mcp(entwurf-bridge/entwurf_peers)`, `mcp(entwurf-bridge/entwurf_self)` — in `~/.gemini/antigravity-cli/settings.json`. agy defaults every `mcp` action to Ask, so a tool that ships without its own rule stops for a y/n on every call; `entwurf_inbox_read` is deliberately not granted (native-push has no inbox), neither is the manual `entwurf_register_native` fallback, and neither are `entwurf_fresh_call` / `entwurf_resume_call` (both launch into the caller's own tmux
|
|
157
|
+
- bridge: one `entwurf-bridge` server in `~/.gemini/config/mcp_config.json`, plus one narrow permission string per tool the normal agy workflow calls — `mcp(entwurf-bridge/entwurf_v2)`, `mcp(entwurf-bridge/entwurf_peers)`, `mcp(entwurf-bridge/entwurf_self)` — in `~/.gemini/antigravity-cli/settings.json`. agy defaults every `mcp` action to Ask, so a tool that ships without its own rule stops for a y/n on every call; `entwurf_inbox_read` is deliberately not granted (native-push has no inbox), neither is the manual `entwurf_register_native` fallback, and neither are `entwurf_fresh_call` / `entwurf_resume_call` (both launch into the caller's own tmux server, which an agy conversation has none of);
|
|
155
158
|
- statusline: the complete `statusLine` subtree pointing at the bare stable bin `entwurf-agy-statusline`;
|
|
156
159
|
- hooks: one named `PreInvocation` hook pointing at the bare stable bin `entwurf-agy-imprint`.
|
|
157
160
|
|
package/docs/setup-clean-host.md
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
# Clean-host setup
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Operator recipe for a POSIX host. **Linux is the certified axis** — §2–§6 are
|
|
4
|
+
written for it and their receipts are Linux receipts. What follows is the macOS
|
|
5
|
+
evidence split, and its three states must not collapse into "macOS is supported":
|
|
6
|
+
|
|
7
|
+
- **CERTIFIED (CI)** — the Entwurf-only install surface on macOS
|
|
8
|
+
(`macos-install-surface`). Weaker than a physical-host doctor green. §1 is
|
|
9
|
+
this surface.
|
|
10
|
+
- **NOT CERTIFIED — pending physical host** — **on macOS**, every garden-native
|
|
11
|
+
harness rail in §2–§6 (pi, Claude, Copilot, OMP, agy), marker join, ACP turn,
|
|
12
|
+
mux. Wiring may be written; that is not a rail receipt. The remaining
|
|
13
|
+
unmeasured Darwin doctor reason is per-process environment DISCOVERY
|
|
14
|
+
(start-key is portable).
|
|
15
|
+
- **UNSUPPORTED** — native Windows only. macOS is never this.
|
|
6
16
|
|
|
7
17
|
## Requirements
|
|
8
18
|
|
|
@@ -22,8 +32,35 @@ only on Linux because its strict live-owner join uses `/proc`.
|
|
|
22
32
|
Claude Code >=2.1.217 is required for the managed exec-hook lifecycle. The package
|
|
23
33
|
never supplies or proxies backend credentials.
|
|
24
34
|
|
|
35
|
+
On a physical Darwin host, `python3` may be the CommandLineTools stub (a
|
|
36
|
+
dialog instead of an interpreter) — unmeasured. That is a probe cell
|
|
37
|
+
(`scripts/raw-macos-measure/probe.sh` M3), not a certification path.
|
|
38
|
+
|
|
25
39
|
## 1. Install Node and entwurf
|
|
26
40
|
|
|
41
|
+
This section is the Entwurf-only install surface. On macOS it is
|
|
42
|
+
**CERTIFIED (CI)** (`macos-install-surface`): npm pack → clean consumer
|
|
43
|
+
install → bins → `--help` → `check-bridge` → harness-absent `setup`. That
|
|
44
|
+
is not a harness-rail receipt.
|
|
45
|
+
|
|
46
|
+
On Darwin, `entwurf setup` is intentionally non-green when it detects a
|
|
47
|
+
harness. The wiring is written; the row is FAIL:
|
|
48
|
+
|
|
49
|
+
> the wiring WAS written and nothing failed to install, but this harness
|
|
50
|
+
> rail is NOT CERTIFIED — pending physical host on Darwin. setup runs no
|
|
51
|
+
> doctor; the rail axis is owned by '<doctor>', which refuses on this
|
|
52
|
+
> platform. Tracking: #78.
|
|
53
|
+
|
|
54
|
+
That FAIL is honest: setup runs no doctor, and no physical-host rail
|
|
55
|
+
receipt exists — it is not an install failure. An Entwurf-only host (no
|
|
56
|
+
harness on PATH) stays green (five SKIP, `bins: PASS`, `core: PASS`,
|
|
57
|
+
`result: green`), which is what CERTIFIED (CI) observed.
|
|
58
|
+
|
|
59
|
+
A physical Mac can send host facts without installing entwurf or logging
|
|
60
|
+
into a harness: `scripts/raw-macos-measure/probe.sh` (`/bin/sh`, ~3.5s,
|
|
61
|
+
cells M1–M9, writes nothing). Measurement, not certification — it does
|
|
62
|
+
not move CERTIFIED (CI) or close a rail.
|
|
63
|
+
|
|
27
64
|
Use the host's normal Node 24 installation. With nvm:
|
|
28
65
|
|
|
29
66
|
```bash
|
|
@@ -107,6 +144,12 @@ packageRoot↔installerRoot coupling mismatch and a package/provider managed-pat
|
|
|
107
144
|
|
|
108
145
|
## 2. Optional pi adapter / ACP plugin
|
|
109
146
|
|
|
147
|
+
This rail is CERTIFIED on Linux; on macOS it is NOT CERTIFIED — pending
|
|
148
|
+
physical host. Control sockets, mux, and ACP plugin hosting have no
|
|
149
|
+
physical-Darwin receipt. `entwurf install` may write `.pi/settings.json`
|
|
150
|
+
on Darwin; that is wiring, not a rail receipt. If `pi` is on PATH,
|
|
151
|
+
`setup` names the pi row FAIL with the §1 Darwin wording.
|
|
152
|
+
|
|
110
153
|
Install the exact release floor, then wire the project:
|
|
111
154
|
|
|
112
155
|
```bash
|
|
@@ -134,6 +177,9 @@ The V3 record births the garden id; do not inject a pi session id manually.
|
|
|
134
177
|
|
|
135
178
|
## 3. Optional Claude Code native citizen
|
|
136
179
|
|
|
180
|
+
This rail is CERTIFIED on Linux; on macOS it is NOT CERTIFIED — pending physical
|
|
181
|
+
host (see the end of this section).
|
|
182
|
+
|
|
137
183
|
First register the MCP bridge if the stable bin is not already present:
|
|
138
184
|
|
|
139
185
|
```bash
|
|
@@ -159,12 +205,21 @@ validation, or hand-inspected marker cannot replace a new real session. If the l
|
|
|
159
205
|
form is unsupported, reinstall; if ownership is correct but the live join is absent,
|
|
160
206
|
restart the affected session.
|
|
161
207
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
208
|
+
The Darwin install fence is open (`Linux | Darwin`); python3 is the
|
|
209
|
+
refusal, not the platform name. A completed Darwin install is still not
|
|
210
|
+
a rail receipt: this rail is NOT CERTIFIED — pending physical host. The
|
|
211
|
+
remaining unmeasured doctor reason is per-process environment DISCOVERY
|
|
212
|
+
of live bridge children (start-key is portable). A CI runner cannot
|
|
213
|
+
supply a Claude login. Uninstall is open on Darwin too. That is an
|
|
214
|
+
evidence boundary, not UNSUPPORTED.
|
|
165
215
|
|
|
166
216
|
## 4. Optional GitHub Copilot CLI native citizen
|
|
167
217
|
|
|
218
|
+
This rail is CERTIFIED on Linux; on macOS it is NOT CERTIFIED — pending
|
|
219
|
+
physical host. The Darwin install fence for `install-copilot-bridge` is
|
|
220
|
+
open (`Linux | Darwin`); a completed install is not a rail receipt. That
|
|
221
|
+
is an evidence boundary, not UNSUPPORTED.
|
|
222
|
+
|
|
168
223
|
Copilot has four independently owned surfaces. `setup` composes all four when `copilot` is on
|
|
169
224
|
PATH (#86 C3b); the commands below are the per-unit repair, doctor, and inverse surfaces. All
|
|
170
225
|
four must be green for supported visible fresh; a manual citizen may omit the footer, but fresh
|
|
@@ -187,7 +242,12 @@ scanning for that process, checks the receiver, removes inherited pi identity ca
|
|
|
187
242
|
the model/permission defaults. Birth occurs on the first prompt. `entwurf_fresh_call` uses this
|
|
188
243
|
same managed invocation and requires the birth, MCP, receiver, and visible-identity preflight.
|
|
189
244
|
|
|
190
|
-
## 4b. Optional OMP (`omp`) native citizen — accepted on one host
|
|
245
|
+
## 4b. Optional OMP (`omp`) native citizen — accepted on one Linux host (thinkpad)
|
|
246
|
+
|
|
247
|
+
This rail is CERTIFIED on Linux (one host, named in the version rule
|
|
248
|
+
below); on macOS it is NOT CERTIFIED — pending physical host. The Darwin
|
|
249
|
+
install fences for `install-omp-bridge` and `install-omp-receive` are
|
|
250
|
+
open (`Linux | Darwin`); a completed install is not a rail receipt.
|
|
191
251
|
|
|
192
252
|
Three independently owned surfaces, and a boundary that is part of the instructions rather
|
|
193
253
|
than a footnote. Birth, visible identity, who-sent, the MCP hand and RECEIVE are landed, and
|
|
@@ -338,6 +398,10 @@ why `disabledServers` is never the way to hide an import.
|
|
|
338
398
|
|
|
339
399
|
## 5. Optional Antigravity native citizen
|
|
340
400
|
|
|
401
|
+
This rail is CERTIFIED on Linux; on macOS it is NOT CERTIFIED — pending
|
|
402
|
+
physical host. The installers may write on Darwin; a green install is
|
|
403
|
+
not a native-push receipt.
|
|
404
|
+
|
|
341
405
|
Install the three independently owned surfaces:
|
|
342
406
|
|
|
343
407
|
```bash
|
|
@@ -363,6 +427,10 @@ LIVE=1 AGY_CONVERSATION_ID=<id> entwurf smoke-agy-native-push-live
|
|
|
363
427
|
|
|
364
428
|
## 6. Optional ACP backend turns
|
|
365
429
|
|
|
430
|
+
ACP turns are CERTIFIED on Linux; on macOS they are NOT CERTIFIED —
|
|
431
|
+
pending physical host. Mux (visible fresh / resume) is the same state.
|
|
432
|
+
A CI runner has no Claude or Cortex login.
|
|
433
|
+
|
|
366
434
|
Claude uses the operator's existing local Claude authentication:
|
|
367
435
|
|
|
368
436
|
```bash
|
|
@@ -386,6 +454,15 @@ After upgrading the package, rerun the managed installers for every native harne
|
|
|
386
454
|
in use and restart their existing processes. Native plugin caches are not live-reload
|
|
387
455
|
safe across launch-contract changes.
|
|
388
456
|
|
|
457
|
+
On Darwin the four previously closed install fences
|
|
458
|
+
(`install-meta-bridge`, `install-copilot-bridge`, `install-omp-bridge`,
|
|
459
|
+
`install-omp-receive`) now accept `Linux | Darwin` and refuse on the
|
|
460
|
+
real toolchain (python3 / node / harness presence), not the platform
|
|
461
|
+
name. Re-running them writes wiring. `setup` still names every detected
|
|
462
|
+
harness unit FAIL with the §1 Darwin wording — upgrade does not mint a
|
|
463
|
+
rail receipt. Doctors refuse on Darwin until a physical-host receipt
|
|
464
|
+
exists.
|
|
465
|
+
|
|
389
466
|
If install or doctor reports an unreadable/old active citizen generation, do not edit
|
|
390
467
|
records by hand. Close pi, Claude, Copilot, and agy sessions first, run
|
|
391
468
|
`entwurf meta-bridge-fresh-cut`, and read its exit status before any install. Then choose the
|
|
@@ -414,6 +491,10 @@ PASS/SKIP/FAIL summary. The complete quiescence, archive, and exit-code contract
|
|
|
414
491
|
core / full candidate floor); maintainer checkout only.
|
|
415
492
|
- `check-install-container`: checkout-invisible Linux package-consumer shape using
|
|
416
493
|
fixtures; not a native lifecycle proof.
|
|
494
|
+
- `macos-install-surface`: macOS Entwurf-only package-consumer shape, CERTIFIED (CI)
|
|
495
|
+
(`macos-latest` runner, run 34303884286 @ `70eda03`); not a native lifecycle proof.
|
|
496
|
+
- `scripts/raw-macos-measure/probe.sh`: physical-Darwin host facts (~3.5s,
|
|
497
|
+
no install, no login). Measurement, not a certification path.
|
|
417
498
|
- `doctor-meta-bridge`: one installed real Claude host, only with a new live session.
|
|
418
499
|
- `LIVE=1 entwurf release-gate /path/to/scratch --cut`: aggregate runtime acceptance (`--cut` makes any MUST SKIP red; without it the run is a diagnostic pass).
|
|
419
500
|
|
|
@@ -422,6 +503,11 @@ host verdicts are [BASELINE.md](../BASELINE.md).
|
|
|
422
503
|
|
|
423
504
|
## Uninstall
|
|
424
505
|
|
|
506
|
+
Darwin uninstall is open for the same surfaces the installers write
|
|
507
|
+
(the Claude uninstall fence was already open; the four install fences
|
|
508
|
+
now match). Running an inverse on Darwin is cleanup, not a rail
|
|
509
|
+
certification.
|
|
510
|
+
|
|
425
511
|
Run only the surfaces this host owns:
|
|
426
512
|
|
|
427
513
|
```bash
|
|
@@ -26,10 +26,11 @@
|
|
|
26
26
|
* this read is the receipt.
|
|
27
27
|
* - entwurf_register_native — explicit/manual fallback binding an ALREADY-RUNNING native
|
|
28
28
|
* conversation (antigravity) to a garden id. Never a spawn.
|
|
29
|
-
* - entwurf_fresh_call — open ONE fresh visible sibling in the operator's
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
29
|
+
* - entwurf_fresh_call — open ONE fresh visible sibling in the operator's tmux — the caller's own
|
|
30
|
+
* session, or ONE EXISTING named session on the same server (the project
|
|
31
|
+
* seat, #105; nothing is ever created), optionally at ONE literal requested
|
|
32
|
+
* cwd (cross-repo fresh, #73); returns a LAUNCH receipt only, and the new
|
|
33
|
+
* address arrives later as the sender envelope of the sibling's nonce callback.
|
|
33
34
|
* - entwurf_resume_call — reopen ONE DORMANT pi citizen under its OWN garden id in a visible
|
|
34
35
|
* window; target-only, runs no turn, LAUNCH and OBSERVATION receipts stay
|
|
35
36
|
* apart.
|
|
@@ -609,7 +610,7 @@ server.tool("entwurf_register_native", "Register an ALREADY-RUNNING native conve
|
|
|
609
610
|
// its own garden id, a fresh cell answered with its uuidv7 `PI_SESSION_ID` value read out of the
|
|
610
611
|
// environment by an MCP server it had spawned itself — confidently, and wrong. A sibling launched
|
|
611
612
|
// against that answer would call home to a garden id nobody holds.
|
|
612
|
-
server.tool("entwurf_fresh_call", "Open ONE fresh visible sibling in the operator's
|
|
613
|
+
server.tool("entwurf_fresh_call", "Open ONE fresh visible sibling in the operator's tmux and hand it a first task. Four fixed " +
|
|
613
614
|
"backends only: pi, claude-code, copilot, omp. The sibling's FIRST action is a callback to you carrying a nonce, and the " +
|
|
614
615
|
"sender envelope of that callback is its garden id — that is how you learn the address of something that " +
|
|
615
616
|
"did not exist a moment ago. This returns a LAUNCH receipt (tmux window/pane plus that nonce) and nothing " +
|
|
@@ -624,6 +625,8 @@ server.tool("entwurf_fresh_call", "Open ONE fresh visible sibling in the operato
|
|
|
624
625
|
"prompt, so the sibling could not call you back at all). An optional " +
|
|
625
626
|
"cwd starts the sibling in ONE literal absolute existing directory (cross-repo fresh) — never pick resume " +
|
|
626
627
|
"for a dormant record's cwd; resume is continuity-only. Omitted/empty cwd means the caller's own directory. " +
|
|
628
|
+
"An optional placement.tmuxSession opens it in ONE EXISTING session of this agent's own tmux server; an " +
|
|
629
|
+
"absent SESSION is tmux-session-missing and NOTHING is created. Omit placement for the caller's own session. " +
|
|
627
630
|
"There are no arbitrary command/env knobs. Do not put secrets in the task — model and task argv are visible to " +
|
|
628
631
|
"same-user processes on this host. Requires that this agent itself runs " +
|
|
629
632
|
"inside tmux: without a pane anchor there is no session to open a sibling beside.", {
|
|
@@ -653,7 +656,15 @@ server.tool("entwurf_fresh_call", "Open ONE fresh visible sibling in the operato
|
|
|
653
656
|
.string()
|
|
654
657
|
.optional()
|
|
655
658
|
.describe("Optional literal ABSOLUTE path of an existing directory to start the sibling in (cross-repo fresh). Omit or pass \"\" to start in this agent's own cwd. Taken exactly as given — no trim, no realpath, no project-name resolution; '#' is refused (tmux format expansion). The receipt echoes what was REQUESTED, never an observation."),
|
|
656
|
-
|
|
659
|
+
placement: z
|
|
660
|
+
.object({
|
|
661
|
+
tmuxSession: z
|
|
662
|
+
.string()
|
|
663
|
+
.describe("EXACT name of an EXISTING session on this agent's own tmux server. Nothing is created: an absent session is refused as tmux-session-missing, and a name outside [A-Za-z0-9][A-Za-z0-9_-]* as tmux-session-name-invalid."),
|
|
664
|
+
})
|
|
665
|
+
.optional()
|
|
666
|
+
.describe("Optional project seat: open the sibling in ONE EXISTING tmux session of this agent's own server instead of the caller's session. Nothing is ever created — an absent session is a refusal, not a new session. Independent of cwd; neither is inferred from the other. The receipt echoes the REQUESTED name and reports the resolved target session id."),
|
|
667
|
+
}, async ({ backend, model, task, cwd, placement }) => {
|
|
657
668
|
let callerGardenId = null;
|
|
658
669
|
try {
|
|
659
670
|
const self = await buildAuthoritativeSelfEnvelope();
|
|
@@ -672,7 +683,7 @@ server.tool("entwurf_fresh_call", "Open ONE fresh visible sibling in the operato
|
|
|
672
683
|
callerGardenId = null;
|
|
673
684
|
}
|
|
674
685
|
try {
|
|
675
|
-
const rendered = renderFreshCall(freshCall({ backend, model, task, cwd, callerGardenId }));
|
|
686
|
+
const rendered = renderFreshCall(freshCall({ backend, model, task, cwd, placement, callerGardenId }));
|
|
676
687
|
return rendered.isError ? textErr(rendered.text) : textOk(rendered.text);
|
|
677
688
|
}
|
|
678
689
|
catch (err) {
|
|
@@ -49,11 +49,11 @@ export const ENTWURF_ACP_NO_AUTH_SENTINEL = "entwurf-no-auth";
|
|
|
49
49
|
// both axes (protocol smoke + agent interview) — do not extend casually.
|
|
50
50
|
// Exported so the claude backend adapter (backend-adapter.ts) can answer
|
|
51
51
|
// `routeModel` without re-deriving the set from curatedClaudeModels().
|
|
52
|
-
export const SUPPORTED_ANTHROPIC_MODEL_IDS = ["claude-sonnet-5", "claude-opus-5"];
|
|
52
|
+
export const SUPPORTED_ANTHROPIC_MODEL_IDS = ["claude-sonnet-5", "claude-opus-5", "claude-fable-5-1"];
|
|
53
53
|
/** The anchor model whose absence is a hard registry regression, not a soft skip. */
|
|
54
54
|
export const CURATED_ANCHOR_MODEL_ID = "claude-opus-5";
|
|
55
|
-
// Anthropic's registry reports 1M for
|
|
56
|
-
// entwurf surface exposes the full 1M for
|
|
55
|
+
// Anthropic's registry reports 1M for Sonnet 5, Opus 5 and Fable 5.1, and the
|
|
56
|
+
// entwurf surface exposes the full 1M for all three. Sonnet 5's 1M window is the
|
|
57
57
|
// whole point of the 0.12.3 bump — it is the compact-free long-context floor the
|
|
58
58
|
// earlier 200K Sonnet cap could not provide. We still clamp to a 1M ceiling so a
|
|
59
59
|
// future registry value can't silently inflate the surface past what we verify.
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
import { createHash } from "node:crypto";
|
|
36
36
|
import { existsSync, lstatSync, mkdirSync, readdirSync, readlinkSync, rmSync, symlinkSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
37
37
|
import { homedir } from "node:os";
|
|
38
|
-
import { join } from "node:path";
|
|
38
|
+
import { isAbsolute, join, win32 } from "node:path";
|
|
39
39
|
/** Operator's real Claude config dir — the symlink-passthrough SOURCE. */
|
|
40
40
|
export const CLAUDE_REAL_CONFIG_DIR = join(homedir(), ".claude");
|
|
41
41
|
/** pi-owned overlay dir — the CLAUDE_CONFIG_DIR target for ACP child spawns. */
|
|
@@ -356,7 +356,11 @@ function cortexLinkIfExists(realPath, overlayPath) {
|
|
|
356
356
|
* Returns the isolated HOME/SNOWFLAKE_HOME the spawn env must carry.
|
|
357
357
|
*/
|
|
358
358
|
export function ensureCortexDualHomeOverlay(params) {
|
|
359
|
-
|
|
359
|
+
// Absoluteness is judged in BOTH path flavors so the guard states the contract
|
|
360
|
+
// ("the parent captured an absolute HOME") instead of the host it happens to run
|
|
361
|
+
// on. This asserts nothing about native-Windows support; it only stops a POSIX
|
|
362
|
+
// host from silently accepting a drive/UNC path as "relative".
|
|
363
|
+
if (!params.realHome || !(isAbsolute(params.realHome) || win32.isAbsolute(params.realHome))) {
|
|
360
364
|
throw new Error(`entwurf: cortex dual-HOME overlay requires an absolute realHome captured by the parent (got ${JSON.stringify(params.realHome)})`);
|
|
361
365
|
}
|
|
362
366
|
const overlaysRoot = params.overlaysRoot ?? CORTEX_OVERLAYS_ROOT;
|