date('c'), 'source'=>'opus5-autonomy-kpi']; // === 1. Truth registry === $truth_raw = @file_get_contents('/var/www/html/api/wevia-truth-registry.json'); $truth = @json_decode((string)$truth_raw, true) ?: []; $R['truth'] = [ 'agents_unique' => $truth['agents']['count_unique'] ?? 0, 'agents_overlaps' => $truth['agents']['count_with_overlaps'] ?? 0, 'apis_php' => $truth['apis_php_count'] ?? 0, 'autonomy_score' => $truth['autonomy_score'] ?? 0, 'intents_count' => $truth['intents']['count'] ?? 0, 'doctrines_count' => $truth['doctrines']['count'] ?? 0, 'dashboards_count' => $truth['dashboards']['count'] ?? 0 ]; // === 2. Plans PG (Phase 1 autonomy) === try { $db = new PDO('pgsql:host=10.1.0.3;port=5432;dbname=adx_system;user=admin;password=admin123', null, null, [PDO::ATTR_TIMEOUT=>5]); $plans_stats = $db->query("SELECT COUNT(*) AS total, COUNT(*) FILTER (WHERE status='done') AS done, COUNT(*) FILTER (WHERE status='failed') AS failed, COUNT(*) FILTER (WHERE status='draft') AS draft, COUNT(*) FILTER (WHERE status='running') AS running, COUNT(*) FILTER (WHERE status='archived') AS archived, COUNT(*) FILTER (WHERE created_at > NOW() - INTERVAL '1 hour') AS last_hour, COUNT(*) FILTER (WHERE name LIKE 'AutoPlan%') AS auto_generated FROM admin.wevia_plans")->fetch(PDO::FETCH_ASSOC); $steps_stats = $db->query("SELECT COUNT(*) AS total_steps, COUNT(*) FILTER (WHERE status='done') AS done_steps, COUNT(*) FILTER (WHERE status='failed') AS failed_steps FROM admin.wevia_plan_steps")->fetch(PDO::FETCH_ASSOC); $R['plans'] = array_merge($plans_stats, $steps_stats); $R['plans']['success_rate_pct'] = $plans_stats['total'] > 0 ? round(($plans_stats['done'] / $plans_stats['total']) * 100, 1) : 0; } catch (Throwable $e) { $R['plans'] = ['err'=>$e->getMessage()]; } // === 3. Phase status === $R['phases'] = [ 'P0_cache_stream_sandbox' => file_exists('/var/www/html/api/opus5-predictive-cache.php') && file_exists('/var/www/html/api/opus5-task-stream.php') && file_exists('/var/www/html/api/opus5-python-sandbox.php') ? 'LIVE' : 'MISSING', 'P1_plugin_n8n_graph' => file_exists('/var/www/html/api/opus5-plugin-store.php') && file_exists('/var/www/html/api/opus5-n8n-generator.php') && file_exists('/var/www/html/api/opus5-knowledge-graph.php') ? 'LIVE' : 'MISSING', 'P2_tmux_grid_orch3' => file_exists('/var/www/html/api/opus5-ssh-tmux-stream.php') && file_exists('/var/www/html/api/opus5-gpu-grid.php') && file_exists('/var/www/html/api/opus5-autonomous-orchestrator-v3.php') ? 'LIVE' : 'MISSING', 'Phase1_registry_orch' => file_exists('/var/www/html/api/opus5-plan-registry.php') && file_exists('/var/www/html/api/opus5-plan-orchestrator.php') ? 'LIVE' : 'MISSING', 'Phase2_nl_parser' => file_exists('/var/www/html/api/opus5-plan-from-text.php') && file_exists('/var/www/html/api/opus5-plan-from-text-action.php') ? 'LIVE' : 'MISSING' ]; // === 4. Health stack === $R['health'] = []; // PHP endpoints via curl, JSON files via filesystem $php_endpoints = [ 'cache' => 'http://127.0.0.1/api/opus5-predictive-cache.php?action=stats', 'nonreg' => 'http://127.0.0.1/api/nonreg-api.php?cat=all', 'plan_registry' => 'http://127.0.0.1/api/opus5-plan-registry.php?action=list&limit=1', 'plan_from_text' => 'http://127.0.0.1/api/opus5-plan-from-text-action.php?dry_run=1' ]; foreach ($php_endpoints as $k => $url) { $ch = curl_init($url); curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER=>true, CURLOPT_TIMEOUT=>5, CURLOPT_FOLLOWLOCATION=>true]); $body = curl_exec($ch); $http = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); $R['health'][$k] = $http === 200 ? 'OK' : "HTTP$http"; } $json_files = [ 'l99' => '/var/www/html/api/l99-state.json', 'truth' => '/var/www/html/api/wevia-truth-registry.json' ]; foreach ($json_files as $k => $path) { $R['health'][$k] = (file_exists($path) && filesize($path) > 100) ? 'OK' : 'MISSING'; } // === 5. Intents Phase 1/2 mapped === $R['intents_autonomy'] = [ 'implement_plan' => file_exists('/var/www/html/api/wired-pending/intent-opus4-implement_plan.php') ? 'WIRED' : 'MISSING', 'plan_list' => file_exists('/var/www/html/api/wired-pending/intent-opus4-plan_list.php') ? 'WIRED' : 'MISSING', 'plan_status' => file_exists('/var/www/html/api/wired-pending/intent-opus4-plan_status.php') ? 'WIRED' : 'MISSING', 'plan_from_text' => file_exists('/var/www/html/api/wired-pending/intent-opus4-plan_from_text.php') ? 'WIRED' : 'MISSING' ]; // === 6. Score synthèse === $phases_live = 0; foreach ($R['phases'] as $v) if ($v === 'LIVE') $phases_live++; $intents_wired = 0; foreach ($R['intents_autonomy'] as $v) if ($v === 'WIRED') $intents_wired++; $health_ok = 0; foreach ($R['health'] as $v) if ($v === 'OK') $health_ok++; $R['synthesis'] = [ 'phases_live' => "$phases_live/5", 'phases_pct' => round($phases_live / 5 * 100, 1), 'intents_wired' => "$intents_wired/4", 'intents_pct' => round($intents_wired / 4 * 100, 1), 'health_ok' => "$health_ok/6", 'health_pct' => round($health_ok / 6 * 100, 1), 'overall_autonomy_pct' => round( ($phases_live / 5 * 30) + // 30% poids phases ($intents_wired / 4 * 25) + // 25% intents ($health_ok / 6 * 20) + // 20% health ($R['truth']['autonomy_score'] / 100 * 25), // 25% truth registry 1 ), 'grade' => 'computed below' ]; $pct = $R['synthesis']['overall_autonomy_pct']; $R['synthesis']['grade'] = $pct >= 95 ? 'A+ GODMODE' : ($pct >= 85 ? 'A EXCELLENT' : ($pct >= 70 ? 'B GOOD' : ($pct >= 50 ? 'C AVERAGE' : 'D NEEDS WORK'))); $R['doctrine'] = '90 — KPI autonomie consolidé (lecture seule, agrège truth+plans+phases+health)'; $R['total_ms'] = round((microtime(true) - $t0) * 1000); echo json_encode($R, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);