@junghanacs/entwurf 0.15.1 → 0.16.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.
Files changed (91) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +354 -0
  3. package/DELIVERY.md +3 -2
  4. package/README.md +68 -88
  5. package/VERIFY.md +4 -1
  6. package/demo/README.md +1 -1
  7. package/docs/acp-backend-rail.md +1 -1
  8. package/docs/external-mcp-host.md +147 -9
  9. package/docs/setup-clean-host.md +125 -6
  10. package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +65 -20
  11. package/mcp/entwurf-bridge/dist/pi-extensions/entwurf-capabilities.json +1 -0
  12. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/backend-adapter.js +19 -10
  13. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-self-address.js +17 -6
  14. package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-sender-identity.js +1 -1
  15. package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-session.js +172 -5
  16. package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +152 -17
  17. package/mcp/entwurf-bridge/dist/pi-extensions/lib/omp-fresh-preflight.js +271 -0
  18. package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-omp.js +988 -0
  19. package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-receive-omp.js +574 -0
  20. package/mcp/entwurf-bridge/dist/scripts/omp-receive-facts.js +84 -0
  21. package/mcp/entwurf-bridge/src/index.ts +65 -19
  22. package/mcp/entwurf-bridge/tsconfig.build.json +19 -3
  23. package/mcp/tsconfig.json +10 -0
  24. package/package.json +19 -9
  25. package/pi/entwurf-capabilities.json +1 -0
  26. package/pi/meta-bridge-omp/entwurf-meta-omp/package.json +7 -0
  27. package/pi/omp-receive/entwurf-receive-omp/package.json +7 -0
  28. package/pi-extensions/entwurf-control.ts +12 -9
  29. package/pi-extensions/lib/acp/backend-adapter.ts +19 -9
  30. package/pi-extensions/lib/acp/backend.ts +125 -7
  31. package/pi-extensions/lib/acp/claude-acp-launch.js +100 -0
  32. package/pi-extensions/lib/entwurf-self-address.ts +18 -7
  33. package/pi-extensions/lib/meta-sender-identity.ts +1 -1
  34. package/pi-extensions/lib/meta-session.ts +219 -5
  35. package/pi-extensions/lib/mux-fresh-call.ts +171 -17
  36. package/pi-extensions/lib/omp-fresh-preflight.ts +275 -0
  37. package/pi-extensions/meta-bridge-omp.ts +1244 -0
  38. package/pi-extensions/meta-bridge-receive-omp.ts +666 -0
  39. package/run.sh +399 -31
  40. package/scripts/check-acp-launch-namespace.ts +127 -0
  41. package/scripts/check-acp-prompt-lifecycle.ts +145 -2
  42. package/scripts/check-copilot-birth-hook.ts +28 -1
  43. package/scripts/check-entwurf-self-address.ts +31 -0
  44. package/scripts/check-gate-qualification.ts +7 -3
  45. package/scripts/check-harness-admission-parity.ts +143 -0
  46. package/scripts/check-meta-doctor-oracle.sh +20 -0
  47. package/scripts/check-omp-birth-hook.ts +1049 -0
  48. package/scripts/check-omp-fresh-preflight.ts +208 -0
  49. package/scripts/check-omp-receive-arm.ts +516 -0
  50. package/scripts/check-setup-qualification.sh +40 -2
  51. package/scripts/copilot-bridge-oracle.sh +14 -6
  52. package/scripts/fake-copilot-vendor.sh +4 -2
  53. package/scripts/inventory-verification-surface.ts +1 -1
  54. package/scripts/meta-bridge-hook-log.sh +9 -1
  55. package/scripts/mutants/acp-launch-namespace.json +34 -0
  56. package/scripts/mutants/acp-prompt-lifecycle.json +67 -2
  57. package/scripts/mutants/copilot-birth.json +10 -10
  58. package/scripts/mutants/mux-fresh-call.json +22 -22
  59. package/scripts/mutants/omp-birth.json +173 -0
  60. package/scripts/mutants/omp-fresh.json +300 -0
  61. package/scripts/mutants/omp-receive.json +135 -0
  62. package/scripts/mutants/pack-install.json +2 -2
  63. package/scripts/mutants/self-address.json +34 -0
  64. package/scripts/mutants/setup-verdict.json +35 -0
  65. package/scripts/omp-bridge-doctor.sh +315 -0
  66. package/scripts/omp-bridge-install.sh +221 -0
  67. package/scripts/omp-bridge-oracle.sh +154 -0
  68. package/scripts/omp-bridge-uninstall.sh +57 -0
  69. package/scripts/omp-config-xdev.py +310 -0
  70. package/scripts/omp-config-xdev.sh +76 -0
  71. package/scripts/omp-mcp-bridge.sh +320 -0
  72. package/scripts/omp-mcp-config.py +392 -0
  73. package/scripts/omp-receive-doctor.sh +246 -0
  74. package/scripts/omp-receive-facts.ts +106 -0
  75. package/scripts/omp-receive-install.sh +228 -0
  76. package/scripts/omp-receive-uninstall.sh +60 -0
  77. package/scripts/omp-tool-surface.py +400 -0
  78. package/scripts/raw-acp-child-exit-measure/README.md +285 -0
  79. package/scripts/raw-acp-child-exit-measure/acp-turn-population.py +89 -0
  80. package/scripts/raw-acp-child-exit-measure/reaper-correlation.py +47 -0
  81. package/scripts/raw-omp-measure/README.md +420 -0
  82. package/scripts/raw-omp-measure/probe-extension.ts +76 -0
  83. package/scripts/raw-omp-measure/probe-receive-surface.ts +250 -0
  84. package/scripts/raw-omp-measure/source-audit.md +414 -0
  85. package/scripts/smoke-omp-bridge-state.sh +221 -0
  86. package/scripts/smoke-omp-fresh-live.ts +497 -0
  87. package/scripts/smoke-omp-mcp-state.sh +327 -0
  88. package/scripts/smoke-omp-receive-live.ts +340 -0
  89. package/scripts/smoke-omp-receive-state.sh +196 -0
  90. package/scripts/smoke-setup-verdict.sh +48 -3
  91. 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 and GitHub Copilot CLI are shipped as mailbox-backed self-fetch meta-sessions; Antigravity (`agy`) is shipped as a native-push citizen with automatic `PreInvocation` birth, ambient garden-id status, and a managed MCP/permission install surface. Codex has a launch-mode-specific verified delivery probe documented in [DELIVERY.md](./DELIVERY.md), but no managed native-citizen install lane yet. The ACP plugin ships two backends through one adapter rail: Claude (the reference) and Snowflake Cortex Code (landed in 0.13.0 under the measured contract in [docs/acp-backend-rail.md](./docs/acp-backend-rail.md#cortex-code-audit-d1d10)).
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 / Copilot / 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
@@ -59,10 +59,11 @@ native Antigravity / agy
59
59
  ↔ entwurf_v2 native-push
60
60
  ```
61
61
 
62
- Claude's `install-meta-bridge`, Copilot's four `install-copilot-*` surfaces, and agy's
63
- `install-agy-{bridge,statusline,hooks}` are distinct because their lifecycle and delivery
64
- transports are genuinely different. Codex remains verified probe evidence, not a shipped managed
65
- native-citizen lane; see [DELIVERY.md](./DELIVERY.md).
62
+ Claude's `install-meta-bridge`, Copilot's four `install-copilot-*` surfaces, agy's
63
+ `install-agy-{bridge,statusline,hooks}` and OMP's four `install-omp-{bridge,mcp,config,receive}`
64
+ units 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).
66
67
 
67
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.
68
69
 
@@ -71,17 +72,20 @@ native-citizen lane; see [DELIVERY.md](./DELIVERY.md).
71
72
  A few words that look unusual for a coding tool.
72
73
 
73
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.
74
- - **Garden / garden id** — the garden is the shared address space where independent harness sessions become citizens without losing their own runtime or transcript. A garden id is the stable address of one such citizen (for pi, a garden-native session id like `YYYYMMDDTHHMMSS-<6hex>`; for native harnesses, a meta-session id minted from an authoritative lifecycle hook — Claude `SessionStart`, Copilot's first-prompt birth hook, agy `PreInvocation`). It is not a worker name and not proof that pi owns the session. The same-looking id may name a live control socket, a dormant pi record, a mailbox-backed native session, or a native-push conversation, so callers discover facts with `entwurf_peers` and deliver with `entwurf_v2` instead of choosing a transport by hand.
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.
75
76
  - **Engraving** — optional short operator text delivered through each backend's native identity carrier. Not a giant hidden prompt, not a tool catalog.
76
- - **MCP** — in this repo, MCP is just the transport by which ACP-backed sessions receive pi capabilities that native pi exposes directly as extensions. It is not a general MCP platform. Explicit `entwurfProvider.mcpServers` only; no ambient `~/.mcp.json` scanning, no automatic retrieval. The same `entwurf-bridge` entry can also be wired into another host's MCP catalog (Claude Code, Copilot, Codex, Antigravity, …) when the operator chooses. `entwurf_self` returns an authoritative pi-session or trusted meta-session identity envelope; `entwurf_v2` requires an authoritative sender by default (#50 C4) — a plain external MCP host with no identity lane is refused unless the operator explicitly wires the documented anonymous hatch, and even then it is never replyable.
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.
77
78
  - **Session persistence** — re-attaches pi to the same remote ACP session. Does not hydrate backend transcripts into pi history.
78
79
 
79
80
  ## Install
80
81
 
81
- `entwurf` is a neutral npm package first. Install the package with `npm` (or
82
- `pnpm`/`yarn`) and then wire the harness you want to use. Pi is still the
83
- adapter that hosts the ACP plugin and live control-socket surface, but the base
84
- install is **not** `pi install npm:...` anymore.
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.
85
89
 
86
90
  The package exposes six bins:
87
91
 
@@ -95,7 +99,7 @@ The package exposes six bins:
95
99
  The bridge/renderers/hook use stable bin names so package upgrades do not bake versioned package-store paths into native-harness settings.
96
100
 
97
101
  Installing Entwurf installs **Entwurf only**: its package bytes, six bins, bridge, and
98
- integration artifacts. It does not install `pi`, Claude Code, Copilot CLI, Codex, agy, Cortex,
102
+ integration artifacts. It does not install `pi`, Claude Code, Copilot CLI, Codex, agy, omp, Cortex,
99
103
  or any other harness runtime. Those are operator choices and may all be absent. The bridge also
100
104
  does not provide credentials, tokens, subscription access, or an auth bypass; whatever an
101
105
  operator-installed harness already trusts is what Entwurf can use. `setup` is composition, not
@@ -107,15 +111,12 @@ look complete.
107
111
  ```bash
108
112
  npm install -g @junghanacs/entwurf
109
113
 
110
- # wire a target project for the pi adapter / ACP plugin lane
111
- cd /path/to/your-project
112
- entwurf install .
114
+ entwurf setup /path/to/your-project
113
115
  entwurf check-bridge
114
116
  ```
115
117
 
116
- This writes `.pi/settings.json` in the target project with the absolute path to
117
- the installed `entwurf-bridge` launcher. (The old `~/.pi/agent/` target-registry
118
- 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
119
120
  Claude Code's USER-scope MCP registration should work from every cwd.
120
121
 
121
122
  ### From npm — project-local install
@@ -124,27 +125,25 @@ Claude Code's USER-scope MCP registration should work from every cwd.
124
125
  cd /path/to/your-project
125
126
  npm install --save-dev @junghanacs/entwurf
126
127
 
127
- npx entwurf install .
128
+ npx entwurf setup .
128
129
  npx entwurf check-bridge
129
130
  ```
130
131
 
131
- For an npm upgrade, rerun the install command in the same scope (use
132
+ For an npm upgrade, rerun `setup` in the same scope (use
132
133
  `@junghanacs/entwurf@latest` when you want the registry's stable line explicitly),
133
134
  then make the first check from that same scope: `entwurf check-bridge` for a global
134
135
  install or `npx entwurf check-bridge` for a project-local install. Native-harness
135
- installers and process restarts remain a separate post-upgrade step below.
136
-
137
- For manual MCP registration from a project-local install, point the host at:
138
-
139
- ```text
140
- /path/to/your-project/node_modules/.bin/entwurf-bridge
141
- ```
136
+ repair and process restarts remain a separate post-upgrade step below.
142
137
 
143
- or at the package launcher directly:
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.)
144
143
 
145
- ```text
146
- /path/to/your-project/node_modules/@junghanacs/entwurf/mcp/entwurf-bridge/start.sh
147
- ```
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).
148
147
 
149
148
  ### From source — development clone
150
149
 
@@ -158,35 +157,25 @@ cd ~/repos/gh/entwurf
158
157
 
159
158
  The full source setup requires Node 24, pnpm, and Python 3 on PATH. Harnesses are
160
159
  optional-by-presence: `setup` runs the frozen dependency install, then composes what the operator
161
- already installed — a compatible `pi` (`>=0.84.3 <0.85`), Claude Code, agy, and the Copilot CLI
160
+ already installed — a compatible `pi` (`>=0.84.4 <0.85`), Claude Code, agy, and the Copilot CLI
162
161
  each get their wiring completed when detected, an absent harness is an explicit zero-state SKIP,
163
162
  and a detected harness that cannot be completed (including a below-floor `pi`) is a named FAIL
164
163
  that makes setup exit nonzero. `setup` never installs a harness binary or touches a credential
165
164
  store. It also exposes stable commands under `~/.local/bin`, including `entwurf` → this
166
165
  checkout's `run.sh`, so managed Copilot fresh does not depend on an unrelated global npm/pnpm
167
- installation. A detected `copilot` composes all four native units (birth → MCP → receiver →
168
- visible footer) independently; the explicit `install-copilot-*` surfaces below remain the
169
- per-unit repair and inverse path. Package consumers
166
+ installation. A detected `copilot` composes all four of its native units (birth → MCP →
167
+ receiver → visible footer) in one go. Package consumers
170
168
  run the same `entwurf setup <project>` through their npm-provided bin: installed mode is decided
171
169
  by name first, skips the source-only pnpm bootstrap entirely, and reports the stable commands as
172
- already provided by npm bin linking; `entwurf install` remains the narrower pi-wiring repair
173
- leaf.
170
+ already provided by npm bin linking.
174
171
 
175
172
  The pi user-scope registration is ONE shared entry with a recorded owner (#86 C2): installing
176
173
  from a second checkout or npm root does not silently steal it — normal `install`/`setup` refuse
177
- (zero settings writes, live or missing owner alike), `entwurf takeover-user-scope` is the
178
- operator-explicit move (old→new reported), `entwurf doctor-pi-package` names the ownership
179
- verdict (including `missing-owner` for a moved/deleted root), and `entwurf remove-user-scope`
180
- is same-owner-only with a reported orphan cleanup when entry, package state and provider
181
- installerRoot all name the same missing root. User-scope operations are atomic across the
182
- package and provider halves (read-only preflights first — a refusal on one side writes nothing
183
- on the other); a takeover over an operator's provider override reports a split verdict (package
184
- moved, override preserved unowned) and a legacy unattributed provider state must be adopted by
185
- a same-root `setup`/`install` before it can be removed. Both halves' install-states also record
186
- exactly WHICH settings file they manage (`managedSettingsPath`): an operation targeting a
187
- different, symlinked or unparseable file is a zero-write refusal before either half goes green,
188
- and the owned/orphan inverse removes only the recorded owner's exact `packages[]` entry —
189
- 0 or 2+ exact entries refuse, so an npm spec or another `.../entwurf` path is never collateral.
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).
190
179
 
191
180
  A development clone runs the bridge source through Node's strip-types path;
192
181
  an npm-installed package runs the prebuilt JS under `mcp/entwurf-bridge/dist/`
@@ -199,7 +188,7 @@ gitignored and may be absent or stale immediately after a checkout or pull.
199
188
  ### Pi adapter / ACP plugin lane
200
189
 
201
190
  To use the `entwurf` provider inside pi, install a compatible pi binary
202
- separately (`@earendil-works/pi-coding-agent >=0.84.3 <0.85`). Then point pi at
191
+ separately (`@earendil-works/pi-coding-agent >=0.84.4 <0.85`). Then point pi at
203
192
  the npm-installed package or development clone:
204
193
 
205
194
  ```bash
@@ -214,41 +203,27 @@ For daily operator sessions, launch pi with `--entwurf-control` — no id
214
203
  injection; the meta-record mints the garden address (see [Garden launcher](#garden-launcher)). Older pi
215
204
  versions may silently miss the provider/extension surface, so treat the pi floor
216
205
  as release-critical for the ACP/plugin lane. A host that only uses
217
- `entwurf-bridge` from Claude Code / Copilot / Codex / Antigravity does not need pi at all for
218
- delivery: no `entwurf_v2` rail launches a pi process. That external-only shape works with the same
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
219
209
  `setup` command: pi is optional-by-presence there, so a pi-less host simply gets an explicit pi
220
210
  SKIP while the detected harnesses are composed.
221
211
 
222
- ### Native harness install and doctors
212
+ ### Native harness repair and doctors
223
213
 
224
214
  A plain MCP registration exposes the bridge tools; a **garden-native** session also
225
- needs entwurf's lifecycle hook and identity marker. Use the managed installers rather
226
- than editing native-harness state by hand:
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. This is the repair
217
+ surface: each unit has its own installer, its own doctor with a named refusal, and its own
218
+ inverse, so a single broken unit can be redone without touching the rest.
227
219
 
228
- ```bash
229
- # Claude Code (Linux-certified axis)
230
- entwurf install-meta-bridge
231
- entwurf doctor-meta-bridge
232
-
233
- # Antigravity / agy
234
- entwurf install-agy-bridge
235
- entwurf install-agy-statusline
236
- entwurf install-agy-hooks
237
- entwurf doctor-agy-bridge
238
- entwurf doctor-agy-statusline
239
- entwurf doctor-agy-hooks
240
-
241
- # GitHub Copilot CLI — four independent surfaces, four independent failure modes
242
- # (`setup` composes all four when `copilot` is on PATH; these remain the per-unit repair/inverse surfaces)
243
- entwurf install-copilot-bridge # birth: garden id + who-sent, on the first prompt (owns an install-state; inverse: uninstall-copilot-bridge)
244
- entwurf install-copilot-mcp # the entwurf tool hand (entwurf_inbox_read lives here)
245
- entwurf install-copilot-receive # the receiver extension: doorbell + receiver marker
246
- entwurf install-copilot-statusline # optional for a manual citizen; required for supported fresh
247
- entwurf doctor-copilot-bridge
248
- entwurf doctor-copilot-mcp
249
- entwurf doctor-copilot-receive
250
- entwurf doctor-copilot-statusline
251
- ```
220
+ - **Claude Code** (Linux-certified axis) — `install-meta-bridge`, `doctor-meta-bridge`.
221
+ - **Antigravity / agy** — `install-agy-bridge`, `install-agy-statusline`, `install-agy-hooks`, each with a matching `doctor-agy-*`.
222
+ - **GitHub Copilot CLI** — four independent units, four independent failure modes: `install-copilot-bridge` (birth: garden id + who-sent, on the first prompt), `install-copilot-mcp` (the entwurf tool hand, where `entwurf_inbox_read` lives), `install-copilot-receive` (the receiver extension: doorbell + receiver marker), `install-copilot-statusline` (optional for a manual citizen, required for supported fresh) — each with a matching `doctor-copilot-*` and `uninstall-copilot-*`.
223
+ - **OMP (`omp`)** — four units, in-process extensions rather than launchers: `install-omp-bridge` (birth: the `mode === "tui"` visible host, its garden id on the status line, and who-sent), `install-omp-mcp` (the omp-native `entwurf-bridge` entry), `install-omp-config` (the one operator setting `tools: xdev: false`, without which the vendor mounts MCP tools as `xd://` devices the model cannot call), `install-omp-receive` (the receiver extension: mailbox watch + announce-only doorbell) — each with a matching `uninstall-omp-*`, and a `doctor-omp-*` for all but the setting, whose runtime axis `doctor-omp-mcp` owns. The setting writer owns exactly the lines it adds and refuses an explicit operator `tools: xdev: true` by name rather than overwriting it.
224
+
225
+ Run them as `entwurf <command>`. Which unit a doctor's refusal names, and the clean-host
226
+ walk-through for each harness, live in [docs/setup-clean-host.md](./docs/setup-clean-host.md).
252
227
 
253
228
  #### Launching Copilot as a garden citizen — `entwurf copilot`
254
229
 
@@ -294,8 +269,10 @@ the default permission prompts — which an idle, unattended session is not ther
294
269
 
295
270
  Claude Code uses the supported floor `>=2.1.217`; older versions silently discard the
296
271
  exec-hook `args`, so install and doctor fail loud rather than falling back. After any
297
- upgrade, rerun every owned installer for the native harness you use (all four for Copilot) and
298
- restart its existing processes. A claimed Claude host is certified only when a **new** session using the
272
+ upgrade, rerun `entwurf setup <project>` it re-composes every detected harness, all four
273
+ Copilot units included and restart its existing processes; reach for a single
274
+ `install-*` only when one unit needs repair on its own. A claimed Claude host is certified
275
+ only when a **new** session using the
299
276
  installed artifact makes `doctor-meta-bridge` exit 0 with the live owner join.
300
277
 
301
278
  Linux is the only currently certified Claude meta-bridge axis. New macOS wiring is
@@ -409,7 +386,7 @@ Reference shape lives in [`pi/settings.reference.json`](./pi/settings.reference.
409
386
  ### External MCP registration
410
387
 
411
388
  `entwurf-bridge` can also be registered in a separate MCP-aware harness (Claude Code,
412
- Copilot CLI, Codex CLI, Antigravity). Two shapes exist and they are not interchangeable:
389
+ Copilot CLI, Codex CLI, Antigravity, OMP). Two shapes exist and they are not interchangeable:
413
390
 
414
391
  - **plain external MCP host** — no garden meta-record or sender marker. It can read the
415
392
  surfaces, but `entwurf_v2` is **refused by default**: there is no authoritative sender.
@@ -421,7 +398,10 @@ claude mcp add --scope user entwurf-bridge entwurf-bridge
421
398
  ```
422
399
 
423
400
  Per-harness registration (Claude Code `~/.mcp.json`, Codex `~/.codex/config.toml`, the
424
- managed `install-agy-*` surfaces), the PATH/env boundary for GUI-launched MCP servers, the
401
+ managed `install-agy-*` surfaces, and OMP's managed `install-omp-mcp` into `<omp agent dir>/mcp.json`
402
+ — whose pinned server key is what shadows a borrowed Claude import, see
403
+ [docs/external-mcp-host.md](./docs/external-mcp-host.md) §OMP), the PATH/env boundary for
404
+ GUI-launched MCP servers, the
425
405
  anonymous-sender hatch, and the full external/meta-session semantics are in
426
406
  [docs/external-mcp-host.md](./docs/external-mcp-host.md).
427
407
  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.
@@ -527,7 +507,7 @@ A two-pane recording covers the pre-0.12 v1 surface end-to-end — sibling resum
527
507
 
528
508
  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.)
529
509
 
530
- In ACP-backed and external native-harness sessions, `entwurf-bridge` exposes seven tools: `entwurf_v2`, `entwurf_peers`, `entwurf_fresh_call`, `entwurf_resume_call`, `entwurf_self`, `entwurf_inbox_read`, and the explicit/manual `entwurf_register_native` fallback. Native pi exposes the shared capability directly through the extension surface (`entwurf_v2`, `entwurf_peers`, `entwurf_fresh_call`, `entwurf_resume_call` tools; the socket-scan `/entwurf-sessions` command is gone — #50 C4). **For garden-id delivery/reply use `entwurf_v2`** — the canonical surface that classifies the target and routes to live-pi / Claude-or-Copilot-meta-mailbox / Antigravity-native-push, and refuses a dormant target instead of waking it. **To open a sibling that does not exist yet use `entwurf_fresh_call`** — it launches one fixed backend (`pi`, `claude-code`, or `copilot`) as a visible window in the operator's own tmux session, requires an explicit model, accepts one optional literal absolute `cwd` (omit it or pass `""` to use the caller's cwd), passes the model and selected directory through the runtime's visible launch path, and hands it a first task; a `copilot` launch goes through entwurf's own managed invocation and is refused before any window opens if this host lacks the Copilot birth, MCP, receiver or visible-footer units. The sibling's first action is a nonce callback whose sender envelope carries its garden id. The launch receipt records the requested model/cwd plus tmux coordinates and never claims that the runtime accepted them or completed delivery. (The v1 verbs `entwurf` / `entwurf_resume` / `entwurf_send` are gone.) Garden-native operator commands require `--entwurf-control`. There is no spawn target allowlist — the target registry is gone (#50 C3): `entwurf_v2` and `entwurf_resume_call` address an existing record-backed citizen, while `entwurf_fresh_call` takes its explicit backend/model/task and optional cwd directly rather than resolving a model tuple from a registry file. **To reopen a DORMANT pi citizen use `entwurf_resume_call {target}`** — the record supplies transcript, model, provider and cwd, so it takes no prompt, no task and no model override; it runs no turn, returns a LAUNCH receipt and a separate OBSERVATION receipt (only the second says the citizen is back), refuses a non-pi target as `target-not-pi`, and on an unobserved socket leaves the visible window open and releases its lock rather than retrying.
510
+ 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.
531
511
 
532
512
  ### `entwurf_v2` — canonical dispatch verb
533
513
 
@@ -544,9 +524,9 @@ In ACP-backed and external native-harness sessions, `entwurf-bridge` exposes sev
544
524
  | dead / indeterminate native-push conversation | fire-and-forget | **reject** (`native-push-target-dead` / `native-push-probe-indeterminate`) |
545
525
  | record-less control socket (no meta-record) | any | **reject** (`record-less-socket` — pre-probe; diagnostic state, #50 C4) |
546
526
 
547
- **`entwurf_v2` is the canonical surface for garden-id delivery.** When you have a garden id and want to reach whoever it names — message, reply, or hand-off — `entwurf_v2` is the one surface that reads whether the target is live pi, dormant pi, mailbox-backed Claude Code or Copilot, or native-push Antigravity and routes correctly; *when unsure which transport, use `entwurf_v2`*. This prevents callers from guessing a rail from the shape of an id.
527
+ **`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.
548
528
 
549
- What v2 provides is a **deterministic dispatch substrate** that moves the "which transport?" decision out of the fallible caller/model and into the decider, with transport-appropriate locking and an honest reject (no `✓ delivered`, no `.msg` garbage) when a target cannot receive. It still does **not** mint siblings, and it does not relaunch one either: every row above either reaches a citizen that is already running or refuses. Reopening a dormant pi citizen is `entwurf_resume_call`, a separate lifecycle verb that never routes through this decider. Fresh creation is the separate `entwurf_fresh_call` verb. It opens one fixed Pi, Claude Code, or Copilot runtime visibly in the caller's tmux session with a required explicit model passed in that runtime's measured CLI dialect and one optional literal absolute `cwd`; omitted or `""` means the caller's cwd. Copilot opens through `entwurf copilot`, never the bare vendor. It returns only a synchronous launch receipt and lets the sibling report its new address asynchronously through the sender envelope of a nonce callback. Use this cwd input for a new cross-repository sibling; do not resume a dormant citizen as a cwd substitute. The meta-mailbox row requires an **active** self-fetch receiver; native-push requires a record-backed, probe-alive native conversation and never borrows mailbox state. The [mux launch lane](./docs/mux-launch-rail.md) owns placement, fixed-runtime launch, and the two narrow compositions above it (fresh-call and resume-call placement); delivery does not import launch, and mux is not a delivery transport.
529
+ 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.
550
530
 
551
531
  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.
552
532
 
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`), and `smoke-entwurf-chain-live` — the cross-harness delivery chain (native Claude Code → pi GPT → pi ACP Sonnet → mailbox terminus) proving sender identity and replyability at every hop plus a real read receipt at the end. (`smoke-session-id-name` is gone — #50 C3: its `--session-id`/`--name` substrate has no entwurf consumer anymore.)
46
+ - **MUST tier** (release-blocking — owns the exit code; "green" applies only here): `pnpm run check:full`, `check-gate-qualification`, `smoke-entwurf-v2-matrix-live`, `check-bridge`, `doctor-pi-provider` (#81 — `check-bridge` proves the launcher this checkout SHIPS; this proves the invocation the operator's pi provider actually EXECS, by booting it and requiring the entwurf verb set back, because `command -v` answers yes for a command that exits 127; wired as a step on 2026-08-19 after a relocated pnpm cmd-shim cost a cut sixteen LIVE steps before the same fact surfaced at `smoke-acp-bundled-mcp-live`), the resident-garden-guard zero-token half (record birth / record-keyed socket / attach-on-reopen), the `smoke-acp-*-live` ACP plugin smokes (socket-citizen / raw-turn / overlay / provider / session-reuse / carrier-augment / memory-containment / rgg / mcp / skill / bundled-mcp / v2-send), the axis wired in on 2026-07-31 that the aggregate had simply never listed (`smoke-claude-native-resume-live`), `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
  >
@@ -285,6 +287,7 @@ The minimum passing bar:
285
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.
286
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.
287
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.
288
291
 
289
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).
290
293
 
