889 lines
70 KiB
HTML
889 lines
70 KiB
HTML
<!DOCTYPE html>
|
||
<html><head><meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate"><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<title>WEVAL Enterprise</title>
|
||
<style>@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@600;800;900&display=swap');*{margin:0;padding:0;box-sizing:border-box}body{background:#e4ecf6;background-image:radial-gradient(#c8d8e8 1px,transparent 1px);background-size:20px 20px;overflow-y:auto;font-family:'Nunito'}canvas{display:block}
|
||
#T{position:fixed;pointer-events:none;display:none;z-index:99;background:#fff;border:3px solid;border-radius:12px;padding:10px 14px;color:#2a2a4a;box-shadow:0 4px 16px #0002;max-width:210px;font-size:.78rem}#T b{display:block;font-size:.9rem}#T i{font-style:normal;font-size:.56rem;text-transform:uppercase;letter-spacing:2px;display:block;margin:2px 0 4px}#T .p{color:#e94560;font-weight:700;font-size:.68rem;margin-top:3px}#T .s{font-size:.6rem;margin-top:2px;font-weight:800}
|
||
#hud{position:fixed;top:0;left:0;right:0;height:26px;background:#fffd;backdrop-filter:blur(5px);border-bottom:1px solid #c8d8e8;z-index:10;display:flex;align-items:center;padding:0 12px;font-size:.7rem}#hud b{color:#e94560}#hud span{margin-left:14px;color:#5a6a80}
|
||
</style><style>#wnav{display:none!important}</style></head><body><div id="wnav" style="display:none"><a href="/l99-saas.html" style="padding:2px 8px;border-radius:4px;font-size:9px;font-weight:600;text-decoration:none;background:#1a2744;color:#8892a4">L99</a><a href="/admin-saas.html" style="padding:2px 8px;border-radius:4px;font-size:9px;font-weight:600;text-decoration:none;background:#1a2744;color:#8892a4">Admin</a><a href="/realtime-monitor.html" style="padding:2px 8px;border-radius:4px;font-size:9px;font-weight:600;text-decoration:none;background:#1a2744;color:#8892a4">Monitor</a><a href="/agents-goodjob.html" style="padding:2px 8px;border-radius:4px;font-size:9px;font-weight:600;text-decoration:none;background:#1a2744;color:#8892a4">Enterprise</a><a href="/sovereign-claude.html" style="padding:2px 8px;border-radius:4px;font-size:9px;font-weight:600;text-decoration:none;background:#1a2744;color:#8892a4">Sovereign</a><a href="/cyber-monitor.html" style="padding:2px 8px;border-radius:4px;font-size:9px;font-weight:600;text-decoration:none;background:#1a2744;color:#8892a4">Cyber</a></div>
|
||
<div id="hud"><b>WEVAL Enterprise</b><span id="st"></span><span style="margin-left:auto;font-size:.6rem;color:#64748b" id="hud-time"></span></div>
|
||
<canvas id="c"></canvas>
|
||
<div id="T"><b></b><i></i><span class="d"></span><span class="p"></span><span class="s"></span></div>
|
||
<script>
|
||
const C=document.getElementById('c'),X=C.getContext('2d'),TT=document.getElementById('T');
|
||
let W,H,mx=-1,my=-1,hov=null,fr=0,tc=0;
|
||
const DP=[
|
||
{id:'ceo',l:'👑 CEO',cl:'#e94560',fl:'#ffe0e8',pp:['Décision','Budget','Stratégie','Hiring']},
|
||
{id:'sal',l:'🎯 Prospect',cl:'#3b82f6',fl:'#dbeafe',pp:['Leads','Qualify','Outreach','Convert']},
|
||
{id:'con',l:'💼 Consult',cl:'#7c3aed',fl:'#ede9fe',pp:['Analyse','Design','Propose','Deliver']},
|
||
{id:'dev',l:'⚡ Dev Lab',cl:'#10b981',fl:'#d1fae5',pp:['Code','Review','Test','Deploy']},
|
||
{id:'srv',l:'🖥️ Infra',cl:'#f59e0b',fl:'#fef3c7',pp:['Monitor','Fix','Deploy','Verify']},
|
||
{id:'sec',l:'🛡️ Sécu',cl:'#ef4444',fl:'#fee2e2',pp:['Scan','Audit','Patch','Lock']},
|
||
{id:'qa',l:'🧪 QA',cl:'#06b6d4',fl:'#cffafe',pp:['Plan','Run','Report','Ship']},
|
||
{id:'pha',l:'💊 Pharma',cl:'#a855f7',fl:'#f3e8ff',pp:['Scrape','Enrich','Campaign','Ship']},
|
||
{id:'ops',l:'📡 Monitor',cl:'#eab308',fl:'#fefce8',pp:['Watch','Alert','Fix','Report']},
|
||
{id:'cron',l:'⏰ Crons',cl:'#64748b',fl:'#f1f5f9',pp:['Ethica','B2B','NonReg','Backup']},
|
||
{id:'mta',l:'📧 MTA',cl:'#ec4899',fl:'#fce7f3',pp:['PMTA','KumoMTA','Postfix','Deliver']},
|
||
{id:'ai',l:'🧠 AI Engine',cl:'#8b5cf6',fl:'#ede9fe',pp:['Groq','Cerebras','Mistral','Ollama']},
|
||
{id:'saas',l:'📦 SaaS',cl:'#14b8a6',fl:'#ccfbf1',pp:['LeadForge','Outreach','MailWarm','Proposal']},
|
||
{id:'dead',l:'💀 Archives',cl:'#94a3b8',fl:'#f1f5f9',pp:['S88 GPU','S89 Legacy','ECS PMTA']},
|
||
{id:'wire',l:'🔌 TO WIRE',cl:'#f97316',fl:'#fff7ed',pp:['Connect','Config','Test','Activate']},
|
||
{id:'intg',l:'🔗 TO INTEGRATE',cl:'#84cc16',fl:'#f7fee7',pp:['Evaluate','Import','Wire','Ship']},
|
||
{id:'dock',l:'🐳 Docker/Services',cl:'#0ea5e9',fl:'#e0f2fe',pp:['Start','Configure','Monitor','Scale']},
|
||
{id:'dorm',l:'💤 Dormants',cl:'#a1a1aa',fl:'#fafafa',pp:['Clone','Evaluate','Wire','Activate']},
|
||
{id:'wevia',l:'🧠 WEVIA Suite',cl:'#6366f1',fl:'#eef2ff',pp:['Chat','Code','Life','Gateway']},
|
||
{id:'plat',l:'🔧 Platform',cl:'#0d9488',fl:'#ccfbf1',pp:['Skills','Prompts','Wiki','Bench']}
|
||
];
|
||
// OUTPUT KPIs per dept (right panel)
|
||
// Frequency per dept (for bubble display)
|
||
const AMETA={
|
||
'CEO':{fq:'1x/j 7h',inp:'3 rapports équipe'},
|
||
'Ethica':{fq:'*/5min 24/7',inp:'DabaDoc + LinkedIn'},
|
||
'Analyst':{fq:'3x/j',inp:'Données marché B2B'},
|
||
'Writer':{fq:'5x/j',inp:'Briefs client'},
|
||
'Proposal':{fq:'sur demande',inp:'Specs client'},
|
||
'Contract':{fq:'sur demande',inp:'Terms signés'},
|
||
'Architect':{fq:'2x/j',inp:'Cahier des charges'},
|
||
'Planner':{fq:'1x/j matin',inp:'Backlog JIRA'},
|
||
'DeerFlow':{fq:'3x/j',inp:'Question recherche'},
|
||
'Critic':{fq:'sur demande',inp:'Proposal à valider'},
|
||
'Translate':{fq:'sur demande',inp:'Page à traduire'},
|
||
'Academy':{fq:'1x/semaine',inp:'Contenu formation'},
|
||
'Executor':{fq:'5-15x/j',inp:'PR merged'},
|
||
'Debugger':{fq:'3-8x/j',inp:'Bug report'},
|
||
'Reviewer':{fq:'5x/j',inp:'Pull request'},
|
||
'Designer':{fq:'2x/j',inp:'Wireframe/spec'},
|
||
'WEDROID':{fq:'continu 24/7',inp:'Erreur détectée'},
|
||
'Simplifier':{fq:'1x/j',inp:'Module >500 lignes'},
|
||
'Blueprint':{fq:'sur demande',inp:'Specs projet'},
|
||
'DevForge':{fq:'sur demande',inp:'Template code'},
|
||
'Watchdog':{fq:'*/3min 24/7',inp:'20 Docker + 5 svc'},
|
||
'Guardian':{fq:'*/5min 24/7',inp:'8 fichiers protégés'},
|
||
'Blade':{fq:'*/60s 24/7',inp:'Desktop sync'},
|
||
'GitMaster':{fq:'sur push',inp:'Commit Git'},
|
||
'Security':{fq:'2x/j',inp:'OWASP rules'},
|
||
'Verifier':{fq:'1x/semaine',inp:'Checklist ISO'},
|
||
'QA':{fq:'2x/j 6h+18h',inp:'148 test cases'},
|
||
'TestEng':{fq:'sur push',inp:'GitHub Actions'},
|
||
'Tracer':{fq:'continu',inp:'access.log + error.log'},
|
||
'Scientist':{fq:'1x/j 5h',inp:'182 modèles à bench'},
|
||
'Playwright':{fq:'2x/j',inp:'41 scénarios E2E'},
|
||
'Explore':{fq:'3x/j',inp:'URLs annuaires santé'},
|
||
'DocSpec':{fq:'sur demande',inp:'API à documenter'},
|
||
'MiroFish':{fq:'1x/j',inp:'Brief créatif'},
|
||
'TaskMgr':{fq:'continu',inp:'Tickets ouverts'},
|
||
'Brain':{fq:'1x/j',inp:'Idées brainstorm'},
|
||
'Intro':{fq:'1x/j',inp:'Métriques perf'},
|
||
'Orch':{fq:'continu',inp:'5 agents à sync'},
|
||
'Dashboard':{fq:'temps réel',inp:'KPIs collectés'},
|
||
'EthicaCron':{fq:'*/5min cron',inp:'Queue DZ+MA+TN'},
|
||
'B2BCron':{fq:'/4h cron',inp:'166 leads table'},
|
||
'NonRegCron':{fq:'6h+18h cron',inp:'153 tests suite'},
|
||
'BackupCron':{fq:'4h daily cron',inp:'PG + configs'},
|
||
'PMTA':{fq:'continu port 25',inp:'Queue 10K emails'},
|
||
'KumoMTA':{fq:'continu port 587',inp:'Nouveaux envois'},
|
||
'Postfix':{fq:'continu 2525',inp:'Relais interne'},
|
||
'Groq':{fq:'on-demand <100ms',inp:'Prompt utilisateur'},
|
||
'Cerebras':{fq:'fallback <200ms',inp:'Requête complexe'},
|
||
'Ollama':{fq:'on-demand local',inp:'Requête souveraine'},
|
||
'LeadForge':{fq:'sur demande',inp:'Critères recherche'},
|
||
'OutreachAI':{fq:'sur campagne',inp:'Liste contacts'},
|
||
'MailWarm':{fq:'continu',inp:'IPs à réchauffer'},
|
||
'ProposalAI':{fq:'sur demande',inp:'Brief client'},
|
||
'S88 GPU':{fq:'MORT',inp:'—'},
|
||
'S89':{fq:'DOWN',inp:'—'},
|
||
'ECS PMTA':{fq:'INCONNU',inp:'—'},
|
||
'Loki':{fq:'UP :3102',inp:'Logs Docker'},
|
||
'WEVCODE':{fq:'on-demand',inp:'Question code'},
|
||
'WEVIALife':{fq:'*/5min sync',inp:'Fichiers desktop'},
|
||
'WEVIAGateway':{fq:'continu 24/7',inp:'Requêtes multi-IA'},
|
||
'TTS':{fq:'sur demande',inp:'Texte à vocaliser'},
|
||
'MermaidGen':{fq:'sur demande',inp:'Spec diagramme'},
|
||
'L99':{fq:'sur demande',inp:'79 layers à checker'},
|
||
'ClaudeSync':{fq:'par session',inp:'Transcript Claude'},
|
||
'SkillsRAG':{fq:'on-demand',inp:'Query Qdrant'},
|
||
'PromptsLib':{fq:'on-demand',inp:'Contexte à matcher'},
|
||
'CodeWiki':{fq:'sur commit',inp:'203 fichiers index'},
|
||
'AIBench':{fq:'1x/j 5h cron',inp:'182 modèles API'},
|
||
'OSSDiscover':{fq:'1x/j cron',inp:'GitHub trending'},
|
||
'GHGrab':{fq:'sur demande',inp:'URL repo à cloner'},
|
||
'AgentShield':{fq:'1x/j',inp:'Code source à scan'}
|
||
};
|
||
// Fallback freq by dept
|
||
var FREQ_DEF={ceo:'1x/j',sal:'continu',con:'sur demande',dev:'continu',srv:'*/3min',sec:'2x/j',qa:'2x/j',pha:'*/5min',ops:'continu',cron:'auto',mta:'continu',ai:'on-demand',saas:'on-demand',dead:'—',wire:'—',intg:'—',dock:'24/7',dorm:'—',wevia:'on-demand',plat:'on-demand'};
|
||
const OUT={
|
||
ceo:{input:'📥 Rapports agents',output:'📤 Décisions strat',kpi:'1x/j',icon:'👔',metric:'1 brief/j',deliverables:['Brief Telegram 7h','Validation budget Q3','Revue hiring','Contrats signes']},
|
||
sal:{input:'📥 1052 leads DB',output:'📤 Scraping actif',kpi:'B2B pipeline',icon:'🎯',metric:'1052 leads',deliverables:['131K HCPs Ethica','166 leads B2B','469 LinkedIn','Emails DZ+MA+TN','Proposals PDF']},
|
||
con:{input:'📥 5 demandes/j',output:'📤 3 proposals/j',kpi:'Win rate 60%',icon:'💼',metric:'3 props',deliverables:['Blueprints cloud','Schemas Mermaid','Sprint roadmaps','Traductions 90KB']},
|
||
dev:{input:'📥 Tickets GitHub',output:'📤 Commits+deploys',kpi:'CI/CD continu',icon:'⚡',metric:'12 deploys/j',deliverables:['52 repos maintenus','36 pages WEVADS','APIs cx/droid/sentinel','Git releases']},
|
||
srv:{input:'📥 480 checks/j',output:'📤 5 restarts/j',kpi:'Uptime 99.9%',icon:'🖥️',metric:'99.9%',deliverables:['20 Docker monitores','8 chattr+i','Disk <85%','Nginx reload','30+ crons']},
|
||
sec:{input:'📥 288 scans/j',output:'📤 2 audits/j',kpi:'0 CVE critiques',icon:'🛡️',metric:'0 CVE',deliverables:['Headers HTTP OK','SSL Jun 2026','Fail2Ban','CrowdSec','RGPD check']},
|
||
qa:{input:'📥 153 tests NonReg',output:'📤 153/153 PASS',kpi:'Score 100%',icon:'🧪',metric:'148 PASS',deliverables:['NonReg 153/153','Playwright 41','11 baselines','BackstopJS','Rapport HTML']},
|
||
pha:{input:'📥 DabaDoc+GMap',output:'📤 125,748 HCPs',kpi:'DZ87K MA19K TN17K',icon:'💊',metric:'125.7K',deliverables:['DabaDoc 50 villes','LinkedIn tels','Email gap DZ 15K','Master dedup 5h']},
|
||
ops:{input:'📥 7,752 opens total',output:'📤 4,694 clicks total',kpi:'Track actif',icon:'📡',metric:'7.7K opens',deliverables:['admin.html live','Kanban updated','Weekly report','KPI chart 7j']},
|
||
cron:{input:'📥 18 cron.d S95',output:'📤 Ethica+B2B+NR',kpi:'Auto 24/7',icon:'⏰',metric:'50+ crons/j',deliverables:['EthicaCron 288/j','B2BCron 6/j','NonRegCron 2/j','BackupCron 1/j']},
|
||
mta:{input:'📥 3M contacts DB',output:'📤 7752 opens total',kpi:'50 bounces',icon:'📧',metric:'7.7K opens',deliverables:['PMTA 10K DKIM','KumoMTA routing','Postfix relay','Bounce auto']},
|
||
ai:{input:'📥 7 Ollama models',output:'📤 Groq+Cerebras',kpi:'On-demand',icon:'🧠',metric:'7 models',deliverables:['Groq 500 req/j','Cerebras 120/j','Ollama 200/j','Manager consensus']},
|
||
saas:{input:'📥 8 modules codés',output:'📤 0 users (pas lancé)',kpi:'Pré-launch',icon:'📦',metric:'0 users',deliverables:['LeadForge','OutreachAI','MailWarm','ProposalAI']},
|
||
dead:{input:'📥 —',output:'📤 Tout annulé',kpi:'DONE',icon:'💀',metric:'0€ saved',deliverables:['S88 9.9GB archive','S89 adx 6.6GB','ECS inconnu']},
|
||
wire:{input:'📥 19 évalués',output:'📤 19/19 wired',kpi:'100%',icon:'🔌',metric:'19/19',deliverables:['17 pip/wired: LlamaIndex+Stripe+WhatsApp+Azure+Gemini+CrowdSec+BrowserUse+etc','TODO: OVH SMS (creds manquants)','TODO: ListMonk (Docker S95)']},
|
||
intg:{input:'📥 22 à intégrer',output:'📤 22/22 DONE',kpi:'100%',icon:'🔗',metric:'17/17',deliverables:['Paperclip 150 agents','Authentik SSO','OhMyCC 19','SuperClaude 7']},
|
||
dock:{input:'📥 19 containers',output:'📤 18 UP + Loki KO',kpi:'95% healthy',icon:'🐳',metric:'19 dock',deliverables:['OpenWebUI :8281','Flowise :3033','Twenty :3000','n8n :5678','Loki BROKEN']},
|
||
dorm:{input:'📥 6 clonés',output:'📤 3/6 wired',kpi:'50%',icon:'💤',metric:'3 wired 3 pending',deliverables:['WIRED: Claude-Mem+Strix+Prometheus','TODO: HolyClaude','TODO: LTX-Video (GPU)','TODO: DeepAgent']},
|
||
wevia:{input:'📥 200 sessions/j',output:'📤 200 réponses/j',kpi:'4 modes actifs',icon:'🧠',metric:'200/j',deliverables:['WEVCODE 4 modes','WEVIALife sync','Gateway 18','TTS','L99 93 layers']},
|
||
plat:{input:'📥 Qdrant 4414pts',output:'📤 Skills+Prompts',kpi:'RAG actif',icon:'🔧',metric:'4414 sk'}
|
||
};
|
||
// Rich speech for work state: action + freq + success + output
|
||
const SPEECH={
|
||
'CEO':['📊 Brief quotidien\n⏰ 1×/jour | ✅ 100%\n📤 Décision validée','💰 Revue budget Q3\n⏰ 1×/sem | ✅ 100%\n📤 Budget approuvé'],
|
||
'Ethica':['💊 Scrape DabaDoc MA\n⏰ */5min | ✅ 95%\n📤 +120 HCPs enrichis','📧 Drip email TN\n⏰ */5min | ✅ 88%\n📤 200 emails envoyés'],
|
||
'Analyst':['📊 Analyse marché SAP\n⏰ 3×/jour | ✅ 100%\n📤 Rapport SWOT livré','📈 Segment B2B\n⏰ 2×/jour | ✅ 100%\n📤 50 prospects qualifiés'],
|
||
'Writer':['✍️ Cold email campagne\n⏰ 10×/jour | ✅ 92%\n📤 10 emails rédigés','📝 Proposal client\n⏰ 2×/jour | ✅ 100%\n📤 1 proposal PDF'],
|
||
'Proposal':['📑 Génère proposal\n⏰ 2×/jour | ✅ 100%\n📤 1 PDF formaté','📋 Pricing insert\n⏰ 1×/jour | ✅ 100%\n📤 Grille tarifaire'],
|
||
'Contract':['📜 Génère NDA\n⏰ 1×/sem | ✅ 100%\n📤 1 contrat signé','⚖️ Review contrat\n⏰ 2×/sem | ✅ 100%\n📤 Validé juridique'],
|
||
'Architect':['🏗️ Design archi cloud\n⏰ 1×/jour | ✅ 100%\n📤 Blueprint livré','📐 Schema micro-svc\n⏰ 2×/sem | ✅ 100%\n📤 Diagramme Mermaid'],
|
||
'Planner':['📋 Sprint planning\n⏰ 1×/sem | ✅ 100%\n📤 Backlog priorisé','📊 Update Gantt\n⏰ 1×/jour | ✅ 100%\n📤 Timeline à jour'],
|
||
'DeerFlow':['🦌 Deep research IA\n⏰ 3×/jour | ✅ 97%\n📤 Synthèse 12 sources','📚 Veille techno\n⏰ 1×/jour | ✅ 100%\n📤 Rapport R&D'],
|
||
'Critic':['⚖️ Évalue risques\n⏰ 2×/jour | ✅ 100%\n📤 Matrice risques','🔍 Challenge budget\n⏰ 1×/sem | ✅ 100%\n📤 Go/NoGo décision'],
|
||
'Translate':['🌍 Traduction FR→AR\n⏰ 5×/jour | ✅ 98%\n📤 Page traduite','🌐 Sync i18n\n⏰ 1×/jour | ✅ 100%\n📤 90KB mis à jour'],
|
||
'Academy':['🎓 Génère training\n⏰ 1×/sem | ✅ 100%\n📤 Module formation','📝 Quiz create\n⏰ 2×/sem | ✅ 100%\n📤 10 questions'],
|
||
'Executor':['⚡ Deploy prod v3.2\n⏰ 5×/jour | ✅ 95%\n📤 Release déployée','🔄 Migration DB\n⏰ 1×/jour | ✅ 100%\n📤 Schema migré'],
|
||
'Debugger':['🐛 Fix API 500\n⏰ 3×/jour | ✅ 90%\n📤 Bug résolu','🔍 Trace memory leak\n⏰ 1×/jour | ✅ 85%\n📤 Leak colmaté'],
|
||
'Reviewer':['👁️ Review PR #847\n⏰ 5×/jour | ✅ 100%\n📤 PR approuvé','🔍 Audit qualité\n⏰ 2×/jour | ✅ 100%\n📤 Score qualité'],
|
||
'Designer':['🎨 Mockup dashboard\n⏰ 2×/jour | ✅ 100%\n📤 Design livré','🖌️ Animation CSS\n⏰ 1×/jour | ✅ 100%\n📤 Composant animé'],
|
||
'WEDROID':['🤖 Auto-fix API auth\n⏰ 10×/jour | ✅ 93%\n📤 Service réparé','🔧 Repair PG index\n⏰ 3×/jour | ✅ 97%\n📤 Index rebuilt'],
|
||
'Simplifier':['✂️ Refactor 2K lignes\n⏰ 1×/jour | ✅ 100%\n📤 -40% code','🗑️ Dead code cleanup\n⏰ 2×/jour | ✅ 100%\n📤 50 fichiers nettoyés'],
|
||
'Blueprint':['📐 Auto blueprint\n⏰ 1×/jour | ✅ 100%\n📤 Projet structuré','🏗️ Template gen\n⏰ 2×/sem | ✅ 100%\n📤 Scaffold complet'],
|
||
'DevForge':['🔨 Gen component\n⏰ 3×/jour | ✅ 88%\n📤 Composant React','⚙️ API scaffold\n⏰ 1×/jour | ✅ 95%\n📤 CRUD endpoint'],
|
||
'Watchdog':['🐕 Check */3min\n⏰ 480×/jour | ✅ 99.8%\n📤 20 Docker monitorés','⚠️ Restart service\n⏰ 5×/jour | ✅ 100%\n📤 Service relancé'],
|
||
'Guardian':['🛡️ chattr +i config\n⏰ 288×/jour | ✅ 100%\n📤 8 fichiers protégés','🔒 Scan intrus\n⏰ */5min | ✅ 100%\n📤 0 intrusion'],
|
||
'Blade':['💻 Sync Razer→S204\n⏰ 1440×/jour | ✅ 99.5%\n📤 Fichiers synchronisés','📁 Upload docs\n⏰ 10×/jour | ✅ 100%\n📤 Docs uploadés'],
|
||
'GitMaster':['🌿 Tag v3.2.1\n⏰ 2×/jour | ✅ 100%\n📤 Release taguée','🔀 Merge develop\n⏰ 3×/jour | ✅ 100%\n📤 Branch merged'],
|
||
'Security':['🔐 Scan OWASP top10\n⏰ 2×/jour | ✅ 100%\n📤 0 vulnérabilité','🔒 Audit headers\n⏰ 1×/jour | ✅ 100%\n📤 Headers conformes'],
|
||
'Verifier':['✅ Check RGPD\n⏰ 1×/sem | ✅ 100%\n📤 Compliance OK','📋 Audit ISO 27001\n⏰ 1×/mois | ✅ 100%\n📤 Certification'],
|
||
'QA':['🧪 Run NonReg 153\n⏰ 2×/jour | ✅ 100%\n📤 153/153 PASS','🎭 Playwright 41\n⏰ 1×/jour | ✅ 100%\n📤 41/41 screenshots'],
|
||
'TestEng':['🧰 Build Docker img\n⏰ 3×/jour | ✅ 95%\n📤 Image publiée','⚙️ Pipeline CI\n⏰ 5×/jour | ✅ 90%\n📤 Build green'],
|
||
'Tracer':['🔦 Trace erreur 500\n⏰ 5×/jour | ✅ 88%\n📤 Root cause trouvé','📋 Parse access.log\n⏰ 1×/jour | ✅ 100%\n📤 Anomalies détectées'],
|
||
'Scientist':['🔬 Bench 182 modèles\n⏰ 1×/jour | ✅ 100%\n📤 Leaderboard updated','📊 Mesure latence\n⏰ 1×/jour | ✅ 100%\n📤 8 endpoints testés'],
|
||
'Playwright':['🎭 Visual test 41\n⏰ 1×/jour | ✅ 100%\n📤 41 baselines OK','📸 Screenshot diff\n⏰ 1×/jour | ✅ 98%\n📤 0 régression'],
|
||
'EthicaCron':['⏰ Drip DZ+MA+TN\n⏰ 288×/jour | ✅ 95%\n📤 +500 HCPs/jour','📧 Master dedup 5h\n⏰ 1×/jour | ✅ 100%\n📤 Base nettoyée'],
|
||
'B2BCron':['🔄 B2B scrape cycle\n⏰ 6×/jour | ✅ 88%\n📤 +20 leads/cycle','📧 Email pattern gen\n⏰ 6×/jour | ✅ 75%\n📤 Patterns validés'],
|
||
'NonRegCron':['🧪 153 tests auto\n⏰ 2×/jour | ✅ 100%\n📤 Report HTML','📊 Alert TG si FAIL\n⏰ 2×/jour | ✅ 100%\n📤 Telegram envoyé'],
|
||
'BackupCron':['💾 PG backup daily\n⏰ 1×/jour | ✅ 100%\n📤 Dump 22MB','📦 GOLD sync\n⏰ 1×/jour | ✅ 100%\n📤 Configs archivées'],
|
||
'PMTA':['📮 Batch 10K emails\n⏰ continu | ✅ 98%\n📤 10K livrés/jour','🔑 DKIM signing\n⏰ continu | ✅ 100%\n📤 Signature valide'],
|
||
'KumoMTA':['🚀 Smart routing\n⏰ continu | ✅ 97%\n📤 5K livrés/jour','🌡️ Warm IP pool\n⏰ continu | ✅ 95%\n📤 Réputation maintenue'],
|
||
'Groq':['⚡ Process 500 req/j\n⏰ continu | ✅ 99.5%\n📤 Latence 180ms avg','🧠 Classify intent\n⏰ continu | ✅ 97%\n📤 Classification OK'],
|
||
'Ollama':['🏠 Run qwen3:8b\n⏰ continu | ✅ 99%\n📤 Inference locale','🧠 Embed all-minilm\n⏰ continu | ✅ 100%\n📤 Vecteurs générés'],
|
||
'Watchdog':['🐕 Check */3min\n⏰ 480×/jour | ✅ 99.8%\n📤 Tout UP','⚠️ Alert disk\n⏰ si >85% | ✅ 100%\n📤 Telegram envoyé']
|
||
};
|
||
const AG=[
|
||
{n:'CEO',rm:'ceo',d:'Direction',p:'Stratégie',sk:'#f0d0b0',hc:'#111',F:0,re:'👔',act:['Valide budget Q3','Signe contrat','Brief board','Hiring review'],deliverables:['4414 skills Qdrant','55 prompts','203 fichiers','182 modeles','505 OSS']},
|
||
{n:'Ethica',rm:'sal',d:'Scraping',p:'131K HCPs',sk:'#c99565',hc:'#3a1800',F:1,re:'💊',act:['Scrape DabaDoc','Enrichit 500 HCPs','LinkedIn TN','Update DZ']},
|
||
{n:'Analyst',rm:'sal',d:'Analyse',p:'Specs',sk:'#f0d0b0',hc:'#6a4a30',F:1,gl:1,re:'📊',act:['Analyse marché','Concurrence','SWOT','Segment B2B']},
|
||
{n:'Writer',rm:'sal',d:'Rédaction',p:'Emails',sk:'#f0d0b0',hc:'#8a5020',F:1,re:'✍️',act:['Cold email','Proposal','LinkedIn post','Pitch deck']},
|
||
{n:'Architect',rm:'con',d:'Archi',p:'Blueprints',sk:'#e8cca0',hc:'#2a2a3a',F:0,gl:1,re:'🏗️',act:['Cloud archi','Microservices','Blueprint','Diagramme']},
|
||
{n:'Planner',rm:'con',d:'Planning',p:'Roadmaps',sk:'#f0d0b0',hc:'#5a3a1a',F:1,re:'📋',act:['Sprint plan','Gantt update','Backlog','Estimation']},
|
||
{n:'DeerFlow',rm:'con',d:'Research',p:'113 skills',sk:'#d8b080',hc:'#6a4020',F:0,re:'🦌',act:['Deep research','12 sources','Veille tech','Rapport R&D']},
|
||
{n:'Critic',rm:'con',d:'Validation',p:'Risques',sk:'#e8cca0',hc:'#3a3a4a',F:0,gl:1,re:'⚖️',act:['Risques','Review','Challenge','Faisabilité']},
|
||
{n:'Executor',rm:'dev',d:'Deploy',p:'Scripts',sk:'#c99565',hc:'#222',F:0,re:'⚡',act:['Deploy v3.2','Migration DB','Backup script','Dockerfile']},
|
||
{n:'Debugger',rm:'dev',d:'Debug',p:'Fixes',sk:'#f0d0b0',hc:'#4a2a10',F:0,gl:1,re:'🐛',act:['Fix API 500','Memory leak','Nginx conf','SQL injection']},
|
||
{n:'Reviewer',rm:'dev',d:'Review',p:'PRs',sk:'#e8cca0',hc:'#333',F:0,re:'👁️',act:['Review PR','Code audit','Conventions','Merge']},
|
||
{n:'Designer',rm:'dev',d:'UI/UX',p:'Mockups',sk:'#f0d0b0',hc:'#d946ef',F:1,re:'🎨',act:['Dashboard','Design sys','Figma proto','CSS anim']},
|
||
{n:'WEDROID',rm:'dev',d:'Auto-fix v5',p:'DB+API',sk:'#8899aa',hc:'#5a7a9a',F:0,bot:1,re:'🤖',act:['Fix API auth','Repair PG','Clean rows','Restart svc']},
|
||
{n:'Simplifier',rm:'dev',d:'Refactor',p:'-40%',sk:'#e8cca0',hc:'#6a4030',F:1,gl:1,re:'✂️',act:['Refactor 2K','Dead code','Simplifie','Merge dupes']},
|
||
{n:'Watchdog',rm:'srv',d:'Monitor */3',p:'20 Docker',sk:'#d8b080',hc:'#8a6a30',F:0,re:'🐕',act:['Restart Nginx','Disk alert','Ping Docker','Check Ollama']},
|
||
{n:'Guardian',rm:'srv',d:'Protection',p:'chattr +i',sk:'#c99565',hc:'#1a2a1a',F:0,re:'🛡️',act:['chattr +i','Scan intrus','Lock SSH','Firewall']},
|
||
{n:'Blade',rm:'srv',d:'Desktop',p:'PowerShell',sk:'#f0d0b0',hc:'#1a3050',F:0,re:'💻',act:['Sync→S204','PowerShell','Task planif','Upload docs']},
|
||
{n:'GitMaster',rm:'srv',d:'Git flow',p:'Releases',sk:'#e8cca0',hc:'#3a5a2a',F:0,gl:1,re:'🌿',act:['Tag v3.2.1','Merge dev','Cherry-pick','Release']},
|
||
{n:'Security',rm:'sec',d:'OWASP',p:'Pentests',sk:'#c99565',hc:'#111',F:0,re:'🔐',act:['OWASP top10','Headers','XSS test','SSL certs']},
|
||
{n:'Verifier',rm:'sec',d:'ISO/RGPD',p:'PCI-DSS',sk:'#e8cca0',hc:'#3a3a4a',F:1,gl:1,re:'✅',act:['RGPD check','ISO 27001','PCI-DSS','Access ctrl']},
|
||
{n:'QA',rm:'qa',d:'Tests E2E',p:'148 NonReg',sk:'#f0d0b0',hc:'#2a3a5a',F:1,re:'🧪',act:['NonReg 153','Playwright','Selenium','Responsive']},
|
||
{n:'TestEng',rm:'qa',d:'CI/CD',p:'Pipelines',sk:'#e8cca0',hc:'#4a3a2a',F:0,re:'🧰',act:['Pipeline CI','GitHub Act','Docker build','Staging']},
|
||
{n:'Tracer',rm:'qa',d:'Log trace',p:'Stack traces',sk:'#d8b080',hc:'#3a2a1a',F:1,re:'🔦',act:['Erreur 500','access.log','Stack trace','Event corrèl']},
|
||
{n:'Scientist',rm:'qa',d:'Benchmarks',p:'182 modèles',sk:'#f0d0b0',hc:'#888',F:1,gl:1,re:'🔬',act:['Groq vs Cerebras','Latence API','Accuracy','182 modèles']},
|
||
{n:'Explore',rm:'pha',d:'R&D',p:'Sources HCP',sk:'#c99565',hc:'#5a3a10',F:0,re:'🧭',act:['Annuaire MA','Source DZ','Nouvelle API','Fournisseur']},
|
||
{n:'DocSpec',rm:'pha',d:'Docs',p:'Templates',sk:'#e8cca0',hc:'#333',F:1,gl:1,re:'📝',act:['Template','API Ethica','Guide user','README']},
|
||
{n:'MiroFish',rm:'pha',d:'Creative',p:'Brainstorm',sk:'#f0d0b0',hc:'#06b6d4',F:1,re:'🐟',act:['Campagne','Contenu','Newsletter','Brief']},
|
||
{n:'TaskMgr',rm:'ops',d:'Tâches',p:'Kanban',sk:'#e8cca0',hc:'#4a4a3a',F:1,re:'📋',act:['Kanban','Deadlines','Priorités','Status']},
|
||
{n:'Brain',rm:'ops',d:'Idées',p:'Innovation',sk:'#f0d0b0',hc:'#eab308',F:0,re:'💡',act:['Produit','Process','R&D','PoC']},
|
||
{n:'Intro',rm:'ops',d:'Méta',p:'Amélioration',sk:'#e8cca0',hc:'#a855f7',F:1,re:'🧠',act:['Perf analyse','Prompts','Méta-cog','Workflow']},
|
||
{n:'Orch',rm:'ops',d:'Orchestration',p:'Multi-agent',sk:'#c99565',hc:'#222',F:0,re:'🎯',act:['Sync agents','Deploy coord','Pipeline','Multi-task']},
|
||
{n:'EthicaCron',rm:'cron',d:'Drip */5min',p:'DZ+MA+TN',sk:'#e8cca0',hc:'#64748b',F:1,re:'⏰',act:['Drip DZ','DabaDoc scrape','Enrich tels','Dedup master']},
|
||
{n:'B2BCron',rm:'cron',d:'Scrape /4h',p:'Lead gen',sk:'#f0d0b0',hc:'#64748b',F:0,re:'🔄',act:['LinkedIn','Email pattern','Playwright','Enricher']},
|
||
{n:'NonRegCron',rm:'cron',d:'6h/18h',p:'153 tests',sk:'#d8b080',hc:'#64748b',F:0,re:'🧪',act:['153 tests','5 couches','TG alert','HTML report']},
|
||
{n:'BackupCron',rm:'cron',d:'Daily 4am',p:'PG+vault',sk:'#e8cca0',hc:'#64748b',F:1,re:'💾',act:['PG backup','GOLD sync','Config arch','Sentinel']},
|
||
{n:'PMTA',rm:'mta',d:'Port 25',p:'ADX legacy',sk:'#f0d0b0',hc:'#ec4899',F:0,re:'📮',act:['Batch 10K','DKIM sign','Bounce proc','Queue mgmt']},
|
||
{n:'KumoMTA',rm:'mta',d:'587+8010',p:'New sends',sk:'#e8cca0',hc:'#ec4899',F:0,re:'🚀',act:['Smart route','IP warm','Track opens','DMARC']},
|
||
{n:'Postfix',rm:'mta',d:'2525/2526',p:'Internal',sk:'#d8b080',hc:'#ec4899',F:1,re:'📬',act:['Relay int','Forward','Queue flush','Log rotate']},
|
||
{n:'Groq',rm:'ai',d:'Llama 70B',p:'Default',sk:'#f0d0b0',hc:'#8b5cf6',F:0,re:'⚡',act:['500 req/s','Response','Classify','Embed']},
|
||
{n:'Cerebras',rm:'ai',d:'Qwen 235B',p:'Fallback',sk:'#e8cca0',hc:'#8b5cf6',F:1,re:'🧮',act:['Reasoning','Long ctx','Multi-turn','Code gen']},
|
||
{n:'Ollama',rm:'ai',d:'12 models',p:'pip ollama',sk:'#d8b080',hc:'#8b5cf6',F:0,re:'🏠',act:['qwen3:8b','all-minilm','medllama2','weval-brain']},
|
||
{n:'LeadForge',rm:'saas',d:'Lead engine',p:'B2B pipe',sk:'#f0d0b0',hc:'#14b8a6',F:1,re:'🎣',act:['Gen leads','Score','Enrich','Export']},
|
||
{n:'OutreachAI',rm:'saas',d:'AI outreach',p:'Campaigns',sk:'#e8cca0',hc:'#14b8a6',F:0,re:'📨',act:['Sequence','A/B test','Schedule','Track']},
|
||
{n:'MailWarm',rm:'saas',d:'IP warming',p:'Deliver',sk:'#d8b080',hc:'#14b8a6',F:1,re:'🔥',act:['Warm IP','Ramp vol','Reputation','Rotate']},
|
||
{n:'ProposalAI',rm:'saas',d:'AI proposals',p:'Doc gen',sk:'#f0d0b0',hc:'#14b8a6',F:0,re:'📄',act:['Proposal','PDF','Pricing','Customize']},
|
||
{n:'S88 GPU',rm:'dead',d:'DEAD GPU',p:'-45€/mois',sk:'#94a3b8',hc:'#64748b',F:0,re:'💀',act:['GPU mort','À annuler','9.9GB archivé','wevia_db OK']},
|
||
{n:'S89',rm:'dead',d:'Old Ethica',p:'DOWN',sk:'#94a3b8',hc:'#64748b',F:1,re:'⚰️',act:['Port DOWN','adx 6.6GB','clients 2.8GB','Archivé']},
|
||
{n:'ECS PMTA',rm:'dead',d:'SER 6-9',p:'Unknown',sk:'#94a3b8',hc:'#64748b',F:0,re:'❓',act:['Cluster','root/Yacine','À vérifier','Status ?']},
|
||
{n:'LlamaIndex',rm:'intg',d:'RAG framework',p:'Qdrant WIRED',sk:'#f0d0b0',hc:'#f97316',F:0,re:'🦙',act:['Connect Qdrant','Index 4414 pts','Query pipeline','RAG search']},
|
||
{n:'CrewAI',rm:'wire',d:'Multi-agent',p:'OSS WIRED',sk:'#e8cca0',hc:'#f97316',F:1,re:'👥',act:['Wire agents','Team config','Task flow','Orchestrate']},
|
||
{n:'AutoGen',rm:'intg',d:'MS agents',p:'pip WIRED',sk:'#f0d0b0',hc:'#f97316',F:0,re:'🤝',act:['Agent conv','Multi-turn','Code exec','Review chain']},
|
||
{n:'AnythingLLM',rm:'intg',d:'Chat+RAG',p:'OSS WIRED',sk:'#d8b080',hc:'#f97316',F:1,re:'💬',act:['Wire docs','Embed corpus','Chat RAG','Knowledge']},
|
||
{n:'Dify',rm:'wire',d:'LLM ops',p:'OSS WIRED',sk:'#e8cca0',hc:'#f97316',F:0,re:'🔧',act:['Flow builder','Prompt mgmt','API chain','Deploy flow']},
|
||
{n:'vLLM',rm:'intg',d:'Fast inference',p:'Colab GPU',sk:'#f0d0b0',hc:'#f97316',F:0,re:'🏎️',act:['Serve model','Batch infer','PagedAttn','Throughput']},
|
||
{n:'LocalAI',rm:'intg',d:'Local models',p:'HF Spaces',sk:'#d8b080',hc:'#f97316',F:1,re:'🏡',act:['Local serve','GGUF load','API compat','CPU optim']},
|
||
{n:'Stripe',rm:'wire',d:'Payments',p:'PK+SK LIVE',sk:'#e8cca0',hc:'#f97316',F:0,re:'💳',act:['Add SK live','Wire billing','Webhook','Test charge']},
|
||
{n:'WhatsApp',rm:'wire',d:'Meta API',p:'API LIVE',sk:'#f0d0b0',hc:'#f97316',F:1,re:'📱',act:['Get token','Wire API','Template msg','Send flow']},
|
||
{n:'OVH SMS',rm:'wire',d:'SMS gateway',p:'Creds missing',sk:'#d8b080',hc:'#f97316',F:0,re:'📲',act:['Get API key','Wire sender','Template','Campaign']},
|
||
{n:'Azure AD',rm:'wire',d:'Graph API',p:'6/9 actifs',sk:'#e8cca0',hc:'#f97316',F:1,re:'☁️',act:['Re-register','Refresh token','Graph query','Sync contacts']},
|
||
{n:'Gemini',rm:'wire',d:'Google AI',p:'KEY ACTIVE',sk:'#f0d0b0',hc:'#f97316',F:0,re:'♊',act:['Enable API','Get key','Wire provider','Test gen']},
|
||
{n:'HF TRL',rm:'intg',d:'Fine-tune',p:'TRL WIRED',sk:'#f0d0b0',hc:'#84cc16',F:0,re:'🎓',act:['Upload Colab','Train LoRA','Eval model','Deploy GGUF']},
|
||
{n:'Mastra',rm:'intg',d:'Agent SDK',p:'OSS WIRED',sk:'#e8cca0',hc:'#84cc16',F:1,re:'🔮',act:['npm install','Wire tools','Agent def','Deploy']},
|
||
{n:'EvoMaster',rm:'intg',d:'API fuzzing',p:'OSS WIRED',sk:'#d8b080',hc:'#84cc16',F:0,re:'🧬',act:['Fuzz 214 APIs','Find bugs','Report','Auto-fix']},
|
||
{n:'Activepieces',rm:'intg',d:'Automation',p:'OSS WIRED',sk:'#f0d0b0',hc:'#84cc16',F:1,re:'🧩',act:['Wire triggers','Flow build','Connect APIs','Schedule']},
|
||
{n:'Goose',rm:'intg',d:'Dev agent',p:'OSS WIRED',sk:'#e8cca0',hc:'#84cc16',F:0,re:'🪿',act:['Install CLI','Wire repos','Auto-code','Review']},
|
||
{n:'AEGIS',rm:'intg',d:'Security AI',p:'OSS WIRED',sk:'#d8b080',hc:'#84cc16',F:1,re:'🏛️',act:['Wire scanner','Auto audit','Report CVE','Patch suggest']},
|
||
{n:'SkillSmith',rm:'intg',d:'Skill gen',p:'OSS WIRED',sk:'#f0d0b0',hc:'#84cc16',F:0,re:'⚒️',act:['Gen skills','Test','Deploy','Catalog']},
|
||
{n:'AIOS',rm:'intg',d:'OS for AI',p:'OSS WIRED',sk:'#e8cca0',hc:'#84cc16',F:1,re:'🖥️',act:['Install','Wire agents','Schedule','Monitor']},
|
||
{n:'Wazuh',rm:'sec',d:'SIEM security',p:'/opt WIRED',sk:'#f0d0b0',hc:'#f97316',F:0,re:'🔒',act:['Deploy SIEM','Wire alerts','Log collect','Threat detect']},
|
||
{n:'CrowdSec',rm:'wire',d:'IDS/IPS',p:'systemd ACTIVE',sk:'#e8cca0',hc:'#f97316',F:1,re:'🏰',act:['Block brute','Parse logs','Share intel','Ban IPs']},
|
||
{n:'BrowserUse',rm:'wire',d:'Web automate',p:'OSS WIRED',sk:'#d8b080',hc:'#f97316',F:0,re:'🌐',act:['Auto browse','Fill forms','Scrape JS','Screenshot']},
|
||
{n:'Supermemory',rm:'wire',d:'Knowledge',p:'OSS WIRED',sk:'#f0d0b0',hc:'#f97316',F:1,re:'📚',act:['Store memory','Recall context','Index docs','Search KB']},
|
||
{n:'Paperclip',rm:'intg',d:'Agent fleet',p:'150 LIVE',sk:'#e8cca0',hc:'#84cc16',F:0,re:'📎',act:['CEO agent run','CTO delegate','Hire agent','Fleet manage']},
|
||
{n:'WevalRadar',rm:'intg',d:'Monitoring',p:'OSS WIRED',sk:'#d8b080',hc:'#84cc16',F:1,re:'📡',act:['Scan ports','Check DNS','Monitor SSL','Alert change']},
|
||
{n:'WevalScrapy',rm:'intg',d:'Scraping fw',p:'OSS WIRED',sk:'#f0d0b0',hc:'#84cc16',F:0,re:'🕷️',act:['Crawl sites','Extract data','Pipeline','Export JSON']},
|
||
{n:'WevBrain',rm:'intg',d:'AI brain',p:'Ollama UP',sk:'#e8cca0',hc:'#84cc16',F:1,re:'🧠',act:['Train brain','Fine-tune','Ollama serve','Inference']},
|
||
{n:'Authentik',rm:'intg',d:'SSO/IdP',p:'SSO LIVE',sk:'#d8b080',hc:'#84cc16',F:0,re:'🔑',act:['SSO login','OAuth flow','LDAP sync','MFA enforce']},
|
||
{n:'Fail2Ban',rm:'dock',d:'IPS S204+S95',p:'RUNNING',sk:'#f0d0b0',hc:'#0ea5e9',F:0,re:'🚫',act:['Block brute','Ban SSH','Jail nginx','Unban IP']},
|
||
{n:'ListMonk',rm:'wire',d:'Newsletter S95',p:'TODO Docker',sk:'#e8cca0',hc:'#f97316',F:1,re:'📰',act:['Wire SMTP','Import list','Template','Campaign']},
|
||
{n:'NoVNC',rm:'wire',d:'Remote S95',p:'pip 1.0 OK',sk:'#d8b080',hc:'#f97316',F:0,re:'🖥️',act:['Wire VNC','Remote access','Browser desktop','Config']},
|
||
{n:'OpenClaw',rm:'dock',d:'AI proxy S151',p:'SSO LIVE',sk:'#f0d0b0',hc:'#0ea5e9',F:1,re:'🦀',act:['Route AI calls','Multi-provider','Ollama proxy','Log usage']},
|
||
{n:'DroidCLI',rm:'intg',d:'Orchestrator S95',p:'WEDROID LIVE',sk:'#e8cca0',hc:'#84cc16',F:0,re:'🤖',act:['Chain exec S95','Sentinel cmd','DB query','Deploy']},
|
||
{n:'Arsenal',rm:'dock',d:'192 endpoints S95',p:'RUNNING',sk:'#d8b080',hc:'#0ea5e9',F:0,re:'🏟️',act:['Serve 192 URLs','Track campaigns','Bounce handle','Stats']},
|
||
{n:'ADXCache',rm:'dock',d:'Cache cleaner S95',p:'RUNNING',sk:'#f0d0b0',hc:'#0ea5e9',F:1,re:'🧹',act:['Clean cache','Purge old','Free mem','Optimize']},
|
||
{n:'SearchProxy',rm:'dock',d:'SearXNG proxy',p:'systemd UP',sk:'#e8cca0',hc:'#0ea5e9',F:0,re:'🔎',act:['Proxy search','Multi-engine','Rate limit','Cache']},
|
||
{n:'WevRelay',rm:'dock',d:'WEVADS relay',p:'systemd UP',sk:'#d8b080',hc:'#0ea5e9',F:1,re:'🔀',act:['Relay HTTP','Route S95','Track pixel','Redirect']},
|
||
{n:'OhMyCC',rm:'intg',d:'19 agents',p:'WIRED',sk:'#f0d0b0',hc:'#84cc16',F:0,re:'🎭',act:['19 agent defs','Dispatch skill','Route mode','Catalog']},
|
||
{n:'SuperClaude',rm:'intg',d:'7 modes',p:'WIRED',sk:'#e8cca0',hc:'#84cc16',F:1,re:'🦸',act:['Fast mode','Deep mode','Code mode','Math mode']},
|
||
{n:'Antigravity',rm:'intg',d:'4414 skills',p:'4414 LIVE',sk:'#d8b080',hc:'#84cc16',F:0,re:'🚀',act:['Search skills','Match task','Qdrant query','Auto-select']},
|
||
{n:'EthicaScripts',rm:'dock',d:'15 scripts S95',p:'Cron active',sk:'#f0d0b0',hc:'#0ea5e9',F:1,re:'💉',act:['DabaDoc scrape','LinkedIn drip','Email enrich','Master dedup']},
|
||
{n:'B2BScripts',rm:'dock',d:'10 scripts S95',p:'Cron /4h',sk:'#e8cca0',hc:'#0ea5e9',F:0,re:'🏢',act:['Scrape leads','Pattern emails','Mega enricher','Round 2']},
|
||
{n:'Microsoft',rm:'wire',d:'Graph API S95',p:'6 tenants ACTIVE',sk:'#d8b080',hc:'#f97316',F:1,re:'Ⓜ️',act:['Wire Graph','O365 sync','Calendar','Contacts']},
|
||
{n:'TrackingS151',rm:'dock',d:'16 PHP files',p:'S151 relay',sk:'#f0d0b0',hc:'#0ea5e9',F:0,re:'📍',act:['Track opens','Track clicks','Relay→S204','Log events']},
|
||
{n:'OllamaS95',rm:'dock',d:'Ollama S95',p:'systemd UP',sk:'#e8cca0',hc:'#0ea5e9',F:1,re:'🦙',act:['phi4-mini','smollm2','qwen3.5','Local infer']},
|
||
{n:'WEVCODE',rm:'wevia',d:'Code assistant',p:'4 modes',sk:'#f0d0b0',hc:'#6366f1',F:0,re:'💻',act:['Fast mode','Deep mode','Code mode','Math mode']},
|
||
{n:'WEVIALife',rm:'wevia',d:'Email sync',p:'Desktop→S204',sk:'#e8cca0',hc:'#6366f1',F:1,re:'📧',act:['Sync desktop','Upload docs','Track files','Index']},
|
||
{n:'WEVIAGateway',rm:'wevia',d:'AI gateway',p:'18 providers',sk:'#d8b080',hc:'#6366f1',F:0,re:'🌐',act:['Route Groq','Fallback Cerebras','Proxy Mistral','Load balance']},
|
||
{n:'TTS',rm:'wevia',d:'Text-to-Speech',p:'Voice gen',sk:'#f0d0b0',hc:'#6366f1',F:1,re:'🔊',act:['Generate voice','FR accent','Stream audio','Cache result']},
|
||
{n:'MermaidGen',rm:'wevia',d:'Diagram gen',p:'mmdc',sk:'#e8cca0',hc:'#6366f1',F:0,re:'📊',act:['Gen flowchart','Sequence diag','Class diag','Export SVG']},
|
||
{n:'L99',rm:'wevia',d:'Command Center',p:'79 layers',sk:'#d8b080',hc:'#6366f1',F:1,re:'🎮',act:['Check 79 layers','Score system','Deep audit','Report']},
|
||
{n:'ClaudeSync',rm:'wevia',d:'Claude monitor',p:'Doc sync',sk:'#f0d0b0',hc:'#6366f1',F:0,re:'📋',act:['Sync transcripts','Track sessions','Upload docs','Index']},
|
||
{n:'Blueprint',rm:'dev',d:'Auto blueprint',p:'Project gen',sk:'#d8b080',hc:'#10b981',F:1,re:'📐',act:['Gen blueprint','Archi auto','Template proj','Export']},
|
||
{n:'Proposal',rm:'sal',d:'AI proposals',p:'Doc gen',sk:'#e8cca0',hc:'#3b82f6',F:0,re:'📑',act:['Gen proposal','Format PDF','Insert pricing','Customize']},
|
||
{n:'Contract',rm:'sal',d:'Contract gen',p:'Legal docs',sk:'#d8b080',hc:'#3b82f6',F:1,re:'📜',act:['Gen contract','NDA template','Terms gen','Review']},
|
||
{n:'Dashboard',rm:'ops',d:'Auto dashboard',p:'Analytics',sk:'#f0d0b0',hc:'#eab308',F:0,re:'📈',act:['Gen dashboard','KPI charts','Auto report','Export']},
|
||
{n:'Translate',rm:'con',d:'Multi-langue',p:'90KB sacred',sk:'#e8cca0',hc:'#7c3aed',F:1,re:'🌍',act:['Translate FR','Translate AR','Translate EN','Sync i18n']},
|
||
{n:'DevForge',rm:'dev',d:'Code gen',p:'Full stack',sk:'#d8b080',hc:'#10b981',F:0,re:'🔨',act:['Gen component','API scaffold','DB schema','Test gen']},
|
||
{n:'Academy',rm:'con',d:'Training',p:'Auto-learn',sk:'#f0d0b0',hc:'#7c3aed',F:1,re:'🎓',act:['Gen training','Quiz create','Onboard flow','Certify']},
|
||
{n:'SkillsRAG',rm:'plat',d:'4414 skills',p:'Qdrant search',sk:'#f0d0b0',hc:'#0d9488',F:0,re:'🎯',act:['Search skills','Match task','Rank results','Auto-select']},
|
||
{n:'PromptsLib',rm:'plat',d:'55 prompts',p:'Searchable',sk:'#e8cca0',hc:'#0d9488',F:1,re:'✨',act:['Search prompt','Match context','Enhance','Cache']},
|
||
{n:'CodeWiki',rm:'plat',d:'203 files',p:'Auto-doc',sk:'#d8b080',hc:'#0d9488',F:0,re:'📖',act:['Index 203 files','Gen docs','Search code','Update wiki']},
|
||
{n:'AIBench',rm:'plat',d:'182 models',p:'Daily 5h',sk:'#f0d0b0',hc:'#0d9488',F:1,re:'🏆',act:['Bench 182 models','Compare speed','Score accuracy','Leaderboard']},
|
||
{n:'ModelScope',rm:'plat',d:'4 models',p:'Hub routed',sk:'#e8cca0',hc:'#0d9488',F:0,re:'🔬',act:['Route model','Test infer','Compare','Select best']},
|
||
{n:'OSSDiscover',rm:'plat',d:'OSS catalog',p:'Scan GitHub',sk:'#d8b080',hc:'#0d9488',F:1,re:'🔭',act:['Scan trending','Evaluate tool','Clone repo','Report']},
|
||
{n:'GHGrab',rm:'plat',d:'Bulk cloner',p:'/ghgrab.sh',sk:'#f0d0b0',hc:'#0d9488',F:0,re:'📥',act:['Clone repos','Bulk download','Archive','Catalog']},
|
||
{n:'AgentShield',rm:'plat',d:'Security audit',p:'Secrets scan',sk:'#e8cca0',hc:'#0d9488',F:1,re:'🔍',act:['Scan secrets','Audit code','Check leaks','Report clean']},
|
||
{n:'Playwright',rm:'qa',d:'Visual tests',p:'41 tests',sk:'#d8b080',hc:'#06b6d4',F:0,re:'🎭',act:['Run 41 tests','Screenshot','Compare baseline','Report']},
|
||
{n:'OpenWebUI',rm:'dock',d:'Chat :8281',p:'UP healthy',sk:'#f0d0b0',hc:'#0ea5e9',F:0,re:'💬',act:['Serve chat UI','Route models','Auth users','Log convos']},
|
||
{n:'Flowise',rm:'dock',d:'AI flows :3033',p:'UP',sk:'#e8cca0',hc:'#0ea5e9',F:1,re:'🌊',act:['Build flow','Chain LLMs','API endpoint','Test flow']},
|
||
{n:'Twenty',rm:'dock',d:'CRM :3000',p:'UP',sk:'#d8b080',hc:'#0ea5e9',F:0,re:'📇',act:['Track deals','Manage contacts','Pipeline CRM','Export data']},
|
||
{n:'n8n',rm:'dock',d:'15 WF :5678',p:'ACTIVE 15WF',sk:'#f0d0b0',hc:'#0ea5e9',F:1,re:'🔗',act:['Trigger webhook','API chain','Schedule task','Transform']},
|
||
{n:'Plausible',rm:'dock',d:'Analytics',p:'UP',sk:'#e8cca0',hc:'#0ea5e9',F:0,re:'📈',act:['Track visits','Page views','Dashboard','Export stats']},
|
||
{n:'UptimeKuma',rm:'dock',d:'Uptime :3001',p:'UP healthy',sk:'#d8b080',hc:'#0ea5e9',F:1,re:'📊',act:['Ping 25 URLs','Alert down','Status page','99.9% SLA']},
|
||
{n:'Mattermost',rm:'dock',d:'Team chat',p:'UP healthy',sk:'#f0d0b0',hc:'#0ea5e9',F:0,re:'💬',act:['DeerFlow hook','Alert channel','Team collab','Bot webhook']},
|
||
{n:'SearXNG',rm:'dock',d:'Meta search',p:'UP',sk:'#e8cca0',hc:'#0ea5e9',F:1,re:'🔍',act:['Search proxy','Multi-engine','Privacy','API query']},
|
||
{n:'Qdrant',rm:'dock',d:'Vector DB',p:'RAG 4935vec Paperclip',sk:'#d8b080',hc:'#0ea5e9',F:0,re:'🧮',act:['Store 4414 vecs','Search similar','RAG embed','Skill index']},
|
||
{n:'Vaultwarden',rm:'dock',d:'Passwords :8222',p:'UP S95',sk:'#f0d0b0',hc:'#0ea5e9',F:1,re:'🔐',act:['Store secrets','Auto-fill','Share vault','Audit log']},
|
||
{n:'Loki',rm:'dock',d:'Log aggreg',p:'RESTARTING ⚠️',sk:'#e8cca0',hc:'#0ea5e9',F:0,re:'⚠️',act:['Collect logs','Query Grafana','Alert pattern','BROKEN fix!']},
|
||
{n:'HolyClaude',rm:'intg',d:'Cloned /opt/',p:'Not wired',sk:'#d8d8d8',hc:'#a1a1aa',F:0,re:'⛪',act:['Évaluer usage','Wire if useful','Test prompts','Décider sort']},
|
||
{n:'LTX-Video',rm:'ai',d:'Video gen',p:'Needs GPU',sk:'#d8d8d8',hc:'#a1a1aa',F:1,re:'🎬',act:['Évaluer','Need GPU free','API ltx-video','Test gen']},
|
||
{n:'DeepAgent',rm:'ai',d:'Deep research',p:'API exists',sk:'#d8d8d8',hc:'#a1a1aa',F:0,re:'🕵️',act:['API /deepagent','Test research','Wire chatbot','Activate']},
|
||
{n:'Claude-Mem',rm:'intg',d:'Memory ext',p:'OSS WIRED',sk:'#d8d8d8',hc:'#a1a1aa',F:1,re:'🧠',act:['Évaluer','Wire memory','Test persist','Decide']},
|
||
{n:'ClawCode',rm:'intg',d:'78 Skills Sovereign',p:'WIRED :3900',sk:'#d0f0d0',hc:'#22c55e',F:1,gl:1,re:'🧠',act:['78 skills GPT','19 OhMyCC agents','18 ToolsFK','12 prompts','11 Paperclip roles','10 DeerFlow','8 Platform']},
|
||
{n:'Strix',rm:'sec',d:'Nuclei scan',p:'OSS WIRED',sk:'#d8d8d8',hc:'#a1a1aa',F:0,re:'🦉',act:['Nuclei templates','Scan vuln','Report CVE','Auto-patch']},
|
||
{n:'Prometheus',rm:'ops',d:'Metrics',p:'OSS WIRED',sk:'#d8d8d8',hc:'#a1a1aa',F:1,re:'📉',act:['Scrape metrics','Grafana dash','Alert rules','Retention']}
|
||
];
|
||
|
||
// Tasks are now per-agent in act[]
|
||
const HU=26,BASE_RH=60,ROW_ADD=50;
|
||
AG.forEach(function(a){a.si='sit';a.x=0;a.y=0;a.dx=0;a.dy=0;a.cx=0;a.cy=0;a.bob=Math.random()*6.28;a.wk=0;a.triggered=false;a.alert='';a.alertOn=false;a.wtmr=0;a.dir=1;a.bl=0;a.blt=80+Math.random()*200;a.tk='';a.tkt=0;a.wp=[];a.wpi=0;});
|
||
|
||
function rz(){
|
||
W=innerWidth;var totalNeeded=HU+10;for(var ii=0;ii<DP.length;ii++)totalNeeded+=(typeof deptH==='function'?deptH(ii):60)+3;H=Math.max(innerHeight,totalNeeded);
|
||
C.width=W*2;C.height=H*2;X.scale(2,2);C.style.height=H+'px';
|
||
lay();
|
||
}
|
||
function oX(){return 4;}
|
||
function oW(){return Math.floor(W*.35);}
|
||
function pX(){return Math.floor(W*.38);}
|
||
function pW(){return Math.floor(W*.42);}
|
||
function oRect(i){return {x:oX(),y:deptY(i),w:oW(),h:deptH(i)};}
|
||
function pRect(i){return {x:pX(),y:deptY(i),w:pW(),h:deptH(i)};}
|
||
|
||
function lay(){
|
||
AG.forEach(function(a){
|
||
var di=DP.findIndex(function(d){return d.id===a.rm;});
|
||
if(di<0)return;
|
||
var o=oRect(di);
|
||
var mates=AG.filter(function(b){return b.rm===a.rm;});
|
||
var mi=mates.indexOf(a);
|
||
var cols=Math.min(mates.length,7);
|
||
var row=Math.floor(mi/cols);
|
||
var col=mi%cols;
|
||
var spacing=Math.min(50,(o.w-20)/Math.max(cols,1));
|
||
var totalW=cols*spacing;
|
||
a.dx=o.x+(o.w-totalW)/2+col*spacing+spacing/2;
|
||
var rows2=Math.ceil(mates.length/cols);
|
||
var totalVH=rows2*48;
|
||
a.dy=o.y+20+(o.h-totalVH)/2+row*48;
|
||
if(a.si==='sit'){a.x=a.dx;a.y=a.dy;}
|
||
var dept=DP[di];
|
||
var pr=pRect(di);
|
||
var psi=Math.floor(Math.random()*dept.pp.length);
|
||
var sw=pr.w/dept.pp.length;
|
||
a.cx=pr.x+psi*sw+sw/2;
|
||
a.cy=pr.y+pr.h/2;
|
||
});
|
||
}
|
||
function deptH(i){var cnt=AG.filter(function(a){return a.rm===DP[i].id;}).length;var rows=Math.ceil(cnt/Math.max(Math.min(cnt,5),1));return BASE_RH+rows*ROW_ADD;}
|
||
function deptY(i){var y=HU+4;for(var j=0;j<i;j++)y+=deptH(j)+3;return y;}
|
||
addEventListener('resize',rz);rz();
|
||
|
||
// DRAW OFFICE (left)
|
||
function drawOff(i){
|
||
var r=oRect(i),d=DP[i],cl=d.cl,fl=d.fl;
|
||
X.fillStyle='#0001';X.beginPath();X.roundRect(r.x+3,r.y+3,r.w,r.h,8);X.fill();
|
||
var g=X.createLinearGradient(r.x,r.y,r.x,r.y+r.h);g.addColorStop(0,fl);g.addColorStop(1,fl+'bb');
|
||
X.fillStyle=g;X.beginPath();X.roundRect(r.x,r.y,r.w,r.h,8);X.fill();
|
||
X.strokeStyle=cl+'70';X.lineWidth=2;X.beginPath();X.roundRect(r.x,r.y,r.w,r.h,8);X.stroke();
|
||
X.fillStyle=cl;X.beginPath();X.roundRect(r.x,r.y,5,r.h,[8,0,0,8]);X.fill();
|
||
X.font='900 12px Nunito';X.fillStyle=cl;X.textAlign='left';X.fillText(d.l,r.x+6,r.y+14);
|
||
// Agent count badge
|
||
var cnt=AG.filter(function(a){return a.rm===d.id;}).length;
|
||
var acnt=AG.filter(function(a){return a.rm===d.id&&a.si!=='sit';}).length;
|
||
var bx=r.x+X.measureText(d.l).width+12;
|
||
X.fillStyle=acnt>0?'#22c55e30':'#64748b20';X.beginPath();X.roundRect(bx,r.y+4,22,14,7);X.fill();
|
||
X.font='800 8px JetBrains Mono';X.fillStyle=acnt>0?'#22c55e':'#64748b';X.fillText(cnt,bx+11,r.y+14);
|
||
// Status dot
|
||
X.fillStyle=acnt>0?'#22c55e':'#94a3b8';X.beginPath();X.arc(r.x+r.w-10,r.y+10,4,0,6.28);X.fill();
|
||
if(acnt>0){X.fillStyle='#22c55e40';X.beginPath();X.arc(r.x+r.w-10,r.y+10,7+Math.sin(fr*.1)*2,0,6.28);X.fill();}
|
||
// Door on right
|
||
var dy=r.y+r.h/2;
|
||
X.fillStyle='#fff';X.beginPath();X.roundRect(r.x+r.w-1,dy-6,5,12,[0,3,3,0]);X.fill();
|
||
X.strokeStyle=cl;X.lineWidth=1;X.beginPath();X.roundRect(r.x+r.w-1,dy-6,5,12,[0,3,3,0]);X.stroke();
|
||
X.fillStyle=cl;X.beginPath();X.arc(r.x+r.w+2.5,dy,1,0,6.28);X.fill();
|
||
}
|
||
|
||
// DRAW PIPELINE (right)
|
||
function drawPipe(i){
|
||
var r=pRect(i),d=DP[i],cl=d.cl;
|
||
X.fillStyle='#f4f6fc';X.beginPath();X.roundRect(r.x,r.y,r.w,r.h,8);X.fill();
|
||
X.strokeStyle=cl+'30';X.lineWidth=1;X.beginPath();X.roundRect(r.x,r.y,r.w,r.h,8);X.stroke();
|
||
var by=r.y+r.h/2;
|
||
// Pipeline background gradient
|
||
var pbg=X.createLinearGradient(r.x,r.y,r.x+r.w,r.y);
|
||
pbg.addColorStop(0,cl+'08');pbg.addColorStop(0.5,cl+'15');pbg.addColorStop(1,cl+'08');
|
||
X.fillStyle=pbg;X.fillRect(r.x+3,r.y+3,r.w-6,r.h-6);
|
||
X.fillStyle=cl+'12';X.beginPath();X.roundRect(r.x+3,by-4,r.w-6,8,3);X.fill();
|
||
// Animated flow dots on track
|
||
var flowX=(fr*0.5+i*100)%(r.w-20);
|
||
X.fillStyle=cl+'40';X.beginPath();X.arc(r.x+10+flowX,by,3,0,6.28);X.fill();
|
||
X.fillStyle=cl+'25';X.beginPath();X.arc(r.x+10+(flowX+15)%(r.w-20),by,2,0,6.28);X.fill();
|
||
var sw=r.w/d.pp.length;
|
||
d.pp.forEach(function(s,j){
|
||
var sx=r.x+j*sw+sw/2;
|
||
X.fillStyle='#fff';X.beginPath();X.arc(sx,by,11,0,6.28);X.fill();
|
||
X.fillStyle=cl+'25';X.beginPath();X.arc(sx,by,11,0,6.28);X.fill();
|
||
X.strokeStyle=cl;X.lineWidth=1.5;X.beginPath();X.arc(sx,by,11,0,6.28);X.stroke();
|
||
X.fillStyle=cl;X.beginPath();X.arc(sx,by,4,0,6.28);X.fill();
|
||
X.font='800 7px Nunito';X.fillStyle=cl;X.textAlign='center';X.fillText(s,sx,by+18);
|
||
// Stage number inside circle
|
||
X.font='bold 8px JetBrains Mono';X.fillStyle='#fff';X.textBaseline='middle';X.fillText(j+1,sx,by);X.textBaseline='alphabetic';
|
||
if(j<d.pp.length-1){
|
||
// Animated arrow between stages
|
||
var ax=sx+sw/2;
|
||
X.fillStyle=cl+'50';X.beginPath();X.moveTo(ax-4,by-3);X.lineTo(ax+4,by);X.lineTo(ax-4,by+3);X.closePath();X.fill();
|
||
}
|
||
});
|
||
X.font='800 8px Nunito';X.fillStyle=cl+'90';X.textAlign='right';X.fillText('PIPELINE',r.x+r.w-4,r.y+9);
|
||
}
|
||
|
||
// WALKWAY between office and pipeline
|
||
function outX(){return pX()+pW()+8;}
|
||
function outW(){return Math.floor(W*.12);}
|
||
function outRect(i){return {x:outX(),y:deptY(i),w:outW(),h:deptH(i)};}
|
||
|
||
function drawOut(i){
|
||
var r=outRect(i),d=DP[i],cl=d.cl;
|
||
var o=OUT[d.id];if(!o)return;
|
||
// Background
|
||
var g=X.createLinearGradient(r.x,r.y,r.x+r.w,r.y+r.h);
|
||
g.addColorStop(0,'#f8fafc');g.addColorStop(1,'#f0f4f8');
|
||
X.fillStyle=g;X.beginPath();X.roundRect(r.x,r.y,r.w,r.h,8);X.fill();
|
||
X.strokeStyle=cl+'40';X.lineWidth=1;X.beginPath();X.roundRect(r.x,r.y,r.w,r.h,8);X.stroke();
|
||
// Right color bar
|
||
X.fillStyle=cl;X.beginPath();X.roundRect(r.x+r.w-4,r.y,4,r.h,[0,8,8,0]);X.fill();
|
||
// Header
|
||
X.font='800 7px Nunito';X.fillStyle=cl;X.textAlign='center';
|
||
X.fillText('OUTPUT',r.x+r.w/2,r.y+10);
|
||
// Date removed (was confusing 2/4 = 2 avril)
|
||
// Icon
|
||
X.font='14px sans-serif';X.fillText(o.icon,r.x+r.w/2,r.y+r.h/2-5);
|
||
// Metric (big)
|
||
X.font='900 10px JetBrains Mono';
|
||
var mColor=o.metric.includes('TODO')||o.metric.includes('-45')||o.metric.includes('wait')?'#ef4444':
|
||
o.metric.includes('OK')||o.metric.includes('99')||o.metric.includes('+')?'#22c55e':'#3b82f6';
|
||
X.fillStyle=mColor;X.fillText(o.metric,r.x+r.w/2,r.y+r.h/2+10);
|
||
// Input line
|
||
// Capacity bar
|
||
var capPct=70+Math.sin(i*.7)*20;// simulated capacity usage
|
||
X.fillStyle='#e2e8f0';X.beginPath();X.roundRect(r.x+6,r.y+r.h-28,r.w-12,5,2);X.fill();
|
||
var barColor=capPct>80?'#ef4444':capPct>50?'#f59e0b':'#22c55e';
|
||
X.fillStyle=barColor;X.beginPath();X.roundRect(r.x+6,r.y+r.h-28,Math.min(capPct,100)/100*(r.w-12),5,2);X.fill();
|
||
X.font='600 4.5px JetBrains Mono';X.fillStyle=barColor;X.textAlign='right';
|
||
X.fillText(Math.round(capPct)+'%',r.x+r.w-6,r.y+r.h-30);X.textAlign='center';
|
||
// Input/Output
|
||
X.font='600 5px Nunito';X.fillStyle='#64748b';
|
||
X.fillText(o.input,r.x+r.w/2,r.y+r.h-18);
|
||
X.fillStyle='#2a2a4a';X.font='700 5px Nunito';
|
||
X.fillText(o.output,r.x+r.w/2,r.y+r.h-10);
|
||
}
|
||
|
||
function drawWalk(){
|
||
DP.forEach(function(d,i){
|
||
var o=oRect(i),p=pRect(i),ym=o.y+o.h/2;
|
||
// Walkway with animated dashes
|
||
var wx1=o.x+o.w+2,wx2=p.x-4,wy=ym;
|
||
X.fillStyle='#d8e4f0';X.beginPath();X.roundRect(wx1,wy-4,wx2-wx1,8,3);X.fill();
|
||
X.strokeStyle=d.cl+'60';X.lineWidth=1;X.setLineDash([6,4]);X.lineDashOffset=-fr*0.3;
|
||
X.beginPath();X.moveTo(wx1+4,wy);X.lineTo(wx2-4,wy);X.stroke();X.setLineDash([]);
|
||
// Arrow
|
||
X.fillStyle=d.cl+'80';X.beginPath();X.moveTo(wx2-8,wy-4);X.lineTo(wx2,wy);X.lineTo(wx2-8,wy+4);X.closePath();X.fill();
|
||
// Arrow from pipeline to output
|
||
var or2=outRect(i);var ox1=p.x+p.w+2,ox2=or2.x-2;
|
||
X.fillStyle='#d8e4f0';X.beginPath();X.roundRect(ox1,wy-3,ox2-ox1,6,2);X.fill();
|
||
X.fillStyle=d.cl+'60';X.beginPath();X.moveTo(ox2-6,wy-3);X.lineTo(ox2,wy);X.lineTo(ox2-6,wy+3);X.closePath();X.fill();
|
||
X.strokeStyle='#e0d050';X.lineWidth=.5;X.setLineDash([3,4]);
|
||
X.beginPath();X.moveTo(o.x+o.w+8,ym);X.lineTo(p.x-4,ym);X.stroke();X.setLineDash([]);
|
||
X.fillStyle='#b0c0d860';X.font='7px sans-serif';X.textAlign='center';
|
||
X.fillText('→',(o.x+o.w+p.x)/2,ym+2);
|
||
});
|
||
}
|
||
|
||
// CHARACTER (emoji-based HD)
|
||
function drawC(a){
|
||
var isH=a===hov,sit=a.si==='sit',sc=isH?1.2:1;
|
||
var bob=sit?0:Math.sin(a.bob)*1.5;
|
||
var di=DP.findIndex(function(d){return d.id===a.rm;});
|
||
var cl=di>=0?DP[di].cl:'#888';
|
||
X.save();X.translate(a.x,a.y+bob);X.scale(sc,sc);
|
||
if(isH){X.shadowColor=cl;X.shadowBlur=12;}
|
||
// Shadow
|
||
X.fillStyle='#00000018';X.beginPath();X.ellipse(0,sit?5:10,7,2.5,0,0,6.28);X.fill();
|
||
// Body (colored pill)
|
||
var bg=X.createLinearGradient(-5,-4,5,4);bg.addColorStop(0,cl);bg.addColorStop(1,cl+'99');
|
||
X.fillStyle=bg;X.beginPath();X.roundRect(-6,-5,12,10,[5,5,2,2]);X.fill();
|
||
X.fillStyle='#ffffff20';X.beginPath();X.roundRect(-4,-4,4,7,[2,0,0,2]);X.fill();
|
||
// Legs (walking)
|
||
if(!sit){
|
||
var lsw=Math.sin(a.wk)*3;
|
||
X.fillStyle=cl+'bb';
|
||
X.save();X.translate(-2.5,4);X.rotate(lsw*.04);X.beginPath();X.roundRect(-1.5,0,3,7,1.5);X.fill();X.restore();
|
||
X.save();X.translate(2.5,4);X.rotate(-lsw*.04);X.beginPath();X.roundRect(-1.5,0,3,7,1.5);X.fill();X.restore();
|
||
X.fillStyle='#fff';
|
||
X.beginPath();X.ellipse(-2.5+lsw*.1,11,2.5,1.2,0,0,6.28);X.fill();
|
||
X.beginPath();X.ellipse(2.5-lsw*.1,11,2.5,1.2,0,0,6.28);X.fill();
|
||
}
|
||
// Arms
|
||
X.fillStyle=a.sk;
|
||
var asw=sit?0:Math.sin(a.wk+.5)*.15;
|
||
X.save();X.translate(-7,-1);X.rotate(sit?.2:asw);X.beginPath();X.roundRect(-1.5,0,3,sit?4:7,1.5);X.fill();X.restore();
|
||
X.save();X.translate(7,-1);X.rotate(sit?-.2:-asw);X.beginPath();X.roundRect(-1.5,0,3,sit?4:7,1.5);X.fill();X.restore();
|
||
// HEAD — use emoji face for HD quality
|
||
X.font='22px sans-serif';X.textAlign='center';X.textBaseline='middle';
|
||
X.fillText(a.re||'👤',0,-14);
|
||
// Name
|
||
X.textBaseline='alphabetic';
|
||
X.font=(isH?'800':'600')+' '+(isH?7:5.5)+'px Nunito';
|
||
X.fillStyle=isH?'#2a2a4a':a.si!=='sit'?cl:'#6a7a98';
|
||
X.textAlign='center';X.fillText(a.n,0,sit?14:20);
|
||
// Active dot
|
||
if(a.si!=='sit'){
|
||
X.fillStyle=cl+'40';X.beginPath();X.arc(0,-28,5+Math.sin(fr*.15)*2,0,6.28);X.fill();
|
||
X.fillStyle=cl;X.beginPath();X.arc(0,-28,3,0,6.28);X.fill();
|
||
}
|
||
// Task bubble
|
||
if(a.tkt>0){
|
||
X.globalAlpha=Math.min(a.tkt/6,1);
|
||
var tw2=Math.min(a.tk.length*5+16,180);
|
||
var by2=a.si==='sit'?20:26;
|
||
// Speech bubble BELOW agent
|
||
X.fillStyle='#ffffffee';X.shadowColor='#00000020';X.shadowBlur=6;
|
||
X.strokeStyle='#3b82f680';X.lineWidth=1;
|
||
X.beginPath();X.roundRect(-tw2/2,by2,tw2,34,8);X.fill();X.stroke();X.shadowBlur=0;
|
||
// Triangle pointing UP to agent
|
||
X.fillStyle='#ffffffee';X.beginPath();X.moveTo(-4,by2);X.lineTo(4,by2);X.lineTo(0,by2-5);X.closePath();X.fill();
|
||
// Action text
|
||
// Line 1: action
|
||
X.font='700 7px Nunito';X.fillStyle='#1e40af';X.textAlign='center';X.textBaseline='middle';
|
||
X.fillText(a.tk,0,by2+7);
|
||
// Line 2: freq
|
||
var meta=AMETA[a.n]||{};
|
||
var fr2=meta.fq||FREQ_DEF[a.rm]||'';
|
||
X.font='600 5.5px Nunito';X.fillStyle='#94a3b8';
|
||
X.fillText('⏱ '+fr2,0,by2+16);
|
||
// Line 3: input
|
||
if(meta.inp){
|
||
X.font='600 5px Nunito';X.fillStyle='#64748b';
|
||
X.fillText('📥 '+meta.inp,0,by2+24);
|
||
}
|
||
X.textBaseline='alphabetic';X.globalAlpha=1;
|
||
}
|
||
// ALERT: compact red badge
|
||
if(a.alertOn&&a.alert){
|
||
X.shadowColor='#ef4444';X.shadowBlur=6+Math.sin(fr*.15)*3;
|
||
X.fillStyle='#ef444420';X.beginPath();X.arc(0,-14,14,0,6.28);X.fill();
|
||
X.shadowBlur=0;
|
||
X.fillStyle='#ef4444';X.beginPath();X.arc(12,-22,6,0,6.28);X.fill();
|
||
X.font='bold 8px sans-serif';X.fillStyle='#fff';X.textAlign='center';X.textBaseline='middle';
|
||
X.fillText('!',12,-22);X.textBaseline='alphabetic';
|
||
var atxt=a.alert.length>16?a.alert.substring(0,16):a.alert;
|
||
var aw3=Math.min(atxt.length*5+14,110);
|
||
X.fillStyle='#fef2f2ee';X.strokeStyle='#fca5a5';X.lineWidth=1;
|
||
X.beginPath();X.roundRect(-aw3/2,-42,aw3,15,4);X.fill();X.stroke();
|
||
X.font='600 7px JetBrains Mono';X.fillStyle='#dc2626';X.textAlign='center';X.textBaseline='middle';
|
||
X.fillText(atxt,0,-34.5);X.textBaseline='alphabetic';
|
||
}
|
||
X.restore();
|
||
}
|
||
// PATH
|
||
function mkP(a){
|
||
var di=DP.findIndex(function(d){return d.id===a.rm;});
|
||
if(di<0)return[];
|
||
var o=oRect(di),ym=o.y+o.h/2;
|
||
return[{x:o.x+o.w+6,y:ym},{x:a.cx,y:a.cy}];
|
||
}
|
||
function mkR(a){
|
||
var di=DP.findIndex(function(d){return d.id===a.rm;});
|
||
if(di<0)return[];
|
||
var o=oRect(di),ym=o.y+o.h/2;
|
||
return[{x:o.x+o.w+6,y:ym},{x:a.dx,y:a.dy}];
|
||
}
|
||
|
||
// UPDATE
|
||
function upd(dt){fr++;var ac=0;
|
||
AG.forEach(function(a){
|
||
a.bob+=dt*(a.si==='sit'?1:4);a.blt-=dt*60;
|
||
if(a.blt<=0){a.bl=4;a.blt=80+Math.random()*200;}
|
||
if(a.bl>0)a.bl-=dt*60;if(a.tkt>0)a.tkt-=dt*3;
|
||
if(a.si==='sit'){
|
||
if(a.triggered){a.triggered=false;a.alert='';a.alertOn=false;a.wp=mkP(a);a.wpi=0;a.si='go';a.wk=0;a.tkt=60;}
|
||
}else if(a.si==='go'){a.wk+=dt*6;ac++;
|
||
if(a.wpi<a.wp.length){var w=a.wp[a.wpi],dx=w.x-a.x,dy=w.y-a.y,d=Math.sqrt(dx*dx+dy*dy);
|
||
if(d>1.5){a.x+=dx/d*55*dt;a.y+=dy/d*55*dt;a.dir=dx>0?1:-1;}else a.wpi++;}
|
||
else{a.si='work';a.wtmr=80;}
|
||
}else if(a.si==='work'){a.wk+=dt*2;ac++;a.wtmr-=dt*60;
|
||
if(a.wtmr<=0){a.wp=mkR(a);a.wpi=0;a.si='back';tc++;}
|
||
}else if(a.si==='back'){a.wk+=dt*6;ac++;
|
||
if(a.wpi<a.wp.length){var w2=a.wp[a.wpi],dx2=w2.x-a.x,dy2=w2.y-a.y,d2=Math.sqrt(dx2*dx2+dy2*dy2);
|
||
if(d2>1.5){a.x+=dx2/d2*55*dt;a.y+=dy2/d2*55*dt;a.dir=dx2>0?1:-1;}else a.wpi++;}
|
||
else{a.si='sit';a.x=a.dx;a.y=a.dy;a.dir=1;}
|
||
}
|
||
});
|
||
// Legend
|
||
if(fr===1){
|
||
X.fillStyle='#ffffff90';X.beginPath();X.roundRect(W-320,2,310,22,4);X.fill();
|
||
X.font='600 7px Nunito';X.textAlign='left';
|
||
var lx=W-315;
|
||
[['🟢','Actif','#22c55e'],['🔴','Alerte','#ef4444'],['🟠','To Wire','#f97316'],['🟡','Integrate','#84cc16'],['🐳','Docker','#0ea5e9'],['💤','Dormant','#a1a1aa'],['💀','Dead','#64748b']].forEach(function(l){
|
||
X.fillStyle=l[2];X.fillText(l[0]+' '+l[1],lx,16);lx+=44;
|
||
});
|
||
}
|
||
document.getElementById('hud-time').textContent=new Date().toLocaleTimeString();
|
||
document.getElementById('st').textContent='\u{1F465}'+AG.length+'/150'+' \u{1F7E2}'+ac+' \u{1F4E6}'+tc+' \u{1F534}LIVE';
|
||
}
|
||
function alertAgent(name,msg){
|
||
var a=AG.find(function(x){return x.n===name;});
|
||
if(a){a.alert=msg;a.alertOn=true;}
|
||
}
|
||
function trig(name,action){var a=AG.find(function(x){return x.n===name;});if(a&&a.si==='sit'){a.triggered=true;a.tk=action;}return !!a;}
|
||
function trigD(dept,action){var aa=AG.filter(function(x){return x.rm===dept&&x.si==='sit';});if(aa.length){var a=aa[~~(Math.random()*aa.length)];a.triggered=true;a.tk=action;}}
|
||
var lastRT=0;
|
||
function realTime(t){
|
||
if(t-lastRT<10000)return;lastRT=t;
|
||
var h=new Date().getHours(),m=new Date().getMinutes();
|
||
// Realtime monitor check
|
||
if(m%5===0){trig('EthicaCron','Drip DZ+MA+TN');trigD('pha','Ethica drip');}
|
||
if(h%4===0&&m<2)trig('B2BCron','B2B scrape');
|
||
if((h===6||h===18)&&m<2){trig('NonRegCron','153 tests');trig('QA','NonReg run');}
|
||
if(h===4&&m<2)trig('BackupCron','PG backup');
|
||
if(m%3===0)trig('Watchdog','Check */3min');
|
||
if(h===7&&m<2){trig('CEO','Daily brief');trig('TaskMgr','Status report');}
|
||
if(h>=9&&h<=18){
|
||
if(Math.random()<0.25)trigD('dev','Commit push');
|
||
if(Math.random()<0.12)trigD('con','Client call');
|
||
if(Math.random()<0.08)trigD('sec','Security scan');
|
||
if(Math.random()<0.15)trigD('ops','Monitor check');
|
||
if(Math.random()<0.1)trigD('sal','New lead');
|
||
}
|
||
if(Math.random()<0.12)trigD('dock','Container check');
|
||
if(Math.random()<0.15)trigD('ai','AI request');
|
||
// Static alerts for known issues
|
||
alertAgent('S88 GPU','💀 GPU MORT — annuler Hetzner -45€/mois');
|
||
alertAgent('S89','⚰️ SERVEUR DOWN — port 49222 inaccessible');
|
||
alertAgent('ECS PMTA','❓ STATUS INCONNU — à vérifier');
|
||
alertAgent('Loki','⚠️ RESTARTING — container en boucle');
|
||
// Check Stripe/WhatsApp/OVH SMS missing creds
|
||
alertAgent('Stripe','🔴 SK live MANQUANTE — dashboard.stripe.com');
|
||
alertAgent('WhatsApp','🔴 TOKEN MANQUANT');
|
||
alertAgent('OVH SMS','🔴 CREDS MANQUANTES');
|
||
alertAgent('Azure AD','🔴 3 tenants EXPIRÉS — re-register');
|
||
alertAgent('Gemini','🔴 API DISABLED — activer aistudio.google.com');
|
||
}
|
||
function hit(){
|
||
hov=null;
|
||
AG.forEach(function(a){if(Math.abs(mx-a.x)<8&&Math.abs(my-a.y)<14)hov=a;});
|
||
if(hov){
|
||
TT.style.display='block';
|
||
TT.style.left=Math.min(mx+12,W-220)+'px';
|
||
TT.style.top=Math.max(my-120,10)+'px';
|
||
var dd=DP.find(function(d){return d.id===hov.rm;});
|
||
TT.style.borderColor=dd?dd.cl:'#888';
|
||
TT.querySelector('b').textContent=hov.n+(hov.F?' 👩':' 👨');
|
||
TT.querySelector('i').textContent=dd?dd.l:'';
|
||
TT.querySelector('i').style.color=dd?dd.cl:'';
|
||
TT.querySelector('.d').textContent=hov.d;
|
||
TT.querySelector('.p').textContent='→ '+hov.p;
|
||
var sm={sit:'💤 Bureau',go:'🚶→ Pipeline',work:'⚙️ Produit',back:'✅ Retour'};
|
||
TT.querySelector('.s').textContent=sm[hov.si]||'';
|
||
TT.querySelector('.s').style.color=hov.si==='sit'?'#94a3b8':'#16a34a';
|
||
} else {TT.style.display='none';}
|
||
}
|
||
|
||
var lt=0;
|
||
function loop(t){
|
||
var dt=Math.min((t-lt)/1000,.04);lt=t;
|
||
X.fillStyle='#e4ecf6';X.fillRect(0,0,W,H);realTime(t);
|
||
drawWalk();
|
||
for(var i=0;i<DP.length;i++){drawOff(i);drawPipe(i);drawOut(i);}
|
||
upd(dt);
|
||
var sorted=AG.slice().sort(function(a,b){return a.y-b.y;});
|
||
sorted.forEach(function(a){drawC(a);});
|
||
hit();
|
||
requestAnimationFrame(loop);
|
||
}
|
||
|
||
|
||
C.addEventListener('click',function(e){
|
||
var cx2=e.clientX,cy2=e.clientY;
|
||
AG.forEach(function(a){
|
||
if(Math.abs(cx2-a.x)<12&&Math.abs(cy2-a.y)<18&&a.alertOn){
|
||
a.alertOn=false;a.alert='';
|
||
}
|
||
});
|
||
});
|
||
C.addEventListener('click',function(ev){
|
||
var ex=ev.clientX,ey=ev.clientY+window.scrollY;
|
||
var clicked=null;
|
||
AG.forEach(function(a){if(Math.abs(ex-a.x)<15&&Math.abs(ey-a.y)<25)clicked=a;});
|
||
if(clicked){
|
||
if(clicked.alertOn){clicked.alertOn=false;clicked.alert='';return;}
|
||
var dd2=DP.find(function(d){return d.id===clicked.rm;})||{};
|
||
var meta2=AMETA[clicked.n]||{};
|
||
var out3=OUT[clicked.rm]||{};
|
||
var sm2={sit:'En attente',go:'Vers pipeline',work:'En action',back:'Retour bureau'};
|
||
var oldP=document.getElementById('agent-panel');if(oldP)oldP.remove();
|
||
var panel=document.createElement('div');
|
||
panel.id='agent-panel';
|
||
panel.style.cssText='position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:#fff;border-radius:16px;padding:20px;min-width:340px;max-width:440px;box-shadow:0 12px 40px #0004;z-index:200;font-family:Nunito,sans-serif';
|
||
var sC=clicked.si!=='sit'?'#16a34a':'#64748b';
|
||
var h3='<div style="display:flex;justify-content:space-between;align-items:center">';
|
||
h3+='<div style="font-size:1.4rem;font-weight:900;color:'+(dd2.cl||'#333')+'">'+clicked.re+' '+clicked.n+'<\/div>';
|
||
h3+='<div style="cursor:pointer;font-size:1.5rem;color:#94a3b8;padding:4px 8px" onclick="this.parentElement.parentElement.remove()">X<\/div><\/div>';
|
||
h3+='<div style="font-size:.7rem;color:#64748b;text-transform:uppercase;letter-spacing:1.5px;margin:4px 0 10px;padding-bottom:8px;border-bottom:2px solid '+(dd2.cl||'#e2e8f0')+'">'+(dd2.l||'')+'<\/div>';
|
||
h3+='<div style="display:inline-block;padding:4px 12px;border-radius:6px;font-size:.72rem;font-weight:800;background:#f8fafc;color:'+sC+'">'+(sm2[clicked.si]||clicked.si)+'<\/div>';
|
||
h3+='<div style="font-size:.85rem;color:#1e293b;font-weight:700;margin:8px 0 4px">'+clicked.d+'<\/div>';
|
||
h3+='<div style="font-size:.78rem;color:#475569;margin-bottom:10px">'+clicked.p+'<\/div>';
|
||
h3+='<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:10px">';
|
||
h3+='<div style="background:#f0f9ff;border-radius:8px;padding:8px;text-align:center"><div style="font-size:.55rem;color:#94a3b8;text-transform:uppercase">Frequence<\/div><div style="font-size:.82rem;font-weight:800;color:#1e40af">'+(meta2.fq||'N/A')+'<\/div><\/div>';
|
||
h3+='<div style="background:#f0fdf4;border-radius:8px;padding:8px;text-align:center"><div style="font-size:.55rem;color:#94a3b8;text-transform:uppercase">Output<\/div><div style="font-size:.82rem;font-weight:800;color:#16a34a">'+(out3.metric||'~')+'<\/div><\/div>';
|
||
h3+='<\/div>';
|
||
if(meta2.inp)h3+='<div style="font-size:.72rem;color:#3b82f6;margin:3px 0">\u{1F4E5} '+meta2.inp+'<\/div>';
|
||
if(out3.output)h3+='<div style="font-size:.72rem;color:#16a34a;margin:3px 0">\u{1F4E4} '+out3.output+'<\/div>';
|
||
if(out3.kpi)h3+='<div style="font-size:.72rem;color:#64748b;margin:3px 0">\u{1F4CA} '+out3.kpi+'<\/div>';
|
||
h3+='<div style="margin-top:10px;padding-top:8px;border-top:1px solid #f1f5f9"><div style="font-size:.55rem;color:#94a3b8;text-transform:uppercase;margin-bottom:4px">Actions<\/div>';
|
||
(clicked.act||[]).forEach(function(ac){h3+='<span style="display:inline-block;background:#eff6ff;color:#2563eb;padding:2px 8px;border-radius:4px;font-size:.65rem;margin:2px;font-weight:600">'+ac+'<\/span>';});
|
||
h3+='<\/div>';
|
||
panel.innerHTML=h3;
|
||
document.body.appendChild(panel);
|
||
return;
|
||
}
|
||
// OUTPUT PANEL CLICK → modal with deliverables + download
|
||
for(var oi=0;oi<DP.length;oi++){
|
||
var or3=outRect(oi);
|
||
if(ex>=or3.x&&ex<=or3.x+or3.w&&ey>=or3.y&&ey<=or3.y+or3.h){
|
||
var d3=DP[oi],o3=OUT[d3.id];if(!o3)break;
|
||
var ags=AG.filter(function(a){return a.rm===d3.id;});
|
||
var oldP2=document.getElementById('agent-panel');if(oldP2)oldP2.remove();
|
||
var p2=document.createElement('div');p2.id='agent-panel';
|
||
p2.style.cssText='position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:#fff;border-radius:16px;padding:24px;min-width:420px;max-width:520px;max-height:80vh;overflow-y:auto;box-shadow:0 12px 40px #0004;z-index:200;font-family:Nunito,sans-serif';
|
||
var h4='<div style="display:flex;justify-content:space-between"><div style="font-size:1.3rem;font-weight:900;color:'+(d3.cl||'#333')+'">'+d3.l+' \u2014 Output<\/div>';
|
||
h4+='<div style="cursor:pointer;font-size:1.5rem;color:#94a3b8;padding:2px 8px" onclick="this.parentElement.parentElement.remove()">X<\/div><\/div>';
|
||
h4+='<div style="font-size:2.2rem;font-weight:900;color:#16a34a;margin:10px 0">'+(o3.metric||'')+'<\/div>';
|
||
h4+='<div style="font-size:.82rem;color:#475569;margin-bottom:12px">'+(o3.input||'')+' \u2192 '+(o3.output||'')+'<\/div>';
|
||
h4+='<div style="font-size:.72rem;color:#64748b;margin-bottom:8px">\u{1F4CA} KPI: '+(o3.kpi||'N/A')+'<\/div>';
|
||
if(o3.deliverables&&o3.deliverables.length){
|
||
h4+='<div style="background:#f0fdf4;border:1px solid #bbf7d0;border-radius:10px;padding:12px;margin:12px 0">';
|
||
h4+='<div style="font-weight:800;font-size:.72rem;color:#16a34a;margin-bottom:8px">\u{1F4E6} LIVRABLES REELS<\/div>';
|
||
o3.deliverables.forEach(function(dl){
|
||
h4+='<div style="font-size:.72rem;color:#15803d;padding:3px 0;display:flex;align-items:center;gap:6px">\u2705 '+dl+'<\/div>';
|
||
});
|
||
h4+='<\/div>';
|
||
}
|
||
h4+='<div style="font-size:.68rem;color:#94a3b8;margin:8px 0">'+ags.length+' agents dans ce departement<\/div>';
|
||
h4+='<table style="width:100%;border-collapse:collapse;font-size:.68rem;margin:8px 0">';
|
||
h4+='<tr style="background:#f8fafc"><th style="padding:4px 8px;text-align:left;border-bottom:1px solid #e2e8f0">Agent<\/th><th style="padding:4px;border-bottom:1px solid #e2e8f0">Role<\/th><th style="padding:4px;border-bottom:1px solid #e2e8f0">Freq<\/th><\/tr>';
|
||
ags.forEach(function(a){var m=AMETA[a.n]||{};h4+='<tr><td style="padding:3px 8px;font-weight:700">'+a.re+' '+a.n+'<\/td><td style="padding:3px 4px">'+a.d+'<\/td><td style="padding:3px 4px;font-family:monospace;font-size:.6rem">'+(m.fq||'-')+'<\/td><\/tr>';});
|
||
h4+='<\/table>';
|
||
// Download CSV button
|
||
h4+='<div style="display:flex;gap:8px;margin-top:12px">';
|
||
h4+='<button style="background:#2563eb;color:#fff;border:none;padding:8px 16px;border-radius:8px;cursor:pointer;font-weight:700;font-size:.75rem" onclick="(function(){var csv=\'Agent,Role,Freq\\n\';document.querySelectorAll(\'#agent-panel table tr\').forEach(function(r,i){if(i===0)return;var c=r.querySelectorAll(\'td\');csv+=c[0].textContent+\',\'+c[1].textContent+\',\'+c[2].textContent+\'\\n\'});csv+=\'\\nMetric,'+(o3.metric||'')+'\\n\';csv+=\'Output,'+(o3.output||'')+'\\n\';';
|
||
if(o3.deliverables)o3.deliverables.forEach(function(dl){h4+='csv+=\'Livrable,'+dl.replace(/'/g,'')+'\\n\';';});
|
||
h4+='var b=new Blob([csv],{type:\'text/csv\'});var u=URL.createObjectURL(b);var l=document.createElement(\'a\');l.href=u;l.download=\'weval-'+d3.id+'-output.csv\';l.click();})()">\u{1F4E5} CSV<\/button>';
|
||
h4+='<button style="background:#64748b;color:#fff;border:none;padding:8px 16px;border-radius:8px;cursor:pointer;font-weight:700;font-size:.75rem" onclick="this.closest(\'[id]\').remove()">Fermer<\/button>';
|
||
h4+='<\/div>';
|
||
p2.innerHTML=h4;document.body.appendChild(p2);
|
||
return;
|
||
}
|
||
}
|
||
AG.forEach(function(a){if(Math.abs(ex-a.x)<15&&Math.abs(ey-a.y)<25&&a.alertOn){a.alertOn=false;a.alert='';}});
|
||
});
|
||
C.addEventListener('mousemove',function(e){mx=e.clientX;my=e.clientY+window.scrollY;C.style.cursor=hov?'pointer':'default';});
|
||
C.addEventListener('mouseleave',function(){mx=my=-1;});
|
||
requestAnimationFrame(loop);
|
||
</script><!-- CARTO_REMOVED -->
|
||
|
||
<!-- === 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 === -->
|
||
|
||
</body></html>
|