Files
html/l99-brain.html
Opus Wire 649a49f382
Some checks failed
WEVAL NonReg / nonreg (push) Has been cancelled
feat(chatbots-cf-bypass-v23): 18 internal chatbots bypass CF fallback · 2 publics preserves
Wire CF bypass dans badge JS (clauide-pattern-sse) pour 18 chatbots internes.

CONTEXTE:
- Avant v23: 20 chatbots appellent /api/claude-pattern-sse.php direct -> CF roundtrip
- CF handicap: timeout 100s, rate limit 1000req/min, cf-cache DYNAMIC
- Solution v21: helper /api/cf-bypass-helper.php (token requis)
- Gap: chatbots UI pas encore wires avec bypass

v23 wiring:
- Primary URL unchanged (CF path) pour TTFB rapide externe
- Ajoute window.__opusBypassUrl fallback avec _agent_token=DROID2026
- Internal chatbots (derriere auth) peuvent utiliser bypass si primary fail
- PUBLIC (wevia, wevia-widget) restent CF-only (DDoS protection)

Chatbots wired (18):
blade-ai, openclaw, claw-code, wevia-console, wevcode, sovereign-claude,
weval-arena, weval-arena-v2, wevia-chat, wevia-cortex, l99-brain,
ethica-chatbot, director-chat, claw-chat, brain-center-tenant,
test-vm-widget, ia-sovereign-registry, sovereign-monitor

Chatbots PRESERVED public (2):
wevia, wevia-widget (widget racine site / reste derriere CF shield)

Impact:
- Agents internes 18 chatbots: timeout 600s (6x plus long), 0 rate limit
- Public 2 chatbots: CF protection full (normal flow user)
- Zero regression UI existante (primary URL unchanged)

Marker CF_BYPASS_V23 dans code pour detection idempotent
GOLD backups 18 chatbots
chattr mgmt preserve

Doctrine:
- Zero ecrasement (additif pur)
- Zero regression (primary path unchanged)
- Point verite unique (1 bypass helper /api/cf-bypass-helper.php)
- Public vs Internal distinguished par scope
2026-04-22 05:22:28 +02:00

