petter2025 commited on
Commit
34a2540
·
verified ·
1 Parent(s): d4ad053

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +407 -619
app.py CHANGED
@@ -3,6 +3,7 @@
3
  # Enhanced with clear OSS vs Enterprise boundaries
4
  # UPDATED: Added realism panel integration for enterprise-seasoned SRE experience
5
  # UPDATED: Added dynamic performance metrics for Phase 2
 
6
 
7
  import logging
8
  import sys
@@ -178,7 +179,7 @@ class BoundaryManager:
178
  <strong>Boundary:</strong> Real execution with safety guarantees
179
  </p>
180
  <div style="display: inline-block; padding: 10px 24px; background: #065f46;
181
- border-radius: 20px; font-size=14px; font-weight: bold; color: white;
182
  text-transform: uppercase; letter-spacing: 1px;">
183
  ENTERPRISE+
184
  </div>
@@ -556,267 +557,431 @@ def create_empty_plot(title: str, is_real_arf: bool = True) -> go.Figure:
556
  fig.update_layout(height=300)
557
  return fig
558
 
559
- # Keep the HTML fallback functions for other uses
560
- def create_html_telemetry_fallback(scenario_name: str, is_real_arf: bool) -> str:
561
- """HTML fallback for telemetry visualization (unchanged)"""
562
- severity_colors = {
563
- "Cache Miss Storm": "#f59e0b",
564
- "Database Connection Pool Exhaustion": "#ef4444",
565
- "Kubernetes Memory Leak": "#8b5cf6",
566
- "API Rate Limit Storm": "#ec4899",
567
- "Network Partition": "#14b8a6",
568
- "Storage I/O Saturation": "#84cc16"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
569
  }
570
 
571
- color = severity_colors.get(scenario_name, "#64748b")
572
- boundary_indicator = "🏢 ENTERPRISE" if is_real_arf else "🔓 OSS ONLY"
 
573
 
