moving
Some checks failed
Installer Smoke / installer-smoke (push) Has been cancelled

This commit is contained in:
Oleg Maslov
2026-09-02 10:10:29 +02:00
commit 0c3e2ead3b
3841 changed files with 970576 additions and 0 deletions

View File

@@ -0,0 +1,227 @@
<!DOCTYPE html>
<html lang="en" data-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Waggle · Memory Trust</title>
<script>document.documentElement.classList.add('js');</script>
<link rel="stylesheet" href="../styles/waggle.css">
<style>
body { height:100vh; overflow:hidden; display:flex; flex-direction:column; }
.controls { flex:none; display:flex; align-items:center; gap:14px; padding:11px 20px; border-bottom:1px solid var(--line-soft); background:color-mix(in srgb,var(--bg) 88%,transparent); backdrop-filter:blur(10px); z-index:30; }
.controls .lab { font-family:var(--mono); font-size:10.5px; letter-spacing:.12em; text-transform:uppercase; color:var(--text-dim); }
.seg { display:inline-flex; padding:3px; gap:3px; border-radius:10px; background:var(--surface-2); border:1px solid var(--line-soft); }
.seg button { font-family:var(--sans); font-size:12.5px; font-weight:600; cursor:pointer; border:0; background:transparent; color:var(--text-muted); padding:6px 13px; border-radius:7px; transition:.14s; white-space:nowrap; }
.seg button.on { background:var(--honey); color:#1a1407; }
.controls .vlabel { font-size:12.5px; color:var(--text-muted); } .controls .vlabel b { color:var(--text); font-weight:600; }
.controls .right { margin-left:auto; display:flex; align-items:center; gap:10px; }
.tbtn { width:34px; height:34px; border-radius:9px; border:1px solid var(--line); background:var(--surface); color:var(--text-2); cursor:pointer; }
.tbtn:hover { border-color:var(--honey-line); color:var(--honey); }
.stage { flex:1; min-height:0; overflow:auto; }
.wrap { max-width:920px; margin:0 auto; padding:30px 32px 70px; }
.view { display:none; } .view.on { display:block; }
.head { margin-bottom:22px; }
.head .eyebrow { font-family:var(--mono); font-size:11px; letter-spacing:.14em; text-transform:uppercase; color:var(--honey); margin-bottom:12px; display:flex; align-items:center; gap:9px; } .head .eyebrow::before { content:''; width:20px; height:1px; background:var(--honey-line); }
.head h1 { font-size:28px; font-weight:650; letter-spacing:-0.02em; margin:0 0 10px; } .head h1 em { font-style:normal; color:var(--honey); }
.head p { font-size:15px; color:var(--text-muted); line-height:1.55; margin:0; max-width:64ch; } .head p b { color:var(--text-2); }
/* trust summary bar */
.tsum { display:grid; grid-template-columns:repeat(4,1fr); gap:12px; margin-bottom:24px; }
.ts { padding:16px; border-radius:var(--r-lg); border:1px solid var(--line-soft); background:var(--surface); }
.ts .v { font-size:24px; font-weight:750; letter-spacing:-0.02em; } .ts .l { font-size:11.5px; color:var(--text-muted); margin-top:5px; }
.ts.warn { border-color:color-mix(in srgb,var(--attention) 35%,transparent); } .ts.warn .v { color:var(--attention); }
.toolbar { display:flex; align-items:center; gap:10px; margin-bottom:16px; flex-wrap:wrap; }
.search { flex:1; min-width:200px; display:flex; align-items:center; gap:10px; padding:9px 14px; border-radius:11px; border:1px solid var(--line); background:var(--surface); }
.search svg { width:16px; height:16px; stroke:var(--text-dim); fill:none; stroke-width:1.9; }
.search input { flex:1; border:0; background:transparent; color:var(--text); font-family:var(--sans); font-size:14px; outline:none; }
.filt { font-size:12.5px; font-weight:600; color:var(--text-muted); padding:8px 13px; border-radius:9px; border:1px solid var(--line-soft); background:var(--surface); cursor:pointer; transition:.14s; }
.filt:hover { color:var(--text); } .filt.on { color:var(--text); border-color:var(--honey-line); background:var(--honey-wash); }
/* memory rows */
.mems { display:grid; gap:10px; }
.mem { border:1px solid var(--line-soft); background:var(--surface); border-radius:var(--r-lg); padding:16px 18px; transition:.15s; }
.mem.stale { border-color:color-mix(in srgb,var(--attention) 30%,var(--line-soft)); }
.mem.disputed { border-color:color-mix(in srgb,var(--risk) 30%,var(--line-soft)); opacity:.92; }
.mem .top { display:flex; align-items:flex-start; gap:13px; }
.mem .conf { width:42px; flex:none; text-align:center; }
.mem .conf .ring { width:38px; height:38px; border-radius:999px; display:grid; place-items:center; font-family:var(--mono); font-size:11px; font-weight:600; }
.mem .conf .cl { font-size:9px; color:var(--text-dim); font-family:var(--mono); margin-top:4px; text-transform:uppercase; letter-spacing:.06em; }
.mem .mbody { flex:1; min-width:0; }
.mem .mtext { font-size:14.5px; line-height:1.5; color:var(--text); } .mem .mtext b { font-weight:650; }
.mem.disputed .mtext { text-decoration:line-through; text-decoration-color:color-mix(in srgb,var(--risk) 60%,transparent); color:var(--text-muted); }
.mem .prov { margin-top:8px; display:flex; flex-wrap:wrap; gap:7px 14px; align-items:center; font-family:var(--mono); font-size:10.5px; color:var(--text-dim); }
.mem .prov .src { color:var(--intel); } .mem .prov .fresh.ok { color:var(--healthy); } .mem .prov .fresh.old { color:var(--attention); }
.mem .acts { display:flex; gap:6px; align-items:center; flex:none; }
.mact { width:30px; height:30px; border-radius:8px; border:1px solid var(--line-soft); background:var(--surface-2); color:var(--text-muted); cursor:pointer; display:grid; place-items:center; transition:.14s; }
.mact:hover { border-color:var(--honey-line); color:var(--honey); }
.mact.danger:hover { border-color:color-mix(in srgb,var(--risk) 45%,transparent); color:var(--risk); }
.mact svg { width:15px; height:15px; stroke:currentColor; fill:none; stroke-width:1.8; }
.corrected { margin-top:10px; padding:9px 13px; border-radius:9px; background:var(--healthy-wash); border:1px solid color-mix(in srgb,var(--healthy) 30%,transparent); font-size:12.5px; color:var(--text-2); display:flex; gap:9px; align-items:center; }
.corrected svg { width:14px; height:14px; stroke:var(--healthy); fill:none; stroke-width:2; flex:none; }
.corrected b { color:var(--text); }
.stalebanner { margin-top:10px; padding:9px 13px; border-radius:9px; background:var(--honey-wash); border:1px solid var(--honey-line); font-size:12.5px; color:var(--text-2); display:flex; gap:9px; align-items:center; }
.stalebanner svg { width:14px; height:14px; stroke:var(--honey); fill:none; stroke-width:2; flex:none; }
.stalebanner .sp { margin-left:auto; display:flex; gap:6px; }
.sbtn { font-size:11.5px; font-weight:650; padding:5px 11px; border-radius:7px; cursor:pointer; border:1px solid transparent; }
.sbtn.go { background:var(--honey); color:#1a1407; } .sbtn.ghost { background:var(--surface); color:var(--text-2); border-color:var(--line-strong); }
/* why-trace (variation B) */
.trace { border:1px solid var(--line); border-radius:var(--r-xl); background:var(--bg-2); overflow:hidden; }
.trace .th { display:flex; align-items:center; gap:12px; padding:18px 22px; border-bottom:1px solid var(--line-soft); }
.trace .th .ti { width:34px; height:38px; flex:none; display:grid; place-items:center; color:#1a1407; background:linear-gradient(150deg,var(--honey-bright),var(--honey-deep)); }
.trace .th .ti svg { width:18px; height:18px; stroke:#1a1407; fill:none; stroke-width:2; }
.trace .th b { font-size:15.5px; font-weight:650; } .trace .th .sub { font-size:12px; color:var(--text-muted); }
.trace .th .when { margin-left:auto; font-family:var(--mono); font-size:11px; color:var(--text-dim); }
.tchain { padding:8px 22px 18px; }
.tnode { display:grid; grid-template-columns:24px 1fr; gap:14px; padding:14px 0; position:relative; }
.tnode::before { content:''; position:absolute; left:11px; top:34px; bottom:-14px; width:1.5px; background:var(--line); }
.tnode:last-child::before { display:none; }
.tnode .tdot { width:24px; height:24px; border-radius:999px; display:grid; place-items:center; flex:none; z-index:1; }
.tnode .tdot svg { width:13px; height:13px; stroke:#1a1407; fill:none; stroke-width:2.4; }
.tnode .tc b { font-size:13.5px; font-weight:600; } .tnode .tc p { margin:4px 0 0; font-size:13px; color:var(--text-muted); line-height:1.5; } .tnode .tc p .mono { font-family:var(--mono); font-size:11.5px; color:var(--text-dim); } .tnode .tc p .src { color:var(--intel); font-family:var(--mono); font-size:11px; }
.tnode .tc .ev { margin-top:7px; font-size:12px; color:var(--text-2); padding:8px 12px; border-radius:8px; background:var(--surface); border:1px solid var(--line-soft); }
.traceact { display:flex; gap:9px; padding:16px 22px; border-top:1px solid var(--line-soft); background:var(--surface); }
.tbtn2 { font-size:12.5px; font-weight:650; padding:9px 15px; border-radius:9px; cursor:pointer; border:1px solid transparent; }
.tbtn2.go { background:var(--honey); color:#1a1407; } .tbtn2.ghost { background:var(--surface-2); color:var(--text-2); border-color:var(--line-strong); } .tbtn2.danger { background:transparent; color:var(--risk); border-color:color-mix(in srgb,var(--risk) 35%,transparent); }
.principle { margin-top:24px; display:flex; gap:13px; align-items:flex-start; padding:18px 20px; border-radius:var(--r-lg); background:var(--bg-2); border:1px solid var(--line-soft); }
.principle svg { width:20px; height:20px; stroke:var(--healthy); fill:none; stroke-width:1.8; flex:none; margin-top:1px; }
.principle p { margin:0; font-size:13.5px; color:var(--text-muted); line-height:1.6; } .principle b { color:var(--text); }
.toast { position:fixed; bottom:22px; left:50%; transform:translateX(-50%) translateY(18px); opacity:0; pointer-events:none; display:flex; align-items:center; gap:10px; padding:12px 18px; border-radius:12px; background:var(--surface); border:1px solid var(--healthy); box-shadow:var(--shadow-lg); font-size:13.5px; color:var(--text); z-index:80; transition:.28s cubic-bezier(.16,1,.3,1); }
.toast.show { opacity:1; transform:translateX(-50%) translateY(0); }
.toast .td2 { width:8px; height:8px; border-radius:999px; background:var(--healthy); flex:none; }
@media (max-width:820px){ .tsum { grid-template-columns:1fr 1fr; } }
</style>
</head>
<body>
<div class="controls">
<span class="lab">Memory Trust · view</span>
<div class="seg" id="seg">
<button class="on" data-v="manage">Manage memory</button>
<button data-v="why">Why did you do that?</button>
</div>
<span class="vlabel" id="vlabel"><b>Manage</b> — forget, correct, confirm; see confidence &amp; freshness</span>
<div class="right"><button class="tbtn" id="tbtn" title="Toggle theme"></button></div>
</div>
<div class="stage">
<!-- ════ A — MANAGE ════ -->
<div class="view on wrap" data-view="manage">
<div class="head">
<div class="eyebrow">Trust · the thing that makes you stay</div>
<h1>Memory you can <em>correct, age, and forget.</em></h1>
<p>A memory that only grows is a liability. Waggle shows you <b>how sure it is</b>, <b>how fresh it is</b>, and <b>where it came from</b> — and lets you fix or forget anything. You're always in control of what the hive believes.</p>
</div>
<div class="tsum">
<div class="ts"><div class="v">142</div><div class="l">Memories in this hive</div></div>
<div class="ts"><div class="v" style="color:var(--healthy)">128</div><div class="l">High confidence &amp; fresh</div></div>
<div class="ts warn"><div class="v">9</div><div class="l">Stale · worth a review</div></div>
<div class="ts warn"><div class="v">3</div><div class="l">Awaiting your confirm</div></div>
</div>
<div class="toolbar">
<div class="search"><svg viewBox="0 0 24 24"><circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/></svg><input placeholder="Search what Waggle knows… or ask it to forget something"></div>
<span class="filt on">All</span><span class="filt">Stale</span><span class="filt">Needs confirm</span><span class="filt">Forgotten</span>
</div>
<div class="mems" id="mems"></div>
<div class="principle">
<svg viewBox="0 0 24 24"><path d="M12 3l8 4v5c0 5-3.5 7.5-8 9-4.5-1.5-8-4-8-9V7z"/><path d="M9 12l2 2 4-4"/></svg>
<p><b>Nothing is remembered behind your back.</b> Every memory is inspectable, editable, and forgettable — and forgetting is real: it's removed from recall and from anything Waggle says next. Confidence and freshness are shown so the agent (and you) can discount what's old or shaky instead of acting on it blindly.</p>
</div>
</div>
<!-- ════ B — WHY TRACE ════ -->
<div class="view wrap" data-view="why">
<div class="head">
<div class="eyebrow">Provenance · accountability</div>
<h1>Ask the agent <em>“why did you do that?”</em></h1>
<p>Any action an agent takes can be traced back to the exact memories and sources behind it — so a wrong move is <b>diagnosable, not mysterious</b>. If a bad memory caused it, fix the memory right from the trace.</p>
</div>
<div class="trace">
<div class="th">
<div class="ti hex"><svg viewBox="0 0 24 24"><path d="m22 2-7 20-4-9-9-4Z"/><path d="M22 2 11 13"/></svg></div>
<div><b>Drafted the board brief around “regulated industries”</b><div class="sub">Deck-builder · 18m ago · Q2 Board Deck</div></div>
<span class="when">trace #a1f9</span>
</div>
<div class="tchain">
<div class="tnode"><div class="tdot" style="background:var(--intel)"><svg viewBox="0 0 24 24"><path d="M5 12h14M13 6l6 6-6 6"/></svg></div><div class="tc"><b>Goal received</b><p>You asked: <span class="mono">“tighten the board narrative.”</span></p></div></div>
<div class="tnode"><div class="tdot" style="background:var(--honey)"><svg viewBox="0 0 24 24"><path d="M20 6 9 17l-5-5"/></svg></div><div class="tc"><b>Recalled 3 memories</b><p>Strongest was: <span class="src">⬡ mem #M-204</span> — “Mara wants market work to lead with the regulated-industries angle.”</p><div class="ev">confidence 94% · source: chat · Tue · still fresh</div></div></div>
<div class="tnode"><div class="tdot" style="background:var(--honey)"><svg viewBox="0 0 24 24"><path d="M20 6 9 17l-5-5"/></svg></div><div class="tc"><b>Cross-checked the teardown</b><p>Confirmed 2 of 3 proof points cite customer quotes <span class="src">⬡ teardown.md</span></p></div></div>
<div class="tnode"><div class="tdot" style="background:var(--healthy)"><svg viewBox="0 0 24 24"><path d="M5 12h14M13 6l6 6-6 6"/></svg></div><div class="tc"><b>Acted</b><p>Wrote slide 6 around the regulated angle and flagged it for your review.</p></div></div>
</div>
<div class="traceact">
<button class="tbtn2 go">Looks right</button>
<button class="tbtn2 ghost">That memory is wrong → correct it</button>
<button class="tbtn2 danger">Forget #M-204 &amp; redo</button>
</div>
</div>
<div class="principle">
<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M12 8h.01M11 12h1v4h1"/></svg>
<p><b>Every agent action keeps its trace.</b> The chain from goal → recalled memories → checks → action is stored with the result, so "why did you do that?" always has an answer — and the fix (correct or forget the offending memory) is one click from the explanation.</p>
</div>
</div>
</div>
<div class="toast" id="toast"><span class="td2"></span><span id="toastText"></span></div>
<script>
const root = document.documentElement, tbtn = document.getElementById('tbtn');
function setTheme(t){ root.setAttribute('data-theme', t); tbtn.textContent = t==='dark'?'☾':'☀'; try{localStorage.setItem('waggle-concept-theme',t);}catch(e){} }
setTheme((()=>{ try{ return localStorage.getItem('waggle-concept-theme')||'dark'; }catch(e){ return 'dark'; } })());
tbtn.onclick = () => setTheme(root.getAttribute('data-theme')==='dark'?'light':'dark');
window.addEventListener('message', e => { if(e.data && e.data.theme) setTheme(e.data.theme); });
window.addEventListener('storage', e => { if(e.key==='waggle-concept-theme' && e.newValue) setTheme(e.newValue); });
function confColor(c){ return c>=85?'var(--healthy)':c>=60?'var(--attention)':'var(--risk)'; }
const mems = [
{ id:'M-204', text:'Mara wants market work to <b>lead with the regulated-industries angle</b>.', conf:94, src:'chat · Tue', fresh:'fresh', state:'ok' },
{ id:'M-198', text:'<b>Mem0</b> is cloud-only and raised prices ~15% in March.', conf:88, src:'web · mem0.ai', fresh:'fresh', state:'ok' },
{ id:'M-141', text:'The Q3 launch date is <b>September 12</b>.', conf:61, src:'chat · 6 weeks ago', fresh:'old', state:'stale' },
{ id:'M-088', text:'Mara prefers <b>Slack over email</b> for updates.', conf:47, src:'inferred · once', fresh:'old', state:'disputed', corrected:'Corrected by you → prefers a daily digest, not Slack pings.' },
{ id:'M-052', text:'Primary competitor is <b>Letta</b>.', conf:90, src:'teardown.md', fresh:'fresh', state:'ok' },
];
const FRESH = { fresh:['ok','fresh'], old:['old','aging'] };
function row(m){
const stale = m.state==='stale', disp = m.state==='disputed';
return `<div class="mem ${m.state}">
<div class="top">
<div class="conf"><div class="ring" style="color:${confColor(m.conf)};border:2px solid ${confColor(m.conf)}">${m.conf}</div><div class="cl">conf</div></div>
<div class="mbody">
<div class="mtext">${m.text}</div>
<div class="prov"><span><span class="src">⬡ ${m.id}</span></span><span>source: ${m.src}</span><span class="fresh ${m.fresh==='fresh'?'ok':'old'}">● ${m.fresh==='fresh'?'fresh':'aging — last seen 6w ago'}</span></div>
${disp&&m.corrected?`<div class="corrected"><svg viewBox="0 0 24 24"><path d="M20 6 9 17l-5-5"/></svg><span><b>${m.corrected.split('→')[0].trim()}</b> → ${m.corrected.split('→')[1].trim()}</span></div>`:''}
${stale?`<div class="stalebanner"><svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg><span>This is 6 weeks old — still true?</span><span class="sp"><button class="sbtn go" data-act="confirm" data-id="${m.id}">Still true</button><button class="sbtn ghost" data-act="forget" data-id="${m.id}">Forget</button></span></div>`:''}
</div>
<div class="acts">
<button class="mact" title="Edit / correct" data-act="edit" data-id="${m.id}"><svg viewBox="0 0 24 24"><path d="M14 7l-1.5-1.5a2 2 0 0 0-3 0l-5 5L4 14l3.5-.5 5-5a2 2 0 0 0 0-3z"/></svg></button>
<button class="mact danger" title="Forget this" data-act="forget" data-id="${m.id}"><svg viewBox="0 0 24 24"><path d="M4 7h16M9 7V5h6v2M6 7l1 13h10l1-13"/></svg></button>
</div>
</div>
</div>`;
}
document.getElementById('mems').innerHTML = mems.map(row).join('');
function toast(msg){ const t=document.getElementById('toast'); document.getElementById('toastText').textContent=msg; t.classList.add('show'); clearTimeout(t._t); t._t=setTimeout(()=>t.classList.remove('show'),2400); }
document.getElementById('mems').addEventListener('click', e=>{
const b=e.target.closest('[data-act]'); if(!b) return;
const act=b.dataset.act, id=b.dataset.id;
if(act==='forget'){ const el=b.closest('.mem'); el.style.transition='.3s'; el.style.opacity='0'; el.style.transform='translateX(-12px)'; setTimeout(()=>el.remove(),300); toast('Forgotten '+id+' — removed from recall'); }
else if(act==='confirm'){ const sb=b.closest('.stalebanner'); if(sb){ sb.outerHTML='<div class="corrected"><svg viewBox="0 0 24 24"><path d="M20 6 9 17l-5-5"/></svg><span>Confirmed still true · freshness reset</span></div>'; } toast('Confirmed '+id+' — freshness reset'); }
else if(act==='edit'){ toast('Correcting '+id+' — opens an inline editor'); }
});
const labels = { manage:'<b>Manage</b> — forget, correct, confirm; see confidence &amp; freshness', why:'<b>Why-trace</b> — every action explains itself' };
const seg = document.getElementById('seg');
seg.addEventListener('click', e=>{ const b=e.target.closest('button'); if(!b) return; [...seg.children].forEach(x=>x.classList.toggle('on',x===b)); document.querySelectorAll('.view').forEach(v=>v.classList.toggle('on', v.dataset.view===b.dataset.v)); document.getElementById('vlabel').innerHTML=labels[b.dataset.v]; document.querySelector('.stage').scrollTop=0; });
</script>
</body>
</html>