fix(rectification): stop yearless ungrounded varga contrast from minting cards
Independent Staging Quality Gate / validate (push) Successful in 9m10s
Independent Staging Quality Gate / publish (push) Successful in 8m43s

Only sign-bound varga_style questions may omit a concrete period. Remaining-layer existence and quality probes now drop as yearless_ungrounded_contrast instead of scoring by group order.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-08-30 10:55:11 +08:00
co-authored by Cursor
parent 95f5851261
commit b43808b016
18 changed files with 741 additions and 138 deletions
@@ -437,6 +437,7 @@ export function inspectDiscriminatorProbes(
expectedOutcomeCount: completed.probe.expectedOutcomes.length,
choiceKind: completed.probe.choiceKind,
styleOptions: completed.probe.styleOptions,
year: completed.probe.year,
});
if (!renderable.ok) {
dropped.push({
@@ -9,7 +9,7 @@
*/
import type { AnswerClass } from "../core/types";
import { completeStyleOptions, clippedProbeLabel } from "./probe-question-contract";
import { completeStyleOptions, clippedProbeLabel, canRenderYearlessChoice } from "./probe-question-contract";
import type { DiscriminatingEventProbe, EventProbeChoiceKind, EventProbeStyleOption } from "./refinement-packet";
import type { InternalVargaObservation } from "./varga-observations";
@@ -337,8 +337,11 @@ function hypothesisFor(
if (!styleOptions.ok) return null;
const period = periodFor(evidence, domain, probes, birthDate, followup);
const kind = followup.choice_kind ?? probe.choice_kind ?? "existence";
const yearlessVarga = (followup.semantic_key ?? probe.semantic_key ?? "").startsWith("varga.");
if (kind !== "varga_style" && !isConcreteChoicePeriod(period) && !yearlessVarga) return null;
if (kind === "varga_style") {
if (!canRenderYearlessChoice({ choiceKind: kind, styleOptions: styleOptions.options })) return null;
} else if (!isConcreteChoicePeriod(period)) {
return null;
}
const prompt = eventQuestionPrompt(period, probe.event_family, kind, domain);
const why = probe.user_meaning?.trim() || followup.user_prompt_hint.trim();
if (!why) return null;
@@ -47,13 +47,14 @@
* do not stamp a ledger year onto a yearless scoring card. An open varga
* discriminator must resolve from the contrast packet when Python event
* probes have no row in that domain. Scoring reverse-inference cards need
* the engine year or month. Yearless varga cards stay out of the dated
* ranking until the training gate is open. Uncovered relationship, career,
* and family still ask a same-domain card or spoken collect first.
* Occupation collect must not block those yearless cards once training
* events already pass. If the next ask would be a spoken
* collect in the same domain, prefer a renderable yearless scoring card
* instead of an unscoreable collect question.
* the engine year or month. Yearless contrast is renderable only when
* choice_kind is varga_style and scoring options carry signs. Other
* remaining-layer probes stay in the packet but are dropped as
* yearless_ungrounded_contrast. Uncovered relationship, career, and
* family still ask a same-domain signed style card or dated spoken
* collect first. Occupation collect must not block signed D9/D10 cards
* once training events already pass. Do not re-widen yearless existence
* or quality cards to keep the interview moving.
*/
import {
@@ -600,8 +601,10 @@ function renderableEventProbe(
expectedOutcomeCount: probe.expected_outcomes?.length,
choiceKind: probe.choice_kind,
styleOptions: styleOptions.options,
year: probe.year,
yearLabel: probe.year_label,
});
if (!renderable.ok) {
if (!renderable.ok && renderable.reason !== "yearless_ungrounded_contrast") {
return { row: null, dropped: droppedFromProbe(key, probe.information_gain ?? 0, renderable.reason) };
}
const layer = vargaLayerFromSemanticKey(key);
@@ -620,7 +623,9 @@ function renderableEventProbe(
topCandidateTimes,
}),
},
dropped: null,
dropped: renderable.ok
? null
: droppedFromProbe(key, probe.information_gain ?? 0, renderable.reason),
};
}
@@ -653,8 +658,9 @@ function renderableContrastProbe(
expectedOutcomeCount: working.expectedOutcomes.length,
choiceKind: working.choiceKind,
styleOptions,
year: working.year,
});
if (!renderable.ok) {
if (!renderable.ok && renderable.reason !== "yearless_ungrounded_contrast") {
return {
row: null,
dropped: droppedFromProbe(working.semanticKey, working.informationGain, renderable.reason),
@@ -677,7 +683,9 @@ function renderableContrastProbe(
topCandidateTimes,
}),
},
dropped: null,
dropped: renderable.ok
? null
: droppedFromProbe(working.semanticKey, working.informationGain, renderable.reason),
};
}
@@ -853,10 +861,12 @@ function agentHint(
}
export function shouldAttachChoiceFrame(
item: Pick<MethodFollowup, "intent" | "ask_theme" | "source">,
item: Pick<MethodFollowup, "intent" | "ask_theme" | "source" | "probe_year" | "year_label">,
evidence: readonly MethodFollowupEvidence[] = [],
): boolean {
if (item.intent === "out_of_sample_check" || item.source === "oos_blind") return true;
if (item.intent === "out_of_sample_check" || item.source === "oos_blind") {
return (item.probe_year ?? 0) > 0;
}
if (item.intent === "reverse_verify" || item.source === "reverse_verify") return true;
if (item.intent === "clarify_event") return true;
if (item.source === "event_probe") return true;
@@ -1377,7 +1387,7 @@ export function buildMethodFollowupPlan(input: {
);
return {
methods,
next_followup: fields ? makeFollowup(fields, false, true) : null,
next_followup: fields ? makeFollowup(fields, false) : null,
deferred_followup: null,
session_outcome: sessionOutcome ?? "collect_evidence",
stop_domain_rotation: true,
@@ -1816,7 +1826,7 @@ export function buildMethodFollowupPlan(input: {
input.oosBlindPrompts?.[0],
(input.holdoutEvents ?? []).find((item) => item.year !== null) ?? null,
);
if (fields) next = makeFollowup(fields, false, true);
if (fields) next = makeFollowup(fields, false);
} else if (horaryStatus === "uncovered") {
next = sameDomainYearlessCard("horary") ?? makeFollowup({
method_id: "horary",
@@ -32,7 +32,8 @@ export type ProbeRejectReason =
| StyleOptionsRejectReason
| "zero_gain"
| "insufficient_candidates"
| "insufficient_outcomes";
| "insufficient_outcomes"
| "yearless_ungrounded_contrast";
export type StyleOptionsResult =
| { ok: true; options: ProbeStyleOption[] }
@@ -78,8 +79,11 @@ export const VARGA_UNSURE_STYLE_OPTION: ProbeStyleOption = {
};
export const FORBIDDEN_COPY_TOKENS = ["外貌", "体质", "胎记", "疤痕", "伤疤", "身高", "体型"] as const;
export const YEARLESS_PERIOD_COPY_MARKERS = ["时间吻合", "这段"] as const;
export const LABEL_MIN = 4;
export const LABEL_MAX = 80;
const PLACEHOLDER_PERIOD_LABEL = /^(当前这几个候选|那段时间)$/;
const CONCRETE_YEAR_IN_LABEL = /(?:19|20)\d{2}/;
const FORBIDDEN_COPY = /外貌|体质|胎记|疤痕|伤疤|身高|体型|(?:[01]?\d|2[0-3]):[0-5]\d/;
@@ -220,12 +224,51 @@ export function isRenderableStyleOptions(options: readonly ProbeStyleOption[] |
&& options.every((item) => !/·(?:yes|weak_yes|no|unsure)$/.test(item.label));
}
export function probeHasConcretePeriod(input: {
year?: number | null;
yearLabel?: string | null;
}): boolean {
if ((input.year ?? 0) <= 0) return false;
const label = (input.yearLabel ?? "").trim();
if (!label) return true;
if (PLACEHOLDER_PERIOD_LABEL.test(label)) return false;
return CONCRETE_YEAR_IN_LABEL.test(label);
}
export function scoringOptionsHaveSigns(options: readonly ProbeStyleOption[]): boolean {
const yes = options.find((item) => item.answer_class === "yes");
const weakYes = options.find((item) => item.answer_class === "weak_yes");
if (!yes?.sign?.trim() || !weakYes?.sign?.trim()) return false;
const none = options.find((item) => item.answer_class === "no");
if (!none) return false;
if (none.sign?.trim()) return true;
return none.label === VARGA_NONE_STYLE_OPTION.label;
}
export function optionCopyPresupposesPeriod(options: readonly ProbeStyleOption[]): boolean {
return options.some((item) => (
YEARLESS_PERIOD_COPY_MARKERS.some((marker) => item.label.includes(marker))
));
}
export function canRenderYearlessChoice(input: {
choiceKind?: string | null;
styleOptions: readonly ProbeStyleOption[];
}): boolean {
if (probeQuestionKind(input.choiceKind) !== "varga_style") return false;
if (!scoringOptionsHaveSigns(input.styleOptions)) return false;
return !optionCopyPresupposesPeriod(input.styleOptions);
}
export function isRenderableProbe(input: {
informationGain?: number | null;
candidateIds?: readonly string[] | null;
expectedOutcomeCount?: number | null;
choiceKind?: string | null;
styleOptions?: readonly unknown[] | null;
year?: number | null;
yearLabel?: string | null;
hasConcretePeriod?: boolean;
}): ProbeRenderResult {
const gain = typeof input.informationGain === "number" && Number.isFinite(input.informationGain)
? input.informationGain
@@ -238,6 +281,19 @@ export function isRenderableProbe(input: {
styleOptions: input.styleOptions,
});
if (!styles.ok) return { ok: false, reason: styles.reason };
const kind = probeQuestionKind(input.choiceKind);
const concrete = kind === "varga_style"
? false
: input.hasConcretePeriod ?? probeHasConcretePeriod({
year: input.year,
yearLabel: input.yearLabel,
});
if (!concrete && !canRenderYearlessChoice({
choiceKind: input.choiceKind,
styleOptions: styles.options,
})) {
return { ok: false, reason: "yearless_ungrounded_contrast" };
}
return { ok: true };
}