574
- return f"""
575
- <div style="border: 1px solid {color}; border-radius: 14px; padding: 20px;
576
- background: linear-gradient(135deg, {color}10 0%, #ffffff 100%);
577
- position: relative; overflow: hidden;">
578
-
579
- <!-- Boundary indicator -->
580
- <div style="position: absolute; top: 10px; right: 10px; background: {color};
581
- color: white; padding: 4px 10px; border-radius: 12px; font-size: 11px;
582
- font-weight: bold;">
583
- {boundary_indicator}
584
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
585
 
586
- <div style="display: flex; justify-content: space-between; align-items: flex-start;">
587
- <div>
588
- <h4 style="margin: 0 0 10px 0; font-size: 16px; color: #1e293b; font-weight: 600;">
589
- 📊 Telemetry: {scenario_name}
590
- </h4>
591
- <p style="margin: 0; font-size: 13px; color: #64748b; max-width: 300px;">
592
- Real-time metrics showing anomalous behavior pattern detection.
593
- ARF analyzes 45+ data points per second.
594
- </p>
595
- </div>
596
-
597
- <div style="text-align: right;">
598
- <div style="font-size: 28px; font-weight: 700; color: {color}; margin-bottom: 5px;">
599
- 94%
600
- </div>
601
- <div style="font-size: 12px; color: #64748b;">
602
- Anomaly Confidence
603
- </div>
604
- </div>
605
- </div>
606
 
607
- <!-- Simulated telemetry chart -->
608
- <div style="margin-top: 20px; height: 100px; position: relative;">
609
- <div style="position: absolute; bottom: 0; left: 0; width: 100%; height: 2px;
610
- background: #e2e8f0;"></div>
611
-
612
- <!-- Anomaly region -->
613
- <div style="position: absolute; bottom: 0; left: 60%; width: 30%; height: 80px;
614
- background: linear-gradient(90deg, {color}20, {color}40); border-radius: 6px 6px 0 0;
615
- border: 2px solid {color}; border-bottom: none;">
616
- <div style="position: absolute; top: -25px; left: 50%; transform: translateX(-50%);
617
- background: {color}; color: white; padding: 2px 8px; border-radius: 10px;
618
- font-size: 11px; font-weight: bold; white-space: nowrap;">
619
- ANOMALY
620
- </div>
621
- </div>
622
-
623
- <!-- Data points -->
624
- <div style="position: absolute; bottom: 0; left: 0; width: 60%; height: 40px;
625
- background: linear-gradient(90deg, #10b98120, #10b98140); border-radius: 6px 0 0 0;">
626
- </div>
627
- </div>
628
 
629
- <!-- Metrics row -->
630
- <div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 15px; margin-top: 20px;">
631
- <div style="text-align: center;">
632
- <div style="font-size: 14px; font-weight: 600; color: {color};">45s</div>
633
- <div style="font-size: 11px; color: #64748b;">Detection Time</div>
634
- </div>
635
- <div style="text-align: center;">
636
- <div style="font-size: 14px; font-weight: 600; color: {color};">12/min</div>
637
- <div style="font-size: 11px; color: #64748b;">Data Points</div>
638
- </div>
639
- <div style="text-align: center;">
640
- <div style="font-size: 14px; font-weight: 600; color: {color};">3</div>
641
- <div style="font-size: 11px; color: #64748b;">Similar Patterns</div>
642
- </div>
643
- </div>
644
 
645
- <!-- Boundary note -->
646
- <div style="margin-top: 15px; padding: 10px; background: #f8fafc; border-radius: 8px;
647
- border-left: 3px solid {color}; font-size: 12px; color: #475569;">
648
- <strong>Boundary:</strong> This visualization shows {'real' if is_real_arf else 'simulated'}
649
- telemetry analysis. {'Enterprise' if is_real_arf else 'OSS'} edition provides enhanced
650
- anomaly detection.
651
- </div>
652
- </div>
653
- """
654
-
655
- def create_html_impact_fallback(scenario_name: str, is_real_arf: bool) -> str:
656
- """HTML fallback for impact visualization (unchanged)"""
657
- impact_values = {
658
- "Cache Miss Storm": 8500,
659
- "Database Connection Pool Exhaustion": 4200,
660
- "Kubernetes Memory Leak": 5500,
661
- "API Rate Limit Storm": 3800,
662
- "Network Partition": 12000,
663
- "Storage I/O Saturation": 6800
664
- }
665
-
666
- impact = impact_values.get(scenario_name, 5000)
667
- savings = int(impact * 0.85)
668
- boundary_text = "Enterprise Autonomous" if is_real_arf else "OSS Advisory"
669
- boundary_color = "#8b5cf6" if is_real_arf else "#10b981"
670
-
671
- return f"""
672
- <div style="border: 1px solid {boundary_color}; border-radius: 14px; padding: 20px;
673
- background: linear-gradient(135deg, {boundary_color}10 0%, #ffffff 100%);">
 
 
 
 
 
674
 
675
- <div style="display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 20px;">
676
- <div>
677
- <h4 style="margin: 0 0 8px 0; font-size: 16px; color: #1e293b; font-weight: 600;">
678
- 💰 Business Impact Analysis
679
- </h4>
680
- <div style="display: inline-block; padding: 4px 10px; background: {boundary_color};
681
- color: white; border-radius: 12px; font-size: 11px; font-weight: bold;">
682
- {boundary_text}
683
- </div>
684
- </div>
685
-
686
- <div style="text-align: right;">
687
- <div style="font-size: 24px; font-weight: 700; color: {boundary_color};">
688
- ${impact:,}
 
689
  </div>
690
- <div style="font-size: 12px; color: #64748b;">
691
- Revenue Loss/Hour
 
 
692
  </div>
693
  </div>
694
  </div>
 
695
 
696
- <!-- Gauge visualization -->
697
- <div style="position: relative; height: 80px; margin: 20px 0;">
698
- <!-- Gauge background -->
699
- <div style="position: absolute; top: 0; left: 0; width: 100%; height: 40px;
700
- background: #f1f5f9; border-radius: 20px; overflow: hidden;">
701
-
702
- <!-- Impact fill -->
703
- <div style="position: absolute; top: 0; left: 0; width: 85%; height: 100%;
704
- background: linear-gradient(90deg, {boundary_color}, {boundary_color}aa);">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
705
  </div>
706
-
707
- <!-- Savings indicator -->
708
- <div style="position: absolute; top: 0; left: 85%; width: 2px; height: 100%;
709
- background: #10b981; z-index: 2;"></div>
710
- </div>
711
-
712
- <!-- Labels -->
713
- <div style="position: absolute; top: 50px; left: 0; font-size: 12px; color: #64748b;">
714
- $0
715
- </div>
716
- <div style="position: absolute; top: 50px; left: 50%; transform: translateX(-50%);
717
- font-size: 12px; color: #64748b;">
718
- ${impact//2:,}
719
- </div>
720
- <div style="position: absolute; top: 50px; right: 0; font-size: 12px; color: #64748b;">
721
- ${impact:,}
722
- </div>
723
-
724
- <!-- Savings marker -->
725
- <div style="position: absolute; top: -25px; left: 85%; transform: translateX(-50%);
726
- text-align: center;">
727
- <div style="width: 0; height: 0; border-left: 6px solid transparent;
728
- border-right: 6px solid transparent; border-top: 10px solid #10b981;
729
- margin: 0 auto 5px auto;"></div>
730
- <div style="font-size: 11px; color: #10b981; font-weight: bold; white-space: nowrap;">
731
- ${savings:,} SAVED
732
  </div>
733
  </div>
734
  </div>
 
735
 
736
- <!-- Impact breakdown -->
737
- <div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 15px; margin-top: 25px;">
738
- <div style="padding: 12px; background: #f8fafc; border-radius: 8px;">
739
- <div style="font-size: 13px; color: #64748b; margin-bottom: 5px;">Without ARF</div>
740
- <div style="font-size: 16px; font-weight: 700; color: #ef4444;">45 min</div>
741
- <div style="font-size: 11px; color: #94a3b8;">Mean time to resolve</div>
742
- </div>
743
-
744
- <div style="padding: 12px; background: #f8fafc; border-radius=8px;">
745
- <div style="font-size: 13px; color: #64748b; margin-bottom: 5px;">With ARF</div>
746
- <div style="font-size: 16px; font-weight: 700; color: #10b981;">12 min</div>
747
- <div style="font-size: 11px; color: #94a3b8;">Autonomous recovery</div>
748
- </div>
749
- </div>
750
 
751
- <!-- ROI indicator -->
752
- <div style="margin-top: 20px; padding: 12px; background: #f0fdf4; border-radius: 8px;
753
- border: 1px solid #d1fae5; display: flex; align-items: center; gap: 12px;">
754
- <div style="font-size: 24px; color: #10b981;">📈</div>
755
- <div>
756
- <div style="font-size: 14px; font-weight: 600; color: #065f46;">
757
- Potential ROI: 5.2×
 
 
 
 
 
 
 
 
758
  </div>
759
- <div style="font-size: 12px; color: #059669;">
760
- ARF saves 85% of potential revenue loss through autonomous recovery
 
 
761
  </div>
762
  </div>
763
  </div>
 
764
 
765
- <!-- Boundary context -->
766
- <div style="margin-top: 15px; padding-top: 15px; border-top: 1px dashed #e2e8f0;
767
- font-size: 12px; color: #64748b; line-height: 1.5;">
768
- <strong>Boundary Context:</strong> {'Enterprise' if is_real_arf else 'OSS'} analysis shows
769
- {'real' if is_real_arf else 'simulated'} impact metrics.
770
- {'Commercial license enables autonomous execution.' if is_real_arf else 'Upgrade to Enterprise for autonomous recovery.'}
771
- </div>
772
- </div>
773
- """
774
-
775
- def get_inactive_agent_html(agent_name: str, description: str, is_real_arf: bool = False):
776
- """Get HTML for inactive agent state with boundary indicators (unchanged)"""
777
- boundary_color = "#8b5cf6" if is_real_arf else "#10b981"
778
- status_color = "#64748b"
779
-
780
- return f"""
781
- <div style="border: 1px solid {status_color}40; border-radius: 12px; padding: 20px;
782
- background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
783
- position: relative; min-height: 120px;">
784
-
785
- <!-- Status indicator -->
786
- <div style="position: absolute; top: 15px; right: 15px; width: 12px; height: 12px;
787
- background: {status_color}60; border-radius: 50%;"></div>
788
-
789
- <!-- Agent header -->
790
- <div style="display: flex; align-items: center; gap: 12px; margin-bottom: 15px;">
791
- <div style="width: 40px; height: 40px; background: {status_color}20; border-radius: 10px;
792
- display: flex; align-items: center; justify-content: center; font-size: 18px; color: {status_color};">
793
- 🤖
794
- </div>
795
- <div>
796
- <h4 style="margin: 0 0 4px 0; font-size: 16px; color: #475569; font-weight: 600;">
797
- {agent_name}
798
- </h4>
799
- <div style="display: inline-block; padding: 3px 8px; background: {status_color}20;
800
- color: {status_color}; border-radius: 10px; font-size: 11px; font-weight: bold;">
801
- INACTIVE
802
  </div>
803
  </div>
804
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
805
 
806
- <!-- Agent description -->
807
- <p style="margin: 0; font-size: 13px; color: #64748b; line-height: 1.5;">
808
- {description}
809
- </p>
810
 
811
- <!-- Boundary note -->
812
- <div style="margin-top: 15px; padding-top: 15px; border-top: 1px dashed #e2e8f0;">
813
- <div style="font-size: 11px; color: #94a3b8; display: flex; align-items: center; gap: 6px;">
814
- <span style="display: inline-block; width: 8px; height: 8px; background: {boundary_color}; border-radius: 50%;"></span>
815
- Requires { 'Enterprise' if is_real_arf else 'OSS' } activation
816
- </div>
817
- </div>
818
- </div>
819
- """
820
 
821
  # ===========================================
822
  # IMPORT MODULAR COMPONENTS - FIXED: Added MockEnhancedROICalculator
@@ -1439,7 +1604,7 @@ class AuditTrailManager:
1439
  <td style="padding: 12px; font-size: 13px; color: #1e293b;">
1440
  {status} {exec["scenario"]}
1441
  </td>
1442
- <td style="padding: 12px; font-size: 13px; color: #64748b;">
1443
  {exec["mode"]}
1444
  </td>
1445
  <td style="padding: 12px; font-size: 13px;">
@@ -1715,211 +1880,6 @@ def update_scenario_display_with_metrics(scenario_name: str) -> tuple:
1715
  return (scenario_card, telemetry_fig, impact_fig, timeline_fig, realism_html,
1716
  detection_time_html, mttr_html, auto_heal_html, savings_html)
1717
 
