docs: library comments say what the scanner and resolver do, not how they came to be (#6277)
release / govulncheck (push) Successful in 20s
release / web (push) Successful in 1m20s
release / go (push) Successful in 1m37s
release / integration (push) Successful in 5m15s
release / android (push) Successful in 5m26s
release / Build signed APK (releases and dev) (push) Successful in 5m45s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 16s
release / Verify release artifacts (tag releases only) (push) Skipped

Rewrites the internal/library comment blocks to rule 32. Task, milestone,
decision and rule ids are gone; the incidents behind them are restated as
the constraint they left (why a file is deleted before its row, why the
missing mark is a mark, why duplicates block on duration). Counts and
album names from one library are dropped from production comments; test
comments keep the names their fixtures use. The tagReadVersion log keeps
each version's before and after, without the measurements.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-23 12:27:34 -04:00
co-authored by Claude Opus 5.5
parent 08a2c06b85
commit 7e6228c13f
66 changed files with 578 additions and 564 deletions
+19 -20
View File
@@ -17,7 +17,7 @@ import (
syncpkg "git.fabledsword.com/bvandeusen/minstrel/internal/sync"
)
// Duplicate resolver (M498 #5435, #5437; M502 #5517).
// Duplicate resolver.
//
// The sweep proposes duplicate groups; the resolver decides what each one is
// and settles the ones that are safe to settle without asking. Minstrel is the
@@ -29,8 +29,7 @@ import (
// - Across releases, each copy belongs to its own release (a single and its
// album): nothing is removed, and the copies are linked as one song. An
// album holding the song twice among them still holds it once: its extra
// copies are merged into its best (Humanz held Saturnz Barz twice beside
// the single, #5401).
// copies are merged into its best.
// - Except that a video rip is no release's copy. When every copy but one is
// a rip, across releases or under another title, the rips are merged into
// the one that is not.
@@ -40,7 +39,7 @@ import (
// lengths say which slot it belongs to, or AcoustID which song it is when
// each copy was cut to its own slot's length, and the copies in the other
// slots are removed so the album is fetched again (duplicate_settle.go).
// - Anything else waits for the operator.
// - Anything else waits for an admin.
const (
// resolveMergeCap bounds the merges one pass makes. The first pass after
@@ -50,7 +49,7 @@ const (
// duplicateResolveTick is how often the worker runs a pass.
duplicateResolveTick = time.Hour
// scanWaitRetry is how soon a pass put off for a running scan is tried
// again: a boot scan takes under a minute on the operator's library.
// again; a boot scan is short.
scanWaitRetry = time.Minute
)
@@ -83,7 +82,7 @@ type resolveGroup struct {
}
// isRip says whether a copy is a video rip: held back as one, or named like
// one and not kept by the operator. The name is read as well as the verdict
// one and not kept by an admin. The name is read as well as the verdict
// because a pass reads the groups before it flags new rips.
func isRip(m dbq.ListDuplicateGroupsForResolveRow) bool {
if m.SourceVerdict != nil {
@@ -141,7 +140,7 @@ type ResolveSources struct {
Identify RecordingIdentifier
}
// ResolveDuplicates runs one pass. act is the operator's auto-resolve setting;
// ResolveDuplicates runs one pass. act is the auto-resolve setting;
// with it off, the pass only classifies. It decides from what the library and
// catalogue hold; ResolveDuplicatesWith may also ask MusicBrainz and AcoustID.
func ResolveDuplicates(
@@ -238,14 +237,13 @@ func ResolveDuplicatesWith(
}
// foldAlbumCopies merges, in each cross-release group, the extra copies one
// album holds of the song into the best of that album's copies: the one that
// is not a video rip when only one is not, else ProposeSurvivor's choice.
// Copies whose title or file name name different versions (versionWords) are
// not folded: "Suite-Pee" and "Suite-Pee (Clean Version)" carried one title tag
// on 2026-10-20, and the explicit copy went. The
// copies on other releases stay and are linked as one song. At most budget
// copies go. It returns how many went and the songs they were, and drops them
// from their groups.
// album holds of the song into the best of that album's copies: the one that is
// not a video rip when only one is not, else ProposeSurvivor's choice. Copies
// whose title or file name name different versions (versionWords) are not
// folded, even when they carry one title tag: a song and its clean version are
// both kept. The copies on other releases stay and are linked as one song. At
// most budget copies go. It returns how many went and the songs they were, and
// drops them from their groups.
func foldAlbumCopies(
ctx context.Context, pool *pgxpool.Pool, logger *slog.Logger, dataDir string,
groups []*resolveGroup, merged map[pgtype.UUID]bool, budget int,
@@ -358,9 +356,10 @@ func foldAlbumCopy(
return nil
}
// linkCrossRelease links each cross-release group's copies as one song
// (#5438): a like on one is a like on all, and the Liked list, shuffle and the
// mixes count the song once. A group the pass merged has nothing left to link. Linking an already-linked group changes nothing,
// linkCrossRelease links each cross-release group's copies as one song: a
// like on one is a like on all, and the Liked list, shuffle and the
// mixes count the song once. A group the pass merged has nothing left to link.
// Linking an already-linked group changes nothing,
// so this runs every pass; likes are shared only when a link is new, since a
// like made after it reaches every copy as it is made.
func linkCrossRelease(
@@ -597,8 +596,8 @@ func (w *DuplicateResolveWorker) tickOnce(ctx context.Context) (waitForScan bool
return false
}
// A scan in flight has listed the files it will reconcile: a copy removed
// now is marked present again when it does (7 of the 13 removed at boot
// on 2026-10-20, #6169). A run past StuckScanThreshold is a dead one.
// now is marked present again when it does. A run past StuckScanThreshold
// is a dead one.
run, err := q.GetInFlightScanRun(ctx)
switch {
case err == nil && time.Since(run.StartedAt.Time) <= StuckScanThreshold: