@plot-pm/board 0.6.0-rc.147 → 0.6.0-rc.149

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.
@@ -135,7 +135,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
135
135
  `)){if(!a.trim())continue;let l=JSON.parse(a);for(let s of l.issues??[])t.add(s)}}catch{return null}return t}async function My(e,n){let r;try{r=await se("bash",[re.join(e.scriptsDir,"plot-host.sh"),"issue-list","--limit",String(xy)],e.repoRoot)}catch(a){if(a.code===4){n.issues=[],n.issueAnswer="unsupported",n.issueError=null;return}n.issueAnswer="failed",n.issueError=a instanceof Error?a.message:String(a);return}let o=[];for(let a of r.split(`
136
136
  `))if(a.trim())try{let l=JSON.parse(a);o.push({number:l.number,title:l.title??"",url:typeof l.url=="string"?l.url:"",createdAt:typeof l.createdAt=="string"?l.createdAt:""})}catch{}let t=await Fy(e);if(t===null){n.issueAnswer="failed",n.issueError="plans could not be read, so no issue can be called unplanned";return}let i=Date.now();n.issues=o.filter(a=>!t.has(a.number)).map(a=>{let l=a.createdAt?Date.parse(a.createdAt):NaN;return{number:a.number,title:a.title,url:a.url,ageMinutes:Number.isNaN(l)?null:Math.max(0,Math.round((i-l)/6e4))}}),n.issueAnswer="answered",n.issueError=null}async function By(e,n){if(n.backend!==null)return n.backend;try{let o=(await se("bash",[re.join(e.scriptsDir,"plot-host.sh"),"backend"],e.repoRoot)).trim();n.backend=o||"github"}catch{n.backend="github"}return n.backend}async function Vy(e,n){let r=Date.now(),o=await By(e,n);try{let t=await se("bash",[re.join(e.scriptsDir,"plot-host.sh"),"pr-list","--rich","--state","all","--limit",String(yy)],e.repoRoot),i=new Map,a=new Map,l=new Map;for(let c of t.split(`
137
137
  `)){if(!c.trim())continue;let u=JSON.parse(c);if(typeof u.url!="string"&&(u.url=""),(typeof u.mergeable!="string"||!u.mergeable)&&(u.mergeable="unknown"),Array.isArray(u.failing_checks)||(u.failing_checks=[]),u.head&&u.state==="OPEN"&&i.set(u.head,u),a.set(u.number,u),u.head){let f=l.get(u.head);(!f||Yy(u,f))&&l.set(u.head,u)}}n.prs=i,n.prsByNumber=a,n.prsByHead=l,await Zy(e,n,i),n.prAt=Date.now();let s=nm(r,null,Date.now(),o);n.prNextAt=s.at,n.prNextIsBackoff=s.hard,n.prError=null}catch(t){let i=t instanceof Error?t.message:String(t);n.prError=i;let a=o==="github"?()=>Ty(e.repoRoot):void 0,l=await Ny(i,Date.now(),a),s=nm(r,l,Date.now(),o);n.prNextAt=s.at,n.prNextIsBackoff=s.hard}}async function rm(e,n){if(!(n.prRunning||!Ry(n.prNextAt,n.prNextIsBackoff))){n.prRunning=!0;try{await Vy(e,n),await My(e,n)}finally{n.prRunning=!1}}}function Wy(e,n,r){for(let o of n.plans)for(let t of o.waves)for(let i of t.branches){let a=r?.get(i.branch)??null,l=$i({state:i.state,conflicts:i.conflicts,conflictsKnown:i.conflicts_known,localAhead:i.local_ahead,prState:a?Tt(a):null,changedPaths:i.changed_paths,failingChecks:a?.failing_checks??[]});Wp(i.branch,l,e)}}async function im(e,n){if(n.running)return;n.running=!0;let r=n.pulseComplete?n.pulse:null;try{let o=null,t=[],i=n.pulse?.plans??[],a=()=>{let c=new Set(t.map(f=>f.file)),u=[...i.filter(f=>!c.has(f.file)),...t];n.pulse={main:n.pulse?.main??"",head:n.pulse?.head??"",read_ref:n.pulse?.read_ref,local_head:n.pulse?.local_head,plans:u,summary:Sy(u)},n.pulseComplete=!1},l="";if(await _y("bash",[re.join(e.scriptsDir,"plot-fleet-scan.sh"),"--stream"],e.repoRoot,c=>{let u;try{u=Mp.parse(JSON.parse(c))}catch{return}if(u.kind==="plan"){t=$y(t,u.plan),a();return}o=u.pulse},9e4,{env:{PLOT_TERMINAL_CACHE:n.terminal},onErrLine:c=>{c.startsWith("terminal:")&&(l+=`${c.slice(9).trim()}
