petter2025's picture
Update ui/components.py
d83d0aa verified
raw
history blame
58.2 kB
"""
Gradio-only UI components for ARF
Ensures full compatibility with app.py
Updated with proper imports and error handling
NOW WITH REAL ARF INSTALLATION DETECTION
UPDATED: Added realism panel integration for Tab 1
"""
import gradio as gr
from typing import Dict, List, Any
import logging
logger = logging.getLogger(__name__)
# Try to import scenarios from registry first
try:
from config.scenario_registry import ScenarioRegistry
INCIDENT_SCENARIOS = ScenarioRegistry.load_scenarios()
logger.info(f"Loaded {len(INCIDENT_SCENARIOS)} scenarios from registry")
except ImportError:
logger.warning("Scenario registry not available, falling back to demo scenarios")
from demo.scenarios import INCIDENT_SCENARIOS
# -----------------------------
# Header & Status - UPDATED WITH INSTALLATION CHECK
# -----------------------------
def create_header(version="3.3.7", mock_mode=False) -> gr.HTML:
# Try to get installation status
try:
from app import get_installation_badges
installation_badges = get_installation_badges()
except ImportError:
installation_badges = """
<div style="display: flex; justify-content: center; gap: 10px; margin-top: 10px; flex-wrap: wrap;">
<span style="padding: 4px 12px; background: #f59e0b;
color: white; border-radius: 20px; font-size: 12px; font-weight: bold;
display: flex; align-items: center; gap: 6px;">
⚠️ Mock ARF
</span>
<span style="padding: 4px 12px; background: #64748b;
color: white; border-radius: 20px; font-size: 12px; font-weight: bold;
display: flex; align-items: center; gap: 6px;">
πŸ”’ Enterprise Required
</span>
</div>
"""
mock_text = " Β· MOCK MODE" if mock_mode else ""
return gr.HTML(f"""
<div style="text-align: center; margin-bottom: 25px; padding: 30px 40px; background: linear-gradient(135deg, #1e3a8a 0%, #3b82f6 100%); color: white; border-radius: 16px; box-shadow: 0 8px 32px rgba(59, 130, 246, 0.15);">
<h1 style="margin: 0 0 10px 0; font-size: 32px;">πŸš€ Agentic Reliability Framework</h1>
<h2 style="margin: 0; font-size: 24px; opacity: 0.9;">v{version} (OSS Edition){mock_text}</h2>
<p style="margin: 15px 0 0 0; font-size: 16px; opacity: 0.8;">
Production-grade multi-agent AI for autonomous system reliability intelligence
</p>
<!-- Installation Status Badges -->
{installation_badges}
</div>
""")
def create_status_bar() -> gr.HTML:
# Try to get installation status
try:
from app import get_installation_status
installation = get_installation_status()
oss_badge = installation["badges"]["oss"]
enterprise_badge = installation["badges"]["enterprise"]
oss_status_html = f"""
<span style="padding: 8px 16px; background: {oss_badge['color']}; color: white; border-radius: 8px; font-size: 14px; font-weight: 500; display: flex; align-items: center; gap: 6px; border: 1px solid {oss_badge['color']};">
{oss_badge['icon']} {oss_badge['text']}
</span>
"""
enterprise_status_html = f"""
<span style="padding: 8px 16px; background: {enterprise_badge['color']}; color: white; border-radius: 8px; font-size: 14px; font-weight: 500; display: flex; align-items: center; gap: 6px; border: 1px solid {enterprise_badge['color']};">
{enterprise_badge['icon']} {enterprise_badge['text']}
</span>
"""
except ImportError:
oss_status_html = """
<span style="padding: 8px 16px; background: #f59e0b; color: white; border-radius: 8px; font-size: 14px; font-weight: 500; display: flex; align-items: center; gap: 6px; border: 1px solid #f59e0b;">
⚠️ Mock ARF
</span>
"""
enterprise_status_html = """
<span style="padding: 8px 16px; background: #64748b; color: white; border-radius: 8px; font-size: 14px; font-weight: 500; display: flex; align-items: center; gap: 6px; border: 1px solid #64748b;">
πŸ”’ Enterprise Required
</span>
"""
return gr.HTML(f"""
<div style="display: flex; justify-content: center; gap: 20px; margin-bottom: 30px; padding: 15px; background: #f8fafc; border-radius: 12px; border: 1px solid #e2e8f0; flex-wrap: wrap;">
<span style="padding: 8px 16px; background: #10b981; color: white; border-radius: 8px; font-size: 14px; font-weight: 500; display: flex; align-items: center; gap: 6px; border: 1px solid #10b981;">βœ… System Online</span>
<span style="padding: 8px 16px; background: #10b981; color: white; border-radius: 8px; font-size: 14px; font-weight: 500; display: flex; align-items: center; gap: 6px; border: 1px solid #10b981;">🧠 Agentic Core Active</span>
{oss_status_html}
{enterprise_status_html}
<span style="padding: 8px 16px; background: white; border-radius: 8px; font-size: 14px; font-weight: 500; display: flex; align-items: center; gap: 6px; border: 1px solid #e2e8f0;">πŸ’° <a href="#tab2" style="color: #10b981; text-decoration: underline;">Enterprise ROI: 5.2Γ—</a></span>
</div>
""")
# -----------------------------
# Tab 1: Live Incident Demo - UPDATED WITH REALISM PANEL
# -----------------------------
def create_tab1_incident_demo(scenarios=INCIDENT_SCENARIOS, default_scenario="Cache Miss Storm") -> tuple:
"""
Create an expressive, comprehensive incident demo tab for ARF.
Shows the complete OSS analysis β†’ Enterprise execution workflow.
UPDATED: Now includes realism panel for enterprise-seasoned SRE experience
"""
# Get the default scenario data
default_scenario_data = scenarios.get(default_scenario, {})
business_impact = default_scenario_data.get("business_impact", {})
metrics = default_scenario_data.get("metrics", {})
with gr.Row():
# Left Column: Scenario Selection & Live Visualization
with gr.Column(scale=1, variant="panel") as left_col:
# Scenario Selection with rich preview
scenario_dropdown = gr.Dropdown(
choices=list(scenarios.keys()),
value=default_scenario,
label="🎯 Select Incident Scenario",
info="Choose a production incident to analyze",
interactive=True,
container=False
)
# Scenario Card with rich information - USING INLINE STYLES
scenario_card = gr.HTML(f"""
<div style="border: 1px solid #e2e8f0; border-radius: 14px; padding: 20px; background: white; box-shadow: 0 4px 12px rgba(0,0,0,0.05); margin-bottom: 20px;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; padding-bottom: 12px; border-bottom: 2px solid #f1f5f9;">
<h3 style="margin: 0; font-size: 18px; color: #1e293b;">🚨 {default_scenario}</h3>
<span style="padding: 4px 12px; background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%); border-radius: 20px; font-size: 12px; font-weight: bold; color: white; text-transform: uppercase; letter-spacing: 0.5px;">{default_scenario_data.get('severity', 'HIGH')}</span>
</div>
<div style="margin-top: 15px;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; padding: 4px 0;">
<span style="font-size: 13px; color: #64748b; font-weight: 500;">Component:</span>
<span style="font-size: 14px; color: #1e293b; font-weight: 600;">{default_scenario_data.get('component', 'Unknown').replace('_', ' ').title()}</span>
</div>
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; padding: 4px 0;">
<span style="font-size: 13px; color: #64748b; font-weight: 500;">Affected Users:</span>
<span style="font-size: 14px; color: #1e293b; font-weight: 600;">{metrics.get('affected_users', 'Unknown') if 'affected_users' in metrics else 'Unknown'}</span>
</div>
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; padding: 4px 0;">
<span style="font-size: 13px; color: #64748b; font-weight: 500;">Revenue Risk:</span>
<span style="font-size: 14px; color: #ef4444; font-weight: 700;">${business_impact.get('revenue_loss_per_hour', 0):,}/hour</span>
</div>
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; padding: 4px 0;">
<span style="font-size: 13px; color: #64748b; font-weight: 500;">Detection Time:</span>
<span style="font-size: 14px; color: #1e293b; font-weight: 600;">45 seconds (ARF AI)</span>
</div>
<div style="display: flex; flex-wrap: wrap; gap: 6px; margin-top: 15px; padding-top: 12px; border-top: 1px solid #f1f5f9;">
<span style="padding: 3px 8px; background: #f1f5f9; border-radius: 6px; font-size: 11px; color: #475569; font-weight: 500;">{default_scenario_data.get('component', 'unknown').split('_')[0]}</span>
<span style="padding: 3px 8px; background: #f1f5f9; border-radius: 6px; font-size: 11px; color: #475569; font-weight: 500;">{default_scenario_data.get('severity', 'high').lower()}</span>
<span style="padding: 3px 8px; background: #f1f5f9; border-radius: 6px; font-size: 11px; color: #475569; font-weight: 500;">production</span>
<span style="padding: 3px 8px; background: #f1f5f9; border-radius: 6px; font-size: 11px; color: #475569; font-weight: 500;">incident</span>
</div>
</div>
</div>
""")
# Visualization section - USING gr.Plot() FOR PLOTLY FIGURES
with gr.Row():
with gr.Column(scale=1):
telemetry_header = gr.Markdown("### πŸ“ˆ Live Telemetry")
# This expects a Plotly figure from app.py
telemetry_viz = gr.Plot(
label="",
show_label=False,
elem_id="telemetry_plot"
)
with gr.Column(scale=1):
impact_header = gr.Markdown("### πŸ’° Business Impact")
impact_viz = gr.Plot(
label="",
show_label=False,
elem_id="impact_plot"
)
# Middle Column: Agent Workflow
with gr.Column(scale=2, variant="panel") as middle_col:
# Agent Workflow Header
workflow_header = gr.Markdown("## πŸ”„ ARF Agent Workflow")
workflow_subheader = gr.Markdown("### How ARF transforms incidents into autonomous healing")
# Agent Status Cards - USING INLINE STYLES
with gr.Row():
detection_agent = gr.HTML("""
<div style="border: 2px solid #e2e8f0; border-radius: 14px; padding: 18px; background: #f8fafc; text-align: center; flex: 1; margin: 5px; min-height: 180px; display: flex; flex-direction: column; align-items: center; justify-content: center; opacity: 0.7;">
<div style="font-size: 32px; margin-bottom: 10px; opacity: 0.5;">πŸ•΅οΈβ€β™‚οΈ</div>
<div style="width: 100%;">
<h4 style="margin: 0 0 8px 0; font-size: 16px; color: #94a3b8;">Detection Agent</h4>
<p style="font-size: 13px; color: #cbd5e1; margin-bottom: 12px; line-height: 1.4;">Click "Run OSS Analysis" to activate</p>
<div style="display: flex; justify-content: space-around; margin-bottom: 12px;">
<span style="font-size: 11px; padding: 3px 8px; background: rgba(255, 255, 255, 0.5); border-radius: 6px; color: #cbd5e1; font-weight: 500;">Status: Inactive</span>
</div>
<div style="display: inline-block; padding: 5px 14px; background: #e2e8f0; border-radius: 20px; font-size: 12px; font-weight: bold; color: #64748b; text-transform: uppercase; letter-spacing: 0.5px;">WAITING</div>
</div>
</div>
""")
recall_agent = gr.HTML("""
<div style="border: 2px solid #e2e8f0; border-radius: 14px; padding: 18px; background: #f8fafc; text-align: center; flex: 1; margin: 5px; min-height: 180px; display: flex; flex-direction: column; align-items: center; justify-content: center; opacity: 0.7;">
<div style="font-size: 32px; margin-bottom: 10px; opacity: 0.5;">🧠</div>
<div style="width: 100%;">
<h4 style="margin: 0 0 8px 0; font-size: 16px; color: #94a3b8;">Recall Agent</h4>
<p style="font-size: 13px; color: #cbd5e1; margin-bottom: 12px; line-height: 1.4;">Click "Run OSS Analysis" to activate</p>
<div style="display: flex; justify-content: space-around; margin-bottom: 12px;">
<span style="font-size: 11px; padding: 3px 8px; background: rgba(255, 255, 255, 0.5); border-radius: 6px; color: #cbd5e1; font-weight: 500;">Status: Inactive</span>
</div>
<div style="display: inline-block; padding: 5px 14px; background: #e2e8f0; border-radius: 20px; font-size: 12px; font-weight: bold; color: #64748b; text-transform: uppercase; letter-spacing: 0.5px;">WAITING</div>
</div>
</div>
""")
decision_agent = gr.HTML("""
<div style="border: 2px solid #e2e8f0; border-radius: 14px; padding: 18px; background: #f8fafc; text-align: center; flex: 1; margin: 5px; min-height: 180px; display: flex; flex-direction: column; align-items: center; justify-content: center; opacity: 0.7;">
<div style="font-size: 32px; margin-bottom: 10px; opacity: 0.5;">🎯</div>
<div style="width: 100%;">
<h4 style="margin: 0 0 8px 0; font-size: 16px; color: #94a3b8;">Decision Agent</h4>
<p style="font-size: 13px; color: #cbd5e1; margin-bottom: 12px; line-height: 1.4;">Click "Run OSS Analysis" to activate</p>
<div style="display: flex; justify-content: space-around; margin-bottom: 12px;">
<span style="font-size: 11px; padding: 3px 8px; background: rgba(255, 255, 255, 0.5); border-radius: 6px; color: #cbd5e1; font-weight: 500;">Status: Inactive</span>
</div>
<div style="display: inline-block; padding: 5px 14px; background: #e2e8f0; border-radius: 20px; font-size: 12px; font-weight: bold; color: #64748b; text-transform: uppercase; letter-spacing: 0.5px;">WAITING</div>
</div>
</div>
""")
# OSS vs Enterprise Boundary Visualization
boundary_header = gr.Markdown("### 🎭 OSS vs Enterprise: The Safety Boundary")
with gr.Row():
oss_section = gr.HTML("""
<div style="padding: 20px; border-radius: 14px; margin-bottom: 15px; flex: 1; min-height: 320px; background: #f0f9ff; border: 2px solid #0ea5e9;">
<div style="display: flex; align-items: center; gap: 10px; margin-bottom: 15px; padding-bottom: 12px; border-bottom: 2px solid rgba(0, 0, 0, 0.1);">
<div style="font-size: 28px;">πŸ†“</div>
<h3 style="margin: 0; font-size: 20px; color: #1e293b; flex: 1;">OSS Edition</h3>
<span style="padding: 4px 10px; background: rgba(255, 255, 255, 0.9); border-radius: 8px; font-size: 11px; font-weight: bold; color: #475569;">Apache 2.0</span>
</div>
<div style="margin-bottom: 20px; padding: 12px; background: rgba(255, 255, 255, 0.7); border-radius: 10px;">
<p style="margin: 0; font-size: 14px; color: #475569; font-weight: 500;"><strong>Analysis & Advisory Only</strong> - No execution, permanently safe</p>
</div>
<div style="background: white; border-radius: 12px; padding: 20px; box-shadow: 0 4px 12px rgba(0,0,0,0.05);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; padding-bottom: 10px; border-bottom: 1px solid #f1f5f9;">
<h4 style="margin: 0; font-size: 16px; color: #1e293b;">πŸ“ Healing Intent Created</h4>
<span style="padding: 4px 10px; background: #dbeafe; color: #1d4ed8; border-radius: 6px; font-size: 12px; font-weight: bold;">94% confidence</span>
</div>
<div>
<p style="margin: 8px 0; font-size: 14px; color: #475569;"><strong>Action:</strong> Scale Redis cluster from 3 to 5 nodes</p>
<p style="margin: 8px 0; font-size: 14px; color: #475569;"><strong>Pattern Match:</strong> Similar incident resolved with scaling (87% success rate)</p>
<p style="margin: 8px 0; font-size= 14px; color: #475569;"><strong>Safety Check:</strong> βœ… Passed (blast radius: 2 services)</p>
<p style="margin: 8px 0; font-size: 14px; color: #475569;"><strong>Estimated Impact:</strong> Reduce MTTR from 45min to 12min</p>
</div>
<div style="margin-top: 20px; text-align: center;">
<div style="height: 2px; background: linear-gradient(90deg, transparent, #3b82f6, transparent); margin: 8px 0;"></div>
<div style="font-size: 12px; font-weight: bold; padding: 6px 12px; background: #fee2e2; color: #dc2626; border-radius: 8px; display: inline-block;">🚫 OSS STOPS HERE - No execution</div>
<div style="height: 2px; background: linear-gradient(90deg, transparent, #3b82f6, transparent); margin: 8px 0;"></div>
</div>
</div>
</div>
""")
enterprise_section = gr.HTML("""
<div style="padding: 20px; border-radius: 14px; margin-bottom: 15px; flex: 1; min-height: 320px; background: #f0fdf4; border: 2px solid #10b981;">
<div style="display: flex; align-items: center; gap: 10px; margin-bottom: 15px; padding-bottom: 12px; border-bottom: 2px solid rgba(0, 0, 0, 0.1);">
<div style="font-size: 28px;">πŸ’°</div>
<h3 style="margin: 0; font-size: 20px; color: #1e293b; flex: 1;">Enterprise Edition</h3>
<span style="padding: 4px 10px; background: rgba(255, 255, 255, 0.9); border-radius: 8px; font-size: 11px; font-weight: bold; color: #475569;">Commercial</span>
</div>
<div style="margin-bottom: 20px; padding: 12px; background: rgba(255, 255, 255, 0.7); border-radius: 10px;">
<p style="margin: 0; font-size: 14px; color: #475569; font-weight: 500;"><strong>Full Execution & Learning</strong> - Autonomous healing with safety guarantees</p>
</div>
<div style="background: white; border-radius: 12px; padding: 20px; box-shadow: 0 4px 12px rgba(0,0,0,0.05);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; padding-bottom: 10px; border-bottom: 1px solid #f1f5f9;">
<h4 style="margin: 0; font-size: 16px; color: #1e293b;">⚑ Ready to Execute</h4>
<span style="padding: 4px 10px; background: #10b981; color: white; border-radius: 6px; font-size: 12px; font-weight: bold; text-transform: uppercase;">AUTONOMOUS</span>
</div>
<div>
<p style="margin: 8px 0; font-size: 14px; color: #475569;"><strong>Mode:</strong> Autonomous (Requires Enterprise license)</p>
<p style="margin: 8px 0; font-size: 14px; color: #475569;"><strong>Expected Recovery:</strong> 12 minutes (vs 45 min manual)</p>
<p style="margin: 8px 0; font-size: 14px; color: #475569;"><strong>Cost Saved:</strong> <span style="color: #10b981; font-weight: 700;">$6,375</span></p>
<p style="margin: 8px 0; font-size= 14px; color: #475569;"><strong>Users Protected:</strong> 45,000 β†’ 0 impacted</p>
</div>
<div style="margin-top: 20px; text-align: center;">
<div style="height: 2px; background: linear-gradient(90deg, transparent, #10b981, transparent); margin: 8px 0;"></div>
<div style="font-size: 12px; font-weight: bold; padding: 6px 12px; background: #dcfce7; color: #166534; border-radius: 8px; display: inline-block;">βœ… Enterprise executes with MCP safety</div>
<div style="height: 2px; background: linear-gradient(90deg, transparent, #10b981, transparent); margin: 8px 0;"></div>
</div>
</div>
</div>
""")
# Execution Controls
with gr.Row():
with gr.Column(scale=1):
oss_btn = gr.Button(
"πŸ†“ Run OSS Analysis",
variant="secondary",
size="lg"
)
oss_info = gr.Markdown("*Free, open-source analysis*")
with gr.Column(scale=1):
enterprise_btn = gr.Button(
"πŸ’° Execute Enterprise Healing",
variant="primary",
size="lg"
)
enterprise_info = gr.Markdown("*Requires Enterprise license*")
# Mode Selection & Safety Controls
with gr.Row():
with gr.Column(scale=1):
approval_toggle = gr.CheckboxGroup(
choices=["πŸ‘€ Require Human Approval"],
label="Safety Controls",
value=[],
info="Toggle human oversight"
)
with gr.Column(scale=2):
mcp_mode = gr.Radio(
choices=["πŸ›‘οΈ Advisory (OSS Only)", "πŸ‘₯ Approval", "⚑ Autonomous"],
value="πŸ›‘οΈ Advisory (OSS Only)",
label="MCP Safety Mode",
info="Control execution safety level",
interactive=True
)
# Timeline visualization
timeline_header = gr.Markdown("### ⏰ Incident Timeline")
timeline_viz = gr.Plot(
label="",
show_label=False,
elem_id="timeline_plot"
)
# ============ NEW: Realism Panel Section ============
realism_header = gr.Markdown("### 🎭 Realism: Trade-offs & Uncertainty")
realism_panel = gr.HTML(
value="""<div style="text-align: center; padding: 30px; color: #64748b;">
<div style="font-size: 48px; margin-bottom: 10px;">πŸ”§</div>
<h4 style="margin: 0 0 10px 0;">Realism Panel</h4>
<p style="margin: 0;">Select a scenario to see ranked actions, risks, and trade-offs</p>
</div>""",
elem_id="realism_panel"
)
# Right Column: Results & Metrics
with gr.Column(scale=1, variant="panel") as right_col:
# Real-time Metrics Dashboard
metrics_header = gr.Markdown("## πŸ“Š Performance Metrics")
# Metric Cards Grid - USING INLINE STYLES
with gr.Row():
detection_time = gr.HTML("""
<div style="border: 1px solid #e2e8f0; border-radius: 12px; padding: 18px; background: white; margin: 8px; text-align: center; flex: 1; min-width: 140px; border-left: 4px solid #3b82f6;">
<div style="font-size: 28px; margin-bottom: 10px;">⏱️</div>
<div>
<h4 style="margin: 0 0 8px 0; font-size: 14px; color: #64748b; font-weight: 600;">Detection Time</h4>
<p style="font-size: 28px; font-weight: bold; color: #1e40af; margin: 8px 0;">45s</p>
<p style="font-size: 12px; color: #64748b; margin: 0;">↓ 89% faster than average</p>
</div>
</div>
""")
mttr = gr.HTML("""
<div style="border: 1px solid #e2e8f0; border-radius: 12px; padding: 18px; background: white; margin: 8px; text-align: center; flex: 1; min-width: 140px; border-left: 4px solid #10b981;">
<div style="font-size: 28px; margin-bottom: 10px;">⚑</div>
<div>
<h4 style="margin: 0 0 8px 0; font-size: 14px; color: #64748b; font-weight: 600;">Mean Time to Resolve</h4>
<p style="font-size: 28px; font-weight: bold; color: #10b981; margin: 8px 0;">12m</p>
<p style="font-size: 12px; color: #64748b; margin: 0;">↓ 73% faster than manual</p>
</div>
</div>
""")
with gr.Row():
auto_heal = gr.HTML("""
<div style="border: 1px solid #e2e8f0; border-radius: 12px; padding: 18px; background: white; margin: 8px; text-align: center; flex: 1; min-width: 140px; border-left: 4px solid #8b5cf6;">
<div style="font-size: 28px; margin-bottom: 10px;">πŸ€–</div>
<div>
<h4 style="margin: 0 0 8px 0; font-size: 14px; color: #64748b; font-weight: 600;">Auto-Heal Rate</h4>
<p style="font-size: 28px; font-weight: bold; color: #8b5cf6; margin: 8px 0;">81.7%</p>
<p style="font-size: 12px; color: #64748b; margin: 0;">↑ 5.4Γ— industry average</p>
</div>
</div>
""")
savings = gr.HTML(f"""
<div style="border: 1px solid #e2e8f0; border-radius: 12px; padding: 18px; background: white; margin: 8px; text-align: center; flex: 1; min-width: 140px; border-left: 4px solid #f59e0b;">
<div style="font-size: 28px; margin-bottom: 10px;">πŸ’°</div>
<div>
<h4 style="margin: 0 0 8px 0; font-size: 14px; color: #64748b; font-weight: 600;">Cost Saved</h4>
<p style="font-size: 28px; font-weight: bold; color: #f59e0b; margin: 8px 0;">${int(business_impact.get('revenue_loss_per_hour', 8500) * 0.85 / 1000):.1f}K</p>
<p style="font-size: 12px; color: #64748b; margin: 0;">Per incident avoided</p>
</div>
</div>
""")
# Results Display Areas
oss_results_header = gr.Markdown("### πŸ†“ OSS Analysis Results")
oss_results_display = gr.JSON(
label="",
value={
"status": "Analysis Pending",
"agents": ["Detection", "Recall", "Decision"],
"mode": "Advisory Only",
"action": "Generate HealingIntent"
},
height=200
)
enterprise_results_header = gr.Markdown("### πŸ’° Enterprise Results")
enterprise_results_display = gr.JSON(
label="",
value={
"status": "Execution Pending",
"requires_license": True,
"available_modes": ["Approval", "Autonomous"],
"expected_outcome": "12m MTTR, $6.3K saved"
},
height=200
)
# Approval Status - USING INLINE STYLES
approval_display = gr.HTML("""
<div style="border: 2px solid #e2e8f0; border-radius: 14px; padding: 20px; background: white; margin-top: 20px;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; padding-bottom: 12px; border-bottom: 2px solid #f1f5f9;">
<h4 style="margin: 0; font-size: 16px; color: #1e293b;">πŸ‘€ Human Approval Status</h4>
<span style="padding: 4px 12px; background: #10b981; color: white; border-radius: 8px; font-size: 12px; font-weight: bold; text-transform: uppercase;">Not Required</span>
</div>
<div style="margin-top: 15px;">
<p style="margin: 8px 0; font-size: 14px; color: #475569;"><strong>Current Mode:</strong> Advisory (OSS Only)</p>
<p style="margin: 8px 0; font-size: 14px; color: #475569; font-style: italic;">Switch to "Approval" mode to enable human-in-the-loop workflows</p>
<div style="display: flex; flex-direction: column; gap: 10px; margin-top: 20px;">
<div style="padding: 12px; background: #f8fafc; border-radius: 10px; border-left: 4px solid #3b82f6; font-size: 14px; color: #475569; font-weight: 500;">1. ARF generates intent</div>
<div style="padding: 12px; background: #f8fafc; border-radius: 10px; border-left: 4px solid #3b82f6; font-size: 14px; color: #475569; font-weight: 500;">2. Human reviews & approves</div>
<div style="padding: 12px; background: #f8fafc; border-radius: 10px; border-left: 4px solid #3b82f6; font-size: 14px; color: #475569; font-weight: 500;">3. ARF executes safely</div>
</div>
</div>
</div>
""")
# Demo Actions
demo_btn = gr.Button(
"▢️ Run Complete Demo Walkthrough",
variant="secondary",
size="lg"
)
demo_info = gr.Markdown("*Experience the full ARF workflow from detection to resolution*")
return (
# Left column returns
scenario_dropdown, scenario_card, telemetry_viz, impact_viz,
# Middle column returns (WITH REALISM PANEL)
workflow_header, detection_agent, recall_agent, decision_agent,
oss_section, enterprise_section, oss_btn, enterprise_btn,
approval_toggle, mcp_mode, timeline_viz, realism_panel,
# Right column returns
detection_time, mttr, auto_heal, savings,
oss_results_display, enterprise_results_display, approval_display, demo_btn
)
# -----------------------------
# Tab 2: Business ROI - Updated
# -----------------------------
def create_tab2_business_roi(scenarios=INCIDENT_SCENARIOS) -> tuple:
dashboard_output = gr.Plot(label="Executive Dashboard", show_label=True)
roi_scenario_dropdown = gr.Dropdown(
choices=list(scenarios.keys()),
value="Cache Miss Storm",
label="Scenario for ROI Analysis",
info="Select the primary incident type for ROI calculation"
)
monthly_slider = gr.Slider(
minimum=1,
maximum=50,
value=15,
step=1,
label="Monthly Incidents",
info="Average number of incidents per month"
)
team_slider = gr.Slider(
minimum=1,
maximum=50,
value=5,
step=1,
label="Team Size",
info="Number of engineers on reliability team"
)
calculate_btn = gr.Button("πŸ“Š Calculate Comprehensive ROI", variant="primary", size="lg")
roi_output = gr.JSON(label="ROI Analysis Results", value={})
roi_chart = gr.Plot(label="ROI Visualization")
return (dashboard_output, roi_scenario_dropdown, monthly_slider, team_slider,
calculate_btn, roi_output, roi_chart)
# -----------------------------
# Tab 3: Enterprise Features - UPDATED WITH INSTALLATION STATUS
# -----------------------------
def create_tab3_enterprise_features() -> tuple:
# Get installation status
try:
from app import get_installation_status
installation = get_installation_status()
license_data = {
"status": "βœ… OSS Installed" if installation["oss_installed"] else "⚠️ OSS Not Installed",
"oss_version": installation["oss_version"] or "Not installed",
"enterprise_installed": installation["enterprise_installed"],
"enterprise_version": installation["enterprise_version"] or "Not installed",
"execution_allowed": installation["execution_allowed"],
"recommendations": installation["recommendations"],
"badges": installation["badges"]
}
# Update features table based on installation
features_data = [
["ARF OSS Package", "βœ… Installed" if installation["oss_installed"] else "❌ Not Installed", "OSS"],
["Self-Healing Core", "βœ… Active", "Enterprise"],
["RAG Graph Memory", "βœ… Active", "Both"],
["Predictive Analytics", "πŸ”’ Enterprise" if not installation["enterprise_installed"] else "βœ… Available", "Enterprise"],
["Audit Trail", "πŸ”’ Enterprise" if not installation["enterprise_installed"] else "βœ… Available", "Enterprise"],
["Compliance (SOC2)", "πŸ”’ Enterprise" if not installation["enterprise_installed"] else "βœ… Available", "Enterprise"]
]
except ImportError:
# Fallback if installation check fails
license_data = {
"status": "⚠️ Installation Check Failed",
"oss_version": "Unknown",
"enterprise_installed": False,
"recommendations": ["Run installation check"]
}
features_data = [
["Self-Healing Core", "βœ… Active", "Enterprise"],
["RAG Graph Memory", "βœ… Active", "Both"],
["Predictive Analytics", "πŸ”’ Enterprise", "Enterprise"],
["Audit Trail", "πŸ”’ Enterprise", "Enterprise"],
["Compliance (SOC2)", "πŸ”’ Enterprise", "Enterprise"],
["Multi-Cloud", "πŸ”’ Enterprise", "Enterprise"]
]
license_display = gr.JSON(
value=license_data,
label="πŸ“¦ Package Installation Status"
)
validate_btn = gr.Button("πŸ” Validate Installation", variant="secondary")
trial_btn = gr.Button("πŸ†“ Start 30-Day Trial", variant="secondary")
upgrade_btn = gr.Button("πŸš€ Upgrade to Enterprise", variant="primary")
mcp_mode = gr.Dropdown(
choices=["advisory", "approval", "autonomous"],
value="advisory",
label="MCP Safety Mode"
)
# Initial mode info
mcp_mode_info = gr.JSON(
value={
"current_mode": "advisory",
"description": "OSS Edition - Analysis only, no execution",
"features": ["Incident analysis", "RAG similarity", "HealingIntent creation"],
"package": "agentic-reliability-framework==3.3.7",
"license": "Apache 2.0"
},
label="Mode Details"
)
integrations_data = [
["Prometheus", "βœ… Connected", "Monitoring"],
["Grafana", "βœ… Connected", "Visualization"],
["Slack", "πŸ”’ Enterprise", "Notifications"],
["PagerDuty", "πŸ”’ Enterprise", "Alerting"],
["Jira", "πŸ”’ Enterprise", "Ticketing"],
["Datadog", "πŸ”’ Enterprise", "Monitoring"]
]
features_table = gr.Dataframe(
headers=["Feature", "Status", "Edition"],
value=features_data,
label="Feature Comparison"
)
integrations_table = gr.Dataframe(
headers=["Integration", "Status", "Type"],
value=integrations_data,
label="Integration Status"
)
return (license_display, validate_btn, trial_btn, upgrade_btn,
mcp_mode, mcp_mode_info, features_table, integrations_table)
# -----------------------------
# Tab 4: Audit Trail
# -----------------------------
def create_tab4_audit_trail() -> tuple:
refresh_btn = gr.Button("πŸ”„ Refresh Audit Trail", variant="secondary")
clear_btn = gr.Button("πŸ—‘οΈ Clear History", variant="secondary")
export_btn = gr.Button("πŸ“₯ Export as JSON", variant="primary")
execution_headers = ["Time", "Scenario", "Mode", "Status", "Savings", "Details"]
incident_headers = ["Time", "Component", "Scenario", "Severity", "Status"]
execution_table = gr.Dataframe(
headers=execution_headers,
value=[],
label="Execution History"
)
incident_table = gr.Dataframe(
headers=incident_headers,
value=[],
label="Incident History"
)
export_text = gr.JSON(
value={"status": "Export ready"},
label="Export Data"
)
return (refresh_btn, clear_btn, export_btn, execution_table, incident_table, export_text)
# -----------------------------
# Tab 5: Learning Engine
# -----------------------------
def create_tab5_learning_engine() -> tuple:
learning_graph = gr.Plot(label="RAG Memory Graph")
graph_type = gr.Dropdown(
choices=["Incident Patterns", "Action-Outcome Chains", "System Dependencies"],
value="Incident Patterns",
label="Graph Type"
)
show_labels = gr.Checkbox(label="Show Labels", value=True)
search_query = gr.Textbox(label="Search Patterns", placeholder="Enter pattern to search...")
search_btn = gr.Button("πŸ” Search Patterns", variant="secondary")
clear_btn_search = gr.Button("πŸ—‘οΈ Clear Search", variant="secondary")
search_results = gr.JSON(
value={"status": "Ready for search"},
label="Search Results"
)
stats_display = gr.JSON(
value={"patterns": 42, "incidents": 156, "success_rate": "87.3%"},
label="Learning Statistics"
)
patterns_display = gr.JSON(
value={"common_patterns": ["cache_storm", "db_pool", "memory_leak"]},
label="Pattern Library"
)
performance_display = gr.JSON(
value={"accuracy": "94.2%", "recall": "89.7%", "precision": "92.1%"},
label="Agent Performance"
)
return (learning_graph, graph_type, show_labels, search_query, search_btn,
clear_btn_search, search_results, stats_display, patterns_display, performance_display)
# -----------------------------
# Realism Panel Component
# -----------------------------
def create_realism_panel(scenario_data: Dict, scenario_name: str) -> gr.HTML:
"""
Create a realism panel showing ranked actions, risks, and uncertainty.
This makes ARF look cautious, opinionated, and enterprise-seasoned.
"""
realism = scenario_data.get("realism", {})
ranked_actions = realism.get("ranked_actions", [])
# Build ranked actions HTML
actions_html = ""
for action in ranked_actions:
rank_color = "#10b981" if action["rank"] == 1 else "#f59e0b" if action["rank"] == 2 else "#ef4444"
status = "βœ… RECOMMENDED" if action["rank"] == 1 else "🟑 SECONDARY" if action["rank"] == 2 else "πŸ”΄ REJECTED"
actions_html += f"""
<div style="border: 2px solid {rank_color}; border-radius: 12px; padding: 16px;
background: {rank_color}10; margin-bottom: 12px;">
<div style="display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 10px;">
<div>
<div style="display: flex; align-items: center; gap: 10px; margin-bottom: 5px;">
<div style="width: 24px; height: 24px; background: {rank_color};
color: white; border-radius: 50%; display: flex; align-items: center;
justify-content: center; font-size: 12px; font-weight: bold;">
{action['rank']}
</div>
<span style="font-size: 14px; font-weight: 600; color: #1e293b;">
{status} β€’ {action['confidence']}% confidence
</span>
</div>
<p style="font-size: 14px; color: #475569; margin: 8px 0; font-weight: 500;">
{action['action']}
</p>
</div>
<div style="padding: 6px 12px; background: {rank_color}20; border-radius: 20px;
font-size: 12px; font-weight: bold; color: {rank_color};">
{action['confidence']}%
</div>
</div>
<div style="font-size: 13px; color: #64748b; margin: 8px 0; line-height: 1.5;">
<strong>Rationale:</strong> {action.get('rationale', 'No rationale provided')}
</div>
{"<div style='font-size: 13px; color: #dc2626; margin: 8px 0; padding: 8px; background: #fef2f2; border-radius: 6px; border-left: 3px solid #dc2626;'><strong>⚠️ Risk:</strong> " + action['risk'] + "</div>" if action.get('risk') else ""}
{"<div style='font-size: 13px; color: #92400e; margin: 8px 0; padding: 8px; background: #fffbeb; border-radius: 6px; border-left: 3px solid #f59e0b;'><strong>πŸ”„ Trade-off:</strong> " + action['tradeoff'] + "</div>" if action.get('tradeoff') else ""}
{"<div style='font-size: 13px; color: #b45309; margin: 8px 0; padding: 8px; background: #fef3c7; border-radius: 6px; border-left: 3px solid #f59e0b;'><strong>⏱️ Execution:</strong> " + action['execution_time'] + "</div>" if action.get('execution_time') else ""}
{"<div style='font-size: 13px; color: #b91c1c; margin: 8px 0; padding: 8px; background: #fee2e2; border-radius: 6px; border-left: 3px solid #ef4444;'><strong>🚫 Rejected:</strong> " + action['rejection_reason'] + "</div>" if action.get('rejection_reason') else ""}
{"<div style='font-size: 13px; color: #7c3aed; margin: 8px 0; padding: 8px; background: #f5f3ff; border-radius: 6px; border-left: 3px solid #8b5cf6;'><strong>πŸ›‘οΈ Safety:</strong> " + action['safety_override'] + "</div>" if action.get('safety_override') else ""}
</div>
"""
# Build competing hypotheses (for Network Partition scenario)
hypotheses_html = ""
if realism.get("competing_hypotheses"):
hypotheses_html = """
<div style="margin-top: 20px; padding-top: 20px; border-top: 2px solid #e2e8f0;">
<div style="font-size: 15px; font-weight: 600; color: #1e293b; margin-bottom: 15px;">
🧠 Competing Hypotheses
</div>
"""
for hypo in realism["competing_hypotheses"]:
hypotheses_html += f"""
<div style="display: flex; align-items: center; gap: 15px; margin-bottom: 12px; padding: 12px;
background: #f8fafc; border-radius: 8px;">
<div style="font-size: 24px; color: #3b82f6;">?</div>
<div style="flex: 1;">
<div style="font-size: 14px; font-weight: 500; color: #1e293b; margin-bottom: 4px;">
{hypo['cause']} ({hypo['confidence']}%)
</div>
<div style="font-size: 12px; color: #64748b; margin-bottom: 6px;">
{hypo['evidence']}
</div>
<div style="font-size: 11px; color: #475569; font-weight: 500;">
Investigation: {hypo['investigation_path']}
</div>
</div>
<div style="width: 60px; height: 60px; background: conic-gradient(#3b82f6 0% {hypo['confidence']}%, #e2e8f0 {hypo['confidence']}% 100%);
border-radius: 50%; display: flex; align-items: center; justify-content: center;">
<div style="width: 50px; height: 50px; background: white; border-radius: 50%;
display: flex; align-items: center; justify-content: center; font-size: 14px; font-weight: bold; color: #1e293b;">
{hypo['confidence']}%
</div>
</div>
</div>
"""
hypotheses_html += "</div>"
# Build risk assessment panel
risk_html = ""
if realism.get("risk_assessment"):
risk_html = """
<div style="margin-top: 20px; padding-top: 20px; border-top: 2px solid #e2e8f0;">
<div style="font-size: 15px; font-weight: 600; color: #1e293b; margin-bottom: 15px;">
⚠️ Risk Assessment
</div>
<div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px;">
"""
for key, value in realism["risk_assessment"].items():
risk_html += f"""
<div style="padding: 12px; background: #f8fafc; border-radius: 8px; border-left: 4px solid #f59e0b;">
<div style="font-size: 12px; color: #64748b; text-transform: uppercase; margin-bottom: 4px;">
{key.replace('_', ' ').title()}
</div>
<div style="font-size: 14px; font-weight: 600; color: #92400e;">
{value}
</div>
</div>
"""
risk_html += "</div></div>"
# Build confidence degradation panel
confidence_html = ""
if realism.get("confidence_degradation"):
conf = realism["confidence_degradation"]
confidence_html = f"""
<div style="margin-top: 20px; padding-top: 20px; border-top: 2px solid #e2e8f0;">
<div style="font-size: 15px; font-weight: 600; color: #1e293b; margin-bottom: 15px;">
⏱️ Confidence Degradation Over Time
</div>
<div style="background: #f8fafc; border-radius: 10px; padding: 20px;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
<div style="text-align: center;">
<div style="font-size: 28px; font-weight: 700; color: #10b981;">{conf['initial']}%</div>
<div style="font-size: 12px; color: #64748b;">Initial Confidence</div>
</div>
<div style="font-size: 24px; color: #94a3b8;">β†’</div>
<div style="text-align: center;">
<div style="font-size: 28px; font-weight: 700; color: #f59e0b;">{conf['after_8_min']}%</div>
<div style="font-size: 12px; color: #64748b;">After 8 minutes</div>
</div>
<div style="font-size: 24px; color: #94a3b8;">β†’</div>
<div style="text-align: center;">
<div style="font-size: 28px; font-weight: 700; color: #ef4444;">{conf['after_15_min']}%</div>
<div style="font-size: 12px; color: #64748b;">After 15 minutes</div>
</div>
</div>
<div style="height: 10px; background: #e2e8f0; border-radius: 5px; margin: 20px 0; position: relative;">
<div style="position: absolute; left: 0; width: 100%; height: 100%; background: linear-gradient(90deg, #10b981, #f59e0b, #ef4444); border-radius: 5px;"></div>
<div style="position: absolute; left: {conf['escalation_threshold']}%; top: -5px; width: 2px; height: 20px; background: #1e293b;"></div>
<div style="position: absolute; left: {conf['escalation_threshold']}%; top: 25px; font-size: 11px; color: #64748b; transform: translateX(-50%);">
Escalation at {conf['escalation_threshold']}%
</div>
</div>
<div style="padding: 12px; background: #fef3c7; border-radius: 8px; border-left: 4px solid #f59e0b;">
<div style="font-size: 13px; color: #92400e; font-weight: 500;">
⚠️ ARF escalates to human operators when confidence drops below {conf['escalation_threshold']}%
</div>
<div style="font-size: 12px; color: #b45309; margin-top: 5px;">
This prevents autonomous execution in high-uncertainty scenarios
</div>
</div>
</div>
</div>
"""
# Build "What ARF Will NOT Do" panel (global)
wont_do_html = """
<div style="margin-top: 20px; padding-top: 20px; border-top: 2px solid #e2e8f0;">
<div style="font-size: 15px; font-weight: 600; color: #1e293b; margin-bottom: 15px;">
🚫 What ARF Will NOT Do (Safety Boundaries)
</div>
<div style="background: linear-gradient(135deg, #fef2f2 0%, #fee2e2 100%);
border: 2px solid #ef4444; border-radius: 12px; padding: 20px;">
<div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 15px;">
<div style="display: flex; align-items: flex-start; gap: 10px;">
<div style="font-size: 20px; color: #ef4444;">β›”</div>
<div>
<div style="font-size: 14px; font-weight: 600; color: #7f1d1d;">Restart stateful leaders</div>
<div style="font-size: 12px; color: #b91c1c;">During peak traffic or elections</div>
</div>
</div>
<div style="display: flex; align-items: flex-start; gap: 10px;">
<div style="font-size: 20px; color: #ef4444;">β›”</div>
<div>
<div style="font-size: 14px; font-weight: 600; color: #7f1d1d;">Apply schema changes</div>
<div style="font-size: 12px; color: #b91c1c;">To production databases autonomously</div>
</div>
</div>
<div style="display: flex; align-items: flex-start; gap: 10px;">
<div style="font-size: 20px; color: #ef4444;">β›”</div>
<div>
<div style="font-size: 14px; font-weight: 600; color: #7f1d1d;">Exceed API limits</div>
<div style="font-size: 12px; color: #b91c1c;">Contractual or rate limits</div>
</div>
</div>
<div style="display: flex; align-items: flex-start; gap: 10px;">
<div style="font-size: 20px; color: #ef4444;">β›”</div>
<div>
<div style="font-size: 14px; font-weight: 600; color: #7f1d1d;">Modify ACLs/RBAC</div>
<div style="font-size: 12px; color: #b91c1c;">Security permissions autonomously</div>
</div>
</div>
</div>
<div style="margin-top: 15px; padding: 12px; background: rgba(255, 255, 255, 0.7);
border-radius: 8px; border-left: 4px solid #dc2626;">
<div style="font-size: 13px; color: #7f1d1d; font-weight: 500;">
These boundaries ensure ARF operates within safe, reversible limits.
Enterprise edition adds approval workflows for edge cases.
</div>
</div>
</div>
</div>
"""
# Combine all panels
full_html = f"""
<div style="border: 2px solid #3b82f6; border-radius: 16px; padding: 25px;
background: linear-gradient(135deg, #f0f9ff 0%, #ffffff 100%);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
<div>
<h3 style="margin: 0 0 8px 0; font-size: 18px; color: #1e293b; font-weight: 700;">
🎯 Ranked Healing Intents
</h3>
<p style="margin: 0; font-size: 13px; color: #64748b;">
ARF evaluates multiple options with confidence scores and risk assessments
</p>
</div>
<div style="padding: 8px 16px; background: #dbeafe; color: #1e40af;
border-radius: 20px; font-size: 12px; font-weight: bold;">
REALISM UPGRADE v3.3.9+
</div>
</div>
{actions_html}
{hypotheses_html}
{risk_html}
{confidence_html}
{wont_do_html}
<!-- ROI as Ranges -->
<div style="margin-top: 20px; padding-top: 20px; border-top: 2px solid #e2e8f0;">
<div style="font-size: 15px; font-weight: 600; color: #1e293b; margin-bottom: 15px;">
πŸ“ˆ Realistic ROI Estimates (Ranges)
</div>
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 15px;">
<div style="text-align: center; padding: 15px; background: #f8fafc; border-radius: 10px;">
<div style="font-size: 16px; font-weight: 700; color: #10b981;">$5.8K – $7.2K</div>
<div style="font-size: 12px; color: #64748b;">Cost Avoided</div>
<div style="font-size: 11px; color: #94a3b8; margin-top: 5px;">Estimated range</div>
</div>
<div style="text-align: center; padding: 15px; background: #f8fafc; border-radius: 10px;">
<div style="font-size: 16px; font-weight: 700; color: #10b981;">4.8Γ— – 5.6Γ—</div>
<div style="font-size: 12px; color: #64748b;">ROI Multiplier</div>
<div style="font-size: 11px; color: #94a3b8; margin-top: 5px;">Confidence interval</div>
</div>
<div style="text-align: center; padding: 15px; background: #f8fafc; border-radius: 10px;">
<div style="font-size: 16px; font-weight: 700; color: #10b981;">68% – 87%</div>
<div style="font-size: 12px; color: #64748b;">Success Rate</div>
<div style="font-size: 11px; color: #94a3b8; margin-top: 5px;">Based on similar incidents</div>
</div>
</div>
<div style="margin-top: 15px; padding: 12px; background: #f0fdf4; border-radius: 8px;">
<div style="font-size: 13px; color: #065f46; text-align: center; font-weight: 500;">
πŸ“Š Real systems have ranges, not single-point estimates. ARF shows uncertainty honestly.
</div>
</div>
</div>
<!-- Engineering Insight -->
<div style="margin-top: 20px; padding: 20px; background: #f8fafc; border-radius: 12px;
border-left: 4px solid #3b82f6;">
<div style="display: flex; align-items: flex-start; gap: 15px;">
<div style="font-size: 32px;">🎭</div>
<div>
<div style="font-size: 14px; font-weight: 600; color: #1e293b; margin-bottom: 8px;">
What Senior SREs Expect at 3 a.m.
</div>
<div style="font-size: 13px; color: #475569; line-height: 1.6;">
"Real systems hesitate. Real systems explain risk. Real systems earn trust.
ARF shows multiple options with confidence scores because in production,
there's never a single perfect answerβ€”just trade-offs managed carefully."
</div>
</div>
</div>
</div>
</div>
"""
return gr.HTML(full_html)
# -----------------------------
# Footer
# -----------------------------
def create_footer() -> gr.HTML:
return gr.HTML("""
<div style="text-align: center; padding: 25px; color: #6b7280; font-size: 14px; margin-top: 40px; border-top: 2px solid #e5e7eb; background: #f9fafb; border-radius: 12px;">
<p><strong style="color: #1e293b; font-size: 16px;">Agentic Reliability Framework</strong> Β© 2025</p>
<p>Production-grade multi-agent AI for autonomous system reliability intelligence</p>
<div style="margin-top: 15px; display: flex; justify-content: center; gap: 20px; flex-wrap: wrap;">
<a href="https://github.com/petterjuan/agentic-reliability-framework" target="_blank" style="color: #3b82f6; text-decoration: none; font-weight: 500;">GitHub</a> β€’
<a href="https://huggingface.co/spaces/petter2025/agentic-reliability-framework" target="_blank" style="color: #3b82f6; text-decoration: none; font-weight: 500;">Demo</a> β€’
<a href="https://pypi.org/project/agentic-reliability-framework" target="_blank" style="color: #3b82f6; text-decoration: none; font-weight: 500;">PyPI</a> β€’
<a href="mailto:sales@arf.dev" style="color: #3b82f6; text-decoration: none; font-weight: 500;">Enterprise Inquiries</a>
</div>
</div>
""")