Files
html/sovereign-monitor.html
Opus 9a5f534d8b
Some checks failed
WEVAL NonReg / nonreg (push) Has been cancelled
phase30 doctrine 167 cascade enrich 6 pages - 18 pages UX doctrine 60 total
6 pages centrales enrichies via cascade Cerebras:
- wevia-chat-v2 (+1328B)
- sovereign-monitor (+1271B)
- wevia-audit (+1266B)
- wevia-console (+1263B)
- wevia-autonomy-dashboard (+1292B)
- wevia-business-visual-studio (+1300B)

Handler /var/www/html/api/enrich-hub-cascade.sh:
- Try Cerebras qwen-3-235b primary
- Fallback Ollama llama3.2 LOCAL (zero rate limit)
- GOLD backup + chattr handling + lint
- Markers DOCTRINE-60-UX-ENRICH idempotent

Intent wevia_enrich_hub_cascade_cerebras_ollama wired pour chat NL.
Total: 18 pages UX doctrine 60 (12 avant + 6 aujourd hui).

Cascade zero-rate-limit effective: Cerebras OK + Ollama llama3.2 ready.
Disk 87% stable apres recovery phase 29 +19GB.
2026-04-24 10:44:16 +02:00

516 lines
31 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>WEVAL Realtime Monitor v3</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;600;700&family=Outfit:wght@400;600;700;900&display=swap');
:root{--bg:#06080f;--card:#0c1018;--border:#1a1f2e;--text:#e2e8f0;--dim:#64748b;--green:#10b981;--red:#ef4444;--yellow:#f59e0b;--blue:#3b82f6;--purple:#8b5cf6;--cyan:#06b6d4;--pink:#ec4899;--accent:#6d28d9}
*{margin:0;padding:0;box-sizing:border-box}
body{background:var(--bg);color:var(--text);font-family:'Outfit',sans-serif;overflow-x:hidden}
.header{padding:16px 24px;display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid var(--border);background:linear-gradient(180deg,#0c1018 0%,#06080f 100%)}
.header h1{font-size:20px;font-weight:900;background:linear-gradient(135deg,var(--purple),var(--cyan));-webkit-background-clip:text;-webkit-text-fill-color:transparent}
.header .stats{display:flex;gap:20px;font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--dim)}
.header .stats span{color:var(--green)}
.tabs{display:flex;gap:4px;padding:12px 24px;border-bottom:1px solid var(--border)}
.tab{padding:8px 16px;border-radius:6px;cursor:pointer;font-size:13px;font-weight:600;color:var(--dim);transition:.2s}
.tab:hover{background:var(--card);color:var(--text)}
.tab.active{background:var(--accent);color:#fff}
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:12px;padding:16px 24px}
.card{background:var(--card);border:1px solid var(--border);border-radius:10px;padding:14px;position:relative;transition:.2s}
.card:hover{border-color:var(--accent);transform:translateY(-1px)}
.card .top{display:flex;justify-content:space-between;align-items:center;margin-bottom:8px}
.card .name{font-weight:700;font-size:14px;display:flex;align-items:center;gap:6px}
.card .name .icon{font-size:16px}
.badge{padding:2px 8px;border-radius:4px;font-size:10px;font-weight:700;font-family:'JetBrains Mono',monospace;text-transform:uppercase}
.badge.up{background:#064e3b;color:var(--green)}
.badge.down{background:#450a0a;color:var(--red)}
.badge.idle{background:#422006;color:var(--yellow)}
.badge.agent{background:#1e1b4b;color:var(--purple)}
.badge.mode{background:#083344;color:var(--cyan)}
.card .meta{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--dim);line-height:1.8}
.card .meta b{color:var(--text)}
.section-title{padding:16px 24px 4px;font-size:13px;font-weight:700;text-transform:uppercase;letter-spacing:1px;color:var(--dim);border-top:1px solid var(--border)}
.counter-row{display:flex;gap:12px;padding:12px 24px;flex-wrap:wrap}
.counter{background:var(--card);border:1px solid var(--border);border-radius:10px;padding:14px 20px;text-align:center;min-width:100px;flex:1}
.counter .num{font-size:28px;font-weight:900;font-family:'JetBrains Mono',monospace;background:linear-gradient(135deg,var(--purple),var(--cyan));-webkit-background-clip:text;-webkit-text-fill-color:transparent}
.counter .label{font-size:11px;color:var(--dim);text-transform:uppercase;margin-top:2px}
.pulse{width:8px;height:8px;border-radius:50%;display:inline-block;animation:pulse 2s infinite}
.pulse.green{background:var(--green);box-shadow:0 0 6px var(--green)}
.pulse.red{background:var(--red);box-shadow:0 0 6px var(--red)}
.pulse.yellow{background:var(--yellow);box-shadow:0 0 6px var(--yellow)}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.4}}
#scan-bar{height:2px;background:var(--accent);width:0;transition:width 1s linear;position:fixed;top:0;left:0;z-index:99}
</style>
<!-- DOCTRINE-60-UX-ENRICH cerebras-qwen-235b 20260424-104103 --><style id="doctrine60-ux-sovereign-monitor">
body::before {
content: '';
position: fixed;
width: 100%;
height: 100%;
background: radial-gradient(circle, rgba(0,0,0,0.12), transparent 70%);
z-index: -1;
pointer-events: none;
}
.card, .btn, .kpi, .panel {
opacity: 0;
transform: translateY(20px);
transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}
.enter-stagger {
opacity: 1;
transform: translateY(0);
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.6; }
}
.pulse, .active, .live-indicator, .online {
animation: pulse 3s ease-in-out infinite;
}
.card:hover {
box-shadow: 0 8px 24px rgba(0,0,0,0.15);
border-color: var(--accent);
}
.modal, .chat, .speech, .overlay {
backdrop-filter: blur(12px);
}
</style>
</head>
<body>
<div id="scan-bar"></div>
<div class="header">
<h1>⚡ WEVAL SOVEREIGN COMMAND v3</h1>
<div class="stats">
<div>Scan: <span id="scan-time">...</span>ms</div>
<div>Updated: <span id="update-time">...</span></div>
<div>Refresh: <span>15s</span></div>
</div>
</div>
<div class="counter-row" id="counters"></div>
<div class="tabs">
<div class="tab active" onclick="show('all')">All</div>
<div class="tab" onclick="show('infra')">🏗 Infra</div>
<div class="tab" onclick="show('agents')">🤖 Agents</div>
<div class="tab" onclick="show('modes')">⚡ Modes</div>
<div class="tab" onclick="show('services')">🔧 Services</div>
<div class="tab" onclick="show('data')">📊 Data</div>
<div class="tab" onclick="show('oss')">🌐 OSS</div>
</div>
<div id="content"></div>
<script>
const BASE = '';
const services = [
// === INFRASTRUCTURE ===
{cat:'infra',icon:'💚',name:'WEVIA Brain',url:'/api/weval-chatbot-api.php',check:'status',desc:'Chatbot API souverain'},
{cat:'infra',icon:'🧠',name:'Qdrant Vector DB',url:'/api/health-qdrant.php',check:'status',desc:'RAG 4,414 skills'},
{cat:'infra',icon:'🔍',name:'SearXNG Search',url:'/api/health-searxng.php',check:'status',desc:'Meta-search souverain'},
{cat:'infra',icon:'⚙️',name:'n8n Automation',url:'/api/health-n8n.php',check:'status',desc:'Workflows & crons'},
{cat:'infra',icon:'💬',name:'Mattermost',url:'/api/health-mm.php',check:'status',desc:'Team chat + webhooks'},
{cat:'infra',icon:'📊',name:'Twenty CRM',url:'/api/health-twenty.php',check:'status',desc:'CRM pipeline contacts'},
{cat:'infra',icon:'📈',name:'Plausible Analytics',url:'/api/health-plausible.php',check:'status',desc:'Analytics GDPR'},
{cat:'infra',icon:'👁️',name:'Uptime Kuma',url:'/api/health-kuma.php',check:'status',desc:'Monitoring 9 endpoints'},
{cat:'infra',icon:'🐳',name:'Docker Engine',check:'static',status:'up',desc:'19 containers',meta:'images: 17'},
{cat:'infra',icon:'🌐',name:'Nginx Gateway',check:'static',status:'up',desc:'SSL + 172 req/day',meta:'http2: yes'},
{cat:'infra',icon:'📧',name:'PMTA Mail',check:'static',status:'idle',desc:'Port 25 STANDBY',meta:'Hetzner anti-spam'},
{cat:'infra',icon:'🔒',name:'Authentik SSO',check:'static',status:'up',desc:'2 users, 38 auth/day'},
// === AI SERVICES ===
{cat:'services',icon:'🤖',name:'Ollama S151',url:'/api/health-ollama.php',check:'status',desc:'5 models local CPU'},
{cat:'services',icon:'🖥️',name:'Open WebUI',check:'static',status:'up',desc:'Chat UI :8281',meta:'Ollama frontend'},
{cat:'services',icon:'🔀',name:'Flowise',check:'static',status:'up',desc:'LLM Workflows :3033'},
{cat:'services',icon:'📎',name:'Paperclip CEO',check:'static',status:'up',desc:'Sovereign AI agent',meta:'WEVIA Brain'},
{cat:'services',icon:'🦌',name:'DeerFlow Research',check:'static',status:'up',desc:'113 skills :3002'},
{cat:'services',icon:'🐟',name:'MiroFish',check:'static',status:'up',desc:'AI Fish :3050+:5001'},
{cat:'services',icon:'🖥️',name:'WEVCODE',check:'static',status:'up',desc:'4 modes fast/deep/code/math'},
{cat:'services',icon:'🔧',name:'WEDROID v5',check:'static',status:'up',desc:'7 providers backend diag'},
{cat:'services',icon:'💊',name:'Ethica HCP',check:'static',status:'up',desc:'131K+ HCPs MA/TN/DZ'},
{cat:'services',icon:'📧',name:'WEVIA Life Email',check:'static',status:'up',desc:'Eisenhower triage'},
{cat:'services',icon:'🗡️',name:'Blade Sentinel',url:'/api/blade-api.php?k=BLADE2026&action=status',check:'blade',desc:'Razer Blade v2.2'},
{cat:'services',icon:'🔊',name:'TTS Voice',check:'static',status:'idle',desc:'espeak/pico2wave'},
{cat:'services',icon:'📊',name:'Mermaid Diagrams',check:'static',status:'up',desc:'mmdc server-side'},
{cat:'services',icon:'🧪',name:'Playwright Tests',check:'static',status:'up',desc:'41/41 E2E pass'},
{cat:'services',icon:'📜',name:'L99 Command Center',check:'static',status:'up',desc:'250 tests, 13 layers'},
{cat:'services',icon:'🔄',name:'Claude Sync',check:'static',status:'up',desc:'23 transcripts 21.4MB'},
// === 19 AGENTS (oh-my-claudecode) ===
{cat:'agents',icon:'🏗️',name:'Agent: Architect',check:'static',status:'up',desc:'System design & API patterns',badge:'agent'},
{cat:'agents',icon:'🐛',name:'Agent: Debugger',check:'static',status:'up',desc:'Bug tracing & root cause',badge:'agent'},
{cat:'agents',icon:'👀',name:'Agent: Code Reviewer',check:'static',status:'up',desc:'Security & best practices',badge:'agent'},
{cat:'agents',icon:'✂️',name:'Agent: Code Simplifier',check:'static',status:'up',desc:'Refactoring & cleanup',badge:'agent'},
{cat:'agents',icon:'🎯',name:'Agent: Critic',check:'static',status:'up',desc:'Quality assessment',badge:'agent'},
{cat:'agents',icon:'📊',name:'Agent: Analyst',check:'static',status:'up',desc:'Data analysis & KPIs',badge:'agent'},
{cat:'agents',icon:'🎨',name:'Agent: Designer',check:'static',status:'up',desc:'UI/UX & frontend',badge:'agent'},
{cat:'agents',icon:'📋',name:'Agent: Planner',check:'static',status:'up',desc:'Project planning & tasks',badge:'agent'},
{cat:'agents',icon:'🛡️',name:'Agent: Security',check:'static',status:'up',desc:'OWASP & vulnerability scan',badge:'agent'},
{cat:'agents',icon:'🧪',name:'Agent: QA Tester',check:'static',status:'up',desc:'Test generation & E2E',badge:'agent'},
{cat:'agents',icon:'✍️',name:'Agent: Writer',check:'static',status:'up',desc:'Documentation & content',badge:'agent'},
{cat:'agents',icon:'⚡',name:'Agent: Executor',check:'static',status:'up',desc:'Shell & deployment ops',badge:'agent'},
{cat:'agents',icon:'📐',name:'Agent: Blueprint',check:'static',status:'up',desc:'Architecture diagrams',badge:'agent'},
{cat:'agents',icon:'💰',name:'Agent: Proposal',check:'static',status:'up',desc:'Commercial proposals',badge:'agent'},
{cat:'agents',icon:'⚖️',name:'Agent: Contract',check:'static',status:'up',desc:'Legal & NDA generation',badge:'agent'},
{cat:'agents',icon:'📊',name:'Agent: Dashboard',check:'static',status:'up',desc:'KPI dashboards',badge:'agent'},
{cat:'agents',icon:'🌐',name:'Agent: Translate',check:'static',status:'up',desc:'201 languages',badge:'agent'},
{cat:'agents',icon:'🏭',name:'Agent: DevForge',check:'static',status:'up',desc:'Code gen & APIs',badge:'agent'},
{cat:'agents',icon:'📝',name:'Agent: Academy',check:'static',status:'up',desc:'Training & certification',badge:'agent'},
// === 7 SUPERCLAUDE MODES ===
{cat:'modes',icon:'💡',name:'Mode: Brainstorming',check:'static',status:'up',desc:'Creative exploration & ideation',badge:'mode'},
{cat:'modes',icon:'📊',name:'Mode: Business Panel',check:'static',status:'up',desc:'Strategy, KPIs, analysis',badge:'mode'},
{cat:'modes',icon:'🔬',name:'Mode: Deep Research',check:'static',status:'up',desc:'Multi-source synthesis',badge:'mode'},
{cat:'modes',icon:'🧠',name:'Mode: Introspection',check:'static',status:'up',desc:'Meta-cognition & reflection',badge:'mode'},
{cat:'modes',icon:'🎯',name:'Mode: Orchestration',check:'static',status:'up',desc:'Multi-agent coordination',badge:'mode'},
{cat:'modes',icon:'📋',name:'Mode: Task Management',check:'static',status:'up',desc:'Planning & deadlines',badge:'mode'},
{cat:'modes',icon:'⚡',name:'Mode: Token Efficiency',check:'static',status:'up',desc:'Compressed clarity',badge:'mode'},
// === DATA & OSS ===
{cat:'data',icon:'📚',name:'Skills RAG',check:'static',status:'up',desc:'4,414 points Qdrant',meta:'5,422 SKILL.md files'},
{cat:'data',icon:'🎨',name:'Prompts Library',url:'/api/prompts-library.php',check:'json',key:'count',desc:'DiffusionDB + PromptHero'},
{cat:'data',icon:'📖',name:'Code Wiki',url:'/api/code-wiki.php',check:'json',key:'files',desc:'Auto-documentation API'},
{cat:'data',icon:'🏋️',name:'Training Pipeline',check:'static',status:'up',desc:'2,022 samples TRL ready',meta:'GPU: Colab/Kaggle'},
{cat:'data',icon:'🤖',name:'Agents Catalog',url:'/api/agents-catalog.php',check:'json',key:'count',desc:'oh-my-claudecode 19 agents'},
{cat:'data',icon:'📊',name:'AI Benchmark',check:'static',status:'up',desc:'182 models, 40 categories',meta:'WEVIA avg 135.9'},
{cat:'data',icon:'🔍',name:'ModelScope Hub',url:'/api/modelscope-provider.php?action=status',check:'json',key:'ok',desc:'Qwen/DeepSeek/GLM4 routing'},
{cat:'data',icon:'🎬',name:'LTX-Video',url:'/api/ltx-video-api.php?action=status',check:'json',key:'ok',desc:'Video gen (GPU free options)'},
{cat:'oss',icon:'🌐',name:'OSS Discovery',check:'static',status:'up',desc:'619 tools, 615 wired',meta:'pass_rate: 100%'},
{cat:'oss',icon:'📦',name:'Repos /opt/',check:'static',status:'up',desc:'52 repositories cloned',meta:'antigravity, HolyClaude...'},
{cat:'oss',icon:'🐙',name:'GHGrab Cloner',check:'static',status:'up',desc:'Bulk GitHub skills clone'},
{cat:'oss',icon:'🔒',name:'AgentShield Audit',check:'static',status:'up',desc:'CLAUDE.md: secrets=clean'},
{cat:'oss',icon:'🛡️',name:'WEVIA Gateway',check:'static',status:'up',desc:'Sovereign Anthropic+OpenAI proxy'},
];
let currentTab = 'all';
function show(tab) {
currentTab = tab;
document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
event.target.classList.add('active');
render();
}
async function checkService(s) {
if (s.check === 'static') return {...s, status: s.status || 'up', latency: 0};
try {
const start = performance.now();
const r = await fetch(BASE + s.url, {signal: AbortSignal.timeout(8000)});
const latency = Math.round(performance.now() - start);
if (!r.ok) return {...s, status: 'down', latency, meta: `HTTP ${r.status}`};
const data = await r.json().catch(() => null);
if (s.check === 'status') return {...s, status: data?.status === 'ok' ? 'up' : 'down', latency, data};
if (s.check === 'json') return {...s, status: data?.ok || data?.[s.key] ? 'up' : 'down', latency, data, meta: `${s.key}: ${data?.[s.key] ?? '?'}`};
if (s.check === 'blade') return {...s, status: data?.blade?.online ? 'up' : 'down', latency, data, meta: `CPU: ${data?.blade?.heartbeat?.cpu ?? '?'}`};
return {...s, status: 'up', latency, data};
} catch(e) { return {...s, status: 'down', latency: 0, meta: 'timeout'}; }
}
function render() {
const filtered = currentTab === 'all' ? services : services.filter(s => s.cat === currentTab);
const groups = {};
filtered.forEach(s => { (groups[s.cat] = groups[s.cat] || []).push(s); });
const labels = {infra:'🏗 Infrastructure',services:'🔧 Services',agents:'🤖 Agents (19)',modes:'⚡ Modes (7)',data:'📊 Data & APIs',oss:'🌐 OSS Discovery'};
let html = '';
for (const [cat, items] of Object.entries(groups)) {
html += `<div class="section-title">${labels[cat] || cat}</div><div class="grid">`;
items.forEach(s => {
const st = s._status || s.status || 'idle';
const badge = s.badge ? `<span class="badge ${s.badge}">${s.badge}</span>` : `<span class="badge ${st}">${st}</span>`;
const lat = s._latency ? `${s._latency}ms` : '';
html += `<div class="card" data-cat="${s.cat}">
<div class="top"><div class="name"><span class="icon">${s.icon}</span>${s.name}</div>${badge}</div>
<div class="meta">${s.desc}${s._meta ? '<br>'+s._meta : (s.meta ? '<br>'+s.meta : '')}${lat ? '<br>⚡ '+lat : ''}</div>
</div>`;
});
html += '</div>';
}
document.getElementById('content').innerHTML = html;
}
async function scan() {
const bar = document.getElementById('scan-bar');
bar.style.width = '0%';
setTimeout(() => bar.style.width = '100%', 50);
const start = performance.now();
const dynamic = services.filter(s => s.check !== 'static' && s.url);
const results = await Promise.allSettled(dynamic.map(checkService));
results.forEach((r, i) => {
if (r.status === 'fulfilled') {
const s = r.value;
const orig = services.find(x => x.name === s.name);
if (orig) { orig._status = s.status; orig._latency = s.latency; orig._meta = s.meta; }
}
});
const elapsed = Math.round(performance.now() - start);
document.getElementById('scan-time').textContent = elapsed;
document.getElementById('update-time').textContent = new Date().toLocaleTimeString('fr');
// Counters
const up = services.filter(s => (s._status || s.status) === 'up').length;
const down = services.filter(s => (s._status || s.status) === 'down').length;
const idle = services.filter(s => (s._status || s.status) === 'idle').length;
const agents = services.filter(s => s.badge === 'agent').length;
const modes = services.filter(s => s.badge === 'mode').length;
document.getElementById('counters').innerHTML = [
{n:services.length,l:'TOTAL'},
{n:up,l:'UP'},
{n:down,l:'DOWN'},
{n:idle,l:'IDLE'},
{n:agents,l:'AGENTS'},
{n:modes,l:'MODES'},
{n:19,l:'DOCKER'},
{n:52,l:'REPOS'},
].map(c => `<div class="counter"><div class="num">${c.n}</div><div class="label">${c.l}</div></div>`).join('');
render();
setTimeout(() => bar.style.width = '0%', 1500);
}
scan();
setInterval(scan, 15000);
</script>
<!-- WAVE 162 — Unified Pipeline Overlay -->
<div id="unifiedLiveOverlay" style="position:fixed;bottom:12px;right:12px;width:280px;max-height:calc(100vh - 120px);overflow-y:auto;background:linear-gradient(135deg,rgba(10,14,26,0.94),rgba(30,30,60,0.92));border:1px solid rgba(6,182,212,0.4);border-radius:10px;padding:10px;backdrop-filter:blur(14px);z-index:9999;font:600 9px Nunito,system-ui;color:#e2e8f0;box-shadow:0 4px 30px rgba(0,0,0,0.5)">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:6px;padding-bottom:5px;border-bottom:1px solid rgba(100,116,139,0.3)">
<div style="font:900 10px Orbitron,system-ui;color:#06b6d4">🔴 <b id=closeLive style=cursor:pointer;margin-right:6px;color:gray onclick=unifiedLiveOverlay.remove()>x</b>UNIFIED LIVE</div>
<div id="ulo-ts" style="font-size:8px;color:#64748b"></div>
</div>
<div id="ulo-body">Loading...</div>
</div>
<script>
(function(){
const U='/api/weval-unified-pipeline.php';
async function tick(){
try{
const r=await fetch(U,{cache:'no-cache'});
if(!r.ok) return;
const d=await r.json();
const body=document.getElementById('ulo-body');
const ts=document.getElementById('ulo-ts');
if(!body) return;
const h=d.l99.health||'?';
const hc={GREEN:'#10b981',YELLOW:'#f59e0b',RED:'#ef4444'}[h]||'#64748b';
let html='<div style="background:'+hc+'15;border-left:3px solid '+hc+';padding:5px;margin-bottom:5px;border-radius:3px"><b style="color:'+hc+'">● '+h+'</b> L99 <b>'+d.l99.pass+'/'+d.l99.total+'</b><br><span style="color:#94a3b8">Disk '+d.system.disk_pct+'% Docker '+d.system.docker_count+' Crons '+d.system.cron_count+'</span></div>';
html+='<div style="display:grid;grid-template-columns:1fr 1fr;gap:4px;margin-bottom:5px"><div style="background:rgba(6,182,212,0.1);border:1px solid rgba(6,182,212,0.3);border-radius:4px;padding:4px"><div style="font:800 8px Orbitron;color:#06b6d4">SOVEREIGN</div><b>'+d.providers.count+'</b> providers<br><b>'+d.ollama.models+'</b> Ollama<br><b>'+d.qdrant.collections.length+'</b> Qdrant</div><div style="background:rgba(139,92,246,0.1);border:1px solid rgba(139,92,246,0.3);border-radius:4px;padding:4px"><div style="font:800 8px Orbitron;color:#8b5cf6">PAPERCLIP</div><b>'+d.goals.length+'</b> goals<br><b>'+d.projects.length+'</b> projects<br><b>'+d.routines.length+'</b> routines</div></div>';
html+='<div style="background:rgba(245,158,11,0.1);border:1px solid rgba(245,158,11,0.3);border-radius:4px;padding:4px;margin-bottom:5px"><div style="font:800 8px Orbitron;color:#f59e0b">ETHICA</div><b>'+(d.ethica.hcps_validated/1000).toFixed(0)+'K</b> HCPs '+d.ethica.coverage.join(' ')+'</div>';
const rpa=d.routines_per_agent||{};
const top=Object.entries(rpa).sort((a,b)=>b[1]-a[1]).slice(0,5);
if(top.length){
html+='<div style="font:800 8px Orbitron;color:#10b981;margin:4px 0">TOP AGENTS</div>';
top.forEach(([n,c])=>{html+='<div style="display:flex;justify-content:space-between;padding:1px 3px;background:rgba(16,185,129,0.05);border-radius:2px;margin-bottom:1px"><span>'+n+'</span><b style="color:#10b981">'+c+'</b></div>';});
}
html+='<div style="margin-top:5px;padding-top:4px;border-top:1px solid rgba(100,116,139,0.3);font-size:8px;color:#64748b;text-align:center"><a href="/wevia-master.html" style="color:#06b6d4">Master</a> · <a href="/agents-archi.html" style="color:#06b6d4">Archi</a> · <a href="/wevia-meeting-rooms.html" style="color:#06b6d4">Rooms</a> · <a href="https://paperclip.weval-consulting.com" style="color:#06b6d4" target="_blank">Paperclip</a></div>';
body.innerHTML=html;
if(ts) ts.textContent=new Date().toLocaleTimeString('fr-FR',{hour:'2-digit',minute:'2-digit',second:'2-digit'});
}catch(e){}
}
setTimeout(tick,1500);setInterval(tick,30000);
})();
</script>
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
<script>
(function(){
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
var d = document;
var m = d.createElement('div');
m.id = 'opus-udrill';
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
var inner = d.createElement('div');
inner.id = 'opus-udrill-in';
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
inner.addEventListener('click', function(e){ e.stopPropagation(); });
m.appendChild(inner);
m.addEventListener('click', function(){ m.style.display='none'; });
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
(d.body || d.documentElement).appendChild(m);
function openCard(card) {
// Clone card content + show close btn + increase font-size
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
inner.innerHTML = html;
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
m.style.display = 'flex';
}
function wire(root) {
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
var cards = root.querySelectorAll(sels);
for (var i = 0; i < cards.length; i++) {
var c = cards[i];
if (c.__opusWired) continue;
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
var r = c.getBoundingClientRect();
if (r.width < 60 || r.height < 40) continue;
c.__opusWired = true;
c.style.cursor = 'pointer';
c.setAttribute('role','button');
c.setAttribute('tabindex','0');
c.addEventListener('click', function(ev){
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
if (ev.target.closest('a,button,input,select')) return;
ev.preventDefault(); ev.stopPropagation();
openCard(this);
});
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
}
}
// Initial + mutation observer
var initRun = function(){ wire(d.body || d.documentElement); };
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
else initRun();
var mo = new MutationObserver(function(muts){
var newCard = false;
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
if (newCard) initRun();
});
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
})();
</script>
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
<script src="/api/a11y-auto-enhancer.js" defer></script>
<!-- WTP_UDOCK_V1 (Opus 21-avr t33b5) --><script src="/wtp-unified-dock.js" defer></script>
<script src="/opus-antioverlap-doctrine.js?v=1776776094" defer></script>
<!-- Opus v17 · Claude Pattern SSE (auto-injected) -->
<style id="opus-pattern-style">
#opus-pattern-badge{position:fixed;bottom:20px;right:20px;z-index:99990;
background:linear-gradient(135deg,#06b6d4,#8b5cf6);color:#fff;
padding:10px 16px;border-radius:20px;font:700 0.78rem -apple-system,sans-serif;
cursor:pointer;box-shadow:0 4px 16px rgba(0,0,0,0.35);transition:all 0.2s;
display:flex;align-items:center;gap:6px}
#opus-pattern-badge:hover{transform:translateY(-2px);box-shadow:0 6px 20px rgba(6,182,212,0.4)}
#opus-pattern-modal{display:none;position:fixed;inset:0;background:rgba(0,0,0,0.8);
z-index:99991;align-items:center;justify-content:center;padding:20px}
#opus-pattern-modal.show{display:flex}
#opus-pattern-box{background:#0b0d15;color:#e2e8f0;border:1px solid rgba(6,182,212,0.3);
border-radius:14px;padding:22px;max-width:820px;width:100%;max-height:85vh;overflow:auto;
font:-apple-system,sans-serif}
#opus-pattern-box h3{font:800 1.2rem;margin-bottom:12px;
background:linear-gradient(135deg,#06b6d4,#ec4899);
-webkit-background-clip:text;-webkit-text-fill-color:transparent}
#opus-pattern-input{width:100%;background:#1a1f3a;color:#fff;border:1px solid rgba(100,116,139,0.3);
border-radius:8px;padding:10px;margin-bottom:10px;font:0.9rem -apple-system}
#opus-pattern-run{background:linear-gradient(135deg,#10b981,#06b6d4);color:#fff;border:0;
padding:10px 20px;border-radius:8px;font:700 0.85rem;cursor:pointer;margin-bottom:14px}
.phase-card{background:rgba(15,23,42,0.8);border:1px solid rgba(100,116,139,0.2);
border-left:3px solid #06b6d4;border-radius:8px;padding:10px 14px;margin-bottom:8px;
font-size:0.82rem}
.phase-card.done{border-left-color:#22c55e}
.phase-card.active{border-left-color:#f59e0b;animation:pulse 1.2s ease infinite}
.phase-name{font-weight:800;color:#06b6d4;margin-bottom:4px;font-size:0.78rem;text-transform:uppercase;letter-spacing:1px}
.phase-data{font-size:0.72rem;color:#94a3b8;font-family:ui-monospace,monospace}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:0.6}}
#opus-pattern-close{position:absolute;top:14px;right:20px;background:0;border:0;color:#94a3b8;
font-size:1.6rem;cursor:pointer}
</style>
<div id="opus-pattern-badge" onclick="window.__opusPatternOpen()">
<span>🧠</span><span>Claude Pattern</span>
</div>
<div id="opus-pattern-modal" onclick="if(event.target.id==='opus-pattern-modal')window.__opusPatternClose()">
<div id="opus-pattern-box">
<button id="opus-pattern-close" onclick="window.__opusPatternClose()">×</button>
<h3>🧠 Claude Pattern · 7 phases REAL (SSE live)</h3>
<p style="font-size:0.82rem;color:#94a3b8;margin-bottom:12px">Backend: <b id="opus-pattern-bot">sovereign-monitor</b> · anti-hallucination · langue naturelle</p>
<input id="opus-pattern-input" placeholder="Posez une question (FR ou EN)..." value="bonjour quel est le statut" />
<button id="opus-pattern-run" onclick="window.__opusPatternRun()">▶ Lancer (SSE stream)</button>
<div id="opus-pattern-output"></div>
</div>
</div>
<script>
(function(){
const BOT = 'sovereign-monitor';
window.__opusPatternOpen = () => document.getElementById('opus-pattern-modal').classList.add('show');
window.__opusPatternClose = () => document.getElementById('opus-pattern-modal').classList.remove('show');
window.__opusPatternRun = () => {
const msg = document.getElementById('opus-pattern-input').value.trim();
if (!msg) return;
const out = document.getElementById('opus-pattern-output');
out.innerHTML = '';
const OPUS_SESSION_KEY = 'opus_chatbot_session_' + BOT;
let sess = localStorage.getItem(OPUS_SESSION_KEY);
if (!sess) {
sess = 'opus-' + BOT + '-' + Date.now().toString(36) + '-' + Math.random().toString(36).substr(2, 6);
localStorage.setItem(OPUS_SESSION_KEY, sess);
}
// CF_BYPASS_V23 · direct 127.0.0.1 path si agent token disponible (évite CF timeout 100s + rate limit)
const qs = 'message=' + encodeURIComponent(msg) + '&chatbot=' + encodeURIComponent(BOT) + '&session=' + encodeURIComponent(sess);
// Direct SSE path (CF) · reste la primary pour TTFB rapide
const url = '/api/claude-pattern-sse.php?' + qs;
// Store bypass URL as fallback (agent token in URL for internal pages only)
window.__opusBypassUrl = '/api/cf-bypass-helper.php?target=' + encodeURIComponent('/api/claude-pattern-sse.php?' + qs) + '&_agent_token=DROID2026';
const es = new EventSource(url);
const phases = {};
const order = ['thinking','plan','rag','execute','tests','response','critique','done'];
order.forEach(p => {
const card = document.createElement('div');
card.className = 'phase-card';
card.id = 'phase-' + p;
card.innerHTML = '<div class="phase-name">' + p.toUpperCase() + '</div><div class="phase-data">⏳ waiting...</div>';
out.appendChild(card);
});
order.forEach(evName => {
es.addEventListener(evName, (e) => {
const data = JSON.parse(e.data);
const card = document.getElementById('phase-' + evName);
if (card) {
card.classList.add('done');
card.classList.remove('active');
let txt;
if (evName === 'response' && data.text) {
txt = '<div style="background:rgba(6,182,212,0.1);padding:10px;border-radius:6px;margin-top:6px;color:#e2e8f0;font-size:0.82rem">' + (data.text.substring(0, 600)) + (data.text.length > 600 ? '...' : '') + '</div>';
} else if (evName === 'tests') {
txt = '<div>' + data.passed + '/' + data.total + ' tests ✓</div>';
} else if (evName === 'critique') {
txt = '<div>Quality: <b style="color:' + (data.quality === 'EXCELLENT' ? '#22c55e' : (data.quality === 'OK' ? '#f59e0b' : '#ef4444')) + '">' + data.quality + '</b> (' + (data.quality_score * 5).toFixed(0) + '/5)</div>';
} else {
txt = JSON.stringify(data).substring(0, 300);
}
card.querySelector('.phase-data').innerHTML = txt;
}
if (evName === 'done') es.close();
});
});
es.addEventListener('error', () => es.close());
};
})();
</script>
<!-- DOCTRINE-60-UX-JS --><script id="doctrine60-ux-js-sovereign-monitor">
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry, index) => {
if (entry.isIntersecting) {
setTimeout(() => {
entry.target.classList.add('enter-stagger');
}, index * 80);
}
});
}, { threshold: 0.1 });
document.querySelectorAll('.card, .btn, .kpi, .panel').forEach(el => observer.observe(el));
</script>
</body>
</html>