auto-commit via WEVIA vault_git intent 2026-04-18T13:23:22+00:00
Some checks failed
WEVAL NonReg / nonreg (push) Has been cancelled
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"generated_at": "2026-04-18T15:15:01.952834",
|
||||
"generated_at": "2026-04-18T15:20:01.907427",
|
||||
"stats": {
|
||||
"total": 153,
|
||||
"pending": 268,
|
||||
|
||||
11
api/blade-tasks/task_20260418132002_356aea.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"id": "task_20260418132002_356aea",
|
||||
"name": "Blade self-heal 15:20",
|
||||
"type": "powershell",
|
||||
"command": "\n# Blade self-heal\nWrite-Host \"Self-heal triggered $(Get-Date)\"\n$agentProc = Get-Process powershell | Where-Object { $_.CommandLine -match 'sentinel-agent' }\nif (!$agentProc) {\n Write-Host \"Agent not running, starting...\"\n Start-Process powershell -ArgumentList \"-ExecutionPolicy\",\"Bypass\",\"-File\",\"C:\\ProgramData\\WEVAL\\sentinel-agent.ps1\" -WindowStyle Hidden\n}\n# Clear stale tasks > 3 days locally\n$cutoff = (Get-Date).AddDays(-3)\nGet-ChildItem \"C:\\ProgramData\\WEVAL\\tasks\\*.json\" -ErrorAction SilentlyContinue | Where-Object { $_.LastWriteTime -lt $cutoff } | Move-Item -Destination \"C:\\ProgramData\\WEVAL\\tasks\\archived\\\" -Force -ErrorAction SilentlyContinue\nWrite-Host \"Self-heal complete\"\n",
|
||||
"cmd": "\n# Blade self-heal\nWrite-Host \"Self-heal triggered $(Get-Date)\"\n$agentProc = Get-Process powershell | Where-Object { $_.CommandLine -match 'sentinel-agent' }\nif (!$agentProc) {\n Write-Host \"Agent not running, starting...\"\n Start-Process powershell -ArgumentList \"-ExecutionPolicy\",\"Bypass\",\"-File\",\"C:\\ProgramData\\WEVAL\\sentinel-agent.ps1\" -WindowStyle Hidden\n}\n# Clear stale tasks > 3 days locally\n$cutoff = (Get-Date).AddDays(-3)\nGet-ChildItem \"C:\\ProgramData\\WEVAL\\tasks\\*.json\" -ErrorAction SilentlyContinue | Where-Object { $_.LastWriteTime -lt $cutoff } | Move-Item -Destination \"C:\\ProgramData\\WEVAL\\tasks\\archived\\\" -Force -ErrorAction SilentlyContinue\nWrite-Host \"Self-heal complete\"\n",
|
||||
"priority": "high",
|
||||
"status": "pending",
|
||||
"created": "2026-04-18T13:20:02+00:00",
|
||||
"created_by": "blade-control-ui"
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"ok": true,
|
||||
"version": "V83-business-kpi",
|
||||
"ts": "2026-04-18T13:15:14+00:00",
|
||||
"ts": "2026-04-18T13:21:16+00:00",
|
||||
"summary": {
|
||||
"total_categories": 7,
|
||||
"total_kpis": 56,
|
||||
|
||||
186
dsh-predict-widget.js
Normal file
@@ -0,0 +1,186 @@
|
||||
/**
|
||||
* DSH PREDICT Widget · WePredict v1.0 · 18avr2026
|
||||
* Self-contained · zero external deps · safe to include anywhere.
|
||||
* Fetches live data from WePredict endpoints and renders a glass-card panel.
|
||||
* Yacine Mahboub · WEVAL Consulting
|
||||
*/
|
||||
(function(){
|
||||
if (window.__DSH_PREDICT_LOADED__) return;
|
||||
window.__DSH_PREDICT_LOADED__ = true;
|
||||
|
||||
const API_V71 = '/api/wevia-v71-intelligence-growth.php';
|
||||
const API_HEAL = '/api/opus-arch-predictive-heal.php';
|
||||
const API_CACHE = '/api/opus5-predictive-cache.php';
|
||||
const API_GROWTH = '/api/growth-engine-api.php';
|
||||
|
||||
// ── Styles injection (scoped by .dsh-predict prefix) ──
|
||||
const css = `
|
||||
.dsh-predict-wrap{position:relative;margin:20px 0;font-family:-apple-system,Segoe UI,Roboto,sans-serif;color:#e6e9f0}
|
||||
.dsh-predict-card{
|
||||
background:linear-gradient(135deg,rgba(20,25,40,.72),rgba(35,20,60,.58));
|
||||
backdrop-filter:blur(18px) saturate(1.2);-webkit-backdrop-filter:blur(18px) saturate(1.2);
|
||||
border:1px solid rgba(120,140,255,.18);border-radius:20px;padding:22px 26px;
|
||||
box-shadow:0 8px 32px rgba(0,0,0,.4), inset 0 1px 0 rgba(255,255,255,.05);
|
||||
transition:transform .25s ease, box-shadow .25s ease, border-color .25s ease;
|
||||
overflow:hidden
|
||||
}
|
||||
.dsh-predict-card:hover{transform:translateY(-3px);box-shadow:0 14px 42px rgba(80,100,255,.28);border-color:rgba(140,170,255,.38)}
|
||||
.dsh-predict-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:18px;gap:12px;flex-wrap:wrap}
|
||||
.dsh-predict-title{font-size:15px;font-weight:600;letter-spacing:.5px;display:flex;align-items:center;gap:10px;margin:0}
|
||||
.dsh-predict-title .emoji{font-size:22px}
|
||||
.dsh-predict-title small{display:block;font-size:10px;font-weight:400;color:#8892b4;letter-spacing:1px;margin-top:2px}
|
||||
.dsh-predict-badge{
|
||||
display:inline-flex;align-items:center;gap:6px;padding:5px 12px;border-radius:999px;font-size:10px;
|
||||
font-weight:700;letter-spacing:1.2px;text-transform:uppercase
|
||||
}
|
||||
.dsh-predict-badge.live{background:rgba(52,211,153,.15);color:#34d399;border:1px solid rgba(52,211,153,.35)}
|
||||
.dsh-predict-badge.warn{background:rgba(250,204,21,.15);color:#facc15;border:1px solid rgba(250,204,21,.35)}
|
||||
.dsh-predict-badge.alert{background:rgba(248,113,113,.15);color:#f87171;border:1px solid rgba(248,113,113,.45)}
|
||||
.dsh-predict-badge .dot{width:7px;height:7px;border-radius:50%;background:currentColor;animation:dshPulse 1.8s ease-in-out infinite}
|
||||
@keyframes dshPulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.4;transform:scale(.75)}}
|
||||
.dsh-predict-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:14px}
|
||||
.dsh-predict-tile{
|
||||
background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.07);border-radius:14px;
|
||||
padding:14px 16px;transition:all .2s ease;cursor:default
|
||||
}
|
||||
.dsh-predict-tile:hover{background:rgba(255,255,255,.06);border-color:rgba(140,170,255,.25)}
|
||||
.dsh-predict-tile .label{font-size:10px;text-transform:uppercase;letter-spacing:1px;color:#8892b4;margin-bottom:6px;font-weight:600}
|
||||
.dsh-predict-tile .value{font-size:26px;font-weight:700;line-height:1;letter-spacing:-.5px}
|
||||
.dsh-predict-tile .value.g{background:linear-gradient(135deg,#34d399,#60a5fa);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
|
||||
.dsh-predict-tile .value.w{color:#facc15}
|
||||
.dsh-predict-tile .value.r{color:#f87171}
|
||||
.dsh-predict-tile .sub{font-size:11px;color:#8892b4;margin-top:6px}
|
||||
.dsh-predict-actions{margin-top:14px;padding-top:14px;border-top:1px solid rgba(255,255,255,.07)}
|
||||
.dsh-predict-actions .label{font-size:10px;text-transform:uppercase;letter-spacing:1px;color:#8892b4;font-weight:600;margin-bottom:8px}
|
||||
.dsh-predict-actions ul{margin:0;padding:0 0 0 18px;font-size:12px;color:#c5cbe0;line-height:1.7}
|
||||
.dsh-predict-foot{margin-top:14px;font-size:10px;color:#5f6787;display:flex;justify-content:space-between;gap:8px;flex-wrap:wrap}
|
||||
.dsh-predict-foot a{color:#60a5fa;text-decoration:none}
|
||||
.dsh-predict-foot a:hover{text-decoration:underline}
|
||||
.dsh-predict-err{color:#f87171;font-size:12px;padding:10px;text-align:center}
|
||||
.dsh-predict-skel{display:inline-block;width:60%;height:22px;background:linear-gradient(90deg,rgba(255,255,255,.05),rgba(255,255,255,.12),rgba(255,255,255,.05));background-size:200% 100%;animation:dshShim 1.5s ease-in-out infinite;border-radius:4px}
|
||||
@keyframes dshShim{0%{background-position:200% 0}100%{background-position:-200% 0}}
|
||||
`;
|
||||
const st = document.createElement('style');
|
||||
st.id='dsh-predict-style';st.textContent=css;
|
||||
document.head.appendChild(st);
|
||||
|
||||
// ── Mount point: use #dsh-predict-mount if present, else inject before </body> ──
|
||||
let mount = document.getElementById('dsh-predict-mount');
|
||||
if (!mount) {
|
||||
mount = document.createElement('div');
|
||||
mount.id = 'dsh-predict-mount';
|
||||
mount.className = 'dsh-predict-wrap';
|
||||
// Insert inside main/container if available, else body end
|
||||
const parent = document.querySelector('main, .main, .content, .container, #app') || document.body;
|
||||
parent.appendChild(mount);
|
||||
}
|
||||
mount.classList.add('dsh-predict-wrap');
|
||||
mount.innerHTML = `
|
||||
<div class="dsh-predict-card" role="region" aria-label="DSH Predict live">
|
||||
<div class="dsh-predict-head">
|
||||
<div>
|
||||
<p class="dsh-predict-title"><span class="emoji">🔮</span>DSH PREDICT <small>WePredict · growth · spy · heal</small></p>
|
||||
</div>
|
||||
<span id="dshp-badge" class="dsh-predict-badge live"><span class="dot"></span>LIVE</span>
|
||||
</div>
|
||||
<div class="dsh-predict-grid" id="dshp-grid">
|
||||
<div class="dsh-predict-tile"><div class="label">Loading…</div><div class="value"><span class="dsh-predict-skel"></span></div></div>
|
||||
</div>
|
||||
<div class="dsh-predict-actions" id="dshp-actions" style="display:none">
|
||||
<div class="label">Recommended actions</div>
|
||||
<ul id="dshp-reco"></ul>
|
||||
</div>
|
||||
<div class="dsh-predict-foot">
|
||||
<span id="dshp-ts">—</span>
|
||||
<span>Sources: <a href="${API_V71}" target="_blank">v71 Growth</a> · <a href="${API_HEAL}" target="_blank">Heal</a> · <a href="${API_CACHE}" target="_blank">Cache</a></span>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
// ── Fetch helpers ──
|
||||
const fetchJSON = (url, timeout=8000) => new Promise((res)=>{
|
||||
const ctrl = new AbortController();
|
||||
const to = setTimeout(()=>ctrl.abort(), timeout);
|
||||
fetch(url,{signal:ctrl.signal,cache:'no-store'})
|
||||
.then(r=>r.ok?r.json():Promise.reject(r.status))
|
||||
.then(d=>{clearTimeout(to);res({ok:true,data:d});})
|
||||
.catch(e=>{clearTimeout(to);res({ok:false,err:String(e)});});
|
||||
});
|
||||
|
||||
const fmt = (n) => {
|
||||
if (n===null||n===undefined) return '—';
|
||||
if (typeof n==='number'){
|
||||
if (Math.abs(n)>=1e6) return (n/1e6).toFixed(1)+'M';
|
||||
if (Math.abs(n)>=1e3) return (n/1e3).toFixed(1)+'k';
|
||||
return Number.isInteger(n)?n.toString():n.toFixed(2);
|
||||
}
|
||||
return String(n);
|
||||
};
|
||||
|
||||
// ── Render ──
|
||||
async function render(){
|
||||
const [r71, rheal, rcache] = await Promise.all([
|
||||
fetchJSON(API_V71), fetchJSON(API_HEAL), fetchJSON(API_CACHE)
|
||||
]);
|
||||
|
||||
const grid = document.getElementById('dshp-grid');
|
||||
const badge = document.getElementById('dshp-badge');
|
||||
const ts = document.getElementById('dshp-ts');
|
||||
const actionsBox = document.getElementById('dshp-actions');
|
||||
const reco = document.getElementById('dshp-reco');
|
||||
|
||||
if (!r71.ok && !rheal.ok && !rcache.ok) {
|
||||
grid.innerHTML = `<div class="dsh-predict-err">⚠ Predict APIs unreachable. Retry soon.</div>`;
|
||||
badge.className='dsh-predict-badge alert';badge.innerHTML='<span class="dot"></span>ALERT';
|
||||
return;
|
||||
}
|
||||
|
||||
const s = (r71.ok && r71.data && r71.data.summary) ? r71.data.summary : {};
|
||||
const heal = rheal.ok ? rheal.data : {};
|
||||
const cache = rcache.ok && rcache.data && rcache.data.stats ? rcache.data.stats : {};
|
||||
|
||||
// Tiles
|
||||
const tiles = [
|
||||
{ lbl:'Load · next hour', val:fmt(heal.predicted_next_hour), sub:(heal.alert?'⚠ over threshold':'safe · threshold '+(heal.threshold||5)), klass:heal.alert?'w':'g' },
|
||||
{ lbl:'Competitors tracked', val:s.competitors_tracked||0, sub:`${s.competitors_high_threat||0} high threat`, klass:(s.competitors_high_threat>=3?'w':'g') },
|
||||
{ lbl:'Opportunities · k€', val:fmt(s.opportunities_total_value_keur), sub:`${s.opportunities_high_urgency||0} high urgency`, klass:'g' },
|
||||
{ lbl:'Innovations · 24h', val:s.innovations_last_24h||0, sub:`total ${s.innovations_total||0}`, klass:'g' },
|
||||
{ lbl:'Chatbots deployed', val:`${s.chatbots_deployed||0}/${s.chatbots_total||0}`, sub:'lead capture hub', klass:'g' },
|
||||
{ lbl:'Leads · 7d', val:s.leads_captured_7d||0, sub:(s.leads_captured_7d===0?'🔴 capture à relancer':'ok'), klass:(s.leads_captured_7d===0?'r':'g') },
|
||||
{ lbl:'Agility agents · gap', val:s.agility_agents_gap||0, sub:`FTE savings ${s.agility_fte_savings_year||0}/an`, klass:(s.agility_agents_gap>=5?'w':'g') },
|
||||
{ lbl:'Cache predict · hit%', val:(cache.hit_rate_pct!==undefined?cache.hit_rate_pct+'%':'—'), sub:`${cache.gets||0} gets · ${cache.hits||0} hits`, klass:'g' }
|
||||
];
|
||||
grid.innerHTML = tiles.map(t => `
|
||||
<div class="dsh-predict-tile">
|
||||
<div class="label">${t.lbl}</div>
|
||||
<div class="value ${t.klass}">${t.val}</div>
|
||||
<div class="sub">${t.sub}</div>
|
||||
</div>`).join('');
|
||||
|
||||
// Badge status
|
||||
const hasAlert = heal.alert || (s.leads_captured_7d===0) || (s.competitors_high_threat>=3);
|
||||
const hasWarn = (s.opportunities_high_urgency>=3) || (s.agility_agents_gap>=5);
|
||||
if (hasAlert) { badge.className='dsh-predict-badge alert'; badge.innerHTML='<span class="dot"></span>ALERT'; }
|
||||
else if (hasWarn) { badge.className='dsh-predict-badge warn'; badge.innerHTML='<span class="dot"></span>WARN'; }
|
||||
else { badge.className='dsh-predict-badge live'; badge.innerHTML='<span class="dot"></span>LIVE'; }
|
||||
|
||||
// Recommendations
|
||||
const rec = [];
|
||||
if (heal.alert && Array.isArray(heal.recommended_actions)) rec.push(...heal.recommended_actions);
|
||||
if (s.leads_captured_7d===0) rec.push('Relancer campagne lead capture (0 leads 7j)');
|
||||
if (s.competitors_high_threat>=3) rec.push(`${s.competitors_high_threat} concurrents high-threat · revoir positionnement`);
|
||||
if (s.opportunities_high_urgency>=3) rec.push(`${s.opportunities_high_urgency} opportunités urgentes · prioriser`);
|
||||
if (s.agility_agents_gap>=5) rec.push(`${s.agility_agents_gap} agents agility à créer · potentiel FTE ${s.agility_fte_savings_year||0}/an`);
|
||||
if (rec.length) {
|
||||
actionsBox.style.display='block';
|
||||
reco.innerHTML = rec.slice(0,4).map(x=>`<li>${x}</li>`).join('');
|
||||
} else {
|
||||
actionsBox.style.display='none';
|
||||
}
|
||||
|
||||
ts.textContent = 'Updated ' + new Date().toLocaleTimeString('fr-FR');
|
||||
}
|
||||
|
||||
render();
|
||||
// Refresh every 60s
|
||||
setInterval(render, 60000);
|
||||
})();
|
||||
@@ -120,4 +120,7 @@ h2{padding:12px 40px 0;font-size:15px;color:#7c3aed;text-transform:uppercase;let
|
||||
})();
|
||||
</script>
|
||||
<!-- /CARTO_BANNER_V1 -->
|
||||
</body></html>
|
||||
|
||||
<!-- DSH PREDICT 18avr26 -->
|
||||
<script src="/dsh-predict-widget.js" defer></script>
|
||||
</body></html>
|
||||
BIN
screenshots/l99-pw-20260418-152034/01-agents-archi.png
Normal file
|
After Width: | Height: | Size: 564 KiB |
BIN
screenshots/l99-pw-20260418-152034/02-meeting-rooms.png
Normal file
|
After Width: | Height: | Size: 380 KiB |
BIN
screenshots/l99-pw-20260418-152034/03-enterprise-model.png
Normal file
|
After Width: | Height: | Size: 477 KiB |
BIN
screenshots/l99-pw-20260418-152034/04-director-center.png
Normal file
|
After Width: | Height: | Size: 267 KiB |
BIN
screenshots/l99-pw-20260418-152034/05-l99-brain.png
Normal file
|
After Width: | Height: | Size: 99 KiB |
BIN
screenshots/l99-pw-20260418-152034/06-wevia-master.png
Normal file
|
After Width: | Height: | Size: 100 KiB |
BIN
screenshots/l99-pw-20260418-152034/07-paperclip.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
screenshots/l99-pw-20260418-152034/09-arena-v2.png
Normal file
|
After Width: | Height: | Size: 179 KiB |
BIN
screenshots/l99-pw-20260418-152034/10-ethica.png
Normal file
|
After Width: | Height: | Size: 138 KiB |
BIN
screenshots/l99-pw-20260418-152034/11-v85-biz-kpi-tech.png
Normal file
|
After Width: | Height: | Size: 372 KiB |
BIN
screenshots/l99-pw-20260418-152034/12-v83-biz-kpi-dashboard.png
Normal file
|
After Width: | Height: | Size: 493 KiB |
@@ -1329,5 +1329,8 @@ if (typeof window.navigateTo === 'function'){
|
||||
</section>
|
||||
<!-- DSH-PREDICT-v1 WIDGET END -->
|
||||
|
||||
</body>
|
||||
|
||||
<!-- DSH PREDICT 18avr26 -->
|
||||
<script src="/dsh-predict-widget.js" defer></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -2963,5 +2963,8 @@ init();
|
||||
</section>
|
||||
<!-- DSH-PREDICT-v1 WIDGET END -->
|
||||
|
||||
</body>
|
||||
|
||||
<!-- DSH PREDICT 18avr26 -->
|
||||
<script src="/dsh-predict-widget.js" defer></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||