Skip to main content

archimedes_kernel/
lib.rs

1#![forbid(unsafe_code)]
2//! Archimedes minimal kernel v0
3//! Proves one minimal Archimedean movement without production concerns.
4
5pub 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
23/// Perform one minimal Archimedean movement.
24/// Returns Ok(ProofResult) only if all checks pass.
25/// Returns Err(MovementError) on the first failure encountered.
26pub fn perform_movement(reality: &mut Reality, event: Event) -> Result<ProofResult, MovementError> {
27    // ---- 1. Reality exists ----
28    // (reality is passed by reference)
29
30    // ---- 2. Identity confirmed ----
31    if reality.identity.0.is_empty() {
32        return Err(MovementError::IdentityMissingOrUnstable);
33    }
34
35    // ---- 3. Boundary confirmed ----
36    if reality.boundary.allowed_values.is_empty() {
37        return Err(MovementError::BoundaryMissing);
38    }
39
40    // ---- 4. Law confirmed ----
41    if reality.law.allowed_transitions.is_empty() {
42        return Err(MovementError::LawMissing);
43    }
44
45    // ---- 5. State confirmed ----
46    if reality.state.field.is_empty() {
47        return Err(MovementError::StateMissing);
48    }
49
50    // ---- 6. State is inside Boundary ----
51    if !reality
52        .boundary
53        .allowed_values
54        .contains(&reality.state.field)
55    {
56        return Err(MovementError::StateOutsideBoundary);
57    }
58
59    // ---- Event received ----
60    // event is passed by value.
61
62    // ---- Event must NOT mutate state directly ----
63    // By design, event only carries a proposed field; it cannot mutate reality.
64    let event_directly_mutated_state = false;
65
66    // ---- 7. LawCheck performed ----
67    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    // ---- 8. Transition occurs before LawCheck? No, we do LawCheck first. ----
79    if !law_check.result {
80        return Err(MovementError::TransitionNotGroundedInLawCheck);
81    }
82
83    // ---- 9. Transition recorded ----
84    let after_state = State {
85        field: event.proposed_field.clone(),
86    };
87
88    // Compute tamper-evident hashes for the movement memory.
89    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    // ---- Test hook: simulate hidden mutation (only in test builds) ----
105    #[cfg(test)]
106    if let Some(hook) = reality.test_hook {
107        hook(reality);
108    }
109
110    // ---- 10. Inspection available ----
111    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    // ---- 11. Replay ----
121    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    // ---- 12. Continuity ----
131    let continuity_result = replay_result;
132
133    // ---- 13. DriftCheck ----
134    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    // ---- 14. ProofResult ----
156    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    // Final sanity check
181    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
208/// Perform multiple sequential lawful movements.
209/// Stops at first error and returns the error.
210pub 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        // Simulate hidden mutation by directly changing state (only possible in test code)
426        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        // Tamper with a past transition's recorded after state
468        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        // Simulate hidden mutation between movements by directly changing boundary
484        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        // Mutate boundary after movement
521        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()); // end out of bounds
563    }
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        // Tamper with a transition inside the composition segment
582        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        // Original unchanged
604        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        // Original unchanged
623        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        // Simulate hidden boundary growth after movement
708        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        // Memory integrity still true because boundary drift does not affect hash chain
715        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        // Original unchanged
769        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        // Directly mutate boundary inside test code
863        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}