media-apply.py gains a fourth subcommand, sweep: it removes the release folders an apply emptied. The live relayout moved 8189 files and left 1675 empty husks at the library root — clutter that confuses Jellyfin's folder browser and every human reading the share.
The law it enforces
A sweep deletes only what the journal proves this run emptied:
a journalled move went out of the folder, or out of something under it;
the folder now holds nothing but empty directories;
no journalled destination lives beneath it (never a live target subtree);
it is not a folder the run created (rollback already handles those).
A folder nobody moved cannot be selected at all, so a hand-made placeholder survives untouched. Deepest-first: Extras/ is only a candidate if the journal moved files out of it too. A symlink anywhere inside disqualifies the whole subtree — the thing behind a link is not this tool's to delete. A journal whose moves belong to another --root is refused.
Every removal is journalled as rmdir, so rollback recreates the folders a sweep removed: one command undoes the whole change, moves and sweep alike.
Evidence
tests/media_relayout.bats — 6 new behaviour tests, written red first (sweep was an unknown subcommand), now green: dry-run writes nothing and reports the count; a content-holding folder stays; rollback restores folders and files; a second sweep says there is nothing to do; symlink guard; cross-library journal guard; idempotence.
./tests/run.sh — 621 tests, all pass.
serverAppConfigs-docs/Dankserver/Media Relayout.md — the sweep command shape, the journal's real path (/mnt/entropy/media-relayout.jsonl, never /tmp), the Plex rescan recipe (the API answers only through its own netns), and the new law that an apply breaks Plex playback until the section is rescanned.
A sweep deletes no media file: only directories the journal proves empty.
## What
`media-apply.py` gains a fourth subcommand, `sweep`: it removes the release folders an apply emptied. The live relayout moved 8189 files and left **1675 empty husks** at the library root — clutter that confuses Jellyfin's folder browser and every human reading the share.
## The law it enforces
A sweep deletes only what the journal *proves this run emptied*:
- a journalled `move` went out of the folder, or out of something under it;
- the folder now holds nothing but empty directories;
- no journalled destination lives beneath it (never a live target subtree);
- it is not a folder the run created (rollback already handles those).
A folder nobody moved cannot be selected at all, so a hand-made placeholder survives untouched. Deepest-first: `Extras/` is only a candidate if the journal moved files out of it too. A symlink anywhere inside disqualifies the whole subtree — the thing behind a link is not this tool's to delete. A journal whose moves belong to another `--root` is refused.
Every removal is journalled as `rmdir`, so `rollback` recreates the folders a sweep removed: one command undoes the whole change, moves and sweep alike.
## Evidence
- `tests/media_relayout.bats` — 6 new behaviour tests, written red first (`sweep` was an unknown subcommand), now green: dry-run writes nothing and reports the count; a content-holding folder stays; rollback restores folders *and* files; a second sweep says there is nothing to do; symlink guard; cross-library journal guard; idempotence.
- `./tests/run.sh` — 621 tests, all pass.
- `serverAppConfigs-docs/Dankserver/Media Relayout.md` — the sweep command shape, the journal's real path (`/mnt/entropy/media-relayout.jsonl`, never `/tmp`), the Plex rescan recipe (the API answers only through its own netns), and the new law that an apply breaks Plex playback until the section is rescanned.
A sweep deletes no media file: only directories the journal proves empty.
---
cwd: /home/blank/.omp/wt/wt-20261030-163847-6d1fc1f · session: 01a18f2e-18b1-7573-bcd5-ac99636f8bcb
An apply leaves every release folder it emptied standing where it was: the
live library run left 1675 husks at the root. sweep takes the same journal
and deletes only folders it can prove this run emptied - a journalled move
out of the folder or something under it, nothing but empty directories left,
no journalled destination beneath it, not a folder the run created. A folder
nobody moved cannot be selected at all, so a hand-made placeholder survives,
and a symlink anywhere inside disqualifies the subtree. Every rmdir is
journalled, so rollback recreates what a sweep removed.
dank
merged commit dd76fcf5d4 into main2026-10-30 20:04:24 -07:00
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.
What
media-apply.pygains a fourth subcommand,sweep: it removes the release folders an apply emptied. The live relayout moved 8189 files and left 1675 empty husks at the library root — clutter that confuses Jellyfin's folder browser and every human reading the share.The law it enforces
A sweep deletes only what the journal proves this run emptied:
movewent out of the folder, or out of something under it;A folder nobody moved cannot be selected at all, so a hand-made placeholder survives untouched. Deepest-first:
Extras/is only a candidate if the journal moved files out of it too. A symlink anywhere inside disqualifies the whole subtree — the thing behind a link is not this tool's to delete. A journal whose moves belong to another--rootis refused.Every removal is journalled as
rmdir, sorollbackrecreates the folders a sweep removed: one command undoes the whole change, moves and sweep alike.Evidence
tests/media_relayout.bats— 6 new behaviour tests, written red first (sweepwas an unknown subcommand), now green: dry-run writes nothing and reports the count; a content-holding folder stays; rollback restores folders and files; a second sweep says there is nothing to do; symlink guard; cross-library journal guard; idempotence../tests/run.sh— 621 tests, all pass.serverAppConfigs-docs/Dankserver/Media Relayout.md— the sweep command shape, the journal's real path (/mnt/entropy/media-relayout.jsonl, never/tmp), the Plex rescan recipe (the API answers only through its own netns), and the new law that an apply breaks Plex playback until the section is rescanned.A sweep deletes no media file: only directories the journal proves empty.
cwd: /home/blank/.omp/wt/wt-20261030-163847-6d1fc1f · session: 01a18f2e-18b1-7573-bcd5-ac99636f8bcb