138
- `)}}),o===null)throw new Error("fleet scan ended without a terminal pulse line");n.terminal=l;let s=o;n.shrink=zy(r,s,n.at),n.pulse=s,n.pulseComplete=!0,n.ages=await Py(e),n.branchUrlBase=await jy(e),n.approvedAt=await Ey(e,s),n.ideaPlans=await Iy(e),n.questions=await Xp(o),n.at=Date.now(),n.error=null,Kp(e.repoRoot,{at:n.at,pulse:s,ages:n.ages,branchUrlBase:n.branchUrlBase,approvedAt:n.approvedAt,ideaPlans:n.ideaPlans}),Wy(e,s,n.prs)}catch(o){n.error=o instanceof Error?o.message:String(o)}finally{n.running=!1}}function lu(e){let n=ky(e),r=em.get(n);if(r)return r;r={pulse:null,ages:new Map,at:null,error:null,shrink:null,branchUrlBase:"",terminal:"",approvedAt:new Map,ideaPlans:new Map,questions:new Map,issues:[],issueAnswer:"unsupported",issueError:null,prs:null,prsByNumber:null,prsByHead:null,runs:new Map,prAt:null,prError:null,prNextAt:0,prNextIsBackoff:!1,backend:null,pulseComplete:!0,timer:null,prTimer:null,running:!1,prRunning:!1},em.set(n,r);let o=Gp(e.repoRoot);return o&&(r.pulse=o.pulse,r.ages=o.ages,r.branchUrlBase=o.branchUrlBase,r.approvedAt=o.approvedAt,r.ideaPlans=o.ideaPlans,r.at=o.at),im(e,r),rm(e,r),r.timer=setInterval(()=>{im(e,r)},cm),r.timer.unref?.(),r.prTimer=setInterval(()=>{rm(e,r)},Pi),r.prTimer.unref?.(),r}function um(e){return lu(e).prsByNumber}function Fe(e){return lu(e).pulse}function Jy(e,n){return n==="deferred"?_n(e,!1):_n(e,n==="wip"||n==="merged")}function Hy(e){if(e.draft)return!0;let n=Tt(e);return n==="green"||n==="pending"}function qy(e,n,r,o){return e!=="not-started"?null:n==="deferred"?"you":n!=="open"?null:r!=="eligible"?"time":"click"}function Ky(e){let n=yi.safeParse(e);return n.success?n.data:null}function Gy(e,n,r,o,t,i=!1,a=0,l="",s="elsewhere",c="",u="",f=!1,m=[],g="",v=""){if(e==="deferred")return l==="delivered"||l==="released"?{group:"done",note:Hc}:l!==""&&l!=="approved"&&l!=="draft"?{group:"done",note:qc(l)}:t?{group:"not-started",note:Ie(`PR #${t.number}`,ou(t))}:r===null?{group:"not-started",note:"no commits"}:{group:"not-started",note:`last commit ${zi(r)} ago`};if(t&&e!=="merged"&&e!=="open"&&!(s==="running"&&Hy(t))){let w=ou(t);if(t.mergeable==="conflicting")return{group:"waiting-on-you",note:Ie(`PR #${t.number}, conflicts`,w)};if(t.mergeable!=="mergeable")return{group:"waiting-on-you",note:Ie(`PR #${t.number}, cannot say whether it merges`,w)};switch(t.checks){case"pending":return{group:"waiting-on-machine",note:Ie(`PR #${t.number}, CI running`,w)};case"failing":return{group:"waiting-on-you",note:Ie(`PR #${t.number}, checks failing`,w)};case"none":return{group:"waiting-on-you",note:Ie(`PR #${t.number}, no checks`,w)};case"unknown":return{group:"waiting-on-you",note:Ie(`PR #${t.number}, cannot read the checks`,w)};case"green":if(t.draft)break;return{group:"waiting-on-you",note:Ie(`PR #${t.number} green`,w)}}}if(e==="open")return l==="delivered"||l==="released"?{group:"done",note:Hc}:i||f||v!==""?iu(i,a,f,v):l==="draft"?{group:"waiting-on-you",note:Up}:l!==""&&l!=="approved"?{group:"done",note:qc(l)}:n==="blocked"?{group:"not-started",note:xi}:n==="eligible"?{group:"not-started",note:Lp}:{group:"not-started",note:xi};if(e!=="merged"){if(s==="running")return{group:"working",note:`worker running (pid ${u})`};if(s==="waiting")return{group:"working",note:g?`worker waiting on you: ${g}`:"worker waiting on you \u2014 reason unavailable, look in its worktree"};if(s==="failed")return{group:"waiting-on-you",note:c?`worker failed (exit ${c}) \u2014 restart it`:"worker failed \u2014 restart it"};if(s==="finished")return{group:"waiting-on-you",note:"worker finished \u2014 review it"};if(s==="stalled"){let w=m.slice(0,3).join(", "),S=m.length-3;return{group:"waiting-on-you",note:`worker stopped with work unfinished${w?` (${w}${S>0?` +${S} more`:""})`:""} \u2014 resume it`}}if(s==="ended")return{group:"waiting-on-you",note:"worker ended, exit status unknown"}}if(e==="claimed"){let w=s==="elsewhere",S=w?"claimed elsewhere":"claimed, no known worker";return r!==null&&r<=o?{group:"working",note:S}:i||a>0||f?iu(i,a,f):{group:"quiet",note:r===null?S:`claimed ${zi(r)} ago, ${w?"claimed elsewhere":"no known worker"}`}}return e==="merged"?n==="complete"?{group:"done",note:"merged"}:{group:"done",note:"merged \u2014 wave still open"}:r!==null&&r<=o?{group:"working",note:`last commit ${zi(r)} ago`}:i||a>0||f?iu(i,a,f):r===null?{group:"quiet",note:"pushed work, age unknown"}:{group:"quiet",note:`no commit for ${zi(r)}`}}function om(e,n,r){let o=[];return e==="running"&&o.push({origin:"local",evidence:n?`a worker process is running in a local worktree (pid ${n})`:"a worker process is running in a local worktree",pid:n}),r&&Tt(r)==="pending"&&o.push({origin:"host",evidence:`CI is running for PR #${r.number}`,pid:""}),o}function am(...e){return{...Gy(...e),verdict:Ky(e[1])}}function iu(e,n,r=!1,o=""){if(r)return{group:"working",note:"a write is in progress in a local worktree"};if(!e&&n<=0&&o!=="")return{group:"working",note:"held in a local worktree"};if(n<=0)return{group:"working",note:"uncommitted work in a local worktree"};let t=`${n} commit${n===1?"":"s"} not pushed locally`;return{group:"working",note:e?`${t}, uncommitted changes`:t}}function ou(e){switch(e.review){case"APPROVED":return"approved";case"CHANGES_REQUESTED":return"changes requested";case"REVIEW_REQUIRED":return"awaiting review";default:return""}}function Xy(e){let n=`PR #${e.number}, draft`,r=e.mergeable==="conflicting"?"conflicts":e.mergeable!=="mergeable"?"cannot say whether it merges":e.checks==="failing"?"checks failing":e.checks==="pending"?"CI running":e.checks==="none"?"no checks":e.checks==="unknown"?"cannot read the checks":"";return Ie(r?`${n}, ${r}`:n,ou(e))}function Tt(e){if(e.mergeable==="conflicting")return"conflicts";if(e.mergeable!=="mergeable")return"unknown";switch(e.checks){case"green":return"green";case"pending":return"pending";case"failing":return"failing";case"none":return"none";default:return"unknown"}}function Yy(e,n){let r=o=>o.state==="OPEN";return r(e)!==r(n)?r(e):e.number>n.number}function lm(e){return{number:e.number,url:e.url??"",draft:e.draft===!0,state:Tt(e)}}function Ie(e,n){return n?`${e} \xB7 ${n}`:e}function zi(e){if(e<60)return`${e} min`;let n=Math.floor(e/60);if(n<24)return n===1?"1 hour":`${n} hours`;let r=Math.floor(n/24);return r===1?"1 day":`${r} days`}var sm=["waiting-on-you","working","waiting-on-machine","not-started","quiet","done"];function Qy(e,n){return e.group==="not-started"?(e.waitingDays??-1)-(n.waitingDays??-1):(n.ageMinutes??-1)-(e.ageMinutes??-1)}function e0(e,n,r,o,t,i="",a,l=Date.now(),s,c,u,f){let m=[];for(let v of e.plans){let S=v.waves.find(A=>A.verdict==="eligible")??v.waves.find(A=>A.verdict!=="complete"),Z=S?.name?.trim()?S.name.trim():null;for(let A of v.waves)for(let $ of A.branches){let E=n.get($.branch)??null,j=t?.get($.branch)??null,V=f?.get($.branch)??j,{group:W,note:z,verdict:Q}=am($.state,A.verdict,E,o,j,$.local_dirty,$.local_ahead,v.phase,$.worker,$.worker_exit,$.worker_pid,$.local_locked,$.worker_dirty_paths,u?.get($.branch)??"",$.local_worktree),he=qy(W,$.state,A.verdict,v.phase),tt=he==="time"?Zp(Z):z;m.push({repo:r,branch:$.branch,plan:v.file.replace(/^\d{4}-\d{2}-\d{2}-/,"").replace(/\.md$/,""),planFile:v.file,wave:A.name||"(unnamed)",state:$.state,phase:Jy(v.phase,$.state),group:W,ageMinutes:E,note:$.claimed?`${tt} \xB7 ${$.claimed}`:tt,pr:V?lm(V):null,branchUrl:i&&$.state!=="merged"?`${i}${$.branch.split("/").map(encodeURIComponent).join("/")}`:"",waitingDays:$.state==="open"&&a?.has(v.file)?Math.max(0,Math.floor((l-a.get(v.file))/864e5)):null,localDirty:$.local_dirty,localLocked:$.local_locked,localAhead:$.local_ahead,waitingOn:he,blockedBy:he==="time"?Z:null,verdict:Q,stuck:$i({state:$.state,conflicts:$.conflicts,conflictsKnown:$.conflicts_known,localAhead:$.local_ahead,prState:j?Tt(j):null,changedPaths:$.changed_paths,failingChecks:j?.failing_checks??[],runHistory:c?.get($.branch)??[]}),repair:eu($.branch,l),worker:$.worker,processes:om($.worker,$.worker_pid,j)})}}let g=new Set(m.map(v=>v.branch));for(let[v,w]of t??[]){if(w.state!=="OPEN"||g.has(v))continue;let S=n.get(v)??null,{group:Z,note:A}=w.draft?{group:"waiting-on-you",note:Xy(w)}:am("wip","eligible",S,o,w),$=/^idea\/(.+)$/.exec(v)?.[1]??"";m.push({repo:r,plan:$,planFile:s?.get(v)??"",wave:"",state:"wip",phase:/^idea\//.test(v)?"Discovery":null,group:Z,ageMinutes:S,note:A,branch:v,branchUrl:i?`${i}${v.split("/").map(encodeURIComponent).join("/")}`:"",pr:lm(w),waitingDays:null,localDirty:!1,localLocked:!1,localAhead:0,waitingOn:null,blockedBy:null,verdict:null,worker:"elsewhere",stuck:$i({state:"wip",conflicts:[],conflictsKnown:!1,localAhead:0,prState:Tt(w),failingChecks:w.failing_checks??[],runHistory:c?.get(v)??[]}),repair:eu(v,l),processes:om("elsewhere","",w)})}return m.sort((v,w)=>{let S=sm.indexOf(v.group)-sm.indexOf(w.group);return S!==0?S:Qy(v,w)}),m}var t0={plans:0,waves:0,branches:0,claimed:0,eligible:0,blocked:0,deferred:0};function Ii(e,n=vy){let r=lu(e),o=re.basename(e.repoRoot),t=Date.now(),i=r.at===null?0:Math.round((t-r.at)/1e3),a=r.pulse?e0(r.pulse,r.ages,o,n,r.prs,r.branchUrlBase,r.approvedAt,t,r.ideaPlans,r.runs,r.questions,r.prsByHead):[];return{generatedAt:new Date().toISOString(),ageSeconds:i,readRef:r.pulse?.read_ref??null,readRefAge:r.at===null?null:i,localHead:r.pulse?.local_head??r.pulse?.head??null,ready:r.pulse!==null,complete:r.pulseComplete,error:r.error,shrink:r.shrink,rows:a,summary:r.pulse?.summary??t0,stuck:Bp(a.map(l=>l.stuck)),prAgeSeconds:r.prAt===null?null:Math.round((t-r.prAt)/1e3),prNextInSeconds:Math.max(0,Math.round((r.prNextAt-t)/1e3)),scanNextInSeconds:r.at===null?null:Math.max(0,Math.round((r.at+cm-t)/1e3)),prError:r.prError,issues:r.issues,issueAnswer:r.issueAnswer,issueError:r.issueError}}function Ei(e){try{return F.realpathSync(e.repoRoot)}catch{return e.repoRoot}}function r0(e){let n=0,r=0;for(let o of e.split(`
138
+ `)}}),o===null)throw new Error("fleet scan ended without a terminal pulse line");n.terminal=l;let s=o;n.shrink=zy(r,s,n.at),n.pulse=s,n.pulseComplete=!0,n.ages=await Py(e),n.branchUrlBase=await jy(e),n.approvedAt=await Ey(e,s),n.ideaPlans=await Iy(e),n.questions=await Xp(o),n.at=Date.now(),n.error=null,Kp(e.repoRoot,{at:n.at,pulse:s,ages:n.ages,branchUrlBase:n.branchUrlBase,approvedAt:n.approvedAt,ideaPlans:n.ideaPlans}),Wy(e,s,n.prs)}catch(o){n.error=o instanceof Error?o.message:String(o)}finally{n.running=!1}}function lu(e){let n=ky(e),r=em.get(n);if(r)return r;r={pulse:null,ages:new Map,at:null,error:null,shrink:null,branchUrlBase:"",terminal:"",approvedAt:new Map,ideaPlans:new Map,questions:new Map,issues:[],issueAnswer:"unsupported",issueError:null,prs:null,prsByNumber:null,prsByHead:null,runs:new Map,prAt:null,prError:null,prNextAt:0,prNextIsBackoff:!1,backend:null,pulseComplete:!0,timer:null,prTimer:null,running:!1,prRunning:!1},em.set(n,r);let o=Gp(e.repoRoot);return o&&(r.pulse=o.pulse,r.ages=o.ages,r.branchUrlBase=o.branchUrlBase,r.approvedAt=o.approvedAt,r.ideaPlans=o.ideaPlans,r.at=o.at),im(e,r),rm(e,r),r.timer=setInterval(()=>{im(e,r)},cm),r.timer.unref?.(),r.prTimer=setInterval(()=>{rm(e,r)},Pi),r.prTimer.unref?.(),r}function um(e){return lu(e).prsByNumber}function Fe(e){return lu(e).pulse}function Jy(e,n){return n==="deferred"?_n(e,!1):_n(e,n==="wip"||n==="merged")}function Hy(e){if(e.draft)return!0;let n=Tt(e);return n==="green"||n==="pending"}function qy(e,n,r,o){return e!=="not-started"?null:n==="deferred"?"you":n!=="open"?null:r!=="eligible"?"time":"click"}function Ky(e){let n=yi.safeParse(e);return n.success?n.data:null}function Gy(e,n,r,o,t,i=!1,a=0,l="",s="elsewhere",c="",u="",f=!1,m=[],g="",v=!1){if(e==="deferred")return l==="delivered"||l==="released"?{group:"done",note:Hc}:l!==""&&l!=="approved"&&l!=="draft"?{group:"done",note:qc(l)}:t?{group:"not-started",note:Ie(`PR #${t.number}`,ou(t))}:r===null?{group:"not-started",note:"no commits"}:{group:"not-started",note:`last commit ${zi(r)} ago`};if(t&&e!=="merged"&&e!=="open"&&!(s==="running"&&Hy(t))){let w=ou(t);if(t.mergeable==="conflicting")return{group:"waiting-on-you",note:Ie(`PR #${t.number}, conflicts`,w)};if(t.mergeable!=="mergeable")return{group:"waiting-on-you",note:Ie(`PR #${t.number}, cannot say whether it merges`,w)};switch(t.checks){case"pending":return{group:"waiting-on-machine",note:Ie(`PR #${t.number}, CI running`,w)};case"failing":return{group:"waiting-on-you",note:Ie(`PR #${t.number}, checks failing`,w)};case"none":return{group:"waiting-on-you",note:Ie(`PR #${t.number}, no checks`,w)};case"unknown":return{group:"waiting-on-you",note:Ie(`PR #${t.number}, cannot read the checks`,w)};case"green":if(t.draft)break;return{group:"waiting-on-you",note:Ie(`PR #${t.number} green`,w)}}}if(e==="open")return l==="delivered"||l==="released"?{group:"done",note:Hc}:i||f||v?iu(i,a,f,v):l==="draft"?{group:"waiting-on-you",note:Up}:l!==""&&l!=="approved"?{group:"done",note:qc(l)}:n==="blocked"?{group:"not-started",note:xi}:n==="eligible"?{group:"not-started",note:Lp}:{group:"not-started",note:xi};if(e!=="merged"){if(s==="running")return{group:"working",note:`worker running (pid ${u})`};if(s==="waiting")return{group:"working",note:g?`worker waiting on you: ${g}`:"worker waiting on you \u2014 reason unavailable, look in its worktree"};if(s==="failed")return{group:"waiting-on-you",note:c?`worker failed (exit ${c}) \u2014 restart it`:"worker failed \u2014 restart it"};if(s==="finished")return{group:"waiting-on-you",note:"worker finished \u2014 review it"};if(s==="stalled"){let w=m.slice(0,3).join(", "),S=m.length-3;return{group:"waiting-on-you",note:`worker stopped with work unfinished${w?` (${w}${S>0?` +${S} more`:""})`:""} \u2014 resume it`}}if(s==="ended")return{group:"waiting-on-you",note:"worker ended, exit status unknown"}}if(e==="claimed"){let w=s==="elsewhere",S=w?"claimed elsewhere":"claimed, no known worker";return r!==null&&r<=o?{group:"working",note:S}:i||a>0||f?iu(i,a,f):{group:"quiet",note:r===null?S:`claimed ${zi(r)} ago, ${w?"claimed elsewhere":"no known worker"}`}}return e==="merged"?n==="complete"?{group:"done",note:"merged"}:{group:"done",note:"merged \u2014 wave still open"}:r!==null&&r<=o?{group:"working",note:`last commit ${zi(r)} ago`}:i||a>0||f?iu(i,a,f):r===null?{group:"quiet",note:"pushed work, age unknown"}:{group:"quiet",note:`no commit for ${zi(r)}`}}function om(e,n,r){let o=[];return e==="running"&&o.push({origin:"local",evidence:n?`a worker process is running in a local worktree (pid ${n})`:"a worker process is running in a local worktree",pid:n}),r&&Tt(r)==="pending"&&o.push({origin:"host",evidence:`CI is running for PR #${r.number}`,pid:""}),o}function am(...e){return{...Gy(...e),verdict:Ky(e[1])}}function iu(e,n,r=!1,o=!1){if(r)return{group:"working",note:"a write is in progress in a local worktree"};if(!e&&n<=0&&o)return{group:"working",note:"held in a local worktree"};if(n<=0)return{group:"working",note:"uncommitted work in a local worktree"};let t=`${n} commit${n===1?"":"s"} not pushed locally`;return{group:"working",note:e?`${t}, uncommitted changes`:t}}function ou(e){switch(e.review){case"APPROVED":return"approved";case"CHANGES_REQUESTED":return"changes requested";case"REVIEW_REQUIRED":return"awaiting review";default:return""}}function Xy(e){let n=`PR #${e.number}, draft`,r=e.mergeable==="conflicting"?"conflicts":e.mergeable!=="mergeable"?"cannot say whether it merges":e.checks==="failing"?"checks failing":e.checks==="pending"?"CI running":e.checks==="none"?"no checks":e.checks==="unknown"?"cannot read the checks":"";return Ie(r?`${n}, ${r}`:n,ou(e))}function Tt(e){if(e.mergeable==="conflicting")return"conflicts";if(e.mergeable!=="mergeable")return"unknown";switch(e.checks){case"green":return"green";case"pending":return"pending";case"failing":return"failing";case"none":return"none";default:return"unknown"}}function Yy(e,n){let r=o=>o.state==="OPEN";return r(e)!==r(n)?r(e):e.number>n.number}function lm(e){return{number:e.number,url:e.url??"",draft:e.draft===!0,state:Tt(e)}}function Ie(e,n){return n?`${e} \xB7 ${n}`:e}function zi(e){if(e<60)return`${e} min`;let n=Math.floor(e/60);if(n<24)return n===1?"1 hour":`${n} hours`;let r=Math.floor(n/24);return r===1?"1 day":`${r} days`}var sm=["waiting-on-you","working","waiting-on-machine","not-started","quiet","done"];function Qy(e,n){return e.group==="not-started"?(e.waitingDays??-1)-(n.waitingDays??-1):(n.ageMinutes??-1)-(e.ageMinutes??-1)}function e0(e,n,r,o,t,i="",a,l=Date.now(),s,c,u,f){let m=[];for(let v of e.plans){let S=v.waves.find(A=>A.verdict==="eligible")??v.waves.find(A=>A.verdict!=="complete"),Z=S?.name?.trim()?S.name.trim():null;for(let A of v.waves)for(let $ of A.branches){let E=n.get($.branch)??null,j=t?.get($.branch)??null,V=f?.get($.branch)??j,{group:W,note:z,verdict:Q}=am($.state,A.verdict,E,o,j,$.local_dirty,$.local_ahead,v.phase,$.worker,$.worker_exit,$.worker_pid,$.local_locked,$.worker_dirty_paths,u?.get($.branch)??"",$.held),he=qy(W,$.state,A.verdict,v.phase),tt=he==="time"?Zp(Z):z;m.push({repo:r,branch:$.branch,plan:v.file.replace(/^\d{4}-\d{2}-\d{2}-/,"").replace(/\.md$/,""),planFile:v.file,wave:A.name||"(unnamed)",state:$.state,phase:Jy(v.phase,$.state),group:W,ageMinutes:E,note:$.claimed?`${tt} \xB7 ${$.claimed}`:tt,pr:V?lm(V):null,branchUrl:i&&$.state!=="merged"?`${i}${$.branch.split("/").map(encodeURIComponent).join("/")}`:"",waitingDays:$.state==="open"&&a?.has(v.file)?Math.max(0,Math.floor((l-a.get(v.file))/864e5)):null,localDirty:$.local_dirty,localLocked:$.local_locked,localAhead:$.local_ahead,waitingOn:he,blockedBy:he==="time"?Z:null,verdict:Q,stuck:$i({state:$.state,conflicts:$.conflicts,conflictsKnown:$.conflicts_known,localAhead:$.local_ahead,prState:j?Tt(j):null,changedPaths:$.changed_paths,failingChecks:j?.failing_checks??[],runHistory:c?.get($.branch)??[]}),repair:eu($.branch,l),worker:$.worker,processes:om($.worker,$.worker_pid,j)})}}let g=new Set(m.map(v=>v.branch));for(let[v,w]of t??[]){if(w.state!=="OPEN"||g.has(v))continue;let S=n.get(v)??null,{group:Z,note:A}=w.draft?{group:"waiting-on-you",note:Xy(w)}:am("wip","eligible",S,o,w),$=/^idea\/(.+)$/.exec(v)?.[1]??"";m.push({repo:r,plan:$,planFile:s?.get(v)??"",wave:"",state:"wip",phase:/^idea\//.test(v)?"Discovery":null,group:Z,ageMinutes:S,note:A,branch:v,branchUrl:i?`${i}${v.split("/").map(encodeURIComponent).join("/")}`:"",pr:lm(w),waitingDays:null,localDirty:!1,localLocked:!1,localAhead:0,waitingOn:null,blockedBy:null,verdict:null,worker:"elsewhere",stuck:$i({state:"wip",conflicts:[],conflictsKnown:!1,localAhead:0,prState:Tt(w),failingChecks:w.failing_checks??[],runHistory:c?.get(v)??[]}),repair:eu(v,l),processes:om("elsewhere","",w)})}return m.sort((v,w)=>{let S=sm.indexOf(v.group)-sm.indexOf(w.group);return S!==0?S:Qy(v,w)}),m}var t0={plans:0,waves:0,branches:0,claimed:0,eligible:0,blocked:0,deferred:0};function Ii(e,n=vy){let r=lu(e),o=re.basename(e.repoRoot),t=Date.now(),i=r.at===null?0:Math.round((t-r.at)/1e3),a=r.pulse?e0(r.pulse,r.ages,o,n,r.prs,r.branchUrlBase,r.approvedAt,t,r.ideaPlans,r.runs,r.questions,r.prsByHead):[];return{generatedAt:new Date().toISOString(),ageSeconds:i,readRef:r.pulse?.read_ref??null,readRefAge:r.at===null?null:i,localHead:r.pulse?.local_head??r.pulse?.head??null,ready:r.pulse!==null,complete:r.pulseComplete,error:r.error,shrink:r.shrink,rows:a,summary:r.pulse?.summary??t0,stuck:Bp(a.map(l=>l.stuck)),prAgeSeconds:r.prAt===null?null:Math.round((t-r.prAt)/1e3),prNextInSeconds:Math.max(0,Math.round((r.prNextAt-t)/1e3)),scanNextInSeconds:r.at===null?null:Math.max(0,Math.round((r.at+cm-t)/1e3)),prError:r.prError,issues:r.issues,issueAnswer:r.issueAnswer,issueError:r.issueError}}function Ei(e){try{return F.realpathSync(e.repoRoot)}catch{return e.repoRoot}}function r0(e){let n=0,r=0;for(let o of e.split(`
139
139
  `)){let t=/^\s*[-*]\s+\[([ xX])\]\s/.exec(o);t&&(r+=1,t[1]!==" "&&(n+=1))}return r>0?{done:n,total:r}:null}function i0(e,n){try{let r=D.join(e,n),t=F.readdirSync(r).filter(i=>/-checklist\.md$/.test(i)).sort().at(-1);return t?r0(F.readFileSync(D.join(r,t),"utf8")):null}catch{return null}}function B(e,n,r){try{return uu("bash",[D.join(e.scriptsDir,"plot-config.sh"),"get",n,r],{cwd:e.repoRoot,encoding:"utf8"}).trim()||r}catch{return r}}function fm(e,n){let r=new Set,o=[],t=D.join(e,n),i=[D.join(t,"active"),D.join(t,"delivered"),t];for(let a of i)if(F.existsSync(a))for(let l of F.readdirSync(a)){if(!l.endsWith(".md"))continue;let s;try{if(s=F.realpathSync(D.join(a,l)),!F.statSync(s).isFile())continue}catch{continue}r.has(s)||(r.add(s),o.push(s))}return o}function Sn(e,n){try{return uu("git",n,{cwd:e,encoding:"utf8",maxBuffer:16*1024*1024,stdio:["ignore","pipe","ignore"]})}catch{return""}}function o0(e,n,r){if(n.length===0)return[];let o=Sn(e,["rev-parse","--show-toplevel"]).trim();if(!o)return[];try{if(F.realpathSync(o)!==F.realpathSync(e))return[]}catch{return[]}let t=n.map(l=>`refs/remotes/origin/${l}*`),i=Sn(e,["for-each-ref","--format=%(refname:short) %(objectname)",...t]),a=[];for(let l of i.split(`
