62 lines
2.6 KiB
JavaScript
62 lines
2.6 KiB
JavaScript
// lib/gold-consistency.mjs — G3 (programdok §8): deterministisk gull-intern-
|
|
// konsistens-vakt. Fanger FP1-klassen (Spor 2b): et claim med verdict=correct
|
|
// hvis egen `notes` innrømmer at den påståtte verdien ikke er bekreftet mot
|
|
// kilden («uverifisert / illustrativ / ikke i kilden»). Verdikten sier «matcher
|
|
// kilden»; noten sier det motsatte — en selvmotsigende annotasjon.
|
|
//
|
|
// Tripwire-design: brede markører for recall, presisjon via en eksplisitt
|
|
// `consistency_waiver`-escape-hatch (menneske-i-loop §4c). Linten klassifiserer
|
|
// ikke — den surfacer kandidater et menneske enten relabel-er eller waiver-er
|
|
// med begrunnelse. Ren funksjon, ingen I/O; testet i tests/kb-eval/.
|
|
|
|
// Markører som — i en note festet til et verdict=correct-claim — innrømmer at
|
|
// den påståtte verdien IKKE er bekreftet mot den siterte kilden. Holdt brede med
|
|
// vilje (recall); falske positive absorberes av waiver-hatchen, ikke av en
|
|
// perfekt regex. Hver er en delstreng matchet case-insensitivt.
|
|
export const CONTRADICTION_MARKERS = [
|
|
'uverifisert',
|
|
'ikke verifiser', // ikke verifisert / ikke verifiserbar
|
|
'kan ikke verifiser',
|
|
'illustrativ', // illustrativt / illustrative
|
|
'ikke i kilden',
|
|
'ikke nevnt i kild',
|
|
'kilden oppgir ikke',
|
|
'ikke bekreftet',
|
|
'ubekreftet',
|
|
'source_silent',
|
|
'plassholder',
|
|
'placeholder',
|
|
'eksempel-tall',
|
|
'eksempeltall',
|
|
];
|
|
|
|
// Verdikter som hevder samsvar med dagens kilde. Kun disse kan motsi en
|
|
// «ikke bekreftet»-note: outdated/wrong/unsourced anerkjenner allerede ikke-match.
|
|
const ASSERTS_SOURCE_MATCH = new Set(['correct']);
|
|
|
|
export function findContradictionMarkers(notes) {
|
|
if (!notes || typeof notes !== 'string') return [];
|
|
const lc = notes.toLowerCase();
|
|
return CONTRADICTION_MARKERS.filter((m) => lc.includes(m));
|
|
}
|
|
|
|
function hasWaiver(claim) {
|
|
return typeof claim.consistency_waiver === 'string' && claim.consistency_waiver.trim().length > 0;
|
|
}
|
|
|
|
// Returnerer { ok, flagged: [{ id, verdict, notes, markers }] }.
|
|
// Et claim flagges når: verdikten hevder kilde-samsvar, noten bærer en
|
|
// motsigelses-markør, og det ikke finnes et ikke-tomt consistency_waiver.
|
|
export function lintGoldConsistency(goldSet) {
|
|
const claims = (goldSet && goldSet.claims) || [];
|
|
const flagged = [];
|
|
for (const c of claims) {
|
|
if (!ASSERTS_SOURCE_MATCH.has(c.verdict)) continue;
|
|
if (hasWaiver(c)) continue;
|
|
const markers = findContradictionMarkers(c.notes);
|
|
if (markers.length) {
|
|
flagged.push({ id: c.id, verdict: c.verdict, notes: c.notes, markers });
|
|
}
|
|
}
|
|
return { ok: flagged.length === 0, flagged };
|
|
}
|