@junghanacs/entwurf 0.13.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +52 -17
- package/BASELINE.md +60 -206
- package/CHANGELOG.md +64 -0
- package/CONTRIBUTING.md +14 -10
- package/DELIVERY.md +118 -261
- package/README.md +91 -431
- package/VERIFY.md +74 -95
- package/demo/README.md +1 -1
- package/demo/demo-baseline.sh +1 -3
- package/demo/demo.sh +2 -5
- package/docs/acp-backend-rail.md +236 -0
- package/docs/external-mcp-host.md +131 -0
- package/docs/fresh-cut-policy.md +99 -0
- package/docs/setup-clean-host.md +124 -328
- package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +160 -67
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/acp-client.js +12 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/backend-adapter.js +11 -10
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/config.js +1 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/engraving.js +42 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/models.js +4 -4
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/overlay.js +11 -9
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-control-rpc.js +7 -5
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-core.js +13 -14
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-resume-args.js +45 -40
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-contract.js +117 -95
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-decider.js +23 -57
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-lock.js +16 -7
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-production.js +5 -53
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-release.js +21 -36
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-runner.js +3 -15
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-send-fallback.js +12 -11
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-send.js +2 -7
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-surface.js +30 -67
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-visible-resume.js +256 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-session.js +91 -5
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +258 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-launch.js +202 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-placement.js +289 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-resume-call.js +170 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/resume-launch-identity.js +136 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/session-id.js +8 -5
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/socket-discovery.js +3 -3
- package/mcp/entwurf-bridge/dist/scripts/meta-facts.js +51 -0
- package/mcp/entwurf-bridge/dist/scripts/new-session-id.js +9 -4
- package/mcp/entwurf-bridge/src/index.ts +176 -67
- package/mcp/entwurf-bridge/start.sh +2 -2
- package/mcp/entwurf-bridge/test.sh +23 -9
- package/mcp/entwurf-bridge/tsconfig.build.json +11 -2
- package/package.json +25 -11
- package/pi-extensions/entwurf-control.ts +220 -71
- package/pi-extensions/lib/acp/acp-client.ts +22 -0
- package/pi-extensions/lib/acp/augment.ts +42 -3
- package/pi-extensions/lib/acp/backend-adapter.ts +12 -11
- package/pi-extensions/lib/acp/backend.ts +366 -38
- package/pi-extensions/lib/acp/config.ts +1 -1
- package/pi-extensions/lib/acp/engraving.ts +43 -1
- package/pi-extensions/lib/acp/event-mapper.ts +16 -13
- package/pi-extensions/lib/acp/models.ts +4 -4
- package/pi-extensions/lib/acp/overlay.ts +11 -9
- package/pi-extensions/lib/entwurf-control-rpc.ts +7 -5
- package/pi-extensions/lib/entwurf-core.ts +15 -15
- package/pi-extensions/lib/entwurf-resume-args.ts +41 -52
- package/pi-extensions/lib/entwurf-v2-contract-schema.ts +1 -1
- package/pi-extensions/lib/entwurf-v2-contract.ts +120 -99
- package/pi-extensions/lib/entwurf-v2-decider.ts +30 -91
- package/pi-extensions/lib/entwurf-v2-lock.ts +16 -7
- package/pi-extensions/lib/entwurf-v2-production.ts +4 -78
- package/pi-extensions/lib/entwurf-v2-release.ts +25 -49
- package/pi-extensions/lib/entwurf-v2-runner.ts +6 -21
- package/pi-extensions/lib/entwurf-v2-send-fallback.ts +12 -11
- package/pi-extensions/lib/entwurf-v2-send.ts +2 -7
- package/pi-extensions/lib/entwurf-v2-surface.ts +36 -76
- package/pi-extensions/lib/entwurf-v2-visible-resume.ts +370 -0
- package/pi-extensions/lib/meta-session.ts +93 -5
- package/pi-extensions/lib/mux-fresh-call.ts +328 -0
- package/pi-extensions/lib/mux-launch.ts +267 -0
- package/pi-extensions/lib/mux-placement.ts +387 -0
- package/pi-extensions/lib/mux-resume-call.ts +221 -0
- package/pi-extensions/lib/resume-launch-identity.ts +162 -0
- package/pi-extensions/lib/session-id.js +8 -5
- package/pi-extensions/lib/socket-discovery.ts +3 -3
- package/prompts/engraving.md +13 -5
- package/run.sh +688 -282
- package/scripts/agy-bridge-config.py +5 -1
- package/scripts/check-acp-backend-preflight.ts +1 -1
- package/scripts/check-acp-carrier-augment.ts +246 -10
- package/scripts/check-acp-cortex.ts +5 -5
- package/scripts/check-acp-overlay.ts +13 -3
- package/scripts/check-acp-prompt-lifecycle.ts +565 -0
- package/scripts/check-acp-stop-reason.ts +342 -0
- package/scripts/check-acp-stream-hooks.ts +504 -0
- package/scripts/check-elapsed.sh +25 -0
- package/scripts/check-entwurf-bridge-boot.ts +51 -4
- package/scripts/check-entwurf-bridge-pi-free.ts +6 -5
- package/scripts/check-entwurf-control-rpc.ts +4 -3
- package/scripts/check-entwurf-resume-args.ts +72 -70
- package/scripts/check-entwurf-session-identity.ts +14 -10
- package/scripts/check-entwurf-v2-contract.ts +34 -59
- package/scripts/check-entwurf-v2-decider.ts +17 -177
- package/scripts/check-entwurf-v2-lock.ts +5 -2
- package/scripts/check-entwurf-v2-matrix.ts +3 -53
- package/scripts/check-entwurf-v2-production.ts +2 -91
- package/scripts/check-entwurf-v2-release.ts +10 -105
- package/scripts/check-entwurf-v2-runner.ts +4 -85
- package/scripts/check-entwurf-v2-send-fallback.ts +5 -6
- package/scripts/check-entwurf-v2-send.ts +0 -28
- package/scripts/check-entwurf-v2-surface.ts +198 -128
- package/scripts/check-entwurf-v2-visible-resume.ts +445 -0
- package/scripts/check-fresh-cut-gate.sh +1 -1
- package/scripts/check-gate-qualification.ts +101 -7
- package/scripts/check-install-container.sh +10 -2
- package/scripts/check-install-surface.ts +1 -1
- package/scripts/check-keyset-overlap.py +1 -1
- package/scripts/check-meta-facts.ts +249 -0
- package/scripts/check-meta-identity-consumers.ts +1 -1
- package/scripts/check-meta-session.ts +169 -0
- package/scripts/check-mux-launch-tmux.ts +316 -0
- package/scripts/check-mux-launch.ts +288 -0
- package/scripts/check-mux-launcher-fence.ts +264 -0
- package/scripts/check-mux-parent-artifact.ts +195 -0
- package/scripts/check-mux-placement-tmux.ts +322 -0
- package/scripts/check-mux-placement.ts +323 -0
- package/scripts/check-mux-resume-call.ts +282 -0
- package/scripts/check-probe-cli-shim.ts +25 -22
- package/scripts/check-probe-ordering.ts +121 -81
- package/scripts/check-release-gate-outcomes.ts +452 -0
- package/scripts/check-resume-launch-identity.ts +244 -0
- package/scripts/check-socket-discovery.ts +1 -1
- package/scripts/fixtures/mux-parent-transcript.scrubbed.jsonl +3 -0
- package/scripts/inventory-verification-surface.ts +349 -0
- package/scripts/lib/claude-launcher-fence.ts +322 -0
- package/scripts/lib/live-skip.ts +33 -0
- package/scripts/lib/mutation-qualify.ts +109 -3
- package/scripts/lib/probe-acp-turn.ts +33 -12
- package/scripts/lib/step-outcome.sh +88 -0
- package/scripts/meta-bridge-doctor.sh +6 -8
- package/scripts/meta-facts.ts +60 -0
- package/scripts/mutants/acp-augment.json +106 -0
- package/scripts/mutants/acp-cortex.json +2 -2
- package/scripts/mutants/acp-overlay.json +17 -0
- package/scripts/mutants/acp-prompt-lifecycle.json +100 -0
- package/scripts/mutants/acp-stop-reason.json +80 -0
- package/scripts/mutants/acp-stream-hooks.json +158 -0
- package/scripts/mutants/bridge-boot-resume.json +45 -0
- package/scripts/mutants/meta-facts.json +50 -0
- package/scripts/mutants/meta-identity.json +36 -0
- package/scripts/mutants/mux-boundary.json +196 -0
- package/scripts/mutants/mux-fresh-call.json +185 -0
- package/scripts/mutants/mux-launcher-fence.json +123 -0
- package/scripts/mutants/mux-parent-artifact.json +39 -0
- package/scripts/mutants/mux-resume-call.json +148 -0
- package/scripts/mutants/probe-ordering.json +6 -1021
- package/scripts/mutants/release-gate.json +140 -0
- package/scripts/mutants/resume-args.json +76 -0
- package/scripts/mutants/resume-launch-identity.json +96 -0
- package/scripts/mutants/v2-surface.json +74 -23
- package/scripts/mutants/v2-visible-resume.json +215 -0
- package/scripts/new-session-id.ts +9 -4
- package/scripts/smoke-acp-bundled-mcp-live.ts +4 -3
- package/scripts/smoke-acp-carrier-augment-live.ts +2 -2
- package/scripts/smoke-acp-cortex-live.ts +8 -14
- package/scripts/smoke-acp-long-turn-live.ts +185 -0
- package/scripts/smoke-acp-mcp-live.ts +2 -2
- package/scripts/smoke-acp-memory-containment-live.ts +2 -2
- package/scripts/smoke-acp-ordering-probe-live.ts +2 -2
- package/scripts/smoke-acp-overlay-live.ts +2 -2
- package/scripts/smoke-acp-provider-live.ts +2 -2
- package/scripts/smoke-acp-raw-turn-live.ts +3 -3
- package/scripts/smoke-acp-session-reuse-live.ts +2 -2
- package/scripts/smoke-acp-skill-live.ts +2 -2
- package/scripts/smoke-acp-socket-citizen-live.ts +4 -3
- package/scripts/smoke-acp-v2-send-live.ts +4 -3
- package/scripts/smoke-agy-native-push-live.ts +10 -20
- package/scripts/smoke-claude-native-resume-live.sh +13 -3
- package/scripts/smoke-entwurf-chain-live.ts +352 -0
- package/scripts/smoke-entwurf-v2-matrix-live.ts +3 -3
- package/scripts/smoke-meta-honesty.sh +1 -1
- package/scripts/smoke-meta-install-state.sh +4 -0
- package/scripts/smoke-mux-fresh-call-live.ts +365 -0
- package/scripts/smoke-mux-lifecycle-live.ts +1136 -0
- package/scripts/smoke-pi-attach.ts +1 -1
- package/scripts/smoke-user-scope-citizen.sh +1 -1
- package/scripts/tsconfig.json +1 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-preflight.js +0 -160
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-spawn-production.js +0 -273
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-spawn.js +0 -216
- package/pi-extensions/lib/entwurf-v2-spawn-production.ts +0 -373
- package/pi-extensions/lib/entwurf-v2-spawn.ts +0 -323
- package/scripts/check-acp-sdk-surface.ts +0 -236
- package/scripts/check-entwurf-v2-spawn-production.ts +0 -551
- package/scripts/check-entwurf-v2-spawn.ts +0 -399
- package/scripts/smoke-entwurf-v2-spawn-live.ts +0 -188
- package/scripts/smoke-entwurf-v2-spawn-resume-live.ts +0 -469
package/CONTRIBUTING.md
CHANGED
|
@@ -4,7 +4,7 @@ This is a daily-driver bridge. Correctness beats feature breadth. Read this befo
|
|
|
4
4
|
|
|
5
5
|
## What this repo is
|
|
6
6
|
|
|
7
|
-
`entwurf` is a **garden-citizen dispatch bridge** — entwurf-core (v2 dispatch) + a meta-bridge + a pi adapter + an **ACP plugin on a two-backend adapter rail** — that lets already-running harnesses address one another by garden id; pi is one adapter, not the subject. The ACP plugin borrows the backend's identity (system prompt preset, model behavior, tool implementations) and shapes the *operating surface* — tools, MCP, skills, permissions — to match pi's own policy **wherever that backend exposes a knob for it**. Where it does not, the plugin does not fake one: a cortex session keeps its own native tool surface and receives MCP through an overlay projection, so "shaped to pi's policy" is a Claude-strength claim, not a universal one. Claude is the reference ACP backend and Snowflake Cortex Code is the second (landed 0.13.0, `cortex-` prefixed ids — [docs/acp-backend-rail.md](./docs/acp-backend-rail.md
|
|
7
|
+
`entwurf` is a **garden-citizen dispatch bridge** — entwurf-core (v2 dispatch) + a meta-bridge + a pi adapter + an **ACP plugin on a two-backend adapter rail** — that lets already-running harnesses address one another by garden id; pi is one adapter, not the subject. The ACP plugin borrows the backend's identity (system prompt preset, model behavior, tool implementations) and shapes the *operating surface* — tools, MCP, skills, permissions — to match pi's own policy **wherever that backend exposes a knob for it**. Where it does not, the plugin does not fake one: a cortex session keeps its own native tool surface and receives MCP through an overlay projection, so "shaped to pi's policy" is a Claude-strength claim, not a universal one. Claude is the reference ACP backend and Snowflake Cortex Code is the second (landed 0.13.0, `cortex-` prefixed ids — [docs/acp-backend-rail.md](./docs/acp-backend-rail.md#cortex-code-audit-d1d10)); Codex has native delivery-probe evidence but no managed citizen lane, and Gemini is not a shipped backend. That is the entire scope.
|
|
8
8
|
|
|
9
9
|
**How a backend joins the rail** (the shape a PR must take): one adapter object in `pi-extensions/lib/acp/backend-adapter.ts` + its own curated rows/overlay modules + its own `check-acp-*` gate and mutant lane. Backend-specific *behavior* must stay behind the adapter, and backend-specific settings ride the opaque `adapterSettings` seam rather than growing the common config. That is not a ban on ever touching the common layer (`backend.ts`'s turn loop, `acp-client.ts`, `event-mapper.ts`, `session-store.ts`, `config.ts`) — cortex's landing did change `backend.ts` to pass the authoritative session key through the generic `ensureOverlay` seam. The rule is narrower and stricter: a common-layer change must be **backend-invariant** (it reads no backend name and branches on no backend) and **separately gated**. A common file that grows an `if (backend === …)` is the thing to reject.
|
|
10
10
|
|
|
@@ -17,7 +17,7 @@ These are enforced by code, gates, and review. Do not weaken them in a PR; if yo
|
|
|
17
17
|
1. **Bootstrap order**: `resume > load > new`. Always.
|
|
18
18
|
2. **Session persistence**: only `pi:<sessionId>` is persisted. `cwd:<cwd>` is never persisted.
|
|
19
19
|
3. **MCP injection**: only via `entwurfProvider.mcpServers`. No ambient `~/.mcp.json` scanning, no `~/.claude/settings.json` MCP inheritance.
|
|
20
|
-
4. **Operating surface, not config inheritance**: the user's filesystem Claude Code config (`~/.claude/settings.json` hooks, env, plugins, `permissions.defaultMode`) is intentionally *not* inherited. Skills come from `skillPlugins
|
|
20
|
+
4. **Operating surface, not config inheritance**: the user's filesystem Claude Code config (`~/.claude/settings.json` hooks, env, plugins, `permissions.defaultMode`) is intentionally *not* inherited. Skills come from `skillPlugins`; callable tools are shaped by `tools` / `disallowedTools`, and `permissionAllow` still rides the inline Claude settings. The overlay authors `permissions.defaultMode: "bypassPermissions"` so an unattended ACP turn cannot suspend on an interactive prompt; this does not bypass backend authentication. `CLAUDE_CONFIG_DIR` enforces the isolation even where the SDK reads filesystem independently of `settingSources`.
|
|
21
21
|
5. **Backend-specific knobs stay explicit and namespaced**: retired Codex/Gemini-era ACP knobs are not carried on the current path. A backend that needs its own knob uses the `ENTWURF_ACP_*` namespace, and invalid values must throw, never fall back — cortex followed this with `ENTWURF_ACP_CORTEX_CONNECTION` (the renamed `PI_SHELL_ACP*` legacy var), and its settings key rides `adapterSettings`, not the common config.
|
|
22
22
|
6. **Bridge does not implement compaction**: When a backend compacts natively, the pi session and mapping survive that. Pi-side JSONL compaction must not be presented as backend-transcript reduction, and backend-specific compaction controls belong to the backend's own native interface. Legacy `PI_SHELL_ACP_*` compaction knobs must not reappear.
|
|
23
23
|
7. **Backend coverage honesty**: changes to operating surface, session lifecycle, or persistence must state which shipped/probed backend surfaces they cover. A claim that silently drops a covered backend is a regression; if one backend is genuinely not covered, record that carve-out explicitly.
|
|
@@ -26,27 +26,31 @@ These are enforced by code, gates, and review. Do not weaken them in a PR; if yo
|
|
|
26
26
|
## Required gate before opening a PR
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
|
-
pnpm check
|
|
29
|
+
pnpm check # everyday core (prints wall time; <=60s on the reference host)
|
|
30
|
+
pnpm run check:full # full deterministic floor — the required PR gate
|
|
30
31
|
```
|
|
31
32
|
|
|
32
|
-
|
|
33
|
+
The deterministic floor is tiered (#70). `pnpm check` is the everyday core (biome, tsc, the vitest lanes, and the fast contract gates); `pnpm run check:full` adds the hermetic-integration and package/install tiers — all but the separately scheduled `check-gate-qualification`, which CI runs on every push and a gate-changing PR must run once itself. Exact membership is the named `check:*` scripts in `package.json`. Run `check:full` once on your frozen commit candidate — the pre-commit hook (`.husky/pre-commit`) carries only fast static checks (whitespace, lint, typecheck), not the full floor, so a green `pnpm run check:full` before commit is the evidence that your change holds (scheduling contract: AGENTS.md "Verification scheduling").
|
|
33
34
|
|
|
34
|
-
For changes that touch backend launch, session lifecycle, or `_meta` shape, also run
|
|
35
|
+
For changes that touch backend launch, session lifecycle, or `_meta` shape, also run
|
|
36
|
+
the live ACP smokes that cover the touched rail — at minimum:
|
|
35
37
|
|
|
36
38
|
```bash
|
|
37
|
-
./run.sh smoke-
|
|
38
|
-
./run.sh
|
|
39
|
+
LIVE=1 ./run.sh smoke-acp-provider-live
|
|
40
|
+
LIVE=1 ./run.sh smoke-acp-session-reuse-live
|
|
39
41
|
```
|
|
40
42
|
|
|
41
|
-
These need a real ACP subprocess
|
|
43
|
+
These need a real ACP subprocess plus the operator's local backend auth, so they stay
|
|
44
|
+
manual — the hook does not run them. The full aggregate is `LIVE=1 ./run.sh release-gate
|
|
45
|
+
<scratch> --cut` (see [VERIFY.md](./VERIFY.md)).
|
|
42
46
|
|
|
43
47
|
## What gets PRs rejected
|
|
44
48
|
|
|
45
49
|
- adds ambient MCP discovery (project `.mcp.json`, `~/.mcp.json`, etc.) without an explicit `entwurfProvider.mcpServers` opt-in path
|
|
46
|
-
- inherits user / project / local backend config by default (i.e. flips `settingSources` away from `[]`, drops the `CLAUDE_CONFIG_DIR` overlay,
|
|
50
|
+
- inherits user / project / local backend config by default (i.e. flips `settingSources` away from `[]`, drops the `CLAUDE_CONFIG_DIR` overlay, or weakens cortex's session-scoped HOME containment)
|
|
47
51
|
- weakens `resume > load > new` (e.g. silently downgrading to `new` without a logged invalidation reason)
|
|
48
52
|
- introduces `console.warn` / silent fallback where the bridge should `throw` (see `AGENTS.md` "Never warn. Throw.")
|
|
49
|
-
- changes
|
|
53
|
+
- changes a backend operating surface (tools, skills, MCP, permissions, sandbox) without accounting for both shipped backends (Claude, Cortex) or recording an explicit carve-out
|
|
50
54
|
- adds a second transcript ledger, a prompt reconstruction layer, or any state that competes with pi's session as the source of truth
|
|
51
55
|
- skews version pins across `package.json`, `run.sh`, and `README.md` (the `check-dep-versions` gate catches this; if it complains, fix all three)
|
|
52
56
|
|
package/DELIVERY.md
CHANGED
|
@@ -1,285 +1,142 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Async delivery capability levels
|
|
2
2
|
|
|
3
|
-
`DELIVERY.md`
|
|
3
|
+
`DELIVERY.md` answers one cross-harness question:
|
|
4
4
|
|
|
5
|
-
> Can an already-running native agent session receive an
|
|
6
|
-
> pretending that pi owns the backend transcript?
|
|
5
|
+
> Can an already-running native agent session receive an asynchronous message
|
|
6
|
+
> without pretending that pi owns the backend transcript?
|
|
7
7
|
|
|
8
|
-
It is
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
It is a diagnostic coordinate system, not a product promise or benchmark. Record
|
|
9
|
+
the highest demonstrated capability instead of collapsing results into “works” or
|
|
10
|
+
“doesn't work.” Evidence quality is tracked separately in [VERIFY.md](./VERIFY.md);
|
|
11
|
+
operator observations live in [BASELINE.md](./BASELINE.md).
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
## Scope
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
- [`scripts/raw-async-delivery/`](./scripts/raw-async-delivery/) — reproducible raw delivery probes.
|
|
15
|
+
Qualifying delivery targets an already-running, backend-owned native session through
|
|
16
|
+
an official surface. It does **not** include:
|
|
18
17
|
|
|
19
|
-
|
|
18
|
+
- tmux/pty keystroke injection or transcript scraping;
|
|
19
|
+
- direct writes into backend transcripts or state databases;
|
|
20
|
+
- a fresh prompt/process/thread presented as continuation;
|
|
21
|
+
- transcript hydration or a second tool-result ledger inside entwurf.
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
messages reach that session through the backend's own supported surface —
|
|
24
|
-
mailbox wake for Claude Code, native-push for agy, or a launch-mode-specific
|
|
25
|
-
probe rail for Codex.
|
|
26
|
-
|
|
27
|
-
Non-goals:
|
|
28
|
-
|
|
29
|
-
- no tmux / pty `send-keys` as evidence for native delivery;
|
|
30
|
-
- no backend transcript hydration into pi JSONL;
|
|
31
|
-
- no direct writes into backend transcript databases / JSONL / protobuf files;
|
|
32
|
-
- no new prompt spawn (`claude -p`, fresh Codex thread, etc.) masquerading as
|
|
33
|
-
delivery into an already-running subscription/native session;
|
|
34
|
-
- no fake pi session or tool-result ledger for an external backend.
|
|
35
|
-
|
|
36
|
-
A backend may use a socket, filesystem watch, JSON-RPC app server, lifecycle
|
|
37
|
-
hook, or another official surface. The transport differs; the levels below keep
|
|
38
|
-
the judgement comparable.
|
|
23
|
+
A transport may be a socket, filesystem watch, mailbox, lifecycle hook, or native
|
|
24
|
+
API. The levels compare capabilities, not implementation shapes.
|
|
39
25
|
|
|
40
26
|
## State vocabulary
|
|
41
27
|
|
|
42
|
-
Use these words precisely in scripts and docs:
|
|
43
|
-
|
|
44
28
|
| State | Meaning |
|
|
45
29
|
|---|---|
|
|
46
|
-
| `queued` |
|
|
47
|
-
| `triggered` | A
|
|
48
|
-
| `woke` | An idle interactive session
|
|
49
|
-
| `injected` | The message
|
|
50
|
-
| `processed` |
|
|
51
|
-
| `replied` | A result returned
|
|
30
|
+
| `queued` | A message is durable; the backend may not have seen it. |
|
|
31
|
+
| `triggered` | A supported event/API accepted the signal. |
|
|
32
|
+
| `woke` | An idle interactive session began a turn without user typing. |
|
|
33
|
+
| `injected` | The message reached model-visible context. |
|
|
34
|
+
| `processed` | A supported event says the turn completed. |
|
|
35
|
+
| `replied` | A result returned through an explicit garden-side path. |
|
|
52
36
|
|
|
53
|
-
Avoid bare `delivered
|
|
54
|
-
`queued → triggered → woke → injected → processed → replied`.
|
|
37
|
+
Avoid bare `delivered`; name the observed boundary.
|
|
55
38
|
|
|
56
|
-
##
|
|
39
|
+
## Levels (D0–D8)
|
|
57
40
|
|
|
58
|
-
These are
|
|
59
|
-
|
|
60
|
-
partial levels.
|
|
41
|
+
These are independent of VERIFY's `L0–L5` evidence levels and BASELINE's question
|
|
42
|
+
layers.
|
|
61
43
|
|
|
62
|
-
| Level |
|
|
63
|
-
|
|
64
|
-
| **D0** | Live
|
|
65
|
-
| **D1** | Native
|
|
66
|
-
| **D2** | Receiver armed | The
|
|
67
|
-
| **D3** | Addressed enqueue |
|
|
68
|
-
| **D4** | Idle
|
|
69
|
-
| **D5** | Context injection | A unique
|
|
70
|
-
| **D6** |
|
|
71
|
-
| **D7** | Completion
|
|
72
|
-
| **D8** | Operational robustness |
|
|
44
|
+
| Level | Capability | PASS criterion |
|
|
45
|
+
|---|---|---|
|
|
46
|
+
| **D0** | Live identity | Native id, cwd/project, backend, and enough liveness data identify one target. |
|
|
47
|
+
| **D1** | Native continuation | The existing native/subscription session receives the message; no fresh worker/thread substitutes for it. |
|
|
48
|
+
| **D2** | Receiver armed | The session exposes a supported watch, hook, socket, subscription, or API route. |
|
|
49
|
+
| **D3** | Addressed enqueue | One target is selected; siblings are not broadcast-woken. |
|
|
50
|
+
| **D4** | Idle wake | An idle session wakes without user typing or pty injection. |
|
|
51
|
+
| **D5** | Context injection | A unique message reaches model-visible context through the supported route. |
|
|
52
|
+
| **D6** | Continuity | The same native session/conversation and model path responds. |
|
|
53
|
+
| **D7** | Completion/reply observation | Completion or reply is observable without transcript scraping. |
|
|
54
|
+
| **D8** | Operational robustness | Dedupe, ordering, stale handling, loop guards, and crash recovery are implemented and tested. |
|
|
73
55
|
|
|
74
|
-
|
|
56
|
+
Mark partial or conditional cells explicitly. Capability and evidence are different:
|
|
57
|
+
a D7 claim from one direct-native run may still have only L4 evidence on one host.
|
|
75
58
|
|
|
76
|
-
|
|
77
|
-
|
|
59
|
+
### Probe output
|
|
60
|
+
|
|
61
|
+
Raw probes under [`scripts/raw-async-delivery/`](./scripts/raw-async-delivery/)
|
|
62
|
+
should print one comparable block:
|
|
78
63
|
|
|
79
64
|
```text
|
|
80
65
|
DELIVERY_LEVELS:
|
|
81
|
-
harness
|
|
82
|
-
transport
|
|
83
|
-
D0
|
|
84
|
-
D1
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
D5 context_injection: pass token=AGY-PARITY-3399
|
|
89
|
-
D6 continuity: pass session_id=<native-id> model=claude-opus-5
|
|
90
|
-
D7 completion_reply: partial reason="no garden outbox yet"
|
|
91
|
-
D8 robustness: partial reason="loop guard present; crash recovery not tested"
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
When a level is **not applicable** or **conditional**, say so explicitly. For
|
|
95
|
-
example, Codex app-server delivery is conditional on a loaded thread and control
|
|
96
|
-
socket; direct Codex TUI is a different surface.
|
|
97
|
-
|
|
98
|
-
## Current capability matrix (2026-07-22)
|
|
99
|
-
|
|
100
|
-
This matrix is a snapshot of what the raw probes have established. It should be
|
|
101
|
-
updated when a backend version changes the delivery surface.
|
|
102
|
-
|
|
103
|
-
The **Status** column is the current 0.12.x release framing, kept separate from
|
|
104
|
-
the `D0–D8` capability level:
|
|
105
|
-
|
|
106
|
-
- **shipped** — a supported lane: wired, gated, and addressable through the bridge today.
|
|
107
|
-
- **verified-probe** — async delivery proven by a raw probe, but not yet a managed supported citizen lane.
|
|
108
|
-
- **deferred** — not addressable as-is, or needs an extra managed install / cloud surface outside the current release.
|
|
109
|
-
|
|
110
|
-
| Harness / surface | Status | Highest current level | Transport | Notes |
|
|
111
|
-
|---|---|---:|---|---|
|
|
112
|
-
| **pi native Entwurf** | shipped | D7+ | Unix control socket + pi followUp/custom messages | Replyable pi session. This is the resident baseline, not an external meta-session. The meta-record is the sole address authority (#50 C4): a record-less control socket — live or not — is refused as `record-less-socket` (diagnostic state), never dispatched. |
|
|
113
|
-
| **Claude Code interactive >=2.1.217** | shipped *(Linux is the only certified axis)* | D6, D7 partial, D8 partial | Exec-form global plugin: `SessionStart` arms `watchPaths`; external write triggers exec-form `FileChanged`; `asyncRewake` wakes idle session | B2 direct-native at 2.1.217 on one NixOS host proved per-element argv, no shell expansion, parent join, and exit-2 idle wake. B at 2.1.138 proved the negative: `args` discarded while Claude reported success, so installer/doctor enforce 2.1.217 and there is no shell fallback. The launcher provenance token keeps an old cached command fail-closed. Active idle wake is D6; D7/D8 remain partial as before. The Linux container's planted cache/owner/bridge are fixtures, not a second native-host proof. |
|
|
114
|
-
| **Antigravity / agy** | shipped | D6, D7 partial | Native LS gRPC `agentapi send-message` (native-push) | `PreInvocation` automatically births/attaches by native `conversationId` and writes the record-backed pid/start-key sender marker; `entwurf_v2` fire-and-forget probes and direct-injects through the antigravity adapter with a one-shot re-probe retry. Three managed adapters own MCP+one exact permission, statusline, and hook separately. `entwurf_register_native` remains an explicit/manual fallback, not the normal birth path. Live sender→sibling→same-gid reply passed on 2026-07-13, re-verified at **agy 1.1.0** on 2026-07-14 (13/13 LIVE checks); D7 stays partial because there is no canonical transcript/content receipt owned by the smoke. |
|
|
115
|
-
| **Codex app-server-backed TUI 0.136.0** | verified-probe | D6, D7 (status) | WebSocket-over-UDS `turn/start` into the live `threadId` | **Demonstrated, no managed standalone, no cloud.** `codex app-server --listen unix://<owned 0700 dir>` + plain `codex` auto-attach (or `--remote unix://`). Full message injection (agy-like, not a doorbell); `thread/status/changed` gives completion observation. D8 robustness (dedupe / crash recovery / ordering policy) is not tested. `turn/steer` is active-turn steering, not idle wake. |
|
|
116
|
-
| **Codex embedded TUI 0.136.0** | deferred | D0 partial | Native state DB / rollout transcript only | Standalone Embedded TUI binds no socket; no `FileChanged`/`asyncRewake` in Codex hooks; not retrofittable. Identify-only via state DB / rollout. |
|
|
117
|
-
| **Codex managed-daemon / remote-control 0.136.0** | deferred | D4–D6 conditional | `app-server proxy` newline JSON-RPC over the daemon control socket | Needs the managed standalone install; `remote-control` also enables the **cloud** bridge. Use the bare `--listen` path above for a purely-local setup. |
|
|
118
|
-
| **ACP Claude / Cortex (runtime lane)** | shipped as runtime; deferred as delivery target | — | ACP (via entwurf's pi adapter) | Both ACP backends are **landed runtime lanes** (Claude the reference; Cortex since 0.13.0 under the dual-HOME containment — `docs/acp-backend-rail.md` §11-8), but **not native-async-*delivery* targets**: ACP sessions are bridge-spawned children, not already-running native sessions to wake, so they fall outside this doc's delivery question. `deferred` here means "no async-delivery lane," not "unsupported." |
|
|
119
|
-
|
|
120
|
-
## Backend notes
|
|
121
|
-
|
|
122
|
-
### Claude Code — filesystem event wake, not socket push
|
|
123
|
-
|
|
124
|
-
The current launch contract is **exec-only at Claude Code >=2.1.217**. All four
|
|
125
|
-
hook leaves run the shipped `hook-launch.sh` as `command` with the real argv in
|
|
126
|
-
`args`; the launcher stamps non-identity launch provenance and `exec`s the payload.
|
|
127
|
-
A hook reached through an old cached shell command still mints its record but writes
|
|
128
|
-
no sender/receiver marker, so an upgrade mismatch is fail-closed. Reinstall the
|
|
129
|
-
meta-bridge and restart all old Claude sessions before judging delivery.
|
|
130
|
-
|
|
131
|
-
Evidence boundary: B/B2 were real Claude sessions and therefore direct-native
|
|
132
|
-
runtime evidence, but both ran on one NixOS host. `check-hook-launch-topology` is a
|
|
133
|
-
deterministic execution proof of the shipped argv; `check-install-container` uses a
|
|
134
|
-
fake Claude, planted plugin cache, stand-in owner, and fake live bridge. Those fixtures
|
|
135
|
-
prove package/oracle behavior, not actual native session wake. A claimed Linux host
|
|
136
|
-
is accepted only when its **installed** strict doctor sees the live owner join and
|
|
137
|
-
exits 0; missing evidence is `NOT CERTIFIED`, not a partial delivery PASS. macOS is
|
|
138
|
-
not yet verified/certified for this repair cut: install refuses Darwin, doctor stays
|
|
139
|
-
nonzero, and only the uninstaller keeps Darwin support so an older managed install
|
|
140
|
-
can be removed. Future native validation may reopen that lane.
|
|
141
|
-
|
|
142
|
-
A missing local listening socket does **not** imply idle wake is impossible.
|
|
143
|
-
Claude Code interactive can be woken by a supported filesystem-event path:
|
|
144
|
-
|
|
145
|
-
1. a plugin or settings hook runs at `SessionStart`;
|
|
146
|
-
2. it emits `watchPaths` for a per-session signal file;
|
|
147
|
-
3. an external sender writes a per-session message and pokes that signal;
|
|
148
|
-
4. `FileChanged` fires while the session is idle;
|
|
149
|
-
5. the hook exits with `asyncRewake` and writes the doorbell to **stderr**;
|
|
150
|
-
6. the same session/model wakes and self-fetches the message body.
|
|
151
|
-
|
|
152
|
-
#### D8 partial — signal/body separation is level-triggered
|
|
153
|
-
|
|
154
|
-
Claude's `FileChanged` signal is an edge: rapid signal writes may coalesce, and a
|
|
155
|
-
true missed edge can leave an idle session with unread mail until another wake or
|
|
156
|
-
backstop occurs. The body is not carried in that edge. Bodies are durable mailbox
|
|
157
|
-
files (`*.msg` before the doorbell, `*.msg.delivered` after the doorbell), and
|
|
158
|
-
`entwurf_inbox_read` drains the whole unread set in one read and archives them as
|
|
159
|
-
`*.read`. Therefore a coalesced doorbell does not drop message bodies: once the
|
|
160
|
-
receiver self-fetches, it consumes all queued bodies, not "one event = one body".
|
|
161
|
-
|
|
162
|
-
Deterministic gates: `check-meta-session` asserts mixed fresh/delivered bodies are
|
|
163
|
-
drained together and re-read is empty; `smoke-meta-honesty` asserts the doorbell's
|
|
164
|
-
unread count matches what the inbox reader will drain. Remaining D8 work is still
|
|
165
|
-
honest/open in #34: empirical FileChanged coalescing bounds, active-turn arrival,
|
|
166
|
-
watchPath edge cases, compact-window re-arm gaps, and a heartbeat/re-poke backstop
|
|
167
|
-
for live sessions with unread mail.
|
|
168
|
-
|
|
169
|
-
Important gotchas live in [`scripts/raw-async-delivery/README.md`](./scripts/raw-async-delivery/README.md):
|
|
170
|
-
`Stop` hooks do not wake idle sessions, bare skills cannot arm startup watches,
|
|
171
|
-
plugins can, and imperatives in injected text can be flagged as prompt injection.
|
|
172
|
-
|
|
173
|
-
### Antigravity / agy — native push
|
|
174
|
-
|
|
175
|
-
Antigravity reaches the same delivery levels through a different transport:
|
|
176
|
-
`agy agentapi send-message` over the native LS gRPC surface. This is not a reason
|
|
177
|
-
to make the garden layer backend-specific; it is exactly why the adapter contract
|
|
178
|
-
must describe capability (`D0–D8`) separately from transport.
|
|
179
|
-
|
|
180
|
-
The raw probe (`scripts/raw-async-delivery/raw-agy-send.sh` — the Live-SSOT method
|
|
181
|
-
`pgrep -x agy` + an LS socket that answers `get-conversation-metadata`) is now
|
|
182
|
-
productionized as the **native-push rail**: `pi-extensions/lib/native-push/adapter.ts`
|
|
183
|
-
(full pid/LS scan, volatile route, 1-shot re-probe retry in the executor hand),
|
|
184
|
-
`registerNativeConversation` (bind an already-running conversation as a garden
|
|
185
|
-
citizen; no spawn), the `entwurf_v2` `native-push` transport (post-probe reject
|
|
186
|
-
taxonomy: `native-push-target-dead` / `-probe-indeterminate` / `-no-resume-authority`),
|
|
187
|
-
and the `install-agy-bridge` install adapter. agy is a `native-push` domain, distinct
|
|
188
|
-
from the pi control-socket liveness domain and from the Claude mailbox self-fetch domain.
|
|
189
|
-
|
|
190
|
-
#### agy ambient-status axis (install surface, orthogonal to D0–D8)
|
|
191
|
-
|
|
192
|
-
Beyond delivery, agy carries two more entwurf-owned install surfaces: **ambient
|
|
193
|
-
garden identity in the native statusline** (`entwurf-agy-statusline`) and the
|
|
194
|
-
**`PreInvocation` birth/sender imprint** (`entwurf-agy-imprint`). These are not
|
|
195
|
-
delivery levels — they are install-surface ownership axes with the same discipline
|
|
196
|
-
the delivery rail uses: bare stable bins only (never repo/checkout paths),
|
|
197
|
-
state-backed install/uninstall, element-level adopt-and-preserve with honest
|
|
198
|
-
inverse, symlink refusal, fail-loud doctors, and an honest `?` before identity
|
|
199
|
-
exists.
|
|
200
|
-
|
|
201
|
-
Identity authority is the native `conversationId` looked up against meta-record
|
|
202
|
-
**bodies**. No cwd back-match, filename-derived identity, or gid invention. agy
|
|
203
|
-
has no `SessionStart`; the earliest hook is `PreInvocation`, so a new conversation
|
|
204
|
-
may briefly render `🪛 ? agy`. On the first invocation the installed hook reads
|
|
205
|
-
`conversationId` + `workspacePaths`, calls `upsertMetaSession` idempotently, and
|
|
206
|
-
writes a sender marker only after the record exists. It always returns the neutral
|
|
207
|
-
`{"injectSteps":[]}` response so identity bookkeeping cannot block the agy loop.
|
|
208
|
-
|
|
209
|
-
The marker is keyed by the shared host pid + process start-key and is revalidated
|
|
210
|
-
against the record body. Replyability is `recordBacked ∧ probeAlive`, never
|
|
211
|
-
mailbox `watchArmed`. This supports separate agy processes (measured: three pids,
|
|
212
|
-
three markers) but **not** simultaneous model invocation by two conversations
|
|
213
|
-
under one agy pid: one marker file would be last-writer-wins, so that concurrency
|
|
214
|
-
is explicitly unsupported.
|
|
215
|
-
|
|
216
|
-
Current deterministic floor: `smoke-agy-install-state` 167 checks,
|
|
217
|
-
`smoke-agy-statusline-state` 69, `smoke-agy-hooks-state` 44,
|
|
218
|
-
`check-agy-sender-identity` 28, plus the shared self-address/native-push gates.
|
|
219
|
-
The bridge installer owns one narrow rule per normal-path tool
|
|
220
|
-
(`entwurf_v2`, `entwurf_peers`, `entwurf_self`) in `permissions.allow`;
|
|
221
|
-
broad YOLO policy stays operator-owned. Live 2026-07-13
|
|
222
|
-
(agy 1.0.x): automatic birth → gid/statusline → record-backed sender → sibling
|
|
223
|
-
delivery → same-gid native-push reply passed. Live 2026-07-14 (**agy 1.1.0**):
|
|
224
|
-
re-verified on the new minor — `entwurf_self` answered without a permission
|
|
225
|
-
prompt under the operator's broad allow (gid `20260714T101829-e7fccd`, native
|
|
226
|
-
conversation `21266946-64a6-4a35-a7e5-fc84f0a7f250`), bidirectional native-push
|
|
227
|
-
reply arrived on the same gid, and `LIVE=1 smoke-agy-native-push-live` passed
|
|
228
|
-
13/13; the drift-sentinel agy pin moved to the 1.1 line on this evidence.
|
|
229
|
-
|
|
230
|
-
### Codex — split by launch mode, not by "Codex"
|
|
231
|
-
|
|
232
|
-
> **Version verdict (2026-07-14, 0.12.7 cut):** the installed codex is **0.144.1**;
|
|
233
|
-
> every claim in this section was measured at **0.136.0** and has **NOT been
|
|
234
|
-
> re-verified** since. Codex is not a shipped native-citizen lane in 0.12.x, so the
|
|
235
|
-
> drift-sentinel pin moved to the 0.144 line with this explicit non-reverification
|
|
236
|
-
> verdict instead of a fresh probe run. Re-run the raw probes (and re-date the matrix
|
|
237
|
-
> rows) before building any codex adapter on the new line.
|
|
238
|
-
|
|
239
|
-
Do not describe "Codex" as one delivery shape. The split is the TUI's launch mode:
|
|
240
|
-
|
|
241
|
-
- **standalone Embedded TUI**: binds no socket, no `FileChanged`/`asyncRewake` in
|
|
242
|
-
Codex hooks, decision fixed at `run_main` → not addressable, not retrofittable;
|
|
243
|
-
- **app-server-backed TUI**: idle-wake **works**. Run a bare
|
|
244
|
-
`codex app-server --listen unix://$HOME/.codex/app-server-control/app-server-control.sock`
|
|
245
|
-
(no managed standalone, no cloud — only the official daemon path needs the
|
|
246
|
-
managed install). Plain `codex` (no `-c`) auto-attaches to that default socket;
|
|
247
|
-
an external WebSocket-over-UDS client sends `turn/start` to the live `threadId`.
|
|
248
|
-
Measured: idle thread woke with zero typing, body injected, model replied,
|
|
249
|
-
completion observed via `thread/status/changed`.
|
|
250
|
-
|
|
251
|
-
Sender: `raw-codex-ws-turn-start.py` → bare `--listen` socket (WebSocket, no managed
|
|
252
|
-
standalone, no cloud). A second surface exists but is out of scope here — the managed
|
|
253
|
-
**daemon** control socket (via `codex app-server proxy`) needs the managed standalone
|
|
254
|
-
install, and `remote-control` enables the cloud bridge; we ship only the bare-local
|
|
255
|
-
path. Per-folder `config.toml` `[projects."<path>"]` trust gates project-hook loading,
|
|
256
|
-
not addressability.
|
|
257
|
-
|
|
258
|
-
A Codex adapter must declare which launch mode + which socket it targets.
|
|
259
|
-
|
|
260
|
-
## How to use this in the current 0.12.x design
|
|
261
|
-
|
|
262
|
-
For meta-sessions, peer records should expose capability rather than hiding
|
|
263
|
-
backend differences:
|
|
264
|
-
|
|
265
|
-
```ts
|
|
266
|
-
type WakeMode = "socket" | "file-watch" | "native-push" | "app-server" | "piggyback" | "none";
|
|
267
|
-
|
|
268
|
-
type DeliveryPeer = {
|
|
269
|
-
sessionId: string; // garden id
|
|
270
|
-
kind: "pi-session" | "meta-session";
|
|
271
|
-
backend: "pi" | "claude-code" | "antigravity" | "codex" | string;
|
|
272
|
-
replyable: boolean;
|
|
273
|
-
wakeMode: WakeMode;
|
|
274
|
-
deliveryLevel: "D0" | "D1" | "D2" | "D3" | "D4" | "D5" | "D6" | "D7" | "D8";
|
|
275
|
-
};
|
|
66
|
+
harness=<name>
|
|
67
|
+
transport=<official surface>
|
|
68
|
+
D0 live_identity: pass
|
|
69
|
+
D1 native_continuation: pass
|
|
70
|
+
...
|
|
71
|
+
D7 completion_reply: partial reason="..."
|
|
72
|
+
D8 robustness: partial reason="..."
|
|
276
73
|
```
|
|
277
74
|
|
|
278
|
-
|
|
75
|
+
## Current matrix
|
|
279
76
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
-
|
|
77
|
+
| Harness / surface | Product status | Capability | Transport and boundary |
|
|
78
|
+
|---|---|---|---|
|
|
79
|
+
| **pi native Entwurf** | shipped | D7; D8 partial | Record-addressed Unix control socket. A record-less socket is diagnostic only and never dispatched. |
|
|
80
|
+
| **Claude Code interactive `>=2.1.217`** | shipped; Linux certified | D6; D7/D8 partial | Per-session mailbox + exec-form `FileChanged`/`asyncRewake`. B2 proved idle wake and same-session continuity on one NixOS host. |
|
|
81
|
+
| **Antigravity / agy** | shipped | D6; D7 partial | Record-backed native-push through LS gRPC `agentapi send-message`; no mailbox or receiver marker. |
|
|
82
|
+
| **Codex app-server-backed TUI** | verified probe | D7; D8 unproven | WebSocket-over-UDS `turn/start` into a live `threadId`; status events expose completion. No managed citizen lane yet. |
|
|
83
|
+
| **Codex embedded TUI** | deferred | D0 partial | No supported receive socket/hook on the measured standalone shape. |
|
|
84
|
+
| **ACP Claude / Cortex** | shipped runtime, outside this matrix | — | ACP sessions are children launched by entwurf's pi adapter, not already-running native sessions to wake. |
|
|
85
|
+
|
|
86
|
+
“Verified probe” means the transport worked in a reproducible raw probe but entwurf
|
|
87
|
+
does not yet own lifecycle, installation, doctors, or release acceptance for it.
|
|
88
|
+
Re-audit backend versions before turning probe evidence into a shipped adapter.
|
|
89
|
+
|
|
90
|
+
## Rail notes
|
|
91
|
+
|
|
92
|
+
### Claude Code: durable body, edge-triggered wake
|
|
93
|
+
|
|
94
|
+
Claude's hook contract is exec-only at `>=2.1.217`. `SessionStart` arms a per-session
|
|
95
|
+
watch path; the sender writes durable `*.msg` bodies before poking the signal;
|
|
96
|
+
`FileChanged` emits a doorbell and `asyncRewake` wakes the idle session. The receiver
|
|
97
|
+
then calls `entwurf_inbox_read`, which drains all unread bodies and archives them as
|
|
98
|
+
`*.read`.
|
|
99
|
+
|
|
100
|
+
The signal is edge-triggered and may coalesce, but the message body is level-triggered:
|
|
101
|
+
one successful wake drains the backlog. D8 remains partial until active-turn arrival,
|
|
102
|
+
coalescing bounds, re-arm gaps, and crash/re-poke behavior are measured. A synthetic
|
|
103
|
+
container doctor proves package/oracle shape, not a real Claude wake; a claimed host
|
|
104
|
+
needs the installed strict doctor against a new native session.
|
|
105
|
+
|
|
106
|
+
### Antigravity: native push
|
|
107
|
+
|
|
108
|
+
`PreInvocation` births or reattaches a citizen by native `conversationId` and writes a
|
|
109
|
+
record-backed sender marker. `entwurf_v2` probes the live conversation and injects
|
|
110
|
+
directly through the native adapter, with one bounded re-probe retry. Replyability is
|
|
111
|
+
`record-backed identity ∧ probe-alive`; mailbox state does not exist on this rail, and no
|
|
112
|
+
rail has resume authority since the visible-first cut.
|
|
113
|
+
|
|
114
|
+
The managed bridge, statusline, and hook installers own separate configuration atoms.
|
|
115
|
+
Same-pid concurrent model invocation by multiple conversations is not claimed because
|
|
116
|
+
the pid/start-key sender marker would be last-writer-wins. Current operator checks are
|
|
117
|
+
in [BASELINE.md](./BASELINE.md); deterministic ownership and sender gates run in
|
|
118
|
+
`pnpm run check:full`.
|
|
119
|
+
|
|
120
|
+
### Codex: launch mode is part of the capability
|
|
121
|
+
|
|
122
|
+
Do not describe “Codex” as one delivery shape. The measured app-server-backed TUI can
|
|
123
|
+
accept `turn/start` for a live thread and report completion; the standalone embedded
|
|
124
|
+
TUI exposed no equivalent receive route. This remains archived method evidence, not a
|
|
125
|
+
shipping commitment: GLG closed the managed native Codex lane on 2026-08-01 because pi
|
|
126
|
+
already supplies the official GPT provider path. Entwurf will not duplicate it as a
|
|
127
|
+
native citizen or ACP backend. `turn/steer` is active-turn steering, not idle wake.
|
|
128
|
+
|
|
129
|
+
## Recording a new claim
|
|
130
|
+
|
|
131
|
+
For every matrix change, record:
|
|
132
|
+
|
|
133
|
+
1. backend version and launch mode;
|
|
134
|
+
2. native session identifier and liveness join;
|
|
135
|
+
3. exact official transport;
|
|
136
|
+
4. highest D-level plus every partial boundary;
|
|
137
|
+
5. evidence level and artifact/log location;
|
|
138
|
+
6. what remains outside entwurf ownership.
|
|
139
|
+
|
|
140
|
+
Keep transcript ownership native, lookup authority in the meta-record, and transport
|
|
141
|
+
asymmetry explicit. Historical probes and per-version chronology belong in CHANGELOG,
|
|
142
|
+
issues, and git history rather than this standing capability contract.
|