Spaces:
Running
Running
feat(console): Receipt Fingerprint Graph tab (B3, P-GNN anchor-set); byte-identical to GitHub 1cb1e82b
Browse files- pages/console.html +141 -0
pages/console.html
CHANGED
|
@@ -10543,5 +10543,146 @@ window.warboard_init=warboard_init; window.warboard_all=warboard_all;
|
|
| 10543 |
})();
|
| 10544 |
</script>
|
| 10545 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10546 |
</body>
|
| 10547 |
</html>
|
|
|
|
| 10543 |
})();
|
| 10544 |
</script>
|
| 10545 |
|
| 10546 |
+
<script>
|
| 10547 |
+
/* receipt-fingerprint-tab (B3) — P-GNN anchor-set structural fingerprints over the
|
| 10548 |
+
LIVE Khipu receipt DAG, rendered as a D3 force graph. Adapts the anchor-set
|
| 10549 |
+
distance-encoding idea from P-GNN (You/Ying/Leskovec, ICML 2019, arXiv:1906.04817)
|
| 10550 |
+
to give every receipt a position-aware structural fingerprint h_v, used for
|
| 10551 |
+
fork detection / anomalous-agent (structurally isolated) detection / capability
|
| 10552 |
+
similarity. HONEST: the fingerprint is a structural HEURISTIC, never a proof; it
|
| 10553 |
+
does NOT change the locked-8 set and is not a trust oracle. 0 runtime CDN (d3 is
|
| 10554 |
+
vendored in-image). Reads REAL receipts; if none are present it says so. Additive
|
| 10555 |
+
only — registers one new VIEWS entry + one nav item, idempotent. */
|
| 10556 |
+
(function(){
|
| 10557 |
+
"use strict";
|
| 10558 |
+
var E=window.el, esc=window.esc, getPublic=window.getPublic;
|
| 10559 |
+
var TEAL=(window.TEAL||'#5fb3a3'), GOLD=(window.GOLD||'#c9b787'), RED='#b06a5a';
|
| 10560 |
+
function H(id,h){ var e=E&&E(id); if(e) e.innerHTML=h; }
|
| 10561 |
+
|
| 10562 |
+
/* ---- anchor-set fingerprint math (P-GNN-style) -------------------------- */
|
| 10563 |
+
// Build an undirected adjacency over the receipt DAG (prev_hash -> hash edges),
|
| 10564 |
+
// pick k anchors (genesis + evenly-spaced checkpoints), BFS hop-distance to each
|
| 10565 |
+
// anchor, fingerprint = [ 1/(1+d_i) ] per anchor (the P-GNN distance kernel
|
| 10566 |
+
// w_phi(d)=1/(1+d)). Cosine similarity between fingerprints = structural affinity.
|
| 10567 |
+
function buildGraph(recs){
|
| 10568 |
+
var byHash={}, nodes=[], idx={};
|
| 10569 |
+
recs.forEach(function(r,i){ var id=r.hash||('seq'+(r.seq!=null?r.seq:i));
|
| 10570 |
+
nodes.push({id:id,seq:(r.seq!=null?r.seq:i),kind:r.kind||'rcpt',prev:r.prev_hash||null});
|
| 10571 |
+
byHash[id]=i; idx[id]=i; });
|
| 10572 |
+
var adj=nodes.map(function(){return [];});
|
| 10573 |
+
nodes.forEach(function(n,i){ if(n.prev!=null && idx[n.prev]!=null){ var j=idx[n.prev];
|
| 10574 |
+
adj[i].push(j); adj[j].push(i); } });
|
| 10575 |
+
return {nodes:nodes,adj:adj,idx:idx};
|
| 10576 |
+
}
|
| 10577 |
+
function bfsDist(adj,src){ var d=adj.map(function(){return Infinity;}); d[src]=0;
|
| 10578 |
+
var q=[src]; while(q.length){ var u=q.shift(); adj[u].forEach(function(v){ if(d[v]===Infinity){ d[v]=d[u]+1; q.push(v); } }); } return d; }
|
| 10579 |
+
function pickAnchors(n,k){ if(n<=0) return []; k=Math.min(k,n); var a=[];
|
| 10580 |
+
for(var i=0;i<k;i++){ a.push(Math.round(i*(n-1)/Math.max(1,k-1))); } // genesis..head, evenly spaced
|
| 10581 |
+
return Array.from(new Set(a)); }
|
| 10582 |
+
function fingerprints(g,k){
|
| 10583 |
+
var n=g.nodes.length; var anchors=pickAnchors(n,k);
|
| 10584 |
+
var dmaps=anchors.map(function(a){ return bfsDist(g.adj,a); });
|
| 10585 |
+
var fps=g.nodes.map(function(_,i){ return anchors.map(function(_,ai){ var d=dmaps[ai][i];
|
| 10586 |
+
return isFinite(d)?(1/(1+d)):0; }); });
|
| 10587 |
+
return {anchors:anchors,fps:fps};
|
| 10588 |
+
}
|
| 10589 |
+
function cosine(a,b){ var dot=0,na=0,nb=0; for(var i=0;i<a.length;i++){ dot+=a[i]*b[i]; na+=a[i]*a[i]; nb+=b[i]*b[i]; }
|
| 10590 |
+
return (na&&nb)?(dot/(Math.sqrt(na)*Math.sqrt(nb))):0; }
|
| 10591 |
+
|
| 10592 |
+
/* ---- render ------------------------------------------------------------- */
|
| 10593 |
+
window.renderReceiptFP=function(c){
|
| 10594 |
+
c.innerHTML='<div class="kpis">'
|
| 10595 |
+
+'<div class="kpi"><div class="k">Receipts</div><div class="v teal" id="rfp-n">\u2014</div><div class="d">live command-log</div></div>'
|
| 10596 |
+
+'<div class="kpi"><div class="k">Anchor set</div><div class="v" id="rfp-k">\u2014</div><div class="d">P-GNN anchors</div></div>'
|
| 10597 |
+
+'<div class="kpi"><div class="k">Chain</div><div class="v" id="rfp-ch">\u2014</div><div class="d">hash-chain re-walk</div></div>'
|
| 10598 |
+
+'<div class="kpi"><div class="k">Structural flags</div><div class="v warn" id="rfp-flag">\u2014</div><div class="d">heuristic only</div></div></div>'
|
| 10599 |
+
+'<div class="card"><div class="card-h"><span class="card-t">Receipt fingerprint graph \u2014 anchor-set structural embedding</span>'
|
| 10600 |
+
+'<span class="card-ep">P-GNN distance kernel \u00b7 d3-force (BSD/ISC, vendored)</span></div>'
|
| 10601 |
+
+'<div id="rfp-svg" style="height:460px;border:1px solid rgba(201,183,135,0.12);border-radius:8px;overflow:hidden;background:#080a09"></div>'
|
| 10602 |
+
+'<div class="brain-note" id="rfp-note"><span style="color:'+GOLD+'">gold ring = anchor receipt</span>, '
|
| 10603 |
+
+'<span style="color:'+TEAL+'">teal = ordinary receipt</span>, <span style="color:'+RED+'">red = structurally isolated (anomaly heuristic)</span>. '
|
| 10604 |
+
+'Edge drawn where fingerprint cosine \u2265 0.92 (structural affinity). This is a structural <b>heuristic</b> for fork / spoof / isolated-agent detection \u2014 <b>not</b> a proof and not a trust oracle. '
|
| 10605 |
+
+'\u039b remains Conjecture 1; locked-proven stays exactly 8 {F1,F4,F7,F11,F12,F18,F19,F22}.</div></div>'
|
| 10606 |
+
+(window.HONEST||'');
|
| 10607 |
+
(function(){
|
| 10608 |
+
function go(){
|
| 10609 |
+
getPublic('/api/a11oy/v2/operator/command-log',12000).then(function(cl){
|
| 10610 |
+
var recs=(cl.receipts||[]).slice(-80);
|
| 10611 |
+
H('rfp-n', recs.length); H('rfp-ch', cl.chain_verified?('verified \u00b7 depth '+(cl.depth!=null?cl.depth:'')):'unverified');
|
| 10612 |
+
var host=E('rfp-svg'); if(!host) return;
|
| 10613 |
+
if(!recs.length){ host.innerHTML='<div class="row mono dim" style="padding:1rem">no receipts emitted in this runtime yet \u2014 nothing to fingerprint (honest empty state)</div>';
|
| 10614 |
+
H('rfp-k','0'); H('rfp-flag','0'); return; }
|
| 10615 |
+
var g=buildGraph(recs); var k=Math.min(5,Math.max(2,Math.round(Math.sqrt(g.nodes.length))));
|
| 10616 |
+
var R=fingerprints(g,k); H('rfp-k', R.anchors.length);
|
| 10617 |
+
// edges by fingerprint cosine affinity (plus the real prev_hash chain edges)
|
| 10618 |
+
var anchorSet={}; R.anchors.forEach(function(a){ anchorSet[a]=true; });
|
| 10619 |
+
var links=[]; var deg=g.nodes.map(function(){return 0;});
|
| 10620 |
+
// real chain edges
|
| 10621 |
+
g.nodes.forEach(function(n,i){ if(n.prev!=null && g.idx[n.prev]!=null){ links.push({source:i,target:g.idx[n.prev],kind:'chain'}); deg[i]++; deg[g.idx[n.prev]]++; } });
|
| 10622 |
+
// structural-affinity edges
|
| 10623 |
+
for(var i=0;i<g.nodes.length;i++){ for(var j=i+1;j<g.nodes.length;j++){
|
| 10624 |
+
if(cosine(R.fps[i],R.fps[j])>=0.92){ links.push({source:i,target:j,kind:'affinity'}); deg[i]++; deg[j]++; } } }
|
| 10625 |
+
var isolated=[]; g.nodes.forEach(function(n,i){ if(deg[i]===0 && !anchorSet[i]) isolated.push(i); });
|
| 10626 |
+
H('rfp-flag', isolated.length);
|
| 10627 |
+
H('rfp-note', E('rfp-note').innerHTML + (isolated.length?(' <b style="color:'+RED+'">'+isolated.length+' structurally isolated receipt(s) flagged.</b>'):' No structural anomalies in this window.'));
|
| 10628 |
+
drawD3(host, g, R, links, anchorSet, isolated);
|
| 10629 |
+
}).catch(function(e){ var host=E('rfp-svg'); if(host) host.innerHTML='<div class="row mono dim" style="padding:1rem">live command-log unavailable: '+esc(e.message)+'</div>';
|
| 10630 |
+
H('rfp-n','offline'); });
|
| 10631 |
+
}
|
| 10632 |
+
if(window.a11oyPoll){ window.a11oyPoll(go); } else { go(); }
|
| 10633 |
+
})();
|
| 10634 |
+
};
|
| 10635 |
+
|
| 10636 |
+
function drawD3(host, g, R, links, anchorSet, isolated){
|
| 10637 |
+
host.innerHTML='';
|
| 10638 |
+
if(!window.d3 || !d3.forceSimulation){ host.innerHTML='<div class="row mono dim" style="padding:1rem">d3-force unavailable</div>'; return; }
|
| 10639 |
+
var W=host.clientWidth||720, Hh=460;
|
| 10640 |
+
var iso={}; isolated.forEach(function(i){ iso[i]=true; });
|
| 10641 |
+
var nodes=g.nodes.map(function(n,i){ return {i:i,seq:n.seq,kind:n.kind,anchor:!!anchorSet[i],iso:!!iso[i]}; });
|
| 10642 |
+
var svg=d3.select(host).append('svg').attr('width','100%').attr('height','100%').attr('viewBox','0 0 '+W+' '+Hh);
|
| 10643 |
+
var lsel=svg.append('g').selectAll('line').data(links).enter().append('line')
|
| 10644 |
+
.attr('stroke',function(d){return d.kind==='chain'?'rgba(201,183,135,0.30)':'rgba(95,179,163,0.18)';})
|
| 10645 |
+
.attr('stroke-width',function(d){return d.kind==='chain'?1.1:0.7;});
|
| 10646 |
+
var nsel=svg.append('g').selectAll('circle').data(nodes).enter().append('circle')
|
| 10647 |
+
.attr('r',function(d){return d.anchor?9:5;})
|
| 10648 |
+
.attr('fill',function(d){return d.iso?RED:(d.anchor?'transparent':TEAL);})
|
| 10649 |
+
.attr('stroke',function(d){return d.iso?RED:(d.anchor?GOLD:TEAL);})
|
| 10650 |
+
.attr('stroke-width',function(d){return d.anchor?2:1.2;});
|
| 10651 |
+
nsel.append('title').text(function(d){return '#'+d.seq+' '+(d.kind||'')+(d.anchor?' (anchor)':'')+(d.iso?' (isolated)':'');});
|
| 10652 |
+
var sim=d3.forceSimulation(nodes)
|
| 10653 |
+
.force('link',d3.forceLink(links).distance(function(d){return d.kind==='chain'?34:60;}).strength(0.4))
|
| 10654 |
+
.force('charge',d3.forceManyBody().strength(-60))
|
| 10655 |
+
.force('center',d3.forceCenter(W/2,Hh/2))
|
| 10656 |
+
.on('tick',function(){
|
| 10657 |
+
lsel.attr('x1',function(d){return d.source.x;}).attr('y1',function(d){return d.source.y;})
|
| 10658 |
+
.attr('x2',function(d){return d.target.x;}).attr('y2',function(d){return d.target.y;});
|
| 10659 |
+
nsel.attr('cx',function(d){return d.x=Math.max(10,Math.min(W-10,d.x));}).attr('cy',function(d){return d.y=Math.max(10,Math.min(Hh-10,d.y));});
|
| 10660 |
+
});
|
| 10661 |
+
setTimeout(function(){ try{ sim.stop(); }catch(e){} }, 4200); // settle then freeze (no perpetual CPU)
|
| 10662 |
+
}
|
| 10663 |
+
|
| 10664 |
+
/* ---- register + nav (idempotent, waits for VIEWS) ----------------------- */
|
| 10665 |
+
function reg(){ if(!window.VIEWS){ return setTimeout(reg,120); }
|
| 10666 |
+
if(window.VIEWS.receiptfp) return;
|
| 10667 |
+
window.VIEWS.receiptfp={
|
| 10668 |
+
title:'Receipt Fingerprint Graph',
|
| 10669 |
+
badge:'P-GNN ANCHOR-SET \u00b7 STRUCTURAL FINGERPRINT',
|
| 10670 |
+
sub:'Position-aware structural fingerprints over the live Khipu receipt DAG (anchor-set distance encoding, after P-GNN \u2014 You/Ying/Leskovec, ICML 2019). Each receipt gets a fingerprint from its hop-distances to anchor receipts; structural affinity (cosine \u2265 0.92) and isolation surface fork / spoof / anomalous-agent signals. A structural heuristic \u2014 never a proof, never a trust oracle; \u039b stays Conjecture 1, locked-proven stays 8.',
|
| 10671 |
+
render:async function(c){ window.renderReceiptFP(c); }
|
| 10672 |
+
};
|
| 10673 |
+
}
|
| 10674 |
+
reg();
|
| 10675 |
+
function injectNav(){
|
| 10676 |
+
var anchor=document.querySelector('.nav-item[data-view="ledger3d"]')||document.querySelector('.nav-item[data-view="chain"]')||document.querySelector('.nav-item');
|
| 10677 |
+
if(!anchor){ return setTimeout(injectNav,250); }
|
| 10678 |
+
if(document.getElementById('rfp-nav')){ return; }
|
| 10679 |
+
var n=document.createElement('div'); n.className='nav-item'; n.id='rfp-nav';
|
| 10680 |
+
n.setAttribute('data-view','receiptfp'); n.setAttribute('onclick',"go('receiptfp')");
|
| 10681 |
+
n.innerHTML='<span class="ico">\u25c9</span>Receipt Fingerprint';
|
| 10682 |
+
anchor.parentNode.insertBefore(n, anchor.nextSibling);
|
| 10683 |
+
}
|
| 10684 |
+
if(document.readyState==='loading'){ document.addEventListener('DOMContentLoaded',injectNav); } else { injectNav(); }
|
| 10685 |
+
})();
|
| 10686 |
+
</script>
|
| 10687 |
</body>
|
| 10688 |
</html>
|