@junghanacs/entwurf 0.20.1 → 0.22.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 +85 -190
- package/BASELINE.md +6 -3
- package/CHANGELOG.md +473 -14
- package/CONTRIBUTING.md +1 -1
- package/DELIVERY.md +332 -60
- package/README.md +100 -22
- package/VERIFY.md +93 -7
- package/docs/acp-backend-rail.md +0 -1
- package/docs/external-mcp-host.md +64 -33
- package/docs/setup-clean-host.md +151 -17
- package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +130 -114
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/codex-caller-seat.js +174 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/codex-fresh-preflight.js +519 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-fact-provider.js +22 -2
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-peers-render.js +3 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-contract.js +6 -7
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-native-push.js +30 -17
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-production.js +7 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-runner.js +3 -2
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-send.js +8 -4
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-surface.js +7 -4
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-mailbox-body.js +20 -11
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-sender-identity.js +227 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +189 -19
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/native-push/adapter.js +10 -7
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/native-push/codex-ws-client.js +403 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/native-push/register.js +4 -4
- package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-hook-codex.js +325 -0
- package/mcp/entwurf-bridge/dist/scripts/codex-socket-path.js +30 -0
- package/mcp/entwurf-bridge/dist/scripts/meta-bridge-fresh-cut.js +6 -1
- package/mcp/entwurf-bridge/src/index.ts +154 -116
- package/mcp/entwurf-bridge/tsconfig.build.json +10 -0
- package/package.json +13 -4
- package/pi-extensions/entwurf-control.ts +71 -19
- package/pi-extensions/lib/codex-caller-seat.ts +204 -0
- package/pi-extensions/lib/codex-fresh-preflight.ts +580 -0
- package/pi-extensions/lib/compaction-send-guard.ts +80 -0
- package/pi-extensions/lib/entwurf-fact-provider.ts +29 -3
- package/pi-extensions/lib/entwurf-peers-render.ts +4 -1
- package/pi-extensions/lib/entwurf-v2-contract.ts +6 -7
- package/pi-extensions/lib/entwurf-v2-native-push.ts +35 -18
- package/pi-extensions/lib/entwurf-v2-production.ts +10 -3
- package/pi-extensions/lib/entwurf-v2-runner.ts +3 -2
- package/pi-extensions/lib/entwurf-v2-send.ts +16 -11
- package/pi-extensions/lib/entwurf-v2-surface.ts +7 -4
- package/pi-extensions/lib/meta-mailbox-body.ts +22 -13
- package/pi-extensions/lib/meta-sender-identity.ts +305 -0
- package/pi-extensions/lib/mux-fresh-call.ts +233 -29
- package/pi-extensions/lib/native-push/adapter.ts +21 -24
- package/pi-extensions/lib/native-push/codex-ws-client.ts +506 -0
- package/pi-extensions/lib/native-push/register.ts +7 -9
- package/pi-extensions/meta-bridge-hook-codex.ts +371 -0
- package/run.sh +342 -28
- package/scripts/check-agy-sender-identity.ts +1 -1
- package/scripts/check-codex-app-server-launch.ts +445 -0
- package/scripts/check-codex-birth-hook.ts +264 -0
- package/scripts/check-codex-bridge-identity.ts +179 -0
- package/scripts/check-codex-native-push.ts +386 -0
- package/scripts/check-codex-sender-identity.ts +495 -0
- package/scripts/check-compaction-send-guard.ts +130 -0
- package/scripts/check-copilot-receive-arm.ts +4 -1
- package/scripts/check-entwurf-fact-provider.ts +38 -0
- package/scripts/check-entwurf-peers-surface.ts +13 -1
- package/scripts/check-entwurf-self-address.ts +15 -16
- package/scripts/check-entwurf-v2-contract.ts +4 -3
- package/scripts/check-entwurf-v2-decider.ts +7 -5
- package/scripts/check-entwurf-v2-native-push.ts +35 -7
- package/scripts/check-entwurf-v2-production.ts +245 -12
- package/scripts/check-entwurf-v2-runner.ts +1 -1
- package/scripts/check-entwurf-v2-send.ts +26 -7
- package/scripts/check-entwurf-v2-surface.ts +1 -1
- package/scripts/check-gate-qualification.ts +8 -3
- package/scripts/check-harness-admission-parity.ts +0 -1
- package/scripts/check-mux-launch-tmux.ts +345 -4
- package/scripts/check-native-push-adapter.ts +20 -16
- package/scripts/check-native-push-register.ts +5 -1
- package/scripts/check-release-gate-outcomes.ts +47 -1
- package/scripts/check-setup-qualification.sh +3 -1
- package/scripts/codex-app-server-launch.sh +275 -0
- package/scripts/codex-birth-doctor.sh +276 -0
- package/scripts/codex-birth-install.sh +414 -0
- package/scripts/codex-birth-uninstall.sh +170 -0
- package/scripts/codex-mcp-config.py +435 -0
- package/scripts/codex-socket-path.ts +33 -0
- package/scripts/codex-statusline-config.py +434 -0
- package/scripts/codex-terminal-title-config.py +500 -0
- package/scripts/codex_toml_io.py +653 -0
- package/scripts/lib/codex-fresh-live-protocol.ts +121 -0
- package/scripts/lib/codex-fresh-source-receipts.ts +426 -0
- package/scripts/lib/launch-receipt-windows.ts +46 -0
- package/scripts/lib/tmux-coordinate-row.ts +58 -0
- package/scripts/meta-bridge-fresh-cut.ts +6 -1
- package/scripts/mutants/codex-app-server-launch.json +157 -0
- package/scripts/mutants/codex-caller-seat.json +336 -0
- package/scripts/mutants/codex-native.json +838 -0
- package/scripts/mutants/compaction-send-guard.json +103 -0
- package/scripts/mutants/entwurf-peers.json +19 -0
- package/scripts/mutants/mux-fresh-call.json +93 -10
- package/scripts/mutants/omp-fresh.json +6 -4
- package/scripts/mutants/release-gate.json +13 -0
- package/scripts/mutants/v2-surface.json +75 -1
- package/scripts/raw-async-delivery/README.md +2 -1
- package/scripts/raw-codex-measure/README.md +114 -46
- package/scripts/smoke-agy-native-push-live.ts +3 -1
- package/scripts/smoke-codex-birth.sh +347 -0
- package/scripts/smoke-codex-config-state.sh +700 -0
- package/scripts/smoke-codex-fresh-live.ts +1426 -0
- package/scripts/smoke-codex-native-push-live.ts +75 -0
- package/scripts/smoke-entwurf-chain-live.ts +50 -0
- package/scripts/smoke-setup-verdict.sh +125 -10
- package/scripts/tsconfig.json +1 -0
package/DELIVERY.md
CHANGED
|
@@ -88,8 +88,8 @@ physical host. Do not read a D-level cell as a Darwin receipt.
|
|
|
88
88
|
| **pi native Entwurf** | shipped | D7; D8 partial | Record-addressed Unix control socket. A record-less socket is diagnostic only and never dispatched. |
|
|
89
89
|
| **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. |
|
|
90
90
|
| **Antigravity / agy** | shipped | D6; D7 partial | Record-backed native-push through LS gRPC `agentapi send-message`; no mailbox or receiver marker. Admitted before the #82 step 9 contract and not re-evaluated under it, so it is legacy citizen evidence, not a step-9 supported harness: `entwurf_fresh_call` cannot open an agy sibling, and nothing here should be read as claiming visible lifecycle parity. |
|
|
91
|
-
| **Codex app-server
|
|
92
|
-
| **Codex embedded TUI** | deferred | D0 partial |
|
|
91
|
+
| **Codex CLI app-server citizen** | supported in 0.21.0; caller-seat topology ACCEPTED on Linux at 0.153.4, 2026-09-16 (56 assertions, exit 0), and the caller-DIRECTORY axis ACCEPTED the same day on the same host (#95 lane C, 65 assertions, exit 0; the 2026-09-12 explicit-home acceptance is history — #95 D1 retired that room) | D6 accepted; D7 partial; D8 unproven | Vendor-trusted user-scope `SessionStart` birth plus strict per-request metadata join; no shared-pid sender marker. `thread/loaded/list` probes the operator-owned app-server UDS and one-shot `codex queue` delivers with no retry. The operator owns the app-server and seats it wherever they like; Entwurf creates, moves and supervises none of it. Since #95 lane B a Codex CALLER with no explicit placement opens its sibling beside its OWN pane, located by the `thread-id` its `[tui].terminal_title` writes into the pane title; 0 or 2+ matching panes refuse with no fallback, and the title is a placement input only — never an address, liveness or delivery fact. #95 D1 (2026-09-16) retired the fixed `codex` home that omitted-placement Codex TARGETS used to select, so an omitted seat is the caller's own session for every backend. Exact 0.153.4 source still bounds placing a sibling beside a TUI whose thread nobody named as unsupported; the anchor resolves only the pane showing the caller's own thread. |
|
|
92
|
+
| **Codex embedded TUI** | deferred | D0 partial | At the 2026-09-08 Codex 0.153.4 measurement, standalone mode had no `watchPaths`/`FileChanged`/`asyncRewake` analogue or supported idle receive route. This is dated vendor evidence, not a claim that the current candidate lacks records or fresh. |
|
|
93
93
|
| **Copilot CLI first-party extension** | raw transport probe; superseded by the owned product unit | D7 path observed; D3 control receipt incomplete; D8 unproven | CLI-spawned extension over stdio JSON-RPC; `joinSession()` + documented `fs.watch` → `session.send({mode:"enqueue"})`. Idle wake, exact-marker reply, and completion passed on 2026-08-23 (CLI 1.0.80, L4, one Linux host). Two-process isolation was observed but its decisive B log was not preserved. Kept as the transport receipt the owned receive unit was built on; the shipped unit differs deliberately — it announces the inbox instead of injecting the body. |
|
|
94
94
|
| **Copilot CLI garden citizen** | shipped in 0.15.0; send + receive + visible fresh accepted on one host | D6; D7 partial; D3 pending; D8 unproven | Birth, garden id, MCP hand and record-backed sender identity are accepted; the RECEIVER is an installed first-party extension that binds to the V3 record, writes a receiver marker owned by the WATCHER pid, and rings a doorbell the model drains with `entwurf_inbox_read`. `wakeMode` is `self-fetch`, so dispatch reaches the mailbox rail: armed → delivered, unarmed/stale → the honest `mailbox-undeliverable` refusal. **D6 is the owned-invocation LIVE acceptance of 2026-08-23** — garden `20260823T181316-d9f6ba`, native `20fe30c8-b2bc-4600-91a0-8a409131be51`, CLI 1.0.80: receive log `joined`→`armed`→`doorbell fresh=1`→`rang`, mailbox `lastEnqueuedAt 09:23:41.235Z` / `lastReadAt 09:23:56.480Z`, and a model reply on the same record/native/gid chain. **Visible fresh (step 9 clause 7) is a separate LIVE, 2026-08-25** — launch window `@89`/`%89` nonce `mux-fresh-call-690529ae99f99faa2252aefb`; exact-callback garden `20260825T085721-f68be0`; one `entwurf_v2` → `meta-mailbox → enqueued`; same garden `lastReadAt 2026-08-24T23:57:47.784Z` plus same-gid reply; GLG saw footer garden id and a healthy multi-turn window. Those rows stay unmerged. D7 is PARTIAL: reply and read receipt were observed, the completion taxonomy and long-haul operation were not. D3 (second-session isolation of an owned invocation) is PENDING — observed once, decisive log lost to scratch cleanup. Evidence level L4: one host. Launch through the owned invocation `entwurf copilot`, which sets `COPILOT_CLI_ENABLED_FEATURE_FLAGS=EXTENSIONS` for that one process; `doctor-copilot-receive` reads live CLI environments because a session launched without it is silently inert. Visible fresh is operator-metered and is not a release-gate MUST. |
|
|
95
95
|
| **OMP (`omp`) garden citizen** | shipped in 0.16.0; send + receive + visible fresh accepted on one host | D6; D3 proven; D7 partial; D8 partial | Two in-process extensions in the operator's own TUI: birth mints the `mode === "tui"` host (subagents mint nothing) and names it as sender; the RECEIVER unit joins that citizen in the SAME process, holds an `fs.watch` on its mailbox signal, and rings an announce-only doorbell through the vendor's `pi.sendUserMessage` — measured to be on the FACTORY object, not the event ctx, and measured to start a turn on an idle host with zero typing (`agent_start` +31ms). `wakeMode` is `self-fetch`: the model drains with `entwurf_inbox_read` and THAT read is the receipt. **D6 is the LIVE acceptance of 2026-08-30** (oracle, omp 18.0.0) — garden `20260830T140819-116f6a`, `lastEnqueuedAt 05:08:20.555Z` / `lastReadAt 05:08:23.958Z`, and the citizen's own transcript carrying `mcp__entwurf_bridge_entwurf_inbox_read` for its own garden id. **D3 is PROVEN, not pending**: with two live omp citizens armed, one addressed enqueue rang exactly one doorbell and the sibling persisted no transcript and kept an empty mailbox. D7 is PARTIAL (`lastReadAt` needs no scraping; the reply does). D8 is PARTIAL — dedupe and every stale-handling path are implemented and hermetically pinned, ordering/loop-guard/crash-recovery are not. The `/new` unarm is the rail-specific one: the watch lives in the operator's TUI, so pid + start-key cannot see a citizen change underneath a living process, and without an explicit unarm the previous garden id would keep reading deliverable. Requires `tools: xdev: false` in `~/.omp/agent/config.yml` — the vendor default hides MCP tool schemas from the prompt, so the doorbell would name a tool the model cannot call. The decisive receipt lines — the ordering probe, the D6 chain, the D3 isolation and the `/new` unarm — are pasted into `scripts/raw-omp-measure/README.md` §M7 rather than left in a host-local `/tmp` path. Evidence level L4: one Linux host, ARM. **Visible fresh (step 9) is ACCEPTED — the clause 7 LIVE went green on 2026-08-30:** `entwurf_fresh_call` opens omp on all three public surfaces through the bare `omp` runtime with an explicit `--approval-mode yolo` width and the `mcp__entwurf_bridge_entwurf_v` callback name, behind a five-axis pre-mutation preflight whose fifth axis is omp-specific (`tools.xdev !== true`, without which the model cannot call the callback tool at all). **The first turn is a TWO-STAGE BOOTSTRAP rather than a positional prompt, and that is a measured correction, not a preference.** `[LIVE 2026-08-30]` the positional-prompt candidate opened its window and minted its citizen (garden `20260830T181342-452167`, native `01a051f2-3107-7147-8806-fa2a6f527610`), delivered the byte-identical framing as a user message at `09:13:42.413Z`, and the model answered the literal text `ACK` at `09:13:47.105Z` with ZERO tool calls; the caller timed out at 240s. `[source]` the interactive UI defers MCP discovery (`sdk.ts:1847-1855`, `:1881-1905`) while the positional `initialMessage` prompts straight after `mode.init()` (`main.ts:540-565`), and `[측정]` an observer on the same runtime saw `turn_start` at +654ms with the entwurf tools absent and the callback tool present only at +1484ms. So the launcher now carries `{v,target,nonce,task}` on the fixed registered flag `--entwurf-bootstrap`, and the in-process birth extension polls `getAllTools`(`source:"mcp"`) AND `getActiveTools` for the exact callback name, sends a callback-ONLY prompt, arms the task only on a `tool_result` whose stored `toolCallId`, tool name, target, nonce and `isError === false` all match, and DELIVERS it at the next `turn_end` of that same session. `[LIVE 2026-08-30]` that last boundary is itself a measured correction: a first attempt sent the task from inside the `tool_result` handler with an explicit `deliverAs: "followUp"`, the hook log showed the full chain (`bootstrap-armed` → `bootstrap-ready` +440ms → `bootstrap-callback-observed` → `bootstrap-released`), and the task still never appeared in the session — `[source]` an explicit `deliverAs` queues without starting a turn in either state, while the omitted form starts one when idle (`agent-session.ts:6511-6513`), which the same transcript confirmed three seconds later when the Bundle B doorbell's omitted-option send landed and started a turn. `[측정 2026-08-30]` the callback-only half is what was proven to work: model `openai-codex/gpt-5.6-sol`, tool live at +1105ms, prompt injected at +1107ms, and the sibling calling `mcp__entwurf_bridge_entwurf_v` with the exact nonce (`omp-cb-btkvva4r87` → `20260830T184054-1aa1f2`, `meta-mailbox → enqueued`). **The clause 7 acceptance, `smoke-omp-fresh-live` (release-gate MUST), 2026-08-30, 21 assertions, omp 18.0.0 / `openai-codex/gpt-5.6-sol`:** launch through `tools/call entwurf_fresh_call` with nonce `mux-fresh-call-34faea228f3c3638684b40ff`; sibling garden `20260830T192913-df52b9` taken from the CALLBACK's sender envelope and never from the launch receipt; exactly one new citizen (§3.5); addressed `entwurf_v2` → `meta-mailbox → enqueued`; `lastEnqueuedAt 10:29:19.179Z` / `lastReadAt 10:29:24.673Z`; the drain visible in that session's own transcript for its own garden id. **Both bootstrap stages are in that transcript in order** — the callback-only prompt at offset 970, the caller's task at 4732, no four-backend positional framing anywhere, and an assistant message after the task proving it started a turn rather than sitting in a queue. The unit's own log carries the state machine: `bootstrap-armed 10:29:13.399Z` → `bootstrap-ready 10:29:13.819Z` (+420ms) → `bootstrap-callback-observed 10:29:18.663Z` (`toolCallId=call_KZJtkxfzy1IEE4ejKutCPWcm|fc_0858…`) → `bootstrap-released 10:29:18.731Z` → `bootstrap-task-sent 10:29:18.759Z`. Evidence level L4: one Linux host, ARM, one run. `check-harness-admission-parity` keeps the deterministic half of the admission from being a matter of memory. What this does NOT establish: multi-host, multi-model, or repeated fresh calls in one process. **Cross-harness leg, 2026-08-31 (first bidirectional live-turn roundtrip on the committed bytes + operator redeploy):** a claude-code citizen (`20260831T090152-f998ac`) opened a fresh omp sibling through the public surface (nonce `mux-fresh-call-807cb693b1913ce98ffdbfd1`, callback sender garden `20260831T124226-eac41a`), dispatched an addressed `entwurf_v2` → `meta-mailbox → enqueued`, and the omp citizen's own live turn drained and replied into the claude mailbox — its self-report (doorbell → `entwurf_inbox_read`; callback-only first user message, task second) agrees with every receipt on the chain. |
|
|
@@ -130,64 +130,336 @@ the pid/start-key sender marker would be last-writer-wins. Current operator chec
|
|
|
130
130
|
in [BASELINE.md](./BASELINE.md); deterministic ownership and sender gates run in
|
|
131
131
|
`pnpm run check:full`.
|
|
132
132
|
|
|
133
|
-
### Codex:
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
133
|
+
### Codex: one app-server-backed native-push shape
|
|
134
|
+
|
|
135
|
+
Codex support is deliberately narrower than “drive Codex” and ships that way in
|
|
136
|
+
**0.21.0**. Its purpose is to keep the operator's real Codex session —
|
|
137
|
+
native tools, delegation, auth, transcript, and work context — addressable through
|
|
138
|
+
the app-server-backed shape measured at Codex CLI **0.153.4**. It is not ACP and does
|
|
139
|
+
not duplicate GPT access:
|
|
140
|
+
|
|
141
|
+
```text
|
|
142
|
+
operator starts app-server in existing exact tmux session `codex`
|
|
143
|
+
→ its configured MCP env_vars forward that home coordinate and explicit roots
|
|
144
|
+
→ visible codex TUI attaches with --remote unix://<default socket>
|
|
145
|
+
→ first turn runs the vendor-trusted user-scope SessionStart birth
|
|
146
|
+
→ V3 record(nativeSessionId = threadId)
|
|
147
|
+
→ thread/name/set(gardenId)
|
|
148
|
+
→ MCP tools/call carries strict request metadata
|
|
149
|
+
→ entwurf_self / entwurf_v2 resolve that exact record
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
The standalone embedded TUI remains outside this rail: the 2026-09-08 measurement
|
|
153
|
+
found no idle receive route equivalent to the app-server. `turn/steer` is active-turn
|
|
154
|
+
steering, not idle wake. Entwurf does not start, stop, supervise, or health-loop the
|
|
155
|
+
app-server. The operator starts it in a tmux session **of their own choosing**:
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
# Run from a pane in the operator-owned tmux session that will hold the app-server.
|
|
159
|
+
# For the LIVE acceptance that session must NOT be the one the Pi/Codex pair runs in.
|
|
160
|
+
entwurf codex-app-server
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
That verb owns the SPELLING of one vendor command and nothing else — it `exec`s
|
|
164
|
+
`codex app-server --listen "unix://$CODEX_HOME/app-server-control/app-server-control.sock"`
|
|
165
|
+
in the terminal it was typed in, after creating the control directory that address lives in.
|
|
166
|
+
It resolves the socket through the same leaf every other Codex surface reads, so the address a
|
|
167
|
+
consumer gets cannot drift from the one delivery looks for. There is no supervisor, no restart,
|
|
168
|
+
no daemon and no pid file: Ctrl-C is the operator's. A live socket, an unidentifiable one, or a
|
|
169
|
+
second `--listen` are named refusals; a dead socket file is reported and launched over. Passing
|
|
170
|
+
the raw vendor command by hand remains equivalent and is not deprecated.
|
|
171
|
+
|
|
172
|
+
#95 D1 (GLG, 2026-09-16) retired the requirement that this session be named `codex`, and with it the
|
|
173
|
+
rule that an omitted-placement Codex TARGET selected it. The operator still owns the app-server and
|
|
174
|
+
still chooses its room; Entwurf neither creates nor supervises it, and a missing app-server rejects.
|
|
175
|
+
|
|
176
|
+
Since #95 lane B the outbound direction no longer rides the app-server's inherited
|
|
177
|
+
`TMUX`/`TMUX_PANE`: a Codex CALLER with no explicit placement opens its sibling beside its own
|
|
178
|
+
pane, found by matching the caller's `_meta.threadId` against the `thread-id` the TUI writes
|
|
179
|
+
into that pane's title. Zero matching panes (`codex-caller-seat-unresolved`), two or more
|
|
180
|
+
(`codex-caller-seat-ambiguous`) and a caller whose `[tui].terminal_title` lacks `thread-id`
|
|
181
|
+
(`codex-caller-title-missing`) are all named refusals with no fallback seat. An attached TUI
|
|
182
|
+
still does not lend its pane to the server, and N arbitrary clients whose threads nobody named
|
|
183
|
+
still have no adjacency claim: the anchor resolves only the pane displaying the thread the
|
|
184
|
+
caller itself put on the request.
|
|
185
|
+
|
|
186
|
+
The seat order, for all five backends, and it follows the CALLER rather than what is being
|
|
187
|
+
opened: explicit `placement` wins; then a Codex CALLER's own pane (`codex-title-anchor`, no
|
|
188
|
+
session name on the receipt because a session was observed rather than requested); then the
|
|
189
|
+
caller's own session.
|
|
190
|
+
|
|
191
|
+
The DIRECTORY follows the caller the same way (#95 lane C, 2026-09-16): requested `cwd` wins;
|
|
192
|
+
then a Codex CALLER's own RECORD cwd, because this bridge is the app-server's MCP child and its
|
|
193
|
+
process directory is the app-server's rather than that caller's; then the launching process's
|
|
194
|
+
own, which is what tmux gives a window opened with no `-c`. Codex alone also carries that one
|
|
195
|
+
value into its argv as `-C <dir>`, and omitting it is a wrong answer rather than a neutral one:
|
|
196
|
+
an explicit `--remote` target takes its new thread's cwd from that override ALONE
|
|
197
|
+
(`codex-rs/tui/src/app_server_session.rs:2022-2033` at rust-v0.153.4), so without it the THREAD
|
|
198
|
+
opens in the app-server's repo while its pane sits elsewhere — measured on 2026-09-16 as three
|
|
199
|
+
citizens of one chain recording a directory none of them was in. The receipt names which rule
|
|
200
|
+
chose the directory (`requested` / the Codex caller's own record directory) and invents nothing
|
|
201
|
+
for the inherited case.
|
|
202
|
+
|
|
203
|
+
Four ownership atoms remain separate:
|
|
204
|
+
|
|
205
|
+
1. `entwurf install-codex-birth` owns `$CODEX_HOME/hooks.json` — one whole file, ours or
|
|
206
|
+
absent — plus its launcher and import closure under `$XDG_DATA_HOME/entwurf/codex-birth`.
|
|
207
|
+
No root: every path belongs to the operator. The vendor gates a user-layer declaration on
|
|
208
|
+
ONE interactive "Trust all", which entwurf never answers, pre-seeds or computes; the
|
|
209
|
+
receipt is read as its own doctor axis, and until it exists setup is honestly non-green.
|
|
210
|
+
2. `entwurf install-codex-mcp` owns `[mcp_servers.entwurf-bridge]` in
|
|
211
|
+
`$CODEX_HOME/config.toml`, including exact `env_vars` forwarding for `CODEX_HOME`,
|
|
212
|
+
Entwurf garden/control roots, and `TMUX`/`TMUX_PANE`. This explicit name boundary
|
|
213
|
+
keeps custom roots and the app-server seat intact without storing their values.
|
|
214
|
+
3. `entwurf install-codex-statusline` owns only `thread-title` within
|
|
215
|
+
`tui.status_line`. Birth calls `thread/name/set`, so the visible title is the garden id.
|
|
216
|
+
4. `entwurf install-codex-terminal-title` owns only `thread-id` within `tui.terminal_title`
|
|
217
|
+
— a different key and a different axis from atom 3: `status_line` is what a human reads
|
|
218
|
+
inside the TUI, `terminal_title` is what the multiplexer reports back as `#{pane_title}`
|
|
219
|
+
and is the only value a caller seat can be matched against. The seeded list is
|
|
220
|
+
`["activity", "project-name", "thread-id"]` (`activity` leads because the herdr Codex
|
|
221
|
+
detector keys on the spinner/action-required prefix) and an existing operator list is
|
|
222
|
+
appended to, never reordered. A tmux server with `allow-set-title off` replaces every pane
|
|
223
|
+
title with the hostname, so the seat refuses there even with the atom installed — that is
|
|
224
|
+
a repair condition the refusal names, not an inference this rail makes.
|
|
225
|
+
|
|
226
|
+
All four have state-backed doctors and inverses. Symlinked or foreign config is a
|
|
227
|
+
named refusal, not an adoption. Entwurf never installs Codex or its credentials.
|
|
228
|
+
|
|
229
|
+
Sender identity is request-scoped. The bridge requires the complete Codex metadata
|
|
230
|
+
tuple — `_meta.threadId`, `_meta.x-codex-turn-metadata.session_id`, and
|
|
231
|
+
`_meta.x-codex-turn-metadata.thread_id` — to agree, then joins that native id through
|
|
232
|
+
the addressable V3 record reader. Missing or conflicting fields refuse; there is no
|
|
233
|
+
parent-pid fallback. A complete pi env claim or other native claim must also agree.
|
|
234
|
+
This is load-bearing because every attached TUI shares the app-server ancestry.
|
|
235
|
+
|
|
236
|
+
The native-push adapter probes `thread/loaded/list`. A missing socket, malformed
|
|
237
|
+
handshake, protocol failure, or absent loaded target is `native-push-probe-indeterminate`
|
|
238
|
+
or dead as defined by the probe result; no mailbox fallback exists. Delivery uses the
|
|
239
|
+
measured one-shot `codex queue` command. Unlike Antigravity, Codex delivery has **zero
|
|
240
|
+
retry**: losing stdout after vendor acceptance must not replay the user's message.
|
|
241
|
+
|
|
242
|
+
Direct injection carries the **mailbox-serialized trusted sender envelope**, not the raw
|
|
243
|
+
message. This rail has neither the control socket's RPC framing nor a mailbox file, so the
|
|
244
|
+
envelope rides in the body through the same `formatMetaMailboxBody` SSOT the mailbox rail
|
|
245
|
+
uses — one rail for both native-push backends, no per-backend branch. It is rendered once,
|
|
246
|
+
before delivery, so Antigravity's one permitted re-probe retry replays byte-identical
|
|
247
|
+
content. A caller with no authoritative sender still injects the raw message; an envelope is
|
|
248
|
+
never fabricated. #95 measured the cost of the old raw behaviour: a fresh sibling's
|
|
249
|
+
nonce-only callback landed in a Codex thread as bare text, so the Codex citizen could not
|
|
250
|
+
name its caller and the callback was uncorrelatable.
|
|
251
|
+
|
|
252
|
+
Visible fresh runs:
|
|
253
|
+
|
|
254
|
+
```text
|
|
255
|
+
operator-owned tmux session A (any name — the operator seats it)
|
|
256
|
+
operator-owned app-server + supported Codex TUIs
|
|
257
|
+
codex --remote unix://<default socket> -C <launch directory> --model <explicit model>
|
|
258
|
+
--dangerously-bypass-approvals-and-sandbox <callback-first prompt>
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
With `placement` omitted the seat follows the CALLER: a Codex citizen's own TUI pane, resolved from
|
|
262
|
+
the `thread-id` in that pane's title to a native `$id` before mutation, with 0 or 2+ matches refused
|
|
263
|
+
and no fallback; every other caller keeps caller-session default placement. An explicit seat remains
|
|
264
|
+
an expert override. The preflight must certify the state-backed birth closure digests, vendor trust
|
|
265
|
+
receipt, exact MCP/env boundary, `thread-title`, `terminal_title`, app-server socket, and a narrow LOCAL
|
|
266
|
+
read of the LAUNCH DIRECTORY's folder consent before tmux mutation — a guard on the cases the user
|
|
267
|
+
config decides, not a certification of the vendor's verdict. That last axis is the vendor's, not ours:
|
|
268
|
+
`[source rust-v0.153.4]` a `--remote` startup always runs `check_directory_trust` on the `-C` value
|
|
269
|
+
(`tui/src/lib.rs:1699-1725`) and nothing on that path reads the approval or sandbox policy
|
|
270
|
+
(`tui/src/onboarding/directory_trust.rs:33-130`), so
|
|
271
|
+
`--dangerously-bypass-approvals-and-sandbox` does not cover it — approvals and folder consent are
|
|
272
|
+
two different gates. A DIRECT decision is keyed to the exact directory: for `ProjectTrustHost::Remote` that lookup is
|
|
273
|
+
`vec![cwd_key]` alone (`tui/src/config_update.rs:290-296`), with no project-root marker, git root or
|
|
274
|
+
parent inheritance. An UNDECIDED directory renders a consent screen, and a TUI waiting on one has started no turn —
|
|
275
|
+
no rollout, no birth, no callback. Entwurf NOTES that as `codex-launch-cwd-undecided` and opens the
|
|
276
|
+
window anyway: the screen is self-repairing for the human this rail exists to put a window in front
|
|
277
|
+
of, and one answer teaches the vendor that directory for good. The unattended case is answered
|
|
278
|
+
where it belongs — `smoke-codex-fresh-live` asserts the same leaf up front, so a gate with nobody
|
|
279
|
+
at the keyboard reads a named precondition instead of a callback timeout. A directory the operator deliberately answered `untrusted`
|
|
280
|
+
is NOT refused: on a remote target the vendor skips that screen
|
|
281
|
+
(`onboarding/directory_trust.rs:94-96`; `uses_remote_workspace()` is `matches!(self, Self::Remote
|
|
282
|
+
{ .. })` at `tui/src/lib.rs:307-309`), so the turn starts and refusing it would be entwurf
|
|
283
|
+
inventing a policy the vendor does not have. A cwd INSIDE an explicitly `untrusted` project is a
|
|
284
|
+
third answer with its own reason, `codex-launch-cwd-untrusted-ancestor`: there the vendor returns
|
|
285
|
+
`pass the repository root explicitly with --cd` (`config_update.rs:357-371`) rather than a screen,
|
|
286
|
+
so answering a prompt at the child would only reproduce that error.
|
|
287
|
+
|
|
288
|
+
**The preflight leaf is narrower than the vendor's decision and does not claim otherwise.** It
|
|
289
|
+
reads one TOML file while the vendor reads a layered config through its app-server, where an
|
|
290
|
+
enabled project layer can consent with no entry at all (`config_update.rs:346-354`). Every case the
|
|
291
|
+
leaf cannot see resolves to "proceed", so it may fail to catch a hang but never refuses a launch
|
|
292
|
+
the vendor would have run. The callback spelling is `mcp__entwurf_bridge__entwurf_v2`; the new garden id
|
|
293
|
+
comes only from its sender envelope. There is no Codex resume, watcher, session/app-server creator,
|
|
294
|
+
or lifecycle supervisor.
|
|
295
|
+
|
|
296
|
+
The 2026-09-11 Linux run used Codex 0.153.4 and the default app-server: the production
|
|
297
|
+
probe found loaded thread `01a08bff-4efa-7071-9cac-b6d29da5f126`; native-push and a
|
|
298
|
+
public MCP `entwurf_v2` call woke its visible TUI; a real authenticated request returned
|
|
299
|
+
`agentId=meta-session/codex`, `replyable=true`; and a source birth hook minted garden
|
|
300
|
+
`20260911T005221-fc7c47` in an isolated store. Those receipts are preserved as
|
|
301
|
+
**pre-amendment focused delivery/identity evidence**, not qualification of the current
|
|
302
|
+
candidate.
|
|
303
|
+
|
|
304
|
+
The amended same-session acceptance (**A**) passed on local candidate `6e28c9e` at Codex
|
|
305
|
+
0.153.4. Receipt `.probe-artifacts/a95-live-20260911T162152-6e28c9e.log` (SHA-256
|
|
306
|
+
`e159f8fd1cf23cb1abd7782dc9e24cf9604add6b61ae24b7fd5260f16dfc2795`) records 50
|
|
307
|
+
assertions and exit 0: real initial Pi `20260911T162155-0db222` opened and addressed Codex
|
|
308
|
+
`20260911T162210-a974fe` / thread `01a08f58-588b-7620-a67c-cc0f6c62a79e`; Codex then
|
|
309
|
+
opened outbound Pi `20260911T162238-7dcdaa` and correlated its exact callback nonce and
|
|
310
|
+
sender garden id. The operator app-server, initial Pi, Codex, and outbound Pi all resolved to
|
|
311
|
+
tmux session `$158`. Cleanup removed only smoke windows `@355`, `@356`, and `@357`,
|
|
312
|
+
preserved all three records/transcripts, and left operator app-server PID `155166` and
|
|
313
|
+
`$158/@351/%351` alive.
|
|
314
|
+
|
|
315
|
+
That receipt established the mechanism of the now-selected deployment, but its initial Pi also sat
|
|
316
|
+
in the app-server session and predates the fixed-home default. The stronger explicit-home acceptance
|
|
317
|
+
passed on 2026-09-12, under the `codex` home topology #95 D1 later retired. Receipt
|
|
318
|
+
`.probe-artifacts/20260912T140745-codex-home-live-green.log`
|
|
319
|
+
(SHA-256 `09e79bd1b62962f8a11d647ee456a71b11965b6792c7972d97ac4992119c91d7`)
|
|
320
|
+
records 57 assertions and exit 0. The operator app-server stayed at `$158/@390/%390`; real initial Pi
|
|
321
|
+
`20260912T140748-355654` opened outside the home at `$150/@397`, omitted-placement Codex
|
|
322
|
+
`20260912T140800-8bc8d9` / thread `01a09403-e232-76b0-af9a-5cbaed8d94a9` opened at `$158/@398`,
|
|
323
|
+
and Codex opened outbound Pi `20260912T140829-a08178` at `$158/@399`. The callbacks preserved exact
|
|
324
|
+
nonces `mux-fresh-call-5d28f8e5bc2acf275ded30ec` and
|
|
325
|
+
`mux-fresh-call-7a5fb4960dbb172843eb14fe`; initial Pi → Codex reported
|
|
326
|
+
`entwurf_v2 native-push → delivered`, Codex read back its live garden-id title through `thread/read`,
|
|
327
|
+
and every smoke-owned window was removed while the operator app-server remained alive.
|
|
328
|
+
|
|
329
|
+
Two red attempts tightened the acceptance rather than weakening it. The first reached correct home
|
|
330
|
+
placement but Codex interpreted “wait” as `wait_agent(timeout_ms=3600000)`, leaving its first turn
|
|
331
|
+
active; the prompt now requires ending the turn and forbids every wait tool. The second proved that a
|
|
332
|
+
model may reformat a receipt while copying it. That accepted run still travelled coordinate reports
|
|
333
|
+
between citizens and checked them against Pi/Codex source results. A later prepare run exposed the
|
|
334
|
+
remaining flaw by truncating a report token: the amended gate removes intermediate model reports,
|
|
335
|
+
joins exact Pi toolCall/toolResult rows and structured Codex `thread/read` MCP items directly, and
|
|
336
|
+
reads garden ids only from raw callback events. Failure cleanup recovers the exact Codex thread from
|
|
337
|
+
its nonce callback, interrupts only its still-running smoke-owned turn, and closes only windows named
|
|
338
|
+
by joined source fresh-call results.
|
|
339
|
+
|
|
340
|
+
The amendment's own standalone acceptance then passed on 2026-09-12 (Codex 0.153.4): **48 assertions,
|
|
341
|
+
exit 0**, final source audit `initial-pi=3/3 completed exact` and `codex=3/3 completed exact`. Fixture
|
|
342
|
+
`20260912T232054-14c8e8` at `$150/@430`; initial Pi `20260912T232056-c0be9e` at `$150/@431`;
|
|
343
|
+
operator-owned app-server `1693273` at `$158/@390/%390`; omitted-placement Codex `20260912T232110-1cd889`
|
|
344
|
+
(thread `01a095fe-4f1a-7d93-8c5a-ed7539cf8930`) at `$158/@432`; Codex-opened Pi `20260912T232133-4ac684`
|
|
345
|
+
at `$158/@433`; final token `CODEX-PI-FINAL-6QWDSELJ` carried `PI_CALLBACK_FROM=20260912T232133-4ac684`,
|
|
346
|
+
`PI_SESSION_ID=$158`, `PI_WINDOW_ID=@433` into the fixture mailbox, which read it. Cleanup reclaimed
|
|
347
|
+
`@433`, `@432`, `@431` — every one named by a joined source fresh-call result, with no tmux inventory scan
|
|
348
|
+
and no mailbox prose promoted to authority. Artifact `.probe-artifacts/codex-fresh-live-fZccoK/`
|
|
349
|
+
(`run-manifest.json` sha256 `05f20f00…`). The 57-assertion first-admission receipt above is preserved as
|
|
350
|
+
its own pre-amendment axis; the two counts are different contracts, not a regression.
|
|
351
|
+
|
|
352
|
+
That run also closed a defect the amendment had introduced. A source path read once at callback
|
|
353
|
+
correlation froze out a record that gained `transcriptPath` 34s later, so the observer saw nothing while
|
|
354
|
+
the chain actually completed — the preceding red run's Codex thread holds a completed final `entwurf_v2`
|
|
355
|
+
result naming `PI_WINDOW_ID=@426`, and its two orphan windows were reclaimed only after their own joined
|
|
356
|
+
source receipts named them (`@425` backend codex from the initial Pi, `@426` backend pi from the Codex
|
|
357
|
+
thread; cleanup log preserved at `.probe-artifacts/codex-fresh-live-FblYLs/source-authorized-cleanup.log`,
|
|
358
|
+
sha256 `07fe18fc…`, alongside `run-manifest.json` sha256 `62a538fd…`). The path is now re-read while the
|
|
359
|
+
cache is empty. Note honestly what the green run does and does not prove: its manifest carries neither
|
|
360
|
+
`initialPiTranscriptResolvedLate` nor `sourcePathUnresolved`, so the late-write timing did not recur and
|
|
361
|
+
the repair is proven by its deterministic claim, not by this LIVE.
|
|
362
|
+
|
|
363
|
+
**Repeat acceptance inside the aggregate release gate (2026-09-13).** The same acceptance ran again as
|
|
364
|
+
the `smoke-codex-fresh-live` MUST step of `release-gate --cut` and passed at 48 assertions: fixture
|
|
365
|
+
`20260913T065136-59d143` at `$187/@442`, initial Pi `20260913T065138-ad5f57` at `$187/@447`,
|
|
366
|
+
omitted-placement Codex `20260913T065151-4b6078` (thread `01a0979a-edc4-7570-a29b-50f7e48cf298`) at
|
|
367
|
+
`$158/@448`, Codex-opened Pi `20260913T065213-0811e6` at `$158/@449`, against the same operator-owned
|
|
368
|
+
app-server at `$158/@390/%390`. Artifact `.probe-artifacts/codex-fresh-live-2oId4C/` (`run-manifest.json`
|
|
369
|
+
sha256 `2cff6f08…`). Note the fixture seat differs from the standalone run: the aggregate builds its own
|
|
370
|
+
tmux session (`$187`), while the Codex legs resolved to the exact `codex` home that was the contract
|
|
371
|
+
at the time. That gate reported
|
|
372
|
+
MUST PASS=24 FAIL=0 SKIP=0 and `cut: OK`. Keep the three Codex acceptances apart — 57-assertion
|
|
373
|
+
pre-amendment first admission, 48-assertion standalone amended (`fZccoK`), and this 48-assertion
|
|
374
|
+
aggregate repeat (`2oId4C`).
|
|
375
|
+
|
|
376
|
+
An earlier attempt at the identical source fingerprint failed two model-in-loop MUST steps and is kept
|
|
377
|
+
as an observation rather than a defect: a callback nonce arrived one character short and an addressed
|
|
378
|
+
instruction carried the wrong payload. Joined source receipts showed target, rail, and delivery were all
|
|
379
|
+
correct, so both oracles refused for the right reason and nothing in the product was changed.
|
|
380
|
+
|
|
381
|
+
**Caller-seat acceptance (#95 lane B), 2026-09-16, Codex 0.153.4 — 56 assertions, exit 0.** This is the
|
|
382
|
+
receipt for the topology that replaced the fixed home: `ENTWURF_CODEX_FRESH_MODEL=gpt-5.6-sol`,
|
|
383
|
+
`ENTWURF_CODEX_FRESH_PI_MODEL=openai-codex/gpt-5.6-luna`, final source audit `codex=3/3 completed exact`.
|
|
384
|
+
On one tmux server (`36728`) the operator-owned app-server `737636` stayed in ITS OWN session
|
|
385
|
+
A = `$30`/`@41`/`%45`, while all three smoke citizens opened in S = `$2`: initial Pi
|
|
386
|
+
`20260916T144205-e876ff` at `@46`, omitted-placement Codex `20260916T144230-d050d7` at `@47`, and the
|
|
387
|
+
Codex-opened outbound Pi at `@48`. **A ≠ S is what makes the run decisive rather than merely green:**
|
|
388
|
+
the app-server's inherited `TMUX` names A, so the pre-#95 environment fallback would have put that
|
|
389
|
+
outbound Pi there. It landed in S, and its receipt names the rule that chose the seat —
|
|
390
|
+
`seat: $2 (the Codex caller's own pane, found by its thread-id terminal title — an OBSERVED session,
|
|
391
|
+
not a requested name)`, recorded as `seat-source=codex-title-anchor`. Artifact
|
|
392
|
+
`.probe-artifacts/codex-fresh-live-nYcGC1/`, stdout preserved at `run-stdout.log`
|
|
393
|
+
(SHA-256 `ed60c2bdb46c13c51bf1d2dcf147b88c3c9f368a86a2bf17e972d3ecfde5fde9`). Cleanup reclaimed exactly
|
|
394
|
+
`@46`, `@47`, `@48` with no CLEANUP FAILURE, preserved every born record and transcript, and left the
|
|
395
|
+
app-server and `$30` untouched.
|
|
396
|
+
|
|
397
|
+
**Caller-directory acceptance (#95 lane C), 2026-09-16, Codex 0.153.4 — 65 assertions, exit 0.** Same
|
|
398
|
+
host, same models, same four-coordinate topology (app-server `737636` in A = `$30`/`@41`/`%45`; initial
|
|
399
|
+
Pi `20260916T154902-556eb5` at `$2`/`@58`, omitted-placement Codex `20260916T155037-10ddaa` at `$2`/`@59`,
|
|
400
|
+
Codex-opened outbound Pi `20260916T155102-9add8a` at `$2`/`@61` with `seat-source=codex-title-anchor`),
|
|
401
|
+
final source audit `initial-pi=3/3` and `codex=3/3 completed exact`. **65 and 56 are different
|
|
402
|
+
contracts, not a regression:** lane C added the cwd axis (seven assertions) and the pane-directory
|
|
403
|
+
reader it needs, on top of everything lane B already asserted.
|
|
404
|
+
|
|
405
|
+
The two decisive receipts, both measured against the app-server's own live directory
|
|
406
|
+
`/home/junghan/repos/gh/entwurf` (read from `/proc/737636/cwd`):
|
|
407
|
+
|
|
408
|
+
- **hop 1, cwd REQUESTED** (`8b-codex-thread-cwd`): the fresh Codex's pane `#{pane_current_path}`, the
|
|
409
|
+
vendor's own rollout `session_meta.cwd`, its Entwurf record and the requested scratch are ONE
|
|
410
|
+
directory — `/tmp/entwurf-codex-fresh-live-db65N2` — and it is not the app-server's. Four authorities
|
|
411
|
+
that cannot borrow from each other; before `-C` the rollout carried the app-server's path while the
|
|
412
|
+
pane sat in the scratch.
|
|
413
|
+
- **hop 2, cwd NOT REQUESTED** (`13b-outbound-pi-cwd`): the leg named neither placement nor cwd, and the
|
|
414
|
+
outbound Pi still opened in `/tmp/entwurf-codex-fresh-live-db65N2` — its pane, its own birth-written
|
|
415
|
+
record, and the Codex caller's record all agree. Its launch receipt names the rule rather than
|
|
416
|
+
borrowing the other one's noun: `cwd: /tmp/entwurf-codex-fresh-live-db65N2 (the Codex caller's own
|
|
417
|
+
record directory, used because no cwd was requested — not an observation)`, while both requested legs
|
|
418
|
+
still read `requested start directory`.
|
|
419
|
+
|
|
420
|
+
Artifact `.probe-artifacts/codex-fresh-live-w4yJBw/` (run manifest, mailbox observations/selections and
|
|
421
|
+
a 13-file pre-cleanup snapshot including all three records, both Pi transcripts and the Codex rollout);
|
|
422
|
+
stdout preserved at `.probe-artifacts/lane-c-live-20260916T154900.log`
|
|
423
|
+
(SHA-256 `712050e7a8cf03ece98e7f34029ae98a92e9b2a7fd96aff87d0c1e6ba2ee9af2`). Cleanup reclaimed exactly
|
|
424
|
+
`@58`, `@59`, `@61` with no CLEANUP FAILURE, removed its own scratch and fixture record, preserved every
|
|
425
|
+
born citizen record and transcript, and left the app-server and `$30` untouched.
|
|
426
|
+
|
|
427
|
+
Two earlier attempts that day are kept as their own receipts, because each stopped at a different
|
|
428
|
+
truth. The FIRST stopped at 26 assertions, before any window opened: `codex-birth-unit-missing`, because
|
|
429
|
+
`~/.codex/hooks.json` carried a second `SessionStart` entry added after install, so the declaration no
|
|
430
|
+
longer matched its recorded digest. The unit was not broken — entwurf's own atom and all six helper
|
|
431
|
+
digests were intact — but this rail owns that file whole, and the preflight refused rather than run
|
|
432
|
+
against bytes it could not vouch for. The SECOND stopped at 43 assertions with hop 1 already green, and
|
|
433
|
+
its log is kept as the D1 measurement: `.probe-artifacts/codex-fresh-live-4aFCDD/run-stdout.log`
|
|
434
|
+
(SHA-256 `8392a603dcfe7e89549942d55e515f97724398fb261bd8873d25806f71086afe`) carries
|
|
435
|
+
`omitted placement opened fresh Codex in the caller's own session S, away from the app-server's A` —
|
|
436
|
+
the retirement of the fixed home, observed on a real host. It then failed on the gate's own defect
|
|
437
|
+
rather than the product's: the source-call oracle compared arguments with `isDeepStrictEqual`, so a
|
|
438
|
+
model that omitted the optional `wants_reply` instead of passing it explicitly read as drift. That
|
|
439
|
+
oracle now normalizes exactly that key to its schema default and nothing else.
|
|
440
|
+
|
|
441
|
+
Unrestricted attached-TUI parity (**B**) is explicitly outside this support claim. The exact vendor
|
|
442
|
+
checkout `rust-v0.153.4` at `3d2ee51ca2d5db578f328aa75e20aa22c0197c9a` found no public
|
|
443
|
+
request→attached-TUI-seat carrier: process-local `ConnectionId` does not cross into thread/core/MCP/hook
|
|
444
|
+
state, and the TUI-local dynamic task MCP is a closed vendor namespace. That source result now bounds
|
|
445
|
+
the topology instead of blocking the explicit home. Manual pane/process guessing and hidden manager
|
|
446
|
+
behaviour remain invalid; explicit `placement.tmuxSession` is an operator-named expert override, not
|
|
447
|
+
an inferred seat. The gate strips ambient `PI_SESSION_ID`/`PI_AGENT_ID`; a fixture may preserve receipts
|
|
448
|
+
but cannot substitute for the initial visible record-backed Pi turn.
|
|
449
|
+
|
|
450
|
+
Run the clause-7 invocation from a tmux session OTHER than the app-server's own; the explicit app-server PID must belong to the operator-owned app-server, and that session's NAME is not a requirement — #95 D1 retired the fixed `codex` home on 2026-09-16, so A ≠ S is the precondition and no particular name is. Both models are explicit, and the launch directory must already be answered in this Codex (`VERIFY.md` owns the derivation and the one-time `Trust`):
|
|
451
|
+
|
|
452
|
+
```bash
|
|
453
|
+
LIVE=1 \
|
|
454
|
+
ENTWURF_CODEX_APP_SERVER_PID=<existing-app-server-pid> \
|
|
455
|
+
ENTWURF_CODEX_FRESH_MODEL=<codex-model> \
|
|
456
|
+
ENTWURF_CODEX_FRESH_PI_MODEL=<pi-model> \
|
|
457
|
+
./run.sh smoke-codex-fresh-live
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
This is the intended gate entrypoint, not acceptance by command name. The accepted receipt above
|
|
461
|
+
has a fixture only collecting evidence: a real visible record-backed Pi opens Codex from outside the
|
|
462
|
+
home, and the later exact callback and bidirectional delivery receipts close the topology claim.
|
|
191
463
|
|
|
192
464
|
### Copilot CLI: one citizen, two rails, one pending receipt
|
|
193
465
|
|