package/demo/README.md CHANGED
@@ -139,7 +139,7 @@ SCENE_DELAY=30 FINAL_PAUSE=10 bash demo.sh
139
139
 
140
140
  ## Prerequisites
141
141
 
142
- - `pi` on PATH (current floor 0.84.3)
142
+ - `pi` on PATH (current floor 0.84.4)
143
143
  - `entwurf` provider configured + auth ready for the selected sender/peer models
144
144
  - `asciinema` installed
145
145
  - `agg` installed (optional — only for GIF conversion)
@@ -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.15.0` | shipped baseline | the package contract these rows belong to |
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 |
@@ -1,25 +1,25 @@
1
1
  # Wiring `entwurf-bridge` into an external MCP host
2
2
 
3
- Per-harness registration for Claude Code, Codex CLI, and Antigravity, plus the
4
- PATH/env boundary and the external vs garden-native semantics. `README.md` keeps only
3
+ Per-harness registration for Claude Code, Codex CLI, Antigravity, GitHub Copilot CLI and OMP,
4
+ plus the PATH/env boundary and the external vs garden-native semantics. `README.md` keeps only
5
5
  the one-line registration; everything an operator needs to actually wire a host is here.
6
6
 
7
- `entwurf-bridge` can also be registered in a separate MCP-aware harness (Claude Code, Codex CLI, Antigravity/`agy`, …). That host does **not** become a pi session and does **not** need to be ACP-backed. There are now two honest cases:
7
+ `entwurf-bridge` can also be registered in a separate MCP-aware harness (Claude Code, Codex CLI, Antigravity/`agy`, GitHub Copilot CLI, OMP, …). That host does **not** become a pi session and does **not** need to be ACP-backed. There are now two honest cases:
8
8
 
9
9
  - **plain external MCP host**: no garden meta-record / sender marker. It can call the read surfaces (`entwurf_peers`, `entwurf_inbox_read`), but `entwurf_v2` sends are **refused by default** (#50 C4: "if we don't know who sent it, we don't send it"). The operator may wire the explicit hatch below; the send then goes out external/non-replyable.
10
- - **garden-native native session**: a trusted lifecycle hook minted a garden id and sender marker — `SessionStart` for Claude Code, `PreInvocation` for agy, `userPromptSubmitted`/`sessionStart` for GitHub Copilot CLI. It is not a pi control-socket session, but it can be replyable by garden id when its own mailbox/probe rail says so.
10
+ - **garden-native native session**: a trusted lifecycle hook minted a garden id and sender marker — `SessionStart` for Claude Code, `PreInvocation` for agy, `userPromptSubmitted`/`sessionStart` for GitHub Copilot CLI, and for OMP an in-process extension on `session_start`/`session_switch` that mints only a `mode === "tui"` host. It is not a pi control-socket session, but it can be replyable by garden id when its own mailbox/probe rail says so.
11
11
 
12
12
  **Being garden-native is not the same as being replyable, and Copilot is the case that separates them.** Its hook writes a sender marker, so an `entwurf_v2` send carries its own garden id and the receiver learns who wrote — measured 2026-08-21 on Copilot CLI 1.0.80, where a live send arrived under its own garden id with `origin: "meta-session"` and `replyable: false`. Replyability arrived later and through a different process: a first-party extension (`run.sh install-copilot-receive`) that the CLI forks, which binds to the same V3 record and writes a receiver marker owned by its own pid (#82 RAIL 5). So a Copilot citizen is `replyable: true` exactly while that extension is armed for it, and `replyable: false` — honestly, with a real garden identity — when it is not installed, not launched with `COPILOT_CLI_ENABLED_FEATURE_FLAGS=EXTENSIONS` (which is what `entwurf copilot` sets for one invocation), not yet born, or gone. Read the two facts off different rails: the sender marker answers *who sent this*; the receiver marker answers *can a reply land*. The onboarding obligations are in [`adding-a-harness.md`](./adding-a-harness.md) step 7, and the evidence boundary — the managed LIVE acceptance that moved receive to D6, and what D7-partial / D3-pending still exclude — is in [`DELIVERY.md`](../DELIVERY.md).
13
13
 
14
- **Which verb an external agent should reach for:** to deliver to / reply to a garden id, use **`entwurf_v2`** — it is the canonical delivery surface and the only one that reads whether the target is live pi, dormant pi, mailbox-backed Claude Code, or native-push Antigravity and routes correctly. Discover targets with `entwurf_peers`, confirm your own identity with `entwurf_self`, drain a mailbox with `entwurf_inbox_read`, and use `entwurf_register_native` only as the explicit/manual fallback for binding an already-running agy conversation (normal agy birth is automatic through the installed hook). Open a NEW sibling with **`entwurf_fresh_call {backend, model, task, cwd?}`**, and reopen a DORMANT pi citizen under its own garden id with **`entwurf_resume_call {target}`**. Fresh call accepts one optional literal absolute `cwd`: omit it or pass `""` for the caller's cwd; otherwise it must name an existing directory and may not contain `#`. Use that input for a new cross-repository sibling — resume preserves a dormant Pi citizen's recorded continuity and is not a cwd substitute. Fresh call needs its selected runtime on the server's PATH (`pi`, `claude`, or `entwurf` — Copilot opens through the managed `entwurf copilot` invocation, never the bare vendor); resume call always needs `pi`. Both start a runtime, while delivery does not. (The old v1 verbs `entwurf` / `entwurf_resume` / `entwurf_send` are gone.)
14
+ **Which verb an external agent should reach for:** to deliver to / reply to a garden id, use **`entwurf_v2`** — it is the canonical delivery surface and the only one that reads whether the target is live pi, dormant pi, a mailbox-backed self-fetch citizen (Claude Code, Copilot, OMP), or native-push Antigravity and routes correctly. Discover targets with `entwurf_peers`, confirm your own identity with `entwurf_self`, drain a mailbox with `entwurf_inbox_read`, and use `entwurf_register_native` only as the explicit/manual fallback for binding an already-running agy conversation (normal agy birth is automatic through the installed hook). Open a NEW sibling with **`entwurf_fresh_call {backend, model, task, cwd?}`**, and reopen a DORMANT pi citizen under its own garden id with **`entwurf_resume_call {target}`**. Fresh call accepts one optional literal absolute `cwd`: omit it or pass `""` for the caller's cwd; otherwise it must name an existing directory and may not contain `#`. Use that input for a new cross-repository sibling — resume preserves a dormant Pi citizen's recorded continuity and is not a cwd substitute. Fresh call needs its selected runtime on the server's PATH (`pi`, `claude`, `entwurf` or `omp` — Copilot opens through the managed `entwurf copilot` invocation, never the bare vendor, while OMP is opened as the bare `omp` runtime); resume call always needs `pi`. Both start a runtime, while delivery does not. (The old v1 verbs `entwurf` / `entwurf_resume` / `entwurf_send` are gone.)
15
15
 
