fix: propagate formula metrics into FOL diagnostic mapping

- mapFolDiagnostic now accepts optional metrics parameter
- adaptFOLResultToImhotepResult matches solver diagnostics to
  formula results by clauseId/formulaId and passes formula-level
  metrics (gap, dimensions, stacking context, overflow, etc.)
  into the diagnostics output
- Previously mapFolDiagnostic always returned metrics: {} and
  sourceRef: {}, making compound/quantified failures undiagnosable
  for users investigating contracts
This commit is contained in:
John Dvorak
2026-05-21 17:17:06 -07:00
parent 16dcf42762
commit 7c61cb51ee
+12 -3
View File
@@ -1518,7 +1518,10 @@ const PREDICATE_TO_DIAGNOSTIC_CODE: Record<string, DiagnosticCode> = {
between: 'IMH_SIZE_BETWEEN_FAILED', between: 'IMH_SIZE_BETWEEN_FAILED',
} }
export function mapFolDiagnostic(d: { code: string; severity: 'error' | 'warning' | 'info'; category?: string; message: string; clauseId?: string }): ImhotepDiagnostic { export function mapFolDiagnostic(
d: { code: string; severity: 'error' | 'warning' | 'info'; category?: string; message: string; clauseId?: string },
metrics?: Record<string, number>,
): ImhotepDiagnostic {
let code = d.code as DiagnosticCode let code = d.code as DiagnosticCode
let message = d.message let message = d.message
const fixHints: string[] = [] const fixHints: string[] = []
@@ -1606,7 +1609,7 @@ export function mapFolDiagnostic(d: { code: string; severity: 'error' | 'warning
source: 'imhotep-solver', source: 'imhotep-solver',
related: [], related: [],
fixHints, fixHints,
metrics: {}, metrics: metrics ?? {},
sourceRef: {}, sourceRef: {},
} }
} }
@@ -1931,8 +1934,14 @@ export function adaptFOLResultToImhotepResult(
clauseId?: string, clauseId?: string,
traceMeta?: TraceMetadata, traceMeta?: TraceMetadata,
): ImhotepResult { ): ImhotepResult {
const formulaMetricsById = new Map<string, Record<string, number> | undefined>()
for (const fr of folResult.formulaResults) {
formulaMetricsById.set(fr.formulaId, fr.metrics)
}
const diagnostics: ImhotepDiagnostic[] = folResult.diagnostics.map((d) => { const diagnostics: ImhotepDiagnostic[] = folResult.diagnostics.map((d) => {
const mapped = mapFolDiagnostic(d) const metrics = d.clauseId ? formulaMetricsById.get(d.clauseId) : undefined
const mapped = mapFolDiagnostic(d, metrics)
if (traceMeta?.sourceRef) mapped.sourceRef = traceMeta.sourceRef if (traceMeta?.sourceRef) mapped.sourceRef = traceMeta.sourceRef
if (traceMeta?.clauseLabel) mapped.clauseLabel = traceMeta.clauseLabel if (traceMeta?.clauseLabel) mapped.clauseLabel = traceMeta.clauseLabel
return mapped return mapped