1718
- # ===========================================
1719
- # SURGICAL FIX: run_true_arf_analysis() - FIXED to return DataFrames
1720
- # ===========================================
1721
- @AsyncRunner.async_to_sync
1722
- async def run_true_arf_analysis(scenario_name: str) -> tuple:
1723
- """
1724
- FIXED: Returns exactly 5 values as expected by UI:
1725
- 1. detection_html (HTML string)
1726
- 2. recall_html (HTML string)
1727
- 3. decision_html (HTML string)
1728
- 4. oss_results_dict (Python dict for JSON display)
1729
- 5. incident_df (DataFrame for Gradio DataFrame component)
1730
- """
1731
-
1732
- components = get_components()
1733
- installation = get_installation_status()
1734
- boundaries = BoundaryManager.get_system_boundaries()
1735
-
1736
- logger.info(f"🔍 Running True ARF analysis for: {scenario_name}")
1737
-
1738
- try:
1739
- # Get orchestrator
1740
- orchestrator = components["DemoOrchestrator"]()
1741
-
1742
- # Get scenario data
1743
- scenarios = components["INCIDENT_SCENARIOS"]
1744
- scenario_data = scenarios.get(scenario_name, {})
1745
-
1746
- # Run analysis
1747
- analysis_result = await orchestrator.analyze_incident(scenario_name, scenario_data)
1748
-
1749
- # Add to audit trail
1750
- get_audit_manager().add_incident(scenario_name, analysis_result)
1751
-
1752
- # Check if we have real ARF
1753
- is_real_arf = installation["oss_installed"] or settings.use_true_arf
1754
-
1755
- # Create HTML for active agents
1756
- boundary_color = boundaries["oss"]["color"] if is_real_arf else "#f59e0b"
1757
- boundary_text = boundaries["oss"]["label"] if is_real_arf else "Mock ARF"
1758
-
1759
- # Detection Agent HTML
1760
- detection_html = f"""
1761
- <div style="border: 2px solid {boundary_color}; border-radius: 14px; padding: 18px;
1762
- background: linear-gradient(135deg, {boundary_color}10 0%, #ffffff 100%);
1763
- text-align: center; flex: 1; margin: 5px; min-height: 180px;">
1764
- <div style="font-size: 32px; margin-bottom: 10px; color: {boundary_color};">🕵️‍♂️</div>
1765
- <div style="width: 100%;">
1766
- <h4 style="margin: 0 0 8px 0; font-size: 16px; color: #1e293b;">Detection Agent</h4>
1767
- <p style="font-size: 13px; color: #64748b; margin-bottom: 12px; line-height: 1.4;">
1768
- Anomaly detected with 94% confidence
1769
- </p>
1770
- <div style="display: flex; justify-content: space-around; margin-bottom: 12px;">
1771
- <span style="font-size: 11px; padding: 3px 8px; background: {boundary_color}20;
1772
- border-radius: 6px; color: {boundary_color}; font-weight: 500;">
1773
- Status: Active
1774
- </span>
1775
- </div>
1776
- <div style="display: inline-block; padding: 5px 14px; background: {boundary_color};
1777
- border-radius: 20px; font-size: 12px; font-weight: bold; color: white;
1778
- text-transform: uppercase; letter-spacing: 0.5px;">
1779
- DETECTED
1780
- </div>
1781
- </div>
1782
- </div>
1783
- """
1784
-
1785
- # Recall Agent HTML
1786
- recall_html = f"""
1787
- <div style="border: 2px solid {boundary_color}; border-radius: 14px; padding: 18px;
1788
- background: linear-gradient(135deg, {boundary_color}10 0%, #ffffff 100%);
1789
- text-align: center; flex: 1; margin: 5px; min-height: 180px;">
1790
- <div style="font-size: 32px; margin-bottom: 10px; color: {boundary_color};">🧠</div>
1791
- <div style="width: 100%;">
1792
- <h4 style="margin: 0 0 8px 0; font-size: 16px; color: #1e293b;">Recall Agent</h4>
1793
- <p style="font-size: 13px; color: #64748b; margin-bottom: 12px; line-height: 1.4;">
1794
- 3 similar incidents found in RAG memory
1795
- </p>
1796
- <div style="display: flex; justify-content: space-around; margin-bottom: 12px;">
1797
- <span style="font-size: 11px; padding: 3px 8px; background: {boundary_color}20;
1798
- border-radius: 6px; color: {boundary_color}; font-weight: 500;">
1799
- Status: Active
1800
- </span>
1801
- </div>
1802
- <div style="display: inline-block; padding: 5px 14px; background: {boundary_color};
1803
- border-radius: 20px; font-size: 12px; font-weight: bold; color: white;
1804
- text-transform: uppercase; letter-spacing: 0.5px;">
1805
- RECALLED
1806
- </div>
1807
- </div>
1808
- </div>
1809
- """
1810
-
1811
- # Decision Agent HTML
1812
- decision_html = f"""
1813
- <div style="border: 2px solid {boundary_color}; border-radius: 14px; padding: 18px;
1814
- background: linear-gradient(135deg, {boundary_color}10 0%, #ffffff 100%);
1815
- text-align: center; flex: 1; margin: 5px; min-height: 180px;">
1816
- <div style="font-size: 32px; margin-bottom: 10px; color: {boundary_color};">🎯</div>
1817
- <div style="width: 100%;">
1818
- <h4 style="margin: 0 0 8px 0; font-size: 16px; color: #1e293b;">Decision Agent</h4>
1819
- <p style="font-size: 13px; color: #64748b; margin-bottom: 12px; line-height: 1.4;">
1820
- HealingIntent created: Scale Redis cluster
1821
- </p>
1822
- <div style="display: flex; justify-content: space-around; margin-bottom: 12px;">
1823
- <span style="font-size: 11px; padding: 3px 8px; background: {boundary_color}20;
1824
- border-radius: 6px; color: {boundary_color}; font-weight: 500;">
1825
- Status: Active
1826
- </span>
1827
- </div>
1828
- <div style="display: inline-block; padding: 5px 14px; background: {boundary_color};
1829
- border-radius: 20px; font-size: 12px; font-weight: bold; color: white;
1830
- text-transform: uppercase; letter-spacing: 0.5px;">
1831
- DECIDED
1832
- </div>
1833
- </div>
1834
- </div>
1835
- """
1836
-
1837
- # OSS Results Dict for JSON display
1838
- if is_real_arf and "real" in str(analysis_result).lower():
1839
- oss_results_dict = {
1840
- "status": "success",
1841
- "scenario": scenario_name,
1842
- "arf_version": "3.3.9",
1843
- "analysis": {
1844
- "detected": True,
1845
- "confidence": 94,
1846
- "similar_incidents": 3,
1847
- "healing_intent_created": True,
1848
- "recommended_action": "Scale Redis cluster from 3 to 5 nodes",
1849
- "estimated_recovery": "12 minutes"
1850
- },
1851
- "agents": {
1852
- "detection": {"status": "active", "confidence": 94},
1853
- "recall": {"status": "active", "similar_incidents": 3},
1854
- "decision": {"status": "active", "healing_intent_created": True}
1855
- },
1856
- "boundary_note": f"OSS analysis complete → Ready for Enterprise execution"
1857
- }
1858
- else:
1859
- oss_results_dict = {
1860
- "status": "mock_analysis",
1861
- "scenario": scenario_name,
1862
- "arf_version": "mock",
1863
- "analysis": {
1864
- "detected": True,
1865
- "confidence": 94,
1866
- "similar_incidents": 3,
1867
- "healing_intent_created": True,
1868
- "recommended_action": "Scale Redis cluster from 3 to 5 nodes",
1869
- "estimated_recovery": "12 minutes"
1870
- },
1871
- "agents": {
1872
- "detection": {"status": "active", "confidence": 94},
1873
- "recall": {"status": "active", "similar_incidents": 3},
1874
- "decision": {"status": "active", "healing_intent_created": True}
1875
- },
1876
- "boundary_note": f"Mock analysis - {boundary_text}"
1877
- }
1878
-
1879
- # Incident DataFrame (FIXED: Returns DataFrame instead of HTML)
1880
- incident_df = get_audit_manager().get_incident_dataframe()
1881
-
1882
- return detection_html, recall_html, decision_html, oss_results_dict, incident_df
1883
-
1884
- except Exception as e:
1885
- logger.error(f"True ARF analysis failed: {e}")
1886
-
1887
- # Return error state with proper types
1888
- error_html = f"""
1889
- <div style="border: 2px solid #ef4444; border-radius: 14px; padding: 18px;
1890
- background: linear-gradient(135deg, #fef2f2 0%, #ffffff 100%);
1891
- text-align: center; flex: 1; margin: 5px; min-height: 180px;">
1892
- <div style="font-size: 32px; margin-bottom: 10px; color: #ef4444;">❌</div>
1893
- <div style="width: 100%;">
1894
- <h4 style="margin: 0 0 8px 0; font-size: 16px; color: #1e293b;">Analysis Error</h4>
1895
- <p style="font-size: 13px; color: #64748b; margin-bottom: 12px; line-height: 1.4;">
1896
- Failed to analyze incident
1897
- </p>
1898
- <div style="display: flex; justify-content: space-around; margin-bottom: 12px;">
1899
- <span style="font-size: 11px; padding: 3px 8px; background: #ef4444;
1900
- border-radius: 6px; color: white; font-weight: 500;">
1901
- Status: Error
1902
- </span>
1903
- </div>
1904
- </div>
1905
- </div>
1906
- """
1907
-
1908
- error_dict = {
1909
- "status": "error",
1910
- "error": str(e),
1911
- "scenario": scenario_name,
1912
- "arf_version": "3.3.9",
1913
- "recommendation": "Check ARF installation"
1914
- }
1915
-
1916
- # Return empty DataFrame on error
1917
- error_df = pd.DataFrame(columns=["Error", "Message"]).from_records([
1918
- {"Error": "Analysis Failed", "Message": str(e)}
1919
- ])
1920
-
1921
- return error_html, error_html, error_html, error_dict, error_df
1922
-
1923
  # ===========================================
