diff --git a/llm_team_ui.py b/llm_team_ui.py
index 65810f7..d1b993f 100644
--- a/llm_team_ui.py
+++ b/llm_team_ui.py
@@ -3385,8 +3385,12 @@ LAB_HTML = r"""
Your Experiments
+
+
Self-Analysis AI reports from your own system data
+
+
-
Templates click to auto-fill the create form
+
Experiment Templates click to auto-fill the create form
@@ -3797,6 +3801,80 @@ var LAB_TEMPLATES = [
}
];
+// ─── SELF-ANALYSIS REPORTS ───
+var SELF_REPORTS = [
+ {id:'threat_intel', name:'Threat Intelligence Report', desc:'Analyze security logs to identify attack patterns, profile attackers, predict next moves, and recommend defenses', icon:'shield'},
+ {id:'model_performance', name:'Model Performance Analysis', desc:'Analyze your 96 team runs to find which models perform best at which tasks and where to optimize', icon:'chart'},
+ {id:'access_patterns', name:'Usage Analytics', desc:'Analyze nginx logs to understand traffic patterns, feature usage, user journeys, and UX opportunities', icon:'eye'},
+ {id:'security_posture', name:'Security Posture Assessment', desc:'Combined audit of security logs, sentinel verdicts, fail2ban status, and threat intel DB — overall risk rating', icon:'lock'}
+];
+
+function renderSelfReports() {
+ var container = document.getElementById('self-reports');
+ if (!container) return;
+ container.textContent = '';
+ SELF_REPORTS.forEach(function(r) {
+ var card = document.createElement('div');
+ card.style.cssText = 'background:rgba(0,0,0,0.25);border:2px solid rgba(74,222,128,0.2);border-radius:2px;padding:12px;cursor:pointer;transition:all 0.15s;display:flex;align-items:center;gap:12px';
+ card.onmouseenter = function(){card.style.borderColor='var(--green)'};
+ card.onmouseleave = function(){card.style.borderColor='rgba(74,222,128,0.2)'};
+ card.onclick = function(){runSelfReport(r.id, card)};
+ var info = document.createElement('div'); info.style.flex = '1';
+ var name = document.createElement('div');
+ name.style.cssText = 'font-weight:700;font-size:12px;margin-bottom:3px';
+ name.textContent = r.name;
+ var desc = document.createElement('div');
+ desc.style.cssText = 'font-size:11px;color:var(--text2);line-height:1.4';
+ desc.textContent = r.desc;
+ info.appendChild(name); info.appendChild(desc); card.appendChild(info);
+ var btn = document.createElement('span');
+ btn.style.cssText = 'font-family:JetBrains Mono,monospace;font-size:9px;text-transform:uppercase;letter-spacing:1px;color:var(--green);white-space:nowrap';
+ btn.textContent = 'Run →';
+ card.appendChild(btn);
+ container.appendChild(card);
+ });
+}
+
+async function runSelfReport(type, card) {
+ var origBorder = card.style.borderColor;
+ card.style.borderColor = 'var(--green)';
+ var btn = card.querySelector('span:last-child');
+ btn.textContent = 'Analyzing...';
+ btn.style.color = 'var(--accent)';
+ // Find or create result panel
+ var resultId = 'report-' + type;
+ var existing = document.getElementById(resultId);
+ if (existing) existing.remove();
+ try {
+ var r = await fetch('/api/self-analyze', {method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({type:type, model:'qwen2.5:latest'})});
+ var d = await r.json();
+ if (d.error) { toast(d.error, false); return; }
+ var panel = document.createElement('div');
+ panel.id = resultId;
+ panel.style.cssText = 'background:rgba(0,0,0,0.3);border:2px solid var(--green);border-radius:2px;padding:16px;margin-top:8px;max-height:500px;overflow-y:auto';
+ var title = document.createElement('div');
+ title.style.cssText = 'font-family:JetBrains Mono,monospace;font-size:9px;text-transform:uppercase;letter-spacing:1.5px;color:var(--green);margin-bottom:8px;display:flex;justify-content:space-between';
+ title.textContent = type.replace(/_/g,' ') + ' — ' + d.model;
+ var closeBtn = document.createElement('span');
+ closeBtn.style.cssText = 'cursor:pointer;opacity:0.6';
+ closeBtn.textContent = '✕';
+ closeBtn.onclick = function(e){e.stopPropagation();panel.remove()};
+ title.appendChild(closeBtn);
+ panel.appendChild(title);
+ var content = document.createElement('div');
+ content.style.cssText = 'font-size:12px;line-height:1.7;white-space:pre-wrap;color:var(--text)';
+ content.textContent = d.report;
+ panel.appendChild(content);
+ card.parentNode.insertBefore(panel, card.nextSibling);
+ toast('Report generated', true);
+ } catch(e) { toast('Error: '+e.message, false); }
+ btn.textContent = 'Run →';
+ btn.style.color = 'var(--green)';
+ card.style.borderColor = origBorder;
+}
+
+renderSelfReports();
+
function renderTemplates() {
var el = document.getElementById('template-list');
if (!el) return;
@@ -5509,6 +5587,111 @@ loadRuns();