16
- Observed: Claude Code, Codex CLI, Antigravity CLI and GitHub Copilot CLI all reach the read surfaces through this MCP bridge from a plain external host — `entwurf_peers` is a pure fact projection, while `entwurf_inbox_read` is a **mutating drain** (it archives the messages and stamps the read-receipt), so "read" here does not mean side-effect-free; **sending** needs an identity lane. Claude and Copilot become symmetric/replyable through a mailbox-backed meta-session — Claude's watch armed by its own hook, Copilot's by the forked extension it installs; agy becomes symmetric/replyable through its record-backed sender marker plus live native-push probe. Codex has no managed citizen lifecycle yet, so a Codex host cannot send without the explicit anonymous hatch below.
16
+ Observed: Claude Code, Codex CLI, Antigravity CLI, GitHub Copilot CLI and OMP all reach the read surfaces through this MCP bridge from a plain external host — `entwurf_peers` is a pure fact projection, while `entwurf_inbox_read` is a **mutating drain** (it archives the messages and stamps the read-receipt), so "read" here does not mean side-effect-free; **sending** needs an identity lane. Claude, Copilot and OMP become symmetric/replyable through a mailbox-backed meta-session — Claude's watch armed by its own hook, Copilot's by the forked extension it installs, OMP's by an extension running inside the operator's own TUI process; agy becomes symmetric/replyable through its record-backed sender marker plus live native-push probe. Codex has no managed citizen lifecycle yet, so a Codex host cannot send without the explicit anonymous hatch below.
17
17
 