1924
  # FIXED EXECUTION FUNCTION - Returns DataFrames
1925
  # ===========================================
@@ -2195,192 +2155,20 @@ def create_demo_interface():
2195
  )
2196
 
2197
  # ===========================================
2198
- # FIXED: OSS Analysis Button Connection - USING REAL ARF OSS
2199
  # ===========================================
2200
  def run_oss_analysis_real_arf(scenario_name: str) -> tuple:
2201
  """
2202
- Use REAL ARF OSS installation to run analysis
2203
  Returns: (detection_html, recall_html, decision_html, oss_results_dict, incident_df)
2204
  """
2205
- logger.info(f"🚀 Running REAL ARF OSS analysis for: {scenario_name}")
2206
 
2207
  try:
2208
- # Get real ARF installation status
2209
- installation = get_installation_status()
2210
- boundaries = BoundaryManager.get_system_boundaries()
2211
-
2212
- # Check if real ARF OSS is installed
2213
- if installation["oss_installed"]:
2214
- logger.info("✅ Using REAL ARF OSS installation")
2215
-
2216
- # Try to use real TrueARFOrchestrator
2217
- orchestrator = components["DemoOrchestrator"]()
2218
-
2219
- # Run analysis using real ARF (sync wrapper for async)
2220
- async def _run_real_analysis():
2221
- scenario_data = components["INCIDENT_SCENARIOS"].get(scenario_name, {})
2222
- return await orchestrator.analyze_incident(scenario_name, scenario_data)
2223
-
2224
- analysis_result = AsyncRunner.run_async(_run_real_analysis())
2225
-
2226
- # Add to audit trail
2227
- get_audit_manager().add_incident(scenario_name, analysis_result)
2228
-
2229
- # Create HTML for active agents using real ARF colors
2230
- boundary_color = boundaries["oss"]["color"] # Green for OSS
2231
- boundary_text = boundaries["oss"]["label"]
2232
-
2233
- else:
2234
- logger.warning("⚠️ Real ARF OSS not installed, using enhanced simulation")
2235
- # Enhanced simulation with realistic data
2236
- boundary_color = "#10b981" # Green for OSS
2237
- boundary_text = "OSS Simulation"
2238
-
2239
- # Create realistic analysis result
2240
- analysis_result = {
2241
- "status": "success",
2242
- "scenario": scenario_name,
2243
- "arf_version": "3.3.9",
2244
- "analysis": {
2245
- "detected": True,
2246
- "confidence": 94,
2247
- "similar_incidents": 3,
2248
- "healing_intent_created": True,
2249
- "recommended_action": "Scale Redis cluster from 3 to 5 nodes",
2250
- "estimated_recovery": "12 minutes"
2251
- },
2252
- "agents": {
2253
- "detection": {"status": "active", "confidence": 94},
2254
- "recall": {"status": "active", "similar_incidents": 3},
2255
- "decision": {"status": "active", "healing_intent_created": True}
2256
- },
2257
- "boundary_note": "OSS analysis complete → Ready for Enterprise execution"
2258
- }
2259
-
2260
- # Add to audit trail
2261
- get_audit_manager().add_incident(scenario_name, analysis_result)
2262
-
2263
- # Create ACTIVE agent HTML (green theme for OSS)
2264
- detection_html = f"""
2265
- <div style="border: 2px solid {boundary_color}; border-radius: 14px; padding: 18px;
2266
- background: linear-gradient(135deg, {boundary_color}10 0%, #ffffff 100%);
2267
- text-align: center; flex: 1; margin: 5px; min-height: 180px;">
2268
- <div style="font-size: 32px; margin-bottom: 10px; color: {boundary_color};">🕵️‍♂️</div>
2269
- <div style="width: 100%;">
2270
- <h4 style="margin: 0 0 8px 0; font-size: 16px; color: #1e293b;">Detection Agent</h4>
2271
- <p style="font-size: 13px; color: #64748b; margin-bottom: 12px; line-height: 1.4;">
2272
- Anomaly detected with 94% confidence
2273
- </p>
2274
- <div style="display: flex; justify-content: space-around; margin-bottom: 12px;">
2275
- <span style="font-size: 11px; padding: 3px 8px; background: {boundary_color}20;
2276
- border-radius: 6px; color: {boundary_color}; font-weight: 500;">
2277
- Status: 🔥 ACTIVE
2278
- </span>
2279
- </div>
2280
- <div style="display: inline-block; padding: 5px 14px; background: {boundary_color};
2281
- border-radius: 20px; font-size: 12px; font-weight: bold; color: white;
2282
- text-transform: uppercase; letter-spacing: 0.5px;">
2283
- DETECTED
2284
- </div>
2285
- </div>
2286
- </div>
2287
- """
2288
-
2289
- recall_html = f"""
2290
- <div style="border: 2px solid {boundary_color}; border-radius: 14px; padding: 18px;
2291
- background: linear-gradient(135deg, {boundary_color}10 0%, #ffffff 100%);
2292
- text-align: center; flex: 1; margin: 5px; min-height: 180px;">
2293
- <div style="font-size: 32px; margin-bottom: 10px; color: {boundary_color};">🧠</div>
2294
- <div style="width: 100%;">
2295
- <h4 style="margin: 0 0 8px 0; font-size: 16px; color: #1e293b;">Recall Agent</h4>
2296
- <p style="font-size: 13px; color: #64748b; margin-bottom: 12px; line-height: 1.4;">
2297
- 3 similar incidents found in RAG memory
2298
- </p>
2299
- <div style="display: flex; justify-content: space-around; margin-bottom: 12px;">
2300
- <span style="font-size: 11px; padding: 3px 8px; background: {boundary_color}20;
2301
- border-radius: 6px; color: {boundary_color}; font-weight: 500;">
2302
- Status: 🔥 ACTIVE
2303
- </span>
2304
- </div>
2305
- <div style="display: inline-block; padding: 5px 14px; background: {boundary_color};
2306
- border-radius: 20px; font-size: 12px; font-weight: bold; color: white;
2307
- text-transform: uppercase; letter-spacing: 0.5px;">
2308
- RECALLED
2309
- </div>
2310
- </div>
2311
- </div>
2312
- """
2313
-
2314
- decision_html = f"""
2315
- <div style="border: 2px solid {boundary_color}; border-radius: 14px; padding: 18px;
2316
- background: linear-gradient(135deg, {boundary_color}10 0%, #ffffff 100%);
2317
- text-align: center; flex: 1; margin: 5px; min-height: 180px;">
2318
- <div style="font-size: 32px; margin-bottom: 10px; color: {boundary_color};">🎯</div>
2319
- <div style="width: 100%;">
2320
- <h4 style="margin: 0 0 8px 0; font-size: 16px; color: #1e293b;">Decision Agent</h4>
2321
- <p style="font-size: 13px; color: #64748b; margin-bottom: 12px; line-height: 1.4;">
2322
- HealingIntent created: Scale Redis cluster
2323
- </p>
2324
- <div style="display: flex; justify-content: space-around; margin-bottom: 12px;">
2325
- <span style="font-size: 11px; padding: 3px 8px; background: {boundary_color}20;
2326
- border-radius: 6px; color: {boundary_color}; font-weight: 500;">
2327
- Status: 🔥 ACTIVE
2328
- </span>
2329
- </div>
2330
- <div style="display: inline-block; padding: 5px 14px; background: {boundary_color};
2331
- border-radius: 20px; font-size: 12px; font-weight: bold; color: white;
2332
- text-transform: uppercase; letter-spacing: 0.5px;">
2333
- DECIDED
2334
- </div>
2335
- </div>
2336
- </div>
2337
- """
2338
-
2339
- # Create OSS results dict
2340
- if installation["oss_installed"] and "real" in str(analysis_result).lower():
2341
- oss_results_dict = {
2342
- "status": "success",
2343
- "scenario": scenario_name,
2344
- "arf_version": installation["oss_version"] or "3.3.9",
2345
- "analysis": analysis_result.get("analysis", {}),
2346
- "agents": analysis_result.get("agents", {}),
2347
- "boundary_note": f"Real ARF OSS {installation['oss_version']} analysis complete → Ready for Enterprise execution",
2348
- "installation": {
2349
- "oss_installed": True,
2350
- "version": installation["oss_version"],
2351
- "edition": installation["oss_edition"]
2352
- }
2353
- }
2354
- else:
2355
- oss_results_dict = {
2356
- "status": "success",
2357
- "scenario": scenario_name,
2358
- "arf_version": "3.3.9",
2359
- "analysis": {
2360
- "detected": True,
2361
- "confidence": 94,
2362
- "similar_incidents": 3,
2363
- "healing_intent_created": True,
2364
- "recommended_action": "Scale Redis cluster from 3 to 5 nodes",
2365
- "estimated_recovery": "12 minutes"
2366
- },
2367
- "agents": {
2368
- "detection": {"status": "active", "confidence": 94},
2369
- "recall": {"status": "active", "similar_incidents": 3},
2370
- "decision": {"status": "active", "healing_intent_created": True}
2371
- },
2372
- "boundary_note": f"OSS analysis complete → Ready for Enterprise execution",
2373
- "installation": {
2374
- "oss_installed": installation["oss_installed"],
2375
- "version": installation["oss_version"] or "demo",
2376
- "edition": installation["oss_edition"]
2377
- }
2378
- }
2379
-
2380
- # Get incident DataFrame
2381
- incident_df = get_audit_manager().get_incident_dataframe()
2382
 
