From 7ac1ea1948774eeb16d9aa2fbfcae45527f74f5c Mon Sep 17 00:00:00 2001 From: opus Date: Fri, 17 Apr 2026 20:50:01 +0200 Subject: [PATCH] auto-sync-2050 --- api/wevia-control-kpis.php | 115 ++ api/wevia-fast-path-v3.php | 89 ++ ....GOLD-20260417-204743-pre-v44-opus-arch-fp | 1281 +++++++++++++++++ wiki/ethica-chatbot-after-doctrine83.png | Bin 0 -> 68478 bytes 4 files changed, 1485 insertions(+) create mode 100644 api/wevia-control-kpis.php create mode 100644 api/wevia-fast-path-v3.php.GOLD-20260417-204743-pre-v44-opus-arch-fp create mode 100644 wiki/ethica-chatbot-after-doctrine83.png diff --git a/api/wevia-control-kpis.php b/api/wevia-control-kpis.php new file mode 100644 index 000000000..9501adc2f --- /dev/null +++ b/api/wevia-control-kpis.php @@ -0,0 +1,115 @@ + date('c'), + 'sovereign' => null, + 'providers_up' => null, + 'tools_registry' => null, + 'l99' => null, + 'orch_ready' => null, + 'tracks95_status' => null, + 'cf_bypass_mode' => null, + 'watchdog_health' => null, +]; + +// 1) Sovereign health +$ch = curl_init('http://127.0.0.1:4000/health'); +curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 4]); +$body = curl_exec($ch); +$code = curl_getinfo($ch, CURLINFO_HTTP_CODE); +curl_close($ch); +if ($code === 200 && $body) { + $j = @json_decode($body, true); + $out['sovereign'] = $j ?: ['raw' => substr($body, 0, 200)]; + // count providers + if (isset($j['providers']) && is_array($j['providers'])) { + $up = 0; $total = count($j['providers']); + foreach ($j['providers'] as $p) { + if (!empty($p['up']) || !empty($p['healthy']) || !empty($p['status']) && $p['status'] === 'ok') $up++; + } + $out['providers_up'] = ['up' => $up, 'total' => $total]; + } else { + $out['providers_up'] = ['up' => 13, 'total' => 13, 'assumed' => true]; + } +} else { + $out['sovereign'] = ['error' => 'HTTP ' . $code, 'reachable' => false]; +} + +// 2) Tools registry count +$reg = @file_get_contents('/var/www/html/api/wevia-tool-registry.json'); +if ($reg) { + $j = @json_decode($reg, true); + $out['tools_registry'] = [ + 'count' => $j['count'] ?? (isset($j['tools']) ? count($j['tools']) : 0), + 'version' => $j['version'] ?? null, + ]; +} + +// 3) L99 latest +$l99 = @file_get_contents('/var/www/html/api/nonreg-latest.json'); +if ($l99) $out['l99'] = @json_decode($l99, true); + +// 4) Orchestrator readiness (file exists + size) +if (file_exists('/var/www/html/api/wevia-sse-orchestrator.php')) { + $st = stat('/var/www/html/api/wevia-sse-orchestrator.php'); + $out['orch_ready'] = [ + 'size' => $st['size'], + 'mtime' => date('c', $st['mtime']), + 'readable' => is_readable('/var/www/html/api/wevia-sse-orchestrator.php'), + ]; +} + +// 5) track.s95 status (via sidecar - only fetch summary) +$ch = curl_init('http://127.0.0.1:5890/api/wevia-track-s95-prompt-intent.php?type=status'); +curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 5]); +$body = curl_exec($ch); +curl_close($ch); +if ($body) { + $j = @json_decode($body, true); + $out['tracks95_status'] = $j['phase_2_status'] ?? null; +} + +// 6) CF bypass mode (via Sentinel S95) +$ch = curl_init('https://wevads.weval-consulting.com/api/sentinel-brain.php'); +curl_setopt_array($ch, [ + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => http_build_query(['action' => 'exec', 'cmd' => 'cat /opt/wevads/state/cf-bypass-mode.json 2>/dev/null']), + CURLOPT_RETURNTRANSFER => true, + CURLOPT_TIMEOUT => 5, + CURLOPT_SSL_VERIFYPEER => false, +]); +$body = curl_exec($ch); +curl_close($ch); +if ($body) { + $j = @json_decode($body, true); + if ($j && !empty($j['output'])) { + $inner = @json_decode($j['output'], true); + $out['cf_bypass_mode'] = $inner ?: ['raw' => $j['output']]; + } +} + +// 7) Watchdog health (similar) +$ch = curl_init('https://wevads.weval-consulting.com/api/sentinel-brain.php'); +curl_setopt_array($ch, [ + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => http_build_query(['action' => 'exec', 'cmd' => 'cat /opt/wevads/state/cf-bypass-health.json 2>/dev/null']), + CURLOPT_RETURNTRANSFER => true, + CURLOPT_TIMEOUT => 5, + CURLOPT_SSL_VERIFYPEER => false, +]); +$body = curl_exec($ch); +curl_close($ch); +if ($body) { + $j = @json_decode($body, true); + if ($j && !empty($j['output']) && $j['output'] !== '') { + $inner = @json_decode($j['output'], true); + $out['watchdog_health'] = $inner ?: null; + } +} + +echo json_encode($out, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); diff --git a/api/wevia-fast-path-v3.php b/api/wevia-fast-path-v3.php index 06bcff708..b307f1b25 100644 --- a/api/wevia-fast-path-v3.php +++ b/api/wevia-fast-path-v3.php @@ -52,6 +52,95 @@ function _cerebrasCall($prompt, $mode = "general") { function wevia_fast_path($msg) { error_log("FP ENTRY: " . substr($msg, 0, 80)); + +// === OPUS_ARCH_FP_V44 — opus-arch intercept BEFORE all other fast-path (17-18avr) === +$__oafp = mb_strtolower(trim($msg)); +// Cap 12 +if (preg_match('/\b(explique|audit)\s+(derniere|last|trail)\b/iu', $__oafp) || preg_match('/pourquoi\s+cette\s+reponse/iu', $__oafp)) { + $r = @file_get_contents('http://127.0.0.1/api/opus-arch-explainability.php?action=stats', false, stream_context_create(['http'=>['header'=>'Host: weval-consulting.com','timeout'=>5]])); + return ['content'=>'Explain: '.substr($r,0,500),'provider'=>'opus-arch-fp','tool'=>'opus_arch_explain']; +} +// Cap 8 DeepSeek-R1 +if (preg_match('/\b(deep.?reason|system.?2|chain.?of.?thought|deepseek.?r1)\b/iu', $__oafp)) { + $ctx = stream_context_create(['http'=>['method'=>'POST','header'=>"Host: weval-consulting.com\r\nContent-Type: application/x-www-form-urlencoded",'content'=>http_build_query(['message'=>$msg]),'timeout'=>45]]); + $r = @file_get_contents('http://127.0.0.1/api/opus-arch-deepseek-r1.php', false, $ctx); + $d = @json_decode($r, true); + if ($d) return ['content'=>$d['answer'] ?? $d['full'] ?? 'R1 unavailable','provider'=>'opus-arch-fp','tool'=>'opus_arch_r1']; +} +// Cap 5 RLHF +if (preg_match('/\b(feedback|rlhf)\b/iu', $__oafp) && !preg_match('/\b(list|stats|view|show)\b/iu', $__oafp)) { + $score = preg_match('/\bup\b|positif|bon/iu', $__oafp) ? 1 : (preg_match('/\bdown\b|negatif|mauvais/iu', $__oafp) ? -1 : 0); + $ctx = stream_context_create(['http'=>['method'=>'POST','header'=>"Host: weval-consulting.com\r\nContent-Type: application/x-www-form-urlencoded",'content'=>http_build_query(['score'=>$score,'intent'=>'chat','session_id'=>session_id() ?: 'anon','correction'=>$msg]),'timeout'=>5]]); + $r = @file_get_contents('http://127.0.0.1/api/opus-arch-rlhf-feedback.php?action=submit', false, $ctx); + return ['content'=>'Feedback score='.$score.' logged','provider'=>'opus-arch-fp','tool'=>'opus_arch_rlhf']; +} +// Cap 14 Predictive Heal +if (preg_match('/\bpredictive\s+heal\b/iu', $__oafp)) { + $metric = preg_match('/disk/iu', $__oafp) ? 'disk' : (preg_match('/fpm/iu', $__oafp) ? 'fpm' : 'load'); + $r = @file_get_contents('http://127.0.0.1/api/opus-arch-predictive-heal.php?metric='.$metric, false, stream_context_create(['http'=>['header'=>'Host: weval-consulting.com','timeout'=>5]])); + return ['content'=>'Predictive '.$metric.': '.substr($r,0,600),'provider'=>'opus-arch-fp','tool'=>'opus_arch_predict']; +} +// Cap 3 API Fuzzer +if (preg_match('/\b(fuzz|auto.?discover)\s+api\b/iu', $__oafp)) { + $act = preg_match('/\b(list|results|view|show)\b/iu', $__oafp) ? 'list' : 'scan'; + $r = @file_get_contents('http://127.0.0.1/api/opus-arch-api-fuzzer.php?action='.$act.'&limit=10', false, stream_context_create(['http'=>['header'=>'Host: weval-consulting.com','timeout'=>20]])); + return ['content'=>'API fuzzer '.$act.': '.substr($r,0,800),'provider'=>'opus-arch-fp','tool'=>'opus_arch_fuzz']; +} +// Cap 17 GraphRAG +if (preg_match('/\b(graphrag|knowledge\s+graph)\b/iu', $__oafp)) { + $act = preg_match('/\bbuild\b/iu', $__oafp) ? 'build' : 'query'; + $r = @file_get_contents('http://127.0.0.1/api/opus-arch-graphrag.php?action='.$act.'&q='.urlencode($msg), false, stream_context_create(['http'=>['header'=>'Host: weval-consulting.com','timeout'=>12]])); + return ['content'=>'GraphRAG '.$act.': '.substr($r,0,800),'provider'=>'opus-arch-fp','tool'=>'opus_arch_graphrag']; +} +// Cap 15 Infinite Context +if (preg_match('/\b(infinite\s+context|analyze\s+long|chunk\s+document)\b/iu', $__oafp)) { + $r = @file_get_contents('http://127.0.0.1/api/opus-arch-infinite-context.php?action=analyze&url='.urlencode($msg), false, stream_context_create(['http'=>['header'=>'Host: weval-consulting.com','timeout'=>15]])); + return ['content'=>'Infinite context: '.substr($r,0,600),'provider'=>'opus-arch-fp','tool'=>'opus_arch_infinite']; +} +// Cap 16 Continuous FT +if (preg_match('/\b(continuous\s+fine.?tune|kaggle\s+phase\s*5|trigger\s+finetune)\b/iu', $__oafp)) { + $act = preg_match('/\btrigger\b/iu', $__oafp) ? 'trigger' : (preg_match('/\bcollect\b/iu', $__oafp) ? 'collect_logs' : 'status'); + $r = @file_get_contents('http://127.0.0.1/api/opus-arch-continuous-ft.php?action='.$act, false, stream_context_create(['http'=>['header'=>'Host: weval-consulting.com','timeout'=>10]])); + return ['content'=>'Continuous FT '.$act.': '.substr($r,0,600),'provider'=>'opus-arch-fp','tool'=>'opus_arch_finetune']; +} +// Cap 4 Prompt Evolution +if (preg_match('/\b(prompt\s+evolution|genetic\s+prompt)\b/iu', $__oafp)) { + $r = @file_get_contents('http://127.0.0.1/api/opus-arch-prompt-evolution.php', false, stream_context_create(['http'=>['header'=>'Host: weval-consulting.com','timeout'=>5]])); + return ['content'=>'Prompt evolution: '.substr($r,0,500),'provider'=>'opus-arch-fp','tool'=>'opus_arch_prompt']; +} +// Cap 10 GPU Grid +if (preg_match('/\b(gpu\s+grid|shard\s+prompt)\b/iu', $__oafp)) { + $r = @file_get_contents('http://127.0.0.1/api/opus-arch-gpu-grid-prod.php?action=status', false, stream_context_create(['http'=>['header'=>'Host: weval-consulting.com','timeout'=>5]])); + return ['content'=>'GPU Grid: '.substr($r,0,500),'provider'=>'opus-arch-fp','tool'=>'opus_arch_gpu']; +} +// Cap 2 Browser Use +if (preg_match('/\b(browser\s+use|playwright\s+browse|browse\s+url)\b/iu', $__oafp)) { + $r = @file_get_contents('http://127.0.0.1/api/opus-arch-browser-use.php?action=whitelist', false, stream_context_create(['http'=>['header'=>'Host: weval-consulting.com','timeout'=>5]])); + return ['content'=>'Browser Use: '.substr($r,0,500),'provider'=>'opus-arch-fp','tool'=>'opus_arch_browser']; +} +// Cap 7 Voice Status +if (preg_match('/\b(voice\s+status|whisper\s+status|xtts)\b/iu', $__oafp)) { + $r = @file_get_contents('http://127.0.0.1/api/opus-arch-voice.php?action=status', false, stream_context_create(['http'=>['header'=>'Host: weval-consulting.com','timeout'=>5]])); + return ['content'=>'Voice status: '.substr($r,0,500),'provider'=>'opus-arch-fp','tool'=>'opus_arch_voice']; +} +// Cap 9 Self-refactor +if (preg_match('/\b(self.?refactor|refactor\s+queue)\b/iu', $__oafp)) { + $r = @file_get_contents('http://127.0.0.1/api/opus-arch-self-refactor.php?action=queue', false, stream_context_create(['http'=>['header'=>'Host: weval-consulting.com','timeout'=>5]])); + return ['content'=>'Refactor queue: '.substr($r,0,500),'provider'=>'opus-arch-fp','tool'=>'opus_arch_refactor']; +} +// Cap 11 n8n +if (preg_match('/\bn8n\s+(generate|create\s+workflow|gen)\b/iu', $__oafp)) { + $ctx = stream_context_create(['http'=>['method'=>'POST','header'=>"Host: weval-consulting.com\r\nContent-Type: application/x-www-form-urlencoded",'content'=>http_build_query(['description'=>$msg]),'timeout'=>10]]); + $r = @file_get_contents('http://127.0.0.1/api/opus-arch-n8n-gen-v2.php?action=generate', false, $ctx); + return ['content'=>'n8n workflow: '.substr($r,0,800),'provider'=>'opus-arch-fp','tool'=>'opus_arch_n8n']; +} +// Meta Autonomy Report +if (preg_match('/\b(autonomy\s+report|carry.?overs?\s+status|gap\s+report|autonomie)\b/iu', $__oafp)) { + $r = @file_get_contents('http://127.0.0.1/api/opus-arch-autonomy-reporter.php', false, stream_context_create(['http'=>['header'=>'Host: weval-consulting.com','timeout'=>5]])); + return ['content'=>'Autonomy report: '.substr($r,0,1500),'provider'=>'opus-arch-fp','tool'=>'opus_arch_autonomy']; +} +// === END OPUS_ARCH_FP_V44 === + $m = mb_strtolower(trim($msg)); $r = null; diff --git a/api/wevia-fast-path-v3.php.GOLD-20260417-204743-pre-v44-opus-arch-fp b/api/wevia-fast-path-v3.php.GOLD-20260417-204743-pre-v44-opus-arch-fp new file mode 100644 index 000000000..06bcff708 --- /dev/null +++ b/api/wevia-fast-path-v3.php.GOLD-20260417-204743-pre-v44-opus-arch-fp @@ -0,0 +1,1281 @@ +"code-mastery","debug"=>"code-mastery","explain_code"=>"code-mastery","education"=>"domain-expertise","email"=>"domain-expertise","search"=>"domain-expertise","automation"=>"rpa-mastery","analysis"=>"domain-expertise"]; + if (isset($nmap[$mode])) { + $nf = "/opt/wevia-brain/prompts/nucleus/{$nmap[$mode]}.md"; + if (file_exists($nf)) $nucleus = "\n" . substr(file_get_contents($nf), 0, 1500); + } + + $system = "Tu es WEVIA Master, IA souveraine de WEVAL Consulting Casablanca. Reponds en francais concis, technique et actionnable." . $nucleus; + + // Use sovereign proxy (port 4000) — handles cascade + retry automatically + $ch = curl_init("http://127.0.0.1:4000/v1/chat/completions"); + curl_setopt_array($ch, [ + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => json_encode(["model"=>"fast","messages"=>[["role"=>"system","content"=>$system],["role"=>"user","content"=>$prompt]],"max_tokens"=>1500,"temperature"=>0.7]), + CURLOPT_HTTPHEADER => ["Content-Type: application/json"], + CURLOPT_RETURNTRANSFER => true, + CURLOPT_TIMEOUT => 20 + ]); + $r = curl_exec($ch); + $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + if ($code === 200) { + $d = json_decode($r, true); + $content = $d["choices"][0]["message"]["content"] ?? null; + if ($content) return ["provider"=>"pareto-".$mode,"content"=>$content,"engine"=>"Pareto/".$mode,"intent"=>"pareto_".$mode]; + } + + // Fallback Ollama + $ch = curl_init("http://127.0.0.1:11434/api/chat"); + curl_setopt_array($ch, [CURLOPT_POST=>true, CURLOPT_POSTFIELDS=>json_encode(["model"=>"qwen3:4b","messages"=>[["role"=>"system","content"=>$system],["role"=>"user","content"=>$prompt]],"stream"=>false]), CURLOPT_HTTPHEADER=>["Content-Type: application/json"], CURLOPT_RETURNTRANSFER=>true, CURLOPT_TIMEOUT=>25]); + $r = curl_exec($ch); curl_close($ch); + $d = json_decode($r, true); + return ["provider"=>"pareto-sovereign","content"=>$d["message"]["content"]??"Pas de reponse","engine"=>"Ollama/Pareto","intent"=>"pareto_".$mode]; +} + +function wevia_fast_path($msg) { + error_log("FP ENTRY: " . substr($msg, 0, 80)); + $m = mb_strtolower(trim($msg)); + $r = null; + + // === OPUS_FP_TASK_DECOMPOSER_GUARD (16AVR v3) === + // RC: opus-autonomy passe APRES fast-path donc mes AGENT 9 unreachable + // si le message contient un keyword fast-path (wiki/nonreg/paperclip/...). + // Solution: trigger TRES SPECIFIQUE en tete de fast-path. Strict prefix only. + if (preg_match('/^\s*(task[\s_-]?decompose|>>\s*decompose|\[TD\])\b/iu', trim($msg))) { + $tasks = []; + foreach (preg_split('/\r?\n/', $msg) as $line) { + $line = trim($line); + if (preg_match('/^(?:\d+[\.)]\s*|[-*]\s*|fix\s*#?\d+\s*[:\-]?\s*)(.+)/iu', $line, $tx)) { + $t = trim($tx[1]); + if (mb_strlen($t) > 3 && mb_strlen($t) < 500) $tasks[] = $t; + } + } + if (count($tasks) >= 1) { + $sub = []; + foreach ($tasks as $i => $task) { + if ($i >= 6) { $sub[] = "[truncated at 6 tasks to avoid CF 502]"; break; } + $ch = curl_init('http://127.0.0.1/api/wevia-master-api.php'); + curl_setopt_array($ch, [ + CURLOPT_POST => 1, + CURLOPT_RETURNTRANSFER => 1, + CURLOPT_TIMEOUT => 18, + CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'X-Decomp-Sub: 1'], + CURLOPT_POSTFIELDS => json_encode(['message' => $task]), + ]); + $rr = curl_exec($ch); + curl_close($ch); + $j = @json_decode($rr, true); + $resp = (string)($j['content'] ?? $rr ?? 'NULL'); + $prov = $j['provider'] ?? '?'; + $sub[] = sprintf("**[%d] %s**\n _[%s]_ %s", $i + 1, mb_substr($task, 0, 100), $prov, mb_substr($resp, 0, 350)); + } + return ['content' => "TASK_DECOMPOSER (" . count($tasks) . " tasks executed):\n\n" . implode("\n\n", $sub), 'provider' => 'opus-decompose-fp', 'source' => 'task-decomposer-fastpath', 'tool' => 'task-decomposer']; + } + } + + // === OPUS_FP_HCP_COUNTRY (opus wire 16avr) === + if (preg_match('/combien.*(hcp|medecin).*(maroc|tunis|alger)|hcp.*(maroc|tunis|alger)|medecin.*(maroc|tunis|alger)/iu', $m)) { + $cj=@json_decode(@file_get_contents('http://127.0.0.1/api/ethica-country-api.php'),true); + if($cj&&!empty($cj['countries'])){ + $out="ETHICA PAR PAYS (DB LIVE):\n"; + foreach($cj['countries'] as $cp)$out.=" ".$cp['pays'].": ".$cp['t']." HCPs, ".$cp['e']." email, ".$cp['p']." tel\n"; + $out.="\nTotal: ".$cj['total']." | Email: ".$cj['email']; + return ['content'=>$out,'provider'=>'opus-hcp-country','tool'=>'ethica-country']; + } + } + // === OPUS_FP_CONSENT_GUARD (16AVR) === + if(preg_match("/\\b(consent|optin|consentement)\\b/i",$msg) && !preg_match("/\\b(kaouther|draft|refais|wire|propos|offre|palier|tarif|45000|DH)\\b/i",$msg)){ + $cs=@json_decode(@file_get_contents("http://127.0.0.1/api/ethica-consent-api.php?action=stats"),true); + $r="CONSENTEMENTS ETHICA:\nOpt-in: ".(($cs["optin"]??0))."\nTotal: ".(($cs["total_log"]??0)); + return ["content"=>$r,"provider"=>"consent-guard","tool"=>"ethica-consent"]; + } +// === OPUS_FP_ETHICA_STATS_GUARD (16AVR v6) === + // RC: tools-catalog.json retourne descriptor statique "141K HCPs DZ/MA/TN pharma" + // quand user demande détail email/tel/breakdown → hallucinations. Call vrai endpoint. + if (preg_match('/\bethica\b/iu', $m) && preg_match('/\b(combien|detail|d[ée]tail|breakdown|split|email|telephone|t[ée]l[ée]phone|hcps?|total|exact|chiffres?|live|stats?|statistique|repartition|r[ée]partition|par.*pays|valide|gap)\b/iu', $m)) { + $j = @json_decode(@file_get_contents('http://127.0.0.1/api/ethica-stats-api.php'), true); + if (is_array($j) && !empty($j['ok'])) { + $t = (int)($j['total'] ?? 0); + $e = (int)($j['with_email'] ?? 0); + $tel = (int)($j['with_telephone'] ?? 0); + $pct_e = $t ? round(100 * $e / $t, 1) : 0; + $pct_t = $t ? round(100 * $tel / $t, 1) : 0; + $content = "ETHICA STATS LIVE (DB ethica.medecins_real sur S95):\n\n" + . "- Total HCPs: " . number_format($t, 0, ',', ' ') . "\n" + . "- Avec email valide: " . number_format($e, 0, ',', ' ') . " ({$pct_e}%)\n" + . "- Avec telephone: " . number_format($tel, 0, ',', ' ') . " ({$pct_t}%)\n" + . "- Gap email: " . number_format($t - $e, 0, ',', ' ') . "\n" + . "- Gap telephone: " . number_format($t - $tel, 0, ',', ' ') . "\n\n" + . "Source: /api/ethica-stats-api.php (query direct PG S95)\n" + . "MAJ: " . date('Y-m-d H:i:s'); + if (preg_match('/pays|country|maroc|tunisie|alger|\\bdz\\b|\\bma\\b|\\btn\\b|par\\s+pays|breakdown|repartition/iu', $m)) { $cj=@json_decode(@file_get_contents('http://127.0.0.1/api/ethica-country-api.php'),true); if($cj&&!empty($cj['countries'])){foreach($cj['countries'] as $cp)$content.="\n ".$cp['pays'].": ".$cp['t']." HCPs, ".$cp['e']." email, ".$cp['p']." tel";}} return ['content' => $content, 'provider' => 'opus-ethica-live-fp', 'source' => 'ethica-stats-api-fastpath', 'tool' => 'ethica-stats']; + } + } + + + // === NL-AUTOWIRE PRIORITY (Opus fix 16avr v6: cause racine #4+#5) === + // Loaded FIRST before any resolver to prevent fs-verify/dynamic-resolver hijack. + // v6: word-boundary matching + skip if message is an auto-wire request itself. + error_log("FP CP1 nl-priority"); $_is_autowire_req = @preg_match("/(wire|ajoute|rajoute|apprends|fais.*comprendre|sache.*repondre|nouveau.*intent|nouvel.*intent|cable|branche|connecte).*(quand|lorsque|si.*demande|si.*dit|si.*tape|si.*ecrit|pour.*question|pour.*commande)/iu", $m); + $_nlprio = "/opt/wevia-brain/priority-intents-nl.json"; + if (!$_is_autowire_req && file_exists($_nlprio)) { + $_nllist = @json_decode(@file_get_contents($_nlprio), true); + if (is_array($_nllist)) { + foreach ($_nllist as $_pi) { + if (empty($_pi["triggers"])) continue; + // Word-boundary match to avoid substring collisions (e.g. 'xcode' in 'xcode_vhost') + $_pat = "/\b(" . $_pi["triggers"] . ")\b/i"; + if (@preg_match($_pat, $m)) { + $_cmd = $_pi["command"] ?? ""; + $_nm = $_pi["name"] ?? "nl_priority"; + if (!empty($_pi["static"])) { + return ["provider"=>"nl-priority","content"=>$_cmd,"engine"=>"NL-Priority","intent"=>$_nm]; + } + $_out = trim(@shell_exec($_cmd . " 2>&1")); + if ($_out === "" || $_out === null) $_out = "(pas de sortie)"; + return ["provider"=>"nl-priority","content"=>$_out,"engine"=>"NL-Priority","intent"=>$_nm]; + } + } + } + } + + + + error_log("FP CP2 llm-classifier-start"); // === LLM INTENT CLASSIFIER (Lean 6Sigma — zero keywords) === + // Groq classifies query → picks best agent → executes transparently + // No regex patterns. Master UNDERSTANDS the query. + if ($r === null) { + // Check: is this a COMPLEX query that needs an agent? (not simple data/status) + $is_simple_data = preg_match("/^(nonreg|reconcile|git|docker|cascade|toolhub|aide|help|ping|disk|qa|wiki|vault|screenshot|sovereign|finetune|brain|hermes|paperclip|deerflow|blade|l99|pages|audit|6sigma|brains|debug|architecture|security|cartographie|director|s95|ethica|test|nouvelles|verify|send|infra|status)\b/i", trim($m)) && strlen($m) < 80; + + error_log('GATE_DEBUG m='.$m.' len='.strlen($m)); + $_has_data_kw = preg_match('/nonreg|docker|conteneur|ethica|hcp|medecin|git|cron|provider|l99|blade|qdrant|disk|port|ping|reconcil|bilan|aide|help|sovereign|paperclip|deerflow|combien.*page/iu', $m); + if (!$is_simple_data && !$_has_data_kw && strlen($m) > 15) { + // Load secrets once + static $__sk = null; + if (!$__sk) { $__sk=[]; foreach(file("/etc/weval/secrets.env") as $l) { $l=trim($l); if($l&&$l[0]!=="#"&&strpos($l,"=")!==false){list($k,$v)=explode("=",$l,2);$__sk[trim($k)]=trim($v,"\"' ");}}} + + // Step 1: Classify with Groq (200ms) + $catalog = "AGENTS: architect(design/review systeme), debugger(root cause/fix bugs), security(audit vulns/pentest), test-engineer(tests unitaires/e2e), code-reviewer(review code/qualite), planner(roadmap/strategie/planning), product-manager(PRD/personas/go-to-market), writer(emails/rapports/articles/pitch), coder(scripts/code/API), translator(FR/EN/AR), analyst(calculs/ROI/stats/finance), researcher(deep research/benchmarks), ethica-expert(pharma/HCP/medecins), sap-consultant(ERP/S4HANA), cloud-architect(infra/migration/cloud), cyber-auditor(securite/OWASP/pentest), devops(CI-CD/docker/deploy), data-scientist(ML/IA/modeles)"; + + $classify_prompt = "Classifie cette requete utilisateur. Reponds UNIQUEMENT le nom de l'agent (1 mot): $catalog\n\nRequete: $msg\nAgent:"; + + $ch = curl_init("https://api.groq.com/openai/v1/chat/completions"); + curl_setopt_array($ch, [CURLOPT_POST=>true, CURLOPT_POSTFIELDS=>json_encode(["model"=>"llama-3.3-70b-versatile","messages"=>[["role"=>"user","content"=>$classify_prompt]],"max_tokens"=>20,"temperature"=>0]), CURLOPT_HTTPHEADER=>["Content-Type: application/json","Authorization: Bearer ".($__sk["GROQ_KEY"]??"")], CURLOPT_RETURNTRANSFER=>true, CURLOPT_TIMEOUT=>5]); + $cr = curl_exec($ch); curl_close($ch); + $cd = json_decode($cr, true); + $agent = strtolower(trim($cd["choices"][0]["message"]["content"] ?? "")); + $agent = preg_replace("/[^a-z\-]/", "", $agent); + + if ($agent && strlen($agent) > 2) { + // Step 2: Load agent prompt + execute with Groq + $prompts_map = [ + "architect" => "/opt/oh-my-claudecode/prompts/architect.md", + "debugger" => "/opt/oh-my-claudecode/prompts/debugger.md", + "security" => "/opt/oh-my-claudecode/prompts/security-reviewer.md", + "test-engineer" => "/opt/oh-my-claudecode/prompts/test-engineer.md", + "code-reviewer" => "/opt/oh-my-claudecode/prompts/code-reviewer.md", + "planner" => "/opt/oh-my-claudecode/prompts/planner.md", + "product-manager" => "/opt/oh-my-claudecode/prompts/product-manager.md", + ]; + $sys = "Tu es WEVIA Master agent [$agent], IA souveraine WEVAL Consulting Casablanca. Reponds en francais professionnel.\n"; + if (isset($prompts_map[$agent]) && file_exists($prompts_map[$agent])) { + $sys .= substr(file_get_contents($prompts_map[$agent]), 0, 1500); + } + // Add domain nucleus + $nuc_map = ["coder"=>"code-mastery","debugger"=>"code-mastery","security"=>"cyber-mastery","cyber-auditor"=>"cyber-mastery","sap-consultant"=>"domain-expertise","cloud-architect"=>"domain-expertise","devops"=>"domain-expertise"]; + if (isset($nuc_map[$agent])) { + $nf = "/opt/wevia-brain/prompts/nucleus/".($nuc_map[$agent]).".md"; + if (file_exists($nf)) $sys .= "\n" . substr(file_get_contents($nf), 0, 1000); + } + $sys .= "\nContexte WEVAL: S204 8cpu/32GB, 10 Docker, 13 providers, 141K HCPs, 177 pages, NonReg 152/152."; + + $ch2 = curl_init("https://api.groq.com/openai/v1/chat/completions"); + curl_setopt_array($ch2, [CURLOPT_POST=>true, CURLOPT_POSTFIELDS=>json_encode(["model"=>"llama-3.3-70b-versatile","messages"=>[["role"=>"system","content"=>$sys],["role"=>"user","content"=>$msg]],"max_tokens"=>2000,"temperature"=>0.7]), CURLOPT_HTTPHEADER=>["Content-Type: application/json","Authorization: Bearer ".($__sk["GROQ_KEY"]??"")], CURLOPT_RETURNTRANSFER=>true, CURLOPT_TIMEOUT=>10]); + $rr = curl_exec($ch2); curl_close($ch2); + $dd = json_decode($rr, true); + $content = $dd["choices"][0]["message"]["content"] ?? null; + if ($content && strlen($content) > 20) { + error_log("FP CLASSIFIER FIRED: agent=$agent msg=" . substr($msg, 0, 80)); + return ["provider"=>"agent-$agent","content"=>$content,"engine"=>"LLM-Classifier/$agent","intent"=>"auto_classify"]; + } + error_log("FP CLASSIFIER PASS: agent=$agent content_len=" . strlen($content ?? "") . " msg=" . substr($msg, 0, 80)); + } + } + } + + + + + // === NATURAL LANGUAGE AUTO-WIRE (Opus GODMODE 16avr) === + // Yanis parle en francais naturel, Master comprend et wire automatiquement + if ($r === null && preg_match("/(wire|ajoute|rajoute|apprends|fais.*comprendre|sache.*repondre|nouveau.*intent|nouvel.*intent|cable|branche|connecte).*(quand|lorsque|si.*demande|si.*dit|si.*tape|si.*ecrit|pour.*question|pour.*commande)/iu", $m)) { + // Use LLM to parse natural language into pattern + command + $nl_prompt = "Tu es un parseur d'intents pour WEVIA Master. L'utilisateur veut ajouter une nouvelle capacite. Extrais: +1. intent_name: nom court snake_case +2. triggers: mots-cles separes par | (regex simple, pas de regex complexe) +3. command: commande shell a executer OU reponse statique entre guillemets + +Reponds UNIQUEMENT en JSON strict: {\"intent_name\":\"...\",\"triggers\":\"...\",\"command\":\"...\"} + +Message utilisateur: " . $msg; + + // Call sovereign LLM to parse + $ch = curl_init("http://127.0.0.1:4000/chat"); + curl_setopt_array($ch, [ + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => json_encode(["messages"=>[["role"=>"user","content"=>$nl_prompt]],"max_tokens"=>300,"temperature"=>0.1]), + CURLOPT_HTTPHEADER => ["Content-Type: application/json"], + CURLOPT_RETURNTRANSFER => true, + CURLOPT_TIMEOUT => 12 + ]); + $llm_resp = curl_exec($ch); + curl_close($ch); + $llm_data = @json_decode($llm_resp, true); + $llm_text = $llm_data["choices"][0]["message"]["content"] ?? ""; + if (empty(trim($llm_text))) { + $ch2 = curl_init("https://api.groq.com/openai/v1/chat/completions"); + curl_setopt_array($ch2, [ + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => json_encode(["model"=>"llama-3.3-70b-versatile","messages"=>[["role"=>"user","content"=>$nl_prompt]],"max_tokens"=>300,"temperature"=>0.1]), + CURLOPT_HTTPHEADER => ["Content-Type: application/json", "Authorization: Bearer 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"], + CURLOPT_RETURNTRANSFER => true, + CURLOPT_TIMEOUT => 8 + ]); + $llm_resp2 = curl_exec($ch2); + curl_close($ch2); + $llm_data2 = @json_decode($llm_resp2, true); + $llm_text = $llm_data2["choices"][0]["message"]["content"] ?? ""; + } + + // Extract JSON from LLM response + if (preg_match("/\{[^}]+\}/", $llm_text, $jm)) { + $parsed = @json_decode($jm[0], true); + if ($parsed && !empty($parsed["intent_name"]) && !empty($parsed["triggers"])) { + $name = preg_replace("/[^a-z0-9_]/", "", strtolower($parsed["intent_name"])); + $triggers = $parsed["triggers"]; + $cmd = $parsed["command"] ?? "echo \"Intent $name: pas de commande definie\""; + + // Check if command is a static response (quoted) or shell command + $is_static = (substr($cmd, 0, 1) === "'" || substr($cmd, 0, 1) === "\""); + + // Wire into NL-PRIORITY JSON (Opus fix 16avr: route racine #4) + $_nlp = "/opt/wevia-brain/priority-intents-nl.json"; + $_list = file_exists($_nlp) ? (@json_decode(@file_get_contents($_nlp), true) ?: []) : []; + $_list = array_filter($_list, function($x) use ($name) { return ($x["name"] ?? "") !== $name; }); + $_list = array_values($_list); + $_list[] = ["name"=>$name, "triggers"=>$triggers, "command"=>$cmd, "static"=>$is_static]; + $gold = "/opt/wevads/vault/GOLD-nlprio-" . date("YmdHis") . ".json"; + if (file_exists($_nlp)) copy($_nlp, $gold); + @file_put_contents($_nlp, json_encode($_list, JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT)); + @chmod($_nlp, 0664); + shell_exec("rm -f /dev/shm/wevia_cache_* 2>&1"); + $r = "AUTO-WIRE NL OK (PRIORITY): intent '{$name}' active au top du pipeline. Triggers: {$triggers}. Commande: {$cmd}. GOLD: " . basename($gold); + // Keep master-router legacy block commented for back-compat rollback + $mr = "/opt/wevia-brain/wevia-master-router.php"; + exec("sudo chattr -i $mr"); + $mc = file_get_contents($mr); + $gold_legacy_unused = "/opt/wevads/vault/GOLD-router-" . date("YmdHis") . ".php"; + + if ($is_static) { + $clean_resp = trim($cmd, "\"'"); + $insert = " if(preg_match('/(" . $triggers . ")/i',\$msg)) return array_merge(\$base,['content'=>'" . addslashes($clean_resp) . "','engine'=>'NL-AutoWire','intent'=>'" . $name . "']);\n"; + } else { + $insert = " if(preg_match('/(" . $triggers . ")/i',\$msg)){\$ro=trim(shell_exec('" . addslashes($cmd) . " 2>&1'));return array_merge(\$base,['content'=>\$ro,'engine'=>'NL-AutoWire','intent'=>'" . $name . "']);}\n"; + } + + // Insert at auto-wire point or before catch-all + if (strpos($mc, "// auto-wire-insertion-point") !== false) { + $mc = str_replace(" // auto-wire-insertion-point", $insert . " // auto-wire-insertion-point", $mc); + } + + file_put_contents($mr, $mc); + $lint = shell_exec("php -l $mr 2>&1"); + if (strpos($lint, "No syntax errors") !== false) { + exec("sudo chattr +i $mr"); + shell_exec("rm -f /dev/shm/wevia_cache_*"); + $r = "AUTO-WIRE NL OK: intent '{$name}' cree. Triggers: {$triggers}. Commande: {$cmd}. GOLD: " . basename($gold); + } else { + copy($gold, $mr); + exec("sudo chattr +i $mr"); + $r = "AUTO-WIRE NL FAIL: lint error, rollback. Debug: " . substr($lint, 0, 100); + } + } else { + $r = "AUTO-WIRE NL: pas pu parser. Reformule: 'ajoute un intent pour [description] quand on demande [trigger]'. LLM a dit: " . substr($llm_text, 0, 200); + } + } else { + $r = "AUTO-WIRE NL: LLM n'a pas retourne de JSON. Reformule plus clairement. Raw: " . substr($llm_text, 0, 200); + } + } + + error_log("FP CP3 priority-bypass"); // PRIORITY BYPASS + if (preg_match('/\\bgit\\s+(push|commit)\\b/i',$m) && preg_match('/dirty|fichier/i',$m)) { /* commit intent handles */ } + // OPUS-FIX RC#1: Long complex messages skip FastPath -> go to LLM (orphan elseif removed) + if (mb_strlen($m) > 80 && preg_match('/\b(pourquoi|comment|explique|corrige|repare|fixe|analyse|compare|ameliore|propose|aide.*:|wire|autowire|self.fix)\b/iu', $m)) return null; + // === MULTI_TOPIC_GUARD (opus wire 16avr) === + $_kw_count = 0; + foreach (['nonreg','l99','ethica','docker','git','cron','provider','infra'] as $_kw) if (strpos($m, $_kw) !== false) $_kw_count++; + if ($_kw_count >= 3 || (preg_match('/bilan.*complet|tout.*verif|donnee.*fraich|diagnostic.*complet/iu', $m) && mb_strlen($m) > 40)) { + $_agg = @json_decode(@file_get_contents('http://127.0.0.1/api/wevia-multiagent.php'), true); + if ($_agg && !empty($_agg['diagnostic'])) return ['provider'=>'fast-path','content'=>$_agg['diagnostic'],'tool'=>'multiagent-exec']; + } + if (preg_match('/combien.*pages?|pages?.*site|nombre.*pages?/iu', $m)) { + $r = 'PAGES: '.trim(@shell_exec('ls /var/www/html/*.html 2>/dev/null | wc -l')).' HTML pages'; + } elseif ($m === 'ping' || strpos($m, 'ping') === 0) { + $r = trim(@shell_exec('echo S95:$(timeout 1 ping -c1 -W1 10.1.0.3 2>/dev/null | grep -oP "time=\K[0-9.]+") Groq:$(curl -so/dev/null -w%{http_code} -m2 https://api.groq.com 2>/dev/null)')); + } elseif (strpos($m, 'nonreg') !== false) { + + $d = @json_decode(@file_get_contents(__DIR__.'/nonreg-latest.json'),true); $r = $d ? 'NONREG: '.$d['pass'].'/'.$d['total'].' ('.$d['score'].'%)' : 'NONREG: run check'; + } elseif ($m === 'aide' || $m === 'help') { + $r = "WEVIA MASTER 375 tools. reconcile dirty l99 ports providers git ethica crons docker nonreg ping aide"; + } elseif (strpos($m, 'diagn') !== false || strpos($m, 'health') !== false) { + + $r = trim(@shell_exec('echo "LOAD: $(cat /proc/loadavg)" && echo "RAM: $(free -m | grep Mem)" && echo "DISK: $(df -h / | tail -1)" && echo "FPM: $(pgrep -c php-fpm) workers"')); + } elseif (strpos($m, 'disk') !== false || strpos($m, 'espace') !== false) { + + $r = trim(@shell_exec('df -h / | tail -1')); + } elseif (strpos($m, 'reconcil') !== false || strpos($m, 'bilan') !== false) { + + $cmds = []; + $cmds[] = 'echo "=GIT=" && cd /var/www/html && echo "Dirty:$(git status -s|wc -l)" && git status -s 2>/dev/null|head -15'; + $cmds[] = 'echo "=PORTS=" && ss -tlnp 2>/dev/null|grep -oP ":\K[0-9]+"|sort -un|tr "\n" " "'; + $cmds[] = 'echo "" && echo "=SOVEREIGN=" && curl -s -m3 localhost:4000/health 2>/dev/null|head -c 80'; + $cmds[] = 'echo "" && echo "=NONREG=" && php8.4 /var/www/html/api/nonreg-quick.php 2>/dev/null|tail -1'; + $cmds[] = 'echo "=L99=" && echo "Pages:$(ls /var/www/html/*.html|wc -l) Wiki:$(ls /opt/weval-l99/wiki/*.json 2>/dev/null|wc -l)"'; + $cmds[] = 'echo "=CRONS=" && echo "Active:$(crontab -l 2>/dev/null|grep -cv ^#)"'; + $r = trim(@shell_exec(implode(' && ', $cmds))); + } elseif (strpos($m, 'dirty') !== false || strpos($m, 'fichiers modif') !== false) { + + if (preg_match('/\\bgit\\s+(push|commit)\\b/i',$m)) { + $r = trim(@shell_exec('cd /var/www/html && git add -A && git commit -m "auto-wevia-master" 2>&1|tail -3 && git push 2>&1|tail -3')); + $r2 = trim(@shell_exec('cd /opt/weval-l99 && git add -A && git commit -m "auto-wevia-master" 2>&1|tail -3 && git push gitea master 2>&1|tail -3')); $r .= " +OPT: ".$r2; + } else { + $r = trim(@shell_exec('cd /var/www/html && echo "DIRTY FILES:" && git status --short 2>/dev/null|head -40')); + } + } elseif (preg_match('/\\bgit\\s+(push|commit)\\b/i',$m)) { + + $r = trim(@shell_exec('cd /var/www/html && git add -A && git commit -m "auto-wevia-master" 2>&1|tail -3 && git push 2>&1|tail -3')); + $r2 = trim(@shell_exec('cd /opt/weval-l99 && git add -A && git commit -m "auto-wevia-master" 2>&1|tail -3 && git push gitea master 2>&1|tail -3')); $r .= " +OPT: ".$r2; + } elseif (strpos($m, 'git') !== false) { + + if (strpos($m,'pat')!==false||strpos($m,'token')!==false||strpos($m,'credential')!==false||strpos($m,'expir')!==false) { + $pat = trim(@shell_exec('cd /var/www/html && git remote get-url origin 2>/dev/null | grep -oP "ghp_[a-zA-Z0-9]+"')); + $code = $pat ? trim(@shell_exec('curl -s -o/dev/null -w "%{http_code}" -H "Authorization: token '.$pat.'" https://api.github.com/user 2>/dev/null')) : '0'; + $r = 'PAT: ' . ($pat ? substr($pat,0,10).'...' : 'NOT FOUND') . ' API: ' . ($code == '200' ? 'VALID' : 'EXPIRED('.$code.')'); + } else { + $r = trim(@shell_exec('cd /var/www/html && echo "DIRTY:$(git status -s|wc -l)" && git log --oneline -3 2>/dev/null')); + } + } elseif ((strpos($m, 'l99') !== false || strpos($m, 'saas') !== false) && !preg_match('/\b(lance|run|execute|update|rescan|met[s]?.*jour|fullscan|restart)\b/iu', $m)) { + + $r = trim(@shell_exec('echo "Pages:$(ls /var/www/html/*.html|wc -l) Wiki:$(ls /opt/weval-l99/wiki/*.json 2>/dev/null|wc -l)" && echo "Last wiki:" && ls -lt /opt/weval-l99/wiki/*.json 2>/dev/null|head -3')); + } elseif (preg_match("/\bports?\b/i", $m)) { + $r = trim(@shell_exec('ss -tlnp 2>/dev/null|grep LISTEN|head -25')); + } elseif (strpos($m, 'ethica') !== false && !preg_match('/redige|ecris|propose|email|mail|lettre|courrier|pays|country|crons|cron|s95|gap|enrichment|dz|ma|tn|detail|par pays|breakdown|test|e2e|end.to.end|check|verif/iu', $m)) { + $r = trim(@shell_exec('curl -s -m3 http://127.0.0.1:8443/api/ethica-stats-api.php 2>/dev/null') ?: 'Ethica: 141K HCPs'); +error_log("FP CP4 my-intents-start"); // INTENT: cascade_routing + if ($r === null && preg_match("/cascade.*dediee.*intent|routing.*par.*intent|provider.*par.*type|cascade.*type.*intent|quel.*provider.*pour.*(?:code|pharma|strategy|legal)/iu", $m)) { + $routing = [ + "code" => ["primary" => "Cerebras-fast", "model" => "llama-3.3-70b", "rationale" => "800 tokens/s, code completion optimal"], + "code_deep" => ["primary" => "NVIDIA NIM", "model" => "glm-4.5", "rationale" => "Reasoning + long context"], + "pharma" => ["primary" => "Gemini", "model" => "gemini-2.0-flash", "rationale" => "Knowledge cutoff récent, strict factualité"], + "strategy" => ["primary" => "Groq", "model" => "llama-3.3-70b-versatile", "rationale" => "Latency ultra-basse + 70B"], + "legal" => ["primary" => "DeepSeek", "model" => "deepseek-reasoner", "rationale" => "Chain-of-thought, précision juridique"], + "translation" => ["primary" => "Mistral", "model" => "mistral-large-latest", "rationale" => "Français/EN/AR natif"], + "creative" => ["primary" => "SambaNova", "model" => "Meta-Llama-3.3-70B", "rationale" => "Générative + rapide"], + "pharma_research" => ["primary" => "Cohere", "model" => "command-r-plus", "rationale" => "RAG optimisé"], + "classification" => ["primary" => "Groq", "model" => "llama-3.1-8b-instant", "rationale" => "200ms pour routing rapide"], + "embedding" => ["primary" => "Ollama (local)", "model" => "nomic-embed-text", "rationale" => "Souverain, 768dim, 0€"], + ]; + $r = "CASCADE IA DÉDIÉE PAR TYPE D'INTENT:\n"; + foreach ($routing as $type => $cfg) { + $r .= sprintf(" %-18s → %-20s (%s)\n", $type, $cfg["primary"] . "/" . $cfg["model"], $cfg["rationale"]); + } + } elseif (strpos($m, 'provider') !== false || strpos($m, 'cascade') !== false) { + + $r = trim(@shell_exec('curl -s -m3 localhost:4000/health 2>/dev/null') ?: 'Sovereign: check'); + } elseif (strpos($m, 'cron') !== false && !preg_match('/s95|ethica/iu', $m)) { + + $r = trim(@shell_exec('echo "Active:$(crontab -l 2>/dev/null|grep -cv "^#")" && crontab -l 2>/dev/null|grep -v "^#"|head -10')); + } elseif ((strpos($m, 'docker') !== false || strpos($m, 'conteneur') !== false)) { + + $r = trim(@shell_exec('docker ps --format "{{.Names}}: {{.Status}}" 2>/dev/null|head -10')); + } elseif (strpos($m, 'tableau') !== false || strpos($m, 'dashboard') !== false || (strpos($m, 'resum') !== false && strpos($m, 'system') !== false)) { + + $pages = trim(@shell_exec('ls /var/www/html/*.html 2>/dev/null | wc -l')); + $tools = '382'; + $nr = trim(@shell_exec('bash /var/www/html/api/nonreg-check.sh 2>/dev/null')); + $eth = trim(@shell_exec('curl -s -m3 http://127.0.0.1:8443/api/ethica-stats-api.php 2>/dev/null')); + $sov = @json_decode(trim(@shell_exec('curl -s -m3 http://127.0.0.1:4000/health 2>/dev/null')), true); + $dk = trim(@shell_exec('docker ps -q 2>/dev/null | wc -l')); + $disk = trim(@shell_exec("df -h / | tail -1 | awk '{print \}'")); + $pw = @json_decode(@file_get_contents('/opt/weval-l99/playwright-visual-state.json'), true); + $ft = @json_decode(@file_get_contents('/opt/weval-l99/functional-test-results.json'), true); + $wiki = trim(@shell_exec('ls /opt/weval-l99/wiki/*.json 2>/dev/null | wc -l')); + $r = "DASHBOARD WEVAL +"; + $r .= "Pages: " . $pages . " | Tools: " . $tools . " | NonReg: " . $nr . " +"; + $r .= "Ethica: " . $eth . " +"; + $r .= "Providers: " . ($sov['active'] ?? '?') . "/" . ($sov['total'] ?? '?') . " (" . ($sov['primary'] ?? '?') . ") +"; + $r .= "Docker: " . $dk . " | Disk: " . $disk . " +"; + $r .= "Playwright: " . ($pw['pass'] ?? '?') . " pass | Functional: " . ($ft['pass'] ?? '?') . "/" . (($ft['pass']??0)+($ft['fail']??0)) . " +"; + $r .= "Wiki: " . $wiki . " articles"; + } elseif (strpos($m, 'qdrant') !== false) { + + if (strpos($m, '768') !== false || strpos($m, 'embed') !== false || strpos($m, 'nomic') !== false) { + $r = trim(@shell_exec('curl -s localhost:6333/collections/wevia_kb_768 2>/dev/null | python3 -c "import json,sys; d=json.load(sys.stdin); print(\"wevia_kb_768:\", d.get(\"result\",{}).get(\"points_count\",0), \"points 768dims\")" 2>/dev/null')); + } elseif (preg_match('/ingest|alimente|rempli/i', $m)) { + @shell_exec('nohup python3 /opt/weval-l99/qdrant-ingest.py > /tmp/qdrant-ingest.log 2>&1 &'); + $r = 'QDRANT_INGEST lancé en background.'; + } else { + $r = trim(@shell_exec('curl -s -m3 http://127.0.0.1:6333/collections 2>/dev/null')); + } + } elseif (strpos($m, 'ssl') !== false || strpos($m, 'securit') !== false || strpos($m, 'crowdsec') !== false) { + + $ssl = trim(@shell_exec('openssl s_client -connect weval-consulting.com:443 -servername weval-consulting.com /dev/null | openssl x509 -noout -enddate 2>/dev/null')); $cs = trim(@shell_exec('docker exec crowdsec cscli decisions list -o raw 2>/dev/null | tail -n+2 | wc -l')) ?: '0'; $r = 'SSL: ' . $ssl . ' | CrowdSec bans: ' . $cs; + } elseif (strpos($m, 'pat') !== false && (strpos($m, 'github') !== false || strpos($m, 'token') !== false || strpos($m, 'credential') !== false)) { + + $pat = trim(@shell_exec('cd /var/www/html && git remote get-url origin 2>/dev/null | grep -oP "ghp_[a-zA-Z0-9]+"')); + $code = $pat ? trim(@shell_exec('curl -s -o/dev/null -w "%{http_code}" -H "Authorization: token '.$pat.'" https://api.github.com/user 2>/dev/null')) : '0'; + $r = 'PAT: ' . ($pat ? substr($pat,0,10).'...' : 'NOT FOUND') . ' API: ' . ($code == '200' ? 'VALID' : 'EXPIRED('.$code.')'); + } elseif (strpos($m, 'ollama') !== false || strpos($m, 'doctrine') !== false) { + + $oll = trim(@shell_exec('pgrep -c ollama 2>/dev/null || echo 0')); + $port = trim(@shell_exec('ss -tlnp sport = :11434 2>/dev/null | grep -c LISTEN')); + $models = @json_decode(@shell_exec('curl -s -m2 localhost:11434/api/tags 2>/dev/null'),true); + $mlist = $models ? implode(',', array_map(fn($m)=>$m['name'], $models['models']??[])) : 'none'; + $r = 'Ollama: ' . $oll . ' procs, port 11434: ' . ($port > 0 ? 'UP' : 'OFF'); + $r .= ' | Models: ' . $mlist; + $r .= ' | Doctrine: embedding-only (nomic-embed-text+weval-brain-v3). Sovereign=primary LLM.'; + } elseif ((strpos($m, 'screenshot') !== false || strpos($m, 'video') !== false || strpos($m, 'vidéo') !== false) && !preg_match('/detail|playwright/iu', $m)) { + + $ss = trim(@shell_exec('find /opt/weval-l99/screenshots -name "*.png" 2>/dev/null | wc -l')); + $vd = trim(@shell_exec('find /opt/weval-l99/videos -name "*.webm" -o -name "*.mp4" 2>/dev/null | wc -l')); + $r = 'Screenshots: ' . $ss . ', Videos: ' . $vd; + } elseif (strpos($m, 'paperclip') !== false || strpos($m, 'register') !== false) { + + if (preg_match('/register|lance|run/i', $m)) { + @shell_exec('nohup timeout 60 python3 /opt/weval-l99/wevia-register-agent.py > /var/log/l99-paperclip.log 2>&1 &'); + $r = 'PAPERCLIP_REGISTER lancé en background. Résultats dans ~30s.'; + } else { + $db = @pg_connect('host=127.0.0.1 dbname=adx_system user=weval'); + if ($db) { + $agents = @pg_fetch_result(@pg_query($db, "SELECT count(*) FROM paperclip.company_agents"), 0, 0); + $active = @pg_fetch_result(@pg_query($db, "SELECT count(*) FROM paperclip.company_agents WHERE status=1"), 0, 0); + $skills = @pg_fetch_result(@pg_query($db, "SELECT count(*) FROM paperclip.company_skills"), 0, 0); + @pg_close($db); + $r = "Agents:" . $agents . " Active:" . $active . " Skills:" . $skills; + } else { + $r = 'Paperclip DB: connection failed'; + } + } + } elseif ((strpos($m, 'wiki') !== false || strpos($m, 'vault') !== false) && !preg_match('#\b(lis|affiche|ouvre|montre|cat|contenu|read|show|lance|run|execute|update|rescan|met[s]?.*jour|sync|sauvegarde|save|enregistr|cr[ée]e?|stop|kill|tue|arrete|snapshot)\b|/opt/wevads/vault/|/opt/weval-l99/wiki/#iu', $m)) { + + $r = 'Wiki: ' . trim(@shell_exec('ls /opt/weval-l99/wiki/*.json 2>/dev/null | wc -l')) . ' articles, Vault: ' . trim(@shell_exec('ls /opt/wevads/vault/*.gold 2>/dev/null | wc -l')) . ' docs'; + } elseif (strpos($m, 'sous-domaine') !== false || strpos($m, 'subdomain') !== false) { + + $r = trim(@shell_exec('for d in analytics code crm deerflow git langfuse mirofish mm monitor n8n paperclip wevads; do c=$(curl -so/dev/null -w%{http_code} --max-time 3 https://$d.weval-consulting.com/ 2>/dev/null); echo $d:$c; done')); + } elseif (strpos($m, 'playwright') !== false || strpos($m, 'selenium') !== false || strpos($m, 'visual test') !== false || strpos($m, 'qa') !== false) { + + if (preg_match('/lance|execut|run|relance|demarre/i', $m)) { + @shell_exec('curl -s -m5 "http://127.0.0.1:8443/api/wevia-qa-hub.php?action=playwright" > /dev/null 2>&1 &'); + $r = 'PLAYWRIGHT_LAUNCHED en background. Résultats dans ~60s. Tape "playwright" pour voir les résultats.'; + } else { + $pw = @json_decode(@file_get_contents('/opt/weval-l99/playwright-visual-state.json'), true); + $qa = @json_decode(@file_get_contents('/var/www/html/api/wevia-quality-status.json'), true); + $ft = @json_decode(@file_get_contents('/opt/weval-l99/functional-test-results.json'), true); + $r = 'Playwright: ' . ($pw['pass'] ?? '?') . ' pass, ' . ($pw['fail'] ?? '?') . ' fail | '; + $r .= 'QA Global: ' . ($qa['global_pass'] ?? '?') . '/' . (($qa['global_pass'] ?? 0)+($qa['global_fail'] ?? 0)) . ' (' . ($qa['global_rate'] ?? '?') . '%) | '; + $r .= 'Functional: ' . ($ft['pass'] ?? '?') . '/' . (($ft['pass'] ?? 0)+($ft['fail'] ?? 0)) . ' | '; + $r .= 'NonReg: 152/152'; + } + } elseif (strpos($m, 'deerflow') !== false) { + + if (preg_match('/relance|restart|redemarr|down|mort|crash/i', $m)) { + $r = trim(@shell_exec('ssh -p 49222 -o StrictHostKeyChecking=no -i /var/www/.ssh/wevads_key root@127.0.0.1 "systemctl restart deerflow deerflow-web 2>&1 && echo DEERFLOW_RESTARTED" 2>/dev/null')); + } else { + $r = trim(@shell_exec('curl -s -m5 http://127.0.0.1:3002/health 2>/dev/null | head -5')) ?: 'DeerFlow check'; + } + } elseif (strpos($m, 'arena') !== false) { + + $r = trim(@shell_exec('echo "Groq:$(timeout 2 curl -so/dev/null -w%{http_code} https://api.groq.com/openai/v1/models 2>/dev/null) Cerebras:$(timeout 2 curl -so/dev/null -w%{http_code} https://api.cerebras.ai/v1/models 2>/dev/null)"')); + } elseif ((strpos($m, 'strateg') !== false || strpos($m, 'priorit') !== false) && !preg_match('/propose|ecris|redige|planifie/iu', $m)) { + $r = "TOP3 Q2: 1.Cloud Scaleway 5POC 240KMAD 2.Ethica 3K/mois 3.Growth 3RDV/sem Pipeline:3.5MMAD"; + } elseif (preg_match('/fonctionne|tout.+va|sant.+syst|status.+global|everything.+ok/i', $m)) { + $nr = @json_decode(@file_get_contents(__DIR__.'/nonreg-latest.json'),true); + $dk = trim(@shell_exec('docker ps -q 2>/dev/null | wc -l')); + $disk = trim(@shell_exec("df -h / | tail -1 | awk '{print \$5}'")); + $sov = @json_decode(trim(@shell_exec('curl -s -m3 localhost:4000/health 2>/dev/null')),true); + $load = trim(@shell_exec('cut -d" " -f1 /proc/loadavg')); + $r = 'SANTE: NonReg=' . ($nr ? $nr['pass'].'/'.$nr['total'] : '?') . ' Docker=' . $dk . '/8 Disk=' . $disk . ' Sovereign=' . ($sov['active']??'?') . '/' . ($sov['total']??'?') . ' Load=' . $load; + $r .= ($nr && $nr['score']>=99 && intval($dk)>=8) ? ' => TOUT OK' : ' => ALERTES'; + } elseif (false && preg_match('/^(bonjour|hello|hi|salut|hey)/i', $m)) { + $r = "WEVIA Master IA souveraine WEVAL. 375 tools, 13 providers, 141K HCPs. Tapez: reconcile dirty l99 ports providers git ethica crons docker nonreg ping aide"; + } + + if ($r === null && preg_match("/cascade.*status|providers.*status|ia.*status|litellm.*status|combien.*provider/i", $m) && !preg_match("/lance|demarre|ajoute|wire/iu", $m)) { + $cc = @json_decode(@file_get_contents("/opt/wevia-brain/wevia-sovereign-cascade.json"), true); + $ps = array_map(fn($p) => $p["name"], $cc["providers"] ?? []); + $lt = @file_get_contents("http://localhost:4001/health") ? "UP" : "DOWN"; + $lf = @file_get_contents("http://localhost:3001") ? "UP" : "DOWN"; + $r = "CASCADE: " . count($ps) . " providers [" . implode(",", $ps) . "] LiteLLM:{$lt} Langfuse:{$lf}"; + } + + if ($r === null && preg_match("/finetune.*status|fine.tune.*status|training.*data.*status|donnees.*entrainement|combien.*sample/i", $m) && !preg_match("/lance|demarre|execute|run|ouvre/iu", $m)) { + $lines = file_exists("/opt/wevia-brain/weval-finetune-data.jsonl") ? count(file("/opt/wevia-brain/weval-finetune-data.jsonl")) : 0; + $r = "FINETUNE: {$lines} samples prets dans /opt/wevia-brain/weval-finetune-data.jsonl. Script Kaggle: /opt/wevia-brain/kaggle-finetune.py. Model cible: Qwen2.5-3B-Instruct -> weval-brain-v4."; + } + + if ($r === null && preg_match("/groq.*console|groq.*api|groq.*model/i", $m)) { $r = "Groq: Provider #1, llama-3.3-70b, <100ms. Console: console.groq.com. Key in secrets.env."; } + if ($r === null && preg_match("/cerebras.*console|cerebras.*api/i", $m)) { $r = "Cerebras: Provider #2, qwen-3-235b, ultra-rapide. Console: cloud.cerebras.ai."; } + if ($r === null && preg_match("/mistral.*console|mistral.*api|mistral.*model/i", $m)) { $r = "Mistral: Provider #3, modeles europeens souverains. Console: console.mistral.ai."; } + if ($r === null && preg_match("/sambanova.*api|sambanova.*model/i", $m)) { $r = "SambaNova: Provider #4, DeepSeek-V3.1. API: api.sambanova.ai."; } + if ($r === null && preg_match("/alibaba.*qwen|qwen.*api|qwen.*model/i", $m)) { $r = "Alibaba Qwen: Provider #5, consensus parallele Manager v5. Modeles: Qwen3-235B, Qwen2.5-72B."; } + if ($r === null && preg_match("/deepseek.*api|deepseek.*model|deepseek.*v3/i", $m)) { $r = "DeepSeek: Provider #7, V3.1 reasoning model. OSS. Via SambaNova/Groq gratuit."; } + if ($r === null && preg_match("/glm.5|nvidia.*glm|glm.*api/i", $m)) { $r = "NVIDIA GLM-5: Blade Brain provider. Key: nvapi-hvNO... dans secrets.env. Score 85 #1 open weight."; } + if ($r === null && preg_match("/claude.*opus|opus.*4.6/i", $m)) { $r = "Claude Opus 4.6: Modele le plus avance. Orchestrateur WEVAL, analyse, architecture. API Anthropic."; } + if ($r === null && preg_match("/claude.*sonnet|sonnet.*4.6/i", $m)) { $r = "Claude Sonnet 4.6: Modele rapide, coding, execution. WEVIA Anthropic proxy."; } + if ($r === null && preg_match("/claude.*haiku|haiku.*4.5/i", $m)) { $r = "Claude Haiku 4.5: Modele leger, classification rapide, triage."; } + if ($r === null && preg_match("/claude.*code.*cli|claude.*code.*install/i", $m)) { $r = "Claude Code CLI: v2.1.89 installe. Paperclip CEO agent. npm install."; } + if ($r === null && preg_match("/oh.my.claude|omc.*agent/i", $m)) { $r = "oh-my-claudecode: 20K stars, 19 agents, 28 skills, Teams orchestration. /opt/oh-my-claudecode/"; } + if ($r === null && preg_match("/superclaude|sc.*research|sc.*brainstorm/i", $m)) { $r = "SuperClaude: 30 commandes, personas cognitives, /sc:research. /opt/superclaude/"; } + if ($r === null && preg_match("/everything.*claude|agentshield|ecc.*skill/i", $m)) { $r = "everything-claude-code: AgentShield 420 skills, 1282 tests, red/blue team. /opt/ecc/"; } + if ($r === null && preg_match("/antigravity|awesome.*skill/i", $m)) { $r = "antigravity: 4198 SKILL.md, Claude Code + Codex + Gemini CLI. /opt/antigravity/"; } + if ($r === null && preg_match("/huggingface.*skill|hf.*skill/i", $m)) { $r = "HuggingFace Skills: 12 officiels, TRL training, datasets, Spaces, GGUF. /opt/hf-skills/"; } + if ($r === null && preg_match("/voltagent|volt.*agent/i", $m)) { $r = "VoltAgent: 1000+ agent skills communautaires multi-plateforme. /opt/voltagent/"; } + if ($r === null && preg_match("/awesome.*claude.*toolkit|claude.*toolkit/i", $m)) { $r = "awesome-claude-toolkit: 135 agents, 42 commands, 150+ plugins. /opt/awesome-claude-toolkit/"; } + if ($r === null && preg_match("/claude.*mem|memoire.*persistante|cross.*session/i", $m)) { $r = "claude-mem: 13K stars, memoire persistante cross-sessions. /opt/claude-mem/"; } + if ($r === null && preg_match("/skillsmith|generateur.*skill/i", $m)) { $r = "SkillSmith: Generateur auto de skills Claude Code. /opt/skillsmith/"; } + if ($r === null && preg_match("/lyria|musique.*ia|generer.*musique/i", $m)) { $r = "Lyria 3: Generation musique IA Google. Endpoint pret, cle Gemini a activer dans AI Studio."; } + if ($r === null && preg_match("/diffusiondb|2m.*prompt|dataset.*image/i", $m)) { $r = "DiffusionDB: 6K stars, 2M prompts+images dataset. /opt/diffusiondb/"; } + if ($r === null && preg_match("/vllm|vllm.*install|pagedattention/i", $m)) { $r = "vLLM: Inference haute perf PagedAttention. /opt/vllm/ Clone."; } + if ($r === null && preg_match("/localai|local.*ai|openai.*compat.*local/i", $m)) { $r = "LocalAI: Drop-in OpenAI API compatible local. /opt/localai/"; } + if ($r === null && preg_match("/open.*webui|web.*ui.*llm/i", $m)) { $r = "Open WebUI: Interface web LLMs. /opt/open-webui/"; } + if ($r === null && preg_match("/librechat|libre.*chat/i", $m)) { $r = "LibreChat: Clone ChatGPT multi-provider. /opt/librechat/"; } + if ($r === null && preg_match("/modelscope|alibaba.*hub/i", $m)) { $r = "ModelScope: Hub IA Alibaba, Qwen/DeepSeek alternatifs. modelscope.cn"; } + if ($r === null && preg_match("/lmarena|chatbot.*arena|benchmark.*arena/i", $m)) { $r = "LMArena: 8K stars, Chatbot Arena benchmark, ELO ranking LLMs. lmarena.ai"; } + if ($r === null && preg_match("/ltx.*video|lightricks.*video/i", $m)) { $r = "LTX-Video: Generation video IA Lightricks. /opt/ltx-video/"; } + if ($r === null && preg_match("/euria|infomaniak.*ia|ia.*suisse/i", $m)) { $r = "Euria (Infomaniak): IA souveraine suisse RGPD. Benchmark reference."; } + if ($r === null && preg_match("/manus.*agent|agent.*autonome.*multi/i", $m)) { $r = "Manus: Agent IA autonome multi-etapes. manus.im"; } + if ($r === null && preg_match("/activepieces|workflow.*alt/i", $m)) { $r = "Activepieces: Workflow automation alternative n8n. /opt/activepieces/"; } + if ($r === null && preg_match("/mastra|framework.*agent.*ts/i", $m)) { $r = "Mastra: Framework agents TypeScript. /opt/mastra/"; } + if ($r === null && preg_match("/dify|llm.*app.*platform/i", $m)) { $r = "Dify: LLM app platform. /opt/dify/"; } + if ($r === null && preg_match("/goose.*agent|goose.*ia/i", $m)) { $r = "Goose: Agent IA (Block). /opt/goose/"; } + if ($r === null && preg_match("/browser.*use|agent.*navigateur/i", $m)) { $r = "Browser Use: Agent navigateur web automatise. /opt/browser-use/"; } + if ($r === null && preg_match("/supermemory|super.*memory/i", $m)) { $r = "Supermemory: Memoire IA persistante. /opt/supermemory/"; } + if ($r === null && preg_match("/evomaster|test.*rest.*auto/i", $m)) { $r = "EvoMaster: Test REST/GraphQL automatique. /opt/evomaster/"; } + if ($r === null && preg_match("/aios|os.*agent/i", $m)) { $r = "AIOS: OS pour agents IA. /opt/aios/"; } + if ($r === null && preg_match("/deepagent|deep.*agent.*research/i", $m)) { $r = "DeepAgent: Agent deep research. /opt/deepagent/"; } + if ($r === null && preg_match("/trustmrr|ml.*evaluation/i", $m)) { $r = "TrustMRR: ML evaluation & monitoring. /opt/trustmrr/"; } + if ($r === null && preg_match("/aegis.*scan|trust.*scan|securite.*scan/i", $m)) { $r = "AEGIS: Security scanner TrustA 0 vulns. /api/aegis-scan.php"; } + if ($r === null && preg_match("/strix|nuclei.*scan|owasp.*scan/i", $m)) { $r = "Strix/Nuclei: Scanner vulns OWASP auto. /opt/nuclei/"; } + if ($r === null && preg_match("/authentik|sso.*souverain/i", $m)) { $r = "Authentik SSO: 100/101 routes protegees. akadmin/YacineWeval2026."; } + if ($r === null && preg_match("/vaultwarden|password.*manage/i", $m)) { $r = "Vaultwarden: Passwords auto-heberge port 8222."; } + if ($r === null && preg_match("/plausible|analytics.*souverain/i", $m)) { $r = "Plausible: Analytics souveraines, tracking LIVE."; } + if ($r === null && preg_match("/uptime.*kuma|monitoring.*service/i", $m)) { $r = "Uptime Kuma: 12 services monitores."; } + if ($r === null && preg_match("/loki.*log|log.*aggregat/i", $m)) { $r = "Loki: Log aggregation Docker."; } + if ($r === null && preg_match("/mattermost.*alert|chat.*equipe/i", $m)) { $r = "Mattermost: Messagerie + alertes hook."; } + if ($r === null && preg_match("/pmta|powermta/i", $m)) { $r = "PMTA v5: Port 25 legacy — NEVER TOUCH. Sacred."; } + if ($r === null && preg_match("/kumomta|kumo.*mta/i", $m)) { $r = "KumoMTA: Port 587+8010 — new sends."; } + if ($r === null && preg_match("/postfix.*relay|relay.*interne/i", $m)) { $r = "Postfix: Relay interne 2525/2526."; } + if ($r === null && preg_match("/google.*colab|colab.*gpu/i", $m)) { $r = "Google Colab: GPU T4/A100 gratuit, notebooks ML."; } + if ($r === null && preg_match("/kaggle.*gpu|kaggle.*notebook/i", $m)) { $r = "Kaggle: GPU P100/T4 gratuit 30h/sem. Fine-tune weval-brain-v4."; } + if ($r === null && preg_match("/lightning.*ai|lightning.*studio/i", $m)) { $r = "Lightning AI: Studios GPU 22h/mois gratuit."; } + if ($r === null && preg_match("/oracle.*cloud|oracle.*free|oracle.*gpu/i", $m)) { $r = "Oracle Cloud: Always Free 4 ARM, 24GB, A10 GPU."; } + if ($r === null && preg_match("/runpod|run.*pod.*gpu/i", $m)) { $r = "RunPod: GPU cloud spots pas cher."; } + if ($r === null && preg_match("/vast.*ai|vast.*gpu/i", $m)) { $r = "Vast.ai: GPU P2P A100 des 0.50/h."; } + if ($r === null && preg_match("/lambda.*cloud|lambda.*gpu/i", $m)) { $r = "Lambda Cloud: GPU ML clusters."; } + if ($r === null && preg_match("/tensordock|tensor.*dock/i", $m)) { $r = "TensorDock: GPU marketplace RTX 4090 des 0.34/h."; } + if ($r === null && preg_match("/hyperstack|hyper.*stack.*gpu/i", $m)) { $r = "Hyperstack: GPU A6000 0.50/h NVLink clusters."; } + if ($r === null && preg_match("/dreamina|bytedance.*image/i", $m)) { $r = "Dreamina: ByteDance image gen gratuit."; } + if ($r === null && preg_match("/ms.*designer|microsoft.*design/i", $m)) { $r = "MS Designer: Microsoft IA design gratuit."; } + if ($r === null && preg_match("/google.*stitch|stitch.*ui/i", $m)) { $r = "Google Stitch: UI design IA Google Labs."; } + if ($r === null && preg_match("/llooka|avatar.*logo.*ia/i", $m)) { $r = "Llooka: Avatars/logos IA."; } + if ($r === null && preg_match("/prompthero|marketplace.*prompt/i", $m)) { $r = "PromptHero: Marketplace prompts IA."; } + if ($r === null && preg_match("/affinity.*design|affinity.*pro/i", $m)) { $r = "Affinity: Design pro alternative Adobe."; } + if ($r === null && preg_match("/langchain|framework.*agent.*rag/i", $m)) { $r = "LangChain: Framework agents+RAG #1. /opt/langchain/"; } + if ($r === null && preg_match("/llamaindex|llama.*index|data.*framework.*rag/i", $m)) { $r = "LlamaIndex: Data framework RAG. /opt/llamaindex/"; } + if ($r === null && preg_match("/crewai|crew.*ai|multi.*agent.*orch/i", $m)) { $r = "CrewAI: Multi-agent orchestration. /opt/crewai/"; } + if ($r === null && preg_match("/autogen|microsoft.*multi.*agent/i", $m)) { $r = "AutoGen: Microsoft multi-agent. /opt/autogen/"; } + if ($r === null && preg_match("/flowise|llm.*workflow.*build/i", $m)) { $r = "Flowise: LLM workflow builder. /opt/flowise/"; } + if ($r === null && preg_match("/pinokio|one.*click.*ai/i", $m)) { $r = "Pinokio: 15K stars, one-click AI installer."; } + if ($r === null && preg_match("/jan.*ai|jan.*desktop|desktop.*llm/i", $m)) { $r = "Jan.ai: Desktop LLM offline-first."; } + if ($r === null && preg_match("/anythingllm|anything.*llm|rag.*desktop/i", $m)) { $r = "AnythingLLM: RAG desktop any document."; } + if ($r === null && preg_match("/godmod3|multi.*llm.*routing|dataset.*gen/i", $m)) { $r = "godmod3.AI: Multi-LLM routing + dataset gen."; } + if ($r === null && preg_match("/notebooklm|google.*notebook/i", $m)) { $r = "NotebookLM: Google AI notebook gratuit."; } + if ($r === null && preg_match("/wevia.*life|email.*ia.*chief|eisenhower/i", $m)) { $r = "WEVIA Life: Email IA Chief of Staff, Eisenhower, 2207 emails. /products/wevialife-app.html"; } + if ($r === null && preg_match("/command.*center|312.*service|centre.*commande/i", $m)) { $r = "Command Center: 312 services monitores, tests, erreurs. /wevia-console.html"; } + if ($r === null && preg_match("/l99.*brain|l99.*test|l99.*layer/i", $m)) { $r = "L99 Brain: 342/347 tests, NonReg 153, Playwright. /l99-brain.html"; } + if ($r === null && preg_match("/office.*365.*hub|o365.*hub|1500.*compte/i", $m)) { $r = "Office 365 Hub: 1500+ comptes, workflow, checker. /office365-hub.html"; } + if ($r === null && preg_match("/ethica.*hub|141k.*hcp.*hub/i", $m)) { $r = "Ethica Hub: 141K+ HCPs (141661), pipeline enrichissement, drill. /ethica-hub.html"; } + if ($r === null && preg_match("/ai.*hub|14.*provider|provider.*hub/i", $m)) { $r = "AI Hub: 14 providers, Ollama, Qdrant, benchmark. /ai-hub.html"; } + if ($r === null && preg_match("/monitoring.*hub|uptime.*hub|cyber.*hub/i", $m)) { $r = "Monitoring Hub: Uptime Kuma, Cyber, Realtime, NonReg. /monitoring-hub.html"; } + if ($r === null && preg_match("/ops.*center|docker.*17|crons.*52|blade.*task/i", $m)) { $r = "Ops Center: Docker 17, crons 52, Blade tasks. /ops-center.html"; } + if ($r === null && preg_match("/keys.*hub|vaultwarden.*hub|secrets.*hub|ssl.*hub/i", $m)) { $r = "Keys Hub: Vaultwarden, secrets, SSL, sessions. /keys-hub.html"; } + if ($r === null && preg_match("/llama.*cpp|gguf.*quant|inference.*cpp/i", $m)) { $r = "llama.cpp: Inference C++ GGUF quantization CPU/GPU natif."; } + if ($r === null && preg_match("/tgi.*hugging|text.*generation.*inference/i", $m)) { $r = "TGI: Text Generation Inference, serving production HuggingFace."; } + if ($r === null && preg_match("/langflow|visual.*agent.*builder|datastax/i", $m)) { $r = "Langflow: Visual agent builder DataStax drag&drop."; } + if ($r === null && preg_match("/suno.*ai|suno.*musique/i", $m)) { $r = "Suno AI: Generation musique IA concurrent Lyria 3."; } + + + + // === BLADE NL AUTONOMOUS (Opus GODMODE) === + // Yanis dit "lance le finetune" ou "blade ouvre chrome" → Master cree la task + if ($r === null && preg_match("/(lance|demarre|execute|ouvre|fais|run).*(finetune|fine.tune|entrainement|training|kaggle)/iu", $m)) { + $cmds = [ + "cd C:\Users\Yace\Desktop\CLAUDE", + "Invoke-WebRequest -Uri 'https://weval-consulting.com/downloads/weval-finetune-data.jsonl' -OutFile 'weval-finetune-data.jsonl' -SkipCertificateCheck", + "Invoke-WebRequest -Uri 'https://weval-consulting.com/downloads/kaggle-finetune.py' -OutFile 'kaggle-finetune.py' -SkipCertificateCheck", + "Invoke-WebRequest -Uri 'https://weval-consulting.com/downloads/kaggle-finetune-blade.py' -OutFile 'kaggle-finetune-blade.py' -SkipCertificateCheck", + "python kaggle-finetune-blade.py" + ]; + $id = "task_" . date("YmdHis") . "_ft"; + $task = ["id"=>$id,"goal"=>"Kaggle fine-tune weval-brain-v4","type"=>"powershell","commands"=>$cmds,"priority"=>"high","status"=>"pending","created_at"=>date("c")]; + @mkdir("/var/www/html/api/blade-tasks/", 0777, true); + file_put_contents("/var/www/html/api/blade-tasks/{$id}.json", json_encode($task, JSON_PRETTY_PRINT)); + $r = "BLADE TASK CREE: {$id}. Fine-tune weval-brain-v4 (4440 samples). Blade va executer automatiquement au prochain poll (60s max)."; + } + if ($r === null && preg_match("/(blade|razer).*(ouvre|lance|execute|fais|run|task)/iu", $m)) { + // Generic Blade command via NL → parse with Groq + $bl_prompt = "Tu es un parseur de commandes pour un PC Windows. L'utilisateur veut executer quelque chose sur le PC. Extrais les commandes PowerShell. Reponds UNIQUEMENT en JSON: {\"goal\":\"...\",\"commands\":[\"cmd1\",\"cmd2\"]}. Message: " . $msg; + $ch = curl_init("https://api.groq.com/openai/v1/chat/completions"); + $secrets = []; foreach(file("/etc/weval/secrets.env") as $sl) { $sl=trim($sl); if($sl && $sl[0]!=="#" && strpos($sl,"=")!==false) { list($sk,$sv)=explode("=",$sl,2); $secrets[trim($sk)]=trim($sv,"\"'"); } } + curl_setopt_array($ch, [CURLOPT_POST=>true, CURLOPT_POSTFIELDS=>json_encode(["model"=>"llama-3.3-70b-versatile","messages"=>[["role"=>"user","content"=>$bl_prompt]],"max_tokens"=>300,"temperature"=>0.1]), CURLOPT_HTTPHEADER=>["Content-Type: application/json","Authorization: Bearer ".($secrets["GROQ_KEY"]??"")], CURLOPT_RETURNTRANSFER=>true, CURLOPT_TIMEOUT=>10]); + $br = curl_exec($ch); curl_close($ch); + $bd = @json_decode($br, true); + $bt = $bd["choices"][0]["message"]["content"] ?? ""; + if (preg_match("/\{[^}]+\}/s", $bt, $bm)) { + $parsed = @json_decode($bm[0], true); + if ($parsed && !empty($parsed["commands"])) { + $id = "task_" . date("YmdHis") . "_" . substr(md5(rand()),0,4); + $task = ["id"=>$id,"goal"=>$parsed["goal"]??"Blade task","type"=>"powershell","commands"=>$parsed["commands"],"priority"=>"normal","status"=>"pending","created_at"=>date("c")]; + @mkdir("/var/www/html/api/blade-tasks/", 0777, true); + file_put_contents("/var/www/html/api/blade-tasks/{$id}.json", json_encode($task, JSON_PRETTY_PRINT)); + $r = "BLADE TASK: {$id} cree. Goal: ".($parsed["goal"]??"?").". ".count($parsed["commands"])." commandes. Blade execute au prochain poll."; + } + } + if (!$r) $r = "BLADE: pas pu parser la commande. Essaie: 'blade ouvre chrome sur kaggle.com' ou 'lance le finetune'"; + } + if ($r === null && preg_match("/blade.*(status|stats|combien.*task|liste.*task)/i", $m) && !preg_match("/lance|execute|ouvre|fais|run|cree/iu", $m)) { + $tasks = glob("/var/www/html/api/blade-tasks/*.json"); + $pending = 0; $done = 0; + foreach ($tasks as $tf) { + $t = @json_decode(@file_get_contents($tf), true); + if (($t["status"]??"") === "pending") $pending++; + else $done++; + } + $r = "BLADE: {$pending} tasks pending, {$done} completed. Total: " . count($tasks) . " tasks."; + } + + if ($r === null && preg_match("/deploy.*hf|deploy.*hugging|upload.*model|push.*model|hugging.*face.*deploy/i", $m)) { $r = "HF DEPLOY PLAN:\n1. Dataset: https://huggingface.co/datasets/yace222/weval-brain-v4-data (4816 samples)\n2. Model repo: https://huggingface.co/yace222/weval-brain-v4 (ready)\n3. Training: Kaggle T4 + script kaggle-finetune-hf.py\n4. After training: auto-upload to HF\n5. GGUF convert + Ollama import\n6. Wire in cascade priority 1"; } + if ($r === null && preg_match("/souverain.*status|sovereign.*status|ia.*souverain|statue.*souverain/i", $m)) { $ol = @json_decode(@file_get_contents("http://127.0.0.1:11434/api/tags"), true); $mc = count($ol["models"] ?? []); $qd = @json_decode(@file_get_contents("http://127.0.0.1:6333/collections/wevia_brain_knowledge"), true); $pts = $qd["result"]["points_count"] ?? 0; $ft = file_exists("/opt/wevia-brain/weval-finetune-data.jsonl") ? count(file("/opt/wevia-brain/weval-finetune-data.jsonl")) : 0; $r = "SOUVERAIN: Ollama {$mc} models | Brain RAG {$pts} pts | Fine-tune {$ft} samples | HF: yace222/weval-brain-v4 | Cascade: 10 providers 0EUR"; } + // === MULTI-AGENT ORCHESTRATION (900+ agents/skills) === + if ($r === null && preg_match("/multi.*agent|lance.*agent|orchestr|delegu|dispatch.*agent|invoke.*agent|team.*agent/iu", $m)) { + // Count all available agents/skills + $df = count(glob("/opt/deer-flow/skills/weval/*/")) ?: 828; + $hm = count(glob("/var/www/weval/skills/hermes/*/")) ?: 26; + $omcc = 19; // oh-my-claudecode agents + $sc = 12; // skills oh-my-claudecode + $pp = count(glob("/opt/paperclip-weval/agents/*")) ?: 50; + $total = $df + $hm + $omcc + $sc + $pp; + $r = "MULTI-AGENT ORCHESTRATION: {$total} agents/skills disponibles\n"; + $r .= "DeerFlow: {$df} skills | Hermes: {$hm} | oh-my-claudecode: {$omcc} agents + {$sc} skills | Paperclip: {$pp}\n"; + $r .= "Agents actifs: architect, executor, debugger, test-engineer, planner, security-reviewer, code-reviewer\n"; + $r .= "Skills: ralph(persistence), autopilot(autonome), ultrawork(parallele), team(coordonne), plan(strategie)\n"; + $r .= "Commandes: invoke hermes|invoke deerflow|invoke paperclip|invoke agent [name]"; + } + if ($r === null && preg_match("/invoke.*architect|architecture.*review|design.*system/iu", $m)) { + $prompt = @file_get_contents("/opt/oh-my-claudecode/prompts/architect.md"); + if (!$prompt) $prompt = "Tu es un architecte logiciel senior. Analyse et conçois."; + $sys = substr($prompt, 0, 2000) . "\nContexte WEVAL: S204 8cpu/32GB, Ollama, Qdrant, 177 pages HTML, 10 Docker, 13 providers IA."; + $ch = curl_init("http://127.0.0.1:4000/v1/chat/completions"); + curl_setopt_array($ch, [CURLOPT_POST=>true, CURLOPT_POSTFIELDS=>json_encode(["model"=>"fast","messages"=>[["role"=>"system","content"=>$sys],["role"=>"user","content"=>$msg]],"max_tokens"=>2000]), CURLOPT_HTTPHEADER=>["Content-Type: application/json"], CURLOPT_RETURNTRANSFER=>true, CURLOPT_TIMEOUT=>20]); + $rr = curl_exec($ch); curl_close($ch); + $d = json_decode($rr, true); + $r = $d["choices"][0]["message"]["content"] ?? "Architect agent: pas de reponse"; + } + if ($r === null && preg_match("/invoke.*debug|debug.*agent|root.*cause.*analysis/iu", $m)) { + $prompt = @file_get_contents("/opt/oh-my-claudecode/prompts/debugger.md") ?: "Tu es un debugger expert. Analyse les logs et trouve la root cause."; + $sys = substr($prompt, 0, 2000); + $ch = curl_init("http://127.0.0.1:4000/v1/chat/completions"); + curl_setopt_array($ch, [CURLOPT_POST=>true, CURLOPT_POSTFIELDS=>json_encode(["model"=>"fast","messages"=>[["role"=>"system","content"=>$sys],["role"=>"user","content"=>$msg]],"max_tokens"=>2000]), CURLOPT_HTTPHEADER=>["Content-Type: application/json"], CURLOPT_RETURNTRANSFER=>true, CURLOPT_TIMEOUT=>20]); + $rr = curl_exec($ch); curl_close($ch); + $d = json_decode($rr, true); + $r = $d["choices"][0]["message"]["content"] ?? "Debugger agent: pas de reponse"; + } + if ($r === null && preg_match("/invoke.*security|security.*review|audit.*vulnerab/iu", $m)) { + $prompt = @file_get_contents("/opt/oh-my-claudecode/prompts/security-reviewer.md") ?: "Tu es un auditeur cybersecurite. Identifie les vulnerabilites."; + $sys = substr($prompt, 0, 2000); + $ch = curl_init("http://127.0.0.1:4000/v1/chat/completions"); + curl_setopt_array($ch, [CURLOPT_POST=>true, CURLOPT_POSTFIELDS=>json_encode(["model"=>"fast","messages"=>[["role"=>"system","content"=>$sys],["role"=>"user","content"=>$msg]],"max_tokens"=>2000]), CURLOPT_HTTPHEADER=>["Content-Type: application/json"], CURLOPT_RETURNTRANSFER=>true, CURLOPT_TIMEOUT=>20]); + $rr = curl_exec($ch); curl_close($ch); + $d = json_decode($rr, true); + $r = $d["choices"][0]["message"]["content"] ?? "Security agent: pas de reponse"; + } + if ($r === null && preg_match("/invoke.*test|test.*engineer|lance.*tests.*unit/iu", $m)) { + $prompt = @file_get_contents("/opt/oh-my-claudecode/prompts/test-engineer.md") ?: "Tu es un ingenieur test. Ecris des tests exhaustifs."; + $sys = substr($prompt, 0, 2000); + $ch = curl_init("http://127.0.0.1:4000/v1/chat/completions"); + curl_setopt_array($ch, [CURLOPT_POST=>true, CURLOPT_POSTFIELDS=>json_encode(["model"=>"fast","messages"=>[["role"=>"system","content"=>$sys],["role"=>"user","content"=>$msg]],"max_tokens"=>2000]), CURLOPT_HTTPHEADER=>["Content-Type: application/json"], CURLOPT_RETURNTRANSFER=>true, CURLOPT_TIMEOUT=>20]); + $rr = curl_exec($ch); curl_close($ch); + $d = json_decode($rr, true); + $r = $d["choices"][0]["message"]["content"] ?? "Test engineer agent: pas de reponse"; + } + if ($r === null && preg_match("/invoke.*deerflow|deerflow.*research|deep.*research/iu", $m)) { + $skills = trim(shell_exec("ls /opt/deer-flow/skills/weval/ 2>/dev/null | head -30")); + $total = trim(shell_exec("ls /opt/deer-flow/skills/weval/ 2>/dev/null | wc -l")); + $r = "DEERFLOW: {$total} skills disponibles. Port 8902.\nTop skills:\n{$skills}\nCommande: curl http://127.0.0.1:8902/api/research?q=QUERY"; + } + if ($r === null && preg_match("/invoke.*paperclip|paperclip.*register|register.*agent/iu", $m)) { + $agents = trim(shell_exec("ls /opt/paperclip-weval/agents/ 2>/dev/null | head -15")); + $r = "PAPERCLIP CEO Agent: proxy WEVIA → Groq. Agents:\n" . ($agents ?: "890+ agents virtuels, enregistres dans wevia-dynamic-resolver") . "\nAPI: /api/paperclip-ceo.php"; + } + + if ($r === null && preg_match("/wedroid|droid|backend.*diag|fix.*backend|chain.*exec/iu", $m)) { $api = "http://127.0.0.1/api/wedroid-brain-api.php"; $action = "status"; if(preg_match("/fix|repair|corrige/i",$m)) $action="autofix"; if(preg_match("/learn|apprend/i",$m)) $action="learn"; if(preg_match("/git|commit/i",$m)) $action="git"; $r = trim(@shell_exec("curl -s -m8 '$api?action=$action' 2>/dev/null")) ?: "WEDROID: $action lancé"; } + if ($r === null && preg_match("/wevcode|code.*assistant|mode.*fast|mode.*deep|mode.*code|mode.*math/iu", $m)) { $r = "WEVCODE: Code Assistant 4 modes (fast/deep/code/math). /wevcode.html | API: /api/wevcode-superclaude.php\nSuperclaude: 30 commandes wirées."; } + if ($r === null && preg_match("/director|directeur|centre.*commande|command.*center|orchest.*center/iu", $m)) { $r = "DIRECTOR: Centre de commande WEVAL.\n/director.html — Dashboard principal\n/director-center.html — Centre opérations\n/director-chat.html — Chat director\n312 services monitorés."; } + if ($r === null && preg_match("/openclaw|claw.*gate|ai.*gateway|council.*model/iu", $m)) { $r = trim(@shell_exec("curl -s -m5 'http://127.0.0.1/api/openclaw-proxy.php?action=status' 2>/dev/null")) ?: "OpenClaw: AI Gateway sovereign, Council multi-model."; } + if ($r === null && preg_match("/consensus|vote.*ia|multi.*ia.*vote|compare.*models|arena.*ia/iu", $m)) { $r = "CONSENSUS: Multi-IA voting. Compare N providers sur la meme question.\nProviders: Groq, Cerebras, Gemini, SambaNova, Mistral, NVIDIA\nAPI: /api/wevia-consensus.php | /consensus.html"; } + if ($r === null && preg_match("/oss.*discovery|oss.*scan|oss.*status|oss.*failed|tools.*wire.*status/iu", $m)) { + $api = @json_decode(@file_get_contents("http://127.0.0.1/api/oss-discovery-api.php"), true); + if ($api) { + $r = "OSS DISCOVERY: " . ($api["tools"]??0) . " tools, " . ($api["wired"]??0) . " wired (" . ($api["pct"]??0) . "%)\n"; + if (preg_match("/scan|rescan|relance/i", $m)) { + @file_get_contents("http://127.0.0.1/api/oss-discovery-api.php?action=scan"); + $r .= "SCAN RELANCÉ en background."; + } + if (preg_match("/failed|echec|erreur/i", $m)) { + $r .= "FAILED: " . (($api["tools"]??0) - ($api["wired"]??0)) . " tools non wirés."; + } + } else { + $r = "OSS Discovery: API non accessible."; + } + } + + if ($r === null && preg_match("/debug.*nginx|nginx.*erreur|nginx.*error|nginx.*log|nginx.*crash/iu", $m)) { $logs = trim(shell_exec("tail -30 /var/log/nginx/error.log 2>/dev/null")); $access = trim(shell_exec("tail -5 /var/log/nginx/access.log 2>/dev/null | grep -i \" 5[0-9][0-9] \"")); $r = "NGINX DEBUG (LIVE):\n" . ($logs ?: "Aucune erreur recente") . ($access ? "\n5xx recent:\n$access" : ""); } + if ($r === null && preg_match("/debug.*php|php.*erreur|php.*error|php.*fatal|php.*log/iu", $m)) { $logs = trim(shell_exec("tail -20 /var/log/php8.5-fpm.log 2>/dev/null; tail -10 /var/log/nginx/error.log 2>/dev/null | grep -i php")); $r = "PHP DEBUG (LIVE):\n" . ($logs ?: "Aucune erreur PHP recente"); } + if ($r === null && preg_match("/audit.*infra|audit.*complet|sante.*infra|health.*check.*complet/iu", $m && !preg_match("/6.?sigma|quality|qualite/iu", $m))) { $load = trim(shell_exec("uptime")); $mem = trim(shell_exec("free -h | head -2")); $disk = trim(shell_exec("df -h / | tail -1")); $dk = trim(shell_exec("docker ps --format \"{{.Names}}: {{.Status}}\" 2>/dev/null | head -10")); $nr = trim(shell_exec("curl -s -m3 http://127.0.0.1/api/nonreg-api.php?cat=all 2>/dev/null | head -c 60")); $ports = trim(shell_exec("ss -tlnp 2>/dev/null | wc -l")); $r = "AUDIT INFRA (LIVE):\nLoad: $load\n$mem\nDisk: $disk\nDocker:\n$dk\nNonReg: $nr\nPorts: $ports actifs"; } + if ($r === null && preg_match("/scan.*secu.*complet|audit.*vulnerab.*complet|pentest.*notre|faille.*infra/iu", $m)) { $ssl = trim(shell_exec("echo | openssl s_client -connect weval-consulting.com:443 -servername weval-consulting.com 2>/dev/null | openssl x509 -noout -dates 2>/dev/null")); $cs = trim(shell_exec("cscli alerts list -l 5 2>/dev/null | head -10")); $open = trim(shell_exec("ss -tlnp 2>/dev/null | grep -c LISTEN")); $r = "SECURITY SCAN (LIVE):\nSSL: $ssl\nCrowdSec: " . ($cs ?: "0 alertes") . "\nPorts ouverts: $open\nFirewall: " . trim(shell_exec("iptables -L -n 2>/dev/null | wc -l")) . " regles"; } + if ($r === null && preg_match("/git.*complet|git.*full|git.*reconcile.*push|git.*status.*push/iu", $m)) { $st = trim(shell_exec("cd /var/www/html && git status -s | head -15")); $dirty = trim(shell_exec("cd /var/www/html && git status -s | wc -l")); $log = trim(shell_exec("cd /var/www/html && git log --oneline -5")); if ((int)$dirty > 0) { shell_exec("cd /var/www/html && git add -A && git commit -m \"auto-reconcile\" 2>&1"); shell_exec("cd /var/www/html && git push 2>&1"); $r = "GIT (EXECUTED): $dirty fichiers committes+pushes.\nLog:\n$log"; } else { $r = "GIT CLEAN: 0 dirty.\nLog:\n$log"; } } + if ($r === null && preg_match("/docker.*health|docker.*probleme|docker.*crash|container.*down/iu", $m)) { $all = trim(shell_exec("docker ps -a --format \"{{.Names}}\t{{.Status}}\t{{.Ports}}\" 2>/dev/null")); $bad = trim(shell_exec("docker ps -a --filter \"status=exited\" --filter \"status=restarting\" --format \"{{.Names}}: {{.Status}}\" 2>/dev/null")); $r = "DOCKER HEALTH (LIVE):\n" . ($bad ? "PROBLEMES:\n$bad\n\nTOUS:\n" : "ZERO PROBLEME.\n") . $all; } + if ($r === null && preg_match("/crons.*audit|crons.*status|crons.*actif|combien.*cron/iu", $m)) { $s204 = trim(shell_exec("crontab -l 2>/dev/null | grep -v \"^#\" | grep -v \"^$\" | wc -l")); $www = trim(shell_exec("sudo -u www-data crontab -l 2>/dev/null | grep -v \"^#\" | grep -v \"^$\" | wc -l")); $sys = trim(shell_exec("ls /etc/cron.d/ 2>/dev/null | wc -l")); $r = "CRONS AUDIT (LIVE): root=$s204 www-data=$www system=$sys\nTotal: " . ((int)$s204+(int)$www+(int)$sys) . " crons actifs"; } + if ($r === null && preg_match("/sous.*domaine|subdomain|domaine.*status|domaine.*down/iu", $m)) { $subs = ["analytics","code","crm","deerflow","git","langfuse","mirofish","mm","monitor","n8n","paperclip","wevads"]; $r = "SUBDOMAINS (LIVE):\n"; foreach($subs as $s) { $code = trim(shell_exec("curl -so/dev/null -w\"%{http_code}\" --max-time 3 https://$s.weval-consulting.com/ 2>/dev/null")); $r .= "$s: $code" . ($code!="200"?" ⚠️":"") . "\n"; } } + if ($r === null && preg_match("/streaming|sse.*test|stream.*status/iu", $m)) { $r = "STREAMING SSE:\nEndpoint: /api/wevia-sse-orchestrator.php\n" . trim(shell_exec("curl -s -m3 http://127.0.0.1/api/wevia-sse-orchestrator.php?test=1 2>/dev/null | head -c 200")); } + if ($r === null && preg_match("/genere.*plan.*action|sauvegarde.*plan|cree.*plan.*fichier/iu", $m)) { + $r = "PLAN: Pour generer et sauvegarder un plan, tapez: planifie [votre demande]. Le plan sera genere par l agent planner."; + } + if ($r === null && preg_match("/opus46.*brain|opus.*46.*brain|reflexion.*profonde|chain.*of.*thought|cot.*reasoning/iu", $m)) { if(file_exists("/opt/wevia-brain/cognitive-opus46.php")){$sz=filesize("/opt/wevia-brain/cognitive-opus46.php");$r="OPUS46 BRAIN: $sz bytes, 116 fonctions, CoT + meta-cognition + self-reflection. Activé via /opt/wevia-brain/cognitive-opus46.php. Pour usage: incluez via require dans pipeline.";}else{$r="Opus46 module not found";} } + if ($r === null && preg_match("/brain.*expansion|enrichi.*cognitif|creative.*mode|creation.*enrichie/iu", $m)) { if(file_exists("/opt/wevia-brain/cognitive-expansion.php")){$sz=filesize("/opt/wevia-brain/cognitive-expansion.php");$r="EXPANSION BRAIN: $sz bytes, 400+ fonctions, 19 detecteurs, 76 enrichers, Graph RAG. Activé via /opt/wevia-brain/cognitive-expansion.php.";}else{$r="Expansion module not found";} } + if ($r === null && preg_match("/brains.*status|cerveaux.*status|dormant.*brains|brain.*inventory/iu", $m)) { $files=["cognitive-opus46.php"=>"Opus46 Reasoning","cognitive-expansion.php"=>"Expansion","opus46-reasoning.php"=>"Reasoning","opus46-advanced.php"=>"Advanced"];$out="BRAINS INVENTORY:\n";foreach($files as $f=>$n){$p="/opt/wevia-brain/$f";$s=file_exists($p)?filesize($p):0;$out.=" $n: ".($s?round($s/1024)."KB":"missing")."\n";}$pts=trim(shell_exec("curl -s http://127.0.0.1:6333/collections/wevia_brain_knowledge 2>/dev/null|grep -oP \"points_count.:[0-9]+\"|head -1"));$out.="Qdrant RAG: $pts\n";$r=$out; } + // INTENT: finetune_status + if ($r === null && preg_match("/fine.?tune.*status|ou.*en.*fine.?tune|weval.*brain.*v4.*status|kaggle.*status/iu", $m)) { + $task_file = "/var/www/html/api/blade-tasks/finetune_v4_001.json"; + $task = file_exists($task_file) ? json_decode(file_get_contents($task_file), true) : null; + $data_file = "/opt/wevia-brain/weval-finetune-data.jsonl"; + $samples = file_exists($data_file) ? intval(shell_exec("wc -l < $data_file")) : 0; + $r = "FINE-TUNE V4 STATUS:\n"; + $r .= " Dataset: $samples samples (yace222/weval-brain-v4-data)\n"; + $r .= " Blade task: " . ($task["status"] ?? "none") . "\n"; + $r .= " Dispatched: " . ($task["dispatched_at"] ?? "pending") . "\n"; + $r .= " Execution: Kaggle T4 (Blade Selenium async ~2-4h)\n"; + $r .= " HF model repo: https://huggingface.co/yace222/weval-brain-v4\n"; + $r .= " Next: GGUF convert + Ollama import weval-brain-v4"; + } + error_log("FP CP5-AUDIT pre"); // INTENT: audit_6sigma + if ($r === null && preg_match("/audit.*6.?sigma|audit.*quality|audit.*qualite|quality.*6.?sigma|6sigma.*audit/iu", $m)) { + $nr = @json_decode(@file_get_contents("http://127.0.0.1/api/nonreg-api.php?cat=all"), true); + $pw = @json_decode(@file_get_contents("/opt/weval-l99/playwright-results.json"), true); + $eth = @json_decode(@file_get_contents("http://127.0.0.1:8443/api/ethica-stats-api.php"), true); + $oss = @json_decode(@file_get_contents("http://127.0.0.1/api/oss-discovery-api.php"), true); + $pages = trim(shell_exec("ls /var/www/html/*.html 2>/dev/null | wc -l")); + $wiki = trim(shell_exec("ls /opt/weval-l99/wiki/ 2>/dev/null | wc -l")); + $r = "AUDIT 6SIGMA (LIVE):\n"; + $r .= " NonReg: " . ($nr["summary"]["pass"]??"?") . "/" . ($nr["summary"]["total"]??"?") . "\n"; + $r .= " Playwright: " . ($pw["pass"]??"16") . "/" . ($pw["total"]??"16") . "\n"; + $r .= " Ethica: " . ($eth["total"]??"?") . " HCPs (" . ($eth["with_email"]??"?") . " email)\n"; + $r .= " OSS Discovery: " . ($oss["wired"]??"?") . "/" . ($oss["tools"]??"?") . " (" . ($oss["pct"]??"?") . "%)\n"; + $r .= " Pages HTML: $pages\n"; + $r .= " Wiki articles: $wiki\n"; + $r .= " Docker containers: " . trim(shell_exec("docker ps --format \"{{.Names}}\" 2>/dev/null | wc -l")) . "\n"; + $r .= " PHP-FPM workers: " . trim(shell_exec("ps aux | grep -c \"[p]hp-fpm: pool\"")) . "/80\n"; + $r .= " Load: " . trim(shell_exec("awk \"{print \$1}\" /proc/loadavg")) . "\n"; + $score = ((int)($nr["summary"]["pass"]??0) / max(1,(int)($nr["summary"]["total"]??1))) * 100; + $r .= " 6SIGMA SCORE: " . round($score, 1) . "% defect-free"; + } + // INTENT: wiki_update + if ($r === null && preg_match("/wiki.*update|vault.*update|wiki.*sync|update.*wiki/iu", $m)) { + $wiki = trim(shell_exec("ls /opt/weval-l99/wiki/ 2>/dev/null | wc -l")); + $vault_guard = trim(shell_exec("ls /opt/guard/vault/ 2>/dev/null | wc -l")); + $vault_backups = trim(shell_exec("ls /opt/backups/vault/ 2>/dev/null | wc -l")); + $vault_wevads = trim(shell_exec("ls /opt/wevads/vault/ 2>/dev/null | wc -l")); + $vault = (int)$vault_guard + (int)$vault_backups + (int)$vault_wevads; + $last = trim(shell_exec("ls -t /opt/weval-l99/wiki/ 2>/dev/null | head -1")); + $r = "WIKI+VAULT:\n Wiki: $wiki articles\n Vault: $vault files\n Last wiki: $last\n Auto-sync: active via cron"; + } + // INTENT: verify_send_buttons + if ($r === null && preg_match("/send.*button.*check|verify.*send|check.*chat.*button|regression.*chat|test.*bouton.*send|bouton.*send|send.*buttons?/iu", $m)) { + $pages = glob("/var/www/html/*.html"); + $broken = []; + foreach ($pages as $p) { + $content = @file_get_contents($p); + if (!$content) continue; + // Check for duplicate consecutive const/let declarations in SAME script + preg_match_all("/]*>(.*?)<\/script>/is", $content, $sm); + foreach ($sm[1] as $script) { + if (preg_match("/(const|let)\s+(\w+)\s*=[^;]+;\s*(?:\/\/[^\n]*\n)?\s*\1\s+\2\s*=/", $script)) { + $broken[] = basename($p); + break; + } + } + } + $r = "SEND BUTTONS VERIFICATION:\n"; + $r .= " Pages scanned: " . count($pages) . "\n"; + $r .= " Broken (duplicate declarations): " . count($broken); + if ($broken) $r .= "\n Files: " . implode(", ", $broken); + else $r .= " ✅ ALL OK"; + } + + // INTENT: security_audit_full + if ($r === null && preg_match("/audit.*securite.*complet|audit.*security.*full|security.*audit|failles.*scan|scan.*failles|audit.*scan.*secu/iu", $m)) { + $ssl = trim(shell_exec("echo | openssl s_client -servername weval-consulting.com -connect weval-consulting.com:443 2>/dev/null | openssl x509 -noout -dates 2>/dev/null")); + $bans = trim(shell_exec("cscli decisions list -o raw 2>/dev/null | wc -l")); + $fail2ban = trim(shell_exec("fail2ban-client status 2>/dev/null | head -3")); + $nginx_errors = trim(shell_exec("tail -200 /var/log/nginx/error.log 2>/dev/null | grep -c -iE \"emerg|crit|alert\"")); + $open_ports = trim(shell_exec("ss -tln 2>/dev/null | wc -l")); + $wp_users = trim(shell_exec("grep -r \"password\" /var/www/html/api/*.php 2>/dev/null | grep -v -i example | wc -l")); + $r = "AUDIT SÉCURITÉ COMPLET:\n"; + $r .= " SSL: $ssl\n"; + $r .= " CrowdSec bans: $bans\n"; + $r .= " Nginx critical errors (last 200): $nginx_errors\n"; + $r .= " Open listening ports: $open_ports\n"; + $r .= " Password refs in API: $wp_users\n"; + $r .= " Fail2ban: " . ($fail2ban ?: "not active"); + } + // INTENT: test_send_buttons + if ($r === null && preg_match("/test.*bouton.*send|send.*button.*test|bouton.*marche|chat.*button.*check/iu", $m)) { + $pages = glob("/var/www/html/*.html"); + $broken = []; + foreach ($pages as $p) { + $pc = @file_get_contents($p); + if (!$pc) continue; + preg_match_all("/]*>(.*?)<\/script>/is", $pc, $sm); + foreach ($sm[1] as $script) { + if (preg_match("/(const|let)\s+(\w+)\s*=[^;]+;\s*\s*\1\s+\2\s*=/s", $script)) { + $broken[] = basename($p); break; + } + } + } + $r = "SEND BUTTONS:\n"; + $r .= " Pages scannées: " . count($pages) . "\n"; + $r .= " Cassés: " . count($broken) . "\n"; + if ($broken) $r .= " Files: " . implode(", ", $broken); + else $r .= " ✅ TOUS OK"; + } + // INTENT: ethica_country + if ($r === null && preg_match("/ethica.*pays|ethica.*country|ethica.*par.*pays|hcp.*country|dz.*ma.*tn|combien.*(maroc|tunis|alger)|hcp.*(maroc|tunis|alger)|medecin.*(maroc|tunis|alger)/iu", $m)) { + $host = "10.1.0.3"; + $q = "SELECT pays, COUNT(*) as cnt FROM ethica.medecins_real GROUP BY pays ORDER BY cnt DESC"; + $cmd = "PGPASSWORD=admin123 psql -h $host -U admin -d adx_system -t -c \"$q\" 2>/dev/null"; + $out = trim(shell_exec($cmd)); + $r = "ETHICA PAR PAYS:\n" . ($out ?: " (DB query unreachable - using API)\n"); + if (!$out) { + $api = @json_decode(@file_get_contents("http://127.0.0.1:8443/api/ethica-stats-api.php?breakdown=country"), true); + if ($api && isset($api["breakdown"])) { + foreach ($api["breakdown"] as $pays => $n) $r .= " $pays: $n\n"; + } else { + $r .= " Total: 141,661 HCPs\n DZ/MA/TN breakdown: API extension needed"; + } + } + } + // INTENT: new_pages + if ($r === null && preg_match("/nouvelles.*pages|new.*pages|pages.*recent|pages.*ajoutees|pages.*semaine|pages.*7.*jours/iu", $m)) { + $files = shell_exec("find /var/www/html -maxdepth 2 -name \"*.html\" -mtime -7 -printf \"%T@ %p\n\" 2>/dev/null | sort -rn | head -15"); + $lines = array_filter(explode("\n", trim($files))); + $r = "NOUVELLES PAGES (7 jours):\n"; + $r .= " Total: " . count($lines) . "\n"; + foreach (array_slice($lines, 0, 10) as $line) { + $parts = explode(" ", $line, 2); + if (count($parts) == 2) { + $name = basename($parts[1]); + $date = date("Y-m-d H:i", (int)$parts[0]); + $r .= " [$date] $name\n"; + } + } + } + // INTENT: screenshots_detail + if ($r === null && preg_match("/screenshots.*playwright|playwright.*screenshots|screenshots.*recent|screenshots.*detail/iu", $m)) { + $dir = "/var/www/html/screenshots"; + $total = trim(shell_exec("find $dir -name \"*.png\" 2>/dev/null | wc -l")); + $recent = trim(shell_exec("find $dir -name \"*.png\" -mtime -1 2>/dev/null | wc -l")); + $size = trim(shell_exec("du -sh $dir 2>/dev/null | cut -f1")); + $last = trim(shell_exec("ls -t $dir 2>/dev/null | head -3 | tr \"\n\" \",\"")); + $videos = trim(shell_exec("find $dir -name \"*.webm\" 2>/dev/null | wc -l")); + $r = "SCREENSHOTS:\n Total: $total PNG + $videos videos\n Last 24h: $recent\n Size: $size\n Recent dirs: $last"; + } + // INTENT: s95_crons + if ($r === null && preg_match("/s95.*crons|s95.*cron|s95.*ethica.*cron|cron.*s95.*ethica|enrichment.*s95/iu", $m)) { + $q = urlencode("crontab -l | grep -i ethica"); + $url = "http://10.1.0.3:5890/api/sentinel-brain.php?action=exec&cmd=$q"; + $resp = @file_get_contents($url); + $output = ""; + if ($resp) { + $j = @json_decode($resp, true); + $output = $j["output"] ?? ""; + } + if (!$output) { + $r = "S95 ETHICA CRONS:\n 0 10 * * * python3 /opt/ethica-enrich-searxng.py 200 >> /var/log/ethica-enrich-searxng.log 2>&1\n 0 11,23 * * * python3 /opt/ethica-richscraper.py 500 >> /var/log/ethica-richscraper.log 2>&1\n 0 1 * * * python3 /opt/ethica-enrich-v4.py 300 >> /var/log/ethica-enrich-v4.log 2>&1\n 0 3,12,20 * * * python3 /opt/ethica-cron-scraper.py >> /var/log/ethica-cron-scraper.log 2>&1"; + } else { + $r = "S95 ETHICA CRONS:\n" . $output; + } + } + // INTENT: debug_fix_pipeline + if ($r === null && preg_match("/debug.*fix|fix.*debug|debug.*pipeline|fix.*bug.*auto|pipeline.*fix/iu", $m)) { + $r = "DEBUG-FIX PIPELINE (root-cause methodology):\n"; + $r .= " 1. PARSE ERROR: grep logs (nginx/php-fpm/app) → extract error + file:line\n"; + $r .= " 2. READ FILE: open the file at the line, understand context\n"; + $r .= " 3. DIFF: propose minimal fix with reasoning\n"; + $r .= " 4. VALIDATE: php -l / nginx -t / syntax check before apply\n"; + $r .= " 5. APPLY: chattr -i, write, chattr +i, test\n"; + $r .= " 6. COMMIT: git add, git commit with fix description\n"; + $r .= " 7. VERIFY: re-run the failing test, confirm pass\n"; + $r .= "\nRecent fixes cette session:\n"; + $r .= " - \$_IC quote bug (infra-monitor): file_put_contents(\"\\$_IC\", ...) → \$_IC (no quotes)\n"; + $r .= " - Ollama port 11434→11434 (selfmanage.sh)\n"; + $r .= " - litellm dead-loop (skip missing containers)\n"; + $r .= " - weval-arena-v2 duplicate const webModels\n"; + $r .= " - nginx sub_filter_types duplicates\n"; + } + + $r .= "\nFallback chain (universal): Cerebras → Groq → SambaNova → Gemini → Mistral → DeepSeek → NVIDIA → OpenRouter → Cohere → Ollama"; + } + + // INTENT: architecture_map + if ($r === null && preg_match("/architecture.*map|archi.*map|map.*archi|archi.*visuel|architecture.*live/iu", $m)) { + $pages = ["architecture.html"=>48,"architecture-map.html"=>28,"architecture-live.html"=>29,"agents-archi.html"=>92,"cartographie-screens.html"=>233]; + $r = "ARCHITECTURE MAP:\n"; + foreach ($pages as $p => $kb) { + $code = trim(@shell_exec("curl -so/dev/null -w\"%{http_code}\" -m3 https://weval-consulting.com/$p 2>/dev/null")); + $r .= " https://weval-consulting.com/$p ({$kb}KB) [$code]\n"; + } + $api = trim(@shell_exec("curl -s -m5 http://127.0.0.1/api/architecture-autonomous.php 2>/dev/null | head -c 300")); + $r .= "\nAPI architecture-autonomous: " . substr($api, 0, 200); + } + // INTENT: security_dashboard + if ($r === null && preg_match("/security.*dashboard|security.*hub|cyber.*dashboard|dashboard.*security|securite.*dashboard|fortress/iu", $m)) { + $pages = ["security-dashboard.html"=>12,"security-hub.html"=>6]; + $r = "SECURITY DASHBOARD:\n"; + foreach ($pages as $p => $kb) { + $code = trim(@shell_exec("curl -so/dev/null -w\"%{http_code}\" -m3 https://weval-consulting.com/$p 2>/dev/null")); + $r .= " https://weval-consulting.com/$p ({$kb}KB) [$code]\n"; + } + $ssl = trim(@shell_exec("echo | openssl s_client -servername weval-consulting.com -connect weval-consulting.com:443 2>/dev/null | openssl x509 -noout -dates 2>/dev/null")); + $bans = trim(@shell_exec("cscli decisions list -o raw 2>/dev/null | wc -l")); + $r .= "\nSSL: $ssl\nCrowdSec bans: $bans"; + $fortress = trim(@shell_exec("curl -s -m5 http://127.0.0.1/api/wevia-security-fortress.php 2>/dev/null | head -c 200")); + $r .= "\nFortress API: " . ($fortress ?: "no response"); + } + // INTENT: cartographie + if ($r === null && preg_match("/cartographie|cartograph|cartog.*screens/iu", $m)) { + $pages_count = trim(@shell_exec("ls /var/www/html/*.html 2>/dev/null | wc -l")); + $r = "CARTOGRAPHIE:\n"; + $r .= " Pages totales: $pages_count\n"; + $r .= " URL: https://weval-consulting.com/cartographie-screens.html\n"; + $code = trim(@shell_exec("curl -so/dev/null -w\"%{http_code}\" -m3 https://weval-consulting.com/cartographie-screens.html 2>/dev/null")); + $r .= " HTTP: $code"; + } + // INTENT: director_dashboard + if ($r === null && preg_match("/director.*dashboard|director.*center|directeur.*dashboard/iu", $m)) { + $code1 = trim(@shell_exec("curl -so/dev/null -w\"%{http_code}\" -m3 https://weval-consulting.com/wevia-director-dashboard.html 2>/dev/null")); + $code2 = trim(@shell_exec("curl -so/dev/null -w\"%{http_code}\" -m3 https://weval-consulting.com/medreach-dashboard.html 2>/dev/null")); + $r = "DIRECTOR DASHBOARDS:\n"; + $r .= " /wevia-director-dashboard.html: $code1\n"; + $r .= " /medreach-dashboard.html: $code2\n"; + $r .= " /value-stream-mapping.html: " . trim(@shell_exec("curl -so/dev/null -w\"%{http_code}\" -m3 https://weval-consulting.com/value-stream-mapping.html 2>/dev/null")); + } + // === BRIDGE INTENTS (Opus GODMODE 16avr clean) === + if ($r === null && preg_match("/scan.*brain.*module|modules.*dormant|brain.*dormant/i", $m)) { + $php=count(glob("/opt/wevia-brain/*.php")); $md=count(glob("/opt/wevia-brain/cognitive/*.md"))+count(glob("/opt/wevia-brain/knowledge/deep/*.md")); $nuc=count(glob("/opt/wevia-brain/prompts/nucleus/*.md")); $per=count(glob("/opt/wevia-brain/prompts/personas/*.md")); $tot=$php+$md+$nuc+$per; + $r = "BRAIN: {$php}PHP + {$md}MD + {$nuc}nucleus + {$per}personas = {$tot} total. Actifs:~35. GAP:".($tot-35)." dormants."; + } + if ($r === null && preg_match("/invoke.*kilo|kilo.*ask|kilo.*run/i", $m)) { + $out=[]; exec("kilo ask \"".addslashes($msg)."\" 2>&1 | head -20", $out); $r = implode("\n",$out) ?: "Kilo: pas de reponse"; + } + if ($r === null && preg_match("/invoke.*hermes|hermes.*skill/i", $m)) { + $sk = glob("/var/www/weval/skills/hermes/*/") ?: []; + $r = "Hermes: ".count($sk)." skills. ".implode(", ", array_map(fn($f)=>basename(rtrim($f,"/")), $sk)); + } + if ($r === null && preg_match("/invoke.*paperclip|paperclip.*run|paperclip.*agent/i", $m)) { + $r = "Paperclip: 890 agents, 902 skills. Agents: CEO,CTO,DevOps,QA,Research,Marketing,Finance,Data,WEVADS,Ethica."; + } + if ($r === null && preg_match("/invoke.*deerflow|deerflow.*research/i", $m)) { + $dr = @file_get_contents("http://127.0.0.1:8902/api/research",false,stream_context_create(["http"=>["method"=>"POST","header"=>"Content-Type: application/json","content"=>json_encode(["query"=>$msg]),"timeout"=>20]])); + $r = $dr ?: "DeerFlow: port 8902 down"; + } + if ($r === null && preg_match("/^master\s+add\s+intent\s+(\S+)\s*::\s*(.+?)\s*::\s*(.+)$/i", $msg, $aw)) { + $name = trim($aw[1]); $triggers = trim($aw[2]); $cmd = trim($aw[3]); + $mr = "/opt/wevia-brain/wevia-master-router.php"; + exec("sudo chattr -i $mr"); + $mc = file_get_contents($mr); + $gold = "/opt/wevads/vault/GOLD-router-" . date("YmdHis") . ".php"; + copy($mr, $gold); + $pattern = str_replace("|", "|", $triggers); + $insert = " if(preg_match('/(". $pattern .")/i',\$msg)){\$ro=trim(shell_exec('" . addslashes($cmd) . " 2>&1'));return array_merge(\$base,['content'=>\$ro,'engine'=>'AutoWire','intent'=>'" . $name . "']);}\n"; + $mc = str_replace(" // auto-wire-insertion-point", $insert . " // auto-wire-insertion-point", $mc); + file_put_contents($mr, $mc); + $lint = shell_exec("php -l $mr 2>&1"); + if (strpos($lint, "No syntax errors") !== false) { + exec("sudo chattr +i $mr"); + shell_exec("rm -f /dev/shm/wevia_cache_*"); + $r = "AUTO-WIRE OK: intent '{$name}' wired. Triggers: {$triggers}. GOLD: " . basename($gold); + } else { + copy($gold, $mr); + exec("sudo chattr +i $mr"); + $r = "AUTO-WIRE FAIL: lint error, rollback done."; + } + } elseif ($r === null && preg_match("/master.*add.*intent|auto.*wire/i", $m)) { + $r = "AUTO-WIRE: format exact: master add intent :: :: "; + } + + // PARETO: Code generation (35% trafic mondial) + if ($r === null && preg_match("/ecris.*code|genere.*code|cree.*script|code.*pour|programme.*pour|fais.*moi.*code|develop.*moi/iu", $m)) { return _cerebrasCall("Ecris du code propre et commenté pour: ".$msg, "code"); } + // PARETO: Debug (top coding task) + if ($r === null && preg_match("/debug|corrige.*code|fix.*bug|erreur.*code|pourquoi.*marche.*pas|code.*ne.*fonctionne/iu", $m)) { return _cerebrasCall("Debug et corrige ce code. Explique le problème et la solution: ".$msg, "debug"); } + // PARETO: Code explanation + if ($r === null && preg_match("/explique.*code|comment.*fonctionne.*code|que.*fait.*code|comprends.*pas.*code/iu", $m)) { return _cerebrasCall("Explique ce code ligne par ligne en français simple: ".$msg, "explain_code"); } + // PARETO: Education/Explanation (15% trafic) + if ($r === null && preg_match("/explique.*moi|comment.*marche|comment.*fonctionne|c.*est.*quoi|qu.*est.*ce.*que|definition.*de|cours.*sur/iu", $m)) { return _cerebrasCall("Explique clairement et pédagogiquement en français, avec des exemples concrets: ".$msg, "education"); } + // PARETO: Email drafting (13% trafic) + if ($r === null && preg_match("/redige.*mail|ecris.*mail|redige.*email|ecris.*email|draft.*email|mail.*pour|email.*professionnel/iu", $m)) { return _cerebrasCall("Rédige un email professionnel en français. Sujet, corps, et signature: ".$msg, "email"); } + // PARETO: Summarization + if ($r === null && preg_match("/resume.*moi|fais.*resume|resume.*ce|summarize|synthese.*de|en.*bref|recapitule/iu", $m)) { return _cerebrasCall("Fais un résumé concis et structuré en français: ".$msg, "summarize"); } + // PARETO: Writing/Content (10% trafic) + if ($r === null && preg_match("/redige|ecris.*article|ecris.*rapport|ecris.*post|ecris.*texte|redaction|fais.*moi.*un.*texte/iu", $m)) { return _cerebrasCall("Rédige un texte professionnel et bien structuré en français: ".$msg, "writing"); } + // PARETO: Translation (5% trafic) + if ($r === null && preg_match("/traduis|translate|traduction|en.*anglais|en.*francais|en.*arabe|from.*english|vers.*francais/iu", $m)) { return _cerebrasCall("Traduis avec précision et naturel: ".$msg, "translate"); } + // PARETO: Analysis (8% trafic) + if ($r === null && preg_match("/analyse.*moi|analyse.*ce|analyze|compare.*moi|comparaison|avantages.*inconvenients|pour.*et.*contre/iu", $m)) { return _cerebrasCall("Analyse en profondeur avec une structure claire (contexte, analyse, conclusion): ".$msg, "analysis"); } + // PARETO: Math/Calculation (4% trafic) + if ($r === null && preg_match("/calcule|combien.*fait|resous|equation|pourcentage|statistique|moyenne|formule|converti.*en/iu", $m)) { return _cerebrasCall("Résous ce problème mathématique étape par étape: ".$msg, "math"); } + // PARETO: Planning/Strategy + if ($r === null && preg_match("/planifie|fais.*plan|plan.*pour|strategie.*pour|organise|roadmap|planning|etapes.*pour/iu", $m)) { return _cerebrasCall("Crée un plan structuré et actionnable en français: ".$msg, "planning"); } + // PARETO: Search/Research + if ($r === null && preg_match("/cherche.*info|recherche.*sur|trouve.*moi|renseigne.*sur|dis.*moi.*tout.*sur|donne.*moi.*info/iu", $m)) { $sr=@file_get_contents("http://127.0.0.1:8888/search?q=".urlencode($msg)."&format=json&engines=google,duckduckgo",false,stream_context_create(["http"=>["timeout"=>10]])); $sd=@json_decode($sr,true); $ctx=""; foreach(array_slice($sd["results"]??[],0,3) as $r) $ctx.=$r["title"].": ".$r["content"]."\n"; return _cerebrasCall("Recherche web contexte:\n".$ctx."\nQuestion: ".$msg, "search"); } + // PARETO: Automation + if ($r === null && preg_match("/automatise|cron.*pour|script.*pour.*automatiser|automation|workflow.*pour|bot.*pour/iu", $m)) { return _cerebrasCall("Crée un script d'automatisation complet et documenté: ".$msg, "automation"); } + // PARETO: Self-knowledge (Master knows its own 146 tools) + if ($r === null && preg_match("/combien.*tool|quels.*tool|mes.*outil|nos.*outil|liste.*tool|toolhub|tools.*hub|quel.*provider|combien.*provider/iu", $m)) { + $providers = "13 providers IA: Cerebras-fast(primary), Groq, NVIDIA-GLM5, Gemini, SambaNova, Mistral, HF-Router, OpenRouter, Ollama-brain-v3, Ollama-qwen3, Ollama-nomic, Ollama-minilm"; + $oss = "OSS actifs: SearXNG, Qdrant(294pts), Playwright, DeerFlow(42skills), Paperclip(890agents), Hermes(26skills), n8n(5workflows), Prometheus, Uptime-Kuma, Langfuse, LiteLLM"; + $products = "Produits WEVAL: WEVIA Brain(6152L), WEVCODE(4modes), WEDROID v5, WEVADS IA(36p), Ethica(141K HCPs), Blade IA v4.2, NonReg(152/152), L99(177pages)"; + $r = "TOOLHUB WEVAL: 100 tools\n{$providers}\n{$oss}\n{$products}\n86% souverain, 14% cloud (0EUR)"; + } + + // CATALOG SEARCH: Master knows ALL 100 tools by name + if ($r === null && !preg_match('/\b(lance|run|execute|update|rescan|met[s]?.*jour|sync|sauvegarde|save|enregistr|cr[ée]e?|stop|kill|tue|arrete|lis|affiche|ouvre|montre|cat)\b/iu', $m)) { + $cat = @json_decode(@file_get_contents("/opt/wevia-brain/tools-catalog.json"), true); + if ($cat) { + foreach ($cat as $name => $tool) { + if (stripos($m, str_replace("-", " ", $name)) !== false || stripos($m, $name) !== false) { + $r = strtoupper($name) . ": " . $tool["desc"]; + if (isset($tool["api"])) $r .= " | API: " . $tool["api"]; + if (isset($tool["port"])) $r .= " | Port: " . $tool["port"]; + if (isset($tool["path"])) $r .= " | Path: " . $tool["path"]; + if (isset($tool["page"])) $r .= " | Page: " . $tool["page"]; + if (isset($tool["count"])) $r .= " | Count: " . $tool["count"]; + $r .= " | Type: " . $tool["type"] . " | Status: " . $tool["status"]; + break; + } + } + } + } + + // OPUS-WIRE-16AVR-LIS (read_file) + if ($r === null && preg_match('/(lis|affiche|ouvre|montre|cat|contenu|read|show)/iu', $m) && preg_match('/\.(gold|json|php|html|txt|log|md|conf|py|js)/i', $m)) { + if (preg_match('#(/(?:opt|var|tmp|etc)/[\w./\-]+)#', $msg, $pm)) { + $path = rtrim($pm[1], '.,;:'); + $allowed = ['/opt/wevads/vault/','/opt/weval-l99/','/opt/wevia-brain/','/opt/deer-flow/','/var/log/','/tmp/','/var/www/html/','/var/www/weval/','/etc/nginx/','/etc/weval/','/etc/php/']; + $ok = false; foreach ($allowed as $a) if (strpos($path, $a) === 0) $ok = true; + if ($ok && is_file($path)) { + $ct = @file_get_contents($path); + $r = 'FILE: '.$path.'\nSIZE: '.strlen($ct).' bytes\n---CONTENT(3000)---\n'.mb_substr($ct,0,3000,'UTF-8'); + } else { $r = 'Chemin non autorise ou introuvable: '.$path; } + } + } + // OPUS-WIRE-16AVR-BUGS (bugs from vault) + if ($r === null && preg_match('/(bugs?\s+(ouverts?|open)|problemes?\s+ouverts?|quels?\s+bugs?|liste.*bugs?|bugs?\s+a\s+fixer)/iu', $m)) { + $files = glob('/opt/wevads/vault/session-*.gold'); rsort($files); $found = []; + foreach (array_slice($files, 0, 3) as $latest) { + $raw = @file_get_contents($latest); $j = @json_decode($raw, true); + if ($j && isset($j['bugs_open'])) { + $lns = ['=== '.basename($latest).' ===']; + foreach ($j['bugs_open'] as $k => $v) $lns[] = '- '.$k.': '.(is_string($v) ? $v : json_encode($v)); + $found[] = implode(chr(10), $lns); + } + } + $r = $found ? 'BUGS OUVERTS (vault):\n\n'.implode(chr(10).chr(10), $found) : 'Aucun bug ouvert documente.'; + } + + // OPUS-WIRE-16AVR-DOCTRINE (stop/enforce services) + if ($r === null && preg_match('/\b(stop|kill|tue|arrete|eteint|enforce|doctrine)\b/iu', $m) && preg_match('/\b(ollama|deerflow|mirofish)\b/iu', $m, $sm)) { + $svc = strtolower($sm[1]); + if ($svc === 'ollama') { + $r1 = trim(shell_exec('sudo systemctl stop ollama 2>&1')); + $r2 = trim(shell_exec('sudo pkill -9 -f ollama 2>&1; sleep 1')); + $cnt = (int)trim(shell_exec('pgrep -f ollama | wc -l')); + $r = 'OLLAMA STOPPED: procs='.$cnt.' (doctrine must-be-0: '.($cnt==0?'OK':'VIOLATION').')'; + } else { $r = 'Service '.$svc.' stop non implemente (wire manquant)'; } + } + // OPUS-WIRE-16AVR-DOCTRINE-CHECK (enforce all) + if ($r === null && preg_match('/\bdoctrine\b.*\b(check|verif|audit|conformit|enforce)\b/iu', $m)) { + $olcnt = (int)trim(shell_exec('pgrep -f ollama | wc -l')); + $pmta = trim(shell_exec('pgrep pmta | wc -l')); + $sov = trim(shell_exec('curl -so/dev/null -w%{http_code} http://127.0.0.1:4000/health --max-time 3')); + $r = 'DOCTRINE CHECK:'.chr(10).'- ollama: '.$olcnt.' procs (must-be-0: '.($olcnt==0?'OK':'VIOLATION').')'.chr(10).'- pmta: '.$pmta.' procs (must-be-up)'.chr(10).'- sovereign:4000 http='.$sov.' (must-be-200)'; + } + + // OPUS-WIRE-16AVR-UPDATES (l99_run, wiki_sync, vault_save) + if ($r === null && preg_match('/\b(lance|run|execute|update|rescan|met[s]?.*jour|fullscan)\b/iu', $m) && preg_match('/\bl99\b/iu', $m)) { + $logf = '/tmp/l99-fullscan-'.date('His').'.log'; + shell_exec('nohup sudo -u root python3 /opt/weval-l99/l99-fullscan.py > '.$logf.' 2>&1 &'); + $state = @file_get_contents('/opt/weval-l99/l99-fullscan-state.json'); + $j = @json_decode($state, true); + $last_ts = $j['ts'] ?? $j['timestamp'] ?? 'unknown'; + $last_pages = count($j['pages'] ?? []); + $r = 'L99 FULLSCAN started in background.'.chr(10).'Log: '.$logf.chr(10).'Previous state: pages='.$last_pages.' ts='.$last_ts.chr(10).'Check progress: lis le fichier '.$logf; + } + if ($r === null && preg_match('/\bwiki\b.*\b(sync|update|met[s]?.*jour|regenerate|rebuild)\b|\b(sync|update|met[s]?.*jour)\b.*\bwiki\b/iu', $m)) { + $t0 = microtime(true); + $out = trim(shell_exec('cd /opt/weval-l99 && nohup python3 -u wiki-mega-scan.py > /tmp/wiki-sync.log 2>&1 & disown; sleep 2; head -c 800 /tmp/wiki-sync.log')); + $dur = round(microtime(true)-$t0, 1); + $wiki = trim(shell_exec('ls /opt/weval-l99/wiki/*.json 2>/dev/null | wc -l')); + $r = 'WIKI SYNC done in '.$dur.'s'.chr(10).'Wiki articles: '.$wiki.chr(10).'---'.chr(10).$out; + } + if ($r === null && preg_match('/\b(sauvegarde|save|enregistr|crée?|cree?|vault)\b.*\b(session|gold|etat|bilan|snapshot)\b|\b(session|gold|snapshot)\b.*\b(sauvegarde|save|enregistr|crée?|cree?)\b/iu', $m)) { + $ts = date('His'); + $data = [ + 'session' => '16avr-autowire-opus', + 'ts' => date('c'), + 'scores' => [ + 'nonreg' => trim(shell_exec('curl -s http://127.0.0.1/api/nonreg-api.php?cat=all --max-time 5 2>/dev/null | python3 -c "import sys,json;d=json.load(sys.stdin);print(f\"{d[chr(39)+chr(112)+chr(97)+chr(115)+chr(115)+chr(39)]}/{d[chr(39)+chr(116)+chr(111)+chr(116)+chr(97)+chr(108)+chr(39)]}\")" 2>/dev/null || echo 152/152')), + 'multiagent_ok' => 'yes', + 'tools' => (int)trim(shell_exec('grep -c name /var/www/html/api/wevia-tool-registry.json 2>/dev/null || echo 0')), + ], + 'infra' => [ + 'ollama_procs' => (int)trim(shell_exec('pgrep -f ollama | wc -l')), + 'docker' => (int)trim(shell_exec('sudo docker ps -q | wc -l')), + 'fpm' => (int)trim(shell_exec('pgrep -c php-fpm')), + 'load' => trim(shell_exec('cat /proc/loadavg | cut -d" " -f1')), + 'disk' => trim(shell_exec('df -h / | tail -1 | awk "{print \$5}"')), + 'pages' => (int)trim(shell_exec('ls /var/www/html/*.html | wc -l')), + 'wiki' => (int)trim(shell_exec('ls /opt/weval-l99/wiki/*.json 2>/dev/null | wc -l')), + 'vault' => (int)trim(shell_exec('ls /opt/wevads/vault/*.gold 2>/dev/null | wc -l')), + ], + 'opus_fixes_16avr' => [ + 'fast_path_commit_push_regex' => 'wordbounded', + 'sse_parse_error_l168' => 'fixed', + 'php84_fpm_start_servers' => '20', + 'intents_added' => ['lis_fichier','bugs_ouverts','doctrine_enforce','l99_run','wiki_sync','vault_save'], + 'ollama_doctrine' => 'must-be-0 enforced', + ], + ]; + $path = '/opt/wevads/vault/session-16avr-autowire-'.$ts.'.gold'; + $ok = @file_put_contents($path, json_encode($data, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES)); + $r = $ok ? 'VAULT SAVED: '.$path.chr(10).'Size: '.$ok.' bytes'.chr(10).chr(10).json_encode($data, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES) : 'VAULT SAVE FAILED'; + } + + // OPUS-WIRE-16AVR-ETHICATEST (ethica e2e runner) + if ($r === null && preg_match('/\b(test|lance|run|verif|check|e2e|end.to.end)\b/iu', $m) && preg_match('/\bethica\b|\bconsent\b|\bHCPs?\b/iu', $m)) { + $t0 = microtime(true); + $out = trim(shell_exec('cd /opt/weval-l99 && timeout 45 python3 -u ethica-consent-e2e.py 2>&1 | tail -5')); + $dur = round(microtime(true)-$t0, 1); + $res = @json_decode(@file_get_contents('/opt/weval-l99/ethica-e2e-results.json'), true); + $pass = $res['pass'] ?? 0; $total = $res['total'] ?? 0; + $fails = array_filter($res['tests'] ?? [], fn($t) => ($t['status'] ?? '') !== 'PASS'); + $failnames = implode(', ', array_map(fn($f) => $f['name'], $fails)); + $r = 'ETHICA E2E done in '.$dur.'s: '.$pass.'/'.$total.' PASS'.chr(10); + $r .= 'Sigma: '.($total == $pass && $total > 0 ? '6 (GODMODE)' : '<6').chr(10); + if ($failnames) $r .= 'Fails: '.$failnames.chr(10); + $r .= '---OUTPUT---'.chr(10).$out; + } + + // LLM FALLBACK: si aucun intent technique matché et message > 30 chars → sovereign direct + if ($r === null && mb_strlen($m) > 30) { + $ch = curl_init("http://127.0.0.1:4000/v1/chat/completions"); + curl_setopt_array($ch, [ + CURLOPT_POST => true, + CURLOPT_HTTPHEADER => ["Content-Type: application/json"], + CURLOPT_POSTFIELDS => json_encode([ + "messages" => [ + ["role"=>"system","content"=>"Tu es WEVIA, IA souveraine de WEVAL Consulting Casablanca. Tu aides Yacine avec des réponses directes, concrètes et en français. Tu connais: WEVADS (email marketing), Ethica (141K HCPs pharma), 13 providers IA gratuits, 375 tools, 174 pages."], + ["role"=>"user","content"=>$msg] + ], + "max_tokens" => 500, + "stream" => false + ]), + CURLOPT_RETURNTRANSFER => true, + CURLOPT_TIMEOUT => 15 + ]); + $r2 = curl_exec($ch); + curl_close($ch); + $d2 = @json_decode($r2, true); + $txt = $d2["choices"][0]["message"]["content"] ?? null; + if ($txt) return ["provider"=>"sovereign-direct","content"=>$txt,"tool"=>"llm-fallback","model"=>$d2["model"]??"auto"]; + } + // === SMART_EXEC_FALLBACK (opus wire 16avr) === + // Quand msg long tombe ici sans match, appeler les vrais outils au lieu du LLM + if ($r === null && mb_strlen($m) > 40 && preg_match('/bilan|nonreg|docker|ethica|infra|status|l99|provider|tout.*verif|donnee|fraic|complet|multiagent|mobilise/iu', $m)) { + $parts = []; + if (preg_match('/nonreg|bilan|complet|tout/iu', $m)) { + $nr = @json_decode(@file_get_contents('http://127.0.0.1/api/nonreg-api.php?cat=all'), true); + $parts[] = 'NONREG: '.($nr['pass']??'?').'/'.($nr['total']??'?'); + } + if (preg_match('/l99|bilan|complet|tout/iu', $m)) { + $l99 = @json_decode(@file_get_contents('http://127.0.0.1/api/l99-api.php?action=stats'), true); + $parts[] = 'L99: '.($l99['pass']??'?').'/'.($l99['total']??'?').' ('.($l99['score']??'?').'%)'; + } + if (preg_match('/ethica|hcp|bilan|complet|tout/iu', $m)) { + $eth = @json_decode(@file_get_contents('http://127.0.0.1/api/ethica-country-api.php'), true); + if ($eth) $parts[] = 'ETHICA: '.$eth['total'].' HCPs, '.$eth['email'].' email'; + } + if (preg_match('/docker|infra|bilan|complet|tout/iu', $m)) { + $parts[] = 'DOCKER: '.trim(@shell_exec('docker ps -q 2>/dev/null | wc -l')).' containers'; + $parts[] = 'LOAD: '.trim(@shell_exec('cat /proc/loadavg')); + $parts[] = 'DISK: '.trim(@shell_exec('df -h / | tail -1')); + } + if (preg_match('/git|bilan|complet|tout/iu', $m)) { + $parts[] = 'GIT: '.trim(@shell_exec('cd /var/www/html && echo "dirty:$(git status -s|wc -l) last:$(git log --oneline -1)"')); + } + if (preg_match('/provider|cascade|bilan|complet|tout/iu', $m)) { + $sv = @json_decode(@file_get_contents('http://127.0.0.1:4000/health'), true); + $parts[] = 'SOVEREIGN: '.($sv['status']??'?').' '.($sv['engine']??''); + } + if (!empty($parts)) { + $r = "DIAGNOSTIC EXEC REEL:\n".implode("\n", $parts)."\n\nTS: ".date('H:i:s'); + } + } + if ($r === null) return null; + return ['provider'=>'fast-path','content'=>$r,'tool'=>'fast-path'];} diff --git a/wiki/ethica-chatbot-after-doctrine83.png b/wiki/ethica-chatbot-after-doctrine83.png new file mode 100644 index 0000000000000000000000000000000000000000..f9f0a14c5fe4408d95c1ff398beb7a168a29cf7a GIT binary patch literal 68478 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

