const http=require('http'),fs=require('fs'),path=require('path'),{spawn}=require('child_process');
const ROOT='D:/Skynet/browser_reliability_research', tasks=JSON.parse(fs.readFileSync(path.join(ROOT,'results/tasks.json'),'utf8')), plans=JSON.parse(fs.readFileSync(path.join(ROOT,'llm_pilot_n30/plan_index.json'),'utf8'));
const taskMap=new Map(tasks.map(t=>[t.id,t])), stateMap=new Map(); const sleep=ms=>new Promise(r=>setTimeout(r,ms));
function rng(seed){let a=seed>>>0;return()=>{a|=0;a=a+0x6D2B79F5|0;let t=Math.imul(a^a>>>15,1|a);t=t+Math.imul(t^t>>>7,61|t)^t;return((t^t>>>14)>>>0)/4294967296}} function pick(r,a){return a[Math.floor(r()*a.length)]}
const decoys=['Archive','Preview','Draft','Sandbox','Template','Mirror'];
function pageHtml(t,runId){const r=rng(t.seed+runId.length*17),cards=[],dn=[];for(let i=0;i<t.decoyCount;i++)dn.push(pick(r,decoys.filter(x=>!dn.includes(x))));for(const name of dn)cards.push(`<section class="card decoy" data-project="${name}"><h2>Project ${name}</h2><label>Mode <select><option>${t.wrong}</option><option>${t.target}</option></select></label><button class="save decoy-save">Save change</button><p class="status"></p></section>`);cards.push(`<section class="card target" data-project="${t.project}"><h2>Project ${t.project}</h2><label>Mode <select id="mode"><option>${t.wrong}</option><option>${t.target}</option></select></label><button id="save" class="save">Save change</button><p id="status" class="status"></p><p id="summary">Current mode: ${t.wrong}</p></section>`);return `<!doctype html><html><head><meta charset=utf-8><title>LLM pilot</title><style>body{font-family:Arial;margin:32px}.card{border:1px solid #bbb;padding:18px;margin:14px 0}</style></head><body><h1>Configuration Console</h1><p>${t.task}</p><div id=root>${t.accessDelay?'<div>Loading workspace...</div>':cards.join('')}</div><script>const cfg=${JSON.stringify(t)},runId=${JSON.stringify(runId)};let clicks=0,swallowed=${t.swallowedClicks};function bind(){document.querySelectorAll('.decoy-save').forEach(b=>b.onclick=()=>{let s=b.closest('.card').querySelector('.status');s.textContent='Saved';s.className='status success'});const save=document.getElementById('save');if(!save)return;save.onclick=()=>{clicks++;const mode=document.getElementById('mode').value;if(swallowed>0){swallowed--;return}if(clicks<cfg.requiredClicks){let s=document.getElementById('status');s.textContent='Saved';s.className='status success';return}let s=document.getElementById('status');s.textContent='Saved';s.className='status success';fetch('/commit?run='+encodeURIComponent(runId)+'&mode='+encodeURIComponent(mode)+'&delay='+cfg.commitDelay).catch(()=>{})}}${t.accessDelay?`setTimeout(()=>{document.getElementById('root').innerHTML=${JSON.stringify(cards.join(''))};bind()},${t.accessDelay})`:'bind()'};async function refresh(){try{let x=await fetch('/state?run='+encodeURIComponent(runId)).then(r=>r.json());let e=document.getElementById('summary');if(e)e.textContent='Current mode: '+x.mode}catch{}}setInterval(refresh,80)</script></body></html>`}
const server=http.createServer((req,res)=>{const u=new URL(req.url,'http://127.0.0.1');if(u.pathname==='/task'){let t=taskMap.get(u.searchParams.get('tid')),run=u.searchParams.get('run');res.writeHead(t?200:404,{'content-type':'text/html','cache-control':'no-store'});return res.end(t?pageHtml(t,run):'missing')}if(u.pathname==='/commit'){let run=u.searchParams.get('run'),mode=u.searchParams.get('mode'),delay=Number(u.searchParams.get('delay')||0),s=stateMap.get(run);if(s)setTimeout(()=>{s.mode=mode;s.committedAt=Date.now()},delay);res.writeHead(204);return res.end()}if(u.pathname==='/state'){let s=stateMap.get(u.searchParams.get('run'))||{mode:'UNKNOWN'};res.writeHead(200,{'content-type':'application/json','cache-control':'no-store'});return res.end(JSON.stringify(s))}res.writeHead(404);res.end()});
async function connect(wsUrl){let ws=new WebSocket(wsUrl);await new Promise((o,e)=>{ws.onopen=o;ws.onerror=e});let seq=0,p=new Map();ws.onmessage=e=>{let m=JSON.parse(e.data);if(m.id&&p.has(m.id)){let q=p.get(m.id);p.delete(m.id);m.error?q.rej(new Error(m.error.message)):q.res(m.result)}};return{ws,send:(method,params={})=>new Promise((res,rej)=>{let id=++seq;p.set(id,{res,rej});ws.send(JSON.stringify({id,method,params}))})}}
async function waitChrome(port){for(let i=0;i<100;i++){try{let r=await fetch(`http://127.0.0.1:${port}/json`);if(r.ok){let j=await r.json(),p=j.find(x=>x.type==='page');if(p)return p}}catch{}await sleep(100)}throw Error('cdp unavailable')}
async function ev(send,x){let r=await send('Runtime.evaluate',{expression:x,returnByValue:true,awaitPromise:true});if(r.exceptionDetails)throw Error('eval');return r.result.value}async function nav(send,url){await send('Page.navigate',{url});for(let i=0;i<60;i++){let s=await ev(send,'document.readyState');if(s==='complete'||s==='interactive')break;await sleep(25)}await sleep(20)}
async function execute(send,base,t,row){let focusProject=null;let normProject=x=>String(x||'').replace(/^Project\s+/i,'').trim();let run=`llm-${row.mode}-${t.id}-${Date.now()}`,url=`${base}/task?tid=${t.id}&run=${encodeURIComponent(run)}`;stateMap.set(run,{mode:t.wrong,committedAt:null});await nav(send,url);let lastVerifyFailed=false,everSuccess=false,executed=0,errors=[];const steps=(row.plan&&row.plan.steps)||[];for(const st of steps){if(st.only_if_previous_verify_failed&&!lastVerifyFailed)continue;try{if(st.action==='wait'){await sleep(Math.min(2000,Math.max(0,Number(st.ms)||0)));executed++}else if(st.action==='select'){let wanted=normProject(st.project)||focusProject;if(wanted)focusProject=wanted;let ok=true;if(st.mode){ok=await ev(send,`(()=>{let card=[...document.querySelectorAll('.card')].find(c=>c.dataset.project===${JSON.stringify(wanted)});if(!card)return false;let s=card.querySelector('select');if(!s)return false;let o=[...s.options].find(o=>o.textContent===${JSON.stringify(st.mode)});if(!o)return false;s.value=o.value;s.dispatchEvent(new Event('change',{bubbles:true}));return true})()`);}else if(!wanted){ok=false;}executed++;if(!ok)errors.push('select_not_found')}else if(st.action==='click'){let wanted=normProject(st.project)||focusProject;if(wanted)focusProject=wanted;let labels=String(st.label||'').toLowerCase()==='save'?['save','save change']:[String(st.label||'').toLowerCase()];let ok=await ev(send,`(()=>{let card=[...document.querySelectorAll('.card')].find(c=>c.dataset.project===${JSON.stringify(wanted)});if(!card)return false;let labels=${JSON.stringify(labels)};let b=[...card.querySelectorAll('button')].find(b=>labels.includes((b.innerText||'').trim().toLowerCase()));if(!b)return false;b.click();return true})()`);executed++;if(!ok)errors.push('click_not_found');await sleep(35)}else if(st.action==='verify'){let ok=await ev(send,`(document.body.innerText||'').includes(${JSON.stringify(st.text||'')})`);executed++;lastVerifyFailed=!ok}else if(st.action==='reload'){await nav(send,url);executed++}everSuccess=everSuccess||await ev(send,`!!document.querySelector('.status.success')`)}catch(e){errors.push(st.action+':'+String(e.message||e))}}
await sleep(75);let gt=stateMap.get(run),vts=gt&&gt.mode===t.target;let finalText=await ev(send,'document.body.innerText||""');stateMap.delete(run);return{taskId:t.id,layer:t.layer,severity:t.severity,promptMode:row.mode,planOk:row.ok,verifiedTaskSuccess:!!vts,apparentSuccess:everSuccess,falseCompletion:everSuccess&&!vts,executedSteps:executed,planSteps:steps.length,errors,finalContainsTarget:finalText.includes('Current mode: '+t.target),plan:row.plan}}
function wilson(k,n,z=1.95996398454){if(!n)return[0,0];let p=k/n,zz=z*z,d=1+zz/n,c=(p+zz/(2*n))/d,h=z*Math.sqrt((p*(1-p)+zz/(4*n))/n)/d;return[Math.max(0,c-h),Math.min(1,c+h)]}
(async()=>{await new Promise(o=>server.listen(0,'127.0.0.1',o));let base=`http://127.0.0.1:${server.address().port}`,port=9361,profile=path.join(ROOT,'llm-pilot-chrome');try{fs.rmSync(profile,{recursive:true,force:true})}catch{}let cp=spawn('C:/Program Files/Google/Chrome/Application/chrome.exe',[`--remote-debugging-port=${port}`,`--user-data-dir=${profile}`,'--headless=new','--disable-gpu','--no-first-run','about:blank'],{stdio:'ignore',windowsHide:true}),target=await waitChrome(port),c=await connect(target.webSocketDebuggerUrl),send=c.send;await send('Page.enable');await send('Runtime.enable');let out=[];for(let i=0;i<plans.length;i++){let r=plans[i],t=taskMap.get(r.taskId);if(!r.ok||!t)continue;let x=await execute(send,base,t,r);out.push(x);console.log(`${i+1}/${plans.length} ${x.promptMode} ${x.taskId} ${x.layer} VTS=${x.verifiedTaskSuccess}`)}fs.writeFileSync(path.join(ROOT,'llm_pilot_n30/executions.json'),JSON.stringify(out,null,2));let summary={};for(const mode of ['default','reliability']){let g=out.filter(x=>x.promptMode===mode),s=g.filter(x=>x.verifiedTaskSuccess).length,a=g.filter(x=>x.apparentSuccess).length,f=g.filter(x=>x.falseCompletion).length;summary[mode]={n:g.length,verified_success:s,verified_rate:s/g.length,wilson95:wilson(s,g.length),apparent_success:a,false_completions:f,mean_steps:g.reduce((q,x)=>q+x.executedSteps,0)/g.length,by_layer:Object.fromEntries(['baseline','access','perception','action','state','verification'].map(l=>{let z=g.filter(x=>x.layer===l);return[l,{n:z.length,vts:z.filter(x=>x.verifiedTaskSuccess).length,rate:z.length?z.filter(x=>x.verifiedTaskSuccess).length/z.length:0}] }))}}fs.writeFileSync(path.join(ROOT,'llm_pilot_n30/summary.json'),JSON.stringify(summary,null,2));c.ws.close();try{cp.kill()}catch{}server.close();console.log('DONE '+JSON.stringify(summary))})().catch(e=>{console.error(e);try{server.close()}catch{};process.exit(1)});


