/dev/null | tail -n +2 | wc -l"); if ($out !== null) $docker_count = (int)trim($out); if ($docker_count === 0 && isset($sot["docker_running"])) $docker_count = (int)$sot["docker_running"]; // V83 summary (via architecture_quality) $v83 = ["kpis" => null, "ok" => null, "warn" => null, "fail" => null, "complete_pct" => null]; if (is_readable("/var/www/html/api/v83-business-kpi-latest.json")) { $v83_raw = @json_decode(@file_get_contents("/var/www/html/api/v83-business-kpi-latest.json"), true); if ($v83_raw && isset($v83_raw["summary"])) { $v83 = [ "kpis" => $v83_raw["summary"]["total_kpis"] ?? null, "ok" => $v83_raw["summary"]["ok"] ?? null, "warn" => $v83_raw["summary"]["warn"] ?? null, "fail" => $v83_raw["summary"]["fail"] ?? null, "complete_pct" => $v83_raw["summary"]["data_completeness_pct"] ?? null ]; } } // Orphans (from V83 architecture_quality KPI) $orphans_count = 0; if (is_readable("/tmp/wevia-pages-registry-cache.json")) { $reg = @json_decode(@file_get_contents("/tmp/wevia-pages-registry-cache.json"), true); if ($reg && isset($reg["orphans"])) $orphans_count = (int)$reg["orphans"]; } // Build unified schema (SINGLE SOURCE OF TRUTH) $response = [ "ok" => true, "version" => "v118-kpi-unified", "doctrine" => "zero doublon single source-of-truth", "ts" => date("c"), "cache_hit" => false, "cache_ttl_sec" => $cache_ttl, "providers" => [ "total" => $sot["providers_count"] ?? ($sot["counts"]["providers"] ?? 0), "ok" => $tokens["summary"]["live_ok"] ?? null, "expired" => $tokens["summary"]["expired_ko"] ?? null, "health_pct" => $tokens["summary"]["health_pct"] ?? null ], "agents" => [ "active" => $sot["agents_count"] ?? 0, "total_live" => $sot["counts"]["agents_total_live"] ?? ($sot["agents_total"] ?? 0) ], "skills" => [ "count" => $sot["skills_count"] ?? 0, "total" => $sot["skills_total"] ?? ($sot["counts"]["skills_total"] ?? 0) ], "intents" => [ "count" => $sot["intents_count"] ?? ($sot["counts"]["intents"] ?? 0), "total" => $sot["intents_total"] ?? 0 ], "docker" => [ "running" => $docker_count ], "orphans" => [ "count" => $orphans_count, "status" => ($orphans_count === 0) ? "ok" : "warn" ], "nonreg" => [ "pass" => $nonreg["pass"] ?? 0, "fail" => $nonreg["fail"] ?? 0, "total" => ($nonreg["pass"] ?? 0) + ($nonreg["fail"] ?? 0), "score" => $nonreg["score"] ?? 0, "ts" => $nonreg["ts"] ?? null ], "v83" => $v83, "autonomy" => [ "score" => $sot["autonomy_score"] ?? 0, "level" => $sot["autonomy_level"] ?? "UNKNOWN" ], "qdrant" => [ "collections" => $sot["counts"]["qdrant_cols"] ?? 0, "points" => $sot["counts"]["qdrant_points"] ?? 0 ], "dashboards" => [ "count" => $sot["dashboards_count"] ?? ($sot["counts"]["dashboards"] ?? 0) ], "brains" => [ "count" => $sot["brains_count"] ?? ($sot["counts"]["brains"] ?? 0) ], "doctrines" => [ "count" => $sot["doctrines_count"] ?? ($sot["counts"]["doctrines"] ?? 0) ], "business" => [ "cash_collected_month_keur" => $sot["cash_collected_month_keur"] ?? 0, "cash_collected_ytd_keur" => $sot["cash_collected_ytd_keur"] ?? 0, "cash_target_month_keur" => $sot["cash_target_month_keur"] ?? 0, "dso_days" => $sot["dso_days"] ?? 0 ], "ethica" => [ "total_hcps" => $sot["ethica_total"] ?? 0 ], "sources_used" => [ "source_of_truth_json" => !empty($sot), "nonreg_latest" => !empty($nonreg), "token_health_cache" => !empty($tokens), "v83_latest" => ($v83["kpis"] !== null), "docker_live" => ($docker_count > 0) ] ]; // Write cache @file_put_contents($cache_file, json_encode($response, JSON_PRETTY_PRINT)); echo json_encode($response, JSON_PRETTY_PRINT);