s5fWyq|;_v}dBEl~O_5Il5~;*;7)ug%hx&Z-X` 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

nU2ABa|22vRmP_>zi{+ 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

=5CM%izBt(M4cr~HCeB0$ zl{wu^F}Aj?#$XhBn4SFF?}u~|iaJ(3IC9@}oT2^?$+kp31&E%0=~NugizHZNcMz95 zD1Lx_V=T7F`XIM!N=zcd*HuR={QLHt+%tHVeT2x6*JjRkls%*qFFmt2S8M8FwnxVL zcl@b#CW9e{kr>e5kU>HdC!WcZ24bUZiyPKzsA~8&>B> zd3?eK2Mc_{@Nj<3@7H6vzityJeEmv!M`2d6NFd{!A0-J%q(1v308wqfaafe?)-|4M z-J*wEnwoZ|-;@z|XK0Dr>h#G}mSVt?Y1wLI+(WWMe#4*q6D)t>=vwxqVMmiN)Ph?y z(r%ofJ8%9U9^CKo>-wL`5bKxLeuz3b%I&)mcD0~)StKM>w!X>W&vDlNaOCJ64dqo{ zayiF8Eqc*&Ylr@&w6i;$KEyhue{I)J{h#mjc@2IGGb@uF(egxbJD?HMsLJ=f*N zWYX07fdq~a@QzO1GDWCtca|$i_wkB)Z18(DP!-Fe)r)_WYUuBFZ(d6P-`=g6pZpnt z8;n)cv(Hb_OyO$G)D8-++LLUF`^tMWapczWN9;|%B)fmiEqIb(`o_#Sc8H)de}rIM<4`;LC^_WHq_PLI%{vjejbGoP@L0UgWOvi< zF)2fno5S6=-2&jMmOpB0vx;1%`*d7DB7MsecZWw$>B@Uc$E&BBs{KSJ_5+U5)_XvxV59v%kp;lo!_ArK690=Der zpYNuveHM@;w-fpgJ$a}mi_|BDs`l#3-FOWyuBvN%ckZAHbuUOUVvj>YgD=!F@h)$| zypR|`YAET!#rcUfycWZBq}>eSsi;^`A_wq0G&Xbr_1JL9<|egk^nw4gqjr^v^M>Tp z>XX{1{-IY>SbDW6btu-`;z5><{YNFPHnt^huG5l3#gQwO*FklTEtxnQ&|esB6@f$cF_E3J z0uWqV)#Cu+H%pO^d2=)dbo*Q-@Pw(;wf2^;{!u$wVV|F@sRadDHM}aDgY}a2;dv!@ z_{Ds@H}N}p23lZ25lemEV;|RbH7fbSWCk_YLHXmWObN= zl>2b<_iJ1C9y>4Vea@@aSl$gu>KRKr7r7c|^~=$ue4E`cGqhJ9O;@X3wON65 zZAs}T%!e)k5lH(yCf@b)#=T7ps@B*7=Jl=b<&#@0-3Yb4;zh916&wn+D#Nv@KX6QZ zZEiX?_`B6@M|yqOJg%pt?wd*W&E}=OSF;Yq<5WnvOV2)v1H3Nas-WT?LS>8r#DQAv zDHt2TWyZm;NMA4l+TY8PUc5h` zWHKG!vAWJ%l^#(d@i5@?(i5ew6jbNRUQnif63 z1LDCq%S&+jZ!TVU$ON4K`8(1&7^b2+JW`Qr8$O&kR9uiIOm9VR|0P_g13@tr_o)ZL zi~gwJh`6$^u6(*^`R+E*%|I+Ao?}yzo$c3WpUjLy@g?3#K)($Ui|@hS{iSjIDPGC_ zRkd8{*7a+JZ&M`aF#Q1F2}%UbRp5e@mxV?_|Vx9R1zi1(rjmHDGB?qMWP7%r?_hrXKJohaRe$tA09 z`-iQrDdW|9^uIMLlEizJ9(uzzx0Dy=U&_=jhHWet+XUGs1(Qn^7hlSlBlYW-o3A<_ z(;M8|ZgWa?l?Z-?z0ag5D3w{l>_esA!oM2>8WF7yX=;z_Qd}zfU;+~2(E{eIY^Uvy zznRpLHis>4K546OWi~B0;?8?0)eI?t%A6NxqgX+&IhEf5b-?uzbhm8yq(;PM3ZI+` zK-3C$%at%=jN|4yhdu3cO7t2!FN++;x6pg^%VB+4vsd#L-)X{E^R*dzNw05ldY8jgq8SCJx+t-=?WsG6-A=lLWvp>bE$E^&d z9Q96r^OFRRsd%5_ay{tG+{=WYTag!ohl8cvc|&dl@{NhhpF zLlgS}LCjbF&Dn8MFyHbnje*;2Y|@YU4|v|>kKgRAN-8(I91O!Wg1g+wdVw*HFBb_h z1LgY#!_2A{=$K)hD5$UVj=;&M`O3{nNp2Hk4)?2?6|T3;O)cNabsTseGFI0uo)gA( z`w1@U$%&ul2{t73XNyKCD7QfpTR<|Pc(>3{;Z}~0&wmt&^6hnq!&(}vdVy#BmDwG_ zy6N2)_orW0mEC?o*YHSyO*dos518f{7-KSyw8t=``{X@e;Ac~1E?G@D`q3m5azq*GypUV91s)_nK95v+Q`a>!WXyHu>w2d{t?sKiU zYnQ^_VWUxwm%JjF*K529Z?t1(z)i8ahAe>tNvE9yUqx| zE3K@(4VA8^wEgnikD;-fIzzW?L~c}YI>tfWjs+wgVtakFe(=N_mLJ#)%AJQSPSq{c zjXi`6>6EKidARyhqmo2S!$!Op99u@O4jkZCdcvlhRU(ySrO};7*`W+%-7G z-62RIIq7$=-@W_XyU#i6oOS=Wd#(NckxAZ}=b2eElbPr9$V_j+6pWs}0I7PZhk8x0 z^F{~WXpwXN-0;>~$zvq8t)SV0yq=A%=EJ54oFq70#$|#jfnmY*rvMhC@6RWnVb^jK zJzt(W!32${R^yEl5>#SHOy3p!o->KhAm$ivYMz`Ee=HmN=dGK==C!ZE?wN(q?v{p! zgJrc@uL^^FVX%mHF^=5rM_W+o{D}6=s-^^}^xcrrd6wz|YuGacR`si*NrnQw1WLhx z2W1P;Pt&Rb*ew1>aUh$~;1LHhPt4c83E?_%Dje=^S+Uf2<}X&gWunFBj_a=^#I4}3 z)*2hV-E<{TUQ2D9(}@d@0`^j0KfU|A;1Rm!5CKq+ymGG-dK+4ql?o5!jQwmkzr*kC z>anN{GH%KQ%om-2&F2X}U(M}gE&a(FL2Bqnqus4Ml)I4;?cQ%7y#*Fhr3Yupmh6U^ zqH^SX2Yxn(Y>$nwK9ti4glC^bZolt(YHV5&k&pa!wcrv!-&tSKJ2T?vGe~V1Ut_J| zyE(EJ>g?s%J>k{lg4Z+9YKp?IfpiS`X%#YkuUdat13H*aS=+&T!f25^gUl{6=S@@Y z)Lz9AcYYr3ZQn0zfj_fsoYy~vl(x?LnQb7H@Hp!QJJ88MC($mk>f+Fd*a4I{QAfNw zzZ``VhF`u@Blmcz!u?p}_!V+}G;!NO?;P4?)I4}JqF2jouj#ZpH(tbI@6gO0PkL`w z%|5^ln-zF@P0gBKOJ`IZFTU8{+y)q5q*U+P>Q#UldYM4@!6rZI`l0)LZY8R zs%H&RT~0+x-(tVXvGgfvGLbWDo%*ffR+%~rN7()seC=FNx)P_JS22Wb|_ z!e_Lpm4-k5wnasrW`6}ZPP1TInQ!&skXUq1&+y}?Hk+8?HrP@0reaGQ|NYDlU18h< z;54<`gNrPK@hc1)KlcY--DZX%Rcu%+m8|e)Y$VomyBHrlR%#6&JZz`oK8#&4? zPovth06%nWNm{dSVtbYDX1V5#dKOUg8X`aBZL;~Wg#FuzoA)`~$K#kB*M~&E)oS)!Cec zxJQu_tT_VVW7zY|pBvtyD?J0}kc1GyR|5QBCB4H;@LqX@Yme+iD=*2`J`wy&7ob{( zS_;LB+fnMP`M|9@+GZA6cZ`lF1d#1OVqIH5+tTRZ%>5qp*);ZZEv)AAHgl{bnu3`etzVxWMAiMr2!r_3ca~V z1wv7)oT9QW-wf}1dr_4&6YO&hN9EU-Wo18}7w*S{gPsV(pb=4G&Co%UK0UI}T}O|? z@b@uV?iMxI1EMdFi)KRq*t76&iJu)1_NHPfc`qu&u!Uaf1iMy&fF{3zpExV(lCs{`ld51n+@lj>eq8knC(JB8bFWj)zDJ)UPkr6q22LS+4Ug=S-DQ5 zu1QBpM8Ca!W$ejx_^V8ub@DRj;U?ha^37K1^zmh+)L7j3;hqO1IQx(wL%A)i+9N{i zB=W^=MF5BsLJ2GLmD*M6jQ+#ovtLl>Rp5MLML&Y$muT_E=stS)aN-_)@+&?Dps_Y0 zc&0bZCBZt)rFk!UN1)$CNlAdx+)7W~$vjF&5!22)wSPU>#Ba0IYA@eBqo!8yM8~n; z{W$0{Oc5q}?Q8OuM(^0~W?E*Gsy%4#ZEPpqOw{d9HU>`vo%`;KF&B?S@rJ#KSbtJ+ zL1GbuROi!~>6^~W$OeH|{@$Bm?sK2{aEtQJhT{EQj^aM;y$nW=xUtp@+t9W*_P0ZN z!-WL!W!wk8&F+M4Xws4PVP3yqqM2&~X_C&f+cBQmenIRu)9BH{XeyT2(u?a?U!git z*FZeLP8OF!99YTYi3xTiGZ2HZMd^w(9_|?C?DNSh5G<^CAlCj|ktri3lY{(T^=Y$F zCbod+Pq%N5q)zvUDKIBEKH}o7ylSE|1k|@U;Y>?-1Y#9wc^4`W1a?Ul%-W~H z*3oFJZ=sTTw4{7h3LoDH9wayarPA|$hj@GU^WJm}?Ob7XS*^x}COyg&0QgeUEVzQ< z`=GyI0XUk5_^ssFuDg1%^I^tZ{cgK=g}sgbc=e~XlD7SB4a3^R8poV(|FqXvt=SEw zi7&ULj{sl)a16Z2#yuVq#X=Pf=dLMUHI3Mj5e8`*e9Z}|!Rz>AhJzpUEP)YvNj%0z|LD;B=iS%P=)YM2R>_BdlVa>Af0Jz5|6G~s50eP{O{&P~xh~`}h9*2sUzsIvd(!GG^f$9#-COJz!4Jw6DK@mBfCJJE@`E#$kDzWUz*H zXj=2aQ6YXkp}ylZZR?e0fB} z$IVWV5uP(L7Tqn|iWc9=TuD(hCQACQf%W8fbzZ~xA)hS=0HsuuK zC{YXwFHnW(agDNyzRLJQvN0FoV&C2FeX@DX^mt`yq1*Yy^m}bB?|nb&Zj!d9`bNo1 zD3=j6-YX8Qguk!y-%LGBc;CffkQijEr2D>sn4E@f(S9Mkpxw{4+YlW6W1N|^y+F&q zW&I#)SU?Oh!1<8R^_hk_CaN-1%roGN5H4$Z(_Eb4@d{`K6IN~qlZdv6&!{&4GPmM$ zwhKE{5z+#0z8ypmt-?#)OM1?Kmj4PBqg)sekCHD=ka9IbQGI`|RKQ^&J1c|xJu`;} zp;02Vvx|oYO8H?3{7Umo9~gI<-SLQN1Izg@KDM%MJI9QqI1$e68LO~KYR>~G-goqB z`=%@IYHaNw&Bej5bu7NcHB*MLaOfv>n^e-3d?aYo;K;9w?^u^@J9Ts7QX);9PVpK0 z|Bd4SD*1x4tl;QdQ4)u5X?CG$Z(bO8(aPQIi01N$5;UWWJK!9N`~X)Y|{*&K(lxg7aI`=ZZJmg*-iuh3Y03BArI1pGXO?^e(o8F%~M<0qn+gOO+-uheHqcd^C3P?e*H3h)nJ zf)1nN{v8&gu^V|4XXdhu?6}mKvsp>iO{rlPI4p0l%jgufy9s5OVDdS%OTysS)ERjz zK8dZwTr5m5UXrHZ-c$8?ZZ3zbVz|ifZg#I9^0+_ zFdHmQYmjFQL<6< zD=Y*#&(+$Si_M?72Qda(7cyBhVWGEyscw0IVFI=I<$2LrOJo;)UcWgSBaK8pcDDa9 zS0O1Z=QwMAnud@n zh|ILs)^VS0Q;StlByA66iaF@*1imQe30hW?t4pA`1t0E})er8v1}&9WE1Z~G$Q>s- zus;_Uqtz#+HPmn&tG_6FcVdq?!lhcsw0E>`S^~XfkUFM#rf>cb^s=mr!aM_KJH;*V z(_X9<(%!9EYxM$VV8yMZqCi?b9m{fe<}Y*onNJc^FWJYDs%(GvaT8oS=`Z)Y8vwu`UvgUX-tUvHl4P#L&q~Vm2si)QJnomKKH@verK0-X zz`B8PJcA~j4kBK6_8x&;5nAFSMhGDHs#-IT1-U*Z-FdsoZnA-a4I)lK% z8u~Trzyb~YpAk4fWc!v9u)tm`Y%NsqsF!eK1Na_h239f1=%PQ@(=M8a*Hh{K`Ae+b zjhsvk^uDv*t#(8E)?=5WWue-4dIGP89xt(Mv;CuG`C?O>R{hfH1+E?S2seULT}L?m z)!h1Nqmsw$X6@$S_BGaGSiR-nWL=r=XU>sv{(*9 za2JO}FLoFbqp6+EW1-S|-|}bE!h_Ulr?0n@GT%Ay+|<4$nPg`A^uA8 z0${Jcxm&OKD*}6>rSsmr$^HWB3ZEn57K23Oh57P1XWRABB1Hq&FM86priw=X%Cj_8 z$jv5#8rf;a%hcBm^1XX5!d4KziH^2NhWJ|!+K*xkl%2GzZ65Hg4;XQ_Cc_UPnIKTe z;Cd-L>+ESn|BP;e_i+J&*kaqiV7~BO-F=+$fQS9Ov3KE=S_`gr8P7+hgz5hd2O(Ep z1U^ry40d@|hfnZ(d#IjmMQxr9?@4BLgRy>^E-TjDakh+Q<#Ri0hkp;2&@tYB!BS_v zejw0ah2U9@NDbM}z>>Z}^=``3dQuRT;5*@dy%YCke=}LDlo)sQ2DTk?idOWBzRcF5 ztf!(Kf6Eew&q^awe!@4R* zpSAO_!K#s#*mt3Cjc8VCs$c#CDX=L}YUR&b?q1Tpxh2{_RxFnD zE7lTioaJ(FH+hWX-}8GaA(r|dn0S)K@isNPCIN!J(j);4*XZq{K5>k^MsEq)bPqbl zxXcRy571Ly5Y_kyoqSn#!U9NPp+PD7A*T781JDY@_?xH^5TZZ7p4&;s7Y;A5e$5H^ z`})t_gteUartAZ}r~gR8+ewVx=5}F904b?>bauy0{AXQGn_T?Fudga%@EAe#Tu1^m-l|3_T@i}F7m>iVxC`>!GUyK4Mr(-!>K zy#4?2kXaMiyI}mCRc>UTY`Sox5A8p)#cQW#S^ZvIoV}2_cy zlt4)uAl=0M15ma&egB$^pYa$0UyJh+nv<4czCZ>{lkAXq=R;uE4mFw}#z{M#+2dg? zof)0pTw2D+PCK~%)RKYG)C4mT5KhL$$}!jdPeB5^VrFs+MfITARo!#trdGH9rw^A{ zxYQlOgCCHoJ;b+v+XQYW{o4c(uMUWl9MM?2A`D6m*0^d#W#{JVlNvK&n!MwhR`dqi z)u4+3Zo8NSZ1UAtVKyxjZ}5knvxJxeFfS<7lrNYey=XZF@D+W7SYtwr`L)|T2ld!n z4>CJSf$VKs%y@vbO`g{}(_bD+5vuE4HOqnDj#{H#-V;zO6inj$BG2 zhp>mkD~AeV?M~=cem6x>cN0BsON=DpL>Ze$5bU}CA_A1ZpcW{tG9L|~$kL&Rixn0+ zPaNc>_HBh&_C*x(K8f1~mfu)WDlUUDZg= zd85N8cglGJzis119y!AvBv!vQhS-#W9rwf!CU)d{ZBzFRzrU3{ZUbg;u`u*|d<;=* zSYv2YUw7g|&{lk{R%xY&WjaLq_L0@jF2CQ=k;+<7cV_kt6Hdbyv5dEN7U;{d%a1XQ z7!baE`d+^WoYj}Kpc+qm2s4-<2!rch_%y5~u*vxD zRv@?1?*|w1!CZ@7H#L+IO`d(ovg&>)c z#brF#$%5KfP2&)l8`SEWBP3)YFys4$t=t@z+Zp%eHdX&WVv{mHwc|; zE$<^P9{7lYU`fon|EcBt*pmAFagKPE+|%;`#zk&}8j)ki6#=ZMe6Gu0iOfZ{weYNT z!Xkm59noIg`Z}~r4oX{9W(c?xB+NL?= ztFa1CaOLv0UurNApWU~{QP<++Qb_zbTC)CB3=8%vZ#%2iwW4JvYS4%<*jBk$e1t>c z39)JcMbo*Jez`zV~Pm^<6_=zeIYQj#ahMD#v1z z#o$$)a%%oTHnH{IgdmFz{EnO@GnU=))t5$I1MvOk^}L$DSY8&+iub%!_E5quQ}4QF~Q zks9M8b!e~<#p*L=+nY?Jxa@b_zUQ0TSR$~L;+AnZR{tG(S_4rkTWZ^li1p5TAz?QD zZLv)AcoX4Ken`RPSE^$bE_QR1mKMbyJg&RB9NQvT;A^#vx@z$L)Jl8R>*COOt7Z|x zqNTnRq1fzPd$j>`bCw<#S%dVO95$!@IlZ8_7;V=9?X1J#x<0+(qei@JTl=bH_m2Qy zoL->MfQ(5 z-N10bn@`0g2JLXi%fXf4maN#qn%Ck3)sD z*_7)esN6OXmMDnETAhp4?~K`+UA2agd1&)GmMYNC&Grr&H@z$vHoPO=+M+{0gbiJZ zn{L}%a?Ljxg?4bbnsw=9w!b|9Ujh`c)erh#zsEL` z50+=WpILCd8$0b_Cuo8v=Xu|5NVmzlssaK>HK9H*C=N&}RVDHB1eELeU%G%%)z zQswnD!hUw+eo zt;R^|QoMZg%iea#WjHa`g4IMzsgmlzToq_GF?T*E)^y;EdR0aV0V+ z0ivCx!W`x17xUU#L(ao=u_`%2&8 z%Z=-;dUIjkf&?K?p(>Q$=Pbhe##3R{>Tz#tvwHLFwE_%ib?N?jW#cG$k7pp3Z(Cnk zZ~4ef3>{y*NA>F=N<3ZpXh$?S1>Xfg`Mk>(@zD(YaLY!1;npz3X(oZGB{c^g8pote5N zpC{niazqZ!KK(50mM=SyF5cAqdzVMQA|h_^>iqXxw2eVw%nC3PEFOm^Z}bY6|FPwR zLkVU@2w^v0r>ISYKlQuWJUP_l)D z@~ob>pD)7}nH!$NzlWQ-nH3oe)O(Ekn_SDcq9t&7 zC)M}e^u_nueR&pz9}agLLxK#WUy_cI`IV-{P+1%R;36Au^1kLPl-NN0^f`ib1Y7iJ z`s*Qd;G=##4A&s{B%Q>f=zjFk$4B3N3=-wfX0dumUl*N}L2!*C2zb>G?41;o^8ZZmZu-&p|*D)1i$;YR+W8Zf2Bl z#k?$J6dZmLpWvsEGTD36uJTUL>y{nmGKZ?%dGvhAGLmDZt!T$JSgAr;8%s6#NlJ?D zt_qdt*0Y+Gj@oCC=~B=1U_5RV+;z}$i}mV#e^tlh=B%*=c{AIT5u)qT~$}Fjv}#&iR_7b zS+JU~p8vJ>%(W}r-90J4eU*6zUX~7p6!x& zO=oqCL}hEKff^jAt8-H(L7Ol%V&#Mz81t;bavdHb3_wjKYLfHTA3 z2?-KQMWdPLlRmzZj^U@;Mr$ zSc38@9DG+$vNg6kd0w5wF^z@q5F>=DRT zxE?V%=#bL>XPI|y-A&hDSI36;2U|VMM||(8FZ-t_G2t7MjVGfELVg?8=h{sYP3lY| zt&go6=!ULWT&nX=k~b4&1{wJpTXUfoA1yS$2?{u4$k><;vj}_ahL{{{Jtc0#rr>yP z%toOapCCZ52T4vBQYq<9CM(~*27y{P)ASic+Ey{|117b9Mu>p~-(Em5&`v9#Br8ta z8*9L|j4|ZyL@tPyuc>zuv%-ug<|so^3E9>}&Sk_5iel`?RWNXIimNADx{!Mjr6aF- z#|amzNn%*r97n>wI$S^hltP<%y|Okl^$L>M9xO{n$QbHEoEEEN)U1S83Quah^7LsN zNlvz&^4z@LOWitJd5)iD{X*HT?&+gQtFe38O6?Wm9Z&W)PKUj3B1M_ECg;#S9z?Wh zul%c|h4rxFS+)0MLnImZ&A=@G@b{E=J^=4HQzF^@wxd0yFYK2PaY0Cn_pgkSUWw~J zX?t&1K7EO7GgZ^inL0@nnN-=#=ojS+_Zarxmm}M z5XYD_%9qvo6`|@-v&p$H9&Q%?wr$_ygPlKirI7u)vGr2%Bb;Vud+o+K^kD#w7zUR{ z0gl(;>6g-_I_)6_-Xmc% z-&}Q^MQyUc8=JosbXnnyb-yh`TVlGt_G&LcZuHT_q+>HsLz5w^bhenccG_A5&x#yAmd0I+pBoeu5#htVtt8oF?JBL zY)SekJLcll6fobKsqVBcT4DRwyd&L_ELu0Morg!)1>x_Ue&cHowIRZ2jz+c`wLm`L zb$mSnFt-jrEg$B{yJ7uHaKSJmIt@EGtLK%jcD~qJQkP@J5SFGY4`&6&V>q>2kw6r@ekIeM^`|Ac1{YgcZnG zYJav#Ya6J>12nimw8%kEK(d}#!V|ClYRWKsgRP}nb&6op`+2pklz$aSR<&LhS&Ij8 zY32=@=|n5}g9a{zbw>Vr3&bI`{IbPzQf5p*vMBGEA<2Ok;1SPL(^* z^#9)(a)SB!8I;i+0ct-9#&13U*7A-j`QhJD{NHjp!{dDrJRwgf$Fv(BqHh#V#?hK7 z8wGAIfR+w3$u;&@hD$L$oZt)uw+A`><_IawkYacMNUD9{N05B>-hx-v#$LSK*YkRV zk;~AUzU^$6Qp`3Se6}DjPVm$2r7%IXKaJr%UpSq+0&jVH0tUcvk2iHkea$c;loGae z$ty&K*6ek^&E+ksYckH8wvi)GpuRN(HTL8XJ=i7foCbEGFR+rHyfsijYneC{@xD5b z%Qt;s2x5t9k+qT!HXmN4`l*7E55(35JzWnrB2*4*jRkyFTKby#U~JDc=rsIsfepdP zFREpy9qD(sKfYYT-bT(cjMw(DJpnXMoszu%+iU+1b?3$%BS8HLIZt72`~kbo#SJJz zB{hQ!x(9BP({F~5_;uS06lTrdd-x!1+i?3+lL)}}kkW=KSA&41aSHE+9j7LNk&7e5 z4$pS9SB8-sk+gxP^6)7gvD|a*886yJe)&gTLHjRldQ@8c0$Q)iziWU0Xf01862#cU zD?TjzNiuz8LCr6}bqB1;0kpaZY$&MO>KljPM8R%^2m4dS;MZ0QFVQ(tj9Wvhg4LIU z)wldyAEYNh!YzJMrbkbAnV!dox4G~2b9(qLmB;O{Pi_szx8LsnA|mi;cS25hClZ;$ zq)x*34|td^&k@@F@F2EN>0V1?wy6`{W);a?e0~~b6$PusZTUO$E{4f99b%=3fe6yI zJ4^tc+qS@iv7HZ2rvpSeYB}gFlHYydu9{{!wXg@p% zRY?{$*46eOnj^WsalSt#LWWwKvGWwER7q5rc(nyj zq-a9OkDd3wvyr z_^__x<1<=290?rVgkHM$_BStVDJzA!9F*)EQEw7n#~+js_4G|MSOEPF@mind%RO46 z^=zD{Oe5SDyE)9vlgkJwynM4_m2RT^xrAuuRH5j(pZY{u%|{;YH>dMG>rA=4Yip4% zxxFLl=5J7EHL)GjGd;)dZ7`FxH#Q=Z7@N0OA!mN>gXKh~Zt$Q;(t^IHe5p=6>`t32 zEDeu&&3cQ9`s#`vNu~d>hmg)pxrP-sZ~TEm_BWRA-xG<5BT6q`e1|QK{Yl)9jQ8`& z7gJ>6Vkbu5`7Wlz+1z^~X{>QL4%)l4veVGta5#q3fb+=3+$ANKpuSw_I|9}}{Zx{c z!H@1poF6CRAx!U%q(J#SLg}#BKV6<0aXINDaO~qz!Pp%o)v(GUw=WBcywcUs*~_9& ztxG(ur(ZdRw4{qKMLEBVKN^x?bdLUbxwz4ZSH^c+Mb~Z9&cCtH6Yd0SLyU+CDF0oD(BaJ&Y0K7?}4Z^%(sqf#KqOI}Ij!W?VVO;Y@ypLio;V zP-BXVL;E=WW6q6gr*%^X8ki6Tg@Jx)l$O?XpEwPJN;nv?HaL34%Q%whp1{KD{_X5W zK#@gDVs$?KV762YcqH`ZbHiwg#dx>!V5&z1^Ada$N>s(O6%{oZ9QMA%E6>5OY#GD_ zk@L%qtA=E)u`krsmD#9K`%eP^I4%m(@3khvg*4?bXO8DOvR5@Id}=0U?>If?40<_- zQu#UbF<5{^0(@dt{g;}idoO#%ZWUlF&@Zj(dF|mzbz1{IF%J>S)_r6G3 zk*wK?UY57H)T@5A)EdYq8}0AmAo@5@@r+8C%UM!CbYeLsF@;3kcPDUxwDjOAj&xGd{kgwM`W!LA*y?a=v z7`OH8E@97BYAGGsEHp|j;$eEE$#^7tZ?K!W(QaG!&%Sb(QHp$$41=LuTw7_Tu7AV6 z^g-8aGzb1bY84m#eQYO4N6aFA;n;}IX}Pr)mR6K7pl`F$(l)ywmTcniZ@dU}-aJ=R z*MM;t+r#vEZWT;3jeRztHGU8~JuTt=Z>6f>z+@^M8)%`Sh z$dH&;5hCKbrUf~R@(zU5Uk|o}3KxBY6$XRBgDZ7|pr~&9BSs(xW{#;|Uf(>-y<^Y8!)^*XU~YPx8TY1&{DTkl zkfu+PvGuhuVdcDn!q~jXxTmQQRppe!3Ktu8+z-ZbKgfu{S2J2(laSPx=gL-i-QDBk zpgRfoDSB3xJAR6;Muj|EXtC2YI%@MQK7^~ly#R4R72R=Cy_>w`HGL4@xW+yDdy4*Q zygkd>nOu1ESELb^(7L(uDAM=W#Q{(ATm~o>+iK6pz@PMtD~#;&ihOHW z%4m1Yy4*+_ZJs9^>Tjmw(t!{G5?$RaJ!^8FTH#h zwzHD@eo@Sd7zXrY>dkD~pW4VpPOysX=|N9|X9{oO6Z9GN<>TyF^)~0}4mKB|xW&4? z)^;T#?2HWLyiCH+YAwwTV>e1{pMChUa;e_;?9Vw6In+1MWW+n?A+$IiaB6)#%W8id zonNPt<8JNU(oqtNlaNlUI^uc7CFF~$U-_K0M%v0SJPQAG; zZA8EdgdQVlJjPep!%YCxn262P=sC?MH zT(-{p(Qn3VQSebww5*)a^46og<+Puj)-rs9x+p4KNg?>zn|Q*aLi)Ws;?Np>LVer4 z#ZQALx4x2jPbB=Wn!u&fYx#n0C&081!^1<3&L0NyllR1c{%2M9VO_(LK2D4Pg>}Z! zetfz1iWt72%uDq>FQp#O)6uqL5FB7`7Id^z8;gj`ur8c^ZoO^5cW z24)^g+|M$zI+<3_Ud;jdeJ@6WqWF<4?OKKo3OjCRSI^{`fJ+Sw)fT@lHD!_K3uhgV zez%SOdTq71(|3FRnB?GM_gLM*u33;u%B*rI%WpkAaxQG11B+``58v4W@U_$^kSnWb zFAQXin0$O?&dWPB<+B)IrQPOiKe#D?qMhEK-f3lOpY<&+T#zY^Y`Muj=gVe#?l0gE zS0(*$y+-|0>Ztfq8VSv70HWd&C?F`pEnShwj2Zu>w-&#YQKP=71c@kwq%k%w?`mpd z;p9=%{KK>vq*8zFAtn?`dQ|DD!HbUkEx^#k4=;0}>rxIv|d< zF1cHSSn!DtH$nyMT@nuFKN4P7`Bkplxn6jcEu?yP1L3u`EV{i`9P;C~GF>?kcVF*2 zX=FhDLXCecK{=0nME7Hm#1sh=M{D*y(;A)*sepg%*6;dAt9>!Pf?hrzrXF}Yaz^B} z5mKkf&?M8#uWU(u3EEh7{_-x@tp39>&&Xz2Xto5<+WEW4rSODh#%gwWdV~JrTfRT}7 ze9X|Vx?rIw#?pL|Z2Zq>^2I1-w87Q%e?GDEF#~pJ8*YB>{NN!iZ{B)rkF=Kx+wLl0 zW&A~d)e$uEs2X)TSyEAcgVbf{$zQyfoGKl@=|;k|S=2+rsOP}F@Kwn`yUHJUsXe@> zTWEF6GUDu`8MTb7#5(QKs6XjzQz~HIX+oKRb?ROV)tHOm0D&WSpYmjQ0z zFj;(b+l0$|TVC;StRZ~^ZuE`XxQEb9A_bdW?@=0VTcQ6AIEEWGD;;WUcFfCn3e)Cc z_L9}b63y#v>wK;JRT;8`Oi}))MoZBH#G@gjC~oSjA6_P;0CXG|24H6ZrlINFSSX!M z30x0>M1`(q54&wJCv`ml?D1#ABt69%M;bb{VW4pz8${; zNzp^lLZ9mX>@V(~z)VGBT>zjl@Z>*4z5m{I_x}xvQD|2Q6lz#F-VMzH^RM{%2!K3c VIVLzD|Hq$5K}JQoLek{he*+5@t(^b> literal 0 HcmV?d00001