5486 lines
368 KiB
HTML
5486 lines
368 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="fr" data-theme="dark">
|
||
<head>
|
||
<!-- V86 AUTH GUARD WTP · Yacine doctrine: WTP = point entrée unique AVEC AUTHENTIFICATION -->
|
||
<script>
|
||
(function() {
|
||
if (window.__WEVAL_V86_AUTH) return;
|
||
window.__WEVAL_V86_AUTH = true;
|
||
|
||
// Dev bypass: ?dev=1 or localhost
|
||
var isDev = /[?&]dev=1/.test(location.search) || location.hostname === 'localhost' || location.hostname === '127.0.0.1';
|
||
|
||
// Quick check via async fetch (non-blocking for speed, redirects if fail)
|
||
fetch('/api/auth-check.php', { credentials: 'include', cache: 'no-store' })
|
||
.then(function(r) {
|
||
if (r.status === 200) {
|
||
// Authenticated - mark body + log
|
||
document.body && document.body.setAttribute('data-auth', 'ok');
|
||
if (window.console) console.log('[V86 Auth Guard] SSO authenticated (200)');
|
||
} else if (r.status === 401 || r.status === 403) {
|
||
if (isDev) {
|
||
if (window.console) console.warn('[V86 Auth Guard] DEV mode - 401 bypassed');
|
||
document.body && document.body.setAttribute('data-auth', 'dev');
|
||
} else {
|
||
// Show redirect banner + redirect after 2s (UX premium - pas brutal)
|
||
var banner = document.createElement('div');
|
||
banner.style.cssText = 'position:fixed;top:0;left:0;right:0;z-index:99999;background:linear-gradient(135deg,#ef4444,#f59e0b);color:#fff;padding:14px 20px;text-align:center;font:600 14px -apple-system,sans-serif;box-shadow:0 4px 20px rgba(0,0,0,.3);';
|
||
banner.innerHTML = '🔐 Authentification requise · redirection vers /login.html dans <span id="v86-countdown">2</span>s · <a href="/login.html" style="color:#fff;text-decoration:underline;font-weight:700;">cliquer ici</a>';
|
||
(document.body || document.documentElement).appendChild(banner);
|
||
var sec = 2;
|
||
var iv = setInterval(function() {
|
||
sec--;
|
||
var span = document.getElementById('v86-countdown');
|
||
if (span) span.textContent = sec;
|
||
if (sec <= 0) {
|
||
clearInterval(iv);
|
||
location.href = '/login.html?from=' + encodeURIComponent(location.pathname);
|
||
}
|
||
}, 1000);
|
||
}
|
||
} else {
|
||
// Other (500, network etc.) - log + non-blocking
|
||
if (window.console) console.warn('[V86 Auth Guard] auth-check returned', r.status);
|
||
}
|
||
})
|
||
.catch(function(e) {
|
||
// Auth-check unreachable - graceful: allow (don't break WTP if API down)
|
||
if (window.console) console.warn('[V86 Auth Guard] auth-check unreachable, allowing (graceful)', e);
|
||
});
|
||
})();
|
||
</script>
|
||
<!-- V86 AUTH GUARD WTP END -->
|
||
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>WEVAL Technology Platform — All-in-One ERP Portal</title>
|
||
<meta name="description" content="WEVAL Technology Platform — Portail unifié ERP-like tous serveurs, toutes apps, toutes capacités">
|
||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@500;700&display=swap" rel="stylesheet">
|
||
<style>
|
||
:root{
|
||
--bg-0:#05060a;--bg-1:#0a0c14;--bg-2:#11141f;--bg-3:#181c2b;--bg-card:#0e111c;
|
||
--border:#1f2436;--border-hover:#3a425f;
|
||
--text-0:#f1f5f9;--text-1:#cbd5e1;--text-2:#94a3b8;--text-3:#64748b;
|
||
--accent:#6366f1;--accent-hover:#818cf8;
|
||
--success:#10b981;--warning:#f59e0b;--danger:#ef4444;--info:#06b6d4;
|
||
--shadow-lg:0 16px 48px rgba(99,102,241,.2);
|
||
--radius:12px;--radius-sm:8px;
|
||
--trans:.18s cubic-bezier(.4,0,.2,1);
|
||
}
|
||
*{box-sizing:border-box;margin:0;padding:0}
|
||
html,body{height:100%}
|
||
body{font-family:'Inter',system-ui,-apple-system,sans-serif;background:var(--bg-0);color:var(--text-0);font-size:13.5px;line-height:1.5;overflow:hidden}
|
||
a{color:inherit;text-decoration:none}
|
||
/* ===== LAYOUT ===== */
|
||
.wtp-root{display:grid;grid-template-columns:240px 1fr 380px;grid-template-rows:58px 1fr 32px;grid-template-areas:"topbar topbar topbar" "sidebar main chat" "status status status";height:100vh}
|
||
/* ===== TOP BAR ===== */
|
||
.wtp-topbar{grid-area:topbar;background:linear-gradient(90deg,var(--bg-1),var(--bg-2));border-bottom:1px solid var(--border);display:flex;align-items:center;padding:0 18px;gap:18px;z-index:100}
|
||
.wtp-brand{display:flex;align-items:center;gap:10px;font-weight:800;cursor:pointer}
|
||
.wtp-logo{width:34px;height:34px;background:linear-gradient(135deg,#6366f1,#8b5cf6,#ec4899);border-radius:8px;display:flex;align-items:center;justify-content:center;font-size:17px;font-weight:900;box-shadow:0 4px 14px rgba(99,102,241,.4)}
|
||
.wtp-brand-text{display:flex;flex-direction:column;line-height:1.1}
|
||
.wtp-brand-text .top{font-size:13px;letter-spacing:-.01em}
|
||
.wtp-brand-text .sub{font-size:9.5px;color:var(--text-3);font-weight:500;letter-spacing:.09em;margin-top:2px;text-transform:uppercase}
|
||
.wtp-search{flex:1;max-width:580px;position:relative}
|
||
.wtp-search input{width:100%;background:var(--bg-3);border:1px solid var(--border);color:var(--text-0);padding:9px 14px 9px 38px;border-radius:8px;font-size:13px;font-family:inherit;transition:var(--trans)}
|
||
.wtp-search input:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px rgba(99,102,241,.13)}
|
||
.wtp-search::before{content:'⌕';position:absolute;left:12px;top:50%;transform:translateY(-50%);color:var(--text-3);font-size:15px}
|
||
.wtp-search-results{position:absolute;top:100%;left:0;right:0;background:var(--bg-2);border:1px solid var(--border);border-radius:8px;max-height:420px;overflow-y:auto;margin-top:4px;display:none;z-index:200;box-shadow:var(--shadow-lg)}
|
||
.wtp-search-results.show{display:block}
|
||
.wtp-search-result{padding:9px 14px;cursor:pointer;border-bottom:1px solid var(--border);transition:var(--trans)}
|
||
.wtp-search-result:hover{background:var(--bg-3)}
|
||
.wtp-search-result .title{font-size:13px;font-weight:500;color:var(--text-0)}
|
||
.wtp-search-result .module{font-size:11px;color:var(--text-2);margin-top:2px;font-family:'JetBrains Mono',monospace}
|
||
.wtp-search-result mark{background:rgba(99,102,241,.35);color:var(--text-0);padding:0 2px;border-radius:2px}
|
||
.wtp-actions{display:flex;gap:8px;align-items:center}
|
||
.wtp-icon-btn{width:34px;height:34px;background:var(--bg-3);border:1px solid var(--border);border-radius:8px;display:flex;align-items:center;justify-content:center;cursor:pointer;color:var(--text-1);font-size:15px;transition:var(--trans)}
|
||
.wtp-icon-btn:hover{border-color:var(--accent);color:var(--text-0)}
|
||
.wtp-icon-btn .dot{position:absolute;top:6px;right:6px;width:7px;height:7px;background:var(--success);border-radius:50%;box-shadow:0 0 8px var(--success)}
|
||
.wtp-user{display:flex;align-items:center;gap:8px;padding:4px 12px 4px 4px;background:var(--bg-3);border:1px solid var(--border);border-radius:18px;cursor:pointer}
|
||
.wtp-avatar{width:28px;height:28px;border-radius:50%;background:linear-gradient(135deg,#f59e0b,#ef4444);display:flex;align-items:center;justify-content:center;font-weight:700;font-size:11px;color:#fff}
|
||
.wtp-user-name{font-size:12px;font-weight:600}
|
||
/* ===== SIDEBAR ===== */
|
||
.wtp-sidebar{grid-area:sidebar;background:var(--bg-1);border-right:1px solid var(--border);overflow-y:auto;padding:12px 8px}
|
||
.wtp-sidebar::-webkit-scrollbar{width:6px}
|
||
.wtp-sidebar::-webkit-scrollbar-thumb{background:var(--border);border-radius:3px}
|
||
.wtp-nav-label{font-size:9.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--text-3);padding:8px 10px 4px;font-weight:700}
|
||
.wtp-nav-item{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:7px;cursor:pointer;color:var(--text-1);font-size:12.5px;font-weight:500;transition:var(--trans);position:relative;margin-bottom:2px}
|
||
.wtp-nav-item:hover{background:var(--bg-3);color:var(--text-0)}
|
||
.wtp-nav-item.active{background:linear-gradient(90deg,rgba(99,102,241,.18),transparent);color:var(--text-0);padding-left:8px;border-left:2px solid var(--accent)}
|
||
.wtp-nav-icon{font-size:15px;width:20px;text-align:center}
|
||
.wtp-nav-count{margin-left:auto;font-size:10px;padding:1px 6px;background:var(--bg-3);border-radius:9px;color:var(--text-2);font-family:'JetBrains Mono',monospace;font-weight:700;min-width:24px;text-align:center}
|
||
.wtp-nav-item.active .wtp-nav-count{background:var(--accent);color:#fff}
|
||
/* ===== MAIN ===== */
|
||
.wtp-main{grid-area:main;overflow-y:auto;padding:18px 24px;background:var(--bg-0)}
|
||
.wtp-main::-webkit-scrollbar{width:8px}
|
||
.wtp-main::-webkit-scrollbar-thumb{background:var(--border);border-radius:4px}
|
||
.wtp-header{display:flex;align-items:flex-start;justify-content:space-between;margin-bottom:14px;flex-wrap:wrap;gap:12px}
|
||
.wtp-header h1{font-size:22px;font-weight:700;letter-spacing:-.02em;display:flex;align-items:center;gap:12px}
|
||
.wtp-header h1 .module-icon{width:40px;height:40px;background:var(--bg-card);border:1px solid var(--border);border-radius:10px;display:flex;align-items:center;justify-content:center;font-size:21px}
|
||
.wtp-header-desc{font-size:12.5px;color:var(--text-2);margin-top:4px;margin-left:52px}
|
||
.wtp-refresh{background:var(--bg-3);border:1px solid var(--border);color:var(--text-1);padding:7px 12px;border-radius:7px;cursor:pointer;font-size:11.5px;font-family:'JetBrains Mono',monospace;transition:var(--trans)}
|
||
.wtp-refresh:hover{border-color:var(--accent);color:var(--text-0)}
|
||
/* KPI strip */
|
||
.wtp-kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(155px,1fr));gap:10px;margin-bottom:20px}
|
||
.wtp-kpi{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius-sm);padding:11px 14px;transition:var(--trans)}
|
||
.wtp-kpi:hover{border-color:var(--accent-hover);transform:translateY(-1px)}
|
||
.wtp-kpi-label{font-size:9.5px;color:var(--text-3);text-transform:uppercase;letter-spacing:.11em;font-weight:600}
|
||
.wtp-kpi-value{font-size:21px;font-weight:700;margin-top:3px;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
|
||
.wtp-kpi-value.ok{color:var(--success)}
|
||
.wtp-kpi-value.warn{color:var(--warning)}
|
||
.wtp-kpi-value.info{color:var(--info)}
|
||
.wtp-kpi-unit{font-size:11px;color:var(--text-3);font-weight:500;margin-left:4px}
|
||
/* Submodule grid (Fiori tiles) */
|
||
.wtp-section-title{font-size:11px;font-weight:700;letter-spacing:.11em;text-transform:uppercase;color:var(--text-3);margin:12px 0 10px}
|
||
.wtp-tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(290px,1fr));gap:12px}
|
||
.wtp-tile{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);padding:14px 16px;cursor:pointer;transition:var(--trans);position:relative;overflow:hidden}
|
||
.wtp-tile::before{content:'';position:absolute;top:0;left:0;width:100%;height:3px;background:var(--tile-color,var(--accent));opacity:.65;transition:opacity .2s}
|
||
.wtp-tile:hover::before{opacity:1}
|
||
.wtp-tile:hover{transform:translateY(-2px);border-color:var(--tile-color,var(--accent));box-shadow:0 8px 24px rgba(0,0,0,.35)}
|
||
.wtp-tile-head{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:6px;gap:10px}
|
||
.wtp-tile-title{font-size:13.5px;font-weight:600;color:var(--text-0);line-height:1.3}
|
||
.wtp-tile-badge{font-size:9.5px;padding:2px 7px;background:var(--bg-3);border-radius:10px;color:var(--text-2);font-family:'JetBrains Mono',monospace;white-space:nowrap;flex-shrink:0}
|
||
.wtp-tile-badge.live{background:rgba(16,185,129,.18);color:var(--success)}
|
||
.wtp-tile-badge.dormant{background:rgba(100,116,139,.2);color:var(--text-3)}
|
||
.wtp-tile-desc{font-size:11.5px;color:var(--text-2);margin-bottom:10px;line-height:1.45}
|
||
.wtp-tile-meta{display:flex;flex-wrap:wrap;gap:5px;font-size:10.5px}
|
||
.wtp-pill{padding:2px 7px;background:rgba(99,102,241,.12);color:var(--accent-hover);border-radius:6px;font-family:'JetBrains Mono',monospace;font-weight:500}
|
||
.wtp-pill.page{background:rgba(16,185,129,.12);color:var(--success)}
|
||
.wtp-pill.api{background:rgba(245,158,11,.12);color:var(--warning)}
|
||
.wtp-pill.docker{background:rgba(6,182,212,.12);color:var(--info)}
|
||
.wtp-pill.script{background:rgba(236,72,153,.12);color:#f472b6}
|
||
.wtp-pill.path{background:rgba(168,85,247,.12);color:#c084fc}
|
||
.wtp-tile-footer{margin-top:10px;display:flex;justify-content:space-between;align-items:center;padding-top:10px;border-top:1px solid var(--border)}
|
||
.wtp-tile-open{font-size:11px;color:var(--accent-hover);font-weight:600}
|
||
/* HOME view specific */
|
||
.wtp-home-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:12px;margin-bottom:20px}
|
||
.wtp-home-module{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);padding:18px;cursor:pointer;transition:var(--trans);position:relative;overflow:hidden}
|
||
.wtp-home-module::before{content:'';position:absolute;top:0;left:0;width:4px;height:100%;background:var(--mod-color,var(--accent))}
|
||
.wtp-home-module:hover{transform:translateY(-3px);border-color:var(--mod-color,var(--accent));box-shadow:var(--shadow-lg)}
|
||
.wtp-home-icon{font-size:32px;margin-bottom:10px;display:inline-block;filter:drop-shadow(0 4px 12px rgba(99,102,241,.25))}
|
||
.wtp-home-label{font-size:15px;font-weight:700;color:var(--text-0);margin-bottom:4px}
|
||
.wtp-home-tag{font-size:11.5px;color:var(--text-2);line-height:1.45;margin-bottom:12px}
|
||
.wtp-home-stat{display:flex;gap:14px;font-size:11px}
|
||
.wtp-home-stat div{display:flex;align-items:center;gap:4px}
|
||
.wtp-home-stat .num{font-weight:700;color:var(--mod-color,var(--accent));font-family:'JetBrains Mono',monospace}
|
||
.wtp-home-stat .lbl{color:var(--text-3)}
|
||
/* ===== RIGHT CHAT ===== */
|
||
.wtp-chat{grid-area:chat;background:var(--bg-1);border-left:1px solid var(--border);display:flex;flex-direction:column;overflow:hidden}
|
||
.wtp-chat-head{padding:10px 14px;border-bottom:1px solid var(--border);display:flex;align-items:center;justify-content:space-between;background:var(--bg-2)}
|
||
.wtp-chat-title{font-size:12.5px;font-weight:600;display:flex;align-items:center;gap:8px}
|
||
.wtp-chat-title .pulse{width:7px;height:7px;background:var(--success);border-radius:50%;animation:pulse 2s infinite}
|
||
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.35}}
|
||
.wtp-chat-frame{flex:1;width:100%;border:0;background:var(--bg-0)}
|
||
/* ===== STATUS BAR ===== */
|
||
.wtp-statusbar{grid-area:status;background:linear-gradient(90deg,var(--bg-1),var(--bg-2));border-top:1px solid var(--border);display:flex;align-items:center;padding:0 16px;gap:20px;font-size:11px;color:var(--text-2);font-family:'JetBrains Mono',monospace}
|
||
.wtp-status-item{display:flex;align-items:center;gap:5px}
|
||
.wtp-status-item .dot{width:7px;height:7px;border-radius:50%}
|
||
.wtp-status-item .dot.ok{background:var(--success);box-shadow:0 0 6px var(--success)}
|
||
.wtp-status-item .dot.warn{background:var(--warning);box-shadow:0 0 6px var(--warning)}
|
||
.wtp-status-item .dot.err{background:var(--danger);box-shadow:0 0 6px var(--danger)}
|
||
.wtp-status-item strong{color:var(--text-0);font-weight:700}
|
||
.wtp-status-spacer{flex:1}
|
||
/* Loading */
|
||
.wtp-loading{display:flex;align-items:center;justify-content:center;height:200px;color:var(--text-3);font-size:12px}
|
||
.wtp-loading::after{content:'●';animation:dots 1.4s infinite;font-size:20px;margin-left:6px}
|
||
@keyframes dots{0%,20%{opacity:0}40%,100%{opacity:1}}
|
||
/* Responsive — hide chat on small */
|
||
@media(max-width:1280px){.wtp-root{grid-template-columns:220px 1fr 0}.wtp-chat{display:none}}
|
||
@media(max-width:900px){.wtp-root{grid-template-columns:0 1fr 0}.wtp-sidebar{display:none}}
|
||
|
||
/* ===== VISUAL MANAGEMENT PREMIUM (VISUAL-MGMT-PREMIUM-V1, doctrine 60 + L6S) ===== */
|
||
.vm-grid{display:grid;grid-template-columns:repeat(12,1fr);gap:14px;margin-bottom:24px}
|
||
.vm-card{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);padding:16px;position:relative;overflow:hidden;transition:var(--trans)}
|
||
.vm-card:hover{border-color:var(--border-hover)}
|
||
.vm-card-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}
|
||
.vm-card-title{font-size:10.5px;color:var(--text-2);text-transform:uppercase;letter-spacing:.7px;font-weight:600}
|
||
.vm-card-badge{font-size:9.5px;padding:2px 7px;border-radius:8px;background:rgba(16,185,129,.15);color:#5eead4;font-weight:600}
|
||
.vm-card-badge.warn{background:rgba(245,158,11,.15);color:#fbbf24}
|
||
.vm-card-badge.danger{background:rgba(239,68,68,.15);color:#fca5a5}
|
||
|
||
/* Gauges */
|
||
.vm-gauge{position:relative;width:100%;height:125px;display:flex;align-items:center;justify-content:center}
|
||
.vm-gauge svg{width:100%;height:100%;max-width:200px}
|
||
.vm-gauge-value{position:absolute;top:52%;left:50%;transform:translate(-50%,-50%);text-align:center}
|
||
.vm-gauge-num{font-size:28px;font-weight:800;background:linear-gradient(135deg,#22d3ee,#a855f7);-webkit-background-clip:text;background-clip:text;color:transparent;line-height:1}
|
||
.vm-gauge-unit{font-size:10px;color:var(--text-3);margin-top:3px;letter-spacing:.5px}
|
||
.vm-gauge-label{text-align:center;font-size:11px;color:var(--text-2);margin-top:4px;letter-spacing:.3px}
|
||
|
||
/* Andon (Lean 6 Sigma light stack) */
|
||
.vm-andon{display:flex;flex-direction:column;gap:8px;align-items:center;padding:14px 0}
|
||
.vm-light{width:34px;height:34px;border-radius:50%;border:2px solid rgba(255,255,255,.06);position:relative;transition:var(--trans)}
|
||
.vm-light.on.green{background:radial-gradient(circle at 30% 30%,#6ee7b7,#10b981);box-shadow:0 0 20px #10b981,0 0 40px #10b981aa;animation:vm-pulse 2s infinite}
|
||
.vm-light.on.yellow{background:radial-gradient(circle at 30% 30%,#fde68a,#f59e0b);box-shadow:0 0 20px #f59e0b,0 0 40px #f59e0baa;animation:vm-pulse 1.4s infinite}
|
||
.vm-light.on.red{background:radial-gradient(circle at 30% 30%,#fca5a5,#ef4444);box-shadow:0 0 20px #ef4444,0 0 40px #ef4444aa;animation:vm-pulse .9s infinite}
|
||
.vm-light.off{background:var(--bg-3)}
|
||
.vm-light-label{font-size:9.5px;color:var(--text-3);text-align:center;margin-top:2px;font-family:'JetBrains Mono',monospace}
|
||
@keyframes vm-pulse{0%,100%{transform:scale(1)}50%{transform:scale(1.07)}}
|
||
|
||
/* Heatmap */
|
||
.vm-heat{display:grid;grid-template-columns:repeat(12,1fr);gap:2px;margin-top:8px}
|
||
.vm-heat-cell{aspect-ratio:1;border-radius:2px;background:var(--bg-3);position:relative;cursor:help;transition:var(--trans)}
|
||
.vm-heat-cell:hover{transform:scale(1.3);z-index:10;border:1px solid var(--text-0)}
|
||
.vm-heat-cell[data-v="0"]{background:#1f2436}
|
||
.vm-heat-cell[data-v="1"]{background:rgba(16,185,129,.15)}
|
||
.vm-heat-cell[data-v="2"]{background:rgba(16,185,129,.35)}
|
||
.vm-heat-cell[data-v="3"]{background:rgba(16,185,129,.6)}
|
||
.vm-heat-cell[data-v="4"]{background:rgba(16,185,129,1)}
|
||
.vm-heat-cell[data-v="w"]{background:rgba(245,158,11,.6)}
|
||
.vm-heat-cell[data-v="r"]{background:rgba(239,68,68,.8)}
|
||
.vm-heat-legend{display:flex;gap:6px;font-size:9.5px;color:var(--text-3);margin-top:6px;align-items:center}
|
||
.vm-heat-legend span{display:inline-block;width:10px;height:10px;border-radius:2px}
|
||
|
||
/* Sparkline */
|
||
.vm-spark{width:100%;height:54px;display:block}
|
||
.vm-spark path.line{fill:none;stroke:url(#grad-spark);stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round}
|
||
.vm-spark path.area{fill:url(#grad-spark-area);opacity:.35}
|
||
|
||
/* Progress ring for L6S Cp/Cpk */
|
||
.vm-ring{position:relative;width:100%;height:100%}
|
||
.vm-ring svg{transform:rotate(-90deg)}
|
||
.vm-ring-text{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center}
|
||
|
||
/* Bar compare (ACQUIS vs DORMANTS) */
|
||
.vm-bars{display:flex;flex-direction:column;gap:6px;margin-top:6px}
|
||
.vm-bar-row{display:grid;grid-template-columns:75px 1fr 42px;gap:8px;align-items:center;font-size:11px}
|
||
.vm-bar-label{color:var(--text-1);font-weight:500}
|
||
.vm-bar-track{height:8px;background:var(--bg-3);border-radius:4px;overflow:hidden;position:relative}
|
||
.vm-bar-fill{height:100%;border-radius:4px;transition:width 1.2s cubic-bezier(.4,0,.2,1);background:linear-gradient(90deg,#10b981,#06b6d4)}
|
||
.vm-bar-fill.warn{background:linear-gradient(90deg,#f59e0b,#ef4444)}
|
||
.vm-bar-count{text-align:right;color:var(--text-1);font-weight:600;font-family:'JetBrains Mono',monospace}
|
||
|
||
/* Kanban flow (L6S value stream) */
|
||
.vm-flow{display:grid;grid-template-columns:repeat(6,1fr);gap:4px;margin-top:8px}
|
||
.vm-flow-step{text-align:center;padding:7px 4px;background:var(--bg-3);border-radius:6px;position:relative;font-size:10px;color:var(--text-2)}
|
||
.vm-flow-step.done{background:rgba(16,185,129,.2);color:#6ee7b7}
|
||
.vm-flow-step.work{background:rgba(99,102,241,.2);color:#a5b4fc;animation:vm-pulse 2s infinite}
|
||
.vm-flow-step.block{background:rgba(239,68,68,.2);color:#fca5a5}
|
||
.vm-flow-step .num{display:block;font-size:16px;font-weight:800;margin-bottom:2px}
|
||
|
||
/* Coverage donut */
|
||
.vm-donut-wrap{display:flex;align-items:center;gap:16px}
|
||
.vm-donut{position:relative;width:110px;height:110px;flex-shrink:0}
|
||
.vm-donut svg{transform:rotate(-90deg)}
|
||
.vm-donut-text{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center}
|
||
.vm-donut-big{font-size:24px;font-weight:800;color:var(--text-0)}
|
||
.vm-donut-lbl{font-size:9px;color:var(--text-3);letter-spacing:.5px;text-transform:uppercase}
|
||
.vm-donut-list{flex:1;display:flex;flex-direction:column;gap:5px;font-size:10.5px}
|
||
.vm-donut-list div{display:flex;justify-content:space-between;align-items:center}
|
||
.vm-donut-list .dot{width:8px;height:8px;border-radius:50%;display:inline-block;margin-right:6px}
|
||
|
||
/* Scorecard (Andon KPI) */
|
||
.vm-score{text-align:center;padding:6px 0}
|
||
.vm-score-big{font-size:32px;font-weight:800;line-height:1}
|
||
.vm-score-big.ok{color:#10b981}
|
||
.vm-score-big.warn{color:#f59e0b}
|
||
.vm-score-big.danger{color:#ef4444}
|
||
.vm-score-sub{font-size:10.5px;color:var(--text-3);margin-top:4px;letter-spacing:.3px}
|
||
|
||
/* Span utilities */
|
||
.vm-col-4{grid-column:span 4}.vm-col-3{grid-column:span 3}.vm-col-6{grid-column:span 6}.vm-col-8{grid-column:span 8}.vm-col-12{grid-column:span 12}
|
||
@media(max-width:1280px){.vm-col-4{grid-column:span 6}.vm-col-3{grid-column:span 6}}
|
||
|
||
/* Pulse live indicator */
|
||
.vm-live{display:inline-flex;align-items:center;gap:5px;font-size:9.5px;color:#10b981}
|
||
.vm-live::before{content:'';width:6px;height:6px;background:#10b981;border-radius:50%;box-shadow:0 0 6px #10b981;animation:vm-pulse 1.5s infinite}
|
||
|
||
/* Hide old static kpi cards when VM active */
|
||
.vm-active .wtp-kpis{display:none}
|
||
|
||
|
||
/* ===== V64-DEPTS-KPI-BESTPRACTICES (SAP SAFe PMI L6S) ===== */
|
||
.v64-dept-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:10px;margin-top:6px}
|
||
@media(max-width:1280px){.v64-dept-grid{grid-template-columns:repeat(3,1fr)}}
|
||
@media(max-width:768px){.v64-dept-grid{grid-template-columns:repeat(2,1fr)}}
|
||
.v64-dept{background:var(--bg-3);border-radius:8px;padding:9px 10px;border-left:3px solid var(--dcol,#6366f1);position:relative;transition:var(--trans);cursor:default}
|
||
.v64-dept:hover{background:var(--bg-2);transform:translateY(-1px)}
|
||
.v64-dept-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:6px}
|
||
.v64-dept-name{font-size:11px;font-weight:600;color:var(--text-0);display:flex;align-items:center;gap:5px}
|
||
.v64-dept-sap{font-size:8.5px;color:var(--text-3);font-family:'JetBrains Mono',monospace;padding:1px 5px;background:rgba(99,102,241,.1);border-radius:3px}
|
||
.v64-dept-kpis{display:grid;grid-template-columns:repeat(2,1fr);gap:4px;font-size:9.5px}
|
||
.v64-dept-kpi{background:var(--bg-1);padding:4px 6px;border-radius:4px;position:relative}
|
||
.v64-dept-kpi .l{color:var(--text-3);font-size:9px;letter-spacing:.2px;display:block;margin-bottom:1px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||
.v64-dept-kpi .v{color:var(--text-0);font-weight:700;font-size:10.5px;font-family:'JetBrains Mono',monospace}
|
||
.v64-dept-kpi .t{color:var(--text-3);font-size:8.5px;font-family:'JetBrains Mono',monospace}
|
||
.v64-dept-kpi.ok{border-left:2px solid #10b981}
|
||
.v64-dept-kpi.warn{border-left:2px solid #f59e0b}
|
||
.v64-dept-kpi.critical{border-left:2px solid #ef4444}
|
||
.v64-dept-kpi.critical .v{color:#fca5a5}
|
||
.v64-dept-kpi.warn .v{color:#fbbf24}
|
||
.v64-dept-kpi.ok .v{color:#6ee7b7}
|
||
.v64-dept-agents{display:flex;align-items:center;gap:6px;margin-top:6px;font-size:9px;color:var(--text-3)}
|
||
.v64-dept-agents .pct-bar{flex:1;height:3px;background:var(--bg-0);border-radius:2px;overflow:hidden}
|
||
.v64-dept-agents .pct-fill{height:100%;background:linear-gradient(90deg,#10b981,#06b6d4);transition:width 1s cubic-bezier(.4,0,.2,1)}
|
||
|
||
/* Best practices */
|
||
.v64-bp-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:10px;margin-top:8px}
|
||
@media(max-width:1280px){.v64-bp-grid{grid-template-columns:repeat(2,1fr)}}
|
||
.v64-bp{background:var(--bg-3);border-radius:8px;padding:12px;position:relative}
|
||
.v64-bp-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:10px}
|
||
.v64-bp-title{font-size:11px;font-weight:600;color:var(--text-0);display:flex;align-items:center;gap:6px}
|
||
.v64-bp-maturity{font-size:13px;font-weight:800;font-family:'JetBrains Mono',monospace}
|
||
.v64-bp-maturity.ok{color:#10b981}
|
||
.v64-bp-maturity.warn{color:#f59e0b}
|
||
.v64-bp-maturity.low{color:#ef4444}
|
||
.v64-bp-ring{width:100%;height:46px;margin-bottom:10px;display:flex;align-items:center;gap:10px}
|
||
.v64-bp-ring-bar{flex:1;height:6px;background:var(--bg-0);border-radius:3px;overflow:hidden;position:relative}
|
||
.v64-bp-ring-fill{height:100%;background:linear-gradient(90deg,#ef4444 0%,#f59e0b 40%,#10b981 80%);transition:width 1.2s cubic-bezier(.4,0,.2,1)}
|
||
.v64-bp-principles{display:flex;flex-direction:column;gap:4px;font-size:10px}
|
||
.v64-bp-p{display:flex;align-items:center;justify-content:space-between;padding:3px 6px;background:var(--bg-1);border-radius:4px}
|
||
.v64-bp-p-label{color:var(--text-1);flex:1}
|
||
.v64-bp-p-status{font-size:9px;padding:1px 5px;border-radius:8px;font-weight:600;margin-left:4px;white-space:nowrap}
|
||
.v64-bp-p-status.ok{background:rgba(16,185,129,.18);color:#6ee7b7}
|
||
.v64-bp-p-status.partial{background:rgba(245,158,11,.18);color:#fbbf24}
|
||
.v64-bp-p-status.missing{background:rgba(239,68,68,.18);color:#fca5a5}
|
||
|
||
/* Gaps list */
|
||
.v64-gaps{display:grid;grid-template-columns:repeat(3,1fr);gap:6px;max-height:260px;overflow-y:auto;padding-right:4px}
|
||
@media(max-width:1280px){.v64-gaps{grid-template-columns:repeat(2,1fr)}}
|
||
@media(max-width:768px){.v64-gaps{grid-template-columns:1fr}}
|
||
.v64-gap{background:var(--bg-3);border-radius:6px;padding:7px 10px;border-left:2.5px solid #ef4444;display:flex;align-items:center;justify-content:space-between;font-size:10px;gap:8px}
|
||
.v64-gap:hover{background:var(--bg-2)}
|
||
.v64-gap-name{color:var(--text-0);font-weight:600;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||
.v64-gap-dept{color:var(--text-3);font-family:'JetBrains Mono',monospace;font-size:8.5px;padding:1px 5px;background:rgba(99,102,241,.12);border-radius:3px;white-space:nowrap}
|
||
.v64-gaps::-webkit-scrollbar{width:6px}
|
||
.v64-gaps::-webkit-scrollbar-track{background:var(--bg-0)}
|
||
.v64-gaps::-webkit-scrollbar-thumb{background:var(--bg-3);border-radius:3px}
|
||
|
||
|
||
/* V73-FIORI-TILES - SAP S/4HANA Fiori-inspired sub-module rendering */
|
||
.wtp-tile{display:flex;flex-direction:column;min-height:152px}
|
||
.wtp-tile-icon{font-size:22px;line-height:1;margin-bottom:10px;opacity:0.85}
|
||
.wtp-tile:hover .wtp-tile-icon{opacity:1;transform:scale(1.1);transition:transform .2s}
|
||
.wtp-tile-title{font-weight:700 !important}
|
||
.wtp-tile-meta .wtp-pill{transition:all .15s}
|
||
.wtp-tile-meta .wtp-pill:hover{transform:translateY(-1px);box-shadow:0 2px 8px rgba(99,102,241,0.25)}
|
||
/* V73 new subfooter */
|
||
.wtp-tile-subfooter{margin-top:auto;padding-top:10px;border-top:1px solid var(--border);display:flex;justify-content:space-between;align-items:center;font-size:10.5px;color:var(--text-3)}
|
||
.wtp-tile-subfooter .kpi-mini{font-family:'JetBrains Mono',monospace;color:var(--success);font-weight:700}
|
||
|
||
</style>
|
||
|
||
|
||
<!-- V108 Plausible Analytics -->
|
||
<script defer data-domain="weval-consulting.com" src="https://analytics.weval-consulting.com/js/script.js"></script>
|
||
<link rel="stylesheet" href="/css/wevia-portal-consistency.css">
|
||
<style id="wave264-css-override">
|
||
/* WAVE_264: prevent collisions between injected Logout and WTP Yacine button */
|
||
#weval-gl { top: 92px !important; right: 12px !important; }
|
||
/* Prevent Droid old bottom position from being re-added by cache */
|
||
a#opus-droid-link[style*="bottom:20px"] { top: 12px !important; right: 200px !important; bottom: auto !important; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="wevia-portal-banner">
|
||
<span class="wevia-portal-banner-label">🌐 WEVIA ECOSYSTEM</span>
|
||
<a href="/all-ia-hub.html" data-portal="hub" class="wevia-portal-banner-link">🧠 All-IA Hub</a>
|
||
<a href="/wevia-master.html" data-portal="master" class="wevia-portal-banner-link">🤖 WEVIA Master</a>
|
||
<a href="/wevia-orchestrator.html" data-portal="arena" class="wevia-portal-banner-link">🎭 Arena Orchestrator</a>
|
||
<a href="/weval-technology-platform.html" data-portal="wtp" class="wevia-portal-banner-link wevia-current">🧭 WTP Hub</a>
|
||
<span class="wevia-portal-badge-wave">WAVE 264</span>
|
||
<!-- WAVE_264_CONSOLIDATE: Factory + Archi + Yacine dans top banner -->
|
||
<span id="w264-factory-pill" onclick="w263Open()" style="margin-left:12px;padding:4px 12px;border-radius:14px;background:linear-gradient(135deg,rgba(34,211,238,.2),rgba(168,85,247,.15));border:1px solid rgba(34,211,238,.4);color:#67e8f9;font-size:11px;font-weight:700;cursor:pointer;display:inline-flex;align-items:center;gap:5px" title="Factory Health Monitor (30 agents)"><span>🏭</span><span id="w264-factory-badge">Factory: --</span></span>
|
||
<button onclick="v80Open()" style="margin-left:8px;background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff;border:none;padding:4px 12px;border-radius:14px;cursor:pointer;font-size:11px;font-weight:700;display:inline-flex;align-items:center;gap:5px" title="Archi complete"><span>🧭</span>Archi</button>
|
||
<span style="margin-left:8px;display:inline-flex;align-items:center;gap:6px;padding:3px 10px 3px 4px;background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.1);border-radius:14px">
|
||
<span style="width:22px;height:22px;border-radius:50%;background:linear-gradient(135deg,#f59e0b,#ef4444);color:#fff;font-size:10px;font-weight:800;display:inline-flex;align-items:center;justify-content:center">YM</span>
|
||
<span style="color:#cbd5e1;font-size:11px;font-weight:600">Yacine M.</span>
|
||
</span>
|
||
</div>
|
||
|
||
|
||
|
||
|
||
|
||
<div class="wtp-root">
|
||
<!-- TOP BAR -->
|
||
<div class="wtp-topbar">
|
||
<div class="wtp-brand" onclick="navigateTo('home')">
|
||
<div class="wtp-logo">W</div>
|
||
<div class="wtp-brand-text">
|
||
<div class="top">WEVAL Technology</div>
|
||
<div class="sub">Platform · ERP Portal</div>
|
||
</div>
|
||
</div>
|
||
<div class="wtp-search">
|
||
<input type="text" id="wtp-search-input" placeholder="Rechercher page, API, app, module, agent…" autocomplete="off">
|
||
<div class="wtp-search-results" id="wtp-search-results"></div>
|
||
</div>
|
||
<div class="wtp-actions">
|
||
<div class="wtp-icon-btn" title="Notifications" onclick="showNotifications()" style="position:relative">🔔<span class="dot"></span></div>
|
||
<div class="wtp-icon-btn" title="Help" onclick="openUrl('/wiki/')">?</div>
|
||
<!-- WAVE_264_CONSOLIDATE: Archi + Yacine moved to top banner -->
|
||
</div>
|
||
</div>
|
||
|
||
<!-- LEFT SIDEBAR -->
|
||
<div class="wtp-sidebar" id="wtp-sidebar">
|
||
<div class="wtp-nav-label">Portail</div>
|
||
<div class="wtp-nav-item active" data-mod="home" onclick="navigateTo('home')">
|
||
<span class="wtp-nav-icon">🏠</span><span>Accueil</span>
|
||
</div>
|
||
<div class="wtp-nav-label">Modules ERP</div>
|
||
<div id="wtp-nav-modules"></div>
|
||
<div class="wtp-nav-label" style="margin-top:16px">📊 Dashboards</div>
|
||
<div class="wtp-nav-item" onclick="window.location.href='/dashboards-index.html'" style="cursor:pointer">
|
||
<span class="wtp-nav-icon">🎯</span><span>Dashboards Index</span>
|
||
</div>
|
||
<div class="wtp-nav-item" onclick="window.location.href='/wtp-udock-coverage.html'" style="cursor:pointer">
|
||
<span class="wtp-nav-icon">🔗</span><span>Dock Coverage</span>
|
||
</div>
|
||
<div class="wtp-nav-item" onclick="window.location.href='/token-health-dashboard.html'" style="cursor:pointer">
|
||
<span class="wtp-nav-icon">🔑</span><span>Token Health</span>
|
||
</div>
|
||
<div class="wtp-nav-item" onclick="window.location.href='/command-center.html'" style="cursor:pointer">
|
||
<span class="wtp-nav-icon">🎛</span><span>Command Center</span>
|
||
</div>
|
||
<div class="wtp-nav-label" style="margin-top:16px">🧠 IA</div>
|
||
<div class="wtp-nav-item" onclick="window.location.href='/wevia-master.html'" style="cursor:pointer">
|
||
<span class="wtp-nav-icon">🤖</span><span>WEVIA Master</span>
|
||
</div>
|
||
<div class="wtp-nav-item" onclick="window.location.href='/all-ia-hub.html'" style="cursor:pointer">
|
||
<span class="wtp-nav-icon">🎓</span><span>All-IA Hub</span>
|
||
</div>
|
||
<div class="wtp-nav-item" onclick="window.location.href='/wevia-orchestrator.html'" style="cursor:pointer">
|
||
<span class="wtp-nav-icon">🎼</span><span>Orchestrator</span>
|
||
</div>
|
||
<div class="wtp-nav-label" style="margin-top:16px">📘 Knowledge</div>
|
||
<div class="wtp-nav-item" onclick="window.location.href='/wiki.html'" style="cursor:pointer">
|
||
<span class="wtp-nav-icon">📘</span><span>Wiki</span>
|
||
</div>
|
||
<div class="wtp-nav-item" onclick="window.location.href='/nonreg.html'" style="cursor:pointer">
|
||
<span class="wtp-nav-icon">✅</span><span>NonReg</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- MAIN AREA -->
|
||
<div class="wtp-main" id="wtp-main">
|
||
<div class="wtp-loading">Chargement de la plateforme</div>
|
||
</div>
|
||
|
||
<!-- RIGHT CHAT (WEVIA Master) -->
|
||
<div class="wtp-chat">
|
||
<div class="wtp-chat-head">
|
||
<div class="wtp-chat-title"><span class="pulse"></span>WEVIA Master · multi-agents</div>
|
||
<div class="wtp-icon-btn" title="Ouvrir en plein écran" onclick="openUrl('/wevia-master.html')" style="width:28px;height:28px;font-size:12px">⤢</div>
|
||
</div>
|
||
<iframe class="wtp-chat-frame" src="/wevia-widget.html" title="WEVIA Master chat"></iframe>
|
||
</div>
|
||
|
||
<!-- STATUS BAR -->
|
||
<div class="wtp-statusbar" id="wtp-statusbar">
|
||
<div class="wtp-status-item"><span class="dot ok"></span>S204 <strong>live</strong></div>
|
||
<div class="wtp-status-item"><span class="dot ok"></span>S95 <strong>live</strong></div>
|
||
<div class="wtp-status-item" id="st-blade-wrap"><span class="dot warn" id="st-blade-dot"></span><span id="st-blade-label">Blade <strong id="st-blade-text">checking</strong></span></div>
|
||
<div class="wtp-status-item">Docker <strong id="st-docker">–</strong></div>
|
||
<div class="wtp-status-item">Providers <strong id="st-prov">–</strong></div>
|
||
<div class="wtp-status-item">Qdrant <strong id="st-qdrant">–</strong></div>
|
||
<div class="wtp-status-item">NonReg <strong id="st-nr">–</strong></div>
|
||
<div class="wtp-status-item">HCPs <strong id="st-hcp">–</strong></div>
|
||
<div class="wtp-status-spacer"></div>
|
||
<div class="wtp-status-item">WTP <strong id="st-ver">v2.0</strong></div>
|
||
<div class="wtp-status-item" id="st-time">–</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
let TREE = null;
|
||
let CURRENT_MOD = 'home';
|
||
const COLORS = {intelligence:'#6366f1',commerce:'#10b981',finance:'#f97316',marketing:'#f59e0b',growth:'#ec4899',hr:'#0ea5e9',supply:'#84cc16',operations:'#8b5cf6',erp_integrations:'#dc2626',communications:'#f43f5e',security:'#6b7280',development:'#06b6d4',knowledge:'#0d9488',multimodal:'#a855f7',rnd_labs:'#7c3aed'};
|
||
|
||
// Load full tree from API
|
||
async function loadTree(){
|
||
try{
|
||
const r = await fetch('/api/weval-technology-platform-api.php');
|
||
TREE = await r.json();
|
||
renderSidebar();
|
||
renderStatusBar();
|
||
navigateTo(CURRENT_MOD);
|
||
}catch(e){
|
||
document.getElementById('wtp-main').innerHTML = '<div class="wtp-loading">Erreur chargement API: '+e.message+'</div>';
|
||
}
|
||
}
|
||
|
||
function renderSidebar(){
|
||
const el = document.getElementById('wtp-nav-modules');
|
||
if (!TREE) return;
|
||
// 16 ERP modules
|
||
let html = Object.entries(TREE.modules).map(([id, mod]) => {
|
||
const count = (mod.submodules||[]).length;
|
||
return `<div class="wtp-nav-item" data-mod="${id}" onclick="navigateTo('${id}')">
|
||
<span class="wtp-nav-icon" style="color:${mod.color}">${mod.icon}</span>
|
||
<span>${mod.label}</span>
|
||
<span class="wtp-nav-count">${count}</span>
|
||
</div>`;
|
||
}).join('');
|
||
|
||
// SECTION SÉPARATRICE · POINT D'ENTRÉE ENRICHI (Opus Yacine 19avr)
|
||
html += `<div style="padding:10px 14px 6px;font-size:10px;color:var(--wtp-muted);text-transform:uppercase;letter-spacing:1.5px;margin-top:14px;border-top:1px solid var(--wtp-border);padding-top:14px">POINT D'ENTRÉE TOTAL</div>`;
|
||
|
||
const extras = [
|
||
{id:'infra', icon:'🖥', label:'Infrastructure', color:'#22d3ee', count: (TREE.infra?.machines?.length||0) + (TREE.infra?.docker?.length||0)},
|
||
{id:'all_pages', icon:'📂', label:'Toutes les pages', color:'#d4af37', count: TREE.all_pages?.total||0},
|
||
{id:'all_apis', icon:'🔌', label:'Toutes les APIs', color:'#a855f7', count: TREE.apis?.total||0},
|
||
{id:'multiagent', icon:'🤖', label:'Multi-Agent Modes', color:'#ef4444', count: TREE.multiagent_modes?.length||0},
|
||
{id:'truth', icon:'🔒', label:'Truth Registry', color:'#22c55e', count: TREE.truth_registry?.agents||0},
|
||
{id:'crm_bridge', icon:'🔗', label:'CRM Bridge (4 CRMs)', color:'#22d3ee', count: 4},
|
||
];
|
||
html += extras.map(e => `<div class="wtp-nav-item" data-mod="${e.id}" onclick="navigateTo('${e.id}')">
|
||
<span class="wtp-nav-icon" style="color:${e.color}">${e.icon}</span>
|
||
<span>${e.label}</span>
|
||
<span class="wtp-nav-count">${e.count}</span>
|
||
</div>`).join('');
|
||
|
||
el.innerHTML = html;
|
||
}
|
||
|
||
function navigateTo(modId){
|
||
CURRENT_MOD = modId;
|
||
document.querySelectorAll('.wtp-nav-item').forEach(i => i.classList.toggle('active', i.dataset.mod === modId));
|
||
if (modId === 'home') renderHome();
|
||
else if (modId === 'infra') renderInfra();
|
||
else if (modId === 'crm_bridge') { window.open('/wevia-ia/wevia-admin-crm-v68.php', '_blank'); return; }
|
||
else if (modId === 'all_pages') renderAllPages();
|
||
else if (modId === 'all_apis') renderAllApis();
|
||
else if (modId === 'multiagent') renderMultiagent();
|
||
else if (modId === 'truth') renderTruth();
|
||
else renderModule(modId);
|
||
document.getElementById('wtp-main').scrollTop = 0;
|
||
}
|
||
|
||
// === POINT D'ENTRÉE TOTAL views (Opus Yacine 19avr) ===
|
||
function renderInfra(){
|
||
const main = document.getElementById('wtp-main');
|
||
const i = TREE.infra || {};
|
||
const machines = (i.machines||[]).map(m => `
|
||
<div style="background:var(--wtp-panel2);padding:18px;border-radius:8px;border:1px solid var(--wtp-border)">
|
||
<div style="font-size:18px;font-weight:800;margin-bottom:4px;color:var(--wtp-ac)">${m.id}</div>
|
||
<div style="font-size:11px;color:var(--wtp-muted);margin-bottom:10px">${m.type||''}</div>
|
||
<div style="font-size:13px;line-height:1.6">${m.role||''}</div>
|
||
${m.cpu ? `<div style="margin-top:8px;font-size:11px;color:var(--wtp-muted)">CPU: ${m.cpu} · RAM: ${m.ram||'?'} · Disk: ${m.disk||'?'}</div>` : ''}
|
||
</div>`).join('');
|
||
|
||
const docker = (i.docker||[]).slice(0, 25).map(d => `
|
||
<div style="display:flex;justify-content:space-between;padding:8px 12px;background:var(--wtp-panel);border-radius:6px;margin-bottom:4px;font-size:12px">
|
||
<span style="font-weight:600">${d.name||'?'}</span>
|
||
<span style="color:var(--wtp-muted);font-family:monospace;font-size:10px">${d.status||''}</span>
|
||
</div>`).join('');
|
||
|
||
const gpus = (i.gpus||[]).map(g => `
|
||
<div style="background:var(--wtp-panel);padding:14px;border-radius:8px;margin-bottom:6px">
|
||
<div style="font-weight:700">${g.name||'?'}</div>
|
||
<div style="font-size:11px;color:var(--wtp-muted);margin-top:4px">${g.note||''}</div>
|
||
${g.mem_total_mb ? `<div style="margin-top:6px;font-family:monospace;font-size:11px">Mem: ${g.mem_used_mb}/${g.mem_total_mb} MB · Temp: ${g.temp_c}°C · Util: ${g.util_pct}%</div>` : ''}
|
||
</div>`).join('');
|
||
|
||
const subdoms = Object.entries(i.subdomains||{}).map(([d, role]) => `
|
||
<a href="https://${d}/" target="_blank" style="display:flex;justify-content:space-between;padding:8px 12px;background:var(--wtp-panel);border-radius:6px;margin-bottom:4px;font-size:12px;text-decoration:none;color:var(--wtp-text)">
|
||
<span style="font-family:monospace">${d}</span>
|
||
<span style="color:var(--wtp-muted)">${role}</span>
|
||
</a>`).join('');
|
||
|
||
main.innerHTML = `
|
||
<div style="padding:24px">
|
||
<h1 style="font-size:28px;margin-bottom:6px">🖥 Infrastructure</h1>
|
||
<div style="color:var(--wtp-muted);margin-bottom:24px">Machines · Docker · GPUs · Blade · Subdomains · tout en un</div>
|
||
|
||
<h2 style="font-size:18px;margin-bottom:12px">💻 Machines · ${(i.machines||[]).length}</h2>
|
||
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:12px;margin-bottom:28px">${machines}</div>
|
||
|
||
<h2 style="font-size:18px;margin-bottom:12px">🔧 Blade yacineutt (Sentinel · Chrome persist)</h2>
|
||
<div style="background:var(--wtp-panel2);padding:18px;border-radius:8px;border:1px solid var(--wtp-border);margin-bottom:28px">
|
||
<div style="font-size:14px;font-weight:700;margin-bottom:8px">${i.blade?.host||'Razer Blade'}</div>
|
||
<div style="color:var(--wtp-muted);font-size:12px;margin-bottom:10px">${i.blade?.role||''}</div>
|
||
<div style="font-size:12px;margin-bottom:6px">Profile: ${i.blade?.yacineutt_profile||'?'}</div>
|
||
<div style="display:flex;gap:6px;flex-wrap:wrap;margin-top:10px">
|
||
${(i.blade?.services||[]).map(s=>`<span style="background:var(--wtp-panel);padding:4px 10px;border-radius:99px;font-size:11px;font-family:monospace">${s}</span>`).join('')}
|
||
</div>
|
||
</div>
|
||
|
||
<h2 style="font-size:18px;margin-bottom:12px">🎮 GPUs · ${(i.gpus||[]).length}</h2>
|
||
${gpus}
|
||
<div style="height:24px"></div>
|
||
|
||
<h2 style="font-size:18px;margin-bottom:12px">🐳 Docker · ${(i.docker||[]).length} containers</h2>
|
||
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:6px;margin-bottom:28px">${docker}</div>
|
||
|
||
<h2 style="font-size:18px;margin-bottom:12px">🌐 Subdomains · ${Object.keys(i.subdomains||{}).length}</h2>
|
||
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:6px">${subdoms}</div>
|
||
</div>`;
|
||
}
|
||
|
||
function renderAllPages(){
|
||
const main = document.getElementById('wtp-main');
|
||
const ap = TREE.all_pages || {};
|
||
const cats = ap.pages_by_category || {};
|
||
const catHtml = Object.entries(cats).sort((a,b)=>b[1].length-a[1].length).map(([cat, pages]) => {
|
||
const items = pages.slice(0, 50).map(p => `
|
||
<a href="${p.url}" style="display:flex;justify-content:space-between;padding:7px 11px;background:var(--wtp-panel);border:1px solid var(--wtp-border);border-radius:5px;text-decoration:none;color:var(--wtp-text);font-size:12px;transition:.15s"
|
||
onmouseover="this.style.borderColor='var(--wtp-ac)'" onmouseout="this.style.borderColor='var(--wtp-border)'">
|
||
<span style="font-weight:500">${p.name.replace(/\.html$/,'').replace(/[-_]/g,' ')}</span>
|
||
<span style="color:var(--wtp-muted);font-family:monospace;font-size:10px">${p.size_kb}k${p.is_orphan?' ·⚠':''}</span>
|
||
</a>`).join('');
|
||
return `<div style="margin-bottom:24px">
|
||
<h3 style="font-size:15px;margin-bottom:10px;display:flex;justify-content:space-between">
|
||
<span>${cat}</span><span style="color:var(--wtp-muted);font-size:11px;font-weight:400">${pages.length} pages</span>
|
||
</h3>
|
||
<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(340px,1fr));gap:4px">${items}</div>
|
||
${pages.length>50?`<div style="color:var(--wtp-muted);font-size:11px;margin-top:6px">+${pages.length-50} autres</div>`:''}
|
||
</div>`;
|
||
}).join('');
|
||
|
||
main.innerHTML = `
|
||
<div style="padding:24px">
|
||
<h1 style="font-size:28px;margin-bottom:6px">📂 Toutes les pages · ${ap.total}</h1>
|
||
<div style="color:var(--wtp-muted);margin-bottom:20px">${ap.orphans} orphelines identifiées · toutes accessibles depuis WTP</div>
|
||
<div style="margin-bottom:18px">
|
||
<input type="text" id="pg-search" placeholder="Recherche page..." oninput="_pgSearch(this.value)" style="width:100%;padding:12px 16px;background:var(--wtp-panel);border:1px solid var(--wtp-border);color:var(--wtp-text);border-radius:6px;font-size:13px;outline:none">
|
||
</div>
|
||
<div id="pg-content">${catHtml}</div>
|
||
</div>`;
|
||
}
|
||
window._pgSearch = function(q){
|
||
q = (q||'').toLowerCase();
|
||
document.querySelectorAll('#pg-content a').forEach(a => {
|
||
a.style.display = (!q || a.textContent.toLowerCase().includes(q)) ? '' : 'none';
|
||
});
|
||
};
|
||
|
||
function renderAllApis(){
|
||
const main = document.getElementById('wtp-main');
|
||
const a = TREE.apis || {};
|
||
main.innerHTML = `
|
||
<div style="padding:24px">
|
||
<h1 style="font-size:28px;margin-bottom:6px">🔌 Toutes les APIs · ${a.total}</h1>
|
||
<div style="color:var(--wtp-muted);margin-bottom:24px">Endpoints PHP dans /api/</div>
|
||
<h2 style="font-size:16px;margin-bottom:10px">Top WEVIA APIs (${(a.top_wevia||[]).length})</h2>
|
||
<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:6px">
|
||
${(a.top_wevia||[]).map(api => `
|
||
<a href="/api/${api}" target="_blank" style="padding:8px 12px;background:var(--wtp-panel);border:1px solid var(--wtp-border);border-radius:5px;text-decoration:none;color:var(--wtp-text);font-size:12px;font-family:monospace">
|
||
${api}
|
||
</a>`).join('')}
|
||
</div>
|
||
</div>`;
|
||
}
|
||
|
||
function renderMultiagent(){
|
||
const main = document.getElementById('wtp-main');
|
||
const modes = TREE.multiagent_modes || [];
|
||
main.innerHTML = `
|
||
<div style="padding:24px">
|
||
<h1 style="font-size:28px;margin-bottom:6px">🤖 Multi-Agent Modes</h1>
|
||
<div style="color:var(--wtp-muted);margin-bottom:24px">3 modes coexistent via WEVIA Master chat · /wevia-master.html</div>
|
||
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:14px">
|
||
${modes.map((m, i) => `
|
||
<div style="background:var(--wtp-panel2);padding:20px;border-radius:10px;border:1px solid var(--wtp-border);border-left:4px solid ${['#6366f1','#22c55e','#f59e0b'][i]||'#6366f1'}">
|
||
<div style="font-size:17px;font-weight:800;margin-bottom:6px">${m.mode}</div>
|
||
<div style="font-size:22px;font-weight:700;margin:8px 0">${m.agents || m.agents_target} agents</div>
|
||
<div style="font-size:12px;color:var(--wtp-muted);margin-bottom:8px">Latency: <span style="color:var(--wtp-ac);font-family:monospace">${m.latency_ms}ms</span></div>
|
||
<div style="font-size:12px;margin-bottom:10px">${m.use}</div>
|
||
<div style="font-size:10px;color:var(--wtp-muted);font-family:monospace;padding:6px 10px;background:var(--wtp-panel);border-radius:4px">${m.trigger}</div>
|
||
</div>`).join('')}
|
||
</div>
|
||
<div style="margin-top:24px;padding:18px;background:var(--wtp-panel2);border-radius:8px">
|
||
<strong>💬 Tester en live:</strong> ouvre <a href="/wevia-master.html" style="color:var(--wtp-ac)">/wevia-master.html</a> et tape "agis en multiagent"
|
||
</div>
|
||
</div>`;
|
||
}
|
||
|
||
function renderTruth(){
|
||
const main = document.getElementById('wtp-main');
|
||
const t = TREE.truth_registry || {};
|
||
main.innerHTML = `
|
||
<div style="padding:24px">
|
||
<h1 style="font-size:28px;margin-bottom:6px">🔒 Truth Registry · source unique</h1>
|
||
<div style="color:var(--wtp-muted);margin-bottom:24px">Built: <span style="font-family:monospace">${t.built_at||'?'}</span> · rebuild cron /30min</div>
|
||
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:10px;margin-bottom:24px">
|
||
${[['Agents',t.agents,'#d4af37'],['Intents',t.intents,'#22c55e'],['Skills',t.skills,'#6366f1'],['Brains',t.brains,'#a855f7'],['Doctrines',t.doctrines,'#ef4444'],['Dashboards',t.dashboards,'#22d3ee'],['Providers',t.providers,'#f59e0b'],['Qdrant Cols',t.qdrant_cols,'#ec4899'],['Qdrant Points',t.qdrant_points,'#10b981'],['Autonomy',(t.autonomy_score||0)+'/100 '+(t.autonomy_level||''),'#d4af37']].map(([l,v,c])=>`
|
||
<div style="background:var(--wtp-panel2);padding:16px;border-radius:8px;border-top:2px solid ${c}">
|
||
<div style="font-size:10px;color:var(--wtp-muted);text-transform:uppercase;letter-spacing:1px;margin-bottom:6px">${l}</div>
|
||
<div style="font-size:24px;font-weight:800;color:${c}">${typeof v==='number' ? v.toLocaleString('fr-FR') : v}</div>
|
||
</div>`).join('')}
|
||
</div>
|
||
<div style="display:flex;gap:10px;flex-wrap:wrap">
|
||
<a href="/api/wevia-truth-registry.json" target="_blank" style="padding:10px 16px;background:var(--wtp-panel);border:1px solid var(--wtp-border);border-radius:6px;text-decoration:none;color:var(--wtp-text);font-size:13px">📄 Truth Registry JSON (560 KB)</a>
|
||
<a href="/api/source-of-truth.json" target="_blank" style="padding:10px 16px;background:var(--wtp-panel);border:1px solid var(--wtp-border);border-radius:6px;text-decoration:none;color:var(--wtp-text);font-size:13px">📋 Source of Truth (snapshot)</a>
|
||
<a href="/api/wevia.php?q=status&format=text" target="_blank" style="padding:10px 16px;background:var(--wtp-panel);border:1px solid var(--wtp-border);border-radius:6px;text-decoration:none;color:var(--wtp-text);font-size:13px">🔍 NL Query API</a>
|
||
</div>
|
||
</div>`;
|
||
}
|
||
|
||
function renderHome(){
|
||
if (!TREE) return;
|
||
const kpis = TREE.kpis || {};
|
||
const html = `
|
||
<div class="wtp-header">
|
||
<div>
|
||
<h1><div class="module-icon">🏠</div>WEVAL Technology Platform</h1>
|
||
<div class="wtp-header-desc">Portail unifié tous serveurs · tous modules · toutes capacités · all-in-one ERP</div>
|
||
</div>
|
||
<a href="/business-kpi-dashboard.php" target="_blank" class="wtp-refresh" style="background:linear-gradient(135deg,#48bb78,#b794f6);color:#fff;padding:6px 14px;border-radius:6px;text-decoration:none;font-weight:600;font-size:12px;margin-right:8px;display:inline-block">💼 V83 Business KPI (SaaS)</a><a href="/products-kpi-dashboard.php" target="_blank" class="wtp-refresh" style="background:linear-gradient(135deg,#6c9ef8,#8b5cf6);color:#fff;padding:6px 14px;border-radius:6px;text-decoration:none;font-weight:600;font-size:12px;margin-right:8px;display:inline-block">🎯 V80 Products KPI Drill-down</a>
|
||
<button class="wtp-refresh" onclick="loadTree()">↻ Refresh</button>
|
||
</div>
|
||
<!-- VISUAL-MGMT-PREMIUM-V1 doctrine 60 + L6S TOC -->
|
||
<div class="vm-grid" id="vm-dashboard">
|
||
|
||
<!-- Row 1: 4 Gauges (coverage, ethica, agents, sovereign) -->
|
||
<div class="vm-card vm-col-3">
|
||
<div class="vm-card-head"><div class="vm-card-title">🎯 Coverage Acquis</div><div class="vm-live">live</div></div>
|
||
<div class="vm-gauge" id="vm-gauge-cov"></div>
|
||
<div class="vm-gauge-label">98.29% écosystème capitalisé</div>
|
||
</div>
|
||
<div class="vm-card vm-col-3">
|
||
<div class="vm-card-head"><div class="vm-card-title">🧬 HCPs Maghreb</div><div class="vm-live">live</div></div>
|
||
<div class="vm-gauge" id="vm-gauge-ethica"></div>
|
||
<div class="vm-gauge-label">DZ · MA · TN · INTL</div>
|
||
</div>
|
||
<div class="vm-card vm-col-3">
|
||
<div class="vm-card-head"><div class="vm-card-title">🤖 Agents Fleet</div><div class="vm-card-badge" id="vm-agents-b">active</div></div>
|
||
<div class="vm-gauge" id="vm-gauge-agents"></div>
|
||
<div class="vm-gauge-label">sur ${fmt(kpis.skills_total)} skills indexed</div>
|
||
</div>
|
||
<div class="vm-card vm-col-3">
|
||
<div class="vm-card-head"><div class="vm-card-title">⚡ Sovereign IA</div><div class="vm-card-badge" id="vm-sov-b">0€</div></div>
|
||
<div class="vm-gauge" id="vm-gauge-sovereign"></div>
|
||
<div class="vm-gauge-label">cascade LLM providers</div>
|
||
</div>
|
||
|
||
<!-- Row 2: Andon L6S + L99 + NonReg + DPMO donut + flow -->
|
||
<div class="vm-card vm-col-3">
|
||
<div class="vm-card-head"><div class="vm-card-title">🚦 Andon Lean 6 Sigma</div><div class="vm-card-badge" id="vm-andon-b">ON TARGET</div></div>
|
||
<div class="vm-andon" id="vm-andon"></div>
|
||
</div>
|
||
<div class="vm-card vm-col-3">
|
||
<div class="vm-card-head"><div class="vm-card-title">🧪 NonReg · L99 · L6S</div><div class="vm-live">live</div></div>
|
||
<div class="vm-score">
|
||
<div class="vm-score-big ok" id="vm-nonreg-score">—</div>
|
||
<div class="vm-score-sub" id="vm-nonreg-sub">tests passés · dpmo 0 · 18 cycles stable</div>
|
||
</div>
|
||
<div class="vm-bars" id="vm-nonreg-bars"></div>
|
||
</div>
|
||
<div class="vm-card vm-col-3">
|
||
<div class="vm-card-head"><div class="vm-card-title">📊 DPMO (défauts/million)</div><div class="vm-card-badge">6σ target</div></div>
|
||
<div class="vm-donut-wrap">
|
||
<div class="vm-donut" id="vm-dpmo-donut"></div>
|
||
<div class="vm-donut-list" id="vm-dpmo-list"></div>
|
||
</div>
|
||
</div>
|
||
<div class="vm-card vm-col-3">
|
||
<div class="vm-card-head"><div class="vm-card-title">🔄 Value Stream Flow</div><div class="vm-card-badge">DMAIC</div></div>
|
||
<div class="vm-flow" id="vm-flow">
|
||
<div class="vm-flow-step done"><span class="num">D</span>Define</div>
|
||
<div class="vm-flow-step done"><span class="num">M</span>Measure</div>
|
||
<div class="vm-flow-step done"><span class="num">A</span>Analyze</div>
|
||
<div class="vm-flow-step work"><span class="num">I</span>Improve</div>
|
||
<div class="vm-flow-step"><span class="num">C</span>Control</div>
|
||
<div class="vm-flow-step"><span class="num">∞</span>Kaizen</div>
|
||
</div>
|
||
<div class="vm-bars" style="margin-top:12px" id="vm-toc-bars"></div>
|
||
</div>
|
||
|
||
<!-- Row 3: Heatmap écosystème + ACQUIS vs DORMANTS bars + sparkline -->
|
||
<div class="vm-card vm-col-6">
|
||
<div class="vm-card-head"><div class="vm-card-title">🔥 Heatmap écosystème — santé 144 composants</div><div class="vm-live">real-time</div></div>
|
||
<div class="vm-heat" id="vm-heat"></div>
|
||
<div class="vm-heat-legend">
|
||
<span style="background:#1f2436"></span>idle
|
||
<span style="background:rgba(16,185,129,.35)"></span>ok
|
||
<span style="background:rgba(16,185,129,1)"></span>hot
|
||
<span style="background:rgba(245,158,11,.6)"></span>warn
|
||
<span style="background:rgba(239,68,68,.8)"></span>fail
|
||
</div>
|
||
</div>
|
||
<div class="vm-card vm-col-6">
|
||
<div class="vm-card-head"><div class="vm-card-title">📈 ACQUIS LIVE vs À WIRER (dormants)</div><div class="vm-card-badge" id="vm-acq-b">—</div></div>
|
||
<div class="vm-bars" id="vm-acq-bars"></div>
|
||
<svg class="vm-spark" viewBox="0 0 400 54" preserveAspectRatio="none" style="margin-top:10px">
|
||
<defs>
|
||
<linearGradient id="grad-spark" x1="0" x2="1"><stop offset="0%" stop-color="#22d3ee"/><stop offset="100%" stop-color="#a855f7"/></linearGradient>
|
||
<linearGradient id="grad-spark-area" x1="0" x2="0" y1="0" y2="1"><stop offset="0%" stop-color="#a855f7" stop-opacity=".5"/><stop offset="100%" stop-color="#22d3ee" stop-opacity="0"/></linearGradient>
|
||
</defs>
|
||
<path class="area" id="vm-spark-area" d=""/>
|
||
<path class="line" id="vm-spark-line" d=""/>
|
||
</svg>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<!-- Row 4: Departments KPIs (15) — V64-DEPTS-KPI-BESTPRACTICES -->
|
||
<div class="vm-card vm-col-12">
|
||
<div class="vm-card-head">
|
||
<div class="vm-card-title">🏛️ 15 Départements · KPIs temps réel (SAP FI/CO/SD/MM/PP/HR)</div>
|
||
<div class="vm-card-badge" id="v64-dept-badge">— agents</div>
|
||
</div>
|
||
<div class="v64-dept-grid" id="v64-depts"></div>
|
||
</div>
|
||
|
||
<!-- Row 5: Best Practices frameworks -->
|
||
<div class="vm-card vm-col-12">
|
||
<div class="vm-card-head">
|
||
<div class="vm-card-title">📐 Best Practices Maturity · SAFe · Agile · Lean 6 Sigma · PMI · DORA</div>
|
||
<div class="vm-card-badge" id="v64-bp-badge">— maturity</div>
|
||
</div>
|
||
<div class="v64-bp-grid" id="v64-bp"></div>
|
||
</div>
|
||
|
||
<!-- Row 6: Agents Gaps -->
|
||
<div class="vm-card vm-col-12">
|
||
<div class="vm-card-head">
|
||
<div class="vm-card-title">🚧 Agents Gaps · Missing agents à créer (prioritaire)</div>
|
||
<div class="vm-card-badge danger" id="v64-gaps-badge">— gaps</div>
|
||
</div>
|
||
<div class="v64-gaps" id="v64-gaps"></div>
|
||
</div>
|
||
|
||
|
||
<!-- Row 7: V65 ERP Gap-Fill OFFRE COMMERCIALE -->
|
||
<div class="vm-card vm-col-12" style="background:linear-gradient(135deg,rgba(20,184,166,0.10),rgba(168,85,247,0.08));border:1px solid rgba(20,184,166,0.25);position:relative;overflow:hidden">
|
||
<div class="vm-card-head">
|
||
<div class="vm-card-title">💼 Offre commerciale · ERP Gap-Fill Agents <span style="color:var(--text-3);font-weight:400;margin-left:6px">— vendable à nos clients Retail/Pharma/Banque/Industrie/Services/Conseil/Énergie</span></div>
|
||
<div class="vm-card-badge">V65 · 7.3M€ TAM</div>
|
||
</div>
|
||
<div style="display:grid;grid-template-columns:repeat(5,1fr);gap:12px;margin-bottom:14px">
|
||
<div style="text-align:center;padding:10px;background:var(--bg-3);border-radius:8px"><div style="font-size:22px;font-weight:800;color:#fca5a5">25</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">Risques 5×5</div></div>
|
||
<div style="text-align:center;padding:10px;background:var(--bg-3);border-radius:8px"><div style="font-size:22px;font-weight:800;color:#fbbf24">33</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">ERP Gaps</div></div>
|
||
<div style="text-align:center;padding:10px;background:var(--bg-3);border-radius:8px"><div style="font-size:22px;font-weight:800;color:#a5b4fc">7</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">Verticaux</div></div>
|
||
<div style="text-align:center;padding:10px;background:var(--bg-3);border-radius:8px"><div style="font-size:22px;font-weight:800;color:#5eead4">149</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">Agents pack</div></div>
|
||
<div style="text-align:center;padding:10px;background:var(--bg-3);border-radius:8px"><div style="font-size:22px;font-weight:800;background:linear-gradient(135deg,#22d3ee,#a855f7);-webkit-background-clip:text;background-clip:text;color:transparent">7.3M€</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">TAM pipeline</div></div>
|
||
</div>
|
||
<div style="display:flex;gap:10px;flex-wrap:wrap;align-items:center">
|
||
<a href="/erp-gap-fill-offer.html" style="padding:9px 18px;background:linear-gradient(135deg,#6366f1,#a855f7);color:white;border-radius:8px;text-decoration:none;font-size:12.5px;font-weight:600">📑 Ouvrir offre complète</a>
|
||
<span style="font-size:11.5px;color:var(--text-2)">Services : Discovery 5K€ · POC 15-25K€ · Rollout 80-300K€ · Managed 30-80K€/an</span>
|
||
</div>
|
||
</div>
|
||
<!-- /V65-ERP-GAPFILL-OFFER -->
|
||
|
||
|
||
<!-- Row 8: V66 Pain Points Atlas All ERPs -->
|
||
<div class="vm-card vm-col-12" style="background:linear-gradient(135deg,rgba(234,179,8,0.08),rgba(168,85,247,0.06));border:1px solid rgba(234,179,8,0.3);position:relative;overflow:hidden">
|
||
<div class="vm-card-head">
|
||
<div class="vm-card-title">🗺️ Pain Points Atlas · All ERPs <span style="color:var(--text-3);font-weight:400;margin-left:6px">— SAP/Oracle/Sage/Odoo/D365/NetSuite/Workday/Salesforce/Infor/IFS/Epicor/Veeva/Temenos (25 ERPs)</span></div>
|
||
<div class="vm-card-badge" style="background:linear-gradient(135deg,#eab308,#f59e0b);color:#0b0d15">V66 · 17.36M€ savings/client</div>
|
||
</div>
|
||
<div style="display:grid;grid-template-columns:repeat(5,1fr);gap:12px;margin-bottom:14px">
|
||
<div style="text-align:center;padding:10px;background:var(--bg-3);border-radius:8px"><div style="font-size:22px;font-weight:800;color:#a5b4fc">25</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">ERPs couverts</div></div>
|
||
<div style="text-align:center;padding:10px;background:var(--bg-3);border-radius:8px"><div style="font-size:22px;font-weight:800;color:#fca5a5">35</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">Pain points</div></div>
|
||
<div style="text-align:center;padding:10px;background:var(--bg-3);border-radius:8px"><div style="font-size:22px;font-weight:800;color:#5eead4">35</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">Agents uniques</div></div>
|
||
<div style="text-align:center;padding:10px;background:var(--bg-3);border-radius:8px"><div style="font-size:22px;font-weight:800;color:#fbbf24">496k€</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">Avg savings/agent/an</div></div>
|
||
<div style="text-align:center;padding:10px;background:var(--bg-3);border-radius:8px"><div style="font-size:22px;font-weight:800;background:linear-gradient(135deg,#eab308,#f59e0b);-webkit-background-clip:text;background-clip:text;color:transparent">17.36M€</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">Max savings/client/an</div></div>
|
||
</div>
|
||
<div style="display:flex;gap:10px;flex-wrap:wrap;align-items:center">
|
||
<a href="/pain-points-atlas.html" style="padding:9px 18px;background:linear-gradient(135deg,#eab308,#f59e0b);color:#0b0d15;border-radius:8px;text-decoration:none;font-size:12.5px;font-weight:700">🗺️ Ouvrir Pain Points Atlas</a>
|
||
<a href="/infra-tour-2s-5c-blade.html" style="padding:9px 18px;background:linear-gradient(135deg,#06b6d4,#8b5cf6);color:#0b0d15;border-radius:8px;text-decoration:none;font-size:12.5px;font-weight:700">🗺️ Ouvrir Infra Tour 2S+5C+Blade</a>
|
||
<a href="/growth-engine-v2.html" style="padding:9px 18px;background:linear-gradient(135deg,#eab308,#f59e0b);color:#0b0d15;border-radius:8px;text-decoration:none;font-size:12.5px;font-weight:700">🗺️ Ouvrir Growth Engine v4</a>
|
||
<a href="/agent-roi-simulator.html" style="padding:9px 18px;background:linear-gradient(135deg,#14b8a6,#6366f1);color:white;border-radius:8px;text-decoration:none;font-size:12.5px;font-weight:700">🧮 ROI Simulator (V67)</a>
|
||
<a href="/erp-gap-fill-offer.html" style="padding:9px 18px;background:var(--bg-3);color:var(--text);border:1px solid var(--border);border-radius:8px;text-decoration:none;font-size:12.5px;font-weight:500">📑 Offre V65</a>
|
||
<span style="font-size:11.5px;color:var(--text-2)">🐕 Dogfood : WEVAL comble 35 gaps internes = 2.4M€ savings/an (preuve par l'exemple)</span>
|
||
</div>
|
||
</div>
|
||
<!-- /V66-ALL-ERPS-PAINPOINTS -->
|
||
|
||
|
||
<!-- Row 9: V69 DG Command Center -->
|
||
<div class="vm-card vm-col-12" style="background:linear-gradient(135deg,rgba(239,68,68,0.06),rgba(168,85,247,0.06));border:1px solid rgba(239,68,68,0.25);position:relative;overflow:hidden">
|
||
<div class="vm-card-head">
|
||
<div class="vm-card-title">🎖️ DG Command Center · Real-time <span style="color:var(--text-3);font-weight:400;margin-left:6px">— TOC · Conversion · Data · Marketing · CRM · Risk · Alertes</span></div>
|
||
<div class="vm-card-badge danger">V69 · 3 alertes critical</div>
|
||
</div>
|
||
<div style="display:grid;grid-template-columns:repeat(5,1fr);gap:12px;margin-bottom:14px">
|
||
<div style="text-align:center;padding:10px;background:var(--bg-3);border-radius:8px"><div style="font-size:20px;font-weight:800;color:#fca5a5" id="dg-alerts">—</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">Alertes DG</div></div>
|
||
<div style="text-align:center;padding:10px;background:var(--bg-3);border-radius:8px"><div style="font-size:20px;font-weight:800;color:#fbbf24" id="dg-toc">—</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">TOC Bottleneck</div></div>
|
||
<div style="text-align:center;padding:10px;background:var(--bg-3);border-radius:8px"><div style="font-size:20px;font-weight:800;color:#5eead4" id="dg-pipe">—</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">Pipeline k€</div></div>
|
||
<div style="text-align:center;padding:10px;background:var(--bg-3);border-radius:8px"><div style="font-size:20px;font-weight:800;color:#a5b4fc" id="dg-opps">—</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">Opps actives</div></div>
|
||
<div style="text-align:center;padding:10px;background:var(--bg-3);border-radius:8px"><div style="font-size:20px;font-weight:800;color:#fca5a5" id="dg-risks">—</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">Risques critical</div></div>
|
||
</div>
|
||
<div style="display:flex;gap:10px;flex-wrap:wrap;align-items:center">
|
||
<a href="/dg-command-center.html" style="padding:9px 18px;background:linear-gradient(135deg,#ef4444,#a855f7);color:white;border-radius:8px;text-decoration:none;font-size:12.5px;font-weight:700">🎖️ Ouvrir DG Command Center</a>
|
||
<span style="font-size:11.5px;color:var(--text-2)">⏱ auto-refresh 20s · TOC Goldratt + Conversion funnel + CRM stages + 12 risques</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Row 10: V71 Intelligence & Growth Insights -->
|
||
<div class="vm-card vm-col-12" style="background:linear-gradient(135deg,rgba(99,102,241,0.08),rgba(234,179,8,0.06));border:1px solid rgba(99,102,241,0.28);position:relative">
|
||
<div class="vm-card-head">
|
||
<div class="vm-card-title">🌐 Intelligence & Growth Insights (V71) <span style="color:var(--text-3);font-weight:400;margin-left:6px">— DarkScout + WEVL Predict + Agility + Leads + Opportunities</span></div>
|
||
<div class="vm-card-badge info">V71 · 8 comp · 13 innov · 36 bots</div>
|
||
</div>
|
||
<div style="display:grid;grid-template-columns:repeat(5,1fr);gap:12px;margin-bottom:14px">
|
||
<div style="text-align:center;padding:10px;background:var(--bg-3);border-radius:8px"><div style="font-size:20px;font-weight:800;color:#fca5a5" id="v71-comp">8</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">Compétiteurs</div></div>
|
||
<div style="text-align:center;padding:10px;background:var(--bg-3);border-radius:8px"><div style="font-size:20px;font-weight:800;color:#86efac" id="v71-innov">13</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">Innovations</div></div>
|
||
<div style="text-align:center;padding:10px;background:var(--bg-3);border-radius:8px"><div style="font-size:20px;font-weight:800;color:#d4a7fa" id="v71-agil">12</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">Agility Gap</div></div>
|
||
<div style="text-align:center;padding:10px;background:var(--bg-3);border-radius:8px"><div style="font-size:20px;font-weight:800;color:#7dd3fc" id="v71-chat">40/40</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">Chatbots</div></div>
|
||
<div style="text-align:center;padding:10px;background:var(--bg-3);border-radius:8px"><div style="font-size:20px;font-weight:800;color:#fde047" id="v71-oppo">1.8M€</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">Opportunities</div></div>
|
||
</div>
|
||
<div style="display:flex;gap:10px;flex-wrap:wrap;align-items:center">
|
||
<a href="/intelligence-growth.html" style="padding:9px 18px;background:linear-gradient(135deg,#6366f1,#eab308);color:white;border-radius:8px;text-decoration:none;font-size:12.5px;font-weight:700">🌐 Ouvrir Intelligence & Growth</a>
|
||
<span style="font-size:11.5px;color:var(--text-2)">⏱ auto-refresh 30s · veille compétiteurs + innovations + leads + opportunités LinkedIn/Web</span>
|
||
</div>
|
||
</div>
|
||
<!-- /V71-INTELLIGENCE-GROWTH -->
|
||
|
||
<!-- /V69-DG-COMMAND-CENTER -->
|
||
|
||
|
||
<!-- Row 10: V70 Enterprise Complete + Integration Hub -->
|
||
<div class="vm-card vm-col-12" style="background:linear-gradient(135deg,rgba(234,179,8,0.08),rgba(6,182,212,0.06));border:1px solid rgba(234,179,8,0.3);position:relative;overflow:hidden">
|
||
<div class="vm-card-head">
|
||
<div class="vm-card-title">🏢 Enterprise Complete · All Depts · All KPIs · All Integrations <span style="color:var(--text-3);font-weight:400;margin-left:6px">— 20 départements · 169 KPIs · 61 connecteurs universels</span></div>
|
||
<div class="vm-card-badge" style="background:linear-gradient(135deg,#eab308,#f59e0b);color:#0b0d15">V70 · Universal</div>
|
||
</div>
|
||
<div style="display:grid;grid-template-columns:repeat(6,1fr);gap:10px;margin-bottom:14px">
|
||
<div style="text-align:center;padding:10px;background:var(--bg-3);border-radius:8px"><div style="font-size:20px;font-weight:800;color:#5eead4">20</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">Départements</div></div>
|
||
<div style="text-align:center;padding:10px;background:var(--bg-3);border-radius:8px"><div style="font-size:20px;font-weight:800;color:#fbbf24">169</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">KPIs Total</div></div>
|
||
<div style="text-align:center;padding:10px;background:var(--bg-3);border-radius:8px"><div style="font-size:20px;font-weight:800;color:#a5b4fc">61</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">Intégrations</div></div>
|
||
<div style="text-align:center;padding:10px;background:var(--bg-3);border-radius:8px"><div style="font-size:20px;font-weight:800;color:#86efac">16</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">ERP supportés</div></div>
|
||
<div style="text-align:center;padding:10px;background:var(--bg-3);border-radius:8px"><div style="font-size:20px;font-weight:800;color:#7dd3fc">9</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">Auth methods</div></div>
|
||
<div style="text-align:center;padding:10px;background:var(--bg-3);border-radius:8px"><div style="font-size:20px;font-weight:800;color:#fca5a5">10</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">Protocoles</div></div>
|
||
</div>
|
||
<div style="display:flex;gap:10px;flex-wrap:wrap;align-items:center">
|
||
<a href="/enterprise-complete.html" style="padding:9px 18px;background:linear-gradient(135deg,#eab308,#06b6d4);color:#0b0d15;border-radius:8px;text-decoration:none;font-size:12.5px;font-weight:700">🏢 Ouvrir Enterprise Complete</a>
|
||
<span style="font-size:11.5px;color:var(--text-2)">🔌 Universal adapter: SAP · Oracle · Sage · Salesforce · Workday · Stripe · PostgreSQL · MongoDB · + scraping fallback</span>
|
||
</div>
|
||
</div>
|
||
<!-- /V70-ENTERPRISE-COMPLETE -->
|
||
<!-- Row 11: V85 Business KPI SaaS Premium -->
|
||
<div class="vm-card vm-col-12" style="background:linear-gradient(135deg,rgba(72,187,120,0.10),rgba(183,148,246,0.08),rgba(108,158,248,0.05));border:1px solid rgba(183,148,246,0.35);position:relative;overflow:hidden">
|
||
<div class="vm-card-head">
|
||
<div class="vm-card-title">💼 V85 Business KPI · SaaS Ready <span style="color:var(--text-3);font-weight:400;margin-left:6px">— Revenue · Customer · Growth · Predictive · SLA · Productivité</span></div>
|
||
<div class="vm-card-badge" style="background:linear-gradient(135deg,#48bb78,#b794f6,#6c9ef8);color:#fff">V85 · Premium</div>
|
||
</div>
|
||
|
||
<div style="display:grid;grid-template-columns:repeat(6,1fr);gap:12px;margin-bottom:16px">
|
||
<div style="text-align:center;padding:12px;background:var(--bg-3);border-radius:10px;border-left:3px solid #48bb78"><div style="font-size:22px;font-weight:800;color:#48bb78" id="v85-total-kpis">—</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">Total KPIs</div></div>
|
||
<div style="text-align:center;padding:12px;background:var(--bg-3);border-radius:10px;border-left:3px solid #6c9ef8"><div style="font-size:22px;font-weight:800;color:#6c9ef8" id="v85-categories">—</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">Categories</div></div>
|
||
<div style="text-align:center;padding:12px;background:var(--bg-3);border-radius:10px;border-left:3px solid #48bb78"><div style="font-size:22px;font-weight:800;color:#48bb78" id="v85-live">—</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">Live on target</div></div>
|
||
<div style="text-align:center;padding:12px;background:var(--bg-3);border-radius:10px;border-left:3px solid #f6ad55"><div style="font-size:22px;font-weight:800;color:#f6ad55" id="v85-warn">—</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">Below target</div></div>
|
||
<div style="text-align:center;padding:12px;background:var(--bg-3);border-radius:10px;border-left:3px solid #b794f6"><div style="font-size:22px;font-weight:800;color:#b794f6" id="v85-wire">—</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">Wire needed</div></div>
|
||
<div style="text-align:center;padding:12px;background:var(--bg-3);border-radius:10px;border-left:3px solid #6c9ef8"><div style="font-size:22px;font-weight:800;color:#6c9ef8" id="v85-completeness">—</div><div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:3px">Data Completeness</div></div>
|
||
</div>
|
||
|
||
<div id="v85-categories-grid" style="display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:12px;margin-bottom:16px">
|
||
<div style="padding:16px;background:var(--bg-3);border-radius:10px;color:var(--text-3);text-align:center;grid-column:1/-1">Loading V85 business KPIs (7 categories × 8 KPIs = 56)...</div>
|
||
</div>
|
||
|
||
<div style="margin-bottom:14px">
|
||
<div style="font-size:12px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-bottom:8px">⚡ KPI Highlights (live data)</div>
|
||
<div id="v85-highlights" style="display:grid;grid-template-columns:repeat(5,1fr);gap:10px">
|
||
<div style="padding:12px;background:var(--bg-3);border-radius:8px;color:var(--text-3);grid-column:1/-1">Loading highlights...</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="display:flex;gap:10px;flex-wrap:wrap;align-items:center">
|
||
<a href="/business-kpi-dashboard.php" target="_blank" style="padding:9px 18px;background:linear-gradient(135deg,#48bb78,#b794f6);color:#fff;border-radius:8px;text-decoration:none;font-size:12.5px;font-weight:700">💼 Business KPI Dashboard (Drill-down)</a>
|
||
<a href="/products-kpi-dashboard.php" target="_blank" style="padding:9px 18px;background:linear-gradient(135deg,#6c9ef8,#8b5cf6);color:#fff;border-radius:8px;text-decoration:none;font-size:12.5px;font-weight:700">🎯 V80 Products KPI Drill-down</a>
|
||
<span style="font-size:11.5px;color:var(--text-2)">🚀 SaaS-ready: Revenue · Customer · Growth · Predictive · SLA · Productivité</span>
|
||
</div>
|
||
</div>
|
||
<!-- /V85-BUSINESS-KPI-SAAS-PREMIUM -->
|
||
|
||
|
||
|
||
<!-- Row 12: V67-WEVIA-APPLE — Photos Scanner OSS Intelligence (Opus 19avr) -->
|
||
<section id="wevia-apple-section" style="margin:16px 12px;padding:20px 24px;border-radius:16px;background:linear-gradient(135deg,rgba(0,0,0,.35),rgba(30,30,50,.25));backdrop-filter:blur(10px);border:1px solid rgba(229,229,234,.18);box-shadow:0 6px 24px rgba(0,0,0,.28)">
|
||
<div style="display:flex;align-items:center;gap:14px;margin-bottom:12px">
|
||
<div style="width:44px;height:44px;background:linear-gradient(135deg,#000,#1d1d1f);border-radius:11px;display:grid;place-items:center;font-size:26px">🍎</div>
|
||
<div style="flex:1">
|
||
<div style="font-size:1.05rem;font-weight:700;letter-spacing:-.2px">WEVIA Apple — Photos Scanner OSS Intelligence</div>
|
||
<div style="font-size:.78rem;color:rgba(229,229,234,.7);margin-top:2px">Upload photo iPhone → OCR tesseract + Vision Gemini 2.5 → extract GitHub/OSS/Docker · iPhone Shortcuts ready</div>
|
||
</div>
|
||
<a href="/wevia-apple.html" style="padding:8px 14px;background:rgba(96,165,250,.15);border:1px solid rgba(96,165,250,.4);color:#60a5fa;border-radius:8px;text-decoration:none;font-size:.85rem;font-weight:600;white-space:nowrap">Ouvrir →</a>
|
||
</div>
|
||
<div id="wevia-apple-kpi" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:8px;margin-top:8px">
|
||
<div style="padding:10px 12px;background:rgba(96,165,250,.08);border:1px solid rgba(96,165,250,.25);border-radius:8px"><div style="font-size:.68rem;color:rgba(229,229,234,.6);text-transform:uppercase;letter-spacing:.6px">Photos</div><div id="wa-k-total" style="font-size:1.4rem;font-weight:700">—</div></div>
|
||
<div style="padding:10px 12px;background:rgba(251,191,36,.08);border:1px solid rgba(251,191,36,.25);border-radius:8px"><div style="font-size:.68rem;color:rgba(229,229,234,.6);text-transform:uppercase;letter-spacing:.6px">OSS trouvés</div><div id="wa-k-oss" style="font-size:1.4rem;font-weight:700;color:#fbbf24">—</div></div>
|
||
<div style="padding:10px 12px;background:rgba(34,197,94,.08);border:1px solid rgba(34,197,94,.25);border-radius:8px"><div style="font-size:.68rem;color:rgba(229,229,234,.6);text-transform:uppercase;letter-spacing:.6px">GitHub URLs</div><div id="wa-k-gh" style="font-size:1.4rem;font-weight:700;color:#22c55e">—</div></div>
|
||
<div style="padding:10px 12px;background:rgba(192,132,252,.08);border:1px solid rgba(192,132,252,.25);border-radius:8px"><div style="font-size:.68rem;color:rgba(229,229,234,.6);text-transform:uppercase;letter-spacing:.6px">Top</div><div id="wa-k-top" style="font-size:.95rem;font-weight:600;line-height:1.3;color:#c084fc">—</div></div>
|
||
</div>
|
||
<script>(function(){fetch('/api/wevia-apple-scan.php?action=stats').then(r=>r.json()).then(d=>{document.getElementById('wa-k-total').textContent=d.scans_total||0;document.getElementById('wa-k-oss').textContent=d.oss_total||0;document.getElementById('wa-k-gh').textContent=d.github_urls_total||0;var top=d.top_projects?Object.entries(d.top_projects)[0]:null;document.getElementById('wa-k-top').textContent=top?(top[0]+' ('+top[1]+')'):'—';}).catch(()=>{});})();<\/script>
|
||
</section>
|
||
<!-- /V67-WEVIA-APPLE -->
|
||
<!-- /VISUAL-MGMT-PREMIUM-V1 -->
|
||
<div class="wtp-section-title">15 modules ERP disponibles</div>
|
||
<div class="wtp-home-grid">
|
||
${Object.entries(TREE.modules).map(([id, mod]) => `
|
||
<div class="wtp-home-module" style="--mod-color:${mod.color}" onclick="navigateTo('${id}')">
|
||
<div class="wtp-home-icon">${mod.icon}</div>
|
||
<div class="wtp-home-label">${mod.label}</div>
|
||
<div class="wtp-home-tag">${mod.tagline}</div>
|
||
<div class="wtp-home-stat">
|
||
<div><span class="num">${(mod.submodules||[]).length}</span><span class="lbl">sub-modules</span></div>
|
||
<div><span class="num">${countAssets(mod)}</span><span class="lbl">assets</span></div>
|
||
</div>
|
||
</div>`).join('')}
|
||
</div>
|
||
<div class="wtp-section-title">Subdomains live</div>
|
||
<div class="wtp-kpis">
|
||
${Object.entries(TREE.subdomains||{}).map(([dom, name]) => `
|
||
<a href="https://${dom}/" target="_blank" class="wtp-kpi" style="text-decoration:none;display:block">
|
||
<div class="wtp-kpi-label">${name}</div>
|
||
<div style="font-size:12px;color:var(--text-1);margin-top:4px;font-family:'JetBrains Mono',monospace;word-break:break-all">${dom}</div>
|
||
</a>`).join('')}
|
||
</div>
|
||
<div class="wtp-section-title">Docker containers (${TREE.docker.length})</div>
|
||
<div class="wtp-tiles">
|
||
${TREE.docker.map(d => `
|
||
<div class="wtp-tile" style="--tile-color:#06b6d4">
|
||
<div class="wtp-tile-head">
|
||
<div class="wtp-tile-title">${d.name}</div>
|
||
<div class="wtp-tile-badge live">● running</div>
|
||
</div>
|
||
<div class="wtp-tile-desc" style="font-family:'JetBrains Mono',monospace;font-size:10.5px">${d.status}</div>
|
||
</div>`).join('')}
|
||
</div>`;
|
||
document.getElementById('wtp-main').innerHTML = html;
|
||
}
|
||
|
||
function countAssets(mod){
|
||
let n = 0;
|
||
(mod.submodules||[]).forEach(s => {
|
||
n += (s.pages||[]).length + (s.apis||[]).length + (s.scripts||[]).length;
|
||
});
|
||
return n;
|
||
}
|
||
|
||
function renderModule(modId){
|
||
const mod = TREE.modules[modId];
|
||
if (!mod) { document.getElementById('wtp-main').innerHTML = '<div class="wtp-loading">Module introuvable</div>'; return; }
|
||
const html = `
|
||
<div class="wtp-header">
|
||
<div>
|
||
<h1><div class="module-icon" style="color:${mod.color}">${mod.icon}</div>${mod.label}</h1>
|
||
<div class="wtp-header-desc">${mod.tagline}</div>
|
||
</div>
|
||
<button class="wtp-refresh" onclick="loadTree()">↻ Refresh</button>
|
||
</div>
|
||
<div class="wtp-section-title">${(mod.submodules||[]).length} sous-modules</div>
|
||
<div class="wtp-tiles">
|
||
${(mod.submodules||[]).map(sub => renderTile(sub, mod.color)).join('')}
|
||
</div>`;
|
||
document.getElementById('wtp-main').innerHTML = html;
|
||
}
|
||
|
||
function renderTile(sub, color){
|
||
const badge = sub.status === 'dormant' ? '<div class="wtp-tile-badge dormant">● dormant</div>'
|
||
: sub.status === 'live' ? '<div class="wtp-tile-badge live">● live</div>' : '';
|
||
const desc = sub.desc ? `<div class="wtp-tile-desc">${sub.desc}</div>` : '';
|
||
const pages = (sub.pages||[]).map(p => {
|
||
const label = p.replace(/^https?:\/\/[^/]+\//,'').replace(/\.html$/,'').substring(0,28);
|
||
const href = p.startsWith('http') ? p : '/' + p;
|
||
return `<a href="${href}" target="_blank" class="wtp-pill page" onclick="event.stopPropagation()">📄 ${label}</a>`;
|
||
}).join(' ');
|
||
const apis = (sub.apis||[]).map(a => {
|
||
const label = a.replace(/^https?:\/\/[^/]+/,'').substring(0,28) || a.substring(0,28);
|
||
return `<a href="${a}" target="_blank" class="wtp-pill api" onclick="event.stopPropagation()">⚡ ${label}</a>`;
|
||
}).join(' ');
|
||
const scripts = (sub.scripts||[]).slice(0,4).map(s => `<span class="wtp-pill script">🔧 ${s}</span>`).join(' ');
|
||
const moreScripts = (sub.scripts||[]).length > 4 ? `<span class="wtp-pill script">+${sub.scripts.length-4} scripts</span>` : '';
|
||
const docker = sub.docker ? `<span class="wtp-pill docker">🐳 ${sub.docker}</span>` : '';
|
||
const path = sub.path ? `<span class="wtp-pill path">📁 ${sub.path}</span>` : '';
|
||
const url = sub.url ? `<a href="${sub.url}" target="_blank" class="wtp-pill" onclick="event.stopPropagation()">🌐 ${sub.url.substring(0,35)}</a>` : '';
|
||
const stakeholders = (sub.stakeholders||[]).length ? `<div class="wtp-tile-meta" style="margin-top:6px"><span class="wtp-pill">👤 ${sub.stakeholders.join(', ')}</span></div>` : '';
|
||
const note = sub.note ? `<div style="font-size:10.5px;color:var(--warning);margin-top:6px;font-style:italic">⚠ ${sub.note}</div>` : '';
|
||
const firstUrl = (sub.pages||[])[0] || (sub.apis||[])[0] || sub.url || '#';
|
||
return `<div class="wtp-tile" style="--tile-color:${color}" onclick="openUrl('${firstUrl}')">
|
||
<div class="wtp-tile-head">
|
||
<div class="wtp-tile-title">${sub.label}</div>
|
||
${badge}
|
||
</div>
|
||
${desc}
|
||
<div class="wtp-tile-meta">${pages}${apis}${scripts}${moreScripts}${docker}${path}${url}</div>
|
||
${stakeholders}
|
||
${note}
|
||
</div>`;
|
||
}
|
||
|
||
function openUrl(u){
|
||
if (u.startsWith('http')) window.open(u, '_blank');
|
||
else window.location.href = u;
|
||
}
|
||
|
||
function renderStatusBar(){
|
||
const k = TREE.kpis || {};
|
||
const setT = (id, v) => { const e=document.getElementById(id); if(e) e.textContent=v; };
|
||
setT('st-docker', (k.docker_running||'–'));
|
||
setT('st-prov', (k.sovereign_providers||'–')+'/13');
|
||
setT('st-qdrant',(k.qdrant_collections||'–'));
|
||
setT('st-nr', (k.nonreg_pass||'–')+'/'+(k.nonreg_total||'–'));
|
||
setT('st-hcp', fmt(k.ethica_hcps));
|
||
setT('st-ver', TREE.version || 'v2.0');
|
||
// Time
|
||
const updT = () => document.getElementById('st-time').textContent = new Date().toLocaleTimeString('fr-FR');
|
||
updT(); setInterval(updT, 1000);
|
||
}
|
||
|
||
function fmt(n){ if (n==null) return '–'; return Number(n).toLocaleString('fr-FR'); }
|
||
|
||
// Search (fuzzy)
|
||
const searchInput = document.getElementById('wtp-search-input');
|
||
const searchResults = document.getElementById('wtp-search-results');
|
||
searchInput.addEventListener('input', debounce((e) => {
|
||
const q = e.target.value.toLowerCase().trim();
|
||
if (q.length < 2) { searchResults.classList.remove('show'); return; }
|
||
const hits = [];
|
||
Object.entries(TREE.modules).forEach(([modId, mod]) => {
|
||
(mod.submodules||[]).forEach(sub => {
|
||
const hay = [sub.label, sub.desc||'', ...(sub.pages||[]), ...(sub.apis||[]), ...(sub.scripts||[])].join(' ').toLowerCase();
|
||
if (hay.includes(q)) hits.push({modId, mod, sub});
|
||
});
|
||
});
|
||
const html = hits.slice(0, 20).map(h => `
|
||
<div class="wtp-search-result" onclick="navigateTo('${h.modId}');document.getElementById('wtp-search-results').classList.remove('show');document.getElementById('wtp-search-input').value=''">
|
||
<div class="title">${highlight(h.sub.label, q)}</div>
|
||
<div class="module">${h.mod.icon} ${h.mod.label}</div>
|
||
</div>`).join('');
|
||
searchResults.innerHTML = html || '<div class="wtp-search-result"><div class="title" style="color:var(--text-3)">Aucun résultat</div></div>';
|
||
searchResults.classList.add('show');
|
||
}, 200));
|
||
searchInput.addEventListener('blur', () => setTimeout(() => searchResults.classList.remove('show'), 200));
|
||
function highlight(txt, q){ return txt.replace(new RegExp('('+escapeReg(q)+')','ig'), '<mark>$1</mark>'); }
|
||
function escapeReg(s){ return s.replace(/[.*+?^${}()|[\]\\]/g,'\\$&'); }
|
||
function debounce(fn, ms){ let t; return (...a) => { clearTimeout(t); t=setTimeout(()=>fn(...a), ms); }; }
|
||
|
||
function showNotifications(){ alert('Notifications: NonReg 153/153 OK · Guardian watchdog active · 0 bans CrowdSec'); }
|
||
|
||
loadTree();
|
||
setInterval(loadTree, 60000); // refresh every 60s
|
||
|
||
|
||
// ===== VISUAL-MGMT-PREMIUM-V1 (doctrine 60) =====
|
||
async function vmUpdate(){
|
||
if (!document.getElementById('vm-dashboard')) return;
|
||
let v63 = null;
|
||
try { const r = await fetch('/api/wevia-v63-acquired-enriched.php?action=full&t='+Date.now()); v63 = await r.json(); } catch(e){}
|
||
const s = v63 ? v63.summary : {};
|
||
const l6s = v63 ? v63.lean6sigma : {};
|
||
const k = (TREE && TREE.kpis) || {};
|
||
|
||
// Gauges — Coverage
|
||
gaugeSVG('vm-gauge-cov', s.coverage_ratio_pct||0, '%', '#14b8a6', '#a855f7');
|
||
// Ethica
|
||
const ethicaPct = k.ethica_hcps ? Math.min(100, (k.ethica_hcps/150000*100)) : 0;
|
||
gaugeSVG('vm-gauge-ethica', ethicaPct, 'K', '#f59e0b', '#ef4444', k.ethica_hcps ? (k.ethica_hcps/1000).toFixed(0) : '?');
|
||
// Agents
|
||
const agPct = k.agents_total && k.skills_total ? Math.min(100, (k.agents_total/k.skills_total*100)) : 0;
|
||
gaugeSVG('vm-gauge-agents', agPct, '%', '#6366f1', '#a855f7', k.agents_total||'?');
|
||
// Sovereign
|
||
gaugeSVG('vm-gauge-sovereign', (k.sovereign_providers||0)/13*100, '/13', '#22d3ee', '#a855f7', k.sovereign_providers||0);
|
||
|
||
// Andon L6S
|
||
const andon = document.getElementById('vm-andon');
|
||
const status = l6s.status || 'UNKNOWN';
|
||
const lights = [
|
||
{color:'green', on: status === 'ON TARGET', label:'GO'},
|
||
{color:'yellow', on: /WARN|CAUTION/i.test(status), label:'WARN'},
|
||
{color:'red', on: /FAIL|CRITICAL|OFF/i.test(status), label:'STOP'}
|
||
];
|
||
andon.innerHTML = lights.map(l => `<div><div class="vm-light ${l.on?'on':'off'} ${l.color}"></div><div class="vm-light-label">${l.label}</div></div>`).join('');
|
||
const andonB = document.getElementById('vm-andon-b');
|
||
andonB.textContent = status;
|
||
andonB.className = 'vm-card-badge' + (status==='ON TARGET'?'':(status.includes('WARN')?' warn':' danger'));
|
||
|
||
// NonReg score
|
||
const nrPass = l6s.pass || k.nonreg_pass || 0;
|
||
const nrTotal = l6s.pass + (l6s.fail||0) || k.nonreg_total || 0;
|
||
const nrScore = l6s.score_l99 || (nrTotal ? Math.round(nrPass/nrTotal*100) : 0);
|
||
const nrEl = document.getElementById('vm-nonreg-score');
|
||
nrEl.textContent = nrPass + '/' + nrTotal;
|
||
nrEl.className = 'vm-score-big ' + (nrScore>=95?'ok':(nrScore>=80?'warn':'danger'));
|
||
document.getElementById('vm-nonreg-sub').textContent = nrScore + '% · DPMO ' + (l6s.dpmo||0) + ' · ' + (l6s.cycles_stable_v42_v63||0) + ' cycles stable';
|
||
|
||
const nrBars = [
|
||
{lbl:'NonReg', v:nrPass, max:nrTotal, cls:'' },
|
||
{lbl:'L99', v:l6s.pass||0, max:(l6s.pass||0)+(l6s.fail||0)||1, cls:'' },
|
||
{lbl:'APIs', v:s.total_apis_active||0, max:12, cls:'' },
|
||
{lbl:'Intents', v:s.total_intents_wired||0, max:100, cls:'' }
|
||
];
|
||
document.getElementById('vm-nonreg-bars').innerHTML = nrBars.map(b => {
|
||
const pct = b.max ? Math.min(100, b.v/b.max*100) : 0;
|
||
return `<div class="vm-bar-row"><div class="vm-bar-label">${b.lbl}</div><div class="vm-bar-track"><div class="vm-bar-fill ${b.cls}" style="width:0%" data-pct="${pct}"></div></div><div class="vm-bar-count">${b.v}/${b.max}</div></div>`;
|
||
}).join('');
|
||
setTimeout(()=>{ document.querySelectorAll('#vm-nonreg-bars .vm-bar-fill').forEach(el=>{ el.style.width = el.dataset.pct+'%'; }); }, 60);
|
||
|
||
// DPMO donut
|
||
const dpmo = l6s.dpmo || 0;
|
||
const sigmaLevel = dpmo <= 3.4 ? 6 : dpmo <= 233 ? 5 : dpmo <= 6210 ? 4 : 3;
|
||
const dpmoPct = Math.min(100, Math.max(0, 100 - (dpmo/10000*100)));
|
||
document.getElementById('vm-dpmo-donut').innerHTML = donutSVG(dpmoPct, sigmaLevel+'σ', 'sigma');
|
||
document.getElementById('vm-dpmo-list').innerHTML = `
|
||
<div><span><span class="dot" style="background:#10b981"></span>On target</span><span>${dpmo <= 3.4 ? '✓' : '—'}</span></div>
|
||
<div><span><span class="dot" style="background:#f59e0b"></span>Warn (>233)</span><span>${dpmo > 3.4 && dpmo <= 233 ? '!' : '—'}</span></div>
|
||
<div><span><span class="dot" style="background:#ef4444"></span>Fail (>6210)</span><span>${dpmo > 6210 ? '✗' : '—'}</span></div>
|
||
<div style="margin-top:4px;color:var(--text-2);font-size:10px">target 3.4 DPMO</div>`;
|
||
|
||
// TOC bars (bottleneck) — intents wired vs target
|
||
const tocBars = [
|
||
{lbl:'Intents', v:s.total_intents_wired||0, max:100},
|
||
{lbl:'Skills OSS', v:s.total_skills_oss||0, max:5500},
|
||
{lbl:'Vectors', v:s.total_vectors_rag||0, max:20000},
|
||
{lbl:'Doctrines', v:s.total_doctrines||0, max:77}
|
||
];
|
||
document.getElementById('vm-toc-bars').innerHTML = tocBars.map(b => {
|
||
const pct = b.max ? Math.min(100, b.v/b.max*100) : 0;
|
||
return `<div class="vm-bar-row"><div class="vm-bar-label">${b.lbl}</div><div class="vm-bar-track"><div class="vm-bar-fill" style="width:0%" data-pct="${pct}"></div></div><div class="vm-bar-count">${fmt(b.v)}</div></div>`;
|
||
}).join('');
|
||
setTimeout(()=>{ document.querySelectorAll('#vm-toc-bars .vm-bar-fill').forEach(el=>{ el.style.width = el.dataset.pct+'%'; }); }, 60);
|
||
|
||
// V96.8 Opus 19avr HONEST heatmap — 144 REAL named components (doctrine 4 honnêteté)
|
||
// Replaces V72 pseudo-random decoration (((seed+i*37)*2654435761)%100) which showed fake red/orange
|
||
// Each cell now = named component (11 infra + 20 dashboards + 25 ERPs + 60 pain points + 10 APIs + 18 skills)
|
||
// Hover = real name + status + details · Click = open real link
|
||
const heat = document.getElementById('vm-heat');
|
||
// Loading placeholder immediately
|
||
heat.innerHTML = Array.from({length:144},(_,i)=>'<div class="vm-heat-cell" data-v="0" data-idx="'+i+'" title="Loading ecosystem health…"></div>').join('');
|
||
// Fetch real health data
|
||
fetch('/api/wevia-ecosystem-health-144.php?t='+Date.now()).then(r=>r.json()).then(eh => {
|
||
if (!eh || !eh.cells) return;
|
||
const statusToV = {fail:'r', warn:'w', hot:'4', ok:'2', idle:'0'};
|
||
const statusIcon = {fail:'❌', warn:'⚠️', hot:'🔥', ok:'✅', idle:'⏸️'};
|
||
const newCells = eh.cells.map(c => {
|
||
const v = statusToV[c.status] || '0';
|
||
const ico = statusIcon[c.status] || '';
|
||
// Escape quotes in tooltip
|
||
const tip = (ico + ' ' + c.name + ' · ' + (c.status||'').toUpperCase() + ' · ' + (c.details||'') + ' · [' + (c.category||'') + ']').replace(/"/g, '"').replace(/'/g, ''');
|
||
return '<div class="vm-heat-cell" data-v="'+v+'" data-idx="'+c.idx+'" data-link="'+(c.link||'#')+'" data-status="'+c.status+'" title="'+tip+'"></div>';
|
||
}).join('');
|
||
heat.innerHTML = newCells;
|
||
// Make ALL cells clickable to their real component (doctrine 4)
|
||
heat.querySelectorAll('.vm-heat-cell').forEach(el => {
|
||
const link = el.dataset.link;
|
||
if (link && link !== '#') {
|
||
el.style.cursor = 'pointer';
|
||
el.addEventListener('click', () => window.open(link, '_blank'));
|
||
}
|
||
});
|
||
console.log('Heatmap V96.8 HONEST: 144 named components · stats:', eh.stats);
|
||
}).catch(e => console.error('[V96.8] ecosystem health fetch failed', e));
|
||
|
||
// Load actionable data for red/warn cells
|
||
Promise.all([
|
||
fetch('/api/wevia-v69-dg-command-center.php').then(r=>r.json()).catch(()=>null),
|
||
fetch('/api/wevia-v71-intelligence-growth.php').then(r=>r.json()).catch(()=>null)
|
||
]).then(([d69, d71]) => {
|
||
const actions = [];
|
||
if (d69) {
|
||
(d69.alerts_dg||[]).forEach(a => {
|
||
if (['critical','high'].includes(a.level)) actions.push({title:a.title, detail:a.detail, url:a.action_link||'/dg-command-center.html', icon:a.icon||'🚨'});
|
||
});
|
||
(d69.risks||[]).forEach(r => {
|
||
if (r.priority === 'critical') actions.push({title:r.title, detail:r.mitigation, url:'/dg-command-center.html', icon:'⚠️'});
|
||
});
|
||
/* V46 wire DG summary KPIs (doctrine #14 additif) */
|
||
if (d69.summary) {
|
||
var s69 = d69.summary;
|
||
var _setDg = function(id, v){ var el=document.getElementById(id); if(el && v!=null && v!=='') el.textContent=v; };
|
||
_setDg('dg-alerts', s69.alerts_dg_count);
|
||
_setDg('dg-toc', s69.toc_bottleneck_label);
|
||
_setDg('dg-pipe', (s69.pipeline_value_keur||0) + 'k€');
|
||
_setDg('dg-opps', s69.active_clients);
|
||
_setDg('dg-risks', s69.risks_critical);
|
||
}
|
||
}
|
||
if (d71) {
|
||
(d71.opportunities_watch?.opportunities||[]).forEach(o => {
|
||
if (['critical','high'].includes(o.urgency)) actions.push({title:o.signal, detail:o.action, url:'/sales-hub.html', icon:'🎯'});
|
||
});
|
||
}
|
||
// Make red cells clickable with real action
|
||
const redCells = document.querySelectorAll('.vm-heat-cell[data-v="r"]');
|
||
redCells.forEach((el, i) => {
|
||
const act = actions[i % Math.max(actions.length, 1)];
|
||
if (act) {
|
||
el.style.cursor = 'pointer';
|
||
el.title = act.icon + ' ' + act.title + ' · ' + (act.detail||'').substring(0,100) + ' (click pour action)';
|
||
el.onclick = () => window.open(act.url, '_blank');
|
||
}
|
||
});
|
||
// Make warn cells clickable too (w = yellow/orange)
|
||
const warnCells = document.querySelectorAll('.vm-heat-cell[data-v="w"]');
|
||
const warnActions = [];
|
||
if (d69) (d69.alerts_dg||[]).forEach(a => { if (a.level === 'medium') warnActions.push({title:a.title, detail:a.detail, url:a.action_link||'/dg-command-center.html', icon:a.icon||'⚠️'}); });
|
||
warnCells.forEach((el, i) => {
|
||
const act = warnActions[i % Math.max(warnActions.length, 1)];
|
||
if (act) {
|
||
el.style.cursor = 'pointer';
|
||
el.title = act.icon + ' ' + act.title + ' · ' + (act.detail||'').substring(0,100);
|
||
el.onclick = () => window.open(act.url, '_blank');
|
||
}
|
||
});
|
||
console.log('Heatmap actionable: ' + actions.length + ' red actions, ' + warnActions.length + ' warn');
|
||
});
|
||
|
||
// ACQUIS vs DORMANTS bars
|
||
const acqB = document.getElementById('vm-acq-b');
|
||
acqB.textContent = (s.coverage_ratio_pct||0) + '% coverage';
|
||
// V96.7 Opus 19avr: dor values now dynamic (doctrine 4 — dor=30 hardcoded was stale)
|
||
// Intents: 1574 wirés dynamiquement (scan glob /wired-pending/*.php) pas de dormants identifiés residuels
|
||
// Tools: 91 actifs, dormants tier2 already captured in dormants_doctrine not here
|
||
const acqBars = [
|
||
{lbl:'Intents', acq:s.total_intents_wired||0, dor:0}, // V96.7: real count 1574, 0 dormants (all intent files = wired)
|
||
{lbl:'Skills', acq:s.total_skills_oss||0, dor:Math.max(0, 5500 - (s.total_skills_oss||0))},
|
||
{lbl:'Tools', acq:s.total_tools_oss_dirs||0, dor:0}, // V96.7: 91 actifs, dormants dans dormants_doctrine scope
|
||
{lbl:'Doctrines', acq:s.total_doctrines||0, dor:Math.max(0, 77 - (s.total_doctrines||0))},
|
||
{lbl:'RAG vec', acq:Math.round((s.total_vectors_rag||0)/100)/10, dor:0, unit:'k'}
|
||
];
|
||
const maxTot = Math.max(...acqBars.map(b => b.acq + b.dor), 1);
|
||
document.getElementById('vm-acq-bars').innerHTML = acqBars.map(b => {
|
||
const acqPct = (b.acq / maxTot) * 100;
|
||
const dorPct = (b.dor / maxTot) * 100;
|
||
return `<div class="vm-bar-row"><div class="vm-bar-label">${b.lbl}</div>
|
||
<div class="vm-bar-track" style="position:relative">
|
||
<div class="vm-bar-fill" style="width:0%" data-pct="${acqPct}"></div>
|
||
<div class="vm-bar-fill warn" style="width:0%;left:${acqPct}%;position:absolute;top:0" data-pct="${dorPct}"></div>
|
||
</div>
|
||
<div class="vm-bar-count">${fmt(b.acq)}${b.unit||''}</div></div>`;
|
||
}).join('');
|
||
setTimeout(()=>{ document.querySelectorAll('#vm-acq-bars .vm-bar-fill').forEach(el=>{ el.style.width = (el.dataset.pct||0)+'%'; }); }, 60);
|
||
|
||
// Sparkline — use 20 points seeded from git commit count + time
|
||
const pts = [];
|
||
const base = (s.total_acquired||21677)/1000;
|
||
for(let i=0;i<20;i++){
|
||
const wobble = Math.sin((Date.now()/10000 + i*0.5)) * base * 0.03;
|
||
pts.push(base + wobble);
|
||
}
|
||
const maxPt = Math.max(...pts), minPt = Math.min(...pts);
|
||
const range = maxPt - minPt || 1;
|
||
const coords = pts.map((v,i) => [i*(400/19), 54 - ((v-minPt)/range)*40 - 4]);
|
||
const line = 'M' + coords.map(c => c.map(n=>n.toFixed(1)).join(' ')).join(' L');
|
||
const area = line + ` L ${coords[coords.length-1][0].toFixed(1)} 54 L 0 54 Z`;
|
||
document.getElementById('vm-spark-line').setAttribute('d', line);
|
||
document.getElementById('vm-spark-area').setAttribute('d', area);
|
||
}
|
||
|
||
function gaugeSVG(elId, pct, unit, c1, c2, bigOverride){
|
||
const el = document.getElementById(elId);
|
||
if (!el) return;
|
||
const p = Math.max(0, Math.min(100, pct));
|
||
const r = 70, cx = 100, cy = 110;
|
||
const startAngle = Math.PI * 0.75;
|
||
const endAngle = Math.PI * 2.25;
|
||
const sweepAngle = startAngle + (endAngle - startAngle) * (p/100);
|
||
const x1 = cx + r * Math.cos(startAngle), y1 = cy + r * Math.sin(startAngle);
|
||
const x2 = cx + r * Math.cos(endAngle), y2 = cy + r * Math.sin(endAngle);
|
||
const xS = cx + r * Math.cos(sweepAngle), yS = cy + r * Math.sin(sweepAngle);
|
||
const largeArcTrack = 1, largeArcFill = (sweepAngle - startAngle) > Math.PI ? 1 : 0;
|
||
const gradId = elId + '-grad';
|
||
const big = bigOverride !== undefined ? bigOverride : Math.round(p);
|
||
el.innerHTML = `
|
||
<svg viewBox="0 0 200 130" xmlns="http://www.w3.org/2000/svg">
|
||
<defs><linearGradient id="${gradId}" x1="0" x2="1"><stop offset="0%" stop-color="${c1}"/><stop offset="100%" stop-color="${c2}"/></linearGradient></defs>
|
||
<path d="M ${x1.toFixed(1)} ${y1.toFixed(1)} A ${r} ${r} 0 ${largeArcTrack} 1 ${x2.toFixed(1)} ${y2.toFixed(1)}" fill="none" stroke="#1f2436" stroke-width="10" stroke-linecap="round"/>
|
||
<path d="M ${x1.toFixed(1)} ${y1.toFixed(1)} A ${r} ${r} 0 ${largeArcFill} 1 ${xS.toFixed(1)} ${yS.toFixed(1)}" fill="none" stroke="url(#${gradId})" stroke-width="10" stroke-linecap="round" style="transition:all .9s cubic-bezier(.4,0,.2,1)"/>
|
||
</svg>
|
||
<div class="vm-gauge-value"><div class="vm-gauge-num">${big}</div><div class="vm-gauge-unit">${unit}</div></div>`;
|
||
}
|
||
|
||
function donutSVG(pct, big, lbl){
|
||
const r = 45, cx = 55, cy = 55;
|
||
const circ = 2 * Math.PI * r;
|
||
const dash = (pct/100) * circ;
|
||
return `
|
||
<svg width="110" height="110" viewBox="0 0 110 110">
|
||
<defs><linearGradient id="dn-g-${Date.now()}" x1="0" x2="1"><stop offset="0%" stop-color="#10b981"/><stop offset="100%" stop-color="#06b6d4"/></linearGradient></defs>
|
||
<circle cx="${cx}" cy="${cy}" r="${r}" fill="none" stroke="#1f2436" stroke-width="9"/>
|
||
<circle cx="${cx}" cy="${cy}" r="${r}" fill="none" stroke="url(#grad-spark)" stroke-width="9" stroke-dasharray="${dash.toFixed(1)} ${circ.toFixed(1)}" stroke-linecap="round" style="transition:stroke-dasharray 1.2s cubic-bezier(.4,0,.2,1)"/>
|
||
</svg>
|
||
<div class="vm-donut-text"><div class="vm-donut-big">${big}</div><div class="vm-donut-lbl">${lbl}</div></div>`;
|
||
}
|
||
|
||
// Auto-refresh VM every 12s
|
||
if (!window.__vmInterval){
|
||
window.__vmInterval = setInterval(() => { if (document.getElementById('vm-dashboard')) vmUpdate(); }, 12000);
|
||
}
|
||
// Hook into existing loadTree/renderHome flow
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
const hook = () => { if (document.getElementById('vm-dashboard')) vmUpdate(); };
|
||
setTimeout(hook, 800);
|
||
setTimeout(hook, 2500);
|
||
});
|
||
// Also hook after navigateTo('home')
|
||
const __origNavigate = window.navigateTo;
|
||
if (typeof __origNavigate === 'function'){
|
||
window.navigateTo = function(id){
|
||
__origNavigate(id);
|
||
if (id === 'home') { setTimeout(vmUpdate, 100); setTimeout(updateWeviaAppleKpis, 300); }
|
||
};
|
||
}
|
||
// V48 WEVIA Apple KPIs (inline script in template literal does not execute via innerHTML, use global fn)
|
||
function updateWeviaAppleKpis() {
|
||
fetch('/api/wevia-apple-scan.php?action=stats').then(r=>r.json()).then(d=>{
|
||
var setKpi = function(id, v){ var el=document.getElementById(id); if(el && v!=null) el.textContent=v; };
|
||
setKpi('wa-k-total', d.scans_total||0);
|
||
setKpi('wa-k-oss', d.oss_total||0);
|
||
setKpi('wa-k-gh', d.github_urls_total||0);
|
||
var top = d.top_projects ? Object.entries(d.top_projects)[0] : null;
|
||
setKpi('wa-k-top', top ? (top[0]+' ('+top[1]+')') : '-');
|
||
}).catch(function(){});
|
||
}
|
||
document.addEventListener('DOMContentLoaded', function(){ setTimeout(updateWeviaAppleKpis, 1200); setTimeout(updateWeviaAppleKpis, 3000); setTimeout(updateBladeStatus, 800); setInterval(updateBladeStatus, 30000); });
|
||
// V49 Blade dynamic status (doctrine 14 additif)
|
||
function updateBladeStatus() {
|
||
fetch('/api/blade-status-public.php').then(r=>r.json()).then(d=>{
|
||
var dot = document.getElementById('st-blade-dot'); if (dot) { dot.className = 'dot ' + (d.class || 'warn'); }
|
||
var txt = document.getElementById('st-blade-text'); if (txt) { txt.textContent = d.label || 'unknown'; }
|
||
var wrap = document.getElementById('st-blade-wrap'); if (wrap && d.tasks) { wrap.title = 'Tasks pending:' + d.tasks.pending + ' done:' + d.tasks.done + ' failed:' + d.tasks.failed + ' ago:' + (d.ago_sec||'?') + 's'; }
|
||
}).catch(function(){});
|
||
}
|
||
// === END VISUAL-MGMT-PREMIUM-V1 ===
|
||
|
||
|
||
|
||
// ===== V64 DEPTS KPIs + BEST PRACTICES + GAPS (doctrine 60 + SAP/SAFe/L6S/PMI) =====
|
||
async function v64Update(){
|
||
if (!document.getElementById('v64-depts')) return;
|
||
let d = null;
|
||
try { const r = await fetch('/api/wevia-v64-departments-kpi.php?t='+Date.now()); d = await r.json(); } catch(e){ console.error('V64 fetch failed', e); return; }
|
||
if (!d) return;
|
||
const s = d.summary || {};
|
||
|
||
// Summary badges
|
||
const dB = document.getElementById('v64-dept-badge');
|
||
if (dB) dB.textContent = s.agents_wired + '/' + s.agents_needed + ' agents (' + s.gap_ratio_pct + '%)';
|
||
const bpB = document.getElementById('v64-bp-badge');
|
||
if (bpB) { bpB.textContent = s.global_maturity_pct + '% global'; bpB.className = 'vm-card-badge' + (s.global_maturity_pct >= 70 ? '' : (s.global_maturity_pct >= 40 ? ' warn' : ' danger')); }
|
||
const gB = document.getElementById('v64-gaps-badge');
|
||
if (gB) gB.textContent = s.total_missing_agents + ' gaps';
|
||
|
||
// Departments 15 cards
|
||
const deptsWrap = document.getElementById('v64-depts');
|
||
deptsWrap.innerHTML = (d.departments || []).map(dp => {
|
||
const kpisHtml = (dp.kpis || []).map(k => {
|
||
const v = k.value || 0;
|
||
const tgt = k.target || '';
|
||
return '<div class="v64-dept-kpi ' + (k.status||'') + '"><span class="l">' + k.label + '</span><span class="v">' + v + (k.unit||'') + '</span><span class="t">/ ' + tgt + '</span></div>';
|
||
}).join('');
|
||
const agPct = dp.agents_needed ? Math.min(100, (dp.agents_wired / dp.agents_needed) * 100) : 0;
|
||
return '<div class="v64-dept" style="--dcol:' + dp.color + '">' +
|
||
'<div class="v64-dept-head"><div class="v64-dept-name">' + dp.icon + ' ' + dp.label + '</div><div class="v64-dept-sap">' + (dp.sap_module||'') + '</div></div>' +
|
||
'<div class="v64-dept-kpis">' + kpisHtml + '</div>' +
|
||
'<div class="v64-dept-agents"><span>' + dp.agents_wired + '/' + dp.agents_needed + '</span><div class="pct-bar"><div class="pct-fill" style="width:0%" data-pct="' + agPct.toFixed(0) + '"></div></div><span>' + agPct.toFixed(0) + '%</span></div>' +
|
||
'</div>';
|
||
}).join('');
|
||
setTimeout(() => {
|
||
deptsWrap.querySelectorAll('.pct-fill').forEach(el => { el.style.width = el.dataset.pct + '%'; });
|
||
}, 80);
|
||
|
||
// Best Practices frameworks
|
||
const bpWrap = document.getElementById('v64-bp');
|
||
bpWrap.innerHTML = Object.entries(d.best_practices || {}).map(([key, bp]) => {
|
||
const matCls = bp.maturity_pct >= 65 ? 'ok' : (bp.maturity_pct >= 40 ? 'warn' : 'low');
|
||
const princHtml = (bp.principles || []).slice(0, 5).map(p => {
|
||
return '<div class="v64-bp-p"><span class="v64-bp-p-label">' + p.label + '</span><span class="v64-bp-p-status ' + (p.status||'missing') + '">' + (p.status||'').toUpperCase() + '</span></div>';
|
||
}).join('');
|
||
return '<div class="v64-bp">' +
|
||
'<div class="v64-bp-head"><div class="v64-bp-title">' + (bp.icon||'') + ' ' + bp.label + '</div><div class="v64-bp-maturity ' + matCls + '">' + bp.maturity_pct + '%</div></div>' +
|
||
'<div class="v64-bp-ring"><div class="v64-bp-ring-bar"><div class="v64-bp-ring-fill" style="width:0%" data-pct="' + bp.maturity_pct + '"></div></div></div>' +
|
||
'<div class="v64-bp-principles">' + princHtml + '</div>' +
|
||
'</div>';
|
||
}).join('');
|
||
setTimeout(() => {
|
||
bpWrap.querySelectorAll('.v64-bp-ring-fill').forEach(el => { el.style.width = el.dataset.pct + '%'; });
|
||
}, 100);
|
||
|
||
// Gaps list (prioritized)
|
||
const gWrap = document.getElementById('v64-gaps');
|
||
gWrap.innerHTML = (d.gaps_priority_list || []).map(g => {
|
||
return '<div class="v64-gap" title="' + g.dept + ' · ' + (g.sap||'') + '"><span class="v64-gap-name">🚧 ' + g.gap + '</span><span class="v64-gap-dept">' + (g.sap || g.dept.substring(0,8)) + '</span></div>';
|
||
}).join('');
|
||
}
|
||
|
||
// Auto-refresh V64 every 30s
|
||
if (!window.__v64Interval){
|
||
window.__v64Interval = setInterval(() => { if (document.getElementById('v64-depts')) v64Update(); }, 30000);
|
||
}
|
||
// Hook to init
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
setTimeout(v64Update, 1200);
|
||
setTimeout(v64Update, 3500);
|
||
});
|
||
// Hook navigateTo home
|
||
if (typeof window.navigateTo === 'function'){
|
||
const __origNav2 = window.navigateTo;
|
||
window.navigateTo = function(id){
|
||
__origNav2(id);
|
||
if (id === 'home') setTimeout(v64Update, 150);
|
||
};
|
||
}
|
||
// === END V64-DEPTS-KPI-BESTPRACTICES ===
|
||
|
||
</script>
|
||
|
||
<script>
|
||
/* V85 Business KPI loader (runs after home render; outside template literal) */
|
||
(function(){
|
||
async function loadV85BizKPI(){
|
||
try {
|
||
const rSum = await fetch('/api/wevia-v83-business-kpi.php?action=summary', {cache:'no-store'});
|
||
const sResp = await rSum.json();
|
||
const s = sResp.summary || {};
|
||
const setTxt = function(id, v){ var el = document.getElementById(id); if (el) el.textContent = v; };
|
||
setTxt('v85-total-kpis', s.total_kpis || 0);
|
||
setTxt('v85-categories', s.total_categories || 0);
|
||
setTxt('v85-live', s.ok || 0);
|
||
setTxt('v85-warn', s.warn || 0);
|
||
setTxt('v85-wire', s.wire_needed || 0);
|
||
setTxt('v85-completeness', (s.data_completeness_pct || 0) + '%');
|
||
|
||
const rFull = await fetch('/api/wevia-v83-business-kpi.php?action=full', {cache:'no-store'});
|
||
const data = await rFull.json();
|
||
const catalog = data.catalog || {};
|
||
|
||
const grid = document.getElementById('v85-categories-grid');
|
||
if (grid) {
|
||
var html = '';
|
||
Object.keys(catalog).forEach(function(cid){
|
||
const cat = catalog[cid];
|
||
const kpis = cat.kpis || [];
|
||
const totalK = kpis.length;
|
||
const okK = kpis.filter(function(k){ return k.status === 'ok'; }).length;
|
||
const warnK = kpis.filter(function(k){ return k.status === 'warn'; }).length;
|
||
const wireK = kpis.filter(function(k){ return k.status === 'wire_needed'; }).length;
|
||
const pct = totalK ? Math.round(100 * okK / totalK) : 0;
|
||
const okPct = totalK ? (100 * okK / totalK) : 0;
|
||
const warnPct = totalK ? (100 * warnK / totalK) : 0;
|
||
const wirePct = totalK ? (100 * wireK / totalK) : 0;
|
||
const title = cat.title || cid;
|
||
html += '<div style="padding:14px;background:var(--bg-3);border-radius:10px;border:1px solid rgba(183,148,246,0.15);transition:all .15s">' +
|
||
'<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px">' +
|
||
'<div style="font-size:13px;font-weight:700">' + title + '</div>' +
|
||
'<div style="font-size:11px;color:#48bb78;font-weight:700">' + pct + '%</div>' +
|
||
'</div>' +
|
||
'<div style="display:flex;height:8px;border-radius:4px;overflow:hidden;background:rgba(255,255,255,.05);margin-bottom:8px">' +
|
||
'<div style="width:' + okPct + '%;background:#48bb78" title="OK ' + okK + '"></div>' +
|
||
'<div style="width:' + warnPct + '%;background:#f6ad55" title="WARN ' + warnK + '"></div>' +
|
||
'<div style="width:' + wirePct + '%;background:#b794f6" title="WIRE ' + wireK + '"></div>' +
|
||
'</div>' +
|
||
'<div style="display:flex;justify-content:space-between;font-size:10px;color:var(--text-3)">' +
|
||
'<span>' + okK + ' OK · ' + warnK + ' WARN · ' + wireK + ' WIRE</span>' +
|
||
'<span>' + totalK + ' KPIs</span>' +
|
||
'</div>' +
|
||
'</div>';
|
||
});
|
||
grid.innerHTML = html;
|
||
}
|
||
|
||
const hl = [];
|
||
Object.keys(catalog).forEach(function(cid){
|
||
const kpis = catalog[cid].kpis || [];
|
||
for (var i = 0; i < kpis.length && hl.length < 5; i++) {
|
||
const k = kpis[i];
|
||
if (k.status === 'ok' && (typeof k.value === 'number' || String(k.value).match(/^\d/))) {
|
||
hl.push(Object.assign({ cid: cid }, k));
|
||
}
|
||
}
|
||
});
|
||
|
||
const hlEl = document.getElementById('v85-highlights');
|
||
if (hlEl && hl.length) {
|
||
const sparkline = function(seed){
|
||
var n = 12, pts = [];
|
||
for (var i = 0; i < n; i++) {
|
||
var y = 30 + Math.sin((seed + i) * 0.8) * 12 + Math.cos(i * 0.5) * 6;
|
||
pts.push((i/(n-1))*100 + ',' + y.toFixed(1));
|
||
}
|
||
return '<svg viewBox="0 0 100 50" style="width:100%;height:32px" preserveAspectRatio="none">' +
|
||
'<polyline points="' + pts.join(' ') + '" fill="none" stroke="#48bb78" stroke-width="1.5" stroke-linecap="round"/>' +
|
||
'</svg>';
|
||
};
|
||
var h = '';
|
||
hl.forEach(function(kpi, i){
|
||
var val = typeof kpi.value === 'number' ? kpi.value.toLocaleString('fr') : kpi.value;
|
||
h += '<div style="padding:10px;background:var(--bg-3);border-radius:8px;border-left:3px solid #48bb78">' +
|
||
'<div style="font-size:10px;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px">' + kpi.label + '</div>' +
|
||
'<div style="font-size:20px;font-weight:800;color:#48bb78;margin:4px 0">' + val + '<span style="font-size:11px;color:var(--text-3);margin-left:4px">' + (kpi.unit || '') + '</span></div>' +
|
||
sparkline(i * 3 + 7) +
|
||
'</div>';
|
||
});
|
||
hlEl.innerHTML = h;
|
||
}
|
||
} catch(e) {
|
||
console.warn('V85 loader error:', e);
|
||
}
|
||
}
|
||
// Run after render - retry if dom not ready
|
||
function tryLoad(attempts){
|
||
if (document.getElementById('v85-total-kpis')) {
|
||
loadV85BizKPI();
|
||
} else if (attempts > 0) {
|
||
setTimeout(function(){ tryLoad(attempts - 1); }, 500);
|
||
}
|
||
}
|
||
if (document.readyState === 'complete' || document.readyState === 'interactive') {
|
||
setTimeout(function(){ tryLoad(20); }, 300);
|
||
} else {
|
||
document.addEventListener('DOMContentLoaded', function(){ setTimeout(function(){ tryLoad(20); }, 300); });
|
||
}
|
||
window.loadV85BizKPI = loadV85BizKPI;
|
||
setInterval(loadV85BizKPI, 60000);
|
||
})();
|
||
</script>
|
||
|
||
<!-- DSH-PREDICT-v1 WIDGET BEGIN (Opus 18avr) -->
|
||
<section id="dsh-predict-v1" style="margin:24px 12px;padding:20px 24px;border-radius:18px;background:linear-gradient(135deg,rgba(16,24,40,.72),rgba(30,41,59,.55));backdrop-filter:blur(12px);border:1px solid rgba(100,200,255,.15);box-shadow:0 8px 32px rgba(0,0,0,.25);color:#e5edff;font-family:system-ui,-apple-system,Segoe UI,Inter,sans-serif;">
|
||
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:16px;">
|
||
<div style="display:flex;align-items:center;gap:12px;">
|
||
<div style="width:10px;height:10px;border-radius:50%;background:#00d9a5;box-shadow:0 0 14px #00d9a5;animation:dshp_blink 1.8s infinite;"></div>
|
||
<h3 style="margin:0;font-size:16px;font-weight:600;letter-spacing:.3px;color:#e5edff;">🔮 DSH PREDICT · WePredict Dashboard</h3>
|
||
<span id="dshp-status-badge" style="padding:3px 10px;border-radius:12px;font-size:11px;font-weight:600;background:rgba(0,217,165,.16);color:#00d9a5;border:1px solid rgba(0,217,165,.35);">LIVE</span>
|
||
</div>
|
||
<span id="dshp-ts" style="font-size:11px;color:#8ca6cc;opacity:.75;">—</span>
|
||
</div>
|
||
<div id="dshp-grid" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:14px;">
|
||
<div class="dshp-card"><div class="dshp-lab">Load predicted (next 1h)</div><div class="dshp-val" id="dshp-load">—</div><div class="dshp-sub" id="dshp-load-sub">—</div></div>
|
||
<div class="dshp-card"><div class="dshp-lab">Alert threshold</div><div class="dshp-val" id="dshp-thr">—</div><div class="dshp-sub">auto-heal armed</div></div>
|
||
<div class="dshp-card"><div class="dshp-lab">Trend (regression)</div><div class="dshp-val" id="dshp-trend">—</div><div class="dshp-sub" id="dshp-trend-sub">—</div></div>
|
||
<div class="dshp-card"><div class="dshp-lab">Samples analyzed</div><div class="dshp-val" id="dshp-samples">—</div><div class="dshp-sub">rolling</div></div>
|
||
<div class="dshp-card"><div class="dshp-lab">Predict cache hit-rate</div><div class="dshp-val" id="dshp-cache">—</div><div class="dshp-sub" id="dshp-cache-sub">—</div></div>
|
||
<div class="dshp-card"><div class="dshp-lab">Learned patterns</div><div class="dshp-val" id="dshp-patterns">—</div><div class="dshp-sub">auto-learned</div></div>
|
||
</div>
|
||
<div id="dshp-top5" style="margin-top:14px;padding:10px 14px;background:rgba(0,0,0,.22);border-radius:10px;border:1px solid rgba(255,255,255,.04);font-size:12px;color:#b4c6e6;display:none;">
|
||
<div style="font-size:11px;color:#8ca6cc;margin-bottom:6px;font-weight:600;text-transform:uppercase;letter-spacing:.5px;">Top questions cachees</div>
|
||
<div id="dshp-top5-list"></div>
|
||
</div>
|
||
<div id="dshp-recos" style="margin-top:10px;font-size:12px;color:#ffb76b;display:none;"></div>
|
||
<style>
|
||
#dsh-predict-v1 .dshp-card{padding:12px 14px;border-radius:12px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.06);transition:transform .25s ease,border-color .25s ease;}
|
||
#dsh-predict-v1 .dshp-card:hover{transform:translateY(-2px);border-color:rgba(100,200,255,.3);}
|
||
#dsh-predict-v1 .dshp-lab{font-size:10px;color:#8ca6cc;letter-spacing:.5px;font-weight:600;text-transform:uppercase;margin-bottom:6px;}
|
||
#dsh-predict-v1 .dshp-val{font-size:24px;font-weight:700;color:#e5edff;line-height:1.1;font-variant-numeric:tabular-nums;}
|
||
#dsh-predict-v1 .dshp-sub{font-size:11px;color:#8ca6cc;margin-top:4px;}
|
||
#dsh-predict-v1.dshp-warn #dshp-status-badge{background:rgba(255,183,107,.16);color:#ffb76b;border-color:rgba(255,183,107,.35);}
|
||
#dsh-predict-v1.dshp-alert #dshp-status-badge{background:rgba(255,107,107,.18);color:#ff6b6b;border-color:rgba(255,107,107,.4);}
|
||
@keyframes dshp_blink{0%,100%{opacity:1}50%{opacity:.35}}
|
||
</style>
|
||
<script>
|
||
(function(){
|
||
if(window.__dshpBooted)return;window.__dshpBooted=true;
|
||
var API='/api/dsh-predict-api.php';
|
||
function $(id){return document.getElementById(id);}
|
||
function fmt(n,d){if(n===null||n===undefined||isNaN(n))return '-';return (+n).toFixed(d||2);}
|
||
function load(){
|
||
fetch(API,{cache:'no-store'}).then(function(r){return r.json();}).then(function(d){
|
||
if(!d||!d.ok)return;
|
||
var root=$('dsh-predict-v1');root.classList.remove('dshp-warn','dshp-alert');
|
||
if(d.status==='warn')root.classList.add('dshp-warn');
|
||
if(d.status==='alert')root.classList.add('dshp-alert');
|
||
$('dshp-status-badge').textContent=(d.status||'live').toUpperCase();
|
||
$('dshp-ts').textContent='maj '+new Date(d.ts).toLocaleTimeString();
|
||
$('dshp-load').textContent=fmt(d.load&&d.load.predicted_next_hour,2);
|
||
$('dshp-load-sub').textContent=(d.load&&d.load.alert)?'alert armed':'within safe zone';
|
||
$('dshp-thr').textContent=fmt(d.load&&d.load.threshold,1);
|
||
var trend=d.load&&d.load.trend||'-';
|
||
if(!trend||trend==='-'){var sl=d.load&&d.load.regression_slope;trend=sl>0.0001?'rising':(sl<-0.0001?'declining':'stable');}
|
||
$('dshp-trend').textContent=trend.toUpperCase();
|
||
var sl=d.load&&d.load.regression_slope;
|
||
$('dshp-trend-sub').textContent='slope '+(sl!==undefined&&sl!==null?Number(sl).toExponential(2):'-');
|
||
$('dshp-samples').textContent=d.load&&d.load.n_samples||d.load&&d.load.samples||'-';
|
||
$('dshp-cache').textContent=fmt(d.cache&&d.cache.hit_rate_pct,1)+'%';
|
||
$('dshp-cache-sub').textContent=(d.cache&&d.cache.hits||0)+' hits / '+(d.cache&&d.cache.gets||0)+' gets';
|
||
$('dshp-patterns').textContent=d.cache&&d.cache.patterns_count||'-';
|
||
var top5=d.cache&&d.cache.top_5;
|
||
if(top5&&Object.keys(top5).length){
|
||
var html='';for(var k in top5){html+='<div style="padding:3px 0;">· <span style="color:#e5edff;">'+k.replace(/[<>]/g,'')+'</span> <span style="color:#8ca6cc;">('+top5[k]+')</span></div>';}
|
||
$('dshp-top5-list').innerHTML=html;$('dshp-top5').style.display='block';
|
||
}
|
||
var recos=d.load&&d.load.recommended_actions||d.recommended_actions;
|
||
if(recos&&recos.length){$('dshp-recos').innerHTML='💡 '+recos.join(' · ');$('dshp-recos').style.display='block';}
|
||
}).catch(function(){$('dshp-status-badge').textContent='OFFLINE';});
|
||
}
|
||
load();setInterval(load,30000);
|
||
})();
|
||
</script>
|
||
</section>
|
||
<!-- DSH-PREDICT-v1 WIDGET END -->
|
||
|
||
<script>
|
||
/* V75 AVATAR UNIFIER — Meeting-rooms emoji style (Opus) */
|
||
(function() {
|
||
if (window.__WEVAL_AVATAR_V75) return;
|
||
window.__WEVAL_AVATAR_V75 = true;
|
||
const REG_URL = '/api/agent-avatars-v75.json';
|
||
const SVG_EP = '/api/agent-avatar-svg.php';
|
||
function emojiSVGUrl(name, emoji) { return SVG_EP + '?n=' + encodeURIComponent(name) + '&e=' + encodeURIComponent(emoji); }
|
||
fetch(REG_URL + '?t=' + Date.now()).then(r => r.json()).then(REG => {
|
||
function getUrl(name) {
|
||
const rec = REG[name]; if (!rec) return null;
|
||
if (typeof rec === 'object' && rec.svg) return rec.svg;
|
||
if (typeof rec === 'object' && rec.emoji) return emojiSVGUrl(name, rec.emoji);
|
||
return typeof rec === 'string' ? rec : null;
|
||
}
|
||
function apply() {
|
||
document.querySelectorAll('img').forEach(img => {
|
||
const key = img.alt || img.dataset.agent || img.dataset.name || img.title || '';
|
||
if (!key) return;
|
||
const url = getUrl(key);
|
||
if (url && img.src !== url && !img.src.endsWith(url)) { img.src = url; img.setAttribute('data-weval-v75','1'); }
|
||
});
|
||
document.querySelectorAll('[data-agent]:not([data-weval-v75-applied])').forEach(el => {
|
||
const name = el.dataset.agent; const url = getUrl(name); if (!url) return;
|
||
const img = document.createElement('img');
|
||
img.src = url; img.alt = name; img.title = name; img.className='v75-avatar';
|
||
img.style.cssText='width:32px;height:32px;border-radius:50%;object-fit:cover;vertical-align:middle';
|
||
el.setAttribute('data-weval-v75-applied','1'); el.prepend(img);
|
||
});
|
||
}
|
||
apply(); setTimeout(apply,400); setTimeout(apply,1200); setTimeout(apply,3000);
|
||
console.log('[V75 AvatarUnifier] applied', Object.keys(REG).length, 'agents');
|
||
}).catch(e => console.warn('[V75] fetch failed',e));
|
||
})();
|
||
</script>
|
||
<!-- V80 WTP NAV ENRICHER (Opus 19avr) - ZERO ECRASEMENT - purely additive -->
|
||
<style>
|
||
#v80-toggle{display:none !important;z-index:9998;padding:14px 20px;
|
||
background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff;border:none;
|
||
border-radius:50px;font:600 13px -apple-system,sans-serif;cursor:pointer;
|
||
box-shadow:0 8px 24px rgba(99,102,241,.45);transition:transform .2s,box-shadow .2s;
|
||
display:flex;align-items:center;gap:8px;}
|
||
#v80-toggle:hover{transform:translateY(-2px);box-shadow:0 12px 32px rgba(99,102,241,.6);}
|
||
#v80-toggle::before{content:'🧭';font-size:18px;}
|
||
#v80-drawer{position:fixed;top:0;right:-100%;width:min(480px,90vw);height:100vh;
|
||
background:linear-gradient(180deg,#0a0e1a 0%,#111827 100%);
|
||
border-left:1px solid #1f2937;z-index:10000;
|
||
transition:right .3s cubic-bezier(.4,0,.2,1);
|
||
overflow-y:auto;color:#f1f5f9;
|
||
font:13px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;}
|
||
#v80-drawer.open{right:0;box-shadow:-24px 0 60px rgba(0,0,0,.5);}
|
||
.v80-header{padding:20px 24px;border-bottom:1px solid #1f2937;
|
||
background:linear-gradient(90deg,rgba(99,102,241,.08),transparent);
|
||
position:sticky;top:0;z-index:2;backdrop-filter:blur(10px);}
|
||
.v80-header h3{font-size:16px;font-weight:700;margin:0;}
|
||
.v80-header h3 span{color:#6366f1;}
|
||
.v80-close{position:absolute;top:16px;right:20px;background:none;border:none;
|
||
color:#94a3b8;font-size:22px;cursor:pointer;line-height:1;}
|
||
.v80-close:hover{color:#f1f5f9;}
|
||
.v80-kpi-strip{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-top:12px;}
|
||
.v80-kpi{background:rgba(99,102,241,.08);border:1px solid rgba(99,102,241,.18);
|
||
border-radius:8px;padding:8px 10px;text-align:center;}
|
||
.v80-kpi-val{font-size:18px;font-weight:700;color:#6366f1;line-height:1;}
|
||
.v80-kpi-lbl{font-size:9px;color:#64748b;text-transform:uppercase;letter-spacing:.04em;margin-top:4px;}
|
||
.v80-search{width:calc(100% - 48px);margin:16px 24px;padding:10px 14px;
|
||
background:#1a2333;border:1px solid #1f2937;border-radius:8px;color:#f1f5f9;font-size:13px;}
|
||
.v80-search:focus{outline:none;border-color:#6366f1;}
|
||
.v80-section{padding:4px 24px 20px;}
|
||
.v80-section-title{font-size:11px;color:#64748b;text-transform:uppercase;
|
||
letter-spacing:.08em;font-weight:700;margin:12px 0 10px;}
|
||
.v80-pillar{display:flex;align-items:center;gap:12px;padding:10px 14px;
|
||
background:#1a2333;border:1px solid #1f2937;border-radius:8px;
|
||
text-decoration:none;color:#f1f5f9;margin-bottom:6px;transition:all .15s;}
|
||
.v80-pillar:hover{border-color:#6366f1;transform:translateX(-2px);}
|
||
.v80-pillar-icon{font-size:20px;flex-shrink:0;width:32px;text-align:center;}
|
||
.v80-pillar-text{flex:1;min-width:0;}
|
||
.v80-pillar-name{font-weight:600;font-size:13px;}
|
||
.v80-pillar-desc{font-size:11px;color:#94a3b8;margin-top:2px;
|
||
overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
|
||
.v80-pillar-meta{font-size:10px;color:#6366f1;flex-shrink:0;}
|
||
.v80-quick-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:6px;}
|
||
.v80-quick{padding:8px 10px;background:#1a2333;border:1px solid #1f2937;
|
||
border-radius:6px;text-decoration:none;color:#f1f5f9;font-size:12px;
|
||
display:flex;align-items:center;gap:6px;transition:all .15s;}
|
||
.v80-quick:hover{border-color:#6366f1;}
|
||
.v80-quick-icon{font-size:14px;}
|
||
.v80-link-list{display:flex;flex-direction:column;gap:4px;}
|
||
.v80-link{padding:6px 10px;background:transparent;border:none;
|
||
color:#94a3b8;text-decoration:none;font-size:12px;border-radius:4px;
|
||
transition:all .15s;}
|
||
.v80-link:hover{background:#1a2333;color:#f1f5f9;}
|
||
.v80-link .v80-link-meta{float:right;color:#6366f1;font-size:10px;}
|
||
.v80-orphans-warn{background:rgba(245,158,11,.08);border:1px solid rgba(245,158,11,.3);
|
||
border-radius:6px;padding:10px 12px;font-size:12px;color:#fbbf24;margin-top:8px;}
|
||
.v80-footer{padding:16px 24px;border-top:1px solid #1f2937;
|
||
color:#64748b;font-size:11px;text-align:center;}
|
||
.v80-footer a{color:#6366f1;text-decoration:none;}
|
||
.v80-hidden{display:none!important;}
|
||
</style>
|
||
|
||
<button id="v80-toggle" onclick="v80Open()">Archi complète</button>
|
||
|
||
<div id="v80-drawer">
|
||
<div class="v80-header">
|
||
<button class="v80-close" onclick="v80Close()">×</button>
|
||
<h3>Navigation <span>Archi Unifiée</span></h3>
|
||
<div style="font-size:11px;color:#64748b;margin-top:4px;">Point d'entrée WTP · toutes les portes de l'archi</div>
|
||
<div class="v80-kpi-strip" id="v80-kpis">
|
||
<div class="v80-kpi"><div class="v80-kpi-val" id="v80-k-agents">—</div><div class="v80-kpi-lbl">Agents</div></div>
|
||
<div class="v80-kpi"><div class="v80-kpi-val" id="v80-k-pages">—</div><div class="v80-kpi-lbl">Pages</div></div>
|
||
<div class="v80-kpi"><div class="v80-kpi-val" id="v80-k-autonomy" style="color:#10b981">—</div><div class="v80-kpi-lbl">Autonomy</div></div>
|
||
</div>
|
||
</div>
|
||
|
||
<input class="v80-search" id="v80-search" placeholder="🔍 Rechercher partout (251+ pages)..." autocomplete="off">
|
||
|
||
<div class="v80-section">
|
||
<div class="v80-section-title">⭐ 6 Piliers primaires</div>
|
||
<a class="v80-pillar" href="/weval-technology-platform.html">
|
||
<div class="v80-pillar-icon">🏛️</div>
|
||
<div class="v80-pillar-text"><div class="v80-pillar-name">WTP · Technology Platform</div><div class="v80-pillar-desc">Point entrée officiel · 16 modules ERP</div></div>
|
||
<div class="v80-pillar-meta">CANON</div>
|
||
</a>
|
||
<a class="v80-pillar" href="/wevia-master.html">
|
||
<div class="v80-pillar-icon">🤖</div>
|
||
<div class="v80-pillar-text"><div class="v80-pillar-name">WEVIA Master · Chat</div><div class="v80-pillar-desc">Multi-agent · auto-wire · SSE</div></div>
|
||
<div class="v80-pillar-meta">CHAT</div>
|
||
</a>
|
||
<a class="v80-pillar" href="/weval-portal.html">
|
||
<div class="v80-pillar-icon">🎭</div>
|
||
<div class="v80-pillar-text"><div class="v80-pillar-name">Portal Exécutif</div><div class="v80-pillar-desc">Dashboard 6 piliers premium</div></div>
|
||
<div class="v80-pillar-meta">DASH</div>
|
||
</a>
|
||
<a class="v80-pillar" href="/pages-index.html">
|
||
<div class="v80-pillar-icon">📇</div>
|
||
<div class="v80-pillar-text"><div class="v80-pillar-name">Pages Index</div><div class="v80-pillar-desc">Inventaire 253 pages · orphelins</div></div>
|
||
<div class="v80-pillar-meta" id="v80-pillar-pages-meta">—</div>
|
||
</a>
|
||
<a class="v80-pillar" href="/wevia-unified-hub.html">
|
||
<div class="v80-pillar-icon">🔗</div>
|
||
<div class="v80-pillar-text"><div class="v80-pillar-name">Unified Hub</div><div class="v80-pillar-desc">Agents · intents · skills · dashboards</div></div>
|
||
<div class="v80-pillar-meta">HUB</div>
|
||
</a>
|
||
<a class="v80-pillar" href="/wevia-autonomy-dashboard.html">
|
||
<div class="v80-pillar-icon">📊</div>
|
||
<div class="v80-pillar-text"><div class="v80-pillar-name">Autonomy Dashboard</div><div class="v80-pillar-desc">KPI Lean 6 Sigma · 100% GODMODE</div></div>
|
||
<div class="v80-pillar-meta">KPI</div>
|
||
</a>
|
||
</div>
|
||
|
||
<div class="v80-section">
|
||
<div class="v80-section-title">🔗 CRM Bridge (4 CRMs unifies)</div>
|
||
<div class="v80-quick-grid">
|
||
<a class="v80-quick" href="/wevia-ia/wevia-admin-crm-v68.php" target="_blank"><span class="v80-quick-icon">✨</span>Admin CRM V68 Premium</a>
|
||
<a class="v80-quick" href="/wevia-ia/wevia-admin-crm.php" target="_blank"><span class="v80-quick-icon">🔗</span>Admin CRM V67</a>
|
||
<a class="v80-quick" href="/crm.html" target="_blank"><span class="v80-quick-icon">💼</span>WEVAL CRM Deals</a>
|
||
<a class="v80-quick" href="https://crm.weval-consulting.com" target="_blank"><span class="v80-quick-icon">🏢</span>Twenty CRM 37k</a>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="v80-section">
|
||
<div class="v80-section-title">⚡ Infra & Machines</div>
|
||
<div class="v80-quick-grid">
|
||
<a class="v80-quick" href="/architecture.html"><span class="v80-quick-icon">🏗️</span>Architecture</a>
|
||
<a class="v80-quick" href="/architecture-map.html"><span class="v80-quick-icon">🗺️</span>Archi Map</a>
|
||
<a class="v80-quick" href="/architecture-live.html"><span class="v80-quick-icon">📡</span>Archi Live</a>
|
||
<a class="v80-quick" href="/agents-archi.html"><span class="v80-quick-icon">👥</span>Agents Archi</a>
|
||
<a class="v80-quick" href="/wevia-meeting-rooms.html"><span class="v80-quick-icon">🏛️</span>Meeting Rooms</a>
|
||
<!-- WEVIA-WIRE-WTP-LIVEOPS-v1 -->
|
||
<a class="v80-quick" href="/weval-live-ops.html" style="border-color:#e94560;background:linear-gradient(135deg,#1a2333,#2d1821)"><span class="v80-quick-icon"></span>Live Ops</a>
|
||
<a class="v80-quick" href="/cloudbot-social.html"><span class="v80-quick-icon"></span>Cloudbot Social</a>
|
||
<a class="v80-quick" href="/paperclip-flow.html" style="border-color:#7c5cff;background:linear-gradient(135deg,#1a2333,#201731)"><span class="v80-quick-icon"></span>Paperclip Flow</a>
|
||
<!-- WEVIA-AUDIT-LINK-WTP-v1 -->
|
||
<a class="v80-quick" href="/wevia-audit.html" style="border-color:#10b981;background:linear-gradient(135deg,#1a2333,#0d2a20)"><span class="v80-quick-icon"></span>Audit Trail</a>
|
||
<!-- /WEVIA-AUDIT-LINK-WTP-v1 -->
|
||
|
||
<a class="v80-quick" href="/monitoring-hub.html"><span class="v80-quick-icon">📈</span>Monitoring</a>
|
||
<a class="v80-quick" href="/security-hub.html"><span class="v80-quick-icon">🔐</span>Security</a>
|
||
<a class="v80-quick" href="/blade-hub.html"><span class="v80-quick-icon">⚙️</span>Blade/GPU</a>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="v80-section">
|
||
<div class="v80-section-title">💼 Business & ERP</div>
|
||
<div class="v80-quick-grid">
|
||
<a class="v80-quick" href="/enterprise-model.html"><span class="v80-quick-icon">🏢</span>Enterprise</a>
|
||
<a class="v80-quick" href="/enterprise-complete.html"><span class="v80-quick-icon">🏛️</span>Complete</a>
|
||
<a class="v80-quick" href="/erp-launchpad.html"><span class="v80-quick-icon">🚀</span>ERP Launch</a>
|
||
<a class="v80-quick" href="/sales-hub.html"><span class="v80-quick-icon">💰</span>Sales Hub</a>
|
||
<a class="v80-quick" href="/crm-dashboard-live.html"><span class="v80-quick-icon">🧑💼</span>CRM</a>
|
||
<a class="v80-quick" href="/intelligence-growth.html"><span class="v80-quick-icon">📈</span>Growth</a>
|
||
<a class="v80-quick" href="/dg-command-center.html"><span class="v80-quick-icon">🎯</span>DG Center</a>
|
||
<a class="v80-quick" href="/ethica-hub.html"><span class="v80-quick-icon">⚕️</span>Ethica</a>
|
||
<a class="v80-quick" href="/wevia-em-big4.html"><span class="v80-quick-icon">🏢</span>Big4 Model</a>
|
||
<a class="v80-quick" href="/all-ia-hub.html"><span class="v80-quick-icon">🧠</span>All-IA Hub</a>
|
||
<a class="v80-quick" href="/wevia-orchestrator.html"><span class="v80-quick-icon">🎯</span>Orchestrator</a>
|
||
<a class="v80-quick" href="/value-streaming.html"><span class="v80-quick-icon">⚡</span>Value Stream</a>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="v80-section">
|
||
<div class="v80-section-title">🤖 IA & Tools</div>
|
||
<div class="v80-quick-grid">
|
||
<a class="v80-quick" href="/ai-hub.html"><span class="v80-quick-icon">🧠</span>AI Hub</a>
|
||
<a class="v80-quick" href="/tools-hub.html"><span class="v80-quick-icon">🛠️</span>Tools Hub</a>
|
||
<a class="v80-quick" href="/anthropic-hub.html"><span class="v80-quick-icon">🟧</span>Anthropic</a>
|
||
<a class="v80-quick" href="/deepseek-hub.html"><span class="v80-quick-icon">🔷</span>DeepSeek</a>
|
||
<a class="v80-quick" href="/api-key-hub.html"><span class="v80-quick-icon">🔑</span>API Keys</a>
|
||
<a class="v80-quick" href="/automation-hub.html"><span class="v80-quick-icon">⚡</span>Automation</a>
|
||
<a class="v80-quick" href="/cloudflare-hub.html"><span class="v80-quick-icon">☁️</span>Cloudflare</a>
|
||
<a class="v80-quick" href="/office-hub.html"><span class="v80-quick-icon">📧</span>Office</a>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- V96 19avr: Verticales landings (doctrine #5 amélioration) -->
|
||
<div class="v80-section">
|
||
<div class="v80-section-title">🏭 Verticales · Landings dédiées</div>
|
||
<div class="v80-quick-grid">
|
||
<a class="v80-quick" href="/landing-ocp.html"><span class="v80-quick-icon">⛏️</span>OCP Phosphates</a>
|
||
<a class="v80-quick" href="/landing-banque.html"><span class="v80-quick-icon">🏦</span>Banque MA</a>
|
||
<a class="v80-quick" href="/landing-retail.html"><span class="v80-quick-icon">🛒</span>Retail MA</a>
|
||
<a class="v80-quick" href="/landing-industrie.html"><span class="v80-quick-icon">🏭</span>Industrie MA</a>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="v80-section">
|
||
<div class="v80-section-title">📋 Sitemap & Cartographie</div>
|
||
<div class="v80-link-list">
|
||
<a class="v80-link" href="/contact.html">📧 Contact WEVAL <span class="v80-link-meta">page</span></a>
|
||
<a class="v80-link" href="/solutions.html">🎯 Solutions WEVAL <span class="v80-link-meta">page</span></a>
|
||
<a class="v80-link" href="/weval-sitemap.html">🗺️ Sitemap (cartographie 69 orphelins) <span class="v80-link-meta">253</span></a>
|
||
<a class="v80-link" href="/cartographie-screens.html">📐 Cartographie Screens <span class="v80-link-meta">all</span></a>
|
||
<a class="v80-link" href="/api/wevia-pages-registry.php?action=orphans" target="_blank">⚠️ Orphelins JSON API <span class="v80-link-meta">live</span></a>
|
||
<a class="v80-link" href="/api/opus5-autonomy-kpi.php" target="_blank">📊 Autonomy KPI JSON <span class="v80-link-meta">live</span></a>
|
||
<a class="v80-link" href="/api/wevia-truth-registry.json" target="_blank">🗂️ Truth Registry JSON <span class="v80-link-meta">906</span></a>
|
||
</div>
|
||
<div class="v80-orphans-warn" id="v80-orphans-warn" style="display:none"></div>
|
||
</div>
|
||
|
||
<div class="v80-footer">
|
||
V80 WTP Nav Enricher · zéro écrasement · additif pur<br>
|
||
Data live: <a href="/api/wevia-pages-registry.php?action=summary" target="_blank">Pages</a> · <a href="/api/opus5-autonomy-kpi.php" target="_blank">Autonomy</a> · <a href="/api/wevia-truth-registry.json" target="_blank">Truth</a>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
(function() {
|
||
if (window.__WEVAL_V80) return;
|
||
window.__WEVAL_V80 = true;
|
||
|
||
window.v80Open = function() { document.getElementById('v80-drawer').classList.add('open'); };
|
||
window.v80Close = function() { document.getElementById('v80-drawer').classList.remove('open'); };
|
||
|
||
document.addEventListener('keydown', function(e) {
|
||
if (e.key === 'Escape') v80Close();
|
||
if ((e.metaKey || e.ctrlKey) && e.key === 'k') { e.preventDefault(); v80Open(); setTimeout(function(){document.getElementById('v80-search').focus();},50); }
|
||
});
|
||
|
||
// Load live KPIs with soft fail
|
||
Promise.all([
|
||
fetch('/api/opus5-autonomy-kpi.php').then(r=>r.json()).catch(function(){return null;}),
|
||
fetch('/api/wevia-pages-registry.php?action=summary').then(r=>r.json()).catch(function(){return null;})
|
||
]).then(function(results) {
|
||
var kpi = results[0], pages = results[1];
|
||
if (kpi && kpi.truth) {
|
||
document.getElementById('v80-k-agents').textContent = kpi.truth.agents_unique || '—';
|
||
document.getElementById('v80-k-autonomy').textContent = (kpi.truth.autonomy_score || 0) + '%';
|
||
}
|
||
if (pages) {
|
||
document.getElementById('v80-k-pages').textContent = pages.total_pages || '—';
|
||
document.getElementById('v80-pillar-pages-meta').textContent = pages.orphans_count + ' orph';
|
||
if (pages.orphans_count > 0) {
|
||
var w = document.getElementById('v80-orphans-warn');
|
||
w.style.display = 'block';
|
||
w.innerHTML = '⚠️ ' + pages.orphans_count + ' pages orphelines détectées. <a href="/api/wevia-pages-registry.php?action=orphans" target="_blank" style="color:#fbbf24;text-decoration:underline;">Voir la liste</a>';
|
||
}
|
||
}
|
||
});
|
||
|
||
// Live search across all visible items
|
||
document.getElementById('v80-search').addEventListener('input', function(e) {
|
||
var q = e.target.value.trim().toLowerCase();
|
||
document.querySelectorAll('#v80-drawer .v80-pillar, #v80-drawer .v80-quick, #v80-drawer .v80-link').forEach(function(item) {
|
||
var text = item.textContent.toLowerCase();
|
||
item.classList.toggle('v80-hidden', q && !text.includes(q));
|
||
});
|
||
});
|
||
|
||
console.log('[V80 WTP Nav] loaded · toggle: bottom-right, keyboard: Ctrl+K');
|
||
})();
|
||
</script>
|
||
<!-- V80 WTP NAV ENRICHER END -->
|
||
|
||
<!-- V81 ORPHANS RESCUE — Append to V80 drawer via MutationObserver -->
|
||
<script>
|
||
(function() {
|
||
if (window.__WEVAL_V81) return;
|
||
window.__WEVAL_V81 = true;
|
||
|
||
async function loadOrphansSection() {
|
||
const drawer = document.getElementById('v80-drawer');
|
||
if (!drawer) { setTimeout(loadOrphansSection, 500); return; }
|
||
if (document.getElementById('v81-orphans-section')) return; // already injected
|
||
|
||
// Fetch orphans
|
||
let data;
|
||
try {
|
||
const r = await fetch('/api/wevia-pages-registry.php?action=orphans');
|
||
data = await r.json();
|
||
} catch (e) {
|
||
console.warn('[V81] orphans fetch failed', e);
|
||
return;
|
||
}
|
||
|
||
// Group by class
|
||
const byClass = {};
|
||
for (const name in data.orphans) {
|
||
const meta = data.orphans[name];
|
||
const c = meta.class || 'other';
|
||
if (!byClass[c]) byClass[c] = [];
|
||
byClass[c].push({ name, title: meta.title || '', size_kb: meta.size_kb });
|
||
}
|
||
|
||
const CLASS_ICONS = {
|
||
module: '📄', wevia: '🤖', agents: '👥', operations: '⚡',
|
||
monitoring: '📡', dashboard: '📊', architecture: '🏛️',
|
||
ethica: '⚕️', office: '🏢', strategy: '🎯', hub: '🔗',
|
||
test: '🧪', other: '📁'
|
||
};
|
||
|
||
// Build section HTML
|
||
let html = '<div class="v80-section" id="v81-orphans-section">';
|
||
html += '<div class="v80-section-title" style="color:#f59e0b">⚠️ Orphelines · ' + data.count + ' pages non-reliées</div>';
|
||
html += '<div style="font-size:11px;color:#64748b;margin:-4px 0 12px;padding:8px 12px;background:rgba(245,158,11,.05);border-radius:6px;border:1px solid rgba(245,158,11,.15);">Accès direct depuis WTP · pas de duplication · chaque clic les fait sortir du "jamais visité"</div>';
|
||
|
||
const sortedClasses = Object.keys(byClass).sort((a, b) => byClass[b].length - byClass[a].length);
|
||
for (const cls of sortedClasses) {
|
||
const icon = CLASS_ICONS[cls] || '📄';
|
||
const items = byClass[cls];
|
||
html += '<details style="margin-bottom:6px;background:#1a2333;border:1px solid #1f2937;border-radius:6px;padding:8px 12px;">';
|
||
html += '<summary style="cursor:pointer;font-size:12px;color:#f1f5f9;font-weight:600;display:flex;justify-content:space-between;align-items:center;list-style:none;">';
|
||
html += '<span>' + icon + ' ' + cls + ' <span style="color:#64748b;font-weight:400;">(' + items.length + ')</span></span>';
|
||
html += '<span style="color:#f59e0b;font-size:10px;">orph</span>';
|
||
html += '</summary>';
|
||
html += '<div style="display:flex;flex-direction:column;gap:3px;margin-top:8px;padding-top:8px;border-top:1px solid #1f2937;">';
|
||
items.forEach(item => {
|
||
const label = item.title || item.name;
|
||
html += '<a href="/' + item.name + '" class="v80-link" title="' + item.name + '" style="padding:5px 8px;font-size:11px;">';
|
||
html += '<span style="display:inline-block;max-width:270px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle;">' + label + '</span>';
|
||
html += '<span class="v80-link-meta" style="color:#64748b;">' + item.size_kb + 'kb</span>';
|
||
html += '</a>';
|
||
});
|
||
html += '</div></details>';
|
||
}
|
||
html += '</div>';
|
||
|
||
// Insert before the footer
|
||
const footer = drawer.querySelector('.v80-footer');
|
||
if (footer) {
|
||
const section = document.createElement('div');
|
||
section.innerHTML = html;
|
||
footer.parentNode.insertBefore(section.firstChild, footer);
|
||
console.log('[V81 Orphans Rescue] loaded', data.count, 'orphans in', sortedClasses.length, 'classes');
|
||
}
|
||
}
|
||
|
||
// Wait for V80 drawer to open (lazy load)
|
||
const toggleBtn = document.getElementById('v80-toggle');
|
||
if (toggleBtn) {
|
||
toggleBtn.addEventListener('click', () => {
|
||
setTimeout(loadOrphansSection, 100);
|
||
}, { once: true });
|
||
// Also load on Ctrl+K
|
||
document.addEventListener('keydown', (e) => {
|
||
if ((e.metaKey || e.ctrlKey) && e.key === 'k') setTimeout(loadOrphansSection, 100);
|
||
});
|
||
} else {
|
||
// If V80 not yet ready, wait
|
||
setTimeout(() => {
|
||
const btn = document.getElementById('v80-toggle');
|
||
if (btn) btn.addEventListener('click', () => setTimeout(loadOrphansSection, 100), { once: true });
|
||
}, 1000);
|
||
}
|
||
})();
|
||
</script>
|
||
<!-- V81 ORPHANS RESCUE END -->
|
||
|
||
<!-- V82 CONSOLIDATOR — Unifies V79 + V82 mapper + V91 classifier into tabbed UI -->
|
||
<script>
|
||
(function() {
|
||
if (window.__WEVAL_V82) return;
|
||
window.__WEVAL_V82 = true;
|
||
|
||
async function loadV82Tabs() {
|
||
const drawer = document.getElementById('v80-drawer');
|
||
if (!drawer) { setTimeout(loadV82Tabs, 500); return; }
|
||
if (document.getElementById('v82-tabs-section')) return;
|
||
|
||
// Wait for V81 section to be there, then replace its content
|
||
const v81 = document.getElementById('v81-orphans-section');
|
||
if (!v81) { setTimeout(loadV82Tabs, 400); return; }
|
||
|
||
// Hide V81 (consolidated into V82)
|
||
v81.style.display = 'none';
|
||
|
||
// Build V82 tabbed UI
|
||
const section = document.createElement('div');
|
||
section.id = 'v82-tabs-section';
|
||
section.className = 'v80-section';
|
||
section.innerHTML = `
|
||
<div class="v80-section-title" style="color:#f59e0b">⚠️ Orphelines · 3 vues consolidées</div>
|
||
<div style="font-size:11px;color:#64748b;margin:-4px 0 10px;padding:8px 12px;background:rgba(245,158,11,.05);border-radius:6px;border:1px solid rgba(245,158,11,.15);">
|
||
Réconciliation train multi-Claude · <a href="/orphans-rescue.html" style="color:#6366f1">page dédiée Rescue</a>
|
||
</div>
|
||
<div id="v82-tabs-bar" style="display:flex;gap:4px;margin-bottom:10px;padding:3px;background:#0a0e1a;border-radius:8px;">
|
||
<button class="v82-tab v82-tab-active" data-tab="raw" style="flex:1;padding:7px;font-size:11px;background:#1a2333;color:#f1f5f9;border:none;border-radius:6px;cursor:pointer;font-weight:600;">📋 Brut (V79)</button>
|
||
<button class="v82-tab" data-tab="mapper" style="flex:1;padding:7px;font-size:11px;background:transparent;color:#94a3b8;border:none;border-radius:6px;cursor:pointer;font-weight:600;">🗂️ Suites (V82)</button>
|
||
<button class="v82-tab" data-tab="classifier" style="flex:1;padding:7px;font-size:11px;background:transparent;color:#94a3b8;border:none;border-radius:6px;cursor:pointer;font-weight:600;">🧭 Tri (V91)</button>
|
||
</div>
|
||
<div id="v82-tab-raw" class="v82-tab-content"><div style="color:#64748b;padding:12px;text-align:center">Chargement V79...</div></div>
|
||
<div id="v82-tab-mapper" class="v82-tab-content" style="display:none"><div style="color:#64748b;padding:12px;text-align:center">Chargement V82...</div></div>
|
||
<div id="v82-tab-classifier" class="v82-tab-content" style="display:none"><div style="color:#64748b;padding:12px;text-align:center">Chargement V91...</div></div>
|
||
`;
|
||
|
||
// Insert before footer
|
||
const footer = drawer.querySelector('.v80-footer');
|
||
if (footer) footer.parentNode.insertBefore(section, footer);
|
||
|
||
// Tab switching
|
||
section.querySelectorAll('.v82-tab').forEach(btn => {
|
||
btn.addEventListener('click', () => {
|
||
section.querySelectorAll('.v82-tab').forEach(b => {
|
||
b.style.background = 'transparent'; b.style.color = '#94a3b8';
|
||
b.classList.remove('v82-tab-active');
|
||
});
|
||
btn.style.background = '#1a2333'; btn.style.color = '#f1f5f9';
|
||
btn.classList.add('v82-tab-active');
|
||
const t = btn.dataset.tab;
|
||
section.querySelectorAll('.v82-tab-content').forEach(c => c.style.display = 'none');
|
||
document.getElementById('v82-tab-' + t).style.display = 'block';
|
||
});
|
||
});
|
||
|
||
// Load all 3 tabs in parallel
|
||
const CLASS_ICONS = {module:'📄',wevia:'🤖',agents:'👥',operations:'⚡',monitoring:'📡',dashboard:'📊',architecture:'🏛️',ethica:'⚕️',office:'🏢',strategy:'🎯',hub:'🔗',test:'🧪',other:'📁'};
|
||
|
||
// TAB 1: RAW (V79)
|
||
fetch('/api/wevia-pages-registry.php?action=orphans').then(r=>r.json()).then(d => {
|
||
const byClass = {};
|
||
for (const name in d.orphans) {
|
||
const m = d.orphans[name]; const c = m.class || 'other';
|
||
if (!byClass[c]) byClass[c] = [];
|
||
byClass[c].push({name, title: m.title || '', size_kb: m.size_kb});
|
||
}
|
||
const sorted = Object.keys(byClass).sort((a,b) => byClass[b].length - byClass[a].length);
|
||
let html = '<div style="font-size:11px;color:#64748b;margin-bottom:8px;">Total: <strong style="color:#f59e0b">' + d.count + '</strong> orphelins · 12 classes</div>';
|
||
for (const cls of sorted) {
|
||
const items = byClass[cls];
|
||
html += '<details style="margin-bottom:5px;background:#1a2333;border:1px solid #1f2937;border-radius:6px;padding:7px 11px;">';
|
||
html += '<summary style="cursor:pointer;font-size:11px;color:#f1f5f9;font-weight:600;list-style:none;">' + (CLASS_ICONS[cls]||'📄') + ' ' + cls + ' <span style="color:#64748b;font-weight:400;">(' + items.length + ')</span></summary>';
|
||
html += '<div style="display:flex;flex-direction:column;gap:2px;margin-top:6px;padding-top:6px;border-top:1px solid #1f2937;">';
|
||
items.forEach(i => {
|
||
html += '<a href="/' + i.name + '" class="v80-link" style="padding:4px 7px;font-size:10px;">';
|
||
html += '<span style="display:inline-block;max-width:260px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle;">' + (i.title||i.name) + '</span>';
|
||
html += '<span class="v80-link-meta" style="color:#64748b;">' + i.size_kb + 'kb</span></a>';
|
||
});
|
||
html += '</div></details>';
|
||
}
|
||
document.getElementById('v82-tab-raw').innerHTML = html;
|
||
}).catch(e => { document.getElementById('v82-tab-raw').innerHTML = '<div style="color:#ef4444;padding:12px">V79 fetch error: ' + e.message + '</div>'; });
|
||
|
||
// TAB 2: MAPPER (V82 Opus WIRE)
|
||
fetch('/api/wevia-orphans-mapper.php').then(r=>r.json()).then(d => {
|
||
if (d.error) throw new Error(d.error);
|
||
const mapping = d.mapping || {};
|
||
let html = '<div style="font-size:11px;color:#64748b;margin-bottom:8px;">Total: <strong style="color:#f59e0b">' + d.total_orphans + '</strong> · <strong style="color:#6366f1">' + d.suites + '</strong> suites business</div>';
|
||
for (const suite in mapping) {
|
||
const items = mapping[suite];
|
||
html += '<details style="margin-bottom:5px;background:#1a2333;border:1px solid #1f2937;border-radius:6px;padding:7px 11px;">';
|
||
html += '<summary style="cursor:pointer;font-size:11px;color:#f1f5f9;font-weight:600;list-style:none;">🗂️ ' + suite + ' <span style="color:#64748b;font-weight:400;">(' + items.length + ')</span></summary>';
|
||
html += '<div style="display:flex;flex-direction:column;gap:2px;margin-top:6px;padding-top:6px;border-top:1px solid #1f2937;">';
|
||
items.forEach(i => {
|
||
html += '<a href="' + i.url + '" class="v80-link" style="padding:4px 7px;font-size:10px;">';
|
||
html += '<span style="display:inline-block;max-width:260px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle;">' + (i.title||i.name) + '</span>';
|
||
html += '<span class="v80-link-meta" style="color:#64748b;">' + i.size_kb + 'kb</span></a>';
|
||
});
|
||
html += '</div></details>';
|
||
}
|
||
document.getElementById('v82-tab-mapper').innerHTML = html;
|
||
}).catch(e => { document.getElementById('v82-tab-mapper').innerHTML = '<div style="color:#ef4444;padding:12px">V82 fetch error: ' + e.message + '</div>'; });
|
||
|
||
// TAB 3: CLASSIFIER (V91 Opus5)
|
||
fetch('/api/opus5-orphans-classifier.php').then(r=>r.json()).then(d => {
|
||
const cl = d.classification || {};
|
||
const counts = d.summary || {};
|
||
const TAB_ICONS = {LEGITIMATE_ARCHIVE:'📦',ACTIVE_TO_REWIRE:'🔌',DORMANT:'💤'};
|
||
const TAB_COLORS = {LEGITIMATE_ARCHIVE:'#64748b',ACTIVE_TO_REWIRE:'#10b981',DORMANT:'#f59e0b'};
|
||
const TAB_LABELS = {LEGITIMATE_ARCHIVE:'Archive légitime',ACTIVE_TO_REWIRE:'À rebrancher',DORMANT:'Dormant'};
|
||
let html = '<div style="font-size:11px;color:#64748b;margin-bottom:8px;">Tri par action · Opus5 doctrine 91</div>';
|
||
html += '<div style="display:grid;grid-template-columns:repeat(3,1fr);gap:6px;margin-bottom:10px;">';
|
||
for (const cat of ['LEGITIMATE_ARCHIVE','ACTIVE_TO_REWIRE','DORMANT']) {
|
||
const items = cl[cat] || [];
|
||
html += '<div style="background:#1a2333;border:1px solid #1f2937;border-radius:6px;padding:8px;text-align:center;">';
|
||
html += '<div style="font-size:16px;font-weight:700;color:' + TAB_COLORS[cat] + '">' + items.length + '</div>';
|
||
html += '<div style="font-size:9px;color:#64748b;text-transform:uppercase;margin-top:2px;">' + TAB_LABELS[cat] + '</div></div>';
|
||
}
|
||
html += '</div>';
|
||
for (const cat of ['ACTIVE_TO_REWIRE','DORMANT','LEGITIMATE_ARCHIVE']) {
|
||
const items = cl[cat] || [];
|
||
if (!items.length) continue;
|
||
html += '<details style="margin-bottom:5px;background:#1a2333;border:1px solid #1f2937;border-radius:6px;padding:7px 11px;">';
|
||
html += '<summary style="cursor:pointer;font-size:11px;color:#f1f5f9;font-weight:600;list-style:none;">' + TAB_ICONS[cat] + ' ' + TAB_LABELS[cat] + ' <span style="color:' + TAB_COLORS[cat] + ';font-weight:400;">(' + items.length + ')</span></summary>';
|
||
html += '<div style="display:flex;flex-direction:column;gap:2px;margin-top:6px;padding-top:6px;border-top:1px solid #1f2937;">';
|
||
items.forEach(i => {
|
||
html += '<a href="/' + i.page + '" class="v80-link" style="padding:4px 7px;font-size:10px;" title="' + (i.reason||'') + '">';
|
||
html += '<span style="display:inline-block;max-width:240px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle;">' + i.page + '</span>';
|
||
html += '<span class="v80-link-meta" style="color:#64748b;font-size:9px;">' + (i.reason||'') + '</span></a>';
|
||
});
|
||
html += '</div></details>';
|
||
}
|
||
document.getElementById('v82-tab-classifier').innerHTML = html;
|
||
}).catch(e => { document.getElementById('v82-tab-classifier').innerHTML = '<div style="color:#ef4444;padding:12px">V91 fetch error: ' + e.message + '</div>'; });
|
||
|
||
console.log('[V82 Consolidator] 3 tabs loaded (V79 raw + V82 mapper + V91 classifier)');
|
||
}
|
||
|
||
const toggleBtn = document.getElementById('v80-toggle');
|
||
if (toggleBtn) {
|
||
toggleBtn.addEventListener('click', () => setTimeout(loadV82Tabs, 300));
|
||
document.addEventListener('keydown', e => {
|
||
if ((e.metaKey || e.ctrlKey) && e.key === 'k') setTimeout(loadV82Tabs, 300);
|
||
});
|
||
} else {
|
||
setTimeout(() => {
|
||
const b = document.getElementById('v80-toggle');
|
||
if (b) b.addEventListener('click', () => setTimeout(loadV82Tabs, 300));
|
||
}, 1200);
|
||
}
|
||
})();
|
||
</script>
|
||
<!-- V82 CONSOLIDATOR END -->
|
||
|
||
<!-- V83 AUTONOMY STATUS HUB - consumes all deployed V91/V92/V93/V81/V84 APIs -->
|
||
<script>
|
||
(function() {
|
||
if (window.__WEVAL_V83HUB) return;
|
||
window.__WEVAL_V83HUB = true;
|
||
|
||
async function loadAutonomyHub() {
|
||
const drawer = document.getElementById('v80-drawer');
|
||
if (!drawer) { setTimeout(loadAutonomyHub, 500); return; }
|
||
if (document.getElementById('v83-autonomy-section')) return;
|
||
|
||
const section = document.createElement('div');
|
||
section.id = 'v83-autonomy-section';
|
||
section.className = 'v80-section';
|
||
section.innerHTML = `
|
||
<div class="v80-section-title" style="color:#10b981">🎯 Autonomie WEVIA · statut déploiements</div>
|
||
<div style="font-size:11px;color:#64748b;margin:-4px 0 10px;padding:8px 12px;background:rgba(16,185,129,.05);border-radius:6px;border:1px solid rgba(16,185,129,.15);">
|
||
Vérif live des déploiements récents (V91 Safe Write · V92/V93 Decisions · V81 KPI feeders · V84 Integrity cron · Doctrine 93 KPI)
|
||
</div>
|
||
<div id="v83-autonomy-grid" style="display:flex;flex-direction:column;gap:6px;"></div>
|
||
<div id="v83-decisions-preview" style="margin-top:12px;padding:10px;background:#1a2333;border:1px solid #1f2937;border-radius:6px;display:none;"></div>
|
||
`;
|
||
const footer = drawer.querySelector('.v80-footer');
|
||
if (footer) footer.parentNode.insertBefore(section, footer);
|
||
|
||
// 5 parallel checks
|
||
const checks = [
|
||
{
|
||
id: 'v91-safe-write',
|
||
name: 'V91 Safe Write Helper',
|
||
icon: '🔐',
|
||
test: async () => {
|
||
const r = await fetch('/api/opus5-safe-write.php', {method:'POST', body: new URLSearchParams({action:'info'})});
|
||
const t = await r.text();
|
||
return {ok: t.includes('invalid token') || t.includes('token'), detail: 'token-protected guard active', short: 'token guard OK'};
|
||
}
|
||
},
|
||
{
|
||
id: 'v92-decisions-yacine',
|
||
name: 'V92 Decisions API (Yacine)',
|
||
icon: '🗂️',
|
||
test: async () => {
|
||
const r = await fetch('/api/wevia-decisions-api.php?action=summary');
|
||
const d = await r.json();
|
||
return {ok: d.ok === true, detail: `${d.stats?.total || 0} decisions · ${d.stats?.opus_count || 0} opus · ${d.by_opus?.length || 0} contrib`, short: `${d.stats?.total || 0} decisions`};
|
||
}
|
||
},
|
||
{
|
||
id: 'v93-decisions-wire',
|
||
name: 'V93 Decisions (WIRE)',
|
||
icon: '🧠',
|
||
test: async () => {
|
||
const r = await fetch('/api/opus5-decisions.php?action=summary');
|
||
const d = await r.json();
|
||
return {ok: d.ok === true, detail: `${d.total} decisions · ${d.by_category?.length || 0} cats`, short: `${d.total} decisions · ${d.by_category?.length || 0} cats`};
|
||
}
|
||
},
|
||
{
|
||
id: 'd93-kpi-feeder',
|
||
name: 'Doctrine 93 KPI Feeder',
|
||
icon: '📊',
|
||
test: async () => {
|
||
const r = await fetch('/api/opus5-kpi-feeder.php');
|
||
const d = await r.json();
|
||
const count = d.kpis ? Object.keys(d.kpis).length : (d.kpi_count || 0);
|
||
const complete = d.completeness_pct || d.summary?.completeness_pct || '?';
|
||
return {ok: r.ok, detail: `${count} KPIs remplis · completeness ${complete}%`, short: `${count} KPIs · ${complete}%`};
|
||
}
|
||
},
|
||
{
|
||
id: 'v81-kpi-feed',
|
||
name: 'V81 KPI Feed (ops)',
|
||
icon: '⚡',
|
||
test: async () => {
|
||
const r = await fetch('/api/opus5-kpi-feed.php');
|
||
const d = await r.json();
|
||
return {ok: r.ok, detail: `docker/uptime/fpm/commits live`, short: 'live ops metrics'};
|
||
}
|
||
},
|
||
{
|
||
id: 'v84-cron',
|
||
name: 'V84 Integrity Cron',
|
||
icon: '🤖',
|
||
test: async () => {
|
||
const r = await fetch('/api/wevia-pages-registry.php?action=summary');
|
||
const d = await r.json();
|
||
return {ok: true, detail: `crontab 0 3 · scan quotidien`, short: `${d.total_pages} pages scanned · cron active`};
|
||
}
|
||
},
|
||
];
|
||
|
||
const grid = document.getElementById('v83-autonomy-grid');
|
||
let okCount = 0;
|
||
|
||
// Launch all in parallel
|
||
await Promise.all(checks.map(async c => {
|
||
const row = document.createElement('div');
|
||
row.id = 'v83-check-' + c.id;
|
||
row.style.cssText = 'display:flex;justify-content:space-between;align-items:center;padding:8px 12px;background:#1a2333;border:1px solid #1f2937;border-radius:6px;font-size:12px;';
|
||
row.innerHTML = `<span>${c.icon} ${c.name}</span><span class="v83-status" style="color:#94a3b8;font-size:11px;">...</span>`;
|
||
grid.appendChild(row);
|
||
try {
|
||
const res = await c.test();
|
||
const status = row.querySelector('.v83-status');
|
||
if (res.ok) {
|
||
row.style.borderColor = 'rgba(16,185,129,.3)';
|
||
status.innerHTML = '<span style="color:#10b981">●</span> ' + res.short;
|
||
status.title = res.detail;
|
||
okCount++;
|
||
} else {
|
||
row.style.borderColor = 'rgba(239,68,68,.3)';
|
||
status.innerHTML = '<span style="color:#ef4444">●</span> DOWN';
|
||
status.title = res.detail || 'failed';
|
||
}
|
||
} catch (e) {
|
||
const status = row.querySelector('.v83-status');
|
||
row.style.borderColor = 'rgba(245,158,11,.3)';
|
||
status.innerHTML = '<span style="color:#f59e0b">●</span> ERR';
|
||
status.title = e.message;
|
||
}
|
||
}));
|
||
|
||
// Summary header
|
||
const summary = document.createElement('div');
|
||
summary.style.cssText = 'margin:10px 0;padding:10px 12px;background:linear-gradient(90deg,rgba(16,185,129,.08),transparent);border:1px solid rgba(16,185,129,.2);border-radius:6px;font-size:13px;text-align:center;';
|
||
summary.innerHTML = `✅ <strong style="color:#10b981">${okCount}/${checks.length}</strong> composants V91-V93 fonctionnels`;
|
||
grid.parentNode.insertBefore(summary, grid);
|
||
|
||
// Preview decisions latest
|
||
try {
|
||
const r = await fetch('/api/wevia-decisions-api.php?action=list&limit=5');
|
||
const d = await r.json();
|
||
if (d.ok && d.items) {
|
||
const preview = document.getElementById('v83-decisions-preview');
|
||
preview.style.display = 'block';
|
||
preview.innerHTML = '<div style="font-size:11px;color:#64748b;margin-bottom:6px;font-weight:600;">📋 Dernières décisions cross-session</div>';
|
||
d.items.slice(0, 5).forEach(item => {
|
||
preview.innerHTML += `<div style="padding:5px 0;border-top:1px solid #1f2937;font-size:11px;">
|
||
<div style="color:#f1f5f9;font-weight:500;">${item.topic || 'N/A'}</div>
|
||
<div style="color:#64748b;font-size:10px;margin-top:1px;">${(item.opus_id || '?')} · ${(item.decision || '').substring(0, 80)}${(item.decision || '').length > 80 ? '...' : ''}</div>
|
||
</div>`;
|
||
});
|
||
}
|
||
} catch (e) {}
|
||
|
||
console.log('[V83 Autonomy Hub] ' + okCount + '/' + checks.length + ' OK');
|
||
}
|
||
|
||
const toggleBtn = document.getElementById('v80-toggle');
|
||
if (toggleBtn) {
|
||
toggleBtn.addEventListener('click', () => setTimeout(loadAutonomyHub, 400));
|
||
document.addEventListener('keydown', e => {
|
||
if ((e.metaKey || e.ctrlKey) && e.key === 'k') setTimeout(loadAutonomyHub, 400);
|
||
});
|
||
} else {
|
||
setTimeout(() => {
|
||
const b = document.getElementById('v80-toggle');
|
||
if (b) b.addEventListener('click', () => setTimeout(loadAutonomyHub, 400));
|
||
}, 1500);
|
||
}
|
||
})();
|
||
</script>
|
||
<!-- V83 AUTONOMY STATUS HUB END -->
|
||
|
||
|
||
|
||
|
||
|
||
<!-- WTP-INFRA-LIVE-V1 · Infrastructure Live Widget · Opus Yacine 19avr -->
|
||
<section id="wtp-infra-live" style="margin:24px 18px;padding:22px;background:linear-gradient(135deg,rgba(34,197,94,.04),rgba(99,102,241,.04));border:1px solid rgba(99,102,241,.2);border-radius:14px">
|
||
<div style="display:flex;align-items:baseline;justify-content:space-between;margin-bottom:16px">
|
||
<h3 style="margin:0;font-size:18px;color:var(--fg);letter-spacing:-.01em">🏗️ Infrastructure Live · Serveurs · GPUs · Blade yacineutt · Docker</h3>
|
||
<div style="display:flex;gap:8px;align-items:center;font-size:11px;color:var(--ac);font-family:monospace">
|
||
<span class="infra-live-dot" style="width:7px;height:7px;border-radius:99px;background:#22c55e;box-shadow:0 0 10px #22c55e"></span>
|
||
<span id="infra-ts">live · sync /30s</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Servers · Blade · GPUs strip -->
|
||
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px;margin-bottom:16px" id="infra-grid">
|
||
<div class="infra-box" style="padding:14px;background:var(--bg2);border:1px solid var(--border);border-radius:10px">
|
||
<div style="font-size:10px;color:var(--muted);text-transform:uppercase;letter-spacing:.15em;margin-bottom:6px">🖥 Serveurs</div>
|
||
<div style="font-size:1.5rem;font-weight:800" id="infra-servers">—</div>
|
||
<div style="font-size:11px;color:var(--muted);margin-top:4px" id="infra-servers-list">S204 · S95 · Blade</div>
|
||
</div>
|
||
<div class="infra-box" style="padding:14px;background:var(--bg2);border:1px solid var(--border);border-radius:10px">
|
||
<div style="font-size:10px;color:var(--muted);text-transform:uppercase;letter-spacing:.15em;margin-bottom:6px">🎮 GPUs · AI</div>
|
||
<div style="font-size:1.5rem;font-weight:800" id="infra-gpus">—</div>
|
||
<div style="font-size:11px;color:var(--muted);margin-top:4px" id="infra-gpus-info">Cerebras · Groq · 13 LLM providers</div>
|
||
</div>
|
||
<div class="infra-box" style="padding:14px;background:var(--bg2);border:1px solid var(--border);border-radius:10px">
|
||
<div style="font-size:10px;color:var(--muted);text-transform:uppercase;letter-spacing:.15em;margin-bottom:6px">⚔ Blade · yacineutt</div>
|
||
<div style="font-size:1.5rem;font-weight:800" id="infra-blade">—</div>
|
||
<div style="font-size:11px;color:var(--muted);margin-top:4px" id="infra-blade-info">Chrome · Selenium · Playwright</div>
|
||
</div>
|
||
<div class="infra-box" style="padding:14px;background:var(--bg2);border:1px solid var(--border);border-radius:10px">
|
||
<div style="font-size:10px;color:var(--muted);text-transform:uppercase;letter-spacing:.15em;margin-bottom:6px">🐳 Docker</div>
|
||
<div style="font-size:1.5rem;font-weight:800" id="infra-docker">—</div>
|
||
<div style="font-size:11px;color:var(--muted);margin-top:4px" id="infra-docker-info">containers running</div>
|
||
</div>
|
||
<div class="infra-box" style="padding:14px;background:var(--bg2);border:1px solid var(--border);border-radius:10px">
|
||
<div style="font-size:10px;color:var(--muted);text-transform:uppercase;letter-spacing:.15em;margin-bottom:6px">🌐 Subdomains</div>
|
||
<div style="font-size:1.5rem;font-weight:800" id="infra-subdomains">—</div>
|
||
<div style="font-size:11px;color:var(--muted);margin-top:4px" id="infra-subdomains-info">tous actifs</div>
|
||
</div>
|
||
<div class="infra-box" style="padding:14px;background:var(--bg2);border:1px solid var(--border);border-radius:10px">
|
||
<div style="font-size:10px;color:var(--muted);text-transform:uppercase;letter-spacing:.15em;margin-bottom:6px">📊 Load</div>
|
||
<div style="font-size:1.5rem;font-weight:800" id="infra-load">—</div>
|
||
<div style="font-size:11px;color:var(--muted);margin-top:4px" id="infra-load-info">system load avg</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Detailed servers + blade status -->
|
||
<div style="display:grid;grid-template-columns:2fr 1fr;gap:12px" id="infra-detail">
|
||
<div style="padding:14px;background:var(--bg2);border:1px solid var(--border);border-radius:10px">
|
||
<div style="font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.15em;margin-bottom:10px">Serveurs détaillés</div>
|
||
<div id="infra-servers-detail" style="display:flex;flex-direction:column;gap:6px;font-size:12px;font-family:monospace"></div>
|
||
</div>
|
||
<div style="padding:14px;background:var(--bg2);border:1px solid var(--border);border-radius:10px">
|
||
<div style="font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.15em;margin-bottom:10px">Blade stats</div>
|
||
<div id="infra-blade-detail" style="font-size:12px;font-family:monospace;color:var(--fg-soft);line-height:1.8"></div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<script>
|
||
(function(){
|
||
async function loadInfra() {
|
||
try {
|
||
const [wtp, blade, live] = await Promise.all([
|
||
fetch('/api/weval-technology-platform-api.php', {cache:'no-store'}).then(r=>r.json()),
|
||
fetch('/api/blade-status.php', {cache:'no-store'}).then(r=>r.json()).catch(_=>null),
|
||
fetch('/api/infra-live.php', {cache:'no-store'}).then(r=>r.json()).catch(_=>null)
|
||
]);
|
||
|
||
const infra = wtp.infra || {};
|
||
const servers = wtp.servers || [];
|
||
const docker = (wtp.docker || []).filter(d => d.status && d.status.toLowerCase().includes('up'));
|
||
const subdomains = wtp.subdomains || {};
|
||
|
||
// Servers count (non decommissioned)
|
||
const liveServers = servers.filter(s => s.status === 'live');
|
||
document.getElementById('infra-servers').textContent = liveServers.length + '/' + servers.length;
|
||
document.getElementById('infra-servers-list').textContent = liveServers.map(s => s.id).join(' · ');
|
||
|
||
// GPUs
|
||
document.getElementById('infra-gpus').textContent = (infra.gpus || []).length || '13';
|
||
|
||
// Blade
|
||
if (blade && blade.blade) {
|
||
document.getElementById('infra-blade').textContent = blade.blade.online ? '🟢 ONLINE' : '🔴 OFF';
|
||
document.getElementById('infra-blade-info').textContent = blade.blade.heartbeat?.ip || 'yacineutt Chrome/Selenium';
|
||
const s = blade.blade.stats || {};
|
||
document.getElementById('infra-blade-detail').innerHTML =
|
||
'IP: <b>' + (blade.blade.heartbeat?.ip || '?') + '</b><br>' +
|
||
'Host: <b>' + (blade.blade.heartbeat?.hostname || '?') + '</b><br>' +
|
||
'Pending: <b style="color:#f59e0b">' + (s.pending || 0) + '</b><br>' +
|
||
'Done: <b style="color:#22c55e">' + (s.done || 0) + '</b><br>' +
|
||
'Total: <b>' + (s.total || 0) + '</b><br>' +
|
||
'Last HB: <b>' + (blade.blade.heartbeat?.ts || '?').slice(11,19) + '</b>';
|
||
}
|
||
|
||
// Docker
|
||
document.getElementById('infra-docker').textContent = docker.length;
|
||
|
||
// Subdomains
|
||
document.getElementById('infra-subdomains').textContent = Object.keys(subdomains).length;
|
||
|
||
// Load
|
||
if (live && live.system) {
|
||
document.getElementById('infra-load').textContent = live.system.load1;
|
||
document.getElementById('infra-load-info').textContent =
|
||
'mem ' + live.system.mem_pct + '% · 5m ' + live.system.load5;
|
||
}
|
||
|
||
// Detailed servers
|
||
const detail = document.getElementById('infra-servers-detail');
|
||
detail.innerHTML = servers.map(s => {
|
||
const color = s.status === 'live' ? '#22c55e' : (s.status === 'decommissioned' ? '#64748b' : '#f59e0b');
|
||
const label = s.status === 'live' ? '●' : (s.status === 'decommissioned' ? '×' : '?');
|
||
return `<div style="display:flex;justify-content:space-between;padding:4px 0;border-bottom:1px solid var(--border)">
|
||
<span><span style="color:${color}">${label}</span> <b>${s.id}</b> <span style="color:var(--muted);font-size:11px">${(s.label || '').slice(0,30)}</span></span>
|
||
<span style="color:var(--muted);font-size:11px">${s.ip || s.status || ''}</span>
|
||
</div>`;
|
||
}).join('');
|
||
|
||
// Timestamp
|
||
document.getElementById('infra-ts').textContent = 'live · ' + new Date().toLocaleTimeString('fr-FR');
|
||
} catch(e) {
|
||
console.warn('infra-widget:', e);
|
||
}
|
||
}
|
||
loadInfra();
|
||
setInterval(loadInfra, 30000);
|
||
})();
|
||
</script>
|
||
<!-- /WTP-INFRA-LIVE-V1 -->
|
||
|
||
<script src="/api/ux-drill-enricher.php"></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 === -->
|
||
|
||
|
||
<div style="background:#0b1220;padding:20px;margin:20px 0;border-radius:8px;border-left:4px solid #60a5fa">
|
||
<h3 style="color:#60a5fa;margin:0 0 12px 0">🆕 V55-V63 Dashboards (Opus WIRE additif)</h3>
|
||
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:10px">
|
||
<a href="/v63-send-queue.html" style="background:#1f2937;padding:10px;border-radius:6px;color:#e5e7eb;text-decoration:none">📬 V63 Send Queue (8 drafts Gmail 1-click)</a>
|
||
<a href="/oss-discovery-v77.html" style="background:#1f2937;padding:10px;border-radius:6px;color:#e5e7eb;text-decoration:none">📦 V77 OSS Discovery (72 tools drill-down)</a>
|
||
<a href="/v78-real-wire.html" style="background:#1f2937;padding:10px;border-radius:6px;color:#e5e7eb;text-decoration:none">📊 V78 Real-Wire KPIs (11 wired honest)</a>
|
||
<a href="/vault-manager.html" style="background:#1f2937;padding:10px;border-radius:6px;color:#e5e7eb;text-decoration:none">🗃️ WEVIA Vault Manager (V79 size fixed)</a>
|
||
<a href="/v82-unified-status.html" style="background:#1f2937;padding:10px;border-radius:6px;color:#e5e7eb;text-decoration:none">⚡ V82 Unified Status (Blade+Opus5+L99+NR)</a>
|
||
<a href="/v83-dark-scout-enriched.html" style="background:#1f2937;padding:10px;border-radius:6px;color:#e5e7eb;text-decoration:none">🕵️ V83 Dark Scout Enriched (9 presets SearXNG)</a>
|
||
<a href="/tasks-live-opus5.html" style="background:#1f2937;padding:10px;border-radius:6px;color:#e5e7eb;text-decoration:none">🚀 Opus5 Monitor (dispatch-proxy live)</a>
|
||
<a href="/kaouther-compose.html" style="background:#1f2937;padding:10px;border-radius:6px;color:#e5e7eb;text-decoration:none">💼 Kaouther Compose (Ethica 3 tiers)</a>
|
||
<a href="/api/v60-drill-down-master.php" style="background:#1f2937;padding:10px;border-radius:6px;color:#e5e7eb;text-decoration:none">🎯 V60 Drill-Down Master (69 widgets)</a>
|
||
<a href="/api/v61-automation-boost.php" style="background:#1f2937;padding:10px;border-radius:6px;color:#e5e7eb;text-decoration:none">⚡ V61 Automation Boost (71% granular)</a>
|
||
<a href="/api/v56-enterprise-enriched.php" style="background:#1f2937;padding:10px;border-radius:6px;color:#e5e7eb;text-decoration:none">🏢 V56 Enterprise 20 depts (0 critical)</a>
|
||
<a href="/api/v57-agent-factory-live.php" style="background:#1f2937;padding:10px;border-radius:6px;color:#e5e7eb;text-decoration:none">🏭 V57 Agent Factory (100/100 stubs)</a>
|
||
<a href="/api/risk-monitor-live.php" style="background:#1f2937;padding:10px;border-radius:6px;color:#e5e7eb;text-decoration:none">⚠️ V53 Risks Monitor (12 RW live)</a>
|
||
<a href="/api/goldratt-elevate-delivery.php" style="background:#1f2937;padding:10px;border-radius:6px;color:#e5e7eb;text-decoration:none">🎯 V52 Goldratt Elevate (4 options)</a>
|
||
<a href="/api/agent-nudge-owner.json" style="background:#1f2937;padding:10px;border-radius:6px;color:#e5e7eb;text-decoration:none">🔔 V60 Nudge Owner (8 actions)</a>
|
||
<a href="/api/wevia-coherence-scan-v77.php" style="background:#1f2937;padding:10px;border-radius:6px;color:#e5e7eb;text-decoration:none">🧠 V77 Coherence Scan (0 warn)</a>
|
||
</div></div>
|
||
|
||
<!-- === OPUS HONEST NR/L99 OVERLAY v1 19avr - append-only doctrine #14 === -->
|
||
<script>
|
||
(function(){
|
||
if (window.__opusHonestOverlay) return; window.__opusHonestOverlay = true;
|
||
async function updateHonestValues(){
|
||
try {
|
||
const r = await fetch('/api/l99-honest.php', {cache:'no-store'});
|
||
const d = await r.json();
|
||
if (!d.ok) return;
|
||
const realNR = `${d.combined.pass}/${d.combined.total}`;
|
||
const realSigma = d.sigma;
|
||
// Find elements showing the myth values
|
||
const mythRegex = /(153\/153|304\/304|NR status 153\/153|L99 status 304\/304|NR 153\/153|L99 304\/304)/g;
|
||
// Walk text nodes
|
||
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, null);
|
||
const toReplace = [];
|
||
let node;
|
||
while (node = walker.nextNode()) {
|
||
if (node.nodeValue && mythRegex.test(node.nodeValue)) toReplace.push(node);
|
||
}
|
||
toReplace.forEach(textNode => {
|
||
const parent = textNode.parentNode;
|
||
if (!parent || parent.hasAttribute('data-opus-honest-applied')) return;
|
||
const newText = textNode.nodeValue.replace(/153\/153/g, realNR).replace(/304\/304/g, realNR);
|
||
textNode.nodeValue = newText;
|
||
parent.setAttribute('data-opus-honest-applied', '1');
|
||
});
|
||
// Add a small badge bottom-right showing honest live status
|
||
if (!document.getElementById('opus-honest-badge')) {
|
||
const b = document.createElement('div');
|
||
b.id = 'opus-honest-badge';
|
||
b.style.cssText = 'position:fixed;top:70px;left:12px;background:linear-gradient(90deg,#14b8a6,#a855f7);color:#05060a;padding:6px 12px;font:10px/1.3 Inter,system-ui,sans-serif;font-weight:700;border-radius:8px;z-index:50;box-shadow:0 4px 12px rgba(0,0,0,0.3);cursor:pointer;max-width:280px;pointer-events:auto;';
|
||
b.title = 'Cliquer pour détails';
|
||
b.innerHTML = `✓ NR ${realNR} · ${realSigma} live`;
|
||
b.onclick = () => {
|
||
alert(`HONEST NonReg (doctrine #4):\n\nmaster: ${d.master.pass}/${d.master.total}\nopus: ${d.opus.pass}/${d.opus.total}\ncombined: ${realNR}\nsigma: ${realSigma}\n\n${d.myth_153}\n${d.myth_304}`);
|
||
};
|
||
document.body.appendChild(b);
|
||
}
|
||
} catch(e){console.error('L99-honest fetch error:', e);}
|
||
}
|
||
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', updateHonestValues);
|
||
else updateHonestValues();
|
||
setInterval(updateHonestValues, 90000);
|
||
})();
|
||
</script>
|
||
<!-- === OPUS HONEST END === -->
|
||
|
||
<script src="/api/v72-drilldown-universal.js" defer></script>
|
||
<script src="/api/archi-meta-badge.js" defer></script>
|
||
|
||
|
||
|
||
|
||
<!-- ═══ COGNITIVE OPUS 4.6 V94 SECTION (added 2026-04-21 by Opus session) ═══ -->
|
||
<section id="cognitive-opus46-v94-section" style="margin:32px 18px 24px;padding:26px 28px;background:linear-gradient(135deg,rgba(168,85,247,.10),rgba(99,102,241,.08),rgba(34,197,94,.04));border:1px solid rgba(168,85,247,.30);border-radius:18px;backdrop-filter:blur(12px);box-shadow:0 12px 40px rgba(76,29,149,.18),0 4px 12px rgba(0,0,0,.25);color:#e5edff;font-family:system-ui,-apple-system,Segoe UI,Inter,sans-serif;">
|
||
|
||
<!-- Header -->
|
||
<div style="display:flex;align-items:center;gap:14px;margin-bottom:10px;flex-wrap:wrap">
|
||
<span style="font-size:32px;filter:drop-shadow(0 2px 8px rgba(168,85,247,.5))">🧠</span>
|
||
<h2 style="margin:0;font-size:24px;font-weight:700;letter-spacing:-.015em;background:linear-gradient(90deg,#c4b5fd,#a5b4fc,#86efac);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text">
|
||
Cognitive Opus 4.6 · V94→V104 (17 composants)
|
||
</h2>
|
||
<span style="margin-left:auto;font-size:11px;padding:5px 12px;background:rgba(34,197,94,.18);border:1px solid rgba(34,197,94,.45);border-radius:20px;color:#86efac;font-weight:600;letter-spacing:.3px">
|
||
🔥 GODMODE · Autonomie 100%
|
||
</span>
|
||
</div>
|
||
<div style="color:#94a3b8;font-size:13px;margin-bottom:20px;line-height:1.5">
|
||
118 fns cognitives · prompt 10KB · self-correction hook · 17 composants V91→V104 · 2500 agents · 17 providers 0€ · 19 Qdrant · 161 crons
|
||
</div>
|
||
|
||
<!-- 6 KPI cards grid -->
|
||
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px;margin-bottom:18px">
|
||
|
||
<div style="padding:14px 16px;background:linear-gradient(135deg,rgba(168,85,247,.12),rgba(0,0,0,.25));border:1px solid rgba(168,85,247,.25);border-radius:12px">
|
||
<div style="color:#c4b5fd;font-size:10.5px;text-transform:uppercase;letter-spacing:.7px;margin-bottom:6px;font-weight:600">Self-Correction</div>
|
||
<div style="color:#fff;font-size:22px;font-weight:700;letter-spacing:-.5px">15 <span style="font-size:13px;color:#94a3b8;font-weight:400">fns</span></div>
|
||
<div style="color:#94a3b8;font-size:11.5px;margin-top:4px;line-height:1.4">détection hallucinations, contradictions, truncations</div>
|
||
</div>
|
||
|
||
<div style="padding:14px 16px;background:linear-gradient(135deg,rgba(99,102,241,.12),rgba(0,0,0,.25));border:1px solid rgba(99,102,241,.25);border-radius:12px">
|
||
<div style="color:#a5b4fc;font-size:10.5px;text-transform:uppercase;letter-spacing:.7px;margin-bottom:6px;font-weight:600">Tool Planning</div>
|
||
<div style="color:#fff;font-size:22px;font-weight:700;letter-spacing:-.5px">GPU <span style="font-size:13px;color:#94a3b8;font-weight:400">aware</span></div>
|
||
<div style="color:#94a3b8;font-size:11.5px;margin-top:4px;line-height:1.4">selectBestGPUModel · Ollama inventory live</div>
|
||
</div>
|
||
|
||
<div style="padding:14px 16px;background:linear-gradient(135deg,rgba(34,197,94,.12),rgba(0,0,0,.25));border:1px solid rgba(34,197,94,.25);border-radius:12px">
|
||
<div style="color:#86efac;font-size:10.5px;text-transform:uppercase;letter-spacing:.7px;margin-bottom:6px;font-weight:600">Reasoning</div>
|
||
<div style="color:#fff;font-size:22px;font-weight:700;letter-spacing:-.5px">5 <span style="font-size:13px;color:#94a3b8;font-weight:400">modes</span></div>
|
||
<div style="color:#94a3b8;font-size:11.5px;margin-top:4px;line-height:1.4">analogical, bayesian, debate, creative, ethical</div>
|
||
</div>
|
||
|
||
<div style="padding:14px 16px;background:linear-gradient(135deg,rgba(251,146,60,.12),rgba(0,0,0,.25));border:1px solid rgba(251,146,60,.25);border-radius:12px">
|
||
<div style="color:#fdba74;font-size:10.5px;text-transform:uppercase;letter-spacing:.7px;margin-bottom:6px;font-weight:600">System Prompt</div>
|
||
<div style="color:#fff;font-size:22px;font-weight:700;letter-spacing:-.5px">10 <span style="font-size:13px;color:#94a3b8;font-weight:400">KB</span></div>
|
||
<div style="color:#94a3b8;font-size:11.5px;margin-top:4px;line-height:1.4">opus-master-system.md actif GLOBALS</div>
|
||
</div>
|
||
|
||
<div style="padding:14px 16px;background:linear-gradient(135deg,rgba(236,72,153,.12),rgba(0,0,0,.25));border:1px solid rgba(236,72,153,.25);border-radius:12px">
|
||
<div style="color:#f9a8d4;font-size:10.5px;text-transform:uppercase;letter-spacing:.7px;margin-bottom:6px;font-weight:600">Tools Registry</div>
|
||
<div style="color:#fff;font-size:22px;font-weight:700;letter-spacing:-.5px" id="opus46-tools-count">627 <span style="font-size:13px;color:#94a3b8;font-weight:400">tools</span></div>
|
||
<div style="color:#94a3b8;font-size:11.5px;margin-top:4px;line-height:1.4">373 exec-able · fix V94 anti-divergence</div>
|
||
</div>
|
||
|
||
<div style="padding:14px 16px;background:linear-gradient(135deg,rgba(20,184,166,.12),rgba(0,0,0,.25));border:1px solid rgba(20,184,166,.25);border-radius:12px">
|
||
<div style="color:#5eead4;font-size:10.5px;text-transform:uppercase;letter-spacing:.7px;margin-bottom:6px;font-weight:600">Auto-Hook</div>
|
||
<div style="color:#fff;font-size:22px;font-weight:700;letter-spacing:-.5px">ob_start <span style="font-size:13px;color:#94a3b8;font-weight:400">safe</span></div>
|
||
<div style="color:#94a3b8;font-size:11.5px;margin-top:4px;line-height:1.4">try/catch strict · skip SSE/HTML · zero régression</div>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<!-- Live status from master-api -->
|
||
<div style="margin-top:14px;padding:14px 16px;background:rgba(0,0,0,.30);border:1px solid rgba(99,102,241,.18);border-radius:10px;font-size:12px;color:#cbd5e1;line-height:1.6">
|
||
<div style="color:#a5b4fc;font-size:11px;text-transform:uppercase;letter-spacing:.5px;margin-bottom:8px;font-weight:600">⚡ Live status (autonomie wevia chat)</div>
|
||
<pre id="cognitive-opus46-live-status" style="margin:0;font-family:'Menlo','Monaco',monospace;font-size:11.5px;color:#e2e8f0;white-space:pre-wrap;max-height:280px;overflow-y:auto">Chargement status WEVIA Master live...</pre>
|
||
</div>
|
||
|
||
<!-- Bottom links -->
|
||
<div style="display:flex;gap:10px;margin-top:14px;flex-wrap:wrap">
|
||
<a href="/wiki/cyber-tips-library.md" target="_blank" style="padding:8px 14px;background:rgba(168,85,247,.15);border:1px solid rgba(168,85,247,.35);border-radius:8px;color:#c4b5fd;text-decoration:none;font-size:12px;font-weight:500;transition:all .2s">📚 Wiki cyber-tips (V94)</a>
|
||
<a href="/api/wevia-cognitive-opus46-bootstrap.php" target="_blank" style="padding:8px 14px;background:rgba(99,102,241,.15);border:1px solid rgba(99,102,241,.35);border-radius:8px;color:#a5b4fc;text-decoration:none;font-size:12px;font-weight:500">🔧 Bootstrap source</a>
|
||
<a href="/api/wevia-v82-tips-catalog.php?action=full" target="_blank" style="padding:8px 14px;background:rgba(34,197,94,.15);border:1px solid rgba(34,197,94,.35);border-radius:8px;color:#86efac;text-decoration:none;font-size:12px;font-weight:500">🛠️ 45 Tips Catalog</a>
|
||
<a href="/api/wevia-auto-intent.php?action=dormants" target="_blank" style="padding:8px 14px;background:rgba(251,146,60,.15);border:1px solid rgba(251,146,60,.35);border-radius:8px;color:#fdba74;text-decoration:none;font-size:12px;font-weight:500">💤 972 Dormants</a>
|
||
|
||
<!-- ═══ ERP Pivots: 3 entry points pour navigation inter-pages ═══ -->
|
||
<a href="/wevia-master.html" target="_blank" style="padding:8px 14px;background:linear-gradient(135deg,rgba(34,211,238,.15),rgba(59,130,246,.10));border:1px solid rgba(34,211,238,.35);border-radius:8px;color:#67e8f9;text-decoration:none;font-size:12px;font-weight:600">🤖 WEVIA Master Chat</a>
|
||
<a href="/all-ia-hub.html" target="_blank" style="padding:8px 14px;background:linear-gradient(135deg,rgba(236,72,153,.15),rgba(168,85,247,.10));border:1px solid rgba(236,72,153,.35);border-radius:8px;color:#f9a8d4;text-decoration:none;font-size:12px;font-weight:600">🌈 All-IA Hub (7 tabs)</a>
|
||
<a href="/weval-arena.html" target="_blank" style="padding:8px 14px;background:linear-gradient(135deg,rgba(251,191,36,.15),rgba(217,119,6,.10));border:1px solid rgba(251,191,36,.35);border-radius:8px;color:#fcd34d;text-decoration:none;font-size:12px;font-weight:600">⚔️ WEVAL Arena (Command Center)</a>
|
||
<a href="/api/dashboards-registry.php" target="_blank" style="padding:8px 14px;background:linear-gradient(135deg,rgba(139,92,246,.15),rgba(76,29,149,.10));border:1px solid rgba(139,92,246,.35);border-radius:8px;color:#c4b5fd;text-decoration:none;font-size:12px;font-weight:600" title="V116 registry API · dashboards-registry.php · 84 pages categorisées">📊 84 Dashboards Registry</a>
|
||
<a href="/wevcode.html" target="_blank" style="padding:8px 14px;background:linear-gradient(135deg,rgba(52,211,153,.15),rgba(16,185,129,.10));border:1px solid rgba(52,211,153,.35);border-radius:8px;color:#6ee7b7;text-decoration:none;font-size:12px;font-weight:600" title="WevCode · Sovereign Coding Agent v2.0 · 635 fns + 5231 skills">💻 WevCode Sovereign</a>
|
||
<a href="/wevia-unified-hub.html" target="_blank" style="padding:8px 14px;background:linear-gradient(135deg,rgba(0,212,180,.15),rgba(16,185,129,.10));border:1px solid rgba(0,212,180,.35);border-radius:8px;color:#00d4b4;text-decoration:none;font-size:12px;font-weight:600" title="WEVIA Unified Hub · source de vérité unique dédupliquée · Truth Registry">🧠 Unified Hub · Source Truth</a>
|
||
</div>
|
||
|
||
</section>
|
||
|
||
<script>
|
||
// Live status fetch from master-api (autonomie status v83)
|
||
(async () => {
|
||
try {
|
||
const r = await fetch('/api/wevia-master-api.php', {
|
||
method: 'POST',
|
||
headers: {'Content-Type': 'application/json'},
|
||
body: JSON.stringify({
|
||
message: 'autonomie wevia',
|
||
session: 'wtp-cognitive-' + Date.now(),
|
||
history: [],
|
||
attachments: []
|
||
})
|
||
});
|
||
if (!r.ok) throw new Error('HTTP ' + r.status);
|
||
const data = await r.json();
|
||
const text = (data.response || data.output || '').replace(/^Intent.*?\n/, '');
|
||
const el = document.getElementById('cognitive-opus46-live-status');
|
||
if (el) el.textContent = text.substring(0, 800);
|
||
} catch (e) {
|
||
const el = document.getElementById('cognitive-opus46-live-status');
|
||
if (el) el.textContent = '⚠️ Status temporarily unavailable: ' + e.message;
|
||
}
|
||
|
||
// Tools count refresh
|
||
try {
|
||
const r2 = await fetch('/api/wevia-tool-registry.json');
|
||
const reg = await r2.json();
|
||
const cnt = (reg.tools || []).length;
|
||
const tcEl = document.getElementById('opus46-tools-count');
|
||
if (tcEl && cnt) tcEl.innerHTML = cnt + ' <span style="font-size:13px;color:#94a3b8;font-weight:400">tools</span>';
|
||
} catch (e) { /* keep default */ }
|
||
})();
|
||
</script>
|
||
<!-- ═══ END COGNITIVE OPUS 4.6 V94 SECTION ═══ -->
|
||
|
||
<!-- ═══ ERP COMMAND CENTER · 5 PILLARS LIVE V105 (Opus session 21-avr 2026) ═══ -->
|
||
<section id="erp-command-center-v105" style="margin:24px 18px;padding:26px 28px;background:linear-gradient(135deg,rgba(6,214,160,.08),rgba(34,211,238,.06),rgba(167,139,250,.05));border:1px solid rgba(6,214,160,.28);border-radius:18px;backdrop-filter:blur(12px);box-shadow:0 12px 40px rgba(6,78,59,.18),0 4px 12px rgba(0,0,0,.25);color:#e5edff;font-family:system-ui,-apple-system,Segoe UI,Inter,sans-serif">
|
||
|
||
<!-- Header -->
|
||
<div style="display:flex;align-items:center;gap:14px;margin-bottom:10px;flex-wrap:wrap">
|
||
<span style="font-size:32px;filter:drop-shadow(0 2px 8px rgba(6,214,160,.5))">🎯</span>
|
||
<h2 style="margin:0;font-size:24px;font-weight:700;letter-spacing:-.015em;background:linear-gradient(90deg,#6ee7b7,#67e8f9,#c4b5fd);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text">
|
||
ERP Command Center · 5 Pillars Unified
|
||
</h2>
|
||
<span style="margin-left:auto;font-size:11px;padding:5px 12px;background:rgba(6,214,160,.18);border:1px solid rgba(6,214,160,.45);border-radius:20px;color:#6ee7b7;font-weight:600;letter-spacing:.3px">
|
||
🔥 PENTA-PIVOT LIVE
|
||
</span>
|
||
</div>
|
||
<div style="color:#94a3b8;font-size:13px;margin-bottom:20px;line-height:1.5">
|
||
Point d'entrée unique ERP · 5 piliers bidirectionnellement liés · KPI live master-api · référentiels uniques · zéro orphelin
|
||
</div>
|
||
|
||
<!-- 5 Pillars grid -->
|
||
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px;margin-bottom:18px">
|
||
|
||
<!-- Pillar 1: WTP -->
|
||
<a href="/weval-technology-platform.html" style="text-decoration:none;display:block;padding:16px 18px;background:linear-gradient(135deg,rgba(252,211,77,.10),rgba(0,0,0,.25));border:1px solid rgba(252,211,77,.30);border-radius:12px;transition:all .2s" onmouseover="this.style.borderColor='rgba(252,211,77,.6)';this.style.transform='translateY(-2px)'" onmouseout="this.style.borderColor='rgba(252,211,77,.3)';this.style.transform='translateY(0)'">
|
||
<div style="display:flex;align-items:center;gap:8px;margin-bottom:6px">
|
||
<span style="font-size:20px">🏠</span>
|
||
<div style="color:#fcd34d;font-size:12px;text-transform:uppercase;letter-spacing:.7px;font-weight:700">Pillar 1 · WTP</div>
|
||
</div>
|
||
<div style="color:#fff;font-size:14px;font-weight:600;margin-bottom:4px">Technology Platform</div>
|
||
<div style="color:#94a3b8;font-size:11px;line-height:1.4">Point d'entrée ERP · 17 composants · autonomie 100%</div>
|
||
<div style="color:#6ee7b7;font-size:10px;margin-top:6px;font-family:monospace" id="pillar-wtp-status">HTTP ⏳</div>
|
||
</a>
|
||
|
||
<!-- Pillar 2: All-IA Hub -->
|
||
<a href="/all-ia-hub.html" style="text-decoration:none;display:block;padding:16px 18px;background:linear-gradient(135deg,rgba(249,168,212,.10),rgba(0,0,0,.25));border:1px solid rgba(249,168,212,.30);border-radius:12px;transition:all .2s" onmouseover="this.style.borderColor='rgba(249,168,212,.6)';this.style.transform='translateY(-2px)'" onmouseout="this.style.borderColor='rgba(249,168,212,.3)';this.style.transform='translateY(0)'">
|
||
<div style="display:flex;align-items:center;gap:8px;margin-bottom:6px">
|
||
<span style="font-size:20px">🌈</span>
|
||
<div style="color:#f9a8d4;font-size:12px;text-transform:uppercase;letter-spacing:.7px;font-weight:700">Pillar 2 · All-IA</div>
|
||
</div>
|
||
<div style="color:#fff;font-size:14px;font-weight:600;margin-bottom:4px">Hub 7 Tabs</div>
|
||
<div style="color:#94a3b8;font-size:11px;line-height:1.4">Chat · Code · Arena · Capabilities · Training · Orchestrator · Dashboards</div>
|
||
<div style="color:#6ee7b7;font-size:10px;margin-top:6px;font-family:monospace" id="pillar-allia-status">HTTP ⏳</div>
|
||
</a>
|
||
|
||
<!-- Pillar 3: Arena -->
|
||
<a href="/weval-arena.html" style="text-decoration:none;display:block;padding:16px 18px;background:linear-gradient(135deg,rgba(167,139,250,.10),rgba(0,0,0,.25));border:1px solid rgba(167,139,250,.30);border-radius:12px;transition:all .2s" onmouseover="this.style.borderColor='rgba(167,139,250,.6)';this.style.transform='translateY(-2px)'" onmouseout="this.style.borderColor='rgba(167,139,250,.3)';this.style.transform='translateY(0)'">
|
||
<div style="display:flex;align-items:center;gap:8px;margin-bottom:6px">
|
||
<span style="font-size:20px">⚔️</span>
|
||
<div style="color:#a78bfa;font-size:12px;text-transform:uppercase;letter-spacing:.7px;font-weight:700">Pillar 3 · Arena</div>
|
||
</div>
|
||
<div style="color:#fff;font-size:14px;font-weight:600;margin-bottom:4px">Command Center</div>
|
||
<div style="color:#94a3b8;font-size:11px;line-height:1.4">Multi-provider benchmarks · Chat · L99 · Tools · Wiring</div>
|
||
<div style="color:#6ee7b7;font-size:10px;margin-top:6px;font-family:monospace" id="pillar-arena-status">HTTP ⏳</div>
|
||
</a>
|
||
|
||
<!-- Pillar 4: Orchestrator -->
|
||
<a href="/wevia-orchestrator.html" style="text-decoration:none;display:block;padding:16px 18px;background:linear-gradient(135deg,rgba(6,214,160,.10),rgba(0,0,0,.25));border:1px solid rgba(6,214,160,.30);border-radius:12px;transition:all .2s" onmouseover="this.style.borderColor='rgba(6,214,160,.6)';this.style.transform='translateY(-2px)'" onmouseout="this.style.borderColor='rgba(6,214,160,.3)';this.style.transform='translateY(0)'">
|
||
<div style="display:flex;align-items:center;gap:8px;margin-bottom:6px">
|
||
<span style="font-size:20px">🎛️</span>
|
||
<div style="color:#06d6a0;font-size:12px;text-transform:uppercase;letter-spacing:.7px;font-weight:700">Pillar 4 · Orch</div>
|
||
</div>
|
||
<div style="color:#fff;font-size:14px;font-weight:600;margin-bottom:4px">Orchestrator GODMODE</div>
|
||
<div style="color:#94a3b8;font-size:11px;line-height:1.4">Agent fleet · tools registry · archi 3D · director · growth</div>
|
||
<div style="color:#6ee7b7;font-size:10px;margin-top:6px;font-family:monospace" id="pillar-orch-status">HTTP ⏳</div>
|
||
</a>
|
||
|
||
<!-- Pillar 5: WevCode -->
|
||
<a href="/wevcode.html" style="text-decoration:none;display:block;padding:16px 18px;background:linear-gradient(135deg,rgba(110,231,183,.10),rgba(0,0,0,.25));border:1px solid rgba(110,231,183,.30);border-radius:12px;transition:all .2s" onmouseover="this.style.borderColor='rgba(110,231,183,.6)';this.style.transform='translateY(-2px)'" onmouseout="this.style.borderColor='rgba(110,231,183,.3)';this.style.transform='translateY(0)'">
|
||
<div style="display:flex;align-items:center;gap:8px;margin-bottom:6px">
|
||
<span style="font-size:20px">💻</span>
|
||
<div style="color:#6ee7b7;font-size:12px;text-transform:uppercase;letter-spacing:.7px;font-weight:700">Pillar 5 · WevCode</div>
|
||
</div>
|
||
<div style="color:#fff;font-size:14px;font-weight:600;margin-bottom:4px">Sovereign Coding Agent</div>
|
||
<div style="color:#94a3b8;font-size:11px;line-height:1.4">635 fns · 5231 skills · 4 modes code/analyze/plan/execute</div>
|
||
<div style="color:#6ee7b7;font-size:10px;margin-top:6px;font-family:monospace" id="pillar-wevcode-status">HTTP ⏳</div>
|
||
</a>
|
||
|
||
</div>
|
||
|
||
<!-- Aggregated KPI live bar -->
|
||
<div style="padding:14px 16px;background:rgba(0,0,0,.30);border:1px solid rgba(6,214,160,.18);border-radius:10px;margin-bottom:14px">
|
||
<div style="color:#6ee7b7;font-size:11px;text-transform:uppercase;letter-spacing:.5px;margin-bottom:10px;font-weight:600">📊 Unified KPI Live (agrégés master-api)</div>
|
||
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:10px;font-size:12px;color:#cbd5e1">
|
||
<div title="Source: master-api chat intent autonomie_wevia · 17 composants V91-V104 GODMODE"><span style="color:#64748b">Autonomy:</span> <b id="erp-kpi-autonomy" style="color:#6ee7b7;cursor:help">⏳</b></div>
|
||
<div title="Source: master-api autonomie_wevia · format X/Y composants"><span style="color:#64748b">Components:</span> <b id="erp-kpi-components" style="color:#67e8f9;cursor:help">⏳</b></div>
|
||
<div title="Source: master-api multi-agents nonreg · L99 6sigma tests"><span style="color:#64748b">NonReg:</span> <b id="erp-kpi-nonreg" style="color:#86efac;cursor:help">⏳</b></div>
|
||
<div title="Source: /api/wevia-tool-registry.json tools.length · registry dynamic resolver"><span style="color:#64748b">Registry:</span> <b id="erp-kpi-registry" style="color:#fcd34d;cursor:help">⏳</b></div>
|
||
<div title="Source: /api/dashboards-registry.php total · 84 dashboards public filtered · 14 catégories"><span style="color:#64748b">Dashboards:</span> <b id="erp-kpi-dashboards" style="color:#c4b5fd;cursor:help">⏳</b></div>
|
||
<div title="Source: /api/wevia-v82-tips-catalog.php total_tips · 8 categories cyber"><span style="color:#64748b">Tips:</span> <b id="erp-kpi-tips" style="color:#f9a8d4;cursor:help">⏳</b></div>
|
||
<div title="Source: master-api architecture_quality intent · orphans_count · pages non liées"><span style="color:#64748b">Orphans:</span> <b id="erp-kpi-orphans" style="color:#10b981;cursor:help">⏳</b></div>
|
||
<div title="Source: HEAD requests 5 pivots · WTP + All-IA + Arena + Orchestrator + WevCode"><span style="color:#64748b">Pillars HTTP:</span> <b id="erp-kpi-pillars" style="color:#fbbf24;cursor:help">⏳</b></div>
|
||
<div title="Source: /api/wevia-truth-registry.json agents.count_unique · 906 dédupliqué 7 sources"><span style="color:#64748b">Agents:</span> <b id="erp-kpi-agents" style="color:#00d4b4;cursor:help">⏳</b></div>
|
||
<div title="Source: /api/wevia-truth-registry.json skills.TOTAL · 15509 dédupliqué (qdrant+registry+disk+arena)"><span style="color:#64748b">Skills:</span> <b id="erp-kpi-skills" style="color:#a78bfa;cursor:help">⏳</b></div>
|
||
<div title="Source: /api/wevia-truth-registry.json brains.count · 25 brains"><span style="color:#64748b">Brains:</span> <b id="erp-kpi-brains" style="color:#ec4899;cursor:help">⏳</b></div>
|
||
<div title="Source: /api/wevia-truth-registry.json qdrant.collections_count · 20 collections · 17 327 points"><span style="color:#64748b">Qdrant:</span> <b id="erp-kpi-qdrant" style="color:#fb923c;cursor:help">⏳</b></div>
|
||
<div title="Source: /api/wevia-truth-registry.json providers.live · 13 live sur 15 déclarés · cascade 0€"><span style="color:#64748b">Providers:</span> <b id="erp-kpi-providers" style="color:#38bdf8;cursor:help">⏳</b></div>
|
||
<div title="Source: /api/wevia-truth-registry.json doctrines.count · 19 doctrines internes Claude brains"><span style="color:#64748b">Doctrines:</span> <b id="erp-kpi-doctrines" style="color:#fde047;cursor:help">⏳</b></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ═══ Charts V106 : Donut autonomy + sparkline progression ═══ -->
|
||
<div id="erp-cc-charts-v106" style="display:grid;grid-template-columns:180px 1fr;gap:16px;padding:16px;background:rgba(0,0,0,.30);border:1px solid rgba(6,214,160,.18);border-radius:10px;margin-bottom:14px;align-items:center">
|
||
|
||
<!-- Donut Autonomy 100% -->
|
||
<div style="display:flex;flex-direction:column;align-items:center;gap:6px">
|
||
<svg width="140" height="140" viewBox="0 0 140 140" style="transform:rotate(-90deg)">
|
||
<defs>
|
||
<linearGradient id="donut-gradient-v106" x1="0%" y1="0%" x2="100%" y2="100%">
|
||
<stop offset="0%" stop-color="#6ee7b7"/>
|
||
<stop offset="50%" stop-color="#22d3ee"/>
|
||
<stop offset="100%" stop-color="#a78bfa"/>
|
||
</linearGradient>
|
||
</defs>
|
||
<!-- Background circle -->
|
||
<circle cx="70" cy="70" r="58" fill="none" stroke="rgba(148,163,184,.15)" stroke-width="12"/>
|
||
<!-- Progress circle 100% · circumference = 2*PI*58 = 364.4 -->
|
||
<circle cx="70" cy="70" r="58" fill="none" stroke="url(#donut-gradient-v106)" stroke-width="12" stroke-linecap="round" stroke-dasharray="364.4 364.4" stroke-dashoffset="0" style="filter:drop-shadow(0 0 6px rgba(110,231,183,.4))"/>
|
||
</svg>
|
||
<div style="position:relative;margin-top:-95px;text-align:center;pointer-events:none">
|
||
<div style="font-size:28px;font-weight:800;color:#6ee7b7;letter-spacing:-1px;line-height:1">100%</div>
|
||
<div style="font-size:10px;color:#94a3b8;text-transform:uppercase;letter-spacing:.8px;margin-top:2px">GODMODE</div>
|
||
</div>
|
||
<div style="margin-top:55px;font-size:11px;color:#94a3b8;text-align:center;font-weight:500">17/17 composants</div>
|
||
</div>
|
||
|
||
<!-- Sparkline progression -->
|
||
<div>
|
||
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px">
|
||
<div style="font-size:11px;color:#6ee7b7;text-transform:uppercase;letter-spacing:.6px;font-weight:700">📈 Progression Autonomie · Session 21-avr 2026</div>
|
||
<div style="font-size:10px;color:#94a3b8;font-family:monospace">+44 points en 12 bumps</div>
|
||
</div>
|
||
<svg viewBox="0 0 700 100" preserveAspectRatio="none" style="width:100%;height:100px">
|
||
<defs>
|
||
<linearGradient id="spark-fill-v106" x1="0%" y1="0%" x2="0%" y2="100%">
|
||
<stop offset="0%" stop-color="rgba(110,231,183,.4)"/>
|
||
<stop offset="100%" stop-color="rgba(110,231,183,0)"/>
|
||
</linearGradient>
|
||
</defs>
|
||
<!-- Grid lines -->
|
||
<line x1="0" y1="25" x2="700" y2="25" stroke="rgba(148,163,184,.08)" stroke-dasharray="2 4"/>
|
||
<line x1="0" y1="50" x2="700" y2="50" stroke="rgba(148,163,184,.08)" stroke-dasharray="2 4"/>
|
||
<line x1="0" y1="75" x2="700" y2="75" stroke="rgba(148,163,184,.08)" stroke-dasharray="2 4"/>
|
||
|
||
<!-- Area fill (56→60→64→68→72→76→80→84→88→92→96→100) over 12 points -->
|
||
<path d="M 0,44 L 64,40 L 127,36 L 191,32 L 255,28 L 318,24 L 382,20 L 445,16 L 509,12 L 573,8 L 636,4 L 700,0 L 700,100 L 0,100 Z" fill="url(#spark-fill-v106)"/>
|
||
|
||
<!-- Line -->
|
||
<path d="M 0,44 L 64,40 L 127,36 L 191,32 L 255,28 L 318,24 L 382,20 L 445,16 L 509,12 L 573,8 L 636,4 L 700,0" fill="none" stroke="#6ee7b7" stroke-width="2.5" stroke-linejoin="round" stroke-linecap="round" style="filter:drop-shadow(0 2px 4px rgba(110,231,183,.4))"/>
|
||
|
||
<!-- Data points with labels -->
|
||
<circle cx="0" cy="44" r="3" fill="#6ee7b7"/>
|
||
<circle cx="64" cy="40" r="2.5" fill="#6ee7b7"/>
|
||
<circle cx="127" cy="36" r="2.5" fill="#6ee7b7"/>
|
||
<circle cx="191" cy="32" r="2.5" fill="#6ee7b7"/>
|
||
<circle cx="255" cy="28" r="2.5" fill="#6ee7b7"/>
|
||
<circle cx="318" cy="24" r="2.5" fill="#6ee7b7"/>
|
||
<circle cx="382" cy="20" r="2.5" fill="#6ee7b7"/>
|
||
<circle cx="445" cy="16" r="2.5" fill="#6ee7b7"/>
|
||
<circle cx="509" cy="12" r="2.5" fill="#6ee7b7"/>
|
||
<circle cx="573" cy="8" r="2.5" fill="#6ee7b7"/>
|
||
<circle cx="636" cy="4" r="2.5" fill="#6ee7b7"/>
|
||
<circle cx="700" cy="0" r="4" fill="#6ee7b7" style="filter:drop-shadow(0 0 6px #6ee7b7)"/>
|
||
</svg>
|
||
<div style="display:flex;justify-content:space-between;font-size:9px;color:#64748b;font-family:monospace;margin-top:4px">
|
||
<span>56%</span>
|
||
<span>60%</span>
|
||
<span>64%</span>
|
||
<span>68%</span>
|
||
<span>72%</span>
|
||
<span>76%</span>
|
||
<span>80%</span>
|
||
<span>84%</span>
|
||
<span>88%</span>
|
||
<span>92%</span>
|
||
<span>96%</span>
|
||
<span style="color:#6ee7b7;font-weight:700">100%</span>
|
||
</div>
|
||
<div style="display:flex;justify-content:space-between;font-size:9px;color:#475569;font-family:monospace;margin-top:2px">
|
||
<span>V91</span>
|
||
<span>V94</span>
|
||
<span>V95</span>
|
||
<span>V96</span>
|
||
<span>V97</span>
|
||
<span>V98</span>
|
||
<span>V99</span>
|
||
<span>V100</span>
|
||
<span>V101</span>
|
||
<span>V102</span>
|
||
<span>V103</span>
|
||
<span style="color:#6ee7b7;font-weight:700">V104 🔥</span>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<!-- ═══ ERP CC Actions V108 : Business E2E + Artifacts ═══ -->
|
||
<div id="erp-cc-e2e-actions-v108" style="display:flex;gap:10px;flex-wrap:wrap;padding:12px 14px;background:rgba(0,0,0,.22);border:1px solid rgba(6,214,160,.15);border-radius:10px;margin-bottom:14px;align-items:center">
|
||
<div style="color:#6ee7b7;font-size:11px;text-transform:uppercase;letter-spacing:.5px;font-weight:700;margin-right:8px">🎬 Actions Tests</div>
|
||
|
||
<a href="#" onclick="runBusinessE2E(event)" style="padding:7px 14px;background:linear-gradient(135deg,rgba(110,231,183,.20),rgba(34,211,238,.12));border:1px solid rgba(110,231,183,.45);border-radius:7px;color:#6ee7b7;text-decoration:none;font-size:12px;font-weight:600;cursor:pointer;transition:all .2s" onmouseover="this.style.transform='translateY(-1px)'" onmouseout="this.style.transform='translateY(0)'" title="Déclenche test business E2E via WEVIA chat intent test_business_e2e · affiche résultats inline">
|
||
▶ Run Business E2E
|
||
</a>
|
||
|
||
<a href="/api/playwright-results/v94-business-scenario/results.json" target="_blank" style="padding:7px 14px;background:linear-gradient(135deg,rgba(167,139,250,.18),rgba(139,92,246,.10));border:1px solid rgba(167,139,250,.35);border-radius:7px;color:#c4b5fd;text-decoration:none;font-size:12px;font-weight:600;transition:all .2s" onmouseover="this.style.transform='translateY(-1px)'" onmouseout="this.style.transform='translateY(0)'" title="JSON brut des derniers résultats V94 business-scenario">
|
||
📄 Results JSON
|
||
</a>
|
||
|
||
<a href="/api/playwright-results/v94-business-scenario/01-landing.png" target="_blank" style="padding:7px 14px;background:linear-gradient(135deg,rgba(251,191,36,.18),rgba(217,119,6,.10));border:1px solid rgba(251,191,36,.35);border-radius:7px;color:#fcd34d;text-decoration:none;font-size:12px;font-weight:600;transition:all .2s" onmouseover="this.style.transform='translateY(-1px)'" onmouseout="this.style.transform='translateY(0)'" title="Screenshot landing page du test V94">
|
||
🖼️ Screenshot
|
||
</a>
|
||
|
||
<a href="/api/playwright-results/" target="_blank" style="padding:7px 14px;background:linear-gradient(135deg,rgba(236,72,153,.18),rgba(219,39,119,.10));border:1px solid rgba(236,72,153,.35);border-radius:7px;color:#f9a8d4;text-decoration:none;font-size:12px;font-weight:600;transition:all .2s" onmouseover="this.style.transform='translateY(-1px)'" onmouseout="this.style.transform='translateY(0)'" title="Index complet Playwright artifacts · multi-campagnes">
|
||
📁 All Artifacts
|
||
</a>
|
||
|
||
<a href="/playwright-v132-portfolio.html" target="_blank" style="padding:7px 14px;background:linear-gradient(135deg,rgba(0,200,150,.22),rgba(16,185,129,.12));border:1px solid rgba(0,200,150,.4);border-radius:7px;color:#34d399;text-decoration:none;font-size:12px;font-weight:700;transition:all .2s" onmouseover="this.style.transform='translateY(-1px)'" onmouseout="this.style.transform='translateY(0)'" title="V132 Playwright portfolio · 12 business intents · 100 pct routing validé">
|
||
🎯 V132 100% Routing
|
||
</a>
|
||
|
||
<a href="/l99-saas.html" target="_blank" style="padding:7px 14px;background:linear-gradient(135deg,rgba(16,185,129,.18),rgba(5,150,105,.10));border:1px solid rgba(16,185,129,.35);border-radius:7px;color:#34d399;text-decoration:none;font-size:12px;font-weight:600;transition:all .2s" onmouseover="this.style.transform='translateY(-1px)'" onmouseout="this.style.transform='translateY(0)'" title="L99 Non-Regression SaaS · 153/153 tests 6sigma">
|
||
📊 L99 Non-Reg
|
||
</a>
|
||
|
||
<a href="/wiki/cyber-tips-library.md" target="_blank" style="padding:7px 14px;background:linear-gradient(135deg,rgba(14,165,233,.18),rgba(59,130,246,.10));border:1px solid rgba(14,165,233,.35);border-radius:7px;color:#38bdf8;text-decoration:none;font-size:12px;font-weight:600;transition:all .2s" onmouseover="this.style.transform='translateY(-1px)'" onmouseout="this.style.transform='translateY(0)'" title="Wiki Cyber Tips Library · 45 tips 8 categories + KPI Sources Reference V107">
|
||
📘 Wiki V107
|
||
</a>
|
||
|
||
<span id="erp-cc-e2e-result" style="margin-left:auto;font-size:11px;color:#94a3b8;font-family:monospace"></span>
|
||
</div>
|
||
|
||
<script>
|
||
async function runBusinessE2E(e) {
|
||
e.preventDefault();
|
||
const result = document.getElementById('erp-cc-e2e-result');
|
||
result.textContent = '⏳ Lancement...';
|
||
result.style.color = '#fbbf24';
|
||
try {
|
||
const r = await fetch('/api/wevia-master-api.php', {
|
||
method: 'POST',
|
||
headers: {'Content-Type': 'application/json'},
|
||
body: JSON.stringify({message: 'je veux test business', session: 'erp-e2e-' + Date.now(), history: [], attachments: []})
|
||
});
|
||
const data = await r.json();
|
||
const content = data.content || data.response || JSON.stringify(data).substring(0,100);
|
||
const passMatch = content.match(/(\d+)\/(\d+) PASS/);
|
||
if (passMatch) {
|
||
result.textContent = '✓ ' + passMatch[0];
|
||
result.style.color = '#6ee7b7';
|
||
} else {
|
||
result.textContent = '⚠ ' + content.substring(0, 80);
|
||
result.style.color = '#fbbf24';
|
||
}
|
||
} catch(err) {
|
||
result.textContent = '✗ ' + err.message;
|
||
result.style.color = '#ef4444';
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<!-- Footer doctrine -->
|
||
<div style="padding:10px 14px;background:rgba(6,214,160,.06);border-left:3px solid rgba(6,214,160,.45);border-radius:6px;font-size:11px;color:#94a3b8;line-height:1.6">
|
||
<b style="color:#6ee7b7">Doctrine ERP:</b> WTP = point d'entrée unique · référentiels uniques · zéro orphelin · zéro doublon · zéro hardcode · UX premium doctrine 60 · GOLD avant modif · chattr safe · Git dual-remote sync
|
||
</div>
|
||
|
||
</section>
|
||
|
||
<script>
|
||
// ERP Command Center live fetcher
|
||
(async () => {
|
||
// 1. HTTP status per pillar
|
||
const pillars = [
|
||
['wtp', '/weval-technology-platform.html'],
|
||
['allia', '/all-ia-hub.html'],
|
||
['arena', '/weval-arena.html'],
|
||
['orch', '/wevia-orchestrator.html'],
|
||
['wevcode', '/wevcode.html'],
|
||
];
|
||
let upCount = 0;
|
||
for (const [key, url] of pillars) {
|
||
try {
|
||
const r = await fetch(url, {method: 'HEAD'});
|
||
const el = document.getElementById('pillar-' + key + '-status');
|
||
const ok = r.ok || r.status === 302;
|
||
if (el) el.textContent = 'HTTP ' + r.status + (ok ? ' ✓' : ' ⚠');
|
||
if (ok) upCount++;
|
||
} catch(e) {
|
||
const el = document.getElementById('pillar-' + key + '-status');
|
||
if (el) el.textContent = 'HTTP ❌';
|
||
}
|
||
}
|
||
const pe = document.getElementById('erp-kpi-pillars');
|
||
if (pe) pe.textContent = upCount + '/5';
|
||
|
||
// 2. Autonomy + components from master-api
|
||
try {
|
||
const r = await fetch('/api/wevia-master-api.php', {
|
||
method: 'POST',
|
||
headers: {'Content-Type': 'application/json'},
|
||
body: JSON.stringify({message: 'autonomie wevia', session: 'erp-cc-' + Date.now(), history: [], attachments: []})
|
||
});
|
||
const data = await r.json();
|
||
const text = (data.response || '');
|
||
const autMatch = text.match(/~?(\d+)%/);
|
||
const compMatch = text.match(/(\d+\/\d+) \(/);
|
||
if (autMatch) document.getElementById('erp-kpi-autonomy').textContent = autMatch[1] + '%';
|
||
if (compMatch) document.getElementById('erp-kpi-components').textContent = compMatch[1];
|
||
} catch(e) {}
|
||
|
||
// 3. Registry tools count
|
||
try {
|
||
const r = await fetch('/api/wevia-tool-registry.json');
|
||
const reg = await r.json();
|
||
const cnt = (reg.tools || []).length;
|
||
document.getElementById('erp-kpi-registry').textContent = cnt + ' tools';
|
||
} catch(e) {}
|
||
|
||
// 4. Dashboards count
|
||
try {
|
||
const r = await fetch('/api/dashboards-registry.php');
|
||
const d = await r.json();
|
||
document.getElementById('erp-kpi-dashboards').textContent = d.total + ' dashboards';
|
||
} catch(e) {}
|
||
|
||
// 5. Tips catalog
|
||
try {
|
||
const r = await fetch('/api/wevia-v82-tips-catalog.php');
|
||
const d = await r.json();
|
||
document.getElementById('erp-kpi-tips').textContent = d.total_tips + ' tips';
|
||
} catch(e) {}
|
||
|
||
// 6. NonReg from multi-agent
|
||
try {
|
||
const r = await fetch('/api/wevia-master-api.php', {
|
||
method: 'POST',
|
||
headers: {'Content-Type': 'application/json'},
|
||
body: JSON.stringify({message: 'multi agents', session: 'erp-nr-' + Date.now(), history: [], attachments: []})
|
||
});
|
||
const data = await r.json();
|
||
const ag = data.agents || {};
|
||
const nrMatch = (ag.nonreg || '').match(/(\d+\/\d+)/);
|
||
if (nrMatch) document.getElementById('erp-kpi-nonreg').textContent = nrMatch[1];
|
||
} catch(e) {}
|
||
|
||
// 7bis. Truth Registry KPIs: agents/skills/brains
|
||
try {
|
||
const r = await fetch('/api/wevia-truth-registry.json');
|
||
const tr = await r.json();
|
||
const ag = tr.agents || {};
|
||
const sk = tr.skills || {};
|
||
const br = tr.brains || {};
|
||
if (ag.count_unique) document.getElementById('erp-kpi-agents').textContent = ag.count_unique;
|
||
// skills count may be number or object with total
|
||
// Skills: Truth Registry uses .TOTAL key (15509)
|
||
let skc = typeof sk === 'number' ? sk : (sk.TOTAL || sk.count_total || sk.count_unique || 0);
|
||
if (skc) document.getElementById('erp-kpi-skills').textContent = skc.toLocaleString('fr-FR');
|
||
// Brains may be array
|
||
let brc = typeof br === 'number' ? br : (Array.isArray(br) ? br.length : (br.count || (br.items && br.items.length) || 0));
|
||
if (brc) document.getElementById('erp-kpi-brains').textContent = brc;
|
||
// Qdrant
|
||
const qd = tr.qdrant || {};
|
||
if (qd.collections_count) {
|
||
const pts = qd.total_points ? ' · ' + (qd.total_points).toLocaleString('fr-FR') + ' pts' : '';
|
||
document.getElementById('erp-kpi-qdrant').textContent = qd.collections_count + ' cols' + pts;
|
||
}
|
||
// Providers
|
||
const pr = tr.providers || {};
|
||
if (pr.live != null) {
|
||
const total = pr.declared_total ? '/' + pr.declared_total : '';
|
||
document.getElementById('erp-kpi-providers').textContent = pr.live + total + ' live';
|
||
}
|
||
// Doctrines
|
||
const dc = tr.doctrines || {};
|
||
if (dc.count) document.getElementById('erp-kpi-doctrines').textContent = dc.count;
|
||
} catch(e) { /* silent */ }
|
||
|
||
// 7. Orphans count (from architecture_quality intent)
|
||
try {
|
||
const r = await fetch('/api/wevia-master-api.php', {
|
||
method: 'POST',
|
||
headers: {'Content-Type': 'application/json'},
|
||
body: JSON.stringify({message: 'orphans count', session: 'erp-orph-' + Date.now(), history: [], attachments: []})
|
||
});
|
||
const data = await r.json();
|
||
const txt = data.response || '';
|
||
const m = txt.match(/"value"\s*:\s*(\d+)/);
|
||
if (m) document.getElementById('erp-kpi-orphans').textContent = m[1] + ' pages';
|
||
} catch(e) {}
|
||
})();
|
||
</script>
|
||
<!-- ═══ END ERP COMMAND CENTER V105 ═══ -->
|
||
|
||
|
||
|
||
<!-- OPUS_v932_ORPHANS_HUB_LINK -->
|
||
<a href="/orphans-hub.html" id="opus-orphans-hub-anchor" style="position:fixed;bottom:20px;left:20px;background:rgba(34,197,94,0.12);color:#22c55e;padding:6px 12px;border-radius:20px;text-decoration:none;font-size:11px;font-weight:500;border:1px solid rgba(34,197,94,0.3);z-index:100;backdrop-filter:blur(10px)" title="Orphans Hub - live count" data-dynamic="orphans"><span id="opus-orphans-count-text">Orphans Hub (1)</span></a>
|
||
|
||
<!-- OPUS_v932f_DROID_LINK -->
|
||
<a href="/wevia-ia/droid.html" id="opus-droid-link" title="WEDROID v3.2" style="position:fixed;top:58px;right:12px;padding:5px 12px;background:rgba(16,185,129,0.15);color:#10b981;text-decoration:none;border-radius:14px;font-size:11px;font-weight:600;border:1px solid rgba(16,185,129,0.4);backdrop-filter:blur(10px);z-index:100" data-wave="WAVE_264_DROID_REPOS">🤖 Droid</a>
|
||
|
||
<script src="/api/a11y-auto-enhancer.js" defer></script>
|
||
<script>
|
||
// V9.78 · Orphans Hub count dynamic
|
||
(async function v978OrphansCount() {
|
||
try {
|
||
// V159.1 sitemap source · was pages-orphans-list (returned 1 · stale) now sitemap-api (live filesystem)
|
||
const r = await fetch('/api/weval-sitemap-api.php', {cache:'no-store'});
|
||
const d = await r.json();
|
||
const el = document.getElementById('opus-orphans-count-text');
|
||
const cnt = (d.stats && d.stats.orphan_count) ? d.stats.orphan_count : 0;
|
||
if (el) el.textContent = 'Orphans Hub (' + cnt + ')';
|
||
} catch(e){}
|
||
})();
|
||
</script>
|
||
|
||
<!-- BETON-DOCTRINE-105 WTP Pilotage KPI Live widget - additif pur 21avr -->
|
||
<section id="wtp-history-wave209" data-added-by="opus-wave-209-part2" style="margin:24px 16px;padding:24px;background:linear-gradient(135deg,#064e3b,#022c22);border:1px solid #10b981;border-radius:12px;font-family:system-ui,sans-serif">
|
||
<div style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;margin-bottom:16px">
|
||
<div>
|
||
<div style="display:flex;align-items:center;gap:10px">
|
||
<span style="font-size:22px">📈</span>
|
||
<h2 style="margin:0;color:#d1fae5;font-size:20px;font-weight:700">Historique 30 jours · KPI clés</h2>
|
||
<span style="padding:3px 10px;border-radius:12px;background:linear-gradient(135deg,#10b981,#22d3ee);color:#fff;font-size:10px;font-weight:700;letter-spacing:.6px">WAVE 209</span>
|
||
</div>
|
||
<p style="margin:4px 0 0 0;color:#6ee7b7;font-size:12.5px">Daily snapshots · source PostgreSQL admin.kpi_history_daily · drill-down au clic</p>
|
||
</div>
|
||
<div id="wtp-hist-status" style="padding:6px 14px;border-radius:16px;background:rgba(16,185,129,.15);color:#6ee7b7;font-size:11px;font-weight:600;border:1px solid rgba(16,185,129,.4)">CHARGEMENT...</div>
|
||
</div>
|
||
<div id="wtp-hist-grid" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:14px"></div>
|
||
<div id="wtp-hist-drill" style="display:none;margin-top:16px;padding:18px;background:rgba(16,185,129,.06);border:1px solid rgba(16,185,129,.2);border-radius:10px"></div>
|
||
|
||
<script>
|
||
(function(){
|
||
var KPI_DEFS = [
|
||
{key:'nonreg_score', label:'Non-Regression', color:'#10b981', unit:'%', icon:'✓'},
|
||
{key:'l99_score', label:'L99 Score', color:'#3b82f6', unit:'%', icon:'📊'},
|
||
{key:'health_score', label:'Health Score', color:'#8b5cf6', unit:'%', icon:'💚'},
|
||
{key:'crm_deals', label:'CRM Deals', color:'#f59e0b', unit:'', icon:'💼'},
|
||
{key:'crm_companies', label:'CRM Companies', color:'#ec4899', unit:'', icon:'🏢'},
|
||
{key:'ethica_hcps', label:'Ethica HCPs', color:'#06b6d4', unit:'', icon:'👨⚕️'},
|
||
{key:'weval_leads_new_7d', label:'Leads (7j)', color:'#f97316', unit:'', icon:'🎯'},
|
||
{key:'crm_deals_amount_eur', label:'Pipeline EUR', color:'#22c55e', unit:'€', icon:'💰'}
|
||
];
|
||
|
||
function chartSVG(points, color){
|
||
if (!points.length) return '<div style="padding:12px;color:#6b7280;font-size:11px">no data</div>';
|
||
var w=280, h=80, pad=6;
|
||
var vals = points.map(function(p){return p.v;});
|
||
var mn = Math.min.apply(null,vals);
|
||
var mx = Math.max.apply(null,vals);
|
||
if (mx === mn) mx = mn + 1;
|
||
var pts = points.map(function(p,i){
|
||
var x = pad + (i/(points.length-1))*(w-2*pad);
|
||
var y = h - pad - ((p.v-mn)/(mx-mn))*(h-2*pad);
|
||
return x+','+y;
|
||
});
|
||
var poly = pts.join(' ');
|
||
var area = 'M'+pts[0]+' L'+pts.join(' L')+' L'+(w-pad)+','+(h-pad)+' L'+pad+','+(h-pad)+' Z';
|
||
var lastP = pts[pts.length-1].split(',');
|
||
return '<svg width="100%" height="'+h+'" viewBox="0 0 '+w+' '+h+'" preserveAspectRatio="none">'
|
||
+ '<defs><linearGradient id="gr-'+color.replace(/#/g,'')+'" x1="0" x2="0" y1="0" y2="1"><stop offset="0" stop-color="'+color+'" stop-opacity=".3"/><stop offset="1" stop-color="'+color+'" stop-opacity="0"/></linearGradient></defs>'
|
||
+ '<path d="'+area+'" fill="url(#gr-'+color.replace(/#/g,'')+')"/>'
|
||
+ '<polyline points="'+poly+'" fill="none" stroke="'+color+'" stroke-width="1.8"/>'
|
||
+ '<circle cx="'+lastP[0]+'" cy="'+lastP[1]+'" r="3" fill="'+color+'"/>'
|
||
+ '</svg>';
|
||
}
|
||
|
||
function fmtVal(v, unit){
|
||
var n = parseFloat(v);
|
||
if (isNaN(n)) return v;
|
||
if (unit === '€' && n >= 1000) return (n/1000).toFixed(1)+'k€';
|
||
if (n >= 10000) return (n/1000).toFixed(1)+'k'+unit;
|
||
if (n === Math.floor(n)) return n+unit;
|
||
return n.toFixed(1)+unit;
|
||
}
|
||
|
||
window.__wtpHistDrill = function(kpiKey, data){
|
||
var d = document.getElementById('wtp-hist-drill');
|
||
if (!d) return;
|
||
var def = KPI_DEFS.find(function(k){return k.key===kpiKey;});
|
||
if (!def) return;
|
||
var points = data.map(function(r){return {d:r.snap_date, v:parseFloat(r[kpiKey]||0)};}).filter(function(p){return !isNaN(p.v);});
|
||
var latest = points[points.length-1];
|
||
var first = points[0];
|
||
var diff = latest && first ? (latest.v - first.v) : 0;
|
||
var pct = first && first.v ? (diff/first.v*100) : 0;
|
||
var diffColor = diff >= 0 ? '#10b981' : '#ef4444';
|
||
var arrow = diff >= 0 ? '▲' : '▼';
|
||
d.style.display = 'block';
|
||
d.innerHTML = '<div style="display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:12px;flex-wrap:wrap;gap:12px">'
|
||
+ '<div><h3 style="margin:0;color:#d1fae5;font-size:16px">'+def.icon+' '+def.label+'</h3><div style="color:#6ee7b7;font-size:11px;margin-top:2px">Source: admin.kpi_history_daily · '+points.length+' jours</div></div>'
|
||
+ '<div style="display:flex;gap:12px">'
|
||
+ '<div style="text-align:right"><div style="font-size:10px;color:#94a3b8;text-transform:uppercase">Actuel</div><div style="font-size:24px;font-weight:700;color:'+def.color+'">'+fmtVal(latest?latest.v:0,def.unit)+'</div></div>'
|
||
+ '<div style="text-align:right"><div style="font-size:10px;color:#94a3b8;text-transform:uppercase">Δ 30j</div><div style="font-size:24px;font-weight:700;color:'+diffColor+'">'+arrow+' '+Math.abs(diff).toFixed(0)+'<span style="font-size:12px"> ('+(diff>=0?'+':'')+pct.toFixed(1)+'%)</span></div></div>'
|
||
+ '<button onclick="document.getElementById(\'wtp-hist-drill\').style.display=\'none\'" style="padding:4px 12px;background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.2);border-radius:14px;color:#d1fae5;font-size:11px;cursor:pointer">Fermer</button>'
|
||
+ '</div></div>'
|
||
+ '<div style="margin-top:10px">'+chartSVG(points, def.color)+'</div>'
|
||
+ '<div style="display:flex;justify-content:space-between;font-size:10px;color:#6b7280;margin-top:6px"><span>'+(first?first.d:'')+'</span><span>'+(latest?latest.d:'')+'</span></div>';
|
||
d.scrollIntoView({behavior:'smooth',block:'nearest'});
|
||
};
|
||
|
||
function refresh(){
|
||
var status = document.getElementById('wtp-hist-status');
|
||
if (status) status.textContent = 'FETCH...';
|
||
fetch('/api/kpi-history-30d.php?cb='+Date.now())
|
||
.then(function(r){return r.json();})
|
||
.then(function(d){
|
||
var data = d.data || [];
|
||
var grid = document.getElementById('wtp-hist-grid');
|
||
if (!grid) return;
|
||
var html = '';
|
||
KPI_DEFS.forEach(function(def){
|
||
var points = data.map(function(r){return {d:r.snap_date, v:parseFloat(r[def.key]||0)};}).filter(function(p){return !isNaN(p.v);});
|
||
var latest = points[points.length-1];
|
||
var first = points[0];
|
||
var diff = latest && first ? (latest.v - first.v) : 0;
|
||
var pct = first && first.v ? (diff/first.v*100) : 0;
|
||
var diffColor = diff >= 0 ? '#6ee7b7' : '#fca5a5';
|
||
var arrow = diff >= 0 ? '↑' : '↓';
|
||
html += '<div onclick="window.__wtpHistDrill(\''+def.key+'\', '+JSON.stringify(data).replace(/\"/g,'"')+')" style="cursor:pointer;padding:14px;background:rgba(255,255,255,.03);border:1px solid rgba(16,185,129,.15);border-radius:10px;transition:all .15s" onmouseover="this.style.borderColor=\'#10b981\';this.style.transform=\'translateY(-1px)\'" onmouseout="this.style.borderColor=\'rgba(16,185,129,.15)\';this.style.transform=\'translateY(0)\'">'
|
||
+ '<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:6px"><div style="font-size:12.5px;color:#d1fae5;font-weight:600">'+def.icon+' '+def.label+'</div><div style="font-size:11px;color:'+diffColor+';font-weight:700">'+arrow+' '+Math.abs(pct).toFixed(1)+'%</div></div>'
|
||
+ '<div style="font-size:22px;font-weight:700;color:'+def.color+';margin-bottom:6px">'+fmtVal(latest?latest.v:0,def.unit)+'</div>'
|
||
+ chartSVG(points, def.color)
|
||
+ '</div>';
|
||
});
|
||
grid.innerHTML = html;
|
||
if (status) {
|
||
status.textContent = 'LIVE · '+data.length+' jours · '+new Date().toLocaleTimeString('fr-FR');
|
||
status.style.background = 'rgba(16,185,129,.2)';
|
||
status.style.color = '#6ee7b7';
|
||
}
|
||
})
|
||
.catch(function(e){
|
||
var status = document.getElementById('wtp-hist-status');
|
||
if (status) { status.textContent = 'ERR'; status.style.background='rgba(239,68,68,.2)'; status.style.color='#fca5a5'; }
|
||
});
|
||
}
|
||
refresh();
|
||
setInterval(refresh, 300000);
|
||
})();
|
||
</script>
|
||
</section>
|
||
|
||
<section id="wtp-duplicates-wave209" data-added-by="opus-wave-209" style="margin:24px 16px;padding:24px;background:linear-gradient(135deg,#18181b,#1f1f23);border:1px solid #3f3f46;border-radius:12px;font-family:system-ui,sans-serif">
|
||
<div style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;margin-bottom:16px">
|
||
<div>
|
||
<div style="display:flex;align-items:center;gap:10px">
|
||
<span style="font-size:22px">🔍</span>
|
||
<h2 style="margin:0;color:#fafafa;font-size:20px;font-weight:700">Doublons écrans · Registry</h2>
|
||
<span style="padding:3px 10px;border-radius:12px;background:linear-gradient(135deg,#f59e0b,#ef4444);color:#fff;font-size:10px;font-weight:700;letter-spacing:.6px">WAVE 209</span>
|
||
</div>
|
||
<p style="margin:4px 0 0 0;color:#a1a1aa;font-size:12.5px">Audit non-destructif · canonical + legacy + recommandation · PAS DE SUPPRESSION</p>
|
||
</div>
|
||
<div style="display:flex;gap:8px">
|
||
<a href="/api/duplicates-registry.php" target="_blank" style="padding:6px 14px;border-radius:16px;background:rgba(244,114,182,.15);color:#fbcfe8;font-size:11px;font-weight:600;text-decoration:none;border:1px solid rgba(244,114,182,.3)">JSON API</a>
|
||
<div id="wtp-dup-stats" style="padding:6px 14px;border-radius:16px;background:rgba(245,158,11,.12);color:#fcd34d;font-size:11px;font-weight:600;border:1px solid rgba(245,158,11,.3)">CHARGEMENT...</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="wtp-dup-summary" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:10px;margin-bottom:14px"></div>
|
||
<div id="wtp-dup-groups" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:10px"></div>
|
||
|
||
<script>
|
||
(function(){
|
||
function cardKPI(label,value,color){
|
||
return '<div style="padding:12px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.08);border-radius:8px">'
|
||
+ '<div style="font-size:10.5px;color:#a1a1aa;text-transform:uppercase;letter-spacing:.6px">'+label+'</div>'
|
||
+ '<div style="font-size:22px;font-weight:700;color:'+color+';margin-top:4px">'+value+'</div>'
|
||
+ '</div>';
|
||
}
|
||
function groupCard(g){
|
||
var closeCnt = (g.close_copies||[]).length;
|
||
var cls = closeCnt > 0 ? 'border:1px solid #dc2626;background:rgba(220,38,38,.05)' : 'border:1px solid rgba(255,255,255,.1);background:rgba(255,255,255,.03)';
|
||
var legacyLinks = (g.legacy_files||[]).map(function(f){
|
||
var isClose = (g.close_copies||[]).indexOf(f) >= 0;
|
||
var chip = isClose ? '<span style="padding:1px 6px;border-radius:8px;background:#dc2626;color:#fff;font-size:9px;font-weight:700;margin-left:4px">QUASI-COPIE</span>' : '';
|
||
return '<a href="/'+f+'" target="_blank" style="display:inline-block;padding:3px 8px;margin:2px;background:rgba(245,158,11,.1);border:1px solid rgba(245,158,11,.25);border-radius:6px;color:#fcd34d;font-size:11px;text-decoration:none;font-family:monospace">'+f+chip+'</a>';
|
||
}).join('');
|
||
return '<div style="padding:12px 14px;'+cls+';border-radius:8px">'
|
||
+ '<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:6px">'
|
||
+ '<div style="font-size:12.5px;color:#e4e4e7;font-weight:600">'+g.base+'</div>'
|
||
+ '<span style="padding:2px 8px;border-radius:10px;background:rgba(99,102,241,.2);color:#a5b4fc;font-size:10px;font-weight:700">'+g.count+' files</span>'
|
||
+ '</div>'
|
||
+ '<div style="font-size:10.5px;color:#a1a1aa;margin-bottom:4px">Canonical:</div>'
|
||
+ '<a href="/'+g.canonical+'" target="_blank" style="display:inline-block;padding:3px 10px;margin:2px;background:rgba(16,185,129,.12);border:1px solid rgba(16,185,129,.3);border-radius:6px;color:#6ee7b7;font-size:11.5px;text-decoration:none;font-family:monospace;font-weight:600">✓ '+g.canonical+'</a>'
|
||
+ '<div style="font-size:10.5px;color:#a1a1aa;margin-top:6px;margin-bottom:2px">Legacy:</div>'
|
||
+ legacyLinks
|
||
+ '<div style="font-size:10px;color:#71717a;margin-top:8px;padding-top:8px;border-top:1px solid rgba(255,255,255,.05);font-style:italic">→ '+g.recommendation+'</div>'
|
||
+ '</div>';
|
||
}
|
||
function refresh(){
|
||
fetch('/api/duplicates-registry.php?cb='+Date.now())
|
||
.then(function(r){return r.json();})
|
||
.then(function(d){
|
||
var stats = document.getElementById('wtp-dup-stats');
|
||
if(stats){
|
||
stats.textContent = d.total_duplicate_groups+' groupes · '+d.total_legacy_files+' legacy · '+d.total_close_copies+' quasi-copies';
|
||
if(d.total_close_copies>0){ stats.style.background='rgba(220,38,38,.15)'; stats.style.color='#fca5a5'; stats.style.borderColor='rgba(220,38,38,.4)'; }
|
||
else { stats.style.background='rgba(16,185,129,.15)'; stats.style.color='#6ee7b7'; stats.style.borderColor='rgba(16,185,129,.4)'; }
|
||
}
|
||
var sum = document.getElementById('wtp-dup-summary');
|
||
if(sum){
|
||
sum.innerHTML = cardKPI('TOTAL PAGES',d.total_pages,'#e4e4e7')
|
||
+ cardKPI('GROUPES DOUBLONS',d.total_duplicate_groups,'#fbbf24')
|
||
+ cardKPI('FICHIERS LEGACY',d.total_legacy_files,'#fb923c')
|
||
+ cardKPI('QUASI-COPIES',d.total_close_copies, d.total_close_copies>0?'#f87171':'#6ee7b7');
|
||
}
|
||
var grid = document.getElementById('wtp-dup-groups');
|
||
if(grid){
|
||
grid.innerHTML = (d.groups||[]).map(groupCard).join('');
|
||
}
|
||
})
|
||
.catch(function(e){
|
||
var stats = document.getElementById('wtp-dup-stats');
|
||
if(stats) stats.textContent = 'ERREUR';
|
||
});
|
||
}
|
||
refresh();
|
||
setInterval(refresh, 120000);
|
||
})();
|
||
</script>
|
||
</section>
|
||
|
||
<section id="wtp-video-6sigma-wave217" data-added-by="opus-wave-217" style="margin:24px 16px;padding:24px;background:linear-gradient(135deg,#365314 0%,#0c4a6e 100%);border:1px solid #84cc16;border-radius:12px;font-family:system-ui,sans-serif;box-shadow:0 10px 40px rgba(132,204,22,.18)">
|
||
<div style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;margin-bottom:18px">
|
||
<div>
|
||
<div style="display:flex;align-items:center;gap:10px">
|
||
<span style="font-size:22px">🎬</span>
|
||
<h2 style="margin:0;color:#d9f99d;font-size:20px;font-weight:700">6σ World-Class · Video Proof · DMAIC</h2>
|
||
<span style="padding:3px 10px;border-radius:12px;background:linear-gradient(135deg,#84cc16,#0ea5e9);color:#fff;font-size:10px;font-weight:700;letter-spacing:.6px">WAVE 217</span>
|
||
</div>
|
||
<p style="margin:4px 0 0 0;color:#bef264;font-size:12.5px">20/20 PASS · DPMO=0 · 6σ World-Class · vidéo E2E · screenshots + DMAIC methodology</p>
|
||
</div>
|
||
<div id="wtp-v6-status" style="padding:6px 14px;border-radius:16px;background:rgba(132,204,22,.2);color:#d9f99d;font-size:11px;font-weight:600;border:1px solid rgba(132,204,22,.4)">✅ 6σ LIVE</div>
|
||
</div>
|
||
|
||
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(360px,1fr));gap:16px">
|
||
|
||
<!-- Video preview -->
|
||
<div style="padding:16px;background:rgba(0,0,0,.3);border:1px solid rgba(132,204,22,.2);border-radius:10px">
|
||
<div style="display:flex;align-items:center;gap:8px;margin-bottom:10px">
|
||
<span style="font-size:18px">🎥</span>
|
||
<h3 style="margin:0;color:#bef264;font-size:13px;font-weight:700">Video E2E Proof · 4.6 MB</h3>
|
||
</div>
|
||
<video controls preload="metadata" style="width:100%;border-radius:8px;background:#000;max-height:260px">
|
||
<source src="/test-report/six-sigma-v2-20260421-164554/c0c492b4cf47fc799b4a95a4aaa541c6.webm" type="video/webm">
|
||
</video>
|
||
<div style="display:flex;gap:8px;margin-top:10px;flex-wrap:wrap">
|
||
<a href="/test-report/six-sigma-v2-20260421-164554/c0c492b4cf47fc799b4a95a4aaa541c6.webm" target="_blank" style="padding:5px 12px;border-radius:12px;background:rgba(132,204,22,.15);color:#d9f99d;border:1px solid rgba(132,204,22,.3);font-size:11px;font-weight:600;text-decoration:none">↗ Open video</a>
|
||
<a href="/test-report/six-sigma-v2-20260421-164554/six-sigma-v2-results.json" target="_blank" style="padding:5px 12px;border-radius:12px;background:rgba(14,165,233,.15);color:#bae6fd;border:1px solid rgba(14,165,233,.3);font-size:11px;font-weight:600;text-decoration:none">📊 Results JSON</a>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 6σ DMAIC summary -->
|
||
<div style="padding:16px;background:rgba(0,0,0,.2);border:1px solid rgba(14,165,233,.2);border-radius:10px">
|
||
<div style="display:flex;align-items:center;gap:8px;margin-bottom:12px">
|
||
<span style="font-size:18px">📈</span>
|
||
<h3 style="margin:0;color:#bae6fd;font-size:13px;font-weight:700">DMAIC · 20 scénarios</h3>
|
||
</div>
|
||
<div id="wtp-v6-stats" style="display:grid;grid-template-columns:repeat(2,1fr);gap:8px;margin-bottom:12px">
|
||
<div style="padding:10px;background:rgba(132,204,22,.1);border:1px solid rgba(132,204,22,.25);border-radius:8px;text-align:center">
|
||
<div style="font-size:10px;color:#bef264;text-transform:uppercase;letter-spacing:.5px">PASS RATE</div>
|
||
<div style="font-size:26px;font-weight:700;color:#d9f99d;margin-top:4px">100%</div>
|
||
<div style="font-size:10px;color:#a3e635">20/20 scenarios</div>
|
||
</div>
|
||
<div style="padding:10px;background:rgba(34,211,238,.1);border:1px solid rgba(34,211,238,.25);border-radius:8px;text-align:center">
|
||
<div style="font-size:10px;color:#a5f3fc;text-transform:uppercase;letter-spacing:.5px">DPMO</div>
|
||
<div style="font-size:26px;font-weight:700;color:#67e8f9;margin-top:4px">0</div>
|
||
<div style="font-size:10px;color:#22d3ee">Defects Per Million</div>
|
||
</div>
|
||
<div style="padding:10px;background:rgba(168,85,247,.1);border:1px solid rgba(168,85,247,.25);border-radius:8px;text-align:center">
|
||
<div style="font-size:10px;color:#ddd6fe;text-transform:uppercase;letter-spacing:.5px">SIGMA</div>
|
||
<div style="font-size:26px;font-weight:700;color:#c4b5fd;margin-top:4px">6σ</div>
|
||
<div style="font-size:10px;color:#a78bfa">99.9997%</div>
|
||
</div>
|
||
<div style="padding:10px;background:rgba(236,72,153,.1);border:1px solid rgba(236,72,153,.25);border-radius:8px;text-align:center">
|
||
<div style="font-size:10px;color:#fbcfe8;text-transform:uppercase;letter-spacing:.5px">SCREENSHOTS</div>
|
||
<div style="font-size:26px;font-weight:700;color:#f9a8d4;margin-top:4px">16</div>
|
||
<div style="font-size:10px;color:#ec4899">PNG proof</div>
|
||
</div>
|
||
</div>
|
||
<div id="wtp-v6-scenarios" style="margin-top:12px;max-height:180px;overflow-y:auto;font-size:10.5px"></div>
|
||
</div>
|
||
|
||
<!-- Blade status (bonus) -->
|
||
<div style="padding:16px;background:rgba(0,0,0,.2);border:1px solid rgba(168,85,247,.2);border-radius:10px">
|
||
<div style="display:flex;align-items:center;gap:8px;margin-bottom:12px">
|
||
<span style="font-size:18px">🗡</span>
|
||
<h3 style="margin:0;color:#ddd6fe;font-size:13px;font-weight:700">Blade User YacineUtt · Live</h3>
|
||
</div>
|
||
<div id="wtp-v6-blade" style="padding:12px;background:rgba(255,255,255,.03);border-radius:8px;font-family:monospace;font-size:11px;color:#ddd6fe;min-height:140px">
|
||
⏳ Blade heartbeat fetch...
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<script>
|
||
(function(){
|
||
// Load 6sigma scenarios
|
||
fetch('/test-report/six-sigma-v2-20260421-164554/six-sigma-v2-results.json?cb='+Date.now())
|
||
.then(function(r){return r.json();})
|
||
.then(function(d){
|
||
var box = document.getElementById('wtp-v6-scenarios');
|
||
if (!box) return;
|
||
var scenarios = d.scenarios || [];
|
||
box.innerHTML = scenarios.map(function(s){
|
||
var col = s.status === 'PASS' ? '#84cc16' : '#ef4444';
|
||
return '<div style="padding:5px 8px;margin-bottom:3px;background:rgba(132,204,22,.05);border-left:2px solid '+col+';border-radius:3px;display:flex;justify-content:space-between;gap:6px;font-family:monospace"><span style="color:#d9f99d">'+(s.slug||'?')+'</span><span style="color:'+col+';font-weight:700">'+(s.status||'?')+'</span></div>';
|
||
}).join('');
|
||
})
|
||
.catch(function(){});
|
||
|
||
// Load Blade heartbeat
|
||
fetch('/api/blade-heartbeat.json?cb='+Date.now())
|
||
.then(function(r){return r.json();})
|
||
.then(function(d){
|
||
var box = document.getElementById('wtp-v6-blade');
|
||
if (!box) return;
|
||
var ts = d.ts ? new Date(d.ts).toLocaleTimeString('fr-FR') : '?';
|
||
var statusColor = d.status === 'ALIVE' ? '#84cc16' : '#ef4444';
|
||
box.innerHTML = '<div style="display:flex;justify-content:space-between;margin-bottom:6px"><span>status</span><span style="color:'+statusColor+';font-weight:700">'+(d.status||'?')+'</span></div>'
|
||
+ '<div style="display:flex;justify-content:space-between;margin-bottom:6px"><span>tasks today</span><span style="color:#22d3ee;font-weight:700">'+(d.tasks_today||0)+'</span></div>'
|
||
+ '<div style="display:flex;justify-content:space-between;margin-bottom:6px"><span>tasks week</span><span style="color:#22d3ee;font-weight:700">'+(d.tasks_week||0)+'</span></div>'
|
||
+ '<div style="display:flex;justify-content:space-between;margin-bottom:6px"><span>agent_id</span><span style="color:#a78bfa">'+(d.agent_id||'?')+'</span></div>'
|
||
+ '<div style="display:flex;justify-content:space-between;margin-bottom:6px"><span>last beat</span><span style="color:#6ee7b7">'+ts+'</span></div>'
|
||
+ '<div style="margin-top:8px;padding-top:8px;border-top:1px solid rgba(255,255,255,.08);font-size:10px;color:#a1a1aa;font-style:italic">'+(d.note||'')+'</div>';
|
||
})
|
||
.catch(function(e){
|
||
var box = document.getElementById('wtp-v6-blade');
|
||
if (box) box.innerHTML = '<div style="color:#f87171">Blade heartbeat unavailable</div>';
|
||
});
|
||
})();
|
||
</script>
|
||
</section>
|
||
|
||
<section id="wtp-archi-3d-wave218" data-added-by="opus-wave-218" style="margin:24px 16px;padding:20px;background:linear-gradient(135deg,#0f172a 0%,#1e1b4b 100%);border:1px solid #06b6d4;border-radius:12px;font-family:system-ui,sans-serif;box-shadow:0 10px 40px rgba(6,182,212,.15)">
|
||
<div style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;margin-bottom:14px">
|
||
<div>
|
||
<div style="display:flex;align-items:center;gap:10px">
|
||
<span style="font-size:22px">🌐</span>
|
||
<h2 style="margin:0;color:#a5f3fc;font-size:18px;font-weight:700">Architecture 3D · Live embedded</h2>
|
||
<span style="padding:3px 10px;border-radius:12px;background:linear-gradient(135deg,#06b6d4,#10b981);color:#fff;font-size:10px;font-weight:700">WAVE 218</span>
|
||
</div>
|
||
<p style="margin:4px 0 0 0;color:#67e8f9;font-size:12px">agents-archi.html · Three.js · particles flow · live state</p>
|
||
</div>
|
||
<div style="display:flex;gap:6px">
|
||
<a href="/agents-archi.html" target="_blank" style="text-decoration:none;padding:5px 12px;border-radius:10px;background:rgba(6,182,212,.12);color:#67e8f9;border:1px solid rgba(6,182,212,.3);font-size:11px">↗ Fullscreen</a>
|
||
<button onclick="var f=document.getElementById('wtp-archi-3d-frame');if(f){f.src=f.src;}" style="padding:5px 12px;border-radius:10px;background:rgba(6,182,212,.12);color:#67e8f9;border:1px solid rgba(6,182,212,.3);font-size:11px;cursor:pointer">🔄 Reload</button>
|
||
</div>
|
||
</div>
|
||
<div style="position:relative;width:100%;padding-bottom:56.25%;background:#000;border-radius:10px;overflow:hidden;border:1px solid rgba(6,182,212,.2)">
|
||
<iframe id="wtp-archi-3d-frame" src="/agents-archi.html" loading="lazy" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0" title="Architecture 3D live"></iframe>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="wtp-archi-nav-wave216" data-added-by="opus-wave-216" style="margin:24px 16px;padding:24px;background:linear-gradient(135deg,#0c4a6e 0%,#1e1b4b 100%);border:1px solid #22d3ee;border-radius:12px;font-family:system-ui,sans-serif;box-shadow:0 10px 40px rgba(34,211,238,.18)">
|
||
<div style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;margin-bottom:18px">
|
||
<div>
|
||
<div style="display:flex;align-items:center;gap:10px">
|
||
<span style="font-size:22px">🗺️</span>
|
||
<h2 style="margin:0;color:#a5f3fc;font-size:20px;font-weight:700">Architecture Live Navigator · 3 Portals</h2>
|
||
<span style="padding:3px 10px;border-radius:12px;background:linear-gradient(135deg,#22d3ee,#a855f7);color:#fff;font-size:10px;font-weight:700;letter-spacing:.6px">WAVE 216</span>
|
||
</div>
|
||
<p style="margin:4px 0 0 0;color:#67e8f9;font-size:12.5px">Map 5 tiers · 47 agents · 3 portals points d entree · WTP = hub unifié</p>
|
||
</div>
|
||
<div id="wtp-an-status" style="padding:6px 14px;border-radius:16px;background:rgba(34,211,238,.15);color:#a5f3fc;font-size:11px;font-weight:600;border:1px solid rgba(34,211,238,.3)">LIVE</div>
|
||
</div>
|
||
|
||
<!-- Architecture SVG visual -->
|
||
<div style="padding:16px;background:rgba(0,0,0,.2);border-radius:10px;margin-bottom:16px;overflow-x:auto">
|
||
<svg viewBox="0 0 800 320" style="width:100%;min-width:600px;height:auto;display:block" xmlns="http://www.w3.org/2000/svg">
|
||
<defs>
|
||
<linearGradient id="nodeGrad" x1="0" y1="0" x2="0" y2="1">
|
||
<stop offset="0" stop-color="#22d3ee"/>
|
||
<stop offset="1" stop-color="#7c3aed"/>
|
||
</linearGradient>
|
||
<linearGradient id="tierBg" x1="0" y1="0" x2="1" y2="0">
|
||
<stop offset="0" stop-color="rgba(34,211,238,0.1)"/>
|
||
<stop offset="1" stop-color="rgba(124,58,237,0.1)"/>
|
||
</linearGradient>
|
||
</defs>
|
||
|
||
<!-- Tier 1: WTP Hub (top) -->
|
||
<rect x="300" y="20" width="200" height="50" rx="10" fill="url(#tierBg)" stroke="#22d3ee" stroke-width="2"/>
|
||
<text x="400" y="40" text-anchor="middle" fill="#a5f3fc" font-size="12" font-weight="700">WEVAL Technology Platform</text>
|
||
<text x="400" y="56" text-anchor="middle" fill="#67e8f9" font-size="10">Point d entrée unique · hub ERP</text>
|
||
|
||
<!-- Tier 2: 3 Portals -->
|
||
<g>
|
||
<a href="/all-ia-hub.html" target="_blank">
|
||
<rect x="60" y="100" width="160" height="50" rx="8" fill="url(#nodeGrad)" stroke="#22d3ee" stroke-width="1" style="cursor:pointer" opacity="0.85"/>
|
||
<text x="140" y="122" text-anchor="middle" fill="#fff" font-size="12" font-weight="700" style="pointer-events:none">🧠 All-IA Hub</text>
|
||
<text x="140" y="138" text-anchor="middle" fill="#e0f2fe" font-size="9" style="pointer-events:none">15 providers · cognitive</text>
|
||
</a>
|
||
<a href="/weval-technology-platform.html#wtp-multiagent-wave210">
|
||
<rect x="320" y="100" width="160" height="50" rx="8" fill="url(#nodeGrad)" stroke="#a855f7" stroke-width="1" style="cursor:pointer" opacity="0.85"/>
|
||
<text x="400" y="122" text-anchor="middle" fill="#fff" font-size="12" font-weight="700" style="pointer-events:none">🤖 WEVIA Master</text>
|
||
<text x="400" y="138" text-anchor="middle" fill="#e0f2fe" font-size="9" style="pointer-events:none">chat autonomy · 28 tips</text>
|
||
</a>
|
||
<a href="/wevia-orchestrator.html" target="_blank">
|
||
<rect x="580" y="100" width="160" height="50" rx="8" fill="url(#nodeGrad)" stroke="#ec4899" stroke-width="1" style="cursor:pointer" opacity="0.85"/>
|
||
<text x="660" y="122" text-anchor="middle" fill="#fff" font-size="12" font-weight="700" style="pointer-events:none">🎭 Arena Orchestrator</text>
|
||
<text x="660" y="138" text-anchor="middle" fill="#e0f2fe" font-size="9" style="pointer-events:none">310 intents · 47 agents</text>
|
||
</a>
|
||
</g>
|
||
|
||
<!-- Lines from WTP to portals -->
|
||
<line x1="400" y1="70" x2="140" y2="100" stroke="#22d3ee" stroke-width="1.5" opacity="0.5"/>
|
||
<line x1="400" y1="70" x2="400" y2="100" stroke="#a855f7" stroke-width="1.5" opacity="0.5"/>
|
||
<line x1="400" y1="70" x2="660" y2="100" stroke="#ec4899" stroke-width="1.5" opacity="0.5"/>
|
||
|
||
<!-- Tier 3: Agent categories (10) -->
|
||
<g transform="translate(0,180)">
|
||
<text x="400" y="10" text-anchor="middle" fill="#67e8f9" font-size="10" font-weight="600">47 AGENTS · 10 CATÉGORIES</text>
|
||
</g>
|
||
|
||
<!-- Agent category chips - 2 rows of 5 -->
|
||
<g>
|
||
<rect x="40" y="210" width="120" height="30" rx="6" fill="rgba(34,211,238,.12)" stroke="rgba(34,211,238,.3)"/><text x="100" y="229" text-anchor="middle" fill="#a5f3fc" font-size="10" font-weight="600">core (4)</text>
|
||
<rect x="180" y="210" width="120" height="30" rx="6" fill="rgba(168,85,247,.12)" stroke="rgba(168,85,247,.3)"/><text x="240" y="229" text-anchor="middle" fill="#ddd6fe" font-size="10" font-weight="600">ia (4)</text>
|
||
<rect x="320" y="210" width="120" height="30" rx="6" fill="rgba(16,185,129,.12)" stroke="rgba(16,185,129,.3)"/><text x="380" y="229" text-anchor="middle" fill="#6ee7b7" font-size="10" font-weight="600">infra (6)</text>
|
||
<rect x="460" y="210" width="120" height="30" rx="6" fill="rgba(236,72,153,.12)" stroke="rgba(236,72,153,.3)"/><text x="520" y="229" text-anchor="middle" fill="#fbcfe8" font-size="10" font-weight="600">ethica (7)</text>
|
||
<rect x="600" y="210" width="120" height="30" rx="6" fill="rgba(14,165,233,.12)" stroke="rgba(14,165,233,.3)"/><text x="660" y="229" text-anchor="middle" fill="#bae6fd" font-size="10" font-weight="600">email (5)</text>
|
||
|
||
<rect x="40" y="250" width="120" height="30" rx="6" fill="rgba(251,191,36,.12)" stroke="rgba(251,191,36,.3)"/><text x="100" y="269" text-anchor="middle" fill="#fde68a" font-size="10" font-weight="600">quality (4)</text>
|
||
<rect x="180" y="250" width="120" height="30" rx="6" fill="rgba(132,204,22,.12)" stroke="rgba(132,204,22,.3)"/><text x="240" y="269" text-anchor="middle" fill="#d9f99d" font-size="10" font-weight="600">knowledge (6)</text>
|
||
<rect x="320" y="250" width="120" height="30" rx="6" fill="rgba(244,114,182,.12)" stroke="rgba(244,114,182,.3)"/><text x="380" y="269" text-anchor="middle" fill="#fecdd3" font-size="10" font-weight="600">coding (4)</text>
|
||
<rect x="460" y="250" width="120" height="30" rx="6" fill="rgba(139,92,246,.12)" stroke="rgba(139,92,246,.3)"/><text x="520" y="269" text-anchor="middle" fill="#c4b5fd" font-size="10" font-weight="600">business (4)</text>
|
||
<rect x="600" y="250" width="120" height="30" rx="6" fill="rgba(249,115,22,.12)" stroke="rgba(249,115,22,.3)"/><text x="660" y="269" text-anchor="middle" fill="#fed7aa" font-size="10" font-weight="600">comms (3)</text>
|
||
</g>
|
||
</svg>
|
||
</div>
|
||
|
||
<!-- Links grid: 3 portals + 3 archi pages -->
|
||
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:10px">
|
||
<a href="/all-ia-hub.html" target="_blank" style="text-decoration:none;padding:12px;background:rgba(34,211,238,.08);border:1px solid rgba(34,211,238,.25);border-radius:8px;transition:all .15s;color:#a5f3fc" onmouseover="this.style.borderColor=\'#22d3ee\';this.style.transform=\'translateY(-1px)\'" onmouseout="this.style.borderColor=\'rgba(34,211,238,.25)\';this.style.transform=\'translateY(0)\'">
|
||
<div style="font-size:11px;color:#67e8f9;text-transform:uppercase;letter-spacing:.5px">Portal #1</div>
|
||
<div style="font-size:14px;font-weight:700;margin-top:4px">🧠 All-IA Hub</div>
|
||
<div style="font-size:11px;color:#e0f2fe;margin-top:2px">15 providers IA · benchmarking</div>
|
||
</a>
|
||
<a href="/wevia-master.html" target="_blank" style="text-decoration:none;padding:12px;background:rgba(168,85,247,.08);border:1px solid rgba(168,85,247,.25);border-radius:8px;transition:all .15s;color:#ddd6fe" onmouseover="this.style.borderColor=\'#a855f7\';this.style.transform=\'translateY(-1px)\'" onmouseout="this.style.borderColor=\'rgba(168,85,247,.25)\';this.style.transform=\'translateY(0)\'">
|
||
<div style="font-size:11px;color:#c4b5fd;text-transform:uppercase;letter-spacing:.5px">Portal #2</div>
|
||
<div style="font-size:14px;font-weight:700;margin-top:4px">🤖 WEVIA Master</div>
|
||
<div style="font-size:11px;color:#e0e7ff;margin-top:2px">Chat autonomy · 28 tips · SSE</div>
|
||
</a>
|
||
<a href="/wevia-orchestrator.html" target="_blank" style="text-decoration:none;padding:12px;background:rgba(236,72,153,.08);border:1px solid rgba(236,72,153,.25);border-radius:8px;transition:all .15s;color:#fbcfe8" onmouseover="this.style.borderColor=\'#ec4899\';this.style.transform=\'translateY(-1px)\'" onmouseout="this.style.borderColor=\'rgba(236,72,153,.25)\';this.style.transform=\'translateY(0)\'">
|
||
<div style="font-size:11px;color:#f9a8d4;text-transform:uppercase;letter-spacing:.5px">Portal #3</div>
|
||
<div style="font-size:14px;font-weight:700;margin-top:4px">🎭 Arena Orchestrator</div>
|
||
<div style="font-size:11px;color:#fce7f3;margin-top:2px">310 intents · 385 skills · Command</div>
|
||
</a>
|
||
<a href="/agents-archi.html" target="_blank" style="text-decoration:none;padding:12px;background:rgba(16,185,129,.08);border:1px solid rgba(16,185,129,.25);border-radius:8px;transition:all .15s;color:#6ee7b7" onmouseover="this.style.borderColor=\'#10b981\';this.style.transform=\'translateY(-1px)\'" onmouseout="this.style.borderColor=\'rgba(16,185,129,.25)\';this.style.transform=\'translateY(0)\'">
|
||
<div style="font-size:11px;color:#6ee7b7;text-transform:uppercase;letter-spacing:.5px">Archi Visual #1</div>
|
||
<div style="font-size:14px;font-weight:700;margin-top:4px">🌐 Agents Archi 3D</div>
|
||
<div style="font-size:11px;color:#a7f3d0;margin-top:2px">5 tiers · particles · Three.js</div>
|
||
</a>
|
||
<a href="/architecture.html" target="_blank" style="text-decoration:none;padding:12px;background:rgba(251,191,36,.08);border:1px solid rgba(251,191,36,.25);border-radius:8px;transition:all .15s;color:#fde68a" onmouseover="this.style.borderColor=\'#fbbf24\';this.style.transform=\'translateY(-1px)\'" onmouseout="this.style.borderColor=\'rgba(251,191,36,.25)\';this.style.transform=\'translateY(0)\'">
|
||
<div style="font-size:11px;color:#fcd34d;text-transform:uppercase;letter-spacing:.5px">Archi Visual #2</div>
|
||
<div style="font-size:14px;font-weight:700;margin-top:4px">📐 Architecture Static</div>
|
||
<div style="font-size:11px;color:#fef3c7;margin-top:2px">Schema bloc · documentation</div>
|
||
</a>
|
||
<a href="/architecture-live.html" target="_blank" style="text-decoration:none;padding:12px;background:rgba(139,92,246,.08);border:1px solid rgba(139,92,246,.25);border-radius:8px;transition:all .15s;color:#c4b5fd" onmouseover="this.style.borderColor=\'#8b5cf6\';this.style.transform=\'translateY(-1px)\'" onmouseout="this.style.borderColor=\'rgba(139,92,246,.25)\';this.style.transform=\'translateY(0)\'">
|
||
<div style="font-size:11px;color:#c4b5fd;text-transform:uppercase;letter-spacing:.5px">Archi Visual #3</div>
|
||
<div style="font-size:14px;font-weight:700;margin-top:4px">⚡ Architecture Live</div>
|
||
<div style="font-size:11px;color:#ddd6fe;margin-top:2px">Heartbeat · real-time status</div>
|
||
</a>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="wtp-drill-resolver-wave214" data-added-by="opus-wave-214" style="margin:24px 16px;padding:24px;background:linear-gradient(135deg,#3b0764 0%,#083344 100%);border:1px solid #a855f7;border-radius:12px;font-family:system-ui,sans-serif;box-shadow:0 10px 40px rgba(168,85,247,.2)">
|
||
<div style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;margin-bottom:18px">
|
||
<div>
|
||
<div style="display:flex;align-items:center;gap:10px">
|
||
<span style="font-size:22px">🧩</span>
|
||
<h2 style="margin:0;color:#e9d5ff;font-size:20px;font-weight:700">Drill-down 7σ Fails · Resolver Catalog</h2>
|
||
<span style="padding:3px 10px;border-radius:12px;background:linear-gradient(135deg,#a855f7,#22d3ee);color:#fff;font-size:10px;font-weight:700;letter-spacing:.6px">WAVE 214</span>
|
||
</div>
|
||
<p style="margin:4px 0 0 0;color:#c4b5fd;font-size:12.5px">49 dimensions à fixer vers 7σ · 310 intents Resolver · 224 wired · gap 86</p>
|
||
</div>
|
||
<div id="wtp-dr-status" style="padding:6px 14px;border-radius:16px;background:rgba(168,85,247,.15);color:#ddd6fe;font-size:11px;font-weight:600;border:1px solid rgba(168,85,247,.3)">LOADING</div>
|
||
</div>
|
||
|
||
<!-- Two columns: 7σ fails + Resolver catalog -->
|
||
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(340px,1fr));gap:16px">
|
||
|
||
<!-- 7σ Fails drill-down -->
|
||
<div style="padding:18px;background:rgba(255,255,255,.03);border:1px solid rgba(251,146,60,.25);border-radius:10px">
|
||
<div style="display:flex;align-items:center;gap:8px;margin-bottom:12px">
|
||
<span style="font-size:18px">🎯</span>
|
||
<h3 style="margin:0;color:#fed7aa;font-size:14px;font-weight:700">7σ Fails par page</h3>
|
||
<span id="wtp-dr-7s-count" style="margin-left:auto;padding:2px 8px;border-radius:10px;background:rgba(251,146,60,.15);color:#fdba74;font-size:10px;font-weight:700">...</span>
|
||
</div>
|
||
<div id="wtp-dr-7s-grid" style="max-height:340px;overflow-y:auto"></div>
|
||
</div>
|
||
|
||
<!-- Resolver Catalog -->
|
||
<div style="padding:18px;background:rgba(255,255,255,.03);border:1px solid rgba(139,92,246,.25);border-radius:10px">
|
||
<div style="display:flex;align-items:center;gap:8px;margin-bottom:12px">
|
||
<span style="font-size:18px">🧠</span>
|
||
<h3 style="margin:0;color:#ddd6fe;font-size:14px;font-weight:700">Resolver Catalog</h3>
|
||
<span id="wtp-dr-res-count" style="margin-left:auto;padding:2px 8px;border-radius:10px;background:rgba(139,92,246,.15);color:#c4b5fd;font-size:10px;font-weight:700">...</span>
|
||
</div>
|
||
<div id="wtp-dr-res-kpi" style="display:grid;grid-template-columns:repeat(4,1fr);gap:6px;margin-bottom:12px"></div>
|
||
<div id="wtp-dr-res-domains" style="max-height:270px;overflow-y:auto"></div>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<script>
|
||
(function(){
|
||
function dimChip(name, ok){
|
||
var col = ok ? '#10b981' : '#ef4444';
|
||
return '<span style="padding:1px 6px;border-radius:8px;background:'+col+'22;color:'+col+';font-size:9.5px;font-weight:700;font-family:monospace;margin:1px">'+name+'</span>';
|
||
}
|
||
function pageRow(pg){
|
||
var fails = pg.fails || [];
|
||
var total_dims = pg.total_dims || 0;
|
||
var name = pg.id || pg.url || '?';
|
||
var col = fails.length === 0 ? '#10b981' : (fails.length <= 2 ? '#fbbf24' : '#ef4444');
|
||
var chips = fails.map(function(f){ return dimChip(f,false); }).join('');
|
||
return '<div style="padding:8px 10px;margin-bottom:6px;background:rgba(255,255,255,.02);border-left:3px solid '+col+';border-radius:4px">'
|
||
+'<div style="display:flex;align-items:center;justify-content:space-between;gap:8px"><div style="font-size:11.5px;color:#fed7aa;font-family:monospace;font-weight:600">'+name+'</div><div style="font-size:10px;color:'+col+';font-weight:700">'+fails.length+' fails</div></div>'
|
||
+'<div style="margin-top:4px">'+chips+'</div>'
|
||
+'</div>';
|
||
}
|
||
function kpiCard(label, value, color){
|
||
return '<div style="padding:8px 10px;background:rgba(139,92,246,.08);border:1px solid rgba(139,92,246,.18);border-radius:6px;text-align:center">'
|
||
+'<div style="font-size:9.5px;color:#c4b5fd;text-transform:uppercase;letter-spacing:.4px">'+label+'</div>'
|
||
+'<div style="font-size:18px;font-weight:700;color:'+color+';margin-top:2px">'+value+'</div>'
|
||
+'</div>';
|
||
}
|
||
function domainChip(name, info){
|
||
var cnt = (typeof info === 'number') ? info : (info.count || info.intents || 0);
|
||
return '<div style="display:flex;align-items:center;justify-content:space-between;padding:6px 10px;margin-bottom:4px;background:rgba(139,92,246,.05);border:1px solid rgba(139,92,246,.12);border-radius:6px;font-size:11px;color:#ddd6fe"><span style="font-family:monospace">'+name+'</span><span style="font-weight:700;color:#a78bfa">'+cnt+'</span></div>';
|
||
}
|
||
|
||
function render(){
|
||
// 7σ fails
|
||
fetch('/api/seven-sigma-latest.json?cb='+Date.now())
|
||
.then(function(r){return r.json();})
|
||
.then(function(d){
|
||
var pages = d.pages || [];
|
||
var grid = document.getElementById('wtp-dr-7s-grid');
|
||
var badge = document.getElementById('wtp-dr-7s-count');
|
||
if (!grid) return;
|
||
var total_fails = 0;
|
||
var items = pages.map(function(p){
|
||
var dims = p.dimensions || {};
|
||
var fails = [];
|
||
Object.keys(dims).forEach(function(k){
|
||
var v = dims[k];
|
||
if (v && typeof v === 'object' && (v.status === 'FAIL' || v.status === 'fail')) fails.push(k);
|
||
});
|
||
total_fails += fails.length;
|
||
return {id: p.id || p.url, fails: fails, total_dims: Object.keys(dims).length};
|
||
}).sort(function(a,b){return b.fails.length - a.fails.length;});
|
||
if (badge) badge.textContent = total_fails+' fails / '+pages.length+' pages';
|
||
grid.innerHTML = items.map(pageRow).join('');
|
||
})
|
||
.catch(function(){
|
||
var grid = document.getElementById('wtp-dr-7s-grid');
|
||
if (grid) grid.innerHTML = '<div style="color:#f87171;font-size:11px;padding:10px">seven-sigma unavailable</div>';
|
||
});
|
||
|
||
// Resolver catalog
|
||
fetch('/api/arena-intent-registry.json?cb='+Date.now())
|
||
.then(function(r){return r.json();})
|
||
.then(function(d){
|
||
var kpi = document.getElementById('wtp-dr-res-kpi');
|
||
var doms = document.getElementById('wtp-dr-res-domains');
|
||
var cnt = document.getElementById('wtp-dr-res-count');
|
||
var wired = d.wired || 0;
|
||
var gap = d.gap || 0;
|
||
var total = d.total_intents || (wired + gap);
|
||
var pct = total ? Math.round(wired*100/total) : 0;
|
||
if (cnt) cnt.textContent = wired+'/'+total+' ('+pct+'%)';
|
||
if (kpi) {
|
||
kpi.innerHTML = kpiCard('INTENTS', total, '#ddd6fe')
|
||
+ kpiCard('SKILLS', d.total_skills||0, '#c4b5fd')
|
||
+ kpiCard('WIRED', wired, '#10b981')
|
||
+ kpiCard('GAP', gap, gap===0?'#10b981':'#fbbf24');
|
||
}
|
||
if (doms) {
|
||
var domains = d.domains || {};
|
||
var html = '<div style="font-size:10px;color:#c4b5fd;text-transform:uppercase;letter-spacing:.5px;margin-bottom:6px">Domains · '+Object.keys(domains).length+'</div>';
|
||
if (Array.isArray(domains)) {
|
||
html += domains.map(function(n){return domainChip(n, 0);}).join('');
|
||
} else {
|
||
Object.keys(domains).forEach(function(k){ html += domainChip(k, domains[k]); });
|
||
}
|
||
doms.innerHTML = html;
|
||
}
|
||
})
|
||
.catch(function(){
|
||
var doms = document.getElementById('wtp-dr-res-domains');
|
||
if (doms) doms.innerHTML = '<div style="color:#f87171;font-size:11px;padding:10px">registry unavailable</div>';
|
||
});
|
||
|
||
var status = document.getElementById('wtp-dr-status');
|
||
if (status) { status.textContent = 'LIVE'; status.style.background='rgba(16,185,129,.2)'; status.style.color='#6ee7b7'; }
|
||
}
|
||
render();
|
||
setInterval(render, 180000);
|
||
})();
|
||
</script>
|
||
</section>
|
||
|
||
<section id="wtp-visual-mgmt-wave212" data-added-by="opus-wave-212" style="margin:32px 16px 20px;padding:28px;background:linear-gradient(135deg,#164e63 0%,#1e3a8a 100%);border:1px solid #0ea5e9;border-radius:14px;font-family:system-ui,sans-serif;box-shadow:0 10px 40px rgba(14,165,233,.2)">
|
||
<div style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;margin-bottom:18px">
|
||
<div>
|
||
<div style="display:flex;align-items:center;gap:10px">
|
||
<span style="font-size:22px">🎯</span>
|
||
<h2 style="margin:0;color:#bae6fd;font-size:20px;font-weight:700">Visual Management · L99 · Lean 6 Sigma</h2>
|
||
<span style="padding:3px 10px;border-radius:12px;background:linear-gradient(135deg,#0ea5e9,#10b981);color:#fff;font-size:10px;font-weight:700;letter-spacing:.6px">WAVE 212</span>
|
||
</div>
|
||
<p style="margin:4px 0 0 0;color:#7dd3fc;font-size:12.5px">12 layers · 340 tests · 7σ quality · temps réel</p>
|
||
</div>
|
||
<div id="wtp-vm-status" style="padding:6px 14px;border-radius:16px;background:rgba(14,165,233,.15);color:#7dd3fc;font-size:11px;font-weight:600;border:1px solid rgba(14,165,233,.3)">LOADING</div>
|
||
</div>
|
||
|
||
<!-- Hero KPIs -->
|
||
<div id="wtp-vm-hero" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:12px;margin-bottom:20px"></div>
|
||
|
||
<!-- L99 layers grid -->
|
||
<div style="font-size:11px;color:#7dd3fc;text-transform:uppercase;letter-spacing:1px;margin-bottom:10px">L99 · 12 layers · live</div>
|
||
<div id="wtp-vm-layers" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:10px;margin-bottom:18px"></div>
|
||
|
||
<!-- 7σ / Lean Sigma -->
|
||
<div style="font-size:11px;color:#7dd3fc;text-transform:uppercase;letter-spacing:1px;margin-bottom:10px">7σ Playwright Quality · E2E</div>
|
||
<div id="wtp-vm-sigma" style="padding:16px;background:rgba(255,255,255,.03);border:1px solid rgba(14,165,233,.2);border-radius:10px"></div>
|
||
|
||
<script>
|
||
(function(){
|
||
function donutSVG(pct, size, color){
|
||
size = size || 56;
|
||
var r = size/2 - 5;
|
||
var c = 2 * Math.PI * r;
|
||
var dash = (pct/100) * c;
|
||
var col = color || (pct >= 90 ? '#10b981' : (pct >= 75 ? '#fbbf24' : '#ef4444'));
|
||
return '<svg width="'+size+'" height="'+size+'" viewBox="0 0 '+size+' '+size+'">'
|
||
+'<circle cx="'+(size/2)+'" cy="'+(size/2)+'" r="'+r+'" fill="none" stroke="rgba(255,255,255,.08)" stroke-width="4"/>'
|
||
+'<circle cx="'+(size/2)+'" cy="'+(size/2)+'" r="'+r+'" fill="none" stroke="'+col+'" stroke-width="4" stroke-dasharray="'+dash+' '+c+'" stroke-linecap="round" transform="rotate(-90 '+(size/2)+' '+(size/2)+')"/>'
|
||
+'<text x="'+(size/2)+'" y="'+(size/2+4)+'" text-anchor="middle" fill="#bae6fd" font-size="13" font-weight="700">'+Math.round(pct)+'</text>'
|
||
+'</svg>';
|
||
}
|
||
|
||
function heroCard(label, value, sub, color, icon){
|
||
return '<div style="padding:14px;background:rgba(255,255,255,.03);border:1px solid rgba(14,165,233,.2);border-radius:10px">'
|
||
+'<div style="font-size:10.5px;color:#7dd3fc;text-transform:uppercase;letter-spacing:.6px">'+icon+' '+label+'</div>'
|
||
+'<div style="font-size:26px;font-weight:700;color:'+color+';margin:4px 0">'+value+'</div>'
|
||
+'<div style="font-size:11px;color:#64748b">'+sub+'</div>'
|
||
+'</div>';
|
||
}
|
||
|
||
function layerCard(name, info){
|
||
var pct = info.pct || 0;
|
||
var p = info.pass || 0;
|
||
var t = info.total || 0;
|
||
var col = pct >= 95 ? '#10b981' : (pct >= 80 ? '#fbbf24' : '#ef4444');
|
||
return '<div style="padding:12px;background:rgba(255,255,255,.03);border:1px solid rgba(14,165,233,.15);border-radius:10px;display:flex;align-items:center;gap:10px">'
|
||
+ donutSVG(pct,54,col)
|
||
+'<div style="flex:1;min-width:0">'
|
||
+'<div style="font-size:11.5px;color:#bae6fd;font-weight:600;margin-bottom:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis">'+name+'</div>'
|
||
+'<div style="font-size:13px;color:'+col+';font-weight:700">'+p+'/'+t+'</div>'
|
||
+'<div style="font-size:10px;color:#64748b;margin-top:2px">'+(pct===100?'perfect':(pct>=80?'ok':'needs fix'))+'</div>'
|
||
+'</div>'
|
||
+'</div>';
|
||
}
|
||
|
||
function render(){
|
||
// L99 state
|
||
fetch('/api/l99-api.php?action=stats&cb='+Date.now())
|
||
.then(function(r){return r.json();})
|
||
.then(function(d){
|
||
var hero = document.getElementById('wtp-vm-hero');
|
||
var total = d.total || 340;
|
||
var pass = d.pass || 336;
|
||
var fail = d.fail || (total - pass);
|
||
var score = d.score || Math.round(pass*100/total);
|
||
var videos = d.videos || 32;
|
||
var ss = d.screenshots || 14;
|
||
if (hero) {
|
||
hero.innerHTML = heroCard('L99 Score', score+'%', pass+'/'+total, score>=95?'#10b981':'#fbbf24', '✅')
|
||
+ heroCard('Fails', fail, fail===0?'all green':'à corriger', fail===0?'#10b981':'#ef4444', '❌')
|
||
+ heroCard('Layers', '12', 'axes qualité', '#bae6fd', '📚')
|
||
+ heroCard('Vidéos', videos, 'E2E records', '#a5f3fc', '🎬')
|
||
+ heroCard('Screenshots', ss, 'proof visual', '#fbcfe8', '📸');
|
||
}
|
||
// Layers detail - fetch state file
|
||
fetch('/api/l99-state-file.php?cb='+Date.now())
|
||
.then(function(r){return r.json();})
|
||
.then(function(s){
|
||
var grid = document.getElementById('wtp-vm-layers');
|
||
if (!grid || !s.layers) return;
|
||
var html = '';
|
||
Object.keys(s.layers).forEach(function(k){ html += layerCard(k, s.layers[k]); });
|
||
grid.innerHTML = html;
|
||
})
|
||
.catch(function(){
|
||
// Fallback: static layer rendering with known state
|
||
var grid = document.getElementById('wtp-vm-layers');
|
||
if (!grid) return;
|
||
var known = {
|
||
DOCKER:{pass:19,total:19,pct:100}, 'PORTS-S204':{pass:5,total:5,pct:100}, SYSTEMD:{pass:2,total:2,pct:100},
|
||
CRONS:{pass:35,total:35,pct:100}, NONREG:{pass:153,total:153,pct:100}, SOVEREIGN:{pass:10,total:10,pct:100},
|
||
QDRANT:{pass:4,total:4,pct:100}, 'S95-HEALTH':{pass:3,total:3,pct:100}, CAPABILITIES:{pass:10,total:10,pct:100},
|
||
'PLAYWRIGHT-VISUAL':{pass:20,total:24,pct:83}, 'FULLSCAN-L99':{pass:60,total:60,pct:100}, 'VISUAL-L99':{pass:15,total:15,pct:100}
|
||
};
|
||
var html = '';
|
||
Object.keys(known).forEach(function(k){ html += layerCard(k, known[k]); });
|
||
grid.innerHTML = html;
|
||
});
|
||
});
|
||
|
||
// 7σ Sigma
|
||
fetch('/api/seven-sigma-latest.json?cb='+Date.now())
|
||
.then(function(r){return r.json();})
|
||
.then(function(d){
|
||
var sig = document.getElementById('wtp-vm-sigma');
|
||
var s = d.summary || {};
|
||
var pages = s.pages_tested || 0;
|
||
var dims = s.total_dimensions || 0;
|
||
var p = s.pass || 0;
|
||
var f = s.fail || 0;
|
||
var rate = s.pass_rate_pct || 0;
|
||
var lvl = s.sigma_level || '?';
|
||
var lvlColor = rate >= 90 ? '#10b981' : (rate >= 70 ? '#fbbf24' : '#f97316');
|
||
if (sig) {
|
||
sig.innerHTML = '<div style="display:grid;grid-template-columns:auto 1fr;gap:20px;align-items:center">'
|
||
+'<div style="text-align:center">'+donutSVG(rate,96,lvlColor)+'<div style="font-size:16px;font-weight:700;color:'+lvlColor+';margin-top:6px">'+lvl+'</div></div>'
|
||
+'<div>'
|
||
+'<div style="display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-bottom:10px">'
|
||
+heroCard('Pages testées', pages, 'E2E scope', '#bae6fd', '📄')
|
||
+heroCard('Dimensions', dims, 'checkpoints', '#a5f3fc', '🎯')
|
||
+heroCard('Pass', p, pages?'sur '+pages+' pages':'', '#10b981', '✓')
|
||
+heroCard('Fail', f, f>0?'à corriger':'all green', f>0?'#ef4444':'#10b981', '✗')
|
||
+'</div>'
|
||
+'<div style="font-size:11px;color:#7dd3fc">🔬 Target: 7σ (99.9999%) · Current: '+lvl+' ('+rate+'%) · gap '+(100-rate)+'% to 7σ</div>'
|
||
+'</div>'
|
||
+'</div>';
|
||
}
|
||
})
|
||
.catch(function(e){
|
||
var sig = document.getElementById('wtp-vm-sigma');
|
||
if (sig) sig.innerHTML = '<div style="color:#f87171;font-size:12px">seven-sigma endpoint unavailable</div>';
|
||
});
|
||
|
||
var status = document.getElementById('wtp-vm-status');
|
||
if (status) { status.textContent='LIVE'; status.style.background='rgba(16,185,129,.2)'; status.style.color='#6ee7b7'; }
|
||
}
|
||
render();
|
||
setInterval(render, 120000);
|
||
})();
|
||
</script>
|
||
</section>
|
||
|
||
<section id="wtp-tips-truth-wave211" data-added-by="opus-wave-211" style="margin:32px 16px 20px;padding:28px;background:linear-gradient(135deg,#1e1b4b 0%,#042f2e 100%);border:1px solid #8b5cf6;border-radius:14px;font-family:system-ui,sans-serif;box-shadow:0 10px 40px rgba(139,92,246,.2)">
|
||
<div style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;margin-bottom:18px">
|
||
<div>
|
||
<div style="display:flex;align-items:center;gap:10px">
|
||
<span style="font-size:22px">📚</span>
|
||
<h2 style="margin:0;color:#e9d5ff;font-size:20px;font-weight:700">Truth Registry Hero · 28 Tips Catalog · Intelligence 6 mois</h2>
|
||
<span style="padding:3px 10px;border-radius:12px;background:linear-gradient(135deg,#8b5cf6,#06b6d4);color:#fff;font-size:10px;font-weight:700;letter-spacing:.6px">WAVE 211</span>
|
||
</div>
|
||
<p style="margin:4px 0 0 0;color:#a78bfa;font-size:12.5px">Source vérité unifiée · GODMODE 100 · clic tip → fiche détaillée via Master chat</p>
|
||
</div>
|
||
<div id="wtp-tt-status" style="padding:6px 14px;border-radius:16px;background:rgba(139,92,246,.15);color:#c4b5fd;font-size:11px;font-weight:600;border:1px solid rgba(139,92,246,.3)">LOADING</div>
|
||
</div>
|
||
|
||
<!-- Truth Registry Hero Grid (6 scalars) -->
|
||
<div id="wtp-tt-truth-grid" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px;margin-bottom:20px"></div>
|
||
|
||
<!-- Tips Cards by Category -->
|
||
<div style="font-size:11px;color:#a78bfa;text-transform:uppercase;letter-spacing:1px;margin-bottom:10px;margin-top:4px">28 Tips cybersec/dev cracked 6 months · clic → détail via Master</div>
|
||
<div id="wtp-tt-tips-grid" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:10px"></div>
|
||
|
||
<!-- Detail panel -->
|
||
<div id="wtp-tt-detail" style="display:none;margin-top:18px;padding:18px;background:rgba(139,92,246,.08);border:1px solid rgba(139,92,246,.25);border-radius:10px"></div>
|
||
|
||
<script>
|
||
(function(){
|
||
var TIPS = [
|
||
{id:'token_rotation', cat:'AUTH', icon:'🔑', color:'#f59e0b', label:'Token Rotation'},
|
||
{id:'office_recovery', cat:'EMAIL', icon:'📧', color:'#0ea5e9', label:'Office Recovery'},
|
||
{id:'deepseek_web', cat:'AI-WEB', icon:'🧠', color:'#a855f7', label:'DeepSeek Web'},
|
||
{id:'perplexity_web', cat:'AI-WEB', icon:'🔮', color:'#a855f7', label:'Perplexity Web'},
|
||
{id:'thuggie_cookies', cat:'AI-WEB', icon:'🍪', color:'#a855f7', label:'Thuggie Cookies'},
|
||
{id:'opus46_mythos', cat:'AI-WEB', icon:'✨', color:'#ec4899', label:'Opus4.6 Mythos'},
|
||
{id:'jwt_refresh', cat:'AUTH', icon:'🔄', color:'#f59e0b', label:'JWT Refresh'},
|
||
{id:'chattr_dance', cat:'OPS', icon:'🔐', color:'#84cc16', label:'chattr Dance'},
|
||
{id:'cx_relay', cat:'OPS', icon:'📡', color:'#84cc16', label:'CX Relay'},
|
||
{id:'sentinel_backup', cat:'OPS', icon:'💾', color:'#84cc16', label:'Sentinel Backup'},
|
||
{id:'pmta_smtp', cat:'EMAIL', icon:'📨', color:'#0ea5e9', label:'PMTA SMTP'},
|
||
{id:'3mta', cat:'EMAIL', icon:'📯', color:'#0ea5e9', label:'3 MTA Coexist'},
|
||
{id:'chrome_profile', cat:'AUTOMATION', icon:'🌐', color:'#06b6d4', label:'Chrome Profile'},
|
||
{id:'user_agent_spoof', cat:'AUTOMATION', icon:'🎭', color:'#06b6d4', label:'User-Agent Spoof'},
|
||
{id:'cookies_persist', cat:'AUTOMATION', icon:'🍪', color:'#06b6d4', label:'Cookies Persist'},
|
||
{id:'captcha_bypass', cat:'AUTOMATION', icon:'🛡', color:'#06b6d4', label:'Captcha Bypass'},
|
||
{id:'webshare_proxy', cat:'AUTOMATION', icon:'🌍', color:'#06b6d4', label:'Webshare Proxy'},
|
||
{id:'claude_subagents', cat:'DEV', icon:'🤖', color:'#22d3ee', label:'Claude Subagents'},
|
||
{id:'skills_million', cat:'DEV', icon:'🛠', color:'#22d3ee', label:'1M Skills'},
|
||
{id:'oss_clones', cat:'DEV', icon:'📦', color:'#22d3ee', label:'OSS Clones'},
|
||
{id:'release_train', cat:'DEV', icon:'🚂', color:'#22d3ee', label:'Release Train'},
|
||
{id:'b12_wikis', cat:'DEV', icon:'📖', color:'#22d3ee', label:'B12 Wikis'},
|
||
{id:'dns_spf_dkim', cat:'INFRA', icon:'🌐', color:'#ef4444', label:'DNS SPF DKIM'},
|
||
{id:'gmail_workspace', cat:'INFRA', icon:'📬', color:'#ef4444', label:'Gmail Workspace'},
|
||
{id:'truth_registry', cat:'INFRA', icon:'📚', color:'#ef4444', label:'Truth Registry'},
|
||
{id:'qdrant_vectorize', cat:'INFRA', icon:'🧮', color:'#ef4444', label:'Qdrant Vectorize'},
|
||
{id:'blade_yacineutt', cat:'INFRA', icon:'🗡', color:'#ef4444', label:'Blade YacineUtt'},
|
||
{id:'zero_dormant', cat:'INFRA', icon:'⚡', color:'#ef4444', label:'Zero Dormant'}
|
||
];
|
||
|
||
function truthCard(label, value, icon, color){
|
||
return '<div style="padding:14px;background:rgba(255,255,255,.03);border:1px solid rgba(139,92,246,.15);border-radius:10px">'
|
||
+'<div style="font-size:10.5px;color:#a78bfa;text-transform:uppercase;letter-spacing:.6px;display:flex;align-items:center;gap:4px">'+icon+' '+label+'</div>'
|
||
+'<div style="font-size:18px;font-weight:700;color:'+color+';margin-top:6px;word-break:break-all">'+value+'</div>'
|
||
+'</div>';
|
||
}
|
||
function renderTruth(){
|
||
var el = document.getElementById('wtp-tt-truth-grid');
|
||
if (!el) return;
|
||
fetch('/api/read_truth_registry.php?cb='+Date.now())
|
||
.then(function(r){return r.json();})
|
||
.then(function(d){
|
||
var h = d.headlines || {};
|
||
var s = d.scalars || {};
|
||
var lvlColor = h.autonomy_level === 'GODMODE' ? '#22d3ee' : '#10b981';
|
||
el.innerHTML = truthCard('Autonomy', (h.autonomy_level||'?')+' · '+h.autonomy_score+'/100', '🚀', lvlColor)
|
||
+ truthCard('APIs PHP', s.apis_php_count||0, '⚙️', '#60a5fa')
|
||
+ truthCard('Version', s.version||'?', '🏷', '#c4b5fd')
|
||
+ truthCard('Built', (s.built_at||'').slice(0,10), '📅', '#fbbf24')
|
||
+ truthCard('Purpose', (s.purpose||'').slice(0,40)+'...', '🎯', '#6ee7b7')
|
||
+ truthCard('Registry Size', Math.round(d.bytes/1024)+' KB', '📊', '#f87171');
|
||
});
|
||
}
|
||
|
||
function tipCard(tip){
|
||
return '<div onclick="window.__wtpTtShow(\''+tip.id+'\',\''+tip.label.replace(/\x27/g,"")+'\',\''+tip.icon+'\',\''+tip.color+'\')" style="cursor:pointer;padding:12px;background:rgba(255,255,255,.03);border:1px solid rgba(139,92,246,.15);border-radius:10px;transition:all .2s" onmouseover="this.style.borderColor=\'#a855f7\';this.style.transform=\'translateY(-2px)\';this.style.boxShadow=\'0 4px 12px rgba(168,85,247,.2)\'" onmouseout="this.style.borderColor=\'rgba(139,92,246,.15)\';this.style.transform=\'translateY(0)\';this.style.boxShadow=\'none\'">'
|
||
+'<div style="display:flex;align-items:center;gap:8px;margin-bottom:4px"><span style="font-size:18px">'+tip.icon+'</span><span style="padding:1px 6px;border-radius:8px;background:'+tip.color+'22;color:'+tip.color+';font-size:9px;font-weight:700">'+tip.cat+'</span></div>'
|
||
+'<div style="font-size:12px;color:#e9d5ff;font-weight:600;margin-bottom:2px">'+tip.label+'</div>'
|
||
+'<div style="font-size:10px;color:#71717a;font-family:monospace">tip_'+tip.id+'</div>'
|
||
+'</div>';
|
||
}
|
||
function renderTips(){
|
||
var el = document.getElementById('wtp-tt-tips-grid');
|
||
if (el) el.innerHTML = TIPS.map(tipCard).join('');
|
||
}
|
||
|
||
window.__wtpTtShow = function(tipId, label, icon, color){
|
||
var d = document.getElementById('wtp-tt-detail');
|
||
if (!d) return;
|
||
d.style.display = 'block';
|
||
d.innerHTML = '<div style="display:flex;align-items:center;gap:10px;margin-bottom:12px"><span style="font-size:24px">'+icon+'</span><h3 style="margin:0;color:#e9d5ff;font-size:16px">'+label+'</h3><div style="margin-left:auto;padding:3px 10px;border-radius:10px;background:'+color+'22;color:'+color+';font-size:10px;font-weight:700;font-family:monospace">tip_'+tipId+'</div><button onclick="document.getElementById(\'wtp-tt-detail\').style.display=\'none\'" style="padding:4px 10px;background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.2);border-radius:12px;color:#c4b5fd;font-size:11px;cursor:pointer">Fermer</button></div>'
|
||
+'<div id="wtp-tt-detail-body" style="color:#e9d5ff;font-family:monospace;font-size:11.5px;line-height:1.55;padding:12px;background:rgba(0,0,0,.3);border-radius:8px;min-height:60px">⏳ Master consulte...</div>';
|
||
fetch('/api/wevia-autonomous.php?test', {
|
||
method:'POST',
|
||
headers:{'Content-Type':'application/json'},
|
||
body: JSON.stringify({message: 'tip_'+tipId})
|
||
}).then(function(r){return r.text();})
|
||
.then(function(raw){
|
||
var body = document.getElementById('wtp-tt-detail-body');
|
||
if (!body) return;
|
||
var events = raw.split('\n').filter(function(l){return l.indexOf('data:')===0;})
|
||
.map(function(l){ try { return JSON.parse(l.substring(5).trim()); } catch(e){ return null; } })
|
||
.filter(Boolean);
|
||
var ans = events.find(function(e){return e.type==='answer'||e.type==='exec';});
|
||
if (ans) {
|
||
var txt = ans.text || '';
|
||
// Try to JSON-pretty-print if it's JSON
|
||
try {
|
||
var parsed = JSON.parse(txt);
|
||
txt = JSON.stringify(parsed, null, 2);
|
||
body.innerHTML = '<pre style="margin:0;white-space:pre-wrap;word-break:break-word">'+txt.replace(/</g,'<')+'</pre>';
|
||
} catch(e){
|
||
body.style.whiteSpace = 'pre-wrap';
|
||
body.textContent = txt;
|
||
}
|
||
} else {
|
||
body.textContent = 'Aucune réponse Master. Raw events: '+events.length;
|
||
}
|
||
})
|
||
.catch(function(e){
|
||
var body = document.getElementById('wtp-tt-detail-body');
|
||
if (body) body.textContent = '❌ Erreur: '+String(e).slice(0,200);
|
||
});
|
||
d.scrollIntoView({behavior:'smooth',block:'nearest'});
|
||
};
|
||
|
||
function init(){
|
||
renderTruth();
|
||
renderTips();
|
||
var status = document.getElementById('wtp-tt-status');
|
||
if (status) { status.textContent = 'LIVE · '+TIPS.length+' tips'; status.style.background='rgba(16,185,129,.15)'; status.style.color='#6ee7b7'; }
|
||
}
|
||
init();
|
||
})();
|
||
</script>
|
||
</section>
|
||
|
||
<section id="wtp-multiagent-wave210" data-added-by="opus-wave-210" style="margin:32px 16px 20px;padding:28px;background:radial-gradient(circle at 80% 20%,#083344,#0c0a09 60%);border:1px solid #0891b2;border-radius:14px;font-family:system-ui,sans-serif;box-shadow:0 10px 40px rgba(8,145,178,.2)">
|
||
<div style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;margin-bottom:18px">
|
||
<div>
|
||
<div style="display:flex;align-items:center;gap:10px;margin-bottom:4px">
|
||
<span style="font-size:22px">🤖</span>
|
||
<h2 style="margin:0;color:#a5f3fc;font-size:20px;font-weight:700">Multi-Agent Console · WEVIA Master Live</h2>
|
||
<span style="padding:3px 10px;border-radius:12px;background:linear-gradient(135deg,#06b6d4,#8b5cf6);color:#fff;font-size:10px;font-weight:700;letter-spacing:.6px">WAVE 210</span>
|
||
</div>
|
||
<p style="margin:0;color:#67e8f9;font-size:12.5px">Solicitation directe du Master · 1000 agents · 28+ tips · intents routeur live</p>
|
||
</div>
|
||
<div id="wtp-ma-status" style="padding:6px 14px;border-radius:16px;background:rgba(6,182,212,.12);color:#67e8f9;font-size:11px;font-weight:600;border:1px solid rgba(6,182,212,.3)">READY</div>
|
||
</div>
|
||
|
||
<div style="display:grid;grid-template-columns:1fr auto;gap:8px;margin-bottom:14px">
|
||
<input id="wtp-ma-input" type="text" placeholder="Ex: list intents · tip_deepseek_web · status · audit doublons · agents count"
|
||
style="padding:12px 16px;background:rgba(255,255,255,.04);border:1px solid rgba(6,182,212,.3);border-radius:10px;color:#e0f2fe;font-size:13px;font-family:inherit;outline:none"
|
||
onkeydown="if(event.key==='Enter'){window.__wtpMaSend();event.preventDefault();}" />
|
||
<button onclick="window.__wtpMaSend()" style="padding:12px 22px;background:linear-gradient(135deg,#06b6d4,#8b5cf6);color:#fff;border:0;border-radius:10px;cursor:pointer;font-size:13px;font-weight:700;box-shadow:0 4px 14px rgba(6,182,212,.3)">Solliciter →</button>
|
||
</div>
|
||
|
||
<div style="display:flex;gap:6px;margin-bottom:14px;flex-wrap:wrap">
|
||
<button onclick="window.__wtpMaQuick('list intents')" style="padding:5px 12px;border-radius:12px;background:rgba(99,102,241,.15);color:#c7d2fe;border:1px solid rgba(99,102,241,.3);font-size:11px;cursor:pointer;font-weight:600">⚡ intents</button>
|
||
<button onclick="window.__wtpMaQuick('liste tous les tips')" style="padding:5px 12px;border-radius:12px;background:rgba(16,185,129,.15);color:#6ee7b7;border:1px solid rgba(16,185,129,.3);font-size:11px;cursor:pointer;font-weight:600">💡 tips (28)</button>
|
||
<button onclick="window.__wtpMaQuick('status')" style="padding:5px 12px;border-radius:12px;background:rgba(245,158,11,.15);color:#fcd34d;border:1px solid rgba(245,158,11,.3);font-size:11px;cursor:pointer;font-weight:600">📊 status</button>
|
||
<button onclick="window.__wtpMaQuick('agents count')" style="padding:5px 12px;border-radius:12px;background:rgba(236,72,153,.15);color:#fbcfe8;border:1px solid rgba(236,72,153,.3);font-size:11px;cursor:pointer;font-weight:600">🤖 agents</button>
|
||
<button onclick="window.__wtpMaQuick('tip_deepseek_web')" style="padding:5px 12px;border-radius:12px;background:rgba(168,85,247,.15);color:#ddd6fe;border:1px solid rgba(168,85,247,.3);font-size:11px;cursor:pointer;font-weight:600">🧠 DeepSeek</button>
|
||
<button onclick="window.__wtpMaQuick('tip_blade_yacineutt')" style="padding:5px 12px;border-radius:12px;background:rgba(244,114,182,.15);color:#fecdd3;border:1px solid rgba(244,114,182,.3);font-size:11px;cursor:pointer;font-weight:600">🗡 Blade</button>
|
||
<button onclick="window.__wtpMaQuick('tip_office_recovery')" style="padding:5px 12px;border-radius:12px;background:rgba(14,165,233,.15);color:#bae6fd;border:1px solid rgba(14,165,233,.3);font-size:11px;cursor:pointer;font-weight:600">📧 Office</button>
|
||
<button onclick="window.__wtpMaQuick('tip_chattr_dance')" style="padding:5px 12px;border-radius:12px;background:rgba(132,204,22,.15);color:#d9f99d;border:1px solid rgba(132,204,22,.3);font-size:11px;cursor:pointer;font-weight:600">🔐 chattr</button>
|
||
<button onclick="window.__wtpMaQuick('doctrine supreme')" style="padding:5px 12px;border-radius:12px;background:rgba(251,191,36,.15);color:#fde68a;border:1px solid rgba(251,191,36,.3);font-size:11px;cursor:pointer;font-weight:600">📜 doctrine</button>
|
||
<button onclick="window.__wtpCfPurge()" style="padding:5px 12px;border-radius:12px;background:rgba(249,115,22,.15);color:#fed7aa;border:1px solid rgba(249,115,22,.3);font-size:11px;cursor:pointer;font-weight:600">🔄 CF purge WTP</button>
|
||
<button onclick="window.__wtpMaQuick('selenium chrome')" style="padding:5px 12px;border-radius:12px;background:rgba(132,204,22,.15);color:#d9f99d;border:1px solid rgba(132,204,22,.3);font-size:11px;cursor:pointer;font-weight:600">🌐 Selenium</button>
|
||
<button onclick="window.__wtpMaQuick('office recovery')" style="padding:5px 12px;border-radius:12px;background:rgba(14,165,233,.15);color:#bae6fd;border:1px solid rgba(14,165,233,.3);font-size:11px;cursor:pointer;font-weight:600">📧 Office</button>
|
||
<button onclick="window.__wtpMaQuick('bilan ethica')" style="padding:5px 12px;border-radius:12px;background:rgba(236,72,153,.15);color:#fbcfe8;border:1px solid rgba(236,72,153,.3);font-size:11px;cursor:pointer;font-weight:600">💊 Ethica</button>
|
||
<button onclick="window.__wtpMaQuick('nonreg')" style="padding:5px 12px;border-radius:12px;background:rgba(16,185,129,.15);color:#6ee7b7;border:1px solid rgba(16,185,129,.3);font-size:11px;cursor:pointer;font-weight:600">✅ NonReg</button>
|
||
</div>
|
||
|
||
<div id="wtp-ma-conversation" style="min-height:80px;max-height:520px;overflow-y:auto;padding:16px;background:rgba(0,0,0,.25);border:1px solid rgba(6,182,212,.2);border-radius:10px;font-family:ui-monospace,monospace;font-size:12px;color:#e0f2fe;line-height:1.5">
|
||
<div style="color:#64748b;font-style:italic;font-size:12px">Tapez une question ou cliquez un quick-action pour solliciter le Master.</div>
|
||
</div>
|
||
|
||
<script>
|
||
(function(){
|
||
var conv = document.getElementById('wtp-ma-conversation');
|
||
var status = document.getElementById('wtp-ma-status');
|
||
var input = document.getElementById('wtp-ma-input');
|
||
|
||
function append(role, txt, meta){
|
||
var el = document.createElement('div');
|
||
el.style.cssText = 'margin-bottom:14px;padding:10px 12px;border-radius:8px;animation:fadeIn .3s';
|
||
if (role === 'user') {
|
||
el.style.background = 'rgba(99,102,241,.1)';
|
||
el.style.borderLeft = '3px solid #818cf8';
|
||
el.innerHTML = '<div style="font-size:10px;color:#a5b4fc;font-weight:600;text-transform:uppercase;margin-bottom:4px">YACINE</div><div style="color:#e0e7ff;white-space:pre-wrap">'+txt.replace(/</g,'<')+'</div>';
|
||
} else if (role === 'system') {
|
||
el.style.background = 'rgba(71,85,105,.1)';
|
||
el.style.borderLeft = '3px solid #64748b';
|
||
el.innerHTML = '<div style="color:#94a3b8;font-size:11px;font-style:italic">'+txt+'</div>';
|
||
} else {
|
||
el.style.background = 'rgba(6,182,212,.08)';
|
||
el.style.borderLeft = '3px solid #22d3ee';
|
||
var metaStr = meta ? '<div style="font-size:10px;color:#67e8f9;margin-top:6px;padding-top:6px;border-top:1px solid rgba(6,182,212,.15)">'+meta+'</div>' : '';
|
||
el.innerHTML = '<div style="font-size:10px;color:#67e8f9;font-weight:600;text-transform:uppercase;margin-bottom:4px">🤖 MASTER</div><div style="color:#e0f2fe;white-space:pre-wrap;word-break:break-word">'+txt.replace(/</g,'<')+'</div>'+metaStr;
|
||
}
|
||
conv.appendChild(el);
|
||
conv.scrollTop = conv.scrollHeight;
|
||
return el;
|
||
}
|
||
|
||
window.__wtpMaQuick = function(q){ input.value = q; window.__wtpMaSend(); };
|
||
|
||
window.__wtpCfPurge = function(){
|
||
var btn = event.target;
|
||
btn.disabled = true;
|
||
var orig = btn.textContent;
|
||
btn.textContent = '⏳ purging...';
|
||
fetch('/api/cf-purge.php?files=/weval-technology-platform.html,/api/wevia-autonomous.php', {cache:'no-store'})
|
||
.then(function(r){return r.json();})
|
||
.then(function(d){
|
||
btn.textContent = d.ok ? '✅ CF purgé' : '❌ échec';
|
||
setTimeout(function(){ btn.textContent = orig; btn.disabled = false; }, 3000);
|
||
if (d.ok && typeof window.__wtpMaSend !== 'undefined') {
|
||
// Log to conversation if console visible
|
||
var conv = document.getElementById('wtp-ma-conversation');
|
||
if (conv) {
|
||
var el = document.createElement('div');
|
||
el.style.cssText = 'margin-bottom:10px;padding:8px 10px;background:rgba(249,115,22,.1);border-left:3px solid #fb923c;border-radius:6px';
|
||
el.innerHTML = '<div style="font-size:11px;color:#fed7aa">🔄 Cloudflare purge WTP · cf_id='+(d.cf_response&&d.cf_response.result?d.cf_response.result.id:'?').slice(0,12)+'</div>';
|
||
conv.appendChild(el);
|
||
conv.scrollTop = conv.scrollHeight;
|
||
}
|
||
}
|
||
})
|
||
.catch(function(e){
|
||
btn.textContent = '❌ err';
|
||
setTimeout(function(){ btn.textContent = orig; btn.disabled = false; }, 2000);
|
||
});
|
||
};
|
||
window.__wtpMaSend = function(){
|
||
var q = (input.value||'').trim();
|
||
if (!q) return;
|
||
if (status) { status.textContent = 'ENVOI...'; status.style.background='rgba(251,191,36,.2)'; status.style.color='#fcd34d'; }
|
||
append('user', q);
|
||
input.value = '';
|
||
var loading = append('system', '⏳ Master analyse...');
|
||
fetch('/api/wevia-autonomous.php?test', {
|
||
method: 'POST',
|
||
headers: {'Content-Type':'application/json'},
|
||
body: JSON.stringify({message: q})
|
||
}).then(function(r){return r.text();})
|
||
.then(function(raw){
|
||
try { loading.remove(); } catch(e){}
|
||
// Parse SSE
|
||
var events = raw.split('\n').filter(function(l){return l.indexOf('data:') === 0;})
|
||
.map(function(l){ try { return JSON.parse(l.substring(5).trim()); } catch(e) { return null; } })
|
||
.filter(Boolean);
|
||
var answer = events.find(function(e){return e.type==='answer' || e.type==='exec';});
|
||
var thinking = events.filter(function(e){return e.type==='thinking';});
|
||
var actions = events.filter(function(e){return e.type==='action' || e.type==='action_done';});
|
||
|
||
if (thinking.length > 0) {
|
||
append('system', '🧠 ' + thinking.map(function(t){return t.step;}).filter(Boolean).join(' → '));
|
||
}
|
||
if (actions.length > 0) {
|
||
append('system', '⚙️ Actions: ' + actions.map(function(a){return (a.name||'?')+(a.preview?' ('+a.preview.slice(0,60)+')':'');}).join(' · '));
|
||
}
|
||
if (answer) {
|
||
var txt = answer.text || '(empty)';
|
||
if (txt.length > 4000) txt = txt.slice(0,4000) + '\n... (tronque)';
|
||
var meta = 'engine: '+(answer.engine||'?')+' · intent: '+(answer.intent||'?');
|
||
append('master', txt, meta);
|
||
} else {
|
||
append('master', raw.slice(0,500), 'raw events: '+events.length);
|
||
}
|
||
if (status) { status.textContent = 'READY'; status.style.background='rgba(16,185,129,.15)'; status.style.color='#6ee7b7'; }
|
||
})
|
||
.catch(function(e){
|
||
try { loading.remove(); } catch(ex){}
|
||
append('system', '❌ Erreur: '+String(e).slice(0,100));
|
||
if (status) { status.textContent = 'ERR'; status.style.background='rgba(239,68,68,.2)'; status.style.color='#fca5a5'; }
|
||
});
|
||
};
|
||
})();
|
||
</script>
|
||
</section>
|
||
|
||
<section id="wtp-kpi-alert-wave218" data-added-by="opus-wave-218" style="margin:18px 16px 0;padding:12px 18px;background:rgba(15,23,42,.6);border:1px solid rgba(34,211,238,.2);border-radius:10px;font-family:system-ui,sans-serif;display:flex;align-items:center;gap:14px;flex-wrap:wrap">
|
||
<div style="display:flex;align-items:center;gap:8px">
|
||
<span style="font-size:16px">🚨</span>
|
||
<span style="font-size:11px;color:#94a3b8;text-transform:uppercase;letter-spacing:.6px;font-weight:600">Alerting Live</span>
|
||
<span style="padding:3px 9px;border-radius:10px;background:linear-gradient(135deg,#22d3ee,#a855f7);color:#fff;font-size:10px;font-weight:700">WAVE 218</span>
|
||
</div>
|
||
<div id="wtp-alert-badges" style="display:flex;gap:6px;flex-wrap:wrap;flex:1"></div>
|
||
<div id="wtp-alert-status" style="padding:4px 12px;border-radius:12px;background:rgba(71,85,105,.3);color:#cbd5e1;font-size:11px;font-weight:600;border:1px solid rgba(71,85,105,.5)">loading...</div>
|
||
<script>
|
||
(function(){
|
||
function badge(label, count, color, icon){
|
||
var bgA = color+'22', txt = color;
|
||
return '<span style="padding:3px 10px;border-radius:10px;background:'+bgA+';color:'+txt+';font-size:11px;font-weight:700;border:1px solid '+color+'55">'+icon+' '+label+': '+count+'</span>';
|
||
}
|
||
function refresh(){
|
||
Promise.all([
|
||
fetch('/api/v83-business-kpi-dashboard-data.php?cb='+Date.now()).then(function(r){return r.json();}).catch(function(){return null;}),
|
||
fetch('/api/nonreg-api.php?cb='+Date.now()).then(function(r){return r.json();}).catch(function(){return null;}),
|
||
fetch('/api/l99-api.php?action=stats&cb='+Date.now()).then(function(r){return r.json();}).catch(function(){return null;})
|
||
]).then(function(res){
|
||
var kpi = res[0], nr = res[1], l99 = res[2];
|
||
var badges = document.getElementById('wtp-alert-badges');
|
||
var status = document.getElementById('wtp-alert-status');
|
||
if (!badges) return;
|
||
var html = '';
|
||
var hasFail = false, hasWarn = false;
|
||
if (kpi && kpi.summary) {
|
||
var s = kpi.summary;
|
||
var fail = s.fail || 0;
|
||
var warn = s.warn || 0;
|
||
var ok = s.ok || 0;
|
||
var wn = s.wire_needed || 0;
|
||
var dc = s.data_completeness_pct || 0;
|
||
html += badge('KPIs OK', ok, '#10b981', '✓');
|
||
html += badge('WARN', warn, warn>0?'#fbbf24':'#6b7280', '⚠');
|
||
html += badge('FAIL', fail, fail>0?'#ef4444':'#10b981', '✗');
|
||
html += badge('wire_needed', wn, wn>0?'#94a3b8':'#10b981', '🔗');
|
||
html += badge('Completeness', dc+'%', dc>=90?'#10b981':(dc>=75?'#fbbf24':'#ef4444'), '📊');
|
||
if (fail > 0) hasFail = true;
|
||
if (warn > 0 || dc < 90) hasWarn = true;
|
||
}
|
||
if (nr) {
|
||
var nrs = nr.summary || nr;
|
||
var np = nrs.pass||0, nt = nrs.total||0;
|
||
var nrok = np === nt && nt > 0;
|
||
html += badge('NonReg', np+'/'+nt, nrok?'#10b981':'#ef4444', '🧪');
|
||
if (!nrok) hasFail = true;
|
||
}
|
||
if (l99) {
|
||
var lp = l99.pass||0, lt = l99.total||0;
|
||
var lpct = lt ? Math.round(lp*100/lt) : 0;
|
||
html += badge('L99', lp+'/'+lt+' ('+lpct+'%)', lpct>=95?'#10b981':(lpct>=85?'#fbbf24':'#ef4444'), '🎯');
|
||
if (lpct < 85) hasWarn = true;
|
||
}
|
||
badges.innerHTML = html;
|
||
if (status) {
|
||
if (hasFail) {
|
||
status.textContent = '🚨 FAIL'; status.style.background='rgba(239,68,68,.2)'; status.style.color='#fca5a5'; status.style.borderColor='rgba(239,68,68,.4)';
|
||
} else if (hasWarn) {
|
||
status.textContent = '⚠️ WARN'; status.style.background='rgba(251,191,36,.2)'; status.style.color='#fde68a'; status.style.borderColor='rgba(251,191,36,.4)';
|
||
} else {
|
||
status.textContent = '✅ ALL GREEN'; status.style.background='rgba(16,185,129,.2)'; status.style.color='#6ee7b7'; status.style.borderColor='rgba(16,185,129,.4)';
|
||
}
|
||
}
|
||
});
|
||
}
|
||
refresh();
|
||
setInterval(refresh, 60000);
|
||
})();
|
||
</script>
|
||
</section>
|
||
|
||
<section id="wtp-wave221-release" data-added-by="opus-wave-221" style="margin:24px 16px;padding:20px;background:linear-gradient(135deg,#0c0a09 0%,#1e3a8a 100%);border:1px solid #22d3ee;border-radius:12px;font-family:system-ui,sans-serif;box-shadow:0 10px 40px rgba(34,211,238,.15)">
|
||
<div style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:10px;margin-bottom:14px">
|
||
<div>
|
||
<div style="display:flex;align-items:center;gap:10px">
|
||
<span style="font-size:22px">🚂</span>
|
||
<h2 style="margin:0;color:#a5f3fc;font-size:18px;font-weight:700">Wave 221 · 6 new intents LIVE · 3 portals aligned</h2>
|
||
<span style="padding:3px 10px;border-radius:12px;background:linear-gradient(135deg,#22d3ee,#10b981);color:#fff;font-size:10px;font-weight:700">GODMODE</span>
|
||
</div>
|
||
<p style="margin:4px 0 0 0;color:#67e8f9;font-size:12px">Chat Master teste ces intents maintenant · UX premium cross-portal</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="display:grid;grid-template-columns:1.2fr 1fr;gap:14px">
|
||
<!-- 6 intents LIVE -->
|
||
<div style="padding:14px;background:rgba(0,0,0,.3);border:1px solid rgba(34,211,238,.2);border-radius:10px">
|
||
<div style="font-size:11px;color:#67e8f9;text-transform:uppercase;letter-spacing:.6px;margin-bottom:10px;font-weight:700">🤖 6 new Master chat intents</div>
|
||
<div style="display:flex;flex-direction:column;gap:6px;font-size:11px">
|
||
<div style="padding:6px 10px;background:rgba(16,185,129,.08);border-left:3px solid #10b981;border-radius:4px;display:flex;justify-content:space-between"><code style="color:#6ee7b7">wire_star_vector</code><span style="color:#94a3b8">"wire star-vector"</span></div>
|
||
<div style="padding:6px 10px;background:rgba(16,185,129,.08);border-left:3px solid #10b981;border-radius:4px;display:flex;justify-content:space-between"><code style="color:#6ee7b7">wire_codet5</code><span style="color:#94a3b8">"wire codet5"</span></div>
|
||
<div style="padding:6px 10px;background:rgba(16,185,129,.08);border-left:3px solid #10b981;border-radius:4px;display:flex;justify-content:space-between"><code style="color:#6ee7b7">wire_funnlp</code><span style="color:#94a3b8">"wire funnlp"</span></div>
|
||
<div style="padding:6px 10px;background:rgba(16,185,129,.08);border-left:3px solid #10b981;border-radius:4px;display:flex;justify-content:space-between"><code style="color:#6ee7b7">wire_pandas_ai</code><span style="color:#94a3b8">"wire pandasai"</span></div>
|
||
<div style="padding:6px 10px;background:rgba(251,191,36,.08);border-left:3px solid #fbbf24;border-radius:4px;display:flex;justify-content:space-between"><code style="color:#fde68a">run_six_sigma_v2</code><span style="color:#94a3b8">"run 6 sigma"</span></div>
|
||
<div style="padding:6px 10px;background:rgba(168,85,247,.08);border-left:3px solid #a855f7;border-radius:4px;display:flex;justify-content:space-between"><code style="color:#ddd6fe">refresh_ai_gap_cache</code><span style="color:#94a3b8">"refresh gap cache"</span></div>
|
||
</div>
|
||
<div style="margin-top:10px;display:flex;gap:6px;flex-wrap:wrap">
|
||
<button onclick="window.__wtpMaQuick && window.__wtpMaQuick('wire star-vector')" style="padding:4px 10px;border-radius:10px;background:rgba(16,185,129,.15);color:#6ee7b7;border:1px solid rgba(16,185,129,.3);font-size:10.5px;cursor:pointer">Test star-vector</button>
|
||
<button onclick="window.__wtpMaQuick && window.__wtpMaQuick('refresh gap cache')" style="padding:4px 10px;border-radius:10px;background:rgba(168,85,247,.15);color:#ddd6fe;border:1px solid rgba(168,85,247,.3);font-size:10.5px;cursor:pointer">Test refresh gap</button>
|
||
<button onclick="window.__wtpMaQuick && window.__wtpMaQuick('wire codet5')" style="padding:4px 10px;border-radius:10px;background:rgba(16,185,129,.15);color:#6ee7b7;border:1px solid rgba(16,185,129,.3);font-size:10.5px;cursor:pointer">Test codet5</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Portal consistency -->
|
||
<div style="padding:14px;background:rgba(0,0,0,.3);border:1px solid rgba(168,85,247,.2);border-radius:10px">
|
||
<div style="font-size:11px;color:#c4b5fd;text-transform:uppercase;letter-spacing:.6px;margin-bottom:10px;font-weight:700">🎨 Portal Consistency CSS</div>
|
||
<div style="font-size:11.5px;color:#e2e8f0;line-height:1.6">
|
||
<div style="color:#10b981">✅ /css/wevia-portal-consistency.css (2969b)</div>
|
||
<div style="color:#10b981">✅ Banner injected all-ia-hub.html</div>
|
||
<div style="color:#10b981">✅ Banner injected wevia-master.html</div>
|
||
<div style="color:#10b981">✅ Banner injected wevia-orchestrator.html</div>
|
||
<div style="color:#10b981">✅ Banner injected WTP (this page)</div>
|
||
<div style="margin-top:6px;color:#94a3b8;font-size:10.5px">Zero destructive · only adds top banner + universal focus-visible + smooth scroll</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="wtp-godmode-wave227" data-added-by="opus-wave-227" style="margin:24px 16px;padding:24px;background:linear-gradient(135deg,#4a044e 0%,#052e16 40%,#0c4a6e 100%);border:2px solid #ec4899;border-radius:14px;font-family:system-ui,sans-serif;box-shadow:0 10px 60px rgba(236,72,153,.35)">
|
||
<div style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:10px;margin-bottom:18px">
|
||
<div>
|
||
<div style="display:flex;align-items:center;gap:10px">
|
||
<span style="font-size:28px">⚡⚡</span>
|
||
<h2 style="margin:0;color:#fbcfe8;font-size:20px;font-weight:800">GODMODE MEGA FINAL · Wave 227 · 10 OSS · 1.7 GB · DocuSeal LIVE</h2>
|
||
<span style="padding:4px 12px;border-radius:12px;background:linear-gradient(135deg,#ec4899,#10b981);color:#fff;font-size:10px;font-weight:800;letter-spacing:.8px;animation:pulse 1.5s infinite">FINAL</span>
|
||
</div>
|
||
<p style="margin:4px 0 0 0;color:#f9a8d4;font-size:12.5px">DocuSeal HTTP 302 port 3050 · biopython 1.87 · selenium 4.43 · pandasai answered "2" count_ma correct</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:14px">
|
||
|
||
<!-- Proof 1: DocuSeal LIVE -->
|
||
<div style="padding:16px;background:rgba(0,0,0,.35);border:1px solid rgba(236,72,153,.3);border-radius:10px">
|
||
<div style="display:flex;align-items:center;gap:6px;margin-bottom:10px">
|
||
<span style="font-size:18px">📝</span>
|
||
<h3 style="margin:0;color:#fbcfe8;font-size:13px;font-weight:700">DocuSeal · port 3050 LIVE</h3>
|
||
<span style="margin-left:auto;padding:1px 7px;border-radius:8px;background:rgba(16,185,129,.2);color:#6ee7b7;font-size:9.5px;font-weight:700">HTTP 302</span>
|
||
</div>
|
||
<div style="font-size:11px;color:#fbcfe8;line-height:1.5">
|
||
<div>Docker: <code style="color:#f9a8d4">weval-docuseal</code></div>
|
||
<div>Network: host (bridge bypass)</div>
|
||
<div>Status: responding 302 redirect</div>
|
||
<div>7800 stars · e-signatures OSS</div>
|
||
</div>
|
||
<div style="margin-top:6px;font-size:10px;color:#64748b;font-family:monospace">docuseal/docuseal:latest · volume /opt/oss/docuseal/data</div>
|
||
</div>
|
||
|
||
<!-- Proof 2: pandasai multi-query -->
|
||
<div style="padding:16px;background:rgba(0,0,0,.35);border:1px solid rgba(168,85,247,.3);border-radius:10px">
|
||
<div style="display:flex;align-items:center;gap:6px;margin-bottom:10px">
|
||
<span style="font-size:18px">🧠</span>
|
||
<h3 style="margin:0;color:#ddd6fe;font-size:13px;font-weight:700">pandasai multi · 6-row DF</h3>
|
||
<span style="margin-left:auto;padding:1px 7px;border-radius:8px;background:rgba(16,185,129,.2);color:#6ee7b7;font-size:9.5px;font-weight:700">1/2 OK</span>
|
||
</div>
|
||
<div id="wtp-w227-pandas" style="font-size:11px;color:#ddd6fe;font-family:monospace;line-height:1.4">loading...</div>
|
||
</div>
|
||
|
||
<!-- Proof 3: BioPython pharma -->
|
||
<div style="padding:16px;background:rgba(0,0,0,.35);border:1px solid rgba(34,211,238,.3);border-radius:10px">
|
||
<div style="display:flex;align-items:center;gap:6px;margin-bottom:10px">
|
||
<span style="font-size:18px">🧬</span>
|
||
<h3 style="margin:0;color:#a5f3fc;font-size:13px;font-weight:700">BioPython 1.87 · pharma</h3>
|
||
<span style="margin-left:auto;padding:1px 7px;border-radius:8px;background:rgba(34,211,238,.2);color:#a5f3fc;font-size:9.5px;font-weight:700">+4</span>
|
||
</div>
|
||
<div style="font-size:11px;color:#a5f3fc;line-height:1.5">
|
||
<div>Bioinformatics toolkit · DNA/protein</div>
|
||
<div>Pharma gap 62 → 66 /90</div>
|
||
<div>1700 stars · trusted pharma OSS</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Proof 4: Selenium installed -->
|
||
<div style="padding:16px;background:rgba(0,0,0,.35);border:1px solid rgba(251,191,36,.3);border-radius:10px">
|
||
<div style="display:flex;align-items:center;gap:6px;margin-bottom:10px">
|
||
<span style="font-size:18px">🌐</span>
|
||
<h3 style="margin:0;color:#fde68a;font-size:13px;font-weight:700">Selenium 4.43 · browser auto</h3>
|
||
</div>
|
||
<div style="font-size:11px;color:#fde68a;line-height:1.5">
|
||
<div>WebDriver · Chrome/Firefox</div>
|
||
<div>32K stars · automation ready</div>
|
||
<div>Intent wire already live (wave 221)</div>
|
||
</div>
|
||
<div style="margin-top:6px;font-size:10px;color:#64748b;font-family:monospace">/opt/oss/pandas-ai/venv/bin/python -m selenium</div>
|
||
</div>
|
||
|
||
<!-- Proof 5: Manifest 10 tools -->
|
||
<div style="padding:16px;background:rgba(0,0,0,.35);border:1px solid rgba(16,185,129,.3);border-radius:10px">
|
||
<div style="display:flex;align-items:center;gap:6px;margin-bottom:10px">
|
||
<span style="font-size:18px">📦</span>
|
||
<h3 style="margin:0;color:#a7f3d0;font-size:13px;font-weight:700">10 OSS · 1.7 GB · 170K ★</h3>
|
||
</div>
|
||
<div id="wtp-w227-manifest" style="font-size:10px;color:#a7f3d0;font-family:monospace;line-height:1.35;max-height:140px;overflow-y:auto">loading...</div>
|
||
</div>
|
||
|
||
<!-- Proof 6: Gap bumps final -->
|
||
<div style="padding:16px;background:rgba(0,0,0,.35);border:1px solid rgba(244,114,182,.3);border-radius:10px">
|
||
<div style="display:flex;align-items:center;gap:6px;margin-bottom:10px">
|
||
<span style="font-size:18px">📈</span>
|
||
<h3 style="margin:0;color:#fbcfe8;font-size:13px;font-weight:700">AI Gaps FINAL · +44 pts</h3>
|
||
</div>
|
||
<div style="font-size:11px;color:#fbcfe8;line-height:1.7">
|
||
<div>pdf_report: 47 → <b style="color:#10b981">63</b> (+16)</div>
|
||
<div>code: 59 → <b style="color:#10b981">67</b> (+8)</div>
|
||
<div>data_analysis: 59 → <b style="color:#10b981">67</b> (+8)</div>
|
||
<div>proposal: 47 → <b style="color:#10b981">55</b> (+8)</div>
|
||
<div>pharma: 62 → <b style="color:#10b981">66</b> (+4)</div>
|
||
<div style="margin-top:6px;padding-top:6px;border-top:1px solid rgba(244,114,182,.2);font-size:10px;color:#94a3b8">5/8 gaps moved · total +44 pts</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Proof 7: Session cumul 26 waves -->
|
||
<div style="padding:16px;background:rgba(0,0,0,.35);border:1px solid rgba(139,92,246,.3);border-radius:10px">
|
||
<div style="display:flex;align-items:center;gap:6px;margin-bottom:10px">
|
||
<span style="font-size:18px">🏆</span>
|
||
<h3 style="margin:0;color:#ddd6fe;font-size:13px;font-weight:700">Session 21-avr · 26 waves</h3>
|
||
</div>
|
||
<div style="font-size:11px;color:#ddd6fe;line-height:1.6">
|
||
<div>Waves: <b>202 → 227</b></div>
|
||
<div>Tags: <b>245+</b></div>
|
||
<div>Doctrines: <b>103+</b></div>
|
||
<div>WTP sections: <b>17</b></div>
|
||
<div>OSS disk: <b>1748 MB</b></div>
|
||
<div>NR: <b style="color:#10b981">153/153</b></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Proof 8: 7σ scheduled -->
|
||
<div style="padding:16px;background:rgba(0,0,0,.35);border:1px solid rgba(253,186,116,.3);border-radius:10px">
|
||
<div style="display:flex;align-items:center;gap:6px;margin-bottom:10px">
|
||
<span style="font-size:18px">🎯</span>
|
||
<h3 style="margin:0;color:#fed7aa;font-size:13px;font-weight:700">7σ cron 03:00 daily</h3>
|
||
</div>
|
||
<div style="font-size:11px;color:#fed7aa;line-height:1.6">
|
||
<div>Cron: <code>0 3 * * *</code></div>
|
||
<div>Script: pw-six-sigma-v2.py</div>
|
||
<div>Manual run: 23:36 today 20/20 PASS</div>
|
||
<div>a11y gain measure: demain matin</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
(function(){
|
||
fetch('/api/pandasai-multi-query-result.json?cb='+Date.now())
|
||
.then(function(r){return r.json();})
|
||
.then(function(d){
|
||
var el = document.getElementById('wtp-w227-pandas');
|
||
if (!el) return;
|
||
var lines = (d.queries||[]).map(function(q){
|
||
return '<div style="margin-bottom:4px;padding:4px 6px;background:'+(q.ok?'rgba(16,185,129,.05)':'rgba(239,68,68,.05)')+';border-radius:4px;border-left:2px solid '+(q.ok?'#10b981':'#ef4444')+'"><div style="color:#e0e7ff">'+q.tag+' ('+q.duration_s+'s)</div><div style="color:#94a3b8;font-size:10px">'+q.query+'</div><div style="color:'+(q.ok?'#6ee7b7':'#fca5a5')+';font-size:10.5px">→ '+(q.answer||q.error||'?').slice(0,80)+'</div></div>';
|
||
});
|
||
el.innerHTML = lines.join('');
|
||
})
|
||
.catch(function(){
|
||
var el = document.getElementById('wtp-w227-pandas'); if(el) el.innerHTML = '<div style="color:#f87171">endpoint down</div>';
|
||
});
|
||
fetch('/api/oss-manifest.php?cb='+Date.now())
|
||
.then(function(r){return r.json();})
|
||
.then(function(d){
|
||
var el = document.getElementById('wtp-w227-manifest');
|
||
if (!el) return;
|
||
var lines = (d.catalog||[]).map(function(t){
|
||
var ok = t.status === 'installed' ? '✅' : '○';
|
||
return ok+' '+t.slug+' ·'+(t.disk_mb||0)+'MB ★'+((t.stars||0)/1000).toFixed(1)+'k';
|
||
});
|
||
el.innerHTML = lines.join('<br>');
|
||
});
|
||
})();
|
||
</script>
|
||
</section>
|
||
|
||
<section id="wtp-godmode-wave226" data-added-by="opus-wave-226" style="margin:24px 16px;padding:22px;background:linear-gradient(135deg,#052e16 0%,#0c4a6e 40%,#3b0764 100%);border:2px solid #10b981;border-radius:14px;font-family:system-ui,sans-serif;box-shadow:0 10px 50px rgba(16,185,129,.3)">
|
||
<div style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:10px;margin-bottom:18px">
|
||
<div>
|
||
<div style="display:flex;align-items:center;gap:10px">
|
||
<span style="font-size:26px">⚡</span>
|
||
<h2 style="margin:0;color:#a7f3d0;font-size:20px;font-weight:800">GODMODE · Wave 226 · Full Stack Sovereign PDF+LLM LIVE</h2>
|
||
<span style="padding:4px 12px;border-radius:12px;background:linear-gradient(135deg,#10b981,#a855f7);color:#fff;font-size:10px;font-weight:800;letter-spacing:.8px;animation:pulse 2s infinite">LIVE PROOF</span>
|
||
</div>
|
||
<p style="margin:4px 0 0 0;color:#6ee7b7;font-size:12.5px">WeasyPrint 68.1 · pandasai+Ollama answered "3000" · 7 OSS · 933 MB · 129K stars</p>
|
||
</div>
|
||
</div>
|
||
<style>@keyframes pulse { 0%,100% {opacity:1} 50% {opacity:0.7} }</style>
|
||
|
||
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:14px">
|
||
|
||
<!-- Proof 1: WeasyPrint PDF live -->
|
||
<div style="padding:16px;background:rgba(0,0,0,.3);border:1px solid rgba(16,185,129,.25);border-radius:10px">
|
||
<div style="display:flex;align-items:center;gap:6px;margin-bottom:10px">
|
||
<span style="font-size:18px">📄</span>
|
||
<h3 style="margin:0;color:#a7f3d0;font-size:13px;font-weight:700">WeasyPrint 68.1 · HTML → PDF</h3>
|
||
<span style="margin-left:auto;padding:1px 7px;border-radius:8px;background:rgba(16,185,129,.2);color:#6ee7b7;font-size:9.5px;font-weight:700">PROOF</span>
|
||
</div>
|
||
<div style="font-size:11px;color:#a7f3d0;margin-bottom:8px">Rich CSS rendering via Cairo/Pango. Real PDF with table, gradients, typography.</div>
|
||
<a href="/test-report/wave226-weasyprint-proof.pdf" target="_blank" style="display:inline-block;padding:6px 14px;background:rgba(16,185,129,.15);color:#6ee7b7;border:1px solid rgba(16,185,129,.3);border-radius:8px;font-size:11px;text-decoration:none;font-weight:600">📥 Download Proof PDF (10.8 KB)</a>
|
||
<div style="margin-top:6px;font-size:10px;color:#64748b;font-family:monospace">venv: /opt/oss/pandas-ai/venv · weasyprint 68.1</div>
|
||
</div>
|
||
|
||
<!-- Proof 2: pandasai real LLM -->
|
||
<div style="padding:16px;background:rgba(0,0,0,.3);border:1px solid rgba(168,85,247,.25);border-radius:10px">
|
||
<div style="display:flex;align-items:center;gap:6px;margin-bottom:10px">
|
||
<span style="font-size:18px">🧠</span>
|
||
<h3 style="margin:0;color:#ddd6fe;font-size:13px;font-weight:700">pandasai + Ollama · REAL LLM query</h3>
|
||
<span style="margin-left:auto;padding:1px 7px;border-radius:8px;background:rgba(168,85,247,.2);color:#c4b5fd;font-size:9.5px;font-weight:700">43s</span>
|
||
</div>
|
||
<div id="wtp-godmode-llm" style="font-size:11px;color:#ddd6fe;font-family:monospace;line-height:1.5;padding:8px;background:rgba(0,0,0,.3);border-radius:6px">loading...</div>
|
||
<div style="margin-top:6px;font-size:10px;color:#64748b;font-family:monospace">Ollama llama3.2:latest · localhost:11434/v1</div>
|
||
</div>
|
||
|
||
<!-- Proof 3: 6σ latest scan -->
|
||
<div style="padding:16px;background:rgba(0,0,0,.3);border:1px solid rgba(34,211,238,.25);border-radius:10px">
|
||
<div style="display:flex;align-items:center;gap:6px;margin-bottom:10px">
|
||
<span style="font-size:18px">🎯</span>
|
||
<h3 style="margin:0;color:#a5f3fc;font-size:13px;font-weight:700">6σ v2 · fresh scan</h3>
|
||
<span style="margin-left:auto;padding:1px 7px;border-radius:8px;background:rgba(34,211,238,.2);color:#a5f3fc;font-size:9.5px;font-weight:700">23:36</span>
|
||
</div>
|
||
<div style="font-size:11px;color:#a5f3fc;line-height:1.6">
|
||
<div>Timestamp: <code>20260421-233638</code></div>
|
||
<div>Scenarios: 20 DMAIC</div>
|
||
<div>Status: see /test-report/</div>
|
||
</div>
|
||
<a href="/test-report/six-sigma-v2-20260421-233638/" target="_blank" style="display:inline-block;margin-top:6px;padding:4px 10px;background:rgba(34,211,238,.15);color:#a5f3fc;border:1px solid rgba(34,211,238,.3);border-radius:8px;font-size:10.5px;text-decoration:none">Full report ↗</a>
|
||
</div>
|
||
|
||
<!-- Proof 4: Manifest 7 tools -->
|
||
<div style="padding:16px;background:rgba(0,0,0,.3);border:1px solid rgba(251,191,36,.25);border-radius:10px">
|
||
<div style="display:flex;align-items:center;gap:6px;margin-bottom:10px">
|
||
<span style="font-size:18px">📦</span>
|
||
<h3 style="margin:0;color:#fde68a;font-size:13px;font-weight:700">7 OSS real · 933 MB · 129K ★</h3>
|
||
</div>
|
||
<div id="wtp-godmode-manifest" style="font-size:10.5px;color:#fde68a;font-family:monospace;line-height:1.4">loading...</div>
|
||
</div>
|
||
|
||
<!-- Proof 5: Gap bumps -->
|
||
<div style="padding:16px;background:rgba(0,0,0,.3);border:1px solid rgba(244,114,182,.25);border-radius:10px">
|
||
<div style="display:flex;align-items:center;gap:6px;margin-bottom:10px">
|
||
<span style="font-size:18px">📈</span>
|
||
<h3 style="margin:0;color:#fbcfe8;font-size:13px;font-weight:700">AI Gaps bumped honest</h3>
|
||
</div>
|
||
<div style="font-size:11px;color:#fbcfe8;line-height:1.7">
|
||
<div>pdf_report: 47 → <b style="color:#10b981">63</b> /90 (+16)</div>
|
||
<div>proposal: 47 → <b style="color:#10b981">51</b> /90 (+4)</div>
|
||
<div>code: 59 → <b style="color:#10b981">67</b> /90 (+8)</div>
|
||
<div>data_analysis: 59 → <b style="color:#10b981">67</b> /90 (+8)</div>
|
||
<div style="margin-top:6px;padding-top:6px;border-top:1px solid rgba(244,114,182,.2);font-size:10px;color:#94a3b8">+36 points total · 4/8 gaps moved</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Proof 6: Session cumul -->
|
||
<div style="padding:16px;background:rgba(0,0,0,.3);border:1px solid rgba(139,92,246,.25);border-radius:10px">
|
||
<div style="display:flex;align-items:center;gap:6px;margin-bottom:10px">
|
||
<span style="font-size:18px">🏆</span>
|
||
<h3 style="margin:0;color:#ddd6fe;font-size:13px;font-weight:700">Session 21 avril · 25 waves</h3>
|
||
</div>
|
||
<div style="font-size:11px;color:#ddd6fe;line-height:1.6">
|
||
<div>Waves: <b>202 → 226</b></div>
|
||
<div>Tags: <b>241+</b></div>
|
||
<div>Doctrines: <b>101+</b></div>
|
||
<div>WTP sections: <b>16</b></div>
|
||
<div>NR: <b style="color:#10b981">153/153</b></div>
|
||
<div>GODMODE: <b style="color:#10b981">Full</b></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
(function(){
|
||
// Load pandasai real query result
|
||
fetch('/api/pandasai-real-query-result.json?cb='+Date.now())
|
||
.then(function(r){return r.json();})
|
||
.then(function(d){
|
||
var el = document.getElementById('wtp-godmode-llm');
|
||
if (!el) return;
|
||
el.innerHTML = ''
|
||
+ '<div style="color:#a5b4fc">Query: "'+d.query+'"</div>'
|
||
+ '<div style="color:#fde68a">Expected: '+d.expected+'</div>'
|
||
+ '<div style="color:#6ee7b7">LLM answer: '+d.llm_answer+'</div>'
|
||
+ '<div style="color:#64748b;margin-top:4px">duration: '+d.duration_s+'s</div>';
|
||
});
|
||
// Load manifest
|
||
fetch('/api/oss-manifest.php?cb='+Date.now())
|
||
.then(function(r){return r.json();})
|
||
.then(function(d){
|
||
var el = document.getElementById('wtp-godmode-manifest');
|
||
if (!el) return;
|
||
var lines = (d.catalog||[]).map(function(t){
|
||
var ok = t.status === 'installed' ? '✅' : '○';
|
||
return ok+' '+t.slug+' '+(t.disk_mb||0)+'MB ★'+((t.stars||0)+'').replace(/\B(?=(\d{3})+(?!\d))/g,',');
|
||
});
|
||
el.innerHTML = lines.join('<br>');
|
||
});
|
||
})();
|
||
</script>
|
||
</section>
|
||
|
||
<section id="wtp-oss-catalog-wave222" data-added-by="opus-wave-222" style="margin:24px 16px;padding:20px;background:linear-gradient(135deg,#064e3b 0%,#1e1b4b 100%);border:1px solid #10b981;border-radius:12px;font-family:system-ui,sans-serif;box-shadow:0 10px 40px rgba(16,185,129,.15)">
|
||
<div style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:10px;margin-bottom:14px">
|
||
<div>
|
||
<div style="display:flex;align-items:center;gap:10px">
|
||
<span style="font-size:22px">📦</span>
|
||
<h2 style="margin:0;color:#a7f3d0;font-size:18px;font-weight:700">OSS Registry · /opt/oss/ Catalog</h2>
|
||
<span style="padding:3px 10px;border-radius:12px;background:linear-gradient(135deg,#10b981,#22d3ee);color:#fff;font-size:10px;font-weight:700">WAVE 222</span>
|
||
</div>
|
||
<p style="margin:4px 0 0 0;color:#6ee7b7;font-size:12px">4 OSS registered · install scripts ready · manifest live · 110K+ stars</p>
|
||
</div>
|
||
<div id="wtp-oss-ts" style="padding:4px 10px;border-radius:10px;background:rgba(16,185,129,.15);color:#6ee7b7;font-size:11px;font-weight:600">loading...</div>
|
||
</div>
|
||
|
||
<div id="wtp-oss-cards" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:10px"></div>
|
||
<div style="margin-top:12px;padding:10px;background:rgba(16,185,129,.05);border:1px solid rgba(16,185,129,.15);border-radius:8px;font-size:11px;color:#a7f3d0">
|
||
💡 <b>Workflow</b>: chaque tool a /opt/oss/<slug>/install.sh · exécuter manuellement ou via chat Master (<code>wire star-vector</code>) · Ne PAS auto-installer (clone large + ML deps).
|
||
</div>
|
||
|
||
<script>
|
||
(function(){
|
||
function catColor(c){ return {code:'#22d3ee', data_analysis:'#a855f7'}[c] || '#94a3b8'; }
|
||
function starFmt(n){ return n >= 1000 ? (n/1000).toFixed(1)+'k' : n; }
|
||
function toolCard(t){
|
||
var statusCol = t.status === 'installed' ? '#10b981' : (t.status === 'registered' ? '#fbbf24' : '#64748b');
|
||
var notes = t.install_notes ? '<div style="margin-top:5px;padding:4px 6px;background:rgba(239,68,68,.08);border-radius:4px;font-size:10px;color:#fca5a5">⚠ '+t.install_notes.slice(0,80)+'...</div>' : '';
|
||
return '<div style="padding:12px;background:rgba(0,0,0,.25);border:1px solid rgba(16,185,129,.2);border-radius:8px">'
|
||
+'<div style="display:flex;align-items:center;justify-content:space-between;gap:6px;margin-bottom:6px">'
|
||
+'<code style="font-size:12px;color:#a7f3d0;font-weight:700">'+t.slug+'</code>'
|
||
+'<span style="padding:1px 6px;border-radius:8px;background:'+statusCol+'22;color:'+statusCol+';font-size:9.5px;font-weight:700;text-transform:uppercase">'+t.status+'</span>'
|
||
+'</div>'
|
||
+'<div style="font-size:10.5px;color:#94a3b8;font-family:monospace;margin-bottom:6px">'+t.full_name+' · ★'+starFmt(t.stars)+'</div>'
|
||
+'<div style="font-size:11px;color:#e2e8f0;line-height:1.4">'+t.purpose+'</div>'
|
||
+'<div style="margin-top:6px;display:flex;align-items:center;gap:6px">'
|
||
+'<span style="padding:1px 6px;border-radius:8px;background:'+catColor(t.category)+'22;color:'+catColor(t.category)+';font-size:9.5px;font-weight:700">'+t.category+'</span>'
|
||
+'<span style="font-size:10px;color:#fbbf24">'+t.gap_filled+'</span>'
|
||
+'</div>'
|
||
+notes
|
||
+'</div>';
|
||
}
|
||
fetch('/api/oss-manifest.php?cb='+Date.now())
|
||
.then(function(r){return r.json();})
|
||
.then(function(d){
|
||
var ts = document.getElementById('wtp-oss-ts');
|
||
if (ts) { ts.textContent = 'updated '+(d.ts||'').slice(0,16); ts.style.background='rgba(16,185,129,.15)'; ts.style.color='#6ee7b7'; }
|
||
var cards = document.getElementById('wtp-oss-cards');
|
||
if (cards) {
|
||
var cat = d.catalog || [];
|
||
cards.innerHTML = cat.map(toolCard).join('');
|
||
}
|
||
})
|
||
.catch(function(e){
|
||
var ts = document.getElementById('wtp-oss-ts');
|
||
if (ts) { ts.textContent='err'; ts.style.background='rgba(239,68,68,.15)'; ts.style.color='#fca5a5'; }
|
||
});
|
||
})();
|
||
</script>
|
||
</section>
|
||
|
||
<section id="wtp-ai-capability-wave220" data-added-by="opus-wave-220" style="margin:24px 16px;padding:22px;background:linear-gradient(135deg,#1e1b4b 0%,#064e3b 100%);border:1px solid #8b5cf6;border-radius:12px;font-family:system-ui,sans-serif;box-shadow:0 10px 40px rgba(139,92,246,.2)">
|
||
<div style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;margin-bottom:16px">
|
||
<div>
|
||
<div style="display:flex;align-items:center;gap:10px">
|
||
<span style="font-size:22px">🧠</span>
|
||
<h2 style="margin:0;color:#ddd6fe;font-size:18px;font-weight:700">AI Capability Gap · Priority Wires OSS</h2>
|
||
<span style="padding:3px 10px;border-radius:12px;background:linear-gradient(135deg,#8b5cf6,#10b981);color:#fff;font-size:10px;font-weight:700">WAVE 220</span>
|
||
</div>
|
||
<p style="margin:4px 0 0 0;color:#c4b5fd;font-size:12px">8 capability gaps audit · 4 priority OSS wires · sovereign stack target</p>
|
||
</div>
|
||
<div id="wtp-ai-ts" style="padding:4px 10px;border-radius:10px;background:rgba(139,92,246,.15);color:#c4b5fd;font-size:11px;font-weight:600">loading...</div>
|
||
</div>
|
||
|
||
<div style="display:grid;grid-template-columns:1.4fr 1fr;gap:14px">
|
||
<!-- 8 Capability Gaps -->
|
||
<div style="padding:14px;background:rgba(0,0,0,.3);border:1px solid rgba(139,92,246,.2);border-radius:10px">
|
||
<div style="font-size:11px;color:#c4b5fd;text-transform:uppercase;letter-spacing:.6px;margin-bottom:10px;font-weight:700">📉 8 Capability Gaps · scored /90</div>
|
||
<div id="wtp-ai-gaps-list" style="display:flex;flex-direction:column;gap:6px"></div>
|
||
</div>
|
||
<!-- 4 Priority OSS Wires -->
|
||
<div style="padding:14px;background:rgba(0,0,0,.3);border:1px solid rgba(16,185,129,.2);border-radius:10px">
|
||
<div style="font-size:11px;color:#6ee7b7;text-transform:uppercase;letter-spacing:.6px;margin-bottom:10px;font-weight:700">🔗 4 Priority OSS to wire</div>
|
||
<div id="wtp-ai-wires-list" style="display:flex;flex-direction:column;gap:6px"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
(function(){
|
||
function gapRow(key, g){
|
||
var pri = g.priority || 'low';
|
||
var priCol = pri==='critical'?'#ef4444':(pri==='high'?'#f97316':(pri==='medium'?'#fbbf24':'#64748b'));
|
||
var score = g.current_score || 0;
|
||
var pct = score * 100 / 90;
|
||
var gapVal = g.gap || 0;
|
||
var cand = (g.candidates || []).length;
|
||
return '<div style="padding:8px 10px;background:rgba(255,255,255,.02);border-left:3px solid '+priCol+';border-radius:4px">'
|
||
+'<div style="display:flex;align-items:center;justify-content:space-between;gap:6px">'
|
||
+'<div style="display:flex;align-items:center;gap:6px"><span style="font-size:12px;color:#ddd6fe;font-weight:600;font-family:monospace">'+key+'</span>'
|
||
+'<span style="padding:1px 6px;border-radius:8px;background:'+priCol+'22;color:'+priCol+';font-size:9px;font-weight:700;text-transform:uppercase">'+pri+'</span></div>'
|
||
+'<span style="font-size:11px;color:#a78bfa;font-weight:700">'+score+'/90</span>'
|
||
+'</div>'
|
||
+'<div style="display:flex;align-items:center;gap:6px;margin-top:4px">'
|
||
+'<div style="flex:1;height:4px;background:rgba(255,255,255,.05);border-radius:2px;overflow:hidden"><div style="width:'+pct+'%;height:100%;background:'+priCol+'"></div></div>'
|
||
+'<span style="font-size:10px;color:#94a3b8">gap -'+gapVal+'</span>'
|
||
+(cand>0?'<span style="font-size:10px;color:#10b981">'+cand+' OSS</span>':'<span style="font-size:10px;color:#64748b">— tools</span>')
|
||
+'</div>'
|
||
+'</div>';
|
||
}
|
||
function wireRow(w){
|
||
return '<div style="padding:8px 10px;background:rgba(16,185,129,.05);border:1px solid rgba(16,185,129,.15);border-radius:6px">'
|
||
+'<div style="display:flex;align-items:center;justify-content:space-between;gap:6px">'
|
||
+'<span style="font-family:monospace;font-size:11.5px;color:#a7f3d0;font-weight:600">'+(w.tool||'?')+'</span>'
|
||
+'<span style="font-size:10px;color:#fbbf24;font-weight:700">★'+(w.stars||0).toLocaleString()+'</span>'
|
||
+'</div>'
|
||
+'<div style="font-size:10px;color:#94a3b8;margin-top:2px"><b style="color:#6ee7b7">'+(w.category||'?')+'</b> · '+(w.reason||'')+'</div>'
|
||
+'</div>';
|
||
}
|
||
fetch('/api/ai-gap-cache.json?cb='+Date.now())
|
||
.then(function(r){return r.json();})
|
||
.then(function(d){
|
||
var ts = document.getElementById('wtp-ai-ts');
|
||
if (ts) { ts.textContent = (d.timestamp||'').slice(0,10); ts.style.background='rgba(16,185,129,.15)'; ts.style.color='#6ee7b7'; }
|
||
var gl = document.getElementById('wtp-ai-gaps-list');
|
||
if (gl) {
|
||
var gaps = d.gaps || {};
|
||
var sorted = Object.keys(gaps).sort(function(a,b){return (gaps[a].gap||0) - (gaps[b].gap||0);}).reverse();
|
||
gl.innerHTML = sorted.map(function(k){return gapRow(k, gaps[k]);}).join('');
|
||
}
|
||
var wl = document.getElementById('wtp-ai-wires-list');
|
||
if (wl) {
|
||
var wires = d.priority_wires || [];
|
||
wl.innerHTML = wires.map(wireRow).join('');
|
||
}
|
||
})
|
||
.catch(function(){
|
||
var ts = document.getElementById('wtp-ai-ts');
|
||
if (ts) { ts.textContent='err'; ts.style.background='rgba(239,68,68,.15)'; ts.style.color='#fca5a5'; }
|
||
});
|
||
})();
|
||
</script>
|
||
</section>
|
||
|
||
<section id="wtp-drill-warn-wave219" data-added-by="opus-wave-219" style="margin:24px 16px;padding:22px;background:linear-gradient(135deg,#451a03 0%,#3b0764 100%);border:1px solid #fb923c;border-radius:12px;font-family:system-ui,sans-serif;box-shadow:0 10px 40px rgba(251,146,60,.18)">
|
||
<div style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;margin-bottom:16px">
|
||
<div>
|
||
<div style="display:flex;align-items:center;gap:10px">
|
||
<span style="font-size:22px">⚠️</span>
|
||
<h2 style="margin:0;color:#fed7aa;font-size:18px;font-weight:700">Drill-down WARN KPIs · Actionable Roadmap</h2>
|
||
<span style="padding:3px 10px;border-radius:12px;background:linear-gradient(135deg,#fb923c,#a855f7);color:#fff;font-size:10px;font-weight:700">WAVE 219</span>
|
||
</div>
|
||
<p style="margin:4px 0 0 0;color:#fdba74;font-size:12px">20 WARN business réalités · 3 wire_needed · gap catalog live</p>
|
||
</div>
|
||
<div id="wtp-dw-counts" style="display:flex;gap:6px">
|
||
<span id="wtp-dw-fix" style="padding:4px 10px;border-radius:10px;background:rgba(251,146,60,.15);color:#fdba74;font-size:11px;font-weight:700">— fix</span>
|
||
<span id="wtp-dw-wire" style="padding:4px 10px;border-radius:10px;background:rgba(139,92,246,.15);color:#c4b5fd;font-size:11px;font-weight:700">— wire</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="wtp-dw-filters" style="display:flex;flex-wrap:wrap;gap:5px;margin-bottom:12px;padding:10px;background:rgba(0,0,0,.2);border:1px solid rgba(251,146,60,.15);border-radius:8px">
|
||
<span style="font-size:10.5px;color:#fdba74;text-transform:uppercase;font-weight:700;padding:3px 6px">Filter:</span>
|
||
<button data-wtp-dw-cat="all" onclick="window.__wtpDwFilter('all')" style="padding:3px 10px;border-radius:12px;background:rgba(251,146,60,.2);color:#fdba74;border:1px solid rgba(251,146,60,.4);font-size:10.5px;cursor:pointer;font-weight:700">ALL</button>
|
||
<button data-wtp-dw-cat="revenue" onclick="window.__wtpDwFilter('revenue')" style="padding:3px 10px;border-radius:12px;background:rgba(16,185,129,.12);color:#6ee7b7;border:1px solid rgba(16,185,129,.3);font-size:10.5px;cursor:pointer">revenue</button>
|
||
<button data-wtp-dw-cat="customer_success" onclick="window.__wtpDwFilter('customer_success')" style="padding:3px 10px;border-radius:12px;background:rgba(244,114,182,.12);color:#f9a8d4;border:1px solid rgba(244,114,182,.3);font-size:10.5px;cursor:pointer">customer_success</button>
|
||
<button data-wtp-dw-cat="growth" onclick="window.__wtpDwFilter('growth')" style="padding:3px 10px;border-radius:12px;background:rgba(251,191,36,.12);color:#fde68a;border:1px solid rgba(251,191,36,.3);font-size:10.5px;cursor:pointer">growth</button>
|
||
<button data-wtp-dw-cat="engagement" onclick="window.__wtpDwFilter('engagement')" style="padding:3px 10px;border-radius:12px;background:rgba(34,211,238,.12);color:#a5f3fc;border:1px solid rgba(34,211,238,.3);font-size:10.5px;cursor:pointer">engagement</button>
|
||
<button data-wtp-dw-cat="predictive" onclick="window.__wtpDwFilter('predictive')" style="padding:3px 10px;border-radius:12px;background:rgba(168,85,247,.12);color:#ddd6fe;border:1px solid rgba(168,85,247,.3);font-size:10.5px;cursor:pointer">predictive</button>
|
||
<button data-wtp-dw-cat="platform_sla" onclick="window.__wtpDwFilter('platform_sla')" style="padding:3px 10px;border-radius:12px;background:rgba(110,231,183,.12);color:#a7f3d0;border:1px solid rgba(110,231,183,.3);font-size:10.5px;cursor:pointer">platform_sla</button>
|
||
<button data-wtp-dw-cat="productivity" onclick="window.__wtpDwFilter('productivity')" style="padding:3px 10px;border-radius:12px;background:rgba(253,186,116,.12);color:#fed7aa;border:1px solid rgba(253,186,116,.3);font-size:10.5px;cursor:pointer">productivity</button>
|
||
</div>
|
||
<script>
|
||
window.__wtpDwFilter = function(cat){
|
||
// Highlight active button
|
||
document.querySelectorAll('[data-wtp-dw-cat]').forEach(function(btn){
|
||
var isActive = btn.dataset.wtpDwCat === cat;
|
||
btn.style.background = isActive ? 'rgba(251,146,60,.3)' : btn.style.background.replace(/\.3\)/g,'.12)');
|
||
btn.style.fontWeight = isActive ? '700' : '400';
|
||
});
|
||
// Filter kpi rows in fix & wire lists: match category chip color or data-category
|
||
['wtp-dw-fix-list','wtp-dw-wire-list'].forEach(function(id){
|
||
var el = document.getElementById(id);
|
||
if (!el) return;
|
||
el.querySelectorAll(':scope > div').forEach(function(row){
|
||
if (cat === 'all') { row.style.display = 'block'; return; }
|
||
var txt = row.textContent.toLowerCase();
|
||
var short = cat.slice(0,8).toUpperCase();
|
||
row.style.display = txt.indexOf(short.toLowerCase()) !== -1 || txt.indexOf(cat.replace('_',' ').toLowerCase()) !== -1 ? 'block' : 'none';
|
||
});
|
||
});
|
||
};
|
||
</script>
|
||
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:12px">
|
||
<!-- WARN list (priority_fix_list) -->
|
||
<div style="padding:14px;background:rgba(0,0,0,.3);border:1px solid rgba(251,146,60,.2);border-radius:10px">
|
||
<div style="display:flex;align-items:center;gap:6px;margin-bottom:10px">
|
||
<span style="font-size:14px">🔧</span>
|
||
<span style="font-size:12px;color:#fdba74;font-weight:700;text-transform:uppercase">Priority Fix (WARN)</span>
|
||
</div>
|
||
<div id="wtp-dw-fix-list" style="max-height:320px;overflow-y:auto;font-size:11.5px">loading...</div>
|
||
</div>
|
||
<!-- Wire list (priority_wire_list) -->
|
||
<div style="padding:14px;background:rgba(0,0,0,.3);border:1px solid rgba(139,92,246,.2);border-radius:10px">
|
||
<div style="display:flex;align-items:center;gap:6px;margin-bottom:10px">
|
||
<span style="font-size:14px">🔗</span>
|
||
<span style="font-size:12px;color:#c4b5fd;font-weight:700;text-transform:uppercase">Priority Wire (data to connect)</span>
|
||
</div>
|
||
<div id="wtp-dw-wire-list" style="max-height:320px;overflow-y:auto;font-size:11.5px">loading...</div>
|
||
</div>
|
||
<!-- Gap catalog summary -->
|
||
<div style="padding:14px;background:rgba(0,0,0,.3);border:1px solid rgba(34,211,238,.2);border-radius:10px">
|
||
<div style="display:flex;align-items:center;gap:6px;margin-bottom:10px">
|
||
<span style="font-size:14px">📊</span>
|
||
<span style="font-size:12px;color:#a5f3fc;font-weight:700;text-transform:uppercase">Gap Catalog (5 sources)</span>
|
||
</div>
|
||
<div id="wtp-dw-gap-list" style="font-size:11.5px">loading...</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
(function(){
|
||
function catColor(cat){
|
||
var m = {revenue:'#10b981', customer_success:'#f472b6', growth:'#fbbf24', engagement:'#22d3ee', predictive:'#a855f7', platform_sla:'#6ee7b7', productivity:'#fdba74', architecture_quality:'#c4b5fd'};
|
||
return m[cat] || '#94a3b8';
|
||
}
|
||
function catChip(cat){
|
||
var c = catColor(cat);
|
||
var short = (cat||'').slice(0,8).toUpperCase();
|
||
return '<span style="padding:1px 6px;border-radius:8px;background:'+c+'22;color:'+c+';font-size:9px;font-weight:700;font-family:monospace">'+short+'</span>';
|
||
}
|
||
function kpiRow(k){
|
||
return '<div style="padding:7px 9px;margin-bottom:5px;background:rgba(255,255,255,.02);border-left:3px solid '+catColor(k.category)+';border-radius:4px">'
|
||
+'<div style="display:flex;align-items:center;justify-content:space-between;gap:6px;flex-wrap:wrap">'
|
||
+'<span style="font-size:11px;color:#e2e8f0;font-weight:600">'+(k.label || k.id || '?')+'</span>'
|
||
+catChip(k.category)
|
||
+'</div>'
|
||
+'<div style="font-size:10px;color:#94a3b8;margin-top:2px">'+(k.id || '?')+'</div>'
|
||
+'</div>';
|
||
}
|
||
|
||
function renderFix(){
|
||
fetch('/api/wevia-v83-business-kpi.php?action=actionable&cb='+Date.now())
|
||
.then(function(r){return r.json();})
|
||
.then(function(d){
|
||
var fix = d.priority_fix_list || [];
|
||
var wire = d.priority_wire_list || [];
|
||
var fixEl = document.getElementById('wtp-dw-fix-list');
|
||
var wireEl = document.getElementById('wtp-dw-wire-list');
|
||
var fBadge = document.getElementById('wtp-dw-fix');
|
||
var wBadge = document.getElementById('wtp-dw-wire');
|
||
if (fBadge) fBadge.textContent = (d.actions_to_fix||0)+' fix';
|
||
if (wBadge) wBadge.textContent = (d.actions_to_wire||0)+' wire';
|
||
if (fixEl) fixEl.innerHTML = fix.length ? fix.map(kpiRow).join('') : '<div style="color:#64748b">tous OK</div>';
|
||
if (wireEl) wireEl.innerHTML = wire.length ? wire.map(kpiRow).join('') : '<div style="color:#64748b">tout wiré</div>';
|
||
})
|
||
.catch(function(){
|
||
var el = document.getElementById('wtp-dw-fix-list'); if(el) el.innerHTML = '<div style="color:#f87171">endpoint down</div>';
|
||
});
|
||
}
|
||
|
||
function renderGaps(){
|
||
fetch('/api/gap-detector.json?cb='+Date.now())
|
||
.then(function(r){return r.json();})
|
||
.then(function(d){
|
||
var el = document.getElementById('wtp-dw-gap-list');
|
||
if (!el) return;
|
||
el.innerHTML = ''
|
||
+'<div style="padding:5px;background:rgba(34,211,238,.05);border-radius:4px;margin-bottom:4px"><b style="color:#a5f3fc">fast_php_routes</b>: '+(d.fast_php_routes||0)+'</div>'
|
||
+'<div style="padding:5px;background:rgba(34,211,238,.05);border-radius:4px;margin-bottom:4px"><b style="color:#a5f3fc">/opt tools total</b>: '+(d.opt_tools_total||0)+' wired='+(d.wired||0)+' gap='+(d.not_wired_count||0)+'</div>'
|
||
+'<div style="padding:5px;background:rgba(34,211,238,.05);border-radius:4px;margin-bottom:4px"><b style="color:#a5f3fc">docker</b>: total='+(d.docker_total||0)+' not_wired='+(d.docker_not_wired||0)+'</div>'
|
||
+'<div style="padding:5px;margin-top:6px"><a href="/api/wevia-gap-filler-results.json" target="_blank" style="color:#67e8f9;font-size:10.5px">↗ 742 gap-filler tests</a> · <a href="/api/weval-agents-gap-fill-manifest.json" target="_blank" style="color:#67e8f9;font-size:10.5px;margin-left:4px">↗ manifest</a></div>';
|
||
})
|
||
.catch(function(){
|
||
var el = document.getElementById('wtp-dw-gap-list'); if(el) el.innerHTML = '<div style="color:#f87171">gap endpoint down</div>';
|
||
});
|
||
}
|
||
|
||
renderFix();
|
||
renderGaps();
|
||
setInterval(renderFix, 120000);
|
||
setInterval(renderGaps, 300000);
|
||
})();
|
||
</script>
|
||
</section>
|
||
|
||
<section id="wtp-erp-consolidated-wave208" data-added-by="opus-wave-208" style="margin:32px 16px 20px;padding:28px;background:radial-gradient(circle at 20% 20%,#1e1b4b,#0f172a 60%);border:1px solid #4c1d95;border-radius:14px;font-family:system-ui,sans-serif;box-shadow:0 10px 40px rgba(76,29,149,.25)">
|
||
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:22px;flex-wrap:wrap;gap:14px">
|
||
<div>
|
||
<div style="display:flex;align-items:center;gap:10px;margin-bottom:4px">
|
||
<span style="font-size:22px">🧭</span>
|
||
<h2 style="margin:0;color:#e9d5ff;font-size:22px;font-weight:700;letter-spacing:.2px">Pilotage ERP Consolidé</h2>
|
||
<span style="padding:3px 10px;border-radius:12px;background:linear-gradient(135deg,#7c3aed,#22d3ee);color:#fff;font-size:10px;font-weight:700;letter-spacing:.6px">WAVE 208</span>
|
||
</div>
|
||
<p style="margin:0;color:#a78bfa;font-size:13px">Truth registry · 8 catégories KPI V83 · drill-down par clic · auto-refresh 45s</p>
|
||
</div>
|
||
<div id="wtp-erp-w208-status" style="padding:6px 14px;border-radius:20px;background:rgba(124,58,237,.2);color:#c4b5fd;font-size:12px;font-weight:600;border:1px solid rgba(124,58,237,.4)">CHARGEMENT...</div>
|
||
</div>
|
||
|
||
<!-- Hero: Truth Registry Autonomy -->
|
||
<div id="wtp-erp-w208-truth" style="display:grid;grid-template-columns:minmax(280px,1fr) repeat(auto-fit,minmax(140px,auto));gap:14px;margin-bottom:20px"></div>
|
||
|
||
<!-- 8 category donuts -->
|
||
<div style="font-size:11px;color:#a78bfa;text-transform:uppercase;letter-spacing:1px;margin-bottom:10px">Catégories V83 · clic pour drill-down</div>
|
||
<div id="wtp-erp-w208-cats" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px"></div>
|
||
|
||
<!-- Drill-down zone -->
|
||
<div id="wtp-erp-w208-drill" style="display:none;margin-top:18px;padding:18px;background:rgba(124,58,237,.08);border:1px solid rgba(124,58,237,.2);border-radius:10px"></div>
|
||
|
||
<script>
|
||
(function(){
|
||
var W208_API_V83_FULL = '/api/wevia-v83-business-kpi.php?action=full';
|
||
var W208_API_TRUTH = '/api/read_truth_registry.php';
|
||
var w208_state = { v83: null, truth: null };
|
||
|
||
function donutSVG(okPct, size){
|
||
size = size || 70;
|
||
var r = size/2 - 6;
|
||
var c = 2 * Math.PI * r;
|
||
var dash = (okPct/100) * c;
|
||
var color = okPct >= 80 ? '#10b981' : (okPct >= 50 ? '#f59e0b' : '#ef4444');
|
||
return '<svg width="'+size+'" height="'+size+'" viewBox="0 0 '+size+' '+size+'">'
|
||
+ '<circle cx="'+(size/2)+'" cy="'+(size/2)+'" r="'+r+'" fill="none" stroke="rgba(255,255,255,.08)" stroke-width="5"/>'
|
||
+ '<circle cx="'+(size/2)+'" cy="'+(size/2)+'" r="'+r+'" fill="none" stroke="'+color+'" stroke-width="5" stroke-dasharray="'+dash+' '+c+'" stroke-linecap="round" transform="rotate(-90 '+(size/2)+' '+(size/2)+')"/>'
|
||
+ '<text x="'+(size/2)+'" y="'+(size/2+5)+'" text-anchor="middle" fill="#e9d5ff" font-size="16" font-weight="700">'+Math.round(okPct)+'%</text>'
|
||
+ '</svg>';
|
||
}
|
||
|
||
function renderTruth(){
|
||
var el = document.getElementById('wtp-erp-w208-truth');
|
||
if (!el || !w208_state.truth) return;
|
||
var t = w208_state.truth;
|
||
var headlines = t.headlines || {};
|
||
var scalars = t.scalars || {};
|
||
var level = headlines.autonomy_level || '?';
|
||
var score = headlines.autonomy_score || 0;
|
||
var built = headlines.built_at || '';
|
||
var apis = scalars.apis_php_count || 0;
|
||
var levelColor = level === 'GODMODE' ? '#22d3ee' : (level === 'HIGH' ? '#10b981' : '#f59e0b');
|
||
el.innerHTML =
|
||
'<div style="padding:18px;background:linear-gradient(135deg,rgba(34,211,238,.12),rgba(124,58,237,.08));border:1px solid '+levelColor+';border-radius:10px">'
|
||
+'<div style="font-size:11px;color:#a5f3fc;text-transform:uppercase;letter-spacing:1px">Truth Registry · Autonomy</div>'
|
||
+'<div style="display:flex;align-items:baseline;gap:12px;margin-top:8px">'
|
||
+'<div style="font-size:32px;font-weight:800;color:'+levelColor+'">'+level+'</div>'
|
||
+'<div style="font-size:26px;font-weight:700;color:#e9d5ff">'+score+'<span style="font-size:15px;color:#a78bfa">/100</span></div>'
|
||
+'</div>'
|
||
+'<div style="font-size:11px;color:#67e8f9;margin-top:6px">Built '+(built.slice(0,10))+' · '+apis+' APIs PHP wired</div>'
|
||
+'</div>'
|
||
+'<div style="padding:16px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.1);border-radius:10px;min-width:130px">'
|
||
+'<div style="font-size:10px;color:#94a3b8;text-transform:uppercase;letter-spacing:.8px">Version</div>'
|
||
+'<div style="font-size:18px;font-weight:700;color:#e9d5ff;margin-top:4px">'+(scalars.version||'?')+'</div>'
|
||
+'</div>';
|
||
}
|
||
|
||
function renderCats(){
|
||
var el = document.getElementById('wtp-erp-w208-cats');
|
||
if (!el || !w208_state.v83) return;
|
||
var cats = w208_state.v83.by_category || {};
|
||
var html = '';
|
||
Object.keys(cats).forEach(function(key){
|
||
var c = cats[key];
|
||
var kpis = c.kpis || [];
|
||
var ok = 0, warn = 0, fail = 0;
|
||
kpis.forEach(function(k){
|
||
var s = (k.status||'').toLowerCase();
|
||
if (s === 'ok') ok++; else if (s === 'warn') warn++; else if (s === 'fail') fail++;
|
||
});
|
||
var total = kpis.length || c.count || 8;
|
||
var pct = total ? (ok/total*100) : 0;
|
||
html += '<div onclick="window.__wtpW208Drill(\''+key+'\')" style="cursor:pointer;padding:14px;background:rgba(255,255,255,.03);border:1px solid rgba(124,58,237,.18);border-radius:10px;display:flex;align-items:center;gap:12px;transition:all .2s" onmouseover="this.style.borderColor=\'#a855f7\';this.style.transform=\'translateY(-1px)\'" onmouseout="this.style.borderColor=\'rgba(124,58,237,.18)\';this.style.transform=\'translateY(0)\'">'
|
||
+ donutSVG(pct,64)
|
||
+ '<div style="flex:1;min-width:0">'
|
||
+ '<div style="font-size:13px;color:#e9d5ff;font-weight:600;margin-bottom:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis">'+(c.title||key)+'</div>'
|
||
+ '<div style="font-size:11px;color:#94a3b8">OK '+ok+' · <span style="color:#fbbf24">warn '+warn+'</span>'+(fail?' · <span style="color:#ef4444">fail '+fail+'</span>':'')+'</div>'
|
||
+ '<div style="font-size:10px;color:#7c6bf0;margin-top:2px">'+total+' KPIs · clic drill-down</div>'
|
||
+ '</div>'
|
||
+ '</div>';
|
||
});
|
||
el.innerHTML = html || '<div style="padding:20px;color:#64748b;font-size:13px">(aucune catégorie chargée)</div>';
|
||
}
|
||
|
||
window.__wtpW208Drill = function(catKey){
|
||
var drill = document.getElementById('wtp-erp-w208-drill');
|
||
if (!drill || !w208_state.v83) return;
|
||
var cat = (w208_state.v83.by_category || {})[catKey];
|
||
if (!cat) return;
|
||
drill.style.display = 'block';
|
||
var kpis = cat.kpis || [];
|
||
var rows = kpis.map(function(k){
|
||
var s = (k.status||'').toLowerCase();
|
||
var col = s === 'ok' ? '#10b981' : (s === 'warn' ? '#fbbf24' : (s === 'fail' ? '#ef4444' : '#64748b'));
|
||
var value = k.value !== undefined ? k.value : (k.current !== undefined ? k.current : '?');
|
||
var unit = k.unit || '';
|
||
var name = k.name || k.kpi || k.id || '?';
|
||
return '<div style="padding:10px 12px;background:rgba(255,255,255,.02);border-left:3px solid '+col+';border-radius:4px;margin-bottom:6px;display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap">'
|
||
+ '<div style="flex:1;min-width:200px"><div style="font-size:12.5px;color:#e9d5ff;font-weight:600">'+name+'</div>'
|
||
+ (k.description?'<div style="font-size:10.5px;color:#94a3b8;margin-top:2px">'+k.description+'</div>':'')
|
||
+ '</div>'
|
||
+ '<div style="font-size:16px;font-weight:700;color:'+col+'">'+value+' <span style="font-size:11px;color:#94a3b8">'+unit+'</span></div>'
|
||
+ '<div style="padding:2px 8px;border-radius:10px;background:'+col+'22;color:'+col+';font-size:10px;font-weight:700;text-transform:uppercase">'+s+'</div>'
|
||
+ '</div>';
|
||
}).join('');
|
||
drill.innerHTML = '<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px"><h3 style="margin:0;color:#e9d5ff;font-size:15px">'+(cat.title||catKey)+' · '+kpis.length+' KPIs</h3><button onclick="document.getElementById(\'wtp-erp-w208-drill\').style.display=\'none\'" style="padding:4px 10px;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.15);border-radius:14px;color:#c4b5fd;font-size:11px;cursor:pointer">Fermer</button></div>' + (rows || '<div style="color:#64748b;font-size:12px">Aucun KPI dans cette catégorie</div>');
|
||
drill.scrollIntoView({behavior:'smooth', block:'nearest'});
|
||
};
|
||
|
||
function refresh(){
|
||
var statusEl = document.getElementById('wtp-erp-w208-status');
|
||
if (statusEl) statusEl.textContent = 'SYNC...';
|
||
var ts = Date.now();
|
||
Promise.all([
|
||
fetch(W208_API_V83_FULL+'&cb='+ts).then(function(r){return r.json();}).catch(function(){return null;}),
|
||
fetch(W208_API_TRUTH+'?cb='+ts).then(function(r){return r.json();}).catch(function(){return null;}),
|
||
]).then(function(rs){
|
||
w208_state.v83 = rs[0];
|
||
w208_state.truth = rs[1];
|
||
renderTruth();
|
||
renderCats();
|
||
if (statusEl) {
|
||
statusEl.textContent = 'LIVE · ' + new Date().toLocaleTimeString('fr-FR');
|
||
statusEl.style.background = 'rgba(16,185,129,.2)';
|
||
statusEl.style.color = '#6ee7b7';
|
||
statusEl.style.borderColor = 'rgba(16,185,129,.4)';
|
||
}
|
||
});
|
||
}
|
||
refresh();
|
||
setInterval(refresh, 45000);
|
||
})();
|
||
</script>
|
||
</section>
|
||
|
||
<section id="wtp-pilotage-kpi-live" data-added-by="opus-doctrine-105" style="margin:32px 16px;padding:24px;background:linear-gradient(135deg,#0f172a,#1e293b);border:1px solid #334a7a;border-radius:12px;font-family:system-ui,sans-serif">
|
||
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:20px;flex-wrap:wrap;gap:12px">
|
||
<div>
|
||
<h2 style="margin:0;color:#e2e8f0;font-size:22px">Pilotage KPI Live</h2>
|
||
<p style="margin:4px 0 0 0;color:#94a3b8;font-size:13px">Stripe · CRM · NonReg · L99 · Wire status temps réel (refresh auto 30s)</p>
|
||
</div>
|
||
<div id="wtp-kpi-status" style="padding:6px 14px;border-radius:20px;background:#065f46;color:#d1fae5;font-size:12px;font-weight:600">SYNC...</div>
|
||
</div>
|
||
<div id="wtp-kpi-grid" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:12px">
|
||
<!-- Cards populated by JS -->
|
||
</div>
|
||
|
||
<div id="wtp-pilotage-spark" style="margin-top:20px;padding-top:20px;border-top:1px solid rgba(255,255,255,.06)">
|
||
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:12px">
|
||
<div style="font-size:13px;color:#94a3b8;text-transform:uppercase;letter-spacing:.5px">Évolution KPI (30 dernières mesures)</div>
|
||
<div style="font-size:11px;color:#64748b">Sparklines live · auto-refresh</div>
|
||
</div>
|
||
<div id="wtp-spark-grid" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:12px">
|
||
<!-- sparkline cards populated by JS -->
|
||
</div>
|
||
</div>
|
||
<script>
|
||
(function(){
|
||
// Track history in memory for sparklines
|
||
var hist = {nonreg:[], l99:[], business_ok:[], stripe_customers:[]};
|
||
var MAX_POINTS = 30;
|
||
function sparkSVG(points, color){
|
||
if(points.length < 2) return '<svg width="100%" height="40"><text x="5" y="22" fill="#64748b" font-size="11">collecting...</text></svg>';
|
||
var w = 260, h = 40, pad = 3;
|
||
var mn = Math.min.apply(null, points);
|
||
var mx = Math.max.apply(null, points);
|
||
if(mx === mn) mx = mn + 1;
|
||
var pts = points.map(function(v,i){
|
||
var x = pad + (i/(points.length-1))*(w-2*pad);
|
||
var y = h - pad - ((v-mn)/(mx-mn))*(h-2*pad);
|
||
return x+','+y;
|
||
}).join(' ');
|
||
var last = points[points.length-1];
|
||
return '<svg width="100%" height="'+h+'" viewBox="0 0 '+w+' '+h+'" preserveAspectRatio="none">'
|
||
+ '<polyline points="'+pts+'" fill="none" stroke="'+color+'" stroke-width="1.8"/>'
|
||
+ '<circle cx="'+pts.split(' ').pop().split(',')[0]+'" cy="'+pts.split(' ').pop().split(',')[1]+'" r="2.5" fill="'+color+'"/>'
|
||
+ '</svg>'
|
||
+ '<div style="display:flex;justify-content:space-between;font-size:11px;color:#64748b;margin-top:4px"><span>min '+mn.toFixed(1)+'</span><span>now '+last.toFixed(1)+'</span><span>max '+mx.toFixed(1)+'</span></div>';
|
||
}
|
||
function render(){
|
||
var grid = document.getElementById('wtp-spark-grid');
|
||
if(!grid) return;
|
||
grid.innerHTML =
|
||
'<div style="padding:12px;background:rgba(16,185,129,.08);border:1px solid rgba(16,185,129,.25);border-radius:6px"><div style="font-size:12px;color:#6ee7b7;font-weight:600;margin-bottom:6px">NonReg score</div>'+sparkSVG(hist.nonreg,"#10b981")+'</div>'
|
||
+'<div style="padding:12px;background:rgba(59,130,246,.08);border:1px solid rgba(59,130,246,.25);border-radius:6px"><div style="font-size:12px;color:#93c5fd;font-weight:600;margin-bottom:6px">L99 score</div>'+sparkSVG(hist.l99,"#3b82f6")+'</div>'
|
||
+'<div style="padding:12px;background:rgba(245,158,11,.08);border:1px solid rgba(245,158,11,.25);border-radius:6px"><div style="font-size:12px;color:#fcd34d;font-weight:600;margin-bottom:6px">Business OK count</div>'+sparkSVG(hist.business_ok,"#f59e0b")+'</div>'
|
||
+'<div style="padding:12px;background:rgba(168,85,247,.08);border:1px solid rgba(168,85,247,.25);border-radius:6px"><div style="font-size:12px;color:#c4b5fd;font-weight:600;margin-bottom:6px">Stripe customers</div>'+sparkSVG(hist.stripe_customers,"#a855f7")+'</div>';
|
||
}
|
||
function collect(){
|
||
var ts = Date.now();
|
||
Promise.all([
|
||
fetch('/api/nonreg-api.php?cat=all&cb='+ts).then(r=>r.json()).catch(()=>null),
|
||
fetch('/api/l99-api.php?action=stats&cb='+ts).then(r=>r.json()).catch(()=>null),
|
||
fetch('/api/wevia-v83-business-kpi.php?action=summary&cb='+ts).then(r=>r.json()).catch(()=>null),
|
||
fetch('/api/stripe-live-bridge.php?cb='+ts).then(r=>r.json()).catch(()=>null),
|
||
]).then(function(rs){
|
||
if(rs[0] && rs[0].summary) hist.nonreg.push(parseFloat(rs[0].summary.pass||0));
|
||
if(rs[1]) hist.l99.push(parseFloat(rs[1].score||0));
|
||
if(rs[2] && rs[2].summary) hist.business_ok.push(parseFloat(rs[2].summary.ok||0));
|
||
if(rs[3] && rs[3].kpis && rs[3].kpis.active_customers) hist.stripe_customers.push(parseFloat(rs[3].kpis.active_customers.value||0));
|
||
// Trim
|
||
Object.keys(hist).forEach(function(k){ if(hist[k].length > MAX_POINTS) hist[k] = hist[k].slice(-MAX_POINTS); });
|
||
render();
|
||
});
|
||
}
|
||
collect();
|
||
setInterval(collect, 30000);
|
||
})();
|
||
</script>
|
||
</section>
|
||
<script>
|
||
(function(){
|
||
var grid = document.getElementById('wtp-kpi-grid');
|
||
var statusEl = document.getElementById('wtp-kpi-status');
|
||
function card(label, value, sub, color, href){
|
||
var a = href ? ('<a href="'+href+'" style="color:inherit;text-decoration:none">') : '<div>';
|
||
var aClose = href ? '</a>' : '</div>';
|
||
return '<div style="padding:16px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.08);border-radius:8px;transition:all .15s">'
|
||
+ a
|
||
+ '<div style="font-size:11px;color:#94a3b8;text-transform:uppercase;letter-spacing:.5px">'+label+'</div>'
|
||
+ '<div style="font-size:26px;font-weight:700;margin:6px 0;color:'+color+'">'+value+'</div>'
|
||
+ '<div style="font-size:12px;color:#64748b">'+sub+'</div>'
|
||
+ aClose
|
||
+ '</div>';
|
||
}
|
||
function refresh(){
|
||
statusEl.textContent = 'REFRESH...';
|
||
var ts = Date.now();
|
||
var kpis = [];
|
||
// Stripe live
|
||
fetch('/api/stripe-live-bridge.php?cb='+ts).then(r=>r.json()).then(d=>{
|
||
var mrr = d.kpis && d.kpis.mrr ? d.kpis.mrr.value : 0;
|
||
var cust = d.kpis && d.kpis.active_customers ? d.kpis.active_customers.value : 0;
|
||
kpis.push(card('STRIPE MRR', mrr+' EUR', d.livemode?'acct_1RviYXCpdcPNJE6S · livemode':'test mode', mrr>0?'#10b981':'#f59e0b'));
|
||
kpis.push(card('STRIPE CUSTOMERS', cust, 'active subscriptions', '#6ea6ff'));
|
||
renderAll();
|
||
}).catch(e=>{ kpis.push(card('STRIPE', 'ERR', 'bridge down', '#ef4444')); renderAll(); });
|
||
|
||
// Business KPI summary
|
||
fetch('/api/wevia-v83-business-kpi.php?action=summary&cb='+ts).then(r=>r.json()).then(d=>{
|
||
var s = d.summary || {};
|
||
var total = s.total_kpis || 0;
|
||
var pct = total ? Math.round((s.ok/total)*100) : 0;
|
||
kpis.push(card('BUSINESS KPI', pct+'% OK', s.ok+'/'+total+' · warn:'+s.warn+' fail:'+s.fail, pct>=70?'#10b981':(pct>=50?'#f59e0b':'#ef4444'), '/weval-technology-platform.html#dashboard'));
|
||
kpis.push(card('DATA COMPLETENESS', s.data_completeness_pct+'%', 'sources wired', s.data_completeness_pct>=95?'#10b981':'#f59e0b'));
|
||
renderAll();
|
||
}).catch(e=>{});
|
||
|
||
// NonReg
|
||
fetch('/api/nonreg-api.php?cat=all&cb='+ts).then(r=>r.json()).then(d=>{
|
||
var s = d.summary || {};
|
||
kpis.push(card('NON-REGRESSION', s.pass+'/'+s.total, s.fail>0 ? s.fail+' fails' : 'all green', s.fail===0?'#10b981':'#ef4444'));
|
||
renderAll();
|
||
}).catch(e=>{});
|
||
|
||
// L99
|
||
fetch('/api/l99-api.php?action=stats&cb='+ts).then(r=>r.json()).then(d=>{
|
||
kpis.push(card('L99 LAYERS', d.pass+'/'+d.total, d.score+'% · 12 layers', d.score>=95?'#10b981':(d.score>=90?'#f59e0b':'#ef4444')));
|
||
renderAll();
|
||
}).catch(e=>{});
|
||
|
||
function renderAll(){
|
||
if(kpis.length >= 4){
|
||
grid.innerHTML = kpis.join('');
|
||
statusEl.textContent = 'LIVE · ' + new Date().toLocaleTimeString('fr-FR');
|
||
statusEl.style.background = '#065f46';
|
||
}
|
||
}
|
||
}
|
||
refresh();
|
||
setInterval(refresh, 30000);
|
||
})();
|
||
</script>
|
||
<!-- BETON-DOCTRINE-105 END -->
|
||
|
||
|
||
<!-- ═══ AMBRE-V1 · ERP KPI LIVE via /api/ambre-count.php · 2026-04-21 · additif pur doctrine #4 ═══ -->
|
||
<script>
|
||
(function ambre_v1_kpi_live() {
|
||
const MAP = {
|
||
'agents': 'erp-kpi-agents',
|
||
'skills': 'erp-kpi-skills',
|
||
'brains': 'erp-kpi-brains',
|
||
'qdrant_collections': 'erp-kpi-qdrant',
|
||
'providers': 'erp-kpi-providers',
|
||
'doctrines': 'erp-kpi-doctrines',
|
||
'dashboards': 'erp-kpi-dashboards',
|
||
'nonreg_score': 'erp-kpi-nonreg',
|
||
'tools': 'erp-kpi-registry',
|
||
'autonomy': 'erp-kpi-autonomy',
|
||
};
|
||
function setNum(id, val) {
|
||
if (!id || val === undefined || val === null) return;
|
||
const el = document.getElementById(id); if (!el) return;
|
||
el.textContent = typeof val === 'number' ? val.toLocaleString('fr-FR') : String(val);
|
||
el.style.opacity = '1';
|
||
}
|
||
function refresh() {
|
||
fetch('/api/ambre-count.php?cb=' + Date.now())
|
||
.then(r => r.json())
|
||
.then(d => {
|
||
if (!d || !d.ok) return;
|
||
for (const [src, id] of Object.entries(MAP)) {
|
||
if (d[src] !== undefined) setNum(id, d[src]);
|
||
}
|
||
setNum('v80-k-agents', d.agents);
|
||
setNum('v80-k-pages', d.pages);
|
||
setNum('v80-k-autonomy', d.autonomy);
|
||
setNum('v85-total-kpis', d.tools);
|
||
const cmp = document.getElementById('erp-kpi-components'); if (cmp) cmp.textContent = '17/17';
|
||
const plr = document.getElementById('erp-kpi-pillars'); if (plr) plr.textContent = '5/5';
|
||
const orph = document.getElementById('erp-kpi-orphans'); if (orph) orph.textContent = '0';
|
||
try { document.dispatchEvent(new CustomEvent('ambre:kpi-refreshed', { detail: d })); } catch(e){}
|
||
})
|
||
.catch(e => console.warn('[AMBRE-V1] ambre-count failed', e));
|
||
}
|
||
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', refresh);
|
||
else refresh();
|
||
setInterval(refresh, 30000);
|
||
})();
|
||
</script>
|
||
<!-- ═══ AMBRE-V1-ERP-KPI-LIVE END ═══ -->
|
||
|
||
<script src="/opus-antioverlap-doctrine.js?v=1776777074" defer></script>
|
||
<script src="/api/weval-feature-tracker.js" defer></script>
|
||
|
||
<!-- Mega Master + Arsenal Master + Arsenal History links - 22avr2026 -->
|
||
<div id="wtp-mega-master-banner" style="background:linear-gradient(135deg,rgba(34,211,238,.08),rgba(167,139,250,.08));border:1px solid rgba(34,211,238,.3);border-radius:12px;padding:18px 22px;margin:18px 0;display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:14px;font-family:-apple-system,'Segoe UI',sans-serif">
|
||
<div>
|
||
<div style="font-size:14px;font-weight:700;background:linear-gradient(135deg,#22d3ee,#a78bfa);-webkit-background-clip:text;-webkit-text-fill-color:transparent;margin-bottom:4px">🎯 WEVAL Universe — vue globale</div>
|
||
<div style="font-size:11px;color:#94a3b8">Acces direct aux dashboards de catalogage : 747 ecrans live + 606 references uniques + 6 snapshots Arsenal historiques</div>
|
||
</div>
|
||
<div style="display:flex;gap:8px;flex-wrap:wrap">
|
||
<a href="/weval-mega-master.html" style="padding:9px 16px;background:rgba(34,211,238,.15);border:1px solid rgba(34,211,238,.4);border-radius:8px;color:#22d3ee;text-decoration:none;font-size:11px;font-weight:600">🌐 Mega Master (606)</a>
|
||
<a href="/arsenal-master.html" style="padding:9px 16px;background:rgba(52,211,153,.15);border:1px solid rgba(52,211,153,.4);border-radius:8px;color:#34d399;text-decoration:none;font-size:11px;font-weight:600">🎯 Arsenal Master (183)</a>
|
||
<a href="/arsenal-history/" style="padding:9px 16px;background:rgba(167,139,250,.15);border:1px solid rgba(167,139,250,.4);border-radius:8px;color:#a78bfa;text-decoration:none;font-size:11px;font-weight:600">📚 Arsenal History (6)</a>
|
||
<a href="/wevia-multiagent-dashboard.html" style="padding:9px 16px;background:rgba(244,114,182,.15);border:1px solid rgba(244,114,182,.4);border-radius:8px;color:#f472b6;text-decoration:none;font-size:11px;font-weight:600">🤖 Multi-Agent (2440)</a>
|
||
<a href="/wevia-memory-dashboard.html" style="padding:9px 16px;background:rgba(52,211,153,.15);border:1px solid rgba(52,211,153,.4);border-radius:8px;color:#34d399;text-decoration:none;font-size:11px;font-weight:600">🧠 Memory Unified</a>
|
||
<!-- V157 Opus orphans link · droid + e2e-dashboard added to ecosystem index -->
|
||
<a href="/droid.html" style="padding:9px 16px;background:rgba(16,185,129,.15);border:1px solid rgba(16,185,129,.4);border-radius:8px;color:#10b981;text-decoration:none;font-size:11px;font-weight:600">🤖 WEDROID Terminal (28KB)</a>
|
||
<a href="/e2e-dashboard.html" style="padding:9px 16px;background:rgba(251,191,36,.15);border:1px solid rgba(251,191,36,.4);border-radius:8px;color:#fbbf24;text-decoration:none;font-size:11px;font-weight:600">🎭 E2E Tests (8 screenshots)</a>
|
||
<a href="/dashboards-hub-unified.html" class="wtp-link" title="Hub Dashboards Unifié - 24 dashboards 13 categories wave-246" style="display:inline-flex;align-items:center;gap:6px;padding:6px 12px;background:linear-gradient(135deg,#4338ca,#6366f1);color:#fff;border-radius:6px;text-decoration:none;font-size:12px;font-weight:500;margin:0 4px"><span>📊 Hub Unifié · 24 dashboards</span></a>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<!-- V178: Archive all orphan pages -->
|
||
<div style="text-align:center;padding:20px 0;border-top:1px solid rgba(0,229,160,0.08);margin-top:40px;font-size:12px;opacity:0.6">
|
||
<a href="/archive-pages.html" style="color:#7a8899;text-decoration:none;transition:color .2s" onmouseover="this.style.color='#00e5a0'" onmouseout="this.style.color='#7a8899'">📚 Archive complète · 212 pages</a>
|
||
</div>
|
||
|
||
|
||
<!-- WAVE_262: Factory Health Monitor widget -->
|
||
<!-- WAVE_263_REPOSITION: Factory Monitor · discrete modal, no overlap -->
|
||
<!-- WAVE_264: old standalone pill removed, Factory is now in top banner -->
|
||
|
||
<div id="w263-modal" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,.8);z-index:9999;align-items:center;justify-content:center;padding:20px;font-family:system-ui,-apple-system,sans-serif" onclick="if(event.target===this)w263Close()">
|
||
<div style="max-width:900px;width:100%;background:linear-gradient(135deg,#0a0f1a,#1a1f2e);border:2px solid #22d3ee;border-radius:14px;padding:20px;box-shadow:0 20px 80px rgba(34,211,238,.4);color:#e0e7ff;max-height:85vh;overflow:auto">
|
||
<div style="display:flex;align-items:center;gap:12px;padding-bottom:12px;border-bottom:1px solid rgba(34,211,238,.3);margin-bottom:14px">
|
||
<span style="font-size:24px">🏭</span>
|
||
<h3 style="margin:0;color:#67e8f9;font-size:17px;flex:1">Factory Health Monitor · 30 agents</h3>
|
||
<span id="w263-badge" style="padding:4px 10px;border-radius:12px;background:#10b981;color:#0a0f1a;font-size:11px;font-weight:800">LOADING</span>
|
||
<button onclick="w263Close()" style="background:rgba(239,68,68,.2);border:1px solid rgba(239,68,68,.4);color:#fca5a5;padding:6px 12px;border-radius:8px;cursor:pointer;font-weight:700">✕ Fermer</button>
|
||
</div>
|
||
<div style="display:grid;grid-template-columns:1fr 2fr;gap:14px">
|
||
<div style="padding:18px;background:linear-gradient(135deg,rgba(34,211,238,.1),rgba(168,85,247,.05));border:1px solid rgba(34,211,238,.3);border-radius:10px;text-align:center">
|
||
<div id="w263-pct" style="font-size:48px;font-weight:800;color:#67e8f9;line-height:1">--%</div>
|
||
<div id="w263-counts" style="font-size:12px;color:#94a3b8;margin-top:6px">-/- agents</div>
|
||
<button onclick="w263Run(24)" style="width:100%;margin-top:14px;padding:10px;border-radius:8px;background:linear-gradient(135deg,rgba(236,72,153,.3),rgba(168,85,247,.3));color:#fbcfe8;border:1px solid rgba(236,72,153,.5);font-size:12px;cursor:pointer;font-weight:700">🚀 MAX 24 dispatch</button>
|
||
<button onclick="w263Refresh()" style="width:100%;margin-top:6px;padding:8px;border-radius:8px;background:rgba(34,211,238,.2);color:#67e8f9;border:1px solid rgba(34,211,238,.4);font-size:11px;cursor:pointer">↻ Refresh</button>
|
||
</div>
|
||
<div id="w263-agents" style="max-height:430px;overflow-y:auto;display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:5px;padding-right:4px"></div>
|
||
</div>
|
||
<div style="margin-top:10px;font-size:10px;color:#64748b;text-align:center">WAVE_263 · Discrete modal mode · Auto-refresh 30s · 30 agents Redis-persisted</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
// WAVE_263: modal-based Factory Monitor, no overlap, auto-refresh quick badge
|
||
(function(){
|
||
var autoTimer = null;
|
||
function updateQuick(){
|
||
fetch('/api/wevia-factory.php?action=health').then(function(r){return r.json();}).then(function(d){
|
||
var qb = document.getElementById('w263-quickbadge');
|
||
if (qb) qb.textContent = 'Factory: '+d.health_pct+'% ('+d.green+'/'+d.total+')'; var qb2 = document.getElementById('w264-factory-badge'); if (qb2) qb2.textContent = 'Factory: '+d.health_pct+'% ('+d.green+'/'+d.total+')';
|
||
}).catch(function(){});
|
||
}
|
||
window.w263Open = function(){
|
||
document.getElementById('w263-modal').style.display = 'flex';
|
||
w263Refresh();
|
||
};
|
||
window.w263Close = function(){
|
||
document.getElementById('w263-modal').style.display = 'none';
|
||
};
|
||
window.w263Refresh = function(){
|
||
var badge = document.getElementById('w263-badge');
|
||
badge.textContent = 'PROBING...';
|
||
badge.style.background = '#fbbf24';
|
||
fetch('/api/wevia-factory.php?action=health').then(function(r){return r.json();}).then(function(d){
|
||
document.getElementById('w263-pct').textContent = d.health_pct + '%';
|
||
document.getElementById('w263-counts').textContent = d.green+'/'+d.total+' GREEN · '+d.red+' RED';
|
||
badge.textContent = d.health_pct + '%';
|
||
badge.style.background = d.health_pct >= 90 ? '#10b981' : (d.health_pct >= 50 ? '#fbbf24' : '#ef4444');
|
||
var grid = document.getElementById('w263-agents');
|
||
grid.innerHTML = '';
|
||
Object.keys(d.results).forEach(function(k){
|
||
var r = d.results[k];
|
||
var color = r.status === 'green' ? '#10b981' : '#ef4444';
|
||
var item = document.createElement('div');
|
||
item.style.cssText = 'padding:6px 8px;background:rgba(0,0,0,.3);border-left:3px solid '+color+';border-radius:4px;font-size:11px;color:#cbd5e1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap';
|
||
item.innerHTML = (r.status==='green'?'🟢':'🔴')+' <b>'+k+'</b>'+(r.time_ms?'<span style=\'color:#64748b;margin-left:4px\'>'+r.time_ms+'ms</span>':'');
|
||
grid.appendChild(item);
|
||
});
|
||
updateQuick();
|
||
}).catch(function(){ badge.textContent='ERR'; badge.style.background='#ef4444'; });
|
||
};
|
||
window.w263Run = function(max){
|
||
var badge = document.getElementById('w263-badge');
|
||
badge.textContent = 'RUN '+max+'...';
|
||
badge.style.background = '#a855f7';
|
||
fetch('/api/wevia-factory.php?action=run',{
|
||
method:'POST',headers:{'Content-Type':'application/json'},
|
||
body:JSON.stringify({message:"Audit maximum global",max_agents:max})
|
||
}).then(function(r){return r.json();}).then(function(d){
|
||
badge.textContent = (d.agents_succeeded||0)+'/'+(d.agents_parallel||0)+' · '+(d.grade||'?');
|
||
badge.style.background = d.grade==='A'?'#10b981':'#fbbf24';
|
||
alert('MAX '+max+' · Parallel: '+d.agents_parallel+' · Succeeded: '+d.agents_succeeded+' · Grade: '+d.grade+' · '+d.total_duration_ms+'ms\n\n'+(d.response||'').slice(0,400));
|
||
setTimeout(w263Refresh,1500);
|
||
}).catch(function(){ badge.textContent='ERR'; badge.style.background='#ef4444'; });
|
||
};
|
||
// Auto-update quick badge every 30s
|
||
setTimeout(updateQuick, 2000);
|
||
setInterval(updateQuick, 30000);
|
||
})();
|
||
</script>
|
||
|
||
<!-- === WAVE-277 PHASE-7 WTP ORPHANS AUTO-INTEGRATION (Opus wave-278) === -->
|
||
<!-- Doctrine 14: enrichir pas écraser | Zero régression | Load registry API + render cards -->
|
||
<style id="wtp-orphans-style">
|
||
#wtp-orphans-panel{margin:40px auto;max-width:1400px;padding:0 20px;font-family:'Inter',system-ui,sans-serif}
|
||
#wtp-orphans-panel .op-hdr{display:flex;justify-content:space-between;align-items:flex-end;margin-bottom:20px;flex-wrap:wrap;gap:16px}
|
||
#wtp-orphans-panel .op-title{font-size:1.6rem;font-weight:700;color:#f1f5f9;margin:0;letter-spacing:-.02em}
|
||
#wtp-orphans-panel .op-subtitle{font-size:.85rem;color:#94a3b8;margin-top:6px}
|
||
#wtp-orphans-panel .op-kpis{display:flex;gap:16px;flex-wrap:wrap}
|
||
#wtp-orphans-panel .op-kpi{background:rgba(15,23,42,.6);border:1px solid rgba(148,163,184,.15);padding:10px 16px;border-radius:10px;backdrop-filter:blur(8px)}
|
||
#wtp-orphans-panel .op-kpi-val{font-size:1.2rem;font-weight:700;color:#06b6d4}
|
||
#wtp-orphans-panel .op-kpi-lbl{font-size:.7rem;color:#94a3b8;text-transform:uppercase;letter-spacing:1px}
|
||
#wtp-orphans-panel .op-tabs{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:20px}
|
||
#wtp-orphans-panel .op-tab{background:rgba(30,41,59,.8);border:1px solid rgba(148,163,184,.15);color:#cbd5e1;padding:8px 14px;border-radius:8px;font-size:.8rem;cursor:pointer;transition:all .15s}
|
||
#wtp-orphans-panel .op-tab:hover{background:rgba(6,182,212,.1);border-color:rgba(6,182,212,.4);color:#06b6d4}
|
||
#wtp-orphans-panel .op-tab.ac{background:rgba(6,182,212,.15);border-color:#06b6d4;color:#06b6d4}
|
||
#wtp-orphans-panel .op-tab .cnt{margin-left:6px;background:rgba(148,163,184,.2);padding:1px 7px;border-radius:10px;font-size:.7rem}
|
||
#wtp-orphans-panel .op-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:14px}
|
||
#wtp-orphans-panel .op-card{background:rgba(15,23,42,.5);border:1px solid rgba(148,163,184,.15);border-radius:10px;padding:12px;transition:all .15s;cursor:pointer;text-decoration:none;display:flex;flex-direction:column;gap:8px}
|
||
#wtp-orphans-panel .op-card:hover{border-color:#06b6d4;background:rgba(6,182,212,.06);transform:translateY(-2px)}
|
||
#wtp-orphans-panel .op-card .thumb{width:100%;aspect-ratio:16/10;background:rgba(30,41,59,.8);border-radius:6px;background-size:cover;background-position:center;flex-shrink:0}
|
||
#wtp-orphans-panel .op-card .thumb.no-thumb{display:flex;align-items:center;justify-content:center;color:#64748b;font-size:2rem}
|
||
#wtp-orphans-panel .op-card .name{font-size:.82rem;font-weight:600;color:#e2e8f0;margin:0;word-break:break-word}
|
||
#wtp-orphans-panel .op-card .badge{font-size:.65rem;color:#94a3b8;text-transform:uppercase;letter-spacing:.5px;display:inline-block;padding:2px 6px;background:rgba(30,41,59,.6);border-radius:4px;width:fit-content}
|
||
#wtp-orphans-panel .op-search{background:rgba(15,23,42,.6);border:1px solid rgba(148,163,184,.2);color:#e2e8f0;padding:8px 14px;border-radius:8px;font-size:.85rem;margin-bottom:14px;width:280px;outline:none}
|
||
#wtp-orphans-panel .op-search:focus{border-color:#06b6d4}
|
||
</style>
|
||
|
||
<div id="wtp-orphans-panel">
|
||
<div class="op-hdr">
|
||
<div>
|
||
<h2 class="op-title">🔗 Orphans Auto-Registry</h2>
|
||
<div class="op-subtitle">Pages HTML non-reliées à WTP — rattachement zéro écrasement · rendu temps réel depuis <code>/api/wtp-orphans-registry.php</code></div>
|
||
</div>
|
||
<div class="op-kpis" id="op-kpis-container">
|
||
<div class="op-kpi"><div class="op-kpi-val" id="op-total">—</div><div class="op-kpi-lbl">Total HTML</div></div>
|
||
<div class="op-kpi"><div class="op-kpi-val" id="op-linked">—</div><div class="op-kpi-lbl">Linked WTP</div></div>
|
||
<div class="op-kpi"><div class="op-kpi-val" id="op-orphans">—</div><div class="op-kpi-lbl">Orphans</div></div>
|
||
<div class="op-kpi"><div class="op-kpi-val" id="op-coverage">—</div><div class="op-kpi-lbl">Link rate</div></div>
|
||
</div>
|
||
</div>
|
||
<input type="text" class="op-search" id="op-search" placeholder="🔍 filter by name..." />
|
||
<div class="op-tabs" id="op-tabs"></div>
|
||
<div class="op-grid" id="op-grid"></div>
|
||
</div>
|
||
|
||
<script>
|
||
(async function wtpOrphans(){
|
||
try {
|
||
const r = await fetch('/api/wtp-orphans-registry.php?t='+Date.now());
|
||
const d = await r.json();
|
||
if(!d.ok) return;
|
||
|
||
// KPIs
|
||
document.getElementById('op-total').textContent = d.total_html;
|
||
document.getElementById('op-linked').textContent = d.linked_in_wtp;
|
||
document.getElementById('op-orphans').textContent = d.orphans_count;
|
||
document.getElementById('op-coverage').textContent = d.link_rate_pct + '%';
|
||
|
||
// Tabs per category - hide legacy/doublon/deprecated by default (less relevant)
|
||
const cats = d.categories || {};
|
||
const catOrder = ['ACTIVE_HUB','ACTIVE_DASHBOARD','ACTIVE_ADMIN','ACTIVE_AGENT','ACTIVE_BLADE','ACTIVE_AI','ACTIVE_CRM','ACTIVE_PRODUCT','ACTIVE_OTHER','LEGACY','DOUBLON','TESTS','DEPRECATED'];
|
||
const tabsEl = document.getElementById('op-tabs');
|
||
const catsPresent = catOrder.filter(c => cats[c] && cats[c].length > 0);
|
||
const allBtn = `<button class="op-tab ac" data-cat="__all">All<span class="cnt">${d.orphans_count}</span></button>`;
|
||
tabsEl.innerHTML = allBtn + catsPresent.map(c => {
|
||
const lbl = c.replace('ACTIVE_','').replace('_',' ');
|
||
return `<button class="op-tab" data-cat="${c}">${lbl}<span class="cnt">${cats[c].length}</span></button>`;
|
||
}).join('');
|
||
|
||
// Merge flat list with category info
|
||
const all = [];
|
||
for(const c of catsPresent) {
|
||
for(const item of cats[c]) {
|
||
all.push({...item, _cat: c});
|
||
}
|
||
}
|
||
|
||
const gridEl = document.getElementById('op-grid');
|
||
const searchEl = document.getElementById('op-search');
|
||
let activeCat = '__all';
|
||
let searchTerm = '';
|
||
|
||
function render(){
|
||
const filtered = all.filter(i => {
|
||
if(activeCat !== '__all' && i._cat !== activeCat) return false;
|
||
if(searchTerm && !i.name.toLowerCase().includes(searchTerm)) return false;
|
||
return true;
|
||
});
|
||
if(filtered.length === 0) {
|
||
gridEl.innerHTML = '<div style="color:#94a3b8;padding:40px;text-align:center;grid-column:1/-1">No pages match</div>';
|
||
return;
|
||
}
|
||
gridEl.innerHTML = filtered.map(i => {
|
||
const url = '/' + i.name;
|
||
const thumb = i.thumb_url ? `<div class="thumb" style="background-image:url('${i.thumb_url}')"></div>` : `<div class="thumb no-thumb">📄</div>`;
|
||
const catBadge = i._cat.replace('ACTIVE_','').toLowerCase();
|
||
return `<a class="op-card" href="${url}" target="_blank" title="${i.name}">${thumb}<div class="name">${i.name.replace('.html','')}</div><span class="badge">${catBadge}</span></a>`;
|
||
}).join('');
|
||
}
|
||
|
||
// Tab click
|
||
tabsEl.addEventListener('click', (e) => {
|
||
const t = e.target.closest('.op-tab');
|
||
if(!t) return;
|
||
tabsEl.querySelectorAll('.op-tab').forEach(x => x.classList.remove('ac'));
|
||
t.classList.add('ac');
|
||
activeCat = t.dataset.cat;
|
||
render();
|
||
});
|
||
|
||
// Search input
|
||
searchEl.addEventListener('input', (e) => {
|
||
searchTerm = e.target.value.toLowerCase().trim();
|
||
render();
|
||
});
|
||
|
||
render();
|
||
console.log('[WTP Orphans] loaded', d.orphans_count, 'orphans across', catsPresent.length, 'active categories');
|
||
} catch(e) {
|
||
console.warn('[WTP Orphans] load failed:', e);
|
||
document.getElementById('wtp-orphans-panel').style.display = 'none';
|
||
}
|
||
})();
|
||
</script>
|
||
<!-- === END WAVE-277 PHASE-7 === -->
|
||
|
||
</body>
|
||
</html>
|