//! Independent exact native lesson oracle, compiled against existing core libraries. //! Usage: CHECKER oa|review|fold|state-rename NATIVE_ENTRY BEFORE_REVIEW_ENTRY OUTPUT_DIRECTORY #[path = "../examples/release1/model.rs"] mod teaching; use oa_core::{source_files, source_project::*, transitions::*, *}; use std::{fs, path::Path}; fn disk(entry: &Path) -> CompiledSourceProject { let read = source_files::load_project(entry, ProjectLimits::default()).unwrap(); assert!( read.diagnostics .iter() .all(|diagnostic| diagnostic.diagnostic.severity != validation::Severity::Error), "{:?}", read.diagnostics ); let raw = read.reachable_bundle(); let compiled = compile_bundle(&raw, ProjectLimits::default()).unwrap(); assert_eq!( raw, compiled.bundle, "Use a checker built for the source profile being measured; migration or identity stabilization must not normalize the native bytes." ); compiled } fn compare(expected: &CompiledSourceProject, actual: &CompiledSourceProject, label: &str) { assert_eq!( expected.decoded.project, actual.decoded.project, "{label}: full model differs; no metadata/identity exclusions are allowed" ); assert_eq!( expected.bundle.entry, actual.bundle.entry, "{label}: entry differs" ); assert_eq!( expected.bundle.files.keys().collect::>(), actual.bundle.files.keys().collect::>(), "{label}: module set differs" ); for (name, text) in &expected.bundle.files { assert_eq!( text, &actual.bundle.files[name], "{label}: exact source differs in {name}" ); } } fn main() { let args: Vec<_> = std::env::args().collect(); assert_eq!( args.len(), 5, "usage: CHECKER oa|review|fold|state-rename NATIVE_ENTRY BEFORE_REVIEW_ENTRY OUTPUT_DIRECTORY" ); assert!(matches!( args[1].as_str(), "oa" | "review" | "fold" | "state-rename" )); let lesson = teaching::build(); assert_eq!(lesson.before_transition.id, lesson.project.id); assert!(!lesson.request.sources.is_empty()); let original = compile_bundle( &teaching::checked_bundle(&lesson.project), ProjectLimits::default(), ) .unwrap(); let source = teaching::id("oa_confirm"); let target = teaching::id("sa_confirm"); let mut renamed = lesson.project.elements[&source].clone(); renamed.name = "Confirm stable pressure".into(); let renamed_model = execute_batch(&lesson.project, &[Command::EditElement(source, renamed)]).unwrap(); let before = update_bundle(&original, &renamed_model, ProjectLimits::default()).unwrap(); compare( &before, &disk(Path::new(&args[3])), "preserved OA rename baseline", ); let mut transition = TransitionRequest::new(TransitionDirection::OaToSa, vec![source]); transition.fields.clear(); transition.mappings.push(TransitionMapping { source, target: Some(target), target_kind: None, }); let mut request = SemanticTransitionRequest::new(transition); request.reviews.push(SemanticReviewRequest { source, resolutions: vec![FacetResolution { facet: FacetSelector::Header(HeaderFacet::Name), decision: SemanticDecision::TakeSource, }], reset: vec![], }); let plan = plan_semantic_transition(&before.decoded.project, request).unwrap(); assert!(plan.conflicts.is_empty(), "{:?}", plan.conflicts); let reviewed = apply_semantic_transition(&before.decoded.project, &plan).unwrap(); let after = update_bundle(&before, &reviewed, ProjectLimits::default()).unwrap(); let mut state_model = reviewed.clone(); if args[1] == "fold" { let diagram = state_model .diagrams .get_mut(&teaching::id("sa_state_view")) .unwrap(); let matching: Vec<_> = diagram .nodes .values_mut() .filter(|node| node.element == teaching::id("sa_monitor_region")) .collect(); assert_eq!(matching.len(), 1); for node in matching { assert!(!node.collapsed); node.collapsed = true; } } else if args[1] == "state-rename" { let work = state_model .elements .get_mut(&teaching::id("sa_assess")) .unwrap(); assert_eq!(work.name, "Assess pressure alarm"); work.name = "Assess incoming pressure alarm".into(); } let state_model = execute_batch(&reviewed, &[Command::Replace(state_model)]).unwrap(); let state_after = update_bundle(&after, &state_model, ProjectLimits::default()).unwrap(); let expected = match args[1].as_str() { "oa" => &before, "review" => &after, _ => &state_after, }; let output = Path::new(&args[4]); fs::create_dir_all(output).unwrap(); fs::write( output.join("expected-model.json"), serde_json::to_string_pretty(&expected.decoded.project).unwrap(), ) .unwrap(); fs::write( output.join("expected-source-bundle.json"), serde_json::to_string_pretty(&expected.bundle).unwrap(), ) .unwrap(); compare(expected, &disk(Path::new(&args[2])), "native result"); println!( "PASS {}: exact full model and {} source files; preserved OA rename baseline verified; no identity or metadata normalization", args[1], expected.bundle.files.len() ); }