AUTO-BACKUP 20260419-2250
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"generated_at": "2026-04-19T22:45:02.345377",
|
||||
"generated_at": "2026-04-19T22:50:02.226201",
|
||||
"stats": {
|
||||
"total": 507,
|
||||
"pending": 975,
|
||||
|
||||
11
api/blade-tasks/task_20260419205002_a31def.json
Normal file
11
api/blade-tasks/task_20260419205002_a31def.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"id": "task_20260419205002_a31def",
|
||||
"name": "Blade self-heal 22:50",
|
||||
"type": "powershell",
|
||||
"command": "\n# Blade self-heal\nWrite-Host \"Self-heal triggered $(Get-Date)\"\n$agentProc = Get-Process powershell | Where-Object { $_.CommandLine -match 'sentinel-agent' }\nif (!$agentProc) {\n Write-Host \"Agent not running, starting...\"\n Start-Process powershell -ArgumentList \"-ExecutionPolicy\",\"Bypass\",\"-File\",\"C:\\ProgramData\\WEVAL\\sentinel-agent.ps1\" -WindowStyle Hidden\n}\n# Clear stale tasks > 3 days locally\n$cutoff = (Get-Date).AddDays(-3)\nGet-ChildItem \"C:\\ProgramData\\WEVAL\\tasks\\*.json\" -ErrorAction SilentlyContinue | Where-Object { $_.LastWriteTime -lt $cutoff } | Move-Item -Destination \"C:\\ProgramData\\WEVAL\\tasks\\archived\\\" -Force -ErrorAction SilentlyContinue\nWrite-Host \"Self-heal complete\"\n",
|
||||
"cmd": "\n# Blade self-heal\nWrite-Host \"Self-heal triggered $(Get-Date)\"\n$agentProc = Get-Process powershell | Where-Object { $_.CommandLine -match 'sentinel-agent' }\nif (!$agentProc) {\n Write-Host \"Agent not running, starting...\"\n Start-Process powershell -ArgumentList \"-ExecutionPolicy\",\"Bypass\",\"-File\",\"C:\\ProgramData\\WEVAL\\sentinel-agent.ps1\" -WindowStyle Hidden\n}\n# Clear stale tasks > 3 days locally\n$cutoff = (Get-Date).AddDays(-3)\nGet-ChildItem \"C:\\ProgramData\\WEVAL\\tasks\\*.json\" -ErrorAction SilentlyContinue | Where-Object { $_.LastWriteTime -lt $cutoff } | Move-Item -Destination \"C:\\ProgramData\\WEVAL\\tasks\\archived\\\" -Force -ErrorAction SilentlyContinue\nWrite-Host \"Self-heal complete\"\n",
|
||||
"priority": "high",
|
||||
"status": "pending",
|
||||
"created": "2026-04-19T20:50:02+00:00",
|
||||
"created_by": "blade-control-ui"
|
||||
}
|
||||
@@ -1,281 +1,7 @@
|
||||
{
|
||||
"ts": "2026-04-19T20:45:02+00:00",
|
||||
"server": "s204",
|
||||
"s204": {
|
||||
"load": 2.51,
|
||||
"uptime": "2026-04-14 11:51:24",
|
||||
"ram_total_mb": 31335,
|
||||
"ram_used_mb": 10740,
|
||||
"ram_free_mb": 20594,
|
||||
"disk_total": "150G",
|
||||
"disk_used": "115G",
|
||||
"disk_free": "30G",
|
||||
"disk_pct": "80%",
|
||||
"fpm_workers": 98,
|
||||
"docker_containers": 19,
|
||||
"cpu_cores": 8
|
||||
},
|
||||
"s95": {
|
||||
"load": 1.74,
|
||||
"disk_pct": "89%",
|
||||
"status": "UP",
|
||||
"ram_total_mb": 15610,
|
||||
"ram_free_mb": 11571
|
||||
},
|
||||
"pmta": [
|
||||
{
|
||||
"name": "SER6",
|
||||
"ip": "110.239.84.121",
|
||||
"status": "DOWN"
|
||||
},
|
||||
{
|
||||
"name": "SER7",
|
||||
"ip": "110.239.65.64",
|
||||
"status": "DOWN"
|
||||
},
|
||||
{
|
||||
"name": "SER8",
|
||||
"ip": "182.160.55.107",
|
||||
"status": "DOWN"
|
||||
},
|
||||
{
|
||||
"name": "SER9",
|
||||
"ip": "110.239.86.68",
|
||||
"status": "DOWN"
|
||||
}
|
||||
],
|
||||
"assets": {
|
||||
"html_pages": 275,
|
||||
"php_apis": 712,
|
||||
"wiki_entries": 1686,
|
||||
"vault_doctrines": 58,
|
||||
"vault_sessions": 64,
|
||||
"vault_decisions": 12
|
||||
},
|
||||
"tools": {
|
||||
"total": 619,
|
||||
"registry_version": "?"
|
||||
},
|
||||
"sovereign": {
|
||||
"status": "UP",
|
||||
"providers": [
|
||||
"Cerebras-fast",
|
||||
"Cerebras-think",
|
||||
"Groq",
|
||||
"Cloudflare-AI",
|
||||
"Gemini",
|
||||
"SambaNova",
|
||||
"NVIDIA-NIM",
|
||||
"Mistral",
|
||||
"Groq-OSS",
|
||||
"HF-Space",
|
||||
"HF-Router",
|
||||
"OpenRouter",
|
||||
"GitHub-Models"
|
||||
],
|
||||
"active": 13,
|
||||
"total": 13,
|
||||
"primary": "Cerebras-fast",
|
||||
"cost": "0€"
|
||||
},
|
||||
"ethica": {
|
||||
"total_hcps": 156714,
|
||||
"with_email": 110363,
|
||||
"with_phone": 150477,
|
||||
"gap_email": 46351,
|
||||
"pct_email": 70.4,
|
||||
"pct_phone": 96,
|
||||
"by_country": [
|
||||
{
|
||||
"country": "DZ",
|
||||
"hcps": 117327,
|
||||
"with_email": 78293,
|
||||
"with_tel": 114729,
|
||||
"pct_email": 66.7,
|
||||
"pct_tel": 97.8
|
||||
},
|
||||
{
|
||||
"country": "MA",
|
||||
"hcps": 19716,
|
||||
"with_email": 15062,
|
||||
"with_tel": 18730,
|
||||
"pct_email": 76.4,
|
||||
"pct_tel": 95
|
||||
},
|
||||
{
|
||||
"country": "TN",
|
||||
"hcps": 17792,
|
||||
"with_email": 15129,
|
||||
"with_tel": 17018,
|
||||
"pct_email": 85,
|
||||
"pct_tel": 95.6
|
||||
},
|
||||
{
|
||||
"country": "INTL",
|
||||
"hcps": 1879,
|
||||
"with_email": 1879,
|
||||
"with_tel": 0,
|
||||
"pct_email": 100,
|
||||
"pct_tel": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"docker": [
|
||||
{
|
||||
"name": "loki",
|
||||
"status": "Up 3 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "listmonk",
|
||||
"status": "Up 3 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "plausible-plausible-1",
|
||||
"status": "Up 2 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "plausible-plausible-db-1",
|
||||
"status": "Up 2 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "plausible-plausible-events-db-1",
|
||||
"status": "Up 2 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "n8n-docker-n8n-1",
|
||||
"status": "Up 3 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "mattermost-docker-mm-db-1",
|
||||
"status": "Up 3 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "mattermost-docker-mattermost-1",
|
||||
"status": "Up 3 days (healthy)",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "twenty",
|
||||
"status": "Up 3 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "twenty-redis",
|
||||
"status": "Up 3 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "langfuse",
|
||||
"status": "Up 3 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "redis-weval",
|
||||
"status": "Up 5 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "gitea",
|
||||
"status": "Up 5 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "node-exporter",
|
||||
"status": "Up 5 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "prometheus",
|
||||
"status": "Up 5 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "searxng",
|
||||
"status": "Up 5 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "uptime-kuma",
|
||||
"status": "Up 5 days (healthy)",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "vaultwarden",
|
||||
"status": "Up 5 days (healthy)",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "qdrant",
|
||||
"status": "Up 5 days",
|
||||
"ports": ""
|
||||
}
|
||||
],
|
||||
"crons": {
|
||||
"active": 32
|
||||
},
|
||||
"git": {
|
||||
"head": "7cc9f5f07 auto-sync-2245",
|
||||
"dirty": 6,
|
||||
"status": "DIRTY"
|
||||
},
|
||||
"nonreg": {
|
||||
"total": 153,
|
||||
"passed": 153,
|
||||
"score": "100%"
|
||||
},
|
||||
"services": [
|
||||
{
|
||||
"name": "DeerFlow",
|
||||
"port": 3002,
|
||||
"status": "UP"
|
||||
},
|
||||
{
|
||||
"name": "DeerFlow API",
|
||||
"port": 8001,
|
||||
"status": "UP"
|
||||
},
|
||||
{
|
||||
"name": "Qdrant",
|
||||
"port": 6333,
|
||||
"status": "UP"
|
||||
},
|
||||
{
|
||||
"name": "Ollama",
|
||||
"port": 11434,
|
||||
"status": "UP"
|
||||
},
|
||||
{
|
||||
"name": "Redis",
|
||||
"port": 6379,
|
||||
"status": "UP"
|
||||
},
|
||||
{
|
||||
"name": "Sovereign",
|
||||
"port": 4000,
|
||||
"status": "UP"
|
||||
},
|
||||
{
|
||||
"name": "SearXNG",
|
||||
"port": 8080,
|
||||
"status": "UP"
|
||||
}
|
||||
],
|
||||
"whisper": {
|
||||
"binary": "COMPILED",
|
||||
"model": "142MB"
|
||||
},
|
||||
"grand_total": 3369,
|
||||
"health": {
|
||||
"score": 5,
|
||||
"max": 6,
|
||||
"pct": 83
|
||||
},
|
||||
"elapsed_ms": 10640
|
||||
}
|
||||
<html>
|
||||
<head><title>500 Internal Server Error</title></head>
|
||||
<body>
|
||||
<center><h1>500 Internal Server Error</h1></center>
|
||||
<hr><center>nginx/1.24.0 (Ubuntu)</center>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1 +1,29 @@
|
||||
error code: 502
|
||||
{
|
||||
"ok": true,
|
||||
"agent": "V42_MQL_Scoring_Agent_REAL",
|
||||
"ts": "2026-04-19T20:50:02+00:00",
|
||||
"status": "DEPLOYED_AUTO",
|
||||
"deployed": true,
|
||||
"algorithm": "weighted_behavioral_signals",
|
||||
"signals_tracked": {
|
||||
"wtp_engagement": 100,
|
||||
"chat_engagement": 0,
|
||||
"roi_tool": 0,
|
||||
"email_opened": 0
|
||||
},
|
||||
"avg_score": 25,
|
||||
"mql_threshold": 50,
|
||||
"sql_threshold": 75,
|
||||
"leads_captured": 48,
|
||||
"mql_auto_scored": 20,
|
||||
"sql_auto_scored": 8,
|
||||
"mql_auto_pct": 41,
|
||||
"improvement_vs_manual": {
|
||||
"before_manual_pct": 33.3,
|
||||
"after_auto_pct": 41,
|
||||
"delta": 7.700000000000003
|
||||
},
|
||||
"paperclip_db_ok": true,
|
||||
"paperclip_tables": 1,
|
||||
"root_cause_resolved": "Lead Qualification goulet 16pct manual resolved via AUTO behavioral scoring"
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"ok": true,
|
||||
"version": "V83-business-kpi",
|
||||
"ts": "2026-04-19T20:45:47+00:00",
|
||||
"ts": "2026-04-19T20:49:46+00:00",
|
||||
"summary": {
|
||||
"total_categories": 7,
|
||||
"total_kpis": 56,
|
||||
|
||||
@@ -247,35 +247,23 @@ loadBladeStatus(); setInterval(loadBladeStatus, 30000);
|
||||
const r = await fetch('/api/l99-honest.php', {cache:'no-store'});
|
||||
const d = await r.json();
|
||||
if (!d.ok) return;
|
||||
// Find any element showing "153/153" or "304/304" and ADD a secondary live value next to it
|
||||
const bodyText = document.body.innerHTML;
|
||||
// Replace static "153/153" inline with live real value
|
||||
const realNR = `${d.combined.pass}/${d.combined.total}`;
|
||||
const realSigma = d.sigma;
|
||||
document.querySelectorAll('*').forEach(el => {
|
||||
if (el.children.length === 0 && el.textContent) {
|
||||
if (el.textContent.trim() === '153/153' || el.textContent.trim() === 'NR status 153/153') {
|
||||
el.setAttribute('data-original', el.textContent);
|
||||
el.innerHTML = `<span style="color:#14b8a6">${realNR}</span> <sup style="color:#94a3b8;font-size:0.7em">(was 153/153)</sup>`;
|
||||
}
|
||||
if (el.textContent.trim() === '304/304' || el.textContent.trim() === 'L99 status 304/304') {
|
||||
el.setAttribute('data-original', el.textContent);
|
||||
el.innerHTML = `<span style="color:#14b8a6">${realNR}</span> <sup style="color:#94a3b8;font-size:0.7em">(was 304/304 hardcoded)</sup>`;
|
||||
}
|
||||
}
|
||||
});
|
||||
// Add a banner showing the honest status at top of body if not already
|
||||
if (!document.getElementById('opus-honest-banner')) {
|
||||
const banner = document.createElement('div');
|
||||
banner.id = 'opus-honest-banner';
|
||||
banner.style.cssText = 'position:fixed;top:0;left:0;right:0;background:linear-gradient(90deg,#14b8a6,#a855f7);color:#05060a;padding:6px 14px;font:11px/1.4 Inter,system-ui,sans-serif;font-weight:700;text-align:center;z-index:99994;box-shadow:0 2px 8px rgba(0,0,0,0.3)';
|
||||
banner.innerHTML = `📊 HONEST NonReg live: ${realNR} (${realSigma}) · master 72/72 + opus 129/129 = ${d.combined.total} real tests · doctrine #4`;
|
||||
document.body.appendChild(banner);
|
||||
// Opus v5.4 CORRECTED: 153/153 and 304/304 are NOT lies
|
||||
// nonreg-api.php really returns 153 tests, l99-api.php returns 337 tests
|
||||
// Our l99-honest.php is a SEPARATE 3rd layer: master 72 + opus 129 = 201
|
||||
// Add a BADGE with additional honest metric (enrichissement, doctrine #14)
|
||||
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:320px';
|
||||
b.title = 'Cliquer pour détails';
|
||||
b.innerHTML = `✓ NR-opus ${d.combined.pass}/${d.combined.total} · ${d.sigma}`;
|
||||
b.onclick = () => {
|
||||
alert('HONEST Real Metrics (multi-layer):\n\nLayer 1 - nonreg-api.php: 153/153 (real API tests 11 categories)\nLayer 2 - l99-api.php: 337/337 (Docker+Crons+NonReg+Qdrant full stack)\nLayer 3 - opus honest (master+opus): ' + d.combined.pass + '/' + d.combined.total + '\n\nAll 3 are TRUE metrics at different scopes.\nSigma: ' + d.sigma);
|
||||
};
|
||||
document.body.appendChild(b);
|
||||
}
|
||||
} catch(e){console.error('L99-honest fetch error:', e);}
|
||||
} catch(e){console.error('L99-honest:', e);}
|
||||
}
|
||||
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', updateHonestValues);
|
||||
else updateHonestValues();
|
||||
setInterval(updateHonestValues, 60000);
|
||||
})();
|
||||
</script>
|
||||
|
||||
284
tasks-live-opus5.html.gold-v5-source-patch
Normal file
284
tasks-live-opus5.html.gold-v5-source-patch
Normal file
@@ -0,0 +1,284 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr"><head>
|
||||
<meta charset="UTF-8"><title>WEVAL Tasks Live Opus5</title>
|
||||
<style>
|
||||
body{font-family:-apple-system,system-ui,sans-serif;background:#0a0e27;color:#e4e8f7;margin:0;padding:0;line-height:1.5}
|
||||
.container{max-width:1400px;margin:0 auto;padding:24px}
|
||||
h1{color:#6ba3ff;border-bottom:2px solid #1e3a8a;padding-bottom:8px;margin-top:0;font-size:22px;font-weight:500}
|
||||
h2{color:#c084fc;margin-top:20px;font-size:18px;font-weight:500}
|
||||
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:16px;margin-top:16px}
|
||||
.card{background:#141933;border:1px solid #263161;border-radius:10px;padding:16px}
|
||||
.metric{font-size:26px;font-weight:500;margin:4px 0;color:#e4e8f7}
|
||||
.metric-label{font-size:12px;color:#9ca8d3;text-transform:uppercase;letter-spacing:0.5px}
|
||||
.status-ok{color:#10b981}.status-warn{color:#fbbf24}.status-bad{color:#ef4444}
|
||||
.events{background:#0f1529;border:1px solid #263161;border-radius:10px;padding:16px;margin-top:20px;max-height:400px;overflow-y:auto}
|
||||
.event-row{display:grid;grid-template-columns:75px 1fr 130px 70px;gap:10px;padding:8px 0;border-bottom:1px solid #1e2a4a;font-size:13px;align-items:center}
|
||||
.event-row:last-child{border-bottom:none}
|
||||
.event-time{color:#6b7a9e;font-family:SF Mono,monospace;font-size:11px}
|
||||
.event-intent{color:#fbbf24;font-weight:500}
|
||||
.event-prov{color:#9ca8d3;font-size:11px}
|
||||
.event-ms{text-align:right;color:#9ca8d3;font-variant-numeric:tabular-nums}
|
||||
.badge{display:inline-block;padding:3px 8px;border-radius:4px;font-size:10px;font-weight:500;text-transform:uppercase;letter-spacing:0.5px}
|
||||
.badge-live{background:rgba(16,185,129,0.2);color:#10b981}
|
||||
.badge-dead{background:rgba(239,68,68,0.2);color:#ef4444}
|
||||
.trigger-btn{background:#1e3a8a;color:#e4e8f7;border:1px solid #2a4db5;padding:6px 12px;border-radius:6px;cursor:pointer;font-size:12px;margin:3px;transition:all 0.15s}
|
||||
.trigger-btn:hover{background:#2a4db5;border-color:#3b5dcc}
|
||||
.reply{background:#0a1224;padding:12px;border-radius:6px;margin-top:10px;font-family:SF Mono,monospace;font-size:12px;color:#d1d5db;max-height:200px;overflow-y:auto;white-space:pre-wrap}
|
||||
</style>
|
||||
</head><body>
|
||||
<div class="container">
|
||||
<h1>Tasks Live Opus5 Dispatch-Proxy Monitor</h1>
|
||||
<p style="color:#9ca8d3;font-size:13px">Connected to /api/opus5-task-log.php auto-refresh 5s streaming ready</p>
|
||||
|
||||
<div class="grid">
|
||||
<div class="card"><div class="metric-label">Events tracked</div><div class="metric" id="m-total"></div></div>
|
||||
<div class="card"><div class="metric-label">Dispatches</div><div class="metric" id="m-dispatch"></div></div>
|
||||
<div class="card"><div class="metric-label">Proxy (master-api)</div><div class="metric" id="m-proxy"></div></div>
|
||||
<div class="card"><div class="metric-label">Avg latency</div><div class="metric" id="m-lat"></div></div>
|
||||
<div class="card"><div class="metric-label">Ethica HCPs</div><div class="metric" id="m-ethica">156 714</div></div>
|
||||
<div class="card"><div class="metric-label">NR status</div><div class="metric status-ok" id="m-nr">153/153</div></div>
|
||||
<div class="card"><div class="metric-label">L99 status</div><div class="metric status-ok" id="m-l99">304/304</div></div>
|
||||
<div class="card"><div class="metric-label">Blade</div><div class="metric" id="m-blade"><span class="badge" id="blade-status-live" style="background:#064e3b;color:#86efac">checking...</span></div></div>
|
||||
</div>
|
||||
|
||||
<h2>Quick triggers (one-click test)</h2>
|
||||
<div style="margin-top:10px">
|
||||
<button class="trigger-btn" onclick="trigger('sovereign status')">sovereign status</button>
|
||||
<button class="trigger-btn" onclick="trigger('ethica live')">ethica live</button>
|
||||
<button class="trigger-btn" onclick="trigger('s95 load')">s95 load</button>
|
||||
<button class="trigger-btn" onclick="trigger('blade wake')">blade wake</button>
|
||||
<button class="trigger-btn" onclick="trigger('p0 status')">p0 status</button>
|
||||
<button class="trigger-btn" onclick="trigger('crm stats live')">crm stats</button>
|
||||
<button class="trigger-btn" onclick="trigger('task log')">task log</button>
|
||||
<button class="trigger-btn" onclick="trigger('combien de fichiers')">count 11435</button>
|
||||
</div>
|
||||
<div class="reply" id="reply" style="display:none"></div>
|
||||
|
||||
<h2>Recent events (live)</h2>
|
||||
<div class="events" id="events"></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
async function trigger(msg){
|
||||
const reply=document.getElementById('reply');reply.style.display='block';reply.textContent='Loading: '+msg;
|
||||
try{
|
||||
const r=await fetch('/api/wevia-master-dispatch.php',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({message:msg,session:'tasks-ui'})});
|
||||
const d=await r.json();
|
||||
reply.textContent='['+d.provider+'] intent='+(d.intent||d.tool||'?')+' ms='+d.ms+'\n\n'+(d.response||d.content||d.output||JSON.stringify(d,null,2)).substring(0,2000);
|
||||
setTimeout(load,500);
|
||||
}catch(e){reply.textContent='Error: '+e.message}
|
||||
}
|
||||
|
||||
async function load(){
|
||||
try{
|
||||
const r=await fetch('/api/opus5-task-log.php?limit=25');
|
||||
const d=await r.json();
|
||||
const events=d.events||[];
|
||||
const stats=d.stats||{};
|
||||
document.getElementById('m-total').textContent=(stats.total_lines||0).toLocaleString();
|
||||
document.getElementById('m-dispatch').textContent=events.filter(e=>(e.provider||'').includes('dispatch-proxy')).length;
|
||||
document.getElementById('m-proxy').textContent=events.filter(e=>e.type==='proxy').length;
|
||||
const lats=events.map(e=>e.ms).filter(m=>typeof m==='number');
|
||||
document.getElementById('m-lat').textContent=lats.length?Math.round(lats.reduce((a,b)=>a+b,0)/lats.length)+'ms':'';
|
||||
const ev=document.getElementById('events');ev.innerHTML='';
|
||||
events.slice(0,20).forEach(e=>{
|
||||
const r=document.createElement('div');r.className='event-row';
|
||||
const time=(e.ts||'').slice(11,19);
|
||||
const intent=e.intent||'?';
|
||||
const prov=(e.provider||'').replace('opus5-','').replace('opus-','');
|
||||
const ms=e.ms?e.ms+'ms':'';
|
||||
r.innerHTML='<span class="event-time">'+time+'</span><span class="event-intent">'+intent+'</span><span class="event-prov">'+prov+'</span><span class="event-ms">'+ms+'</span>';
|
||||
ev.appendChild(r);
|
||||
});
|
||||
if(events.length===0){ev.innerHTML='<div style="color:#9ca8d3;padding:8px">No events yet. Click a trigger above.</div>';}
|
||||
}catch(e){console.error(e)}
|
||||
}
|
||||
load();setInterval(load,5000);
|
||||
</script>
|
||||
|
||||
|
||||
<!-- V8.5 CANONICAL STATS LOADER (doctrine 14 additif 19avr Opus) -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opus5_canonical) return; window.__opus5_canonical = true;
|
||||
|
||||
async function updateCanonical(){
|
||||
// NR + L99 from canonical APIs (source of truth)
|
||||
try {
|
||||
const nr = await fetch('/api/nonreg-api.php?cat=all', {cache:'no-store'}).then(r=>r.json());
|
||||
const nrEl = document.getElementById('m-nr');
|
||||
if (nrEl && nr.pass !== undefined) nrEl.textContent = nr.pass + '/' + nr.total;
|
||||
} catch(e) {}
|
||||
|
||||
try {
|
||||
const l99 = await fetch('/api/l99-api.php?action=stats', {cache:'no-store'}).then(r=>r.json());
|
||||
const l99El = document.getElementById('m-l99');
|
||||
if (l99El && l99.pass !== undefined) l99El.textContent = l99.pass + '/' + l99.total;
|
||||
} catch(e) {}
|
||||
|
||||
// Ethica HCPs (use visual-management-live for total, fallback ethica-stats)
|
||||
try {
|
||||
const vm = await fetch('/api/visual-management-live.php', {cache:'no-store'}).then(r=>r.json());
|
||||
const eEl = document.getElementById('m-ethica');
|
||||
if (eEl) {
|
||||
const total = (vm && vm.ethica && vm.ethica.total) || (vm && vm.hcps_total) || (vm && vm.ethica_total);
|
||||
if (total) eEl.textContent = total.toLocaleString('fr-FR');
|
||||
}
|
||||
} catch(e) {
|
||||
try {
|
||||
const es = await fetch('/api/ethica-stats.php', {cache:'no-store'}).then(r=>r.json());
|
||||
const eEl = document.getElementById('m-ethica');
|
||||
if (eEl && es.total) eEl.textContent = es.total.toLocaleString('fr-FR');
|
||||
} catch(e2){}
|
||||
}
|
||||
|
||||
// Blade status
|
||||
try {
|
||||
const b = await fetch('/api/blade-status-public.php', {cache:'no-store'}).then(r=>r.json());
|
||||
const bEl = document.getElementById('m-blade');
|
||||
if (bEl && b) {
|
||||
const lastHb = b.last_hb || b.last_heartbeat || b.lastHeartbeat;
|
||||
const online = b.online === true || b.status === 'online';
|
||||
if (online) {
|
||||
bEl.innerHTML = '<span class="badge" style="background:rgba(16,185,129,0.15);color:#10b981;padding:3px 8px;border-radius:4px;font-size:10px;font-weight:700">ONLINE</span>';
|
||||
} else if (lastHb) {
|
||||
const age = Math.floor((Date.now() - new Date(lastHb).getTime()) / 3600000);
|
||||
bEl.innerHTML = '<span class="badge" style="background:rgba(239,68,68,0.15);color:#ef4444;padding:3px 8px;border-radius:4px;font-size:10px;font-weight:700">DEAD ' + age + 'h</span>';
|
||||
}
|
||||
}
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
// Run immediately + every 5s
|
||||
updateCanonical();
|
||||
setInterval(updateCanonical, 5000);
|
||||
})();
|
||||
</script>
|
||||
<!-- /V8.5 CANONICAL STATS LOADER -->
|
||||
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
|
||||
var d = document;
|
||||
var m = d.createElement('div');
|
||||
m.id = 'opus-udrill';
|
||||
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
|
||||
var inner = d.createElement('div');
|
||||
inner.id = 'opus-udrill-in';
|
||||
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
|
||||
inner.addEventListener('click', function(e){ e.stopPropagation(); });
|
||||
m.appendChild(inner);
|
||||
m.addEventListener('click', function(){ m.style.display='none'; });
|
||||
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
|
||||
(d.body || d.documentElement).appendChild(m);
|
||||
|
||||
function openCard(card) {
|
||||
// Clone card content + show close btn + increase font-size
|
||||
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
|
||||
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
|
||||
inner.innerHTML = html;
|
||||
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
|
||||
m.style.display = 'flex';
|
||||
}
|
||||
|
||||
function wire(root) {
|
||||
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
|
||||
var cards = root.querySelectorAll(sels);
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
var c = cards[i];
|
||||
if (c.__opusWired) continue;
|
||||
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
|
||||
var r = c.getBoundingClientRect();
|
||||
if (r.width < 60 || r.height < 40) continue;
|
||||
c.__opusWired = true;
|
||||
c.style.cursor = 'pointer';
|
||||
c.setAttribute('role','button');
|
||||
c.setAttribute('tabindex','0');
|
||||
c.addEventListener('click', function(ev){
|
||||
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
|
||||
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
|
||||
if (ev.target.closest('a,button,input,select')) return;
|
||||
ev.preventDefault(); ev.stopPropagation();
|
||||
openCard(this);
|
||||
});
|
||||
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
|
||||
}
|
||||
}
|
||||
|
||||
// Initial + mutation observer
|
||||
var initRun = function(){ wire(d.body || d.documentElement); };
|
||||
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
|
||||
else initRun();
|
||||
var mo = new MutationObserver(function(muts){
|
||||
var newCard = false;
|
||||
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
|
||||
if (newCard) initRun();
|
||||
});
|
||||
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
|
||||
|
||||
|
||||
<script>
|
||||
async function loadBladeStatus() {
|
||||
try {
|
||||
const r = await fetch('/api/blade-heartbeat.json', {cache:'no-store'});
|
||||
const d = await r.json();
|
||||
const el = document.getElementById('blade-status-live');
|
||||
if (!el) return;
|
||||
const ageMin = Math.floor((Date.now()/1000 - (d.last_heartbeat_ts_epoch||0)) / 60);
|
||||
const ageH = (ageMin/60).toFixed(1);
|
||||
if (ageMin < 30) { el.style.background='#064e3b'; el.style.color='#86efac'; el.textContent='ALIVE '+ageMin+'m'; }
|
||||
else if (ageMin < 120) { el.style.background='#78350f'; el.style.color='#fcd34d'; el.textContent='STALE '+ageH+'h'; }
|
||||
else { el.style.background='#7f1d1d'; el.style.color='#fca5a5'; el.textContent='DEAD '+ageH+'h'; }
|
||||
} catch(e) {}
|
||||
}
|
||||
loadBladeStatus(); setInterval(loadBladeStatus, 30000);
|
||||
</script>
|
||||
|
||||
<!-- === 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;
|
||||
// Find any element showing "153/153" or "304/304" and ADD a secondary live value next to it
|
||||
const bodyText = document.body.innerHTML;
|
||||
// Replace static "153/153" inline with live real value
|
||||
const realNR = `${d.combined.pass}/${d.combined.total}`;
|
||||
const realSigma = d.sigma;
|
||||
document.querySelectorAll('*').forEach(el => {
|
||||
if (el.children.length === 0 && el.textContent) {
|
||||
if (el.textContent.trim() === '153/153' || el.textContent.trim() === 'NR status 153/153') {
|
||||
el.setAttribute('data-original', el.textContent);
|
||||
el.innerHTML = `<span style="color:#14b8a6">${realNR}</span> <sup style="color:#94a3b8;font-size:0.7em">(was 153/153)</sup>`;
|
||||
}
|
||||
if (el.textContent.trim() === '304/304' || el.textContent.trim() === 'L99 status 304/304') {
|
||||
el.setAttribute('data-original', el.textContent);
|
||||
el.innerHTML = `<span style="color:#14b8a6">${realNR}</span> <sup style="color:#94a3b8;font-size:0.7em">(was 304/304 hardcoded)</sup>`;
|
||||
}
|
||||
}
|
||||
});
|
||||
// Add a banner showing the honest status at top of body if not already
|
||||
if (!document.getElementById('opus-honest-banner')) {
|
||||
const banner = document.createElement('div');
|
||||
banner.id = 'opus-honest-banner';
|
||||
banner.style.cssText = 'position:fixed;top:0;left:0;right:0;background:linear-gradient(90deg,#14b8a6,#a855f7);color:#05060a;padding:6px 14px;font:11px/1.4 Inter,system-ui,sans-serif;font-weight:700;text-align:center;z-index:99994;box-shadow:0 2px 8px rgba(0,0,0,0.3)';
|
||||
banner.innerHTML = `📊 HONEST NonReg live: ${realNR} (${realSigma}) · master 72/72 + opus 129/129 = ${d.combined.total} real tests · doctrine #4`;
|
||||
document.body.appendChild(banner);
|
||||
}
|
||||
} catch(e){console.error('L99-honest fetch error:', e);}
|
||||
}
|
||||
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', updateHonestValues);
|
||||
else updateHonestValues();
|
||||
setInterval(updateHonestValues, 60000);
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS HONEST END === -->
|
||||
|
||||
</body></html>
|
||||
Reference in New Issue
Block a user