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
+11 -9
View File
@@ -12,10 +12,10 @@ import (
"git.fabledsword.com/bvandeusen/minstrel/internal/db/dbq"
)
// Fingerprinting settings (M400 #3913).
// Fingerprinting settings.
//
// Rule 25: what an operator might tune lives in the database and changes without
// a restart. One service instance is shared by the scanner, the backfill, the
// What an admin might tune lives in the database and changes without a
// restart. One service instance is shared by the scanner, the backfill, the
// duplicate sweep and the admin API, so a save reaches all of them at once.
//
// The length is the dangerous knob: chromaprints taken at two lengths cannot be
@@ -29,8 +29,9 @@ import (
// Bounds for each setting, mirrored by migration 0061's CHECKs.
const (
// Below 30s a print has too few items to align at the matcher's larger
// offsets and still overlap by minOverlapItems. Above 600s each print passes
// 20 KB and a candidate page of them grows past what one sweep should hold.
// offsets and still overlap by minOverlapItems. Above 600s each print
// passes 20 KB and a candidate page of them grows past what one sweep
// should hold.
minChromaprintLengthSec = 30
maxChromaprintLengthSec = 600
// Unrelated audio sits near 0.5; a ceiling of 0.35 keeps a loosened
@@ -55,9 +56,9 @@ type FingerprintSettings struct {
AcousticMaxBitErrorRate float64
BackfillConcurrency int32
SweepIntervalHours int32
// AutoResolve lets the duplicate resolver (M498) act on its own: merge
// copies no release needs. Off, it only classifies, and every group waits
// for the operator.
// AutoResolve lets the duplicate resolver act on its own: merge copies no
// release needs. Off, it only classifies, and every group waits for an
// admin.
AutoResolve bool
// UpdatedAt is when the settings were last saved. Set by the database;
// ignored by Set.
@@ -143,7 +144,8 @@ func validateFingerprintSettings(in FingerprintSettings) error {
case in.ChromaprintLengthSec < minChromaprintLengthSec || in.ChromaprintLengthSec > maxChromaprintLengthSec:
return fmt.Errorf("%w: chromaprint_length_sec must be %d-%d",
ErrFingerprintSettingOutOfRange, minChromaprintLengthSec, maxChromaprintLengthSec)
// Written as a negated range so NaN, which fails every comparison, is refused.
// Written as a negated range so NaN, which fails every comparison, is
// refused.
case !(in.AcousticMaxBitErrorRate >= minAcousticMaxBitErrorRate && in.AcousticMaxBitErrorRate <= maxAcousticMaxBitErrorRate):
return fmt.Errorf("%w: acoustic_max_bit_error_rate must be %.2f-%.2f",
ErrFingerprintSettingOutOfRange, minAcousticMaxBitErrorRate, maxAcousticMaxBitErrorRate)