pyroboreplay 2.7.0__tar.gz → 2.8.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (279) hide show
  1. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/Cargo.lock +1 -1
  2. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/Cargo.toml +1 -1
  3. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/PKG-INFO +2 -2
  4. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/pyproject.toml +2 -2
  5. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/lib.rs +1 -0
  6. pyroboreplay-2.8.0/src/phase20/counterfactual_scenarios.rs +299 -0
  7. pyroboreplay-2.8.0/src/phase20/decision_tree.rs +452 -0
  8. pyroboreplay-2.8.0/src/phase20/mod.rs +12 -0
  9. pyroboreplay-2.8.0/src/phase20/rule_extraction.rs +286 -0
  10. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/.env.example +0 -0
  11. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/.gitattributes +0 -0
  12. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/.github/CI_SETUP.md +0 -0
  13. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/.github/workflows/ci.yml +0 -0
  14. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/.github/workflows/docs.yml +0 -0
  15. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/.github/workflows/release.yml +0 -0
  16. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/.github/workflows/security.yml +0 -0
  17. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/.gitignore +0 -0
  18. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/CAUSALITY_DECISION_ENGINE_VISION.md +0 -0
  19. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/CLI_STATS_DASHBOARD_FEATURE.md +0 -0
  20. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/CONTRIBUTING.md +0 -0
  21. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/FINAL_REPORT.txt +0 -0
  22. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/IMPLEMENTATION_SUMMARY.md +0 -0
  23. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/LICENSE +0 -0
  24. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/OTEL_SETUP_GUIDE.md +0 -0
  25. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/PHASE16_CAUSAL_GRAPHS_ROADMAP.md +0 -0
  26. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/PRODUCTION_DEPLOYMENT.md +0 -0
  27. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/README.md +0 -0
  28. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/ROADMAP.md +0 -0
  29. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/SECURITY.md +0 -0
  30. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/STATS_DASHBOARD.md +0 -0
  31. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/STATS_DASHBOARD_QUICKSTART.md +0 -0
  32. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/API.md +0 -0
  33. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/ARCHITECTURE.md +0 -0
  34. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/ARCHITECTURE_COMPLETE.md +0 -0
  35. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/BUILD_SUMMARY.md +0 -0
  36. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/CAMERA_EXPORT.md +0 -0
  37. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/CLAUDE.md +0 -0
  38. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/CODE_OF_CONDUCT.md +0 -0
  39. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/GITHUB_SETTINGS.md +0 -0
  40. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/IMPLEMENTATION_STATUS.md +0 -0
  41. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/IMU_VISUALIZATION.md +0 -0
  42. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/KEYBOARD_SHORTCUTS.md +0 -0
  43. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/LIDAR_VISUALIZATION.md +0 -0
  44. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/MLRIAS_ARCHITECTURE.md +0 -0
  45. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/MLRIAS_PHASES_COMPLETE.md +0 -0
  46. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/PHASE1_COMPLETION_REPORT.md +0 -0
  47. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/PHASE1_IMPLEMENTATION.md +0 -0
  48. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/PHASE2_ADAPTER_STRATEGY.md +0 -0
  49. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/PHASE2_TESTING_COMPLETE.md +0 -0
  50. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/PHASE3_COMPLETE.md +0 -0
  51. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/PHASE3_PHASE4_ROADMAP.md +0 -0
  52. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/PHASE4_COMPLETE.md +0 -0
  53. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/PRODUCT_STRATEGY.md +0 -0
  54. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/PUBLISH.md +0 -0
  55. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/QUICKSTART.md +0 -0
  56. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/RELEASES.md +0 -0
  57. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/RELEASE_v2.0.0.md +0 -0
  58. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/REVISED_ROADMAP_PHASES_5_ONWARDS.md +0 -0
  59. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/ROADMAP.md +0 -0
  60. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/SENSOR_METADATA.md +0 -0
  61. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/TESTING_COMPLETE.md +0 -0
  62. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/TESTING_PLAN.md +0 -0
  63. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/docs/TESTING_STATUS.md +0 -0
  64. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/examples/camera_export_demo.rs +0 -0
  65. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/examples/causal_analysis_demo.rs +0 -0
  66. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/examples/causal_query_engine_demo.rs +0 -0
  67. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/examples/causal_visualization_demo.rs +0 -0
  68. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/examples/compliance_report_demo.rs +0 -0
  69. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/examples/correlation_analysis_demo.rs +0 -0
  70. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/examples/counterfactual_reasoning_demo.rs +0 -0
  71. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/examples/coverage_evolution_demo.rs +0 -0
  72. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/examples/deterministic_replay_demo.rs +0 -0
  73. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/examples/diagnostic_report_demo.rs +0 -0
  74. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/examples/failover_demo.rs +0 -0
  75. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/examples/fleet_monitor_demo.rs +0 -0
  76. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/examples/generate_warehouse_mission.rs +0 -0
  77. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/examples/imu_visualization_demo.rs +0 -0
  78. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/examples/keyboard_shortcuts_demo.rs +0 -0
  79. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/examples/lidar_visualization_demo.rs +0 -0
  80. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/examples/multi_robot_coordination_demo.rs +0 -0
  81. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/examples/phase1_complete_diagnostics.py +0 -0
  82. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/examples/pyterrain_bridge_demo.rs +0 -0
  83. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/examples/recommendation_engine_demo.rs +0 -0
  84. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/examples/root_cause_analysis_demo.rs +0 -0
  85. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/examples/sensor_metadata_demo.rs +0 -0
  86. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/examples/spatial_causality_demo.rs +0 -0
  87. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/examples/sqlite_backend_demo.rs +0 -0
  88. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/examples/stats_dashboard_demo.rs +0 -0
  89. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/examples/storage_backend_demo.rs +0 -0
  90. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/examples/streaming_demo.rs +0 -0
  91. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/examples/test_python_api.py +0 -0
  92. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/otel_exporter.py +0 -0
  93. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/pyroboreplay/_mcp_connector.py +0 -0
  94. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/pyroboreplay/_mcp_tools.py +0 -0
  95. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/pyroboreplay/scripts/__init__.py.bak +0 -0
  96. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/pyroboreplay.toml +0 -0
  97. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/scripts/test_dashboards_crossplatform.sh +0 -0
  98. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/adapters/configuration.rs +0 -0
  99. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/adapters/linux_log.rs +0 -0
  100. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/adapters/metrics.rs +0 -0
  101. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/adapters/mod.rs +0 -0
  102. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/adapters/ros2.rs +0 -0
  103. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/adaptive_recalibration.rs +0 -0
  104. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/aggregation.rs +0 -0
  105. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/coordination/mod.rs +0 -0
  106. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/drift_detection.rs +0 -0
  107. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/environmental/mod.rs +0 -0
  108. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/evidence_quality_scoring.rs +0 -0
  109. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/feedback_loop.rs +0 -0
  110. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/fleet_learning.rs +0 -0
  111. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/gap_narrative_pipeline.rs +0 -0
  112. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/gap_to_causal.rs +0 -0
  113. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/historical.rs +0 -0
  114. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/incident_narrative.rs +0 -0
  115. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/mod.rs +0 -0
  116. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/multi_factor_causality.rs +0 -0
  117. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/phase3_validation.rs +0 -0
  118. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/phase4_integration.rs +0 -0
  119. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/physical/mechanical_degradation.rs +0 -0
  120. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/physical/mod.rs +0 -0
  121. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/physical/structural_dynamics.rs +0 -0
  122. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/physical/thermal_effects.rs +0 -0
  123. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/predictive_gaps.rs +0 -0
  124. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/quality_confidence.rs +0 -0
  125. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/recalibration.rs +0 -0
  126. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/robot_calibration.rs +0 -0
  127. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/scoring.rs +0 -0
  128. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/sensor/detection_robustness.rs +0 -0
  129. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/sensor/mod.rs +0 -0
  130. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/sensor/optical_contamination.rs +0 -0
  131. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/severity.rs +0 -0
  132. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/severity_contracts.rs +0 -0
  133. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/system/clock_drift.rs +0 -0
  134. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/system/mod.rs +0 -0
  135. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/telemetry.rs +0 -0
  136. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/test_data.rs +0 -0
  137. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/analyzers/validation.rs +0 -0
  138. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/cli/args.rs +0 -0
  139. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/cli/camera_export.rs +0 -0
  140. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/cli/causal_viz.rs +0 -0
  141. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/cli/consolidated_output.rs +0 -0
  142. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/cli/gap_analysis.rs +0 -0
  143. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/cli/imu_viz.rs +0 -0
  144. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/cli/json_output.rs +0 -0
  145. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/cli/keyboard.rs +0 -0
  146. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/cli/lidar_viz.rs +0 -0
  147. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/cli/mod.rs +0 -0
  148. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/cli/replay_ui.rs +0 -0
  149. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/cli/sensor_stats.rs +0 -0
  150. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/cli/stats_dashboard.rs +0 -0
  151. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/cli/tests_consolidation_integration.rs +0 -0
  152. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/anomaly_detector.rs +0 -0
  153. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/causality.rs +0 -0
  154. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/compliance.rs +0 -0
  155. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/confidence_scoring.rs +0 -0
  156. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/correlation.rs +0 -0
  157. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/counterfactual.rs +0 -0
  158. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/coverage_evolution.rs +0 -0
  159. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/cross_mission.rs +0 -0
  160. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/deterministic_replay.rs +0 -0
  161. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/diagnostic_report.rs +0 -0
  162. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/event.rs +0 -0
  163. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/evidence_discovery.rs +0 -0
  164. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/explanation.rs +0 -0
  165. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/failure_actions.rs +0 -0
  166. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/failure_detection/localization.rs +0 -0
  167. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/failure_detection/middleware.rs +0 -0
  168. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/failure_detection/mod.rs +0 -0
  169. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/failure_detection/navigation.rs +0 -0
  170. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/failure_detection/perception.rs +0 -0
  171. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/failure_detection/system.rs +0 -0
  172. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/geospatial_export.rs +0 -0
  173. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/incident_analysis.rs +0 -0
  174. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/incident_bundle.rs +0 -0
  175. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/mod.rs +0 -0
  176. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/multi_robot.rs +0 -0
  177. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/pyterrain_bridge.rs +0 -0
  178. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/recommendation.rs +0 -0
  179. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/recommendations_engine.rs +0 -0
  180. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/root_cause.rs +0 -0
  181. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/spatial_causality.rs +0 -0
  182. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/timeline.rs +0 -0
  183. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/core/timeline_correlation.rs +0 -0
  184. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/fusion/forensic_reporter.rs +0 -0
  185. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/fusion/invisible_person_detector.rs +0 -0
  186. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/fusion/mod.rs +0 -0
  187. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/fusion/rgb_thermal_fusion.rs +0 -0
  188. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/fusion/thermal_model.rs +0 -0
  189. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/intelligence/agent_friendly_output.rs +0 -0
  190. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/intelligence/event_extraction.rs +0 -0
  191. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/intelligence/hidden_explanations.rs +0 -0
  192. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/intelligence/mod.rs +0 -0
  193. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/intelligence/perception_gap_analysis.rs +0 -0
  194. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/intelligence/scene_reconstruction.rs +0 -0
  195. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/knowledge/change_detection.rs +0 -0
  196. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/knowledge/fleet_terrain_learning.rs +0 -0
  197. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/knowledge/knowledge_graph.rs +0 -0
  198. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/knowledge/longitudinal_reasoning.rs +0 -0
  199. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/knowledge/mod.rs +0 -0
  200. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/knowledge/multi_mission_learning.rs +0 -0
  201. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/knowledge/spatial_grounding.rs +0 -0
  202. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/knowledge/temporal_analysis.rs +0 -0
  203. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/knowledge/terrain_integration.rs +0 -0
  204. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/knowledge/world_model.rs +0 -0
  205. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/main.rs +0 -0
  206. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/perception/detection_backends.rs +0 -0
  207. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/perception/detection_orchestrator.rs +0 -0
  208. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/perception/gap_context_analyzer.rs +0 -0
  209. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/perception/mod.rs +0 -0
  210. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/perception/object_detection.rs +0 -0
  211. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/perception/object_tracking.rs +0 -0
  212. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/perception/perception_analysis.rs +0 -0
  213. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/perception/retrospective_detection.rs +0 -0
  214. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/perception/scene_understanding.rs +0 -0
  215. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase14/analyzer_capabilities.rs +0 -0
  216. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase14/mod.rs +0 -0
  217. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase14/modality_adapters.rs +0 -0
  218. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase14/navigation_session.rs +0 -0
  219. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase14/temporal_sync.rs +0 -0
  220. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase14/timeline_indexing.rs +0 -0
  221. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase14/video_processing.rs +0 -0
  222. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase15/costmap_analyzer.rs +0 -0
  223. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase15/dynamic_obstacle_analyzer.rs +0 -0
  224. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase15/failure_detector.rs +0 -0
  225. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase15/finding_generator.rs +0 -0
  226. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase15/localization_analyzer.rs +0 -0
  227. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase15/mod.rs +0 -0
  228. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase15/nav2_limitation_detector.rs +0 -0
  229. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase15/planner_analyzer.rs +0 -0
  230. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase15/root_cause_generator.rs +0 -0
  231. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase15/semantic_gap_analyzer.rs +0 -0
  232. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase16/causal_builder.rs +0 -0
  233. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase16/decision_reconstructor.rs +0 -0
  234. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase16/graph_validator.rs +0 -0
  235. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase16/mod.rs +0 -0
  236. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase16/pattern_matcher.rs +0 -0
  237. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase17/alternative_timeline.rs +0 -0
  238. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase17/counterfactual.rs +0 -0
  239. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase17/mod.rs +0 -0
  240. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase17/outcome_influence.rs +0 -0
  241. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase18/decision_clustering.rs +0 -0
  242. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase18/fleet_learning.rs +0 -0
  243. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase18/mod.rs +0 -0
  244. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase18/pattern_discovery.rs +0 -0
  245. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase19/mod.rs +0 -0
  246. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase19/temporal_patterns.rs +0 -0
  247. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase19/trend_detector.rs +0 -0
  248. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/phase19/window_analyzer.rs +0 -0
  249. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/pyroboreplay/__init__.py +0 -0
  250. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/reasoning/explanation_generator.rs +0 -0
  251. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/reasoning/incident_patterns.rs +0 -0
  252. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/reasoning/llm_integration.rs +0 -0
  253. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/reasoning/mod.rs +0 -0
  254. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/reasoning/semantic_search.rs +0 -0
  255. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/storage/audit.rs +0 -0
  256. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/storage/backend.rs +0 -0
  257. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/storage/backends.rs +0 -0
  258. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/storage/failover.rs +0 -0
  259. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/storage/inmemory.rs +0 -0
  260. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/storage/mod.rs +0 -0
  261. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/storage/sqlite.rs +0 -0
  262. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/streaming/channel.rs +0 -0
  263. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/streaming/fleet_monitor.rs +0 -0
  264. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/streaming/kafka_stub.rs +0 -0
  265. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/streaming/live_diagnostics.rs +0 -0
  266. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/streaming/mod.rs +0 -0
  267. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/streaming/processor.rs +0 -0
  268. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/src/streaming/sla.rs +0 -0
  269. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/tests/integration_tests.rs +0 -0
  270. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/tests/test_actions.rs +0 -0
  271. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/tests/test_anomaly_detector.rs +0 -0
  272. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/tests/test_edge_cases.rs +0 -0
  273. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/tests/test_explanation.rs +0 -0
  274. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/tests/test_geospatial_export.rs +0 -0
  275. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/tests/test_mlrias_integration.rs +0 -0
  276. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/tests/test_performance.rs +0 -0
  277. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/tests/test_phase2_patterns.rs +0 -0
  278. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/tests/test_phase2_prediction.rs +0 -0
  279. {pyroboreplay-2.7.0 → pyroboreplay-2.8.0}/tests/test_python_api_integration.rs +0 -0
