Meridian v2.0.0
Release Notes
Feed Discovery
Meridian now ships a first-class feed discovery workflow backed by the Feedly search API. Users can search by topic or keyword and subscribe to one or many feeds in a single flow, without leaving the app or knowing any feed URLs in advance. The discovery panel runs on a dedicated async event loop in a daemon thread, completely isolated from the UI and poll scheduler threads.
The discovery stack is built to the same layered boundaries as the rest of the system: a DiscoveryFetcher ABC defines the backend contract, FeedsearchFetcher provides the Feedly implementation, and DiscoveryService owns enrichment logic (subscription state, source type inference). Source type inference was extracted from SubscriptionService into a shared module to eliminate duplication. The AppController async lifecycle was extended to support clean shutdown with in-flight request cancellation.
Keyboard Accessibility
All interactive controls across the main reader, subscription manager, and discovery panel are now reachable and operable by keyboard. Tab order is consistent and left-to-right throughout. List views are single tab stops: arrow keys navigate within them, Tab and Shift+Tab move between sections. Focus state is visually indicated on all custom controls. Space toggles the selection checkbox on the focused feed row; Space on the check-all control selects or clears the entire list.
Startup Behaviour
The application window is raised to the front and given input focus immediately after the splash screen closes. A named Win32 mutex prevents multiple concurrent instances: if Meridian is already running, a second launch exits silently. The splash screen is rendered with rounded corners via a per-pixel alpha mask, relying on PyInstaller's frameless transparent window to composite cleanly against the desktop.
Feed Compatibility
Feed subscriptions now accept both http:// and https:// URLs. A previous constraint that rejected plain HTTP URLs blocked discovery-sourced subscriptions for feeds that the Feedly index still carries over HTTP (including well-known science and journal feeds). Feeds served over HTTP are fetched normally; the network layer follows redirects and respects any server-side HTTPS upgrade transparently.
Quality
100% branch coverage maintained across all modules including the new discovery stack. A pre-existing pytest-asyncio configuration gap that had silently prevented 34 async tests from running was also resolved in this release.