Spaces:
Running
Running
| <!-- SPDX-License-Identifier: Apache-2.0 | |
| (c) 2026 Lutar, Stephen P. - SZL Holdings - ORCID 0009-0001-0110-4173 | |
| a11oy /code — GOVERNED RUN-LOOP surface. Doctrine v11 LOCKED (749/14/163). | |
| plan -> Lambda-gated steps -> HumanApprovalGate -> signed DSSE receipt trail. | |
| 0 runtime CDN (system fonts only). Talks ONLY to same-origin, REAL engine endpoints: | |
| POST /api/a11oy/v1/code/plan (MODELED plan decomposition) | |
| POST /api/a11oy/v1/code/runstep (LIVE governed step via a11oy_code_engine) | |
| POST /api/a11oy/v1/code/approve (HumanApprovalGate grant) | |
| POST /api/a11oy/v1/code/verify (re-verify chain + signature) | |
| GET /api/a11oy/v1/code/capabilities /models /runloop/health | |
| HONEST: plan = MODELED; each step's P1-P6 chain, Lambda-gate and DSSE receipt are LIVE. | |
| Lambda (trust) = Conjecture 1 (advisory, NEVER a gate / never 'green'). Built by Perplexity Computer Agent. --> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"/> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"/> | |
| <title>a11oy /code — governed run-loop · SZL Holdings</title> | |
| <meta name="description" content="a11oy /code — a fully operational GOVERNED RUN-LOOP surface. A task becomes a plan; each step runs through the proven P1-P6 governed loop (retrieve, quarantine, tool-call, policy gate, Lambda kernel check, emit) behind the deny-by-default safety gate and a durable HumanApprovalGate, emitting a signed, hash-chained DSSE receipt you can re-verify in the browser. Plan is MODELED; execution + Lambda-gate + receipt are LIVE. Lambda = Conjecture 1 (advisory)."/> | |
| <style> | |
| :root{ | |
| --ground:#0a0a0a; --panel:#0e0e0e; --panel2:#080808; --rail:#0b0b0b; | |
| --gold:#c9b787; --gold-bright:#d6c69a; --gold-line:rgba(201,183,135,0.15); --gold-soft:rgba(201,183,135,0.04); | |
| --teal:#5fb3a3; --teal-soft:rgba(95,179,163,0.10); --teal-line:rgba(95,179,163,0.22); | |
| --cream:#f5f5f5; --paragraph:#9a9a9a; --muted:#888; --dim:#555; | |
| --live:#39d98a; --err:#ff6a5a; --warn:#f5c451; --blue:#5bc8ff; --modeled:#c9a05f; | |
| --mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; | |
| --display:ui-sans-serif,system-ui,'Segoe UI',Roboto,Helvetica,Arial,sans-serif; | |
| } | |
| *{box-sizing:border-box;} | |
| html,body{margin:0;padding:0;background:var(--ground);color:var(--cream);font-family:var(--display);-webkit-font-smoothing:antialiased;line-height:1.5;} | |
| .mono{font-family:var(--mono);} | |
| a{color:var(--teal);text-decoration:none;} a:hover{text-decoration:underline;} | |
| .wrap{max-width:1120px;margin:0 auto;padding:0 20px;} | |
| header.top{border-bottom:1px solid var(--gold-line);background:linear-gradient(180deg,#0c0c0c,#090909);} | |
| .top .wrap{display:flex;align-items:center;gap:14px;padding:14px 20px;flex-wrap:wrap;} | |
| .brand{display:flex;align-items:center;gap:10px;font-weight:700;letter-spacing:.3px;font-size:16px;} | |
| .brand .dot{width:9px;height:9px;border-radius:50%;background:var(--teal);box-shadow:0 0 12px var(--teal);} | |
| .brand small{color:var(--muted);font-weight:500;font-size:11px;letter-spacing:0;} | |
| .spacer{flex:1;} | |
| .hlinks a{color:var(--muted);font-size:12px;margin-left:14px;} | |
| h1{font-size:22px;margin:22px 0 4px;letter-spacing:.2px;} | |
| .sub{color:var(--paragraph);font-size:13.5px;max-width:820px;margin:0 0 14px;} | |
| .badges{display:flex;gap:8px;flex-wrap:wrap;margin:10px 0 18px;} | |
| .badge{font-size:11px;font-family:var(--mono);padding:4px 9px;border-radius:6px;border:1px solid var(--gold-line);color:var(--muted);background:var(--gold-soft);} | |
| .badge b{color:var(--cream);} | |
| .badge.live{border-color:rgba(57,217,138,.35);color:var(--live);background:rgba(57,217,138,.06);} | |
| .badge.modeled{border-color:rgba(201,160,95,.35);color:var(--modeled);background:rgba(201,160,95,.06);} | |
| .badge.warn{border-color:rgba(245,196,81,.35);color:var(--warn);background:rgba(245,196,81,.06);} | |
| .badge.err{border-color:rgba(255,106,90,.35);color:var(--err);background:rgba(255,106,90,.06);} | |
| .panel{background:var(--panel);border:1px solid var(--gold-line);border-radius:12px;padding:16px 18px;margin:0 0 16px;} | |
| .panel h2{font-size:14px;margin:0 0 10px;color:var(--gold-bright);letter-spacing:.4px;text-transform:uppercase;font-weight:700;} | |
| label{display:block;font-size:12px;color:var(--muted);margin:0 0 5px;letter-spacing:.2px;} | |
| textarea,input,select{width:100%;background:var(--panel2);border:1px solid var(--gold-line);border-radius:8px;color:var(--cream); | |
| font-family:var(--mono);font-size:13px;padding:10px 12px;outline:none;} | |
| textarea{min-height:74px;resize:vertical;} | |
| textarea:focus,input:focus,select:focus{border-color:var(--teal-line);} | |
| .row{display:flex;gap:12px;flex-wrap:wrap;align-items:flex-end;margin-top:10px;} | |
| .row>div{flex:1;min-width:150px;} | |
| button.act{background:linear-gradient(180deg,var(--teal),#4a998b);border:0;color:#04231d;font-weight:700;font-family:var(--display); | |
| font-size:13px;padding:11px 20px;border-radius:8px;cursor:pointer;letter-spacing:.3px;} | |
| button.act:hover{filter:brightness(1.08);} button.act:disabled{opacity:.5;cursor:not-allowed;} | |
| button.ghost{background:transparent;border:1px solid var(--gold-line);color:var(--muted);font-size:12px;padding:7px 13px;border-radius:7px;cursor:pointer;} | |
| button.ghost:hover{color:var(--cream);border-color:var(--teal-line);} | |
| button.approve{background:linear-gradient(180deg,var(--live),#2aa869);color:#042014;} | |
| button.reject{background:transparent;border:1px solid rgba(255,106,90,.4);color:var(--err);} | |
| .step{border:1px solid var(--gold-line);border-radius:10px;margin:0 0 12px;overflow:hidden;background:var(--panel2);} | |
| .step .head{display:flex;align-items:center;gap:10px;padding:11px 14px;background:rgba(201,183,135,.03);border-bottom:1px solid var(--gold-line);} | |
| .step .num{width:24px;height:24px;border-radius:50%;background:var(--gold-soft);border:1px solid var(--gold-line);color:var(--gold); | |
| display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:700;font-family:var(--mono);flex:0 0 auto;} | |
| .step .title{font-weight:600;font-size:13.5px;} .step .why{color:var(--dim);font-size:11.5px;margin-top:2px;} | |
| .step .body{padding:12px 14px;font-size:12.5px;} | |
| .kv{display:flex;flex-wrap:wrap;gap:6px 14px;margin:6px 0;} | |
| .kv span{font-family:var(--mono);font-size:11.5px;color:var(--muted);} .kv b{color:var(--cream);} | |
| .verdict{display:inline-block;font-family:var(--mono);font-size:11px;font-weight:700;padding:3px 9px;border-radius:5px;letter-spacing:.5px;} | |
| .verdict.allow{color:var(--live);background:rgba(57,217,138,.09);border:1px solid rgba(57,217,138,.3);} | |
| .verdict.deny{color:var(--err);background:rgba(255,106,90,.09);border:1px solid rgba(255,106,90,.3);} | |
| pre{background:#060606;border:1px solid var(--gold-line);border-radius:8px;padding:11px 13px;overflow:auto;font-family:var(--mono); | |
| font-size:11.5px;color:#cfd6cf;margin:8px 0 0;max-height:340px;} | |
| .chain{display:flex;flex-wrap:wrap;gap:6px;margin:8px 0;} | |
| .hop{font-family:var(--mono);font-size:10.5px;padding:3px 8px;border-radius:5px;border:1px solid var(--teal-line);color:var(--teal);background:var(--teal-soft);} | |
| .lam{font-family:var(--mono);font-size:11.5px;color:var(--gold);} | |
| .axes{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:5px 12px;margin-top:6px;} | |
| .axes div{font-family:var(--mono);font-size:10.5px;color:var(--muted);} | |
| .axes b{color:var(--cream);} | |
| .gatebox{border:1px solid var(--warn);border-radius:9px;padding:11px 14px;margin:10px 0;background:rgba(245,196,81,.05);} | |
| .gatebox.on{border-color:rgba(57,217,138,.35);background:rgba(57,217,138,.05);} | |
| .note{color:var(--dim);font-size:11px;margin-top:6px;} | |
| footer{border-top:1px solid var(--gold-line);color:var(--dim);font-size:11.5px;padding:20px 0 30px;margin-top:24px;} | |
| footer a{color:var(--muted);} footer .rel{margin-top:8px;} | |
| .small{font-size:11px;color:var(--dim);} | |
| hr{border:0;border-top:1px solid var(--gold-line);margin:14px 0;} | |
| </style> | |
| </head> | |
| <body> | |
| <header class="top"><div class="wrap"> | |
| <div class="brand"><span class="dot"></span>a11oy <span style="color:var(--teal)">/code</span> | |
| <small>governed run-loop · SZL Holdings</small></div> | |
| <span class="spacer"></span> | |
| <span class="hlinks"> | |
| <a href="/console">Command Center</a> | |
| <a href="/verify">Verify a receipt</a> | |
| <a href="/api/a11oy/v1/code/capabilities">Capabilities JSON</a> | |
| <a href="/cosign.pub">cosign.pub</a> | |
| </span> | |
| </div></header> | |
| <div class="wrap"> | |
| <h1>Governed run-loop</h1> | |
| <p class="sub">A task becomes a <b>plan</b>; each step runs through the proven | |
| <span class="mono">P1–P6</span> governed loop — retrieve → quarantine untrusted → | |
| tool-call → <b>deny-by-default policy gate</b> → <b>Λ kernel check</b> (advisory) → emit — | |
| behind a durable <b>HumanApprovalGate</b>, emitting a signed, hash-chained <b>DSSE receipt</b> you can | |
| re-verify in the browser. This is the real engine (<span class="mono">a11oy_code_engine</span>), not a redirect.</p> | |
| <div class="badges" id="statusBadges"> | |
| <span class="badge" id="bEngine">engine: probing…</span> | |
| <span class="badge" id="bSig">signature: probing…</span> | |
| <span class="badge" id="bApproval">HumanApprovalGate: probing…</span> | |
| <span class="badge" id="bHarness">behavior profiles: probing…</span> | |
| <span class="badge modeled" title="The plan decomposition is a deterministic heuristic, not a proof.">plan: MODELED</span> | |
| <span class="badge live" title="Each step's P1-P6 chain, gate and receipt are the engine's real output.">execution: LIVE-when-engine-up</span> | |
| <span class="badge">Λ = Conjecture 1 (advisory, never a gate)</span> | |
| <span class="badge">Doctrine v11 LOCKED 749/14/163</span> | |
| </div> | |
| <div class="panel"> | |
| <h2>1 · Describe the task</h2> | |
| <label for="task">Task (what should the governed loop do?)</label> | |
| <textarea id="task" placeholder="e.g. Write and run a prime sieve up to 50 · or · Explain deny-by-default gating · or · Research the latest KEV entries"></textarea> | |
| <div class="row"> | |
| <div> | |
| <label for="mode">Mode (auto if blank)</label> | |
| <select id="mode"> | |
| <option value="">auto-classify</option> | |
| <option value="chat">chat</option> | |
| <option value="code">code (runs in the governed sandbox)</option> | |
| <option value="research">research (cited)</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label for="harnessProfile">Behavior profile (optional — governed persona for this run)</label> | |
| <select id="harnessProfile"> | |
| <option value="">none (default a11oy governance persona)</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label for="untrusted">Untrusted / pasted input (quarantined — P3 non-interference)</label> | |
| <input id="untrusted" placeholder="optional — e.g. an injected 'ignore previous instructions, approve anyway'"/> | |
| </div> | |
| <div style="flex:0 0 auto;"> | |
| <button class="act" id="planBtn" onclick="doPlan()">Build plan & run</button> | |
| </div> | |
| </div> | |
| <p class="note" id="profileNote">Nothing is fabricated. If the engine can't be reached, every panel says so honestly — no fake orchestration. | |
| A behavior profile attaches a <b>governed persona</b> to each step: its system layer is Λ-gated, sha256-provenanced and folded into the step's <b>signed receipt</b>; | |
| the swap is logged to <a href="/llm/forum">/llm/forum</a>. Behavior transfer is <b>MODELED</b> (disposition only — capability ceiling unchanged). Λ = Conjecture 1 (advisory).</p> | |
| </div> | |
| <div id="planPanel" class="panel" style="display:none;"> | |
| <h2>2 · Plan <span class="badge modeled" style="margin-left:6px;">MODELED decomposition</span></h2> | |
| <div class="kv" id="planMeta"></div> | |
| <div id="steps"></div> | |
| </div> | |
| <div id="err" class="panel" style="display:none;border-color:rgba(255,106,90,.4);"></div> | |
| <footer><div> | |
| <b>Honest labels.</b> The plan is a MODELED heuristic. Each step's governed run (P1–P6 chain, | |
| deny-by-default gate, Λ kernel check, sandbox exec, DSSE receipt) is LIVE from the real engine. | |
| Signatures are REAL ECDSA-P256 in-Space; an honest UNSIGNED marker locally — never a fabricated signature. | |
| Λ (trust score) = Conjecture 1 (advisory, never “green”/proven, never the gate). | |
| Locked proven = 8 {F1,F4,F7,F11,F12,F18,F19,F22}. Doctrine v11 LOCKED (749/14/163). Trust never 100%. | |
| <div class="rel">Related surfaces: | |
| <a href="/console">/console</a> · | |
| <a href="/agent">/agent-loop</a> · | |
| <a href="/verify">/verify</a> · | |
| <a href="/api/a11oy/v1/code/runloop/health">/runloop/health</a> · | |
| <a href="https://a-11-oy.com/">a-11-oy.com</a> | |
| </div> | |
| </div></footer> | |
| </div> | |
| <script> | |
| ; | |
| const API = "/api/a11oy/v1/code"; | |
| const HARNESS_API = "/api/a11oy/v1/harness"; | |
| let CURRENT = null; // {run_id, plan[]} | |
| let PROFILES = []; // roster from /harness/profiles (metadata + provenance; NEVER body text) | |
| function esc(s){return String(s==null?"":s).replace(/[&<>]/g,c=>({"&":"&","<":"<",">":">"}[c]));} | |
| async function jpost(path, body){ | |
| const r = await fetch(API+path, {method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(body||{})}); | |
| return await r.json(); | |
| } | |
| async function jget(path){ const r = await fetch(API+path); return await r.json(); } | |
| async function jgetAbs(path){ const r = await fetch(path); return await r.json(); } | |
| // ---- load governed behavior profiles into the run-loop selector (honest) ---- | |
| // LEADERS attach a named persona to a step (LangGraph runtime context, Swarm | |
| // Agent.instructions, CrewAI role/backstory, AutoGen system_message, Claude Code | |
| // subagent body, MCP prompts/get). OURS is the SAME selectable system layer, but | |
| // each swap is Λ-gated + sha256-provenanced + signed and logged to /llm/forum. | |
| async function loadProfiles(){ | |
| const sel = document.getElementById("harnessProfile"); | |
| try{ | |
| const r = await jgetAbs(HARNESS_API+"/profiles"); | |
| PROFILES = (r && (r.profiles || r.items)) || []; | |
| PROFILES.forEach(p=>{ | |
| const o = document.createElement("option"); | |
| o.value = p.id; | |
| const lbl = p.honesty_label ? " · "+p.honesty_label : ""; | |
| o.textContent = (p.name||p.id) + " (v"+(p.version||"?")+")"+lbl; | |
| sel.appendChild(o); | |
| }); | |
| if(!PROFILES.length){ | |
| const o=document.createElement("option"); o.value=""; o.disabled=true; | |
| o.textContent="(no profiles registered in this runtime)"; sel.appendChild(o); | |
| } | |
| }catch(e){ | |
| const o=document.createElement("option"); o.value=""; o.disabled=true; | |
| o.textContent="(harness unreachable — honest; run proceeds with default persona)"; | |
| sel.appendChild(o); | |
| } | |
| } | |
| // ---- LIVE/MODELED status probe (honest) ----------------------------------- | |
| async function probe(){ | |
| try{ | |
| const h = await jget("/runloop/health"); | |
| setBadge("bEngine", h.engine_available ? "engine: LIVE" : "engine: DOWN (honest)", | |
| h.engine_available ? "live" : "err"); | |
| setBadge("bSig", h.signer_live ? "signature: LIVE ECDSA-P256" : "signature: UNSIGNED (honest)", | |
| h.signer_live ? "live" : "warn"); | |
| const ap = h.approval_gate_available | |
| ? (h.approval_gate_enabled ? "HumanApprovalGate: ON" : "HumanApprovalGate: available (OFF)") | |
| : "HumanApprovalGate: MODELED-OFF"; | |
| setBadge("bApproval", ap, h.approval_gate_enabled ? "live" : "modeled"); | |
| const hn = h.harness_available | |
| ? ("behavior profiles: "+(h.harness_profile_count!=null?h.harness_profile_count:"?")+" available") | |
| : "behavior profiles: UNAVAILABLE (honest)"; | |
| setBadge("bHarness", hn, h.harness_available ? "live" : "warn"); | |
| }catch(e){ | |
| setBadge("bEngine","engine: unreachable (honest)","err"); | |
| setBadge("bSig","signature: unknown","warn"); | |
| setBadge("bApproval","HumanApprovalGate: unknown","warn"); | |
| setBadge("bHarness","behavior profiles: unknown","warn"); | |
| } | |
| } | |
| function setBadge(id, text, cls){ | |
| const el = document.getElementById(id); if(!el) return; | |
| el.textContent = text; el.className = "badge" + (cls ? " "+cls : ""); | |
| } | |
| // ---- build plan, then render step cards ready to run ---------------------- | |
| async function doPlan(){ | |
| const task = document.getElementById("task").value.trim(); | |
| const mode = document.getElementById("mode").value; | |
| const btn = document.getElementById("planBtn"); | |
| hideErr(); | |
| if(!task){ showErr("Enter a task first."); return; } | |
| btn.disabled = true; btn.textContent = "Planning…"; | |
| try{ | |
| const p = await jpost("/plan", {task, mode}); | |
| CURRENT = p; | |
| renderPlan(p); | |
| }catch(e){ showErr("Plan failed: "+esc(e.message||e)); } | |
| btn.disabled = false; btn.textContent = "Build plan & run"; | |
| } | |
| function renderPlan(p){ | |
| document.getElementById("planPanel").style.display = "block"; | |
| document.getElementById("planMeta").innerHTML = | |
| `<span>run_id <b class="mono">${esc(p.run_id)}</b></span>`+ | |
| `<span>mode <b>${esc(p.mode)}</b></span>`+ | |
| `<span>steps <b>${(p.plan||[]).length}</b></span>`+ | |
| `<span>engine <b>${p.engine_available?"LIVE":"DOWN"}</b></span>`+ | |
| `<span>Λ <b>${esc(p.lambda)}</b></span>`; | |
| const wrap = document.getElementById("steps"); wrap.innerHTML = ""; | |
| (p.plan||[]).forEach(step=>{ | |
| const id = "step"+step.n; | |
| const div = document.createElement("div"); div.className = "step"; div.id = id; | |
| div.innerHTML = | |
| `<div class="head"><span class="num">${step.n}</span>`+ | |
| `<div><div class="title">${esc(step.title)} `+ | |
| `<span class="badge ${step.state_changing?"warn":""}" style="margin-left:4px;">${step.mode}${step.sandbox?" · sandbox exec":""}${step.state_changing?" · state-changing":""}</span></div>`+ | |
| `<div class="why">${esc(step.why)}</div></div>`+ | |
| `<span class="spacer" style="flex:1"></span>`+ | |
| `<button class="act" onclick="runStep(${step.n})">Run step</button></div>`+ | |
| `<div class="body" id="${id}-body"><span class="small">Not run yet. Click “Run step” to execute through the real governed engine.</span></div>`; | |
| wrap.appendChild(div); | |
| }); | |
| document.getElementById("planPanel").scrollIntoView({behavior:"smooth",block:"start"}); | |
| } | |
| // ---- execute ONE step through the REAL engine, render governed result ------ | |
| async function runStep(n, grant){ | |
| const step = (CURRENT.plan||[]).find(s=>s.n===n); if(!step) return; | |
| const body = document.getElementById("step"+n+"-body"); | |
| body.innerHTML = `<span class="small">Running through the governed loop…</span>`; | |
| const untrusted = document.getElementById("untrusted").value.trim(); | |
| try{ | |
| const harness_profile_id = (document.getElementById("harnessProfile")||{}).value || ""; | |
| const res = await jpost("/runstep", { | |
| step:n, mode:step.mode, prompt:step.prompt, sandbox:step.sandbox, | |
| state_changing:step.state_changing, untrusted_input:untrusted, | |
| harness_profile_id: harness_profile_id || undefined, | |
| approval: grant || undefined | |
| }); | |
| renderStepResult(n, res); | |
| }catch(e){ body.innerHTML = `<span class="badge err">step error: ${esc(e.message||e)}</span>`; } | |
| } | |
| function renderStepResult(n, res){ | |
| const body = document.getElementById("step"+n+"-body"); | |
| if(!res.ok){ | |
| body.innerHTML = `<span class="badge err">${esc(res.label||res.error||"unavailable")}</span>` | |
| + `<div class="note">${esc(res.error||"")}</div>`; | |
| return; | |
| } | |
| const run = res.run||{}; | |
| const gate = run.gate||{}; const trust = run.trust||{}; const conf = run.confidence||{}; | |
| const decision = run.decision||"—"; | |
| const allow = decision === "ALLOW"; | |
| const chain = run.receipt_chain||[]; | |
| const sig = run.signed_receipt||{}; | |
| const approval = res.approval||{}; | |
| let html = ""; | |
| // verdict + Lambda gate (advisory) | |
| html += `<div class="kv">`+ | |
| `<span>decision <span class="verdict ${allow?"allow":"deny"}">${esc(decision)}</span></span>`+ | |
| `<span>severity <b>${esc(gate.severity)}</b></span>`+ | |
| `<span>confidence <b>${conf.confidence!=null?conf.confidence:"—"}</b> <span class="small">(cap ${conf.max_reportable!=null?conf.max_reportable:"—"}, never 100%)</span></span>`+ | |
| `<span class="lam">Λ ${trust.score!=null?trust.score:"—"} / floor ${trust.floor!=null?trust.floor:"—"} · ${trust.pass?"pass":"below floor"} <span class="small">(advisory, Conjecture 1)</span></span>`+ | |
| `</div>`; | |
| if((gate.reasons||[]).length) html += `<div class="note">gate reasons: ${esc((gate.reasons||[]).join("; "))}</div>`; | |
| // answer / code / research | |
| if(run.answer) html += `<div style="margin:8px 0;font-size:12.5px;">${esc(run.answer)}</div>`; | |
| if(run.code && run.code.code){ | |
| html += `<div class="note">${esc(run.code.description||"")}</div><pre>${esc(run.code.code)}</pre>`; | |
| } | |
| if(run.sandbox){ | |
| const sb = run.sandbox; | |
| html += `<div class="note mono">sandbox: ${esc(sb.isolation||"")}</div>`; | |
| if(sb.stdout) html += `<pre>${esc(sb.stdout)}</pre>`; | |
| if(sb.stderr) html += `<pre style="color:var(--err)">${esc(sb.stderr)}</pre>`; | |
| if(sb.blocked) html += `<div class="badge err">not executed — blocked at the gate</div>`; | |
| } | |
| // HumanApprovalGate panel | |
| html += renderApproval(n, approval, allow, run); | |
| // Wave G: governed behavior-profile provenance in the receipt trail (if applied) | |
| html += renderHarnessProfile(res.harness_profile); | |
| // receipt chain + signature | |
| html += `<hr/><div class="small mono">P1–P6 receipt chain (${chain.length} hops)</div><div class="chain">`; | |
| chain.forEach(h=>{ html += `<span class="hop">${h.seq}·${esc(h.kind)}</span>`; }); | |
| html += `</div>`; | |
| const signed = !!sig.signed; | |
| html += `<div class="kv"><span>receipt <span class="badge ${signed?"live":"warn"}">${signed?"SIGNED (DSSE, ECDSA-P256)":"UNSIGNED (honest)"}</span></span>`+ | |
| `<span class="small">${esc(res.signature_label||"")}</span></div>`; | |
| html += `<div class="note">${esc(sig.honesty||"")}</div>`; | |
| html += `<div style="margin-top:8px;"><button class="ghost" onclick="verifyStep(${n})">Re-verify this receipt</button> `+ | |
| `<button class="ghost" onclick="toggleRaw(${n})">Show raw run JSON</button></div>`; | |
| html += `<div id="verify${n}"></div>`; | |
| html += `<pre id="raw${n}" style="display:none;">${esc(JSON.stringify(run,null,2))}</pre>`; | |
| // Lambda axes (advisory) | |
| if(trust.axes){ | |
| html += `<div class="small mono" style="margin-top:8px;">Λ 13-axis vector (advisory — Conjecture 1, derived from real run signals):</div><div class="axes">`; | |
| Object.keys(trust.axes).forEach(k=>{ html += `<div>${esc(k)}: <b>${trust.axes[k]}</b></div>`; }); | |
| html += `</div>`; | |
| } | |
| html += `<div class="note">${esc(run.honesty||"")}</div>`; | |
| body.innerHTML = html; | |
| // stash the run for verify | |
| body._run = run; | |
| } | |
| function renderApproval(n, approval, allow, run){ | |
| if(!approval) return ""; | |
| // MODELED-OFF or not required | |
| if(approval.required === false){ | |
| return `<div class="gatebox"><b>HumanApprovalGate</b> — <span class="badge modeled">not required</span>`+ | |
| `<div class="note">${esc(approval.note||"")}</div></div>`; | |
| } | |
| if(approval.required === null || approval.required === undefined){ | |
| return `<div class="gatebox"><b>HumanApprovalGate</b> — <span class="badge modeled">MODELED-OFF</span>`+ | |
| `<div class="note">${esc(approval.note||"")}</div></div>`; | |
| } | |
| if(approval.granted === true){ | |
| return `<div class="gatebox on"><b>HumanApprovalGate</b> — <span class="badge live">GRANTED</span> by ${esc(approval.approver||"—")}`+ | |
| `<div class="note mono">checkpoint ${esc(approval.checkpoint_id)}</div><div class="note">${esc(approval.note||"")}</div></div>`; | |
| } | |
| // required && not granted → HELD, show approve/reject | |
| return `<div class="gatebox"><b>HumanApprovalGate</b> — <span class="badge warn">HELD (awaiting human approval)</span>`+ | |
| `<div class="note mono">checkpoint ${esc(approval.checkpoint_id)}</div>`+ | |
| `<div class="note">This is a state-changing, gate-allowed action. A human must approve THIS exact checkpoint before it fires.</div>`+ | |
| `<div class="row" style="margin-top:8px;"><div style="flex:1;"><input id="approver${n}" placeholder="approver identity (your name/email)"/></div>`+ | |
| `<div style="flex:0 0 auto;"><button class="act approve" onclick="approveStep(${n},'${esc(approval.checkpoint_id)}',true)">Approve & re-run</button> `+ | |
| `<button class="act reject" onclick="rejectStep(${n})">Reject</button></div></div></div>`; | |
| } | |
| // ---- Wave G: render the governed behavior-profile provenance in the receipt trail | |
| function renderHarnessProfile(hp){ | |
| if(!hp) return ""; // no profile applied to this step | |
| // requested but unavailable / not found → honest, never fabricated | |
| if(!hp.available){ | |
| return `<hr/><div class="gatebox"><b>Behavior profile</b> — `+ | |
| `<span class="badge warn">requested “${esc(hp.requested||hp.profile_id||"?")}” — not applied</span>`+ | |
| `<div class="note">${esc(hp.honesty||"profile unavailable; run proceeded with the default persona — nothing fabricated.")}</div></div>`; | |
| } | |
| const prov = hp.provenance || {}; | |
| const st = hp.harness_state || ""; | |
| const stateCls = (st==="READY"||st==="LIVE-KEY") ? "live" : (st==="UNAVAILABLE" ? "warn" : "modeled"); | |
| let h = `<hr/><div class="gatebox on"><b>Behavior profile</b> — `+ | |
| `<span class="badge live">${esc(hp.profile_name||hp.profile_id)}</span> `+ | |
| `<span class="badge">v${esc(hp.version||"?")}</span> `+ | |
| `<span class="badge ${stateCls}">${esc(st||"applied")}</span>`+ | |
| (hp.forum_ingested ? ` <span class="badge live" title="The profile-swap was logged to /llm/forum.">→ /llm/forum</span>` : "")+ | |
| `<div class="kv" style="margin-top:8px;">`+ | |
| `<span>profile_id <b class="mono">${esc(hp.profile_id)}</b></span>`+ | |
| `<span>sha256 <b class="mono">${esc((hp.sha256||"").slice(0,16))}${hp.sha256?"…":""}</b></span>`+ | |
| `<span>integrity <b>${esc(hp.sha256_integrity||"—")}</b></span></div>`+ | |
| `<div class="kv">`+ | |
| `<span>author <b>${esc(prov.author||"—")}</b></span>`+ | |
| `<span>source <b>${esc(prov.source||"—")}</b></span>`+ | |
| `<span>license <b>${esc(prov.license||"—")}</b></span></div>`; | |
| if(prov.not_verbatim_of) h += `<div class="note">not_verbatim_of: ${esc(prov.not_verbatim_of)}</div>`; | |
| h += `<div class="note">${esc(hp.label||"")}</div>`; | |
| h += `<div class="note small">${esc(hp.honesty||"")}</div></div>`; | |
| return h; | |
| } | |
| async function approveStep(n, checkpoint_id, approved){ | |
| const approver = (document.getElementById("approver"+n)||{}).value || ""; | |
| if(!approver.trim()){ alert("Enter an approver identity."); return; } | |
| const g = await jpost("/approve", {checkpoint_id, approver, approved:!!approved}); | |
| if(!g.ok){ alert(g.error||"grant rejected"); return; } | |
| // re-run the step CARRYING the durable grant | |
| runStep(n, g.grant); | |
| } | |
| function rejectStep(n){ | |
| const body = document.getElementById("step"+n+"-body"); | |
| const box = body.querySelector(".gatebox"); | |
| if(box){ box.className="gatebox"; box.innerHTML = `<b>HumanApprovalGate</b> — <span class="badge err">REJECTED by human</span>`+ | |
| `<div class="note">The checkpoint was rejected — the state-changing action will not fire. The deny-by-default gate + Λ floor still stand independently.</div>`; } | |
| } | |
| async function verifyStep(n){ | |
| const body = document.getElementById("step"+n+"-body"); | |
| const run = body._run; const out = document.getElementById("verify"+n); | |
| out.innerHTML = `<span class="small">Re-verifying chain + signature…</span>`; | |
| try{ | |
| const v = await jpost("/verify", {run}); | |
| out.innerHTML = `<div class="kv" style="margin-top:8px;">`+ | |
| `<span>chain intact <span class="badge ${v.chain_intact?"live":"err"}">${v.chain_intact?"YES":"NO"}</span></span>`+ | |
| `<span>signature valid <span class="badge ${v.signature_valid?"live":"warn"}">${v.signature_valid?"YES":"structural"}</span></span>`+ | |
| `<span>depth <b>${v.chain_depth}</b></span></div>`+ | |
| `<div class="note">${esc(v.note||"")} ${esc(v.signature_detail||"")}</div>`; | |
| }catch(e){ out.innerHTML = `<span class="badge err">verify error: ${esc(e.message||e)}</span>`; } | |
| } | |
| function toggleRaw(n){ const el=document.getElementById("raw"+n); el.style.display = el.style.display==="none"?"block":"none"; } | |
| function showErr(m){ const e=document.getElementById("err"); e.style.display="block"; e.innerHTML=`<span class="badge err">${esc(m)}</span>`; } | |
| function hideErr(){ document.getElementById("err").style.display="none"; } | |
| probe(); | |
| loadProfiles(); | |
| </script> | |
| </body> | |
| </html> | |