# Issue 10517 proof audit, pass 1

Read-only source audit; no application launch, captures, server, tests, or repository edits performed. Complete diff inspected: base `52c2b38ea4` → head `ef5a77d2f16e5612a97e1e388afbcafe4f7c1422`, branch `fix/issue-10517`, worktree `/home/ubuntu/wt/issue-10517`. This is a capture specification, NOT visual verification. No PR exists or was created.

## Complete-diff coverage

All four changed files read. DesktopObservability exposes filePath only for an opened backend log sink; no-op sink omits it. DesktopBackendManager counts accepted restart schedules, not elapsed time; notification fires exactly at streak 3, excludes bounded/fatal preflight retries, resets at readiness, forks the notification into parent scope before scheduling the next retry. DesktopBackendPool supplies the callback only for primary; renders one unowned native Electron error message box, then copies exactly the two diagnostic lines only for response 0. DesktopBackendPool.test adds spies and tests for crash, open-dialog retries, bounded-preflight→crash, and missing entry; these tests are not native visual evidence.

Native dialog: title “T3 Code's backend couldn't start”; message “The local backend keeps stopping before it is ready.”; detail contains `Reason: …`, `Backend log: …`, retry/reopen guidance; buttons Copy Diagnostics (default 0), Close (cancel 1). No renderer, CSS, mobile layout, shared contract, provider adapter, network transport, or web Settings caller changed.

## Fixture matrix

A = affected by diff; C = unaffected control; S = static screenshot; R = RECORDING REQUIRED for every time/interaction row. All expectations below are source-derived until captured. Each affected capture must have real base/head runs with the same seed, host, display, theme and elapsed milestones. “Same shape” permits omitting duplicate static screenshots, never omitting a distinct behavioral assertion.

