Skip to content

feat: JSON verification reports#50

Open
augustepoiroux wants to merge 7 commits into
leanprover:masterfrom
augustepoiroux:upstream/json-verification-report
Open

feat: JSON verification reports#50
augustepoiroux wants to merge 7 commits into
leanprover:masterfrom
augustepoiroux:upstream/json-verification-report

Conversation

@augustepoiroux

@augustepoiroux augustepoiroux commented Jun 4, 2026

Copy link
Copy Markdown

Implement optional verification output in JSON format.

Key Changes

  • JSON Serialization: Added optional "json_output_path" configuration to output structured verification reports.
  • Target by target report: Evaluate each theorem and definition target independently in Main.lean by running compareAt and checkAxioms on each target separately instead of all at once. This is used to get type comparison and axiom checks result per target in the json report. Caching has been implemented to avoid traversing dependencies multiple times. Nanoda and kernel checking are still run on the full solution file.
  • Testing: Added integration tests in runtests.lean checking correctness of the JSON outputs.

JSON Fields Summary

  • reports: Array of individual target results.
    • targetName: Name of the theorem/definition.
    • targetKind: Declaration type ("theorem" or "definition").
    • failureCategory: Location of failure ("signature", "kind", "dependency", "axioms", or "not found").
    • failureMessage: Specific error reason/message.
    • unpermittedAxioms: Transitive axioms used by the target that are not legal.
    • transitiveAxioms: List of all transitive axioms used by the target.
  • kernel:
    • accepted: Boolean flags indicating global check verification success.
    • failureMessage: Diagnostic messages in case global checks fail.
  • nanoda:
    • accepted: Boolean flags indicating global check verification success.
    • failureMessage: Diagnostic messages in case global checks fail.

Comment thread Main.lean Outdated
Comment on lines +279 to +299
let reports ← (theoremNames.map (·, "theorem") ++ definitionNames.map (·, "definition")).mapM fun (n, k) => do
let (t, d) := if k == "theorem" then (#[n], definitionNames) else (#[], #[n])
let (cat, msg) := match Comparator.compareAt challenge solution t d (← primitiveTargets) with
| .error e => (some "comparison", some e)
| .ok () => match Comparator.checkAxioms solution t d legalAxioms with
| .error e => (some "axioms", some e)
| .ok () => (none, none)
return targetReport n k cat msg

let mut result := { reports }
writeReport result

let fails := reports.filter (·.failureCategory.isSome)
if !fails.isEmpty then
let msg := fails.foldl (init := "Some targets failed:\n") fun acc o =>
acc ++ s!"- {o.target}: {o.failureMessage.get!}\n"
throw <| .userError msg

let mut errs := #[]
if ← getNanodaEnabled then
runNanoda solutionExport
runKernel solution
try runNanoda solutionExport

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file looks in general a little oddly formatted, could you try sticking more to a standard code style from either core or Mathlib?

Comment thread Main.lean Outdated
let unpermittedAxioms := transitiveAxioms.filter (!legalAxioms.contains ·)
{ target := n, targetKind := k, failureCategory := cat, failureMessage := msg, unpermittedAxioms, transitiveAxioms : TargetReport }

let reports ← (theoremNames.map (·, "theorem") ++ definitionNames.map (·, "definition")).mapM fun (n, k) => do

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This loop has the same performance issue as checking each constant in the kernel individually. Suppose theoremNames is large and contains a lot of transitive dependencies (a lot of which are most likely going to be shared if they are coming from the same area of mathematics). Running the comparison functions on each of them is going to re-check the entire dependency closure O(|theoremNames|) times instead of just once. This is not going to be a noticeable performance diff for challenges with a small amount of theorems but if a user is interested in massively batching comparison this will slow the checking time down massively.

@augustepoiroux augustepoiroux force-pushed the upstream/json-verification-report branch from 74b0a8b to 7dc4553 Compare June 15, 2026 10:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants