Update app.py
Browse files
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
|
| 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 |
-
#
|
| 560 |
-
|
| 561 |
-
|
| 562 |
-
|
| 563 |
-
|
| 564 |
-
|
| 565 |
-
|
| 566 |
-
|
| 567 |
-
|
| 568 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 569 |
}
|
| 570 |
|
| 571 |
-
|
| 572 |
-
|
|
|
|
| 573 |
|
| 574 |
-
return
|
| 575 |
-
|
| 576 |
-
|
| 577 |
-
|
| 578 |
-
|
| 579 |
-
|
| 580 |
-
|
| 581 |
-
|
| 582 |
-
|
| 583 |
-
|
| 584 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 585 |
|
| 586 |
-
|
| 587 |
-
|
| 588 |
-
|
| 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 |
-
|
| 608 |
-
|
| 609 |
-
|
| 610 |
-
|
| 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 |
-
|
| 630 |
-
|
| 631 |
-
|
| 632 |
-
|
| 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 |
-
|
| 646 |
-
|
| 647 |
-
|
| 648 |
-
|
| 649 |
-
|
| 650 |
-
|
| 651 |
-
|
| 652 |
-
|
| 653 |
-
|
| 654 |
-
|
| 655 |
-
|
| 656 |
-
|
| 657 |
-
|
| 658 |
-
|
| 659 |
-
|
| 660 |
-
|
| 661 |
-
|
| 662 |
-
|
| 663 |
-
|
| 664 |
-
|
| 665 |
-
|
| 666 |
-
|
| 667 |
-
|
| 668 |
-
|
| 669 |
-
|
| 670 |
-
|
| 671 |
-
|
| 672 |
-
|
| 673 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 674 |
|
| 675 |
-
|
| 676 |
-
|
| 677 |
-
|
| 678 |
-
|
| 679 |
-
|
| 680 |
-
|
| 681 |
-
|
| 682 |
-
|
| 683 |
-
|
| 684 |
-
|
| 685 |
-
|
| 686 |
-
|
| 687 |
-
|
| 688 |
-
|
|
|
|
| 689 |
</div>
|
| 690 |
-
<div style="
|
| 691 |
-
|
|
|
|
|
|
|
| 692 |
</div>
|
| 693 |
</div>
|
| 694 |
</div>
|
|
|
|
| 695 |
|
| 696 |
-
|
| 697 |
-
|
| 698 |
-
|
| 699 |
-
|
| 700 |
-
|
| 701 |
-
|
| 702 |
-
|
| 703 |
-
|
| 704 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 705 |
</div>
|
| 706 |
-
|
| 707 |
-
|
| 708 |
-
|
| 709 |
-
|
| 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 |
-
|
| 737 |
-
|
| 738 |
-
|
| 739 |
-
|
| 740 |
-
|
| 741 |
-
|
| 742 |
-
|
| 743 |
-
|
| 744 |
-
|
| 745 |
-
|
| 746 |
-
|
| 747 |
-
|
| 748 |
-
|
| 749 |
-
|
| 750 |
|
| 751 |
-
|
| 752 |
-
<div style="
|
| 753 |
-
|
| 754 |
-
|
| 755 |
-
<div>
|
| 756 |
-
|
| 757 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 758 |
</div>
|
| 759 |
-
<div style="
|
| 760 |
-
|
|
|
|
|
|
|
| 761 |
</div>
|
| 762 |
</div>
|
| 763 |
</div>
|
|
|
|
| 764 |
|
| 765 |
-
|
| 766 |
-
|
| 767 |
-
|
| 768 |
-
|
| 769 |
-
|
| 770 |
-
|
| 771 |
-
|
| 772 |
-
|
| 773 |
-
|
| 774 |
-
|
| 775 |
-
|
| 776 |
-
|
| 777 |
-
|
| 778 |
-
|
| 779 |
-
|
| 780 |
-
|
| 781 |
-
|
| 782 |
-
|
| 783 |
-
|
| 784 |
-
|
| 785 |
-
|
| 786 |
-
|
| 787 |
-
|
| 788 |
-
|
| 789 |
-
|
| 790 |
-
|
| 791 |
-
|
| 792 |
-
|
| 793 |
-
|
| 794 |
-
|
| 795 |
-
|
| 796 |
-
|
| 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 |
-
|
| 807 |
-
|
| 808 |
-
{
|
| 809 |
-
|
| 810 |
|
| 811 |
-
|
| 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
|
| 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
|
| 2199 |
# ===========================================
|
| 2200 |
def run_oss_analysis_real_arf(scenario_name: str) -> tuple:
|
| 2201 |
"""
|
| 2202 |
-
Use
|
| 2203 |
Returns: (detection_html, recall_html, decision_html, oss_results_dict, incident_df)
|
| 2204 |
"""
|
| 2205 |
-
logger.info(f"🚀 Running
|
| 2206 |
|
| 2207 |
try:
|
| 2208 |
-
#
|
| 2209 |
-
|
| 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}
|
| 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
|
| 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
|
| 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
|