* fix(autoscan): advance marker past paths outside any library folder
A filesystem-watcher scan source (e.g. the CephFS plugin) observes the
entire volume, so it legitimately returns changes for paths that live in
folders which are not registered as Silo libraries (unregistered decade
buckets, 4k-dv, anime-dub, download/recycle dirs, etc.).
Previously, when a poll returned paths but none resolved to a library
folder, PollOnce recorded an "unresolved" error and refused to advance
the marker, on the assumption this only happens for a freshly-enabled
source with unconfigured path rewrites. For a whole-volume watcher that
assumption is wrong: a single change under an unregistered folder pins
the journal marker in place, so every subsequent poll re-reads the same
window and autoscan stalls permanently. Real imports pile up behind the
stuck marker and are never scanned until the next full library scan.
Treat "paths returned but none resolved" as a benign, expected condition:
log a warning (so an operator can still investigate a genuinely
misconfigured source) and advance the marker so the queue keeps moving.
Partial resolution was already handled correctly — the unresolved subset
is simply outside Silo's libraries.
Observed in production: one file added under movies/4k-dv (not a library
path) froze the CephFS source for ~18 days; ~42k journal changes had
accumulated behind it. With this change the marker advances and the
backlog drains on the next poll.
* fix(autoscan): hold marker on transient resolve failures, keep unresolved events visible
Review follow-up: advancing past a window where nothing resolved is only
safe when every path is genuinely outside Silo's libraries (RequestError).
When resolve attempts fail internally (resolver/database fault), the same
resolvedAny=false state now holds the marker and records the error so the
window is retried once the fault clears, instead of silently skipping
imports until the next full library scan.
The benign outside-libraries case still advances, but finishes its poll
event as "unresolved" (with an explaining message) instead of "success",
so the condition stays visible in poll history and the existing
unresolved status filter in the API/admin UI keeps working. Stale doc
comments on PollOnce and AdvanceMarker updated to match the new behavior.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(autoscan): hold marker when any resolve attempt fails transiently, not only when all do
The transient-failure hold was gated inside the nothing-resolved branch, so
a mixed window (some paths resolved+enqueued, others failed on an internal
resolver fault) still advanced the marker past the failed paths. Hoist the
gate: any internal resolve failure now records the error and holds the
marker regardless of how many paths resolved. The resolved targets were
already enqueued; re-reading the window at worst re-scans them, which is
safe. Adds a mixed-window regression test.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Quick <31828688+Quick104@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>