2222//! - **Schema version sentinel** (all consumers):
2323//! reads `schema_version` to detect incompatible changes
2424
25- use panic_attack:: abduct;
26- use panic_attack:: amuck;
27- use panic_attack:: axial;
25+ use panic_attack:: abduct:: { self , AbductReport } ;
26+ use panic_attack:: amuck:: { self , AmuckReport } ;
27+ use panic_attack:: axial:: { self , AxialReport } ;
2828use panic_attack:: types:: * ;
2929use serde_json:: Value ;
3030
@@ -291,6 +291,7 @@ fn old_report_without_schema_version_deserializes_with_default() {
291291 ) ;
292292}
293293
294+ <<<<<<< HEAD
294295// ─── schema_version on subsidiary report types ───────────────────────────
295296
296297#[ test]
@@ -366,10 +367,23 @@ fn abduct_report_has_schema_version() {
366367 source_root : std:: path:: PathBuf :: from ( "." ) ,
367368 workspace_dir : std:: path:: PathBuf :: from ( "runtime/abduct" ) ,
368369 dependency_scope : "direct" . to_string ( ) ,
370+ =======
371+ // ─── AbductReport schema pin ─────────────────────────────────────────────
372+
373+ fn minimal_abduct_report( ) -> AbductReport {
374+ AbductReport {
375+ schema_version : "2.5" . to_string ( ) ,
376+ created_at : "2026-01-01T00:00:00Z" . to_string ( ) ,
377+ target : std:: path:: PathBuf :: from ( "src/main.rs" ) ,
378+ source_root : std:: path:: PathBuf :: from ( "src" ) ,
379+ workspace_dir : std:: path:: PathBuf :: from ( "runtime/abduct/test" ) ,
380+ dependency_scope : "none" . to_string ( ) ,
381+ >>>>>>> 87578 d9 ( feat( pa15) : complete P2 -A15 must-items — schema_version, headless, adjust. ncl , seam tests)
369382 selected_files: 0 ,
370383 locked_files: 0 ,
371384 mtime_shifted_files: 0 ,
372385 mtime_offset_days: 0 ,
386+ <<<<<<< HEAD
373387 time_mode: "real". to_string ( ) ,
374388 time_scale: None ,
375389 virtual_now: None ,
@@ -380,4 +394,165 @@ fn abduct_report_has_schema_version() {
380394 let json: Value = serde_json:: to_value ( & r) . expect ( "serialize" ) ;
381395 assert_eq ! ( json[ "schema_version" ] . as_str( ) , Some ( "2.5" ) ,
382396 "AbductReport must carry schema_version" ) ;
397+ =======
398+ time_mode: "normal" . to_string ( ) ,
399+ time_scale: None ,
400+ virtual_now: None ,
401+ notes: vec ! [ ] ,
402+ files: vec![ ] ,
403+ execution: None ,
404+ }
405+ }
406+
407+ #[ test]
408+ fn abduct_report_has_schema_version( ) {
409+ let report = minimal_abduct_report( ) ;
410+ let json: Value = serde_json:: to_value( & report) . expect( "serialize" ) ;
411+ assert_eq!(
412+ json[ "schema_version" ] . as_str( ) ,
413+ Some ( "2.5" ) ,
414+ "AbductReport schema_version must be '2.5'"
415+ ) ;
416+ }
417+
418+ #[ test]
419+ fn abduct_report_schema_version_round_trip( ) {
420+ let report = minimal_abduct_report( ) ;
421+ let json_str = serde_json:: to_string( & report) . expect( "serialize" ) ;
422+ let back: AbductReport = serde_json:: from_str( & json_str) . expect( "deserialize" ) ;
423+ assert_eq!( back. schema_version, "2.5" ) ;
424+ }
425+
426+ #[ test]
427+ fn old_abduct_report_without_schema_version_deserializes_with_default( ) {
428+ let json_str = r#"{
429+ "created_at": "2026-01-01T00:00:00Z",
430+ "target": "src/main.rs",
431+ "source_root": "src",
432+ "workspace_dir": "runtime/abduct/test",
433+ "dependency_scope": "none",
434+ "selected_files": 0,
435+ "locked_files": 0,
436+ "mtime_shifted_files": 0,
437+ "mtime_offset_days": 0,
438+ "time_mode": "normal"
439+ }"# ;
440+ let report: AbductReport =
441+ serde_json:: from_str( json_str) . expect( "deserialize old abduct report" ) ;
442+ assert_eq!(
443+ report. schema_version, "2.5" ,
444+ "old AbductReport missing schema_version must default to '2.5'"
445+ ) ;
446+ }
447+
448+ // ─── AmuckReport schema pin ──────────────────────────────────────────────
449+
450+ fn minimal_amuck_report( ) -> AmuckReport {
451+ AmuckReport {
452+ schema_version: "2.5" . to_string( ) ,
453+ created_at: "2026-01-01T00:00:00Z" . to_string( ) ,
454+ target: std:: path:: PathBuf :: from( "src/main.rs" ) ,
455+ source_spec: None ,
456+ preset: "light" . to_string( ) ,
457+ max_combinations: 0 ,
458+ output_dir: std:: path:: PathBuf :: from( "runtime/amuck" ) ,
459+ combinations_planned: 0 ,
460+ combinations_run: 0 ,
461+ outcomes: vec![ ] ,
462+ }
463+ }
464+
465+ #[ test]
466+ fn amuck_report_has_schema_version( ) {
467+ let report = minimal_amuck_report( ) ;
468+ let json: Value = serde_json:: to_value( & report) . expect( "serialize" ) ;
469+ assert_eq!(
470+ json[ "schema_version" ] . as_str( ) ,
471+ Some ( "2.5" ) ,
472+ "AmuckReport schema_version must be '2.5'"
473+ ) ;
474+ }
475+
476+ #[ test]
477+ fn amuck_report_schema_version_round_trip( ) {
478+ let report = minimal_amuck_report( ) ;
479+ let json_str = serde_json:: to_string( & report) . expect( "serialize" ) ;
480+ let back: AmuckReport = serde_json:: from_str( & json_str) . expect( "deserialize" ) ;
481+ assert_eq!( back. schema_version, "2.5" ) ;
482+ }
483+
484+ #[ test]
485+ fn old_amuck_report_without_schema_version_deserializes_with_default( ) {
486+ let json_str = r#"{
487+ "created_at": "2026-01-01T00:00:00Z",
488+ "target": "src/main.rs",
489+ "preset": "light",
490+ "max_combinations": 0,
491+ "output_dir": "runtime/amuck",
492+ "combinations_planned": 0,
493+ "combinations_run": 0,
494+ "outcomes": []
495+ }"# ;
496+ let report: AmuckReport = serde_json:: from_str( json_str) . expect( "deserialize old amuck report" ) ;
497+ assert_eq!(
498+ report. schema_version, "2.5" ,
499+ "old AmuckReport missing schema_version must default to '2.5'"
500+ ) ;
501+ }
502+
503+ // ─── AxialReport schema pin ──────────────────────────────────────────────
504+
505+ fn minimal_axial_report( ) -> AxialReport {
506+ AxialReport {
507+ schema_version: "2.5" . to_string( ) ,
508+ created_at: "2026-01-01T00:00:00Z" . to_string( ) ,
509+ target: std:: path:: PathBuf :: from( "src/main.rs" ) ,
510+ executed_program: None ,
511+ repeat: 0 ,
512+ observed_runs: 0 ,
513+ observed_reports: 0 ,
514+ language: "en" . to_string( ) ,
515+ run_observations: vec![ ] ,
516+ report_observations: vec![ ] ,
517+ signal_counts: std:: collections:: BTreeMap :: new( ) ,
518+ recommendations: vec![ ] ,
519+ aspell: None ,
520+ }
521+ }
522+
523+ #[ test]
524+ fn axial_report_has_schema_version( ) {
525+ let report = minimal_axial_report( ) ;
526+ let json: Value = serde_json:: to_value( & report) . expect( "serialize" ) ;
527+ assert_eq!(
528+ json[ "schema_version" ] . as_str( ) ,
529+ Some ( "2.5" ) ,
530+ "AxialReport schema_version must be '2.5'"
531+ ) ;
532+ }
533+
534+ #[ test]
535+ fn axial_report_schema_version_round_trip( ) {
536+ let report = minimal_axial_report( ) ;
537+ let json_str = serde_json:: to_string( & report) . expect( "serialize" ) ;
538+ let back: AxialReport = serde_json:: from_str( & json_str) . expect( "deserialize" ) ;
539+ assert_eq!( back. schema_version, "2.5" ) ;
540+ }
541+
542+ #[ test]
543+ fn old_axial_report_without_schema_version_deserializes_with_default( ) {
544+ let json_str = r#"{
545+ "created_at": "2026-01-01T00:00:00Z",
546+ "target": "src/main.rs",
547+ "repeat": 0,
548+ "observed_runs": 0,
549+ "observed_reports": 0,
550+ "language": "en"
551+ }"# ;
552+ let report: AxialReport = serde_json:: from_str( json_str) . expect( "deserialize old axial report" ) ;
553+ assert_eq!(
554+ report. schema_version, "2.5" ,
555+ "old AxialReport missing schema_version must default to '2.5'"
556+ ) ;
557+ >>>>>>> 87578 d9 ( feat( pa15) : complete P2 -A15 must-items — schema_version, headless, adjust. ncl, seam tests)
383558}
0 commit comments