Why now
BS#1351's rotation-picker gate trusts only search_type === 'direct'. The SEARCH_TYPE_CONFIDENCE table in the same file (apps/backend/services/library.service.ts:841) assigns positive confidence to the four search_types BS#1351 explicitly rejects:
const SEARCH_TYPE_CONFIDENCE: Record<LookupResponse['search_type'], number | null> = {
direct: 0.9,
fallback: 0.5,
alternative: 0.3,
compilation: 0.3,
song_as_artist: 0.3,
none: null,
};
Two trust policies live in the same file. The picker says non-direct is noise. The canonical-entity mapper says non-direct is signal worth quantifying. A reviewer can't tell which represents intended policy.
The fragility
fireAndForgetCanonicalEntity (apps/backend/controllers/library.controller.ts:148-165 per the BS-wide review) writes library.canonical_entity_id for ANY non-null linkage with no threshold check. flowsheet-linkage.service.ts:93 correctly gates with AUTO_ACCEPT_THRESHOLD = 0.9, blocking non-direct. But the threshold is the only thing stopping non-direct from materializing wrong data, and that's an easy guard to weaken under pressure (e.g., "add a gray-zone review queue, lower the threshold to 0.7 for recall").
The columns library.canonical_entity_id + library.canonical_entity_confidence retain the wrong-album linkages from low-confidence writes today. Any future consumer that reads canonical_entity_id without a confidence floor inherits the same Yenbett-class defect BS#1351 closed at the picker layer.
No current consumer materializes the wrong release_id through this path (projectMainRow in the library-identity-consumer job hardcodes discogs_release_id: null, so tier-2 of the picker reads NULL even when library.canonical_entity_id is low-confidence). But the configuration is fragile.
Proposed reconciliation
One of:
-
Set non-direct to null in the table to match the picker's policy. mapLookupToCanonicalEntity would return null for non-direct, fireAndForgetCanonicalEntity would no-op. Eliminates the low-confidence write path entirely.
-
Export a single trust predicate (isTrustedLmlAlbumMatch(response): boolean) from library.service.ts that derives search_type === 'direct' AND confidence >= AUTO_ACCEPT_THRESHOLD. Use it from the picker gate and from fireAndForgetCanonicalEntity's precondition.
-
Keep the table but add a hard threshold inside fireAndForgetCanonicalEntity (e.g., refuse to write below 0.9). Documents the asymmetric intent: confidence ranks are descriptive (for audit / future re-judging), not prescriptive.
Option 1 is the smallest change and lets the two policies converge. Option 2 captures the relationship explicitly. Option 3 preserves the original B-0 calibration framing.
Related
Why now
BS#1351's rotation-picker gate trusts only
search_type === 'direct'. TheSEARCH_TYPE_CONFIDENCEtable in the same file (apps/backend/services/library.service.ts:841) assigns positive confidence to the four search_types BS#1351 explicitly rejects:Two trust policies live in the same file. The picker says non-direct is noise. The canonical-entity mapper says non-direct is signal worth quantifying. A reviewer can't tell which represents intended policy.
The fragility
fireAndForgetCanonicalEntity(apps/backend/controllers/library.controller.ts:148-165per the BS-wide review) writeslibrary.canonical_entity_idfor ANY non-null linkage with no threshold check.flowsheet-linkage.service.ts:93correctly gates withAUTO_ACCEPT_THRESHOLD = 0.9, blocking non-direct. But the threshold is the only thing stopping non-direct from materializing wrong data, and that's an easy guard to weaken under pressure (e.g., "add a gray-zone review queue, lower the threshold to 0.7 for recall").The columns
library.canonical_entity_id+library.canonical_entity_confidenceretain the wrong-album linkages from low-confidence writes today. Any future consumer that readscanonical_entity_idwithout a confidence floor inherits the same Yenbett-class defect BS#1351 closed at the picker layer.No current consumer materializes the wrong release_id through this path (
projectMainRowin the library-identity-consumer job hardcodesdiscogs_release_id: null, so tier-2 of the picker reads NULL even whenlibrary.canonical_entity_idis low-confidence). But the configuration is fragile.Proposed reconciliation
One of:
Set non-direct to
nullin the table to match the picker's policy.mapLookupToCanonicalEntitywould returnnullfor non-direct,fireAndForgetCanonicalEntitywould no-op. Eliminates the low-confidence write path entirely.Export a single trust predicate (
isTrustedLmlAlbumMatch(response): boolean) fromlibrary.service.tsthat derivessearch_type === 'direct'ANDconfidence >= AUTO_ACCEPT_THRESHOLD. Use it from the picker gate and fromfireAndForgetCanonicalEntity's precondition.Keep the table but add a hard threshold inside
fireAndForgetCanonicalEntity(e.g., refuse to write below 0.9). Documents the asymmetric intent: confidence ranks are descriptive (for audit / future re-judging), not prescriptive.Option 1 is the smallest change and lets the two policies converge. Option 2 captures the relationship explicitly. Option 3 preserves the original B-0 calibration framing.
Related