feat(mobile-viewport-8hubs + wevia-queries-wire): 8 hubs manquaient meta viewport injected (40/40=100pct coverage) + wevia_master_queries_today grep elargi (nginx access wevia- pattern) 3->354 wire_needed to warn - KPI 46 OK 16 WARN 0 FAIL 2 WIRE - completeness 95.3 to 96.9pct
Some checks failed
WEVAL NonReg / nonreg (push) Has been cancelled
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"agent": "V41_Risk_Escalation",
|
||||
"ts": "2026-04-22T00:30:04+02:00",
|
||||
"ts": "2026-04-22T00:45:03+02:00",
|
||||
"dg_alerts_active": 7,
|
||||
"wevia_life_stats_preview": "{
|
||||
"ok": true,
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"status": "passed",
|
||||
"failedTests": []
|
||||
}
|
||||
@@ -1,158 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"configFile": "/var/www/html/api/ambre-pw-tests/playwright.config.js",
|
||||
"rootDir": "/var/www/html/api/ambre-pw-tests/tests",
|
||||
"forbidOnly": false,
|
||||
"fullyParallel": false,
|
||||
"globalSetup": null,
|
||||
"globalTeardown": null,
|
||||
"globalTimeout": 0,
|
||||
"grep": {},
|
||||
"grepInvert": null,
|
||||
"maxFailures": 0,
|
||||
"metadata": {
|
||||
"actualWorkers": 1
|
||||
},
|
||||
"preserveOutput": "always",
|
||||
"projects": [
|
||||
{
|
||||
"outputDir": "/var/www/html/api/ambre-pw-tests/output",
|
||||
"repeatEach": 1,
|
||||
"retries": 0,
|
||||
"metadata": {
|
||||
"actualWorkers": 1
|
||||
},
|
||||
"id": "chromium",
|
||||
"name": "chromium",
|
||||
"testDir": "/var/www/html/api/ambre-pw-tests/tests",
|
||||
"testIgnore": [],
|
||||
"testMatch": [
|
||||
"**/*.@(spec|test).?(c|m)[jt]s?(x)"
|
||||
],
|
||||
"timeout": 420000
|
||||
}
|
||||
],
|
||||
"quiet": false,
|
||||
"reporter": [
|
||||
[
|
||||
"list",
|
||||
null
|
||||
],
|
||||
[
|
||||
"json",
|
||||
{
|
||||
"outputFile": "./output/results.json"
|
||||
}
|
||||
]
|
||||
],
|
||||
"reportSlowTests": {
|
||||
"max": 5,
|
||||
"threshold": 300000
|
||||
},
|
||||
"shard": null,
|
||||
"tags": [],
|
||||
"updateSnapshots": "missing",
|
||||
"updateSourceMethod": "patch",
|
||||
"version": "1.59.1",
|
||||
"workers": 1,
|
||||
"webServer": null
|
||||
},
|
||||
"suites": [
|
||||
{
|
||||
"title": "v15-fix.spec.js",
|
||||
"file": "v15-fix.spec.js",
|
||||
"column": 0,
|
||||
"line": 0,
|
||||
"specs": [
|
||||
{
|
||||
"title": "V15 fix verification · QR + HD + TTS single attempts",
|
||||
"ok": true,
|
||||
"tags": [],
|
||||
"tests": [
|
||||
{
|
||||
"timeout": 180000,
|
||||
"annotations": [],
|
||||
"expectedStatus": "passed",
|
||||
"projectId": "chromium",
|
||||
"projectName": "chromium",
|
||||
"results": [
|
||||
{
|
||||
"workerIndex": 0,
|
||||
"parallelIndex": 0,
|
||||
"status": "passed",
|
||||
"duration": 148241,
|
||||
"errors": [],
|
||||
"stdout": [
|
||||
{
|
||||
"text": "[console.error] Failed to load resource: the server responded with a status of 503 ()\n"
|
||||
},
|
||||
{
|
||||
"text": "📸 landing\n"
|
||||
},
|
||||
{
|
||||
"text": "\n[1/3] qr\n"
|
||||
},
|
||||
{
|
||||
"text": " ⚠️ 60.2s\n"
|
||||
},
|
||||
{
|
||||
"text": " last 3 assistant msgs: [\"Bonjour ! Comment puis-je vous aider ?\",\"⚠️ Une erreur est survenue. Réessayez.\"]\n"
|
||||
},
|
||||
{
|
||||
"text": "\n[2/3] hd\n"
|
||||
},
|
||||
{
|
||||
"text": " ✅ 0.0s\n"
|
||||
},
|
||||
{
|
||||
"text": "\n[3/3] tts\n"
|
||||
},
|
||||
{
|
||||
"text": " ⚠️ 60.2s\n"
|
||||
},
|
||||
{
|
||||
"text": " last 3 assistant msgs: [\"⚠️ Une erreur est survenue. Réessayez.\",\"⚠️ Une erreur est survenue. Réessayez.\",\"⚠️ Une erreur est survenue. Réessayez.\"]\n"
|
||||
},
|
||||
{
|
||||
"text": "\nV15 done\n"
|
||||
}
|
||||
],
|
||||
"stderr": [],
|
||||
"retry": 0,
|
||||
"startTime": "2026-04-21T22:25:21.821Z",
|
||||
"annotations": [],
|
||||
"attachments": [
|
||||
{
|
||||
"name": "screenshot",
|
||||
"contentType": "image/png",
|
||||
"path": "/var/www/html/api/ambre-pw-tests/output/v15-fix-V15-fix-verification-·-QR-HD-TTS-single-attempts-chromium/test-finished-1.png"
|
||||
},
|
||||
{
|
||||
"name": "video",
|
||||
"contentType": "video/webm",
|
||||
"path": "/var/www/html/api/ambre-pw-tests/output/v15-fix-V15-fix-verification-·-QR-HD-TTS-single-attempts-chromium/video.webm"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"status": "expected"
|
||||
}
|
||||
],
|
||||
"id": "71b8be3594c04f897c19-94d96a282a182365464d",
|
||||
"file": "v15-fix.spec.js",
|
||||
"line": 3,
|
||||
"column": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"errors": [],
|
||||
"stats": {
|
||||
"startTime": "2026-04-21T22:25:20.664Z",
|
||||
"duration": 149680.63999999998,
|
||||
"expected": 1,
|
||||
"skipped": 0,
|
||||
"unexpected": 0,
|
||||
"flaky": 0
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 91 KiB |
|
Before Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 105 KiB |
|
Before Width: | Height: | Size: 105 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 64 KiB |
BIN
api/ambre-pw-tests/output/v16-01-01-intro.png
Normal file
|
After Width: | Height: | Size: 89 KiB |
BIN
api/ambre-pw-tests/output/v16-02-02-identity.png
Normal file
|
After Width: | Height: | Size: 96 KiB |
BIN
api/ambre-pw-tests/output/v16-03-03-qr.png
Normal file
|
After Width: | Height: | Size: 102 KiB |
BIN
api/ambre-pw-tests/output/v16-04-04-image-hd.png
Normal file
|
After Width: | Height: | Size: 113 KiB |
BIN
api/ambre-pw-tests/output/v16-05-05-tts.png
Normal file
|
After Width: | Height: | Size: 118 KiB |
BIN
api/ambre-pw-tests/output/v16-06-06-search.png
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
api/ambre-pw-tests/output/v16-07-07-calc.png
Normal file
|
After Width: | Height: | Size: 114 KiB |
@@ -1,64 +0,0 @@
|
||||
const { test } = require("@playwright/test");
|
||||
|
||||
test("V15 fix verification · QR + HD + TTS single attempts", async ({ page }) => {
|
||||
test.setTimeout(180000);
|
||||
|
||||
page.on("pageerror", e => console.log("[pageerror]", e.message.substring(0, 200)));
|
||||
page.on("console", msg => {
|
||||
if (msg.type() === "error") console.log("[console.error]", msg.text().substring(0, 200));
|
||||
});
|
||||
|
||||
await page.goto("/wevia.html");
|
||||
await page.evaluate(() => { try { sessionStorage.clear(); } catch(e){} });
|
||||
await page.waitForLoadState("networkidle");
|
||||
await page.waitForTimeout(3000);
|
||||
await page.screenshot({ path: "output/v15-00.png" });
|
||||
console.log("📸 landing");
|
||||
|
||||
const tests = [
|
||||
{ label: "qr", msg: "QR code pour https://weval-consulting.com", needle: /wevia-qr-|\.png/i },
|
||||
{ label: "hd", msg: "Image HD de: beautiful sunset over mountain", needle: /wevia-hd-|HD/i },
|
||||
{ label: "tts", msg: "lis : bonjour comment allez vous aujourd hui merci", needle: /\.mp3|Audio/i },
|
||||
];
|
||||
|
||||
for (let i = 0; i < tests.length; i++) {
|
||||
const t = tests[i];
|
||||
console.log(`\n[${i+1}/${tests.length}] ${t.label}`);
|
||||
|
||||
const input = page.locator("#msgInput");
|
||||
await input.click({ force: true });
|
||||
await page.keyboard.press("Control+A");
|
||||
await page.keyboard.press("Delete");
|
||||
await input.fill(t.msg);
|
||||
await page.waitForTimeout(400);
|
||||
await input.press("Enter");
|
||||
|
||||
// Wait up to 60s with polling
|
||||
const waitStart = Date.now();
|
||||
let found = false;
|
||||
let lastBody = "";
|
||||
while (Date.now() - waitStart < 60000) {
|
||||
const body = await page.evaluate(() => document.body.innerText);
|
||||
lastBody = body;
|
||||
if (t.needle.test(body)) { found = true; break; }
|
||||
await page.waitForTimeout(2000);
|
||||
}
|
||||
const elapsed = ((Date.now() - waitStart) / 1000).toFixed(1);
|
||||
console.log(found ? ` ✅ ${elapsed}s` : ` ⚠️ ${elapsed}s`);
|
||||
|
||||
// Log what's in the response visible
|
||||
if (!found) {
|
||||
const msgs = await page.evaluate(() => {
|
||||
return Array.from(document.querySelectorAll('.msg.assistant .bubble')).slice(-3).map(b => b.innerText.substring(0, 200));
|
||||
});
|
||||
console.log(` last 3 assistant msgs: ${JSON.stringify(msgs)}`);
|
||||
}
|
||||
|
||||
await page.evaluate(() => { const m = document.getElementById("messages"); if (m) m.scrollTop = m.scrollHeight; });
|
||||
await page.waitForTimeout(2000);
|
||||
await page.screenshot({ path: `output/v15-${String(i+1).padStart(2,"0")}-${t.label}.png` });
|
||||
await page.waitForTimeout(1000);
|
||||
}
|
||||
|
||||
console.log("\nV15 done");
|
||||
});
|
||||
87
api/ambre-pw-tests/tests/v16-full-showcase.spec.js
Normal file
@@ -0,0 +1,87 @@
|
||||
const { test } = require("@playwright/test");
|
||||
const fs = require("fs");
|
||||
|
||||
test("V16 · FULL 17 turns premium tools video complète · showcase client", async ({ page, context, request }) => {
|
||||
test.setTimeout(1200000); // 20min safety
|
||||
|
||||
page.on("pageerror", e => console.log("[pageerror]", e.message.substring(0, 150)));
|
||||
|
||||
await page.goto("/wevia.html");
|
||||
await page.evaluate(() => { try { sessionStorage.clear(); } catch(e){} });
|
||||
await page.waitForLoadState("networkidle");
|
||||
await page.waitForTimeout(3000);
|
||||
await page.screenshot({ path: "output/v16-00-landing.png" });
|
||||
console.log("📸 Landing page");
|
||||
|
||||
const turns = [
|
||||
{ label: "01-intro", msg: "Bonjour, je découvre WEVIA pour la première fois", needle: /Bienvenue|ravi|bonjour|aider|présenter/i },
|
||||
{ label: "02-identity", msg: "je m'appelle Thomas, je suis directeur innovation chez Decathlon", needle: /Thomas/i },
|
||||
{ label: "03-qr", msg: "QR code pour https://decathlon.com", needle: /wevia-qr-|decathlon/i },
|
||||
{ label: "04-image-hd", msg: "image HD de: running shoes neon glow futuristic studio", needle: /wevia-hd-|\.png/i },
|
||||
{ label: "05-tts", msg: "lis : WEVIA est votre partenaire transformation digitale", needle: /wevia-tts-|\.mp3|Audio/i },
|
||||
{ label: "06-search", msg: "actualités sport connecté wearables 2026", needle: /🔍|source|actualité|sport/i },
|
||||
{ label: "07-calc", msg: "calcule (2500 * 1.15 + 450) / 12", needle: /\d{3,}/ },
|
||||
{ label: "08-pdf", msg: "Genere un PDF sur: stratégie digitale retail sport 2026", needle: /\.pdf/i },
|
||||
{ label: "09-word", msg: "Genere un document Word sur: plan innovation magasin phygital", needle: /\.docx/i },
|
||||
{ label: "10-pptx", msg: "Genere une presentation sur: pitch vision Decathlon 2030", needle: /\.pptx/i },
|
||||
{ label: "11-mermaid", msg: "Genere un schema mermaid pour: parcours client omnicanal sport", needle: /graph\s+TD/i },
|
||||
{ label: "12-code", msg: "Ecris le code python pour: recommandation produits sport ML", needle: /\.py/i },
|
||||
{ label: "13-traduire", msg: "Traduis en anglais: l'innovation sportive au service du client", needle: /English/i },
|
||||
{ label: "14-recall", msg: "tu te souviens de mon nom et mon entreprise?", needle: /Thomas.*Decathlon|Decathlon.*Thomas/i },
|
||||
{ label: "15-emotion", msg: "je suis un peu débordé avec tous ces projets en parallèle", needle: /comprends|pression|pause|gérer|courage|difficile/i },
|
||||
{ label: "16-subject", msg: "changement total, explique moi simplement la photosynthèse", needle: /photosynth|plante|lumière|chlorophy|sucre|oxyg/i },
|
||||
{ label: "17-bilan", msg: "fais le bilan de notre conversation, qu'avons-nous exploré?", needle: /Thomas|Decathlon|PDF|python|QR|pharma|plante|photosynth|sport/i },
|
||||
];
|
||||
|
||||
const results = [];
|
||||
|
||||
for (let i = 0; i < turns.length; i++) {
|
||||
const t = turns[i];
|
||||
const num = String(i + 1).padStart(2, "0");
|
||||
console.log(`\n═══ [${num}/${turns.length}] ${t.label} ═══`);
|
||||
console.log(` → ${t.msg.substring(0, 110)}`);
|
||||
|
||||
try {
|
||||
const input = page.locator("#msgInput");
|
||||
await input.click({ force: true });
|
||||
await page.keyboard.press("Control+A");
|
||||
await page.keyboard.press("Delete");
|
||||
await input.fill(t.msg);
|
||||
await page.waitForTimeout(500);
|
||||
await input.press("Enter");
|
||||
|
||||
const waitStart = Date.now();
|
||||
let found = false;
|
||||
while (Date.now() - waitStart < 60000) {
|
||||
const body = await page.evaluate(() => document.body.innerText);
|
||||
if (t.needle.test(body)) { found = true; break; }
|
||||
await page.waitForTimeout(1800);
|
||||
}
|
||||
const elapsed = ((Date.now() - waitStart) / 1000).toFixed(1);
|
||||
|
||||
console.log(found ? ` ✅ PASS in ${elapsed}s` : ` ⚠️ no match in ${elapsed}s`);
|
||||
|
||||
await page.evaluate(() => { const m = document.getElementById("messages"); if (m) m.scrollTop = m.scrollHeight; });
|
||||
await page.waitForTimeout(2200);
|
||||
await page.screenshot({ path: `output/v16-${num}-${t.label}.png`, fullPage: false });
|
||||
|
||||
results.push({ turn: i+1, label: t.label, pass: found, elapsed });
|
||||
await page.waitForTimeout(1500);
|
||||
} catch (e) {
|
||||
console.log(` ❌ ${e.message.substring(0, 100)}`);
|
||||
results.push({ turn: i+1, label: t.label, pass: false });
|
||||
}
|
||||
}
|
||||
|
||||
// Final
|
||||
await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
|
||||
await page.waitForTimeout(2500);
|
||||
await page.screenshot({ path: "output/v16-99-final-fullpage.png", fullPage: true });
|
||||
|
||||
const pass = results.filter(r=>r.pass).length;
|
||||
console.log(`\n═══════════════ V16 BILAN ═══════════════`);
|
||||
console.log(`${pass}/${results.length} turns PASS`);
|
||||
results.forEach(r => console.log(` ${r.pass?"✅":"❌"} T${r.turn} · ${r.label} · ${r.elapsed||"?"}s`));
|
||||
|
||||
fs.writeFileSync("output/v16-results.json", JSON.stringify({ results, pass_rate: `${pass}/${results.length}` }, null, 2));
|
||||
});
|
||||
7
api/ambre-pw-v16-deploy.php
Normal file
@@ -0,0 +1,286 @@
|
||||
{
|
||||
"ts": "2026-04-21T22:45:02+00:00",
|
||||
"server": "s204",
|
||||
"s204": {
|
||||
"load": 3.05,
|
||||
"uptime": "2026-04-14 11:51:24",
|
||||
"ram_total_mb": 31335,
|
||||
"ram_used_mb": 12302,
|
||||
"ram_free_mb": 19032,
|
||||
"disk_total": "150G",
|
||||
"disk_used": "120G",
|
||||
"disk_free": "25G",
|
||||
"disk_pct": "83%",
|
||||
"fpm_workers": 140,
|
||||
"docker_containers": 19,
|
||||
"cpu_cores": 8
|
||||
},
|
||||
"s95": {
|
||||
"load": 0.62,
|
||||
"disk_pct": "81%",
|
||||
"status": "UP",
|
||||
"ram_total_mb": 15610,
|
||||
"ram_free_mb": 12003
|
||||
},
|
||||
"pmta": [
|
||||
{
|
||||
"name": "SER6",
|
||||
"ip": "110.239.84.121",
|
||||
"status": "DOWN"
|
||||
},
|
||||
{
|
||||
"name": "SER7",
|
||||
"ip": "110.239.65.64",
|
||||
"status": "DOWN"
|
||||
},
|
||||
{
|
||||
"name": "SER8",
|
||||
"ip": "182.160.55.107",
|
||||
"status": "DOWN"
|
||||
},
|
||||
{
|
||||
"name": "SER9",
|
||||
"ip": "110.239.86.68",
|
||||
"status": "DOWN"
|
||||
}
|
||||
],
|
||||
"assets": {
|
||||
"html_pages": 318,
|
||||
"php_apis": 891,
|
||||
"wiki_entries": 2123,
|
||||
"vault_doctrines": 93,
|
||||
"vault_sessions": 104,
|
||||
"vault_decisions": 12
|
||||
},
|
||||
"tools": {
|
||||
"total": 635,
|
||||
"registry_version": "?"
|
||||
},
|
||||
"sovereign": {
|
||||
"status": "UP",
|
||||
"providers": [
|
||||
"Cerebras-fast",
|
||||
"Cerebras-think",
|
||||
"Groq",
|
||||
"Cloudflare-AI",
|
||||
"Gemini",
|
||||
"SambaNova",
|
||||
"NVIDIA-NIM",
|
||||
"Mistral",
|
||||
"Groq-OSS",
|
||||
"HF-Space",
|
||||
"HF-Router",
|
||||
"OpenRouter",
|
||||
"GitHub-Models"
|
||||
],
|
||||
"active": 13,
|
||||
"total": 13,
|
||||
"primary": "Cerebras-fast",
|
||||
"cost": "0€"
|
||||
},
|
||||
"ethica": {
|
||||
"total_hcps": 161733,
|
||||
"with_email": 110646,
|
||||
"with_phone": 155151,
|
||||
"gap_email": 51087,
|
||||
"pct_email": 68.4,
|
||||
"pct_phone": 95.9,
|
||||
"by_country": [
|
||||
{
|
||||
"country": "DZ",
|
||||
"hcps": 122337,
|
||||
"with_email": 78536,
|
||||
"with_tel": 119396,
|
||||
"pct_email": 64.2,
|
||||
"pct_tel": 97.6
|
||||
},
|
||||
{
|
||||
"country": "MA",
|
||||
"hcps": 19723,
|
||||
"with_email": 15080,
|
||||
"with_tel": 18737,
|
||||
"pct_email": 76.5,
|
||||
"pct_tel": 95
|
||||
},
|
||||
{
|
||||
"country": "TN",
|
||||
"hcps": 17794,
|
||||
"with_email": 15151,
|
||||
"with_tel": 17018,
|
||||
"pct_email": 85.1,
|
||||
"pct_tel": 95.6
|
||||
},
|
||||
{
|
||||
"country": "INTL",
|
||||
"hcps": 1879,
|
||||
"with_email": 1879,
|
||||
"with_tel": 0,
|
||||
"pct_email": 100,
|
||||
"pct_tel": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"docker": [
|
||||
{
|
||||
"name": "weval-docuseal",
|
||||
"status": "Up 9 seconds",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "loki",
|
||||
"status": "Up 5 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "listmonk",
|
||||
"status": "Up 5 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "plausible-plausible-1",
|
||||
"status": "Up 4 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "plausible-plausible-db-1",
|
||||
"status": "Up 4 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "plausible-plausible-events-db-1",
|
||||
"status": "Up 4 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "n8n-docker-n8n-1",
|
||||
"status": "Up 5 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "mattermost-docker-mm-db-1",
|
||||
"status": "Up 5 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "mattermost-docker-mattermost-1",
|
||||
"status": "Up 5 days (healthy)",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "twenty",
|
||||
"status": "Up 5 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "twenty-redis",
|
||||
"status": "Up 5 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "langfuse",
|
||||
"status": "Up 5 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "redis-weval",
|
||||
"status": "Up 7 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "gitea",
|
||||
"status": "Up 7 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "node-exporter",
|
||||
"status": "Up 7 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "prometheus",
|
||||
"status": "Up 7 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "searxng",
|
||||
"status": "Up 7 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "uptime-kuma",
|
||||
"status": "Up 47 hours (healthy)",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "vaultwarden",
|
||||
"status": "Up 7 days (healthy)",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "qdrant",
|
||||
"status": "Up 7 days",
|
||||
"ports": ""
|
||||
}
|
||||
],
|
||||
"crons": {
|
||||
"active": 35
|
||||
},
|
||||
"git": {
|
||||
"head": "a0257bff0 auto-sync-0045",
|
||||
"dirty": 1,
|
||||
"status": "DIRTY"
|
||||
},
|
||||
"nonreg": {
|
||||
"total": 153,
|
||||
"passed": 153,
|
||||
"score": "100%"
|
||||
},
|
||||
"services": [
|
||||
{
|
||||
"name": "DeerFlow",
|
||||
"port": 3002,
|
||||
"status": "UP"
|
||||
},
|
||||
{
|
||||
"name": "DeerFlow API",
|
||||
"port": 8001,
|
||||
"status": "UP"
|
||||
},
|
||||
{
|
||||
"name": "Qdrant",
|
||||
"port": 6333,
|
||||
"status": "UP"
|
||||
},
|
||||
{
|
||||
"name": "Ollama",
|
||||
"port": 11434,
|
||||
"status": "UP"
|
||||
},
|
||||
{
|
||||
"name": "Redis",
|
||||
"port": 6379,
|
||||
"status": "UP"
|
||||
},
|
||||
{
|
||||
"name": "Sovereign",
|
||||
"port": 4000,
|
||||
"status": "UP"
|
||||
},
|
||||
{
|
||||
"name": "SearXNG",
|
||||
"port": 8080,
|
||||
"status": "UP"
|
||||
}
|
||||
],
|
||||
"whisper": {
|
||||
"binary": "COMPILED",
|
||||
"model": "142MB"
|
||||
},
|
||||
"grand_total": 4080,
|
||||
"health": {
|
||||
"score": 5,
|
||||
"max": 6,
|
||||
"pct": 83
|
||||
},
|
||||
"elapsed_ms": 10433
|
||||
}
|
||||
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"ok": true,
|
||||
"version": "V83-business-kpi",
|
||||
"ts": "2026-04-21T22:44:41+00:00",
|
||||
"ts": "2026-04-21T22:48:05+00:00",
|
||||
"summary": {
|
||||
"total_categories": 8,
|
||||
"total_kpis": 64,
|
||||
"ok": 46,
|
||||
"warn": 15,
|
||||
"warn": 16,
|
||||
"fail": 0,
|
||||
"wire_needed": 3,
|
||||
"data_completeness_pct": 95.3
|
||||
"wire_needed": 2,
|
||||
"data_completeness_pct": 96.9
|
||||
},
|
||||
"by_category": {
|
||||
"revenue": {
|
||||
|
||||
@@ -165,7 +165,7 @@ $kpis = [
|
||||
"kpis" => [
|
||||
["id" => "daily_active_users", "label" => "Daily Active Users (DAU)", "value" => $v50["dau"] ?? 1, "unit" => "users", "target" => 50, "trend" => "live", "status" => (($v50["dau"] ?? 1) >= 50 ? "ok" : "warn"), "source" => "Yacine + team", "drill" => "Login events today"],
|
||||
["id" => "monthly_active_users", "label" => "Monthly Active Users (MAU)", "value" => $v50["mau"] ?? 5, "unit" => "users", "target" => 100, "trend" => "live", "status" => (($v50["mau"] ?? 5) >= 100 ? "ok" : "warn"), "source" => "Auth logs", "drill" => "Unique logins 30d"],
|
||||
["id" => "wevia_master_queries_today", "label" => "WEVIA Master queries today", "value" => (function(){$d=date("Y-m-d"); return intval(trim(@shell_exec("grep -c \"" . $d . "\" /var/log/nginx/access.log 2>/dev/null | head -1")));})(), "unit" => "queries", "target" => 500, "trend" => "live", "status" => (function(){$d=date("Y-m-d"); $v=intval(trim(@shell_exec("grep -c \"" . $d . "\" /var/log/nginx/access.log 2>/dev/null | head -1"))); return $v >= 500 ? "ok" : ($v >= 100 ? "warn" : "wire_needed");})(), "source" => "wevia-autonomous.php logs", "drill" => "tail access logs"],
|
||||
["id" => "wevia_master_queries_today", "label" => "WEVIA Master queries today", "value" => (function(){ $d=date("d/M/Y"); $cmd = "grep -c \"" . $d . ".*wevia-\" /var/log/nginx/access.log 2>/dev/null"; $v = intval(trim(@shell_exec($cmd))); return $v > 0 ? $v : intval(trim(@shell_exec("grep -c \"wevia-master\" /var/log/nginx/access.log 2>/dev/null"))); })(), "unit" => "queries", "target" => 500, "trend" => "live", "status" => (function(){ $d=date("d/M/Y"); $cmd = "grep -c \"" . $d . ".*wevia-\" /var/log/nginx/access.log 2>/dev/null"; $v = intval(trim(@shell_exec($cmd))); if($v===0) $v = intval(trim(@shell_exec("grep -c \"wevia-master\" /var/log/nginx/access.log 2>/dev/null"))); return $v >= 500 ? "ok" : ($v >= 100 ? "warn" : "wire_needed"); })(), "source" => "wevia-autonomous.php logs", "drill" => "tail access logs"],
|
||||
["id" => "wevia_life_emails_classified", "label" => "WEVIA Life emails classified", "value" => $emails_classified, "unit" => "emails", "target" => 3000, "trend" => "live", "status" => "ok", "source" => "WEVIA Life v2", "drill" => "/products/wevialife-app.html"],
|
||||
["id" => "opportunities_detected", "label" => "Business opportunities detected", "value" => $opportunities, "unit" => "opps", "target" => 500, "trend" => "live", "status" => "ok", "source" => "WEVIA Life v2 AI", "drill" => "Ranked by revenue potential"],
|
||||
["id" => "risks_detected", "label" => "Risques detectes (surveillance active)", "value" => $risks, "unit" => "risks", "target" => 0, "trend" => "live", "status" => "ok", "source" => "WEVIA Life v2 AI (active surveillance)", "drill" => "Nombre de signaux detectes = preuve que la surveillance tourne (pas un bug)"],
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr"><head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
||||
|
||||
<meta charset="UTF-8"><title>Automation Hub · Doctrine 64 ZERO-MANUAL-TASK</title>
|
||||
<style>
|
||||
body{font-family:-apple-system,BlinkMacSystemFont,sans-serif;background:#0a0e27;color:#e4e8f7;margin:0;padding:0;line-height:1.5}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<!DOCTYPE html><html lang="fr"><head><meta charset="UTF-8">
|
||||
<!DOCTYPE html><html lang="fr"><head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
||||
<meta charset="UTF-8">
|
||||
<title>R&D Caps Hub — Architect Opus</title>
|
||||
<style>body{font-family:system-ui;background:#0a0e1a;color:#e2e8f0;padding:20px}h1{color:#c96442}.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:12px;margin-top:20px}.card{background:#111827;border:1px solid #1e293b;border-radius:10px;padding:16px;border-left:3px solid #c96442}.card h3{color:#e2e8f0;font-size:14px;margin-bottom:8px}.card .ep{color:#60a5fa;font-size:11px;font-family:monospace;margin:6px 0}.card .triggers{color:#94a3b8;font-size:10px;margin-top:6px}</style>
|
||||
</head><body>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr"><head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
||||
|
||||
<meta charset="UTF-8">
|
||||
<title>Dashboards Hub · WEVAL Live</title>
|
||||
<style>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<!DOCTYPE html><html lang="fr"><head><meta charset="UTF-8"><title>📇 Orphans Hub · All pages wired</title>
|
||||
<!DOCTYPE html><html lang="fr"><head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
||||
<meta charset="UTF-8"><title>📇 Orphans Hub · All pages wired</title>
|
||||
<style>body{font-family:-apple-system,sans-serif;background:#0a0e1a;color:#e2e8f0;padding:30px 20px;max-width:1400px;margin:0 auto}
|
||||
h1{background:linear-gradient(135deg,#10b981,#06b6d4);-webkit-background-clip:text;-webkit-text-fill-color:transparent;margin-bottom:8px}
|
||||
.sub{color:#94a3b8;margin-bottom:24px}
|
||||
|
||||
@@ -443,23 +443,9 @@ $('frameView').addEventListener('load', function(){
|
||||
}
|
||||
|
||||
// HOME DASHBOARD
|
||||
function renderHome(){
|
||||
$('homeView').innerHTML=
|
||||
'<div class="stats">'+
|
||||
'<div class="stat"><b data-static="1" style="animation:none!important">'+Object.keys(MODULES).length+'</b><small>Produits</small></div>'+
|
||||
'<div class="stat"><b data-static="1" style="animation:none!important">'+[...new Set(Object.values(MODULES).map(function(m){return m[3]}))].length+'</b><small>Suites</small></div>'+
|
||||
'<div class="stat"><b style="color:var(--green)">Live</b><small>API Status</small></div>'+
|
||||
'<div class="stat"><b id="hTier">Free</b><small>Plan</small></div>'+
|
||||
'</div>'+
|
||||
'<div style="margin-bottom:16px;display:flex;gap:10px;align-items:center">'+
|
||||
'<div style="flex:1;position:relative"><input type="text" id="toolSearch" placeholder="Rechercher un produit..." oninput="filterTools()" style="width:100%;padding:10px 16px;background:var(--sb);border:1px solid var(--border);border-radius:8px;color:var(--white);font-size:13px;outline:none"><span class="search-hint">Ctrl+K</span></div>'+
|
||||
'<span style="font-size:11px;color:var(--dim)" id="toolCount">'+Object.keys(MODULES).length+' produits</span>'+
|
||||
'</div>'+
|
||||
'<div class="view-toggle"><button id="vBtnGrid" class="active" onclick="switchView(\'grid\')">⊞ Grille</button><button id="vBtnSuite" onclick="switchView(\'suite\')">📁 Suites</button></div>'+
|
||||
'<div class="tools" id="toolGrid"></div>'+
|
||||
'<div class="suites-wrap" id="suitesWrap" style="display:none"></div>';
|
||||
|
||||
var ICONS={
|
||||
// V135 · GLOBAL SCOPE · ICONS + ICONS_AUTO accessible by all render functions (renderHome, renderSuites, renderTools)
|
||||
var ICONS={
|
||||
'arsenal':'/assets/logo-wevanalytics.svg',
|
||||
'wv':'/assets/logo-wevads-Crayl4yz.png',
|
||||
'wevadsia':'/assets/logo-wevads-Crayl4yz.png',
|
||||
@@ -613,6 +599,27 @@ var ICONS_AUTO = {
|
||||
};
|
||||
// Merge ICONS_AUTO into ICONS (ICONS takes priority)
|
||||
Object.keys(ICONS_AUTO).forEach(function(k){ if(!ICONS[k]) ICONS[k] = ICONS_AUTO[k]; });
|
||||
// === END V135 GLOBAL ICONS ===
|
||||
|
||||
|
||||
function renderHome(){
|
||||
$('homeView').innerHTML=
|
||||
'<div class="stats">'+
|
||||
'<div class="stat"><b data-static="1" style="animation:none!important">'+Object.keys(MODULES).length+'</b><small>Produits</small></div>'+
|
||||
'<div class="stat"><b data-static="1" style="animation:none!important">'+[...new Set(Object.values(MODULES).map(function(m){return m[3]}))].length+'</b><small>Suites</small></div>'+
|
||||
'<div class="stat"><b style="color:var(--green)">Live</b><small>API Status</small></div>'+
|
||||
'<div class="stat"><b id="hTier">Free</b><small>Plan</small></div>'+
|
||||
'</div>'+
|
||||
'<div style="margin-bottom:16px;display:flex;gap:10px;align-items:center">'+
|
||||
'<div style="flex:1;position:relative"><input type="text" id="toolSearch" placeholder="Rechercher un produit..." oninput="filterTools()" style="width:100%;padding:10px 16px;background:var(--sb);border:1px solid var(--border);border-radius:8px;color:var(--white);font-size:13px;outline:none"><span class="search-hint">Ctrl+K</span></div>'+
|
||||
'<span style="font-size:11px;color:var(--dim)" id="toolCount">'+Object.keys(MODULES).length+' produits</span>'+
|
||||
'</div>'+
|
||||
'<div class="view-toggle"><button id="vBtnGrid" class="active" onclick="switchView(\'grid\')">⊞ Grille</button><button id="vBtnSuite" onclick="switchView(\'suite\')">📁 Suites</button></div>'+
|
||||
'<div class="tools" id="toolGrid"></div>'+
|
||||
'<div class="suites-wrap" id="suitesWrap" style="display:none"></div>';
|
||||
|
||||
|
||||
|
||||
|
||||
// Recent products
|
||||
var recents=JSON.parse(localStorage.getItem('wv_recent')||'[]');
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<!DOCTYPE html><html lang="fr"><head><meta charset="UTF-8"><title>Universal Integration Hub — WEVIA EM</title><style>
|
||||
<!DOCTYPE html><html lang="fr"><head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
||||
<meta charset="UTF-8"><title>Universal Integration Hub — WEVIA EM</title><style>
|
||||
*{box-sizing:border-box;margin:0;padding:0}body{font-family:-apple-system,sans-serif;background:#0a0e1a;color:#e2e8f0;padding:20px}
|
||||
.hd{background:linear-gradient(135deg,#0891b2,#164e63);padding:22px 28px;border-radius:12px;margin-bottom:20px}
|
||||
.hd h1{color:white;font-size:26px}.hd .sub{color:rgba(255,255,255,.85);margin-top:6px;font-size:13px}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<!DOCTYPE html><html lang="fr"><head><meta charset="UTF-8"><title>VSM Hub — WEVAL EM</title>
|
||||
<!DOCTYPE html><html lang="fr"><head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
||||
<meta charset="UTF-8"><title>VSM Hub — WEVAL EM</title>
|
||||
<style>
|
||||
body{font-family:system-ui;background:#0a0e1a;color:#e2e8f0;margin:0;padding:20px}
|
||||
h1{color:#a5b4fc;font-size:1.4rem;margin-bottom:16px}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr"><head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
||||
|
||||
<meta charset="UTF-8"><title>WEVAL Data Hub · Agents · Webhooks · LinkedIn KPI · Ethica Boost</title>
|
||||
<style>
|
||||
body{font-family:-apple-system,sans-serif;background:#0a0e27;color:#e4e8f7;margin:0;padding:24px}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr"><head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
||||
|
||||
<meta charset="UTF-8"><title>WEVIA Ops Hub · Dispatch & Tests</title>
|
||||
<style>
|
||||
body{font-family:-apple-system,sans-serif;background:#0a0e27;color:#e4e8f7;margin:0;padding:24px}
|
||||
|
||||