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 = 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 { 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; }