import type { DiscriminatingEventProbe } from "../v9/refinement-packet.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 { const semanticKey = probe.semantic_key ?? `${probe.domain}.${probe.year}`; const splitHash = probe.candidate_split_hash ?? `${probe.domain}:${probe.year}:${[probe.left_time ?? "", probe.right_time ?? ""].sort().join("|")}`; return { id: `probe:${semanticKey}:${splitHash}`, semantic_key: semanticKey, candidate_split_hash: splitHash, domain: probe.domain, year: probe.year, question: probe.user_meaning, candidate_ids: [probe.left_time, probe.right_time].filter((item): item is string => Boolean(item)), expected_outcomes: outcomesFromEngine( probe.expected_outcomes, probe.left_time, probe.right_time, ), information_gain: probe.information_gain ?? 0, source: probe.source, }; } function outcomesFromEngine( rows: DiscriminatingEventProbe["expected_outcomes"], left?: string, right?: string, ): readonly ProbeOutcome[] { if (!rows) return defaultOutcomes(left, right); 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.length > 0 ? parsed : defaultOutcomes(left, right); } function defaultOutcomes(left?: string, right?: string): ProbeOutcome[] { if (!left || !right || left === right) return []; return [ { answer_class: "yes", supports: [left], conflicts: [right] }, { answer_class: "no", supports: [right], conflicts: [left] }, { answer_class: "weak_yes", supports: [left], conflicts: [right] }, { answer_class: "unsure", supports: [], conflicts: [] }, ]; }