2383
- logger.info(f"✅ OSS analysis completed for {scenario_name} using {'REAL ARF' if installation['oss_installed'] else 'enhanced simulation'}")
2384
  return detection_html, recall_html, decision_html, oss_results_dict, incident_df
2385
 
2386
  except Exception as e:
@@ -2413,7 +2201,7 @@ def create_demo_interface():
2413
 
2414
  return error_html, error_html, error_html, error_dict, error_df
2415
 
2416
- # Run OSS Analysis - FIXED: Uses REAL ARF OSS connection
2417
  oss_btn.click(
2418
  fn=run_oss_analysis_real_arf,
2419
  inputs=[scenario_dropdown],
@@ -2437,7 +2225,7 @@ def create_demo_interface():
2437
  # Step 1: Update scenario with metrics
2438
  update_result = update_scenario_display_with_metrics(scenario_name)
2439
 
2440
- # Step 2: Run OSS analysis using REAL ARF function
2441
  oss_result = run_oss_analysis_real_arf(scenario_name)
2442
 
2443
  # Step 3: Execute Enterprise (simulation) with boundary context
 
3
  # Enhanced with clear OSS vs Enterprise boundaries
4
  # UPDATED: Added realism panel integration for enterprise-seasoned SRE experience
5
  # UPDATED: Added dynamic performance metrics for Phase 2
6
+ # SURGICAL FIX: Added doctrinally pure ARF OSS UI adapter
7
 
8
  import logging
9
  import sys
 
179
  <strong>Boundary:</strong> Real execution with safety guarantees
180
  </p>
181
  <div style="display: inline-block; padding: 10px 24px; background: #065f46;
182
+ border-radius: 20px; font-size: 14px; font-weight: bold; color: white;
183
  text-transform: uppercase; letter-spacing: 1px;">
184
  ENTERPRISE+
185
  </div>
 
557
  fig.update_layout(height=300)
558
  return fig
559
 
560
+ # ===========================================
561
+ # ARF OSS UI ADAPTER - DOCTRINALLY PURE IMPLEMENTATION
562
+ # ===========================================
563
+
564
+ def transform_arf_output_for_ui(raw_result: dict, scenario_name: str) -> dict:
565
+ """
566
+ TRANSLATOR FUNCTION - NOT AN ANALYST
567
+
568
+ Extracts existing intelligence from real ARF OSS output and transforms
569
+ to UI-expected format. Does not compute, infer, or enhance.
570
+
571
+ Rules:
572
+ 1. Source of truth: raw_result["oss_analysis"]["analysis"]
573
+ 2. Extract only what exists
574
+ 3. Derive UI fields mechanically from existing data
575
+ 4. Never invent intelligence
576
+ 5. Defaults must be visibly conservative, not plausible
577
+ 6. Status must reflect contribution, not invocation
578
+
579
+ Returns: UI-compatible dict with populated analysis and agents fields
580
+ """
581
+
582
+ # ===================================================
583
+ # STEP 1: DETERMINE INPUT MODE AND SOURCE DATA
584
+ # ===================================================
585
+
586
+ # Mode 1: Real OSS Mode (has oss_analysis)
587
+ if "oss_analysis" in raw_result and raw_result["oss_analysis"]:
588
+ oss_analysis = raw_result["oss_analysis"]
589
+ source_analysis = oss_analysis.get("analysis", {}) if isinstance(oss_analysis, dict) else {}
590
+ is_real_oss = True
591
+
592
+ # Mode 2: Mock/Fallback Mode (already has analysis at root)
593
+ elif "analysis" in raw_result and raw_result["analysis"]:
594
+ source_analysis = raw_result["analysis"]
595
+ is_real_oss = False
596
+
597
+ # Mode 3: Error/Failure Mode
598
+ else:
599
+ # Return minimal UI-safe structure to prevent UI breakage
600
+ return {
601
+ "status": raw_result.get("status", "error"),
602
+ "scenario": scenario_name,
603
+ "arf_version": raw_result.get("arf_version", "3.3.9"),
604
+ "analysis": {
605
+ "detected": False,
606
+ "confidence": 0, # VISIBLY CONSERVATIVE
607
+ "similar_incidents": 0, # VISIBLY CONSERVATIVE
608
+ "healing_intent_created": False,
609
+ "recommended_action": "Check OSS analysis output",
610
+ "estimated_recovery": "Unknown" # VISIBLY CONSERVATIVE
611
+ },
612
+ "agents": {
613
+ "detection": {"status": "error", "confidence": 0},
614
+ "recall": {"status": "error", "similar_incidents": 0},
615
+ "decision": {"status": "error", "healing_intent_created": False}
616
+ },
617
+ "boundary_note": "OSS analysis output malformed",
618
+ "installation": {
619
+ "oss_installed": True,
620
+ "version": "3.3.9",
621
+ "edition": "oss"
622
+ }
623
+ }
624
+
625
+ # ===================================================
626
+ # STEP 2: EXTRACT ANALYSIS DATA (SOURCE OF TRUTH ONLY)
627
+ # ===================================================
628
+
629
+ # Extract detection data - MUST EXIST IN SOURCE
630
+ detection_data = source_analysis.get("detection", {}) if isinstance(source_analysis, dict) else {}
631
+ recall_data = source_analysis.get("recall", {}) if isinstance(source_analysis, dict) else {}
632
+ decision_data = source_analysis.get("decision", {}) if isinstance(source_analysis, dict) else {}
633
+
634
+ # ===================================================
635
+ # STEP 3: BUILD UI ANALYSIS (DERIVED, NOT INFERRED)
636
+ # ===================================================
637
+
638
+ # REFINED: detected requires explicit detection signal in OSS output
639
+ # Not just existence of detection_data, but evidence of actual detection
640
+ detected = False
641
+ if isinstance(detection_data, dict):
642
+ # Look for explicit detection signals that OSS should provide
643
+ detection_signals = ["signal", "anomaly", "finding", "detected", "alert", "indicator"]
644
+ detected = any(k in detection_data for k in detection_signals)
645
+
646
+ # CORRECTED: confidence = 0 if not in source (visibly conservative)
647
+ confidence = 0 # VISIBLY CONSERVATIVE DEFAULT
648
+ if "confidence" in decision_data:
649
+ confidence = decision_data["confidence"]
650
+ elif "confidence" in detection_data:
651
+ confidence = detection_data["confidence"]
652
+
653
+ # CORRECTED: similar_incidents = 0 if not in source (visibly conservative)
654
+ similar_incidents = 0 # VISIBLY CONSERVATIVE DEFAULT
655
+ if isinstance(recall_data, dict) and "results" in recall_data:
656
+ if isinstance(recall_data["results"], list):
657
+ similar_incidents = len(recall_data["results"])
658
+ elif "similar_incidents" in recall_data:
659
+ similar_incidents = recall_data["similar_incidents"]
660
+
661
+ # CORRECTED: healing_intent_created requires explicit action in decision data
662
+ healing_intent_created = False
663
+ if isinstance(decision_data, dict):
664
+ healing_intent_created = "action" in decision_data or "recommended_action" in decision_data
665
+
666
+ # Rule: recommended_action = pass through existing decision action text
667
+ recommended_action = "No actionable intelligence found" # VISIBLY CONSERVATIVE
668
+ if isinstance(decision_data, dict):
669
+ if "action" in decision_data:
670
+ recommended_action = decision_data["action"]
671
+ elif "recommended_action" in decision_data:
672
+ recommended_action = decision_data["recommended_action"]
673
+
674
+ # CORRECTED: estimated_recovery = "Unknown" (do not calculate or imply)
675
+ estimated_recovery = "Unknown"
676
+
677
+ # ===================================================
678
+ # STEP 4: BUILD UI AGENTS (CONTRIBUTION-BASED STATUS)
679
+ # ===================================================
680
+
681
+ # REFINED: Agent status reflects actual contribution, not mere invocation
682
+ # Detection agent: "active" only if detection actually occurred
683
+ detection_status = "active" if detected else "inactive"
684
+
685
+ # Recall agent: "active" only if similar incidents were found
686
+ recall_status = "active" if similar_incidents > 0 else "inactive"
687
+
688
+ # Decision agent: "active" only if healing intent was created
689
+ decision_status = "active" if healing_intent_created else "inactive"
690
+
691
+ # Override status to "error" if OSS status is error
692
+ if raw_result.get("status") == "error":
693
+ detection_status = "error"
694
+ recall_status = "error"
695
+ decision_status = "error"
696
+
697
+ # ===================================================
698
+ # STEP 5: ASSEMBLE FINAL UI-COMPATIBLE RESULT
699
+ # ===================================================
700
+
701
+ result = {
702
+ "status": raw_result.get("status", "success"),
703
+ "scenario": raw_result.get("scenario", scenario_name),
704
+ "arf_version": raw_result.get("arf_version", "3.3.9"),
705
+ "analysis": {
706
+ "detected": detected,
707
+ "confidence": confidence,
708
+ "similar_incidents": similar_incidents,
709
+ "healing_intent_created": healing_intent_created,
710
+ "recommended_action": recommended_action,
711
+ "estimated_recovery": estimated_recovery
712
+ },
713
+ "agents": {
714
+ "detection": {
715
+ "status": detection_status,
716
+ "confidence": confidence if detection_status == "active" else 0
717
+ },
718
+ "recall": {
719
+ "status": recall_status,
720
+ "similar_incidents": similar_incidents if recall_status == "active" else 0
721
+ },
722
+ "decision": {
723
+ "status": decision_status,
724
+ "healing_intent_created": healing_intent_created if decision_status == "active" else False
725
+ }
726
+ },
727
+ "boundary_note": raw_result.get("boundary_note",
728
+ "Real ARF OSS 3.3.9 analysis complete → Ready for Enterprise execution"),
729
+ "installation": {
730
+ "oss_installed": True,
731
+ "version": "3.3.9",
732
+ "edition": "oss"
733
+ }
734
  }
735
 
736
+ # Preserve original oss_analysis for debugging (optional)
737
+ if is_real_oss:
738
+ result["_original_oss_analysis"] = raw_result.get("oss_analysis")
739
 
740
+ return result
741
+
742
+ # ===========================================
743
+ # UPDATED: run_true_arf_analysis() - DOCTRINALLY PURE
744
+ # ===========================================
745
+
746
+ @AsyncRunner.async_to_sync
747
+ async def run_true_arf_analysis(scenario_name: str) -> tuple:
748
+ """
749
+ DOCTRINALLY PURE VERSION: Adapter transforms ARF OSS output with epistemic honesty
750
+ Returns exactly 5 values as expected by UI:
751
+ 1. detection_html (HTML string)
752
+ 2. recall_html (HTML string)
753
+ 3. decision_html (HTML string)
754
+ 4. oss_results_dict (Python dict for JSON display)
755
+ 5. incident_df (DataFrame for Gradio DataFrame component)
756
+ """
757
+
758
+ components = get_components()
759
+ installation = get_installation_status()
760
+ boundaries = BoundaryManager.get_system_boundaries()
761
+
762
+ logger.info(f"🔍 Running True ARF analysis for: {scenario_name}")
763
+
764
+ try:
765
+ # Get orchestrator
766
+ orchestrator = components["DemoOrchestrator"]()
767
 
768
+ # Get scenario data
769
+ scenarios = components["INCIDENT_SCENARIOS"]
770
+ scenario_data = scenarios.get(scenario_name, {})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
771
 
772
+ # ======================================================
773
+ # DOCTRINAL FIX POINT: CALL REAL ARF OSS
774
+ # ======================================================
775
+ raw_result = await orchestrator.analyze_incident(scenario_name, scenario_data)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
776
 
777
+ # ======================================================
778
+ # DOCTRINAL ADAPTER: TRANSFORM WITH EPISTEMIC HONESTY
779
+ # ======================================================
780
+ transformed_result = transform_arf_output_for_ui(raw_result, scenario_name)
 
 
 
 
 
 
 
 
 
 
 
781
 
782
+ # ======================================================
783
+ # EXISTING UI INTEGRATION (PRESERVED)
784
+ # ======================================================
785
+ # Add to audit trail
786
+ get_audit_manager().add_incident(scenario_name, transformed_result)
787
+
788
+ # Create HTML for active agents using transformed result
789
+ boundary_color = boundaries["oss"]["color"]
790
+
791
+ # Extract data from transformed result
792
+ analysis = transformed_result.get("analysis", {})
793
+ agents = transformed_result.get("agents", {})
794
+
795
+ # Get data for HTML templates
796
+ confidence = analysis.get("confidence", 0) # CONSERVATIVE DEFAULT
797
+ similar_incidents = analysis.get("similar_incidents", 0) # CONSERVATIVE DEFAULT
798
+ detection_agent = agents.get("detection", {})
799
+ recall_agent = agents.get("recall", {})
800
+ decision_agent = agents.get("decision", {})
801
+
802
+ # Detection Agent HTML - Now truthfully reflects actual detection
803
+ detection_status = detection_agent.get("status", "inactive")
804
+ detection_status_text = detection_status.capitalize()
805
+
806
+ # REFINED: Badge text reflects actual contribution state
807
+ if detection_status == "active":
808
+ detection_badge = "DETECTED"
809
+ confidence_text = f"Anomaly detected with {confidence}% confidence"
810
+ elif detection_status == "inactive":
811
+ detection_badge = "ANALYZING"
812
+ confidence_text = "No anomaly signal found"
813
+ else:
814
+ detection_badge = "ERROR"
815
+ confidence_text = "Detection analysis failed"
816
 
817
+ detection_html = f"""
818
+ <div style="border: 2px solid {boundary_color}; border-radius: 14px; padding: 18px;
819
+ background: linear-gradient(135deg, {boundary_color}10 0%, #ffffff 100%);
820
+ text-align: center; flex: 1; margin: 5px; min-height: 180px;">
821
+ <div style="font-size: 32px; margin-bottom: 10px; color: {boundary_color};">🕵️‍♂️</div>
822
+ <div style="width: 100%;">
823
+ <h4 style="margin: 0 0 8px 0; font-size: 16px; color: #1e293b;">Detection Agent</h4>
824
+ <p style="font-size: 13px; color: #64748b; margin-bottom: 12px; line-height: 1.4;">
825
+ {confidence_text}
826
+ </p>
827
+ <div style="display: flex; justify-content: space-around; margin-bottom: 12px;">
828
+ <span style="font-size: 11px; padding: 3px 8px; background: {boundary_color}20;
829
+ border-radius: 6px; color: {boundary_color}; font-weight: 500;">
830
+ Status: {detection_status_text}
831
+ </span>
832
  </div>
833
+ <div style="display: inline-block; padding: 5px 14px; background: {boundary_color};
834
+ border-radius: 20px; font-size: 12px; font-weight: bold; color: white;
835
+ text-transform: uppercase; letter-spacing: 0.5px;">
836
+ {detection_badge}
837
  </div>
838
  </div>
839
  </div>
840
+ """
841
 
842
+ # Recall Agent HTML - Now truthfully reflects actual recall
843
+ recall_status = recall_agent.get("status", "inactive")
844
+ recall_status_text = recall_status.capitalize()
845
+
846
+ # REFINED: Badge text reflects actual contribution state
847
+ if recall_status == "active":
848
+ recall_badge = "RECALLED"
849
+ recall_text = f"Found {similar_incidents} similar incident{'s' if similar_incidents != 1 else ''}"
850
+ elif recall_status == "inactive":
851
+ recall_badge = "SEARCHING"
852
+ recall_text = "No similar incidents found"
853
+ else:
854
+ recall_badge = "ERROR"
855
+ recall_text = "Recall analysis failed"
856
+
857
+ recall_html = f"""
858
+ <div style="border: 2px solid {boundary_color}; border-radius: 14px; padding: 18px;
859
+ background: linear-gradient(135deg, {boundary_color}10 0%, #ffffff 100%);
860
+ text-align: center; flex: 1; margin: 5px; min-height: 180px;">
861
+ <div style="font-size: 32px; margin-bottom: 10px; color: {boundary_color};">🧠</div>
862
+ <div style="width: 100%;">
863
+ <h4 style="margin: 0 0 8px 0; font-size: 16px; color: #1e293b;">Recall Agent</h4>
864
+ <p style="font-size: 13px; color: #64748b; margin-bottom: 12px; line-height: 1.4;">
865
+ {recall_text}
866
+ </p>
867
+ <div style="display: flex; justify-content: space-around; margin-bottom: 12px;">
868
+ <span style="font-size: 11px; padding: 3px 8px; background: {boundary_color}20;
869
+ border-radius: 6px; color: {boundary_color}; font-weight: 500;">
870
+ Status: {recall_status_text}
871
+ </span>
872
  </div>
873
+ <div style="display: inline-block; padding: 5px 14px; background: {boundary_color};
874
+ border-radius: 20px; font-size: 12px; font-weight: bold; color: white;
875
+ text-transform: uppercase; letter-spacing: 0.5px;">
876
+ {recall_badge}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
877
  </div>
878
  </div>
879
  </div>
880
+ """
881
 
882
+ # Decision Agent HTML - Now truthfully reflects actual decision
883
+ decision_status = decision_agent.get("status", "inactive")
884
+ decision_status_text = decision_status.capitalize()
885
+
886
+ # REFINED: Badge text reflects actual contribution state
887
+ if decision_status == "active":
888
+ decision_badge = "DECIDED"
889
+ decision_text = analysis.get('recommended_action', 'Action recommended')
890
+ elif decision_status == "inactive":
891
+ decision_badge = "EVALUATING"
892
+ decision_text = "No action recommended"
893
+ else:
894
+ decision_badge = "ERROR"
895
+ decision_text = "Decision analysis failed"
896
 
897
+ decision_html = f"""
898
+ <div style="border: 2px solid {boundary_color}; border-radius: 14px; padding: 18px;
899
+ background: linear-gradient(135deg, {boundary_color}10 0%, #ffffff 100%);
900
+ text-align: center; flex: 1; margin: 5px; min-height: 180px;">
901
+ <div style="font-size: 32px; margin-bottom: 10px; color: {boundary_color};">🎯</div>
902
+ <div style="width: 100%;">
903
+ <h4 style="margin: 0 0 8px 0; font-size: 16px; color: #1e293b;">Decision Agent</h4>
904
+ <p style="font-size: 13px; color: #64748b; margin-bottom: 12px; line-height: 1.4;">
905
+ {decision_text}
906
+ </p>
907
+ <div style="display: flex; justify-content: space-around; margin-bottom: 12px;">
908
+ <span style="font-size: 11px; padding: 3px 8px; background: {boundary_color}20;
909
+ border-radius: 6px; color: {boundary_color}; font-weight: 500;">
910
+ Status: {decision_status_text}
911
+ </span>
912
  </div>
913
+ <div style="display: inline-block; padding: 5px 14px; background: {boundary_color};
914
+ border-radius: 20px; font-size: 12px; font-weight: bold; color: white;
915
+ text-transform: uppercase; letter-spacing: 0.5px;">
916
+ {decision_badge}
917
  </div>
918
  </div>
919
  </div>
920
+ """
921
 
922
+ # OSS Results Dict for JSON display (using transformed result)
923
+ oss_results_dict = transformed_result
924
+
925
+ # Incident DataFrame
926
+ incident_df = get_audit_manager().get_incident_dataframe()
927
+
928
+ logger.info(f"✅ True ARF analysis complete for {scenario_name}")
929
+ logger.info(f" Detection: {'ACTIVE' if detection_status == 'active' else 'INACTIVE'} (confidence: {confidence})")
930
+ logger.info(f" Recall: {'ACTIVE' if recall_status == 'active' else 'INACTIVE'} (incidents: {similar_incidents})")
931
+ logger.info(f" Decision: {'ACTIVE' if decision_status == 'active' else 'INACTIVE'}")
932
+
933
+ return detection_html, recall_html, decision_html, oss_results_dict, incident_df
934
+
935
+ except Exception as e:
936
+ logger.error(f"True ARF analysis failed: {e}")
937
+
938
+ # Return error state with proper types
939
+ error_html = f"""
940
+ <div style="border: 2px solid #ef4444; border-radius: 14px; padding: 18px;
941
+ background: linear-gradient(135deg, #fef2f2 0%, #ffffff 100%);
942
+ text-align: center; flex: 1; margin: 5px; min-height: 180px;">
943
+ <div style="font-size: 32px; margin-bottom: 10px; color: #ef4444;">❌</div>
944
+ <div style="width: 100%;">
945
+ <h4 style="margin: 0 0 8px 0; font-size: 16px; color: #1e293b;">Analysis Error</h4>
946
+ <p style="font-size: 13px; color: #64748b; margin-bottom: 12px; line-height: 1.4;">
947
+ Failed to analyze incident
948
+ </p>
949
+ <div style="display: flex; justify-content: space-around; margin-bottom: 12px;">
950
+ <span style="font-size: 11px; padding: 3px 8px; background: #ef4444;
951
+ border-radius: 6px; color: white; font-weight: 500;">
952
+ Status: Error
953
+ </span>
 
 
 
 
 
954
  </div>
955
  </div>
956
  </div>
957
+ """
958
+
959
+ error_dict = {
960
+ "status": "error",
961
+ "error": str(e),
962
+ "scenario": scenario_name,
963
+ "arf_version": "3.3.9",
964
+ "analysis": {
965
+ "detected": False,
966
+ "confidence": 0,
967
+ "similar_incidents": 0,
968
+ "healing_intent_created": False,
969
+ "recommended_action": "Check ARF installation",
970
+ "estimated_recovery": "Unknown"
971
+ },
972
+ "agents": {
973
+ "detection": {"status": "error", "confidence": 0},
974
+ "recall": {"status": "error", "similar_incidents": 0},
975
+ "decision": {"status": "error", "healing_intent_created": False}
976
+ }
977
+ }
978
 
979
+ # Return empty DataFrame on error
980
+ error_df = pd.DataFrame(columns=["Error", "Message"]).from_records([
981
+ {"Error": "Analysis Failed", "Message": str(e)}
982
+ ])
983
 
984
+ return error_html, error_html, error_html, error_dict, error_df
 
 
 
 
 
 
 
 
985
 
986
  # ===========================================
987
  # IMPORT MODULAR COMPONENTS - FIXED: Added MockEnhancedROICalculator
 
1604
  <td style="padding: 12px; font-size: 13px; color: #1e293b;">
1605
  {status} {exec["scenario"]}
1606
  </td>
1607
+ <td style="padding: 12px; font-size=13px; color: #64748b;">
1608
  {exec["mode"]}
1609
  </td>
1610
  <td style="padding: 12px; font-size: 13px;">
 
1880
  return (scenario_card, telemetry_fig, impact_fig, timeline_fig, realism_html,
1881
  detection_time_html, mttr_html, auto_heal_html, savings_html)
1882
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1883
  # ===========================================
1884
  # FIXED EXECUTION FUNCTION - Returns DataFrames
1885
  # ===========================================
 
2155
  )
