Files
Frank 42bc482ed8 docs(media): campaign artifacts live in /mnt/entropy/.media-campaign
The array root carried 48 planning artifacts (journals, plans, run logs)
accumulated by the relayout campaigns since 2026-11-02. They sit beside the
libraries now, which is how a media server ends up indexing a journal.

Moved all 48 (219.8 MiB) into the dot-directory `/mnt/entropy/.media-campaign`
with a journaled `media-apply` run (plan, apply, verify — 48 verified at their
targets, 0 root files left). Jellyfin and Plex ignore dot-directories, and the
overlay view exposes the array root to both servers, so the same pollution
existed on the view side.

Every vault page that named a root-level journal path is rewritten to the new
home (26 occurrences across 6 pages), and the law is stated once, in
[[Media Relayout]], which owns the tool chain: `media-apply.py` defaults its
journal to `media-relayout.jsonl` beside `--root`, so a run that omits
`--journal` recreates exactly the root-level log this now forbids.
2026-11-02 17:44:49 -08:00

3.2 KiB

type, title, description, tags, timestamp
type title description tags timestamp
reference Media Music Relayout Re-filing /mnt/entropy/Music by Jellyfin's tag rows: the census, the album key, the refusals.
dankserver
media-server
jellyfin
media-relayout
2026-10-31T00:00:00Z

Media Music Relayout

/mnt/entropy/Music is rips and discography packs, and Jellyfin has matched and tagged almost all of it. scripts/media-music.py re-files it into the shape Jellyfin's music scanner reads —

Music/<album artist>/<Album> (<year>)/NN - <Title>.ext

— and the authority is the tag row of the track, never the name the ripper gave the file. The shared gates, the executor, the journal law and the rollback live in Media Relayout; this page is the music arm only.

# 1. The authority: Jellyfin's audio rows, one per track, with the album and
#    artist ids its own database carries (the DB opens read-only).
python3 scripts/media-census.py music --root /mnt/entropy/Music \
    --out /tmp/music_rows.tsv
# 2. What is on disk (stat only).
python3 scripts/media-census.py enumerate --root /mnt/entropy/Music \
    --out /tmp/music_enum.tsv
# 3. The plan.
python3 scripts/media-music.py --root /mnt/entropy/Music --enum /tmp/music_enum.tsv \
    --rows /tmp/music_rows.tsv --out /tmp/music_plan.tsv \
    --exceptions /tmp/music_exceptions.txt
# 4. Read the exceptions file FIRST — it is the review, not a log. Then the same
#    executor, journal and rollback as [[Media Relayout]] shows, on its own journal.
scripts/media-apply.py apply --plan /tmp/music_plan.tsv --root /mnt/entropy \
    --journal /mnt/entropy/.media-campaign/media-relayout-music.jsonl --apply

The group is what the tags assert, not where the files sit: (album-artist tag, album, year). One album arrives as three disc folders and as two copies of one rip, and one MusicBrainz release group is one album. A compilation is one album whose tracks name many performers, so it files once under Various Artists: keying on the performer would file one album once per artist. Two different album-artist tags on one album name are two albums, which is what Jellyfin's two album items say.

What it refuses:

+- A sidecar is placed by the audio around it, never by its own name. A .lrc, .txt or picture that shares a track's stem follows that track and takes the name the track now has, or Jellyfin cannot find it; anything else goes to the album its own folder was placed in, or to the folder whose discs sit one level below it. A folder whose audio belongs to two albums parks its sidecar rather than guessing. +- An image album keeps its name. A folder holding one audio file and a .cue is a whole album in one file; numbering it 01 - … tells Jellyfin to index it as one track. +- A video container parks, because Jellyfin will not index it as music and a rename to .m4a would claim it is; audio no provider row names parks too, because unmatched audio is a tagging job, not a renaming job.

ONE writer at a time on this array: two rename passes race, and neither journal tells. Verify the run against Jellyfin's own tables — see Proving the move landed in Media Relayout.

See Also

Media Relayout, Jellyfin, Media Audiobook Relayout