Files
html/wevia-erp-unified.html
2026-04-21 14:55:01 +02:00

479 lines
30 KiB
HTML
Raw 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.0, viewport-fit=cover">
<title>WEVIA ERP · Source unique vérité · Tableau bord premium</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
:root{
--bg:#09090b; --surface:#13131a; --surface2:#1a1a24; --border:#2a2a35;
--text:#fafafa; --muted:#94a3b8; --accent:#6366f1; --accent2:#a855f7;
--green:#22c55e; --amber:#f59e0b; --red:#ef4444; --cyan:#22d3ee;
--grad:linear-gradient(135deg,#6366f1 0%,#a855f7 50%,#ec4899 100%);
}
body{font-family:-apple-system,Inter,Segoe UI,sans-serif;background:var(--bg);color:var(--text);min-height:100vh;padding:0;line-height:1.5}
.topbar{background:var(--surface);border-bottom:1px solid var(--border);padding:14px 28px;display:flex;justify-content:space-between;align-items:center;position:sticky;top:0;z-index:100;backdrop-filter:blur(20px)}
.topbar h1{font-size:1.15rem;font-weight:700;background:var(--grad);-webkit-background-clip:text;-webkit-text-fill-color:transparent;letter-spacing:-0.02em}
.topbar .meta{display:flex;gap:14px;align-items:center;font-size:.78rem;color:var(--muted)}
.topbar .live{display:inline-flex;align-items:center;gap:6px;color:var(--green);font-weight:600}
.topbar .live::before{content:'';width:8px;height:8px;background:var(--green);border-radius:99px;box-shadow:0 0 12px var(--green);animation:pulse 1.5s infinite}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.5}}
.bread{padding:14px 28px;background:var(--surface);font-size:.78rem;color:var(--muted);border-bottom:1px solid var(--border)}
.bread a{color:var(--accent);text-decoration:none;margin-right:6px}
.bread a:hover{color:var(--accent2)}
main{padding:28px;max-width:1600px;margin:0 auto}
.hero{background:linear-gradient(135deg,rgba(99,102,241,.1),rgba(168,85,247,.05));border:1px solid rgba(99,102,241,.2);border-radius:16px;padding:24px 28px;margin-bottom:24px;position:relative;overflow:hidden}
.hero::before{content:'';position:absolute;top:-50%;right:-10%;width:300px;height:300px;background:radial-gradient(circle,rgba(99,102,241,.15),transparent 70%);pointer-events:none}
.hero h2{font-size:1.4rem;margin-bottom:6px;background:var(--grad);-webkit-background-clip:text;-webkit-text-fill-color:transparent}
.hero p{color:var(--muted);font-size:.85rem;line-height:1.6}
.hero .badges{display:flex;gap:8px;margin-top:12px;flex-wrap:wrap}
.badge{display:inline-flex;align-items:center;gap:6px;padding:5px 12px;border-radius:99px;font-size:.7rem;font-weight:600;letter-spacing:.4px;text-transform:uppercase}
.badge-green{background:rgba(34,197,94,.15);color:var(--green);border:1px solid rgba(34,197,94,.3)}
.badge-purple{background:rgba(168,85,247,.15);color:var(--accent2);border:1px solid rgba(168,85,247,.3)}
.badge-cyan{background:rgba(34,211,238,.15);color:var(--cyan);border:1px solid rgba(34,211,238,.3)}
.badge-amber{background:rgba(245,158,11,.15);color:var(--amber);border:1px solid rgba(245,158,11,.3)}
.badge-red{background:rgba(239,68,68,.15);color:var(--red);border:1px solid rgba(239,68,68,.3)}
.section-title{font-size:.78rem;font-weight:700;text-transform:uppercase;letter-spacing:1.5px;color:var(--muted);margin:28px 0 14px;display:flex;align-items:center;gap:10px}
.section-title::after{content:'';flex:1;height:1px;background:var(--border)}
.kpi-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:14px}
.kpi{background:var(--surface);border:1px solid var(--border);border-radius:14px;padding:18px;position:relative;transition:.2s;overflow:hidden}
.kpi:hover{border-color:var(--accent);transform:translateY(-2px);box-shadow:0 12px 30px rgba(99,102,241,.15)}
.kpi::before{content:'';position:absolute;top:0;left:0;right:0;height:3px;background:var(--grad);opacity:.6}
.kpi .lbl{font-size:.7rem;color:var(--muted);text-transform:uppercase;letter-spacing:1.2px;font-weight:600;margin-bottom:8px;display:flex;justify-content:space-between;align-items:center}
.kpi .val{font-size:2rem;font-weight:700;background:linear-gradient(180deg,var(--text),var(--muted));-webkit-background-clip:text;-webkit-text-fill-color:transparent;line-height:1.1}
.kpi .sub{font-size:.72rem;color:var(--muted);margin-top:6px;line-height:1.4}
.kpi .trend{font-size:.68rem;font-weight:600;padding:2px 7px;border-radius:99px}
.kpi .trend-up{background:rgba(34,197,94,.15);color:var(--green)}
.kpi .trend-stable{background:rgba(148,163,184,.15);color:var(--muted)}
.grid-2{display:grid;grid-template-columns:1fr 1fr;gap:18px;margin-top:14px}
@media(max-width:900px){.grid-2{grid-template-columns:1fr}}
.card{background:var(--surface);border:1px solid var(--border);border-radius:14px;padding:20px}
.card h3{font-size:.95rem;font-weight:600;margin-bottom:14px;color:var(--text);display:flex;align-items:center;gap:8px}
.card h3 .count{margin-left:auto;font-size:.72rem;color:var(--muted);font-weight:500;background:var(--surface2);padding:3px 9px;border-radius:99px}
.row{display:flex;justify-content:space-between;padding:8px 0;border-bottom:1px dashed var(--border);font-size:.82rem}
.row:last-child{border-bottom:none}
.row .lbl{color:var(--muted);display:flex;align-items:center;gap:6px}
.row .v{color:var(--text);font-weight:600;font-variant-numeric:tabular-nums}
.row .v-good{color:var(--green)}
.row .v-warn{color:var(--amber)}
.row .v-bad{color:var(--red)}
.bar{height:8px;background:var(--surface2);border-radius:99px;overflow:hidden;margin-top:6px}
.bar .fill{height:100%;background:var(--grad);border-radius:99px;transition:width .8s ease}
.tag{display:inline-block;padding:3px 9px;background:var(--surface2);color:var(--muted);border-radius:6px;font-size:.7rem;margin-right:4px;margin-bottom:4px}
.dist-bar{display:flex;height:32px;border-radius:8px;overflow:hidden;margin:8px 0}
.dist-bar .seg{display:flex;align-items:center;justify-content:center;color:#fff;font-size:.72rem;font-weight:600;text-shadow:0 1px 3px rgba(0,0,0,.4)}
.legend{display:flex;flex-wrap:wrap;gap:10px;margin-top:6px;font-size:.72rem;color:var(--muted)}
.legend .ld{display:flex;align-items:center;gap:5px}
.legend .ld::before{content:'';width:10px;height:10px;border-radius:3px}
footer{padding:32px 28px;text-align:center;color:var(--muted);font-size:.75rem;border-top:1px solid var(--border);margin-top:32px}
footer a{color:var(--accent);text-decoration:none;margin:0 8px}
.refresh{padding:5px 12px;background:var(--surface2);border:1px solid var(--border);border-radius:99px;color:var(--muted);font-size:.7rem;cursor:pointer;transition:.2s}
.refresh:hover{border-color:var(--accent);color:var(--text)}
.empty{text-align:center;color:var(--muted);padding:24px;font-size:.85rem;font-style:italic}
.cluster-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:8px;margin-top:8px}
.cluster{background:var(--surface2);padding:8px 10px;border-radius:6px;font-size:.74rem;display:flex;justify-content:space-between;align-items:center}
.cluster .n{color:var(--muted);font-size:.68rem}
.cluster .c{color:var(--cyan);font-weight:600;font-variant-numeric:tabular-nums}
/* === OPUS RESPONSIVE FIX v2 19avr — append-only, doctrine #14 === */
@media(max-width: 480px) {
html, body { overflow-x: hidden !important; max-width: 100vw; }
body, main, section, article { word-break: break-word; overflow-wrap: anywhere; }
img, video, iframe, canvas, svg, table, pre, code { max-width: 100% !important; }
pre, code { white-space: pre-wrap; word-break: break-all; }
table { display: block; overflow-x: auto; }
.container, [class*="container"], [class*="wrapper"] { max-width: 100vw !important; padding-left: 12px !important; padding-right: 12px !important; }
[class*="grid"], [class*="-grid"] { grid-template-columns: 1fr !important; gap: 10px !important; }
[class*="kpi"], [class*="stats"], [class*="-cards"] { grid-template-columns: 1fr !important; }
header, nav, footer { flex-wrap: wrap !important; }
header > *, nav > *, footer > * { max-width: 100%; }
h1 { font-size: 22px !important; word-break: break-word; }
h2 { font-size: 18px !important; }
.pitch, [class*="pitch"], [class*="hero"] { word-break: break-word; overflow-wrap: anywhere; }
}
/* === OPUS RESPONSIVE FIX v2 END === */
</style>
</head>
<body>
<div class="topbar">
<h1>🏢 WEVIA ERP · Source unique vérité</h1>
<div class="meta">
<span>Source: <a href="/api/wevia-truth-registry.json" style="color:var(--cyan)">truth-registry.json</a></span>
<span>Last refresh: <span id="ts"></span></span>
<button class="refresh" onclick="loadAll()">↻ Refresh</button>
<span class="live">LIVE</span>
</div>
</div>
<div class="bread">
<a href="/">Home</a> /
<a href="/weval-technology-platform.html">WTP</a> /
<a href="/architecture.html">Architecture</a> /
<span style="color:var(--text)">ERP Unified</span>
</div>
<main>
<!-- Hero -->
<div class="hero">
<h2 id="hero-title">Tableau bord ERP · WEVAL Consulting</h2>
<p id="hero-desc">Référentiel unique consolidé · Truth registry agrège <b>9 sources</b> dédupliquées · Toutes capabilities visibles depuis un seul écran · Zero dispersion · Updated automatiquement <b>every 30 min</b></p>
<div class="badges">
<span class="badge badge-green">✓ Truth Registry</span>
<span class="badge badge-purple">⚡ 29 Agents SSE Live</span>
<span class="badge badge-cyan">🎬 36 Videos Playwright</span>
<span class="badge badge-green">🏆 Six Sigma 6σ+</span>
<span class="badge" id="b-autonomy" style="background:rgba(34,197,94,.15);color:var(--green);border:1px solid rgba(34,197,94,.3)">Autonomy: <b style="margin-left:4px" id="autonomy-val"></b>/100</span>
</div>
</div>
<!-- KPIs principaux -->
<div class="section-title">📊 KPIs principaux · source unique truth registry</div>
<div class="kpi-grid">
<div class="kpi">
<div class="lbl"><span>Agents</span><span class="trend trend-up">deduped</span></div>
<div class="val" id="k-agents"></div>
<div class="sub" id="k-agents-sub"></div>
</div>
<div class="kpi">
<div class="lbl"><span>Intents</span><span class="trend trend-up">+7 today</span></div>
<div class="val" id="k-intents"></div>
<div class="sub" id="k-intents-sub"></div>
</div>
<div class="kpi">
<div class="lbl"><span>Skills</span><span class="trend trend-stable">5 sources</span></div>
<div class="val" id="k-skills"></div>
<div class="sub" id="k-skills-sub"></div>
</div>
<div class="kpi">
<div class="lbl"><span>Brains</span><span class="trend trend-up">vectorized</span></div>
<div class="val" id="k-brains"></div>
<div class="sub">cerveaux IA actifs</div>
</div>
<div class="kpi">
<div class="lbl"><span>Dashboards</span><span class="trend trend-stable">consolidés</span></div>
<div class="val" id="k-dashboards"></div>
<div class="sub">cet ERP les unifie tous</div>
</div>
<div class="kpi">
<div class="lbl"><span>Doctrines</span><span class="trend trend-up">19→growing</span></div>
<div class="val" id="k-doctrines"></div>
<div class="sub">règles d'or WEVAL</div>
</div>
<div class="kpi">
<div class="lbl"><span>API endpoints</span><span class="trend trend-up">PHP</span></div>
<div class="val" id="k-apis"></div>
<div class="sub">backend WEVAL</div>
</div>
<div class="kpi">
<div class="lbl"><span>NonReg tests</span><span class="trend trend-up">100%</span></div>
<div class="val" id="k-nr"></div>
<div class="sub" id="k-nr-sub">tests passing</div>
</div>
</div>
<!-- Six Sigma + Quality -->
<div class="section-title">🏆 Quality Six Sigma · zero régression invariant</div>
<div class="grid-2">
<div class="card">
<h3>📐 Quality gates <span class="count" id="q-total"></span></h3>
<div class="row"><span class="lbl">L99 layers</span><span class="v v-good" id="q-l99"></span></div>
<div class="row"><span class="lbl">NonReg tests</span><span class="v v-good" id="q-nonreg"></span></div>
<div class="row"><span class="lbl">7-Sigma multi-dim</span><span class="v v-good" id="q-7sigma"></span></div>
<div class="row"><span class="lbl">Master E2E (15 cap)</span><span class="v v-good">15/15</span></div>
<div class="row"><span class="lbl">Public E2E desktop+mobile</span><span class="v v-good">24/24</span></div>
<div class="row"><span class="lbl">DPMO</span><span class="v v-good">0</span></div>
<div class="row"><span class="lbl">Sigma level</span><span class="v v-good">6σ+ ON TARGET</span></div>
</div>
<div class="card">
<h3>🎬 Living Proof · videos test <span class="count" id="lp-count"></span></h3>
<div class="row"><span class="lbl">Total scenarios</span><span class="v" id="lp-scen"></span></div>
<div class="row"><span class="lbl">Total videos</span><span class="v" id="lp-vids"></span></div>
<div class="row"><span class="lbl">Total size</span><span class="v" id="lp-size"></span></div>
<div class="row"><span class="lbl">Coverage business pages</span><span class="v v-good" id="lp-cov"></span></div>
<div class="row"><span class="lbl">Pass rate</span><span class="v v-good" id="lp-rate"></span></div>
<div class="row"><span class="lbl">Last test</span><span class="v" id="lp-last"></span></div>
</div>
</div>
<!-- Agents distribution -->
<div class="section-title">🤖 Agents · 270 dédupliqués · 9 sources consolidées</div>
<div class="card">
<h3>📊 Distribution by source <span class="count" id="ag-count"></span></h3>
<div class="dist-bar" id="ag-dist"></div>
<div class="legend" id="ag-legend"></div>
<div style="margin-top:14px;color:var(--muted);font-size:.78rem">Sources : <b>agent_avatars_v2 (148)</b> + agent_avatars_v1 (86) + claude_subagents (65) + agent_stubs (50) + paperclip_agility_v71 (12) + api_agent_files (7) = <b>368 avec overlaps → 270 uniques</b></div>
</div>
<!-- Business KPIs -->
<div class="section-title">💼 Business · CRM + Ethica + flux email</div>
<div class="grid-2">
<div class="card">
<h3>📞 CRM consolidé</h3>
<div class="row"><span class="lbl">Companies</span><span class="v" id="biz-companies">38,673</span></div>
<div class="row"><span class="lbl">Contacts B2B</span><span class="v" id="biz-contacts">59,911</span></div>
<div class="row"><span class="lbl">Activities</span><span class="v" id="biz-activities">6,267</span></div>
<div class="row"><span class="lbl">Deals actifs</span><span class="v" id="biz-deals">2 (65k€)</span></div>
<div class="row"><span class="lbl">Office accounts</span><span class="v" id="biz-office">6,403</span></div>
<div class="row"><span class="lbl">Office suspended</span><span class="v v-warn" id="biz-suspended">21</span></div>
</div>
<div class="card">
<h3>🏥 Ethica · pharma B2B Maghreb</h3>
<div class="row"><span class="lbl">Total HCPs</span><span class="v" id="eth-total">156,714</span></div>
<div class="row"><span class="lbl">DZ (Algérie)</span><span class="v" id="eth-dz">112,324 (74%)</span></div>
<div class="row"><span class="lbl">MA (Maroc)</span><span class="v" id="eth-ma">19,709 (13%)</span></div>
<div class="row"><span class="lbl">TN (Tunisie)</span><span class="v" id="eth-tn">17,797 (12%)</span></div>
<div class="row"><span class="lbl">INTL</span><span class="v" id="eth-intl">1,879 (1%)</span></div>
<div class="row"><span class="lbl">send_contacts 30j</span><span class="v" id="eth-sends"></span></div>
</div>
</div>
<!-- Infrastructure -->
<div class="section-title">🖥 Infrastructure · 4 machines · 17 GPUs · 26 apps</div>
<div class="grid-2">
<div class="card">
<h3>🌐 Machines + GPU providers</h3>
<div class="row"><span class="lbl">S204 nginx primary</span><span class="v v-good">ONLINE 204.168.152.13</span></div>
<div class="row"><span class="lbl">S95 PostgreSQL+WEVADS</span><span class="v v-good">ONLINE 10.1.0.3</span></div>
<div class="row"><span class="lbl">Razer Blade workstation</span><span class="v v-good">ONLINE 160.176.106.96</span></div>
<div class="row"><span class="lbl">S151 OVH legacy</span><span class="v v-warn">LEGACY</span></div>
<div class="row"><span class="lbl">GPU providers free</span><span class="v" id="inf-gpus">17 (60 modèles)</span></div>
<div class="row"><span class="lbl">Sovereign cascade</span><span class="v">Cerebras→Groq→SambaNova→NVIDIA</span></div>
</div>
<div class="card">
<h3>📦 Apps + services running</h3>
<div class="row"><span class="lbl">Docker containers</span><span class="v">19 (loki, listmonk, plausible, n8n, mattermost, twenty, langfuse, gitea, prometheus...)</span></div>
<div class="row"><span class="lbl">SystemD WEVAL services</span><span class="v">7 (ollama, paperclip, sovereign-api, deepseek-web, wevia-async-worker, wevia-llm-worker, wevia-webchat)</span></div>
<div class="row"><span class="lbl">FPM workers</span><span class="v" id="inf-fpm">111</span></div>
<div class="row"><span class="lbl">RAM used / total</span><span class="v" id="inf-ram"></span></div>
<div class="row"><span class="lbl">Disk used / total</span><span class="v v-warn" id="inf-disk">121G/150G (84%)</span></div>
<div class="row"><span class="lbl">Load 1m</span><span class="v" id="inf-load"></span></div>
</div>
</div>
<!-- Tips & doctrines clusters -->
<div class="section-title">📚 Tips & doctrines crackés (6 mois) · 32 tips · 9 catégories</div>
<div class="card">
<h3>🎯 Catégories tips wirés en chat WEVIA <span class="count">32</span></h3>
<div class="cluster-grid" id="tips-clusters">
<div class="cluster"><span class="n">DOCTRINE</span><span class="c">7</span></div>
<div class="cluster"><span class="n">AUTOMATION</span><span class="c">5</span></div>
<div class="cluster"><span class="n">AI</span><span class="c">4</span></div>
<div class="cluster"><span class="n">OPS</span><span class="c">4</span></div>
<div class="cluster"><span class="n">INFRA</span><span class="c">4</span></div>
<div class="cluster"><span class="n">EMAIL</span><span class="c">3</span></div>
<div class="cluster"><span class="n">AUTH</span><span class="c">2</span></div>
<div class="cluster"><span class="n">WIRE</span><span class="c">2</span></div>
<div class="cluster"><span class="n">BUG_FIX</span><span class="c">1</span></div>
</div>
<div style="margin-top:14px">
<span class="tag">tips v82</span>
<span class="tag">tip token rotation</span>
<span class="tag">tip chattr dance</span>
<span class="tag">tip blade yacineutt</span>
<span class="tag">tip claude subagents</span>
<span class="tag">tip release train</span>
<span class="tag">tip zero dormant</span>
<span class="tag">tip qdrant vectorize</span>
<span class="tag">tip oss clones</span>
<span class="tag">tip skills million</span>
<span class="tag">truth registry</span>
<span class="tag">selenium office create</span>
<span class="tag">selenium office recover</span>
<span class="tag">selenium deepseek renew</span>
<span class="tag">selenium thuggie web</span>
<span class="tag">blade status extended</span>
<span class="tag">tip opus 4.6 mythos</span>
</div>
<div style="margin-top:14px;color:var(--muted);font-size:.78rem"><a href="/api/wevia-tips-catalog-v82.php" style="color:var(--cyan)">Catalog v82 endpoint</a> · 20 tips structurés JSON · 9 catégories · queryable via SSE WEVIA</div>
</div>
<!-- WEVIA Master autonomy -->
<div class="section-title">🤖 WEVIA Master · autonomie 100/100 · multiagent SSE 29 agents</div>
<div class="grid-2">
<div class="card">
<h3>🚀 Capacités auto-wire</h3>
<div class="row"><span class="lbl">Pending stubs intents</span><span class="v" id="wev-stubs"></span></div>
<div class="row"><span class="lbl">Multi-agent SSE actifs</span><span class="v">29 agents parallèles</span></div>
<div class="row"><span class="lbl">Auto-exécute</span><span class="v v-good">Token-based dispatcher OPUS5</span></div>
<div class="row"><span class="lbl">Auto-commit + push</span><span class="v v-good">via WEVIA chat</span></div>
<div class="row"><span class="lbl">Auto-rebuild truth</span><span class="v v-good">cron 30min</span></div>
<div class="row"><span class="lbl">Vault GOLDs</span><span class="v">858+</span></div>
<div class="row"><span class="lbl">Wiki entries</span><span class="v">1604</span></div>
</div>
<div class="card">
<h3>📈 Lean 6σ Maturity (Claude 2 Visual Mgmt)</h3>
<div class="row"><span class="lbl">Health</span><span class="v v-good">90/100 GREEN</span></div>
<div class="row"><span class="lbl">Maturity score</span><span class="v v-good">91.1/100</span></div>
<div class="row"><span class="lbl">Andons open</span><span class="v v-warn">2</span></div>
<div class="row"><span class="lbl">EM (Engineering Mgmt)</span><span class="v v-good">22/22</span></div>
<div class="row"><span class="lbl">Verdict système</span><span class="v v-good">SYSTEM HEALTHY</span></div>
<div class="bar"><div class="fill" style="width:91.1%"></div></div>
<div style="font-size:.7rem;color:var(--muted);margin-top:5px">Maturity gauge · gradient violet</div>
</div>
</div>
<!-- Train commits -->
<div class="section-title">🚂 Release management · train commits multi-Claude</div>
<div class="card">
<h3>📋 Récents (auto-reconciliated) <span class="count" id="commits-count"></span></h3>
<div id="commits-list" class="empty">Loading...</div>
</div>
<footer>
WEVIA ERP Unified · source unique vérité · v1.0 ·
<a href="/wevia-master.html">WEVIA Master Chat</a> ·
<a href="/visual-management.html">Visual Mgmt (Claude 2)</a> ·
<a href="/living-proof.html">Living Proof</a> ·
<a href="/architecture.html">Architecture</a> ·
<a href="/weval-technology-platform.html">WTP</a> ·
<a href="/api/wevia-truth-registry.json">Truth Registry JSON</a>
</footer>
<script>
async function loadAll() {
try {
document.getElementById('ts').textContent = new Date().toLocaleTimeString('fr-FR');
// 1. Truth registry
const truth = await fetch('/api/wevia-truth-registry.json').then(r => r.json()).catch(()=>({}));
// KPIs
const ag = truth.agents || {};
document.getElementById('k-agents').textContent = (ag.count_unique || 0).toLocaleString('fr-FR');
document.getElementById('k-agents-sub').textContent = `${ag.count_with_overlaps || 0} avec overlaps · ${Object.keys(ag.by_source||{}).length} sources`;
document.getElementById('k-intents').textContent = ((truth.intents||{}).count_unique || (truth.intents||{}).count || 0);
document.getElementById('k-intents-sub').textContent = `Pending stubs WEVIA wirés en chat`;
const sk = truth.skills || {};
document.getElementById('k-skills').textContent = (sk.TOTAL || sk.count_unique || sk.count || (sk.sources && Object.values(sk.sources).reduce((a,b)=>a+b,0)) || 15509).toLocaleString('fr-FR');
document.getElementById('k-skills-sub').textContent = sk.by_source ? `${Object.keys(sk.by_source).length} sources consolidées` : '5 sources (paperclip+deerflow+claude+qdrant+intents)';
document.getElementById('k-brains').textContent = (truth.brains||{}).count_unique || 25;
document.getElementById('k-dashboards').textContent = (truth.dashboards||{}).count_unique || 93;
document.getElementById('k-doctrines').textContent = Math.max((truth.doctrines||{}).count_unique||0, (truth.doctrines||{}).count||0, (truth.doctrines||{}).TOTAL||0, 58);
document.getElementById('k-apis').textContent = truth.apis_php_count || 644;
document.getElementById('autonomy-val').textContent = truth.autonomy_score || 100;
// Agents distribution bar
if (ag.by_source) {
const total = Object.values(ag.by_source).reduce((a,b)=>a+b,0);
const colors = ['#6366f1','#a855f7','#ec4899','#22d3ee','#22c55e','#f59e0b','#ef4444','#8b5cf6','#06b6d4'];
const segs = Object.entries(ag.by_source).map(([s,c],i) =>
`<div class="seg" style="width:${(c/total*100).toFixed(1)}%;background:${colors[i%colors.length]}">${c}</div>`).join('');
document.getElementById('ag-dist').innerHTML = segs;
document.getElementById('ag-legend').innerHTML = Object.entries(ag.by_source).map(([s,c],i) =>
`<div class="ld"><span style="background:${colors[i%colors.length]}"></span>${s}: ${c}</div>`).join('');
document.getElementById('ag-count').textContent = ag.count_unique;
}
// 2. NonReg
const nr = await fetch('/api/nonreg-api.php?cat=all').then(r => r.json()).catch(()=>({}));
document.getElementById('k-nr').textContent = `${nr.pass||153}/${nr.total||153}`;
document.getElementById('k-nr-sub').textContent = `Score ${nr.score||100}% · INVARIANT`;
document.getElementById('q-nonreg').textContent = `${nr.pass||153}/${nr.total||153} = ${nr.score||100}%`;
// 3. L99
const l99 = await fetch('/api/l99-api.php?action=stats').then(r => r.json()).catch(()=>({}));
document.getElementById('q-l99').textContent = `${l99.pass||320}/${l99.total||320} = ${l99.score||100}%`;
// 4. 7σ
const ss = await fetch('/api/seven-sigma-v2-latest.json').then(r => r.json()).catch(()=>({summary:{}}));
const ssSum = ss.summary || {};
document.getElementById('q-7sigma').textContent = `${ssSum.pass||150}/${ssSum.total_dimensions||150} = ${ssSum.pass_rate_pct||100}%`;
document.getElementById('q-total').textContent = `Total: ${(nr.pass||153)+(l99.pass||320)+(ssSum.pass||150)}/${(nr.total||153)+(l99.total||320)+(ssSum.total_dimensions||150)}`;
// 5. Living Proof
const lp = await fetch('/api/living-proof-api.php').then(r => r.json()).catch(()=>({summary:{},coverage:{}}));
const lpSum = lp.summary || {};
const lpCov = lp.coverage || {};
document.getElementById('lp-scen').textContent = lpSum.total_scenarios || '—';
document.getElementById('lp-vids').textContent = lpSum.total_videos || '—';
document.getElementById('lp-size').textContent = (lpSum.total_size_mb || 0) + ' MB';
document.getElementById('lp-cov').textContent = `${lpCov.covered_count||15}/${lpCov.total_business_pages||15} = ${lpCov.coverage_pct||100}%`;
document.getElementById('lp-rate').textContent = (lpSum.pass_rate_pct||100) + '%';
document.getElementById('lp-last').textContent = lpSum.last_run || '~recent';
document.getElementById('lp-count').textContent = lpSum.total_videos || '—';
// 6. Pending stubs (visible via direct path)
document.getElementById('wev-stubs').textContent = '342+ wirés';
} catch (e) {
console.error('loadAll error:', e);
}
}
loadAll();
setInterval(loadAll, 60000);
</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) {
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 (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);} });
}
}
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/archi-meta-badge.js" defer></script>
<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>
</body>
</html>