phase-5 doctrine-144 WTP orphans registry rattache 261 pages zero ecrasement
Some checks failed
WEVAL NonReg / nonreg (push) Has been cancelled
Some checks failed
WEVAL NonReg / nonreg (push) Has been cancelled
Constat initial: - 333 pages html racine - 72 linkees dans WTP (21.6 pct) - 261 ORPHELINES (78 pct) non reliees a la source de verite Solution zero ecrasement WTP: 1. Endpoint /api/wtp-orphans-registry.php (80L PHP) - Scan dynamique pages racine - Categorisation auto 13 categories - Detection variantes (-v, -hd, -final, -alive) - Scan duration 6-10ms live - Retourne JSON avec mtime size counts variant_groups 2. Page /wtp-orphans-registry.html (201L 14KB HTML) - UX premium editorial Fraunces serif Inter JetBrains Mono - 6 KPI cards gold/green/orange/gold/violet - Filter tags cliquables 13 categories - Search input live - 262 page cards nom size date - Zero chevauchement bouton Back WTP Hub - 0 JS errors valide Playwright 3. Doctrine 144 sync 3 emplacements wiki + vault + weval-l99 Categorisation 261 orphelines: - 244 ACTIVE a rattacher (HUB 36 + DASHBOARD 21 + ADMIN 10 + CRM 4 + BLADE 4 + AGENT 2 + AI 2 + PRODUCT 1 + OTHER 165) - 17 ARCHIVABLE (DOUBLON 8 + LEGACY 4 + TESTS 4 + DEPRECATED 1) Validation Playwright: - 5 screenshots + video webm - Public URL weval-consulting.com/proofs/wtp-orphans-registry-2026-04-23T20-02-58/ - KPIs 6 sections 13 pagecards 262 JS errors 0 Zero modification WTP (doctrine Yacine: pas ecraser sans autorisation). Doctrine 145 futur: merge WTP+registry vue unifiee ERP si autorisation.
This commit is contained in:
69
vault-gold/opus/phase5-20260423-220512/pw-wtp-registry.js
Executable file
69
vault-gold/opus/phase5-20260423-220512/pw-wtp-registry.js
Executable file
@@ -0,0 +1,69 @@
|
||||
const { chromium } = require('/var/www/html/api/node_modules/playwright');
|
||||
const fs = require('fs');
|
||||
(async () => {
|
||||
const ts = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
|
||||
const outdir = `/var/www/html/proofs/wtp-orphans-registry-${ts}`;
|
||||
fs.mkdirSync(outdir, { recursive: true });
|
||||
|
||||
const browser = await chromium.launch({ headless: true, args: ['--no-sandbox', '--disable-dev-shm-usage'] });
|
||||
const ctx = await browser.newContext({ viewport: { width: 1400, height: 900 }, recordVideo: { dir: outdir, size: { width: 1400, height: 900 } } });
|
||||
const page = await ctx.newPage();
|
||||
|
||||
const js_errors = [];
|
||||
page.on('pageerror', err => js_errors.push(err.message));
|
||||
|
||||
const result = { ts: new Date().toISOString(), ok: false };
|
||||
|
||||
try {
|
||||
await page.goto('https://weval-consulting.com/wtp-orphans-registry.html', { waitUntil: 'domcontentloaded', timeout: 20000 });
|
||||
await page.waitForTimeout(3500); // wait for fetch JSON + render
|
||||
|
||||
await page.screenshot({ path: `${outdir}/01-initial.png`, fullPage: false });
|
||||
|
||||
const diag = await page.evaluate(() => ({
|
||||
title: document.title,
|
||||
kpis_count: document.querySelectorAll('.k-card').length,
|
||||
sections_count: document.querySelectorAll('.sec').length,
|
||||
pagecards: document.querySelectorAll('.pc').length,
|
||||
filter_tags: document.querySelectorAll('.filter .tag').length,
|
||||
has_search: !!document.getElementById('q'),
|
||||
body_height: document.body.scrollHeight
|
||||
}));
|
||||
result.diag = diag;
|
||||
|
||||
// Scroll
|
||||
await page.evaluate(() => window.scrollTo(0, 800));
|
||||
await page.waitForTimeout(500);
|
||||
await page.screenshot({ path: `${outdir}/02-scroll-1.png`, fullPage: false });
|
||||
|
||||
await page.evaluate(() => window.scrollTo(0, 2000));
|
||||
await page.waitForTimeout(500);
|
||||
await page.screenshot({ path: `${outdir}/03-scroll-2.png`, fullPage: false });
|
||||
|
||||
// Fullpage
|
||||
await page.evaluate(() => window.scrollTo(0, 0));
|
||||
await page.waitForTimeout(400);
|
||||
await page.screenshot({ path: `${outdir}/04-fullpage.png`, fullPage: true });
|
||||
|
||||
// Click HUB filter test
|
||||
await page.click('.tag[data-cat="ACTIVE_HUB"]');
|
||||
await page.waitForTimeout(700);
|
||||
await page.screenshot({ path: `${outdir}/05-filter-hub.png`, fullPage: false });
|
||||
|
||||
result.ok = true;
|
||||
result.js_errors = js_errors;
|
||||
|
||||
} catch (e) {
|
||||
result.error = e.message;
|
||||
result.js_errors = js_errors;
|
||||
}
|
||||
|
||||
await ctx.close();
|
||||
await browser.close();
|
||||
|
||||
const videos = fs.readdirSync(outdir).filter(f => f.endsWith('.webm'));
|
||||
result.videos = videos;
|
||||
result.public_url = `https://weval-consulting.com/proofs/wtp-orphans-registry-${ts}/`;
|
||||
fs.writeFileSync(`${outdir}/results.json`, JSON.stringify(result, null, 2));
|
||||
console.log(JSON.stringify(result, null, 2));
|
||||
})();
|
||||
201
vault-gold/opus/phase5-20260423-220512/wtp-orphans-registry.html
Normal file
201
vault-gold/opus/phase5-20260423-220512/wtp-orphans-registry.html
Normal file
@@ -0,0 +1,201 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>WTP Orphans Registry · 261 pages à relier</title>
|
||||
<style>
|
||||
:root{
|
||||
--ink:#0a0e1a;--ink2:#0c1120;--ink3:#111a2e;--line:#1a2238;--line2:#2a3450;
|
||||
--paper:#e8eaf0;--smoke:#9aa3b8;--fog:#6b7490;
|
||||
--gold:#d4a853;--gold-br:#f3c678;--gold-lt:#ffd98a;
|
||||
--em:#10b981;--em-lt:#4ade80;--sa:#22d3ee;--to:#fbbf24;--to-lt:#fde047;
|
||||
--ru:#ef4444;--vi:#a855f7;--pi:#f472b6;
|
||||
--sans:-apple-system,BlinkMacSystemFont,"Segoe UI",Inter,system-ui,sans-serif;
|
||||
--serif:"Fraunces","Playfair Display",Georgia,serif;
|
||||
--mono:"JetBrains Mono","Fira Code",ui-monospace,monospace;
|
||||
}
|
||||
*{box-sizing:border-box;margin:0;padding:0}
|
||||
body{background:var(--ink);color:var(--paper);font-family:var(--sans);font-size:13.5px;line-height:1.6;min-height:100vh;padding:20px 28px;overflow-x:hidden}
|
||||
.hd{max-width:1400px;margin:0 auto 30px;padding-bottom:18px;border-bottom:1px solid var(--line2);position:relative}
|
||||
.hd .eyebrow{font-family:var(--mono);font-size:10px;color:var(--gold);letter-spacing:.2em;text-transform:uppercase;margin-bottom:8px}
|
||||
.hd h1{font-family:var(--serif);font-weight:500;font-size:34px;line-height:1.1;color:var(--paper)}
|
||||
.hd h1 em{color:var(--gold);font-style:italic}
|
||||
.hd .sub{margin-top:6px;font-size:13px;color:var(--fog);font-style:italic;font-family:var(--serif)}
|
||||
.hd .back{position:absolute;top:0;right:0;padding:7px 14px;background:transparent;border:1px solid var(--line2);border-radius:2px;color:var(--fog);font-family:var(--sans);font-size:11px;text-decoration:none;text-transform:uppercase;letter-spacing:.08em;transition:all .15s}
|
||||
.hd .back:hover{color:var(--gold);border-color:var(--gold)}
|
||||
.wrap{max-width:1400px;margin:0 auto}
|
||||
.kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px;margin-bottom:24px}
|
||||
.k-card{padding:16px 20px;background:var(--ink2);border:1px solid var(--line);border-radius:3px;position:relative;overflow:hidden;transition:all .2s}
|
||||
.k-card:hover{border-color:var(--line2);transform:translateY(-2px)}
|
||||
.k-card .lbl{font-family:var(--mono);font-size:9px;text-transform:uppercase;letter-spacing:.15em;color:var(--fog);margin-bottom:8px}
|
||||
.k-card .v{font-family:var(--serif);font-weight:600;font-size:36px;line-height:1;margin-bottom:4px;color:var(--gold)}
|
||||
.k-card .d{font-size:11px;color:var(--fog)}
|
||||
.k-card.em .v{color:var(--em-lt)} .k-card.wa .v{color:var(--to-lt)} .k-card.ru .v{color:var(--ru)} .k-card.vi .v{color:var(--vi)}
|
||||
.sec{margin:24px 0 14px;padding-bottom:8px;border-bottom:1px dotted var(--line2);display:flex;align-items:baseline;gap:12px}
|
||||
.sec h2{font-family:var(--serif);font-weight:500;font-size:22px;color:var(--paper)}
|
||||
.sec h2 em{color:var(--gold);font-style:italic}
|
||||
.sec .kick{font-family:var(--mono);font-size:10px;color:var(--fog);letter-spacing:.1em;text-transform:uppercase}
|
||||
.sec .badge{margin-left:auto;padding:3px 9px;font-family:var(--mono);font-size:10px;background:var(--ink3);color:var(--gold);border:1px solid var(--line2);border-radius:2px}
|
||||
.grid-cat{display:grid;grid-template-columns:repeat(auto-fill,minmax(330px,1fr));gap:10px;margin-bottom:14px}
|
||||
.pc{padding:10px 12px 10px 13px;background:var(--ink2);border:1px solid var(--line);border-left:2px solid var(--gold);border-radius:2px;transition:all .15s}
|
||||
.pc:hover{border-left-color:var(--gold-br);transform:translateX(3px);background:var(--ink3)}
|
||||
.pc.leg{border-left-color:var(--fog)} .pc.dup{border-left-color:var(--to)} .pc.dep{border-left-color:var(--ru)}
|
||||
.pc a{color:var(--paper);font-family:var(--sans);font-size:12.5px;font-weight:500;text-decoration:none;display:block}
|
||||
.pc a:hover{color:var(--gold)}
|
||||
.pc .m{font-family:var(--mono);font-size:9px;color:var(--fog);margin-top:3px;display:flex;gap:10px}
|
||||
.filter{position:sticky;top:8px;background:var(--ink);padding:10px 0;z-index:10;margin-bottom:14px;display:flex;gap:8px;flex-wrap:wrap;align-items:center}
|
||||
.filter input{flex:1;min-width:200px;padding:8px 12px;background:var(--ink3);border:1px solid var(--line);color:var(--paper);font-family:var(--sans);font-size:12px;border-radius:2px;outline:none}
|
||||
.filter input:focus{border-color:var(--gold)}
|
||||
.filter .tag{padding:5px 10px;font-family:var(--mono);font-size:10px;background:var(--ink3);color:var(--smoke);border:1px solid var(--line);border-radius:2px;cursor:pointer;user-select:none}
|
||||
.filter .tag.on{background:var(--gold);color:var(--ink);border-color:var(--gold)}
|
||||
.cat-colors{display:flex;gap:4px;margin-bottom:14px;flex-wrap:wrap;font-size:10px;font-family:var(--mono)}
|
||||
.cat-colors .c{padding:3px 8px;border-radius:10px}
|
||||
.c-active{background:rgba(212,168,83,.15);color:var(--gold-lt);border:1px solid var(--gold)}
|
||||
.c-legacy{background:rgba(107,116,144,.15);color:var(--smoke);border:1px solid var(--fog)}
|
||||
.c-doublon{background:rgba(251,191,36,.1);color:var(--to-lt);border:1px solid var(--to)}
|
||||
.c-deprecated{background:rgba(239,68,68,.1);color:var(--ru);border:1px solid var(--ru)}
|
||||
.hint{padding:12px 14px;background:var(--ink2);border:1px solid var(--line);border-radius:2px;margin-bottom:14px;font-size:12px;color:var(--smoke);line-height:1.6}
|
||||
.loading{padding:40px 0;text-align:center;color:var(--fog);font-family:var(--serif);font-style:italic}
|
||||
footer{margin-top:40px;padding:14px 0;border-top:1px solid var(--line);text-align:center;color:var(--fog);font-family:var(--serif);font-style:italic;font-size:11.5px}
|
||||
footer a{color:var(--gold);text-decoration:none;margin:0 6px}
|
||||
.scroll-tip{font-size:10px;color:var(--fog);font-family:var(--mono);margin-top:2px}
|
||||
@media(max-width:700px){.hd h1{font-size:24px}.grid-cat{grid-template-columns:1fr}.hd .back{position:static;margin-top:8px;display:inline-block}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header class="hd">
|
||||
<div class="eyebrow">WEVAL · WTP Orphans Registry</div>
|
||||
<h1>Toutes les pages <em>reliées à WTP</em></h1>
|
||||
<p class="sub">Catalogue vivant — 333 pages scannées, catégorisées, actionnables</p>
|
||||
<a href="/weval-technology-platform.html" class="back">← WTP Hub</a>
|
||||
</header>
|
||||
|
||||
<div class="wrap">
|
||||
<div class="kpis" id="kpis"></div>
|
||||
|
||||
<div class="hint">
|
||||
🎯 <strong>Objectif</strong> : rattacher les 261 pages orphelines au référentiel WTP sans doublon ni écrasement.
|
||||
Cliquez une page pour l'ouvrir. Filtrez par catégorie ou nom.
|
||||
Les variantes LEGACY/DOUBLON/DEPRECATED sont archivables (consolidation).
|
||||
</div>
|
||||
|
||||
<div class="cat-colors">
|
||||
<span class="c c-active">● ACTIVE (liens or)</span>
|
||||
<span class="c c-doublon">● DOUBLON (jaune)</span>
|
||||
<span class="c c-legacy">● LEGACY (gris)</span>
|
||||
<span class="c c-deprecated">● DEPRECATED (rouge)</span>
|
||||
</div>
|
||||
|
||||
<div class="filter">
|
||||
<input id="q" type="text" placeholder="Filter by name…" oninput="filterAll()">
|
||||
<span class="tag on" data-cat="ALL" onclick="toggleCat(this)">ALL</span>
|
||||
<span class="tag" data-cat="ACTIVE_HUB" onclick="toggleCat(this)">HUB</span>
|
||||
<span class="tag" data-cat="ACTIVE_DASHBOARD" onclick="toggleCat(this)">DASHBOARD</span>
|
||||
<span class="tag" data-cat="ACTIVE_AGENT" onclick="toggleCat(this)">AGENT</span>
|
||||
<span class="tag" data-cat="ACTIVE_BLADE" onclick="toggleCat(this)">BLADE</span>
|
||||
<span class="tag" data-cat="ACTIVE_AI" onclick="toggleCat(this)">AI</span>
|
||||
<span class="tag" data-cat="ACTIVE_CRM" onclick="toggleCat(this)">CRM</span>
|
||||
<span class="tag" data-cat="ACTIVE_ADMIN" onclick="toggleCat(this)">ADMIN</span>
|
||||
<span class="tag" data-cat="ACTIVE_PRODUCT" onclick="toggleCat(this)">PRODUCT</span>
|
||||
<span class="tag" data-cat="ACTIVE_OTHER" onclick="toggleCat(this)">OTHER</span>
|
||||
<span class="tag" data-cat="DOUBLON" onclick="toggleCat(this)">DOUBLON</span>
|
||||
<span class="tag" data-cat="LEGACY" onclick="toggleCat(this)">LEGACY</span>
|
||||
<span class="tag" data-cat="TESTS" onclick="toggleCat(this)">TESTS</span>
|
||||
</div>
|
||||
|
||||
<div id="content"><div class="loading">⏳ Scanning 333 pages…</div></div>
|
||||
|
||||
<footer>
|
||||
Généré dynamiquement via <a href="/api/wtp-orphans-registry.php">/api/wtp-orphans-registry.php</a> ·
|
||||
<a href="/weval-technology-platform.html">WTP Hub</a> ·
|
||||
<a href="/all-ia-hub.html">All-IA Hub</a> ·
|
||||
<a href="/wevia-master.html">WEVIA Master</a>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let DATA = null, FILTER_CATS = new Set(['ALL']);
|
||||
|
||||
const CAT_LABELS = {
|
||||
ACTIVE_HUB: { label: 'Hubs & Centers', kick: 'Points d\'entrée modulaires', color: 'var(--gold)' },
|
||||
ACTIVE_DASHBOARD: { label: 'Dashboards & KPIs', kick: 'Tableaux de bord business', color: 'var(--em-lt)' },
|
||||
ACTIVE_AGENT: { label: 'Agents', kick: 'Agents IA & assistants', color: 'var(--sa)' },
|
||||
ACTIVE_BLADE: { label: 'Blade Hub', kick: 'Blade AI assistants', color: 'var(--vi)' },
|
||||
ACTIVE_AI: { label: 'AI & LLM', kick: 'IA souveraines & modèles', color: 'var(--pi)' },
|
||||
ACTIVE_CRM: { label: 'CRM & HCP', kick: 'Sales & healthcare', color: 'var(--em-lt)' },
|
||||
ACTIVE_ADMIN: { label: 'Admin & Auth', kick: 'Back-office', color: 'var(--to-lt)' },
|
||||
ACTIVE_PRODUCT: { label: 'Products & Offers', kick: 'Commercial pages', color: 'var(--gold-br)' },
|
||||
ACTIVE_OTHER: { label: 'Autres pages', kick: 'Catégorisation libre', color: 'var(--paper)' },
|
||||
DOUBLON: { label: 'Doublons probables', kick: 'Variantes à consolider', color: 'var(--to)' },
|
||||
LEGACY: { label: 'Legacy', kick: 'Anciennes versions', color: 'var(--fog)' },
|
||||
TESTS: { label: 'Tests & Demos', kick: 'Sandbox', color: 'var(--fog)' },
|
||||
DEPRECATED: { label: 'Deprecated', kick: '404 / offline', color: 'var(--ru)' },
|
||||
};
|
||||
|
||||
async function load() {
|
||||
try {
|
||||
const r = await fetch('/api/wtp-orphans-registry.php');
|
||||
DATA = await r.json();
|
||||
renderKPIs();
|
||||
renderAll();
|
||||
} catch (e) {
|
||||
document.getElementById('content').innerHTML = `<div class="loading">❌ Erreur: ${e.message}</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
function renderKPIs() {
|
||||
const d = DATA;
|
||||
const html = `
|
||||
<div class="k-card"><div class="lbl">Total pages</div><div class="v">${d.total_html}</div><div class="d">scannées racine</div></div>
|
||||
<div class="k-card em"><div class="lbl">Linkées WTP</div><div class="v">${d.linked_in_wtp}</div><div class="d">${d.link_rate_pct}% couverture</div></div>
|
||||
<div class="k-card wa"><div class="lbl">Orphelines</div><div class="v">${d.orphans_count}</div><div class="d">à rattacher</div></div>
|
||||
<div class="k-card"><div class="lbl">Hubs actifs</div><div class="v">${d.counts.ACTIVE_HUB}</div><div class="d">+ ${d.counts.ACTIVE_DASHBOARD} dashboards</div></div>
|
||||
<div class="k-card vi"><div class="lbl">À consolider</div><div class="v">${d.counts.DOUBLON + d.counts.LEGACY + d.counts.TESTS + d.counts.DEPRECATED}</div><div class="d">doublons/legacy</div></div>
|
||||
<div class="k-card"><div class="lbl">Scan</div><div class="v" style="font-size:20px">${d.scan_duration_ms}ms</div><div class="d">live dynamique</div></div>
|
||||
`;
|
||||
document.getElementById('kpis').innerHTML = html;
|
||||
}
|
||||
|
||||
function renderAll() {
|
||||
const d = DATA;
|
||||
const q = (document.getElementById('q').value || '').toLowerCase();
|
||||
let html = '';
|
||||
|
||||
const order = ['ACTIVE_HUB','ACTIVE_DASHBOARD','ACTIVE_AGENT','ACTIVE_BLADE','ACTIVE_AI','ACTIVE_CRM','ACTIVE_ADMIN','ACTIVE_PRODUCT','ACTIVE_OTHER','DOUBLON','LEGACY','TESTS','DEPRECATED'];
|
||||
|
||||
for (const cat of order) {
|
||||
if (!FILTER_CATS.has('ALL') && !FILTER_CATS.has(cat)) continue;
|
||||
const items = d.categories[cat] || [];
|
||||
const filtered = q ? items.filter(i => i.name.toLowerCase().includes(q)) : items;
|
||||
if (!filtered.length) continue;
|
||||
|
||||
const meta = CAT_LABELS[cat] || { label: cat, kick: '', color: 'var(--gold)' };
|
||||
html += `<div class="sec"><h2>${meta.label} <em>${cat.split('_')[1]?.toLowerCase() || ''}</em></h2><span class="kick">${meta.kick}</span><span class="badge">${filtered.length}</span></div>`;
|
||||
html += `<div class="grid-cat">`;
|
||||
|
||||
const pcClass = cat === 'LEGACY' ? 'pc leg' : cat === 'DOUBLON' ? 'pc dup' : cat === 'DEPRECATED' ? 'pc dep' : 'pc';
|
||||
for (const item of filtered) {
|
||||
const sizeKB = (item.size / 1024).toFixed(0);
|
||||
html += `<div class="${pcClass}"><a href="/${item.name}" target="_blank">${item.name}</a><div class="m"><span>${sizeKB} KB</span><span>${item.mtime_h || '?'}</span></div></div>`;
|
||||
}
|
||||
html += `</div>`;
|
||||
}
|
||||
|
||||
document.getElementById('content').innerHTML = html || `<div class="loading">Aucune page trouvée pour ces filtres</div>`;
|
||||
}
|
||||
|
||||
function toggleCat(el) {
|
||||
const cat = el.dataset.cat;
|
||||
document.querySelectorAll('.tag').forEach(t => t.classList.remove('on'));
|
||||
FILTER_CATS = new Set([cat]);
|
||||
el.classList.add('on');
|
||||
renderAll();
|
||||
}
|
||||
|
||||
function filterAll() { renderAll(); }
|
||||
|
||||
load();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
/*
|
||||
WTP Orphans Registry · Opus 23avr2026 22h
|
||||
Doctrine 144 · Point d'entrée unique WTP sans écrasement
|
||||
|
||||
Génère JSON live des 333 pages catégorisées pour widget WTP
|
||||
Zéro hardcode, scan dynamique à chaque appel
|
||||
*/
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
header('Cache-Control: public, max-age=300'); // 5min cache
|
||||
|
||||
$root = '/var/www/html';
|
||||
$wtp_file = $root . '/weval-technology-platform.html';
|
||||
|
||||
// 1. Scan toutes pages .html racine
|
||||
$all_pages = glob($root . '/*.html');
|
||||
$all_names = array_map('basename', $all_pages);
|
||||
sort($all_names);
|
||||
|
||||
// 2. Pages linkées dans WTP
|
||||
$linked = [];
|
||||
if (file_exists($wtp_file)) {
|
||||
$wtp_content = file_get_contents($wtp_file);
|
||||
preg_match_all('/href="\/?([a-z0-9_-]+\.html)"/i', $wtp_content, $m);
|
||||
$linked = array_unique($m[1]);
|
||||
}
|
||||
sort($linked);
|
||||
|
||||
// 3. Orphans
|
||||
$orphans = array_diff($all_names, $linked, ['weval-technology-platform.html']);
|
||||
$orphans = array_values($orphans);
|
||||
|
||||
// 4. Categorize
|
||||
$cats = [
|
||||
'LEGACY'=>[], 'DOUBLON'=>[], 'TESTS'=>[], 'DEPRECATED'=>[],
|
||||
'ACTIVE_HUB'=>[], 'ACTIVE_AGENT'=>[], 'ACTIVE_BLADE'=>[], 'ACTIVE_AI'=>[],
|
||||
'ACTIVE_CRM'=>[], 'ACTIVE_ADMIN'=>[], 'ACTIVE_DASHBOARD'=>[],
|
||||
'ACTIVE_PRODUCT'=>[], 'ACTIVE_OTHER'=>[],
|
||||
];
|
||||
|
||||
foreach ($orphans as $p) {
|
||||
$n = strtolower($p);
|
||||
$stats = @stat("$root/$p");
|
||||
$item = [
|
||||
'name' => $p,
|
||||
'size' => $stats['size'] ?? 0,
|
||||
'mtime' => $stats['mtime'] ?? 0,
|
||||
'mtime_h' => $stats['mtime'] ? date('Y-m-d', $stats['mtime']) : '',
|
||||
];
|
||||
|
||||
if (in_array($p, ['404.html','offline.html','error.html'])) $cats['DEPRECATED'][] = $item;
|
||||
elseif (preg_match('/-old|-backup|-v1\.|-legacy|-deprecated/', $n)) $cats['LEGACY'][] = $item;
|
||||
elseif (preg_match('/^test-|-test\.|^demo-|-demo\.|sandbox/', $n)) $cats['TESTS'][] = $item;
|
||||
elseif (preg_match('/-alive|-hd\d*\.|-goodjob|-fleet|-final|-3d|-iso3d/', $n)) $cats['DOUBLON'][] = $item;
|
||||
elseif (strpos($n, '-hub') !== false || strpos($n, '-center') !== false || strpos($n, '-registry') !== false) $cats['ACTIVE_HUB'][] = $item;
|
||||
elseif (strpos($n, 'agents-') === 0 || strpos($n, 'agent-') === 0) $cats['ACTIVE_AGENT'][] = $item;
|
||||
elseif (strpos($n, 'blade-') === 0) $cats['ACTIVE_BLADE'][] = $item;
|
||||
elseif (preg_match('/^(ai|ia)-|ollama|llm/', $n)) $cats['ACTIVE_AI'][] = $item;
|
||||
elseif (strpos($n, 'crm') !== false || strpos($n, 'hcp') !== false) $cats['ACTIVE_CRM'][] = $item;
|
||||
elseif (strpos($n, 'admin') !== false || strpos($n, 'login') !== false) $cats['ACTIVE_ADMIN'][] = $item;
|
||||
elseif (strpos($n, 'dashboard') !== false || strpos($n, 'kpi') !== false || strpos($n, 'metric') !== false) $cats['ACTIVE_DASHBOARD'][] = $item;
|
||||
elseif (strpos($n, 'product') !== false || strpos($n, 'offer') !== false || strpos($n, 'pricing') !== false) $cats['ACTIVE_PRODUCT'][] = $item;
|
||||
else $cats['ACTIVE_OTHER'][] = $item;
|
||||
}
|
||||
|
||||
// Sort each category by mtime desc (recent first)
|
||||
foreach ($cats as $k => $v) {
|
||||
usort($cats[$k], fn($a,$b) => $b['mtime'] - $a['mtime']);
|
||||
}
|
||||
|
||||
// Variant detection for duplicates
|
||||
$variants = [];
|
||||
foreach ($orphans as $p) {
|
||||
$base = str_replace('.html','',$p);
|
||||
if (preg_match('/^(.+?)(-v\d+|-hd\d*|-final|-alive|-old|-backup|-new|-2|-3)$/', $base, $m)) {
|
||||
$variants[$m[1]][] = $p;
|
||||
}
|
||||
}
|
||||
$variant_groups = array_filter($variants, fn($v) => count($v) > 1);
|
||||
|
||||
echo json_encode([
|
||||
'ok' => true,
|
||||
'ts' => date('c'),
|
||||
'total_html' => count($all_names),
|
||||
'linked_in_wtp' => count($linked),
|
||||
'orphans_count' => count($orphans),
|
||||
'link_rate_pct' => round(count($linked) / max(count($all_names), 1) * 100, 1),
|
||||
'categories' => $cats,
|
||||
'counts' => array_map('count', $cats),
|
||||
'variant_groups' => $variant_groups,
|
||||
'scan_duration_ms' => (int)((microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']) * 1000)
|
||||
], JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
|
||||
91
wiki/doctrine-144-wtp-orphans-registry.md
Normal file
91
wiki/doctrine-144-wtp-orphans-registry.md
Normal file
@@ -0,0 +1,91 @@
|
||||
# Doctrine 144 · WTP Orphans Registry · rattacher 261 pages à la source de vérité
|
||||
|
||||
Créée 23avr2026 22h par Opus suite directive Yacine :
|
||||
"IL FAUT RELIER TOUTE LES PAGE MODULES FONCTION DE LARCHI PAS DORPHELLIN...
|
||||
WEVALTECKCNOLGY PLATFOM POINT DENTREE DE TOUT ARCHI"
|
||||
|
||||
## Constat initial
|
||||
|
||||
Audit exhaustif au 23avr2026 21h58 :
|
||||
|
||||
- **333 pages .html** à la racine `/var/www/html/`
|
||||
- **72 pages linkées dans WTP** (`weval-technology-platform.html`)
|
||||
- **261 pages ORPHELINES** (78% — aucun lien depuis WTP)
|
||||
- Link rate = 21.6% (loin du 100% cible ERP)
|
||||
|
||||
## Solution zéro écrasement
|
||||
|
||||
**Ne pas modifier WTP directement** (5350L, 368KB, risque régression haut).
|
||||
|
||||
Créer :
|
||||
1. **Endpoint API `/api/wtp-orphans-registry.php`** (PHP 80L)
|
||||
- Scan dynamique des pages racine
|
||||
- Catégorisation automatique (13 catégories)
|
||||
- Détection variantes/doublons (regex `-v\d+`, `-hd`, `-final`, `-alive`...)
|
||||
- Retourne JSON live avec mtime + size + counts
|
||||
- Scan duration typique : 6-10ms
|
||||
|
||||
2. **Page standalone `/wtp-orphans-registry.html`** (201L, 14KB)
|
||||
- UX premium éditorial Fraunces serif + Inter + JetBrains Mono
|
||||
- Palette gold/ink deep navy cohérente WEVAL
|
||||
- 6 KPI cards : total/linkées/orphelines/hubs/consolidation/scan duration
|
||||
- Filter tags cliquables (ALL + 12 catégories)
|
||||
- Search input live
|
||||
- 262 page cards avec nom + size + date, cliquables
|
||||
- Lien back vers WTP (pas de chevauchement avec Logout SSO)
|
||||
- Zéro JS errors (testé Playwright)
|
||||
|
||||
## Catégorisation automatique
|
||||
|
||||
| Catégorie | Count | Usage |
|
||||
|---|---|---|
|
||||
| ACTIVE_HUB | 36 | Points d'entrée modulaires (-hub, -center, -registry) |
|
||||
| ACTIVE_DASHBOARD | 21 | Tableaux de bord KPI/metric |
|
||||
| ACTIVE_ADMIN | 10 | Back-office (admin, login) |
|
||||
| ACTIVE_CRM | 4 | Sales healthcare (crm, hcp) |
|
||||
| ACTIVE_BLADE | 4 | Blade AI assistants |
|
||||
| ACTIVE_AGENT | 2 | Agents IA |
|
||||
| ACTIVE_AI | 2 | IA/LLM souveraines |
|
||||
| ACTIVE_PRODUCT | 1 | Commercial |
|
||||
| ACTIVE_OTHER | 165 | Divers (à affiner en sous-catégories) |
|
||||
| **Total ACTIVE** | **244** | **À rattacher à WTP** |
|
||||
| DOUBLON | 8 | Variantes à consolider (-hd, -final, -alive) |
|
||||
| LEGACY | 4 | Versions anciennes |
|
||||
| TESTS | 4 | Sandbox/demos |
|
||||
| DEPRECATED | 1 | 404, offline |
|
||||
| **Total ARCHIVABLE** | **17** | **Consolidation** |
|
||||
|
||||
## Validation Playwright
|
||||
|
||||
Script `/opt/weval-nonreg/pw-wtp-registry.js` :
|
||||
|
||||
```
|
||||
title: "WTP Orphans Registry · 261 pages à relier"
|
||||
kpis_count: 6
|
||||
sections_count: 13
|
||||
pagecards: 262
|
||||
filter_tags: 13
|
||||
has_search: true
|
||||
body_height: 7963
|
||||
js_errors: []
|
||||
```
|
||||
|
||||
Preuves publiques : `weval-consulting.com/proofs/wtp-orphans-registry-<TS>/`
|
||||
5 screenshots + 1 vidéo webm
|
||||
|
||||
## Prochain objectif (si Yacine autorise)
|
||||
|
||||
Ajouter **1 seule ligne** dans WTP qui link `/wtp-orphans-registry.html` :
|
||||
- Pattern : chercher la nav principale de WTP et ajouter un item "Registry"
|
||||
- Validation nginx -t + NR 153/153 avant/après
|
||||
- GOLD backup obligatoire
|
||||
- Sous autorisation explicite uniquement (doctrine zéro écrasement)
|
||||
|
||||
## Doctrine chaînée
|
||||
|
||||
- 136 · Référentiel unique (principe)
|
||||
- 141 · Mémoire persistante universelle
|
||||
- 142 · Pattern shutdown_function chatbots
|
||||
- 143 · Cloudbot-social SSE (autre Claude)
|
||||
- **144 · WTP Orphans Registry** ← CE DOC
|
||||
- 145 futur · Merger WTP + registry en vue unifiée dashboard ERP-like
|
||||
Reference in New Issue
Block a user