Three interacting bugs reported by a user (Discord/ericepe) on a fresh install:
1. The state reconciler retried failed auto-repairs on every HTTP request,
pegging CPU and flooding logs with "Plugin not found in registry: github
/ youtube". Root cause: ``_run_startup_reconciliation`` reset
``_reconciliation_started`` to False on any unresolved inconsistency, so
``@app.before_request`` re-fired the entire pass on the next request.
Fix: run reconciliation exactly once per process; cache per-plugin
unrecoverable failures inside the reconciler so even an explicit
re-trigger stays cheap; add a registry pre-check to skip the expensive
GitHub fetch when we already know the plugin is missing; expose
``force=True`` on ``/plugins/state/reconcile`` so users can retry after
fixing the underlying issue.
2. Uninstalling a plugin via the UI succeeded but the plugin reappeared.
Root cause: a race between ``store_manager.uninstall_plugin`` (removes
files) and ``cleanup_plugin_config`` (removes config entry) — if
reconciliation fired in the gap it saw "config entry with no files" and
reinstalled. Fix: reorder uninstall to clean config FIRST, drop a
short-lived "recently uninstalled" tombstone on the store manager that
the reconciler honors, and pass ``store_manager`` to the manual
``/plugins/state/reconcile`` endpoint (it was previously omitted, which
silently disabled auto-repair entirely).
3. ``GET /plugins/installed`` was very slow on a Pi4 (UI hung on
"connecting to display" for minutes, ~98% CPU). Root causes: per-request
``discover_plugins()`` + manifest re-read + four ``git`` subprocesses per
plugin (``rev-parse``, ``--abbrev-ref``, ``config``, ``log``). Fix:
mtime-gate ``discover_plugins()`` and drop the per-plugin manifest
re-read in the endpoint; cache ``_get_local_git_info`` keyed on
``.git/HEAD`` mtime so subprocesses only run when the working copy
actually moved; bump registry cache TTL from 5 to 15 minutes and fall
back to stale cache on transient network failure.
Tests: 16 reconciliation cases (including 5 new ones covering the
unrecoverable cache, force-reconcile path, transient-failure handling, and
recently-uninstalled tombstone) and 8 new store_manager cache tests
covering tombstone TTL, git-info mtime cache hit/miss, and the registry
stale-cache fallback. All 24 pass; the broader 288-test suite continues to
pass with no new failures.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>