Load/save the installed-plugin registry (plugins.json), mirroring
pause_store / screen_time_store: a capped read and an atomic,
0o600 write via secure_io. A missing or unparseable file yields an
empty registry rather than failing startup.
Local-only plugin API (#156): manifests, signatures, the installed-plugin
registry, and the install/uninstall orchestration. See the staged plan in
docs/developer/plugin-api-design.md.
Shared process-name matching. Used by the run loopβs app-pause guard and
by the local-context detector probes, so both agree on what βprocess X is
runningβ means β in particular both reject substring collisions
(zoom must not match zoominfo) while allowing digit-versioned
binaries (obs matches obs64).
Renderer-side error reporter. The web error boundary calls this
from componentDidCatch so the crash lands in the same rotating
log file as everything else, instead of vanishing into the webview
devtools console where no end user ever looks.