fix: resolve Live catalog projection failure during Analyze again in Laya mode (#17)
Fix the regression introduced by the weighted Laya signal (#16): rebuild now merges exact fingerprints in every engine mode after evaluating hard blockers, compares candidates against all variants of a group, falls back to deterministic scoring when Laya is unavailable, and reports transaction errors safely. Non-regression tests cover the Laya-mode rebuild path; verified against a real catalog copy (39,341 streams rebuilt successfully). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -7,6 +7,7 @@ const {
|
||||
} = require('../server/services/liveGroupingScoring');
|
||||
const {
|
||||
collectIdentityHints,
|
||||
collectOptionalIdentityHints,
|
||||
normalizeChannelName,
|
||||
projectCatalog
|
||||
} = require('../server/services/liveProjectionService');
|
||||
@ -44,6 +45,16 @@ test('exact algorithm match survives a contradictory Laya opinion', () => {
|
||||
assert.equal(score.signals.laya, 0);
|
||||
});
|
||||
|
||||
test('exact generic fingerprints merge in Laya-only mode without family metadata', () => {
|
||||
const left = channel('a', '1000 x Hora TV', { category_id: 'one' });
|
||||
const right = channel('b', '|UY| 1000 x Hora TV', { category_id: 'two' });
|
||||
const score = scoreCandidate(left, right, { mode: 'laya' });
|
||||
assert.equal(score.total, 55);
|
||||
assert.equal(score.matched, true);
|
||||
const groups = projectCatalog([left, right], { mode: 'laya' });
|
||||
assert.equal(groups.length, 1);
|
||||
});
|
||||
|
||||
test('different channel numbers block even when Laya proposes a merge', () => {
|
||||
const left = channel('a', 'beIN Sports 1');
|
||||
const right = channel('b', 'beIN Sports 2');
|
||||
@ -110,3 +121,28 @@ test('hybrid mode caps the positive Laya contribution at weight 10', () => {
|
||||
assert.equal(score.total, 72);
|
||||
assert.equal(score.matched, true);
|
||||
});
|
||||
|
||||
test('Laya bridge followed by an exact alias stays in one unique fingerprint group', () => {
|
||||
const items = [
|
||||
channel('a', 'beIN Sports 1 Event'),
|
||||
channel('b', 'beIN Sports 1'),
|
||||
channel('c', 'beIN Sports 1')
|
||||
];
|
||||
const hints = new Map([[
|
||||
['a', 'b'].sort().join('\0'),
|
||||
{ sameIdentityProbability: 1, confidence: 1 }
|
||||
]]);
|
||||
const groups = projectCatalog(items, { mode: 'hybrid', identityHints: hints });
|
||||
assert.equal(groups.length, 1);
|
||||
assert.equal(groups[0].fingerprint, 'bein sports 1');
|
||||
assert.equal(groups[0].variants.length, 3);
|
||||
});
|
||||
|
||||
test('optional Laya failure degrades to an empty signal set', async () => {
|
||||
const hints = await collectOptionalIdentityHints([
|
||||
channel('a', 'beIN Sports 1 Event'), channel('b', 'beIN Sports 1')
|
||||
], 'hybrid', {
|
||||
identityHintBatch: async () => { throw new Error('runtime unavailable at https://private.invalid'); }
|
||||
});
|
||||
assert.equal(hints.size, 0);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user