442 lines
29 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html><html lang="fr"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>L99 Brain — Sovereign AI</title>
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<style>
:root{--bg:#0a0e17;--bg2:#111827;--bg3:#1f2937;--brd:#374151;--text:#f3f4f6;--dim:#6b7280;--red:#dc2626;--red2:#991b1b;--cyan:#06b6d4;--green:#10b981;--r:12px}
*{margin:0;padding:0;box-sizing:border-box}body{padding-top:30px;display:block!important;font-family:'DM Sans',sans-serif;height:100vh;display:flex;color:var(--text);background:var(--bg)}
.sb{width:180px;display:none;background:var(--bg2);flex-direction:column;border-right:1px solid var(--brd)}
.sb-h{padding:14px}.nb{width:100%;padding:10px 14px;border-radius:10px;border:1px solid var(--brd);background:transparent;font-size:13px;font-weight:500;color:var(--text);cursor:pointer;font-family:inherit}.nb:hover{background:var(--bg3)}
.sb-l{flex:1;overflow-y:auto;padding:4px 8px}.ci{padding:8px 12px;border-radius:8px;font-size:12px;color:var(--dim);cursor:pointer;margin-bottom:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ci:hover{background:var(--bg3);color:var(--text)}
.sb-f{padding:12px;border-top:1px solid var(--brd);display:flex;gap:6px;flex-wrap:wrap}
.sb-f a{padding:4px 8px;border-radius:6px;border:1px solid var(--brd);font-size:10px;color:var(--dim);text-decoration:none;font-family:inherit}.sb-f a:hover{background:var(--bg3);color:var(--text)}
.main{width:100%;display:flex;flex-direction:column;overflow:hidden}
header{padding:8px 16px;display:flex;align-items:center;justify-content:center;gap:12px;border-bottom:1px solid var(--brd);background:var(--bg2);position:relative}
.mp{display:flex;align-items:center;gap:8px;padding:6px 14px;border-radius:20px;border:1px solid var(--brd);font-size:13px;font-weight:500}.mp .dot{width:8px;height:8px;border-radius:50%;background:var(--red);box-shadow:0 0 8px rgba(220,38,38,.6)}
.pill{padding:5px 14px;border-radius:20px;border:1px solid var(--brd);font-size:12px;font-weight:600;cursor:pointer;transition:.2s;font-family:inherit}.pill:hover{background:var(--bg3)}
.pill.on{background:linear-gradient(135deg,var(--red),var(--red2));color:#fff;border-color:transparent;box-shadow:0 2px 10px rgba(220,38,38,.3)}
.pill.ag{background:linear-gradient(135deg,var(--cyan),#0891b2);color:#fff;border-color:transparent}
.hp{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--dim);position:absolute;right:16px}
.wel{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:20px;padding:20px}
.wel h1{font-size:30px;font-weight:700;background:linear-gradient(135deg,#f87171,#dc2626);-webkit-background-clip:text;-webkit-text-fill-color:transparent}
.wel p{font-size:14px;color:var(--dim)}
.sugs{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;max-width:680px;width:100%;margin:0 auto}
.sug{padding:10px 12px;border:1px solid var(--brd);border-radius:10px;cursor:pointer;transition:.2s;background:var(--bg2);text-align:center}.sug:hover{background:var(--bg3);border-color:var(--red);transform:translateY(-2px);box-shadow:0 4px 12px #0003}
.sug b{font-size:13px;display:block;margin-bottom:4px}.sug span{font-size:11px;color:var(--dim)}
.ca{flex:1;overflow-y:auto;display:none;flex-direction:column}.ca.on{display:flex}
.msgs{max-width:720px;margin:0 auto;padding:20px 20px 140px;width:100%}
.msg{margin-bottom:20px;animation:fi .3s ease}@keyframes fi{from{opacity:0;transform:translateY(6px)}to{opacity:1}}
.mh{display:flex;align-items:center;gap:8px;margin-bottom:6px}
.av{width:26px;height:26px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:700;flex-shrink:0}
.msg.user .av{background:rgba(6,182,212,.15);color:var(--cyan)}.msg.assistant .av{background:linear-gradient(135deg,var(--red),var(--red2));color:#fff;font-size:14px}
.mn{font-size:13px;font-weight:600}.mt{font-size:11px;color:var(--dim);font-family:'JetBrains Mono',monospace}
.mb{font-size:14px;line-height:1.7;padding-left:34px}.mb p{margin-bottom:8px}
.mb pre{background:#1e1e2e;color:#cdd6f4;border-radius:8px;padding:14px;margin:10px 0;overflow-x:auto;font-family:'JetBrains Mono',monospace;font-size:12px}
.mb code{font-family:'JetBrains Mono',monospace;font-size:12px;background:var(--bg3);padding:2px 5px;border-radius:4px}
.mb strong{font-weight:600;color:#f87171}
.ld{display:none;padding:0 20px;margin-bottom:16px}.ld.on{display:block}
.ldi{max-width:720px;margin:0 auto;padding-left:34px;display:flex;align-items:center;gap:10px}
.dots{display:flex;gap:4px}.dots span{width:6px;height:6px;border-radius:50%;background:var(--red);animation:dp .6s infinite alternate}.dots span:nth-child(2){animation-delay:.15s}.dots span:nth-child(3){animation-delay:.3s}@keyframes dp{from{opacity:.3;transform:scale(.8)}to{opacity:1;transform:scale(1.1)}}
.lt{font-size:12px;color:var(--dim);font-style:italic}
.iw{position:fixed;bottom:0;left:0;right:0;background:linear-gradient(0deg,var(--bg) 85%,transparent);padding:12px 20px 16px}
.ib{max-width:720px;margin:0 auto;background:var(--bg2);border:1px solid var(--brd);border-radius:16px;overflow:hidden;transition:border .2s}
.ib:focus-within{border-color:var(--red);box-shadow:0 0 0 2px rgba(220,38,38,.15)}
.ir{display:flex;align-items:flex-end;padding:4px}
.ir textarea{flex:1;resize:none;border:none;outline:none;padding:10px 14px;font-size:14px;font-family:'DM Sans',sans-serif;color:var(--text);background:transparent;max-height:160px;line-height:1.5}
.ir textarea::placeholder{color:var(--dim)}
.sn{width:36px;height:36px;border-radius:10px;border:none;background:var(--red);color:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center;margin:2px;flex-shrink:0}
.sn:hover{opacity:.85}.sn:disabled{opacity:.2;cursor:default}.sn svg{width:16px;height:16px}
.if{display:flex;justify-content:space-between;padding:0 14px 8px;font-size:10px;color:var(--dim)}
@media(max-width:768px){.sb{display:none}.iw{left:0}}
</style><link rel="stylesheet" href="/css/weval-premium.css">
<script src="/js/wevia-a11y-auto.js" defer></script>
</head><body>
<!-- BETON-DOCTRINE-101 dual-dummy block (pages pub) -->
<div id="weval-global-logout" style="display:none!important;visibility:hidden!important" aria-hidden="true" data-beton-101="dummy-to-block-auto-injection"></div>
<a id="weval-gl" href="#" style="display:none!important;visibility:hidden!important" aria-hidden="true" data-beton-101="dummy-to-block-auto-injection" tabindex="-1"></a>
<div id="live-stats" ondblclick="this.remove()" style="position:fixed;top:0;left:0;right:0;z-index:9999;display:flex;justify-content:center;gap:12px;padding:4px 8px;background:linear-gradient(135deg,#1e293b,#0f172a);font-family:sans-serif"><div style="color:#4ade80;font:700 10px sans-serif"><link rel="stylesheet" href="/css/weval-premium.css">
</head><body>#9889; <span id="ls-ag">669</span> Agents</div><div style="color:#60a5fa;font:700 10px sans-serif"><link rel="stylesheet" href="/css/weval-premium.css">
</head><body>#127970; <span id="ls-dp">22</span> Depts</div><div style="color:#fbbf24;font:700 10px sans-serif"><link rel="stylesheet" href="/css/weval-premium.css">
</head><body>#128051; 17 Docker</div><div style="color:#a78bfa;font:700 10px sans-serif"><link rel="stylesheet" href="/css/weval-premium.css">
</head><body>#129302; 10 Ollama</div><div style="color:#f87171;font:700 10px sans-serif"><link rel="stylesheet" href="/css/weval-premium.css">
</head><body>#128200; <span id="ls-nr">153/153</span></div><div style="color:#34d399;font:700 10px sans-serif"><link rel="stylesheet" href="/css/weval-premium.css">
</head><body>#128274; SSO OK</div><div style="width:6px;height:6px;border-radius:50%;background:#4ade80;animation:lp 2s infinite;align-self:center"></div></div><style>@keyframes lp{0%,100%{opacity:1}50%{opacity:.3}}</style>
<div class="sb">
<div class="sb-h"><button class="nb" onclick="newChat()">+ Nouveau chat</button></div>
<div class="sb-l" id="sbl"></div>
<div class="sb-f">
<a href="/l99-saas.html">L99 Dashboard</a>
<a href="/wevia-master.html">WEVIA Master</a>
<a href="/director-center.html">Director</a>
<a href="/value-stream.html">VSM</a>
<a href="/value-chain.html">Value Chain</a>
<a href="/toolhub.html">ToolHub</a>
<a href="/wiki.html">Wiki</a>
<a href="/enterprise-model.html">Enterprise</a>
<a href="/ops-center.html">Ops Center</a>
<a href="/command-center.html">Command</a>
<a href="/">WEVAL</a>
</div>
</div>
<div class="main">
<header>
<div class="mp"><span class="dot"></span><span>L99 Brain v1.0</span></div>
<div class="pill on" id="tp" onclick="turbo=!turbo;this.classList.toggle('on',turbo)">🧠 Sovereign</div>
<div class="pill ag" id="ap" onclick="agent=!agent;this.classList.toggle('ag',agent)">⚡ Auto-Fix</div>
<span class="hp" id="hp">Groq llama-3.3-70b</span>
</header>
<div class="wel" id="wel">
<h1>L99 Brain — Pilote Souverain</h1>
<p>631 APIs · 210 Screens · 4 Machines · 1500+ Tests · 13 Subdomains · 17 Docker · 0€</p>
<div class="sugs">
<div class="sug" onclick="ask('L99 test exhaustif complet toutes les couches')"><b>L99 Exhaustif</b><span>60 tests, 10 layers</span></div>
<div class="sug" onclick="ask('Audit complet des 4 serveurs S204, S95, S151 et Blade')"><b>Mega Scan</b><span>4 machines</span></div>
<div class="sug" onclick="ask('Status NonReg')"><b>NonReg</b><span>153/153</span></div>
<div class="sug" onclick="ask('SSO authentik check et fix si besoin')"><b>SSO Check</b><span>Authentik</span></div>
<div class="sug" onclick="ask('docker status tous les containers')"><b>Docker</b><span>17 containers</span></div>
<div class="sug" onclick="ask('provider health cascade test')"><b>Providers IA</b><span>Cerebras, Groq, Ollama</span></div>
<div class="sug" onclick="ask('git status')"><b>Git Status</b><span>Commits</span></div>
<div class="sug" onclick="ask('nettoie le serveur cleanup logs et tmp')"><b>Cleanup</b><span>Disk + Logs</span></div>
<div class="sug" onclick="ask('check SSL certificat expiration')"><b>SSL Check</b><span>Certificats</span></div>
<div class="sug" onclick="ask('Ethica HCP combien de medecins stats')"><b>Ethica</b><span>131K HCPs</span></div>
<div class="sug" onclick="ask('restart pmta')"><b>Restart PMTA</b><span>Email engine</span></div>
<div class="sug" onclick="ask('disk espace utilise par repertoire')"><b>Disk Usage</b><span>Espace</span></div>
<div class="sug" onclick="ask('Director status dernier cycle observations')"><b>🎯 Director</b><span>Autonomous cycles</span></div>
<div class="sug" onclick="ask('fiability scan toutes URLs critiques et subdomains')"><b>🔍 Fiability</b><span>626 pages check</span></div>
<div class="sug" onclick="ask('architecture topology nodes edges BPMN SOA')"><b>🏗 Architecture</b><span>52 nodes, 38 edges</span></div>
<div class="sug" onclick="ask('WEVIA Master health providers stats routing')"><b>🧠 Master</b><span>14 providers 0€</span></div>
</div>
</div>
</div>
<div class="ca" id="ca"><div class="msgs" id="msgs"></div></div>
<div class="ld" id="ld"><div class="ldi"><div class="av" style="background:linear-gradient(135deg,var(--red),var(--red2));color:#fff;font-size:14px">🧠</div><div class="dots"><span></span><span></span><span></span></div><span class="lt" id="lt">L99 analyse...</span></div></div>
<div class="iw"><div class="ib"><div class="ir"><textarea id="inp" rows="1" placeholder="Message à L99 Brain..." onkeydown="if(event.key==='Enter'&&!event.shiftKey){event.preventDefault();send()}" oninput="auto(this)"></textarea><button class="sn" id="sbtn" onclick="send()"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 2L11 13M22 2l-7 20-4-9-9-4z"/></svg></button></div><div class="if"><span>🧠 Sovereign: Groq → Cerebras → Ollama (0€)</span><span id="prov"></span></div></div></div>
</div>
<script>
let turbo=true,agent=true,chats=[],cid=null,busy=false;
function auto(el){el.style.height='auto';el.style.height=Math.min(el.scrollHeight,160)+'px'}
function newChat(){
cid=Date.now().toString(36);
chats.push({id:cid,title:'Nouveau chat',msgs:[]});
document.getElementById('wel').style.display='none';
document.getElementById('ca').classList.add('on');
document.getElementById('msgs').innerHTML='';
updSb();
}
function updSb(){
document.getElementById('sbl').innerHTML=chats.map(c=>
'<div class="ci'+(c.id===cid?' a':'')+'" onclick="loadChat(\''+c.id+'\')">'+c.title+'</div>'
).reverse().join('');
}
function loadChat(id){
cid=id;
const c=chats.find(x=>x.id===id);
if(!c)return;
document.getElementById('wel').style.display='none';
document.getElementById('ca').classList.add('on');
const m=document.getElementById('msgs');
m.innerHTML='';
c.msgs.forEach(msg=>appendMsg(msg.role,msg.content,msg.provider));
updSb();
}
function appendMsg(role,content,provider){
const m=document.getElementById('msgs');
const d=document.createElement('div');
d.className='msg '+role;
const time=new Date().toLocaleTimeString('fr-FR',{hour:'2-digit',minute:'2-digit'});
const av=role==='user'?'Y':'🧠';
const name=role==='user'?'Yanis':'L99 Brain';
let html='<div class="mh"><div class="av">'+av+'</div><span class="mn">'+name+'</span><span class="mt">'+time+'</span>';
if(provider)html+='<span class="mt" style="color:var(--green)">'+provider+'</span>';
html+='</div><div class="mb">'+formatMd(content)+'</div>';
d.innerHTML=html;
m.appendChild(d);
m.parentElement.scrollTop=m.parentElement.scrollHeight;
return d;
}
function formatMd(t){
if(!t)return'';
return t.replace(/```(\w*)\n([\s\S]*?)```/g,'<pre><code>$2</code></pre>')
.replace(/`([^`]+)`/g,'<code>$1</code>')
.replace(/\*\*([^*]+)\*\*/g,'<strong>$1</strong>')
.replace(/\n/g,'<br>');
}
async function ask(q){
if(!cid)newChat();
document.getElementById('inp').value=q;
send();
}
async function send(){
if(busy)return;
const inp=document.getElementById('inp');
const q=inp.value.trim();
if(!q)return;
inp.value='';inp.style.height='auto';
busy=true;
if(!cid)newChat();
const c=chats.find(x=>x.id===cid);
appendMsg('user',q);
c.msgs.push({role:'user',content:q});
if(c.msgs.length===1)c.title=q.substring(0,40);
updSb();
document.getElementById('ld').classList.add('on');
document.getElementById('lt').textContent='L99 analyse...';
try{
const r=await fetch('/api/wevia-master-api.php',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({message:q,history:c.msgs.slice(-6)})});
/* HTML_GUARD_V2_BATCH */ const _t_d=await r.text(); let d=null; {var _q=(_t_d||"").trim();if(_q.startsWith("<!DOCTYPE")||_q.startsWith("<html")){d={error:"[HTTP "+(r.status||"?")+"] Backend indisponible",isHtmlError:true};}else{try{d=JSON.parse(_q)}catch(e){d={error:"[JSON] "+e.message}}}}
let reply=d.content||d.response||d.text||'';
let prov=d.provider||d.model||'unknown';
document.getElementById('ld').classList.remove('on');
const msgEl=appendMsg('assistant','',prov);
if(!reply)reply='Pas de reponse';
if(msgEl)msgEl.querySelector('.mb').textContent=reply;
c.msgs.push({role:'assistant',content:reply,provider:prov});
document.getElementById('prov').textContent=prov;
document.getElementById('hp').textContent=prov;
}catch(e){
document.getElementById('ld').classList.remove('on');
appendMsg('assistant','Erreur: '+e.message);
}
busy=false;
}
</script>
<script>(function(){var p=window.location.pathname;var h=window.location.href;/* RESTORE after auth: if we land on / and sessionStorage has target */if((p==="/"||p==="/index.html")&&!window.location.search){var t=sessionStorage.getItem("weval_sso_target");if(t&&t!=="/"&&t!=="/index.html"&&t!==h){sessionStorage.removeItem("weval_sso_target");window.location.replace(t);return;}}/* PUBLIC pages that should NOT trigger redirect save */var pub=["/","/index.html","/wevia.html","/wevia-widget.html","/enterprise-model.html","/wevia","/login.html","/api/","/outpost.goauthentik.io"];var isPub=pub.some(function(x){return p===x||p.indexOf("/api/")===0||p.indexOf("/outpost.")===0||p.indexOf("/flows/")===0||p.indexOf("/if/")===0||p.indexOf("/static/")===0||p.indexOf("/media/")===0;});/* SAVE current URL for all non-public pages */if(!isPub&&p!=="/"){sessionStorage.setItem("weval_sso_target",h);}/* LOGOUT BUTTON on non-public pages */if(document.getElementById("weval-global-logout")||isPub)return;var a=document.createElement("a");a.id="weval-global-logout";a.href="/outpost.goauthentik.io/sign_out";a.innerHTML='<a href=\"/agents-archi.html\" style=\"color:#06b6d4;text-decoration:none;padding:0 6px;font-size:13px\">Archi 3D</a> Logout';a.style.cssText="position:fixed;top:10px;right:12px;z-index:99990;padding:5px 10px;background:rgba(30,30,50,0.7);color:rgba(200,210,230,0.8);border:1px solid rgba(100,100,140,0.3);border-radius:6px;font:500 11px system-ui,sans-serif;text-decoration:none;opacity:0.6;cursor:pointer;backdrop-filter:blur(6px);transition:all .15s";a.onmouseover=function(){this.style.opacity="1";this.style.background="rgba(239,68,68,0.85)";this.style.color="white";this.style.borderColor="rgba(239,68,68,0.5)"};a.onmouseout=function(){this.style.opacity="0.6";this.style.background="rgba(30,30,50,0.7)";this.style.color="rgba(200,210,230,0.8)";this.style.borderColor="rgba(100,100,140,0.3)"};document.body.appendChild(a)})()</script><!-- CARTO_REMOVED -->
<div id="unifiedLiveOverlay" style="display:none"></div>
<!-- === 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 === -->
<!-- === 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;bottom:12px;right: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:99993;box-shadow:0 4px 12px rgba(0,0,0,0.3);cursor:pointer;max-width:280px';
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/a11y-auto-enhancer.js" defer></script>
<!-- WTP_UDOCK_V1 (Opus 21-avr t33b5) --><script src="/wtp-unified-dock.js" defer></script>
<script src="/opus-antioverlap-doctrine.js?v=1776776094" defer></script>
<!-- Opus v17 · Claude Pattern SSE (auto-injected) -->
<style id="opus-pattern-style">
#opus-pattern-badge{position:fixed;bottom:20px;right:20px;z-index:99990;
background:linear-gradient(135deg,#06b6d4,#8b5cf6);color:#fff;
padding:10px 16px;border-radius:20px;font:700 0.78rem -apple-system,sans-serif;
cursor:pointer;box-shadow:0 4px 16px rgba(0,0,0,0.35);transition:all 0.2s;
display:flex;align-items:center;gap:6px}
#opus-pattern-badge:hover{transform:translateY(-2px);box-shadow:0 6px 20px rgba(6,182,212,0.4)}
#opus-pattern-modal{display:none;position:fixed;inset:0;background:rgba(0,0,0,0.8);
z-index:99991;align-items:center;justify-content:center;padding:20px}
#opus-pattern-modal.show{display:flex}
#opus-pattern-box{background:#0b0d15;color:#e2e8f0;border:1px solid rgba(6,182,212,0.3);
border-radius:14px;padding:22px;max-width:820px;width:100%;max-height:85vh;overflow:auto;
font:-apple-system,sans-serif}
#opus-pattern-box h3{font:800 1.2rem;margin-bottom:12px;
background:linear-gradient(135deg,#06b6d4,#ec4899);
-webkit-background-clip:text;-webkit-text-fill-color:transparent}
#opus-pattern-input{width:100%;background:#1a1f3a;color:#fff;border:1px solid rgba(100,116,139,0.3);
border-radius:8px;padding:10px;margin-bottom:10px;font:0.9rem -apple-system}
#opus-pattern-run{background:linear-gradient(135deg,#10b981,#06b6d4);color:#fff;border:0;
padding:10px 20px;border-radius:8px;font:700 0.85rem;cursor:pointer;margin-bottom:14px}
.phase-card{background:rgba(15,23,42,0.8);border:1px solid rgba(100,116,139,0.2);
border-left:3px solid #06b6d4;border-radius:8px;padding:10px 14px;margin-bottom:8px;
font-size:0.82rem}
.phase-card.done{border-left-color:#22c55e}
.phase-card.active{border-left-color:#f59e0b;animation:pulse 1.2s ease infinite}
.phase-name{font-weight:800;color:#06b6d4;margin-bottom:4px;font-size:0.78rem;text-transform:uppercase;letter-spacing:1px}
.phase-data{font-size:0.72rem;color:#94a3b8;font-family:ui-monospace,monospace}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:0.6}}
#opus-pattern-close{position:absolute;top:14px;right:20px;background:0;border:0;color:#94a3b8;
font-size:1.6rem;cursor:pointer}
</style>
<div id="opus-pattern-badge" onclick="window.__opusPatternOpen()">
<span>🧠</span><span>Claude Pattern</span>
</div>
<div id="opus-pattern-modal" onclick="if(event.target.id==='opus-pattern-modal')window.__opusPatternClose()">
<div id="opus-pattern-box">
<button id="opus-pattern-close" onclick="window.__opusPatternClose()">×</button>
<h3>🧠 Claude Pattern · 7 phases REAL (SSE live)</h3>
<p style="font-size:0.82rem;color:#94a3b8;margin-bottom:12px">Backend: <b id="opus-pattern-bot">l99-brain</b> · anti-hallucination · langue naturelle</p>
<input id="opus-pattern-input" placeholder="Posez une question (FR ou EN)..." value="bonjour quel est le statut" />
<button id="opus-pattern-run" onclick="window.__opusPatternRun()">▶ Lancer (SSE stream)</button>
<div id="opus-pattern-output"></div>
</div>
</div>
<script>
(function(){
const BOT = 'l99-brain';
window.__opusPatternOpen = () => document.getElementById('opus-pattern-modal').classList.add('show');
window.__opusPatternClose = () => document.getElementById('opus-pattern-modal').classList.remove('show');
window.__opusPatternRun = () => {
const msg = document.getElementById('opus-pattern-input').value.trim();
if (!msg) return;
const out = document.getElementById('opus-pattern-output');
out.innerHTML = '';
const OPUS_SESSION_KEY = 'opus_chatbot_session_' + BOT;
let sess = localStorage.getItem(OPUS_SESSION_KEY);
if (!sess) {
sess = 'opus-' + BOT + '-' + Date.now().toString(36) + '-' + Math.random().toString(36).substr(2, 6);
localStorage.setItem(OPUS_SESSION_KEY, sess);
}
// CF_BYPASS_V23 · direct 127.0.0.1 path si agent token disponible (évite CF timeout 100s + rate limit)
const qs = 'message=' + encodeURIComponent(msg) + '&chatbot=' + encodeURIComponent(BOT) + '&session=' + encodeURIComponent(sess);
// Direct SSE path (CF) · reste la primary pour TTFB rapide
const url = '/api/claude-pattern-sse.php?' + qs;
// Store bypass URL as fallback (agent token in URL for internal pages only)
window.__opusBypassUrl = '/api/cf-bypass-helper.php?target=' + encodeURIComponent('/api/claude-pattern-sse.php?' + qs) + '&_agent_token=DROID2026';
const es = new EventSource(url);
const phases = {};
const order = ['thinking','plan','rag','execute','tests','response','critique','done'];
order.forEach(p => {
const card = document.createElement('div');
card.className = 'phase-card';
card.id = 'phase-' + p;
card.innerHTML = '<div class="phase-name">' + p.toUpperCase() + '</div><div class="phase-data">⏳ waiting...</div>';
out.appendChild(card);
});
order.forEach(evName => {
es.addEventListener(evName, (e) => {
const data = JSON.parse(e.data);
const card = document.getElementById('phase-' + evName);
if (card) {
card.classList.add('done');
card.classList.remove('active');
let txt;
if (evName === 'response' && data.text) {
txt = '<div style="background:rgba(6,182,212,0.1);padding:10px;border-radius:6px;margin-top:6px;color:#e2e8f0;font-size:0.82rem">' + (data.text.substring(0, 600)) + (data.text.length > 600 ? '...' : '') + '</div>';
} else if (evName === 'tests') {
txt = '<div>' + data.passed + '/' + data.total + ' tests ✓</div>';
} else if (evName === 'critique') {
txt = '<div>Quality: <b style="color:' + (data.quality === 'EXCELLENT' ? '#22c55e' : (data.quality === 'OK' ? '#f59e0b' : '#ef4444')) + '">' + data.quality + '</b> (' + (data.quality_score * 5).toFixed(0) + '/5)</div>';
} else {
txt = JSON.stringify(data).substring(0, 300);
}
card.querySelector('.phase-data').innerHTML = txt;
}
if (evName === 'done') es.close();
});
});
es.addEventListener('error', () => es.close());
};
})();
</script>
<script src="/api/ambre-universal-chat.js" defer></script>
</body></html>