[{"data":1,"prerenderedAt":4},["ShallowReactive",2],{"NmJ5vOtCbl":3},"# ChallengeGen\n\nOne declaration of a compiled Lean project, turned into a file that compiles on its own: its\ntransitive dependencies inlined, its proofs replaced by `sorry`, its imports cut down to the\nexternal frontier. One such file is a self-contained statement of one problem — which is what makes\nit usable as a challenge for something that has to produce the proof.\n\nDepends on Lean core and [`MeaningGraph`](https://github.com/RemyDegenne/meaning-graph), and\nnothing else. It was extracted from the\n[`exposition`](https://github.com/LeanMachineLearning/exposition) repository, whose `referee` tool\nis its first consumer, and is a package of its own so that generating challenges does not drag in\nthat tool's build (Verso, SubVerso, MD4Lean, …).\n\n## Two tiers\n\nBoth take the same input and differ only in how they render a declaration.\n\n- **`writeAllExtractions`** — the readable tier. Copies the **verbatim source text** of each\n  declaration and replays the surrounding `namespace`/`open`/`variable`/notation context, so\n  notation survives and the file reads the way a mathematician wrote it. Needs the project's source\n  files on disk.\n- **`Flat.writeAllFlatExtractions`** — the robust tier. Renders each declaration from its\n  `ConstantInfo`: fully qualified, `@`-explicit, no notation, no instance search, no context to\n  replay. Never opens a source file. Gives up readability and, with it, the entire class of\n  context-replay failures.\n\nThe intended use is both: prefer the readable file, fall back to the flat one for the declarations\nwhose readable version does not compile.\n\n## What you have to supply\n\n```lean\nstructure ChallengeDecl where\n  name : Name\n  kind : DeclKind\n  moduleName : Name\n  transDeps : Array Name := #[]\n```\n\nFour fields, and that is the whole interface. This package does **not** decide which declarations\nare worth extracting, and it does **not** compute or choose the dependency closure — a closure that\ndropped a lemma some kept tactic block calls would produce a file that does not compile, so the\nedge policy belongs to whoever knows what the files are for. Take the closure over edges that keep\nproofs; `MeaningGraph.transitiveDeps` is what computes it.\n\nBoth entry points also need a live `Environment` with the project imported, so a tool built on this\nruns inside the target project's `lake env`, the way `referee extract` does.\n\n```lean\nimport ChallengeGen\n\nopen Lean ChallengeGen\n\ndef writeChallenges (env : Environment) (root : Name) (decls : Array ChallengeDecl)\n    (projectDir out : System.FilePath) : IO Nat :=\n  writeAllExtractions env root decls projectDir out\n```\n\nEach file is named `\u003CanchorIdOf decl.name>.lean`. `anchorIdOf` is exported for exactly that reason:\na tool that links to these files has to compute the stem the same way the writer does, so there is\none definition of it and both sides import it.\n\n## Checks\n\n`lake build ChallengeGenTest` runs the `#guard`s: the pure string and syntax helpers, and the name\nmapping that decides what a file is called. They are elaboration-time, so building the target is\nrunning them.\n\nThe bulk of the extraction is exercised end to end against real projects instead — constructing a\nsynthetic `Environment` for those paths is impractical, and what actually matters is whether the\nfiles compile. The consumer this was extracted from measures that with a script that runs\n`lake env lean` over every generated file.\n\nThe test module is `ChallengeGen.Test`, not `Test`: module roots are shared across a whole Lake\nworkspace, so a package that claims the top-level name `Test` takes it away from every project that\nrequires it.\n",1790445563806]