@junghanacs/entwurf 0.12.6 → 0.12.7

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 (92) hide show
  1. package/AGENTS.md +31 -17
  2. package/BASELINE.md +42 -8
  3. package/CHANGELOG.md +22 -0
  4. package/DELIVERY.md +71 -14
  5. package/README.md +77 -45
  6. package/VERIFY.md +18 -13
  7. package/docs/setup-clean-host.md +80 -22
  8. package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +90 -66
  9. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/acp-client.js +54 -0
  10. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/backend-adapter.js +153 -0
  11. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/config.js +436 -0
  12. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/context.js +157 -0
  13. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/engraving.js +105 -0
  14. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/models.js +90 -0
  15. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/overlay.js +194 -0
  16. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/tool-surface.js +153 -0
  17. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-deliverability.js +42 -9
  18. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-self-address.js +49 -13
  19. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-contract.js +104 -11
  20. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-decider.js +30 -1
  21. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-native-push.js +57 -0
  22. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-production.js +10 -0
  23. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-release.js +9 -0
  24. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-runner.js +21 -0
  25. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-send.js +5 -0
  26. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-surface.js +17 -0
  27. package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-sender-identity.js +125 -0
  28. package/mcp/entwurf-bridge/dist/pi-extensions/lib/native-push/adapter.js +158 -0
  29. package/mcp/entwurf-bridge/dist/pi-extensions/lib/native-push/register.js +61 -0
  30. package/mcp/entwurf-bridge/dist/scripts/agy-imprint.js +166 -0
  31. package/mcp/entwurf-bridge/dist/scripts/doctor-pi-provider.js +130 -0
  32. package/mcp/entwurf-bridge/dist/scripts/meta-bridge-prune.js +178 -0
  33. package/mcp/entwurf-bridge/dist/scripts/new-session-id.js +24 -0
  34. package/mcp/entwurf-bridge/src/index.ts +101 -67
  35. package/mcp/entwurf-bridge/test.sh +1 -1
  36. package/mcp/entwurf-bridge/tsconfig.build.json +23 -3
  37. package/package.json +10 -5
  38. package/pi-extensions/lib/entwurf-deliverability.ts +62 -9
  39. package/pi-extensions/lib/entwurf-self-address.ts +58 -15
  40. package/pi-extensions/lib/entwurf-v2-contract.ts +120 -12
  41. package/pi-extensions/lib/entwurf-v2-decider.ts +60 -0
  42. package/pi-extensions/lib/entwurf-v2-native-push.ts +86 -0
  43. package/pi-extensions/lib/entwurf-v2-production.ts +20 -0
  44. package/pi-extensions/lib/entwurf-v2-release.ts +9 -0
  45. package/pi-extensions/lib/entwurf-v2-runner.ts +29 -1
  46. package/pi-extensions/lib/entwurf-v2-send.ts +7 -0
  47. package/pi-extensions/lib/entwurf-v2-surface.ts +17 -0
  48. package/pi-extensions/lib/meta-sender-identity.ts +154 -0
  49. package/pi-extensions/lib/native-push/adapter.ts +255 -0
  50. package/pi-extensions/lib/native-push/register.ts +99 -0
  51. package/run.sh +756 -214
  52. package/scripts/agy-bridge-config.py +446 -0
  53. package/scripts/agy-bridge.sh +359 -0
  54. package/scripts/agy-hooks-bridge.sh +193 -0
  55. package/scripts/agy-hooks-config.py +257 -0
  56. package/scripts/agy-imprint.sh +28 -0
  57. package/scripts/agy-imprint.ts +193 -0
  58. package/scripts/agy-statusline-bridge.sh +176 -0
  59. package/scripts/agy-statusline-config.py +213 -0
  60. package/scripts/agy-statusline.sh +256 -0
  61. package/scripts/build-bridge.sh +20 -0
  62. package/scripts/check-agy-sender-identity.ts +364 -0
  63. package/scripts/check-entwurf-bridge-boot.ts +8 -2
  64. package/scripts/check-entwurf-deliverability.ts +34 -0
  65. package/scripts/check-entwurf-self-address.ts +78 -11
  66. package/scripts/check-entwurf-v2-contract.ts +136 -1
  67. package/scripts/check-entwurf-v2-decider.ts +95 -1
  68. package/scripts/check-entwurf-v2-matrix.ts +14 -3
  69. package/scripts/check-entwurf-v2-native-push.ts +193 -0
  70. package/scripts/check-entwurf-v2-production.ts +68 -1
  71. package/scripts/check-entwurf-v2-runner.ts +58 -0
  72. package/scripts/check-entwurf-v2-surface.ts +35 -0
  73. package/scripts/check-install-surface.ts +357 -0
  74. package/scripts/check-native-push-adapter.ts +319 -0
  75. package/scripts/check-native-push-register.ts +130 -0
  76. package/scripts/dev-bin.sh +195 -0
  77. package/scripts/doctor-pi-provider.ts +140 -0
  78. package/scripts/meta-bridge-doctor.sh +36 -2
  79. package/scripts/register-pi-package.py +37 -3
  80. package/scripts/register-pi-provider.py +287 -0
  81. package/scripts/smoke-agy-hooks-state.sh +172 -0
  82. package/scripts/smoke-agy-install-state.sh +660 -0
  83. package/scripts/smoke-agy-native-push-live.ts +243 -0
  84. package/scripts/smoke-agy-statusline-state.sh +300 -0
  85. package/scripts/smoke-meta-async-drift.sh +9 -2
  86. package/scripts/smoke-meta-install-state.sh +20 -0
  87. package/scripts/smoke-pi-provider-state.sh +182 -0
  88. package/scripts/smoke-user-scope-citizen.sh +62 -0
  89. package/scripts/with-dist-lock.sh +81 -0
  90. package/scripts/__pycache__/meta-bridge-state.cpython-312.pyc +0 -0
  91. package/scripts/__pycache__/meta-bridge-state.cpython-313.pyc +0 -0
  92. package/scripts/__pycache__/register-pi-package.cpython-313.pyc +0 -0
package/README.md CHANGED
@@ -10,7 +10,7 @@ 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) + a meta-bridge + 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 is shipped through the meta-bridge; pi is shipped through the control-socket adapter. Codex and Antigravity (`agy`) have verified delivery probes documented per launch mode in [DELIVERY.md](./DELIVERY.md); shipped adapter/install lanes are tracked separately. The ACP plugin is Claude-first; Cortex/vendor-governed ACP backends are future lanes.
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 is shipped as a mailbox-backed meta-session; 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 is Claude-first; Cortex/vendor-governed ACP backends are future lanes.
14
14
 
15
15
  <details>
16
16
  <summary>Watch archived pre-0.12 demo (2131×1142 GIF, click to expand)</summary>
@@ -25,10 +25,10 @@ Legacy package: [`@junghanacs/pi-shell-acp`](https://www.npmjs.com/package/@jung
25
25
  Claude Code / Codex / agy / pi
26
26
  → garden id
27
27
  → entwurf_v2
28
- → control-socket | spawn-bg resume | meta-mailbox
28
+ → control-socket | spawn-bg resume | meta-mailbox | native-push
29
29
  ```
30
30
 
31
- [`entwurf_v2`](#entwurf_v2--canonical-dispatch-verb) is the canonical dispatch surface over *existing* garden citizens — live control-socket send (including record-less socket-only pi sessions), spawn-bg resume, and meta-mailbox enqueue. The v1 entwurf verbs are gone. Fresh sibling minting and non-Claude ACP backends are deferred lanes.
31
+ [`entwurf_v2`](#entwurf_v2--canonical-dispatch-verb) is the canonical dispatch surface over *existing* garden citizens — live control-socket send (including record-less socket-only pi sessions), spawn-bg resume, meta-mailbox enqueue, and native-push into a live Antigravity conversation. The v1 entwurf verbs are gone. Fresh sibling minting and non-Claude ACP backends are deferred lanes.
32
32
 
33
33
  **Garden id is deliberate vocabulary.** It is not a decorative synonym for session id, worker, delegate, or subagent. The unfamiliar word is a guard: each harness keeps its own identity and transcript, while `entwurf` supplies a narrow addressable surface between siblings.
34
34
 
@@ -43,17 +43,26 @@ pi --entwurf-control
43
43
  → Claude backend under the operator's local auth
44
44
  ```
45
45
 
46
- **The meta-bridge reaches beyond ACP transport.** A global `SessionStart` hook registers native Claude Code sessions as **garden-native meta-sessions** with a garden id, a mailbox, and a trusted sender marker. That makes an already-running Claude Code terminal addressable through `entwurf_v2` (the mailbox path), self-identifying through `entwurf_self`, and replyable by garden id — without turning pi into a second harness or importing Claude's transcript.
46
+ **Native bridges reach beyond ACP transport.** A global `SessionStart` hook registers native Claude Code sessions as **garden-native meta-sessions** with a garden id, a mailbox, and a trusted sender marker. That makes an already-running Claude Code terminal addressable through `entwurf_v2` (the mailbox path), self-identifying through `entwurf_self`, and replyable by garden id — without turning pi into a second harness or importing Claude's transcript.
47
47
 
48
48
  ```text
49
49
  native Claude Code
50
50
  → SessionStart hook
51
- → meta-session <garden-id>
51
+ mailbox-backed meta-session <garden-id>
52
52
  → entwurf-bridge MCP
53
53
  → entwurf_self | entwurf_v2 | entwurf_inbox_read
54
54
  ```
55
55
 
56
- This meta-bridge installer/doctor is **Claude Code only** in the current shipped surface. Codex and Antigravity delivery probes are recorded in [DELIVERY.md](./DELIVERY.md) as verified adapter evidence, not yet shipped install surfaces.
56
+ Antigravity uses a separate shipped rail. Its `PreInvocation` hook births or re-attaches the conversation by native `conversationId`, writes a record-backed sender marker, and leaves delivery to the live native LS gRPC route. There is no mailbox or receiver marker on this rail: `entwurf_v2` probes the conversation and direct-injects with native-push.
57
+
58
+ ```text
59
+ native Antigravity / agy
60
+ → PreInvocation imprint → meta-session <garden-id>
61
+ → entwurf-bridge MCP sender identity
62
+ ↔ entwurf_v2 native-push
63
+ ```
64
+
65
+ Claude's `install-meta-bridge` and agy's `install-agy-{bridge,statusline,hooks}` are distinct managed install surfaces because their lifecycle and delivery transports are genuinely different. Codex remains verified probe evidence, not a shipped managed native-citizen lane; see [DELIVERY.md](./DELIVERY.md).
57
66
 
58
67
  > **Direction.** Inverse of [`pi-acp`](https://github.com/svkozak/pi-acp). `pi-acp` lets external ACP clients talk *to* pi; `entwurf` lets garden citizens talk across harness boundaries — with pi as one adapter, not the center.
59
68
 
@@ -68,7 +77,7 @@ This meta-bridge installer/doctor is **Claude Code only** in the current shipped
68
77
  A few words that look unusual for a coding tool.
69
78
 
70
79
  - **Entwurf** (기투, projection-of-self) — sibling sessions with their own runtime boundary. Not "delegate," not "worker," not "sub-agent." Spawn, resume, and live peer messaging are first-class.
71
- - **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 by the `SessionStart` hook). 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, or a mailbox-backed native session, so callers discover facts with `entwurf_peers` and deliver with `entwurf_v2` instead of choosing a transport by hand.
80
+ - **Garden / garden id** — the garden is the shared address space where independent harness sessions become citizens without losing their own runtime or transcript. A garden id is the stable address of one such citizen (for pi, a garden-native session id like `YYYYMMDDTHHMMSS-<6hex>`; for native harnesses, a meta-session id minted from an authoritative lifecycle hook — Claude `SessionStart`, agy `PreInvocation`). It is not a worker name and not proof that pi owns the session. The same-looking id may name a live control socket, a dormant pi record, a mailbox-backed native session, or a native-push conversation, so callers discover facts with `entwurf_peers` and deliver with `entwurf_v2` instead of choosing a transport by hand.
72
81
  - **Engraving** — optional short operator text delivered through each backend's native identity carrier. Not a giant hidden prompt, not a tool catalog.
73
82
  - **MCP** — in this repo, MCP is just the transport by which ACP-backed sessions receive pi capabilities that native pi exposes directly as extensions. It is not a general MCP platform. Explicit `entwurfProvider.mcpServers` only; no ambient `~/.mcp.json` scanning, no automatic retrieval. The same `entwurf-bridge` entry can also be wired into another host's MCP catalog (Claude Code, Codex, Antigravity, …) when the operator chooses. `entwurf_self` returns an authoritative pi-session or trusted meta-session identity envelope; `entwurf_v2` can deliver from plain external MCP hosts, but only pi-session and trusted meta-session senders are replyable.
74
83
  - **Session persistence** — re-attaches pi to the same remote ACP session. Does not hydrate backend transcripts into pi history.
@@ -80,15 +89,19 @@ A few words that look unusual for a coding tool.
80
89
  adapter that hosts the ACP plugin and live control-socket surface, but the base
81
90
  install is **not** `pi install npm:...` anymore.
82
91
 
83
- The package exposes three bins:
92
+ The package exposes five bins:
84
93
 
85
- - `entwurf` → `run.sh` (installer, checks, meta-bridge doctor/install)
94
+ - `entwurf` → `run.sh` (installer, checks, native-bridge doctors/installers)
86
95
  - `entwurf-bridge` → the MCP stdio launcher (`mcp/entwurf-bridge/start.sh`)
87
- - `entwurf-statusline` → the Claude Code statusline renderer (`scripts/meta-bridge-statusline.sh`); a stable bin shim so a package upgrade tracks the current version without rewriting Claude settings
96
+ - `entwurf-statusline` → the Claude Code statusline renderer (`scripts/meta-bridge-statusline.sh`)
97
+ - `entwurf-agy-statusline` → the Antigravity garden-id statusline renderer (`scripts/agy-statusline.sh`)
98
+ - `entwurf-agy-imprint` → the Antigravity `PreInvocation` birth/sender hook (`scripts/agy-imprint.sh`)
88
99
 
89
- The bridge does not provide Claude credentials, tokens, or subscription access,
100
+ The bridge/renderers/hook use stable bin names so package upgrades do not bake versioned package-store paths into native-harness settings.
101
+
102
+ The bridge does not provide backend credentials, tokens, or subscription access,
90
103
  and does not bypass any backend auth. Whatever the operator's local `claude` /
91
- `codex` / pi runtime already trusts is what entwurf can use.
104
+ `codex` / `agy` / pi runtime already trusts is what entwurf can use.
92
105
 
93
106
  ### From npm — user/global install
94
107
 
@@ -188,12 +201,21 @@ raw `.ts` helpers under `node_modules`. If the doctor reports
188
201
  `ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING`, reinstall a current package before
189
202
  trusting the floor result.
190
203
 
191
- After upgrading a globally installed package, run `entwurf install-meta-bridge`
192
- again before trusting native Claude Code sessions. The installed statusline and
193
- MCP entries use stable bin shims, and the marketplace source uses a version-stable
194
- operator data dir, but the Claude plugin bundle/cache still has to be
195
- re-materialized for the new package writer. Existing Claude Code sessions should
196
- be restarted after reinstall.
204
+ After upgrading a globally installed package, reinstall the native-harness surface you use before trusting it:
205
+
206
+ ```bash
207
+ entwurf install-meta-bridge
208
+ entwurf doctor-meta-bridge
209
+
210
+ entwurf install-agy-bridge
211
+ entwurf install-agy-statusline
212
+ entwurf install-agy-hooks
213
+ entwurf doctor-agy-bridge
214
+ entwurf doctor-agy-statusline
215
+ entwurf doctor-agy-hooks
216
+ ```
217
+
218
+ The installed entries use stable bin shims, but Claude's plugin bundle/cache still has to be re-materialized and agy's three ownership records must be refreshed by their idempotent installers. Restart existing Claude Code and agy processes after reinstall.
197
219
 
198
220
  For manual configuration, [`pi/settings.reference.json`](./pi/settings.reference.json)
199
221
  shows the pi adapter settings shape, and the external-host examples below show
@@ -273,11 +295,11 @@ Reference shape lives in [`pi/settings.reference.json`](./pi/settings.reference.
273
295
  `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:
274
296
 
275
297
  - **plain external MCP host**: no garden meta-record / sender marker. It can call tools, but its sender envelope is external/non-replyable.
276
- - **garden-native meta-session**: the native `SessionStart` hook minted a garden id and wrote a trusted sender marker. It is not a pi control-socket session, but it **is replyable by garden id**.
298
+ - **garden-native native session**: a trusted lifecycle hook minted a garden id and sender marker `SessionStart` for Claude Code, `PreInvocation` for agy. It is not a pi control-socket session, but it can be replyable by garden id when its own mailbox/probe rail says so.
277
299
 
278
- **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 the target's type (live pi vs. dormant pi vs. Claude Code meta-session, which a bare garden id does not reveal) and routes correctly. Discover targets with `entwurf_peers`, confirm your own identity with `entwurf_self`, and drain your mailbox with `entwurf_inbox_read`. Fresh sibling creation from nothing is a deferred lane. (The old v1 verbs `entwurf` / `entwurf_resume` / `entwurf_send` are gone — the bridge wires only the v2 dispatch surface.)
300
+ **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). Fresh sibling creation from nothing is a deferred lane. (The old v1 verbs `entwurf` / `entwurf_resume` / `entwurf_send` are gone.)
279
301
 
280
- Observed: Claude Code, Codex CLI, and Antigravity CLI all reach garden citizens through this MCP bridge from a plain external host; sync result delivery is the baseline, and a garden-native meta-session is symmetric/replyable over the mailbox once sender identity is proven.
302
+ Observed: Claude Code, Codex CLI, and Antigravity CLI all reach garden citizens through this MCP bridge from a plain external host. Claude becomes symmetric/replyable through its mailbox-backed meta-session; agy becomes symmetric/replyable through its record-backed sender marker plus live native-push probe. Codex remains a plain external/probe lane until it has a managed citizen lifecycle.
281
303
 
282
304
  Prerequisites on the host running the external MCP client:
283
305
 
@@ -359,29 +381,27 @@ command = "/absolute/path/to/entwurf/mcp/entwurf-bridge/start.sh"
359
381
 
360
382
  #### Antigravity CLI (`agy`)
361
383
 
362
- Documented global config path:
384
+ Use the managed install surface rather than editing agy's files by hand:
363
385
 
364
- ```text
365
- ~/.gemini/antigravity-cli/mcp_config.json
386
+ ```bash
387
+ entwurf install-agy-bridge
388
+ entwurf install-agy-statusline
389
+ entwurf install-agy-hooks
390
+
391
+ entwurf doctor-agy-bridge
392
+ entwurf doctor-agy-statusline
393
+ entwurf doctor-agy-hooks
366
394
  ```
367
395
 
368
- Current runtime-compatible path also observed:
396
+ The three adapters deliberately own different atoms:
369
397
 
370
- ```text
371
- ~/.gemini/config/mcp_config.json
372
- ```
398
+ - bridge: one `entwurf-bridge` server in `~/.gemini/config/mcp_config.json`, plus exactly one permission string — `mcp(entwurf-bridge/entwurf_v2)` — in `~/.gemini/antigravity-cli/settings.json`;
399
+ - statusline: the complete `statusLine` subtree pointing at the bare stable bin `entwurf-agy-statusline`;
400
+ - hooks: one named `PreInvocation` hook pointing at the bare stable bin `entwurf-agy-imprint`.
373
401
 
374
- Use the same server entry in either file:
402
+ Unrelated servers, permissions, settings, and hooks are preserved; every adapter has a state-backed honest inverse and refuses symlink-owned SSOTs. The installer never grants broad `command(*)`, `unsandboxed(*)`, or other YOLO policy — those remain operator decisions.
375
403
 
376
- ```json
377
- {
378
- "mcpServers": {
379
- "entwurf-bridge": {
380
- "command": "/absolute/path/to/entwurf/mcp/entwurf-bridge/start.sh"
381
- }
382
- }
383
- }
384
- ```
404
+ 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.
385
405
 
386
406
  #### External-host skills and commands
387
407
 
@@ -397,6 +417,8 @@ The Claude ACP backend keeps its native model / API / tools; entwurf shapes only
397
417
 
398
418
  (Codex is *not* an ACP backend here — it reaches the garden natively. Vendor / governed CLIs are a later ACP backend lane.)
399
419
 
420
+ Antigravity is also not an ACP backend. It is a native-push citizen: `PreInvocation` supplies birth/sender identity, `entwurf_v2` probes and direct-injects replies into the live conversation, and no mailbox/receiver marker is involved.
421
+
400
422
  Pi is the canonical memory authority (semantic-memory + Denote llmlog); Claude's native memory layer is pinned off.
401
423
 
402
424
  ## Smoke commands
@@ -404,6 +426,13 @@ Pi is the canonical memory authority (semantic-memory + Denote llmlog); Claude's
404
426
  ```bash
405
427
  pnpm check # full deterministic floor (all check-* gates, incl. check-acp-*)
406
428
  ./run.sh check-bridge # entwurf-bridge direct MCP smoke (no backend auth)
429
+ ./run.sh smoke-agy-install-state # agy MCP + exact permission ownership (120 checks)
430
+ ./run.sh smoke-agy-statusline-state # agy ambient garden-id install surface (62 checks)
431
+ ./run.sh smoke-agy-hooks-state # agy PreInvocation birth hook (37 checks)
432
+ ./run.sh check-agy-sender-identity # record-backed pid/start-key sender identity (28 checks)
433
+
434
+ # agy LIVE acceptance — requires an already-running conversation:
435
+ LIVE=1 AGY_CONVERSATION_ID=<id> ./run.sh smoke-agy-native-push-live
407
436
 
408
437
  # ACP plugin LIVE acceptance — need the operator's local Claude auth/credit:
409
438
  LIVE=1 ./run.sh smoke-acp-socket-citizen-live # turn-free socket citizenship (S1)
@@ -449,9 +478,9 @@ For a real consumer arranging many skills, see [agent-config](https://github.com
449
478
 
450
479
  ## Entwurf orchestration
451
480
 
452
- **Entwurf is a pi capability with two surfaces.** Native pi exposes it directly as an extension tool; ACP-backed sessions reach the same capability through entwurf's MCP/Unix-socket bridge. The purpose is not to invent a different sub-agent system, but to preserve the same sibling-based model across backends.
481
+ **Entwurf is one dispatch capability with native-pi and MCP surfaces.** Native pi exposes it directly as extension tools; ACP-backed and external native-harness sessions reach it through `entwurf-bridge`. The purpose is not to invent a different sub-agent system, but to preserve the same sibling-based model across harnesses.
453
482
 
454
- A sibling has its own runtime boundary and its own provider/model identity — not a worker, delegate, or sub-agent. Minting a brand-new sibling from nothing is a deferred v2 lane (`spawn-fresh`); today every transport targets an *existing* garden citizen. `entwurf_v2` dispatches over those: it reads the target's liveness as a fact and routes a `fire-and-forget` send (live pi), an `owned-outcome` spawn-bg resume (dormant pi, a real `pi --entwurf-control` child), or a meta-mailbox enqueue (active self-fetch receiver) under a per-target lock, reporting one honest outcome.
483
+ A sibling has its own runtime boundary and its own provider/model identity — not a worker, delegate, or sub-agent. Minting a brand-new sibling from nothing is a deferred v2 lane (`spawn-fresh`); today every transport targets an *existing* garden citizen. `entwurf_v2` routes from rail-specific liveness + intent: live pi fire-and-forget control socket; dormant pi owned-outcome spawn-bg resume; active self-fetch meta-mailbox; probe-alive agy → native-push. Pi paths use the per-target lock; mailbox/native-push use their own deliverability evidence and remain lock-free.
455
484
 
456
485
  A two-pane recording covers the surface end-to-end — sibling resume, cross-process MCP dispatch across a different cwd, and a live peer greeting:
457
486
 
@@ -464,11 +493,11 @@ A two-pane recording covers the surface end-to-end — sibling resume, cross-pro
464
493
 
465
494
  Live peer messaging carries a sender envelope `{ sessionId, agentId, cwd, timestamp }`; `entwurf_self` returns that authoritative envelope for the current pi session or trusted meta-session. Plain external MCP hosts are non-replyable; garden-native meta-sessions carry a trusted `meta-session` envelope and are replyable by garden id. `wants_reply` is an etiquette marker rendered as a `(wants reply)` badge — not a transport contract, no wait, no polling — and is rejected only from non-replyable external senders.
466
495
 
467
- In ACP-backed sessions, agent tools (`entwurf_v2`, `entwurf_peers`, `entwurf_self`, `entwurf_inbox_read`) auto-attach through `entwurf-bridge`; in native pi sessions the same capability is available directly through the extension surface (`entwurf_v2`, `entwurf_peers` tools + `/entwurf-sessions`, `/gnew` commands). **For garden-id delivery/reply use `entwurf_v2`** — the canonical surface that classifies the target and routes to live-pi / dormant-resume / Claude-Code-meta-mailbox. Fresh sibling creation from nothing is a deferred lane. (The v1 verbs `entwurf` / `entwurf_resume` / `entwurf_send` are gone — replaced by the v2 dispatch surface.) Garden-native operator commands require `--entwurf-control`. The spawn target allowlist is [`pi/entwurf-targets.json`](./pi/entwurf-targets.json).
496
+ In ACP-backed and external native-harness sessions, `entwurf-bridge` exposes five tools: `entwurf_v2`, `entwurf_peers`, `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` tools + `/entwurf-sessions`, `/gnew` commands). **For garden-id delivery/reply use `entwurf_v2`** — the canonical surface that classifies the target and routes to live-pi / dormant-resume / Claude-Code-meta-mailbox / Antigravity-native-push. Fresh sibling creation from nothing is a deferred lane. (The v1 verbs `entwurf` / `entwurf_resume` / `entwurf_send` are gone.) Garden-native operator commands require `--entwurf-control`. The spawn target allowlist is [`pi/entwurf-targets.json`](./pi/entwurf-targets.json).
468
497
 
469
498
  ### `entwurf_v2` — canonical dispatch verb
470
499
 
471
- `entwurf_v2` / `runEntwurfV2` is the canonical v2 dispatch verb over **existing** garden targets — record-backed citizens plus live socket-only `pi` endpoints (a record-less but live `pi --entwurf-control` peer is a *target*, intentionally **not** an owned citizen). You give a target garden id plus an intent (`fire-and-forget` or `owned-outcome`); one decider reads the target's liveness as a fact (via the `entwurf_peers` fact surface) and picks the transport from a frozen table keyed on **both** the target's state **and** the intent — never on state alone — then reports one outcome under the v2 lock policy (the pi control-socket and spawn-bg paths take a per-target lock; the meta-mailbox path is lock-free but guarded by active-receiver deliverability):
500
+ `entwurf_v2` / `runEntwurfV2` is the canonical v2 dispatch verb over **existing** garden targets — record-backed citizens plus live socket-only `pi` endpoints (a record-less but live `pi --entwurf-control` peer is a *target*, intentionally **not** an owned citizen). You give a target garden id plus an intent (`fire-and-forget` or `owned-outcome`); one decider reads the target's liveness as a fact and picks the transport from a frozen table keyed on **both** the target's state **and** the intent — never on state alone — then reports one outcome under the v2 lock policy. Pi control-socket and spawn-bg paths take a per-target lock; mailbox and native-push are lock-free, with deliverability guarded by their own receiver/probe evidence:
472
501
 
473
502
  | target state | intent | transport |
474
503
  |---|---|---|
@@ -479,10 +508,13 @@ In ACP-backed sessions, agent tools (`entwurf_v2`, `entwurf_peers`, `entwurf_sel
479
508
  | active self-fetch receiver | fire-and-forget | meta-mailbox enqueue + doorbell |
480
509
  | inactive / terminated self-fetch receiver | fire-and-forget | **reject** (`mailbox-undeliverable` — no `.msg`, no doorbell) |
481
510
  | self-fetch | owned-outcome | **reject** (no owned result over a mailbox) |
511
+ | live native-push conversation | fire-and-forget | native-push direct injection |
512
+ | dead / indeterminate native-push conversation | fire-and-forget | **reject** (`native-push-target-dead` / `native-push-probe-indeterminate`) |
513
+ | native-push | owned-outcome | **reject** (`native-push-no-resume-authority`) |
482
514
 
483
- **`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 a live pi session, a dormant pi session, or a Claude Code meta-session (they look alike) and routes correctly; *when unsure which transport, use `entwurf_v2`*. This is exactly what prevents an agent from poking a live-socket transport at a Claude Code meta-session that needs the mailbox.
515
+ **`entwurf_v2` is the canonical surface for garden-id delivery.** When you have a garden id and want to reach whoever it names — message, reply, or hand-off — `entwurf_v2` is the one surface that reads whether the target is live pi, dormant pi, mailbox-backed Claude Code, or native-push Antigravity and routes correctly; *when unsure which transport, use `entwurf_v2`*. This prevents callers from guessing a rail from the shape of an id.
484
516
 
485
- What v2 provides is a **deterministic dispatch substrate** that moves the "which transport?" decision out of the fallible caller/model and into the decider, under a per-target lock, with an honest reject (no `✓ delivered`, no `.msg` garbage) when a target cannot receive. What it does **not** do is **fresh sibling creation** — minting a brand-new sibling from a provider/model/prompt is a deferred lane (the `dormant pi → spawn-bg resume` row above resumes an *already-identified* citizen, it does not mint a new one). The meta-mailbox row requires an **active** self-fetch receiver; Claude↔Claude / Claude tmux-live transport is a later lane (the contract enum names `tmux-live` but no production path executes it).
517
+ 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. What it does **not** do is **fresh sibling creation** — minting a brand-new sibling from a provider/model/prompt is a deferred lane (the `dormant pi → spawn-bg resume` row above resumes an *already-identified* citizen, it does not mint one). 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. Claude↔Claude / Claude tmux-live transport is a later lane (the contract enum names `tmux-live` but no production path executes it).
486
518
 
487
519
  A live pi target is addressed by its **control socket**, so a record-less but live `pi --entwurf-control` session (an operator-greeted peer with no meta-record) is accepted as a `fire-and-forget` control-send target, matching what `entwurf_peers` lists as alive. An `owned-outcome` resume, however, needs a record-backed citizen (its cwd/launch authority); a record-less endpoint is a socket-only fire-and-forget target only — record-less dormant resume is a later lane.
488
520
 
@@ -524,7 +556,7 @@ Enforcement (no uuid / back-compat path): a `--entwurf-control` session whose id
524
556
 
525
557
  The human-greeted 담당자 pattern is first-class: the operator opens a entwurf session in repo B, greets it directly, then passes that `sessionId` to another session, which reaches it via `entwurf_v2`. Resumed citizens and human-opened peers share the same messaging semantics; only how they came to exist differs.
526
558
 
527
- **Mitsein over MCP** (공존) — the cross-harness counterpart. Pi may collaborate with an external interactive coding session (Claude Code, Codex, Antigravity used as a human terminal) without spawning it. A plain external host is one-directional in shape: outbound `pi → external` rides whatever the operator already uses (tmux send-keys, manual paste, any interactive input path), while inbound `external → pi` returns through this bridge's `entwurf_v2`. A garden-native meta-session closes that gap both sides are addressable by garden id through the mailbox, and `wants_reply` is allowed when the sender marker proves the native session identity, so send/inbox is symmetric. The one remaining asymmetry is the followUp channel: async owned-outcome delivery still needs a pi control socket, which a meta-session does not have. This is still not a second harness — no control daemon and no transcript scraping are introduced; the bridge only fronts the mailbox/dispatch surface.
559
+ **Mitsein over MCP** (공존) — the cross-harness counterpart. Pi may collaborate with an external interactive coding session (Claude Code, Codex, Antigravity used as a human terminal) without spawning it. A plain external host is one-directional in shape: inbound `external → pi` returns through this bridge's `entwurf_v2`, but the host has no reply address. A garden-native native session closes that gap on its own rail: Claude Code through mailbox self-fetch, agy through probe-alive native-push. `wants_reply` is allowed only when the sender marker and rail-specific evidence prove replyability. Async `owned-outcome` still needs a dormant pi citizen with spawn authority; neither mailbox nor native-push has it. This is still not a second harness — no control daemon and no transcript scraping are introduced.
528
560
 
529
561
  After a session is anchored, entwurf locks its model identity: switches that touch `entwurf` are reverted; native-to-native and pre-turn selection remain free. `ensureBridgeSession` refuses direct reuse-path mismatches before backend handoff.
530
562
 
package/VERIFY.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # VERIFY.md
2
2
 
3
- Agent-driven verification guide for `entwurf` (0.12.0 surface).
3
+ Agent-driven verification guide for the current `entwurf` 0.12.x surface.
4
4
 
5
- > **Current surface.** The live release surface is one bundled MCP server, `entwurf-bridge`, exposing four tools: `entwurf_v2`, `entwurf_peers`, `entwurf_self`, `entwurf_inbox_read`. The shipped ACP backend is **Claude**; Codex is pi-native by default (`ENTWURF_ACP_FOR_CODEX=1` opts a Codex target into ACP), and Gemini is a **non-goal/probe** on 0.12 historical Gemini rows are kept for context, not as a current expectation. The 0.4.x `session-bridge` adapter, the 0.11.0 fat-bridge (`acp-bridge.ts` / `ensureBridgeSession`), and the v1 `entwurf` / `entwurf_resume` / `entwurf_send` verbs are **retired** — rows mentioning them survive in CHANGELOG/git as historical baseline, never as a runnable recipe.
5
+ > **Current surface.** The bundled MCP server, `entwurf-bridge`, exposes five tools: `entwurf_v2`, `entwurf_peers`, `entwurf_self`, `entwurf_inbox_read`, and `entwurf_register_native` (an explicit/manual fallback for binding an already-running native conversation). The shipped ACP backend is **Claude**. Antigravity (`agy`) is a separate shipped **native-push citizen** lane, not an ACP backend: automatic `PreInvocation` birth + sender identity + live probe/direct injection. Codex is pi-native by default and has native delivery probe evidence; Gemini is a non-goal/historical ACP probe on 0.12. The 0.4.x `session-bridge` adapter, the 0.11.0 fat-bridge (`acp-bridge.ts` / `ensureBridgeSession`), and the v1 `entwurf` / `entwurf_resume` / `entwurf_send` verbs are **retired** — rows mentioning them survive in CHANGELOG/git as historical baseline, never as a runnable recipe.
6
6
 
7
7
  This is a **working document, not a metrics document**. The deterministic and live gates carry the machine-checkable invariants; this file carries only what a gate cannot judge — the human/agent reading of *whether the bridge is honestly itself*. Where a former manual procedure is now a gate, it is named as a pointer rather than re-spelled as a runnable script.
8
8
 
@@ -39,12 +39,15 @@ Verification here is not a benchmark. In production we exchange short turns and
39
39
  - **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**.
40
40
  - LIVE-gated MUST steps honest-skip when `LIVE!=1`; a real cut needs `LIVE=1` with `SKIP=0`. A green MUST gate is **necessary, not sufficient** — GLG authorizes the cut.
41
41
 
42
- > The authoritative per-cut counts live in BASELINE.md's HISTORY and CHANGELOG/git, not inline here (they drift against `run.sh`). Most recent recorded floor: **2026-06-27 MUST 17/0/0 + BEHAVIOR 1/0**.
42
+ > 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 check`; do not misreport the aggregate gate as live agy evidence.
43
+ >
44
+ > The authoritative per-cut counts live in BASELINE.md's HISTORY and CHANGELOG/git, not inline here (they drift against `run.sh`). Most recent recorded aggregate floor: **2026-06-27 — MUST 17/0/0 + BEHAVIOR 1/0**.
43
45
 
44
46
  ### Verifying the two capabilities a gate cannot fully judge
45
47
 
46
- - **Garden-id delivery:** discover a target with `entwurf_peers`, then `entwurf_v2` with the correct intent — `fire-and-forget` for a live/replyable or meta-session target, `owned-outcome` only to wake a dormant record-backed pi citizen. Picking the wrong intent is rejected, never auto-fixed.
48
+ - **Garden-id delivery:** discover a target with `entwurf_peers`, then `entwurf_v2` with the correct intent — `fire-and-forget` for live pi, mailbox-backed meta, or native-push targets; `owned-outcome` only to wake a dormant record-backed pi citizen. Picking the wrong intent is rejected, never auto-fixed.
47
49
  - **ACP continuity:** a direct `pi --provider entwurf --model claude-sonnet-5` turn, or the `smoke-acp-session-reuse-live` gate (process-scoped reuse + recall). Multi-turn reuse is proven by that gate, not by any v1 resume tool.
50
+ - **agy citizenship:** in a fresh agy conversation, the first `PreInvocation` must yield a garden id, `entwurf_self` must report `agentId=meta-session/antigravity` and `replyable:true` only while the native probe is alive, and a reply to that same garden id must direct-inject into the same conversation. No mailbox/receiver-marker evidence counts on this rail.
48
51
 
49
52
  ### What NOT to do — bypassing the operational path
50
53
 
@@ -92,8 +95,9 @@ The goal is not merely "invoke Claude Code." We want:
92
95
 
93
96
  1. `pnpm install` — bundles pi (a dev/peer dependency; no separate `pi install` step) and builds the bridge
94
97
  2. project wiring → `<project>/.pi/settings.json` `entwurfProvider.mcpServers.entwurf-bridge`
95
- 3. meta-bridge global plugin — only when a native harness (`claude`) is on PATH; a pi-only host skips it cleanly
96
- 4. `entwurf-bridge` install smoke (`validate_entwurf_bridge`)
98
+ 3. Claude meta-bridge global plugin — only when `claude` is on PATH; otherwise skipped cleanly
99
+ 4. agy bridge + exact permission + statusline + `PreInvocation` hook only when `agy` is on PATH; each adapter is idempotent and independently doctorable
100
+ 5. `entwurf-bridge` install smoke (`validate_entwurf_bridge`)
97
101
 
98
102
  ```bash
99
103
  git clone https://github.com/junghan0611/entwurf /path/to/entwurf && cd $_
@@ -101,7 +105,7 @@ git clone https://github.com/junghan0611/entwurf /path/to/entwurf && cd $_
101
105
  # re-run the SAME command any time to repair a broken install
102
106
  ```
103
107
 
104
- Expected tail: `DONE: entwurf setup (pi package + meta-bridge + v2 install smoke) green.` On a host with `claude`, verify the native wiring with `./run.sh doctor-meta-bridge`.
108
+ Expected tail: `DONE: entwurf setup (pi adapter + detected native bridges + v2 install smoke) green.` On a host with `claude`, verify `./run.sh doctor-meta-bridge`. On a host with `agy`, verify all three: `doctor-agy-bridge`, `doctor-agy-statusline`, and `doctor-agy-hooks`. Setup keeps optional-harness failures non-fatal so pi/Claude hosts are not bricked; the doctors are the fail-loud acceptance surface.
105
109
 
106
110
  The wiring / meta-bridge / smoke steps are internal building blocks of `setup` (`install_local_package`, `scripts/meta-bridge-install.sh`, `validate_entwurf_bridge`) — call `setup`, never the parts. Consumers who `npm install @junghanacs/entwurf` get the obvious npm surface; that path is not the developer concern here.
107
111
 
@@ -120,11 +124,11 @@ LIVE=1 ./run.sh release-gate /path/to/consumer-project
120
124
  pi --provider entwurf --model claude-sonnet-5 -p "reply with ok only" # one-turn smoke
121
125
  ```
122
126
 
123
- `setup` runs `pnpm install` + `install` + meta-bridge (native harness) + the v2 install smoke; a green `setup` implies the settings.json wiring and install surface are healthy. The full live floor is still `LIVE=1 ./run.sh release-gate`.
127
+ `setup` runs `pnpm install` + project/user-scope install + detected native-harness wiring (Claude and/or agy) + the v2 install smoke. A green setup proves the required core path and reports optional-harness degradation; it does **not** replace the native-harness doctors. The full aggregate live floor is still `LIVE=1 ./run.sh release-gate`, with agy's conversation-id-gated round trip verified separately.
124
128
 
125
129
  ### 1.4 Cross-install / cross-backend parity (optional, high-value)
126
130
 
127
- Compare a fresh self-awareness report across axes: (1) same backend, different install path — answer must be path-invariant; (2) same backend, different machine — identical native tool list + MCP server/tool set; (3) different backend, same bridge — same harness id (`entwurf`) and MCP surface but **different** native tool surface (a Claude session reporting `apply_patch` as native, or normalized cross-backend tools, is a fail); (4) native pi routing vs ACP-bridged, same model — the native target reports **no `entwurf-bridge` MCP** (capability via pi's extension surface) while the ACP target reports it as the single MCP server. Honest "native: I cannot tell" hedging is PASS on the native side. Status: Claude axes 1–4 closed; Gemini is probe-only on 0.12.
131
+ Compare a fresh self-awareness report across axes: (1) same backend, different install path — answer must be path-invariant; (2) same backend, different machine — identical native tool list + MCP server/tool set; (3) different backend, same bridge — same garden capability but **different** native tool surface (a Claude session reporting another backend's native tools is a fail); (4) native pi routing vs ACP-bridged, same model — the native target reports no `entwurf-bridge` MCP (capability via pi's extension surface), while the ACP target reports it as the single MCP server. Honest "native: I cannot tell" hedging is PASS on the native side. Claude axes 1–4 are closed. agy is graded by the separate native-citizen checklist above, not by pretending it has Claude's ACP overlay. Gemini remains probe-only on 0.12.
128
132
 
129
133
  ---
130
134
 
@@ -147,7 +151,7 @@ Pass (carrier honesty): the subject distinguishes engraving from pi-context-augm
147
151
 
148
152
  - **Layer 0 — self-awareness:** ask environment self-awareness / MCP visibility / upstream-instruction awareness, guessing prohibited. Pass: recognizes native tool family, says "I don't know" honestly, answers MCP visibility only as configured, describes upstream instruction type without reproducing internal prompts. Fail: claims a nonexistent tool, conflates pi-custom and native tools, hallucinates MCP visibility, or conflates the two carriers (§1A.0).
149
153
  - **Layer 1 — native tool use:** throw file-reading / structure-analysis / regression-hunting tasks. Pass: Read/Edit/Bash/Grep/Glob selection is natural; no detour through MCP or recursive `pi`. Fail: strange detours for simple reads; speaks from memory without reading.
150
- - **Layer 2 — MCP boundary:** by default the four v2 MCP tools are not visible (they appear only when `entwurf-bridge` is registered). Pass: says invisible tools are not visible; explains the native-vs-MCP boundary. Fail: pretends to use an unseen tool; mimics entwurf via recursive `pi`.
154
+ - **Layer 2 — MCP boundary:** by default the five entwurf MCP tools are not visible (they appear only when `entwurf-bridge` is registered). Pass: says invisible tools are not visible; explains the native-vs-MCP boundary; treats `entwurf_register_native` as binding an already-running conversation, never as fresh spawn. Fail: pretends to use an unseen tool; mimics entwurf via recursive `pi`.
151
155
  - **Layer 3 — focus across turns:** inject a fact, then accumulate turns mixing retrieval/exploration. Pass (post-0.4.1): after **8 turns** holds **3+ early facts** incl. **one verbatim string injected before turn 5**; no repeated exploration, no self-contradiction, no tool-strategy drift. Fail: forgets early reads; paraphrases instead of returning the verbatim string. Note: entwurf exposes no user-facing compaction; use the backend's `usage_update` footer as an overflow-risk signal (it follows the ACP backend's `used/size`, not pi's visible-transcript estimate).
152
156
  - **Layer 4 — vs direct Claude Code:** requires a verifier holding **both** the `entwurf` and a direct path (human-in-loop, or both transport handles). Compare latency / native tool accuracy / detours / boundary confusion / quality around turns 10–15. Repeated tool confusion, long-turn forgetting, or boundary workarounds are a fail.
153
157
 
@@ -215,10 +219,11 @@ The minimum passing bar:
215
219
 
216
220
  1. **Deterministic floor green:** `pnpm check` passes (lint + typecheck + the `check-*` gate set + `check-pack`).
217
221
  2. **Live floor MUST green:** `LIVE=1 ./run.sh release-gate <dir>` reports `MUST PASS=N FAIL=0 SKIP=0`; a BEHAVIOR FAIL is advisory, not blocking.
218
- 3. **Honest self-recognition:** the bridged model identifies the harness as `entwurf`, names its backend, lists `entwurf-bridge` as the single MCP server with its four v2 tools, and presents a **backend-native** (not normalized) tool surface.
222
+ 3. **Honest self-recognition:** the bridged model identifies its actual harness/backend, lists `entwurf-bridge` as the single MCP server with its five current tools, and presents a backend-native (not normalized) tool surface.
219
223
  4. **Carrier separation honored:** engraving vs pi-context-augment kept distinct (§1A.0); no bridge-identity narrative attributed to the engraving carrier.
220
- 5. **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.
221
- 6. **Hygiene:** no orphan ACP children; no unexpected persisted session garbage (a turn-scoped `cwd:` fallback is never a persisted reuse).
224
+ 5. **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.
225
+ 6. **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.
226
+ 7. **Hygiene:** no orphan ACP children; no unexpected persisted session garbage (a turn-scoped `cwd:` fallback is never a persisted reuse).
222
227
 
223
228
  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).
224
229
 
@@ -4,11 +4,12 @@ End-to-end install of **entwurf** on a host with only `git` available — no
4
4
  node, no npm package, no pi binary, no dotfiles. The point is to validate the
5
5
  public install surface as an outside user would experience it.
6
6
 
7
- > **Scope.** This is the entwurf 0.12.5 install recipe. The base package install
8
- > is **neutral npm**, not `pi install npm:...`. Pi is an optional adapter lane for
9
- > the ACP provider / control-socket runtime. The 0.12.5 floor fix is explicitly
10
- > covered here: installed packages under `node_modules` must not run raw `.ts`
11
- > bridge, doctor, or plugin-hook helpers through Node strip-types.
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.
12
13
 
13
14
  `entwurf` is a garden-citizen dispatch substrate and meta-bridge. It does not
14
15
  provide, copy, or mediate backend credentials — it lets the official backend CLI
@@ -21,7 +22,7 @@ Written against a clean Ubuntu / Debian / macOS host reachable via SSH, here
21
22
  called `cleanhost`. `nvm` keeps the path identical across them.
22
23
 
23
24
  ```bash
24
- ssh cleanhost 'uname -a; whoami; which git node npm pi claude 2>/dev/null'
25
+ ssh cleanhost 'uname -a; whoami; which git node npm pi claude agy 2>/dev/null'
25
26
  # expect on a fully clean host: git present, node/npm/pi/claude absent
26
27
  ```
27
28
 
@@ -31,8 +32,9 @@ ssh cleanhost 'uname -a; whoami; which git node npm pi claude 2>/dev/null'
31
32
  |---|---|---|
32
33
  | Node | **24** recommended; `>=22.6.0` minimum | `engines.node` (Node strip-types / ESM runtime) |
33
34
  | npm | bundled with Node 24 | public package install path |
34
- | entwurf | `@junghanacs/entwurf` | neutral npm package; exposes `entwurf`, `entwurf-bridge`, and `entwurf-statusline` bins |
35
+ | entwurf | `@junghanacs/entwurf` | neutral npm package; exposes `entwurf`, `entwurf-bridge`, `entwurf-statusline`, `entwurf-agy-statusline`, and `entwurf-agy-imprint` bins |
35
36
  | pi binary | **optional**, `@earendil-works/pi-coding-agent >=0.80.3 <0.81` | needed only for the pi adapter / ACP provider / spawn-bg resume lane |
37
+ | Antigravity `agy` | **optional**, operator-installed/authenticated native CLI | needed only for the shipped native-push citizen lane; entwurf never moves its auth |
36
38
 
37
39
  ## Stage 0 — Node 24 via nvm
38
40
 
@@ -65,6 +67,8 @@ npm install -g @junghanacs/entwurf
65
67
  which entwurf
66
68
  which entwurf-bridge
67
69
  which entwurf-statusline
70
+ which entwurf-agy-statusline
71
+ which entwurf-agy-imprint
68
72
  entwurf --help | head -5
69
73
  ```
70
74
 
@@ -78,11 +82,12 @@ Prove the installed MCP server answers `tools/list` from inside `node_modules`.
78
82
  This is the first `node_modules` strip-types regression fixed in 0.12.0: Node
79
83
  refuses `--experimental-strip-types` for `.ts` under `node_modules`, so the
80
84
  installed package must boot the prebuilt JS under `mcp/entwurf-bridge/dist/`.
81
- The same installed-vs-dev split then closes the other two `.ts`-at-runtime
82
- surfaces on that same fence: the `doctor-meta-bridge` store-scan helper (0.12.4)
83
- and the plugin `SessionStart`/`UserPromptSubmit` hook (0.12.5, runs the compiled
84
- `dist/pi-extensions/meta-bridge-hook.js` when installed). Installed packages run
85
- tsc-emitted JS on every one of these; dev clones keep the `.ts` source.
85
+ The same installed-vs-dev split closes every shipped `.ts`-at-runtime surface on
86
+ that fence: the `doctor-meta-bridge` store-scan helper (0.12.4), the Claude plugin
87
+ hook (0.12.5, compiled `dist/pi-extensions/meta-bridge-hook.js`), and the agy
88
+ `PreInvocation` imprint (0.12.7, compiled `dist/scripts/agy-imprint.js`). Installed
89
+ packages run tsc-emitted JS on these paths; dev clones keep transparent `.ts`
90
+ source execution.
86
91
 
87
92
  ```bash
88
93
  node --input-type=module <<'JS'
@@ -96,7 +101,7 @@ child.stdout.on('data', d => {
96
101
  try {
97
102
  const msg = JSON.parse(out.trim());
98
103
  const names = (msg.result?.tools ?? []).map(t => t.name).sort();
99
- for (const n of ['entwurf_v2','entwurf_peers','entwurf_self','entwurf_inbox_read']) {
104
+ for (const n of ['entwurf_v2','entwurf_peers','entwurf_self','entwurf_inbox_read','entwurf_register_native']) {
100
105
  if (!names.includes(n)) throw new Error(`missing ${n}: ${names.join(',')}`);
101
106
  }
102
107
  clearTimeout(timer);
@@ -108,8 +113,9 @@ child.stdin.write(JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'tools/list' }
108
113
  JS
109
114
  ```
110
115
 
111
- Expected: a comma-separated tool list containing all four `entwurf_*` tools,
112
- exit code 0, no backend auth required.
116
+ Expected: a comma-separated tool list containing all five current `entwurf_*`
117
+ tools, exit code 0, no backend auth required. `entwurf_register_native` binds an
118
+ already-running native conversation; it is not a fresh-spawn verb.
113
119
 
114
120
  ## Stage 3 — wire a project for the pi adapter / ACP plugin (optional)
115
121
 
@@ -178,7 +184,54 @@ A plain external MCP host can call tools but is non-replyable. A garden-native
178
184
  meta-session has a garden id, a mailbox, and a trusted sender marker; it can call
179
185
  `entwurf_self`, receive mailbox wakeups, and be replied to by garden id.
180
186
 
181
- ## Stage 5 — backend auth and live runtime smoke
187
+ ## Stage 5 — Antigravity native citizen (optional)
188
+
189
+ If `agy` is already installed and authenticated by the operator, wire the three
190
+ separate ownership atoms. Entwurf does not install agy or copy its auth.
191
+
192
+ ```bash
193
+ which agy
194
+
195
+ entwurf install-agy-bridge
196
+ entwurf install-agy-statusline
197
+ entwurf install-agy-hooks
198
+
199
+ entwurf doctor-agy-bridge
200
+ entwurf doctor-agy-statusline
201
+ entwurf doctor-agy-hooks
202
+ ```
203
+
204
+ What these commands own:
205
+
206
+ - `install-agy-bridge`: one MCP server in `~/.gemini/config/mcp_config.json`
207
+ and exactly `mcp(entwurf-bridge/entwurf_v2)` in
208
+ `~/.gemini/antigravity-cli/settings.json`'s permission allow-list;
209
+ - `install-agy-statusline`: the `statusLine` subtree only, pointing at
210
+ `entwurf-agy-statusline`;
211
+ - `install-agy-hooks`: one named plugin `PreInvocation` hook pointing at
212
+ `entwurf-agy-imprint`.
213
+
214
+ They preserve unrelated user state, record independent install-state under
215
+ `$XDG_DATA_HOME/entwurf/`, and refuse symlink-owned config instead of writing
216
+ through someone else's SSOT. Broad YOLO rules such as `command(*)` and
217
+ `unsandboxed(*)` are operator policy and are never granted by this package.
218
+
219
+ Restart agy, open a **fresh conversation**, and make one model invocation. The
220
+ hook's first `PreInvocation` births/attaches the conversation by native
221
+ `conversationId`; after that, the statusline should show `🪛 <garden-id> agy`.
222
+ Verify:
223
+
224
+ 1. `entwurf_self` reports that gid with `agentId=meta-session/antigravity` and
225
+ `replyable:true` while the native route probes alive;
226
+ 2. an `entwurf_v2` send from agy reaches a sibling with that sender gid;
227
+ 3. a sibling's `entwurf_v2(..., intent=fire-and-forget)` reply to the same gid
228
+ direct-injects into the same agy conversation.
229
+
230
+ This rail has no mailbox/receiver marker and no `owned-outcome` authority.
231
+ Same-pid concurrent conversation invocation is not supported; separate agy
232
+ processes have separate pid/start-key sender markers.
233
+
234
+ ## Stage 6 — backend auth and live ACP runtime smoke
182
235
 
183
236
  Backend authentication is the operator's responsibility and lives entirely
184
237
  outside entwurf. For the Claude ACP lane:
@@ -196,7 +249,7 @@ pi --provider entwurf --model claude-sonnet-5 -p "reply with ok only"
196
249
  If the backend CLI fails directly (`claude -p "ping"`), fix that upstream first.
197
250
  `entwurf` surfaces missing auth; it does not repair it.
198
251
 
199
- ## Stage 6 — garden/control-socket surface (optional)
252
+ ## Stage 7 — garden/control-socket surface (optional)
200
253
 
201
254
  To address a long-lived pi session from another session or an external MCP host,
202
255
  open it with `--entwurf-control`. A garden-native `--session-id` is required —
@@ -210,7 +263,8 @@ pi --session-id "$(entwurf new-session-id)" \
210
263
 
211
264
  Use `entwurf_peers` to discover citizens and `entwurf_v2` to deliver by garden
212
265
  id. Do not choose the transport by hand: the same-looking id may name a live pi
213
- socket, a dormant pi record, or a mailbox-backed native session.
266
+ socket, a dormant pi record, a mailbox-backed Claude session, or a native-push
267
+ Antigravity conversation.
214
268
 
215
269
  ## Teardown
216
270
 
@@ -218,8 +272,11 @@ socket, a dormant pi record, or a mailbox-backed native session.
218
272
  # project wiring
219
273
  rm -rf ~/entwurf-smoke/.pi
220
274
 
221
- # meta-bridge plugin (if installed)
275
+ # native-harness surfaces (if installed)
222
276
  entwurf uninstall-meta-bridge 2>/dev/null || true
277
+ entwurf uninstall-agy-hooks 2>/dev/null || true
278
+ entwurf uninstall-agy-statusline 2>/dev/null || true
279
+ entwurf uninstall-agy-bridge 2>/dev/null || true
223
280
 
224
281
  # package and optional pi binary
225
282
  npm uninstall -g @junghanacs/entwurf
@@ -231,6 +288,7 @@ rm -rf ~/.nvm
231
288
  ```
232
289
 
233
290
  This walk-through is a verification floor underneath release cuts: neutral npm
234
- install, installed bridge boot, optional pi adapter registration, and at least
235
- one authenticated runtime smoke when cutting a live release. GLG owns the
236
- publish/tag decision.
291
+ install, installed bridge boot, optional pi adapter registration, Claude
292
+ meta-bridge verification where used, all three agy doctors plus a fresh native
293
+ round trip where used, and at least one authenticated ACP runtime smoke. GLG owns
294
+ the publish/tag decision.