18
18
  Prerequisites on the host running the external MCP client:
19
19
 
20
20
  - A live pi session launched with `--entwurf-control` populates `~/.pi/entwurf-control/<gardenId>.sock` — the key is the **record's** garden id, never a transcript/session id (`PI_SESSION_ID` only carries the id record birth already established). Required for `entwurf_v2` control-socket dispatch and `entwurf_peers`.
21
21
 
22
- > **PATH boundary.** MCP servers are often launched by GUI/editor daemons and may not inherit the interactive shell's PATH. No `entwurf_v2` rail launches a process, so this does not affect delivery — but `entwurf_fresh_call` and `entwurf_resume_call` do open a fixed runtime. If that runtime works in your terminal but an external-host call fails with `spawn pi ENOENT`, `spawn claude ENOENT`, or `spawn entwurf ENOENT`, pass a full PATH in the MCP server `env`, set `ENTWURF_BRIDGE_ENV_FILE` to a small shell file that exports PATH, or point the host at a wrapper that can find the runtime. `start.sh` sources only the explicit `ENTWURF_BRIDGE_ENV_FILE`; it never reads personal dotfiles automatically.
22
+ > **PATH boundary.** MCP servers are often launched by GUI/editor daemons and may not inherit the interactive shell's PATH. No `entwurf_v2` rail launches a process, so this does not affect delivery — but `entwurf_fresh_call` and `entwurf_resume_call` do open a fixed runtime. If that runtime works in your terminal but an external-host call fails with `spawn pi ENOENT`, `spawn claude ENOENT`, `spawn entwurf ENOENT`, or `spawn omp ENOENT`, pass a full PATH in the MCP server `env`, set `ENTWURF_BRIDGE_ENV_FILE` to a small shell file that exports PATH, or point the host at a wrapper that can find the runtime. `start.sh` sources only the explicit `ENTWURF_BRIDGE_ENV_FILE`; it never reads personal dotfiles automatically.
23
23
 
