Files
Jyotisha/frontend/src/lib/rectification-agentic/core/probes-from-engine.ts
T
Jesse_ChenandCursor 86d6923e6e
Independent Staging Quality Gate / validate (push) Successful in 10m10s
Independent Staging Quality Gate / publish (push) Successful in 7m25s
fix(rectification): stop discriminator followup from dropping user evidence
Decision and question ranking now share contrast option completion, so a
missing style card cannot deadlock the interview with a dead-end reply.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-29 10:23:34 +08:00

72 lines
2.5 KiB
TypeScript

import type { DiscriminatingEventProbe } from "../v9/refinement-packet.ts";
import { candidateIdsFromProbe, distinguishContractErrors } from "./distinguish-contract.ts";
import type { AnswerClass, ConflictProbe, ProbeOutcome } from "./types.ts";
const ANSWER_CLASSES: ReadonlySet<string> = new Set(["yes", "weak_yes", "no", "unsure"]);
export type EngineProbeFields = DiscriminatingEventProbe;
export function probeFromEngine(probe: EngineProbeFields): ConflictProbe | null {
if (distinguishContractErrors({ ...probe, role: probe.role ?? "distinguish" }).length > 0) {
return null;
}
const semanticKey = probe.semantic_key ?? `${probe.domain}.${probe.year}`;
const splitHash = probe.candidate_split_hash
?? `${probe.candidate_set_version ?? ""}:${probe.domain}:${probe.year}`;
const outcomes = outcomesFromEngine(probe.expected_outcomes);
const candidateIds = probe.candidate_ids?.length
? [...probe.candidate_ids]
: candidateIdsFromProbe(probe);
if (outcomes.length < 2 || candidateIds.length < 2 || (probe.information_gain ?? 0) <= 0) {
return null;
}
const styleOptions = styleOptionsFromEngine(probe.style_options);
return {
id: `probe:${semanticKey}:${splitHash}`,
semantic_key: semanticKey,
candidate_split_hash: splitHash,
domain: probe.domain,
year: probe.year,
question: probe.user_meaning,
candidate_ids: candidateIds,
expected_outcomes: outcomes,
information_gain: probe.information_gain ?? 0,
source: probe.source,
...(probe.choice_kind === "varga_style"
|| probe.choice_kind === "event_quality"
|| probe.choice_kind === "existence"
? { choice_kind: probe.choice_kind }
: {}),
...(styleOptions.length > 0 ? { style_options: styleOptions } : {}),
};
}
function styleOptionsFromEngine(
rows: DiscriminatingEventProbe["style_options"],
): NonNullable<ConflictProbe["style_options"]> {
return (rows ?? []).flatMap((row) => {
if (!ANSWER_CLASSES.has(row.answer_class)) return [];
return [{
label: row.label,
answer_class: row.answer_class as AnswerClass,
...(row.sign ? { sign: row.sign } : {}),
}];
});
}
function outcomesFromEngine(
rows: DiscriminatingEventProbe["expected_outcomes"],
): ProbeOutcome[] {
if (!rows) return [];
const parsed: ProbeOutcome[] = [];
for (const row of rows) {
if (!ANSWER_CLASSES.has(row.answer_class)) continue;
parsed.push({
answer_class: row.answer_class as AnswerClass,
supports: row.supports,
conflicts: row.conflicts,
});
}
return parsed;
}