fix(rectification): surface dropped probes and filter tools by the decision
Independent Staging Quality Gate / validate (push) Failing after 17m9s
Independent Staging Quality Gate / publish (push) Has been skipped

Silent unrenderable discriminators, a missing question-contract golden, and a always-on tool table were hiding fail-closed drops behind the prompt wall.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-08-28 20:31:15 +08:00
co-authored by Cursor
parent 69c3e94920
commit 63b4591aae
25 changed files with 856 additions and 274 deletions
@@ -8,6 +8,7 @@ import { d9StyleLabel, d10StyleLabel } from "../v9/varga-type-tables.ts";
import {
completeStyleOptions,
isRenderableProbe,
type DroppedProbe,
rankDiscriminatorScore,
} from "../v9/probe-question-contract.ts";
@@ -396,6 +397,67 @@ export function vargaLayerFromSemanticKey(key: string): string | null {
return key.match(/^varga\.(d\d+)/)?.[1] ?? null;
}
export function inspectDiscriminatorProbes(
packet: CandidateContrastPacket | null | undefined,
options?: {
askedKeys?: readonly string[];
mentionedKeys?: readonly string[];
topCandidateTimes?: readonly string[];
},
): {
selected: CandidateDiscriminatorProbe | null;
dropped: DroppedProbe[];
} {
const asked = new Set(options?.askedKeys ?? []);
const mentioned = new Set(options?.mentionedKeys ?? []);
const dropped: DroppedProbe[] = [];
const ranked = (packet?.probes ?? []).flatMap((probe) => {
const completed = withCompletedContrastOptions(probe);
if (!completed.ok) {
dropped.push({
semantic_key: probe.semanticKey,
information_gain: probe.informationGain,
reason: completed.reason,
});
return [];
}
const ids = [...new Set(completed.probe.expectedOutcomes.flatMap((row) => [
...row.supportsCandidateIds,
...row.conflictsCandidateIds,
]))];
const renderable = isRenderableProbe({
informationGain: completed.probe.informationGain,
candidateIds: ids,
expectedOutcomeCount: completed.probe.expectedOutcomes.length,
choiceKind: completed.probe.choiceKind,
styleOptions: completed.probe.styleOptions,
});
if (!renderable.ok) {
dropped.push({
semantic_key: completed.probe.semanticKey,
information_gain: completed.probe.informationGain,
reason: renderable.reason,
});
return [];
}
const layer = vargaLayerFromSemanticKey(completed.probe.semanticKey);
const askedAlready = asked.has(completed.probe.semanticKey)
|| asked.has(completed.probe.candidateSplitHash)
|| asked.has(completed.probe.probeId)
|| (layer ? vargaLayerCovered(mentioned, layer) : false);
return [{
probe: completed.probe,
score: rankDiscriminatorScore({
informationGain: completed.probe.informationGain,
asked: askedAlready,
candidateIds: ids,
topCandidateTimes: options?.topCandidateTimes,
}),
}];
}).sort((left, right) => right.score - left.score || right.probe.informationGain - left.probe.informationGain);
return { selected: ranked[0]?.probe ?? null, dropped };
}
export function selectDiscriminatorProbe(
packet: CandidateContrastPacket | null | undefined,
options?: {
@@ -404,43 +466,12 @@ export function selectDiscriminatorProbe(
topCandidateTimes?: readonly string[];
},
): CandidateDiscriminatorProbe | null {
const asked = new Set(options?.askedKeys ?? []);
const mentioned = new Set(options?.mentionedKeys ?? []);
const ranked = (packet?.probes ?? []).flatMap((probe) => {
const completed = withCompletedContrastOptions(probe);
if (!completed) return [];
const ids = [...new Set(completed.expectedOutcomes.flatMap((row) => [
...row.supportsCandidateIds,
...row.conflictsCandidateIds,
]))];
if (!isRenderableProbe({
informationGain: completed.informationGain,
candidateIds: ids,
expectedOutcomeCount: completed.expectedOutcomes.length,
choiceKind: completed.choiceKind,
styleOptions: completed.styleOptions,
})) return [];
const layer = vargaLayerFromSemanticKey(completed.semanticKey);
const askedAlready = asked.has(completed.semanticKey)
|| asked.has(completed.candidateSplitHash)
|| asked.has(completed.probeId)
|| (layer ? vargaLayerCovered(mentioned, layer) : false);
return [{
probe: completed,
score: rankDiscriminatorScore({
informationGain: completed.informationGain,
asked: askedAlready,
candidateIds: ids,
topCandidateTimes: options?.topCandidateTimes,
}),
}];
}).sort((left, right) => right.score - left.score || right.probe.informationGain - left.probe.informationGain);
return ranked[0]?.probe ?? null;
return inspectDiscriminatorProbes(packet, options).selected;
}
function withCompletedContrastOptions(
probe: CandidateDiscriminatorProbe,
): CandidateDiscriminatorProbe | null {
): { ok: true; probe: CandidateDiscriminatorProbe } | { ok: false; reason: DroppedProbe["reason"] } {
const mapped = probe.styleOptions?.map((item) => ({
label: item.label,
answer_class: item.answerClass,
@@ -459,17 +490,20 @@ function withCompletedContrastOptions(
choiceKind,
styleOptions: incoming,
});
if (!styleOptions) return null;
if (!styleOptions.ok) return { ok: false, reason: styleOptions.reason };
const outcomes = withUnsureOutcome(probe.expectedOutcomes);
return {
...probe,
choiceKind,
expectedOutcomes: outcomes,
styleOptions: styleOptions.map((item) => ({
label: item.label,
answerClass: item.answer_class,
...(item.sign ? { sign: item.sign } : {}),
})),
ok: true,
probe: {
...probe,
choiceKind,
expectedOutcomes: outcomes,
styleOptions: styleOptions.options.map((item) => ({
label: item.label,
answerClass: item.answer_class,
...(item.sign ? { sign: item.sign } : {}),
})),
},
};
}
@@ -728,8 +762,8 @@ function remainingStyleOptions(
})
: [];
const completed = completeStyleOptions({ choiceKind: kind, styleOptions: incoming });
if (!completed) return undefined;
return uniquifyStyleLabels(completed.map((item) => ({
if (!completed.ok) return undefined;
return uniquifyStyleLabels(completed.options.map((item) => ({
label: item.label,
answerClass: item.answer_class,
...(item.sign ? { sign: item.sign } : {}),
@@ -13,6 +13,7 @@ import {
type CandidateSeparation,
} from "./candidate-separation.ts";
import { rangeFromTimes } from "./credible-range.ts";
import type { DroppedProbe } from "../v9/probe-question-contract.ts";
import type { RectificationPhase, ResultStatus } from "./types.ts";
export type RectificationNextActionType =
@@ -63,6 +64,7 @@ export type RectificationDecision = Readonly<{
separation: CandidateSeparation;
probe: CandidateDiscriminatorProbe | null;
holdoutValidation: HoldoutValidationStatus;
droppedProbes: readonly DroppedProbe[];
}>;
export type DecideRectificationInput = Readonly<{
@@ -192,6 +194,7 @@ function collect(
separation,
probe,
holdoutValidation: holdout,
droppedProbes: [],
};
}
@@ -220,6 +223,7 @@ function discriminate(
separation,
probe,
holdoutValidation: holdout,
droppedProbes: [],
};
}
@@ -246,6 +250,7 @@ function holdoutValidation(
separation,
probe: null,
holdoutValidation: "not_started",
droppedProbes: [],
};
}
@@ -282,6 +287,7 @@ function completeWithRange(
separation,
probe: null,
holdoutValidation: holdout,
droppedProbes: [],
};
}
@@ -329,6 +335,7 @@ function finish(
separation: input.separation,
probe: input.probe,
holdoutValidation: input.holdout,
droppedProbes: [],
};
}