Ensure printed output and HTML logs are safe by importing and applying sanitize_string, opening log files with utf-8 and errors='replace', and sanitizing text before writing. Add tests to verify lone surrogate characters are replaced and that logging won't crash on invalid Unicode. In the plugin installer UI, introduce POPULAR_PLUGIN_MIN_STARS and centralize popularity checking in _isPopularPlugin, using it for filtering and counts.
- Add force parameter to plugin index fetch with cache-busting headers and timestamp
- Add openIndexView and reloadIndex methods to pluginInstallStore for explicit refresh
- Add request sequence tracking to prevent race conditions in concurrent index loads
- Move models summary state from component to store with loading/caching support
- Add refreshModelsSummary, ensureModelsSummaryLoaded, and modal
The browse view used x-create on install-index to load the index, but
that hook was not a dependable signal when returning from the Git or ZIP
tabs. setTab('store') now resets browse state and calls fetchIndex so the
hub stays in sync whenever Browse is selected, including on modal open.
Surface repository metadata for installed custom plugins and add quick actions from the plugin info modal to open plugin files or jump back into the Plugin Hub. Refresh Plugin Hub card/status styling and modal spacing.