1use chrono::{DateTime, Utc};
12use serde::{Deserialize, Serialize};
13
14use crate::TemporalId;
15
16#[derive(Debug, Clone, Serialize, Deserialize)]
22pub struct BranchPoint {
23 pub id: TemporalId,
25 pub decided_at: DateTime<Utc>,
27 pub decision: String,
29 pub alternatives: Vec<Alternative>,
31 pub context_snapshot: serde_json::Value,
33 pub actual_outcome: Option<String>,
35}
36
37#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct Alternative {
40 pub label: String,
42 pub description: String,
44 pub was_chosen: bool,
46}
47
48#[derive(Debug, Clone, Serialize, Deserialize)]
50pub struct TimelineFork {
51 pub id: TemporalId,
53 pub branch_point: TemporalId,
55 pub alternative_index: usize,
57 pub simulated_events: Vec<SimulatedEvent>,
59 pub projected_outcome: String,
61 pub confidence: f64,
63}
64
65#[derive(Debug, Clone, Serialize, Deserialize)]
67pub struct SimulatedEvent {
68 pub timestamp: DateTime<Utc>,
70 pub description: String,
72 pub impact: f64,
74}
75
76#[derive(Debug, Clone, Serialize, Deserialize)]
80pub struct TemporalClone {
81 pub id: TemporalId,
83 pub parent: TemporalId,
85 pub hypothesis: String,
87 pub status: CloneStatus,
89 pub findings: Vec<Finding>,
91 pub exploration_time_secs: i64,
93 pub created_at: DateTime<Utc>,
95 pub completed_at: Option<DateTime<Utc>>,
97}
98
99#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
101pub enum CloneStatus {
102 Exploring,
104 FoundSolution,
106 RuledOut,
108 Merged,
110 Abandoned,
112}
113
114#[derive(Debug, Clone, Serialize, Deserialize)]
116pub struct Finding {
117 pub description: String,
119 pub confidence: f64,
121 pub evidence: String,
123}
124
125#[derive(Debug, Clone, Serialize, Deserialize)]
127pub struct CloneRace {
128 pub id: TemporalId,
130 pub clones: Vec<TemporalId>,
132 pub winner: Option<TemporalId>,
134 pub started_at: DateTime<Utc>,
136}
137
138#[derive(Debug, Clone, Serialize, Deserialize)]
142pub struct TemporalEcho {
143 pub id: TemporalId,
145 pub source_change: String,
147 pub ripples: Vec<Ripple>,
149 pub impact_summary: String,
151}
152
153#[derive(Debug, Clone, Serialize, Deserialize)]
155pub struct Ripple {
156 pub time_horizon: TimeHorizon,
158 pub affected_items: Vec<AffectedItem>,
160 pub severity: f64,
162 pub reversible: bool,
164}
165
166#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
168pub enum TimeHorizon {
169 Immediate,
171 ShortTerm,
173 MediumTerm,
175 LongTerm,
177 Extended,
179}
180
181#[derive(Debug, Clone, Serialize, Deserialize)]
183pub struct AffectedItem {
184 pub entity_id: TemporalId,
186 pub description: String,
188 pub impact: f64,
190}
191
192#[derive(Debug, Clone, Serialize, Deserialize)]
198pub struct DeadlineProphecy {
199 pub id: TemporalId,
201 pub deadline_id: TemporalId,
203 pub success_probability: f64,
205 pub factors: Vec<ProphecyFactor>,
207 pub interventions: Vec<Intervention>,
209 pub prophesied_at: DateTime<Utc>,
211 pub historical_accuracy: f64,
213}
214
215#[derive(Debug, Clone, Serialize, Deserialize)]
217pub struct ProphecyFactor {
218 pub name: String,
220 pub impact: f64,
222 pub confidence: f64,
224 pub evidence: String,
226}
227
228#[derive(Debug, Clone, Serialize, Deserialize)]
230pub struct Intervention {
231 pub action: String,
233 pub success_probability_after: f64,
235 pub cost: String,
237 pub recommended: bool,
239}
240
241#[derive(Debug, Clone, Serialize, Deserialize)]
245pub struct CausalExcavation {
246 pub id: TemporalId,
248 pub problem: String,
250 pub root_cause: CausalEvent,
252 pub causal_chain: Vec<CausalEvent>,
254 pub inflection_points: Vec<InflectionPoint>,
256 pub patterns: Vec<CausalPattern>,
258}
259
260#[derive(Debug, Clone, Serialize, Deserialize)]
262pub struct CausalEvent {
263 pub timestamp: DateTime<Utc>,
265 pub description: String,
267 pub event_type: CausalEventType,
269 pub led_to: Vec<String>,
271}
272
273#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
275pub enum CausalEventType {
276 Decision,
278 ExternalEvent,
280 Inaction,
282 Miscommunication,
284 TechnicalFailure,
286}
287
288#[derive(Debug, Clone, Serialize, Deserialize)]
290pub struct InflectionPoint {
291 pub event: CausalEvent,
293 pub alternative_action: String,
295 pub estimated_impact: String,
297}
298
299#[derive(Debug, Clone, Serialize, Deserialize)]
301pub struct CausalPattern {
302 pub description: String,
304 pub occurrences: u32,
306 pub severity: f64,
308}
309
310#[derive(Debug, Clone, Serialize, Deserialize)]
314pub struct FutureMemory {
315 pub id: TemporalId,
317 pub event_id: TemporalId,
319 pub event_time: DateTime<Utc>,
321 pub context_items: Vec<ContextItem>,
323 pub precomputed: Vec<PrecomputedData>,
325 pub suggested_focus: Vec<String>,
327 pub created_at: DateTime<Utc>,
329}
330
331#[derive(Debug, Clone, Serialize, Deserialize)]
333pub struct ContextItem {
334 pub label: String,
336 pub content_type: ContextType,
338 pub content: String,
340 pub relevance: f64,
342}
343
344#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
346pub enum ContextType {
347 Document,
349 PreviousMeeting,
351 RelatedTask,
353 PersonInfo,
355 Metric,
357}
358
359#[derive(Debug, Clone, Serialize, Deserialize)]
361pub struct PrecomputedData {
362 pub label: String,
364 pub data: serde_json::Value,
366}
367
368#[derive(Debug, Clone, Serialize, Deserialize)]
374pub struct TemporalDebt {
375 pub id: TemporalId,
377 pub description: String,
379 pub principal_minutes: u32,
381 pub interest_rate: f64,
383 pub compound_period_secs: i64,
385 pub incurred_at: DateTime<Utc>,
387 pub current_total_minutes: u32,
389 pub blocking: Vec<String>,
391 pub category: DebtCategory,
393 pub paid_at: Option<DateTime<Utc>>,
395}
396
397#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
399pub enum DebtCategory {
400 Testing,
402 Documentation,
404 Refactoring,
406 Security,
408 Performance,
410}
411
412#[derive(Debug, Clone, Serialize, Deserialize)]
414pub struct DebtReport {
415 pub total_debt_minutes: u32,
417 pub items: Vec<TemporalDebt>,
419 pub interest_per_week_minutes: u32,
421 pub recommendations: Vec<PayoffRecommendation>,
423}
424
425#[derive(Debug, Clone, Serialize, Deserialize)]
427pub struct PayoffRecommendation {
428 pub debt_id: TemporalId,
430 pub current_cost_minutes: u32,
432 pub future_cost_if_unpaid: u32,
434 pub roi_percentage: f64,
436}
437
438impl TemporalDebt {
439 pub fn new(description: &str, principal_minutes: u32, category: DebtCategory) -> Self {
441 let now = Utc::now();
442 Self {
443 id: TemporalId::new(),
444 description: description.to_string(),
445 principal_minutes,
446 interest_rate: 0.1,
447 compound_period_secs: 7 * 24 * 3600, incurred_at: now,
449 current_total_minutes: principal_minutes,
450 blocking: Vec::new(),
451 category,
452 paid_at: None,
453 }
454 }
455
456 pub fn calculate_current_total(&self) -> u32 {
463 if self.paid_at.is_some() {
464 return self.current_total_minutes;
465 }
466
467 let elapsed_secs = (Utc::now() - self.incurred_at).num_seconds();
468 if elapsed_secs <= 0 || self.compound_period_secs <= 0 {
469 return self.principal_minutes;
470 }
471
472 let periods = elapsed_secs as f64 / self.compound_period_secs as f64;
473 let total = self.principal_minutes as f64 * (1.0 + self.interest_rate).powf(periods);
474 total.round() as u32
475 }
476
477 pub fn pay(&mut self) {
479 self.current_total_minutes = self.calculate_current_total();
480 self.paid_at = Some(Utc::now());
481 }
482}
483
484#[derive(Debug, Clone, Serialize, Deserialize)]
488pub struct ChronoGravity {
489 pub id: TemporalId,
491 pub event_id: TemporalId,
493 pub mass: f64,
495 pub radius_days: u32,
497 pub event_horizon: Option<DateTime<Utc>>,
499 pub attracted_items: Vec<AttractedItem>,
501 pub time_dilation_factor: f64,
503}
504
505#[derive(Debug, Clone, Serialize, Deserialize)]
507pub struct AttractedItem {
508 pub item_id: TemporalId,
510 pub item_type: String,
512 pub pull_strength: f64,
514 pub will_reach_event: bool,
516}
517
518#[derive(Debug, Clone, Serialize, Deserialize)]
520pub struct GravityConflict {
521 pub item_id: TemporalId,
523 pub pulled_by: Vec<TemporalId>,
525 pub resolution_needed: bool,
527 pub suggested_resolution: String,
529}
530
531#[derive(Debug, Clone, Serialize, Deserialize)]
535pub struct TemporalEntanglement {
536 pub id: TemporalId,
538 pub entities: Vec<TemporalId>,
540 pub entanglement_type: EntanglementType,
542 pub active: bool,
544 pub created_at: DateTime<Utc>,
546 pub notify: Vec<String>,
548}
549
550#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
552pub enum EntanglementType {
553 Sync,
555 Sequence {
557 gap_secs: i64,
559 },
560 Mirror,
562 Inverse,
564 FailurePropagation,
566}
567
568#[derive(Debug, Clone, Serialize, Deserialize)]
574pub struct TemporalAnomaly {
575 pub id: TemporalId,
577 pub anomaly_type: AnomalyType,
579 pub severity: f64,
581 pub involved_entities: Vec<TemporalId>,
583 pub description: String,
585 pub resolutions: Vec<Resolution>,
587 pub detected_at: DateTime<Utc>,
589}
590
591#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
593pub enum AnomalyType {
594 DependencyCycle,
596 CapacityOverflow,
598 CausalityViolation,
600 EntanglementConflict,
602 GravityConflict,
604 ImpossibleDeadline,
606}
607
608#[derive(Debug, Clone, Serialize, Deserialize)]
610pub struct Resolution {
611 pub action: String,
613 pub removes_anomaly: bool,
615 pub side_effects: Vec<String>,
617}
618
619#[derive(Debug, Clone, Serialize, Deserialize)]
621pub struct ImmuneStatus {
622 pub anomaly_count: u32,
624 pub anomalies: Vec<TemporalAnomaly>,
626 pub last_scan: DateTime<Utc>,
628 pub health_score: f64,
630}
631
632#[derive(Debug, Clone, Serialize, Deserialize)]
636pub struct DecayReversal {
637 pub id: TemporalId,
639 pub decay_id: TemporalId,
641 pub current_value: f64,
643 pub target_value: f64,
645 pub options: Vec<ReversalOption>,
647 pub recommended: Option<usize>,
649}
650
651#[derive(Debug, Clone, Serialize, Deserialize)]
653pub struct ReversalOption {
654 pub name: String,
656 pub time_required_secs: i64,
658 pub restored_value: f64,
660 pub steps: Vec<String>,
662 pub durability_secs: i64,
664}
665
666#[derive(Debug, Clone, Serialize, Deserialize)]
670pub struct TimeDilationModel {
671 pub id: TemporalId,
673 pub activity_factors: Vec<ActivityDilation>,
675 pub energy_curve: Vec<(u32, f64)>,
677 pub weekly_pattern: Vec<(String, f64)>,
679}
680
681#[derive(Debug, Clone, Serialize, Deserialize)]
683pub struct ActivityDilation {
684 pub activity: String,
686 pub dilation_factor: f64,
688 pub energy_cost: f64,
690 pub optimal_hours: Vec<u32>,
692}
693
694#[derive(Debug, Clone, Serialize, Deserialize)]
696pub struct SubjectiveTimeReport {
697 pub period_start: DateTime<Utc>,
699 pub period_end: DateTime<Utc>,
701 pub clock_hours: f64,
703 pub perceived_productive_hours: f64,
705 pub perceived_wasted_hours: f64,
707 pub total_perceived_hours: f64,
709 pub recommendations: Vec<String>,
711}
712
713#[derive(Debug, Clone, Serialize, Deserialize)]
753pub struct TemporalJump {
754 pub id: TemporalId,
756 pub current_position: DateTime<Utc>,
758 pub origin: DateTime<Utc>,
760 pub known_facts: Vec<KnownFact>,
762 pub unknown_facts: Vec<UnknownFact>,
764 pub jump_history: Vec<JumpPoint>,
766 pub active: bool,
768 pub created_at: DateTime<Utc>,
770}
771
772#[derive(Debug, Clone, Serialize, Deserialize)]
774pub struct KnownFact {
775 pub fact: String,
777 pub source: String,
779 pub confidence_at_time: f64,
781}
782
783#[derive(Debug, Clone, Serialize, Deserialize)]
785pub struct UnknownFact {
786 pub fact: String,
788 pub discovered_at: DateTime<Utc>,
790 pub impact: String,
792 pub missed_signals: Vec<String>,
794}
795
796#[derive(Debug, Clone, Serialize, Deserialize)]
798pub struct JumpPoint {
799 pub timestamp: DateTime<Utc>,
801 pub jumped_at: DateTime<Utc>,
803 pub reason: String,
805}
806
807impl TemporalJump {
808 pub fn new(destination: DateTime<Utc>) -> Self {
810 let now = Utc::now();
811 Self {
812 id: TemporalId::new(),
813 current_position: destination,
814 origin: now,
815 known_facts: Vec::new(),
816 unknown_facts: Vec::new(),
817 jump_history: vec![JumpPoint {
818 timestamp: destination,
819 jumped_at: now,
820 reason: "Initial jump".to_string(),
821 }],
822 active: true,
823 created_at: now,
824 }
825 }
826
827 pub fn return_to_origin(&mut self) {
829 self.active = false;
830 self.jump_history.push(JumpPoint {
831 timestamp: self.origin,
832 jumped_at: Utc::now(),
833 reason: "Return to origin".to_string(),
834 });
835 self.current_position = self.origin;
836 }
837}
838
839#[derive(Debug, Clone, Serialize, Deserialize)]
843pub struct TemporalAnchor {
844 pub id: TemporalId,
846 pub name: String,
848 pub anchored_at: DateTime<Utc>,
850 pub state_snapshot: StateSnapshot,
852 pub reason: String,
854 pub tags: Vec<String>,
856 pub expires_at: Option<DateTime<Utc>>,
858 pub jump_count: u32,
860 pub last_jumped_at: Option<DateTime<Utc>>,
862}
863
864#[derive(Debug, Clone, Serialize, Deserialize)]
866pub struct StateSnapshot {
867 pub codebase_state: Option<String>,
869 pub memory_state: Option<String>,
871 pub active_deadlines: Vec<TemporalId>,
873 pub active_schedules: Vec<TemporalId>,
875 pub active_sequences: Vec<TemporalId>,
877 pub decay_values: Vec<(TemporalId, f64)>,
879 pub mental_model: Option<String>,
881 pub checksum: String,
883}
884
885#[derive(Debug, Clone, Serialize, Deserialize)]
887pub struct AnchorJumpResult {
888 pub anchor_id: TemporalId,
890 pub anchor_name: String,
892 pub anchored_at: DateTime<Utc>,
894 pub future_knowledge: Vec<String>,
896 pub divergence_summary: String,
898}
899
900impl TemporalAnchor {
901 pub fn new(name: impl Into<String>, reason: impl Into<String>) -> Self {
903 Self {
904 id: TemporalId::new(),
905 name: name.into(),
906 anchored_at: Utc::now(),
907 state_snapshot: StateSnapshot {
908 codebase_state: None,
909 memory_state: None,
910 active_deadlines: Vec::new(),
911 active_schedules: Vec::new(),
912 active_sequences: Vec::new(),
913 decay_values: Vec::new(),
914 mental_model: None,
915 checksum: String::new(),
916 },
917 reason: reason.into(),
918 tags: Vec::new(),
919 expires_at: None,
920 jump_count: 0,
921 last_jumped_at: None,
922 }
923 }
924
925 pub fn is_expired(&self) -> bool {
927 self.expires_at.map(|exp| Utc::now() > exp).unwrap_or(false)
928 }
929
930 pub fn record_jump(&mut self) {
932 self.jump_count += 1;
933 self.last_jumped_at = Some(Utc::now());
934 }
935}
936
937#[derive(Debug, Clone, Serialize, Deserialize)]
941pub struct TimeLoop {
942 pub id: TemporalId,
944 pub pattern: LoopPattern,
946 pub iterations: Vec<LoopIteration>,
948 pub total_time_spent_secs: i64,
950 pub active: bool,
952 pub root_cause: Option<RootCauseAnalysis>,
954 pub breaker: Option<LoopBreaker>,
956 pub detected_at: DateTime<Utc>,
958}
959
960#[derive(Debug, Clone, Serialize, Deserialize)]
962pub struct LoopPattern {
963 pub repeating_actions: Vec<String>,
965 pub trigger: String,
967 pub expected_outcome: String,
969 pub actual_outcome: String,
971 pub similarity_score: f64,
973}
974
975#[derive(Debug, Clone, Serialize, Deserialize)]
977pub struct LoopIteration {
978 pub number: u32,
980 pub started_at: DateTime<Utc>,
982 pub ended_at: Option<DateTime<Utc>>,
984 pub action_taken: String,
986 pub result: String,
988 pub duration_secs: i64,
990}
991
992#[derive(Debug, Clone, Serialize, Deserialize)]
994pub struct RootCauseAnalysis {
995 pub root_cause: String,
997 pub why_fix_fails: String,
999 pub evidence: Vec<String>,
1001 pub confidence: f64,
1003}
1004
1005#[derive(Debug, Clone, Serialize, Deserialize)]
1007pub struct LoopBreaker {
1008 pub action: String,
1010 pub rationale: String,
1012 pub estimated_time_secs: i64,
1014 pub expected_outcome: String,
1016 pub confidence: f64,
1018}
1019
1020impl TimeLoop {
1021 pub fn new(pattern: LoopPattern) -> Self {
1023 Self {
1024 id: TemporalId::new(),
1025 pattern,
1026 iterations: Vec::new(),
1027 total_time_spent_secs: 0,
1028 active: true,
1029 root_cause: None,
1030 breaker: None,
1031 detected_at: Utc::now(),
1032 }
1033 }
1034
1035 pub fn add_iteration(&mut self, iteration: LoopIteration) {
1037 self.total_time_spent_secs += iteration.duration_secs;
1038 self.iterations.push(iteration);
1039 }
1040
1041 pub fn iteration_count(&self) -> u32 {
1043 self.iterations.len() as u32
1044 }
1045
1046 pub fn mark_broken(&mut self) {
1048 self.active = false;
1049 }
1050}
1051
1052#[derive(Debug, Clone, Serialize, Deserialize)]
1056pub struct TemporalWormhole {
1057 pub id: TemporalId,
1059 pub endpoint_a: WormholeEndpoint,
1061 pub endpoint_b: WormholeEndpoint,
1063 pub relationship: String,
1065 pub transmitted_insights: Vec<WormholeInsight>,
1067 pub active: bool,
1069 pub created_at: DateTime<Utc>,
1071 pub query_count: u32,
1073}
1074
1075#[derive(Debug, Clone, Serialize, Deserialize)]
1077pub struct WormholeEndpoint {
1078 pub timestamp: DateTime<Utc>,
1080 pub label: String,
1082 pub event_description: String,
1084 pub related_entities: Vec<TemporalId>,
1086 pub context_summary: String,
1088}
1089
1090#[derive(Debug, Clone, Serialize, Deserialize)]
1092pub struct WormholeInsight {
1093 pub direction: InsightDirection,
1095 pub insight: String,
1097 pub transmitted_at: DateTime<Utc>,
1099 pub impact: String,
1101}
1102
1103#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
1105pub enum InsightDirection {
1106 PastToFuture,
1108 FutureToPast,
1110 Bidirectional,
1112}
1113
1114impl TemporalWormhole {
1115 pub fn new(
1117 endpoint_a: WormholeEndpoint,
1118 endpoint_b: WormholeEndpoint,
1119 relationship: impl Into<String>,
1120 ) -> Self {
1121 Self {
1122 id: TemporalId::new(),
1123 endpoint_a,
1124 endpoint_b,
1125 relationship: relationship.into(),
1126 transmitted_insights: Vec::new(),
1127 active: true,
1128 created_at: Utc::now(),
1129 query_count: 0,
1130 }
1131 }
1132
1133 pub fn transmit_insight(
1135 &mut self,
1136 direction: InsightDirection,
1137 insight: String,
1138 impact: String,
1139 ) {
1140 self.transmitted_insights.push(WormholeInsight {
1141 direction,
1142 insight,
1143 transmitted_at: Utc::now(),
1144 impact,
1145 });
1146 }
1147
1148 pub fn record_query(&mut self) {
1150 self.query_count += 1;
1151 }
1152
1153 pub fn close(&mut self) {
1155 self.active = false;
1156 }
1157}
1158
1159#[cfg(test)]
1160mod tests {
1161 use super::*;
1162 use chrono::Duration as ChronoDuration;
1163
1164 #[test]
1165 fn test_temporal_debt_new_defaults() {
1166 let debt = TemporalDebt::new("Write unit tests", 60, DebtCategory::Testing);
1167 assert_eq!(debt.principal_minutes, 60);
1168 assert_eq!(debt.current_total_minutes, 60);
1169 assert!((debt.interest_rate - 0.1).abs() < f64::EPSILON);
1170 assert_eq!(debt.compound_period_secs, 7 * 24 * 3600);
1171 assert!(debt.paid_at.is_none());
1172 assert!(debt.blocking.is_empty());
1173 assert_eq!(debt.category, DebtCategory::Testing);
1174 }
1175
1176 #[test]
1177 fn test_temporal_debt_no_interest_before_first_period() {
1178 let debt = TemporalDebt::new("Fresh debt", 100, DebtCategory::Documentation);
1179 let total = debt.calculate_current_total();
1181 assert_eq!(total, 100);
1182 }
1183
1184 #[test]
1185 fn test_temporal_debt_compound_interest_one_period() {
1186 let mut debt = TemporalDebt::new("Old debt", 100, DebtCategory::Refactoring);
1187 debt.incurred_at = Utc::now() - ChronoDuration::seconds(debt.compound_period_secs);
1189
1190 let total = debt.calculate_current_total();
1191 assert_eq!(total, 110);
1193 }
1194
1195 #[test]
1196 fn test_temporal_debt_compound_interest_two_periods() {
1197 let mut debt = TemporalDebt::new("Older debt", 100, DebtCategory::Security);
1198 debt.incurred_at = Utc::now() - ChronoDuration::seconds(2 * debt.compound_period_secs);
1200
1201 let total = debt.calculate_current_total();
1202 assert_eq!(total, 121);
1204 }
1205
1206 #[test]
1207 fn test_temporal_debt_pay_freezes_total() {
1208 let mut debt = TemporalDebt::new("Pay me", 100, DebtCategory::Performance);
1209 debt.incurred_at = Utc::now() - ChronoDuration::seconds(debt.compound_period_secs);
1211
1212 debt.pay();
1213 assert!(debt.paid_at.is_some());
1214 assert_eq!(debt.current_total_minutes, 110);
1215
1216 let total = debt.calculate_current_total();
1218 assert_eq!(total, 110);
1219 }
1220
1221 #[test]
1222 fn test_temporal_debt_custom_rate() {
1223 let mut debt = TemporalDebt::new("Custom rate", 200, DebtCategory::Testing);
1224 debt.interest_rate = 0.2;
1225 debt.incurred_at = Utc::now() - ChronoDuration::seconds(debt.compound_period_secs);
1226
1227 let total = debt.calculate_current_total();
1228 assert_eq!(total, 240);
1230 }
1231
1232 #[test]
1233 fn test_clone_status_derives() {
1234 let s1 = CloneStatus::Exploring;
1235 let s2 = CloneStatus::Exploring;
1236 assert_eq!(s1, s2);
1237
1238 let s3 = s1;
1240 assert_eq!(s3, CloneStatus::Exploring);
1241 }
1242
1243 #[test]
1244 fn test_entanglement_type_partial_eq() {
1245 let t1 = EntanglementType::Sequence { gap_secs: 3600 };
1246 let t2 = EntanglementType::Sequence { gap_secs: 3600 };
1247 let t3 = EntanglementType::Sync;
1248 assert_eq!(t1, t2);
1249 assert_ne!(t1, t3);
1250 }
1251
1252 #[test]
1253 fn test_anomaly_type_copy() {
1254 let a = AnomalyType::CausalityViolation;
1255 let b = a; assert_eq!(a, b);
1257 }
1258
1259 #[test]
1260 fn test_debt_category_copy() {
1261 let c = DebtCategory::Security;
1262 let d = c; assert_eq!(c, d);
1264 }
1265
1266 #[test]
1269 fn test_temporal_jump_create_and_return() {
1270 let destination = Utc::now() - ChronoDuration::hours(24);
1271 let mut jump = TemporalJump::new(destination);
1272 assert!(jump.active);
1273 assert_eq!(jump.jump_history.len(), 1);
1274
1275 jump.return_to_origin();
1276 assert!(!jump.active);
1277 assert_eq!(jump.jump_history.len(), 2);
1278 assert_eq!(jump.current_position, jump.origin);
1279 }
1280
1281 #[test]
1282 fn test_temporal_anchor_create_and_expire() {
1283 let anchor = TemporalAnchor::new("pre-refactor", "Safety save before risky change");
1284 assert_eq!(anchor.name, "pre-refactor");
1285 assert_eq!(anchor.jump_count, 0);
1286 assert!(!anchor.is_expired());
1287 }
1288
1289 #[test]
1290 fn test_temporal_anchor_record_jump() {
1291 let mut anchor = TemporalAnchor::new("checkpoint", "test");
1292 anchor.record_jump();
1293 anchor.record_jump();
1294 assert_eq!(anchor.jump_count, 2);
1295 assert!(anchor.last_jumped_at.is_some());
1296 }
1297
1298 #[test]
1299 fn test_time_loop_add_iterations() {
1300 let pattern = LoopPattern {
1301 repeating_actions: vec!["fix null check".to_string()],
1302 trigger: "null pointer exception".to_string(),
1303 expected_outcome: "bug fixed".to_string(),
1304 actual_outcome: "bug returns".to_string(),
1305 similarity_score: 0.95,
1306 };
1307 let mut loop_det = TimeLoop::new(pattern);
1308 assert_eq!(loop_det.iteration_count(), 0);
1309
1310 loop_det.add_iteration(LoopIteration {
1311 number: 1,
1312 started_at: Utc::now(),
1313 ended_at: Some(Utc::now()),
1314 action_taken: "Added null check".to_string(),
1315 result: "Bug returned after 2 hours".to_string(),
1316 duration_secs: 7200,
1317 });
1318
1319 assert_eq!(loop_det.iteration_count(), 1);
1320 assert_eq!(loop_det.total_time_spent_secs, 7200);
1321
1322 loop_det.mark_broken();
1323 assert!(!loop_det.active);
1324 }
1325
1326 #[test]
1327 fn test_temporal_wormhole_create_and_transmit() {
1328 let ep_a = WormholeEndpoint {
1329 timestamp: Utc::now() - ChronoDuration::days(30),
1330 label: "Architecture decision".to_string(),
1331 event_description: "Chose sync calls".to_string(),
1332 related_entities: vec![],
1333 context_summary: "Early design phase".to_string(),
1334 };
1335 let ep_b = WormholeEndpoint {
1336 timestamp: Utc::now(),
1337 label: "Scaling problems".to_string(),
1338 event_description: "3x cost increase".to_string(),
1339 related_entities: vec![],
1340 context_summary: "Production scaling issues".to_string(),
1341 };
1342 let mut wormhole = TemporalWormhole::new(ep_a, ep_b, "Sync calls causing scale issues");
1343 assert!(wormhole.active);
1344 assert_eq!(wormhole.transmitted_insights.len(), 0);
1345
1346 wormhole.transmit_insight(
1347 InsightDirection::FutureToPast,
1348 "This sync design causes 3x scaling cost".to_string(),
1349 "Would have saved $50k".to_string(),
1350 );
1351 assert_eq!(wormhole.transmitted_insights.len(), 1);
1352
1353 wormhole.record_query();
1354 assert_eq!(wormhole.query_count, 1);
1355
1356 wormhole.close();
1357 assert!(!wormhole.active);
1358 }
1359
1360 #[test]
1361 fn test_insight_direction_copy() {
1362 let d = InsightDirection::PastToFuture;
1363 let e = d; assert_eq!(d, e);
1365 }
1366}