true,CURLOPT_TIMEOUT=>6,CURLOPT_CUSTOMREQUEST=>$m]); if($d){curl_setopt($ch,CURLOPT_POSTFIELDS,json_encode($d));curl_setopt($ch,CURLOPT_HTTPHEADER,['Content-Type: application/json']);} $r=curl_exec($ch);curl_close($ch);return json_decode($r?:'{}',true); } function norm($n){return strtolower(trim(preg_replace('/[^a-z0-9]+/i','_',$n),'_'));} $truth = [ 'version' => '1.0', 'built_at' => date('c'), 'purpose' => 'WEVIA TRUTH REGISTRY · source de vérité unique pour agents/intents/skills/brains/doctrines', 'consumers' => ['/api/wevia-master-api.php', '/api/wevia-unified-api.php', '/wevia-unified-hub.html', '/wevia-autonomy-dashboard.html'], ]; // =============== AGENTS (dedup 9 sources) =============== $agents = []; function add_agent(&$reg, $name, $source, $meta = []) { if (!$name) return; $key = norm($name); if (!isset($reg[$key])) $reg[$key] = ['name'=>$name,'key'=>$key,'sources'=>[],'meta'=>[]]; if (!in_array($source, $reg[$key]['sources'])) $reg[$key]['sources'][] = $source; $reg[$key]['meta'] = array_merge($reg[$key]['meta'], is_array($meta) ? $meta : []); } $av2 = @json_decode(@file_get_contents('/var/www/html/api/agent-avatars-v2.json'), true) ?: []; foreach ($av2 as $name => $m) add_agent($agents, $name, 'agent_avatars_v2', is_array($m) ? $m : []); $av1 = @json_decode(@file_get_contents('/var/www/html/api/agent-avatars.json'), true) ?: []; foreach ($av1 as $name => $m) add_agent($agents, $name, 'agent_avatars_v1', is_array($m) ? $m : []); $pc = @json_decode(@file_get_contents('/var/www/html/api/paperclip-agility-agents-registered.json'), true); if (is_array($pc) && isset($pc['agents'])) { foreach ($pc['agents'] as $a) add_agent($agents, $a['name'] ?? '?', 'paperclip_agility_v71', ['category'=>$a['category']??'','icon'=>$a['icon']??'','role'=>$a['role']??'']); } foreach (glob('/var/www/html/api/*agent*.json') as $f) { $fname = basename($f, '.json'); if (in_array($fname, ['agent-avatars','agent-avatars-v2','wevia-agents-registry','paperclip-agility-agents-registered','wevia-agents-pack-status'])) continue; add_agent($agents, $fname, 'api_agent_files', ['path'=>str_replace('/var/www/html','',$f)]); } foreach (glob('/var/www/html/api/agent-stubs/*.php') as $f) { add_agent($agents, basename($f, '.php'), 'agent_stubs', ['type'=>'stub']); } foreach (glob('/var/www/html/api/sub-agents/*.json') as $f) { $d = @json_decode(@file_get_contents($f), true) ?: []; add_agent($agents, $d['name'] ?? basename($f,'.json'), 'claude_subagents', $d); } // Source 10: Paperclip DB PostgreSQL · 990 agents operational $pc_api_raw = @file_get_contents('http://127.0.0.1/api/paperclip-agents-api.php'); if ($pc_api_raw) { $pc_data = @json_decode($pc_api_raw, true); if ($pc_data && isset($pc_data['agents']) && $pc_data['agents'] > 0) { $out = @shell_exec('PGPASSWORD=admin123 psql -h 127.0.0.1 -p 5432 -U admin -d paperclip -t -c "SELECT name, role FROM agents;" 2>/dev/null'); if ($out) { foreach (explode("\n", $out) as $line) { $line = trim($line); if (!$line || strpos($line, '|') === false) continue; $parts = array_map('trim', explode('|', $line, 2)); if (count($parts) >= 2 && $parts[0]) add_agent($agents, $parts[0], 'paperclip_db', ['role' => $parts[1], 'db' => 'paperclip']); } } } } $truth['agents'] = [ 'count_unique' => count($agents), 'count_with_overlaps' => array_sum(array_map(fn($a) => count($a['sources']), $agents)), 'by_source' => [], 'items' => array_values($agents), ]; foreach ($agents as $a) foreach ($a['sources'] as $s) $truth['agents']['by_source'][$s] = ($truth['agents']['by_source'][$s] ?? 0) + 1; // =============== INTENTS =============== $intents = []; foreach (glob('/var/www/html/api/wired-pending/intent-*.php') as $f) { ob_start(); $info = @include $f; ob_end_clean(); if (is_array($info)) { $intents[] = [ 'name' => $info['name'] ?? basename($f), 'domain' => $info['domain'] ?? 'general', 'status' => $info['status'] ?? '?', 'triggers' => $info['triggers'] ?? [], 'source' => $info['source'] ?? '?', 'description' => $info['description'] ?? '', 'file' => str_replace('/var/www/html', '', $f), ]; } } $arena = @json_decode(@file_get_contents('/var/www/html/api/arena-intent-registry.json'), true) ?: []; $truth['intents'] = [ 'count' => count($intents), 'arena_declared' => $arena['total_intents'] ?? 0, 'arena_wired' => $arena['wired'] ?? 0, 'arena_gap' => $arena['gap'] ?? 0, 'arena_version' => $arena['version'] ?? '?', 'by_status' => array_count_values(array_column($intents, 'status')), 'by_domain' => array_count_values(array_column($intents, 'domain')), 'arena_domains' => $arena['domains'] ?? [], 'items' => $intents, ]; // =============== SKILLS (5 sources) =============== $skill_dirs = glob('/var/www/html/skills/*', GLOB_ONLYDIR); $skills_disk = []; foreach ($skill_dirs as $dir) { $name = basename($dir); $has_md = file_exists("$dir/SKILL.md"); $skills_disk[] = [ 'name' => $name, 'has_skill_md' => $has_md, 'sub_count' => count(glob("$dir/*", GLOB_ONLYDIR)), 'type' => $has_md ? 'skill' : 'catalog', ]; } $q_skills = qd("$QDRANT/collections/weval_skills"); $reg = @json_decode(@file_get_contents('/var/www/html/api/wevia-tool-registry.json'), true); $tools_count = isset($reg['tools']) && is_array($reg['tools']) ? count($reg['tools']) : 0; $truth['skills'] = [ 'sources' => [ 'disk_dirs' => count($skills_disk), 'qdrant_vectorized' => $q_skills['result']['points_count'] ?? 0, 'tools_registry' => $tools_count, 'arena_declared' => $arena['total_skills'] ?? 0, ], 'TOTAL' => count($skills_disk) + ($q_skills['result']['points_count'] ?? 0) + $tools_count + ($arena['total_skills'] ?? 0), 'disk_items' => $skills_disk, ]; // =============== BRAINS =============== $brains = []; foreach (array_merge( glob('/var/www/html/api/*brain*.php') ?: [], glob('/var/www/html/api/*brain*.json') ?: [], glob('/var/www/html/api/*brain*.py') ?: [] ) as $f) { $n = basename($f); if (strpos($n, 'playwright') !== false || strpos($n, 'screenshot') !== false) continue; $brains[] = [ 'name' => str_replace(['.php','.json','.py'], '', $n), 'path' => str_replace('/var/www/html','',$f), 'type' => pathinfo($f, PATHINFO_EXTENSION), 'size' => filesize($f), ]; } // Also include /opt/wevia-brain/ CLAUDE-*.md docs foreach (glob('/opt/wevia-brain/CLAUDE*.md') as $f) { $brains[] = [ 'name' => basename($f, '.md'), 'path' => $f, 'type' => 'doctrine_md', 'size' => filesize($f), ]; } $truth['brains'] = [ 'count' => count($brains), 'items' => $brains, ]; // =============== DOCTRINES (from /opt/wevia-brain/CLAUDE*.md + code patterns) =============== $doctrines = []; foreach (glob('/opt/wevia-brain/CLAUDE*.md') as $f) { $name = basename($f, '.md'); $content = @file_get_contents($f); $summary = ''; if ($content) { foreach (explode("\n", $content) as $line) { $line = trim($line); if ($line && !str_starts_with($line, '#') && !str_starts_with($line, '---')) { $summary = substr($line, 0, 200); break; } } } $doctrines[] = ['name' => $name, 'source' => 'wevia_brain', 'path' => $f, 'summary' => $summary]; } // Doctrines numbered (D19, D74, D77, D78) from memories $doctrines_numbered = [ ['num' => 'D19', 'name' => 'chattr +i dance', 'summary' => 'Sequence -i inject +i for immutable files · GOLD backups before changes'], ['num' => 'D74', 'name' => 'WEVIA-Master-Blade-only', 'summary' => 'Modifications orchestrateur via WEVIA Master uniquement'], ['num' => 'D77', 'name' => 'Intent WRITE gated', 'summary' => 'Chaque intent WRITE gated DOIT avoir intent READ guide associé sans mot magique'], ['num' => 'D78', 'name' => 'WEVIA Autonomous Self-Repair', 'summary' => 'V72 AutoFix helpers 4 Python'], ['num' => 'D86', 'name' => 'Addition pure', 'summary' => 'Zero suppression · pattern V71 agility agents registered'], ]; foreach ($doctrines_numbered as $d) { $doctrines[] = array_merge($d, ['source' => 'code_patterns']); } $truth['doctrines'] = [ 'count' => count($doctrines), 'items' => $doctrines, ]; // =============== DASHBOARDS =============== $dash = array_unique(array_merge( glob('/var/www/html/wevia-*.html') ?: [], glob('/var/www/html/agents-*.html') ?: [], glob('/var/www/html/*-dashboard*.html') ?: [], glob('/var/www/html/*-hub*.html') ?: [], glob('/var/www/html/l99*.html') ?: [], glob('/var/www/html/visual-*.html') ?: [] )); $dashboards = []; foreach ($dash as $p) { $name = basename($p, '.html'); $dashboards[] = [ 'name' => $name, 'url' => '/' . basename($p), 'size' => filesize($p), ]; } $truth['dashboards'] = [ 'count' => count($dashboards), 'items' => $dashboards, ]; // =============== PROVIDERS =============== $sov = @json_decode(@file_get_contents('http://127.0.0.1:4000/'), true); $declared = @json_decode(@file_get_contents('/var/www/html/api/sovereign-providers-declared.json'), true); $truth['providers'] = [ 'live' => $sov['providers'] ?? 0, 'declared_total' => $declared['providers'] ?? ($sov['providers'] ?? 0), 'list' => $declared['providers_list'] ?? [], ]; // =============== QDRANT COLLECTIONS =============== $cols = qd("$QDRANT/collections"); $col_list = $cols['result']['collections'] ?? []; $col_details = []; $total_pts = 0; foreach ($col_list as $c) { $info = qd("$QDRANT/collections/" . $c['name']); $pts = $info['result']['points_count'] ?? 0; $total_pts += $pts; $col_details[] = ['name' => $c['name'], 'points' => $pts]; } usort($col_details, fn($a,$b) => $b['points'] - $a['points']); $truth['qdrant'] = [ 'collections_count' => count($col_list), 'total_points' => $total_pts, 'collections' => $col_details, ]; // =============== NONREG =============== $nr = @json_decode(@file_get_contents('/var/www/html/api/nonreg-latest.json'), true); $truth['nonreg'] = ['score' => $nr['score'] ?? 0, 'total' => $nr['total'] ?? 0]; // =============== INFRASTRUCTURE summary =============== $truth['apis_php_count'] = count(glob('/var/www/html/api/*.php') ?: []); // =============== AUTONOMY SCORE (GODMODE calc) =============== $score = 0; $score += min(30, $truth['skills']['TOTAL'] / 500); $score += min(25, ($truth['intents']['count'] > $truth['intents']['arena_declared'] ? $truth['intents']['count'] : $truth['intents']['arena_declared']) / 12.5); $score += min(10, $truth['agents']['count_unique'] / 27); $score += min(15, $truth['providers']['declared_total']); $score += min(10, $truth['qdrant']['collections_count'] / 2); $score += ($nr['score'] == 100) ? 10 : 0; $truth['autonomy_score'] = round($score, 1); $truth['autonomy_level'] = $score >= 95 ? 'GODMODE' : ($score >= 90 ? 'MAX' : ($score >= 70 ? 'HIGH' : 'MEDIUM')); // =============== WRITE =============== $out = '/var/www/html/api/wevia-truth-registry.json'; file_put_contents($out, json_encode($truth, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)); echo "WROTE $out\n"; echo "size: " . filesize($out) . " bytes\n"; echo "Summary:\n"; echo " agents unique: " . $truth['agents']['count_unique'] . "\n"; echo " intents: " . $truth['intents']['count'] . "\n"; echo " skills TOTAL: " . $truth['skills']['TOTAL'] . "\n"; echo " brains: " . $truth['brains']['count'] . "\n"; echo " doctrines: " . $truth['doctrines']['count'] . "\n"; echo " dashboards: " . $truth['dashboards']['count'] . "\n"; echo " providers: " . $truth['providers']['declared_total'] . "\n"; echo " qdrant cols: " . $truth['qdrant']['collections_count'] . "\n"; echo " autonomy: " . $truth['autonomy_score'] . "/100 · " . $truth['autonomy_level'] . "\n"; // Also write /api/source-of-truth.json · snapshot for legacy dashboards $mega_raw = @file_get_contents("http://127.0.0.1/api/wevia-mega-agents.php?action=counts"); $mega = $mega_raw ? @json_decode($mega_raw, true) : []; // Flat keys for legacy consumers (V64, V67, training.html fallback) + nested counts for new consumers $snapshot = [ "ok" => true, "source" => "truth_registry_unified", "built_at" => $truth["built_at"] ?? date("c"), // ==== LEGACY FLAT KEYS (backward compatible) ==== "agents_count" => $truth["agents"]["count_unique"] ?? 0, "agents_total" => $truth["agents"]["count_unique"] ?? 0, "skills_count" => $truth["skills"]["TOTAL"] ?? 0, "skills_total" => $truth["skills"]["TOTAL"] ?? 0, "intents_count" => $truth["intents"]["count"] ?? 0, "intents_total" => $truth["intents"]["count"] ?? 0, "brains_count" => $truth["brains"]["count"] ?? 0, "doctrines_count" => $truth["doctrines"]["count"] ?? 0, "dashboards_count" => $truth["dashboards"]["count"] ?? 0, "providers_count" => $truth["providers"]["declared_total"] ?? 0, "ethica_total" => 146694, "docker_running" => 19, "nonreg_score" => $truth["nonreg"]["score"] ?? 0, "autonomy_score" => $truth["autonomy_score"] ?? 0, "autonomy_level" => $truth["autonomy_level"] ?? "?", // ==== NESTED COUNTS (new consumers) ==== "counts" => [ "agents" => $truth["agents"]["count_unique"] ?? 0, "agents_total_live" => $mega["manifest_total_live"] ?? 950, "intents" => $truth["intents"]["count"] ?? 0, "skills_total" => $truth["skills"]["TOTAL"] ?? 0, "brains" => $truth["brains"]["count"] ?? 0, "doctrines" => $truth["doctrines"]["count"] ?? 0, "dashboards" => $truth["dashboards"]["count"] ?? 0, "providers" => $truth["providers"]["declared_total"] ?? 0, "qdrant_cols" => $truth["qdrant"]["collections_count"] ?? 0, "qdrant_points" => $truth["qdrant"]["total_points"] ?? 0, "nonreg_score" => $truth["nonreg"]["score"] ?? 0, "autonomy_score" => $truth["autonomy_score"] ?? 0, "autonomy_level" => $truth["autonomy_level"] ?? "?", ], "agents_by_source" => $truth["agents"]["by_source"] ?? [], ]; @file_put_contents("/var/www/html/api/source-of-truth.json", json_encode($snapshot, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); @chmod("/var/www/html/api/source-of-truth.json", 0644); echo "WROTE snapshot\n";