* feat(analytics): capture JS exceptions to PostHog
Turn on posthog-js exception autocapture (window.onerror + unhandled
rejections, with stack) and add a buffered captureException() wrapper for
boundary-caught React errors those handlers can't see. Wire the web
route-level global-error boundary to report through it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(diagnostics): add shared freeze watchdog
Long-task observer (>=2s) emits client_unresponsive via captureEvent;
client_type super-property tags desktop vs web for free. Installed once in
CoreProvider so web and desktop share one in-thread, SSR-safe detector for
recoverable freezes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(desktop): report true hangs and crashes via breadcrumb
A real hang or crashed renderer can't report itself. The main process now
persists a breadcrumb on unresponsive / render-process-gone, and the next
renderer boot flushes it to PostHog (client_unresponsive / client_crash).
A recovered hang clears its breadcrumb so it isn't double-counted by the
in-thread watchdog.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(analytics): scrub PII from $exception before send
Error messages can interpolate user input (typed values, URLs with tokens).
Add a before_send hook that redacts emails, URL query strings, and long
opaque tokens from the exception message and $exception_list values, keeping
type + stack frames (code locations, not user data). Addresses the privacy
gap from leaving capture_exceptions on with no sanitizer.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test: cover breadcrumb state machine and freeze watchdog
The breadcrumb persist/clear orchestration is the correctness-critical part
and was untested. Cover: hang->write, recover->clear (no double-count),
recover-before-delay->no-op, force-quit->retained, crash->write-and-never-
clear, clean-exit->no-write. Add watchdog tests (threshold, idempotent,
SSR/PerformanceObserver no-op) via a fake observer.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(desktop): breadcrumb field precedence + document limits
Spread the persisted context FIRST so explicit event fields (source,
recovered) always win over a future colliding context key. Document why
preload-error skips the breadcrumb and the single-slot last-write-wins
undercount limitation.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>