| ID | Affected | Path / seed / conditional | Base → head expected result | Width / theme / platform | Evidence / collapse rationale |
|---|---|---|---|---|---|
| F01 | A | Primary child exits before ready; literal missing-column DB | No new native failure box → one new box at third counted failure; reason normally `code=1`, real backend log path | Linux first; 1440 light/dark; 390 light/dark constraint pass; Windows/macOS native samples | S dialog each applicable distinct native style; R startup-to-dialog. Anchor fixture for startup issue |
| F02 | A | Primary child exits; generic invalid DB `.t3/userdata/statev2.sqlite` | Same new box as F01, backend log contains different actual DB error | Same as F01 | Collapse static into F01 if identical reason/path wrapping; R one base/head startup per distinct failure recipe; assert generic error in log, do not call it literal issue reproduction |
| F03 | A | Log sink cannot open; primary crash | Head renders `Backend log: unavailable`, not bogus path | 1440 light/dark representative; 390 if wrapping differs; native OS samples | S distinct diagnostic text; R startup plus Copy Diagnostics and clipboard result. Cannot collapse with F01 path-present branch |
| F04 | A | Missing server entry; `exists` false or errors | Silent retry → same dialog with `Reason: missing server entry at <absolute entry path>` | 1440 light/dark; 390 both for long path/clipping | S distinct long text; R retry onset and Copy Diagnostics. Separate content/wrapping from code=1 |
| F05 | A | Config resolution fails AFTER desiredRunning became true | Silent retries → reason `failed to generate desktop backend configuration` | Representative 1440 light; other styles collapse with F04 if same wrapping | R; static same dialog chrome, different diagnostic line; retain text assertion |
| F06 | C / caveat | Very first config resolution fails while desiredRunning=false | Neither revision schedules restart or new repeated-start box from this branch | One native host, 1440 light | R bounded observation + logs; cannot claim initial config errors are covered by F05 |
| F07 | A | Nonfatal unbounded preflight (`retryLimit` absent) | Retry only → new box at 3 counted failures, preflight reason | Windows/WSL; representative 1440 light | R; static collapse with F04/F05 by actual wrapping. Need actual unbounded configuration path, not missing-column substitute |
| F08 | A transition; old box C | Bounded nonfatal preflight exhausted → Windows fallback → child crashes | Existing “WSL backend is still unavailable” box unchanged; head later shows new crash box; bounded attempts do not consume streak | Windows/WSL; 1440 light/dark if native styling differs | R entire old-dialog dismissal/fallback/three-crash sequence; new dialog static collapses F01 |
| F09 | A transition; old box C | Fatal preflight → persisted Windows fallback → child crashes | Existing “WSL backend couldn't start” unchanged; head later new crash box | Windows/WSL; representative 1440 light | R; collapse new box F01, retain fatal fallback/settings assertions separately from F08 |
| F10 | A | Repeated failures while new dialog remains open | Base continues retrying without new box; head continues retrying with exactly one box for streak | 1440 light representative | R until >=2 subsequent restarts shown by correlated log/PIDs; still screenshot cannot prove this; collapse startup R with F01 |
| F11 | A | Click Copy Diagnostics / default Enter | Base has no corresponding box; head closes box and clipboard receives exactly `Reason: <reason>\nBackend log: <path or unavailable>` | 1440 light; F03 covers unavailable; native keyboard check each OS | R click/Enter + clipboard readback in same display session; do not assert full logs/stack copied |
| F12 | A | Close button / Escape / native window dismissal | Head closes without changing sentinel clipboard; retries continue, no second box during same streak | 1440 representative; OS-specific dismissal | R for explicit Close and cancel semantics; static same chrome F01. Base negative control has no action target |
| F13 | A | Ready resets streak; later three failures without readiness | Head can show a new box for new streak; no notification on one/two failures | One host, representative theme | R recovery-to-new-failure sequence + readiness/retry milestones. If first box still open on recovery, test whether second can overlap; do not claim global single-dialog dedupe |
| F14 | A | Readiness failure/spawn error vs ordinary exit | Same new dialog, reason supplied by runBackendProcess error/exit path | One host, long reason at 1440/390 if distinct wrapping | R; collapse screenshot only if diagnostics shape is already represented by F04. Use actual error, not mocked dialog |
| F15 | A error handling, no intended new UI | showMessageBox rejects, or clipboard write rejects | Callback logs warning for typed dialog error; clipboard wrapper swallows rejection; no guaranteed success feedback | Host supporting controlled failure injection | R + log/clipboard assertion; no extra static fixture. Service tests appropriate if real OS failure cannot be seeded; disclose lack of real-app proof |
| C01 | C | Healthy isolated clean home, backend reaches ready | Normal main client, no new error dialog | 1440 light/dark; 390 only if feasible desktop window constraint, no mobile claim | R startup control base/head; one S per genuinely distinct style is enough; no backend corruption |
| C02 | C | Backend reaches ready on every restart; deliberate normal shutdown | No repeated-start notification; readiness resets streak, stop disables restart | Representative native host | R + milestones, collapse control static C01 |
| C03 | C | State-dir ownership exit | Existing “This T3 home is unavailable” and quit; bypasses new callback | Representative native host, isolated competing server only when later authorized | R; do not use live developer home or start a server in this audit |
| C04 | C | Registered secondary/WSL backend, no repeated-failure callback | Shared counter changes but no new primary dialog for secondary crashes | Windows/WSL if available | R; no separate screenshot, keep instance identity in logs |
| C05 | C / out of scope | Web, mobile, providers, remote/relay/tunnel, local-backend-disabled mode | No new UI paths; callback is local primary desktop only | No 390 browser/mobile fixture | Source coverage sufficient; no unrelated browser capture |

## Minimum capture set after collapsing shapes

