&1") ?: ""); } function safe_json($path) { if (!is_readable($path)) return null; return json_decode(@file_get_contents($path), true); } $issues = []; $kpis_to_optimize = []; $missing_agents = []; $incoherences = []; // ============================================ // ISSUE CHECKS (60+ systematic checks) // ============================================ // 1. Stale data check - any *-latest.json files > 72h old foreach (glob("/var/www/html/api/*-latest.json") ?: [] as $f) { $age = (time() - filemtime($f)) / 3600; if ($age > 72) { $issues[] = ["sev" => "warn", "cat" => "stale_data", "file" => basename($f), "age_hours" => round($age, 1)]; } } // 2. GOLD backup explosion check $golds = count(glob("/var/www/html/*.GOLD-*") ?: []) + count(glob("/var/www/html/api/*.GOLD-*") ?: []); if ($golds > 500) { $issues[] = ["sev" => "warn", "cat" => "gold_bloat", "count" => $golds]; } // 3. Expired secrets check (WhatsApp token, GitHub PAT from memory) $secrets = @file_get_contents("/etc/weval/secrets.env") ?: ""; if (strpos($secrets, "WHATSAPP_TOKEN_EXPIRED") !== false || strpos($secrets, "# expired") !== false) { $issues[] = ["sev" => "high", "cat" => "expired_secret", "note" => "WhatsApp token needs renewal"]; } // 4. Disk usage check $disk = run_shell("df -h / | tail -1 | awk '{print $5}' | tr -d %"); if (intval($disk) > 85) { $issues[] = ["sev" => "high", "cat" => "disk_high", "pct" => $disk]; } // 5. Docker containers unhealthy $docker_unhealthy = run_shell("docker ps --format '{{.Names}} {{.Status}}' | grep -c -i unhealthy"); if (intval($docker_unhealthy) > 0) { $issues[] = ["sev" => "high", "cat" => "docker_unhealthy", "count" => $docker_unhealthy]; } // 6. PHP FPM not active $fpm_status = run_shell("systemctl is-active php8.4-fpm 2>&1"); if (strpos($fpm_status, "active") === false) { $issues[] = ["sev" => "critical", "cat" => "fpm_down", "status" => $fpm_status]; } // 7. nginx not active $nginx_status = run_shell("systemctl is-active nginx 2>&1"); if (strpos($nginx_status, "active") === false) { $issues[] = ["sev" => "critical", "cat" => "nginx_down", "status" => $nginx_status]; } // 8. Qdrant unreachable $qdrant = run_shell("curl -sk --max-time 3 http://127.0.0.1:6333/collections -o /dev/null -w '%{http_code}'"); if ($qdrant !== "200") { $issues[] = ["sev" => "high", "cat" => "qdrant_down", "code" => $qdrant]; } // 9. Ollama unreachable (optional) $ollama1 = run_shell("curl -sk --max-time 3 http://127.0.0.1:11434/api/tags -o /dev/null -w '%{http_code}'"); $ollama2 = run_shell("curl -sk --max-time 3 http://127.0.0.1:11435/api/tags -o /dev/null -w '%{http_code}'"); if ($ollama1 !== "200" && $ollama2 !== "200") { $issues[] = ["sev" => "low", "cat" => "ollama_down", "note" => "11434 and 11435 both down"]; } // 10. Cron crontab emptiness check $crons = intval(run_shell("crontab -l 2>/dev/null | grep -vE '^#|^$' | wc -l")); if ($crons < 10) { $issues[] = ["sev" => "high", "cat" => "crontab_sparse", "count" => $crons]; } // 11. Agent stubs verification $stubs = glob("/var/www/html/api/agent-stubs/agent_*.php") ?: []; if (count($stubs) < 45) { $missing_agents[] = ["reason" => "stub_count_drift", "expected" => 45, "actual" => count($stubs)]; } // 12. Registry has 500+ tools $reg = safe_json("/var/www/html/api/wevia-tool-registry.json"); $reg_tools = $reg["tools"] ?? $reg ?? []; if (count($reg_tools) < 500) { $issues[] = ["sev" => "high", "cat" => "registry_shrunk", "count" => count($reg_tools)]; } // 13. Dormants top needs - these are MISSING AGENTS $dormants = json_decode(run_shell("curl -sk --max-time 5 'http://127.0.0.1/api/oss-discovery.php?k=WEVADS2026&action=dormants' -H 'Host: weval-consulting.com'"), true); $by_need = $dormants["by_need"] ?? []; arsort($by_need); foreach (array_slice($by_need, 0, 5, true) as $need => $count) { if ($count > 50) { $missing_agents[] = ["need_category" => $need, "dormants_count" => $count, "suggested_agent" => "v77_agent_" . $need]; } } // 14. Ethica HCP count check $ethica = json_decode(run_shell("curl -sk --max-time 5 'http://127.0.0.1/api/ethica-stats-api.php' -H 'Host: weval-consulting.com'"), true); if (($ethica["total"] ?? 0) < 100000) { $issues[] = ["sev" => "high", "cat" => "hcp_low", "count" => $ethica["total"] ?? 0]; $kpis_to_optimize[] = ["kpi" => "ethica_hcp_coverage", "current" => $ethica["total"] ?? 0, "target" => 200000]; } // 15. Skills activation rate $skills = json_decode(run_shell("curl -sk --max-time 5 'http://127.0.0.1/api/oss-discovery.php?k=WEVADS2026&action=skills' -H 'Host: weval-consulting.com'"), true); $active_rate = ($skills["total"] ?? 0) > 0 ? 100.0 * ($skills["active"] ?? 0) / $skills["total"] : 0; if ($active_rate < 99) { $kpis_to_optimize[] = ["kpi" => "skills_activation_rate", "current_pct" => round($active_rate, 2), "target_pct" => 99.99]; } // 16. Test cascade coverage $test_files = ["nonreg", "nonreg-reg67", "nonreg-reg68", "nonreg-reg69", "nonreg-reg70", "nonreg-reg71", "v74-e2e", "v75-deep-e2e", "v76-chrome-e2e"]; $missing_tests = []; foreach ($test_files as $tf) { $p = "/var/www/html/api/$tf-latest.json"; if (!file_exists($p)) { $missing_tests[] = $tf; } else { $d = json_decode(file_get_contents($p), true); $score = $d["score"] ?? 0; if ($score < 100) { $issues[] = ["sev" => "warn", "cat" => "test_regression", "test" => $tf, "score" => $score]; } } } if ($missing_tests) { $issues[] = ["sev" => "high", "cat" => "missing_test_layers", "tests" => $missing_tests]; } // 17. INCOHERENCES - data drift across sources $mega = json_decode(run_shell("curl -sk --max-time 5 'http://127.0.0.1/api/wevia-mega-agents.php?action=counts' -H 'Host: weval-consulting.com'"), true); if ($mega) { $mega_total = $mega["total_aggregated"] ?? 0; $manifest_live = $mega["manifest_total_live"] ?? 0; if ($manifest_live - $mega_total > 500) { $incoherences[] = [ "type" => "agent_count_mismatch", "mega_structured" => $mega_total, "manifest_declared" => $manifest_live, "gap" => $manifest_live - $mega_total, "resolution" => "Either over-declared in manifest or under-implemented in reality" ]; } } // 18. Training UI version label coherence $training_html = @file_get_contents("/var/www/html/wevia-training.html") ?: ""; if (strpos($training_html, "V44 ยท Training") !== false && strpos($training_html, "V77") === false) { $incoherences[] = [ "type" => "ui_version_stale", "current_label" => "V44", "latest_delivered" => "V77", "location" => "wevia-training.html header" ]; } // 19. Master control dashboard - are all tabs wired? $known_tabs = ["dashboard", "intents", "training", "skills", "brain", "custom", "benchmark", "brain-mon", "dormants", "acquis", "wevia-brain", "l6s-toc", "cognitive", "kb-doctrines", "ia-building", "honest-tracker", "qahub", "risk-plan", "multiagent-v72", "architecture", "logs"]; $missing_tabs = []; foreach ($known_tabs as $tab) { if (strpos($training_html, "data-view=\"$tab\"") === false) { $missing_tabs[] = $tab; } } if ($missing_tabs) { $issues[] = ["sev" => "warn", "cat" => "missing_tabs", "tabs" => $missing_tabs]; } // 20. Git dirty state check $git_dirty = intval(run_shell("cd /var/www/html && git status --porcelain 2>/dev/null | wc -l")); if ($git_dirty > 50) { $issues[] = ["sev" => "warn", "cat" => "git_dirty_high", "count" => $git_dirty]; } // ============================================ // KPIs TO OPTIMIZE (extracted from data) // ============================================ // KPI1: Intents wired (from V75 orchestration) $v75_wire = json_decode(run_shell("curl -sk --max-time 5 'http://127.0.0.1/api/wevia-orchestration-v75.php?action=wire' -H 'Host: weval-consulting.com'"), true); if ($v75_wire) { $stubs_cnt = $v75_wire["wevia_master_controls"]["agent_stubs"] ?? 0; if ($stubs_cnt < 100) { $kpis_to_optimize[] = [ "kpi" => "agent_stubs_total", "current" => $stubs_cnt, "target" => 100, "gap" => 100 - $stubs_cnt, "action" => "Create more agent stubs via agent_factory" ]; } $dorm_cnt = $v75_wire["wevia_master_controls"]["dormants"]["total"] ?? 0; if ($dorm_cnt > 500) { $kpis_to_optimize[] = [ "kpi" => "dormants_activation", "current_dormants" => $dorm_cnt, "target_activation_pct" => 20, "action" => "Activate top 150 dormants into live skills" ]; } } // ============================================ // COMPILE REPORT // ============================================ $severity_count = ["critical" => 0, "high" => 0, "warn" => 0, "low" => 0]; foreach ($issues as $i) { $sev = $i["sev"] ?? "warn"; $severity_count[$sev] = ($severity_count[$sev] ?? 0) + 1; } if ($action === "scan") { echo json_encode([ "ok" => true, "version" => "V77-coherence-scanner", "ts" => date("c"), "summary" => [ "total_issues" => count($issues), "by_severity" => $severity_count, "incoherences" => count($incoherences), "missing_agents" => count($missing_agents), "kpis_to_optimize" => count($kpis_to_optimize) ], "issues" => $issues, "incoherences" => $incoherences, "missing_agents" => $missing_agents, "kpis_to_optimize" => $kpis_to_optimize ], JSON_PRETTY_PRINT); exit; } if ($action === "summary") { echo json_encode([ "ok" => true, "ts" => date("c"), "issues_count" => count($issues), "by_severity" => $severity_count, "incoherences_count" => count($incoherences), "missing_agents_count" => count($missing_agents), "kpis_to_optimize_count" => count($kpis_to_optimize), "top_3_issues" => array_slice($issues, 0, 3), "top_incoherence" => $incoherences[0] ?? null ], JSON_PRETTY_PRINT); exit; } if ($action === "issues_only") { echo json_encode(["ok" => true, "issues" => $issues, "count" => count($issues)], JSON_PRETTY_PRINT); exit; } if ($action === "incoherences_only") { echo json_encode(["ok" => true, "incoherences" => $incoherences, "count" => count($incoherences)], JSON_PRETTY_PRINT); exit; } if ($action === "missing_agents") { echo json_encode(["ok" => true, "missing_agents" => $missing_agents, "count" => count($missing_agents)], JSON_PRETTY_PRINT); exit; } if ($action === "kpis") { echo json_encode(["ok" => true, "kpis_to_optimize" => $kpis_to_optimize, "count" => count($kpis_to_optimize)], JSON_PRETTY_PRINT); exit; } echo json_encode(["ok" => false, "error" => "unknown action", "valid" => ["scan","summary","issues_only","incoherences_only","missing_agents","kpis"]]);