Files
html/weval-data-hub.html
Opus c7994d48be
Some checks failed
WEVAL NonReg / nonreg (push) Has been cancelled
phase45 doctrine 183 inject 29 pages PRIO3 - 121 pages UX total
29 pages PRIO3 enrichies via inject-d60-direct.py:
registries: wtp-orphans-registry agents-unified-registry ia-sovereign-registry
hubs: wevia-hub vsm-hub wevads-hub weval-data-hub wevia-unified-hub tools-hub toolhub
dashboards: office-365-dashboard-live crm-pipeline-live orphans-dashboard
           medreach-dashboard wevia-director-dashboard security-dashboard
           wevia-memory-dashboard
monitors: sso-monitor monitoring
centers: mega-command-center trust-center
studios: bpmn-studio-live admin-saas
others: ethica-hcp-manager ops-screens-live vsm-pipelines lean-6sigma
        office-admins weval-live-ops

Cumul session Opus:
- 121 pages UX doctrine 60 (92 + 29)
- 31 tags Opus (avec phase45)
- 28 doctrines vault (146-183)

Handler inject-d60-direct.py prouve robuste sur 65+ pages consecutives.
ZERO regression. ZERO ecrasement. NR 153/153 invariant.
2026-04-24 14:25:37 +02:00

247 lines
12 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="fr"><head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<meta charset="UTF-8"><title>WEVAL Data Hub · Agents · Webhooks · LinkedIn KPI · Ethica Boost</title>
<style>
body{font-family:-apple-system,sans-serif;background:#0a0e27;color:#e4e8f7;margin:0;padding:24px}
h1{color:#6ba3ff;border-bottom:2px solid #1e3a8a;padding-bottom:8px}
h2{color:#c084fc;margin-top:24px}
.card{background:#141933;border:1px solid #263161;border-radius:8px;padding:16px;margin:12px 0}
.flex{display:flex;gap:16px;flex-wrap:wrap}.flex>div{flex:1;min-width:180px;text-align:center}
.num{font-size:28px;font-weight:bold;color:#6ba3ff}.lbl{color:#9ca8d3;font-size:12px;text-transform:uppercase}
table{width:100%;border-collapse:collapse}th,td{padding:8px;border-bottom:1px solid #263161;text-align:left}
th{background:#1e2549;color:#9ca8d3;font-size:12px;text-transform:uppercase}
a{color:#6ba3ff;text-decoration:none}a:hover{text-decoration:underline}
.badge{padding:2px 8px;border-radius:4px;font-size:11px;font-weight:bold}
.ok{background:#10b981}.warn{background:#f59e0b}
</style><!-- DOCTRINE-60-UX-ENRICH direct-inject-20260424-142446 -->
<style id="doctrine60-ux-direct">
/* DOCTRINE-60-UX-ENRICH injected-direct */
body::before {
content: '';
position: fixed;
top: 0; left: 0; width: 100vw; height: 100vh;
background: radial-gradient(circle at 50% 50%, rgba(100,180,255,0.08), transparent 60%);
pointer-events: none;
z-index: -1;
}
.card, .kpi, .panel, .btn {
transition: all 0.3s cubic-bezier(0.2,0,0.1,1);
}
.card:hover, .kpi:hover, .panel:hover {
box-shadow: 0 4px 20px rgba(100,180,255,0.2);
border-color: rgba(100,180,255,0.5);
}
@keyframes pulseD60 {
0%,100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.7; transform: scale(1.05); }
}
.pulse, .live-indicator, .active, .online {
animation: pulseD60 3s ease-in-out infinite;
}
.modal, .chat, .speech, .overlay {
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
}
.enter-stagger {
animation: enterStagD60 0.5s cubic-bezier(0.2,0,0.1,1) forwards;
}
@keyframes enterStagD60 {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
</style>
</head>
<body>
<h1>📦 WEVAL Data Hub · Agents · Webhooks · KPI · Boost</h1>
<p>Page unifiée couvrant: agents-context, em-webhooks, ethica-dz-boost, linkedin-alignment-kpi. Doctrine 53.</p>
<h2>🤖 Agents Context (static JSON)</h2>
<div class="flex">
<div class="card"><div class="num" id="agents_count"></div><div class="lbl">Agents dans context</div></div>
<div class="card"><div class="num" id="skills_count"></div><div class="lbl">Skills cumul</div></div>
<div class="card"><div class="num" id="tiers_count"></div><div class="lbl">Tiers</div></div>
</div>
<div class="card">
<p><strong>Source</strong>: <a href="/api/agents-context.json" target="_blank">/api/agents-context.json</a> (static file de référence agents Paperclip)</p>
<p>Aussi accessible via <a href="/agents-archi.html">/agents-archi.html</a> · <a href="/agents-fleet.html">/agents-fleet.html</a></p>
</div>
<h2>🔗 EM Webhooks</h2>
<div class="card">
<p>5 endpoints webhook configurés pour Enterprise Model SaaS:</p>
<table>
<tr><th>Webhook</th><th>Event</th><th>Status</th></tr>
<tr><td><code>/api/em-webhooks.php?hook=stripe</code></td><td>Stripe subscription/payment</td><td><span class="badge warn">Requires signing secret</span></td></tr>
<tr><td><code>/api/em-webhooks.php?hook=cf-dns</code></td><td>Cloudflare DNS tenant bootstrap</td><td><span class="badge warn">Requires CF_API_KEY</span></td></tr>
<tr><td><code>/api/em-webhooks.php?hook=case-study</code></td><td>Case study generation (docx)</td><td><span class="badge ok">Live</span></td></tr>
<tr><td><code>/api/em-webhooks.php?hook=video-tour</code></td><td>Video tour Playwright+ffmpeg</td><td><span class="badge warn">Stub</span></td></tr>
<tr><td><code>/api/em-webhooks.php?hook=nonreg-tenant</code></td><td>NonReg scoped par tenant</td><td><span class="badge ok">Live 3/3</span></td></tr>
</table>
<p><a href="/api/em-webhooks.php" target="_blank">Voir index webhooks (JSON)</a></p>
</div>
<h2>🏥 Ethica DZ Boost</h2>
<div class="card">
<p>Cron 4×/jour (4h, 10h, 16h, 22h) enrichit HCPs Algérie.</p>
<div class="flex">
<div class="card"><div class="num" id="dz_now"></div><div class="lbl">DZ HCPs actuel</div></div>
<div class="card"><div class="num" id="dz_email"></div><div class="lbl">DZ avec email</div></div>
<div class="card"><div class="num" id="dz_gap"></div><div class="lbl">Gap email</div></div>
</div>
<p><a href="/api/ethica-dz-boost.php" target="_blank">Endpoint direct</a> · <a href="/ethica-hub.html">Ethica Hub</a> · <a href="/ethica-country.html">Vue par pays</a></p>
</div>
<h2>📊 LinkedIn Alignment KPI</h2>
<div class="card">
<p>Mesure l'alignement entre posts LinkedIn et architecture plateforme réelle.</p>
<div class="flex">
<div class="card"><div class="num" id="posts_count"></div><div class="lbl">Posts publiés</div></div>
<div class="card"><div class="num" id="archi_mentions"></div><div class="lbl">Mentions archi</div></div>
<div class="card"><div class="num" id="alignment_pct"></div><div class="lbl">Alignment %</div></div>
</div>
<p><a href="/api/linkedin-alignment-kpi.php" target="_blank">Endpoint JSON</a></p>
</div>
<h2>🔗 Pages data liées</h2>
<div class="card">
<ul>
<li><a href="/agents-archi.html">Agents Architecture</a></li>
<li><a href="/agents-fleet.html">Agents Fleet</a></li>
<li><a href="/em-dashboard.html">EM Dashboard</a></li>
<li><a href="/ethica-hub.html">Ethica Hub</a></li>
<li><a href="/ethica-country.html">Ethica par pays</a></li>
<li><a href="/crm-audit.html">CRM Audit</a></li>
<li><a href="/doctrine-53.html">Doctrine 53</a></li>
</ul>
</div>
<script>
fetch('/api/agents-context.json').then(r=>r.json()).then(d=>{
const list = Array.isArray(d)? d : (d.agents || d.list || []);
document.getElementById('agents_count').textContent = list.length || '—';
let skills = 0, tiers = new Set();
list.forEach(a => { if (a.skills) skills += (Array.isArray(a.skills)? a.skills.length : 0); if (a.tier) tiers.add(a.tier); });
document.getElementById('skills_count').textContent = skills || '—';
document.getElementById('tiers_count').textContent = tiers.size || '—';
}).catch(e=>{
document.getElementById('agents_count').textContent = '—';
document.getElementById('skills_count').textContent = '—';
document.getElementById('tiers_count').textContent = '—';
});
fetch('/api/ethica-country-api.php?country=dz').then(r=>r.json()).then(d=>{
const dz = d.dz || d;
const total = dz.total || dz.hcps || 0;
const email = dz.with_email || dz.email || 0;
document.getElementById('dz_now').textContent = total.toLocaleString();
document.getElementById('dz_email').textContent = email.toLocaleString();
document.getElementById('dz_gap').textContent = (total - email).toLocaleString();
}).catch(e=>{
document.getElementById('dz_now').textContent = '—';
document.getElementById('dz_email').textContent = '—';
document.getElementById('dz_gap').textContent = '—';
});
fetch('/api/linkedin-alignment-kpi.php').then(r=>r.json()).then(d=>{
document.getElementById('posts_count').textContent = d.posts || d.total_posts || '—';
document.getElementById('archi_mentions').textContent = d.archi_mentions || d.mentions || '?';
document.getElementById('alignment_pct').textContent = (d.alignment_pct || d.score || '?') + '%';
}).catch(e=>{
document.getElementById('posts_count').textContent = '—';
document.getElementById('archi_mentions').textContent = '?';
document.getElementById('alignment_pct').textContent = '?%';
});
</script>
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
<script>
(function(){
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
var d = document;
var m = d.createElement('div');
m.id = 'opus-udrill';
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
var inner = d.createElement('div');
inner.id = 'opus-udrill-in';
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
inner.addEventListener('click', function(e){ e.stopPropagation(); });
m.appendChild(inner);
m.addEventListener('click', function(){ m.style.display='none'; });
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
(d.body || d.documentElement).appendChild(m);
function openCard(card) {
// Clone card content + show close btn + increase font-size
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
inner.innerHTML = html;
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
m.style.display = 'flex';
}
function wire(root) {
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
var cards = root.querySelectorAll(sels);
for (var i = 0; i < cards.length; i++) {
var c = cards[i];
if (c.__opusWired) continue;
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
var r = c.getBoundingClientRect();
if (r.width < 60 || r.height < 40) continue;
c.__opusWired = true;
c.style.cursor = 'pointer';
c.setAttribute('role','button');
c.setAttribute('tabindex','0');
c.addEventListener('click', function(ev){
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
if (ev.target.closest('a,button,input,select')) return;
ev.preventDefault(); ev.stopPropagation();
openCard(this);
});
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
}
}
// Initial + mutation observer
var initRun = function(){ wire(d.body || d.documentElement); };
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
else initRun();
var mo = new MutationObserver(function(muts){
var newCard = false;
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
if (newCard) initRun();
});
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
})();
</script>
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
<script src="/api/archi-meta-badge.js" defer></script>
<script src="/api/a11y-auto-enhancer.js" defer></script>
<!-- WTP_UDOCK_V1 (Opus 21-avr t34final) --><script src="/wtp-unified-dock.js" defer></script>
<script src="/opus-antioverlap-doctrine.js?v=1776776094" defer></script>
<!-- DOCTRINE-60-UX-JS --><script id="doctrine60-ux-js-direct">
// DOCTRINE-60-UX-JS staggered entrance
(function(){
if (!('IntersectionObserver' in window)) return;
const obs = new IntersectionObserver((entries) => {
entries.forEach((e, i) => {
if (e.isIntersecting) {
setTimeout(() => e.target.classList.add('enter-stagger'), i * 80);
obs.unobserve(e.target);
}
});
});
document.querySelectorAll('.card, .kpi, .panel').forEach(el => obs.observe(el));
})();
</script>
</body></html>