24
24
  > **Identity-carrier boundary.** A complete `PI_SESSION_ID` + `PI_AGENT_ID` pair wins before a
25
25
  > native sender marker in the bridge's authoritative-self resolution. Those variables are correct
@@ -40,6 +40,22 @@ Prerequisites on the host running the external MCP client:
40
40
  > and still speak under the parent's garden id, so the flag verdict must not absorb it. The other
41
41
  > native launchers have NOT been certified against this failure mode; do not read Copilot's cells
42
42
  > as coverage for them.
43
+ >
44
+ > **OMP has both halves, and the strip one is not an omp launcher** (#87 Bundle C). entwurf still
45
+ > owns no managed omp invocation — the bare vendor runtime IS this harness's clause 1 answer, and
46
+ > nothing here argues for a wrapper. The strip sits one level up instead, at the shared launch seam
47
+ > every `entwurf_fresh_call` backend passes through: `SCRUBBED_INHERITED_ENV` empties
48
+ > `PI_SESSION_ID` and `PI_AGENT_ID` on the `new-window` argv itself
49
+ > (`pi-extensions/lib/mux-fresh-call.ts:402`), for all four backends rather than only the one whose
50
+ > measurement surfaced it, because the leak is a property of tmux and not of a vendor. `-e VAR=`
51
+ > sets the variable empty rather than unsetting it — tmux has no per-window unset — and every
52
+ > carrier reader trims and tests truthiness, so empty and absent are the same answer by
53
+ > construction. Pinned by `[QK:FRESHCALL-IDENTITY-SCRUB]` in the `check-mux-fresh-call` vitest lane,
54
+ > inside `check:full`. The DETECT half is unchanged and still load-bearing, because a seam covers
55
+ > only the launches that pass through it: `doctor-omp-bridge` reads `/proc/<pid>/environ` for every
56
+ > live `omp` process and goes RED on its own axis when one carries either carrier. An omp the
57
+ > operator started from a pi citizen's bash never touched the seam and is still unsupported, exactly
58
+ > as this boundary says.
43
59
 
44
60
  Example env file:
45
61
 
@@ -66,7 +82,7 @@ Emergency/manual workaround when the MCP server environment is wrong but an exis
66
82
  External/meta-session semantics:
67
83
 
68
84
  - `entwurf_v2` from a plain external host is **refused by default** (no authoritative sender — #50 C4). With the explicit `ENTWURF_BRIDGE_ALLOW_ANONYMOUS_SENDER=1` hatch it delivers with `origin: "external-mcp"` / `replyable: false`; there is still no reply address.
69
- - `entwurf_v2` from a trusted meta-session delivers with `origin: "meta-session"`, and `replyable` is **derived from that sender's own rail — not granted by being trusted**: a self-fetch sender (Claude Code) is replyable only while its receiver is live and armed, and a native-push sender (Antigravity) only while its adapter probe finds the live conversation. Identity survives either way; only `replyable` drops to `false`. When it is `true`, `wants_reply: true` is allowed and the receiver can reply to the sender's garden id.
85
+ - `entwurf_v2` from a trusted meta-session delivers with `origin: "meta-session"`, and `replyable` is **derived from that sender's own rail — not granted by being trusted**: a self-fetch sender (Claude Code, Copilot, OMP) is replyable only while its receiver is live and armed, and a native-push sender (Antigravity) only while its adapter probe finds the live conversation. Identity survives either way; only `replyable` drops to `false`. When it is `true`, `wants_reply: true` is allowed and the receiver can reply to the sender's garden id.
70
86
  - `entwurf_v2` never launches a process, so no delivery path needs `pi` on PATH. A dormant pi target is refused as `dormant-fire-forget-unsupported`: the hidden background resume that used to answer there was withdrawn under the visible-first rule, and re-opening the session is the separate `entwurf_resume_call` verb — which DOES need `pi` on PATH, because it starts one.
71
87
  - `entwurf_self` returns the same authoritative identity for pi sessions **and** trusted meta-sessions. A plain external host with no pi env and no trusted sender marker still fails because there is no reply address to report.
72
88
 
@@ -143,9 +159,131 @@ Unrelated servers, permissions, settings, and hooks are preserved; every adapter
143
159
 
144
160
  The **global** MCP config live agy reads is `~/.gemini/config/mcp_config.json`. `~/.gemini/antigravity-cli/mcp_config.json` is not the global MCP root; the bridge installer one-way cleans only a stale entwurf-owned entry there. After the first model invocation, the imprint hook binds the native `conversationId` to a garden id, the statusline shows `🪛 <garden-id> agy`, and sends from that MCP child carry `agentId=meta-session/antigravity` with `replyable:true` only when the record exists and the live native-push probe succeeds.
145
161
 
162
+ #### OMP (`omp`, oh-my-pi)
163
+
164
+ Use the managed install surface rather than editing omp's files by hand:
165
+
166
+ ```bash
167
+ entwurf install-omp-bridge # the BIRTH extension (a garden id per visible TUI session)
168
+ entwurf install-omp-mcp # the MCP hand (this section)
169
+ entwurf install-omp-receive # the RECEIVER extension (mailbox watch + announce-only doorbell)
170
+
171
+ entwurf doctor-omp-bridge
172
+ entwurf doctor-omp-mcp
173
+ entwurf doctor-omp-receive
174
+ ```
175
+
176
+ Three units, not two. The receiver is what makes the citizen answerable at all — without it omp
177
+ sends under its own garden id and every reply is refused as `mailbox-undeliverable` — and it is
178
+ also a prerequisite of visible fresh: the fresh preflight refuses this host before touching tmux
179
+ when the receive unit is missing, rather than opening a window that can never be reached.
180
+
181
+ `install-omp-mcp` writes ONE server into omp's own user MCP file,
182
+ `<omp agent dir>/mcp.json` (`~/.omp/agent/mcp.json`, profile-aware), in omp's own writer
183
+ shape — `{command, args?, env?}` with `type` omitted, since stdio is the default:
184
+
185
+ ```json
186
+ {
187
+ "$schema": "https://raw.githubusercontent.com/can1357/oh-my-pi/main/packages/coding-agent/src/config/mcp-schema.json",
188
+ "mcpServers": {
189
+ "entwurf-bridge": {
190
+ "command": "bash",
191
+ "args": ["/absolute/path/to/entwurf/mcp/entwurf-bridge/start.sh"],
192
+ "env": { "ENTWURF_BRIDGE_EXTERNAL_AGENT_ID": "external-mcp/omp" }
193
+ }
194
+ }
195
+ }
196
+ ```
197
+
198
+ **The server key is a pinned literal, and that is the whole point.** omp translates Claude
199
+ Code's `~/.claude.json` as an import provider, so a host that ever used Claude Code already
200
+ has an `entwurf-bridge` — carrying `external-mcp/claude-code`. An omp session riding that
201
+ import introduces itself to the bridge under Claude Code's name. Writing the native entry
202
+ under the byte-identical key shadows it: native provider priority 100 beats claude 80,
203
+ dedupe is first-wins on the server NAME, and on a key hit the equivalence check is never
204
+ consulted, so an entry whose env deliberately differs still suppresses the import outright
205
+ — not both-loaded, not merged, no warning. A different key would load BOTH.
206
+ `[측정]` 2026-08-27, omp/18.0.0: the vendor's own `/mcp list` pane flipped from
207
+ `Claude Code (~/.claude.json): entwurf-bridge ● connected` to
208
+ `User level (~/.omp/agent/mcp.json): entwurf-bridge ● connected [stdio]`, and the spawned
209
+ bridge child's environ flipped with it.
210
+
211
+ **`disabledServers` is never the way to hide the import.** Suppression is by name and a
212
+ suppressed item still claims the dedupe key, so denylisting `entwurf-bridge` kills the
213
+ native entry and the import together. `[측정]` with that denylist the pane shows
214
+ `entwurf-bridge ○ not connected` and no Claude Code section at all, and no MCP child is
215
+ spawned. The installer refuses to write into a config that denylists its own key, and
216
+ `doctor-omp-mcp` is red while one exists.
217
+
218
+ **The tool names are omp's dialect, not Claude's.** omp mints `mcp__<server>_<tool>` after
219
+ lowercasing and replacing every `[^a-z_]+` run with `_`, collapsing runs and trimming edges,
220
+ so `entwurf_v2` surfaces as `mcp__entwurf_bridge_entwurf_v` — the trailing digit is eaten by
221
+ the charset, not by the length cap. The live tool list is the acceptance oracle; a live
222
+ session mounts all seven.
223
+
224
+ **And the NAME is not the invocation. Under omp's default settings an MCP tool is not a
225
+ function the model calls — it is a virtual file it writes to.** `tools.xdev` (boolean,
226
+ **default on**) mounts "discoverable" tools as `xd://<tool>` devices and DROPS them from the
227
+ top-level toolset; the model then reads `xd://<tool>` for the schema and *writes* the JSON
228
+ argument object to `xd://<tool>` to execute it. `tools.xdevDocs` (**default `builtins`**)
229
+ keeps built-in docs inline while MCP and extension schemas stay off-prompt until read. That
230
+ default costs a real capability. `[측정]` 2026-08-28, omp/18.0.0: with the defaults, a plain
231
+ "send this message to garden id X" produced a `write` to `xd://…entwurf_peers` (a LISTING)
232
+ and then the sentence "보냈습니다" — no `entwurf_v2` call, nothing enqueued, `lastEnqueuedAt`
233
+ unchanged. Discovery and delivery share one verb (`write`) and neither schema was in the
234
+ prompt. The vendor has hit the same shape in its own toolset: its changelog records
235
+ `web_search` becoming unreachable under `tools.xdev: true` because the mount dropped it from
236
+ top-level (`Tool web_search not found`, upstream #5973), fixed by pinning it via
237
+ `XDEV_KEEP_TOP_LEVEL` — a pin no MCP tool has.
238
+
239
+ `read xd://` reports exactly what the default hides. `[측정]` on a host with only this
240
+ bridge registered, **11 devices**: omp's own `ast_edit`, `debug`, `lsp`, `browser`, plus all
241
+ seven `entwurf_*`. So the default does not merely wrap entwurf — it wraps omp's own LSP and
242
+ debugger too.
243
+
244
+ **Set this on any omp host that is meant to work as a citizen:**
245
+
246
+ ```yaml
247
+ # ~/.omp/agent/config.yml
248
+ tools:
249
+ xdev: false # every enabled tool top-level — MCP is MCP again
250
+ ```
251
+
252
+ Nothing is disabled by that: the setting's own text is *"Disable to expose every enabled tool
253
+ top-level"*, and it moves tools rather than removing them. `[측정]` with `xdev: false` the
254
+ same plain-language request produced a first-try `mcp__entwurf_bridge_entwurf_v` function
255
+ call carrying a correct `intent`, the marker landed in the target mailbox, `read xd://`
256
+ answered `xd:// is not mounted in this session.`, and `lsp` / `debug` / `browser` /
257
+ `ast_edit` were all present top-level. The cost is prompt size: the system prompt's
258
+ non-message tokens went 18,707 → 21,834 (+3,127, +17%) on that host.
259
+
260
+ Two boundaries worth carrying:
261
+
262
+ - **`xd://` resolution devices survive the switch.** omp's plan mode and every staged-action
263
+ finalization write to `xd://propose` / `xd://resolve` / `xd://reject`, and its plan prompt
264
+ names them unconditionally — so "turn xdev off" looks like it should break planning. It
265
+ does not: the write dispatcher matches the resolution devices BEFORE the mount check.
266
+ `[측정]` with `xdev: false`, plan mode reached `write xd://propose` and the approval dialog
267
+ normally.
268
+ - **The narrow alternative keeps the wrapper.** `tools.xdevInlineDevices:
269
+ ["mcp__entwurf_bridge_*"]` inlines only our schemas (+1,013 tokens instead of +3,127) and
270
+ also fixed the send in the same measurement — but the 11 devices stay off top-level, `lsp`
271
+ included, and the listing/delivery verb stays shared. Prefer it only on a host carrying so many MCP servers
272
+ that the full top-level toolset is the larger problem.
273
+
274
+ All of the above is measured against omp 18.0.0 and is a setting, not a contract: re-measure
275
+ at a vendor upgrade.
276
+
277
+ Registration is tools, not identity: sending needs the birth extension
278
+ (`install-omp-bridge`), whose sender marker is keyed to the omp host's OWN pid — omp runs
279
+ its extensions in-process, so the marker's owner, the host, and the MCP child's parent are
280
+ one pid rather than the two-process join Claude and Copilot have. An omp session is a
281
+ citizen only in the operator-visible TUI; task subagents borrow its tools under its garden
282
+ id and never receive a second address.
283
+
146
284
  #### External-host skills and commands
147
285
 
148
- MCP registration gives the external harness the tools; the host still needs workflow guidance. Put the Mitsein-over-MCP (cross-harness collaboration) rules in that host's instruction file or, when supported, as a host-native skill. Do not assume pi slash commands are portable across external hosts — if a workflow must work across Claude Code, Codex CLI, Antigravity, and future hosts, make it a skill or MCP tool rather than a command shortcut.
286
+ MCP registration gives the external harness the tools; the host still needs workflow guidance. Put the Mitsein-over-MCP (cross-harness collaboration) rules in that host's instruction file or, when supported, as a host-native skill. Do not assume pi slash commands are portable across external hosts — if a workflow must work across Claude Code, Codex CLI, Antigravity, OMP, and future hosts, make it a skill or MCP tool rather than a command shortcut.
149
287
 
150
288
  For the maintained multi-harness setup and skill/command packaging details, see
151
289
  [agent-config](https://github.com/junghan0611/agent-config). See also the