140
140
  `)){let[s,c]=l.trim().split(" ");if(!s||!c)continue;let u=s.replace(/^origin\//,"");!u||u===r||a.push({branch:u,sha:c})}return a}function pm(e,n){let r=B(e,"Main branch","");return r||Sn(n,["symbolic-ref","--short","refs/remotes/origin/HEAD"]).trim().replace(/^origin\//,"")||"main"}function dm(e,n,r){let o=new Set,t=Sn(e,["ls-tree","-r",n,"--",r]);for(let i of t.split(`
141
141
  `)){let a=/^(\d{6}) blob [0-9a-f]+\t(.+)$/.exec(i);a&&(a[1]!=="100644"&&a[1]!=="100755"||a[2].endsWith(".md")&&o.add(a[2]))}return o}function a0(e,n,r,o){let t=dm(e,`origin/${o}`,n),i=[],a=new Set;for(let{branch:l}of r)for(let s of dm(e,`origin/${l}`,n)){if(t.has(s)||a.has(s))continue;let c=Sn(e,["show",`origin/${l}:${s}`]);c&&(a.add(s),i.push({path:s,content:c}))}return i}var su=new Map;function mm(e,n,r,o){let t=o0(e,r,o);if(t.length===0)return su.delete(e),[];let i=t.map(s=>`${s.branch}@${s.sha}`).join(" "),a=su.get(e);if(a&&a.key===i)return a.plans;let l=a0(e,n,t,o);return su.set(e,{key:i,plans:l}),l}function l0(e,n){let r=0,o=0;for(let s of e.waves)for(let c of s.branches)c.deferred?o+=1:r+=1;let t={waves:e.waves.length,branches:r,deferred:o},i=n?.plans.find(s=>s.file===D.basename(e.file));if(!i)return t;let a=0,l=0;for(let s of i.waves)for(let c of s.branches)c.state==="claimed"?a+=1:c.state==="open"&&s.verdict==="eligible"&&(l+=1);return t.claimed=a,t.eligible=l,t}function s0(e,n){let r=n?.plans.find(t=>t.file===D.basename(e.file));if(!r)return[];let o=[];for(let t of r.waves)for(let i of t.branches)i.local_worktree&&o.push({branch:i.branch,path:i.local_worktree});return o}function cu(e){let n=/^(\d{4}-\d{2}-\d{2})(?![\d-])/.exec(e.trim());return n?n[1]:""}function c0(e,n){switch(e){case"Released":return cu(n.released_raw);case"Endgame":return cu(n.delivered_raw);case"Design":case"Development":return cu(n.approved_raw);case"Discovery":return""}}function u0(e){let n=D.basename(e,".md"),r=n.match(/^\d{4}-\d{2}-\d{2}-(.+)$/);return r?r[1]:n}function d0(e,n){return n.length===0?[]:uu("bash",[D.join(e,"plot-plan-meta.sh"),...n],{encoding:"utf8",maxBuffer:64*1024*1024}).split(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plot-pm/board",
3
- "version": "0.6.0-rc.147",
3
+ "version": "0.6.0-rc.149",
4
4
  "description": "Local Kanban board for Plot — a glanceable view of plan phases from docs/plans, with sprint and story filters",
5
5
  "type": "module",
6
6
  "license": "MIT",