From f2bf7862ea49e65f6e2ce0fd4ea685e00cb69bc4 Mon Sep 17 00:00:00 2001 From: itsrubberduck Date: Fri, 10 Jul 2026 15:34:50 +0200 Subject: [PATCH] refactor(live-atc): drop unreachable decision-trace normalization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit normalizeDecisionTraceResult had no callers — it was the only root of ensureTraceCalls, normalizeTraceFallback/AutoSelection, the whole normalizeTimeline* chain, VALID_TRACE_STAGES and isPlainObject, so that entire block was unreachable. Same for activeFlowInfo. Leftovers from the LLM decision routing that moved to the Python backend (see CLAUDE.md): the trace the debug panel renders now comes straight from the engine's lastDecisionTrace, already shaped. cloneForTrace stays — runFullSimulation still uses it. Co-Authored-By: Claude Opus 4.8 --- app/pages/live-atc.vue | 245 ----------------------------------------- 1 file changed, 245 deletions(-) diff --git a/app/pages/live-atc.vue b/app/pages/live-atc.vue index 3313b0c..872c8b6 100644 --- a/app/pages/live-atc.vue +++ b/app/pages/live-atc.vue @@ -1532,14 +1532,6 @@ import { useBugReport } from '~/composables/useBugReport' import { useSimBridgeSync } from '~/composables/useSimBridgeSync' import { useSpeechInterrupt } from '~/composables/useSpeechInterrupt' import { useRadioSpeech } from '~/composables/useRadioSpeech' -import type { - CandidateTraceElimination, - CandidateTraceEntry, - CandidateTraceStage, - CandidateTraceStep, - DecisionCandidateTimeline, - LLMDecisionTrace, -} from '../../shared/types/llm' // Core State const engine = useCommunicationsEngine() @@ -1747,18 +1739,6 @@ const clearLog = () => { clearLastTransmission() } -const activeFlowInfo = computed(() => { - const slug = activeFlow.value - const flows = availableFlows.value - const entry = (slug ? flows.find((flow) => flow.slug === slug) : undefined) || flows.find((flow) => flow.mode === 'main') || flows[0] - const resolvedSlug = entry?.slug || slug || '' - const name = entry?.name || resolvedSlug || 'Main Flow' - const description = entry?.description || '' - const mode = entry?.mode || (resolvedSlug && resolvedSlug === slug ? 'parallel' : 'parallel') - const modeLabel = mode === 'main' ? 'Main' : mode === 'linear' ? 'Linear' : 'Parallel' - return { slug: resolvedSlug, name, description, mode, modeLabel } -}) - const decisionTrace = computed(() => lastDecisionTrace.value) const timelineSteps = computed(() => decisionTrace.value?.candidateTimeline?.steps ?? []) const timelineUsedFallback = computed(() => Boolean(decisionTrace.value?.candidateTimeline?.fallbackUsed)) @@ -1766,17 +1746,6 @@ const traceAutoSelection = computed(() => decisionTrace.value?.autoSelection ?? const traceFallback = computed(() => decisionTrace.value?.fallback ?? null) const sessionLabel = computed(() => engineSessionId.value || flags.value.session_id || '-') -const VALID_TRACE_STAGES: ReadonlySet = new Set( - [ - 'regex_candidates', - 'regex_filtered', - 'condition_filtered', - 'fallback_candidates', - 'fallback_filtered', - 'final' - ] as CandidateTraceStage[] -) - const cloneForTrace = (value: T): T => { if (value === undefined || value === null) { return value @@ -1789,220 +1758,6 @@ const cloneForTrace = (value: T): T => { } } -const isPlainObject = (value: unknown): value is Record => { - return typeof value === 'object' && value !== null -} - -const ensureTraceCalls = (calls: unknown): LLMDecisionTrace['calls'] => { - if (!Array.isArray(calls)) { - return [] - } - return calls - .filter((entry): entry is Record => isPlainObject(entry)) - .map((entry) => { - const normalized: LLMDecisionTrace['calls'][number] = { - stage: entry.stage === 'readback-check' ? 'readback-check' : 'decision', - request: isPlainObject(entry.request) ? cloneForTrace(entry.request) : {}, - } - if ('response' in entry) { - normalized.response = cloneForTrace(entry.response) - } - if (typeof entry.rawResponseText === 'string') { - normalized.rawResponseText = entry.rawResponseText - } - if (typeof entry.error === 'string') { - normalized.error = entry.error - } - return normalized - }) -} - -const normalizeTraceFallback = (raw: unknown): LLMDecisionTrace['fallback'] | undefined => { - if (!isPlainObject(raw)) { - return undefined - } - const fallback: LLMDecisionTrace['fallback'] = { - used: Boolean(raw.used), - } - if (typeof raw.reason === 'string' && raw.reason.trim().length) { - fallback.reason = raw.reason - } - if (typeof raw.selected === 'string' && raw.selected.trim().length) { - fallback.selected = raw.selected - } - return fallback -} - -const normalizeTraceAutoSelection = ( - raw: unknown -): NonNullable | undefined => { - if (!isPlainObject(raw)) { - return undefined - } - const id = typeof raw.id === 'string' && raw.id.trim().length ? raw.id : undefined - if (!id) { - return undefined - } - const flow = typeof raw.flow === 'string' && raw.flow.trim().length ? raw.flow : 'current' - const autoSelection: NonNullable = { id, flow } - if (typeof raw.reason === 'string' && raw.reason.trim().length) { - autoSelection.reason = raw.reason - } - return autoSelection -} - -const normalizeTimelineCandidate = (raw: unknown): CandidateTraceEntry | null => { - if (!isPlainObject(raw)) { - return null - } - const id = typeof raw.id === 'string' && raw.id.trim().length ? raw.id : undefined - if (!id) { - return null - } - const flow = typeof raw.flow === 'string' && raw.flow.trim().length - ? raw.flow - : typeof raw.flow?.slug === 'string' - ? raw.flow.slug - : 'current' - const candidate: CandidateTraceEntry = { - id, - flow, - } - if (typeof raw.name === 'string') { - candidate.name = raw.name - } - if (typeof raw.summary === 'string') { - candidate.summary = raw.summary - } - if (typeof raw.role === 'string') { - candidate.role = raw.role - } - if (Array.isArray(raw.triggers)) { - candidate.triggers = cloneForTrace(raw.triggers) - } - if (Array.isArray(raw.conditions)) { - candidate.conditions = cloneForTrace(raw.conditions) - } - return candidate -} - -const normalizeTimelineElimination = (raw: unknown): CandidateTraceElimination | null => { - if (!isPlainObject(raw)) { - return null - } - const candidate = normalizeTimelineCandidate(raw.candidate) - if (!candidate) { - return null - } - const kind: CandidateTraceElimination['kind'] = raw.kind === 'regex' ? 'regex' : 'condition' - const reason = typeof raw.reason === 'string' && raw.reason.trim().length ? raw.reason : '' - const elimination: CandidateTraceElimination = { - candidate, - kind, - reason, - } - if (isPlainObject(raw.context)) { - elimination.context = cloneForTrace(raw.context) - } - return elimination -} - -const normalizeTimelineStep = (raw: unknown): CandidateTraceStep | null => { - if (!isPlainObject(raw)) { - return null - } - const stageCandidate = typeof raw.stage === 'string' && VALID_TRACE_STAGES.has(raw.stage as CandidateTraceStage) - ? (raw.stage as CandidateTraceStage) - : 'final' - const label = typeof raw.label === 'string' && raw.label.trim().length ? raw.label : stageCandidate - const candidates = Array.isArray(raw.candidates) - ? raw.candidates - .map((candidate) => normalizeTimelineCandidate(candidate)) - .filter((candidate): candidate is CandidateTraceEntry => Boolean(candidate)) - : [] - const eliminated = Array.isArray(raw.eliminated) - ? raw.eliminated - .map((entry) => normalizeTimelineElimination(entry)) - .filter((entry): entry is CandidateTraceElimination => Boolean(entry)) - : [] - const note = typeof raw.note === 'string' && raw.note.trim().length ? raw.note : undefined - const step: CandidateTraceStep = { - stage: stageCandidate, - label, - candidates, - } - if (eliminated.length) { - step.eliminated = eliminated - } - if (note) { - step.note = note - } - return step -} - -const normalizeCandidateTimeline = (raw: unknown): DecisionCandidateTimeline | undefined => { - if (!isPlainObject(raw)) { - return undefined - } - const steps = Array.isArray(raw.steps) - ? raw.steps - .map((step) => normalizeTimelineStep(step)) - .filter((step): step is CandidateTraceStep => Boolean(step)) - : [] - const timeline: DecisionCandidateTimeline = { steps } - if ('fallbackUsed' in raw) { - timeline.fallbackUsed = Boolean((raw as any).fallbackUsed) - } else if ('fallback_used' in raw) { - timeline.fallbackUsed = Boolean((raw as any).fallback_used) - } - const autoSelected = normalizeTimelineCandidate((raw as any).autoSelected ?? (raw as any).auto_selected) - if (autoSelected !== null && autoSelected !== undefined) { - timeline.autoSelected = autoSelected - } - return timeline -} - -const normalizeDecisionTraceResult = (result: any): LLMDecisionTrace | null => { - const traceSource = isPlainObject(result?.trace) ? result.trace : undefined - const fallbackFromTrace = normalizeTraceFallback(traceSource?.fallback) - const timelineFromTrace = normalizeCandidateTimeline(traceSource?.candidateTimeline ?? traceSource?.timeline) - const autoSelectionFromTrace = normalizeTraceAutoSelection(traceSource?.autoSelection ?? traceSource?.auto_selection) - - const baseTrace: LLMDecisionTrace | null = traceSource - ? { - calls: ensureTraceCalls(traceSource.calls), - ...(fallbackFromTrace ? { fallback: fallbackFromTrace } : {}), - ...(timelineFromTrace ? { candidateTimeline: timelineFromTrace } : {}), - ...(autoSelectionFromTrace ? { autoSelection: autoSelectionFromTrace } : {}), - } - : null - - const candidateTimeline = timelineFromTrace - ?? normalizeCandidateTimeline(result?.candidateTimeline ?? result?.candidate_timeline ?? result?.timeline) - const autoSelection = autoSelectionFromTrace - ?? normalizeTraceAutoSelection(result?.autoSelection ?? result?.auto_selection) - const fallback = fallbackFromTrace - ?? normalizeTraceFallback(result?.fallback ?? result?.fallbackInfo ?? result?.fallback_info) - - if (!baseTrace && !candidateTimeline && !autoSelection && !fallback) { - return null - } - - const trace: LLMDecisionTrace = baseTrace ?? { calls: [] } - - if (candidateTimeline && !trace.candidateTimeline) { - trace.candidateTimeline = candidateTimeline - } - if (autoSelection && !trace.autoSelection) { - trace.autoSelection = autoSelection - } - if (fallback && !trace.fallback) { - trace.fallback = fallback - } - - return trace -} - function describeElimination(entry: any): string { if (!entry || typeof entry !== 'object') { return ''