@junghanacs/entwurf 0.15.0 → 0.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -0
- package/CHANGELOG.md +70 -0
- package/DELIVERY.md +1 -1
- package/README.md +67 -18
- package/VERIFY.md +9 -6
- package/docs/acp-backend-rail.md +1 -1
- package/docs/setup-clean-host.md +116 -16
- package/package.json +2 -2
- package/run.sh +746 -171
- package/scripts/agy-bridge.sh +4 -2
- package/scripts/check-copilot-birth-hook.ts +700 -23
- package/scripts/check-fresh-cut-gate.sh +12 -4
- package/scripts/check-gate-qualification.ts +4 -1
- package/scripts/check-setup-qualification.sh +126 -0
- package/scripts/copilot-bridge-doctor.sh +104 -71
- package/scripts/copilot-bridge-install.sh +180 -20
- package/scripts/copilot-bridge-oracle.sh +223 -0
- package/scripts/copilot-bridge-uninstall.sh +137 -0
- package/scripts/dev-bin.sh +50 -9
- package/scripts/fake-copilot-vendor.sh +67 -0
- package/scripts/mutants/copilot-birth.json +89 -0
- package/scripts/mutants/pi-package-ownership.json +92 -0
- package/scripts/mutants/setup-verdict.json +148 -0
- package/scripts/mutants/source-install.json +32 -0
- package/scripts/pi_settings_io.py +22 -0
- package/scripts/register-pi-package.py +525 -7
- package/scripts/register-pi-provider.py +162 -12
- package/scripts/smoke-agy-install-state.sh +86 -30
- package/scripts/smoke-agy-statusline-state.sh +9 -6
- package/scripts/smoke-setup-verdict.sh +291 -0
- package/scripts/smoke-user-scope-citizen.sh +388 -1
package/AGENTS.md
CHANGED
|
@@ -51,6 +51,7 @@ For agents that own this repo: invariant principles and reproducible verificatio
|
|
|
51
51
|
14. **Native hook ownership is structural.** Claude hooks use the shipped exec-form launcher and provenance token; marker writers/readers share `isPlausibleOwnerPid`; no shell-form fallback, ancestry guess, or retired pid carrier. entwurf requires Claude Code `>=2.1.217` and enforces that floor itself because upstream gives no fail-loud — an older Claude validates the exec manifest, then drops `args` at runtime and reports success. The number is derived from `package.json` `entwurf.claudeCodeFloor`, never retyped as a second source. Currently certified axis is Linux desktop/workstation. Source/gates: `hook-launch.sh`, `meta-session.ts`, `check-hook-launch-topology`, `check-claude-floor-coherence`, `check-meta-doctor-oracle`.
|
|
52
52
|
15. **Crash, don't warn.** Bad config/path/model/store state throws. Empty catches are only for bounded environment probing; operator diagnostics go to stderr.
|
|
53
53
|
16. **mux is launch, never delivery.** A tmux window/pane handle is an ephemeral operator view, not an address: it mints no garden id, stores no record, and reports no liveness. Screen text and keystrokes are never an `entwurf_v2` receipt. Mux owns only placement and fixed-runtime launch; fresh identity correlation stays in callback envelopes, while same-id resume identity/liveness/locking stays on the v2 side of an injected launch seam.
|
|
54
|
+
17. **Entwurf installs itself; setup composes what the operator already chose.** Package installation and source bootstrap supply Entwurf's own bytes, bins, dependencies and development fixtures only. They never install a harness binary, subscription, credential or login — `pi` has no privileged exception. `setup` detects already-present harnesses by capability and completes each detected integration; absence is an explicit zero-state SKIP, while a detected-but-incomplete integration is named non-green rather than cosmetic success. Source-only pinned Pi dev dependencies are build/test fixtures, not a product promise that neutral npm consumers receive Pi. Installation portability and rail/runtime support are separate evidence axes: Linux proof never certifies macOS or native Windows, and WSL counts as Linux rather than Windows.
|
|
54
55
|
|
|
55
56
|
Detailed incident histories belong in CHANGELOG/issues/BASELINE and source-adjacent comments, not in this prompt. When a concise rule and old archaeology disagree, verify source + gate and repair the stale prose.
|
|
56
57
|
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,76 @@ All notable changes to this project will be documented here. Format follows [Kee
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## 0.15.1 — 2026-08-27
|
|
8
|
+
|
|
9
|
+
This patch is the Linux install-honesty floor for #86: Entwurf installs itself only,
|
|
10
|
+
`setup` composes harnesses the operator already chose, and a detected integration that
|
|
11
|
+
cannot be completed makes the command non-green. It is not a new garden capability.
|
|
12
|
+
macOS and native-Windows implementation move to #78; this cut makes no cross-platform
|
|
13
|
+
support claim.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- **`setup` is presence-driven composition, not recruitment.** Mode is a named
|
|
18
|
+
source-versus-installed branch before any prerequisite check or write. Each detected
|
|
19
|
+
harness (pi, Claude Code, Copilot, agy) is completed independently; absence is
|
|
20
|
+
zero-state SKIP; below-floor or incomplete is named FAIL and a nonzero exit. The old
|
|
21
|
+
unconditional `DONE ... green` is gone — the summary is computed from component
|
|
22
|
+
outcomes. Pi is optional-by-presence with the package-derived floor `>=0.84.3 <0.85`.
|
|
23
|
+
A detected Copilot composes all four native units (birth → MCP → receiver → visible
|
|
24
|
+
footer). Installed-package setup never runs npm/pnpm inside `node_modules`. (#86)
|
|
25
|
+
- **The shared Pi user-scope registration has a recorded owner.** Silent
|
|
26
|
+
last-writer-wins normalization is retired. A second root's install/setup/remove refuses
|
|
27
|
+
with zero settings writes and names `takeover-user-scope`; only that explicit operator
|
|
28
|
+
verb moves the entry (old→new reported). The inverse removes only the recorded owner's
|
|
29
|
+
exact entry. (#86 C2)
|
|
30
|
+
- **Setup no longer mutates credential stores.** The unconditional `sync_auth` path that
|
|
31
|
+
copied the Anthropic OAuth object to an `entwurf` alias is removed. Hosts that already
|
|
32
|
+
ran the legacy path keep the alias and `auth.json.bak` as a documented manual cleanup,
|
|
33
|
+
not an automated one. (#86 A5)
|
|
34
|
+
|
|
35
|
+
### Added
|
|
36
|
+
|
|
37
|
+
- **Copilot birth has a package-owned inverse.** `uninstall-copilot-bridge` uses the
|
|
38
|
+
qualified `plugin@marketplace` identity, runs a read-only ownership/safety preflight
|
|
39
|
+
before any vendor write, and refuses to remove an unproven foreign unit. Installer,
|
|
40
|
+
inverse, and doctor share one structural oracle. (#86 C3a)
|
|
41
|
+
- **Packed-consumer and all-absent setup rows are first-class fixtures.**
|
|
42
|
+
`smoke-setup-verdict` and the installed `entwurf setup` path inside `check-pack-install`
|
|
43
|
+
prove absence, independence, false-success refusal, and the named installed-versus-source
|
|
44
|
+
branch without a model turn. That npm-consumer harness is the Linux install evidence
|
|
45
|
+
#78 waits on. (#86)
|
|
46
|
+
|
|
47
|
+
### Fixed
|
|
48
|
+
|
|
49
|
+
- **Source setup now exposes the `entwurf` operator command Copilot fresh requires.**
|
|
50
|
+
`./run.sh setup` manages `~/.local/bin/entwurf` as an ownership-checked symlink to the
|
|
51
|
+
current checkout's `run.sh`, with per-bin state and an honest inverse. npm consumers
|
|
52
|
+
already received this command through package bin linking; the missing source half caused
|
|
53
|
+
`entwurf_fresh_call {backend:"copilot"}` to reject `runtime-unresolved` unless an unrelated
|
|
54
|
+
global package happened to mask the defect. Source setup now fails loud when that
|
|
55
|
+
operator path is foreign, outside PATH, or shadowed; helper units are attempted
|
|
56
|
+
independently and a foreign helper is a named FAIL, never a warning followed by cosmetic
|
|
57
|
+
success. The managed `entwurf copilot` boundary and every fresh/preflight/delivery
|
|
58
|
+
contract are unchanged. Discovered while rechecking #82. (#86)
|
|
59
|
+
|
|
60
|
+
### Verification
|
|
61
|
+
|
|
62
|
+
- **`pnpm run check:full`** — PASS, exit 0, 252s standalone / 247s inside the gate
|
|
63
|
+
on the 0.15.1 versioned tree (HEAD `4a23af1` + uncommitted changelog/version).
|
|
64
|
+
- **`LIVE=1 ./run.sh release-gate /tmp/entwurf-release-gate-0.15.1.hAAn7U --cut`** —
|
|
65
|
+
**MUST PASS=21 FAIL=0 SKIP=0, BEHAVIOR PASS=1 FAIL=0 SKIP=0, `cut: OK`.**
|
|
66
|
+
`check-gate-qualification` inside the gate killed **277/277** mutants across 33
|
|
67
|
+
lanes. Log: `/tmp/entwurf-release-gate-0.15.1.hAAn7U/release-gate.log`
|
|
68
|
+
(SHA-256 `aa1364922301e685c650670dd6556a3c27feacdf1481d850d8e2ef56ef5cb23e`).
|
|
69
|
+
|
|
70
|
+
### Notes
|
|
71
|
+
|
|
72
|
+
- #78 owns macOS and native-Windows implementation. WSL remains Linux evidence.
|
|
73
|
+
- Native-harness doctors stay the per-leaf live-certification surface. Setup writes
|
|
74
|
+
artifacts; a new session is still required before `doctor-meta-bridge` / Copilot receive
|
|
75
|
+
can go green on a host that already had processes open.
|
|
76
|
+
|
|
7
77
|
## 0.15.0 — 2026-08-25
|
|
8
78
|
|
|
9
79
|
This release admits Copilot CLI as a full self-fetch garden citizen — birth, an owned
|
package/DELIVERY.md
CHANGED
|
@@ -88,7 +88,7 @@ can be owned without being supported; a supported harness still has to walk
|
|
|
88
88
|
| **Codex app-server-backed TUI** | verified probe | D7; D8 unproven | WebSocket-over-UDS `turn/start` into a live `threadId`; status events expose completion. No owned native-citizen install/invocation lane. |
|
|
89
89
|
| **Codex embedded TUI** | deferred | D0 partial | No supported receive socket/hook on the measured standalone shape. |
|
|
90
90
|
| **Copilot CLI first-party extension** | raw transport probe; superseded by the owned product unit | D7 path observed; D3 control receipt incomplete; D8 unproven | CLI-spawned extension over stdio JSON-RPC; `joinSession()` + documented `fs.watch` → `session.send({mode:"enqueue"})`. Idle wake, exact-marker reply, and completion passed on 2026-08-23 (CLI 1.0.80, L4, one Linux host). Two-process isolation was observed but its decisive B log was not preserved. Kept as the transport receipt the owned receive unit was built on; the shipped unit differs deliberately — it announces the inbox instead of injecting the body. |
|
|
91
|
-
| **Copilot CLI garden citizen** |
|
|
91
|
+
| **Copilot CLI garden citizen** | shipped in 0.15.0; send + receive + visible fresh accepted on one host | D6; D7 partial; D3 pending; D8 unproven | Birth, garden id, MCP hand and record-backed sender identity are accepted; the RECEIVER is an installed first-party extension that binds to the V3 record, writes a receiver marker owned by the WATCHER pid, and rings a doorbell the model drains with `entwurf_inbox_read`. `wakeMode` is `self-fetch`, so dispatch reaches the mailbox rail: armed → delivered, unarmed/stale → the honest `mailbox-undeliverable` refusal. **D6 is the owned-invocation LIVE acceptance of 2026-08-23** — garden `20260823T181316-d9f6ba`, native `20fe30c8-b2bc-4600-91a0-8a409131be51`, CLI 1.0.80: receive log `joined`→`armed`→`doorbell fresh=1`→`rang`, mailbox `lastEnqueuedAt 09:23:41.235Z` / `lastReadAt 09:23:56.480Z`, and a model reply on the same record/native/gid chain. **Visible fresh (step 9 clause 7) is a separate LIVE, 2026-08-25** — launch window `@89`/`%89` nonce `mux-fresh-call-690529ae99f99faa2252aefb`; exact-callback garden `20260825T085721-f68be0`; one `entwurf_v2` → `meta-mailbox → enqueued`; same garden `lastReadAt 2026-08-24T23:57:47.784Z` plus same-gid reply; GLG saw footer garden id and a healthy multi-turn window. Those rows stay unmerged. D7 is PARTIAL: reply and read receipt were observed, the completion taxonomy and long-haul operation were not. D3 (second-session isolation of an owned invocation) is PENDING — observed once, decisive log lost to scratch cleanup. Evidence level L4: one host. Launch through the owned invocation `entwurf copilot`, which sets `COPILOT_CLI_ENABLED_FEATURE_FLAGS=EXTENSIONS` for that one process; `doctor-copilot-receive` reads live CLI environments because a session launched without it is silently inert. Visible fresh is operator-metered and is not a release-gate MUST. |
|
|
92
92
|
| **Copilot CLI TUI+server** — *withdrawn lane, kept as evidence* | rejected | D7; D8 unproven | Older official-SDK probe over hidden `--ui-server`; idle enqueue worked, but loopback RPC authentication was not established. The bundled extension supersedes this candidate without reviving it. |
|
|
93
93
|
| **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. |
|
|
94
94
|
|
package/README.md
CHANGED
|
@@ -10,10 +10,10 @@ npm package: <https://www.npmjs.com/package/@junghanacs/entwurf>
|
|
|
10
10
|
|
|
11
11
|
Legacy package: [`@junghanacs/pi-shell-acp`](https://www.npmjs.com/package/@junghanacs/pi-shell-acp). `entwurf` is its 0.12+ successor line: the same work renamed around the garden-citizen dispatch substrate rather than the pi adapter.
|
|
12
12
|
|
|
13
|
-
> **Repository shape.** This repo is **entwurf-core (v2 dispatch) + native-harness bridges + a pi adapter + an ACP plugin**. Pi is one supported harness adapter — important because it supplies control sockets and hosts the ACP plugin today — but it is not the project subject. Claude Code
|
|
13
|
+
> **Repository shape.** This repo is **entwurf-core (v2 dispatch) + native-harness bridges + a pi adapter + an ACP plugin**. Pi is one supported harness adapter — important because it supplies control sockets and hosts the ACP plugin today — but it is not the project subject. Claude Code and GitHub Copilot CLI are shipped as mailbox-backed self-fetch meta-sessions; Antigravity (`agy`) is shipped as a native-push citizen with automatic `PreInvocation` birth, ambient garden-id status, and a managed MCP/permission install surface. Codex has a launch-mode-specific verified delivery probe documented in [DELIVERY.md](./DELIVERY.md), but no managed native-citizen install lane yet. The ACP plugin ships two backends through one adapter rail: Claude (the reference) and Snowflake Cortex Code (landed in 0.13.0 under the measured contract in [docs/acp-backend-rail.md](./docs/acp-backend-rail.md#cortex-code-audit-d1d10)).
|
|
14
14
|
|
|
15
15
|
```text
|
|
16
|
-
Claude Code / Codex / agy / pi
|
|
16
|
+
Claude Code / Copilot / Codex / agy / pi
|
|
17
17
|
→ garden id
|
|
18
18
|
→ entwurf_v2
|
|
19
19
|
→ control-socket | meta-mailbox | native-push
|
|
@@ -44,6 +44,12 @@ native Claude Code
|
|
|
44
44
|
→ entwurf_self | entwurf_v2 | entwurf_inbox_read
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
+
Copilot uses another self-fetch rail. Its birth hook mints the V3 record on the first prompt,
|
|
48
|
+
the MCP hand supplies `entwurf_inbox_read`, and a first-party extension arms the receiver marker
|
|
49
|
+
and rings a doorbell for queued bodies. Supported launch is `entwurf copilot`; visible fresh uses
|
|
50
|
+
that same managed invocation so extension scan, receiver preconditions, model, and permission
|
|
51
|
+
policy are present before the sibling calls back with its garden id.
|
|
52
|
+
|
|
47
53
|
Antigravity uses a separate shipped rail. Its `PreInvocation` hook births or re-attaches the conversation by native `conversationId`, writes a record-backed sender marker, and leaves delivery to the live native LS gRPC route. There is no mailbox or receiver marker on this rail: `entwurf_v2` probes the conversation and direct-injects with native-push.
|
|
48
54
|
|
|
49
55
|
```text
|
|
@@ -53,7 +59,10 @@ native Antigravity / agy
|
|
|
53
59
|
↔ entwurf_v2 native-push
|
|
54
60
|
```
|
|
55
61
|
|
|
56
|
-
Claude's `install-meta-bridge
|
|
62
|
+
Claude's `install-meta-bridge`, Copilot's four `install-copilot-*` surfaces, and agy's
|
|
63
|
+
`install-agy-{bridge,statusline,hooks}` are distinct because their lifecycle and delivery
|
|
64
|
+
transports are genuinely different. Codex remains verified probe evidence, not a shipped managed
|
|
65
|
+
native-citizen lane; see [DELIVERY.md](./DELIVERY.md).
|
|
57
66
|
|
|
58
67
|
> **Direction.** Inverse of [`pi-acp`](https://github.com/svkozak/pi-acp). `pi-acp` lets external ACP clients talk *to* pi; `entwurf` lets garden citizens talk across harness boundaries — with pi as one adapter, not the center.
|
|
59
68
|
|
|
@@ -62,9 +71,9 @@ Claude's `install-meta-bridge` and agy's `install-agy-{bridge,statusline,hooks}`
|
|
|
62
71
|
A few words that look unusual for a coding tool.
|
|
63
72
|
|
|
64
73
|
- **Entwurf** (기투, projection-of-self) — sibling sessions with their own runtime boundary. Not "delegate," not "worker," not "sub-agent." Opening a visible sibling (`entwurf_fresh_call`), live peer messaging (`entwurf_v2`) and reopening a dormant one (`entwurf_resume_call`) are first-class; the hidden background resume that preceded the last of those was withdrawn under the visible-first rule.
|
|
65
|
-
- **Garden / garden id** — the garden is the shared address space where independent harness sessions become citizens without losing their own runtime or transcript. A garden id is the stable address of one such citizen (for pi, a garden-native session id like `YYYYMMDDTHHMMSS-<6hex>`; for native harnesses, a meta-session id minted from an authoritative lifecycle hook — Claude `SessionStart`, agy `PreInvocation`). It is not a worker name and not proof that pi owns the session. The same-looking id may name a live control socket, a dormant pi record, a mailbox-backed native session, or a native-push conversation, so callers discover facts with `entwurf_peers` and deliver with `entwurf_v2` instead of choosing a transport by hand.
|
|
74
|
+
- **Garden / garden id** — the garden is the shared address space where independent harness sessions become citizens without losing their own runtime or transcript. A garden id is the stable address of one such citizen (for pi, a garden-native session id like `YYYYMMDDTHHMMSS-<6hex>`; for native harnesses, a meta-session id minted from an authoritative lifecycle hook — Claude `SessionStart`, Copilot's first-prompt birth hook, agy `PreInvocation`). It is not a worker name and not proof that pi owns the session. The same-looking id may name a live control socket, a dormant pi record, a mailbox-backed native session, or a native-push conversation, so callers discover facts with `entwurf_peers` and deliver with `entwurf_v2` instead of choosing a transport by hand.
|
|
66
75
|
- **Engraving** — optional short operator text delivered through each backend's native identity carrier. Not a giant hidden prompt, not a tool catalog.
|
|
67
|
-
- **MCP** — in this repo, MCP is just the transport by which ACP-backed sessions receive pi capabilities that native pi exposes directly as extensions. It is not a general MCP platform. Explicit `entwurfProvider.mcpServers` only; no ambient `~/.mcp.json` scanning, no automatic retrieval. The same `entwurf-bridge` entry can also be wired into another host's MCP catalog (Claude Code, Codex, Antigravity, …) when the operator chooses. `entwurf_self` returns an authoritative pi-session or trusted meta-session identity envelope; `entwurf_v2` requires an authoritative sender by default (#50 C4) — a plain external MCP host with no identity lane is refused unless the operator explicitly wires the documented anonymous hatch, and even then it is never replyable.
|
|
76
|
+
- **MCP** — in this repo, MCP is just the transport by which ACP-backed sessions receive pi capabilities that native pi exposes directly as extensions. It is not a general MCP platform. Explicit `entwurfProvider.mcpServers` only; no ambient `~/.mcp.json` scanning, no automatic retrieval. The same `entwurf-bridge` entry can also be wired into another host's MCP catalog (Claude Code, Copilot, Codex, Antigravity, …) when the operator chooses. `entwurf_self` returns an authoritative pi-session or trusted meta-session identity envelope; `entwurf_v2` requires an authoritative sender by default (#50 C4) — a plain external MCP host with no identity lane is refused unless the operator explicitly wires the documented anonymous hatch, and even then it is never replyable.
|
|
68
77
|
- **Session persistence** — re-attaches pi to the same remote ACP session. Does not hydrate backend transcripts into pi history.
|
|
69
78
|
|
|
70
79
|
## Install
|
|
@@ -85,9 +94,13 @@ The package exposes six bins:
|
|
|
85
94
|
|
|
86
95
|
The bridge/renderers/hook use stable bin names so package upgrades do not bake versioned package-store paths into native-harness settings.
|
|
87
96
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
97
|
+
Installing Entwurf installs **Entwurf only**: its package bytes, six bins, bridge, and
|
|
98
|
+
integration artifacts. It does not install `pi`, Claude Code, Copilot CLI, Codex, agy, Cortex,
|
|
99
|
+
or any other harness runtime. Those are operator choices and may all be absent. The bridge also
|
|
100
|
+
does not provide credentials, tokens, subscription access, or an auth bypass; whatever an
|
|
101
|
+
operator-installed harness already trusts is what Entwurf can use. `setup` is composition, not
|
|
102
|
+
recruitment: it may wire a harness that is present, but never downloads one to make a matrix cell
|
|
103
|
+
look complete.
|
|
91
104
|
|
|
92
105
|
### From npm — user/global install
|
|
93
106
|
|
|
@@ -138,12 +151,43 @@ or at the package launcher directly:
|
|
|
138
151
|
```bash
|
|
139
152
|
git clone https://github.com/junghan0611/entwurf ~/repos/gh/entwurf
|
|
140
153
|
cd ~/repos/gh/entwurf
|
|
141
|
-
pnpm install
|
|
142
154
|
|
|
143
|
-
./run.sh
|
|
155
|
+
./run.sh setup /path/to/your-project
|
|
144
156
|
./run.sh check-bridge
|
|
145
157
|
```
|
|
146
158
|
|
|
159
|
+
The full source setup requires Node 24, pnpm, and Python 3 on PATH. Harnesses are
|
|
160
|
+
optional-by-presence: `setup` runs the frozen dependency install, then composes what the operator
|
|
161
|
+
already installed — a compatible `pi` (`>=0.84.3 <0.85`), Claude Code, agy, and the Copilot CLI
|
|
162
|
+
each get their wiring completed when detected, an absent harness is an explicit zero-state SKIP,
|
|
163
|
+
and a detected harness that cannot be completed (including a below-floor `pi`) is a named FAIL
|
|
164
|
+
that makes setup exit nonzero. `setup` never installs a harness binary or touches a credential
|
|
165
|
+
store. It also exposes stable commands under `~/.local/bin`, including `entwurf` → this
|
|
166
|
+
checkout's `run.sh`, so managed Copilot fresh does not depend on an unrelated global npm/pnpm
|
|
167
|
+
installation. A detected `copilot` composes all four native units (birth → MCP → receiver →
|
|
168
|
+
visible footer) independently; the explicit `install-copilot-*` surfaces below remain the
|
|
169
|
+
per-unit repair and inverse path. Package consumers
|
|
170
|
+
run the same `entwurf setup <project>` through their npm-provided bin: installed mode is decided
|
|
171
|
+
by name first, skips the source-only pnpm bootstrap entirely, and reports the stable commands as
|
|
172
|
+
already provided by npm bin linking; `entwurf install` remains the narrower pi-wiring repair
|
|
173
|
+
leaf.
|
|
174
|
+
|
|
175
|
+
The pi user-scope registration is ONE shared entry with a recorded owner (#86 C2): installing
|
|
176
|
+
from a second checkout or npm root does not silently steal it — normal `install`/`setup` refuse
|
|
177
|
+
(zero settings writes, live or missing owner alike), `entwurf takeover-user-scope` is the
|
|
178
|
+
operator-explicit move (old→new reported), `entwurf doctor-pi-package` names the ownership
|
|
179
|
+
verdict (including `missing-owner` for a moved/deleted root), and `entwurf remove-user-scope`
|
|
180
|
+
is same-owner-only with a reported orphan cleanup when entry, package state and provider
|
|
181
|
+
installerRoot all name the same missing root. User-scope operations are atomic across the
|
|
182
|
+
package and provider halves (read-only preflights first — a refusal on one side writes nothing
|
|
183
|
+
on the other); a takeover over an operator's provider override reports a split verdict (package
|
|
184
|
+
moved, override preserved unowned) and a legacy unattributed provider state must be adopted by
|
|
185
|
+
a same-root `setup`/`install` before it can be removed. Both halves' install-states also record
|
|
186
|
+
exactly WHICH settings file they manage (`managedSettingsPath`): an operation targeting a
|
|
187
|
+
different, symlinked or unparseable file is a zero-write refusal before either half goes green,
|
|
188
|
+
and the owned/orphan inverse removes only the recorded owner's exact `packages[]` entry —
|
|
189
|
+
0 or 2+ exact entries refuse, so an npm spec or another `.../entwurf` path is never collateral.
|
|
190
|
+
|
|
147
191
|
A development clone runs the bridge source through Node's strip-types path;
|
|
148
192
|
an npm-installed package runs the prebuilt JS under `mcp/entwurf-bridge/dist/`
|
|
149
193
|
because Node refuses to strip `.ts` files under `node_modules`. The dev launcher's
|
|
@@ -170,8 +214,10 @@ For daily operator sessions, launch pi with `--entwurf-control` — no id
|
|
|
170
214
|
injection; the meta-record mints the garden address (see [Garden launcher](#garden-launcher)). Older pi
|
|
171
215
|
versions may silently miss the provider/extension surface, so treat the pi floor
|
|
172
216
|
as release-critical for the ACP/plugin lane. A host that only uses
|
|
173
|
-
`entwurf-bridge` from Claude Code / Codex / Antigravity does not need pi at all for
|
|
174
|
-
delivery: no `entwurf_v2` rail launches a pi process.
|
|
217
|
+
`entwurf-bridge` from Claude Code / Copilot / Codex / Antigravity does not need pi at all for
|
|
218
|
+
delivery: no `entwurf_v2` rail launches a pi process. That external-only shape works with the same
|
|
219
|
+
`setup` command: pi is optional-by-presence there, so a pi-less host simply gets an explicit pi
|
|
220
|
+
SKIP while the detected harnesses are composed.
|
|
175
221
|
|
|
176
222
|
### Native harness install and doctors
|
|
177
223
|
|
|
@@ -193,12 +239,15 @@ entwurf doctor-agy-statusline
|
|
|
193
239
|
entwurf doctor-agy-hooks
|
|
194
240
|
|
|
195
241
|
# GitHub Copilot CLI — four independent surfaces, four independent failure modes
|
|
196
|
-
|
|
242
|
+
# (`setup` composes all four when `copilot` is on PATH; these remain the per-unit repair/inverse surfaces)
|
|
243
|
+
entwurf install-copilot-bridge # birth: garden id + who-sent, on the first prompt (owns an install-state; inverse: uninstall-copilot-bridge)
|
|
197
244
|
entwurf install-copilot-mcp # the entwurf tool hand (entwurf_inbox_read lives here)
|
|
198
245
|
entwurf install-copilot-receive # the receiver extension: doorbell + receiver marker
|
|
199
246
|
entwurf install-copilot-statusline # optional for a manual citizen; required for supported fresh
|
|
200
247
|
entwurf doctor-copilot-bridge
|
|
248
|
+
entwurf doctor-copilot-mcp
|
|
201
249
|
entwurf doctor-copilot-receive
|
|
250
|
+
entwurf doctor-copilot-statusline
|
|
202
251
|
```
|
|
203
252
|
|
|
204
253
|
#### Launching Copilot as a garden citizen — `entwurf copilot`
|
|
@@ -245,8 +294,8 @@ the default permission prompts — which an idle, unattended session is not ther
|
|
|
245
294
|
|
|
246
295
|
Claude Code uses the supported floor `>=2.1.217`; older versions silently discard the
|
|
247
296
|
exec-hook `args`, so install and doctor fail loud rather than falling back. After any
|
|
248
|
-
upgrade, rerun
|
|
249
|
-
processes. A claimed Claude host is certified only when a **new** session using the
|
|
297
|
+
upgrade, rerun every owned installer for the native harness you use (all four for Copilot) and
|
|
298
|
+
restart its existing processes. A claimed Claude host is certified only when a **new** session using the
|
|
250
299
|
installed artifact makes `doctor-meta-bridge` exit 0 with the live owner join.
|
|
251
300
|
|
|
252
301
|
Linux is the only currently certified Claude meta-bridge axis. New macOS wiring is
|
|
@@ -360,7 +409,7 @@ Reference shape lives in [`pi/settings.reference.json`](./pi/settings.reference.
|
|
|
360
409
|
### External MCP registration
|
|
361
410
|
|
|
362
411
|
`entwurf-bridge` can also be registered in a separate MCP-aware harness (Claude Code,
|
|
363
|
-
Codex CLI, Antigravity). Two shapes exist and they are not interchangeable:
|
|
412
|
+
Copilot CLI, Codex CLI, Antigravity). Two shapes exist and they are not interchangeable:
|
|
364
413
|
|
|
365
414
|
- **plain external MCP host** — no garden meta-record or sender marker. It can read the
|
|
366
415
|
surfaces, but `entwurf_v2` is **refused by default**: there is no authoritative sender.
|
|
@@ -478,7 +527,7 @@ A two-pane recording covers the pre-0.12 v1 surface end-to-end — sibling resum
|
|
|
478
527
|
|
|
479
528
|
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.)
|
|
480
529
|
|
|
481
|
-
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-
|
|
530
|
+
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-or-Copilot-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`, `claude-code`, or `copilot`) 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; 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. 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.
|
|
482
531
|
|
|
483
532
|
### `entwurf_v2` — canonical dispatch verb
|
|
484
533
|
|
|
@@ -495,7 +544,7 @@ In ACP-backed and external native-harness sessions, `entwurf-bridge` exposes sev
|
|
|
495
544
|
| dead / indeterminate native-push conversation | fire-and-forget | **reject** (`native-push-target-dead` / `native-push-probe-indeterminate`) |
|
|
496
545
|
| record-less control socket (no meta-record) | any | **reject** (`record-less-socket` — pre-probe; diagnostic state, #50 C4) |
|
|
497
546
|
|
|
498
|
-
**`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.
|
|
547
|
+
**`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 Copilot, 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.
|
|
499
548
|
|
|
500
549
|
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, or Copilot 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. Copilot opens through `entwurf copilot`, never the bare vendor. 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.
|
|
501
550
|
|
package/VERIFY.md
CHANGED
|
@@ -134,11 +134,14 @@ The goal is not merely "invoke Claude Code." We want:
|
|
|
134
134
|
|
|
135
135
|
**One install command to remember: `./run.sh setup <project>`.** It is idempotent — re-run the exact same command whenever anything looks wrong. There is no second install surface to juggle: from a clone `setup` runs the whole floor in order.
|
|
136
136
|
|
|
137
|
-
1. `pnpm install` —
|
|
138
|
-
2.
|
|
137
|
+
1. `pnpm install` — installs the pinned development dependencies and builds the bridge (source-checkout bootstrap only; an installed package never runs npm/pnpm inside `node_modules`)
|
|
138
|
+
2. pi wiring → `<project>/.pi/settings.json` + user-scope registration — only when a `pi` inside the supported range (`>=0.84.3 <0.85`) is on PATH; absent pi is an explicit zero-state SKIP, a below-floor pi is a detected FAIL. The user-scope entry is owner-recorded (#86 C2): another root's live-or-missing ownership makes this step a zero-write refusal (setup: pi FAIL) that names `takeover-user-scope`; the install-states bind the exact managed settings path (a drifted/symlinked/corrupt target is a zero-write refusal) and the inverse removes only the recorded owner's exact entry; `doctor-pi-package` reports the verdict
|
|
139
139
|
3. Claude meta-bridge global plugin — only when `claude` is on PATH; otherwise skipped cleanly
|
|
140
|
-
4.
|
|
141
|
-
5.
|
|
140
|
+
4. source stable-bin exposure — including certified `entwurf` → this checkout's `run.sh`, the managed runtime Copilot fresh resolves; helper units are attempted independently and a foreign helper is a named FAIL
|
|
141
|
+
5. agy bridge + exact permission + statusline + `PreInvocation` hook — only when `agy` is on PATH; each adapter is idempotent and independently doctorable
|
|
142
|
+
6. Copilot four-unit composition (birth → MCP → receiver → visible footer) — only when `copilot` is on PATH (#86 C3b); the units run independently, each keeps its package-owned install-state and inverse, and a failed unit is a named component FAIL. The explicit `install-copilot-*`/`uninstall-copilot-*` surfaces remain the per-unit repair and inverse path
|
|
143
|
+
7. `entwurf-bridge` install smoke (`validate_entwurf_bridge`)
|
|
144
|
+
8. computed summary — per-component PASS/SKIP/FAIL; any detected-integration FAIL makes the whole command exit nonzero while valid components stay installed
|
|
142
145
|
|
|
143
146
|
```bash
|
|
144
147
|
git clone https://github.com/junghan0611/entwurf /path/to/entwurf && cd $_
|
|
@@ -146,7 +149,7 @@ git clone https://github.com/junghan0611/entwurf /path/to/entwurf && cd $_
|
|
|
146
149
|
# re-run the SAME command any time to repair a broken install
|
|
147
150
|
```
|
|
148
151
|
|
|
149
|
-
Expected tail: `DONE: entwurf setup (
|
|
152
|
+
Expected tail on a fully green host: `DONE: entwurf setup — result: green (computed from the component outcomes above).` The summary above it lists every component as PASS/SKIP/FAIL; a detected harness that could not be completed is named FAIL and the command exits nonzero (`result: NON-GREEN (FAIL: …)`) while every valid component stays installed — re-running the same `setup` is the repair action. On a host with `claude`, verify `./run.sh doctor-meta-bridge`. On a host with `agy`, verify all three: `doctor-agy-bridge`, `doctor-agy-statusline`, and `doctor-agy-hooks`. After adding a backend to `META_BACKENDS`, re-run the sibling install then the doctor — a green checkout with a stale deployed plugin is a silent write-stop on that rail. Each harness doctor remains the fail-loud per-leaf acceptance surface.
|
|
150
153
|
|
|
151
154
|
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.
|
|
152
155
|
|
|
@@ -173,7 +176,7 @@ addressable sends require `--entwurf-control` (measured 2026-07-24: the same
|
|
|
173
176
|
one-shot with that flag returns its own gid and delivers `entwurf_v2` to a peer
|
|
174
177
|
mailbox with `origin=pi-session`, `replyable=true`).
|
|
175
178
|
|
|
176
|
-
`setup` runs `pnpm install` + project/user
|
|
179
|
+
`setup` requires Node 24 and Python 3 (pnpm only on a source checkout — the dependency bootstrap is source-only, and installed mode needs no pnpm); harnesses including pi are optional-by-presence (absent → explicit zero-state SKIP, detected incomplete/below-floor → named FAIL + nonzero result). On a source checkout it runs the frozen `pnpm install` + presence-gated pi project/user wiring + detected Claude wiring + source stable-bin exposure + detected agy wiring + detected Copilot four-unit composition + the v2 install smoke. A green setup certifies that the source-owned `entwurf` symlink targets this checkout and wins PATH resolution; helper units are attempted independently and a foreign helper is a named bins FAIL (nonzero), with harness-specific doctors keeping the per-leaf verdict. A detected `copilot` composes all four native units (birth → MCP → receiver → visible footer) with independent per-unit verdicts (#86 C3b); setup does **not** replace any native-harness doctor. The full aggregate live floor is still `LIVE=1 ./run.sh release-gate <scratch> --cut` — without `--cut` it is a diagnostic pass, not acceptance — with agy's conversation-id-gated round trip verified separately.
|
|
177
180
|
|
|
178
181
|
### 1.4 Cross-install / cross-backend parity (optional, high-value)
|
|
179
182
|
|
package/docs/acp-backend-rail.md
CHANGED
|
@@ -92,7 +92,7 @@ undifferentiated "supported" column is what let a Claude PASS read as if it also
|
|
|
92
92
|
|
|
93
93
|
| Surface | Declaration | Class | What a green actually says |
|
|
94
94
|
|---|---|---|---|
|
|
95
|
-
| Entwurf package | `0.
|
|
95
|
+
| Entwurf package | `0.15.0` | shipped baseline | the package contract these rows belong to |
|
|
96
96
|
| pi runtime | devDep exact `0.84.3`, peer `>=0.84.3 <0.85` | **exact** oracle + **closed range** | built and certified against 0.84.3; hosts inside the range are accepted, and the ceiling moves only on measurement |
|
|
97
97
|
| ACP wire SDK | `@agentclientprotocol/sdk 1.3.0` | **exact** | the shared wire oracle both adapters speak |
|
|
98
98
|
| Claude ACP adapter | `@agentclientprotocol/claude-agent-acp 0.70.0` | **exact**, bundled | the adapter we ship and certify; resolved before any PATH fallback |
|
package/docs/setup-clean-host.md
CHANGED
|
@@ -9,10 +9,12 @@ only on Linux because its strict live-owner join uses `/proc`.
|
|
|
9
9
|
| Component | Requirement | Needed for |
|
|
10
10
|
|---|---|---|
|
|
11
11
|
| Node | **`>=24.0.0`** | package and bridge runtime |
|
|
12
|
-
| npm | bundled with Node | package installation |
|
|
13
|
-
|
|
|
14
|
-
|
|
|
12
|
+
| npm/pnpm | npm is bundled with Node; pnpm is required for source setup | package or source installation |
|
|
13
|
+
| Python 3 | required by `setup`/`install` (project-path normalization + settings writers); `--help`/`check-bridge` stay Python-free | pi/Claude/agy/Copilot wiring writers |
|
|
14
|
+
| entwurf | global/project-local `@junghanacs/entwurf`, or a source checkout | operator command and garden capability |
|
|
15
|
+
| pi | optional-by-presence, `>=0.84.3 <0.85` — absent is an explicit setup SKIP, below-floor is a named FAIL | ACP provider, control sockets |
|
|
15
16
|
| Claude Code | optional, **`>=2.1.217`** — the exec-form hook floor | Claude ACP auth/runtime and mailbox-backed native citizen |
|
|
17
|
+
| GitHub Copilot CLI | optional-by-presence, operator-installed and authenticated — absent is an explicit setup SKIP; detected composes all four units (birth/MCP/receiver/footer) | self-fetch citizen and visible fresh |
|
|
16
18
|
| Antigravity `agy` | optional, operator-installed and authenticated | native-push citizen |
|
|
17
19
|
| Cortex Code | optional, operator-installed and authenticated | Cortex ACP backend |
|
|
18
20
|
|
|
@@ -51,6 +53,56 @@ npx entwurf check-bridge
|
|
|
51
53
|
`check-bridge` is auth-free. It proves the installed prebuilt MCP server boots and
|
|
52
54
|
lists the seven garden tools; it does not prove a backend model turn or native hook.
|
|
53
55
|
|
|
56
|
+
Neither npm form installs a harness runtime. `pi`, Claude Code, Copilot CLI, agy, Cortex and their
|
|
57
|
+
authentication remain operator-owned optional prerequisites for the integrations that use them;
|
|
58
|
+
all may be absent on an Entwurf-only host. A source checkout's pinned Pi development packages are
|
|
59
|
+
for building and testing this repo, not a transitive product installation promise.
|
|
60
|
+
|
|
61
|
+
Maintainers using a source checkout do not install a second global entwurf package. Full source
|
|
62
|
+
setup currently requires Node 24, pnpm, and Python 3 on PATH; every harness — including pi — is
|
|
63
|
+
optional-by-presence (absent → explicit SKIP, detected but below the supported floor → named FAIL
|
|
64
|
+
with a nonzero setup result):
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
git clone https://github.com/junghan0611/entwurf ~/repos/gh/entwurf
|
|
68
|
+
cd ~/repos/gh/entwurf
|
|
69
|
+
./run.sh setup /path/to/consumer-project
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
This owns `~/.local/bin/entwurf` as a symlink to that checkout's `run.sh` and fails if the
|
|
73
|
+
link is foreign, outside PATH, or shadowed by another command. It detects and wires
|
|
74
|
+
pi/Claude/agy/Copilot by presence and prints a computed per-component PASS/SKIP/FAIL summary — a
|
|
75
|
+
detected harness that cannot be completed makes setup exit nonzero. A detected `copilot`
|
|
76
|
+
composes all four native units (birth → MCP → receiver → visible footer) with independent
|
|
77
|
+
per-unit verdicts (#86 C3b); §4 keeps the explicit per-unit install/doctor/inverse surfaces for
|
|
78
|
+
repair.
|
|
79
|
+
|
|
80
|
+
### 1.1 User-scope ownership (one shared registration, one recorded owner)
|
|
81
|
+
|
|
82
|
+
The GLOBAL pi user-scope registration (`~/.pi/agent/settings.json` `packages[]` plus the
|
|
83
|
+
`entwurfProvider.mcpServers.entwurf-bridge` key) is ONE shared entry across every install root, and
|
|
84
|
+
it carries a recorded owner: `packageRoot` in `$XDG_DATA_HOME/entwurf/pi-package/install-state.json`
|
|
85
|
+
and `installerRoot` in the provider install-state. Normal `install`/`setup` from a different root —
|
|
86
|
+
whether the recorded owner is live or missing — refuses with zero settings bytes written; the only
|
|
87
|
+
writer that moves the shared entry is the operator-explicit `entwurf takeover-user-scope`
|
|
88
|
+
(old→new reported). Every user-scope operation is ATOMIC across the two halves: both ownership
|
|
89
|
+
preflights run read-only first, so a refusal on either side leaves the other byte-identical. A
|
|
90
|
+
takeover over an operator's own provider override is a SPLIT verdict — the package owner moves,
|
|
91
|
+
the override is preserved and stays unowned (its stale ownership state is cleared), never a false
|
|
92
|
+
"both owned". A LEGACY provider state (no `installerRoot`) accepts no inverse: run `setup`/`install`
|
|
93
|
+
from the owning root first (named adoption), then remove. Both install-states also bind the exact
|
|
94
|
+
settings file they manage (`managedSettingsPath`): pointing an operation at a different, symlinked
|
|
95
|
+
or unparseable file refuses with zero writes before either half proceeds, and the owned/orphan
|
|
96
|
+
inverse removes only the recorded owner's exact `packages[]` entry (0 or 2+ exact entries refuse).
|
|
97
|
+
`entwurf doctor-pi-package` names the package-side verdict including the
|
|
98
|
+
packageRoot↔installerRoot coupling mismatch and a package/provider managed-path mismatch.
|
|
99
|
+
|
|
100
|
+
| Root shape | Package root written | Stable commands from | Project write | User write | Takeover trigger | Inverse | Stale/moved verdict |
|
|
101
|
+
|---|---|---|---|---|---|---|---|
|
|
102
|
+
| source checkout | the checkout dir | `dev-bin` symlinks (`setup`) | `<project>/.pi/settings.json` | shared entry + owner state | `takeover-user-scope` from the new checkout | `remove` (project) / `remove-user-scope` (global, same-owner-only) | `doctor-pi-package` → `missing-owner`; normal install still refuses |
|
|
103
|
+
| global npm (`npm i -g`) | the global `node_modules/@junghanacs/entwurf` | npm bin linking | same | same shared entry | same explicit action | same; a LIVE foreign owner always refuses | same |
|
|
104
|
+
| project-local npm | that project's `node_modules/@junghanacs/entwurf` | `node_modules/.bin` | same | same shared entry | same explicit action | same | same; a deleted root becomes the aligned `remove-user-scope` orphan cleanup (entry + package state + provider installerRoot must all name that missing root) |
|
|
105
|
+
|
|
54
106
|
## 2. Optional pi adapter / ACP plugin
|
|
55
107
|
|
|
56
108
|
Install the exact release floor, then wire the project:
|
|
@@ -109,7 +161,31 @@ New macOS wiring is refused because the live join is not instrumented there. Dar
|
|
|
109
161
|
uninstall remains available for cleaning an older managed install; this is an evidence
|
|
110
162
|
boundary, not a permanent impossibility claim.
|
|
111
163
|
|
|
112
|
-
## 4. Optional
|
|
164
|
+
## 4. Optional GitHub Copilot CLI native citizen
|
|
165
|
+
|
|
166
|
+
Copilot has four independently owned surfaces. `setup` composes all four when `copilot` is on
|
|
167
|
+
PATH (#86 C3b); the commands below are the per-unit repair, doctor, and inverse surfaces. All
|
|
168
|
+
four must be green for supported visible fresh; a manual citizen may omit the footer, but fresh
|
|
169
|
+
refuses before opening a window when any required surface is absent.
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
entwurf install-copilot-bridge
|
|
173
|
+
entwurf install-copilot-mcp
|
|
174
|
+
entwurf install-copilot-receive
|
|
175
|
+
entwurf install-copilot-statusline
|
|
176
|
+
|
|
177
|
+
entwurf doctor-copilot-bridge
|
|
178
|
+
entwurf doctor-copilot-mcp
|
|
179
|
+
entwurf doctor-copilot-receive
|
|
180
|
+
entwurf doctor-copilot-statusline
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Launch the supported invocation with `entwurf copilot`, not bare `copilot`. It enables extension
|
|
184
|
+
scanning for that process, checks the receiver, removes inherited pi identity carriers, and owns
|
|
185
|
+
the model/permission defaults. Birth occurs on the first prompt. `entwurf_fresh_call` uses this
|
|
186
|
+
same managed invocation and requires the birth, MCP, receiver, and visible-identity preflight.
|
|
187
|
+
|
|
188
|
+
## 5. Optional Antigravity native citizen
|
|
113
189
|
|
|
114
190
|
Install the three independently owned surfaces:
|
|
115
191
|
|
|
@@ -134,7 +210,7 @@ Real native-push acceptance needs an already-running conversation:
|
|
|
134
210
|
LIVE=1 AGY_CONVERSATION_ID=<id> entwurf smoke-agy-native-push-live
|
|
135
211
|
```
|
|
136
212
|
|
|
137
|
-
##
|
|
213
|
+
## 6. Optional ACP backend turns
|
|
138
214
|
|
|
139
215
|
Claude uses the operator's existing local Claude authentication:
|
|
140
216
|
|
|
@@ -153,25 +229,34 @@ LIVE=1 ENTWURF_ACP_CORTEX_CONNECTION=<conn> \
|
|
|
153
229
|
The aggregate release gate is Claude-backed and does not run Cortex automatically.
|
|
154
230
|
Its silence is not a Cortex PASS.
|
|
155
231
|
|
|
156
|
-
##
|
|
232
|
+
## 7. Upgrade and repair
|
|
157
233
|
|
|
158
234
|
After upgrading the package, rerun the managed installers for every native harness
|
|
159
235
|
in use and restart their existing processes. Native plugin caches are not live-reload
|
|
160
236
|
safe across launch-contract changes.
|
|
161
237
|
|
|
162
238
|
If install or doctor reports an unreadable/old active citizen generation, do not edit
|
|
163
|
-
records by hand
|
|
239
|
+
records by hand. Close pi, Claude, Copilot, and agy sessions first, run
|
|
240
|
+
`entwurf meta-bridge-fresh-cut`, and read its exit status before any install. Then choose the
|
|
241
|
+
installation mode you actually own:
|
|
164
242
|
|
|
165
243
|
```bash
|
|
166
|
-
#
|
|
167
|
-
entwurf
|
|
168
|
-
entwurf
|
|
244
|
+
# npm package consumer
|
|
245
|
+
entwurf install ~/entwurf-smoke
|
|
246
|
+
entwurf install-meta-bridge
|
|
247
|
+
# `entwurf setup` re-composes the four Copilot units when `copilot` is on PATH
|
|
248
|
+
|
|
249
|
+
# source maintainer — from the checkout
|
|
250
|
+
./run.sh setup ~/entwurf-smoke
|
|
169
251
|
```
|
|
170
252
|
|
|
171
|
-
|
|
172
|
-
|
|
253
|
+
The package-installed `entwurf setup` is the same consumer command in installed mode: it names
|
|
254
|
+
that mode first, never runs npm/pnpm inside `node_modules` (the frozen pnpm bootstrap is
|
|
255
|
+
source-checkout-only), and composes the detected harnesses with the same per-component
|
|
256
|
+
PASS/SKIP/FAIL summary. The complete quiescence, archive, and exit-code contract is
|
|
257
|
+
[fresh-cut-policy.md](./fresh-cut-policy.md).
|
|
173
258
|
|
|
174
|
-
##
|
|
259
|
+
## 8. Release acceptance versus host acceptance
|
|
175
260
|
|
|
176
261
|
- `entwurf check-bridge`: installed MCP bytes boot; no backend auth.
|
|
177
262
|
- `pnpm check` / `pnpm run check:full`: tiered source deterministic floors (everyday
|
|
@@ -190,12 +275,27 @@ Run only the surfaces this host owns:
|
|
|
190
275
|
|
|
191
276
|
```bash
|
|
192
277
|
entwurf uninstall-meta-bridge
|
|
278
|
+
entwurf uninstall-copilot-statusline
|
|
279
|
+
entwurf uninstall-copilot-receive
|
|
280
|
+
entwurf uninstall-copilot-mcp
|
|
281
|
+
entwurf uninstall-copilot-bridge
|
|
193
282
|
entwurf uninstall-agy-hooks
|
|
194
283
|
entwurf uninstall-agy-statusline
|
|
195
284
|
entwurf uninstall-agy-bridge
|
|
196
|
-
entwurf
|
|
285
|
+
entwurf remove ~/entwurf-smoke
|
|
286
|
+
# only when no other project uses the shared user-scope pi registration:
|
|
287
|
+
entwurf remove-user-scope
|
|
197
288
|
npm uninstall -g @junghanacs/entwurf
|
|
198
289
|
```
|
|
199
290
|
|
|
200
|
-
|
|
201
|
-
|
|
291
|
+
The package `uninstall-*`/`remove` surfaces preserve unrelated native-harness configuration.
|
|
292
|
+
Copilot birth now has a package-owned inverse: `uninstall-copilot-bridge` removes exactly what
|
|
293
|
+
its install-state (`$XDG_DATA_HOME/entwurf/copilot-bridge/install-state.json`) records — the
|
|
294
|
+
qualified plugin, the local marketplace registration when it is owned and still at the recorded
|
|
295
|
+
path, and the recorded assembly — never with `--force`, never a bare plugin name that could
|
|
296
|
+
match somebody else's unit, and never the stale Claude unit. The complete ownership preflight
|
|
297
|
+
runs read-only before the first vendor write, so a marketplace under our name at another path,
|
|
298
|
+
a registration the state does not own, or a failing vendor list (UNKNOWN, never absence)
|
|
299
|
+
refuses the whole inverse with zero writes; the state is deleted last, so a partial failure
|
|
300
|
+
keeps a rerun-repair authority.
|
|
301
|
+
A legacy no-state installation is adopted by re-running `install-copilot-bridge` first.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@junghanacs/entwurf",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.1",
|
|
4
4
|
"description": "Garden-citizen dispatch substrate and meta-bridge for Claude Code, Codex, Antigravity, and pi harnesses.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -156,7 +156,7 @@
|
|
|
156
156
|
"check:vitest": "./run.sh check-mux-fresh-call && ./run.sh check-acp-sdk-surface",
|
|
157
157
|
"check:contracts": "./run.sh check-shell-quote && ./run.sh check-entwurf-session-identity && ./run.sh check-meta-session && ./run.sh check-meta-v3-record && ./run.sh check-mailbox-receipt-state && ./run.sh check-entwurf-capabilities && ./run.sh check-capability-bundle-reach && ./run.sh check-meta-mailbox-state-write && ./run.sh check-meta-receiver-marker && ./run.sh check-meta-capability-source && ./run.sh check-model-lock && ./run.sh check-dep-versions && ./run.sh check-node-floor-coherence && ./run.sh check-claude-floor-coherence && ./run.sh check-copilot-statusline && ./run.sh check-pi-import-surface && ./run.sh check-env-namespace && ./run.sh check-pi-runtime-version && ./run.sh check-pi-preflight && ./run.sh check-project-trust-handler && ./run.sh check-entwurf-v2-contract && ./run.sh check-entwurf-v2-lock && ./run.sh check-entwurf-v2-decider && ./run.sh check-entwurf-v2-matrix && ./run.sh check-entwurf-v2-release && ./run.sh check-entwurf-v2-send && ./run.sh check-entwurf-v2-send-fallback && ./run.sh check-entwurf-v2-mailbox && ./run.sh check-entwurf-v2-native-push && ./run.sh check-entwurf-v2-runner && ./run.sh check-entwurf-v2-production && ./run.sh check-entwurf-v2-surface && ./run.sh check-entwurf-bridge-pi-free && ./run.sh check-entwurf-resume-args && ./run.sh check-resume-launch-identity && ./run.sh check-mux-placement && ./run.sh check-mux-launch && ./run.sh check-mux-resume-call && ./run.sh check-mux-parent-artifact && ./run.sh check-mux-launcher-fence && ./run.sh check-entwurf-v2-visible-resume && ./run.sh check-entwurf-facts && ./run.sh check-control-socket-path && ./run.sh check-socket-discovery && ./run.sh check-meta-listing && ./run.sh check-entwurf-fact-provider && ./run.sh check-entwurf-peers-surface && ./run.sh check-entwurf-self-address && ./run.sh check-entwurf-deliverability && ./run.sh check-native-push-adapter && ./run.sh check-native-push-register && ./run.sh check-auth-boundary && ./run.sh check-acp-overlay && ./run.sh check-acp-tool-surface && ./run.sh check-acp-event-mapper && ./run.sh check-acp-prompt-builder && ./run.sh check-acp-config && ./run.sh check-acp-session-store && ./run.sh check-acp-carrier-augment",
|
|
158
158
|
"check:hermetic": "./run.sh check-bridge-delivery && ./run.sh smoke-pi-attach && ./run.sh check-fresh-cut-gate && ./run.sh check-hook-launch-topology && ./run.sh check-copilot-birth-hook && ./run.sh check-copilot-receive-arm && ./run.sh check-copilot-launch && ./run.sh check-meta-identity-consumers && ./run.sh check-socket-probe && ./run.sh smoke-meta-honesty && ./run.sh check-meta-doctor-oracle && ./run.sh check-agy-permission-matrix && ./run.sh smoke-agy-statusline-state && ./run.sh smoke-copilot-statusline-state && ./run.sh smoke-copilot-mcp-state && ./run.sh smoke-agy-hooks-state && ./run.sh smoke-pi-provider-state && ./run.sh smoke-user-scope-citizen && ./run.sh smoke-meta-prune && ./run.sh smoke-meta-keyset-guard && ./run.sh check-meta-manifest-schema && ./run.sh check-entwurf-control-rpc && ./run.sh check-entwurf-bridge-boot && ./run.sh check-probe-bridge-command && ./run.sh check-meta-facts && ./run.sh check-agy-sender-identity && ./run.sh check-acp-provider-surface && ./run.sh check-acp-stop-reason && ./run.sh check-acp-prompt-lifecycle && ./run.sh check-acp-stream-hooks && ./run.sh check-acp-backend-preflight && ./run.sh check-acp-session-reuse && ./run.sh check-release-gate-outcomes && ./run.sh check-probe-ordering && ./run.sh check-probe-cli-shim && ./run.sh check-acp-cortex",
|
|
159
|
-
"check:package": "./run.sh check-install-surface && ./run.sh smoke-meta-install-state && ./run.sh smoke-agy-install-state && ./run.sh check-pack-pin-matcher && ./run.sh check-package-source-routing && ./run.sh check-install-preflight && ./run.sh check-pack"
|
|
159
|
+
"check:package": "./run.sh check-install-surface && ./run.sh smoke-meta-install-state && ./run.sh smoke-agy-install-state && ./run.sh smoke-setup-verdict && ./run.sh check-pack-pin-matcher && ./run.sh check-package-source-routing && ./run.sh check-install-preflight && ./run.sh check-pack"
|
|
160
160
|
},
|
|
161
161
|
"pi": {
|
|
162
162
|
"extensions": [
|