# Codex stdout EOF — current-head runtime evidence

PR [#12777](https://git.cafe/pingdotgg/t3code/pulls/12777), [GitHub #12777](https://github.com/pingdotgg/t3code/pull/12777).
Before [3cc31ed](https://github.com/pingdotgg/t3code/commit/3cc31ed27c8956b36cee35a50509fb7c6869592b): `3cc31ed27c8956b36cee35a50509fb7c6869592b`.
After [23cee43](https://github.com/pingdotgg/t3code/commit/23cee434441629deae178c9ac9f8ec43c268547f): `23cee434441629deae178c9ac9f8ec43c268547f`.

**All four required runtime rows pass. Six timestamped sessions: A+B combined, C, D, each before/after.**
Final recordings: 2026-10-24 23:31 UTC. Earlier recordings are superseded and are not linked here.

| Row | Before | After | Transcripts |
| --- | --- | --- | --- |
| A: live-child stdout EOF, two received pending IDs | Both pending remain unresolved over 1000 ms observation; PID alive | Both fail with `CodexAppServerInputStreamEndedError`, message `Codex App Server input stream ended.`, at 259.087 / 259.953 ms from child EOF emission; PID alive | A-before / A-after |
| B: delayed real exit after grace | Both eventually fail with code 23 and exact PID | Exit emitted at 265.908 ms after EOF; original pending EOF settlements unchanged; callback count remains one; exit code 23 reaped | Same A-before / A-after |
| C: real exit inside grace | Both fail with code 37 and exact PID; exit emission 100.878 ms after EOF | Both retain process-exit error with code 37 and exact PID; emission 100.805 ms after EOF | C-before / C-after |
| D: ordinary healthy owning-scope close | Initialize + ordinary RPC succeed; child reaped in 13.211 ms | Same success; child reaped in 14.330 ms; no termination callback or escaped EOF failure | D-before / D-after |

A-after also proves request, notify, respond and respondError reject after EOF without adding outgoing wire writes (6 before / 6 after). Pending failures occur while an incoming handler finalizer is blocked. Scope cleanup releases it.

## Method and environment

Linux x86_64, host fs-03, kernel 6.1.102, Node v24.22.1, Effect/@effect/platform-node 4.0.5, test runner v5.0.5. Real subprocess fixture replaces only the Codex executable; production snapshot protocol, `ChildProcessSpawner`, `makeChildStdio`, and `makeTerminationError` are exercised. This is server-only evidence; no provider credentials or running user agents are used.

Every session initializes and completes `x/healthy` before fault/shutdown. Child stderr records request IDs and EOF/exit emissions using `process.hrtime.bigint()`. Timing uses emission timestamps, not delayed parent stderr receipt. A's exact settlement times are recomputed in the observation record from `settledHr` and the child EOF timestamp. Scheduler overhead means these real timings are observations, not an SLA. The 250 ms boundary itself is covered by the snapshot protocol tests.

Source snapshots and regression tests are extracted with `git show` from both full SHAs, hashed in the manifest, and stored outside the checkout. Dependencies are symlinked to the existing package dependencies. No source alterations in either snapshot. The source archive excludes dependency targets.

Reproduce (working directory `/tmp/ev-12777-capture`):

```sh
python3 refresh.py
python3 run.py
python3 verify.py
cd after
vp test run --config /home/ubuntu/wt/pr-12777/vite.config.ts --dir src
```

Snapshot tests: **5 files / 28 tests passed**. Test output is included. The initial omitted-fixture failure is retained separately and superseded by the passing run after extracting the pinned fixture.

Driver PID spawn/reap pairs are in runs.jsonl; each transcript records child spawn, exit/reap or scope close, and dead-child check. summary.json verifies final driver/child PIDs absent and snapshot hashes correct. Known preliminary failed-run child and missing-fixture test PIDs were also checked absent. No process was killed by matching names or paths.

## Scope and limitations

Checkout `/home/ubuntu/wt/pr-12777` remained clean at the requested full after SHA. No edits, checkout switches, pushes, forge comments, or watchers. Only temporary evidence material under `/tmp/ev-12777-capture` changed. T3 PR registration was performed as required bookkeeping; watching is false.

The underlying diff is only protocol EOF classification and two regression tests (two files, 61 insertions / 5 deletions). No other implementation changes were made during capture.

Unverified: actual Codex binary internals, OS signal crash variant (C uses a deliberate nonzero exit), other operating systems, and UI/network surfaces. These are outside the requested server fixture matrix. The fixture uses a real child process but is not an end-to-end live Codex session.

## FRICTION

| Category | Happened | Prevention |
| --- | --- | --- |
| Stale evidence | Existing after snapshot and old C were unsuitable | Refresh exact SHA snapshots, manifest hashes and revision labels; replace C with two pending calls and real ~100 ms exit |
| Harness assertion | Preliminary C used an incorrect error-tag spelling and reached its watchdog after the child was already reaped | Correct tag to `CodexAppServerProcessExitedError`; all final sessions pass |
| Snapshot completeness | First package test run omitted the client mock-peer fixture (26 passed / 2 failed) | Extract pinned test fixtures too; rerun passes all 28 |
| Workspace/upload | None | Keep artifacts external; upload explicitly through ghdrop; verify clean head |

## Downloadable evidence

[driver.ts](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/4651415117b790a6/driver.ts)
[codex](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/d98125816b4fe4e3/codex)
[refresh.py](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/175ce75d61975f6c/refresh.py)
[run.py](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/af6197e04a324c75/run.py)
[verify.py](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/ada2ca09d8ab2b75/verify.py)
[A-before.jsonl](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/c8d4942758d3173d/A-before.jsonl)
[A-after.jsonl](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/8701f73fc5489905/A-after.jsonl)
[C-before.jsonl](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/08c55efaca1e0041/C-before.jsonl)
[C-after.jsonl](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/80e94b8928921612/C-after.jsonl)
[D-before.jsonl](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/fc816207e62dae72/D-before.jsonl)
[D-after.jsonl](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/6ab9fb3087e77c1f/D-after.jsonl)
[runs.jsonl](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/37a4089c68a0ee31/runs.jsonl)
[summary.json](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/e9f099a9665cb8a1/summary.json)
[tests.txt](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/6a2b95929781a165/tests.txt)
[tests-missing-fixture.txt](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/70e7c2546858c0f3/tests-missing-fixture.txt)
[source-snapshots.tar.gz](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/54acadbab1566980/source-snapshots.tar.gz)
[matrix.md](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/d14425d18d2bbff5/matrix.md)

