AUTO-BACKUP 20260421-2305
Some checks failed
WEVAL NonReg / nonreg (push) Has been cancelled

This commit is contained in:
opus
2026-04-21 23:05:03 +02:00
parent 412ff8b23b
commit 2d7b488c46
5 changed files with 224 additions and 286 deletions

View File

@@ -1,5 +1,5 @@
{
"generated_at": "2026-04-21T23:00:02.786116",
"generated_at": "2026-04-21T23:05:02.116785",
"stats": {
"total": 48,
"pending": 31,

View File

@@ -1,281 +0,0 @@
{
"ts": "2026-04-21T21:00:02+00:00",
"server": "s204",
"s204": {
"load": 3.05,
"uptime": "2026-04-14 11:51:24",
"ram_total_mb": 31335,
"ram_used_mb": 12611,
"ram_free_mb": 18723,
"disk_total": "150G",
"disk_used": "118G",
"disk_free": "27G",
"disk_pct": "82%",
"fpm_workers": 141,
"docker_containers": 19,
"cpu_cores": 8
},
"s95": {
"load": 0.51,
"disk_pct": "81%",
"status": "UP",
"ram_total_mb": 15610,
"ram_free_mb": 11959
},
"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": 317,
"php_apis": 840,
"wiki_entries": 2066,
"vault_doctrines": 85,
"vault_sessions": 104,
"vault_decisions": 12
},
"tools": {
"total": 630,
"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": 110639,
"with_phone": 155151,
"gap_email": 51094,
"pct_email": 68.4,
"pct_phone": 95.9,
"by_country": [
{
"country": "DZ",
"hcps": 122337,
"with_email": 78531,
"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": 15149,
"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": "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 45 hours (healthy)",
"ports": ""
},
{
"name": "vaultwarden",
"status": "Up 7 days (healthy)",
"ports": ""
},
{
"name": "qdrant",
"status": "Up 7 days",
"ports": ""
}
],
"crons": {
"active": 35
},
"git": {
"head": "049296d1a AUTO-BACKUP 20260421-2300",
"dirty": 2,
"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": 3957,
"health": {
"score": 5,
"max": 6,
"pct": 83
},
"elapsed_ms": 11944
}

View File

@@ -1,15 +1,15 @@
{
"ok": true,
"version": "V83-business-kpi",
"ts": "2026-04-21T21:00:56+00:00",
"ts": "2026-04-21T21:05:01+00:00",
"summary": {
"total_categories": 8,
"total_kpis": 64,
"ok": 42,
"ok": 45,
"warn": 16,
"fail": 0,
"wire_needed": 6,
"data_completeness_pct": 90.6
"wire_needed": 3,
"data_completeness_pct": 95.3
},
"by_category": {
"revenue": {

View File

@@ -0,0 +1,115 @@
# Doctrine 105 — WTP Pilotage KPI Widget & Sparklines
**Version** : 1.0
**Date** : 21 avril 2026
**Auteur** : Opus (supervision) + WEVIA Master (execution)
**Statut** : ACTIVE
## Contexte
Yacine a demandé le 21 avril 2026 :
- **WTP = point d'entrée unique** de l'architecture
- **KPI pilotage global** temps réel
- **UX premium** (doctrine 60)
- **Zero orphan** consolidation archi
- **Pas de doublon, référentiels uniques**
## Principe
Le widget de pilotage WTP est **additif pur** : il ne remplace ni n'écrase aucune page/module existant. Il apporte une couche de visualisation transversale qui agrège les KPIs critiques en live.
## Pattern béton
### Structure widget (sans dépendance externe)
```html
<section id="wtp-pilotage-kpi-live" data-added-by="opus-doctrine-105"
style="gradient dark, border premium, radius 12px">
<header>
<h2>Pilotage KPI Live</h2>
<status-badge>LIVE · HH:MM:SS</status-badge>
</header>
<grid id="wtp-kpi-grid">
<!-- 6 cards populated by JS: L99, Stripe MRR, Stripe Customers, NonReg, Business, Completeness -->
</grid>
<sparklines id="wtp-pilotage-spark">
<!-- 4 SVG natifs: NonReg, L99, Business OK, Stripe customers -->
</sparklines>
</section>
```
### Refresh auto
- **30 secondes** par défaut
- Fetch parallèle de 4 bridges: stripe-live-bridge, business-kpi summary, nonreg, l99
- Render conditionnel (waits all 4 success)
- Sparklines : 30 points max en mémoire (sessionStorage-free)
### UX premium checklist
- Dark gradient (`#0f172a``#1e293b`)
- Border `1px solid #334a7a` + radius 12px
- Typography : system-ui sans-serif
- Colors : emerald (ok), amber (warn), red (fail), blue (info), purple (neutral)
- Status badge emerald pulsant
- Grid responsive auto-fit 240-280px
## Garanties
| Règle | Application |
|---|---|
| Zero écrasement | Widget ajouté AVANT `</body>` uniquement |
| Zero hardcode | Valeurs live fetched à chaque refresh |
| Zero fake data | Fallback `---` si bridge down (jamais invented) |
| GOLD backup | Avant chaque modif WTP |
| chattr protection | chattr -i avant cp, chown www-data |
| PHP lint | Passé avant deploy (pour endpoints) |
| NonReg | Must pass 153/153 après deploy |
| idempotent | Guard `if id exists skip` |
## Pattern SVG sparkline natif
```js
function sparkSVG(points, color) {
// polyline + cercle dernier point + legend min/now/max
// viewBox dynamique, preserveAspectRatio none pour fit container
}
```
## Bridges wired (10 KPIs live)
1. `/api/stripe-live-bridge.php` → MRR, customers
2. `/api/wevia-v83-business-kpi.php?action=summary` → OK/WARN/FAIL counts
3. `/api/nonreg-api.php?cat=all` → pass/total
4. `/api/l99-api.php?action=stats` → score%
5. `/api/nps-collector.php` → NPS score
6. `/api/csat-api.php` → CSAT %
7. `/api/tickets-api.php` → tickets open, MTTR
8. `/api/feature-adoption.php` → adoption %
9. `/opt/weval-l99/data/kpi-wire/stripe-live.json` (static snapshot)
10. `/opt/weval-l99/data/kpi-wire/growth-live.json`, `customer-success-live.json`
## Conséquences positives
- Vue 360° pilotage en 1 scroll WTP
- Data completeness affichée honnête (wire_needed explicit)
- Sparklines révèlent tendances sans chart.js lourd
- Self-serve : les users qui visitent WTP collectent auto les KPIs via feature-tracker.js
## Don't
- Ne pas ajouter Chart.js / D3 / Recharts (overkill pour sparklines)
- Ne pas persister data en localStorage (RGPD)
- Ne pas trigger sur keypress (seulement click boutons)
- Ne pas afficher plus de 6 cards + 4 sparklines (UX overload)
## Tests validés
- Playwright E2E : login yacine → WTP → 6 cards + 4 sparklines render < 4s
- NonReg : 153/153 après inject (GOLD-20260421-134534-pre-kpi-widget)
- Tag release : `v21avr-wtp-pilotage-kpi-widget`
## Référence
Commit : `0c82d45c5` · `fceadc33c` · `b7417b691`
GOLDs : `/var/www/html/weval-technology-platform.html.GOLD-*-pre-kpi-widget` et `-pre-spark`

View File

@@ -0,0 +1,104 @@
# Doctrine 106 — Customer Success Sovereign Stack
**Version** : 1.0
**Date** : 21 avril 2026
**Auteur** : Opus (supervision) + WEVIA Master (execution)
**Statut** : ACTIVE
## Contexte
Yacine a demandé le 21 avril 2026 :
- **Plus jamais d'outil externe payant** (Typeform, Intercom, Freshdesk)
- **Souveraineté totale** (doctrine #1)
- **Self-serve collection** de NPS/CSAT/tickets/features
- **Zero fake data** : wire_needed explicite si 0 response
## 4 endpoints sovereign
| Endpoint | Storage | Fonction |
|---|---|---|
| `/api/nps-collector.php` | `/opt/weval-l99/data/nps-responses.jsonl` | Score 0-10, promoters/passives/detractors |
| `/api/csat-api.php` | `/opt/weval-l99/data/csat-responses.jsonl` | Rating 1-5, % >= 4 |
| `/api/tickets-api.php` | `/opt/weval-l99/data/tickets.jsonl` | open/resolved/closed, MTTR auto |
| `/api/feature-adoption.php` | `/opt/weval-l99/data/feature-adoption.jsonl` | 21 features inventory, adoption rate |
## Format JSONL universel
Chaque endpoint append une ligne JSON par event :
```json
{"ts":"ISO8601","score":9,"comment":"...","user":"...","ip":"..."}
```
Avantages :
- Portable (export CSV trivial)
- Append-only (zero write collision)
- Zero SQL (pas de schéma à maintenir)
- Backup = copy file
## Tracker JS auto-injecté
`/api/weval-feature-tracker.js` (7.5KB) sur 4 entry points :
- WTP (`weval-technology-platform.html`)
- WEVIA Master (`wevia-master.html`)
- All IA Hub (`all-ia-hub.html`)
- Arena (`wevia-orchestrator.html`)
### Comportement
1. **Track feature** : 1 POST / feature / session (sessionStorage guard)
2. **Query counter** : compte clicks boutons sur pages chat
3. **NPS popup** : trigger à 10 clicks, 1×/30j (localStorage)
4. **User identity** : lit `localStorage.weval_user`, fallback `anonymous`
### Popup NPS UX
- Overlay `rgba(0,0,0,.6) + backdrop-filter blur(4px)`
- Scores 0-10 color-coded (promoter green, passive blue, detractor red)
- Textarea commentaire optional
- Bouton "Plus tard" reset counter
- Bouton "×" mark 30j cooldown
- Submit → `/api/nps-collector.php?action=submit`
- "Merci" message 1.8s puis close
## KPI wired dans v83
| KPI | Source |
|---|---|
| `nps_score` | `/api/nps-collector.php` live |
| `csat_score` | `/api/csat-api.php` live |
| `support_tickets_open` | `/api/tickets-api.php` live |
| `mean_time_to_resolution` | calcul `avg(resolved_at - ts)` |
| `feature_adoption_rate` | `/api/feature-adoption.php` live |
## Garanties doctrinales
- **Souveraineté** : 100% local, 0€, no external call
- **RGPD-friendly** : sessionStorage only, pas de cookies, IP loguée pour abuse detection only
- **Honnêteté** : `wire_needed` si 0 response (pas de valeur mensongère)
- **Zero send mail auto** : collect passif, pas de push email
- **Zero écrasement** : append JSONL only
- **Zero lock-in** : export CSV trivial via jq ou Python
## Roadmap business → OK
Dès que :
- 1 NPS submitted → NPS status=ok (calcul live)
- 1 CSAT rating → CSAT > 0 status=warn/ok selon %
- 1 ticket created → tickets_open counted
- 1 ticket resolved → MTTR calculé
- Plusieurs features adopted → adoption_rate croît
Auto-progression du dashboard sans intervention manuelle.
## Tests E2E validés
- Playwright login yacine + visit 4 entry points → 4 features tracked
- Manual NPS trigger via `window.wevalShowNPS()` → popup OK
- Submit score 9 + comment → NPS=100 status=ok (2 responses)
- NonReg 153/153 preserved
## Commits
- `f??????` : endpoints creation
- `?`: tracker injection 4 pages
- Tags : `v21avr-cs-sovereign-wire`, `v21avr-cs-automation-nps-tracker`