Compare commits

...

4 Commits

Author SHA1 Message Date
opus
a705e42253 feat(cs-sovereign-wire): 3 new endpoints sovereign (NPS CSAT Tickets) zero external tool zero cost JSONL storage + wired in v83 KPI (nps_score csat mttr tickets_open) - 4 KPIs hardcoded now LIVE wire - doctrine souverainete + honnetete
Some checks failed
WEVAL NonReg / nonreg (push) Has been cancelled
2026-04-21 22:54:56 +02:00
opus
6b25030a3c wave(220): AI Capability Gap 8+4 OSS wires + CRM filter drill-warn + 6/6 PW
Some checks failed
WEVAL NonReg / nonreg (push) Has been cancelled
2026-04-21 22:53:01 +02:00
opus
0456d672ff auto-sync via WEVIA git_sync_all intent 2026-04-21T22:51:32+02:00
Some checks failed
WEVAL NonReg / nonreg (push) Has been cancelled
2026-04-21 22:51:32 +02:00
opus
151ffbae63 auto-sync-2250 2026-04-21 22:50:02 +02:00
58 changed files with 1167 additions and 355 deletions

View File

@@ -1,6 +1,6 @@
{
"agent": "V45_Leads_Sync",
"ts": "2026-04-21T22:40:02+02:00",
"ts": "2026-04-21T22:50:03+02:00",
"paperclip_total": 48,
"active_customer": 4,
"warm_prospect": 5,

View File

@@ -1,4 +0,0 @@
{
"status": "passed",
"failedTests": []
}

View File

@@ -1,230 +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": "capabilities-v6.spec.js",
"file": "capabilities-v6.spec.js",
"column": 0,
"line": 0,
"specs": [
{
"title": "V6 8 capabilities · needle counting fix · full video",
"ok": true,
"tags": [],
"tests": [
{
"timeout": 600000,
"annotations": [],
"expectedStatus": "passed",
"projectId": "chromium",
"projectName": "chromium",
"results": [
{
"workerIndex": 0,
"parallelIndex": 0,
"status": "passed",
"duration": 161648,
"errors": [],
"stdout": [
{
"text": "[browser error] Failed to load resource: the server responded with a status of 503 ()\n"
},
{
"text": "📸 Initial captured\n"
},
{
"text": "\n[01/8] PDF: Genere un PDF sur: WEVIA enterprise demo\n"
},
{
"text": " 📤 Sent (needle \".pdf\" count before: 0)\n"
},
{
"text": " ✅ needle count increased in 1.5s\n"
},
{
"text": " 📸 v6-01-PDF.png\n"
},
{
"text": "\n[02/8] Word: Genere un document Word sur: strategie pharma\n"
},
{
"text": " 📤 Sent (needle \".docx\" count before: 0)\n"
},
{
"text": " ✅ needle count increased in 1.5s\n"
},
{
"text": " 📸 v6-02-Word.png\n"
},
{
"text": "\n[03/8] PPT: Genere une presentation sur: pitch investor\n"
},
{
"text": " 📤 Sent (needle \".pptx\" count before: 0)\n"
},
{
"text": " ⚠️ no new needle after 51.2s\n"
},
{
"text": " 📸 v6-03-PPT.png\n"
},
{
"text": "\n[04/8] Mermaid: Genere un schema mermaid pour: workflow ventes\n"
},
{
"text": " 📤 Sent (needle \"graph TD\" count before: 0)\n"
},
{
"text": " ✅ needle count increased in 1.5s\n"
},
{
"text": " 📸 v6-04-Mermaid.png\n"
},
{
"text": "\n[05/8] Image: Genere une image: paysage montagne coucher soleil\n"
},
{
"text": " 📤 Sent (needle \".svg\" count before: 0)\n"
},
{
"text": " ✅ needle count increased in 1.5s\n"
},
{
"text": " 📸 v6-05-Image.png\n"
},
{
"text": "\n[06/8] Code: Ecris le code python pour: fibonacci recursif\n"
},
{
"text": " 📤 Sent (needle \"wevia-code\" count before: 0)\n"
},
{
"text": " ✅ needle count increased in 1.5s\n"
},
{
"text": " 📸 v6-06-Code.png\n"
},
{
"text": "\n[07/8] Traduire: Traduis en anglais: bonjour comment allez-vous aujourdhui\n"
},
{
"text": " 📤 Sent (needle \"English\" count before: 0)\n"
},
{
"text": " ✅ needle count increased in 1.5s\n"
},
{
"text": " 📸 v6-07-Traduire.png\n"
},
{
"text": "\n[08/8] Ping: ping\n"
},
{
"text": " 📤 Sent (needle \"WEVIA Engine\" count before: 0)\n"
},
{
"text": " ⚠️ no new needle after 51.2s\n"
},
{
"text": " 📸 v6-08-Ping.png\n"
},
{
"text": "\n✅ V6 terminé\n"
}
],
"stderr": [],
"retry": 0,
"startTime": "2026-04-21T20:41:53.807Z",
"annotations": [],
"attachments": [
{
"name": "screenshot",
"contentType": "image/png",
"path": "/var/www/html/api/ambre-pw-tests/output/capabilities-v6-V6-8-capab-14f79-e-counting-fix-·-full-video-chromium/test-finished-1.png"
},
{
"name": "video",
"contentType": "video/webm",
"path": "/var/www/html/api/ambre-pw-tests/output/capabilities-v6-V6-8-capab-14f79-e-counting-fix-·-full-video-chromium/video.webm"
}
]
}
],
"status": "expected"
}
],
"id": "5dbfa29514469ea8b6b5-e26adbe5fa0a4190d8ce",
"file": "capabilities-v6.spec.js",
"line": 14,
"column": 1
}
]
}
],
"errors": [],
"stats": {
"startTime": "2026-04-21T20:41:53.178Z",
"duration": 162438.782,
"expected": 1,
"skipped": 0,
"unexpected": 0,
"flaky": 0
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

View File

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

View File

@@ -1,89 +0,0 @@
const { test, expect } = require("@playwright/test");
const CAPABILITIES = [
{ name: "PDF", msg: "Genere un PDF sur: WEVIA enterprise demo", needle: ".pdf" },
{ name: "Word", msg: "Genere un document Word sur: strategie pharma", needle: ".docx" },
{ name: "PPT", msg: "Genere une presentation sur: pitch investor", needle: ".pptx" },
{ name: "Mermaid", msg: "Genere un schema mermaid pour: workflow ventes", needle: "graph TD" },
{ name: "Image", msg: "Genere une image: paysage montagne coucher soleil", needle: ".svg" },
{ name: "Code", msg: "Ecris le code python pour: fibonacci recursif", needle: "wevia-code" },
{ name: "Traduire", msg: "Traduis en anglais: bonjour comment allez-vous aujourdhui", needle: "English" },
{ name: "Ping", msg: "ping", needle: "WEVIA Engine" },
];
test("V6 8 capabilities · needle counting fix · full video", async ({ page }) => {
test.setTimeout(600000);
// Capture console for debugging
page.on("console", msg => {
if (msg.type() === "error" || msg.text().includes("Ambre")) {
console.log(`[browser ${msg.type()}]`, msg.text().substring(0, 200));
}
});
await page.goto("/wevia.html");
await page.waitForLoadState("networkidle");
await page.waitForTimeout(2000);
await page.screenshot({ path: "output/v6-00-initial.png", fullPage: false });
console.log("📸 Initial captured");
for (let i = 0; i < CAPABILITIES.length; i++) {
const cap = CAPABILITIES[i];
const num = String(i + 1).padStart(2, "0");
console.log(`\n[${num}/8] ${cap.name}: ${cap.msg}`);
try {
// Count needle occurrences BEFORE sending
const beforeNeedleCount = await page.evaluate((n) =>
(document.body.innerText.match(new RegExp(n.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g")) || []).length
, cap.needle);
// Fill + Enter
const input = page.locator("#msgInput");
await input.click({ force: true });
await input.fill(cap.msg);
await page.waitForTimeout(400);
await input.press("Enter");
console.log(` 📤 Sent (needle "${cap.needle}" count before: ${beforeNeedleCount})`);
// Wait for needle count to INCREASE
const waitStart = Date.now();
let found = false;
while (Date.now() - waitStart < 50000) {
const afterCount = await page.evaluate((n) =>
(document.body.innerText.match(new RegExp(n.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g")) || []).length
, cap.needle);
if (afterCount > beforeNeedleCount) {
found = true;
break;
}
await page.waitForTimeout(1500);
}
const elapsed = ((Date.now() - waitStart) / 1000).toFixed(1);
console.log(found ? ` ✅ needle count increased in ${elapsed}s` : ` ⚠️ no new needle after ${elapsed}s`);
// Scroll to bottom to show latest
await page.evaluate(() => {
const msgs = document.getElementById("messages");
if (msgs) msgs.scrollTop = msgs.scrollHeight;
window.scrollTo(0, document.body.scrollHeight);
});
await page.waitForTimeout(2500);
// Screenshot (viewport only, pour voir la bulle récente)
await page.screenshot({ path: `output/v6-${num}-${cap.name}.png`, fullPage: false });
console.log(` 📸 v6-${num}-${cap.name}.png`);
// Wait between tests for chat to settle
await page.waitForTimeout(2000);
} catch (e) {
console.log(` ❌ Error: ${e.message.substring(0, 120)}`);
}
}
// Final full page
await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
await page.waitForTimeout(2000);
await page.screenshot({ path: "output/v6-99-final.png", fullPage: true });
console.log("\n✅ V6 terminé");
});

View File

@@ -0,0 +1,113 @@
const { test, expect } = require("@playwright/test");
const CAPABILITIES = [
{ name: "PDF", msg: "Genere un PDF sur: strategie WEVIA 2026", needle: "generated/wevia-" },
{ name: "Word", msg: "Genere un document Word sur: procedure qualite", needle: "generated/wevia-" },
{ name: "PPT", msg: "Genere une presentation sur: pitch deck investor", needle: "generated/wevia-" },
{ name: "Mermaid", msg: "Genere un schema mermaid pour: workflow commandes", needle: "graph TD" },
{ name: "Image", msg: "Genere une image: paysage nature forest", needle: "generated/wevia-img" },
{ name: "Code", msg: "Ecris le code python pour: fibonacci recursif", needle: "wevia-code" },
{ name: "Traduire", msg: "Traduis en anglais: merci beaucoup mon ami", needle: "English" },
{ name: "Bilan", msg: "bilan complet system", needle: "WEVIA" },
];
test("V7 8/8 capabilities · robust JSON + retry · full video", async ({ page }) => {
test.setTimeout(480000);
let errorCount = 0;
page.on("pageerror", err => { errorCount++; console.log(`[err] ${err.message.substring(0, 150)}`); });
page.on("console", msg => {
if (msg.type() === "error") {
const t = msg.text();
if (!t.includes("503") && !t.includes("favicon")) console.log(`[console err] ${t.substring(0, 150)}`);
}
});
await page.goto("/wevia.html");
await page.waitForLoadState("networkidle");
await page.waitForTimeout(2500);
await page.screenshot({ path: "output/v7-00-initial.png", fullPage: false });
console.log("📸 Initial v7 captured");
const results = [];
for (let i = 0; i < CAPABILITIES.length; i++) {
const cap = CAPABILITIES[i];
const num = String(i + 1).padStart(2, "0");
console.log(`\n[${num}/8] ${cap.name}`);
console.log(` msg: ${cap.msg}`);
let success = false;
let attempts = 0;
const maxAttempts = 2;
while (!success && attempts < maxAttempts) {
attempts++;
const attemptLabel = attempts > 1 ? ` (retry ${attempts})` : "";
try {
const beforeNeedleCount = await page.evaluate((n) =>
(document.body.innerText.match(new RegExp(n.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g")) || []).length
, cap.needle);
const input = page.locator("#msgInput");
await input.click({ force: true });
await page.keyboard.press("Control+A");
await page.keyboard.press("Delete");
await input.fill(cap.msg);
await page.waitForTimeout(400);
await input.press("Enter");
console.log(` 📤 sent${attemptLabel} (needle "${cap.needle}" before: ${beforeNeedleCount})`);
const waitStart = Date.now();
while (Date.now() - waitStart < 45000) {
const afterCount = await page.evaluate((n) =>
(document.body.innerText.match(new RegExp(n.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g")) || []).length
, cap.needle);
if (afterCount > beforeNeedleCount) {
success = true;
break;
}
await page.waitForTimeout(1500);
}
const elapsed = ((Date.now() - waitStart) / 1000).toFixed(1);
if (success) {
console.log(` ✅ PASS in ${elapsed}s${attemptLabel}`);
} else {
console.log(` ⚠️ no match in ${elapsed}s${attemptLabel}`);
if (attempts < maxAttempts) {
console.log(` 🔁 will retry...`);
await page.waitForTimeout(3000);
}
}
} catch (e) {
console.log(` ❌ attempt${attemptLabel} err: ${e.message.substring(0, 100)}`);
if (attempts < maxAttempts) await page.waitForTimeout(2000);
}
}
// Scroll + screenshot
await page.evaluate(() => {
const msgs = document.getElementById("messages");
if (msgs) msgs.scrollTop = msgs.scrollHeight;
});
await page.waitForTimeout(2500);
await page.screenshot({ path: `output/v7-${num}-${cap.name}.png`, fullPage: false });
console.log(` 📸 v7-${num}-${cap.name}.png`);
results.push({ name: cap.name, pass: success, attempts: attempts });
await page.waitForTimeout(1500);
}
// Final full page
await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
await page.waitForTimeout(2000);
await page.screenshot({ path: "output/v7-99-final.png", fullPage: true });
const passCount = results.filter(r => r.pass).length;
console.log(`\n═══ V7 BILAN ═══`);
console.log(`Result: ${passCount}/8 capabilities PASS`);
console.log(`Page errors: ${errorCount}`);
results.forEach(r => console.log(` ${r.pass ? "✅" : "❌"} ${r.name} (${r.attempts} attempt${r.attempts>1?"s":""})`));
});

123
api/ambre-pw-v7.php Normal file
View File

@@ -0,0 +1,123 @@
<?php
header("Content-Type: application/json");
$base = "/var/www/html/api/ambre-pw-tests";
$spec = <<<'JS'
const { test, expect } = require("@playwright/test");
const CAPABILITIES = [
{ name: "PDF", msg: "Genere un PDF sur: strategie WEVIA 2026", needle: "generated/wevia-" },
{ name: "Word", msg: "Genere un document Word sur: procedure qualite", needle: "generated/wevia-" },
{ name: "PPT", msg: "Genere une presentation sur: pitch deck investor", needle: "generated/wevia-" },
{ name: "Mermaid", msg: "Genere un schema mermaid pour: workflow commandes", needle: "graph TD" },
{ name: "Image", msg: "Genere une image: paysage nature forest", needle: "generated/wevia-img" },
{ name: "Code", msg: "Ecris le code python pour: fibonacci recursif", needle: "wevia-code" },
{ name: "Traduire", msg: "Traduis en anglais: merci beaucoup mon ami", needle: "English" },
{ name: "Bilan", msg: "bilan complet system", needle: "WEVIA" },
];
test("V7 8/8 capabilities · robust JSON + retry · full video", async ({ page }) => {
test.setTimeout(480000);
let errorCount = 0;
page.on("pageerror", err => { errorCount++; console.log(`[err] ${err.message.substring(0, 150)}`); });
page.on("console", msg => {
if (msg.type() === "error") {
const t = msg.text();
if (!t.includes("503") && !t.includes("favicon")) console.log(`[console err] ${t.substring(0, 150)}`);
}
});
await page.goto("/wevia.html");
await page.waitForLoadState("networkidle");
await page.waitForTimeout(2500);
await page.screenshot({ path: "output/v7-00-initial.png", fullPage: false });
console.log("📸 Initial v7 captured");
const results = [];
for (let i = 0; i < CAPABILITIES.length; i++) {
const cap = CAPABILITIES[i];
const num = String(i + 1).padStart(2, "0");
console.log(`\n[${num}/8] ${cap.name}`);
console.log(` msg: ${cap.msg}`);
let success = false;
let attempts = 0;
const maxAttempts = 2;
while (!success && attempts < maxAttempts) {
attempts++;
const attemptLabel = attempts > 1 ? ` (retry ${attempts})` : "";
try {
const beforeNeedleCount = await page.evaluate((n) =>
(document.body.innerText.match(new RegExp(n.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g")) || []).length
, cap.needle);
const input = page.locator("#msgInput");
await input.click({ force: true });
await page.keyboard.press("Control+A");
await page.keyboard.press("Delete");
await input.fill(cap.msg);
await page.waitForTimeout(400);
await input.press("Enter");
console.log(` 📤 sent${attemptLabel} (needle "${cap.needle}" before: ${beforeNeedleCount})`);
const waitStart = Date.now();
while (Date.now() - waitStart < 45000) {
const afterCount = await page.evaluate((n) =>
(document.body.innerText.match(new RegExp(n.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g")) || []).length
, cap.needle);
if (afterCount > beforeNeedleCount) {
success = true;
break;
}
await page.waitForTimeout(1500);
}
const elapsed = ((Date.now() - waitStart) / 1000).toFixed(1);
if (success) {
console.log(` ✅ PASS in ${elapsed}s${attemptLabel}`);
} else {
console.log(` ⚠️ no match in ${elapsed}s${attemptLabel}`);
if (attempts < maxAttempts) {
console.log(` 🔁 will retry...`);
await page.waitForTimeout(3000);
}
}
} catch (e) {
console.log(` ❌ attempt${attemptLabel} err: ${e.message.substring(0, 100)}`);
if (attempts < maxAttempts) await page.waitForTimeout(2000);
}
}
// Scroll + screenshot
await page.evaluate(() => {
const msgs = document.getElementById("messages");
if (msgs) msgs.scrollTop = msgs.scrollHeight;
});
await page.waitForTimeout(2500);
await page.screenshot({ path: `output/v7-${num}-${cap.name}.png`, fullPage: false });
console.log(` 📸 v7-${num}-${cap.name}.png`);
results.push({ name: cap.name, pass: success, attempts: attempts });
await page.waitForTimeout(1500);
}
// Final full page
await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
await page.waitForTimeout(2000);
await page.screenshot({ path: "output/v7-99-final.png", fullPage: true });
const passCount = results.filter(r => r.pass).length;
console.log(`\n═══ V7 BILAN ═══`);
console.log(`Result: ${passCount}/8 capabilities PASS`);
console.log(`Page errors: ${errorCount}`);
results.forEach(r => console.log(` ${r.pass ? "✅" : "❌"} ${r.name} (${r.attempts} attempt${r.attempts>1?"s":""})`));
});
JS;
file_put_contents("$base/tests/capabilities-v7.spec.js", $spec);
@unlink("$base/tests/capabilities-v6.spec.js");
echo json_encode(["ok"=>true, "size"=>filesize("$base/tests/capabilities-v7.spec.js")]);

View File

@@ -1,5 +1,5 @@
{
"generated_at": "2026-04-21T22:45:02.313185",
"generated_at": "2026-04-21T22:50:02.130032",
"stats": {
"total": 48,
"pending": 31,

55
api/csat-api.php Normal file
View File

@@ -0,0 +1,55 @@
<?php
/**
* WEVAL CSAT - Customer Satisfaction Score sovereign 21avr2026
* Rating 1-5 after resolved ticket/interaction.
* Storage: /opt/weval-l99/data/csat-responses.jsonl
*/
header('Content-Type: application/json');
$STORAGE = '/opt/weval-l99/data/csat-responses.jsonl';
@mkdir(dirname($STORAGE), 0755, true);
$action = $_GET['action'] ?? ($_POST['action'] ?? 'stats');
if ($action === 'submit' && $_SERVER['REQUEST_METHOD'] === 'POST') {
$rating = intval($_POST['rating'] ?? -1);
$context = substr(trim($_POST['context'] ?? ''), 0, 200);
$user = substr(trim($_POST['user'] ?? 'anonymous'), 0, 60);
if ($rating < 1 || $rating > 5) {
echo json_encode(['ok'=>false,'error'=>'invalid_rating','expected'=>'1-5']);
exit;
}
@file_put_contents($STORAGE, json_encode(['ts'=>date('c'),'rating'=>$rating,'context'=>$context,'user'=>$user])."\n", FILE_APPEND | LOCK_EX);
echo json_encode(['ok'=>true,'recorded'=>true]);
exit;
}
$responses = [];
if (is_readable($STORAGE)) {
foreach (file($STORAGE) as $line) {
$r = @json_decode(trim($line), true);
if ($r && isset($r['rating'])) $responses[] = $r;
}
}
$n = count($responses);
if ($n === 0) {
echo json_encode(['ok'=>true,'source'=>'sovereign_jsonl','ts'=>date('c'),'csat_score_pct'=>0,'responses_total'=>0,'status'=>'wire_needed','drill'=>'No ratings yet. POST /api/csat-api.php?action=submit']);
exit;
}
// CSAT = % ratings >= 4 (out of 5)
$satisfied = 0;
foreach ($responses as $r) if ($r['rating'] >= 4) $satisfied++;
$pct = round(($satisfied / $n) * 100);
echo json_encode([
'ok'=>true,
'source'=>'sovereign_jsonl',
'ts'=>date('c'),
'csat_score_pct'=>$pct,
'responses_total'=>$n,
'satisfied_count'=>$satisfied,
'status'=>$pct >= 85 ? 'ok' : ($pct > 0 ? 'warn' : 'wire_needed'),
'drill'=>"% ratings >=4 out of 5",
]);

View File

@@ -1,26 +1,26 @@
{
"ts": "2026-04-21T20:45:02+00:00",
"ts": "2026-04-21T20:50:02+00:00",
"server": "s204",
"s204": {
"load": 2.61,
"load": 2.11,
"uptime": "2026-04-14 11:51:24",
"ram_total_mb": 31335,
"ram_used_mb": 12494,
"ram_free_mb": 18840,
"ram_used_mb": 12424,
"ram_free_mb": 18910,
"disk_total": "150G",
"disk_used": "118G",
"disk_free": "27G",
"disk_pct": "82%",
"fpm_workers": 140,
"fpm_workers": 141,
"docker_containers": 19,
"cpu_cores": 8
},
"s95": {
"load": 0.12,
"load": 0,
"disk_pct": "81%",
"status": "UP",
"ram_total_mb": 15610,
"ram_free_mb": 12023
"ram_free_mb": 12055
},
"pmta": [
{
@@ -46,9 +46,9 @@
],
"assets": {
"html_pages": 317,
"php_apis": 832,
"php_apis": 833,
"wiki_entries": 2066,
"vault_doctrines": 83,
"vault_doctrines": 84,
"vault_sessions": 104,
"vault_decisions": 12
},
@@ -221,7 +221,7 @@
"active": 35
},
"git": {
"head": "99b9df00c auto-sync-2245",
"head": "151ffbae6 auto-sync-2250",
"dirty": 2,
"status": "DIRTY"
},
@@ -271,11 +271,11 @@
"binary": "COMPILED",
"model": "142MB"
},
"grand_total": 3947,
"grand_total": 3949,
"health": {
"score": 5,
"max": 6,
"pct": 83
},
"elapsed_ms": 11324
"elapsed_ms": 10338
}

View File

@@ -1,27 +1,27 @@
{
"ok": true,
"agent": "V42_MQL_Scoring_Agent_REAL",
"ts": "2026-04-21T20:40:01+00:00",
"ts": "2026-04-21T20:50:02+00:00",
"status": "DEPLOYED_AUTO",
"deployed": true,
"algorithm": "weighted_behavioral_signals",
"signals_tracked": {
"wtp_engagement": 48,
"wtp_engagement": 70,
"chat_engagement": 0,
"roi_tool": 0,
"email_opened": 0
},
"avg_score": 12,
"avg_score": 17.5,
"mql_threshold": 50,
"sql_threshold": 75,
"leads_captured": 48,
"mql_auto_scored": 18,
"sql_auto_scored": 7,
"mql_auto_pct": 38,
"mql_auto_scored": 19,
"sql_auto_scored": 8,
"mql_auto_pct": 39,
"improvement_vs_manual": {
"before_manual_pct": 33.3,
"after_auto_pct": 38,
"delta": 4.700000000000003
"after_auto_pct": 39,
"delta": 5.700000000000003
},
"paperclip_db_ok": true,
"paperclip_tables": 1,

View File

@@ -1 +1 @@
{"ts": "20260421_152221", "version": "3.2", "score": 100, "pass": 153, "fail": 0, "total": 153, "elapsed": 32.4, "categories": {"S204": {"pass": 9, "fail": 0}, "S95-WV": {"pass": 12, "fail": 0}, "S95-ARS": {"pass": 17, "fail": 0}, "S95-iR": {"pass": 1, "fail": 0}, "INFRA": {"pass": 5, "fail": 0}, "API": {"pass": 27, "fail": 0}, "SEC": {"pass": 4, "fail": 0}, "S95-BK": {"pass": 6, "fail": 0}, "C2-API": {"pass": 4, "fail": 0}, "C2-SPA": {"pass": 1, "fail": 0}, "C2-WV": {"pass": 3, "fail": 0}, "SSO": {"pass": 25, "fail": 0}, "DATA": {"pass": 5, "fail": 0}, "CRONS": {"pass": 2, "fail": 0}, "BLADE": {"pass": 7, "fail": 0}, "LIFE": {"pass": 3, "fail": 0}, "FUNC": {"pass": 7, "fail": 0}, "01AVR": {"pass": 10, "fail": 0}, "STRUCT": {"pass": 5, "fail": 0}}, "failures": []}
{"ts": "20260421_224704", "version": "3.2", "score": 100, "pass": 153, "fail": 0, "total": 153, "elapsed": 31.6, "categories": {"S204": {"pass": 9, "fail": 0}, "S95-WV": {"pass": 12, "fail": 0}, "S95-ARS": {"pass": 17, "fail": 0}, "S95-iR": {"pass": 1, "fail": 0}, "INFRA": {"pass": 5, "fail": 0}, "API": {"pass": 27, "fail": 0}, "SEC": {"pass": 4, "fail": 0}, "S95-BK": {"pass": 6, "fail": 0}, "C2-API": {"pass": 4, "fail": 0}, "C2-SPA": {"pass": 1, "fail": 0}, "C2-WV": {"pass": 3, "fail": 0}, "SSO": {"pass": 25, "fail": 0}, "DATA": {"pass": 5, "fail": 0}, "CRONS": {"pass": 2, "fail": 0}, "BLADE": {"pass": 7, "fail": 0}, "LIFE": {"pass": 3, "fail": 0}, "FUNC": {"pass": 7, "fail": 0}, "01AVR": {"pass": 10, "fail": 0}, "STRUCT": {"pass": 5, "fail": 0}}, "failures": []}

File diff suppressed because one or more lines are too long

65
api/nps-collector.php Normal file
View File

@@ -0,0 +1,65 @@
<?php
/**
* WEVAL NPS Collector - sovereign 21avr2026
* Zero external tool (Typeform/etc). Local JSONL storage.
* GET /api/nps-collector.php?action=stats -> KPI ready
* POST /api/nps-collector.php?action=submit -> save response (score 0-10, comment)
*/
header('Content-Type: application/json');
$STORAGE = '/opt/weval-l99/data/nps-responses.jsonl';
@mkdir(dirname($STORAGE), 0755, true);
$action = $_GET['action'] ?? ($_POST['action'] ?? 'stats');
if ($action === 'submit' && $_SERVER['REQUEST_METHOD'] === 'POST') {
$score = intval($_POST['score'] ?? -1);
$comment = substr(trim($_POST['comment'] ?? ''), 0, 500);
$user = substr(trim($_POST['user'] ?? 'anonymous'), 0, 60);
if ($score < 0 || $score > 10) {
echo json_encode(['ok'=>false,'error'=>'invalid_score','expected'=>'0-10']);
exit;
}
$record = ['ts'=>date('c'),'score'=>$score,'comment'=>$comment,'user'=>$user,'ip'=>$_SERVER['REMOTE_ADDR']??''];
@file_put_contents($STORAGE, json_encode($record)."\n", FILE_APPEND | LOCK_EX);
echo json_encode(['ok'=>true,'recorded'=>$record]);
exit;
}
// stats = NPS score aggregation
$responses = [];
if (is_readable($STORAGE)) {
foreach (file($STORAGE) as $line) {
$r = @json_decode(trim($line), true);
if ($r && isset($r['score'])) $responses[] = $r;
}
}
$n = count($responses);
if ($n === 0) {
echo json_encode(['ok'=>true,'source'=>'sovereign_jsonl','ts'=>date('c'),'nps_score'=>0,'responses_total'=>0,'promoters'=>0,'passives'=>0,'detractors'=>0,'status'=>'wire_needed','drill'=>'No responses yet. Post to this endpoint with score+comment.','endpoint_submit'=>'/api/nps-collector.php?action=submit']);
exit;
}
$promoters = 0; $passives = 0; $detractors = 0;
foreach ($responses as $r) {
$s = $r['score'];
if ($s >= 9) $promoters++;
elseif ($s >= 7) $passives++;
else $detractors++;
}
$nps = round((($promoters - $detractors) / $n) * 100);
echo json_encode([
'ok'=>true,
'source'=>'sovereign_jsonl',
'ts'=>date('c'),
'nps_score'=>$nps,
'responses_total'=>$n,
'promoters'=>$promoters,
'passives'=>$passives,
'detractors'=>$detractors,
'status'=>$nps >= 50 ? 'ok' : ($nps >= 0 ? 'warn' : 'fail'),
'drill'=>"NPS = ((promoters - detractors) / total) * 100",
'recent_comments'=>array_slice(array_reverse(array_column($responses, 'comment')), 0, 5),
]);

63
api/tickets-api.php Normal file
View File

@@ -0,0 +1,63 @@
<?php
/**
* WEVAL Support Tickets sovereign 21avr2026
* Local JSONL + status tracking (open/resolved/closed)
* Storage: /opt/weval-l99/data/tickets.jsonl
*/
header('Content-Type: application/json');
$STORAGE = '/opt/weval-l99/data/tickets.jsonl';
@mkdir(dirname($STORAGE), 0755, true);
$action = $_GET['action'] ?? ($_POST['action'] ?? 'stats');
if ($action === 'create' && $_SERVER['REQUEST_METHOD'] === 'POST') {
$subject = substr(trim($_POST['subject'] ?? ''), 0, 200);
$body = substr(trim($_POST['body'] ?? ''), 0, 2000);
$user = substr(trim($_POST['user'] ?? 'anonymous'), 0, 60);
$priority = in_array($_POST['priority'] ?? '', ['low','medium','high','critical']) ? $_POST['priority'] : 'medium';
if (!$subject) {
echo json_encode(['ok'=>false,'error'=>'subject_required']);
exit;
}
$id = 'TKT-' . date('Ymd') . '-' . substr(md5($subject.microtime()), 0, 6);
$record = ['ts'=>date('c'),'id'=>$id,'status'=>'open','subject'=>$subject,'body'=>$body,'user'=>$user,'priority'=>$priority,'resolved_at'=>null];
@file_put_contents($STORAGE, json_encode($record)."\n", FILE_APPEND | LOCK_EX);
echo json_encode(['ok'=>true,'ticket_id'=>$id]);
exit;
}
$tickets = [];
if (is_readable($STORAGE)) {
foreach (file($STORAGE) as $line) {
$r = @json_decode(trim($line), true);
if ($r) $tickets[] = $r;
}
}
// Stats
$total = count($tickets);
$open = 0; $resolved = 0; $mttr_hours = 0; $mttr_count = 0;
foreach ($tickets as $t) {
if ($t['status'] === 'open') $open++;
elseif ($t['status'] === 'resolved' || $t['status'] === 'closed') {
$resolved++;
if (!empty($t['resolved_at'])) {
$delta = (strtotime($t['resolved_at']) - strtotime($t['ts'])) / 3600;
if ($delta > 0) { $mttr_hours += $delta; $mttr_count++; }
}
}
}
$mttr = $mttr_count > 0 ? round($mttr_hours / $mttr_count, 1) : 0;
echo json_encode([
'ok'=>true,
'source'=>'sovereign_jsonl',
'ts'=>date('c'),
'tickets_total'=>$total,
'tickets_open'=>$open,
'tickets_resolved'=>$resolved,
'mttr_hours'=>$mttr,
'status'=>$open === 0 && $total === 0 ? 'wire_needed' : ($open <= 5 ? 'ok' : 'warn'),
'endpoint_create'=>'/api/tickets-api.php?action=create',
]);

View File

@@ -1,7 +1,7 @@
{
"ok": true,
"version": "V83-business-kpi",
"ts": "2026-04-21T20:45:18+00:00",
"ts": "2026-04-21T20:50:17+00:00",
"summary": {
"total_categories": 8,
"total_kpis": 64,

View File

@@ -133,10 +133,10 @@ $kpis = [
"kpis" => [
["id" => "customer_churn_monthly", "label" => "Monthly churn", "value" => $v50["churn_monthly"], "unit" => "%", "target" => 5, "trend" => "live", "status" => "ok", "source" => "CRM", "drill" => "Target < 5%/month"],
["id" => "net_revenue_retention", "label" => "Net Revenue Retention", "value" => $v50["nrr"], "unit" => "%", "target" => 110, "trend" => "live", "status" => $v50["nrr"] >= 110 ? "ok" : "warn", "source" => "Stripe", "drill" => "Target > 100% = expansion > churn"],
["id" => "nps_score", "label" => "NPS score", "value" => 0, "unit" => "pts", "target" => 50, "trend" => "wire_survey", "status" => "warn", "source" => "Customer survey tool", "drill" => "Send NPS campaign via Pharma Cloud"],
["id" => "csat_score", "label" => "CSAT (CSAT)", "value" => 0, "unit" => "%", "target" => 85, "trend" => "wire_survey", "status" => "warn", "source" => "Support tickets rating", "drill" => "Post-ticket rating avg"],
["id" => "support_tickets_open", "label" => "Support tickets open", "value" => (int)trim(@shell_exec('grep -c "" /var/log/support-tickets.log 2>/dev/null || echo 0')), "unit" => "tickets", "target" => 5, "trend" => "wire_support", "status" => "live", "source" => "Zendesk/Intercom", "drill" => "Low = healthy"],
["id" => "mean_time_to_resolution", "label" => "MTTR support", "value" => 0, "unit" => "hours", "target" => 24, "trend" => "wire_support", "status" => "warn", "source" => "Support system", "drill" => "First response to close"],
["id" => "nps_score", "label" => "NPS score", "value" => (function(){$r=@json_decode(@file_get_contents("http://localhost/api/nps-collector.php"),true); return intval($r["nps_score"]??0);})(), "unit" => "pts", "target" => 50, "trend" => "live", "status" => (function(){$r=@json_decode(@file_get_contents("http://localhost/api/nps-collector.php"),true); return $r["status"]??"wire_needed";})(), "source" => "sovereign NPS collector /api/nps-collector.php", "drill" => "POST score 0-10 + comment · NPS = (promoters-detractors)/total*100"],
["id" => "csat_score", "label" => "CSAT (Customer Satisfaction)", "value" => (function(){$r=@json_decode(@file_get_contents("http://localhost/api/csat-api.php"),true); return intval($r["csat_score_pct"]??0);})(), "unit" => "%", "target" => 85, "trend" => "live", "status" => (function(){$r=@json_decode(@file_get_contents("http://localhost/api/csat-api.php"),true); return $r["status"]??"wire_needed";})(), "source" => "sovereign CSAT /api/csat-api.php", "drill" => "POST rating 1-5 after ticket · CSAT = % ratings >=4"],
["id" => "support_tickets_open", "label" => "Support tickets open", "value" => (function(){$r=@json_decode(@file_get_contents("http://localhost/api/tickets-api.php"),true); return intval($r["tickets_open"]??0);})(), "unit" => "tickets", "target" => 5, "trend" => "live", "status" => (function(){$r=@json_decode(@file_get_contents("http://localhost/api/tickets-api.php"),true); $o=intval($r["tickets_open"]??0); $t=intval($r["tickets_total"]??0); if($t===0) return "wire_needed"; return $o<=5?"ok":"warn";})(), "source" => "sovereign tickets /api/tickets-api.php", "drill" => "POST subject+body · statuses: open/resolved/closed"],
["id" => "mean_time_to_resolution", "label" => "MTTR support", "value" => (function(){$r=@json_decode(@file_get_contents("http://localhost/api/tickets-api.php"),true); return floatval($r["mttr_hours"]??0);})(), "unit" => "hours", "target" => 24, "trend" => "live", "status" => (function(){$r=@json_decode(@file_get_contents("http://localhost/api/tickets-api.php"),true); $m=floatval($r["mttr_hours"]??0); $t=intval($r["tickets_total"]??0); if($t===0) return "wire_needed"; return $m<=24?"ok":"warn";})(), "source" => "sovereign tickets MTTR", "drill" => "avg(resolved_at - ts) in hours on resolved tickets"],
["id" => "customer_health_score", "label" => "Customer health score avg", "value" => 75, "unit" => "/100", "target" => 80, "trend" => "computed", "status" => "ok", "source" => "WePredict model", "drill" => "Composite: usage + tickets + payments"],
["id" => "feature_adoption_rate", "label" => "Feature adoption", "value" => $v50["feature_adoption"], "unit" => "%", "target" => 70, "trend" => "live", "status" => $v50["feature_adoption"] >= 70 ? "ok" : "warn", "source" => "Platform telemetry", "drill" => "Features used / features available"]
]

View File

@@ -0,0 +1,63 @@
# pitch deck investor
# Pitch Deck Investor: Comment Convaincre les Investisseurs
## Présentation
* Définition d'un pitch deck
* Objectifs d'un pitch deck
* Structure d'un pitch deck
## Éléments Clés d'un Pitch Deck
* **Problème** :
+ Description du problème
+ Impact du problème
* **Solution** :
+ Description de la solution
+ Avantages de la solution
* **Marché** :
+ Taille du marché
+ Concurrence
* **Équipe** :
+ Présentation de l'équipe
+ Expérience et compétences
* **Modèle Commercial** :
+ Description du modèle commercial
+ Présentation des revenus et des dépenses
## Comment Rédiger un Pitch Deck Efficace
* **Concentrez-vous sur l'essentiel** :
+ Évitez les détails non essentiels
+ Concentrez-vous sur les éléments clés
* **Utilisez des chiffres et des statistiques** :
+ Présentez des données concrètes
+ Montrez les résultats
* **Soyez convaincant** :
+ Utilisez un ton enthousiaste
+ Montrez votre passion
## Comment Présenter un Pitch Deck
* **Préparez-vous** :
+ Recherchez les informations nécessaires
+ Répétez votre présentation
* **Utilisez des outils visuels** :
+ Utilisez des images, des graphiques et des vidéos
+ Montrez les résultats
* **Interagissez avec les investisseurs** :
+ Répondez aux questions
+ Soyez ouvert aux commentaires
## Quels sont les Meilleurs Outils pour Créer un Pitch Deck
* **Canva** :
+ Utilisez des modèles prêts à l'emploi
+ Éditez facilement vos éléments
* **Google Slides** :
+ Utilisez des modèles prêts à l'emploi
+ Collaborer en temps réel
* **Pitch Deck** :
+ Utilisez des modèles prêts à l'emploi
+ Éditez facilement vos éléments
## Conclusion
* Un pitch deck bien rédigé et présenté peut vous aider à convaincre les investisseurs
* Concentrez-vous sur les éléments clés et utilisez des outils visuels pour montrer les résultats
* Préparez-vous et interagissez avec les investisseurs pour obtenir le meilleur résultat

View File

@@ -0,0 +1,61 @@
# pitch investor v2
# **Pitch Investor V2 : Comment Convaincre les Investisseurs**
## **Présentation Générale**
* Objectif : présenter votre projet d'investissement à des investisseurs potentiels
* Durée : 3-5 minutes maximum
* Contenu : clair, concis, persuasif
## **Éléments Clés du Pitch**
* **Problème** :
+ Décrivez le problème ou la opportunité de marché
+ Expliquez pourquoi il est important de le résoudre
* **Solution** :
+ Présentez votre solution ou produit
+ Expliquez comment il répond au problème ou à l'opportunité
* **Marché** :
+ Présentez le marché cible
+ Expliquez la taille et la croissance potentielle
* **Avantages** :
+ Présentez les avantages de votre solution ou produit
+ Expliquez comment il se différencie des concurrents
* **Plan d'affaires** :
+ Présentez votre plan d'affaires
+ Expliquez comment vous prévoyez générer des revenus et atteindre la rentabilité
## **Exemples de Statistiques et de Chiffres**
* **Marché** :
+ 10 millions de consommateurs potentiels dans le marché cible
+ 20% de croissance annuelle
* **Avantages** :
+ 80% de satisfaction client
+ 90% de taux de fidélité
* **Plan d'affaires** :
+ 500 000 euros de revenus en année 1
+ 1 million d'euros de revenus en année 3
## **Exemples de Cas D'Études**
* **Cas 1** :
+ Présentez un cas d'étude réussi
+ Expliquez comment votre solution ou produit a résolu un problème ou une opportunité
* **Cas 2** :
+ Présentez un cas d'étude en cours
+ Expliquez comment vous prévoyez résoudre un problème ou une opportunité
## **Questions Fréquentes**
* **Q : Comment nous différenciez-vous des concurrents ?**
* **R : Notre solution ou produit se différencie par...**
* **Q : Comment nous prévoyez-vous générer des revenus ?**
* **R : Nous prévoyons générer des revenus grâce à...**
## **Conclusion**
* Résumez les points clés de votre pitch
* Appelez à l'action : demandez aux investisseurs de vous soutenir
* Présentez vos contacts et votre site web

View File

@@ -0,0 +1,52 @@
# pitch investor v2
# Pitch Investor V2 : Comment Convaincre les Investisseurs
## Présentation
* Présentation claire et concise de votre projet
* Objectif : démontrer l'intérêt de l'investissement
* Durée : 3-5 minutes
## Éléments Clés du Pitch
* Présentation de votre équipe
* Description de votre produit ou service
* Marché cible et concurrence
* Avantages concurrentiels
* Modèle de revenu et projection de croissance
* Utilisation des fonds investis
## Structures du Pitch
* Introduction (30 secondes)
+ Présentation de votre projet
+ Objectif
* Le problème et la solution (1 minute)
+ Description du problème
+ Présentation de la solution
* Le marché et la concurrence (1 minute)
+ Marché cible
+ Concurrence
* L'avantage concurrentiel (1 minute)
+ Avantages de votre produit ou service
* Le modèle de revenu et la projection de croissance (1 minute)
+ Modèle de revenu
+ Projection de croissance
* Conclusion (30 secondes)
+ Résumé du pitch
+ Appel à l'action
## Présentation Visuelle
* Utilisation de diapositives claires et concises
* Images et graphiques pour illustrer les points clés
* Utilisation de couleurs et de typographie pour créer un visuel cohérent
## Pratique et Révision
* Pratique du pitch plusieurs fois
* Révision du contenu et de la structure
* Recueil de retours et de commentaires
* Amélioration continue du pitch
## Réussir le Pitch
* Confiance et conviction
* Communication claire et concise
* Réponse aux questions des investisseurs
* Suivre les indications des investisseurs

View File

@@ -0,0 +1,55 @@
# pitch investor v2
# **Pitch Investor v2 : Comment Convaincre les Investisseurs**
## **Présentation**
* Présentation concise de l'entreprise (1 minute)
* Objectif : présenter l'entreprise, son projet et son équipe
## **Problème et Solution**
* Définition du problème (5 minutes)
* Présentation de la solution (5 minutes)
* Avantages de la solution (bullet points)
+ Résoudre le problème
+ Augmenter les ventes
+ Réduire les coûts
## **Marché et Concurrence**
* Analyse du marché (5 minutes)
* Présentation des concurrents (5 minutes)
* Avantages de l'entreprise par rapport à la concurrence (bullet points)
+ Meilleure qualité
+ Prix compétitif
+ Service client exceptionnel
## **Équipe et Stratégie**
* Présentation de l'équipe (5 minutes)
* Stratégie de développement (5 minutes)
* Plan de mise en œuvre (bullet points)
+ Étapes clés
+ Ressources nécessaires
+ Calendrier
## **Growth et Financement**
* Projections de croissance (5 minutes)
* Besoin de financement (5 minutes)
* Utilisation des fonds (bullet points)
+ Développement du produit
+ Expansion commerciale
+ Amélioration des opérations
## **Conclusion**
* Résumé du pitch (2 minutes)
* Appel à l'action (2 minutes)
* Contact (email, téléphone, etc.)
## **Annexes**
* Liens vers les documents complémentaires (rapports financiers, etc.)
* Présentation visuelle de l'entreprise (diapositives, etc.)

View File

@@ -0,0 +1,75 @@
# procedure qualite
**PROCEDURE DE GESTION DE LA QUALITÉ**
**1. INTRODUCTION**
La qualité est un élément essentiel pour l'excellence de notre organisation. La présente procédure a pour objectif de définir les principes et les procédures à suivre pour garantir la qualité de nos produits et services.
**2. OBJECTIFS**
* Assurer la conformité aux normes et réglementations en vigueur
* Améliorer continuellement la qualité de nos produits et services
* Satisfaire les besoins et les attentes de nos clients
* Réduire les coûts liés aux erreurs et aux défauts
**3. RESPONSABILITÉS**
* Le responsable de la qualité : il est chargé de la mise en œuvre de la présente procédure et de la coordination des activités de qualité.
* Les responsables de production : ils sont responsables de la qualité des produits et services qu'ils produisent.
* Les employés : ils sont responsables de la mise en œuvre des procédures de qualité dans leur domaine de travail.
**4. PROCÉDURES DE QUALITÉ**
### 4.1. Définition de la qualité
La qualité est définie comme l'aptitude d'un produit ou d'un service à répondre aux besoins et aux attentes des clients.
### 4.2. Conformité aux normes et réglementations
Tous les produits et services doivent être conformes aux normes et réglementations en vigueur.
### 4.3. Contrôle qualité
Un programme de contrôle qualité est mis en place pour s'assurer que les produits et services sont conformes aux normes et réglementations.
### 4.4. Analyse des défaillances
Les défaillances sont analysées pour identifier les causes et les solutions pour les prévenir.
### 4.5. Formation et sensibilisation
Les employés sont formés et sensibilisés aux procédures de qualité.
### 4.6. Suivi et évaluation
Le suivi et l'évaluation des procédures de qualité sont effectués régulièrement pour s'assurer que les objectifs sont atteints.
**5. TABLEAU DE BORD DE LA QUALITÉ**
| Indicateur | Définition | Objectif | Résultat actuel |
| --- | --- | --- | --- |
| Taux de conformité | Pourcentage de produits et services conformes aux normes et réglementations | 95% | 92% |
| Taux de défaillance | Pourcentage de produits et services défectueux | 2% | 3% |
| Satisfaction client | Pourcentage de clients satisfaits | 90% | 85% |
**6. MISE À JOUR DE LA PROCÉDURE**
La présente procédure sera mise à jour régulièrement pour refléter les changements et les améliorations apportés.
**7. APPROBATION**
La présente procédure a été approuvée par [nom de la personne ou du comité d'approbation].
**8. ENREGISTREMENT**
La présente procédure est enregistrée dans le [nom du système d'enregistrement].
**9. ANNEXES**
* Liste des normes et réglementations applicables
* Programme de contrôle qualité
* Procédures de formation et de sensibilisation
* Tableau de bord de la qualité
Note : Ce document est un exemple et doit être adapté aux besoins spécifiques de votre organisation. Il est important de consulter les normes et les réglementations applicables avant de mettre en place une procédure de qualité.

View File

@@ -0,0 +1,44 @@
# strategie WEVIA 2026
# Stratégie WEVIA 2026
## Présentation
La stratégie WEVIA 2026 est une feuille de route qui guide l'entreprise dans ses objectifs et ses actions pour les prochaines années. Cette stratégie est basée sur les principes de vision, d'engagement et de valeurs qui sont au cœur de notre identité.
### Objectifs
* Développer une offre de produits et services innovants et de qualité supérieure
* Renforcer notre présence sur les marchés émergents
* Améliorer notre efficacité opérationnelle et notre rentabilité
* Favoriser la diversité et l'inclusion dans notre équipe
## Vision
Notre vision est de devenir un leader dans notre secteur, connu pour sa créativité, sa qualité et son engagement envers la durabilité.
### Axes stratégiques
* **Innovation** : Continuer à innover et à améliorer nos produits et services pour répondre aux besoins de nos clients
* **Diversité et inclusion** : Promouvoir la diversité et l'inclusion dans notre équipe pour enrichir notre culture et notre expertise
* **Durabilité** : Agir en faveur de la durabilité et de l'écologie dans nos opérations et nos décisions
## Engagement
Notre engagement est de travailler ensemble pour atteindre nos objectifs et de nous tenir aux principes de notre stratégie.
### Axes d'action
* **Développement de la marque** : Renforcer notre présence sur les réseaux sociaux et améliorer notre image de marque
* **Formation et développement** : Offrir des opportunités de formation et de développement pour nos employés
* **Collaboration avec les partenaires** : Renforcer nos partenariats avec les autres entreprises et les organisations pour partager les connaissances et les ressources
## Conclusion
La stratégie WEVIA 2026 est un document vivant qui guide notre entreprise dans ses objectifs et ses actions. Nous sommes convaincus que cette stratégie nous aidera à atteindre notre vision et à devenir un leader dans notre secteur.
### Prochaines étapes
* **Mise en œuvre de la stratégie** : Lancer les projets et les actions pour mettre en œuvre la stratégie
* **Suivi et évaluation** : Suivre et évaluer les progrès et les résultats de la stratégie
* **Adaptation et ajustement** : Adapter et ajuster la stratégie en fonction des résultats et des changements de l'environnement

View File

@@ -0,0 +1,49 @@
# test stability
# **Test de stabilité**
Les tests de stabilité sont essentiels pour garantir que les applications sont robustes et peuvent fonctionner correctement dans diverses conditions.
* Vérification des erreurs et des exceptions
* Contrôle des performances et de la latence
* Évaluation de la tolérance aux erreurs de l'utilisateur
# **Types de tests de stabilité**
Il existe plusieurs types de tests de stabilité, notamment :
* Tests de stabilité fonctionnelle
* Tests de stabilité de performances
* Tests de stabilité sous charge
* Tests de stabilité en environnement de production
# **Objectifs des tests de stabilité**
Les objectifs des tests de stabilité sont multiples :
* Identifier les problèmes de stabilité
* Améliorer la robustesse de l'application
* Réduire les temps de maintenance et les coûts associés
* Améliorer l'expérience utilisateur
# **Méthodes de test de stabilité**
Les méthodes de test de stabilité incluent :
* Tests unitaires et intégrés
* Tests de charge et de stress
* Tests de compatibilité avec les différents navigateurs et systèmes d'exploitation
* Tests de tolérance aux erreurs de l'utilisateur
# **Résultats attendus**
Les résultats attendus des tests de stabilité sont :
* Une application robuste et stable
* Une réduction des temps de maintenance et des coûts associés
* Une amélioration de l'expérience utilisateur
* Une confiance accrue des utilisateurs dans l'application
# **Exemple de cas d'utilisation**
Exemple de cas d'utilisation :
* Une application en ligne de commerce qui doit pouvoir gérer un grand nombre d'utilisateurs simultanément
* Une application de gestion de projet qui doit pouvoir gérer des données sensibles et des utilisateurs multiples
# **Conclusion**
Les tests de stabilité sont essentiels pour garantir que les applications sont robustes et peuvent fonctionner correctement dans diverses conditions. En suivant les méthodes et les objectifs présentés dans cette présentation, les développeurs peuvent améliorer la stabilité de leurs applications et offrir une meilleure expérience utilisateur.

View File

@@ -0,0 +1,43 @@
# test stability
# Introduction au test de stabilité
* Définition : Test de stabilité pour vérifier la résistance d'un logiciel ou d'un système à des conditions normales et anormales.
* Objectif : Identifier les problèmes de stabilité et garantir la qualité du produit.
# Causes de perte de stabilité
* Bug de conception ou de codage
* Utilisation inappropriée de ressources système
* Interaction avec d'autres logiciels ou systèmes
* Changements dans l'environnement d'exécution
* Erreurs de configuration ou de paramétrage
# Types de tests de stabilité
* Tests de charge : Simuler un grand nombre d'utilisateurs ou de requêtes pour vérifier la capacité à gérer la charge.
* Tests de stress : Simuler un scénario de défaillance pour vérifier la capacité à résister à la pression.
* Tests de fonctionnement continu : Vérifier la stabilité du logiciel pendant une période prolongée.
* Tests de réparation : Vérifier la capacité à se réparer après une défaillance.
# Méthodes de test de stabilité
* Tests unitaires : Vérifier les fonctionnalités individuelles du logiciel.
* Tests d'intégration : Vérifier la cohérence entre les différentes parties du logiciel.
* Tests de système : Vérifier la stabilité du logiciel dans son ensemble.
* Tests de performance : Vérifier la vitesse et la efficacité du logiciel.
# Outils de test de stabilité
* Logiciels de test automatisé (par exemple, Selenium, Appium)
* Outils de test de performance (par exemple, JMeter, Gatling)
* Outils de test de stabilité (par exemple, Apache JMeter, NeoLoad)
* Outils de monitoring et de surveillance (par exemple, Nagios, Prometheus)
# Planification et exécution de tests de stabilité
* Définir les objectifs et les critères de réussite
* Développer un plan de test et une stratégie de test
* Exécuter les tests et analyser les résultats
* Réparer les problèmes identifiés et réitérer les tests
* Valider les résultats et livrer le produit

View File

@@ -0,0 +1,37 @@
# test stability
# Introduction au Test de Stabilité
* Définition : Test de stabilité pour vérifier la capacité d'un logiciel à fonctionner sans erreur ou problème pendant une période prolongée.
* Importance : Assurer la qualité et la fiabilité d'un logiciel avant sa mise en production.
* Objectifs : Identifier les bugs, les erreurs et les problèmes potentiels qui pourraient affecter la stabilité du logiciel.
# Types de Test de Stabilité
* **Test de stabilité fonctionnelle** : Vérifie la capacité du logiciel à fonctionner correctement dans différents scénarios.
* **Test de stabilité de performance** : Évalue la capacité du logiciel à gérer un volume important de données et de requêtes.
* **Test de stabilité de sécurité** : Vérifie la capacité du logiciel à résister aux attaques et aux vulnérabilités.
# Méthodes de Test de Stabilité
* **Test automatique** : Utilisation de scripts et de logiciels pour exécuter des tests répétitifs.
* **Test manuel** : Exécution de tests par des humains pour vérifier la stabilité du logiciel.
* **Test hybride** : Combinaison de tests automatiques et manuels pour couvrir un large éventail de scénarios.
# Avantages du Test de Stabilité
* **Amélioration de la qualité** : Identifie les bugs et les erreurs avant la mise en production.
* **Réduction des coûts** : Évite les coûts associés à la correction de bugs et à la maintenance.
* **Amélioration de la confiance** : Fournit une garantie de qualité et de fiabilité pour les utilisateurs.
# Défis du Test de Stabilité
* **Complexité** : Les tests de stabilité peuvent être complexes et nécessiter des ressources importantes.
* **Temps** : Les tests de stabilité peuvent prendre beaucoup de temps pour être exécutés.
* **Ressources** : Les tests de stabilité nécessitent des ressources importantes, notamment des équipements et des personnel.
# Conclusion
* Le test de stabilité est essentiel pour assurer la qualité et la fiabilité d'un logiciel.
* Les tests de stabilité peuvent être complexes et nécessiter des ressources importantes.
* La mise en place d'une stratégie de test de stabilité efficace peut aider à améliorer la qualité et la fiabilité d'un logiciel.

View File

@@ -0,0 +1,34 @@
# test stability
# Test de stabilité : Présentation
## Définition
* Test de stabilité : évaluation de la capacité d'un système à fonctionner correctement et de manière prévisible dans différentes conditions
* Objectif : identifier les problèmes de stabilité et garantir la qualité du logiciel
## Types de tests de stabilité
* Tests de stress : évaluation de la capacité du système à fonctionner sous une charge élevée
* Tests de fatigue : évaluation de la capacité du système à fonctionner pendant une longue période
* Tests de récupération : évaluation de la capacité du système à se rétablir après une panne
## Méthodologies de test de stabilité
* Tests unitaires : tests de code individuels pour garantir la stabilité des composants
* Tests d'intégration : tests de la stabilité des interactions entre les composants
* Tests de système : tests de la stabilité du système dans son ensemble
## Résultats et analyse
* Analyse des résultats : identification des problèmes de stabilité et des causes sous-jacentes
* Priorisation des problèmes : détermination de la gravité et de l'urgence des problèmes de stabilité
## Exemple de test de stabilité
* Test de stress : simulation d'une charge élevée sur le système pour évaluer sa capacité à fonctionner correctement
* Test de récupération : simulation d'une panne du système pour évaluer sa capacité à se rétablir
## Conclusion
* Test de stabilité : essentiel pour garantir la qualité et la fiabilité du logiciel
* Importance de la planification et de l'exécution efficace des tests de stabilité
## Bonnes pratiques
* Planification et coordination des tests de stabilité
* Utilisation de outils de test de stabilité efficaces
* Analyse et suivi des résultats des tests de stabilité

View File

@@ -0,0 +1,36 @@
# test stability
# **Test de stabilité : Introduction**
* Définition : Test de stabilité, également appelé test de durée ou test de stress, est un type de test qui vise à évaluer la capacité d'un système à fonctionner correctement pendant une période prolongée.
* Objectifs : Identifier les problèmes de stabilité, évaluer la capacité du système à gérer les charges de travail, et améliorer la fiabilité globale.
# **Types de tests de stabilité**
* **Test de durée** : Test de stabilité pendant une période prolongée (par exemple, 24 heures).
* **Test de stress** : Test de stabilité sous charge de travail élevée (par exemple, 1000 utilisateurs simultanément).
* **Test de charge de travail** : Test de stabilité avec une charge de travail réelle (par exemple, 1000 transactions par heure).
# **Méthodes de test de stabilité**
* **Test automatique** : Utilisation de scripts et de logiciels pour exécuter des tests de stabilité automatiquement.
* **Test manuel** : Utilisation d'humains pour exécuter des tests de stabilité manuellement.
* **Test hybride** : Combinaison de tests automatiques et manuels.
# **Éléments à tester**
* **Système d'exploitation** : Évaluation de la stabilité du système d'exploitation.
* **Applications** : Évaluation de la stabilité des applications.
* **Réseau** : Évaluation de la stabilité du réseau.
# **Résultats et analyse**
* **Rapports de test** : Génération de rapports détaillés sur les résultats des tests de stabilité.
* **Analyse des données** : Analyse des données collectées pendant les tests pour identifier les problèmes de stabilité.
* **Amélioration du système** : Application des résultats des tests pour améliorer la stabilité du système.
# **Conclusion**
* **Importance des tests de stabilité** : Les tests de stabilité sont essentiels pour évaluer la capacité d'un système à fonctionner correctement pendant une période prolongée.
* **Méthodes de test** : Les tests de stabilité peuvent être effectués de différentes manières, notamment par test automatique, test manuel et test hybride.
* **Amélioration du système** : Les résultats des tests de stabilité peuvent être utilisés pour améliorer la stabilité du système.

View File

@@ -219,4 +219,7 @@ h2{padding:12px 40px 0;font-size:15px;color:#22c55e;text-transform:uppercase;let
<script src="/api/a11y-auto-enhancer.js" defer></script>
<!-- WTP_UDOCK_V1 (Opus 21-avr t33b6) --><script src="/wtp-unified-dock.js" defer></script>
<script src="/opus-antioverlap-doctrine.js?v=1776776094" defer></script>
<section style="max-width:1200px;margin:20px auto;padding:20px 24px"><h2 style="font-family:Unbounded,sans-serif;font-size:20px;color:#eef0f4;margin-bottom:16px">Rescued Dashboards</h2><div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:16px"><a href="/dashboards-index.html" class="card" data-opus-wired="orphan-rescue"><div class="card-pill">OPS</div><h3>Dashboards Index</h3><p>Index complet des dashboards WEVAL</p><span class="card-link">Ouvrir →</span></a>
<a href="/token-health-dashboard.html" class="card" data-opus-wired="orphan-rescue"><div class="card-pill">OPS</div><h3>Token Health</h3><p>Santé tokens Anthropic/Gemini/OSS</p><span class="card-link">Ouvrir →</span></a>
</div></section>
</body></html>

View File

@@ -407,4 +407,7 @@ h1{background:linear-gradient(135deg,#10b981,#06b6d4);-webkit-background-clip:te
<a href="/wtp-udock-coverage.html" style="display:inline-block;padding:8px 14px;background:#3b82f6;color:#fff;text-decoration:none;border-radius:4px;font-size:13px">Ouvrir →</a>
</div>
<script src="/opus-antioverlap-doctrine.js?v=1776776094" defer></script>
<section style="max-width:1200px;margin:20px auto;padding:20px 24px"><h2 style="font-family:Unbounded,sans-serif;font-size:20px;color:#eef0f4;margin-bottom:16px">Rescued Dashboards v933</h2><div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:16px"><a href="/dashboards-index.html" class="card" data-opus-rescue="1"><div class="card-pill">OPS</div><h3>Dashboards Index</h3><p>Index complet des dashboards WEVAL</p><span class="card-link">Ouvrir →</span></a>
<a href="/token-health-dashboard.html" class="card" data-opus-rescue="1"><div class="card-pill">OPS</div><h3>Token Health</h3><p>Sante tokens Anthropic/Gemini/OSS</p><span class="card-link">Ouvrir →</span></a>
</div></section>
</body></html>

View File

@@ -4244,6 +4244,88 @@ if (typeof window.navigateTo === 'function'){
</script>
</section>
<section id="wtp-ai-capability-wave220" data-added-by="opus-wave-220" style="margin:24px 16px;padding:22px;background:linear-gradient(135deg,#1e1b4b 0%,#064e3b 100%);border:1px solid #8b5cf6;border-radius:12px;font-family:system-ui,sans-serif;box-shadow:0 10px 40px rgba(139,92,246,.2)">
<div style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;margin-bottom:16px">
<div>
<div style="display:flex;align-items:center;gap:10px">
<span style="font-size:22px">🧠</span>
<h2 style="margin:0;color:#ddd6fe;font-size:18px;font-weight:700">AI Capability Gap · Priority Wires OSS</h2>
<span style="padding:3px 10px;border-radius:12px;background:linear-gradient(135deg,#8b5cf6,#10b981);color:#fff;font-size:10px;font-weight:700">WAVE 220</span>
</div>
<p style="margin:4px 0 0 0;color:#c4b5fd;font-size:12px">8 capability gaps audit · 4 priority OSS wires · sovereign stack target</p>
</div>
<div id="wtp-ai-ts" style="padding:4px 10px;border-radius:10px;background:rgba(139,92,246,.15);color:#c4b5fd;font-size:11px;font-weight:600">loading...</div>
</div>
<div style="display:grid;grid-template-columns:1.4fr 1fr;gap:14px">
<!-- 8 Capability Gaps -->
<div style="padding:14px;background:rgba(0,0,0,.3);border:1px solid rgba(139,92,246,.2);border-radius:10px">
<div style="font-size:11px;color:#c4b5fd;text-transform:uppercase;letter-spacing:.6px;margin-bottom:10px;font-weight:700">📉 8 Capability Gaps · scored /90</div>
<div id="wtp-ai-gaps-list" style="display:flex;flex-direction:column;gap:6px"></div>
</div>
<!-- 4 Priority OSS Wires -->
<div style="padding:14px;background:rgba(0,0,0,.3);border:1px solid rgba(16,185,129,.2);border-radius:10px">
<div style="font-size:11px;color:#6ee7b7;text-transform:uppercase;letter-spacing:.6px;margin-bottom:10px;font-weight:700">🔗 4 Priority OSS to wire</div>
<div id="wtp-ai-wires-list" style="display:flex;flex-direction:column;gap:6px"></div>
</div>
</div>
<script>
(function(){
function gapRow(key, g){
var pri = g.priority || 'low';
var priCol = pri==='critical'?'#ef4444':(pri==='high'?'#f97316':(pri==='medium'?'#fbbf24':'#64748b'));
var score = g.current_score || 0;
var pct = score * 100 / 90;
var gapVal = g.gap || 0;
var cand = (g.candidates || []).length;
return '<div style="padding:8px 10px;background:rgba(255,255,255,.02);border-left:3px solid '+priCol+';border-radius:4px">'
+'<div style="display:flex;align-items:center;justify-content:space-between;gap:6px">'
+'<div style="display:flex;align-items:center;gap:6px"><span style="font-size:12px;color:#ddd6fe;font-weight:600;font-family:monospace">'+key+'</span>'
+'<span style="padding:1px 6px;border-radius:8px;background:'+priCol+'22;color:'+priCol+';font-size:9px;font-weight:700;text-transform:uppercase">'+pri+'</span></div>'
+'<span style="font-size:11px;color:#a78bfa;font-weight:700">'+score+'/90</span>'
+'</div>'
+'<div style="display:flex;align-items:center;gap:6px;margin-top:4px">'
+'<div style="flex:1;height:4px;background:rgba(255,255,255,.05);border-radius:2px;overflow:hidden"><div style="width:'+pct+'%;height:100%;background:'+priCol+'"></div></div>'
+'<span style="font-size:10px;color:#94a3b8">gap -'+gapVal+'</span>'
+(cand>0?'<span style="font-size:10px;color:#10b981">'+cand+' OSS</span>':'<span style="font-size:10px;color:#64748b">— tools</span>')
+'</div>'
+'</div>';
}
function wireRow(w){
return '<div style="padding:8px 10px;background:rgba(16,185,129,.05);border:1px solid rgba(16,185,129,.15);border-radius:6px">'
+'<div style="display:flex;align-items:center;justify-content:space-between;gap:6px">'
+'<span style="font-family:monospace;font-size:11.5px;color:#a7f3d0;font-weight:600">'+(w.tool||'?')+'</span>'
+'<span style="font-size:10px;color:#fbbf24;font-weight:700">★'+(w.stars||0).toLocaleString()+'</span>'
+'</div>'
+'<div style="font-size:10px;color:#94a3b8;margin-top:2px"><b style="color:#6ee7b7">'+(w.category||'?')+'</b> · '+(w.reason||'')+'</div>'
+'</div>';
}
fetch('/api/ai-gap-cache.json?cb='+Date.now())
.then(function(r){return r.json();})
.then(function(d){
var ts = document.getElementById('wtp-ai-ts');
if (ts) { ts.textContent = (d.timestamp||'').slice(0,10); ts.style.background='rgba(16,185,129,.15)'; ts.style.color='#6ee7b7'; }
var gl = document.getElementById('wtp-ai-gaps-list');
if (gl) {
var gaps = d.gaps || {};
var sorted = Object.keys(gaps).sort(function(a,b){return (gaps[a].gap||0) - (gaps[b].gap||0);}).reverse();
gl.innerHTML = sorted.map(function(k){return gapRow(k, gaps[k]);}).join('');
}
var wl = document.getElementById('wtp-ai-wires-list');
if (wl) {
var wires = d.priority_wires || [];
wl.innerHTML = wires.map(wireRow).join('');
}
})
.catch(function(){
var ts = document.getElementById('wtp-ai-ts');
if (ts) { ts.textContent='err'; ts.style.background='rgba(239,68,68,.15)'; ts.style.color='#fca5a5'; }
});
})();
</script>
</section>
<section id="wtp-drill-warn-wave219" data-added-by="opus-wave-219" style="margin:24px 16px;padding:22px;background:linear-gradient(135deg,#451a03 0%,#3b0764 100%);border:1px solid #fb923c;border-radius:12px;font-family:system-ui,sans-serif;box-shadow:0 10px 40px rgba(251,146,60,.18)">
<div style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;margin-bottom:16px">
<div>
@@ -4260,7 +4342,39 @@ if (typeof window.navigateTo === 'function'){
</div>
</div>
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:12px">
<div id="wtp-dw-filters" style="display:flex;flex-wrap:wrap;gap:5px;margin-bottom:12px;padding:10px;background:rgba(0,0,0,.2);border:1px solid rgba(251,146,60,.15);border-radius:8px">
<span style="font-size:10.5px;color:#fdba74;text-transform:uppercase;font-weight:700;padding:3px 6px">Filter:</span>
<button data-wtp-dw-cat="all" onclick="window.__wtpDwFilter('all')" style="padding:3px 10px;border-radius:12px;background:rgba(251,146,60,.2);color:#fdba74;border:1px solid rgba(251,146,60,.4);font-size:10.5px;cursor:pointer;font-weight:700">ALL</button>
<button data-wtp-dw-cat="revenue" onclick="window.__wtpDwFilter('revenue')" style="padding:3px 10px;border-radius:12px;background:rgba(16,185,129,.12);color:#6ee7b7;border:1px solid rgba(16,185,129,.3);font-size:10.5px;cursor:pointer">revenue</button>
<button data-wtp-dw-cat="customer_success" onclick="window.__wtpDwFilter('customer_success')" style="padding:3px 10px;border-radius:12px;background:rgba(244,114,182,.12);color:#f9a8d4;border:1px solid rgba(244,114,182,.3);font-size:10.5px;cursor:pointer">customer_success</button>
<button data-wtp-dw-cat="growth" onclick="window.__wtpDwFilter('growth')" style="padding:3px 10px;border-radius:12px;background:rgba(251,191,36,.12);color:#fde68a;border:1px solid rgba(251,191,36,.3);font-size:10.5px;cursor:pointer">growth</button>
<button data-wtp-dw-cat="engagement" onclick="window.__wtpDwFilter('engagement')" style="padding:3px 10px;border-radius:12px;background:rgba(34,211,238,.12);color:#a5f3fc;border:1px solid rgba(34,211,238,.3);font-size:10.5px;cursor:pointer">engagement</button>
<button data-wtp-dw-cat="predictive" onclick="window.__wtpDwFilter('predictive')" style="padding:3px 10px;border-radius:12px;background:rgba(168,85,247,.12);color:#ddd6fe;border:1px solid rgba(168,85,247,.3);font-size:10.5px;cursor:pointer">predictive</button>
<button data-wtp-dw-cat="platform_sla" onclick="window.__wtpDwFilter('platform_sla')" style="padding:3px 10px;border-radius:12px;background:rgba(110,231,183,.12);color:#a7f3d0;border:1px solid rgba(110,231,183,.3);font-size:10.5px;cursor:pointer">platform_sla</button>
<button data-wtp-dw-cat="productivity" onclick="window.__wtpDwFilter('productivity')" style="padding:3px 10px;border-radius:12px;background:rgba(253,186,116,.12);color:#fed7aa;border:1px solid rgba(253,186,116,.3);font-size:10.5px;cursor:pointer">productivity</button>
</div>
<script>
window.__wtpDwFilter = function(cat){
// Highlight active button
document.querySelectorAll('[data-wtp-dw-cat]').forEach(function(btn){
var isActive = btn.dataset.wtpDwCat === cat;
btn.style.background = isActive ? 'rgba(251,146,60,.3)' : btn.style.background.replace(/\.3\)/g,'.12)');
btn.style.fontWeight = isActive ? '700' : '400';
});
// Filter kpi rows in fix & wire lists: match category chip color or data-category
['wtp-dw-fix-list','wtp-dw-wire-list'].forEach(function(id){
var el = document.getElementById(id);
if (!el) return;
el.querySelectorAll(':scope > div').forEach(function(row){
if (cat === 'all') { row.style.display = 'block'; return; }
var txt = row.textContent.toLowerCase();
var short = cat.slice(0,8).toUpperCase();
row.style.display = txt.indexOf(short.toLowerCase()) !== -1 || txt.indexOf(cat.replace('_',' ').toLowerCase()) !== -1 ? 'block' : 'none';
});
});
};
</script>
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:12px">
<!-- WARN list (priority_fix_list) -->
<div style="padding:14px;background:rgba(0,0,0,.3);border:1px solid rgba(251,146,60,.2);border-radius:10px">
<div style="display:flex;align-items:center;gap:6px;margin-bottom:10px">

View File

@@ -1279,11 +1279,21 @@ function send() {
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({message: text, session_id: convId || ('wv-' + Date.now())})
})
.then(function(r) { return r.json(); })
.then(function(r) {
// AMBRE-V4-ROBUST: safe JSON parsing, tolerate empty/HTML responses
return r.text().then(function(txt) {
if (!txt || !txt.trim()) return { response: 'Pas de reponse.', provider: 'empty', intent: 'empty' };
try { return JSON.parse(txt); }
catch (e) {
console.warn('[Ambre] JSON parse failed, using text fallback');
return { response: txt.substring(0, 2000), provider: 'text-fallback', intent: 'raw' };
}
});
})
.then(function(data) {
hideThinking();
var elapsed = ((performance.now() - startTime) / 1000).toFixed(1);
var response = data.response || data.content || 'Pas de reponse.';
var response = data.response || data.content || data.message || data.result || 'Pas de reponse.';
if (data.conversation_id) convId = data.conversation_id;
chatHistory.push({role: 'assistant', content: response});
var msgEl = addMsg('assistant', response, elapsed);

View File

@@ -0,0 +1,37 @@
# Session Opus v9.33 · Orphans Rescue + Cache Refresh · 21 avr 22h50
## Scan exhaustif post 7h autres Claudes
- Autres Claudes tres actifs: wave(218) KPI alerting + Archi 3D + Playwright 6/6
- Auto-sync WEVIA toutes les 5min (nombreux commits)
- 2 nouvelles pages dashboards: dashboards-index.html + token-health-dashboard.html
- Regression detectee: orphans_count 0 -> 1 (puis 2 avec 2e page)
- NonReg 153/153 MAINTENU throughout
## Root cause orphans
- pages-orphans-list.php check 27 "anchor_files" hardcoded
- monitoring-hub.html NOT in anchor list
- orphans-hub.html IS in anchor list
- Wiring monitoring-hub ne suffit pas, il faut orphans-hub
## Fix applique
1. 2 orphan cards wired dans orphans-hub.html (GOLD backup cree)
2. 2 orphan cards wired dans monitoring-hub.html (double coverage)
3. Trigger regen /tmp/wevia-pages-registry-cache.json
4. V83 KPI orphans_count: 1 -> 0 ✅
## Autres Claudes reconcile
- wave(218) KPI alerting banner live
- wave(209) duplicates registry API + WTP section
- public-P3-P4-sanitize 12 replacements
- wiki-agents-archi-flatten 28 items full-width
- Multi auto-sync WEVIA git_sync_all
## Status final
NonReg 153/153 ✅
Arch KPIs 8/8 [OK] tous verts ✅
pages_total 317 (+2 nouvelles dashboards) ✅
orphans 0 ✅ (RESTORED)
tools_exec_ratio 79% (stable) ✅
Multi-agent 14 LIVE ✅
Vault 5392 Wiki 2066 GOLD 160 ✅
3-way sync OK