a11oy / web /autoreview.html
betterwithage's picture
chore(sync): mirror front-door files to Space (hf-sync)
e97df21 verified
Raw
History Blame Contribute Delete
35.8 kB
<!DOCTYPE html>
<!--
a11oy AUTO-REVIEW console — GOVERNED + SIGNED evolution of Cursor's Auto-review.
© 2026 Lutar, Stephen P. — SZL Holdings. SPDX-License-Identifier: Apache-2.0
0 runtime CDN: the ONLY external script is the in-image vendored Chart.js
(/vendor/chart.umd.min.js) plus in-image shared label/receipt engines. All data
is fetched live from /api/a11oy/v1/autoreview/*. Every rate is MEASURED from the
live decision log or honestly labelled ROADMAP — nothing fabricated.
Pattern credit: Cursor "Agent autonomy & Auto-review"
https://cursor.com/blog/agent-autonomy-auto-review — made GOVERNED (OPA/Rego +
OSCAL + NIST AI RMF MANAGE), Λ-gated (Conjecture 1, never 100%), DSSE-signed,
conformal-calibrated, with flapping detection.
-->
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>a11oy · Auto-Review (Governed Autonomy)</title>
<script src="/vendor/chart.umd.min.js"></script>
<script src="/static/shared/szl_label_engine.js"></script>
<script src="/static/shared/szl_receipt_cosign.js"></script>
<!-- F2: vendored F1 holographic kit (0 runtime CDN) for the optional 3D autonomy dial + verdict trust-sphere. -->
<script src="/static/shared/szl_holo3d.js"></script>
<style>
:root{
--bg:#0a0e14; --panel:#121823; --panel2:#0f141d; --line:#1f2a3a;
--ink:#e6edf3; --mut:#8b98a9; --acc:#5ad1c9; --acc2:#7aa2f7;
--ok:#3fb950; --warn:#d29922; --err:#f85149; --road:#a371f7;
}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--ink);
font:14px/1.5 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
header{padding:18px 22px;border-bottom:1px solid var(--line);
background:linear-gradient(180deg,#0d1320,#0a0e14)}
h1{margin:0;font-size:18px;letter-spacing:.3px}
.sub{color:var(--mut);font-size:12px;margin-top:4px;max-width:980px}
.wrap{max-width:1180px;margin:0 auto;padding:18px 22px}
.grid{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(340px,1fr))}
.card{background:var(--panel);border:1px solid var(--line);border-radius:10px;
padding:16px 18px}
.card.full{grid-column:1/-1}
.card h2{margin:0 0 10px;font-size:14px;letter-spacing:.4px;color:var(--acc)}
.kv{display:flex;justify-content:space-between;gap:10px;padding:3px 0;
border-bottom:1px dotted #1a2435}
.kv:last-child{border-bottom:0}
.k{color:var(--mut)} .v{color:var(--ink);text-align:right;word-break:break-word}
.big{font-size:30px;font-weight:700;letter-spacing:.5px}
.pill{display:inline-block;padding:2px 9px;border-radius:999px;font-size:11px;
border:1px solid var(--line)}
.pill.ok{color:var(--ok);border-color:#163a1f;background:#0e2113}
.pill.err{color:var(--err);border-color:#4a1c1c;background:#240f0f}
.pill.warn{color:var(--warn);border-color:#3a3015;background:#1f1a0a}
.pill.road{color:var(--road);border-color:#2e2147;background:#160f24}
.pill.acc{color:var(--acc);border-color:#13403c;background:#0a201e}
.cite{color:var(--mut);font-size:11px;margin-top:8px}
.cite code{color:var(--acc2)} .cite a{color:var(--acc2)}
.mono{font-family:inherit}
.set{display:flex;gap:8px;flex-wrap:wrap;margin:6px 0}
.set .lab{padding:4px 11px;border-radius:7px;border:1px solid var(--line);
background:#0e1622;font-size:13px}
.set .lab.in{border-color:#13403c;background:#0a201e;color:var(--acc)}
table{width:100%;border-collapse:collapse;font-size:12px}
th,td{text-align:left;padding:5px 7px;border-bottom:1px solid #1a2435;
vertical-align:top}
th{color:var(--mut);font-weight:600}
.note{color:var(--mut);font-size:11px;margin-top:8px;line-height:1.55}
.loading{color:var(--mut)} .err{color:var(--err)}
.sha{color:var(--acc2);font-size:11px}
a{color:var(--acc2)}
footer{color:var(--mut);font-size:11px;padding:14px 22px;border-top:1px solid var(--line)}
/* dial */
.dial{display:flex;gap:6px;flex-wrap:wrap;margin:6px 0 10px}
.dlv{flex:1 1 80px;min-width:78px;text-align:center;padding:8px 6px;border-radius:8px;
border:1px solid var(--line);background:#0e1622;cursor:pointer;font-size:12px;
transition:.12s}
.dlv:hover{border-color:var(--acc)}
.dlv.sel{border-color:var(--acc);background:#0a201e;color:var(--acc);font-weight:700}
.dlv .lv{font-size:16px;font-weight:700}
.dlv .nm{font-size:10px;color:var(--mut);margin-top:2px;line-height:1.3}
.dlv.sel .nm{color:var(--acc)}
.btn{display:inline-block;padding:7px 14px;border-radius:8px;border:1px solid var(--acc);
background:#0a201e;color:var(--acc);cursor:pointer;font:inherit;font-size:12px}
.btn:hover{background:#0d2b28}
/* react/inline review stream */
.step{border:1px solid var(--line);border-radius:8px;padding:10px 12px;margin:8px 0;
background:var(--panel2)}
.step .hd{display:flex;justify-content:space-between;gap:8px;align-items:center}
.step .act{font-size:11px;color:var(--mut);margin-top:6px}
.step.allow{border-left:3px solid var(--ok)}
.step.narrow{border-left:3px solid var(--warn)}
.step.block{border-left:3px solid var(--err)}
.step.escalate{border-left:3px solid var(--road)}
.ti{color:#b9c6d6;word-break:break-all}
.vd{font-size:11px}
.meta{font-size:11px;color:var(--mut);margin-top:6px;display:flex;gap:12px;flex-wrap:wrap}
.meta b{color:var(--ink)}
.explain{color:#cfd8e3;font-size:12px;margin-top:6px;border-top:1px dotted #1a2435;
padding-top:6px}
.selfc{color:var(--acc);font-size:11px;margin-top:4px}
/* F2 — 3D autonomy dial + verdict trust-sphere (additive; 2D content stays). */
#ar3d-toggle{background:#0e1622;border:1px solid var(--acc);color:var(--acc);border-radius:7px;
padding:6px 12px;font:12px ui-monospace,monospace;cursor:pointer;margin-top:8px}
#ar3d-panel{display:none;margin:16px 0;background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:16px}
#ar3d-panel h2{margin:0 0 8px;font-size:14px;letter-spacing:.4px;color:var(--acc)}
.ar3d-stage{display:grid;grid-template-columns:1.4fr 1fr;gap:14px}
@media(max-width:860px){.ar3d-stage{grid-template-columns:1fr}}
#ar3d-canvas{width:100%;height:400px;background:#070b12;border:1px solid var(--line);border-radius:8px;position:relative}
#ar3d-mode{position:absolute;top:8px;right:10px;font-size:10px;color:var(--mut);z-index:5}
.ar3d-side{display:flex;flex-direction:column;gap:10px}
.ar3d-box{background:#0e1622;border:1px solid var(--line);border-radius:8px;padding:10px}
.ar3d-box h3{margin:0 0 6px;font-size:11px;text-transform:uppercase;letter-spacing:.8px;color:var(--mut)}
.ar3d-dialrow{display:flex;gap:5px;flex-wrap:wrap;margin-bottom:8px}
.ar3d-dlv{flex:1;min-width:42px;text-align:center;padding:6px 4px;border:1px solid var(--line);
border-radius:7px;background:#0b121c;cursor:pointer;font-size:11px}
.ar3d-dlv.sel{border-color:var(--acc);color:var(--acc);background:#0a201e}
.ar3d-ctl{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-bottom:8px}
.ar3d-ctl input{background:#0e1622;color:var(--ink);border:1px solid var(--line);border-radius:6px;
padding:6px 9px;font:12px ui-monospace,monospace}
.ar3d-ctl button{background:#0e1622;color:var(--ink);border:1px solid var(--line);border-radius:6px;
padding:6px 11px;font:12px ui-monospace,monospace;cursor:pointer}
.ar3d-ctl button:hover{border-color:var(--acc)}
#ar3d-verdict{font-size:12px;color:var(--ink);line-height:1.6;min-height:18px}
#ar3d-lam{font-size:30px;font-weight:700;letter-spacing:.5px}
.ar3d-board{display:flex;gap:6px;flex-wrap:wrap;min-height:30px;align-items:center}
.ar3d-rcpt{padding:3px 8px;border-radius:7px;border:1px solid var(--line);background:#0b121c;
font-size:10px;animation:ar3d-in .5s ease}
@keyframes ar3d-in{from{opacity:0;transform:translateX(18px)}to{opacity:1;transform:none}}
.ar3d-rcpt.allow{border-color:var(--ok);color:var(--ok)}.ar3d-rcpt.narrow{border-color:var(--warn);color:var(--warn)}
.ar3d-rcpt.block-with-explanation{border-color:var(--err);color:var(--err)}.ar3d-rcpt.escalate{border-color:var(--road);color:var(--road)}
.ar3d-mut{color:var(--mut);font-size:11px}
</style>
</head>
<body>
<header>
<h1>a11oy · Auto-Review <span class="pill acc">GOVERNED AUTONOMY</span></h1>
<div class="sub">Our governed + signed evolution of Cursor's
<a href="https://cursor.com/blog/agent-autonomy-auto-review" target="_blank" rel="noopener">Auto-review</a>:
a context-aware classifier runs <b>INLINE before every Action node</b> in the ReAct loop.
Verdict ∈ {allow, narrow, block-with-explanation, escalate}, intent-relative, workspace-aware.
Each verdict is <b>Λ-gated</b> (Conjecture 1, never 100% safe), <b>DSSE-signed</b>, expressed as
<b>OPA/Rego</b> rules mapped to <b>OSCAL</b> controls + <b>NIST AI RMF MANAGE</b>, and
conformal-calibrated. On block we return an explanation so the parent self-corrects;
we escalate to a human only when truly needed. Effectors stay SIMULATED.</div>
<button id="ar3d-toggle" type="button">Show 3D autonomy</button>
</header>
<div class="wrap">
<!-- ===================== 3D AUTONOMY ENHANCEMENT (toggle; 2D below is the fallback) ===================== -->
<section id="ar3d-panel" aria-label="3D autonomy review">
<h2>3D AUTONOMY — dial L0–L5 drives a live Λ-gated verdict sphere</h2>
<div class="ar3d-stage">
<div id="ar3d-canvas"><div id="ar3d-mode">init…</div></div>
<div class="ar3d-side">
<div class="ar3d-box">
<h3>Autonomy dial (graded, not binary)</h3>
<div class="ar3d-dialrow" id="ar3d-dial"><span class="ar3d-mut">loading dial…</span></div>
<div id="ar3d-dialdesc" class="ar3d-mut"></div>
</div>
<div class="ar3d-box">
<h3>Classify an action (live /classify)</h3>
<div class="ar3d-ctl">
<input id="ar3d-intent" value="debug the auth flow" aria-label="intent" placeholder="intent"/>
</div>
<div class="ar3d-ctl">
<input id="ar3d-tool" value="shell" aria-label="tool" placeholder="tool" style="max-width:90px"/>
<input id="ar3d-input" value="cat .env api_key token" aria-label="tool input" placeholder="tool input"/>
<button id="ar3d-classify" type="button">▶ classify</button>
</div>
<div class="ar3d-mut" style="margin-bottom:6px">Verdict colors the trust-sphere by Λ-effective; each signed verdict animates a receipt chip onto the board below.</div>
<div id="ar3d-lam">Λ —</div>
<div id="ar3d-verdict" class="ar3d-mut">no verdict yet</div>
</div>
<div class="ar3d-box">
<h3>Signed-verdict receipts (board)</h3>
<div class="ar3d-board" id="ar3d-board"><span class="ar3d-mut">run a classify to sign verdicts onto the board</span></div>
</div>
</div>
</div>
<div class="cite" style="margin-top:10px">3D enhancement of the
<a href="https://cursor.com/blog/agent-autonomy-auto-review" target="_blank" rel="noopener">Cursor Auto-review</a>
autonomy-dial pattern, hardened with
<a href="https://github.com/invariantlabs-ai/invariant" target="_blank" rel="noopener">Invariant</a>-style
inline guardrails and
<a href="https://github.com/NVIDIA/NeMo-Guardrails" target="_blank" rel="noopener">NeMo Guardrails (Colang)</a>
dialogue rails. Each verdict stays Λ-gated (Conjecture 1, &lt; 1.0), DSSE-signed, never 100% safe.
Holographic kit vendored at <code>/static/shared/szl_holo3d.js</code> · 0 runtime CDN.</div>
</section>
<div class="grid">
<!-- AUTONOMY DIAL -->
<div class="card" id="dial-card">
<h2>AUTONOMY DIAL — L0–L5 (graded, not a binary switch)</h2>
<div id="dial" class="loading">loading dial…</div>
<div class="cite">SAE-style graded autonomy for agents. Higher levels auto-execute
more action classes; risky/secret/irreversible/effector actions still gate at
<em>every</em> level. Cursor Auto-review autonomy-dial pattern, made governed.</div>
</div>
<!-- MEASURED RATES -->
<div class="card" id="rates-card">
<h2>MEASURED RATES — block / interrupt / flap</h2>
<div id="rates" class="loading">measuring live…</div>
<div class="cite">Block-rate / interrupt-rate / flap-rate are MEASURED from the live
rolling decision log (label <em>ROADMAP</em> until enough real runs accrue). Cursor
reports ~4% blocked / ~7% chats interrupted — we <b>measure ours</b>, we do not borrow it.</div>
</div>
<!-- CALIBRATION + CONFORMAL -->
<div class="card" id="cal-card">
<h2>CALIBRATION (ECE/Brier gate) + CONFORMAL SET</h2>
<div id="cal" class="loading">measuring live…</div>
<canvas id="relchart" height="150" style="margin-top:10px"></canvas>
<div class="cite">ECE (equal-width bins) + Brier; gate ECE &lt; 0.05 required for any
automated (no-human) verdict, <b>fails closed</b> on unmeasured. Conformal set replaces
bare confidence % (Dev B's <code>szl_conformal</code> helper).
<code>arXiv:2505.15437</code> / <code>arXiv:2305.18404</code>.</div>
</div>
<!-- FLAPPING -->
<div class="card" id="flap-card">
<h2>FLAPPING DETECTION — verdict stability</h2>
<div id="flap" class="loading">measuring live…</div>
<div class="cite">FLAPPING = the same case (intent+tool+input+dial) gets DIFFERENT
verdicts across repeated runs. Flapping → policy is unstable → tighten it.</div>
</div>
<!-- INLINE REVIEW STREAM (gated-run) -->
<div class="card full" id="run-card">
<h2>INLINE REVIEW STREAM — block → explanation → self-correct trace</h2>
<div style="margin-bottom:10px">
<span class="k">demo intent:</span>
<input id="intent" value="debug the auth flow" style="width:280px;background:#0e1622;
color:var(--ink);border:1px solid var(--line);border-radius:6px;padding:5px 8px;
font:inherit;font-size:12px"/>
<span class="k" style="margin-left:10px">dial:</span>
<span id="run-dial" class="mono acc">L3</span>
<button class="btn" id="runbtn" style="margin-left:12px">▶ run gated ReAct plan</button>
</div>
<div id="run" class="loading">Click “run gated ReAct plan” — the classifier reviews each
Action node inline, signs each verdict, blocks the risky one with an explanation
(so the parent self-corrects), and allows the safe one.</div>
<div class="cite">Demonstrates the keystone: classifier runs subagent-style INLINE at
the Action node of Dev A's ReAct loop (<code>/api/a11oy/v1/agent/react/*</code>), not as
a separate round-trip. Each step carries a DSSE-signed receipt + the Rego rule hit + the
OSCAL control cited. A code-shaped step also shows its <b>a11oy Restraint rung</b>
(<code>/api/a11oy/v1/restraint</code>): a bloated diff that skipped the frugality ladder is
narrowed by <b>AR-006 prefer-minimal-diff</b> (OSCAL SA-8/SA-15/CM-7 · NIST AI RMF MANAGE 2.3).</div>
</div>
<!-- POLICY (Rego + OSCAL + NIST) -->
<div class="card full" id="pol-card">
<h2>POLICY — OPA/Rego rules → OSCAL controls → NIST AI RMF MANAGE</h2>
<div id="pol" class="loading">loading policy…</div>
<div class="cite">Rules authored in <a href="https://github.com/open-policy-agent/opa"
target="_blank" rel="noopener">OPA/Rego</a>; each maps to an
<a href="https://github.com/usnistgov/OSCAL" target="_blank" rel="noopener">OSCAL</a>
control (SP 800-53 Rev5 via
<a href="https://github.com/usnistgov/oscal-content" target="_blank" rel="noopener">oscal-content</a>)
and a <a href="https://airc.nist.gov/airmf-resources/airmf/5-sec-core/" target="_blank"
rel="noopener">NIST AI RMF MANAGE</a> subcategory. We MAP-TO / ALIGN-WITH — this is not a
certification or ATO.</div>
</div>
<!-- RECENT SIGNED DECISIONS -->
<div class="card full" id="recent-card">
<h2>RECENT DECISIONS — per-decision signed receipt + rule + control</h2>
<div id="recent" class="loading">loading live decision log…</div>
<div class="cite">Live rolling log. Each row carries the verdict, the Rego rule hit, the
OSCAL control(s), the Λ-effective value (&lt; 1.0), and the canonical decision hash that is
DSSE-signed into the node's receipt.</div>
</div>
</div>
</div>
<footer>
a11oy auto-review lane · Λ = Conjecture 1 (advisory, &lt; 1.0, never 100%) · trust &lt; 100% ·
tamper-evident DSSE · SLSA L1 honest / L2 in progress / L3 roadmap · effectors SIMULATED · 0 runtime CDN.
Data: <span class="mono">/api/a11oy/v1/autoreview/{dial,classify,gated-run,policy,metrics,recent,_diag}</span>
</footer>
<script>
const $=s=>document.querySelector(s);
const esc=s=>String(s==null?"":s).replace(/[&<>"']/g,function(c){return({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]||c);});
function kv(k,v){return `<div class="kv"><span class="k">${esc(k)}</span><span class="v">${v}</span></div>`}
async function getj(u){const r=await fetch(u);if(!r.ok)throw new Error(u+" -> "+r.status);return r.json()}
async function postj(u,b){const r=await fetch(u,{method:"POST",headers:{"content-type":"application/json"},
body:JSON.stringify(b||{})});if(!r.ok)throw new Error(u+" -> "+r.status);return r.json()}
const pct=x=>(x==null?"—":(x*100).toFixed(1)+"%");
function vpill(v){
const m={allow:"ok","narrow":"warn","block-with-explanation":"err","escalate":"road"};
return `<span class="pill ${m[v]||""}">${esc(v)}</span>`;
}
let DIAL=3;
// ---- AUTONOMY DIAL ----
getj("/api/a11oy/v1/autoreview/dial").then(d=>{
DIAL=d.default!=null?d.default:3;
let cells=(d.levels||[]).map(l=>
`<div class="dlv ${l.level===DIAL?"sel":""}" data-lv="${l.level}">
<div class="lv">L${l.level}</div>
<div class="nm">${esc((l.label||"").replace(/^L\d+\s*[—-]\s*/,""))}</div>
</div>`).join("");
$("#dial").innerHTML=`<div class="dial">${cells}</div><div id="dialdesc" class="note"></div>`;
const desc=()=>{const sel=(d.levels||[]).find(x=>x.level===DIAL)||{};
$("#dialdesc").innerHTML=`<b style="color:var(--acc)">L${DIAL}${esc((sel.label||"").replace(/^L\d+\s*[—-]\s*/,""))}</b>: ${esc(sel.desc||sel.policy||sel.description||"")}`;
$("#run-dial").textContent="L"+DIAL;};
desc();
document.querySelectorAll(".dlv").forEach(c=>c.addEventListener("click",()=>{
DIAL=parseInt(c.dataset.lv,10);
document.querySelectorAll(".dlv").forEach(x=>x.classList.toggle("sel",parseInt(x.dataset.lv,10)===DIAL));
desc();
}));
}).catch(e=>$("#dial").innerHTML=`<div class="err">dial unavailable: ${esc(e.message)}</div>`);
// ---- MEASURED RATES + CALIBRATION + FLAP (one /metrics call) ----
getj("/api/a11oy/v1/autoreview/metrics").then(d=>{
const meas=(d.rate_status||"").indexOf("MEASURED")>=0;
const stp=meas?`<span class="pill acc">MEASURED</span>`:`<span class="pill road">ROADMAP</span>`;
$("#rates").innerHTML=
`<div class="big">${pct(d.block_rate)}</div><div class="k" style="margin-top:-6px">block-rate ${stp}</div>`+
kv("decisions logged (n)",`<b>${d.decisions_logged}</b>`)+
kv("interrupt-rate",pct(d.interrupt_rate))+
kv("escalate-rate",pct(d.escalate_rate))+
kv("narrow-rate",pct(d.narrow_rate))+
kv("allow-rate",pct(d.allow_rate))+
`<div class="note">${esc(d.honest_target||"")}</div>`;
// calibration + conformal
const m=d.calibration||{};
const measured=m.status==="measured";
const gateok=(m.ece!=null)&&(m.ece<(m.ece_gate_threshold||0.05));
$("#cal").innerHTML=
kv("model / agent",`<span class="mono">${esc(m.model)} / ${esc(m.agent_type)}</span>`)+
kv("status",measured?`<span class="pill acc">measured</span>`:`<span class="pill warn">${esc(m.status)}</span>`)+
kv("samples (n)",m.n)+
kv("ECE",`<b class="mono">${measured?m.ece.toFixed(4):"not_measured"}</b>`)+
kv("Brier"+(m.brier_kind?` (${esc(m.brier_kind)})`:""),`<span class="mono">${m.brier!=null?m.brier.toFixed(4):"—"}</span>`)+
kv("accuracy",pct(m.accuracy))+
kv("auto-response gate",gateok?`<span class="pill ok">ALLOW (ECE&lt;${m.ece_gate_threshold||0.05})</span>`:`<span class="pill err">DENY → human-on-loop</span>`)+
`<div class="note">Λ-effective is capped &lt; 1.0 (Conjecture 1): we never claim 100% safe.</div>`;
const arr=Array.isArray(m.reliability)?m.reliability.filter(b=>b.count>0):[];
if(window.Chart&&arr.length){
new Chart($("#relchart"),{type:"bar",
data:{labels:arr.map(b=>(b.lo!=null?b.lo:0).toFixed(2)),
datasets:[
{label:"accuracy",data:arr.map(b=>b.accuracy),backgroundColor:"#5ad1c9"},
{label:"mean confidence",data:arr.map(b=>b.mean_conf),type:"line",borderColor:"#7aa2f7",fill:false}
]},
options:{plugins:{legend:{labels:{color:"#8b98a9"}}},
scales:{x:{ticks:{color:"#8b98a9"},grid:{color:"#1a2435"}},
y:{min:0,max:1,ticks:{color:"#8b98a9"},grid:{color:"#1a2435"}}}}});
} else { $("#relchart").style.display="none"; }
// flapping
const f=d.flapping||{};
$("#flap").innerHTML=
`<div class="big">${pct(f.flap_rate)}</div><div class="k" style="margin-top:-6px">flap-rate <span class="pill ${ (f.flap_rate_status||"").indexOf("MEASURED")>=0?"acc":"road"}">${esc(f.flap_rate_status||"ROADMAP")}</span></div>`+
kv("cases seen",f.cases_seen)+
kv("cases repeated",f.cases_repeated)+
kv("cases flapping",f.cases_flapping!=null?`<b>${f.cases_flapping}</b>`:"—")+
`<div class="note">${esc(f.definition||"")}</div>`;
}).catch(e=>{
$("#rates").innerHTML=`<div class="err">metrics unavailable: ${esc(e.message)}</div>`;
$("#cal").innerHTML=$("#flap").innerHTML=`<div class="err">unavailable</div>`;
});
// ---- INLINE REVIEW STREAM ----
function renderRun(d){
const cls={allow:"allow","narrow":"narrow","block-with-explanation":"block","escalate":"escalate"};
let steps=(d.trace||[]).map(s=>{
const signed=s.signed?`<span class="pill ok">DSSE signed</span>`:`<span class="pill warn">unsigned</span>`;
const conf=(s.conformal_set||[]).join(", ");
return `<div class="step ${cls[s.verdict]||""}">
<div class="hd">
<div><span class="k">#${s.seq} ${esc(s.node)}</span>
<span class="ti"> → ${esc(s.tool)}: <code>${esc(s.tool_input)}</code></span></div>
<div class="vd">${vpill(s.verdict)} ${signed}</div>
</div>
<div class="act">${esc(s.action)}</div>
${s.explanation?`<div class="explain">${esc(s.explanation)}</div>`:""}
${s.self_correct_hint?`<div class="selfc">↻ self-correct hint: ${esc(s.self_correct_hint)}</div>`:""}
<div class="meta">
<span>rule <b>${esc(s.rule_id||"—")}</b></span>
<span>OSCAL <b>${esc((s.oscal_controls||[]).join(", ")||"—")}</b></span>
<span>NIST <b>${esc(s.nist_ai_rmf||"—")}</b></span>
<span>Λ-eff <b>${s.lambda_effective!=null?s.lambda_effective.toFixed(3):"—"}</b></span>
<span>conformal {<b>${esc(conf)}</b>}</span>
<span>restraint ${(s.restraint&&s.restraint.code_shaped)?`rung <b>${esc(String(s.restraint_rung!=null?s.restraint_rung:"?"))}/6 ${esc(s.restraint.rung_key||"")}</b>${s.restraint.bloated?` · <b class="acc">bloated → prefer minimal diff</b>`:` · within ladder`}`:`<b>n/a (not code)</b>`}</span>
<span class="sha">hash ${esc((s.decision_hash||"").slice(0,20))}…</span>
</div></div>`;
}).join("");
$("#run").innerHTML=
`<div class="note" style="margin-bottom:8px">${esc(d.pattern||"")} · dial <b class="acc">L${d.dial}${esc((d.dial_label||"").replace(/^L\d+\s*[—-]\s*/,""))}</b></div>`+
steps;
}
$("#runbtn").addEventListener("click",async()=>{
$("#run").innerHTML=`<div class="loading">running inline review at each Action node…</div>`;
try{
const d=await postj("/api/a11oy/v1/autoreview/gated-run",
{intent:$("#intent").value,dial:DIAL,
actions:[
{tool:"read",tool_input:"README.md"},
{tool:"shell",tool_input:"cat .env api_key token"},
{tool:"shell",tool_input:"rm -rf / production"},
{tool:"write_file",tool_input:"# format the current date as ISO 8601\nclass DateFormatter:\n def __init__(self, sep='-', upper=False):\n self.sep = sep\n self.upper = upper\n def _pad(self, n):\n s = str(n)\n return s if len(s) >= 2 else '0' + s\n def format(self, y, m, d):\n parts = [self._pad(y), self._pad(m), self._pad(d)]\n out = self.sep.join(parts)\n return out.upper() if self.upper else out\n"}
]});
renderRun(d);
}catch(e){$("#run").innerHTML=`<div class="err">gated-run failed: ${esc(e.message)}</div>`;}
});
// ---- POLICY ----
getj("/api/a11oy/v1/autoreview/policy").then(d=>{
let rows=(d.rules||[]).map(r=>
`<tr><td class="mono">${esc(r.id)}</td><td>${esc(r.title)}</td><td>${vpill(r.verdict)}</td>
<td class="mono">${esc((r.oscal||[]).join(", "))}</td>
<td class="mono">${esc(r.nist_ai_rmf)}</td></tr>`).join("");
const cdroot=d.oscal_component_definition||{};
const ocd=cdroot["component-definition"]||{};
const comp=(ocd.components||[])[0]||{};
const ci=(comp["control-implementations"]||[])[0]||{};
const ireqs=(ci["implemented-requirements"]||[]).length;
const otitle=(ocd.metadata||{}).title||"component-definition";
$("#pol").innerHTML=
kv("policy version",`<span class="mono">${esc(d.policy_version)}</span>`)+
kv("rego sha256",`<span class="sha mono">${esc((d.rego_sha256||"").slice(0,32))}…</span>`)+
kv("engine",`<span class="pill road">in-image deterministic eval (opa runtime ROADMAP)</span>`)+
kv("honesty",`<span class="note">${esc(d.honest)}</span>`)+
`<table style="margin-top:10px"><tr><th>rule id</th><th>title</th><th>verdict</th><th>OSCAL</th><th>NIST AI RMF</th></tr>${rows}</table>`+
`<div class="note" style="margin-top:8px">OSCAL component-definition: <b>${esc(otitle)}</b> · <b>${ireqs}</b> implemented requirements (SP 800-53 Rev5 + NIST AI RMF MANAGE).</div>`;
}).catch(e=>$("#pol").innerHTML=`<div class="err">policy unavailable: ${esc(e.message)}</div>`);
// ---- RECENT DECISIONS ----
getj("/api/a11oy/v1/autoreview/recent?limit=25").then(d=>{
let rows=(d.recent||[]).map(r=>
`<tr><td class="mono">${esc((r.ts||"").slice(11,19))}</td>
<td>${esc(r.intent||"")}</td>
<td class="ti"><code>${esc(r.tool)}: ${esc((r.tool_input||"").slice(0,46))}</code></td>
<td>L${r.dial}</td>
<td>${vpill(r.verdict)}</td>
<td class="mono">${esc(r.rule_id||"—")}</td>
<td class="mono">${esc((r.oscal||[]).join(", "))}</td>
<td class="mono">${esc(r.nist||"")}</td>
<td class="mono">${r.lambda_effective!=null?r.lambda_effective.toFixed(3):"—"}</td>
<td class="sha">${esc((r.decision_hash||"").slice(0,14))}…</td></tr>`).join("");
$("#recent").innerHTML=
`<table><tr><th>time</th><th>intent</th><th>action</th><th>dial</th><th>verdict</th>
<th>Rego rule</th><th>OSCAL</th><th>NIST</th><th>Λ-eff</th><th>decision hash (signed)</th></tr>
${rows||`<tr><td colspan="10" class="k">no decisions logged yet</td></tr>`}</table>`;
}).catch(e=>$("#recent").innerHTML=`<div class="err">recent unavailable: ${esc(e.message)}</div>`);
// honesty audit of our own copy (catch "100%", "tamper-proof", etc.)
try{ if(window.SZLLabels&&SZLLabels.auditText){
const flags=SZLLabels.auditText(document.body.innerText||"");
if(flags&&flags.length){console.warn("[autoreview] label audit flags:",flags);}
}}catch(_){}
</script>
<script>
/* F2 Auto-Review 3D (additive) */
/* F2 — Auto-Review 3D controller (additive enhancement; 2D content is the fallback).
* 0 runtime CDN: kit is vendored at /static/shared/szl_holo3d.js (imported only).
* Reads LIVE /api/a11oy/v1/autoreview/{dial,classify}. Λ-gated (Conjecture 1, <1.0),
* DSSE-signed verdicts, trust < 100%. Never fabricates metrics. */
(function () {
"use strict";
var BASE = "/api/a11oy/v1/autoreview";
var Q = function (id) { return document.getElementById(id); };
var ESC = function (s) {
return String(s == null ? "" : s).replace(/[&<>"']/g,function(c){return({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]||c);});
};
// verdict -> board chip class (matches .ar3d-rcpt.<verdict> CSS)
var VCLASS = {
"allow": "allow", "narrow": "narrow",
"block-with-explanation": "block-with-explanation", "escalate": "escalate"
};
var scene = null, sphere = null, dial = 3, dialLevels = [], built = false, signed = 0;
function getj(u) {
return fetch(u).then(function (r) {
if (!r.ok) { throw new Error(u + " -> " + r.status); }
return r.json();
});
}
function postj(u, b) {
return fetch(u, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify(b || {})
}).then(function (r) {
if (!r.ok) { throw new Error(u + " -> " + r.status); }
return r.json();
});
}
function setMode() {
var el = Q("ar3d-mode");
if (!el) { return; }
if (!window.SZLHolo) { el.textContent = "3D kit unavailable — using 2D content below"; return; }
try {
var caps = SZLHolo.capabilities();
el.textContent = "render: " + (caps.mode || "?") + (caps.webgl2 ? " (webgl2)" : "");
} catch (_) { el.textContent = "render: ready"; }
}
// ---- AUTONOMY DIAL (live /dial) ----
function loadDial() {
return getj(BASE + "/dial").then(function (d) {
dialLevels = d.levels || [];
dial = (d.default != null) ? d.default : 3;
renderDial();
}).catch(function (e) {
var r = Q("ar3d-dial");
if (r) { r.innerHTML = '<span class="ar3d-mut">dial unavailable: ' + ESC(e.message) + "</span>"; }
});
}
function renderDial() {
var row = Q("ar3d-dial");
if (!row) { return; }
row.innerHTML = dialLevels.map(function (l) {
return '<div class="ar3d-dlv' + (l.level === dial ? " sel" : "") +
'" data-lv="' + l.level + '">L' + l.level + "</div>";
}).join("");
var cells = row.querySelectorAll(".ar3d-dlv");
for (var i = 0; i < cells.length; i++) {
cells[i].addEventListener("click", function (ev) {
dial = parseInt(ev.currentTarget.getAttribute("data-lv"), 10);
renderDial();
describeDial();
});
}
describeDial();
}
function describeDial() {
var el = Q("ar3d-dialdesc");
if (!el) { return; }
var sel = null;
for (var i = 0; i < dialLevels.length; i++) {
if (dialLevels[i].level === dial) { sel = dialLevels[i]; break; }
}
sel = sel || {};
var label = (sel.label || "").replace(/^L\d+\s*[\u2014-]\s*/, "");
el.innerHTML = '<b style="color:var(--acc)">L' + dial + " — " + ESC(label) + "</b>: " +
ESC(sel.desc || sel.policy || sel.description || "");
}
// ---- 3D SCENE + verdict trust-sphere ----
function ensureScene() {
if (built) { return true; }
var mount = Q("ar3d-canvas");
if (!mount || !window.SZLHolo) { return false; }
try {
scene = SZLHolo.createScene(mount, { sample: false });
// verdict trust-sphere — starts at a neutral, honest sub-1.0 Λ
sphere = scene.addTrustSphere({ center: [0, 0, 0], radius: 0.8, lambda: 0.5, label: "VERDICT" });
scene.setLambda(0.5);
scene.start();
built = true;
setMode();
return true;
} catch (e) {
var el = Q("ar3d-mode");
if (el) { el.textContent = "3D init failed — 2D content below is intact"; }
return false;
}
}
// map a verdict to a board chip + animate it onto the board
function pushReceipt(d) {
var board = Q("ar3d-board");
if (!board) { return; }
if (signed === 0) { board.innerHTML = ""; }
signed += 1;
var v = d.verdict || "—";
var lam = (typeof d.lambda_effective === "number") ? d.lambda_effective : null;
var sig = d.receipt && d.receipt.envelope && d.receipt.envelope.signed;
var hash = (d.decision_hash || "").slice(0, 12);
var chip = document.createElement("div");
chip.className = "ar3d-rcpt " + (VCLASS[v] || "");
chip.innerHTML = "#" + signed + " " + ESC(v) +
(lam != null ? " · Λ" + lam.toFixed(2) : "") +
(sig ? " · ✔signed" : " · unsigned") +
(hash ? ' · <span style="opacity:.7">' + ESC(hash) + "…</span>" : "");
board.appendChild(chip);
}
// ---- CLASSIFY (live /classify) -> recolor sphere by Λ, sign receipt onto board ----
function classify() {
var btn = Q("ar3d-classify");
if (btn) { btn.disabled = true; }
var verdEl = Q("ar3d-verdict");
if (verdEl) { verdEl.textContent = "classifying…"; }
// NOTE: /classify treats `workspace` as an object; omit it (string 500s the endpoint).
var body = {
intent: (Q("ar3d-intent") || {}).value || "",
tool: (Q("ar3d-tool") || {}).value || "",
tool_input: (Q("ar3d-input") || {}).value || "",
dial: dial
};
return postj(BASE + "/classify", body).then(function (d) {
var lam = (typeof d.lambda_effective === "number") ? d.lambda_effective : 0.5;
// honest: Λ stays < 1.0 (Conjecture 1) — clamp just under 1
if (lam >= 1.0) { lam = 0.999; }
if (sphere) { sphere.lambda = lam; }
if (scene) { scene.setLambda(lam); }
var lamEl = Q("ar3d-lam");
if (lamEl) {
lamEl.textContent = "Λ " + lam.toFixed(3);
if (window.SZLHolo && SZLHolo.lambdaColor) { lamEl.style.color = SZLHolo.lambdaColor(lam); }
}
if (verdEl) {
verdEl.innerHTML = "<b>" + ESC(d.verdict || "—") + "</b> (L" +
ESC(d.dial != null ? d.dial : dial) + ") · rule <b>" + ESC(d.rule_id || "—") +
"</b> · OSCAL " + ESC((d.oscal_controls || []).join(", ") || "—") +
"<br>" + ESC(d.explanation || "");
verdEl.className = "";
}
pushReceipt(d);
}).catch(function (e) {
if (verdEl) { verdEl.innerHTML = '<span style="color:var(--err)">classify failed: ' + ESC(e.message) + "</span>"; }
}).then(function () {
if (btn) { btn.disabled = false; }
});
}
// ---- TOGGLE (keeps 2D content as fallback) ----
function toggle() {
var panel = Q("ar3d-panel");
var btn = Q("ar3d-toggle");
if (!panel) { return; }
var showing = panel.style.display !== "none" && panel.style.display !== "";
if (showing) {
panel.style.display = "none";
if (btn) { btn.textContent = "Show 3D autonomy"; }
if (scene && scene.stop) { try { scene.stop(); } catch (_) {} }
} else {
panel.style.display = "block";
if (btn) { btn.textContent = "Hide 3D autonomy"; }
if (ensureScene() && scene && scene.start) { try { scene.start(); } catch (_) {} }
}
}
function init() {
var btn = Q("ar3d-toggle");
if (btn) { btn.addEventListener("click", toggle); }
var cb = Q("ar3d-classify");
if (cb) { cb.addEventListener("click", classify); }
loadDial();
setMode();
if (!window.SZLHolo) {
var el = Q("ar3d-mode");
if (el) { el.textContent = "3D kit unavailable — 2D content below is the fallback"; }
}
// expose hooks for live verification
window.__AR3D_toggle = toggle;
window.__AR3D_classify = classify;
window.__AR3D_state = function () {
return { built: built, dial: dial, signed: signed, lambda: sphere ? sphere.lambda : null };
};
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", init);
} else {
init();
}
})();
</script>
</body>
</html>