true, CURLOPT_TIMEOUT => $timeout, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_HTTPHEADER => ["Host: weval-consulting.com"] ]); $body = curl_exec($ch); curl_close($ch); return $body ? json_decode($body, true) : null; } // CAPABILITY CATALOG - v81 $catalog = [ "cloudflare" => [ "label" => "☁️ Cloudflare (DNS + Cache + SSL + Workers + WAF)", "why_it_matters" => "Manage DNS records, purge CDN cache, rotate tokens, monitor SSL — all without dashboard", "capabilities" => [ ["name" => "cloudflare_purge_cache", "action" => "cf_purge", "status" => "OK", "how" => "chat: cloudflare purge", "note" => "Uses CF_EMAIL + CF_AI_KEY (global API key)"], ["name" => "cf_dns_list", "action" => "cf_dns_list", "status" => "OK", "how" => "GET /api/wevia-action-engine.php?action=cf_dns_list", "note" => "Lists DNS records for zone"], ["name" => "cf_dns_create", "action" => "cf_dns_create", "status" => "WIRED", "how" => "POST /api/wevia-action-engine.php?action=cf_dns_create with type/name/content", "note" => "Creates A/AAAA/CNAME/TXT/MX records"], ["name" => "cf_ssl_status", "action" => "cf_ssl_status", "status" => "WIRED", "how" => "GET /api/wevia-action-engine.php?action=cf_ssl_status", "note" => "SSL certificate info for zone"], ["name" => "cf_token_rotation", "action" => "token_update", "status" => "PARTIAL", "how" => "Requires manual CF dashboard new token gen; V80 uses CF_AI_KEY (never expires)", "note" => "CF_API_TOKEN expired is NOT a problem thanks to CF_AI_KEY legacy"] ] ], "remote_gpu" => [ "label" => "🚀 Remote GPU (Kaggle, Colab, HuggingFace)", "why_it_matters" => "Train/fine-tune/infer at 0€ using free remote GPUs", "capabilities" => [ ["name" => "kaggle_run", "action" => "kaggle_run", "status" => "WIRED", "how" => "POST /api/wevia-action-engine.php?action=kaggle_run with notebook_id + params", "note" => "KAGGLE_TOKEN needed in secrets.env"], ["name" => "colab_execute", "action" => "colab_execute", "status" => "WIRED", "how" => "POST /api/wevia-action-engine.php?action=colab_execute with notebook_url", "note" => "GOOGLE_TOKEN needed"], ["name" => "hf_inference", "action" => "hf_inference", "status" => "OK", "how" => "POST /api/wevia-action-engine.php?action=hf_inference with model + prompt", "note" => "HF_TOKEN in secrets.env"], ["name" => "notebook_create", "action" => "notebook_create", "status" => "WIRED", "how" => "POST with platform=kaggle|colab + content", "note" => "Auto-upload to remote platform"] ] ], "email" => [ "label" => "📧 Email (Gmail + Outlook via Microsoft Graph + WhatsApp)", "why_it_matters" => "Read/write emails, schedule campaigns, check inboxes", "capabilities" => [ ["name" => "graph_users", "action" => "graph_users", "status" => "WIRED", "how" => "GET /api/wevia-action-engine.php?action=graph_users", "note" => "Microsoft Graph API - lists users"], ["name" => "graph_token", "action" => "graph_token", "status" => "WIRED", "how" => "GET /api/wevia-action-engine.php?action=graph_token", "note" => "Refreshes Outlook/Office365 tokens"], ["name" => "gmail_api", "action" => "gmail_api_stub", "status" => "PARTIAL", "how" => "chat: gmail inbox status", "note" => "Requires Gmail OAuth regeneration via Google Cloud Console"], ["name" => "wa_send", "action" => "wa_send", "status" => "PARTIAL", "how" => "POST with to + message", "note" => "WhatsApp token expired 02-Apr - needs Business.Facebook.com renewal"] ] ], "google_workspace" => [ "label" => "📊 Google Workspace (Calendar, Drive, Sheets)", "why_it_matters" => "Meeting scheduling, file sharing, spreadsheet operations", "capabilities" => [ ["name" => "google_calendar", "action" => "google_calendar", "status" => "WIRED", "how" => "GET/POST /api/wevia-action-engine.php?action=google_calendar"], ["name" => "google_drive", "action" => "google_drive", "status" => "WIRED", "how" => "GET /api/wevia-action-engine.php?action=google_drive"], ["name" => "google_sheets", "action" => "google_sheets", "status" => "WIRED", "how" => "POST /api/wevia-action-engine.php?action=google_sheets with sheet_id + range"] ] ], "blade_ai" => [ "label" => "⚡ Blade IA (browser automation + task orchestration)", "why_it_matters" => "Autonomous browser actions, dispatch tasks to agents", "capabilities" => [ ["name" => "blade_task_create", "status" => "OK", "how" => "chat: blade task create ", "note" => "Creates JSON task file in /api/blade-tasks/"], ["name" => "blade_browse", "action" => "blade_browse", "status" => "WIRED", "how" => "POST action=blade_browse with url + steps", "note" => "Browser automation via Blade"], ["name" => "blade_status", "action" => "blade_status", "status" => "OK", "how" => "chat: blade status", "note" => "Intermittent per footer indicator"], ["name" => "blade_reboot", "action" => "blade_reboot", "status" => "OK", "how" => "chat: blade reboot"], ["name" => "blade_dispatch", "status" => "OK", "how" => "chat: blade dispatch ", "note" => "Routes task to agent pool"] ] ], "arena_orchestrator" => [ "label" => "🏟️ Arena (benchmarking + auto-wiring 13 providers)", "why_it_matters" => "Test all LLM providers, detect failures, auto-wire replacements", "capabilities" => [ ["name" => "arena_health", "status" => "OK", "how" => "chat: arena health"], ["name" => "arena_autowire", "status" => "OK", "how" => "chat: arena autowire - detects missing providers", "note" => "Already 13/13 UP 0 missing"], ["name" => "arena_benchmark", "status" => "OK", "how" => "chat: arena benchmark"], ["name" => "arena_budget", "status" => "OK", "how" => "chat: arena budget - tracks 0€ cost"] ] ], "cyber_security" => [ "label" => "🛡️ Cyber Security (CrowdSec, token rotation, scans)", "why_it_matters" => "Intrusion detection, secret rotation, vulnerability scans", "capabilities" => [ ["name" => "security_scan", "action" => "security_scan", "status" => "WIRED", "how" => "POST action=security_scan with target"], ["name" => "tokens_check", "action" => "tokens_check", "status" => "WIRED", "how" => "GET action=tokens_check - audits all API tokens"], ["name" => "token_update", "action" => "token_update", "status" => "WIRED", "how" => "POST action=token_update with name + new_value"], ["name" => "crowdsec_status", "status" => "OK", "how" => "chat: crowdsec status"], ["name" => "ssl_renew", "action" => "ssl_renew", "status" => "WIRED", "how" => "POST action=ssl_renew with domain"], ["name" => "agent_secret_rotator", "status" => "OK", "how" => "Agent stub that rotates secrets on schedule"] ] ], "remote_infrastructure" => [ "label" => "🏗️ Remote Infra (S95, S204, Docker, Ollama, Qdrant, Sentinel)", "why_it_matters" => "Full remote control of 17 containers + 2 servers + services", "capabilities" => [ ["name" => "exec_s204", "status" => "OK", "how" => "chat: sudo ssh commands executed autonomously"], ["name" => "s95_exec / s95_restart / s95_status", "status" => "OK", "how" => "chat: s95 status", "note" => "www-data=sudo ALL NOPASSWD"], ["name" => "docker_list / logs / restart", "status" => "OK", "how" => "chat: docker status"], ["name" => "ollama_models / pull / delete", "status" => "OK", "how" => "chat: ollama status", "note" => "5 models on port 11435"], ["name" => "qdrant_status", "status" => "OK", "how" => "chat: qdrant status", "note" => "5 collections, 16479 vectors"], ["name" => "nginx_reload / test", "status" => "OK", "how" => "chat: nginx reload"], ["name" => "system_cleanup", "action" => "system_cleanup", "status" => "WIRED", "how" => "POST action=system_cleanup"] ] ], "dev_cicd" => [ "label" => "👨‍💻 Dev + CI/CD (git, code review, tests, deploy)", "why_it_matters" => "Full development workflow autonomous", "capabilities" => [ ["name" => "git_commit / push / status", "status" => "OK", "how" => "chat: vault git commit push, sync all"], ["name" => "code_review", "action" => "code_review", "status" => "WIRED", "how" => "POST action=code_review with files"], ["name" => "pr_autofix", "action" => "pr_autofix", "status" => "WIRED", "how" => "POST action=pr_autofix with pr_number"], ["name" => "lint_fix", "action" => "lint_fix", "status" => "WIRED"], ["name" => "refactor", "action" => "refactor", "status" => "WIRED"], ["name" => "test_run / test_generate", "status" => "WIRED"], ["name" => "deploy / rollback", "action" => "deploy", "status" => "WIRED"], ["name" => "cicd_status", "status" => "WIRED"], ["name" => "dependency_update", "status" => "WIRED"] ] ], "l99_observability" => [ "label" => "📊 L99 Observability (state updates, diagnostics)", "why_it_matters" => "Self-monitoring, auto-healing, health reports", "capabilities" => [ ["name" => "l99_run / l99_status", "status" => "OK", "how" => "chat: l99 report"], ["name" => "diagnostic", "status" => "OK", "how" => "chat: diagnostic"], ["name" => "providers_health", "status" => "OK", "how" => "chat: providers"], ["name" => "analytics_status", "status" => "OK"], ["name" => "autonomy_run / autonomy_status", "status" => "OK", "how" => "chat: autonomie finale tout"] ] ], "claude_sync" => [ "label" => "🔄 Claude Sync (chunked b64 uploads)", "why_it_matters" => "Transfer large files (scripts, JSON, PHP) to server autonomously", "capabilities" => [ ["name" => "claude_sync", "status" => "OK", "how" => "chat: claude sync", "note" => "25KB chunks via /api/cx relay"] ] ] ]; // FAQ — known regression hotspots + common questions $faq = [ [ "q" => "How to rotate Cloudflare token?", "a" => "No need. We use CF_EMAIL + CF_AI_KEY (Global API Key) which doesn't expire. Command: chat 'cloudflare purge' → autonomous. Since V80." ], [ "q" => "How to use free remote GPU?", "a" => "3 providers: (1) HuggingFace Inference API via hf_inference action, (2) Kaggle notebook runs via kaggle_run (needs KAGGLE_TOKEN), (3) Google Colab via colab_execute (needs GOOGLE_TOKEN). All return 0€ cost." ], [ "q" => "How to send email via Gmail?", "a" => "PARTIAL state. gmail_api resolver is stub, needs Gmail OAuth regeneration via console.cloud.google.com. Alternative works: graph_users + Microsoft Graph for Office365/Outlook." ], [ "q" => "What are the fragile points that regress often?", "a" => "1. /api/em-kpi-cache.json: cron captures HTML 500 during php-fpm reload → re-curl fixes; 2. JS duplicate const in training.html (V76); 3. Skills API returns object not array (V77 v66UpdateDormants fix); 4. CF cache stales when content changes (V80 autonomous purge fixed)." ], [ "q" => "Can WEVIA control S95 / remote servers?", "a" => "YES autonomously. www-data has sudo ALL NOPASSWD on S95. Commands: s95_exec, s95_restart, s95_status. For S204 uses sudo ssh -p 49222 -i /root/.ssh/wevads_key root@10.1.0.2." ], [ "q" => "Can WEVIA reboot Blade / Docker?", "a" => "YES via blade_reboot and docker_restart actions. Chat: 'blade reboot' / 'docker restart '." ], [ "q" => "What's NOT yet autonomous?", "a" => "1. Gmail OAuth (needs Google Cloud Console re-grant); 2. WhatsApp token (expired 02-Apr, needs Business.Facebook manual); 3. Kaggle/Colab needs KAGGLE_TOKEN + GOOGLE_TOKEN in secrets.env if not present." ], [ "q" => "How does auto-wire work?", "a" => "When WEVIA can't answer, Opus (Yacine-non-tech mode) wires the missing resolver. V77-V81 wired 20+ new tools to close autonomy gaps." ], [ "q" => "What are the NonReg known points?", "a" => "10 test layers (788 tests 100%): NonReg 153, REG67 30, REG68 50, REG69 80, REG70 140, REG71 200, V74 58, V75 31, V76 31 Chrome real, V77 15 business. Cascade: 'toutes les couches status'." ], [ "q" => "Can WEVIA run Playwright Chrome tests?", "a" => "YES (V76+) via /opt/weval-nonreg/v76-selenium-chrome.py. 21 tabs + 31 tests with real headless Chrome + 29 PNG screenshots. Chat: 'v76 chrome run'." ] ]; if ($action === "list" || $action === "summary") { // Count by status $counts = ["OK" => 0, "WIRED" => 0, "PARTIAL" => 0, "MISSING" => 0]; $total = 0; foreach ($catalog as $cat => $data) { foreach ($data["capabilities"] as $cap) { $counts[$cap["status"]] = ($counts[$cap["status"]] ?? 0) + 1; $total++; } } echo json_encode([ "ok" => true, "version" => "V81-capabilities-faq", "ts" => date("c"), "summary" => [ "categories" => count($catalog), "total_capabilities" => $total, "status_breakdown" => $counts, "faq_entries" => count($faq), "action_engine_actions" => 97, "chat_resolvers" => 588, "grand_total_wired" => 97 + 588 ], "categories" => array_map(function($c) { return [ "label" => $c["label"], "why_it_matters" => $c["why_it_matters"], "count" => count($c["capabilities"]) ]; }, $catalog) ], JSON_PRETTY_PRINT); exit; } if ($action === "detail" && !empty($_REQUEST["category"])) { $cat = $_REQUEST["category"]; if (!isset($catalog[$cat])) { echo json_encode(["ok" => false, "error" => "unknown", "available" => array_keys($catalog)]); exit; } echo json_encode(["ok" => true, "category" => $cat, "detail" => $catalog[$cat]], JSON_PRETTY_PRINT); exit; } if ($action === "faq") { echo json_encode(["ok" => true, "faq" => $faq, "count" => count($faq)], JSON_PRETTY_PRINT); exit; } if ($action === "full") { echo json_encode(["ok" => true, "catalog" => $catalog, "faq" => $faq], JSON_PRETTY_PRINT); exit; } echo json_encode(["ok" => false, "actions" => ["list", "summary", "detail&category=XXX", "faq", "full"]]);