fix(rectification): surface dropped probes and filter tools by the decision
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:
@@ -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: [],
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user