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
+14 -12
View File
@@ -18,17 +18,17 @@ import (
"git.fabledsword.com/bvandeusen/minstrel/internal/db/dbq"
)
// AcoustID lookup worker (M401 #3921).
// AcoustID lookup worker.
//
// A track whose tags carry no recording MBID is invisible to the ListenBrainz
// similarity arm: it is never a seed and never comes back as a result. This
// worker fingerprints such tracks and asks AcoustID which recording they are,
// writing an id only when the answer is unambiguous (D5). The file's own tag
// always outranks it (D4).
// writing an id only when the answer is unambiguous (chooseRecording). The
// file's own tag always outranks it.
//
// It never gates anything else (rule 164). With no key, switched off or
// AcoustID unreachable, it idles and says why through Status; scans and
// playback do not notice.
// It never gates anything else. With no key, switched off or AcoustID
// unreachable, it idles and says why through Status; scans and playback do
// not notice.
// acoustIDLookupTick is how often the worker looks for work. A settings save
// starts a pass at once, so this only paces new tracks and retries after an
@@ -187,7 +187,7 @@ func (w *AcoustIDLookupWorker) Run(ctx context.Context) {
}
// runOnce contains a pass so that nothing it does (an error, a panic) can stop
// the next one from starting (rule 157).
// the next one from starting.
func (w *AcoustIDLookupWorker) runOnce(ctx context.Context) {
w.setStatus(func(s *AcoustIDLookupStatus) { s.Running = true })
problem := ""
@@ -216,8 +216,8 @@ func (w *AcoustIDLookupWorker) runOnce(ctx context.Context) {
"no_match", res.NoMatch, "failed", res.Failed, "inconclusive", res.Inconclusive)
}
// A recording MBID AcoustID just gave a replacement may be the one its
// missing predecessor carried (M485): most of the operator's stale rows
// became pairable exactly this way.
// missing predecessor carried, which makes the pair foldable
// (PairMissingTracks).
if res.Matched > 0 && ctx.Err() == nil {
if _, err := PairMissingTracks(ctx, w.pool, w.logger); err != nil && ctx.Err() == nil {
w.logger.Warn("acoustid lookup: missing-pair pass failed", "err", err)
@@ -322,7 +322,8 @@ func (w *AcoustIDLookupWorker) lookupTrack(
if isInconclusive(err) {
return "", nil
}
// fpcalc ran and rejected the file: a verdict, settled until it changes.
// fpcalc ran and rejected the file: a verdict, settled until it
// changes.
return w.store(ctx, row, lookupDecision{state: lookupFailed, detail: err.Error()}), nil
}
cands, err := w.client.Lookup(ctx, cfg.APIKey, fp.fingerprint, fp.durationSec)
@@ -351,7 +352,7 @@ func (w *AcoustIDLookupWorker) lookupTrack(
var ErrIdentifyUnavailable = errors.New("acoustid: cannot be asked now")
// IdentifyRecordings asks AcoustID which recordings a file may be, for the
// duplicate resolver (#6169): every candidate at or above the minimum score,
// duplicate resolver: every candidate at or above the minimum score,
// best first. None is an answer: AcoustID does not know the audio. Nothing is
// stored; the file's own lookup is the worker's.
func (w *AcoustIDLookupWorker) IdentifyRecordings(ctx context.Context, path string) ([]string, error) {
@@ -432,7 +433,8 @@ type lookupDecision struct {
detail string
}
// chooseRecording applies D5 to AcoustID's candidates (best score first):
// chooseRecording picks a recording from AcoustID's candidates (best score
// first):
// only recordings at or above minScore count, one of them is a match, and
// several are told apart by the track's title and length or not at all. A
// wrong MBID would feed similarity the wrong neighbours, which is worse than