Bug fixes

This commit is contained in:
2026-07-05 17:52:43 +02:00
parent fb6108bd0c
commit c40531b6ae
12 changed files with 1196 additions and 946 deletions

46
server/lib/scanReview.js Normal file
View File

@@ -0,0 +1,46 @@
const { normalizeText } = require('./scanGrounding');
// Agreement must be judged on the RAW model answers, not the grounded ones:
// catalog grounding has a genus-level fallback that can collapse two different
// species onto the same catalog entry and fake an agreement.
const reviewAgreesWithPrimary = (rawPrimary, rawReview) => {
if (!rawPrimary || !rawReview) return false;
const primaryBotanical = normalizeText(rawPrimary.botanicalName);
const primaryName = normalizeText(rawPrimary.name);
const botanicalMatch = Boolean(primaryBotanical) && primaryBotanical === normalizeText(rawReview.botanicalName);
const nameMatch = Boolean(primaryName) && primaryName === normalizeText(rawReview.name);
return botanicalMatch || nameMatch;
};
// The review runs on a stronger model chain than the primary, and models are
// not calibrated against each other — so on disagreement the review wins even
// when it trails the primary by up to this margin.
const REVIEW_DISAGREEMENT_MARGIN = 0.05;
// A second low-confidence guess is not a verification: the review may only
// replace the primary when it agrees with it or is (near-)competitively
// confident. On agreement the higher-confidence variant wins (tie goes to
// the review, which runs on the stronger model chain).
const decideReviewOutcome = ({ primaryResult, reviewResult, agrees }) => {
const primaryConfidence = primaryResult?.confidence || 0;
const reviewConfidence = reviewResult?.confidence || 0;
if (agrees) {
return {
accept: true,
replace: reviewConfidence >= primaryConfidence,
reason: 'review-confirmed-primary',
};
}
if (reviewConfidence >= primaryConfidence - REVIEW_DISAGREEMENT_MARGIN) {
return { accept: true, replace: true, reason: 'review-overrode-primary' };
}
return { accept: false, replace: false, reason: 'review-rejected-low-confidence' };
};
module.exports = {
decideReviewOutcome,
reviewAgreesWithPrimary,
};