- merge-catalog: stop dropping anilist_id on every new anime insert
(bun:sqlite .get() returns null, so the old !== undefined guard always
fired); the guard was dead anyway since a colliding id is caught earlier
- sync-command: throw instead of fail() inside runHostSync so the finally
block runs and temp dirs holding snapshot data are cleaned up on failure
- ssh: shell-quote the user-supplied --remote-cmd in the probe, and reject
option-like (-prefixed) SSH hosts that ssh/scp would parse as flags
- sync-db: close the remote handle if opening the local DB throws
- sync-shared: treat EPERM from process.kill(pid, 0) as alive, not dead
- cli-parser: trim the sync host before the mode-exclusivity check
- tests: cover anilist_id preservation, anilist-based anime matching, and
the SSH host/shell-quote guards
subminer sync <host> exchanges VACUUM INTO snapshots over ssh/scp and each
side merges the other's data as an insert-only union keyed on session UUIDs,
video keys, series title keys, and word/kanji identity. Lifetime totals and
daily/monthly rollups are applied incrementally so pre-retention history
survives, remote-only historical rollups are copied, and re-syncing is
idempotent. sync --snapshot/--merge expose the underlying steps for manual
transfers; a pid-file/mpv-socket guard refuses to run while SubMiner may be
writing the database and schema-version mismatches abort the merge.