bostrat-node 1.13.0 → 1.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +8 -8
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -157,7 +157,7 @@ your turn. The operator sees the questions as an interactive card in their chat
157
157
  They may instead reply in free text \u2014 treat that as the answer. Never use the block for rhetorical questions, progress updates, or
158
158
  anything you can decide yourself; keep asking in prose for questions without
159
159
  enumerable options.
160
- `});function xF(e){return{id:e.id,kind:"prompt",groupId:e.groupId,provider:e.provider,box:e.box,agent:e.provider,questionTotal:e.questions.length,answeredVia:"chat",questions:e.questions.map((t,n)=>({index:n,header:t.header||"",question:t.question,multiSelect:!!t.multiSelect,chosen:[]})),ts:e.ts}}function fA(e,t,n){let r=fw(n),o=e.has(r)?r:null;if(!o&&n.number!=null)for(let[i,c]of e){if(Number(c.number)!==Number(n.number))continue;let l=!!(n.url&&c.url&&n.url===c.url),u=!c.repo&&!!n.repo||!!c.repo&&!n.repo;if(l||u&&(!c.url||!n.url||c.url===n.url)){o=i;break}}let s=n.repo||!o?r:o,a=o?e.get(o):e.get(s);if(o&&o!==s){e.delete(o);let i=t.get(o);if(t.delete(o),i?.length){let c=t.get(s)??[];t.set(s,c.concat(i))}}return e.set(s,{number:n.number,url:n.url??a?.url??null,title:n.title??a?.title??null,repo:n.repo??a?.repo??null,branch:n.branch??a?.branch??null}),s}function Gn(e,{now:t=Date.now()}={}){let n=[],r=new Set,o=new Set,s=new Map,a=new Map,i=new Set,c=new Map,l=new Map,u=new Map,d=(k,f)=>{f!=null&&(u.has(k)||u.set(k,[]),u.get(k).push(f))},p=(k,f)=>{let v=null;for(let O of[k,null])for(let G of u.get(O)||[])G>f&&(v==null||G<v)&&(v=G);return v},m=new Set,w=new Map,h=new Map,g=(k,f)=>{h.set(k,f),n.push(f)},b=k=>{let f=h.get(k);f&&(f.retired=!0)},y=/^Agent "([\s\S]+)" finished$/,x=new Map;for(let k of e||[]){if(k.type!=="tool.called"||k.source!=="transcript")continue;let f=String(k.payload?.command||"");if(/\bbostrat-mock\s+(?:add|update)\b/.test(f))for(let v of f.matchAll(/[\w./~-]+\.(?:png|jpe?g|gif|webp|bmp|svg)\b/gi)){let O=v[0].split("/").pop().toLowerCase();x.has(O)||x.set(O,[]),x.get(O).push(k.payload?.ts??k.ts)}}let E=3*6e4,A=20*6e4,$=(k,f)=>!!(k?.name&&x.get(String(k.name).toLowerCase()))?.some(O=>O>=f-E&&O<=f+A);for(let k of e||[])if(k.type==="turn.retracted"){o.add(`${k.boxId}|${k.payload?.saidTs}`);let f=Be(k.payload?.text);f&&(s.has(k.boxId)||s.set(k.boxId,[]),s.get(k.boxId).push(f))}else if(k.type==="turn.user"&&k.source==="orchestrator"){let f=Be(k.payload?.text);f&&(a.has(k.boxId)||a.set(k.boxId,new Set),a.get(k.boxId).add(f))}else if(k.type==="job.stalled"&&k.payload?.id)c.set(k.payload.id,{ts:me(k),quietMs:Number(k.payload.quietMs)||null});else if(k.type==="job.stopped"&&k.payload?.id)l.has(k.payload.id)||l.set(k.payload.id,{status:"killed",summary:null,resultHead:null,ts:me(k)});else if(k.type==="session.ready"){let f=k.payload?.source;f!=="compact"&&f!=="clear"&&d(k.boxId??null,me(k))}else if(k.type==="handoff.done")d(k.boxId??k.payload?.from??null,me(k));else if(k.type==="box.state.changed"&&k.payload?.change==="archived")d(null,me(k));else if(k.type==="job.started"&&k.payload?.id)i.add(k.payload.id),(k.payload.kind||"agent")==="agent"&&k.payload.name&&m.add(k.payload.name);else if(k.type==="turn.user"&&k.payload?.note?.kind==="task"){let f=k.payload.note,v={status:f.status||null,summary:f.summary||null,resultHead:f.resultHead??null,ts:me(k)};f.toolUseId&&l.set(f.toolUseId,v);let O=String(f.summary||"").match(y);O&&w.set(O[1],v)}let P=new Map,L=new Map,T=null,C=new Map,j=new Map,K=new Map,M=new Map,I=new Map,S=new Map,U=new Map,W=new Map,ie=new Map,z=new Map,Ge=new Map,_e=new Map,Y=new Map,ne=new Map,Ie=new Map,Pe=new Map,ae=(k,f)=>{k.arm.status=f;let v=k.line,O=v.arms.map(G=>G.status);v.status=O.includes("armed")?"armed":O.includes("offered")?"offered":O.includes("replaced")?"replaced":"cancelled"},Ae=[],be=new Set,Q=new Map,he=(k,f)=>{Q.delete(k);let v=n.indexOf(k);v>=0&&n.splice(v,1),f!=null&&(k.ts=f),n.push(k)},Ue=k=>{if(Ae.push(k),!(k.box?be.has(k.box):be.size>0))return;let v=n.indexOf(k);v>=0&&n.splice(v,1),Q.set(k,"held")},nt=k=>{if(!Ae.length)return;let f=me(k);for(let v of Ae)v.status!=="open"||Q.get(v)==="superseded"||v.box&&v.box!==k.boxId||(v.ts??0)>f||he(v,f)},rt=k=>{if(!Ae.length)return;let f=me(k);for(let v of Ae)Q.get(v)!=="held"||v.status!=="open"||v.box&&k.boxId&&v.box!==k.boxId||he(v,Math.max(v.ts??0,f))},N=()=>{for(let[k,f]of[...Q])f==="held"&&he(k,null);Ae.length=0,se.clear()},se=new Set,le=k=>{for(let f of se){if(f.status!=="open"||f.box&&k&&f.box!==k)continue;f.status="superseded";let v=n.indexOf(f);v>=0&&n.splice(v,1),Q.set(f,"superseded"),C.delete(f.offerId)}se.clear()},ve=new Map,Ye=new Map,Fe=new Map,Zt=new Map,ut=new Map,kn=new Map,Kr=new Map,at=new Map,Vr=()=>{for(let k of at.values())k.questions.length&&n.push(k);at.clear()},it=null,xt=new Map,Lt=6e4,Ot=new Map,Zi=(k,f)=>{let v=s.get(k);if(!v?.length)return!1;let O=Be(f),G=a.get(k);return v.some(ge=>{if(!O.startsWith(ge))return!1;let ye=Be(O.slice(ge.length));return!!ye&&!!G?.has(ye)})};for(let k of e||[]){let f=k.payload||{};switch(k.type){case"turn.user":{if(k.source==="hook"){k.boxId&&be.add(k.boxId);break}if(N(),!String(f.text||"").trim()&&!f.images?.length&&!f.attachments?.length)break;{let O=_S(f.text);if(O){if(O.kind==="shell-input"){let G={id:k.id,kind:"shell",command:O.command,stdout:null,stderr:null,done:!1,ts:me(k),box:k.boxId,agent:k.provider};n.push(G),xt.set(k.boxId,G)}else{let G=xt.get(k.boxId);G?(G.stdout=O.stdout||null,G.stderr=O.stderr||null,G.done=!0,xt.delete(k.boxId)):n.push({id:k.id,kind:"shell",command:null,stdout:O.stdout||null,stderr:O.stderr||null,done:!0,ts:me(k),box:k.boxId,agent:k.provider})}break}}{let O=f.note||Hc(f.text);if(O){if(O.kind==="task"){if(O.toolUseId&&i.has(O.toolUseId))break;let G=String(O.summary||"").match(y);if(!O.toolUseId&&G&&m.has(G[1]))break}if(O.kind==="command"&&TS(O.command))break;if(O.kind==="resume-summary"){n.push({id:k.id,kind:"resume-summary",title:O.title||"Context resumed from summary",bullets:O.bullets||[],sections:O.sections||[],rawChars:O.rawChars??null,ts:me(k),box:k.boxId,agent:k.provider});break}O.kind!=="suppress"&&n.push({id:k.id,kind:"event",type:IS(O),name:O.name??null,command:O.command??null,summary:O.summary??null,status:O.status??null,...O.kind==="cut-delivery"?{received:O.received??null,sent:O.sent??null,head:O.head??null}:{},ts:me(k),box:k.boxId,agent:k.provider});break}}if(o.has(`${k.boxId}|${me(k)}`)||k.source==="transcript"&&Zi(k.boxId,f.text))break;let v=f.text;if(k.source==="transcript"){let O=Ba(v);if(O!==v){if(a.get(k.boxId)?.has(Be(O)))break;v=O}let G=Dd(v,a.get(k.boxId)??[]);if(G){n.push({id:k.id,kind:"event",type:"delivery-cut",received:G.received,sent:G.sent,head:G.head,ts:me(k),box:k.boxId,agent:k.provider});break}}if(f.kind==="merge-notify"||f.kind==="ship-notify"){n.push({id:k.id,kind:"event",type:f.kind==="ship-notify"?"ship-notified":"merge-notified",text:f.text,ts:me(k),box:k.boxId,agent:k.provider});break}if(f.kind==="mock-picked"||f.kind==="ci-fix"||f.kind==="reconcile"||f.kind==="pr-go"||f.kind==="push-go"||f.kind==="spin-up-view"||f.kind==="prompt-answer"||f.kind==="followup-go"||f.kind==="login-greet"){f.kind==="prompt-answer"&&(it=null);break}for(let O of C.values())O.status="stale";C.clear();for(let O of K.values())O.status="stale";K.clear();for(let O of Y.values())O.rows.some(G=>G.rowStatus==="sent")||(O.status="stale",Y.delete(O.offerId));it&&it.box===k.boxId&&(n.push(xF(it)),it=null),n.push({id:k.id,kind:"message",role:"user",text:v,ts:me(k),box:k.boxId,agent:k.provider,boxRole:f.boxRole,...k.actor==="orchestrator"?{orchestration:f.kind||!0}:{},...f.sourceId?{sourceId:f.sourceId}:{},...f.attachments?.length?{attachments:f.attachments}:{},...f.images?.length?{images:f.images}:{}});break}case"peer.message":{let v=f.from||{};n.push({id:k.id,kind:"event",type:"peer-message",text:f.text,from:v.trackName||v.boxId||v.name||null,fromTrackId:v.trackId||null,ts:me(k),box:k.boxId,agent:k.provider});break}case"turn.agent":{if(f.model==="<synthetic>"&&/^No response requested\.$/.test(String(f.text||"").trim()))break;let v=mS(f,{codexFailedText:ws});if(v){n.push({id:k.id,kind:"event",type:"provider-error",cls:v.cls,status:v.status??void 0,text:v.text,provider:k.provider,legacy:!0,at:me(k),ts:me(k),box:k.boxId,agent:k.provider});break}Vr();let O=(f.images||[]).filter(ct=>!$(ct,me(k)));if(k.source==="hook"&&!String(f.text||"").trim()&&(rt(k),k.boxId&&be.delete(k.boxId)),!String(f.text||"").trim()&&!O.length)break;if(k.provider==="cursor"){let ct=`${k.boxId}|${f.text}`;if(r.has(ct))break;r.add(ct)}(!it||it.box===k.boxId)&&(it=null);let G=k.provider==="codex"?(f.tools||[]).filter(ct=>!Vm.has(ct)&&!Bc.has(ct)):f.tools||[],ge=f.text,ye=null,vt=lw(String(f.text||""));vt&&(ge=vt.text,ye={questions:vt.questions}),n.push({id:k.id,kind:"message",role:"assistant",text:ge,ts:me(k),box:k.boxId,agent:k.provider,boxRole:f.boxRole,...ye?{ask:ye}:{},...G.length?{tools:G}:{},...f.model?{model:f.model}:{},...f.sourceId?{sourceId:f.sourceId}:{},...O.length?{images:O}:{}}),nt(k),ye&&(it={id:k.id,groupId:uw(k.provider,f.sourceId||k.id,ye.questions),provider:k.provider,box:k.boxId,questions:ye.questions,ts:me(k)});break}case"job.started":{if(!f.id)break;let v=me(k),O=l.get(f.id);if(!O&&(f.kind||"agent")==="agent"&&f.name){let Mt=w.get(f.name);Mt&&Mt.ts>=v&&(O=Mt)}let G=O?null:c.get(f.id)||null,ge=O||G?null:p(k.boxId??null,v),ye={jobId:f.id,jobKind:f.kind||"agent",name:f.name||null,detail:f.detail||null,status:O?O.status==="killed"?"stopped":O.status&&O.status!=="completed"?"failed":"done":G?"stalled":ge!=null?"lost":"running",startedTs:v,finishedTs:O?.ts??G?.ts??ge??null,quietMs:G?.quietMs??null,summary:O?.summary??null,resultHead:O?.resultHead??null},vt=Ot.get(k.boxId),ct=vt?.jobs[vt.jobs.length-1]?.startedTs;if(vt&&ct!=null&&v-ct<=Lt)vt.jobs.push(ye);else{let Mt={id:k.id,kind:"job-dock",dockId:f.id,ts:v,box:k.boxId,agent:k.provider,jobs:[ye]};Ot.set(k.boxId,Mt),n.push(Mt)}break}case"handoff.done":n.push(yt(k,"lead-handoff"));break;case"subtask.delegated":n.push({...yt(k,"subtask-delegated"),to:k.boxId,toAgent:k.provider});break;case"subtask.merged":n.push(yt(k,"subtask-merged"));break;case"pr.state.changed":{if(!f.change)break;if(f.change==="opened"){for(let O of C.values())O.status="stale";C.clear();for(let O of K.values())O.status="stale";K.clear()}let v=yt(k,`pr-${f.change}`);if(v.box=k.boxId??null,pA.has(f.change)&&f.number!=null){let O=fA(P,L,f);if(P.size>=2){for(let ge of L.values())for(let ye of ge)ye.grouped=!0;v.groupPrs=[...P.values()];let G=[v];for(let ge of P.keys())L.set(ge,G)}else{let G=L.get(O)??[];G.push(v),L.set(O,G)}}else if(f.change==="merged"||f.change==="closed"||f.change==="lost"){let O=fw(f),G=T&&!T.complete||P.size>=2;if(P.has(O))P.delete(O),L.delete(O);else if(f.number!=null)for(let ge of[...P.keys()])ge.endsWith(`#${f.number}`)&&(P.delete(ge),L.delete(ge));if(G&&f.number!=null){(!T||T.complete)&&(T={id:k.id,kind:"event",type:"pr-group-settled",prs:[],remaining:[],complete:!1,at:me(k),ts:me(k),box:k.boxId,agent:k.provider},n.push(T)),T.prs.push({number:f.number,url:f.url??null,title:f.title??null,repo:f.repo??null,branch:f.branch??null,change:f.change,ts:me(k)}),T.remaining=[...P.values()],T.complete=P.size===0;break}}n.push(v);break}case"pr.offered":{if(!f.offerId)break;le(k.boxId);for(let O of C.values())O.status="stale";C.clear();for(let O of K.values())O.status="stale";K.clear();let v={id:k.id,kind:"pr-offer",offerId:f.offerId,excerpt:f.excerpt||null,branch:f.branch||null,base:f.base||null,offered:Array.isArray(f.offered)&&f.offered.length?f.offered:null,toPr:f.toPr&&typeof f.toPr=="object"?{number:f.toPr.number??null}:null,available:Array.isArray(f.available)?f.available:null,defaults:Array.isArray(f.defaults)?f.defaults:null,prState:f.prState||null,openPr:f.openPr&&typeof f.openPr=="object"?f.openPr:null,repos:Array.isArray(f.repos)&&f.repos.length?f.repos:null,status:"open",source:k.source==="cli"||f.via==="cli"?"cli":"transcript",ts:me(k),box:k.boxId,agent:k.provider};C.set(f.offerId,v),j.set(f.offerId,v),n.push(v),se.add(v),v.source==="cli"&&Ue(v);break}case"pr.offer.answered":{let v=j.get(f.offerId);v&&(v.status=f.action||"dismiss",v.actions=Array.isArray(f.actions)?f.actions:null,v.notify=f.notify===!0,f.existingPr&&typeof f.existingPr=="object"&&(v.existingPr={number:f.existingPr.number??null}),C.delete(f.offerId));break}case"pr.exists.offered":{if(!f.offerId)break;for(let O of K.values())O.status="stale";K.clear();let v={id:k.id,kind:"pr-exists-offer",offerId:f.offerId,srcOfferId:f.srcOfferId??null,branch:f.branch||null,base:f.base||null,pr:f.pr&&typeof f.pr=="object"?{number:f.pr.number??null,url:f.pr.url??null,title:f.pr.title??null}:null,actions:Array.isArray(f.actions)&&f.actions.length?f.actions:null,notify:f.notify===!0,status:"open",ts:me(k),box:k.boxId,agent:k.provider};K.set(f.offerId,v),M.set(f.offerId,v),n.push(v);break}case"pr.exists.answered":{let v=M.get(f.offerId);v&&(v.status=f.choice||"dismiss",K.delete(f.offerId));break}case"box.state.changed":{let v=f.change==="model"?"model-change":f.change;if(!v||v==="cli-update"&&f.status!=="failed")break;let O=yt(k,v);if(v==="model-change"&&(O.to=f.model),v==="node-update"&&O.latest){let G=n.findIndex(ge=>ge.kind==="event"&&ge.type==="node-update"&&ge.latest===O.latest);if(G>=0){let ge=n[G];n[G]={...O,ts:ge.ts,at:ge.at,firstAt:ge.firstAt??ge.ts,updatedAt:O.ts};break}}n.push(O);break}case"track.transferred":case"track.recovered":n.push(yt(k,"track-moved"));break;case"view.state.changed":{if(f.change==="deleted"){b(`view:${f.viewId}`);break}if(f.change!=="created"||f.restarted)break;g(`view:${f.viewId}`,{id:k.id,kind:"view-card",viewId:f.viewId,name:f.name,slug:f.slug,port:f.port,origin:f.origin,ts:me(k),box:k.boxId,agent:k.provider});break}case"view.spinup.failed":{n.push({id:k.id,kind:"view-spinup-failed",name:f.name||null,reason:f.reason||"no-view",ts:me(k),box:k.boxId,agent:k.provider});break}case"mock.state.changed":{if(f.change==="picked"){n.push({id:k.id,kind:"mock-picked",mockId:f.mockId,name:f.name,group:f.group??null,version:f.version??null,siblings:f.siblings??[],ts:me(k),box:k.boxId,agent:k.provider});break}if(f.change==="deleted"){b(`mock:${f.mockId}`);break}if(f.change!=="created")break;g(`mock:${f.mockId}`,{id:k.id,kind:"mock-card",mockId:f.mockId,name:f.name,group:f.group??null,ts:me(k),box:k.boxId,agent:k.provider});break}case"flow.state.changed":{if(f.change==="deleted"){b(`flow:${f.flowId}`);break}if(f.change!=="created")break;g(`flow:${f.flowId}`,{id:k.id,kind:"flow-card",flowId:f.flowId,name:f.name,stepCount:f.stepCount??null,mockIds:f.mockIds??[],ts:me(k),box:k.boxId,agent:k.provider});break}case"runbook.state.changed":{if(f.change==="deleted"){b(`runbook:${f.runbookId}`);break}if(f.change!=="created")break;g(`runbook:${f.runbookId}`,{id:k.id,kind:"runbook-card",runbookId:f.runbookId,name:f.name,ts:me(k),box:k.boxId,agent:k.provider});break}case"ticket.linked":{n.push({id:k.id,kind:"ticket-card",provider:f.provider||"linear",key:f.key,url:f.url,title:f.title??null,linkSource:f.linkSource??null,ts:me(k),box:k.boxId,agent:k.provider});break}case"box.fullscreen.detected":case"box.stuck.detected":{if(!f.offerId)break;for(let O of U.values())O.box===(f.box||k.boxId)&&(O.status="stale",U.delete(O.offerId));let v={id:k.id,kind:"fullscreen-offer",reason:k.type==="box.stuck.detected"?"stuck":"fullscreen",offerId:f.offerId,status:"open",ts:me(k),box:f.box||k.boxId,agent:f.agent||k.provider,...k.type==="box.stuck.detected"?{escSends:f.escSends??null,kept:f.kept??0}:{}};U.set(f.offerId,v),W.set(f.offerId,v),n.push(v);break}case"box.fullscreen.answered":case"box.stuck.answered":{let v=W.get(f.offerId);v&&(v.status=f.action==="restarted"?"restarted":f.action==="cleared"?"cleared":"dismiss",U.delete(f.offerId));break}case"ticket.move.offered":{if(!f.offerId)break;for(let O of I.values())O.key===f.key&&(O.status="stale",I.delete(O.offerId));let v={id:k.id,kind:"ticket-offer",offerId:f.offerId,provider:f.provider||"linear",key:f.key,url:f.url??null,phase:f.phase??null,from:f.from??null,to:f.to?.name??null,prNumber:f.prNumber??null,status:"open",ts:me(k),box:k.boxId,agent:k.provider};I.set(f.offerId,v),S.set(f.offerId,v),n.push(v);break}case"ticket.move.answered":{let v=S.get(f.offerId);v&&(v.status=f.action==="moved"?"moved":"dismiss",I.delete(f.offerId));break}case"ticket.state.changed":{for(let v of I.values())v.key===f.key&&v.to===f.to&&(v.status="stale",I.delete(v.offerId));if(f.mode==="offer")break;n.push(yt(k,"ticket-state"));break}case"ticket.commented":{n.push({id:k.id,kind:"ticket-comment",key:f.key,url:f.url??null,excerpt:f.excerpt??null,ts:me(k),box:k.boxId,agent:k.provider});break}case"ticket.flow.changed":n.push(yt(k,"ticket-flow"));break;case"ticket.create.offered":{if(!f.proposalId)break;for(let O of ie.values())O.status="stale";ie.clear();let v={id:k.id,kind:"ticket-create-offer",proposalId:f.proposalId,provider:f.provider||"linear",epic:f.epic??null,issues:Array.isArray(f.issues)?f.issues:[],team:f.team??null,needsTeam:!!f.needsTeam,linkCurrentTrack:!!f.linkCurrentTrack,status:"open",ts:me(k),box:k.boxId,agent:k.provider};ie.set(f.proposalId,v),z.set(f.proposalId,v),n.push(v),Ue(v);break}case"ticket.create.answered":{let v=z.get(f.proposalId);v&&(v.status=f.action==="created"?"created":"dismiss",v.createdCount=f.createdCount??null,v.failedCount=f.failedCount??null,ie.delete(f.proposalId));break}case"loop.create.offered":{if(!f.proposalId)break;for(let O of Ge.values())O.status="stale";Ge.clear();let v={id:k.id,kind:"loop-create-offer",proposalId:f.proposalId,name:f.name??"",schedule:f.schedule??"",prompt:f.prompt??"",expectation:f.expectation??null,notify:f.notify??"off",assignment:f.assignment??{provider:"claude"},repo:f.repo??null,nodeId:f.nodeId??null,nodeName:f.nodeName??null,status:"open",ts:me(k),box:k.boxId,agent:k.provider};Ge.set(f.proposalId,v),_e.set(f.proposalId,v),n.push(v),Ue(v);break}case"loop.create.answered":{let v=_e.get(f.proposalId);v&&(v.status=f.action==="created"?"created":"dismiss",Ge.delete(f.proposalId));break}case"followup.armed":{if(!f.armId)break;let v=f.replaces?Ie.get(f.replaces):null;v&&v.arm.status==="armed"&&ae(v,"replaced");let O={armId:f.armId,seq:Number.isInteger(f.seq)?f.seq:0,label:f.label??"",prompt:f.prompt??"",why:f.why??null,standing:f.standing==="never"?"never":"offerable",status:"armed"},G=f.groupId??null,ge=G?Pe.get(G):null;ge||(ge={id:k.id,kind:"followup-armed",groupId:G,armId:O.armId,trigger:f.trigger??"now",label:O.label,prompt:O.prompt,why:O.why,planWhy:f.planWhy??null,arms:[],status:"armed",ts:me(k),box:k.boxId,agent:k.provider},G&&Pe.set(G,ge),ge.trigger!=="now"&&n.push(ge)),ge.arms.push(O),Ie.set(f.armId,{arm:O,line:ge});break}case"followup.armed.cancelled":{let v=Ie.get(f.armId);v&&v.arm.status==="armed"&&ae(v,"cancelled");break}case"followup.offered":{if(!f.offerId)break;for(let G of Y.values())G.trigger===f.trigger&&(G.status="stale",Y.delete(G.offerId));let v=Array.isArray(f.rows)?f.rows:[];for(let G of v){let ge=G.armId?Ie.get(G.armId):null;ge&&ge.arm.status==="armed"&&ae(ge,"offered")}let O={id:k.id,kind:"followup-offer",offerId:f.offerId,trigger:f.trigger??"now",repo:f.repo??null,context:f.context&&typeof f.context=="object"?f.context:{},groupId:f.groupId??null,why:f.why??null,rows:v.map(G=>({followupId:G.followupId??null,armId:G.armId??null,label:G.label??"",prompt:G.prompt??null,promptPreview:G.promptPreview??null,promptHash:G.promptHash??null,origin:G.origin??"operator",why:G.why??null,groupId:G.groupId??null,seq:Number.isInteger(G.seq)?G.seq:0,standing:G.standing==="never"?"never":"offerable",promotable:G.armId?G.promotable!==!1:!1,promotableReason:G.promotableReason??null,rowStatus:"open",saved:null})),status:"open",answer:null,answers:[],ts:me(k),box:k.boxId,agent:k.provider};Y.set(f.offerId,O),ne.set(f.offerId,O),n.push(O),O.trigger==="now"&&Ue(O);break}case"followup.arm.saved":{let v=ne.get(f.offerId);if(!v)break;let O=v.rows.find(G=>G.armId&&G.armId===f.armId);O&&(O.saved=f.followupId??null);break}case"followup.answered":{let v=ne.get(f.offerId);if(!v)break;let O=new Set;f.armId&&O.add(`arm:${f.armId}`),f.followupId&&O.add(`fu:${f.followupId}`);for(let ye of Array.isArray(f.armIds)?f.armIds:[])O.add(`arm:${ye}`);for(let ye of Array.isArray(f.followupIds)?f.followupIds:[])O.add(`fu:${ye}`);let G=f.action==="sent"?"sent":f.action==="removed"?"removed":"dismiss";for(let ye of v.rows){if(ye.rowStatus!=="open")continue;let vt=ye.armId?`arm:${ye.armId}`:`fu:${ye.followupId}`;O.size&&!O.has(vt)||(ye.rowStatus=G)}let ge={followupId:f.followupId??null,armId:f.armId??null,label:f.label??null,promoted:f.promoted??null,revived:f.revived===!0,action:G,batchId:f.batchId??null,edited:f.edited===!0,order:Number.isInteger(f.order)?f.order:null,reordered:f.reordered===!0};v.answers.push(ge),v.answer=ge,v.rows.some(ye=>ye.rowStatus==="open")?v.status="open":(v.status=v.rows.some(ye=>ye.rowStatus==="sent")?"sent":v.rows.some(ye=>ye.rowStatus==="removed")?"removed":"dismiss",Y.delete(f.offerId));break}case"followup.create.offered":{if(!f.proposalId)break;for(let O of ve.values())O.status="stale";ve.clear();let v={id:k.id,kind:"followup-create-offer",proposalId:f.proposalId,label:f.label??"",prompt:f.prompt??"",trigger:f.trigger??"pr.merged",repo:f.repo??null,why:f.why??null,status:"open",created:null,ts:me(k),box:k.boxId,agent:k.provider};ve.set(f.proposalId,v),Ye.set(f.proposalId,v),n.push(v),Ue(v);break}case"followup.create.answered":{let v=Ye.get(f.proposalId);v&&(v.status=f.action==="created"?"created":"dismiss",ve.delete(f.proposalId));break}case"followup.created":{let v=f.proposalId?Ye.get(f.proposalId):null;v&&(v.created={followupId:f.followupId??null});break}case"loop.created":{let v=f.proposalId?_e.get(f.proposalId):null;v&&(v.created={loopId:f.loopId??null,nextFireAt:Number.isFinite(Number(f.nextFireAt))?Number(f.nextFireAt):null}),n.push(yt(k,"loop-created"));break}case"loop.update.offered":case"loop.delete.offered":{if(!f.proposalId||!f.loopId)break;for(let G of Fe.values())G.loopId===f.loopId&&(G.status="stale",G.staleReason="superseded",Fe.delete(G.proposalId));let v=k.type==="loop.update.offered",O={id:k.id,kind:v?"loop-update-offer":"loop-delete-offer",proposalId:f.proposalId,loopId:String(f.loopId),name:f.name??f.base?.name??"",base:f.base??null,...v?{patch:f.patch??{},changed:Array.isArray(f.changed)?f.changed:Object.keys(f.patch||{})}:{reason:f.reason??""},selfEdit:!!f.selfEdit,status:"open",staleReason:null,ts:me(k),box:k.boxId,agent:k.provider};Fe.set(f.proposalId,O),Zt.set(f.proposalId,O),n.push(O),Ue(O);break}case"loop.update.answered":{let v=Zt.get(f.proposalId);v&&(f.action==="moved"?(v.status="stale",v.staleReason="moved"):v.status=f.action==="applied"?"applied":"dismiss",Fe.delete(f.proposalId));break}case"loop.delete.answered":{let v=Zt.get(f.proposalId);v&&(f.action==="moved"?(v.status="stale",v.staleReason="moved"):v.status=f.action==="delete"?"deleted":f.action==="pause"?"paused":"keep",Fe.delete(f.proposalId));break}case"loop.updated":{let v=f.proposalId?Zt.get(f.proposalId):null;v&&(v.applied={changed:Array.isArray(f.changed)?f.changed:[],nextFireAt:Number.isFinite(Number(f.nextFireAt))?Number(f.nextFireAt):null}),n.push(yt(k,"loop-updated"));break}case"loop.deleted":n.push(yt(k,"loop-deleted"));break;case"loop.paused":n.push(yt(k,"loop-paused"));break;case"planning.change.offered":{if(!f.proposalId||!Array.isArray(f.ops)||!f.ops.length)break;for(let O of ut.values())O.status="stale",O.staleReason="superseded",ut.delete(O.proposalId);let v={id:k.id,kind:"planning-offer",proposalId:f.proposalId,why:f.why??"",ops:f.ops,base:f.base??{},resolved:f.resolved??{},snapped:!!f.snapped,createsMeRow:!!f.createsMeRow,status:"open",staleReason:null,applied:null,ts:me(k),box:k.boxId,agent:k.provider};ut.set(f.proposalId,v),kn.set(f.proposalId,v),n.push(v),Ue(v);break}case"planning.change.answered":{let v=kn.get(f.proposalId);v&&(f.action==="moved"?(v.status="stale",v.staleReason="moved"):v.status=f.action==="applied"?"applied":"dismiss",ut.delete(f.proposalId));break}case"planning.changed":{let v=f.proposalId?kn.get(f.proposalId):null;v&&(v.applied={results:Array.isArray(f.results)?f.results:[]}),n.push(yt(k,"planning-changed"));break}case"rework.cause.offered":{if(!f.sha||Kr.has(f.sha))break;let v={id:k.id,kind:"rework-cause-offer",sha:f.sha,subject:f.subject??"",linesReworked:Number(f.linesReworked)||0,origins:Array.isArray(f.origins)?f.origins:[],heuristic:f.heuristic??null,intent:f.intent??null,shas:Array.isArray(f.shas)?f.shas:null,pr:f.pr??null,retracts:0,status:"open",cause:null,ts:me(k),box:k.boxId,agent:k.provider};Kr.set(f.sha,v),n.push(v);break}case"rework.cause.answered":{let v=f.sha?Kr.get(f.sha):null;v&&(v.status="answered",v.cause=f.cause??null);break}case"rework.cause.retracted":{let v=f.sha?Kr.get(f.sha):null;v&&(v.status="open",v.cause=null,v.retracts=(v.retracts??0)+1);break}case"ticket.created":{let v={items:Array.isArray(f.items)?f.items:[],failed:Array.isArray(f.failed)?f.failed:[],team:f.team??null},O=f.proposalId?z.get(f.proposalId):null;if(O){O.created=v;break}n.push({id:k.id,kind:"ticket-created",...v,ts:me(k),box:k.boxId,agent:k.provider});break}case"error":{if(!f.kind)break;n.push(yt(k,f.kind));break}case"turn.aborted":{(f.cause==="cli-exited"||f.cause==="session-gone")&&n.push(yt(k,"turn-aborted"));break}case"provider.error":n.push({...yt(k,"provider-error"),provider:k.provider,box:k.boxId,agent:k.provider});break;case"usage.cap.hit":n.push(yt(k,"usage-cap-hit"));break;case"usage.cap.warning":n.push(yt(k,"usage-cap-warning"));break;case"provider.connected":{n.push({id:k.id,kind:"event",type:"provider-connected",provider:f.provider||k.provider,account:f.account||null,reason:f.reason||null,ts:me(k),at:me(k),box:k.boxId,agent:k.provider});break}case"provider.login.started":break;case"prompt.answered":{if(it=null,f.control||!f.question)break;let v=f.groupId||f.promptId;if(!v)break;let O=at.get(v);O||(O={id:k.id,kind:"prompt",groupId:v,provider:k.provider,box:k.boxId,agent:k.provider,questionTotal:f.questionTotal??1,questions:[],ts:me(k)},at.set(v,O));let G=f.questionIndex??0,ge={index:G,header:f.header||"",question:f.question,multiSelect:!!f.multiSelect,chosen:Array.isArray(f.chosen)?f.chosen:[]},ye=O.questions.findIndex(ct=>ct.index===G&&Be(ct.question)===Be(ge.question));ye>=0?O.questions[ye]=ge:O.questions.push(ge),O.questions.sort((ct,zr)=>ct.index-zr.index),O.questionTotal=Math.max(O.questionTotal,f.questionTotal??1),O.questions.length>=O.questionTotal&&(n.push(O),at.delete(v));break}case"prompt.dismissed":{it=null;let v=f.groupId||f.promptId;if(!v||!f.question)break;let G=at.get(v)||{id:k.id,kind:"prompt",groupId:v,provider:k.provider,box:k.boxId,agent:k.provider,questionTotal:f.questionTotal??1,questions:[],ts:me(k)},ge=f.questionIndex??0;G.questions.some(ye=>ye.index===ge&&Be(ye.question)===Be(f.question))||(G.questions.push({index:ge,header:f.header||"",question:f.question,multiSelect:!!f.multiSelect,chosen:[]}),G.questions.sort((ye,vt)=>ye.index-vt.index)),G.answeredVia="chat",n.push(G),at.delete(v);break}default:break}}for(let[k,f]of[...Q]){if(f==="superseded"){k.status!=="superseded"&&he(k,null);continue}(k.status!=="open"||t-(k.ts??0)>=vF)&&he(k,null)}let ns=h.size?n.filter(k=>!k.retired):n;return AF(ns.sort((k,f)=>(k.ts??0)-(f.ts??0)))}function AF(e){let t=new Map,n=[];for(let r of e){if(r.kind!=="message"||!r.box){n.push(r);continue}let o=r.role==="assistant"&&!String(r.text||"").trim()&&r.images?.length,s=t.get(r.box);if(o&&s&&(r.ts??0)-s.lastTs<=SF){s.item.images.push(...r.images),s.lastTs=r.ts??s.lastTs;continue}if(o){let a={...r,images:[...r.images]};t.set(r.box,{item:a,lastTs:r.ts??0}),n.push(a)}else t.delete(r.box),n.push(r)}return n}function hw(e,t=null){let n=[];for(let o of e||[]){if(o.type!=="tool.called"||o.source!=="transcript")continue;let s=o.payload||{};String(s.command||"").trim()&&n.push({id:s.id??null,tool:s.tool||null,command:s.command,description:s.description||"",summary:TF(s),ts:s.ts??o.ts,n:s.n,box:o.boxId,agent:o.provider,boxRole:s.boxRole})}if(!n.length)return[];let r=(t??Gn(e)).filter(o=>o.kind==="message");return iS(n,r)}function TF(e){let t=String(e.summary||"").trim();return t&&t!==e.command&&t!==Ca(e.command)?t:ao(e.command,e.description||"")}function yt(e,t){let{ts:n,change:r,kind:o,...s}=e.payload||{};return{id:e.id,kind:"event",type:t,...s,at:me(e),ts:me(e)}}function hA(e){let t=[...e];for(let n=0;n<t.length;n++){let r=t[n];if(r?.kind!=="event"||r.type!=="archived")continue;let o=(r.ts??0)+EF,s=n;for(;s+1<t.length;){let a=t[s+1];if((a?.ts??0)>o||a?.kind==="event"&&_F.has(a.type))break;s++}s>n&&t.splice(s,0,...t.splice(n,1)),n=s}return t}function mA(e){let t=[...e];for(let n=0;n<t.length;n++){let r=t[n];if(r?.kind!=="event"||!$F.has(r.type)||!r.box)continue;let o=(r.ts??0)+IF,s=n;for(;s+1<t.length;){let a=t[s+1];if((a?.ts??0)>o||!(a?.kind==="message"&&a.role==="assistant"&&a.box===r.box||a?.kind==="command-batch"&&a.anchorBox===r.box))break;s++}s>n&&t.splice(s,0,...t.splice(n,1)),n=s}return t}function Jd(e){return(e||[]).filter(t=>RF.has(t?.kind)&&t.status==="open")}function wA(e){let t=new Map,n=new Map;for(let r of e||[]){if(r.type!=="pr.state.changed")continue;let o=r.payload||{};if(pA.has(o.change)&&o.number!=null)fA(t,n,o);else if(o.change==="merged"||o.change==="closed"||o.change==="lost"){let s=fw(o);if(t.has(s))t.delete(s);else if(o.number!=null)for(let a of[...t.keys()])a.endsWith(`#${o.number}`)&&t.delete(a)}}return[...t.values()]}var me,pA,fw,vF,SF,EF,_F,IF,$F,RF,Yd=V(()=>{Na();gs();Od();Da();La();pw();me=e=>e.payload?.ts??e.ts;pA=new Set(["opened","ci-fixed","reconciled","pushed"]),fw=e=>`${e.repo??""}#${e.number}`;vF=3e4;SF=2*6e4;EF=12e4,_F=new Set(["archived","unarchived","opened"]);IF=2500,$F=new Set(["pr-opened","pr-merged","pr-auto-armed"]);RF=new Set(["pr-offer","pr-exists-offer","ticket-offer","ticket-create-offer","loop-create-offer","loop-update-offer","loop-delete-offer","planning-offer","fullscreen-offer","followup-create-offer"])});function PF(e){let t=null,n=null,r=null;for(let o of e??[]){let s=o?.ts??null;s&&(r=Math.max(r??0,s)),o?.type==="handoff.artifact"&&(t={ts:o.payload?.ts??s,truncated:!!o.payload?.truncated,...o.payload?.reconstructed?{reconstructed:!0}:{}}),o?.type==="code.pushed"&&(n={ts:o.payload?.ts??s,sha:o.payload?.sha??null,ref:o.payload?.ref??null,wip:!!o.payload?.wip})}return{lastArtifact:t,lastPush:n,lastEventAt:r}}function BF(e){for(let t=(e?.length??0)-1;t>=0;t--){let n=e[t];if(n?.type==="handoff.artifact"&&!n.payload?.reconstructed)return n}return null}function LF(e,t){let n=[],r=[],o=new Set,s=new Set;for(let a=(e?.length??0)-1;a>=0;a--){let i=e[a];if(i?.type!=="tool.called")continue;if(t!=null&&(i.ts??0)<=t)break;let c=i.payload||{};c.path&&!o.has(c.path)&&n.length<CF&&(o.add(c.path),n.push(c.path)),c.head&&!s.has(c.head)&&r.length<NF&&(s.add(c.head),r.push(c.head))}return{files:n,heads:r}}function kA(e,{trackName:t="this Track",now:n=null,mode:r="failover"}={}){let o=PF(e),s=BF(e),a=s?.payload?.content??null,i=s?s.payload?.ts??s.ts??null:null,c=Gn(e??[]).filter(p=>p?.kind==="message"&&typeof p.text=="string"&&p.text.trim()).slice(-OF);if(!a&&!c.length)return null;let l=[];if(l.push(`# Reconstructed resume brief \u2014 ${t}`),l.push(""),l.push(bA[r]??bA.failover),l.push(""),o.lastPush?.sha){let p=yA(n,o.lastPush.ts),m=p?` (~${p} min before the loss)`:"";l.push(`**Code state:** last pushed ref \`${o.lastPush.ref}\` @ \`${o.lastPush.sha.slice(0,12)}\`${m}`+(o.lastPush.wip?" \u2014 a bostrat WIP snapshot (full working tree incl. uncommitted edits at push time).":"."))}else r==="in-place"?l.push("**Code state:** no push recorded \u2014 the working tree in this workspace is the only copy; commit early."):l.push("**Code state:** no push was ever recorded for this Track \u2014 work since the branch's last known state stayed on the offline node.");if(l.push(""),a){let p=yA(n,i);l.push(`## Last real checkpoint (written by the previous agent${p?`, ~${p} min before this reconstruction`:""})`),l.push(""),l.push(a.trim()),l.push("")}let u=LF(e??[],i);if((u.files.length||u.heads.length)&&(l.push(`## Work since ${a?"that checkpoint":"the start of the log"} (from the event log)`),l.push(""),u.files.length&&l.push(`Files touched (most recent first): ${u.files.map(p=>`\`${p}\``).join(", ")}`),u.heads.length&&(u.files.length&&l.push(""),l.push(`Commands run (most recent first): ${u.heads.map(p=>`\`${p}\``).join(" \xB7 ")}`)),l.push("")),c.length){l.push(`## Recent conversation (last ${c.length} message${c.length===1?"":"s"})`),l.push("");for(let p of c)l.push(`**${p.role==="user"?"operator":"agent"}:** ${DF(p.text,MF)}`),l.push("")}l.push("---"),l.push("Resume: continue the objective above from the verified repository state; ask the operator before redoing anything the log says was already done.");let d=l.join(`
160
+ `});function xF(e){return{id:e.id,kind:"prompt",groupId:e.groupId,provider:e.provider,box:e.box,agent:e.provider,questionTotal:e.questions.length,answeredVia:"chat",questions:e.questions.map((t,n)=>({index:n,header:t.header||"",question:t.question,multiSelect:!!t.multiSelect,chosen:[]})),ts:e.ts}}function fA(e,t,n){let r=fw(n),o=e.has(r)?r:null;if(!o&&n.number!=null)for(let[i,c]of e){if(Number(c.number)!==Number(n.number))continue;let l=!!(n.url&&c.url&&n.url===c.url),u=!c.repo&&!!n.repo||!!c.repo&&!n.repo;if(l||u&&(!c.url||!n.url||c.url===n.url)){o=i;break}}let s=n.repo||!o?r:o,a=o?e.get(o):e.get(s);if(o&&o!==s){e.delete(o);let i=t.get(o);if(t.delete(o),i?.length){let c=t.get(s)??[];t.set(s,c.concat(i))}}return e.set(s,{number:n.number,url:n.url??a?.url??null,title:n.title??a?.title??null,repo:n.repo??a?.repo??null,branch:n.branch??a?.branch??null}),s}function Gn(e,{now:t=Date.now()}={}){let n=[],r=new Set,o=new Set,s=new Map,a=new Map,i=new Set,c=new Map,l=new Map,u=new Map,d=(k,f)=>{f!=null&&(u.has(k)||u.set(k,[]),u.get(k).push(f))},p=(k,f)=>{let v=null;for(let O of[k,null])for(let G of u.get(O)||[])G>f&&(v==null||G<v)&&(v=G);return v},m=new Set,w=new Map,h=new Map,g=(k,f)=>{h.set(k,f),n.push(f)},b=k=>{let f=h.get(k);f&&(f.retired=!0)},y=/^Agent "([\s\S]+)" finished$/,x=new Map;for(let k of e||[]){if(k.type!=="tool.called"||k.source!=="transcript")continue;let f=String(k.payload?.command||"");if(/\bbostrat-mock\s+(?:add|update)\b/.test(f))for(let v of f.matchAll(/[\w./~-]+\.(?:png|jpe?g|gif|webp|bmp|svg)\b/gi)){let O=v[0].split("/").pop().toLowerCase();x.has(O)||x.set(O,[]),x.get(O).push(k.payload?.ts??k.ts)}}let E=3*6e4,A=20*6e4,$=(k,f)=>!!(k?.name&&x.get(String(k.name).toLowerCase()))?.some(O=>O>=f-E&&O<=f+A);for(let k of e||[])if(k.type==="turn.retracted"){o.add(`${k.boxId}|${k.payload?.saidTs}`);let f=Be(k.payload?.text);f&&(s.has(k.boxId)||s.set(k.boxId,[]),s.get(k.boxId).push(f))}else if(k.type==="turn.user"&&k.source==="orchestrator"){let f=Be(k.payload?.text);f&&(a.has(k.boxId)||a.set(k.boxId,new Set),a.get(k.boxId).add(f))}else if(k.type==="job.stalled"&&k.payload?.id)c.set(k.payload.id,{ts:he(k),quietMs:Number(k.payload.quietMs)||null});else if(k.type==="job.stopped"&&k.payload?.id)l.has(k.payload.id)||l.set(k.payload.id,{status:"killed",summary:null,resultHead:null,ts:he(k)});else if(k.type==="session.ready"){let f=k.payload?.source;f!=="compact"&&f!=="clear"&&d(k.boxId??null,he(k))}else if(k.type==="handoff.done")d(k.boxId??k.payload?.from??null,he(k));else if(k.type==="box.state.changed"&&k.payload?.change==="archived")d(null,he(k));else if(k.type==="job.started"&&k.payload?.id)i.add(k.payload.id),(k.payload.kind||"agent")==="agent"&&k.payload.name&&m.add(k.payload.name);else if(k.type==="turn.user"&&k.payload?.note?.kind==="task"){let f=k.payload.note,v={status:f.status||null,summary:f.summary||null,resultHead:f.resultHead??null,ts:he(k)};f.toolUseId&&l.set(f.toolUseId,v);let O=String(f.summary||"").match(y);O&&w.set(O[1],v)}let P=new Map,L=new Map,T=null,C=new Map,j=new Map,K=new Map,M=new Map,I=new Map,S=new Map,U=new Map,W=new Map,ie=new Map,z=new Map,Ge=new Map,_e=new Map,Y=new Map,ne=new Map,Ie=new Map,Pe=new Map,ae=(k,f)=>{k.arm.status=f;let v=k.line,O=v.arms.map(G=>G.status);v.status=O.includes("armed")?"armed":O.includes("offered")?"offered":O.includes("replaced")?"replaced":"cancelled"},Ae=[],be=new Set,Q=new Map,me=(k,f)=>{Q.delete(k);let v=n.indexOf(k);v>=0&&n.splice(v,1),f!=null&&(k.ts=f),n.push(k)},Ue=k=>{if(Ae.push(k),!(k.box?be.has(k.box):be.size>0))return;let v=n.indexOf(k);v>=0&&n.splice(v,1),Q.set(k,"held")},nt=k=>{if(!Ae.length)return;let f=he(k);for(let v of Ae)v.status!=="open"||Q.get(v)==="superseded"||v.box&&v.box!==k.boxId||(v.ts??0)>f||me(v,f)},rt=k=>{if(!Ae.length)return;let f=he(k);for(let v of Ae)Q.get(v)!=="held"||v.status!=="open"||v.box&&k.boxId&&v.box!==k.boxId||me(v,Math.max(v.ts??0,f))},N=()=>{for(let[k,f]of[...Q])f==="held"&&me(k,null);Ae.length=0,se.clear()},se=new Set,le=k=>{for(let f of se){if(f.status!=="open"||f.box&&k&&f.box!==k)continue;f.status="superseded";let v=n.indexOf(f);v>=0&&n.splice(v,1),Q.set(f,"superseded"),C.delete(f.offerId)}se.clear()},ve=new Map,Ye=new Map,Fe=new Map,Zt=new Map,ut=new Map,kn=new Map,Kr=new Map,at=new Map,Vr=()=>{for(let k of at.values())k.questions.length&&n.push(k);at.clear()},it=null,xt=new Map,Lt=6e4,Ot=new Map,Zi=(k,f)=>{let v=s.get(k);if(!v?.length)return!1;let O=Be(f),G=a.get(k);return v.some(ge=>{if(!O.startsWith(ge))return!1;let ye=Be(O.slice(ge.length));return!!ye&&!!G?.has(ye)})};for(let k of e||[]){let f=k.payload||{};switch(k.type){case"turn.user":{if(k.source==="hook"){k.boxId&&be.add(k.boxId);break}if(N(),!String(f.text||"").trim()&&!f.images?.length&&!f.attachments?.length)break;{let O=_S(f.text);if(O){if(O.kind==="shell-input"){let G={id:k.id,kind:"shell",command:O.command,stdout:null,stderr:null,done:!1,ts:he(k),box:k.boxId,agent:k.provider};n.push(G),xt.set(k.boxId,G)}else{let G=xt.get(k.boxId);G?(G.stdout=O.stdout||null,G.stderr=O.stderr||null,G.done=!0,xt.delete(k.boxId)):n.push({id:k.id,kind:"shell",command:null,stdout:O.stdout||null,stderr:O.stderr||null,done:!0,ts:he(k),box:k.boxId,agent:k.provider})}break}}{let O=f.note||Hc(f.text);if(O){if(O.kind==="task"){if(O.toolUseId&&i.has(O.toolUseId))break;let G=String(O.summary||"").match(y);if(!O.toolUseId&&G&&m.has(G[1]))break}if(O.kind==="command"&&TS(O.command))break;if(O.kind==="resume-summary"){n.push({id:k.id,kind:"resume-summary",title:O.title||"Context resumed from summary",bullets:O.bullets||[],sections:O.sections||[],rawChars:O.rawChars??null,ts:he(k),box:k.boxId,agent:k.provider});break}O.kind!=="suppress"&&n.push({id:k.id,kind:"event",type:IS(O),name:O.name??null,command:O.command??null,summary:O.summary??null,status:O.status??null,...O.kind==="cut-delivery"?{received:O.received??null,sent:O.sent??null,head:O.head??null}:{},ts:he(k),box:k.boxId,agent:k.provider});break}}if(o.has(`${k.boxId}|${he(k)}`)||k.source==="transcript"&&Zi(k.boxId,f.text))break;let v=f.text;if(k.source==="transcript"){let O=Ba(v);if(O!==v){if(a.get(k.boxId)?.has(Be(O)))break;v=O}let G=Dd(v,a.get(k.boxId)??[]);if(G){n.push({id:k.id,kind:"event",type:"delivery-cut",received:G.received,sent:G.sent,head:G.head,ts:he(k),box:k.boxId,agent:k.provider});break}}if(f.kind==="merge-notify"||f.kind==="ship-notify"){n.push({id:k.id,kind:"event",type:f.kind==="ship-notify"?"ship-notified":"merge-notified",text:f.text,ts:he(k),box:k.boxId,agent:k.provider});break}if(f.kind==="subtask-resume"){n.push({id:k.id,kind:"event",type:"subtask-finished",text:f.text,...f.detail&&typeof f.detail=="object"?f.detail:{},ts:he(k),box:k.boxId,agent:k.provider});break}if(f.kind==="mock-picked"||f.kind==="ci-fix"||f.kind==="reconcile"||f.kind==="pr-go"||f.kind==="push-go"||f.kind==="spin-up-view"||f.kind==="prompt-answer"||f.kind==="followup-go"||f.kind==="login-greet"){f.kind==="prompt-answer"&&(it=null);break}for(let O of C.values())O.status="stale";C.clear();for(let O of K.values())O.status="stale";K.clear();for(let O of Y.values())O.rows.some(G=>G.rowStatus==="sent")||(O.status="stale",Y.delete(O.offerId));it&&it.box===k.boxId&&(n.push(xF(it)),it=null),n.push({id:k.id,kind:"message",role:"user",text:v,ts:he(k),box:k.boxId,agent:k.provider,boxRole:f.boxRole,...k.actor==="orchestrator"?{orchestration:f.kind||!0}:{},...f.sourceId?{sourceId:f.sourceId}:{},...f.attachments?.length?{attachments:f.attachments}:{},...f.images?.length?{images:f.images}:{}});break}case"peer.message":{let v=f.from||{};n.push({id:k.id,kind:"event",type:"peer-message",text:f.text,from:v.trackName||v.boxId||v.name||null,fromTrackId:v.trackId||null,ts:he(k),box:k.boxId,agent:k.provider});break}case"turn.agent":{if(f.model==="<synthetic>"&&/^No response requested\.$/.test(String(f.text||"").trim()))break;let v=mS(f,{codexFailedText:ws});if(v){n.push({id:k.id,kind:"event",type:"provider-error",cls:v.cls,status:v.status??void 0,text:v.text,provider:k.provider,legacy:!0,at:he(k),ts:he(k),box:k.boxId,agent:k.provider});break}Vr();let O=(f.images||[]).filter(ct=>!$(ct,he(k)));if(k.source==="hook"&&!String(f.text||"").trim()&&(rt(k),k.boxId&&be.delete(k.boxId)),!String(f.text||"").trim()&&!O.length)break;if(k.provider==="cursor"){let ct=`${k.boxId}|${f.text}`;if(r.has(ct))break;r.add(ct)}(!it||it.box===k.boxId)&&(it=null);let G=k.provider==="codex"?(f.tools||[]).filter(ct=>!Vm.has(ct)&&!Bc.has(ct)):f.tools||[],ge=f.text,ye=null,vt=lw(String(f.text||""));vt&&(ge=vt.text,ye={questions:vt.questions}),n.push({id:k.id,kind:"message",role:"assistant",text:ge,ts:he(k),box:k.boxId,agent:k.provider,boxRole:f.boxRole,...ye?{ask:ye}:{},...G.length?{tools:G}:{},...f.model?{model:f.model}:{},...f.sourceId?{sourceId:f.sourceId}:{},...O.length?{images:O}:{}}),nt(k),ye&&(it={id:k.id,groupId:uw(k.provider,f.sourceId||k.id,ye.questions),provider:k.provider,box:k.boxId,questions:ye.questions,ts:he(k)});break}case"job.started":{if(!f.id)break;let v=he(k),O=l.get(f.id);if(!O&&(f.kind||"agent")==="agent"&&f.name){let Mt=w.get(f.name);Mt&&Mt.ts>=v&&(O=Mt)}let G=O?null:c.get(f.id)||null,ge=O||G?null:p(k.boxId??null,v),ye={jobId:f.id,jobKind:f.kind||"agent",name:f.name||null,detail:f.detail||null,status:O?O.status==="killed"?"stopped":O.status&&O.status!=="completed"?"failed":"done":G?"stalled":ge!=null?"lost":"running",startedTs:v,finishedTs:O?.ts??G?.ts??ge??null,quietMs:G?.quietMs??null,summary:O?.summary??null,resultHead:O?.resultHead??null},vt=Ot.get(k.boxId),ct=vt?.jobs[vt.jobs.length-1]?.startedTs;if(vt&&ct!=null&&v-ct<=Lt)vt.jobs.push(ye);else{let Mt={id:k.id,kind:"job-dock",dockId:f.id,ts:v,box:k.boxId,agent:k.provider,jobs:[ye]};Ot.set(k.boxId,Mt),n.push(Mt)}break}case"handoff.done":n.push(yt(k,"lead-handoff"));break;case"subtask.delegated":n.push({...yt(k,"subtask-delegated"),to:k.boxId,toAgent:k.provider});break;case"subtask.merged":n.push(yt(k,"subtask-merged"));break;case"pr.state.changed":{if(!f.change)break;if(f.change==="opened"){for(let O of C.values())O.status="stale";C.clear();for(let O of K.values())O.status="stale";K.clear()}let v=yt(k,`pr-${f.change}`);if(v.box=k.boxId??null,pA.has(f.change)&&f.number!=null){let O=fA(P,L,f);if(P.size>=2){for(let ge of L.values())for(let ye of ge)ye.grouped=!0;v.groupPrs=[...P.values()];let G=[v];for(let ge of P.keys())L.set(ge,G)}else{let G=L.get(O)??[];G.push(v),L.set(O,G)}}else if(f.change==="merged"||f.change==="closed"||f.change==="lost"){let O=fw(f),G=T&&!T.complete||P.size>=2;if(P.has(O))P.delete(O),L.delete(O);else if(f.number!=null)for(let ge of[...P.keys()])ge.endsWith(`#${f.number}`)&&(P.delete(ge),L.delete(ge));if(G&&f.number!=null){(!T||T.complete)&&(T={id:k.id,kind:"event",type:"pr-group-settled",prs:[],remaining:[],complete:!1,at:he(k),ts:he(k),box:k.boxId,agent:k.provider},n.push(T)),T.prs.push({number:f.number,url:f.url??null,title:f.title??null,repo:f.repo??null,branch:f.branch??null,change:f.change,ts:he(k)}),T.remaining=[...P.values()],T.complete=P.size===0;break}}n.push(v);break}case"pr.offered":{if(!f.offerId)break;le(k.boxId);for(let O of C.values())O.status="stale";C.clear();for(let O of K.values())O.status="stale";K.clear();let v={id:k.id,kind:"pr-offer",offerId:f.offerId,excerpt:f.excerpt||null,branch:f.branch||null,base:f.base||null,offered:Array.isArray(f.offered)&&f.offered.length?f.offered:null,toPr:f.toPr&&typeof f.toPr=="object"?{number:f.toPr.number??null}:null,available:Array.isArray(f.available)?f.available:null,defaults:Array.isArray(f.defaults)?f.defaults:null,prState:f.prState||null,openPr:f.openPr&&typeof f.openPr=="object"?f.openPr:null,repos:Array.isArray(f.repos)&&f.repos.length?f.repos:null,status:"open",source:k.source==="cli"||f.via==="cli"?"cli":"transcript",ts:he(k),box:k.boxId,agent:k.provider};C.set(f.offerId,v),j.set(f.offerId,v),n.push(v),se.add(v),v.source==="cli"&&Ue(v);break}case"pr.offer.answered":{let v=j.get(f.offerId);v&&(v.status=f.action||"dismiss",v.actions=Array.isArray(f.actions)?f.actions:null,v.notify=f.notify===!0,f.existingPr&&typeof f.existingPr=="object"&&(v.existingPr={number:f.existingPr.number??null}),C.delete(f.offerId));break}case"pr.exists.offered":{if(!f.offerId)break;for(let O of K.values())O.status="stale";K.clear();let v={id:k.id,kind:"pr-exists-offer",offerId:f.offerId,srcOfferId:f.srcOfferId??null,branch:f.branch||null,base:f.base||null,pr:f.pr&&typeof f.pr=="object"?{number:f.pr.number??null,url:f.pr.url??null,title:f.pr.title??null}:null,actions:Array.isArray(f.actions)&&f.actions.length?f.actions:null,notify:f.notify===!0,status:"open",ts:he(k),box:k.boxId,agent:k.provider};K.set(f.offerId,v),M.set(f.offerId,v),n.push(v);break}case"pr.exists.answered":{let v=M.get(f.offerId);v&&(v.status=f.choice||"dismiss",K.delete(f.offerId));break}case"box.state.changed":{let v=f.change==="model"?"model-change":f.change;if(!v||v==="cli-update"&&f.status!=="failed")break;let O=yt(k,v);if(v==="model-change"&&(O.to=f.model),v==="node-update"&&O.latest){let G=n.findIndex(ge=>ge.kind==="event"&&ge.type==="node-update"&&ge.latest===O.latest);if(G>=0){let ge=n[G];n[G]={...O,ts:ge.ts,at:ge.at,firstAt:ge.firstAt??ge.ts,updatedAt:O.ts};break}}n.push(O);break}case"track.transferred":case"track.recovered":n.push(yt(k,"track-moved"));break;case"view.state.changed":{if(f.change==="deleted"){b(`view:${f.viewId}`);break}if(f.change!=="created"||f.restarted)break;g(`view:${f.viewId}`,{id:k.id,kind:"view-card",viewId:f.viewId,name:f.name,slug:f.slug,port:f.port,origin:f.origin,ts:he(k),box:k.boxId,agent:k.provider});break}case"view.spinup.failed":{n.push({id:k.id,kind:"view-spinup-failed",name:f.name||null,reason:f.reason||"no-view",ts:he(k),box:k.boxId,agent:k.provider});break}case"mock.state.changed":{if(f.change==="picked"){n.push({id:k.id,kind:"mock-picked",mockId:f.mockId,name:f.name,group:f.group??null,version:f.version??null,siblings:f.siblings??[],ts:he(k),box:k.boxId,agent:k.provider});break}if(f.change==="deleted"){b(`mock:${f.mockId}`);break}if(f.change!=="created")break;g(`mock:${f.mockId}`,{id:k.id,kind:"mock-card",mockId:f.mockId,name:f.name,group:f.group??null,ts:he(k),box:k.boxId,agent:k.provider});break}case"flow.state.changed":{if(f.change==="deleted"){b(`flow:${f.flowId}`);break}if(f.change!=="created")break;g(`flow:${f.flowId}`,{id:k.id,kind:"flow-card",flowId:f.flowId,name:f.name,stepCount:f.stepCount??null,mockIds:f.mockIds??[],ts:he(k),box:k.boxId,agent:k.provider});break}case"runbook.state.changed":{if(f.change==="deleted"){b(`runbook:${f.runbookId}`);break}if(f.change!=="created")break;g(`runbook:${f.runbookId}`,{id:k.id,kind:"runbook-card",runbookId:f.runbookId,name:f.name,ts:he(k),box:k.boxId,agent:k.provider});break}case"ticket.linked":{n.push({id:k.id,kind:"ticket-card",provider:f.provider||"linear",key:f.key,url:f.url,title:f.title??null,linkSource:f.linkSource??null,ts:he(k),box:k.boxId,agent:k.provider});break}case"box.fullscreen.detected":case"box.stuck.detected":{if(!f.offerId)break;for(let O of U.values())O.box===(f.box||k.boxId)&&(O.status="stale",U.delete(O.offerId));let v={id:k.id,kind:"fullscreen-offer",reason:k.type==="box.stuck.detected"?"stuck":"fullscreen",offerId:f.offerId,status:"open",ts:he(k),box:f.box||k.boxId,agent:f.agent||k.provider,...k.type==="box.stuck.detected"?{escSends:f.escSends??null,kept:f.kept??0}:{}};U.set(f.offerId,v),W.set(f.offerId,v),n.push(v);break}case"box.fullscreen.answered":case"box.stuck.answered":{let v=W.get(f.offerId);v&&(v.status=f.action==="restarted"?"restarted":f.action==="cleared"?"cleared":"dismiss",U.delete(f.offerId));break}case"ticket.move.offered":{if(!f.offerId)break;for(let O of I.values())O.key===f.key&&(O.status="stale",I.delete(O.offerId));let v={id:k.id,kind:"ticket-offer",offerId:f.offerId,provider:f.provider||"linear",key:f.key,url:f.url??null,phase:f.phase??null,from:f.from??null,to:f.to?.name??null,prNumber:f.prNumber??null,status:"open",ts:he(k),box:k.boxId,agent:k.provider};I.set(f.offerId,v),S.set(f.offerId,v),n.push(v);break}case"ticket.move.answered":{let v=S.get(f.offerId);v&&(v.status=f.action==="moved"?"moved":"dismiss",I.delete(f.offerId));break}case"ticket.state.changed":{for(let v of I.values())v.key===f.key&&v.to===f.to&&(v.status="stale",I.delete(v.offerId));if(f.mode==="offer")break;n.push(yt(k,"ticket-state"));break}case"ticket.commented":{n.push({id:k.id,kind:"ticket-comment",key:f.key,url:f.url??null,excerpt:f.excerpt??null,ts:he(k),box:k.boxId,agent:k.provider});break}case"ticket.flow.changed":n.push(yt(k,"ticket-flow"));break;case"ticket.create.offered":{if(!f.proposalId)break;for(let O of ie.values())O.status="stale";ie.clear();let v={id:k.id,kind:"ticket-create-offer",proposalId:f.proposalId,provider:f.provider||"linear",epic:f.epic??null,issues:Array.isArray(f.issues)?f.issues:[],team:f.team??null,needsTeam:!!f.needsTeam,linkCurrentTrack:!!f.linkCurrentTrack,status:"open",ts:he(k),box:k.boxId,agent:k.provider};ie.set(f.proposalId,v),z.set(f.proposalId,v),n.push(v),Ue(v);break}case"ticket.create.answered":{let v=z.get(f.proposalId);v&&(v.status=f.action==="created"?"created":"dismiss",v.createdCount=f.createdCount??null,v.failedCount=f.failedCount??null,ie.delete(f.proposalId));break}case"loop.create.offered":{if(!f.proposalId)break;for(let O of Ge.values())O.status="stale";Ge.clear();let v={id:k.id,kind:"loop-create-offer",proposalId:f.proposalId,name:f.name??"",schedule:f.schedule??"",prompt:f.prompt??"",expectation:f.expectation??null,notify:f.notify??"off",assignment:f.assignment??{provider:"claude"},repo:f.repo??null,nodeId:f.nodeId??null,nodeName:f.nodeName??null,status:"open",ts:he(k),box:k.boxId,agent:k.provider};Ge.set(f.proposalId,v),_e.set(f.proposalId,v),n.push(v),Ue(v);break}case"loop.create.answered":{let v=_e.get(f.proposalId);v&&(v.status=f.action==="created"?"created":"dismiss",Ge.delete(f.proposalId));break}case"followup.armed":{if(!f.armId)break;let v=f.replaces?Ie.get(f.replaces):null;v&&v.arm.status==="armed"&&ae(v,"replaced");let O={armId:f.armId,seq:Number.isInteger(f.seq)?f.seq:0,label:f.label??"",prompt:f.prompt??"",why:f.why??null,standing:f.standing==="never"?"never":"offerable",status:"armed"},G=f.groupId??null,ge=G?Pe.get(G):null;ge||(ge={id:k.id,kind:"followup-armed",groupId:G,armId:O.armId,trigger:f.trigger??"now",label:O.label,prompt:O.prompt,why:O.why,planWhy:f.planWhy??null,arms:[],status:"armed",ts:he(k),box:k.boxId,agent:k.provider},G&&Pe.set(G,ge),ge.trigger!=="now"&&n.push(ge)),ge.arms.push(O),Ie.set(f.armId,{arm:O,line:ge});break}case"followup.armed.cancelled":{let v=Ie.get(f.armId);v&&v.arm.status==="armed"&&ae(v,"cancelled");break}case"followup.offered":{if(!f.offerId)break;for(let G of Y.values())G.trigger===f.trigger&&(G.status="stale",Y.delete(G.offerId));let v=Array.isArray(f.rows)?f.rows:[];for(let G of v){let ge=G.armId?Ie.get(G.armId):null;ge&&ge.arm.status==="armed"&&ae(ge,"offered")}let O={id:k.id,kind:"followup-offer",offerId:f.offerId,trigger:f.trigger??"now",repo:f.repo??null,context:f.context&&typeof f.context=="object"?f.context:{},groupId:f.groupId??null,why:f.why??null,rows:v.map(G=>({followupId:G.followupId??null,armId:G.armId??null,label:G.label??"",prompt:G.prompt??null,promptPreview:G.promptPreview??null,promptHash:G.promptHash??null,origin:G.origin??"operator",why:G.why??null,groupId:G.groupId??null,seq:Number.isInteger(G.seq)?G.seq:0,standing:G.standing==="never"?"never":"offerable",promotable:G.armId?G.promotable!==!1:!1,promotableReason:G.promotableReason??null,rowStatus:"open",saved:null})),status:"open",answer:null,answers:[],ts:he(k),box:k.boxId,agent:k.provider};Y.set(f.offerId,O),ne.set(f.offerId,O),n.push(O),O.trigger==="now"&&Ue(O);break}case"followup.arm.saved":{let v=ne.get(f.offerId);if(!v)break;let O=v.rows.find(G=>G.armId&&G.armId===f.armId);O&&(O.saved=f.followupId??null);break}case"followup.answered":{let v=ne.get(f.offerId);if(!v)break;let O=new Set;f.armId&&O.add(`arm:${f.armId}`),f.followupId&&O.add(`fu:${f.followupId}`);for(let ye of Array.isArray(f.armIds)?f.armIds:[])O.add(`arm:${ye}`);for(let ye of Array.isArray(f.followupIds)?f.followupIds:[])O.add(`fu:${ye}`);let G=f.action==="sent"?"sent":f.action==="removed"?"removed":"dismiss";for(let ye of v.rows){if(ye.rowStatus!=="open")continue;let vt=ye.armId?`arm:${ye.armId}`:`fu:${ye.followupId}`;O.size&&!O.has(vt)||(ye.rowStatus=G)}let ge={followupId:f.followupId??null,armId:f.armId??null,label:f.label??null,promoted:f.promoted??null,revived:f.revived===!0,action:G,batchId:f.batchId??null,edited:f.edited===!0,order:Number.isInteger(f.order)?f.order:null,reordered:f.reordered===!0};v.answers.push(ge),v.answer=ge,v.rows.some(ye=>ye.rowStatus==="open")?v.status="open":(v.status=v.rows.some(ye=>ye.rowStatus==="sent")?"sent":v.rows.some(ye=>ye.rowStatus==="removed")?"removed":"dismiss",Y.delete(f.offerId));break}case"followup.create.offered":{if(!f.proposalId)break;for(let O of ve.values())O.status="stale";ve.clear();let v={id:k.id,kind:"followup-create-offer",proposalId:f.proposalId,label:f.label??"",prompt:f.prompt??"",trigger:f.trigger??"pr.merged",repo:f.repo??null,why:f.why??null,status:"open",created:null,ts:he(k),box:k.boxId,agent:k.provider};ve.set(f.proposalId,v),Ye.set(f.proposalId,v),n.push(v),Ue(v);break}case"followup.create.answered":{let v=Ye.get(f.proposalId);v&&(v.status=f.action==="created"?"created":"dismiss",ve.delete(f.proposalId));break}case"followup.created":{let v=f.proposalId?Ye.get(f.proposalId):null;v&&(v.created={followupId:f.followupId??null});break}case"loop.created":{let v=f.proposalId?_e.get(f.proposalId):null;v&&(v.created={loopId:f.loopId??null,nextFireAt:Number.isFinite(Number(f.nextFireAt))?Number(f.nextFireAt):null}),n.push(yt(k,"loop-created"));break}case"loop.update.offered":case"loop.delete.offered":{if(!f.proposalId||!f.loopId)break;for(let G of Fe.values())G.loopId===f.loopId&&(G.status="stale",G.staleReason="superseded",Fe.delete(G.proposalId));let v=k.type==="loop.update.offered",O={id:k.id,kind:v?"loop-update-offer":"loop-delete-offer",proposalId:f.proposalId,loopId:String(f.loopId),name:f.name??f.base?.name??"",base:f.base??null,...v?{patch:f.patch??{},changed:Array.isArray(f.changed)?f.changed:Object.keys(f.patch||{})}:{reason:f.reason??""},selfEdit:!!f.selfEdit,status:"open",staleReason:null,ts:he(k),box:k.boxId,agent:k.provider};Fe.set(f.proposalId,O),Zt.set(f.proposalId,O),n.push(O),Ue(O);break}case"loop.update.answered":{let v=Zt.get(f.proposalId);v&&(f.action==="moved"?(v.status="stale",v.staleReason="moved"):v.status=f.action==="applied"?"applied":"dismiss",Fe.delete(f.proposalId));break}case"loop.delete.answered":{let v=Zt.get(f.proposalId);v&&(f.action==="moved"?(v.status="stale",v.staleReason="moved"):v.status=f.action==="delete"?"deleted":f.action==="pause"?"paused":"keep",Fe.delete(f.proposalId));break}case"loop.updated":{let v=f.proposalId?Zt.get(f.proposalId):null;v&&(v.applied={changed:Array.isArray(f.changed)?f.changed:[],nextFireAt:Number.isFinite(Number(f.nextFireAt))?Number(f.nextFireAt):null}),n.push(yt(k,"loop-updated"));break}case"loop.deleted":n.push(yt(k,"loop-deleted"));break;case"loop.paused":n.push(yt(k,"loop-paused"));break;case"planning.change.offered":{if(!f.proposalId||!Array.isArray(f.ops)||!f.ops.length)break;for(let O of ut.values())O.status="stale",O.staleReason="superseded",ut.delete(O.proposalId);let v={id:k.id,kind:"planning-offer",proposalId:f.proposalId,why:f.why??"",ops:f.ops,base:f.base??{},resolved:f.resolved??{},snapped:!!f.snapped,createsMeRow:!!f.createsMeRow,status:"open",staleReason:null,applied:null,ts:he(k),box:k.boxId,agent:k.provider};ut.set(f.proposalId,v),kn.set(f.proposalId,v),n.push(v),Ue(v);break}case"planning.change.answered":{let v=kn.get(f.proposalId);v&&(f.action==="moved"?(v.status="stale",v.staleReason="moved"):v.status=f.action==="applied"?"applied":"dismiss",ut.delete(f.proposalId));break}case"planning.changed":{let v=f.proposalId?kn.get(f.proposalId):null;v&&(v.applied={results:Array.isArray(f.results)?f.results:[]}),n.push(yt(k,"planning-changed"));break}case"rework.cause.offered":{if(!f.sha||Kr.has(f.sha))break;let v={id:k.id,kind:"rework-cause-offer",sha:f.sha,subject:f.subject??"",linesReworked:Number(f.linesReworked)||0,origins:Array.isArray(f.origins)?f.origins:[],heuristic:f.heuristic??null,intent:f.intent??null,shas:Array.isArray(f.shas)?f.shas:null,pr:f.pr??null,retracts:0,status:"open",cause:null,ts:he(k),box:k.boxId,agent:k.provider};Kr.set(f.sha,v),n.push(v);break}case"rework.cause.answered":{let v=f.sha?Kr.get(f.sha):null;v&&(v.status="answered",v.cause=f.cause??null);break}case"rework.cause.retracted":{let v=f.sha?Kr.get(f.sha):null;v&&(v.status="open",v.cause=null,v.retracts=(v.retracts??0)+1);break}case"ticket.created":{let v={items:Array.isArray(f.items)?f.items:[],failed:Array.isArray(f.failed)?f.failed:[],team:f.team??null},O=f.proposalId?z.get(f.proposalId):null;if(O){O.created=v;break}n.push({id:k.id,kind:"ticket-created",...v,ts:he(k),box:k.boxId,agent:k.provider});break}case"error":{if(!f.kind)break;n.push(yt(k,f.kind));break}case"turn.aborted":{(f.cause==="cli-exited"||f.cause==="session-gone")&&n.push(yt(k,"turn-aborted"));break}case"provider.error":n.push({...yt(k,"provider-error"),provider:k.provider,box:k.boxId,agent:k.provider});break;case"usage.cap.hit":n.push(yt(k,"usage-cap-hit"));break;case"usage.cap.warning":n.push(yt(k,"usage-cap-warning"));break;case"provider.connected":{n.push({id:k.id,kind:"event",type:"provider-connected",provider:f.provider||k.provider,account:f.account||null,reason:f.reason||null,ts:he(k),at:he(k),box:k.boxId,agent:k.provider});break}case"provider.login.started":break;case"prompt.answered":{if(it=null,f.control||!f.question)break;let v=f.groupId||f.promptId;if(!v)break;let O=at.get(v);O||(O={id:k.id,kind:"prompt",groupId:v,provider:k.provider,box:k.boxId,agent:k.provider,questionTotal:f.questionTotal??1,questions:[],ts:he(k)},at.set(v,O));let G=f.questionIndex??0,ge={index:G,header:f.header||"",question:f.question,multiSelect:!!f.multiSelect,chosen:Array.isArray(f.chosen)?f.chosen:[]},ye=O.questions.findIndex(ct=>ct.index===G&&Be(ct.question)===Be(ge.question));ye>=0?O.questions[ye]=ge:O.questions.push(ge),O.questions.sort((ct,zr)=>ct.index-zr.index),O.questionTotal=Math.max(O.questionTotal,f.questionTotal??1),O.questions.length>=O.questionTotal&&(n.push(O),at.delete(v));break}case"prompt.dismissed":{it=null;let v=f.groupId||f.promptId;if(!v||!f.question)break;let G=at.get(v)||{id:k.id,kind:"prompt",groupId:v,provider:k.provider,box:k.boxId,agent:k.provider,questionTotal:f.questionTotal??1,questions:[],ts:he(k)},ge=f.questionIndex??0;G.questions.some(ye=>ye.index===ge&&Be(ye.question)===Be(f.question))||(G.questions.push({index:ge,header:f.header||"",question:f.question,multiSelect:!!f.multiSelect,chosen:[]}),G.questions.sort((ye,vt)=>ye.index-vt.index)),G.answeredVia="chat",n.push(G),at.delete(v);break}default:break}}for(let[k,f]of[...Q]){if(f==="superseded"){k.status!=="superseded"&&me(k,null);continue}(k.status!=="open"||t-(k.ts??0)>=vF)&&me(k,null)}let ns=h.size?n.filter(k=>!k.retired):n;return AF(ns.sort((k,f)=>(k.ts??0)-(f.ts??0)))}function AF(e){let t=new Map,n=[];for(let r of e){if(r.kind!=="message"||!r.box){n.push(r);continue}let o=r.role==="assistant"&&!String(r.text||"").trim()&&r.images?.length,s=t.get(r.box);if(o&&s&&(r.ts??0)-s.lastTs<=SF){s.item.images.push(...r.images),s.lastTs=r.ts??s.lastTs;continue}if(o){let a={...r,images:[...r.images]};t.set(r.box,{item:a,lastTs:r.ts??0}),n.push(a)}else t.delete(r.box),n.push(r)}return n}function hw(e,t=null){let n=[];for(let o of e||[]){if(o.type!=="tool.called"||o.source!=="transcript")continue;let s=o.payload||{};String(s.command||"").trim()&&n.push({id:s.id??null,tool:s.tool||null,command:s.command,description:s.description||"",summary:TF(s),ts:s.ts??o.ts,n:s.n,box:o.boxId,agent:o.provider,boxRole:s.boxRole})}if(!n.length)return[];let r=(t??Gn(e)).filter(o=>o.kind==="message");return iS(n,r)}function TF(e){let t=String(e.summary||"").trim();return t&&t!==e.command&&t!==Ca(e.command)?t:ao(e.command,e.description||"")}function yt(e,t){let{ts:n,change:r,kind:o,...s}=e.payload||{};return{id:e.id,kind:"event",type:t,...s,at:he(e),ts:he(e)}}function hA(e){let t=[...e];for(let n=0;n<t.length;n++){let r=t[n];if(r?.kind!=="event"||r.type!=="archived")continue;let o=(r.ts??0)+EF,s=n;for(;s+1<t.length;){let a=t[s+1];if((a?.ts??0)>o||a?.kind==="event"&&_F.has(a.type))break;s++}s>n&&t.splice(s,0,...t.splice(n,1)),n=s}return t}function mA(e){let t=[...e];for(let n=0;n<t.length;n++){let r=t[n];if(r?.kind!=="event"||!$F.has(r.type)||!r.box)continue;let o=(r.ts??0)+IF,s=n;for(;s+1<t.length;){let a=t[s+1];if((a?.ts??0)>o||!(a?.kind==="message"&&a.role==="assistant"&&a.box===r.box||a?.kind==="command-batch"&&a.anchorBox===r.box))break;s++}s>n&&t.splice(s,0,...t.splice(n,1)),n=s}return t}function Jd(e){return(e||[]).filter(t=>RF.has(t?.kind)&&t.status==="open")}function wA(e){let t=new Map,n=new Map;for(let r of e||[]){if(r.type!=="pr.state.changed")continue;let o=r.payload||{};if(pA.has(o.change)&&o.number!=null)fA(t,n,o);else if(o.change==="merged"||o.change==="closed"||o.change==="lost"){let s=fw(o);if(t.has(s))t.delete(s);else if(o.number!=null)for(let a of[...t.keys()])a.endsWith(`#${o.number}`)&&t.delete(a)}}return[...t.values()]}var he,pA,fw,vF,SF,EF,_F,IF,$F,RF,Yd=V(()=>{Na();gs();Od();Da();La();pw();he=e=>e.payload?.ts??e.ts;pA=new Set(["opened","ci-fixed","reconciled","pushed"]),fw=e=>`${e.repo??""}#${e.number}`;vF=3e4;SF=2*6e4;EF=12e4,_F=new Set(["archived","unarchived","opened"]);IF=2500,$F=new Set(["pr-opened","pr-merged","pr-auto-armed"]);RF=new Set(["pr-offer","pr-exists-offer","ticket-offer","ticket-create-offer","loop-create-offer","loop-update-offer","loop-delete-offer","planning-offer","fullscreen-offer","followup-create-offer"])});function PF(e){let t=null,n=null,r=null;for(let o of e??[]){let s=o?.ts??null;s&&(r=Math.max(r??0,s)),o?.type==="handoff.artifact"&&(t={ts:o.payload?.ts??s,truncated:!!o.payload?.truncated,...o.payload?.reconstructed?{reconstructed:!0}:{}}),o?.type==="code.pushed"&&(n={ts:o.payload?.ts??s,sha:o.payload?.sha??null,ref:o.payload?.ref??null,wip:!!o.payload?.wip})}return{lastArtifact:t,lastPush:n,lastEventAt:r}}function BF(e){for(let t=(e?.length??0)-1;t>=0;t--){let n=e[t];if(n?.type==="handoff.artifact"&&!n.payload?.reconstructed)return n}return null}function LF(e,t){let n=[],r=[],o=new Set,s=new Set;for(let a=(e?.length??0)-1;a>=0;a--){let i=e[a];if(i?.type!=="tool.called")continue;if(t!=null&&(i.ts??0)<=t)break;let c=i.payload||{};c.path&&!o.has(c.path)&&n.length<CF&&(o.add(c.path),n.push(c.path)),c.head&&!s.has(c.head)&&r.length<NF&&(s.add(c.head),r.push(c.head))}return{files:n,heads:r}}function kA(e,{trackName:t="this Track",now:n=null,mode:r="failover"}={}){let o=PF(e),s=BF(e),a=s?.payload?.content??null,i=s?s.payload?.ts??s.ts??null:null,c=Gn(e??[]).filter(p=>p?.kind==="message"&&typeof p.text=="string"&&p.text.trim()).slice(-OF);if(!a&&!c.length)return null;let l=[];if(l.push(`# Reconstructed resume brief \u2014 ${t}`),l.push(""),l.push(bA[r]??bA.failover),l.push(""),o.lastPush?.sha){let p=yA(n,o.lastPush.ts),m=p?` (~${p} min before the loss)`:"";l.push(`**Code state:** last pushed ref \`${o.lastPush.ref}\` @ \`${o.lastPush.sha.slice(0,12)}\`${m}`+(o.lastPush.wip?" \u2014 a bostrat WIP snapshot (full working tree incl. uncommitted edits at push time).":"."))}else r==="in-place"?l.push("**Code state:** no push recorded \u2014 the working tree in this workspace is the only copy; commit early."):l.push("**Code state:** no push was ever recorded for this Track \u2014 work since the branch's last known state stayed on the offline node.");if(l.push(""),a){let p=yA(n,i);l.push(`## Last real checkpoint (written by the previous agent${p?`, ~${p} min before this reconstruction`:""})`),l.push(""),l.push(a.trim()),l.push("")}let u=LF(e??[],i);if((u.files.length||u.heads.length)&&(l.push(`## Work since ${a?"that checkpoint":"the start of the log"} (from the event log)`),l.push(""),u.files.length&&l.push(`Files touched (most recent first): ${u.files.map(p=>`\`${p}\``).join(", ")}`),u.heads.length&&(u.files.length&&l.push(""),l.push(`Commands run (most recent first): ${u.heads.map(p=>`\`${p}\``).join(" \xB7 ")}`)),l.push("")),c.length){l.push(`## Recent conversation (last ${c.length} message${c.length===1?"":"s"})`),l.push("");for(let p of c)l.push(`**${p.role==="user"?"operator":"agent"}:** ${DF(p.text,MF)}`),l.push("")}l.push("---"),l.push("Resume: continue the objective above from the verified repository state; ask the operator before redoing anything the log says was already done.");let d=l.join(`
161
161
  `);return d.length<=gA?d:`${d.slice(0,gA)}
162
162
 
163
163
  [\u2026 brief truncated]`}var OF,MF,gA,CF,NF,DF,yA,bA,xA=V(()=>{Yd();OF=12,MF=2e3,gA=48e3,CF=30,NF=10;DF=(e,t)=>{let n=String(e??"").trim();return n.length<=t?n:`${n.slice(0,t-1)}\u2026`},yA=(e,t)=>e&&t?Math.max(1,Math.round((e-t)/6e4)):null;bA={failover:"**This is a reconstruction, not a checkpoint.** The node this Track lived on went offline without a clean handoff; bostrat assembled this brief from the durable event log. Treat every claim below as a lead, not a fact \u2014 **verify the repository state first** (git status, git log, the diff against the last pushed ref) before continuing work.","in-place":"**This is a reconstruction, not a checkpoint.** The previous lead ended without writing one (out of credits, capped, or unresponsive); bostrat assembled this status from the Track's event log. You are in the SAME live workspace \u2014 uncommitted work is present locally. **Run git status and git log first** and treat every claim below as a lead, not a fact.",get recover(){return this.failover},transfer:"**This Track was MOVED to a new machine while it was alive.** The previous node checkpointed and pushed its work as part of the move; this workspace was re-created from that push (uncommitted work re-applied when possible). **Run git status and git log to confirm what carried over**, then continue the objective below."}});function uo(e){let t=e.search(yw);return(t>=0?e.slice(0,t):e).trim()}function jF(e){if(!e)return"";let t=e.replace(/[│┌└├─┘┤┬┴┼─✂].*$/,"").trim();return!t||/hidden|\d+\s+lines?/i.test(t)?"":t}function FF(e){let t=String(e).trim();return!!(!t||lo.test(e)||yw.test(t)||/hidden|\d+\s+lines?/i.test(t)||/notespress|press n to add/i.test(t)||/^\s*notes?\s*$/i.test(t))}function UF(e,t=""){let n=[],r=/([☐☒])\s+([^☐☒←→✔]+)/g,o;for(;(o=r.exec(e))!==null;)n.push({label:o[2].trim(),answered:o[1]==="\u2612",current:!1});if(!n.length)return null;let s=HF(n,t);return n.forEach((a,i)=>{a.current=i===s}),{tabs:n,questionIndex:s,questionTotal:n.length,currentTabLabel:n[s].label}}function HF(e,t){let n=String(t).toLowerCase(),r=e.findIndex(c=>!c.answered),o=r>=0?r:e.length-1;if(!n)return o;let s=e.map(c=>{let l=c.label.toLowerCase(),u=l.split(/\s+/).filter(p=>p.length>3&&n.includes(p)).length;if(u)return u;let d=l.slice(0,8).trim();return d.length>=4&&n.includes(d)?1:0}),a=Math.max(...s);if(a===0||s[o]===a)return o;let i=s.flatMap((c,l)=>c===a?[l]:[]);return i.length===1?i[0]:o}function vA(e){return e.replace(/[←→✔☐☒●▶]/g," ").replace(/\bSubmit\b/g," ").replace(/\s+/g," ").trim()}function WF(e,t=""){let n=String(e);if(!TA.test(n))return null;let r=n.replace(/\r/g,"").split(`
@@ -189,7 +189,7 @@ ${String(t||"")}`;return/Try the new fullscreen renderer|Flicker-free output/i.t
189
189
  `),n=t.findIndex(o=>/Select Model and Effort/i.test(o));if(n<0)return null;let r=[];for(let o=n+1;o<t.length;o++){let s=t[o].match(/^\s*(›\s*)?(\d+)\.\s+(\S+?)(?:\s+\((current|default)\))?(?:\s{2,}|\s*$)/);if(s)r.push({n:Number(s[2]),id:s[3],current:s[4]==="current",active:!!s[1]});else if(r.length&&/Press enter|esc to go back/i.test(t[o]))break}return r.length?r:null}function yE(e){let t=String(e||"").split(`
190
190
  `),n=t.findIndex(o=>/Select Reasoning Level/i.test(o));if(n<0)return null;let r=[];for(let o=n+1;o<t.length;o++){let s=t[o].match(/^\s*(›\s*)?(\d+)\.\s+([A-Za-z ]+?)(?:\s+\((default|current)\))?(?:\s{2,}|\s*$)/);if(s)r.push({n:Number(s[2]),label:s[3].trim(),isDefault:!!s[4],active:!!s[1]});else if(r.length&&/Press enter|esc to go back/i.test(t[o]))break}return r.length?r:null}function Q4(e){let t=String(e||"").split(`
191
191
  `);for(let n=t.length-1;n>=0;n--){let r=t[n].match(/Model changed to\s+(\S+)(?:\s+(\S+))?\s*$/i);if(r)return{model:r[1],effort:r[2]||null}}return null}function bE(e){let t=String(e||"").split(`
192
- `),n=t.findIndex(s=>/Available models|Models matching/i.test(s));if(n<0)return null;let r=/Models matching/i.test(t[n]),o=[];for(let s=n+1;s<t.length;s++){let a=t[s];if(/^\s*Filter:/i.test(a)||!a.trim())continue;if(/to filter|Enter to select|^\s*\d+-\d+ of \d+/i.test(a))break;let i=a.match(/^\s*(→\s+)?(.+?)\s*$/);if(!i)continue;let c=i[2].replace(/\s*\(Tab to modify\)\s*$/i,""),l=null,u=c.split(/\s{2,}/);u.length>1&&(c=u[0],l=u.slice(1).join(" ").trim()||null),c&&o.push({label:c.trim(),params:l,active:!!i[1]})}return o.length?{filtered:r,rows:o}:null}function SE(e,t){if(typeof t!="string"||!t.trim())throw new Error("model (string) required");let n=t.trim();if(e==="codex"){let[r,o]=n.split(/[\s:]+/);if(o&&!xE.has(o))throw new Error(`unknown codex effort "${o}" (low | medium | high | xhigh)`);return{model:r,effort:o||null}}if(e==="cursor"){let r=vE.find(o=>o.alias===n);return{model:n,filter:r?r.label:n}}if(!X4.has(n))throw new Error(`unknown model "${n}"`);return{model:n}}async function al(e,t,{timeoutMs:n=J4}={}){let r=Date.now()+n;for(;;){let o=await Le(e,{lines:80}).catch(()=>""),s=t(o);if(s)return s;if(Date.now()>r)return null;await kp(Y4)}}async function e2(e,t){return await Ze(e,`/model ${t.model}`,qn("claude")),{verified:!1,note:"confirmed when the next turn's transcript model flips"}}async function t2(e,t){await Ed(e),await Ze(e,"/model",{enter:!1}),await kp(250),await Je(e,["Enter"],{kind:"model-switch"});let n=await al(e,gE);if(!n)throw new Error("codex model picker didn't open");let r=n.find(i=>i.id===t.model);if(!r)throw await Je(e,["Escape"],{kind:"model-switch"}).catch(()=>{}),new Error(`unknown model "${t.model}" \u2014 codex offers: ${n.map(i=>i.id).join(", ")}`);let o=i=>{let c=Q4(i);return!c||c.model!==t.model||t.effort&&c.effort&&c.effort.toLowerCase()!==t.effort.toLowerCase()?null:c};await Ze(e,String(r.n),{enter:!1,kind:"model-switch"});let s=await al(e,i=>yE(i)||!gE(i)&&o(i)&&{done:o(i)});if(!s)throw await Je(e,["Escape"],{kind:"model-switch"}).catch(()=>{}),new Error("codex reasoning-level picker didn't open");if(!s.done){let i=t.effort?xE.get(t.effort):null,c=i?s.find(l=>l.label.toLowerCase()===i.toLowerCase()):s.find(l=>l.isDefault)||s[0];if(!c)throw await Je(e,["Escape","Escape"],{kind:"model-switch"}).catch(()=>{}),new Error(`codex doesn't offer effort "${t.effort}" for ${t.model}`);await Ze(e,String(c.n),{enter:!1,kind:"model-switch"})}let a=s.done||await al(e,i=>!yE(i)&&o(i));if(!a)throw new Error("codex never confirmed the model change");return{verified:!0,model:a.model,effort:a.effort}}async function n2(){let e=wE.join(process.env.CURSOR_CONFIG_DIR||wE.join(z4.homedir(),".cursor"),"cli-config.json");try{return JSON.parse(await V4.readFile(e,"utf8"))?.model||null}catch{return null}}async function r2(e,t){await Ed(e),await Id(e,`/model ${t.filter}`,{kind:"model-switch"});let n=await al(e,bE),r=c=>String(c||"").toLowerCase(),o=c=>r(c.label).startsWith(r(t.filter)),s=n?.rows.find(c=>c.active)||null;if(n&&!(s&&o(s)))for(let c=0;c<12;c++){let l=await al(e,bE,{timeoutMs:1500});if(s=l?.rows.find(u=>u.active)||null,s&&o(s))break;if(!l||!l.rows.some(o)){s=null;break}await Je(e,["Down"],{kind:"model-switch"}),await kp(250)}if(!n||!s||!o(s)){await Je(e,["Escape"],{kind:"model-switch"}).catch(()=>{});let c=Array(`/model ${t.filter}`.length).fill("BSpace");throw await Je(e,c,{settleMs:15,kind:"model-switch"}).catch(()=>{}),new Error(n?`cursor picker has no model matching "${t.filter}"`:"cursor model picker didn't open")}await Je(e,["Enter"],{kind:"model-switch"}),await kp(800);let a=await n2();return{verified:!!a&&(a.modelId===t.model||a.displayModelId===t.model||r(a.displayName).startsWith(r(t.filter))),model:a?.modelId||null,note:"cursor applies this as the global default for new sessions too"}}async function AE(e,t,n){return e==="codex"?t2(t,n):e==="cursor"?r2(t,n):e2(t,n)}var kp,J4,Y4,kE,X4,Z4,xE,vE,TE=V(()=>{mt();Yc();kp=e=>new Promise(t=>setTimeout(t,e)),J4=Number(process.env.BOSTRAT_MODEL_PICKER_TIMEOUT_MS)||8e3,Y4=300,kE=[{alias:"default",label:"Default"},{alias:"opus",label:"Opus 5"},{alias:"sonnet",label:"Sonnet 5"},{alias:"haiku",label:"Haiku 4.5"},{alias:"fable",label:"Fable 5.1"},{alias:"opusplan",label:"Opus Plan"}],X4=new Set([...kE.map(e=>e.alias),"best","opus[1m]","sonnet[1m]","claude-opus-5","claude-opus-4-8","claude-sonnet-5","claude-sonnet-4-6","claude-haiku-4-5","claude-fable-5","claude-fable-5-1"]),Z4=[{alias:"gpt-5.6-sol",label:"GPT-5.6 Sol"},{alias:"gpt-5.6-terra",label:"GPT-5.6 Terra"},{alias:"gpt-5.6-luna",label:"GPT-5.6 Luna"},{alias:"gpt-5.5",label:"GPT-5.5"},{alias:"gpt-5.3-codex",label:"Codex 5.3"}],xE=new Map([["low","Low"],["medium","Medium"],["high","High"],["xhigh","Extra high"]]),vE=[{alias:"auto",label:"Auto"},{alias:"composer-2.5",label:"Composer 2.5"},{alias:"claude-opus-5-high",label:"Opus 5"},{alias:"claude-fable-5-1-high",label:"Fable 5.1"},{alias:"claude-sonnet-5-high",label:"Sonnet 5"},{alias:"cursor-grok-4.6-high",label:"Cursor Grok 4.6"},{alias:"gpt-5.6-sol-high",label:"GPT-5.6 Sol High"},{alias:"gpt-5.3-codex",label:"Codex 5.3"}]});function Sp(e){let t=e||{},n=o2(t);return n&&(n.payload={ts:t.at,...n.payload}),n}function o2(e){switch(e.type){case"said":return{type:"turn.user",actor:"user",source:"orchestrator",boxId:e.box,provider:ft(e.agent),payload:{text:e.text,boxRole:e.boxRole,...e.kind?{kind:e.kind}:{},...e.attachments?.length?{attachments:e.attachments}:{},...e.deliveryId?{deliveryId:e.deliveryId}:{}}};case"unsaid":return{type:"turn.retracted",actor:"user",source:"orchestrator",boxId:e.box,provider:ft(e.agent),payload:{saidTs:e.saidTs,text:e.text,boxRole:e.boxRole}};case"orchestration-prompt":return{type:"turn.user",actor:"orchestrator",source:"orchestrator",boxId:e.box,provider:ft(e.agent),payload:{text:e.prompt,kind:e.kind,boxRole:e.boxRole,...e.deliveryId?{deliveryId:e.deliveryId}:{}}};case"lead-handoff":return{type:"handoff.done",actor:"orchestrator",source:"orchestrator",boxId:e.to,provider:ft(e.toAgent),payload:{from:e.from,fromAgent:e.fromAgent,to:e.to,toAgent:e.toAgent,reason:e.reason,handoffStartedAt:e.handoffStartedAt,fromSessionId:e.fromSessionId,toSessionId:e.toSessionId,epoch:e.epoch,singleBox:e.singleBox,forced:e.forced,recovered:e.recovered,checkpoint:e.checkpoint,cliVersion:e.cliVersion??null,...e.standing?{standing:e.standing}:{}}};case"lead-handoff-failed":return{type:"handoff.failed",actor:"orchestrator",source:"orchestrator",boxId:e.box,provider:ft(e.toAgent),payload:{box:e.box,fromAgent:e.fromAgent,toAgent:e.toAgent,reason:e.reason,error:e.error,rolledBack:e.rolledBack,handoffStartedAt:e.handoffStartedAt}};case"subtask-delegated":return{type:"subtask.delegated",actor:"orchestrator",source:"orchestrator",boxId:e.to,provider:ft(e.toAgent),payload:{task:e.task,subtaskId:e.subtaskId,reason:e.reason}};case"subtask-merged":return{type:"subtask.merged",actor:"orchestrator",source:"orchestrator",boxId:e.box||e.from,provider:ft(e.agent),payload:{...Vn(e)}};case"subtask-failed":return{type:"error",actor:"system",source:"orchestrator",boxId:e.box||e.to,provider:ft(e.agent||e.toAgent),payload:{kind:"subtask-failed",...Vn(e)}};case"subtask-resumed":return{type:"box.state.changed",actor:"orchestrator",source:"orchestrator",boxId:e.box,provider:ft(e.agent),payload:{change:"subtask-resumed",...Vn(e)}};case"model-change":return{type:"box.state.changed",actor:"user",source:"orchestrator",boxId:e.box,payload:{change:"model",model:e.to,from:e.from??null,verified:e.verified??null}};case"codex-update":return{type:"box.state.changed",actor:"orchestrator",source:"orchestrator",boxId:e.box,provider:"codex",payload:{change:"cli-update",from:e.from??null,to:e.to??null,status:e.status,...e.error?{error:e.error}:{}}};case"node-update":return{type:"box.state.changed",actor:"orchestrator",source:"orchestrator",payload:{change:"node-update",...Vn(e)}};case"opened":return{type:"box.state.changed",actor:"user",source:"orchestrator",boxId:e.box,payload:{change:"opened",...Vn(e)}};case"archived":case"unarchived":case"track-deleted":case"renamed":return{type:"box.state.changed",actor:"user",source:"orchestrator",payload:{change:e.type,...Vn(e)}};case"rehydrated":return{type:"box.state.changed",actor:"orchestrator",source:"orchestrator",boxId:e.box,provider:ft(e.agent),payload:{change:"rehydrated",...e.fresh?{fresh:!0}:{}}};case"lead-refreshed":return{type:"box.state.changed",actor:"orchestrator",source:"orchestrator",boxId:e.box,provider:ft(e.agent),payload:{change:"lead-refreshed",box:e.box,agent:e.agent,fromSessionId:e.fromSessionId,toSessionId:e.toSessionId,epoch:e.epoch,reason:e.reason,cliVersion:e.cliVersion??null,...e.standing?{standing:e.standing}:{}}};case"transferred-in":return{type:e.mode==="recover"?"track.recovered":"track.transferred",actor:"orchestrator",source:"orchestrator",boxId:e.box,provider:ft(e.agent),payload:{...Vn(e)}};case"transferred-out":return null;case"retagged":return{type:"box.state.changed",actor:"user",source:"orchestrator",payload:{change:"retagged",...Vn(e)}};case"retag-failed":return{type:"error",actor:"orchestrator",source:"orchestrator",boxId:e.box,provider:ft(e.agent),payload:{kind:"retag-failed",action:e.action??"reshape",reason:e.reason,rolledBack:e.rolledBack!==!1,...e.recovered?{recovered:!0}:{}}};case"rehydrate-failed":return{type:"error",actor:"system",source:"orchestrator",boxId:e.box,provider:ft(e.agent),payload:{kind:"rehydrate-failed",reason:e.reason}};case"delivery-held":return{type:"error",actor:"system",source:"orchestrator",boxId:e.box,provider:ft(e.agent),payload:{kind:"delivery-held",...Vn(e)}};case"startup-gate":return{type:"error",actor:"system",source:"orchestrator",boxId:e.box,provider:ft(e.agent),payload:{kind:"startup-gate",...Vn(e)}};default:return null}}function IE(e,t){let n=Sp(t);if(!n)return;let r=t?.type==="track-deleted"?{id:e.id}:e;Ap(()=>D(r,n))}async function $E(e){if(!(!e?.id||EE.has(e.id))){EE.add(e.id);try{let t=await J(e),n=new Set(t.filter(r=>r.source==="orchestrator").map(r=>`${r.type}|${r.payload?.ts??"?"}`));for(let r of e.events||[]){let o=Sp(r);!o||n.has(`${o.type}|${o.payload?.ts??"?"}`)||await D(e,o)}}catch{}}}function Vn(e){let{type:t,at:n,...r}=e;return r}function RE(e,t,n){!n?.promptId||vp.get(e.id)===n.promptId||(vp.set(e.id,n.promptId),Ap(()=>D(e,{type:"prompt.raised",actor:"agent",source:"pane",boxId:t?.name,provider:ft(n.provider||t?.agent),payload:{promptId:n.promptId,question:n.question||n.title||null,options:(n.options||[]).map(r=>r?.label??r).slice(0,12)}})))}function OE(e,t,n,r={}){vp.delete(e.id),Ap(()=>D(e,{type:"prompt.dismissed",actor:"user",source:"orchestrator",boxId:t?.name,provider:ft(n?.provider||t?.agent),payload:{promptId:n?.promptId,...r}}))}function dg(e,t,n,r={}){vp.delete(e.id),Ap(()=>D(e,{type:"prompt.answered",actor:"user",source:"orchestrator",boxId:t?.name,provider:ft(n?.provider||t?.agent),payload:{promptId:n?.promptId,...r}}))}var ft,xp,Ap,_E,EE,vp,pg=V(()=>{ke();ft=e=>e||null;xp=Promise.resolve(),Ap=e=>(xp=xp.then(e).catch(()=>{}),xp),_E=()=>xp;EE=new Set;vp=new Map});function l2(e){return String(e).split(/(?<=[.?!])\s+|\n+/).map(t=>t.trim()).filter(Boolean)}function BE(e){let t=String(e||"").trim();if(!t)return null;let n=t.slice(-600);for(let r of l2(n).reverse()){if(!s2.test(r))continue;let o=r.endsWith("?")&&r.length<=c2&&i2.test(r);if(a2.test(r)||o)return r.length>200?r.slice(0,197)+"\u2026":r}return null}function jE(e){let t=String(e||""),n=[];u2.test(t)&&n.push("commit"),LE.test(t)&&n.push("rebase"),d2.test(t)&&n.push("push");let r=f2.test(t);!r&&p2.test(t)&&n.push("pr");let o=null;if(r){let s=t.match(/(?:pr|pull\s+request)\s*\(?\s*#(\d+)\)?/i)||t.match(/#(\d+)/);o={number:s?Number(s[1]):null}}return{offered:n.length?n:null,toPr:o}}function FE(e){return LE.test(String(e||""))}function ei(e,{branch:t=null,base:n=null,toPr:r=null,repos:o=null,offeredRebase:s=!1}={}){Array.isArray(e)||(e=e==="push"?["commit","push"]:["commit","push","pr"]);let a=new Set(e),i=Array.isArray(o)&&o.length>0,c=i?o.map(m=>`${m.name}/`).join(", "):null,l=t?` on this branch (${t})`:"",u=[];if(a.has("commit")&&u.push(i?`commit the work in each changed checkout (${c})${l} with a clear commit message per repo`:`commit the work${l} with a clear commit message`),a.has("rebase")){let m=a.has("commit")?"the branch":`this branch${t?` (${t})`:""}`;u.push(i?`rebase ${m} in each changed checkout (${c}) onto its own base branch (fetch origin first), resolving any conflicts so both sides' intent is preserved`:`rebase ${m} onto ${n?`the latest ${n}`:"its base branch"} (fetch origin first), resolving any conflicts so both sides' intent is preserved`)}if(a.has("push")||a.has("pr")){let m=r&&!a.has("pr")?` (the open PR${r.number?` #${r.number}`:""} picks it up)`:"",w=a.has("rebase")?" with `--force-with-lease` (the rebase rewrote history)":"";i?u.push(a.has("commit")||a.has("rebase")?`push each one to its remote${w}${m}`:`push this branch${t?` (${t})`:""} from each changed checkout (${c}) to its remote${m}`):u.push(a.has("commit")||a.has("rebase")?`push it to the remote${w}${m}`:`push this branch${l} to the remote${m}`)}a.has("pr")&&u.push(i?"open a pull request in each changed repo with a concise title and a description of what changed and why (run `gh pr create` inside each checkout)":`open a pull request${n?` against ${n}`:""} with a concise title and a description of what changed and why (use \`gh pr create\`)`);let d=[];a.has("commit")||d.push("don't create any new commits \u2014 ship what's already committed"),s&&!a.has("rebase")&&d.push("don't rebase \u2014 leave the branch's history as it is"),!a.has("push")&&!a.has("pr")&&d.push("don't push"),a.has("pr")||d.push("don't open a pull request");let p=`Yes \u2014 go ahead: ${u.join(", then ")}.`;return d.length&&(p+=` ${d.join(", and ").replace(/^./,m=>m.toUpperCase())}.`),a.has("pr")&&(p+=i?" If a repo's PR for this branch is already open, just push that repo's update instead.":" If a PR for this branch is already open, just push the update instead."),p}function UE(e,{branch:t=null,base:n=null,prNumber:r=null,offeredRebase:o=!1}={}){let s=new Set(Array.isArray(e)?e:["commit","push","pr"]),a=t?` on this branch (${t})`:"",i=[];s.has("commit")&&i.push(`commit the work${a} with a clear commit message`),s.has("rebase")&&i.push(`rebase ${s.has("commit")?"the branch":`this branch${t?` (${t})`:""}`} onto ${n?`the latest ${n}`:"its base branch"} (fetch origin first), resolving any conflicts so both sides' intent is preserved`),i.push("move the work to a fresh branch (branch off the current HEAD with a clear new name)"),i.push("push the new branch to the remote"),i.push(`open a pull request${n?` against ${n}`:""} from the new branch with a concise title and a description of what changed and why (use \`gh pr create\`)`);let c=[];s.has("commit")||c.push("don't create any new commits \u2014 ship what's already committed"),o&&!s.has("rebase")&&c.push("don't rebase \u2014 leave the branch's history as it is");let l=`Yes \u2014 go ahead, as a NEW pull request: ${i.join(", then ")}.`;return c.length&&(l+=` ${c.join(", and ").replace(/^./,u=>u.toUpperCase())}.`),l+=` Leave the existing open PR${r?` #${r}`:""}${t?` and its remote branch (${t})`:" and its remote branch"} exactly as they are \u2014 don't push ${t||"the old branch"} itself.`,l}function HE(e,t=Date.now()){let n=[],r=null;for(let o of e||[]){let s=o.payload||{},a=s.ts??o.ts;if(o.type==="pr.offer.answered"&&s.action==="pr"){r={box:o.boxId,from:a,lastActivity:a};continue}if(o.type==="pr.exists.answered"&&s.choice==="new"){r={box:o.boxId,from:a,lastActivity:a};continue}!r||a==null||a<r.from||(o.type==="pr.offer.answered"||o.type==="pr.exists.answered"?r=null:o.type==="pr.state.changed"&&s.change==="opened"?(n.push({box:r.box,from:r.from,to:a,settled:!0}),r=null):o.type==="turn.user"&&o.source!=="hook"&&!s.kind&&String(s.text||"").trim()?r=null:o.boxId===r.box&&/^(?:turn|tool)\./.test(o.type)&&(r.lastActivity=Math.max(r.lastActivity,a)))}return r&&t-r.lastActivity<=h2&&n.push({box:r.box,from:r.from,to:t+1e12}),n}function WE(e,t){let n=new Set;for(let r of t||[]){if(!r.settled)continue;let o=null;for(let s of e||[])s.kind!=="message"||s.role!=="assistant"||s.box!==r.box||s.ts==null||s.ts<r.from||s.ts>r.to+m2||(!o||s.ts>=o.ts)&&(o=s);o&&n.add(o)}return n}function qE(e){let t=(Array.isArray(e)?e:[]).filter(r=>ME[r]).map(r=>ME[r]);return`The ship you were given the go-ahead for${t.length?` (${t.join(", then ")})`:""} should now be complete. This is an automated ship notification the operator armed on the offer: carry straight on with this Track's follow-up work (dependent tasks, cleanup, next steps) \u2014 don't wait for review or merge. If a ship step failed or is unfinished, finish the ship first. If nothing needs doing, say so briefly.`}var CE,NE,PE,DE,s2,a2,i2,c2,Eo,u2,LE,d2,p2,f2,h2,m2,ME,Ds=V(()=>{CE=/(?<!\b(?:a|an|the|this|that|another|one|each|any|no|separate|single|new|initial|final|first|second|third|last|later|next|subsequent|extra|additional|amend(?:ed)?|squash|merge|follow[\s-]?up|clean[\s-]?up)\s)commit(?!s\b)(?!\s+(?:history|log|message|hash|sha)s?\b)/.source,NE=/(?<!\b(?:a|an|the|this|that|another|one|each|any|no|separate|single|new|initial|final|first|second|third|last|later|next|subsequent|extra|additional)\s)push(?!\s+notifications?\b)(?:\s+(?:it|this|that|them|everything|the\s+\w+))?\s*(?:up)?/.source,PE=/open(?:\s+up)?\s+(?:a|the|that)\s+(?:draft\s+)?(?:pr|pull\s+request)|creat(?:e|ing)\s+(?:a|the)\s+(?:draft\s+)?(?:pr|pull\s+request)|rais(?:e|ing)\s+(?:a|the)\s+(?:pr|pull\s+request)|put\s+up\s+(?:a|the)\s+(?:pr|pull\s+request)|send\s+(?:up\s+)?(?:a|the)\s+(?:pr|pull\s+request)/.source,DE=/(?<!\b(?:a|an|the|this|that|another|one|each|any|no|clean|interactive)\s)rebase(?!s\b)(?:\s+(?:it|this|that|them|(?:this|that|the)\s+branch))?(?:\s+(?:on(?:to)?|against|atop|over)\s+\S+)?/.source,s2=new RegExp(`\\b(?:${CE}|${NE}|${PE}|${DE})\\b`,"i"),a2=/\b(?:want\s+me\s+to|would\s+you\s+like(?:\s+me)?(?:\s+to)?|should\s+i|shall\s+i|do\s+you\s+want(?:\s+me)?(?:\s+to)?|happy\s+to|ready\s+for\s+me\s+to|let\s+me\s+know\s+(?:if|when|whether|and)|say\s+the\s+word|give\s+me\s+the\s+(?:word|go[\s-]?ahead)|if\s+you(?:'d|\s+would)?\s+(?:like|want|prefer)|just\s+say\s+(?:so|yes|go))\b/i,i2=/^(?:commit|push|open|create|raise|rebase|ready|ok(?:ay)?\s+to|good\s+to)\b/i,c2=90;Eo=["commit","rebase","push","pr"],u2=new RegExp(`\\b(?:${CE})\\b`,"i"),LE=new RegExp(`\\b(?:${DE})\\b`,"i"),d2=new RegExp(`\\b(?:${NE})\\b`,"i"),p2=new RegExp(`\\b(?:${PE})\\b`,"i"),f2=/\b(?:to|into|onto|on|updat(?:e|es|ing))\s+(?:the|that|this)\s+(?:open\s+|existing\s+|current\s+|same\s+)?(?:draft\s+)?(?:pr|pull\s+request)\b/i;h2=3e4;m2=2500;ME={commit:"commit",rebase:"rebase",push:"push",pr:"open a PR"}});import w2 from"node:crypto";import Tp from"node:fs/promises";import GE from"node:path";import g2 from"node:os";function JE(e){zE=typeof e=="function"?e:async()=>new Set}function y2(e,t,n){if(e.originNode&&e.originNode===t)return!0;let r=e.data?.trackId;return!!r&&n.has(r)}async function Ke(){return xr||(fg??=Tp.readFile(mg,"utf8").then(e=>({links:JSON.parse(e)?.links??{},existed:!0})).catch(()=>({links:{},existed:!1})).then(async({links:e,existed:t})=>{if(xr=e,!t&&ze()){let{records:n,source:r}=await wt("prlinks").catch(()=>({records:[],source:"error"}));if(r==="plane"){let o=Sv(),s=await zE().catch(()=>new Set),a=0;for(let i of n){if(i.deletedAt||!i.data?.repo||i.data?.number==null)continue;if(!y2(i,o,s)){a++;continue}let{id:c,updatedAt:l,...u}=i.data;xr[de(u.repo,u.number)]=u}a&&console.log(`[pr-links] restore: ${Object.keys(xr).length} link(s) re-seeded, ${a} other-node record(s) left on the plane`),Object.keys(xr).length&&await wg().catch(()=>{})}}return xr}).finally(()=>fg=null),fg)}async function wg(){let e=JSON.stringify({links:xr},null,2),t=`${mg}.${process.pid}.tmp`;await Tp.mkdir(KE,{recursive:!0}),await Tp.writeFile(t,e),await Tp.rename(t,mg)}async function tt(e){hg=hg.then(wg,wg),await hg.catch(()=>{});let t=xr?.[e];t&&Ct("prlinks",{id:VE(e),updatedAt:Date.now(),...t},{trackId:t.trackId??null}).catch(()=>{})}async function rn({repo:e,number:t,trackId:n,url:r=null,headRef:o=null,title:s=null,source:a="matched"}){if(!e||!Number.isInteger(Number(t))||!n)return{link:null,created:!1};let i=await Ke(),c=de(e,t);return i[c]?{link:i[c],created:!1}:(i[c]={repo:e,number:Number(t),trackId:n,url:r,headRef:o,title:s,source:a,announced:b2.has(a),firstSeen:Date.now()},await tt(de(e,t)),{link:i[c],created:!0})}async function vr(e,t){if(!e||t==null)return null;let n=(await Ke())[de(e,t)];return!n||n.announced?null:(n.announced=!0,await tt(de(e,t)),n)}async function YE(e,t){if(!e||t==null)return!1;let n=(await Ke())[de(e,t)];return n?.notifyOnMerge?(delete n.notifyOnMerge,await tt(de(e,t)),!0):!1}async function bt(e,t){return!e||t==null?null:(await Ke())[de(e,t)]??null}async function _o(e,t,n){if(!e||t==null)return null;let r=(await Ke())[de(e,t)];return r?(r.state=n,r.resolvedAt=Date.now(),delete r.armedAt,delete r.autoMerge,delete r.archiveOnMerge,delete r.notifyOnMerge,delete r.notifyPending,delete r.followupPending,await tt(de(e,t)),r):null}async function XE(e,t,{headSha:n=null,trackId:r=null}={}){if(!e||t==null)return null;let o=(await Ke())[de(e,t)];return o?(o.ciFix={delegatedAt:Date.now(),headSha:n,trackId:r},await tt(de(e,t)),o):null}async function ZE(e,t,{headSha:n=null,trackId:r=null}={}){if(!e||t==null)return null;let o=(await Ke())[de(e,t)];return o?(o.reconcile={delegatedAt:Date.now(),headSha:n,trackId:r},await tt(de(e,t)),o):null}async function Ep(e,t,{headSha:n=null}={}){if(!e||t==null)return null;let r=(await Ke())[de(e,t)];return!r||!r.ciFix?null:(r.ciFixAwait={since:Date.now(),trackId:r.ciFix.trackId??null,headSha:n},delete r.ciFix,await tt(de(e,t)),r)}async function _p(e,t){if(!e||t==null)return null;let n=(await Ke())[de(e,t)];return!n||!n.ciFixAwait?null:(delete n.ciFixAwait,await tt(de(e,t)),n)}async function Ip(e,t,{headSha:n=null}={}){if(!e||t==null)return null;let r=(await Ke())[de(e,t)];return!r||!r.reconcile?null:(r.reconcileAwait={since:Date.now(),trackId:r.reconcile.trackId??null,headSha:n},delete r.reconcile,await tt(de(e,t)),r)}async function $p(e,t){if(!e||t==null)return null;let n=(await Ke())[de(e,t)];return!n||!n.reconcileAwait?null:(delete n.reconcileAwait,await tt(de(e,t)),n)}async function QE(e,t,{at:n=Date.now()}={}){if(!e||t==null)return null;let r=(await Ke())[de(e,t)];return r?(r.baseFoldAt=n,await tt(de(e,t)),r):null}async function e_(e,t,{misses:n,until:r}){if(!e||t==null)return null;let o=(await Ke())[de(e,t)];return o?(o.brokerRefused={misses:Number(n)||0,until:Number(r)||0},await tt(de(e,t)),o):null}async function t_(e,t){if(!e||t==null)return null;let n=(await Ke())[de(e,t)];return n?.brokerRefused?(delete n.brokerRefused,await tt(de(e,t)),n):null}async function n_(e,t){if(!e||t==null)return null;let n=(await Ke())[de(e,t)];return!n||!n.baseFoldAt?null:(delete n.baseFoldAt,await tt(de(e,t)),n)}async function gg(e,t,n){if(!e||t==null||!n)return null;let r=(await Ke())[de(e,t)];return r?(r.lastHeadSha=n,await tt(de(e,t)),r):null}async function r_(e,t,n){if(!e||t==null||!n)return{prev:null,link:null};let r=(await Ke())[de(e,t)];if(!r)return{prev:null,link:null};let o=r.verdict??null;return o&&o.blocked===(n.blocked??null)&&(o.sha??null)===(n.sha??null)||(r.verdict={blocked:n.blocked??null,sha:n.sha??null,at:n.at??Date.now()},await tt(de(e,t))),{prev:o,link:r}}async function il(e,t,{merge:n=null}={}){if(!e||t==null)return null;let r=(await Ke())[de(e,t)];return r?(r.armedAt=Date.now(),n&&(r.autoMerge={method:n.method||"merge",armedAt:r.armedAt}),await tt(de(e,t)),r):null}async function Bs(e,t,n=!0){if(!e||t==null)return null;let r=(await Ke())[de(e,t)];return r?(n?r.archiveOnMerge=!0:delete r.archiveOnMerge,await tt(de(e,t)),r):null}async function Ls(e,t,n=!0){if(!e||t==null)return null;let r=(await Ke())[de(e,t)];return r?(n?r.notifyOnMerge=!0:delete r.notifyOnMerge,await tt(de(e,t)),r):null}async function o_(e,t,n){if(!e||t==null)return null;let r=(await Ke())[de(e,t)];if(!r)return null;r.notifyOnMerge=!0;let o=new Map((r.notifyPending||[]).map(s=>[`${s.repo}#${s.number}`,s]));for(let s of n||[])s&&s.number!=null&&o.set(`${s.repo}#${s.number}`,s);return r.notifyPending=[...o.values()],await tt(de(e,t)),r}async function s_(e,t,n){if(!e||t==null)return null;let r=(await Ke())[de(e,t)];if(!r)return null;let o=new Map((r.followupPending||[]).map(s=>[`${s.repo}#${s.number}`,s]));for(let s of n||[])s&&s.number!=null&&o.set(`${s.repo}#${s.number}`,s);return r.followupPending=[...o.values()],await tt(de(e,t)),r}async function cl(e,t){if(!e||t==null)return null;let n=(await Ke())[de(e,t)];return!n||!n.armedAt&&!n.autoMerge?null:(delete n.armedAt,delete n.autoMerge,delete n.archiveOnMerge,delete n.notifyOnMerge,delete n.notifyPending,delete n.verdict,await tt(de(e,t)),n)}async function a_(){return Object.values(await Ke()).filter(e=>!k2.has(e.state))}async function In(){return Object.values(await Ke()).sort((e,t)=>t.firstSeen-e.firstSeen)}async function i_(){if(!ze())return{pushed:0,source:"unconfigured"};let{records:e,source:t}=await wt("prlinks");if(t!=="plane"||e.length)return{pushed:0,source:t};let n=await Ke(),r=0;for(let[o,s]of Object.entries(n))await Ct("prlinks",{id:VE(o),updatedAt:Date.now(),...s},{trackId:s.trackId??null}).catch(()=>{}),r++;return{pushed:r,source:"plane"}}var KE,mg,de,VE,xr,fg,hg,zE,b2,k2,zn=V(()=>{no();KE=process.env.BOSTRAT_STATE_DIR||GE.join(process.env.HOME||g2.tmpdir(),".bostrat"),mg=GE.join(KE,"pr-links.json"),de=(e,t)=>`${e}#${Number(t)}`,VE=e=>{let t=e.replace(/[^A-Za-z0-9._-]+/g,"-").replace(/^[^A-Za-z0-9]+/,"").slice(0,55),n=w2.createHash("sha256").update(e).digest("hex").slice(0,8);return`${t||"pr"}-${n}`},xr=null,fg=null,hg=Promise.resolve(),zE=async()=>new Set;b2=new Set(["api","observed","reconciled"]);k2=new Set(["merged","closed","lost"])});import x2 from"node:fs";import yg from"node:fs/promises";import d_ from"node:path";import v2 from"node:os";function h_(e,t=!1){if(!t&&e-l_<S2)return;l_=e;let n=JSON.stringify({windowStart:ti,byCaller:Object.fromEntries(Sr),lastHour:Io});u_=u_.then(()=>yg.mkdir(p_,{recursive:!0})).then(()=>yg.writeFile(`${Rp}.tmp`,n)).then(()=>yg.rename(`${Rp}.tmp`,Rp)).catch(()=>{})}function m_(e){e-ti<f_||(Io={start:ti,total:Op(Sr),byCaller:Object.fromEntries(Sr)},Io.total&&console.log(`[github] ${Io.total} calls last hour`,Io.byCaller),ti=e,Sr=new Map,h_(e,!0))}function Ar(e="other",t=Date.now()){m_(t),Sr.set(e,(Sr.get(e)||0)+1),h_(t)}function w_(e=Date.now()){return m_(e),{windowStart:ti,total:Op(Sr),byCaller:Object.fromEntries(Sr),lastHour:Io,backoffUntil:js>e?js:null}}function $o(e){return A2.test(String(e?.message||e||""))}function Ro(e,t=Date.now()){return js<=t&&console.warn(`[github] rate limited \u2014 backing off ${c_/6e4} min:`,String(e?.message||e||"").slice(0,200)),js=Math.max(js,t+c_),js}function Mp(e=Date.now()){return Math.max(0,js-e)}var p_,Rp,f_,c_,S2,ti,Sr,Io,js,l_,Op,u_,A2,ll=V(()=>{p_=process.env.BOSTRAT_STATE_DIR||d_.join(process.env.HOME||v2.tmpdir(),".bostrat"),Rp=d_.join(p_,"github-metrics.json"),f_=60*6e4,c_=5*6e4,S2=6e4,ti=Date.now(),Sr=new Map,Io=null,js=0,l_=0,Op=e=>[...e.values()].reduce((t,n)=>t+n,0);try{let e=JSON.parse(x2.readFileSync(Rp,"utf8"));e?.windowStart&&(Date.now()-e.windowStart<f_?(ti=e.windowStart,Sr=new Map(Object.entries(e.byCaller||{})),Io=e.lastHour||null):Op(new Map(Object.entries(e.byCaller||{})))&&(Io={start:e.windowStart,total:Op(new Map(Object.entries(e.byCaller||{}))),byCaller:e.byCaller||{}}))}catch{}u_=Promise.resolve();A2=/rate limit|too quickly|abuse detection|HTTP 429/i});import g_ from"node:fs/promises";import y_ from"node:path";import T2 from"node:os";function ul({change:e,repo:t=null,number:n=null,githubAt:r=null,observedAt:o=Date.now(),lane:s=null,intervalMs:a=null,source:i=null}){let c=r?o-r:null,l={change:e,repo:t,number:n,githubAt:r,observedAt:o,latencyMs:c,lane:s,intervalMs:a,source:i};Cp.push(l),Cp.length>_2&&Cp.shift();let u=bg.get(e)||{count:0,measured:0,totalMs:0,maxMs:0};return u.count+=1,c!=null&&(u.measured+=1,u.totalMs+=c,u.maxMs=Math.max(u.maxMs,c)),bg.set(e,u),I2(l),l}async function I2(e){try{await g_.mkdir(b_,{recursive:!0}),await g_.appendFile(E2,JSON.stringify(e)+`
192
+ `),n=t.findIndex(s=>/Available models|Models matching/i.test(s));if(n<0)return null;let r=/Models matching/i.test(t[n]),o=[];for(let s=n+1;s<t.length;s++){let a=t[s];if(/^\s*Filter:/i.test(a)||!a.trim())continue;if(/to filter|Enter to select|^\s*\d+-\d+ of \d+/i.test(a))break;let i=a.match(/^\s*(→\s+)?(.+?)\s*$/);if(!i)continue;let c=i[2].replace(/\s*\(Tab to modify\)\s*$/i,""),l=null,u=c.split(/\s{2,}/);u.length>1&&(c=u[0],l=u.slice(1).join(" ").trim()||null),c&&o.push({label:c.trim(),params:l,active:!!i[1]})}return o.length?{filtered:r,rows:o}:null}function SE(e,t){if(typeof t!="string"||!t.trim())throw new Error("model (string) required");let n=t.trim();if(e==="codex"){let[r,o]=n.split(/[\s:]+/);if(o&&!xE.has(o))throw new Error(`unknown codex effort "${o}" (low | medium | high | xhigh)`);return{model:r,effort:o||null}}if(e==="cursor"){let r=vE.find(o=>o.alias===n);return{model:n,filter:r?r.label:n}}if(!X4.has(n))throw new Error(`unknown model "${n}"`);return{model:n}}async function al(e,t,{timeoutMs:n=J4}={}){let r=Date.now()+n;for(;;){let o=await Le(e,{lines:80}).catch(()=>""),s=t(o);if(s)return s;if(Date.now()>r)return null;await kp(Y4)}}async function e2(e,t){return await Ze(e,`/model ${t.model}`,qn("claude")),{verified:!1,note:"confirmed when the next turn's transcript model flips"}}async function t2(e,t){await Ed(e),await Ze(e,"/model",{enter:!1}),await kp(250),await Je(e,["Enter"],{kind:"model-switch"});let n=await al(e,gE);if(!n)throw new Error("codex model picker didn't open");let r=n.find(i=>i.id===t.model);if(!r)throw await Je(e,["Escape"],{kind:"model-switch"}).catch(()=>{}),new Error(`unknown model "${t.model}" \u2014 codex offers: ${n.map(i=>i.id).join(", ")}`);let o=i=>{let c=Q4(i);return!c||c.model!==t.model||t.effort&&c.effort&&c.effort.toLowerCase()!==t.effort.toLowerCase()?null:c};await Ze(e,String(r.n),{enter:!1,kind:"model-switch"});let s=await al(e,i=>yE(i)||!gE(i)&&o(i)&&{done:o(i)});if(!s)throw await Je(e,["Escape"],{kind:"model-switch"}).catch(()=>{}),new Error("codex reasoning-level picker didn't open");if(!s.done){let i=t.effort?xE.get(t.effort):null,c=i?s.find(l=>l.label.toLowerCase()===i.toLowerCase()):s.find(l=>l.isDefault)||s[0];if(!c)throw await Je(e,["Escape","Escape"],{kind:"model-switch"}).catch(()=>{}),new Error(`codex doesn't offer effort "${t.effort}" for ${t.model}`);await Ze(e,String(c.n),{enter:!1,kind:"model-switch"})}let a=s.done||await al(e,i=>!yE(i)&&o(i));if(!a)throw new Error("codex never confirmed the model change");return{verified:!0,model:a.model,effort:a.effort}}async function n2(){let e=wE.join(process.env.CURSOR_CONFIG_DIR||wE.join(z4.homedir(),".cursor"),"cli-config.json");try{return JSON.parse(await V4.readFile(e,"utf8"))?.model||null}catch{return null}}async function r2(e,t){await Ed(e),await Id(e,`/model ${t.filter}`,{kind:"model-switch"});let n=await al(e,bE),r=c=>String(c||"").toLowerCase(),o=c=>r(c.label).startsWith(r(t.filter)),s=n?.rows.find(c=>c.active)||null;if(n&&!(s&&o(s)))for(let c=0;c<12;c++){let l=await al(e,bE,{timeoutMs:1500});if(s=l?.rows.find(u=>u.active)||null,s&&o(s))break;if(!l||!l.rows.some(o)){s=null;break}await Je(e,["Down"],{kind:"model-switch"}),await kp(250)}if(!n||!s||!o(s)){await Je(e,["Escape"],{kind:"model-switch"}).catch(()=>{});let c=Array(`/model ${t.filter}`.length).fill("BSpace");throw await Je(e,c,{settleMs:15,kind:"model-switch"}).catch(()=>{}),new Error(n?`cursor picker has no model matching "${t.filter}"`:"cursor model picker didn't open")}await Je(e,["Enter"],{kind:"model-switch"}),await kp(800);let a=await n2();return{verified:!!a&&(a.modelId===t.model||a.displayModelId===t.model||r(a.displayName).startsWith(r(t.filter))),model:a?.modelId||null,note:"cursor applies this as the global default for new sessions too"}}async function AE(e,t,n){return e==="codex"?t2(t,n):e==="cursor"?r2(t,n):e2(t,n)}var kp,J4,Y4,kE,X4,Z4,xE,vE,TE=V(()=>{mt();Yc();kp=e=>new Promise(t=>setTimeout(t,e)),J4=Number(process.env.BOSTRAT_MODEL_PICKER_TIMEOUT_MS)||8e3,Y4=300,kE=[{alias:"default",label:"Default"},{alias:"opus",label:"Opus 5"},{alias:"sonnet",label:"Sonnet 5"},{alias:"haiku",label:"Haiku 4.5"},{alias:"fable",label:"Fable 5.1"},{alias:"opusplan",label:"Opus Plan"}],X4=new Set([...kE.map(e=>e.alias),"best","opus[1m]","sonnet[1m]","claude-opus-5","claude-opus-4-8","claude-sonnet-5","claude-sonnet-4-6","claude-haiku-4-5","claude-fable-5","claude-fable-5-1"]),Z4=[{alias:"gpt-5.6-sol",label:"GPT-5.6 Sol"},{alias:"gpt-5.6-terra",label:"GPT-5.6 Terra"},{alias:"gpt-5.6-luna",label:"GPT-5.6 Luna"},{alias:"gpt-5.5",label:"GPT-5.5"},{alias:"gpt-5.3-codex",label:"Codex 5.3"}],xE=new Map([["low","Low"],["medium","Medium"],["high","High"],["xhigh","Extra high"]]),vE=[{alias:"auto",label:"Auto"},{alias:"composer-2.5",label:"Composer 2.5"},{alias:"claude-opus-5-high",label:"Opus 5"},{alias:"claude-fable-5-1-high",label:"Fable 5.1"},{alias:"claude-sonnet-5-high",label:"Sonnet 5"},{alias:"cursor-grok-4.6-high",label:"Cursor Grok 4.6"},{alias:"gpt-5.6-sol-high",label:"GPT-5.6 Sol High"},{alias:"gpt-5.3-codex",label:"Codex 5.3"}]});function Sp(e){let t=e||{},n=o2(t);return n&&(n.payload={ts:t.at,...n.payload}),n}function o2(e){switch(e.type){case"said":return{type:"turn.user",actor:"user",source:"orchestrator",boxId:e.box,provider:ft(e.agent),payload:{text:e.text,boxRole:e.boxRole,...e.kind?{kind:e.kind}:{},...e.attachments?.length?{attachments:e.attachments}:{},...e.deliveryId?{deliveryId:e.deliveryId}:{}}};case"unsaid":return{type:"turn.retracted",actor:"user",source:"orchestrator",boxId:e.box,provider:ft(e.agent),payload:{saidTs:e.saidTs,text:e.text,boxRole:e.boxRole}};case"orchestration-prompt":return{type:"turn.user",actor:"orchestrator",source:"orchestrator",boxId:e.box,provider:ft(e.agent),payload:{text:e.prompt,kind:e.kind,boxRole:e.boxRole,...e.deliveryId?{deliveryId:e.deliveryId}:{},...e.detail?{detail:e.detail}:{}}};case"lead-handoff":return{type:"handoff.done",actor:"orchestrator",source:"orchestrator",boxId:e.to,provider:ft(e.toAgent),payload:{from:e.from,fromAgent:e.fromAgent,to:e.to,toAgent:e.toAgent,reason:e.reason,handoffStartedAt:e.handoffStartedAt,fromSessionId:e.fromSessionId,toSessionId:e.toSessionId,epoch:e.epoch,singleBox:e.singleBox,forced:e.forced,recovered:e.recovered,checkpoint:e.checkpoint,cliVersion:e.cliVersion??null,...e.standing?{standing:e.standing}:{}}};case"lead-handoff-failed":return{type:"handoff.failed",actor:"orchestrator",source:"orchestrator",boxId:e.box,provider:ft(e.toAgent),payload:{box:e.box,fromAgent:e.fromAgent,toAgent:e.toAgent,reason:e.reason,error:e.error,rolledBack:e.rolledBack,handoffStartedAt:e.handoffStartedAt}};case"subtask-delegated":return{type:"subtask.delegated",actor:"orchestrator",source:"orchestrator",boxId:e.to,provider:ft(e.toAgent),payload:{task:e.task,subtaskId:e.subtaskId,reason:e.reason}};case"subtask-merged":return{type:"subtask.merged",actor:"orchestrator",source:"orchestrator",boxId:e.box||e.from,provider:ft(e.agent),payload:{...Vn(e)}};case"subtask-failed":return{type:"error",actor:"system",source:"orchestrator",boxId:e.box||e.to,provider:ft(e.agent||e.toAgent),payload:{kind:"subtask-failed",...Vn(e)}};case"subtask-resumed":return{type:"box.state.changed",actor:"orchestrator",source:"orchestrator",boxId:e.box,provider:ft(e.agent),payload:{change:"subtask-resumed",...Vn(e)}};case"model-change":return{type:"box.state.changed",actor:"user",source:"orchestrator",boxId:e.box,payload:{change:"model",model:e.to,from:e.from??null,verified:e.verified??null}};case"codex-update":return{type:"box.state.changed",actor:"orchestrator",source:"orchestrator",boxId:e.box,provider:"codex",payload:{change:"cli-update",from:e.from??null,to:e.to??null,status:e.status,...e.error?{error:e.error}:{}}};case"node-update":return{type:"box.state.changed",actor:"orchestrator",source:"orchestrator",payload:{change:"node-update",...Vn(e)}};case"opened":return{type:"box.state.changed",actor:"user",source:"orchestrator",boxId:e.box,payload:{change:"opened",...Vn(e)}};case"archived":case"unarchived":case"track-deleted":case"renamed":return{type:"box.state.changed",actor:"user",source:"orchestrator",payload:{change:e.type,...Vn(e)}};case"rehydrated":return{type:"box.state.changed",actor:"orchestrator",source:"orchestrator",boxId:e.box,provider:ft(e.agent),payload:{change:"rehydrated",...e.fresh?{fresh:!0}:{}}};case"lead-refreshed":return{type:"box.state.changed",actor:"orchestrator",source:"orchestrator",boxId:e.box,provider:ft(e.agent),payload:{change:"lead-refreshed",box:e.box,agent:e.agent,fromSessionId:e.fromSessionId,toSessionId:e.toSessionId,epoch:e.epoch,reason:e.reason,cliVersion:e.cliVersion??null,...e.standing?{standing:e.standing}:{}}};case"transferred-in":return{type:e.mode==="recover"?"track.recovered":"track.transferred",actor:"orchestrator",source:"orchestrator",boxId:e.box,provider:ft(e.agent),payload:{...Vn(e)}};case"transferred-out":return null;case"retagged":return{type:"box.state.changed",actor:"user",source:"orchestrator",payload:{change:"retagged",...Vn(e)}};case"retag-failed":return{type:"error",actor:"orchestrator",source:"orchestrator",boxId:e.box,provider:ft(e.agent),payload:{kind:"retag-failed",action:e.action??"reshape",reason:e.reason,rolledBack:e.rolledBack!==!1,...e.recovered?{recovered:!0}:{}}};case"rehydrate-failed":return{type:"error",actor:"system",source:"orchestrator",boxId:e.box,provider:ft(e.agent),payload:{kind:"rehydrate-failed",reason:e.reason}};case"delivery-held":return{type:"error",actor:"system",source:"orchestrator",boxId:e.box,provider:ft(e.agent),payload:{kind:"delivery-held",...Vn(e)}};case"startup-gate":return{type:"error",actor:"system",source:"orchestrator",boxId:e.box,provider:ft(e.agent),payload:{kind:"startup-gate",...Vn(e)}};default:return null}}function IE(e,t){let n=Sp(t);if(!n)return;let r=t?.type==="track-deleted"?{id:e.id}:e;Ap(()=>D(r,n))}async function $E(e){if(!(!e?.id||EE.has(e.id))){EE.add(e.id);try{let t=await J(e),n=new Set(t.filter(r=>r.source==="orchestrator").map(r=>`${r.type}|${r.payload?.ts??"?"}`));for(let r of e.events||[]){let o=Sp(r);!o||n.has(`${o.type}|${o.payload?.ts??"?"}`)||await D(e,o)}}catch{}}}function Vn(e){let{type:t,at:n,...r}=e;return r}function RE(e,t,n){!n?.promptId||vp.get(e.id)===n.promptId||(vp.set(e.id,n.promptId),Ap(()=>D(e,{type:"prompt.raised",actor:"agent",source:"pane",boxId:t?.name,provider:ft(n.provider||t?.agent),payload:{promptId:n.promptId,question:n.question||n.title||null,options:(n.options||[]).map(r=>r?.label??r).slice(0,12)}})))}function OE(e,t,n,r={}){vp.delete(e.id),Ap(()=>D(e,{type:"prompt.dismissed",actor:"user",source:"orchestrator",boxId:t?.name,provider:ft(n?.provider||t?.agent),payload:{promptId:n?.promptId,...r}}))}function dg(e,t,n,r={}){vp.delete(e.id),Ap(()=>D(e,{type:"prompt.answered",actor:"user",source:"orchestrator",boxId:t?.name,provider:ft(n?.provider||t?.agent),payload:{promptId:n?.promptId,...r}}))}var ft,xp,Ap,_E,EE,vp,pg=V(()=>{ke();ft=e=>e||null;xp=Promise.resolve(),Ap=e=>(xp=xp.then(e).catch(()=>{}),xp),_E=()=>xp;EE=new Set;vp=new Map});function l2(e){return String(e).split(/(?<=[.?!])\s+|\n+/).map(t=>t.trim()).filter(Boolean)}function BE(e){let t=String(e||"").trim();if(!t)return null;let n=t.slice(-600);for(let r of l2(n).reverse()){if(!s2.test(r))continue;let o=r.endsWith("?")&&r.length<=c2&&i2.test(r);if(a2.test(r)||o)return r.length>200?r.slice(0,197)+"\u2026":r}return null}function jE(e){let t=String(e||""),n=[];u2.test(t)&&n.push("commit"),LE.test(t)&&n.push("rebase"),d2.test(t)&&n.push("push");let r=f2.test(t);!r&&p2.test(t)&&n.push("pr");let o=null;if(r){let s=t.match(/(?:pr|pull\s+request)\s*\(?\s*#(\d+)\)?/i)||t.match(/#(\d+)/);o={number:s?Number(s[1]):null}}return{offered:n.length?n:null,toPr:o}}function FE(e){return LE.test(String(e||""))}function ei(e,{branch:t=null,base:n=null,toPr:r=null,repos:o=null,offeredRebase:s=!1}={}){Array.isArray(e)||(e=e==="push"?["commit","push"]:["commit","push","pr"]);let a=new Set(e),i=Array.isArray(o)&&o.length>0,c=i?o.map(m=>`${m.name}/`).join(", "):null,l=t?` on this branch (${t})`:"",u=[];if(a.has("commit")&&u.push(i?`commit the work in each changed checkout (${c})${l} with a clear commit message per repo`:`commit the work${l} with a clear commit message`),a.has("rebase")){let m=a.has("commit")?"the branch":`this branch${t?` (${t})`:""}`;u.push(i?`rebase ${m} in each changed checkout (${c}) onto its own base branch (fetch origin first), resolving any conflicts so both sides' intent is preserved`:`rebase ${m} onto ${n?`the latest ${n}`:"its base branch"} (fetch origin first), resolving any conflicts so both sides' intent is preserved`)}if(a.has("push")||a.has("pr")){let m=r&&!a.has("pr")?` (the open PR${r.number?` #${r.number}`:""} picks it up)`:"",w=a.has("rebase")?" with `--force-with-lease` (the rebase rewrote history)":"";i?u.push(a.has("commit")||a.has("rebase")?`push each one to its remote${w}${m}`:`push this branch${t?` (${t})`:""} from each changed checkout (${c}) to its remote${m}`):u.push(a.has("commit")||a.has("rebase")?`push it to the remote${w}${m}`:`push this branch${l} to the remote${m}`)}a.has("pr")&&u.push(i?"open a pull request in each changed repo with a concise title and a description of what changed and why (run `gh pr create` inside each checkout)":`open a pull request${n?` against ${n}`:""} with a concise title and a description of what changed and why (use \`gh pr create\`)`);let d=[];a.has("commit")||d.push("don't create any new commits \u2014 ship what's already committed"),s&&!a.has("rebase")&&d.push("don't rebase \u2014 leave the branch's history as it is"),!a.has("push")&&!a.has("pr")&&d.push("don't push"),a.has("pr")||d.push("don't open a pull request");let p=`Yes \u2014 go ahead: ${u.join(", then ")}.`;return d.length&&(p+=` ${d.join(", and ").replace(/^./,m=>m.toUpperCase())}.`),a.has("pr")&&(p+=i?" If a repo's PR for this branch is already open, just push that repo's update instead.":" If a PR for this branch is already open, just push the update instead."),p}function UE(e,{branch:t=null,base:n=null,prNumber:r=null,offeredRebase:o=!1}={}){let s=new Set(Array.isArray(e)?e:["commit","push","pr"]),a=t?` on this branch (${t})`:"",i=[];s.has("commit")&&i.push(`commit the work${a} with a clear commit message`),s.has("rebase")&&i.push(`rebase ${s.has("commit")?"the branch":`this branch${t?` (${t})`:""}`} onto ${n?`the latest ${n}`:"its base branch"} (fetch origin first), resolving any conflicts so both sides' intent is preserved`),i.push("move the work to a fresh branch (branch off the current HEAD with a clear new name)"),i.push("push the new branch to the remote"),i.push(`open a pull request${n?` against ${n}`:""} from the new branch with a concise title and a description of what changed and why (use \`gh pr create\`)`);let c=[];s.has("commit")||c.push("don't create any new commits \u2014 ship what's already committed"),o&&!s.has("rebase")&&c.push("don't rebase \u2014 leave the branch's history as it is");let l=`Yes \u2014 go ahead, as a NEW pull request: ${i.join(", then ")}.`;return c.length&&(l+=` ${c.join(", and ").replace(/^./,u=>u.toUpperCase())}.`),l+=` Leave the existing open PR${r?` #${r}`:""}${t?` and its remote branch (${t})`:" and its remote branch"} exactly as they are \u2014 don't push ${t||"the old branch"} itself.`,l}function HE(e,t=Date.now()){let n=[],r=null;for(let o of e||[]){let s=o.payload||{},a=s.ts??o.ts;if(o.type==="pr.offer.answered"&&s.action==="pr"){r={box:o.boxId,from:a,lastActivity:a};continue}if(o.type==="pr.exists.answered"&&s.choice==="new"){r={box:o.boxId,from:a,lastActivity:a};continue}!r||a==null||a<r.from||(o.type==="pr.offer.answered"||o.type==="pr.exists.answered"?r=null:o.type==="pr.state.changed"&&s.change==="opened"?(n.push({box:r.box,from:r.from,to:a,settled:!0}),r=null):o.type==="turn.user"&&o.source!=="hook"&&!s.kind&&String(s.text||"").trim()?r=null:o.boxId===r.box&&/^(?:turn|tool)\./.test(o.type)&&(r.lastActivity=Math.max(r.lastActivity,a)))}return r&&t-r.lastActivity<=h2&&n.push({box:r.box,from:r.from,to:t+1e12}),n}function WE(e,t){let n=new Set;for(let r of t||[]){if(!r.settled)continue;let o=null;for(let s of e||[])s.kind!=="message"||s.role!=="assistant"||s.box!==r.box||s.ts==null||s.ts<r.from||s.ts>r.to+m2||(!o||s.ts>=o.ts)&&(o=s);o&&n.add(o)}return n}function qE(e){let t=(Array.isArray(e)?e:[]).filter(r=>ME[r]).map(r=>ME[r]);return`The ship you were given the go-ahead for${t.length?` (${t.join(", then ")})`:""} should now be complete. This is an automated ship notification the operator armed on the offer: carry straight on with this Track's follow-up work (dependent tasks, cleanup, next steps) \u2014 don't wait for review or merge. If a ship step failed or is unfinished, finish the ship first. If nothing needs doing, say so briefly.`}var CE,NE,PE,DE,s2,a2,i2,c2,Eo,u2,LE,d2,p2,f2,h2,m2,ME,Ds=V(()=>{CE=/(?<!\b(?:a|an|the|this|that|another|one|each|any|no|separate|single|new|initial|final|first|second|third|last|later|next|subsequent|extra|additional|amend(?:ed)?|squash|merge|follow[\s-]?up|clean[\s-]?up)\s)commit(?!s\b)(?!\s+(?:history|log|message|hash|sha)s?\b)/.source,NE=/(?<!\b(?:a|an|the|this|that|another|one|each|any|no|separate|single|new|initial|final|first|second|third|last|later|next|subsequent|extra|additional)\s)push(?!\s+notifications?\b)(?:\s+(?:it|this|that|them|everything|the\s+\w+))?\s*(?:up)?/.source,PE=/open(?:\s+up)?\s+(?:a|the|that)\s+(?:draft\s+)?(?:pr|pull\s+request)|creat(?:e|ing)\s+(?:a|the)\s+(?:draft\s+)?(?:pr|pull\s+request)|rais(?:e|ing)\s+(?:a|the)\s+(?:pr|pull\s+request)|put\s+up\s+(?:a|the)\s+(?:pr|pull\s+request)|send\s+(?:up\s+)?(?:a|the)\s+(?:pr|pull\s+request)/.source,DE=/(?<!\b(?:a|an|the|this|that|another|one|each|any|no|clean|interactive)\s)rebase(?!s\b)(?:\s+(?:it|this|that|them|(?:this|that|the)\s+branch))?(?:\s+(?:on(?:to)?|against|atop|over)\s+\S+)?/.source,s2=new RegExp(`\\b(?:${CE}|${NE}|${PE}|${DE})\\b`,"i"),a2=/\b(?:want\s+me\s+to|would\s+you\s+like(?:\s+me)?(?:\s+to)?|should\s+i|shall\s+i|do\s+you\s+want(?:\s+me)?(?:\s+to)?|happy\s+to|ready\s+for\s+me\s+to|let\s+me\s+know\s+(?:if|when|whether|and)|say\s+the\s+word|give\s+me\s+the\s+(?:word|go[\s-]?ahead)|if\s+you(?:'d|\s+would)?\s+(?:like|want|prefer)|just\s+say\s+(?:so|yes|go))\b/i,i2=/^(?:commit|push|open|create|raise|rebase|ready|ok(?:ay)?\s+to|good\s+to)\b/i,c2=90;Eo=["commit","rebase","push","pr"],u2=new RegExp(`\\b(?:${CE})\\b`,"i"),LE=new RegExp(`\\b(?:${DE})\\b`,"i"),d2=new RegExp(`\\b(?:${NE})\\b`,"i"),p2=new RegExp(`\\b(?:${PE})\\b`,"i"),f2=/\b(?:to|into|onto|on|updat(?:e|es|ing))\s+(?:the|that|this)\s+(?:open\s+|existing\s+|current\s+|same\s+)?(?:draft\s+)?(?:pr|pull\s+request)\b/i;h2=3e4;m2=2500;ME={commit:"commit",rebase:"rebase",push:"push",pr:"open a PR"}});import w2 from"node:crypto";import Tp from"node:fs/promises";import GE from"node:path";import g2 from"node:os";function JE(e){zE=typeof e=="function"?e:async()=>new Set}function y2(e,t,n){if(e.originNode&&e.originNode===t)return!0;let r=e.data?.trackId;return!!r&&n.has(r)}async function Ke(){return xr||(fg??=Tp.readFile(mg,"utf8").then(e=>({links:JSON.parse(e)?.links??{},existed:!0})).catch(()=>({links:{},existed:!1})).then(async({links:e,existed:t})=>{if(xr=e,!t&&ze()){let{records:n,source:r}=await wt("prlinks").catch(()=>({records:[],source:"error"}));if(r==="plane"){let o=Sv(),s=await zE().catch(()=>new Set),a=0;for(let i of n){if(i.deletedAt||!i.data?.repo||i.data?.number==null)continue;if(!y2(i,o,s)){a++;continue}let{id:c,updatedAt:l,...u}=i.data;xr[de(u.repo,u.number)]=u}a&&console.log(`[pr-links] restore: ${Object.keys(xr).length} link(s) re-seeded, ${a} other-node record(s) left on the plane`),Object.keys(xr).length&&await wg().catch(()=>{})}}return xr}).finally(()=>fg=null),fg)}async function wg(){let e=JSON.stringify({links:xr},null,2),t=`${mg}.${process.pid}.tmp`;await Tp.mkdir(KE,{recursive:!0}),await Tp.writeFile(t,e),await Tp.rename(t,mg)}async function tt(e){hg=hg.then(wg,wg),await hg.catch(()=>{});let t=xr?.[e];t&&Ct("prlinks",{id:VE(e),updatedAt:Date.now(),...t},{trackId:t.trackId??null}).catch(()=>{})}async function rn({repo:e,number:t,trackId:n,url:r=null,headRef:o=null,title:s=null,source:a="matched"}){if(!e||!Number.isInteger(Number(t))||!n)return{link:null,created:!1};let i=await Ke(),c=de(e,t);return i[c]?{link:i[c],created:!1}:(i[c]={repo:e,number:Number(t),trackId:n,url:r,headRef:o,title:s,source:a,announced:b2.has(a),firstSeen:Date.now()},await tt(de(e,t)),{link:i[c],created:!0})}async function vr(e,t){if(!e||t==null)return null;let n=(await Ke())[de(e,t)];return!n||n.announced?null:(n.announced=!0,await tt(de(e,t)),n)}async function YE(e,t){if(!e||t==null)return!1;let n=(await Ke())[de(e,t)];return n?.notifyOnMerge?(delete n.notifyOnMerge,await tt(de(e,t)),!0):!1}async function bt(e,t){return!e||t==null?null:(await Ke())[de(e,t)]??null}async function _o(e,t,n){if(!e||t==null)return null;let r=(await Ke())[de(e,t)];return r?(r.state=n,r.resolvedAt=Date.now(),delete r.armedAt,delete r.autoMerge,delete r.archiveOnMerge,delete r.notifyOnMerge,delete r.notifyPending,delete r.followupPending,await tt(de(e,t)),r):null}async function XE(e,t,{headSha:n=null,trackId:r=null}={}){if(!e||t==null)return null;let o=(await Ke())[de(e,t)];return o?(o.ciFix={delegatedAt:Date.now(),headSha:n,trackId:r},await tt(de(e,t)),o):null}async function ZE(e,t,{headSha:n=null,trackId:r=null}={}){if(!e||t==null)return null;let o=(await Ke())[de(e,t)];return o?(o.reconcile={delegatedAt:Date.now(),headSha:n,trackId:r},await tt(de(e,t)),o):null}async function Ep(e,t,{headSha:n=null}={}){if(!e||t==null)return null;let r=(await Ke())[de(e,t)];return!r||!r.ciFix?null:(r.ciFixAwait={since:Date.now(),trackId:r.ciFix.trackId??null,headSha:n},delete r.ciFix,await tt(de(e,t)),r)}async function _p(e,t){if(!e||t==null)return null;let n=(await Ke())[de(e,t)];return!n||!n.ciFixAwait?null:(delete n.ciFixAwait,await tt(de(e,t)),n)}async function Ip(e,t,{headSha:n=null}={}){if(!e||t==null)return null;let r=(await Ke())[de(e,t)];return!r||!r.reconcile?null:(r.reconcileAwait={since:Date.now(),trackId:r.reconcile.trackId??null,headSha:n},delete r.reconcile,await tt(de(e,t)),r)}async function $p(e,t){if(!e||t==null)return null;let n=(await Ke())[de(e,t)];return!n||!n.reconcileAwait?null:(delete n.reconcileAwait,await tt(de(e,t)),n)}async function QE(e,t,{at:n=Date.now()}={}){if(!e||t==null)return null;let r=(await Ke())[de(e,t)];return r?(r.baseFoldAt=n,await tt(de(e,t)),r):null}async function e_(e,t,{misses:n,until:r}){if(!e||t==null)return null;let o=(await Ke())[de(e,t)];return o?(o.brokerRefused={misses:Number(n)||0,until:Number(r)||0},await tt(de(e,t)),o):null}async function t_(e,t){if(!e||t==null)return null;let n=(await Ke())[de(e,t)];return n?.brokerRefused?(delete n.brokerRefused,await tt(de(e,t)),n):null}async function n_(e,t){if(!e||t==null)return null;let n=(await Ke())[de(e,t)];return!n||!n.baseFoldAt?null:(delete n.baseFoldAt,await tt(de(e,t)),n)}async function gg(e,t,n){if(!e||t==null||!n)return null;let r=(await Ke())[de(e,t)];return r?(r.lastHeadSha=n,await tt(de(e,t)),r):null}async function r_(e,t,n){if(!e||t==null||!n)return{prev:null,link:null};let r=(await Ke())[de(e,t)];if(!r)return{prev:null,link:null};let o=r.verdict??null;return o&&o.blocked===(n.blocked??null)&&(o.sha??null)===(n.sha??null)||(r.verdict={blocked:n.blocked??null,sha:n.sha??null,at:n.at??Date.now()},await tt(de(e,t))),{prev:o,link:r}}async function il(e,t,{merge:n=null}={}){if(!e||t==null)return null;let r=(await Ke())[de(e,t)];return r?(r.armedAt=Date.now(),n&&(r.autoMerge={method:n.method||"merge",armedAt:r.armedAt}),await tt(de(e,t)),r):null}async function Bs(e,t,n=!0){if(!e||t==null)return null;let r=(await Ke())[de(e,t)];return r?(n?r.archiveOnMerge=!0:delete r.archiveOnMerge,await tt(de(e,t)),r):null}async function Ls(e,t,n=!0){if(!e||t==null)return null;let r=(await Ke())[de(e,t)];return r?(n?r.notifyOnMerge=!0:delete r.notifyOnMerge,await tt(de(e,t)),r):null}async function o_(e,t,n){if(!e||t==null)return null;let r=(await Ke())[de(e,t)];if(!r)return null;r.notifyOnMerge=!0;let o=new Map((r.notifyPending||[]).map(s=>[`${s.repo}#${s.number}`,s]));for(let s of n||[])s&&s.number!=null&&o.set(`${s.repo}#${s.number}`,s);return r.notifyPending=[...o.values()],await tt(de(e,t)),r}async function s_(e,t,n){if(!e||t==null)return null;let r=(await Ke())[de(e,t)];if(!r)return null;let o=new Map((r.followupPending||[]).map(s=>[`${s.repo}#${s.number}`,s]));for(let s of n||[])s&&s.number!=null&&o.set(`${s.repo}#${s.number}`,s);return r.followupPending=[...o.values()],await tt(de(e,t)),r}async function cl(e,t){if(!e||t==null)return null;let n=(await Ke())[de(e,t)];return!n||!n.armedAt&&!n.autoMerge?null:(delete n.armedAt,delete n.autoMerge,delete n.archiveOnMerge,delete n.notifyOnMerge,delete n.notifyPending,delete n.verdict,await tt(de(e,t)),n)}async function a_(){return Object.values(await Ke()).filter(e=>!k2.has(e.state))}async function In(){return Object.values(await Ke()).sort((e,t)=>t.firstSeen-e.firstSeen)}async function i_(){if(!ze())return{pushed:0,source:"unconfigured"};let{records:e,source:t}=await wt("prlinks");if(t!=="plane"||e.length)return{pushed:0,source:t};let n=await Ke(),r=0;for(let[o,s]of Object.entries(n))await Ct("prlinks",{id:VE(o),updatedAt:Date.now(),...s},{trackId:s.trackId??null}).catch(()=>{}),r++;return{pushed:r,source:"plane"}}var KE,mg,de,VE,xr,fg,hg,zE,b2,k2,zn=V(()=>{no();KE=process.env.BOSTRAT_STATE_DIR||GE.join(process.env.HOME||g2.tmpdir(),".bostrat"),mg=GE.join(KE,"pr-links.json"),de=(e,t)=>`${e}#${Number(t)}`,VE=e=>{let t=e.replace(/[^A-Za-z0-9._-]+/g,"-").replace(/^[^A-Za-z0-9]+/,"").slice(0,55),n=w2.createHash("sha256").update(e).digest("hex").slice(0,8);return`${t||"pr"}-${n}`},xr=null,fg=null,hg=Promise.resolve(),zE=async()=>new Set;b2=new Set(["api","observed","reconciled"]);k2=new Set(["merged","closed","lost"])});import x2 from"node:fs";import yg from"node:fs/promises";import d_ from"node:path";import v2 from"node:os";function h_(e,t=!1){if(!t&&e-l_<S2)return;l_=e;let n=JSON.stringify({windowStart:ti,byCaller:Object.fromEntries(Sr),lastHour:Io});u_=u_.then(()=>yg.mkdir(p_,{recursive:!0})).then(()=>yg.writeFile(`${Rp}.tmp`,n)).then(()=>yg.rename(`${Rp}.tmp`,Rp)).catch(()=>{})}function m_(e){e-ti<f_||(Io={start:ti,total:Op(Sr),byCaller:Object.fromEntries(Sr)},Io.total&&console.log(`[github] ${Io.total} calls last hour`,Io.byCaller),ti=e,Sr=new Map,h_(e,!0))}function Ar(e="other",t=Date.now()){m_(t),Sr.set(e,(Sr.get(e)||0)+1),h_(t)}function w_(e=Date.now()){return m_(e),{windowStart:ti,total:Op(Sr),byCaller:Object.fromEntries(Sr),lastHour:Io,backoffUntil:js>e?js:null}}function $o(e){return A2.test(String(e?.message||e||""))}function Ro(e,t=Date.now()){return js<=t&&console.warn(`[github] rate limited \u2014 backing off ${c_/6e4} min:`,String(e?.message||e||"").slice(0,200)),js=Math.max(js,t+c_),js}function Mp(e=Date.now()){return Math.max(0,js-e)}var p_,Rp,f_,c_,S2,ti,Sr,Io,js,l_,Op,u_,A2,ll=V(()=>{p_=process.env.BOSTRAT_STATE_DIR||d_.join(process.env.HOME||v2.tmpdir(),".bostrat"),Rp=d_.join(p_,"github-metrics.json"),f_=60*6e4,c_=5*6e4,S2=6e4,ti=Date.now(),Sr=new Map,Io=null,js=0,l_=0,Op=e=>[...e.values()].reduce((t,n)=>t+n,0);try{let e=JSON.parse(x2.readFileSync(Rp,"utf8"));e?.windowStart&&(Date.now()-e.windowStart<f_?(ti=e.windowStart,Sr=new Map(Object.entries(e.byCaller||{})),Io=e.lastHour||null):Op(new Map(Object.entries(e.byCaller||{})))&&(Io={start:e.windowStart,total:Op(new Map(Object.entries(e.byCaller||{}))),byCaller:e.byCaller||{}}))}catch{}u_=Promise.resolve();A2=/rate limit|too quickly|abuse detection|HTTP 429/i});import g_ from"node:fs/promises";import y_ from"node:path";import T2 from"node:os";function ul({change:e,repo:t=null,number:n=null,githubAt:r=null,observedAt:o=Date.now(),lane:s=null,intervalMs:a=null,source:i=null}){let c=r?o-r:null,l={change:e,repo:t,number:n,githubAt:r,observedAt:o,latencyMs:c,lane:s,intervalMs:a,source:i};Cp.push(l),Cp.length>_2&&Cp.shift();let u=bg.get(e)||{count:0,measured:0,totalMs:0,maxMs:0};return u.count+=1,c!=null&&(u.measured+=1,u.totalMs+=c,u.maxMs=Math.max(u.maxMs,c)),bg.set(e,u),I2(l),l}async function I2(e){try{await g_.mkdir(b_,{recursive:!0}),await g_.appendFile(E2,JSON.stringify(e)+`
193
193
  `)}catch{}}function k_(){let e={};for(let[t,n]of bg)e[t]={count:n.count,measured:n.measured,avgMs:n.measured?Math.round(n.totalMs/n.measured):null,maxMs:n.measured?n.maxMs:null};return{byChange:e,recent:Cp.slice(-20)}}var b_,E2,_2,Cp,bg,Np=V(()=>{b_=process.env.BOSTRAT_STATE_DIR||y_.join(process.env.HOME||T2.tmpdir(),".bostrat"),E2=y_.join(b_,"github-latency.ndjson"),_2=100,Cp=[],bg=new Map});import{execFile as $2}from"node:child_process";import{promisify as R2}from"node:util";async function O2(e){let t=/workspaces[/\\]([0-9a-f]{8})(?:[/\\]|$)/.exec(e||"")?.[1];if(t)try{let[{stdout:n},{stdout:r}]=await Promise.all([ri("git",["-C",e,"rev-parse","HEAD"]),ri("git",["-C",e,"rev-parse","--abbrev-ref","HEAD"])]);await D({id:t,cwd:e},{type:"code.pushed",actor:"orchestrator",payload:{ref:r.trim(),sha:n.trim(),wip:!1,ts:Date.now()}})}catch{}}async function fn(e,t,n={}){let{caller:r="prs",...o}=n,s=await Fn({cwd:e});Ar(r);try{let{stdout:a}=await ri("gh",t,{cwd:e,...M2,...o,env:{...process.env,...s,...o.env||{}}});return String(a||"")}catch(a){throw $o(a)&&Ro(a),a}}async function vg(){if(Pp&&Date.now()-Pp.at<6e4)return Pp.data;let e;try{Ar("auth");let t=await ri("gh",["auth","status"],{timeout:1e4});e={installed:!0,authenticated:!0,login:`${t.stdout||""}${t.stderr||""}`.match(/account\s+(\S+)/)?.[1]??null}}catch(t){e=t?.code==="ENOENT"||t?.code===127?{installed:!1,authenticated:!1,login:null}:{installed:!0,authenticated:!1,login:null}}if(e.installed&&!e.authenticated)try{let t=await pc();t.configured&&(e={installed:!0,authenticated:!0,login:t.username,via:"broker"})}catch{}return Pp={at:Date.now(),data:e},e}async function C2(e){try{let{stdout:t}=await ri("git",["-C",e,"config","--get","remote.origin.url"],{timeout:5e3});return/github\.com/.test(t)}catch{return!1}}function v_(e){let t=e.name||e.context||"check",n=e.detailsUrl||e.targetUrl||null,r=e.completedAt||e.createdAt||null,o;return e.__typename==="StatusContext"?o=e.state==="SUCCESS"?"pass":e.state==="PENDING"||e.state==="EXPECTED"?"pending":"fail":e.status&&e.status!=="COMPLETED"?o="pending":["SUCCESS","NEUTRAL","SKIPPED"].includes(e.conclusion)?o="pass":o="fail",{name:t,state:o,url:n,completedAt:r}}function kg(e){let t=(e||[]).map(v_),n=t.filter(s=>s.state==="pending").length,r=t.map(s=>Date.parse(s.completedAt||"")).filter(s=>s>0),o=t.length&&!n&&r.length?Math.max(...r):null;return{total:t.length,passed:t.filter(s=>s.state==="pass").length,failed:t.filter(s=>s.state==="fail").length,pending:n,failing:t.filter(s=>s.state==="fail").map(({name:s,url:a})=>({name:s,url:a})),settledAt:o}}function Ag(e){return/Resource not accessible by personal access token/.test(String(e?.stderr||e?.message||""))}async function A_(e,t){if(!t)return null;let n=await De(e);if(!n)return null;try{let r=await fn(e,["api",`repos/${n}/actions/runs?head_sha=${encodeURIComponent(t)}&per_page=100`,"--jq",".workflow_runs"]),o=new Map;for(let s of JSON.parse(r||"[]"))o.has(s.name)||o.set(s.name,s);return[...o.values()]}catch{return null}}function T_(e){return(e||[]).map(t=>({name:t.name,detailsUrl:t.html_url||null,status:String(t.status||"").toUpperCase(),conclusion:t.conclusion?String(t.conclusion).toUpperCase():null,completedAt:t.status==="completed"&&t.updated_at||null}))}async function E_(e,t){let n=await A_(e,t);return n===null?{...kg([]),unavailable:!0}:kg(T_(n))}function Bp(e,t=kg(e.statusCheckRollup)){return{number:e.number,title:e.title,url:e.url,author:e.author?.login??null,headRefName:e.headRefName,headSha:e.headRefOid??null,baseRefName:e.baseRefName,isDraft:!!e.isDraft,reviewDecision:e.reviewDecision||null,mergeable:e.mergeable||"UNKNOWN",mergeStateStatus:e.mergeStateStatus||"UNKNOWN",state:e.state??null,mergedAt:e.mergedAt??null,closedAt:e.closedAt??null,additions:e.additions??0,deletions:e.deletions??0,createdAt:e.createdAt,updatedAt:e.updatedAt,checks:t,green:t.failed===0&&t.pending===0&&e.mergeStateStatus==="CLEAN",autoMergeArmed:!!e.autoMergeRequest,mergeabilityPending:!1}}function P2(e,t,n){let r=new Set;for(let o of t){let s=`${e}#${o.number}`;if(o.mergeable!=="UNKNOWN"&&o.mergeStateStatus!=="UNKNOWN"){ni.delete(s);continue}r.add(s),ni.has(s)||ni.set(s,n),o.mergeabilityPending=n-ni.get(s)<N2}for(let o of ni.keys())o.startsWith(`${e}#`)&&!r.has(o)&&ni.delete(o);return t}async function oi(e,t){let n=await _r(e),r=Number(t);if(!Number.isInteger(r)||r<=0)throw new Error("invalid PR number");try{let o=await fn(n.path,["pr","view",String(r),"--json",Sg]);return Bp(JSON.parse(o))}catch(o){if(!Ag(o))throw o;let s=await fn(n.path,["pr","view",String(r),"--json",S_]),a=JSON.parse(s);return Bp(a,await E_(n.path,a.headRefOid))}}async function Jn(e,{caller:t="prs"}={}){try{let n=await fn(e,["pr","list","--json",Sg,"--limit","50"],{caller:t});return JSON.parse(n||"[]").map(r=>Bp(r)).sort(x_)}catch(n){if(!Ag(n))throw n;let r=await fn(e,["pr","list","--json",S_,"--limit","50"],{caller:t});return(await Promise.all(JSON.parse(r||"[]").map(async o=>Bp(o,await E_(e,o.headRefOid))))).sort(x_)}}function hn(){Fs.clear()}function Tg(e=Date.now()){for(let[t,n]of Tr){let r=Math.min(n.announcedAt??1/0,n.webhookAt??1/0);(r===1/0||e-r>L2)&&Tr.delete(t)}}async function Er({repo:e,number:t,via:n="unknown",at:r=Date.now()}={}){if(!I_(e,t))return null;Tg(r);let o=__(e,t);o.announcedAt=r,o.via=n;let s=await cs(e).catch(()=>null);return s?Fs.delete(s):Fs.clear(),console.log(`[pr-open] ${e}#${t} opened card announced via ${n}`+(o.webhookAt?` (opened webhook already in, ${r-o.webhookAt}ms ago)`:"")+` \u2014 ${s?"repo":"whole"} PR cache dropped`),o}function $_({repo:e,number:t,at:n=Date.now()}={}){if(!I_(e,t))return null;Tg(n);let r=__(e,t);return r.webhookAt==null&&(r.webhookAt=n),console.log(`[pr-open] ${e}#${t} opened webhook received`+(r.announcedAt?` ${n-r.announcedAt}ms after its card`:" (card not announced yet)")),r}function R_(e=Date.now()){return Tg(e),[...Tr.values()].map(t=>({...t}))}function F2(e){if(!e)return;let t=`${String(e).toLowerCase()}#`,n;for(let[r,o]of Tr)!r.startsWith(t)||o.webhookAt==null||((n??={})[String(o.number)]=o.webhookAt);return n}function Dp(e,{fromCache:t,slug:n}){let r=F2(n);return{...e,readAt:e.readAt??null,fromCache:t,...r?{openedWebhooks:r}:{}}}function U2(e,t,n,r){if(!e)return;let o=`${String(e).toLowerCase()}#`;for(let[s,a]of Tr)!s.startsWith(o)||a.announcedAt==null||(t.prs||[]).some(i=>i.number===a.number)||(a.staleServes+=1,a.staleServes===1&&console.log(`[pr-open] ${e}#${a.number} poll served from cache (read ${r-n}ms old) without it, ${r-a.announcedAt}ms after its opened card`))}function H2(e,t,n){if(!e)return;let r=`${String(e).toLowerCase()}#`;for(let[o,s]of Tr){if(!o.startsWith(r))continue;if(!(t||[]).some(i=>i.number===s.number)){s.announcedAt!=null&&(s.freshMisses+=1,console.log(`[pr-open] ${e}#${s.number} fresh poll read still lacks it ${n-s.announcedAt}ms after its opened card`+(s.webhookAt?` (opened webhook seen ${n-s.webhookAt}ms ago)`:" (no opened webhook yet)")));continue}s.announcedAt!=null&&(ul({change:"opened-listed",repo:e,number:s.number,githubAt:s.announcedAt,observedAt:n,lane:s.webhookAt!=null?"event":null,source:"tab"}),console.log(`[pr-open] ${e}#${s.number} listed ${n-s.announcedAt}ms after its opened card (${s.staleServes} cache read(s) and ${s.freshMisses} fresh read(s) served without it`+(s.webhookAt?`, opened webhook ${s.webhookAt-s.announcedAt}ms after the card)`:", no opened webhook seen)"))),Tr.delete(o)}}async function W2(e,t){if(!e)return t;for(let n of t){let r=await bt(e,n.number).catch(()=>null);if(!r)continue;r.trackId&&(n.trackId=r.trackId),r.autoMerge&&(n.autoMergeArmed=!0),r.archiveOnMerge&&(n.archiveOnMerge=!0),r.notifyOnMerge&&(n.notifyOnMerge=!0);let o=s=>n.headSha&&s.headSha&&n.headSha!==s.headSha;r.ciFix&&(o(r.ciFix)?await Ep(e,n.number,{headSha:n.headSha}).catch(()=>{}):n.ciFix={delegatedAt:r.ciFix.delegatedAt,trackId:r.ciFix.trackId??null}),r.reconcile&&(o(r.reconcile)?await Ip(e,n.number,{headSha:n.headSha}).catch(()=>{}):n.reconcile={delegatedAt:r.reconcile.delegatedAt,trackId:r.reconcile.trackId??null})}return t}async function O_(){let e=await vg();if(!e.authenticated)return{auth:e,repos:[]};let t=[];for(let a of await fr())await C2(a.path)&&t.push(a);let n=Date.now(),r=Mp(n)>0,o=await Promise.all(t.map(async a=>{let i=Fs.get(a.path),c=await De(a.path).catch(()=>null),l=i?.pending?B2:D2;if(i&&(r||n-i.at<l))return U2(c,i.entry,i.at,n),Dp(i.entry,{fromCache:!0,slug:c});try{let u=Date.now(),d=P2(a.path,await Jn(a.path,{caller:"tab"}),n);if(await W2(c,d),H2(c,d,Date.now()),i?.entry?.prs)for(let w of d)i.entry.prs.find(g=>g.number===w.number)?.checks?.pending>0&&w.checks.total>0&&w.checks.pending===0&&ul({change:w.checks.failed>0?"checks-failed":"checks-green",repo:c||a.name,number:w.number,githubAt:w.checks.settledAt,source:"tab"});let p={name:a.name,path:a.path,prs:d,readAt:u},m=d.some(w=>w.mergeabilityPending||w.checks.pending>0||w.autoMergeArmed);return Fs.set(a.path,{at:Date.now(),entry:p,pending:m}),Dp(p,{fromCache:!1,slug:c})}catch(u){return i?Dp(i.entry,{fromCache:!0,slug:c}):Dp({name:a.name,path:a.path,prs:[],error:Yn(u),readAt:null},{fromCache:!1,slug:c})}})),s=new Set(t.map(a=>a.path));for(let a of Fs.keys())s.has(a)||Fs.delete(a);return{auth:e,repos:o}}async function _r(e){let t=(await fr()).find(n=>n.path===e);if(!t)throw new Error(`unknown repo: ${e}`);return t}async function Us(e){return cs(e)}async function si(e,t,{method:n="squash"}={}){let r=await _r(e);if(!dl.has(n))throw new Error(`invalid merge method: ${n}`);let o=Number(t);if(!Number.isInteger(o)||o<=0)throw new Error("invalid PR number");let s=["pr","merge",String(o),`--${n}`];if(n!=="rebase"&&(await Fn({cwd:r.path})).GH_TOKEN){let a=await um().catch(()=>null);a&&s.push("--body",`Merged by bostrat on behalf of @${a}`)}try{await fn(r.path,s)}catch(a){throw new Error(Yn(a))}finally{hn()}return{ok:!0,number:o}}async function pl(e,t){let n=await _r(e),r=Number(t);if(!Number.isInteger(r)||r<=0)throw new Error("invalid PR number");try{await fn(n.path,["api","-X","PUT",`repos/{owner}/{repo}/pulls/${r}/update-branch`])}catch(s){throw new Error(Yn(s))}finally{hn()}let o=await De(n.path).catch(()=>null);return o&&await QE(o,r).catch(()=>{}),{ok:!0,number:r}}async function Eg(e,t){let n=await _r(e),r=Number(t);if(!Number.isInteger(r)||r<=0)throw new Error("invalid PR number");try{await fn(n.path,["pr","merge",String(r),"--disable-auto"])}catch(o){throw new Error(Yn(o))}finally{hn()}return{ok:!0,number:r}}function _g(e){return e.green&&!e.isDraft}function V2(e){return e.isDraft?"draft":e.mergeable==="CONFLICTING"?`conflicts with ${e.baseRefName}`:e.checks.failed>0?"checks failing":e.checks.pending>0?"checks running":e.mergeable==="UNKNOWN"||e.mergeStateStatus==="UNKNOWN"?"mergeability unresolved":e.mergeStateStatus==="BEHIND"?`behind ${e.baseRefName}`:e.mergeStateStatus==="BLOCKED"?"blocked by branch protection":`not clean (${e.mergeStateStatus})`}function M_(e,{update:t=!0}={}){return e.isDraft?{action:"skip",reason:"draft"}:_g(e)?{action:"merge"}:t&&e.mergeStateStatus==="BEHIND"&&e.mergeable!=="CONFLICTING"&&e.checks.failed===0?{action:"update-arm"}:{action:"arm"}}function C_(e){return[...e.filter(t=>t.plan.action!=="merge"),...e.filter(t=>t.plan.action==="merge")]}function fl(e,t){let n=a=>a?.firstSeen!=null&&Number.isFinite(Number(a.firstSeen))?Number(a.firstSeen):Number.MAX_SAFE_INTEGER,r=n(e),o=n(t);if(r!==o)return r-o;let s=String(e?.repo||"").localeCompare(String(t?.repo||""));return s||Number(e?.number||0)-Number(t?.number||0)}function P_(e){let t=new Map;for(let n of[...e].filter(r=>r?.autoMerge&&r?.trackId).sort(fl)){let r=N_(n.trackId,n.repo);t.has(r)||t.set(r,`${n.repo}#${n.number}`)}return t}function D_(e,t){return t?.trackId?e.get(N_(t.trackId,t.repo))===`${t.repo}#${t.number}`:!0}function B_(){let e={};for(let[t,n]of xg)e[t]={...n};return e}async function L_(e,{method:t="merge",onMerged:n=null}={}){let r=await _r(e);if(!dl.has(t))throw new Error(`invalid merge method: ${t}`);if(xg.get(r.path)?.running)throw new Error("a merge-all is already running for this repo");let o=(await Jn(r.path)).filter(_g).sort((a,i)=>Date.parse(a.createdAt)-Date.parse(i.createdAt));if(!o.length)throw new Error("no PRs ready to merge");let s={running:!0,startedAt:Date.now(),finishedAt:null,method:t,total:o.length,current:o[0].number,queue:o.map(a=>({number:a.number,title:a.title})),merged:[],skipped:[],failed:[]};return xg.set(r.path,s),J2(s,o,{listPrs:()=>Jn(r.path),merge:a=>si(r.path,a,{method:t}),sleep:K2,onMerged:n}).catch(()=>{}),{ok:!0,repo:r.path,total:s.total,queue:o.map(a=>a.number)}}async function z2(e,t){let n=Date.now()+(t.settleMaxMs??G2),r=null;for(;;){let o=null;try{if(o=await t.listPrs(),r=null,!o.some(a=>e.includes(a.number)&&(a.mergeable==="UNKNOWN"||a.mergeStateStatus==="UNKNOWN")))return o}catch(s){r=s}if(Date.now()>=n){if(o)return o;if(r)throw r;return[]}await t.sleep(q2)}}async function J2(e,t,n){try{let r=t;for(let o=0;o<t.length;o++){let s=t[o];if(e.current=s.number,o>0)try{r=await z2(t.slice(o).map(i=>i.number),n)}catch(i){for(let c of t.slice(o))e.failed.push({number:c.number,title:c.title,reason:`couldn't re-check PR state: ${Yn(i)}`});break}let a=r.find(i=>i.number===s.number);if(!a){e.skipped.push({number:s.number,title:s.title,reason:"no longer open"});continue}if(!_g(a)){e.skipped.push({number:a.number,title:a.title,reason:V2(a)});continue}try{await n.merge(a.number),e.merged.push({number:a.number,title:a.title});try{await n.onMerged?.(a)}catch{}}catch(i){e.failed.push({number:a.number,title:a.title,reason:Yn(i)})}}}finally{e.current=null,e.running=!1,e.finishedAt=Date.now(),hn()}}async function Ig(e,{title:t,body:n="",base:r=null}={}){if(typeof t!="string"||!t.trim())throw new Error("title required");try{await ri("git",["-C",e,"push","-u","origin","HEAD"],{timeout:12e4,maxBuffer:4*1024*1024})}catch(l){throw new Error(`push failed: ${Yn(l)}`)}await O2(e);let o=n||"";if((await Fn({cwd:e})).GH_TOKEN){let l=await um().catch(()=>null);l&&(o=`${o?`${o}
194
194
 
195
195
  `:""}Opened by bostrat on behalf of @${l}`)}let s=["pr","create","--title",t.trim(),"--body",o];r&&s.push("--base",r);let a;try{a=await fn(e,s)}catch(l){throw new Error(Yn(l))}finally{hn()}let i=a.match(/https:\/\/\S+\/pull\/\d+/)?.[0]??null,c=i?Number(i.match(/\/pull\/(\d+)/)?.[1]):null;return{ok:!0,url:i,number:c}}async function j_(e,t){let n=await _r(e),r=Number(t);if(!Number.isInteger(r)||r<=0)throw new Error("invalid PR number");let o;try{let i;try{i=await fn(n.path,["pr","checks",String(r),"--json","name,state,link,bucket"])}catch(c){if(i=String(c?.stdout||""),!i.trim())throw new Error(Yn(c))}o=JSON.parse(i||"[]").filter(c=>c.bucket==="fail")}catch(i){if(!Ag(i))throw i;let c=await fn(n.path,["pr","view",String(r),"--json","headRefOid"]),l=await A_(n.path,JSON.parse(c).headRefOid);if(l===null)throw new Error(Yn(i));o=T_(l).map(v_).filter(u=>u.state==="fail").map(u=>({name:u.name,link:u.url}))}let s=new Set,a=[];for(let i of o){let c=Y2(i.link),l=null;c&&!s.has(c)&&(s.add(c),l=await fn(n.path,["run","view",c,"--log-failed"]).then(u=>X2(u)).catch(()=>null)),a.push({name:i.name,link:i.link||null,log:l})}return a}function Y2(e){return String(e||"").match(/\/actions\/runs\/(\d+)/)?.[1]??null}function X2(e,{maxLines:t=400,maxBytes:n=64*1024}={}){let r=String(e||""),o=r.split(`
@@ -202,7 +202,7 @@ ${String(t||"")}`;return/Try the new fullscreen renderer|Flicker-free output/i.t
202
202
  `)){if(o.startsWith("diff --git ")){n={oldPath:null,newPath:null,deleted:[],added:0,binary:!1,hunks:[]},r=null,t.push(n);continue}if(n)if(o.startsWith("--- ")&&!r){let s=o.slice(4).trim();n.oldPath=s==="/dev/null"?null:s.replace(/^a\//,"")}else if(o.startsWith("+++ ")&&!r){let s=o.slice(4).trim();n.newPath=s==="/dev/null"?null:s.replace(/^b\//,"")}else if(o.startsWith("Binary files"))n.binary=!0;else if(o.startsWith("@@")){let s=/^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/.exec(o);if(!s)continue;let a=Number(s[1]),i=s[2]==null?1:Number(s[2]),c=Number(s[3]),l=s[4]==null?1:Number(s[4]);i>0&&n.deleted.push([a,i]),n.added+=l,r={oldStart:a,oldCount:i,newStart:c,newCount:l,del:[],add:[]},n.hunks.push(r)}else r&&o.startsWith("-")?r.del.push(o.slice(1)):r&&o.startsWith("+")&&r.add.push(o.slice(1))}return t}function MH(e,t){let n=Cg(e),r=Cg(t);if(n===r)return 1;if(!n.length||!r.length)return 0;n.length>Hp&&(n=n.slice(0,Hp)),r.length>Hp&&(r=r.slice(0,Hp));let o=new Array(r.length+1),s=new Array(r.length+1);for(let a=0;a<=r.length;a++)o[a]=a;for(let a=1;a<=n.length;a++){s[0]=a;let i=n.charCodeAt(a-1);for(let c=1;c<=r.length;c++){let l=i===r.charCodeAt(c-1)?0:1;s[c]=Math.min(o[c]+1,s[c-1]+1,o[c-1]+l)}[o,s]=[s,o]}return 1-o[r.length]/Math.max(n.length,r.length)}function CH(e,t=X_){let n=new Set,r=e?.del||[],o=e?.add||[];for(let s=0;s<r.length;s++){let a=e.oldStart+s;if(!Cg(r[s]).length){n.add(a);continue}s<o.length&&MH(r[s],o[s])>=t&&n.add(a)}return n}function NH(e){let t=[...e].sort((r,o)=>r-o),n=[];for(let r of t){let o=n[n.length-1];o&&o[0]+o[1]===r?o[1]+=1:n.push([r,1])}return n}function PH(e){let t=new Map,n=null;for(let r of String(e||"").split(`
203
203
  `)){let o=/^([0-9a-f]{40}) (\d+) (\d+)(?: (\d+))?$/.exec(r);if(o){n={sha:o[1],line:Number(o[3]),time:null},t.set(n.line,n);continue}n&&r.startsWith("committer-time ")&&(n.time=Number(r.slice(15))*1e3)}return t}async function V_(e,t){let{stdout:n}=await Mg(e,["show","-s","--format=%H%n%P%n%ct%n%s%n%B",t]),[r,o,s,a,...i]=n.split(`
204
204
  `);return{sha:r.trim(),parents:o.trim()?o.trim().split(" "):[],ts:Number(s)*1e3,subject:a??"",message:i.join(`
205
- `)}}async function Z_(e,t,{fixKey:n=null,window:r=Co,resolveOrigin:o=null,context:s={}}={}){let a=await V_(e,t);if(a.parents.length!==1)return null;let i=a.parents[0],c=q_(a.message),l=n?Wp(n):c.epoch,u=l?ii(l):null,{stdout:d}=await Mg(e,["diff","-U0","--no-color","-M","-C",i,t]),p=OH(d),m=0,w=0,h=0,g=0,b=0,y=0,x=0,E=new Map;for(let C of p){if(C.binary)continue;let j=C.oldPath||C.newPath||"",K=C.deleted.reduce((W,[,ie])=>W+ie,0),M=RH(j);if(M==="excluded"){h+=K;continue}if(M==="docs"){g+=K,b+=C.added;continue}if(M==="config"){y+=K;continue}m+=C.added;let I=new Set;for(let W of C.hunks||[])for(let ie of CH(W))I.add(ie);x+=I.size;let S=[];for(let[W,ie]of C.deleted)for(let z=W;z<W+ie;z++)I.has(z)||S.push(z);if(w+=S.length,!C.oldPath||!S.length)continue;let U;try{let W=["blame","-w","-M","-C","--line-porcelain"];for(let[ie,z]of NH(S))W.push("-L",`${ie},${ie+z-1}`);W.push(i,"--",C.oldPath),U=PH((await Mg(e,W)).stdout)}catch{continue}for(let{sha:W,time:ie}of U.values()){let z=E.get(W)??{lines:0,time:ie};z.lines+=1,E.set(W,z)}}let A=[],$=0,P=new Map;for(let[C,{lines:j,time:K}]of E){let M=P.get(C);if(!M){try{M=await V_(e,C)}catch{M=null}P.set(C,M)}let I=M?q_(M.message):{epoch:null},S=I.epoch,U=I.provider,W=I.model;if(!S&&o){let Y=await o(C,M);Y?.trackId&&Y?.boxId!=null&&(S={trackId:Y.trackId,boxId:Y.boxId,epoch:Y.epoch??0},U=U??Y.provider??null,W=W??Y.model??null)}if(!S){$+=j;continue}let ie=Number.isFinite(K)?K:M?.ts??a.ts,z=Math.max(0,(a.ts-ie)/hH),Ge=ii(S),_e=Ge===u?"self":yH(z,r);A.push({sha:C,key:Ge,trackId:S.trackId,boxId:S.boxId,epoch:S.epoch,provider:U??null,model:W??null,lines:j,ageDays:Math.round(z*100)/100,class:_e,decay:_e==="rework"?1:_e==="drift"?Math.round(bH(z,{window:r})*1e3)/1e3:0})}A.sort((C,j)=>j.lines-C.lines);let L=Kp({subject:a.subject,trailerCause:c.cause,wallReason:s.wallReason??null,fixerCategory:s.fixerCategory??null,ciFix:s.ciFix===!0}),T=Dg({heuristic:L,subject:a.subject,ref:s.ref??null,promptKind:s.promptKind??null,fixerCategory:s.fixerCategory??null,ticketKind:s.ticketKind??null});return{sha:a.sha,parent:i,subject:a.subject.slice(0,200),ts:a.ts,fixKey:u,fixProvider:c.provider??s.provider??null,fixModel:c.model??s.model??null,window:r,added:m,deleted:w,excludedDeleted:h,cosmeticDeleted:x,docsDeleted:g,docsAdded:b,configDeleted:y,codeDelta:m+w+x>0,origins:A,unattributedLines:$,ghost:w===0&&m>0,heuristic:L,intent:T}}function Q_(e,{minLines:t=Pg}={}){if(!e)return!1;let n=e.intent?.intent??"unknown";return ci.has(n)?ml(e)>=t:!1}function ml(e){return(e?.origins||[]).filter(t=>t.class==="rework").reduce((t,n)=>t+n.lines,0)}function Og(e){let t=e.genUsd;return{...e,genUsd:$n(t),reworkChargedUsd:$n(e.reworkChargedUsd),reworkPendingUsd:$n(e.reworkPendingUsd),trueUsd:$n(t+e.reworkChargedUsd),multiplier:t>0?$n((t+e.reworkChargedUsd)/t):null}}function eI(e,{window:t=Co,boxMeta:n={}}={}){let r=e||[],o=r.filter(T=>T.type==="cost.recorded"),s=r.filter(T=>T.type==="code.committed"),a=r.filter(T=>T.type==="code.rework"),i=T=>Array.isArray(T?.shas)&&T.shas.length?T.shas:T?.sha?[T.sha]:[],c=new Map,l=new Set;for(let T of r)if(T.type==="rework.cause.offered")for(let C of i(T.payload))l.add(C);else if(T.type==="rework.cause.answered"&&T.payload?.cause)for(let C of i(T.payload))c.set(C,T.payload.cause);else if(T.type==="rework.cause.retracted")for(let C of i(T.payload))c.delete(C);let u={},d=(T,C,j)=>ii({trackId:T,boxId:C,epoch:j??0}),p=(T,C={})=>{if(!u[T]){let K=Wp(T)||{};u[T]={key:T,...K,provider:null,model:null,...Rg()}}let j=u[T];return C.provider&&!j.provider&&(j.provider=C.provider),C.model&&!j.model&&(j.model=C.model),j};for(let T of o){if(!T.boxId)continue;let C=d(T.trackId,T.boxId,T.epoch),{usd:j,model:K}=dn(T),M=p(C,{provider:T.provider,model:K!=="unknown"?K:null});M.genUsd+=j}let m=new Map;for(let T of s){let C=`${T.trackId}/${T.boxId}`;(m.get(C)??m.set(C,[]).get(C)).push({...T,ts:T.payload?.ts??T.ts})}for(let T of m.values())T.sort((C,j)=>C.ts-j.ts);let w=(T,C,j,K)=>{let M=m.get(`${T}/${C}`)||[],I=-1/0;for(let W of M)W.ts<K&&(I=W.ts);let S=0,U=0;for(let W of o)W.trackId!==T||W.boxId!==C||(W.epoch??0)===(j??0)&&(W.ts<=I||W.ts>K||(S+=dn(W).usd,U++));return{usd:S,turns:U,from:Number.isFinite(I)?I:null}},h={charged:0,pending:0,self:0,decayed:0,unattributed:0,ghost:0,planned:0},g={A:0,B:0,C:0,E:0,none:0},b={fix:0,"likely-fix":0,planned:0,unknown:0},y=0,x=[],E=[],A={},$={},P=new Set;for(let T of a){let C=T.payload||{};if(!C.sha||P.has(C.sha))continue;if(P.add(C.sha),C.codeDelta===!1){y++;continue}let j=Wp(C.fixKey)||{trackId:T.trackId,boxId:T.boxId,epoch:T.epoch??0},{usd:K,turns:M}=w(j.trackId,j.boxId,j.epoch,C.ts??T.ts),I=wH.includes(C.intent?.intent)?C.intent.intent:"unknown";b[I]+=1;let S=null;c.has(C.sha)?S={cause:c.get(C.sha),level:"B",basis:"operator"}:(C.heuristic?.level&&C.heuristic.level!=="C"||C.heuristic)&&(S=C.heuristic);let U=S?.level??"none";g[U]=(g[U]||0)+1;let W=mH.has(U),ie=Number(C.deleted)||0,z=Array.isArray(C.origins)?C.origins:[],Ge=z.filter(Y=>Y.class==="rework").reduce((Y,ne)=>Y+ne.lines,0),_e={sha:C.sha,subject:C.subject??"",ts:C.ts??T.ts,trackId:T.trackId,fixKey:C.fixKey??null,fixProvider:C.fixProvider??T.provider??null,fixUsd:$n(K),fixTurns:M,linesReworked:Ge,unattributedLines:Number(C.unattributedLines)||0,ghost:C.ghost===!0,intent:{intent:I,basis:C.intent?.basis??null},verdict:S?{cause:S.cause,level:U,basis:S.basis??null}:null,charged:$n(0),origins:[]};if(I==="planned"||S?.cause===qp){h.planned+=K;for(let Y of z)Y.class==="rework"&&_e.origins.push({key:Y.key,provider:Y.provider??null,model:Y.model??null,lines:Y.lines,ageDays:Y.ageDays,class:Y.class,usd:0})}else if(C.ghost||ie===0)h.ghost+=K;else{let Y=0;for(let Ie of z){let Pe=Ie.lines/ie,ae=K*Pe;if(Y+=ae,Ie.class==="self"){h.self+=ae;continue}let Ae=Ie.class==="rework"?1:Number(Ie.decay)||0,be=ae*Ae;if(h.decayed+=ae-be,be<=0)continue;let Q=p(Ie.key,{provider:Ie.provider,model:Ie.model});Q.fixes+=1,Q.linesReworked+=Ie.class==="rework"?Ie.lines:0;let he=S?.cause&&hl.includes(S.cause)?S.cause:"unclassified";Q.causes[he]+=1,W?(Q.reworkChargedUsd+=be,h.charged+=be,_e.charged=$n(_e.charged+be)):(Q.reworkPendingUsd+=be,h.pending+=be),_e.origins.push({key:Ie.key,provider:Q.provider,model:Q.model,lines:Ie.lines,ageDays:Ie.ageDays,class:Ie.class,usd:$n(be)})}let ne=Math.max(0,K-Y);h.unattributed+=ne}x.push(_e),!c.has(C.sha)&&l.has(C.sha)&&E.push(C.sha)}for(let T of Object.values(u)){let C=T.provider||"unknown",j=T.model||"unknown",K=M=>{M.genUsd+=T.genUsd,M.reworkChargedUsd+=T.reworkChargedUsd,M.reworkPendingUsd+=T.reworkPendingUsd,M.linesReworked+=T.linesReworked,M.fixes+=T.fixes;for(let I of Object.keys(M.causes))M.causes[I]+=T.causes[I]};K(A[C]||=Rg()),K($[j]||=Rg())}x.sort((T,C)=>C.ts-T.ts);let L=Object.values(u).map(T=>{let C=n[`${T.trackId}/${T.boxId}`]||{};return Og({...T,trackName:C.trackName??null,label:C.label??null})}).sort((T,C)=>C.reworkChargedUsd+C.reworkPendingUsd-(T.reworkChargedUsd+T.reworkPendingUsd)||C.genUsd-T.genUsd);return{window:t,basis:`rework = code lines a fix deletes/modifies that blame to another epoch's commit \u2264${t} d old (docs/config churn and in-place updates \u2265${X_} similar are counted, not blamed); fix cost = the fixing box's turns since its previous commit; charged only on an authoritative / operator / self-reported cause; planned work (follow-up, blueprint item, feat:/docs: prefix, non-fix prompt) is generation cost`,intents:b,noCodeDelta:y,byEpoch:Object.fromEntries(L.map(T=>[T.key,T])),epochs:L,byProvider:Object.fromEntries(Object.entries(A).map(([T,C])=>[T,Og(C)])),byModel:Object.fromEntries(Object.entries($).map(([T,C])=>[T,Og(C)])),buckets:Object.fromEntries(Object.entries(h).map(([T,C])=>[T,$n(C)])),fixUsdTotal:$n(Object.values(h).reduce((T,C)=>T+C,0)),fixes:x,verdicts:g,pendingTaps:E,commits:s.length}}var pH,fH,Mg,z_,J_,Y_,hH,Co,Ng,Pg,hl,qp,mH,wH,ci,X_,gH,kH,G_,xH,vH,SH,AH,TH,K_,EH,_H,IH,$H,Cg,Hp,$n,Rg,Vp=V(()=>{xo();pH=dH(uH),fH=64*1024*1024,Mg=(e,t)=>pH("git",["-C",e,...t],{maxBuffer:fH,timeout:6e4}),z_="Bostrat-Epoch",J_="Bostrat-Model",Y_="Bostrat-Fix-Cause",hH=24*36e5,Co=Number(process.env.BOSTRAT_REWORK_WINDOW_DAYS)||21,Ng=90,Pg=3,hl=Object.freeze(["defect","design","requirements","style"]),qp="not-a-fix",mH=new Set(["A","B","E"]),wH=Object.freeze(["fix","likely-fix","planned","unknown"]),ci=new Set(["fix","likely-fix"]),X_=.8;gH={claude:"Co-Authored-By: Claude <noreply@anthropic.com>",codex:"Co-authored-by: Codex <noreply@openai.com>",cursor:"Made-with: Cursor"};kH=/^revert\b|^revert "/i,G_=/\b(fix(es|ed)?|bug|hotfix|regression|crash|broken|npe|null ?pointer|off[- ]by[- ]one|leak)\b/i,xH=/\b(refactor|rearchitect|re-architect|restructure|rework|rewrite|redesign|simplif(y|ied)|clean ?up)\b/i,vH=/\b(lint|format(ting)?|prettier|typo|whitespace|rename)\b/i;SH=/^([a-z]+)(\([^)]*\))?!?:\s/i,AH=new Set(["fix","hotfix","bugfix","revert"]),TH=new Set(["feat","feature","docs","doc","test","tests","build","ci","chore"]),K_=/\bBP-[A-Z0-9]+(?:-[A-Z0-9]+)*\b/i,EH=new Set(["feature-build","docs-writing","research","design","ops-infra","orchestration"]);_H=[/(^|\/)\.bostrat\//,/(^|\/)(package-lock\.json|yarn\.lock|pnpm-lock\.yaml|Cargo\.lock|poetry\.lock|Gemfile\.lock|go\.sum|composer\.lock)$/,/\.min\.(js|css)$/,/\.map$/,/\.snap$/,/(^|\/)(node_modules|dist|build|vendor|\.next|target)\//],IH=[/\.(md|mdx|markdown|rst|txt|adoc|asciidoc)$/i,/(^|\/)(docs?|notes|business|design)\//i,/(^|\/)(README|CHANGELOG|CHANGES|LICENSE|CONTRIBUTING|AUTHORS|NOTICE)(\.[a-z]+)?$/i],$H=[/\.(json|jsonc|json5|ya?ml|toml|ini|cfg|conf|properties|env|example)$/i,/(^|\/)\.[^/]+$/,/(^|\/)\.github\//,/(^|\/)(Dockerfile|Makefile|Procfile|fly\.toml)$/];Cg=e=>String(e??"").replace(/\s+/g," ").trim(),Hp=400;$n=e=>Math.round(e*1e4)/1e4,Rg=()=>({genUsd:0,reworkChargedUsd:0,reworkPendingUsd:0,linesReworked:0,fixes:0,causes:{defect:0,design:0,requirements:0,style:0,unclassified:0}})});import{execFile as DH}from"node:child_process";import{promisify as BH}from"node:util";function tI(e,t=Date.now()){return fc(e,t)??0}function jH(e,t,n){for(let r=e.length-1;r>=0;r--){let o=e[r];if(o.type!=="cost.recorded"||o.boxId!==t||n!=null&&o.epoch!=null&&o.epoch!==n)continue;let s=o.payload?.model;if(s&&s!=="unknown")return s}return null}async function nI(e,t,{now:n=Date.now()}={}){let r=tI(t,n),o=await J(e);return Gp({trackId:e.id,boxId:t.name,epoch:r,provider:t.agent??null,model:jH(o,t.name,r)})}function FH(e,t){let n=null;for(let r=e.length-1;r>=0;r--){let o=e[r];if(o.type!=="turn.user"||o.boxId!==t||o.actor!=="user")continue;let s=o.payload||{};if(s.note?.kind!=="task"){if(o.source==="orchestrator"&&typeof s.text=="string"&&s.text.trim())return{text:s.text,kind:s.kind??null};!n&&typeof s.promptHead=="string"&&s.promptHead.trim()&&(n={text:s.promptHead,kind:s.kind??null})}}return n}function UH(e,t,n,r){let o=Array.isArray(t?.epochs)?t.epochs:[],s=r>0?o[r-1]:null,a=s?.endReason?.code??(typeof s?.endReason=="string"?s.endReason:null),i=FH(n,t.name),c=i?yr(i.text)?.category??null:null;return{wallReason:a,fixerCategory:c,promptKind:i?.kind??null}}async function HH(e,t){try{let{stdout:n}=await Bg(e,["show","--shortstat","--format=",t]),r=/(\d+) files? changed/.exec(n),o=/(\d+) insertions?\(\+\)/.exec(n),s=/(\d+) deletions?\(-\)/.exec(n);return{files:r?Number(r[1]):0,insertions:o?Number(o[1]):0,deletions:s?Number(s[1]):0}}catch{return{files:0,insertions:0,deletions:0}}}async function WH(e){try{let{stdout:t}=await Bg(e,["rev-parse","--abbrev-ref","HEAD"]);return t.trim()||null}catch{return null}}async function rI(e,t,n,{cwd:r=t?.cwd,log:o=console,now:s=Date.now()}={}){if(!e?.id||!t?.name||!n||!r)return{recorded:!1,reason:"incomplete"};let a=await J(e);if(a.some(h=>h.type==="code.committed"&&h.payload?.sha===n))return{recorded:!1,reason:"duplicate"};let i=s,c=null;try{let{stdout:h}=await Bg(r,["show","-s","--format=%ct%n%s",n]),[g,...b]=h.split(`
205
+ `)}}async function Z_(e,t,{fixKey:n=null,window:r=Co,resolveOrigin:o=null,context:s={}}={}){let a=await V_(e,t);if(a.parents.length!==1)return null;let i=a.parents[0],c=q_(a.message),l=n?Wp(n):c.epoch,u=l?ii(l):null,{stdout:d}=await Mg(e,["diff","-U0","--no-color","-M","-C",i,t]),p=OH(d),m=0,w=0,h=0,g=0,b=0,y=0,x=0,E=new Map;for(let C of p){if(C.binary)continue;let j=C.oldPath||C.newPath||"",K=C.deleted.reduce((W,[,ie])=>W+ie,0),M=RH(j);if(M==="excluded"){h+=K;continue}if(M==="docs"){g+=K,b+=C.added;continue}if(M==="config"){y+=K;continue}m+=C.added;let I=new Set;for(let W of C.hunks||[])for(let ie of CH(W))I.add(ie);x+=I.size;let S=[];for(let[W,ie]of C.deleted)for(let z=W;z<W+ie;z++)I.has(z)||S.push(z);if(w+=S.length,!C.oldPath||!S.length)continue;let U;try{let W=["blame","-w","-M","-C","--line-porcelain"];for(let[ie,z]of NH(S))W.push("-L",`${ie},${ie+z-1}`);W.push(i,"--",C.oldPath),U=PH((await Mg(e,W)).stdout)}catch{continue}for(let{sha:W,time:ie}of U.values()){let z=E.get(W)??{lines:0,time:ie};z.lines+=1,E.set(W,z)}}let A=[],$=0,P=new Map;for(let[C,{lines:j,time:K}]of E){let M=P.get(C);if(!M){try{M=await V_(e,C)}catch{M=null}P.set(C,M)}let I=M?q_(M.message):{epoch:null},S=I.epoch,U=I.provider,W=I.model;if(!S&&o){let Y=await o(C,M);Y?.trackId&&Y?.boxId!=null&&(S={trackId:Y.trackId,boxId:Y.boxId,epoch:Y.epoch??0},U=U??Y.provider??null,W=W??Y.model??null)}if(!S){$+=j;continue}let ie=Number.isFinite(K)?K:M?.ts??a.ts,z=Math.max(0,(a.ts-ie)/hH),Ge=ii(S),_e=Ge===u?"self":yH(z,r);A.push({sha:C,key:Ge,trackId:S.trackId,boxId:S.boxId,epoch:S.epoch,provider:U??null,model:W??null,lines:j,ageDays:Math.round(z*100)/100,class:_e,decay:_e==="rework"?1:_e==="drift"?Math.round(bH(z,{window:r})*1e3)/1e3:0})}A.sort((C,j)=>j.lines-C.lines);let L=Kp({subject:a.subject,trailerCause:c.cause,wallReason:s.wallReason??null,fixerCategory:s.fixerCategory??null,ciFix:s.ciFix===!0}),T=Dg({heuristic:L,subject:a.subject,ref:s.ref??null,promptKind:s.promptKind??null,fixerCategory:s.fixerCategory??null,ticketKind:s.ticketKind??null});return{sha:a.sha,parent:i,subject:a.subject.slice(0,200),ts:a.ts,fixKey:u,fixProvider:c.provider??s.provider??null,fixModel:c.model??s.model??null,window:r,added:m,deleted:w,excludedDeleted:h,cosmeticDeleted:x,docsDeleted:g,docsAdded:b,configDeleted:y,codeDelta:m+w+x>0,origins:A,unattributedLines:$,ghost:w===0&&m>0,heuristic:L,intent:T}}function Q_(e,{minLines:t=Pg}={}){if(!e)return!1;let n=e.intent?.intent??"unknown";return ci.has(n)?ml(e)>=t:!1}function ml(e){return(e?.origins||[]).filter(t=>t.class==="rework").reduce((t,n)=>t+n.lines,0)}function Og(e){let t=e.genUsd;return{...e,genUsd:$n(t),reworkChargedUsd:$n(e.reworkChargedUsd),reworkPendingUsd:$n(e.reworkPendingUsd),trueUsd:$n(t+e.reworkChargedUsd),multiplier:t>0?$n((t+e.reworkChargedUsd)/t):null}}function eI(e,{window:t=Co,boxMeta:n={}}={}){let r=e||[],o=r.filter(T=>T.type==="cost.recorded"),s=r.filter(T=>T.type==="code.committed"),a=r.filter(T=>T.type==="code.rework"),i=T=>Array.isArray(T?.shas)&&T.shas.length?T.shas:T?.sha?[T.sha]:[],c=new Map,l=new Set;for(let T of r)if(T.type==="rework.cause.offered")for(let C of i(T.payload))l.add(C);else if(T.type==="rework.cause.answered"&&T.payload?.cause)for(let C of i(T.payload))c.set(C,T.payload.cause);else if(T.type==="rework.cause.retracted")for(let C of i(T.payload))c.delete(C);let u={},d=(T,C,j)=>ii({trackId:T,boxId:C,epoch:j??0}),p=(T,C={})=>{if(!u[T]){let K=Wp(T)||{};u[T]={key:T,...K,provider:null,model:null,...Rg()}}let j=u[T];return C.provider&&!j.provider&&(j.provider=C.provider),C.model&&!j.model&&(j.model=C.model),j};for(let T of o){if(!T.boxId)continue;let C=d(T.trackId,T.boxId,T.epoch),{usd:j,model:K}=dn(T),M=p(C,{provider:T.provider,model:K!=="unknown"?K:null});M.genUsd+=j}let m=new Map;for(let T of s){let C=`${T.trackId}/${T.boxId}`;(m.get(C)??m.set(C,[]).get(C)).push({...T,ts:T.payload?.ts??T.ts})}for(let T of m.values())T.sort((C,j)=>C.ts-j.ts);let w=(T,C,j,K)=>{let M=m.get(`${T}/${C}`)||[],I=-1/0;for(let W of M)W.ts<K&&(I=W.ts);let S=0,U=0;for(let W of o)W.trackId!==T||W.boxId!==C||(W.epoch??0)===(j??0)&&(W.ts<=I||W.ts>K||(S+=dn(W).usd,U++));return{usd:S,turns:U,from:Number.isFinite(I)?I:null}},h={charged:0,pending:0,self:0,decayed:0,unattributed:0,ghost:0,planned:0},g={A:0,B:0,C:0,E:0,none:0},b={fix:0,"likely-fix":0,planned:0,unknown:0},y=0,x=[],E=[],A={},$={},P=new Set;for(let T of a){let C=T.payload||{};if(!C.sha||P.has(C.sha))continue;if(P.add(C.sha),C.codeDelta===!1){y++;continue}let j=Wp(C.fixKey)||{trackId:T.trackId,boxId:T.boxId,epoch:T.epoch??0},{usd:K,turns:M}=w(j.trackId,j.boxId,j.epoch,C.ts??T.ts),I=wH.includes(C.intent?.intent)?C.intent.intent:"unknown";b[I]+=1;let S=null;c.has(C.sha)?S={cause:c.get(C.sha),level:"B",basis:"operator"}:(C.heuristic?.level&&C.heuristic.level!=="C"||C.heuristic)&&(S=C.heuristic);let U=S?.level??"none";g[U]=(g[U]||0)+1;let W=mH.has(U),ie=Number(C.deleted)||0,z=Array.isArray(C.origins)?C.origins:[],Ge=z.filter(Y=>Y.class==="rework").reduce((Y,ne)=>Y+ne.lines,0),_e={sha:C.sha,subject:C.subject??"",ts:C.ts??T.ts,trackId:T.trackId,fixKey:C.fixKey??null,fixProvider:C.fixProvider??T.provider??null,fixUsd:$n(K),fixTurns:M,linesReworked:Ge,unattributedLines:Number(C.unattributedLines)||0,ghost:C.ghost===!0,intent:{intent:I,basis:C.intent?.basis??null},verdict:S?{cause:S.cause,level:U,basis:S.basis??null}:null,charged:$n(0),origins:[]};if(I==="planned"||S?.cause===qp){h.planned+=K;for(let Y of z)Y.class==="rework"&&_e.origins.push({key:Y.key,provider:Y.provider??null,model:Y.model??null,lines:Y.lines,ageDays:Y.ageDays,class:Y.class,usd:0})}else if(C.ghost||ie===0)h.ghost+=K;else{let Y=0;for(let Ie of z){let Pe=Ie.lines/ie,ae=K*Pe;if(Y+=ae,Ie.class==="self"){h.self+=ae;continue}let Ae=Ie.class==="rework"?1:Number(Ie.decay)||0,be=ae*Ae;if(h.decayed+=ae-be,be<=0)continue;let Q=p(Ie.key,{provider:Ie.provider,model:Ie.model});Q.fixes+=1,Q.linesReworked+=Ie.class==="rework"?Ie.lines:0;let me=S?.cause&&hl.includes(S.cause)?S.cause:"unclassified";Q.causes[me]+=1,W?(Q.reworkChargedUsd+=be,h.charged+=be,_e.charged=$n(_e.charged+be)):(Q.reworkPendingUsd+=be,h.pending+=be),_e.origins.push({key:Ie.key,provider:Q.provider,model:Q.model,lines:Ie.lines,ageDays:Ie.ageDays,class:Ie.class,usd:$n(be)})}let ne=Math.max(0,K-Y);h.unattributed+=ne}x.push(_e),!c.has(C.sha)&&l.has(C.sha)&&E.push(C.sha)}for(let T of Object.values(u)){let C=T.provider||"unknown",j=T.model||"unknown",K=M=>{M.genUsd+=T.genUsd,M.reworkChargedUsd+=T.reworkChargedUsd,M.reworkPendingUsd+=T.reworkPendingUsd,M.linesReworked+=T.linesReworked,M.fixes+=T.fixes;for(let I of Object.keys(M.causes))M.causes[I]+=T.causes[I]};K(A[C]||=Rg()),K($[j]||=Rg())}x.sort((T,C)=>C.ts-T.ts);let L=Object.values(u).map(T=>{let C=n[`${T.trackId}/${T.boxId}`]||{};return Og({...T,trackName:C.trackName??null,label:C.label??null})}).sort((T,C)=>C.reworkChargedUsd+C.reworkPendingUsd-(T.reworkChargedUsd+T.reworkPendingUsd)||C.genUsd-T.genUsd);return{window:t,basis:`rework = code lines a fix deletes/modifies that blame to another epoch's commit \u2264${t} d old (docs/config churn and in-place updates \u2265${X_} similar are counted, not blamed); fix cost = the fixing box's turns since its previous commit; charged only on an authoritative / operator / self-reported cause; planned work (follow-up, blueprint item, feat:/docs: prefix, non-fix prompt) is generation cost`,intents:b,noCodeDelta:y,byEpoch:Object.fromEntries(L.map(T=>[T.key,T])),epochs:L,byProvider:Object.fromEntries(Object.entries(A).map(([T,C])=>[T,Og(C)])),byModel:Object.fromEntries(Object.entries($).map(([T,C])=>[T,Og(C)])),buckets:Object.fromEntries(Object.entries(h).map(([T,C])=>[T,$n(C)])),fixUsdTotal:$n(Object.values(h).reduce((T,C)=>T+C,0)),fixes:x,verdicts:g,pendingTaps:E,commits:s.length}}var pH,fH,Mg,z_,J_,Y_,hH,Co,Ng,Pg,hl,qp,mH,wH,ci,X_,gH,kH,G_,xH,vH,SH,AH,TH,K_,EH,_H,IH,$H,Cg,Hp,$n,Rg,Vp=V(()=>{xo();pH=dH(uH),fH=64*1024*1024,Mg=(e,t)=>pH("git",["-C",e,...t],{maxBuffer:fH,timeout:6e4}),z_="Bostrat-Epoch",J_="Bostrat-Model",Y_="Bostrat-Fix-Cause",hH=24*36e5,Co=Number(process.env.BOSTRAT_REWORK_WINDOW_DAYS)||21,Ng=90,Pg=3,hl=Object.freeze(["defect","design","requirements","style"]),qp="not-a-fix",mH=new Set(["A","B","E"]),wH=Object.freeze(["fix","likely-fix","planned","unknown"]),ci=new Set(["fix","likely-fix"]),X_=.8;gH={claude:"Co-Authored-By: Claude <noreply@anthropic.com>",codex:"Co-authored-by: Codex <noreply@openai.com>",cursor:"Made-with: Cursor"};kH=/^revert\b|^revert "/i,G_=/\b(fix(es|ed)?|bug|hotfix|regression|crash|broken|npe|null ?pointer|off[- ]by[- ]one|leak)\b/i,xH=/\b(refactor|rearchitect|re-architect|restructure|rework|rewrite|redesign|simplif(y|ied)|clean ?up)\b/i,vH=/\b(lint|format(ting)?|prettier|typo|whitespace|rename)\b/i;SH=/^([a-z]+)(\([^)]*\))?!?:\s/i,AH=new Set(["fix","hotfix","bugfix","revert"]),TH=new Set(["feat","feature","docs","doc","test","tests","build","ci","chore"]),K_=/\bBP-[A-Z0-9]+(?:-[A-Z0-9]+)*\b/i,EH=new Set(["feature-build","docs-writing","research","design","ops-infra","orchestration"]);_H=[/(^|\/)\.bostrat\//,/(^|\/)(package-lock\.json|yarn\.lock|pnpm-lock\.yaml|Cargo\.lock|poetry\.lock|Gemfile\.lock|go\.sum|composer\.lock)$/,/\.min\.(js|css)$/,/\.map$/,/\.snap$/,/(^|\/)(node_modules|dist|build|vendor|\.next|target)\//],IH=[/\.(md|mdx|markdown|rst|txt|adoc|asciidoc)$/i,/(^|\/)(docs?|notes|business|design)\//i,/(^|\/)(README|CHANGELOG|CHANGES|LICENSE|CONTRIBUTING|AUTHORS|NOTICE)(\.[a-z]+)?$/i],$H=[/\.(json|jsonc|json5|ya?ml|toml|ini|cfg|conf|properties|env|example)$/i,/(^|\/)\.[^/]+$/,/(^|\/)\.github\//,/(^|\/)(Dockerfile|Makefile|Procfile|fly\.toml)$/];Cg=e=>String(e??"").replace(/\s+/g," ").trim(),Hp=400;$n=e=>Math.round(e*1e4)/1e4,Rg=()=>({genUsd:0,reworkChargedUsd:0,reworkPendingUsd:0,linesReworked:0,fixes:0,causes:{defect:0,design:0,requirements:0,style:0,unclassified:0}})});import{execFile as DH}from"node:child_process";import{promisify as BH}from"node:util";function tI(e,t=Date.now()){return fc(e,t)??0}function jH(e,t,n){for(let r=e.length-1;r>=0;r--){let o=e[r];if(o.type!=="cost.recorded"||o.boxId!==t||n!=null&&o.epoch!=null&&o.epoch!==n)continue;let s=o.payload?.model;if(s&&s!=="unknown")return s}return null}async function nI(e,t,{now:n=Date.now()}={}){let r=tI(t,n),o=await J(e);return Gp({trackId:e.id,boxId:t.name,epoch:r,provider:t.agent??null,model:jH(o,t.name,r)})}function FH(e,t){let n=null;for(let r=e.length-1;r>=0;r--){let o=e[r];if(o.type!=="turn.user"||o.boxId!==t||o.actor!=="user")continue;let s=o.payload||{};if(s.note?.kind!=="task"){if(o.source==="orchestrator"&&typeof s.text=="string"&&s.text.trim())return{text:s.text,kind:s.kind??null};!n&&typeof s.promptHead=="string"&&s.promptHead.trim()&&(n={text:s.promptHead,kind:s.kind??null})}}return n}function UH(e,t,n,r){let o=Array.isArray(t?.epochs)?t.epochs:[],s=r>0?o[r-1]:null,a=s?.endReason?.code??(typeof s?.endReason=="string"?s.endReason:null),i=FH(n,t.name),c=i?yr(i.text)?.category??null:null;return{wallReason:a,fixerCategory:c,promptKind:i?.kind??null}}async function HH(e,t){try{let{stdout:n}=await Bg(e,["show","--shortstat","--format=",t]),r=/(\d+) files? changed/.exec(n),o=/(\d+) insertions?\(\+\)/.exec(n),s=/(\d+) deletions?\(-\)/.exec(n);return{files:r?Number(r[1]):0,insertions:o?Number(o[1]):0,deletions:s?Number(s[1]):0}}catch{return{files:0,insertions:0,deletions:0}}}async function WH(e){try{let{stdout:t}=await Bg(e,["rev-parse","--abbrev-ref","HEAD"]);return t.trim()||null}catch{return null}}async function rI(e,t,n,{cwd:r=t?.cwd,log:o=console,now:s=Date.now()}={}){if(!e?.id||!t?.name||!n||!r)return{recorded:!1,reason:"incomplete"};let a=await J(e);if(a.some(h=>h.type==="code.committed"&&h.payload?.sha===n))return{recorded:!1,reason:"duplicate"};let i=s,c=null;try{let{stdout:h}=await Bg(r,["show","-s","--format=%ct%n%s",n]),[g,...b]=h.split(`
206
206
  `),y=Number(g.trim())*1e3;Number.isFinite(y)&&y>0&&(i=y),c=b.join(`
207
207
  `).trim().slice(0,300)||null}catch{return{recorded:!1,reason:"unknown-sha"}}let l=tI(t,i),u=await HH(r,n),d=await WH(r),p=await D(e,{type:"code.committed",actor:"agent",source:"hook",boxId:t.name,provider:t.agent??null,payload:{sha:n,ref:d,subject:c,...u,ts:i}}),m=null,w=!1;try{let h=await Z_(r,n,{fixKey:ii({trackId:e.id,boxId:t.name,epoch:l}),window:Co,context:{...UH(e,t,a,l),ref:d,provider:t.agent??null}});if(h&&(m=await D(e,{type:"code.rework",actor:"system",source:"orchestrator",boxId:t.name,provider:t.agent??null,causationId:p.id,payload:h}),!(e?.workspace?.kind==="worktree"&&!!e?.workspace?.branch)&&Q_(h))){let b=ml(h),y=h.origins.filter(x=>x.class==="rework").slice(0,3);await D(e,{type:"rework.cause.offered",actor:"orchestrator",source:"orchestrator",boxId:t.name,provider:t.agent??null,causationId:m.id,payload:{sha:n,subject:h.subject,linesReworked:b,origins:y.map(x=>({key:x.key,provider:x.provider,model:x.model,lines:x.lines,ageDays:x.ageDays})),heuristic:h.heuristic,intent:h.intent,ts:i}}),w=!0}}catch(h){o.warn?.(`[rework] ${e.id}: analysis of ${String(n).slice(0,7)} failed: ${h?.message||h}`)}return{recorded:!0,event:p,rework:m,offered:w}}function oI(e,t){let n=0;for(let r of e)r.payload?.sha===t&&(r.type==="rework.cause.answered"?n++:r.type==="rework.cause.retracted"&&n--);return n>0}async function sI(e,t,n){if(!hl.includes(n)&&n!==qp)throw new Error(`bad cause "${n}" (${hl.join("|")}|${qp})`);let r=await J(e),o=r.find(s=>s.type==="rework.cause.offered"&&s.payload?.sha===t);if(!o)throw new Error("unknown rework offer");if(oI(r,t))throw new Error("already answered");return D(e,{type:"rework.cause.answered",actor:"user",source:"orchestrator",boxId:o.boxId??null,causationId:o.id,payload:{sha:t,...Array.isArray(o.payload?.shas)?{shas:o.payload.shas}:{},cause:n,level:"B",ts:Date.now()}})}async function aI(e,t){let n=await J(e);if(!oI(n,t))throw new Error("no standing answer to retract");let r=[...n].reverse().find(o=>o.type==="rework.cause.answered"&&o.payload?.sha===t);return D(e,{type:"rework.cause.retracted",actor:"user",source:"orchestrator",boxId:r?.boxId??null,causationId:r?.id,payload:{sha:t,...Array.isArray(r?.payload?.shas)?{shas:r.payload.shas}:{},ts:Date.now()}})}async function zp(e,{repo:t=null,number:n,title:r="",branch:o=null,url:s=null}={},{log:a=console,now:i=Date.now()}={}){try{if(!e?.id||n==null)return{offered:!1,reason:"incomplete"};let c=await J(e);if(c.some(y=>y.type==="rework.cause.offered"&&y.payload?.pr?.number===n&&(t==null||y.payload.pr.repo===t)))return{offered:!1,reason:"duplicate"};let l=new Set;for(let y of c)if(y.type==="rework.cause.offered")for(let x of Array.isArray(y.payload?.shas)?y.payload.shas:[y.payload?.sha])x&&l.add(x);let u=new Map;for(let y of c)y.type==="code.committed"&&y.payload?.sha&&u.set(y.payload.sha,y.payload.ref??null);let d=Dg({heuristic:Kp({subject:r}),subject:r,ref:o}),p=[];for(let y of c){if(y.type!=="code.rework")continue;let x=y.payload||{};if(!x.sha||l.has(x.sha)||x.codeDelta===!1||o&&u.has(x.sha)&&u.get(x.sha)!==o)continue;let E=x.intent?.intent??"unknown";(ci.has(E)||E==="unknown"&&ci.has(d.intent))&&ml(x)!==0&&p.push(x)}let m=p.reduce((y,x)=>y+ml(x),0);if(m<Pg)return{offered:!1,reason:"below-threshold"};let w=new Map;for(let y of p)for(let x of y.origins??[]){if(x.class!=="rework")continue;let E=w.get(x.key)??{key:x.key,provider:x.provider??null,model:x.model??null,lines:0,ageDays:x.ageDays};E.lines+=x.lines,E.ageDays=Math.min(E.ageDays,x.ageDays),w.set(x.key,E)}let h=p.map(y=>y.sha),g=p.map(y=>y.heuristic).find(y=>y&&y.level!=="C")??Kp({subject:r})??p.map(y=>y.heuristic).find(Boolean)??null,b=ci.has(d.intent)?d:p.find(y=>ci.has(y.intent?.intent))?.intent??d;return await D(e,{type:"rework.cause.offered",actor:"orchestrator",source:"orchestrator",boxId:null,payload:{sha:h[h.length-1],shas:h,pr:{repo:t,number:n,title:String(r||"").slice(0,200),url:s,branch:o},subject:String(r||"").slice(0,200)||p[p.length-1].subject,linesReworked:m,origins:[...w.values()].sort((y,x)=>x.lines-y.lines).slice(0,3),heuristic:g,intent:b,ts:i}}),{offered:!0,shas:h}}catch(c){return a.warn?.(`[rework] ${e?.id}: PR-level offer for #${n} failed: ${c?.message||c}`),{offered:!1,reason:"error"}}}var LH,Bg,Jp=V(()=>{ke();Kd();Vp();LH=BH(DH),Bg=(e,t)=>LH("git",["-C",e,...t],{maxBuffer:16*1024*1024,timeout:3e4})});import{execFile as qH}from"node:child_process";import{promisify as GH}from"node:util";async function Lg(e,t,{midTurn:n=Es,pollMs:r=KH,capMs:o=VH}={}){let s=Date.now()+o;for(;await n(e,t).catch(()=>!1);){if(Date.now()>=s)return!1;await new Promise(a=>setTimeout(a,r))}return!0}function pI(e){let t=String(e||""),n=0;for(let r=0;r<64;r++){iI.lastIndex=n;let o=iI.exec(t);if(!o)break;n=o.index+o[0].length;let s=o[1]==="-",a=o[2]??o[3]??o[4],i=t.indexOf(`
208
208
  `,o.index);if(i<0)break;let l=new RegExp("^"+(s?"\\t*":"")+eW(a)+"[ \\t]*$","m").exec(t.slice(i+1));if(!l)continue;let u=i+1+l.index+l[0].length;t=t.slice(0,i)+t.slice(u)}return t}function jg(e,t){return e.slice(t).replace(/^[\s;&|)]+/,"").replace(/"[^"]*"|'[^']*'/g,'""').split(/[;&|\n]/)[0]}function hI(e){let t=pI(e),n=t.match(XH);if(!n)return null;let r=jg(t,n.index);return QH.test(r)?null:{repo:r.match(fI)?.[1]??null,head:r.match(tW)?.[1]??null}}function mI(e){let t=pI(e),n=t.match(ZH);if(!n)return null;let r=jg(t,n.index),o=jg(t,n.index+n[0].length),s=null,a=o.trim().split(/\s+/).filter(Boolean);for(let i=0;i<a.length;i++){let c=a[i];if(c.startsWith("-")){rW.has(c)&&i++;continue}s=c.replace(/^["']+|["']+$/g,"")||null;break}return{repo:r.match(fI)?.[1]??null,selector:s,auto:/\s--auto\b/.test(r)}}async function sW(e,t,{exclude:n=()=>!1}={}){let r=async i=>{Ar("observer");let{stdout:c}=await cI("gh",["pr","list","--repo",e,"--author","@me","--state","all","--limit","10","--json",oW],{timeout:3e4,maxBuffer:4*1024*1024,env:{...process.env,...i}}).catch(l=>{throw $o(l)&&Ro(l),l});return JSON.parse(c||"[]")},o=i=>(i||[]).filter(c=>Date.parse(c.createdAt)>=t-zH&&!n(c)),s=await Fn({slug:e}),a=o(await r(s));return!a.length&&s.GH_TOKEN&&(a=o(await r({}).catch(()=>[]))),a.sort((i,c)=>Date.parse(c.createdAt)-Date.parse(i.createdAt))}async function aW(e,t){if(t)return[t];let n=[];for(let r of wI(e)){let o=await De(r).catch(()=>null);o&&!n.includes(o)&&n.push(o)}for(let r of await fr().catch(()=>[])){let o=await De(r.path).catch(()=>null);o&&!n.includes(o)&&n.push(o)}return n}function wI(e){let t=e.workspace;return t?.kind==="multi"?(t.repos??[]).map(n=>n?.base).filter(Boolean):[t?.base||e.cwd].filter(Boolean)}async function iW(e,t,n){let r=await ai(e).catch(()=>[e.workspace?.branch].filter(Boolean)),o=t?.head??null,s=c=>r.includes(c)||o&&c===o,a=c=>o!=null&&!s(c.headRefName)||nW(c.headRefName,e.id),i=[];for(let c of await aW(e,t?.repo??null)){let l;try{l=await sW(c,n,{exclude:a})}catch{continue}for(let u of l){let d=await bt(c,u.number);if(s(u.headRefName)){if(d&&d.trackId===e.id&&d.announced)return{settled:!0};if(d&&d.trackId!==e.id)continue;return{slug:c,pr:u}}d&&(d.trackId!==e.id||d.announced)||i.push({slug:c,pr:u})}}return i.length?(i.sort((c,l)=>Date.parse(l.pr.createdAt)-Date.parse(c.pr.createdAt)),i[0]):null}function gI(e){if(!e)return 0;let t=0;for(let n of Ir)n.startsWith(`${e}|`)&&t++;return t}function yI(){for(let e of[...Fg])e()}function bI(e,t,{delays:n=lI,turnEnd:r}={}){let o=hI(t.command);if(!o)return null;let s=!!mI(t.command),a=`${e.id}|${t.id??t.ts??t.command}`;if(Ir.has(a))return null;Ir.add(a);let i=t.ts??Date.now(),c=(async()=>{try{for(let l of n){await new Promise(h=>{let g=()=>{clearTimeout(b),Fg.delete(g),h()},b=setTimeout(g,l);Fg.add(g)});let u=await iW(e,o,i).catch(()=>null);if(u?.settled)return null;if(!u)continue;let{slug:d,pr:p}=u,{link:m,created:w}=await rn({repo:d,number:p.number,trackId:e.id,url:p.url,headRef:p.headRefName,title:p.title,source:"observed"});return!w&&!(m?.trackId===e.id&&await vr(d,p.number))?null:(await Lg(t.box,t.agent,r),await Er({repo:d,number:p.number,via:"observer"}).catch(()=>{}),await D({id:e.id,cwd:e.cwd},{type:"pr.state.changed",actor:"agent",source:"transcript",boxId:t.box??null,provider:t.agent??null,payload:{ts:Date.now(),change:"opened",number:p.number,url:p.url,title:p.title,branch:p.headRefName,repo:d,...s?{selfMerge:!0}:{}}}),p)}return null}finally{Ir.delete(a)}})();return c.catch(()=>Ir.delete(a)),c}function kI(e,t,{delays:n=lI,turnEnd:r,openedWait:o}={}){let s=mI(t.command);if(!s)return null;let a=`merge|${e.id}|${t.id??t.ts??t.command}`;if(Ir.has(a))return null;Ir.add(a);let i=(async()=>{try{let c=s.repo,l=s.selector,u=l?.match(/github\.com\/([\w.-]+\/[\w.-]+)\/pull\/(\d+)/);u&&([,c,l]=u);let d=[];if(c)d=[c];else{let w=wI(e);if(w.length>1&&/^\d+$/.test(String(s.selector??"")))return null;for(let h of w){let g=await De(h).catch(()=>null);g&&!d.includes(g)&&d.push(g)}}if(l||=(await ai(e).catch(()=>[])).filter(w=>w!==e.workspace?.branch)[0]||e.workspace?.branch,!d.length||!l)return null;c=d[0];let p=async(w,h)=>{let g=await bt(c,w.number);return g&&g.trackId!==e.id?null:(g||await rn({repo:c,number:w.number,trackId:e.id,url:w.url,headRef:w.headRefName,title:w.title,source:"merge-observed"}),await il(c,w.number),h&&((await J(e).catch(()=>[])).some(x=>x.type==="pr.state.changed"&&(x.payload?.change==="auto-armed"||x.payload?.change==="merged")&&x.payload?.number===w.number)||(await Lg(t.box,t.agent,r),await D({id:e.id,cwd:e.cwd},{type:"pr.state.changed",actor:"agent",source:"transcript",boxId:t.box??null,provider:t.agent??null,payload:{ts:Date.now(),change:"auto-armed",number:w.number,url:w.url,title:w.title,branch:w.headRefName,repo:c}}))),w)},m=null;for(let w of n){await new Promise($=>setTimeout($,w));let h=[];for(let $ of d)try{Ar("observer");let{stdout:P}=await cI("gh",["pr","view",String(l),"--repo",$,"--json",cW],{timeout:3e4,maxBuffer:4*1024*1024,env:{...process.env,...await Fn({slug:$})}}),L=JSON.parse(P||"null");L?.number&&h.push({slug:$,pr:L})}catch(P){$o(P)&&Ro(P)}let g=h.find($=>$.pr.state==="MERGED")??(h.length===1?h[0]:null);if(!g)continue;c=g.slug;let b=g.pr;if(!b?.number)continue;if(b.state==="CLOSED")return null;if(b.state!=="MERGED"){if(m=b,s.auto)return p(b,!0);continue}let y=await bt(c,b.number);if(y&&y.trackId!==e.id)return null;y||await rn({repo:c,number:b.number,trackId:e.id,url:b.url,headRef:b.headRefName,title:b.title,source:"merge-observed"}),await Lg(t.box,t.agent,r);let x=await J(e).catch(()=>[]);if(x.some($=>$.type==="pr.state.changed"&&$.payload?.change==="merged"&&$.payload?.number===b.number))return null;let E=$=>$.some(P=>P.type==="pr.state.changed"&&P.payload?.change==="opened"&&P.payload?.number===b.number),A=0;if(!E(x)){if(hI(t.command)&&await vr(c,b.number)){await Er({repo:c,number:b.number,via:"observer-merge"}).catch(()=>{});let $=Date.now();A=$+1,await D({id:e.id,cwd:e.cwd},{type:"pr.state.changed",actor:"agent",source:"transcript",boxId:t.box??null,provider:t.agent??null,payload:{ts:$,change:"opened",number:b.number,url:b.url,title:b.title,branch:b.headRefName,repo:c,selfMerge:!0}})}else if((await bt(c,b.number))?.announced){let $=o?.capMs??JH,P=o?.pollMs??YH,L=Date.now()+$;for(;Date.now()<L&&(await new Promise(T=>setTimeout(T,P)),!E(await J(e).catch(()=>[]))););}}return await D({id:e.id,cwd:e.cwd},{type:"pr.state.changed",actor:"agent",source:"transcript",boxId:t.box??null,provider:t.agent??null,payload:{ts:Math.max(Date.now(),A),change:"merged",number:b.number,url:b.url,title:b.title,branch:b.headRefName,repo:c}}),await zp(e,{repo:c,number:b.number,title:b.title,branch:b.headRefName,url:b.url}).catch(()=>{}),await Rr(c,b.number).catch(()=>{}),await $r(c,b.number).catch(()=>{}),await _o(c,b.number,"merged"),b}return m?p(m,!1):null}finally{Ir.delete(a)}})();return i.catch(()=>Ir.delete(a)),i}var cI,lI,KH,VH,zH,JH,YH,uI,dI,XH,ZH,QH,iI,eW,fI,tW,nW,rW,oW,Ir,Fg,cW,Yp=V(()=>{ke();Xr();Tt();ll();zn();Oo();Or();_s();Hs();Jp();cI=GH(qH),lI=[4e3,15e3,45e3],KH=2500,VH=5*6e4;zH=15e3,JH=9e4,YH=2e3,uI=/(?:^|[;&|\n({`]\s*|\)\s*)(?:(?:then|do|else|elif|if|while|until|time)\s+)?/.source,dI=/gh\s+(?:[^\s;&|"'`$]+\s+)*?pr\s+/.source,XH=new RegExp(`${uI}${dI}create\\b`),ZH=new RegExp(`${uI}${dI}merge\\b`),QH=/\s--web\b/,iI=/<<(-?)\s*(?:'([^'\n]+)'|"([^"\n]+)"|\\?([A-Za-z_][\w-]*))/g,eW=e=>e.replace(/[.*+?^${}()|[\]\\-]/g,"\\$&");fI=/(?:--repo|-R)[\s=]+([\w.-]+\/[\w.-]+)/,tW=/(?:--head|-H)[\s=]+([^\s"'`;&|]+)/,nW=W_;rW=new Set(["--subject","-t","--body","-b","--body-file","-F","--match-head-commit","--author-email","-A","--repo","-R"]);oW="number,url,title,headRefName,createdAt";Ir=new Set;Fg=new Set;cW="number,url,title,headRefName,state"});import lW from"node:fs/promises";import Hg from"node:path";import uW from"node:os";function Ug(e,t){let n=new RegExp(`\\b${t}="([^"]*)"`).exec(e);return n?n[1]:null}function Xp(e){let t=dW.exec(String(e||""));if(!t)return null;let[,n,r]=t,o=Ug(n,"from"),s=o?o.replace(/^uds:/,""):null,a=xI(s);return{socket:s,pid:a,name:Ug(n,"from-name"),mode:Ug(n,"from-mode"),text:r.trim()}}function xI(e){let t=/(\d+)\.sock$/.exec(String(e||""));return t?Number(t[1]):null}function pW(){return process.env.CLAUDE_CONFIG_DIR?Hg.join(process.env.CLAUDE_CONFIG_DIR,"sessions"):Hg.join(uW.homedir(),".claude","sessions")}async function fW(e){let t=xI(e);if(!t)return null;try{let n=await lW.readFile(Hg.join(pW(),`${t}.json`),"utf8"),r=JSON.parse(n);return{pid:t,sessionId:r.sessionId??null,cwd:r.cwd??null,name:r.name??null,tmux:r.tmux??null}}catch{return null}}async function vI(e,t){let n=await fW(e?.socket),r=n?.cwd??null,o=null;if((n?.sessionId||r)&&typeof t=="function")try{o=await t(n?.sessionId??null,r)??null}catch{o=null}return{socket:e?.socket??null,pid:n?.pid??e?.pid??null,sessionId:n?.sessionId??null,cwd:r,tmux:n?.tmux??null,name:n?.name??e?.name??null,mode:e?.mode??null,trackId:o?.track?.id??null,trackName:o?.track?.name??null,boxId:o?.box?.name??null}}var dW,Wg=V(()=>{dW=/<cross-session-message\b([^>]*)>([\s\S]*?)<\/cross-session-message>/});function hW(e,t){let n=0;for(let o of e||[]){if(o?.type!=="track.obligations.changed")continue;let s=Number(o.payload?.open);n=Number.isFinite(s)&&s>0?Math.floor(s):0}let r=Number(t?.openActions)||0;return r===n?null:{open:r,since:r?t.openActionSince??null:null}}async function mW(e,t,n){let r=hW(t,n);return r?D(e,{type:"track.obligations.changed",actor:"system",source:"orchestrator",payload:{ts:Date.now(),open:r.open,since:r.since}}).catch(()=>null):null}function li(e){let t=r=>Number(r.payload?.ts??r.ts??0)||0,n={askedAt:0,closedAt:0,hookClosedAt:0,abortedAt:0};for(let r of e||[])r&&(r.type==="turn.user"||r.type==="peer.message"?n.askedAt=Math.max(n.askedAt,t(r)):r.type==="turn.agent"?(n.closedAt=Math.max(n.closedAt,t(r)),r.source==="hook"&&(n.hookClosedAt=Math.max(n.hookClosedAt,t(r)))):r.type==="turn.aborted"&&(n.abortedAt=Math.max(n.abortedAt,t(r))));return n}function AI(e){let t=li(e);return t.askedAt?t.askedAt>Math.max(t.closedAt,t.abortedAt):!1}function gW(e,{epochStartedAt:t=null}={}){let n=l=>Number(l.payload?.ts??l.ts??0)||0,r=li(e),o=null,s=null,a=null;for(let l of e||[]){if(!l)continue;let u=l.payload||{};l.type==="turn.interrupted"?(u.result==="stopped"||u.result==="stopped-late")&&u.busyAtClick!==!1&&n(l)>=(o?.at||0)&&(o={at:n(l),unsent:!!u.unsent,busyAtClick:u.busyAtClick===!0}):l.type==="turn.aborted"?n(l)>=(s?.at||0)&&(s={at:n(l),cause:u.cause||"cli-exited",agent:u.agent||l.provider||null}):l.type==="provider.error"&&n(l)>=(a?.at||0)&&(a={at:n(l),cls:u.cls||"other",provider:l.provider||null})}let i=Math.max(r.askedAt,Number(t)||0),c=[];if(o&&o.at>i&&(r.askedAt||o.busyAtClick)&&c.push({at:o.at,source:"stop",summary:o.unsent?"stopped before it started \u2014 your message is back in the composer":"you stopped the agent"}),s&&s.at>i&&c.push({at:s.at,source:`abort:${s.cause}`,summary:SI[s.cause]||SI["cli-exited"]}),a&&r.askedAt&&a.at>i&&a.at>r.closedAt){let l=wW[a.cls]||"returned an error";c.push({at:a.at,source:"provider-error",summary:`${a.provider||"the provider"} ${l} instead of finishing the turn`})}return c.length?c.reduce((l,u)=>u.at>l.at?u:l):null}function yW(e,t){let n=null;for(let o of e||[]){if(o?.type!=="track.interrupted.changed")continue;let s=o.payload||{};n=s.at?{at:Number(s.at)||0,source:s.source||null}:null}let r=t?.at?{at:t.at,source:t.source||null}:null;return!r&&!n||r&&n&&r.at===n.at&&r.source===n.source?null:{at:r?.at??null,source:r?.source??null,summary:t?.summary??null}}async function bW(e,t,n){let r=yW(t,n);return r?D(e,{type:"track.interrupted.changed",actor:"system",source:"orchestrator",payload:{ts:Date.now(),...r}}).catch(()=>null):null}async function qg(e){if(Zp.has(e.id))return Zp.get(e.id);let t=await J(e).catch(()=>[]),n=[];try{n=Gn(t)}catch{}let r=Jd(n),o=n.filter(g=>g?.kind==="followup-offer"&&g.status==="open"),s=new Set(t.filter(g=>g.type==="prompt.answered").map(g=>g.payload?.promptId)),a=t.filter(g=>g.type==="prompt.raised"&&g.payload?.promptId&&!s.has(g.payload.promptId)),i=[...r,...o,...a.map(g=>({ts:g.payload?.ts??g.ts}))],c=null;for(let g of t){if(g.type!=="track.phase.changed")continue;let b=g.payload||{};c=b.phase?{phase:b.phase,summary:b.summary??null,scope:b.scope??null,phaseId:b.phaseId??null,at:b.ts??g.ts}:null}let l=n.flatMap(g=>g?.kind==="job-dock"?g.jobs||[]:[]).filter(g=>g?.status==="running"),u=t.reduce((g,b)=>b.type==="turn.agent"?Math.max(g,b.payload?.ts??b.ts??0):g,0)||null,d=t.reduce((g,b)=>b.type==="turn.user"?Math.max(g,b.payload?.ts??b.ts??0):g,0)||null,p=(e.boxes||[]).find(g=>g.name===e.leadBox),m=Array.isArray(p?.epochs)&&p.epochs.length?p.epochs[p.epochs.length-1]:null,w=gW(t,{epochStartedAt:m?.startedAt??null}),h={openActions:i.length,openActionSince:i.length?Math.min(...i.map(g=>g.ts||Date.now())):null,phase:c,completedTurnAt:u,currentTurnAt:d,interrupted:w,runningJobs:l.length,runningJobsSince:l.length?Math.min(...l.map(g=>g.startedTs||Date.now())):null};return Zp.set(e.id,h),!He(e)&&e.kind!=="setup"&&(mW(e,t,h),bW(e,t,w)),h}function TI({trackOf:e,debounceMs:t=kW,log:n=console}={}){if(typeof e!="function")throw new Error("watchObligations: trackOf(id) is required");let r=o=>{let s=o?.trackId;if(!s)return;clearTimeout(wl.get(s));let a=setTimeout(()=>{wl.delete(s),Promise.resolve(e(s)).then(i=>i&&!He(i)&&i.kind!=="setup"?qg(i):null).catch(i=>n.warn?.(`[obligations] fold ${s} failed: ${i?.message||i}`))},t);a.unref?.(),wl.set(s,a)};return et.on("event",r),()=>{et.off("event",r);for(let o of wl.values())clearTimeout(o);wl.clear()}}var Zp,SI,wW,kW,wl,gl=V(()=>{ke();Yd();pn();Zp=new Map;et.on("event",e=>{e?.trackId&&Zp.delete(e.trackId)});SI={"cli-exited":"the agent exited before finishing","session-gone":"the agent's session is gone before it finished","terminal-esc":"interrupted with Esc in the terminal"},wW={rate_limit:"hit a rate limit",entitlement:"refused the request (plan / credits)",auth:"needs a login",overloaded:"was overloaded",server:"returned a server error"};kW=750,wl=new Map});function EI(e=process.env){return!!(je(e)&&e.BOSTRAT_PLANE_TOKEN)}async function _I(e,t,n=Gg){let r=new AbortController,o=setTimeout(()=>r.abort(),n);try{return await vW(`${je(t)}${e}`,{headers:SW(t),signal:r.signal})}finally{clearTimeout(o)}}async function yl({env:e=process.env,force:t=!1,timeoutMs:n=Gg}={}){if(!EI(e))return{followups:[],source:"unconfigured"};if(!t&&Ws&&Date.now()-Ws.at<xW)return{followups:Ws.followups,source:"cache"};try{let r=await _I("/v1/followups?deleted=1",e,n);if(!r.ok)throw new Error(`plane ${r.status}`);let o=await r.json(),s=Array.isArray(o?.followups)?o.followups:[];return Ws={at:Date.now(),followups:s},{followups:s,source:"plane"}}catch(r){return Ws?{followups:Ws.followups,source:"stale",error:r?.message}:{followups:[],source:"unreachable",error:r?.message}}}async function II(e,{env:t=process.env,timeoutMs:n=Gg}={}){if(!e)return{followup:null,source:"unconfigured"};if(!EI(t))return{followup:null,source:"unconfigured"};try{let r=await _I(`/v1/followups/${encodeURIComponent(e)}`,t,n);if(r.status===404)return{followup:null,source:"gone"};if(!r.ok)throw new Error(`plane ${r.status}`);return{followup:(await r.json())?.followup??null,source:"plane"}}catch(r){let o=Ws?.followups.find(s=>s.id===e)??null;return o?{followup:o,source:"stale",error:r?.message}:{followup:null,source:"unreachable",error:r?.message}}}var xW,Gg,Ws,vW,SW,$I=V(()=>{Tt();xW=6e4,Gg=5e3,Ws=null,vW=(...e)=>fetch(...e);SW=e=>({authorization:`Bearer ${e.BOSTRAT_PLANE_TOKEN||""}`})});async function No(e,t){if(Kg.has(e)){let n=new Error("offer already answered (answer in flight)");throw n.code="answer-in-flight",n}Kg.add(e);try{return await t()}finally{Kg.delete(e)}}var Kg,bl=V(()=>{Kg=new Set});import{randomUUID as Gs,createHash as AW}from"node:crypto";function Qp(e){return String(e||"").toLowerCase().replace(/[^a-z0-9]+/g," ").trim()}function jI(e){for(let[t,n]of IW)if(t.test(String(e||"")))return`a standing prompt must not embed this Track's specifics (${n}) \u2014 the card supplies them at fire time; arm a one-shot with \`offer\` instead`;return null}function CI(e,{at:t="",promptRequired:n=!0,standing:r=!1}={}){let o=e&&typeof e=="object"?e:{},s=Ks(o.label).replace(/\s+/g," ");if(!s)throw new Error(`${t}label required (\u2264${Vg} chars, e.g. "Deploy to Pi")`);if(s.length>Vg)throw new Error(`${t}label must be \u2264${Vg} characters`);let a=Ks(o.prompt);if(n&&!a)throw new Error(`${t}prompt required \u2014 the full instruction a fresh session could execute`);if(Buffer.byteLength(a,"utf8")>RI)throw new Error(`${t}prompt must be \u2264${RI} bytes`);if(r){let l=jI(a);if(l)throw new Error(`${t}${l}`)}let i=o.standing==null||o.standing===""?"offerable":String(o.standing).trim().toLowerCase();if(!_W.includes(i))throw new Error(`${t}standing must be "offerable" or "never", got "${o.standing}"`);let c=Ks(o.why).slice(0,DI)||null;return{label:s,prompt:a,why:c,standing:i}}function FI(e,{standing:t=!1}={}){let n=e&&typeof e=="object"?e:{},r=Ks(n.trigger)||(n.ship?"now":""),o=t?TW:BI.filter(p=>p!=="track.opened");if(!o.includes(r))throw new Error(`trigger must be one of ${o.join(" | ")}${t?" (a standing follow-up can't be `now` \u2014 it would fire every turn)":""}, got "${n.trigger??""}"`);let s=n.ship&&r==="now"?OW(n.ship):null,a=n.items!=null;if(a&&s)throw new Error("a ship offer has its own card \u2014 `items` cannot be combined with a `ship` block");let i,c=null;if(a){if(!Array.isArray(n.items)||!n.items.length)throw new Error("items must be a non-empty array of {label, prompt, why?, standing?}");if(n.items.length>MI)throw new Error(`items must be \u2264${MI} \u2014 one item per step the operator might run, save or skip separately`);if(t&&n.items.length>1)throw new Error("propose one standing follow-up at a time \u2014 a standing follow-up is one prompt");i=n.items.map((m,w)=>CI(m,{at:`items[${w}]: `,standing:t})),c=Ks(n.why).slice(0,DI)||null;let p=new Set;for(let m of i){let w=Qp(m.label);if(p.has(w))throw new Error(`items must have distinct labels ("${m.label}" appears twice)`);p.add(w)}}else i=[CI(n,{promptRequired:!s,standing:t})];let l=i[0],u=c??l.why,d=t?RW(n.repo):null;return{label:l.label,prompt:l.prompt,trigger:r,why:u,planWhy:c,items:i,...d?{repo:d}:{},...s?{ship:s}:{}}}function $W(e){return e.standing==="never"?{promotable:!1,promotableReason:"one-off"}:jI(e.prompt)?{promotable:!1,promotableReason:"specifics"}:{promotable:!0,promotableReason:null}}function RW(e){if(e==null||e===""||e==="*")return null;let t=String(e).trim();if(!/^[\w.-]+\/[\w.-]+$/.test(t))throw new Error(`repo must be a forge slug like owner/name, got "${e}"`);return t}function OW(e){let t=e&&typeof e=="object"?e:{},n=Array.isArray(t.actions)?t.actions.map(i=>String(i).trim().toLowerCase()):zg.slice();for(let i of n)if(!zg.includes(i))throw new Error(`ship.actions may only contain ${zg.join(" | ")}, got "${i}"`);if(!n.length)throw new Error("ship.actions must name at least one of commit | push | pr");let r=t.rebase==null?"none":String(t.rebase).trim();if(!["offered","none"].includes(r))throw new Error(`ship.rebase must be "offered" or "none", got "${t.rebase}"`);let o=null;if(t.toPr!=null&&t.toPr!==""){let i=Number(t.toPr);if(!Number.isInteger(i)||i<=0)throw new Error(`ship.toPr must be a PR number, got "${t.toPr}"`);o=i}let s=Ks(t.base)||null,a=null;if(t.repos!=null){if(!Array.isArray(t.repos))throw new Error("ship.repos must be an array of checkout names");a=t.repos.map(i=>Ks(i)).filter(Boolean),a.length||(a=null)}return{actions:[...new Set(n)],rebase:r,toPr:o,base:s,repos:a}}function ef(e,{trigger:t=null}={}){let n=new Map;for(let r of e){let o=r.payload||{};if(r.type==="followup.armed"&&o.armId)o.replaces&&n.delete(o.replaces),n.set(o.armId,{...o,ts:o.ts??r.ts,boxId:r.boxId??null,provider:r.provider??null});else if(r.type==="followup.armed.cancelled"&&o.armId)n.delete(o.armId);else if(r.type==="followup.offered")for(let s of o.rows||[])s.armId&&n.delete(s.armId)}return[...n.values()].filter(r=>!t||r.trigger===t)}function UI(e){return{armId:e.armId,label:e.label,prompt:e.prompt,promptHash:LI(e.prompt),origin:"agent",why:e.why??null,groupId:e.groupId??null,seq:Number.isInteger(e.seq)?e.seq:0,standing:e.standing==="never"?"never":"offerable",...$W(e)}}async function HI(e,t,{pull:n=yl,ship:r={}}={}){if(Xg(e))throw new Error("follow-ups don't fire on a loop's run Track \u2014 report the outcome with `bostrat-loop report` instead");let o=FI(t);if(o.ship)return{kind:"ship",...await BW(e,o,r)};let s={id:e.id,cwd:e.cwd},a=(e.boxes||[]).find(y=>y.name===e.leadBox)||null,i={boxId:e.leadBox??null,provider:a?.agent??null},c=Gs(),l=(y,x,E={})=>({ts:Date.now(),armId:Gs(),trigger:o.trigger,label:y.label,prompt:y.prompt,why:y.why,standing:y.standing,groupId:c,seq:x,...o.planWhy?{planWhy:o.planWhy}:{},...E}),u={groupId:c,trigger:o.trigger,label:o.label,prompt:o.prompt,why:o.why,planWhy:o.planWhy};if(o.trigger==="now"){let y=Gs(),x=[];for(let[E,A]of o.items.entries()){let $=l(A,E);await D(s,{type:"followup.armed",actor:"agent",source:"cli",...i,payload:$}),x.push($)}return await D(s,{type:"followup.offered",actor:"system",source:"orchestrator",...i,payload:{ts:Date.now(),offerId:y,trigger:"now",repo:e.workspace?.repo||null,context:{},groupId:c,why:o.planWhy,rows:x.map(UI)}}),{kind:"now",offerId:y,armId:x[0].armId,items:x.map(E=>({armId:E.armId,label:E.label,standing:E.standing})),...u}}let d=e.workspace?.repo||null,{followups:p}=await n().catch(()=>({followups:[]})),m=await J(s),w=ef(m,{trigger:o.trigger}),h=[],g=0;for(let y of o.items){let x=Qp(y.label),E=p.find(L=>L.status==="active"&&L.mode!=="off"&&L.trigger===o.trigger&&(L.repo==null||L.repo===d)&&L.dedupeKey===x);if(E){h.push({label:y.label,standing:y.standing,covered:{id:E.id,label:E.label}});continue}let A=w.filter(L=>Qp(L.label)===x),$=A.length?A[A.length-1].armId:null,P=l(y,g++,$?{replaces:$}:{});await D(s,{type:"followup.armed",actor:"agent",source:"cli",...i,payload:P}),h.push({armId:P.armId,label:y.label,standing:y.standing,replaces:$})}let b=h.filter(y=>y.armId);return b.length?{kind:"armed",armId:b[0].armId,replaces:b[0].replaces,items:h,...u}:{kind:"covered",covered:h[0].covered,items:h,...u}}async function WI(e,t){if(!t)throw new Error("armId required");let n={id:e.id,cwd:e.cwd},r=await J(n);if(!ef(r).some(o=>o.armId===t))throw new Error("unknown or already-settled arm");return await D(n,{type:"followup.armed.cancelled",actor:"user",source:"orchestrator",payload:{ts:Date.now(),armId:t}}),{armId:t}}async function qI(e,t,{pull:n=yl}={}){if(Xg(e))throw new Error("propose from a lead Track, not a loop's run Track");let r=FI(t,{standing:!0}),o=r.repo??e.workspace?.repo??null,s={id:e.id,cwd:e.cwd};if((await J(s)).reduce((g,b)=>b.type==="followup.create.offered"?b.payload?.proposalId??g:b.type==="followup.create.answered"&&b.payload?.proposalId===g?null:g,null))throw new Error("a follow-up proposal is already waiting on the operator in this Track \u2014 one at a time");let{followups:c,source:l}=await n().catch(()=>({followups:[],source:"unreachable"}));if(l==="unreachable")throw new Error("plane unreachable \u2014 standing follow-ups live in the plane; try again shortly");let u=Qp(r.label),d=c.filter(g=>g.dedupeKey===u&&g.trigger===r.trigger),p=d.find(g=>g.status==="deleted"),m=d.find(g=>g.status!=="deleted");if(m)throw new Error(`"${m.label}" (${Yg[m.trigger]||m.trigger}) already exists as a standing follow-up \u2014 not re-proposed`);if(p){let g=p.deletedAt?new Date(p.deletedAt).toISOString().slice(0,10):"earlier";throw new Error(`the operator deleted "${p.label}" on ${g} \u2014 do not re-propose it`)}let w=Gs(),h=(e.boxes||[]).find(g=>g.name===e.leadBox)||null;return await D(s,{type:"followup.create.offered",actor:"agent",source:"cli",boxId:e.leadBox??null,provider:h?.agent??null,payload:{ts:Date.now(),proposalId:w,label:r.label,prompt:r.prompt,trigger:r.trigger,repo:o,why:r.why,origin:"agent"}}),{proposalId:w,label:r.label,prompt:r.prompt,trigger:r.trigger,repo:o,why:r.why}}async function GI(e,t,n,{followupId:r=null}={}){if(!t)throw new Error("proposalId required");let o={id:e.id,cwd:e.cwd},s=await J(o),a=s.find(c=>c.type==="followup.create.offered"&&c.payload?.proposalId===t);if(!a)throw new Error("unknown proposal");if(s.some(c=>c.type==="followup.create.answered"&&c.payload?.proposalId===t))throw new Error("proposal already answered");if(!n)return await D(o,{type:"followup.create.answered",actor:"user",source:"orchestrator",payload:{ts:Date.now(),proposalId:t,action:"dismiss"}}),{proposalId:t,action:"dismiss"};if(!r)throw new Error("followupId required \u2014 the follow-up is created on the plane before the card is answered");let i=a.payload;return await D(o,{type:"followup.created",actor:"user",source:"orchestrator",payload:{ts:Date.now(),proposalId:t,followupId:String(r),label:i.label,trigger:i.trigger,repo:i.repo??null}}),await D(o,{type:"followup.create.answered",actor:"user",source:"orchestrator",payload:{ts:Date.now(),proposalId:t,action:"created",followupId:String(r)}}),{proposalId:t,action:"created",followupId:String(r)}}async function kl(e,t,n={},{pull:r=yl}={}){if(!e||Xg(e))return null;let o={id:e.id,cwd:e.cwd},s=await J(o).catch(()=>[]),a=n.repo??e.workspace?.repo??null;if(t==="pr.merged"){let y=A=>{let $=(A?.prs||[]).filter(P=>Number.isFinite(Number(P?.number))).map(P=>`${P?.repo??A?.repo??""}#${Number(P.number)}`);return Number.isFinite(Number(A?.prNumber))&&$.push(`${A?.repo??""}#${Number(A.prNumber)}`),$},x=new Set(y(n));if(s.some(A=>A.type==="followup.offered"&&A.payload?.trigger==="pr.merged"&&y(A.payload?.context).some($=>x.has($))))return null}let i=ef(s,{trigger:t}),c=i.length?i[i.length-1].groupId??null:null,l=i.slice(0,OI).map(UI),u=c?i.find(y=>y.groupId===c&&y.planWhy)?.planWhy??null:null,d=[];if(t!=="now"){let{followups:y}=await r().catch(()=>({followups:[]}));d=y.filter(x=>x.status==="active"&&x.mode!=="off"&&x.trigger===t&&(x.repo==null||x.repo===a)).sort((x,E)=>{let A=$=>$.stats?.offered?($.stats.accepted||0)/$.stats.offered:0;return A(E)-A(x)||(x.origin==="operator"?-1:0)-(E.origin==="operator"?-1:0)||(E.createdAt||0)-(x.createdAt||0)}).slice(0,EW).map(x=>({followupId:x.id,label:x.label,promptPreview:MW(x.prompt),promptHash:LI(x.prompt),origin:x.origin,repo:x.repo??null}))}let p=[...l,...d].slice(0,OI);if(!p.length)return null;let m=Gs(),w={ts:Date.now(),offerId:m,trigger:t,repo:a,context:{...n,repo:a},groupId:c,why:u,rows:p},h=(e.boxes||[]).find(y=>y.name===e.leadBox)||null,g=i.find(y=>y.provider)?.provider??h?.agent??null,b=i.find(y=>y.boxId)?.boxId??e.leadBox??null;return await D(o,{type:"followup.offered",actor:"system",source:"orchestrator",boxId:b,provider:g,payload:w}),w}function CW(e,t){let n=t?.rows||[],r=new Map(n.map(s=>[qs(s),null])),o=(s,a)=>{r.has(s)&&r.get(s)==null&&r.set(s,a)};for(let s of e){if(s.type!=="followup.answered"||s.payload?.offerId!==t.offerId)continue;let a=s.payload,i=[];a.armId&&i.push(`arm:${a.armId}`),a.followupId&&i.push(`fu:${a.followupId}`);for(let c of Array.isArray(a.armIds)?a.armIds:[])i.push(`arm:${c}`);for(let c of Array.isArray(a.followupIds)?a.followupIds:[])i.push(`fu:${c}`);if(i.length)for(let c of i)o(c,a.action);else for(let c of r.keys())o(c,a.action)}return r}function Jg(e){let t=e?.context||{},n=Array.isArray(t.prs)&&t.prs.length?t.prs:t.prNumber?[{number:t.prNumber,title:t.prTitle,url:t.prUrl,repo:t.repo}]:[],r=o=>`PR #${o.number}${o.title?` "${o.title}"`:""}${o.url?` (${o.url})`:""}${o.repo?` on ${o.repo}`:""}`;switch(e?.trigger){case"pr.merged":return n.length?`Follow-up the operator tapped after ${n.map(r).join(" and ")} merged:`:"Follow-up the operator tapped after this Track's PR merged:";case"pr.opened":return n.length?`Follow-up the operator tapped after ${n.map(r).join(" and ")} opened:`:"Follow-up the operator tapped after this Track's PR opened:";case"checks.green":return n.length?`Follow-up the operator tapped after CI went green on ${n.map(r).join(" and ")}:`:"Follow-up the operator tapped after CI went green:";case"ship.done":return"Follow-up the operator tapped after the ship you just ran completed:";default:return"Follow-up the operator tapped:"}}async function KI(e,{offerId:t,followupId:n=null,armId:r=null,promoted:o=null,all:s=!1,rows:a=null,prompt:i=null,prompts:c=null,reordered:l=!1}={},u={}){if(!t)throw new Error("offerId required");if(a!=null&&!Array.isArray(a))throw new Error("rows must be an array of row keys");if(i!=null&&typeof i!="string")throw new Error("prompt must be a string");if(c!=null&&(typeof c!="object"||Array.isArray(c)))throw new Error("prompts must be an object of row key \u2192 text");return No(`fu:${e.id}:${t}`,()=>DW(e,{offerId:t,followupId:n,armId:r,promoted:o,all:s===!0,rows:a,prompt:i,prompts:c,reordered:l===!0},u))}function PI(e,t){if(e==null)return null;let n=String(e).replace(/\u0000/g,"").trim();if(!n)throw new Error("an edited prompt can't be empty \u2014 Reset it or type the step");if(n.length>NI)throw new Error(`an edited prompt must be \u2264${NI} characters`);return n===String(t??"").trim()?null:n}async function VI(e,{offerId:t,armId:n,followupId:r}={}){if(!t||!n||!r)throw new Error("offerId, armId and followupId required");let o={id:e.id,cwd:e.cwd},s=await J(o),a=s.find(c=>c.type==="followup.offered"&&c.payload?.offerId===t);if(!a)throw new Error("unknown offer");if(!(a.payload.rows||[]).find(c=>c.armId===n))throw new Error("that arm is not on this card");if(s.some(c=>c.type==="followup.arm.saved"&&c.payload?.armId===n))throw new Error("that row is already saved");return await D(o,{type:"followup.arm.saved",actor:"user",source:"orchestrator",payload:{ts:Date.now(),offerId:t,armId:n,followupId:String(r)}}),{offerId:t,armId:n,followupId:String(r)}}async function DW(e,{offerId:t,followupId:n,armId:r,promoted:o,all:s,rows:a,prompt:i,prompts:c,reordered:l},u){let{sayToLead:d,unarchiveTrack:p,getFollowup:m=II}=u,w={id:e.id,cwd:e.cwd},h=await J(w),g=h.find(I=>I.type==="followup.offered"&&I.payload?.offerId===t);if(!g)throw new Error("unknown offer");let b=g.payload.rows||[],y=CW(h,g.payload),x=NW(y,b);if(!x.length)throw new Error("offer already answered");let E=I=>D(w,{type:"followup.answered",actor:"user",source:"orchestrator",payload:{ts:Date.now(),offerId:t,...I}}),A=async()=>{if(!e.archivedAt)return!1;if(!p)throw new Error("this Track is archived");return await p(e.id,{freshSession:!0}),e={...e,archivedAt:null},!0},$=I=>{let U=h.find(W=>W.type==="followup.armed"&&W.payload?.armId===I.armId)?.payload?.prompt??I.prompt;if(!U)throw new Error("the arm's prompt is missing from the log");return U};if(s||a){let I,S=!1;if(a){let Y=[...new Set(a.map(Pe=>String(Pe)))];if(!Y.length)throw new Error("rows must name at least one item");let ne=new Map(b.map(Pe=>[qs(Pe),Pe]));for(let Pe of Y){let ae=ne.get(Pe);if(!ae)throw new Error(`${Pe} is not on this card`);if(!ae.armId)throw new Error("a standing follow-up runs on its own \u2014 it is not part of a batch");if(y.get(Pe)!=null)throw new Error("that row is already answered")}let Ie=b.filter(Pe=>Y.includes(qs(Pe)));I=l?Y.map(Pe=>ne.get(Pe)):Ie,S=l&&I.some((Pe,ae)=>Pe!==Ie[ae])}else I=x.filter(Y=>Y.armId);if(!I.length)throw new Error("nothing to run together \u2014 no open items from this plan remain on the card");let U=new Map;if(c){let Y=new Map(I.map(ne=>[qs(ne),ne]));for(let[ne,Ie]of Object.entries(c)){let Pe=Y.get(ne);if(!Pe)throw new Error(`${ne} is not in this batch \u2014 prompts can only edit the rows being sent`);let ae=PI(Ie,$(Pe));ae!=null&&U.set(ne,ae)}}let W=I.map(Y=>({row:Y,key:qs(Y),prompt:U.get(qs(Y))??$(Y)})),ie=await A();if(!d)throw new Error("sayToLead unavailable");let z=W.length===1?`${Jg(g.payload)}
@@ -231,7 +231,7 @@ ${n.trim().split(`
231
231
  `),await Ky.rename(d,a),r.log?.(`[spine-pull] rehydrated ${o}: ${l.length} event(s) \u2192 ${a}`),{restored:!0,rows:l.length}}var W5,q5,G5,JR=V(()=>{Tt();ke();W5=1e3,q5=5e5,G5=3e4});function YR(e,t=Date.now()){let n=e.find(s=>s.reconcile||s.ciFix);if(n?.reconcile)return{status:"working",since:n.reconcile.delegatedAt,summary:"reconciling the branch"};if(n?.ciFix)return{status:"working",since:n.ciFix.delegatedAt,summary:"repairing failed checks"};let r=e.find(s=>s.reconcileAwait||s.ciFixAwait);if(r?.reconcileAwait)return{status:"waiting",since:r.reconcileAwait.since,summary:"fix pushed \u2014 waiting for mergeability"};if(r?.ciFixAwait)return{status:"waiting",since:r.ciFixAwait.since,summary:"fix pushed \u2014 waiting for CI"};let o=e.filter(s=>s.autoMerge||s.armedAt);return o.length?{status:"waiting",since:Math.min(...o.map(s=>s.autoMerge?.armedAt||s.armedAt||t)),count:o.length,summary:o.length===1?"auto-merge armed \u2014 lands when checks pass":`auto-merge armed on ${o.length} PRs`}:null}function XR(e){let t=(e||[]).filter(n=>!V5.has(n.state)&&!n.ciFix&&!n.reconcile&&!n.ciFixAwait&&!n.reconcileAwait&&!n.autoMerge&&!n.armedAt);return t.length?{count:t.length,since:Math.min(...t.map(n=>n.announcedAt||n.firstSeen||Date.now())),summary:t.length===1?`PR #${t[0].number} is open \u2014 review, merge or arm it`:`${t.length} open PRs waiting on you`}:null}function ZR({archivedAt:e=null,archiving:t=!1,prompted:n=!1,openActions:r=0,openActionSince:o=null,loopAttention:s=!1,prDecisions:a=null,operation:i=null,phase:c=null,working:l=!1,workingSince:u=null,pending:d=null,interrupted:p=null,completedTurnAt:m=null,live:w=!1,now:h=Date.now()}={}){if(e&&!t)return sn("archived","lifecycle",e);if(n)return sn("needs-you","pane",o||h,{count:r||1});if(t)return sn("archiving","lifecycle",e||h);if(i?.status==="working")return sn("working","operation",i.since,{summary:i.summary??null,count:i.count??null});if((l||n)&&c?.phase)return sn("working","agent-phase",c.at,{summary:c.summary??null});if(l)return sn("working","pane",u||h);if(r>0||s)return sn("needs-you",s?"loop":"obligations",o||h,{count:r||1});if(a?.count)return sn("needs-you","pr",a.since,{count:a.count,summary:a.summary??null});if(p?.at){let g=i?.status==="waiting"?i.summary:d?.count?d.summary:null,b=[p.summary,g].filter(Boolean).join(" \xB7 ")||null;return sn("interrupted",p.source||"interrupted",p.at,{summary:b})}return i?.status==="waiting"?sn("waiting","operation",i.since,{summary:i.summary??null,count:i.count??null}):d?.count?sn("waiting",d.source||"pending",d.since,{summary:d.summary??null,count:d.count}):m&&w?sn("settled","obligations",m,{summary:"no open actions"}):sn("idle","fallback",m||h)}var sn,V5,QR=V(()=>{sn=(e,t,n,r={})=>({kind:e,source:t,since:n||0,...r});V5=new Set(["merged","closed","lost"])});import Vy from"node:fs/promises";async function J5(e){let t;try{t=await Vy.readFile(`/proc/${e}/stat`,"utf8")}catch{return null}let n=t.lastIndexOf(")");if(n<0)return null;let r=t.slice(n+2).split(" "),o=Number(r[1]),s=Number(r[11])+Number(r[12]);return!Number.isFinite(o)||!Number.isFinite(s)?null:{ppid:o,cpuMs:s/z5*1e3,ioBytes:await Y5(e)}}async function Y5(e){let t;try{t=await Vy.readFile(`/proc/${e}/io`,"utf8")}catch{return 0}let n=r=>Number(t.match(new RegExp(`^${r}: (\\d+)$`,"m"))?.[1]||0);return n("rchar")+n("wchar")}async function eO(e){let t=[...new Set((e||[]).map(Number).filter(l=>Number.isFinite(l)&&l>0))];if(!t.length)return{procs:0,cpuMs:0,ioBytes:0};let n;try{n=await Vy.readdir("/proc")}catch{return null}let r=new Map;await Promise.all(n.map(async l=>{if(!/^\d+$/.test(l))return;let u=await J5(l);u&&r.set(Number(l),u)}));let o=new Map;for(let[l,u]of r)o.has(u.ppid)||o.set(u.ppid,[]),o.get(u.ppid).push(l);let s=new Set,a=t.filter(l=>r.has(l));for(let l of a)s.add(l);let i=0,c=0;for(let l=0;l<a.length;l++){let u=a[l];i+=r.get(u).cpuMs,c+=r.get(u).ioBytes;for(let d of o.get(u)||[])s.has(d)||(s.add(d),a.push(d))}return{procs:s.size,cpuMs:Math.round(i),ioBytes:c}}var z5,tO=V(()=>{z5=100});import X5 from"node:fs/promises";function Xy(e){let t=[];for(let n of e||[])if(!(!n||n.archivedAt&&!n.archiving||n.transferredTo))for(let r of n.boxes||[])r?.state==="live"&&r.name&&t.push({track:n,box:r});return t}async function Zy(e,t,n){let r=null;try{r=await n.updatedAt(e)}catch{r=null}let o=nO.get(e.name);if(o&&o.mtime===r&&t-o.at<nG)return o.jobs;let s=[];try{s=await n.readOpenJobs(e)}catch{s=[]}return nO.set(e.name,{at:t,mtime:r,jobs:s}),s}async function rG(e,t,n){let r=await n.panePids(e.name),o=r.length?await n.treeStats(r):null,s=null;try{s=await n.updatedAt(e)}catch{s=null}return{at:t,cpuMs:o?.cpuMs??null,ioBytes:o?.ioBytes??null,procs:o?.procs??null,mtime:s}}async function oG(e,t){return e?.outputFile?await t.statFile(e.outputFile):null}function sG(e,t){if(!e)return!0;let n=Math.max(1,(t.at-e.at)/1e3);return t.mtime!=null&&e.mtime!=null&&t.mtime>e.mtime||t.procs!=null&&e.procs!=null&&t.procs>e.procs||t.cpuMs!=null&&e.cpuMs!=null&&(t.cpuMs-e.cpuMs)/n>=eG||t.ioBytes!=null&&e.ioBytes!=null&&(t.ioBytes-e.ioBytes)/n>=tG}function rO(e,t,n,r){let o=[];for(let s of n){let a=Yy(e.id,t.name,s.id),i=Mn.get(a);i?i.job=s:Mn.set(a,{trackId:e.id,boxName:t.name,agent:t.agent||null,job:s,firstSeenAt:r,quiet:0,stalled:!1}),o.push(a)}return o}async function oO(e,{now:t=Date.now(),deps:n=Jy}={}){let o=(await Promise.all(Xy([e]).map(({box:s})=>Zy(s,t,n)))).flat();return o.length?{source:"jobs",count:o.length,since:Math.min(...o.map(s=>s.ts||t)),summary:o.length===1?"a background job is still running":`${o.length} background jobs are still running`}:null}async function sO(e,{now:t=Date.now(),deps:n=Jy}={}){let r=new Map,o=new Set;for(let{track:s,box:a}of Xy(e)){let i=await Zy(a,t,n);for(let l of i)o.add(Yy(s.id,a.name,l.id));let c=rO(s,a,i,t).filter(l=>!Mn.get(l).stalled).map(l=>Mn.get(l).job);c.length&&r.set(s.id,[...r.get(s.id)??[],...c])}for(let s of[...Mn.keys()])o.has(s)||Mn.delete(s);return r}async function aG(e,{now:t=Date.now(),deps:n=Jy}={}){let r={checked:0,progressing:0,quiet:0,stalled:[]},o=Xy(e),s=new Set(o.map(({box:a})=>a.name));for(let[a,i]of[...Mn])s.has(i.boxName)||Mn.delete(a);for(let{track:a,box:i}of o){let c=await Zy(i,t,n),l=new Set(c.map(w=>Yy(a.id,i.name,w.id)));for(let[w,h]of[...Mn])h.boxName===i.name&&!l.has(w)&&Mn.delete(w);if(!c.length){zy.delete(i.name);continue}let u=rO(a,i,c,t),d=await rG(i,t,n),p=zy.get(i.name);zy.set(i.name,d);let m=sG(p,d);for(let w of u){let h=Mn.get(w);r.checked++;let g=await oG(h.job,n),b=!!g&&!!h.file&&(g.size>h.file.size||g.mtimeMs>h.file.mtimeMs),y=!!g&&!h.file;if(h.file=g??h.file,m||b||y){h.quiet=0,h.lastProgressAt=t,h.stalled=!1,r.progressing++;continue}if(h.stalled||(h.quiet++,r.quiet++,h.quiet<Q5))continue;h.stalled=!0,h.stalledAt=t,r.stalled.push(w);let E=t-(h.lastProgressAt??h.firstSeenAt);try{await n.appendEvent(a,{type:"job.stalled",actor:"orchestrator",source:"orchestrator",boxId:i.name,provider:i.agent||null,payload:{id:h.job.id,kind:h.job.kind||"agent",name:h.job.name||null,detail:h.job.detail||null,startedTs:h.job.ts??h.firstSeenAt,quietMs:E,checks:h.quiet}})}catch{}console.log(`[job-watch] ${a.id}/${i.name} job ${h.job.id} (${h.job.name||h.job.kind}) quiet for ${Math.round(E/6e4)}m over ${h.quiet} check(s) \u2014 released; the node may sleep`)}}return r}function aO({listTracks:e,intervalMs:t=Z5}={}){let n=!1,o=setInterval(async()=>{if(!n){n=!0;try{await aG(await e())}catch(s){console.error(`[job-watch] sweep: ${s?.message||s}`)}finally{n=!1}}},t);return o.unref?.(),o}var Z5,Q5,eG,tG,nG,Jy,Mn,nO,zy,Yy,Qy=V(()=>{ke();op();mt();tO();Z5=Number(process.env.BOSTRAT_JOB_CHECK_MS)||15*6e4,Q5=Number(process.env.BOSTRAT_JOB_STALL_CHECKS)||3,eG=Number(process.env.BOSTRAT_JOB_CPU_RATE_MIN)||25,tG=Number(process.env.BOSTRAT_JOB_IO_RATE_MIN)||64*1024,nG=5*6e4,Jy={readOpenJobs:rp,statFile:async e=>{try{let t=await X5.stat(e);return{size:t.size,mtimeMs:Math.round(t.mtimeMs)}}catch{return null}},updatedAt:e=>mo(e.agent).updatedAt(e),panePids:qv,treeStats:eO,appendEvent:D},Mn=new Map,nO=new Map,zy=new Map,Yy=(e,t,n)=>`${e}|${t}|${n}`});import iG from"node:fs/promises";import cG from"node:os";import kf from"node:path";async function eb(e){try{return(await iG.stat(e)).size}catch{return null}}async function yi(e){let[t,n,r]=await Promise.all([eb(kf.join(lG,"CLAUDE.md")),e?eb(kf.join(e,"CLAUDE.md")):null,e?eb(kf.join(e,".bostrat","memory","MEMORY.md")):null]);return{bostratClaudeMd:t,repoClaudeMd:n,memoryIndex:r}}var lG,tb=V(()=>{lG=process.env.BOSTRAT_STATE_DIR||kf.join(process.env.HOME||cG.tmpdir(),".bostrat")});import{randomUUID as uG}from"node:crypto";async function vf(e,t,n={}){let r={operationId:uG(),kind:t,startedAt:Date.now(),...n};return xf.set(e.id,r),await D(e,{type:"track.operation.changed",actor:"orchestrator",source:"orchestrator",payload:{ts:r.startedAt,state:"started",...r}}).catch(()=>{}),r}async function nb(e,t,n="completed",r=null){xf.get(e.id)?.operationId===t?.operationId&&xf.delete(e.id),await D(e,{type:"track.operation.changed",actor:"orchestrator",source:"orchestrator",payload:{ts:Date.now(),state:"finished",operationId:t?.operationId,kind:t?.kind,outcome:n,...r?{error:String(r)}:{}}}).catch(()=>{})}var xf,iO,rb=V(()=>{ke();xf=new Map;iO=e=>xf.get(e)||null});var KO={};Vh(KO,{HANDOFF_LATEST_REL:()=>Uo,KNOWN_AGENTS:()=>tu,LOGIN_GREETING:()=>TO,TRACK_NAME_MAX:()=>gb,_resetRestartRefusalsForTest:()=>x6,addTrackRepo:()=>Lf,adoptTrack:()=>ok,agentAvailability:()=>Mf,announceNodeUpdate:()=>ir,answerFullscreenOffer:()=>Jb,answerPrompt:()=>Nf,answeringFor:()=>Ab,archiveTrack:()=>ea,archiveTrackForMergedPr:()=>$r,augmentFirstPromptAfterHandoff:()=>gO,buildAgentCmd:()=>yb,canResumeSubtask:()=>WO,cancelQueued:()=>Df,cancelQueuedToDraft:()=>_b,cancelQueuedWhere:()=>_O,cancelStopJob:()=>Qs,cancelSubtask:()=>Vf,changedRepos:()=>Vs,commitTransferOut:()=>qf,createSetupTrack:()=>Ub,createTrack:()=>Ff,deleteTrack:()=>Wb,demoteTransferredTracks:()=>rk,ensureLeadEpochs:()=>Fo,forceMergeSubtask:()=>ik,getHandoffJob:()=>Ri,getReshapeJob:()=>ru,getSubtaskJob:()=>M6,getTrack:()=>we,getTransferOutJob:()=>Qb,healDeadLead:()=>Zl,interruptLead:()=>Bf,isArchiving:()=>h6,isHandoffNoteEcho:()=>db,isInterruptEcho:()=>pb,isLeadStarting:()=>SO,isModelSwitchEcho:()=>fb,leadCliDead:()=>ou,listSubtaskJobs:()=>na,listTracks:()=>xe,matchTranscriptsToBoxes:()=>xO,mergeNotifyMessage:()=>jO,navigatePrompt:()=>Tb,notifyTrackForMergedPr:()=>Rr,notifyTrackForResolvedPr:()=>Uf,offerFollowupsForMergedPr:()=>ta,pendingOffers:()=>vb,queueGauges:()=>Eb,queueShipCompleteNotify:()=>Rb,queuedMessages:()=>Wo,rawTrack:()=>xb,reapArchivedOrphans:()=>zb,reconcileDemotedTracks:()=>Vb,reconcileHandoffOutcome:()=>FO,reconcileInterruptedHandoffs:()=>Xb,reconcileInterruptedReshapes:()=>jb,reconcileInterruptedSubtasks:()=>sk,reconcileMoveBeliefs:()=>nk,reconcileNodeUpdateNotices:()=>kb,reconcileSubtaskOutcome:()=>HO,refreshStandingInstructions:()=>Fb,refuseIfTransferred:()=>Oi,rehydrateLead:()=>Ii,removeTrackRepo:()=>jf,renameTrack:()=>Kb,reposOf:()=>Jt,reshapeTrack:()=>Lb,resolveTrackBox:()=>vl,resolveTrackBoxByHookToken:()=>nu,restartLead:()=>Hf,resumeAgentCmd:()=>Of,reviveLeadForSession:()=>Gb,sayToLead:()=>zt,sendOptionsForAgent:()=>qn,setTrackDraft:()=>Nb,setTrackModel:()=>Pb,staleTransferNotice:()=>tk,startLeadHandoff:()=>Wf,startSpinUpView:()=>Ob,startSubtask:()=>ak,startTransferOut:()=>ek,stopJobActive:()=>Sl,subtaskMessages:()=>Sb,trackMessages:()=>Cf,unarchiveTrack:()=>$i});import Z from"node:fs/promises";import X from"node:path";import{randomUUID as eu,createHash as dG}from"node:crypto";import{execFile as pG}from"node:child_process";import{promisify as fG}from"node:util";function yb(e,{skipPermissions:t=!0,model:n=null}={}){let r=Rf[e];if(!r)throw new Error(`unknown agent "${e}"`);let o=process.env[r.envVar];if(o)return o;let s=t&&r.skipFlag?`${r.base} ${r.skipFlag}`:r.base;if(n&&n!=="default"){let a=ug(e).find(i=>i.alias===n);if(!a)throw new Error(`unknown ${e} launch model "${n}"`);s+=` --model ${a.alias}`}return s}function Of(e,t,{skipPermissions:n=!0,cwd:r=null,peerName:o=null}={}){let s=Rf[e];if(!s)throw new Error(`unknown agent "${e}"`);let a=process.env[s.envVar];if(a)return a;let i=n&&s.skipFlag?` ${s.skipFlag}`:"";switch(e){case"claude":{if(!t)return`${s.base}${i}`;if(r&&!Sn(r,t)){let c=o&&We(o)?` --name ${o}`:"";return`${s.base} --session-id ${t}${c}${i}`}return`${s.base} --resume ${t}${i}`}case"cursor":return`${s.base} --continue${i}`;case"codex":return`${s.base} resume --last${i}`;default:return`${s.base}${i}`}}function Zs(e){let t=Rf[e];if(t)return process.env[t.envVar]||t.base}async function Mf({maxAgeMs:e=6e4}={}){if(jo.value&&Date.now()-jo.at<e)return jo.value;let t=jo.value,n=await Promise.all(tu.map(async r=>{let o=await Ad(Zs(r),{retries:[]});return o===Ia?[r,t?.[r]??!0]:[r,o===Sd]}));return jo.value=Object.fromEntries(n),jo.at=Date.now(),jo.value}async function Ei(e,t=!0,n=null){let r=yb(e,{skipPermissions:t,model:n});if(await Ad(r)===_a){jo.at=0;let o=r.split(/\s+/)[0],s=process.env.FLY_APP_NAME?"This Fly node's image predates CLI parity \u2014 update the node image (Links page \u2192 Fly card \u2192 Update) or re-provision.":Nm[o]?`Install it on this node: ${Nm[o]}`:"Its CLI must be installed and on PATH first.";throw new Error(`agent "${e}" isn't available on this box (command not found: ${o}). ${s}`)}return r}function gO(e,t=Uo){return`${e.trim()}
232
232
 
233
233
  (Read ${t} ${Uc}`}function db(e){return e.role==="user"&&wG.test((e.text||"").trim())}async function te(){return Kt||(ob||=(async()=>{try{Kt=JSON.parse(await Z.readFile(wO,"utf8"))}catch{Kt={tracks:[]}}finally{ob=null}return Kt})(),ob)}async function ue(){await Ut(wO,Kt)}function bG(e,t){let n=JSON.stringify({trackId:e,...t})+`
234
- `;return sb=sb.then(()=>Z.mkdir(sr,{recursive:!0})).then(()=>Z.appendFile(hG,n)).catch(()=>{}),sb}async function yO(e,{box:t,agent:n,message:r}){let o=pe(await te(),e);!o||o.archivedAt||(Re(o,"startup-gate",{box:t,agent:n??null,message:r}),await ue(),$s(o,{provider:n??null,cls:"startup-gate",note:r}).catch(()=>{}))}async function ir({current:e,latest:t,min:n=null,installKind:r=null,required:o=!1,status:s="available",policy:a=null,error:i=null,reason:c=null}={}){if(!t)return{announced:0};if(s==="available"){let d=null;try{d=JSON.parse(await Z.readFile(ab,"utf8"))}catch{}if(d?.latest===t&&d?.current===e)return{announced:0,deduped:!0}}let l=await te(),u=0;for(let d of l.tracks)He(d)||!d.leadBox||(Re(d,"node-update",{status:s,current:e??null,latest:t,...n?{min:n}:{},...r?{installKind:r}:{},...a?{policy:a}:{},...i?{error:String(i).slice(0,400)}:{},...c?{reason:c}:{},required:o===!0}),u++);if(await ue().catch(()=>{}),s==="available")try{await Z.mkdir(X.dirname(ab),{recursive:!0}),await Z.writeFile(ab,JSON.stringify({current:e,latest:t,at:Date.now()}))}catch{}return{announced:u}}async function kb({current:e,installKind:t=null,policy:n=null}={}){if(!e)return{reconciled:!1,announced:0,targets:[]};let r=await te(),o=0,s=new Set;for(let a of r.tracks){if(a.archivedAt||a.transferredTo||!a.leadBox)continue;let i=new Map;for(let c of a.events||[])c.type==="node-update"&&c.latest&&i.set(c.latest,c);for(let[c,l]of i)["done","failed","rolled-back"].includes(l.status)||kG(e,c)||(Re(a,"node-update",{status:"done",current:l.current??null,latest:c,...t?{installKind:t}:{},...n?{policy:n}:{},reason:"version-reconciled",installed:e,required:!1}),o++,s.add(c))}return o&&await ue().catch(()=>{}),{reconciled:o>0,announced:o,targets:[...s]}}function kG(e,t){let n=String(e).split(".").map(Number),r=String(t).split(".").map(Number);if(n.some(Number.isNaN)||r.some(Number.isNaN))return!0;for(let o=0;o<Math.max(n.length,r.length);o++){let s=(n[o]||0)-(r[o]||0);if(s)return s<0}return!1}function bO(e){if(!e)return null;let t=typeof e=="string"?[e]:Array.isArray(e?.codes)&&e.codes.length?e.codes:e?.code?[e.code]:[],n=[...new Set(t.filter(s=>xG.has(s)))];if(!n.length)return null;let r=typeof e=="object"?e?.note:null,o=r&&String(r).slice(0,500).trim()||null;return{code:n[0],...n.length>1?{codes:n}:{},note:o}}async function kO(e,t,n,{kind:r}={}){let o=await Ee(t);if(!o)throw new Error(`box "${t}" is not running`);let s=Zs(o.agent),a=Tl({text:n,producer:Al({kind:r,orchestration:!0}),kind:r||"orchestration",provider:o.agent}),i=pe(await te(),e)||null,c=Date.now(),l=null;try{l=await gr({cwd:o.cwd,sessionId:o.sessionId,sessionName:t,agent:o.agent,agentCmd:s})}catch(g){throw _l(a,{ms:Date.now()-c,outcome:g?.code==="cli-not-running"?"cli-not-running":"blocked"}),await Rn(i,a,ui(g)),g}_l(a,{ms:Date.now()-c,outcome:l||"up"});let u=qn(o.agent,n);a.paste=!!u.paste;try{await Ze(t,n,{...u,kind:r||"orchestration"})}catch(g){throw await Rn(i,a,ui(g)),g}let d={},p=await Zc({sessionName:t,agent:o.agent,agentCmd:s,text:n,trackId:e,flow:"orchestration",stats:d});a.verify=d,await Rn(i,a,p?d.verdict==="unverified"?"unverified":"delivered":"unsubmitted"),await ee({flow:"orchestration",phase:"sent",submitted:p,trackId:e,sessionName:t,agent:o.agent,kind:r||"orchestration",promptHead:n.slice(0,160)});let m=await te(),w=pe(m,e);if(!w)return;let h=w.boxes.find(g=>g.name===t);Re(w,"orchestration-prompt",{box:t,agent:h?.agent||o.agent,boxRole:h?.role,prompt:n,kind:r||"orchestration",deliveryId:a.id}),await ue()}async function vG(e){let t=X.join(va(e),`${e.id}.ndjson`),n;try{n=await Z.stat(t)}catch{return null}let r=cO.get(e.id);if(r&&r.mtimeMs===n.mtimeMs)return r.at;let o=null;for(let s of await J(e)){if(s.type!=="turn.agent")continue;let a=s.payload?.ts??s.ts;a&&(!o||a>o)&&(o=a)}return cO.set(e.id,{mtimeMs:n.mtimeMs,at:o}),o}async function SG(e,t){let n=t.find(r=>r.name===e.leadBox);return n?.state!=="live"?{working:!1,prompted:!1}:fo(n.name,n.agent)}async function an(e,t=null,n=null){let r=t??new Map((await en()).map(A=>[A.name,A])),o=!!e.transferredTo,s=e.boxes.map(A=>{A.launchEcho&&!o&&Ha(A.name,A.launchEcho);let $=o?null:r.get(A.name),P=Hr.has(A.state)?A.state:$?A.role==="lead"?"live":A.state:"stopped";return{...A,state:P,cwd:$?.cwd||A.cwd,agent:$?.agent||A.agent,sessionId:$?.sessionId||A.sessionId}}),[a,{working:i,prompted:c,awaitingBackground:l=null},u,d,p]=await Promise.all([vG(e),SG(e,s),qg(e),n??In().catch(()=>[]),oO({...e,boxes:s})]),m=Xl.has(e.id),w=(d||[]).filter(A=>A.trackId===e.id&&!["merged","closed","lost"].includes(A.state)),h=iO(e.id),g=h&&{status:"waiting",since:h.startedAt,summary:h.summary??null,count:h.count??null}||YR(w),b=s.find(A=>A.name===e.leadBox)?.state==="live",y=b?Wo(e.id).filter(A=>A.kind!=="ship-notify"&&A.kind!=="prompt-answer"&&A.kind!=="login-greet"):[],x=p||(b&&l?{source:"pane",count:l.count||1,since:u.completedTurnAt||a||Date.now(),summary:l.summary||"waiting for background jobs to finish"}:b&&u.runningJobs?{source:"jobs",count:u.runningJobs,since:u.runningJobsSince,summary:u.runningJobs===1?"a background job is still running":`${u.runningJobs} background jobs are still running`}:y.length?{source:"queue",count:y.length,since:Math.min(...y.map(A=>A.ts||Date.now())),summary:"a queued message is about to send"}:null),E=ZR({archivedAt:e.archivedAt,archiving:m,prompted:c,openActions:u.openActions,openActionSince:u.openActionSince,prDecisions:XR(w),operation:g,phase:u.phase,working:i,workingSince:u.currentTurnAt,pending:x,interrupted:u.interrupted,completedTurnAt:u.completedTurnAt||a,live:b});return{...e,boxes:s,lastResponseAt:a,working:i,prompted:c,archiving:m,status:E}}function xO(e,t,n){let r=[...e].sort((l,u)=>l.createdAt-u.createdAt),o=[...t].sort((l,u)=>l.birthMs-u.birthMs),s=new Set,a=[];for(let l of r)l.sessionId&&n(l.sessionId)&&!s.has(l.sessionId)?s.add(l.sessionId):a.push(l);let i=new Map(r.map((l,u)=>[l,u])),c=[];for(let l of a){if(l.sessionId&&n(l.sessionId)){c.push({box:l.name,sessionId:null});continue}if(!l.sessionId||l.pinned)continue;let u=i.get(l),d=l.createdAt-AG,p=r[u+1]?.createdAt??1/0,m=o.find(w=>!s.has(w.id)&&w.birthMs>=d&&w.birthMs<p);m&&(s.add(m.id),c.push({box:l.name,sessionId:m.id}))}return c}async function vO(e){let t=new Map;for(let r of e.tracks)for(let o of r.boxes)o.agent==="claude"&&o.cwd&&(t.has(o.cwd)||t.set(o.cwd,[]),t.get(o.cwd).push({track:r,box:o}));let n=!1;for(let[r,o]of t){let s=o.map(p=>p.box.sessionId),a=eS(r),i=new Set(a.map(p=>p.id)),c=s.every(p=>p&&i.has(p)),l=new Set(s).size===s.length;if(c&&l)continue;let u=o.map(p=>p.box),d=xO(u,a,p=>i.has(p));for(let p of d){let m=u.find(w=>w.name===p.box);m&&(m.sessionId=p.sessionId),await Wv(p.box,p.sessionId),n=!0}}return n}async function xe(){let e=await te();await vO(e)&&await ue();let t=new Map((await en()).map(r=>[r.name,r])),n=await In().catch(()=>[]);return Promise.all(e.tracks.map(r=>an(r,t,n)))}async function vl(e,t){let n=await te();if(e)for(let r of n.tracks||[]){let o=r.boxes.find(s=>s.sessionId&&s.sessionId===e);if(o)return{track:r,box:o}}if(t)for(let r of n.tracks||[]){let o=r.boxes.find(s=>s.cwd===t);if(o)return{track:r,box:o}}return null}async function nu(e){let t=ss(e);if(!t)return null;let n=await te();for(let r of n.tracks||[])for(let o of r.boxes||[])if(o.hookTokenHash&&ux(o.hookTokenHash,t))return{track:r,box:o};return null}async function xb(e){return pe(await te(),e)??null}async function we(e){let t=await te(),n=pe(t,e);return n?(await vO(t)&&await ue(),an(n)):null}async function vb(e){let t=await J(e).catch(()=>[]),n;try{n=Gn(t)}catch{return[]}let r=Jd(n).map(s=>({kind:s.kind,id:s.offerId??s.proposalId??s.id,ts:s.ts??null})),o=[];try{o=wA(t)}catch{o=[]}return r.concat(o.map(s=>({kind:"pr-open",id:`${s.repo??""}#${s.number}`,ts:null})))}function pb(e){if(e.role!=="user")return!1;let t=(e.text||"").trim();return(TG[e.agent]||[]).some(n=>n.test(t))}function fb(e){let t=(e.text||"").trim();return t?EG.some(n=>n.test(t)):!1}function SO(e,t,n=Date.now()){return!e||e.readyAt||e.state!=="live"?!1:n-(t||0)<_G}async function Cf(e,t={}){let n=await we(e);if(!n)return null;let r=new Set([...n.events.filter(N=>N.type==="orchestration-prompt"&&N.prompt).map(N=>String(N.prompt).trim()),...n.events.filter(N=>N.type==="said"&&N.text).map(N=>String(N.text).trim())]),o=Ri(n.id),s=!!(o&&!o.finishedAt&&o.step!=="done"&&!o.error),a=s&&o?.startedAt?[...o.fromBox?[{box:o.fromBox,from:o.startedAt,to:Date.now()+1e12}]:[],...o.toBox?[{box:o.toBox,from:o.startedAt,to:Date.now()+1e12}]:[]]:[],i=wy(n.id),c=!!(i&&!i.finishedAt),l=c&&i.startedAt&&i.box?[{box:i.box,from:i.startedAt,to:Date.now()+1e12}]:[],u=[...$$(n),...l],p={windows:[...IT(n),...$T(n,ip),...a,...u]},w=(await Promise.all(n.boxes.map(N=>Cw(N,t)))).flat(),h=[],g=w.map(N=>{let se={kind:"message",...N};if(se.role==="assistant"&&(se.text||"").trim()&&se.tools?.length){let le=mo(se.agent).cliTools,ve=se.tools.filter(Ye=>!le.has(Ye));return{...se,tools:ve.length?ve:void 0}}return se}).map(N=>{if(N.role!=="user")return N;let se=ES(N);return se?se.kind==="suppress"?null:{...N,note:se,text:Qm(se)}:N}).filter(Boolean).filter(N=>!(N.role==="user"&&r.has((N.text||"").trim()))).map(N=>{if(N.role!=="user"||N.note)return N;let se=Dd(N.text,r);if(!se)return N;let le={kind:"cut-delivery",...se};return{...N,note:le,text:Qm(le)}}).filter(N=>pb(N)?(h.push(N),!1):!0).filter(N=>!fb(N)).filter(N=>!db(N)).filter(N=>!jy(N)).filter(N=>N.role!=="assistant"||!!(N.text||"").trim()||!!N.images?.length).filter(N=>!RT(N,p)),b=g.filter(N=>N.failed&&N.text===ws);if(b.length){let N=new Map;for(let se of b){if(!N.has(se.box)){let Ye=[...(await Le(se.box,{lines:Xe}).catch(()=>"")).matchAll(/^\s*■\s+(.+?)\s*$/gm)].map(Fe=>Fe[1]);N.set(se.box,Ye.length?Ye[Ye.length-1]:null)}let le=N.get(se.box);le&&(se.text=`\u25A0 ${le}`)}}let y=await Promise.all(n.boxes.map(N=>iT(N,t)));await r$(n,y.flat());let{agentTurnBoxes:x}=await t$(n,g);await e$(n,h);for(let N of n.boxes)x.has(N.name)&&N.cwd&&pd(N.cwd);await $E(n),await P$(n,g).catch(()=>{});for(let N of n.boxes)N.agent==="codex"&&N.state==="live"&&await s$(n,N),N.agent==="cursor"&&N.state==="live"&&await u$(n,N);let E=await Promise.all(n.boxes.map(N=>aT(N,t)));await n$(n,E.flat().filter(N=>!ib(N.box,N.ts,u)));let A=await J(n),$=c&&i.viewId?i.viewId:null,P=HE(A),L=Gn(A).filter(N=>!(N.kind==="message"&&(pb(N)||fb(N)||db(N)||jy(N)))&&!(N.kind==="view-card"&&$&&N.viewId===$)),T=WE(L,P),C=L.filter(N=>!(N.kind==="message"&&N.role==="assistant"&&!T.has(N)&&ib(N.box,N.ts,P))),j=hw(A,C).map(N=>({kind:"command-batch",id:N.id,ts:N.pending?N.ts:(N.anchorTs??N.ts)-1,anchorTs:N.anchorTs,anchorBox:N.anchorBox,agent:N.agent,boxRole:N.boxRole,commands:N.commands,pending:N.pending})).filter(N=>!ib(N.anchorBox,N.anchorTs??N.ts,u)),K=hA(mA([...C,...j].filter(N=>N.ts!=null).sort((N,se)=>N.ts-se.ts))),M=IG(n),I=M.size?K.filter(N=>N.kind==="event"||!M.has(N.box??N.anchorBox)):K,S=n.boxes.find(N=>N.name===n.leadBox)||null,U=S?await Nc(S.cwd,S.sessionId,{fallbackNewest:!1}):null;if(!U&&S){let N=[...A].reverse().find(se=>se.type==="context.usage"&&se.boxId===S.name);N?.payload?.window&&(U={pct:N.payload.pct??(N.payload.occupancy!=null?N.payload.occupancy/N.payload.window:null),occupancy:N.payload.occupancy??null,window:N.payload.window,windowKnown:!0,model:N.payload.model||null})}let W=[...w].reverse().find(N=>N.role==="assistant"&&N.model),ie=W?.model||null,z=[...n.events||[]].reverse().find(N=>N.type==="model-change"),Ge=U?.model||ie;z&&(!W?.ts||z.at>=W.ts)&&(Ge=z.to);let _e=S?nn(S.name,await Le(S.name,{lines:Xe}).catch(()=>"")):"",Y=S&&po(S.agent,_e)?await tn(S.name).catch(()=>_e):_e,ne=S?Tn(S,Y):null;if(S&&Ab(S.name,ne,Y)&&ne&&(ne={...ne,answering:!0}),ne&&S){let N=Zd(S,ne,Y);if(N){let se=LA(S.name,ne.promptId);se.action!=="give-up"&&(se.action==="send"&&(N.accept&&Ud(S.name,Y),(!N.gate||io(S.name,N.gate))&&Je(S.name,N.keys,{kind:N.accept?"auto-accept":"auto-reject"}).catch(()=>{}),se.first&&D(n,{type:"prompt.autoRejected",actor:"system",source:"pane",boxId:S.name,provider:S.agent,payload:{ts:Date.now(),promptId:ne.promptId,rule:N.id}}).catch(()=>{})),ne=null)}}S&&(ne?.setup&&PS(S.name,Y),!ne&&Wc(S.agent,_e)&&jd(S.name)&&io(S.name,"login-issue")&&(Fd(S.name),Ze(S.name,"/login",{enter:!0,submitDelayMs:600,kind:"login-issue"}).catch(()=>{}))),!ne&&S&&!Ua(S.agent,_e)&&!Wo(n.id).length&&(ne=dw(I,{leadBoxId:S.name,provider:S.agent,isAnswered:N=>A.some(se=>se.type==="prompt.answered"&&se.payload?.promptId===N)})),ne&&RE(n,S,ne);let Ie=I.filter(N=>!(N.kind==="message"&&N.role==="assistant"&&N.ask&&!String(N.text||"").trim()&&!N.images?.length)),ae=!!S&&Qd(S.name,S.agent,_e)&&!ne;if(S&&!S.readyAt&&(ae||ne||_e&&co(S.agent,_e))){S.readyAt=Date.now();let N=pe(await te(),n.id)?.boxes?.find(se=>se.name===S.name);N&&!N.readyAt&&(N.readyAt=S.readyAt,await ue())}let Ae=SO(S,n.createdAt),be=!!S&&!!_e&&co(S.agent,_e)&&!ne&&!Wc(S.agent,_e)&&!Fa(S.agent,_e),Q=!1;if(n.kind==="setup"&&n.setup?.provider&&!n.setup.connectedAt&&S){if(be){let N=await te(),se=pe(N,n.id);se?.setup&&!se.setup.connectedAt&&(se.setup.connectedAt=Date.now(),n.setup.connectedAt=se.setup.connectedAt,Q=!0,await ue())}}else S&&be&&NS(S.name)&&(Q=!0);if(Q&&DS(S.name),S){let N=BS(S.name),se=CS(S.name);N.started&&D(n,{type:"provider.login.started",actor:"system",source:"pane",boxId:S.name,provider:S.agent,payload:{provider:S.agent,reason:se?.startedReason||"auth-screen",ts:Date.now()}}).catch(()=>{}),N.connected&&(await D(n,{type:"provider.connected",actor:"system",source:"pane",boxId:S.name,provider:S.agent,payload:{provider:S.agent,ts:se?.connectedAt||Date.now(),...se?.account?{account:se.account}:{},reason:se?.startedReason||"already-signed-in"}}).catch(()=>{}),n.kind!=="setup"&&se?.startedReason&&!BG(n.id)&&zt(n.id,TO,{kind:"login-greet"}).catch(le=>{console.warn(`[track ${n.id}] login greeting not delivered: ${le?.message||le}`)}))}let he=s?{running:!0,step:o.step,toAgent:o.toAgent||null,wait:o.wait||null}:null,Ue=ru(n.id),nt=Ue&&!Ue.finishedAt?{running:!0,step:Ue.step||null,added:Ue.added||[],removed:Ue.removed||[]}:null,rt=null;if(c){let N=Date.now()-i.startedAt;if(i.viewId&&!ae){let se=cf(n.id);se&&(Re(n,"view-spinup",{box:i.box,startedAt:i.startedAt,endedAt:se.finishedAt}),await ue())}else if(ne||N>_$&&!ae&&!i.viewId||N>my){let se=ne?"needs-input":N>my?"timeout":"no-view";cf(n.id,{error:se})&&await D(n,{type:"view.spinup.failed",actor:"orchestrator",source:"orchestrator",boxId:i.box,provider:S?.agent||null,payload:{ts:i.startedAt,name:i.name,reason:se}}).catch(()=>{})}else rt={running:!0,step:i.step,name:i.name}}return{trackId:n.id,leadBox:n.leadBox,items:Ie,context:U?{pct:U.pct,occupancy:U.occupancy,window:U.window,windowKnown:U.windowKnown,model:U.model}:null,models:{current:Ge,options:ug(S?.agent)},pendingPrompt:ne,working:ae,stopping:Sl(n.id),leadStarting:Ae,handoff:he,reshape:nt,view:rt,queued:Wo(n.id).filter(N=>N.kind!=="ship-notify"&&N.kind!=="prompt-answer"&&N.kind!=="login-greet"),draft:n.draft||null,draftRev:n.draftRev||0}}function IG(e){let t=new Set;for(let n of e.boxes||[])n.role==="subtask"&&n.name&&t.add(n.name);for(let n of Object.values(e.subtasks||{}))n?.box&&t.add(n.box);return t}async function Sb(e,t){let n=await we(e);if(!n)return null;let r=na(e).find(d=>d.id===t)||null;if(!r)return null;let o=r.box||null;if(!o)return{items:[],working:!1,box:null,agent:r.agent,task:r.task};let s=await J(n),a=Gn(s).filter(d=>d.box===o&&!(d.kind==="message"&&d.role==="assistant"&&d.ask&&!String(d.text||"").trim()&&!d.images?.length)),i=hw(s.filter(d=>d.boxId===o),a.filter(d=>d.kind==="message")).map(d=>({kind:"command-batch",id:d.id,ts:d.pending?d.ts:(d.anchorTs??d.ts)-1,anchorTs:d.anchorTs,anchorBox:d.anchorBox,agent:d.agent,boxRole:d.boxRole,commands:d.commands,pending:d.pending})),c=[...a,...i].filter(d=>d.ts!=null).sort((d,p)=>d.ts-p.ts),l=n.boxes.find(d=>d.name===o)||null,u=!1;if(l&&l.state==="live"){let d=await Le(o,{lines:Xe}).catch(()=>"");u=Qd(o,l.agent||r.agent,d)}return{items:c,working:u,box:o,agent:r.agent,task:r.task}}function $G(e,t){if(e==null)return[];if(!Array.isArray(e))throw new Error("custom answer must be a list of strings");return e.slice(0,Math.max(1,t)).map(n=>{if(n==null||n==="")return"";if(typeof n!="string")throw new Error("custom answer must be text");let r=n.replace(/\s+/g," ").trim();if(/[\x00-\x1f\x7f]/.test(r))throw new Error("custom answer can't contain control characters");if(r.length>lO)throw new Error(`custom answer is too long (max ${lO} characters)`);return r})}function RG(e,t){let n=String(e||"").replace(/\s+/g," ").trim(),r=String(t||"").replace(/\s+/g," ").trim();return!n||!r?!1:n===r||r.startsWith(n)||n.startsWith(r.slice(0,24))}function Ab(e,t,n,r=Date.now()){let o=hb.get(e);if(!o)return!1;let s=!!t&&t.promptId===o.promptId&&r-o.at<OG&&(t.setup?!0:AO(n)===o.paneHash);return s||hb.delete(e),s}async function CG(e,t,n){let r=n;for(let o of MG){await ar(o);let s=await tn(e).catch(()=>null);if(s!=null&&(r=s,s!==n))break}hb.set(e,{promptId:t.promptId,paneHash:AO(r),setup:t.setup||null,at:Date.now()})}async function Nf(e,t={}){let n=Ul.get(e);n&&await n.catch(()=>{});let r=NG(e,t);Ul.set(e,r);try{return await r}finally{Ul.get(e)===r&&Ul.delete(e)}}async function NG(e,{promptId:t,answers:n,text:r,custom:o}={}){let s=pe(await te(),e);if(!s)throw new Error(`track "${e}" not found`);Qs(e,"prompt-answer");let a=s.boxes.find(y=>y.name===s.leadBox);if(!a)throw new Error(`track "${e}" has no lead box`);if(!await Ee(s.leadBox))throw new Error(`lead box "${s.leadBox}" is not running`);let c=await tn(a.name).catch(()=>""),l=Tn(a,c);if(l||(l=await PG(s,a)),!l)throw new Error("no pending prompt to answer");if(t&&t!==l.promptId)throw new Error("prompt changed since it was shown \u2014 reload and answer the current prompt");if(l.answerMode!=="say"&&Ab(a.name,l,c))throw new Error("prompt already answered \u2014 waiting for the CLI to move on");let u=$G(o,l.questions?.length??1);if(u.some(Boolean)&&!l.custom)throw new Error("custom answer isn't available for this prompt \u2014 pick one of its options");let d=(n||[]).some(y=>Array.isArray(y)&&y.length>0);if(l.custom&&!d&&!u.some(Boolean)&&l.answerMode!=="text")throw new Error("no answer selected \u2014 pick an option or type your own");u.some(Boolean)&&(n=(l.questions||[]).map((y,x)=>u[x]&&!y.multiSelect?[]:Array.isArray(n?.[x])?n[x]:[]));let p;if(l.answerMode==="text"){let y=typeof r=="string"?r.trim():"";if(!y)throw new Error("this prompt needs a code \u2014 paste it into the card");if(/\s/.test(y)||y.length>2048)throw new Error("that doesn't look like a sign-in code \u2014 paste the code exactly as shown");await Ze(s.leadBox,y,{enter:!0,kind:"answer-prompt"}),p={mode:"text-input",value:"\u2039code\u203A",count:1,redacted:!0}}else if(l.answerMode==="esc")await Je(s.leadBox,["Escape"],{kind:"answer-prompt"}),p={mode:"keys",value:"Escape",count:1};else if(l.answerMode==="say"){let y=uA(l,n||[],typeof r=="string"?r:"",u);if(!y)throw new Error("no answer selected \u2014 pick an option or reply in chat");await zt(s.id,y,{kind:"prompt-answer"}),p={mode:"say",value:y,count:1}}else if(u[0]&&l.provider==="claude"){let y=NA(l,n||[],u[0]);await Pm(s.leadBox,[...y.pre,{text:y.text}],{kind:"answer-prompt"});let x=!1;for(let A of[150,300,600]){await ar(A);let $=await tn(s.leadBox).catch(()=>""),P=Tn(a,$);if(P?.customText&&RG(P.customText,y.text)){x=!0;break}}if(!x)throw new Error("custom answer didn't take \u2014 the widget moved; reload and answer again");await Pm(s.leadBox,y.post,{kind:"answer-prompt"});let E=A=>A.map($=>$.key).join(" ");p={mode:"keys+text",value:`${E(y.pre)} \u2039text\u203A ${E(y.post)}`.trim(),count:y.pre.length+1+y.post.length}}else if(l.provider==="claude"||l.answerMode==="keys"){let y=xw(l,n||[]);await Je(s.leadBox,y,{kind:"answer-prompt"}),p={mode:"keys",value:y.join(" "),count:y.length}}else{let y=WS(l,n||[]);await Ze(s.leadBox,y,{enter:!0,kind:"answer-prompt"}),p={mode:"text",value:y,count:1}}if(l.answerMode!=="say"&&await CG(a.name,l,c),l.answerMode==="say"){let y=l.questions||[];for(let x=0;x<y.length;x++){let E=y[x],A=new Set(Array.isArray(n?.[x])?n[x]:[]),$=[...A].map(L=>E.options?.[L]).filter(Boolean).map(L=>({label:L.label,description:L.description||""}));u[x]&&$.push({label:u[x],description:"",custom:!0});let P=(E.options||[]).map((L,T)=>A.has(T)?null:L?.label).filter(Boolean);dg(s,a,l,{...p,groupId:l.groupId||l.promptId,questionIndex:x,questionTotal:l.questionTotal??y.length,header:E.header||"",question:E.question||"",multiSelect:!!E.multiSelect,chosen:$,rejected:P})}return await ee({flow:"prompt",phase:"answered",sessionName:s.leadBox,agent:a.agent,provider:l.provider,promptId:l.promptId,...p}).catch(()=>{}),{ok:!0,promptId:l.promptId,sent:p.count}}let m=l.questions?.[0]||{},w=new Set(Array.isArray(n?.[0])?n[0]:[]),h=[...w].map(y=>m.options?.[y]).filter(Boolean).map(y=>({label:y.label,description:y.description||""}));u[0]&&h.push({label:u[0],description:"",custom:!0});let g=(m.options||[]).map((y,x)=>w.has(x)?null:y?.label).filter(Boolean),b=l.review?"review":/^claude:model-confirm:/.test(l.promptId||"")?"model-confirm":/^claude:resume-confirm:/.test(l.promptId||"")?"resume-confirm":l.setup==="continue"?"login-continue":void 0;return p={...p,groupId:l.groupId||l.promptId,questionIndex:l.questionIndex??0,questionTotal:l.questionTotal??1,header:m.header||"",question:m.question||"",multiSelect:!!m.multiSelect,chosen:h,rejected:g,...b?{control:b}:{}},await ee({flow:"prompt",phase:"answered",sessionName:s.leadBox,agent:a.agent,provider:l.provider,promptId:l.promptId,...p}).catch(()=>{}),dg(s,a,l,p),{ok:!0,promptId:l.promptId,sent:p.count}}async function PG(e,t){if(!t)return null;let n=await J(e).catch(()=>[]);return dw(Gn(n),{leadBoxId:t.name,provider:t.agent,isAnswered:r=>n.some(o=>o.type==="prompt.answered"&&o.payload?.promptId===r)})}async function Tb(e,{promptId:t,questionIndex:n}={}){let r=pe(await te(),e);if(!r)throw new Error(`track "${e}" not found`);let o=r.boxes.find(l=>l.name===r.leadBox);if(!o)throw new Error(`track "${e}" has no lead box`);if(!await Ee(r.leadBox))throw new Error(`lead box "${r.leadBox}" is not running`);let a=await MA(o);if(!a)throw new Error("no pending prompt to navigate");if(a.provider!=="claude")throw new Error("prompt navigation not supported for this provider");if(a.review)throw new Error("cannot navigate on the review screen \u2014 answer or cancel");let i=a.questionTotal??1;if(i<2)throw new Error("not a multi-question prompt");if(!Number.isInteger(n)||n<0||n>=i)throw new Error("questionIndex out of range");if(t&&t!==a.promptId)throw new Error("prompt changed since it was shown \u2014 reload and try again");let c=PA(a,n);return c.length?(await Je(r.leadBox,c,{kind:"navigate-prompt"}),await ee({flow:"prompt",phase:"navigated",sessionName:r.leadBox,agent:o.agent,provider:a.provider,promptId:a.promptId,fromIndex:a.questionIndex??0,toIndex:n,mode:"keys",value:c.join(" "),count:c.length}).catch(()=>{}),{ok:!0,promptId:a.promptId,sent:c.length}):{ok:!0,promptId:a.promptId,sent:0}}function Pf(e){let t=Ho.get(e);return t||(t={items:[],timer:null,flushing:!1,idleSince:null},Ho.set(e,t)),t}function BG(e){let t=Ho.get(e);return!!t&&(t.items.length>0||!!t.flushing)}function Wo(e){return(Ho.get(e)?.items??[]).map(({delivery:t,...n})=>({...n}))}function Eb(e=Date.now()){let t=0,n=0;for(let r of Ho.values())for(let o of r.items){t+=1;let s=e-(o.delivery?.queuedAt??o.ts??e);s>n&&(n=s)}return{queueDepth:t,queueOldestAgeMs:n}}function EO(e,t,n){let r=t.filter(o=>o.delivery&&!o.delivery.settled);r.length&&(async()=>{let o=pe(await te(),e)||null;for(let s of r)await Rn(o,s.delivery,`dropped:${n}`)})().catch(()=>{})}function Df(e,t="cancel"){let n=Ho.get(e);if(!n)return[];let r=n.items.splice(0);return n.idleSince=null,n.timer&&(clearInterval(n.timer),n.timer=null),EO(e,r,t),r}function _O(e,t,n){let r=Ho.get(e);if(!r)return[];let o=r.items.filter(s=>n(s));return o.length?(r.items=r.items.filter(s=>!n(s)),r.items.length||(r.idleSince=null,r.timer&&(clearInterval(r.timer),r.timer=null)),EO(e,o,t),o):[]}async function _b(e){let t=Df(e),n=t.filter(o=>o.text&&!o.kind).map(o=>o.text),r=null;if(n.length){let o=pe(await te(),e);if(o)return r=zl(o,n),await ue(),{removed:t,restored:r,draftRev:o.draftRev||0}}return{removed:t,restored:r,draftRev:null}}function Ib(e){let t=Pf(e);t.timer||(t.timer=setInterval(()=>LG(e).catch(()=>{}),DG))}async function LG(e){let t=Ho.get(e);if(!(!t||t.flushing)){if(!t.items.length){t.timer&&(clearInterval(t.timer),t.timer=null);return}t.flushing=!0;try{let n=pe(await te(),e);if(!n||n.archivedAt){Df(e,"archived");return}let r=async(l,u="")=>{let d=[];for(let g of t.items)y$(g.delivery,l),FR(g,l)&&d.push(g);if(!d.length)return;t.items=t.items.filter(g=>!d.includes(g));let p=Date.now()-Math.min(...d.map(g=>g.heldSince||Date.now())),m=Math.max(1,Math.round(Uy()/6e4)),w=String(u||"").split(`
234
+ `;return sb=sb.then(()=>Z.mkdir(sr,{recursive:!0})).then(()=>Z.appendFile(hG,n)).catch(()=>{}),sb}async function yO(e,{box:t,agent:n,message:r}){let o=pe(await te(),e);!o||o.archivedAt||(Re(o,"startup-gate",{box:t,agent:n??null,message:r}),await ue(),$s(o,{provider:n??null,cls:"startup-gate",note:r}).catch(()=>{}))}async function ir({current:e,latest:t,min:n=null,installKind:r=null,required:o=!1,status:s="available",policy:a=null,error:i=null,reason:c=null}={}){if(!t)return{announced:0};if(s==="available"){let d=null;try{d=JSON.parse(await Z.readFile(ab,"utf8"))}catch{}if(d?.latest===t&&d?.current===e)return{announced:0,deduped:!0}}let l=await te(),u=0;for(let d of l.tracks)He(d)||!d.leadBox||(Re(d,"node-update",{status:s,current:e??null,latest:t,...n?{min:n}:{},...r?{installKind:r}:{},...a?{policy:a}:{},...i?{error:String(i).slice(0,400)}:{},...c?{reason:c}:{},required:o===!0}),u++);if(await ue().catch(()=>{}),s==="available")try{await Z.mkdir(X.dirname(ab),{recursive:!0}),await Z.writeFile(ab,JSON.stringify({current:e,latest:t,at:Date.now()}))}catch{}return{announced:u}}async function kb({current:e,installKind:t=null,policy:n=null}={}){if(!e)return{reconciled:!1,announced:0,targets:[]};let r=await te(),o=0,s=new Set;for(let a of r.tracks){if(a.archivedAt||a.transferredTo||!a.leadBox)continue;let i=new Map;for(let c of a.events||[])c.type==="node-update"&&c.latest&&i.set(c.latest,c);for(let[c,l]of i)["done","failed","rolled-back"].includes(l.status)||kG(e,c)||(Re(a,"node-update",{status:"done",current:l.current??null,latest:c,...t?{installKind:t}:{},...n?{policy:n}:{},reason:"version-reconciled",installed:e,required:!1}),o++,s.add(c))}return o&&await ue().catch(()=>{}),{reconciled:o>0,announced:o,targets:[...s]}}function kG(e,t){let n=String(e).split(".").map(Number),r=String(t).split(".").map(Number);if(n.some(Number.isNaN)||r.some(Number.isNaN))return!0;for(let o=0;o<Math.max(n.length,r.length);o++){let s=(n[o]||0)-(r[o]||0);if(s)return s<0}return!1}function bO(e){if(!e)return null;let t=typeof e=="string"?[e]:Array.isArray(e?.codes)&&e.codes.length?e.codes:e?.code?[e.code]:[],n=[...new Set(t.filter(s=>xG.has(s)))];if(!n.length)return null;let r=typeof e=="object"?e?.note:null,o=r&&String(r).slice(0,500).trim()||null;return{code:n[0],...n.length>1?{codes:n}:{},note:o}}async function kO(e,t,n,{kind:r,detail:o}={}){let s=await Ee(t);if(!s)throw new Error(`box "${t}" is not running`);let a=Zs(s.agent),i=Tl({text:n,producer:Al({kind:r,orchestration:!0}),kind:r||"orchestration",provider:s.agent}),c=pe(await te(),e)||null,l=Date.now(),u=null;try{u=await gr({cwd:s.cwd,sessionId:s.sessionId,sessionName:t,agent:s.agent,agentCmd:a})}catch(b){throw _l(i,{ms:Date.now()-l,outcome:b?.code==="cli-not-running"?"cli-not-running":"blocked"}),await Rn(c,i,ui(b)),b}_l(i,{ms:Date.now()-l,outcome:u||"up"});let d=qn(s.agent,n);i.paste=!!d.paste;try{await Ze(t,n,{...d,kind:r||"orchestration"})}catch(b){throw await Rn(c,i,ui(b)),b}let p={},m=await Zc({sessionName:t,agent:s.agent,agentCmd:a,text:n,trackId:e,flow:"orchestration",stats:p});i.verify=p,await Rn(c,i,m?p.verdict==="unverified"?"unverified":"delivered":"unsubmitted"),await ee({flow:"orchestration",phase:"sent",submitted:m,trackId:e,sessionName:t,agent:s.agent,kind:r||"orchestration",promptHead:n.slice(0,160)});let w=await te(),h=pe(w,e);if(!h)return;let g=h.boxes.find(b=>b.name===t);Re(h,"orchestration-prompt",{box:t,agent:g?.agent||s.agent,boxRole:g?.role,prompt:n,kind:r||"orchestration",deliveryId:i.id,...o?{detail:o}:{}}),await ue()}async function vG(e){let t=X.join(va(e),`${e.id}.ndjson`),n;try{n=await Z.stat(t)}catch{return null}let r=cO.get(e.id);if(r&&r.mtimeMs===n.mtimeMs)return r.at;let o=null;for(let s of await J(e)){if(s.type!=="turn.agent")continue;let a=s.payload?.ts??s.ts;a&&(!o||a>o)&&(o=a)}return cO.set(e.id,{mtimeMs:n.mtimeMs,at:o}),o}async function SG(e,t){let n=t.find(r=>r.name===e.leadBox);return n?.state!=="live"?{working:!1,prompted:!1}:fo(n.name,n.agent)}async function an(e,t=null,n=null){let r=t??new Map((await en()).map(A=>[A.name,A])),o=!!e.transferredTo,s=e.boxes.map(A=>{A.launchEcho&&!o&&Ha(A.name,A.launchEcho);let $=o?null:r.get(A.name),P=Hr.has(A.state)?A.state:$?A.role==="lead"?"live":A.state:"stopped";return{...A,state:P,cwd:$?.cwd||A.cwd,agent:$?.agent||A.agent,sessionId:$?.sessionId||A.sessionId}}),[a,{working:i,prompted:c,awaitingBackground:l=null},u,d,p]=await Promise.all([vG(e),SG(e,s),qg(e),n??In().catch(()=>[]),oO({...e,boxes:s})]),m=Xl.has(e.id),w=(d||[]).filter(A=>A.trackId===e.id&&!["merged","closed","lost"].includes(A.state)),h=iO(e.id),g=h&&{status:"waiting",since:h.startedAt,summary:h.summary??null,count:h.count??null}||YR(w),b=s.find(A=>A.name===e.leadBox)?.state==="live",y=b?Wo(e.id).filter(A=>A.kind!=="ship-notify"&&A.kind!=="prompt-answer"&&A.kind!=="login-greet"):[],x=p||(b&&l?{source:"pane",count:l.count||1,since:u.completedTurnAt||a||Date.now(),summary:l.summary||"waiting for background jobs to finish"}:b&&u.runningJobs?{source:"jobs",count:u.runningJobs,since:u.runningJobsSince,summary:u.runningJobs===1?"a background job is still running":`${u.runningJobs} background jobs are still running`}:y.length?{source:"queue",count:y.length,since:Math.min(...y.map(A=>A.ts||Date.now())),summary:"a queued message is about to send"}:null),E=ZR({archivedAt:e.archivedAt,archiving:m,prompted:c,openActions:u.openActions,openActionSince:u.openActionSince,prDecisions:XR(w),operation:g,phase:u.phase,working:i,workingSince:u.currentTurnAt,pending:x,interrupted:u.interrupted,completedTurnAt:u.completedTurnAt||a,live:b});return{...e,boxes:s,lastResponseAt:a,working:i,prompted:c,archiving:m,status:E}}function xO(e,t,n){let r=[...e].sort((l,u)=>l.createdAt-u.createdAt),o=[...t].sort((l,u)=>l.birthMs-u.birthMs),s=new Set,a=[];for(let l of r)l.sessionId&&n(l.sessionId)&&!s.has(l.sessionId)?s.add(l.sessionId):a.push(l);let i=new Map(r.map((l,u)=>[l,u])),c=[];for(let l of a){if(l.sessionId&&n(l.sessionId)){c.push({box:l.name,sessionId:null});continue}if(!l.sessionId||l.pinned)continue;let u=i.get(l),d=l.createdAt-AG,p=r[u+1]?.createdAt??1/0,m=o.find(w=>!s.has(w.id)&&w.birthMs>=d&&w.birthMs<p);m&&(s.add(m.id),c.push({box:l.name,sessionId:m.id}))}return c}async function vO(e){let t=new Map;for(let r of e.tracks)for(let o of r.boxes)o.agent==="claude"&&o.cwd&&(t.has(o.cwd)||t.set(o.cwd,[]),t.get(o.cwd).push({track:r,box:o}));let n=!1;for(let[r,o]of t){let s=o.map(p=>p.box.sessionId),a=eS(r),i=new Set(a.map(p=>p.id)),c=s.every(p=>p&&i.has(p)),l=new Set(s).size===s.length;if(c&&l)continue;let u=o.map(p=>p.box),d=xO(u,a,p=>i.has(p));for(let p of d){let m=u.find(w=>w.name===p.box);m&&(m.sessionId=p.sessionId),await Wv(p.box,p.sessionId),n=!0}}return n}async function xe(){let e=await te();await vO(e)&&await ue();let t=new Map((await en()).map(r=>[r.name,r])),n=await In().catch(()=>[]);return Promise.all(e.tracks.map(r=>an(r,t,n)))}async function vl(e,t){let n=await te();if(e)for(let r of n.tracks||[]){let o=r.boxes.find(s=>s.sessionId&&s.sessionId===e);if(o)return{track:r,box:o}}if(t)for(let r of n.tracks||[]){let o=r.boxes.find(s=>s.cwd===t);if(o)return{track:r,box:o}}return null}async function nu(e){let t=ss(e);if(!t)return null;let n=await te();for(let r of n.tracks||[])for(let o of r.boxes||[])if(o.hookTokenHash&&ux(o.hookTokenHash,t))return{track:r,box:o};return null}async function xb(e){return pe(await te(),e)??null}async function we(e){let t=await te(),n=pe(t,e);return n?(await vO(t)&&await ue(),an(n)):null}async function vb(e){let t=await J(e).catch(()=>[]),n;try{n=Gn(t)}catch{return[]}let r=Jd(n).map(s=>({kind:s.kind,id:s.offerId??s.proposalId??s.id,ts:s.ts??null})),o=[];try{o=wA(t)}catch{o=[]}return r.concat(o.map(s=>({kind:"pr-open",id:`${s.repo??""}#${s.number}`,ts:null})))}function pb(e){if(e.role!=="user")return!1;let t=(e.text||"").trim();return(TG[e.agent]||[]).some(n=>n.test(t))}function fb(e){let t=(e.text||"").trim();return t?EG.some(n=>n.test(t)):!1}function SO(e,t,n=Date.now()){return!e||e.readyAt||e.state!=="live"?!1:n-(t||0)<_G}async function Cf(e,t={}){let n=await we(e);if(!n)return null;let r=new Set([...n.events.filter(N=>N.type==="orchestration-prompt"&&N.prompt).map(N=>String(N.prompt).trim()),...n.events.filter(N=>N.type==="said"&&N.text).map(N=>String(N.text).trim())]),o=Ri(n.id),s=!!(o&&!o.finishedAt&&o.step!=="done"&&!o.error),a=s&&o?.startedAt?[...o.fromBox?[{box:o.fromBox,from:o.startedAt,to:Date.now()+1e12}]:[],...o.toBox?[{box:o.toBox,from:o.startedAt,to:Date.now()+1e12}]:[]]:[],i=wy(n.id),c=!!(i&&!i.finishedAt),l=c&&i.startedAt&&i.box?[{box:i.box,from:i.startedAt,to:Date.now()+1e12}]:[],u=[...$$(n),...l],p={windows:[...IT(n),...$T(n,ip),...a,...u]},w=(await Promise.all(n.boxes.map(N=>Cw(N,t)))).flat(),h=[],g=w.map(N=>{let se={kind:"message",...N};if(se.role==="assistant"&&(se.text||"").trim()&&se.tools?.length){let le=mo(se.agent).cliTools,ve=se.tools.filter(Ye=>!le.has(Ye));return{...se,tools:ve.length?ve:void 0}}return se}).map(N=>{if(N.role!=="user")return N;let se=ES(N);return se?se.kind==="suppress"?null:{...N,note:se,text:Qm(se)}:N}).filter(Boolean).filter(N=>!(N.role==="user"&&r.has((N.text||"").trim()))).map(N=>{if(N.role!=="user"||N.note)return N;let se=Dd(N.text,r);if(!se)return N;let le={kind:"cut-delivery",...se};return{...N,note:le,text:Qm(le)}}).filter(N=>pb(N)?(h.push(N),!1):!0).filter(N=>!fb(N)).filter(N=>!db(N)).filter(N=>!jy(N)).filter(N=>N.role!=="assistant"||!!(N.text||"").trim()||!!N.images?.length).filter(N=>!RT(N,p)),b=g.filter(N=>N.failed&&N.text===ws);if(b.length){let N=new Map;for(let se of b){if(!N.has(se.box)){let Ye=[...(await Le(se.box,{lines:Xe}).catch(()=>"")).matchAll(/^\s*■\s+(.+?)\s*$/gm)].map(Fe=>Fe[1]);N.set(se.box,Ye.length?Ye[Ye.length-1]:null)}let le=N.get(se.box);le&&(se.text=`\u25A0 ${le}`)}}let y=await Promise.all(n.boxes.map(N=>iT(N,t)));await r$(n,y.flat());let{agentTurnBoxes:x}=await t$(n,g);await e$(n,h);for(let N of n.boxes)x.has(N.name)&&N.cwd&&pd(N.cwd);await $E(n),await P$(n,g).catch(()=>{});for(let N of n.boxes)N.agent==="codex"&&N.state==="live"&&await s$(n,N),N.agent==="cursor"&&N.state==="live"&&await u$(n,N);let E=await Promise.all(n.boxes.map(N=>aT(N,t)));await n$(n,E.flat().filter(N=>!ib(N.box,N.ts,u)));let A=await J(n),$=c&&i.viewId?i.viewId:null,P=HE(A),L=Gn(A).filter(N=>!(N.kind==="message"&&(pb(N)||fb(N)||db(N)||jy(N)))&&!(N.kind==="view-card"&&$&&N.viewId===$)),T=WE(L,P),C=L.filter(N=>!(N.kind==="message"&&N.role==="assistant"&&!T.has(N)&&ib(N.box,N.ts,P))),j=hw(A,C).map(N=>({kind:"command-batch",id:N.id,ts:N.pending?N.ts:(N.anchorTs??N.ts)-1,anchorTs:N.anchorTs,anchorBox:N.anchorBox,agent:N.agent,boxRole:N.boxRole,commands:N.commands,pending:N.pending})).filter(N=>!ib(N.anchorBox,N.anchorTs??N.ts,u)),K=hA(mA([...C,...j].filter(N=>N.ts!=null).sort((N,se)=>N.ts-se.ts))),M=IG(n),I=M.size?K.filter(N=>N.kind==="event"||!M.has(N.box??N.anchorBox)):K,S=n.boxes.find(N=>N.name===n.leadBox)||null,U=S?await Nc(S.cwd,S.sessionId,{fallbackNewest:!1}):null;if(!U&&S){let N=[...A].reverse().find(se=>se.type==="context.usage"&&se.boxId===S.name);N?.payload?.window&&(U={pct:N.payload.pct??(N.payload.occupancy!=null?N.payload.occupancy/N.payload.window:null),occupancy:N.payload.occupancy??null,window:N.payload.window,windowKnown:!0,model:N.payload.model||null})}let W=[...w].reverse().find(N=>N.role==="assistant"&&N.model),ie=W?.model||null,z=[...n.events||[]].reverse().find(N=>N.type==="model-change"),Ge=U?.model||ie;z&&(!W?.ts||z.at>=W.ts)&&(Ge=z.to);let _e=S?nn(S.name,await Le(S.name,{lines:Xe}).catch(()=>"")):"",Y=S&&po(S.agent,_e)?await tn(S.name).catch(()=>_e):_e,ne=S?Tn(S,Y):null;if(S&&Ab(S.name,ne,Y)&&ne&&(ne={...ne,answering:!0}),ne&&S){let N=Zd(S,ne,Y);if(N){let se=LA(S.name,ne.promptId);se.action!=="give-up"&&(se.action==="send"&&(N.accept&&Ud(S.name,Y),(!N.gate||io(S.name,N.gate))&&Je(S.name,N.keys,{kind:N.accept?"auto-accept":"auto-reject"}).catch(()=>{}),se.first&&D(n,{type:"prompt.autoRejected",actor:"system",source:"pane",boxId:S.name,provider:S.agent,payload:{ts:Date.now(),promptId:ne.promptId,rule:N.id}}).catch(()=>{})),ne=null)}}S&&(ne?.setup&&PS(S.name,Y),!ne&&Wc(S.agent,_e)&&jd(S.name)&&io(S.name,"login-issue")&&(Fd(S.name),Ze(S.name,"/login",{enter:!0,submitDelayMs:600,kind:"login-issue"}).catch(()=>{}))),!ne&&S&&!Ua(S.agent,_e)&&!Wo(n.id).length&&(ne=dw(I,{leadBoxId:S.name,provider:S.agent,isAnswered:N=>A.some(se=>se.type==="prompt.answered"&&se.payload?.promptId===N)})),ne&&RE(n,S,ne);let Ie=I.filter(N=>!(N.kind==="message"&&N.role==="assistant"&&N.ask&&!String(N.text||"").trim()&&!N.images?.length)),ae=!!S&&Qd(S.name,S.agent,_e)&&!ne;if(S&&!S.readyAt&&(ae||ne||_e&&co(S.agent,_e))){S.readyAt=Date.now();let N=pe(await te(),n.id)?.boxes?.find(se=>se.name===S.name);N&&!N.readyAt&&(N.readyAt=S.readyAt,await ue())}let Ae=SO(S,n.createdAt),be=!!S&&!!_e&&co(S.agent,_e)&&!ne&&!Wc(S.agent,_e)&&!Fa(S.agent,_e),Q=!1;if(n.kind==="setup"&&n.setup?.provider&&!n.setup.connectedAt&&S){if(be){let N=await te(),se=pe(N,n.id);se?.setup&&!se.setup.connectedAt&&(se.setup.connectedAt=Date.now(),n.setup.connectedAt=se.setup.connectedAt,Q=!0,await ue())}}else S&&be&&NS(S.name)&&(Q=!0);if(Q&&DS(S.name),S){let N=BS(S.name),se=CS(S.name);N.started&&D(n,{type:"provider.login.started",actor:"system",source:"pane",boxId:S.name,provider:S.agent,payload:{provider:S.agent,reason:se?.startedReason||"auth-screen",ts:Date.now()}}).catch(()=>{}),N.connected&&(await D(n,{type:"provider.connected",actor:"system",source:"pane",boxId:S.name,provider:S.agent,payload:{provider:S.agent,ts:se?.connectedAt||Date.now(),...se?.account?{account:se.account}:{},reason:se?.startedReason||"already-signed-in"}}).catch(()=>{}),n.kind!=="setup"&&se?.startedReason&&!BG(n.id)&&zt(n.id,TO,{kind:"login-greet"}).catch(le=>{console.warn(`[track ${n.id}] login greeting not delivered: ${le?.message||le}`)}))}let me=s?{running:!0,step:o.step,toAgent:o.toAgent||null,wait:o.wait||null}:null,Ue=ru(n.id),nt=Ue&&!Ue.finishedAt?{running:!0,step:Ue.step||null,added:Ue.added||[],removed:Ue.removed||[]}:null,rt=null;if(c){let N=Date.now()-i.startedAt;if(i.viewId&&!ae){let se=cf(n.id);se&&(Re(n,"view-spinup",{box:i.box,startedAt:i.startedAt,endedAt:se.finishedAt}),await ue())}else if(ne||N>_$&&!ae&&!i.viewId||N>my){let se=ne?"needs-input":N>my?"timeout":"no-view";cf(n.id,{error:se})&&await D(n,{type:"view.spinup.failed",actor:"orchestrator",source:"orchestrator",boxId:i.box,provider:S?.agent||null,payload:{ts:i.startedAt,name:i.name,reason:se}}).catch(()=>{})}else rt={running:!0,step:i.step,name:i.name}}return{trackId:n.id,leadBox:n.leadBox,items:Ie,context:U?{pct:U.pct,occupancy:U.occupancy,window:U.window,windowKnown:U.windowKnown,model:U.model}:null,models:{current:Ge,options:ug(S?.agent)},pendingPrompt:ne,working:ae,stopping:Sl(n.id),leadStarting:Ae,handoff:me,reshape:nt,view:rt,queued:Wo(n.id).filter(N=>N.kind!=="ship-notify"&&N.kind!=="prompt-answer"&&N.kind!=="login-greet"),draft:n.draft||null,draftRev:n.draftRev||0}}function IG(e){let t=new Set;for(let n of e.boxes||[])n.role==="subtask"&&n.name&&t.add(n.name);for(let n of Object.values(e.subtasks||{}))n?.box&&t.add(n.box);return t}async function Sb(e,t){let n=await we(e);if(!n)return null;let r=na(e).find(d=>d.id===t)||null;if(!r)return null;let o=r.box||null;if(!o)return{items:[],working:!1,box:null,agent:r.agent,task:r.task};let s=await J(n),a=Gn(s).filter(d=>d.box===o&&!(d.kind==="message"&&d.role==="assistant"&&d.ask&&!String(d.text||"").trim()&&!d.images?.length)),i=hw(s.filter(d=>d.boxId===o),a.filter(d=>d.kind==="message")).map(d=>({kind:"command-batch",id:d.id,ts:d.pending?d.ts:(d.anchorTs??d.ts)-1,anchorTs:d.anchorTs,anchorBox:d.anchorBox,agent:d.agent,boxRole:d.boxRole,commands:d.commands,pending:d.pending})),c=[...a,...i].filter(d=>d.ts!=null).sort((d,p)=>d.ts-p.ts),l=n.boxes.find(d=>d.name===o)||null,u=!1;if(l&&l.state==="live"){let d=await Le(o,{lines:Xe}).catch(()=>"");u=Qd(o,l.agent||r.agent,d)}return{items:c,working:u,box:o,agent:r.agent,task:r.task}}function $G(e,t){if(e==null)return[];if(!Array.isArray(e))throw new Error("custom answer must be a list of strings");return e.slice(0,Math.max(1,t)).map(n=>{if(n==null||n==="")return"";if(typeof n!="string")throw new Error("custom answer must be text");let r=n.replace(/\s+/g," ").trim();if(/[\x00-\x1f\x7f]/.test(r))throw new Error("custom answer can't contain control characters");if(r.length>lO)throw new Error(`custom answer is too long (max ${lO} characters)`);return r})}function RG(e,t){let n=String(e||"").replace(/\s+/g," ").trim(),r=String(t||"").replace(/\s+/g," ").trim();return!n||!r?!1:n===r||r.startsWith(n)||n.startsWith(r.slice(0,24))}function Ab(e,t,n,r=Date.now()){let o=hb.get(e);if(!o)return!1;let s=!!t&&t.promptId===o.promptId&&r-o.at<OG&&(t.setup?!0:AO(n)===o.paneHash);return s||hb.delete(e),s}async function CG(e,t,n){let r=n;for(let o of MG){await ar(o);let s=await tn(e).catch(()=>null);if(s!=null&&(r=s,s!==n))break}hb.set(e,{promptId:t.promptId,paneHash:AO(r),setup:t.setup||null,at:Date.now()})}async function Nf(e,t={}){let n=Ul.get(e);n&&await n.catch(()=>{});let r=NG(e,t);Ul.set(e,r);try{return await r}finally{Ul.get(e)===r&&Ul.delete(e)}}async function NG(e,{promptId:t,answers:n,text:r,custom:o}={}){let s=pe(await te(),e);if(!s)throw new Error(`track "${e}" not found`);Qs(e,"prompt-answer");let a=s.boxes.find(y=>y.name===s.leadBox);if(!a)throw new Error(`track "${e}" has no lead box`);if(!await Ee(s.leadBox))throw new Error(`lead box "${s.leadBox}" is not running`);let c=await tn(a.name).catch(()=>""),l=Tn(a,c);if(l||(l=await PG(s,a)),!l)throw new Error("no pending prompt to answer");if(t&&t!==l.promptId)throw new Error("prompt changed since it was shown \u2014 reload and answer the current prompt");if(l.answerMode!=="say"&&Ab(a.name,l,c))throw new Error("prompt already answered \u2014 waiting for the CLI to move on");let u=$G(o,l.questions?.length??1);if(u.some(Boolean)&&!l.custom)throw new Error("custom answer isn't available for this prompt \u2014 pick one of its options");let d=(n||[]).some(y=>Array.isArray(y)&&y.length>0);if(l.custom&&!d&&!u.some(Boolean)&&l.answerMode!=="text")throw new Error("no answer selected \u2014 pick an option or type your own");u.some(Boolean)&&(n=(l.questions||[]).map((y,x)=>u[x]&&!y.multiSelect?[]:Array.isArray(n?.[x])?n[x]:[]));let p;if(l.answerMode==="text"){let y=typeof r=="string"?r.trim():"";if(!y)throw new Error("this prompt needs a code \u2014 paste it into the card");if(/\s/.test(y)||y.length>2048)throw new Error("that doesn't look like a sign-in code \u2014 paste the code exactly as shown");await Ze(s.leadBox,y,{enter:!0,kind:"answer-prompt"}),p={mode:"text-input",value:"\u2039code\u203A",count:1,redacted:!0}}else if(l.answerMode==="esc")await Je(s.leadBox,["Escape"],{kind:"answer-prompt"}),p={mode:"keys",value:"Escape",count:1};else if(l.answerMode==="say"){let y=uA(l,n||[],typeof r=="string"?r:"",u);if(!y)throw new Error("no answer selected \u2014 pick an option or reply in chat");await zt(s.id,y,{kind:"prompt-answer"}),p={mode:"say",value:y,count:1}}else if(u[0]&&l.provider==="claude"){let y=NA(l,n||[],u[0]);await Pm(s.leadBox,[...y.pre,{text:y.text}],{kind:"answer-prompt"});let x=!1;for(let A of[150,300,600]){await ar(A);let $=await tn(s.leadBox).catch(()=>""),P=Tn(a,$);if(P?.customText&&RG(P.customText,y.text)){x=!0;break}}if(!x)throw new Error("custom answer didn't take \u2014 the widget moved; reload and answer again");await Pm(s.leadBox,y.post,{kind:"answer-prompt"});let E=A=>A.map($=>$.key).join(" ");p={mode:"keys+text",value:`${E(y.pre)} \u2039text\u203A ${E(y.post)}`.trim(),count:y.pre.length+1+y.post.length}}else if(l.provider==="claude"||l.answerMode==="keys"){let y=xw(l,n||[]);await Je(s.leadBox,y,{kind:"answer-prompt"}),p={mode:"keys",value:y.join(" "),count:y.length}}else{let y=WS(l,n||[]);await Ze(s.leadBox,y,{enter:!0,kind:"answer-prompt"}),p={mode:"text",value:y,count:1}}if(l.answerMode!=="say"&&await CG(a.name,l,c),l.answerMode==="say"){let y=l.questions||[];for(let x=0;x<y.length;x++){let E=y[x],A=new Set(Array.isArray(n?.[x])?n[x]:[]),$=[...A].map(L=>E.options?.[L]).filter(Boolean).map(L=>({label:L.label,description:L.description||""}));u[x]&&$.push({label:u[x],description:"",custom:!0});let P=(E.options||[]).map((L,T)=>A.has(T)?null:L?.label).filter(Boolean);dg(s,a,l,{...p,groupId:l.groupId||l.promptId,questionIndex:x,questionTotal:l.questionTotal??y.length,header:E.header||"",question:E.question||"",multiSelect:!!E.multiSelect,chosen:$,rejected:P})}return await ee({flow:"prompt",phase:"answered",sessionName:s.leadBox,agent:a.agent,provider:l.provider,promptId:l.promptId,...p}).catch(()=>{}),{ok:!0,promptId:l.promptId,sent:p.count}}let m=l.questions?.[0]||{},w=new Set(Array.isArray(n?.[0])?n[0]:[]),h=[...w].map(y=>m.options?.[y]).filter(Boolean).map(y=>({label:y.label,description:y.description||""}));u[0]&&h.push({label:u[0],description:"",custom:!0});let g=(m.options||[]).map((y,x)=>w.has(x)?null:y?.label).filter(Boolean),b=l.review?"review":/^claude:model-confirm:/.test(l.promptId||"")?"model-confirm":/^claude:resume-confirm:/.test(l.promptId||"")?"resume-confirm":l.setup==="continue"?"login-continue":void 0;return p={...p,groupId:l.groupId||l.promptId,questionIndex:l.questionIndex??0,questionTotal:l.questionTotal??1,header:m.header||"",question:m.question||"",multiSelect:!!m.multiSelect,chosen:h,rejected:g,...b?{control:b}:{}},await ee({flow:"prompt",phase:"answered",sessionName:s.leadBox,agent:a.agent,provider:l.provider,promptId:l.promptId,...p}).catch(()=>{}),dg(s,a,l,p),{ok:!0,promptId:l.promptId,sent:p.count}}async function PG(e,t){if(!t)return null;let n=await J(e).catch(()=>[]);return dw(Gn(n),{leadBoxId:t.name,provider:t.agent,isAnswered:r=>n.some(o=>o.type==="prompt.answered"&&o.payload?.promptId===r)})}async function Tb(e,{promptId:t,questionIndex:n}={}){let r=pe(await te(),e);if(!r)throw new Error(`track "${e}" not found`);let o=r.boxes.find(l=>l.name===r.leadBox);if(!o)throw new Error(`track "${e}" has no lead box`);if(!await Ee(r.leadBox))throw new Error(`lead box "${r.leadBox}" is not running`);let a=await MA(o);if(!a)throw new Error("no pending prompt to navigate");if(a.provider!=="claude")throw new Error("prompt navigation not supported for this provider");if(a.review)throw new Error("cannot navigate on the review screen \u2014 answer or cancel");let i=a.questionTotal??1;if(i<2)throw new Error("not a multi-question prompt");if(!Number.isInteger(n)||n<0||n>=i)throw new Error("questionIndex out of range");if(t&&t!==a.promptId)throw new Error("prompt changed since it was shown \u2014 reload and try again");let c=PA(a,n);return c.length?(await Je(r.leadBox,c,{kind:"navigate-prompt"}),await ee({flow:"prompt",phase:"navigated",sessionName:r.leadBox,agent:o.agent,provider:a.provider,promptId:a.promptId,fromIndex:a.questionIndex??0,toIndex:n,mode:"keys",value:c.join(" "),count:c.length}).catch(()=>{}),{ok:!0,promptId:a.promptId,sent:c.length}):{ok:!0,promptId:a.promptId,sent:0}}function Pf(e){let t=Ho.get(e);return t||(t={items:[],timer:null,flushing:!1,idleSince:null},Ho.set(e,t)),t}function BG(e){let t=Ho.get(e);return!!t&&(t.items.length>0||!!t.flushing)}function Wo(e){return(Ho.get(e)?.items??[]).map(({delivery:t,...n})=>({...n}))}function Eb(e=Date.now()){let t=0,n=0;for(let r of Ho.values())for(let o of r.items){t+=1;let s=e-(o.delivery?.queuedAt??o.ts??e);s>n&&(n=s)}return{queueDepth:t,queueOldestAgeMs:n}}function EO(e,t,n){let r=t.filter(o=>o.delivery&&!o.delivery.settled);r.length&&(async()=>{let o=pe(await te(),e)||null;for(let s of r)await Rn(o,s.delivery,`dropped:${n}`)})().catch(()=>{})}function Df(e,t="cancel"){let n=Ho.get(e);if(!n)return[];let r=n.items.splice(0);return n.idleSince=null,n.timer&&(clearInterval(n.timer),n.timer=null),EO(e,r,t),r}function _O(e,t,n){let r=Ho.get(e);if(!r)return[];let o=r.items.filter(s=>n(s));return o.length?(r.items=r.items.filter(s=>!n(s)),r.items.length||(r.idleSince=null,r.timer&&(clearInterval(r.timer),r.timer=null)),EO(e,o,t),o):[]}async function _b(e){let t=Df(e),n=t.filter(o=>o.text&&!o.kind).map(o=>o.text),r=null;if(n.length){let o=pe(await te(),e);if(o)return r=zl(o,n),await ue(),{removed:t,restored:r,draftRev:o.draftRev||0}}return{removed:t,restored:r,draftRev:null}}function Ib(e){let t=Pf(e);t.timer||(t.timer=setInterval(()=>LG(e).catch(()=>{}),DG))}async function LG(e){let t=Ho.get(e);if(!(!t||t.flushing)){if(!t.items.length){t.timer&&(clearInterval(t.timer),t.timer=null);return}t.flushing=!0;try{let n=pe(await te(),e);if(!n||n.archivedAt){Df(e,"archived");return}let r=async(l,u="")=>{let d=[];for(let g of t.items)y$(g.delivery,l),FR(g,l)&&d.push(g);if(!d.length)return;t.items=t.items.filter(g=>!d.includes(g));let p=Date.now()-Math.min(...d.map(g=>g.heldSince||Date.now())),m=Math.max(1,Math.round(Uy()/6e4)),w=String(u||"").split(`
235
235
  `).map(g=>g.trimEnd()).filter(g=>g.trim()).slice(-3).join(`
236
236
  `),h=l==="noSession"?`The scheduled prompt waited ${m} min for the box's session to come back and was dropped \u2014 open the terminal.`:`The scheduled prompt waited ${m} min for the box to become idle and was dropped \u2014 open the terminal.`;for(let g of d)g.delivery&&await Rn(n,g.delivery,l==="noSession"?"failed:not-running":"failed:blocked");Re(n,"delivery-held",{box:n.leadBox,agent:o?.agent??null,reason:l,heldMs:p,producer:"loop",deliveryId:d[0]?.delivery?.id??null,message:h,...w?{detail:w}:{}}),await ue(),$s(n,{provider:o?.agent??null,cls:"delivery-held",note:h}).catch(()=>{})},o=n.boxes.find(l=>l.name===n.leadBox),s=Ri(e);if(s&&!s.finishedAt&&s.step!=="done"&&!s.error){Bo(t,!1),await r("handoff");return}if(Sl(e)){Bo(t,!1),await r("busy");return}let a=await Ee(n.leadBox);if(a&&await ou(a)&&(a=await Zl(n,o,"queue")?await Ee(n.leadBox):null,await ue()),!a){Bo(t,!1),await r("noSession");return}if(To(o?.agent)){Bo(t,!1),await r("cap");return}let i=nn(n.leadBox,await Le(n.leadBox,{lines:Xe}).catch(()=>""));if(zc(o?.agent,i)){Bo(t,!1),await r("busy",i);return}if(po(o?.agent,i)){let l=await tn(n.leadBox).catch(()=>i);if(Tn(o,l)){Bo(t,!1),await r("prompt");return}}if(!Bo(t,!0)){await r("grace");return}let c=t.items.shift();t.idleSince=null,c.delivery&&(c.delivery.dequeuedAt=Date.now());try{await mb(n,o,a,c.text,c.kind??null,c.attachments??null,c.delivery??null)}catch(l){if(l?.code!=="cli-not-running")throw c.delivery&&await Rn(n,c.delivery,ui(l)),l;t.items.unshift(c),c.delivery&&(c.delivery.requeued+=1,c.delivery.dequeuedAt=null,await El(n,c.delivery,{position:1,reason:"requeue"})),await Zl(n,o,"queue-gate")}await ue()}finally{t.flushing=!1}}}async function $b(e,t,n,r){let o=To(t?.agent);if(!o)return;if(!r&&typeof n=="string"&&n.trim()&&(zl(e,[n]),await ue()),fE(e.id,o))try{await D(e,{type:"usage.cap.hit",actor:"system",provider:t?.agent??null,boxId:e.leadBox,payload:{...o,blockedKind:r??null}})}catch{}let s=new Error(`${t?.agent??"the lead provider"} is paused \u2014 its ${o.window} spend limit is reached ($${o.spentUsd.toFixed(2)} of $${o.limitUsd.toFixed(2)})`);throw s.usageCap=o,s}async function jG(e,t){let n=nn(e.leadBox,await Le(e.leadBox,{lines:Xe}).catch(()=>""));if(!po(t?.agent,n))return!1;let r=await tn(e.leadBox).catch(()=>n);return!!Tn(t,r)}async function mb(e,t,n,r,o=null,s=null,a=null){a||(a=Tl({text:r,producer:Al({kind:o}),kind:o,provider:t?.agent??null,attachments:Array.isArray(s)?s.length:0})),a.provider??=t?.agent??null,await $b(e,t,r,o);let i=Vl.get(e.id)||0,c=r,l=!1,u=e.pendingHandoffHydrate||null;e.pendingHandoffHydrate&&(c=gO(r,e.pendingHandoffHydrate.artifact||Uo),delete e.pendingHandoffHydrate,l=!0);let d=Array.isArray(s)?s.filter(h=>h&&h.rel):[];if(d.length){let h=jR(d.map(g=>g.rel));c=c.trim()?`${c.trim()}
237
237
 
@@ -271,7 +271,7 @@ ${o}`}async function _i(e,t,n,r={}){let o=d6(t,n,r);for(let s of["CLAUDE.md","AG
271
271
  ${s}
272
272
  ${a}`}async function ou(e){return!e?.name||!e.createdMs||Date.now()-e.createdMs<Mc()?!1:Wn(e.name)}async function Zl(e,t,n){return!t||e.archivedAt||Hr.has(t.state)?!1:(await ee({flow:"rehydrate",phase:"resume-dead-cli",trackId:e.id,sessionName:t.name,agent:t.agent,via:n}).catch(()=>{}),console.warn(`[track] ${t.name}: CLI is not running (bare shell) \u2014 relaunching (${n})`),await Ht(t.name).catch(()=>{}),t.state="stopped",Ii(e))}async function Ii(e,{freshSession:t=!1,reason:n=null}={}){let r=e.boxes.find(a=>a.name===e.leadBox);if(!r)return!1;let o=lb.get(r.name);if(o)return o;let s=b6(e,r,{freshSession:t,reason:n}).finally(()=>lb.delete(r.name));return lb.set(r.name,s),s}async function Gb(e){let n=(await te()).tracks.find(o=>o.leadBox===e);if(!n||n.archivedAt||n.transferredTo||Date.now()-(ub.get(e)??0)<y6)return!1;let r=await Ii(n,{reason:"attach"}).catch(()=>!1);return r?(ub.delete(e),await ue()):ub.set(e,Date.now()),r}async function b6(e,t,{freshSession:n=!1,reason:r=null}={}){if(e.archivedAt||e.transferredTo||Hr.has(t.state)||await Ee(t.name))return!1;let o=n===!0,s=o?eu():null,a=o?$c(yb(t.agent),s,t.name):Of(t.agent,t.sessionId,{cwd:t.cwd,peerName:t.name}),i=await Ad(a);if(i===_a)return Re(e,"rehydrate-failed",{box:t.name,agent:t.agent,reason:`agent "${t.agent}" is not installed on this box`}),!1;i===Ia&&console.warn(`[track] ${t.name}: could not confirm "${t.agent}" on PATH \u2014 relaunching anyway (launch verifier will catch a real miss)`);let c=o?{sessionId:t.sessionId??null,pinned:t.pinned===!0,epochs:JSON.parse(JSON.stringify(Fo(t)))}:null,l=Date.now();if(o){let u=Fo(t),d=u[u.length-1];d.endedAt==null&&(d.endedAt=l),d.endReason==null&&(d.endReason=r||"fresh-session"),u.push({agent:t.agent,sessionId:s,pinned:t.agent==="claude",startedAt:l,endedAt:null}),t.sessionId=s,t.pinned=t.agent==="claude"}try{let u=Rs({agent:t.agent,agentCmd:a}),d=await Hn(t.name,t.cwd,{agentCmd:a,agent:t.agent,resumeSessionId:t.sessionId,pinned:t.pinned===!0});return t.hookTokenHash=ss(d.hookToken),Ai(t,d.launchCmd),t.cliVersion=await u,Fo(t)[t.epochs.length-1].cliVersion=t.cliVersion,vs({cwd:t.cwd,sessionName:t.name,agent:t.agent,agentCmd:a,onBlocked:({message:p})=>yO(e.id,{box:t.name,agent:t.agent,message:p}).catch(()=>{})}),t.state="live",o&&Re(e,"lead-refreshed",{box:t.name,agent:t.agent,fromSessionId:c.sessionId,toSessionId:s,epoch:t.epochs.length-1,reason:r||"fresh-session",cliVersion:t.cliVersion??null,standing:await yi(t.cwd)}),Re(e,"rehydrated",{box:t.name,agent:t.agent,...o?{fresh:!0}:{}}),!0}catch(u){return o&&(t.sessionId=c.sessionId,t.pinned=c.pinned,t.epochs=c.epochs),Re(e,"rehydrate-failed",{box:t.name,agent:t.agent,reason:String(u?.message||u)}),!1}}async function $i(e,{freshSession:t=!1,reason:n=null}={}){let r=await te(),o=pe(r,e);if(!o)throw new Error(`track "${e}" not found`);if(!o.archivedAt)throw new Error(`track "${e}" is not archived`);return delete o.archivedAt,Xl.delete(e),Re(o,"unarchived",n?{reason:n}:{}),await Ii(o,t?{freshSession:!0,reason:"loop-fire"}:{}),await ue(),an(o)}async function Kb(e,t){let n=typeof t=="string"?t.trim():"";if(!n)throw new Error("name (non-empty string) required");if(n.length>gb)throw new Error(`name too long (max ${gb} chars)`);let r=await te(),o=pe(r,e);if(!o)throw new Error(`track "${e}" not found`);if(String(o.name||"").startsWith("\u21BB"))throw new Error("loop run Tracks are named by their loop \u2014 rename the loop on the Loops tab");if(n===o.name)return an(o);let s=o.name;return o.name=n,Re(o,"renamed",{from:s,to:n}),await ue(),an(o)}async function Vb(){let e=await te(),t=0;for(let n of e.tracks||[])n.transferredTo&&mp(n,{at:n.transferredAt??Date.now()})&&t++;return t&&await ue(),t}async function zb(){let e=await te(),t=new Set((await en()).map(s=>s.name)),n=new Set((e.tracks||[]).filter(s=>!He(s)).flatMap(s=>(s.boxes||[]).map(a=>a.name))),r=0,o=!1;for(let s of e.tracks||[])if(He(s))for(let a of s.boxes)t.has(a.name)&&!n.has(a.name)&&(await Ht(a.name).catch(()=>{}),s.transferredTo?console.log(`[track] reaped orphan box ${a.name} on transferred-away track ${s.id} (\u2192 ${s.transferredTo})`):Re(s,"orphan-reaped",{box:a.name,agent:a.agent}),r++,o=!0),!Hr.has(a.state)&&a.state!=="stopped"&&(a.state="stopped",o=!0);return o&&await ue(),r}function x6(){Hl.clear()}async function Hf(e,{freshSession:t=!1,force:n=!1}={}){let r=await te(),o=pe(r,e);if(!o)throw new Error(`track "${e}" not found`);if(o.archivedAt)throw new Error(`track "${e}" is archived \u2014 restore it before restarting the lead`);Oi(o);let s=o.boxes.find(c=>c.name===o.leadBox);if(!s)throw new Error(`track "${e}" has no lead box`);if(Hr.has(s.state))throw new Error("lead box is terminal \u2014 nothing to restart");if(await Ee(o.leadBox)){let c=nn(o.leadBox,await Le(o.leadBox,{lines:Xe}).catch(()=>"")),l=zc(s.agent,c);if(l&&!n){let u=Hl.get(e),d=Date.now(),p=u&&d-u.at<k6?u.count+1:1;Hl.set(e,{count:p,at:d});let m=new Error(p>=2?"lead is mid-turn \u2014 retry when it goes idle, or restart anyway if the screen is stuck":"lead is mid-turn \u2014 retry when it goes idle");throw m.code="lead-mid-turn",m.refusals=p,m.forceAvailable=p>=2,m}Hl.delete(e),n&&(Qs(e,"restart"),await ee({flow:"restart",phase:"forced",trackId:e,sessionName:o.leadBox,agent:s.agent,busy:l,paneTail:!0}).catch(()=>{})),await Ht(o.leadBox),s.state="stopped"}else Hl.delete(e);let i=await Ii(o,t?{freshSession:!0,reason:"loop-fire"}:{});if(await ue(),!i)throw new Error("rehydrate failed \u2014 see the track's rehydrate-failed event");return an(o)}async function v6(e,t,{escSends:n=0,kept:r=0}={}){if(!e||!t)return null;let o=eu();return await D(e,{type:"box.stuck.detected",actor:"system",source:"orchestrator",boxId:t.name,provider:t.agent,payload:{ts:Date.now(),offerId:o,box:t.name,agent:t.agent,escSends:n,kept:r}}),o}async function Jb(e,t,n,{force:r=!1}={}){let o=await we(e);if(!o)throw new Error(`track "${e}" not found`);if(!t)throw new Error("unknown offer");let s=await J(o).catch(()=>[]),a=s.find(d=>(d.type==="box.fullscreen.detected"||d.type==="box.stuck.detected")&&d.payload?.offerId===t);if(!a)throw new Error("unknown offer");let i=a.type==="box.stuck.detected",c=i?"box.stuck.answered":"box.fullscreen.answered";if(s.some(d=>d.type===c&&d.payload?.offerId===t))throw new Error("offer already answered");let u=n&&(i||r===!0);return n&&await Hf(e,{force:u}),await D(o,{type:c,actor:"user",source:"orchestrator",boxId:o.leadBox,payload:{ts:Date.now(),offerId:t,action:n?"restarted":"dismiss",...u?{forced:!0}:{}}}).catch(()=>{}),{ok:!0,action:n?"restarted":"dismiss",forced:u}}function Ai(e,t){if(!e)return null;let n=xs(t);return e.launchEcho=n,Ha(e.name,n),n}function Yb(e,t,n){let r={name:e.name,agent:e.agent,role:t,state:n,cwd:e.cwd,sessionId:e.sessionId,pinned:e.pinned===!0,hookTokenHash:ss(e.hookToken),createdAt:Date.now()};return Ai(r,e.launchCmd),r}function fO(e,t){if(!e?.id||!t?.box)return[];let n=(e.boxes||[]).find(r=>r.name===t.box);return Gp({trackId:e.id,boxId:t.box,epoch:0,provider:n?.agent??t.agent??null})}function Fo(e){return(!Array.isArray(e.epochs)||e.epochs.length===0)&&(e.epochs=[{agent:e.agent??null,sessionId:e.sessionId??null,pinned:e.pinned===!0,cliVersion:e.cliVersion??null,startedAt:e.createdAt??null,endedAt:null}]),e.epochs}async function _f(e,t){let n=await te(),r=pe(n,e);r&&(r.handoff={...r.handoff||{},...t},await ue())}function FO(e,t=Date.now()){let n=e?.handoff;if(!n||n.finishedAt)return null;let r=n.step,o=!!n.toBox&&n.toBox===n.fromBox,s=e.boxes?.find?.(i=>i.name===e.leadBox)||null;return(o?e.leadBox===n.fromBox&&!!n.startedAt&&Array.isArray(s?.epochs)&&s.epochs.some(i=>i.startedAt!=null&&i.startedAt>=n.startedAt):!!n.toBox&&e.leadBox===n.toBox)?{...n,step:"done",finishedAt:t,recovered:`committed before restart (was "${r}")`}:{...n,step:"error",finishedAt:t,error:`interrupted by an agent restart during "${r}"; lead "${e.leadBox}" retained \u2014 retry the handoff`,recovered:"rolled-back"}}async function Xb(){let e=await te(),t=!1;for(let n of e.tracks||[]){let r=n.handoff,o=FO(n);if(!o)continue;t=!0;let s=!!r.toBox&&r.toBox===r.fromBox;if(s&&o.step==="error"){let c=await Ee(r.fromBox).catch(()=>null),l=n.boxes.find(u=>u.name===r.fromBox);if(c&&l&&c.agent===r.toAgent&&r.toAgent!==l.agent){let u=Date.now(),d=Fo(l),p=d[d.length-1],m=p.agent,w=p.sessionId??null;p.endedAt=u,r.reason&&(p.endReason=r.reason);let h=c.agent==="claude"&&!!c.sessionId,g=await Rs({agent:r.toAgent});d.push({agent:r.toAgent,sessionId:c.sessionId||null,pinned:h,cliVersion:g,startedAt:u,endedAt:null}),l.agent=r.toAgent,l.cliVersion=g,l.sessionId=c.sessionId||null,l.pinned=h,l.state="live",n.pendingHandoffHydrate={artifact:Uo,at:u},Re(n,"lead-handoff",{from:r.fromBox,to:r.fromBox,fromAgent:m,toAgent:r.toAgent,fromSessionId:w,toSessionId:c.sessionId||null,epoch:d.length-1,singleBox:!0,skipPermissions:r.skipPermissions,reason:r.reason??null,handoffStartedAt:r.startedAt,recovered:!0,standing:await yi(l.cwd)}),n.handoff={...r,step:"done",finishedAt:u,recovered:"swap adopted from live tmux tags after restart"},await ee({flow:"lead-handoff",phase:"reconciled",trackId:n.id,outcome:"done",recovered:n.handoff.recovered,fromBox:r.fromBox,toBox:r.toBox}).catch(()=>{});continue}}let a=!s&&o.recovered==="rolled-back"&&r.toBox&&r.toBox!==n.leadBox?r.toBox:null,i=!s&&o.step==="done"?r.fromBox:null;n.handoff=o,await ee({flow:"lead-handoff",phase:"reconciled",trackId:n.id,outcome:o.step,recovered:o.recovered,fromBox:o.fromBox,toBox:o.toBox}).catch(()=>{}),i&&await Ht(i).catch(()=>{}),a&&await Ht(a).catch(()=>{})}return t&&await ue(),t}async function Wf(e,t,n=!0,r=null,{reviveArchived:o=!1}={}){let s=Xs.get(e);if(s&&!s.finishedAt)throw new Error("a lead handoff is already running for this Track");let a=pe(await te(),e);if(!a)throw new Error(`track "${e}" not found`);if(a.archivedAt&&!o)throw new Error(`track "${e}" is archived \u2014 restore it before handing off`);Oi(a),Qs(e,"handoff");let i=await Ei(t,n),c=To(t);if(c){let m=new Error(`can't hand off to ${t} \u2014 its ${c.window} spend limit is reached ($${c.spentUsd.toFixed(2)} of $${c.limitUsd.toFixed(2)})`);throw m.usageCap=c,m}let l=bO(r),u=!1;a.archivedAt&&(await $i(e,{reason:l?.code==="context-refresh"?"context-refresh":"lead-handoff"}),a=pe(await te(),e),u=!0);let d=await Ee(a.leadBox);if(!d)throw new Error(`lead box "${a.leadBox}" is not running`);let p={trackId:e,step:"checkpoint",fromBox:a.leadBox,toAgent:t,skipPermissions:n,reason:l,revived:u,toBox:a.leadBox,startedAt:Date.now(),finishedAt:null,error:null};return Xs.set(e,p),await _f(e,{step:p.step,fromBox:p.fromBox,toAgent:t,toBox:p.toBox,skipPermissions:n,startedAt:p.startedAt,finishedAt:null,error:null}),S6(p,a,d,i,t).catch(async m=>{p.error=m?.message||String(m),p.finishedAt=Date.now(),console.error(`[lead-handoff ${e}] FAILED at step "${p.step}": ${p.error}`),await _f(e,{step:p.step,error:p.error,finishedAt:p.finishedAt}).catch(()=>{}),ee({flow:"lead-handoff",phase:"failed",trackId:e,step:p.step,error:p.error,fromBox:p.fromBox,toAgent:p.toAgent,toBox:p.toBox}).catch(()=>{})}),ee({flow:"lead-handoff",phase:"started",trackId:e,fromBox:p.fromBox,toAgent:t,cwd:d.cwd}).catch(()=>{}),p}async function S6(e,t,n,r,o){let s=async(P,L={})=>{e.step=P,console.log(`[lead-handoff ${e.trackId}] step \u2192 ${P}`),await _f(e.trackId,{step:P,toBox:e.toBox}),await ee({flow:"lead-handoff",phase:P,trackId:e.trackId,fromBox:e.fromBox,toBox:e.toBox,toAgent:o,sessionName:L.sessionName,...L})};console.log(`[lead-handoff ${e.trackId}] ${e.fromBox}: ${n.agent} \u2192 ${o} IN PLACE`);let a=await te(),i=pe(a,e.trackId)?.boxes.find(P=>P.name===e.fromBox)||null,c=i?.agent||n.agent,l=i?.sessionId??n.sessionId??null,u=i?.pinned===!0;if(await s("checkpoint",{sessionName:e.fromBox}),e.checkpoint="llm",e.quiescence=null,To(c))e.checkpoint="skipped-capped";else try{let P=await cp(e.fromBox,{timeoutMs:bb,quiesce:{box:i?{...i,name:e.fromBox}:n,reason:e.reason?.code||"lead-handoff",onWait:async L=>{e.wait=L,await s("await-turn",{sessionName:e.fromBox,wait:L})},onResume:async()=>{e.wait=null,await s("checkpoint",{sessionName:e.fromBox})}}});e.quiescence=Dw(P),e.waitedMs=(P.quiescence?.pre?.waitedMs||0)+(P.quiescence?.post?.waitedMs||0)}catch(P){e.checkpoint="reconstructed",e.quiescence=Dw(P),e.waitedMs=P?.quiescence?.pre?.waitedMs||0,e.wait=null,await ee({flow:"lead-handoff",phase:"checkpoint-fallback",trackId:e.trackId,fromBox:e.fromBox,error:P?.message||String(P)}).catch(()=>{})}e.checkpoint!=="llm"&&(e.statusArtifact=await lp(e.trackId,n.cwd,{trackName:t.name||t.id}).catch(()=>null),await s("checkpoint-degraded",{sessionName:e.fromBox,checkpoint:e.checkpoint,statusArtifact:e.statusArtifact})),await s("swap",{cwd:n.cwd,agentCmd:r});let p=Rs({agent:o,agentCmd:r}),m=await Gw(e.fromBox,{agentCmd:r,agent:o});Ha(e.fromBox,xs(m.launchCmd)),await s("hydrate",{sessionName:e.fromBox});let w=xs(m.launchCmd);await gr({cwd:n.cwd,sessionId:m.sessionId,sessionName:e.fromBox,agent:o,agentCmd:Zs(o),launchEcho:w}).catch(P=>{if(P?.code!=="cli-not-running")throw P});let h=Kc(await Le(e.fromBox,{lines:Xe}).catch(()=>""),w);if(await ee({flow:"lead-handoff",phase:"hydrate-ready",trackId:e.trackId,sessionName:e.fromBox,toAgent:o,up:co(o,h),paneTail:!0}).catch(()=>{}),!co(o,h)){await s("rollback",{sessionName:e.fromBox,fromAgent:c});let P=Of(c,l,{skipPermissions:e.skipPermissions,cwd:n.cwd,peerName:e.fromBox}),L=await Gw(e.fromBox,{agentCmd:P,agent:c,resumeSessionId:l,pinned:u});Ha(e.fromBox,xs(L.launchCmd));let T=await te(),C=pe(T,e.trackId);if(C){let j=C.boxes.find(K=>K.name===e.fromBox);j&&(j.state="live",Ai(j,L.launchCmd)),Re(C,"lead-handoff-failed",{box:e.fromBox,fromAgent:c,toAgent:o,reason:e.reason,error:`incoming ${o} CLI never drew its composer`,rolledBack:!0,handoffStartedAt:e.startedAt}),await ue()}throw new Error(`incoming ${o} CLI never drew its composer \u2014 rolled back to ${c} (--resume, context intact)`)}await s("commit");let g=await te(),b=pe(g,e.trackId);if(!b)throw new Error(`track "${e.trackId}" not found during handoff commit \u2014 was it deleted or archived mid-flight?`);let y=b.boxes.find(P=>P.name===e.fromBox);if(!y)throw new Error(`lead box row "${e.fromBox}" missing during handoff commit`);let x=Date.now(),E=Fo(y),A=E[E.length-1];A.endedAt=x,e.reason&&(A.endReason=e.reason);let $=await p;E.push({agent:o,sessionId:m.sessionId,pinned:m.pinned,cliVersion:$,startedAt:x,endedAt:null}),y.agent=o,y.sessionId=m.sessionId,y.pinned=m.pinned,y.cliVersion=$,Ai(y,m.launchCmd),y.state="live",y.role="lead",b.pendingHandoffHydrate={artifact:e.statusArtifact||Uo,at:x},Re(b,"lead-handoff",{from:e.fromBox,to:e.fromBox,fromAgent:c,toAgent:o,fromSessionId:l,toSessionId:m.sessionId,epoch:E.length-1,singleBox:!0,forced:m.forced||void 0,skipPermissions:e.skipPermissions,reason:e.reason,cliVersion:$,handoffStartedAt:e.startedAt,checkpoint:e.checkpoint,quiescence:e.quiescence||void 0,waitedMs:e.waitedMs||void 0,standing:await yi(y.cwd)}),await ue(),await s("done",{sessionName:e.fromBox}),await _f(e.trackId,{finishedAt:Date.now(),error:null}),e.finishedAt=Date.now()}async function ek(e){let t=If.get(e);if(t&&!t.finishedAt)throw new Error("a transfer is already running for this Track");let n=await te(),r=pe(n,e);if(!r)throw new Error(`track "${e}" not found`);if(r.archivedAt)throw new Error("track is archived \u2014 restore it before moving it");if(r.kind==="setup")throw new Error("setup boxes don't move");if(r.transferredTo)throw new Error(`track already transferred to ${r.transferredTo}`);let o=Xs.get(e);if(o&&!o.finishedAt)throw new Error("a lead handoff is running \u2014 retry when it settles");for(let a of Vt.values())if(a.trackId===e&&!a.finishedAt)throw new Error("a subtask is still running on this Track \u2014 wait for it to merge back before moving");let s={trackId:e,step:"checkpoint",startedAt:Date.now(),finishedAt:null,error:null};return If.set(e,s),A6(s,r).catch(a=>{s.error=a?.message||String(a),s.finishedAt=Date.now(),console.error(`[transfer-out ${e}] FAILED at step "${s.step}": ${s.error}`)}),s}async function A6(e,t){let n=t.boxes.find(u=>u.name===t.leadBox)||null,r=n?await Ee(n.name).catch(()=>null):null;if(e.checkpoint="llm",!r||n&&To(n.agent))e.checkpoint=r?"skipped-capped":"skipped-dead";else try{await cp(t.leadBox,{timeoutMs:bb,quiesce:{box:n,reason:"transfer-out",onWait:()=>{e.step="await-turn"},onResume:()=>{e.step="checkpoint"}}})}catch{e.checkpoint="reconstructed"}e.checkpoint!=="llm"&&await lp(t.id,t.cwd,{trackName:t.name||t.id}).catch(()=>null),e.step="push";let o=t.workspace?.branch??null,s=[];if(o)for(let u of Jt(t.workspace)){if(!u?.dir)continue;let d={name:u.name??null,repo:u.repo??null,baseSha:null,pushed:!1};try{await Nn(u.dir,["push","origin",o],Zb);let{stdout:p}=await Nn(u.dir,["rev-parse","HEAD"]);d.baseSha=p.trim(),d.pushed=!0}catch(p){d.error=String(p?.message||p).split(`
273
273
  `)[0]}s.push(d)}e.step="wip";let a=await Wy(t,{force:!0}),i=await te(),c=pe(i,t.id),l=c?.boxes.find(u=>u.name===c.leadBox)||null;l&&Fo(l),await ue(),e.result={name:c?.name??t.name,agent:l?.agent??null,leadBox:c?.leadBox??t.leadBox,createdAt:c?.createdAt??null,branch:o,repos:s.filter(u=>u.pushed).map(({name:u,repo:d,baseSha:p})=>({name:u,repo:d,baseSha:p})),unpushed:s.filter(u=>!u.pushed).map(({name:u,repo:d,error:p})=>({name:u,repo:d,error:p})),wip:a.pushed[0]?{ref:a.pushed[0].ref,sha:a.pushed[0].sha}:null,wips:a.pushed,wipSkipped:a.skipped,checkpoint:e.checkpoint,epochs:l?.epochs??[],codeless:!o||!s.some(u=>u.pushed)},e.step="ready",e.finishedAt=Date.now()}function Oi(e){if(!e?.transferredTo)return;let t=new Error(`track "${e.id}" moved to node ${e.transferredTo} \u2014 drive it there`);throw t.transferredTo=e.transferredTo,t}async function qf(e,{toNode:t,mode:n="transfer"}={}){if(!t||typeof t!="string")throw new Error("toNode required");let r=await te(),o=pe(r,e);if(!o)throw new Error(`track "${e}" not found`);if(o.transferredTo)return{ok:!0,alreadyTransferred:o.transferredTo};Mb(e),await Hb(e,o,n==="recover"?"track recovered onto another node":"track transferred to another node");let s=Date.now();mp(o,{at:s,reason:n==="recover"?"node-offline":"node-transfer"});let a=await qy(o,{ts:s}),i=a.pushed[0]??null;return o.transferredTo=t,o.transferredAt=s,Re(o,"transferred-out",{toNode:t,mode:n,box:o.leadBox,...i?{rescueRef:i.ref,rescueSha:i.sha}:{},...a.pushed.length?{rescues:a.pushed}:{}}),await ue(),{ok:!0,toNode:t,rescue:i?{ref:i.ref,sha:i.sha}:null,rescues:a.pushed}}function tk(e,t){if(!e||e.transferredTo)return null;let n=(e.events||[]).filter(a=>a?.type==="transferred-in");if(!n.length)return null;let r=n[n.length-1],o=Number(r.at)||null,s=Number(t?.at)||null;return o!=null&&s!=null&&o>s?{since:o,fromNode:r.fromNode??null}:s==null&&r.fromNode&&r.fromNode===t?.toNode?{since:o,fromNode:r.fromNode}:null}async function nk(e){let t=[],n=await te();for(let r of Array.isArray(e)?e:[]){if(!r?.id)continue;let o=tk(pe(n,r.id),r);o&&(console.error(`[transfer] plane's move record for ${r.id} (\u2192 ${r.toNode??"?"}${r.at?` at ${new Date(r.at).toISOString()}`:""}) predates this node's adoption${o.fromNode?` from ${o.fromNode}`:""} at ${new Date(o.since).toISOString()} \u2014 re-sending the move-commit`),t.push({id:r.id,stale:!0,since:o.since,toNode:r.toNode??null}))}return t}async function rk(e){let t=[];for(let n of Array.isArray(e)?e:[])if(!(!n?.id||!n?.toNode))try{let r=await te(),o=tk(pe(r,n.id),n);if(o){console.error(`[transfer] IGNORING stale demote notice for ${n.id} (plane says it moved to ${n.toNode}${n.at?` at ${new Date(n.at).toISOString()}`:""}; this node adopted it${o.fromNode?` from ${o.fromNode}`:""} at ${new Date(o.since).toISOString()}) \u2014 keeping the live copy; re-sending the move-commit`),t.push({id:n.id,stale:!0,since:o.since,toNode:n.toNode});continue}let s=await qf(n.id,{toNode:n.toNode,mode:n.mode==="recover"?"recover":"transfer"});t.push({id:n.id,...s})}catch(r){/not found/i.test(String(r?.message))||console.error(`[transfer] demote of ${n.id} failed: ${r?.message||r}`)}return t}async function hO(e,t,n){try{await ol(e,t,n)}catch{await Nn(e,["worktree","prune"]).catch(()=>{}),await ol(e,t,n)}return t}function T6(e,{wip:t=null,wips:n=null}={}){let r=Jt(e).filter(a=>a?.dir),o=Array.isArray(n)?n.filter(a=>a?.sha):[];if(!o.length)return t?.sha&&r.length===1?r:[];let s=r.filter(a=>o.some(i=>i.repo?i.repo===a.repo:i.name!=null&&i.name===a.name));return!s.length&&r.length===1&&o.length===1?r:s}async function E6(e,t){try{await Nn(e,["fetch","origin",Hy(t)],Zb);let{stdout:n}=await Nn(e,["rev-parse","FETCH_HEAD^"]),{stdout:r}=await Nn(e,["rev-parse","HEAD"]),o=null,s=n.trim()===r.trim();return s||await Nn(e,["merge-base","--is-ancestor",r.trim(),n.trim()]).then(()=>!0,()=>!1)&&(await Nn(e,["reset","--hard",n.trim()]),o={from:r.trim(),to:n.trim()},s=!0),s?(await Nn(e,["read-tree","--reset","-u","FETCH_HEAD"]),await Nn(e,["reset","-q"]),{applied:!0,skipped:null,advanced:o}):{applied:!1,skipped:"snapshot does not parent the fetched branch head",advanced:null}}catch(n){return{applied:!1,skipped:String(n?.message||n).split(`
274
- `)[0],advanced:null}}}function I6(e){if(typeof e!="string"||!_6.test(e)||e.includes("..")||e.includes("@{")||e.endsWith(".lock"))throw new Error("branch fails the safe-ref check")}async function ok(e={}){let{trackId:t,name:n,agent:r="claude",skipPermissions:o=!0,mode:s="transfer"}=e;if(!t||typeof t!="string"||!/^[0-9a-f]{8}$/.test(t))throw new Error("trackId (8-hex string) required");if(typeof n!="string"||!n.trim())throw new Error("name (string) required");if(s!=="transfer"&&s!=="recover")throw new Error(`unknown adopt mode "${s}"`);if(e.branch!=null&&I6(e.branch),Sf.has(t))throw new Error("an adopt is already running for this Track");Sf.set(t,{startedAt:Date.now()});try{return await $6({...e,trackId:t,name:n,agent:r,skipPermissions:o,mode:s})}finally{Sf.delete(t)}}async function $6({trackId:e,name:t,agent:n,skipPermissions:r,mode:o,fromNode:s=null,toNode:a=null,branch:i=null,repos:c=[],wip:l=null,wips:u=null,brief:d=null,epochs:p=[],createdAt:m=null,leadBox:w=null,reason:h=null,downSince:g=null,fallback:b=null}){let y=await Ei(n,r),x=await te(),E=pe(x,e);if(E&&!E.transferredTo)throw new Error(`track "${e}" is already hosted on this node`);E&&(await qy(E).catch(()=>{}),await BO(E),x.tracks.splice(x.tracks.indexOf(E),1),await ue()),await Z.mkdir(Gl,{recursive:!0});let A=X.join(Gl,e);await Z.rm(A,{recursive:!0,force:!0}).catch(()=>{});let $=null,P=!1,L=[];try{let T=[];if(i)for(let ae of Array.isArray(c)?c:[]){let Ae=typeof ae=="string"?ae:ae?.repo;if(!Ae||!/^[^/\s]+\/[^/\s]+$/.test(Ae))continue;let be=await cs(Ae)??await od(Ae);await Nn(be,["fetch","origin",`+refs/heads/${i}:refs/heads/${i}`],Zb),T.push({slug:Ae,base:be,name:typeof ae=="object"?ae?.name??null:null})}if(i&&T.length===1){let{base:ae,slug:Ae}=T[0];await hO(ae,A,i),L.push({base:ae,dir:A}),await Yl(A);let be=await Ns(ae);$={dir:A,base:ae,branch:i,kind:"worktree",baseRef:be,repo:Ae}}else if(i&&T.length>=2){await Z.mkdir(A,{recursive:!0});let ae=new Set([".bostrat"]),Ae=[];for(let be of T){let Q=be.name||X.basename(be.base);ae.has(Q)&&(Q=be.slug.replace("/","-"));for(let nt=2;ae.has(Q);nt++)Q=`${X.basename(be.base)}-${nt}`;ae.add(Q);let he=X.join(A,Q);await hO(be.base,he,i),L.push({base:be.base,dir:he});let Ue=await Ns(be.base);Ae.push({name:Q,dir:he,base:be.base,baseRef:Ue,repo:be.slug})}await _i(A,Ae,i),$={dir:A,kind:"multi",branch:i,repos:Ae}}else P=!0,await Z.mkdir(A,{recursive:!0}),await eg(A),await Yl(A),$={dir:A,base:null,branch:null,kind:"repo"};let C=[];for(let ae of T6($,{wip:l,wips:u})){let Ae=await E6(ae.dir,e);C.push({name:ae.name,repo:ae.repo,applied:Ae.applied,skipped:Ae.skipped,...Ae.advanced?{advanced:Ae.advanced}:{}})}let j=C.some(ae=>ae.applied),K=C.length===1?C[0].skipped:C.filter(ae=>ae.skipped).map(ae=>`${ae.name??ae.repo}: ${ae.skipped}`).join("; ")||null,M=C.length===1?C[0].advanced??null:null;await zR({id:e,cwd:A}).catch(()=>({restored:!1}));let I=X.join(A,Uo),S=null;(await yd(A)).restored?S="checkpoint":typeof d=="string"&&d.trim()&&(await Z.mkdir(X.dirname(I),{recursive:!0}),await Z.writeFile(I,d),S="brief");let W=new Set(x.tracks.flatMap(ae=>(ae.boxes||[]).map(Ae=>Ae.name))),ie=null;w&&!W.has(w)&&!await Ee(w).catch(()=>null)?ie=w:(ie=`${t.trim()} lead`,W.has(Td(ie))&&(ie=`${t.trim().slice(0,50).trim()} ${e} lead`));let z=await Hn(ie,A,{agentCmd:y,agent:n,trackId:e});vs({cwd:z.cwd,sessionName:z.name,agent:n,agentCmd:y});let Ge=Date.now(),_e=Yb(z,"lead","live"),Y=(Array.isArray(p)?p:[]).filter(ae=>ae&&typeof ae=="object").map(ae=>({...ae})),ne=Y[Y.length-1];ne&&ne.endedAt==null&&(ne.endedAt=Ge,ne.endReason==null&&(ne.endReason=o==="recover"?"node-offline":"node-transfer"));let Ie=await Rs({agent:n,agentCmd:y});Y.push({agent:n,sessionId:z.sessionId??null,pinned:z.pinned===!0,cliVersion:Ie,startedAt:Ge,endedAt:null}),_e.epochs=Y,_e.cliVersion=Ie;let Pe={id:e,name:t.trim(),cwd:z.cwd,workspace:$,leadBox:z.name,boxes:[_e],events:[],createdAt:Number.isFinite(m)?m:Ge,...S?{pendingHandoffHydrate:{artifact:Uo,at:Ge}}:{}};return Re(Pe,"transferred-in",{box:z.name,agent:n,fromNode:s,toNode:a,mode:o,reason:h,...o==="recover"?{downSince:Number.isFinite(g)?g:null}:{},...b&&typeof b=="object"?{fallback:{from:String(b.from??"transfer"),step:b.step??null,error:typeof b.error=="string"?b.error.slice(0,300):null,at:Number.isFinite(b.at)?b.at:null}}:{},branch:$.branch??null,wip:j,...M?{wipAdvanced:M}:{},...$.kind==="multi"&&C.length?{wipRepos:C}:{},epoch:Y.length-1,name:Pe.name,cwd:Pe.cwd,workspace:{base:$.base??null,branch:$.branch??null,kind:$.kind,...$.baseRef?{baseRef:$.baseRef}:{},...$.repo?{repo:$.repo}:{},...$.repos?{repos:$.repos.map(({name:ae,base:Ae,baseRef:be,repo:Q})=>({name:ae,base:Ae,baseRef:be,repo:Q}))}:{}}}),x.tracks.push(Pe),await ue(),{...await an(Pe),adopt:{wipApplied:j,wipSkipped:K,...M?{wipAdvanced:M}:{},...$.kind==="multi"?{wipRepos:C}:{},codeless:P,artifactSource:S}}}catch(T){for(let C of L)await Nt(C.base,C.dir).catch(()=>{});throw await Z.rm(A,{recursive:!0,force:!0}).catch(()=>{}),T}}async function UO(e,t,n){let r=await te(),o=pe(r,e);o&&(o.subtasks=o.subtasks||{},o.subtasks[t]={...o.subtasks[t]||{},...n},await ue())}async function ki(e,t){e.step=t,await su(e)}function HO(e,t=Date.now()){if(!e||e.finishedAt)return null;let n=e.step;return["snapshot","spawn","working"].includes(n)?{...e,step:"error",finishedAt:t,error:`interrupted by an agent restart during "${n}"; no changes were applied to the lead \u2014 retry the delegation`,recovered:"rolled-back"}:{...e,step:"error",finishedAt:t,error:`interrupted by an agent restart during "${n}"; the lead's working tree may hold a PARTIAL merge \u2014 review git status. The subtask's work is preserved on branch ${e.branch}`,recovered:"partial-merge"}}function WO(e){return!!e&&!e.finishedAt&&!e.canceled&&e.step==="working"&&!!e.box&&!!e.dir&&!!e.base&&!!e.branch}async function C6(e,t,n){if(!WO(n)||Vt.has(t)||!await Ee(n.box).catch(()=>null))return!1;try{await Z.access(n.dir)}catch{return!1}let o=await Ee(e.leadBox).catch(()=>null);if(!o?.cwd)return!1;let s={...n,id:t,leadBox:e.leadBox,step:"working",canceled:!1,forceMerge:!1};return Vt.set(t,s),GO(s,o).catch(a=>qO(s,a)),!0}async function sk(){let e=await te(),t=!1;for(let n of e.tracks||[]){for(let[r,o]of Object.entries(n.subtasks||{})){if(Vt.has(r))continue;if(await C6(n,r,o)){t=!0,Re(n,"subtask-resumed",{box:o.box,agent:o.agent,task:o.task,subtaskId:r,resumedStep:o.step}),await ee({flow:"subtask",phase:"resumed",trackId:n.id,subtaskId:r,box:o.box,branch:o.branch}).catch(()=>{});continue}let s=o.step,a=HO(o);if(!a)continue;t=!0,n.subtasks[r]=a;let i=n.boxes.find(c=>c.subtaskId===r);i&&!Hr.has(i.state)&&(i.state="canceled"),Re(n,"subtask-failed",{from:o.box,fromAgent:o.agent,task:o.task,subtaskId:r,failedStep:s,error:a.error,recovered:a.recovered,durationMs:o.startedAt?a.finishedAt-o.startedAt:null}),await ee({flow:"subtask",phase:"reconciled",trackId:n.id,subtaskId:r,outcome:a.step,recovered:a.recovered,box:o.box,branch:o.branch}).catch(()=>{}),await mO(n,o.box,o.dir)}for(let r of n.boxes){if(r.role!=="subtask"||Hr.has(r.state)||Vt.has(r.subtaskId)||n.subtasks?.[r.subtaskId])continue;t=!0,r.state="canceled";let o=r.subtaskId?X.join(Ti,`${n.id}-${r.subtaskId}`):null;await ee({flow:"subtask",phase:"reaped-legacy-orphan",trackId:n.id,subtaskId:r.subtaskId,box:r.name}).catch(()=>{}),await mO(n,r.name,o)}}return t=await N6(e)||t,t&&await ue(),t}async function mO(e,t,n){if(t&&await Ht(t).catch(()=>{}),!n)return;if(e.workspace?.kind==="multi"){for(let o of Jt(e.workspace)){let s=X.join(n,o.name);await Nt(o.base,s).then(()=>!0,()=>!1)||await Nt(o.dir,s).catch(()=>{})}await Z.rm(n,{recursive:!0,force:!0}).catch(()=>{});return}let r=await Ee(e.leadBox).catch(()=>null);r?.cwd&&await Nt(r.cwd,n).catch(()=>{})}async function N6(e){let t;try{t=await Z.readdir(Ti)}catch{return!1}let n=new Set;for(let o of e.tracks||[]){for(let s of Object.keys(o.subtasks||{}))n.add(`${o.id}-${s}`);for(let s of o.boxes||[])s.subtaskId&&n.add(`${o.id}-${s.subtaskId}`)}for(let o of Vt.values())o.dir&&n.add(X.basename(o.dir));let r=!1;for(let o of t){if(n.has(o))continue;let s=X.join(Ti,o),a=(e.tracks||[]).find(i=>o.startsWith(`${i.id}-`));if(a?.workspace?.kind==="multi"){for(let i of Jt(a.workspace))await Nt(i.base,X.join(s,i.name)).catch(()=>{});await Z.rm(s,{recursive:!0,force:!0}).catch(()=>{})}else{let i=a?await Ee(a.leadBox).catch(()=>null):null;i?.cwd?await Nt(i.cwd,s).catch(()=>{}):await Z.rm(s,{recursive:!0,force:!0}).catch(()=>{})}await ee({flow:"subtask",phase:"swept-orphan-worktree",dir:s}).catch(()=>{}),r=!0}return r}async function ak(e,{agent:t,task:n,skipPermissions:r=!0,reason:o=null}={}){if(typeof n!="string"||!Ao(n))throw new Error("task (string) required");let s=await Ei(t,r),a=To(t);if(a){let m=new Error(`can't delegate to ${t} \u2014 its ${a.window} spend limit is reached ($${a.spentUsd.toFixed(2)} of $${a.limitUsd.toFixed(2)})`);throw m.usageCap=a,m}let i=pe(await te(),e);if(!i)throw new Error(`track "${e}" not found`);let c=await Ee(i.leadBox);if(!c)throw new Error(`lead box "${i.leadBox}" is not running`);if(!c.cwd)throw new Error("can't resolve the lead's working directory");let l=i.workspace?.kind==="multi",u=null;if(l){let m=Jt(i.workspace);if(!m.length)throw new Error("this multi-repo Track has no tagged repos to delegate into");for(let w of m)if(!w?.dir||!await Ya(w.dir))throw new Error(`tagged checkout "${w?.name??"?"}" is missing from the lead workspace (${w?.dir??"no dir"})`);u=m.map(w=>({name:w.name,leadDir:w.dir,base:null}))}else if(!await Ya(c.cwd))throw new Error(`subtask delegation needs the lead's workspace to be a git repo (got ${c.cwd})`);let d=eu().slice(0,8),p={id:d,trackId:e,trackName:i.name,agent:t,task:Ao(n),skipPermissions:r,reason:bO(o),step:"snapshot",leadBox:i.leadBox,box:null,branch:`bostrat/${Kf(i.name)}-${d}`,base:null,repos:u,dir:X.join(Ti,`${e}-${d}`),stat:null,conflicts:[],applied:null,startedAt:Date.now(),finishedAt:null,error:null,canceled:!1,forceMerge:!1};return Vt.set(d,p),await su(p),P6(p,c,s).catch(m=>qO(p,m)),p}async function qO(e,t){e.failedStep=e.step,e.error=t instanceof Ql?"canceled":t?.message||String(t),e.step=t instanceof Ql?"canceled":"error",e.finishedAt=Date.now(),await ck(e).catch(()=>{}),await su(e).catch(()=>{}),await j6(e).catch(()=>{})}function Vf(e){let t=Vt.get(e);if(!t)throw new Error(`subtask "${e}" not found`);if(t.finishedAt)throw new Error("subtask already finished");return t.canceled=!0,t}function ik(e){let t=Vt.get(e);if(!t)throw new Error(`subtask "${e}" not found`);if(t.finishedAt)throw new Error("subtask already finished");if(t.step!=="working")throw new Error(`subtask is not waiting to merge (step: ${t.step})`);return t.forceMerge=!0,t}async function P6(e,t,n){if(await ki(e,"snapshot"),e.repos){for(let s of e.repos)s.base=await Xa(s.leadDir,`bostrat: snapshot for subtask ${e.id}`);await su(e)}else e.base=await Xa(t.cwd,`bostrat: snapshot for subtask ${e.id}`);if(await ki(e,"spawn"),await Z.mkdir(Ti,{recursive:!0}),e.repos){await Z.mkdir(e.dir,{recursive:!0});for(let a of e.repos)await Cs(a.leadDir,X.join(e.dir,a.name),e.branch,a.base);let s=Jt((pe(await te(),e.trackId)||{}).workspace);await _i(e.dir,e.repos.map(a=>{let i=s.find(c=>c?.name===a.name);return{name:a.name,repo:i?.repo??null,baseRef:null}}),e.branch)}else await Cs(t.cwd,e.dir,e.branch,e.base),await Yl(e.dir);await D6(e,t);let r=e.trackName.slice(0,38).trim(),o=await Hn(`${r} ${e.agent} sub ${e.id}`,e.dir,{agentCmd:n,agent:e.agent});e.box=o.name,await B6(e,o),await kO(e.trackId,o.name,gG(e.task,!!e.repos),{kind:"subtask"}),await GO(e,t)}async function GO(e,t){await ki(e,"working");let n=X.join(e.dir,Af);if(await U6(n,e),e.canceled)throw new Ql;if(await ki(e,"merge"),e.repos){let s={files:0,insertions:0,deletions:0},a=[],i=[],c=!0;for(let l of e.repos){let u=X.join(e.dir,l.name);await Zw(u,`bostrat: subtask ${e.id} result (auto-committed)`,{trailers:fO({id:e.trackId,boxes:[{name:e.box,agent:e.agent}]},e)}),l.stat=await og(l.leadDir,l.base,e.branch,bi),l.files=await sg(l.leadDir,l.base,e.branch,bi);let d=await ag(l.leadDir,l.base,e.branch,bi);l.applied=d.applied,l.conflicts=d.conflicts??[],s.files+=l.stat.files,s.insertions+=l.stat.insertions,s.deletions+=l.stat.deletions,a.push(...l.files.map(p=>X.join(l.name,p))),i.push(...l.conflicts.map(p=>p.startsWith("patch did not apply cleanly")?`${l.name}: ${p}`:X.join(l.name,p))),d.applied||(c=!1)}e.stat=s,e.files=a,e.conflicts=i,e.applied=c}else{await Zw(e.dir,`bostrat: subtask ${e.id} result (auto-committed)`,{trailers:fO({id:e.trackId,boxes:[{name:e.box,agent:e.agent}]},e)}),e.stat=await og(t.cwd,e.base,e.branch,bi),e.files=await sg(t.cwd,e.base,e.branch,bi);let s=await ag(t.cwd,e.base,e.branch,bi);e.applied=s.applied,e.conflicts=s.conflicts}await su(e);let r=await F6(e,t,n);await ki(e,"resume"),await kO(e.trackId,e.leadBox,yG(e.task,e.stat,e.conflicts,r),{kind:"subtask-resume"}),await ki(e,"reap"),await ck(e),e.step="done";let o=Date.now();await UO(e.trackId,e.id,{...Gf(e),finishedAt:o}),await L6(e,o),e.finishedAt=o}async function D6(e,t){let n=X.join(e.dir,X.dirname(Kl));await Z.mkdir(n,{recursive:!0});let r="";try{r=await OS(t.cwd,t.sessionId)}catch{}if(!r)try{r=await Z.readFile(X.join(t.cwd,".bostrat/handoff/latest.md"),"utf8")}catch{r="_(no prior conversation digest available \u2014 rely on the working tree.)_"}let o=`# Lead context for subtask ${e.id}
274
+ `)[0],advanced:null}}}function I6(e){if(typeof e!="string"||!_6.test(e)||e.includes("..")||e.includes("@{")||e.endsWith(".lock"))throw new Error("branch fails the safe-ref check")}async function ok(e={}){let{trackId:t,name:n,agent:r="claude",skipPermissions:o=!0,mode:s="transfer"}=e;if(!t||typeof t!="string"||!/^[0-9a-f]{8}$/.test(t))throw new Error("trackId (8-hex string) required");if(typeof n!="string"||!n.trim())throw new Error("name (string) required");if(s!=="transfer"&&s!=="recover")throw new Error(`unknown adopt mode "${s}"`);if(e.branch!=null&&I6(e.branch),Sf.has(t))throw new Error("an adopt is already running for this Track");Sf.set(t,{startedAt:Date.now()});try{return await $6({...e,trackId:t,name:n,agent:r,skipPermissions:o,mode:s})}finally{Sf.delete(t)}}async function $6({trackId:e,name:t,agent:n,skipPermissions:r,mode:o,fromNode:s=null,toNode:a=null,branch:i=null,repos:c=[],wip:l=null,wips:u=null,brief:d=null,epochs:p=[],createdAt:m=null,leadBox:w=null,reason:h=null,downSince:g=null,fallback:b=null}){let y=await Ei(n,r),x=await te(),E=pe(x,e);if(E&&!E.transferredTo)throw new Error(`track "${e}" is already hosted on this node`);E&&(await qy(E).catch(()=>{}),await BO(E),x.tracks.splice(x.tracks.indexOf(E),1),await ue()),await Z.mkdir(Gl,{recursive:!0});let A=X.join(Gl,e);await Z.rm(A,{recursive:!0,force:!0}).catch(()=>{});let $=null,P=!1,L=[];try{let T=[];if(i)for(let ae of Array.isArray(c)?c:[]){let Ae=typeof ae=="string"?ae:ae?.repo;if(!Ae||!/^[^/\s]+\/[^/\s]+$/.test(Ae))continue;let be=await cs(Ae)??await od(Ae);await Nn(be,["fetch","origin",`+refs/heads/${i}:refs/heads/${i}`],Zb),T.push({slug:Ae,base:be,name:typeof ae=="object"?ae?.name??null:null})}if(i&&T.length===1){let{base:ae,slug:Ae}=T[0];await hO(ae,A,i),L.push({base:ae,dir:A}),await Yl(A);let be=await Ns(ae);$={dir:A,base:ae,branch:i,kind:"worktree",baseRef:be,repo:Ae}}else if(i&&T.length>=2){await Z.mkdir(A,{recursive:!0});let ae=new Set([".bostrat"]),Ae=[];for(let be of T){let Q=be.name||X.basename(be.base);ae.has(Q)&&(Q=be.slug.replace("/","-"));for(let nt=2;ae.has(Q);nt++)Q=`${X.basename(be.base)}-${nt}`;ae.add(Q);let me=X.join(A,Q);await hO(be.base,me,i),L.push({base:be.base,dir:me});let Ue=await Ns(be.base);Ae.push({name:Q,dir:me,base:be.base,baseRef:Ue,repo:be.slug})}await _i(A,Ae,i),$={dir:A,kind:"multi",branch:i,repos:Ae}}else P=!0,await Z.mkdir(A,{recursive:!0}),await eg(A),await Yl(A),$={dir:A,base:null,branch:null,kind:"repo"};let C=[];for(let ae of T6($,{wip:l,wips:u})){let Ae=await E6(ae.dir,e);C.push({name:ae.name,repo:ae.repo,applied:Ae.applied,skipped:Ae.skipped,...Ae.advanced?{advanced:Ae.advanced}:{}})}let j=C.some(ae=>ae.applied),K=C.length===1?C[0].skipped:C.filter(ae=>ae.skipped).map(ae=>`${ae.name??ae.repo}: ${ae.skipped}`).join("; ")||null,M=C.length===1?C[0].advanced??null:null;await zR({id:e,cwd:A}).catch(()=>({restored:!1}));let I=X.join(A,Uo),S=null;(await yd(A)).restored?S="checkpoint":typeof d=="string"&&d.trim()&&(await Z.mkdir(X.dirname(I),{recursive:!0}),await Z.writeFile(I,d),S="brief");let W=new Set(x.tracks.flatMap(ae=>(ae.boxes||[]).map(Ae=>Ae.name))),ie=null;w&&!W.has(w)&&!await Ee(w).catch(()=>null)?ie=w:(ie=`${t.trim()} lead`,W.has(Td(ie))&&(ie=`${t.trim().slice(0,50).trim()} ${e} lead`));let z=await Hn(ie,A,{agentCmd:y,agent:n,trackId:e});vs({cwd:z.cwd,sessionName:z.name,agent:n,agentCmd:y});let Ge=Date.now(),_e=Yb(z,"lead","live"),Y=(Array.isArray(p)?p:[]).filter(ae=>ae&&typeof ae=="object").map(ae=>({...ae})),ne=Y[Y.length-1];ne&&ne.endedAt==null&&(ne.endedAt=Ge,ne.endReason==null&&(ne.endReason=o==="recover"?"node-offline":"node-transfer"));let Ie=await Rs({agent:n,agentCmd:y});Y.push({agent:n,sessionId:z.sessionId??null,pinned:z.pinned===!0,cliVersion:Ie,startedAt:Ge,endedAt:null}),_e.epochs=Y,_e.cliVersion=Ie;let Pe={id:e,name:t.trim(),cwd:z.cwd,workspace:$,leadBox:z.name,boxes:[_e],events:[],createdAt:Number.isFinite(m)?m:Ge,...S?{pendingHandoffHydrate:{artifact:Uo,at:Ge}}:{}};return Re(Pe,"transferred-in",{box:z.name,agent:n,fromNode:s,toNode:a,mode:o,reason:h,...o==="recover"?{downSince:Number.isFinite(g)?g:null}:{},...b&&typeof b=="object"?{fallback:{from:String(b.from??"transfer"),step:b.step??null,error:typeof b.error=="string"?b.error.slice(0,300):null,at:Number.isFinite(b.at)?b.at:null}}:{},branch:$.branch??null,wip:j,...M?{wipAdvanced:M}:{},...$.kind==="multi"&&C.length?{wipRepos:C}:{},epoch:Y.length-1,name:Pe.name,cwd:Pe.cwd,workspace:{base:$.base??null,branch:$.branch??null,kind:$.kind,...$.baseRef?{baseRef:$.baseRef}:{},...$.repo?{repo:$.repo}:{},...$.repos?{repos:$.repos.map(({name:ae,base:Ae,baseRef:be,repo:Q})=>({name:ae,base:Ae,baseRef:be,repo:Q}))}:{}}}),x.tracks.push(Pe),await ue(),{...await an(Pe),adopt:{wipApplied:j,wipSkipped:K,...M?{wipAdvanced:M}:{},...$.kind==="multi"?{wipRepos:C}:{},codeless:P,artifactSource:S}}}catch(T){for(let C of L)await Nt(C.base,C.dir).catch(()=>{});throw await Z.rm(A,{recursive:!0,force:!0}).catch(()=>{}),T}}async function UO(e,t,n){let r=await te(),o=pe(r,e);o&&(o.subtasks=o.subtasks||{},o.subtasks[t]={...o.subtasks[t]||{},...n},await ue())}async function ki(e,t){e.step=t,await su(e)}function HO(e,t=Date.now()){if(!e||e.finishedAt)return null;let n=e.step;return["snapshot","spawn","working"].includes(n)?{...e,step:"error",finishedAt:t,error:`interrupted by an agent restart during "${n}"; no changes were applied to the lead \u2014 retry the delegation`,recovered:"rolled-back"}:{...e,step:"error",finishedAt:t,error:`interrupted by an agent restart during "${n}"; the lead's working tree may hold a PARTIAL merge \u2014 review git status. The subtask's work is preserved on branch ${e.branch}`,recovered:"partial-merge"}}function WO(e){return!!e&&!e.finishedAt&&!e.canceled&&e.step==="working"&&!!e.box&&!!e.dir&&!!e.base&&!!e.branch}async function C6(e,t,n){if(!WO(n)||Vt.has(t)||!await Ee(n.box).catch(()=>null))return!1;try{await Z.access(n.dir)}catch{return!1}let o=await Ee(e.leadBox).catch(()=>null);if(!o?.cwd)return!1;let s={...n,id:t,leadBox:e.leadBox,step:"working",canceled:!1,forceMerge:!1};return Vt.set(t,s),GO(s,o).catch(a=>qO(s,a)),!0}async function sk(){let e=await te(),t=!1;for(let n of e.tracks||[]){for(let[r,o]of Object.entries(n.subtasks||{})){if(Vt.has(r))continue;if(await C6(n,r,o)){t=!0,Re(n,"subtask-resumed",{box:o.box,agent:o.agent,task:o.task,subtaskId:r,resumedStep:o.step}),await ee({flow:"subtask",phase:"resumed",trackId:n.id,subtaskId:r,box:o.box,branch:o.branch}).catch(()=>{});continue}let s=o.step,a=HO(o);if(!a)continue;t=!0,n.subtasks[r]=a;let i=n.boxes.find(c=>c.subtaskId===r);i&&!Hr.has(i.state)&&(i.state="canceled"),Re(n,"subtask-failed",{from:o.box,fromAgent:o.agent,task:o.task,subtaskId:r,failedStep:s,error:a.error,recovered:a.recovered,durationMs:o.startedAt?a.finishedAt-o.startedAt:null}),await ee({flow:"subtask",phase:"reconciled",trackId:n.id,subtaskId:r,outcome:a.step,recovered:a.recovered,box:o.box,branch:o.branch}).catch(()=>{}),await mO(n,o.box,o.dir)}for(let r of n.boxes){if(r.role!=="subtask"||Hr.has(r.state)||Vt.has(r.subtaskId)||n.subtasks?.[r.subtaskId])continue;t=!0,r.state="canceled";let o=r.subtaskId?X.join(Ti,`${n.id}-${r.subtaskId}`):null;await ee({flow:"subtask",phase:"reaped-legacy-orphan",trackId:n.id,subtaskId:r.subtaskId,box:r.name}).catch(()=>{}),await mO(n,r.name,o)}}return t=await N6(e)||t,t&&await ue(),t}async function mO(e,t,n){if(t&&await Ht(t).catch(()=>{}),!n)return;if(e.workspace?.kind==="multi"){for(let o of Jt(e.workspace)){let s=X.join(n,o.name);await Nt(o.base,s).then(()=>!0,()=>!1)||await Nt(o.dir,s).catch(()=>{})}await Z.rm(n,{recursive:!0,force:!0}).catch(()=>{});return}let r=await Ee(e.leadBox).catch(()=>null);r?.cwd&&await Nt(r.cwd,n).catch(()=>{})}async function N6(e){let t;try{t=await Z.readdir(Ti)}catch{return!1}let n=new Set;for(let o of e.tracks||[]){for(let s of Object.keys(o.subtasks||{}))n.add(`${o.id}-${s}`);for(let s of o.boxes||[])s.subtaskId&&n.add(`${o.id}-${s.subtaskId}`)}for(let o of Vt.values())o.dir&&n.add(X.basename(o.dir));let r=!1;for(let o of t){if(n.has(o))continue;let s=X.join(Ti,o),a=(e.tracks||[]).find(i=>o.startsWith(`${i.id}-`));if(a?.workspace?.kind==="multi"){for(let i of Jt(a.workspace))await Nt(i.base,X.join(s,i.name)).catch(()=>{});await Z.rm(s,{recursive:!0,force:!0}).catch(()=>{})}else{let i=a?await Ee(a.leadBox).catch(()=>null):null;i?.cwd?await Nt(i.cwd,s).catch(()=>{}):await Z.rm(s,{recursive:!0,force:!0}).catch(()=>{})}await ee({flow:"subtask",phase:"swept-orphan-worktree",dir:s}).catch(()=>{}),r=!0}return r}async function ak(e,{agent:t,task:n,skipPermissions:r=!0,reason:o=null}={}){if(typeof n!="string"||!Ao(n))throw new Error("task (string) required");let s=await Ei(t,r),a=To(t);if(a){let m=new Error(`can't delegate to ${t} \u2014 its ${a.window} spend limit is reached ($${a.spentUsd.toFixed(2)} of $${a.limitUsd.toFixed(2)})`);throw m.usageCap=a,m}let i=pe(await te(),e);if(!i)throw new Error(`track "${e}" not found`);let c=await Ee(i.leadBox);if(!c)throw new Error(`lead box "${i.leadBox}" is not running`);if(!c.cwd)throw new Error("can't resolve the lead's working directory");let l=i.workspace?.kind==="multi",u=null;if(l){let m=Jt(i.workspace);if(!m.length)throw new Error("this multi-repo Track has no tagged repos to delegate into");for(let w of m)if(!w?.dir||!await Ya(w.dir))throw new Error(`tagged checkout "${w?.name??"?"}" is missing from the lead workspace (${w?.dir??"no dir"})`);u=m.map(w=>({name:w.name,leadDir:w.dir,base:null}))}else if(!await Ya(c.cwd))throw new Error(`subtask delegation needs the lead's workspace to be a git repo (got ${c.cwd})`);let d=eu().slice(0,8),p={id:d,trackId:e,trackName:i.name,agent:t,task:Ao(n),skipPermissions:r,reason:bO(o),step:"snapshot",leadBox:i.leadBox,box:null,branch:`bostrat/${Kf(i.name)}-${d}`,base:null,repos:u,dir:X.join(Ti,`${e}-${d}`),stat:null,conflicts:[],applied:null,startedAt:Date.now(),finishedAt:null,error:null,canceled:!1,forceMerge:!1};return Vt.set(d,p),await su(p),P6(p,c,s).catch(m=>qO(p,m)),p}async function qO(e,t){e.failedStep=e.step,e.error=t instanceof Ql?"canceled":t?.message||String(t),e.step=t instanceof Ql?"canceled":"error",e.finishedAt=Date.now(),await ck(e).catch(()=>{}),await su(e).catch(()=>{}),await j6(e).catch(()=>{})}function Vf(e){let t=Vt.get(e);if(!t)throw new Error(`subtask "${e}" not found`);if(t.finishedAt)throw new Error("subtask already finished");return t.canceled=!0,t}function ik(e){let t=Vt.get(e);if(!t)throw new Error(`subtask "${e}" not found`);if(t.finishedAt)throw new Error("subtask already finished");if(t.step!=="working")throw new Error(`subtask is not waiting to merge (step: ${t.step})`);return t.forceMerge=!0,t}async function P6(e,t,n){if(await ki(e,"snapshot"),e.repos){for(let s of e.repos)s.base=await Xa(s.leadDir,`bostrat: snapshot for subtask ${e.id}`);await su(e)}else e.base=await Xa(t.cwd,`bostrat: snapshot for subtask ${e.id}`);if(await ki(e,"spawn"),await Z.mkdir(Ti,{recursive:!0}),e.repos){await Z.mkdir(e.dir,{recursive:!0});for(let a of e.repos)await Cs(a.leadDir,X.join(e.dir,a.name),e.branch,a.base);let s=Jt((pe(await te(),e.trackId)||{}).workspace);await _i(e.dir,e.repos.map(a=>{let i=s.find(c=>c?.name===a.name);return{name:a.name,repo:i?.repo??null,baseRef:null}}),e.branch)}else await Cs(t.cwd,e.dir,e.branch,e.base),await Yl(e.dir);await D6(e,t);let r=e.trackName.slice(0,38).trim(),o=await Hn(`${r} ${e.agent} sub ${e.id}`,e.dir,{agentCmd:n,agent:e.agent});e.box=o.name,await B6(e,o),await kO(e.trackId,o.name,gG(e.task,!!e.repos),{kind:"subtask"}),await GO(e,t)}async function GO(e,t){await ki(e,"working");let n=X.join(e.dir,Af);if(await U6(n,e),e.canceled)throw new Ql;if(await ki(e,"merge"),e.repos){let s={files:0,insertions:0,deletions:0},a=[],i=[],c=!0;for(let l of e.repos){let u=X.join(e.dir,l.name);await Zw(u,`bostrat: subtask ${e.id} result (auto-committed)`,{trailers:fO({id:e.trackId,boxes:[{name:e.box,agent:e.agent}]},e)}),l.stat=await og(l.leadDir,l.base,e.branch,bi),l.files=await sg(l.leadDir,l.base,e.branch,bi);let d=await ag(l.leadDir,l.base,e.branch,bi);l.applied=d.applied,l.conflicts=d.conflicts??[],s.files+=l.stat.files,s.insertions+=l.stat.insertions,s.deletions+=l.stat.deletions,a.push(...l.files.map(p=>X.join(l.name,p))),i.push(...l.conflicts.map(p=>p.startsWith("patch did not apply cleanly")?`${l.name}: ${p}`:X.join(l.name,p))),d.applied||(c=!1)}e.stat=s,e.files=a,e.conflicts=i,e.applied=c}else{await Zw(e.dir,`bostrat: subtask ${e.id} result (auto-committed)`,{trailers:fO({id:e.trackId,boxes:[{name:e.box,agent:e.agent}]},e)}),e.stat=await og(t.cwd,e.base,e.branch,bi),e.files=await sg(t.cwd,e.base,e.branch,bi);let s=await ag(t.cwd,e.base,e.branch,bi);e.applied=s.applied,e.conflicts=s.conflicts}await su(e);let r=await F6(e,t,n);await ki(e,"resume"),await kO(e.trackId,e.leadBox,yG(e.task,e.stat,e.conflicts,r),{kind:"subtask-resume",detail:{subtaskId:e.id,from:e.box,fromAgent:e.agent,task:e.task,stat:e.stat,conflicts:e.conflicts,resultRel:r}}),await ki(e,"reap"),await ck(e),e.step="done";let o=Date.now();await UO(e.trackId,e.id,{...Gf(e),finishedAt:o}),await L6(e,o),e.finishedAt=o}async function D6(e,t){let n=X.join(e.dir,X.dirname(Kl));await Z.mkdir(n,{recursive:!0});let r="";try{r=await OS(t.cwd,t.sessionId)}catch{}if(!r)try{r=await Z.readFile(X.join(t.cwd,".bostrat/handoff/latest.md"),"utf8")}catch{r="_(no prior conversation digest available \u2014 rely on the working tree.)_"}let o=`# Lead context for subtask ${e.id}
275
275
 
276
276
  **Delegated task:** ${e.task}
277
277
 
@@ -701,8 +701,8 @@ follow-up on its own; the operator's tap is the gate.
701
701
  SCOPE: these instructions apply ONLY when your working directory is under
702
702
  ~/.bostrat/workspaces/ or ~/.bostrat/worktrees/ \u2014 a bostrat-orchestrated box.
703
703
  When working anywhere else, ignore everything below.
704
- `);f6=new Set(["claude","codex","cursor"]);Xl=new Set,h6=e=>Xl.has(e);m6=9e4;pO={merged:"merged",closed:"closed on GitHub WITHOUT merging",lost:"no longer found on GitHub (deleted, or its repo left the grant)"};lb=new Map;y6=6e4,ub=new Map;gb=120;k6=10*6e4,Hl=new Map;Xs=new Map,Ri=e=>Xs.get(e)||(Kt?pe(Kt,e)?.handoff:null)||null;Zb=6e4,Nn=(e,t,n=15e3)=>$f("git",["-C",e,...t],{timeout:n,maxBuffer:8*1024*1024}),If=new Map,Qb=e=>If.get(e)||null;_6=/^[A-Za-z0-9][A-Za-z0-9._/-]{0,200}$/;Sf=new Map;R6=Number(process.env.BOSTRAT_SUBTASK_TIMEOUT_MS)||18e5,O6=Number(process.env.BOSTRAT_SUBTASK_POLL_MS)||3e3,Ti=X.join(sr,"worktrees"),bi=[Kl,Af],Vt=new Map,M6=e=>Vt.get(e)||(Kt?Kt.tracks.map(t=>t.subtasks?.[e]).find(Boolean):null)||null,na=e=>{let t=new Map([...Vt.values()].filter(r=>r.trackId===e).map(r=>[r.id,r])),n=Kt?pe(Kt,e):null;if(n?.subtasks)for(let[r,o]of Object.entries(n.subtasks))t.has(r)||t.set(r,o);return[...t.values()].sort((r,o)=>r.startedAt-o.startedAt)},Gf=e=>({id:e.id,trackId:e.trackId,trackName:e.trackName,agent:e.agent,task:e.task,skipPermissions:e.skipPermissions,reason:e.reason||null,step:e.step,failedStep:e.failedStep||null,box:e.box,branch:e.branch,base:e.base,repos:e.repos||null,dir:e.dir,stat:e.stat,files:e.files||null,conflicts:e.conflicts||[],applied:e.applied,error:e.error,canceled:e.canceled,startedAt:e.startedAt,finishedAt:e.finishedAt});su=e=>UO(e.trackId,e.id,Gf(e));Kf=e=>e.trim().replace(/\s+/g,"-").replace(/[^A-Za-z0-9._-]/g,"").toLowerCase()||"track",Ql=class extends Error{}});mt();import Ce from"node:path";import At from"node:fs";import LJ from"node:readline";import{fileURLToPath as jJ}from"node:url";import Xt from"express";import LP from"node:http";import FJ from"node:https";import zi from"node:os";import{randomUUID as UJ}from"node:crypto";import{WebSocketServer as HJ}from"ws";mt();import zB from"node-pty";async function Jv(e,t,n={}){if(!We(t)){$d(e,`invalid session name: ${t}`),e.close(1008,"invalid session name");return}if(!await so()){$d(e,`host tmux server not running on ${gt}`),e.close(1011,"tmux server unavailable");return}if(!await Ee(t)){let a=!1;if(typeof n.revive=="function"&&(Rd(e,{type:"notice",message:"Resuming the lead box\u2026"}),a=await n.revive().catch(()=>!1)),!a||!await Ee(t)){$d(e,`session "${t}" not found`),e.close(1008,"session not found");return}if(e.readyState!==e.OPEN)return}let r=zv(n.cols,120,Yv),o=zv(n.rows,32,Xv),s;try{s=zB.spawn(re,["-S",gt,"attach-session","-d","-t",t],{name:"xterm-256color",cols:r,rows:o,cwd:process.env.HOME||"/",env:{...process.env,TERM:"xterm-256color"}})}catch(a){$d(e,`failed to spawn tmux attach: ${a.message}`),e.close(1011,"spawn failed");return}s.onData(a=>{e.readyState===e.OPEN&&Rd(e,{type:"data",data:a})}),s.onExit(({exitCode:a,signal:i})=>{e.readyState===e.OPEN&&(Rd(e,{type:"exit",code:a??null,signal:i??null}),e.close(1e3,"tmux exited"))}),e.on("message",a=>{let i;try{i=JSON.parse(a.toString())}catch{return}if(!(!i||typeof i!="object")){if(i.type==="data"&&typeof i.data=="string")s.write(i.data);else if(i.type==="resize"&&ZB(i.cols,i.rows))try{s.resize(Math.min(500,i.cols|0),Math.min(500,i.rows|0))}catch{}}}),e.on("close",()=>{try{s.kill()}catch{}XB(t)})}var JB=6,YB=250;async function XB(e,t=JB,n=YB){for(let r=0;r<t;r++){if(await hs(e).catch(()=>!0))return!0;await new Promise(o=>setTimeout(o,n))}return!1}var Yv=20,Xv=6;function ZB(e,t){return Number.isFinite(Number(e))&&Number.isFinite(Number(t))&&Number(e)>=Yv&&Number(t)>=Xv}function zv(e,t,n){let r=Number(e);return!Number.isFinite(r)||r<n?t:Math.min(500,r|0)}function Rd(e,t){try{e.send(JSON.stringify(t))}catch{}}function $d(e,t){Rd(e,{type:"error",message:t})}function Zv(e){let t=typeof e=="string"&&e?e:"/",n=t.indexOf("?"),r=n===-1?t:t.slice(0,n),o=n===-1?"":t.slice(n+1),s=r.match(/^\/api\/attach\/([^/]+)$/);if(!s)return{ok:!1,status:404};let a;try{a=decodeURIComponent(s[1])}catch{return{ok:!1,status:400}}let i=new URLSearchParams(o);return{ok:!0,sessionName:a,cols:Number(i.get("cols"))||void 0,rows:Number(i.get("rows"))||void 0}}An();Bd();Lw();Or();import{createRequire as WJ}from"node:module";var H6=e=>!!e&&!e.finishedAt&&!e.canceled&&!e.error;function lk({tracks:e=[],views:t=[],queuedOf:n=()=>[],jobsOf:r=()=>[],prPendingOf:o=()=>[]}={}){let s=[];for(let a of e)!a||a.archivedAt&&!a.archiving||a.transferredTo||(a.working&&s.push(`working:${a.id}`),a.prompted&&s.push(`prompted:${a.id}`),(n(a.id)??[]).length&&s.push(`queued:${a.id}`),(a.boxes||[]).some(i=>i?.role==="subtask"&&i?.state==="live")&&s.push(`subtask:${a.id}`),(r(a.id)??[]).length&&s.push(`job:${a.id}`),Object.values(a.subtasks||{}).some(H6)&&s.push(`merge-back:${a.id}`),(o(a.id)??[]).length&&s.push(`pr:${a.id}`));return t.some(a=>a?.state==="live"||a?.state==="starting")&&s.push("views"),{busy:s.length>0,reasons:s}}Qy();ke();Nl();zn();Yp();pn();var zf=60*6e4,W6=1440*6e4,q6=new Set(["merged","closed","lost"]),au=(e,t,n)=>Number.isFinite(Number(e))&&n-Number(e)<=t;function G6({trackId:e,shipPending:t=null,links:n=[],observers:r=0,now:o=Date.now()}={}){let s=[];t&&Number.isFinite(Number(t.ts))&&o-Number(t.ts)<=Sy&&s.push("ship"),r>0&&s.push("create-net");for(let a of n||[]){if(!a||q6.has(a.state))continue;let i=[a.ciFix,a.reconcile,a.ciFixAwait,a.reconcileAwait];if(!(a.trackId===e||i.some(d=>d?.trackId===e)))continue;let l=a.number??"?";a.ciFix&&au(a.ciFix.delegatedAt,zf,o)&&s.push(`ci-fix#${l}`),a.reconcile&&au(a.reconcile.delegatedAt,zf,o)&&s.push(`reconcile#${l}`),a.ciFixAwait&&au(a.ciFixAwait.since,zf,o)&&s.push(`ci-fix-await#${l}`),a.reconcileAwait&&au(a.reconcileAwait.since,zf,o)&&s.push(`reconcile-await#${l}`);let u=a.autoMerge?.armedAt??a.armedAt??null;a.trackId===e&&(a.autoMerge||a.armedAt)&&au(u,W6,o)&&s.push(`auto-merge#${l}`)}return s}var Jf=new Map;et.on("event",e=>{e?.trackId&&Jf.delete(e.trackId)});async function K6(e){if(Jf.has(e.id))return Jf.get(e.id);let t=await J(e).catch(()=>[]),n=pi(t,-1/0);return Jf.set(e.id,n),n}async function VO(e,{now:t=Date.now()}={}){let n=new Map,r=await In().catch(()=>[]);for(let o of e||[]){if(!o||He(o))continue;let s=G6({trackId:o.id,shipPending:await K6(o),links:r,observers:gI(o.id),now:t});s.length&&n.set(o.id,s)}return n}gl();import iM from"node:fs";import Go from"node:fs/promises";import fK from"node:os";import St from"node:path";import{spawn as hK}from"node:child_process";import{createRequire as mK}from"node:module";ke();bp();import Mi from"node:fs";import cu from"node:fs/promises";import J6 from"node:http";import Dt from"node:path";import Xf from"node:os";import{createRequire as Y6}from"node:module";import dk from"ws";import V6 from"node:path";import z6 from"node:os";var iu=process.env.BOSTRAT_STATE_DIR||V6.join(process.env.HOME||z6.tmpdir(),".bostrat");function uk(e=process.env){let t=(e.BOSTRAT_HOST||"").trim();if(t!=="all")return t||(e.BOSTRAT_PLANE_URL?"127.0.0.1":void 0)}function zO(e=process.env){if(!e.BOSTRAT_PLANE_URL)return null;let t=uk(e);return t==="127.0.0.1"||t==="::1"||t==="localhost"?null:{host:t}}function JO(e){let t=String(e||"").trim();if(!t)return"";let n=/^[a-z][a-z0-9+.-]*:\/\//i.test(t)?t:`wss://${t}`,r;try{r=new URL(n)}catch{return t}let o={"https:":"wss:","http:":"ws:","wss:":"wss:","ws:":"ws:"}[r.protocol];return o?(r.protocol=o,(r.pathname===""||r.pathname==="/")&&(r.pathname="/v1/node"),r.toString()):t}cm();var Pn=(()=>{try{return Y6(import.meta.url)("../package.json").version||null}catch{return null}})(),hk=process.env.BOSTRAT_STATE_DIR||Dt.join(process.env.HOME||Xf.tmpdir(),".bostrat"),nM=Dt.join(hk,"plane-link","removed.json");function YO(e){return typeof e!="string"||e.length<8?"\u2022\u2022\u2022\u2022":`${e.slice(0,6)}\u2026${e.slice(-4)}`}function X6(e=nM){try{let t=JSON.parse(Mi.readFileSync(e,"utf8"));return t&&typeof t=="object"?t:null}catch{return null}}function ra({env:e=process.env,pkgDir:t=Dt.resolve(Dt.dirname(new URL(import.meta.url).pathname),".."),exists:n=Mi.existsSync}={}){let r=String(e.BOSTRAT_INSTALL_KIND||"").trim();return["container","npm-global","git-checkout","dev"].includes(r)?r:/\/lib\/node_modules\/bostrat-node(?:\/|$)/.test(t.replace(/\\/g,"/"))?"npm-global":n(Dt.join(t,"..",".git"))?"git-checkout":"dev"}function lu(e,t){let n=String(e).split(".").map(Number),r=String(t).split(".").map(Number);if(n.some(Number.isNaN)||r.some(Number.isNaN))return!1;for(let o=0;o<Math.max(n.length,r.length);o++){let s=(n[o]||0)-(r[o]||0);if(s)return s<0}return!1}function Yf(e){switch(e){case"npm-global":return"npm install -g bostrat-node && restart the bostrat-node service";case"git-checkout":return"scripts/deploy-pi.sh (or The Bakery \u2192 Deploy to Pi \u2192 bostrat)";case"container":return"Links \u2192 Fly \u2192 Update (or the plane's auto-update while the node sleeps)";default:return"update this node's bostrat-node checkout/install"}}function Z6({home:e=process.env.HOME||Xf.homedir(),env:t=process.env}={}){let n=r=>{try{return Mi.statSync(r),!0}catch{return!1}};return{claude:n(Dt.join(e,".claude",".credentials.json")),codex:n(Dt.join(t.CODEX_HOME||Dt.join(e,".codex"),"auth.json")),cursor:n(Dt.join(t.XDG_CONFIG_HOME||Dt.join(e,".config"),"cursor","auth.json"))}}var kt=1,XO=1e3,ZO=3e4,Q6=6e4,eK=1500,tK=500,qo=100,nK=2e3,rK=25e3,oK=2.5,sK=6e4,rM=(e,t)=>{let n=Number(e);return Number.isFinite(n)&&n>0?n:t},aK=rM(process.env.BOSTRAT_PLANE_DELIVERY_TIMEOUT_MS,18e4),pk="refused:",iK={forgedUserId:"this node's events carry a userId the plane's token does not own \u2014 remove BOSTRAT_OWNER from node.env and the shell environment, then restart the node (current releases never stamp one)",foreignTrack:"the Track belongs to another user's node \u2014 this node must not append to it",squattedTrack:"the Track id is already claimed by another user \u2014 a local Track collided with theirs",transferredAway:"the Track moved to another node \u2014 this copy is stale; it should be demoted, not resumed",slugHijack:"a View slug belongs to another owner \u2014 pick a different slug"},cK=e=>{if(!e||e.userId===void 0)return e;let{userId:t,...n}=e;return n},lK=3e4,QO=10*6e4,uK=400,eM=250,dK=rM(process.env.BOSTRAT_PLANE_INGEST_TIMEOUT_MS,1e4),fk=4,pK=6e4,tM=6e4;function oM({url:e,token:t,nodeId:n=Xf.hostname(),name:r=Xf.hostname(),listTracks:o,detectAgents:s=null,onTracksTransferred:a=null,onTracksMoves:i=null,sampleMetrics:c=null,deliverySample:l=null,onHashKey:u=null,onViewBase:d=null,metricsMs:p=pK,onUpdateAvailable:m=null,onUpdatePolicy:w=null,onHelloRefused:h=null,updatePolicy:g=null,installKind:b=ra(),selfUrl:y=`http://127.0.0.1:${process.env.PORT||3362}`,apiToken:x=null,removedMarkerFile:E=nM,onRemoved:A=null,onDegraded:$=null,onRecovered:P=null,onRefused:L=null,onConnected:T=null,ingestMode:C=["ws","http","auto"].includes(process.env.BOSTRAT_PLANE_INGEST)?process.env.BOSTRAT_PLANE_INGEST:"auto",deliveryTimeoutMs:j=aK,unackedRetryMs:K=sK,pingMs:M=rK,deadLinkMs:I=Math.round(M*oK),maxInflightEvents:S=uK,httpTimeoutMs:U=dK,stallBackoffMinMs:W=lK,fetchImpl:ie=globalThis.fetch,log:z=console}){if(!e||!t)throw new Error("plane-link: url and token are required");if(typeof o!="function")throw new Error("plane-link: listTracks is required");e=JO(e);let Ge=y.replace(/^http/,"ws"),_e=new Set,Y=B=>{let H=typeof B.latestNodeVersion=="string"?B.latestNodeVersion:null;if(!(!(H&&Pn&&lu(Pn,H))||_e.has(H))){_e.add(H),z.log(`[plane-link] bostrat-node ${H} is available (this node runs ${Pn}) \u2014 ${Yf(b)}`);try{m?.({current:Pn,latest:H,min:B.minNodeVersion??null,installKind:b,required:!!(B.minNodeVersion&&lu(Pn,B.minNodeVersion))})}catch(F){z.error(`[plane-link] update notice failed: ${F?.message||F}`)}}},ne=new Map,Ie=new Map,Pe=Dt.join(hk,"plane-link","cursor.json"),ae=Dt.join(hk,"plane-link","dead-letter.ndjson"),Ae=e.replace(/^ws(s?):\/\//,"http$1://").replace(/\/v1\/node\/?$/,""),be={},Q={},he=new Map,Ue=null,nt=null,rt=0,N=0,se=0,le={},ve=new Set,Ye=Promise.resolve(),Fe="ws",Zt=0,ut=!1,kn=0,Kr=!1,at=qo,Vr=new Set,it=[],xt=null,Lt=null,Ot=!1,Zi=!1,ns=XO,k=null,f=null,v=null,O=null,G=0,ge=0,ye=null,vt=!1,ct=0,zr=!1,Mt=X6(E);if(Mt)if(Mt.tokenPreview===YO(t))zr=!0,im({reason:Mt.reason??"removed",at:Mt.at??null,nodeId:Mt.nodeId??n}),z.error(`[plane-link] this node was REMOVED from the plane (${Mt.reason??"removed"}${Mt.at?` at ${new Date(Mt.at).toISOString()}`:""}) \u2014 not dialing. Re-provision it with a new node token, or delete ${E} to force a dial.`);else try{Mi.unlinkSync(E),z.log("[plane-link] stale removed-marker discarded \u2014 the node token changed")}catch{}function Fh({reason:B="removed",at:H=Date.now(),via:F="ctl"}={}){if(!zr){zr=!0,im({reason:B,at:H,nodeId:n,via:F});try{Mi.mkdirSync(Dt.dirname(E),{recursive:!0}),Mi.writeFileSync(E,JSON.stringify({at:H,reason:B,via:F,nodeId:n,tokenPreview:YO(t)},null,2))}catch(R){z.error(`[plane-link] could not write ${E}: ${R?.message||R}`)}z.error(`[plane-link] the plane REMOVED this node (${B}, via ${F}) \u2014 going dormant: no more dials, ingest or broker calls. Re-provision with a new node token to reconnect; the box and its data are untouched.`);try{A?.({reason:B,at:H,via:F})}catch{}ix({bye:!1})}}async function XP(){try{be=JSON.parse(await cu.readFile(Pe,"utf8"))}catch{be={}}}function X0(){vt=!0,!v&&(v=setTimeout(async()=>{if(v=null,!!vt){vt=!1;try{await cu.mkdir(Dt.dirname(Pe),{recursive:!0}),await cu.writeFile(Pe,JSON.stringify(be))}catch(B){z.error("[plane-link] cursor flush failed:",B?.message||B)}}},nK),v.unref?.())}function ht(B){return!Lt||Lt.readyState!==dk.OPEN?!1:(Lt.send(JSON.stringify(B)),!0)}function Qi(B){let H=Date.now();for(let{trackId:R,event:q}of B){let ce=he.get(q.id);he.set(q.id,{trackId:R,seq:q.seq,event:q,sentAt:H,firstSentAt:ce?.firstSentAt??H,retryAt:H+K,tries:(ce?.tries??0)+1,nacks:ce?.nacks??0})}let F=B.map(({trackId:R,event:q})=>({trackId:R,event:cK(q)}));return Fe==="http"?(rD(F),!0):ht({v:kt,ch:"events",type:"append",events:F})}function ZP(B){let H=null;for(let F of he.values())F.trackId===B&&(H==null||F.seq<H)&&(H=F.seq);return H}function Uh(B){let H=Q[B];if(H==null)return;let F=ZP(B),R=F==null?H:Math.min(H,F-1);R>(be[B]??0)&&(be[B]=R,X0())}function ec(){if(Ue=Date.now(),nt!=null){let B=Date.now()-nt;z.log(`[plane-link] spine sync recovered after ${Math.round(B/1e3)}s degraded (${rt} stall redial(s))`);let H=nt;nt=null,rt=0,N=0,ut=!1,kn=0;try{P?.({since:H,downMs:B})}catch(F){z.error(`[plane-link] onRecovered failed: ${F?.message||F}`)}}}function Hh(B){if(!Array.isArray(B)||!B.length)return;let H=new Set;for(let F of B){let R=he.get(F);R&&(he.delete(F),(Q[R.trackId]??0)<R.seq&&(Q[R.trackId]=R.seq),H.add(R.trackId))}for(let F of H)Uh(F);ec()}function Z0(B,H){se++;let F={at:Date.now(),trackId:B.trackId,seq:B.seq,id:B.event?.id??null,type:B.event?.type??null,reason:H,event:B.event??null};z.error(`[plane-link] DEAD-LETTER ${B.trackId} seq ${B.seq} (${F.type??"?"}): plane rejected it permanently (${H}) \u2014 kept in ${ae}`),Ye=Ye.then(async()=>{await cu.mkdir(Dt.dirname(ae),{recursive:!0}),await cu.appendFile(ae,JSON.stringify(F)+`
705
- `)}).catch(R=>z.error(`[plane-link] dead-letter write failed: ${R?.message||R}`))}function QP(B,H){if(le[B]=(le[B]??0)+1,ve.has(B))return;ve.add(B);let F=iK[B]??"see the plane's tenancy alarm ring (GET /plane/tenancy/alarms)";z.error(`[plane-link] REFUSED by the plane (${B}) on track ${H}: events are being dropped, not stored \u2014 ${F}`);try{L?.({reason:B,trackId:H,count:le[B],hint:F})}catch(R){z.error(`[plane-link] onRefused failed: ${R?.message||R}`)}}function Wh(B,H,F,R=null){if(!Array.isArray(B)||!B.length)return;let q=new Set,ce=Date.now();for(let Te of B){let Se=he.get(Te);Se&&(F?(he.delete(Te),Z0(Se,H),String(H).startsWith(pk)&&QP(String(H).slice(pk.length),Se.trackId),(Q[Se.trackId]??0)<Se.seq&&(Q[Se.trackId]=Se.seq),q.add(Se.trackId)):(Se.nacks++,Se.retryAt=ce+Math.max(1e3,Number(R)||K)))}for(let Te of q)Uh(Te);ec()}function Q0(B=Date.now()){let H=1/0;for(let F of he.values())F.firstSentAt<H&&(H=F.firstSentAt);return H===1/0?0:B-H}function eD(B){if(!I||!B||B!==Lt||!G)return!1;let H=Date.now()-G;if(H<=I)return!1;ge++,z.error(`[plane-link] no frame from the plane for ${Math.round(H/1e3)}s \u2014 link is half-open; terminating and redialing`);try{B.terminate()}catch{}return!0}function ex(){if(!Ot||!he.size)return;let B=Date.now(),H=Q0(B);if(H<j||Ue!=null&&B-Ue<j||Fe==="http"&&ut||N>B)return;rt++;let F=Math.min(W*2**(rt-1),QO);if(nt==null){nt=B-H,z.error(`[plane-link] DEGRADED: no ack or nack for ${Math.round(H/1e3)}s with ${he.size} event(s) in flight (${Fe} door) \u2014 the plane is not answering appends`);try{$?.({since:nt,unacked:he.size,oldestAgeMs:H,mode:Fe})}catch(R){z.error(`[plane-link] onDegraded failed: ${R?.message||R}`)}}if(Fe==="http"){ut=!0,kn=B+F,z.error(`[plane-link] ingest circuit OPEN (stall #${rt}); probing /v1/ingest/health in ${Math.round(F/1e3)}s`);return}N=B+F,z.error(`[plane-link] closing the link and redialing in ${Math.round(F/1e3)}s (stall redial #${rt})`);try{Lt?.terminate()}catch{}}function qh(){if(!Ot)return;let B=Date.now();if(Fe==="http"&&ut)return;let H=[...he.values()].filter(R=>R.event&&R.retryAt<=B&&!(Fe==="http"&&Vr.has(R.trackId)));if(!H.length)return;H.sort((R,q)=>R.trackId===q.trackId?R.seq-q.seq:R.trackId<q.trackId?-1:1),z.log(`[plane-link] re-sending ${H.length} unacked event(s) the plane never confirmed`);let F=Fe==="http"?at:qo;if(Fe==="http"){let R=new Map;for(let q of H)(R.get(q.trackId)??R.set(q.trackId,[]).get(q.trackId)).push(q);for(let[,q]of R){if(Zt>=fk)return;Qi(q.slice(0,F).map(ce=>({trackId:ce.trackId,event:ce.event})))}return}for(let R=0;R<H.length;R+=F){let q=H.slice(R,R+F).map(ce=>({trackId:ce.trackId,event:ce.event}));if(!Qi(q))return}}async function tD(B=null){for(;;){if(!Ot)return!1;let H=he.size<S,F=Fe!=="http"||Zt<fk&&!ut&&(!B||!Vr.has(B));if(H&&F)return!0;await new Promise(R=>setTimeout(R,100))}}function Gh(){if(xt=null,!Ot||!it.length)return;let B=it;if(it=[],Fe!=="http"){for(let F=0;F<B.length;F+=qo)Qi(B.slice(F,F+qo));return}let H=new Map;for(let F of B)(H.get(F.trackId)??H.set(F.trackId,[]).get(F.trackId)).push(F);for(let[F,R]of H){if(Vr.has(F)||Zt>=fk||ut){it.push(...R);continue}for(let q=0;q<R.length;q+=at)Qi(R.slice(q,q+at))}it.length&&!xt&&(xt=setTimeout(Gh,eM),xt.unref?.())}let nD=B=>{let H=new Map;for(let{trackId:F,event:R}of B)(H.get(F)??H.set(F,[]).get(F)).push(R);return[...H].map(([F,R])=>({trackId:F,events:R}))},rs=(B,H,F,{progress:R})=>{let q=Date.now();for(let{event:ce}of B){let Te=he.get(ce.id);Te&&(Te.nacks++,Te.retryAt=q+Math.max(1e3,F||K))}R&&ec()};async function rD(B){let H=new Set(B.map(F=>F.trackId));for(let F of H)Vr.add(F);Zt++;try{let F=await ie(`${Ae}/v1/ingest`,{method:"POST",headers:{authorization:`Bearer ${t}`,"content-type":"application/json"},body:JSON.stringify({node:n,batches:nD(B)}),signal:AbortSignal.timeout(U)}),R=(Number(F.headers.get("retry-after"))||0)*1e3;if(F.status===200){let q=await F.json();at=qo;for(let Se of q.results??[]){Hh(Se.acked??[]);let dt=(jn,jt)=>{let qu=new Map;for(let os of jn??[])(qu.get(os.reason)??qu.set(os.reason,[]).get(os.reason)).push(os.id);for(let[os,cx]of qu)Wh(cx,os,jt,q.retryAfterMs??null)};dt(Se.rejected,!0),dt(Se.deferred,!1)}let ce=new Set,Te=new Map;for(let Se of Array.isArray(q.refused)?q.refused:[])!Se||typeof Se.id!="string"||(ce.add(Se.id),(Te.get(Se.reason)??Te.set(Se.reason,[]).get(Se.reason)).push(Se.id));for(let[Se,dt]of Te)Wh(dt,`${pk}${Se}`,!0);Hh((q.discarded??[]).filter(Se=>!ce.has(Se))),ec();return}if(F.status===429){rs(B,"overloaded",R||5e3,{progress:!0});return}if(F.status===413&&B.length>1){at=Math.max(1,Math.floor(B.length/2)),z.error(`[plane-link] ingest request too large (${B.length} events) \u2014 halving batches to ${at}`),rs(B,"too_large",1e3,{progress:!0});return}if(F.status===413){let q=he.get(B[0].event.id);q&&(he.delete(q.event.id),Z0(q,"too_large"),(Q[q.trackId]??0)<q.seq&&(Q[q.trackId]=q.seq),Uh(q.trackId)),ec();return}if(F.status===410){Fh({reason:"removed",via:"410"}),rs(B,"http_410",6e4,{progress:!1});return}if(F.status===401||F.status===403){let{tripped:q,holdMs:ce}=ya();if(q&&z.error(`[plane-link] holding every plane call for ${Math.round(ce/6e4)} min \u2014 the ingest door refused this node's token three times in a row`),Date.now()-ct>=tM){ct=Date.now();let Te="";try{Te=(await F.json())?.error??""}catch{}z.error(`[plane-link] plane refused ingest (HTTP ${F.status}${Te?`: ${Te}`:""}) \u2014 events are held locally and retried; check this node's token/binding`)}rs(B,`http_${F.status}`,Math.max(6e4,uc()),{progress:!1});return}if(F.status===400){z.error(`[plane-link] plane rejected an ingest request as malformed (400) \u2014 holding ${B.length} event(s) for retry; this is a bug, not data`),rs(B,"http_400",6e4,{progress:!1});return}rs(B,`http_${F.status}`,R||5e3,{progress:!1})}catch(F){let R=F?.name==="TimeoutError"||F?.name==="AbortError";R&&B.length>1&&(at=Math.max(1,Math.floor(B.length/2)),z.error(`[plane-link] ingest request of ${B.length} event(s) outlived its ${U} ms deadline \u2014 halving batches to ${at}`)),rs(B,R?"timeout":"network",5e3,{progress:!1})}finally{Zt--;for(let F of H)Vr.delete(F)}}async function oD(){if(Fe!=="http"||!ut||!Ot||Kr)return;let B=Date.now();if(!(kn>B||ba(B))){Kr=!0;try{let H=await ie(`${Ae}/v1/ingest/health`,{headers:{authorization:`Bearer ${t}`},signal:AbortSignal.timeout(U)});if(!H.ok)throw new Error(`HTTP ${H.status}`);z.log("[plane-link] ingest door answering \u2014 closing the circuit and re-sending"),ut=!1,kn=0,N=Date.now()+U+K+1e3;for(let F of he.values())F.retryAt=Math.min(F.retryAt,Date.now());qh()}catch(H){rt++;let F=Math.min(W*2**(rt-1),QO);kn=Date.now()+F,z.error(`[plane-link] ingest door still not answering (${H?.message||H}); next probe in ${Math.round(F/1e3)}s`)}finally{Kr=!1}}}function tx(){let B=Date.now();return{mode:Fe,unacked:he.size,oldestUnackedAgeMs:Q0(B),lastProgressAt:Ue,degradedSince:nt,stallRedials:rt,deadLettered:se,http:Fe==="http"?{inFlight:Zt,circuitOpen:ut,nextProbeInMs:ut?Math.max(0,kn-B):0,batchCap:at}:null}}async function nx(){if(!c)return;let B;try{B=await c()}catch(F){z.error("[plane-link] metrics sample failed:",F?.message||F);return}let H=null;try{H=l?.()??null}catch{}B&&ht({v:kt,ch:"ctl",type:"metrics",metrics:{...B,planeLink:tx(),...H?{delivery:H}:{}}})}function sD(){c&&(ye&&clearInterval(ye),nx(),ye=setInterval(nx,p),ye.unref?.())}async function aD(){let B;try{B=await o()}catch(H){z.error("[plane-link] backfill listTracks failed:",H?.message||H);return}ht({v:kt,ch:"ctl",type:"tracks",ids:B.filter(H=>!H.transferredTo).map(H=>H.id).filter(H=>typeof H=="string")});for(let H of B)if(!Ot||!await rx(H))return}async function rx(B){let H;try{H=await J(B)}catch{return!0}let F=be[B.id]??0,R=H.filter(ce=>ce.seq>F&&typeof ce.id=="string"),q=Fe==="http"?at:qo;for(let ce=0;ce<R.length;ce+=q){if(!await tD(B.id))return!1;let Te=R.slice(ce,ce+Math.min(q,Fe==="http"?at:qo)).map(Se=>({trackId:B.id,event:Se}));if(!Qi(Te))return!1}return!0}let Kh=new Map;async function ox(B,H){if(Kh.get(B)===H)return!1;Kh.set(B,H);let F=null;try{F=(await o()).find(Te=>Te?.id===B)??null}catch{return!1}if(!F)return!1;let R;try{R=await J(F)}catch{return!1}let q=[...R].reverse().find(Te=>(Te?.type==="track.transferred"||Te?.type==="track.recovered")&&Te.payload?.toNode===n);if(!q||!Number.isFinite(q.seq))return!1;let ce=q.seq-1;return(be[B]??0)>ce&&(be[B]=ce,X0()),(Q[B]??0)>ce&&(Q[B]=ce),z.log(`[plane-link] re-sending ${B}'s move-commit (seq ${q.seq}, ${q.type}) \u2014 the plane's move record predates this node's adoption`),Ot?rx(F):!1}function sx(B){!Ot||!B?.trackId||typeof B.id!="string"||(it.push({trackId:B.trackId,event:B}),xt||(xt=setTimeout(Gh,eM),xt.unref?.()))}let tc=new Map;async function iD(B){let{reqId:H,method:F,path:R,headers:q={},body:ce}=B,Te=Object.fromEntries(Object.entries(q).filter(([,dt])=>dt!=null)),Se=new AbortController;tc.set(H,Se);try{if(B.host){await cD(B,Te,Se);return}x&&(Te["x-bostrat-token"]=x);let dt=await fetch(y+R,{method:F,headers:Te,body:ce?Buffer.from(ce,"base64"):void 0,signal:Se.signal}),jn=Object.fromEntries(dt.headers);for(let jt of["connection","keep-alive","transfer-encoding","upgrade","content-encoding","content-length"])delete jn[jt];if(jn["content-type"]||(jn["content-type"]="application/octet-stream"),ht({v:kt,ch:"control",type:"http_head",reqId:H,status:dt.status,headers:jn}),dt.body){for await(let jt of dt.body)if(!ht({v:kt,ch:"control",type:"http_data",reqId:H,data:Buffer.from(jt).toString("base64")}))break}ht({v:kt,ch:"control",type:"http_end",reqId:H,error:null})}finally{tc.delete(H)}}function cD(B,H,F){let{reqId:R,method:q,path:ce,body:Te}=B,Se=new URL(y);return new Promise(dt=>{let jn=J6.request({host:Se.hostname,port:Se.port,method:q,path:ce,headers:{...H,host:B.host},signal:F.signal},jt=>{let{connection:qu,"keep-alive":os,"transfer-encoding":cx,upgrade:lY,...lD}=jt.headers;ht({v:kt,ch:"control",type:"http_head",reqId:R,status:jt.statusCode||502,headers:lD}),jt.on("data",uD=>{ht({v:kt,ch:"control",type:"http_data",reqId:R,data:Buffer.from(uD).toString("base64")})||jt.destroy()}),jt.on("end",()=>{ht({v:kt,ch:"control",type:"http_end",reqId:R,error:null}),dt()}),jt.on("error",()=>{ht({v:kt,ch:"control",type:"http_end",reqId:R,error:"view upstream error"}),dt()})});jn.on("error",jt=>{ht({v:kt,ch:"control",type:"http_end",reqId:R,error:jt?.message||"view request failed"}),dt()}),Te&&jn.write(Buffer.from(Te,"base64")),jn.end()})}function ax(){if(Zi||zr)return;Lt=new dk(e,{headers:{authorization:`Bearer ${t}`}});let B=Lt;G=0,B.on("ping",()=>{G=Date.now()}),B.on("pong",()=>{G=Date.now()}),Lt.on("open",async()=>{let F=null;try{F=await s?.()||null}catch{F=null}ht({v:kt,ch:"ctl",type:"hello",nodeId:n,name:r,platform:process.platform,version:Pn,installKind:b,...typeof g=="function"?{updatePolicy:g()}:g?{updatePolicy:g}:{},providers:Z6(),...F?{agents:F}:{}})}),Lt.on("message",F=>{G=Date.now();let R;try{R=JSON.parse(F)}catch{return}if(R.ch==="ctl"&&R.type==="hello_ok"){Kh.clear(),Ot=!0,ns=XO,k=null,Ox(),z.log(`[plane-link] connected to plane as ${n}`);try{T?.()}catch{}if(typeof R.hashKey=="string"&&R.hashKey)try{u?.(R.hashKey)}catch{}try{d?.(typeof R.viewBase=="string"&&R.viewBase?R.viewBase:null)}catch{}R.minNodeVersion&&Pn&&lu(Pn,R.minNodeVersion)&&z.error(`[plane-link] this node is bostrat-node ${Pn}; the plane asks for \u2265${R.minNodeVersion} \u2014 update with: ${Yf(b)}`);try{w?.(typeof R.updatePolicy=="string"?R.updatePolicy:null)}catch{}Y(R);let q=R.ingest==="http";Fe=C==="ws"?"ws":C==="http"||q?"http":"ws",C==="http"&&!q&&z.error("[plane-link] BOSTRAT_PLANE_INGEST=http but this plane offers no HTTPS ingest door \u2014 events will fail until it does"),Fe==="http"&&z.log("[plane-link] spine rides the HTTPS ingest door"),ut=!1,kn=0,at=qo,O&&clearInterval(O),G=Date.now(),O=setInterval(()=>{eD(B)||(ht({v:kt,ch:"ctl",type:"ping"}),ex(),oD().catch(()=>{}),qh(),it.length&&!xt&&Gh())},M),O.unref?.(),sD(),aD().catch(ce=>z.error("[plane-link] backfill failed:",ce?.message||ce));return}if(R.ch==="ctl"&&R.type==="hello_refused"){let q=typeof R.minNodeVersion=="string"?R.minNodeVersion:null,ce=typeof R.latestNodeVersion=="string"?R.latestNodeVersion:null;z.error(`[plane-link] plane REFUSED this node: bostrat-node ${Pn??"?"} is below its minimum ${q??"?"} \u2014 ${R.fix||Yf(b)}`),ns=ZO,k=0;try{h?.({current:Pn,min:q,latest:ce,fix:R.fix||Yf(b),installKind:b})}catch(Te){z.error(`[plane-link] refusal handler failed: ${Te?.message||Te}`)}return}if(R.ch==="ctl"&&R.type==="removed"){ht({v:kt,ch:"ctl",type:"removed_ack",nodeId:n}),Fh({reason:typeof R.reason=="string"?R.reason:"removed",at:Number(R.at)||Date.now(),via:"ctl"});return}if(R.ch==="ctl"&&R.type==="update_available"){Y(R);return}if(R.ch==="ctl"&&R.type==="update_policy"){try{w?.(typeof R.mode=="string"?R.mode:null)}catch{}return}if(R.ch==="ctl"&&R.type==="usage_caps"){yp(R.caps??{},{source:"plane",updatedAt:R.updatedAt??Date.now()}).then(q=>z.log(`[plane-link] spend caps ${Object.keys(q.caps).length?`updated (${Object.keys(q.caps).join(", ")})`:"cleared"} from plane`)).catch(q=>z.error("[plane-link] spend-caps push rejected:",q?.message||q));return}if(R.ch==="ctl"&&R.type==="transferred"&&Array.isArray(R.tracks)){Promise.resolve().then(()=>a?.(R.tracks)).then(async q=>{for(let ce of Array.isArray(q)?q:[])ce?.stale&&ce.id&&await ox(ce.id,ce.since??null)}).catch(q=>z.error("[plane-link] transfer notice failed:",q?.message||q));return}if(R.ch==="ctl"&&R.type==="moves"&&Array.isArray(R.tracks)){Promise.resolve().then(()=>i?.(R.tracks)).then(async q=>{for(let ce of Array.isArray(q)?q:[])ce?.stale&&ce.id&&await ox(ce.id,ce.since??null)}).catch(q=>z.error("[plane-link] move-record reconcile failed:",q?.message||q));return}if(R.ch==="events"&&R.type==="ack"&&Array.isArray(R.ids)){Hh(R.ids);return}if(R.ch==="events"&&R.type==="nack"&&Array.isArray(R.ids)){Wh(R.ids,R.reason,R.permanent===!0,R.retryAfterMs??null);return}if(R.ch==="control"&&R.type==="http_open"){iD(R).catch(q=>ht({v:kt,ch:"control",type:"http_end",reqId:R.reqId,error:q?.message||"tunnel error"}));return}if(R.ch==="control"&&R.type==="http_cancel"){tc.get(R.reqId)?.abort();return}if(R.ch==="attach"&&R.type==="open"){let q=new dk(Ge+R.path,Array.isArray(R.protocols)?R.protocols:[],R.host?{headers:{host:R.host}}:void 0);ne.set(R.streamId,q),Ie.set(R.streamId,[]),q.on("open",()=>{let Te=Ie.get(R.streamId)||[];Ie.delete(R.streamId);for(let{buf:Se,bin:dt}of Te)q.send(Se,{binary:dt})}),q.on("message",(Te,Se)=>{let dt=Se?Te:Buffer.from(String(Te));ht({v:kt,ch:"attach",type:"data",streamId:R.streamId,data:dt.toString("base64"),...Se?{bin:!0}:{}})});let ce=()=>{Ie.delete(R.streamId),ne.delete(R.streamId)&&ht({v:kt,ch:"attach",type:"close",streamId:R.streamId})};q.on("close",ce),q.on("error",ce);return}if(R.ch==="attach"&&R.type==="data"){let q=ne.get(R.streamId);if(!q)return;let ce=Buffer.from(R.data,"base64"),Te=R.bin===!0,Se=Ie.get(R.streamId);Se?Se.push({buf:ce,bin:Te}):q.send(ce,{binary:Te});return}if(R.ch==="attach"&&R.type==="close"){let q=ne.get(R.streamId);ne.delete(R.streamId),Ie.delete(R.streamId),q?.close();return}});let H=()=>{Ot&&z.log("[plane-link] disconnected from plane"),Ot=!1,O&&(clearInterval(O),O=null),ye&&(clearInterval(ye),ye=null),he.clear(),Q={},it=[],xt&&(clearTimeout(xt),xt=null),Vr.clear();for(let q of ne.values())q.close();ne.clear(),Ie.clear();for(let q of tc.values())q.abort();if(tc.clear(),Zi||f)return;k==null&&(k=Date.now());let F=Date.now()-k<Q6,R=Math.max(F?eK+Math.random()*tK:ns,N-Date.now(),uc());f=setTimeout(()=>{f=null,ax()},R),f.unref?.(),F||(ns=Math.min(ns*2,ZO))};Lt.on("close",H),Lt.on("error",F=>{let R=/Unexpected server response: (\d+)/.exec(F?.message||"")?.[1];if(R==="410"){Fh({reason:"removed",via:"410"});return}if(R==="401"||R==="403"){let{tripped:q,holdMs:ce}=ya();q?z.error(`[plane-link] holding every plane call for ${Math.round(ce/6e4)} min \u2014 three credential refusals in a row (HTTP ${R}) mean the token is revoked or unknown, not that the plane is down; mint a new node token and update this node's BOSTRAT_PLANE_TOKEN. Next dial in ${Math.round(ce/6e4)} min.`):Date.now()-ct>=tM&&(ct=Date.now(),z.error(`[plane-link] plane refused this node's credentials (HTTP ${R}) \u2014 the token was revoked or is unknown to the plane; mint a new node token and update this node's BOSTRAT_PLANE_TOKEN (still retrying)`))}H()})}et.on("event",sx),XP().then(ax);function ix({bye:B=!0}={}){Zi=!0,et.off("event",sx),f&&clearTimeout(f),v&&clearTimeout(v),O&&clearInterval(O),ye&&clearInterval(ye),xt&&clearTimeout(xt),B&&ht({v:kt,ch:"ctl",type:"bye",reason:"shutdown"}),Lt?.close()}return{stop:()=>ix(),status:()=>({connected:Ot,nodeId:n,cursor:{...be},inflight:he.size,...tx(),auth:Mx(),dormant:zr,removed:nd(),deadLinkMs:I,deadLinkRedials:ge,refused:{...le}}),_tick:()=>{ex(),qh()}}}is();var Zf=(()=>{try{return mK(import.meta.url)("../package.json").version||null}catch{return null}})(),wK=process.env.BOSTRAT_STATE_DIR||St.join(process.env.HOME||fK.tmpdir(),".bostrat"),cM=St.join(wK,"self-update"),Qf=St.join(cM,"status.json"),gK=1440*6e4,yK=6e4,sM=60,aM=15,eh=3,uu=new Set(["npm-global","git-checkout"]);function lM({kind:e=ra(),env:t=process.env}={}){let n=String(t.BOSTRAT_UPDATE_POLICY||"").trim();return["auto","prompt","off"].includes(n)?n:uu.has(e)?e==="git-checkout"||bK(t)?"auto":"prompt":"off"}function bK(e=process.env){return!!(e.INVOCATION_ID||e.XPC_SERVICE_NAME&&e.XPC_SERVICE_NAME!=="0")}var Yt=e=>`'${String(e).replace(/'/g,"'\\''")}'`;function kK({kind:e,to:t,from:n=Zf,statusFile:r=Qf,logFile:o=St.join(cM,"last.log"),port:s=Number(process.env.PORT)||3362,npmPrefix:a=null,serviceName:i=process.platform==="darwin"?"com.bostrat.node":"bostrat-node.service",uid:c=typeof process.getuid=="function"?process.getuid():0,liveDir:l=process.env.BOSTRAT_LIVE_CHECKOUT||St.resolve(St.dirname(new URL(import.meta.url).pathname),"..",".."),startedAt:u=Date.now(),attempts:d=1}={}){if(!uu.has(e))throw new Error(`self-update: install kind "${e}" is not actionable here`);if(!/^\d+\.\d+\.\d+$/.test(String(t)))throw new Error(`self-update: bad target version "${t}"`);if(n&&!/^\d+\.\d+\.\d+$/.test(String(n)))throw new Error(`self-update: bad current version "${n}"`);let p=(b,y="")=>`write_status ${Yt(b)} ${y}`,m=process.platform==="darwin"?`launchctl kickstart -k gui/${c}/${i}`:`systemctl --user restart ${Yt(i)}`,w=`
704
+ `);f6=new Set(["claude","codex","cursor"]);Xl=new Set,h6=e=>Xl.has(e);m6=9e4;pO={merged:"merged",closed:"closed on GitHub WITHOUT merging",lost:"no longer found on GitHub (deleted, or its repo left the grant)"};lb=new Map;y6=6e4,ub=new Map;gb=120;k6=10*6e4,Hl=new Map;Xs=new Map,Ri=e=>Xs.get(e)||(Kt?pe(Kt,e)?.handoff:null)||null;Zb=6e4,Nn=(e,t,n=15e3)=>$f("git",["-C",e,...t],{timeout:n,maxBuffer:8*1024*1024}),If=new Map,Qb=e=>If.get(e)||null;_6=/^[A-Za-z0-9][A-Za-z0-9._/-]{0,200}$/;Sf=new Map;R6=Number(process.env.BOSTRAT_SUBTASK_TIMEOUT_MS)||18e5,O6=Number(process.env.BOSTRAT_SUBTASK_POLL_MS)||3e3,Ti=X.join(sr,"worktrees"),bi=[Kl,Af],Vt=new Map,M6=e=>Vt.get(e)||(Kt?Kt.tracks.map(t=>t.subtasks?.[e]).find(Boolean):null)||null,na=e=>{let t=new Map([...Vt.values()].filter(r=>r.trackId===e).map(r=>[r.id,r])),n=Kt?pe(Kt,e):null;if(n?.subtasks)for(let[r,o]of Object.entries(n.subtasks))t.has(r)||t.set(r,o);return[...t.values()].sort((r,o)=>r.startedAt-o.startedAt)},Gf=e=>({id:e.id,trackId:e.trackId,trackName:e.trackName,agent:e.agent,task:e.task,skipPermissions:e.skipPermissions,reason:e.reason||null,step:e.step,failedStep:e.failedStep||null,box:e.box,branch:e.branch,base:e.base,repos:e.repos||null,dir:e.dir,stat:e.stat,files:e.files||null,conflicts:e.conflicts||[],applied:e.applied,error:e.error,canceled:e.canceled,startedAt:e.startedAt,finishedAt:e.finishedAt});su=e=>UO(e.trackId,e.id,Gf(e));Kf=e=>e.trim().replace(/\s+/g,"-").replace(/[^A-Za-z0-9._-]/g,"").toLowerCase()||"track",Ql=class extends Error{}});mt();import Ce from"node:path";import At from"node:fs";import LJ from"node:readline";import{fileURLToPath as jJ}from"node:url";import Xt from"express";import LP from"node:http";import FJ from"node:https";import zi from"node:os";import{randomUUID as UJ}from"node:crypto";import{WebSocketServer as HJ}from"ws";mt();import zB from"node-pty";async function Jv(e,t,n={}){if(!We(t)){$d(e,`invalid session name: ${t}`),e.close(1008,"invalid session name");return}if(!await so()){$d(e,`host tmux server not running on ${gt}`),e.close(1011,"tmux server unavailable");return}if(!await Ee(t)){let a=!1;if(typeof n.revive=="function"&&(Rd(e,{type:"notice",message:"Resuming the lead box\u2026"}),a=await n.revive().catch(()=>!1)),!a||!await Ee(t)){$d(e,`session "${t}" not found`),e.close(1008,"session not found");return}if(e.readyState!==e.OPEN)return}let r=zv(n.cols,120,Yv),o=zv(n.rows,32,Xv),s;try{s=zB.spawn(re,["-S",gt,"attach-session","-d","-t",t],{name:"xterm-256color",cols:r,rows:o,cwd:process.env.HOME||"/",env:{...process.env,TERM:"xterm-256color"}})}catch(a){$d(e,`failed to spawn tmux attach: ${a.message}`),e.close(1011,"spawn failed");return}s.onData(a=>{e.readyState===e.OPEN&&Rd(e,{type:"data",data:a})}),s.onExit(({exitCode:a,signal:i})=>{e.readyState===e.OPEN&&(Rd(e,{type:"exit",code:a??null,signal:i??null}),e.close(1e3,"tmux exited"))}),e.on("message",a=>{let i;try{i=JSON.parse(a.toString())}catch{return}if(!(!i||typeof i!="object")){if(i.type==="data"&&typeof i.data=="string")s.write(i.data);else if(i.type==="resize"&&ZB(i.cols,i.rows))try{s.resize(Math.min(500,i.cols|0),Math.min(500,i.rows|0))}catch{}}}),e.on("close",()=>{try{s.kill()}catch{}XB(t)})}var JB=6,YB=250;async function XB(e,t=JB,n=YB){for(let r=0;r<t;r++){if(await hs(e).catch(()=>!0))return!0;await new Promise(o=>setTimeout(o,n))}return!1}var Yv=20,Xv=6;function ZB(e,t){return Number.isFinite(Number(e))&&Number.isFinite(Number(t))&&Number(e)>=Yv&&Number(t)>=Xv}function zv(e,t,n){let r=Number(e);return!Number.isFinite(r)||r<n?t:Math.min(500,r|0)}function Rd(e,t){try{e.send(JSON.stringify(t))}catch{}}function $d(e,t){Rd(e,{type:"error",message:t})}function Zv(e){let t=typeof e=="string"&&e?e:"/",n=t.indexOf("?"),r=n===-1?t:t.slice(0,n),o=n===-1?"":t.slice(n+1),s=r.match(/^\/api\/attach\/([^/]+)$/);if(!s)return{ok:!1,status:404};let a;try{a=decodeURIComponent(s[1])}catch{return{ok:!1,status:400}}let i=new URLSearchParams(o);return{ok:!0,sessionName:a,cols:Number(i.get("cols"))||void 0,rows:Number(i.get("rows"))||void 0}}An();Bd();Lw();Or();import{createRequire as WJ}from"node:module";var H6=e=>!!e&&!e.finishedAt&&!e.canceled&&!e.error;function lk({tracks:e=[],views:t=[],queuedOf:n=()=>[],jobsOf:r=()=>[],prPendingOf:o=()=>[]}={}){let s=[];for(let a of e)!a||a.archivedAt&&!a.archiving||a.transferredTo||(a.working&&s.push(`working:${a.id}`),a.prompted&&s.push(`prompted:${a.id}`),(n(a.id)??[]).length&&s.push(`queued:${a.id}`),(a.boxes||[]).some(i=>i?.role==="subtask"&&i?.state==="live")&&s.push(`subtask:${a.id}`),(r(a.id)??[]).length&&s.push(`job:${a.id}`),Object.values(a.subtasks||{}).some(H6)&&s.push(`merge-back:${a.id}`),(o(a.id)??[]).length&&s.push(`pr:${a.id}`));return t.some(a=>a?.state==="live"||a?.state==="starting")&&s.push("views"),{busy:s.length>0,reasons:s}}Qy();ke();Nl();zn();Yp();pn();var zf=60*6e4,W6=1440*6e4,q6=new Set(["merged","closed","lost"]),au=(e,t,n)=>Number.isFinite(Number(e))&&n-Number(e)<=t;function G6({trackId:e,shipPending:t=null,links:n=[],observers:r=0,now:o=Date.now()}={}){let s=[];t&&Number.isFinite(Number(t.ts))&&o-Number(t.ts)<=Sy&&s.push("ship"),r>0&&s.push("create-net");for(let a of n||[]){if(!a||q6.has(a.state))continue;let i=[a.ciFix,a.reconcile,a.ciFixAwait,a.reconcileAwait];if(!(a.trackId===e||i.some(d=>d?.trackId===e)))continue;let l=a.number??"?";a.ciFix&&au(a.ciFix.delegatedAt,zf,o)&&s.push(`ci-fix#${l}`),a.reconcile&&au(a.reconcile.delegatedAt,zf,o)&&s.push(`reconcile#${l}`),a.ciFixAwait&&au(a.ciFixAwait.since,zf,o)&&s.push(`ci-fix-await#${l}`),a.reconcileAwait&&au(a.reconcileAwait.since,zf,o)&&s.push(`reconcile-await#${l}`);let u=a.autoMerge?.armedAt??a.armedAt??null;a.trackId===e&&(a.autoMerge||a.armedAt)&&au(u,W6,o)&&s.push(`auto-merge#${l}`)}return s}var Jf=new Map;et.on("event",e=>{e?.trackId&&Jf.delete(e.trackId)});async function K6(e){if(Jf.has(e.id))return Jf.get(e.id);let t=await J(e).catch(()=>[]),n=pi(t,-1/0);return Jf.set(e.id,n),n}async function VO(e,{now:t=Date.now()}={}){let n=new Map,r=await In().catch(()=>[]);for(let o of e||[]){if(!o||He(o))continue;let s=G6({trackId:o.id,shipPending:await K6(o),links:r,observers:gI(o.id),now:t});s.length&&n.set(o.id,s)}return n}gl();import iM from"node:fs";import Go from"node:fs/promises";import fK from"node:os";import St from"node:path";import{spawn as hK}from"node:child_process";import{createRequire as mK}from"node:module";ke();bp();import Mi from"node:fs";import cu from"node:fs/promises";import J6 from"node:http";import Dt from"node:path";import Xf from"node:os";import{createRequire as Y6}from"node:module";import dk from"ws";import V6 from"node:path";import z6 from"node:os";var iu=process.env.BOSTRAT_STATE_DIR||V6.join(process.env.HOME||z6.tmpdir(),".bostrat");function uk(e=process.env){let t=(e.BOSTRAT_HOST||"").trim();if(t!=="all")return t||(e.BOSTRAT_PLANE_URL?"127.0.0.1":void 0)}function zO(e=process.env){if(!e.BOSTRAT_PLANE_URL)return null;let t=uk(e);return t==="127.0.0.1"||t==="::1"||t==="localhost"?null:{host:t}}function JO(e){let t=String(e||"").trim();if(!t)return"";let n=/^[a-z][a-z0-9+.-]*:\/\//i.test(t)?t:`wss://${t}`,r;try{r=new URL(n)}catch{return t}let o={"https:":"wss:","http:":"ws:","wss:":"wss:","ws:":"ws:"}[r.protocol];return o?(r.protocol=o,(r.pathname===""||r.pathname==="/")&&(r.pathname="/v1/node"),r.toString()):t}cm();var Pn=(()=>{try{return Y6(import.meta.url)("../package.json").version||null}catch{return null}})(),hk=process.env.BOSTRAT_STATE_DIR||Dt.join(process.env.HOME||Xf.tmpdir(),".bostrat"),nM=Dt.join(hk,"plane-link","removed.json");function YO(e){return typeof e!="string"||e.length<8?"\u2022\u2022\u2022\u2022":`${e.slice(0,6)}\u2026${e.slice(-4)}`}function X6(e=nM){try{let t=JSON.parse(Mi.readFileSync(e,"utf8"));return t&&typeof t=="object"?t:null}catch{return null}}function ra({env:e=process.env,pkgDir:t=Dt.resolve(Dt.dirname(new URL(import.meta.url).pathname),".."),exists:n=Mi.existsSync}={}){let r=String(e.BOSTRAT_INSTALL_KIND||"").trim();return["container","npm-global","git-checkout","dev"].includes(r)?r:/\/lib\/node_modules\/bostrat-node(?:\/|$)/.test(t.replace(/\\/g,"/"))?"npm-global":n(Dt.join(t,"..",".git"))?"git-checkout":"dev"}function lu(e,t){let n=String(e).split(".").map(Number),r=String(t).split(".").map(Number);if(n.some(Number.isNaN)||r.some(Number.isNaN))return!1;for(let o=0;o<Math.max(n.length,r.length);o++){let s=(n[o]||0)-(r[o]||0);if(s)return s<0}return!1}function Yf(e){switch(e){case"npm-global":return"npm install -g bostrat-node && restart the bostrat-node service";case"git-checkout":return"scripts/deploy-pi.sh (or The Bakery \u2192 Deploy to Pi \u2192 bostrat)";case"container":return"Links \u2192 Fly \u2192 Update (or the plane's auto-update while the node sleeps)";default:return"update this node's bostrat-node checkout/install"}}function Z6({home:e=process.env.HOME||Xf.homedir(),env:t=process.env}={}){let n=r=>{try{return Mi.statSync(r),!0}catch{return!1}};return{claude:n(Dt.join(e,".claude",".credentials.json")),codex:n(Dt.join(t.CODEX_HOME||Dt.join(e,".codex"),"auth.json")),cursor:n(Dt.join(t.XDG_CONFIG_HOME||Dt.join(e,".config"),"cursor","auth.json"))}}var kt=1,XO=1e3,ZO=3e4,Q6=6e4,eK=1500,tK=500,qo=100,nK=2e3,rK=25e3,oK=2.5,sK=6e4,rM=(e,t)=>{let n=Number(e);return Number.isFinite(n)&&n>0?n:t},aK=rM(process.env.BOSTRAT_PLANE_DELIVERY_TIMEOUT_MS,18e4),pk="refused:",iK={forgedUserId:"this node's events carry a userId the plane's token does not own \u2014 remove BOSTRAT_OWNER from node.env and the shell environment, then restart the node (current releases never stamp one)",foreignTrack:"the Track belongs to another user's node \u2014 this node must not append to it",squattedTrack:"the Track id is already claimed by another user \u2014 a local Track collided with theirs",transferredAway:"the Track moved to another node \u2014 this copy is stale; it should be demoted, not resumed",slugHijack:"a View slug belongs to another owner \u2014 pick a different slug"},cK=e=>{if(!e||e.userId===void 0)return e;let{userId:t,...n}=e;return n},lK=3e4,QO=10*6e4,uK=400,eM=250,dK=rM(process.env.BOSTRAT_PLANE_INGEST_TIMEOUT_MS,1e4),fk=4,pK=6e4,tM=6e4;function oM({url:e,token:t,nodeId:n=Xf.hostname(),name:r=Xf.hostname(),listTracks:o,detectAgents:s=null,onTracksTransferred:a=null,onTracksMoves:i=null,sampleMetrics:c=null,deliverySample:l=null,onHashKey:u=null,onViewBase:d=null,metricsMs:p=pK,onUpdateAvailable:m=null,onUpdatePolicy:w=null,onHelloRefused:h=null,updatePolicy:g=null,installKind:b=ra(),selfUrl:y=`http://127.0.0.1:${process.env.PORT||3362}`,apiToken:x=null,removedMarkerFile:E=nM,onRemoved:A=null,onDegraded:$=null,onRecovered:P=null,onRefused:L=null,onConnected:T=null,ingestMode:C=["ws","http","auto"].includes(process.env.BOSTRAT_PLANE_INGEST)?process.env.BOSTRAT_PLANE_INGEST:"auto",deliveryTimeoutMs:j=aK,unackedRetryMs:K=sK,pingMs:M=rK,deadLinkMs:I=Math.round(M*oK),maxInflightEvents:S=uK,httpTimeoutMs:U=dK,stallBackoffMinMs:W=lK,fetchImpl:ie=globalThis.fetch,log:z=console}){if(!e||!t)throw new Error("plane-link: url and token are required");if(typeof o!="function")throw new Error("plane-link: listTracks is required");e=JO(e);let Ge=y.replace(/^http/,"ws"),_e=new Set,Y=B=>{let H=typeof B.latestNodeVersion=="string"?B.latestNodeVersion:null;if(!(!(H&&Pn&&lu(Pn,H))||_e.has(H))){_e.add(H),z.log(`[plane-link] bostrat-node ${H} is available (this node runs ${Pn}) \u2014 ${Yf(b)}`);try{m?.({current:Pn,latest:H,min:B.minNodeVersion??null,installKind:b,required:!!(B.minNodeVersion&&lu(Pn,B.minNodeVersion))})}catch(F){z.error(`[plane-link] update notice failed: ${F?.message||F}`)}}},ne=new Map,Ie=new Map,Pe=Dt.join(hk,"plane-link","cursor.json"),ae=Dt.join(hk,"plane-link","dead-letter.ndjson"),Ae=e.replace(/^ws(s?):\/\//,"http$1://").replace(/\/v1\/node\/?$/,""),be={},Q={},me=new Map,Ue=null,nt=null,rt=0,N=0,se=0,le={},ve=new Set,Ye=Promise.resolve(),Fe="ws",Zt=0,ut=!1,kn=0,Kr=!1,at=qo,Vr=new Set,it=[],xt=null,Lt=null,Ot=!1,Zi=!1,ns=XO,k=null,f=null,v=null,O=null,G=0,ge=0,ye=null,vt=!1,ct=0,zr=!1,Mt=X6(E);if(Mt)if(Mt.tokenPreview===YO(t))zr=!0,im({reason:Mt.reason??"removed",at:Mt.at??null,nodeId:Mt.nodeId??n}),z.error(`[plane-link] this node was REMOVED from the plane (${Mt.reason??"removed"}${Mt.at?` at ${new Date(Mt.at).toISOString()}`:""}) \u2014 not dialing. Re-provision it with a new node token, or delete ${E} to force a dial.`);else try{Mi.unlinkSync(E),z.log("[plane-link] stale removed-marker discarded \u2014 the node token changed")}catch{}function Fh({reason:B="removed",at:H=Date.now(),via:F="ctl"}={}){if(!zr){zr=!0,im({reason:B,at:H,nodeId:n,via:F});try{Mi.mkdirSync(Dt.dirname(E),{recursive:!0}),Mi.writeFileSync(E,JSON.stringify({at:H,reason:B,via:F,nodeId:n,tokenPreview:YO(t)},null,2))}catch(R){z.error(`[plane-link] could not write ${E}: ${R?.message||R}`)}z.error(`[plane-link] the plane REMOVED this node (${B}, via ${F}) \u2014 going dormant: no more dials, ingest or broker calls. Re-provision with a new node token to reconnect; the box and its data are untouched.`);try{A?.({reason:B,at:H,via:F})}catch{}ix({bye:!1})}}async function XP(){try{be=JSON.parse(await cu.readFile(Pe,"utf8"))}catch{be={}}}function X0(){vt=!0,!v&&(v=setTimeout(async()=>{if(v=null,!!vt){vt=!1;try{await cu.mkdir(Dt.dirname(Pe),{recursive:!0}),await cu.writeFile(Pe,JSON.stringify(be))}catch(B){z.error("[plane-link] cursor flush failed:",B?.message||B)}}},nK),v.unref?.())}function ht(B){return!Lt||Lt.readyState!==dk.OPEN?!1:(Lt.send(JSON.stringify(B)),!0)}function Qi(B){let H=Date.now();for(let{trackId:R,event:q}of B){let ce=me.get(q.id);me.set(q.id,{trackId:R,seq:q.seq,event:q,sentAt:H,firstSentAt:ce?.firstSentAt??H,retryAt:H+K,tries:(ce?.tries??0)+1,nacks:ce?.nacks??0})}let F=B.map(({trackId:R,event:q})=>({trackId:R,event:cK(q)}));return Fe==="http"?(rD(F),!0):ht({v:kt,ch:"events",type:"append",events:F})}function ZP(B){let H=null;for(let F of me.values())F.trackId===B&&(H==null||F.seq<H)&&(H=F.seq);return H}function Uh(B){let H=Q[B];if(H==null)return;let F=ZP(B),R=F==null?H:Math.min(H,F-1);R>(be[B]??0)&&(be[B]=R,X0())}function ec(){if(Ue=Date.now(),nt!=null){let B=Date.now()-nt;z.log(`[plane-link] spine sync recovered after ${Math.round(B/1e3)}s degraded (${rt} stall redial(s))`);let H=nt;nt=null,rt=0,N=0,ut=!1,kn=0;try{P?.({since:H,downMs:B})}catch(F){z.error(`[plane-link] onRecovered failed: ${F?.message||F}`)}}}function Hh(B){if(!Array.isArray(B)||!B.length)return;let H=new Set;for(let F of B){let R=me.get(F);R&&(me.delete(F),(Q[R.trackId]??0)<R.seq&&(Q[R.trackId]=R.seq),H.add(R.trackId))}for(let F of H)Uh(F);ec()}function Z0(B,H){se++;let F={at:Date.now(),trackId:B.trackId,seq:B.seq,id:B.event?.id??null,type:B.event?.type??null,reason:H,event:B.event??null};z.error(`[plane-link] DEAD-LETTER ${B.trackId} seq ${B.seq} (${F.type??"?"}): plane rejected it permanently (${H}) \u2014 kept in ${ae}`),Ye=Ye.then(async()=>{await cu.mkdir(Dt.dirname(ae),{recursive:!0}),await cu.appendFile(ae,JSON.stringify(F)+`
705
+ `)}).catch(R=>z.error(`[plane-link] dead-letter write failed: ${R?.message||R}`))}function QP(B,H){if(le[B]=(le[B]??0)+1,ve.has(B))return;ve.add(B);let F=iK[B]??"see the plane's tenancy alarm ring (GET /plane/tenancy/alarms)";z.error(`[plane-link] REFUSED by the plane (${B}) on track ${H}: events are being dropped, not stored \u2014 ${F}`);try{L?.({reason:B,trackId:H,count:le[B],hint:F})}catch(R){z.error(`[plane-link] onRefused failed: ${R?.message||R}`)}}function Wh(B,H,F,R=null){if(!Array.isArray(B)||!B.length)return;let q=new Set,ce=Date.now();for(let Te of B){let Se=me.get(Te);Se&&(F?(me.delete(Te),Z0(Se,H),String(H).startsWith(pk)&&QP(String(H).slice(pk.length),Se.trackId),(Q[Se.trackId]??0)<Se.seq&&(Q[Se.trackId]=Se.seq),q.add(Se.trackId)):(Se.nacks++,Se.retryAt=ce+Math.max(1e3,Number(R)||K)))}for(let Te of q)Uh(Te);ec()}function Q0(B=Date.now()){let H=1/0;for(let F of me.values())F.firstSentAt<H&&(H=F.firstSentAt);return H===1/0?0:B-H}function eD(B){if(!I||!B||B!==Lt||!G)return!1;let H=Date.now()-G;if(H<=I)return!1;ge++,z.error(`[plane-link] no frame from the plane for ${Math.round(H/1e3)}s \u2014 link is half-open; terminating and redialing`);try{B.terminate()}catch{}return!0}function ex(){if(!Ot||!me.size)return;let B=Date.now(),H=Q0(B);if(H<j||Ue!=null&&B-Ue<j||Fe==="http"&&ut||N>B)return;rt++;let F=Math.min(W*2**(rt-1),QO);if(nt==null){nt=B-H,z.error(`[plane-link] DEGRADED: no ack or nack for ${Math.round(H/1e3)}s with ${me.size} event(s) in flight (${Fe} door) \u2014 the plane is not answering appends`);try{$?.({since:nt,unacked:me.size,oldestAgeMs:H,mode:Fe})}catch(R){z.error(`[plane-link] onDegraded failed: ${R?.message||R}`)}}if(Fe==="http"){ut=!0,kn=B+F,z.error(`[plane-link] ingest circuit OPEN (stall #${rt}); probing /v1/ingest/health in ${Math.round(F/1e3)}s`);return}N=B+F,z.error(`[plane-link] closing the link and redialing in ${Math.round(F/1e3)}s (stall redial #${rt})`);try{Lt?.terminate()}catch{}}function qh(){if(!Ot)return;let B=Date.now();if(Fe==="http"&&ut)return;let H=[...me.values()].filter(R=>R.event&&R.retryAt<=B&&!(Fe==="http"&&Vr.has(R.trackId)));if(!H.length)return;H.sort((R,q)=>R.trackId===q.trackId?R.seq-q.seq:R.trackId<q.trackId?-1:1),z.log(`[plane-link] re-sending ${H.length} unacked event(s) the plane never confirmed`);let F=Fe==="http"?at:qo;if(Fe==="http"){let R=new Map;for(let q of H)(R.get(q.trackId)??R.set(q.trackId,[]).get(q.trackId)).push(q);for(let[,q]of R){if(Zt>=fk)return;Qi(q.slice(0,F).map(ce=>({trackId:ce.trackId,event:ce.event})))}return}for(let R=0;R<H.length;R+=F){let q=H.slice(R,R+F).map(ce=>({trackId:ce.trackId,event:ce.event}));if(!Qi(q))return}}async function tD(B=null){for(;;){if(!Ot)return!1;let H=me.size<S,F=Fe!=="http"||Zt<fk&&!ut&&(!B||!Vr.has(B));if(H&&F)return!0;await new Promise(R=>setTimeout(R,100))}}function Gh(){if(xt=null,!Ot||!it.length)return;let B=it;if(it=[],Fe!=="http"){for(let F=0;F<B.length;F+=qo)Qi(B.slice(F,F+qo));return}let H=new Map;for(let F of B)(H.get(F.trackId)??H.set(F.trackId,[]).get(F.trackId)).push(F);for(let[F,R]of H){if(Vr.has(F)||Zt>=fk||ut){it.push(...R);continue}for(let q=0;q<R.length;q+=at)Qi(R.slice(q,q+at))}it.length&&!xt&&(xt=setTimeout(Gh,eM),xt.unref?.())}let nD=B=>{let H=new Map;for(let{trackId:F,event:R}of B)(H.get(F)??H.set(F,[]).get(F)).push(R);return[...H].map(([F,R])=>({trackId:F,events:R}))},rs=(B,H,F,{progress:R})=>{let q=Date.now();for(let{event:ce}of B){let Te=me.get(ce.id);Te&&(Te.nacks++,Te.retryAt=q+Math.max(1e3,F||K))}R&&ec()};async function rD(B){let H=new Set(B.map(F=>F.trackId));for(let F of H)Vr.add(F);Zt++;try{let F=await ie(`${Ae}/v1/ingest`,{method:"POST",headers:{authorization:`Bearer ${t}`,"content-type":"application/json"},body:JSON.stringify({node:n,batches:nD(B)}),signal:AbortSignal.timeout(U)}),R=(Number(F.headers.get("retry-after"))||0)*1e3;if(F.status===200){let q=await F.json();at=qo;for(let Se of q.results??[]){Hh(Se.acked??[]);let dt=(jn,jt)=>{let qu=new Map;for(let os of jn??[])(qu.get(os.reason)??qu.set(os.reason,[]).get(os.reason)).push(os.id);for(let[os,cx]of qu)Wh(cx,os,jt,q.retryAfterMs??null)};dt(Se.rejected,!0),dt(Se.deferred,!1)}let ce=new Set,Te=new Map;for(let Se of Array.isArray(q.refused)?q.refused:[])!Se||typeof Se.id!="string"||(ce.add(Se.id),(Te.get(Se.reason)??Te.set(Se.reason,[]).get(Se.reason)).push(Se.id));for(let[Se,dt]of Te)Wh(dt,`${pk}${Se}`,!0);Hh((q.discarded??[]).filter(Se=>!ce.has(Se))),ec();return}if(F.status===429){rs(B,"overloaded",R||5e3,{progress:!0});return}if(F.status===413&&B.length>1){at=Math.max(1,Math.floor(B.length/2)),z.error(`[plane-link] ingest request too large (${B.length} events) \u2014 halving batches to ${at}`),rs(B,"too_large",1e3,{progress:!0});return}if(F.status===413){let q=me.get(B[0].event.id);q&&(me.delete(q.event.id),Z0(q,"too_large"),(Q[q.trackId]??0)<q.seq&&(Q[q.trackId]=q.seq),Uh(q.trackId)),ec();return}if(F.status===410){Fh({reason:"removed",via:"410"}),rs(B,"http_410",6e4,{progress:!1});return}if(F.status===401||F.status===403){let{tripped:q,holdMs:ce}=ya();if(q&&z.error(`[plane-link] holding every plane call for ${Math.round(ce/6e4)} min \u2014 the ingest door refused this node's token three times in a row`),Date.now()-ct>=tM){ct=Date.now();let Te="";try{Te=(await F.json())?.error??""}catch{}z.error(`[plane-link] plane refused ingest (HTTP ${F.status}${Te?`: ${Te}`:""}) \u2014 events are held locally and retried; check this node's token/binding`)}rs(B,`http_${F.status}`,Math.max(6e4,uc()),{progress:!1});return}if(F.status===400){z.error(`[plane-link] plane rejected an ingest request as malformed (400) \u2014 holding ${B.length} event(s) for retry; this is a bug, not data`),rs(B,"http_400",6e4,{progress:!1});return}rs(B,`http_${F.status}`,R||5e3,{progress:!1})}catch(F){let R=F?.name==="TimeoutError"||F?.name==="AbortError";R&&B.length>1&&(at=Math.max(1,Math.floor(B.length/2)),z.error(`[plane-link] ingest request of ${B.length} event(s) outlived its ${U} ms deadline \u2014 halving batches to ${at}`)),rs(B,R?"timeout":"network",5e3,{progress:!1})}finally{Zt--;for(let F of H)Vr.delete(F)}}async function oD(){if(Fe!=="http"||!ut||!Ot||Kr)return;let B=Date.now();if(!(kn>B||ba(B))){Kr=!0;try{let H=await ie(`${Ae}/v1/ingest/health`,{headers:{authorization:`Bearer ${t}`},signal:AbortSignal.timeout(U)});if(!H.ok)throw new Error(`HTTP ${H.status}`);z.log("[plane-link] ingest door answering \u2014 closing the circuit and re-sending"),ut=!1,kn=0,N=Date.now()+U+K+1e3;for(let F of me.values())F.retryAt=Math.min(F.retryAt,Date.now());qh()}catch(H){rt++;let F=Math.min(W*2**(rt-1),QO);kn=Date.now()+F,z.error(`[plane-link] ingest door still not answering (${H?.message||H}); next probe in ${Math.round(F/1e3)}s`)}finally{Kr=!1}}}function tx(){let B=Date.now();return{mode:Fe,unacked:me.size,oldestUnackedAgeMs:Q0(B),lastProgressAt:Ue,degradedSince:nt,stallRedials:rt,deadLettered:se,http:Fe==="http"?{inFlight:Zt,circuitOpen:ut,nextProbeInMs:ut?Math.max(0,kn-B):0,batchCap:at}:null}}async function nx(){if(!c)return;let B;try{B=await c()}catch(F){z.error("[plane-link] metrics sample failed:",F?.message||F);return}let H=null;try{H=l?.()??null}catch{}B&&ht({v:kt,ch:"ctl",type:"metrics",metrics:{...B,planeLink:tx(),...H?{delivery:H}:{}}})}function sD(){c&&(ye&&clearInterval(ye),nx(),ye=setInterval(nx,p),ye.unref?.())}async function aD(){let B;try{B=await o()}catch(H){z.error("[plane-link] backfill listTracks failed:",H?.message||H);return}ht({v:kt,ch:"ctl",type:"tracks",ids:B.filter(H=>!H.transferredTo).map(H=>H.id).filter(H=>typeof H=="string")});for(let H of B)if(!Ot||!await rx(H))return}async function rx(B){let H;try{H=await J(B)}catch{return!0}let F=be[B.id]??0,R=H.filter(ce=>ce.seq>F&&typeof ce.id=="string"),q=Fe==="http"?at:qo;for(let ce=0;ce<R.length;ce+=q){if(!await tD(B.id))return!1;let Te=R.slice(ce,ce+Math.min(q,Fe==="http"?at:qo)).map(Se=>({trackId:B.id,event:Se}));if(!Qi(Te))return!1}return!0}let Kh=new Map;async function ox(B,H){if(Kh.get(B)===H)return!1;Kh.set(B,H);let F=null;try{F=(await o()).find(Te=>Te?.id===B)??null}catch{return!1}if(!F)return!1;let R;try{R=await J(F)}catch{return!1}let q=[...R].reverse().find(Te=>(Te?.type==="track.transferred"||Te?.type==="track.recovered")&&Te.payload?.toNode===n);if(!q||!Number.isFinite(q.seq))return!1;let ce=q.seq-1;return(be[B]??0)>ce&&(be[B]=ce,X0()),(Q[B]??0)>ce&&(Q[B]=ce),z.log(`[plane-link] re-sending ${B}'s move-commit (seq ${q.seq}, ${q.type}) \u2014 the plane's move record predates this node's adoption`),Ot?rx(F):!1}function sx(B){!Ot||!B?.trackId||typeof B.id!="string"||(it.push({trackId:B.trackId,event:B}),xt||(xt=setTimeout(Gh,eM),xt.unref?.()))}let tc=new Map;async function iD(B){let{reqId:H,method:F,path:R,headers:q={},body:ce}=B,Te=Object.fromEntries(Object.entries(q).filter(([,dt])=>dt!=null)),Se=new AbortController;tc.set(H,Se);try{if(B.host){await cD(B,Te,Se);return}x&&(Te["x-bostrat-token"]=x);let dt=await fetch(y+R,{method:F,headers:Te,body:ce?Buffer.from(ce,"base64"):void 0,signal:Se.signal}),jn=Object.fromEntries(dt.headers);for(let jt of["connection","keep-alive","transfer-encoding","upgrade","content-encoding","content-length"])delete jn[jt];if(jn["content-type"]||(jn["content-type"]="application/octet-stream"),ht({v:kt,ch:"control",type:"http_head",reqId:H,status:dt.status,headers:jn}),dt.body){for await(let jt of dt.body)if(!ht({v:kt,ch:"control",type:"http_data",reqId:H,data:Buffer.from(jt).toString("base64")}))break}ht({v:kt,ch:"control",type:"http_end",reqId:H,error:null})}finally{tc.delete(H)}}function cD(B,H,F){let{reqId:R,method:q,path:ce,body:Te}=B,Se=new URL(y);return new Promise(dt=>{let jn=J6.request({host:Se.hostname,port:Se.port,method:q,path:ce,headers:{...H,host:B.host},signal:F.signal},jt=>{let{connection:qu,"keep-alive":os,"transfer-encoding":cx,upgrade:lY,...lD}=jt.headers;ht({v:kt,ch:"control",type:"http_head",reqId:R,status:jt.statusCode||502,headers:lD}),jt.on("data",uD=>{ht({v:kt,ch:"control",type:"http_data",reqId:R,data:Buffer.from(uD).toString("base64")})||jt.destroy()}),jt.on("end",()=>{ht({v:kt,ch:"control",type:"http_end",reqId:R,error:null}),dt()}),jt.on("error",()=>{ht({v:kt,ch:"control",type:"http_end",reqId:R,error:"view upstream error"}),dt()})});jn.on("error",jt=>{ht({v:kt,ch:"control",type:"http_end",reqId:R,error:jt?.message||"view request failed"}),dt()}),Te&&jn.write(Buffer.from(Te,"base64")),jn.end()})}function ax(){if(Zi||zr)return;Lt=new dk(e,{headers:{authorization:`Bearer ${t}`}});let B=Lt;G=0,B.on("ping",()=>{G=Date.now()}),B.on("pong",()=>{G=Date.now()}),Lt.on("open",async()=>{let F=null;try{F=await s?.()||null}catch{F=null}ht({v:kt,ch:"ctl",type:"hello",nodeId:n,name:r,platform:process.platform,version:Pn,installKind:b,...typeof g=="function"?{updatePolicy:g()}:g?{updatePolicy:g}:{},providers:Z6(),...F?{agents:F}:{}})}),Lt.on("message",F=>{G=Date.now();let R;try{R=JSON.parse(F)}catch{return}if(R.ch==="ctl"&&R.type==="hello_ok"){Kh.clear(),Ot=!0,ns=XO,k=null,Ox(),z.log(`[plane-link] connected to plane as ${n}`);try{T?.()}catch{}if(typeof R.hashKey=="string"&&R.hashKey)try{u?.(R.hashKey)}catch{}try{d?.(typeof R.viewBase=="string"&&R.viewBase?R.viewBase:null)}catch{}R.minNodeVersion&&Pn&&lu(Pn,R.minNodeVersion)&&z.error(`[plane-link] this node is bostrat-node ${Pn}; the plane asks for \u2265${R.minNodeVersion} \u2014 update with: ${Yf(b)}`);try{w?.(typeof R.updatePolicy=="string"?R.updatePolicy:null)}catch{}Y(R);let q=R.ingest==="http";Fe=C==="ws"?"ws":C==="http"||q?"http":"ws",C==="http"&&!q&&z.error("[plane-link] BOSTRAT_PLANE_INGEST=http but this plane offers no HTTPS ingest door \u2014 events will fail until it does"),Fe==="http"&&z.log("[plane-link] spine rides the HTTPS ingest door"),ut=!1,kn=0,at=qo,O&&clearInterval(O),G=Date.now(),O=setInterval(()=>{eD(B)||(ht({v:kt,ch:"ctl",type:"ping"}),ex(),oD().catch(()=>{}),qh(),it.length&&!xt&&Gh())},M),O.unref?.(),sD(),aD().catch(ce=>z.error("[plane-link] backfill failed:",ce?.message||ce));return}if(R.ch==="ctl"&&R.type==="hello_refused"){let q=typeof R.minNodeVersion=="string"?R.minNodeVersion:null,ce=typeof R.latestNodeVersion=="string"?R.latestNodeVersion:null;z.error(`[plane-link] plane REFUSED this node: bostrat-node ${Pn??"?"} is below its minimum ${q??"?"} \u2014 ${R.fix||Yf(b)}`),ns=ZO,k=0;try{h?.({current:Pn,min:q,latest:ce,fix:R.fix||Yf(b),installKind:b})}catch(Te){z.error(`[plane-link] refusal handler failed: ${Te?.message||Te}`)}return}if(R.ch==="ctl"&&R.type==="removed"){ht({v:kt,ch:"ctl",type:"removed_ack",nodeId:n}),Fh({reason:typeof R.reason=="string"?R.reason:"removed",at:Number(R.at)||Date.now(),via:"ctl"});return}if(R.ch==="ctl"&&R.type==="update_available"){Y(R);return}if(R.ch==="ctl"&&R.type==="update_policy"){try{w?.(typeof R.mode=="string"?R.mode:null)}catch{}return}if(R.ch==="ctl"&&R.type==="usage_caps"){yp(R.caps??{},{source:"plane",updatedAt:R.updatedAt??Date.now()}).then(q=>z.log(`[plane-link] spend caps ${Object.keys(q.caps).length?`updated (${Object.keys(q.caps).join(", ")})`:"cleared"} from plane`)).catch(q=>z.error("[plane-link] spend-caps push rejected:",q?.message||q));return}if(R.ch==="ctl"&&R.type==="transferred"&&Array.isArray(R.tracks)){Promise.resolve().then(()=>a?.(R.tracks)).then(async q=>{for(let ce of Array.isArray(q)?q:[])ce?.stale&&ce.id&&await ox(ce.id,ce.since??null)}).catch(q=>z.error("[plane-link] transfer notice failed:",q?.message||q));return}if(R.ch==="ctl"&&R.type==="moves"&&Array.isArray(R.tracks)){Promise.resolve().then(()=>i?.(R.tracks)).then(async q=>{for(let ce of Array.isArray(q)?q:[])ce?.stale&&ce.id&&await ox(ce.id,ce.since??null)}).catch(q=>z.error("[plane-link] move-record reconcile failed:",q?.message||q));return}if(R.ch==="events"&&R.type==="ack"&&Array.isArray(R.ids)){Hh(R.ids);return}if(R.ch==="events"&&R.type==="nack"&&Array.isArray(R.ids)){Wh(R.ids,R.reason,R.permanent===!0,R.retryAfterMs??null);return}if(R.ch==="control"&&R.type==="http_open"){iD(R).catch(q=>ht({v:kt,ch:"control",type:"http_end",reqId:R.reqId,error:q?.message||"tunnel error"}));return}if(R.ch==="control"&&R.type==="http_cancel"){tc.get(R.reqId)?.abort();return}if(R.ch==="attach"&&R.type==="open"){let q=new dk(Ge+R.path,Array.isArray(R.protocols)?R.protocols:[],R.host?{headers:{host:R.host}}:void 0);ne.set(R.streamId,q),Ie.set(R.streamId,[]),q.on("open",()=>{let Te=Ie.get(R.streamId)||[];Ie.delete(R.streamId);for(let{buf:Se,bin:dt}of Te)q.send(Se,{binary:dt})}),q.on("message",(Te,Se)=>{let dt=Se?Te:Buffer.from(String(Te));ht({v:kt,ch:"attach",type:"data",streamId:R.streamId,data:dt.toString("base64"),...Se?{bin:!0}:{}})});let ce=()=>{Ie.delete(R.streamId),ne.delete(R.streamId)&&ht({v:kt,ch:"attach",type:"close",streamId:R.streamId})};q.on("close",ce),q.on("error",ce);return}if(R.ch==="attach"&&R.type==="data"){let q=ne.get(R.streamId);if(!q)return;let ce=Buffer.from(R.data,"base64"),Te=R.bin===!0,Se=Ie.get(R.streamId);Se?Se.push({buf:ce,bin:Te}):q.send(ce,{binary:Te});return}if(R.ch==="attach"&&R.type==="close"){let q=ne.get(R.streamId);ne.delete(R.streamId),Ie.delete(R.streamId),q?.close();return}});let H=()=>{Ot&&z.log("[plane-link] disconnected from plane"),Ot=!1,O&&(clearInterval(O),O=null),ye&&(clearInterval(ye),ye=null),me.clear(),Q={},it=[],xt&&(clearTimeout(xt),xt=null),Vr.clear();for(let q of ne.values())q.close();ne.clear(),Ie.clear();for(let q of tc.values())q.abort();if(tc.clear(),Zi||f)return;k==null&&(k=Date.now());let F=Date.now()-k<Q6,R=Math.max(F?eK+Math.random()*tK:ns,N-Date.now(),uc());f=setTimeout(()=>{f=null,ax()},R),f.unref?.(),F||(ns=Math.min(ns*2,ZO))};Lt.on("close",H),Lt.on("error",F=>{let R=/Unexpected server response: (\d+)/.exec(F?.message||"")?.[1];if(R==="410"){Fh({reason:"removed",via:"410"});return}if(R==="401"||R==="403"){let{tripped:q,holdMs:ce}=ya();q?z.error(`[plane-link] holding every plane call for ${Math.round(ce/6e4)} min \u2014 three credential refusals in a row (HTTP ${R}) mean the token is revoked or unknown, not that the plane is down; mint a new node token and update this node's BOSTRAT_PLANE_TOKEN. Next dial in ${Math.round(ce/6e4)} min.`):Date.now()-ct>=tM&&(ct=Date.now(),z.error(`[plane-link] plane refused this node's credentials (HTTP ${R}) \u2014 the token was revoked or is unknown to the plane; mint a new node token and update this node's BOSTRAT_PLANE_TOKEN (still retrying)`))}H()})}et.on("event",sx),XP().then(ax);function ix({bye:B=!0}={}){Zi=!0,et.off("event",sx),f&&clearTimeout(f),v&&clearTimeout(v),O&&clearInterval(O),ye&&clearInterval(ye),xt&&clearTimeout(xt),B&&ht({v:kt,ch:"ctl",type:"bye",reason:"shutdown"}),Lt?.close()}return{stop:()=>ix(),status:()=>({connected:Ot,nodeId:n,cursor:{...be},inflight:me.size,...tx(),auth:Mx(),dormant:zr,removed:nd(),deadLinkMs:I,deadLinkRedials:ge,refused:{...le}}),_tick:()=>{ex(),qh()}}}is();var Zf=(()=>{try{return mK(import.meta.url)("../package.json").version||null}catch{return null}})(),wK=process.env.BOSTRAT_STATE_DIR||St.join(process.env.HOME||fK.tmpdir(),".bostrat"),cM=St.join(wK,"self-update"),Qf=St.join(cM,"status.json"),gK=1440*6e4,yK=6e4,sM=60,aM=15,eh=3,uu=new Set(["npm-global","git-checkout"]);function lM({kind:e=ra(),env:t=process.env}={}){let n=String(t.BOSTRAT_UPDATE_POLICY||"").trim();return["auto","prompt","off"].includes(n)?n:uu.has(e)?e==="git-checkout"||bK(t)?"auto":"prompt":"off"}function bK(e=process.env){return!!(e.INVOCATION_ID||e.XPC_SERVICE_NAME&&e.XPC_SERVICE_NAME!=="0")}var Yt=e=>`'${String(e).replace(/'/g,"'\\''")}'`;function kK({kind:e,to:t,from:n=Zf,statusFile:r=Qf,logFile:o=St.join(cM,"last.log"),port:s=Number(process.env.PORT)||3362,npmPrefix:a=null,serviceName:i=process.platform==="darwin"?"com.bostrat.node":"bostrat-node.service",uid:c=typeof process.getuid=="function"?process.getuid():0,liveDir:l=process.env.BOSTRAT_LIVE_CHECKOUT||St.resolve(St.dirname(new URL(import.meta.url).pathname),"..",".."),startedAt:u=Date.now(),attempts:d=1}={}){if(!uu.has(e))throw new Error(`self-update: install kind "${e}" is not actionable here`);if(!/^\d+\.\d+\.\d+$/.test(String(t)))throw new Error(`self-update: bad target version "${t}"`);if(n&&!/^\d+\.\d+\.\d+$/.test(String(n)))throw new Error(`self-update: bad current version "${n}"`);let p=(b,y="")=>`write_status ${Yt(b)} ${y}`,m=process.platform==="darwin"?`launchctl kickstart -k gui/${c}/${i}`:`systemctl --user restart ${Yt(i)}`,w=`
706
706
  health() {
707
707
  for i in $(seq 1 45); do
708
708
  sleep 1
@@ -819,7 +819,7 @@ bostrat: no live view "${s}"\r
819
819
  `),n?.length&&a.write(n),t.pipe(a),a.pipe(t)}),i=()=>{a.destroy(),t.destroy()};return a.on("error",i),t.on("error",i),!0}function a0(e){let t=typeof e=="string"?{host:e}:e||{},n=t["x-bostrat-view-base"];if(typeof n=="string"&&n)return{proto:t["x-forwarded-proto"]==="https"?"https":"http",host:n.replace(/:\d+$/,"").toLowerCase(),source:"header"};let r=$k();if(r)return{proto:"https",host:r,source:"learned"};let o=Rk();if(o)return{...o,source:"env"};let s=String(t.host||"").replace(/:\d+$/,"").toLowerCase();if(!s||!s.includes(".")||/^[\d.]+$/.test(s))return null;let a=s.split(".");return{proto:"http",host:Iu(s)&&ky(a[0])?a.slice(1).join("."):s,source:"request"}}function ZC(e,t){return lh(a0(t),e.slug)}function QC({app:e,onUpgrade:t,extractViewSlug:n,log:r=console}){let o=s=>{r.warn?.(`[bostrat-agent] view listener refused non-view Host ${JSON.stringify(String(s||""))}`)};return{request(s,a){if(!n(s.headers.host)){o(s.headers.host),a.statusCode=403,a.setHeader("content-type","text/plain"),a.end("bostrat: this listener serves views only");return}e(s,a)},upgrade(s,a,i){if(!n(s.headers.host)){o(s.headers.host),a.write(`HTTP/1.1 403 Forbidden\r
820
820
  \r
821
821
  `),a.destroy();return}t(s,a,i)}}}function eN(e,{addr:t,port:n,log:r=console,retryMs:o=15e3,maxRetries:s=1/0}){let a=0;e.on("error",c=>{let l=c?.code||c?.message;if(e.listening){r.error?.(`[bostrat-agent] view listener on ${t}:${n}: ${l}`);return}if(a>s){r.error?.(`[bostrat-agent] view listener on ${t}:${n} failed (${l}) \u2014 giving up`);return}r.error?.(`[bostrat-agent] view listener on ${t}:${n} failed (${l}) \u2014 retrying in ${Math.round(o/1e3)}s`),setTimeout(i,o).unref?.()});let i=()=>{a++,e.listen(n,t,()=>{r.log?.(`[bostrat-agent] view listener on ${t}:${n} (view Hosts only; front-door CIDRs decide the rest)`)})};return i(),e}mi();Cy();yf();rl();ke();import tN from"node:os";import{randomUUID as c0}from"node:crypto";var Sz=(e=process.env)=>({nodeId:e.BOSTRAT_NODE_ID||tN.hostname(),nodeName:e.BOSTRAT_NODE_NAME||tN.hostname()});var nN=32768,rN=120,oN=1e3,sN=new Set(["claude","codex","cursor"]),Az=new Set(["off","transition","nag"]),Tz=[[0,59],[0,23],[1,31],[1,12],[0,6]];function Ez(e){let t=String(e??"").trim().split(/\s+/);return t.length!==5?!1:t.every((n,r)=>{let[o,s]=Tz[r];return String(n).split(",").every(a=>{if(!a)return!1;let[i,c]=a.split("/");if(c!==void 0&&!(Number.isInteger(Number(c))&&Number(c)>=1))return!1;if(i==="*")return!0;let[l,u]=i.includes("-")?i.split("-").map(Number):[Number(i),Number(i)];return Number.isInteger(l)&&Number.isInteger(u)&&l>=o&&u<=s&&l<=u})})}var Bn=e=>String(e??"").trim(),pa={name(e){let t=Bn(e);if(!t)throw new Error("a loop needs a name");if(t.length>rN)throw new Error(`name is too long (${t.length}); cap is ${rN}`);return t},schedule(e){let t=Bn(e);if(!t)throw new Error('a loop needs a schedule (5-field UTC crontab, e.g. "0 7 * * *")');if(!Ez(t))throw new Error(`invalid cron schedule: "${t}" \u2014 5 UTC fields, e.g. "0 7 * * *"`);return t},prompt(e){let t=Bn(e);if(!t)throw new Error("a loop needs a prompt \u2014 it is what the run does");if(t.length>nN)throw new Error(`prompt is too long (${t.length} chars); cap is ${nN}`);return t},expectation(e){let t=Bn(e)||null;if(t&&t.length>oN)throw new Error(`expectation is too long (${t.length}); cap is ${oN}`);return t},notify(e){let t=Bn(e)||"off";if(!Az.has(t))throw new Error(`notify must be one of off | transition | nag, got "${e}"`);return t},assignment(e){let t=e??null,n=Bn(typeof t=="string"?t:t?.provider)||"claude";if(!sN.has(n))throw new Error(`unknown provider "${n}" \u2014 one of ${[...sN].join(", ")}`);let r=typeof t=="object"&&t&&Bn(t.model)||null;return r?{provider:n,model:r}:{provider:n}},enabled(e){if(typeof e=="boolean")return e;if(e==="true"||e==="false")return e==="true";throw new Error(`enabled must be true or false, got "${e}"`)}};function _z(e,t){let n=e&&typeof e=="object"?e:{},r=pa.name(n.name),o=pa.schedule(n.schedule),s=pa.prompt(n.prompt),a=pa.expectation(n.expectation),i=pa.notify(n.notify),c=pa.assignment(n.assignment),l=Bn(t?.workspace?.repo)||Bn(t?.workspace?.base)||null;if(!l)throw new Error("this Track isn't based on a repo, so there's nothing for a loop to run in \u2014 propose from a repo-backed Track");let{nodeId:u,nodeName:d}=Sz();return{name:r,schedule:o,prompt:s,expectation:a,notify:i,assignment:c,repo:l,nodeId:u||null,nodeName:d||null}}async function iN(e,t){let n=_z(t,e),r=c0();return await D({id:e.id,cwd:e.cwd},{type:"loop.create.offered",actor:"system",source:"orchestrator",payload:{ts:Date.now(),proposalId:r,...n}}),{proposalId:r,...n}}async function cN(e,t,n,{loopId:r=null,nextFireAt:o=null}={}){if(!t)throw new Error("proposalId required");let s=await J({id:e.id,cwd:e.cwd}),a=s.find(c=>c.type==="loop.create.offered"&&c.payload?.proposalId===t);if(!a)throw new Error("unknown proposal");if(s.some(c=>c.type==="loop.create.answered"&&c.payload?.proposalId===t))throw new Error("proposal already answered");if(!n)return await D({id:e.id,cwd:e.cwd},{type:"loop.create.answered",actor:"user",source:"orchestrator",payload:{ts:Date.now(),proposalId:t,action:"dismiss"}}),{proposalId:t,action:"dismiss"};if(!r)throw new Error("loopId required \u2014 the loop is created on the plane before the card is answered");let i=a.payload;return await D({id:e.id,cwd:e.cwd},{type:"loop.created",actor:"user",source:"orchestrator",payload:{ts:Date.now(),proposalId:t,loopId:String(r),name:i.name,schedule:i.schedule,provider:i.assignment?.provider??"claude",repo:i.repo??null,nodeId:i.nodeId??null,nextFireAt:Number.isFinite(Number(o))?Number(o):null}}),await D({id:e.id,cwd:e.cwd},{type:"loop.create.answered",actor:"user",source:"orchestrator",payload:{ts:Date.now(),proposalId:t,action:"created",loopId:String(r)}}),{proposalId:t,action:"created",loopId:String(r)}}var i0=["name","schedule","prompt","expectation","notify","assignment","enabled"],Iz=(e,t)=>(e?.provider??"claude")===(t?.provider??"claude")&&(e?.model??null)===(t?.model??null);function lN(e){let t=Array.isArray(e.runs)?e.runs:[],n=t[t.length-1]??null;return{definitionUpdatedAt:Number(e.definitionUpdatedAt??e.updatedAt)||null,name:e.name??"",schedule:e.schedule??"",prompt:e.prompt??"",expectation:e.expectation??null,notify:e.notify??"off",assignment:e.assignment&&typeof e.assignment=="object"?e.assignment:{provider:String(e.assignment||"claude")},enabled:e.enabled!==!1,repo:e.repo??null,nodeId:e.nodeId??null,nodeName:e.nodeName??null,trackId:e.trackId??null,nextFireAt:Number.isFinite(Number(e.nextFireAt))?Number(e.nextFireAt):null,createdAt:Number(e.createdAt)||null,runCount:t.length,lastRun:n?{firedAt:Number(n.firedAt)||null,outcome:n.outcome??(n.error?"errored":null)}:null}}function uN(e,t){let n=Bn(t);if(!n)throw new Error("which loop? give an id or a name \u2014 see `bostrat-loop ls`");let r=e.find(a=>a.id===n)||e.find(a=>a.name===n);if(r)return r;let o=n.toLowerCase(),s=e.filter(a=>String(a.id).toLowerCase().startsWith(o)||String(a.name).toLowerCase().startsWith(o));if(s.length===1)return s[0];throw s.length>1?new Error(`"${n}" matches ${s.length} loops: ${s.map(a=>`${a.name} (${a.id})`).join(", ")} \u2014 use the id`):new Error(`no loop matching "${n}" \u2014 use \`bostrat-loop ls\``)}function $z(e,t){let n=e&&typeof e=="object"&&!Array.isArray(e)?e:null;if(!n)throw new Error("a patch must be a JSON object of the fields to change");let r=Object.keys(n).filter(a=>!i0.includes(a));if(r.length){let a=r.filter(i=>["repo","nodeId","cwd","userId","owner","id","trackId"].includes(i));throw a.length?new Error(`a proposal can't change ${a.join(", ")} \u2014 retargeting a loop is a Loops-tab edit (scope D5)`):new Error(`unknown field(s) ${r.join(", ")} \u2014 patchable: ${i0.join(", ")}`)}let o={};for(let a of i0){if(!(a in n))continue;let i=pa[a](n[a]);(a==="assignment"?Iz(i,t.assignment):i===(t[a]??(a==="notify"?"off":a==="enabled"?!0:null)))||(o[a]=i)}let s=Object.keys(o);if(!s.length)throw new Error("nothing would change \u2014 the patch equals the loop's current definition");return{patch:o,changed:s}}async function dN(e,t,n){let r=lN(t),{patch:o,changed:s}=$z(n,r),a=c0(),i={ts:Date.now(),proposalId:a,loopId:String(t.id),name:r.name,base:r,patch:o,changed:s,selfEdit:!!(r.trackId&&r.trackId===e.id)};return await D({id:e.id,cwd:e.cwd},{type:"loop.update.offered",actor:"system",source:"orchestrator",payload:i}),i}var aN=600;async function pN(e,t,n){let r=Bn(n);if(!r)throw new Error('a delete proposal needs a reason \u2014 bostrat-loop propose-delete <loop> --reason "<why this loop should go>"');if(r.length>aN)throw new Error(`reason is too long (${r.length}); cap is ${aN}`);let o=lN(t),s=c0(),a={ts:Date.now(),proposalId:s,loopId:String(t.id),name:o.name,base:o,reason:r,selfEdit:!!(o.trackId&&o.trackId===e.id)};return await D({id:e.id,cwd:e.cwd},{type:"loop.delete.offered",actor:"system",source:"orchestrator",payload:a}),a}var fN=async(e,t,n)=>{if(!n)throw new Error("proposalId required");let r=await J({id:e.id,cwd:e.cwd}),o=r.find(a=>a.type===t&&a.payload?.proposalId===n);if(!o)throw new Error("unknown proposal");let s=t.replace(".offered",".answered");if(r.some(a=>a.type===s&&a.payload?.proposalId===n))throw new Error("proposal already answered");return o};async function hN(e,t,n,{nextFireAt:r=null}={}){if(!["applied","dismiss","moved"].includes(n))throw new Error("action must be one of applied | dismiss | moved");let s=(await fN(e,"loop.update.offered",t)).payload,a={id:e.id,cwd:e.cwd};return n==="applied"&&await D(a,{type:"loop.updated",actor:"user",source:"orchestrator",payload:{ts:Date.now(),proposalId:t,loopId:s.loopId,name:s.patch?.name??s.name,changed:s.changed??Object.keys(s.patch||{}),nextFireAt:Number.isFinite(Number(r))?Number(r):null}}),await D(a,{type:"loop.update.answered",actor:"user",source:"orchestrator",payload:{ts:Date.now(),proposalId:t,action:n,loopId:s.loopId}}),{proposalId:t,action:n,loopId:s.loopId}}async function mN(e,t,n){if(!["delete","pause","keep","moved"].includes(n))throw new Error("action must be one of delete | pause | keep | moved");let o=(await fN(e,"loop.delete.offered",t)).payload,s={id:e.id,cwd:e.cwd};return(n==="delete"||n==="pause")&&await D(s,{type:n==="delete"?"loop.deleted":"loop.paused",actor:"user",source:"orchestrator",payload:{ts:Date.now(),proposalId:t,loopId:o.loopId,name:o.name,trackId:o.base?.trackId??null}}),await D(s,{type:"loop.delete.answered",actor:"user",source:"orchestrator",payload:{ts:Date.now(),proposalId:t,action:n,loopId:o.loopId}}),{proposalId:t,action:n,loopId:o.loopId}}ke();import{randomUUID as Rz}from"node:crypto";var d0=20,Oz=300,l0=120,wN=120,gN=2e3,Ah=new Set(["build","ops","debt","spike"]),yN=new Set(["active","done","abandoned"]),p0=new Set(["circuit.create","circuit.update","circuit.delete"]),Mz=new Set(["person.create","slot.create","slot.update","slot.delete","reservation.create","reservation.update","reservation.delete"]),$u=new Set([...p0,...Mz]),Cz=["name","description","status","type"],Nz=["person","startDate","endDate","estUsd"],Pz=["person","label","startDate","endDate"],Dz=/^\d{4}-\d{2}-\d{2}$/,cn=e=>String(e??"").trim(),f0=e=>typeof e=="string"&&e.startsWith("@"),xN=864e5;function vN(e){let t=Date.parse(`${e}T00:00:00Z`),n=new Date(t).getUTCDay();return new Date(t-(n+6)%7*xN).toISOString().slice(0,10)}function Bz(e){return new Date(Date.parse(`${vN(e)}T00:00:00Z`)+6*xN).toISOString().slice(0,10)}var bN=(e,t)=>{let n=cn(e);if(!Dz.test(n))throw new Error(`${t} must be YYYY-MM-DD, got "${e??""}"`);if(!Number.isFinite(Date.parse(`${n}T00:00:00Z`)))throw new Error(`${t} "${n}" is not a real date`);return n};function Lz(e,t){let n=bN(e,"startDate"),r=bN(t,"endDate");if(r<n)throw new Error(`endDate ${r} is before startDate ${n}`);let o=vN(n),s=Bz(r);return{startDate:o,endDate:s,snapped:o!==n||s!==r}}var kN=e=>{if(e==null||e==="")return null;let t=Number(e);if(!Number.isFinite(t)||t<0)throw new Error(`estUsd must be a non-negative number, got "${e}"`);return t},es=(e,t,n)=>{let r=cn(e);if(r.length>t)throw new Error(`${n} is too long (${r.length}); cap is ${t}`);return r};function u0(e,t){let n=cn(t);if(!n)throw new Error("a circuit name or id is required");if(f0(n))return{ref:n,id:null,name:n.slice(1)};let r=e.find(i=>i.id===n);if(r)return r;let o=n.toLowerCase(),s=e.filter(i=>String(i.name).toLowerCase()===o);if(s.length===1)return s[0];if(s.length>1)throw new Error(`"${n}" names ${s.length} circuits \u2014 use an id (bostrat-circuit ls)`);let a=e.filter(i=>String(i.name).toLowerCase().includes(o)).slice(0,5);throw new Error(a.length?`no circuit named "${n}" \u2014 near matches: ${a.map(i=>`${i.name} (${i.id})`).join(", ")}`:`no circuit named "${n}" \u2014 propose a circuit.create op if it should exist (bostrat-circuit ls lists yours)`)}function jz(e,t){let n=cn(t);if(!n)throw new Error('a person is required \u2014 "me", a person id, or a row label');if(n==="me"||f0(n))return{ref:n,id:null,label:n==="me"?"you":n.slice(1)};let r=e.find(a=>a.personId===n);if(r)return{...r,id:r.personId};let o=n.toLowerCase(),s=e.filter(a=>String(a.label).toLowerCase()===o);if(s.length===1)return{...s[0],id:s[0].personId};throw s.length>1?new Error(`"${n}" names ${s.length} roadmap rows \u2014 use a person id`):new Error(e.length?`no roadmap row for "${n}" \u2014 rows: ${e.map(a=>`${a.label} (${a.personId})`).join(", ")}, or propose a person.create op`:`no roadmap rows yet \u2014 use "me", or propose a person.create op for "${n}"`)}function Fz(e,t,{allow:n=$u}={}){let r=e&&typeof e=="object"&&!Array.isArray(e)?e:null;if(!r)throw new Error("a plan must be a JSON object with an `ops` array");let o=Array.isArray(r.ops)?r.ops:null;if(!o?.length)throw new Error("a plan needs at least one op in `ops`");if(o.length>d0)throw new Error(`too many ops (${o.length}); cap is ${d0} \u2014 propose one intent at a time`);let s=Array.isArray(t?.circuits)?t.circuits:[],a=Array.isArray(t?.people)?t.people:[],i=Array.isArray(t?.slots)?t.slots:[],c=Array.isArray(t?.reservations)?t.reservations:[],l={circuits:{},slots:{},reservations:{}},u={},d=new Set,p=!1,m=!1,w=x=>{x.id&&(l.circuits[x.id]={name:x.name,status:x.status,type:x.type??"build",updatedAt:x.updatedAt??null},u[x.id]=x.name)},h=x=>{x.id&&(u[x.id]=x.label)},g=(x,E)=>{let A=cn(x);if(!A)return null;if(d.has(A))throw new Error(`ref "${A}" is used by two ops \u2014 each ref names one thing`);return d.add(A),u[`@${A}`]=E,A},b=o.map((x,E)=>{let A=x&&typeof x=="object"?x:{},$=cn(A.op),P=`op ${E+1}`;if(!$u.has($))throw new Error(`${P}: unknown op "${$}" \u2014 one of ${[...$u].join(", ")}`);if(!n.has($))throw new Error(`${P}: "${$}" isn't a circuit op \u2014 roadmap changes go through \`bostrat-roadmap propose\` (one card, either CLI)`);let L=M=>{throw new Error(`${P} (${$}): ${M}`)},T=M=>{let I=A.set&&typeof A.set=="object"&&!Array.isArray(A.set)?A.set:null;I||L("needs a `set` object naming the fields to change");let S=Object.keys(I).filter(U=>!M.includes(U));return S.length&&L(`unknown field(s) ${S.join(", ")} \u2014 settable: ${M.join(", ")}`),Object.keys(I).length||L("`set` names no fields"),I},C=M=>{let{startDate:I,endDate:S,snapped:U}=Lz(M.startDate,M.endDate);return U&&(p=!0),{startDate:I,endDate:S,snapped:U}},j=M=>{let I=jz(a,M);return cn(M)==="me"&&(m=!0),h(I),{key:I.id??cn(M),label:I.label}},K=(M,I,S,U,W)=>{let ie=cn(M);ie||L(`needs a ${U} id`);let z=I.find(Ge=>Ge[S]===ie);return z||L(`no ${U} "${ie}" \u2014 see \`bostrat-roadmap ls\``),W[ie]={...z},z};switch($){case"circuit.create":{let M=es(A.name,wN,"name");M||L("a circuit needs a name");let I=cn(A.type)||"build";Ah.has(I)||L(`bad type "${I}" (${[...Ah].join(" | ")})`);let S=s.find(W=>String(W.name).toLowerCase()===M.toLowerCase());S&&L(`a circuit named "${S.name}" already exists (${S.id}) \u2014 update it instead of making a twin`);let U=g(A.ref,M);return{op:$,...U?{ref:U}:{},name:M,description:es(A.description,gN,"description"),type:I}}case"circuit.update":{let M=u0(s,A.circuit);M.id||L("can't update a circuit created in the same plan \u2014 set its fields on the create op"),w(M);let I=T(Cz),S={};if(I.name!==void 0){let U=es(I.name,wN,"name");U||L("name can't be blank"),U!==M.name&&(S.name=U)}return I.description!==void 0&&(S.description=es(I.description,gN,"description")),I.status!==void 0&&(yN.has(I.status)||L(`bad status "${I.status}" (${[...yN].join(" | ")})`),I.status!==M.status&&(S.status=I.status)),I.type!==void 0&&(Ah.has(I.type)||L(`bad type "${I.type}" (${[...Ah].join(" | ")})`),I.type!==(M.type??"build")&&(S.type=I.type)),Object.keys(S).length||L("nothing would change \u2014 the set equals the circuit's current values"),{op:$,circuit:M.id,name:M.name,set:S}}case"circuit.delete":{let M=u0(s,A.circuit);M.id||L("can't delete a circuit created in the same plan"),w(M);let I=o.some((S,U)=>U<E&&cn(S?.op)==="circuit.update"&&S?.set?.status&&S.set.status!=="active"&&cn(S?.circuit)===cn(A.circuit));return M.status==="active"&&!I&&L(`\u201C${M.name}\u201D is active \u2014 an active circuit can't be deleted; propose a circuit.update to done/abandoned first (both can ride one card)`),{op:$,circuit:M.id,name:M.name,status:M.status}}case"person.create":{let M=es(A.label,l0,"label");M||L("a person row needs a label");let I=a.find(U=>String(U.label).toLowerCase()===M.toLowerCase());I&&L(`a roadmap row labelled "${I.label}" already exists (${I.personId})`);let S=g(A.ref,M);return{op:$,...S?{ref:S}:{},label:M}}case"slot.create":{let M=u0(s,A.circuit);w(M);let I=j(A.person),S=C(A);return{op:$,circuit:M.id??M.ref,circuitName:M.name,person:I.key,personLabel:I.label,...S,estUsd:kN(A.estUsd)}}case"slot.update":{let M=K(A.slot,i,"slotId","slot",l.slots),I=T(Nz),S={};if(I.person!==void 0){let W=j(I.person);S.person=W.key,S.personLabel=W.label}if(I.startDate!==void 0||I.endDate!==void 0){let W=C({startDate:I.startDate??M.startDate,endDate:I.endDate??M.endDate});W.startDate!==M.startDate&&(S.startDate=W.startDate),W.endDate!==M.endDate&&(S.endDate=W.endDate)}I.estUsd!==void 0&&(S.estUsd=kN(I.estUsd)),Object.keys(S).length||L("nothing would change");let U=s.find(W=>W.id===M.circuitId);return{op:$,slot:M.slotId,circuitName:U?.name??null,set:S}}case"slot.delete":{let M=K(A.slot,i,"slotId","slot",l.slots),I=s.find(S=>S.id===M.circuitId);return{op:$,slot:M.slotId,circuitName:I?.name??null,startDate:M.startDate,endDate:M.endDate}}case"reservation.create":{let M=j(A.person),I=es(A.label,l0,"label");return I||L("a reservation needs a label (Leave, Support rotation, \u2026)"),{op:$,person:M.key,personLabel:M.label,label:I,...C(A)}}case"reservation.update":{let M=K(A.reservation,c,"reservationId","reservation",l.reservations),I=T(Pz),S={};if(I.person!==void 0){let U=j(I.person);S.person=U.key,S.personLabel=U.label}if(I.label!==void 0){let U=es(I.label,l0,"label");U||L("label can't be blank"),U!==M.label&&(S.label=U)}if(I.startDate!==void 0||I.endDate!==void 0){let U=C({startDate:I.startDate??M.startDate,endDate:I.endDate??M.endDate});U.startDate!==M.startDate&&(S.startDate=U.startDate),U.endDate!==M.endDate&&(S.endDate=U.endDate)}return Object.keys(S).length||L("nothing would change"),{op:$,reservation:M.reservationId,label:M.label,set:S}}case"reservation.delete":{let M=K(A.reservation,c,"reservationId","reservation",l.reservations);return{op:$,reservation:M.reservationId,label:M.label,startDate:M.startDate,endDate:M.endDate}}default:return L("unhandled op")}});b.forEach((x,E)=>{for(let A of[x.circuit,x.person,x.set?.person])if(f0(A)&&!d.has(String(A).slice(1)))throw new Error(`op ${E+1} (${x.op}): unknown ref "${A}" \u2014 no earlier op in this plan creates it`)});let y=a.some(x=>x.kind==="user"&&x.userId);return{why:es(r.why,Oz,"why"),ops:b,base:l,resolved:u,snapped:p,createsMeRow:m&&!y}}async function SN(e,t,n,r={}){let o=Fz(t,n,r),s=Rz(),a={ts:Date.now(),proposalId:s,...o};return await D({id:e.id,cwd:e.cwd},{type:"planning.change.offered",actor:"system",source:"orchestrator",payload:a}),a}var Uz=async(e,t)=>{if(!t)throw new Error("proposalId required");let n=await J({id:e.id,cwd:e.cwd}),r=n.find(o=>o.type==="planning.change.offered"&&o.payload?.proposalId===t);if(!r)throw new Error("unknown proposal");if(n.some(o=>o.type==="planning.change.answered"&&o.payload?.proposalId===t))throw new Error("proposal already answered");return r};async function AN(e,t,n,{results:r=[]}={}){if(!["applied","dismiss","moved"].includes(n))throw new Error("action must be one of applied | dismiss | moved");let o=await Uz(e,t),s={id:e.id,cwd:e.cwd},a=o.payload;return n==="applied"&&await D(s,{type:"planning.changed",actor:"user",source:"orchestrator",payload:{ts:Date.now(),proposalId:t,why:a.why??"",results:Array.isArray(r)?r.slice(0,d0+1):[]}}),await D(s,{type:"planning.change.answered",actor:"user",source:"orchestrator",payload:{ts:Date.now(),proposalId:t,action:n,ops:a.ops?.length??0}}),{proposalId:t,action:n}}tf();ke();no();ke();zn();yf();var TN=10,EN=200,Hz=120,Wz=24,IN=/^\d{4}-\d{2}-\d{2}$/;function h0(e=process.env){return(e.CHANGELOG_REPOS||"globocodes/bostrat").split(",").map(t=>t.trim()).filter(Boolean)}var qz=(e=Date.now())=>new Date(e).toISOString().slice(0,10),$t=(e,t="i")=>new RegExp(e,t),Gz=[{re:$t("^(business|docs|chore|ci|refactor|test|security|sec)(\\([^)]*\\))?!?:"),reason:"non-product PR prefix"},{re:$t("\\bSPC\\b",""),reason:"business (SPC)"},{re:$t("kickstarter|pitch deck|investor|fundrais|commercial ladder|/seat\\b|price[- ]test"),reason:"business"},{re:$t("competitor|cloudcli|\\bkiro\\b"),reason:"competitor research"},{re:$t("\\bReplicas\\b",""),reason:"competitor research"},{re:$t("tenanc|tenant|perimeter|ip[- ]gate|access[- ]code|vulnerab|\\bCVE\\b|audit|hardening|security|\\bsweep\\b"),reason:"security / tenancy"},{re:$t("\\bF-\\d+\\b|\\bBOS-\\d+\\b|\\bAC-D\\d"),reason:"internal codename"},{re:$t("^track/(business|security|spc|sec)-"),reason:"non-product branch"}],Kz=[$t("\\bSPC\\b",""),$t("kickstarter|pitch deck|investor|fundrais|commercial ladder|/seat\\b|price[- ]test"),$t("competitor|cloudcli|\\bkiro\\b"),$t("\\bReplicas\\b",""),$t("tenanc|\\btenants?\\b|cross-tenant|perimeter|ip[- ]gate|vulnerab|\\bCVE\\b|hardening|security register|audit finding"),$t("\\bF-\\d+\\b|\\bBOS-\\d+\\b|\\bAC-D\\d"),$t("(^|[^\\w&])#\\d+\\b"),$t("\\btrack/[\\w.-]+")];function Vz({title:e="",headRef:t=""}={}){let n=String(e||""),r=String(t||"");for(let{re:o,reason:s}of Gz)if(o.test(n)||o.test(r))return s;return null}function _N(e){let t=String(e||"");for(let n of Kz){let r=n.exec(t);if(r)return r[0].trim()}return null}function $N(e,t=Date.now()){if(!e)return t-24*36e5;let n=/^(\d+)\s*([hd])$/.exec(String(e).trim());if(n)return t-Number(n[1])*(n[2]==="h"?36e5:24*36e5);let r=Date.parse(e);if(!Number.isNaN(r))return r;throw new Error(`unparseable since "${e}" \u2014 use 24h, 7d, or an ISO date`)}var zz=/^\*\*([^*]+?)\*\*\s*[:.]?\s*[—–-]?\s*(.*)$/;function Jz(e){if(typeof e!="string"||!e.trim())throw new Error("md (markdown string) required");let t=Ll(e);if(t.length)throw new Error(`changelog entry appears to contain a secret VALUE (${t.join(", ")}) \u2014 entries ship off-box; never put a credential in one. Replace it and retry.`);let n=null,r=[];for(let o of e.split(`
822
- `)){let s=o.trim();if(!s)continue;if(s.startsWith("#")){n==null&&(n=s.replace(/^#+\s*/,"").trim().slice(0,Hz)||null);continue}let a=/^[-*]\s+(.*)$/.exec(s);if(!a)continue;let i=a[1].trim(),c=null,l=new RegExp(`^\\[([^\\]]{1,${Wz}})\\]\\s+(.*)$`).exec(i);if(l&&(c=l[1].trim(),i=l[2].trim()),!i)continue;let u=zz.exec(i);if(!u||!u[1].trim()||!u[2].trim())throw new Error(`bullet ${r.length+1} must be \`**Short summary** \u2014 the item, one sentence.\` (bold summary title, em dash, then the change) \u2014 got "${i.slice(0,80)}". Rewrite it and re-publish.`);i=`**${u[1].trim().replace(/[:.]\s*$/,"")}** \u2014 ${u[2].trim()}`;let d=_N(i);if(d)throw new Error(`bullet ${r.length+1} mentions "${d}" \u2014 the product changelog never carries business, security/tenancy or internal-ops items, PR numbers, branch names or codenames; drop the bullet or rewrite it as the user-visible change and re-publish.`);if(i.length>EN)throw new Error(`bullet ${r.length+1} is ${i.length} chars \u2014 over the ${EN}-char cap; a changelog bullet is one line`);r.push({text:i,...c?{area:c}:{}})}if(n){let o=_N(n);if(o)throw new Error(`headline mentions "${o}" \u2014 the product changelog never carries business, security/tenancy or internal-ops items; rewrite it and re-publish.`)}if(!r.length)throw new Error("no `- ` bullets found \u2014 an entry is a bullet list, optionally under a `# headline`");if(r.length>TN)throw new Error(`${r.length} bullets \u2014 over the ${TN}-bullet cap; group related changes into one line`);return{title:n||null,bullets:r}}async function Yz(e,{repos:t=h0()}={}){let n=new Set(t);return(await In()).filter(r=>r.state==="merged"&&(r.resolvedAt??0)>=e&&n.has(r.repo)).sort((r,o)=>(r.resolvedAt??0)-(o.resolvedAt??0)).map(r=>({repo:r.repo,number:r.number,title:r.title||null,url:r.url||null,headRef:r.headRef||null,mergedAt:r.resolvedAt??null,excluded:Vz({title:r.title,headRef:r.headRef})}))}async function RN(e,t){let n=await Yz(e,t);return{prs:n.filter(r=>!r.excluded),excluded:n.filter(r=>r.excluded)}}async function ON(e,{md:t,day:n=null}){let r=Jz(t),o=n==null||n===""?qz():String(n);if(!IN.test(o)||Number.isNaN(Date.parse(o)))throw new Error(`invalid day "${n}" \u2014 expected YYYY-MM-DD`);let s=await D({id:e.id,cwd:e.cwd},{type:"changelog.published",actor:"agent",source:"orchestrator",boxId:e.leadBox||null,payload:{ts:Date.now(),day:o,title:r.title,bullets:r.bullets}});return{day:o,title:r.title,bullets:r.bullets,eventId:s.id}}async function MN(e,{day:t}){let n=String(t||"");if(!IN.test(n)||Number.isNaN(Date.parse(n)))throw new Error(`invalid day "${t}" \u2014 expected YYYY-MM-DD`);let r=await D({id:e.id,cwd:e.cwd},{type:"changelog.published",actor:"agent",source:"orchestrator",boxId:e.leadBox||null,payload:{ts:Date.now(),day:n,title:null,bullets:[],retract:!0}});return{day:n,retracted:!0,eventId:r.id}}Oo();zn();Hs();ke();Oo();Tt();Or();zn();ll();Jp();Np();_s();pn();import{execFile as c8}from"node:child_process";import{promisify as l8}from"node:util";var Xz=new Set(["pull_request","check_suite","workflow_run","push"]),Zz=/^[^/\s]+\/[^/\s]+$/,Qz=500,m0=new Set,w0=[],Th=new Map,yn={hourStart:0,byEvent:{},duplicates:0,rejected:0};function g0(e,t,n){let r=Math.floor(e/36e5)*36e5;r!==yn.hourStart&&(yn.hourStart=r,yn.byEvent={},yn.duplicates=0,yn.rejected=0),t==="accepted"?yn.byEvent[n]=(yn.byEvent[n]||0)+1:yn[t]+=1}function e8(e){if(!e||typeof e!="object"||e.forge!=="github"||typeof e.event!="string"||!Xz.has(e.event)||typeof e.repo!="string"||!Zz.test(e.repo))return null;let t=(Array.isArray(e.numbers)?e.numbers:[]).map(Number).filter(r=>Number.isInteger(r)&&r>0),n=Number.isInteger(e.number)&&e.number>0?e.number:t[0]??null;return{forge:"github",deliveryId:typeof e.deliveryId=="string"&&e.deliveryId?e.deliveryId.slice(0,128):null,event:e.event,action:typeof e.action=="string"?e.action.slice(0,64):null,repo:e.repo,number:n,numbers:n&&!t.includes(n)?[n,...t]:t,headSha:typeof e.headSha=="string"?e.headSha.slice(0,64):null,headRef:typeof e.headRef=="string"?e.headRef.slice(0,256):null,baseRef:typeof e.baseRef=="string"?e.baseRef.slice(0,256):null,merged:typeof e.merged=="boolean"?e.merged:null,draft:typeof e.draft=="boolean"?e.draft:null,conclusion:typeof e.conclusion=="string"?e.conclusion.slice(0,64):null,deleted:e.deleted===!0,senderLogin:typeof e.senderLogin=="string"?e.senderLogin.slice(0,128):null,ts:Number.isFinite(e.ts)?e.ts:null}}function CN(e,{now:t=Date.now(),onAccept:n=null,log:r=console}={}){let o=e8(e);if(!o)return g0(t,"rejected"),{ok:!1,error:"malformed github event envelope"};if(o.deliveryId){if(m0.has(o.deliveryId))return g0(t,"duplicates"),{ok:!0,duplicate:!0,envelope:o};for(m0.add(o.deliveryId),w0.push(o.deliveryId);w0.length>Qz;)m0.delete(w0.shift())}let s=o.repo.toLowerCase(),a=Th.get(s)||{lastDeliveryAt:0,count:0};a.lastDeliveryAt=t,a.count+=1,Th.set(s,a),g0(t,"accepted",o.event),r.log?.(`[github-event] ${o.event}${o.action?` ${o.action}`:""} ${o.repo}${o.number?` #${o.number}`:o.headRef?` ${o.headRef}`:""}${o.conclusion?` (${o.conclusion})`:""}${o.deliveryId?` delivery ${o.deliveryId.slice(0,8)}`:""}`);try{n?.(o)}catch(i){r.error?.("[github-event] onAccept failed:",i?.message||i)}return{ok:!0,duplicate:!1,envelope:o}}function t8(e,t=Date.now()){let n=Th.get(String(e||"").toLowerCase());return n?{covered:!0,lastDeliveryAt:n.lastDeliveryAt,ageMs:t-n.lastDeliveryAt,count:n.count}:{covered:!1,lastDeliveryAt:null,ageMs:null,count:0}}var NN=1440*6e4;function y0(e,t=Date.now()){let n=t8(e,t);return n.covered&&n.ageMs<NN}function PN(e=Date.now()){let t={};for(let[n,r]of Th)t[n]={lastDeliveryAt:r.lastDeliveryAt,count:r.count,covered:e-r.lastDeliveryAt<NN};return{hourStart:yn.hourStart,byEvent:{...yn.byEvent},duplicates:yn.duplicates,rejected:yn.rejected,repos:t}}ke();zn();Xr();Or();pn();function DN(e){return(e?.checks?.failed??0)>0?"red":e?.mergeable==="CONFLICTING"?"conflict":e?.mergeStateStatus==="BEHIND"?"behind":null}function n8(e){return!(!e?.checks||e.checks.pending>0||e.mergeabilityPending||e.mergeable==="UNKNOWN"||e.mergeStateStatus==="UNKNOWN")}var r8=new Set(["merged","closed","lost"]);function o8(e,t){if(!e?.blocked)return null;let n=DN(t);if(e.blocked==="red")return t.checks.failed===0&&t.checks.total>0?{change:"ci-fixed",reason:"red"}:null;if(e.blocked==="conflict")return t.mergeable==="MERGEABLE"&&n!=="red"?{change:"reconciled",reason:"conflict"}:null;if(e.blocked==="behind"){let r=t.headSha??null;return n===null&&r&&e.sha&&r!==e.sha?{change:"reconciled",reason:"behind"}:null}return null}function s8(e,t){return e.autoMerge?!0:t==="ci-fixed"?!!(e.ciFix||e.ciFixAwait):t==="reconciled"?!!(e.reconcile||e.reconcileAwait):!1}async function a8(e,t,n,r,o){return(await J(e).catch(()=>[])).some(a=>{if(a.type!=="pr.state.changed"||a.payload?.number!==Number(n))return!1;let i=a.payload?.change;return i===t?a.payload?.sha&&r?a.payload.sha===r:(a.payload?.ts||0)>=o:i==="pushed"&&!!r&&a.payload?.sha===r})}async function i8(e,t,n){await D({id:e.id,cwd:e.cwd},{type:"pr.state.changed",actor:"user",source:"orchestrator",boxId:null,payload:{ts:Date.now(),change:t,...n}})}async function Eh(e,t={}){let{now:n=Date.now(),slugOf:r=De,lookup:o=bt,note:s=r_,tracks:a=async()=>(await xe()).filter(d=>!He(d)),asked:i=a8,emitChange:c=i8}=t,l=[],u=null;for(let d of e??[]){if(!d?.prs?.length)continue;let p=await r(d.path).catch(()=>null);if(p)for(let m of d.prs)try{if(!n8(m))continue;let w=await o(p,m.number).catch(()=>null);if(!w?.trackId||r8.has(w.state))continue;let{prev:h}=await s(p,m.number,{blocked:DN(m),sha:m.headSha??null,at:n});if(!h)continue;let g=o8(h,m);if(!g||s8(w,g.change))continue;u??=new Map((await a()).map(E=>[E.id,E]));let b=u.get(w.trackId);if(!b)continue;let y=m.headSha??null;if(await i(b,g.change,m.number,y,h.at||0))continue;let x={number:Number(m.number),url:m.url||w.url,title:m.title||w.title,branch:m.headRefName||w.headRef,repo:p,sha:y,delegated:!1,reason:g.reason};g.change==="ci-fixed"?x.passed=m.checks.passed:x.base=m.baseRefName||null,await c(b,g.change,x),l.push({change:g.change,number:m.number,reason:g.reason})}catch{}}return l}var T0=l8(c8),KN=3e4,u8=30*6e4,d8=KN,p8=10*6e4,f8=10080*6e4,h8=60*6e4,BN=8,VN=1440*6e4,m8=3,zN="number,url,title,headRefName,headRefOid,state,mergedAt,closedAt",v0=60*6e4,w8=15*6e4,g8=9e4,y8=1440*6e4,Wi=new Map,Ru=new Map,b8=360*6e4,k8=e=>e.reduce((t,n)=>({misses:Math.max(t.misses,n.brokerRefused?.misses||0),until:Math.max(t.until,n.brokerRefused?.until||0)}),{misses:0,until:0}),x8=/could not resolve|not found|no pull requests?/i,v8=e=>x8.test(String(e?.message||e||""));function S8(e,t){return[e.ciFix?.delegatedAt,e.reconcile?.delegatedAt,e.ciFixAwait?.since,e.reconcileAwait?.since].some(n=>n&&t-n<v0)}var LN={fast:d8,slow:p8,decay:h8};function jN(e,t,n=y0){return JN(e,t,{grace:0})||!n(e.repo,t)&&(e.armedAt&&t-e.armedAt<u8||S8(e,t))?"fast":t-(e.firstSeen||0)>f8?"decay":"slow"}function Cu(e,t,n,r){let o=e.lanes?.get(de(t.repo,t.number))||{};return ul({change:n,repo:t.repo,number:Number(t.number),githubAt:r||null,lane:o.lane||null,intervalMs:o.intervalMs||null,source:"watch"})}async function A8(e,t){Ar("watch");try{let{stdout:n}=await T0("gh",["pr","view",String(t),"--repo",e,"--json",zN],{timeout:3e4,maxBuffer:4194304,env:{...process.env,...await Fn({slug:e})}});return JSON.parse(n||"null")}catch(n){throw $o(n)&&Ro(n),n}}async function T8(e){Ar("watch");try{let{stdout:t}=await T0("gh",["pr","list","--repo",e,"--state","all","--limit","100","--json",zN],{timeout:3e4,maxBuffer:8388608,env:{...process.env,...await Fn({slug:e})}}),n=new Map;for(let r of JSON.parse(t||"[]"))n.set(Number(r.number),r);return n}catch(t){throw $o(t)&&Ro(t),t}}async function E8(){let e=new Map;for(let t of await xe().catch(()=>[]))e.set(t.id,t);return e}async function _8(e,t){await D({id:e.id,cwd:e.cwd},{type:"pr.state.changed",actor:"user",source:"orchestrator",boxId:null,payload:{ts:Date.now(),change:"merged",...t}}),await zp(e,t).catch(()=>{})}async function I8(e,t){let n=await Us(e);return n?oi(n,t):null}async function $8(e,t,n){let r=await Us(e);if(!r)throw new Error(`no local checkout for ${e}`);return si(r,t,{method:n})}async function R8(e,t){let n=await Us(e);if(!n)throw new Error(`no local checkout for ${e}`);return pl(n,t)}async function O8(e,t){await D({id:e.id,cwd:e.cwd},{type:"pr.state.changed",actor:"user",source:"orchestrator",boxId:null,payload:{ts:Date.now(),change:"auto-canceled",...t}})}async function Ui(e,t,n,r,o){if(!await r.disarm(e.repo,e.number).catch(()=>null))return;let a=n.get(e.trackId);a&&await r.emitDisarmed(a,{number:Number(e.number),url:t?.url||e.url,title:t?.title||e.title,branch:t?.headRefName||e.headRef,repo:e.repo,reason:o}).catch(()=>{})}var M8=10*6e4,FN=2*6e4,C8=2,N8=5*6e4,_h=new Map,S0=new Map,Ou=new Map,A0=new Map;function Hi(e,t){let n=A0.get(e)??t;return A0.set(e,n),t-n>N8?!1:(Wi.delete(e),!0)}function b0(e){A0.delete(e)}function P8(e,t,n,r){let o=n.headSha||null;if(!o||t==null)return!0;if(o!==t)return _h.set(e,{sha:o,at:r}),!1;if(S0.get(e)===o)return!0;let s=_h.get(e);if(s?.sha===o)return r-s.at>=FN;let a=Date.parse(n.updatedAt||"")||0;return a&&r-a<FN?(_h.set(e,{sha:o,at:r}),!1):!0}function k0(e,t,n,r){let o=Ou.get(e),s=o&&o.kind===t&&o.sha===(n||null)?o.count+1:1;return Ou.set(e,{sha:n||null,kind:t,message:r,count:s}),s>=C8}async function D8(e,t,n,{isHead:r=!0,prevHead:o=null}={}){let s=n.now??Date.now(),a=de(e.repo,e.number),i=e.autoMerge?.armedAt||0;if(i&&s-i>VN){await Ui(e,null,t,n,"auto-merge expired \u2014 checks never settled within 24h");return}let c=await n.detail(e.repo,e.number).catch(()=>null);if(!c)return;if(c.headSha&&e.lastHeadSha!==c.headSha&&await gg(e.repo,e.number,c.headSha).catch(()=>{}),c.checks.failed>0){let u=c.checks.failing.map(d=>d.name).join(", ");await Ui(e,c,t,n,`check${c.checks.failed===1?"":"s"} failed: ${u}`);return}if(c.mergeable==="CONFLICTING"){await Ui(e,c,t,n,`conflicts with ${c.baseRefName}`);return}if(!c.checks.total){let u=Math.max(e.autoMerge?.armedAt||0,Date.parse(c.updatedAt||"")||0);if(s-u<M8)return;if(!k0(a,"no-checks",c.headSha,null)){Hi(a,s);return}await Ui(e,c,t,n,c.checks.unavailable?"this token can't read the checks":"no CI checks appeared");return}if(c.checks.pending>0){c.headSha&&S0.set(a,c.headSha),Ou.delete(a),b0(a);return}if(c.mergeable==="UNKNOWN"||c.mergeStateStatus==="UNKNOWN"){Hi(a,s);return}if(c.isDraft)return;if(!P8(a,o,c,s)){Hi(a,s);return}let l=await n.lookup(e.repo,e.number).catch(()=>null);if(l?.autoMerge){if(c.mergeStateStatus==="BEHIND"){if(!r)return;try{await n.updateBranch(e.repo,e.number),Ou.delete(a),b0(a)}catch(u){let d=String(u?.message||u).trim();if(/no new commits|already up.to.date/i.test(d))return;if(!k0(a,"update",c.headSha,d)){Hi(a,s);return}await Ui(e,c,t,n,d||`couldn't update with ${c.baseRefName}`)}return}if(n.mergedRepos?.has(String(e.repo||"").toLowerCase())){Hi(a,s);return}try{await n.merge(e.repo,e.number,l.autoMerge.method||"merge")}catch(u){let d=String(u?.message||u).trim();if(/already merged|not open|is closed/i.test(d))return;if(!k0(a,"merge",c.headSha,d)){Hi(a,s);return}await Ui(e,c,t,n,d||"merge failed");return}return n.mergedRepos?.add(String(e.repo||"").toLowerCase()),Ou.delete(a),b0(a),_h.delete(a),S0.delete(a),await YN(e,{...c,state:"MERGED"},t,n,{change:"auto-merged",githubAt:c.checks.settledAt||null}),"merged"}}async function qi(e,t,n){await D({id:e.id,cwd:e.cwd},{type:"pr.state.changed",actor:"user",source:"orchestrator",boxId:null,payload:{ts:Date.now(),change:t,...n}})}async function B8(e,t){try{return await T0("git",["-C",e.cwd,"cat-file","-e",`${t}^{commit}`],{timeout:1e4}),!0}catch{return!1}}async function Mu(e,t,n,r=()=>!0){return(await J(e).catch(()=>[])).some(s=>s.type==="pr.state.changed"&&s.payload?.change===t&&s.payload?.number===Number(n)&&r(s))}var Gi=(e,t)=>({number:Number(e.number),url:t?.url||e.url,title:t?.title||e.title,branch:t?.headRefName||e.headRef,repo:e.repo});function JN(e,t,{grace:n=g8}={}){if(e.announced!==!1)return!1;let r=t-(e.firstSeen||0);return r>=n&&r<=y8}async function L8(e,t,n,r){let o=r.now??Date.now();if(!JN(e,o))return!1;let s=n.get(e.trackId)||null;if(!s||He(s))return!1;let a=(s.boxes||[]).find(d=>d.name===s.leadBox);return await(r.midTurn??Es)(s.leadBox,a?.agent).catch(()=>!1)?!1:(await J(s).catch(()=>[])).some(d=>d.type==="pr.state.changed"&&d.payload?.number===Number(e.number))?(await(r.claim??vr)(e.repo,e.number).catch(()=>null),!1):await(r.claim??vr)(e.repo,e.number).catch(()=>null)?(await Er({repo:e.repo,number:e.number,via:"watch"}).catch(()=>{}),await qi(s,"opened",{...Gi(e,t),announcedBy:"watch"}).catch(()=>{}),console.log(`[pr-watch] announced passive link ${e.repo}#${e.number} \u2192 track ${s.id} (no active door claimed it)`),!0):!1}async function j8(e,t,n,r){let o=r.now??Date.now(),s=t.headRefOid||null,a=n.get(e.trackId)||null;if(s&&(e.ciFix?.headSha&&s!==e.ciFix.headSha&&await Ep(e.repo,e.number,{headSha:s}).catch(()=>{}),e.reconcile?.headSha&&s!==e.reconcile.headSha&&await Ip(e.repo,e.number,{headSha:s}).catch(()=>{})),s&&s!==e.lastHeadSha){let i=!e.lastHeadSha,c=!!(e.ciFix||e.reconcile||e.ciFixAwait||e.reconcileAwait),l=!!e.baseFoldAt&&o-e.baseFoldAt<w8;await gg(e.repo,e.number,s).catch(()=>{}),e.baseFoldAt&&await n_(e.repo,e.number).catch(()=>{}),!i&&!c&&!l&&a&&!await r.localHasCommit(a,s).catch(()=>!1)&&!await Mu(a,"pushed",e.number,d=>d.payload?.sha===s)&&await qi(a,"pushed",{...Gi(e,t),sha:s}).catch(()=>{})}if(e.ciFixAwait)if(o-(e.ciFixAwait.since||0)>v0)await _p(e.repo,e.number).catch(()=>{});else{let i=await r.detail(e.repo,e.number).catch(()=>null);if(i?.checks){if(i.checks.failed>0)await _p(e.repo,e.number).catch(()=>{});else if(i.checks.total>0&&i.checks.pending===0){let c=Cu(r,e,"ci-fixed",i.checks.settledAt||null),l=e.ciFixAwait.since||0;a&&!await Mu(a,"ci-fixed",e.number,u=>(u.payload?.ts||0)>=l)&&await qi(a,"ci-fixed",{...Gi(e,t),sha:s,delegated:!0,passed:i.checks.passed,githubAt:c.githubAt,latencyMs:c.latencyMs,lane:c.lane}).catch(()=>{}),await _p(e.repo,e.number).catch(()=>{})}}}if(e.reconcileAwait)if(o-(e.reconcileAwait.since||0)>v0)await $p(e.repo,e.number).catch(()=>{});else{let i=await r.detail(e.repo,e.number).catch(()=>null);if(i){if(i.mergeable==="CONFLICTING")await $p(e.repo,e.number).catch(()=>{});else if(i.mergeable==="MERGEABLE"){Cu(r,e,"reconciled",null);let c=e.reconcileAwait.since||0;a&&!await Mu(a,"reconciled",e.number,l=>(l.payload?.ts||0)>=c)&&await qi(a,"reconciled",{...Gi(e,t),sha:s,delegated:!0,base:i.baseRefName||null}).catch(()=>{}),await $p(e.repo,e.number).catch(()=>{})}}}}async function F8(e,t,n,r){let o=Cu(r,e,"closed",Date.parse(t?.closedAt||"")||null),s=n.get(e.trackId);s&&!await Mu(s,"closed",e.number)&&await qi(s,"closed",{...Gi(e,t),githubAt:o.githubAt,latencyMs:o.latencyMs,lane:o.lane}).catch(()=>{}),await r.notifyIfResolved(e.repo,e.number,"closed").catch(()=>{}),await r.mark(e.repo,e.number,"closed").catch(()=>{})}async function UN(e,t,n){Cu(n,e,"lost",null);let r=t.get(e.trackId);r&&!await Mu(r,"lost",e.number)&&await qi(r,"lost",Gi(e,null)).catch(()=>{}),await n.notifyIfResolved(e.repo,e.number,"lost").catch(()=>{}),await n.mark(e.repo,e.number,"lost").catch(()=>{})}async function YN(e,t,n,r,o={}){let s=Cu(r,e,o.change||"merged",o.githubAt??(Date.parse(t.mergedAt||"")||null)),a=n.get(e.trackId);a&&((await J(a).catch(()=>[])).some(l=>l.type==="pr.state.changed"&&l.payload?.change==="merged"&&l.payload?.number===Number(e.number))||await r.emitMerged(a,{number:Number(e.number),url:t.url||e.url,title:t.title||e.title,branch:t.headRefName||e.headRef,repo:e.repo,githubAt:s.githubAt,latencyMs:s.latencyMs,lane:s.lane}).catch(()=>{})),await r.notifyIfArmed(e.repo,e.number).catch(()=>{}),await r.followupsIfMerged(e.repo,e.number).catch(()=>{}),await r.archiveIfArmed(e.repo,e.number).catch(()=>{}),await r.mark(e.repo,e.number,"merged").catch(()=>{})}async function HN(e={}){let{now:t=Date.now(),auth:n=vg,view:r=A8,list:o=T8,links:s=a_,trackMap:a=E8,emitMerged:i=_8,mark:c=_o,archiveIfArmed:l=$r,notifyIfArmed:u=Rr,notifyIfResolved:d=Uf,followupsIfMerged:p=ta,batchThreshold:m=m8,detail:w=I8,merge:h=$8,updateBranch:g=R8,lookup:b=bt,disarm:y=cl,emitDisarmed:x=O8,localHasCommit:E=B8,claim:A=vr,midTurn:$=Es,only:P=null,wantDetail:L=null,covered:T=y0,verdicts:C=null,tokenFor:j=Q=>ka(Q),noteRefusal:K=e_,clearRefusal:M=t_}=e;if(!(await n().catch(()=>null))?.authenticated||Mp()>0)return 0;let S=await s().catch(()=>[]),U=P_(S),W=Q=>{try{return!!L?.(Q)}catch{return!1}},ie=P?S.filter(Q=>{try{return P(Q)}catch{return!1}}):S.filter(Q=>t-(Wi.get(de(Q.repo,Q.number))||0)>=LN[jN(Q,t,T)]);if(!ie.length)return 0;let z=Date.now(),Ge=new Map,_e=new Map;for(let Q of[...ie].sort(fl)){let he=P?"event":jN(Q,t,T);Ge.set(de(Q.repo,Q.number),{lane:he,intervalMs:LN[he]??null}),Wi.set(de(Q.repo,Q.number),t),_e.has(Q.repo)||_e.set(Q.repo,[]),_e.get(Q.repo).push(Q)}let Y=await a().catch(()=>new Map),ne=new Map,Ie=(Q,he)=>{let Ue=de(Q,he);if(!ne.has(Ue)){let nt=Promise.resolve().then(()=>w(Q,he));nt.catch(()=>{}),ne.set(Ue,nt)}return ne.get(Ue)},Pe=C??((Q,he)=>Eh([{path:Q,prs:[he]}],{now:t,slugOf:async()=>Q,tracks:async()=>[...Y.values()].filter(Ue=>!He(Ue))}).catch(()=>{})),Ae={now:t,lanes:Ge,emitMerged:i,mark:c,archiveIfArmed:l,notifyIfArmed:u,notifyIfResolved:d,followupsIfMerged:p,detail:Ie,merge:h,updateBranch:g,lookup:b,disarm:y,emitDisarmed:x,localHasCommit:E,claim:A,midTurn:$,mergedRepos:new Set};for(let[Q,he]of _e){let Ue=k8(he);if(Ue.until>t)continue;let nt=!1;try{if(await j(Q),Ue.misses)for(let le of he)await M(le.repo,le.number).catch(()=>{})}catch(le){nt=Lx(le)}if(nt){let le=Ue.misses+1;if(le>=BN){console.log(`[pr-watch] ${Q}: not granted ${le}\xD7 \u2014 retiring ${he.length} link(s) as lost`);for(let ve of he){await UN(ve,Y,Ae);let Ye=de(ve.repo,ve.number);Ru.delete(Ye),Wi.delete(Ye)}}else for(let ve of he)await K(ve.repo,ve.number,{misses:le,until:t+b8}).catch(()=>{});continue}let rt,N=new Set,se=le=>le.ciFixAwait||le.reconcileAwait||W(le)?!0:le.autoMerge?t-(le.autoMerge.armedAt||0)<=VN:!1;if(he.length>m)rt=await o(Q).catch(()=>null);else{rt=new Map;for(let le of he){if(se(le)){let ve=await Ie(Q,le.number).catch(()=>null);if(ve?.state){rt.set(Number(le.number),{number:Number(le.number),url:ve.url,title:ve.title,headRefName:ve.headRefName,headRefOid:ve.headSha??null,state:ve.state,mergedAt:ve.mergedAt??null,closedAt:ve.closedAt??null});continue}}try{let ve=await r(Q,le.number);ve?.number!=null&&rt.set(Number(ve.number),ve)}catch(ve){v8(ve)&&N.add(de(le.repo,le.number))}}}if(rt)for(let le of he){let ve=de(le.repo,le.number),Ye=rt.get(Number(le.number));if(!Ye){if(N.has(ve)){let Fe=(Ru.get(ve)||0)+1;Ru.set(ve,Fe),Fe>=BN&&(await UN(le,Y,Ae),Ru.delete(ve),Wi.delete(ve))}continue}if(Ru.delete(ve),Ye.state==="MERGED"||Ye.state==="CLOSED")Ye.state==="MERGED"?await YN(le,Ye,Y,Ae):await F8(le,Ye,Y,Ae),Wi.delete(ve);else{let Fe=le.lastHeadSha??null;await L8(le,Ye,Y,Ae).catch(()=>{}),await j8(le,Ye,Y,Ae).catch(()=>{});let Zt=D_(U,le);le.autoMerge&&await D8(le,Y,Ae,{isHead:Zt,prevHead:Fe}).catch(()=>{});try{if(W(le)&&!ne.has(ve)&&Ie(le.repo,le.number),ne.has(ve)){let ut=await ne.get(ve).catch(()=>null);ut?.checks&&await Pe(le.repo,ut)}}catch{}}}}let be={};for(let{lane:Q}of Ge.values())be[Q]=(be[Q]||0)+1;return console.log(`[pr-watch] probed ${ie.length} link(s) (${Object.entries(be).map(([Q,he])=>`${Q} ${he}`).join(", ")}) in ${Date.now()-z}ms`),ie.length}function WN(e,t){return!e||!t?!1:e.all?!0:String(t.repo||"").toLowerCase()!==e.repo?!1:e.numbers?.length?e.numbers.includes(Number(t.number)):e.event==="push"?!!e.branch&&t.headRef===e.branch||!!t.autoMerge:e.branch?t.headRef===e.branch:!0}var x0=!1,Ih=!1,$h=[],qN=Promise.resolve();async function U8(){for(;Ih||$h.length;){if(Ih){Ih=!1;try{await HN()}catch{}continue}let e=$h;$h=[];let t=e.map(r=>r.spec),n=Object.assign({},...e.map(r=>r.deps||{}));try{await HN({...n,only:r=>t.some(o=>WN(o,r)),wantDetail:r=>t.some(o=>o.detail&&WN(o,r))})}catch{}}}function Rh(e,t){return e===null?Ih=!0:$h.push({spec:e,deps:t}),x0||(x0=!0,qN=U8().finally(()=>{x0=!1})),qN}function XN(e,t=void 0){let n=String(e?.repo||"").toLowerCase();if(!/^[^/\s]+\/[^/\s]+$/.test(n))return Promise.resolve();let r=(Array.isArray(e.numbers)?e.numbers:[]).map(Number).filter(o=>Number.isInteger(o)&&o>0);return Rh({repo:n,numbers:r,branch:e.branch||null,event:e.event||null,detail:e.detail===!0},t)}var H8=6e4,GN=0;function ZN(e=void 0){let t=e?.now??Date.now();return t-GN<H8?Promise.resolve():(GN=t,Rh({all:!0},e))}function QN(){Rh(null),setInterval(()=>Rh(null),KN)}Oo();Yp();Nl();Or();pn();var W8=new Set(["opened","reopened","closed","synchronize","ready_for_review","converted_to_draft","edited"]);async function q8({tracks:e=xe,reconcile:t=pf}={}){for(let n of(await e().catch(()=>[])).filter(r=>!He(r)))await t(n,{bypassThrottle:!0}).catch(()=>{})}function eP(e,t={}){let{invalidate:n=hn,probe:r=XN,poke:o=yI,reconcileOpened:s=q8,noteOpenedWebhook:a=$_}=t;try{n()}catch{}let i={probe:null,poked:!1,reconciled:!1};if(!e?.repo)return i;if(e.event==="pull_request"&&W8.has(e.action)){if(e.action==="opened"||e.action==="reopened"){i.poked=!0,i.reconciled=!0;for(let c of e.numbers||[])try{a({repo:e.repo,number:c})}catch{}try{o()}catch{}s()}i.probe={repo:e.repo,numbers:e.numbers,branch:e.headRef||null,event:e.event}}else(e.event==="check_suite"||e.event==="workflow_run")&&e.action==="completed"?i.probe={repo:e.repo,numbers:e.numbers,branch:e.headRef||null,event:e.event,detail:!0}:e.event==="push"&&!e.deleted&&(i.probe={repo:e.repo,branch:e.headRef||null,event:"push"});return i.probe&&r(i.probe),i}mt();ke();Or();pn();_s();gl();rl();import{randomUUID as G8}from"node:crypto";var $0=2e4,tP=3,Ki=new Map,E0=new Set;async function nP(e,t,n){let r=await n(e).catch(()=>[]),o=null;for(let s of r)s.type==="box.fullscreen.detected"&&s.boxId===t?o=s.payload?.offerId||null:s.type==="box.fullscreen.answered"&&o&&s.payload?.offerId===o&&(o=null);return o}async function K8(e={}){let{sessions:t=null,tracks:n=null,append:r=D,read:o=J,now:s=Date.now()}=e;if(process.env.BOSTRAT_CLAUDE_ALT_SCREEN==="1")return;let a,i;try{a=t??await en(),i=n??await xe()}catch{return}let c=new Map(a.map(u=>[u.name,u])),l=new Set;for(let u of i){if(He(u)||!u.leadBox)continue;let d=(u.boxes||[]).find(m=>m.name===u.leadBox);if(!d||d.agent!=="claude"||d.state!=="live")continue;let p=c.get(d.name);if(p)if(l.add(d.name),p.alternateOn){let m=(Ki.get(d.name)||0)+1;Ki.set(d.name,m),m===tP&&(E0.add(d.name),await nP(u,d.name,o)||await r(u,{type:"box.fullscreen.detected",actor:"system",source:"orchestrator",boxId:d.name,provider:d.agent,payload:{ts:s,offerId:G8(),box:d.name,agent:d.agent}}).catch(()=>{}))}else{let m=(Ki.get(d.name)||0)>=tP;if(Ki.delete(d.name),m||!E0.has(d.name)){E0.add(d.name);let w=await nP(u,d.name,o);w&&await r(u,{type:"box.fullscreen.answered",actor:"system",source:"orchestrator",boxId:d.name,provider:d.agent,payload:{ts:s,offerId:w,action:"cleared"}}).catch(()=>{})}}}for(let u of[...Ki.keys()])l.has(u)||Ki.delete(u)}var V8=2,_0=12e4,z8=360*6e4,J8=new Set(["merged","conflict","canceled","failed","handed-off"]),qr=new Map;async function Y8(e={}){let{sessions:t=null,tracks:n=null,append:r=D,read:o=J,now:s=Date.now(),turnState:a=fo,recentRead:i=HA,cliDead:c=ou,busyAt:l=UA,reportLoop:u=$s,boot:d=!1}=e,p,m;try{p=t??await en(),m=n??await xe()}catch{return}let w=new Map(p.map(g=>[g.name,g])),h=new Set;for(let g of m){if(He(g)||!g.leadBox||g.archivedAt||g.transferredTo)continue;let b=(g.boxes||[]).find(M=>M.name===g.leadBox);if(!b||J8.has(b.state))continue;let y=w.get(b.name),x=l(b.name),E=x!=null&&s-x<=_0,A=null;if(y){h.add(b.name);let M=i(b.name,$0),I=M?{working:M.busy,prompted:!1}:await a(b.name,b.agent).catch(()=>({working:!1,prompted:!1}));if(I.working||I.prompted||I.awaitingBackground){qr.delete(b.name);continue}let S=l(b.name);if(!(S!=null&&s-S<=_0)&&!d){qr.delete(b.name);continue}if(!await c(y).catch(()=>!1)){qr.delete(b.name);continue}let W=(qr.get(b.name)||0)+1;if(qr.set(b.name,W),W<V8)continue;A="cli-exited"}else{if(!E&&!d)continue;A="session-gone"}let $=await o(g).catch(()=>[]),P=li($),L=0;for(let M of $)M.type==="turn.interrupted"&&(M.payload?.result==="stopped"||M.payload?.result==="stopped-late")&&(L=Math.max(L,M.payload?.ts??M.ts??0));if(Math.max(P.abortedAt,L)>P.askedAt)continue;let T=l(b.name),C=b.agent==="claude"?P.hookClosedAt:P.closedAt,j=T!=null&&s-T<=_0&&C<=T,K=d&&AI($)&&s-P.askedAt<=z8;if(!j&&!K){qr.delete(b.name);continue}await r(g,{type:"turn.aborted",actor:"system",source:"orchestrator",boxId:b.name,provider:b.agent,payload:{ts:s,cause:A,turnTs:P.askedAt||null,box:b.name,agent:b.agent,evidence:j?"busy-read":"log",...y?.createdMs?{sessionAgeMs:s-y.createdMs}:{}}}).catch(()=>{}),qr.delete(b.name),String(g.name||"").startsWith("\u21BB")&&u(g,{provider:b.agent,note:`run ${A==="session-gone"?"lost its session":"CLI exited"} mid-turn`}).catch(()=>{})}for(let g of[...qr.keys()])h.has(g)||qr.delete(g)}var Nu=null,I0=!1,Oh=null;function rP(){if(Nu)return()=>{};let e=(t=!1)=>{I0||(I0=!0,K8().catch(()=>{}).then(()=>Y8({boot:t})).catch(()=>{}).finally(()=>{I0=!1}))};return Nu=setInterval(()=>e(!1),$0),Nu.unref?.(),Oh=setTimeout(()=>e(!0),Math.min($0,15e3)),Oh.unref?.(),()=>{clearInterval(Nu),clearTimeout(Oh),Nu=null,Oh=null}}Ds();Nl();ke();Oo();Hs();Ds();bl();import{randomUUID as X8}from"node:crypto";async function Z8(){let e=await Promise.resolve().then(()=>(Or(),KO));return{sayToLead:e.sayToLead,queueShipCompleteNotify:e.queueShipCompleteNotify}}var R0={listRepoPrs:Jn,readEvents:J,appendEvent:D,sayDeps:Z8,currentBranch:Mo};async function Q8(e,t=R0,{branch:n=null}={}){if(!e?.cwd)return null;let r=n||await(t.currentBranch??Mo)(e.workspace?.kind==="multi"?null:e.cwd).catch(()=>null)||e?.workspace?.branch;if(!r)return null;let o;try{o=await t.listRepoPrs(e.cwd,{caller:"pr-exists"})}catch{return null}let s=(o||[]).find(a=>a.headRefName===r);return s?{number:s.number,url:s.url??null,title:s.title??null}:null}async function O0(e,t,{actions:n,notify:r=!1}={},o=R0){let s=t?.payload||{};if(!Array.isArray(n)||!n.includes("pr")||s.toPr||Array.isArray(s.repos)&&s.repos.length||!s.branch)return null;let a=await Q8(e,o,{branch:s.branch});if(!a)return null;let i={id:e.id,cwd:e.cwd};await o.appendEvent(i,{type:"pr.offer.answered",actor:"user",source:"orchestrator",boxId:t.boxId,payload:{ts:Date.now(),offerId:s.offerId,action:"pr-exists",actions:n,...r?{notify:!0}:{},existingPr:{number:a.number}}});let c=X8();return await o.appendEvent(i,{type:"pr.exists.offered",actor:"system",source:"orchestrator",boxId:t.boxId,payload:{ts:Date.now(),offerId:c,srcOfferId:s.offerId??null,branch:s.branch,base:s.base??null,pr:a,actions:n,...r?{notify:!0}:{},offeredRebase:Array.isArray(s.offered)&&s.offered.includes("rebase")}}),{offerId:c,pr:a}}async function M0(e,{offerId:t,choice:n}={},r=R0){if(!t)throw new Error("offerId required");if(!["push","new","dismiss"].includes(n))throw new Error('choice "push" | "new" | "dismiss" required');return No(`prx:${e.id}:${t}`,()=>eJ(e,{offerId:t,choice:n},r))}async function eJ(e,{offerId:t,choice:n},r){let o=await r.readEvents(e),s=o.find(u=>u.type==="pr.exists.offered"&&u.payload?.offerId===t);if(!s)throw new Error("unknown offer");if(o.some(u=>u.type==="pr.exists.answered"&&u.payload?.offerId===t))throw new Error("offer already answered");let a=s.payload||{},i=Array.isArray(a.actions)&&a.actions.length?a.actions:["commit","push","pr"],c=null,l=null;if(n==="push"){let{sayToLead:u}=await r.sayDeps();l=Eo.filter(d=>d!=="pr"&&(i.includes(d)||d==="push")),c=await u(e.id,ei(l,{branch:a.branch??null,base:a.base??null,toPr:{number:a.pr?.number??null},offeredRebase:a.offeredRebase===!0}),{kind:"push-go"})}else if(n==="new"){let{sayToLead:u}=await r.sayDeps();l=i,c=await u(e.id,UE(i,{branch:a.branch??null,base:a.base??null,prNumber:a.pr?.number??null,offeredRebase:a.offeredRebase===!0}),{kind:"pr-go"})}if(await r.appendEvent({id:e.id,cwd:e.cwd},{type:"pr.exists.answered",actor:"user",source:"orchestrator",boxId:s.boxId,payload:{ts:Date.now(),offerId:t,choice:n,...n==="push"&&Number.isFinite(Number(a.pr?.number))?{number:Number(a.pr.number)}:{},...l?{actions:l}:{}}}),n!=="dismiss"&&a.notify===!0){let{queueShipCompleteNotify:u}=await r.sayDeps();u(e.id,{actions:l})}return{say:c,choice:n}}bl();import Gr from"node:fs/promises";import Vi from"node:path";import uP from"node:os";import oP from"node:fs/promises";import Mh from"node:path";import{execFile as tJ}from"node:child_process";import{promisify as nJ}from"node:util";import{fileURLToPath as rJ}from"node:url";var oJ=nJ(tJ),aP=Mh.dirname(rJ(import.meta.url)),sJ=Mh.resolve(aP,"..","..","client","dist"),aJ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",iJ=new Map([...aJ].map((e,t)=>[e,t]));function cJ(e){let t=[],n=0,r=0;for(let o of e){let s=iJ.get(o);if(s===void 0)return t;n+=(s&31)<<r,s&32?r+=5:(t.push(n&1?-(n>>>1):n>>>1),n=0,r=0)}return t}function lJ(e){let t=[],n=0,r=0,o=0;for(let s of e.split(";")){let a=[],i=0;if(s)for(let c of s.split(",")){let l=cJ(c);l.length!==0&&(i+=l[0],l.length>=4&&(n+=l[1],r+=l[2],o+=l[3],a.push([i,n,r,o])))}t.push(a)}return t}function uJ(e,t){if(!e||e.length===0||e[0][0]>t)return null;let n=0,r=e.length-1;for(;n<r;){let o=n+r+1>>1;e[o][0]<=t?n=o:r=o-1}return e[n]}var sP=new Map;async function dJ(e){let t;try{t=await oP.stat(e)}catch{return null}let n=sP.get(e);if(n&&n.mtimeMs===t.mtimeMs)return n;try{let r=JSON.parse(await oP.readFile(e,"utf8")),o={mtimeMs:t.mtimeMs,sources:r.sources||[],lines:lJ(r.mappings||"")};return sP.set(e,o),o}catch{return null}}var C0=null;function pJ(){return C0||(C0=process.env.BOSTRAT_RELEASE?Promise.resolve(process.env.BOSTRAT_RELEASE):oJ("git",["rev-parse","--short","HEAD"],{cwd:Mh.resolve(aP,"..","..")}).then(e=>e.stdout.trim()).catch(()=>null)),C0}var fJ=/(?:https?:\/\/[^\s()]*)?\/assets\/([^\s()/]+\.js):(\d+):(\d+)/g;async function hJ(e,{distDir:t=sJ}={}){let n=[],r=0,o=!1;for(let s of e.matchAll(fJ)){let[a,i,c,l]=s,u=await dJ(Mh.join(t,"assets",`${i}.map`)),d=u?uJ(u.lines[Number(c)-1],Number(l)-1):null;if(n.push(e.slice(r,s.index)),d&&u.sources[d[1]]){let p=u.sources[d[1]].replace(/^(\.\.\/)+/,"");n.push(`${p}:${d[2]+1}:${d[3]+1}`),o=!0}else n.push(a);r=s.index+a.length}return n.push(e.slice(r)),{stack:n.join(""),symbolicated:o}}async function iP(e,t={}){try{if(!e?.error?.stack||!e.release||e.release==="unknown")return e;let n=t.release??await pJ();if(!n||e.release!==n)return e;let{stack:r,symbolicated:o}=await hJ(e.error.stack,t);o&&(e.error.stack=r,e.error.symbolicated=!0)}catch{}return e}var mJ=()=>process.env.BOSTRAT_STATE_DIR||Vi.join(process.env.HOME||uP.tmpdir(),".bostrat"),ts=()=>Vi.join(mJ(),"telemetry"),dP=()=>Vi.join(ts(),".relay-offsets.json"),wJ=50,gJ=14,yJ=3e4,cP=500,ln=(e,t)=>typeof e=="string"?e.slice(0,t):"";function bJ(e,t){if(!e||typeof e!="object")return null;let n=ln(e.name,64);if(!n)return null;let r=Number.isFinite(e.ts)?e.ts:t,o={name:n,ts:Math.abs(r-t)<168*3600*1e3?r:t,receivedAt:t,anonId:ln(e.anonId,64),sessionId:ln(e.sessionId,64),userId:ln(e.userId,64),release:ln(e.release,64),appVersion:ln(e.appVersion,32),route:ln(e.route,128),deviceClass:e.deviceClass==="phone"||e.deviceClass==="desktop"?e.deviceClass:""};return e.props&&typeof e.props=="object"&&!Array.isArray(e.props)&&(JSON.stringify(e.props).length<=8192?o.props=e.props:o.props={clamped:!0}),e.error&&typeof e.error=="object"&&(o.error={kind:ln(e.error.kind,256),message:ln(e.error.message,8192),stack:ln(e.error.stack,32768),fingerprint:ln(e.error.fingerprint,64)}),Array.isArray(e.breadcrumbs)&&(o.breadcrumbs=e.breadcrumbs.slice(-50).map(s=>({t:Number.isFinite(s?.t)?s.t:0,n:ln(s?.n,64),r:ln(s?.r,128)}))),o}var pP=e=>new Date(e).toISOString().slice(0,10),lP=0;async function fP(e,t=Date.now()){let r=(Array.isArray(e?.events)?e.events.slice(0,wJ):[]).map(s=>bJ(s,t)).filter(Boolean);if(!r.length)return 0;for(let s of r)s.error?.stack&&await iP(s);await Gr.mkdir(ts(),{recursive:!0});let o=Vi.join(ts(),`${pP(t)}.ndjson`);return await Gr.appendFile(o,r.map(s=>JSON.stringify(s)+`
822
+ `)){let s=o.trim();if(!s)continue;if(s.startsWith("#")){n==null&&(n=s.replace(/^#+\s*/,"").trim().slice(0,Hz)||null);continue}let a=/^[-*]\s+(.*)$/.exec(s);if(!a)continue;let i=a[1].trim(),c=null,l=new RegExp(`^\\[([^\\]]{1,${Wz}})\\]\\s+(.*)$`).exec(i);if(l&&(c=l[1].trim(),i=l[2].trim()),!i)continue;let u=zz.exec(i);if(!u||!u[1].trim()||!u[2].trim())throw new Error(`bullet ${r.length+1} must be \`**Short summary** \u2014 the item, one sentence.\` (bold summary title, em dash, then the change) \u2014 got "${i.slice(0,80)}". Rewrite it and re-publish.`);i=`**${u[1].trim().replace(/[:.]\s*$/,"")}** \u2014 ${u[2].trim()}`;let d=_N(i);if(d)throw new Error(`bullet ${r.length+1} mentions "${d}" \u2014 the product changelog never carries business, security/tenancy or internal-ops items, PR numbers, branch names or codenames; drop the bullet or rewrite it as the user-visible change and re-publish.`);if(i.length>EN)throw new Error(`bullet ${r.length+1} is ${i.length} chars \u2014 over the ${EN}-char cap; a changelog bullet is one line`);r.push({text:i,...c?{area:c}:{}})}if(n){let o=_N(n);if(o)throw new Error(`headline mentions "${o}" \u2014 the product changelog never carries business, security/tenancy or internal-ops items; rewrite it and re-publish.`)}if(!r.length)throw new Error("no `- ` bullets found \u2014 an entry is a bullet list, optionally under a `# headline`");if(r.length>TN)throw new Error(`${r.length} bullets \u2014 over the ${TN}-bullet cap; group related changes into one line`);return{title:n||null,bullets:r}}async function Yz(e,{repos:t=h0()}={}){let n=new Set(t);return(await In()).filter(r=>r.state==="merged"&&(r.resolvedAt??0)>=e&&n.has(r.repo)).sort((r,o)=>(r.resolvedAt??0)-(o.resolvedAt??0)).map(r=>({repo:r.repo,number:r.number,title:r.title||null,url:r.url||null,headRef:r.headRef||null,mergedAt:r.resolvedAt??null,excluded:Vz({title:r.title,headRef:r.headRef})}))}async function RN(e,t){let n=await Yz(e,t);return{prs:n.filter(r=>!r.excluded),excluded:n.filter(r=>r.excluded)}}async function ON(e,{md:t,day:n=null}){let r=Jz(t),o=n==null||n===""?qz():String(n);if(!IN.test(o)||Number.isNaN(Date.parse(o)))throw new Error(`invalid day "${n}" \u2014 expected YYYY-MM-DD`);let s=await D({id:e.id,cwd:e.cwd},{type:"changelog.published",actor:"agent",source:"orchestrator",boxId:e.leadBox||null,payload:{ts:Date.now(),day:o,title:r.title,bullets:r.bullets}});return{day:o,title:r.title,bullets:r.bullets,eventId:s.id}}async function MN(e,{day:t}){let n=String(t||"");if(!IN.test(n)||Number.isNaN(Date.parse(n)))throw new Error(`invalid day "${t}" \u2014 expected YYYY-MM-DD`);let r=await D({id:e.id,cwd:e.cwd},{type:"changelog.published",actor:"agent",source:"orchestrator",boxId:e.leadBox||null,payload:{ts:Date.now(),day:n,title:null,bullets:[],retract:!0}});return{day:n,retracted:!0,eventId:r.id}}Oo();zn();Hs();ke();Oo();Tt();Or();zn();ll();Jp();Np();_s();pn();import{execFile as c8}from"node:child_process";import{promisify as l8}from"node:util";var Xz=new Set(["pull_request","check_suite","workflow_run","push"]),Zz=/^[^/\s]+\/[^/\s]+$/,Qz=500,m0=new Set,w0=[],Th=new Map,yn={hourStart:0,byEvent:{},duplicates:0,rejected:0};function g0(e,t,n){let r=Math.floor(e/36e5)*36e5;r!==yn.hourStart&&(yn.hourStart=r,yn.byEvent={},yn.duplicates=0,yn.rejected=0),t==="accepted"?yn.byEvent[n]=(yn.byEvent[n]||0)+1:yn[t]+=1}function e8(e){if(!e||typeof e!="object"||e.forge!=="github"||typeof e.event!="string"||!Xz.has(e.event)||typeof e.repo!="string"||!Zz.test(e.repo))return null;let t=(Array.isArray(e.numbers)?e.numbers:[]).map(Number).filter(r=>Number.isInteger(r)&&r>0),n=Number.isInteger(e.number)&&e.number>0?e.number:t[0]??null;return{forge:"github",deliveryId:typeof e.deliveryId=="string"&&e.deliveryId?e.deliveryId.slice(0,128):null,event:e.event,action:typeof e.action=="string"?e.action.slice(0,64):null,repo:e.repo,number:n,numbers:n&&!t.includes(n)?[n,...t]:t,headSha:typeof e.headSha=="string"?e.headSha.slice(0,64):null,headRef:typeof e.headRef=="string"?e.headRef.slice(0,256):null,baseRef:typeof e.baseRef=="string"?e.baseRef.slice(0,256):null,merged:typeof e.merged=="boolean"?e.merged:null,draft:typeof e.draft=="boolean"?e.draft:null,conclusion:typeof e.conclusion=="string"?e.conclusion.slice(0,64):null,deleted:e.deleted===!0,senderLogin:typeof e.senderLogin=="string"?e.senderLogin.slice(0,128):null,ts:Number.isFinite(e.ts)?e.ts:null}}function CN(e,{now:t=Date.now(),onAccept:n=null,log:r=console}={}){let o=e8(e);if(!o)return g0(t,"rejected"),{ok:!1,error:"malformed github event envelope"};if(o.deliveryId){if(m0.has(o.deliveryId))return g0(t,"duplicates"),{ok:!0,duplicate:!0,envelope:o};for(m0.add(o.deliveryId),w0.push(o.deliveryId);w0.length>Qz;)m0.delete(w0.shift())}let s=o.repo.toLowerCase(),a=Th.get(s)||{lastDeliveryAt:0,count:0};a.lastDeliveryAt=t,a.count+=1,Th.set(s,a),g0(t,"accepted",o.event),r.log?.(`[github-event] ${o.event}${o.action?` ${o.action}`:""} ${o.repo}${o.number?` #${o.number}`:o.headRef?` ${o.headRef}`:""}${o.conclusion?` (${o.conclusion})`:""}${o.deliveryId?` delivery ${o.deliveryId.slice(0,8)}`:""}`);try{n?.(o)}catch(i){r.error?.("[github-event] onAccept failed:",i?.message||i)}return{ok:!0,duplicate:!1,envelope:o}}function t8(e,t=Date.now()){let n=Th.get(String(e||"").toLowerCase());return n?{covered:!0,lastDeliveryAt:n.lastDeliveryAt,ageMs:t-n.lastDeliveryAt,count:n.count}:{covered:!1,lastDeliveryAt:null,ageMs:null,count:0}}var NN=1440*6e4;function y0(e,t=Date.now()){let n=t8(e,t);return n.covered&&n.ageMs<NN}function PN(e=Date.now()){let t={};for(let[n,r]of Th)t[n]={lastDeliveryAt:r.lastDeliveryAt,count:r.count,covered:e-r.lastDeliveryAt<NN};return{hourStart:yn.hourStart,byEvent:{...yn.byEvent},duplicates:yn.duplicates,rejected:yn.rejected,repos:t}}ke();zn();Xr();Or();pn();function DN(e){return(e?.checks?.failed??0)>0?"red":e?.mergeable==="CONFLICTING"?"conflict":e?.mergeStateStatus==="BEHIND"?"behind":null}function n8(e){return!(!e?.checks||e.checks.pending>0||e.mergeabilityPending||e.mergeable==="UNKNOWN"||e.mergeStateStatus==="UNKNOWN")}var r8=new Set(["merged","closed","lost"]);function o8(e,t){if(!e?.blocked)return null;let n=DN(t);if(e.blocked==="red")return t.checks.failed===0&&t.checks.total>0?{change:"ci-fixed",reason:"red"}:null;if(e.blocked==="conflict")return t.mergeable==="MERGEABLE"&&n!=="red"?{change:"reconciled",reason:"conflict"}:null;if(e.blocked==="behind"){let r=t.headSha??null;return n===null&&r&&e.sha&&r!==e.sha?{change:"reconciled",reason:"behind"}:null}return null}function s8(e,t){return e.autoMerge?!0:t==="ci-fixed"?!!(e.ciFix||e.ciFixAwait):t==="reconciled"?!!(e.reconcile||e.reconcileAwait):!1}async function a8(e,t,n,r,o){return(await J(e).catch(()=>[])).some(a=>{if(a.type!=="pr.state.changed"||a.payload?.number!==Number(n))return!1;let i=a.payload?.change;return i===t?a.payload?.sha&&r?a.payload.sha===r:(a.payload?.ts||0)>=o:i==="pushed"&&!!r&&a.payload?.sha===r})}async function i8(e,t,n){await D({id:e.id,cwd:e.cwd},{type:"pr.state.changed",actor:"user",source:"orchestrator",boxId:null,payload:{ts:Date.now(),change:t,...n}})}async function Eh(e,t={}){let{now:n=Date.now(),slugOf:r=De,lookup:o=bt,note:s=r_,tracks:a=async()=>(await xe()).filter(d=>!He(d)),asked:i=a8,emitChange:c=i8}=t,l=[],u=null;for(let d of e??[]){if(!d?.prs?.length)continue;let p=await r(d.path).catch(()=>null);if(p)for(let m of d.prs)try{if(!n8(m))continue;let w=await o(p,m.number).catch(()=>null);if(!w?.trackId||r8.has(w.state))continue;let{prev:h}=await s(p,m.number,{blocked:DN(m),sha:m.headSha??null,at:n});if(!h)continue;let g=o8(h,m);if(!g||s8(w,g.change))continue;u??=new Map((await a()).map(E=>[E.id,E]));let b=u.get(w.trackId);if(!b)continue;let y=m.headSha??null;if(await i(b,g.change,m.number,y,h.at||0))continue;let x={number:Number(m.number),url:m.url||w.url,title:m.title||w.title,branch:m.headRefName||w.headRef,repo:p,sha:y,delegated:!1,reason:g.reason};g.change==="ci-fixed"?x.passed=m.checks.passed:x.base=m.baseRefName||null,await c(b,g.change,x),l.push({change:g.change,number:m.number,reason:g.reason})}catch{}}return l}var T0=l8(c8),KN=3e4,u8=30*6e4,d8=KN,p8=10*6e4,f8=10080*6e4,h8=60*6e4,BN=8,VN=1440*6e4,m8=3,zN="number,url,title,headRefName,headRefOid,state,mergedAt,closedAt",v0=60*6e4,w8=15*6e4,g8=9e4,y8=1440*6e4,Wi=new Map,Ru=new Map,b8=360*6e4,k8=e=>e.reduce((t,n)=>({misses:Math.max(t.misses,n.brokerRefused?.misses||0),until:Math.max(t.until,n.brokerRefused?.until||0)}),{misses:0,until:0}),x8=/could not resolve|not found|no pull requests?/i,v8=e=>x8.test(String(e?.message||e||""));function S8(e,t){return[e.ciFix?.delegatedAt,e.reconcile?.delegatedAt,e.ciFixAwait?.since,e.reconcileAwait?.since].some(n=>n&&t-n<v0)}var LN={fast:d8,slow:p8,decay:h8};function jN(e,t,n=y0){return JN(e,t,{grace:0})||!n(e.repo,t)&&(e.armedAt&&t-e.armedAt<u8||S8(e,t))?"fast":t-(e.firstSeen||0)>f8?"decay":"slow"}function Cu(e,t,n,r){let o=e.lanes?.get(de(t.repo,t.number))||{};return ul({change:n,repo:t.repo,number:Number(t.number),githubAt:r||null,lane:o.lane||null,intervalMs:o.intervalMs||null,source:"watch"})}async function A8(e,t){Ar("watch");try{let{stdout:n}=await T0("gh",["pr","view",String(t),"--repo",e,"--json",zN],{timeout:3e4,maxBuffer:4194304,env:{...process.env,...await Fn({slug:e})}});return JSON.parse(n||"null")}catch(n){throw $o(n)&&Ro(n),n}}async function T8(e){Ar("watch");try{let{stdout:t}=await T0("gh",["pr","list","--repo",e,"--state","all","--limit","100","--json",zN],{timeout:3e4,maxBuffer:8388608,env:{...process.env,...await Fn({slug:e})}}),n=new Map;for(let r of JSON.parse(t||"[]"))n.set(Number(r.number),r);return n}catch(t){throw $o(t)&&Ro(t),t}}async function E8(){let e=new Map;for(let t of await xe().catch(()=>[]))e.set(t.id,t);return e}async function _8(e,t){await D({id:e.id,cwd:e.cwd},{type:"pr.state.changed",actor:"user",source:"orchestrator",boxId:null,payload:{ts:Date.now(),change:"merged",...t}}),await zp(e,t).catch(()=>{})}async function I8(e,t){let n=await Us(e);return n?oi(n,t):null}async function $8(e,t,n){let r=await Us(e);if(!r)throw new Error(`no local checkout for ${e}`);return si(r,t,{method:n})}async function R8(e,t){let n=await Us(e);if(!n)throw new Error(`no local checkout for ${e}`);return pl(n,t)}async function O8(e,t){await D({id:e.id,cwd:e.cwd},{type:"pr.state.changed",actor:"user",source:"orchestrator",boxId:null,payload:{ts:Date.now(),change:"auto-canceled",...t}})}async function Ui(e,t,n,r,o){if(!await r.disarm(e.repo,e.number).catch(()=>null))return;let a=n.get(e.trackId);a&&await r.emitDisarmed(a,{number:Number(e.number),url:t?.url||e.url,title:t?.title||e.title,branch:t?.headRefName||e.headRef,repo:e.repo,reason:o}).catch(()=>{})}var M8=10*6e4,FN=2*6e4,C8=2,N8=5*6e4,_h=new Map,S0=new Map,Ou=new Map,A0=new Map;function Hi(e,t){let n=A0.get(e)??t;return A0.set(e,n),t-n>N8?!1:(Wi.delete(e),!0)}function b0(e){A0.delete(e)}function P8(e,t,n,r){let o=n.headSha||null;if(!o||t==null)return!0;if(o!==t)return _h.set(e,{sha:o,at:r}),!1;if(S0.get(e)===o)return!0;let s=_h.get(e);if(s?.sha===o)return r-s.at>=FN;let a=Date.parse(n.updatedAt||"")||0;return a&&r-a<FN?(_h.set(e,{sha:o,at:r}),!1):!0}function k0(e,t,n,r){let o=Ou.get(e),s=o&&o.kind===t&&o.sha===(n||null)?o.count+1:1;return Ou.set(e,{sha:n||null,kind:t,message:r,count:s}),s>=C8}async function D8(e,t,n,{isHead:r=!0,prevHead:o=null}={}){let s=n.now??Date.now(),a=de(e.repo,e.number),i=e.autoMerge?.armedAt||0;if(i&&s-i>VN){await Ui(e,null,t,n,"auto-merge expired \u2014 checks never settled within 24h");return}let c=await n.detail(e.repo,e.number).catch(()=>null);if(!c)return;if(c.headSha&&e.lastHeadSha!==c.headSha&&await gg(e.repo,e.number,c.headSha).catch(()=>{}),c.checks.failed>0){let u=c.checks.failing.map(d=>d.name).join(", ");await Ui(e,c,t,n,`check${c.checks.failed===1?"":"s"} failed: ${u}`);return}if(c.mergeable==="CONFLICTING"){await Ui(e,c,t,n,`conflicts with ${c.baseRefName}`);return}if(!c.checks.total){let u=Math.max(e.autoMerge?.armedAt||0,Date.parse(c.updatedAt||"")||0);if(s-u<M8)return;if(!k0(a,"no-checks",c.headSha,null)){Hi(a,s);return}await Ui(e,c,t,n,c.checks.unavailable?"this token can't read the checks":"no CI checks appeared");return}if(c.checks.pending>0){c.headSha&&S0.set(a,c.headSha),Ou.delete(a),b0(a);return}if(c.mergeable==="UNKNOWN"||c.mergeStateStatus==="UNKNOWN"){Hi(a,s);return}if(c.isDraft)return;if(!P8(a,o,c,s)){Hi(a,s);return}let l=await n.lookup(e.repo,e.number).catch(()=>null);if(l?.autoMerge){if(c.mergeStateStatus==="BEHIND"){if(!r)return;try{await n.updateBranch(e.repo,e.number),Ou.delete(a),b0(a)}catch(u){let d=String(u?.message||u).trim();if(/no new commits|already up.to.date/i.test(d))return;if(!k0(a,"update",c.headSha,d)){Hi(a,s);return}await Ui(e,c,t,n,d||`couldn't update with ${c.baseRefName}`)}return}if(n.mergedRepos?.has(String(e.repo||"").toLowerCase())){Hi(a,s);return}try{await n.merge(e.repo,e.number,l.autoMerge.method||"merge")}catch(u){let d=String(u?.message||u).trim();if(/already merged|not open|is closed/i.test(d))return;if(!k0(a,"merge",c.headSha,d)){Hi(a,s);return}await Ui(e,c,t,n,d||"merge failed");return}return n.mergedRepos?.add(String(e.repo||"").toLowerCase()),Ou.delete(a),b0(a),_h.delete(a),S0.delete(a),await YN(e,{...c,state:"MERGED"},t,n,{change:"auto-merged",githubAt:c.checks.settledAt||null}),"merged"}}async function qi(e,t,n){await D({id:e.id,cwd:e.cwd},{type:"pr.state.changed",actor:"user",source:"orchestrator",boxId:null,payload:{ts:Date.now(),change:t,...n}})}async function B8(e,t){try{return await T0("git",["-C",e.cwd,"cat-file","-e",`${t}^{commit}`],{timeout:1e4}),!0}catch{return!1}}async function Mu(e,t,n,r=()=>!0){return(await J(e).catch(()=>[])).some(s=>s.type==="pr.state.changed"&&s.payload?.change===t&&s.payload?.number===Number(n)&&r(s))}var Gi=(e,t)=>({number:Number(e.number),url:t?.url||e.url,title:t?.title||e.title,branch:t?.headRefName||e.headRef,repo:e.repo});function JN(e,t,{grace:n=g8}={}){if(e.announced!==!1)return!1;let r=t-(e.firstSeen||0);return r>=n&&r<=y8}async function L8(e,t,n,r){let o=r.now??Date.now();if(!JN(e,o))return!1;let s=n.get(e.trackId)||null;if(!s||He(s))return!1;let a=(s.boxes||[]).find(d=>d.name===s.leadBox);return await(r.midTurn??Es)(s.leadBox,a?.agent).catch(()=>!1)?!1:(await J(s).catch(()=>[])).some(d=>d.type==="pr.state.changed"&&d.payload?.number===Number(e.number))?(await(r.claim??vr)(e.repo,e.number).catch(()=>null),!1):await(r.claim??vr)(e.repo,e.number).catch(()=>null)?(await Er({repo:e.repo,number:e.number,via:"watch"}).catch(()=>{}),await qi(s,"opened",{...Gi(e,t),announcedBy:"watch"}).catch(()=>{}),console.log(`[pr-watch] announced passive link ${e.repo}#${e.number} \u2192 track ${s.id} (no active door claimed it)`),!0):!1}async function j8(e,t,n,r){let o=r.now??Date.now(),s=t.headRefOid||null,a=n.get(e.trackId)||null;if(s&&(e.ciFix?.headSha&&s!==e.ciFix.headSha&&await Ep(e.repo,e.number,{headSha:s}).catch(()=>{}),e.reconcile?.headSha&&s!==e.reconcile.headSha&&await Ip(e.repo,e.number,{headSha:s}).catch(()=>{})),s&&s!==e.lastHeadSha){let i=!e.lastHeadSha,c=!!(e.ciFix||e.reconcile||e.ciFixAwait||e.reconcileAwait),l=!!e.baseFoldAt&&o-e.baseFoldAt<w8;await gg(e.repo,e.number,s).catch(()=>{}),e.baseFoldAt&&await n_(e.repo,e.number).catch(()=>{}),!i&&!c&&!l&&a&&!await r.localHasCommit(a,s).catch(()=>!1)&&!await Mu(a,"pushed",e.number,d=>d.payload?.sha===s)&&await qi(a,"pushed",{...Gi(e,t),sha:s}).catch(()=>{})}if(e.ciFixAwait)if(o-(e.ciFixAwait.since||0)>v0)await _p(e.repo,e.number).catch(()=>{});else{let i=await r.detail(e.repo,e.number).catch(()=>null);if(i?.checks){if(i.checks.failed>0)await _p(e.repo,e.number).catch(()=>{});else if(i.checks.total>0&&i.checks.pending===0){let c=Cu(r,e,"ci-fixed",i.checks.settledAt||null),l=e.ciFixAwait.since||0;a&&!await Mu(a,"ci-fixed",e.number,u=>(u.payload?.ts||0)>=l)&&await qi(a,"ci-fixed",{...Gi(e,t),sha:s,delegated:!0,passed:i.checks.passed,githubAt:c.githubAt,latencyMs:c.latencyMs,lane:c.lane}).catch(()=>{}),await _p(e.repo,e.number).catch(()=>{})}}}if(e.reconcileAwait)if(o-(e.reconcileAwait.since||0)>v0)await $p(e.repo,e.number).catch(()=>{});else{let i=await r.detail(e.repo,e.number).catch(()=>null);if(i){if(i.mergeable==="CONFLICTING")await $p(e.repo,e.number).catch(()=>{});else if(i.mergeable==="MERGEABLE"){Cu(r,e,"reconciled",null);let c=e.reconcileAwait.since||0;a&&!await Mu(a,"reconciled",e.number,l=>(l.payload?.ts||0)>=c)&&await qi(a,"reconciled",{...Gi(e,t),sha:s,delegated:!0,base:i.baseRefName||null}).catch(()=>{}),await $p(e.repo,e.number).catch(()=>{})}}}}async function F8(e,t,n,r){let o=Cu(r,e,"closed",Date.parse(t?.closedAt||"")||null),s=n.get(e.trackId);s&&!await Mu(s,"closed",e.number)&&await qi(s,"closed",{...Gi(e,t),githubAt:o.githubAt,latencyMs:o.latencyMs,lane:o.lane}).catch(()=>{}),await r.notifyIfResolved(e.repo,e.number,"closed").catch(()=>{}),await r.mark(e.repo,e.number,"closed").catch(()=>{})}async function UN(e,t,n){Cu(n,e,"lost",null);let r=t.get(e.trackId);r&&!await Mu(r,"lost",e.number)&&await qi(r,"lost",Gi(e,null)).catch(()=>{}),await n.notifyIfResolved(e.repo,e.number,"lost").catch(()=>{}),await n.mark(e.repo,e.number,"lost").catch(()=>{})}async function YN(e,t,n,r,o={}){let s=Cu(r,e,o.change||"merged",o.githubAt??(Date.parse(t.mergedAt||"")||null)),a=n.get(e.trackId);a&&((await J(a).catch(()=>[])).some(l=>l.type==="pr.state.changed"&&l.payload?.change==="merged"&&l.payload?.number===Number(e.number))||await r.emitMerged(a,{number:Number(e.number),url:t.url||e.url,title:t.title||e.title,branch:t.headRefName||e.headRef,repo:e.repo,githubAt:s.githubAt,latencyMs:s.latencyMs,lane:s.lane}).catch(()=>{})),await r.notifyIfArmed(e.repo,e.number).catch(()=>{}),await r.followupsIfMerged(e.repo,e.number).catch(()=>{}),await r.archiveIfArmed(e.repo,e.number).catch(()=>{}),await r.mark(e.repo,e.number,"merged").catch(()=>{})}async function HN(e={}){let{now:t=Date.now(),auth:n=vg,view:r=A8,list:o=T8,links:s=a_,trackMap:a=E8,emitMerged:i=_8,mark:c=_o,archiveIfArmed:l=$r,notifyIfArmed:u=Rr,notifyIfResolved:d=Uf,followupsIfMerged:p=ta,batchThreshold:m=m8,detail:w=I8,merge:h=$8,updateBranch:g=R8,lookup:b=bt,disarm:y=cl,emitDisarmed:x=O8,localHasCommit:E=B8,claim:A=vr,midTurn:$=Es,only:P=null,wantDetail:L=null,covered:T=y0,verdicts:C=null,tokenFor:j=Q=>ka(Q),noteRefusal:K=e_,clearRefusal:M=t_}=e;if(!(await n().catch(()=>null))?.authenticated||Mp()>0)return 0;let S=await s().catch(()=>[]),U=P_(S),W=Q=>{try{return!!L?.(Q)}catch{return!1}},ie=P?S.filter(Q=>{try{return P(Q)}catch{return!1}}):S.filter(Q=>t-(Wi.get(de(Q.repo,Q.number))||0)>=LN[jN(Q,t,T)]);if(!ie.length)return 0;let z=Date.now(),Ge=new Map,_e=new Map;for(let Q of[...ie].sort(fl)){let me=P?"event":jN(Q,t,T);Ge.set(de(Q.repo,Q.number),{lane:me,intervalMs:LN[me]??null}),Wi.set(de(Q.repo,Q.number),t),_e.has(Q.repo)||_e.set(Q.repo,[]),_e.get(Q.repo).push(Q)}let Y=await a().catch(()=>new Map),ne=new Map,Ie=(Q,me)=>{let Ue=de(Q,me);if(!ne.has(Ue)){let nt=Promise.resolve().then(()=>w(Q,me));nt.catch(()=>{}),ne.set(Ue,nt)}return ne.get(Ue)},Pe=C??((Q,me)=>Eh([{path:Q,prs:[me]}],{now:t,slugOf:async()=>Q,tracks:async()=>[...Y.values()].filter(Ue=>!He(Ue))}).catch(()=>{})),Ae={now:t,lanes:Ge,emitMerged:i,mark:c,archiveIfArmed:l,notifyIfArmed:u,notifyIfResolved:d,followupsIfMerged:p,detail:Ie,merge:h,updateBranch:g,lookup:b,disarm:y,emitDisarmed:x,localHasCommit:E,claim:A,midTurn:$,mergedRepos:new Set};for(let[Q,me]of _e){let Ue=k8(me);if(Ue.until>t)continue;let nt=!1;try{if(await j(Q),Ue.misses)for(let le of me)await M(le.repo,le.number).catch(()=>{})}catch(le){nt=Lx(le)}if(nt){let le=Ue.misses+1;if(le>=BN){console.log(`[pr-watch] ${Q}: not granted ${le}\xD7 \u2014 retiring ${me.length} link(s) as lost`);for(let ve of me){await UN(ve,Y,Ae);let Ye=de(ve.repo,ve.number);Ru.delete(Ye),Wi.delete(Ye)}}else for(let ve of me)await K(ve.repo,ve.number,{misses:le,until:t+b8}).catch(()=>{});continue}let rt,N=new Set,se=le=>le.ciFixAwait||le.reconcileAwait||W(le)?!0:le.autoMerge?t-(le.autoMerge.armedAt||0)<=VN:!1;if(me.length>m)rt=await o(Q).catch(()=>null);else{rt=new Map;for(let le of me){if(se(le)){let ve=await Ie(Q,le.number).catch(()=>null);if(ve?.state){rt.set(Number(le.number),{number:Number(le.number),url:ve.url,title:ve.title,headRefName:ve.headRefName,headRefOid:ve.headSha??null,state:ve.state,mergedAt:ve.mergedAt??null,closedAt:ve.closedAt??null});continue}}try{let ve=await r(Q,le.number);ve?.number!=null&&rt.set(Number(ve.number),ve)}catch(ve){v8(ve)&&N.add(de(le.repo,le.number))}}}if(rt)for(let le of me){let ve=de(le.repo,le.number),Ye=rt.get(Number(le.number));if(!Ye){if(N.has(ve)){let Fe=(Ru.get(ve)||0)+1;Ru.set(ve,Fe),Fe>=BN&&(await UN(le,Y,Ae),Ru.delete(ve),Wi.delete(ve))}continue}if(Ru.delete(ve),Ye.state==="MERGED"||Ye.state==="CLOSED")Ye.state==="MERGED"?await YN(le,Ye,Y,Ae):await F8(le,Ye,Y,Ae),Wi.delete(ve);else{let Fe=le.lastHeadSha??null;await L8(le,Ye,Y,Ae).catch(()=>{}),await j8(le,Ye,Y,Ae).catch(()=>{});let Zt=D_(U,le);le.autoMerge&&await D8(le,Y,Ae,{isHead:Zt,prevHead:Fe}).catch(()=>{});try{if(W(le)&&!ne.has(ve)&&Ie(le.repo,le.number),ne.has(ve)){let ut=await ne.get(ve).catch(()=>null);ut?.checks&&await Pe(le.repo,ut)}}catch{}}}}let be={};for(let{lane:Q}of Ge.values())be[Q]=(be[Q]||0)+1;return console.log(`[pr-watch] probed ${ie.length} link(s) (${Object.entries(be).map(([Q,me])=>`${Q} ${me}`).join(", ")}) in ${Date.now()-z}ms`),ie.length}function WN(e,t){return!e||!t?!1:e.all?!0:String(t.repo||"").toLowerCase()!==e.repo?!1:e.numbers?.length?e.numbers.includes(Number(t.number)):e.event==="push"?!!e.branch&&t.headRef===e.branch||!!t.autoMerge:e.branch?t.headRef===e.branch:!0}var x0=!1,Ih=!1,$h=[],qN=Promise.resolve();async function U8(){for(;Ih||$h.length;){if(Ih){Ih=!1;try{await HN()}catch{}continue}let e=$h;$h=[];let t=e.map(r=>r.spec),n=Object.assign({},...e.map(r=>r.deps||{}));try{await HN({...n,only:r=>t.some(o=>WN(o,r)),wantDetail:r=>t.some(o=>o.detail&&WN(o,r))})}catch{}}}function Rh(e,t){return e===null?Ih=!0:$h.push({spec:e,deps:t}),x0||(x0=!0,qN=U8().finally(()=>{x0=!1})),qN}function XN(e,t=void 0){let n=String(e?.repo||"").toLowerCase();if(!/^[^/\s]+\/[^/\s]+$/.test(n))return Promise.resolve();let r=(Array.isArray(e.numbers)?e.numbers:[]).map(Number).filter(o=>Number.isInteger(o)&&o>0);return Rh({repo:n,numbers:r,branch:e.branch||null,event:e.event||null,detail:e.detail===!0},t)}var H8=6e4,GN=0;function ZN(e=void 0){let t=e?.now??Date.now();return t-GN<H8?Promise.resolve():(GN=t,Rh({all:!0},e))}function QN(){Rh(null),setInterval(()=>Rh(null),KN)}Oo();Yp();Nl();Or();pn();var W8=new Set(["opened","reopened","closed","synchronize","ready_for_review","converted_to_draft","edited"]);async function q8({tracks:e=xe,reconcile:t=pf}={}){for(let n of(await e().catch(()=>[])).filter(r=>!He(r)))await t(n,{bypassThrottle:!0}).catch(()=>{})}function eP(e,t={}){let{invalidate:n=hn,probe:r=XN,poke:o=yI,reconcileOpened:s=q8,noteOpenedWebhook:a=$_}=t;try{n()}catch{}let i={probe:null,poked:!1,reconciled:!1};if(!e?.repo)return i;if(e.event==="pull_request"&&W8.has(e.action)){if(e.action==="opened"||e.action==="reopened"){i.poked=!0,i.reconciled=!0;for(let c of e.numbers||[])try{a({repo:e.repo,number:c})}catch{}try{o()}catch{}s()}i.probe={repo:e.repo,numbers:e.numbers,branch:e.headRef||null,event:e.event}}else(e.event==="check_suite"||e.event==="workflow_run")&&e.action==="completed"?i.probe={repo:e.repo,numbers:e.numbers,branch:e.headRef||null,event:e.event,detail:!0}:e.event==="push"&&!e.deleted&&(i.probe={repo:e.repo,branch:e.headRef||null,event:"push"});return i.probe&&r(i.probe),i}mt();ke();Or();pn();_s();gl();rl();import{randomUUID as G8}from"node:crypto";var $0=2e4,tP=3,Ki=new Map,E0=new Set;async function nP(e,t,n){let r=await n(e).catch(()=>[]),o=null;for(let s of r)s.type==="box.fullscreen.detected"&&s.boxId===t?o=s.payload?.offerId||null:s.type==="box.fullscreen.answered"&&o&&s.payload?.offerId===o&&(o=null);return o}async function K8(e={}){let{sessions:t=null,tracks:n=null,append:r=D,read:o=J,now:s=Date.now()}=e;if(process.env.BOSTRAT_CLAUDE_ALT_SCREEN==="1")return;let a,i;try{a=t??await en(),i=n??await xe()}catch{return}let c=new Map(a.map(u=>[u.name,u])),l=new Set;for(let u of i){if(He(u)||!u.leadBox)continue;let d=(u.boxes||[]).find(m=>m.name===u.leadBox);if(!d||d.agent!=="claude"||d.state!=="live")continue;let p=c.get(d.name);if(p)if(l.add(d.name),p.alternateOn){let m=(Ki.get(d.name)||0)+1;Ki.set(d.name,m),m===tP&&(E0.add(d.name),await nP(u,d.name,o)||await r(u,{type:"box.fullscreen.detected",actor:"system",source:"orchestrator",boxId:d.name,provider:d.agent,payload:{ts:s,offerId:G8(),box:d.name,agent:d.agent}}).catch(()=>{}))}else{let m=(Ki.get(d.name)||0)>=tP;if(Ki.delete(d.name),m||!E0.has(d.name)){E0.add(d.name);let w=await nP(u,d.name,o);w&&await r(u,{type:"box.fullscreen.answered",actor:"system",source:"orchestrator",boxId:d.name,provider:d.agent,payload:{ts:s,offerId:w,action:"cleared"}}).catch(()=>{})}}}for(let u of[...Ki.keys()])l.has(u)||Ki.delete(u)}var V8=2,_0=12e4,z8=360*6e4,J8=new Set(["merged","conflict","canceled","failed","handed-off"]),qr=new Map;async function Y8(e={}){let{sessions:t=null,tracks:n=null,append:r=D,read:o=J,now:s=Date.now(),turnState:a=fo,recentRead:i=HA,cliDead:c=ou,busyAt:l=UA,reportLoop:u=$s,boot:d=!1}=e,p,m;try{p=t??await en(),m=n??await xe()}catch{return}let w=new Map(p.map(g=>[g.name,g])),h=new Set;for(let g of m){if(He(g)||!g.leadBox||g.archivedAt||g.transferredTo)continue;let b=(g.boxes||[]).find(M=>M.name===g.leadBox);if(!b||J8.has(b.state))continue;let y=w.get(b.name),x=l(b.name),E=x!=null&&s-x<=_0,A=null;if(y){h.add(b.name);let M=i(b.name,$0),I=M?{working:M.busy,prompted:!1}:await a(b.name,b.agent).catch(()=>({working:!1,prompted:!1}));if(I.working||I.prompted||I.awaitingBackground){qr.delete(b.name);continue}let S=l(b.name);if(!(S!=null&&s-S<=_0)&&!d){qr.delete(b.name);continue}if(!await c(y).catch(()=>!1)){qr.delete(b.name);continue}let W=(qr.get(b.name)||0)+1;if(qr.set(b.name,W),W<V8)continue;A="cli-exited"}else{if(!E&&!d)continue;A="session-gone"}let $=await o(g).catch(()=>[]),P=li($),L=0;for(let M of $)M.type==="turn.interrupted"&&(M.payload?.result==="stopped"||M.payload?.result==="stopped-late")&&(L=Math.max(L,M.payload?.ts??M.ts??0));if(Math.max(P.abortedAt,L)>P.askedAt)continue;let T=l(b.name),C=b.agent==="claude"?P.hookClosedAt:P.closedAt,j=T!=null&&s-T<=_0&&C<=T,K=d&&AI($)&&s-P.askedAt<=z8;if(!j&&!K){qr.delete(b.name);continue}await r(g,{type:"turn.aborted",actor:"system",source:"orchestrator",boxId:b.name,provider:b.agent,payload:{ts:s,cause:A,turnTs:P.askedAt||null,box:b.name,agent:b.agent,evidence:j?"busy-read":"log",...y?.createdMs?{sessionAgeMs:s-y.createdMs}:{}}}).catch(()=>{}),qr.delete(b.name),String(g.name||"").startsWith("\u21BB")&&u(g,{provider:b.agent,note:`run ${A==="session-gone"?"lost its session":"CLI exited"} mid-turn`}).catch(()=>{})}for(let g of[...qr.keys()])h.has(g)||qr.delete(g)}var Nu=null,I0=!1,Oh=null;function rP(){if(Nu)return()=>{};let e=(t=!1)=>{I0||(I0=!0,K8().catch(()=>{}).then(()=>Y8({boot:t})).catch(()=>{}).finally(()=>{I0=!1}))};return Nu=setInterval(()=>e(!1),$0),Nu.unref?.(),Oh=setTimeout(()=>e(!0),Math.min($0,15e3)),Oh.unref?.(),()=>{clearInterval(Nu),clearTimeout(Oh),Nu=null,Oh=null}}Ds();Nl();ke();Oo();Hs();Ds();bl();import{randomUUID as X8}from"node:crypto";async function Z8(){let e=await Promise.resolve().then(()=>(Or(),KO));return{sayToLead:e.sayToLead,queueShipCompleteNotify:e.queueShipCompleteNotify}}var R0={listRepoPrs:Jn,readEvents:J,appendEvent:D,sayDeps:Z8,currentBranch:Mo};async function Q8(e,t=R0,{branch:n=null}={}){if(!e?.cwd)return null;let r=n||await(t.currentBranch??Mo)(e.workspace?.kind==="multi"?null:e.cwd).catch(()=>null)||e?.workspace?.branch;if(!r)return null;let o;try{o=await t.listRepoPrs(e.cwd,{caller:"pr-exists"})}catch{return null}let s=(o||[]).find(a=>a.headRefName===r);return s?{number:s.number,url:s.url??null,title:s.title??null}:null}async function O0(e,t,{actions:n,notify:r=!1}={},o=R0){let s=t?.payload||{};if(!Array.isArray(n)||!n.includes("pr")||s.toPr||Array.isArray(s.repos)&&s.repos.length||!s.branch)return null;let a=await Q8(e,o,{branch:s.branch});if(!a)return null;let i={id:e.id,cwd:e.cwd};await o.appendEvent(i,{type:"pr.offer.answered",actor:"user",source:"orchestrator",boxId:t.boxId,payload:{ts:Date.now(),offerId:s.offerId,action:"pr-exists",actions:n,...r?{notify:!0}:{},existingPr:{number:a.number}}});let c=X8();return await o.appendEvent(i,{type:"pr.exists.offered",actor:"system",source:"orchestrator",boxId:t.boxId,payload:{ts:Date.now(),offerId:c,srcOfferId:s.offerId??null,branch:s.branch,base:s.base??null,pr:a,actions:n,...r?{notify:!0}:{},offeredRebase:Array.isArray(s.offered)&&s.offered.includes("rebase")}}),{offerId:c,pr:a}}async function M0(e,{offerId:t,choice:n}={},r=R0){if(!t)throw new Error("offerId required");if(!["push","new","dismiss"].includes(n))throw new Error('choice "push" | "new" | "dismiss" required');return No(`prx:${e.id}:${t}`,()=>eJ(e,{offerId:t,choice:n},r))}async function eJ(e,{offerId:t,choice:n},r){let o=await r.readEvents(e),s=o.find(u=>u.type==="pr.exists.offered"&&u.payload?.offerId===t);if(!s)throw new Error("unknown offer");if(o.some(u=>u.type==="pr.exists.answered"&&u.payload?.offerId===t))throw new Error("offer already answered");let a=s.payload||{},i=Array.isArray(a.actions)&&a.actions.length?a.actions:["commit","push","pr"],c=null,l=null;if(n==="push"){let{sayToLead:u}=await r.sayDeps();l=Eo.filter(d=>d!=="pr"&&(i.includes(d)||d==="push")),c=await u(e.id,ei(l,{branch:a.branch??null,base:a.base??null,toPr:{number:a.pr?.number??null},offeredRebase:a.offeredRebase===!0}),{kind:"push-go"})}else if(n==="new"){let{sayToLead:u}=await r.sayDeps();l=i,c=await u(e.id,UE(i,{branch:a.branch??null,base:a.base??null,prNumber:a.pr?.number??null,offeredRebase:a.offeredRebase===!0}),{kind:"pr-go"})}if(await r.appendEvent({id:e.id,cwd:e.cwd},{type:"pr.exists.answered",actor:"user",source:"orchestrator",boxId:s.boxId,payload:{ts:Date.now(),offerId:t,choice:n,...n==="push"&&Number.isFinite(Number(a.pr?.number))?{number:Number(a.pr.number)}:{},...l?{actions:l}:{}}}),n!=="dismiss"&&a.notify===!0){let{queueShipCompleteNotify:u}=await r.sayDeps();u(e.id,{actions:l})}return{say:c,choice:n}}bl();import Gr from"node:fs/promises";import Vi from"node:path";import uP from"node:os";import oP from"node:fs/promises";import Mh from"node:path";import{execFile as tJ}from"node:child_process";import{promisify as nJ}from"node:util";import{fileURLToPath as rJ}from"node:url";var oJ=nJ(tJ),aP=Mh.dirname(rJ(import.meta.url)),sJ=Mh.resolve(aP,"..","..","client","dist"),aJ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",iJ=new Map([...aJ].map((e,t)=>[e,t]));function cJ(e){let t=[],n=0,r=0;for(let o of e){let s=iJ.get(o);if(s===void 0)return t;n+=(s&31)<<r,s&32?r+=5:(t.push(n&1?-(n>>>1):n>>>1),n=0,r=0)}return t}function lJ(e){let t=[],n=0,r=0,o=0;for(let s of e.split(";")){let a=[],i=0;if(s)for(let c of s.split(",")){let l=cJ(c);l.length!==0&&(i+=l[0],l.length>=4&&(n+=l[1],r+=l[2],o+=l[3],a.push([i,n,r,o])))}t.push(a)}return t}function uJ(e,t){if(!e||e.length===0||e[0][0]>t)return null;let n=0,r=e.length-1;for(;n<r;){let o=n+r+1>>1;e[o][0]<=t?n=o:r=o-1}return e[n]}var sP=new Map;async function dJ(e){let t;try{t=await oP.stat(e)}catch{return null}let n=sP.get(e);if(n&&n.mtimeMs===t.mtimeMs)return n;try{let r=JSON.parse(await oP.readFile(e,"utf8")),o={mtimeMs:t.mtimeMs,sources:r.sources||[],lines:lJ(r.mappings||"")};return sP.set(e,o),o}catch{return null}}var C0=null;function pJ(){return C0||(C0=process.env.BOSTRAT_RELEASE?Promise.resolve(process.env.BOSTRAT_RELEASE):oJ("git",["rev-parse","--short","HEAD"],{cwd:Mh.resolve(aP,"..","..")}).then(e=>e.stdout.trim()).catch(()=>null)),C0}var fJ=/(?:https?:\/\/[^\s()]*)?\/assets\/([^\s()/]+\.js):(\d+):(\d+)/g;async function hJ(e,{distDir:t=sJ}={}){let n=[],r=0,o=!1;for(let s of e.matchAll(fJ)){let[a,i,c,l]=s,u=await dJ(Mh.join(t,"assets",`${i}.map`)),d=u?uJ(u.lines[Number(c)-1],Number(l)-1):null;if(n.push(e.slice(r,s.index)),d&&u.sources[d[1]]){let p=u.sources[d[1]].replace(/^(\.\.\/)+/,"");n.push(`${p}:${d[2]+1}:${d[3]+1}`),o=!0}else n.push(a);r=s.index+a.length}return n.push(e.slice(r)),{stack:n.join(""),symbolicated:o}}async function iP(e,t={}){try{if(!e?.error?.stack||!e.release||e.release==="unknown")return e;let n=t.release??await pJ();if(!n||e.release!==n)return e;let{stack:r,symbolicated:o}=await hJ(e.error.stack,t);o&&(e.error.stack=r,e.error.symbolicated=!0)}catch{}return e}var mJ=()=>process.env.BOSTRAT_STATE_DIR||Vi.join(process.env.HOME||uP.tmpdir(),".bostrat"),ts=()=>Vi.join(mJ(),"telemetry"),dP=()=>Vi.join(ts(),".relay-offsets.json"),wJ=50,gJ=14,yJ=3e4,cP=500,ln=(e,t)=>typeof e=="string"?e.slice(0,t):"";function bJ(e,t){if(!e||typeof e!="object")return null;let n=ln(e.name,64);if(!n)return null;let r=Number.isFinite(e.ts)?e.ts:t,o={name:n,ts:Math.abs(r-t)<168*3600*1e3?r:t,receivedAt:t,anonId:ln(e.anonId,64),sessionId:ln(e.sessionId,64),userId:ln(e.userId,64),release:ln(e.release,64),appVersion:ln(e.appVersion,32),route:ln(e.route,128),deviceClass:e.deviceClass==="phone"||e.deviceClass==="desktop"?e.deviceClass:""};return e.props&&typeof e.props=="object"&&!Array.isArray(e.props)&&(JSON.stringify(e.props).length<=8192?o.props=e.props:o.props={clamped:!0}),e.error&&typeof e.error=="object"&&(o.error={kind:ln(e.error.kind,256),message:ln(e.error.message,8192),stack:ln(e.error.stack,32768),fingerprint:ln(e.error.fingerprint,64)}),Array.isArray(e.breadcrumbs)&&(o.breadcrumbs=e.breadcrumbs.slice(-50).map(s=>({t:Number.isFinite(s?.t)?s.t:0,n:ln(s?.n,64),r:ln(s?.r,128)}))),o}var pP=e=>new Date(e).toISOString().slice(0,10),lP=0;async function fP(e,t=Date.now()){let r=(Array.isArray(e?.events)?e.events.slice(0,wJ):[]).map(s=>bJ(s,t)).filter(Boolean);if(!r.length)return 0;for(let s of r)s.error?.stack&&await iP(s);await Gr.mkdir(ts(),{recursive:!0});let o=Vi.join(ts(),`${pP(t)}.ndjson`);return await Gr.appendFile(o,r.map(s=>JSON.stringify(s)+`
823
823
  `).join(""),"utf8"),t-lP>6*3600*1e3&&(lP=t,kJ(t).catch(()=>{})),r.length}async function kJ(e=Date.now()){let t=pP(e-gJ*24*3600*1e3),n=[];try{n=await Gr.readdir(ts())}catch{return}let r=n.filter(s=>s.endsWith(".ndjson")&&s.slice(0,10)<t);if(!r.length)return;for(let s of r)await Gr.rm(Vi.join(ts(),s),{force:!0});let o=await mP();for(let s of r)delete o[s];await wP(o)}var Ch=new Map;function hP(e,t=Date.now()){let n=e||"unknown",r=Ch.get(n);return r||(Ch.size>512&&Ch.clear(),r={tokens:40,at:t},Ch.set(n,r)),r.tokens=Math.min(40,r.tokens+(t-r.at)/6e4*20),r.at=t,r.tokens<1?!1:(r.tokens-=1,!0)}async function mP(){try{return JSON.parse(await Gr.readFile(dP(),"utf8"))||{}}catch{return{}}}async function wP(e){await Gr.mkdir(ts(),{recursive:!0}),await Gr.writeFile(dP(),JSON.stringify(e),"utf8")}function xJ(e,{env:t,host:n}={}){let r=e.name==="app.error"&&e.error,o={};for(let[a,i]of[["event",e.name],["route",e.route],["session",e.sessionId],["anon",e.anonId],["user",e.userId],["release",e.release],["appVersion",e.appVersion],["device",e.deviceClass]])i&&(o[a]=i);let s={timestamp:new Date(e.ts).toISOString(),service:"bostrat-client",source:"treetop-js",env:t||process.env.BOSTRAT_ENV||"pi",host:n||uP.hostname(),level:r?"error":"info",message:r?`${e.error.kind||"Error"}: ${e.error.message||"(no message)"}`.slice(0,8192):e.name,tags:o,attributes:{...e.props?{props:e.props}:{},receivedAt:e.receivedAt}};return r&&(s.error={kind:e.error.kind,message:e.error.message,stack:e.error.stack},e.error.fingerprint&&(s.fingerprint=e.error.fingerprint),e.error.symbolicated&&(s.attributes.symbolicated=!0),e.breadcrumbs&&(s.attributes.breadcrumbs=e.breadcrumbs)),s}async function vJ({fetchImpl:e=fetch}={}){let t=await SM();if(!t)return{sent:0,disabled:!0};let n;try{n=(await Gr.readdir(ts())).filter(s=>s.endsWith(".ndjson")).sort()}catch{return{sent:0,disabled:!1}}let r=await mP(),o=0;for(let s of n){let a=Vi.join(ts(),s),i=r[s]||0,c;try{let p=await Gr.open(a,"r");try{let m=(await p.stat()).size;if(m<=i)continue;c=Buffer.alloc(m-i),await p.read(c,0,c.length,i)}finally{await p.close()}}catch{continue}let l=c.lastIndexOf(10);if(l<0)continue;let u=c.toString("utf8",0,l+1).split(`
824
824
  `).filter(Boolean),d=[];for(let p of u)try{d.push(JSON.parse(p))}catch{}for(let p=0;p<d.length;p+=cP){let m=d.slice(p,p+cP).map(h=>xJ(h)),w=await e(`${t.url.replace(/\/$/,"")}/v1/logs`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${t.ingestKey}`},body:JSON.stringify({events:m})}).catch(()=>null);if(!w||!w.ok)return{sent:o,disabled:!1};o+=m.length}r[s]=i+l+1,await wP(r)}return{sent:o,disabled:!1}}var N0=null,P0=!1;function gP(){N0||(N0=setInterval(async()=>{if(!P0){P0=!0;try{await vJ()}catch(e){console.error("[telemetry] relay failed:",e?.message||e)}finally{P0=!1}}},yJ),N0.unref?.())}import Ph from"node:fs/promises";import vP from"node:path";import SJ from"node:os";var SP=()=>process.env.BOSTRAT_STATE_DIR||vP.join(process.env.HOME||SJ.tmpdir(),".bostrat"),AP=()=>vP.join(SP(),"dictation-glossary.json"),AJ=100,TJ=500,EJ=["bostrat","globopi","codex","tmux","worktree","Deepgram","Linear","Firecracker","Tigris","WireGuard","misous","postyx","cedar","gerbil","Anthropic","Opus","Haiku","Sonnet","keyterm","monorepo","dogfood"],Dh=null,D0=null,B0=Promise.resolve();function yP(){let e={},t=Date.now();for(let n of EJ)e[n.toLowerCase()]={term:n,count:1,lastUsed:t,source:"seed"};return e}async function TP(){return Dh||(D0??=Ph.readFile(AP(),"utf8").then(e=>JSON.parse(e)?.terms??yP()).catch(()=>yP()).then(e=>Dh=e).finally(()=>D0=null),D0)}async function bP(){let e=JSON.stringify({terms:Dh},null,2),t=AP(),n=`${t}.${process.pid}.tmp`;await Ph.mkdir(SP(),{recursive:!0}),await Ph.writeFile(n,e),await Ph.rename(n,t)}function _J(){return B0=B0.then(bP,bP),B0.catch(()=>{})}async function L0(){return Object.values(await TP()).sort((t,n)=>n.count-t.count||n.lastUsed-t.lastUsed)}var IJ=e=>Math.max(1,Math.ceil(e.length/4));async function $J(){let e=[],t=0;for(let{term:n}of await L0()){let r=IJ(n);if(!(t+r>TJ)&&(e.push(n),t+=r,e.length>=AJ))break}return e}async function RJ(e,t){let n=await TP(),r=e.toLowerCase(),o=n[r];n[r]={term:e,count:(o?.count??0)+1,lastUsed:Date.now(),source:o?.source??t}}var kP=e=>(e||"").split(/\s+/).map(t=>t.replace(/^[^\p{L}\p{N}]+|[^\p{L}\p{N}]+$/gu,"")).filter(Boolean),Nh=e=>e.toLowerCase();function xP(e){return!new RegExp("\\p{L}","u").test(e)||e.length<3?!1:/^[a-z]+$/.test(e)?e.length>=4:!0}async function EP(e,t){let n=kP(e),r=kP(t);if(!n.length||!r.length)return[];let o=n.length,s=r.length,a=Array.from({length:o+1},()=>new Array(s+1).fill(0));for(let u=o-1;u>=0;u--)for(let d=s-1;d>=0;d--)a[u][d]=Nh(n[u])===Nh(r[d])?a[u+1][d+1]+1:Math.max(a[u+1][d],a[u][d+1]);let i=new Set,c=0,l=0;for(;c<o&&l<s;)Nh(n[c])===Nh(r[l])?(c++,l++):a[c+1][l]>=a[c][l+1]?c++:(xP(r[l])&&i.add(r[l]),l++);for(;l<s;l++)xP(r[l])&&i.add(r[l]);if(!i.size)return[];for(let u of i)await RJ(u,"learned");return await _J(),[...i]}var Pu=null;function OJ(e,t){let n=null;try{n=JSON.parse(t)}catch{}let r=n?.err_code||n?.error_code||n?.category||"";return e===402||/PAYMENT_REQUIRED/i.test(r)?{status:402,code:"credits_exhausted",persistent:!0,message:"Deepgram credits are exhausted \u2014 dictation is down until you top up at console.deepgram.com or drop a new key into ~/.bostrat/integrations.json."}:e===401||e===403?{status:502,code:"key_invalid",persistent:!0,message:"Deepgram rejected the API key (revoked, or missing ASR scope) \u2014 replace it in ~/.bostrat/integrations.json."}:{status:502,code:"transcription_failed",persistent:!1,message:`Deepgram error ${e}: ${t.slice(0,300)}`}}async function _P(){if(!Pu)return null;let e=await pu();if(!e||e.apiKey.slice(-6)!==Pu.keyTail)return null;let{keyTail:t,...n}=Pu;return n}async function IP(e,t){let n=await pu();if(!n){let i=new Error("Deepgram is not configured \u2014 add deepgram.apiKey to ~/.bostrat/integrations.json");throw i.status=503,i.code="not_configured",i}let r=new URL("https://api.deepgram.com/v1/listen");r.searchParams.set("model","nova-3"),r.searchParams.set("smart_format","true");for(let i of await $J())r.searchParams.append("keyterm",i);let o=await fetch(r,{method:"POST",headers:{Authorization:`Token ${n.apiKey}`,"Content-Type":t||"application/octet-stream"},body:e});if(!o.ok){let i=await o.text().catch(()=>""),c=OJ(o.status,i);c.persistent&&(Pu={code:c.code,message:c.message,at:Date.now(),keyTail:n.apiKey.slice(-6)});let l=new Error(c.message);throw l.status=c.status,l.code=c.code,l}return Pu=null,{transcript:(await o.json())?.results?.channels?.[0]?.alternatives?.[0]?.transcript??""}}ke();var j0={"gpt-realtime-2.1":{textIn:4,textInCached:.4,textOut:24,audioIn:32,audioInCached:.4,audioOut:64},"gpt-realtime-2":{textIn:4,textInCached:.4,textOut:24,audioIn:32,audioInCached:.4,audioOut:64},"gpt-realtime":{textIn:4,textInCached:.4,textOut:16,audioIn:32,audioInCached:.4,audioOut:64},"gpt-realtime-2.1-mini":{textIn:.6,textInCached:.06,textOut:2.4,audioIn:10,audioInCached:.3,audioOut:20},"gpt-realtime-mini":{textIn:.6,textInCached:.06,textOut:2.4,audioIn:10,audioInCached:.3,audioOut:20}};function MJ(e){if(!e)return null;let t=String(e).trim();if(j0[t])return t;let n=null;for(let r of Object.keys(j0))t.startsWith(r)&&(!n||r.length>n.length)&&(n=r);return n}function CJ(e,t={}){let n=j0[MJ(e)];if(!n)return 0;let r=0;for(let o of Object.keys(n))r+=(Number(t[o])||0)*n[o];return r/1e6}function NJ(e,t){let n=null;try{n=JSON.parse(t)}catch{}let r=n?.error?.code||n?.error?.type||"";return e===429&&/insufficient_quota/i.test(r)?{status:402,code:"credits_exhausted",persistent:!0,message:"The OpenAI account is out of credit \u2014 voice chat is down until you top up at platform.openai.com or drop a new key into ~/.bostrat/integrations.json."}:e===401||e===403?{status:502,code:"key_invalid",persistent:!0,message:"OpenAI rejected the API key (revoked, or missing Realtime access) \u2014 replace it in ~/.bostrat/integrations.json."}:{status:502,code:"mint_failed",persistent:!1,message:`OpenAI realtime session mint failed (${e}): ${t.slice(0,300)}`}}var Du=null;async function PJ(){if(!Du)return null;let e=await ih();if(!e||e.apiKey.slice(-6)!==Du.keyTail)return null;let{keyTail:t,...n}=Du;return n}async function DJ(e){let t=await fetch("https://api.openai.com/v1/realtime/client_secrets",{method:"POST",headers:{Authorization:`Bearer ${e.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify({session:{type:"realtime",model:e.model,audio:{output:{voice:e.voice}}}})});if(!t.ok){let o=await t.text().catch(()=>""),s=NJ(t.status,o);s.persistent&&(Du={code:s.code,message:s.message,at:Date.now(),keyTail:e.apiKey.slice(-6)});let a=new Error(s.message);throw a.status=s.status,a.code=s.code,a}Du=null;let n=await t.json(),r=n?.value??n?.client_secret?.value;if(!r){let o=new Error("OpenAI returned no client secret");throw o.status=502,o.code="mint_failed",o}return{clientSecret:{value:r,expiresAt:n?.expires_at??n?.client_secret?.expires_at??null}}}var BJ={openai:DJ};async function $P(){let e=await ih();return e?{configured:!0,provider:e.provider,model:e.model,voice:e.voice,problem:await PJ()}:{configured:!1}}async function RP(){let e=await ih();if(!e){let n=new Error("Voice chat is not configured \u2014 add openai.apiKey to ~/.bostrat/integrations.json");throw n.status=503,n.code="not_configured",n}let t=await BJ[e.provider](e);return{provider:e.provider,model:e.model,voice:e.voice,...t}}async function OP(e,{model:t,usage:n={},seconds:r}={}){let o=c=>Math.max(0,Math.round(Number(c)||0)),s={textIn:o(n.textIn),textInCached:o(n.textInCached),textOut:o(n.textOut),audioIn:o(n.audioIn),audioInCached:o(n.audioInCached),audioOut:o(n.audioOut)},a=CJ(t,s),i=await D(e,{type:"cost.recorded",actor:"user",provider:"openai-realtime",payload:{model:t||"unknown",usd:a,tokens:{input:s.textIn+s.audioIn,output:s.textOut+s.audioOut,cacheRead:s.textInCached+s.audioInCached,cacheWrite:0},voice:s,seconds:Math.max(0,Math.round(Number(r)||0)),source:"voice-chat"}});return{usd:a,seq:i.seq}}pn();JE(async()=>new Set((await xe()).map(e=>e.id)));var G0=Ce.dirname(jJ(import.meta.url)),q0=Number(process.env.PORT)||3362,Bh=uk(process.env),jP=Number(process.env.BOSTRAT_AUTO_TRIGGER_PCT)||80,Ji=UC(process.env.BOSTRAT_ALLOW_IPS),Lh=HC(process.env.BOSTRAT_VIEW_FRONT_CIDRS,Sh),K0=qC(),FP=process.env.BOSTRAT_ALLOW_LAN_TOKENLESS!=="1",_=Xt();_.disable("x-powered-by");_.use((e,t,n)=>{t.setHeader("x-content-type-options","nosniff"),Iu(e.headers.host)||(t.setHeader("x-frame-options","DENY"),t.setHeader("referrer-policy","strict-origin-when-cross-origin")),n()});_.use((e,t,n)=>{if(_u(e)||Ji.allowed(Ji.clientIp(e))||Lh.allows(e))return n();t.status(403).type("text/plain").send("bostrat: access restricted to the allowlist")});_.use(YC);_.use(VC({token:K0,enforce:FP}));_.use("/api/mocks",Xt.json({limit:"1mb"}));_.use("/api/mocks",Xt.raw({type:"image/png",limit:"24mb"}));_.use("/api/mocks",Xt.raw({type:["video/mp4","video/webm"],limit:"105mb"}));_.use("/api/runbooks",Xt.json({limit:"1mb"}));_.use("/api/blueprints",Xt.json({limit:"1mb"}));_.use("/api/tracks/adopt",Xt.json({limit:"1mb"}));_.use("/api/telemetry",Xt.json({limit:"256kb"}));_.use("/api/hook",Xt.json({limit:"2mb"}));_.use("/api/dictation",Xt.raw({type:["audio/*","video/mp4","application/octet-stream"],limit:"32mb"}));_.use("/api/tracks/:id/upload",Xt.raw({type:()=>!0,limit:"25mb"}));_.use(Xt.json({limit:"64kb"}));var qJ=(()=>{try{let e=JSON.parse(At.readFileSync(Ce.resolve(G0,"..","..","client","dist","build.json"),"utf8")),t=typeof e?.sha=="string"?e.sha.trim():"";return!t||t==="unknown"?null:{sha:t,version:typeof e.version=="string"&&e.version.trim()?e.version.trim():null}}catch{return null}})();_.get("/api/health",async(e,t)=>{t.json({ok:!0,build:qJ,tmuxSocket:gt,hostTmuxAlive:await so(),autoTriggerPct:jP,plane:Yi?Yi.status():null})});_.get("/api/sessions",async(e,t)=>{t.json({sessions:await en()})});_.post("/api/sessions",async(e,t)=>{let{displayName:n,cwd:r}=e.body||{};if(typeof n!="string")return t.status(400).json({error:"displayName (string) required"});try{let o=await Hn(n,r||void 0);t.json({ok:!0,...o})}catch(o){let s=o?.message||String(o),a=/already exists/i.test(s)?409:/must be|invalid/i.test(s)?400:500;t.status(a).json({error:s})}});_.delete("/api/sessions/:name",async(e,t)=>{let n=decodeURIComponent(e.params.name);if(!We(n))return t.status(400).json({error:"invalid session name"});if(!await Ee(n))return t.status(404).json({error:"session not found"});try{await Ht(n),t.json({ok:!0})}catch(r){t.status(500).json({error:`failed to kill: ${r?.message||r}`})}});_.get("/api/context/:name",async(e,t)=>{let n=decodeURIComponent(e.params.name);if(!We(n))return t.status(400).json({error:"invalid session name"});let r=await Ee(n);if(!r)return t.status(404).json({error:"session not found"});let o=await Nc(r.cwd,r.sessionId);if(!o)return t.json({available:!1,cwd:r.cwd,sessionId:r.sessionId||null});t.json({available:!0,...o})});_.post("/api/handoff/:name",async(e,t)=>{let n=decodeURIComponent(e.params.name);if(!We(n))return t.status(400).json({error:"invalid session name"});try{let r=await OT(n);t.json({ok:!0,step:r.step,file:r.file,startedAt:r.startedAt})}catch(r){t.status(409).json({error:r?.message||String(r)})}});_.get("/api/handoff/:name",(e,t)=>{let n=decodeURIComponent(e.params.name),r=ip(n);if(!r)return t.json({running:!1});t.json({running:!r.finishedAt,step:r.step,error:r.error,file:r.file,startedAt:r.startedAt,finishedAt:r.finishedAt})});var MP=10;async function UP(){let e=await xe(),[t,n]=await Promise.all([sO(e),VO(e)]);return{tracks:e,views:await by(),queuedOf:r=>Wo(r),jobsOf:r=>t.get(r)??[],prPendingOf:r=>n.get(r)??[]}}_.get("/api/idle-guard",async(e,t)=>{try{t.json(lk(await UP()))}catch{t.status(500).json({busy:!0,reasons:["error"]})}});var bn=ra(),GJ=lM({kind:bn}),Bu=null,Rt=()=>Bu&&["auto","prompt","off"].includes(Bu)?Bu:GJ,ju=null,KJ=uu.has(bn),V0=async({to:e,from:t})=>!KJ||du(await Ci())?!1:(Fu.arm({to:e,from:t,kind:bn}),!0);async function VJ(e){let t=Rt();Bu=e??null;let n=Rt();if(t!==n){if(console.log(`[self-update] policy ${t} \u2192 ${n} (${e?"plane row":"node default"})`),n!=="auto"){Fu.cancel();return}ju&&await V0(ju)}}var HP=(()=>{try{return WJ(import.meta.url)("../package.json").version||null}catch{return null}})(),Fu=dM({isBusy:async()=>lk(await UP()).busy,onStuck:({to:e,from:t})=>ir({current:t,latest:e,installKind:bn,policy:Rt(),status:"stuck"}).catch(()=>{}),onStarted:({to:e,from:t,result:n})=>(n?.ok?ir({current:t,latest:e,installKind:bn,policy:Rt(),status:"updating",reason:"auto"}):ir({current:t,latest:e,installKind:bn,policy:Rt(),status:"failed",error:n?.reason})).catch(()=>{})});_.get("/api/node/self-update",async(e,t)=>{t.json({installKind:bn,policy:Rt(),policySource:Bu?"plane":"node",current:HP,status:await Ci(),armed:Fu.armed})});_.post("/api/node/self-update",async(e,t)=>{let n=typeof e.body?.to=="string"?e.body.to.trim():"";if(!/^\d+\.\d+\.\d+$/.test(n))return t.status(400).json({error:"body.to must be a release version (X.Y.Z)"});let r=await th({to:n,kind:bn,reason:"manual",force:!0});if(r.ok)return Fu.cancel(),ir({current:r.from,latest:n,installKind:bn,policy:Rt(),status:"updating",reason:"manual"}).catch(()=>{}),t.json({ok:!0,...r});t.status(409).json({ok:!1,error:r.reason,status:r.status??null})});async function WP(){try{let e=await uM();e&&await ir({current:e.from,latest:e.to,installKind:e.kind||bn,policy:Rt(),status:e.status,error:e.error,reason:e.reason}),e?.status==="failed"&&e.retryable===!0&&Rt()==="auto"&&ju?.latest===e.to&&await V0({to:e.to,from:ju.current})&&console.log(`[self-update] ${e.to} is not on the npm registry yet \u2014 re-armed for the next stasis (attempt ${Number(e.attempts)||1} of ${eh} used)`),await kb({current:HP,installKind:bn,policy:Rt()})}catch{}}WP();setInterval(WP,3e4).unref();_.get("/api/tracks",async(e,t)=>{let n=(await xe()).filter(s=>!s.transferredTo),r=n.filter(s=>s.archivedAt&&!s.archiving),o=n;if(e.query.archived!=="all"&&r.length>MP){let s=new Set([...r].sort((a,i)=>(i.archivedAt||0)-(a.archivedAt||0)).slice(0,MP).map(a=>a.id));o=n.filter(a=>!a.archivedAt||a.archiving||s.has(a.id))}t.json({tracks:o,archivedTotal:r.length,agents:tu,agentAvailability:await Mf(),tickets:await GM()})});_.get("/api/cost",async(e,t)=>{try{let n=await xe();e.query.track&&(n=n.filter(o=>o.id===e.query.track));let r=await Yk(n);if(r.cursorUsage=ry(),e.query.format==="text")return t.type("text/plain").send(gC(r));t.json(r)}catch(n){t.status(500).json({error:n?.message||String(n)})}});_.get("/api/usage/roundup",async(e,t)=>{try{let n=await Zk(await xe(),{window:e.query.window,from:e.query.from,to:e.query.to});if(e.query.format==="text")return t.type("text/plain").send(vC(n));t.json(n)}catch(n){t.status(500).json({error:n?.message||String(n)})}});_.get("/api/usage/spend",async(e,t)=>{try{let n=await _C(await xe(),{window:e.query.window,from:e.query.from,to:e.query.to});n.cursorUsage=ry(),n.subscriptionMonthlyUsd=Number(process.env.BOSTRAT_SUBSCRIPTION_MONTHLY_USD)||null,n.caps=sl(),t.json(n)}catch(n){t.status(500).json({error:n?.message||String(n)})}});_.get("/api/usage/caps",(e,t)=>{t.json(sl())});_.post("/api/usage/caps",async(e,t)=>{try{t.json(await yp(e.body?.caps??{},{source:"local"}))}catch(n){t.status(400).json({error:n?.message||String(n)})}});_.get("/api/usage/limits",async(e,t)=>{try{let n=e.query.fresh==="1"||e.query.fresh==="true";t.json(await DC(await xe(),{fresh:n}))}catch(n){t.status(500).json({error:n?.message||String(n)})}});_.post("/api/hook",async(e,t)=>{try{let{mode:n,target:r}=await dx(e.get(pr),{byToken:nu,legacy:()=>vl(e.body?.session_id,e.body?.cwd)});if(n==="refused")return nc("refused",{reason:"unknown-token",hook:e.body?.hook_event_name}),t.json({ok:!1,error:"unknown hook token"});if(n==="legacy-denied")return nc("legacy-denied",{reason:"tokenless-denied",hook:e.body?.hook_event_name}),t.status(401).json({ok:!1,error:"tokenless hook ingest is disabled (BOSTRAT_HOOK_LEGACY_DENY)"});n==="token"&&e.body?.session_id&&r.box?.sessionId&&e.body.session_id!==r.box.sessionId&&nc("mismatch",{track:r.track.id,box:r.box.name}),nc(n,{track:r?.track?.id,hook:e.body?.hook_event_name,...n==="legacy"?{reason:"tokenless-body-resolved",deny_with:"BOSTRAT_HOOK_LEGACY_DENY=1"}:{}});let o=await hC(e.body||{},()=>r);e.body?.hook_event_name==="Stop"&&r?.box?.cwd&&pd(r.box.cwd),t.json({ok:!0,events:o.length})}catch(n){t.json({ok:!1,error:n?.message||String(n)})}});_.get("/api/git/trailers",async(e,t)=>{t.type("text/plain");try{let n=await nu(e.get(pr));if(!n?.track||!n?.box)return t.status(204).end();t.send((await nI(n.track,n.box)).join(`
825
825
  `)+`