Re-opens #114, which was auto-closed when its head branch was deleted
out from under it (the cleanup step ran before the merge was verified — see the
commit-order note below). Same work, now with origin/main merged in.
What is in here
fix(media-verify) — the verifier read the libraries with mode=ro&immutable=1, which makes SQLite skip the WAL: every committed-but-
uncheckpointed row reads as MISSING and a read beside a running scanner can fail
as "malformed database". Plain mode=ro first, immutable=1 only as the
fallback, and the verdict now splits REAL / gone / not-indexed instead of
guessing from the database alone. 3 tests in tests/media_verify.bats.
docs(media) — Media Metadata View said "not deployed, verified
2026-10-31"; it is deployed and serving both servers. Page + AGENTS.md row
corrected (main's paragraph on the same fact, including the restart-aborts-a-scan
law, is kept alongside the re-verification). New page Media Duplicate Prune:
the screen ladder, keep rules, guards, the hold/purge law, and how media-verify.py has to be read for a prune. Media Relayout.md keeps a
pointer — carrying the section blew the vault's 500-line ceiling.
docs(media) (second commit) — the deferred Plex leg (stopped + masked so
its metadata fetches cannot stack on Jellyfin's scan; unmask before morning)
and the guards a detritus sweep must respect: external subtitle folders and
ripped Blu-ray streams (.sup, .thd, .eac3, .dts, .cci) are not trash,
and an unrecognised extension is a reason to stop.
Merge state
origin/main moved 31 commits during the work (the jellyfin-provider-keys and .AGENTTRASH-untracking lines), so main is merged in rather than rebased; the two
lint conflicts in AGENTS.md and the metadata-view page were resolved by keeping
both sides' facts.
Evidence
tests/run.sh on the merged tree: all tests pass. scripts/check-okf.py:
0 violations. Index seam: regeneration is a no-op.
Fleet state this branch records (not a proposal): 226 files (~1.1 TiB) held for
dupes pending Frank's purge decision; 423 detritus files (12 MiB) + 542 empty
folders swept into a second dated hold; Jellyfin scanning; Plex masked overnight.
Re-opens #114, which was **auto-closed** when its head branch was deleted
out from under it (the cleanup step ran before the merge was verified — see the
commit-order note below). Same work, now with `origin/main` merged in.
## What is in here
- **`fix(media-verify)`** — the verifier read the libraries with
`mode=ro&immutable=1`, which makes SQLite skip the WAL: every committed-but-
uncheckpointed row reads as MISSING and a read beside a running scanner can fail
as "malformed database". Plain `mode=ro` first, `immutable=1` only as the
fallback, and the verdict now splits `REAL` / `gone` / `not-indexed` instead of
guessing from the database alone. 3 tests in `tests/media_verify.bats`.
- **`docs(media)`** — [[Media Metadata View]] said "not deployed, verified
2026-10-31"; it is deployed and serving both servers. Page + `AGENTS.md` row
corrected (main's paragraph on the same fact, including the restart-aborts-a-scan
law, is kept alongside the re-verification). New page [[Media Duplicate Prune]]:
the screen ladder, keep rules, guards, the hold/purge law, and how
`media-verify.py` has to be read for a prune. `Media Relayout.md` keeps a
pointer — carrying the section blew the vault's 500-line ceiling.
- **`docs(media)` (second commit)** — the deferred Plex leg (stopped + masked so
its metadata fetches cannot stack on Jellyfin's scan; `unmask` before morning)
and the guards a detritus sweep must respect: external subtitle folders and
ripped Blu-ray streams (`.sup`, `.thd`, `.eac3`, `.dts`, `.cci`) are not trash,
and an unrecognised extension is a reason to stop.
## Merge state
`origin/main` moved 31 commits during the work (the jellyfin-provider-keys and
`.AGENTTRASH`-untracking lines), so main is merged in rather than rebased; the two
lint conflicts in `AGENTS.md` and the metadata-view page were resolved by keeping
both sides' facts.
## Evidence
`tests/run.sh` on the merged tree: **all tests pass**. `scripts/check-okf.py`:
0 violations. Index seam: regeneration is a no-op.
Fleet state this branch records (not a proposal): 226 files (~1.1 TiB) held for
dupes pending Frank's purge decision; 423 detritus files (12 MiB) + 542 empty
folders swept into a second dated hold; Jellyfin scanning; Plex masked overnight.
---
cwd: /home/blank/.omp/wt/wt-20261030-163847-6d1fc1f · session: 01a18f2e-18b1-7573-bcd5-ac99636f8bcb
`mode=ro&immutable=1` claims the file never changes, so sqlite skips the
write-ahead log entirely: every row the server has committed but not yet
checkpointed reads as MISSING, and a read beside a running scanner can fail
outright as "database disk image is malformed". Both servers keep their
libraries in WAL, so plain `mode=ro` is now the first door and `immutable=1`
only the fallback for a database whose `-shm` cannot be read.
The verdict also stopped guessing from the database alone. A file still at its
`src` is REAL (this pass's own damage); a file at neither path is `gone` (a
later pass or the server renamed it); a file sitting at `dst` with no row
naming it is something the server does not index. A row that still names `src`
is none of those — it is the server's stale pointer, and it costs a re-scan,
never a restore.
`Media Metadata View.md` said "Not deployed on Dankserver — verified
2026-10-31". That was true yesterday and is false now: the overlay is mounted
and both installed quadlets bind it (`view:/data` rw for Jellyfin,
`view:/mnt/entropy:ro` for Plex). The page now states the live shape and the
order that proves it — `media-view.sh verify`, then the `Volume=` lines —
because the whole point of the page is to answer "is the view really serving?".
`AGENTS.md` carried the same stale claim in its summary table.
`Media Duplicate Prune.md` is new: the screen ladder (size, then head+tail
blake2b, then a sparse-window confirmation before anything moves), which copy
survives and why, the guards that each encode a file that would otherwise have
been destroyed (qBittorrent `.!qB` state, year-required with digits kept,
feature length, disc/part exclusion, media containers only), and the law that a
hold on the same volume frees nothing until it is purged. It also carries the
different way `media-verify.py` has to be READ for a prune — `landed: 0` is the
correct end state because no server may index the hold — and the planner bug
that class explains: when the planner re-derived "largest wins" from the hold
list alone it dropped every keeper out of its own group and pruned 17 files
instead of 205.
`Media Relayout.md` keeps a one-line pointer; carrying the whole procedure there
pushed it past the vault's 500-line ceiling, which is the linter telling the
truth about progressive disclosure.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Re-opens #114, which was auto-closed when its head branch was deleted
out from under it (the cleanup step ran before the merge was verified — see the
commit-order note below). Same work, now with
origin/mainmerged in.What is in here
fix(media-verify)— the verifier read the libraries withmode=ro&immutable=1, which makes SQLite skip the WAL: every committed-but-uncheckpointed row reads as MISSING and a read beside a running scanner can fail
as "malformed database". Plain
mode=rofirst,immutable=1only as thefallback, and the verdict now splits
REAL/gone/not-indexedinstead ofguessing from the database alone. 3 tests in
tests/media_verify.bats.docs(media)— Media Metadata View said "not deployed, verified2026-10-31"; it is deployed and serving both servers. Page +
AGENTS.mdrowcorrected (main's paragraph on the same fact, including the restart-aborts-a-scan
law, is kept alongside the re-verification). New page Media Duplicate Prune:
the screen ladder, keep rules, guards, the hold/purge law, and how
media-verify.pyhas to be read for a prune.Media Relayout.mdkeeps apointer — carrying the section blew the vault's 500-line ceiling.
docs(media)(second commit) — the deferred Plex leg (stopped + masked soits metadata fetches cannot stack on Jellyfin's scan;
unmaskbefore morning)and the guards a detritus sweep must respect: external subtitle folders and
ripped Blu-ray streams (
.sup,.thd,.eac3,.dts,.cci) are not trash,and an unrecognised extension is a reason to stop.
Merge state
origin/mainmoved 31 commits during the work (the jellyfin-provider-keys and.AGENTTRASH-untracking lines), so main is merged in rather than rebased; the twolint conflicts in
AGENTS.mdand the metadata-view page were resolved by keepingboth sides' facts.
Evidence
tests/run.shon the merged tree: all tests pass.scripts/check-okf.py:0 violations. Index seam: regeneration is a no-op.
Fleet state this branch records (not a proposal): 226 files (~1.1 TiB) held for
dupes pending Frank's purge decision; 423 detritus files (12 MiB) + 542 empty
folders swept into a second dated hold; Jellyfin scanning; Plex masked overnight.
cwd: /home/blank/.omp/wt/wt-20261030-163847-6d1fc1f · session: 01a18f2e-18b1-7573-bcd5-ac99636f8bcb