# Issue 23378 — real Electron evidence

[Issue #23378](https://git.cafe/pingdotgg/t3code/issues/23378). Base [e54e71d725](https://git.cafe/pingdotgg/t3code/commit/e54e71d725); reviewed implementation [c3dd6959fb](https://git.cafe/pingdotgg/t3code/commit/c3dd6959fb); captured head `e38f845adb` (local-only fixture commit). The final commit adds only the reusable synthetic fixture; implementation unchanged. No PR, push, issue comment or other forge write.

Real Linux Electron 44.9.3, dev app 0.1.1, launched through headless-desktop and vp run dev:desktop with --no-sandbox --disable-gpu. Full 1920×1080 Xvfb surface, light theme, same fixed environment ID/data/config, 10 fps X11 video. No browser automation, provider turns, mocked authentication, crop, or product test hook. DevTools windows were unmapped with xdotool. No credentials or copied conversations are in published evidence. Only schema/migration markers were copied into a fresh database; the committed seeder creates one synthetic project and one stopped thread, with zero messages. Isolated state never points at live userdata. Source schema carries three newer migration markers (68–70); both revisions log the same benign skip warning. A clean initialized branch database also works with the committed seeder.

Times below are video elapsed, starting within 0.13 s of backend-ready. A fresh Electron process and fresh isolated home were used for every run. SIGSTOP is sent immediately at ready to the port owner, after checking its cwd and membership in the owned process tree. Resume is measured from ready. Timing files and auth spans in the audit archive provide launch-relative and absolute Unix-nanosecond correlation. Video transition times use two fixed pixel markers, checked against the screenshots, at 0.1 s resolution; these are observed timings, not cross-machine performance promises.

## Matrix results

| Row | Result | Recording |
| --- | --- | --- |
| 1 healthy base | Auth success 36.183 ms; authenticated shell at video 20.6 s (seeded project content settles later), no fatal | [base-healthy.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/57c319b895e76399/base-healthy.mp4) |
| 1 healthy head | Auth success 56.178 ms; authenticated shell at 24.5 s (seeded project content settles later), no fatal; no compulsory 60 s auth delay | [head-healthy.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/5e1d71093f33031e/head-healthy.mp4) |
| 2 base stopped 30 s | First bearer fails after 15007.946 ms; exact fatal fetch-session-state HTTP 500 visible 21.3–40.5 s. Resume at ready+30.256 s. A second bearer succeeds; UI subsequently recovers automatically at 40.6 s without a click. | [base-stall30.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/19d263f2623778f0/base-stall30.mp4) |
| 2 head stopped 30 s | One bearer succeeds after 22275.293 ms; no fatal frame; resumes at ready+30 s and reaches the authenticated shell at 42.0 s (seeded project content settles later), without Reload/Try again | [head-stall30.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/8583b2c1c6ee74b8/head-stall30.mp4) |
| 3 head stopped 85 s | First bearer fails after 60013.950 ms; fatal visible 65.7–85.3 s. Resume at ready+85.262 s, visible Reload app clicked 105 ms later at (830,444), then splash and authenticated shell at 99.0 s (seeded project content settles later). Same Electron process; one main-window launch, no development rebuild. | [head-stall85.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/f4579e970b02ff18/head-stall85.mp4) |
| 4 focused tests | Head: 4/4 pass. Head regression copied into disposable base worktree: new 30 s case fails with 15 s TimeoutError, existing 3 controls pass. Original test file restored before captures. | [focused-tests.txt](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/a83c7470b149c75c/focused-tests.txt) |

The project view displays “Launch recovery demo” and persisted stopped thread “Verify desktop startup recovery” in its sidebar, plus the connected primary environment. No provider execution is necessary.

## Healthy before/after

Fresh launches, backend responsive throughout. Both final stills were captured at ready+40 s after the authenticated UI settled. **Before: base. After: head.** No visible differences: all 2,073,600 pixels identical. diff0 = 0; threshold difference = 0.

![Before: base healthy authenticated project view](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/d076f375c8aec4aa/base-healthy-final.png)

![After: head healthy authenticated project view](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/a08eaa758e267377/head-healthy-final.png)

Diff0 is absolute RGB difference amplified ×8 (saturating). Threshold map marks pixels whose maximum RGB channel difference is **>16/255**; no exclusions or masks.

![Healthy diff0 amplified ×8: zero difference](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/4ecf44e999be9b2f/healthy-diff0-x8.png)

![Healthy threshold >16: zero difference](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/f005daa0eb01f9e7/healthy-diff-threshold16.png)

## Stalled before/after at the same video time

Both owned backends stopped at ready and resumed after 30 s. These full frames are at video **25.0 s**, before resume. **Before: base** shows the exact fatal HTTP 500, error report, Try again, Reload app and Copy error. **After: head** remains on the T3 splash with window controls, still awaiting the same bearer exchange. The fatal card/background/error text replaces the splash only on base. diff0: 1,943,084 pixels; >16 threshold: 132,721 pixels (6.4005%).

![Before: base fatal HTTP 500 at 25 seconds](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/bb2e160b589c27a2/base-stall30-at25.png)

![After: head still waiting without fatal at 25 seconds](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/a81f99282c977c3b/head-stall30-at25.png)

![Stall pair diff0 amplified ×8](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/c9df171fe9836a6b/stall25-diff0-x8.png)

![Stall pair threshold >16](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/3fde84c015b2cb1e/stall25-diff-threshold16.png)

Head then reaches the same seeded UI automatically after resume; this still is at ready+65 s. Base also eventually recovers automatically in this fixture, but visibly enters the fatal screen first. This evidence does not claim the base remains fatal indefinitely.

![Head authenticated UI after automatic 30 second stall recovery](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/75d0616e93e11154/head-stall30-final.png)

## Budget exhaustion and Reload recovery

Same head process, backend held 85 s. First bearer timeout is bounded at 60.014 s. **Before:** fatal still at ready+80 s, backend still stopped. At ready+85.262 s resume, then click Reload app 105 ms later. **After:** authenticated seeded UI at ready+120 s. Fatal card/report/buttons/background are replaced by the normal blue header, project/thread sidebar, environment panel and composer; cursor moves to the Reload click position. diff0: 1,543,895 pixels; >16 threshold: 86,083 pixels (4.1514%). There is no layout change to the healthy screen.

![Before: head bounded fatal while backend remains stopped](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/272261bf17c82666/head-stall85-fatal.png)

![After: head authenticated UI after resume and Reload app](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/fa069b4355438e2d/head-stall85-final.png)

![Reload recovery diff0 amplified ×8](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/4e4b91a9c0001d47/reload-diff0-x8.png)

![Reload recovery threshold >16](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/597017878ec9a491/reload-diff-threshold16.png)

## Rebuild one affected capture

The committed fixture is `scripts/issue-23378/seed-evidence.py` at local commit `e38f845adb` (copy included in the audit archive). All local evidence is retained at `/tmp/issue-23378-evidence` for the proof auditor. Audit archive: [audit-details.zip](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/f683444fdc63f190/audit-details.zip) (runner, committed seeder copy, environment metadata, timing transcripts, filtered auth spans, diff counts, video marker scan and cleanup report).

1. Check out e38f845adb in an isolated worktree and install its dependencies. Initialize an empty isolated home once with `headless-desktop vp run dev:desktop --home-dir /tmp/issue-23378-evidence/fixture-home --no-seed`; stop that owned process tree. This supplies branch-owned migrations without reading live state.
2. Offline, run `python3 scripts/issue-23378/seed-evidence.py /tmp/issue-23378-evidence/fixture-home`. This resets projections/auth/tasks to synthetic data and fixes bounds and identity. Keep this same fixture for both revisions.
3. Extract the audit archive into `/tmp/issue-23378-evidence`. Adjust only `electron-wrapper/electron` to the installed real Electron binary path, retaining `--no-sandbox --disable-gpu`. The capture runner uses the supported ELECTRON_OVERRIDE_DIST_PATH to invoke that wrapper, never mocking Electron or auth.
4. Run `headless-desktop python3 /tmp/issue-23378-evidence/capture.py /absolute/head-worktree head-stall30 30`. The runner copies fixture-home to a fresh run-home, builds/launches the real desktop, stops the verified backend at ready, resumes after 30 s, records and cleans its owned process tree. Port offset 7965 gives backend 21738/web 13698; ensure those ports are free. No screenshot/test hooks are installed in product code.
5. For exhaustion, use label `head-stall85` and argument `85`. The runner pauses its owned `vp pack --watch` process after initial build to prevent a dev rebuild from replacing Electron during a long capture, then resumes it during cleanup. It clicks the existing fatal-screen Reload button at the fixed viewport coordinates. The short rows did not need this: all had one main-window launch and zero rebuilds.

## Scope, cleanup and friction

The original macOS 26.6.2 / MacBook Air M4 / nightly build is **unverified**. This proves shared Electron timeout/recovery behavior on Linux, not the original SQLite/event-loop cause or a fix for that cause. Standalone web/mobile/remote auth do not execute this changed desktop-local service.

All 148 tracked owned PIDs are gone, owned dev ports have no listeners, and Xvfb/DBus/keyring processes are gone. The extra base worktree was removed. Generated run-home credentials/state were removed; only auditor evidence/synthetic fixture remains under the evidence directory. Working tree clean, final branch SHA e38f845adbb6399e28436ce1c62cc1568f81c9f6. Disk free after cleanup: 12 GB (never below 10 GB, hard-stop floor 5 GB).

FRICTION category | happened | avoidance
--- | --- | ---
Fixture schema | First synthetic thread omitted required metadata; discarded initialization run | Include createdBy=user and creationSource=web in committed seeder
Cold renderer | Early 18 s healthy stills caught splash; discarded and reran both controls | Record 45 s after ready and capture settled UI at 40 s
Development watcher | First exhaustion attempt rebuilt dependencies and restarted Electron after fatal; discarded | Freeze owned build watcher after initial build for long row; require one main-window launch
Base behavior | Fatal appeared, then automatic recovery after resume | Report the whole recording, not only its fatal still
Tooling | Web fetch could not read matrix; used curl. xset unavailable; no use required after watcher diagnosis. Initial base dependency links missed scripts/node_modules | Read-only curl fallback; include all workspace dependency links; no added system packages
Publishing | Public evidence contains only synthetic labels, app metadata and source paths | Do not upload raw startup logs, bearer values, runtime secrets or copied user data
Platform | Original macOS host/build not tested | Explicitly limit claim to Linux Electron shared timeout mechanism

Proof audit pass 2: [SUFFICIENT; independently rebuilt capture has zero changed pixels](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/7a5490ac1441b89f/issue-23378-proof-pass2.md). Transition times above identify the first authenticated shell; final stills show settled synthetic project content.
