16e66e721f
Issue #74874. The renderer's 'Repair' button treated every transient backend GIL stall (event loop stalled ... ws ready frame send failed) as a fatal backend fault, asking the bootstrap to force-reinstall + restart, which then stalled again for the same reason — looping the user through 30+ minutes of reinstall cycles. Distinguish 'venv is genuinely broken' from 'backend is just transiently stalled' before honouring a repair request. Probe the live backend process (exitCode === null && signalCode === null) and an in-flight repair-attempt counter: attempt <= 3 AND primary alive → soft restart (skip installer) attempt <= 3 AND primary dead → soft restart (verify before reinstall) attempt > 3 → hard reinstall (escalate) Counter resets on a clean backend.ready so a later, unrelated failure episode starts at attempt 1. The guard is a pure helper (decideBootstrap Repair in electron/bootstrap-repair-guard.ts) so the decision logic is unit-tested in isolation; main.ts only wires the existing flag and counters to it. Refs #74874