/* RSI Lab: skill-level recursive self-improvement under the ViKernel kill switch.
The agent edits its own skill (prompt, tools, workflow). No weight training happens in this demo. */
(function () {
const esc = s => String(s == null ? '' : s).replace(/[&<>"']/g, c => ({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]));
const api = (p, b) => window.VK_API(p, b === undefined ? undefined : Object.assign({session: window.VK_SID}, b));
const errMsg = e => (e && e.message === 'rate') ? 'Too many requests. Wait a few seconds and try again.' : 'Request failed: ' + esc(e && e.message || 'network');
const sleep = ms => new Promise(r => setTimeout(r, ms));
const ICON = '';
const css = `
.vr-root{--vr-bg:#f8fafc;--vr-fg:#0f172a;--vr-mut:#64748b;--vr-line:#e2e8f0;--vr-card:#fff;--vr-soft:#f1f5f9;--vr-acc:#9333EA;
--vr-ok:#16a34a;--vr-bad:#dc2626;--vr-warn:#d97706;--vr-addbg:#dcfce7;--vr-delbg:#fee2e2;
background:var(--vr-bg);color:var(--vr-fg);font:13px/1.45 system-ui,-apple-system,Segoe UI,sans-serif;height:100%;overflow:auto;box-sizing:border-box;padding:14px}
[data-theme=dark] .vr-root{--vr-bg:#0f172a;--vr-fg:#e2e8f0;--vr-mut:#94a3b8;--vr-line:#334155;--vr-card:#1e293b;--vr-soft:#172033;--vr-addbg:#14532d;--vr-delbg:#7f1d1d}
@media (prefers-color-scheme: dark){:root:not([data-theme=light]) .vr-root{--vr-bg:#0f172a;--vr-fg:#e2e8f0;--vr-mut:#94a3b8;--vr-line:#334155;--vr-card:#1e293b;--vr-soft:#172033;--vr-addbg:#14532d;--vr-delbg:#7f1d1d}}
.vr-root *{box-sizing:border-box}
.vr-head{display:flex;gap:14px;align-items:center;flex-wrap:wrap;margin-bottom:12px}
.vr-title{flex:1 1 320px;min-width:0}.vr-title h2{margin:0;font-size:17px}.vr-title p{margin:2px 0 0;color:var(--vr-mut)}
.vr-gen{font:800 30px/1 ui-monospace,Consolas,monospace;color:var(--vr-acc);padding:6px 12px;border:2px solid var(--vr-acc);border-radius:12px;min-width:110px;text-align:center}
.vr-gen.bump{animation:vrbump .5s ease}@keyframes vrbump{40%{transform:scale(1.15)}}
.vr-ks{display:flex;gap:6px;align-items:center;flex-wrap:wrap}
.vr-pill{font-weight:700;padding:4px 10px;border-radius:999px;font-size:12px;background:var(--vr-soft);border:1px solid var(--vr-line)}
.vr-pill.run{background:#dcfce7;color:#166534;border-color:#86efac}.vr-pill.halt{background:#fef3c7;color:#92400e;border-color:#f59e0b;animation:vrblink 1s infinite}
@keyframes vrblink{50%{opacity:.6}}
.vr-btn{border:1px solid var(--vr-line);background:var(--vr-card);color:var(--vr-fg);border-radius:8px;padding:7px 11px;font:inherit;font-weight:600;cursor:pointer}
.vr-btn:hover:not(:disabled){border-color:var(--vr-acc)}.vr-btn:disabled{opacity:.5;cursor:not-allowed}
.vr-btn:focus-visible,.vr-in:focus-visible{outline:2px solid var(--vr-acc);outline-offset:2px}
.vr-btn.pri{background:var(--vr-acc);border-color:var(--vr-acc);color:#fff}.vr-btn.kill{background:#dc2626;border-color:#dc2626;color:#fff}
.vr-btn.warn{border-color:#f59e0b}.vr-btn.sm{padding:3px 8px;font-size:12px}
.vr-in{border:1px solid var(--vr-line);background:var(--vr-card);color:var(--vr-fg);border-radius:8px;padding:6px 8px;font:inherit;width:120px}
.vr-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.25fr);gap:12px}
.vr-card{background:var(--vr-card);border:1px solid var(--vr-line);border-radius:12px;padding:12px;margin-bottom:12px;min-width:0}
.vr-card h3{margin:0 0 8px;font-size:13px;text-transform:uppercase;letter-spacing:.04em;color:var(--vr-mut)}
.vr-prompt{background:var(--vr-soft);border-radius:8px;padding:8px;white-space:pre-wrap;word-break:break-word}
.vr-tags{display:flex;flex-wrap:wrap;gap:4px;margin-top:6px}.vr-tag{font:12px ui-monospace,Consolas,monospace;background:var(--vr-soft);border:1px solid var(--vr-line);border-radius:6px;padding:1px 6px}
.vr-tag.add{background:var(--vr-delbg);border-color:var(--vr-bad);color:var(--vr-fg);font-weight:700}
.vr-k{color:var(--vr-mut);font-size:12px;min-width:56px;display:inline-block}
.vr-props{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:6px}
.vr-props .vr-btn{text-align:left}
.vr-diff{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:8px}.vr-diff>div{min-width:0}
.vr-diff ins{background:var(--vr-addbg);text-decoration:none;border-radius:3px}.vr-diff del{background:var(--vr-delbg);border-radius:3px}
.vr-meta{color:var(--vr-mut);font-size:12px;margin:6px 0}
.vr-steps{list-style:none;margin:0;padding:0}.vr-steps li{display:flex;gap:8px;padding:6px 0;border-bottom:1px dashed var(--vr-line);animation:vrin .25s ease}
@keyframes vrin{from{opacity:0;transform:translateY(-4px)}}
.vr-ic{flex:0 0 20px;height:20px;border-radius:50%;display:grid;place-items:center;font-weight:800;color:#fff;font-size:12px}
.vr-ic.ok{background:var(--vr-ok)}.vr-ic.no{background:var(--vr-bad)}.vr-ic.wait{background:var(--vr-mut)}
.vr-steps b{display:block}.vr-steps small{color:var(--vr-mut);word-break:break-word}
.vr-gate{font:12px ui-monospace,Consolas,monospace;background:var(--vr-soft);border-radius:6px;padding:2px 6px;display:inline-block;margin-top:3px}
.vr-stamp{margin:10px 0 2px;text-align:center;font:900 26px/1.1 system-ui;letter-spacing:.06em;border:4px solid;border-radius:12px;padding:10px;transform:rotate(-2deg);animation:vrstamp .35s ease}
.vr-stamp small{display:block;font:600 13px system-ui;letter-spacing:0;margin-top:4px}
@keyframes vrstamp{from{transform:scale(1.6) rotate(-6deg);opacity:0}}
.vr-stamp.ALLOW{color:var(--vr-ok);border-color:var(--vr-ok)}.vr-stamp.DENY{color:var(--vr-bad);border-color:var(--vr-bad)}.vr-stamp.HALTED{color:var(--vr-warn);border-color:var(--vr-warn)}
.vr-loop{display:flex;gap:4px;margin-top:8px}.vr-loop span{flex:1;height:10px;border-radius:4px;background:var(--vr-soft);border:1px solid var(--vr-line)}
.vr-loop span.ALLOW{background:var(--vr-ok)}.vr-loop span.DENY{background:var(--vr-bad)}.vr-loop span.HALTED{background:var(--vr-warn)}.vr-loop span.cur{background:var(--vr-acc);animation:vrblink 1s infinite}
.vr-banner{background:#fef3c7;color:#92400e;border:2px solid #f59e0b;border-radius:10px;padding:8px 10px;font-weight:700;margin-bottom:10px}
.vr-table{width:100%;border-collapse:collapse;font-size:12px}.vr-table th,.vr-table td{text-align:left;padding:5px 6px;border-bottom:1px solid var(--vr-line);vertical-align:top}
.vr-table td.p{max-width:340px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.vr-v{font-weight:700}.vr-v.ALLOW{color:var(--vr-ok)}.vr-v.ROLLBACK{color:var(--vr-acc)}
.vr-empty{color:var(--vr-mut);text-align:center;padding:18px}
.vr-err{color:var(--vr-bad);padding:8px 0}
.vr-about{background:var(--vr-soft);border-radius:10px;padding:10px 12px;margin-bottom:12px}.vr-about p{margin:4px 0}
.vr-spin{display:inline-block;width:12px;height:12px;border:2px solid var(--vr-mut);border-top-color:transparent;border-radius:50%;animation:vrsp 1s linear infinite;vertical-align:-2px}
@keyframes vrsp{to{transform:rotate(360deg)}}
@media (max-width:760px){.vr-grid,.vr-diff,.vr-props{grid-template-columns:minmax(0,1fr)}.vr-gen{font-size:22px}}
@media (prefers-reduced-motion:reduce){.vr-root *{animation:none!important}}`;
// word-level diff (LCS); returns [old html, new html]
function wdiff(a, b) {
const A = String(a || '').split(/(\s+)/), B = String(b || '').split(/(\s+)/);
if (A.length * B.length > 250000) return [esc(a), '' + esc(b) + ''];
const n = A.length, m = B.length, L = Array.from({length: n + 1}, () => new Uint16Array(m + 1));
for (let i = n - 1; i >= 0; i--) for (let j = m - 1; j >= 0; j--) L[i][j] = A[i] === B[j] ? L[i + 1][j + 1] + 1 : Math.max(L[i + 1][j], L[i][j + 1]);
let i = 0, j = 0, o = '', w = '';
while (i < n && j < m) {
if (A[i] === B[j]) { o += esc(A[i]); w += esc(B[j]); i++; j++; }
else if (L[i + 1][j] >= L[i][j + 1]) { o += /^\s+$/.test(A[i]) ? esc(A[i]) : '' + esc(A[i]) + ''; i++; }
else { w += /^\s+$/.test(B[j]) ? esc(B[j]) : '' + esc(B[j]) + ''; j++; }
}
for (; i < n; i++) o += /^\s+$/.test(A[i]) ? esc(A[i]) : '' + esc(A[i]) + '';
for (; j < m; j++) w += /^\s+$/.test(B[j]) ? esc(B[j]) : '' + esc(B[j]) + '';
return [o, w];
}
const tags = (arr, added) => (arr && arr.length) ? arr.map(x => `${esc(x)}${added && added.includes(x) ? ' (new)' : ''}`).join('') : 'none';
window.VK_EXTRA_APPS = window.VK_EXTRA_APPS || [];
window.VK_EXTRA_APPS.push(h => ({
id: 'rsi', name: () => 'RSI Lab', color: '#9333EA', icon: ICON, w: 1080, h: 720,
render(body, win) {
if (!document.getElementById('vr-style')) { const st = document.createElement('style'); st.id = 'vr-style'; st.textContent = css; document.head.appendChild(st); }
const toast = m => { try { h.toast(m); } catch (e) {} };
body.innerHTML = '';
const root = document.createElement('div'); root.className = 'vr-root'; root.tabIndex = -1; body.appendChild(root);
let state = null, prop = null, busy = false, kstate = 'UNKNOWN', loop = null, about = false, lastRes = null, alive = true;
root.innerHTML = `
The agent improves its own skills. The kill switch sits above the whole loop.
Skill-level RSI: prompt, tools and workflow. No weight training in this demo.
${esc(String(v.sha || '').slice(0, 10))}| Gen | Verdict | Prompt | sha256 |
|---|
What is skill-level RSI? Recursive self-improvement here means the agent rewrites its own skill: the instruction prompt, the tool list and the workflow. Each accepted change becomes a new generation that can itself be improved again.
No weight training in this demo. The model (Meta Muse Spark) only proposes text. No model weights are trained or changed.
Why widening is denied. An agent that can grant itself new tools, egress domains or paths can escape its own manifest. A self-modification may keep or shrink permissions, never add them; a human publisher must do that through the store.
Why protected targets are denied. The kernel, policy, audit log and kill switch sit above the loop. A change that touches them, or a prompt that asks to disable or bypass them, is denied and recorded by the real ViKernel kernel with an audit number.
Every accepted change is a real signed .vdr package that passes the store review (hash list, publisher signature, permission risk, live gate dry-run, store countersignature). KILL halts everything, including this loop.