Releases: cporcellijr/bookbridge
Release list
v7.0.0
The headline change is user accounts: the bridge now supports more than one reader, each with their own sign-in, their own progress, and their own view of the library. This is a bigger release than usual — if you are upgrading from an earlier version, please read the upgrade note below.
What's New
-
Multiple readers. You can now create separate accounts for different people — for example, everyone in a household. Each person signs in to their own dashboard, sees only the books they are reading, and keeps their own progress, even when two people are reading the same book.
-
Separate logins for each reader. The main account gives each reader their own Audiobookshelf, KOSync, Grimmory or BookOrbit, Storyteller, and tracker logins, so everyone syncs against their own accounts and their own shelves. The shared engine settings — how often it syncs, library scans, and shelf watching — still live in one place for the main account to manage.
-
A proper sign-in screen. The dashboard is now protected by a login. The first person to open it sets up the main account, and that account can add more readers from a new Users area in Settings.
-
A streamlined Add Book screen. Searching your libraries, queueing up several books at once, and matching or forging the whole queue now happen in one place.
-
Same-folder matching. When an audiobook and an ebook live in the same library folder, the Suggestions page now flags them as a likely pair before any fuzzy or AI scoring — and treats them as an exact match only when the titles also agree, so two unrelated books sharing a folder aren't matched by mistake.
-
Review suggestions in bulk. Tick several suggestions and add them to the queue at once, or add every exact (100%) match in one click with Add all exact. Adding to the queue no longer reloads the page, so you keep your place in a long list — and you can run Forge & Match All right from the Suggestions page.
-
Hardcover and StoryGraph, independently. You can now enable both trackers at the same time, each with its own toggle, instead of having to choose one or the other.
-
Install the KOReader plugin from Settings. Download the BridgeSync plugin straight from the KOSync settings section — no need to fetch it from GitHub Releases.
What Changed
-
Upgrading from an earlier version. After you update and restart, open the dashboard once. Because there are no accounts yet, you will be asked to create your main login — just pick a username and password. As soon as you do, your existing library, your matches, and every service login you had already entered are moved onto that account automatically, so there is nothing to set up again. Your KOReader devices keep syncing exactly as before. From there you can add accounts for other readers whenever you like.
-
The project is now called BookBridge. This is a name and branding change only — your settings, mappings, KOReader devices, and the way syncing works are all unaffected.
-
Matching returns to the dashboard right away. Single and batch matches now hand the slower work (tracker lookups, forging) to the background, so the screen comes back immediately and books appear as each one finishes.
Fixed
-
CWA progress appears sooner. Books synced through Calibre-Web-Automated's Kobo sync now show their CWA row on the dashboard right away, instead of only after the first position comes in.
-
More accurate Hardcover/StoryGraph matching. Auto-matching now prefers the book's own ISBN, no longer grabs a wrong book that merely shares a title, and works for ebook-only books.
-
Forge & Match survives a restart. If the bridge restarts while a Forge & Match is still processing, it now picks the job back up and finishes it instead of leaving the book stuck.
-
Storyteller forged books are no longer hidden. Storyteller collections the bridge creates are now public, so the books it adds show up as expected.
-
KOReader syncs reliably on wake. The BridgeSync plugin now syncs dependably when a device wakes from sleep.
-
Manual and forged KOReader links stay put. Hash links you set by hand, or that come from forging, now persist across syncs.
-
Large Grimmory libraries scan fully. Library scans now page through big Grimmory libraries (with configurable timeouts) instead of stopping short.
Security
- Hardened the web app for logins. Session-based actions are now protected against cross-site request forgery, and the KOSync login endpoints no longer reveal the sync key.
Release 6.8.0
Release Notes — 6.8.0
The headline additions are a second ebook library manager (BookOrbit) and an optional local-LLM assistant (Ollama), alongside a batch of sync fixes. Existing setups upgrade in place — database migrations and new settings apply automatically.
Added
BookOrbit — a second ebook/audiobook library manager that works like Grimmory. Optional "Up Next" collection watch auto-matches books you drop onto a shelf. Includes a Grimmory→BookOrbit migration script (no rematching needed).
Optional Ollama (local LLM) — smarter match suggestions and audio↔text alignment rescue. Off by default; falls back to normal behavior if Ollama is unreachable, so it never blocks a sync.
Link Storyteller from any dashboard card — not just ebook-only mappings.
Combined KOReader reading stats across devices.
Expanded stats page with more reading-activity views.
Changed
Storyteller-led syncs now count as listening time in Audiobookshelf.
Fixed
Safer SQLite journal mode on filesystems where WAL is unreliable (9p, some NFS, certain VM shares).
Storyteller read-along no longer snaps back in books that navigate by SMIL fragment IDs.
Fewer false rollbacks from stale or out-of-order KoSync updates.
More accurate dashboard "out of sync" warnings.
Cleaned up (for public release)
Removed a stale debug script, pinned dependencies, dropped a bogus ffmpeg pip dependency, fixed license/readme metadata, and neutralized localhost defaults.
Migration
None required. Database migrations and new settings apply automatically on startup. Switching Grimmory→BookOrbit is optional and does not require rematching — run scripts/migrate_grimmory_to_bookorbit.py (dry-run by default; add --apply).
Known limitations
BookOrbit is newer than Grimmory and less battle-tested; the docs cover it lightly for now.
Ollama is advanced and opt-in: you supply your own server and models, and match quality depends on the model you choose.
Release 6.7.0
[6.7.0] - 2026-05-11
What's New
-
Book ratings now appear on dashboard cards. Each card shows StoryGraph and Goodreads ratings as small badges under the cover, with tooltips that include the rating, review count, and source. Both ratings are captured automatically when a book is linked — Goodreads via the cached Grimmory metadata, StoryGraph via a one-time scrape of the book's community-reviews page. A one-time backfill runs in the background at startup so books linked before this release also get their StoryGraph ratings filled in (self-limiting; no settings toggle needed).
-
Sort by rating. A new Rating option in the dashboard sort dropdown sorts books by the average of their StoryGraph and Goodreads ratings (using whichever is available when only one is present). Books without ratings always sort to the bottom regardless of direction.
-
Series grouping on the dashboard. Books that are part of the same series can now be grouped into a single stacked card with combined progress and metadata, instead of showing each entry separately. A new Alembic migration adds the supporting series-metadata columns and existing series entries are populated automatically.
-
StoryGraph supports audio editions and shows audio duration. The StoryGraph edition picker now detects audiobook, digital audiobook, audio CD, and narrated print/audio formats and displays duration alongside other edition metadata, so audiobook listeners can pick the correct StoryGraph edition.
-
Authoritative ABS identifier mapping via Calibre. When the Audiobookshelf-calibre-plugin is in use, the bridge can read its
audiobookshelf_ididentifier from Calibre'smetadata.db(or the CWA/ajax/book/{id}endpoint as fallback) and treat it as authoritative during suggestion scans — bypassing fuzzy title/author matching for already-mapped books. Configurable in Settings → CWA → Authoritative ABS Identifier Mapping. -
Bridge Sync plugin can auto-upload KOReader reading stats. A new "Auto-Sync Reading Stats" toggle (on by default) uploads KOReader's
statistics.sqlitepage-stat rows alongside the plugin's existing auto-syncs (wake, network reconnect, Sync Now), with a 5-minute cooldown between uploads so it stays quiet on the device. -
Forge tuning for Storyteller ReadAloud workflows. Three new settings appear in Settings → Storyteller / Forge:
- Skip ReadAloud EPUB Cache (
STORYTELLER_NO_EPUB_CACHE) — make Forge use the original EPUB for text extraction instead of downloading and caching Storyteller's ReadAloud EPUB. Useful when the original EPUB is on a mapped library volume. - Forge Recovery Max Wait (
STORYTELLER_RECOVERY_MAX_WAIT_MINUTES, default 360) and Forge Recovery Poll Interval (STORYTELLER_RECOVERY_POLL_INTERVAL_MINUTES, default 2) — tune how long the bridge waits for in-flight Storyteller jobs to recover after restart before giving up.
- Skip ReadAloud EPUB Cache (
What Changed
- Grimmory library scans are skipped when Grimmory is not configured. Previously, library refresh paths could attempt a Grimmory scan even with no credentials configured, generating noisy error logs. The bridge now short-circuits cleanly when Grimmory is disabled.
Fixed
- KOReader sync was silently demoted to percent-fallback for many EPUBs with inline span markup. KOReader emits XPaths in the form
/text()[N].MMMwhenever a paragraph contains inline children that split text into multiple nodes. The XPath resolver's offset-stripping regex only matched the unbracketed/text().NNNform, leaving the.MMMglued onto the path and causinglxmlto reject it as invalid. The resolver fell back to percent-based normalization, bypassing single-client-delta and deadband-rollback protections in the sync manager. Both bracketed and unbracketed forms now parse correctly.
Release 6.6.0
What's Changed
Added Storygraph tracking support. Thanks to https://github.com/burneracc0112 for the insperation
Misc. bug fixes.
Full Changelog: v6.5.0...v6.6.0
Release 6.5.0
[6.5.0] 2026-4-12
What's New
-
Add CWA reading progress sync via Kobo sync protocol
Enables bidirectional reading progress sync between the bridge and
Calibre-Web Automated using CWA's Kobo sync endpoints. This allows
stock Kobo e-readers (and KOReader via CWA) to participate in the
sync loop alongside Audiobookshelf, Storyteller, and other clients.
(Thank @dfendr) -
KOReader plugin can now update itself. A new "Check for Plugin Update" option appears in the Bridge Sync plugin menu (after Test Connection). It checks whether a newer version of the plugin is available on your bridge server, and if so, offers to download and install it directly from KOReader — no more downloading a ZIP from GitHub and copying it manually.
-
KOReader stats now shows all your reading activity, not just linked books. The stats page previously only listed books that were linked in BookBridge. It now shows every book KOReader has recorded, whether linked or not. Books that are not linked appear with an "Unlinked" marker so they are easy to tell apart.
What Changed
- Storyteller sync no longer rejects books when the transcript file count doesn't match. If the number of Storyteller transcript files differs from the number of ABS chapters, the bridge previously rejected the book entirely. It now uses whatever transcript files are available and derives timing from them instead. This unblocks sync for books with partial Storyteller transcripts or different chunking than ABS expected.
Fixed
-
Progress was being silently reset to the cover in Scrivener-style EPUBs. EPUBs produced by Scrivener — and other tools that wrap every paragraph's text in a
<span>element — caused the bridge to generate a position reference KOReader could not resolve. KOReader would fall back to position 0 (the cover page) and write that back, erasing saved progress on every sync. The bridge now generates the correct reference for these EPUBs. -
Storyteller sync placed you at the wrong position in some books. Fixed a case where Storyteller could not find the right location in books that use fragment IDs for navigation. Sync positions are now accurate for these books. (Thanks @Sirozha1337)
-
Storyteller auth could fail mid-session when tokens expired. Improved token lifetime management so the bridge no longer hits authentication errors during long Storyteller sync sessions. (Thanks @Sirozha1337)
New Contributors
- @Sirozha1337 made their first contribution in #235
- @dfendr made their first contribution in #238
Full Changelog: v6.4.2...v6.5.0
Release v6.4.2
Fix] Forge/match button survival on disable.
Release 6.4.1
[6.4.1] - 2026-04-04
Fixed
- Fixed a manual Forge regression where Grimmory EPUB selections could be sent with the display label
Grimmoryinstead of the internalBookloresource key, causingUnknown text source: 'Grimmory'failures. - Improved Storyteller transcript-ingest diagnostics so title-directory misses now log the resolved
STORYTELLER_ASSETS_DIR/assetssearch root, candidate titles, and a short sample of available asset directories before falling back to SMIL or Whisper.
Release 6.4.0
All notable changes to ABS-KoSync Enhanced will be documented in this file.
[6.4.0] - 2026-04-04
Added
- Added an optional Bridge Sync KOReader plugin for pulling bridge-managed books onto a device-managed folder.
- Added Find IDs helpers for Audiobookshelf and Grimmory library ID fields in Settings, including quick pick dropdowns.
- Added an Audiobookshelf disabled mode by treating
disabledas an intentional off switch for ABS URL or token settings. - Added Grimmory shelf and magic shelf support for Bridge Sync plugin collection syncing.
- Added a Grimmory shelf picker in Settings to make Bridge Sync collection setup easier.
Changed
- The Whisper Model field in Settings now accepts custom values instead of only the built-in preset list.
- The Bridge Sync KOReader plugin now keeps its settings submenu open while you make multiple configuration changes, and the Managed Folder setting now uses a folder picker instead of manual path entry.
- Storyteller Forge now uploads staged EPUB and audio files directly to Storyteller over the REST/TUS API instead of relying on watched-library folder hand-offs.
- Storyteller direct-upload settings now expose
STORYTELLER_UPLOAD_CHUNK_SIZEfor tuning TUS PATCH chunk size when needed. - Grimmory compatibility was broadened across search, cache refresh, downloads, and progress/session handling so newer Grimmory installs work more reliably as both ebook and audiobook sources.
- Settings now test the values currently typed into the form, and saving settings shows a restart-wait page until the application is healthy again.
- Dashboard cards now show reading session details.
- Match, Batch Match, Suggestions, and Forge now show clearer working feedback when you start an action.
- Built-in KOSync testing in Settings now works with the values currently in the form.
Fixed
- Fixed Grimmory session writes so reading and listening sessions stay in the strict format Grimmory expects.
- Fixed Storyteller TUS
Upload-Metadataformatting for direct Forge uploads. Metadata pairs are now serialized without post-comma whitespace, which restores compatibility with Storytellerweb-v2.9.3and prevents400 Invalid upload-metadatafailures during Auto-Forge and manual Forge. - Fixed Storyteller direct-upload and post-import issues, including
Upload-Metadataformatting, import readiness timing, duplicate Forge triggers, and several incorrect locator/progress writes. - Fixed Grimmory progress writes, single-file audiobook Forge downloads, cache hydration edge cases, and truncated downloads that could break matching or syncing.
- Fixed suggestions and sync edge cases around finished books, instant-sync replays, sentence-level KOReader locators, and cross-format rollback handling.
- Fixed deadband rollback behavior so tiny audiobook-vs-ebook gaps still avoid leader flapping without pushing older ABS progress back onto newer high-confidence ebook locators.
- Fixed Grimmory session reporting so reading and listening sessions are recorded more reliably.
- Fixed dashboard sync warnings so old inactive states do not create misleading out-of-sync messages.
- Fixed the built-in KOSync Test button so it no longer requires saving first.
Release 6.3.3
Changelog
All notable changes to ABS-KoSync Enhanced will be documented in this file.
[6.3.3] - 2026-03-21
✨ Added
-
Library Suggestions Page
- Scan unmatched titles
- Review likely audiobook/ebook pairs
- Queue approved matches in bulk
-
Booklore Audiobook Support
- Use Booklore audiobooks as the audio side of a sync
- Integrated into matching, batch processing, suggestions, Forge, and dashboard tracking
-
Flexible Linking Flows
- Ebook-only links
- Storyteller-only links
- One-click Refresh Booklore Cache action in Settings
-
Enhanced Suggestions System
- Background scanning with progress updates
- Cached repeat scans
- Full Refresh option for full-library rescans
-
Improved Source Visibility
- Clearer source badges across:
- Match
- Batch Match
- Suggestions
- Dashboard
- Enhanced audio-source detail display
- Clearer source badges across:
-
Improved Storyteller Transcript Handling
- More tolerant of real-world file layouts
- Priority order:
- Storyteller timing
- SMIL
- Whisper fallback
🔧 Diagnostics & Controls
-
Test Connection Buttons
- Added to all services:
- ABS, KOSync, Storyteller, Booklore, CWA, Hardcover, Telegram
- Performs live connectivity checks
- Returns specific errors:
- Wrong URL
- Invalid credentials
- DNS failure
- Timeout
- Disabled/unconfigured states
- Added to all services:
-
Instant Sync Toggle
- New setting:
INSTANT_SYNC_ENABLED - Enables/disables event-driven sync globally
- When disabled:
- Socket listener is off
- Falls back to poll cycle
- New setting:
-
Instant Sync Tuning
- New setting:
ABS_SOCKET_DEBOUNCE_SECONDS(default: 30s) - Controls delay after playback events before sync
- Lower = faster sync
- Higher = less load during scrubbing
- New setting:
-
Per-Client Polling
- Storyteller and Booklore can use custom poll intervals
- Independent from global sync cycle
- Only triggers sync on real position changes
-
Shared Write Suppression
- Centralized via
write_trackermodule - Prevents feedback loops across:
- ABS
- KoSync
- Storyteller
- Booklore
- Centralized via
📚 Storyteller Enhancements
-
Transcript Priority Source
- New priority:
- Storyteller (forced alignment)
- SMIL
- Whisper
- New priority:
-
Optional Assets Directory
- New setting:
STORYTELLER_ASSETS_DIR - Path:
{root}/assets/{title}/transcriptions - Optional and skipped if unset
- New setting:
-
Native Alignment Maps
- Built directly from
wordTimeline - Includes:
- Chapter
- Local UTF-16 character offsets
- Local timestamps
- Global timestamps
- Built directly from
-
Direct Timestamp → EPUB Locator
- For Storyteller-backed books
- Converts audiobook timestamps directly to EPUB positions
- Bypasses fuzzy text matching
-
Backfill Action
- Bulk ingest/re-ingest transcripts
- Rebuild native alignments for existing books
-
Forge Pipeline Integration
- Transcript ingestion and alignment generation now built into Forge
⚡ Sync & Automation
-
Event-Driven Real-Time Sync
- Uses ABS Socket.IO listener
- Sync triggers:
- Audiobook play/pause
- KoSync PUT events
- Syncs across:
- KoSync
- Storyteller
- Booklore
- Hardcover
- Typical delay: ~30 seconds
- Configurable via:
ABS_SOCKET_ENABLEDABS_SOCKET_DEBOUNCE_SECONDS
-
Suggestion Discovery from Events
- Unknown-book socket events now trigger automatic suggestion discovery
🖥️ Dashboard Improvements
-
Search
- Instant client-side filtering
- Search by title or author
- No page reload required
-
Quick Actions
- ⚡ Sync Now → triggers immediate sync
- ✅ Mark Complete → marks finished across all platforms
- Optional mapping cleanup prompt
-
Version Badge Cleanup
- Dev builds:
Build dev-N - Releases:
vX.Y.Z - Removed redundant prefixes
- Dev builds:
Release 6.3.2
[6.3.2] - 2026-03-04
Enhancements
- Test Connection Buttons: Added diagnostic "Test" buttons to every service section in Settings (ABS, KOSync, Storyteller, Booklore, CWA, Hardcover, Telegram). Each button performs a live connectivity check and returns specific error messages — distinguishing wrong URL, wrong credentials, DNS failure, timeout, and disabled/unconfigured states.
- Instant Sync Toggle: Added
INSTANT_SYNC_ENABLEDsetting to enable or disable event-driven instant sync globally. When off, the ABS Socket.IO listener and KoSync push trigger are both inactive and the bridge falls back to the standard background poll cycle. - Instant Sync Settings: Added
ABS_SOCKET_DEBOUNCE_SECONDS(default 30s) to control how long the socket listener waits after a playback event before triggering a sync. Tune this lower for faster response or higher to avoid hammering downstream services during active scrubbing. - Per-Client Polling: Storyteller and Booklore can now be configured with their own poll intervals, independent of the global sync cycle. Set either client to
custommode in Settings and choose a polling interval (in seconds). The poller checks for position changes on active books only and triggers a targeted sync when a real change is detected. - Shared Write Suppression: Centralized write-tracking into a single
write_trackermodule. All clients (ABS, KoSync, Storyteller, Booklore) now share the same suppression logic to prevent feedback loops after the bridge pushes a progress update. - Storyteller Transcript Priority Source: Added Storyteller forced-alignment transcript ingestion as the top transcript source during matching/linking (priority: Storyteller -> SMIL -> Whisper).
- New Optional Setting
STORYTELLER_ASSETS_DIR: Added Settings/UI support for Storyteller assets root ({root}/assets/{title}/transcriptions). This source is opt-in and skipped when unset. - Native Storyteller Alignment Maps: Added direct map generation from
wordTimelinedata (chapter, local UTF-16 char, local ts, global ts) without anchor rebuild. - Direct Timestamp -> EPUB Locator (Storyteller only): ABS audiobook timestamps on Storyteller-transcript books can now resolve to EPUB locators directly from transcript offsets, bypassing fuzzy text search.
- Storyteller Backfill Action: Added a Settings maintenance action to bulk ingest/re-ingest Storyteller transcripts for existing Storyteller-linked books and rebuild storyteller-native alignments.
- Storyteller Transcript Ingest in Forge Pipeline: Added transcript ingestion and anchored alignment generation directly in the forge workflow.
- Suggestion Discovery from Socket Events: Unknown-book Socket.IO progress events now trigger suggestion discovery to surface likely matches automatically.
- Event-Driven Real-Time Sync: Added ABS Socket.IO listener for near-instant sync. When you play/pause an audiobook in Audiobookshelf, progress automatically syncs to all configured clients (KoSync, Storyteller, Booklore, Hardcover) within ~30 seconds — no more waiting for the poll cycle. Also triggers instant sync on KoSync PUT from KOReader. Configurable via
ABS_SOCKET_ENABLEDandABS_SOCKET_DEBOUNCE_SECONDS. - Dashboard Search: Added instant client-side search filter to the dashboard. Users can now type in a "Search books..." field to filter the library by title or author in real time without a page reload.
- Sync Now & Mark Complete Actions: Added quick-action buttons to each book card — ⚡ triggers an immediate background sync cycle, and ✅ marks a book as finished across all configured platforms with an optional mapping cleanup prompt.
- Dashboard Version Badge: Cleaned up the version display badge. Dev builds now show
Build dev-Nand official releases showvX.Y.Zwithout redundant prefixes.
Bug Fixes
- Settings Save Not Restarting: Fixed a critical bug where saving settings from the UI did not actually restart the application. The restart function called
sys.exit(0)from a background thread, which in Python only raisesSystemExitin that thread — the main process kept running with stale configuration. All service singletons (Booklore, Storyteller, ABS socket, etc.) retained their old URLs, credentials, and settings until the container was fully rebuilt. Replaced withos.kill(SIGTERM)to properly signal the main process. - Booklore Refresh Retry Storm: Fixed an infinite retry loop when Booklore is slow or unreachable. Failed cache refreshes left the cache timestamp at zero, causing every subsequent sync cycle to immediately retry the full library scan — spiking CPU and flooding logs. Added a 5-minute cooldown after failed refreshes that suppresses retries while preserving normal cache TTL behavior on the happy path.
- ABS Socket.IO Auth Reliability: The socket connection was previously sending the auth token at the transport level (HTTP headers + Socket.IO CONNECT packet) in addition to the
"auth"event. On some ABS setups this caused both the primary token and the fallback to be rejected immediately. Auth is now sent exclusively via the"auth"event (the canonical ABS flow). If authentication fails, the listener disconnects cleanly and the bridge automatically falls back to the standard poll cycle — sync continues uninterrupted. - Storyteller Filename Prefix Compatibility: Ingestion now accepts both
00000-xxxxx.jsonand00001-xxxxx.jsonchapter prefixes. - Storyteller Format Guardrails: Backfill/ingest now validates chapter JSON shape (
dictwithwordTimeline) before ingesting, preventing invalid files from failing alignment after copy. - ABS Sync Lag with Storyteller Transcripts: Fixed delayed ABS synchronization behavior for Storyteller-transcript-backed books.
- Tri-Link Drift and Storyteller Jump Detection: Corrected drift handling and jump-detection logic to prevent incorrect position propagation.
- Storyteller Backfill and BookLore Reset Fallback: Fixed backfill messaging/flow and BookLore clear/reset fallback behavior.
- KOSync Hash Mismatch: Resolved a hash mismatch issue that occurred when the device epub differs from the bridge epub, preventing stale progress lookups.
- KOSync Shadow Documents: Fixed an issue where stale shadow documents could be returned in GET progress responses, causing incorrect sync positions.
- KOSync Admin Endpoints: Corrected auth handling on admin endpoints to allow dashboard access while keeping sensitive operations protected.
- Booklore Double Search: Fixed a redundant double-search issue in Booklore book lookups, improving match performance.
- Database Schema: Consolidated schema repair into a single clean Alembic migration, reducing startup migration time and preventing edge-case schema conflicts.
- Mark Complete Crash: Fixed a
TypeErrorin themark_completeendpoint caused by invalidLocatorResultkeyword arguments. - LRUCache Thread Safety: Added
threading.Lockto theLRUCacheclass inebook_utils.py. The cache is accessed concurrently by the sync daemon, forge background jobs, and web server requests, butOrderedDict.move_to_end()andpopitem()are not thread-safe for concurrent mutation. - Forge Service Audio Copying: Fixed an indentation error in the audio file copying logic that prevented files from being copied when found via exact path or suffix matching.
- ABS Socket.IO Feedback Loop: Fixed a self-triggering sync loop where BookBridge's own ABS progress writes fired a
user_item_progress_updatedsocket event, which the listener then treated as a real user change and scheduled another sync cycle. A module-level write-suppression tracker now stamps each book after a write; any socket event arriving within 60 seconds of that stamp is silently dropped. A single real progress change now produces exactly one sync cycle instead of three. - Booklore Full Library Scan on Progress Update: Fixed
update_progress()calling_refresh_book_cache()after every successful write, which fetched all books from the Booklore API on every sync cycle. Progress is now applied to the cached entry in-place. Full library scans still occur on initial load and the hourly staleness check.
Maintenance
- Comment Cleanup: Removed reflective/speculative inline comments for clearer, more maintainable code.