2156
 
2157
  # ===========================================
2158
+ # FIXED: OSS Analysis Button Connection - USING TRUE ARF OSS ADAPTER
2159
  # ===========================================
2160
  def run_oss_analysis_real_arf(scenario_name: str) -> tuple:
2161
  """
2162
+ Use TRUE ARF OSS with doctrinally pure adapter
2163
  Returns: (detection_html, recall_html, decision_html, oss_results_dict, incident_df)
2164
  """
2165
+ logger.info(f"🚀 Running TRUE ARF OSS analysis for: {scenario_name}")
2166
 
2167
  try:
2168
+ # Use the updated run_true_arf_analysis() which includes the adapter
2169
+ detection_html, recall_html, decision_html, oss_results_dict, incident_df = run_true_arf_analysis(scenario_name)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2170
 
2171
+ logger.info(f"✅ OSS analysis completed for {scenario_name}")
2172
  return detection_html, recall_html, decision_html, oss_results_dict, incident_df
2173
 
2174
  except Exception as e:
 
2201
 
2202
  return error_html, error_html, error_html, error_dict, error_df
2203
 
2204
+ # Run OSS Analysis - FIXED: Uses TRUE ARF OSS with adapter
2205
  oss_btn.click(
2206
  fn=run_oss_analysis_real_arf,
2207
  inputs=[scenario_dropdown],
 
2225
  # Step 1: Update scenario with metrics
2226
  update_result = update_scenario_display_with_metrics(scenario_name)
2227
 
2228
+ # Step 2: Run OSS analysis using TRUE ARF OSS function
2229
  oss_result = run_oss_analysis_real_arf(scenario_name)
2230
 
2231
  # Step 3: Execute Enterprise (simulation) with boundary context