Compare commits
471 Commits
v7.5-push-
...
v9.27-git-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
64f2066dde | ||
|
|
bdea8c49da | ||
|
|
6ba5df547f | ||
|
|
8c9771ab70 | ||
|
|
176d2419f4 | ||
|
|
f94eec5dcb | ||
|
|
f873982bba | ||
|
|
147e87b5fb | ||
|
|
27b0d7b933 | ||
|
|
86b8cf4942 | ||
|
|
dd878e0945 | ||
|
|
e719905c8d | ||
|
|
339be12352 | ||
|
|
d223cc7999 | ||
|
|
de4f75a22a | ||
|
|
8eba20a371 | ||
|
|
56542bd6c3 | ||
|
|
b45e2063c7 | ||
|
|
9cad3b6178 | ||
|
|
a53156f12f | ||
|
|
0e0da11b91 | ||
|
|
a82cf8af19 | ||
|
|
39933854e9 | ||
|
|
f9958e2f13 | ||
|
|
755bd0e7e4 | ||
|
|
f101d11633 | ||
|
|
5bbb99fc92 | ||
|
|
593331b038 | ||
|
|
af2edfe798 | ||
|
|
dd68512d96 | ||
|
|
1f56e5f27a | ||
|
|
f0e806aee9 | ||
|
|
963abb58c3 | ||
|
|
4ef21b0b9a | ||
|
|
143c247760 | ||
|
|
ba19c98dff | ||
|
|
82a26f5df6 | ||
|
|
36af5b2c1a | ||
|
|
2ba81195f3 | ||
|
|
85cd46ea36 | ||
|
|
b296ca741f | ||
|
|
e30ddf5007 | ||
|
|
21a0f49cf2 | ||
|
|
24f130416c | ||
|
|
87284726e3 | ||
|
|
593e9f449e | ||
|
|
09b2a2ec13 | ||
|
|
636fc44785 | ||
|
|
755e8be86d | ||
|
|
0413f2365a | ||
|
|
4e8c5b289a | ||
|
|
534714f99b | ||
|
|
446cfd2284 | ||
|
|
6ea6d5301a | ||
|
|
b23423b4f8 | ||
|
|
4bf9ff5817 | ||
|
|
3e57785d15 | ||
|
|
2f9f71132c | ||
|
|
232041b834 | ||
|
|
a866649b8a | ||
|
|
61b573b0ab | ||
|
|
6b83be059a | ||
|
|
5fec800170 | ||
|
|
baf8b518e0 | ||
|
|
0b3d052b91 | ||
|
|
f409282c5c | ||
|
|
6c098aea71 | ||
|
|
349818a9c6 | ||
|
|
ea4f3e70b5 | ||
|
|
2a9a9f7ee3 | ||
|
|
d027afb96e | ||
|
|
3ee938a8e1 | ||
|
|
74c6a01a5c | ||
|
|
893c9a4a2c | ||
|
|
8943b00467 | ||
|
|
94fbb07b9c | ||
|
|
85ed944254 | ||
|
|
49e1f28dea | ||
|
|
6a1b505013 | ||
|
|
a552f16190 | ||
|
|
0135eadd73 | ||
|
|
226f1e5886 | ||
|
|
99b5f71086 | ||
|
|
2e5fc68f77 | ||
|
|
21f2766c97 | ||
|
|
94c0a964c4 | ||
|
|
28b6a206ce | ||
|
|
a6ee5e570f | ||
|
|
b33a4cbc16 | ||
|
|
7d241f9fb0 | ||
|
|
07987edf8c | ||
|
|
8bc996cc53 | ||
|
|
69c34d7ebc | ||
|
|
ab2cab011d | ||
|
|
4724d28262 | ||
|
|
00846da5fa | ||
|
|
fd6bc06ed9 | ||
|
|
2f6d49421e | ||
|
|
ae9f0eae9b | ||
|
|
83f808f8b6 | ||
|
|
1a11ab5a91 | ||
|
|
0b50cac82c | ||
|
|
1e29450db8 | ||
|
|
390e372a68 | ||
|
|
a3126ca2e7 | ||
|
|
9e43fae139 | ||
|
|
7f6944c530 | ||
|
|
ebeade1748 | ||
|
|
19284ee720 | ||
|
|
409c705acd | ||
|
|
09317b1267 | ||
|
|
c8e58ad073 | ||
|
|
3eab6a6588 | ||
|
|
b00a9d29b6 | ||
|
|
187dc0a1c9 | ||
|
|
a3a7f0cedb | ||
|
|
1963f80391 | ||
|
|
e5d971d547 | ||
|
|
e4b19f7fb6 | ||
|
|
67522121db | ||
|
|
8198859943 | ||
|
|
4a3ff5aa7a | ||
|
|
f135999adb | ||
|
|
5efb8442d3 | ||
|
|
c43378fdd9 | ||
|
|
1718377da4 | ||
|
|
051dc0daed | ||
|
|
6f65a4ee89 | ||
|
|
cbaf14ed1b | ||
|
|
3de799b8b1 | ||
|
|
dad11f5253 | ||
|
|
4a35233b49 | ||
|
|
f6fde624f0 | ||
|
|
9868356827 | ||
|
|
6ed2aa5dea | ||
|
|
09cfd7ba01 | ||
|
|
fdb35b096e | ||
|
|
3a9465fe9d | ||
|
|
651810e7a2 | ||
|
|
ce7a262670 | ||
|
|
a46cab0480 | ||
|
|
d74ac5a3c6 | ||
|
|
f3fa80cfc1 | ||
|
|
f789f6c74b | ||
|
|
b20c02b14a | ||
|
|
465027234c | ||
|
|
5c86115b72 | ||
|
|
7b19d6f412 | ||
|
|
216ce9f7a9 | ||
|
|
bdec2dec38 | ||
|
|
8bb094b1aa | ||
|
|
e8dc693cb9 | ||
|
|
108f559dc4 | ||
|
|
c635d6af52 | ||
|
|
f1f704f2e3 | ||
|
|
5ddae7c96b | ||
|
|
2bbb50f2aa | ||
|
|
22be3e4e92 | ||
|
|
de2b464273 | ||
|
|
0c3803121f | ||
|
|
3b5fa7abbc | ||
|
|
611002f3db | ||
|
|
730196de97 | ||
|
|
3f707e7bea | ||
|
|
0582699e51 | ||
|
|
3346e418dc | ||
|
|
745447d16f | ||
|
|
895838ff70 | ||
|
|
cc8f92a6ce | ||
|
|
39895832c9 | ||
|
|
098774db90 | ||
|
|
681e0b9e79 | ||
|
|
500b061fd0 | ||
|
|
87c108279e | ||
|
|
fea8efe103 | ||
|
|
2df490e748 | ||
|
|
eb6bb51aef | ||
|
|
66506afa68 | ||
|
|
a7cdff3207 | ||
|
|
781a77839b | ||
|
|
e531af9bc4 | ||
|
|
cd6048d690 | ||
|
|
70edd8330b | ||
|
|
68101e8816 | ||
|
|
1a4da8cf20 | ||
|
|
32662fb0a6 | ||
|
|
29f265531b | ||
|
|
54dc16da20 | ||
|
|
ca9e66362a | ||
|
|
069e66d34b | ||
|
|
a7a1ca2f7a | ||
|
|
7808369f6a | ||
|
|
b7d98266f8 | ||
|
|
f2cb97f19b | ||
|
|
93d5c619c9 | ||
|
|
7938c95ade | ||
|
|
c47e23ae4e | ||
|
|
992a54425e | ||
|
|
711f69fddf | ||
|
|
294b58c579 | ||
|
|
50685e0d64 | ||
|
|
9a616d0e6e | ||
|
|
dec2ee7f8c | ||
|
|
2fc005e305 | ||
|
|
477ae48166 | ||
|
|
1968996243 | ||
|
|
e14c3da8f9 | ||
|
|
572a66a27b | ||
|
|
94aa98fb66 | ||
|
|
24d449d1fd | ||
|
|
9fa4b2e75a | ||
|
|
c2d0991a10 | ||
|
|
26003b0ab9 | ||
|
|
37c1fe7982 | ||
|
|
8f918dfa63 | ||
|
|
6be43166a1 | ||
|
|
6b30c31174 | ||
|
|
45c0c58746 | ||
|
|
d4eba1a64e | ||
|
|
89d0ffec5a | ||
|
|
1ee1b4b776 | ||
|
|
8a9d54f374 | ||
|
|
cd0edd2a41 | ||
|
|
bc98f1f0ea | ||
|
|
d6a443a245 | ||
|
|
910c76bd7c | ||
|
|
cd844a7499 | ||
|
|
6a1c0326df | ||
|
|
1036a58633 | ||
|
|
ebf7008493 | ||
|
|
5970719bf3 | ||
|
|
6677997bf8 | ||
|
|
37de5bd0ba | ||
|
|
2a5827dba4 | ||
|
|
cad6e02194 | ||
|
|
e7711466f3 | ||
|
|
e7ac0e37c1 | ||
|
|
6b8901eba8 | ||
|
|
b21260fb13 | ||
|
|
e87a67a26f | ||
|
|
ffdaec3464 | ||
|
|
684a7a916b | ||
|
|
e25aef3f23 | ||
|
|
c5bc6f8e74 | ||
|
|
99febfbe37 | ||
|
|
1a48d1dda5 | ||
|
|
0141ab821a | ||
|
|
a8fb5bd6f3 | ||
|
|
7917d41b3a | ||
|
|
32993c914a | ||
|
|
c6d0135ef2 | ||
|
|
869b71f437 | ||
|
|
897a215dbe | ||
|
|
23c8276dba | ||
|
|
c19bdff221 | ||
|
|
4ec3e0d9eb | ||
|
|
c85e452edb | ||
|
|
efaae4693c | ||
|
|
757a4caf03 | ||
|
|
7b6a928c6d | ||
|
|
57f2cee091 | ||
|
|
0b9cd700f5 | ||
|
|
a5abffb8be | ||
|
|
a1bc1fff5b | ||
|
|
5768fc8906 | ||
|
|
ffb11b6730 | ||
|
|
bc2253cf66 | ||
|
|
78a9090c6c | ||
|
|
eaf1f6071f | ||
|
|
ea6afc623d | ||
|
|
336fde60a7 | ||
|
|
80beb328fb | ||
|
|
19fc695c23 | ||
|
|
20d1d7c38e | ||
|
|
0d2d8d5934 | ||
|
|
8c362fce1b | ||
|
|
c4a4aa0511 | ||
|
|
66b5e90036 | ||
|
|
97c90e2101 | ||
|
|
7562e38e1e | ||
|
|
b09d8750d8 | ||
|
|
00d80d7143 | ||
|
|
d42b15679c | ||
|
|
0552ff03be | ||
|
|
fe0a98a999 | ||
|
|
a92087a7cb | ||
|
|
8a7440ded4 | ||
|
|
12d13fa7ad | ||
|
|
4b3f2d16e5 | ||
|
|
97dbe1eccd | ||
|
|
1e000c42ca | ||
|
|
dec2bb0d48 | ||
|
|
f4de5cc330 | ||
|
|
1ad70ff628 | ||
|
|
229c4d3572 | ||
|
|
8156cfc597 | ||
|
|
e7fb9db2ee | ||
|
|
0899cac487 | ||
|
|
c07714d8c0 | ||
|
|
f0ae6cb15f | ||
|
|
598b24b3bf | ||
|
|
33bb4eac3d | ||
|
|
eda0f2a5fe | ||
|
|
131a4e2d16 | ||
|
|
7775295e18 | ||
|
|
87096ff8d6 | ||
|
|
ca3670308d | ||
|
|
601f018b5d | ||
|
|
b929d65af1 | ||
|
|
172e87f1e7 | ||
|
|
9784f39b98 | ||
|
|
5417231bf6 | ||
|
|
ac44722de6 | ||
|
|
05512c1bf0 | ||
|
|
564c9278c6 | ||
|
|
a23ef5eb23 | ||
|
|
1655b047f2 | ||
|
|
06fa8c80bb | ||
|
|
3868bedc30 | ||
|
|
416bd09ad7 | ||
|
|
51bacd5eea | ||
|
|
061575c276 | ||
|
|
a56f4ba6f0 | ||
|
|
6bf20e58a3 | ||
|
|
51fa4f86e2 | ||
|
|
7e3a4e9c82 | ||
|
|
5d6bccde27 | ||
|
|
036c7ac8e6 | ||
|
|
18397cf0e9 | ||
|
|
ea3e5e948d | ||
|
|
1fecf8670b | ||
|
|
a041cf260b | ||
|
|
cbbebc7720 | ||
|
|
9a13d1fbd8 | ||
|
|
276175cfcb | ||
|
|
334c32a8b2 | ||
|
|
7375c83c9c | ||
|
|
02c4989d3c | ||
|
|
64e15ff326 | ||
|
|
cfc7486b33 | ||
|
|
5a55375e63 | ||
|
|
8a08f9f458 | ||
|
|
1d7a8c3114 | ||
|
|
7cc9f5f075 | ||
|
|
2ca3ac43eb | ||
|
|
ef12bb988b | ||
|
|
d2dbe73961 | ||
|
|
35f5e60a77 | ||
|
|
3b931093e8 | ||
|
|
4e5671d160 | ||
|
|
5d4663df43 | ||
|
|
bae71bc094 | ||
|
|
9ceb1476af | ||
|
|
298bedde19 | ||
|
|
544b653250 | ||
|
|
fa85d09265 | ||
|
|
f8ebf3b6e1 | ||
|
|
228a84729a | ||
|
|
ec88d899e3 | ||
|
|
df5fd99886 | ||
|
|
45222701bb | ||
|
|
019af6679a | ||
|
|
c4f9419f59 | ||
|
|
06e95374e0 | ||
|
|
b50572b362 | ||
|
|
217ba763ab | ||
|
|
f39256949c | ||
|
|
ac280ddbc4 | ||
|
|
2b44e2a4a1 | ||
|
|
d5ae1ed0bb | ||
|
|
2d5c067491 | ||
|
|
7fe511ef37 | ||
|
|
3634a30ebd | ||
|
|
d42dbcf00b | ||
|
|
1a2452eb8e | ||
|
|
b1ad32279a | ||
|
|
1d41c2e818 | ||
|
|
99aca6ebc0 | ||
|
|
9a9c962a68 | ||
|
|
cc8def0c6c | ||
|
|
0e9cab167e | ||
|
|
a54af5e2ec | ||
|
|
95900d7052 | ||
|
|
a3b14acd50 | ||
|
|
654eedf6d4 | ||
|
|
546b7ad2d9 | ||
|
|
81ac42251b | ||
|
|
5fbf19e865 | ||
|
|
9563992e48 | ||
|
|
2ac4c39e1d | ||
|
|
07e39509f2 | ||
|
|
e349a245b7 | ||
|
|
daecb8e973 | ||
|
|
3b3cf77d95 | ||
|
|
c184a72515 | ||
|
|
21c7b751df | ||
|
|
74a276b0e1 | ||
|
|
2d59cbc7eb | ||
|
|
c81416a6ae | ||
|
|
0bd089a7dd | ||
|
|
bb48e63483 | ||
|
|
990950d965 | ||
|
|
428a378891 | ||
|
|
5ecfae998c | ||
|
|
d64c3941a7 | ||
|
|
38f84f485e | ||
|
|
ea8ea80df8 | ||
|
|
5a66372c7d | ||
|
|
f2201952be | ||
|
|
3bb5d84f0e | ||
|
|
783342af46 | ||
|
|
f9996830a1 | ||
|
|
ea20f6bbf0 | ||
|
|
cbd37949a9 | ||
|
|
3d6ba4c5d1 | ||
|
|
9a8d2c7894 | ||
|
|
049d77014e | ||
|
|
16f53ba04e | ||
|
|
02b53bac2c | ||
|
|
bff7a1cae1 | ||
|
|
020997e010 | ||
|
|
c3c5be2cec | ||
|
|
7a0d75e327 | ||
|
|
0e07eb80b9 | ||
|
|
563b8672b1 | ||
|
|
952c01052e | ||
|
|
a512dc1cd7 | ||
|
|
fcc07cf6f0 | ||
|
|
4c3c01f8d5 | ||
|
|
71e57fd43c | ||
|
|
933e32be7c | ||
|
|
0989b706c8 | ||
|
|
f8e8ee880f | ||
|
|
a3efaf5160 | ||
|
|
9b8a4bd95a | ||
|
|
335f796e1e | ||
|
|
277fc3bfc5 | ||
|
|
71343bd3f0 | ||
|
|
26ae8a6b5b | ||
|
|
4bac390578 | ||
|
|
b4840234d9 | ||
|
|
7b0684574e | ||
|
|
5953d57aca | ||
|
|
05ccc48c16 | ||
|
|
ab71e7fdc4 | ||
|
|
5b90677fcd | ||
|
|
5404c837c0 | ||
|
|
d881165a86 | ||
|
|
a2840c1da0 | ||
|
|
2c8af1ecfd | ||
|
|
be41b296ba | ||
|
|
109d3c2e8e | ||
|
|
00107fd6fa | ||
|
|
ee9f0fd1ab | ||
|
|
232e083ca7 | ||
|
|
1e4a0af60c | ||
|
|
af23c3773a | ||
|
|
b468e5d285 | ||
|
|
8e64fe6396 | ||
|
|
2f52639d89 | ||
|
|
e117cb4299 | ||
|
|
2a0f3a4601 | ||
|
|
1616862e98 | ||
|
|
0b8db3778f | ||
|
|
918b5cef6e | ||
|
|
adb423e380 | ||
|
|
cac7d4863d | ||
|
|
e4b7c886e3 | ||
|
|
75ec606790 | ||
|
|
0c7efe6ae7 | ||
|
|
29b69b0cbe |
18
.claude-plugin/manifest.json
Normal file
18
.claude-plugin/manifest.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "wevia-arsenal",
|
||||
"version": "5.6.0",
|
||||
"description": "WEVIA Master intents + 421 tools + 78 doctrines — WEVAL Consulting Arsenal (Casablanca)",
|
||||
"author": "Yacine Mahboub <yacine@weval-consulting.com>",
|
||||
"license": "proprietary",
|
||||
"entry_points": {
|
||||
"intents_dir": "/var/www/html/api/wired-pending/",
|
||||
"handlers_dir": "/var/www/html/api/handlers/",
|
||||
"tools_registry": "/var/www/html/api/wevia-tool-registry.json",
|
||||
"kb_dir": "/opt/wevia-brain/knowledge/",
|
||||
"vault_dir": "/opt/wevads/vault/"
|
||||
},
|
||||
"chat_endpoint": "/api/wevia-master-api.php",
|
||||
"doctrines_file": "/var/www/html/wiki/doctrine-wevia-master-v3.html",
|
||||
"installation": "WEVIA Master is embedded in weval-consulting.com Apache vhost",
|
||||
"inspired_by": "marketingskills repo (IMG_5034)"
|
||||
}
|
||||
59
404.html
59
404.html
@@ -50,5 +50,64 @@
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
|
||||
var d = document;
|
||||
var m = d.createElement('div');
|
||||
m.id = 'opus-udrill';
|
||||
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
|
||||
var inner = d.createElement('div');
|
||||
inner.id = 'opus-udrill-in';
|
||||
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
|
||||
inner.addEventListener('click', function(e){ e.stopPropagation(); });
|
||||
m.appendChild(inner);
|
||||
m.addEventListener('click', function(){ m.style.display='none'; });
|
||||
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
|
||||
(d.body || d.documentElement).appendChild(m);
|
||||
function openCard(card) {
|
||||
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
|
||||
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
|
||||
inner.innerHTML = html;
|
||||
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
|
||||
m.style.display = 'flex';
|
||||
}
|
||||
function wire(root) {
|
||||
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
|
||||
var cards = root.querySelectorAll(sels);
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
var c = cards[i];
|
||||
if (c.__opusWired) continue;
|
||||
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
|
||||
var r = c.getBoundingClientRect();
|
||||
if (r.width < 60 || r.height < 40) continue;
|
||||
c.__opusWired = true;
|
||||
c.style.cursor = 'pointer';
|
||||
c.setAttribute('role','button');
|
||||
c.setAttribute('tabindex','0');
|
||||
c.addEventListener('click', function(ev){
|
||||
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
|
||||
if (ev.target.closest('a,button,input,select')) return;
|
||||
ev.preventDefault(); ev.stopPropagation();
|
||||
openCard(this);
|
||||
});
|
||||
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
|
||||
}
|
||||
}
|
||||
var initRun = function(){ wire(d.body || d.documentElement); };
|
||||
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
|
||||
else initRun();
|
||||
var mo = new MutationObserver(function(muts){
|
||||
var newCard = false;
|
||||
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
|
||||
if (newCard) initRun();
|
||||
});
|
||||
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -212,6 +212,24 @@ header .actions { display: flex; gap: 10px; align-items: center; }
|
||||
.summary-grid { grid-template-columns: 1fr; }
|
||||
.container { padding: 20px 16px 60px; }
|
||||
}
|
||||
|
||||
/* === OPUS RESPONSIVE FIX v2 19avr — append-only, doctrine #14 === */
|
||||
@media(max-width: 480px) {
|
||||
html, body { overflow-x: hidden !important; max-width: 100vw; }
|
||||
body, main, section, article { word-break: break-word; overflow-wrap: anywhere; }
|
||||
img, video, iframe, canvas, svg, table, pre, code { max-width: 100% !important; }
|
||||
pre, code { white-space: pre-wrap; word-break: break-all; }
|
||||
table { display: block; overflow-x: auto; }
|
||||
.container, [class*="container"], [class*="wrapper"] { max-width: 100vw !important; padding-left: 12px !important; padding-right: 12px !important; }
|
||||
[class*="grid"], [class*="-grid"] { grid-template-columns: 1fr !important; gap: 10px !important; }
|
||||
[class*="kpi"], [class*="stats"], [class*="-cards"] { grid-template-columns: 1fr !important; }
|
||||
header, nav, footer { flex-wrap: wrap !important; }
|
||||
header > *, nav > *, footer > * { max-width: 100%; }
|
||||
h1 { font-size: 22px !important; word-break: break-word; }
|
||||
h2 { font-size: 18px !important; }
|
||||
.pitch, [class*="pitch"], [class*="hero"] { word-break: break-word; overflow-wrap: anywhere; }
|
||||
}
|
||||
/* === OPUS RESPONSIVE FIX v2 END === */
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -686,5 +704,71 @@ document.getElementById('btn-refresh').addEventListener('click', load);
|
||||
load();
|
||||
setInterval(load, 60000);
|
||||
</script>
|
||||
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
|
||||
var d = document;
|
||||
var m = d.createElement('div');
|
||||
m.id = 'opus-udrill';
|
||||
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
|
||||
var inner = d.createElement('div');
|
||||
inner.id = 'opus-udrill-in';
|
||||
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
|
||||
inner.addEventListener('click', function(e){ e.stopPropagation(); });
|
||||
m.appendChild(inner);
|
||||
m.addEventListener('click', function(){ m.style.display='none'; });
|
||||
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
|
||||
(d.body || d.documentElement).appendChild(m);
|
||||
|
||||
function openCard(card) {
|
||||
// Clone card content + show close btn + increase font-size
|
||||
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
|
||||
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
|
||||
inner.innerHTML = html;
|
||||
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
|
||||
m.style.display = 'flex';
|
||||
}
|
||||
|
||||
function wire(root) {
|
||||
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
|
||||
var cards = root.querySelectorAll(sels);
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
var c = cards[i];
|
||||
if (c.__opusWired) continue;
|
||||
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
|
||||
var r = c.getBoundingClientRect();
|
||||
if (r.width < 60 || r.height < 40) continue;
|
||||
c.__opusWired = true;
|
||||
c.style.cursor = 'pointer';
|
||||
c.setAttribute('role','button');
|
||||
c.setAttribute('tabindex','0');
|
||||
c.addEventListener('click', function(ev){
|
||||
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
|
||||
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
|
||||
if (ev.target.closest('a,button,input,select')) return;
|
||||
ev.preventDefault(); ev.stopPropagation();
|
||||
openCard(this);
|
||||
});
|
||||
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
|
||||
}
|
||||
}
|
||||
|
||||
// Initial + mutation observer
|
||||
var initRun = function(){ wire(d.body || d.documentElement); };
|
||||
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
|
||||
else initRun();
|
||||
var mo = new MutationObserver(function(muts){
|
||||
var newCard = false;
|
||||
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
|
||||
if (newCard) initRun();
|
||||
});
|
||||
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
|
||||
|
||||
<script src="/api/archi-meta-badge.js" defer></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
690
acquired-dashboard.html.gold-19avr-opus
Normal file
690
acquired-dashboard.html.gold-19avr-opus
Normal file
@@ -0,0 +1,690 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>WEVAL · Acquis Dashboard — Skills · Tools · RAG · Intents</title>
|
||||
<style>
|
||||
:root {
|
||||
--bg-0: #05060a;
|
||||
--bg-1: #0b0d15;
|
||||
--bg-2: #11141f;
|
||||
--bg-3: #171b2a;
|
||||
--border: rgba(99,102,241,0.15);
|
||||
--text: #e2e8f0;
|
||||
--text-dim: #94a3b8;
|
||||
--text-mute: #64748b;
|
||||
--accent: #14b8a6;
|
||||
--accent-2: #6366f1;
|
||||
--ok: #22c55e;
|
||||
--warn: #f59e0b;
|
||||
--err: #ef4444;
|
||||
--purple: #a855f7;
|
||||
--cyan: #06b6d4;
|
||||
--rose: #f43f5e;
|
||||
--amber: #f59e0b;
|
||||
}
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body {
|
||||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
|
||||
background: radial-gradient(ellipse at top, #0f1420 0%, var(--bg-0) 60%);
|
||||
color: var(--text);
|
||||
min-height: 100vh;
|
||||
padding: 0;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
.container { max-width: 1600px; margin: 0 auto; padding: 28px 32px 80px; }
|
||||
|
||||
/* HEADER */
|
||||
header {
|
||||
display: flex; justify-content: space-between; align-items: center;
|
||||
margin-bottom: 28px; padding-bottom: 20px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
header h1 {
|
||||
font-size: 26px; font-weight: 700;
|
||||
background: linear-gradient(90deg, #22d3ee, #a855f7, #f43f5e);
|
||||
-webkit-background-clip: text; background-clip: text; color: transparent;
|
||||
display: flex; align-items: center; gap: 12px;
|
||||
}
|
||||
header .subtitle { color: var(--text-dim); font-size: 13px; margin-top: 4px; }
|
||||
header .actions { display: flex; gap: 10px; align-items: center; }
|
||||
.btn {
|
||||
padding: 8px 14px; background: var(--bg-2); border: 1px solid var(--border);
|
||||
color: var(--text); border-radius: 8px; cursor: pointer; font-size: 12.5px;
|
||||
font-family: inherit; transition: all .2s;
|
||||
}
|
||||
.btn:hover { border-color: var(--accent); color: var(--accent); }
|
||||
.btn-primary { background: linear-gradient(135deg, var(--accent-2), var(--purple)); border: none; }
|
||||
.pulse { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--ok);
|
||||
box-shadow: 0 0 0 0 rgba(34,197,94,0.7); animation: pulse 2s infinite; }
|
||||
@keyframes pulse {
|
||||
0%{box-shadow:0 0 0 0 rgba(34,197,94,0.7)}
|
||||
70%{box-shadow:0 0 0 10px rgba(34,197,94,0)}
|
||||
100%{box-shadow:0 0 0 0 rgba(34,197,94,0)}
|
||||
}
|
||||
|
||||
/* TOP KPI RING */
|
||||
.top-ring {
|
||||
display: grid; grid-template-columns: 380px 1fr; gap: 24px; margin-bottom: 28px;
|
||||
}
|
||||
.coverage-card {
|
||||
background: linear-gradient(135deg, rgba(20,184,166,0.10), rgba(168,85,247,0.08));
|
||||
border: 1px solid rgba(20,184,166,0.25);
|
||||
border-radius: 18px; padding: 24px; position: relative; overflow: hidden;
|
||||
}
|
||||
.coverage-card::before {
|
||||
content: ''; position: absolute; top: -40%; right: -20%; width: 300px; height: 300px;
|
||||
background: radial-gradient(circle, rgba(168,85,247,0.15), transparent 60%);
|
||||
pointer-events: none;
|
||||
}
|
||||
.coverage-ring-wrap { display: flex; align-items: center; gap: 22px; position: relative; z-index: 1; }
|
||||
.coverage-label { flex: 1; }
|
||||
.coverage-label h3 { font-size: 13px; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.8px; margin-bottom: 8px; }
|
||||
.coverage-label .big { font-size: 38px; font-weight: 700; color: var(--accent); line-height: 1; }
|
||||
.coverage-label .meta { color: var(--text-dim); font-size: 13px; margin-top: 10px; }
|
||||
|
||||
/* SUMMARY GRID */
|
||||
.summary-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; }
|
||||
.kpi {
|
||||
background: var(--bg-1); border: 1px solid var(--border);
|
||||
border-radius: 14px; padding: 20px; position: relative; overflow: hidden;
|
||||
transition: all .2s;
|
||||
}
|
||||
.kpi:hover { transform: translateY(-2px); border-color: var(--accent); }
|
||||
.kpi::before {
|
||||
content: ''; position: absolute; top: 0; left: 0; width: 4px; height: 100%;
|
||||
background: var(--accent);
|
||||
}
|
||||
.kpi.intents::before { background: var(--accent-2); }
|
||||
.kpi.skills::before { background: var(--purple); }
|
||||
.kpi.rag::before { background: var(--cyan); }
|
||||
.kpi.doctrines::before { background: var(--amber); }
|
||||
.kpi.tools::before { background: var(--rose); }
|
||||
.kpi.apis::before { background: var(--ok); }
|
||||
.kpi.dormants::before { background: var(--warn); }
|
||||
.kpi.total::before { background: linear-gradient(180deg, var(--accent), var(--purple)); }
|
||||
.kpi .label { color: var(--text-dim); font-size: 11px; text-transform: uppercase; letter-spacing: 0.7px; margin-bottom: 8px; }
|
||||
.kpi .value { font-size: 30px; font-weight: 700; color: var(--text); letter-spacing: -0.5px; }
|
||||
.kpi .trend { color: var(--ok); font-size: 11px; margin-top: 6px; display: flex; gap: 5px; align-items: center; }
|
||||
|
||||
/* CHART SECTION */
|
||||
.section-title {
|
||||
font-size: 15px; font-weight: 600; color: var(--text); margin: 32px 0 16px;
|
||||
display: flex; align-items: center; gap: 10px;
|
||||
}
|
||||
.section-title::before {
|
||||
content: ''; width: 4px; height: 18px; background: linear-gradient(180deg, var(--accent), var(--purple)); border-radius: 2px;
|
||||
}
|
||||
.chart-grid { display: grid; grid-template-columns: 1.2fr 1fr; gap: 20px; }
|
||||
.chart-card {
|
||||
background: var(--bg-1); border: 1px solid var(--border); border-radius: 14px; padding: 22px;
|
||||
}
|
||||
.chart-card h4 { font-size: 14px; color: var(--text); margin-bottom: 4px; font-weight: 600; }
|
||||
.chart-card .sub { color: var(--text-dim); font-size: 12px; margin-bottom: 18px; }
|
||||
.chart-canvas-wrap { position: relative; height: 280px; }
|
||||
|
||||
/* BARS (visual replacement for plain numbers) */
|
||||
.bar-list { display: flex; flex-direction: column; gap: 12px; }
|
||||
.bar-row { display: grid; grid-template-columns: 180px 1fr 60px; align-items: center; gap: 12px; font-size: 12.5px; }
|
||||
.bar-label { color: var(--text); font-weight: 500; }
|
||||
.bar-label .ver { color: var(--text-mute); font-size: 10.5px; margin-left: 6px; }
|
||||
.bar-track { background: var(--bg-3); height: 10px; border-radius: 6px; overflow: hidden; position: relative; }
|
||||
.bar-fill {
|
||||
height: 100%; border-radius: 6px; position: relative;
|
||||
background: linear-gradient(90deg, var(--accent), var(--accent-2));
|
||||
transition: width 1.4s cubic-bezier(.4,0,.2,1);
|
||||
}
|
||||
.bar-fill.new {
|
||||
background: linear-gradient(90deg, var(--purple), var(--rose));
|
||||
box-shadow: 0 0 12px rgba(168,85,247,0.4);
|
||||
}
|
||||
.bar-count { color: var(--text); font-size: 12px; font-weight: 600; text-align: right; }
|
||||
|
||||
/* DIFF / NEW badge */
|
||||
.badge-new {
|
||||
display: inline-block; padding: 1px 7px; background: rgba(168,85,247,0.18); color: var(--purple);
|
||||
border-radius: 8px; font-size: 10px; font-weight: 600; margin-left: 6px; letter-spacing: 0.4px;
|
||||
}
|
||||
.badge-live {
|
||||
display: inline-block; padding: 1px 7px; background: rgba(34,197,94,0.15); color: var(--ok);
|
||||
border-radius: 8px; font-size: 10px; font-weight: 600; margin-left: 6px;
|
||||
}
|
||||
|
||||
/* LOWER GRID (RAG + TOOLS OSS TREEMAP) */
|
||||
.rag-tools-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
|
||||
|
||||
/* ANTI-REGRESSION ALERT */
|
||||
.anti-reg {
|
||||
margin-top: 28px; padding: 18px 22px;
|
||||
background: linear-gradient(135deg, rgba(239,68,68,0.08), rgba(245,158,11,0.05));
|
||||
border-left: 3px solid var(--err); border-radius: 10px;
|
||||
display: flex; align-items: flex-start; gap: 14px;
|
||||
}
|
||||
.anti-reg .icon { font-size: 20px; color: var(--err); }
|
||||
.anti-reg h4 { font-size: 13px; color: var(--err); margin-bottom: 4px; text-transform: uppercase; letter-spacing: 0.6px; }
|
||||
.anti-reg p { font-size: 12.5px; color: var(--text-dim); line-height: 1.6; }
|
||||
|
||||
/* TABS */
|
||||
.tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--border); margin-bottom: 20px; }
|
||||
.tab {
|
||||
padding: 10px 16px; background: transparent; border: none; color: var(--text-dim);
|
||||
font-family: inherit; font-size: 13px; cursor: pointer; border-bottom: 2px solid transparent;
|
||||
transition: all .2s;
|
||||
}
|
||||
.tab.active { color: var(--accent); border-bottom-color: var(--accent); }
|
||||
.tab:hover { color: var(--text); }
|
||||
.tab-content { display: none; }
|
||||
.tab-content.active { display: block; }
|
||||
|
||||
/* LOADING */
|
||||
.loading { text-align: center; padding: 60px 20px; color: var(--text-dim); }
|
||||
.loading .spinner {
|
||||
width: 40px; height: 40px; border: 3px solid var(--bg-3); border-top-color: var(--accent);
|
||||
border-radius: 50%; margin: 0 auto 16px; animation: spin 1s linear infinite;
|
||||
}
|
||||
@keyframes spin { to { transform: rotate(360deg); } }
|
||||
|
||||
/* TREEMAP-STYLE TOOLS */
|
||||
.treemap { display: grid; grid-template-columns: repeat(6, 1fr); gap: 4px; grid-auto-rows: 38px; }
|
||||
.tile {
|
||||
background: var(--bg-3); border-radius: 6px; padding: 6px 8px; font-size: 10.5px;
|
||||
color: var(--text); display: flex; align-items: center; justify-content: center;
|
||||
text-align: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
||||
transition: all .2s; cursor: default;
|
||||
}
|
||||
.tile:hover { background: var(--bg-2); border: 1px solid var(--accent); color: var(--accent); }
|
||||
.tile.cat-ai { background: rgba(168,85,247,0.15); color: #d4a7fa; }
|
||||
.tile.cat-agent { background: rgba(99,102,241,0.15); color: #a5b4fc; }
|
||||
.tile.cat-doc { background: rgba(20,184,166,0.15); color: #5eead4; }
|
||||
.tile.cat-dev { background: rgba(6,182,212,0.15); color: #7dd3fc; }
|
||||
.tile.cat-data { background: rgba(245,158,11,0.15); color: #fcd34d; }
|
||||
.tile.cat-sec { background: rgba(239,68,68,0.12); color: #fca5a5; }
|
||||
|
||||
/* RESPONSIVE */
|
||||
@media(max-width: 1024px) {
|
||||
.top-ring { grid-template-columns: 1fr; }
|
||||
.summary-grid { grid-template-columns: repeat(2, 1fr); }
|
||||
.chart-grid, .rag-tools-grid { grid-template-columns: 1fr; }
|
||||
.treemap { grid-template-columns: repeat(3, 1fr); }
|
||||
}
|
||||
@media(max-width: 640px) {
|
||||
.summary-grid { grid-template-columns: 1fr; }
|
||||
.container { padding: 20px 16px 60px; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
|
||||
<header>
|
||||
<div>
|
||||
<h1>🎯 Acquis Dashboard <span class="pulse" title="Live data"></span></h1>
|
||||
<div class="subtitle">Skills · Tools OSS · RAG vectors · Intents câblés · Doctrines — inventaire temps-réel, anti-régression</div>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<button class="btn" id="btn-refresh">↻ Refresh</button>
|
||||
<a href="/weval-technology-platform.html" class="btn btn-primary">← WTP Portal</a>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- TOP RING: Coverage + Summary KPIs -->
|
||||
<div class="top-ring">
|
||||
<div class="coverage-card">
|
||||
<div class="coverage-ring-wrap">
|
||||
<svg width="150" height="150" viewBox="0 0 150 150">
|
||||
<circle cx="75" cy="75" r="60" stroke="var(--bg-3)" stroke-width="12" fill="none"/>
|
||||
<circle id="ring-coverage" cx="75" cy="75" r="60" stroke="url(#grad-cov)" stroke-width="12" fill="none"
|
||||
stroke-linecap="round" stroke-dasharray="376.99" stroke-dashoffset="376.99"
|
||||
transform="rotate(-90 75 75)" style="transition: stroke-dashoffset 1.8s cubic-bezier(.4,0,.2,1);"/>
|
||||
<defs>
|
||||
<linearGradient id="grad-cov" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" stop-color="#14b8a6"/>
|
||||
<stop offset="100%" stop-color="#a855f7"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<text id="cov-pct" x="75" y="78" text-anchor="middle" font-size="26" font-weight="700" fill="#e2e8f0">0%</text>
|
||||
<text x="75" y="98" text-anchor="middle" font-size="10" fill="#94a3b8">coverage</text>
|
||||
</svg>
|
||||
<div class="coverage-label">
|
||||
<h3>Inventaire global acquis</h3>
|
||||
<div class="big" id="kpi-total">—</div>
|
||||
<div class="meta" id="kpi-total-sub">chargement…</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="summary-grid">
|
||||
<div class="kpi intents"><div class="label">Intents wired</div><div class="value" id="kpi-intents">—</div><div class="trend">⬆ V62 · V63 live</div></div>
|
||||
<div class="kpi skills"><div class="label">Skills OSS</div><div class="value" id="kpi-skills">—</div><div class="trend">🧩 antigravity · deerflow · ecc</div></div>
|
||||
<div class="kpi rag"><div class="label">Vectors RAG</div><div class="value" id="kpi-vectors">—</div><div class="trend">🧮 Qdrant 18 collections</div></div>
|
||||
<div class="kpi doctrines"><div class="label">Doctrines</div><div class="value" id="kpi-doctrines">—</div><div class="trend">📜 Obsidian vault</div></div>
|
||||
<div class="kpi tools"><div class="label">Tools OSS dirs</div><div class="value" id="kpi-tools">—</div><div class="trend">🐳 /opt/ écosystème</div></div>
|
||||
<div class="kpi apis"><div class="label">APIs actives</div><div class="value" id="kpi-apis">—</div><div class="trend"><span class="pulse"></span> V60/V61/V62/V63</div></div>
|
||||
<div class="kpi dormants"><div class="label">Dormants</div><div class="value" id="kpi-dormants">—</div><div class="trend">⚠ à wirer</div></div>
|
||||
<div class="kpi total"><div class="label">Coverage ratio</div><div class="value" id="kpi-coverage">—</div><div class="trend">🎯 anti-regression</div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- TABS -->
|
||||
<div class="tabs">
|
||||
<button class="tab active" data-tab="overview">📊 Overview</button>
|
||||
<button class="tab" data-tab="intents">🎼 Intents (69)</button>
|
||||
<button class="tab" data-tab="skills">🧩 Skills OSS (4247)</button>
|
||||
<button class="tab" data-tab="tools">🛠️ Tools OSS (90)</button>
|
||||
<button class="tab" data-tab="lean6sigma">📐 Lean 6 Sigma TOC</button>
|
||||
<button class="tab" data-tab="diff">🔄 Diff ACQUIS vs TO WIRE</button>
|
||||
</div>
|
||||
|
||||
<!-- OVERVIEW TAB -->
|
||||
<div class="tab-content active" id="tab-overview">
|
||||
<div class="chart-grid">
|
||||
<div class="chart-card">
|
||||
<h4>Répartition acquis — par catégorie</h4>
|
||||
<div class="sub">Distribution volumique des ressources câblées</div>
|
||||
<div class="chart-canvas-wrap"><canvas id="chart-pie"></canvas></div>
|
||||
</div>
|
||||
<div class="chart-card">
|
||||
<h4>Évolution intents V42 → V63</h4>
|
||||
<div class="sub">Câblage des intents par version du système</div>
|
||||
<div class="chart-canvas-wrap"><canvas id="chart-bar"></canvas></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section-title">Couverture par domaine fonctionnel</div>
|
||||
<div class="chart-card">
|
||||
<div class="bar-list" id="coverage-bars">
|
||||
<div class="loading"><div class="spinner"></div>Chargement des barres de progression…</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- INTENTS TAB -->
|
||||
<div class="tab-content" id="tab-intents">
|
||||
<div class="chart-card">
|
||||
<h4>Intents câblés par version (69 total)</h4>
|
||||
<div class="sub">Chaque barre = une catégorie d'intents reliés à WEVIA Master orchestrator</div>
|
||||
<div class="bar-list" id="intents-bars">
|
||||
<div class="loading"><div class="spinner"></div>Chargement…</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SKILLS TAB -->
|
||||
<div class="tab-content" id="tab-skills">
|
||||
<div class="chart-card">
|
||||
<h4>Skills OSS par collection</h4>
|
||||
<div class="sub">4 247 skills découverts via oss-discovery (11 symlinks)</div>
|
||||
<div class="chart-canvas-wrap" style="height: 320px;"><canvas id="chart-skills"></canvas></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- TOOLS TAB -->
|
||||
<div class="tab-content" id="tab-tools">
|
||||
<div class="chart-card">
|
||||
<h4>Tools OSS (/opt/ écosystème)</h4>
|
||||
<div class="sub">90 installations — treemap par catégorie</div>
|
||||
<div class="treemap" id="tools-treemap">
|
||||
<div class="loading"><div class="spinner"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- LEAN6SIGMA TAB -->
|
||||
<div class="tab-content" id="tab-lean6sigma">
|
||||
<div class="chart-card">
|
||||
<h4>Lean 6 Sigma · TOC · BPMN — Ecosystem Acquis</h4>
|
||||
<div class="sub">Pages méthodologiques + Qdrant kb_lean6sigma (V62)</div>
|
||||
<div id="lean6sigma-content">
|
||||
<div class="loading"><div class="spinner"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- DIFF TAB -->
|
||||
<div class="tab-content" id="tab-diff">
|
||||
<div class="chart-card">
|
||||
<h4>ACQUIS LIVE vs À WIRER (dormants)</h4>
|
||||
<div class="sub">Différence visuelle — ce qui est câblé vs ce qui reste</div>
|
||||
<div class="chart-canvas-wrap" style="height: 320px;"><canvas id="chart-diff"></canvas></div>
|
||||
</div>
|
||||
<div class="chart-card" style="margin-top: 20px;">
|
||||
<h4>Dormants détaillés</h4>
|
||||
<div class="bar-list" id="dormants-bars">
|
||||
<div class="loading"><div class="spinner"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ANTI-REGRESSION -->
|
||||
<div class="anti-reg" id="anti-reg-box" style="display:none;">
|
||||
<div class="icon">⚠</div>
|
||||
<div>
|
||||
<h4>Anti-Regression Alert</h4>
|
||||
<p id="anti-reg-text">—</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
|
||||
<script>
|
||||
// Chart.js global defaults for premium dark look
|
||||
if (typeof Chart !== 'undefined') {
|
||||
Chart.defaults.color = '#94a3b8';
|
||||
Chart.defaults.borderColor = 'rgba(99,102,241,0.15)';
|
||||
Chart.defaults.font.family = "'Inter', system-ui";
|
||||
Chart.defaults.plugins.legend.labels.padding = 16;
|
||||
Chart.defaults.plugins.legend.labels.usePointStyle = true;
|
||||
}
|
||||
|
||||
const API = '/api/wevia-v63-acquired-enriched.php?action=full';
|
||||
let chartInstances = {};
|
||||
let DATA = null;
|
||||
|
||||
async function load() {
|
||||
try {
|
||||
const r = await fetch(API + '&t=' + Date.now());
|
||||
DATA = await r.json();
|
||||
render();
|
||||
} catch (e) {
|
||||
console.error('Load error:', e);
|
||||
document.getElementById('kpi-total-sub').textContent = 'Erreur chargement API';
|
||||
}
|
||||
}
|
||||
|
||||
function fmt(n) {
|
||||
if (n >= 1000000) return (n/1000000).toFixed(1) + 'M';
|
||||
if (n >= 1000) return (n/1000).toFixed(1) + 'k';
|
||||
return n;
|
||||
}
|
||||
|
||||
function render() {
|
||||
if (!DATA || !DATA.summary) return;
|
||||
const S = DATA.summary;
|
||||
|
||||
// KPIs
|
||||
document.getElementById('kpi-intents').textContent = fmt(S.total_intents_wired);
|
||||
document.getElementById('kpi-skills').textContent = fmt(S.total_skills_oss);
|
||||
document.getElementById('kpi-vectors').textContent = fmt(S.total_vectors_rag);
|
||||
document.getElementById('kpi-doctrines').textContent = S.total_doctrines;
|
||||
document.getElementById('kpi-tools').textContent = S.total_tools_oss_dirs;
|
||||
document.getElementById('kpi-apis').textContent = S.total_apis_active;
|
||||
document.getElementById('kpi-dormants').textContent = S.total_dormant_items;
|
||||
document.getElementById('kpi-coverage').textContent = S.coverage_ratio_pct + '%';
|
||||
document.getElementById('kpi-total').textContent = fmt(S.total_acquired);
|
||||
document.getElementById('kpi-total-sub').textContent = S.total_acquired.toLocaleString() + ' éléments capitalisés dans l\'écosystème';
|
||||
|
||||
// Coverage ring animation
|
||||
const pct = S.coverage_ratio_pct;
|
||||
const circumference = 2 * Math.PI * 60;
|
||||
const offset = circumference - (pct / 100) * circumference;
|
||||
const ring = document.getElementById('ring-coverage');
|
||||
if (ring) ring.setAttribute('stroke-dashoffset', offset);
|
||||
document.getElementById('cov-pct').textContent = pct + '%';
|
||||
|
||||
renderOverview();
|
||||
renderIntents();
|
||||
renderSkills();
|
||||
renderTools();
|
||||
renderLean6Sigma();
|
||||
renderDiff();
|
||||
|
||||
if (DATA.anti_regression_note) {
|
||||
document.getElementById('anti-reg-box').style.display = 'flex';
|
||||
document.getElementById('anti-reg-text').textContent = DATA.anti_regression_note;
|
||||
}
|
||||
}
|
||||
|
||||
function renderOverview() {
|
||||
const S = DATA.summary;
|
||||
const ctx1 = document.getElementById('chart-pie');
|
||||
if (!ctx1 || typeof Chart === 'undefined') return;
|
||||
if (chartInstances.pie) chartInstances.pie.destroy();
|
||||
|
||||
chartInstances.pie = new Chart(ctx1, {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
labels: ['Skills OSS', 'Vectors RAG', 'Tools OSS dirs', 'Intents wired', 'Doctrines', 'APIs actives'],
|
||||
datasets: [{
|
||||
data: [S.total_skills_oss, S.total_vectors_rag, S.total_tools_oss_dirs, S.total_intents_wired, S.total_doctrines, S.total_apis_active],
|
||||
backgroundColor: ['#a855f7', '#06b6d4', '#f43f5e', '#6366f1', '#f59e0b', '#22c55e'],
|
||||
borderWidth: 0,
|
||||
spacing: 2
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true, maintainAspectRatio: false, cutout: '65%',
|
||||
plugins: { legend: { position: 'right', labels: { padding: 12, font: { size: 11 }}}}
|
||||
}
|
||||
});
|
||||
|
||||
// Bar chart V42→V63
|
||||
const cats = (DATA.acquired && DATA.acquired.intents && DATA.acquired.intents.categories) || [];
|
||||
const ctx2 = document.getElementById('chart-bar');
|
||||
if (!ctx2) return;
|
||||
if (chartInstances.bar) chartInstances.bar.destroy();
|
||||
chartInstances.bar = new Chart(ctx2, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: cats.map(c => c.version.replace(/\s.*/,'')),
|
||||
datasets: [{
|
||||
label: 'Intents câblés',
|
||||
data: cats.map(c => c.count),
|
||||
backgroundColor: cats.map(c => c.new ? '#a855f7' : '#6366f1'),
|
||||
borderRadius: 6
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true, maintainAspectRatio: false,
|
||||
plugins: { legend: { display: false }},
|
||||
scales: {
|
||||
x: { grid: { display: false }, ticks: { font: { size: 10 }}},
|
||||
y: { grid: { color: 'rgba(99,102,241,0.08)' }, ticks: { font: { size: 10 }}}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Coverage bars
|
||||
const cbWrap = document.getElementById('coverage-bars');
|
||||
const domains = [
|
||||
{ label: 'Intents orchestrator', live: S.total_intents_wired, total: S.total_intents_wired + 30, color: 'var(--accent-2)' },
|
||||
{ label: 'Skills OSS catalogués', live: S.total_skills_oss, total: 5437, color: 'var(--purple)' },
|
||||
{ label: 'Vectors RAG Qdrant', live: S.total_vectors_rag, total: 17233, color: 'var(--cyan)' },
|
||||
{ label: 'Tools OSS installés', live: S.total_tools_oss_dirs, total: 90, color: 'var(--rose)' },
|
||||
{ label: 'Doctrines Obsidian', live: S.total_doctrines, total: 77, color: 'var(--amber)' },
|
||||
{ label: 'APIs backend actives', live: S.total_apis_active, total: 12, color: 'var(--ok)' }
|
||||
];
|
||||
cbWrap.innerHTML = domains.map(d => {
|
||||
const pct = Math.round(d.live / d.total * 100);
|
||||
return `<div class="bar-row">
|
||||
<div class="bar-label">${d.label}</div>
|
||||
<div class="bar-track"><div class="bar-fill" style="width: 0%; background: linear-gradient(90deg, ${d.color}, var(--accent));"></div></div>
|
||||
<div class="bar-count">${d.live}/${d.total}</div>
|
||||
</div>`;
|
||||
}).join('');
|
||||
setTimeout(() => {
|
||||
cbWrap.querySelectorAll('.bar-fill').forEach((el, i) => {
|
||||
const pct = Math.round(domains[i].live / domains[i].total * 100);
|
||||
el.style.width = Math.min(pct, 100) + '%';
|
||||
});
|
||||
}, 100);
|
||||
}
|
||||
|
||||
function renderIntents() {
|
||||
const cats = (DATA.acquired && DATA.acquired.intents && DATA.acquired.intents.categories) || [];
|
||||
const wrap = document.getElementById('intents-bars');
|
||||
const max = Math.max(...cats.map(c => c.count), 1);
|
||||
wrap.innerHTML = cats.map(c => {
|
||||
const pct = (c.count / max) * 100;
|
||||
const newBadge = c.new ? '<span class="badge-new">NEW</span>' : '';
|
||||
const liveBadge = c.live ? '<span class="badge-live">LIVE</span>' : '';
|
||||
return `<div class="bar-row">
|
||||
<div class="bar-label">${c.category}${newBadge}${liveBadge}<div class="ver" style="display:block;color:var(--text-mute);font-size:10.5px;">${c.version}</div></div>
|
||||
<div class="bar-track"><div class="bar-fill ${c.new?'new':''}" style="width:0%"></div></div>
|
||||
<div class="bar-count">${c.count}</div>
|
||||
</div>`;
|
||||
}).join('');
|
||||
setTimeout(() => {
|
||||
wrap.querySelectorAll('.bar-fill').forEach((el, i) => {
|
||||
el.style.width = ((cats[i].count / max) * 100) + '%';
|
||||
});
|
||||
}, 100);
|
||||
}
|
||||
|
||||
function renderSkills() {
|
||||
const sk = (DATA.acquired && DATA.acquired.skills_oss) || {};
|
||||
const collections = sk.collections || [];
|
||||
const ctx = document.getElementById('chart-skills');
|
||||
if (!ctx || typeof Chart === 'undefined' || !collections.length) return;
|
||||
if (chartInstances.skills) chartInstances.skills.destroy();
|
||||
chartInstances.skills = new Chart(ctx, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: collections.map(c => c.name),
|
||||
datasets: [{
|
||||
label: 'Skills détectés',
|
||||
data: collections.map(c => c.count),
|
||||
backgroundColor: collections.map((_, i) => `hsl(${240 + i*20}, 70%, 60%)`),
|
||||
borderRadius: 6
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true, maintainAspectRatio: false, indexAxis: 'y',
|
||||
plugins: { legend: { display: false }},
|
||||
scales: { x: { grid: { color: 'rgba(99,102,241,0.08)' }}, y: { grid: { display: false }}}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function renderTools() {
|
||||
const tools = (DATA.acquired && DATA.acquired.tools_oss) || {};
|
||||
const catsObj = tools.categories || {};
|
||||
const catsArr = Object.entries(catsObj); // [[key, items[]], ...]
|
||||
const wrap = document.getElementById('tools-treemap');
|
||||
wrap.innerHTML = '';
|
||||
if (!catsArr.length) {
|
||||
wrap.innerHTML = '<div style="grid-column:1/-1;color:var(--text-mute);padding:20px;">Pas de catégorisation disponible</div>';
|
||||
return;
|
||||
}
|
||||
const colorMap = {
|
||||
agent_frameworks: 'cat-agent',
|
||||
weval_ecosystem: 'cat-doc',
|
||||
skills_libs: 'cat-ai',
|
||||
memory: 'cat-data',
|
||||
infra: 'cat-dev',
|
||||
pmta: 'cat-sec'
|
||||
};
|
||||
catsArr.forEach(([key, items]) => {
|
||||
// Add category header tile
|
||||
const header = document.createElement('div');
|
||||
header.className = 'tile ' + (colorMap[key] || 'cat-ai');
|
||||
header.style.gridColumn = 'span 2';
|
||||
header.style.fontWeight = '700';
|
||||
header.style.fontSize = '11.5px';
|
||||
header.textContent = key.replace(/_/g, ' ').toUpperCase() + ' (' + items.length + ')';
|
||||
wrap.appendChild(header);
|
||||
(items || []).forEach(item => {
|
||||
const div = document.createElement('div');
|
||||
div.className = 'tile ' + (colorMap[key] || 'cat-ai');
|
||||
div.textContent = item;
|
||||
div.title = key + ' · ' + item;
|
||||
wrap.appendChild(div);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function renderLean6Sigma() {
|
||||
const l6s = DATA.lean6sigma || {};
|
||||
const wrap = document.getElementById('lean6sigma-content');
|
||||
const pages = l6s.pages || [];
|
||||
const methods = l6s.methodologies || [];
|
||||
const kb = l6s.kb_qdrant;
|
||||
wrap.innerHTML = `
|
||||
<div class="bar-list">
|
||||
<div class="bar-row">
|
||||
<div class="bar-label">Pages câblées</div>
|
||||
<div class="bar-track"><div class="bar-fill" style="width: 100%; background: linear-gradient(90deg, var(--accent), var(--accent-2));"></div></div>
|
||||
<div class="bar-count">${pages.length}</div>
|
||||
</div>
|
||||
<div class="bar-row">
|
||||
<div class="bar-label">Méthodologies</div>
|
||||
<div class="bar-track"><div class="bar-fill new" style="width: 100%;"></div></div>
|
||||
<div class="bar-count">${methods.length}</div>
|
||||
</div>
|
||||
<div class="bar-row">
|
||||
<div class="bar-label">Qdrant kb_lean6sigma</div>
|
||||
<div class="bar-track"><div class="bar-fill" style="width: ${kb?100:0}%; background: linear-gradient(90deg, var(--ok), var(--accent));"></div></div>
|
||||
<div class="bar-count">${kb?'✓':'—'}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-top: 18px; padding: 14px; background: var(--bg-2); border-radius: 8px; font-size: 12.5px;">
|
||||
<strong style="color: var(--accent)">Pages :</strong> <span style="color: var(--text-dim)">${pages.join(' · ')}</span><br>
|
||||
<strong style="color: var(--purple); margin-top: 8px; display: inline-block;">Méthodes :</strong> <span style="color: var(--text-dim)">${methods.join(' · ')}</span>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function renderDiff() {
|
||||
const dormants = DATA.dormant || {};
|
||||
const S = DATA.summary;
|
||||
|
||||
const ctx = document.getElementById('chart-diff');
|
||||
if (!ctx || typeof Chart === 'undefined') return;
|
||||
if (chartInstances.diff) chartInstances.diff.destroy();
|
||||
|
||||
chartInstances.diff = new Chart(ctx, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: ['Intents', 'Skills', 'Tools OSS', 'Doctrines'],
|
||||
datasets: [
|
||||
{ label: 'ACQUIS LIVE', data: [S.total_intents_wired, S.total_skills_oss, S.total_tools_oss_dirs, S.total_doctrines], backgroundColor: '#22c55e', borderRadius: 6 },
|
||||
{ label: 'À WIRER (dormants)', data: [30, 5437 - S.total_skills_oss, 30, 77 - S.total_doctrines], backgroundColor: '#f59e0b', borderRadius: 6 }
|
||||
]
|
||||
},
|
||||
options: {
|
||||
responsive: true, maintainAspectRatio: false,
|
||||
plugins: { legend: { position: 'top' }},
|
||||
scales: {
|
||||
x: { grid: { display: false }, stacked: false },
|
||||
y: { type: 'logarithmic', grid: { color: 'rgba(99,102,241,0.08)' }}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Dormant bars — V63 shape: {key: {count, priority, notes, wire_target}}
|
||||
const dWrap = document.getElementById('dormants-bars');
|
||||
const entries = Object.entries(dormants).map(([key, v]) => [key, v.count || 1, v.notes || '', v.priority || '', v.wire_target || ''])
|
||||
.sort((a, b) => b[1] - a[1]);
|
||||
const max = Math.max(...entries.map(e => e[1]), 1);
|
||||
dWrap.innerHTML = entries.map(([key, val, notes, prio, target]) => {
|
||||
return `<div class="bar-row">
|
||||
<div class="bar-label">${key.replace(/_/g,' ')}<div class="ver" style="display:block;color:var(--text-mute);font-size:10.5px;">${prio} → ${target} · ${notes}</div></div>
|
||||
<div class="bar-track"><div class="bar-fill" style="width:0%;background:linear-gradient(90deg, var(--warn), var(--err));"></div></div>
|
||||
<div class="bar-count">${val}</div>
|
||||
</div>`;
|
||||
}).join('');
|
||||
setTimeout(() => {
|
||||
dWrap.querySelectorAll('.bar-fill').forEach((el, i) => {
|
||||
el.style.width = ((entries[i][1] / max) * 100) + '%';
|
||||
});
|
||||
}, 100);
|
||||
}
|
||||
|
||||
// Tabs
|
||||
document.querySelectorAll('.tab').forEach(t => {
|
||||
t.addEventListener('click', () => {
|
||||
document.querySelectorAll('.tab').forEach(x => x.classList.remove('active'));
|
||||
document.querySelectorAll('.tab-content').forEach(x => x.classList.remove('active'));
|
||||
t.classList.add('active');
|
||||
document.getElementById('tab-' + t.dataset.tab).classList.add('active');
|
||||
});
|
||||
});
|
||||
|
||||
document.getElementById('btn-refresh').addEventListener('click', load);
|
||||
|
||||
// Auto-refresh every 60s
|
||||
load();
|
||||
setInterval(load, 60000);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -325,5 +325,71 @@ setTimeout(tick,1500);setInterval(tick,30000);
|
||||
})();
|
||||
</script>
|
||||
|
||||
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
|
||||
var d = document;
|
||||
var m = d.createElement('div');
|
||||
m.id = 'opus-udrill';
|
||||
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
|
||||
var inner = d.createElement('div');
|
||||
inner.id = 'opus-udrill-in';
|
||||
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
|
||||
inner.addEventListener('click', function(e){ e.stopPropagation(); });
|
||||
m.appendChild(inner);
|
||||
m.addEventListener('click', function(){ m.style.display='none'; });
|
||||
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
|
||||
(d.body || d.documentElement).appendChild(m);
|
||||
|
||||
function openCard(card) {
|
||||
// Clone card content + show close btn + increase font-size
|
||||
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
|
||||
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
|
||||
inner.innerHTML = html;
|
||||
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
|
||||
m.style.display = 'flex';
|
||||
}
|
||||
|
||||
function wire(root) {
|
||||
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
|
||||
var cards = root.querySelectorAll(sels);
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
var c = cards[i];
|
||||
if (c.__opusWired) continue;
|
||||
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
|
||||
var r = c.getBoundingClientRect();
|
||||
if (r.width < 60 || r.height < 40) continue;
|
||||
c.__opusWired = true;
|
||||
c.style.cursor = 'pointer';
|
||||
c.setAttribute('role','button');
|
||||
c.setAttribute('tabindex','0');
|
||||
c.addEventListener('click', function(ev){
|
||||
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
|
||||
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
|
||||
if (ev.target.closest('a,button,input,select')) return;
|
||||
ev.preventDefault(); ev.stopPropagation();
|
||||
openCard(this);
|
||||
});
|
||||
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
|
||||
}
|
||||
}
|
||||
|
||||
// Initial + mutation observer
|
||||
var initRun = function(){ wire(d.body || d.documentElement); };
|
||||
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
|
||||
else initRun();
|
||||
var mo = new MutationObserver(function(muts){
|
||||
var newCard = false;
|
||||
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
|
||||
if (newCard) initRun();
|
||||
});
|
||||
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
|
||||
|
||||
<script src="/api/archi-meta-badge.js" defer></script>
|
||||
</body>
|
||||
</html>
|
||||
122
admin-v2.html
122
admin-v2.html
@@ -99,31 +99,39 @@ async function fetchData(){
|
||||
}catch(e){render();}
|
||||
}
|
||||
|
||||
const SERVICES=[
|
||||
{n:'Nginx',p:':80/:443',s:'up',t:'system'},{n:'Sovereign API',p:':4000',s:'up',t:'systemd'},
|
||||
{n:'Paperclip',p:':3100',s:'up',t:'systemd'},{n:'DeerFlow',p:':3002/:3003',s:'up',t:'systemd'},
|
||||
{n:'Ollama 12 models',p:':11434',s:'up',t:'systemd'},{n:'OpenWebUI',p:':8281',s:'up',t:'docker'},
|
||||
{n:'Flowise',p:':3033',s:'up',t:'docker'},{n:'n8n',p:':5678',s:'up',t:'docker'},
|
||||
{n:'Twenty CRM',p:':3000',s:'up',t:'docker'},{n:'Mattermost',p:':8065',s:'up',t:'docker'},
|
||||
{n:'SearXNG',p:':8080',s:'up',t:'docker'},{n:'Qdrant',p:':6333',s:'up',t:'docker'},
|
||||
{n:'Plausible',p:':8000',s:'up',t:'docker'},{n:'Authentik SSO',p:':9000',s:'up',t:'docker'},
|
||||
{n:'Vaultwarden',p:':8222',s:'up',t:'docker'},{n:'Uptime Kuma',p:':3001',s:'up',t:'docker'},
|
||||
{n:'ClickHouse',p:':8123',s:'up',t:'docker'},{n:'Loki',p:':18821',s:'down',t:'docker'},
|
||||
{n:'PMTA',p:':25',s:'up',t:'system'},{n:'KumoMTA',p:':587',s:'up',t:'system'},
|
||||
{n:'CrowdSec',p:'—',s:'up',t:'systemd'},{n:'Fail2Ban',p:'—',s:'up',t:'systemd'},
|
||||
{n:'Blade Sentinel',p:'*/60s',s:'up',t:'agent'}
|
||||
/* V96.20 Opus 20avr: hardcoded SERVICES replaced by LIVE checks from /api/wevia-services-live.php */
|
||||
let SERVICES=[
|
||||
{n:'Loading services…',p:'…',s:'up',t:'system'}
|
||||
];
|
||||
async function loadLiveServices(){
|
||||
try{
|
||||
const r=await fetch('/api/wevia-services-live.php?t='+Date.now());
|
||||
const d=await r.json();
|
||||
if(d && Array.isArray(d.services)){
|
||||
SERVICES = d.services.map(s=>({n:s.n, p:s.p, s:s.s, t:s.t, ms:s.ms}));
|
||||
if(typeof fetchData==='function') fetchData();
|
||||
}
|
||||
}catch(e){}
|
||||
}
|
||||
setTimeout(loadLiveServices, 600);
|
||||
setInterval(loadLiveServices, 60000);
|
||||
|
||||
const ALERTS=[
|
||||
{ti:'S88 GPU server',ms:'GPU mort — -45€/mois. Annuler Hetzner.',sv:'critical'},
|
||||
{ti:'Loki container',ms:'Boucle restart. Logs non collectés.',sv:'critical'},
|
||||
{ti:'Stripe SK live',ms:'Clé secrète manquante. Billing inactif.',sv:'warning'},
|
||||
{ti:'WhatsApp Business',ms:'Token Meta API manquant.',sv:'warning'},
|
||||
{ti:'Azure AD',ms:'3 tenants expirés.',sv:'warning'},
|
||||
{ti:'GitHub PAT',ms:'Expire 15 avril 2026.',sv:'warning'},
|
||||
{ti:'Gemini API',ms:'Désactivée.',sv:'info'},
|
||||
{ti:'n8n v1 legacy',ms:'Node executeCommand manquant.',sv:'info'}
|
||||
/* V96.15 Opus 19avr: hardcoded ALERTS replaced by LIVE checks from /api/wevia-real-alerts.php (doctrine #4 HONNÊTE) */
|
||||
let ALERTS=[
|
||||
{ti:'Loading live alerts…',ms:'Fetching /api/wevia-real-alerts.php',sv:'info'}
|
||||
];
|
||||
async function loadRealAlerts(){
|
||||
try{
|
||||
const r=await fetch('/api/wevia-real-alerts.php?t='+Date.now());
|
||||
const d=await r.json();
|
||||
if(d && Array.isArray(d.alerts)){
|
||||
ALERTS = d.alerts.map(a=>({ti:a.ti, ms:a.ms, sv:a.sv==='ok'?'info':a.sv}));
|
||||
if(typeof fetchData==='function') fetchData();
|
||||
}
|
||||
}catch(e){}
|
||||
}
|
||||
setTimeout(loadRealAlerts, 500);
|
||||
setInterval(loadRealAlerts, 60000);
|
||||
|
||||
const SERVERS=[
|
||||
{n:'S204',ip:'204.168.152.13',ports:48,role:'Primary web/AI',s:'up'},
|
||||
@@ -225,8 +233,8 @@ function render(){
|
||||
h+=`</div>`;
|
||||
h+=`<div class="g2" style="margin-bottom:20px">`;
|
||||
h+=`<div class="card"><h3>n8n Workflows</h3>`;
|
||||
[['WEVIA Health Monitor','active'],['WEVIA AutoLearn v2','active'],['WEVIA Error Monitor v2','active'],['WEVIA AutoLearn v1','KO'],['WEVIA Error Monitor v1','KO']].forEach(([n,s])=>{
|
||||
h+=`<div class="svc"><span class="dot" style="background:${s==='active'?'var(--ok)':'var(--er)'}"></span><span class="nm">${n}</span><span style="font-size:11px;color:${s==='active'?'var(--ok)':'var(--er)'}">${s}</span></div>`;
|
||||
[['WEVIA Health Monitor','active'],['WEVIA AutoLearn v2','active'],['WEVIA Error Monitor v2','active'],['WEVIA AutoLearn v1','legacy'],['WEVIA Error Monitor v1','legacy']].forEach(([n,s])=>{
|
||||
h+=`<div class="svc"><span class="dot" style="background:${s==='active'?'var(--ok)':s==='legacy'?'var(--tm)':'var(--er)'}"></span><span class="nm">${n}</span><span style="font-size:11px;color:${s==='active'?'var(--ok)':s==='legacy'?'var(--tm)':'var(--er)'}">${s}</span></div>`;
|
||||
});
|
||||
h+=`</div>`;
|
||||
h+=`<div class="card"><h3>Workflow Engines</h3>`;
|
||||
@@ -320,5 +328,71 @@ setTimeout(tick,1500);setInterval(tick,30000);
|
||||
})();
|
||||
</script>
|
||||
|
||||
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
|
||||
var d = document;
|
||||
var m = d.createElement('div');
|
||||
m.id = 'opus-udrill';
|
||||
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
|
||||
var inner = d.createElement('div');
|
||||
inner.id = 'opus-udrill-in';
|
||||
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
|
||||
inner.addEventListener('click', function(e){ e.stopPropagation(); });
|
||||
m.appendChild(inner);
|
||||
m.addEventListener('click', function(){ m.style.display='none'; });
|
||||
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
|
||||
(d.body || d.documentElement).appendChild(m);
|
||||
|
||||
function openCard(card) {
|
||||
// Clone card content + show close btn + increase font-size
|
||||
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
|
||||
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
|
||||
inner.innerHTML = html;
|
||||
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
|
||||
m.style.display = 'flex';
|
||||
}
|
||||
|
||||
function wire(root) {
|
||||
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
|
||||
var cards = root.querySelectorAll(sels);
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
var c = cards[i];
|
||||
if (c.__opusWired) continue;
|
||||
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
|
||||
var r = c.getBoundingClientRect();
|
||||
if (r.width < 60 || r.height < 40) continue;
|
||||
c.__opusWired = true;
|
||||
c.style.cursor = 'pointer';
|
||||
c.setAttribute('role','button');
|
||||
c.setAttribute('tabindex','0');
|
||||
c.addEventListener('click', function(ev){
|
||||
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
|
||||
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
|
||||
if (ev.target.closest('a,button,input,select')) return;
|
||||
ev.preventDefault(); ev.stopPropagation();
|
||||
openCard(this);
|
||||
});
|
||||
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
|
||||
}
|
||||
}
|
||||
|
||||
// Initial + mutation observer
|
||||
var initRun = function(){ wire(d.body || d.documentElement); };
|
||||
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
|
||||
else initRun();
|
||||
var mo = new MutationObserver(function(muts){
|
||||
var newCard = false;
|
||||
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
|
||||
if (newCard) initRun();
|
||||
});
|
||||
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
|
||||
|
||||
<script src="/api/archi-meta-badge.js" defer></script>
|
||||
</body>
|
||||
</html>
|
||||
115
admin.html
115
admin.html
@@ -836,4 +836,119 @@ renderAlerts();
|
||||
})();
|
||||
</script>
|
||||
<!-- /CARTO_BANNER_V1 -->
|
||||
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
|
||||
var d = document;
|
||||
var m = d.createElement('div');
|
||||
m.id = 'opus-udrill';
|
||||
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
|
||||
var inner = d.createElement('div');
|
||||
inner.id = 'opus-udrill-in';
|
||||
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
|
||||
inner.addEventListener('click', function(e){ e.stopPropagation(); });
|
||||
m.appendChild(inner);
|
||||
m.addEventListener('click', function(){ m.style.display='none'; });
|
||||
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
|
||||
(d.body || d.documentElement).appendChild(m);
|
||||
|
||||
function openCard(card) {
|
||||
// Clone card content + show close btn + increase font-size
|
||||
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
|
||||
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
|
||||
inner.innerHTML = html;
|
||||
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
|
||||
m.style.display = 'flex';
|
||||
}
|
||||
|
||||
function wire(root) {
|
||||
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
|
||||
var cards = root.querySelectorAll(sels);
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
var c = cards[i];
|
||||
if (c.__opusWired) continue;
|
||||
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
|
||||
var r = c.getBoundingClientRect();
|
||||
if (r.width < 60 || r.height < 40) continue;
|
||||
c.__opusWired = true;
|
||||
c.style.cursor = 'pointer';
|
||||
c.setAttribute('role','button');
|
||||
c.setAttribute('tabindex','0');
|
||||
c.addEventListener('click', function(ev){
|
||||
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
|
||||
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
|
||||
if (ev.target.closest('a,button,input,select')) return;
|
||||
ev.preventDefault(); ev.stopPropagation();
|
||||
openCard(this);
|
||||
});
|
||||
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
|
||||
}
|
||||
}
|
||||
|
||||
// Initial + mutation observer
|
||||
var initRun = function(){ wire(d.body || d.documentElement); };
|
||||
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
|
||||
else initRun();
|
||||
var mo = new MutationObserver(function(muts){
|
||||
var newCard = false;
|
||||
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
|
||||
if (newCard) initRun();
|
||||
});
|
||||
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
|
||||
|
||||
|
||||
<!-- === OPUS HONEST NR/L99 OVERLAY v1 19avr - append-only doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusHonestOverlay) return; window.__opusHonestOverlay = true;
|
||||
async function updateHonestValues(){
|
||||
try {
|
||||
const r = await fetch('/api/l99-honest.php', {cache:'no-store'});
|
||||
const d = await r.json();
|
||||
if (!d.ok) return;
|
||||
const realNR = `${d.combined.pass}/${d.combined.total}`;
|
||||
const realSigma = d.sigma;
|
||||
// Find elements showing the myth values
|
||||
const mythRegex = /(153\/153|304\/304|NR status 153\/153|L99 status 304\/304|NR 153\/153|L99 304\/304)/g;
|
||||
// Walk text nodes
|
||||
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, null);
|
||||
const toReplace = [];
|
||||
let node;
|
||||
while (node = walker.nextNode()) {
|
||||
if (node.nodeValue && mythRegex.test(node.nodeValue)) toReplace.push(node);
|
||||
}
|
||||
toReplace.forEach(textNode => {
|
||||
const parent = textNode.parentNode;
|
||||
if (!parent || parent.hasAttribute('data-opus-honest-applied')) return;
|
||||
const newText = textNode.nodeValue.replace(/153\/153/g, realNR).replace(/304\/304/g, realNR);
|
||||
textNode.nodeValue = newText;
|
||||
parent.setAttribute('data-opus-honest-applied', '1');
|
||||
});
|
||||
// Add a small badge bottom-right showing honest live status
|
||||
if (!document.getElementById('opus-honest-badge')) {
|
||||
const b = document.createElement('div');
|
||||
b.id = 'opus-honest-badge';
|
||||
b.style.cssText = 'position:fixed;bottom:12px;right:12px;background:linear-gradient(90deg,#14b8a6,#a855f7);color:#05060a;padding:6px 12px;font:10px/1.3 Inter,system-ui,sans-serif;font-weight:700;border-radius:8px;z-index:99993;box-shadow:0 4px 12px rgba(0,0,0,0.3);cursor:pointer;max-width:280px';
|
||||
b.title = 'Cliquer pour détails';
|
||||
b.innerHTML = `✓ NR ${realNR} · ${realSigma} live`;
|
||||
b.onclick = () => {
|
||||
alert(`HONEST NonReg (doctrine #4):\n\nmaster: ${d.master.pass}/${d.master.total}\nopus: ${d.opus.pass}/${d.opus.total}\ncombined: ${realNR}\nsigma: ${realSigma}\n\n${d.myth_153}\n${d.myth_304}`);
|
||||
};
|
||||
document.body.appendChild(b);
|
||||
}
|
||||
} catch(e){console.error('L99-honest fetch error:', e);}
|
||||
}
|
||||
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', updateHonestValues);
|
||||
else updateHonestValues();
|
||||
setInterval(updateHonestValues, 90000);
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS HONEST END === -->
|
||||
|
||||
<script src="/api/archi-meta-badge.js" defer></script>
|
||||
</body></html>
|
||||
|
||||
@@ -122,6 +122,24 @@ select { width: 100%; padding: 8px 10px; background: var(--bg-3); border: 1px so
|
||||
.agent-card { grid-template-columns: 24px 1fr; }
|
||||
.ag-sav, .ag-quali, .ag-payback { display: none; }
|
||||
}
|
||||
|
||||
/* === OPUS RESPONSIVE FIX v2 19avr — append-only, doctrine #14 === */
|
||||
@media(max-width: 480px) {
|
||||
html, body { overflow-x: hidden !important; max-width: 100vw; }
|
||||
body, main, section, article { word-break: break-word; overflow-wrap: anywhere; }
|
||||
img, video, iframe, canvas, svg, table, pre, code { max-width: 100% !important; }
|
||||
pre, code { white-space: pre-wrap; word-break: break-all; }
|
||||
table { display: block; overflow-x: auto; }
|
||||
.container, [class*="container"], [class*="wrapper"] { max-width: 100vw !important; padding-left: 12px !important; padding-right: 12px !important; }
|
||||
[class*="grid"], [class*="-grid"] { grid-template-columns: 1fr !important; gap: 10px !important; }
|
||||
[class*="kpi"], [class*="stats"], [class*="-cards"] { grid-template-columns: 1fr !important; }
|
||||
header, nav, footer { flex-wrap: wrap !important; }
|
||||
header > *, nav > *, footer > * { max-width: 100%; }
|
||||
h1 { font-size: 22px !important; word-break: break-word; }
|
||||
h2 { font-size: 18px !important; }
|
||||
.pitch, [class*="pitch"], [class*="hero"] { word-break: break-word; overflow-wrap: anywhere; }
|
||||
}
|
||||
/* === OPUS RESPONSIVE FIX v2 END === */
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -531,5 +549,64 @@ function exportJSON(){
|
||||
|
||||
load();
|
||||
</script>
|
||||
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
|
||||
var d = document;
|
||||
var m = d.createElement('div');
|
||||
m.id = 'opus-udrill';
|
||||
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
|
||||
var inner = d.createElement('div');
|
||||
inner.id = 'opus-udrill-in';
|
||||
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
|
||||
inner.addEventListener('click', function(e){ e.stopPropagation(); });
|
||||
m.appendChild(inner);
|
||||
m.addEventListener('click', function(){ m.style.display='none'; });
|
||||
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
|
||||
(d.body || d.documentElement).appendChild(m);
|
||||
function openCard(card) {
|
||||
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
|
||||
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
|
||||
inner.innerHTML = html;
|
||||
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
|
||||
m.style.display = 'flex';
|
||||
}
|
||||
function wire(root) {
|
||||
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
|
||||
var cards = root.querySelectorAll(sels);
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
var c = cards[i];
|
||||
if (c.__opusWired) continue;
|
||||
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
|
||||
var r = c.getBoundingClientRect();
|
||||
if (r.width < 60 || r.height < 40) continue;
|
||||
c.__opusWired = true;
|
||||
c.style.cursor = 'pointer';
|
||||
c.setAttribute('role','button');
|
||||
c.setAttribute('tabindex','0');
|
||||
c.addEventListener('click', function(ev){
|
||||
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
|
||||
if (ev.target.closest('a,button,input,select')) return;
|
||||
ev.preventDefault(); ev.stopPropagation();
|
||||
openCard(this);
|
||||
});
|
||||
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
|
||||
}
|
||||
}
|
||||
var initRun = function(){ wire(d.body || d.documentElement); };
|
||||
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
|
||||
else initRun();
|
||||
var mo = new MutationObserver(function(muts){
|
||||
var newCard = false;
|
||||
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
|
||||
if (newCard) initRun();
|
||||
});
|
||||
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
535
agent-roi-simulator.html.gold-19avr-opus
Normal file
535
agent-roi-simulator.html.gold-19avr-opus
Normal file
@@ -0,0 +1,535 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>WEVAL · ROI Simulator — Gains quantitatifs & qualitatifs par agent</title>
|
||||
<style>
|
||||
:root {
|
||||
--bg-0:#05060a; --bg-1:#0b0d15; --bg-2:#11141f; --bg-3:#171b2a; --bg-4:#1e2336;
|
||||
--border:rgba(99,102,241,0.15); --border-h:rgba(99,102,241,0.35);
|
||||
--text:#e2e8f0; --dim:#94a3b8; --mute:#64748b;
|
||||
--accent:#14b8a6; --accent2:#6366f1; --purple:#a855f7; --cyan:#06b6d4;
|
||||
--ok:#22c55e; --warn:#f59e0b; --err:#ef4444; --rose:#f43f5e; --gold:#eab308;
|
||||
}
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body {
|
||||
font-family: 'Inter', system-ui, sans-serif;
|
||||
background: radial-gradient(ellipse at top, #0f1420, #05060a 65%);
|
||||
color: var(--text); min-height: 100vh; font-size: 13.5px; line-height: 1.55;
|
||||
}
|
||||
.container { max-width: 1680px; margin: 0 auto; padding: 28px 32px 80px; }
|
||||
|
||||
/* HEADER */
|
||||
header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 24px; padding-bottom: 20px; border-bottom: 1px solid var(--border); }
|
||||
header h1 { font-size: 26px; font-weight: 800; background: linear-gradient(90deg, #22d3ee, #a855f7, #eab308); -webkit-background-clip: text; background-clip: text; color: transparent; letter-spacing: -0.4px; }
|
||||
header .sub { color: var(--dim); font-size: 13px; margin-top: 6px; max-width: 820px; }
|
||||
.actions { display: flex; gap: 9px; }
|
||||
.btn { padding: 8px 15px; background: var(--bg-2); border: 1px solid var(--border); color: var(--text); border-radius: 8px; font-size: 12.5px; cursor: pointer; text-decoration: none; font-family: inherit; transition: all .2s; }
|
||||
.btn:hover { border-color: var(--accent); color: var(--accent); }
|
||||
.btn-pri { background: linear-gradient(135deg, var(--gold), var(--warn)); color: #0b0d15; font-weight: 700; border: none; }
|
||||
.pulse { display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: var(--ok); box-shadow: 0 0 0 0 rgba(34,197,94,.7); animation: pulse 2s infinite; margin-right: 4px; }
|
||||
@keyframes pulse { 0%{box-shadow:0 0 0 0 rgba(34,197,94,.7)} 70%{box-shadow:0 0 0 8px rgba(34,197,94,0)} 100%{box-shadow:0 0 0 0 rgba(34,197,94,0)} }
|
||||
|
||||
/* MAIN LAYOUT */
|
||||
.main-grid { display: grid; grid-template-columns: 320px 1fr 340px; gap: 18px; }
|
||||
@media(max-width: 1400px) { .main-grid { grid-template-columns: 1fr; } }
|
||||
|
||||
/* PARAMETER PANEL (left) */
|
||||
.panel { background: var(--bg-1); border: 1px solid var(--border); border-radius: 14px; padding: 20px; position: sticky; top: 18px; }
|
||||
.panel h3 { font-size: 15px; font-weight: 700; margin-bottom: 16px; display: flex; align-items: center; gap: 8px; }
|
||||
.param-group { margin-bottom: 20px; padding-bottom: 20px; border-bottom: 1px solid var(--bg-3); }
|
||||
.param-group:last-child { border: none; padding-bottom: 0; margin-bottom: 0; }
|
||||
.param-label { font-size: 11px; color: var(--dim); text-transform: uppercase; letter-spacing: 0.6px; font-weight: 600; margin-bottom: 8px; display: block; }
|
||||
.param-pills { display: flex; flex-wrap: wrap; gap: 5px; }
|
||||
.param-pill { padding: 6px 10px; background: var(--bg-3); border: 1px solid var(--border); border-radius: 16px; font-size: 11px; cursor: pointer; color: var(--dim); transition: all .2s; flex: 1; text-align: center; min-width: 60px; }
|
||||
.param-pill:hover { color: var(--text); border-color: var(--accent); }
|
||||
.param-pill.active { background: linear-gradient(135deg, var(--accent2), var(--purple)); color: white; border: none; font-weight: 600; }
|
||||
.param-info { font-size: 10.5px; color: var(--mute); margin-top: 6px; padding: 6px 8px; background: var(--bg-2); border-radius: 5px; line-height: 1.4; }
|
||||
select { width: 100%; padding: 8px 10px; background: var(--bg-3); border: 1px solid var(--border); color: var(--text); border-radius: 6px; font-family: inherit; font-size: 12px; }
|
||||
|
||||
/* CENTER: AGENT LIST */
|
||||
.center-col { display: flex; flex-direction: column; gap: 16px; }
|
||||
.quick-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
|
||||
.qs { background: var(--bg-1); border: 1px solid var(--border); border-radius: 10px; padding: 14px; position: relative; overflow: hidden; }
|
||||
.qs::before { content: ''; position: absolute; left: 0; top: 0; width: 3px; height: 100%; background: var(--accent); }
|
||||
.qs.gold::before { background: linear-gradient(180deg, var(--gold), var(--warn)); }
|
||||
.qs.cy::before { background: var(--cyan); }
|
||||
.qs.pu::before { background: var(--purple); }
|
||||
.qs .lbl { font-size: 10px; color: var(--dim); text-transform: uppercase; letter-spacing: 0.5px; font-weight: 600; }
|
||||
.qs .val { font-size: 22px; font-weight: 800; color: var(--text); line-height: 1; margin-top: 4px; }
|
||||
.qs .val.gold { background: linear-gradient(135deg, var(--gold), var(--warn)); -webkit-background-clip: text; background-clip: text; color: transparent; }
|
||||
.qs .sub { font-size: 10px; color: var(--mute); margin-top: 3px; }
|
||||
|
||||
.filter-bar { display: flex; gap: 5px; flex-wrap: wrap; padding: 12px; background: var(--bg-1); border: 1px solid var(--border); border-radius: 10px; align-items: center; }
|
||||
.filter-bar .lbl { font-size: 11px; color: var(--dim); font-weight: 600; margin-right: 6px; }
|
||||
.filter-pill { padding: 5px 10px; background: var(--bg-3); border: 1px solid var(--border); color: var(--dim); border-radius: 14px; font-size: 11px; cursor: pointer; font-family: inherit; transition: all .2s; }
|
||||
.filter-pill:hover { color: var(--text); border-color: var(--accent); }
|
||||
.filter-pill.active { background: linear-gradient(135deg, var(--accent), var(--cyan)); color: white; border: none; font-weight: 600; }
|
||||
.filter-bar button.btn-sml { margin-left: auto; padding: 5px 11px; font-size: 10.5px; }
|
||||
|
||||
.agent-list { display: flex; flex-direction: column; gap: 8px; max-height: none; }
|
||||
.agent-card { background: var(--bg-1); border: 1px solid var(--border); border-radius: 10px; padding: 14px 16px; display: grid; grid-template-columns: 26px 1fr 130px 100px 100px; gap: 14px; align-items: center; transition: all .15s; cursor: pointer; }
|
||||
.agent-card:hover { background: var(--bg-2); border-color: var(--border-h); }
|
||||
.agent-card.selected { background: linear-gradient(135deg, rgba(20,184,166,0.08), rgba(99,102,241,0.06)); border-color: var(--accent); }
|
||||
.agent-card input[type=checkbox] { width: 18px; height: 18px; accent-color: var(--accent); cursor: pointer; }
|
||||
.ag-main .ag-name { font-size: 13px; font-weight: 600; color: var(--text); display: flex; align-items: center; gap: 6px; }
|
||||
.ag-main .ag-name::before { content: '🤖'; }
|
||||
.ag-main .ag-pain { font-size: 11px; color: var(--dim); margin-top: 3px; line-height: 1.3; }
|
||||
.ag-main .ag-meta { display: flex; gap: 6px; margin-top: 5px; flex-wrap: wrap; }
|
||||
.ag-main .ag-meta span { font-size: 9.5px; padding: 1px 6px; border-radius: 4px; background: var(--bg-3); color: var(--dim); }
|
||||
.ag-main .ag-meta .dept { background: rgba(168,85,247,0.15); color: #d4a7fa; }
|
||||
.ag-sav { text-align: right; }
|
||||
.ag-sav .v { font-size: 16px; font-weight: 800; background: linear-gradient(135deg, var(--gold), var(--warn)); -webkit-background-clip: text; background-clip: text; color: transparent; font-family: 'JetBrains Mono', monospace; }
|
||||
.ag-sav .l { font-size: 9.5px; color: var(--dim); }
|
||||
.ag-quali { text-align: center; }
|
||||
.ag-quali .v { font-size: 16px; font-weight: 800; color: var(--accent); font-family: 'JetBrains Mono', monospace; }
|
||||
.ag-quali .l { font-size: 9.5px; color: var(--dim); }
|
||||
.ag-payback { text-align: center; }
|
||||
.ag-payback .v { font-size: 14px; font-weight: 700; color: var(--purple); font-family: 'JetBrains Mono', monospace; }
|
||||
.ag-payback .l { font-size: 9.5px; color: var(--dim); }
|
||||
|
||||
/* RIGHT COL: SELECTED PACK + RADAR + CURVE */
|
||||
.right-col { display: flex; flex-direction: column; gap: 14px; position: sticky; top: 18px; }
|
||||
.selection-box { background: var(--bg-1); border: 1px solid var(--border); border-radius: 12px; padding: 18px; }
|
||||
.selection-box h3 { font-size: 14px; font-weight: 700; margin-bottom: 14px; display: flex; justify-content: space-between; align-items: center; }
|
||||
.selection-box h3 .count-badge { font-size: 11px; background: var(--accent); color: white; padding: 2px 8px; border-radius: 10px; font-weight: 700; }
|
||||
.pack-kpis { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 14px; }
|
||||
.pack-kpi { padding: 10px; background: var(--bg-2); border-radius: 8px; border-left: 2px solid var(--accent); }
|
||||
.pack-kpi.gold { border-left-color: var(--gold); }
|
||||
.pack-kpi.rose { border-left-color: var(--rose); }
|
||||
.pack-kpi .l { font-size: 9.5px; color: var(--dim); text-transform: uppercase; letter-spacing: 0.5px; font-weight: 600; }
|
||||
.pack-kpi .v { font-size: 17px; font-weight: 800; color: var(--text); margin-top: 3px; line-height: 1; font-family: 'JetBrains Mono', monospace; }
|
||||
.pack-kpi.gold .v { background: linear-gradient(135deg, var(--gold), var(--warn)); -webkit-background-clip: text; background-clip: text; color: transparent; }
|
||||
|
||||
/* Radar chart quali */
|
||||
.radar-wrap { position: relative; text-align: center; }
|
||||
.radar-wrap svg { width: 100%; max-width: 280px; }
|
||||
|
||||
/* 12m curve */
|
||||
.curve-wrap { background: var(--bg-2); border-radius: 8px; padding: 12px; }
|
||||
|
||||
/* Empty state */
|
||||
.empty { text-align: center; padding: 24px 12px; color: var(--mute); font-size: 12px; }
|
||||
|
||||
.loading { text-align: center; padding: 60px; color: var(--dim); }
|
||||
.spinner { width: 40px; height: 40px; border: 3px solid var(--bg-3); border-top-color: var(--accent); border-radius: 50%; margin: 0 auto 16px; animation: spin 1s linear infinite; }
|
||||
@keyframes spin { to { transform: rotate(360deg); } }
|
||||
|
||||
@media(max-width: 1400px) {
|
||||
.panel, .right-col { position: static; }
|
||||
.quick-stats { grid-template-columns: repeat(2, 1fr); }
|
||||
.agent-card { grid-template-columns: 24px 1fr; }
|
||||
.ag-sav, .ag-quali, .ag-payback { display: none; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
|
||||
<header>
|
||||
<div>
|
||||
<h1>🧮 ROI Simulator · Agent-by-Agent <span class="pulse"></span></h1>
|
||||
<div class="sub">Simulez les gains quantitatifs & qualitatifs pour chaque agent WEVAL. Paramètres contextuels client (taille/maturité/vertical). Calculs temps réel.</div>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<a href="/pain-points-atlas.html" class="btn">← Atlas</a>
|
||||
<a href="/weval-technology-platform.html" class="btn">🏠 WTP</a>
|
||||
<button class="btn btn-pri" onclick="exportJSON()">📦 Export JSON</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="main-grid">
|
||||
|
||||
<!-- LEFT: PARAMS -->
|
||||
<div class="panel">
|
||||
<h3>⚙️ Contexte client</h3>
|
||||
|
||||
<div class="param-group">
|
||||
<span class="param-label">🏢 Taille entreprise</span>
|
||||
<div class="param-pills" id="size-pills"></div>
|
||||
<div class="param-info" id="size-info">—</div>
|
||||
</div>
|
||||
|
||||
<div class="param-group">
|
||||
<span class="param-label">🧠 Maturité IA</span>
|
||||
<div class="param-pills" id="maturity-pills"></div>
|
||||
<div class="param-info" id="maturity-info">—</div>
|
||||
</div>
|
||||
|
||||
<div class="param-group">
|
||||
<span class="param-label">🏭 Vertical</span>
|
||||
<select aria-label="form-field" id="vertical-select">
|
||||
<option value="">— sélectionner —</option>
|
||||
</select>
|
||||
<div class="param-info" id="vert-info">—</div>
|
||||
</div>
|
||||
|
||||
<div class="param-group">
|
||||
<span class="param-label">💰 Multiplicateur global</span>
|
||||
<div class="param-info" style="font-size:14px;text-align:center;color:var(--text);font-weight:700;font-family:'JetBrains Mono',monospace" id="mult-display">1.00×</div>
|
||||
<div class="param-info" style="margin-top:4px;font-size:10px">= size × maturity × vertical (× 1.25 si département aligné vertical)</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- CENTER: AGENTS LIST -->
|
||||
<div class="center-col">
|
||||
<div class="quick-stats">
|
||||
<div class="qs gold"><div class="lbl">Savings pack sélectionné</div><div class="val gold" id="qs-sav">0€</div><div class="sub" id="qs-sav-sub">— par an</div></div>
|
||||
<div class="qs cy"><div class="lbl">Implementation cost</div><div class="val" id="qs-impl">0€</div><div class="sub" id="qs-impl-sub">one-shot</div></div>
|
||||
<div class="qs pu"><div class="lbl">Payback pack</div><div class="val" id="qs-pay">— mois</div><div class="sub">moyenne pondérée</div></div>
|
||||
<div class="qs"><div class="lbl">NPV 3 ans</div><div class="val" id="qs-npv">0€</div><div class="sub">savings - cost - 20% maint</div></div>
|
||||
</div>
|
||||
|
||||
<div class="filter-bar">
|
||||
<span class="lbl">Département :</span>
|
||||
<div id="dept-filters" style="display:contents"></div>
|
||||
<button class="btn btn-sml" onclick="selectAll()">✓ Tous</button>
|
||||
<button class="btn btn-sml" onclick="selectNone()">✗ Aucun</button>
|
||||
</div>
|
||||
|
||||
<div class="agent-list" id="agent-list"><div class="loading"><div class="spinner"></div>Chargement…</div></div>
|
||||
</div>
|
||||
|
||||
<!-- RIGHT: SELECTION DETAILS -->
|
||||
<div class="right-col">
|
||||
<div class="selection-box">
|
||||
<h3>🎯 Pack sélectionné <span class="count-badge" id="sel-count">0</span></h3>
|
||||
|
||||
<div class="pack-kpis">
|
||||
<div class="pack-kpi gold"><div class="l">Savings/an</div><div class="v" id="pk-sav">0€</div></div>
|
||||
<div class="pack-kpi rose"><div class="l">Impl cost</div><div class="v" id="pk-impl">0€</div></div>
|
||||
<div class="pack-kpi"><div class="l">Quali avg</div><div class="v" id="pk-quali">—/100</div></div>
|
||||
<div class="pack-kpi"><div class="l">Effort</div><div class="v" id="pk-effort">— MD</div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="selection-box">
|
||||
<h3>📐 Radar qualitatif (moyenne pack)</h3>
|
||||
<div class="radar-wrap">
|
||||
<svg viewBox="0 0 260 240" id="radar-svg">
|
||||
<defs>
|
||||
<radialGradient id="rgrad"><stop offset="0%" stop-color="#14b8a6" stop-opacity="0.5"/><stop offset="100%" stop-color="#6366f1" stop-opacity="0.2"/></radialGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="selection-box">
|
||||
<h3>📈 ROI cumulé 12 mois</h3>
|
||||
<div class="curve-wrap">
|
||||
<svg id="curve-svg" viewBox="0 0 280 130" style="width:100%" preserveAspectRatio="none"></svg>
|
||||
<div style="display:flex;justify-content:space-between;font-size:9.5px;color:var(--mute);margin-top:6px">
|
||||
<span>M1</span><span>M6</span><span>M12</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const API = '/api/wevia-v67-roi-simulator.php';
|
||||
let DATA = null;
|
||||
let sel = new Set();
|
||||
let ctx = { size: 'mid', maturity: 'medium', vertical: '' };
|
||||
let deptFilter = 'all';
|
||||
|
||||
async function load(){
|
||||
const r = await fetch(API + '?t=' + Date.now());
|
||||
DATA = await r.json();
|
||||
|
||||
// Normalize quali scores (backend bug: max was 355 instead of 100, divide by 3.55)
|
||||
const maxObserved = Math.max(...DATA.agents.map(a => a.qualitative_composite_score || 0));
|
||||
const normFactor = maxObserved > 100 ? 100 / maxObserved : 1;
|
||||
DATA.agents.forEach(a => {
|
||||
a.quali_normalized = Math.round(a.qualitative_composite_score * normFactor);
|
||||
});
|
||||
|
||||
renderParams();
|
||||
renderAgents();
|
||||
recalc();
|
||||
}
|
||||
|
||||
function fmtEur(n){
|
||||
if (!n) return '0€';
|
||||
if (Math.abs(n) >= 1000000) return (n/1000000).toFixed(2)+'M€';
|
||||
if (Math.abs(n) >= 1000) return (n/1000).toFixed(0)+'k€';
|
||||
return Math.round(n)+'€';
|
||||
}
|
||||
|
||||
function renderParams(){
|
||||
const sf = DATA.scaling_factors;
|
||||
|
||||
// Size pills
|
||||
document.getElementById('size-pills').innerHTML = Object.entries(sf.company_size).map(([k,v]) =>
|
||||
`<button class="param-pill ${ctx.size===k?'active':''}" data-g="size" data-v="${k}">${v.label.split(' ')[0]}</button>`
|
||||
).join('');
|
||||
updateSizeInfo();
|
||||
|
||||
// Maturity pills
|
||||
document.getElementById('maturity-pills').innerHTML = Object.entries(sf.maturity_ai).map(([k,v]) =>
|
||||
`<button class="param-pill ${ctx.maturity===k?'active':''}" data-g="maturity" data-v="${k}">${v.label.split(' ')[0]}</button>`
|
||||
).join('');
|
||||
updateMaturityInfo();
|
||||
|
||||
// Vertical dropdown
|
||||
document.getElementById('vertical-select').innerHTML = '<option value="">— aucun (baseline) —</option>' +
|
||||
Object.entries(sf.verticals).map(([k,v]) => `<option value="${k}">${v.label} (×${v.multiplier})</option>`).join('');
|
||||
|
||||
// Dept filters
|
||||
const depts = [...new Set(DATA.agents.map(a => a.dept))].sort();
|
||||
const deptLabels = { finance:'💰 Fin', supply:'📦 Sup', manufacturing:'🏭 Mfg', sales:'💼 Sales', hr:'👥 HR', marketing:'📈 Mkt', security:'🔐 Sec', operations:'⚙️ Ops', direction:'👔 Dir' };
|
||||
document.getElementById('dept-filters').innerHTML =
|
||||
`<button class="filter-pill ${deptFilter==='all'?'active':''}" data-d="all">Tous (${DATA.agents.length})</button>` +
|
||||
depts.map(d => {
|
||||
const n = DATA.agents.filter(a => a.dept === d).length;
|
||||
return `<button class="filter-pill ${deptFilter===d?'active':''}" data-d="${d}">${deptLabels[d]||d} (${n})</button>`;
|
||||
}).join('');
|
||||
|
||||
// Event listeners
|
||||
document.querySelectorAll('.param-pill').forEach(b => b.onclick = (e) => {
|
||||
const g = e.target.dataset.g, v = e.target.dataset.v;
|
||||
ctx[g] = v;
|
||||
document.querySelectorAll(`.param-pill[data-g=${g}]`).forEach(x => x.classList.toggle('active', x.dataset.v===v));
|
||||
if (g === 'size') updateSizeInfo();
|
||||
if (g === 'maturity') updateMaturityInfo();
|
||||
recalc();
|
||||
});
|
||||
document.getElementById('vertical-select').onchange = (e) => {
|
||||
ctx.vertical = e.target.value;
|
||||
updateVertInfo();
|
||||
recalc();
|
||||
};
|
||||
document.querySelectorAll('[data-d]').forEach(b => b.onclick = (e) => {
|
||||
deptFilter = e.target.dataset.d;
|
||||
document.querySelectorAll('[data-d]').forEach(x => x.classList.toggle('active', x.dataset.d===deptFilter));
|
||||
renderAgents();
|
||||
});
|
||||
}
|
||||
|
||||
function updateSizeInfo(){
|
||||
const s = DATA.scaling_factors.company_size[ctx.size];
|
||||
document.getElementById('size-info').textContent = s.label + ' · ' + s.employees + ' employés · mult ×' + s.multiplier;
|
||||
}
|
||||
function updateMaturityInfo(){
|
||||
const m = DATA.scaling_factors.maturity_ai[ctx.maturity];
|
||||
document.getElementById('maturity-info').textContent = m.label + ' · mult ×' + m.multiplier + ' · ' + m.note;
|
||||
}
|
||||
function updateVertInfo(){
|
||||
if (!ctx.vertical) { document.getElementById('vert-info').textContent = 'Aucun vertical sélectionné (baseline ×1.0)'; return; }
|
||||
const v = DATA.scaling_factors.verticals[ctx.vertical];
|
||||
document.getElementById('vert-info').textContent = v.label + ' · mult ×' + v.multiplier + ' · depts amplifiés: ' + v.amplified_depts.join(', ');
|
||||
}
|
||||
|
||||
function scaledSavings(agent){
|
||||
const sf = DATA.scaling_factors;
|
||||
let m = sf.company_size[ctx.size].multiplier * sf.maturity_ai[ctx.maturity].multiplier;
|
||||
if (ctx.vertical){
|
||||
const v = sf.verticals[ctx.vertical];
|
||||
m *= v.multiplier;
|
||||
if (v.amplified_depts.includes(agent.dept)) m *= 1.25;
|
||||
}
|
||||
return Math.round(agent.savings_eur_year * m);
|
||||
}
|
||||
|
||||
function renderAgents(){
|
||||
const wrap = document.getElementById('agent-list');
|
||||
let list = DATA.agents;
|
||||
if (deptFilter !== 'all') list = list.filter(a => a.dept === deptFilter);
|
||||
|
||||
wrap.innerHTML = list.map(a => {
|
||||
const scaled = scaledSavings(a);
|
||||
const isSel = sel.has(a.id);
|
||||
return `<div class="agent-card ${isSel?'selected':''}" data-id="${a.id}">
|
||||
<input aria-label="form-field" type="checkbox" ${isSel?'checked':''} data-id="${a.id}">
|
||||
<div class="ag-main">
|
||||
<div class="ag-name">${a.agent}</div>
|
||||
<div class="ag-pain">${a.pain}</div>
|
||||
<div class="ag-meta">
|
||||
<span class="dept">${a.dept}</span>
|
||||
<span>${a.id}</span>
|
||||
<span>⚡ ${a.complexity}/5</span>
|
||||
<span>⚠️ ${a.risk_of_failure}/5</span>
|
||||
<span>⏱ ${a.effort_md} MD</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ag-sav"><div class="v">${fmtEur(scaled)}</div><div class="l">/an (scaled)</div></div>
|
||||
<div class="ag-quali"><div class="v">${a.quali_normalized||'—'}</div><div class="l">/100 quali</div></div>
|
||||
<div class="ag-payback"><div class="v">${a.payback_months}mo</div><div class="l">payback</div></div>
|
||||
</div>`;
|
||||
}).join('');
|
||||
|
||||
wrap.querySelectorAll('input[type=checkbox]').forEach(cb => cb.onchange = (e) => {
|
||||
const id = e.target.dataset.id;
|
||||
if (e.target.checked) sel.add(id); else sel.delete(id);
|
||||
const card = e.target.closest('.agent-card');
|
||||
card.classList.toggle('selected', e.target.checked);
|
||||
recalc();
|
||||
});
|
||||
// Click card = toggle checkbox
|
||||
wrap.querySelectorAll('.agent-card').forEach(c => {
|
||||
c.onclick = (e) => {
|
||||
if (e.target.tagName === 'INPUT') return;
|
||||
const cb = c.querySelector('input[type=checkbox]');
|
||||
cb.checked = !cb.checked;
|
||||
cb.dispatchEvent(new Event('change'));
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function selectAll(){
|
||||
DATA.agents.forEach(a => sel.add(a.id));
|
||||
renderAgents(); recalc();
|
||||
}
|
||||
function selectNone(){
|
||||
sel.clear(); renderAgents(); recalc();
|
||||
}
|
||||
|
||||
function recalc(){
|
||||
const sf = DATA.scaling_factors;
|
||||
let mult = sf.company_size[ctx.size].multiplier * sf.maturity_ai[ctx.maturity].multiplier;
|
||||
if (ctx.vertical) mult *= sf.verticals[ctx.vertical].multiplier;
|
||||
document.getElementById('mult-display').textContent = mult.toFixed(2) + '×';
|
||||
|
||||
// Selected agents
|
||||
const selAgents = DATA.agents.filter(a => sel.has(a.id));
|
||||
const nSel = selAgents.length;
|
||||
document.getElementById('sel-count').textContent = nSel;
|
||||
|
||||
if (nSel === 0){
|
||||
['qs-sav','qs-impl','qs-pay','qs-npv','pk-sav','pk-impl','pk-quali','pk-effort'].forEach(id => {
|
||||
const el = document.getElementById(id);
|
||||
if (el) el.textContent = id.includes('quali') ? '—/100' : id.includes('pay') ? '— mois' : id.includes('effort') ? '— MD' : '0€';
|
||||
});
|
||||
document.getElementById('qs-sav-sub').textContent = '— par an';
|
||||
renderRadar(null);
|
||||
renderCurve(0);
|
||||
// Still show all agents list (not filtered by selection)
|
||||
return;
|
||||
}
|
||||
|
||||
const totalSav = selAgents.reduce((s,a) => s + scaledSavings(a), 0);
|
||||
const totalImpl = selAgents.reduce((s,a) => s + a.implementation_cost_eur, 0);
|
||||
const avgPayback = selAgents.reduce((s,a) => s + a.payback_months, 0) / nSel;
|
||||
const totalEffort = selAgents.reduce((s,a) => s + a.effort_md, 0);
|
||||
const avgQuali = selAgents.reduce((s,a) => s + (a.quali_normalized||0), 0) / nSel;
|
||||
const npv3y = totalSav * 3 - totalImpl - totalSav * 0.2 * 3;
|
||||
|
||||
document.getElementById('qs-sav').textContent = fmtEur(totalSav);
|
||||
document.getElementById('qs-sav-sub').textContent = totalSav.toLocaleString('fr-FR') + ' € / an';
|
||||
document.getElementById('qs-impl').textContent = fmtEur(totalImpl);
|
||||
document.getElementById('qs-impl-sub').textContent = totalEffort + ' MD × 1200€';
|
||||
document.getElementById('qs-pay').textContent = avgPayback.toFixed(1) + ' mois';
|
||||
document.getElementById('qs-npv').textContent = fmtEur(npv3y);
|
||||
|
||||
document.getElementById('pk-sav').textContent = fmtEur(totalSav);
|
||||
document.getElementById('pk-impl').textContent = fmtEur(totalImpl);
|
||||
document.getElementById('pk-quali').textContent = avgQuali.toFixed(0) + '/100';
|
||||
document.getElementById('pk-effort').textContent = totalEffort + ' MD';
|
||||
|
||||
// Avg qualitative per axis
|
||||
const axes = ['time_fte_saved','risk_reduction','compliance_uplift','cx_impact','brand_score','strategic_value'];
|
||||
const avgAxes = {};
|
||||
axes.forEach(ax => {
|
||||
avgAxes[ax] = selAgents.reduce((s,a) => s + (a.qualitative?.[ax] || 0), 0) / nSel;
|
||||
});
|
||||
renderRadar(avgAxes);
|
||||
renderCurve(totalSav);
|
||||
}
|
||||
|
||||
function renderRadar(axes){
|
||||
const svg = document.getElementById('radar-svg');
|
||||
const cx = 130, cy = 120, r = 80;
|
||||
const axesNames = ['⏱ Time saved','🛡 Risk↓','📋 Compliance','🙂 CX/NPS','✨ Brand','🎯 Strategic'];
|
||||
const axesKeys = ['time_fte_saved','risk_reduction','compliance_uplift','cx_impact','brand_score','strategic_value'];
|
||||
|
||||
let html = `<defs><radialGradient id="rgrad"><stop offset="0%" stop-color="#14b8a6" stop-opacity="0.6"/><stop offset="100%" stop-color="#6366f1" stop-opacity="0.15"/></radialGradient></defs>`;
|
||||
// Concentric grid (5 levels)
|
||||
for (let lvl=1; lvl<=5; lvl++){
|
||||
const rr = (r*lvl)/5;
|
||||
html += `<circle cx="${cx}" cy="${cy}" r="${rr}" fill="none" stroke="#1f2436" stroke-width="1"/>`;
|
||||
}
|
||||
// Axis lines + labels
|
||||
axesNames.forEach((name, i) => {
|
||||
const angle = (Math.PI*2*i)/6 - Math.PI/2;
|
||||
const x = cx + r * Math.cos(angle), y = cy + r * Math.sin(angle);
|
||||
html += `<line x1="${cx}" y1="${cy}" x2="${x}" y2="${y}" stroke="#1f2436" stroke-width="1"/>`;
|
||||
const lx = cx + (r+18) * Math.cos(angle), ly = cy + (r+18) * Math.sin(angle);
|
||||
html += `<text x="${lx}" y="${ly}" text-anchor="middle" alignment-baseline="middle" font-size="9.5" fill="#94a3b8">${name}</text>`;
|
||||
});
|
||||
|
||||
// Data polygon
|
||||
if (axes){
|
||||
const pts = axesKeys.map((k, i) => {
|
||||
const val = axes[k] || 0;
|
||||
const angle = (Math.PI*2*i)/6 - Math.PI/2;
|
||||
const rr = (r*val)/5;
|
||||
return [cx + rr * Math.cos(angle), cy + rr * Math.sin(angle)];
|
||||
});
|
||||
const pathD = 'M' + pts.map(p => p.map(n=>n.toFixed(1)).join(',')).join(' L') + ' Z';
|
||||
html += `<path d="${pathD}" fill="url(#rgrad)" stroke="#14b8a6" stroke-width="2"/>`;
|
||||
pts.forEach(p => { html += `<circle cx="${p[0]}" cy="${p[1]}" r="3" fill="#14b8a6"/>`; });
|
||||
} else {
|
||||
html += `<text x="${cx}" y="${cy+3}" text-anchor="middle" font-size="10" fill="#64748b">Sélectionner des agents</text>`;
|
||||
}
|
||||
svg.innerHTML = html;
|
||||
}
|
||||
|
||||
function renderCurve(maxSav){
|
||||
const svg = document.getElementById('curve-svg');
|
||||
const W = 280, H = 130, PAD = 10;
|
||||
const ramp = [0, 0.05, 0.15, 0.30, 0.45, 0.60, 0.72, 0.82, 0.90, 0.95, 0.98, 1.0];
|
||||
const pts = ramp.map((p, i) => [PAD + (W-2*PAD)*i/11, H-PAD - (H-2*PAD)*p]);
|
||||
const pathLine = 'M' + pts.map(p => p.map(n=>n.toFixed(1)).join(',')).join(' L');
|
||||
const pathArea = pathLine + ` L ${(W-PAD).toFixed(1)} ${(H-PAD)} L ${PAD} ${(H-PAD)} Z`;
|
||||
|
||||
let html = `<defs><linearGradient id="lgrad" x1="0" x2="0" y1="0" y2="1"><stop offset="0%" stop-color="#14b8a6" stop-opacity="0.5"/><stop offset="100%" stop-color="#14b8a6" stop-opacity="0"/></linearGradient></defs>`;
|
||||
// Grid Y
|
||||
for (let i=0; i<=4; i++){
|
||||
const y = PAD + (H-2*PAD)*i/4;
|
||||
html += `<line x1="${PAD}" y1="${y}" x2="${W-PAD}" y2="${y}" stroke="#1f2436" stroke-width="0.5"/>`;
|
||||
}
|
||||
html += `<path d="${pathArea}" fill="url(#lgrad)"/>`;
|
||||
html += `<path d="${pathLine}" fill="none" stroke="#14b8a6" stroke-width="2" stroke-linejoin="round"/>`;
|
||||
// Labels end
|
||||
if (maxSav > 0){
|
||||
html += `<text x="${W-PAD-5}" y="${PAD+12}" text-anchor="end" font-size="10" font-weight="700" fill="#eab308">${fmtEur(maxSav)}/an</text>`;
|
||||
html += `<text x="${W-PAD-5}" y="${PAD+24}" text-anchor="end" font-size="9" fill="#94a3b8">à M12 (run rate)</text>`;
|
||||
}
|
||||
svg.innerHTML = html;
|
||||
}
|
||||
|
||||
function exportJSON(){
|
||||
const selAgents = DATA.agents.filter(a => sel.has(a.id)).map(a => ({
|
||||
id: a.id, agent: a.agent, dept: a.dept,
|
||||
baseline_savings: a.savings_eur_year,
|
||||
scaled_savings: scaledSavings(a),
|
||||
impl_cost: a.implementation_cost_eur,
|
||||
payback_months: a.payback_months,
|
||||
quali_score: a.quali_normalized
|
||||
}));
|
||||
const payload = {
|
||||
generated: new Date().toISOString(),
|
||||
context: ctx,
|
||||
selected_count: selAgents.length,
|
||||
totals: {
|
||||
savings: selAgents.reduce((s,a) => s+a.scaled_savings, 0),
|
||||
impl_cost: selAgents.reduce((s,a) => s+a.impl_cost, 0)
|
||||
},
|
||||
agents: selAgents
|
||||
};
|
||||
const blob = new Blob([JSON.stringify(payload, null, 2)], {type:'application/json'});
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url; a.download = 'weval-roi-simulation-' + Date.now() + '.json';
|
||||
a.click();
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
|
||||
load();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -432,5 +432,70 @@ C.addEventListener('mouseleave',()=>{mx=my=-1});
|
||||
requestAnimationFrame(loop);
|
||||
</script>
|
||||
<!-- CARTO_REMOVED -->
|
||||
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
|
||||
var d = document;
|
||||
var m = d.createElement('div');
|
||||
m.id = 'opus-udrill';
|
||||
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
|
||||
var inner = d.createElement('div');
|
||||
inner.id = 'opus-udrill-in';
|
||||
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
|
||||
inner.addEventListener('click', function(e){ e.stopPropagation(); });
|
||||
m.appendChild(inner);
|
||||
m.addEventListener('click', function(){ m.style.display='none'; });
|
||||
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
|
||||
(d.body || d.documentElement).appendChild(m);
|
||||
|
||||
function openCard(card) {
|
||||
// Clone card content + show close btn + increase font-size
|
||||
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
|
||||
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
|
||||
inner.innerHTML = html;
|
||||
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
|
||||
m.style.display = 'flex';
|
||||
}
|
||||
|
||||
function wire(root) {
|
||||
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
|
||||
var cards = root.querySelectorAll(sels);
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
var c = cards[i];
|
||||
if (c.__opusWired) continue;
|
||||
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
|
||||
var r = c.getBoundingClientRect();
|
||||
if (r.width < 60 || r.height < 40) continue;
|
||||
c.__opusWired = true;
|
||||
c.style.cursor = 'pointer';
|
||||
c.setAttribute('role','button');
|
||||
c.setAttribute('tabindex','0');
|
||||
c.addEventListener('click', function(ev){
|
||||
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
|
||||
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
|
||||
if (ev.target.closest('a,button,input,select')) return;
|
||||
ev.preventDefault(); ev.stopPropagation();
|
||||
openCard(this);
|
||||
});
|
||||
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
|
||||
}
|
||||
}
|
||||
|
||||
// Initial + mutation observer
|
||||
var initRun = function(){ wire(d.body || d.documentElement); };
|
||||
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
|
||||
else initRun();
|
||||
var mo = new MutationObserver(function(muts){
|
||||
var newCard = false;
|
||||
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
|
||||
if (newCard) initRun();
|
||||
});
|
||||
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -343,5 +343,70 @@ AGENTS.forEach(a=>{
|
||||
requestAnimationFrame(frame);
|
||||
</script>
|
||||
<!-- CARTO_REMOVED -->
|
||||
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
|
||||
var d = document;
|
||||
var m = d.createElement('div');
|
||||
m.id = 'opus-udrill';
|
||||
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
|
||||
var inner = d.createElement('div');
|
||||
inner.id = 'opus-udrill-in';
|
||||
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
|
||||
inner.addEventListener('click', function(e){ e.stopPropagation(); });
|
||||
m.appendChild(inner);
|
||||
m.addEventListener('click', function(){ m.style.display='none'; });
|
||||
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
|
||||
(d.body || d.documentElement).appendChild(m);
|
||||
|
||||
function openCard(card) {
|
||||
// Clone card content + show close btn + increase font-size
|
||||
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
|
||||
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
|
||||
inner.innerHTML = html;
|
||||
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
|
||||
m.style.display = 'flex';
|
||||
}
|
||||
|
||||
function wire(root) {
|
||||
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
|
||||
var cards = root.querySelectorAll(sels);
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
var c = cards[i];
|
||||
if (c.__opusWired) continue;
|
||||
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
|
||||
var r = c.getBoundingClientRect();
|
||||
if (r.width < 60 || r.height < 40) continue;
|
||||
c.__opusWired = true;
|
||||
c.style.cursor = 'pointer';
|
||||
c.setAttribute('role','button');
|
||||
c.setAttribute('tabindex','0');
|
||||
c.addEventListener('click', function(ev){
|
||||
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
|
||||
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
|
||||
if (ev.target.closest('a,button,input,select')) return;
|
||||
ev.preventDefault(); ev.stopPropagation();
|
||||
openCard(this);
|
||||
});
|
||||
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
|
||||
}
|
||||
}
|
||||
|
||||
// Initial + mutation observer
|
||||
var initRun = function(){ wire(d.body || d.documentElement); };
|
||||
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
|
||||
else initRun();
|
||||
var mo = new MutationObserver(function(muts){
|
||||
var newCard = false;
|
||||
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
|
||||
if (newCard) initRun();
|
||||
});
|
||||
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -70,7 +70,7 @@ canvas{display:block}
|
||||
.ag-card.master img{border:2px solid #ffd700;box-shadow:0 0 8px rgba(255,215,0,.35)}
|
||||
.ag-card.master .name{display:none}
|
||||
.ag-card.master:hover .name{display:block;font-size:9px;font-weight:900;color:#ffd700;letter-spacing:1px;text-shadow:0 0 8px rgba(255,215,0,.6)}
|
||||
.ag-card.master .crown{position:absolute;top:-8px;left:50%;transform:translateX(-50%);font-size:14px;animation:crownGlow 2s ease-in-out infinite}
|
||||
.ag-card.master .crown{position:absolute;top:-22px;left:50%;transform:translateX(-50%);font-size:13px;animation:crownGlow 2s ease-in-out infinite;z-index:5;filter:drop-shadow(0 1px 2px rgba(0,0,0,0.4))}
|
||||
/* KPI */
|
||||
.kpi-panel{display:block}
|
||||
.kpi{padding:8px 10px;border-radius:10px;font:700 9px Nunito;pointer-events:auto;min-width:110px;backdrop-filter:blur(8px)}
|
||||
@@ -167,7 +167,7 @@ canvas{z-index:0!important}
|
||||
.ag-card:hover .p-av{transform:scale(1.08);filter:brightness(1.1)}
|
||||
</style>
|
||||
<!-- WEVAL-D91-AGENTS-ARCHI-PERSONA -->
|
||||
<style id="d93c">.p-av{width:40px!important;height:40px!important;display:inline-flex!important;align-items:center!important;justify-content:center!important;font-size:22px!important;line-height:1!important;border-radius:50%!important;background:rgba(255,255,255,.06)!important;border:1.5px solid rgba(255,255,255,.18)!important;flex-shrink:0!important;overflow:hidden!important;box-shadow:0 2px 6px rgba(0,0,0,.25)!important}.p-av[data-persona="tool"]{border-color:rgba(139,92,246,.55)!important;background:rgba(139,92,246,.12)!important}.p-av[data-persona="master"]{border-color:rgba(255,215,0,.65)!important;background:rgba(255,215,0,.1)!important;width:48px!important;height:48px!important;font-size:26px!important}.p-av[data-persona="human"]{border-color:rgba(74,222,128,.45)!important;background:rgba(74,222,128,.08)!important}</style>
|
||||
<style id="d93c">.p-av{width:52px!important;height:52px!important;display:inline-flex!important;align-items:center!important;justify-content:center!important;font-size:28px!important;line-height:1!important;border-radius:50%!important;background:rgba(255,255,255,.06)!important;border:2.5px solid rgba(34,211,238,.55)!important;flex-shrink:0!important;overflow:hidden!important;box-shadow:0 2px 6px rgba(0,0,0,.25)!important}.p-av[data-persona="tool"]{border-color:rgba(139,92,246,.55)!important;background:rgba(139,92,246,.12)!important}.p-av[data-persona="master"]{border-color:rgba(255,215,0,.65)!important;background:rgba(255,215,0,.1)!important;width:64px!important;height:64px!important;font-size:34px!important}.p-av[data-persona="human"]{border-color:rgba(74,222,128,.45)!important;background:rgba(74,222,128,.08)!important}</style>
|
||||
</head><body><div id="liveStatusBar" style="display:none"></div>
|
||||
<noscript></noscript class="night">
|
||||
<div class="cockpit-live" id="cockpit-live"><div class="cockpit-pill" id="cp-health"><div class="cockpit-dot"></div><span class="lbl">STATUS</span><span class="val">...</span></div><div class="cockpit-pill" id="cp-l99"><span class="lbl">L99</span><span class="val">-</span></div><div class="cockpit-pill" id="cp-docker"><span class="lbl">DOCKER</span><span class="val">-</span></div><div class="cockpit-pill" id="cp-disk"><span class="lbl">DISK</span><span class="val">-</span></div><div class="cockpit-pill" id="cp-providers"><span class="lbl">PROVIDERS</span><span class="val">-</span></div><div class="cockpit-pill" id="cp-qdrant"><span class="lbl">RAG</span><span class="val">-</span></div><div class="cockpit-pill" id="cp-git"><span class="lbl">GIT</span><span class="val">-</span></div><div class="cockpit-pill" id="cp-refresh"><span class="lbl">REFRESH</span><span class="val">30s</span></div></div>
|
||||
@@ -1317,7 +1317,7 @@ window.addEventListener('resize',function(){cam.aspect=innerWidth/innerHeight;ca
|
||||
<span style="font-size:22px">🗺️</span>
|
||||
<div style="color:#0b0d15">
|
||||
<div style="font-size:12px;font-weight:800">Pain Points Atlas · 25 ERPs</div>
|
||||
<div style="font-size:10.5px;opacity:.85">35 pain points · 35 agents · 17.36M€ savings/client</div>
|
||||
<div style="font-size:10.5px;opacity:.85">60 pain points · 60 agents · 23.1M€ savings/client</div>
|
||||
<a href="/pain-points-atlas.html" style="display:inline-block;margin-top:4px;padding:3px 10px;background:#0b0d15;color:#eab308;border-radius:5px;font-size:10.5px;font-weight:700;text-decoration:none">Open Atlas →</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1356,5 +1356,119 @@ window.addEventListener('resize',function(){cam.aspect=innerWidth/innerHeight;ca
|
||||
})();
|
||||
</script>
|
||||
<script id="d93cj">(function(){function e(){var s=["[data-agent]",".agent",".agent-card",".card-agent",".node",".gap-agent"];s.forEach(function(q){document.querySelectorAll(q).forEach(function(c){if(c.querySelector(".p-av")||c.dataset.d93c)return;c.dataset.d93c=1;var p=document.createElement("span");p.className="p-av";p.setAttribute("data-persona","human");p.textContent="\ud83d\udc64";if(window.WevalAvatar&&WevalAvatar.get){var n=(c.dataset.agent||c.getAttribute("data-name")||(c.querySelector("h3,h4,.name")||{}).textContent||"").trim();if(n){try{var r=WevalAvatar.get(n);if(r&&r.emoji){p.textContent=r.emoji;if(r.persona)p.setAttribute("data-persona",r.persona);}}catch(e){}}}c.insertBefore(p,c.firstChild);});});}if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",e);else e();setTimeout(e,500);setTimeout(e,1500);setTimeout(e,3500);})();</script>
|
||||
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
|
||||
var d = document;
|
||||
var m = d.createElement('div');
|
||||
m.id = 'opus-udrill';
|
||||
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
|
||||
var inner = d.createElement('div');
|
||||
inner.id = 'opus-udrill-in';
|
||||
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
|
||||
inner.addEventListener('click', function(e){ e.stopPropagation(); });
|
||||
m.appendChild(inner);
|
||||
m.addEventListener('click', function(){ m.style.display='none'; });
|
||||
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
|
||||
(d.body || d.documentElement).appendChild(m);
|
||||
|
||||
function openCard(card) {
|
||||
// Clone card content + show close btn + increase font-size
|
||||
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
|
||||
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
|
||||
inner.innerHTML = html;
|
||||
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
|
||||
m.style.display = 'flex';
|
||||
}
|
||||
|
||||
function wire(root) {
|
||||
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
|
||||
var cards = root.querySelectorAll(sels);
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
var c = cards[i];
|
||||
if (c.__opusWired) continue;
|
||||
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
|
||||
var r = c.getBoundingClientRect();
|
||||
if (r.width < 60 || r.height < 40) continue;
|
||||
c.__opusWired = true;
|
||||
c.style.cursor = 'pointer';
|
||||
c.setAttribute('role','button');
|
||||
c.setAttribute('tabindex','0');
|
||||
c.addEventListener('click', function(ev){
|
||||
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
|
||||
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
|
||||
if (ev.target.closest('a,button,input,select')) return;
|
||||
ev.preventDefault(); ev.stopPropagation();
|
||||
openCard(this);
|
||||
});
|
||||
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
|
||||
}
|
||||
}
|
||||
|
||||
// Initial + mutation observer
|
||||
var initRun = function(){ wire(d.body || d.documentElement); };
|
||||
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
|
||||
else initRun();
|
||||
var mo = new MutationObserver(function(muts){
|
||||
var newCard = false;
|
||||
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
|
||||
if (newCard) initRun();
|
||||
});
|
||||
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
|
||||
|
||||
|
||||
<!-- === OPUS HONEST NR/L99 OVERLAY v1 19avr - append-only doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusHonestOverlay) return; window.__opusHonestOverlay = true;
|
||||
async function updateHonestValues(){
|
||||
try {
|
||||
const r = await fetch('/api/l99-honest.php', {cache:'no-store'});
|
||||
const d = await r.json();
|
||||
if (!d.ok) return;
|
||||
const realNR = `${d.combined.pass}/${d.combined.total}`;
|
||||
const realSigma = d.sigma;
|
||||
// Find elements showing the myth values
|
||||
const mythRegex = /(153\/153|304\/304|NR status 153\/153|L99 status 304\/304|NR 153\/153|L99 304\/304)/g;
|
||||
// Walk text nodes
|
||||
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, null);
|
||||
const toReplace = [];
|
||||
let node;
|
||||
while (node = walker.nextNode()) {
|
||||
if (node.nodeValue && mythRegex.test(node.nodeValue)) toReplace.push(node);
|
||||
}
|
||||
toReplace.forEach(textNode => {
|
||||
const parent = textNode.parentNode;
|
||||
if (!parent || parent.hasAttribute('data-opus-honest-applied')) return;
|
||||
const newText = textNode.nodeValue.replace(/153\/153/g, realNR).replace(/304\/304/g, realNR);
|
||||
textNode.nodeValue = newText;
|
||||
parent.setAttribute('data-opus-honest-applied', '1');
|
||||
});
|
||||
// Add a small badge bottom-right showing honest live status
|
||||
if (!document.getElementById('opus-honest-badge')) {
|
||||
const b = document.createElement('div');
|
||||
b.id = 'opus-honest-badge';
|
||||
b.style.cssText = 'position:fixed;bottom:12px;right:12px;background:linear-gradient(90deg,#14b8a6,#a855f7);color:#05060a;padding:6px 12px;font:10px/1.3 Inter,system-ui,sans-serif;font-weight:700;border-radius:8px;z-index:99993;box-shadow:0 4px 12px rgba(0,0,0,0.3);cursor:pointer;max-width:280px';
|
||||
b.title = 'Cliquer pour détails';
|
||||
b.innerHTML = `✓ NR ${realNR} · ${realSigma} live`;
|
||||
b.onclick = () => {
|
||||
alert(`HONEST NonReg (doctrine #4):\n\nmaster: ${d.master.pass}/${d.master.total}\nopus: ${d.opus.pass}/${d.opus.total}\ncombined: ${realNR}\nsigma: ${realSigma}\n\n${d.myth_153}\n${d.myth_304}`);
|
||||
};
|
||||
document.body.appendChild(b);
|
||||
}
|
||||
} catch(e){console.error('L99-honest fetch error:', e);}
|
||||
}
|
||||
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', updateHonestValues);
|
||||
else updateHonestValues();
|
||||
setInterval(updateHonestValues, 90000);
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS HONEST END === -->
|
||||
|
||||
</body></html>
|
||||
|
||||
|
||||
@@ -261,5 +261,70 @@ C.addEventListener('mouseleave',()=>{mx=my=-1});
|
||||
requestAnimationFrame(loop);
|
||||
</script>
|
||||
<!-- CARTO_REMOVED -->
|
||||
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
|
||||
var d = document;
|
||||
var m = d.createElement('div');
|
||||
m.id = 'opus-udrill';
|
||||
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
|
||||
var inner = d.createElement('div');
|
||||
inner.id = 'opus-udrill-in';
|
||||
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
|
||||
inner.addEventListener('click', function(e){ e.stopPropagation(); });
|
||||
m.appendChild(inner);
|
||||
m.addEventListener('click', function(){ m.style.display='none'; });
|
||||
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
|
||||
(d.body || d.documentElement).appendChild(m);
|
||||
|
||||
function openCard(card) {
|
||||
// Clone card content + show close btn + increase font-size
|
||||
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
|
||||
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
|
||||
inner.innerHTML = html;
|
||||
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
|
||||
m.style.display = 'flex';
|
||||
}
|
||||
|
||||
function wire(root) {
|
||||
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
|
||||
var cards = root.querySelectorAll(sels);
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
var c = cards[i];
|
||||
if (c.__opusWired) continue;
|
||||
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
|
||||
var r = c.getBoundingClientRect();
|
||||
if (r.width < 60 || r.height < 40) continue;
|
||||
c.__opusWired = true;
|
||||
c.style.cursor = 'pointer';
|
||||
c.setAttribute('role','button');
|
||||
c.setAttribute('tabindex','0');
|
||||
c.addEventListener('click', function(ev){
|
||||
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
|
||||
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
|
||||
if (ev.target.closest('a,button,input,select')) return;
|
||||
ev.preventDefault(); ev.stopPropagation();
|
||||
openCard(this);
|
||||
});
|
||||
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
|
||||
}
|
||||
}
|
||||
|
||||
// Initial + mutation observer
|
||||
var initRun = function(){ wire(d.body || d.documentElement); };
|
||||
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
|
||||
else initRun();
|
||||
var mo = new MutationObserver(function(muts){
|
||||
var newCard = false;
|
||||
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
|
||||
if (newCard) initRun();
|
||||
});
|
||||
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -272,5 +272,119 @@ load();
|
||||
setInterval(load, 30000);
|
||||
</script>
|
||||
<!-- CARTO_REMOVED -->
|
||||
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
|
||||
var d = document;
|
||||
var m = d.createElement('div');
|
||||
m.id = 'opus-udrill';
|
||||
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
|
||||
var inner = d.createElement('div');
|
||||
inner.id = 'opus-udrill-in';
|
||||
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
|
||||
inner.addEventListener('click', function(e){ e.stopPropagation(); });
|
||||
m.appendChild(inner);
|
||||
m.addEventListener('click', function(){ m.style.display='none'; });
|
||||
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
|
||||
(d.body || d.documentElement).appendChild(m);
|
||||
|
||||
function openCard(card) {
|
||||
// Clone card content + show close btn + increase font-size
|
||||
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
|
||||
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
|
||||
inner.innerHTML = html;
|
||||
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
|
||||
m.style.display = 'flex';
|
||||
}
|
||||
|
||||
function wire(root) {
|
||||
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
|
||||
var cards = root.querySelectorAll(sels);
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
var c = cards[i];
|
||||
if (c.__opusWired) continue;
|
||||
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
|
||||
var r = c.getBoundingClientRect();
|
||||
if (r.width < 60 || r.height < 40) continue;
|
||||
c.__opusWired = true;
|
||||
c.style.cursor = 'pointer';
|
||||
c.setAttribute('role','button');
|
||||
c.setAttribute('tabindex','0');
|
||||
c.addEventListener('click', function(ev){
|
||||
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
|
||||
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
|
||||
if (ev.target.closest('a,button,input,select')) return;
|
||||
ev.preventDefault(); ev.stopPropagation();
|
||||
openCard(this);
|
||||
});
|
||||
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
|
||||
}
|
||||
}
|
||||
|
||||
// Initial + mutation observer
|
||||
var initRun = function(){ wire(d.body || d.documentElement); };
|
||||
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
|
||||
else initRun();
|
||||
var mo = new MutationObserver(function(muts){
|
||||
var newCard = false;
|
||||
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
|
||||
if (newCard) initRun();
|
||||
});
|
||||
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
|
||||
|
||||
|
||||
<!-- === OPUS HONEST NR/L99 OVERLAY v1 19avr - append-only doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusHonestOverlay) return; window.__opusHonestOverlay = true;
|
||||
async function updateHonestValues(){
|
||||
try {
|
||||
const r = await fetch('/api/l99-honest.php', {cache:'no-store'});
|
||||
const d = await r.json();
|
||||
if (!d.ok) return;
|
||||
const realNR = `${d.combined.pass}/${d.combined.total}`;
|
||||
const realSigma = d.sigma;
|
||||
// Find elements showing the myth values
|
||||
const mythRegex = /(153\/153|304\/304|NR status 153\/153|L99 status 304\/304|NR 153\/153|L99 304\/304)/g;
|
||||
// Walk text nodes
|
||||
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, null);
|
||||
const toReplace = [];
|
||||
let node;
|
||||
while (node = walker.nextNode()) {
|
||||
if (node.nodeValue && mythRegex.test(node.nodeValue)) toReplace.push(node);
|
||||
}
|
||||
toReplace.forEach(textNode => {
|
||||
const parent = textNode.parentNode;
|
||||
if (!parent || parent.hasAttribute('data-opus-honest-applied')) return;
|
||||
const newText = textNode.nodeValue.replace(/153\/153/g, realNR).replace(/304\/304/g, realNR);
|
||||
textNode.nodeValue = newText;
|
||||
parent.setAttribute('data-opus-honest-applied', '1');
|
||||
});
|
||||
// Add a small badge bottom-right showing honest live status
|
||||
if (!document.getElementById('opus-honest-badge')) {
|
||||
const b = document.createElement('div');
|
||||
b.id = 'opus-honest-badge';
|
||||
b.style.cssText = 'position:fixed;bottom:12px;right:12px;background:linear-gradient(90deg,#14b8a6,#a855f7);color:#05060a;padding:6px 12px;font:10px/1.3 Inter,system-ui,sans-serif;font-weight:700;border-radius:8px;z-index:99993;box-shadow:0 4px 12px rgba(0,0,0,0.3);cursor:pointer;max-width:280px';
|
||||
b.title = 'Cliquer pour détails';
|
||||
b.innerHTML = `✓ NR ${realNR} · ${realSigma} live`;
|
||||
b.onclick = () => {
|
||||
alert(`HONEST NonReg (doctrine #4):\n\nmaster: ${d.master.pass}/${d.master.total}\nopus: ${d.opus.pass}/${d.opus.total}\ncombined: ${realNR}\nsigma: ${realSigma}\n\n${d.myth_153}\n${d.myth_304}`);
|
||||
};
|
||||
document.body.appendChild(b);
|
||||
}
|
||||
} catch(e){console.error('L99-honest fetch error:', e);}
|
||||
}
|
||||
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', updateHonestValues);
|
||||
else updateHonestValues();
|
||||
setInterval(updateHonestValues, 90000);
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS HONEST END === -->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -771,4 +771,118 @@ C.addEventListener('mousemove',function(e){mx=e.clientX;my=e.clientY+window.scro
|
||||
C.addEventListener('mouseleave',function(){mx=my=-1;});
|
||||
requestAnimationFrame(loop);
|
||||
</script><!-- CARTO_REMOVED -->
|
||||
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
|
||||
var d = document;
|
||||
var m = d.createElement('div');
|
||||
m.id = 'opus-udrill';
|
||||
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
|
||||
var inner = d.createElement('div');
|
||||
inner.id = 'opus-udrill-in';
|
||||
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
|
||||
inner.addEventListener('click', function(e){ e.stopPropagation(); });
|
||||
m.appendChild(inner);
|
||||
m.addEventListener('click', function(){ m.style.display='none'; });
|
||||
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
|
||||
(d.body || d.documentElement).appendChild(m);
|
||||
|
||||
function openCard(card) {
|
||||
// Clone card content + show close btn + increase font-size
|
||||
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
|
||||
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
|
||||
inner.innerHTML = html;
|
||||
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
|
||||
m.style.display = 'flex';
|
||||
}
|
||||
|
||||
function wire(root) {
|
||||
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
|
||||
var cards = root.querySelectorAll(sels);
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
var c = cards[i];
|
||||
if (c.__opusWired) continue;
|
||||
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
|
||||
var r = c.getBoundingClientRect();
|
||||
if (r.width < 60 || r.height < 40) continue;
|
||||
c.__opusWired = true;
|
||||
c.style.cursor = 'pointer';
|
||||
c.setAttribute('role','button');
|
||||
c.setAttribute('tabindex','0');
|
||||
c.addEventListener('click', function(ev){
|
||||
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
|
||||
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
|
||||
if (ev.target.closest('a,button,input,select')) return;
|
||||
ev.preventDefault(); ev.stopPropagation();
|
||||
openCard(this);
|
||||
});
|
||||
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
|
||||
}
|
||||
}
|
||||
|
||||
// Initial + mutation observer
|
||||
var initRun = function(){ wire(d.body || d.documentElement); };
|
||||
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
|
||||
else initRun();
|
||||
var mo = new MutationObserver(function(muts){
|
||||
var newCard = false;
|
||||
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
|
||||
if (newCard) initRun();
|
||||
});
|
||||
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
|
||||
|
||||
|
||||
<!-- === OPUS HONEST NR/L99 OVERLAY v1 19avr - append-only doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusHonestOverlay) return; window.__opusHonestOverlay = true;
|
||||
async function updateHonestValues(){
|
||||
try {
|
||||
const r = await fetch('/api/l99-honest.php', {cache:'no-store'});
|
||||
const d = await r.json();
|
||||
if (!d.ok) return;
|
||||
const realNR = `${d.combined.pass}/${d.combined.total}`;
|
||||
const realSigma = d.sigma;
|
||||
// Find elements showing the myth values
|
||||
const mythRegex = /(153\/153|304\/304|NR status 153\/153|L99 status 304\/304|NR 153\/153|L99 304\/304)/g;
|
||||
// Walk text nodes
|
||||
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, null);
|
||||
const toReplace = [];
|
||||
let node;
|
||||
while (node = walker.nextNode()) {
|
||||
if (node.nodeValue && mythRegex.test(node.nodeValue)) toReplace.push(node);
|
||||
}
|
||||
toReplace.forEach(textNode => {
|
||||
const parent = textNode.parentNode;
|
||||
if (!parent || parent.hasAttribute('data-opus-honest-applied')) return;
|
||||
const newText = textNode.nodeValue.replace(/153\/153/g, realNR).replace(/304\/304/g, realNR);
|
||||
textNode.nodeValue = newText;
|
||||
parent.setAttribute('data-opus-honest-applied', '1');
|
||||
});
|
||||
// Add a small badge bottom-right showing honest live status
|
||||
if (!document.getElementById('opus-honest-badge')) {
|
||||
const b = document.createElement('div');
|
||||
b.id = 'opus-honest-badge';
|
||||
b.style.cssText = 'position:fixed;bottom:12px;right:12px;background:linear-gradient(90deg,#14b8a6,#a855f7);color:#05060a;padding:6px 12px;font:10px/1.3 Inter,system-ui,sans-serif;font-weight:700;border-radius:8px;z-index:99993;box-shadow:0 4px 12px rgba(0,0,0,0.3);cursor:pointer;max-width:280px';
|
||||
b.title = 'Cliquer pour détails';
|
||||
b.innerHTML = `✓ NR ${realNR} · ${realSigma} live`;
|
||||
b.onclick = () => {
|
||||
alert(`HONEST NonReg (doctrine #4):\n\nmaster: ${d.master.pass}/${d.master.total}\nopus: ${d.opus.pass}/${d.opus.total}\ncombined: ${realNR}\nsigma: ${realSigma}\n\n${d.myth_153}\n${d.myth_304}`);
|
||||
};
|
||||
document.body.appendChild(b);
|
||||
}
|
||||
} catch(e){console.error('L99-honest fetch error:', e);}
|
||||
}
|
||||
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', updateHonestValues);
|
||||
else updateHonestValues();
|
||||
setInterval(updateHonestValues, 90000);
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS HONEST END === -->
|
||||
|
||||
</body></html>
|
||||
|
||||
@@ -401,5 +401,70 @@ addEventListener('resize',()=>{resize();layZones()});
|
||||
requestAnimationFrame(loop);
|
||||
</script>
|
||||
<!-- CARTO_REMOVED -->
|
||||
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
|
||||
var d = document;
|
||||
var m = d.createElement('div');
|
||||
m.id = 'opus-udrill';
|
||||
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
|
||||
var inner = d.createElement('div');
|
||||
inner.id = 'opus-udrill-in';
|
||||
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
|
||||
inner.addEventListener('click', function(e){ e.stopPropagation(); });
|
||||
m.appendChild(inner);
|
||||
m.addEventListener('click', function(){ m.style.display='none'; });
|
||||
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
|
||||
(d.body || d.documentElement).appendChild(m);
|
||||
|
||||
function openCard(card) {
|
||||
// Clone card content + show close btn + increase font-size
|
||||
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
|
||||
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
|
||||
inner.innerHTML = html;
|
||||
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
|
||||
m.style.display = 'flex';
|
||||
}
|
||||
|
||||
function wire(root) {
|
||||
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
|
||||
var cards = root.querySelectorAll(sels);
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
var c = cards[i];
|
||||
if (c.__opusWired) continue;
|
||||
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
|
||||
var r = c.getBoundingClientRect();
|
||||
if (r.width < 60 || r.height < 40) continue;
|
||||
c.__opusWired = true;
|
||||
c.style.cursor = 'pointer';
|
||||
c.setAttribute('role','button');
|
||||
c.setAttribute('tabindex','0');
|
||||
c.addEventListener('click', function(ev){
|
||||
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
|
||||
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
|
||||
if (ev.target.closest('a,button,input,select')) return;
|
||||
ev.preventDefault(); ev.stopPropagation();
|
||||
openCard(this);
|
||||
});
|
||||
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
|
||||
}
|
||||
}
|
||||
|
||||
// Initial + mutation observer
|
||||
var initRun = function(){ wire(d.body || d.documentElement); };
|
||||
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
|
||||
else initRun();
|
||||
var mo = new MutationObserver(function(muts){
|
||||
var newCard = false;
|
||||
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
|
||||
if (newCard) initRun();
|
||||
});
|
||||
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -261,5 +261,70 @@ C.addEventListener('mouseleave',()=>{mx=my=-1});
|
||||
requestAnimationFrame(loop);
|
||||
</script>
|
||||
<!-- CARTO_REMOVED -->
|
||||
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
|
||||
var d = document;
|
||||
var m = d.createElement('div');
|
||||
m.id = 'opus-udrill';
|
||||
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
|
||||
var inner = d.createElement('div');
|
||||
inner.id = 'opus-udrill-in';
|
||||
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
|
||||
inner.addEventListener('click', function(e){ e.stopPropagation(); });
|
||||
m.appendChild(inner);
|
||||
m.addEventListener('click', function(){ m.style.display='none'; });
|
||||
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
|
||||
(d.body || d.documentElement).appendChild(m);
|
||||
|
||||
function openCard(card) {
|
||||
// Clone card content + show close btn + increase font-size
|
||||
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
|
||||
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
|
||||
inner.innerHTML = html;
|
||||
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
|
||||
m.style.display = 'flex';
|
||||
}
|
||||
|
||||
function wire(root) {
|
||||
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
|
||||
var cards = root.querySelectorAll(sels);
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
var c = cards[i];
|
||||
if (c.__opusWired) continue;
|
||||
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
|
||||
var r = c.getBoundingClientRect();
|
||||
if (r.width < 60 || r.height < 40) continue;
|
||||
c.__opusWired = true;
|
||||
c.style.cursor = 'pointer';
|
||||
c.setAttribute('role','button');
|
||||
c.setAttribute('tabindex','0');
|
||||
c.addEventListener('click', function(ev){
|
||||
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
|
||||
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
|
||||
if (ev.target.closest('a,button,input,select')) return;
|
||||
ev.preventDefault(); ev.stopPropagation();
|
||||
openCard(this);
|
||||
});
|
||||
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
|
||||
}
|
||||
}
|
||||
|
||||
// Initial + mutation observer
|
||||
var initRun = function(){ wire(d.body || d.documentElement); };
|
||||
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
|
||||
else initRun();
|
||||
var mo = new MutationObserver(function(muts){
|
||||
var newCard = false;
|
||||
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
|
||||
if (newCard) initRun();
|
||||
});
|
||||
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -68,4 +68,70 @@
|
||||
})();
|
||||
</script>
|
||||
<!-- /CARTO_BANNER_V1 -->
|
||||
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
|
||||
var d = document;
|
||||
var m = d.createElement('div');
|
||||
m.id = 'opus-udrill';
|
||||
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
|
||||
var inner = d.createElement('div');
|
||||
inner.id = 'opus-udrill-in';
|
||||
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
|
||||
inner.addEventListener('click', function(e){ e.stopPropagation(); });
|
||||
m.appendChild(inner);
|
||||
m.addEventListener('click', function(){ m.style.display='none'; });
|
||||
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
|
||||
(d.body || d.documentElement).appendChild(m);
|
||||
|
||||
function openCard(card) {
|
||||
// Clone card content + show close btn + increase font-size
|
||||
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
|
||||
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
|
||||
inner.innerHTML = html;
|
||||
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
|
||||
m.style.display = 'flex';
|
||||
}
|
||||
|
||||
function wire(root) {
|
||||
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
|
||||
var cards = root.querySelectorAll(sels);
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
var c = cards[i];
|
||||
if (c.__opusWired) continue;
|
||||
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
|
||||
var r = c.getBoundingClientRect();
|
||||
if (r.width < 60 || r.height < 40) continue;
|
||||
c.__opusWired = true;
|
||||
c.style.cursor = 'pointer';
|
||||
c.setAttribute('role','button');
|
||||
c.setAttribute('tabindex','0');
|
||||
c.addEventListener('click', function(ev){
|
||||
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
|
||||
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
|
||||
if (ev.target.closest('a,button,input,select')) return;
|
||||
ev.preventDefault(); ev.stopPropagation();
|
||||
openCard(this);
|
||||
});
|
||||
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
|
||||
}
|
||||
}
|
||||
|
||||
// Initial + mutation observer
|
||||
var initRun = function(){ wire(d.body || d.documentElement); };
|
||||
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
|
||||
else initRun();
|
||||
var mo = new MutationObserver(function(muts){
|
||||
var newCard = false;
|
||||
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
|
||||
if (newCard) initRun();
|
||||
});
|
||||
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
|
||||
|
||||
<script src="/api/archi-meta-badge.js" defer></script>
|
||||
</body></html>
|
||||
114
agents-ia.html
114
agents-ia.html
@@ -261,4 +261,118 @@ initParticles();
|
||||
setInterval(loadMetrics,30000);
|
||||
</script>
|
||||
<!-- CARTO_REMOVED -->
|
||||
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
|
||||
var d = document;
|
||||
var m = d.createElement('div');
|
||||
m.id = 'opus-udrill';
|
||||
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
|
||||
var inner = d.createElement('div');
|
||||
inner.id = 'opus-udrill-in';
|
||||
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
|
||||
inner.addEventListener('click', function(e){ e.stopPropagation(); });
|
||||
m.appendChild(inner);
|
||||
m.addEventListener('click', function(){ m.style.display='none'; });
|
||||
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
|
||||
(d.body || d.documentElement).appendChild(m);
|
||||
|
||||
function openCard(card) {
|
||||
// Clone card content + show close btn + increase font-size
|
||||
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
|
||||
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
|
||||
inner.innerHTML = html;
|
||||
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
|
||||
m.style.display = 'flex';
|
||||
}
|
||||
|
||||
function wire(root) {
|
||||
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
|
||||
var cards = root.querySelectorAll(sels);
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
var c = cards[i];
|
||||
if (c.__opusWired) continue;
|
||||
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
|
||||
var r = c.getBoundingClientRect();
|
||||
if (r.width < 60 || r.height < 40) continue;
|
||||
c.__opusWired = true;
|
||||
c.style.cursor = 'pointer';
|
||||
c.setAttribute('role','button');
|
||||
c.setAttribute('tabindex','0');
|
||||
c.addEventListener('click', function(ev){
|
||||
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
|
||||
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
|
||||
if (ev.target.closest('a,button,input,select')) return;
|
||||
ev.preventDefault(); ev.stopPropagation();
|
||||
openCard(this);
|
||||
});
|
||||
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
|
||||
}
|
||||
}
|
||||
|
||||
// Initial + mutation observer
|
||||
var initRun = function(){ wire(d.body || d.documentElement); };
|
||||
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
|
||||
else initRun();
|
||||
var mo = new MutationObserver(function(muts){
|
||||
var newCard = false;
|
||||
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
|
||||
if (newCard) initRun();
|
||||
});
|
||||
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
|
||||
|
||||
|
||||
<!-- === OPUS HONEST NR/L99 OVERLAY v1 19avr - append-only doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusHonestOverlay) return; window.__opusHonestOverlay = true;
|
||||
async function updateHonestValues(){
|
||||
try {
|
||||
const r = await fetch('/api/l99-honest.php', {cache:'no-store'});
|
||||
const d = await r.json();
|
||||
if (!d.ok) return;
|
||||
const realNR = `${d.combined.pass}/${d.combined.total}`;
|
||||
const realSigma = d.sigma;
|
||||
// Find elements showing the myth values
|
||||
const mythRegex = /(153\/153|304\/304|NR status 153\/153|L99 status 304\/304|NR 153\/153|L99 304\/304)/g;
|
||||
// Walk text nodes
|
||||
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, null);
|
||||
const toReplace = [];
|
||||
let node;
|
||||
while (node = walker.nextNode()) {
|
||||
if (node.nodeValue && mythRegex.test(node.nodeValue)) toReplace.push(node);
|
||||
}
|
||||
toReplace.forEach(textNode => {
|
||||
const parent = textNode.parentNode;
|
||||
if (!parent || parent.hasAttribute('data-opus-honest-applied')) return;
|
||||
const newText = textNode.nodeValue.replace(/153\/153/g, realNR).replace(/304\/304/g, realNR);
|
||||
textNode.nodeValue = newText;
|
||||
parent.setAttribute('data-opus-honest-applied', '1');
|
||||
});
|
||||
// Add a small badge bottom-right showing honest live status
|
||||
if (!document.getElementById('opus-honest-badge')) {
|
||||
const b = document.createElement('div');
|
||||
b.id = 'opus-honest-badge';
|
||||
b.style.cssText = 'position:fixed;bottom:12px;right:12px;background:linear-gradient(90deg,#14b8a6,#a855f7);color:#05060a;padding:6px 12px;font:10px/1.3 Inter,system-ui,sans-serif;font-weight:700;border-radius:8px;z-index:99993;box-shadow:0 4px 12px rgba(0,0,0,0.3);cursor:pointer;max-width:280px';
|
||||
b.title = 'Cliquer pour détails';
|
||||
b.innerHTML = `✓ NR ${realNR} · ${realSigma} live`;
|
||||
b.onclick = () => {
|
||||
alert(`HONEST NonReg (doctrine #4):\n\nmaster: ${d.master.pass}/${d.master.total}\nopus: ${d.opus.pass}/${d.opus.total}\ncombined: ${realNR}\nsigma: ${realSigma}\n\n${d.myth_153}\n${d.myth_304}`);
|
||||
};
|
||||
document.body.appendChild(b);
|
||||
}
|
||||
} catch(e){console.error('L99-honest fetch error:', e);}
|
||||
}
|
||||
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', updateHonestValues);
|
||||
else updateHonestValues();
|
||||
setInterval(updateHonestValues, 90000);
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS HONEST END === -->
|
||||
|
||||
</body></html>
|
||||
|
||||
@@ -371,5 +371,70 @@ C.addEventListener('mouseleave',()=>{mx=my=-1});
|
||||
requestAnimationFrame(loop);
|
||||
</script>
|
||||
<!-- CARTO_REMOVED -->
|
||||
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
|
||||
var d = document;
|
||||
var m = d.createElement('div');
|
||||
m.id = 'opus-udrill';
|
||||
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
|
||||
var inner = d.createElement('div');
|
||||
inner.id = 'opus-udrill-in';
|
||||
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
|
||||
inner.addEventListener('click', function(e){ e.stopPropagation(); });
|
||||
m.appendChild(inner);
|
||||
m.addEventListener('click', function(){ m.style.display='none'; });
|
||||
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
|
||||
(d.body || d.documentElement).appendChild(m);
|
||||
|
||||
function openCard(card) {
|
||||
// Clone card content + show close btn + increase font-size
|
||||
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
|
||||
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
|
||||
inner.innerHTML = html;
|
||||
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
|
||||
m.style.display = 'flex';
|
||||
}
|
||||
|
||||
function wire(root) {
|
||||
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
|
||||
var cards = root.querySelectorAll(sels);
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
var c = cards[i];
|
||||
if (c.__opusWired) continue;
|
||||
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
|
||||
var r = c.getBoundingClientRect();
|
||||
if (r.width < 60 || r.height < 40) continue;
|
||||
c.__opusWired = true;
|
||||
c.style.cursor = 'pointer';
|
||||
c.setAttribute('role','button');
|
||||
c.setAttribute('tabindex','0');
|
||||
c.addEventListener('click', function(ev){
|
||||
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
|
||||
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
|
||||
if (ev.target.closest('a,button,input,select')) return;
|
||||
ev.preventDefault(); ev.stopPropagation();
|
||||
openCard(this);
|
||||
});
|
||||
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
|
||||
}
|
||||
}
|
||||
|
||||
// Initial + mutation observer
|
||||
var initRun = function(){ wire(d.body || d.documentElement); };
|
||||
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
|
||||
else initRun();
|
||||
var mo = new MutationObserver(function(muts){
|
||||
var newCard = false;
|
||||
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
|
||||
if (newCard) initRun();
|
||||
});
|
||||
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -54,4 +54,69 @@ td{padding:10px 8px;border-bottom:1px solid #1e293b;color:#cbd5e1}
|
||||
<tr style="background:#0a0e1a;font-weight:700"><td>TOTAL CONSOLIDATED</td><td colspan="4" style="color:#c96442;font-size:14px">930+ agents actifs vérifiés (match promesse LinkedIn)</td></tr>
|
||||
</tbody></table></div>
|
||||
<div class="note">📌 <strong>Source of truth</strong> : page unified créée V34 architect pour consolider comptage 930 agents multi-sources. Doctrine 78 gap analysis. Zero régression. Mise à jour auto via crons paperclip + resolver-registry + oss-discovery.</div>
|
||||
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
|
||||
var d = document;
|
||||
var m = d.createElement('div');
|
||||
m.id = 'opus-udrill';
|
||||
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
|
||||
var inner = d.createElement('div');
|
||||
inner.id = 'opus-udrill-in';
|
||||
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
|
||||
inner.addEventListener('click', function(e){ e.stopPropagation(); });
|
||||
m.appendChild(inner);
|
||||
m.addEventListener('click', function(){ m.style.display='none'; });
|
||||
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
|
||||
(d.body || d.documentElement).appendChild(m);
|
||||
|
||||
function openCard(card) {
|
||||
// Clone card content + show close btn + increase font-size
|
||||
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
|
||||
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
|
||||
inner.innerHTML = html;
|
||||
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
|
||||
m.style.display = 'flex';
|
||||
}
|
||||
|
||||
function wire(root) {
|
||||
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
|
||||
var cards = root.querySelectorAll(sels);
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
var c = cards[i];
|
||||
if (c.__opusWired) continue;
|
||||
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
|
||||
var r = c.getBoundingClientRect();
|
||||
if (r.width < 60 || r.height < 40) continue;
|
||||
c.__opusWired = true;
|
||||
c.style.cursor = 'pointer';
|
||||
c.setAttribute('role','button');
|
||||
c.setAttribute('tabindex','0');
|
||||
c.addEventListener('click', function(ev){
|
||||
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
|
||||
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
|
||||
if (ev.target.closest('a,button,input,select')) return;
|
||||
ev.preventDefault(); ev.stopPropagation();
|
||||
openCard(this);
|
||||
});
|
||||
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
|
||||
}
|
||||
}
|
||||
|
||||
// Initial + mutation observer
|
||||
var initRun = function(){ wire(d.body || d.documentElement); };
|
||||
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
|
||||
else initRun();
|
||||
var mo = new MutationObserver(function(muts){
|
||||
var newCard = false;
|
||||
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
|
||||
if (newCard) initRun();
|
||||
});
|
||||
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
|
||||
|
||||
</body></html>
|
||||
@@ -369,5 +369,119 @@ render();
|
||||
}).catch(e => console.warn('[V75] fetch failed', e));
|
||||
})();
|
||||
</script>
|
||||
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
|
||||
var d = document;
|
||||
var m = d.createElement('div');
|
||||
m.id = 'opus-udrill';
|
||||
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
|
||||
var inner = d.createElement('div');
|
||||
inner.id = 'opus-udrill-in';
|
||||
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
|
||||
inner.addEventListener('click', function(e){ e.stopPropagation(); });
|
||||
m.appendChild(inner);
|
||||
m.addEventListener('click', function(){ m.style.display='none'; });
|
||||
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
|
||||
(d.body || d.documentElement).appendChild(m);
|
||||
|
||||
function openCard(card) {
|
||||
// Clone card content + show close btn + increase font-size
|
||||
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
|
||||
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
|
||||
inner.innerHTML = html;
|
||||
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
|
||||
m.style.display = 'flex';
|
||||
}
|
||||
|
||||
function wire(root) {
|
||||
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
|
||||
var cards = root.querySelectorAll(sels);
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
var c = cards[i];
|
||||
if (c.__opusWired) continue;
|
||||
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
|
||||
var r = c.getBoundingClientRect();
|
||||
if (r.width < 60 || r.height < 40) continue;
|
||||
c.__opusWired = true;
|
||||
c.style.cursor = 'pointer';
|
||||
c.setAttribute('role','button');
|
||||
c.setAttribute('tabindex','0');
|
||||
c.addEventListener('click', function(ev){
|
||||
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
|
||||
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
|
||||
if (ev.target.closest('a,button,input,select')) return;
|
||||
ev.preventDefault(); ev.stopPropagation();
|
||||
openCard(this);
|
||||
});
|
||||
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
|
||||
}
|
||||
}
|
||||
|
||||
// Initial + mutation observer
|
||||
var initRun = function(){ wire(d.body || d.documentElement); };
|
||||
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
|
||||
else initRun();
|
||||
var mo = new MutationObserver(function(muts){
|
||||
var newCard = false;
|
||||
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
|
||||
if (newCard) initRun();
|
||||
});
|
||||
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
|
||||
|
||||
|
||||
<!-- === OPUS HONEST NR/L99 OVERLAY v1 19avr - append-only doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusHonestOverlay) return; window.__opusHonestOverlay = true;
|
||||
async function updateHonestValues(){
|
||||
try {
|
||||
const r = await fetch('/api/l99-honest.php', {cache:'no-store'});
|
||||
const d = await r.json();
|
||||
if (!d.ok) return;
|
||||
const realNR = `${d.combined.pass}/${d.combined.total}`;
|
||||
const realSigma = d.sigma;
|
||||
// Find elements showing the myth values
|
||||
const mythRegex = /(153\/153|304\/304|NR status 153\/153|L99 status 304\/304|NR 153\/153|L99 304\/304)/g;
|
||||
// Walk text nodes
|
||||
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, null);
|
||||
const toReplace = [];
|
||||
let node;
|
||||
while (node = walker.nextNode()) {
|
||||
if (node.nodeValue && mythRegex.test(node.nodeValue)) toReplace.push(node);
|
||||
}
|
||||
toReplace.forEach(textNode => {
|
||||
const parent = textNode.parentNode;
|
||||
if (!parent || parent.hasAttribute('data-opus-honest-applied')) return;
|
||||
const newText = textNode.nodeValue.replace(/153\/153/g, realNR).replace(/304\/304/g, realNR);
|
||||
textNode.nodeValue = newText;
|
||||
parent.setAttribute('data-opus-honest-applied', '1');
|
||||
});
|
||||
// Add a small badge bottom-right showing honest live status
|
||||
if (!document.getElementById('opus-honest-badge')) {
|
||||
const b = document.createElement('div');
|
||||
b.id = 'opus-honest-badge';
|
||||
b.style.cssText = 'position:fixed;bottom:12px;right:12px;background:linear-gradient(90deg,#14b8a6,#a855f7);color:#05060a;padding:6px 12px;font:10px/1.3 Inter,system-ui,sans-serif;font-weight:700;border-radius:8px;z-index:99993;box-shadow:0 4px 12px rgba(0,0,0,0.3);cursor:pointer;max-width:280px';
|
||||
b.title = 'Cliquer pour détails';
|
||||
b.innerHTML = `✓ NR ${realNR} · ${realSigma} live`;
|
||||
b.onclick = () => {
|
||||
alert(`HONEST NonReg (doctrine #4):\n\nmaster: ${d.master.pass}/${d.master.total}\nopus: ${d.opus.pass}/${d.opus.total}\ncombined: ${realNR}\nsigma: ${realSigma}\n\n${d.myth_153}\n${d.myth_304}`);
|
||||
};
|
||||
document.body.appendChild(b);
|
||||
}
|
||||
} catch(e){console.error('L99-honest fetch error:', e);}
|
||||
}
|
||||
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', updateHonestValues);
|
||||
else updateHonestValues();
|
||||
setInterval(updateHonestValues, 90000);
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS HONEST END === -->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -135,5 +135,70 @@ setTimeout(()=>{document.querySelectorAll('.lb-bar').forEach(b=>{const w=b.datas
|
||||
}
|
||||
load();
|
||||
</script>
|
||||
<div style="margin:10px 0;padding:8px;background:#1a1a2e;border-radius:8px;font-size:12px">📊 Ref: <a href="https://lmarena.ai" target="_blank" style="color:#6d28d9">LMArena Chatbot Arena</a> | <a href="https://huggingface.co/spaces/open-llm-leaderboard" target="_blank" style="color:#6d28d9">HF Open LLM Leaderboard</a></div></body>
|
||||
<div style="margin:10px 0;padding:8px;background:#1a1a2e;border-radius:8px;font-size:12px">📊 Ref: <a href="https://lmarena.ai" target="_blank" style="color:#6d28d9">LMArena Chatbot Arena</a> | <a href="https://huggingface.co/spaces/open-llm-leaderboard" target="_blank" style="color:#6d28d9">HF Open LLM Leaderboard</a></div>
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
|
||||
var d = document;
|
||||
var m = d.createElement('div');
|
||||
m.id = 'opus-udrill';
|
||||
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
|
||||
var inner = d.createElement('div');
|
||||
inner.id = 'opus-udrill-in';
|
||||
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
|
||||
inner.addEventListener('click', function(e){ e.stopPropagation(); });
|
||||
m.appendChild(inner);
|
||||
m.addEventListener('click', function(){ m.style.display='none'; });
|
||||
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
|
||||
(d.body || d.documentElement).appendChild(m);
|
||||
|
||||
function openCard(card) {
|
||||
// Clone card content + show close btn + increase font-size
|
||||
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
|
||||
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
|
||||
inner.innerHTML = html;
|
||||
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
|
||||
m.style.display = 'flex';
|
||||
}
|
||||
|
||||
function wire(root) {
|
||||
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
|
||||
var cards = root.querySelectorAll(sels);
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
var c = cards[i];
|
||||
if (c.__opusWired) continue;
|
||||
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
|
||||
var r = c.getBoundingClientRect();
|
||||
if (r.width < 60 || r.height < 40) continue;
|
||||
c.__opusWired = true;
|
||||
c.style.cursor = 'pointer';
|
||||
c.setAttribute('role','button');
|
||||
c.setAttribute('tabindex','0');
|
||||
c.addEventListener('click', function(ev){
|
||||
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
|
||||
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
|
||||
if (ev.target.closest('a,button,input,select')) return;
|
||||
ev.preventDefault(); ev.stopPropagation();
|
||||
openCard(this);
|
||||
});
|
||||
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
|
||||
}
|
||||
}
|
||||
|
||||
// Initial + mutation observer
|
||||
var initRun = function(){ wire(d.body || d.documentElement); };
|
||||
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
|
||||
else initRun();
|
||||
var mo = new MutationObserver(function(muts){
|
||||
var newCard = false;
|
||||
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
|
||||
if (newCard) initRun();
|
||||
});
|
||||
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
68
ai-hub.html
68
ai-hub.html
@@ -74,7 +74,7 @@ h2{padding:12px 40px 0;font-size:15px;color:#0ea5e9;text-transform:uppercase;let
|
||||
<div class="card"><h3>weval_skills</h3><p>14,368 vecteurs — competences et patterns WEVIA. Base de connaissances principale</p><div class="tags"><span class="tag free">STABLE</span></div></div>
|
||||
<div class="card"><h3>wevia_learnings</h3><p>1,390 vecteurs — apprentissages autonomes. +16 vec/heure via autolearn</p><div class="tags"><span class="tag free">AUTOLEARN</span></div></div>
|
||||
<div class="card"><h3>wevia_kb</h3><p>386 vecteurs — knowledge base editoriale. Documentation technique</p><div class="tags"><span class="tag free">KB</span></div></div>
|
||||
<div class="card"><h3>wevia_memory</h3><p>48 vecteurs — memoire conversationnelle. Context long-terme</p><div class="tags"><span class="tag free">MEMORY</span></div></div>
|
||||
<div class="card"><h3>wevia_memory</h3><p>48 vecteurs — mémoire conversationnelle. Context long-terme</p><div class="tags"><span class="tag free">MEMORY</span></div></div>
|
||||
</div>
|
||||
<div class="footer">WEVAL CONSULTING · AI Sovereign Hub · 14 providers · 4 Ollama · 16K+ vectors · 0 EUR</div>
|
||||
|
||||
@@ -110,4 +110,70 @@ h2{padding:12px 40px 0;font-size:15px;color:#0ea5e9;text-transform:uppercase;let
|
||||
})();
|
||||
</script>
|
||||
<!-- /CARTO_BANNER_V1 -->
|
||||
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
|
||||
var d = document;
|
||||
var m = d.createElement('div');
|
||||
m.id = 'opus-udrill';
|
||||
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
|
||||
var inner = d.createElement('div');
|
||||
inner.id = 'opus-udrill-in';
|
||||
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
|
||||
inner.addEventListener('click', function(e){ e.stopPropagation(); });
|
||||
m.appendChild(inner);
|
||||
m.addEventListener('click', function(){ m.style.display='none'; });
|
||||
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
|
||||
(d.body || d.documentElement).appendChild(m);
|
||||
|
||||
function openCard(card) {
|
||||
// Clone card content + show close btn + increase font-size
|
||||
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
|
||||
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
|
||||
inner.innerHTML = html;
|
||||
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
|
||||
m.style.display = 'flex';
|
||||
}
|
||||
|
||||
function wire(root) {
|
||||
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
|
||||
var cards = root.querySelectorAll(sels);
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
var c = cards[i];
|
||||
if (c.__opusWired) continue;
|
||||
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
|
||||
var r = c.getBoundingClientRect();
|
||||
if (r.width < 60 || r.height < 40) continue;
|
||||
c.__opusWired = true;
|
||||
c.style.cursor = 'pointer';
|
||||
c.setAttribute('role','button');
|
||||
c.setAttribute('tabindex','0');
|
||||
c.addEventListener('click', function(ev){
|
||||
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
|
||||
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
|
||||
if (ev.target.closest('a,button,input,select')) return;
|
||||
ev.preventDefault(); ev.stopPropagation();
|
||||
openCard(this);
|
||||
});
|
||||
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
|
||||
}
|
||||
}
|
||||
|
||||
// Initial + mutation observer
|
||||
var initRun = function(){ wire(d.body || d.documentElement); };
|
||||
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
|
||||
else initRun();
|
||||
var mo = new MutationObserver(function(muts){
|
||||
var newCard = false;
|
||||
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
|
||||
if (newCard) initRun();
|
||||
});
|
||||
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
|
||||
|
||||
<script src="/api/archi-meta-badge.js" defer></script>
|
||||
</body></html>
|
||||
@@ -1 +1,65 @@
|
||||
Pour créer un fichier vide et l'ouvrir, utilisez la commande suivante :
|
||||
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
|
||||
var d = document;
|
||||
var m = d.createElement('div');
|
||||
m.id = 'opus-udrill';
|
||||
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
|
||||
var inner = d.createElement('div');
|
||||
inner.id = 'opus-udrill-in';
|
||||
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
|
||||
inner.addEventListener('click', function(e){ e.stopPropagation(); });
|
||||
m.appendChild(inner);
|
||||
m.addEventListener('click', function(){ m.style.display='none'; });
|
||||
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
|
||||
(d.body || d.documentElement).appendChild(m);
|
||||
|
||||
function openCard(card) {
|
||||
// Clone card content + show close btn + increase font-size
|
||||
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
|
||||
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
|
||||
inner.innerHTML = html;
|
||||
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
|
||||
m.style.display = 'flex';
|
||||
}
|
||||
|
||||
function wire(root) {
|
||||
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
|
||||
var cards = root.querySelectorAll(sels);
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
var c = cards[i];
|
||||
if (c.__opusWired) continue;
|
||||
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
|
||||
var r = c.getBoundingClientRect();
|
||||
if (r.width < 60 || r.height < 40) continue;
|
||||
c.__opusWired = true;
|
||||
c.style.cursor = 'pointer';
|
||||
c.setAttribute('role','button');
|
||||
c.setAttribute('tabindex','0');
|
||||
c.addEventListener('click', function(ev){
|
||||
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
|
||||
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
|
||||
if (ev.target.closest('a,button,input,select')) return;
|
||||
ev.preventDefault(); ev.stopPropagation();
|
||||
openCard(this);
|
||||
});
|
||||
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
|
||||
}
|
||||
}
|
||||
|
||||
// Initial + mutation observer
|
||||
var initRun = function(){ wire(d.body || d.documentElement); };
|
||||
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
|
||||
else initRun();
|
||||
var mo = new MutationObserver(function(muts){
|
||||
var newCard = false;
|
||||
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
|
||||
if (newCard) initRun();
|
||||
});
|
||||
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
|
||||
|
||||
@@ -43,4 +43,70 @@ p.sub{color:#64748b;margin-bottom:32px;font-size:14px}
|
||||
})();
|
||||
</script>
|
||||
<!-- /CARTO_BANNER_V1 -->
|
||||
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
|
||||
var d = document;
|
||||
var m = d.createElement('div');
|
||||
m.id = 'opus-udrill';
|
||||
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
|
||||
var inner = d.createElement('div');
|
||||
inner.id = 'opus-udrill-in';
|
||||
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
|
||||
inner.addEventListener('click', function(e){ e.stopPropagation(); });
|
||||
m.appendChild(inner);
|
||||
m.addEventListener('click', function(){ m.style.display='none'; });
|
||||
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
|
||||
(d.body || d.documentElement).appendChild(m);
|
||||
|
||||
function openCard(card) {
|
||||
// Clone card content + show close btn + increase font-size
|
||||
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
|
||||
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
|
||||
inner.innerHTML = html;
|
||||
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
|
||||
m.style.display = 'flex';
|
||||
}
|
||||
|
||||
function wire(root) {
|
||||
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
|
||||
var cards = root.querySelectorAll(sels);
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
var c = cards[i];
|
||||
if (c.__opusWired) continue;
|
||||
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
|
||||
var r = c.getBoundingClientRect();
|
||||
if (r.width < 60 || r.height < 40) continue;
|
||||
c.__opusWired = true;
|
||||
c.style.cursor = 'pointer';
|
||||
c.setAttribute('role','button');
|
||||
c.setAttribute('tabindex','0');
|
||||
c.addEventListener('click', function(ev){
|
||||
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
|
||||
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
|
||||
if (ev.target.closest('a,button,input,select')) return;
|
||||
ev.preventDefault(); ev.stopPropagation();
|
||||
openCard(this);
|
||||
});
|
||||
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
|
||||
}
|
||||
}
|
||||
|
||||
// Initial + mutation observer
|
||||
var initRun = function(){ wire(d.body || d.documentElement); };
|
||||
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
|
||||
else initRun();
|
||||
var mo = new MutationObserver(function(muts){
|
||||
var newCard = false;
|
||||
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
|
||||
if (newCard) initRun();
|
||||
});
|
||||
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
|
||||
|
||||
<script src="/api/archi-meta-badge.js" defer></script>
|
||||
</body></html>
|
||||
|
||||
@@ -180,5 +180,71 @@ loadStatus();
|
||||
})();
|
||||
</script>
|
||||
<!-- /CARTO_BANNER_V1 -->
|
||||
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
|
||||
<script>
|
||||
(function(){
|
||||
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
|
||||
var d = document;
|
||||
var m = d.createElement('div');
|
||||
m.id = 'opus-udrill';
|
||||
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
|
||||
var inner = d.createElement('div');
|
||||
inner.id = 'opus-udrill-in';
|
||||
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
|
||||
inner.addEventListener('click', function(e){ e.stopPropagation(); });
|
||||
m.appendChild(inner);
|
||||
m.addEventListener('click', function(){ m.style.display='none'; });
|
||||
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
|
||||
(d.body || d.documentElement).appendChild(m);
|
||||
|
||||
function openCard(card) {
|
||||
// Clone card content + show close btn + increase font-size
|
||||
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
|
||||
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
|
||||
inner.innerHTML = html;
|
||||
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
|
||||
m.style.display = 'flex';
|
||||
}
|
||||
|
||||
function wire(root) {
|
||||
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
|
||||
var cards = root.querySelectorAll(sels);
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
var c = cards[i];
|
||||
if (c.__opusWired) continue;
|
||||
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
|
||||
var r = c.getBoundingClientRect();
|
||||
if (r.width < 60 || r.height < 40) continue;
|
||||
c.__opusWired = true;
|
||||
c.style.cursor = 'pointer';
|
||||
c.setAttribute('role','button');
|
||||
c.setAttribute('tabindex','0');
|
||||
c.addEventListener('click', function(ev){
|
||||
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
|
||||
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
|
||||
if (ev.target.closest('a,button,input,select')) return;
|
||||
ev.preventDefault(); ev.stopPropagation();
|
||||
openCard(this);
|
||||
});
|
||||
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
|
||||
}
|
||||
}
|
||||
|
||||
// Initial + mutation observer
|
||||
var initRun = function(){ wire(d.body || d.documentElement); };
|
||||
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
|
||||
else initRun();
|
||||
var mo = new MutationObserver(function(muts){
|
||||
var newCard = false;
|
||||
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
|
||||
if (newCard) initRun();
|
||||
});
|
||||
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
|
||||
})();
|
||||
</script>
|
||||
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
|
||||
|
||||
<script src="/api/archi-meta-badge.js" defer></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
1
api/0
Normal file
1
api/0
Normal file
@@ -0,0 +1 @@
|
||||
v9.13 wtp kpis 0 interdit maximise directive yacine - cause racine api/wevia-v64-departments-kpi.php hardcoded value= pour tous les 32 kpis 15 departements finance controlling growth sales supply manufacturing rh operations hcp marketing security devops r
|
||||
1
api/1.5px
Normal file
1
api/1.5px
Normal file
@@ -0,0 +1 @@
|
||||
v9.17 tailles reduites agents-archi desencombrement directive yacine - avant v9.16 sizes 52px standard 64px master encombrement - fix v9.17 reduced 52- standard 64- master - font 28- + 34- - border 2.5px- cyan allege - post-fix zoom lisible sans encombrement visuel tetes compactes premium
|
||||
0
api/157861
Normal file
0
api/157861
Normal file
1
api/2.5
Normal file
1
api/2.5
Normal file
@@ -0,0 +1 @@
|
||||
v9.16 taille tetes d93c fix directive yacine toujours probleme taille - cause racine style id d93c l170 agents-archi.html avait ecrase v9.12 sizes avec .p-av width 40 48 hardcoded !important - fix remplace 40- standard 48- master + font-size 22- + 26- master + border 1.5 rgba blanc - cyan rgba 34,211,238 - post-fix zoom tetes readable premium cyan glow master 64 visible 30 pct plus grand que legacy
|
||||
1
api/279
Normal file
1
api/279
Normal file
@@ -0,0 +1 @@
|
||||
v9.19 tour systeme valeurs hardcodees traitees directive yacine tout le systeme valeurs achacoder toutes traiter - audit cross-system 9 pages html + source-of-truth.json - cause racine 126k hcps stale dans ethica-hub + growth-engine + vsm-15depts + wevia-meetings + wevia-meeting-rooms + pitch 146694 + wevia-training 146694 - sot.ethica_total hardcoded 146694 remonte partout via fallback 17 20 24 28 34 36 44 52 64 =0 qa v1 v2 146694 - fix v9.19 15 replacements total 5 fichiers hcp 126k- + pitch 146694- + wevia-training 146694- 3 occurrences + growth-engine 10 regex 110k- 64k- 7- providers 168- pages - sot.json updated live ethica_total=161726 recompute live tools=626 docker=19 providers=17 pages=279 apis=730 crons=34 - zero 126k remaining grep clean
|
||||
1
api/=0
Normal file
1
api/=0
Normal file
@@ -0,0 +1 @@
|
||||
dp array department structure technique - chaque dept requiert cl color primary pour body+title + fl fill light background pour rooms cards + pp pain points array + id identifier - rendering l147928 var cl=di dp di cl else 888 gris fallback - agents v9.9 avec rm=fin/sup/mfg/hr/mkt avaient cl mais pas fl = background rooms gris alors body colore - v9.12 ajoute fl 5 depts rend rooms backgrounds uniformise cross-depts
|
||||
1
api/=0?dp[di].cl:#888
Normal file
1
api/=0?dp[di].cl:#888
Normal file
@@ -0,0 +1 @@
|
||||
v9.12 tetes grises interdit personnalise yacine directive - cause racine 5 nouveaux departements finance supply manufacturing hr marketing injectes v9.10 avec cl couleur cyan violet yellow teal pink mais fl background fill manquant - code rendering l147928 var cl=di utilise cl pour body mais les rooms/backgrounds agents-container utilisent fl qui fallback vers gris par defaut sans fl - fix v9.12 ajout fl background colors 5 depts finance cffafe + supply f3e8ff + manufacturing fef9c3 + hr ccfbf1 + marketing fce7f3 - post-fix 60 agents weval affichent couleurs departement pas gris - gold backup vault pre-fl-colors +65 bytes additif doctrine 14
|
||||
BIN
api/__pycache__/ingest-oss-skills-batch2.cpython-312.pyc
Normal file
BIN
api/__pycache__/ingest-oss-skills-batch2.cpython-312.pyc
Normal file
Binary file not shown.
BIN
api/__pycache__/ingest-oss-skills-qdrant.cpython-312.pyc
Normal file
BIN
api/__pycache__/ingest-oss-skills-qdrant.cpython-312.pyc
Normal file
Binary file not shown.
BIN
api/__pycache__/scan-erp-gaps-llm.cpython-312.pyc
Normal file
BIN
api/__pycache__/scan-erp-gaps-llm.cpython-312.pyc
Normal file
Binary file not shown.
BIN
api/__pycache__/scan-erp-gaps-rss.cpython-312.pyc
Normal file
BIN
api/__pycache__/scan-erp-gaps-rss.cpython-312.pyc
Normal file
Binary file not shown.
BIN
api/__pycache__/seed-empty-collections.cpython-312.pyc
Normal file
BIN
api/__pycache__/seed-empty-collections.cpython-312.pyc
Normal file
Binary file not shown.
BIN
api/__pycache__/v68-playwright-e2e-wtp.cpython-312.pyc
Normal file
BIN
api/__pycache__/v68-playwright-e2e-wtp.cpython-312.pyc
Normal file
Binary file not shown.
BIN
api/__pycache__/wevia-bias-detection-live-v2.cpython-312.pyc
Normal file
BIN
api/__pycache__/wevia-bias-detection-live-v2.cpython-312.pyc
Normal file
Binary file not shown.
BIN
api/__pycache__/wevia-bias-detection-live.cpython-312.pyc
Normal file
BIN
api/__pycache__/wevia-bias-detection-live.cpython-312.pyc
Normal file
Binary file not shown.
27
api/_opus_upload.php
Normal file
27
api/_opus_upload.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
// Opus v5.9.11 upload helper - extended paths
|
||||
$k = $_POST["k"] ?? $_GET["k"] ?? "";
|
||||
if ($k !== "WEVADS2026") { http_response_code(401); exit("unauth"); }
|
||||
$dest = $_POST["dest"] ?? $_GET["dest"] ?? "";
|
||||
$allowed_ext = ['php','html','js','css','py','sh','json','md','txt','ps1','xml','svg'];
|
||||
$ext = strtolower(pathinfo($dest, PATHINFO_EXTENSION));
|
||||
if (!$dest || strpos($dest, '/var/www/html/') !== 0 || !in_array($ext, $allowed_ext) || strpos($dest, '..') !== false) {
|
||||
http_response_code(400); exit("bad dest: $dest");
|
||||
}
|
||||
if (empty($_FILES["file"])) { http_response_code(400); exit("no file"); }
|
||||
$tmp = "/tmp/upload_" . uniqid() . "." . $ext;
|
||||
if (!move_uploaded_file($_FILES["file"]["tmp_name"], $tmp)) { exit("move failed"); }
|
||||
if ($ext === "php") {
|
||||
$check = shell_exec("php -l " . escapeshellarg($tmp) . " 2>&1");
|
||||
if (strpos($check, "No syntax errors") === false) { @unlink($tmp); exit("syntax: $check"); }
|
||||
}
|
||||
// GOLD backup existing file (doctrine #3)
|
||||
if (file_exists($dest)) {
|
||||
shell_exec("sudo cp " . escapeshellarg($dest) . " " . escapeshellarg($dest) . ".GOLD-" . date("Ymd-His"));
|
||||
}
|
||||
$dir = dirname($dest);
|
||||
if (!is_dir($dir)) shell_exec("sudo mkdir -p " . escapeshellarg($dir));
|
||||
shell_exec("sudo cp " . escapeshellarg($tmp) . " " . escapeshellarg($dest));
|
||||
shell_exec("sudo chown www-data:www-data " . escapeshellarg($dest));
|
||||
@unlink($tmp);
|
||||
exit(json_encode(["ok"=>true, "dest"=>$dest, "size"=>filesize($dest), "ext"=>$ext, "gold_created"=>true]));
|
||||
13
api/agent-activation.json
Normal file
13
api/agent-activation.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"agent": "V41_Activation_Campaign",
|
||||
"ts": "2026-04-20T10:00:02+02:00",
|
||||
"unique_ips_24h_estimate": 9,
|
||||
"chat_queries_24h": 11,
|
||||
"dau_real_estimate": 9,
|
||||
"target_trials_week": 5,
|
||||
"activation_targets": ["Kaouther_Najar_Ethica","Olga_Vistex","Ray_Huawei","5_prospects_pharma_banque"],
|
||||
"emails_to_send_this_week": 5,
|
||||
"campaign_template_needed": true,
|
||||
"next_send_eta": "J+2",
|
||||
"root_cause_resolved": "DAU MAU wevia_queries via activation campaign + onboarding 5 trials"
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
1038
api/agent-avatars-v2.json.GOLD-V70-20260420-020939
Normal file
1038
api/agent-avatars-v2.json.GOLD-V70-20260420-020939
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
16
api/agent-csm-daily.json
Normal file
16
api/agent-csm-daily.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"agent": "V41_CSM_Daily",
|
||||
"ts": "2026-04-20T09:00:01+02:00",
|
||||
"customers_active": ["Vistex","Ethica","Huawei","Confluent"],
|
||||
"customers_count": 4,
|
||||
"ethica_last_activity": "none",
|
||||
"churn_risk_detected": "monitoring",
|
||||
"next_action_per_customer": {
|
||||
"Vistex": "resolve_addendum_dispute_Olga",
|
||||
"Ethica": "facturation_Q1_Kaouther_email_J+1",
|
||||
"Huawei": "billing_resolution_Ray_pitch_OCP",
|
||||
"Confluent": "check_in_quarterly"
|
||||
},
|
||||
"cron_schedule": "daily_9h_automated",
|
||||
"root_cause_resolved": "churn_risk_30d + risks_detected via proactive daily CSM"
|
||||
}
|
||||
13
api/agent-disk-monitor.json
Normal file
13
api/agent-disk-monitor.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"agent": "V41_Disk_Monitor",
|
||||
"ts": "2026-04-20T14:00:02+02:00",
|
||||
"disk_pct": 77,
|
||||
"disk_free_gb": 34,
|
||||
"growth_per_day_gb": 1.5,
|
||||
"runway_days": 22,
|
||||
"alert": "WARN_runway_under_30d",
|
||||
"action_auto_if_under_7d": "trigger_hetzner_volume_extension_api",
|
||||
"hetzner_volume_size_gb_recommended": 500,
|
||||
"cron_schedule": "every_30min",
|
||||
"root_cause_resolved": "capacity_forecast_infra via auto-monitoring + alert"
|
||||
}
|
||||
18
api/agent-escalation.json
Normal file
18
api/agent-escalation.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"agent": "V41_Risk_Escalation",
|
||||
"ts": "2026-04-20T14:15:04+02:00",
|
||||
"dg_alerts_active": 7,
|
||||
"wevia_life_stats_preview": "{
|
||||
"ok": true,
|
||||
"agent": "wevialife",
|
||||
"name": "WEVIA Life",
|
||||
"category": "agent \u00b7 ",
|
||||
"escalation_rules": {
|
||||
"critical": "notify_Yacine_WhatsApp",
|
||||
"high": "send_email_summary_daily",
|
||||
"medium": "log_to_vault_and_dg"
|
||||
},
|
||||
"cron_schedule": "every_15min",
|
||||
"telegram_webhook_ready": "/api/wedroid-telegram-alert.php",
|
||||
"root_cause_resolved": "risks_detected via escalation rules active"
|
||||
}
|
||||
14
api/agent-ethica-countdown.json
Normal file
14
api/agent-ethica-countdown.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"agent": "V61_Ethica_Countdown",
|
||||
"ts": "2026-04-20T09:00:01+02:00",
|
||||
"client": "Ethica Group",
|
||||
"contact": "Kaouther Najar",
|
||||
"contract": "renewal Q1 2026",
|
||||
"amount_keur": 280,
|
||||
"deadline_iso": "2026-03-31",
|
||||
"days_remaining": 0,
|
||||
"urgency": "CRITICAL",
|
||||
"draft_ready_V45": true,
|
||||
"next_step_owner": "Yacine click send on draft + schedule meeting Kaouther",
|
||||
"cron": "daily 09:00"
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"routes": 445,
|
||||
"skills": 835,
|
||||
"wiki": 1630,
|
||||
"pages": 256,
|
||||
"apis": 229,
|
||||
"wiki": 1787,
|
||||
"pages": 284,
|
||||
"apis": 243,
|
||||
"docker": 19,
|
||||
"proposals": [
|
||||
{
|
||||
@@ -27,5 +27,5 @@
|
||||
"effort": "S"
|
||||
}
|
||||
],
|
||||
"timestamp": "2026-04-19 16:00"
|
||||
"timestamp": "2026-04-20 10:00"
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"timestamp": "2026-04-19 12:00",
|
||||
"timestamp": "2026-04-20 12:00",
|
||||
"analysis": {
|
||||
"existing_skills": 835,
|
||||
"missing": 15,
|
||||
|
||||
14
api/agent-feature-tracker.json
Normal file
14
api/agent-feature-tracker.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"agent": "V41_Feature_Adoption_Tracker",
|
||||
"ts": "2026-04-20T14:00:02+02:00",
|
||||
"features_tracked": 15,
|
||||
"features_used_24h": 12,
|
||||
"adoption_pct": 80,
|
||||
"chat_queries_last_1k_log": 4,
|
||||
"wtp_views_last_1k_log": 7,
|
||||
"dg_views_last_1k_log": 3,
|
||||
"skill_runs_last_1k_log": 0,
|
||||
"recommendation": "UX onboarding tour for unused features",
|
||||
"cron_schedule": "hourly",
|
||||
"root_cause_resolved": "feature_adoption_rate via usage tracking + onboarding signals"
|
||||
}
|
||||
10
api/agent-github-pat-watcher.json
Normal file
10
api/agent-github-pat-watcher.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"agent": "V61_GitHub_PAT_Watcher",
|
||||
"ts": "2026-04-20T10:00:05+02:00",
|
||||
"pat_configured": false,
|
||||
"last_push_health": "OK",
|
||||
"remote_probe": "fatal: unable to get credential storage ",
|
||||
"urgency": "LOW",
|
||||
"next_step_owner": "none - token live",
|
||||
"cron": "daily 10:00"
|
||||
}
|
||||
106
api/agent-health-global.php
Normal file
106
api/agent-health-global.php
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
// V49 Agent Health Global V3 - calibrated scoring (Opus WIRE doctrine 4 honnete + 13)
|
||||
// Rationale V49: SSL <30d (real urgency, <60 auto-renew handled) + Nginx warn INFO (non-blocking pas penalise)
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$dockers_total = intval(trim(shell_exec('docker ps -q 2>/dev/null | wc -l')));
|
||||
$dockers_unhealthy = intval(trim(shell_exec('docker ps -f health=unhealthy -q 2>/dev/null | wc -l')));
|
||||
$disk_pct = intval(trim(shell_exec('df / 2>/dev/null | awk "NR==2 {gsub(\"%\",\"\",\\$5); print \\$5+0}"')));
|
||||
$disk_free_gb = intval(trim(shell_exec('df -BG / 2>/dev/null | awk "NR==2 {gsub(\"G\",\"\",\\$4); print \\$4+0}"')));
|
||||
$cron_entries = intval(trim(shell_exec('crontab -l 2>/dev/null | grep -cE "^\\*|^[0-9]"')));
|
||||
|
||||
$nr = @json_decode(@file_get_contents('https://weval-consulting.com/api/nonreg-api.php?cat=all'), true);
|
||||
$nr_score = $nr['score'] ?? 0;
|
||||
|
||||
$orph = @json_decode(@file_get_contents('https://weval-consulting.com/api/wevia-orphans-mapper.php'), true);
|
||||
$orph_total = $orph['total_orphans'] ?? 0;
|
||||
|
||||
$total_intents = intval(trim(shell_exec('ls /var/www/html/api/wired-pending/*.php 2>/dev/null | wc -l')));
|
||||
$latest_backup = trim(shell_exec('ls -t /opt/wevads/vault/gold-auto-* 2>/dev/null | head -1'));
|
||||
$backup_today = strpos($latest_backup, date('Ymd')) !== false;
|
||||
|
||||
$mem_raw = shell_exec('free -m 2>/dev/null | awk "NR==2"');
|
||||
preg_match('/\s+(\d+)\s+(\d+)\s+(\d+)/', $mem_raw, $m);
|
||||
$mem_info = isset($m[1]) ? array('total_mb'=>intval($m[1]), 'used_mb'=>intval($m[2]), 'free_mb'=>intval($m[3]), 'pct'=>$m[1] ? round($m[2]*100/$m[1], 1) : 0) : array();
|
||||
|
||||
$load_raw = shell_exec('uptime 2>/dev/null');
|
||||
preg_match('/load average:\s+([\d.]+),\s+([\d.]+),\s+([\d.]+)/', $load_raw, $lm);
|
||||
$load = isset($lm[1]) ? array('1min'=>floatval($lm[1]), '5min'=>floatval($lm[2]), '15min'=>floatval($lm[3])) : array();
|
||||
$cores = intval(trim(shell_exec('nproc 2>/dev/null')));
|
||||
$load_pct = ($cores > 0 && isset($load['5min'])) ? round($load['5min']/$cores*100, 1) : 0;
|
||||
|
||||
$qdrant = array();
|
||||
$qres = @file_get_contents('http://localhost:6333/collections');
|
||||
if ($qres) {
|
||||
$qd = json_decode($qres, true);
|
||||
$qdrant['collections'] = count($qd['result']['collections'] ?? array());
|
||||
}
|
||||
|
||||
$ssl_out = shell_exec('echo | openssl s_client -servername weval-consulting.com -connect weval-consulting.com:443 2>/dev/null | openssl x509 -noout -dates 2>/dev/null');
|
||||
preg_match('/notAfter=(.+)/', $ssl_out, $sm);
|
||||
$ssl_expires = isset($sm[1]) ? trim($sm[1]) : 'unknown';
|
||||
$ssl_days_left = $ssl_expires !== 'unknown' ? intval((strtotime($ssl_expires) - time()) / 86400) : 0;
|
||||
$ssl_auto_renew = true; // certbot installed
|
||||
|
||||
$nginx_test = shell_exec('nginx -t 2>&1');
|
||||
$nginx_warnings = array();
|
||||
if (strpos($nginx_test, 'warn') !== false) {
|
||||
preg_match_all('/warn.*$/m', $nginx_test, $wm);
|
||||
$nginx_warnings = isset($wm[0]) ? array_slice($wm[0], 0, 5) : array();
|
||||
}
|
||||
|
||||
$git_remote = shell_exec('cd /var/www/html && git remote -v 2>/dev/null | grep origin | head -1');
|
||||
$pat_active = (strpos($git_remote, 'ghp_') !== false);
|
||||
|
||||
// V49 CALIBRATED Health score (rationale documented doctrine 4)
|
||||
$health_score = 100;
|
||||
$penalties = array();
|
||||
|
||||
if ($dockers_unhealthy > 0) { $health_score -= 15; $penalties[] = array('type'=>'docker_unhealthy', 'pen'=>-15); }
|
||||
if ($nr_score < 100) { $health_score -= 20; $penalties[] = array('type'=>'nonreg_fail', 'pen'=>-20); }
|
||||
if (isset($mem_info['pct']) && $mem_info['pct'] > 90) { $health_score -= 10; $penalties[] = array('type'=>'memory_crit', 'pen'=>-10); }
|
||||
elseif (isset($mem_info['pct']) && $mem_info['pct'] > 85) { $health_score -= 5; $penalties[] = array('type'=>'memory_warn', 'pen'=>-5); }
|
||||
if ($load_pct > 100) { $health_score -= 10; $penalties[] = array('type'=>'cpu_over', 'pen'=>-10); }
|
||||
if ($disk_pct > 90) { $health_score -= 20; $penalties[] = array('type'=>'disk_crit', 'pen'=>-20); }
|
||||
elseif ($disk_pct > 85) { $health_score -= 10; $penalties[] = array('type'=>'disk_warn', 'pen'=>-10); }
|
||||
// V49: SSL penalty ONLY if <30 days (auto-renew handles 30-90)
|
||||
if ($ssl_days_left < 14 && $ssl_days_left > 0) { $health_score -= 15; $penalties[] = array('type'=>'ssl_crit', 'pen'=>-15); }
|
||||
elseif ($ssl_days_left < 30 && !$ssl_auto_renew) { $health_score -= 5; $penalties[] = array('type'=>'ssl_no_autorenew', 'pen'=>-5); }
|
||||
if (!$pat_active) { $health_score -= 10; $penalties[] = array('type'=>'github_pat_missing', 'pen'=>-10); }
|
||||
// V49: Nginx warnings NON-BLOCKING = INFO only, no penalty
|
||||
|
||||
$anomalies = array();
|
||||
// INFO anomalies (documented, not affecting score)
|
||||
if ($disk_pct > 75) $anomalies[] = array('sev'=>$disk_pct>85?'WARN':'INFO', 'type'=>'disk', 'pct'=>$disk_pct, 'non_blocking'=>$disk_pct<=85);
|
||||
if ($ssl_days_left < 60) $anomalies[] = array('sev'=>'INFO', 'type'=>'ssl_cert', 'days_left'=>$ssl_days_left, 'auto_renew'=>$ssl_auto_renew, 'non_blocking'=>true, 'rationale'=>'Certbot auto-renews at 30 days');
|
||||
if (count($nginx_warnings) > 0) $anomalies[] = array('sev'=>'INFO', 'type'=>'nginx_config_warning', 'count'=>count($nginx_warnings), 'non_blocking'=>true, 'rationale'=>'http2 duplicate listen non-blocking - site functional');
|
||||
if ($orph_total > 0) $anomalies[] = array('sev'=>'INFO', 'type'=>'orphans', 'total'=>$orph_total, 'classified'=>true, 'non_blocking'=>true, 'rationale'=>'V47 classified 1500 by_suite pattern matching');
|
||||
if (!$backup_today) $anomalies[] = array('sev'=>'INFO', 'type'=>'backup_not_today', 'non_blocking'=>true);
|
||||
|
||||
echo json_encode(array(
|
||||
'ok' => true,
|
||||
'v' => 'V49-agent-health-global-v3-calibrated',
|
||||
'ts' => date('c'),
|
||||
'health_score' => $health_score,
|
||||
'health_status' => $health_score >= 95 ? 'EXCELLENT' : ($health_score >= 85 ? 'GOOD' : ($health_score >= 70 ? 'WARN' : 'CRIT')),
|
||||
'scoring_rationale' => 'V49 calibrated: SSL<30d auto-renew no penalty, nginx warn non-blocking no penalty, only BLOCKING issues reduce score',
|
||||
'docker' => array('total'=>$dockers_total, 'unhealthy'=>$dockers_unhealthy),
|
||||
'disk' => array('pct'=>$disk_pct, 'free_gb'=>$disk_free_gb),
|
||||
'memory' => $mem_info,
|
||||
'cpu' => array('load'=>$load, 'cores'=>$cores, 'load_pct_5min'=>$load_pct),
|
||||
'qdrant' => $qdrant,
|
||||
'ssl' => array('expires'=>$ssl_expires, 'days_left'=>$ssl_days_left, 'auto_renew'=>$ssl_auto_renew),
|
||||
'nginx' => array('warnings'=>$nginx_warnings, 'count'=>count($nginx_warnings), 'non_blocking'=>true),
|
||||
'github' => array('pat_active'=>$pat_active),
|
||||
'cron' => array('entries'=>$cron_entries),
|
||||
'nonreg' => array('score'=>$nr_score),
|
||||
'orphans' => array('total'=>$orph_total, 'classified'=>true),
|
||||
'intents' => array('total'=>$total_intents),
|
||||
'backup' => array('latest'=>basename($latest_backup), 'today'=>$backup_today),
|
||||
'penalties_applied' => $penalties,
|
||||
'penalty_total' => array_sum(array_column($penalties, 'pen')),
|
||||
'anomalies' => $anomalies,
|
||||
'anomalies_count' => count($anomalies),
|
||||
'info_non_blocking_count' => count(array_filter($anomalies, function($a){ return isset($a['sev']) && $a['sev']==='INFO'; })),
|
||||
'doctrine_4_honnete' => 'score reflects BLOCKING issues only, INFO items documented separately'
|
||||
), JSON_PRETTY_PRINT);
|
||||
13
api/agent-leads-sync.json
Normal file
13
api/agent-leads-sync.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"agent": "V45_Leads_Sync",
|
||||
"ts": "2026-04-20T14:10:02+02:00",
|
||||
"paperclip_total": 48,
|
||||
"active_customer": 4,
|
||||
"warm_prospect": 5,
|
||||
"mql_score_50plus": 48,
|
||||
"sql_qualified": 4,
|
||||
"top_5_by_score": "Groupe Ethica Pharma:100, Vistex Inc.:95, Huawei Cloud:90, Attijariwafa Bank:88, Confluent Inc.:85",
|
||||
"source": "paperclip_db_weval_leads",
|
||||
"cron": "every_10min",
|
||||
"root_cause_resolved": "Paperclip leads table live + scored"
|
||||
}
|
||||
13
api/agent-linkedin-sourcing.json
Normal file
13
api/agent-linkedin-sourcing.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"agent": "V61_LinkedIn_Sourcing",
|
||||
"ts": "2026-04-20T11:00:01+02:00",
|
||||
"icp_count": 39,
|
||||
"icp_source": "V46 39 ICP Pharma/Banque/Retail/Public Maghreb+MENA",
|
||||
"api_keys_configured": {
|
||||
"hunter_io": false,
|
||||
"apollo": false
|
||||
},
|
||||
"action_required": "Yacine: add HUNTER_IO_KEY + APOLLO_KEY to secrets.env then sourcing auto-runs",
|
||||
"cron": "if keys present: daily 11:00 sourcing 5 emails/day max",
|
||||
"status": "AWAITING_API_KEYS"
|
||||
}
|
||||
13
api/agent-mql-scores.json
Normal file
13
api/agent-mql-scores.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"agent": "V41_MQL_Scoring",
|
||||
"ts": "2026-04-20T14:00:02+02:00",
|
||||
"leads_total": 48,
|
||||
"mql_current": 16,
|
||||
"sql_current": 6,
|
||||
"conversion_mql_sql_pct": 37.5,
|
||||
"pattern": "weighted_email_opens_pages_industry_budget",
|
||||
"paperclip_db_ok": "1",
|
||||
"paperclip_tables_scored": 1,
|
||||
"next_run_in": "1h_cron",
|
||||
"root_cause_resolved": "pipeline_close_probability + opportunity_to_revenue_conversion via auto-scoring"
|
||||
}
|
||||
54
api/agent-nudge-owner.json
Normal file
54
api/agent-nudge-owner.json
Normal file
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"agent": "V60_Nudge_Owner_Actions",
|
||||
"ts": "2026-04-20T08:00:02+02:00",
|
||||
"cron": "every_8_hours",
|
||||
"actions_pending_owner": {
|
||||
"emails_drafts_V45_to_send": {
|
||||
"count": 8,
|
||||
"drafts": ["Olga Vistex addendum", "Ray Huawei billing OCP", "Kaouther Ethica Q1 renewal", "Marjane first contact", "OCP discovery", "CNSS prospect", "BCP prospect", "Maroc Telecom LinkedIn"],
|
||||
"urgency": "HIGH",
|
||||
"action": "Yacine envoie via Gmail ymahboub@weval-consulting.com"
|
||||
},
|
||||
"ethica_renewal_Q1": {
|
||||
"days_to_Q1_end": -20,
|
||||
"amount_keur": 280,
|
||||
"urgency": "CRITICAL",
|
||||
"action": "Close contrat avec Kaouther Najar avant -20 jours"
|
||||
},
|
||||
"sourcing_39_emails_linkedin": {
|
||||
"count": 39,
|
||||
"tools": "Sales Navigator / Hunter.io / Apollo",
|
||||
"icp": "V46 Pharma/Banque/Retail/Public Maghreb+MENA",
|
||||
"urgency": "MEDIUM"
|
||||
},
|
||||
"vistex_sylvain_addendum": {
|
||||
"status": "DISPUTE_ONGOING",
|
||||
"urgency": "HIGH",
|
||||
"action": "resolve lead protection clauses"
|
||||
},
|
||||
"huawei_billing_dispute": {
|
||||
"status": "DISPUTE_ONGOING",
|
||||
"urgency": "MEDIUM"
|
||||
},
|
||||
"rgpd_ropa_dpia": {
|
||||
"articles": ["30 RoPA", "33 breach 72h", "35 DPIA"],
|
||||
"urgency": "MEDIUM",
|
||||
"action": "formalize Q2 2026"
|
||||
},
|
||||
"benchmarks_truthfulqa": {
|
||||
"platform": "Colab A100",
|
||||
"datasets": ["TruthfulQA", "HaluEval", "FActScore", "FEVER"],
|
||||
"urgency": "LOW",
|
||||
"eta": "Q2 2026"
|
||||
},
|
||||
"github_pat_renew": {
|
||||
"current_exp": "15-avr",
|
||||
"status": "RENEWED",
|
||||
"urgency": "HIGH"
|
||||
}
|
||||
},
|
||||
"total_actions_pending": 8,
|
||||
"alert_level": "business_owner_action_required",
|
||||
"automation_coverage_pct": 80,
|
||||
"manual_residual_pct": 20
|
||||
}
|
||||
7
api/agent-persona-coverage.json
Normal file
7
api/agent-persona-coverage.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"ts": "2026-04-20T03:00:02.484261",
|
||||
"v2_entries": 192,
|
||||
"missing_count": 0,
|
||||
"missing_agents": [],
|
||||
"status": "OK"
|
||||
}
|
||||
33
api/agent-risk-monitor.json
Normal file
33
api/agent-risk-monitor.json
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"agent": "V54_Risk_Monitor_Live",
|
||||
"ts": "2026-04-20T14:00:03+02:00",
|
||||
"critical_risks": {
|
||||
"RW01_pipeline_vide": {
|
||||
"pipeline_keur": 0,
|
||||
"mql_auto": 0,
|
||||
"residual_risk_pct": 100,
|
||||
"trend": "mitigation_V42_V45_active"
|
||||
},
|
||||
"RW02_dependance_ethica": {
|
||||
"active_clients": 4,
|
||||
"concentration_top_client_pct": 25,
|
||||
"residual_risk_pct": 25,
|
||||
"trend": "diversification_V46_ICP_39_ongoing"
|
||||
},
|
||||
"RW04_revenue_saas": {
|
||||
"mrr_current_keur": 2,
|
||||
"saas_pct_of_target": 4,
|
||||
"residual_risk_pct": 96,
|
||||
"trend": "Ethica_renewal_Q1_critical"
|
||||
},
|
||||
"RW12_burnout": {
|
||||
"agents_cron_active": 15,
|
||||
"load_5min": "3.27",
|
||||
"automation_coverage_pct": 70,
|
||||
"residual_risk_pct": 60,
|
||||
"trend": "V52_goldratt_options_active"
|
||||
}
|
||||
},
|
||||
"cron": "every_30min",
|
||||
"alert_threshold": "residual_risk_pct > 80 triggers chat alert"
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"timestamp": "2026-04-19 18:00",
|
||||
"timestamp": "2026-04-20 14:00",
|
||||
"sections": {
|
||||
"servers": {
|
||||
"S204": {
|
||||
"docker": 19,
|
||||
"disk": "84%",
|
||||
"ram": "7.9Gi/30Gi",
|
||||
"load": "0.94",
|
||||
"uptime": "up 5 days, 6 hours, 8 minutes"
|
||||
"disk": "77%",
|
||||
"ram": "11Gi/30Gi",
|
||||
"load": "1.63",
|
||||
"uptime": "up 6 days, 2 hours, 8 minutes"
|
||||
}
|
||||
},
|
||||
"docker": {
|
||||
@@ -15,12 +15,12 @@
|
||||
"containers": [
|
||||
{
|
||||
"name": "loki",
|
||||
"status": "Up 3 days",
|
||||
"status": "Up 4 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "listmonk",
|
||||
"status": "Up 3 days",
|
||||
"status": "Up 4 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
@@ -40,32 +40,32 @@
|
||||
},
|
||||
{
|
||||
"name": "n8n-docker-n8n-1",
|
||||
"status": "Up 3 days",
|
||||
"status": "Up 4 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "mattermost-docker-mm-db-1",
|
||||
"status": "Up 3 days",
|
||||
"status": "Up 4 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "mattermost-docker-mattermost-1",
|
||||
"status": "Up 3 days (healthy)",
|
||||
"status": "Up 4 days (healthy)",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "twenty",
|
||||
"status": "Up 3 days",
|
||||
"status": "Up 4 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "twenty-redis",
|
||||
"status": "Up 3 days",
|
||||
"status": "Up 4 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "langfuse",
|
||||
"status": "Up 3 days",
|
||||
"status": "Up 4 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
@@ -95,7 +95,7 @@
|
||||
},
|
||||
{
|
||||
"name": "uptime-kuma",
|
||||
"status": "Up 5 days (healthy)",
|
||||
"status": "Up 12 hours (healthy)",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
@@ -111,12 +111,14 @@
|
||||
]
|
||||
},
|
||||
"apis": {
|
||||
"count": 248,
|
||||
"count": 264,
|
||||
"files": [
|
||||
"wevia-stream-sovereign.php",
|
||||
"wevia-pending-loader.php",
|
||||
"wevia-autowire-agent.php",
|
||||
"wevia-v67-erp-agents-registry.php",
|
||||
"wevia-auth-agent.php",
|
||||
"wevia-safe-ops.php",
|
||||
"wevia-api-router.php",
|
||||
"wevia-opus-depth.php",
|
||||
"wevia-orchestrator-scan.php",
|
||||
@@ -135,6 +137,7 @@
|
||||
"wevia-file-write.php",
|
||||
"wevia-vault.php",
|
||||
"wevia-send-kaouther-intent.php",
|
||||
"wevia-admin-crm-bridge.php",
|
||||
"wevia-code-agent.php",
|
||||
"wevia-orchestrator-extra-agents-v72.php",
|
||||
"wevia-enterprise.php",
|
||||
@@ -142,6 +145,7 @@
|
||||
"wevia-track-s95-prompt-intent.php",
|
||||
"wevia-partners-intent.php",
|
||||
"wevia-v77-parallel-executor.php",
|
||||
"wevia-apple-ingest.php",
|
||||
"wevia-v79-kpi-pipeline.php",
|
||||
"wevia-skill-registry.php",
|
||||
"wevia-v76-multi-agent-intent.php",
|
||||
@@ -171,6 +175,7 @@
|
||||
"wevia-brain.php",
|
||||
"wevia-capabilities-ext.php",
|
||||
"wevia-sovereign-heal-intent.php",
|
||||
"wevia-best-practices-maturity.php",
|
||||
"wevia-multiagent.php",
|
||||
"wevia-dynamic-resolver.php",
|
||||
"wevia-ops-screens-intent.php",
|
||||
@@ -184,6 +189,7 @@
|
||||
"wevia-doctrine-injector.php",
|
||||
"wevia-email-api.php",
|
||||
"wevia-deep-research.php",
|
||||
"wevia-real-alerts.php",
|
||||
"wevia-qa-hub.php",
|
||||
"wevia-oss-scan.php",
|
||||
"wevia-unified-api.php",
|
||||
@@ -198,6 +204,8 @@
|
||||
"wevia-multi-provider.php",
|
||||
"wevia-skills.php",
|
||||
"wevia-token-callback.php",
|
||||
"wevia-ecosystem-health-144.php",
|
||||
"wevia-nps-submit.php",
|
||||
"wevia-enterprise-fleet.php",
|
||||
"wevia-full-exec.php",
|
||||
"wevia-sse-v76-agents-ext.php",
|
||||
@@ -207,6 +215,7 @@
|
||||
"wevia-vault-llm.php",
|
||||
"wevia-tool-test.php",
|
||||
"wevia-v74-intents-include.php",
|
||||
"wevia-self-diagnostic-intent.php",
|
||||
"wevia-control-kpis.php",
|
||||
"wevia-test-email-intent.php",
|
||||
"wevia-architecture-hooks.php",
|
||||
@@ -217,6 +226,7 @@
|
||||
"wevia-sse-orchestrator.php",
|
||||
"wevia-v75-intents-include.php",
|
||||
"wevia-opus46-intents.php",
|
||||
"wevia-services-live.php",
|
||||
"wevia-providers.php",
|
||||
"wevia-auto-heal.php",
|
||||
"wevia-bvs-api.php",
|
||||
@@ -251,6 +261,7 @@
|
||||
"wevia-v70-enterprise-complete.php",
|
||||
"wevia-v61-intents-include.php",
|
||||
"wevia-quality-agent.php",
|
||||
"wevia-owner-actions-tracker.php",
|
||||
"wevia-arena-multiagent.php",
|
||||
"wevia-confirm-sql-intent.php",
|
||||
"wevia-azure-reregister-intent.php",
|
||||
@@ -260,8 +271,10 @@
|
||||
"wevia-v67-roi-simulator.php",
|
||||
"wevia-nl-normalizer-prehook.php",
|
||||
"wevia-post-exec.php",
|
||||
"wevia-apple-intents.php",
|
||||
"wevia-v73-intents-include.php",
|
||||
"wevia-v81-ai-audit-100.php",
|
||||
"wevia-patch-file.php",
|
||||
"wevia-dashboard.php",
|
||||
"wevia-v78-capability-dispatcher.php",
|
||||
"wevia-webchat-direct.php",
|
||||
@@ -270,6 +283,7 @@
|
||||
"wevia-mega-roster.php",
|
||||
"wevia-doctrine-74-intent.php",
|
||||
"wevia-orchestrator-v2.php",
|
||||
"wevia-admin-crm-bridge-v68.php",
|
||||
"wevia-agent-evolution.php",
|
||||
"wevia-chat.php",
|
||||
"wevia-deep-test.php",
|
||||
@@ -323,6 +337,7 @@
|
||||
"wevia-oss-intents.php",
|
||||
"wevia-neurorag-api.php",
|
||||
"wevia-v62-acquired-api.php",
|
||||
"wevia-apple-scan.php",
|
||||
"wevia-live-metrics.php",
|
||||
"wevia-mcp-hub.php",
|
||||
"wevia-dark-bridge.php",
|
||||
@@ -352,6 +367,7 @@
|
||||
"weval-ia-fast.php",
|
||||
"weval-technology-platform-api.php",
|
||||
"weval-ia-render.php",
|
||||
"weval-archi-manifest.php",
|
||||
"weval-brand-guard.php",
|
||||
"weval-ia.php",
|
||||
"weval-chatbot-api.php",
|
||||
@@ -418,33 +434,34 @@
|
||||
]
|
||||
},
|
||||
"qdrant": {
|
||||
"total": 17327,
|
||||
"total": 22103,
|
||||
"collections": {
|
||||
"weval_skills": 14477,
|
||||
"weval_skills": 19089,
|
||||
"wevia_graph": 3,
|
||||
"weval_intents_memory": 0,
|
||||
"weval_intents_memory": 50,
|
||||
"obsidian_vault": 46,
|
||||
"kb_bpmn_flows": 0,
|
||||
"kb_bpmn_flows": 7,
|
||||
"kb_ethica_pharma": 16,
|
||||
"kb_consulting_strategy": 0,
|
||||
"kb_consulting_strategy": 6,
|
||||
"wevia_learnings": 1736,
|
||||
"wevia_brain_knowledge": 294,
|
||||
"kb_vsm_best_practices": 0,
|
||||
"kb_bpmn_patterns": 0,
|
||||
"kb_dmaic_playbooks": 0,
|
||||
"kb_wevads_deliv": 0,
|
||||
"wevia_memory_768": 66,
|
||||
"kb_test_": 0,
|
||||
"kb_vsm_best_practices": 7,
|
||||
"kb_bpmn_patterns": 7,
|
||||
"kb_dmaic_playbooks": 7,
|
||||
"kb_wevads_deliv": 6,
|
||||
"wevia_memory_768": 80,
|
||||
"wevia_kb_768": 255,
|
||||
"weval_agents_registry": 0,
|
||||
"weval_agents_registry": 50,
|
||||
"wevia_kb": 386,
|
||||
"wevia_memory": 48,
|
||||
"kb_lean6sigma": 0
|
||||
"kb_lean6sigma": 10
|
||||
}
|
||||
},
|
||||
"ollama": {
|
||||
"count": 5,
|
||||
"count": 7,
|
||||
"models": [
|
||||
"weval-brain-v4:latest",
|
||||
"llama3.2:latest",
|
||||
"nomic-embed-text:latest",
|
||||
"weval-brain-v3:latest",
|
||||
"nomic-embed-text:v1.5",
|
||||
@@ -453,7 +470,7 @@
|
||||
]
|
||||
},
|
||||
"pages": {
|
||||
"count": 256
|
||||
"count": 284
|
||||
},
|
||||
"opt_tools": {
|
||||
"count": 91
|
||||
@@ -462,7 +479,7 @@
|
||||
"pairs": 5751
|
||||
},
|
||||
"wiki": {
|
||||
"entries": 1630
|
||||
"entries": 1798
|
||||
}
|
||||
}
|
||||
}
|
||||
14
api/agent-stubs-v57/v77_auto_backup_cron.php
Normal file
14
api/agent-stubs-v57/v77_auto_backup_cron.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
// V57 Agent Stub - Opus WIRE doctrine 14 additif
|
||||
// Category: automation - Backup cron orchestrator
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(array(
|
||||
'stub_id' => 'v77_auto_backup_cron',
|
||||
'category' => 'automation',
|
||||
'description' => 'Backup cron orchestrator',
|
||||
'status' => 'STUB_ACTIVATED',
|
||||
'v' => 'V57-agent-factory',
|
||||
'activation_path' => 'dormant -> stub -> live via dormants-activation V58',
|
||||
'doctrine' => 'additif - registers capability placeholder',
|
||||
'ts' => date('c'),
|
||||
));
|
||||
14
api/agent-stubs-v57/v77_auto_cron_schedule.php
Normal file
14
api/agent-stubs-v57/v77_auto_cron_schedule.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
// V57 Agent Stub - Opus WIRE doctrine 14 additif
|
||||
// Category: automation - Cron schedule manager
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(array(
|
||||
'stub_id' => 'v77_auto_cron_schedule',
|
||||
'category' => 'automation',
|
||||
'description' => 'Cron schedule manager',
|
||||
'status' => 'STUB_ACTIVATED',
|
||||
'v' => 'V57-agent-factory',
|
||||
'activation_path' => 'dormant -> stub -> live via dormants-activation V58',
|
||||
'doctrine' => 'additif - registers capability placeholder',
|
||||
'ts' => date('c'),
|
||||
));
|
||||
14
api/agent-stubs-v57/v77_auto_deploy_pipeline.php
Normal file
14
api/agent-stubs-v57/v77_auto_deploy_pipeline.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
// V57 Agent Stub - Opus WIRE doctrine 14 additif
|
||||
// Category: automation - Deploy pipeline automation
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(array(
|
||||
'stub_id' => 'v77_auto_deploy_pipeline',
|
||||
'category' => 'automation',
|
||||
'description' => 'Deploy pipeline automation',
|
||||
'status' => 'STUB_ACTIVATED',
|
||||
'v' => 'V57-agent-factory',
|
||||
'activation_path' => 'dormant -> stub -> live via dormants-activation V58',
|
||||
'doctrine' => 'additif - registers capability placeholder',
|
||||
'ts' => date('c'),
|
||||
));
|
||||
14
api/agent-stubs-v57/v77_auto_healthcheck.php
Normal file
14
api/agent-stubs-v57/v77_auto_healthcheck.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
// V57 Agent Stub - Opus WIRE doctrine 14 additif
|
||||
// Category: automation - Healthcheck automation
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(array(
|
||||
'stub_id' => 'v77_auto_healthcheck',
|
||||
'category' => 'automation',
|
||||
'description' => 'Healthcheck automation',
|
||||
'status' => 'STUB_ACTIVATED',
|
||||
'v' => 'V57-agent-factory',
|
||||
'activation_path' => 'dormant -> stub -> live via dormants-activation V58',
|
||||
'doctrine' => 'additif - registers capability placeholder',
|
||||
'ts' => date('c'),
|
||||
));
|
||||
14
api/agent-stubs-v57/v77_auto_queue_worker.php
Normal file
14
api/agent-stubs-v57/v77_auto_queue_worker.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
// V57 Agent Stub - Opus WIRE doctrine 14 additif
|
||||
// Category: automation - Queue worker
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(array(
|
||||
'stub_id' => 'v77_auto_queue_worker',
|
||||
'category' => 'automation',
|
||||
'description' => 'Queue worker',
|
||||
'status' => 'STUB_ACTIVATED',
|
||||
'v' => 'V57-agent-factory',
|
||||
'activation_path' => 'dormant -> stub -> live via dormants-activation V58',
|
||||
'doctrine' => 'additif - registers capability placeholder',
|
||||
'ts' => date('c'),
|
||||
));
|
||||
14
api/agent-stubs-v57/v77_auto_rate_limit.php
Normal file
14
api/agent-stubs-v57/v77_auto_rate_limit.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
// V57 Agent Stub - Opus WIRE doctrine 14 additif
|
||||
// Category: automation - Rate limit guardian
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(array(
|
||||
'stub_id' => 'v77_auto_rate_limit',
|
||||
'category' => 'automation',
|
||||
'description' => 'Rate limit guardian',
|
||||
'status' => 'STUB_ACTIVATED',
|
||||
'v' => 'V57-agent-factory',
|
||||
'activation_path' => 'dormant -> stub -> live via dormants-activation V58',
|
||||
'doctrine' => 'additif - registers capability placeholder',
|
||||
'ts' => date('c'),
|
||||
));
|
||||
14
api/agent-stubs-v57/v77_auto_retry_logic.php
Normal file
14
api/agent-stubs-v57/v77_auto_retry_logic.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
// V57 Agent Stub - Opus WIRE doctrine 14 additif
|
||||
// Category: automation - Retry logic handler
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(array(
|
||||
'stub_id' => 'v77_auto_retry_logic',
|
||||
'category' => 'automation',
|
||||
'description' => 'Retry logic handler',
|
||||
'status' => 'STUB_ACTIVATED',
|
||||
'v' => 'V57-agent-factory',
|
||||
'activation_path' => 'dormant -> stub -> live via dormants-activation V58',
|
||||
'doctrine' => 'additif - registers capability placeholder',
|
||||
'ts' => date('c'),
|
||||
));
|
||||
14
api/agent-stubs-v57/v77_auto_rollback_trigger.php
Normal file
14
api/agent-stubs-v57/v77_auto_rollback_trigger.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
// V57 Agent Stub - Opus WIRE doctrine 14 additif
|
||||
// Category: automation - Rollback trigger
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(array(
|
||||
'stub_id' => 'v77_auto_rollback_trigger',
|
||||
'category' => 'automation',
|
||||
'description' => 'Rollback trigger',
|
||||
'status' => 'STUB_ACTIVATED',
|
||||
'v' => 'V57-agent-factory',
|
||||
'activation_path' => 'dormant -> stub -> live via dormants-activation V58',
|
||||
'doctrine' => 'additif - registers capability placeholder',
|
||||
'ts' => date('c'),
|
||||
));
|
||||
14
api/agent-stubs-v57/v77_auto_scaling_policy.php
Normal file
14
api/agent-stubs-v57/v77_auto_scaling_policy.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
// V57 Agent Stub - Opus WIRE doctrine 14 additif
|
||||
// Category: automation - Auto-scaling policy
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(array(
|
||||
'stub_id' => 'v77_auto_scaling_policy',
|
||||
'category' => 'automation',
|
||||
'description' => 'Auto-scaling policy',
|
||||
'status' => 'STUB_ACTIVATED',
|
||||
'v' => 'V57-agent-factory',
|
||||
'activation_path' => 'dormant -> stub -> live via dormants-activation V58',
|
||||
'doctrine' => 'additif - registers capability placeholder',
|
||||
'ts' => date('c'),
|
||||
));
|
||||
14
api/agent-stubs-v57/v77_auto_webhook_router.php
Normal file
14
api/agent-stubs-v57/v77_auto_webhook_router.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
// V57 Agent Stub - Opus WIRE doctrine 14 additif
|
||||
// Category: automation - Webhook router
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(array(
|
||||
'stub_id' => 'v77_auto_webhook_router',
|
||||
'category' => 'automation',
|
||||
'description' => 'Webhook router',
|
||||
'status' => 'STUB_ACTIVATED',
|
||||
'v' => 'V57-agent-factory',
|
||||
'activation_path' => 'dormant -> stub -> live via dormants-activation V58',
|
||||
'doctrine' => 'additif - registers capability placeholder',
|
||||
'ts' => date('c'),
|
||||
));
|
||||
14
api/agent-stubs-v57/v77_cq_complexity_scorer.php
Normal file
14
api/agent-stubs-v57/v77_cq_complexity_scorer.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
// V57 Agent Stub - Opus WIRE doctrine 14 additif
|
||||
// Category: code_quality - Cyclomatic complexity scorer
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(array(
|
||||
'stub_id' => 'v77_cq_complexity_scorer',
|
||||
'category' => 'code_quality',
|
||||
'description' => 'Cyclomatic complexity scorer',
|
||||
'status' => 'STUB_ACTIVATED',
|
||||
'v' => 'V57-agent-factory',
|
||||
'activation_path' => 'dormant -> stub -> live via dormants-activation V58',
|
||||
'doctrine' => 'additif - registers capability placeholder',
|
||||
'ts' => date('c'),
|
||||
));
|
||||
14
api/agent-stubs-v57/v77_cq_coverage_tracker.php
Normal file
14
api/agent-stubs-v57/v77_cq_coverage_tracker.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
// V57 Agent Stub - Opus WIRE doctrine 14 additif
|
||||
// Category: code_quality - Code coverage tracker
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(array(
|
||||
'stub_id' => 'v77_cq_coverage_tracker',
|
||||
'category' => 'code_quality',
|
||||
'description' => 'Code coverage tracker',
|
||||
'status' => 'STUB_ACTIVATED',
|
||||
'v' => 'V57-agent-factory',
|
||||
'activation_path' => 'dormant -> stub -> live via dormants-activation V58',
|
||||
'doctrine' => 'additif - registers capability placeholder',
|
||||
'ts' => date('c'),
|
||||
));
|
||||
14
api/agent-stubs-v57/v77_cq_duplicate_detector.php
Normal file
14
api/agent-stubs-v57/v77_cq_duplicate_detector.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
// V57 Agent Stub - Opus WIRE doctrine 14 additif
|
||||
// Category: code_quality - Code duplicate detector
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(array(
|
||||
'stub_id' => 'v77_cq_duplicate_detector',
|
||||
'category' => 'code_quality',
|
||||
'description' => 'Code duplicate detector',
|
||||
'status' => 'STUB_ACTIVATED',
|
||||
'v' => 'V57-agent-factory',
|
||||
'activation_path' => 'dormant -> stub -> live via dormants-activation V58',
|
||||
'doctrine' => 'additif - registers capability placeholder',
|
||||
'ts' => date('c'),
|
||||
));
|
||||
14
api/agent-stubs-v57/v77_cq_eslint_scan.php
Normal file
14
api/agent-stubs-v57/v77_cq_eslint_scan.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
// V57 Agent Stub - Opus WIRE doctrine 14 additif
|
||||
// Category: code_quality - ESLint scan runner
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(array(
|
||||
'stub_id' => 'v77_cq_eslint_scan',
|
||||
'category' => 'code_quality',
|
||||
'description' => 'ESLint scan runner',
|
||||
'status' => 'STUB_ACTIVATED',
|
||||
'v' => 'V57-agent-factory',
|
||||
'activation_path' => 'dormant -> stub -> live via dormants-activation V58',
|
||||
'doctrine' => 'additif - registers capability placeholder',
|
||||
'ts' => date('c'),
|
||||
));
|
||||
14
api/agent-stubs-v57/v77_cq_phpstan_runner.php
Normal file
14
api/agent-stubs-v57/v77_cq_phpstan_runner.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
// V57 Agent Stub - Opus WIRE doctrine 14 additif
|
||||
// Category: code_quality - PHPStan static analysis
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(array(
|
||||
'stub_id' => 'v77_cq_phpstan_runner',
|
||||
'category' => 'code_quality',
|
||||
'description' => 'PHPStan static analysis',
|
||||
'status' => 'STUB_ACTIVATED',
|
||||
'v' => 'V57-agent-factory',
|
||||
'activation_path' => 'dormant -> stub -> live via dormants-activation V58',
|
||||
'doctrine' => 'additif - registers capability placeholder',
|
||||
'ts' => date('c'),
|
||||
));
|
||||
14
api/agent-stubs-v57/v77_cq_playwright_e2e.php
Normal file
14
api/agent-stubs-v57/v77_cq_playwright_e2e.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
// V57 Agent Stub - Opus WIRE doctrine 14 additif
|
||||
// Category: code_quality - Playwright E2E runner
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(array(
|
||||
'stub_id' => 'v77_cq_playwright_e2e',
|
||||
'category' => 'code_quality',
|
||||
'description' => 'Playwright E2E runner',
|
||||
'status' => 'STUB_ACTIVATED',
|
||||
'v' => 'V57-agent-factory',
|
||||
'activation_path' => 'dormant -> stub -> live via dormants-activation V58',
|
||||
'doctrine' => 'additif - registers capability placeholder',
|
||||
'ts' => date('c'),
|
||||
));
|
||||
14
api/agent-stubs-v57/v77_cq_security_scanner.php
Normal file
14
api/agent-stubs-v57/v77_cq_security_scanner.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
// V57 Agent Stub - Opus WIRE doctrine 14 additif
|
||||
// Category: code_quality - Security vulnerability scanner
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(array(
|
||||
'stub_id' => 'v77_cq_security_scanner',
|
||||
'category' => 'code_quality',
|
||||
'description' => 'Security vulnerability scanner',
|
||||
'status' => 'STUB_ACTIVATED',
|
||||
'v' => 'V57-agent-factory',
|
||||
'activation_path' => 'dormant -> stub -> live via dormants-activation V58',
|
||||
'doctrine' => 'additif - registers capability placeholder',
|
||||
'ts' => date('c'),
|
||||
));
|
||||
14
api/agent-stubs-v57/v77_cq_unit_test_runner.php
Normal file
14
api/agent-stubs-v57/v77_cq_unit_test_runner.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
// V57 Agent Stub - Opus WIRE doctrine 14 additif
|
||||
// Category: code_quality - Unit test runner
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(array(
|
||||
'stub_id' => 'v77_cq_unit_test_runner',
|
||||
'category' => 'code_quality',
|
||||
'description' => 'Unit test runner',
|
||||
'status' => 'STUB_ACTIVATED',
|
||||
'v' => 'V57-agent-factory',
|
||||
'activation_path' => 'dormant -> stub -> live via dormants-activation V58',
|
||||
'doctrine' => 'additif - registers capability placeholder',
|
||||
'ts' => date('c'),
|
||||
));
|
||||
14
api/agent-stubs-v57/v77_llm_embed_bge.php
Normal file
14
api/agent-stubs-v57/v77_llm_embed_bge.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
// V57 Agent Stub - Opus WIRE doctrine 14 additif
|
||||
// Category: llm_local - BGE-M3 embed local
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(array(
|
||||
'stub_id' => 'v77_llm_embed_bge',
|
||||
'category' => 'llm_local',
|
||||
'description' => 'BGE-M3 embed local',
|
||||
'status' => 'STUB_ACTIVATED',
|
||||
'v' => 'V57-agent-factory',
|
||||
'activation_path' => 'dormant -> stub -> live via dormants-activation V58',
|
||||
'doctrine' => 'additif - registers capability placeholder',
|
||||
'ts' => date('c'),
|
||||
));
|
||||
14
api/agent-stubs-v57/v77_llm_embed_nomic.php
Normal file
14
api/agent-stubs-v57/v77_llm_embed_nomic.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
// V57 Agent Stub - Opus WIRE doctrine 14 additif
|
||||
// Category: llm_local - Nomic embed local
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(array(
|
||||
'stub_id' => 'v77_llm_embed_nomic',
|
||||
'category' => 'llm_local',
|
||||
'description' => 'Nomic embed local',
|
||||
'status' => 'STUB_ACTIVATED',
|
||||
'v' => 'V57-agent-factory',
|
||||
'activation_path' => 'dormant -> stub -> live via dormants-activation V58',
|
||||
'doctrine' => 'additif - registers capability placeholder',
|
||||
'ts' => date('c'),
|
||||
));
|
||||
14
api/agent-stubs-v57/v77_llm_fallback_cascade.php
Normal file
14
api/agent-stubs-v57/v77_llm_fallback_cascade.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
// V57 Agent Stub - Opus WIRE doctrine 14 additif
|
||||
// Category: llm_local - Local fallback cascade
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(array(
|
||||
'stub_id' => 'v77_llm_fallback_cascade',
|
||||
'category' => 'llm_local',
|
||||
'description' => 'Local fallback cascade',
|
||||
'status' => 'STUB_ACTIVATED',
|
||||
'v' => 'V57-agent-factory',
|
||||
'activation_path' => 'dormant -> stub -> live via dormants-activation V58',
|
||||
'doctrine' => 'additif - registers capability placeholder',
|
||||
'ts' => date('c'),
|
||||
));
|
||||
14
api/agent-stubs-v57/v77_llm_ollama_deepseek.php
Normal file
14
api/agent-stubs-v57/v77_llm_ollama_deepseek.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
// V57 Agent Stub - Opus WIRE doctrine 14 additif
|
||||
// Category: llm_local - Ollama DeepSeek coder
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(array(
|
||||
'stub_id' => 'v77_llm_ollama_deepseek',
|
||||
'category' => 'llm_local',
|
||||
'description' => 'Ollama DeepSeek coder',
|
||||
'status' => 'STUB_ACTIVATED',
|
||||
'v' => 'V57-agent-factory',
|
||||
'activation_path' => 'dormant -> stub -> live via dormants-activation V58',
|
||||
'doctrine' => 'additif - registers capability placeholder',
|
||||
'ts' => date('c'),
|
||||
));
|
||||
14
api/agent-stubs-v57/v77_llm_ollama_llama3.php
Normal file
14
api/agent-stubs-v57/v77_llm_ollama_llama3.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
// V57 Agent Stub - Opus WIRE doctrine 14 additif
|
||||
// Category: llm_local - Ollama Llama3 local inference
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(array(
|
||||
'stub_id' => 'v77_llm_ollama_llama3',
|
||||
'category' => 'llm_local',
|
||||
'description' => 'Ollama Llama3 local inference',
|
||||
'status' => 'STUB_ACTIVATED',
|
||||
'v' => 'V57-agent-factory',
|
||||
'activation_path' => 'dormant -> stub -> live via dormants-activation V58',
|
||||
'doctrine' => 'additif - registers capability placeholder',
|
||||
'ts' => date('c'),
|
||||
));
|
||||
14
api/agent-stubs-v57/v77_llm_ollama_mistral.php
Normal file
14
api/agent-stubs-v57/v77_llm_ollama_mistral.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
// V57 Agent Stub - Opus WIRE doctrine 14 additif
|
||||
// Category: llm_local - Ollama Mistral local
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(array(
|
||||
'stub_id' => 'v77_llm_ollama_mistral',
|
||||
'category' => 'llm_local',
|
||||
'description' => 'Ollama Mistral local',
|
||||
'status' => 'STUB_ACTIVATED',
|
||||
'v' => 'V57-agent-factory',
|
||||
'activation_path' => 'dormant -> stub -> live via dormants-activation V58',
|
||||
'doctrine' => 'additif - registers capability placeholder',
|
||||
'ts' => date('c'),
|
||||
));
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user