1. F01 real literal missing-column base/head startup recordings; extend head recording while box stays open (F10), then Copy Diagnostics and show clipboard result (F11). Capture head box at native 1440 light/dark. Base must show the corresponding whole desktop/no-main-window state and log-confirmed repeated child failures, not a manufactured blank browser.
2. F01 at native 390 light/dark if display supports it; record clipping/overflow. If the OS cannot display a usable dialog at that width, retain uncropped full-display evidence at minimum supported size and explicitly mark 390 unsupported. Never crop and label it a 390 viewport.
3. F03 unavailable-log base/head recording + Copy/readback; F04 missing-entry base/head recording + longest-path still, at 1440 and feasible 390 in both native themes when wrapping/style differs. These are two distinct diagnostic shapes beyond F01.
4. F12 separate Close/cancel recording with clipboard sentinel, remaining retries and no duplicate; F13 recovery/new-streak recording. Same static shape as F01, so no redundant stills.
5. F02 generic invalid-DB base/head recording; F05/config-after-start and F14 error-path recordings can omit redundant stills but need actual reason assertions. F06 first-config failure negative control must remain explicit.
6. Windows-only F07/F08/F09 recordings, including existing preflight boxes, fallback and eventual crash box. Linux cannot stand in for WSL; no fabricated cross-platform proof. One representative 1440 light/dark dialog per native OS for changed chrome; use F01/F04 on macOS/Windows as appropriate. 390 native limitations documented per OS.
7. C01 healthy base/head startup recording and matched normal-window control. C02-C04 targeted behavioral recordings only if in acceptance scope/environment available. F15 focused behavioral proof; disclose any test-only coverage.

This minimizes distinct still shapes to code=1+path, unavailable-log, long missing-entry/path, plus native platform/theme variants and any genuinely different wrapping. Config/preflight/spawn strings are distinct callers but do not each require a duplicate still when actual measured shapes match. Timing and interaction rows NEVER collapse to a screenshot. A minimum still set is not permission to skip behavioral rows.

## Actual environment and seed recipes for the later capturer

Confirmed on disk: installed Electron executable `apps/desktop/node_modules/electron/dist/electron`; desktop boot/main bundles; saved base `.t3/evidence-base/main.cjs`; current main bundle. Existing reproduction transcript reports Linux x64/Electron 44.4.5; package now declares 44.9.3, so capturer must record executable version rather than assuming either. Current built head attribution is not independently proven by file existence.

Run from `/home/ubuntu/wt/issue-10517`, with no dev-server URL or VITE_HTTP_URL/VITE_WS_URL. This tests installed/built desktop boot against built server assets, not a browser or Vite. Launch template (future authorized capture only):

```sh
XDG_DATA_HOME="$worktree/.t3/keyring-data" T3CODE_HOME="$fixture_home" \
  headless-desktop "$worktree/apps/desktop/node_modules/electron/dist/electron" \
  "$worktree/apps/desktop/dist-electron/boot.cjs" --no-sandbox --disable-gpu
```

`worktree` and `fixture_home` must be explicitly assigned absolute task-local paths. XDG_DATA_HOME is essential: default machine keyring can already be locked. The wrapper creates a D-Bus session and unlocks GNOME keyring; it hardcodes Xvfb 1920x1080x24. For 1440/390 use a task-local equivalent wrapper with explicit Xvfb screen width and chosen height; record screen dimensions, scaling, toolkit theme and actual dialog bounds. Capture helper and clipboard reader must run inside that SAME X display / D-Bus session. No browser launch needed.

Use fresh run-specific copies of `.t3/healthy-home` (isolated clean baseline) for success, `.t3/missing-column` for literal missing-column reproduction, and `.t3`'s invalid `userdata/statev2.sqlite` for generic variant. Do not recursively copy all `.t3` into itself; construct a separate run home and copy only needed userdata/settings. Do not copy keys/secrets merely to share evidence. SQLite copies must be consistent snapshots from stopped fixtures or SQLite backup API (include WAL state correctly). Validate missing-column schema with read-only PRAGMA; specifically absent `projection_threads.branch_pull_request_json`. To regenerate later: snapshot healthy DB then `ALTER TABLE projection_threads DROP COLUMN branch_pull_request_json` on isolated copy; preserve migration ledger so startup does not silently repair it. Generic DB is literal non-SQLite bytes; keep distinct name/label.

