Repository navigation
Expand file tree
/
Copy pathliving-thoughts.js
More file actions
87 lines (85 loc) · 34.4 KB
/
Copy pathliving-thoughts.js
File metadata and controls
87 lines (85 loc) · 34.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import {inputHelp} from './input-help.js';
import {V1Session,QDLV1,QDLV1Library,Anatomy,Chroma,Quinelings,VisualCapsule,WovenBody} from './assets/ranch/quinelings-runtime.js';
import {bodyOnlyExperiment} from './lab-offspring.js';
import {nodeLabel,detailedSummary,evidenceProvenance,receiptTimeline,presentDiagnostic,scenarioPresets} from './lab-insights.js';
import {stories,order,baseline,changed,cappedWaterIntent,positiveFoodIntent} from './lab-examples.js';
const $=id=>document.getElementById(id),copy=x=>structuredClone(x),format=x=>JSON.stringify(x,null,2),canon=x=>Quinelings.canon(x),TAU=Math.PI*2;
const library=new Map(QDLV1Library.programs.map(r=>[r.id,r])),cache=new Map(),metrics={evaluationRequests:0,frames:0,paints:0,renderMs:[],intervalMs:[]};
const originalExecute=QDLV1.execute;QDLV1.execute=(...args)=>{metrics.evaluationRequests++;return originalExecute(...args);};
let session=new V1Session(),recipe,artifact,inputs,before=null,after=null,lastRequest=null,selected=null,phase=0,playing=!matchMedia('(prefers-reduced-motion: reduce)').matches,dirty=false,clock=0;
function safe(fn,statusId='run-status'){return async(...args)=>{const status=$(statusId);try{status.classList.remove('failure');status.textContent='';return await fn(...args);}catch(e){status.textContent=`${e.code||'input'}: ${e.message}`+(statusId==='run-status'?'':' Displayed results were not replaced.');status.classList.add('failure');}};}
function parse(text){if(new TextEncoder().encode(text).length>65536)throw Error('Input editor exceeds 64 KiB.');return JSON.parse(text);}
function snippet(value,max=45){const s=JSON.stringify(value);return s===undefined?'not evaluated':s.length>max?s.slice(0,max-1)+'…':s;}
function result(record){return record?.result.occurrences[0];}
function traceValue(record,id){const row=result(record)?.trace.find(x=>x.nodeId===id);return row?{available:true,value:row.value}:{available:false};}
function isCurrent(){try{return !!after&&after.artifactId===artifact.id&&canon(readInputs())===canon(after.result.bindings);}catch{return false;}}
function readInputs(){const values={};for(const el of document.querySelectorAll('[data-port]'))values[el.dataset.port]=parse(el.value);return values;}
function fillInputs(values){inputs=copy(values);const parent=$('input-fields');parent.replaceChildren();for(const port of artifact.ports){const label=document.createElement('label'),el=document.createElement('textarea');label.textContent=`${port.name} · ${port.type.kind}${port.type.unit?' ['+port.type.unit+']':''}`;label.htmlFor='input-'+port.name;el.id=label.htmlFor;el.dataset.port=port.name;el.rows=Math.min(7,Math.max(2,format(values[port.name]).split('\n').length));el.spellcheck=false;el.value=format(values[port.name]);el.oninput=()=>{dirty=true;renderResults();};const help=document.createElement('p');help.id=el.id+'-help';help.className='control-help';help.textContent=inputHelp(recipe.id,port);el.setAttribute('aria-describedby',help.id);parent.append(label,el,help);}dirty=!!after&&!isCurrent();renderResults();}
function changedNodes(){if(!before||!after)return [];return artifact.payload.task.nodes.filter(n=>canon(traceValue(before,n.id))!==canon(traceValue(after,n.id))).map(n=>n.id);}
function outputs(record){if(!record)return 'No result yet.';const r=result(record);return r.status==='failed'?format({status:'failed',diagnostic:r.diagnostic}):format(r.outputs.length===1?r.outputs[0]:r.outputs);}
function storyOf(record){const r=result(record);if(r?.status==='failed'){const diagnostic=presentDiagnostic(r.diagnostic);return 'Stopped at '+r.diagnostic.nodeId+': '+diagnostic.label+'. '+diagnostic.raw.message;}const insight=detailedSummary(recipe.id,record);if(insight)return insight;if(!r)return 'Run the comparison to calculate both snapshots.';if(r.status!=='completed')return 'Stopped at '+r.diagnostic.nodeId+': '+r.diagnostic.message;const o=r.outputs,t=id=>traceValue(record,id).value;switch(recipe.id){
case 'water-total':return o[0].liters+' liters from '+o[0].measurements+' readings.';
case 'route-preview':return (o[0].found?o[0].path.join(' → ')+'; '+o[0].distance+' edges.':'No route found.')+' Walking proposal: '+o[1].status+'.';
case 'receipt-reconciliation':return o[0].confirmedUnits+' confirmed units; '+o[0].attempts+' attempts; state '+o[0].state+'. Retry advice: '+(o[0].mayRetry?'permitted':'withheld')+'.';
case 'confirmed-checkpoints':return 'Haul '+o[0].haul+'; arrival '+o[0].arrival+'. Completion check: '+o[1]+'.';
case 'craft-quote':return o[0].feasible+' of '+o[0].requested+' batches fit. Bounds: ore '+t('oreBound')+', wood '+t('woodBound')+', space '+t('spaceBound')+'.';
case 'evidence-ledger':return o[0].state+': '+o[0].support+' supporting, '+o[0].refute+' refuting, '+o[0].sources+' distinct source labels.';
case 'work-schedule':return 'Makespan '+o[0].makespan+' ticks; deadline '+record.result.bindings.deadline+': '+(o[1]?'holds':'missed')+'. Independent jobs can overlap.';
case 'trade-preview':return 'Quantity '+o[0].quantity+'; predicted proceeds '+o[0].predictedProceeds+'. Guards: '+['found','unexpired','hasInventory','hasStock','withinAllowance','positive'].filter(id=>artifact.payload.task.nodes.some(n=>n.id===id)).map(id=>id+'='+t(id)).join(', ')+'.';
case 'needs-triage':return 'Selected '+t('chosenId')+'; proposal '+o[0].status+'. Hunger is a positive guard, not a score.';
case 'gather-readiness':return 'Observation age '+t('age')+' ticks; fresh='+t('fresh')+'; ready='+t('ready')+'. Collection proposal: '+o[0].status+'.';
default:return '';
}}
function renderResults(){const current=isCurrent();$('before-result').textContent=outputs(before);$('after-result').textContent=after?(!current?'Recorded for earlier inputs\n':'')+outputs(after):'No result yet.';$('after-result').classList.toggle('dim',!!after&&!current);$('replay').disabled=!current||!lastRequest;$('generations').disabled=!current;$('evaluation-count').textContent=metrics.evaluationRequests;
$('result-story').textContent=after?(current?'Before: '+storyOf(before)+' After: '+storyOf(after):'Last complete comparison: '+storyOf(after)):storyOf(null);const changes=changedNodes();$('metrics-state').textContent=after?(current?'Matching comparison':'Last successful comparison — inputs have since changed'):'No comparison yet';$('changed-nodes').textContent=after?changes.length+' / '+artifact.payload.task.nodes.length:'—';$('same-source').textContent=after?before?.result.sourceHash===after.result.sourceHash?'Unchanged':'Changed':'Not run';$('body-change').textContent=after?geometry(artifact,session.inspect(before.artifactId)).xyzRms+' XYZ RMS':'—';$('overlay-state').textContent=!after?'No recorded values yet.':current?'Value labels refer to the matching recorded run.': 'Inputs edited. Recorded-value labels are hidden until the next run.';
$('answer-caption').textContent=!after?'':!current?'Edit pending; the displayed comparison is historical.':result(after).status==='failed'?'The calculation failed. This occurrence published no outputs or effects.':canon(result(before)?.outputs)===canon(result(after).outputs)?(changes.length?'The output stayed the same, but '+changes.length+' trace values changed. Inspect them to find the guard or constraint.':'Same inputs, same outputs, same trace. Load a change before comparing again.'):`${changes.length} operation values changed. Select a highlighted operation to follow the cause.`;
$('record-detail').textContent=after?format({sourceHash:artifact.sourceHash,beforeInputHash:before?.result.inputHash,afterInputHash:after.result.inputHash,currentInputsHaveRecord:current,emittedSourceExact:after.result.emitted[0]===artifact.source,before:result(before),after:result(after)}):'';syncCurrentControl();renderTrace();renderDomain();paint();}
function renderTrace(){const parent=$('trace'),changes=new Set(changedNodes());parent.replaceChildren();for(const n of artifact.payload.task.nodes){const b=document.createElement('button');b.textContent=n.id+(nodeLabel(recipe.id,n)===n.id?'':' · '+nodeLabel(recipe.id,n))+' · '+n.op+(changes.has(n.id)?' · changed':'');b.dataset.node=n.id;b.classList.toggle('changed',changes.has(n.id));b.setAttribute('aria-pressed',String(selected===n.id));b.onclick=()=>{selected=n.id;renderTrace();paint();};parent.append(b);}const n=artifact.payload.task.nodes.find(n=>n.id===selected);if(!n)return;const owners=compiled(artifact).design.woven.territories.filter(o=>o.node===n.id);$('operation-info').textContent=`${n.id}: ${n.op}. Inputs: ${n.inputs.join(', ')||'source constant or runtime port'}. Owns ${owners.map(o=>o.component+' (normalized length) '+o.u.map(v=>v.toFixed(2)).join('–')).join('; ')}.`;$('operation-values').textContent=format({before:traceValue(before,n.id),after:isCurrent()?traceValue(after,n.id):{available:false,reason:after?'edited inputs have no record':'not run'}});}
function projection(p,d){const c=Math.cos(d.yaw),s=Math.sin(d.yaw),x=p[0]*c+p[2]*s,z=p[2]*c-p[0]*s,y=p[1]*Math.cos(d.pitch)-z*Math.sin(d.pitch);return[x+d.lean*y,y];}
function compiled(a){let c=cache.get(a.sourceHash);if(c)return c;const {task}=a.payload,visual=VisualCapsule.author(a.source,a.payload.design.anatomy?.seed??1),design=visual.design,body=WovenBody.compile(design.woven,task),bounds=WovenBody.portraitFrame(body),lo=[Infinity,Infinity],hi=[-Infinity,-Infinity];for(let k=0;k<8;k++){const v=projection([bounds.cx+((k&1)?1:-1)*bounds.width/2,bounds.cy+((k&2)?1:-1)*bounds.height/2,bounds.cz+((k&4)?1:-1)*bounds.depth/2],design.composition);for(let j=0;j<2;j++){lo[j]=Math.min(lo[j],v[j]);hi[j]=Math.max(hi[j],v[j]);}}c={body,visual,rendered:LifeformRenderer.compile(task,design),design,task,lo,hi,colors:task.nodes.map((_,i)=>Chroma.colorFor({design,nodes:task.nodes},i))};if(cache.size>=16)cache.delete(cache.keys().next().value);cache.set(a.sourceHash,c);return c;}
function draw(canvas,a,time,node=null,values=null,view=null){const c=compiled(a),ctx=canvas.getContext('2d'),projection=LifeformRenderer.draw(canvas,c.rendered,time,{budget:6500,selectedNode:node,showProgram:!!node});metrics.frames++;metrics.renderMs.push(projection.metrics.renderMs);if(metrics.renderMs.length>120)metrics.renderMs.shift();
// Labels reuse the already projected operation anchors; drawing never evaluates tasks.
if(values){for(const id of values.ids.slice(0,5)){const t=traceValue(values.record,id);if(!t.available)continue;const v=projection.anchors.get(id);if(!v)continue;const label=id+': '+snippet(t.value,30),x=Math.min(canvas.width-220,Math.max(10,v.x+12)),y=Math.min(canvas.height-30,Math.max(24,v.y));ctx.font='12px monospace';ctx.fillStyle='#0c171fea';ctx.fillRect(x-6,y-16,Math.min(220,ctx.measureText(label).width+12),24);ctx.fillStyle='#e7d29f';ctx.fillText(label,x,y);}}
metrics.paints++;return projection;}
const shown=new Map([['intro-creature',true],['creature',true]]);
function paint(visibleOnly=false){if(!artifact)return;$('phase-value').textContent=Math.round(phase/TAU*100)+'%';if(!visibleOnly||shown.get('intro-creature'))draw($('intro-creature'),artifact,phase);const ids=[selected,...changedNodes().filter(id=>id!==selected)];if(!visibleOnly||shown.get('creature'))draw($('creature'),artifact,phase,selected,$('overlay').checked&&isCurrent()?{record:after,ids}:null);}
function select(id){recipe=library.get(id);artifact=session.compile(copy(recipe.intent));before=after=lastRequest=null;selected=stories[id].focus;phase=0;dirty=false;for(const b of document.querySelectorAll('[data-example]'))b.setAttribute('aria-pressed',String(b.dataset.example===id));$('example-number').textContent=String(order.indexOf(id)+1).padStart(2,'0');$('example-title').textContent=stories[id].title;$('question').textContent=stories[id].question;$('rule').textContent=stories[id].rule;$('assumption').textContent=stories[id].assumption;$('suggestion').textContent=stories[id].change;loadPresets();$('scenario').replaceChildren();recipe.fixtures.forEach((f,i)=>{const o=document.createElement('option');o.value=i;o.textContent=f.name;$('scenario').append(o);});if(stories[id].baselineInputs){const option=document.createElement('option');option.value='baseline';option.textContent='One confirmed unit — comparison baseline';$('scenario').prepend(option);$('scenario').value='baseline';}else $('scenario').value=stories[id].baseline??0;fillInputs(baseline(recipe));$('run-status').textContent='Both snapshots are ready to compare. No task has run yet.';$('proof').textContent='';$('proof-state').textContent='Run a matching comparison first to compare the recovered calculations.';$('program-source').textContent=compiled(artifact).visual.source;$('phase').value=0;}
function runComparison(){const values=readInputs();$('run-status').classList.remove('failure');const nextBefore=session.run({artifactId:artifact.id,requestId:'before-'+crypto.randomUUID(),inputs:baseline(recipe)});try{const nextRequest={artifactId:artifact.id,requestId:'after-'+crypto.randomUUID(),inputs:values};const nextAfter=session.run(nextRequest);before=nextBefore;after=nextAfter;lastRequest=nextRequest;dirty=false;renderResults();$('run-status').textContent=result(after).status==='failed'?'Evaluation failed. The record contains a diagnostic and only the nodes that finished.':'Both snapshots evaluated. Every reported value comes from the runtime.';return after;}catch(e){renderResults();$('after-result').textContent=format({status:'refused',code:e.code,path:e.path,message:e.message})+(after?'\nPrevious result:\n'+outputs(after):'');$('answer-caption').textContent=after?'The current inputs were refused. The previous complete comparison remains visible; no new pair was recorded.':'The current inputs were refused. No comparison has been recorded.';throw e;}}
function replay(){const count=metrics.evaluationRequests,record=session.run(lastRequest);if(record.id!==after.id)throw Error('Replay identity differs.');after=record;renderResults();$('run-status').textContent=`Same record returned; ${metrics.evaluationRequests-count} additional evaluation requests.`;return record;}
function renderDomain(){const host=$('domain-view');host.replaceChildren();if(!isCurrent()||result(after)?.status!=='completed')return;const ns='http://www.w3.org/2000/svg',svg=document.createElementNS(ns,'svg');svg.classList.add('domain');svg.setAttribute('viewBox','0 0 430 210');svg.setAttribute('role','img');const label=text=>{const t=document.createElementNS(ns,'title');t.textContent=text;svg.append(t);};function node(tag,attrs,text){const e=document.createElementNS(ns,tag);Object.entries(attrs).forEach(([k,v])=>e.setAttribute(k,String(v)));if(text!==undefined)e.textContent=text;svg.append(e);return e;}
if(recipe.id==='route-preview'){const pos={A:[45,105],B:[190,165],C:[190,45],D:[365,105]},route=result(after).outputs[0],v=after.result.bindings;node('text',{x:8,y:18,class:'chart-note'},'Walking proposal: '+result(after).outputs[1].status);label('Computed route '+route.path.join(' to ')+(result(after).outputs[1]?.status==='skipped'?'; walking proposal skipped':''));if(Object.entries(v.streets).some(([from,list])=>!pos[from]||list.some(to=>!pos[to])))node('text',{x:8,y:205,class:'chart-note'},'Partial chart: junctions A–D only. See the full result above.');for(const [from,list]of Object.entries(v.streets))for(const to of list){if(!pos[from]||!pos[to])continue;const active=route.path.some((id,i)=>id===from&&route.path[i+1]===to);node('line',{x1:pos[from][0],y1:pos[from][1],x2:pos[to][0],y2:pos[to][1],stroke:active?'#b9e4c6':'#344553','stroke-width':active?4:2});}for(const[id,[x,y]]of Object.entries(pos)){const blocked=v.blocked.includes(id);node('circle',{cx:x,cy:y,r:20,fill:blocked?'#512d30':'#263e3d',stroke:blocked?'#e4a99a':'#b9e4c6'});node('text',{x,y:y+4,'text-anchor':'middle'},id+(blocked?' ×':''));}}
else if(recipe.id==='receipt-reconciliation'){const rows=receiptTimeline(after);label('Latest supplied state by attempt; retry advice '+result(after).outputs[0].mayRetry);rows.slice(0,4).forEach((r,i)=>{node('circle',{cx:20,cy:32+i*38,r:7,fill:r.latest?.status==='confirmed'?'#b9e4c6':'#e7d29f'});node('text',{x:38,y:36+i*38},r.attempt+': '+r.latest.status+' · '+r.latest.units+' units');});node('text',{x:8,y:205,class:'chart-note'},rows.length>4?'First 4 of '+rows.length+' attempts; full timeline below.':'Latest sequence per matching attempt; history below.');const detail=document.createElement('pre');detail.textContent=format(rows);host.append(detail);}
else if(recipe.id==='water-total'){const all=after.result.bindings.readings,v=all.slice(0,12),max=Math.max(1,...v);label('Measured liters by reading'+(all.length>12?'; first 12 of '+all.length:''));if(all.length>12)node('text',{x:8,y:205,class:'chart-note'},'First 12 of '+all.length+' readings; the total uses every reading.');v.forEach((n,i)=>{const w=360/Math.max(1,v.length),h=n/max*130;node('rect',{x:30+i*w,y:165-h,width:Math.max(1,w-8),height:h,fill:'#9ac8c0',rx:3});node('text',{x:30+i*w,y:185},snippet(n,9));});}
else if(recipe.id==='work-schedule'){const out=result(after).outputs[0],deadline=after.result.bindings.deadline,max=Math.max(1,out.makespan,deadline);label('Computed work schedule; makespan '+out.makespan+', deadline '+deadline+(out.jobs.length>5?'; first five jobs':''));node('line',{x1:50+deadline/max*320,x2:50+deadline/max*320,y1:5,y2:190,stroke:'#e7d29f','stroke-dasharray':'3 3'});node('text',{x:8,y:205,class:'chart-note'},'Deadline '+deadline+(out.jobs.length>5?'; first 5 of '+out.jobs.length+' jobs shown':''));out.jobs.slice(0,5).forEach((j,i)=>{node('text',{x:8,y:30+i*35},j.id);node('rect',{x:50+j.start/max*320,y:14+i*35,width:Math.max(1,(j.end-j.start)/max*320),height:22,rx:3,fill:'#b9c6a3'});node('text',{x:52+j.start/max*320,y:30+i*35,class:'bar-label'},j.start+'–'+j.end);});}
else {const r=result(after),bindings=after.result.bindings,t=id=>traceValue(after,id).value;label(detailedSummary(recipe.id,after)||stories[recipe.id].title);let rows=[];
if(recipe.id==='craft-quote')rows=[['Requested batches',bindings.requested],['Ore bound',t('oreBound')],['Wood bound',t('woodBound')],['Space bound',t('spaceBound')],['Feasible batches',t('feasible')]];
else if(recipe.id==='needs-triage')rows=bindings.foods.map(f=>[f.id+(f.id===t('chosenId')?' · selected':'')+(f.edible&&f.fresh?'':' · ineligible'),f.restoration]);
else if(recipe.id==='trade-preview')rows=['found','unexpired','hasInventory','hasStock','withinAllowance','positive'].map(id=>[nodeLabel(recipe.id,{id}),t(id)]);
else if(recipe.id==='gather-readiness')rows=['Skill','Route','Reservation','Capacity','Owner permission','Remaining uses'].map((name,i)=>[name,bindings.checks[i]]).concat([['Fresh observation',t('fresh')]]);
else if(recipe.id==='confirmed-checkpoints')rows=[['Haul',r.outputs[0].haul],['Arrival',r.outputs[0].arrival],['Complete',r.outputs[1]]];
else if(recipe.id==='evidence-ledger')rows=[['Support',r.outputs[0].support],['Refutation',r.outputs[0].refute],['Source labels',r.outputs[0].sources],['State',r.outputs[0].state]];
const height=Math.max(210,rows.length*30+35);svg.setAttribute('viewBox','0 0 430 '+height);const numbers=rows.map(([,v])=>v).filter(v=>typeof v==='number'),max=Math.max(1,...numbers);
rows.forEach(([name,value],i)=>{const y=24+i*30;node('text',{x:8,y},name);if(typeof value==='number'){node('rect',{x:235,y:y-14,width:Math.max(1,value/max*125),height:18,rx:3,fill:'#9ac8c0'});node('text',{x:370,y},String(value));}else node('text',{x:275,y,fill:value===false||value==='conflict'?'#e4a99a':'#b9e4c6'},String(value));});
if(['evidence-ledger','confirmed-checkpoints'].includes(recipe.id)){const supplied=document.createElement('details'),summary=document.createElement('summary'),data=document.createElement('pre');summary.textContent='Supplied provenance — these labels are unauthenticated';data.textContent=format({supplied:bindings.records,evaluated:evidenceProvenance(recipe.id,after)});supplied.append(summary,data);host.append(supplied);}
}host.prepend(svg);}
function geometry(a,b){if(a.sourceHash!==b.sourceHash){const topology=x=>({mechanism:compiled(x).design.woven.mechanism,strands:compiled(x).design.woven.strands,features:compiled(x).design.woven.topology});const sameTopology=canon(topology(a))===canon(topology(b));const shared=a.payload.task.nodes.filter(n=>b.payload.task.nodes.some(m=>m.id===n.id));let squared=0;for(const n of shared){const p=WovenBody.anchor(compiled(a).body,n.id,0),q=WovenBody.anchor(compiled(b).body,n.id,0);squared+=(p.x-q.x)**2+(p.y-q.y)**2+(p.z-q.z)**2;}return{sameTopology,correspondingSamples:false,sharedNodeAnchors:shared.length,anchorXyzRms:Math.sqrt(squared/shared.length),components:[compiled(a).design.woven.strands,compiled(b).design.woven.strands],ownershipBands:[compiled(a).design.woven.territories.length,compiled(b).design.woven.territories.length],reason:'Area-weighted sample plans differ; indexed points are not corresponding tissue. Shared operation anchors are compared at phase zero.'};}const frameA=Array.from(WovenBody.frame(compiled(a).body,0,{budget:4000,crests:3}).points),frameB=WovenBody.frame(compiled(b).body,0,{budget:4000,crests:3}).points;let squared=0,max=0;for(let i=0;i<frameA.length;i+=4){let d=0;for(let j=0;j<3;j++)d+=(frameA[i+j]-frameB[i+j])**2;squared+=d;max=Math.max(max,Math.sqrt(d));}return{sameTopology:true,xyzRms:Math.sqrt(squared/(frameA.length/4)),maxDisplacement:max};}
function sharedView(...artifacts){const composition=compiled(artifacts[0]).design.composition,lo=[Infinity,Infinity],hi=[-Infinity,-Infinity];for(const a of artifacts){const b=WovenBody.portraitFrame(compiled(a).body);for(let k=0;k<8;k++){const v=projection([b.cx+((k&1)?1:-1)*b.width/2,b.cy+((k&2)?1:-1)*b.height/2,b.cz+((k&4)?1:-1)*b.depth/2],composition);for(let j=0;j<2;j++){lo[j]=Math.min(lo[j],v[j]);hi[j]=Math.max(hi[j],v[j]);}}}return{composition,lo,hi};}
function programVariant(){const water=library.get('water-total'),one=session.compile(copy(water.intent)),two=session.compile(cappedWaterIntent(water)),values={readings:parse($('variant-readings').value)},first=session.run({artifactId:one.id,requestId:'variant-base-'+crypto.randomUUID(),inputs:values}),second=session.run({artifactId:two.id,requestId:'variant-cap-'+crypto.randomUUID(),inputs:values});const shared=sharedView(one,two);draw($('variant-before'),one,0,'total',{record:first,ids:['total']},shared);draw($('variant-after'),two,0,'cappedWater',{record:second,ids:['cappedWater']},shared);$('variant-before-output').textContent=outputs(first);$('variant-after-output').textContent=outputs(second);const edge=a=>a.payload.task.nodes.reduce((sum,n)=>sum+n.inputs.length,0);$('variant-result').textContent=`Source changed. ${one.payload.task.nodes.length} → ${two.payload.task.nodes.length} nodes; ${edge(one)} → ${edge(two)} edges. The added limit owns a new source-declared material territory. Both programs use the same readings.`;$('variant-code').textContent=format({originalSource:one.sourceHash,cappedSource:two.sourceHash,addedOperation:two.payload.task.nodes.find(n=>n.id==='cappedWater'),originalOutputs:result(first).outputs,cappedOutputs:result(second).outputs,sourceEmissionExact:[first.result.emitted[0]===one.source,second.result.emitted[0]===two.source],geometry:geometry(one,two),view:{phase:0,samples:4000,sharedProjection:true,camera:shared.composition,bounds:{lo:shared.lo,hi:shared.hi}}});$('evaluation-count').textContent=metrics.evaluationRequests;return{one,two,first,second};}
function verifySource(){const count=metrics.evaluationRequests,proof=session.verify(artifact.id);$('proof').textContent=format({visualCapsule:VisualCapsule.verify(compiled(artifact).visual),sourceEmittedExactly:proof.source===artifact.source,sourceHash:proof.sourceHash,constructorSteps:proof.constructorSteps,additionalEvaluationRequests:metrics.evaluationRequests-count});$('proof-state').textContent='The constructor rebuilt its complete source. No task was evaluated.';return proof;}
function recoverGenome(encoding){if(!['harmonics','colors'].includes(encoding))throw Error('Choose harmonics or colors.');const count=metrics.evaluationRequests,fresh=new V1Session(),recovered=fresh.recover(encoding==='harmonics'?{harmonics:Quinelings.encode(JSON.parse(artifact.source))}:{colors:Quinelings.encodeColors(JSON.parse(artifact.source))}),proof={encoding,exactVisualSource:VisualCapsule.recover(compiled(artifact).visual,encoding).source===compiled(artifact).visual.source,exactSource:recovered.source===artifact.source,sourceHash:recovered.sourceHash,additionalEvaluationRequests:metrics.evaluationRequests-count};if(!proof.exactSource)throw Error('Recovered bytes differ.');$('proof').textContent=format(proof);$('proof-state').textContent='Genome decoded into the complete source. No task was evaluated; no history was restored.';return proof;}
function generations(){if(!isCurrent())throw Error('Run the current inputs first.');const expected=after.result,rows=[];let source=artifact.source;for(const encoding of ['source','harmonics','colors']){const fresh=new V1Session(),parent=fresh.recover(encoding==='source'?{source}:encoding==='harmonics'?{harmonics:Quinelings.encode(JSON.parse(source))}:{colors:Quinelings.encodeColors(JSON.parse(source))}),r=fresh.run({artifactId:parent.id,requestId:'generation-'+encoding,inputs:copy(after.result.bindings)});rows.push({recovery:encoding,exactVisualSource:encoding==='source'?VisualCapsule.verify(compiled(artifact).visual).exactSource:VisualCapsule.recover(compiled(artifact).visual,encoding).source===compiled(artifact).visual.source,exactSource:parent.source===artifact.source,emissionExact:r.result.emitted[0]===artifact.source,exactCalculation:canon(r.result)===canon(expected),sourceHash:parent.sourceHash});source=r.result.emitted[0];}if(rows.some(r=>!r.exactSource||!r.emissionExact||!r.exactCalculation))throw Error('A reconstruction did not match.');$('proof').textContent=format(rows);$('proof-state').textContent='Three fresh sessions recovered the complete source and calculated the same result. No execution history was imported.';$('evaluation-count').textContent=metrics.evaluationRequests;return rows;}
function retryPolicy(){const max=Number($('retry-cap').value);if(!Number.isSafeInteger(max)||max<1||max>8)throw Error('Choose an integer cap from 1 to 8.');const intent=cap=>({format:'qdl-intent',version:1,name:'Bounded review of prepared retry outcomes',thought:'Inspect the supplied prepared outcome list up to the authored attempt cap; submit no work.',inputs:[{id:'outcomes',name:'outcomes',type:{kind:'array',element:{kind:'string',enum:['ok','retry','unknown']}}}],steps:[{id:'review',op:'retry',inputs:['outcomes'],params:{maxAttempts:cap}}],outputs:['review']}),base=session.compile(intent(4)),edited=session.compile(intent(max)),values={outcomes:['retry','retry','ok']},first=session.run({artifactId:base.id,requestId:'retry-four-'+crypto.randomUUID(),inputs:values}),second=session.run({artifactId:edited.id,requestId:'retry-edited-'+crypto.randomUUID(),inputs:values});const output={preparedOutcomes:values.outcomes,baseline:{cap:4,result:result(first).outputs[0],source:base.sourceHash},edited:{cap:max,result:result(second).outputs[0],source:edited.sourceHash},sourceChanged:base.sourceHash!==edited.sourceHash,effectsPublished:[result(first).effects.length,result(second).effects.length]};$('retry-policy-output').textContent=format(output);$('evaluation-count').textContent=metrics.evaluationRequests;return output;}
$('retry-policy-run').onclick=safe(retryPolicy,'retry-status');$('load-change').onclick=safe(()=>{fillInputs(changed(recipe));$('scenario').selectedIndex=-1;$('suggestion').textContent=stories[recipe.id].change;$('audit-scenario').value='change';$('run-status').textContent='Suggested inputs loaded. Run the comparison to calculate them.';});$('scenario').onchange=safe(()=>{fillInputs($('scenario').value==='baseline'?baseline(recipe):recipe.fixtures[Number($('scenario').value)].inputs);$('suggestion').textContent='Prepared snapshot: '+$('scenario').selectedOptions[0].textContent+'. Compare it with the baseline; inspect the recorded guards when outputs agree.';$('run-status').textContent='Prepared inputs loaded; they have no new result yet.';});$('compare').onclick=safe(runComparison);$('replay').onclick=safe(replay);$('variant-run').onclick=safe(programVariant,'variant-status');$('verify-source').onclick=safe(verifySource,'proof-state');$('generations').onclick=safe(generations,'proof-state');$('recover-harmonics').onclick=safe(()=>recoverGenome('harmonics'),'proof-state');$('recover-colors').onclick=safe(()=>recoverGenome('colors'),'proof-state');$('overlay').onchange=paint;
function foodVariant(){const food=library.get('needs-triage'),base=session.compile(copy(food.intent)),edited=session.compile(positiveFoodIntent(food)),values={foods:[{id:'zero',edible:true,fresh:true,restoration:0}],hunger:4,current:true},first=session.run({artifactId:base.id,requestId:'food-base-'+crypto.randomUUID(),inputs:values}),second=session.run({artifactId:edited.id,requestId:'food-positive-'+crypto.randomUUID(),inputs:values});const evidence={originalSource:base.sourceHash,positiveSource:edited.sourceHash,original:result(first).outputs,positive:result(second).outputs,emissionExact:[first.result.emitted[0]===base.source,second.result.emitted[0]===edited.source],originalRetained:true};$('food-output').textContent=format(evidence);$('food-status').textContent='The retained rule proposes the zero-restoration food; the new rule skips it and reports why. Two separately authored programs ran with the same inputs.';$('evaluation-count').textContent=metrics.evaluationRequests;return evidence;}
$('food-run').onclick=safe(foodVariant,'food-status');
function loadPresets(){const select=$('audit-scenario');select.replaceChildren();const empty=document.createElement('option');empty.value='';empty.textContent='Choose a variation';select.append(empty);for(const p of scenarioPresets(recipe)){const o=document.createElement('option');o.value=p.id;o.textContent=p.label;select.append(o);}}
function syncCurrentControl(){const label=$('current-control'),port=document.querySelector('[data-port="current"]');label.hidden=!port;if(port){try{$('current-snapshot').checked=JSON.parse(port.value)===true;}catch{$('current-snapshot').checked=false;}}}
$('current-snapshot').onchange=safe(()=>{const port=document.querySelector('[data-port="current"]');port.value=String($('current-snapshot').checked);port.dispatchEvent(new Event('input'));$('suggestion').textContent='The caller supplies this freshness flag. A route or candidate can exist while its action proposal is skipped.';});
$('audit-scenario').onchange=safe(()=>{const preset=scenarioPresets(recipe).find(p=>p.id===$('audit-scenario').value);if(!preset)return;fillInputs(preset.inputs);$('scenario').selectedIndex=-1;$('suggestion').textContent=preset.explanation;$('run-status').textContent='Inputs loaded. Run the comparison to see the result.';});
$('reset-session').onclick=safe(()=>{const id=recipe.id,raw=Array.from(document.querySelectorAll('[data-port]'),el=>[el.dataset.port,el.value]);session=new V1Session();cache.clear();select(id);for(const [port,value]of raw)document.querySelector('[data-port="'+port+'"]').value=value;renderResults();for(const output of ['variant-code','variant-before-output','variant-after-output','retry-policy-output','food-output','offspring-output'])$(output).textContent='Local history cleared. Build again.';for(const canvas of ['variant-before','variant-after','offspring-parent','offspring-child']){const el=$(canvas);el.getContext('2d').clearRect(0,0,el.width,el.height);}for(const status of ['variant-status','variant-result','retry-status','food-status','offspring-status']){$(status).textContent='Local history cleared. Build again.';$(status).classList.remove('failure');}$('run-status').textContent='Local run history cleared. Source and edited inputs retained; the cumulative request counter is unchanged.';});
$('offspring-run').onclick=safe(()=>{const water=library.get('water-total'),parent=session.compile(copy(water.intent)),donor=session.compile(copy(library.get('craft-quote').intent)),experiment=bodyOnlyExperiment(session,parent,donor,{readings:[1.5,5,.5]},Number($('offspring-nonce').value));const view=sharedView(parent,experiment.child);draw($('offspring-parent'),parent,0,null,null,view);draw($('offspring-child'),experiment.child,0,null,null,view);$('offspring-output').textContent=format({...experiment.evidence,outputs:result(experiment.childRecord).outputs,geometry:geometry(parent,experiment.child),sharedProjection:true});$('offspring-status').textContent='The child has a new body and gives the same water total. Its complete source was recovered from the RGB genome.';$('evaluation-count').textContent=metrics.evaluationRequests;return experiment;},'offspring-status');
function motionState(){$('motion').textContent=playing?'Pause motion':'Play motion';$('motion').setAttribute('aria-pressed',String(playing));}motionState();$('motion').onclick=()=>{playing=!playing;clock=0;motionState();};$('phase').oninput=()=>{playing=false;motionState();phase=Number($('phase').value)/100*TAU;paint();};document.addEventListener('visibilitychange',()=>{clock=0;});function tick(now){if(playing&&!document.hidden&&[...shown.values()].some(Boolean)&&now-clock>=1000/30){if(clock){metrics.intervalMs.push(now-clock);if(metrics.intervalMs.length>120)metrics.intervalMs.shift();}if(clock)phase=(phase+Math.min(.2,(now-clock)/1000)*.45)%TAU;clock=now;$('phase').value=phase/TAU*100;paint(true);}requestAnimationFrame(tick);}requestAnimationFrame(tick);if('IntersectionObserver'in window){const observer=new IntersectionObserver(entries=>{for(const entry of entries)shown.set(entry.target.id,entry.isIntersecting);clock=0;if(artifact)paint(true);});for(const id of shown.keys())observer.observe($(id));}
matchMedia('(prefers-reduced-motion: reduce)').addEventListener('change',event=>{if(event.matches){playing=false;clock=0;motionState();}});
$('download-source').onclick=e=>{e.preventDefault();const blob=new Blob([format({source:artifact.source,visualSource:compiled(artifact).visual.source})],{type:'application/json'}),url=URL.createObjectURL(blob),a=document.createElement('a');a.href=url;a.download='quineling-source.json';a.click();setTimeout(()=>URL.revokeObjectURL(url),1000);};for(const id of order){const button=document.createElement('button');button.textContent=stories[id].title;button.dataset.example=id;button.onclick=safe(()=>select(id));$('examples').append(button);}select(order[0]);
window.quinelingLab={metrics,select,runComparison,replay,programVariant,retryPolicy,foodVariant,verifySource,recoverGenome,generations,geometry,readInputs,get visual(){return compiled(artifact).visual;},get artifact(){return artifact;},get before(){return before;},get after(){return after;},get phase(){return phase;},get playing(){return playing;},get current(){return isCurrent();},get session(){return session;}};
fetch('./living-copy.json').then(r=>{if(!r.ok)throw Error('Editorial copy unavailable');return r.json();}).then(text=>{for(const el of document.querySelectorAll('[data-copy]')){const value=text[el.dataset.copy];if(typeof value==='string')el.textContent=value;}}).catch(()=>{});