/// The first run of a fixture to report a complete solution set, which every later run must match.
/// modelling choice that loses (or invents) solutions would otherwise be accepted silently whenever
"test_dir={path}, model={essence_base}.{extension}, parser={}, rewriter={}, comprehension_expander={}, heuristic={}, seed={}, channelling={}, solver={}, solver_seed={}",
fn exhaustive_test(path: &str, essence_base: &str, extension: &str) -> Result<(), Box<dyn Error>> {
/// Set `CONJURE_OXIDE_TEST_DISABLE_TRACING=1` to skip rule trace generation and validation during
/// - **Stage 1a (Default)**: Reads the Essence model file and verifies that it parses correctly using `parser = "tree-sitter"`.
/// - **Stage 1b (Optional)**: Reads the Essence model file and verifies that it parses correctly using `parser = "via-conjure"`.
/// Returns an error if any stage fails due to a mismatch with expected results or file I/O issues.
set_default_rule_trace_enabled(rule_trace_snapshots_enabled && default_rule_trace_enabled);
let solutions = if let Some(number_of_solutions) = number_of_solutions.as_solver_limit() {
// Stage 3b: Check solutions against Conjure when accept mode is enabled and validation is enabled.
let generated_solutions = read_solutions_essence(path, case_name, "generated", solver_fam)?;
/// Reports whether the search stopped early because it hit a numeric `number-of-solutions` limit.
/// Once the search is cut short, the solutions found are an arbitrary subset of the full solution
/// set: two runs that enumerate in different orders keep different subsets of the same size. Set
/// comparisons are meaningless in that case, so callers fall back to comparing counts. `count` is
/// the largest number of solutions any of the runs being compared found; a run that finished below
/// Advances a depth-first mixed-radix branch path using the choices observed during the latest
/// replay. Earlier branches are replayed from a freshly parsed model, so no mutable AST state is
if !conjure_captured && let Some(number_of_solutions) = number_of_solutions.as_solver_limit() {