For F03, before launching a copied corrupt-DB home create a DIRECTORY at `<fixture_home>/userdata/logs/server-child.log`, leaving logs parent and all other state writable. This forces primary log sink open failure even when running with elevated permissions; merely deleting the file is insufficient (writer recreates it), chmod may be ineffective. Verify app otherwise reaches primary backend manager and head shows unavailable. For F04 temporarily move built `apps/server/dist/bin.mjs` only in an isolated copied artifact tree preserving desktop's ../../../ root relationship; restore after run. Do not alter the shared worktree bundle while another process could use it.

For base/head, save head main bundle and manifest hashes first; install saved base main.cjs at the SAME relative `apps/desktop/dist-electron/main.cjs` location for base run, restore exact head for after. Prefer two identical isolated artifact trees to avoid mutation races. Other desktop bundles/server/client assets stay byte-identical. Log hashes/build provenance for base/head; do not execute saved main from `.t3/evidence-base` directly because dirname-based resource paths change. Fresh equivalent homes prevent baseline runs/migrations/settings from contaminating head. Capture native light/dark through actual OS/toolkit/nativeTheme, not renderer CSS theme alone; verify what the dialog actually uses at early startup.

Config-after-start, unbounded-preflight, bounded/fatal-preflight→child-crash, readiness reset and native error injection have NO verified turnkey on-disk seed here. Later capturer must supply deterministic real-app fixtures/service-boundary injection and label that provenance. Existing pool tests use spies and TestClock, not actual Electron. Do not describe a spy-rendered box as real application evidence.

## FRICTION and acceptance gaps

- No new visual or behavioral captures in this pass by explicit request. Existing base transcript is contextual evidence, not a matched before/after pair. Final visual acceptance remains pending.
- Source caveat: first configResolve failure never sets desiredRunning, so repeated-config dialog does not cover that initial failure. F06 exposes the limit rather than hiding it under F05.
- New reason is coarse `code=1` for DB failures; copied diagnostics provide reason+log LOCATION, not log content or the missing-column stack. Evidence must show actual log contents separately to establish issue linkage.
- Notification is once per failure streak, not once per currently open dialog. Ready resets counter while an old dialog may remain open; F13 must check possible overlapping dialogs after recovery/re-failure. No assertion of global dedupe is supported by code.
- Threshold is three accepted schedules. Do not require exact 3.5 seconds; process boot/preflight/readiness time adds latency, restart backoff grows to 10s. Record milestones and child logs, not an arbitrary fixed sleep.
- Native dialogs are separate top-level OS surfaces, unowned here, possibly shown before any main BrowserWindow exists. Browser screenshots/viewport emulation cannot prove them. Linux Xvfb cannot prove Windows/macOS layout, WSL fallback, native keyboard order, or modality/focus.
- No physical mobile platform or web-theme matrix applies. 390 is a narrow native desktop constraint probe, not an iPhone/Android simulation. Windows/macOS minimum dialog widths and button order may prevent an exact 390 fit; report measured constraints.
- Native theme may stay identical across requested light/dark on a host; record actual theme implementation/limitations and collapse only with evidence, not assumed equivalence.
- Built bundles exist but need SHA/provenance verification before capture; package/runtime version discrepancy is unresolved.
- Later capturer is required by the brief to COMMIT a reproducible seeding script/fixture. This pass deliberately only wrote scratch outside the worktree and cannot satisfy that implementation step. Do not commit DBs, captures, secrets, or this scratch matrix. No PR creation authorized.

Audit method: full git diff plus caller/context inspection, local artifact metadata and existing reproduction transcript. No tests run; no merge verdict requested or supplied. Authored by gpt-6.1-sol through Codex in T3 Code.
