Spaces:
Running
Running
feat(restraint): R2 front-end - 'Restraint applied' indicator on /nemo (rung+lines-saved+ceilings+signed receipt) and restraint verdict column on /agent-loop trace. Ponytail MIT, governed. Byte-identical to GitHub 3a8305e. Additive; PENDING until R1 live.
Browse files- web/agent-loop.html +21 -3
- web/nemo.html +75 -0
web/agent-loop.html
CHANGED
|
@@ -70,7 +70,7 @@
|
|
| 70 |
<section class="view active" id="v-loop">
|
| 71 |
<div class="card">
|
| 72 |
<div class="row">
|
| 73 |
-
<input id="goal" type="text" placeholder="goal, e.g.
|
| 74 |
<label class="sub">max_steps <input id="maxsteps" type="number" value="4" style="width:64px"/></label>
|
| 75 |
<label class="sub"><input id="kill" type="checkbox"/> kill mid-run (crash demo)</label>
|
| 76 |
<button id="btnRun">Run ReAct</button>
|
|
@@ -85,8 +85,9 @@
|
|
| 85 |
<span id="chainState"></span>
|
| 86 |
</div>
|
| 87 |
<table id="traceTbl"><thead><tr>
|
| 88 |
-
<th>seq</th><th>node</th><th>body</th><th>link</th><th>signature</th><th>hash</th>
|
| 89 |
</tr></thead><tbody></tbody></table>
|
|
|
|
| 90 |
</div>
|
| 91 |
<div class="card" id="cpCard" style="display:none">
|
| 92 |
<strong>Checkpoints (SqliteSaver-style)</strong>
|
|
@@ -166,6 +167,23 @@ async function jget(u){const r=await fetch(u);return {status:r.status,json:await
|
|
| 166 |
function esc(s){return (s==null?"":String(s)).replace(/[&<>]/g,c=>({"&":"&","<":"<",">":">"}[c]));}
|
| 167 |
|
| 168 |
// ---------- Agent Loop ----------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 169 |
async function renderTrace(runId){
|
| 170 |
const {json:tr} = await jget(API+"/trace/"+encodeURIComponent(runId));
|
| 171 |
if(tr.error){return;}
|
|
@@ -179,7 +197,7 @@ async function renderTrace(runId){
|
|
| 179 |
:(r.signed?"<span class='bad'>FAIL ✗</span>":"<span class='mut'>unsigned</span>");
|
| 180 |
const link = r.link_ok?"<span class='ok'>✓</span>":"<span class='bad'>✗</span>";
|
| 181 |
tb.innerHTML += `<tr><td>${r.seq}</td><td><span class="node ${r.node}">${r.node}</span></td>
|
| 182 |
-
<td><pre>${esc(JSON.stringify(r.body))}</pre></td><td>${link}</td><td>${sig}</td>
|
| 183 |
<td class="hash">${esc((r.hash||"").slice(0,18))}…</td></tr>`;
|
| 184 |
});
|
| 185 |
if(tr.reflection){
|
|
|
|
| 70 |
<section class="view active" id="v-loop">
|
| 71 |
<div class="card">
|
| 72 |
<div class="row">
|
| 73 |
+
<input id="goal" type="text" placeholder="goal, e.g. implement a function that validates an email address" value="implement a function that validates an email address"/>
|
| 74 |
<label class="sub">max_steps <input id="maxsteps" type="number" value="4" style="width:64px"/></label>
|
| 75 |
<label class="sub"><input id="kill" type="checkbox"/> kill mid-run (crash demo)</label>
|
| 76 |
<button id="btnRun">Run ReAct</button>
|
|
|
|
| 85 |
<span id="chainState"></span>
|
| 86 |
</div>
|
| 87 |
<table id="traceTbl"><thead><tr>
|
| 88 |
+
<th>seq</th><th>node</th><th>body</th><th>restraint</th><th>link</th><th>signature</th><th>hash</th>
|
| 89 |
</tr></thead><tbody></tbody></table>
|
| 90 |
+
<div class="sub" style="margin-top:6px">Action nodes that <strong>write code</strong> are gated through <strong>a11oy Restraint</strong> (the Ponytail-derived 6-rung frugality ladder, <a href="https://github.com/DietrichGebert/ponytail" target="_blank" rel="noopener">Ponytail MIT</a> — adopted + governed). The chosen rung + signed restraint receipt are recorded in that node's receipt. <strong>R1 owns the ladder module</strong>; honest <strong>PENDING</strong> until it is live.</div>
|
| 91 |
</div>
|
| 92 |
<div class="card" id="cpCard" style="display:none">
|
| 93 |
<strong>Checkpoints (SqliteSaver-style)</strong>
|
|
|
|
| 167 |
function esc(s){return (s==null?"":String(s)).replace(/[&<>]/g,c=>({"&":"&","<":"<",">":">"}[c]));}
|
| 168 |
|
| 169 |
// ---------- Agent Loop ----------
|
| 170 |
+
// Restraint verdict cell for a node body. Only code-writing ACTION nodes carry
|
| 171 |
+
// a `restraint` block; everything else shows a dim em-dash (honest).
|
| 172 |
+
function restraintCell(body){
|
| 173 |
+
const rs = body && body.restraint;
|
| 174 |
+
if(!rs) return "<span class='mut'>—</span>";
|
| 175 |
+
const live = rs.status==="LIVE";
|
| 176 |
+
const badge = live ? L("LIVE") : (L("ROADMAP")+" <span class='lbl' style='border-color:var(--warn);color:var(--warn)'>PENDING</span>");
|
| 177 |
+
if(rs.stopped_at_rung!=null){
|
| 178 |
+
const saved = (rs.lines_saved_estimate!=null)
|
| 179 |
+
? (" · saved≈"+rs.lines_saved_estimate+" LOC ("+esc(rs.lines_saved_label||"MODELED")+")") : "";
|
| 180 |
+
const lam = (rs.lambda_advisory!=null) ? (" · Λ "+Number(rs.lambda_advisory).toFixed(3)) : "";
|
| 181 |
+
const ceil = rs.restraint_comment ? ("<div class='mut' style='font-size:11px'><code>"+esc(rs.restraint_comment)+"</code></div>") : "";
|
| 182 |
+
return "<div><span class='ok'>rung "+rs.stopped_at_rung+"</span> "+esc(rs.rung_key||"")+" "+badge+"</div>"+
|
| 183 |
+
"<div class='mut' style='font-size:11px'>"+esc(rs.rung_name||"")+saved+lam+"</div>"+ceil;
|
| 184 |
+
}
|
| 185 |
+
return "<div>"+badge+"</div><div class='mut' style='font-size:11px'>code gated; restraint not live yet (no rung fabricated)</div>";
|
| 186 |
+
}
|
| 187 |
async function renderTrace(runId){
|
| 188 |
const {json:tr} = await jget(API+"/trace/"+encodeURIComponent(runId));
|
| 189 |
if(tr.error){return;}
|
|
|
|
| 197 |
:(r.signed?"<span class='bad'>FAIL ✗</span>":"<span class='mut'>unsigned</span>");
|
| 198 |
const link = r.link_ok?"<span class='ok'>✓</span>":"<span class='bad'>✗</span>";
|
| 199 |
tb.innerHTML += `<tr><td>${r.seq}</td><td><span class="node ${r.node}">${r.node}</span></td>
|
| 200 |
+
<td><pre>${esc(JSON.stringify(r.body))}</pre></td><td>${restraintCell(r.body)}</td><td>${link}</td><td>${sig}</td>
|
| 201 |
<td class="hash">${esc((r.hash||"").slice(0,18))}…</td></tr>`;
|
| 202 |
});
|
| 203 |
if(tr.reflection){
|
web/nemo.html
CHANGED
|
@@ -165,6 +165,31 @@ table.tau th{color:var(--dim);text-transform:uppercase;font-size:9.5px;letter-sp
|
|
| 165 |
</div>
|
| 166 |
</div>
|
| 167 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 168 |
<!-- ============ 3D ROUTER DASHBOARD (F4 · additive · toggle enhancement; 2D pages above remain the fallback) ============ -->
|
| 169 |
<div class="panel" id="router3d_panel">
|
| 170 |
<h2>3D Router Dashboard <span class="meta">GPU blocks · particle token-flows · signed MoE routing pulses · live J/token</span>
|
|
@@ -447,6 +472,54 @@ async function doRoute(q){
|
|
| 447 |
}
|
| 448 |
}
|
| 449 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 450 |
async function loadMTP(){
|
| 451 |
const d=await getJSON(A+"/mtp"); if(!d){$('mtp_kv').textContent='unreachable';return;}
|
| 452 |
$('mtp_kv').innerHTML=
|
|
@@ -542,11 +615,13 @@ async function doSelfImprove(){
|
|
| 542 |
|
| 543 |
document.querySelectorAll('button.ghost[data-q]').forEach(b=>b.addEventListener('click',()=>{$('q').value=b.getAttribute('data-q');doRoute(b.getAttribute('data-q'));}));
|
| 544 |
$('go').addEventListener('click',()=>doRoute($('q').value));
|
|
|
|
| 545 |
$('si_go').addEventListener('click',doSelfImprove);
|
| 546 |
|
| 547 |
(async function(){
|
| 548 |
await Promise.all([loadDiag(),loadMTP(),loadTiers(),loadTau(),loadCard()]);
|
| 549 |
await doRoute($('q').value);
|
|
|
|
| 550 |
})();
|
| 551 |
</script>
|
| 552 |
</body>
|
|
|
|
| 165 |
</div>
|
| 166 |
</div>
|
| 167 |
|
| 168 |
+
<!-- a11oy RESTRAINT (gates the CODE path before any diff is emitted) -->
|
| 169 |
+
<div class="panel">
|
| 170 |
+
<h2>a11oy Restraint <span class="meta">code-frugality ladder · gates the code path before emit · signed</span></h2>
|
| 171 |
+
<div class="desc">
|
| 172 |
+
Before SZL-Nemo emits ANY code, the intended diff is routed through the governed, Ponytail-derived
|
| 173 |
+
<b>6-rung frugality ladder</b> (YAGNI → stdlib → native → installed-deps → one-liner → minimal). The chosen rung,
|
| 174 |
+
the <code>restraint:</code> ceiling, a lines-saved estimate and a <b>signed restraint receipt</b> are attached to the
|
| 175 |
+
Nemo response. Adopted from <a href="https://github.com/DietrichGebert/ponytail" target="_blank" rel="noopener">Ponytail (MIT)</a>,
|
| 176 |
+
governed + Λ-scored here. <b>R1 owns the ladder module</b>; if it isn't live yet this reads honest <b>PENDING</b>
|
| 177 |
+
(no rung or number fabricated).
|
| 178 |
+
</div>
|
| 179 |
+
<div class="row">
|
| 180 |
+
<input type="text" id="cq" value="write me a Python function that validates email addresses"/>
|
| 181 |
+
<button class="btn" id="cgo">Ask SZL-Nemo for code →</button>
|
| 182 |
+
<span id="c_rung" class="pill dim">rung —</span>
|
| 183 |
+
<span id="c_status" class="pill dim">—</span>
|
| 184 |
+
</div>
|
| 185 |
+
<div class="kv" id="c_restraint" style="margin-top:.5rem;">— (ask SZL-Nemo for code to see the restraint verdict)</div>
|
| 186 |
+
<div style="margin-top:.6rem;">
|
| 187 |
+
<div class="meta mono" style="color:var(--dim);font-size:10px;">SIGNED RESTRAINT RECEIPT (nested in the Nemo code receipt)</div>
|
| 188 |
+
<pre class="rcpt" id="c_receipt">—</pre>
|
| 189 |
+
<div class="kv"><span class="k">verify</span><span class="v" id="c_verify">—</span></div>
|
| 190 |
+
</div>
|
| 191 |
+
</div>
|
| 192 |
+
|
| 193 |
<!-- ============ 3D ROUTER DASHBOARD (F4 · additive · toggle enhancement; 2D pages above remain the fallback) ============ -->
|
| 194 |
<div class="panel" id="router3d_panel">
|
| 195 |
<h2>3D Router Dashboard <span class="meta">GPU blocks · particle token-flows · signed MoE routing pulses · live J/token</span>
|
|
|
|
| 472 |
}
|
| 473 |
}
|
| 474 |
|
| 475 |
+
async function doCode(q){
|
| 476 |
+
$('c_restraint').innerHTML='<span class="muted mono">routing the intended diff through a11oy Restraint…</span>';
|
| 477 |
+
$('c_rung').textContent='rung …'; $('c_rung').className='pill dim';
|
| 478 |
+
$('c_status').textContent='…'; $('c_status').className='pill dim';
|
| 479 |
+
const d=await getJSON(A+"/code",{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({query:q})});
|
| 480 |
+
if(!d){$('c_restraint').innerHTML='<div class="muted mono">code endpoint unreachable</div>';return;}
|
| 481 |
+
const rs=d.restraint||{};
|
| 482 |
+
const status=String(rs.status||'PENDING');
|
| 483 |
+
const live=(status==='LIVE');
|
| 484 |
+
// "Restraint applied" indicator: rung + lines-saved estimate + restraint: ceiling
|
| 485 |
+
// PENDING is not in the shared canonical vocabulary (R1 owns labels); show the
|
| 486 |
+
// closest honest canonical badge (ROADMAP) + the literal PENDING word in text.
|
| 487 |
+
$('c_status').innerHTML = live ? labelPill('LIVE') : (labelPill('ROADMAP')+' <span class="pill yellow">PENDING</span>');
|
| 488 |
+
if(rs.stopped_at_rung!=null){
|
| 489 |
+
$('c_rung').textContent='rung '+rs.stopped_at_rung+' · '+(rs.rung_key||'');
|
| 490 |
+
$('c_rung').className='pill green';
|
| 491 |
+
}else{
|
| 492 |
+
$('c_rung').textContent='rung — (PENDING)'; $('c_rung').className='pill yellow';
|
| 493 |
+
}
|
| 494 |
+
const saved=(rs.lines_saved_estimate!=null)?(rs.lines_saved_estimate+' LOC ('+esc(rs.lines_saved_label||'MODELED')+')'):'— (not measured)';
|
| 495 |
+
const lam=(rs.lambda_advisory!=null)?fmt(rs.lambda_advisory,3):'—';
|
| 496 |
+
const applied = live
|
| 497 |
+
? `<span class="pill green">Restraint applied</span>`
|
| 498 |
+
: `<span class="pill yellow">Restraint PENDING</span>`;
|
| 499 |
+
$('c_restraint').innerHTML=
|
| 500 |
+
`<div>${applied} <span class="k">rung</span> <span class="v">${rs.stopped_at_rung!=null?(rs.stopped_at_rung+' · '+esc(rs.rung_name||rs.rung_key||'')):'—'}</span></div>`+
|
| 501 |
+
`<div><span class="k">lines saved (est.)</span> <span class="v">${saved}</span></div>`+
|
| 502 |
+
`<div><span class="k">Λ advisory</span> <span class="v">${lam}</span></div>`+
|
| 503 |
+
(rs.restraint_comment?`<div><span class="k">restraint: ceiling</span> <code class="mono" style="font-size:10.5px;">${esc(rs.restraint_comment)}</code></div>`:
|
| 504 |
+
(rs.ceiling?`<div><span class="k">ceiling</span> <span class="v">${esc(rs.ceiling)}</span></div>`:''))+
|
| 505 |
+
`<div class="muted" style="font-size:10px;margin-top:.3rem;">integration: ${esc(rs.integration||'')}</div>`+
|
| 506 |
+
(rs.honesty?`<div class="muted" style="font-size:10px;">${esc(rs.honesty)}</div>`:'')+
|
| 507 |
+
`<div class="muted" style="font-size:10px;">Ponytail (MIT) — adopted + governed · R1 owns a11oy_restraint.py</div>`;
|
| 508 |
+
// signed restraint receipt (nested in the Nemo code receipt)
|
| 509 |
+
const r=d.restraint_receipt||rs.restraint_receipt||{};
|
| 510 |
+
$('c_receipt').textContent=JSON.stringify(r,null,1);
|
| 511 |
+
if(r&&r.signatures&&r.signatures.length&&window.SZLReceipts&&window.SZLReceipts.verifyEnvelope){
|
| 512 |
+
$('c_verify').textContent='verifying…';
|
| 513 |
+
try{
|
| 514 |
+
const v=await window.SZLReceipts.verifyEnvelope(r,{});
|
| 515 |
+
const ok=v&&(v.valid||v.signature_valid);
|
| 516 |
+
$('c_verify').innerHTML=ok?pill('SIGNATURE VALID','green'):pill('signed (server-verify)','blue');
|
| 517 |
+
}catch(e){$('c_verify').innerHTML=pill('signed','blue');}
|
| 518 |
+
}else{
|
| 519 |
+
$('c_verify').innerHTML=(r&&r.signed===false)?pill('UNSIGNED/PENDING','yellow')+' '+esc(r.honesty||''):pill('—','dim');
|
| 520 |
+
}
|
| 521 |
+
}
|
| 522 |
+
|
| 523 |
async function loadMTP(){
|
| 524 |
const d=await getJSON(A+"/mtp"); if(!d){$('mtp_kv').textContent='unreachable';return;}
|
| 525 |
$('mtp_kv').innerHTML=
|
|
|
|
| 615 |
|
| 616 |
document.querySelectorAll('button.ghost[data-q]').forEach(b=>b.addEventListener('click',()=>{$('q').value=b.getAttribute('data-q');doRoute(b.getAttribute('data-q'));}));
|
| 617 |
$('go').addEventListener('click',()=>doRoute($('q').value));
|
| 618 |
+
$('cgo').addEventListener('click',()=>doCode($('cq').value));
|
| 619 |
$('si_go').addEventListener('click',doSelfImprove);
|
| 620 |
|
| 621 |
(async function(){
|
| 622 |
await Promise.all([loadDiag(),loadMTP(),loadTiers(),loadTau(),loadCard()]);
|
| 623 |
await doRoute($('q').value);
|
| 624 |
+
await doCode($('cq').value);
|
| 625 |
})();
|
| 626 |
</script>
|
| 627 |
</body>
|