@@ -1403,7 +1403,7 @@ dependencies = [
1403
1403
 
1404
1404
  [[package]]
1405
1405
  name = "pyroboreplay"
1406
- version = "2.7.0"
1406
+ version = "2.8.0"
1407
1407
  dependencies = [
1408
1408
  "anyhow",
1409
1409
  "byteorder",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "pyroboreplay"
3
- version = "2.7.0"
3
+ version = "2.8.0"
4
4
  edition = "2021"
5
5
  authors = ["Georgi Mammen Mullassery <mullassery@gmail.com>"]
6
6
  license = "Proprietary"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyroboreplay
3
- Version: 2.7.0
3
+ Version: 2.8.0
4
4
  Classifier: Development Status :: 5 - Production/Stable
5
5
  Classifier: Environment :: Console
6
6
  Classifier: Intended Audience :: Developers
@@ -22,7 +22,7 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
22
  Classifier: Topic :: System :: Monitoring
23
23
  Classifier: Topic :: System :: Networking
24
24
  License-File: LICENSE
25
- Summary: AI Navigation Reliability Engineer for autonomous robots. Phase 19: Temporal pattern discovery across time windows (27 tests). Trend detection, anomaly scoring, window analysis.
25
+ Summary: AI Navigation Reliability Engineer for autonomous robots. Phase 20: Causal decision trees & counterfactual analysis (25 tests). Rule extraction, scenario simulation, tree-based interpretability.
26
26
  Keywords: robotics,debugging,mission-replay,root-cause-analysis,ros2,observability,fault-diagnosis,autonomous-systems,fleet-monitoring,sla-enforcement,time-travel-debugging
27
27
  Author-email: Georgi Mammen Mullassery <mullassery@gmail.com>
28
28
  License: Proprietary
@@ -4,8 +4,8 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "pyroboreplay"
7
- version = "2.7.0"
8
- description = "AI Navigation Reliability Engineer for autonomous robots. Phase 19: Temporal pattern discovery across time windows (27 tests). Trend detection, anomaly scoring, window analysis."
7
+ version = "2.8.0"
8
+ description = "AI Navigation Reliability Engineer for autonomous robots. Phase 20: Causal decision trees & counterfactual analysis (25 tests). Rule extraction, scenario simulation, tree-based interpretability."
9
9
  authors = [{name = "Georgi Mammen Mullassery", email = "mullassery@gmail.com"}]
10
10
  license = {text = "Proprietary"}
11
11
  readme = "README.md"
@@ -15,6 +15,7 @@ pub mod phase16;
15
15
  pub mod phase17;
16
16
  pub mod phase18;
17
17
  pub mod phase19;
18
+ pub mod phase20;
18
19
 
19
20
  use pyo3::prelude::*;
20
21
  use core::event::{MissionEvent, MissionRecord};
@@ -0,0 +1,299 @@
1
+ /// Counterfactual Scenario Analysis - What-if analysis with impact prediction
2
+
3
+ use serde::{Deserialize, Serialize};
4
+ use std::collections::HashMap;
5
+
6
+ #[derive(Debug, Clone, Serialize, Deserialize)]
7
+ pub struct CounterfactualScenario {
8
+ pub scenario_id: String,
9
+ pub name: String,
10
+ pub description: String,
11
+ pub modifications: HashMap<String, f32>, // Feature -> hypothetical value
12
+ pub predicted_outcome: String,
13
+ pub confidence: f32,
14
+ pub impact_magnitude: f32, // How much different from baseline?
15
+ pub affected_features: Vec<String>,
16
+ }
17
+
18
+ impl CounterfactualScenario {
19
+ pub fn new(name: String) -> Self {
20
+ CounterfactualScenario {
21
+ scenario_id: format!("scenario_{}", uuid::Uuid::new_v4()),
22
+ name,
23
+ description: String::new(),
24
+ modifications: HashMap::new(),
25
+ predicted_outcome: String::new(),
26
+ confidence: 0.0,
27
+ impact_magnitude: 0.0,
28
+ affected_features: Vec::new(),
29
+ }
30
+ }
31
+
32
+ pub fn impact_score(&self) -> f32 {
33
+ // Impact based on magnitude and confidence
34
+ self.impact_magnitude * self.confidence
35
+ }
36
+ }
37
+
38
+ pub struct ScenarioAnalyzer {
39
+ baseline_features: HashMap<String, f32>,
40
+ scenario_history: Vec<CounterfactualScenario>,
41
+ }
42
+
43
+ impl ScenarioAnalyzer {
44
+ pub fn new(baseline: HashMap<String, f32>) -> Self {
45
+ ScenarioAnalyzer {
46
+ baseline_features: baseline,
47
+ scenario_history: Vec::new(),
48
+ }
49
+ }
50
+
51
+ /// Create a counterfactual scenario by modifying baseline features
52
+ pub fn create_scenario(
53
+ &mut self,
54
+ scenario_name: String,
55
+ modifications: HashMap<String, f32>,
56
+ ) -> CounterfactualScenario {
57
+ let mut scenario = CounterfactualScenario::new(scenario_name);
58
+
59
+ scenario.modifications = modifications.clone();
60
+ scenario.affected_features = modifications.keys().cloned().collect();
61
+
62
+ // Calculate impact magnitude
63
+ let mut total_change = 0.0;
64
+ for (feature, hypothetical_value) in &modifications {
65
+ let baseline_value = self.baseline_features.get(feature).unwrap_or(&0.0);
66
+ let change = (hypothetical_value - baseline_value).abs();
67
+ total_change += change;
68
+ }
69
+
70
+ scenario.impact_magnitude = total_change / scenario.affected_features.len().max(1) as f32;
71
+
72
+ self.scenario_history.push(scenario.clone());
73
+ scenario
74
+ }
75
+
76
+ /// Analyze how features cascade through a causal network
77
+ pub fn analyze_cascade(
78
+ &self,
79
+ scenario: &CounterfactualScenario,
80
+ causal_map: &HashMap<String, Vec<String>>,
81
+ ) -> HashMap<String, f32> {
82
+ let mut cascading_effects: HashMap<String, f32> = HashMap::new();
83
+
84
+ // Start with direct modifications
85
+ for (feature, value) in &scenario.modifications {
86
+ cascading_effects.insert(feature.clone(), *value);
87
+ }
88
+
89
+ // Propagate effects through causal chain
90
+ let mut iterations = 0;
91
+ let max_iterations = 10;
92
+
93
+ while iterations < max_iterations {
94
+ let mut new_effects = cascading_effects.clone();
95
+ let mut changed = false;
96
+
97
+ for (source, targets) in causal_map {
98
+ if let Some(&source_value) = cascading_effects.get(source) {
99
+ for target in targets {
100
+ // Simple propagation: effect attenuates by 0.7x per hop
101
+ let indirect_effect = source_value * 0.7;
102
+
103
+ if !new_effects.contains_key(target)
104
+ || (new_effects.get(target).unwrap_or(&0.0) - indirect_effect).abs() > 0.01
105
+ {
106
+ new_effects.insert(target.clone(), indirect_effect);
107
+ changed = true;
108
+ }
109
+ }
110
+ }
111
+ }
112
+
113
+ cascading_effects = new_effects;
114
+
115
+ if !changed {
116
+ break;
117
+ }
118
+
119
+ iterations += 1;
120
+ }
121
+
122
+ cascading_effects
123
+ }
124
+
125
+ /// Generate multiple scenarios to test robustness
126
+ pub fn generate_sensitivity_analysis(
127
+ &mut self,
128
+ feature: String,
129
+ range: (f32, f32),
130
+ steps: usize,
131
+ ) -> Vec<CounterfactualScenario> {
132
+ let mut scenarios = Vec::new();
133
+ let baseline = self.baseline_features.get(&feature).unwrap_or(&0.0);
134
+
135
+ let step_size = (range.1 - range.0) / (steps as f32 - 1.0);
136
+
137
+ for i in 0..steps {
138
+ let value = range.0 + (i as f32 * step_size);
139
+ let mut modifications = HashMap::new();
140
+ modifications.insert(feature.clone(), value);
141
+
142
+ let scenario_name = format!("{}_sensitivity_{}", feature, i);
143
+ let scenario = self.create_scenario(scenario_name, modifications);
144
+
145
+ scenarios.push(scenario);
146
+ }
147
+
148
+ scenarios
149
+ }
150
+
151
+ /// Compare two scenarios to understand trade-offs
152
+ pub fn compare_scenarios(
153
+ &self,
154
+ scenario_a: &CounterfactualScenario,
155
+ scenario_b: &CounterfactualScenario,
156
+ ) -> HashMap<String, f32> {
157
+ let mut comparison = HashMap::new();
158
+
159
+ // Find common modifications
160
+ for feature in &scenario_a.affected_features {
161
+ let mod_a = scenario_a.modifications.get(feature).unwrap_or(&0.0);
162
+ let mod_b = scenario_b.modifications.get(feature).unwrap_or(&0.0);
163
+
164
+ let diff = (mod_b - mod_a).abs();
165
+ comparison.insert(format!("diff_{}", feature), diff);
166
+ }
167
+
168
+ comparison.insert("impact_diff".to_string(),
169
+ (scenario_b.impact_magnitude - scenario_a.impact_magnitude).abs());
170
+
171
+ comparison
172
+ }
173
+
174
+ /// Get scenario statistics
175
+ pub fn get_statistics(&self) -> HashMap<String, f32> {
176
+ let mut stats = HashMap::new();
177
+
178
+ stats.insert("total_scenarios".to_string(), self.scenario_history.len() as f32);
179
+
180
+ if !self.scenario_history.is_empty() {
181
+ let avg_impact: f32 = self.scenario_history
182
+ .iter()
183
+ .map(|s| s.impact_magnitude)
184
+ .sum::<f32>()
185
+ / self.scenario_history.len() as f32;
186
+
187
+ let avg_confidence: f32 = self.scenario_history
188
+ .iter()
189
+ .map(|s| s.confidence)
190
+ .sum::<f32>()
191
+ / self.scenario_history.len() as f32;
192
+
193
+ stats.insert("avg_impact".to_string(), avg_impact);
194
+ stats.insert("avg_confidence".to_string(), avg_confidence);
195
+ }
196
+
197
+ stats
198
+ }
199
+ }
200
+
201
+ #[cfg(test)]
202
+ mod tests {
203
+ use super::*;
204
+
205
+ #[test]
206
+ fn test_scenario_creation() {
207
+ let scenario = CounterfactualScenario::new("test_scenario".to_string());
208
+ assert_eq!(scenario.name, "test_scenario");
209
+ }
210
+
211
+ #[test]
212
+ fn test_scenario_impact_score() {
213
+ let mut scenario = CounterfactualScenario::new("test".to_string());
214
+ scenario.impact_magnitude = 0.5;
215
+ scenario.confidence = 0.8;
216
+
217
+ assert_eq!(scenario.impact_score(), 0.4);
218
+ }
219
+
220
+ #[test]
221
+ fn test_analyzer_creation() {
222
+ let baseline = HashMap::new();
223
+ let analyzer = ScenarioAnalyzer::new(baseline);
224
+ assert!(analyzer.scenario_history.is_empty());
225
+ }
226
+
227
+ #[test]
228
+ fn test_create_scenario() {
229
+ let baseline = {
230
+ let mut m = HashMap::new();
231
+ m.insert("feature1".to_string(), 0.5);
232
+ m
233
+ };
234
+
235
+ let mut analyzer = ScenarioAnalyzer::new(baseline);
236
+ let mut modifications = HashMap::new();
237
+ modifications.insert("feature1".to_string(), 0.8);
238
+
239
+ let scenario = analyzer.create_scenario("test".to_string(), modifications);
240
+ assert_eq!(scenario.affected_features.len(), 1);
241
+ }
242
+
243
+ #[test]
244
+ fn test_analyze_cascade() {
245
+ let baseline = HashMap::new();
246
+ let analyzer = ScenarioAnalyzer::new(baseline);
247
+
248
+ let mut scenario = CounterfactualScenario::new("test".to_string());
249
+ scenario.modifications.insert("f1".to_string(), 1.0);
250
+
251
+ let mut causal_map = HashMap::new();
252
+ causal_map.insert("f1".to_string(), vec!["f2".to_string()]);
253
+
254
+ let effects = analyzer.analyze_cascade(&scenario, &causal_map);
255
+ assert!(effects.contains_key("f1"));
256
+ }
257
+
258
+ #[test]
259
+ fn test_sensitivity_analysis() {
260
+ let baseline = {
261
+ let mut m = HashMap::new();
262
+ m.insert("feature1".to_string(), 0.5);
263
+ m
264
+ };
265
+
266
+ let mut analyzer = ScenarioAnalyzer::new(baseline);
267
+ let scenarios = analyzer.generate_sensitivity_analysis("feature1".to_string(), (0.0, 1.0), 5);
268
+
269
+ assert_eq!(scenarios.len(), 5);
270
+ }
271
+
272
+ #[test]
273
+ fn test_compare_scenarios() {
274
+ let baseline = HashMap::new();
275
+ let analyzer = ScenarioAnalyzer::new(baseline);
276
+
277
+ let mut s1 = CounterfactualScenario::new("s1".to_string());
278
+ s1.modifications.insert("f1".to_string(), 0.5);
279
+
280
+ let mut s2 = CounterfactualScenario::new("s2".to_string());
281
+ s2.modifications.insert("f1".to_string(), 0.8);
282
+
283
+ let comparison = analyzer.compare_scenarios(&s1, &s2);
284
+ assert!(!comparison.is_empty());
285
+ }
286
+
287
+ #[test]
288
+ fn test_analyzer_statistics() {
289
+ let baseline = HashMap::new();
290
+ let mut analyzer = ScenarioAnalyzer::new(baseline);
291
+
292
+ let mut mods = HashMap::new();
293
+ mods.insert("f1".to_string(), 0.5);
294
+ analyzer.create_scenario("test".to_string(), mods);
295
+
296
+ let stats = analyzer.get_statistics();
297
+ assert_eq!(stats.get("total_scenarios"), Some(&1.0));
298
+ }
299
+ }