@junghanacs/entwurf 0.13.0 → 0.13.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 +5 -3
- package/BASELINE.md +57 -203
- package/CHANGELOG.md +19 -0
- package/CONTRIBUTING.md +1 -1
- package/DELIVERY.md +117 -261
- package/README.md +68 -408
- package/VERIFY.md +58 -87
- package/demo/README.md +1 -1
- package/docs/acp-backend-rail.md +231 -0
- package/docs/external-mcp-host.md +132 -0
- package/docs/fresh-cut-policy.md +99 -0
- package/docs/setup-clean-host.md +123 -328
- package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +21 -48
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/acp-client.js +12 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/backend-adapter.js +11 -10
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/config.js +1 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/engraving.js +42 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/models.js +4 -4
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/overlay.js +3 -3
- package/mcp/entwurf-bridge/src/index.ts +21 -48
- package/package.json +12 -9
- package/pi-extensions/entwurf-control.ts +20 -49
- package/pi-extensions/lib/acp/acp-client.ts +22 -0
- package/pi-extensions/lib/acp/augment.ts +42 -3
- package/pi-extensions/lib/acp/backend-adapter.ts +12 -11
- package/pi-extensions/lib/acp/backend.ts +305 -36
- package/pi-extensions/lib/acp/config.ts +1 -1
- package/pi-extensions/lib/acp/engraving.ts +43 -1
- package/pi-extensions/lib/acp/event-mapper.ts +16 -13
- package/pi-extensions/lib/acp/models.ts +4 -4
- package/pi-extensions/lib/acp/overlay.ts +3 -3
- package/prompts/engraving.md +13 -5
- package/run.sh +244 -108
- package/scripts/check-acp-carrier-augment.ts +246 -10
- package/scripts/check-acp-cortex.ts +5 -5
- package/scripts/check-acp-prompt-lifecycle.ts +565 -0
- package/scripts/check-acp-sdk-surface.ts +60 -21
- package/scripts/check-acp-stop-reason.ts +342 -0
- package/scripts/check-entwurf-v2-surface.ts +41 -0
- package/scripts/check-gate-qualification.ts +6 -3
- package/scripts/check-probe-ordering.ts +39 -7
- package/scripts/check-release-gate-outcomes.ts +332 -0
- package/scripts/lib/live-skip.ts +33 -0
- package/scripts/lib/probe-acp-turn.ts +33 -12
- package/scripts/lib/step-outcome.sh +88 -0
- package/scripts/mutants/acp-augment.json +106 -0
- package/scripts/mutants/acp-cortex.json +2 -2
- package/scripts/mutants/acp-prompt-lifecycle.json +100 -0
- package/scripts/mutants/acp-stop-reason.json +80 -0
- package/scripts/mutants/probe-ordering.json +27 -5
- package/scripts/mutants/release-gate.json +105 -0
- package/scripts/mutants/v2-surface.json +26 -15
- package/scripts/smoke-acp-bundled-mcp-live.ts +4 -3
- package/scripts/smoke-acp-carrier-augment-live.ts +2 -2
- package/scripts/smoke-acp-cortex-live.ts +8 -14
- package/scripts/smoke-acp-long-turn-live.ts +185 -0
- package/scripts/smoke-acp-mcp-live.ts +2 -2
- package/scripts/smoke-acp-memory-containment-live.ts +2 -2
- package/scripts/smoke-acp-ordering-probe-live.ts +2 -2
- package/scripts/smoke-acp-overlay-live.ts +2 -2
- package/scripts/smoke-acp-provider-live.ts +2 -2
- package/scripts/smoke-acp-raw-turn-live.ts +3 -3
- package/scripts/smoke-acp-session-reuse-live.ts +2 -2
- package/scripts/smoke-acp-skill-live.ts +2 -2
- package/scripts/smoke-acp-socket-citizen-live.ts +4 -3
- package/scripts/smoke-acp-v2-send-live.ts +4 -3
- package/scripts/smoke-agy-native-push-live.ts +4 -3
- package/scripts/smoke-claude-native-resume-live.sh +13 -3
- package/scripts/smoke-entwurf-chain-live.ts +352 -0
- package/scripts/smoke-entwurf-v2-matrix-live.ts +2 -2
- package/scripts/smoke-entwurf-v2-spawn-resume-live.ts +2 -4
- package/scripts/smoke-meta-install-state.sh +4 -0
package/docs/setup-clean-host.md
CHANGED
|
@@ -1,284 +1,119 @@
|
|
|
1
|
-
# Clean-host setup
|
|
2
|
-
|
|
3
|
-
End-to-end install of **entwurf** on a host with only `git` available — no
|
|
4
|
-
node, no npm package, no pi binary, no dotfiles. The point is to validate the
|
|
5
|
-
public install surface as an outside user would experience it.
|
|
6
|
-
|
|
7
|
-
> **Scope.** This is the current entwurf 0.12.x install recipe, including the
|
|
8
|
-
> 0.12.7 Antigravity (`agy`) citizen surface. The base package install is
|
|
9
|
-
> **neutral npm**, not `pi install npm:...`. Pi is an optional adapter lane for
|
|
10
|
-
> the ACP provider / control-socket runtime. Installed packages under
|
|
11
|
-
> `node_modules` must not run raw `.ts` bridge, doctor, or native-hook helpers
|
|
12
|
-
> through Node strip-types.
|
|
13
|
-
|
|
14
|
-
`entwurf` is a garden-citizen dispatch substrate and meta-bridge. It does not
|
|
15
|
-
provide, copy, or mediate backend credentials — it lets the official backend CLI
|
|
16
|
-
or the pi adapter read whatever auth the user already trusts on the host
|
|
17
|
-
(AGENTS.md Hard Rule #9).
|
|
18
|
-
|
|
19
|
-
## Reference target
|
|
20
|
-
|
|
21
|
-
Written against a clean **Linux** host (Ubuntu / Debian / NixOS) reachable via
|
|
22
|
-
SSH, here called `cleanhost`. `nvm` keeps the Node path independent of the distro.
|
|
23
|
-
The neutral npm package may install elsewhere, but Linux is the only currently
|
|
24
|
-
certified Claude meta-bridge axis. macOS has no `/proc` bridge discovery
|
|
25
|
-
and is not yet verified/certified for this cut, so its installer refuses new wiring
|
|
26
|
-
and its strict doctor stays `NOT CERTIFIED`/nonzero.
|
|
27
|
-
This is not permanent; future native validation may reopen the lane, while Darwin
|
|
28
|
-
uninstall remains available for older managed state.
|
|
1
|
+
# Clean-host setup
|
|
29
2
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
3
|
+
Current operator recipe for a fresh Linux desktop/workstation. The neutral npm
|
|
4
|
+
package can install elsewhere, but Claude's garden-native meta-bridge is certified
|
|
5
|
+
only on Linux because its strict live-owner join uses `/proc`.
|
|
6
|
+
|
|
7
|
+
## Requirements
|
|
34
8
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
The required CI job `artifact-consumer` runs `check-install-container` against one
|
|
38
|
-
candidate tarball in a Node 24 Linux image that has never seen the checkout. It
|
|
39
|
-
records the artifact sha256 plus image id/repository digest, mounts only that tarball
|
|
40
|
-
read-only, installs globally as non-root through an isolated npm prefix, resolves all
|
|
41
|
-
five bins through PATH, freezes the package root, checks the regular-file path+sha256
|
|
42
|
-
manifest across `install-meta-bridge`, boots MCP `tools/list`, and drives the strict
|
|
43
|
-
doctor. This closes the installed package shape; it does **not** replace this real-host
|
|
44
|
-
walk-through. Its fake Claude CLI, planted plugin cache, stand-in owner, and `/proc`
|
|
45
|
-
bridge are fixtures, so they cannot prove native plugin installation, real hook spawn,
|
|
46
|
-
or idle wake.
|
|
47
|
-
|
|
48
|
-
Default CI lets the gate pack once into a temporary directory. Release acceptance
|
|
49
|
-
instead preserves the `npm pack` output and passes its absolute path as
|
|
50
|
-
`ENTWURF_CANDIDATE_TGZ`; the gate verifies package name/version, prints canonical
|
|
51
|
-
path+sha256, and consumes that exact file without chmod/copy/re-pack. The accepted
|
|
52
|
-
file is the one later published with `--tag repair` (full commands in VERIFY.md).
|
|
53
|
-
|
|
54
|
-
The direct runtime complement is #51 B/B2: actual Claude sessions on one NixOS host
|
|
55
|
-
showed 2.1.138 dropping `args` while reporting success and 2.1.217 honoring exec argv
|
|
56
|
-
and waking on FileChanged exit 2. A target host is still accepted only after installing
|
|
57
|
-
the released artifact, opening a new Claude session, and obtaining installed-doctor
|
|
58
|
-
exit 0.
|
|
59
|
-
|
|
60
|
-
## Pin matrix
|
|
61
|
-
|
|
62
|
-
| Component | Pin / floor | Source of truth |
|
|
9
|
+
| Component | Requirement | Needed for |
|
|
63
10
|
|---|---|---|
|
|
64
|
-
| Node | **`>=24.0.0`**
|
|
65
|
-
|
|
|
66
|
-
|
|
|
67
|
-
|
|
|
68
|
-
|
|
|
69
|
-
| Antigravity `agy` |
|
|
11
|
+
| Node | **`>=24.0.0`** | package and bridge runtime |
|
|
12
|
+
| npm | bundled with Node | package installation |
|
|
13
|
+
| entwurf | `@junghanacs/entwurf` | all lanes |
|
|
14
|
+
| pi | optional, `@earendil-works/pi-coding-agent >=0.83.0 <0.84` | ACP provider, control sockets, spawn-bg resume |
|
|
15
|
+
| Claude Code | optional, **`>=2.1.217`** — the exec-form hook floor | Claude ACP auth/runtime and mailbox-backed native citizen |
|
|
16
|
+
| Antigravity `agy` | optional, operator-installed and authenticated | native-push citizen |
|
|
17
|
+
| Cortex Code | optional, operator-installed and authenticated | Cortex ACP backend |
|
|
70
18
|
|
|
71
|
-
|
|
19
|
+
Claude Code >=2.1.217 is required for the managed exec-hook lifecycle. The package
|
|
20
|
+
never supplies or proxies backend credentials.
|
|
72
21
|
|
|
73
|
-
|
|
74
|
-
ssh cleanhost
|
|
22
|
+
## 1. Install Node and entwurf
|
|
75
23
|
|
|
76
|
-
|
|
77
|
-
source ~/.nvm/nvm.sh
|
|
24
|
+
Use the host's normal Node 24 installation. With nvm:
|
|
78
25
|
|
|
26
|
+
```bash
|
|
79
27
|
nvm install 24
|
|
80
|
-
nvm
|
|
81
|
-
node
|
|
82
|
-
npm
|
|
28
|
+
nvm use 24
|
|
29
|
+
node --version
|
|
30
|
+
npm --version
|
|
83
31
|
```
|
|
84
32
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
via git and source `~/.nvm/nvm.sh` directly.
|
|
88
|
-
- **Subshell trap**: `nvm install 24 | tail` runs in a pipe-subshell, so PATH
|
|
89
|
-
changes do not reach the parent shell. Drop the pipe, or run `nvm use 24` in
|
|
90
|
-
the same shell afterward.
|
|
91
|
-
|
|
92
|
-
## Stage 1 — neutral entwurf npm install
|
|
93
|
-
|
|
94
|
-
Install the public package with npm. This does **not** require pi.
|
|
33
|
+
Global install is simplest when native harnesses should find stable bins from every
|
|
34
|
+
working directory:
|
|
95
35
|
|
|
96
36
|
```bash
|
|
97
37
|
npm install -g @junghanacs/entwurf
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
which entwurf-bridge
|
|
101
|
-
which entwurf-statusline
|
|
102
|
-
which entwurf-agy-statusline
|
|
103
|
-
which entwurf-agy-imprint
|
|
104
|
-
entwurf --help | head -5
|
|
38
|
+
entwurf --help
|
|
39
|
+
entwurf check-bridge
|
|
105
40
|
```
|
|
106
41
|
|
|
107
|
-
|
|
108
|
-
not pull them in as package dependencies. That separation is intentional: the
|
|
109
|
-
MCP bridge can boot in Claude Code / Codex / Antigravity without pi present.
|
|
110
|
-
|
|
111
|
-
## Stage 2 — auth-free bridge boot
|
|
112
|
-
|
|
113
|
-
Prove the installed MCP server answers `tools/list` from inside `node_modules`.
|
|
114
|
-
This is the first `node_modules` strip-types regression fixed in 0.12.0: Node
|
|
115
|
-
refuses `--experimental-strip-types` for `.ts` under `node_modules`, so the
|
|
116
|
-
installed package must boot the prebuilt JS under `mcp/entwurf-bridge/dist/`.
|
|
117
|
-
The same installed-vs-dev split closes every shipped `.ts`-at-runtime surface on
|
|
118
|
-
that fence: the `doctor-meta-bridge` store-scan helper (0.12.4), the Claude plugin
|
|
119
|
-
hook (0.12.5, compiled `dist/pi-extensions/meta-bridge-hook.js`), and the agy
|
|
120
|
-
`PreInvocation` imprint (0.12.7, compiled `dist/scripts/agy-imprint.js`). Installed
|
|
121
|
-
packages run tsc-emitted JS on these paths; dev clones keep transparent `.ts`
|
|
122
|
-
source execution.
|
|
42
|
+
A project-local installation is also supported:
|
|
123
43
|
|
|
124
44
|
```bash
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
const timer = setTimeout(() => { child.kill('SIGKILL'); console.error(err || 'timeout'); process.exit(1); }, 5000);
|
|
130
|
-
child.stderr.on('data', d => err += d);
|
|
131
|
-
child.stdout.on('data', d => {
|
|
132
|
-
out += d;
|
|
133
|
-
try {
|
|
134
|
-
const msg = JSON.parse(out.trim());
|
|
135
|
-
const names = (msg.result?.tools ?? []).map(t => t.name).sort();
|
|
136
|
-
for (const n of ['entwurf_v2','entwurf_peers','entwurf_self','entwurf_inbox_read','entwurf_register_native']) {
|
|
137
|
-
if (!names.includes(n)) throw new Error(`missing ${n}: ${names.join(',')}`);
|
|
138
|
-
}
|
|
139
|
-
clearTimeout(timer);
|
|
140
|
-
child.kill('SIGTERM');
|
|
141
|
-
console.log(names.join(','));
|
|
142
|
-
} catch {}
|
|
143
|
-
});
|
|
144
|
-
child.stdin.write(JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'tools/list' }) + '\n');
|
|
145
|
-
JS
|
|
45
|
+
mkdir -p ~/entwurf-smoke && cd ~/entwurf-smoke
|
|
46
|
+
npm init -y
|
|
47
|
+
npm install --save-dev @junghanacs/entwurf
|
|
48
|
+
npx entwurf check-bridge
|
|
146
49
|
```
|
|
147
50
|
|
|
148
|
-
|
|
149
|
-
tools
|
|
150
|
-
already-running native conversation; it is not a fresh-spawn verb.
|
|
51
|
+
`check-bridge` is auth-free. It proves the installed prebuilt MCP server boots and
|
|
52
|
+
lists the five garden tools; it does not prove a backend model turn or native hook.
|
|
151
53
|
|
|
152
|
-
##
|
|
54
|
+
## 2. Optional pi adapter / ACP plugin
|
|
153
55
|
|
|
154
|
-
|
|
155
|
-
a compatible pi binary separately and wire the target project.
|
|
56
|
+
Install the exact release floor, then wire the project:
|
|
156
57
|
|
|
157
58
|
```bash
|
|
158
|
-
npm install -g @earendil-works/pi-coding-agent@0.
|
|
59
|
+
npm install -g @earendil-works/pi-coding-agent@0.83.0
|
|
159
60
|
pi --version
|
|
160
61
|
|
|
161
|
-
mkdir -p ~/entwurf-smoke
|
|
162
62
|
cd ~/entwurf-smoke
|
|
163
63
|
entwurf install .
|
|
164
|
-
entwurf check-bridge
|
|
165
|
-
|
|
166
|
-
# pi adapter/provider registration smoke
|
|
167
64
|
pi -e "$(npm root -g)/@junghanacs/entwurf" --list-models entwurf
|
|
168
65
|
```
|
|
169
66
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
67
|
+
The supported range is `>=0.83.0 <0.84`. It is a hard minimum: installing this
|
|
68
|
+
release onto a 0.82.x pi host upgrades the runtime rather than keeping the older
|
|
69
|
+
minor. A host using only the external MCP bridge can skip pi until it needs a
|
|
70
|
+
control socket or dormant `owned-outcome` resume.
|
|
71
|
+
|
|
72
|
+
For daily garden-native pi sessions:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
cd ~/entwurf-smoke
|
|
76
|
+
pi -e "$(npm root -g)/@junghanacs/entwurf" --entwurf-control
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
The V3 record births the garden id; do not inject a pi session id manually.
|
|
178
80
|
|
|
179
|
-
##
|
|
81
|
+
## 3. Optional Claude Code native citizen
|
|
180
82
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
83
|
+
First register the MCP bridge if the stable bin is not already present:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
claude mcp add --scope user entwurf-bridge entwurf-bridge
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Then install and certify the mailbox/self-fetch lifecycle:
|
|
187
90
|
|
|
188
91
|
```bash
|
|
189
92
|
entwurf install-meta-bridge
|
|
93
|
+
# restart every already-open Claude Code process
|
|
94
|
+
# open a new Claude Code session
|
|
190
95
|
entwurf doctor-meta-bridge
|
|
191
96
|
```
|
|
192
97
|
|
|
193
|
-
|
|
98
|
+
The supported floor `>=2.1.217` is enforced by package metadata through installer
|
|
99
|
+
and doctor gates. Older Claude versions validate an exec-form hook but silently drop
|
|
100
|
+
its `args` at runtime, so there is no shell-form fallback.
|
|
194
101
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
102
|
+
A doctor PASS requires both ownership and runtime evidence, including a live
|
|
103
|
+
MCP↔sender↔receiver owner join. `NOT CERTIFIED` exits nonzero: a fixture, plugin
|
|
104
|
+
validation, or hand-inspected marker cannot replace a new real session. If the launch
|
|
105
|
+
form is unsupported, reinstall; if ownership is correct but the live join is absent,
|
|
106
|
+
restart the affected session.
|
|
198
107
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
ok installed owner argv execs directly (no shell) through hook-launch.sh and keys its sender marker to the live host pid
|
|
203
|
-
ok <N> live Claude MCP process(es): sender + receiver owner join is live and record-backed
|
|
204
|
-
ok full store scan: no corrupt records, duplicate nativeSessionId, body/filename drift, or backend↔wakeMode contradiction
|
|
205
|
-
ok check-entwurf-v2-surface: shipped surface source present; exhaustive source-shape gate is a repo/release invariant (not run under node_modules)
|
|
206
|
-
```
|
|
108
|
+
New macOS wiring is refused because the live join is not instrumented there. Darwin
|
|
109
|
+
uninstall remains available for cleaning an older managed install; this is an evidence
|
|
110
|
+
boundary, not a permanent impossibility claim.
|
|
207
111
|
|
|
208
|
-
|
|
209
|
-
is open — or the host has no `/proc` — the doctor reports `NOT CERTIFIED` and exits
|
|
210
|
-
nonzero, because only the static + synthetic checks were possible and neither of them
|
|
211
|
-
can measure the live join. A host whose live tier was never measured is an
|
|
212
|
-
unmeasured host, not a passing one. An `UNSUPPORTED` launch form needs reinstall; a
|
|
213
|
-
failed live owner join after reinstall means the already-open Claude process still
|
|
214
|
-
holds the old hook definition in memory and must be restarted — the hook itself
|
|
215
|
-
refuses to write markers in that state rather than keying them to whatever the old
|
|
216
|
-
command's shell left behind.
|
|
217
|
-
|
|
218
|
-
If any of those sections reports `ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING`,
|
|
219
|
-
the host is still running a pre-0.12.5 package or a broken tarball. Reinstall the
|
|
220
|
-
current package and re-run `entwurf install-meta-bridge && entwurf doctor-meta-bridge`.
|
|
221
|
-
|
|
222
|
-
Store invariant (only for a host that is NOT clean): this walkthrough assumes no
|
|
223
|
-
prior `~/.pi/agent/meta-sessions`. Production reads **schemaVersion 3 only** and
|
|
224
|
-
the repo carries no legacy reader or migrator — the active store provides no
|
|
225
|
-
cross-generation continuity (sessions flow; memory lives in the native
|
|
226
|
-
transcripts and the embedding axes). On a store the live schema cannot read,
|
|
227
|
-
`entwurf_self`, `entwurf_v2`, and inbox reads fail loud; `entwurf_peers` keeps
|
|
228
|
-
its fact listing alive and reports the records as diagnostics. The owned
|
|
229
|
-
`setup` / `install` / `install-meta-bridge` entrypoints refuse before activation
|
|
230
|
-
writes rather than crossing this boundary silently. The one prescription is the
|
|
231
|
-
generation cut: `entwurf meta-bridge-fresh-cut` (quiesce-checked; archives the
|
|
232
|
-
whole previous generation to a timestamped sibling and opens an empty one — the
|
|
233
|
-
archive is forensic only, no restore verb). Once per boundary. A truly clean
|
|
234
|
-
host has nothing to cut and can ignore this paragraph. The refusal is a
|
|
235
|
-
preflight, not a lock: for checkout-backed installs, quiesce sessions before
|
|
236
|
-
pull, then fresh-cut, setup, and reopen.
|
|
237
|
-
|
|
238
|
-
Read the cut's exit status rather than only chaining it (#54; `--help` prints the
|
|
239
|
-
contract): `0` complete → run `setup`; `1` NOTHING MOVED — a live/unprovable
|
|
240
|
-
surface, an occupied archive destination, an unreadable surface — fix the named
|
|
241
|
-
cause and re-run, and do not run `setup`, because the store it refused is still
|
|
242
|
-
there; `2` usage; `3` CUT TRANSITION INCOMPLETE — at least one archive move
|
|
243
|
-
happened but the fresh generation is not confirmed open — inspect, or re-run to
|
|
244
|
-
finish under a new stamp; `4` the cut is COMPLETE but marker/socket residue could
|
|
245
|
-
not be unlinked — `setup` may run. Prefer fixing the named residue and re-running
|
|
246
|
-
before `setup`; if new citizens have already been born, remove it manually rather
|
|
247
|
-
than fresh-cutting their new generation. Only `0` is success.
|
|
248
|
-
|
|
249
|
-
Upgrade invariant: every global npm/pnpm package upgrade must be followed by
|
|
250
|
-
`entwurf install-meta-bridge` from that same installed binary and then
|
|
251
|
-
`entwurf doctor-meta-bridge`. Installed statusline/MCP entries use stable bin
|
|
252
|
-
shims and the marketplace source lives in a version-stable operator data dir, but
|
|
253
|
-
package managers still do not re-materialize Claude's plugin bundle/cache. If a
|
|
254
|
-
dev checkout's `./run.sh doctor-meta-bridge` expects repo-owned paths while the
|
|
255
|
-
global install intentionally owns the meta-bridge (or the reverse), that is an
|
|
256
|
-
ownership mismatch — run the doctor from the surface that intentionally owns the
|
|
257
|
-
install, or reinstall from the other surface. Restart already-open Claude Code
|
|
258
|
-
sessions after changing the meta-bridge install.
|
|
259
|
-
|
|
260
|
-
A plain external MCP host can call the read surfaces (`entwurf_peers`,
|
|
261
|
-
`entwurf_inbox_read`), but an `entwurf_v2` send is **refused by default** (#50 C4:
|
|
262
|
-
"if we don't know who sent it, we don't send it") — it has no authoritative sender.
|
|
263
|
-
A deliberately-anonymous host may wire the explicit
|
|
264
|
-
`ENTWURF_BRIDGE_ALLOW_ANONYMOUS_SENDER=1` hatch and then delivers external and
|
|
265
|
-
non-replyable; see README §"Wiring `entwurf-bridge` into an external MCP host".
|
|
266
|
-
A garden-native meta-session has a garden id and a trusted sender marker, so it can
|
|
267
|
-
call `entwurf_self` and be addressed by garden id. **Whether it has a mailbox depends
|
|
268
|
-
on its rail**: a self-fetch backend (Claude Code) has a drainable inbox and receives
|
|
269
|
-
mailbox wakeups, while a native-push backend (Antigravity) has **no mailbox and no
|
|
270
|
-
idle-wake watch at all** — a reply is injected straight into its live conversation, and
|
|
271
|
-
it is reachable only while the adapter probe finds that conversation. Do not assume a
|
|
272
|
-
mailbox from "garden-native meta-session".
|
|
273
|
-
|
|
274
|
-
## Stage 5 — Antigravity native citizen (optional)
|
|
275
|
-
|
|
276
|
-
If `agy` is already installed and authenticated by the operator, wire the three
|
|
277
|
-
separate ownership atoms. Entwurf does not install agy or copy its auth.
|
|
112
|
+
## 4. Optional Antigravity native citizen
|
|
278
113
|
|
|
279
|
-
|
|
280
|
-
which agy
|
|
114
|
+
Install the three independently owned surfaces:
|
|
281
115
|
|
|
116
|
+
```bash
|
|
282
117
|
entwurf install-agy-bridge
|
|
283
118
|
entwurf install-agy-statusline
|
|
284
119
|
entwurf install-agy-hooks
|
|
@@ -288,118 +123,78 @@ entwurf doctor-agy-statusline
|
|
|
288
123
|
entwurf doctor-agy-hooks
|
|
289
124
|
```
|
|
290
125
|
|
|
291
|
-
|
|
126
|
+
The bridge owns one MCP server and narrow rules for the normal tools; the statusline
|
|
127
|
+
owns its subtree; the hook owns one `PreInvocation` entry. Unrelated settings are
|
|
128
|
+
preserved. A fresh conversation initially may show `🪛 ? agy`; the first invocation
|
|
129
|
+
births the record by native `conversationId`, after which the garden id appears.
|
|
292
130
|
|
|
293
|
-
|
|
294
|
-
and one narrow rule per tool the normal agy workflow calls —
|
|
295
|
-
`mcp(entwurf-bridge/entwurf_v2)`, `mcp(entwurf-bridge/entwurf_peers)`,
|
|
296
|
-
`mcp(entwurf-bridge/entwurf_self)` — in
|
|
297
|
-
`~/.gemini/antigravity-cli/settings.json`'s permission allow-list;
|
|
298
|
-
- `install-agy-statusline`: the `statusLine` subtree only, pointing at
|
|
299
|
-
`entwurf-agy-statusline`;
|
|
300
|
-
- `install-agy-hooks`: one named plugin `PreInvocation` hook pointing at
|
|
301
|
-
`entwurf-agy-imprint`.
|
|
131
|
+
Real native-push acceptance needs an already-running conversation:
|
|
302
132
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
`unsandboxed(*)` are operator policy and are never granted by this package.
|
|
307
|
-
|
|
308
|
-
Restart agy, open a **fresh conversation**, and make one model invocation. The
|
|
309
|
-
hook's first `PreInvocation` births/attaches the conversation by native
|
|
310
|
-
`conversationId`; after that, the statusline should show `🪛 <garden-id> agy`.
|
|
311
|
-
Verify:
|
|
133
|
+
```bash
|
|
134
|
+
LIVE=1 AGY_CONVERSATION_ID=<id> entwurf smoke-agy-native-push-live
|
|
135
|
+
```
|
|
312
136
|
|
|
313
|
-
|
|
314
|
-
`replyable:true` while the native route probes alive;
|
|
315
|
-
2. an `entwurf_v2` send from agy reaches a sibling with that sender gid;
|
|
316
|
-
3. a sibling's `entwurf_v2(..., intent=fire-and-forget)` reply to the same gid
|
|
317
|
-
direct-injects into the same agy conversation.
|
|
137
|
+
## 5. Optional ACP backend turns
|
|
318
138
|
|
|
319
|
-
|
|
320
|
-
Same-pid concurrent conversation invocation is not supported; separate agy
|
|
321
|
-
processes have separate pid/start-key sender markers.
|
|
139
|
+
Claude uses the operator's existing local Claude authentication:
|
|
322
140
|
|
|
323
|
-
|
|
141
|
+
```bash
|
|
142
|
+
LIVE=1 entwurf smoke-acp-provider-live
|
|
143
|
+
```
|
|
324
144
|
|
|
325
|
-
|
|
326
|
-
|
|
145
|
+
Cortex requires an authenticated `cortex` CLI and an explicit connection. Keep
|
|
146
|
+
`CORTEX_HOME` unset; the adapter refuses its presence because it bypasses containment.
|
|
327
147
|
|
|
328
148
|
```bash
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
source ~/.bashrc
|
|
332
|
-
claude login
|
|
333
|
-
|
|
334
|
-
cd ~/entwurf-smoke
|
|
335
|
-
pi --provider entwurf --model claude-sonnet-5 -p "reply with ok only"
|
|
149
|
+
LIVE=1 ENTWURF_ACP_CORTEX_CONNECTION=<conn> \
|
|
150
|
+
entwurf smoke-acp-cortex-live
|
|
336
151
|
```
|
|
337
152
|
|
|
338
|
-
|
|
339
|
-
|
|
153
|
+
The aggregate release gate is Claude-backed and does not run Cortex automatically.
|
|
154
|
+
Its silence is not a Cortex PASS.
|
|
340
155
|
|
|
341
|
-
|
|
342
|
-
model routing, and one real turn — nothing more. A plain `pi -p` run is not a
|
|
343
|
-
garden citizen: with no `--entwurf-control` there is no routable control socket,
|
|
344
|
-
so entwurf deliberately leaves `PI_SESSION_ID` unset and a bundled
|
|
345
|
-
`entwurf_self` / `entwurf_v2` call **fails loud** naming the missing wiring.
|
|
346
|
-
That is the contract, not a defect — an address a peer cannot route to is worse
|
|
347
|
-
than none. For the garden surface (citizen birth, addressable sends) use Stage 7.
|
|
156
|
+
## 6. Upgrade and repair
|
|
348
157
|
|
|
349
|
-
|
|
158
|
+
After upgrading the package, rerun the managed installers for every native harness
|
|
159
|
+
in use and restart their existing processes. Native plugin caches are not live-reload
|
|
160
|
+
safe across launch-contract changes.
|
|
350
161
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
(#50 C2): pi mints its own session id (a `uuidv7` is normal), `session_start`
|
|
354
|
-
attaches that session to its meta-record, and the **record** mints the garden id
|
|
355
|
-
everything addressable hangs off.
|
|
162
|
+
If install or doctor reports an unreadable/old active citizen generation, do not edit
|
|
163
|
+
records by hand:
|
|
356
164
|
|
|
357
165
|
```bash
|
|
358
|
-
pi
|
|
166
|
+
# close pi, Claude, and agy sessions first
|
|
167
|
+
entwurf meta-bridge-fresh-cut
|
|
168
|
+
entwurf setup ~/entwurf-smoke
|
|
359
169
|
```
|
|
360
170
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
`entwurf_peers` (or `entwurf_self` from inside the session) instead of guessing
|
|
364
|
-
the filename. If the record cannot be written the control server is refused,
|
|
365
|
-
`PI_SESSION_ID` stays unset, and the reason is on stderr: an unaddressable
|
|
366
|
-
resident must never survive quietly.
|
|
171
|
+
Read the cut's exit status before chaining setup. The complete quiescence, archive,
|
|
172
|
+
and exit-code contract is [fresh-cut-policy.md](./fresh-cut-policy.md).
|
|
367
173
|
|
|
368
|
-
|
|
369
|
-
id. Do not choose the transport by hand: the same-looking id may name a live pi
|
|
370
|
-
socket, a dormant pi record, a mailbox-backed Claude session, or a native-push
|
|
371
|
-
Antigravity conversation.
|
|
174
|
+
## 7. Release acceptance versus host acceptance
|
|
372
175
|
|
|
373
|
-
|
|
176
|
+
- `entwurf check-bridge`: installed MCP bytes boot; no backend auth.
|
|
177
|
+
- `pnpm check`: source deterministic floor; maintainer checkout only.
|
|
178
|
+
- `check-install-container`: checkout-invisible Linux package-consumer shape using
|
|
179
|
+
fixtures; not a native lifecycle proof.
|
|
180
|
+
- `doctor-meta-bridge`: one installed real Claude host, only with a new live session.
|
|
181
|
+
- `LIVE=1 entwurf release-gate /path/to/scratch --cut`: aggregate runtime acceptance (`--cut` makes any MUST SKIP red; without it the run is a diagnostic pass).
|
|
374
182
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
rm -rf ~/entwurf-smoke/.pi
|
|
183
|
+
Keep these verdicts separate. Current protocol is [VERIFY.md](../VERIFY.md); recorded
|
|
184
|
+
host verdicts are [BASELINE.md](../BASELINE.md).
|
|
378
185
|
|
|
379
|
-
|
|
380
|
-
entwurf uninstall-meta-bridge 2>/dev/null || true
|
|
381
|
-
entwurf uninstall-agy-hooks 2>/dev/null || true
|
|
382
|
-
entwurf uninstall-agy-statusline 2>/dev/null || true
|
|
383
|
-
entwurf uninstall-agy-bridge 2>/dev/null || true
|
|
186
|
+
## Uninstall
|
|
384
187
|
|
|
385
|
-
|
|
386
|
-
npm uninstall -g @junghanacs/entwurf
|
|
387
|
-
npm uninstall -g @earendil-works/pi-coding-agent 2>/dev/null || true
|
|
188
|
+
Run only the surfaces this host owns:
|
|
388
189
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
190
|
+
```bash
|
|
191
|
+
entwurf uninstall-meta-bridge
|
|
192
|
+
entwurf uninstall-agy-hooks
|
|
193
|
+
entwurf uninstall-agy-statusline
|
|
194
|
+
entwurf uninstall-agy-bridge
|
|
195
|
+
entwurf uninstall ~/entwurf-smoke
|
|
196
|
+
npm uninstall -g @junghanacs/entwurf
|
|
392
197
|
```
|
|
393
198
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
meta-bridge verification where used, all three agy doctors plus a fresh native
|
|
397
|
-
round trip where used, and at least one authenticated ACP runtime smoke. Preserve
|
|
398
|
-
the exact package version, candidate tarball sha256, container image identity,
|
|
399
|
-
host OS, Claude version, and installed doctor output together. The repair history
|
|
400
|
-
is fixed: `0.12.8-repair.0` cannot deliver, while published
|
|
401
|
-
`0.12.8-repair.1` passed installed-native doctors on maintainer + secondary Linux
|
|
402
|
-
hosts and remains under dist-tag `repair`. Stable promotion publishes accepted
|
|
403
|
-
`0.12.8` bytes under `latest` and must preserve `repair=0.12.8-repair.1`.
|
|
404
|
-
GLG owns every version, tag, publish, push, and host-reinstall decision; the
|
|
405
|
-
complete ordered checklist is in VERIFY.md §Stable 0.12.8 order.
|
|
199
|
+
Each managed surface has an honest inverse and preserves unrelated native-harness
|
|
200
|
+
configuration.
|
|
@@ -298,54 +298,27 @@ function abbreviateHomeMcp(cwd) {
|
|
|
298
298
|
// NOT gate on replyability (a `wants_reply` from an external/non-replyable caller
|
|
299
299
|
// is surfaced honestly, not rejected; the decider routes on target + intent, not
|
|
300
300
|
// sender replyability).
|
|
301
|
-
server.tool("entwurf_v2", "CANONICAL DELIVERY SURFACE for garden ids
|
|
302
|
-
"
|
|
303
|
-
"
|
|
304
|
-
"
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
"
|
|
308
|
-
"
|
|
309
|
-
"
|
|
310
|
-
"
|
|
311
|
-
"
|
|
312
|
-
"
|
|
313
|
-
"
|
|
314
|
-
"
|
|
315
|
-
"
|
|
316
|
-
"
|
|
317
|
-
"
|
|
318
|
-
"
|
|
319
|
-
"
|
|
320
|
-
"
|
|
321
|
-
"
|
|
322
|
-
"wants_reply:true if you need an answer (wants_reply is NOT owned-outcome). Replies to a citizen " +
|
|
323
|
-
"with NO socket liveness (liveness=unsupported) are ALSO fire-and-forget, and the decider picks " +
|
|
324
|
-
"that citizen's own rail: a self-fetch backend (e.g. Claude Code) gets the meta-bridge mailbox, " +
|
|
325
|
-
"while a native-push backend (e.g. Antigravity) gets direct injection into its live conversation " +
|
|
326
|
-
"and has NO mailbox at all — do not assume mailbox semantics for every unsupported citizen. A " +
|
|
327
|
-
"native-push target IS measured by its own adapter probe, and that probe is THREE-valued, so " +
|
|
328
|
-
"the send is never silently queued: alive → injected; dead → rejected as " +
|
|
329
|
-
"native-push-target-dead; indeterminate → rejected as native-push-probe-indeterminate. " +
|
|
330
|
-
"Those two rejects stay distinct because 'we could not establish it' is not 'it is gone' — " +
|
|
331
|
-
"collapsing them reports a guess as a fact. THERE IS A " +
|
|
332
|
-
"THIRD RESULT, so do not read liveness=unsupported as 'reachable by some rail': the mailbox path " +
|
|
333
|
-
"delivers only to a DELIVERABLE citizen (a self-fetch backend whose receiver is live and armed), " +
|
|
334
|
-
"so a terminated Claude Code session — and any record whose backend has no adapter on this lane, " +
|
|
335
|
-
"e.g. codex — is rejected as mailbox-undeliverable rather than queued into an inbox nobody drains. " +
|
|
336
|
-
"unsupported means only 'this backend has no control-socket probe'. " +
|
|
337
|
-
"owned-outcome is ONLY for waking a DORMANT socket-domain citizen (spawn-bg resume, currently " +
|
|
338
|
-
"backend pi); on a live target it is rejected as owned-live-no-autosend. Neither self-fetch nor " +
|
|
339
|
-
"native-push has resume authority, but they reject under DIFFERENT reasons — self-fetch as " +
|
|
340
|
-
"backend-liveness-unsupported, native-push as native-push-no-resume-authority. " +
|
|
341
|
-
"It is NEVER auto-converted — so pick the right intent up front. " +
|
|
342
|
-
"mode applies to a CONTROL-SOCKET send only — it is the injection style for a live pi turn, and " +
|
|
343
|
-
"the mailbox, native-push, and spawn-bg plans carry no mode at all, so setting it for those " +
|
|
344
|
-
"targets changes nothing (a native-push send IS live and still ignores it). wants_reply rides " +
|
|
345
|
-
"every rail. Use entwurf_peers to discover targets. " +
|
|
346
|
-
"Payload guidance: message hard cap 16000 chars. For larger reviews/logs, write an " +
|
|
347
|
-
"artifact and dispatch its path plus a short digest; avoid multi-part sends because " +
|
|
348
|
-
"mailbox doorbells may coalesce.", {
|
|
301
|
+
server.tool("entwurf_v2", "CANONICAL DELIVERY SURFACE for garden ids: message, reply, or hand off to whoever an id names. The id " +
|
|
302
|
+
"alone does not say which rail that citizen answers on. Give target + intent; the decider picks transport " +
|
|
303
|
+
"from liveness (live socket citizen → control-socket send; dormant socket citizen → spawn-bg resume; " +
|
|
304
|
+
"deliverable self-fetch citizen → meta-bridge mailbox; probe-alive native-push citizen → direct injection " +
|
|
305
|
+
"into its conversation) and reports ONE outcome (delivered / rejected / lock-retained / " +
|
|
306
|
+
"delivered-but-lock-dirty). EXISTING targets only; discover with entwurf_peers. INTENT — picking wrong is " +
|
|
307
|
+
"rejected, never auto-converted. A peer entwurf_peers shows as liveness=alive → fire-and-forget. A " +
|
|
308
|
+
"citizen with NO socket liveness (liveness=unsupported) is ALSO fire-and-forget — unsupported means only " +
|
|
309
|
+
'"no control-socket probe" — and the decider picks its own rail: a self-fetch backend (e.g. Claude Code) ' +
|
|
310
|
+
"gets the mailbox, a native-push backend (e.g. Antigravity) gets direct injection and has NO mailbox at " +
|
|
311
|
+
"all. THERE IS A THIRD RESULT: the mailbox delivers only to a DELIVERABLE citizen, so a terminated " +
|
|
312
|
+
"session, or a backend with no adapter here (e.g. codex), is mailbox-undeliverable, not queued for an " +
|
|
313
|
+
"inbox nobody drains. The native-push probe is 3-valued: alive → injected; dead → " +
|
|
314
|
+
"native-push-target-dead; indeterminate → native-push-probe-indeterminate (unestablished ≠ gone). " +
|
|
315
|
+
"owned-outcome wakes a DORMANT socket-domain citizen by spawn-bg resume ONLY — live target → " +
|
|
316
|
+
"owned-live-no-autosend, self-fetch → backend-liveness-unsupported, native-push → " +
|
|
317
|
+
"native-push-no-resume-authority. LOCK: taken for a control-socket-DOMAIN dispatch — the live send AND " +
|
|
318
|
+
"the dormant cell's spawn-bg resume, a separate transport that still runs under that domain's lock. The " +
|
|
319
|
+
"mailbox and native-push rails are lock-free — deliverability and the adapter probe guard them. mode " +
|
|
320
|
+
"applies to a CONTROL-SOCKET send only; other plans carry no mode. wants_reply rides every rail. message " +
|
|
321
|
+
"caps at 16000 chars; send an artifact path + digest for more.", {
|
|
349
322
|
target: z.string().min(1).describe("Target garden id (use entwurf_peers to discover)"),
|
|
350
323
|
intent: z
|
|
351
324
|
.enum(["fire-and-forget", "owned-outcome"])
|