@junghanacs/entwurf 0.15.0 → 0.16.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 +1 -0
- package/CHANGELOG.md +299 -0
- package/DELIVERY.md +4 -3
- package/README.md +99 -67
- package/VERIFY.md +13 -7
- package/docs/acp-backend-rail.md +1 -1
- package/docs/external-mcp-host.md +147 -9
- package/docs/setup-clean-host.md +221 -16
- package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +65 -20
- package/mcp/entwurf-bridge/dist/pi-extensions/entwurf-capabilities.json +1 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-self-address.js +17 -6
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-sender-identity.js +1 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-session.js +172 -5
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +152 -17
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/omp-fresh-preflight.js +271 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-omp.js +988 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-receive-omp.js +574 -0
- package/mcp/entwurf-bridge/dist/scripts/omp-receive-facts.js +84 -0
- package/mcp/entwurf-bridge/src/index.ts +65 -19
- package/mcp/entwurf-bridge/tsconfig.build.json +19 -3
- package/mcp/tsconfig.json +10 -0
- package/package.json +14 -4
- package/pi/entwurf-capabilities.json +1 -0
- package/pi/meta-bridge-omp/entwurf-meta-omp/package.json +7 -0
- package/pi/omp-receive/entwurf-receive-omp/package.json +7 -0
- package/pi-extensions/entwurf-control.ts +12 -9
- package/pi-extensions/lib/entwurf-self-address.ts +18 -7
- package/pi-extensions/lib/meta-sender-identity.ts +1 -1
- package/pi-extensions/lib/meta-session.ts +219 -5
- package/pi-extensions/lib/mux-fresh-call.ts +171 -17
- package/pi-extensions/lib/omp-fresh-preflight.ts +275 -0
- package/pi-extensions/meta-bridge-omp.ts +1244 -0
- package/pi-extensions/meta-bridge-receive-omp.ts +666 -0
- package/run.sh +1041 -174
- package/scripts/agy-bridge.sh +4 -2
- package/scripts/check-copilot-birth-hook.ts +700 -23
- package/scripts/check-entwurf-self-address.ts +31 -0
- package/scripts/check-fresh-cut-gate.sh +12 -4
- package/scripts/check-gate-qualification.ts +8 -2
- package/scripts/check-harness-admission-parity.ts +143 -0
- package/scripts/check-meta-doctor-oracle.sh +20 -0
- package/scripts/check-omp-birth-hook.ts +1049 -0
- package/scripts/check-omp-fresh-preflight.ts +181 -0
- package/scripts/check-omp-receive-arm.ts +516 -0
- 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/inventory-verification-surface.ts +1 -1
- package/scripts/meta-bridge-hook-log.sh +9 -1
- package/scripts/mutants/copilot-birth.json +96 -5
- package/scripts/mutants/mux-fresh-call.json +22 -22
- package/scripts/mutants/omp-birth.json +173 -0
- package/scripts/mutants/omp-fresh.json +300 -0
- package/scripts/mutants/omp-receive.json +135 -0
- package/scripts/mutants/pi-package-ownership.json +92 -0
- package/scripts/mutants/self-address.json +34 -0
- package/scripts/mutants/setup-verdict.json +148 -0
- package/scripts/mutants/source-install.json +32 -0
- package/scripts/omp-bridge-doctor.sh +315 -0
- package/scripts/omp-bridge-install.sh +221 -0
- package/scripts/omp-bridge-oracle.sh +154 -0
- package/scripts/omp-bridge-uninstall.sh +57 -0
- package/scripts/omp-mcp-bridge.sh +320 -0
- package/scripts/omp-mcp-config.py +392 -0
- package/scripts/omp-receive-doctor.sh +246 -0
- package/scripts/omp-receive-facts.ts +106 -0
- package/scripts/omp-receive-install.sh +228 -0
- package/scripts/omp-receive-uninstall.sh +60 -0
- package/scripts/omp-tool-surface.py +349 -0
- package/scripts/pi_settings_io.py +22 -0
- package/scripts/raw-omp-measure/README.md +420 -0
- package/scripts/raw-omp-measure/probe-extension.ts +76 -0
- package/scripts/raw-omp-measure/probe-receive-surface.ts +250 -0
- package/scripts/raw-omp-measure/source-audit.md +414 -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-omp-bridge-state.sh +221 -0
- package/scripts/smoke-omp-fresh-live.ts +497 -0
- package/scripts/smoke-omp-mcp-state.sh +327 -0
- package/scripts/smoke-omp-receive-live.ts +340 -0
- package/scripts/smoke-omp-receive-state.sh +196 -0
- package/scripts/smoke-setup-verdict.sh +291 -0
- package/scripts/smoke-user-scope-citizen.sh +388 -1
- package/scripts/tsconfig.json +2 -0
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. OMP (`omp`) is a self-fetch citizen on the same rail as Claude and Copilot, opened by `entwurf_fresh_call` and accepted under the step 9 visible-fresh contract on 2026-08-30 — its first turn is a two-stage in-process bootstrap rather than an argv prompt, because the vendor connects its MCP tools in the background after the session starts. 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 / omp / 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,11 @@ 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, agy's
|
|
63
|
+
`install-agy-{bridge,statusline,hooks}` and OMP's three `install-omp-{bridge,mcp,receive}` units
|
|
64
|
+
(each with its own `doctor-omp-*`) are distinct because their lifecycle and delivery transports are
|
|
65
|
+
genuinely different. Codex remains verified probe evidence, not a shipped managed native-citizen
|
|
66
|
+
lane; see [DELIVERY.md](./DELIVERY.md).
|
|
57
67
|
|
|
58
68
|
> **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
69
|
|
|
@@ -62,17 +72,20 @@ Claude's `install-meta-bridge` and agy's `install-agy-{bridge,statusline,hooks}`
|
|
|
62
72
|
A few words that look unusual for a coding tool.
|
|
63
73
|
|
|
64
74
|
- **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.
|
|
75
|
+
- **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`, and for OMP an in-process extension bound to both session edges that mints only the visible `mode === "tui"` host). 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
76
|
- **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.
|
|
77
|
+
- **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, OMP, …) 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
78
|
- **Session persistence** — re-attaches pi to the same remote ACP session. Does not hydrate backend transcripts into pi history.
|
|
69
79
|
|
|
70
80
|
## Install
|
|
71
81
|
|
|
72
|
-
`entwurf` is a neutral npm package first.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
82
|
+
`entwurf` is a neutral npm package first. Get the package, then run **`entwurf setup
|
|
83
|
+
<project>`** — one command, the same front door from an npm global install, an npm
|
|
84
|
+
project-local install, or a source checkout. It composes every harness it finds on the
|
|
85
|
+
host and reports each one PASS / SKIP / FAIL. You are not meant to assemble the parts by
|
|
86
|
+
hand; the per-harness installers further down are the repair surface for when one unit
|
|
87
|
+
needs to be redone alone. Pi is still the adapter that hosts the ACP plugin and live
|
|
88
|
+
control-socket surface, but the base install is **not** `pi install npm:...` anymore.
|
|
76
89
|
|
|
77
90
|
The package exposes six bins:
|
|
78
91
|
|
|
@@ -85,24 +98,25 @@ The package exposes six bins:
|
|
|
85
98
|
|
|
86
99
|
The bridge/renderers/hook use stable bin names so package upgrades do not bake versioned package-store paths into native-harness settings.
|
|
87
100
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
101
|
+
Installing Entwurf installs **Entwurf only**: its package bytes, six bins, bridge, and
|
|
102
|
+
integration artifacts. It does not install `pi`, Claude Code, Copilot CLI, Codex, agy, omp, Cortex,
|
|
103
|
+
or any other harness runtime. Those are operator choices and may all be absent. The bridge also
|
|
104
|
+
does not provide credentials, tokens, subscription access, or an auth bypass; whatever an
|
|
105
|
+
operator-installed harness already trusts is what Entwurf can use. `setup` is composition, not
|
|
106
|
+
recruitment: it may wire a harness that is present, but never downloads one to make a matrix cell
|
|
107
|
+
look complete.
|
|
91
108
|
|
|
92
109
|
### From npm — user/global install
|
|
93
110
|
|
|
94
111
|
```bash
|
|
95
112
|
npm install -g @junghanacs/entwurf
|
|
96
113
|
|
|
97
|
-
|
|
98
|
-
cd /path/to/your-project
|
|
99
|
-
entwurf install .
|
|
114
|
+
entwurf setup /path/to/your-project
|
|
100
115
|
entwurf check-bridge
|
|
101
116
|
```
|
|
102
117
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
link is gone — #50 C3; nothing reads it.) The global install is the easiest path when
|
|
118
|
+
`setup` wires the target project for the pi adapter / ACP plugin lane and composes
|
|
119
|
+
whatever native harnesses are present. The global install is the easiest path when
|
|
106
120
|
Claude Code's USER-scope MCP registration should work from every cwd.
|
|
107
121
|
|
|
108
122
|
### From npm — project-local install
|
|
@@ -111,39 +125,58 @@ Claude Code's USER-scope MCP registration should work from every cwd.
|
|
|
111
125
|
cd /path/to/your-project
|
|
112
126
|
npm install --save-dev @junghanacs/entwurf
|
|
113
127
|
|
|
114
|
-
npx entwurf
|
|
128
|
+
npx entwurf setup .
|
|
115
129
|
npx entwurf check-bridge
|
|
116
130
|
```
|
|
117
131
|
|
|
118
|
-
For an npm upgrade, rerun
|
|
132
|
+
For an npm upgrade, rerun `setup` in the same scope (use
|
|
119
133
|
`@junghanacs/entwurf@latest` when you want the registry's stable line explicitly),
|
|
120
134
|
then make the first check from that same scope: `entwurf check-bridge` for a global
|
|
121
135
|
install or `npx entwurf check-bridge` for a project-local install. Native-harness
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
For manual MCP registration from a project-local install, point the host at:
|
|
125
|
-
|
|
126
|
-
```text
|
|
127
|
-
/path/to/your-project/node_modules/.bin/entwurf-bridge
|
|
128
|
-
```
|
|
136
|
+
repair and process restarts remain a separate post-upgrade step below.
|
|
129
137
|
|
|
130
|
-
|
|
138
|
+
`entwurf install <project>` is the narrower repair leaf: it writes only
|
|
139
|
+
`.pi/settings.json` in the target project, with the absolute path to the installed
|
|
140
|
+
`entwurf-bridge` launcher, and composes no harness. Reach for it when the pi wiring
|
|
141
|
+
alone needs redoing. (The old `~/.pi/agent/` target-registry link is gone — #50 C3;
|
|
142
|
+
nothing reads it.)
|
|
131
143
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
144
|
+
To register the bridge in an MCP host by hand from a project-local install, point it at
|
|
145
|
+
`node_modules/.bin/entwurf-bridge` — see
|
|
146
|
+
[External MCP registration](#external-mcp-registration).
|
|
135
147
|
|
|
136
148
|
### From source — development clone
|
|
137
149
|
|
|
138
150
|
```bash
|
|
139
151
|
git clone https://github.com/junghan0611/entwurf ~/repos/gh/entwurf
|
|
140
152
|
cd ~/repos/gh/entwurf
|
|
141
|
-
pnpm install
|
|
142
153
|
|
|
143
|
-
./run.sh
|
|
154
|
+
./run.sh setup /path/to/your-project
|
|
144
155
|
./run.sh check-bridge
|
|
145
156
|
```
|
|
146
157
|
|
|
158
|
+
The full source setup requires Node 24, pnpm, and Python 3 on PATH. Harnesses are
|
|
159
|
+
optional-by-presence: `setup` runs the frozen dependency install, then composes what the operator
|
|
160
|
+
already installed — a compatible `pi` (`>=0.84.3 <0.85`), Claude Code, agy, and the Copilot CLI
|
|
161
|
+
each get their wiring completed when detected, an absent harness is an explicit zero-state SKIP,
|
|
162
|
+
and a detected harness that cannot be completed (including a below-floor `pi`) is a named FAIL
|
|
163
|
+
that makes setup exit nonzero. `setup` never installs a harness binary or touches a credential
|
|
164
|
+
store. It also exposes stable commands under `~/.local/bin`, including `entwurf` → this
|
|
165
|
+
checkout's `run.sh`, so managed Copilot fresh does not depend on an unrelated global npm/pnpm
|
|
166
|
+
installation. A detected `copilot` composes all four of its native units (birth → MCP →
|
|
167
|
+
receiver → visible footer) in one go. Package consumers
|
|
168
|
+
run the same `entwurf setup <project>` through their npm-provided bin: installed mode is decided
|
|
169
|
+
by name first, skips the source-only pnpm bootstrap entirely, and reports the stable commands as
|
|
170
|
+
already provided by npm bin linking.
|
|
171
|
+
|
|
172
|
+
The pi user-scope registration is ONE shared entry with a recorded owner (#86 C2): installing
|
|
173
|
+
from a second checkout or npm root does not silently steal it — normal `install`/`setup` refuse
|
|
174
|
+
with zero settings bytes written, `entwurf takeover-user-scope` is the operator-explicit move,
|
|
175
|
+
`entwurf doctor-pi-package` names the ownership verdict, and `entwurf remove-user-scope` is
|
|
176
|
+
same-owner-only. The full contract — atomicity across the package and provider halves, the
|
|
177
|
+
split verdict over an operator's own override, legacy adoption, and the `managedSettingsPath`
|
|
178
|
+
binding — is [docs/setup-clean-host.md §1.1](./docs/setup-clean-host.md#11-user-scope-ownership-one-shared-registration-one-recorded-owner).
|
|
179
|
+
|
|
147
180
|
A development clone runs the bridge source through Node's strip-types path;
|
|
148
181
|
an npm-installed package runs the prebuilt JS under `mcp/entwurf-bridge/dist/`
|
|
149
182
|
because Node refuses to strip `.ts` files under `node_modules`. The dev launcher's
|
|
@@ -170,36 +203,30 @@ For daily operator sessions, launch pi with `--entwurf-control` — no id
|
|
|
170
203
|
injection; the meta-record mints the garden address (see [Garden launcher](#garden-launcher)). Older pi
|
|
171
204
|
versions may silently miss the provider/extension surface, so treat the pi floor
|
|
172
205
|
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.
|
|
206
|
+
`entwurf-bridge` from Claude Code / Copilot / Codex / Antigravity / OMP does not need pi at all for
|
|
207
|
+
delivery: no `entwurf_v2` rail launches a pi process. OMP is a pi fork, but it is its own binary and
|
|
208
|
+
resolves its own agent directory, so that lineage does not reintroduce a `pi` requirement either. That external-only shape works with the same
|
|
209
|
+
`setup` command: pi is optional-by-presence there, so a pi-less host simply gets an explicit pi
|
|
210
|
+
SKIP while the detected harnesses are composed.
|
|
175
211
|
|
|
176
|
-
### Native harness
|
|
212
|
+
### Native harness repair and doctors
|
|
177
213
|
|
|
178
214
|
A plain MCP registration exposes the bridge tools; a **garden-native** session also
|
|
179
|
-
needs entwurf's lifecycle hook and identity marker.
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
entwurf install-
|
|
190
|
-
entwurf install-
|
|
191
|
-
|
|
192
|
-
entwurf doctor-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
# GitHub Copilot CLI — four independent surfaces, four independent failure modes
|
|
196
|
-
entwurf install-copilot-bridge # birth: garden id + who-sent, on the first prompt
|
|
197
|
-
entwurf install-copilot-mcp # the entwurf tool hand (entwurf_inbox_read lives here)
|
|
198
|
-
entwurf install-copilot-receive # the receiver extension: doorbell + receiver marker
|
|
199
|
-
entwurf install-copilot-statusline # optional for a manual citizen; required for supported fresh
|
|
200
|
-
entwurf doctor-copilot-bridge
|
|
201
|
-
entwurf doctor-copilot-receive
|
|
202
|
-
```
|
|
215
|
+
needs entwurf's lifecycle hook and identity marker. `setup` already composes all of that
|
|
216
|
+
for every harness it detects — you do not paste this list to install. OMP is the one
|
|
217
|
+
exception and it is deliberate: its units are operator-selectable installs that `setup`
|
|
218
|
+
does not compose, so the three `install-omp-*` commands below are how an omp host gets
|
|
219
|
+
wired. Otherwise this is the repair surface: each unit has its own installer, its own
|
|
220
|
+
doctor with a named refusal, and its own inverse, so a single broken unit can be redone
|
|
221
|
+
without touching the rest.
|
|
222
|
+
|
|
223
|
+
- **Claude Code** (Linux-certified axis) — `install-meta-bridge`, `doctor-meta-bridge`.
|
|
224
|
+
- **Antigravity / agy** — `install-agy-bridge`, `install-agy-statusline`, `install-agy-hooks`, each with a matching `doctor-agy-*`.
|
|
225
|
+
- **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-*`.
|
|
226
|
+
- **OMP (`omp`)** — three units, all 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-receive` (the receiver extension: mailbox watch + announce-only doorbell) — each with a matching `doctor-omp-*` and `uninstall-omp-*`. One OPERATOR setting sits beside them and is not ours to write: `tools: xdev: false` in the omp agent config, without which the vendor mounts MCP tools as `xd://` devices the model cannot call.
|
|
227
|
+
|
|
228
|
+
Run them as `entwurf <command>`. Which unit a doctor's refusal names, and the clean-host
|
|
229
|
+
walk-through for each harness, live in [docs/setup-clean-host.md](./docs/setup-clean-host.md).
|
|
203
230
|
|
|
204
231
|
#### Launching Copilot as a garden citizen — `entwurf copilot`
|
|
205
232
|
|
|
@@ -245,8 +272,10 @@ the default permission prompts — which an idle, unattended session is not ther
|
|
|
245
272
|
|
|
246
273
|
Claude Code uses the supported floor `>=2.1.217`; older versions silently discard the
|
|
247
274
|
exec-hook `args`, so install and doctor fail loud rather than falling back. After any
|
|
248
|
-
upgrade, rerun
|
|
249
|
-
|
|
275
|
+
upgrade, rerun `entwurf setup <project>` — it re-composes every detected harness, all four
|
|
276
|
+
Copilot units included — and restart its existing processes; reach for a single
|
|
277
|
+
`install-*` only when one unit needs repair on its own. A claimed Claude host is certified
|
|
278
|
+
only when a **new** session using the
|
|
250
279
|
installed artifact makes `doctor-meta-bridge` exit 0 with the live owner join.
|
|
251
280
|
|
|
252
281
|
Linux is the only currently certified Claude meta-bridge axis. New macOS wiring is
|
|
@@ -360,7 +389,7 @@ Reference shape lives in [`pi/settings.reference.json`](./pi/settings.reference.
|
|
|
360
389
|
### External MCP registration
|
|
361
390
|
|
|
362
391
|
`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:
|
|
392
|
+
Copilot CLI, Codex CLI, Antigravity, OMP). Two shapes exist and they are not interchangeable:
|
|
364
393
|
|
|
365
394
|
- **plain external MCP host** — no garden meta-record or sender marker. It can read the
|
|
366
395
|
surfaces, but `entwurf_v2` is **refused by default**: there is no authoritative sender.
|
|
@@ -372,7 +401,10 @@ claude mcp add --scope user entwurf-bridge entwurf-bridge
|
|
|
372
401
|
```
|
|
373
402
|
|
|
374
403
|
Per-harness registration (Claude Code `~/.mcp.json`, Codex `~/.codex/config.toml`, the
|
|
375
|
-
managed `install-agy-*` surfaces
|
|
404
|
+
managed `install-agy-*` surfaces, and OMP's managed `install-omp-mcp` into `<omp agent dir>/mcp.json`
|
|
405
|
+
— whose pinned server key is what shadows a borrowed Claude import, see
|
|
406
|
+
[docs/external-mcp-host.md](./docs/external-mcp-host.md) §OMP), the PATH/env boundary for
|
|
407
|
+
GUI-launched MCP servers, the
|
|
376
408
|
anonymous-sender hatch, and the full external/meta-session semantics are in
|
|
377
409
|
[docs/external-mcp-host.md](./docs/external-mcp-host.md).
|
|
378
410
|
For the maintained multi-harness setup and skill/command packaging details, see `agent-config`. See also the MCP entry in [Concept primer](#concept-primer), the sender envelope contract in [AGENTS.md](./AGENTS.md), and [Custom skills](#custom-skills) for the in-pi ACP skill surface.
|
|
@@ -478,7 +510,7 @@ A two-pane recording covers the pre-0.12 v1 surface end-to-end — sibling resum
|
|
|
478
510
|
|
|
479
511
|
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
512
|
|
|
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 /
|
|
513
|
+
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 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, 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 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
514
|
|
|
483
515
|
### `entwurf_v2` — canonical dispatch verb
|
|
484
516
|
|
|
@@ -495,9 +527,9 @@ In ACP-backed and external native-harness sessions, `entwurf-bridge` exposes sev
|
|
|
495
527
|
| dead / indeterminate native-push conversation | fire-and-forget | **reject** (`native-push-target-dead` / `native-push-probe-indeterminate`) |
|
|
496
528
|
| record-less control socket (no meta-record) | any | **reject** (`record-less-socket` — pre-probe; diagnostic state, #50 C4) |
|
|
497
529
|
|
|
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.
|
|
530
|
+
**`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.
|
|
499
531
|
|
|
500
|
-
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
|
|
532
|
+
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 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; 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.
|
|
501
533
|
|
|
502
534
|
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.
|
|
503
535
|
|
package/VERIFY.md
CHANGED
|
@@ -43,7 +43,7 @@ Verification here is not a benchmark. In production we exchange short turns and
|
|
|
43
43
|
- **Deterministic floor — two tiers (#70):** `pnpm check` is the everyday CORE — toolchain (lint + typecheck), the vitest lanes, and the pure-unit / behavioral-contract / source-topology gates plus the cheap static coherence checks. It prints its own total wall time; acceptance is ≤60s on the reference host `oracle` (an operator measurement, never a hard wall-clock gate on arbitrary hosts). `pnpm run check:full` is the FULL deterministic floor — the core plus the hermetic-integration and package/install tiers — and is what the frozen-candidate protocol, push CI, release-gate, and `prepublishOnly` run. Exact membership is the named `check:*` group scripts in `package.json` (the executable SSOT — this document records meaning and principles, not the command list); a gate changes tier by semantic-class decision, never by getting faster or slower. Both tiers exclude the separately scheduled `check-gate-qualification`.
|
|
44
44
|
- **Discriminating power of that floor:** `./run.sh check-gate-qualification` (scheduled, not ambient: standalone when a lane changes a gate/mutant/matrix, in the CI `check` job on every push, and as a release-gate MUST step — no longer inside the default check chains) re-plants committed defect mutants (`scripts/mutants/*.json`, one per closed defect class) in an isolated snapshot repo and requires each to turn its gate red **bounded and at its claimed `[QK:<claim>]` signature** — a wrong-reason red fails, a baseline-red control voids the whole group, and the runner is negative-controlled on every run (zero-match/multi-match/survived/wrong-reason/hang/control-red/impurity). This measures whether the deterministic gates still *block* what they claim to block; it is **not a new evidence level** (L0–L5 are untouched) and never substitutes for LIVE evidence. Per-cut records cite claim IDs + killed mutant IDs — "N checks passed" alone is not evidence. `check-agy-permission-matrix` complements it with the enumerated permission contract space (literal cells + stated exclusion rules, oracle independent of the SUT).
|
|
45
45
|
- **Live floor:** `LIVE=1 ./run.sh release-gate <scratch-project-dir> --cut` — `pnpm run check:full` + the v2-native live gates + the ACP plugin acceptance floor. It reports a **two-tier summary**:
|
|
46
|
-
- **MUST tier** (release-blocking — owns the exit code; "green" applies only here): `pnpm run check:full`, `check-gate-qualification`, `smoke-entwurf-v2-matrix-live`, `check-bridge`, `doctor-pi-provider` (#81 — `check-bridge` proves the launcher this checkout SHIPS; this proves the invocation the operator's pi provider actually EXECS, by booting it and requiring the entwurf verb set back, because `command -v` answers yes for a command that exits 127; wired as a step on 2026-08-19 after a relocated pnpm cmd-shim cost a cut sixteen LIVE steps before the same fact surfaced at `smoke-acp-bundled-mcp-live`), the resident-garden-guard zero-token half (record birth / record-keyed socket / attach-on-reopen), the `smoke-acp-*-live` ACP plugin smokes (socket-citizen / raw-turn / overlay / provider / session-reuse / carrier-augment / memory-containment / rgg / mcp / skill / bundled-mcp / v2-send), the axis wired in on 2026-07-31 that the aggregate had simply never listed (`smoke-claude-native-resume-live`),
|
|
46
|
+
- **MUST tier** (release-blocking — owns the exit code; "green" applies only here): `pnpm run check:full`, `check-gate-qualification`, `smoke-entwurf-v2-matrix-live`, `check-bridge`, `doctor-pi-provider` (#81 — `check-bridge` proves the launcher this checkout SHIPS; this proves the invocation the operator's pi provider actually EXECS, by booting it and requiring the entwurf verb set back, because `command -v` answers yes for a command that exits 127; wired as a step on 2026-08-19 after a relocated pnpm cmd-shim cost a cut sixteen LIVE steps before the same fact surfaced at `smoke-acp-bundled-mcp-live`), the resident-garden-guard zero-token half (record birth / record-keyed socket / attach-on-reopen), the `smoke-acp-*-live` ACP plugin smokes (socket-citizen / raw-turn / overlay / provider / session-reuse / carrier-augment / memory-containment / rgg / mcp / skill / bundled-mcp / v2-send), the axis wired in on 2026-07-31 that the aggregate had simply never listed (`smoke-claude-native-resume-live`), `smoke-entwurf-chain-live` — the cross-harness delivery chain (native Claude Code → pi GPT → pi ACP Sonnet → mailbox terminus) proving sender identity and replyability at every hop plus a real read receipt at the end — the integrated `smoke-mux-lifecycle-live` (its own note below), and the two OMP steps 0.16.0 wired: `smoke-omp-receive-live` (the addressed roundtrip into a live omp citizen; it reads the capability registry and decides its own outcome rather than passing by default) and `smoke-omp-fresh-live` (the clause 7 receipt the release stop now requires). (`smoke-session-id-name` is gone — #50 C3: its `--session-id`/`--name` substrate has no entwurf consumer anymore.)
|
|
47
47
|
- **BEHAVIOR tier** (advisory, non-blocking): the resident-garden-guard positive (a model-in-loop `entwurf_self` turn). A BEHAVIOR FAIL is surfaced with its artifact path but **never blocks the cut**. The lane holds what the model *chooses*, never what our wiring fails to deliver — a gate that TELLS the model which tool to call stays MUST, because its failure is ours — measured 2026-07-24, when the tool turned out to be absent from the session schema in both observed failures (the bundled-MCP readiness gap recorded in `scripts/smoke-acp-v2-send-live.ts`).
|
|
48
48
|
- **Every MUST step is invoked and reports its own outcome.** Prerequisite-bearing LIVE MUST steps ride the P1 STEP OUTCOME protocol (`scripts/lib/step-outcome.sh`): exit 0 = PASS, exit 97 = SKIP (a prerequisite the step does not have, printed as an `[entwurf:skip]` line), anything else = FAIL. The two non-skippable static steps (`pnpm run check:full`, `check-gate-qualification`) are inline: 0 = PASS, nonzero = FAIL, no SKIP arm — they have no prerequisite to decline. A skip is never counted as a pass — that hole is what let a cortex-less host read as cortex acceptance. Without `--cut` this is the unattended diagnostic: SKIPs are reported and the run still exits 0. **`--cut` makes it acceptance and any MUST SKIP is red**, which is how "a real cut needs `LIVE=1` with `SKIP=0`" stopped being prose. A green MUST gate is **necessary, not sufficient** — GLG authorizes the cut.
|
|
49
49
|
- **When cost-bearing MUST gates run (fixed 2026-07-23, the F6/F7 lesson):** a commit that touches a rail a MUST-tier live gate covers runs that gate **before cross-review is requested** — never parked behind "run it at approval time". Deferring a wired gate to a human decision is what let F6/F7 ship reviewed-and-approved; the wiring exists so the verdict never depends on who pressed enter. "배선이 없어 못 한 것은 OK, 배선이 있는데 안 돌린 것은 우리가 남긴 구멍이다." Model-in-loop cost is spent via the subscription-backed `entwurf` provider where the gate allows it, a free-tier native model otherwise; cost is a reason to pick the cheap target, not to skip the gate.
|
|
@@ -59,6 +59,8 @@ Verification here is not a benchmark. In production we exchange short turns and
|
|
|
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
61
|
> **Fresh-call LIVE is on-demand, not part of `release-gate`.** `LIVE=1 ./run.sh smoke-mux-fresh-call-live` opens configured Pi and Claude Code siblings, spends two model turns, and preserves their native transcripts; run it directly whenever a cut changes mux fresh-call/launch behavior. Its private tmux servers and fixture-bound entwurf write axes make it deterministic about garden-record/socket residue, but those real native turns should not appear unexpectedly in every aggregate cut. **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
|
+
|
|
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.
|
|
62
64
|
>
|
|
63
65
|
> The aggregate release gate does not own a live agy conversation id, so agy's real native-push round trip is a separate acceptance axis: three fail-loud doctors plus `LIVE=1 AGY_CONVERSATION_ID=<id> ./run.sh smoke-agy-native-push-live`, followed by a fresh-conversation sender/reply check after package install. Its deterministic install/sender gates are already inside `pnpm run check:full`; do not misreport the aggregate gate as live agy evidence. **Cost fence:** the agy conversation this smoke drives runs on a free account, so open it on `gemini-3.6-flash` — never a Pro tier. The model is the operator's choice at conversation-open time; entwurf never selects it, and no assertion reads it (see the shipped-lane note: model display is not part of the agy contract).
|
|
64
66
|
>
|
|
@@ -134,11 +136,14 @@ The goal is not merely "invoke Claude Code." We want:
|
|
|
134
136
|
|
|
135
137
|
**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
138
|
|
|
137
|
-
1. `pnpm install` —
|
|
138
|
-
2.
|
|
139
|
+
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`)
|
|
140
|
+
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
141
|
3. Claude meta-bridge global plugin — only when `claude` is on PATH; otherwise skipped cleanly
|
|
140
|
-
4.
|
|
141
|
-
5.
|
|
142
|
+
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
|
|
143
|
+
5. agy bridge + exact permission + statusline + `PreInvocation` hook — only when `agy` is on PATH; each adapter is idempotent and independently doctorable
|
|
144
|
+
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
|
|
145
|
+
7. `entwurf-bridge` install smoke (`validate_entwurf_bridge`)
|
|
146
|
+
8. computed summary — per-component PASS/SKIP/FAIL; any detected-integration FAIL makes the whole command exit nonzero while valid components stay installed
|
|
142
147
|
|
|
143
148
|
```bash
|
|
144
149
|
git clone https://github.com/junghan0611/entwurf /path/to/entwurf && cd $_
|
|
@@ -146,7 +151,7 @@ git clone https://github.com/junghan0611/entwurf /path/to/entwurf && cd $_
|
|
|
146
151
|
# re-run the SAME command any time to repair a broken install
|
|
147
152
|
```
|
|
148
153
|
|
|
149
|
-
Expected tail: `DONE: entwurf setup (
|
|
154
|
+
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
155
|
|
|
151
156
|
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
157
|
|
|
@@ -173,7 +178,7 @@ addressable sends require `--entwurf-control` (measured 2026-07-24: the same
|
|
|
173
178
|
one-shot with that flag returns its own gid and delivers `entwurf_v2` to a peer
|
|
174
179
|
mailbox with `origin=pi-session`, `replyable=true`).
|
|
175
180
|
|
|
176
|
-
`setup` runs `pnpm install` + project/user
|
|
181
|
+
`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
182
|
|
|
178
183
|
### 1.4 Cross-install / cross-backend parity (optional, high-value)
|
|
179
184
|
|
|
@@ -282,6 +287,7 @@ The minimum passing bar:
|
|
|
282
287
|
7. **agy shipped lane accepted:** all three agy doctors are green; automatic birth/statusline/sender identity and same-gid native-push reply are confirmed in a fresh conversation. `agentId=meta-session/antigravity` is correct; model display is not part of that contract. Same-pid concurrent conversation invocation is not claimed.
|
|
283
288
|
8. **Boundary preservation across backends/machines:** for every shipped or explicitly probed backend, regardless of install path or host, no cross-backend tool-surface contamination and no confabulation about pi internals.
|
|
284
289
|
9. **Hygiene:** no orphan ACP children; no unexpected persisted session garbage (a turn-scoped `cwd:` fallback is never a persisted reuse).
|
|
290
|
+
10. **New-harness admission closed:** a release that introduces a native harness admitted under the #82 contract has that harness in `FRESH_CALL_BACKENDS` on all three public surfaces, with `check-harness-admission-parity` green and its clause 7 visible-fresh LIVE step green in the MUST tier. That release also owes the cross-harness leg the same release stop names — two dispatch receipts, an existing citizen's live turn delivered into the new citizen and the new citizen's live turn delivered into an existing one — recorded in `DELIVERY.md`; its deterministic half is an owed follow-up, so until that gate lands this half of the condition is prose and is judged by the recorded receipts. Partial evidence is a branch state; an `unsupported` note in `DELIVERY.md` is a description, never a permit.
|
|
285
291
|
|
|
286
292
|
Passing establishes a **release verification floor**, not an 8-hour/day operational guarantee. The floor says: gates hold, the agent honestly recognizes its environment, no tool surface is normalized away, no identity leaks, no orphans. It does **not** say a real-day workload (50–100+ turns, tool bursts, partial MCP failures, auth/version drift) survives — that needs L3–L5 evidence (appendix).
|
|
287
293
|
|
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.1` | 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 |
|