diff --git a/all-ia-hub.html b/all-ia-hub.html
index 83ed34456..ec9aa4b22 100644
--- a/all-ia-hub.html
+++ b/all-ia-hub.html
@@ -113,7 +113,7 @@ body.light #theme-toggle::before{content:"\263D"}
🎰 Orchestrator
·
💻 WevCode
- All-IA Hub · consolidation 84 dashboards
+ All-IA Hub · consolidation 84 dashboards
@@ -916,6 +916,26 @@ function __dashTogglePin(name){
}
}
+/* V135-KPI-BANNER: load screens-health summary and update banner (zero impact on UX if fetch fails) */
+(function(){
+ const kpi = document.getElementById('v135-kpi-live');
+ if (!kpi) return;
+ fetch('/api/screens-health.json', {cache: 'no-store'}).then(r => r.ok ? r.json() : null).then(d => {
+ if (!d || !d.counts) return;
+ const c = d.counts;
+ const total = d.total || 0;
+ const up = c.UP || 0;
+ const broken = c.BROKEN || 0;
+ const down = c.DOWN || 0;
+ const phantom = c.PHANTOM || 0;
+ const active = total - phantom;
+ const healthPct = active ? Math.round((up / active) * 100) : 0;
+ const dot = (broken + down === 0) ? '\u{1F7E2}' : (broken + down < 20 ? '\u{1F7E1}' : '\u{1F534}');
+ kpi.innerHTML = 'All-IA Hub · ' + dot + ' ' + healthPct + '% (' + up + ' UP · ' + broken + ' broken)';
+ kpi.title = 'Platform health: ' + up + ' UP / ' + broken + ' BROKEN / ' + down + ' DOWN / ' + phantom + ' phantom (total ' + total + ')';
+ }).catch(_ => {});
+})();
+
setTimeout(() => {
const btn = document.querySelector('[data-view="dashboards"]');
if (btn) btn.addEventListener('click', () => { if (!__dashData) loadDashboards(); });
diff --git a/api/blade-tasks/v135-kpi-banner-proof/01-kpi-banner-top.png b/api/blade-tasks/v135-kpi-banner-proof/01-kpi-banner-top.png
new file mode 100644
index 000000000..74146fb5c
Binary files /dev/null and b/api/blade-tasks/v135-kpi-banner-proof/01-kpi-banner-top.png differ
diff --git a/api/blade-tasks/v135-kpi-banner-proof/proof.json b/api/blade-tasks/v135-kpi-banner-proof/proof.json
new file mode 100644
index 000000000..d25f8794b
--- /dev/null
+++ b/api/blade-tasks/v135-kpi-banner-proof/proof.json
@@ -0,0 +1,10 @@
+{
+ "v135": "kpi-banner-live",
+ "banner_exists": true,
+ "fetches_health_live": true,
+ "shows_status_dot": true,
+ "innerHTML_preview": "All-IA Hub \u00b7 \ud83d\udfe1 85% (469 UP \u00b7 17 broken)",
+ "title_preview": "Platform health: 469 UP / 17 BROKEN / 0 DOWN / 1185 phantom (total 1737)",
+ "js_errors": [],
+ "VERDICT": "OK"
+}
\ No newline at end of file
diff --git a/wiki/V135-kpi-banner-live.md b/wiki/V135-kpi-banner-live.md
new file mode 100644
index 000000000..c32ace1b7
--- /dev/null
+++ b/wiki/V135-kpi-banner-live.md
@@ -0,0 +1,110 @@
+# V135 Opus WIRE - KPI Banner Live + Intent Doublon Évité · 21avr 11:22
+
+## Context
+Yacine "CONTINUE" après V131-V134. Objectif: poursuivre consolidation + ajout valeur additive.
+
+## Scan exhaustif initial (doctrine #1)
+
+Découverte MAJEURE: autre Claude (commit `14ecacd24`) a créé **"ERP Command Center V105"** dans WTP:
+- Nouvelle section 12.5KB +
+- 5 cards penta-pivot (WTP gold, All-IA pink, Arena purple, Orchestrator green, WevCode emerald)
+- 8 KPI agrégés live depuis mon `/api/dashboards-registry.php` + master-api + tips catalog
+- HTTP status per pillar live
+- UX doctrine 60 glassmorphism
+
+Mon registry API V116 sert de data source pour cette section. Collaboration multi-Claude excellente.
+
+## Livrables V135
+
+### V135a - Intent `screens health` (AVORTÉ, doublon détecté)
+J'avais commencé à ajouter un intent PHP dans `wevia-opus46-intents.php` pour router les queries "screens health" vers le JSON. Le test chat a révélé qu'un intent **existait déjà** : `ops_screens_health` avec tool `screens_health_real_read`, plus riche que ma version (health_pct, status DEGRADED/OK, problem_urls_sample).
+
+**Action** : Rollback immédiat depuis GOLD (doctrine #1 scan + #14 additif pur = PAS de doublon).
+
+GOLD préservé: `/opt/wevads/vault/wevia-opus46-intents.php.GOLD-V135-pre-screens-health`
+
+### V135b - KPI Banner live dans breadcrumb V130
+Pivot vers enrichissement additif: un banner KPI live dans la barre de navigation cross-surface.
+
+**Avant (V130)** : `All-IA Hub · consolidation 84 dashboards`
+**Après (V135)** : `All-IA Hub · 🟡 85% (469 UP · 17 broken)`
+
+Tooltip enrichi : `Platform health: 469 UP / 17 BROKEN / 0 DOWN / 1185 phantom (total 1737)`
+
+Status dot adaptatif :
+- 🟢 si broken + down == 0
+- 🟡 si broken + down < 20
+- 🔴 sinon
+
+**Source** : `/api/screens-health.json` (déjà maintenu par cron autre Claude, pas de nouvelle infra).
+
+**Impact** :
+- Yacine voit la santé globale plateforme dès l'ouverture du Hub
+- Complète V131 broken badge (local 84 dashboards) avec V135 banner (global 1737 URLs)
+- Zero impact si fetch échoue (silent fallback sur texte original)
+
+## Validation E2E Playwright V135
+
+```json
+{
+ "v135": "kpi-banner-live",
+ "banner_exists": true,
+ "fetches_health_live": true,
+ "shows_status_dot": true,
+ "innerHTML_preview": "All-IA Hub · 🟡 85% (469 UP · 17 broken)",
+ "title_preview": "Platform health: 469 UP / 17 BROKEN / 0 DOWN / 1185 phantom (total 1737)",
+ "js_errors": [],
+ "VERDICT": "OK"
+}
+```
+
+## KPI Architecture 2 niveaux (consolidation)
+
+| Niveau | Source | Scope | Localisation UI |
+|---|---|---|---|
+| **Local** (V131) | `/api/dashboards-registry.php` | 84 dashboards registry | Counter DASHBOARDS tab |
+| **Global** (V135) | `/api/screens-health.json` | 1737 URLs (incluant WTP, Arena, orchestrator etc.) | Breadcrumb xnav top |
+
+Pas de redondance — chaque KPI couvre un scope différent.
+
+## Métriques V134 → V135
+
+| | V134 | V135 |
+|---|---|---|
+| Hub size | 54.7KB | 55.9KB (+1.2KB) |
+| KPI live visibles | 1 (84 dashboards) | **2** (84 dashboards + 1737 URLs) |
+| Status dot plateforme | non | 🟢/🟡/🔴 |
+| Intents doublon créés | 0 | 0 (doublon évité ✅) |
+| Sources JSON consommées | registry | registry + screens-health |
+| JS errors | 0 | 0 |
+
+## Doctrines respectées (session V135)
+
+- **#1 scan exhaustif** : détection doublon intent `ops_screens_health` AVANT merge → rollback immédiat
+- **#3 GOLD** : backup pré-intent + pré-banner
+- **#4 honnêteté** : E2E prouvé 4/4, status dot reflète la vraie santé (17 broken réels)
+- **#13 cause racine** : au lieu de dupliquer intent, consomme le JSON source de vérité
+- **#14 ADDITIF PUR** : pivot vers nouvelle fonctionnalité sans écrasement
+- **#16 NR** : transient 2 fails pas provoqué par V135
+- **#60 UX premium** : status dot adaptatif + tooltip riche
+
+## Sessions consécutives sans régression applicative : **100+** 🎯
+
+## État session cumulé V107 → V135 (16 itérations additives Opus)
+
+```
+V107-V109 Hub base + 3 tabs (chat/code/arena) + Mode Humain
+V110-V115 8 intents + 3 APIs (blade-task, router-activity, training-status)
+V116-V118 DASHBOARDS tab + registry + intent chat dashboards_status
+V119-V121 Search + Sort + Counter + Cmd+K + E2E proof
+V122-V123 CSS polish + Pinning URL hash
+V124-ENRICH (autre Claude) split section + clear + new badge
+V125 Widen patterns 69→84 + 14 cats zero "other"
+V126-V127 Verify new badge + Recent filter chip
+V128-V129 Scroll-to-top + URL state bookmarkable
+V130 Cross-surface breadcrumb (étendu PENTA-PIVOT par autre Claude)
+V131-V134 Broken badge + WTP health + Wiki index + Arena verify
+V135 KPI banner live global (doublon intent évité)
+```
+
+Hub final : 55.9KB · 7 onglets · 84 dashboards · 14 cats · breadcrumb 5-way · KPI global live · URL state complet · GOLDs 18 préservés.