fix(rectification): drop same-year probes after a dated answer (BUG-592)

Point-choice used one compare packet, so a May existence card and the same-domain year card both stayed eligible. Hard-exclude same domain+year; keep adjacent years downranked.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-09-08 15:47:25 +08:00
co-authored by Cursor
parent f17af254c5
commit 8ae17a2630
10 changed files with 562 additions and 12 deletions
@@ -17,6 +17,8 @@ import {
isRenderableProbe,
type DroppedProbe,
rankDiscriminatorScore,
sameYearProbeAsked,
SEMANTIC_YEAR_KEY,
} from "../v9/probe-question-contract.ts";
export type ContrastChoiceKind = "existence" | "varga_style" | "event_quality";
@@ -405,6 +407,18 @@ export function vargaLayerFromSemanticKey(key: string): string | null {
return key.match(/^varga\.(d\d+)/)?.[1] ?? null;
}
function probeDomainYear(probe: Pick<CandidateDiscriminatorProbe, "domain" | "year" | "semanticKey">): {
domain: string;
year: number;
} | null {
if (probe.domain && probe.year && probe.year > 0) {
return { domain: probe.domain, year: probe.year };
}
const match = probe.semanticKey.match(SEMANTIC_YEAR_KEY);
if (!match) return null;
return { domain: match[1], year: Number(match[2]) };
}
export function inspectDiscriminatorProbes(
packet: CandidateContrastPacket | null | undefined,
options?: {
@@ -461,6 +475,15 @@ export function inspectDiscriminatorProbes(
});
return [];
}
const domainYear = probeDomainYear(completed.probe);
if (domainYear && sameYearProbeAsked(asked, domainYear.domain, domainYear.year)) {
dropped.push({
semantic_key: completed.probe.semanticKey,
information_gain: completed.probe.informationGain,
reason: "same_year_asked",
});
return [];
}
const layer = vargaLayerFromSemanticKey(completed.probe.semanticKey);
const askedAlready = asked.has(completed.probe.semanticKey)
|| asked.has(completed.probe.candidateSplitHash)
@@ -110,6 +110,8 @@ import {
informationGainAmongActive,
isRenderableProbe,
rankDiscriminatorScore,
sameYearProbeAsked,
SEMANTIC_YEAR_KEY,
EXISTENCE_STYLE_OPTIONS,
type DroppedProbe,
type ProbeStyleOption,
@@ -142,6 +144,7 @@ import {
} from "./window-widen.ts";
import { DATE_RELIABILITY_PROMPT, pendingDateReliabilityEvidence } from "./date-reliability.ts";
export { sameYearProbeAsked };
export const METHOD_FOLLOWUP_IDS = [
"dasha_events",
@@ -335,18 +338,18 @@ function existenceNearbyYears(domain: string): number {
return EXISTENCE_NEARBY_YEARS[domain] ?? 0;
}
const SEMANTIC_YEAR = /^([a-z_]+)\.((?:19|20)\d{2})(?:\.|$)/;
export function existenceProbeAsked(
askedKeys: ReadonlySet<string> | readonly string[],
domain: string,
year: number,
): boolean {
if (!domain || !year) return false;
if (sameYearProbeAsked(askedKeys, domain, year)) return true;
const asked = askedKeys instanceof Set ? askedKeys : new Set(askedKeys);
const nearby = existenceNearbyYears(domain);
if (nearby <= 0) return false;
for (const key of asked) {
const match = key.match(SEMANTIC_YEAR);
const match = key.match(SEMANTIC_YEAR_KEY);
if (!match || match[1] !== domain) continue;
const askedYear = Number(match[2]);
if (Number.isInteger(askedYear) && Math.abs(askedYear - year) <= nearby) return true;
@@ -806,7 +809,7 @@ function remainingConflictProbes(
if (
askedKeys.has(semantic)
|| (split && askedKeys.has(split))
|| existenceProbeAsked(askedKeys, probe.domain, probe.year)
|| sameYearProbeAsked(askedKeys, probe.domain, probe.year)
) continue;
rows.push(probe);
}
@@ -889,6 +892,9 @@ function renderableEventProbe(
if (!rankedGain) {
return { row: null, dropped: droppedFromProbe(key, probe.information_gain ?? 0, "no_split_among_active") };
}
if (sameYearProbeAsked(askedKeys, probe.domain, probe.year)) {
return { row: null, dropped: droppedFromProbe(key, probe.information_gain ?? 0, "same_year_asked") };
}
const layer = vargaLayerFromSemanticKey(key);
const asked = askedKeys.has(key)
|| Boolean(probe.candidate_split_hash && askedKeys.has(probe.candidate_split_hash))
@@ -960,10 +966,17 @@ function renderableContrastProbe(
dropped: droppedFromProbe(working.semanticKey, working.informationGain, "no_split_among_active"),
};
}
if (sameYearProbeAsked(askedKeys, working.domain, working.year)) {
return {
row: null,
dropped: droppedFromProbe(working.semanticKey, working.informationGain, "same_year_asked"),
};
}
const layer = vargaLayerFromSemanticKey(working.semanticKey);
const asked = askedKeys.has(working.semanticKey)
|| askedKeys.has(working.candidateSplitHash)
|| askedKeys.has(working.probeId)
|| existenceProbeAsked(askedKeys, working.domain ?? "", working.year ?? 0)
|| (layer ? vargaLayerCovered(mentionedKeys, layer) : false);
return {
row: {
@@ -36,7 +36,8 @@ export type ProbeRejectReason =
| "yearless_ungrounded_contrast"
| "no_split_among_active"
| "unanchored_varga_style"
| "frameless_distinguish";
| "frameless_distinguish"
| "same_year_asked";
export type StyleOptionsResult =
| { ok: true; options: ProbeStyleOption[] }
@@ -312,6 +313,23 @@ export function discriminatorPriority(input: {
return input.informationGain * novelty * coverage - penalty;
}
export const SEMANTIC_YEAR_KEY = /^([a-z_]+)\.((?:19|20)\d{2})(?:\.|$)/;
export function sameYearProbeAsked(
askedKeys: ReadonlySet<string> | readonly string[],
domain: string | null | undefined,
year: number | null | undefined,
): boolean {
if (!domain || !year) return false;
const asked = askedKeys instanceof Set ? askedKeys : new Set(askedKeys);
for (const key of asked) {
const match = key.match(SEMANTIC_YEAR_KEY);
if (!match || match[1] !== domain) continue;
if (Number(match[2]) === year) return true;
}
return false;
}
export function rankDiscriminatorScore(input: {
informationGain: number;
asked?: boolean;