1#![forbid(unsafe_code)]
2pub mod movement;
6pub mod persistence;
7pub mod primitives;
8pub mod verification;
9
10pub use movement::{Event, LawCheck, MovementMemory, Transition};
11pub use persistence::{
12 load_reality, load_signed_reality, load_signed_snapshot, load_snapshot, save_reality,
13 save_signed_reality, save_signed_snapshot, save_snapshot, sign_reality, sign_snapshot,
14 PersistenceError, SignedReality, SignedSnapshot, PERSISTENCE_VERSION,
15};
16pub use primitives::{Boundary, Identity, Law, Reality, State};
17pub use verification::{
18 detect_drift, plan_sequence, simulate_sequence, Continuity, DriftCheck, Inspection,
19 IntegrityReport, MovementError, PlannedSequence, PreflightReport, ProofResult, RealityDiff,
20 RealityFingerprint, RealitySnapshot, Replay, SimulationReport, VerificationReport,
21};
22
23pub fn perform_movement(reality: &mut Reality, event: Event) -> Result<ProofResult, MovementError> {
27 if reality.identity.0.is_empty() {
32 return Err(MovementError::IdentityMissingOrUnstable);
33 }
34
35 if reality.boundary.allowed_values.is_empty() {
37 return Err(MovementError::BoundaryMissing);
38 }
39
40 if reality.law.allowed_transitions.is_empty() {
42 return Err(MovementError::LawMissing);
43 }
44
45 if reality.state.field.is_empty() {
47 return Err(MovementError::StateMissing);
48 }
49
50 if !reality
52 .boundary
53 .allowed_values
54 .contains(&reality.state.field)
55 {
56 return Err(MovementError::StateOutsideBoundary);
57 }
58
59 let event_directly_mutated_state = false;
65
66 let law_check_result = reality.law.check(&reality.state, &event);
68 let law_check = LawCheck {
69 result: law_check_result,
70 explanation: if law_check_result {
71 "lawful transition".to_string()
72 } else {
73 "unlawful transition".to_string()
74 },
75 };
76 let law_check_performed = true;
77
78 if !law_check.result {
80 return Err(MovementError::TransitionNotGroundedInLawCheck);
81 }
82
83 let after_state = State {
85 field: event.proposed_field.clone(),
86 };
87
88 let prev_hash = reality.memory.current_hash();
90 let self_hash =
91 movement::hash_transition(prev_hash, &reality.state, &after_state, law_check.result);
92
93 let transition = Transition {
94 before: reality.state.clone(),
95 after: after_state.clone(),
96 law_check_valid: law_check.result,
97 prev_hash,
98 self_hash,
99 };
100
101 reality.memory.transitions.push(transition);
102 reality.state = after_state;
103
104 #[cfg(test)]
106 if let Some(hook) = reality.test_hook {
107 hook(reality);
108 }
109
110 let inspection = Inspection {
112 initial_state: reality.initial_state.clone(),
113 memory: reality.memory.clone(),
114 current_state: reality.state.clone(),
115 };
116 let inspection_available = inspection.initial_state == reality.initial_state
117 && inspection.memory == reality.memory
118 && inspection.current_state == reality.state;
119
120 let mut replayed_state = reality.initial_state.clone();
122 for t in &reality.memory.transitions {
123 if !t.law_check_valid {
124 return Err(MovementError::TransitionNotGroundedInLawCheck);
125 }
126 replayed_state = t.after.clone();
127 }
128 let replay_result = replayed_state == reality.state;
129
130 let continuity_result = replay_result;
132
133 let drift_check = detect_drift(
135 &reality.birth_boundary,
136 &reality.birth_law,
137 &reality.boundary,
138 &reality.law,
139 replay_result,
140 );
141
142 if drift_check.hidden_state_mutation_detected {
143 return Err(MovementError::DriftCheckDetectedHiddenStateMutation);
144 }
145 if drift_check.hidden_boundary_growth_detected {
146 return Err(MovementError::DriftCheckDetectedHiddenBoundaryGrowth);
147 }
148 if drift_check.hidden_law_growth_detected {
149 return Err(MovementError::DriftCheckDetectedHiddenLawGrowth);
150 }
151 if drift_check.permission_drift_detected {
152 return Err(MovementError::DriftCheckDetectedPermissionDrift);
153 }
154
155 let proof = ProofResult {
157 reality_exists: true,
158 identity_confirmed: true,
159 active_boundary_confirmed: true,
160 active_law_confirmed: true,
161 state_confirmed: true,
162 event_received: true,
163 event_directly_mutated_state,
164 law_check_performed,
165 law_check_result: law_check.result,
166 transition_recorded: true,
167 transition_grounded_in_law_check: true,
168 movement_memory_recorded: !reality.memory.transitions.is_empty(),
169 inspection_available,
170 replay_result,
171 continuity_result,
172 hidden_state_mutation_detected: false,
173 hidden_boundary_growth_detected: false,
174 hidden_law_growth_detected: false,
175 permission_drift_detected: false,
176 hidden_drift_required: false,
177 proof_status: true,
178 };
179
180 if !proof.reality_exists
182 || !proof.identity_confirmed
183 || !proof.active_boundary_confirmed
184 || !proof.active_law_confirmed
185 || !proof.state_confirmed
186 || !proof.event_received
187 || proof.event_directly_mutated_state
188 || !proof.law_check_performed
189 || !proof.law_check_result
190 || !proof.transition_recorded
191 || !proof.transition_grounded_in_law_check
192 || !proof.movement_memory_recorded
193 || !proof.inspection_available
194 || !proof.replay_result
195 || !proof.continuity_result
196 || proof.hidden_state_mutation_detected
197 || proof.hidden_boundary_growth_detected
198 || proof.hidden_law_growth_detected
199 || proof.permission_drift_detected
200 || proof.hidden_drift_required
201 {
202 return Err(MovementError::ProofResultDeclaresPassWithoutEvidence);
203 }
204
205 Ok(proof)
206}
207
208pub fn perform_movement_sequence(
211 reality: &mut Reality,
212 events: Vec<Event>,
213) -> Result<Vec<ProofResult>, MovementError> {
214 let mut proofs = Vec::with_capacity(events.len());
215 for event in events {
216 let proof = perform_movement(reality, event)?;
217 proofs.push(proof);
218 }
219 Ok(proofs)
220}
221
222#[cfg(test)]
223mod tests {
224 use super::*;
225
226 fn minimal_reality() -> Reality {
227 Reality::new(
228 Identity("r0".to_string()),
229 Boundary {
230 allowed_values: vec!["before".to_string(), "after".to_string()],
231 },
232 Law {
233 allowed_transitions: vec![("before".to_string(), "after".to_string())],
234 },
235 State {
236 field: "before".to_string(),
237 },
238 )
239 }
240
241 fn multi_step_reality() -> Reality {
242 Reality::new(
243 Identity("r1".to_string()),
244 Boundary {
245 allowed_values: vec![
246 "before".to_string(),
247 "after".to_string(),
248 "done".to_string(),
249 ],
250 },
251 Law {
252 allowed_transitions: vec![
253 ("before".to_string(), "after".to_string()),
254 ("after".to_string(), "done".to_string()),
255 ],
256 },
257 State {
258 field: "before".to_string(),
259 },
260 )
261 }
262
263 #[test]
264 fn valid_movement_passes_all_invariants() {
265 let mut reality = minimal_reality();
266 let event = Event {
267 proposed_field: "after".to_string(),
268 };
269
270 let proof = perform_movement(&mut reality, event).expect("movement should succeed");
271
272 assert!(proof.proof_status);
273 assert!(!proof.event_directly_mutated_state);
274 assert!(proof.law_check_result);
275 assert!(proof.transition_recorded);
276 assert!(proof.continuity_result);
277 assert!(!proof.hidden_state_mutation_detected);
278 assert!(!proof.hidden_drift_required);
279 assert!(reality.memory_integrity());
280 }
281
282 #[test]
283 fn unlawful_event_fails() {
284 let mut reality = minimal_reality();
285 let event = Event {
286 proposed_field: "before".to_string(),
287 };
288
289 let result = perform_movement(&mut reality, event);
290 assert!(result.is_err());
291 assert!(reality.memory().transitions.is_empty());
292 }
293
294 #[test]
295 fn missing_identity_fails() {
296 let mut reality = minimal_reality();
297 reality.identity.0 = String::new();
298 let event = Event {
299 proposed_field: "after".to_string(),
300 };
301 let result = perform_movement(&mut reality, event);
302 assert_eq!(
303 result.unwrap_err(),
304 MovementError::IdentityMissingOrUnstable
305 );
306 }
307
308 #[test]
309 fn state_outside_boundary_fails() {
310 let mut reality = minimal_reality();
311 reality.state.field = "outside".to_string();
312 let event = Event {
313 proposed_field: "after".to_string(),
314 };
315 let result = perform_movement(&mut reality, event);
316 assert_eq!(result.unwrap_err(), MovementError::StateOutsideBoundary);
317 }
318
319 #[test]
320 fn hidden_boundary_growth_detected_via_test_hook() {
321 let mut reality = minimal_reality();
322 reality.test_hook = Some(|r: &mut Reality| {
323 r.boundary.allowed_values.push("sneaky".to_string());
324 });
325 let event = Event {
326 proposed_field: "after".to_string(),
327 };
328
329 let result = perform_movement(&mut reality, event);
330 assert_eq!(
331 result.unwrap_err(),
332 MovementError::DriftCheckDetectedHiddenBoundaryGrowth
333 );
334 assert_eq!(reality.memory().transitions.len(), 1);
335 }
336
337 #[test]
338 fn valid_sequence_moves_through_all_steps() {
339 let mut reality = multi_step_reality();
340 let events = vec![
341 Event {
342 proposed_field: "after".to_string(),
343 },
344 Event {
345 proposed_field: "done".to_string(),
346 },
347 ];
348
349 let proofs =
350 perform_movement_sequence(&mut reality, events).expect("sequence should succeed");
351
352 assert_eq!(proofs.len(), 2);
353 assert!(proofs.iter().all(|p| p.proof_status));
354 assert_eq!(reality.state.field, "done");
355 assert_eq!(reality.memory().transitions.len(), 2);
356 assert!(reality.memory_integrity());
357 }
358
359 #[test]
360 fn sequence_stops_on_unlawful_event() {
361 let mut reality = multi_step_reality();
362 let events = vec![
363 Event {
364 proposed_field: "after".to_string(),
365 },
366 Event {
367 proposed_field: "after".to_string(),
368 },
369 ];
370
371 let result = perform_movement_sequence(&mut reality, events);
372
373 assert!(result.is_err());
374 assert_eq!(reality.state.field, "after");
375 assert_eq!(reality.memory().transitions.len(), 1);
376 }
377
378 #[test]
379 fn inspection_method_returns_proof_path() {
380 let mut reality = minimal_reality();
381 let event = Event {
382 proposed_field: "after".to_string(),
383 };
384 let _ = perform_movement(&mut reality, event).unwrap();
385
386 let inspection = reality.inspect();
387 assert_eq!(inspection.initial_state, reality.initial_state);
388 assert_eq!(inspection.memory, reality.memory);
389 assert_eq!(inspection.current_state, reality.state);
390 }
391
392 #[test]
393 fn replay_method_matches_current_state() {
394 let mut reality = minimal_reality();
395 let event = Event {
396 proposed_field: "after".to_string(),
397 };
398 let _ = perform_movement(&mut reality, event).unwrap();
399
400 let replay = reality.replay();
401 assert!(replay.passed);
402 assert_eq!(replay.replayed_state, reality.state);
403 }
404
405 #[test]
406 fn continuity_method_reflects_state_match() {
407 let mut reality = minimal_reality();
408 let event = Event {
409 proposed_field: "after".to_string(),
410 };
411 let _ = perform_movement(&mut reality, event).unwrap();
412
413 let continuity = reality.continuity();
414 assert!(continuity.preserved);
415 }
416
417 #[test]
418 fn continuity_detects_state_mismatch() {
419 let mut reality = minimal_reality();
420 let event = Event {
421 proposed_field: "after".to_string(),
422 };
423 let _ = perform_movement(&mut reality, event).unwrap();
424
425 reality.state.field = "sneaky".to_string();
427
428 let replay = reality.replay();
429 assert!(!replay.passed);
430 let continuity = reality.continuity();
431 assert!(!continuity.preserved);
432 }
433
434 #[test]
435 fn verify_returns_bundled_report() {
436 let mut reality = minimal_reality();
437 let event = Event {
438 proposed_field: "after".to_string(),
439 };
440 let _ = perform_movement(&mut reality, event).unwrap();
441
442 let report = reality.verify();
443 assert!(report.replay.passed);
444 assert!(report.continuity.preserved);
445 assert!(report.memory_integrity);
446 assert_eq!(report.inspection.current_state, reality.state);
447 }
448
449 #[test]
450 fn memory_integrity_preserved_after_valid_movement() {
451 let mut reality = minimal_reality();
452 let event = Event {
453 proposed_field: "after".to_string(),
454 };
455 let _ = perform_movement(&mut reality, event).unwrap();
456 assert!(reality.memory_integrity());
457 }
458
459 #[test]
460 fn memory_tampering_detected() {
461 let mut reality = minimal_reality();
462 let event = Event {
463 proposed_field: "after".to_string(),
464 };
465 let _ = perform_movement(&mut reality, event).unwrap();
466
467 reality.memory.transitions[0].after.field = "sneaky".to_string();
469
470 assert!(!reality.memory_integrity());
471 let replay = reality.replay();
472 assert!(!replay.passed);
473 }
474
475 #[test]
476 fn drift_between_movements_detected() {
477 let mut reality = multi_step_reality();
478 let first_event = Event {
479 proposed_field: "after".to_string(),
480 };
481 let _ = perform_movement(&mut reality, first_event).unwrap();
482
483 reality.boundary.allowed_values.push("sneaky".to_string());
485
486 let second_event = Event {
487 proposed_field: "done".to_string(),
488 };
489 let result = perform_movement(&mut reality, second_event);
490 assert_eq!(
491 result.unwrap_err(),
492 MovementError::DriftCheckDetectedHiddenBoundaryGrowth
493 );
494 }
495
496 #[test]
497 fn public_drift_check_reports_clean_when_no_drift() {
498 let mut reality = minimal_reality();
499 let event = Event {
500 proposed_field: "after".to_string(),
501 };
502 let _ = perform_movement(&mut reality, event).unwrap();
503
504 let drift = reality.drift_check();
505 assert!(!drift.hidden_state_mutation_detected);
506 assert!(!drift.hidden_boundary_growth_detected);
507 assert!(!drift.hidden_law_growth_detected);
508 assert!(!drift.permission_drift_detected);
509 assert!(!drift.hidden_drift_required);
510 }
511
512 #[test]
513 fn public_drift_check_detects_hidden_boundary_growth() {
514 let mut reality = minimal_reality();
515 let event = Event {
516 proposed_field: "after".to_string(),
517 };
518 let _ = perform_movement(&mut reality, event).unwrap();
519
520 reality.boundary.allowed_values.push("sneaky".to_string());
522
523 let drift = reality.drift_check();
524 assert!(drift.hidden_boundary_growth_detected);
525 assert!(drift.hidden_drift_required);
526 }
527
528 #[test]
529 fn compose_returns_valid_view() {
530 let mut reality = multi_step_reality();
531 let events = vec![
532 Event {
533 proposed_field: "after".to_string(),
534 },
535 Event {
536 proposed_field: "done".to_string(),
537 },
538 ];
539 let _ = perform_movement_sequence(&mut reality, events).unwrap();
540
541 let comp = reality.memory().compose(0, 1).expect("valid composition");
542 assert_eq!(comp.start_state.field, "before");
543 assert_eq!(comp.end_state.field, "done");
544 assert_eq!(comp.hash, reality.memory().current_hash());
545 assert!(comp.verify(reality.memory()));
546 }
547
548 #[test]
549 fn compose_rejects_invalid_range() {
550 let mut reality = multi_step_reality();
551 let events = vec![
552 Event {
553 proposed_field: "after".to_string(),
554 },
555 Event {
556 proposed_field: "done".to_string(),
557 },
558 ];
559 let _ = perform_movement_sequence(&mut reality, events).unwrap();
560
561 assert!(reality.memory().compose(1, 0).is_none());
562 assert!(reality.memory().compose(0, 2).is_none()); }
564
565 #[test]
566 fn composition_verifies_correctly_and_detects_tamper() {
567 let mut reality = multi_step_reality();
568 let events = vec![
569 Event {
570 proposed_field: "after".to_string(),
571 },
572 Event {
573 proposed_field: "done".to_string(),
574 },
575 ];
576 let _ = perform_movement_sequence(&mut reality, events).unwrap();
577
578 let comp = reality.memory().compose(0, 1).unwrap();
579 assert!(comp.verify(reality.memory()));
580
581 reality.memory.transitions[1].after.field = "sneaky".to_string();
583 assert!(!comp.verify(reality.memory()));
584 }
585
586 #[test]
587 fn plan_sequence_succeeds_without_mutating_original() {
588 let reality = multi_step_reality();
589 let events = vec![
590 Event {
591 proposed_field: "after".to_string(),
592 },
593 Event {
594 proposed_field: "done".to_string(),
595 },
596 ];
597
598 let planned = plan_sequence(&reality, events).expect("plan should succeed");
599
600 assert_eq!(planned.final_state.field, "done");
601 assert_eq!(planned.transition_count, 2);
602 assert_eq!(planned.proofs.len(), 2);
603 assert_eq!(reality.state.field, "before");
605 assert_eq!(reality.memory().transitions.len(), 0);
606 }
607
608 #[test]
609 fn plan_sequence_fails_on_unlawful_event() {
610 let reality = multi_step_reality();
611 let events = vec![
612 Event {
613 proposed_field: "after".to_string(),
614 },
615 Event {
616 proposed_field: "after".to_string(),
617 },
618 ];
619
620 let result = plan_sequence(&reality, events);
621 assert!(result.is_err());
622 assert_eq!(reality.state.field, "before");
624 assert_eq!(reality.memory().transitions.len(), 0);
625 }
626
627 #[test]
628 fn planned_sequence_matches_executed_sequence() {
629 let mut reality = multi_step_reality();
630 let events = vec![
631 Event {
632 proposed_field: "after".to_string(),
633 },
634 Event {
635 proposed_field: "done".to_string(),
636 },
637 ];
638
639 let planned = plan_sequence(&reality, events.clone()).expect("plan should succeed");
640 let actual =
641 perform_movement_sequence(&mut reality, events).expect("execute should succeed");
642
643 assert_eq!(planned.final_state, reality.state);
644 assert_eq!(planned.transition_count, reality.memory().transitions.len());
645 assert_eq!(planned.proofs, actual);
646 }
647
648 #[test]
649 fn identical_realities_have_identical_fingerprints() {
650 let reality1 = multi_step_reality();
651 let reality2 = multi_step_reality();
652
653 assert_eq!(reality1.fingerprint(), reality2.fingerprint());
654 }
655
656 #[test]
657 fn mutation_changes_fingerprint() {
658 let mut reality = multi_step_reality();
659 let original_fingerprint = reality.fingerprint();
660
661 let event = Event {
662 proposed_field: "after".to_string(),
663 };
664 let _ = perform_movement(&mut reality, event).unwrap();
665
666 let new_fingerprint = reality.fingerprint();
667 assert_ne!(original_fingerprint, new_fingerprint);
668 }
669
670 #[test]
671 fn integrity_report_reflects_clean_state() {
672 let mut reality = multi_step_reality();
673 let events = vec![
674 Event {
675 proposed_field: "after".to_string(),
676 },
677 Event {
678 proposed_field: "done".to_string(),
679 },
680 ];
681 let _ = perform_movement_sequence(&mut reality, events).unwrap();
682
683 let report = reality.integrity_report();
684
685 assert_eq!(report.fingerprint, reality.fingerprint());
686 assert!(!report.drift.hidden_drift_required);
687 assert!(report.memory_integrity);
688 assert!(report.replay.passed);
689 assert!(report.continuity.preserved);
690 assert_eq!(report.state, reality.state);
691 assert_eq!(report.transition_count, 2);
692 }
693
694 #[test]
695 fn integrity_report_detects_drift() {
696 let mut reality = multi_step_reality();
697 let events = vec![
698 Event {
699 proposed_field: "after".to_string(),
700 },
701 Event {
702 proposed_field: "done".to_string(),
703 },
704 ];
705 let _ = perform_movement_sequence(&mut reality, events).unwrap();
706
707 reality.boundary.allowed_values.push("sneaky".to_string());
709
710 let report = reality.integrity_report();
711
712 assert!(report.drift.hidden_boundary_growth_detected);
713 assert!(report.drift.hidden_drift_required);
714 assert!(report.memory_integrity);
716 }
717
718 #[test]
719 fn would_accept_lawful_event() {
720 let reality = multi_step_reality();
721 let event = Event {
722 proposed_field: "after".to_string(),
723 };
724 assert!(reality.would_accept(&event));
725 }
726
727 #[test]
728 fn would_accept_rejects_unlawful_event() {
729 let reality = multi_step_reality();
730 let event = Event {
731 proposed_field: "before".to_string(),
732 };
733 assert!(!reality.would_accept(&event));
734 }
735
736 #[test]
737 fn would_accept_rejects_empty_event() {
738 let reality = multi_step_reality();
739 let event = Event {
740 proposed_field: String::new(),
741 };
742 assert!(!reality.would_accept(&event));
743 }
744
745 #[test]
746 fn simulate_sequence_succeeds_and_does_not_mutate_original() {
747 let reality = multi_step_reality();
748 let events = vec![
749 Event {
750 proposed_field: "after".to_string(),
751 },
752 Event {
753 proposed_field: "done".to_string(),
754 },
755 ];
756
757 let report = simulate_sequence(&reality, events).expect("simulation should succeed");
758
759 assert_eq!(report.planned.final_state.field, "done");
760 assert_eq!(report.planned.transition_count, 2);
761 assert!(report.integrity.memory_integrity);
762 assert!(report.integrity.replay.passed);
763 assert!(report.integrity.continuity.preserved);
764 assert!(!report.integrity.drift.hidden_drift_required);
765 assert!(report.composition.is_some());
766 assert_eq!(report.fingerprint, report.integrity.fingerprint);
767
768 assert_eq!(reality.state.field, "before");
770 assert_eq!(reality.memory().transitions.len(), 0);
771 }
772
773 #[test]
774 fn simulate_sequence_fails_on_unlawful_event() {
775 let reality = multi_step_reality();
776 let events = vec![
777 Event {
778 proposed_field: "after".to_string(),
779 },
780 Event {
781 proposed_field: "after".to_string(),
782 },
783 ];
784
785 let result = simulate_sequence(&reality, events);
786 assert!(result.is_err());
787 assert_eq!(reality.state.field, "before");
788 assert_eq!(reality.memory().transitions.len(), 0);
789 }
790
791 #[test]
792 fn simulated_report_matches_actual_execution() {
793 let mut reality = multi_step_reality();
794 let events = vec![
795 Event {
796 proposed_field: "after".to_string(),
797 },
798 Event {
799 proposed_field: "done".to_string(),
800 },
801 ];
802
803 let simulation =
804 simulate_sequence(&reality, events.clone()).expect("simulation should succeed");
805 let actual =
806 perform_movement_sequence(&mut reality, events).expect("execution should succeed");
807
808 assert_eq!(simulation.planned.proofs, actual);
809 assert_eq!(simulation.planned.final_state, reality.state);
810 assert_eq!(
811 simulation.planned.transition_count,
812 reality.memory().transitions.len()
813 );
814 assert_eq!(simulation.fingerprint, reality.fingerprint());
815 assert_eq!(simulation.integrity, reality.integrity_report());
816 }
817
818 #[test]
819 fn identical_realities_have_all_same_diff() {
820 let r1 = multi_step_reality();
821 let r2 = multi_step_reality();
822
823 let diff = r1.diff(&r2);
824
825 assert!(diff.identity_same);
826 assert!(diff.boundary_same);
827 assert!(diff.law_same);
828 assert!(diff.state_same);
829 assert!(diff.initial_state_same);
830 assert!(diff.birth_boundary_same);
831 assert!(diff.birth_law_same);
832 assert!(diff.memory_hash_same);
833 assert!(diff.transition_count_same);
834 assert!(diff.fingerprint_same);
835 }
836
837 #[test]
838 fn diff_detects_state_change() {
839 let mut r1 = multi_step_reality();
840 let r2 = multi_step_reality();
841
842 let event = Event {
843 proposed_field: "after".to_string(),
844 };
845 let _ = perform_movement(&mut r1, event).unwrap();
846
847 let diff = r1.diff(&r2);
848
849 assert!(!diff.state_same);
850 assert!(!diff.memory_hash_same);
851 assert!(!diff.transition_count_same);
852 assert!(!diff.fingerprint_same);
853 assert!(diff.boundary_same);
854 assert!(diff.law_same);
855 }
856
857 #[test]
858 fn diff_detects_boundary_change() {
859 let mut r1 = multi_step_reality();
860 let r2 = multi_step_reality();
861
862 r1.boundary.allowed_values.push("sneaky".to_string());
864
865 let diff = r1.diff(&r2);
866
867 assert!(!diff.boundary_same);
868 assert!(diff.fingerprint_same);
869 assert!(diff.identity_same);
870 assert!(diff.law_same);
871 }
872
873 #[test]
874 fn preflight_sequence_all_lawful() {
875 let reality = multi_step_reality();
876 let events = vec![
877 Event {
878 proposed_field: "after".to_string(),
879 },
880 Event {
881 proposed_field: "done".to_string(),
882 },
883 ];
884
885 let report = reality.preflight_sequence(&events);
886
887 assert_eq!(report.results, vec![true, true]);
888 assert!(report.sequence_lawful);
889 assert_eq!(
890 report.final_state.as_ref().map(|s| s.field.as_str()),
891 Some("done")
892 );
893 assert_eq!(report.transition_count, 2);
894 }
895
896 #[test]
897 fn preflight_sequence_stops_at_first_unlawful() {
898 let reality = multi_step_reality();
899 let events = vec![
900 Event {
901 proposed_field: "after".to_string(),
902 },
903 Event {
904 proposed_field: "after".to_string(),
905 },
906 ];
907
908 let report = reality.preflight_sequence(&events);
909
910 assert_eq!(report.results, vec![true, false]);
911 assert!(!report.sequence_lawful);
912 assert!(report.final_state.is_none());
913 assert_eq!(report.transition_count, 1);
914 }
915
916 #[test]
917 fn preflight_does_not_mutate_original() {
918 let reality = multi_step_reality();
919 let events = vec![
920 Event {
921 proposed_field: "after".to_string(),
922 },
923 Event {
924 proposed_field: "done".to_string(),
925 },
926 ];
927
928 let _ = reality.preflight_sequence(&events);
929
930 assert_eq!(reality.state.field, "before");
931 assert_eq!(reality.memory().transitions.len(), 0);
932 }
933
934 #[test]
935 fn snapshot_matches_current_reality() {
936 let mut reality = multi_step_reality();
937 let event = Event {
938 proposed_field: "after".to_string(),
939 };
940 let _ = perform_movement(&mut reality, event).unwrap();
941
942 let snapshot = reality.snapshot();
943
944 assert_eq!(snapshot.identity, reality.identity);
945 assert_eq!(snapshot.boundary, reality.boundary);
946 assert_eq!(snapshot.law, reality.law);
947 assert_eq!(snapshot.state, reality.state);
948 assert_eq!(snapshot.initial_state, reality.initial_state);
949 assert_eq!(snapshot.birth_boundary, reality.birth_boundary);
950 assert_eq!(snapshot.birth_law, reality.birth_law);
951 assert_eq!(snapshot.memory_hash, reality.memory.current_hash());
952 assert_eq!(snapshot.transition_count, reality.memory.transitions.len());
953 assert_eq!(snapshot.fingerprint, reality.fingerprint());
954 assert_eq!(snapshot.integrity, reality.integrity_report());
955 }
956
957 #[test]
958 fn snapshot_changes_after_movement() {
959 let mut reality = multi_step_reality();
960 let before = reality.snapshot();
961
962 let event = Event {
963 proposed_field: "after".to_string(),
964 };
965 let _ = perform_movement(&mut reality, event).unwrap();
966
967 let after = reality.snapshot();
968
969 assert_ne!(before, after);
970 }
971
972 #[test]
973 fn snapshot_is_readonly_by_clone_equality() {
974 let reality = multi_step_reality();
975 let snapshot1 = reality.snapshot();
976 let snapshot2 = reality.snapshot();
977
978 assert_eq!(snapshot1, snapshot2);
979 }
980
981 #[test]
982 fn snapshot_matches_current_when_no_change() {
983 let mut reality = multi_step_reality();
984 let event = Event {
985 proposed_field: "after".to_string(),
986 };
987 let _ = perform_movement(&mut reality, event).unwrap();
988
989 let snapshot = reality.snapshot();
990 assert!(snapshot.matches_current(&reality));
991 }
992
993 #[test]
994 fn snapshot_does_not_match_after_further_movement() {
995 let mut reality = multi_step_reality();
996 let event = Event {
997 proposed_field: "after".to_string(),
998 };
999 let _ = perform_movement(&mut reality, event).unwrap();
1000
1001 let snapshot = reality.snapshot();
1002
1003 let second_event = Event {
1004 proposed_field: "done".to_string(),
1005 };
1006 let _ = perform_movement(&mut reality, second_event).unwrap();
1007
1008 assert!(!snapshot.matches_current(&reality));
1009 }
1010
1011 #[test]
1012 fn snapshot_diff_against_current_detects_changes() {
1013 let mut reality = multi_step_reality();
1014 let event = Event {
1015 proposed_field: "after".to_string(),
1016 };
1017 let _ = perform_movement(&mut reality, event).unwrap();
1018
1019 let snapshot = reality.snapshot();
1020
1021 let second_event = Event {
1022 proposed_field: "done".to_string(),
1023 };
1024 let _ = perform_movement(&mut reality, second_event).unwrap();
1025
1026 let diff = snapshot.diff_against(&reality);
1027 assert!(!diff.state_same);
1028 assert!(!diff.memory_hash_same);
1029 assert!(!diff.transition_count_same);
1030 assert!(!diff.fingerprint_same);
1031 }
1032}