An album the user holds 2 of 10 tracks of showed a green tick reading
"is in your library", and the mechanism was our own writer. tagwriter
wrote track and disc *numbers* and dropped the totals, so autotagging a
folder made the release MBID-matched -- which is what earns the tick --
while erasing the one field GetAlbumCompleteness reads. The evidence
for "2 of 10" was destroyed by the act that produced the tick.
FieldTotalTracks and FieldTotalDiscs are written as the ID3 "n/N" form
and as Vorbis TRACKTOTAL/DISCTOTAL; the autotag apply pass and the
download importer fill them from the release's own tracklist; and
dbsync persists the track total to audio_files.total_tracks so the
album page agrees with the file without waiting for a rescan.
Five things about it are load-bearing, and four fail silently:
- The total is per *disc*, not per release, because that is what the
tag form declares and what GetAlbumCompleteness sums per disc. A
release total on every file multiplies a two-disc album's expectation
by two, which no library can satisfy. backend/tagtotals is that
derivation once, since the two callers must not import the writer or
each other.
- The Vorbis names are TRACKTOTAL and DISCTOTAL and no other spelling.
dhowden/tag reads exactly those two keys, so TOTALTRACKS -- which
xiph lists and several taggers write -- or a "1/12" packed into
TRACKNUMBER writes successfully and reads back as no total at all.
The tests therefore assert the round trip through the reader the scan
uses, not through the bytes.
- ID3's number and total share one frame, so writing either alone must
read the other off the existing tag or discard it. A total with no
number is not written: "/12" parses as track 0.
- The totals are written unconditionally rather than on a diff. The
case this exists for is a file declaring no total at all, which
compares equal to nothing and is exactly what a "only if it changed"
guard skips.
- A single-track download is not totalled. A RecordingMBID anchor
resolves Expected to that one track, so the same code would tag a
track off a twelve-track album "1 of 1" -- and a declared total
outranks the catalog total that would have answered correctly.
autotag's field constants are a second copy of tagwriter's, deliberately
so autotag stays out of the write pipeline's import graph. A key that
drifts neither fails to compile nor fails to write -- the writer simply
finds nothing under the name it looks for -- so autotagservice, the one
package importing both, now pins them.
Steps 2 and 3 of the issue stay open under #38: the catalog fallback
already landed as completenessAnswer(), and the badge call-site audit is
the part that overlaps it.
Closes#16